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