]>
git.ipfire.org Git - thirdparty/cups.git/blob - scheduler/mime.c
4 * MIME database file routines for CUPS.
6 * Copyright 2007-2014 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>
23 #include "mime-private.h"
30 typedef struct _mime_fcache_s
/**** Filter cache structure ****/
32 char *name
, /* Filter name */
33 *path
; /* Full path to filter if available */
41 static const char *mime_add_fcache(cups_array_t
*filtercache
, const char *name
,
42 const char *filterpath
);
43 static int mime_compare_fcache(_mime_fcache_t
*a
, _mime_fcache_t
*b
);
44 static void mime_delete_fcache(cups_array_t
*filtercache
);
45 static void mime_delete_rules(mime_magic_t
*rules
);
46 static void mime_load_convs(mime_t
*mime
, const char *filename
,
47 const char *filterpath
,
48 cups_array_t
*filtercache
);
49 static void mime_load_types(mime_t
*mime
, const char *filename
);
53 * 'mimeDelete()' - Delete (free) a MIME database.
57 mimeDelete(mime_t
*mime
) /* I - MIME database */
59 mime_type_t
*type
; /* Current type */
60 mime_filter_t
*filter
; /* Current filter */
63 DEBUG_printf(("mimeDelete(mime=%p)", mime
));
69 * Loop through filters and free them...
72 for (filter
= (mime_filter_t
*)cupsArrayFirst(mime
->filters
);
74 filter
= (mime_filter_t
*)cupsArrayNext(mime
->filters
))
75 mimeDeleteFilter(mime
, filter
);
78 * Loop through the file types and delete any rules...
81 for (type
= (mime_type_t
*)cupsArrayFirst(mime
->types
);
83 type
= (mime_type_t
*)cupsArrayNext(mime
->types
))
84 mimeDeleteType(mime
, type
);
87 * Free the types and filters arrays, and then the MIME database structure.
90 cupsArrayDelete(mime
->types
);
91 cupsArrayDelete(mime
->filters
);
92 cupsArrayDelete(mime
->srcs
);
98 * 'mimeDeleteFilter()' - Delete a filter from the MIME database.
102 mimeDeleteFilter(mime_t
*mime
, /* I - MIME database */
103 mime_filter_t
*filter
) /* I - Filter */
105 DEBUG_printf(("mimeDeleteFilter(mime=%p, filter=%p(%s/%s->%s/%s, cost=%d, "
106 "maxsize=" CUPS_LLFMT
"))", mime
, filter
,
107 filter
? filter
->src
->super
: "???",
108 filter
? filter
->src
->type
: "???",
109 filter
? filter
->dst
->super
: "???",
110 filter
? filter
->dst
->super
: "???",
111 filter
? filter
->cost
: -1,
112 filter
? CUPS_LLCAST filter
->maxsize
: CUPS_LLCAST
-1));
114 if (!mime
|| !filter
)
118 if (!cupsArrayFind(mime
->filters
, filter
))
119 DEBUG_puts("1mimeDeleteFilter: Filter not in MIME database.");
122 cupsArrayRemove(mime
->filters
, filter
);
126 * Deleting a filter invalidates the source lookup cache used by
132 DEBUG_puts("1mimeDeleteFilter: Deleting source lookup cache.");
133 cupsArrayDelete(mime
->srcs
);
140 * 'mimeDeleteType()' - Delete a type from the MIME database.
144 mimeDeleteType(mime_t
*mime
, /* I - MIME database */
145 mime_type_t
*mt
) /* I - Type */
147 DEBUG_printf(("mimeDeleteType(mime=%p, mt=%p(%s/%s))", mime
, mt
,
148 mt
? mt
->super
: "???", mt
? mt
->type
: "???"));
154 if (!cupsArrayFind(mime
->types
, mt
))
155 DEBUG_puts("1mimeDeleteFilter: Type not in MIME database.");
158 cupsArrayRemove(mime
->types
, mt
);
160 mime_delete_rules(mt
->rules
);
166 * '_mimeError()' - Show an error message.
170 _mimeError(mime_t
*mime
, /* I - MIME database */
171 const char *message
, /* I - Printf-style message string */
172 ...) /* I - Additional arguments as needed */
174 va_list ap
; /* Argument pointer */
175 char buffer
[8192]; /* Message buffer */
180 va_start(ap
, message
);
181 vsnprintf(buffer
, sizeof(buffer
), message
, ap
);
184 (*mime
->error_cb
)(mime
->error_ctx
, buffer
);
190 * 'mimeFirstFilter()' - Get the first filter in the MIME database.
193 mime_filter_t
* /* O - Filter or NULL */
194 mimeFirstFilter(mime_t
*mime
) /* I - MIME database */
196 DEBUG_printf(("6mimeFirstFilter(mime=%p)", mime
));
200 DEBUG_puts("7mimeFirstFilter: Returning NULL.");
205 mime_filter_t
*first
= (mime_filter_t
*)cupsArrayFirst(mime
->filters
);
208 DEBUG_printf(("7mimeFirstFilter: Returning %p.", first
));
215 * 'mimeFirstType()' - Get the first type in the MIME database.
218 mime_type_t
* /* O - Type or NULL */
219 mimeFirstType(mime_t
*mime
) /* I - MIME database */
221 DEBUG_printf(("6mimeFirstType(mime=%p)", mime
));
225 DEBUG_puts("7mimeFirstType: Returning NULL.");
230 mime_type_t
*first
= (mime_type_t
*)cupsArrayFirst(mime
->types
);
233 DEBUG_printf(("7mimeFirstType: Returning %p.", first
));
240 * 'mimeLoad()' - Create a new MIME database from disk.
242 * This function uses @link mimeLoadFilters@ and @link mimeLoadTypes@ to
243 * create a MIME database from a single directory.
246 mime_t
* /* O - New MIME database */
247 mimeLoad(const char *pathname
, /* I - Directory to load */
248 const char *filterpath
) /* I - Directory to load */
250 mime_t
*mime
; /* New MIME database */
252 DEBUG_printf(("mimeLoad(pathname=\"%s\", filterpath=\"%s\")", pathname
,
255 mime
= mimeLoadFilters(mimeLoadTypes(NULL
, pathname
), pathname
, filterpath
);
256 DEBUG_printf(("1mimeLoad: Returning %p.", mime
));
263 * 'mimeLoadFilters()' - Load filter definitions from disk.
265 * This function loads all of the .convs files from the specified directory.
266 * Use @link mimeLoadTypes@ to load all types before you load the filters.
269 mime_t
* /* O - MIME database */
270 mimeLoadFilters(mime_t
*mime
, /* I - MIME database */
271 const char *pathname
, /* I - Directory to load from */
272 const char *filterpath
) /* I - Default filter program directory */
274 cups_dir_t
*dir
; /* Directory */
275 cups_dentry_t
*dent
; /* Directory entry */
276 char filename
[1024]; /* Full filename of .convs file */
277 cups_array_t
*filtercache
; /* Filter cache */
280 DEBUG_printf(("mimeLoadFilters(mime=%p, pathname=\"%s\", filterpath=\"%s\")",
281 mime
, pathname
, filterpath
));
284 * Range check input...
287 if (!mime
|| !pathname
|| !filterpath
)
289 DEBUG_puts("1mimeLoadFilters: Bad arguments.");
294 * Then open the directory specified by pathname...
297 if ((dir
= cupsDirOpen(pathname
)) == NULL
)
299 DEBUG_printf(("1mimeLoadFilters: Unable to open \"%s\": %s", pathname
,
301 _mimeError(mime
, "Unable to open \"%s\": %s", pathname
, strerror(errno
));
306 * Read all the .convs files...
309 filtercache
= cupsArrayNew((cups_array_func_t
)mime_compare_fcache
, NULL
);
311 while ((dent
= cupsDirRead(dir
)) != NULL
)
313 if (strlen(dent
->filename
) > 6 &&
314 !strcmp(dent
->filename
+ strlen(dent
->filename
) - 6, ".convs"))
317 * Load a mime.convs file...
320 snprintf(filename
, sizeof(filename
), "%s/%s", pathname
, dent
->filename
);
321 DEBUG_printf(("1mimeLoadFilters: Loading \"%s\".", filename
));
322 mime_load_convs(mime
, filename
, filterpath
, filtercache
);
326 mime_delete_fcache(filtercache
);
335 * 'mimeLoadTypes()' - Load type definitions from disk.
337 * This function loads all of the .types files from the specified directory.
338 * Use @link mimeLoadFilters@ to load all filters after you load the types.
341 mime_t
* /* O - MIME database */
342 mimeLoadTypes(mime_t
*mime
, /* I - MIME database or @code NULL@ to create a new one */
343 const char *pathname
) /* I - Directory to load from */
345 cups_dir_t
*dir
; /* Directory */
346 cups_dentry_t
*dent
; /* Directory entry */
347 char filename
[1024]; /* Full filename of .types file */
350 DEBUG_printf(("mimeLoadTypes(mime=%p, pathname=\"%s\")", mime
, pathname
));
353 * First open the directory specified by pathname...
356 if ((dir
= cupsDirOpen(pathname
)) == NULL
)
358 DEBUG_printf(("1mimeLoadTypes: Unable to open \"%s\": %s", pathname
,
360 DEBUG_printf(("1mimeLoadTypes: Returning %p.", mime
));
361 _mimeError(mime
, "Unable to open \"%s\": %s", pathname
, strerror(errno
));
366 * If "mime" is NULL, make a new, empty database...
375 DEBUG_puts("1mimeLoadTypes: Returning NULL.");
380 * Read all the .types files...
383 while ((dent
= cupsDirRead(dir
)) != NULL
)
385 if (strlen(dent
->filename
) > 6 &&
386 !strcmp(dent
->filename
+ strlen(dent
->filename
) - 6, ".types"))
389 * Load a mime.types file...
392 snprintf(filename
, sizeof(filename
), "%s/%s", pathname
, dent
->filename
);
393 DEBUG_printf(("1mimeLoadTypes: Loading \"%s\".", filename
));
394 mime_load_types(mime
, filename
);
400 DEBUG_printf(("1mimeLoadTypes: Returning %p.", mime
));
407 * 'mimeNew()' - Create a new, empty MIME database.
410 mime_t
* /* O - MIME database */
413 return ((mime_t
*)calloc(1, sizeof(mime_t
)));
418 * 'mimeNextFilter()' - Get the next filter in the MIME database.
421 mime_filter_t
* /* O - Filter or NULL */
422 mimeNextFilter(mime_t
*mime
) /* I - MIME database */
424 DEBUG_printf(("6mimeNextFilter(mime=%p)", mime
));
428 DEBUG_puts("7mimeNextFilter: Returning NULL.");
433 mime_filter_t
*next
= (mime_filter_t
*)cupsArrayNext(mime
->filters
);
436 DEBUG_printf(("7mimeNextFilter: Returning %p.", next
));
443 * 'mimeNextType()' - Get the next type in the MIME database.
446 mime_type_t
* /* O - Type or NULL */
447 mimeNextType(mime_t
*mime
) /* I - MIME database */
449 DEBUG_printf(("6mimeNextType(mime=%p)", mime
));
453 DEBUG_puts("7mimeNextType: Returning NULL.");
458 mime_type_t
*next
= (mime_type_t
*)cupsArrayNext(mime
->types
);
461 DEBUG_printf(("7mimeNextType: Returning %p.", next
));
468 * 'mimeNumFilters()' - Get the number of filters in a MIME database.
472 mimeNumFilters(mime_t
*mime
) /* I - MIME database */
474 DEBUG_printf(("mimeNumFilters(mime=%p)", mime
));
478 DEBUG_puts("1mimeNumFilters: Returning 0.");
483 DEBUG_printf(("1mimeNumFilters: Returning %d.",
484 cupsArrayCount(mime
->filters
)));
485 return (cupsArrayCount(mime
->filters
));
491 * 'mimeNumTypes()' - Get the number of types in a MIME database.
495 mimeNumTypes(mime_t
*mime
) /* I - MIME database */
497 DEBUG_printf(("mimeNumTypes(mime=%p)", mime
));
501 DEBUG_puts("1mimeNumTypes: Returning 0.");
506 DEBUG_printf(("1mimeNumTypes: Returning %d.",
507 cupsArrayCount(mime
->types
)));
508 return (cupsArrayCount(mime
->types
));
514 * 'mimeSetErrorCallback()' - Set the callback for error messages.
518 mimeSetErrorCallback(
519 mime_t
*mime
, /* I - MIME database */
520 mime_error_cb_t cb
, /* I - Callback function */
521 void *ctx
) /* I - Context pointer for callback */
526 mime
->error_ctx
= ctx
;
532 * 'mime_add_fcache()' - Add a filter to the filter cache.
535 static const char * /* O - Full path to filter or NULL */
537 cups_array_t
*filtercache
, /* I - Filter cache */
538 const char *name
, /* I - Filter name */
539 const char *filterpath
) /* I - Filter path */
541 _mime_fcache_t key
, /* Search key */
542 *temp
; /* New filter cache */
543 char path
[1024]; /* Full path to filter */
546 DEBUG_printf(("2mime_add_fcache(filtercache=%p, name=\"%s\", "
547 "filterpath=\"%s\")", filtercache
, name
, filterpath
));
549 key
.name
= (char *)name
;
550 if ((temp
= (_mime_fcache_t
*)cupsArrayFind(filtercache
, &key
)) != NULL
)
552 DEBUG_printf(("3mime_add_fcache: Returning \"%s\".", temp
->path
));
556 if ((temp
= calloc(1, sizeof(_mime_fcache_t
))) == NULL
)
558 DEBUG_puts("3mime_add_fcache: Returning NULL.");
562 temp
->name
= strdup(name
);
564 if (cupsFileFind(name
, filterpath
, 1, path
, sizeof(path
)))
565 temp
->path
= strdup(path
);
567 cupsArrayAdd(filtercache
, temp
);
569 DEBUG_printf(("3mime_add_fcache: Returning \"%s\".", temp
->path
));
575 * 'mime_compare_fcache()' - Compare two filter cache entries.
578 static int /* O - Result of comparison */
579 mime_compare_fcache(_mime_fcache_t
*a
, /* I - First entry */
580 _mime_fcache_t
*b
) /* I - Second entry */
582 return (strcmp(a
->name
, b
->name
));
587 * 'mime_delete_fcache()' - Free all memory used by the filter cache.
592 cups_array_t
*filtercache
) /* I - Filter cache */
594 _mime_fcache_t
*current
; /* Current cache entry */
597 DEBUG_printf(("2mime_delete_fcache(filtercache=%p)", filtercache
));
599 for (current
= (_mime_fcache_t
*)cupsArrayFirst(filtercache
);
601 current
= (_mime_fcache_t
*)cupsArrayNext(filtercache
))
611 cupsArrayDelete(filtercache
);
616 * 'mime_delete_rules()' - Free all memory for the given rule tree.
620 mime_delete_rules(mime_magic_t
*rules
) /* I - Rules to free */
622 mime_magic_t
*next
; /* Next rule to free */
625 DEBUG_printf(("2mime_delete_rules(rules=%p)", rules
));
628 * Free the rules list, descending recursively to free any child rules.
631 while (rules
!= NULL
)
635 if (rules
->child
!= NULL
)
636 mime_delete_rules(rules
->child
);
638 if (rules
->op
== MIME_MAGIC_REGEX
)
639 regfree(&(rules
->value
.rev
));
648 * 'mime_load_convs()' - Load a xyz.convs file.
653 mime_t
*mime
, /* I - MIME database */
654 const char *filename
, /* I - Convs file to load */
655 const char *filterpath
, /* I - Path for filters */
656 cups_array_t
*filtercache
) /* I - Filter program cache */
658 cups_file_t
*fp
; /* Convs file */
659 char line
[1024], /* Input line from file */
660 *lineptr
, /* Current position in line */
661 super
[MIME_MAX_SUPER
], /* Super-type name */
662 type
[MIME_MAX_TYPE
], /* Type name */
663 *temp
, /* Temporary pointer */
664 *filter
; /* Filter program */
665 mime_type_t
*temptype
, /* MIME type looping var */
666 *dsttype
; /* Destination MIME type */
667 int cost
; /* Cost of filter */
670 DEBUG_printf(("2mime_load_convs(mime=%p, filename=\"%s\", filterpath=\"%s\", "
671 "filtercache=%p)", mime
, filename
, filterpath
, filtercache
));
674 * First try to open the file...
677 if ((fp
= cupsFileOpen(filename
, "r")) == NULL
)
679 DEBUG_printf(("3mime_load_convs: Unable to open \"%s\": %s", filename
,
681 _mimeError(mime
, "Unable to open \"%s\": %s", filename
, strerror(errno
));
686 * Then read each line from the file, skipping any comments in the file...
689 while (cupsFileGets(fp
, line
, sizeof(line
)) != NULL
)
692 * Skip blank lines and lines starting with a #...
695 if (!line
[0] || line
[0] == '#')
699 * Strip trailing whitespace...
702 for (lineptr
= line
+ strlen(line
) - 1;
703 lineptr
>= line
&& isspace(*lineptr
& 255);
708 * Extract the destination super-type and type names from the middle of
713 while (*lineptr
!= ' ' && *lineptr
!= '\t' && *lineptr
!= '\0')
716 while (*lineptr
== ' ' || *lineptr
== '\t')
721 while (*lineptr
!= '/' && *lineptr
!= '\n' && *lineptr
!= '\0' &&
722 (temp
- super
+ 1) < MIME_MAX_SUPER
)
723 *temp
++ = (char)tolower(*lineptr
++ & 255);
733 while (*lineptr
!= ' ' && *lineptr
!= '\t' && *lineptr
!= '\n' &&
734 *lineptr
!= '\0' && (temp
- type
+ 1) < MIME_MAX_TYPE
)
735 *temp
++ = (char)tolower(*lineptr
++ & 255);
739 if (*lineptr
== '\0' || *lineptr
== '\n')
742 if ((dsttype
= mimeType(mime
, super
, type
)) == NULL
)
744 DEBUG_printf(("3mime_load_convs: Destination type %s/%s not found.",
750 * Then get the cost and filter program...
753 while (*lineptr
== ' ' || *lineptr
== '\t')
756 if (*lineptr
< '0' || *lineptr
> '9')
759 cost
= atoi(lineptr
);
761 while (*lineptr
!= ' ' && *lineptr
!= '\t' && *lineptr
!= '\0')
763 while (*lineptr
== ' ' || *lineptr
== '\t')
766 if (*lineptr
== '\0' || *lineptr
== '\n')
771 if (strcmp(filter
, "-"))
774 * Verify that the filter exists and is executable...
777 if (!mime_add_fcache(filtercache
, filter
, filterpath
))
779 DEBUG_printf(("mime_load_convs: Filter %s not found in %s.", filter
,
781 _mimeError(mime
, "Filter \"%s\" not found.", filter
);
787 * Finally, get the source super-type and type names from the beginning of
788 * the line. We do it here so we can support wildcards...
794 while (*lineptr
!= '/' && *lineptr
!= '\n' && *lineptr
!= '\0' &&
795 (temp
- super
+ 1) < MIME_MAX_SUPER
)
796 *temp
++ = (char)tolower(*lineptr
++ & 255);
806 while (*lineptr
!= ' ' && *lineptr
!= '\t' && *lineptr
!= '\n' &&
807 *lineptr
!= '\0' && (temp
- type
+ 1) < MIME_MAX_TYPE
)
808 *temp
++ = (char)tolower(*lineptr
++ & 255);
812 if (!strcmp(super
, "*") && !strcmp(type
, "*"))
815 * Force * / * to be "application/octet-stream"...
818 strlcpy(super
, "application", sizeof(super
));
819 strlcpy(type
, "octet-stream", sizeof(type
));
823 * Add the filter to the MIME database, supporting wildcards as needed...
826 for (temptype
= (mime_type_t
*)cupsArrayFirst(mime
->types
);
828 temptype
= (mime_type_t
*)cupsArrayNext(mime
->types
))
829 if ((super
[0] == '*' || !strcmp(temptype
->super
, super
)) &&
830 (type
[0] == '*' || !strcmp(temptype
->type
, type
)))
831 mimeAddFilter(mime
, temptype
, dsttype
, cost
, filter
);
839 * 'mime_load_types()' - Load a xyz.types file.
843 mime_load_types(mime_t
*mime
, /* I - MIME database */
844 const char *filename
) /* I - Types file to load */
846 cups_file_t
*fp
; /* Types file */
847 size_t linelen
; /* Length of line */
848 char line
[32768], /* Input line from file */
849 *lineptr
, /* Current position in line */
850 super
[MIME_MAX_SUPER
], /* Super-type name */
851 type
[MIME_MAX_TYPE
], /* Type name */
852 *temp
; /* Temporary pointer */
853 mime_type_t
*typeptr
; /* New MIME type */
856 DEBUG_printf(("2mime_load_types(mime=%p, filename=\"%s\")", mime
, filename
));
859 * First try to open the file...
862 if ((fp
= cupsFileOpen(filename
, "r")) == NULL
)
864 DEBUG_printf(("3mime_load_types: Unable to open \"%s\": %s", filename
,
866 _mimeError(mime
, "Unable to open \"%s\": %s", filename
, strerror(errno
));
871 * Then read each line from the file, skipping any comments in the file...
874 while (cupsFileGets(fp
, line
, sizeof(line
)) != NULL
)
877 * Skip blank lines and lines starting with a #...
880 if (!line
[0] || line
[0] == '#')
884 * While the last character in the line is a backslash, continue on to the
885 * next line (and the next, etc.)
888 linelen
= strlen(line
);
890 while (line
[linelen
- 1] == '\\')
894 if (cupsFileGets(fp
, line
+ linelen
, sizeof(line
) - linelen
) == NULL
)
895 line
[linelen
] = '\0';
897 linelen
+= strlen(line
+ linelen
);
901 * Extract the super-type and type names from the beginning of the line.
907 while (*lineptr
!= '/' && *lineptr
!= '\n' && *lineptr
!= '\0' &&
908 (temp
- super
+ 1) < MIME_MAX_SUPER
)
909 *temp
++ = (char)tolower(*lineptr
++ & 255);
919 while (*lineptr
!= ' ' && *lineptr
!= '\t' && *lineptr
!= '\n' &&
920 *lineptr
!= '\0' && (temp
- type
+ 1) < MIME_MAX_TYPE
)
921 *temp
++ = (char)tolower(*lineptr
++ & 255);
926 * Add the type and rules to the MIME database...
929 typeptr
= mimeAddType(mime
, super
, type
);
930 mimeAddTypeRule(typeptr
, lineptr
);