]>
Commit | Line | Data |
---|---|---|
79df52e3 | 1 | /* |
8784b6a6 | 2 | * "$Id: filter.c,v 1.8 1999/06/18 18:36:08 mike Exp $" |
79df52e3 | 3 | * |
0b74af7d | 4 | * File type conversion 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 | * mimeAddFilter() - Add a filter to the current MIME database. |
27 | * mimeFilter() - Find the fastest way to convert from one type to another. | |
28 | * compare() - Compare two filter types... | |
29 | * lookup() - Lookup a filter... | |
79df52e3 | 30 | */ |
31 | ||
32 | /* | |
33 | * Include necessary headers... | |
34 | */ | |
35 | ||
3b960317 | 36 | #include <stdio.h> |
37 | #include <stdlib.h> | |
38 | #include <ctype.h> | |
39 | ||
40 | #include "string.h" | |
0b74af7d | 41 | #include "mime.h" |
42 | ||
43 | ||
44 | /* | |
45 | * Local functions... | |
46 | */ | |
47 | ||
48 | static int compare(mime_filter_t *, mime_filter_t *); | |
49 | static mime_filter_t *lookup(mime_t *, mime_type_t *, mime_type_t *); | |
50 | ||
51 | ||
52 | /* | |
53 | * 'mimeAddFilter()' - Add a filter to the current MIME database. | |
54 | */ | |
55 | ||
56 | mime_filter_t * /* O - New filter */ | |
57 | mimeAddFilter(mime_t *mime, /* I - MIME database */ | |
58 | mime_type_t *src, /* I - Source type */ | |
59 | mime_type_t *dst, /* I - Destination type */ | |
60 | int cost, /* I - Relative time/resource cost */ | |
61 | char *filter) /* I - Filter program to run */ | |
62 | { | |
63 | mime_filter_t *temp; /* New filter */ | |
64 | ||
65 | ||
66 | /* | |
67 | * Range-check the input... | |
68 | */ | |
69 | ||
70 | if (mime == NULL || src == NULL || dst == NULL || filter == NULL) | |
71 | return (NULL); | |
72 | ||
73 | if (strlen(filter) > (MIME_MAX_FILTER - 1)) | |
74 | return (NULL); | |
75 | ||
76 | /* | |
77 | * See if we already have an existing filter for the given source and | |
78 | * destination... | |
79 | */ | |
80 | ||
81 | if ((temp = lookup(mime, src, dst)) != NULL) | |
82 | { | |
83 | /* | |
84 | * Yup, does the existing filter have a higher cost? If so, copy the | |
85 | * filter and cost to the existing filter entry and return it... | |
86 | */ | |
87 | ||
88 | if (temp->cost > cost) | |
89 | { | |
90 | temp->cost = cost; | |
91 | strcpy(temp->filter, filter); | |
e8fda7b9 | 92 | } |
0b74af7d | 93 | } |
94 | else | |
95 | { | |
96 | /* | |
97 | * Nope, add a new one... | |
98 | */ | |
99 | ||
100 | if (mime->num_filters == 0) | |
101 | temp = malloc(sizeof(mime_filter_t)); | |
102 | else | |
103 | temp = realloc(mime->filters, sizeof(mime_filter_t) * (mime->num_filters + 1)); | |
104 | ||
105 | if (temp == NULL) | |
106 | return (NULL); | |
107 | ||
108 | mime->filters = temp; | |
109 | temp += mime->num_filters; | |
110 | mime->num_filters ++; | |
111 | ||
112 | /* | |
113 | * Copy the information over and sort if necessary... | |
114 | */ | |
115 | ||
116 | temp->src = src; | |
117 | temp->dst = dst; | |
118 | temp->cost = cost; | |
119 | strcpy(temp->filter, filter); | |
120 | ||
121 | if (mime->num_filters > 1) | |
122 | qsort(mime->filters, mime->num_filters, sizeof(mime_filter_t), | |
123 | (int (*)(const void *, const void *))compare); | |
e8fda7b9 | 124 | } |
0b74af7d | 125 | |
126 | /* | |
127 | * Return the new/updated filter... | |
128 | */ | |
129 | ||
130 | return (temp); | |
131 | } | |
132 | ||
133 | ||
134 | /* | |
135 | * 'mimeFilter()' - Find the fastest way to convert from one type to another. | |
0b74af7d | 136 | */ |
137 | ||
138 | mime_filter_t * /* O - Array of filters to run */ | |
139 | mimeFilter(mime_t *mime, /* I - MIME database */ | |
140 | mime_type_t *src, /* I - Source file type */ | |
141 | mime_type_t *dst, /* I - Destination file type */ | |
142 | int *num_filters) /* O - Number of filters to run */ | |
143 | { | |
75675d7a | 144 | int i, j, /* Looping vars */ |
145 | num_temp, /* Number of temporary filters */ | |
146 | num_mintemp, /* Number of filters in the minimum */ | |
147 | cost, /* Current cost */ | |
148 | mincost; /* Current minimum */ | |
0b74af7d | 149 | mime_filter_t *temp, /* Temporary filter */ |
4ca01b29 | 150 | *mintemp, /* Current minimum */ |
151 | *mincurrent, /* Current filter for minimum */ | |
0b74af7d | 152 | *current, /* Current filter */ |
153 | *filters; /* Filters to use */ | |
154 | ||
155 | ||
156 | /* | |
157 | * Range-check the input... | |
158 | */ | |
159 | ||
160 | if (mime == NULL || src == NULL || dst == NULL || num_filters == NULL) | |
161 | return (NULL); | |
162 | ||
163 | *num_filters = 0; | |
164 | ||
165 | /* | |
166 | * See if there is a filter that can convert the files directly... | |
167 | */ | |
168 | ||
169 | if ((temp = lookup(mime, src, dst)) != NULL) | |
170 | { | |
171 | /* | |
172 | * Got a direct filter! | |
173 | */ | |
174 | ||
175 | if ((filters = (mime_filter_t *)malloc(sizeof(mime_filter_t))) == NULL) | |
176 | return (NULL); | |
177 | ||
178 | memcpy(filters, temp, sizeof(mime_filter_t)); | |
179 | *num_filters = 1; | |
180 | return (filters); | |
e8fda7b9 | 181 | } |
0b74af7d | 182 | |
183 | /* | |
184 | * OK, now look for filters from the source type to any other type... | |
185 | */ | |
186 | ||
75675d7a | 187 | mincost = 9999999; |
188 | mintemp = NULL; | |
4ca01b29 | 189 | |
0b74af7d | 190 | for (i = mime->num_filters, current = mime->filters; i > 0; i --, current ++) |
191 | if (current->src == src) | |
192 | { | |
193 | /* | |
194 | * See if we have any filters that can convert from the destination type | |
195 | * of this filter to the final type... | |
196 | */ | |
197 | ||
4ca01b29 | 198 | if ((temp = mimeFilter(mime, current->dst, dst, &num_temp)) == NULL) |
0b74af7d | 199 | continue; |
200 | ||
201 | /* | |
4ca01b29 | 202 | * Found a match; see if this one is less costly than the last (if |
203 | * any...) | |
0b74af7d | 204 | */ |
205 | ||
75675d7a | 206 | for (j = 0, cost = 0; j < num_temp; j ++) |
207 | cost += temp->cost; | |
208 | ||
209 | if (cost < mincost) | |
0b74af7d | 210 | { |
4ca01b29 | 211 | if (mintemp != NULL) |
212 | free(mintemp); | |
213 | ||
75675d7a | 214 | mincost = cost; |
4ca01b29 | 215 | mintemp = temp; |
75675d7a | 216 | num_mintemp = num_temp; |
4ca01b29 | 217 | mincurrent = current; |
e8fda7b9 | 218 | } |
4ca01b29 | 219 | else |
220 | free(temp); | |
221 | } | |
0b74af7d | 222 | |
4ca01b29 | 223 | if (mintemp != NULL) |
224 | { | |
225 | /* | |
226 | * Hey, we got a match! Add the current filter to the beginning of the | |
227 | * filter list... | |
228 | */ | |
0b74af7d | 229 | |
4ca01b29 | 230 | filters = (mime_filter_t *)realloc(mintemp, sizeof(mime_filter_t) * |
231 | (num_mintemp + 1)); | |
0b74af7d | 232 | |
4ca01b29 | 233 | if (filters == NULL) |
234 | { | |
235 | *num_filters = 0; | |
236 | return (NULL); | |
e8fda7b9 | 237 | } |
0b74af7d | 238 | |
4ca01b29 | 239 | memmove(filters + 1, filters, num_mintemp * sizeof(mime_filter_t)); |
240 | memcpy(filters, mincurrent, sizeof(mime_filter_t)); | |
241 | ||
242 | *num_filters = num_mintemp + 1; | |
243 | ||
244 | return (filters); | |
245 | } | |
246 | ||
0b74af7d | 247 | return (NULL); |
248 | } | |
249 | ||
250 | ||
251 | /* | |
252 | * 'compare()' - Compare two filter types... | |
253 | */ | |
254 | ||
255 | static int /* O - Comparison result */ | |
256 | compare(mime_filter_t *f0, /* I - First filter */ | |
257 | mime_filter_t *f1) /* I - Second filter */ | |
258 | { | |
259 | int i; /* Result of comparison */ | |
260 | ||
261 | ||
262 | if ((i = strcmp(f0->src->super, f1->src->super)) == 0) | |
263 | if ((i = strcmp(f0->src->type, f1->src->type)) == 0) | |
264 | if ((i = strcmp(f0->dst->super, f1->dst->super)) == 0) | |
265 | i = strcmp(f0->dst->type, f1->dst->type); | |
266 | ||
267 | return (i); | |
268 | } | |
269 | ||
270 | ||
271 | /* | |
272 | * 'lookup()' - Lookup a filter... | |
273 | */ | |
274 | ||
275 | static mime_filter_t * /* O - Filter for src->dst */ | |
276 | lookup(mime_t *mime, /* I - MIME database */ | |
277 | mime_type_t *src, /* I - Source type */ | |
278 | mime_type_t *dst) /* I - Destination type */ | |
279 | { | |
280 | mime_filter_t key; /* Key record for filter search */ | |
281 | ||
282 | ||
283 | if (mime->num_filters == 0) | |
284 | return (NULL); | |
285 | ||
286 | key.src = src; | |
287 | key.dst = dst; | |
288 | ||
289 | return ((mime_filter_t *)bsearch(&key, mime->filters, mime->num_filters, | |
290 | sizeof(mime_filter_t), | |
291 | (int (*)(const void *, const void *))compare)); | |
292 | } | |
79df52e3 | 293 | |
294 | ||
295 | /* | |
8784b6a6 | 296 | * End of "$Id: filter.c,v 1.8 1999/06/18 18:36:08 mike Exp $". |
79df52e3 | 297 | */ |