Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
srohatgi01
GitHub Repository: srohatgi01/cups
Path: blob/master/scheduler/mime.c
1090 views
1
/*
2
* MIME database file routines for CUPS.
3
*
4
* Copyright 2007-2014 by Apple Inc.
5
* Copyright 1997-2006 by Easy Software Products, all rights reserved.
6
*
7
* Licensed under Apache License v2.0. See the file "LICENSE" for more information.
8
*/
9
10
/*
11
* Include necessary headers...
12
*/
13
14
#include <cups/string-private.h>
15
#include <cups/dir.h>
16
#include "mime-private.h"
17
18
19
/*
20
* Debug macros that used to be private API...
21
*/
22
23
#define DEBUG_puts(x)
24
#define DEBUG_printf(...)
25
26
27
/*
28
* Local types...
29
*/
30
31
typedef 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
38
/*
39
* Local functions...
40
*/
41
42
static const char *mime_add_fcache(cups_array_t *filtercache, const char *name,
43
const char *filterpath);
44
static int mime_compare_fcache(_mime_fcache_t *a, _mime_fcache_t *b);
45
static void mime_delete_fcache(cups_array_t *filtercache);
46
static void mime_delete_rules(mime_magic_t *rules);
47
static void mime_load_convs(mime_t *mime, const char *filename,
48
const char *filterpath,
49
cups_array_t *filtercache);
50
static void mime_load_types(mime_t *mime, const char *filename);
51
52
53
/*
54
* 'mimeDelete()' - Delete (free) a MIME database.
55
*/
56
57
void
58
mimeDelete(mime_t *mime) /* I - MIME database */
59
{
60
mime_type_t *type; /* Current type */
61
mime_filter_t *filter; /* Current filter */
62
63
64
DEBUG_printf(("mimeDelete(mime=%p)", mime));
65
66
if (!mime)
67
return;
68
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);
77
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
87
/*
88
* Free the types and filters arrays, and then the MIME database structure.
89
*/
90
91
cupsArrayDelete(mime->types);
92
cupsArrayDelete(mime->filters);
93
cupsArrayDelete(mime->srcs);
94
free(mime);
95
}
96
97
98
/*
99
* 'mimeDeleteFilter()' - Delete a filter from the MIME database.
100
*/
101
102
void
103
mimeDeleteFilter(mime_t *mime, /* I - MIME database */
104
mime_filter_t *filter) /* I - Filter */
105
{
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));
114
115
if (!mime || !filter)
116
return;
117
118
#ifdef DEBUG
119
if (!cupsArrayFind(mime->filters, filter))
120
DEBUG_puts("1mimeDeleteFilter: Filter not in MIME database.");
121
#endif /* DEBUG */
122
123
cupsArrayRemove(mime->filters, filter);
124
free(filter);
125
126
/*
127
* Deleting a filter invalidates the source lookup cache used by
128
* mimeFilter()...
129
*/
130
131
if (mime->srcs)
132
{
133
DEBUG_puts("1mimeDeleteFilter: Deleting source lookup cache.");
134
cupsArrayDelete(mime->srcs);
135
mime->srcs = NULL;
136
}
137
}
138
139
140
/*
141
* 'mimeDeleteType()' - Delete a type from the MIME database.
142
*/
143
144
void
145
mimeDeleteType(mime_t *mime, /* I - MIME database */
146
mime_type_t *mt) /* I - Type */
147
{
148
DEBUG_printf(("mimeDeleteType(mime=%p, mt=%p(%s/%s))", mime, mt,
149
mt ? mt->super : "???", mt ? mt->type : "???"));
150
151
if (!mime || !mt)
152
return;
153
154
#ifdef DEBUG
155
if (!cupsArrayFind(mime->types, mt))
156
DEBUG_puts("1mimeDeleteFilter: Type not in MIME database.");
157
#endif /* DEBUG */
158
159
cupsArrayRemove(mime->types, mt);
160
161
mime_delete_rules(mt->rules);
162
free(mt);
163
}
164
165
166
/*
167
* '_mimeError()' - Show an error message.
168
*/
169
170
void
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
190
/*
191
* 'mimeFirstFilter()' - Get the first filter in the MIME database.
192
*/
193
194
mime_filter_t * /* O - Filter or NULL */
195
mimeFirstFilter(mime_t *mime) /* I - MIME database */
196
{
197
DEBUG_printf(("6mimeFirstFilter(mime=%p)", mime));
198
199
if (!mime)
200
{
201
DEBUG_puts("7mimeFirstFilter: Returning NULL.");
202
return (NULL);
203
}
204
else
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
}
212
}
213
214
215
/*
216
* 'mimeFirstType()' - Get the first type in the MIME database.
217
*/
218
219
mime_type_t * /* O - Type or NULL */
220
mimeFirstType(mime_t *mime) /* I - MIME database */
221
{
222
DEBUG_printf(("6mimeFirstType(mime=%p)", mime));
223
224
if (!mime)
225
{
226
DEBUG_puts("7mimeFirstType: Returning NULL.");
227
return (NULL);
228
}
229
else
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
}
237
}
238
239
240
/*
241
* 'mimeLoad()' - Create a new MIME database from disk.
242
*
243
* This function uses @link mimeLoadFilters@ and @link mimeLoadTypes@ to
244
* create a MIME database from a single directory.
245
*/
246
247
mime_t * /* O - New MIME database */
248
mimeLoad(const char *pathname, /* I - Directory to load */
249
const char *filterpath) /* I - Directory to load */
250
{
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);
260
}
261
262
263
/*
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.
268
*/
269
270
mime_t * /* O - MIME database */
271
mimeLoadFilters(mime_t *mime, /* I - MIME database */
272
const char *pathname, /* I - Directory to load from */
273
const char *filterpath) /* I - Default filter program directory */
274
{
275
cups_dir_t *dir; /* Directory */
276
cups_dentry_t *dent; /* Directory entry */
277
char filename[1024]; /* Full filename of .convs file */
278
cups_array_t *filtercache; /* Filter cache */
279
280
281
DEBUG_printf(("mimeLoadFilters(mime=%p, pathname=\"%s\", filterpath=\"%s\")",
282
mime, pathname, filterpath));
283
284
/*
285
* Range check input...
286
*/
287
288
if (!mime || !pathname || !filterpath)
289
{
290
DEBUG_puts("1mimeLoadFilters: Bad arguments.");
291
return (mime);
292
}
293
294
/*
295
* Then open the directory specified by pathname...
296
*/
297
298
if ((dir = cupsDirOpen(pathname)) == NULL)
299
{
300
DEBUG_printf(("1mimeLoadFilters: Unable to open \"%s\": %s", pathname,
301
strerror(errno)));
302
_mimeError(mime, "Unable to open \"%s\": %s", pathname, strerror(errno));
303
return (mime);
304
}
305
306
/*
307
* Read all the .convs files...
308
*/
309
310
filtercache = cupsArrayNew((cups_array_func_t)mime_compare_fcache, NULL);
311
312
while ((dent = cupsDirRead(dir)) != NULL)
313
{
314
if (strlen(dent->filename) > 6 &&
315
!strcmp(dent->filename + strlen(dent->filename) - 6, ".convs"))
316
{
317
/*
318
* Load a mime.convs file...
319
*/
320
321
snprintf(filename, sizeof(filename), "%s/%s", pathname, dent->filename);
322
DEBUG_printf(("1mimeLoadFilters: Loading \"%s\".", filename));
323
mime_load_convs(mime, filename, filterpath, filtercache);
324
}
325
}
326
327
mime_delete_fcache(filtercache);
328
329
cupsDirClose(dir);
330
331
return (mime);
332
}
333
334
335
/*
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.
340
*/
341
342
mime_t * /* O - MIME database */
343
mimeLoadTypes(mime_t *mime, /* I - MIME database or @code NULL@ to create a new one */
344
const char *pathname) /* I - Directory to load from */
345
{
346
cups_dir_t *dir; /* Directory */
347
cups_dentry_t *dent; /* Directory entry */
348
char filename[1024]; /* Full filename of .types file */
349
350
351
DEBUG_printf(("mimeLoadTypes(mime=%p, pathname=\"%s\")", mime, pathname));
352
353
/*
354
* First open the directory specified by pathname...
355
*/
356
357
if ((dir = cupsDirOpen(pathname)) == NULL)
358
{
359
DEBUG_printf(("1mimeLoadTypes: Unable to open \"%s\": %s", pathname,
360
strerror(errno)));
361
DEBUG_printf(("1mimeLoadTypes: Returning %p.", mime));
362
_mimeError(mime, "Unable to open \"%s\": %s", pathname, strerror(errno));
363
return (mime);
364
}
365
366
/*
367
* If "mime" is NULL, make a new, empty database...
368
*/
369
370
if (!mime)
371
mime = mimeNew();
372
373
if (!mime)
374
{
375
cupsDirClose(dir);
376
DEBUG_puts("1mimeLoadTypes: Returning NULL.");
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);
394
DEBUG_printf(("1mimeLoadTypes: Loading \"%s\".", filename));
395
mime_load_types(mime, filename);
396
}
397
}
398
399
cupsDirClose(dir);
400
401
DEBUG_printf(("1mimeLoadTypes: Returning %p.", mime));
402
403
return (mime);
404
}
405
406
407
/*
408
* 'mimeNew()' - Create a new, empty MIME database.
409
*/
410
411
mime_t * /* O - MIME database */
412
mimeNew(void)
413
{
414
return ((mime_t *)calloc(1, sizeof(mime_t)));
415
}
416
417
418
/*
419
* 'mimeNextFilter()' - Get the next filter in the MIME database.
420
*/
421
422
mime_filter_t * /* O - Filter or NULL */
423
mimeNextFilter(mime_t *mime) /* I - MIME database */
424
{
425
DEBUG_printf(("6mimeNextFilter(mime=%p)", mime));
426
427
if (!mime)
428
{
429
DEBUG_puts("7mimeNextFilter: Returning NULL.");
430
return (NULL);
431
}
432
else
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
}
440
}
441
442
443
/*
444
* 'mimeNextType()' - Get the next type in the MIME database.
445
*/
446
447
mime_type_t * /* O - Type or NULL */
448
mimeNextType(mime_t *mime) /* I - MIME database */
449
{
450
DEBUG_printf(("6mimeNextType(mime=%p)", mime));
451
452
if (!mime)
453
{
454
DEBUG_puts("7mimeNextType: Returning NULL.");
455
return (NULL);
456
}
457
else
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
}
465
}
466
467
468
/*
469
* 'mimeNumFilters()' - Get the number of filters in a MIME database.
470
*/
471
472
int
473
mimeNumFilters(mime_t *mime) /* I - MIME database */
474
{
475
DEBUG_printf(("mimeNumFilters(mime=%p)", mime));
476
477
if (!mime)
478
{
479
DEBUG_puts("1mimeNumFilters: Returning 0.");
480
return (0);
481
}
482
else
483
{
484
DEBUG_printf(("1mimeNumFilters: Returning %d.",
485
cupsArrayCount(mime->filters)));
486
return (cupsArrayCount(mime->filters));
487
}
488
}
489
490
491
/*
492
* 'mimeNumTypes()' - Get the number of types in a MIME database.
493
*/
494
495
int
496
mimeNumTypes(mime_t *mime) /* I - MIME database */
497
{
498
DEBUG_printf(("mimeNumTypes(mime=%p)", mime));
499
500
if (!mime)
501
{
502
DEBUG_puts("1mimeNumTypes: Returning 0.");
503
return (0);
504
}
505
else
506
{
507
DEBUG_printf(("1mimeNumTypes: Returning %d.",
508
cupsArrayCount(mime->types)));
509
return (cupsArrayCount(mime->types));
510
}
511
}
512
513
514
/*
515
* 'mimeSetErrorCallback()' - Set the callback for error messages.
516
*/
517
518
void
519
mimeSetErrorCallback(
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
532
/*
533
* 'mime_add_fcache()' - Add a filter to the filter cache.
534
*/
535
536
static const char * /* O - Full path to filter or NULL */
537
mime_add_fcache(
538
cups_array_t *filtercache, /* I - Filter cache */
539
const char *name, /* I - Filter name */
540
const char *filterpath) /* I - Filter path */
541
{
542
_mime_fcache_t key, /* Search key */
543
*temp; /* New filter cache */
544
char path[1024]; /* Full path to filter */
545
546
547
DEBUG_printf(("2mime_add_fcache(filtercache=%p, name=\"%s\", "
548
"filterpath=\"%s\")", filtercache, name, filterpath));
549
550
key.name = (char *)name;
551
if ((temp = (_mime_fcache_t *)cupsArrayFind(filtercache, &key)) != NULL)
552
{
553
DEBUG_printf(("3mime_add_fcache: Returning \"%s\".", temp->path));
554
return (temp->path);
555
}
556
557
if ((temp = calloc(1, sizeof(_mime_fcache_t))) == NULL)
558
{
559
DEBUG_puts("3mime_add_fcache: Returning NULL.");
560
return (NULL);
561
}
562
563
temp->name = strdup(name);
564
565
if (cupsFileFind(name, filterpath, 1, path, sizeof(path)))
566
temp->path = strdup(path);
567
568
cupsArrayAdd(filtercache, temp);
569
570
DEBUG_printf(("3mime_add_fcache: Returning \"%s\".", temp->path));
571
return (temp->path);
572
}
573
574
575
/*
576
* 'mime_compare_fcache()' - Compare two filter cache entries.
577
*/
578
579
static int /* O - Result of comparison */
580
mime_compare_fcache(_mime_fcache_t *a, /* I - First entry */
581
_mime_fcache_t *b) /* I - Second entry */
582
{
583
return (strcmp(a->name, b->name));
584
}
585
586
587
/*
588
* 'mime_delete_fcache()' - Free all memory used by the filter cache.
589
*/
590
591
static void
592
mime_delete_fcache(
593
cups_array_t *filtercache) /* I - Filter cache */
594
{
595
_mime_fcache_t *current; /* Current cache entry */
596
597
598
DEBUG_printf(("2mime_delete_fcache(filtercache=%p)", filtercache));
599
600
for (current = (_mime_fcache_t *)cupsArrayFirst(filtercache);
601
current;
602
current = (_mime_fcache_t *)cupsArrayNext(filtercache))
603
{
604
free(current->name);
605
606
if (current->path)
607
free(current->path);
608
609
free(current);
610
}
611
612
cupsArrayDelete(filtercache);
613
}
614
615
616
/*
617
* 'mime_delete_rules()' - Free all memory for the given rule tree.
618
*/
619
620
static void
621
mime_delete_rules(mime_magic_t *rules) /* I - Rules to free */
622
{
623
mime_magic_t *next; /* Next rule to free */
624
625
626
DEBUG_printf(("2mime_delete_rules(rules=%p)", rules));
627
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)
637
mime_delete_rules(rules->child);
638
639
if (rules->op == MIME_MAGIC_REGEX)
640
regfree(&(rules->value.rev));
641
642
free(rules);
643
rules = next;
644
}
645
}
646
647
648
/*
649
* 'mime_load_convs()' - Load a xyz.convs file.
650
*/
651
652
static void
653
mime_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 */
658
{
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 */
666
mime_type_t *temptype, /* MIME type looping var */
667
*dsttype; /* Destination MIME type */
668
int cost; /* Cost of filter */
669
670
671
DEBUG_printf(("2mime_load_convs(mime=%p, filename=\"%s\", filterpath=\"%s\", "
672
"filtercache=%p)", mime, filename, filterpath, filtercache));
673
674
/*
675
* First try to open the file...
676
*/
677
678
if ((fp = cupsFileOpen(filename, "r")) == NULL)
679
{
680
DEBUG_printf(("3mime_load_convs: Unable to open \"%s\": %s", filename,
681
strerror(errno)));
682
_mimeError(mime, "Unable to open \"%s\": %s", filename, strerror(errno));
683
return;
684
}
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)
724
*temp++ = (char)tolower(*lineptr++ & 255);
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)
736
*temp++ = (char)tolower(*lineptr++ & 255);
737
738
*temp = '\0';
739
740
if (*lineptr == '\0' || *lineptr == '\n')
741
continue;
742
743
if ((dsttype = mimeType(mime, super, type)) == NULL)
744
{
745
DEBUG_printf(("3mime_load_convs: Destination type %s/%s not found.",
746
super, type));
747
continue;
748
}
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
772
if (strcmp(filter, "-"))
773
{
774
/*
775
* Verify that the filter exists and is executable...
776
*/
777
778
if (!mime_add_fcache(filtercache, filter, filterpath))
779
{
780
DEBUG_printf(("mime_load_convs: Filter %s not found in %s.", filter,
781
filterpath));
782
_mimeError(mime, "Filter \"%s\" not found.", filter);
783
continue;
784
}
785
}
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)
797
*temp++ = (char)tolower(*lineptr++ & 255);
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)
809
*temp++ = (char)tolower(*lineptr++ & 255);
810
811
*temp = '\0';
812
813
if (!strcmp(super, "*") && !strcmp(type, "*"))
814
{
815
/*
816
* Force * / * to be "application/octet-stream"...
817
*/
818
819
strlcpy(super, "application", sizeof(super));
820
strlcpy(type, "octet-stream", sizeof(type));
821
}
822
823
/*
824
* Add the filter to the MIME database, supporting wildcards as needed...
825
*/
826
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);
833
}
834
835
cupsFileClose(fp);
836
}
837
838
839
/*
840
* 'mime_load_types()' - Load a xyz.types file.
841
*/
842
843
static void
844
mime_load_types(mime_t *mime, /* I - MIME database */
845
const char *filename) /* I - Types file to load */
846
{
847
cups_file_t *fp; /* Types file */
848
size_t linelen; /* Length of line */
849
char line[32768], /* Input line from file */
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 */
855
856
857
DEBUG_printf(("2mime_load_types(mime=%p, filename=\"%s\")", mime, filename));
858
859
/*
860
* First try to open the file...
861
*/
862
863
if ((fp = cupsFileOpen(filename, "r")) == NULL)
864
{
865
DEBUG_printf(("3mime_load_types: Unable to open \"%s\": %s", filename,
866
strerror(errno)));
867
_mimeError(mime, "Unable to open \"%s\": %s", filename, strerror(errno));
868
return;
869
}
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)
876
{
877
/*
878
* Skip blank lines and lines starting with a #...
879
*/
880
881
if (!line[0] || line[0] == '#')
882
continue;
883
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)
910
*temp++ = (char)tolower(*lineptr++ & 255);
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)
922
*temp++ = (char)tolower(*lineptr++ & 255);
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);
932
}
933
934
cupsFileClose(fp);
935
}
936
937