]>
git.ipfire.org Git - thirdparty/cups.git/blob - scheduler/type.c
2 * "$Id: type.c 13138 2016-03-15 14:59:54Z msweet $"
4 * MIME typing routines for CUPS.
6 * Copyright 2007-2015 by Apple Inc.
7 * Copyright 1997-2006 by Easy Software Products, all rights reserved.
9 * These coded instructions, statements, and computer programs are the
10 * property of Apple Inc. and are protected by Federal copyright
11 * law. Distribution and use rights are outlined in the file "LICENSE.txt"
12 * which should have been included with this file. If this file is
13 * file is missing or damaged, see the license at "http://www.cups.org/".
17 * Include necessary headers...
20 #include <cups/string-private.h>
21 #include <cups/debug-private.h>
30 typedef struct _mime_filebuf_s
/**** File buffer for MIME typing ****/
32 cups_file_t
*fp
; /* File pointer */
33 int offset
, /* Offset in file */
34 length
; /* Length of buffered data */
35 unsigned char buffer
[MIME_MAX_BUFFER
];/* Buffered data */
43 static int mime_compare_types(mime_type_t
*t0
, mime_type_t
*t1
);
44 static int mime_check_rules(const char *filename
, _mime_filebuf_t
*fb
,
46 static int mime_patmatch(const char *s
, const char *pat
);
54 static const char * const debug_ops
[] =
56 "NOP", /* No operation */
57 "AND", /* Logical AND of all children */
58 "OR", /* Logical OR of all children */
59 "MATCH", /* Filename match */
60 "ASCII", /* ASCII characters in range */
61 "PRINTABLE", /* Printable characters (32-255) */
62 "STRING", /* String matches */
63 "CHAR", /* Character/byte matches */
64 "SHORT", /* Short/16-bit word matches */
65 "INT", /* Integer/32-bit word matches */
66 "LOCALE", /* Current locale matches string */
67 "CONTAINS", /* File contains a string */
68 "ISTRING" /* Case-insensitive string matches */
74 * 'mimeAddType()' - Add a MIME type to a database.
77 mime_type_t
* /* O - New (or existing) MIME type */
78 mimeAddType(mime_t
*mime
, /* I - MIME database */
79 const char *super
, /* I - Super-type name */
80 const char *type
) /* I - Type name */
82 mime_type_t
*temp
; /* New MIME type */
83 size_t typelen
; /* Length of type name */
86 DEBUG_printf(("mimeAddType(mime=%p, super=\"%s\", type=\"%s\")", mime
, super
,
90 * Range check input...
93 if (!mime
|| !super
|| !type
)
95 DEBUG_puts("1mimeAddType: Returning NULL (bad arguments).");
100 * See if the type already exists; if so, return the existing type...
103 if ((temp
= mimeType(mime
, super
, type
)) != NULL
)
105 DEBUG_printf(("1mimeAddType: Returning %p (existing).", temp
));
110 * The type doesn't exist; add it...
114 mime
->types
= cupsArrayNew((cups_array_func_t
)mime_compare_types
, NULL
);
118 DEBUG_puts("1mimeAddType: Returning NULL (no types).");
122 typelen
= strlen(type
) + 1;
124 if ((temp
= calloc(1, sizeof(mime_type_t
) - MIME_MAX_TYPE
+ typelen
)) == NULL
)
126 DEBUG_puts("1mimeAddType: Returning NULL (out of memory).");
130 strlcpy(temp
->super
, super
, sizeof(temp
->super
));
131 memcpy(temp
->type
, type
, typelen
);
132 temp
->priority
= 100;
134 cupsArrayAdd(mime
->types
, temp
);
136 DEBUG_printf(("1mimeAddType: Returning %p (new).", temp
));
142 * 'mimeAddTypeRule()' - Add a detection rule for a file type.
145 int /* O - 0 on success, -1 on failure */
146 mimeAddTypeRule(mime_type_t
*mt
, /* I - Type to add to */
147 const char *rule
) /* I - Rule to add */
149 int num_values
, /* Number of values seen */
150 op
, /* Operation code */
151 logic
, /* Logic for next rule */
152 invert
; /* Invert following rule? */
153 char name
[255], /* Name in rule string */
154 value
[3][255], /* Value in rule string */
155 *ptr
, /* Position in name or value */
156 quote
; /* Quote character */
157 int length
[3]; /* Length of each parameter */
158 mime_magic_t
*temp
, /* New rule */
159 *current
; /* Current rule */
162 DEBUG_printf(("mimeAddTypeRule(mt=%p(%s/%s), rule=\"%s\")", mt
,
163 mt
? mt
->super
: "???", mt
? mt
->type
: "???", rule
));
166 * Range check input...
173 * Find the last rule in the top-level of the rules tree.
176 for (current
= mt
->rules
; current
; current
= current
->next
)
181 * Parse the rules string. Most rules are either a file extension or a
182 * comparison function:
185 * function(parameters)
188 logic
= MIME_MAGIC_NOP
;
191 while (*rule
!= '\0')
193 while (isspace(*rule
& 255))
198 DEBUG_puts("1mimeAddTypeRule: New parenthesis group");
199 logic
= MIME_MAGIC_NOP
;
202 else if (*rule
== ')')
204 DEBUG_puts("1mimeAddTypeRule: Close paren...");
205 if (current
== NULL
|| current
->parent
== NULL
)
208 current
= current
->parent
;
210 if (current
->parent
== NULL
)
211 logic
= MIME_MAGIC_OR
;
213 logic
= current
->parent
->op
;
217 else if (*rule
== '+' && current
!= NULL
)
219 if (logic
!= MIME_MAGIC_AND
&&
220 current
!= NULL
&& current
->prev
!= NULL
)
223 * OK, we have more than 1 rule in the current tree level... Make a
224 * new group tree and move the previous rule to it...
227 if ((temp
= calloc(1, sizeof(mime_magic_t
))) == NULL
)
230 temp
->op
= MIME_MAGIC_AND
;
231 temp
->child
= current
;
232 temp
->parent
= current
->parent
;
233 current
->prev
->next
= temp
;
234 temp
->prev
= current
->prev
;
236 current
->prev
= NULL
;
237 current
->parent
= temp
;
239 DEBUG_printf(("1mimeAddTypeRule: Creating new AND group %p.", temp
));
241 else if (current
->parent
)
243 DEBUG_printf(("1mimeAddTypeRule: Setting group %p op to AND.",
245 current
->parent
->op
= MIME_MAGIC_AND
;
248 logic
= MIME_MAGIC_AND
;
251 else if (*rule
== ',')
253 if (logic
!= MIME_MAGIC_OR
&& current
!= NULL
)
256 * OK, we have two possibilities; either this is the top-level rule or
257 * we have a bunch of AND rules at this level.
260 if (current
->parent
== NULL
)
263 * This is the top-level rule; we have to move *all* of the AND rules
264 * down a level, as AND has precedence over OR.
267 if ((temp
= calloc(1, sizeof(mime_magic_t
))) == NULL
)
270 DEBUG_printf(("1mimeAddTypeRule: Creating new AND group %p inside OR "
273 while (current
->prev
!= NULL
)
275 current
->parent
= temp
;
276 current
= current
->prev
;
279 current
->parent
= temp
;
280 temp
->op
= MIME_MAGIC_AND
;
281 temp
->child
= current
;
283 mt
->rules
= current
= temp
;
288 * This isn't the top rule, so go up one level...
291 DEBUG_puts("1mimeAddTypeRule: Going up one level.");
292 current
= current
->parent
;
296 logic
= MIME_MAGIC_OR
;
299 else if (*rule
== '!')
301 DEBUG_puts("1mimeAddTypeRule: NOT");
305 else if (isalnum(*rule
& 255))
308 * Read an extension name or a function...
312 while (isalnum(*rule
& 255) && (size_t)(ptr
- name
) < (sizeof(name
) - 1))
320 * Read function parameters...
325 num_values
< (int)(sizeof(value
) / sizeof(value
[0]));
328 ptr
= value
[num_values
];
330 while ((size_t)(ptr
- value
[num_values
]) < (sizeof(value
[0]) - 1) &&
331 *rule
!= '\0' && *rule
!= ',' && *rule
!= ')')
333 if (isspace(*rule
& 255))
336 * Ignore whitespace...
342 else if (*rule
== '\"' || *rule
== '\'')
345 * Copy quoted strings literally...
350 while (*rule
!= '\0' && *rule
!= quote
&&
351 (size_t)(ptr
- value
[num_values
]) < (sizeof(value
[0]) - 1))
359 else if (*rule
== '<')
363 while (*rule
!= '>' && *rule
!= '\0' &&
364 (size_t)(ptr
- value
[num_values
]) < (sizeof(value
[0]) - 1))
366 if (isxdigit(rule
[0] & 255) && isxdigit(rule
[1] & 255))
369 *ptr
= (char)((*rule
++ - '0') << 4);
371 *ptr
= (char)((tolower(*rule
++) - 'a' + 10) << 4);
374 *ptr
++ |= *rule
++ - '0';
376 *ptr
++ |= tolower(*rule
++) - 'a' + 10;
392 length
[num_values
] = ptr
- value
[num_values
];
409 * Figure out the function...
412 if (!strcmp(name
, "match"))
413 op
= MIME_MAGIC_MATCH
;
414 else if (!strcmp(name
, "ascii"))
415 op
= MIME_MAGIC_ASCII
;
416 else if (!strcmp(name
, "printable"))
417 op
= MIME_MAGIC_PRINTABLE
;
418 else if (!strcmp(name
, "regex"))
419 op
= MIME_MAGIC_REGEX
;
420 else if (!strcmp(name
, "string"))
421 op
= MIME_MAGIC_STRING
;
422 else if (!strcmp(name
, "istring"))
423 op
= MIME_MAGIC_ISTRING
;
424 else if (!strcmp(name
, "char"))
425 op
= MIME_MAGIC_CHAR
;
426 else if (!strcmp(name
, "short"))
427 op
= MIME_MAGIC_SHORT
;
428 else if (!strcmp(name
, "int"))
430 else if (!strcmp(name
, "locale"))
431 op
= MIME_MAGIC_LOCALE
;
432 else if (!strcmp(name
, "contains"))
433 op
= MIME_MAGIC_CONTAINS
;
434 else if (!strcmp(name
, "priority") && num_values
== 1)
436 mt
->priority
= atoi(value
[0]);
445 * This is just a filename match on the extension...
448 snprintf(value
[0], sizeof(value
[0]), "*.%s", name
);
449 length
[0] = (int)strlen(value
[0]);
450 op
= MIME_MAGIC_MATCH
;
454 * Add a rule for this operation.
457 if ((temp
= calloc(1, sizeof(mime_magic_t
))) == NULL
)
460 temp
->invert
= (short)invert
;
463 temp
->parent
= current
->parent
;
464 current
->next
= temp
;
469 temp
->prev
= current
;
471 if (logic
== MIME_MAGIC_NOP
)
474 * Add parenthetical grouping...
477 DEBUG_printf(("1mimeAddTypeRule: Making new OR group %p for "
478 "parenthesis.", temp
));
480 temp
->op
= MIME_MAGIC_OR
;
482 if ((temp
->child
= calloc(1, sizeof(mime_magic_t
))) == NULL
)
485 temp
->child
->parent
= temp
;
486 temp
->child
->invert
= temp
->invert
;
490 logic
= MIME_MAGIC_OR
;
493 DEBUG_printf(("1mimeAddTypeRule: Adding %p: %s, op=MIME_MAGIC_%s(%d), "
494 "logic=MIME_MAGIC_%s, invert=%d.", temp
, name
,
495 debug_ops
[op
], op
, debug_ops
[logic
], invert
));
498 * Fill in data for the rule...
502 temp
->op
= (short)op
;
507 case MIME_MAGIC_MATCH
:
508 if ((size_t)length
[0] > (sizeof(temp
->value
.matchv
) - 1))
510 strlcpy(temp
->value
.matchv
, value
[0], sizeof(temp
->value
.matchv
));
512 case MIME_MAGIC_ASCII
:
513 case MIME_MAGIC_PRINTABLE
:
514 temp
->offset
= strtol(value
[0], NULL
, 0);
515 temp
->length
= strtol(value
[1], NULL
, 0);
516 if (temp
->length
> MIME_MAX_BUFFER
)
517 temp
->length
= MIME_MAX_BUFFER
;
519 case MIME_MAGIC_REGEX
:
520 temp
->offset
= strtol(value
[0], NULL
, 0);
521 temp
->length
= MIME_MAX_BUFFER
;
522 if (regcomp(&(temp
->value
.rev
), value
[1], REG_NOSUB
| REG_EXTENDED
))
525 case MIME_MAGIC_STRING
:
526 case MIME_MAGIC_ISTRING
:
527 temp
->offset
= strtol(value
[0], NULL
, 0);
528 if ((size_t)length
[1] > sizeof(temp
->value
.stringv
))
530 temp
->length
= length
[1];
531 memcpy(temp
->value
.stringv
, value
[1], (size_t)length
[1]);
533 case MIME_MAGIC_CHAR
:
534 temp
->offset
= strtol(value
[0], NULL
, 0);
536 temp
->value
.charv
= (unsigned char)value
[1][0];
538 temp
->value
.charv
= (unsigned char)strtol(value
[1], NULL
, 0);
540 DEBUG_printf(("1mimeAddTypeRule: CHAR(%d,0x%02x)", temp
->offset
,
543 case MIME_MAGIC_SHORT
:
544 temp
->offset
= strtol(value
[0], NULL
, 0);
545 temp
->value
.shortv
= (unsigned short)strtol(value
[1], NULL
, 0);
547 case MIME_MAGIC_INT
:
548 temp
->offset
= strtol(value
[0], NULL
, 0);
549 temp
->value
.intv
= (unsigned)strtol(value
[1], NULL
, 0);
551 case MIME_MAGIC_LOCALE
:
552 if ((size_t)length
[0] > (sizeof(temp
->value
.localev
) - 1))
555 strlcpy(temp
->value
.localev
, value
[0], sizeof(temp
->value
.localev
));
557 case MIME_MAGIC_CONTAINS
:
558 temp
->offset
= strtol(value
[0], NULL
, 0);
559 temp
->region
= strtol(value
[1], NULL
, 0);
560 if ((size_t)length
[2] > sizeof(temp
->value
.stringv
))
562 temp
->length
= length
[2];
563 memcpy(temp
->value
.stringv
, value
[2], (size_t)length
[2]);
576 * 'mimeFileType()' - Determine the type of a file.
579 mime_type_t
* /* O - Type of file */
580 mimeFileType(mime_t
*mime
, /* I - MIME database */
581 const char *pathname
, /* I - Name of file to check on disk */
582 const char *filename
, /* I - Original filename or NULL */
583 int *compression
) /* O - Is the file compressed? */
585 _mime_filebuf_t fb
; /* File buffer */
586 const char *base
; /* Base filename of file */
587 mime_type_t
*type
, /* File type */
588 *best
; /* Best match */
591 DEBUG_printf(("mimeFileType(mime=%p, pathname=\"%s\", filename=\"%s\", "
592 "compression=%p)", mime
, pathname
, filename
, compression
));
595 * Range check input parameters...
598 if (!mime
|| !pathname
)
600 DEBUG_puts("1mimeFileType: Returning NULL.");
605 * Try to open the file...
608 if ((fb
.fp
= cupsFileOpen(pathname
, "r")) == NULL
)
610 DEBUG_printf(("1mimeFileType: Unable to open \"%s\": %s", pathname
,
612 DEBUG_puts("1mimeFileType: Returning NULL.");
617 * Then preload the first MIME_MAX_BUFFER bytes of the file into the file
618 * buffer, returning an error if we can't read anything...
622 fb
.length
= (int)cupsFileRead(fb
.fp
, (char *)fb
.buffer
, MIME_MAX_BUFFER
);
626 DEBUG_printf(("1mimeFileType: Unable to read from \"%s\": %s", pathname
, strerror(errno
)));
627 DEBUG_puts("1mimeFileType: Returning NULL.");
629 cupsFileClose(fb
.fp
);
635 * Figure out the base filename (without directory portion)...
640 if ((base
= strrchr(filename
, '/')) != NULL
)
645 else if ((base
= strrchr(pathname
, '/')) != NULL
)
651 * Then check it against all known types...
654 for (type
= (mime_type_t
*)cupsArrayFirst(mime
->types
), best
= NULL
;
656 type
= (mime_type_t
*)cupsArrayNext(mime
->types
))
657 if (mime_check_rules(base
, &fb
, type
->rules
))
659 if (!best
|| type
->priority
> best
->priority
)
664 * Finally, close the file and return a match (if any)...
669 *compression
= cupsFileCompression(fb
.fp
);
670 DEBUG_printf(("1mimeFileType: *compression=%d", *compression
));
673 cupsFileClose(fb
.fp
);
675 DEBUG_printf(("1mimeFileType: Returning %p(%s/%s).", best
,
676 best
? best
->super
: "???", best
? best
->type
: "???"));
682 * 'mimeType()' - Lookup a file type.
685 mime_type_t
* /* O - Matching file type definition */
686 mimeType(mime_t
*mime
, /* I - MIME database */
687 const char *super
, /* I - Super-type name */
688 const char *type
) /* I - Type name */
690 mime_type_t key
, /* MIME type search key */
691 *mt
; /* Matching type */
694 DEBUG_printf(("mimeType(mime=%p, super=\"%s\", type=\"%s\")", mime
, super
,
698 * Range check input...
701 if (!mime
|| !super
|| !type
)
703 DEBUG_puts("1mimeType: Returning NULL.");
708 * Lookup the type in the array...
711 strlcpy(key
.super
, super
, sizeof(key
.super
));
712 strlcpy(key
.type
, type
, sizeof(key
.type
));
714 mt
= (mime_type_t
*)cupsArrayFind(mime
->types
, &key
);
715 DEBUG_printf(("1mimeType: Returning %p.", mt
));
721 * 'mime_compare_types()' - Compare two MIME super/type names.
724 static int /* O - Result of comparison */
725 mime_compare_types(mime_type_t
*t0
, /* I - First type */
726 mime_type_t
*t1
) /* I - Second type */
728 int i
; /* Result of comparison */
731 if ((i
= _cups_strcasecmp(t0
->super
, t1
->super
)) == 0)
732 i
= _cups_strcasecmp(t0
->type
, t1
->type
);
739 * 'mime_check_rules()' - Check each rule in a list.
742 static int /* O - 1 if match, 0 if no match */
744 const char *filename
, /* I - Filename */
745 _mime_filebuf_t
*fb
, /* I - File to check */
746 mime_magic_t
*rules
) /* I - Rules to check */
748 int n
; /* Looping var */
749 int region
; /* Region to look at */
750 int logic
, /* Logic to apply */
751 result
; /* Result of test */
752 unsigned intv
; /* Integer value */
753 short shortv
; /* Short value */
754 unsigned char *bufptr
; /* Pointer into buffer */
757 DEBUG_printf(("4mime_check_rules(filename=\"%s\", fb=%p, rules=%p)", filename
,
763 if (rules
->parent
== NULL
)
764 logic
= MIME_MAGIC_OR
;
766 logic
= rules
->parent
->op
;
770 while (rules
!= NULL
)
773 * Compute the result of this rule...
778 case MIME_MAGIC_MATCH
:
779 result
= mime_patmatch(filename
, rules
->value
.matchv
);
782 case MIME_MAGIC_ASCII
:
784 * Load the buffer if necessary...
787 if (fb
->offset
< 0 || rules
->offset
< fb
->offset
||
788 (rules
->offset
+ rules
->length
) > (fb
->offset
+ fb
->length
))
791 * Reload file buffer...
794 cupsFileSeek(fb
->fp
, rules
->offset
);
795 fb
->length
= cupsFileRead(fb
->fp
, (char *)fb
->buffer
,
797 fb
->offset
= rules
->offset
;
799 DEBUG_printf(("4mime_check_rules: MIME_MAGIC_ASCII fb->length=%d", fb
->length
));
803 * Test for ASCII printable characters plus standard control chars.
806 if ((rules
->offset
+ rules
->length
) > (fb
->offset
+ fb
->length
))
807 n
= fb
->offset
+ fb
->length
- rules
->offset
;
811 bufptr
= fb
->buffer
+ rules
->offset
- fb
->offset
;
813 if ((*bufptr
>= 32 && *bufptr
<= 126) ||
814 (*bufptr
>= 8 && *bufptr
<= 13) ||
815 *bufptr
== 26 || *bufptr
== 27)
826 case MIME_MAGIC_PRINTABLE
:
828 * Load the buffer if necessary...
831 if (fb
->offset
< 0 || rules
->offset
< fb
->offset
||
832 (rules
->offset
+ rules
->length
) > (fb
->offset
+ fb
->length
))
835 * Reload file buffer...
838 cupsFileSeek(fb
->fp
, rules
->offset
);
839 fb
->length
= cupsFileRead(fb
->fp
, (char *)fb
->buffer
,
841 fb
->offset
= rules
->offset
;
843 DEBUG_printf(("4mime_check_rules: MIME_MAGIC_PRINTABLE fb->length=%d", fb
->length
));
847 * Test for 8-bit printable characters plus standard control chars.
850 if ((rules
->offset
+ rules
->length
) > (fb
->offset
+ fb
->length
))
851 n
= fb
->offset
+ fb
->length
- rules
->offset
;
855 bufptr
= fb
->buffer
+ rules
->offset
- fb
->offset
;
858 if (*bufptr
>= 128 ||
859 (*bufptr
>= 32 && *bufptr
<= 126) ||
860 (*bufptr
>= 8 && *bufptr
<= 13) ||
861 *bufptr
== 26 || *bufptr
== 27)
872 case MIME_MAGIC_REGEX
:
873 DEBUG_printf(("5mime_check_rules: regex(%d, \"%s\")", rules
->offset
,
874 rules
->value
.stringv
));
877 * Load the buffer if necessary...
880 if (fb
->offset
< 0 || rules
->offset
< fb
->offset
||
881 (rules
->offset
+ rules
->length
) > (fb
->offset
+ fb
->length
))
884 * Reload file buffer...
887 cupsFileSeek(fb
->fp
, rules
->offset
);
888 fb
->length
= cupsFileRead(fb
->fp
, (char *)fb
->buffer
,
890 fb
->offset
= rules
->offset
;
892 DEBUG_printf(("4mime_check_rules: MIME_MAGIC_REGEX fb->length=%d", fb
->length
));
894 DEBUG_printf(("5mime_check_rules: loaded %d byte fb->buffer at %d, starts "
895 "with \"%c%c%c%c\".",
896 fb
->length
, fb
->offset
, fb
->buffer
[0], fb
->buffer
[1],
897 fb
->buffer
[2], fb
->buffer
[3]));
901 * Compare the buffer against the string. If the file is too
902 * short then don't compare - it can't match...
907 char temp
[MIME_MAX_BUFFER
+ 1];
908 /* Temporary buffer */
910 memcpy(temp
, fb
->buffer
, (size_t)fb
->length
);
911 temp
[fb
->length
] = '\0';
912 result
= !regexec(&(rules
->value
.rev
), temp
, 0, NULL
, 0);
915 DEBUG_printf(("5mime_check_rules: result=%d", result
));
918 case MIME_MAGIC_STRING
:
919 DEBUG_printf(("5mime_check_rules: string(%d, \"%s\")", rules
->offset
,
920 rules
->value
.stringv
));
923 * Load the buffer if necessary...
926 if (fb
->offset
< 0 || rules
->offset
< fb
->offset
||
927 (rules
->offset
+ rules
->length
) > (fb
->offset
+ fb
->length
))
930 * Reload file buffer...
933 cupsFileSeek(fb
->fp
, rules
->offset
);
934 fb
->length
= cupsFileRead(fb
->fp
, (char *)fb
->buffer
,
936 fb
->offset
= rules
->offset
;
938 DEBUG_printf(("4mime_check_rules: MIME_MAGIC_STRING fb->length=%d", fb
->length
));
940 DEBUG_printf(("5mime_check_rules: loaded %d byte fb->buffer at %d, starts "
941 "with \"%c%c%c%c\".",
942 fb
->length
, fb
->offset
, fb
->buffer
[0], fb
->buffer
[1],
943 fb
->buffer
[2], fb
->buffer
[3]));
947 * Compare the buffer against the string. If the file is too
948 * short then don't compare - it can't match...
951 if ((rules
->offset
+ rules
->length
) > (fb
->offset
+ fb
->length
))
954 result
= !memcmp(fb
->buffer
+ rules
->offset
- fb
->offset
, rules
->value
.stringv
, (size_t)rules
->length
);
955 DEBUG_printf(("5mime_check_rules: result=%d", result
));
958 case MIME_MAGIC_ISTRING
:
960 * Load the buffer if necessary...
963 if (fb
->offset
< 0 || rules
->offset
< fb
->offset
||
964 (rules
->offset
+ rules
->length
) > (fb
->offset
+ fb
->length
))
967 * Reload file buffer...
970 cupsFileSeek(fb
->fp
, rules
->offset
);
971 fb
->length
= cupsFileRead(fb
->fp
, (char *)fb
->buffer
,
973 fb
->offset
= rules
->offset
;
975 DEBUG_printf(("4mime_check_rules: MIME_MAGIC_ISTRING fb->length=%d", fb
->length
));
979 * Compare the buffer against the string. If the file is too
980 * short then don't compare - it can't match...
983 if ((rules
->offset
+ rules
->length
) > (fb
->offset
+ fb
->length
))
986 result
= !_cups_strncasecmp((char *)fb
->buffer
+ rules
->offset
- fb
->offset
, rules
->value
.stringv
, (size_t)rules
->length
);
989 case MIME_MAGIC_CHAR
:
991 * Load the buffer if necessary...
994 if (fb
->offset
< 0 || rules
->offset
< fb
->offset
)
997 * Reload file buffer...
1000 cupsFileSeek(fb
->fp
, rules
->offset
);
1001 fb
->length
= cupsFileRead(fb
->fp
, (char *)fb
->buffer
,
1002 sizeof(fb
->buffer
));
1003 fb
->offset
= rules
->offset
;
1005 DEBUG_printf(("4mime_check_rules: MIME_MAGIC_CHAR fb->length=%d", fb
->length
));
1009 * Compare the character values; if the file is too short, it
1016 result
= (fb
->buffer
[rules
->offset
- fb
->offset
] ==
1017 rules
->value
.charv
);
1020 case MIME_MAGIC_SHORT
:
1022 * Load the buffer if necessary...
1025 if (fb
->offset
< 0 || rules
->offset
< fb
->offset
||
1026 (rules
->offset
+ 2) > (fb
->offset
+ fb
->length
))
1029 * Reload file buffer...
1032 cupsFileSeek(fb
->fp
, rules
->offset
);
1033 fb
->length
= cupsFileRead(fb
->fp
, (char *)fb
->buffer
,
1034 sizeof(fb
->buffer
));
1035 fb
->offset
= rules
->offset
;
1037 DEBUG_printf(("4mime_check_rules: MIME_MAGIC_SHORT fb->length=%d", fb
->length
));
1041 * Compare the short values; if the file is too short, it
1049 bufptr
= fb
->buffer
+ rules
->offset
- fb
->offset
;
1050 shortv
= (short)((bufptr
[0] << 8) | bufptr
[1]);
1051 result
= (shortv
== rules
->value
.shortv
);
1055 case MIME_MAGIC_INT
:
1057 * Load the buffer if necessary...
1060 if (fb
->offset
< 0 || rules
->offset
< fb
->offset
||
1061 (rules
->offset
+ 4) > (fb
->offset
+ fb
->length
))
1064 * Reload file buffer...
1067 cupsFileSeek(fb
->fp
, rules
->offset
);
1068 fb
->length
= cupsFileRead(fb
->fp
, (char *)fb
->buffer
,
1069 sizeof(fb
->buffer
));
1070 fb
->offset
= rules
->offset
;
1072 DEBUG_printf(("4mime_check_rules: MIME_MAGIC_INT fb->length=%d", fb
->length
));
1076 * Compare the int values; if the file is too short, it
1084 bufptr
= fb
->buffer
+ rules
->offset
- fb
->offset
;
1085 intv
= (unsigned)((((((bufptr
[0] << 8) | bufptr
[1]) << 8) | bufptr
[2]) << 8) | bufptr
[3]);
1086 result
= (intv
== rules
->value
.intv
);
1090 case MIME_MAGIC_LOCALE
:
1091 #if defined(WIN32) || defined(__EMX__) || defined(__APPLE__)
1092 result
= !strcmp(rules
->value
.localev
, setlocale(LC_ALL
, ""));
1094 result
= !strcmp(rules
->value
.localev
, setlocale(LC_MESSAGES
, ""));
1095 #endif /* __APPLE__ */
1098 case MIME_MAGIC_CONTAINS
:
1100 * Load the buffer if necessary...
1103 if (fb
->offset
< 0 || rules
->offset
< fb
->offset
||
1104 (rules
->offset
+ rules
->region
) > (fb
->offset
+ fb
->length
))
1107 * Reload file buffer...
1110 cupsFileSeek(fb
->fp
, rules
->offset
);
1111 fb
->length
= cupsFileRead(fb
->fp
, (char *)fb
->buffer
,
1112 sizeof(fb
->buffer
));
1113 fb
->offset
= rules
->offset
;
1115 DEBUG_printf(("4mime_check_rules: MIME_MAGIC_CONTAINS fb->length=%d", fb
->length
));
1119 * Compare the buffer against the string. If the file is too
1120 * short then don't compare - it can't match...
1123 if ((rules
->offset
+ rules
->length
) > (fb
->offset
+ fb
->length
))
1127 if (fb
->length
> rules
->region
)
1128 region
= rules
->region
- rules
->length
;
1130 region
= fb
->length
- rules
->length
;
1132 for (n
= 0; n
< region
; n
++)
1133 if ((result
= (memcmp(fb
->buffer
+ rules
->offset
- fb
->offset
+ n
, rules
->value
.stringv
, (size_t)rules
->length
) == 0)) != 0)
1139 if (rules
->child
!= NULL
)
1140 result
= mime_check_rules(filename
, fb
, rules
->child
);
1147 * If the logic is inverted, invert the result...
1154 * OK, now if the current logic is OR and this result is true, the this
1155 * rule set is true. If the current logic is AND and this result is false,
1156 * the the rule set is false...
1159 DEBUG_printf(("5mime_check_rules: result of test %p (MIME_MAGIC_%s) is %d",
1160 rules
, debug_ops
[rules
->op
], result
));
1162 if ((result
&& logic
== MIME_MAGIC_OR
) ||
1163 (!result
&& logic
== MIME_MAGIC_AND
))
1167 * Otherwise the jury is still out on this one, so move to the next rule.
1170 rules
= rules
->next
;
1178 * 'mime_patmatch()' - Pattern matching.
1181 static int /* O - 1 if match, 0 if no match */
1182 mime_patmatch(const char *s
, /* I - String to match against */
1183 const char *pat
) /* I - Pattern to match against */
1186 * Range check the input...
1189 if (s
== NULL
|| pat
== NULL
)
1193 * Loop through the pattern and match strings, and stop if we come to a
1194 * point where the strings don't match or we find a complete match.
1197 while (*s
!= '\0' && *pat
!= '\0')
1202 * Wildcard - 0 or more characters...
1207 return (1); /* Last pattern char is *, so everything matches... */
1210 * Test all remaining combinations until we get to the end of the string.
1215 if (mime_patmatch(s
, pat
))
1221 else if (*pat
== '?')
1224 * Wildcard - 1 character...
1231 else if (*pat
== '[')
1234 * Match a character from the input set [chars]...
1238 while (*pat
!= ']' && *pat
!= '\0')
1244 if (*pat
== ']' || *pat
== '\0')
1247 while (*pat
!= ']' && *pat
!= '\0')
1255 else if (*pat
== '\\')
1258 * Handle quoted characters...
1265 * Stop if the pattern and string don't match...
1273 * Done parsing the pattern and string; return 1 if the last character
1274 * matches and 0 otherwise...
1277 return (*s
== *pat
);
1282 * End of "$Id: type.c 13138 2016-03-15 14:59:54Z msweet $".