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