mime.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1996-2017 The Squid Software Foundation and contributors
3  *
4  * Squid software is distributed under GPLv2+ license and includes
5  * contributions from numerous individuals and organizations.
6  * Please see the COPYING and CONTRIBUTORS files for details.
7  */
8 
9 /* DEBUG: section 25 MIME Parsing and Internal Icons */
10 
11 #include "squid.h"
12 #include "fde.h"
13 #include "fs_io.h"
14 #include "globals.h"
15 #include "HttpHdrCc.h"
16 #include "HttpReply.h"
17 #include "HttpRequest.h"
18 #include "internal.h"
19 #include "MemBuf.h"
20 #include "MemObject.h"
21 #include "mime.h"
22 #include "RequestFlags.h"
23 #include "SquidConfig.h"
24 #include "Store.h"
25 #include "StoreClient.h"
26 
27 #include <array>
28 
29 #if HAVE_SYS_STAT_H
30 #include <sys/stat.h>
31 #endif
32 
33 /* forward declarations */
34 static void mimeFreeMemory(void);
35 static const SBuf mimeGetIcon(const char *fn);
36 
37 class MimeIcon : public StoreClient
38 {
40 
41 public:
42  explicit MimeIcon(const char *aName);
43  ~MimeIcon();
44  void setName(char const *);
45  SBuf getName() const;
46  void load();
47 
48  /* StoreClient API */
49  virtual void created(StoreEntry *);
50 
51 private:
53  char *url_;
54 };
55 
56 class MimeEntry
57 {
59 
60 public:
61  explicit MimeEntry(const char *aPattern, const regex_t &compiledPattern,
62  const char *aContentType,
63  const char *aContentEncoding, const char *aTransferMode,
64  bool optionViewEnable, bool optionDownloadEnable,
65  const char *anIconName);
66  ~MimeEntry();
67 
68  const char *pattern;
70  const char *content_type;
71  const char *content_encoding;
77 };
78 
79 static MimeEntry *MimeTable = NULL;
80 static MimeEntry **MimeTableTail = &MimeTable;
81 
82 static MimeEntry *
83 mimeGetEntry(const char *fn, int skip_encodings)
84 {
85  MimeEntry *m;
86  char *t;
87  char *name = xstrdup(fn);
88 
89  do {
90  t = NULL;
91 
92  for (m = MimeTable; m; m = m->next) {
93  if (regexec(&m->compiled_pattern, name, 0, 0, 0) == 0)
94  break;
95  }
96 
97  if (!skip_encodings)
98  (void) 0;
99  else if (m == NULL)
100  (void) 0;
101  else if (strcmp(m->content_type, dash_str))
102  (void) 0;
103  else if (!strcmp(m->content_encoding, dash_str))
104  (void) 0;
105  else {
106  /* Assume we matched /\.\w$/ and cut off the last extension */
107  if ((t = strrchr(name, '.'))) {
108  *t = '\0';
109  } else {
110  /* What? A encoding without a extension? */
111  m = NULL;
112  }
113  }
114  } while (t);
115 
116  xfree(name);
117  return m;
118 }
119 
120 MimeIcon::MimeIcon(const char *aName) :
121  url_(nullptr)
122 {
123  setName(aName);
124 }
125 
127 {
128  xfree(url_);
129 }
130 
131 void
132 MimeIcon::setName(char const *aString)
133 {
134  xfree(url_);
135  icon_ = aString;
136  url_ = xstrdup(internalLocalUri("/squid-internal-static/icons/", icon_));
137 }
138 
139 SBuf
141 {
142  return icon_;
143 }
144 
145 const SBuf
146 mimeGetIcon(const char *fn)
147 {
148  MimeEntry *m = mimeGetEntry(fn, 1);
149 
150  if (!m || !m->theIcon.getName().cmp(dash_str))
151  return SBuf();
152 
153  return m->theIcon.getName();
154 }
155 
156 const char *
157 mimeGetIconURL(const char *fn)
158 {
159  SBuf icon(mimeGetIcon(fn));
160 
161  if (icon.isEmpty())
162  return null_string;
163 
165  static SBuf mb;
166  mb.clear();
167  mb.append("/squid-internal-static/icons/");
168  mb.append(icon);
169  return mb.c_str();
170  } else {
171  return internalLocalUri("/squid-internal-static/icons/", icon);
172  }
173 }
174 
175 const char *
176 mimeGetContentType(const char *fn)
177 {
178  MimeEntry *m = mimeGetEntry(fn, 1);
179 
180  if (m == NULL)
181  return NULL;
182 
183  if (!strcmp(m->content_type, dash_str))
184  return NULL;
185 
186  return m->content_type;
187 }
188 
189 const char *
191 {
192  MimeEntry *m = mimeGetEntry(fn, 0);
193 
194  if (m == NULL)
195  return NULL;
196 
197  if (!strcmp(m->content_encoding, dash_str))
198  return NULL;
199 
200  return m->content_encoding;
201 }
202 
203 char
205 {
206  MimeEntry *m = mimeGetEntry(fn, 0);
207  return m ? m->transfer_mode : 'I';
208 }
209 
210 bool
212 {
213  MimeEntry *m = mimeGetEntry(fn, 1);
214  return m ? m->download_option : 0;
215 }
216 
217 bool
218 mimeGetViewOption(const char *fn)
219 {
220  MimeEntry *m = mimeGetEntry(fn, 0);
221  return m != 0 ? m->view_option : false;
222 }
223 
224 /* Initializes/reloads the mime table
225  * Note: Due to Solaris STDIO problems the caller should NOT
226  * call mimeFreeMemory on reconfigure. This way, if STDIO
227  * fails we at least have the old copy loaded.
228  */
229 void
230 mimeInit(char *filename)
231 {
232  FILE *fp;
233  char buf[BUFSIZ];
234  char chopbuf[BUFSIZ];
235  char *t;
236  char *pattern;
237  char *icon;
238  char *type;
239  char *encoding;
240  char *mode;
241  char *option;
242  int view_option;
243  int download_option;
244  regex_t re;
245  MimeEntry *m;
246  int re_flags = REG_EXTENDED | REG_NOSUB | REG_ICASE;
247 
248  if (filename == NULL)
249  return;
250 
251  if ((fp = fopen(filename, "r")) == NULL) {
252  int xerrno = errno;
253  debugs(25, DBG_IMPORTANT, "mimeInit: " << filename << ": " << xstrerr(xerrno));
254  return;
255  }
256 
257 #if _SQUID_WINDOWS_
258  setmode(fileno(fp), O_TEXT);
259 #endif
260 
261  mimeFreeMemory();
262 
263  while (fgets(buf, BUFSIZ, fp)) {
264  if ((t = strchr(buf, '#')))
265  *t = '\0';
266 
267  if ((t = strchr(buf, '\r')))
268  *t = '\0';
269 
270  if ((t = strchr(buf, '\n')))
271  *t = '\0';
272 
273  if (buf[0] == '\0')
274  continue;
275 
276  xstrncpy(chopbuf, buf, BUFSIZ);
277 
278  if ((pattern = strtok(chopbuf, w_space)) == NULL) {
279  debugs(25, DBG_IMPORTANT, "mimeInit: parse error: '" << buf << "'");
280  continue;
281  }
282 
283  if ((type = strtok(NULL, w_space)) == NULL) {
284  debugs(25, DBG_IMPORTANT, "mimeInit: parse error: '" << buf << "'");
285  continue;
286  }
287 
288  if ((icon = strtok(NULL, w_space)) == NULL) {
289  debugs(25, DBG_IMPORTANT, "mimeInit: parse error: '" << buf << "'");
290  continue;
291  }
292 
293  if ((encoding = strtok(NULL, w_space)) == NULL) {
294  debugs(25, DBG_IMPORTANT, "mimeInit: parse error: '" << buf << "'");
295  continue;
296  }
297 
298  if ((mode = strtok(NULL, w_space)) == NULL) {
299  debugs(25, DBG_IMPORTANT, "mimeInit: parse error: '" << buf << "'");
300  continue;
301  }
302 
303  download_option = 0;
304  view_option = 0;
305 
306  while ((option = strtok(NULL, w_space)) != NULL) {
307  if (!strcmp(option, "+download"))
308  download_option = 1;
309  else if (!strcmp(option, "+view"))
310  view_option = 1;
311  else
312  debugs(25, DBG_IMPORTANT, "mimeInit: unknown option: '" << buf << "' (" << option << ")");
313  }
314 
315  if (regcomp(&re, pattern, re_flags) != 0) {
316  debugs(25, DBG_IMPORTANT, "mimeInit: regcomp error: '" << buf << "'");
317  continue;
318  }
319 
320  m = new MimeEntry(pattern,re,type,encoding,mode,view_option,
321  download_option,icon);
322 
323  *MimeTableTail = m;
324 
325  MimeTableTail = &m->next;
326 
327  debugs(25, 5, "mimeInit: added '" << buf << "'");
328  }
329 
330  fclose(fp);
331 
332  for (m = MimeTable; m != NULL; m = m->next)
333  m->theIcon.load();
334  debugs(25, DBG_IMPORTANT, "Finished loading MIME types and icons.");
335 }
336 
337 void
339 {
340  MimeEntry *m;
341 
342  while ((m = MimeTable)) {
343  MimeTable = m->next;
344  delete m;
345  }
346 
347  MimeTableTail = &MimeTable;
348 }
349 
350 void
352 {
353  const char *type = mimeGetContentType(icon_.c_str());
354 
355  if (type == NULL)
356  fatal("Unknown icon format while reading mime.conf\n");
357 
359 }
360 
361 void
363 {
364  /* if the icon is already in the store, do nothing */
365  if (!newEntry->isNull())
366  return;
367  // XXX: if a 204 is cached due to earlier load 'failure' we should try to reload.
368 
369  // default is a 200 object with image data.
370  // set to the backup value of 204 on image loading errors
372 
373  static char path[MAXPATHLEN];
374  *path = 0;
375  if (snprintf(path, sizeof(path)-1, "%s/" SQUIDSBUFPH, Config.icons.directory, SQUIDSBUFPRINT(icon_)) < 0) {
376  debugs(25, DBG_CRITICAL, "ERROR: icon file '" << Config.icons.directory << "/" << icon_ << "' path is longer than " << MAXPATHLEN << " bytes");
377  status = Http::scNoContent;
378  }
379 
380  int fd = -1;
381  errno = 0;
382  if (status == Http::scOkay && (fd = file_open(path, O_RDONLY | O_BINARY)) < 0) {
383  int xerrno = errno;
384  debugs(25, DBG_CRITICAL, "ERROR: opening icon file " << path << ": " << xstrerr(xerrno));
385  status = Http::scNoContent;
386  }
387 
388  struct stat sb;
389  errno = 0;
390  if (status == Http::scOkay && fstat(fd, &sb) < 0) {
391  int xerrno = errno;
392  debugs(25, DBG_CRITICAL, "ERROR: opening icon file " << path << " FD " << fd << ", fstat error " << xstrerr(xerrno));
393  file_close(fd);
394  status = Http::scNoContent;
395  }
396 
399  if (!r)
400  fatalf("mimeLoadIcon: cannot parse internal URL: %s", url_);
401 
402  // fill newEntry with a canned 2xx response object
403  RequestFlags flags;
404  flags.cachable = true;
406  assert(e != NULL);
408  e->setPublicKey();
409  e->buffer();
410 
411  e->mem_obj->request = r;
412 
413  HttpReplyPointer reply(new HttpReply);
414 
415  if (status == Http::scNoContent)
416  reply->setHeaders(status, NULL, NULL, 0, -1, -1);
417  else
418  reply->setHeaders(status, NULL, mimeGetContentType(icon_.c_str()), sb.st_size, sb.st_mtime, -1);
419  reply->cache_control = new HttpHdrCc();
420  reply->cache_control->maxAge(86400);
421  reply->header.putCc(reply->cache_control);
422  e->replaceHttpReply(reply.getRaw());
423 
424  if (status == Http::scOkay) {
425  /* read the file into the buffer and append it to store */
426  int n;
427  std::array<char, 4096> buf;
428  while ((n = FD_READ_METHOD(fd, buf.data(), buf.size())) > 0)
429  e->append(buf.data(), n);
430 
431  file_close(fd);
432  }
433 
434  e->flush();
435  e->complete();
436  e->timestampsSet();
437  e->unlock("MimeIcon::created");
438  debugs(25, 3, "Loaded icon " << url_);
439 }
440 
442 {
443  xfree(pattern);
447 }
448 
449 MimeEntry::MimeEntry(const char *aPattern, const regex_t &compiledPattern,
450  const char *aContentType, const char *aContentEncoding,
451  const char *aTransferMode, bool optionViewEnable,
452  bool optionDownloadEnable, const char *anIconName) :
453  pattern(xstrdup(aPattern)),
454  compiled_pattern(compiledPattern),
455  content_type(xstrdup(aContentType)),
456  content_encoding(xstrdup(aContentEncoding)),
457  view_option(optionViewEnable),
458  download_option(optionDownloadEnable),
459  theIcon(anIconName), next(NULL)
460 {
461  if (!strcasecmp(aTransferMode, "ascii"))
462  transfer_mode = 'A';
463  else if (!strcasecmp(aTransferMode, "text"))
464  transfer_mode = 'A';
465  else
466  transfer_mode = 'I';
467 }
468 
~MimeIcon()
Definition: mime.cc:126
int regcomp(regex_t *preg, const char *pattern, int cflags)
Definition: GnuRegex.c:4120
const char * pattern
Definition: mime.cc:68
#define assert(EX)
Definition: assert.h:17
bool mimeGetDownloadOption(const char *fn)
Definition: mime.cc:211
Definition: mime.cc:37
const char * mimeGetIconURL(const char *fn)
Definition: mime.cc:157
HttpHdrCc * cache_control
Definition: Message.h:76
int unlock(const char *context)
Definition: store.cc:485
bool mimeGetViewOption(const char *fn)
Definition: mime.cc:218
int type
Definition: errorpage.cc:79
const char * content_encoding
Definition: mime.cc:71
bool timestampsSet()
Definition: store.cc:1525
Definition: SBuf.h:87
void load()
Definition: mime.cc:351
virtual void append(char const *, int)
Appends a c-string to existing packed data.
Definition: store.cc:844
const char * null_string
char * fn
Definition: membanger.c:36
#define xstrdup
void setPublicKey(const KeyScope keyScope=ksDefault)
Definition: store.cc:623
SBuf & append(const SBuf &S)
Definition: SBuf.cc:207
#define MAXPATHLEN
Definition: stdio.h:62
virtual void buffer()
Definition: store.cc:1707
~MimeEntry()
Definition: mime.cc:441
void regfree(regex_t *preg)
Definition: GnuRegex.c:4283
const char * mimeGetContentEncoding(const char *fn)
Definition: mime.cc:190
int file_open(const char *path, int mode)
Definition: fs_io.cc:46
void setName(char const *)
Definition: mime.cc:132
virtual void flush()
Definition: store.cc:1718
void clear()
Definition: SBuf.cc:190
MimeEntry * next
Definition: mime.cc:76
bool isEmpty() const
Definition: SBuf.h:422
#define DBG_CRITICAL
Definition: Debug.h:44
const char * content_type
Definition: mime.cc:70
MimeIcon(const char *aName)
Definition: mime.cc:120
char mimeGetTransferMode(const char *fn)
Definition: mime.cc:204
static MimeEntry * MimeTable
Definition: mime.cc:79
MEMPROXY_CLASS(MimeIcon)
#define w_space
struct SquidConfig::@115 icons
void replaceHttpReply(HttpReply *, bool andStartWriting=true)
Definition: store.cc:1854
void fatalf(const char *fmt,...)
Definition: fatal.cc:79
virtual void complete()
Definition: store.cc:1088
void maxAge(int32_t v)
Definition: HttpHdrCc.h:123
static void getPublic(StoreClient *aClient, const char *uri, const HttpRequestMethod &method)
Definition: store.cc:537
#define REG_EXTENDED
Definition: GnuRegex.h:226
const char * xstrerr(int error)
Definition: xstrerror.cc:83
StatusCode
Definition: StatusCode.h:20
#define REG_ICASE
Definition: GnuRegex.h:230
bool view_option
Definition: mime.cc:73
#define debugs(SECTION, LEVEL, CONTENT)
Definition: Debug.h:123
void setHeaders(Http::StatusCode status, const char *reason, const char *ctype, int64_t clen, time_t lmt, time_t expires)
Definition: HttpReply.cc:151
StoreEntry * storeCreateEntry(const char *url, const char *logUrl, const RequestFlags &flags, const HttpRequestMethod &method)
Definition: store.cc:800
#define DBG_IMPORTANT
Definition: Debug.h:45
regex_t compiled_pattern
Definition: mime.cc:69
FILE * fp
Definition: membanger.c:35
char transfer_mode
Definition: mime.cc:72
char * xstrncpy(char *dst, const char *src, size_t n)
Definition: xstring.cc:37
void fatal(const char *message)
Definition: fatal.cc:39
char * directory
Definition: SquidConfig.h:421
char * url_
Definition: mime.cc:53
const char * c_str()
Definition: SBuf.cc:546
uint16_t flags
Definition: Store.h:173
MemObject * mem_obj
Definition: Store.h:162
MEMPROXY_CLASS(MimeEntry)
#define BUFSIZ
Definition: defines.h:20
char * internalLocalUri(const char *dir, const SBuf &name)
Definition: internal.cc:134
static HttpRequest * FromUrl(const char *url, const MasterXaction::Pointer &, const HttpRequestMethod &method=Http::METHOD_GET)
Definition: HttpRequest.cc:523
void const char * buf
Definition: stub_helper.cc:16
#define O_TEXT
Definition: defines.h:201
HttpHeader header
Definition: Message.h:74
#define EBIT_SET(flag, bit)
Definition: defines.h:105
#define FD_READ_METHOD(fd, buf, len)
Definition: fde.h:161
int regexec(regex_t *preg, const char *string, size_t nmatch, pmatch, int eflags) const
Definition: GnuRegex.c:4191
void putCc(const HttpHdrCc *cc)
Definition: HttpHeader.cc:1079
virtual void created(StoreEntry *)
Definition: mime.cc:362
virtual bool isNull()
Definition: Store.h:195
int cmp(const SBuf &S, const size_type n) const
shorthand version for compare()
Definition: SBuf.h:265
#define REG_NOSUB
Definition: GnuRegex.h:239
bool download_option
Definition: mime.cc:74
void mimeInit(char *filename)
Definition: mime.cc:230
static const SBuf mimeGetIcon(const char *fn)
Definition: mime.cc:146
#define O_BINARY
Definition: defines.h:204
#define SQUIDSBUFPH
Definition: SBuf.h:32
const char * mimeGetContentType(const char *fn)
Definition: mime.cc:176
#define xfree
void file_close(int fd)
Definition: fs_io.cc:76
#define SQUIDSBUFPRINT(s)
Definition: SBuf.h:33
static void mimeFreeMemory(void)
Definition: mime.cc:338
int use_short_names
Definition: SquidConfig.h:422
HttpRequestPointer request
Definition: MemObject.h:157
C * getRaw() const
Definition: RefCount.h:74
class SquidConfig Config
Definition: SquidConfig.cc:12
#define NULL
Definition: types.h:166
static MimeEntry * mimeGetEntry(const char *fn, int skip_encodings)
Definition: mime.cc:83
MimeEntry(const char *aPattern, const regex_t &compiledPattern, const char *aContentType, const char *aContentEncoding, const char *aTransferMode, bool optionViewEnable, bool optionDownloadEnable, const char *anIconName)
Definition: mime.cc:449
SBuf icon_
Definition: mime.cc:52
SBuf getName() const
Definition: mime.cc:140
const char * dash_str
MimeIcon theIcon
Definition: mime.cc:75

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors