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