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