]>
Commit | Line | Data |
---|---|---|
1 | /* | |
2 | * "$Id$" | |
3 | * | |
4 | * MIME test program for CUPS. | |
5 | * | |
6 | * Copyright 2007-2013 by Apple Inc. | |
7 | * Copyright 1997-2006 by Easy Software Products, all rights reserved. | |
8 | * | |
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/". | |
14 | * | |
15 | * Contents: | |
16 | * | |
17 | * main() - Main entry for the test program. | |
18 | * add_ppd_filter() - Add a printer filter from a PPD. | |
19 | * add_ppd_filters() - Add all filters from a PPD. | |
20 | * print_rules() - Print the rules for a file type... | |
21 | * type_dir() - Show the MIME types for a given directory. | |
22 | */ | |
23 | ||
24 | /* | |
25 | * Include necessary headers... | |
26 | */ | |
27 | ||
28 | #include <cups/string-private.h> | |
29 | #include <cups/dir.h> | |
30 | #include <cups/debug-private.h> | |
31 | #include <cups/ppd-private.h> | |
32 | #include "mime.h" | |
33 | ||
34 | ||
35 | /* | |
36 | * Local functions... | |
37 | */ | |
38 | ||
39 | static void add_ppd_filter(mime_t *mime, mime_type_t *filtertype, | |
40 | const char *filter); | |
41 | static void add_ppd_filters(mime_t *mime, ppd_file_t *ppd); | |
42 | static void print_rules(mime_magic_t *rules); | |
43 | static void type_dir(mime_t *mime, const char *dirname); | |
44 | ||
45 | ||
46 | /* | |
47 | * 'main()' - Main entry for the test program. | |
48 | */ | |
49 | ||
50 | int /* O - Exit status */ | |
51 | main(int argc, /* I - Number of command-line args */ | |
52 | char *argv[]) /* I - Command-line arguments */ | |
53 | { | |
54 | int i; /* Looping vars */ | |
55 | const char *filter_path; /* Filter path */ | |
56 | char super[MIME_MAX_SUPER], /* Super-type name */ | |
57 | type[MIME_MAX_TYPE]; /* Type name */ | |
58 | int compression; /* Compression of file */ | |
59 | int cost; /* Cost of filters */ | |
60 | mime_t *mime; /* MIME database */ | |
61 | mime_type_t *src, /* Source type */ | |
62 | *dst; /* Destination type */ | |
63 | struct stat srcinfo; /* Source information */ | |
64 | ppd_file_t *ppd; /* PPD file */ | |
65 | cups_array_t *filters; /* Filters for the file */ | |
66 | mime_filter_t *filter; /* Current filter */ | |
67 | ||
68 | ||
69 | mime = NULL; | |
70 | src = NULL; | |
71 | dst = NULL; | |
72 | ppd = NULL; | |
73 | filter_path = "../filter:" CUPS_SERVERBIN "/filter"; | |
74 | ||
75 | srcinfo.st_size = 0; | |
76 | ||
77 | for (i = 1; i < argc; i ++) | |
78 | if (!strcmp(argv[i], "-d")) | |
79 | { | |
80 | i ++; | |
81 | ||
82 | if (i < argc) | |
83 | { | |
84 | mime = mimeLoad(argv[i], filter_path); | |
85 | ||
86 | if (ppd) | |
87 | add_ppd_filters(mime, ppd); | |
88 | } | |
89 | } | |
90 | else if (!strcmp(argv[i], "-f")) | |
91 | { | |
92 | i ++; | |
93 | ||
94 | if (i < argc) | |
95 | filter_path = argv[i]; | |
96 | } | |
97 | else if (!strcmp(argv[i], "-p")) | |
98 | { | |
99 | i ++; | |
100 | ||
101 | if (i < argc) | |
102 | { | |
103 | ppd = ppdOpenFile(argv[i]); | |
104 | ||
105 | if (mime) | |
106 | add_ppd_filters(mime, ppd); | |
107 | } | |
108 | } | |
109 | else if (!src) | |
110 | { | |
111 | if (!mime) | |
112 | mime = mimeLoad("../conf", filter_path); | |
113 | ||
114 | if (ppd) | |
115 | add_ppd_filters(mime, ppd); | |
116 | ||
117 | src = mimeFileType(mime, argv[i], NULL, &compression); | |
118 | stat(argv[i], &srcinfo); | |
119 | ||
120 | if (src) | |
121 | printf("%s: %s/%s%s\n", argv[i], src->super, src->type, | |
122 | compression ? " (gzipped)" : ""); | |
123 | else if ((src = mimeType(mime, "application", "octet-stream")) != NULL) | |
124 | printf("%s: application/octet-stream\n", argv[i]); | |
125 | else | |
126 | { | |
127 | printf("%s: unknown\n", argv[i]); | |
128 | if (mime) | |
129 | mimeDelete(mime); | |
130 | return (1); | |
131 | } | |
132 | } | |
133 | else | |
134 | { | |
135 | sscanf(argv[i], "%15[^/]/%255s", super, type); | |
136 | dst = mimeType(mime, super, type); | |
137 | ||
138 | filters = mimeFilter2(mime, src, srcinfo.st_size, dst, &cost); | |
139 | ||
140 | if (!filters) | |
141 | { | |
142 | printf("No filters to convert from %s/%s to %s.\n", src->super, | |
143 | src->type, argv[i]); | |
144 | } | |
145 | else | |
146 | { | |
147 | int first = 1; /* First filter shown? */ | |
148 | ||
149 | printf("Filter cost = %d\n", cost); | |
150 | ||
151 | for (filter = (mime_filter_t *)cupsArrayFirst(filters); | |
152 | filter; | |
153 | filter = (mime_filter_t *)cupsArrayNext(filters)) | |
154 | { | |
155 | if (!strcmp(filter->filter, "-")) | |
156 | continue; | |
157 | ||
158 | if (first) | |
159 | { | |
160 | first = 0; | |
161 | fputs(filter->filter, stdout); | |
162 | } | |
163 | else | |
164 | printf(" | %s", filter->filter); | |
165 | } | |
166 | ||
167 | putchar('\n'); | |
168 | ||
169 | cupsArrayDelete(filters); | |
170 | } | |
171 | } | |
172 | ||
173 | if (!mime) | |
174 | { | |
175 | mime = mimeLoad("../conf", filter_path); | |
176 | if (ppd) | |
177 | add_ppd_filters(mime, ppd); | |
178 | } | |
179 | ||
180 | if (!src) | |
181 | { | |
182 | puts("MIME database types:"); | |
183 | for (src = mimeFirstType(mime); src; src = mimeNextType(mime)) | |
184 | { | |
185 | printf("\t%s/%s (%d):\n", src->super, src->type, src->priority); | |
186 | print_rules(src->rules); | |
187 | puts(""); | |
188 | } | |
189 | ||
190 | puts(""); | |
191 | ||
192 | puts("MIME database filters:"); | |
193 | for (filter = mimeFirstFilter(mime); filter; filter = mimeNextFilter(mime)) | |
194 | printf("\t%s/%s to %s/%s: %s (%d)\n", | |
195 | filter->src->super, filter->src->type, | |
196 | filter->dst->super, filter->dst->type, | |
197 | filter->filter, filter->cost); | |
198 | ||
199 | type_dir(mime, "../doc"); | |
200 | } | |
201 | ||
202 | return (0); | |
203 | } | |
204 | ||
205 | ||
206 | /* | |
207 | * 'add_printer_filter()' - Add a printer filter from a PPD. | |
208 | */ | |
209 | ||
210 | static void | |
211 | add_ppd_filter(mime_t *mime, /* I - MIME database */ | |
212 | mime_type_t *filtertype, /* I - Filter or prefilter MIME type */ | |
213 | const char *filter) /* I - Filter to add */ | |
214 | { | |
215 | char super[MIME_MAX_SUPER], /* Super-type for filter */ | |
216 | type[MIME_MAX_TYPE], /* Type for filter */ | |
217 | dsuper[MIME_MAX_SUPER], /* Destination super-type for filter */ | |
218 | dtype[MIME_MAX_TYPE], /* Destination type for filter */ | |
219 | dest[MIME_MAX_SUPER + MIME_MAX_TYPE + 2], | |
220 | /* Destination super/type */ | |
221 | program[1024]; /* Program/filter name */ | |
222 | int cost; /* Cost of filter */ | |
223 | size_t maxsize = 0; /* Maximum supported file size */ | |
224 | mime_type_t *temptype, /* MIME type looping var */ | |
225 | *desttype; /* Destination MIME type */ | |
226 | mime_filter_t *filterptr; /* MIME filter */ | |
227 | ||
228 | ||
229 | DEBUG_printf(("add_ppd_filter(mime=%p, filtertype=%p(%s/%s), filter=\"%s\")", | |
230 | mime, filtertype, filtertype->super, filtertype->type, filter)); | |
231 | ||
232 | /* | |
233 | * Parse the filter string; it should be in one of the following formats: | |
234 | * | |
235 | * source/type cost program | |
236 | * source/type cost maxsize(nnnn) program | |
237 | * source/type dest/type cost program | |
238 | * source/type dest/type cost maxsize(nnnn) program | |
239 | */ | |
240 | ||
241 | if (sscanf(filter, "%15[^/]/%255s%*[ \t]%15[^/]/%255s%d%*[ \t]%1023[^\n]", | |
242 | super, type, dsuper, dtype, &cost, program) == 6) | |
243 | { | |
244 | snprintf(dest, sizeof(dest), "test/%s/%s", dsuper, dtype); | |
245 | ||
246 | if ((desttype = mimeType(mime, "printer", dest)) == NULL) | |
247 | desttype = mimeAddType(mime, "printer", dest); | |
248 | } | |
249 | else | |
250 | { | |
251 | if (sscanf(filter, "%15[^/]/%255s%d%*[ \t]%1023[^\n]", super, type, &cost, | |
252 | program) == 4) | |
253 | { | |
254 | desttype = filtertype; | |
255 | } | |
256 | else | |
257 | { | |
258 | printf("testmime: Invalid filter string \"%s\".\n", filter); | |
259 | return; | |
260 | } | |
261 | } | |
262 | ||
263 | if (!strncmp(program, "maxsize(", 8)) | |
264 | { | |
265 | char *ptr; /* Pointer into maxsize(nnnn) program */ | |
266 | ||
267 | maxsize = strtoll(program + 8, &ptr, 10); | |
268 | ||
269 | if (*ptr != ')') | |
270 | { | |
271 | printf("testmime: Invalid filter string \"%s\".\n", filter); | |
272 | return; | |
273 | } | |
274 | ||
275 | ptr ++; | |
276 | while (_cups_isspace(*ptr)) | |
277 | ptr ++; | |
278 | ||
279 | _cups_strcpy(program, ptr); | |
280 | } | |
281 | ||
282 | /* | |
283 | * Add the filter to the MIME database, supporting wildcards as needed... | |
284 | */ | |
285 | ||
286 | for (temptype = mimeFirstType(mime); | |
287 | temptype; | |
288 | temptype = mimeNextType(mime)) | |
289 | if (((super[0] == '*' && _cups_strcasecmp(temptype->super, "printer")) || | |
290 | !_cups_strcasecmp(temptype->super, super)) && | |
291 | (type[0] == '*' || !_cups_strcasecmp(temptype->type, type))) | |
292 | { | |
293 | if (desttype != filtertype) | |
294 | { | |
295 | DEBUG_printf(("add_ppd_filter: Adding filter %s/%s %s/%s %d %s", | |
296 | temptype->super, temptype->type, desttype->super, | |
297 | desttype->type, cost, program)); | |
298 | filterptr = mimeAddFilter(mime, temptype, desttype, cost, program); | |
299 | ||
300 | if (!mimeFilterLookup(mime, desttype, filtertype)) | |
301 | { | |
302 | DEBUG_printf(("add_printer_filter: Adding filter %s/%s %s/%s 0 -", | |
303 | desttype->super, desttype->type, filtertype->super, | |
304 | filtertype->type)); | |
305 | mimeAddFilter(mime, desttype, filtertype, 0, "-"); | |
306 | } | |
307 | } | |
308 | else | |
309 | { | |
310 | DEBUG_printf(("add_printer_filter: Adding filter %s/%s %s/%s %d %s", | |
311 | temptype->super, temptype->type, filtertype->super, | |
312 | filtertype->type, cost, program)); | |
313 | filterptr = mimeAddFilter(mime, temptype, filtertype, cost, program); | |
314 | } | |
315 | ||
316 | if (filterptr) | |
317 | filterptr->maxsize = maxsize; | |
318 | } | |
319 | } | |
320 | ||
321 | ||
322 | /* | |
323 | * 'add_ppd_filters()' - Add all filters from a PPD. | |
324 | */ | |
325 | ||
326 | static void | |
327 | add_ppd_filters(mime_t *mime, /* I - MIME database */ | |
328 | ppd_file_t *ppd) /* I - PPD file */ | |
329 | { | |
330 | _ppd_cache_t *pc; /* Cache data for PPD */ | |
331 | const char *value; /* Filter definition value */ | |
332 | mime_type_t *filter, /* Filter type */ | |
333 | *prefilter; /* Pre-filter type */ | |
334 | ||
335 | ||
336 | pc = _ppdCacheCreateWithPPD(ppd); | |
337 | if (!pc) | |
338 | return; | |
339 | ||
340 | filter = mimeAddType(mime, "printer", "test"); | |
341 | ||
342 | if (pc->filters) | |
343 | { | |
344 | for (value = (const char *)cupsArrayFirst(pc->filters); | |
345 | value; | |
346 | value = (const char *)cupsArrayNext(pc->filters)) | |
347 | add_ppd_filter(mime, filter, value); | |
348 | } | |
349 | else | |
350 | { | |
351 | add_ppd_filter(mime, filter, "application/vnd.cups-raw 0 -"); | |
352 | add_ppd_filter(mime, filter, "application/vnd.cups-postscript 0 -"); | |
353 | } | |
354 | ||
355 | if (pc->prefilters) | |
356 | { | |
357 | prefilter = mimeAddType(mime, "prefilter", "test"); | |
358 | ||
359 | for (value = (const char *)cupsArrayFirst(pc->prefilters); | |
360 | value; | |
361 | value = (const char *)cupsArrayNext(pc->prefilters)) | |
362 | add_ppd_filter(mime, prefilter, value); | |
363 | } | |
364 | } | |
365 | ||
366 | ||
367 | /* | |
368 | * 'print_rules()' - Print the rules for a file type... | |
369 | */ | |
370 | ||
371 | static void | |
372 | print_rules(mime_magic_t *rules) /* I - Rules to print */ | |
373 | { | |
374 | int i; /* Looping var */ | |
375 | static char indent[255] = "\t"; /* Indentation for rules */ | |
376 | ||
377 | ||
378 | if (rules == NULL) | |
379 | return; | |
380 | ||
381 | while (rules != NULL) | |
382 | { | |
383 | printf("%s[%p] ", indent, rules); | |
384 | ||
385 | if (rules->invert) | |
386 | printf("NOT "); | |
387 | ||
388 | switch (rules->op) | |
389 | { | |
390 | case MIME_MAGIC_MATCH : | |
391 | printf("match(%s)", rules->value.matchv); | |
392 | break; | |
393 | case MIME_MAGIC_LOCALE : | |
394 | printf("locale(%s)", rules->value.localev); | |
395 | break; | |
396 | case MIME_MAGIC_ASCII : | |
397 | printf("ascii(%d,%d)", rules->offset, rules->length); | |
398 | break; | |
399 | case MIME_MAGIC_PRINTABLE : | |
400 | printf("printable(%d,%d)", rules->offset, rules->length); | |
401 | break; | |
402 | case MIME_MAGIC_STRING : | |
403 | printf("string(%d,", rules->offset); | |
404 | for (i = 0; i < rules->length; i ++) | |
405 | if (rules->value.stringv[i] < ' ' || | |
406 | rules->value.stringv[i] > 126) | |
407 | printf("<%02X>", rules->value.stringv[i]); | |
408 | else | |
409 | putchar(rules->value.stringv[i]); | |
410 | putchar(')'); | |
411 | break; | |
412 | case MIME_MAGIC_CHAR : | |
413 | printf("char(%d,%d)", rules->offset, rules->value.charv); | |
414 | break; | |
415 | case MIME_MAGIC_SHORT : | |
416 | printf("short(%d,%d)", rules->offset, rules->value.shortv); | |
417 | break; | |
418 | case MIME_MAGIC_INT : | |
419 | printf("int(%d,%d)", rules->offset, rules->value.intv); | |
420 | break; | |
421 | case MIME_MAGIC_CONTAINS : | |
422 | printf("contains(%d,%d,", rules->offset, rules->region); | |
423 | for (i = 0; i < rules->length; i ++) | |
424 | if (rules->value.stringv[i] < ' ' || | |
425 | rules->value.stringv[i] > 126) | |
426 | printf("<%02X>", rules->value.stringv[i]); | |
427 | else | |
428 | putchar(rules->value.stringv[i]); | |
429 | putchar(')'); | |
430 | break; | |
431 | default : | |
432 | break; | |
433 | } | |
434 | ||
435 | if (rules->child != NULL) | |
436 | { | |
437 | if (rules->op == MIME_MAGIC_OR) | |
438 | puts("OR ("); | |
439 | else | |
440 | puts("AND ("); | |
441 | ||
442 | strcat(indent, "\t"); | |
443 | print_rules(rules->child); | |
444 | indent[strlen(indent) - 1] = '\0'; | |
445 | printf("%s)\n", indent); | |
446 | } | |
447 | else | |
448 | putchar('\n'); | |
449 | ||
450 | rules = rules->next; | |
451 | } | |
452 | } | |
453 | ||
454 | ||
455 | /* | |
456 | * 'type_dir()' - Show the MIME types for a given directory. | |
457 | */ | |
458 | ||
459 | static void | |
460 | type_dir(mime_t *mime, /* I - MIME database */ | |
461 | const char *dirname) /* I - Directory */ | |
462 | { | |
463 | cups_dir_t *dir; /* Directory */ | |
464 | cups_dentry_t *dent; /* Directory entry */ | |
465 | char filename[1024]; /* File to type */ | |
466 | mime_type_t *filetype; /* File type */ | |
467 | int compression; /* Compressed file? */ | |
468 | mime_type_t *pstype; /* application/vnd.cups-postscript */ | |
469 | cups_array_t *filters; /* Filters to pstype */ | |
470 | mime_filter_t *filter; /* Current filter */ | |
471 | int cost; /* Filter cost */ | |
472 | ||
473 | ||
474 | dir = cupsDirOpen(dirname); | |
475 | if (!dir) | |
476 | return; | |
477 | ||
478 | pstype = mimeType(mime, "application", "vnd.cups-postscript"); | |
479 | ||
480 | while ((dent = cupsDirRead(dir)) != NULL) | |
481 | { | |
482 | if (dent->filename[0] == '.') | |
483 | continue; | |
484 | ||
485 | snprintf(filename, sizeof(filename), "%s/%s", dirname, dent->filename); | |
486 | ||
487 | if (S_ISDIR(dent->fileinfo.st_mode)) | |
488 | type_dir(mime, filename); | |
489 | ||
490 | if (!S_ISREG(dent->fileinfo.st_mode)) | |
491 | continue; | |
492 | ||
493 | filetype = mimeFileType(mime, filename, NULL, &compression); | |
494 | ||
495 | if (filetype) | |
496 | { | |
497 | printf("%s: %s/%s%s\n", filename, filetype->super, filetype->type, | |
498 | compression ? " (compressed)" : ""); | |
499 | ||
500 | filters = mimeFilter(mime, filetype, pstype, &cost); | |
501 | ||
502 | if (!filters) | |
503 | puts(" No filters to convert application/vnd.cups-postscript."); | |
504 | else | |
505 | { | |
506 | printf(" Filter cost = %d\n", cost); | |
507 | ||
508 | filter = (mime_filter_t *)cupsArrayFirst(filters); | |
509 | printf(" %s", filter->filter); | |
510 | ||
511 | for (filter = (mime_filter_t *)cupsArrayNext(filters); | |
512 | filter; | |
513 | filter = (mime_filter_t *)cupsArrayNext(filters)) | |
514 | printf(" | %s", filter->filter); | |
515 | ||
516 | putchar('\n'); | |
517 | ||
518 | cupsArrayDelete(filters); | |
519 | } | |
520 | } | |
521 | else | |
522 | printf("%s: unknown%s\n", filename, compression ? " (compressed)" : ""); | |
523 | } | |
524 | ||
525 | cupsDirClose(dir); | |
526 | } | |
527 | ||
528 | ||
529 | /* | |
530 | * End of "$Id$". | |
531 | */ |