]>
git.ipfire.org Git - thirdparty/squid.git/blob - src/mime.cc
2 * Copyright (C) 1996-2014 The Squid Software Foundation and contributors
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.
9 /* DEBUG: section 25 MIME Parsing and Internal Icons */
15 #include "HttpHdrCc.h"
16 #include "HttpReply.h"
17 #include "HttpRequest.h"
21 #include "MemObject.h"
23 #include "RequestFlags.h"
24 #include "SquidConfig.h"
26 #include "StoreClient.h"
32 /* forward declarations */
33 static void mimeFreeMemory(void);
34 static char const *mimeGetIcon(const char *fn
);
36 class MimeIcon
: public StoreClient
39 explicit MimeIcon(const char *aName
);
41 void setName(char const *);
42 char const * getName() const;
44 void created(StoreEntry
*newEntry
);
45 MEMPROXY_CLASS(MimeIcon
);
51 MEMPROXY_CLASS_INLINE(MimeIcon
);
56 explicit MimeEntry(const char *aPattern
, const regex_t
&compiledPattern
,
57 const char *aContentType
,
58 const char *aContentEncoding
, const char *aTransferMode
,
59 bool optionViewEnable
, bool optionDownloadEnable
,
60 const char *anIconName
);
62 MEMPROXY_CLASS(MimeEntry
);
65 regex_t compiled_pattern
;
66 const char *content_type
;
67 const char *content_encoding
;
74 MEMPROXY_CLASS_INLINE(MimeEntry
);
76 static MimeEntry
*MimeTable
= NULL
;
77 static MimeEntry
**MimeTableTail
= &MimeTable
;
80 mimeGetEntry(const char *fn
, int skip_encodings
)
84 char *name
= xstrdup(fn
);
89 for (m
= MimeTable
; m
; m
= m
->next
) {
90 if (regexec(&m
->compiled_pattern
, name
, 0, 0, 0) == 0)
98 else if (strcmp(m
->content_type
, dash_str
))
100 else if (!strcmp(m
->content_encoding
, dash_str
))
103 /* Assume we matched /\.\w$/ and cut off the last extension */
104 if ((t
= strrchr(name
, '.'))) {
107 /* What? A encoding without a extension? */
117 MimeIcon::MimeIcon(const char *aName
) :
118 icon_(xstrdup(aName
))
120 url_
= xstrdup(internalLocalUri("/squid-internal-static/icons/", icon_
));
123 MimeIcon::~MimeIcon()
130 MimeIcon::setName(char const *aString
)
134 icon_
= xstrdup(aString
);
135 url_
= xstrdup(internalLocalUri("/squid-internal-static/icons/", icon_
));
139 MimeIcon::getName() const
145 mimeGetIcon(const char *fn
)
147 MimeEntry
*m
= mimeGetEntry(fn
, 1);
152 if (!strcmp(m
->theIcon
.getName(), dash_str
))
155 return m
->theIcon
.getName();
159 mimeGetIconURL(const char *fn
)
161 char const *icon
= mimeGetIcon(fn
);
166 if (Config
.icons
.use_short_names
) {
169 mb
.Printf("/squid-internal-static/icons/%s", icon
);
172 return internalLocalUri("/squid-internal-static/icons/", icon
);
177 mimeGetContentType(const char *fn
)
179 MimeEntry
*m
= mimeGetEntry(fn
, 1);
184 if (!strcmp(m
->content_type
, dash_str
))
187 return m
->content_type
;
191 mimeGetContentEncoding(const char *fn
)
193 MimeEntry
*m
= mimeGetEntry(fn
, 0);
198 if (!strcmp(m
->content_encoding
, dash_str
))
201 return m
->content_encoding
;
205 mimeGetTransferMode(const char *fn
)
207 MimeEntry
*m
= mimeGetEntry(fn
, 0);
208 return m
? m
->transfer_mode
: 'I';
212 mimeGetDownloadOption(const char *fn
)
214 MimeEntry
*m
= mimeGetEntry(fn
, 1);
215 return m
? m
->download_option
: 0;
219 mimeGetViewOption(const char *fn
)
221 MimeEntry
*m
= mimeGetEntry(fn
, 0);
222 return m
!= 0 ? m
->view_option
: false;
225 /* Initializes/reloads the mime table
226 * Note: Due to Solaris STDIO problems the caller should NOT
227 * call mimeFreeMemory on reconfigure. This way, if STDIO
228 * fails we at least have the old copy loaded.
231 mimeInit(char *filename
)
235 char chopbuf
[BUFSIZ
];
247 int re_flags
= REG_EXTENDED
| REG_NOSUB
| REG_ICASE
;
249 if (filename
== NULL
)
252 if ((fp
= fopen(filename
, "r")) == NULL
) {
253 debugs(25, DBG_IMPORTANT
, "mimeInit: " << filename
<< ": " << xstrerror());
258 setmode(fileno(fp
), O_TEXT
);
263 while (fgets(buf
, BUFSIZ
, fp
)) {
264 if ((t
= strchr(buf
, '#')))
267 if ((t
= strchr(buf
, '\r')))
270 if ((t
= strchr(buf
, '\n')))
276 xstrncpy(chopbuf
, buf
, BUFSIZ
);
278 if ((pattern
= strtok(chopbuf
, w_space
)) == NULL
) {
279 debugs(25, DBG_IMPORTANT
, "mimeInit: parse error: '" << buf
<< "'");
283 if ((type
= strtok(NULL
, w_space
)) == NULL
) {
284 debugs(25, DBG_IMPORTANT
, "mimeInit: parse error: '" << buf
<< "'");
288 if ((icon
= strtok(NULL
, w_space
)) == NULL
) {
289 debugs(25, DBG_IMPORTANT
, "mimeInit: parse error: '" << buf
<< "'");
293 if ((encoding
= strtok(NULL
, w_space
)) == NULL
) {
294 debugs(25, DBG_IMPORTANT
, "mimeInit: parse error: '" << buf
<< "'");
298 if ((mode
= strtok(NULL
, w_space
)) == NULL
) {
299 debugs(25, DBG_IMPORTANT
, "mimeInit: parse error: '" << buf
<< "'");
306 while ((option
= strtok(NULL
, w_space
)) != NULL
) {
307 if (!strcmp(option
, "+download"))
309 else if (!strcmp(option
, "+view"))
312 debugs(25, DBG_IMPORTANT
, "mimeInit: unknown option: '" << buf
<< "' (" << option
<< ")");
315 if (regcomp(&re
, pattern
, re_flags
) != 0) {
316 debugs(25, DBG_IMPORTANT
, "mimeInit: regcomp error: '" << buf
<< "'");
320 m
= new MimeEntry(pattern
,re
,type
,encoding
,mode
,view_option
,
321 download_option
,icon
);
325 MimeTableTail
= &m
->next
;
327 debugs(25, 5, "mimeInit: added '" << buf
<< "'");
332 for (m
= MimeTable
; m
!= NULL
; m
= m
->next
)
334 debugs(25, DBG_IMPORTANT
, "Finished loading MIME types and icons.");
342 while ((m
= MimeTable
)) {
347 MimeTableTail
= &MimeTable
;
353 const char *type
= mimeGetContentType(icon_
);
356 fatal("Unknown icon format while reading mime.conf\n");
358 StoreEntry::getPublic(this, url_
, Http::METHOD_GET
);
362 MimeIcon::created (StoreEntry
*newEntry
)
364 /* if the icon is already in the store, do nothing */
365 if (!newEntry
->isNull())
372 LOCAL_ARRAY(char, path
, MAXPATHLEN
);
375 snprintf(path
, MAXPATHLEN
, "%s/%s", Config
.icons
.directory
, icon_
);
377 fd
= file_open(path
, O_RDONLY
| O_BINARY
);
379 debugs(25, DBG_CRITICAL
, "Problem opening icon file " << path
<< ": " << xstrerror());
382 if (fstat(fd
, &sb
) < 0) {
383 debugs(25, DBG_CRITICAL
, "Problem opening icon file. Fd: " << fd
<< ", fstat error " << xstrerror());
388 flags
.cachable
= true;
389 StoreEntry
*e
= storeCreateEntry(url_
,url_
,flags
,Http::METHOD_GET
);
391 EBIT_SET(e
->flags
, ENTRY_SPECIAL
);
394 HttpRequest
*r
= HttpRequest::CreateFromUrl(url_
);
397 fatal("mimeLoadIcon: cannot parse internal URL");
399 e
->mem_obj
->request
= r
;
400 HTTPMSGLOCK(e
->mem_obj
->request
);
402 HttpReply
*reply
= new HttpReply
;
404 reply
->setHeaders(Http::scOkay
, NULL
, mimeGetContentType(icon_
), sb
.st_size
, sb
.st_mtime
, -1);
405 reply
->cache_control
= new HttpHdrCc();
406 reply
->cache_control
->maxAge(86400);
407 reply
->header
.putCc(reply
->cache_control
);
408 e
->replaceHttpReply(reply
);
410 /* read the file into the buffer and append it to store */
411 buf
= (char *)memAllocate(MEM_4K_BUF
);
412 while ((n
= FD_READ_METHOD(fd
, buf
, 4096)) > 0)
419 e
->unlock("MimeIcon::created");
420 memFree(buf
, MEM_4K_BUF
);
421 debugs(25, 3, "Loaded icon " << url_
);
424 MimeEntry::~MimeEntry()
428 xfree(content_encoding
);
429 regfree(&compiled_pattern
);
432 MimeEntry::MimeEntry(const char *aPattern
, const regex_t
&compiledPattern
,
433 const char *aContentType
, const char *aContentEncoding
,
434 const char *aTransferMode
, bool optionViewEnable
,
435 bool optionDownloadEnable
, const char *anIconName
) :
436 pattern(xstrdup(aPattern
)),
437 compiled_pattern(compiledPattern
),
438 content_type(xstrdup(aContentType
)),
439 content_encoding(xstrdup(aContentEncoding
)),
440 view_option(optionViewEnable
),
441 download_option(optionViewEnable
),
442 theIcon(anIconName
), next(NULL
)
444 if (!strcasecmp(aTransferMode
, "ascii"))
446 else if (!strcasecmp(aTransferMode
, "text"))