]>
Commit | Line | Data |
---|---|---|
79df52e3 | 1 | /* |
68edc300 | 2 | * "$Id: filter.c,v 1.1 2000/01/25 03:50:48 mike Exp $" |
79df52e3 | 3 | * |
0b74af7d | 4 | * File type conversion routines for the Common UNIX Printing System (CUPS). |
79df52e3 | 5 | * |
71fe22b7 | 6 | * Copyright 1997-2000 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 | ||
68edc300 | 40 | #include <cups/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 */ | |
063e1ac7 | 61 | const char *filter) /* I - Filter program to run */ |
0b74af7d | 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; | |
970017a4 | 91 | strncpy(temp->filter, filter, sizeof(temp->filter) - 1); |
92 | temp->filter[sizeof(temp->filter) - 1] = '\0'; | |
e8fda7b9 | 93 | } |
0b74af7d | 94 | } |
95 | else | |
96 | { | |
97 | /* | |
98 | * Nope, add a new one... | |
99 | */ | |
100 | ||
101 | if (mime->num_filters == 0) | |
102 | temp = malloc(sizeof(mime_filter_t)); | |
103 | else | |
104 | temp = realloc(mime->filters, sizeof(mime_filter_t) * (mime->num_filters + 1)); | |
105 | ||
106 | if (temp == NULL) | |
107 | return (NULL); | |
108 | ||
109 | mime->filters = temp; | |
110 | temp += mime->num_filters; | |
111 | mime->num_filters ++; | |
112 | ||
113 | /* | |
114 | * Copy the information over and sort if necessary... | |
115 | */ | |
116 | ||
117 | temp->src = src; | |
118 | temp->dst = dst; | |
119 | temp->cost = cost; | |
970017a4 | 120 | strncpy(temp->filter, filter, sizeof(temp->filter) - 1); |
121 | temp->filter[sizeof(temp->filter) - 1] = '\0'; | |
0b74af7d | 122 | |
123 | if (mime->num_filters > 1) | |
124 | qsort(mime->filters, mime->num_filters, sizeof(mime_filter_t), | |
125 | (int (*)(const void *, const void *))compare); | |
e8fda7b9 | 126 | } |
0b74af7d | 127 | |
128 | /* | |
129 | * Return the new/updated filter... | |
130 | */ | |
131 | ||
132 | return (temp); | |
133 | } | |
134 | ||
135 | ||
136 | /* | |
137 | * 'mimeFilter()' - Find the fastest way to convert from one type to another. | |
0b74af7d | 138 | */ |
139 | ||
140 | mime_filter_t * /* O - Array of filters to run */ | |
141 | mimeFilter(mime_t *mime, /* I - MIME database */ | |
142 | mime_type_t *src, /* I - Source file type */ | |
143 | mime_type_t *dst, /* I - Destination file type */ | |
144 | int *num_filters) /* O - Number of filters to run */ | |
145 | { | |
75675d7a | 146 | int i, j, /* Looping vars */ |
147 | num_temp, /* Number of temporary filters */ | |
148 | num_mintemp, /* Number of filters in the minimum */ | |
149 | cost, /* Current cost */ | |
150 | mincost; /* Current minimum */ | |
0b74af7d | 151 | mime_filter_t *temp, /* Temporary filter */ |
4ca01b29 | 152 | *mintemp, /* Current minimum */ |
153 | *mincurrent, /* Current filter for minimum */ | |
0b74af7d | 154 | *current, /* Current filter */ |
155 | *filters; /* Filters to use */ | |
156 | ||
157 | ||
158 | /* | |
159 | * Range-check the input... | |
160 | */ | |
161 | ||
162 | if (mime == NULL || src == NULL || dst == NULL || num_filters == NULL) | |
163 | return (NULL); | |
164 | ||
165 | *num_filters = 0; | |
166 | ||
167 | /* | |
168 | * See if there is a filter that can convert the files directly... | |
169 | */ | |
170 | ||
171 | if ((temp = lookup(mime, src, dst)) != NULL) | |
172 | { | |
173 | /* | |
174 | * Got a direct filter! | |
175 | */ | |
176 | ||
177 | if ((filters = (mime_filter_t *)malloc(sizeof(mime_filter_t))) == NULL) | |
178 | return (NULL); | |
179 | ||
180 | memcpy(filters, temp, sizeof(mime_filter_t)); | |
181 | *num_filters = 1; | |
182 | return (filters); | |
e8fda7b9 | 183 | } |
0b74af7d | 184 | |
185 | /* | |
186 | * OK, now look for filters from the source type to any other type... | |
187 | */ | |
188 | ||
75675d7a | 189 | mincost = 9999999; |
190 | mintemp = NULL; | |
4ca01b29 | 191 | |
0b74af7d | 192 | for (i = mime->num_filters, current = mime->filters; i > 0; i --, current ++) |
193 | if (current->src == src) | |
194 | { | |
195 | /* | |
196 | * See if we have any filters that can convert from the destination type | |
197 | * of this filter to the final type... | |
198 | */ | |
199 | ||
4ca01b29 | 200 | if ((temp = mimeFilter(mime, current->dst, dst, &num_temp)) == NULL) |
0b74af7d | 201 | continue; |
202 | ||
203 | /* | |
4ca01b29 | 204 | * Found a match; see if this one is less costly than the last (if |
205 | * any...) | |
0b74af7d | 206 | */ |
207 | ||
75675d7a | 208 | for (j = 0, cost = 0; j < num_temp; j ++) |
209 | cost += temp->cost; | |
210 | ||
211 | if (cost < mincost) | |
0b74af7d | 212 | { |
4ca01b29 | 213 | if (mintemp != NULL) |
214 | free(mintemp); | |
215 | ||
75675d7a | 216 | mincost = cost; |
4ca01b29 | 217 | mintemp = temp; |
75675d7a | 218 | num_mintemp = num_temp; |
4ca01b29 | 219 | mincurrent = current; |
e8fda7b9 | 220 | } |
4ca01b29 | 221 | else |
222 | free(temp); | |
223 | } | |
0b74af7d | 224 | |
4ca01b29 | 225 | if (mintemp != NULL) |
226 | { | |
227 | /* | |
228 | * Hey, we got a match! Add the current filter to the beginning of the | |
229 | * filter list... | |
230 | */ | |
0b74af7d | 231 | |
4ca01b29 | 232 | filters = (mime_filter_t *)realloc(mintemp, sizeof(mime_filter_t) * |
233 | (num_mintemp + 1)); | |
0b74af7d | 234 | |
4ca01b29 | 235 | if (filters == NULL) |
236 | { | |
237 | *num_filters = 0; | |
238 | return (NULL); | |
e8fda7b9 | 239 | } |
0b74af7d | 240 | |
4ca01b29 | 241 | memmove(filters + 1, filters, num_mintemp * sizeof(mime_filter_t)); |
242 | memcpy(filters, mincurrent, sizeof(mime_filter_t)); | |
243 | ||
244 | *num_filters = num_mintemp + 1; | |
245 | ||
246 | return (filters); | |
247 | } | |
248 | ||
0b74af7d | 249 | return (NULL); |
250 | } | |
251 | ||
252 | ||
253 | /* | |
254 | * 'compare()' - Compare two filter types... | |
255 | */ | |
256 | ||
257 | static int /* O - Comparison result */ | |
258 | compare(mime_filter_t *f0, /* I - First filter */ | |
259 | mime_filter_t *f1) /* I - Second filter */ | |
260 | { | |
261 | int i; /* Result of comparison */ | |
262 | ||
263 | ||
264 | if ((i = strcmp(f0->src->super, f1->src->super)) == 0) | |
265 | if ((i = strcmp(f0->src->type, f1->src->type)) == 0) | |
266 | if ((i = strcmp(f0->dst->super, f1->dst->super)) == 0) | |
267 | i = strcmp(f0->dst->type, f1->dst->type); | |
268 | ||
269 | return (i); | |
270 | } | |
271 | ||
272 | ||
273 | /* | |
274 | * 'lookup()' - Lookup a filter... | |
275 | */ | |
276 | ||
277 | static mime_filter_t * /* O - Filter for src->dst */ | |
278 | lookup(mime_t *mime, /* I - MIME database */ | |
279 | mime_type_t *src, /* I - Source type */ | |
280 | mime_type_t *dst) /* I - Destination type */ | |
281 | { | |
282 | mime_filter_t key; /* Key record for filter search */ | |
283 | ||
284 | ||
285 | if (mime->num_filters == 0) | |
286 | return (NULL); | |
287 | ||
288 | key.src = src; | |
289 | key.dst = dst; | |
290 | ||
291 | return ((mime_filter_t *)bsearch(&key, mime->filters, mime->num_filters, | |
292 | sizeof(mime_filter_t), | |
293 | (int (*)(const void *, const void *))compare)); | |
294 | } | |
79df52e3 | 295 | |
296 | ||
297 | /* | |
68edc300 | 298 | * End of "$Id: filter.c,v 1.1 2000/01/25 03:50:48 mike Exp $". |
79df52e3 | 299 | */ |