]>
git.ipfire.org Git - thirdparty/cups.git/blob - scheduler/mime.c
2 * "$Id: mime.c 6649 2007-07-11 21:46:42Z mike $"
4 * MIME database file routines for the Common UNIX Printing System (CUPS).
6 * Copyright 2007-2008 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 * mimeFirstFilter() - Get the first filter in the MIME database.
21 * mimeFirstType() - Get the first type in the MIME database.
22 * mimeLoad() - Create a new MIME database from disk.
23 * mimeMerge() - Merge a MIME database from disk with the current one.
24 * mimeNew() - Create a new, empty MIME database.
25 * mimeNextFilter() - Get the next filter in the MIME database.
26 * mimeNextType() - Get the next type in the MIME database.
27 * mimeNumFilters() - Get the number of filters in a MIME database.
28 * mimeNumTypes() - Get the number of types in a MIME database.
29 * add_fcache() - Add a filter to the filter cache.
30 * compare_fcache() - Compare two filter cache entries.
31 * delete_fcache() - Free all memory used by the filter cache.
32 * delete_rules() - Free all memory for the given rule tree.
33 * load_convs() - Load a xyz.convs file...
34 * load_types() - Load a xyz.types file...
38 * Include necessary headers...
45 #include <cups/debug.h>
47 #include <cups/string.h>
55 typedef struct _mime_fcache_s
/**** Filter cache structure ****/
57 char *name
, /* Filter name */
58 *path
; /* Full path to filter if available */
66 static const char *add_fcache(cups_array_t
*filtercache
, const char *name
,
67 const char *filterpath
);
68 static int compare_fcache(_mime_fcache_t
*a
, _mime_fcache_t
*b
);
69 static void delete_fcache(cups_array_t
*filtercache
);
70 static void delete_rules(mime_magic_t
*rules
);
71 static void load_convs(mime_t
*mime
, const char *filename
,
72 const char *filterpath
,
73 cups_array_t
*filtercache
);
74 static void load_types(mime_t
*mime
, const char *filename
);
78 * 'mimeDelete()' - Delete (free) a MIME database.
82 mimeDelete(mime_t
*mime
) /* I - MIME database */
84 mime_type_t
*type
; /* Current type */
85 mime_filter_t
*filter
; /* Current filter */
92 * Loop through filters and free them...
95 for (filter
= (mime_filter_t
*)cupsArrayFirst(mime
->filters
);
97 filter
= (mime_filter_t
*)cupsArrayNext(mime
->filters
))
98 mimeDeleteFilter(mime
, filter
);
101 * Loop through the file types and delete any rules...
104 for (type
= (mime_type_t
*)cupsArrayFirst(mime
->types
);
106 type
= (mime_type_t
*)cupsArrayNext(mime
->types
))
107 mimeDeleteType(mime
, type
);
110 * Free the types and filters arrays, and then the MIME database structure.
113 cupsArrayDelete(mime
->types
);
114 cupsArrayDelete(mime
->filters
);
115 cupsArrayDelete(mime
->srcs
);
121 * 'mimeDeleteFilter()' - Delete a filter from the MIME database.
125 mimeDeleteFilter(mime_t
*mime
, /* I - MIME database */
126 mime_filter_t
*filter
) /* I - Filter */
128 if (!mime
|| !filter
)
131 cupsArrayRemove(mime
->filters
, filter
);
135 * Deleting a filter invalidates the source lookup cache used by
141 cupsArrayDelete(mime
->srcs
);
148 * 'mimeDeleteType()' - Delete a type from the MIME database.
152 mimeDeleteType(mime_t
*mime
, /* I - MIME database */
153 mime_type_t
*mt
) /* I - Type */
158 cupsArrayRemove(mime
->types
, mt
);
160 delete_rules(mt
->rules
);
166 * 'mimeFirstFilter()' - Get the first filter in the MIME database.
169 mime_filter_t
* /* O - Filter or NULL */
170 mimeFirstFilter(mime_t
*mime
) /* I - MIME database */
175 return ((mime_filter_t
*)cupsArrayFirst(mime
->filters
));
180 * 'mimeFirstType()' - Get the first type in the MIME database.
183 mime_type_t
* /* O - Type or NULL */
184 mimeFirstType(mime_t
*mime
) /* I - MIME database */
189 return ((mime_type_t
*)cupsArrayFirst(mime
->types
));
194 * 'mimeLoad()' - Create a new MIME database from disk.
197 mime_t
* /* O - New MIME database */
198 mimeLoad(const char *pathname
, /* I - Directory to load */
199 const char *filterpath
) /* I - Directory to load */
201 return (mimeMerge(NULL
, pathname
, filterpath
));
206 * 'mimeMerge()' - Merge a MIME database from disk with the current one.
209 mime_t
* /* O - Updated MIME database */
210 mimeMerge(mime_t
*mime
, /* I - MIME database to add to */
211 const char *pathname
, /* I - Directory to load */
212 const char *filterpath
) /* I - Directory to load */
214 cups_dir_t
*dir
; /* Directory */
215 cups_dentry_t
*dent
; /* Directory entry */
216 char filename
[1024]; /* Full filename of types/converts file */
217 cups_array_t
*filtercache
; /* Filter cache */
221 * First open the directory specified by pathname... Return NULL if nothing
222 * was read or if the pathname is NULL...
228 if ((dir
= cupsDirOpen(pathname
)) == NULL
)
232 * If "mime" is NULL, make a new, blank database...
244 * Read all the .types files...
247 while ((dent
= cupsDirRead(dir
)) != NULL
)
249 if (strlen(dent
->filename
) > 6 &&
250 !strcmp(dent
->filename
+ strlen(dent
->filename
) - 6, ".types"))
253 * Load a mime.types file...
256 snprintf(filename
, sizeof(filename
), "%s/%s", pathname
, dent
->filename
);
257 load_types(mime
, filename
);
264 * Read all the .convs files...
267 filtercache
= cupsArrayNew((cups_array_func_t
)compare_fcache
, NULL
);
269 while ((dent
= cupsDirRead(dir
)) != NULL
)
271 if (strlen(dent
->filename
) > 6 &&
272 !strcmp(dent
->filename
+ strlen(dent
->filename
) - 6, ".convs"))
275 * Load a mime.convs file...
278 snprintf(filename
, sizeof(filename
), "%s/%s", pathname
, dent
->filename
);
279 load_convs(mime
, filename
, filterpath
, filtercache
);
283 delete_fcache(filtercache
);
292 * 'mimeNew()' - Create a new, empty MIME database.
295 mime_t
* /* O - MIME database */
298 return ((mime_t
*)calloc(1, sizeof(mime_t
)));
303 * 'mimeNextFilter()' - Get the next filter in the MIME database.
306 mime_filter_t
* /* O - Filter or NULL */
307 mimeNextFilter(mime_t
*mime
) /* I - MIME database */
312 return ((mime_filter_t
*)cupsArrayNext(mime
->filters
));
317 * 'mimeNextType()' - Get the next type in the MIME database.
320 mime_type_t
* /* O - Type or NULL */
321 mimeNextType(mime_t
*mime
) /* I - MIME database */
326 return ((mime_type_t
*)cupsArrayNext(mime
->types
));
331 * 'mimeNumFilters()' - Get the number of filters in a MIME database.
335 mimeNumFilters(mime_t
*mime
) /* I - MIME database */
340 return (cupsArrayCount(mime
->filters
));
345 * 'mimeNumTypes()' - Get the number of types in a MIME database.
349 mimeNumTypes(mime_t
*mime
) /* I - MIME database */
354 return (cupsArrayCount(mime
->types
));
359 * 'add_fcache()' - Add a filter to the filter cache.
362 static const char * /* O - Full path to filter or NULL */
363 add_fcache(cups_array_t
*filtercache
, /* I - Filter cache */
364 const char *name
, /* I - Filter name */
365 const char *filterpath
) /* I - Filter path */
367 _mime_fcache_t key
, /* Search key */
368 *temp
; /* New filter cache */
369 char path
[1024]; /* Full path to filter */
372 key
.name
= (char *)name
;
373 if ((temp
= (_mime_fcache_t
*)cupsArrayFind(filtercache
, &key
)) != NULL
)
376 if ((temp
= calloc(1, sizeof(_mime_fcache_t
))) == NULL
)
379 temp
->name
= strdup(name
);
381 if (cupsFileFind(name
, filterpath
, 1, path
, sizeof(path
)))
382 temp
->path
= strdup(path
);
384 cupsArrayAdd(filtercache
, temp
);
391 * 'compare_fcache()' - Compare two filter cache entries.
394 static int /* O - Result of comparison */
395 compare_fcache(_mime_fcache_t
*a
, /* I - First entry */
396 _mime_fcache_t
*b
) /* I - Second entry */
398 return (strcmp(a
->name
, b
->name
));
403 * 'delete_fcache()' - Free all memory used by the filter cache.
407 delete_fcache(cups_array_t
*filtercache
)/* I - Filter cache */
409 _mime_fcache_t
*current
; /* Current cache entry */
412 for (current
= (_mime_fcache_t
*)cupsArrayFirst(filtercache
);
414 current
= (_mime_fcache_t
*)cupsArrayNext(filtercache
))
424 cupsArrayDelete(filtercache
);
429 * 'delete_rules()' - Free all memory for the given rule tree.
433 delete_rules(mime_magic_t
*rules
) /* I - Rules to free */
435 mime_magic_t
*next
; /* Next rule to free */
439 * Free the rules list, descending recursively to free any child rules.
442 while (rules
!= NULL
)
446 if (rules
->child
!= NULL
)
447 delete_rules(rules
->child
);
456 * 'load_convs()' - Load a xyz.convs file...
460 load_convs(mime_t
*mime
, /* I - MIME database */
461 const char *filename
, /* I - Convs file to load */
462 const char *filterpath
, /* I - Path for filters */
463 cups_array_t
*filtercache
) /* I - Filter program cache */
465 cups_file_t
*fp
; /* Convs file */
466 char line
[1024], /* Input line from file */
467 *lineptr
, /* Current position in line */
468 super
[MIME_MAX_SUPER
], /* Super-type name */
469 type
[MIME_MAX_TYPE
], /* Type name */
470 *temp
, /* Temporary pointer */
471 *filter
; /* Filter program */
472 mime_type_t
*temptype
, /* MIME type looping var */
473 *dsttype
; /* Destination MIME type */
474 int cost
; /* Cost of filter */
478 * First try to open the file...
481 if ((fp
= cupsFileOpen(filename
, "r")) == NULL
)
484 DEBUG_printf(("\"%s\":\n", filename
));
487 * Then read each line from the file, skipping any comments in the file...
490 while (cupsFileGets(fp
, line
, sizeof(line
)) != NULL
)
493 * Skip blank lines and lines starting with a #...
498 if (!line
[0] || line
[0] == '#')
502 * Strip trailing whitespace...
505 for (lineptr
= line
+ strlen(line
) - 1;
506 lineptr
>= line
&& isspace(*lineptr
& 255);
511 * Extract the destination super-type and type names from the middle of
516 while (*lineptr
!= ' ' && *lineptr
!= '\t' && *lineptr
!= '\0')
519 while (*lineptr
== ' ' || *lineptr
== '\t')
524 while (*lineptr
!= '/' && *lineptr
!= '\n' && *lineptr
!= '\0' &&
525 (temp
- super
+ 1) < MIME_MAX_SUPER
)
526 *temp
++ = tolower(*lineptr
++ & 255);
536 while (*lineptr
!= ' ' && *lineptr
!= '\t' && *lineptr
!= '\n' &&
537 *lineptr
!= '\0' && (temp
- type
+ 1) < MIME_MAX_TYPE
)
538 *temp
++ = tolower(*lineptr
++ & 255);
542 if (*lineptr
== '\0' || *lineptr
== '\n')
545 if ((dsttype
= mimeType(mime
, super
, type
)) == NULL
)
547 DEBUG_printf((" Destination type %s/%s not found!\n", super
, type
));
552 * Then get the cost and filter program...
555 while (*lineptr
== ' ' || *lineptr
== '\t')
558 if (*lineptr
< '0' || *lineptr
> '9')
561 cost
= atoi(lineptr
);
563 while (*lineptr
!= ' ' && *lineptr
!= '\t' && *lineptr
!= '\0')
565 while (*lineptr
== ' ' || *lineptr
== '\t')
568 if (*lineptr
== '\0' || *lineptr
== '\n')
573 if (strcmp(filter
, "-"))
576 * Verify that the filter exists and is executable...
579 if (!add_fcache(filtercache
, filter
, filterpath
))
581 DEBUG_printf((" Filter %s not found in %s!\n", filter
, filterpath
));
587 * Finally, get the source super-type and type names from the beginning of
588 * the line. We do it here so we can support wildcards...
594 while (*lineptr
!= '/' && *lineptr
!= '\n' && *lineptr
!= '\0' &&
595 (temp
- super
+ 1) < MIME_MAX_SUPER
)
596 *temp
++ = tolower(*lineptr
++ & 255);
606 while (*lineptr
!= ' ' && *lineptr
!= '\t' && *lineptr
!= '\n' &&
607 *lineptr
!= '\0' && (temp
- type
+ 1) < MIME_MAX_TYPE
)
608 *temp
++ = tolower(*lineptr
++ & 255);
612 if (!strcmp(super
, "*") && !strcmp(type
, "*"))
615 * Force * / * to be "application/octet-stream"...
618 strcpy(super
, "application");
619 strcpy(type
, "octet-stream");
623 * Add the filter to the MIME database, supporting wildcards as needed...
626 for (temptype
= (mime_type_t
*)cupsArrayFirst(mime
->types
);
628 temptype
= (mime_type_t
*)cupsArrayNext(mime
->types
))
629 if ((super
[0] == '*' || !strcmp(temptype
->super
, super
)) &&
630 (type
[0] == '*' || !strcmp(temptype
->type
, type
)))
631 mimeAddFilter(mime
, temptype
, dsttype
, cost
, filter
);
639 * 'load_types()' - Load a xyz.types file...
643 load_types(mime_t
*mime
, /* I - MIME database */
644 const char *filename
) /* I - Types file to load */
646 cups_file_t
*fp
; /* Types file */
647 int linelen
; /* Length of line */
648 char line
[32768], /* Input line from file */
649 *lineptr
, /* Current position in line */
650 super
[MIME_MAX_SUPER
], /* Super-type name */
651 type
[MIME_MAX_TYPE
], /* Type name */
652 *temp
; /* Temporary pointer */
653 mime_type_t
*typeptr
; /* New MIME type */
657 * First try to open the file...
660 if ((fp
= cupsFileOpen(filename
, "r")) == NULL
)
663 DEBUG_printf(("\"%s\":\n", filename
));
666 * Then read each line from the file, skipping any comments in the file...
669 while (cupsFileGets(fp
, line
, sizeof(line
)) != NULL
)
672 * Skip blank lines and lines starting with a #...
677 if (!line
[0] || line
[0] == '#')
681 * While the last character in the line is a backslash, continue on to the
682 * next line (and the next, etc.)
685 linelen
= strlen(line
);
687 while (line
[linelen
- 1] == '\\')
691 if (cupsFileGets(fp
, line
+ linelen
, sizeof(line
) - linelen
) == NULL
)
692 line
[linelen
] = '\0';
694 linelen
+= strlen(line
+ linelen
);
698 * Extract the super-type and type names from the beginning of the line.
704 while (*lineptr
!= '/' && *lineptr
!= '\n' && *lineptr
!= '\0' &&
705 (temp
- super
+ 1) < MIME_MAX_SUPER
)
706 *temp
++ = tolower(*lineptr
++ & 255);
716 while (*lineptr
!= ' ' && *lineptr
!= '\t' && *lineptr
!= '\n' &&
717 *lineptr
!= '\0' && (temp
- type
+ 1) < MIME_MAX_TYPE
)
718 *temp
++ = tolower(*lineptr
++ & 255);
723 * Add the type and rules to the MIME database...
726 typeptr
= mimeAddType(mime
, super
, type
);
727 mimeAddTypeRule(typeptr
, lineptr
);
735 * End of "$Id: mime.c 6649 2007-07-11 21:46:42Z mike $".