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