]>
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 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...
241 * Read all the .types files...
244 while ((dent
= cupsDirRead(dir
)) != NULL
)
246 if (strlen(dent
->filename
) > 6 &&
247 !strcmp(dent
->filename
+ strlen(dent
->filename
) - 6, ".types"))
250 * Load a mime.types file...
253 snprintf(filename
, sizeof(filename
), "%s/%s", pathname
, dent
->filename
);
254 load_types(mime
, filename
);
261 * Read all the .convs files...
264 filtercache
= cupsArrayNew((cups_array_func_t
)compare_fcache
, NULL
);
266 while ((dent
= cupsDirRead(dir
)) != NULL
)
268 if (strlen(dent
->filename
) > 6 &&
269 !strcmp(dent
->filename
+ strlen(dent
->filename
) - 6, ".convs"))
272 * Load a mime.convs file...
275 snprintf(filename
, sizeof(filename
), "%s/%s", pathname
, dent
->filename
);
276 load_convs(mime
, filename
, filterpath
, filtercache
);
280 delete_fcache(filtercache
);
289 * 'mimeNew()' - Create a new, empty MIME database.
292 mime_t
* /* O - MIME database */
295 return ((mime_t
*)calloc(1, sizeof(mime_t
)));
300 * 'mimeNextFilter()' - Get the next filter in the MIME database.
303 mime_filter_t
* /* O - Filter or NULL */
304 mimeNextFilter(mime_t
*mime
) /* I - MIME database */
309 return ((mime_filter_t
*)cupsArrayNext(mime
->filters
));
314 * 'mimeNextType()' - Get the next type in the MIME database.
317 mime_type_t
* /* O - Type or NULL */
318 mimeNextType(mime_t
*mime
) /* I - MIME database */
323 return ((mime_type_t
*)cupsArrayNext(mime
->types
));
328 * 'mimeNumFilters()' - Get the number of filters in a MIME database.
332 mimeNumFilters(mime_t
*mime
) /* I - MIME database */
337 return (cupsArrayCount(mime
->filters
));
342 * 'mimeNumTypes()' - Get the number of types in a MIME database.
346 mimeNumTypes(mime_t
*mime
) /* I - MIME database */
351 return (cupsArrayCount(mime
->types
));
356 * 'add_fcache()' - Add a filter to the filter cache.
359 static const char * /* O - Full path to filter or NULL */
360 add_fcache(cups_array_t
*filtercache
, /* I - Filter cache */
361 const char *name
, /* I - Filter name */
362 const char *filterpath
) /* I - Filter path */
364 _mime_fcache_t key
, /* Search key */
365 *temp
; /* New filter cache */
366 char path
[1024]; /* Full path to filter */
369 key
.name
= (char *)name
;
370 if ((temp
= (_mime_fcache_t
*)cupsArrayFind(filtercache
, &key
)) != NULL
)
373 if ((temp
= calloc(1, sizeof(_mime_fcache_t
))) == NULL
)
376 temp
->name
= strdup(name
);
378 if (cupsFileFind(name
, filterpath
, 1, path
, sizeof(path
)))
379 temp
->path
= strdup(path
);
381 cupsArrayAdd(filtercache
, temp
);
388 * 'compare_fcache()' - Compare two filter cache entries.
391 static int /* O - Result of comparison */
392 compare_fcache(_mime_fcache_t
*a
, /* I - First entry */
393 _mime_fcache_t
*b
) /* I - Second entry */
395 return (strcmp(a
->name
, b
->name
));
400 * 'delete_fcache()' - Free all memory used by the filter cache.
404 delete_fcache(cups_array_t
*filtercache
)/* I - Filter cache */
406 _mime_fcache_t
*current
; /* Current cache entry */
409 for (current
= (_mime_fcache_t
*)cupsArrayFirst(filtercache
);
411 current
= (_mime_fcache_t
*)cupsArrayNext(filtercache
))
421 cupsArrayDelete(filtercache
);
426 * 'delete_rules()' - Free all memory for the given rule tree.
430 delete_rules(mime_magic_t
*rules
) /* I - Rules to free */
432 mime_magic_t
*next
; /* Next rule to free */
436 * Free the rules list, descending recursively to free any child rules.
439 while (rules
!= NULL
)
443 if (rules
->child
!= NULL
)
444 delete_rules(rules
->child
);
453 * 'load_convs()' - Load a xyz.convs file...
457 load_convs(mime_t
*mime
, /* I - MIME database */
458 const char *filename
, /* I - Convs file to load */
459 const char *filterpath
, /* I - Path for filters */
460 cups_array_t
*filtercache
) /* I - Filter program cache */
462 cups_file_t
*fp
; /* Convs file */
463 char line
[1024], /* Input line from file */
464 *lineptr
, /* Current position in line */
465 super
[MIME_MAX_SUPER
], /* Super-type name */
466 type
[MIME_MAX_TYPE
], /* Type name */
467 *temp
, /* Temporary pointer */
468 *filter
; /* Filter program */
469 mime_type_t
*temptype
, /* MIME type looping var */
470 *dsttype
; /* Destination MIME type */
471 int cost
; /* Cost of filter */
475 * First try to open the file...
478 if ((fp
= cupsFileOpen(filename
, "r")) == NULL
)
481 DEBUG_printf(("\"%s\":\n", filename
));
484 * Then read each line from the file, skipping any comments in the file...
487 while (cupsFileGets(fp
, line
, sizeof(line
)) != NULL
)
490 * Skip blank lines and lines starting with a #...
495 if (!line
[0] || line
[0] == '#')
499 * Strip trailing whitespace...
502 for (lineptr
= line
+ strlen(line
) - 1;
503 lineptr
>= line
&& isspace(*lineptr
& 255);
508 * Extract the destination super-type and type names from the middle of
513 while (*lineptr
!= ' ' && *lineptr
!= '\t' && *lineptr
!= '\0')
516 while (*lineptr
== ' ' || *lineptr
== '\t')
521 while (*lineptr
!= '/' && *lineptr
!= '\n' && *lineptr
!= '\0' &&
522 (temp
- super
+ 1) < MIME_MAX_SUPER
)
523 *temp
++ = tolower(*lineptr
++ & 255);
533 while (*lineptr
!= ' ' && *lineptr
!= '\t' && *lineptr
!= '\n' &&
534 *lineptr
!= '\0' && (temp
- type
+ 1) < MIME_MAX_TYPE
)
535 *temp
++ = tolower(*lineptr
++ & 255);
539 if (*lineptr
== '\0' || *lineptr
== '\n')
542 if ((dsttype
= mimeType(mime
, super
, type
)) == NULL
)
544 DEBUG_printf((" Destination type %s/%s not found!\n", super
, type
));
549 * Then get the cost and filter program...
552 while (*lineptr
== ' ' || *lineptr
== '\t')
555 if (*lineptr
< '0' || *lineptr
> '9')
558 cost
= atoi(lineptr
);
560 while (*lineptr
!= ' ' && *lineptr
!= '\t' && *lineptr
!= '\0')
562 while (*lineptr
== ' ' || *lineptr
== '\t')
565 if (*lineptr
== '\0' || *lineptr
== '\n')
570 if (strcmp(filter
, "-"))
573 * Verify that the filter exists and is executable...
576 if (!add_fcache(filtercache
, filter
, filterpath
))
578 DEBUG_printf((" Filter %s not found in %s!\n", filter
, filterpath
));
584 * Finally, get the source super-type and type names from the beginning of
585 * the line. We do it here so we can support wildcards...
591 while (*lineptr
!= '/' && *lineptr
!= '\n' && *lineptr
!= '\0' &&
592 (temp
- super
+ 1) < MIME_MAX_SUPER
)
593 *temp
++ = tolower(*lineptr
++ & 255);
603 while (*lineptr
!= ' ' && *lineptr
!= '\t' && *lineptr
!= '\n' &&
604 *lineptr
!= '\0' && (temp
- type
+ 1) < MIME_MAX_TYPE
)
605 *temp
++ = tolower(*lineptr
++ & 255);
609 if (!strcmp(super
, "*") && !strcmp(type
, "*"))
612 * Force * / * to be "application/octet-stream"...
615 strcpy(super
, "application");
616 strcpy(type
, "octet-stream");
620 * Add the filter to the MIME database, supporting wildcards as needed...
623 for (temptype
= (mime_type_t
*)cupsArrayFirst(mime
->types
);
625 temptype
= (mime_type_t
*)cupsArrayNext(mime
->types
))
626 if ((super
[0] == '*' || !strcmp(temptype
->super
, super
)) &&
627 (type
[0] == '*' || !strcmp(temptype
->type
, type
)))
628 mimeAddFilter(mime
, temptype
, dsttype
, cost
, filter
);
636 * 'load_types()' - Load a xyz.types file...
640 load_types(mime_t
*mime
, /* I - MIME database */
641 const char *filename
) /* I - Types file to load */
643 cups_file_t
*fp
; /* Types file */
644 int linelen
; /* Length of line */
645 char line
[32768], /* Input line from file */
646 *lineptr
, /* Current position in line */
647 super
[MIME_MAX_SUPER
], /* Super-type name */
648 type
[MIME_MAX_TYPE
], /* Type name */
649 *temp
; /* Temporary pointer */
650 mime_type_t
*typeptr
; /* New MIME type */
654 * First try to open the file...
657 if ((fp
= cupsFileOpen(filename
, "r")) == NULL
)
660 DEBUG_printf(("\"%s\":\n", filename
));
663 * Then read each line from the file, skipping any comments in the file...
666 while (cupsFileGets(fp
, line
, sizeof(line
)) != NULL
)
669 * Skip blank lines and lines starting with a #...
674 if (!line
[0] || line
[0] == '#')
678 * While the last character in the line is a backslash, continue on to the
679 * next line (and the next, etc.)
682 linelen
= strlen(line
);
684 while (line
[linelen
- 1] == '\\')
688 if (cupsFileGets(fp
, line
+ linelen
, sizeof(line
) - linelen
) == NULL
)
689 line
[linelen
] = '\0';
691 linelen
+= strlen(line
+ linelen
);
695 * Extract the super-type and type names from the beginning of the line.
701 while (*lineptr
!= '/' && *lineptr
!= '\n' && *lineptr
!= '\0' &&
702 (temp
- super
+ 1) < MIME_MAX_SUPER
)
703 *temp
++ = tolower(*lineptr
++ & 255);
713 while (*lineptr
!= ' ' && *lineptr
!= '\t' && *lineptr
!= '\n' &&
714 *lineptr
!= '\0' && (temp
- type
+ 1) < MIME_MAX_TYPE
)
715 *temp
++ = tolower(*lineptr
++ & 255);
720 * Add the type and rules to the MIME database...
723 typeptr
= mimeAddType(mime
, super
, type
);
724 mimeAddTypeRule(typeptr
, lineptr
);
732 * End of "$Id: mime.c 6649 2007-07-11 21:46:42Z mike $".