]>
git.ipfire.org Git - thirdparty/cups.git/blob - scheduler/type.c
4 * MIME typing routines for CUPS.
6 * Copyright 2007-2013 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 * mimeAddType() - Add a MIME type to a database.
18 * mimeAddTypeRule() - Add a detection rule for a file type.
19 * mimeFileType() - Determine the type of a file.
20 * mimeType() - Lookup a file type.
21 * mime_compare_types() - Compare two MIME super/type names.
22 * mime_check_rules() - Check each rule in a list.
23 * mime_patmatch() - Pattern matching.
27 * Include necessary headers...
30 #include <cups/string-private.h>
31 #include <cups/debug-private.h>
40 typedef struct _mime_filebuf_s
/**** File buffer for MIME typing ****/
42 cups_file_t
*fp
; /* File pointer */
43 int offset
, /* Offset in file */
44 length
; /* Length of buffered data */
45 unsigned char buffer
[MIME_MAX_BUFFER
];/* Buffered data */
53 static int mime_compare_types(mime_type_t
*t0
, mime_type_t
*t1
);
54 static int mime_check_rules(const char *filename
, _mime_filebuf_t
*fb
,
56 static int mime_patmatch(const char *s
, const char *pat
);
64 static const char * const debug_ops
[] =
66 "NOP", /* No operation */
67 "AND", /* Logical AND of all children */
68 "OR", /* Logical OR of all children */
69 "MATCH", /* Filename match */
70 "ASCII", /* ASCII characters in range */
71 "PRINTABLE", /* Printable characters (32-255) */
72 "STRING", /* String matches */
73 "CHAR", /* Character/byte matches */
74 "SHORT", /* Short/16-bit word matches */
75 "INT", /* Integer/32-bit word matches */
76 "LOCALE", /* Current locale matches string */
77 "CONTAINS", /* File contains a string */
78 "ISTRING" /* Case-insensitive string matches */
84 * 'mimeAddType()' - Add a MIME type to a database.
87 mime_type_t
* /* O - New (or existing) MIME type */
88 mimeAddType(mime_t
*mime
, /* I - MIME database */
89 const char *super
, /* I - Super-type name */
90 const char *type
) /* I - Type name */
92 mime_type_t
*temp
; /* New MIME type */
93 size_t typelen
; /* Length of type name */
96 DEBUG_printf(("mimeAddType(mime=%p, super=\"%s\", type=\"%s\")", mime
, super
,
100 * Range check input...
103 if (!mime
|| !super
|| !type
)
105 DEBUG_puts("1mimeAddType: Returning NULL (bad arguments).");
110 * See if the type already exists; if so, return the existing type...
113 if ((temp
= mimeType(mime
, super
, type
)) != NULL
)
115 DEBUG_printf(("1mimeAddType: Returning %p (existing).", temp
));
120 * The type doesn't exist; add it...
124 mime
->types
= cupsArrayNew((cups_array_func_t
)mime_compare_types
, NULL
);
128 DEBUG_puts("1mimeAddType: Returning NULL (no types).");
132 typelen
= strlen(type
) + 1;
134 if ((temp
= calloc(1, sizeof(mime_type_t
) - MIME_MAX_TYPE
+ typelen
)) == NULL
)
136 DEBUG_puts("1mimeAddType: Returning NULL (out of memory).");
140 strlcpy(temp
->super
, super
, sizeof(temp
->super
));
141 memcpy(temp
->type
, type
, typelen
);
142 temp
->priority
= 100;
144 cupsArrayAdd(mime
->types
, temp
);
146 DEBUG_printf(("1mimeAddType: Returning %p (new).", temp
));
152 * 'mimeAddTypeRule()' - Add a detection rule for a file type.
155 int /* O - 0 on success, -1 on failure */
156 mimeAddTypeRule(mime_type_t
*mt
, /* I - Type to add to */
157 const char *rule
) /* I - Rule to add */
159 int num_values
, /* Number of values seen */
160 op
, /* Operation code */
161 logic
, /* Logic for next rule */
162 invert
; /* Invert following rule? */
163 char name
[255], /* Name in rule string */
164 value
[3][255], /* Value in rule string */
165 *ptr
, /* Position in name or value */
166 quote
; /* Quote character */
167 int length
[3]; /* Length of each parameter */
168 mime_magic_t
*temp
, /* New rule */
169 *current
; /* Current rule */
172 DEBUG_printf(("mimeAddTypeRule(mt=%p(%s/%s), rule=\"%s\")", mt
,
173 mt
? mt
->super
: "???", mt
? mt
->type
: "???", rule
));
176 * Range check input...
183 * Find the last rule in the top-level of the rules tree.
186 for (current
= mt
->rules
; current
; current
= current
->next
)
191 * Parse the rules string. Most rules are either a file extension or a
192 * comparison function:
195 * function(parameters)
198 logic
= MIME_MAGIC_NOP
;
201 while (*rule
!= '\0')
203 while (isspace(*rule
& 255))
208 DEBUG_puts("1mimeAddTypeRule: New parenthesis group");
209 logic
= MIME_MAGIC_NOP
;
212 else if (*rule
== ')')
214 DEBUG_puts("1mimeAddTypeRule: Close paren...");
215 if (current
== NULL
|| current
->parent
== NULL
)
218 current
= current
->parent
;
220 if (current
->parent
== NULL
)
221 logic
= MIME_MAGIC_OR
;
223 logic
= current
->parent
->op
;
227 else if (*rule
== '+' && current
!= NULL
)
229 if (logic
!= MIME_MAGIC_AND
&&
230 current
!= NULL
&& current
->prev
!= NULL
)
233 * OK, we have more than 1 rule in the current tree level... Make a
234 * new group tree and move the previous rule to it...
237 if ((temp
= calloc(1, sizeof(mime_magic_t
))) == NULL
)
240 temp
->op
= MIME_MAGIC_AND
;
241 temp
->child
= current
;
242 temp
->parent
= current
->parent
;
243 current
->prev
->next
= temp
;
244 temp
->prev
= current
->prev
;
246 current
->prev
= NULL
;
247 current
->parent
= temp
;
249 DEBUG_printf(("1mimeAddTypeRule: Creating new AND group %p.", temp
));
251 else if (current
->parent
)
253 DEBUG_printf(("1mimeAddTypeRule: Setting group %p op to AND.",
255 current
->parent
->op
= MIME_MAGIC_AND
;
258 logic
= MIME_MAGIC_AND
;
261 else if (*rule
== ',')
263 if (logic
!= MIME_MAGIC_OR
&& current
!= NULL
)
266 * OK, we have two possibilities; either this is the top-level rule or
267 * we have a bunch of AND rules at this level.
270 if (current
->parent
== NULL
)
273 * This is the top-level rule; we have to move *all* of the AND rules
274 * down a level, as AND has precedence over OR.
277 if ((temp
= calloc(1, sizeof(mime_magic_t
))) == NULL
)
280 DEBUG_printf(("1mimeAddTypeRule: Creating new AND group %p inside OR "
283 while (current
->prev
!= NULL
)
285 current
->parent
= temp
;
286 current
= current
->prev
;
289 current
->parent
= temp
;
290 temp
->op
= MIME_MAGIC_AND
;
291 temp
->child
= current
;
293 mt
->rules
= current
= temp
;
298 * This isn't the top rule, so go up one level...
301 DEBUG_puts("1mimeAddTypeRule: Going up one level.");
302 current
= current
->parent
;
306 logic
= MIME_MAGIC_OR
;
309 else if (*rule
== '!')
311 DEBUG_puts("1mimeAddTypeRule: NOT");
315 else if (isalnum(*rule
& 255))
318 * Read an extension name or a function...
322 while (isalnum(*rule
& 255) && (ptr
- name
) < (sizeof(name
) - 1))
330 * Read function parameters...
335 num_values
< (sizeof(value
) / sizeof(value
[0]));
338 ptr
= value
[num_values
];
340 while ((ptr
- value
[num_values
]) < (sizeof(value
[0]) - 1) &&
341 *rule
!= '\0' && *rule
!= ',' && *rule
!= ')')
343 if (isspace(*rule
& 255))
346 * Ignore whitespace...
352 else if (*rule
== '\"' || *rule
== '\'')
355 * Copy quoted strings literally...
360 while (*rule
!= '\0' && *rule
!= quote
&&
361 (ptr
- value
[num_values
]) < (sizeof(value
[0]) - 1))
369 else if (*rule
== '<')
373 while (*rule
!= '>' && *rule
!= '\0' &&
374 (ptr
- value
[num_values
]) < (sizeof(value
[0]) - 1))
376 if (isxdigit(rule
[0] & 255) && isxdigit(rule
[1] & 255))
379 *ptr
= (*rule
++ - '0') << 4;
381 *ptr
= (tolower(*rule
++) - 'a' + 10) << 4;
384 *ptr
++ |= *rule
++ - '0';
386 *ptr
++ |= tolower(*rule
++) - 'a' + 10;
402 length
[num_values
] = ptr
- value
[num_values
];
419 * Figure out the function...
422 if (!strcmp(name
, "match"))
423 op
= MIME_MAGIC_MATCH
;
424 else if (!strcmp(name
, "ascii"))
425 op
= MIME_MAGIC_ASCII
;
426 else if (!strcmp(name
, "printable"))
427 op
= MIME_MAGIC_PRINTABLE
;
428 else if (!strcmp(name
, "regex"))
429 op
= MIME_MAGIC_REGEX
;
430 else if (!strcmp(name
, "string"))
431 op
= MIME_MAGIC_STRING
;
432 else if (!strcmp(name
, "istring"))
433 op
= MIME_MAGIC_ISTRING
;
434 else if (!strcmp(name
, "char"))
435 op
= MIME_MAGIC_CHAR
;
436 else if (!strcmp(name
, "short"))
437 op
= MIME_MAGIC_SHORT
;
438 else if (!strcmp(name
, "int"))
440 else if (!strcmp(name
, "locale"))
441 op
= MIME_MAGIC_LOCALE
;
442 else if (!strcmp(name
, "contains"))
443 op
= MIME_MAGIC_CONTAINS
;
444 else if (!strcmp(name
, "priority") && num_values
== 1)
446 mt
->priority
= atoi(value
[0]);
455 * This is just a filename match on the extension...
458 snprintf(value
[0], sizeof(value
[0]), "*.%s", name
);
459 length
[0] = strlen(value
[0]);
460 op
= MIME_MAGIC_MATCH
;
464 * Add a rule for this operation.
467 if ((temp
= calloc(1, sizeof(mime_magic_t
))) == NULL
)
470 temp
->invert
= invert
;
473 temp
->parent
= current
->parent
;
474 current
->next
= temp
;
479 temp
->prev
= current
;
481 if (logic
== MIME_MAGIC_NOP
)
484 * Add parenthetical grouping...
487 DEBUG_printf(("1mimeAddTypeRule: Making new OR group %p for "
488 "parenthesis.", temp
));
490 temp
->op
= MIME_MAGIC_OR
;
492 if ((temp
->child
= calloc(1, sizeof(mime_magic_t
))) == NULL
)
495 temp
->child
->parent
= temp
;
496 temp
->child
->invert
= temp
->invert
;
500 logic
= MIME_MAGIC_OR
;
503 DEBUG_printf(("1mimeAddTypeRule: Adding %p: %s, op=MIME_MAGIC_%s(%d), "
504 "logic=MIME_MAGIC_%s, invert=%d.", temp
, name
,
505 debug_ops
[op
], op
, debug_ops
[logic
], invert
));
508 * Fill in data for the rule...
517 case MIME_MAGIC_MATCH
:
518 if (length
[0] > (sizeof(temp
->value
.matchv
) - 1))
520 strlcpy(temp
->value
.matchv
, value
[0], sizeof(temp
->value
.matchv
));
522 case MIME_MAGIC_ASCII
:
523 case MIME_MAGIC_PRINTABLE
:
524 temp
->offset
= strtol(value
[0], NULL
, 0);
525 temp
->length
= strtol(value
[1], NULL
, 0);
526 if (temp
->length
> MIME_MAX_BUFFER
)
527 temp
->length
= MIME_MAX_BUFFER
;
529 case MIME_MAGIC_REGEX
:
530 temp
->offset
= strtol(value
[0], NULL
, 0);
531 temp
->length
= MIME_MAX_BUFFER
;
532 if (regcomp(&(temp
->value
.rev
), value
[1], REG_NOSUB
| REG_EXTENDED
))
535 case MIME_MAGIC_STRING
:
536 case MIME_MAGIC_ISTRING
:
537 temp
->offset
= strtol(value
[0], NULL
, 0);
538 if (length
[1] > sizeof(temp
->value
.stringv
))
540 temp
->length
= length
[1];
541 memcpy(temp
->value
.stringv
, value
[1], length
[1]);
543 case MIME_MAGIC_CHAR
:
544 temp
->offset
= strtol(value
[0], NULL
, 0);
546 temp
->value
.charv
= value
[1][0];
548 temp
->value
.charv
= (unsigned char)strtol(value
[1], NULL
, 0);
550 DEBUG_printf(("1mimeAddTypeRule: CHAR(%d,0x%02x)", temp
->offset
,
553 case MIME_MAGIC_SHORT
:
554 temp
->offset
= strtol(value
[0], NULL
, 0);
555 temp
->value
.shortv
= (unsigned short)strtol(value
[1], NULL
, 0);
557 case MIME_MAGIC_INT
:
558 temp
->offset
= strtol(value
[0], NULL
, 0);
559 temp
->value
.intv
= (unsigned)strtol(value
[1], NULL
, 0);
561 case MIME_MAGIC_LOCALE
:
562 if (length
[0] > (sizeof(temp
->value
.localev
) - 1))
565 strlcpy(temp
->value
.localev
, value
[0], sizeof(temp
->value
.localev
));
567 case MIME_MAGIC_CONTAINS
:
568 temp
->offset
= strtol(value
[0], NULL
, 0);
569 temp
->region
= strtol(value
[1], NULL
, 0);
570 if (length
[2] > sizeof(temp
->value
.stringv
))
572 temp
->length
= length
[2];
573 memcpy(temp
->value
.stringv
, value
[2], length
[2]);
586 * 'mimeFileType()' - Determine the type of a file.
589 mime_type_t
* /* O - Type of file */
590 mimeFileType(mime_t
*mime
, /* I - MIME database */
591 const char *pathname
, /* I - Name of file to check on disk */
592 const char *filename
, /* I - Original filename or NULL */
593 int *compression
) /* O - Is the file compressed? */
595 _mime_filebuf_t fb
; /* File buffer */
596 const char *base
; /* Base filename of file */
597 mime_type_t
*type
, /* File type */
598 *best
; /* Best match */
601 DEBUG_printf(("mimeFileType(mime=%p, pathname=\"%s\", filename=\"%s\", "
602 "compression=%p)", mime
, pathname
, filename
, compression
));
605 * Range check input parameters...
608 if (!mime
|| !pathname
)
610 DEBUG_puts("1mimeFileType: Returning NULL.");
615 * Try to open the file...
618 if ((fb
.fp
= cupsFileOpen(pathname
, "r")) == NULL
)
620 DEBUG_printf(("1mimeFileType: Unable to open \"%s\": %s", pathname
,
622 DEBUG_puts("1mimeFileType: Returning NULL.");
630 * Figure out the base filename (without directory portion)...
635 if ((base
= strrchr(filename
, '/')) != NULL
)
640 else if ((base
= strrchr(pathname
, '/')) != NULL
)
646 * Then check it against all known types...
649 for (type
= (mime_type_t
*)cupsArrayFirst(mime
->types
), best
= NULL
;
651 type
= (mime_type_t
*)cupsArrayNext(mime
->types
))
652 if (mime_check_rules(base
, &fb
, type
->rules
))
654 if (!best
|| type
->priority
> best
->priority
)
659 * Finally, close the file and return a match (if any)...
664 *compression
= cupsFileCompression(fb
.fp
);
665 DEBUG_printf(("1mimeFileType: *compression=%d", *compression
));
668 cupsFileClose(fb
.fp
);
670 DEBUG_printf(("1mimeFileType: Returning %p(%s/%s).", best
,
671 best
? best
->super
: "???", best
? best
->type
: "???"));
677 * 'mimeType()' - Lookup a file type.
680 mime_type_t
* /* O - Matching file type definition */
681 mimeType(mime_t
*mime
, /* I - MIME database */
682 const char *super
, /* I - Super-type name */
683 const char *type
) /* I - Type name */
685 mime_type_t key
, /* MIME type search key */
686 *mt
; /* Matching type */
689 DEBUG_printf(("mimeType(mime=%p, super=\"%s\", type=\"%s\")", mime
, super
,
693 * Range check input...
696 if (!mime
|| !super
|| !type
)
698 DEBUG_puts("1mimeType: Returning NULL.");
703 * Lookup the type in the array...
706 strlcpy(key
.super
, super
, sizeof(key
.super
));
707 strlcpy(key
.type
, type
, sizeof(key
.type
));
709 mt
= (mime_type_t
*)cupsArrayFind(mime
->types
, &key
);
710 DEBUG_printf(("1mimeType: Returning %p.", mt
));
716 * 'mime_compare_types()' - Compare two MIME super/type names.
719 static int /* O - Result of comparison */
720 mime_compare_types(mime_type_t
*t0
, /* I - First type */
721 mime_type_t
*t1
) /* I - Second type */
723 int i
; /* Result of comparison */
726 if ((i
= _cups_strcasecmp(t0
->super
, t1
->super
)) == 0)
727 i
= _cups_strcasecmp(t0
->type
, t1
->type
);
734 * 'mime_check_rules()' - Check each rule in a list.
737 static int /* O - 1 if match, 0 if no match */
739 const char *filename
, /* I - Filename */
740 _mime_filebuf_t
*fb
, /* I - File to check */
741 mime_magic_t
*rules
) /* I - Rules to check */
743 int n
; /* Looping var */
744 int region
; /* Region to look at */
745 int logic
, /* Logic to apply */
746 result
, /* Result of test */
747 intv
; /* Integer value */
748 short shortv
; /* Short value */
749 unsigned char *bufptr
; /* Pointer into buffer */
752 DEBUG_printf(("4mime_check_rules(filename=\"%s\", fb=%p, rules=%p)", filename
,
758 if (rules
->parent
== NULL
)
759 logic
= MIME_MAGIC_OR
;
761 logic
= rules
->parent
->op
;
765 while (rules
!= NULL
)
768 * Compute the result of this rule...
773 case MIME_MAGIC_MATCH
:
774 result
= mime_patmatch(filename
, rules
->value
.matchv
);
777 case MIME_MAGIC_ASCII
:
779 * Load the buffer if necessary...
782 if (fb
->offset
< 0 || rules
->offset
< fb
->offset
||
783 (rules
->offset
+ rules
->length
) > (fb
->offset
+ fb
->length
))
786 * Reload file buffer...
789 cupsFileSeek(fb
->fp
, rules
->offset
);
790 fb
->length
= cupsFileRead(fb
->fp
, (char *)fb
->buffer
,
792 fb
->offset
= rules
->offset
;
796 * Test for ASCII printable characters plus standard control chars.
799 if ((rules
->offset
+ rules
->length
) > (fb
->offset
+ fb
->length
))
800 n
= fb
->offset
+ fb
->length
- rules
->offset
;
804 bufptr
= fb
->buffer
+ rules
->offset
- fb
->offset
;
806 if ((*bufptr
>= 32 && *bufptr
<= 126) ||
807 (*bufptr
>= 8 && *bufptr
<= 13) ||
808 *bufptr
== 26 || *bufptr
== 27)
819 case MIME_MAGIC_PRINTABLE
:
821 * Load the buffer if necessary...
824 if (fb
->offset
< 0 || rules
->offset
< fb
->offset
||
825 (rules
->offset
+ rules
->length
) > (fb
->offset
+ fb
->length
))
828 * Reload file buffer...
831 cupsFileSeek(fb
->fp
, rules
->offset
);
832 fb
->length
= cupsFileRead(fb
->fp
, (char *)fb
->buffer
,
834 fb
->offset
= rules
->offset
;
838 * Test for 8-bit printable characters plus standard control chars.
841 if ((rules
->offset
+ rules
->length
) > (fb
->offset
+ fb
->length
))
842 n
= fb
->offset
+ fb
->length
- rules
->offset
;
846 bufptr
= fb
->buffer
+ rules
->offset
- fb
->offset
;
849 if (*bufptr
>= 128 ||
850 (*bufptr
>= 32 && *bufptr
<= 126) ||
851 (*bufptr
>= 8 && *bufptr
<= 13) ||
852 *bufptr
== 26 || *bufptr
== 27)
863 case MIME_MAGIC_REGEX
:
864 DEBUG_printf(("5mime_check_rules: regex(%d, \"%s\")", rules
->offset
,
865 rules
->value
.stringv
));
868 * Load the buffer if necessary...
871 if (fb
->offset
< 0 || rules
->offset
< fb
->offset
||
872 (rules
->offset
+ rules
->length
) > (fb
->offset
+ fb
->length
))
875 * Reload file buffer...
878 cupsFileSeek(fb
->fp
, rules
->offset
);
879 fb
->length
= cupsFileRead(fb
->fp
, (char *)fb
->buffer
,
881 fb
->offset
= rules
->offset
;
883 DEBUG_printf(("5mime_check_rules: loaded %d byte fb->buffer at %d, starts "
884 "with \"%c%c%c%c\".",
885 fb
->length
, fb
->offset
, fb
->buffer
[0], fb
->buffer
[1],
886 fb
->buffer
[2], fb
->buffer
[3]));
890 * Compare the buffer against the string. If the file is too
891 * short then don't compare - it can't match...
896 char temp
[MIME_MAX_BUFFER
+ 1];
897 /* Temporary buffer */
899 memcpy(temp
, fb
->buffer
, fb
->length
);
900 temp
[fb
->length
] = '\0';
901 result
= !regexec(&(rules
->value
.rev
), temp
, 0, NULL
, 0);
904 DEBUG_printf(("5mime_check_rules: result=%d", result
));
907 case MIME_MAGIC_STRING
:
908 DEBUG_printf(("5mime_check_rules: string(%d, \"%s\")", rules
->offset
,
909 rules
->value
.stringv
));
912 * Load the buffer if necessary...
915 if (fb
->offset
< 0 || rules
->offset
< fb
->offset
||
916 (rules
->offset
+ rules
->length
) > (fb
->offset
+ fb
->length
))
919 * Reload file buffer...
922 cupsFileSeek(fb
->fp
, rules
->offset
);
923 fb
->length
= cupsFileRead(fb
->fp
, (char *)fb
->buffer
,
925 fb
->offset
= rules
->offset
;
927 DEBUG_printf(("5mime_check_rules: loaded %d byte fb->buffer at %d, starts "
928 "with \"%c%c%c%c\".",
929 fb
->length
, fb
->offset
, fb
->buffer
[0], fb
->buffer
[1],
930 fb
->buffer
[2], fb
->buffer
[3]));
934 * Compare the buffer against the string. If the file is too
935 * short then don't compare - it can't match...
938 if ((rules
->offset
+ rules
->length
) > (fb
->offset
+ fb
->length
))
941 result
= (memcmp(fb
->buffer
+ rules
->offset
- fb
->offset
,
942 rules
->value
.stringv
, rules
->length
) == 0);
943 DEBUG_printf(("5mime_check_rules: result=%d", result
));
946 case MIME_MAGIC_ISTRING
:
948 * Load the buffer if necessary...
951 if (fb
->offset
< 0 || rules
->offset
< fb
->offset
||
952 (rules
->offset
+ rules
->length
) > (fb
->offset
+ fb
->length
))
955 * Reload file buffer...
958 cupsFileSeek(fb
->fp
, rules
->offset
);
959 fb
->length
= cupsFileRead(fb
->fp
, (char *)fb
->buffer
,
961 fb
->offset
= rules
->offset
;
965 * Compare the buffer against the string. If the file is too
966 * short then don't compare - it can't match...
969 if ((rules
->offset
+ rules
->length
) > (fb
->offset
+ fb
->length
))
972 result
= (_cups_strncasecmp((char *)fb
->buffer
+ rules
->offset
-
974 rules
->value
.stringv
, rules
->length
) == 0);
977 case MIME_MAGIC_CHAR
:
979 * Load the buffer if necessary...
982 if (fb
->offset
< 0 || rules
->offset
< fb
->offset
)
985 * Reload file buffer...
988 cupsFileSeek(fb
->fp
, rules
->offset
);
989 fb
->length
= cupsFileRead(fb
->fp
, (char *)fb
->buffer
,
991 fb
->offset
= rules
->offset
;
995 * Compare the character values; if the file is too short, it
1002 result
= (fb
->buffer
[rules
->offset
- fb
->offset
] ==
1003 rules
->value
.charv
);
1006 case MIME_MAGIC_SHORT
:
1008 * Load the buffer if necessary...
1011 if (fb
->offset
< 0 || rules
->offset
< fb
->offset
||
1012 (rules
->offset
+ 2) > (fb
->offset
+ fb
->length
))
1015 * Reload file buffer...
1018 cupsFileSeek(fb
->fp
, rules
->offset
);
1019 fb
->length
= cupsFileRead(fb
->fp
, (char *)fb
->buffer
,
1020 sizeof(fb
->buffer
));
1021 fb
->offset
= rules
->offset
;
1025 * Compare the short values; if the file is too short, it
1033 bufptr
= fb
->buffer
+ rules
->offset
- fb
->offset
;
1034 shortv
= (bufptr
[0] << 8) | bufptr
[1];
1035 result
= (shortv
== rules
->value
.shortv
);
1039 case MIME_MAGIC_INT
:
1041 * Load the buffer if necessary...
1044 if (fb
->offset
< 0 || rules
->offset
< fb
->offset
||
1045 (rules
->offset
+ 4) > (fb
->offset
+ fb
->length
))
1048 * Reload file buffer...
1051 cupsFileSeek(fb
->fp
, rules
->offset
);
1052 fb
->length
= cupsFileRead(fb
->fp
, (char *)fb
->buffer
,
1053 sizeof(fb
->buffer
));
1054 fb
->offset
= rules
->offset
;
1058 * Compare the int values; if the file is too short, it
1066 bufptr
= fb
->buffer
+ rules
->offset
- fb
->offset
;
1067 intv
= (((((bufptr
[0] << 8) | bufptr
[1]) << 8) |
1068 bufptr
[2]) << 8) | bufptr
[3];
1069 result
= (intv
== rules
->value
.intv
);
1073 case MIME_MAGIC_LOCALE
:
1074 #if defined(WIN32) || defined(__EMX__) || defined(__APPLE__)
1075 result
= (strcmp(rules
->value
.localev
,
1076 setlocale(LC_ALL
, "")) == 0);
1078 result
= (strcmp(rules
->value
.localev
,
1079 setlocale(LC_MESSAGES
, "")) == 0);
1080 #endif /* __APPLE__ */
1083 case MIME_MAGIC_CONTAINS
:
1085 * Load the buffer if necessary...
1088 if (fb
->offset
< 0 || rules
->offset
< fb
->offset
||
1089 (rules
->offset
+ rules
->region
) > (fb
->offset
+ fb
->length
))
1092 * Reload file buffer...
1095 cupsFileSeek(fb
->fp
, rules
->offset
);
1096 fb
->length
= cupsFileRead(fb
->fp
, (char *)fb
->buffer
,
1097 sizeof(fb
->buffer
));
1098 fb
->offset
= rules
->offset
;
1102 * Compare the buffer against the string. If the file is too
1103 * short then don't compare - it can't match...
1106 if ((rules
->offset
+ rules
->length
) > (fb
->offset
+ fb
->length
))
1110 if (fb
->length
> rules
->region
)
1111 region
= rules
->region
- rules
->length
;
1113 region
= fb
->length
- rules
->length
;
1115 for (n
= 0; n
< region
; n
++)
1116 if ((result
= (memcmp(fb
->buffer
+ rules
->offset
- fb
->offset
+ n
,
1117 rules
->value
.stringv
,
1118 rules
->length
) == 0)) != 0)
1124 if (rules
->child
!= NULL
)
1125 result
= mime_check_rules(filename
, fb
, rules
->child
);
1132 * If the logic is inverted, invert the result...
1139 * OK, now if the current logic is OR and this result is true, the this
1140 * rule set is true. If the current logic is AND and this result is false,
1141 * the the rule set is false...
1144 DEBUG_printf(("5mime_check_rules: result of test %p (MIME_MAGIC_%s) is %d",
1145 rules
, debug_ops
[rules
->op
], result
));
1147 if ((result
&& logic
== MIME_MAGIC_OR
) ||
1148 (!result
&& logic
== MIME_MAGIC_AND
))
1152 * Otherwise the jury is still out on this one, so move to the next rule.
1155 rules
= rules
->next
;
1163 * 'mime_patmatch()' - Pattern matching.
1166 static int /* O - 1 if match, 0 if no match */
1167 mime_patmatch(const char *s
, /* I - String to match against */
1168 const char *pat
) /* I - Pattern to match against */
1171 * Range check the input...
1174 if (s
== NULL
|| pat
== NULL
)
1178 * Loop through the pattern and match strings, and stop if we come to a
1179 * point where the strings don't match or we find a complete match.
1182 while (*s
!= '\0' && *pat
!= '\0')
1187 * Wildcard - 0 or more characters...
1192 return (1); /* Last pattern char is *, so everything matches... */
1195 * Test all remaining combinations until we get to the end of the string.
1200 if (mime_patmatch(s
, pat
))
1206 else if (*pat
== '?')
1209 * Wildcard - 1 character...
1216 else if (*pat
== '[')
1219 * Match a character from the input set [chars]...
1223 while (*pat
!= ']' && *pat
!= '\0')
1229 if (*pat
== ']' || *pat
== '\0')
1232 while (*pat
!= ']' && *pat
!= '\0')
1240 else if (*pat
== '\\')
1243 * Handle quoted characters...
1250 * Stop if the pattern and string don't match...
1258 * Done parsing the pattern and string; return 1 if the last character
1259 * matches and 0 otherwise...
1262 return (*s
== *pat
);