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