]>
Commit | Line | Data |
---|---|---|
1 | /* | |
2 | * "$Id$" | |
3 | * | |
4 | * MIME database file routines for CUPS. | |
5 | * | |
6 | * Copyright 2007-2012 by Apple Inc. | |
7 | * Copyright 1997-2006 by Easy Software Products, all rights reserved. | |
8 | * | |
9 | * These coded instructions, statements, and computer programs are the | |
10 | * property of Apple Inc. and are protected by Federal copyright | |
11 | * law. Distribution and use rights are outlined in the file "LICENSE.txt" | |
12 | * which should have been included with this file. If this file is | |
13 | * file is missing or damaged, see the license at "http://www.cups.org/". | |
14 | * | |
15 | * Contents: | |
16 | * | |
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. | |
38 | */ | |
39 | ||
40 | /* | |
41 | * Include necessary headers... | |
42 | */ | |
43 | ||
44 | #include <cups/string-private.h> | |
45 | #include <cups/debug-private.h> | |
46 | #include <cups/dir.h> | |
47 | #include "mime-private.h" | |
48 | ||
49 | ||
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 | ||
61 | /* | |
62 | * Local functions... | |
63 | */ | |
64 | ||
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); | |
74 | ||
75 | ||
76 | /* | |
77 | * 'mimeDelete()' - Delete (free) a MIME database. | |
78 | */ | |
79 | ||
80 | void | |
81 | mimeDelete(mime_t *mime) /* I - MIME database */ | |
82 | { | |
83 | mime_type_t *type; /* Current type */ | |
84 | mime_filter_t *filter; /* Current filter */ | |
85 | ||
86 | ||
87 | DEBUG_printf(("mimeDelete(mime=%p)", mime)); | |
88 | ||
89 | if (!mime) | |
90 | return; | |
91 | ||
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); | |
100 | ||
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 | ||
110 | /* | |
111 | * Free the types and filters arrays, and then the MIME database structure. | |
112 | */ | |
113 | ||
114 | cupsArrayDelete(mime->types); | |
115 | cupsArrayDelete(mime->filters); | |
116 | cupsArrayDelete(mime->srcs); | |
117 | free(mime); | |
118 | } | |
119 | ||
120 | ||
121 | /* | |
122 | * 'mimeDeleteFilter()' - Delete a filter from the MIME database. | |
123 | */ | |
124 | ||
125 | void | |
126 | mimeDeleteFilter(mime_t *mime, /* I - MIME database */ | |
127 | mime_filter_t *filter) /* I - Filter */ | |
128 | { | |
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)); | |
137 | ||
138 | if (!mime || !filter) | |
139 | return; | |
140 | ||
141 | #ifdef DEBUG | |
142 | if (!cupsArrayFind(mime->filters, filter)) | |
143 | DEBUG_puts("1mimeDeleteFilter: Filter not in MIME database."); | |
144 | #endif /* DEBUG */ | |
145 | ||
146 | cupsArrayRemove(mime->filters, filter); | |
147 | free(filter); | |
148 | ||
149 | /* | |
150 | * Deleting a filter invalidates the source lookup cache used by | |
151 | * mimeFilter()... | |
152 | */ | |
153 | ||
154 | if (mime->srcs) | |
155 | { | |
156 | DEBUG_puts("1mimeDeleteFilter: Deleting source lookup cache."); | |
157 | cupsArrayDelete(mime->srcs); | |
158 | mime->srcs = NULL; | |
159 | } | |
160 | } | |
161 | ||
162 | ||
163 | /* | |
164 | * 'mimeDeleteType()' - Delete a type from the MIME database. | |
165 | */ | |
166 | ||
167 | void | |
168 | mimeDeleteType(mime_t *mime, /* I - MIME database */ | |
169 | mime_type_t *mt) /* I - Type */ | |
170 | { | |
171 | DEBUG_printf(("mimeDeleteType(mime=%p, mt=%p(%s/%s))", mime, mt, | |
172 | mt ? mt->super : "???", mt ? mt->type : "???")); | |
173 | ||
174 | if (!mime || !mt) | |
175 | return; | |
176 | ||
177 | #ifdef DEBUG | |
178 | if (!cupsArrayFind(mime->types, mt)) | |
179 | DEBUG_puts("1mimeDeleteFilter: Type not in MIME database."); | |
180 | #endif /* DEBUG */ | |
181 | ||
182 | cupsArrayRemove(mime->types, mt); | |
183 | ||
184 | mime_delete_rules(mt->rules); | |
185 | free(mt); | |
186 | } | |
187 | ||
188 | ||
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 | ||
213 | /* | |
214 | * 'mimeFirstFilter()' - Get the first filter in the MIME database. | |
215 | */ | |
216 | ||
217 | mime_filter_t * /* O - Filter or NULL */ | |
218 | mimeFirstFilter(mime_t *mime) /* I - MIME database */ | |
219 | { | |
220 | DEBUG_printf(("6mimeFirstFilter(mime=%p)", mime)); | |
221 | ||
222 | if (!mime) | |
223 | { | |
224 | DEBUG_puts("7mimeFirstFilter: Returning NULL."); | |
225 | return (NULL); | |
226 | } | |
227 | else | |
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 | } | |
235 | } | |
236 | ||
237 | ||
238 | /* | |
239 | * 'mimeFirstType()' - Get the first type in the MIME database. | |
240 | */ | |
241 | ||
242 | mime_type_t * /* O - Type or NULL */ | |
243 | mimeFirstType(mime_t *mime) /* I - MIME database */ | |
244 | { | |
245 | DEBUG_printf(("6mimeFirstType(mime=%p)", mime)); | |
246 | ||
247 | if (!mime) | |
248 | { | |
249 | DEBUG_puts("7mimeFirstType: Returning NULL."); | |
250 | return (NULL); | |
251 | } | |
252 | else | |
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 | } | |
260 | } | |
261 | ||
262 | ||
263 | /* | |
264 | * 'mimeLoad()' - Create a new MIME database from disk. | |
265 | * | |
266 | * This function uses @link mimeLoadFilters@ and @link mimeLoadTypes@ to | |
267 | * create a MIME database from a single directory. | |
268 | */ | |
269 | ||
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 | { | |
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); | |
283 | } | |
284 | ||
285 | ||
286 | /* | |
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. | |
291 | */ | |
292 | ||
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 */ | |
297 | { | |
298 | cups_dir_t *dir; /* Directory */ | |
299 | cups_dentry_t *dent; /* Directory entry */ | |
300 | char filename[1024]; /* Full filename of .convs file */ | |
301 | cups_array_t *filtercache; /* Filter cache */ | |
302 | ||
303 | ||
304 | DEBUG_printf(("mimeLoadFilters(mime=%p, pathname=\"%s\", filterpath=\"%s\")", | |
305 | mime, pathname, filterpath)); | |
306 | ||
307 | /* | |
308 | * Range check input... | |
309 | */ | |
310 | ||
311 | if (!mime || !pathname || !filterpath) | |
312 | { | |
313 | DEBUG_puts("1mimeLoadFilters: Bad arguments."); | |
314 | return (mime); | |
315 | } | |
316 | ||
317 | /* | |
318 | * Then open the directory specified by pathname... | |
319 | */ | |
320 | ||
321 | if ((dir = cupsDirOpen(pathname)) == NULL) | |
322 | { | |
323 | DEBUG_printf(("1mimeLoadFilters: Unable to open \"%s\": %s", pathname, | |
324 | strerror(errno))); | |
325 | _mimeError(mime, "Unable to open \"%s\": %s", pathname, strerror(errno)); | |
326 | return (mime); | |
327 | } | |
328 | ||
329 | /* | |
330 | * Read all the .convs files... | |
331 | */ | |
332 | ||
333 | filtercache = cupsArrayNew((cups_array_func_t)mime_compare_fcache, NULL); | |
334 | ||
335 | while ((dent = cupsDirRead(dir)) != NULL) | |
336 | { | |
337 | if (strlen(dent->filename) > 6 && | |
338 | !strcmp(dent->filename + strlen(dent->filename) - 6, ".convs")) | |
339 | { | |
340 | /* | |
341 | * Load a mime.convs file... | |
342 | */ | |
343 | ||
344 | snprintf(filename, sizeof(filename), "%s/%s", pathname, dent->filename); | |
345 | DEBUG_printf(("1mimeLoadFilters: Loading \"%s\".", filename)); | |
346 | mime_load_convs(mime, filename, filterpath, filtercache); | |
347 | } | |
348 | } | |
349 | ||
350 | mime_delete_fcache(filtercache); | |
351 | ||
352 | cupsDirClose(dir); | |
353 | ||
354 | return (mime); | |
355 | } | |
356 | ||
357 | ||
358 | /* | |
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. | |
363 | */ | |
364 | ||
365 | mime_t * /* O - MIME database */ | |
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 */ | |
368 | { | |
369 | cups_dir_t *dir; /* Directory */ | |
370 | cups_dentry_t *dent; /* Directory entry */ | |
371 | char filename[1024]; /* Full filename of .types file */ | |
372 | ||
373 | ||
374 | DEBUG_printf(("mimeLoadTypes(mime=%p, pathname=\"%s\")", mime, pathname)); | |
375 | ||
376 | /* | |
377 | * First open the directory specified by pathname... | |
378 | */ | |
379 | ||
380 | if ((dir = cupsDirOpen(pathname)) == NULL) | |
381 | { | |
382 | DEBUG_printf(("1mimeLoadTypes: Unable to open \"%s\": %s", pathname, | |
383 | strerror(errno))); | |
384 | DEBUG_printf(("1mimeLoadTypes: Returning %p.", mime)); | |
385 | _mimeError(mime, "Unable to open \"%s\": %s", pathname, strerror(errno)); | |
386 | return (mime); | |
387 | } | |
388 | ||
389 | /* | |
390 | * If "mime" is NULL, make a new, empty database... | |
391 | */ | |
392 | ||
393 | if (!mime) | |
394 | mime = mimeNew(); | |
395 | ||
396 | if (!mime) | |
397 | { | |
398 | cupsDirClose(dir); | |
399 | DEBUG_puts("1mimeLoadTypes: Returning NULL."); | |
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); | |
417 | DEBUG_printf(("1mimeLoadTypes: Loading \"%s\".", filename)); | |
418 | mime_load_types(mime, filename); | |
419 | } | |
420 | } | |
421 | ||
422 | cupsDirClose(dir); | |
423 | ||
424 | DEBUG_printf(("1mimeLoadTypes: Returning %p.", mime)); | |
425 | ||
426 | return (mime); | |
427 | } | |
428 | ||
429 | ||
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 | ||
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 | { | |
448 | DEBUG_printf(("6mimeNextFilter(mime=%p)", mime)); | |
449 | ||
450 | if (!mime) | |
451 | { | |
452 | DEBUG_puts("7mimeNextFilter: Returning NULL."); | |
453 | return (NULL); | |
454 | } | |
455 | else | |
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 | } | |
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 | { | |
473 | DEBUG_printf(("6mimeNextType(mime=%p)", mime)); | |
474 | ||
475 | if (!mime) | |
476 | { | |
477 | DEBUG_puts("7mimeNextType: Returning NULL."); | |
478 | return (NULL); | |
479 | } | |
480 | else | |
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 | } | |
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 | { | |
498 | DEBUG_printf(("mimeNumFilters(mime=%p)", mime)); | |
499 | ||
500 | if (!mime) | |
501 | { | |
502 | DEBUG_puts("1mimeNumFilters: Returning 0."); | |
503 | return (0); | |
504 | } | |
505 | else | |
506 | { | |
507 | DEBUG_printf(("1mimeNumFilters: Returning %d.", | |
508 | cupsArrayCount(mime->filters))); | |
509 | return (cupsArrayCount(mime->filters)); | |
510 | } | |
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 | { | |
521 | DEBUG_printf(("mimeNumTypes(mime=%p)", mime)); | |
522 | ||
523 | if (!mime) | |
524 | { | |
525 | DEBUG_puts("1mimeNumTypes: Returning 0."); | |
526 | return (0); | |
527 | } | |
528 | else | |
529 | { | |
530 | DEBUG_printf(("1mimeNumTypes: Returning %d.", | |
531 | cupsArrayCount(mime->types))); | |
532 | return (cupsArrayCount(mime->types)); | |
533 | } | |
534 | } | |
535 | ||
536 | ||
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 | ||
555 | /* | |
556 | * 'mime_add_fcache()' - Add a filter to the filter cache. | |
557 | */ | |
558 | ||
559 | static const char * /* O - Full path to filter or NULL */ | |
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 */ | |
564 | { | |
565 | _mime_fcache_t key, /* Search key */ | |
566 | *temp; /* New filter cache */ | |
567 | char path[1024]; /* Full path to filter */ | |
568 | ||
569 | ||
570 | DEBUG_printf(("2mime_add_fcache(filtercache=%p, name=\"%s\", " | |
571 | "filterpath=\"%s\")", filtercache, name, filterpath)); | |
572 | ||
573 | key.name = (char *)name; | |
574 | if ((temp = (_mime_fcache_t *)cupsArrayFind(filtercache, &key)) != NULL) | |
575 | { | |
576 | DEBUG_printf(("3mime_add_fcache: Returning \"%s\".", temp->path)); | |
577 | return (temp->path); | |
578 | } | |
579 | ||
580 | if ((temp = calloc(1, sizeof(_mime_fcache_t))) == NULL) | |
581 | { | |
582 | DEBUG_puts("3mime_add_fcache: Returning NULL."); | |
583 | return (NULL); | |
584 | } | |
585 | ||
586 | temp->name = strdup(name); | |
587 | ||
588 | if (cupsFileFind(name, filterpath, 1, path, sizeof(path))) | |
589 | temp->path = strdup(path); | |
590 | ||
591 | cupsArrayAdd(filtercache, temp); | |
592 | ||
593 | DEBUG_printf(("3mime_add_fcache: Returning \"%s\".", temp->path)); | |
594 | return (temp->path); | |
595 | } | |
596 | ||
597 | ||
598 | /* | |
599 | * 'mime_compare_fcache()' - Compare two filter cache entries. | |
600 | */ | |
601 | ||
602 | static int /* O - Result of comparison */ | |
603 | mime_compare_fcache(_mime_fcache_t *a, /* I - First entry */ | |
604 | _mime_fcache_t *b) /* I - Second entry */ | |
605 | { | |
606 | return (strcmp(a->name, b->name)); | |
607 | } | |
608 | ||
609 | ||
610 | /* | |
611 | * 'mime_delete_fcache()' - Free all memory used by the filter cache. | |
612 | */ | |
613 | ||
614 | static void | |
615 | mime_delete_fcache( | |
616 | cups_array_t *filtercache) /* I - Filter cache */ | |
617 | { | |
618 | _mime_fcache_t *current; /* Current cache entry */ | |
619 | ||
620 | ||
621 | DEBUG_printf(("2mime_delete_fcache(filtercache=%p)", filtercache)); | |
622 | ||
623 | for (current = (_mime_fcache_t *)cupsArrayFirst(filtercache); | |
624 | current; | |
625 | current = (_mime_fcache_t *)cupsArrayNext(filtercache)) | |
626 | { | |
627 | free(current->name); | |
628 | ||
629 | if (current->path) | |
630 | free(current->path); | |
631 | ||
632 | free(current); | |
633 | } | |
634 | ||
635 | cupsArrayDelete(filtercache); | |
636 | } | |
637 | ||
638 | ||
639 | /* | |
640 | * 'mime_delete_rules()' - Free all memory for the given rule tree. | |
641 | */ | |
642 | ||
643 | static void | |
644 | mime_delete_rules(mime_magic_t *rules) /* I - Rules to free */ | |
645 | { | |
646 | mime_magic_t *next; /* Next rule to free */ | |
647 | ||
648 | ||
649 | DEBUG_printf(("2mime_delete_rules(rules=%p)", rules)); | |
650 | ||
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) | |
660 | mime_delete_rules(rules->child); | |
661 | ||
662 | free(rules); | |
663 | rules = next; | |
664 | } | |
665 | } | |
666 | ||
667 | ||
668 | /* | |
669 | * 'mime_load_convs()' - Load a xyz.convs file. | |
670 | */ | |
671 | ||
672 | static void | |
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 */ | |
678 | { | |
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 */ | |
686 | mime_type_t *temptype, /* MIME type looping var */ | |
687 | *dsttype; /* Destination MIME type */ | |
688 | int cost; /* Cost of filter */ | |
689 | ||
690 | ||
691 | DEBUG_printf(("2mime_load_convs(mime=%p, filename=\"%s\", filterpath=\"%s\", " | |
692 | "filtercache=%p)", mime, filename, filterpath, filtercache)); | |
693 | ||
694 | /* | |
695 | * First try to open the file... | |
696 | */ | |
697 | ||
698 | if ((fp = cupsFileOpen(filename, "r")) == NULL) | |
699 | { | |
700 | DEBUG_printf(("3mime_load_convs: Unable to open \"%s\": %s", filename, | |
701 | strerror(errno))); | |
702 | _mimeError(mime, "Unable to open \"%s\": %s", filename, strerror(errno)); | |
703 | return; | |
704 | } | |
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) | |
764 | { | |
765 | DEBUG_printf(("3mime_load_convs: Destination type %s/%s not found.", | |
766 | super, type)); | |
767 | continue; | |
768 | } | |
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 | ||
792 | if (strcmp(filter, "-")) | |
793 | { | |
794 | /* | |
795 | * Verify that the filter exists and is executable... | |
796 | */ | |
797 | ||
798 | if (!mime_add_fcache(filtercache, filter, filterpath)) | |
799 | { | |
800 | DEBUG_printf(("mime_load_convs: Filter %s not found in %s.", filter, | |
801 | filterpath)); | |
802 | _mimeError(mime, "Filter \"%s\" not found.", filter); | |
803 | continue; | |
804 | } | |
805 | } | |
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 | ||
833 | if (!strcmp(super, "*") && !strcmp(type, "*")) | |
834 | { | |
835 | /* | |
836 | * Force * / * to be "application/octet-stream"... | |
837 | */ | |
838 | ||
839 | strlcpy(super, "application", sizeof(super)); | |
840 | strlcpy(type, "octet-stream", sizeof(type)); | |
841 | } | |
842 | ||
843 | /* | |
844 | * Add the filter to the MIME database, supporting wildcards as needed... | |
845 | */ | |
846 | ||
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); | |
853 | } | |
854 | ||
855 | cupsFileClose(fp); | |
856 | } | |
857 | ||
858 | ||
859 | /* | |
860 | * 'mime_load_types()' - Load a xyz.types file. | |
861 | */ | |
862 | ||
863 | static void | |
864 | mime_load_types(mime_t *mime, /* I - MIME database */ | |
865 | const char *filename) /* I - Types file to load */ | |
866 | { | |
867 | cups_file_t *fp; /* Types file */ | |
868 | int linelen; /* Length of line */ | |
869 | char line[32768], /* Input line from file */ | |
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 */ | |
875 | ||
876 | ||
877 | DEBUG_printf(("2mime_load_types(mime=%p, filename=\"%s\")", mime, filename)); | |
878 | ||
879 | /* | |
880 | * First try to open the file... | |
881 | */ | |
882 | ||
883 | if ((fp = cupsFileOpen(filename, "r")) == NULL) | |
884 | { | |
885 | DEBUG_printf(("3mime_load_types: Unable to open \"%s\": %s", filename, | |
886 | strerror(errno))); | |
887 | _mimeError(mime, "Unable to open \"%s\": %s", filename, strerror(errno)); | |
888 | return; | |
889 | } | |
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) | |
896 | { | |
897 | /* | |
898 | * Skip blank lines and lines starting with a #... | |
899 | */ | |
900 | ||
901 | if (!line[0] || line[0] == '#') | |
902 | continue; | |
903 | ||
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); | |
952 | } | |
953 | ||
954 | cupsFileClose(fp); | |
955 | } | |
956 | ||
957 | ||
958 | /* | |
959 | * End of "$Id$". | |
960 | */ |