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