]> git.ipfire.org Git - thirdparty/cups.git/blame - cups/mime.c
Fixed address to 44141 Airport View Drive...
[thirdparty/cups.git] / cups / mime.c
CommitLineData
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>
116typedef 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
128typedef struct direct DIRENT;
42d48bd2 129# define NAMLEN(dirent) (dirent)->d_namlen
8e1166b9 130#endif
0b74af7d 131
132
133/*
134 * Local functions...
135 */
136
137static void load_types(mime_t *mime, char *filename);
138static void load_convs(mime_t *mime, char *filename);
139static void delete_rules(mime_magic_t *rules);
140
141
142/*
143 * 'mimeDelete()' - Delete (free) a MIME database.
144 */
145
146void
147mimeDelete(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
179mime_t * /* O - Updated MIME database */
180mimeMerge(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
334mime_t * /* O - MIME database */
335mimeNew(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
345static void
346load_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
448static void
449load_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
589static void
590delete_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 */