]>
Commit | Line | Data |
---|---|---|
ef416fc2 | 1 | /* |
75bd9771 | 2 | * "$Id: mime.c 7694 2008-06-26 00:23:20Z mike $" |
ef416fc2 | 3 | * |
71e16022 | 4 | * MIME database file routines for CUPS. |
ef416fc2 | 5 | * |
22c9029b | 6 | * Copyright 2007-2011 by Apple Inc. |
fa73b229 | 7 | * Copyright 1997-2006 by Easy Software Products, all rights reserved. |
ef416fc2 | 8 | * |
9 | * These coded instructions, statements, and computer programs are the | |
bc44d920 | 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/". | |
ef416fc2 | 14 | * |
15 | * Contents: | |
16 | * | |
22c9029b MS |
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 | * mime_add_fcache() - Add a filter to the filter cache. | |
30 | * mime_compare_fcache() - Compare two filter cache entries. | |
31 | * mime_delete_fcache() - Free all memory used by the filter cache. | |
32 | * mime_delete_rules() - Free all memory for the given rule tree. | |
33 | * mime_load_convs() - Load a xyz.convs file... | |
34 | * mime_load_types() - Load a xyz.types file... | |
ef416fc2 | 35 | */ |
36 | ||
37 | /* | |
38 | * Include necessary headers... | |
39 | */ | |
40 | ||
71e16022 MS |
41 | #include <cups/string-private.h> |
42 | #include <cups/debug-private.h> | |
fa73b229 | 43 | #include <cups/dir.h> |
ef416fc2 | 44 | #include "mime.h" |
45 | ||
ef416fc2 | 46 | |
4400e98d | 47 | /* |
48 | * Local types... | |
49 | */ | |
50 | ||
51 | typedef struct _mime_fcache_s /**** Filter cache structure ****/ | |
52 | { | |
53 | char *name, /* Filter name */ | |
54 | *path; /* Full path to filter if available */ | |
55 | } _mime_fcache_t; | |
56 | ||
57 | ||
ef416fc2 | 58 | /* |
59 | * Local functions... | |
60 | */ | |
61 | ||
22c9029b MS |
62 | static const char *mime_add_fcache(cups_array_t *filtercache, const char *name, |
63 | const char *filterpath); | |
64 | static int mime_compare_fcache(_mime_fcache_t *a, _mime_fcache_t *b); | |
65 | static void mime_delete_fcache(cups_array_t *filtercache); | |
66 | static void mime_delete_rules(mime_magic_t *rules); | |
67 | static void mime_load_convs(mime_t *mime, const char *filename, | |
68 | const char *filterpath, | |
69 | cups_array_t *filtercache); | |
70 | static void mime_load_types(mime_t *mime, const char *filename); | |
75bd9771 | 71 | static mime_t *mime_new(void); |
ef416fc2 | 72 | |
73 | ||
74 | /* | |
75 | * 'mimeDelete()' - Delete (free) a MIME database. | |
76 | */ | |
77 | ||
78 | void | |
fa73b229 | 79 | mimeDelete(mime_t *mime) /* I - MIME database */ |
ef416fc2 | 80 | { |
fa73b229 | 81 | mime_type_t *type; /* Current type */ |
82 | mime_filter_t *filter; /* Current filter */ | |
ef416fc2 | 83 | |
84 | ||
22c9029b MS |
85 | DEBUG_printf(("mimeDelete(mime=%p)", mime)); |
86 | ||
fa73b229 | 87 | if (!mime) |
ef416fc2 | 88 | return; |
89 | ||
fa73b229 | 90 | /* |
91 | * Loop through filters and free them... | |
92 | */ | |
93 | ||
94 | for (filter = (mime_filter_t *)cupsArrayFirst(mime->filters); | |
95 | filter; | |
96 | filter = (mime_filter_t *)cupsArrayNext(mime->filters)) | |
97 | mimeDeleteFilter(mime, filter); | |
ef416fc2 | 98 | |
89d46774 | 99 | /* |
100 | * Loop through the file types and delete any rules... | |
101 | */ | |
102 | ||
103 | for (type = (mime_type_t *)cupsArrayFirst(mime->types); | |
104 | type; | |
105 | type = (mime_type_t *)cupsArrayNext(mime->types)) | |
106 | mimeDeleteType(mime, type); | |
107 | ||
ef416fc2 | 108 | /* |
109 | * Free the types and filters arrays, and then the MIME database structure. | |
110 | */ | |
111 | ||
fa73b229 | 112 | cupsArrayDelete(mime->types); |
113 | cupsArrayDelete(mime->filters); | |
a74454a7 | 114 | cupsArrayDelete(mime->srcs); |
ef416fc2 | 115 | free(mime); |
116 | } | |
117 | ||
118 | ||
119 | /* | |
fa73b229 | 120 | * 'mimeDeleteFilter()' - Delete a filter from the MIME database. |
ef416fc2 | 121 | */ |
122 | ||
fa73b229 | 123 | void |
124 | mimeDeleteFilter(mime_t *mime, /* I - MIME database */ | |
125 | mime_filter_t *filter) /* I - Filter */ | |
ef416fc2 | 126 | { |
22c9029b MS |
127 | DEBUG_printf(("mimeDeleteFilter(mime=%p, filter=%p(%s/%s->%s/%s, cost=%d, " |
128 | "maxsize=" CUPS_LLFMT "))", mime, filter, | |
129 | filter ? filter->src->super : "???", | |
130 | filter ? filter->src->type : "???", | |
131 | filter ? filter->dst->super : "???", | |
132 | filter ? filter->dst->super : "???", | |
133 | filter ? filter->cost : -1, | |
134 | filter ? CUPS_LLCAST filter->maxsize : CUPS_LLCAST -1)); | |
135 | ||
fa73b229 | 136 | if (!mime || !filter) |
137 | return; | |
ef416fc2 | 138 | |
22c9029b MS |
139 | #ifdef DEBUG |
140 | if (!cupsArrayFind(mime->filters, filter)) | |
141 | DEBUG_puts("1mimeDeleteFilter: Filter not in MIME database."); | |
142 | #endif /* DEBUG */ | |
143 | ||
fa73b229 | 144 | cupsArrayRemove(mime->filters, filter); |
145 | free(filter); | |
a74454a7 | 146 | |
147 | /* | |
148 | * Deleting a filter invalidates the source lookup cache used by | |
149 | * mimeFilter()... | |
150 | */ | |
151 | ||
152 | if (mime->srcs) | |
153 | { | |
22c9029b | 154 | DEBUG_puts("1mimeDeleteFilter: Deleting source lookup cache."); |
a74454a7 | 155 | cupsArrayDelete(mime->srcs); |
156 | mime->srcs = NULL; | |
157 | } | |
fa73b229 | 158 | } |
ef416fc2 | 159 | |
ef416fc2 | 160 | |
fa73b229 | 161 | /* |
162 | * 'mimeDeleteType()' - Delete a type from the MIME database. | |
163 | */ | |
ef416fc2 | 164 | |
fa73b229 | 165 | void |
166 | mimeDeleteType(mime_t *mime, /* I - MIME database */ | |
167 | mime_type_t *mt) /* I - Type */ | |
168 | { | |
22c9029b MS |
169 | DEBUG_printf(("mimeDeleteType(mime=%p, mt=%p(%s/%s))", mime, mt, |
170 | mt ? mt->super : "???", mt ? mt->type : "???")); | |
171 | ||
fa73b229 | 172 | if (!mime || !mt) |
173 | return; | |
ef416fc2 | 174 | |
22c9029b MS |
175 | #ifdef DEBUG |
176 | if (!cupsArrayFind(mime->types, mt)) | |
177 | DEBUG_puts("1mimeDeleteFilter: Type not in MIME database."); | |
178 | #endif /* DEBUG */ | |
179 | ||
fa73b229 | 180 | cupsArrayRemove(mime->types, mt); |
ef416fc2 | 181 | |
22c9029b | 182 | mime_delete_rules(mt->rules); |
fa73b229 | 183 | free(mt); |
184 | } | |
ef416fc2 | 185 | |
ef416fc2 | 186 | |
fa73b229 | 187 | /* |
188 | * 'mimeFirstFilter()' - Get the first filter in the MIME database. | |
189 | */ | |
ef416fc2 | 190 | |
fa73b229 | 191 | mime_filter_t * /* O - Filter or NULL */ |
192 | mimeFirstFilter(mime_t *mime) /* I - MIME database */ | |
193 | { | |
22c9029b MS |
194 | DEBUG_printf(("6mimeFirstFilter(mime=%p)", mime)); |
195 | ||
fa73b229 | 196 | if (!mime) |
22c9029b MS |
197 | { |
198 | DEBUG_puts("7mimeFirstFilter: Returning NULL."); | |
fa73b229 | 199 | return (NULL); |
22c9029b | 200 | } |
fa73b229 | 201 | else |
22c9029b MS |
202 | { |
203 | mime_filter_t *first = (mime_filter_t *)cupsArrayFirst(mime->filters); | |
204 | /* First filter */ | |
205 | ||
206 | DEBUG_printf(("7mimeFirstFilter: Returning %p.", first)); | |
207 | return (first); | |
208 | } | |
fa73b229 | 209 | } |
ef416fc2 | 210 | |
ef416fc2 | 211 | |
fa73b229 | 212 | /* |
213 | * 'mimeFirstType()' - Get the first type in the MIME database. | |
214 | */ | |
ef416fc2 | 215 | |
fa73b229 | 216 | mime_type_t * /* O - Type or NULL */ |
217 | mimeFirstType(mime_t *mime) /* I - MIME database */ | |
218 | { | |
22c9029b MS |
219 | DEBUG_printf(("6mimeFirstType(mime=%p)", mime)); |
220 | ||
fa73b229 | 221 | if (!mime) |
22c9029b MS |
222 | { |
223 | DEBUG_puts("7mimeFirstType: Returning NULL."); | |
fa73b229 | 224 | return (NULL); |
22c9029b | 225 | } |
fa73b229 | 226 | else |
22c9029b MS |
227 | { |
228 | mime_type_t *first = (mime_type_t *)cupsArrayFirst(mime->types); | |
229 | /* First type */ | |
230 | ||
231 | DEBUG_printf(("7mimeFirstType: Returning %p.", first)); | |
232 | return (first); | |
233 | } | |
fa73b229 | 234 | } |
ef416fc2 | 235 | |
ef416fc2 | 236 | |
fa73b229 | 237 | /* |
238 | * 'mimeLoad()' - Create a new MIME database from disk. | |
75bd9771 MS |
239 | * |
240 | * This function uses @link mimeLoadFilters@ and @link mimeLoadTypes@ to | |
241 | * create a MIME database from a single directory. | |
fa73b229 | 242 | */ |
ef416fc2 | 243 | |
fa73b229 | 244 | mime_t * /* O - New MIME database */ |
245 | mimeLoad(const char *pathname, /* I - Directory to load */ | |
246 | const char *filterpath) /* I - Directory to load */ | |
247 | { | |
22c9029b MS |
248 | mime_t *mime; /* New MIME database */ |
249 | ||
250 | DEBUG_printf(("mimeLoad(pathname=\"%s\", filterpath=\"%s\")", pathname, | |
251 | filterpath)); | |
252 | ||
253 | mime = mimeLoadFilters(mimeLoadTypes(NULL, pathname), pathname, filterpath); | |
254 | DEBUG_printf(("1mimeLoad: Returning %p.", mime)); | |
255 | ||
256 | return (mime); | |
fa73b229 | 257 | } |
ef416fc2 | 258 | |
ef416fc2 | 259 | |
fa73b229 | 260 | /* |
75bd9771 MS |
261 | * 'mimeLoadFilters()' - Load filter definitions from disk. |
262 | * | |
263 | * This function loads all of the .convs files from the specified directory. | |
264 | * Use @link mimeLoadTypes@ to load all types before you load the filters. | |
fa73b229 | 265 | */ |
ef416fc2 | 266 | |
75bd9771 MS |
267 | mime_t * /* O - MIME database */ |
268 | mimeLoadFilters(mime_t *mime, /* I - MIME database */ | |
269 | const char *pathname, /* I - Directory to load from */ | |
270 | const char *filterpath) /* I - Default filter program directory */ | |
fa73b229 | 271 | { |
272 | cups_dir_t *dir; /* Directory */ | |
273 | cups_dentry_t *dent; /* Directory entry */ | |
75bd9771 | 274 | char filename[1024]; /* Full filename of .convs file */ |
4400e98d | 275 | cups_array_t *filtercache; /* Filter cache */ |
ef416fc2 | 276 | |
277 | ||
22c9029b MS |
278 | DEBUG_printf(("mimeLoadFilters(mime=%p, pathname=\"%s\", filterpath=\"%s\")", |
279 | mime, pathname, filterpath)); | |
280 | ||
ef416fc2 | 281 | /* |
75bd9771 | 282 | * Range check input... |
ef416fc2 | 283 | */ |
284 | ||
75bd9771 | 285 | if (!mime || !pathname || !filterpath) |
22c9029b MS |
286 | { |
287 | DEBUG_puts("1mimeLoadFilters: Bad arguments."); | |
75bd9771 | 288 | return (mime); |
22c9029b | 289 | } |
ef416fc2 | 290 | |
291 | /* | |
75bd9771 | 292 | * Then open the directory specified by pathname... |
ef416fc2 | 293 | */ |
294 | ||
75bd9771 | 295 | if ((dir = cupsDirOpen(pathname)) == NULL) |
22c9029b MS |
296 | { |
297 | DEBUG_printf(("1mimeLoadFilters: Unable to open \"%s\": %s", pathname, | |
298 | strerror(errno))); | |
75bd9771 | 299 | return (mime); |
22c9029b | 300 | } |
ef416fc2 | 301 | |
302 | /* | |
303 | * Read all the .convs files... | |
304 | */ | |
305 | ||
22c9029b | 306 | filtercache = cupsArrayNew((cups_array_func_t)mime_compare_fcache, NULL); |
4400e98d | 307 | |
fa73b229 | 308 | while ((dent = cupsDirRead(dir)) != NULL) |
ef416fc2 | 309 | { |
fa73b229 | 310 | if (strlen(dent->filename) > 6 && |
311 | !strcmp(dent->filename + strlen(dent->filename) - 6, ".convs")) | |
ef416fc2 | 312 | { |
313 | /* | |
314 | * Load a mime.convs file... | |
315 | */ | |
316 | ||
fa73b229 | 317 | snprintf(filename, sizeof(filename), "%s/%s", pathname, dent->filename); |
22c9029b MS |
318 | DEBUG_printf(("1mimeLoadFilters: Loading \"%s\".", filename)); |
319 | mime_load_convs(mime, filename, filterpath, filtercache); | |
ef416fc2 | 320 | } |
321 | } | |
322 | ||
22c9029b | 323 | mime_delete_fcache(filtercache); |
4400e98d | 324 | |
fa73b229 | 325 | cupsDirClose(dir); |
ef416fc2 | 326 | |
327 | return (mime); | |
ef416fc2 | 328 | } |
329 | ||
330 | ||
331 | /* | |
75bd9771 MS |
332 | * 'mimeLoadTypes()' - Load type definitions from disk. |
333 | * | |
334 | * This function loads all of the .types files from the specified directory. | |
335 | * Use @link mimeLoadFilters@ to load all filters after you load the types. | |
ef416fc2 | 336 | */ |
337 | ||
fa73b229 | 338 | mime_t * /* O - MIME database */ |
75bd9771 MS |
339 | mimeLoadTypes(mime_t *mime, /* I - MIME database or @code NULL@ to create a new one */ |
340 | const char *pathname) /* I - Directory to load from */ | |
ef416fc2 | 341 | { |
75bd9771 MS |
342 | cups_dir_t *dir; /* Directory */ |
343 | cups_dentry_t *dent; /* Directory entry */ | |
344 | char filename[1024]; /* Full filename of .types file */ | |
345 | ||
346 | ||
22c9029b MS |
347 | DEBUG_printf(("mimeLoadTypes(mime=%p, pathname=\"%s\")", mime, pathname)); |
348 | ||
75bd9771 MS |
349 | /* |
350 | * First open the directory specified by pathname... | |
351 | */ | |
352 | ||
353 | if ((dir = cupsDirOpen(pathname)) == NULL) | |
22c9029b MS |
354 | { |
355 | DEBUG_printf(("1mimeLoadTypes: Unable to open \"%s\": %s", pathname, | |
356 | strerror(errno))); | |
357 | DEBUG_printf(("1mimeLoadTypes: Returning %p.", mime)); | |
75bd9771 | 358 | return (mime); |
22c9029b | 359 | } |
75bd9771 MS |
360 | |
361 | /* | |
362 | * If "mime" is NULL, make a new, empty database... | |
363 | */ | |
364 | ||
365 | if (!mime) | |
366 | mime = mime_new(); | |
367 | ||
368 | if (!mime) | |
369 | { | |
370 | cupsDirClose(dir); | |
22c9029b | 371 | DEBUG_puts("1mimeLoadTypes: Returning NULL."); |
75bd9771 MS |
372 | return (NULL); |
373 | } | |
374 | ||
375 | /* | |
376 | * Read all the .types files... | |
377 | */ | |
378 | ||
379 | while ((dent = cupsDirRead(dir)) != NULL) | |
380 | { | |
381 | if (strlen(dent->filename) > 6 && | |
382 | !strcmp(dent->filename + strlen(dent->filename) - 6, ".types")) | |
383 | { | |
384 | /* | |
385 | * Load a mime.types file... | |
386 | */ | |
387 | ||
388 | snprintf(filename, sizeof(filename), "%s/%s", pathname, dent->filename); | |
22c9029b MS |
389 | DEBUG_printf(("1mimeLoadTypes: Loading \"%s\".", filename)); |
390 | mime_load_types(mime, filename); | |
75bd9771 MS |
391 | } |
392 | } | |
393 | ||
394 | cupsDirClose(dir); | |
395 | ||
22c9029b MS |
396 | DEBUG_printf(("1mimeLoadTypes: Returning %p.", mime)); |
397 | ||
75bd9771 | 398 | return (mime); |
ef416fc2 | 399 | } |
400 | ||
401 | ||
fa73b229 | 402 | /* |
403 | * 'mimeNextFilter()' - Get the next filter in the MIME database. | |
404 | */ | |
405 | ||
406 | mime_filter_t * /* O - Filter or NULL */ | |
407 | mimeNextFilter(mime_t *mime) /* I - MIME database */ | |
408 | { | |
22c9029b MS |
409 | DEBUG_printf(("6mimeNextFilter(mime=%p)", mime)); |
410 | ||
fa73b229 | 411 | if (!mime) |
22c9029b MS |
412 | { |
413 | DEBUG_puts("7mimeNextFilter: Returning NULL."); | |
fa73b229 | 414 | return (NULL); |
22c9029b | 415 | } |
fa73b229 | 416 | else |
22c9029b MS |
417 | { |
418 | mime_filter_t *next = (mime_filter_t *)cupsArrayNext(mime->filters); | |
419 | /* Next filter */ | |
420 | ||
421 | DEBUG_printf(("7mimeNextFilter: Returning %p.", next)); | |
422 | return (next); | |
423 | } | |
fa73b229 | 424 | } |
425 | ||
426 | ||
427 | /* | |
428 | * 'mimeNextType()' - Get the next type in the MIME database. | |
429 | */ | |
430 | ||
431 | mime_type_t * /* O - Type or NULL */ | |
432 | mimeNextType(mime_t *mime) /* I - MIME database */ | |
433 | { | |
22c9029b MS |
434 | DEBUG_printf(("6mimeNextType(mime=%p)", mime)); |
435 | ||
fa73b229 | 436 | if (!mime) |
22c9029b MS |
437 | { |
438 | DEBUG_puts("7mimeNextType: Returning NULL."); | |
fa73b229 | 439 | return (NULL); |
22c9029b | 440 | } |
fa73b229 | 441 | else |
22c9029b MS |
442 | { |
443 | mime_type_t *next = (mime_type_t *)cupsArrayNext(mime->types); | |
444 | /* Next type */ | |
445 | ||
446 | DEBUG_printf(("7mimeNextType: Returning %p.", next)); | |
447 | return (next); | |
448 | } | |
fa73b229 | 449 | } |
450 | ||
451 | ||
452 | /* | |
453 | * 'mimeNumFilters()' - Get the number of filters in a MIME database. | |
454 | */ | |
455 | ||
456 | int | |
457 | mimeNumFilters(mime_t *mime) /* I - MIME database */ | |
458 | { | |
22c9029b MS |
459 | DEBUG_printf(("mimeNumFilters(mime=%p)", mime)); |
460 | ||
fa73b229 | 461 | if (!mime) |
22c9029b MS |
462 | { |
463 | DEBUG_puts("1mimeNumFilters: Returning 0."); | |
fa73b229 | 464 | return (0); |
22c9029b | 465 | } |
fa73b229 | 466 | else |
22c9029b MS |
467 | { |
468 | DEBUG_printf(("1mimeNumFilters: Returning %d.", | |
469 | cupsArrayCount(mime->filters))); | |
fa73b229 | 470 | return (cupsArrayCount(mime->filters)); |
22c9029b | 471 | } |
fa73b229 | 472 | } |
473 | ||
474 | ||
475 | /* | |
476 | * 'mimeNumTypes()' - Get the number of types in a MIME database. | |
477 | */ | |
478 | ||
479 | int | |
480 | mimeNumTypes(mime_t *mime) /* I - MIME database */ | |
481 | { | |
22c9029b MS |
482 | DEBUG_printf(("mimeNumTypes(mime=%p)", mime)); |
483 | ||
fa73b229 | 484 | if (!mime) |
22c9029b MS |
485 | { |
486 | DEBUG_puts("1mimeNumTypes: Returning 0."); | |
fa73b229 | 487 | return (0); |
22c9029b | 488 | } |
fa73b229 | 489 | else |
22c9029b MS |
490 | { |
491 | DEBUG_printf(("1mimeNumTypes: Returning %d.", | |
492 | cupsArrayCount(mime->types))); | |
fa73b229 | 493 | return (cupsArrayCount(mime->types)); |
22c9029b | 494 | } |
fa73b229 | 495 | } |
496 | ||
497 | ||
ef416fc2 | 498 | /* |
22c9029b | 499 | * 'mime_add_fcache()' - Add a filter to the filter cache. |
ef416fc2 | 500 | */ |
501 | ||
4400e98d | 502 | static const char * /* O - Full path to filter or NULL */ |
22c9029b MS |
503 | mime_add_fcache( |
504 | cups_array_t *filtercache, /* I - Filter cache */ | |
505 | const char *name, /* I - Filter name */ | |
506 | const char *filterpath) /* I - Filter path */ | |
ef416fc2 | 507 | { |
4400e98d | 508 | _mime_fcache_t key, /* Search key */ |
509 | *temp; /* New filter cache */ | |
510 | char path[1024]; /* Full path to filter */ | |
ef416fc2 | 511 | |
512 | ||
22c9029b MS |
513 | DEBUG_printf(("2mime_add_fcache(filtercache=%p, name=\"%s\", " |
514 | "filterpath=\"%s\")", filtercache, name, filterpath)); | |
515 | ||
4400e98d | 516 | key.name = (char *)name; |
517 | if ((temp = (_mime_fcache_t *)cupsArrayFind(filtercache, &key)) != NULL) | |
22c9029b MS |
518 | { |
519 | DEBUG_printf(("3mime_add_fcache: Returning \"%s\".", temp->path)); | |
4400e98d | 520 | return (temp->path); |
22c9029b | 521 | } |
ef416fc2 | 522 | |
4400e98d | 523 | if ((temp = calloc(1, sizeof(_mime_fcache_t))) == NULL) |
22c9029b MS |
524 | { |
525 | DEBUG_puts("3mime_add_fcache: Returning NULL."); | |
4400e98d | 526 | return (NULL); |
22c9029b | 527 | } |
ef416fc2 | 528 | |
4400e98d | 529 | temp->name = strdup(name); |
ef416fc2 | 530 | |
4400e98d | 531 | if (cupsFileFind(name, filterpath, 1, path, sizeof(path))) |
532 | temp->path = strdup(path); | |
ef416fc2 | 533 | |
4400e98d | 534 | cupsArrayAdd(filtercache, temp); |
ef416fc2 | 535 | |
22c9029b | 536 | DEBUG_printf(("3mime_add_fcache: Returning \"%s\".", temp->path)); |
4400e98d | 537 | return (temp->path); |
538 | } | |
ef416fc2 | 539 | |
ef416fc2 | 540 | |
4400e98d | 541 | /* |
22c9029b | 542 | * 'mime_compare_fcache()' - Compare two filter cache entries. |
4400e98d | 543 | */ |
ef416fc2 | 544 | |
4400e98d | 545 | static int /* O - Result of comparison */ |
22c9029b | 546 | mime_compare_fcache(_mime_fcache_t *a, /* I - First entry */ |
4400e98d | 547 | _mime_fcache_t *b) /* I - Second entry */ |
548 | { | |
549 | return (strcmp(a->name, b->name)); | |
550 | } | |
ef416fc2 | 551 | |
ef416fc2 | 552 | |
4400e98d | 553 | /* |
22c9029b | 554 | * 'mime_delete_fcache()' - Free all memory used by the filter cache. |
4400e98d | 555 | */ |
ef416fc2 | 556 | |
4400e98d | 557 | static void |
22c9029b MS |
558 | mime_delete_fcache( |
559 | cups_array_t *filtercache) /* I - Filter cache */ | |
4400e98d | 560 | { |
561 | _mime_fcache_t *current; /* Current cache entry */ | |
ef416fc2 | 562 | |
ef416fc2 | 563 | |
22c9029b MS |
564 | DEBUG_printf(("2mime_delete_fcache(filtercache=%p)", filtercache)); |
565 | ||
4400e98d | 566 | for (current = (_mime_fcache_t *)cupsArrayFirst(filtercache); |
567 | current; | |
568 | current = (_mime_fcache_t *)cupsArrayNext(filtercache)) | |
569 | { | |
570 | free(current->name); | |
ef416fc2 | 571 | |
4400e98d | 572 | if (current->path) |
573 | free(current->path); | |
ef416fc2 | 574 | |
4400e98d | 575 | free(current); |
576 | } | |
ef416fc2 | 577 | |
4400e98d | 578 | cupsArrayDelete(filtercache); |
579 | } | |
ef416fc2 | 580 | |
ef416fc2 | 581 | |
4400e98d | 582 | /* |
22c9029b | 583 | * 'mime_delete_rules()' - Free all memory for the given rule tree. |
4400e98d | 584 | */ |
ef416fc2 | 585 | |
4400e98d | 586 | static void |
22c9029b | 587 | mime_delete_rules(mime_magic_t *rules) /* I - Rules to free */ |
4400e98d | 588 | { |
589 | mime_magic_t *next; /* Next rule to free */ | |
590 | ||
591 | ||
22c9029b MS |
592 | DEBUG_printf(("2mime_delete_rules(rules=%p)", rules)); |
593 | ||
4400e98d | 594 | /* |
595 | * Free the rules list, descending recursively to free any child rules. | |
596 | */ | |
597 | ||
598 | while (rules != NULL) | |
599 | { | |
600 | next = rules->next; | |
601 | ||
602 | if (rules->child != NULL) | |
22c9029b | 603 | mime_delete_rules(rules->child); |
4400e98d | 604 | |
605 | free(rules); | |
606 | rules = next; | |
607 | } | |
ef416fc2 | 608 | } |
609 | ||
610 | ||
611 | /* | |
22c9029b | 612 | * 'mime_load_convs()' - Load a xyz.convs file... |
ef416fc2 | 613 | */ |
614 | ||
615 | static void | |
22c9029b MS |
616 | mime_load_convs( |
617 | mime_t *mime, /* I - MIME database */ | |
618 | const char *filename, /* I - Convs file to load */ | |
619 | const char *filterpath, /* I - Path for filters */ | |
620 | cups_array_t *filtercache) /* I - Filter program cache */ | |
ef416fc2 | 621 | { |
ef416fc2 | 622 | cups_file_t *fp; /* Convs file */ |
623 | char line[1024], /* Input line from file */ | |
624 | *lineptr, /* Current position in line */ | |
625 | super[MIME_MAX_SUPER], /* Super-type name */ | |
626 | type[MIME_MAX_TYPE], /* Type name */ | |
627 | *temp, /* Temporary pointer */ | |
628 | *filter; /* Filter program */ | |
fa73b229 | 629 | mime_type_t *temptype, /* MIME type looping var */ |
ef416fc2 | 630 | *dsttype; /* Destination MIME type */ |
631 | int cost; /* Cost of filter */ | |
ef416fc2 | 632 | |
633 | ||
22c9029b MS |
634 | DEBUG_printf(("2mime_load_convs(mime=%p, filename=\"%s\", filterpath=\"%s\", " |
635 | "filtercache=%p)", mime, filename, filterpath, filtercache)); | |
75bd9771 | 636 | |
ef416fc2 | 637 | /* |
638 | * First try to open the file... | |
639 | */ | |
640 | ||
641 | if ((fp = cupsFileOpen(filename, "r")) == NULL) | |
22c9029b MS |
642 | { |
643 | DEBUG_printf(("3mime_load_convs: Unable to open \"%s\": %s", filename, | |
644 | strerror(errno))); | |
ef416fc2 | 645 | return; |
22c9029b | 646 | } |
ef416fc2 | 647 | |
648 | /* | |
649 | * Then read each line from the file, skipping any comments in the file... | |
650 | */ | |
651 | ||
652 | while (cupsFileGets(fp, line, sizeof(line)) != NULL) | |
653 | { | |
654 | /* | |
655 | * Skip blank lines and lines starting with a #... | |
656 | */ | |
657 | ||
658 | if (!line[0] || line[0] == '#') | |
659 | continue; | |
660 | ||
661 | /* | |
662 | * Strip trailing whitespace... | |
663 | */ | |
664 | ||
665 | for (lineptr = line + strlen(line) - 1; | |
666 | lineptr >= line && isspace(*lineptr & 255); | |
667 | lineptr --) | |
668 | *lineptr = '\0'; | |
669 | ||
670 | /* | |
671 | * Extract the destination super-type and type names from the middle of | |
672 | * the line. | |
673 | */ | |
674 | ||
675 | lineptr = line; | |
676 | while (*lineptr != ' ' && *lineptr != '\t' && *lineptr != '\0') | |
677 | lineptr ++; | |
678 | ||
679 | while (*lineptr == ' ' || *lineptr == '\t') | |
680 | lineptr ++; | |
681 | ||
682 | temp = super; | |
683 | ||
684 | while (*lineptr != '/' && *lineptr != '\n' && *lineptr != '\0' && | |
685 | (temp - super + 1) < MIME_MAX_SUPER) | |
686 | *temp++ = tolower(*lineptr++ & 255); | |
687 | ||
688 | *temp = '\0'; | |
689 | ||
690 | if (*lineptr != '/') | |
691 | continue; | |
692 | ||
693 | lineptr ++; | |
694 | temp = type; | |
695 | ||
696 | while (*lineptr != ' ' && *lineptr != '\t' && *lineptr != '\n' && | |
697 | *lineptr != '\0' && (temp - type + 1) < MIME_MAX_TYPE) | |
698 | *temp++ = tolower(*lineptr++ & 255); | |
699 | ||
700 | *temp = '\0'; | |
701 | ||
702 | if (*lineptr == '\0' || *lineptr == '\n') | |
703 | continue; | |
704 | ||
705 | if ((dsttype = mimeType(mime, super, type)) == NULL) | |
ed486911 | 706 | { |
22c9029b | 707 | DEBUG_printf(("3mime_load_convs: Destination type %s/%s not found.", |
75bd9771 | 708 | super, type)); |
ef416fc2 | 709 | continue; |
ed486911 | 710 | } |
ef416fc2 | 711 | |
712 | /* | |
713 | * Then get the cost and filter program... | |
714 | */ | |
715 | ||
716 | while (*lineptr == ' ' || *lineptr == '\t') | |
717 | lineptr ++; | |
718 | ||
719 | if (*lineptr < '0' || *lineptr > '9') | |
720 | continue; | |
721 | ||
722 | cost = atoi(lineptr); | |
723 | ||
724 | while (*lineptr != ' ' && *lineptr != '\t' && *lineptr != '\0') | |
725 | lineptr ++; | |
726 | while (*lineptr == ' ' || *lineptr == '\t') | |
727 | lineptr ++; | |
728 | ||
729 | if (*lineptr == '\0' || *lineptr == '\n') | |
730 | continue; | |
731 | ||
732 | filter = lineptr; | |
733 | ||
fa73b229 | 734 | if (strcmp(filter, "-")) |
ef416fc2 | 735 | { |
736 | /* | |
737 | * Verify that the filter exists and is executable... | |
738 | */ | |
739 | ||
22c9029b | 740 | if (!mime_add_fcache(filtercache, filter, filterpath)) |
ed486911 | 741 | { |
22c9029b | 742 | DEBUG_printf(("mime_load_convs: Filter %s not found in %s.", filter, |
75bd9771 | 743 | filterpath)); |
fa73b229 | 744 | continue; |
ed486911 | 745 | } |
ef416fc2 | 746 | } |
ef416fc2 | 747 | |
748 | /* | |
749 | * Finally, get the source super-type and type names from the beginning of | |
750 | * the line. We do it here so we can support wildcards... | |
751 | */ | |
752 | ||
753 | lineptr = line; | |
754 | temp = super; | |
755 | ||
756 | while (*lineptr != '/' && *lineptr != '\n' && *lineptr != '\0' && | |
757 | (temp - super + 1) < MIME_MAX_SUPER) | |
758 | *temp++ = tolower(*lineptr++ & 255); | |
759 | ||
760 | *temp = '\0'; | |
761 | ||
762 | if (*lineptr != '/') | |
763 | continue; | |
764 | ||
765 | lineptr ++; | |
766 | temp = type; | |
767 | ||
768 | while (*lineptr != ' ' && *lineptr != '\t' && *lineptr != '\n' && | |
769 | *lineptr != '\0' && (temp - type + 1) < MIME_MAX_TYPE) | |
770 | *temp++ = tolower(*lineptr++ & 255); | |
771 | ||
772 | *temp = '\0'; | |
773 | ||
fa73b229 | 774 | if (!strcmp(super, "*") && !strcmp(type, "*")) |
ef416fc2 | 775 | { |
776 | /* | |
777 | * Force * / * to be "application/octet-stream"... | |
778 | */ | |
779 | ||
780 | strcpy(super, "application"); | |
781 | strcpy(type, "octet-stream"); | |
782 | } | |
783 | ||
784 | /* | |
785 | * Add the filter to the MIME database, supporting wildcards as needed... | |
786 | */ | |
787 | ||
fa73b229 | 788 | for (temptype = (mime_type_t *)cupsArrayFirst(mime->types); |
789 | temptype; | |
790 | temptype = (mime_type_t *)cupsArrayNext(mime->types)) | |
791 | if ((super[0] == '*' || !strcmp(temptype->super, super)) && | |
792 | (type[0] == '*' || !strcmp(temptype->type, type))) | |
793 | mimeAddFilter(mime, temptype, dsttype, cost, filter); | |
ef416fc2 | 794 | } |
795 | ||
796 | cupsFileClose(fp); | |
797 | } | |
798 | ||
799 | ||
800 | /* | |
22c9029b | 801 | * 'mime_load_types()' - Load a xyz.types file... |
ef416fc2 | 802 | */ |
803 | ||
804 | static void | |
22c9029b MS |
805 | mime_load_types(mime_t *mime, /* I - MIME database */ |
806 | const char *filename) /* I - Types file to load */ | |
ef416fc2 | 807 | { |
4400e98d | 808 | cups_file_t *fp; /* Types file */ |
809 | int linelen; /* Length of line */ | |
a74454a7 | 810 | char line[32768], /* Input line from file */ |
4400e98d | 811 | *lineptr, /* Current position in line */ |
812 | super[MIME_MAX_SUPER], /* Super-type name */ | |
813 | type[MIME_MAX_TYPE], /* Type name */ | |
814 | *temp; /* Temporary pointer */ | |
815 | mime_type_t *typeptr; /* New MIME type */ | |
ef416fc2 | 816 | |
817 | ||
22c9029b | 818 | DEBUG_printf(("2mime_load_types(mime=%p, filename=\"%s\")", mime, filename)); |
75bd9771 | 819 | |
ef416fc2 | 820 | /* |
4400e98d | 821 | * First try to open the file... |
ef416fc2 | 822 | */ |
823 | ||
4400e98d | 824 | if ((fp = cupsFileOpen(filename, "r")) == NULL) |
22c9029b MS |
825 | { |
826 | DEBUG_printf(("3mime_load_types: Unable to open \"%s\": %s", filename, | |
827 | strerror(errno))); | |
4400e98d | 828 | return; |
22c9029b | 829 | } |
4400e98d | 830 | |
831 | /* | |
832 | * Then read each line from the file, skipping any comments in the file... | |
833 | */ | |
834 | ||
835 | while (cupsFileGets(fp, line, sizeof(line)) != NULL) | |
ef416fc2 | 836 | { |
4400e98d | 837 | /* |
838 | * Skip blank lines and lines starting with a #... | |
839 | */ | |
ef416fc2 | 840 | |
4400e98d | 841 | if (!line[0] || line[0] == '#') |
842 | continue; | |
ef416fc2 | 843 | |
4400e98d | 844 | /* |
845 | * While the last character in the line is a backslash, continue on to the | |
846 | * next line (and the next, etc.) | |
847 | */ | |
848 | ||
849 | linelen = strlen(line); | |
850 | ||
851 | while (line[linelen - 1] == '\\') | |
852 | { | |
853 | linelen --; | |
854 | ||
855 | if (cupsFileGets(fp, line + linelen, sizeof(line) - linelen) == NULL) | |
856 | line[linelen] = '\0'; | |
857 | else | |
858 | linelen += strlen(line + linelen); | |
859 | } | |
860 | ||
861 | /* | |
862 | * Extract the super-type and type names from the beginning of the line. | |
863 | */ | |
864 | ||
865 | lineptr = line; | |
866 | temp = super; | |
867 | ||
868 | while (*lineptr != '/' && *lineptr != '\n' && *lineptr != '\0' && | |
869 | (temp - super + 1) < MIME_MAX_SUPER) | |
870 | *temp++ = tolower(*lineptr++ & 255); | |
871 | ||
872 | *temp = '\0'; | |
873 | ||
874 | if (*lineptr != '/') | |
875 | continue; | |
876 | ||
877 | lineptr ++; | |
878 | temp = type; | |
879 | ||
880 | while (*lineptr != ' ' && *lineptr != '\t' && *lineptr != '\n' && | |
881 | *lineptr != '\0' && (temp - type + 1) < MIME_MAX_TYPE) | |
882 | *temp++ = tolower(*lineptr++ & 255); | |
883 | ||
884 | *temp = '\0'; | |
885 | ||
886 | /* | |
887 | * Add the type and rules to the MIME database... | |
888 | */ | |
889 | ||
890 | typeptr = mimeAddType(mime, super, type); | |
891 | mimeAddTypeRule(typeptr, lineptr); | |
ef416fc2 | 892 | } |
4400e98d | 893 | |
894 | cupsFileClose(fp); | |
ef416fc2 | 895 | } |
896 | ||
897 | ||
898 | /* | |
75bd9771 MS |
899 | * 'mime_new()' - Create a new, empty MIME database. |
900 | */ | |
901 | ||
902 | static mime_t * /* O - MIME database */ | |
903 | mime_new(void) | |
904 | { | |
905 | return ((mime_t *)calloc(1, sizeof(mime_t))); | |
906 | } | |
907 | ||
908 | ||
909 | /* | |
910 | * End of "$Id: mime.c 7694 2008-06-26 00:23:20Z mike $". | |
ef416fc2 | 911 | */ |