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