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