]>
git.ipfire.org Git - thirdparty/cups.git/blob - scheduler/mime.c
2 * "$Id: mime.c 10996 2013-05-29 11:51:34Z msweet $"
4 * MIME database file routines for CUPS.
6 * Copyright 2007-2012 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 * mimeDelete() - Delete (free) a MIME database.
18 * mimeDeleteFilter() - Delete a filter from the MIME database.
19 * mimeDeleteType() - Delete a type from the MIME database.
20 * _mimeError() - Show an error message.
21 * mimeFirstFilter() - Get the first filter in the MIME database.
22 * mimeFirstType() - Get the first type in the MIME database.
23 * mimeLoad() - Create a new MIME database from disk.
24 * mimeLoadFilters() - Load filter definitions from disk.
25 * mimeLoadTypes() - Load type definitions from disk.
26 * mimeNew() - Create a new, empty MIME database.
27 * mimeNextFilter() - Get the next filter in the MIME database.
28 * mimeNextType() - Get the next type in the MIME database.
29 * mimeNumFilters() - Get the number of filters in a MIME database.
30 * mimeNumTypes() - Get the number of types in a MIME database.
31 * mimeSetErrorCallback() - Set the callback for error messages.
32 * mime_add_fcache() - Add a filter to the filter cache.
33 * mime_compare_fcache() - Compare two filter cache entries.
34 * mime_delete_fcache() - Free all memory used by the filter cache.
35 * mime_delete_rules() - Free all memory for the given rule tree.
36 * mime_load_convs() - Load a xyz.convs file.
37 * mime_load_types() - Load a xyz.types file.
41 * Include necessary headers...
44 #include <cups/string-private.h>
45 #include <cups/debug-private.h>
47 #include "mime-private.h"
54 typedef struct _mime_fcache_s
/**** Filter cache structure ****/
56 char *name
, /* Filter name */
57 *path
; /* Full path to filter if available */
65 static const char *mime_add_fcache(cups_array_t
*filtercache
, const char *name
,
66 const char *filterpath
);
67 static int mime_compare_fcache(_mime_fcache_t
*a
, _mime_fcache_t
*b
);
68 static void mime_delete_fcache(cups_array_t
*filtercache
);
69 static void mime_delete_rules(mime_magic_t
*rules
);
70 static void mime_load_convs(mime_t
*mime
, const char *filename
,
71 const char *filterpath
,
72 cups_array_t
*filtercache
);
73 static void mime_load_types(mime_t
*mime
, const char *filename
);
77 * 'mimeDelete()' - Delete (free) a MIME database.
81 mimeDelete(mime_t
*mime
) /* I - MIME database */
83 mime_type_t
*type
; /* Current type */
84 mime_filter_t
*filter
; /* Current filter */
87 DEBUG_printf(("mimeDelete(mime=%p)", mime
));
93 * Loop through filters and free them...
96 for (filter
= (mime_filter_t
*)cupsArrayFirst(mime
->filters
);
98 filter
= (mime_filter_t
*)cupsArrayNext(mime
->filters
))
99 mimeDeleteFilter(mime
, filter
);
102 * Loop through the file types and delete any rules...
105 for (type
= (mime_type_t
*)cupsArrayFirst(mime
->types
);
107 type
= (mime_type_t
*)cupsArrayNext(mime
->types
))
108 mimeDeleteType(mime
, type
);
111 * Free the types and filters arrays, and then the MIME database structure.
114 cupsArrayDelete(mime
->types
);
115 cupsArrayDelete(mime
->filters
);
116 cupsArrayDelete(mime
->srcs
);
122 * 'mimeDeleteFilter()' - Delete a filter from the MIME database.
126 mimeDeleteFilter(mime_t
*mime
, /* I - MIME database */
127 mime_filter_t
*filter
) /* I - Filter */
129 DEBUG_printf(("mimeDeleteFilter(mime=%p, filter=%p(%s/%s->%s/%s, cost=%d, "
130 "maxsize=" CUPS_LLFMT
"))", mime
, filter
,
131 filter
? filter
->src
->super
: "???",
132 filter
? filter
->src
->type
: "???",
133 filter
? filter
->dst
->super
: "???",
134 filter
? filter
->dst
->super
: "???",
135 filter
? filter
->cost
: -1,
136 filter
? CUPS_LLCAST filter
->maxsize
: CUPS_LLCAST
-1));
138 if (!mime
|| !filter
)
142 if (!cupsArrayFind(mime
->filters
, filter
))
143 DEBUG_puts("1mimeDeleteFilter: Filter not in MIME database.");
146 cupsArrayRemove(mime
->filters
, filter
);
150 * Deleting a filter invalidates the source lookup cache used by
156 DEBUG_puts("1mimeDeleteFilter: Deleting source lookup cache.");
157 cupsArrayDelete(mime
->srcs
);
164 * 'mimeDeleteType()' - Delete a type from the MIME database.
168 mimeDeleteType(mime_t
*mime
, /* I - MIME database */
169 mime_type_t
*mt
) /* I - Type */
171 DEBUG_printf(("mimeDeleteType(mime=%p, mt=%p(%s/%s))", mime
, mt
,
172 mt
? mt
->super
: "???", mt
? mt
->type
: "???"));
178 if (!cupsArrayFind(mime
->types
, mt
))
179 DEBUG_puts("1mimeDeleteFilter: Type not in MIME database.");
182 cupsArrayRemove(mime
->types
, mt
);
184 mime_delete_rules(mt
->rules
);
190 * '_mimeError()' - Show an error message.
194 _mimeError(mime_t
*mime
, /* I - MIME database */
195 const char *message
, /* I - Printf-style message string */
196 ...) /* I - Additional arguments as needed */
198 va_list ap
; /* Argument pointer */
199 char buffer
[8192]; /* Message buffer */
204 va_start(ap
, message
);
205 vsnprintf(buffer
, sizeof(buffer
), message
, ap
);
208 (*mime
->error_cb
)(mime
->error_ctx
, buffer
);
214 * 'mimeFirstFilter()' - Get the first filter in the MIME database.
217 mime_filter_t
* /* O - Filter or NULL */
218 mimeFirstFilter(mime_t
*mime
) /* I - MIME database */
220 DEBUG_printf(("6mimeFirstFilter(mime=%p)", mime
));
224 DEBUG_puts("7mimeFirstFilter: Returning NULL.");
229 mime_filter_t
*first
= (mime_filter_t
*)cupsArrayFirst(mime
->filters
);
232 DEBUG_printf(("7mimeFirstFilter: Returning %p.", first
));
239 * 'mimeFirstType()' - Get the first type in the MIME database.
242 mime_type_t
* /* O - Type or NULL */
243 mimeFirstType(mime_t
*mime
) /* I - MIME database */
245 DEBUG_printf(("6mimeFirstType(mime=%p)", mime
));
249 DEBUG_puts("7mimeFirstType: Returning NULL.");
254 mime_type_t
*first
= (mime_type_t
*)cupsArrayFirst(mime
->types
);
257 DEBUG_printf(("7mimeFirstType: Returning %p.", first
));
264 * 'mimeLoad()' - Create a new MIME database from disk.
266 * This function uses @link mimeLoadFilters@ and @link mimeLoadTypes@ to
267 * create a MIME database from a single directory.
270 mime_t
* /* O - New MIME database */
271 mimeLoad(const char *pathname
, /* I - Directory to load */
272 const char *filterpath
) /* I - Directory to load */
274 mime_t
*mime
; /* New MIME database */
276 DEBUG_printf(("mimeLoad(pathname=\"%s\", filterpath=\"%s\")", pathname
,
279 mime
= mimeLoadFilters(mimeLoadTypes(NULL
, pathname
), pathname
, filterpath
);
280 DEBUG_printf(("1mimeLoad: Returning %p.", mime
));
287 * 'mimeLoadFilters()' - Load filter definitions from disk.
289 * This function loads all of the .convs files from the specified directory.
290 * Use @link mimeLoadTypes@ to load all types before you load the filters.
293 mime_t
* /* O - MIME database */
294 mimeLoadFilters(mime_t
*mime
, /* I - MIME database */
295 const char *pathname
, /* I - Directory to load from */
296 const char *filterpath
) /* I - Default filter program directory */
298 cups_dir_t
*dir
; /* Directory */
299 cups_dentry_t
*dent
; /* Directory entry */
300 char filename
[1024]; /* Full filename of .convs file */
301 cups_array_t
*filtercache
; /* Filter cache */
304 DEBUG_printf(("mimeLoadFilters(mime=%p, pathname=\"%s\", filterpath=\"%s\")",
305 mime
, pathname
, filterpath
));
308 * Range check input...
311 if (!mime
|| !pathname
|| !filterpath
)
313 DEBUG_puts("1mimeLoadFilters: Bad arguments.");
318 * Then open the directory specified by pathname...
321 if ((dir
= cupsDirOpen(pathname
)) == NULL
)
323 DEBUG_printf(("1mimeLoadFilters: Unable to open \"%s\": %s", pathname
,
325 _mimeError(mime
, "Unable to open \"%s\": %s", pathname
, strerror(errno
));
330 * Read all the .convs files...
333 filtercache
= cupsArrayNew((cups_array_func_t
)mime_compare_fcache
, NULL
);
335 while ((dent
= cupsDirRead(dir
)) != NULL
)
337 if (strlen(dent
->filename
) > 6 &&
338 !strcmp(dent
->filename
+ strlen(dent
->filename
) - 6, ".convs"))
341 * Load a mime.convs file...
344 snprintf(filename
, sizeof(filename
), "%s/%s", pathname
, dent
->filename
);
345 DEBUG_printf(("1mimeLoadFilters: Loading \"%s\".", filename
));
346 mime_load_convs(mime
, filename
, filterpath
, filtercache
);
350 mime_delete_fcache(filtercache
);
359 * 'mimeLoadTypes()' - Load type definitions from disk.
361 * This function loads all of the .types files from the specified directory.
362 * Use @link mimeLoadFilters@ to load all filters after you load the types.
365 mime_t
* /* O - MIME database */
366 mimeLoadTypes(mime_t
*mime
, /* I - MIME database or @code NULL@ to create a new one */
367 const char *pathname
) /* I - Directory to load from */
369 cups_dir_t
*dir
; /* Directory */
370 cups_dentry_t
*dent
; /* Directory entry */
371 char filename
[1024]; /* Full filename of .types file */
374 DEBUG_printf(("mimeLoadTypes(mime=%p, pathname=\"%s\")", mime
, pathname
));
377 * First open the directory specified by pathname...
380 if ((dir
= cupsDirOpen(pathname
)) == NULL
)
382 DEBUG_printf(("1mimeLoadTypes: Unable to open \"%s\": %s", pathname
,
384 DEBUG_printf(("1mimeLoadTypes: Returning %p.", mime
));
385 _mimeError(mime
, "Unable to open \"%s\": %s", pathname
, strerror(errno
));
390 * If "mime" is NULL, make a new, empty database...
399 DEBUG_puts("1mimeLoadTypes: Returning NULL.");
404 * Read all the .types files...
407 while ((dent
= cupsDirRead(dir
)) != NULL
)
409 if (strlen(dent
->filename
) > 6 &&
410 !strcmp(dent
->filename
+ strlen(dent
->filename
) - 6, ".types"))
413 * Load a mime.types file...
416 snprintf(filename
, sizeof(filename
), "%s/%s", pathname
, dent
->filename
);
417 DEBUG_printf(("1mimeLoadTypes: Loading \"%s\".", filename
));
418 mime_load_types(mime
, filename
);
424 DEBUG_printf(("1mimeLoadTypes: Returning %p.", mime
));
431 * 'mimeNew()' - Create a new, empty MIME database.
434 mime_t
* /* O - MIME database */
437 return ((mime_t
*)calloc(1, sizeof(mime_t
)));
442 * 'mimeNextFilter()' - Get the next filter in the MIME database.
445 mime_filter_t
* /* O - Filter or NULL */
446 mimeNextFilter(mime_t
*mime
) /* I - MIME database */
448 DEBUG_printf(("6mimeNextFilter(mime=%p)", mime
));
452 DEBUG_puts("7mimeNextFilter: Returning NULL.");
457 mime_filter_t
*next
= (mime_filter_t
*)cupsArrayNext(mime
->filters
);
460 DEBUG_printf(("7mimeNextFilter: Returning %p.", next
));
467 * 'mimeNextType()' - Get the next type in the MIME database.
470 mime_type_t
* /* O - Type or NULL */
471 mimeNextType(mime_t
*mime
) /* I - MIME database */
473 DEBUG_printf(("6mimeNextType(mime=%p)", mime
));
477 DEBUG_puts("7mimeNextType: Returning NULL.");
482 mime_type_t
*next
= (mime_type_t
*)cupsArrayNext(mime
->types
);
485 DEBUG_printf(("7mimeNextType: Returning %p.", next
));
492 * 'mimeNumFilters()' - Get the number of filters in a MIME database.
496 mimeNumFilters(mime_t
*mime
) /* I - MIME database */
498 DEBUG_printf(("mimeNumFilters(mime=%p)", mime
));
502 DEBUG_puts("1mimeNumFilters: Returning 0.");
507 DEBUG_printf(("1mimeNumFilters: Returning %d.",
508 cupsArrayCount(mime
->filters
)));
509 return (cupsArrayCount(mime
->filters
));
515 * 'mimeNumTypes()' - Get the number of types in a MIME database.
519 mimeNumTypes(mime_t
*mime
) /* I - MIME database */
521 DEBUG_printf(("mimeNumTypes(mime=%p)", mime
));
525 DEBUG_puts("1mimeNumTypes: Returning 0.");
530 DEBUG_printf(("1mimeNumTypes: Returning %d.",
531 cupsArrayCount(mime
->types
)));
532 return (cupsArrayCount(mime
->types
));
538 * 'mimeSetErrorCallback()' - Set the callback for error messages.
542 mimeSetErrorCallback(
543 mime_t
*mime
, /* I - MIME database */
544 mime_error_cb_t cb
, /* I - Callback function */
545 void *ctx
) /* I - Context pointer for callback */
550 mime
->error_ctx
= ctx
;
556 * 'mime_add_fcache()' - Add a filter to the filter cache.
559 static const char * /* O - Full path to filter or NULL */
561 cups_array_t
*filtercache
, /* I - Filter cache */
562 const char *name
, /* I - Filter name */
563 const char *filterpath
) /* I - Filter path */
565 _mime_fcache_t key
, /* Search key */
566 *temp
; /* New filter cache */
567 char path
[1024]; /* Full path to filter */
570 DEBUG_printf(("2mime_add_fcache(filtercache=%p, name=\"%s\", "
571 "filterpath=\"%s\")", filtercache
, name
, filterpath
));
573 key
.name
= (char *)name
;
574 if ((temp
= (_mime_fcache_t
*)cupsArrayFind(filtercache
, &key
)) != NULL
)
576 DEBUG_printf(("3mime_add_fcache: Returning \"%s\".", temp
->path
));
580 if ((temp
= calloc(1, sizeof(_mime_fcache_t
))) == NULL
)
582 DEBUG_puts("3mime_add_fcache: Returning NULL.");
586 temp
->name
= strdup(name
);
588 if (cupsFileFind(name
, filterpath
, 1, path
, sizeof(path
)))
589 temp
->path
= strdup(path
);
591 cupsArrayAdd(filtercache
, temp
);
593 DEBUG_printf(("3mime_add_fcache: Returning \"%s\".", temp
->path
));
599 * 'mime_compare_fcache()' - Compare two filter cache entries.
602 static int /* O - Result of comparison */
603 mime_compare_fcache(_mime_fcache_t
*a
, /* I - First entry */
604 _mime_fcache_t
*b
) /* I - Second entry */
606 return (strcmp(a
->name
, b
->name
));
611 * 'mime_delete_fcache()' - Free all memory used by the filter cache.
616 cups_array_t
*filtercache
) /* I - Filter cache */
618 _mime_fcache_t
*current
; /* Current cache entry */
621 DEBUG_printf(("2mime_delete_fcache(filtercache=%p)", filtercache
));
623 for (current
= (_mime_fcache_t
*)cupsArrayFirst(filtercache
);
625 current
= (_mime_fcache_t
*)cupsArrayNext(filtercache
))
635 cupsArrayDelete(filtercache
);
640 * 'mime_delete_rules()' - Free all memory for the given rule tree.
644 mime_delete_rules(mime_magic_t
*rules
) /* I - Rules to free */
646 mime_magic_t
*next
; /* Next rule to free */
649 DEBUG_printf(("2mime_delete_rules(rules=%p)", rules
));
652 * Free the rules list, descending recursively to free any child rules.
655 while (rules
!= NULL
)
659 if (rules
->child
!= NULL
)
660 mime_delete_rules(rules
->child
);
669 * 'mime_load_convs()' - Load a xyz.convs file.
674 mime_t
*mime
, /* I - MIME database */
675 const char *filename
, /* I - Convs file to load */
676 const char *filterpath
, /* I - Path for filters */
677 cups_array_t
*filtercache
) /* I - Filter program cache */
679 cups_file_t
*fp
; /* Convs file */
680 char line
[1024], /* Input line from file */
681 *lineptr
, /* Current position in line */
682 super
[MIME_MAX_SUPER
], /* Super-type name */
683 type
[MIME_MAX_TYPE
], /* Type name */
684 *temp
, /* Temporary pointer */
685 *filter
; /* Filter program */
686 mime_type_t
*temptype
, /* MIME type looping var */
687 *dsttype
; /* Destination MIME type */
688 int cost
; /* Cost of filter */
691 DEBUG_printf(("2mime_load_convs(mime=%p, filename=\"%s\", filterpath=\"%s\", "
692 "filtercache=%p)", mime
, filename
, filterpath
, filtercache
));
695 * First try to open the file...
698 if ((fp
= cupsFileOpen(filename
, "r")) == NULL
)
700 DEBUG_printf(("3mime_load_convs: Unable to open \"%s\": %s", filename
,
702 _mimeError(mime
, "Unable to open \"%s\": %s", filename
, strerror(errno
));
707 * Then read each line from the file, skipping any comments in the file...
710 while (cupsFileGets(fp
, line
, sizeof(line
)) != NULL
)
713 * Skip blank lines and lines starting with a #...
716 if (!line
[0] || line
[0] == '#')
720 * Strip trailing whitespace...
723 for (lineptr
= line
+ strlen(line
) - 1;
724 lineptr
>= line
&& isspace(*lineptr
& 255);
729 * Extract the destination super-type and type names from the middle of
734 while (*lineptr
!= ' ' && *lineptr
!= '\t' && *lineptr
!= '\0')
737 while (*lineptr
== ' ' || *lineptr
== '\t')
742 while (*lineptr
!= '/' && *lineptr
!= '\n' && *lineptr
!= '\0' &&
743 (temp
- super
+ 1) < MIME_MAX_SUPER
)
744 *temp
++ = tolower(*lineptr
++ & 255);
754 while (*lineptr
!= ' ' && *lineptr
!= '\t' && *lineptr
!= '\n' &&
755 *lineptr
!= '\0' && (temp
- type
+ 1) < MIME_MAX_TYPE
)
756 *temp
++ = tolower(*lineptr
++ & 255);
760 if (*lineptr
== '\0' || *lineptr
== '\n')
763 if ((dsttype
= mimeType(mime
, super
, type
)) == NULL
)
765 DEBUG_printf(("3mime_load_convs: Destination type %s/%s not found.",
771 * Then get the cost and filter program...
774 while (*lineptr
== ' ' || *lineptr
== '\t')
777 if (*lineptr
< '0' || *lineptr
> '9')
780 cost
= atoi(lineptr
);
782 while (*lineptr
!= ' ' && *lineptr
!= '\t' && *lineptr
!= '\0')
784 while (*lineptr
== ' ' || *lineptr
== '\t')
787 if (*lineptr
== '\0' || *lineptr
== '\n')
792 if (strcmp(filter
, "-"))
795 * Verify that the filter exists and is executable...
798 if (!mime_add_fcache(filtercache
, filter
, filterpath
))
800 DEBUG_printf(("mime_load_convs: Filter %s not found in %s.", filter
,
802 _mimeError(mime
, "Filter \"%s\" not found.", filter
);
808 * Finally, get the source super-type and type names from the beginning of
809 * the line. We do it here so we can support wildcards...
815 while (*lineptr
!= '/' && *lineptr
!= '\n' && *lineptr
!= '\0' &&
816 (temp
- super
+ 1) < MIME_MAX_SUPER
)
817 *temp
++ = tolower(*lineptr
++ & 255);
827 while (*lineptr
!= ' ' && *lineptr
!= '\t' && *lineptr
!= '\n' &&
828 *lineptr
!= '\0' && (temp
- type
+ 1) < MIME_MAX_TYPE
)
829 *temp
++ = tolower(*lineptr
++ & 255);
833 if (!strcmp(super
, "*") && !strcmp(type
, "*"))
836 * Force * / * to be "application/octet-stream"...
839 strlcpy(super
, "application", sizeof(super
));
840 strlcpy(type
, "octet-stream", sizeof(type
));
844 * Add the filter to the MIME database, supporting wildcards as needed...
847 for (temptype
= (mime_type_t
*)cupsArrayFirst(mime
->types
);
849 temptype
= (mime_type_t
*)cupsArrayNext(mime
->types
))
850 if ((super
[0] == '*' || !strcmp(temptype
->super
, super
)) &&
851 (type
[0] == '*' || !strcmp(temptype
->type
, type
)))
852 mimeAddFilter(mime
, temptype
, dsttype
, cost
, filter
);
860 * 'mime_load_types()' - Load a xyz.types file.
864 mime_load_types(mime_t
*mime
, /* I - MIME database */
865 const char *filename
) /* I - Types file to load */
867 cups_file_t
*fp
; /* Types file */
868 int linelen
; /* Length of line */
869 char line
[32768], /* Input line from file */
870 *lineptr
, /* Current position in line */
871 super
[MIME_MAX_SUPER
], /* Super-type name */
872 type
[MIME_MAX_TYPE
], /* Type name */
873 *temp
; /* Temporary pointer */
874 mime_type_t
*typeptr
; /* New MIME type */
877 DEBUG_printf(("2mime_load_types(mime=%p, filename=\"%s\")", mime
, filename
));
880 * First try to open the file...
883 if ((fp
= cupsFileOpen(filename
, "r")) == NULL
)
885 DEBUG_printf(("3mime_load_types: Unable to open \"%s\": %s", filename
,
887 _mimeError(mime
, "Unable to open \"%s\": %s", filename
, strerror(errno
));
892 * Then read each line from the file, skipping any comments in the file...
895 while (cupsFileGets(fp
, line
, sizeof(line
)) != NULL
)
898 * Skip blank lines and lines starting with a #...
901 if (!line
[0] || line
[0] == '#')
905 * While the last character in the line is a backslash, continue on to the
906 * next line (and the next, etc.)
909 linelen
= strlen(line
);
911 while (line
[linelen
- 1] == '\\')
915 if (cupsFileGets(fp
, line
+ linelen
, sizeof(line
) - linelen
) == NULL
)
916 line
[linelen
] = '\0';
918 linelen
+= strlen(line
+ linelen
);
922 * Extract the super-type and type names from the beginning of the line.
928 while (*lineptr
!= '/' && *lineptr
!= '\n' && *lineptr
!= '\0' &&
929 (temp
- super
+ 1) < MIME_MAX_SUPER
)
930 *temp
++ = tolower(*lineptr
++ & 255);
940 while (*lineptr
!= ' ' && *lineptr
!= '\t' && *lineptr
!= '\n' &&
941 *lineptr
!= '\0' && (temp
- type
+ 1) < MIME_MAX_TYPE
)
942 *temp
++ = tolower(*lineptr
++ & 255);
947 * Add the type and rules to the MIME database...
950 typeptr
= mimeAddType(mime
, super
, type
);
951 mimeAddTypeRule(typeptr
, lineptr
);
959 * End of "$Id: mime.c 10996 2013-05-29 11:51:34Z msweet $".