NetSurf
mimesniff.c
Go to the documentation of this file.
1/*
2 * Copyright 2011 John-Mark Bell <jmb@netsurf-browser.org>
3 *
4 * This file is part of NetSurf, http://www.netsurf-browser.org/
5 *
6 * NetSurf is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * NetSurf is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19/**
20 * \file
21 * MIME type sniffer implementation
22 *
23 * Spec version: 2011-11-27
24 */
25
26#include <string.h>
27#include <strings.h>
28
29#include "utils/http.h"
30#include "utils/utils.h"
31#include "utils/corestrings.h"
32
34#include "content/mimesniff.h"
35
36struct map_s {
37 const uint8_t *sig;
38 size_t len;
39 bool safe;
40 lwc_string **type;
41};
42
43static bool mimesniff__has_binary_octets(const uint8_t *data, size_t len)
44{
45 const uint8_t *end = data + len;
46
47 while (data != end) {
48 const uint8_t c = *data;
49
50 /* Binary iff in C0 and not ESC, CR, FF, LF, HT */
51 if (c <= 0x1f && c != 0x1b && c != '\r' && c != '\f' &&
52 c != '\n' && c != '\t')
53 break;
54
55 data++;
56 }
57
58 return data != end;
59}
60
61static nserror mimesniff__match_mp4(const uint8_t *data, size_t len,
62 lwc_string **effective_type)
63{
64 uint32_t box_size, i;
65
66 /* ISO/IEC 14496-12:2008 $4.3 says (effectively):
67 *
68 * struct ftyp_box {
69 * uint32_t size; (in octets, including size+type words)
70 * uint32_t type; (== 'ftyp')
71 * uint32_t major_brand;
72 * uint32_t minor_version;
73 * uint32_t compatible_brands[];
74 * }
75 *
76 * Note 1: A size of 0 implies that the length of the box is designated
77 * by the remaining input data (and thus may only occur in the last
78 * box in the input). We'll reject this below, as it's pointless
79 * sniffing input that contains no boxes other than 'ftyp'.
80 *
81 * Note 2: A size of 1 implies an additional uint64_t field after
82 * the type which contains the extended box size. We'll reject this,
83 * too, as it implies a minimum of (2^32 - 24) / 4 compatible brands,
84 * which is decidely unlikely.
85 */
86
87 /* 12 reflects the minimum number of octets needed to sniff useful
88 * information out of an 'ftyp' box (i.e. the size, type,
89 * and major_brand words). */
90 if (len < 12)
91 return NSERROR_NOT_FOUND;
92
93 /* Box size is big-endian */
94 box_size = (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3];
95
96 /* Require that we can read the entire box, and reject bad box sizes */
97 if (len < box_size || box_size % 4 != 0)
98 return NSERROR_NOT_FOUND;
99
100 /* Ensure this is an 'ftyp' box */
101 if (data[4] != 'f' || data[5] != 't' ||
102 data[6] != 'y' || data[7] != 'p')
103 return NSERROR_NOT_FOUND;
104
105 /* Check if major brand begins with 'mp4' */
106 if (data[8] == 'm' && data[9] == 'p' && data[10] == '4') {
107 *effective_type = lwc_string_ref(corestring_lwc_video_mp4);
108 return NSERROR_OK;
109 }
110
111 /* Search each compatible brand in the box for "mp4" */
112 for (i = 16; i <= box_size - 4; i += 4) {
113 if (data[i] == 'm' &&
114 data[i+1] == 'p' &&
115 data[i+2] == '4') {
116 *effective_type = lwc_string_ref(corestring_lwc_video_mp4);
117 return NSERROR_OK;
118 }
119 }
120
121 return NSERROR_NOT_FOUND;
122}
123
124static nserror mimesniff__match_unknown_ws(const uint8_t *data, size_t len,
125 lwc_string **effective_type)
126{
127#define SIG(t, s, x) { (const uint8_t *) s, SLEN(s), x, t }
128 static const struct map_s ws_exact_match_types[] = {
129 SIG(&corestring_lwc_text_xml, "<?xml", false),
130 { NULL, 0, false, NULL }
131 };
132
133 static const struct map_s ws_inexact_match_types[] = {
134 SIG(&corestring_lwc_text_html, "<!DOCTYPE HTML", false),
135 SIG(&corestring_lwc_text_html, "<HTML", false),
136 SIG(&corestring_lwc_text_html, "<HEAD", false),
137 SIG(&corestring_lwc_text_html, "<SCRIPT", false),
138 SIG(&corestring_lwc_text_html, "<IFRAME", false),
139 SIG(&corestring_lwc_text_html, "<H1", false),
140 SIG(&corestring_lwc_text_html, "<DIV", false),
141 SIG(&corestring_lwc_text_html, "<FONT", false),
142 SIG(&corestring_lwc_text_html, "<TABLE", false),
143 SIG(&corestring_lwc_text_html, "<A", false),
144 SIG(&corestring_lwc_text_html, "<STYLE", false),
145 SIG(&corestring_lwc_text_html, "<TITLE", false),
146 SIG(&corestring_lwc_text_html, "<B", false),
147 SIG(&corestring_lwc_text_html, "<BODY", false),
148 SIG(&corestring_lwc_text_html, "<BR", false),
149 SIG(&corestring_lwc_text_html, "<P", false),
150 SIG(&corestring_lwc_text_html, "<!--", false),
151 { NULL, 0, false, NULL }
152 };
153#undef SIG
154 const uint8_t *end = data + len;
155 const struct map_s *it;
156
157 /* Skip leading whitespace */
158 while (data != end) {
159 const uint8_t c = *data;
160
161 if (c != '\t' && c != '\n' && c != '\f' &&
162 c != '\r' && c != ' ')
163 break;
164
165 data++;
166 }
167
168 if (data == end)
169 return NSERROR_NOT_FOUND;
170
171 len = end - data;
172
173 for (it = ws_exact_match_types; it->sig != NULL; it++) {
174 if (it->len <= len && memcmp(data, it->sig, it->len) == 0) {
175 *effective_type = lwc_string_ref(*it->type);
176 return NSERROR_OK;
177 }
178 }
179
180 for (it = ws_inexact_match_types; it->sig != NULL; it++) {
181 /* +1 for trailing space or > */
182 if (len < it->len + 1)
183 continue;
184
185 if (strncasecmp((const char *) data,
186 (const char *) it->sig, it->len) == 0 &&
187 (data[it->len] == ' ' ||
188 data[it->len] == '>')) {
189 *effective_type = lwc_string_ref(*it->type);
190 return NSERROR_OK;
191 }
192 }
193
194 return NSERROR_NOT_FOUND;
195}
196
197static nserror mimesniff__match_unknown_bom(const uint8_t *data, size_t len,
198 lwc_string **effective_type)
199{
200#define SIG(t, s, x) { (const uint8_t *) s, SLEN(s), x, t }
201 static const struct map_s bom_match_types[] = {
202 SIG(&corestring_lwc_text_plain, "\xfe\xff", false),
203 SIG(&corestring_lwc_text_plain, "\xff\xfe", false),
204 SIG(&corestring_lwc_text_plain, "\xef\xbb\xbf", false),
205 { NULL, 0, false, NULL }
206 };
207#undef SIG
208 const struct map_s *it;
209
210 for (it = bom_match_types; it->sig != NULL; it++) {
211 if (it->len <= len && memcmp(data, it->sig, it->len) == 0) {
212 *effective_type = lwc_string_ref(*it->type);
213 return NSERROR_OK;
214 }
215 }
216
217 return NSERROR_NOT_FOUND;
218}
219
220static nserror mimesniff__match_unknown_riff(const uint8_t *data, size_t len,
221 lwc_string **effective_type)
222{
223#define SIG(t, s, x) { (const uint8_t *) s, SLEN(s), x, t }
224 static const struct map_s riff_match_types[] = {
225 SIG(&corestring_lwc_image_webp, "WEBPVP", true),
226 SIG(&corestring_lwc_audio_wave, "WAVE", true),
227 { NULL, 0, false, NULL }
228 };
229#undef SIG
230 const struct map_s *it;
231
232 for (it = riff_match_types; it->sig != NULL; it++) {
233 if (it->len + SLEN("RIFF????") <= len &&
234 memcmp(data, "RIFF", SLEN("RIFF")) == 0 &&
235 memcmp(data + SLEN("RIFF????"),
236 it->sig, it->len) == 0) {
237 *effective_type = lwc_string_ref(*it->type);
238 return NSERROR_OK;
239 }
240 }
241
242 return NSERROR_NOT_FOUND;
243}
244
245static nserror mimesniff__match_unknown_exact(const uint8_t *data, size_t len,
246 bool allow_unsafe, lwc_string **effective_type)
247{
248#define SIG(t, s, x) { (const uint8_t *) s, SLEN(s), x, t }
249 static const struct map_s exact_match_types[] = {
250 SIG(&corestring_lwc_image_gif, "GIF87a", true),
251 SIG(&corestring_lwc_image_gif, "GIF89a", true),
252 SIG(&corestring_lwc_image_png, "\x89PNG\r\n\x1a\n", true),
253 SIG(&corestring_lwc_image_jpeg, "\xff\xd8\xff", true),
254 SIG(&corestring_lwc_image_bmp, "BM", true),
255 SIG(&corestring_lwc_image_vnd_microsoft_icon, "\x00\x00\x01\x00", true),
256 SIG(&corestring_lwc_application_ogg, "OggS\x00", true),
257 SIG(&corestring_lwc_video_webm, "\x1a\x45\xdf\xa3", true),
258 SIG(&corestring_lwc_application_x_rar_compressed, "Rar \x1a\x07\x00", true),
259 SIG(&corestring_lwc_application_zip, "PK\x03\x04", true),
260 SIG(&corestring_lwc_application_x_gzip, "\x1f\x8b\x08", true),
261 SIG(&corestring_lwc_application_postscript, "%!PS-Adobe-",true),
262 SIG(&corestring_lwc_application_pdf, "%PDF-", false),
263 SIG(&corestring_lwc_image_jxl, "\xFF\x0A", true), /* containerless jpeg xl*/
264 {
265 (const uint8_t *)"\x00\x00\x00\x0CJXL \x0D\x0A\x87\x0A",
266 12,
267 true,
268 &corestring_lwc_image_jxl
269 }, /* containered jpeg xl*/
270 { NULL, 0, false, NULL }
271 };
272#undef SIG
273 const struct map_s *it;
274
275 for (it = exact_match_types; it->sig != NULL; it++) {
276 if (it->len <= len && memcmp(data, it->sig, it->len) == 0 &&
277 (allow_unsafe || it->safe)) {
278 *effective_type = lwc_string_ref(*it->type);
279 return NSERROR_OK;
280 }
281 }
282
283 return NSERROR_NOT_FOUND;
284}
285
286static nserror mimesniff__match_unknown(const uint8_t *data, size_t len,
287 bool allow_unsafe, lwc_string **effective_type)
288{
289 if (mimesniff__match_unknown_exact(data, len, allow_unsafe,
290 effective_type) == NSERROR_OK)
291 return NSERROR_OK;
292
294 effective_type) == NSERROR_OK)
295 return NSERROR_OK;
296
297 if (allow_unsafe == false)
298 return NSERROR_NOT_FOUND;
299
301 effective_type) == NSERROR_OK)
302 return NSERROR_OK;
303
305 effective_type) == NSERROR_OK)
306 return NSERROR_OK;
307
308 if (mimesniff__match_mp4(data, len, effective_type) == NSERROR_OK)
309 return NSERROR_OK;
310
311 return NSERROR_NOT_FOUND;
312}
313
314static nserror mimesniff__compute_unknown(const uint8_t *data, size_t len,
315 lwc_string **effective_type)
316{
317 if (data == NULL)
318 return NSERROR_NEED_DATA;
319
320 len = min(len, 512);
321
322 if (mimesniff__match_unknown(data, len, true,
323 effective_type) == NSERROR_OK) {
324 return NSERROR_OK;
325 }
326
327 if (mimesniff__has_binary_octets(data, len) == false) {
328 /* No binary octets => text/plain */
329 *effective_type = lwc_string_ref(corestring_lwc_text_plain);
330 return NSERROR_OK;
331 }
332
333 *effective_type = lwc_string_ref(corestring_lwc_application_octet_stream);
334
335 return NSERROR_OK;
336}
337
339 size_t len, lwc_string **effective_type)
340{
341 if (data == NULL) {
342 return NSERROR_NEED_DATA;
343 }
344
345 len = min(len, 512);
346
347 if (len >= 3 && ((data[0] == 0xfe && data[1] == 0xff) ||
348 (data[0] == 0xff && data[1] == 0xfe) ||
349 (data[0] == 0xef && data[1] == 0xbb &&
350 data[2] == 0xbf))) {
351 /* Found a BOM => text/plain */
352 *effective_type = lwc_string_ref(corestring_lwc_text_plain);
353 return NSERROR_OK;
354 }
355
356 if (mimesniff__has_binary_octets(data, len) == false) {
357 /* No binary octets => text/plain */
358 *effective_type = lwc_string_ref(corestring_lwc_text_plain);
359 return NSERROR_OK;
360 }
361
362 if (mimesniff__match_unknown(data, len, false,
363 effective_type) == NSERROR_OK)
364 return NSERROR_OK;
365
366 *effective_type = lwc_string_ref(corestring_lwc_application_octet_stream);
367
368 return NSERROR_OK;
369}
370
371static nserror mimesniff__compute_image(lwc_string *official_type,
372 const uint8_t *data, size_t len, lwc_string **effective_type)
373{
374#define SIG(t, s) { (const uint8_t *) s, SLEN(s), t }
375 static const struct it_s {
376 const uint8_t *sig;
377 size_t len;
378 lwc_string **type;
379 } image_types[] = {
380 SIG(&corestring_lwc_image_gif, "GIF87a"),
381 SIG(&corestring_lwc_image_gif, "GIF89a"),
382 SIG(&corestring_lwc_image_png, "\x89PNG\r\n\x1a\n"),
383 SIG(&corestring_lwc_image_jpeg, "\xff\xd8\xff"),
384 SIG(&corestring_lwc_image_bmp, "BM"),
385 SIG(&corestring_lwc_image_vnd_microsoft_icon, "\x00\x00\x01\x00"),
386 SIG(&corestring_lwc_image_jxl, "\xFF\x0A"), /* containerless jpeg xl*/
387 {
388 (const uint8_t *)"\x00\x00\x00\x0CJXL \x0D\x0A\x87\x0A",
389 12,
390 &corestring_lwc_image_jxl
391 }, /* containered jpeg xl*/
392 { NULL, 0, NULL }
393 };
394#undef SIG
395
396 const struct it_s *it;
397
398 if (data == NULL) {
399 lwc_string_unref(official_type);
400 return NSERROR_NEED_DATA;
401 }
402
403 for (it = image_types; it->sig != NULL; it++) {
404 if (it->len <= len && memcmp(data, it->sig, it->len) == 0) {
405 lwc_string_unref(official_type);
406 *effective_type = lwc_string_ref(*it->type);
407 return NSERROR_OK;
408 }
409 }
410
411 /* WebP has a signature that doesn't fit into the above table */
412 if (SLEN("RIFF????WEBPVP") <= len &&
413 memcmp(data, "RIFF", SLEN("RIFF")) == 0 &&
414 memcmp(data + SLEN("RIFF????"),
415 "WEBPVP", SLEN("WEBPVP")) == 0 ) {
416 lwc_string_unref(official_type);
417 *effective_type = lwc_string_ref(corestring_lwc_image_webp);
418 return NSERROR_OK;
419 }
420
421 *effective_type = official_type;
422
423 return NSERROR_OK;
424}
425
426static nserror mimesniff__compute_feed_or_html(const uint8_t *data,
427 size_t len, lwc_string **effective_type)
428{
429#define RDF_NS "http://www.w3.org/1999/02/22-rdf-syntax-ns#"
430#define RSS_NS "http://purl.org/rss/1.0"
431
432 enum state_e {
433 BEFORE_BOM,
434 BEFORE_MARKUP,
435 MARKUP_START,
436 COMMENT_OR_DOCTYPE,
437 IN_COMMENT,
438 IN_DOCTYPE,
439 IN_PI,
440 IN_TAG,
441 IN_RDF
442 } state = BEFORE_BOM;
443
444 bool rdf = false, rss = false;
445 const uint8_t *end;
446
447 if (data == NULL)
448 return NSERROR_NEED_DATA;
449
450 end = data + min(len, 512);
451
452 while (data < end) {
453 const uint8_t c = *data;
454
455#define MATCH(s) SLEN(s) <= (size_t) (end - data) && \
456 memcmp(data, s, SLEN(s)) == 0
457
458 switch (state) {
459 case BEFORE_BOM:
460 if (3 <= end - data && c == 0xef && data[1] == 0xbb &&
461 data[2] == 0xbf) {
462 data += 3;
463 }
464
465 state = BEFORE_MARKUP;
466 break;
467 case BEFORE_MARKUP:
468 if (c == '\t' || c == '\n' || c == '\r' || c == ' ')
469 data++;
470 else if (c != '<')
471 data = end;
472 else {
473 state = MARKUP_START;
474 data++;
475 }
476 break;
477 case MARKUP_START:
478 if (c == '!') {
479 state = COMMENT_OR_DOCTYPE;
480 data++;
481 } else if (c == '?') {
482 state = IN_PI;
483 data++;
484 } else {
485 /* Reconsume input */
486 state = IN_TAG;
487 }
488 break;
489 case COMMENT_OR_DOCTYPE:
490 if (2 <= end - data && c == '-' && data[1] == '-') {
491 state = IN_COMMENT;
492 data += 2;
493 } else {
494 /* Reconsume input */
495 state = IN_DOCTYPE;
496 }
497 break;
498 case IN_COMMENT:
499 if (3 <= end - data && c == '-' && data[1] == '-' &&
500 data[2] == '>') {
501 state = BEFORE_MARKUP;
502 data += 3;
503 } else
504 data++;
505 break;
506 case IN_DOCTYPE:
507 if (c == '>')
508 state = BEFORE_MARKUP;
509 data++;
510 break;
511 case IN_PI:
512 if (2 <= end - data && c == '?' && data[1] == '>') {
513 state = BEFORE_MARKUP;
514 data += 2;
515 } else
516 data++;
517 break;
518 case IN_TAG:
519 if (MATCH("rss")) {
520 *effective_type =
521 lwc_string_ref(corestring_lwc_application_rss_xml);
522 return NSERROR_OK;
523 } else if (MATCH("feed")) {
524 *effective_type =
525 lwc_string_ref(corestring_lwc_application_atom_xml);
526 return NSERROR_OK;
527 } else if (MATCH("rdf:RDF")) {
528 state = IN_RDF;
529 data += SLEN("rdf:RDF");
530 } else
531 data = end;
532 break;
533 case IN_RDF:
534 if (MATCH(RSS_NS)) {
535 rss = true;
536 data += SLEN(RSS_NS);
537 } else if (MATCH(RDF_NS)) {
538 rdf = true;
539 data += SLEN(RDF_NS);
540 } else
541 data++;
542
543 if (rdf && rss) {
544 *effective_type = lwc_string_ref(corestring_lwc_application_rss_xml);
545 return NSERROR_OK;
546 }
547
548 break;
549 }
550#undef MATCH
551 }
552
553 *effective_type = lwc_string_ref(corestring_lwc_text_html);
554
555 return NSERROR_OK;
556
557#undef RSS_NS
558#undef RDF_NS
559}
560
561/* See mimesniff.h for documentation */
563mimesniff_compute_effective_type(const char *content_type_header,
564 const uint8_t *data,
565 size_t len,
566 bool sniff_allowed,
567 bool image_only,
568 lwc_string **effective_type)
569{
570#define S(s) { s, SLEN(s) }
571 static const struct tt_s {
572 const char *data;
573 size_t len;
574 } text_types[] = {
575 S("text/plain"),
576 S("text/plain; charset=ISO-8859-1"),
577 S("text/plain; charset=iso-8859-1"),
578 S("text/plain; charset=UTF-8"),
579 { NULL, 0 }
580 };
581#undef S
582
583 size_t content_type_header_len;
585 const struct tt_s *tt;
586 bool match;
587 nserror error;
588
589 if (content_type_header == NULL) {
590 if (sniff_allowed == false) {
591 return NSERROR_NOT_FOUND;
592 }
593
594 /* No official type => unknown */
595 return mimesniff__compute_unknown(data, len, effective_type);
596 }
597
598 error = http_parse_content_type(content_type_header, &ct);
599 if (error != NSERROR_OK) {
600 if (sniff_allowed == false)
601 return NSERROR_NOT_FOUND;
602
603 /* Unparseable => unknown */
604 return mimesniff__compute_unknown(data, len, effective_type);
605 }
606
607 if (sniff_allowed == false) {
608 *effective_type = lwc_string_ref(ct->media_type);
610 return NSERROR_OK;
611 }
612
613 if (image_only) {
614 lwc_string *official_type;
615
616 if (lwc_string_caseless_isequal(ct->media_type,
617 corestring_lwc_image_svg,
618 &match) == lwc_error_ok && match) {
619 *effective_type = lwc_string_ref(corestring_lwc_image_svg);
621 return NSERROR_OK;
622 }
623
624 official_type = lwc_string_ref(ct->media_type);
626 return mimesniff__compute_image(official_type,
627 data, len, effective_type);
628 }
629
630 content_type_header_len = strlen(content_type_header);
631
632 /* Look for text types */
633 for (tt = text_types; tt->data != NULL; tt++) {
634 if (tt->len == content_type_header_len &&
635 memcmp(tt->data,
636 content_type_header,
637 content_type_header_len) == 0) {
639 return mimesniff__compute_text_or_binary(data, len,
640 effective_type);
641 }
642 }
643
644 /* unknown/unknown, application/unknown, * / * */
645 if ((lwc_string_caseless_isequal(ct->media_type,
646 corestring_lwc_unknown_unknown,
647 &match) == lwc_error_ok && match) ||
648 (lwc_string_caseless_isequal(ct->media_type,
649 corestring_lwc_application_unknown,
650 &match) == lwc_error_ok && match) ||
651 (lwc_string_caseless_isequal(ct->media_type,
652 corestring_lwc_any,
653 &match) == lwc_error_ok && match)) {
655 return mimesniff__compute_unknown(data, len, effective_type);
656 }
657
658 /* +xml */
659 if (lwc_string_length(ct->media_type) > SLEN("+xml") &&
660 strncasecmp(lwc_string_data(ct->media_type) +
661 lwc_string_length(ct->media_type) -
662 SLEN("+xml"),
663 "+xml", SLEN("+xml")) == 0) {
664 /* Use official type */
665 *effective_type = lwc_string_ref(ct->media_type);
667 return NSERROR_OK;
668 }
669
670 /* text/xml, application/xml */
671 if ((lwc_string_caseless_isequal(ct->media_type,
672 corestring_lwc_text_xml,
673 &match) == lwc_error_ok && match) ||
674 (lwc_string_caseless_isequal(ct->media_type,
675 corestring_lwc_application_xml,
676 &match) == lwc_error_ok && match)) {
677 /* Use official type */
678 *effective_type = lwc_string_ref(ct->media_type);
680 return NSERROR_OK;
681 }
682
683 /* Image types */
686 lwc_string *official_type = lwc_string_ref(ct->media_type);
688 return mimesniff__compute_image(official_type,
689 data, len, effective_type);
690 }
691
692 /* text/html */
693 if ((lwc_string_caseless_isequal(ct->media_type,
694 corestring_lwc_text_html,
695 &match) == lwc_error_ok && match)) {
697 return mimesniff__compute_feed_or_html(data, len,
698 effective_type);
699 }
700
701 /* Use official type */
702 *effective_type = lwc_string_ref(ct->media_type);
703
705
706 return NSERROR_OK;
707}
static const content_type image_types
Definition: box_construct.c:87
nserror http_parse_content_type(const char *header_value, http_content_type **result)
Parse an HTTP Content-Type header value.
Definition: content-type.c:30
void http_content_type_destroy(http_content_type *victim)
Destroy a content type object.
Definition: content-type.c:122
content_type content_factory_type_from_mime_type(lwc_string *mime_type)
Compute the generic content type for a MIME type.
@ CONTENT_IMAGE
All images.
Definition: content_type.h:67
Useful interned string pointers (interface).
nserror
Enumeration of error codes.
Definition: errors.h:29
@ NSERROR_NOT_FOUND
Requested item not found.
Definition: errors.h:34
@ NSERROR_NEED_DATA
More data needed.
Definition: errors.h:46
@ NSERROR_OK
No error.
Definition: errors.h:30
const char * type
Definition: filetype.cpp:44
HTTP header parsing functions.
#define MATCH(s)
static nserror mimesniff__match_unknown_exact(const uint8_t *data, size_t len, bool allow_unsafe, lwc_string **effective_type)
Definition: mimesniff.c:245
static nserror mimesniff__match_mp4(const uint8_t *data, size_t len, lwc_string **effective_type)
Definition: mimesniff.c:61
static nserror mimesniff__compute_text_or_binary(const uint8_t *data, size_t len, lwc_string **effective_type)
Definition: mimesniff.c:338
nserror mimesniff_compute_effective_type(const char *content_type_header, const uint8_t *data, size_t len, bool sniff_allowed, bool image_only, lwc_string **effective_type)
Compute the effective MIME type for an object.
Definition: mimesniff.c:563
static nserror mimesniff__match_unknown(const uint8_t *data, size_t len, bool allow_unsafe, lwc_string **effective_type)
Definition: mimesniff.c:286
static nserror mimesniff__match_unknown_bom(const uint8_t *data, size_t len, lwc_string **effective_type)
Definition: mimesniff.c:197
static bool mimesniff__has_binary_octets(const uint8_t *data, size_t len)
Definition: mimesniff.c:43
static nserror mimesniff__compute_unknown(const uint8_t *data, size_t len, lwc_string **effective_type)
Definition: mimesniff.c:314
#define S(s)
static nserror mimesniff__match_unknown_ws(const uint8_t *data, size_t len, lwc_string **effective_type)
Definition: mimesniff.c:124
static nserror mimesniff__match_unknown_riff(const uint8_t *data, size_t len, lwc_string **effective_type)
Definition: mimesniff.c:220
static nserror mimesniff__compute_image(lwc_string *official_type, const uint8_t *data, size_t len, lwc_string **effective_type)
Definition: mimesniff.c:371
#define SIG(t, s, x)
#define RSS_NS
#define RDF_NS
static nserror mimesniff__compute_feed_or_html(const uint8_t *data, size_t len, lwc_string **effective_type)
Definition: mimesniff.c:426
MIME type sniffer interface.
Interface to utility string handling.
lwc_string * media_type
Definition: content-type.h:27
lwc_string ** type
Definition: mimesniff.c:40
size_t len
Definition: mimesniff.c:38
bool safe
Definition: mimesniff.c:39
const uint8_t * sig
Definition: mimesniff.c:37
Interface to a number of general purpose functionality.
#define min(x, y)
Definition: utils.h:46
#define SLEN(x)
Calculate length of constant C string.
Definition: utils.h:84