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