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