]>
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 | |
662 | free(rules); | |
663 | rules = next; | |
664 | } | |
ef416fc2 | 665 | } |
666 | ||
667 | ||
668 | /* | |
eac3a0a0 | 669 | * 'mime_load_convs()' - Load a xyz.convs file. |
ef416fc2 | 670 | */ |
671 | ||
672 | static void | |
22c9029b MS |
673 | mime_load_convs( |
674 | mime_t *mime, /* I - MIME database */ | |
675 | const char *filename, /* I - Convs file to load */ | |
676 | const char *filterpath, /* I - Path for filters */ | |
677 | cups_array_t *filtercache) /* I - Filter program cache */ | |
ef416fc2 | 678 | { |
ef416fc2 | 679 | cups_file_t *fp; /* Convs file */ |
680 | char line[1024], /* Input line from file */ | |
681 | *lineptr, /* Current position in line */ | |
682 | super[MIME_MAX_SUPER], /* Super-type name */ | |
683 | type[MIME_MAX_TYPE], /* Type name */ | |
684 | *temp, /* Temporary pointer */ | |
685 | *filter; /* Filter program */ | |
fa73b229 | 686 | mime_type_t *temptype, /* MIME type looping var */ |
ef416fc2 | 687 | *dsttype; /* Destination MIME type */ |
688 | int cost; /* Cost of filter */ | |
ef416fc2 | 689 | |
690 | ||
22c9029b MS |
691 | DEBUG_printf(("2mime_load_convs(mime=%p, filename=\"%s\", filterpath=\"%s\", " |
692 | "filtercache=%p)", mime, filename, filterpath, filtercache)); | |
75bd9771 | 693 | |
ef416fc2 | 694 | /* |
695 | * First try to open the file... | |
696 | */ | |
697 | ||
698 | if ((fp = cupsFileOpen(filename, "r")) == NULL) | |
22c9029b MS |
699 | { |
700 | DEBUG_printf(("3mime_load_convs: Unable to open \"%s\": %s", filename, | |
701 | strerror(errno))); | |
eac3a0a0 | 702 | _mimeError(mime, "Unable to open \"%s\": %s", filename, strerror(errno)); |
ef416fc2 | 703 | return; |
22c9029b | 704 | } |
ef416fc2 | 705 | |
706 | /* | |
707 | * Then read each line from the file, skipping any comments in the file... | |
708 | */ | |
709 | ||
710 | while (cupsFileGets(fp, line, sizeof(line)) != NULL) | |
711 | { | |
712 | /* | |
713 | * Skip blank lines and lines starting with a #... | |
714 | */ | |
715 | ||
716 | if (!line[0] || line[0] == '#') | |
717 | continue; | |
718 | ||
719 | /* | |
720 | * Strip trailing whitespace... | |
721 | */ | |
722 | ||
723 | for (lineptr = line + strlen(line) - 1; | |
724 | lineptr >= line && isspace(*lineptr & 255); | |
725 | lineptr --) | |
726 | *lineptr = '\0'; | |
727 | ||
728 | /* | |
729 | * Extract the destination super-type and type names from the middle of | |
730 | * the line. | |
731 | */ | |
732 | ||
733 | lineptr = line; | |
734 | while (*lineptr != ' ' && *lineptr != '\t' && *lineptr != '\0') | |
735 | lineptr ++; | |
736 | ||
737 | while (*lineptr == ' ' || *lineptr == '\t') | |
738 | lineptr ++; | |
739 | ||
740 | temp = super; | |
741 | ||
742 | while (*lineptr != '/' && *lineptr != '\n' && *lineptr != '\0' && | |
743 | (temp - super + 1) < MIME_MAX_SUPER) | |
744 | *temp++ = tolower(*lineptr++ & 255); | |
745 | ||
746 | *temp = '\0'; | |
747 | ||
748 | if (*lineptr != '/') | |
749 | continue; | |
750 | ||
751 | lineptr ++; | |
752 | temp = type; | |
753 | ||
754 | while (*lineptr != ' ' && *lineptr != '\t' && *lineptr != '\n' && | |
755 | *lineptr != '\0' && (temp - type + 1) < MIME_MAX_TYPE) | |
756 | *temp++ = tolower(*lineptr++ & 255); | |
757 | ||
758 | *temp = '\0'; | |
759 | ||
760 | if (*lineptr == '\0' || *lineptr == '\n') | |
761 | continue; | |
762 | ||
763 | if ((dsttype = mimeType(mime, super, type)) == NULL) | |
ed486911 | 764 | { |
22c9029b | 765 | DEBUG_printf(("3mime_load_convs: Destination type %s/%s not found.", |
75bd9771 | 766 | super, type)); |
ef416fc2 | 767 | continue; |
ed486911 | 768 | } |
ef416fc2 | 769 | |
770 | /* | |
771 | * Then get the cost and filter program... | |
772 | */ | |
773 | ||
774 | while (*lineptr == ' ' || *lineptr == '\t') | |
775 | lineptr ++; | |
776 | ||
777 | if (*lineptr < '0' || *lineptr > '9') | |
778 | continue; | |
779 | ||
780 | cost = atoi(lineptr); | |
781 | ||
782 | while (*lineptr != ' ' && *lineptr != '\t' && *lineptr != '\0') | |
783 | lineptr ++; | |
784 | while (*lineptr == ' ' || *lineptr == '\t') | |
785 | lineptr ++; | |
786 | ||
787 | if (*lineptr == '\0' || *lineptr == '\n') | |
788 | continue; | |
789 | ||
790 | filter = lineptr; | |
791 | ||
fa73b229 | 792 | if (strcmp(filter, "-")) |
ef416fc2 | 793 | { |
794 | /* | |
795 | * Verify that the filter exists and is executable... | |
796 | */ | |
797 | ||
22c9029b | 798 | if (!mime_add_fcache(filtercache, filter, filterpath)) |
ed486911 | 799 | { |
22c9029b | 800 | DEBUG_printf(("mime_load_convs: Filter %s not found in %s.", filter, |
5a9febac | 801 | filterpath)); |
eac3a0a0 | 802 | _mimeError(mime, "Filter \"%s\" not found.", filter); |
fa73b229 | 803 | continue; |
ed486911 | 804 | } |
ef416fc2 | 805 | } |
ef416fc2 | 806 | |
807 | /* | |
808 | * Finally, get the source super-type and type names from the beginning of | |
809 | * the line. We do it here so we can support wildcards... | |
810 | */ | |
811 | ||
812 | lineptr = line; | |
813 | temp = super; | |
814 | ||
815 | while (*lineptr != '/' && *lineptr != '\n' && *lineptr != '\0' && | |
816 | (temp - super + 1) < MIME_MAX_SUPER) | |
817 | *temp++ = tolower(*lineptr++ & 255); | |
818 | ||
819 | *temp = '\0'; | |
820 | ||
821 | if (*lineptr != '/') | |
822 | continue; | |
823 | ||
824 | lineptr ++; | |
825 | temp = type; | |
826 | ||
827 | while (*lineptr != ' ' && *lineptr != '\t' && *lineptr != '\n' && | |
828 | *lineptr != '\0' && (temp - type + 1) < MIME_MAX_TYPE) | |
829 | *temp++ = tolower(*lineptr++ & 255); | |
830 | ||
831 | *temp = '\0'; | |
832 | ||
fa73b229 | 833 | if (!strcmp(super, "*") && !strcmp(type, "*")) |
ef416fc2 | 834 | { |
835 | /* | |
836 | * Force * / * to be "application/octet-stream"... | |
837 | */ | |
838 | ||
5a9febac MS |
839 | strlcpy(super, "application", sizeof(super)); |
840 | strlcpy(type, "octet-stream", sizeof(type)); | |
ef416fc2 | 841 | } |
842 | ||
843 | /* | |
844 | * Add the filter to the MIME database, supporting wildcards as needed... | |
845 | */ | |
846 | ||
fa73b229 | 847 | for (temptype = (mime_type_t *)cupsArrayFirst(mime->types); |
848 | temptype; | |
849 | temptype = (mime_type_t *)cupsArrayNext(mime->types)) | |
850 | if ((super[0] == '*' || !strcmp(temptype->super, super)) && | |
851 | (type[0] == '*' || !strcmp(temptype->type, type))) | |
852 | mimeAddFilter(mime, temptype, dsttype, cost, filter); | |
ef416fc2 | 853 | } |
854 | ||
855 | cupsFileClose(fp); | |
856 | } | |
857 | ||
858 | ||
859 | /* | |
eac3a0a0 | 860 | * 'mime_load_types()' - Load a xyz.types file. |
ef416fc2 | 861 | */ |
862 | ||
863 | static void | |
22c9029b MS |
864 | mime_load_types(mime_t *mime, /* I - MIME database */ |
865 | const char *filename) /* I - Types file to load */ | |
ef416fc2 | 866 | { |
4400e98d | 867 | cups_file_t *fp; /* Types file */ |
868 | int linelen; /* Length of line */ | |
a74454a7 | 869 | char line[32768], /* Input line from file */ |
4400e98d | 870 | *lineptr, /* Current position in line */ |
871 | super[MIME_MAX_SUPER], /* Super-type name */ | |
872 | type[MIME_MAX_TYPE], /* Type name */ | |
873 | *temp; /* Temporary pointer */ | |
874 | mime_type_t *typeptr; /* New MIME type */ | |
ef416fc2 | 875 | |
876 | ||
22c9029b | 877 | DEBUG_printf(("2mime_load_types(mime=%p, filename=\"%s\")", mime, filename)); |
75bd9771 | 878 | |
ef416fc2 | 879 | /* |
4400e98d | 880 | * First try to open the file... |
ef416fc2 | 881 | */ |
882 | ||
4400e98d | 883 | if ((fp = cupsFileOpen(filename, "r")) == NULL) |
22c9029b MS |
884 | { |
885 | DEBUG_printf(("3mime_load_types: Unable to open \"%s\": %s", filename, | |
886 | strerror(errno))); | |
eac3a0a0 | 887 | _mimeError(mime, "Unable to open \"%s\": %s", filename, strerror(errno)); |
4400e98d | 888 | return; |
22c9029b | 889 | } |
4400e98d | 890 | |
891 | /* | |
892 | * Then read each line from the file, skipping any comments in the file... | |
893 | */ | |
894 | ||
895 | while (cupsFileGets(fp, line, sizeof(line)) != NULL) | |
ef416fc2 | 896 | { |
4400e98d | 897 | /* |
898 | * Skip blank lines and lines starting with a #... | |
899 | */ | |
ef416fc2 | 900 | |
4400e98d | 901 | if (!line[0] || line[0] == '#') |
902 | continue; | |
ef416fc2 | 903 | |
4400e98d | 904 | /* |
905 | * While the last character in the line is a backslash, continue on to the | |
906 | * next line (and the next, etc.) | |
907 | */ | |
908 | ||
909 | linelen = strlen(line); | |
910 | ||
911 | while (line[linelen - 1] == '\\') | |
912 | { | |
913 | linelen --; | |
914 | ||
915 | if (cupsFileGets(fp, line + linelen, sizeof(line) - linelen) == NULL) | |
916 | line[linelen] = '\0'; | |
917 | else | |
918 | linelen += strlen(line + linelen); | |
919 | } | |
920 | ||
921 | /* | |
922 | * Extract the super-type and type names from the beginning of the line. | |
923 | */ | |
924 | ||
925 | lineptr = line; | |
926 | temp = super; | |
927 | ||
928 | while (*lineptr != '/' && *lineptr != '\n' && *lineptr != '\0' && | |
929 | (temp - super + 1) < MIME_MAX_SUPER) | |
930 | *temp++ = tolower(*lineptr++ & 255); | |
931 | ||
932 | *temp = '\0'; | |
933 | ||
934 | if (*lineptr != '/') | |
935 | continue; | |
936 | ||
937 | lineptr ++; | |
938 | temp = type; | |
939 | ||
940 | while (*lineptr != ' ' && *lineptr != '\t' && *lineptr != '\n' && | |
941 | *lineptr != '\0' && (temp - type + 1) < MIME_MAX_TYPE) | |
942 | *temp++ = tolower(*lineptr++ & 255); | |
943 | ||
944 | *temp = '\0'; | |
945 | ||
946 | /* | |
947 | * Add the type and rules to the MIME database... | |
948 | */ | |
949 | ||
950 | typeptr = mimeAddType(mime, super, type); | |
951 | mimeAddTypeRule(typeptr, lineptr); | |
ef416fc2 | 952 | } |
4400e98d | 953 | |
954 | cupsFileClose(fp); | |
ef416fc2 | 955 | } |
956 | ||
957 | ||
958 | /* | |
f2d18633 | 959 | * End of "$Id$". |
ef416fc2 | 960 | */ |