]>
Commit | Line | Data |
---|---|---|
79df52e3 | 1 | /* |
8784b6a6 | 2 | * "$Id: mime.c,v 1.13 1999/06/18 18:36:10 mike Exp $" |
79df52e3 | 3 | * |
0b74af7d | 4 | * MIME database file routines for the Common UNIX Printing System (CUPS). |
79df52e3 | 5 | * |
3a193f5e | 6 | * Copyright 1997-1999 by Easy Software Products, all rights reserved. |
79df52e3 | 7 | * |
8 | * These coded instructions, statements, and computer programs are the | |
9 | * property of Easy Software Products and are protected by Federal | |
10 | * copyright law. Distribution and use rights are outlined in the file | |
11 | * "LICENSE.txt" which should have been included with this file. If this | |
12 | * file is missing or damaged please contact Easy Software Products | |
13 | * at: | |
14 | * | |
15 | * Attn: CUPS Licensing Information | |
16 | * Easy Software Products | |
8784b6a6 | 17 | * 44141 Airport View Drive, Suite 204 |
79df52e3 | 18 | * Hollywood, Maryland 20636-3111 USA |
19 | * | |
20 | * Voice: (301) 373-9603 | |
21 | * EMail: cups-info@cups.org | |
22 | * WWW: http://www.cups.org | |
23 | * | |
24 | * Contents: | |
25 | * | |
0b74af7d | 26 | * mimeDelete() - Delete (free) a MIME database. |
27 | * mimeMerge() - Merge a MIME database from disk with the current one. | |
28 | * mimeNew() - Create a new, empty MIME database. | |
29 | * load_types() - Load a xyz.types file... | |
30 | * delete_rules() - Free all memory for the given rule tree. | |
31 | * load_convs() - Load a xyz.convs file... | |
79df52e3 | 32 | * |
33 | * Revision History: | |
34 | * | |
35 | * $Log: mime.c,v $ | |
8784b6a6 | 36 | * Revision 1.13 1999/06/18 18:36:10 mike |
37 | * Fixed address to 44141 Airport View Drive... | |
38 | * | |
42d48bd2 | 39 | * Revision 1.12 1999/04/21 21:19:33 mike |
40 | * Changes for HP-UX. | |
41 | * | |
8e1166b9 | 42 | * Revision 1.11 1999/04/21 19:31:29 mike |
43 | * Changed the directory header stuff to use the autoconf-recommended | |
44 | * sequence of #ifdef's. | |
45 | * | |
46 | * Changed the language routines to look for the LOCALEDIR environment | |
47 | * variable, and if it is not defined to use the LOCALEDIR string defined | |
48 | * in config.h. | |
49 | * | |
e8fda7b9 | 50 | * Revision 1.10 1999/03/01 20:51:53 mike |
51 | * Code cleanup - removed extraneous semi-colons... | |
52 | * | |
5081f753 | 53 | * Revision 1.9 1999/02/26 22:00:51 mike |
54 | * Added more debug statements. | |
55 | * | |
56 | * Fixed bugs in cupsPrintFile() - wasn't setting the IPP_TAG_MIMETYPE | |
57 | * value tag for the file type. | |
58 | * | |
59 | * Updated conversion filter code to handle wildcards for super-type. | |
60 | * | |
aaa5608c | 61 | * Revision 1.8 1999/02/20 16:04:38 mike |
62 | * Updated mime.c to scan directories under WIN32. | |
63 | * | |
64 | * Fixed some compiler warnings under WIN32. | |
65 | * | |
66 | * Updated VC++ project files. | |
67 | * | |
68 | * Updated mime.types and mime.convs files for actual registered | |
69 | * MIME type names. | |
70 | * | |
3b960317 | 71 | * Revision 1.7 1999/02/05 17:40:53 mike |
72 | * Added IPP client read/write code. | |
73 | * | |
74 | * Added string functions missing from some UNIXs. | |
75 | * | |
76 | * Added option parsing functions. | |
77 | * | |
78 | * Added IPP convenience functions (not implemented yet). | |
79 | * | |
80 | * Updated source files to use local string.h as needed (for | |
81 | * missing string functions) | |
82 | * | |
3d234d4a | 83 | * Revision 1.6 1999/02/01 22:08:39 mike |
84 | * Restored original directory-scanning functionality of mimeLoad(). | |
2456b740 | 85 | * |
8c1333e2 | 86 | * Revision 1.4 1999/01/27 18:31:56 mike |
87 | * Updated PPD routines to handle emulations and patch files. | |
88 | * | |
89 | * Added DSC comments to emit output as appropriate. | |
90 | * | |
3a193f5e | 91 | * Revision 1.3 1999/01/24 14:18:43 mike |
92 | * Check-in prior to CVS use. | |
93 | * | |
0b74af7d | 94 | * Revision 1.2 1998/08/06 14:38:38 mike |
95 | * Finished coding and testing for CUPS 1.0. | |
96 | * | |
79df52e3 | 97 | * Revision 1.1 1998/06/11 20:50:53 mike |
98 | * Initial revision | |
79df52e3 | 99 | */ |
100 | ||
101 | /* | |
102 | * Include necessary headers... | |
103 | */ | |
104 | ||
3b960317 | 105 | #include <stdio.h> |
106 | #include <stdlib.h> | |
107 | #include <ctype.h> | |
108 | ||
109 | #include "string.h" | |
0b74af7d | 110 | #include "mime.h" |
3d234d4a | 111 | |
aaa5608c | 112 | #if defined(WIN32) || defined(__EMX__) |
113 | # include <windows.h> | |
8e1166b9 | 114 | #elif HAVE_DIRENT_H |
3d234d4a | 115 | # include <dirent.h> |
116 | typedef struct dirent DIRENT; | |
42d48bd2 | 117 | # define NAMLEN(dirent) strlen((dirent)->d_name) |
8e1166b9 | 118 | #else |
119 | # if HAVE_SYS_NDIR_H | |
120 | # include <sys/ndir.h> | |
121 | # endif | |
122 | # if HAVE_SYS_DIR_H | |
123 | # include <sys/dir.h> | |
124 | # endif | |
125 | # if HAVE_NDIR_H | |
126 | # include <ndir.h> | |
127 | # endif | |
128 | typedef struct direct DIRENT; | |
42d48bd2 | 129 | # define NAMLEN(dirent) (dirent)->d_namlen |
8e1166b9 | 130 | #endif |
0b74af7d | 131 | |
132 | ||
133 | /* | |
134 | * Local functions... | |
135 | */ | |
136 | ||
137 | static void load_types(mime_t *mime, char *filename); | |
138 | static void load_convs(mime_t *mime, char *filename); | |
139 | static void delete_rules(mime_magic_t *rules); | |
140 | ||
141 | ||
142 | /* | |
143 | * 'mimeDelete()' - Delete (free) a MIME database. | |
144 | */ | |
145 | ||
146 | void | |
147 | mimeDelete(mime_t *mime) /* I - MIME database */ | |
148 | { | |
149 | int i; /* Looping var */ | |
150 | ||
151 | ||
152 | if (mime == NULL) | |
153 | return; | |
154 | ||
155 | /* | |
156 | * Loop through the file types and delete any rules... | |
157 | */ | |
158 | ||
159 | for (i = 0; i < mime->num_types; i ++) | |
160 | { | |
161 | delete_rules(mime->types[i]->rules); | |
162 | free(mime->types[i]); | |
e8fda7b9 | 163 | } |
0b74af7d | 164 | |
165 | /* | |
166 | * Free the types and filters arrays, and then the MIME database structure. | |
167 | */ | |
168 | ||
169 | free(mime->types); | |
170 | free(mime->filters); | |
171 | free(mime); | |
172 | } | |
173 | ||
174 | ||
175 | /* | |
176 | * 'mimeMerge()' - Merge a MIME database from disk with the current one. | |
177 | */ | |
178 | ||
179 | mime_t * /* O - Updated MIME database */ | |
180 | mimeMerge(mime_t *mime, /* I - MIME database to add to */ | |
181 | char *pathname) /* I - Directory to load */ | |
182 | { | |
aaa5608c | 183 | #if defined(WIN32) || defined(__EMX__) |
184 | HANDLE dir; /* Directory handle */ | |
185 | WIN32_FIND_DATA dent; /* Directory entry */ | |
186 | char filename[1024], /* Full filename of types/converts file */ | |
187 | *pathsep; /* Last character in path */ | |
188 | ||
189 | ||
190 | /* | |
191 | * First open the directory specified by pathname... Return NULL if nothing | |
192 | * was read or if the pathname is NULL... | |
193 | */ | |
194 | ||
195 | if (pathname == NULL) | |
196 | return (NULL); | |
197 | ||
198 | strcpy(filename, pathname); | |
199 | pathsep = filename + strlen(filename); | |
200 | if (pathsep == filename || | |
201 | (pathsep[-1] != '/' && pathsep[-1] != '\\')) | |
202 | { | |
203 | strcpy(pathsep, "/"); | |
204 | pathsep ++; | |
205 | } | |
206 | ||
207 | strcpy(pathsep, "*.types"); | |
208 | ||
209 | if ((dir = FindFirstFile(filename, &dent)) == 0) | |
210 | return (NULL); | |
211 | ||
212 | /* | |
213 | * If "mime" is NULL, make a new, blank database... | |
214 | */ | |
215 | ||
216 | if (mime == NULL) | |
217 | if ((mime = mimeNew()) == NULL) | |
218 | return (NULL); | |
219 | ||
220 | /* | |
221 | * Read all the .types files... | |
222 | */ | |
223 | ||
224 | do | |
225 | { | |
226 | /* | |
227 | * Load a mime.types file... | |
228 | */ | |
229 | ||
230 | strcpy(pathsep, dent.cFileName); | |
231 | load_types(mime, filename); | |
232 | } | |
233 | while (FindNextFile(dir, &dent)); | |
234 | ||
235 | FindClose(dir); | |
236 | ||
237 | /* | |
238 | * Read all the .convs files... | |
239 | */ | |
240 | ||
241 | strcpy(pathsep, "*.convs"); | |
242 | ||
243 | if ((dir = FindFirstFile(filename, &dent)) == 0) | |
244 | return (mime); | |
245 | ||
246 | do | |
247 | { | |
248 | /* | |
249 | * Load a mime.convs file... | |
250 | */ | |
251 | ||
252 | strcpy(pathsep, dent.cFileName); | |
253 | load_convs(mime, filename); | |
254 | } | |
255 | while (FindNextFile(dir, &dent)); | |
256 | ||
257 | FindClose(dir); | |
258 | ||
259 | return (mime); | |
260 | #else | |
3d234d4a | 261 | DIR *dir; /* Directory */ |
262 | DIRENT *dent; /* Directory entry */ | |
0b74af7d | 263 | char filename[1024]; /* Full filename of types/converts file */ |
264 | ||
265 | ||
3d234d4a | 266 | /* |
267 | * First open the directory specified by pathname... Return NULL if nothing | |
268 | * was read or if the pathname is NULL... | |
269 | */ | |
270 | ||
0b74af7d | 271 | if (pathname == NULL) |
272 | return (NULL); | |
273 | ||
3d234d4a | 274 | if ((dir = opendir(pathname)) == NULL) |
275 | return (NULL); | |
276 | ||
0b74af7d | 277 | /* |
3d234d4a | 278 | * If "mime" is NULL, make a new, blank database... |
0b74af7d | 279 | */ |
280 | ||
3d234d4a | 281 | if (mime == NULL) |
282 | if ((mime = mimeNew()) == NULL) | |
283 | return (NULL); | |
284 | ||
285 | /* | |
286 | * Read all the .types files... | |
287 | */ | |
288 | ||
289 | while ((dent = readdir(dir)) != NULL) | |
290 | { | |
42d48bd2 | 291 | if (NAMLEN(dent) > 6 && |
292 | strcmp(dent->d_name + NAMLEN(dent) - 6, ".types") == 0) | |
3d234d4a | 293 | { |
294 | /* | |
295 | * Load a mime.types file... | |
296 | */ | |
297 | ||
298 | sprintf(filename, "%s/%s", pathname, dent->d_name); | |
299 | load_types(mime, filename); | |
aaa5608c | 300 | } |
301 | } | |
3d234d4a | 302 | |
303 | rewinddir(dir); | |
0b74af7d | 304 | |
305 | /* | |
3d234d4a | 306 | * Read all the .convs files... |
0b74af7d | 307 | */ |
308 | ||
3d234d4a | 309 | while ((dent = readdir(dir)) != NULL) |
310 | { | |
42d48bd2 | 311 | if (NAMLEN(dent) > 6 && |
312 | strcmp(dent->d_name + NAMLEN(dent) - 6, ".convs") == 0) | |
3d234d4a | 313 | { |
314 | /* | |
315 | * Load a mime.convs file... | |
316 | */ | |
317 | ||
318 | sprintf(filename, "%s/%s", pathname, dent->d_name); | |
319 | load_convs(mime, filename); | |
aaa5608c | 320 | } |
321 | } | |
3d234d4a | 322 | |
323 | closedir(dir); | |
0b74af7d | 324 | |
325 | return (mime); | |
aaa5608c | 326 | #endif /* WIN32 || __EMX__ */ |
0b74af7d | 327 | } |
328 | ||
329 | ||
330 | /* | |
331 | * 'mimeNew()' - Create a new, empty MIME database. | |
332 | */ | |
333 | ||
334 | mime_t * /* O - MIME database */ | |
335 | mimeNew(void) | |
336 | { | |
337 | return ((mime_t *)calloc(1, sizeof(mime_t))); | |
338 | } | |
339 | ||
340 | ||
341 | /* | |
342 | * 'load_types()' - Load a xyz.types file... | |
343 | */ | |
344 | ||
345 | static void | |
346 | load_types(mime_t *mime, /* I - MIME database */ | |
347 | char *filename) /* I - Types file to load */ | |
348 | { | |
349 | FILE *fp; /* Types file */ | |
350 | int linelen; /* Length of line */ | |
351 | char line[65536], /* Input line from file */ | |
352 | *lineptr, /* Current position in line */ | |
353 | super[MIME_MAX_SUPER], /* Super-type name */ | |
354 | type[MIME_MAX_TYPE], /* Type name */ | |
355 | *temp; /* Temporary pointer */ | |
356 | mime_type_t *typeptr; /* New MIME type */ | |
357 | ||
358 | ||
359 | /* | |
360 | * First try to open the file... | |
361 | */ | |
362 | ||
363 | if ((fp = fopen(filename, "r")) == NULL) | |
364 | return; | |
365 | ||
366 | /* | |
367 | * Then read each line from the file, skipping any comments in the file... | |
368 | */ | |
369 | ||
370 | while (fgets(line, sizeof(line), fp) != NULL) | |
371 | { | |
372 | linelen = strlen(line); | |
373 | ||
374 | /* | |
375 | * While the last character in the line is a backslash, continue on to the | |
376 | * next line (and the next, etc.) | |
377 | */ | |
378 | ||
379 | if (line[linelen - 1] == '\n') | |
380 | { | |
381 | line[linelen - 1] = '\0'; | |
382 | linelen --; | |
e8fda7b9 | 383 | } |
0b74af7d | 384 | |
385 | while (line[linelen - 1] == '\\') | |
386 | { | |
387 | linelen --; | |
388 | ||
389 | if (fgets(line + linelen, sizeof(line) - linelen, fp) == NULL) | |
390 | line[linelen] = '\0'; | |
391 | else | |
392 | { | |
393 | linelen += strlen(line + linelen); | |
394 | if (line[linelen - 1] == '\n') | |
395 | { | |
396 | line[linelen - 1] = '\0'; | |
397 | linelen --; | |
e8fda7b9 | 398 | } |
399 | } | |
400 | } | |
0b74af7d | 401 | |
402 | /* | |
403 | * Skip blank lines and lines starting with a #... | |
404 | */ | |
405 | ||
406 | if (line[0] == '\n' || line[0] == '#') | |
407 | continue; | |
408 | ||
409 | /* | |
410 | * Extract the super-type and type names from the beginning of the line. | |
411 | */ | |
412 | ||
413 | lineptr = line; | |
414 | temp = super; | |
415 | ||
416 | while (*lineptr != '/' && *lineptr != '\n' && *lineptr != '\0' && | |
417 | (temp - super + 1) < MIME_MAX_SUPER) | |
418 | *temp++ = tolower(*lineptr++); | |
419 | ||
420 | *temp = '\0'; | |
421 | ||
422 | if (*lineptr != '/') | |
423 | continue; | |
424 | ||
425 | lineptr ++; | |
426 | temp = type; | |
427 | ||
428 | while (*lineptr != ' ' && *lineptr != '\t' && *lineptr != '\n' && | |
429 | *lineptr != '\0' && (temp - type + 1) < MIME_MAX_TYPE) | |
430 | *temp++ = tolower(*lineptr++); | |
431 | ||
432 | *temp = '\0'; | |
433 | ||
434 | /* | |
435 | * Add the type and rules to the MIME database... | |
436 | */ | |
437 | ||
438 | typeptr = mimeAddType(mime, super, type); | |
439 | mimeAddTypeRule(typeptr, lineptr); | |
e8fda7b9 | 440 | } |
0b74af7d | 441 | } |
442 | ||
443 | ||
444 | /* | |
445 | * 'load_convs()' - Load a xyz.convs file... | |
446 | */ | |
447 | ||
448 | static void | |
449 | load_convs(mime_t *mime, /* I - MIME database */ | |
450 | char *filename) /* I - Convs file to load */ | |
451 | { | |
452 | int i; /* Looping var */ | |
453 | FILE *fp; /* Convs file */ | |
454 | char line[1024], /* Input line from file */ | |
455 | *lineptr, /* Current position in line */ | |
456 | super[MIME_MAX_SUPER], /* Super-type name */ | |
457 | type[MIME_MAX_TYPE], /* Type name */ | |
458 | *temp, /* Temporary pointer */ | |
459 | *filter; /* Filter program */ | |
5081f753 | 460 | mime_type_t **temptype, /* MIME type looping var */ |
0b74af7d | 461 | *dsttype; /* Destination MIME type */ |
462 | int cost; /* Cost of filter */ | |
463 | ||
464 | ||
465 | /* | |
466 | * First try to open the file... | |
467 | */ | |
468 | ||
469 | if ((fp = fopen(filename, "r")) == NULL) | |
470 | return; | |
471 | ||
472 | /* | |
473 | * Then read each line from the file, skipping any comments in the file... | |
474 | */ | |
475 | ||
476 | while (fgets(line, sizeof(line), fp) != NULL) | |
477 | { | |
478 | /* | |
479 | * Skip blank lines and lines starting with a #... | |
480 | */ | |
481 | ||
482 | if (line[0] == '\n' || line[0] == '#') | |
483 | continue; | |
484 | ||
485 | /* | |
486 | * Extract the destination super-type and type names from the middle of | |
487 | * the line. | |
488 | */ | |
489 | ||
490 | lineptr = line; | |
491 | while (*lineptr != ' ' && *lineptr != '\t' && *lineptr != '\0') | |
492 | lineptr ++; | |
493 | ||
494 | while (*lineptr == ' ' || *lineptr == '\t') | |
495 | lineptr ++; | |
496 | ||
497 | temp = super; | |
498 | ||
499 | while (*lineptr != '/' && *lineptr != '\n' && *lineptr != '\0' && | |
500 | (temp - super + 1) < MIME_MAX_SUPER) | |
501 | *temp++ = tolower(*lineptr++); | |
502 | ||
503 | *temp = '\0'; | |
504 | ||
505 | if (*lineptr != '/') | |
506 | continue; | |
507 | ||
508 | lineptr ++; | |
509 | temp = type; | |
510 | ||
511 | while (*lineptr != ' ' && *lineptr != '\t' && *lineptr != '\n' && | |
512 | *lineptr != '\0' && (temp - type + 1) < MIME_MAX_TYPE) | |
513 | *temp++ = tolower(*lineptr++); | |
514 | ||
515 | *temp = '\0'; | |
516 | ||
517 | if (*lineptr == '\0' || *lineptr == '\n') | |
518 | continue; | |
519 | ||
520 | if ((dsttype = mimeType(mime, super, type)) == NULL) | |
521 | continue; | |
522 | ||
523 | /* | |
524 | * Then get the cost and filter program... | |
525 | */ | |
526 | ||
527 | while (*lineptr == ' ' || *lineptr == '\t') | |
528 | lineptr ++; | |
529 | ||
530 | if (*lineptr < '0' || *lineptr > '9') | |
531 | continue; | |
532 | ||
533 | cost = atoi(lineptr); | |
534 | ||
535 | while (*lineptr != ' ' && *lineptr != '\t' && *lineptr != '\0') | |
536 | lineptr ++; | |
537 | while (*lineptr == ' ' || *lineptr == '\t') | |
538 | lineptr ++; | |
539 | ||
540 | if (*lineptr == '\0' || *lineptr == '\n') | |
541 | continue; | |
542 | ||
543 | filter = lineptr; | |
544 | if (filter[strlen(filter) - 1] == '\n') | |
545 | filter[strlen(filter) - 1] = '\0'; | |
546 | ||
547 | /* | |
548 | * Finally, get the source super-type and type names from the beginning of | |
549 | * the line. We do it here so we can support wildcards... | |
550 | */ | |
551 | ||
552 | lineptr = line; | |
553 | temp = super; | |
554 | ||
555 | while (*lineptr != '/' && *lineptr != '\n' && *lineptr != '\0' && | |
556 | (temp - super + 1) < MIME_MAX_SUPER) | |
557 | *temp++ = tolower(*lineptr++); | |
558 | ||
559 | *temp = '\0'; | |
560 | ||
561 | if (*lineptr != '/') | |
562 | continue; | |
563 | ||
564 | lineptr ++; | |
565 | temp = type; | |
566 | ||
567 | while (*lineptr != ' ' && *lineptr != '\t' && *lineptr != '\n' && | |
568 | *lineptr != '\0' && (temp - type + 1) < MIME_MAX_TYPE) | |
569 | *temp++ = tolower(*lineptr++); | |
570 | ||
571 | *temp = '\0'; | |
572 | ||
573 | /* | |
5081f753 | 574 | * Add the filter to the MIME database, supporting wildcards as needed... |
0b74af7d | 575 | */ |
576 | ||
5081f753 | 577 | for (temptype = mime->types, i = 0; i < mime->num_types; i ++, temptype ++) |
578 | if ((super[0] == '*' || strcmp((*temptype)->super, super) == 0) && | |
579 | (type[0] == '*' || strcmp((*temptype)->type, type) == 0)) | |
580 | mimeAddFilter(mime, *temptype, dsttype, cost, filter); | |
581 | } | |
0b74af7d | 582 | } |
583 | ||
584 | ||
585 | /* | |
586 | * 'delete_rules()' - Free all memory for the given rule tree. | |
587 | */ | |
588 | ||
589 | static void | |
590 | delete_rules(mime_magic_t *rules) /* I - Rules to free */ | |
591 | { | |
592 | mime_magic_t *next; /* Next rule to free */ | |
593 | ||
594 | ||
595 | /* | |
596 | * Free the rules list, descending recursively to free any child rules. | |
597 | */ | |
598 | ||
599 | while (rules != NULL) | |
600 | { | |
601 | next = rules->next; | |
602 | ||
603 | if (rules->child != NULL) | |
604 | delete_rules(rules->child); | |
605 | ||
606 | free(rules); | |
607 | rules = next; | |
e8fda7b9 | 608 | } |
0b74af7d | 609 | } |
79df52e3 | 610 | |
611 | ||
612 | /* | |
8784b6a6 | 613 | * End of "$Id: mime.c,v 1.13 1999/06/18 18:36:10 mike Exp $". |
79df52e3 | 614 | */ |