]> git.ipfire.org Git - thirdparty/cups.git/blame - scheduler/mime.c
Update svn:keyword properties.
[thirdparty/cups.git] / scheduler / mime.c
CommitLineData
ef416fc2 1/*
f2d18633 2 * "$Id$"
ef416fc2 3 *
71e16022 4 * MIME database file routines for CUPS.
ef416fc2 5 *
5a9febac 6 * Copyright 2007-2012 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
54typedef 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
65static const char *mime_add_fcache(cups_array_t *filtercache, const char *name,
66 const char *filterpath);
67static int mime_compare_fcache(_mime_fcache_t *a, _mime_fcache_t *b);
68static void mime_delete_fcache(cups_array_t *filtercache);
69static void mime_delete_rules(mime_magic_t *rules);
70static void mime_load_convs(mime_t *mime, const char *filename,
71 const char *filterpath,
72 cups_array_t *filtercache);
73static void mime_load_types(mime_t *mime, const char *filename);
ef416fc2 74
75
76/*
77 * 'mimeDelete()' - Delete (free) a MIME database.
78 */
79
80void
fa73b229 81mimeDelete(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 125void
126mimeDeleteFilter(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 167void
168mimeDeleteType(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
193void
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 217mime_filter_t * /* O - Filter or NULL */
218mimeFirstFilter(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 242mime_type_t * /* O - Type or NULL */
243mimeFirstType(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 270mime_t * /* O - New MIME database */
271mimeLoad(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
293mime_t * /* O - MIME database */
294mimeLoadFilters(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 365mime_t * /* O - MIME database */
75bd9771
MS
366mimeLoadTypes(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
434mime_t * /* O - MIME database */
435mimeNew(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
445mime_filter_t * /* O - Filter or NULL */
446mimeNextFilter(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
470mime_type_t * /* O - Type or NULL */
471mimeNextType(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
495int
496mimeNumFilters(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
518int
519mimeNumTypes(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
541void
542mimeSetErrorCallback(
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 559static const char * /* O - Full path to filter or NULL */
22c9029b
MS
560mime_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 602static int /* O - Result of comparison */
22c9029b 603mime_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 614static void
22c9029b
MS
615mime_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 643static void
22c9029b 644mime_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
672static void
22c9029b
MS
673mime_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
863static void
22c9029b
MS
864mime_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 */