Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
srohatgi01
GitHub Repository: srohatgi01/cups
Path: blob/master/scheduler/filter.c
1090 views
1
/*
2
* File type conversion routines for CUPS.
3
*
4
* Copyright 2007-2011 by Apple Inc.
5
* Copyright 1997-2007 by Easy Software Products, all rights reserved.
6
*
7
* Licensed under Apache License v2.0. See the file "LICENSE" for more information.
8
*/
9
10
/*
11
* Include necessary headers...
12
*/
13
14
#include <cups/string-private.h>
15
#include "mime.h"
16
17
18
/*
19
* Debug macros that used to be private API...
20
*/
21
22
#define DEBUG_puts(x)
23
#define DEBUG_printf(...)
24
25
26
/*
27
* Local types...
28
*/
29
30
typedef struct _mime_typelist_s /**** List of source types ****/
31
{
32
struct _mime_typelist_s *next; /* Next source type */
33
mime_type_t *src; /* Source type */
34
} _mime_typelist_t;
35
36
37
/*
38
* Local functions...
39
*/
40
41
static int mime_compare_filters(mime_filter_t *, mime_filter_t *);
42
static int mime_compare_srcs(mime_filter_t *, mime_filter_t *);
43
static cups_array_t *mime_find_filters(mime_t *mime, mime_type_t *src,
44
size_t srcsize, mime_type_t *dst,
45
int *cost, _mime_typelist_t *visited);
46
47
48
/*
49
* 'mimeAddFilter()' - Add a filter to the current MIME database.
50
*/
51
52
mime_filter_t * /* O - New filter */
53
mimeAddFilter(mime_t *mime, /* I - MIME database */
54
mime_type_t *src, /* I - Source type */
55
mime_type_t *dst, /* I - Destination type */
56
int cost, /* I - Relative time/resource cost */
57
const char *filter) /* I - Filter program to run */
58
{
59
mime_filter_t *temp; /* New filter */
60
61
62
DEBUG_printf(("mimeAddFilter(mime=%p, src=%p(%s/%s), dst=%p(%s/%s), cost=%d, "
63
"filter=\"%s\")", mime,
64
src, src ? src->super : "???", src ? src->type : "???",
65
dst, dst ? dst->super : "???", dst ? dst->type : "???",
66
cost, filter));
67
68
/*
69
* Range-check the input...
70
*/
71
72
if (!mime || !src || !dst || !filter)
73
{
74
DEBUG_puts("1mimeAddFilter: Returning NULL.");
75
return (NULL);
76
}
77
78
/*
79
* See if we already have an existing filter for the given source and
80
* destination...
81
*/
82
83
if ((temp = mimeFilterLookup(mime, src, dst)) != NULL)
84
{
85
/*
86
* Yup, does the existing filter have a higher cost? If so, copy the
87
* filter and cost to the existing filter entry and return it...
88
*/
89
90
if (temp->cost > cost)
91
{
92
DEBUG_printf(("1mimeAddFilter: Replacing filter \"%s\", cost %d.",
93
temp->filter, temp->cost));
94
temp->cost = cost;
95
strlcpy(temp->filter, filter, sizeof(temp->filter));
96
}
97
}
98
else
99
{
100
/*
101
* Nope, add a new one...
102
*/
103
104
if (!mime->filters)
105
mime->filters = cupsArrayNew((cups_array_func_t)mime_compare_filters, NULL);
106
107
if (!mime->filters)
108
return (NULL);
109
110
if ((temp = calloc(1, sizeof(mime_filter_t))) == NULL)
111
return (NULL);
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;
120
strlcpy(temp->filter, filter, sizeof(temp->filter));
121
122
DEBUG_puts("1mimeAddFilter: Adding new filter.");
123
cupsArrayAdd(mime->filters, temp);
124
cupsArrayAdd(mime->srcs, temp);
125
}
126
127
/*
128
* Return the new/updated filter...
129
*/
130
131
DEBUG_printf(("1mimeAddFilter: Returning %p.", temp));
132
133
return (temp);
134
}
135
136
137
/*
138
* 'mimeFilter()' - Find the fastest way to convert from one type to another.
139
*/
140
141
cups_array_t * /* O - Array of filters to run */
142
mimeFilter(mime_t *mime, /* I - MIME database */
143
mime_type_t *src, /* I - Source file type */
144
mime_type_t *dst, /* I - Destination file type */
145
int *cost) /* O - Cost of filters */
146
{
147
DEBUG_printf(("mimeFilter(mime=%p, src=%p(%s/%s), dst=%p(%s/%s), "
148
"cost=%p(%d))", mime,
149
src, src ? src->super : "???", src ? src->type : "???",
150
dst, dst ? dst->super : "???", dst ? dst->type : "???",
151
cost, cost ? *cost : 0));
152
153
return (mimeFilter2(mime, src, 0, dst, cost));
154
}
155
156
157
/*
158
* 'mimeFilter2()' - Find the fastest way to convert from one type to another,
159
* including file size.
160
*/
161
162
cups_array_t * /* O - Array of filters to run */
163
mimeFilter2(mime_t *mime, /* I - MIME database */
164
mime_type_t *src, /* I - Source file type */
165
size_t srcsize, /* I - Size of source file */
166
mime_type_t *dst, /* I - Destination file type */
167
int *cost) /* O - Cost of filters */
168
{
169
cups_array_t *filters; /* Array of filters to run */
170
171
172
/*
173
* Range-check the input...
174
*/
175
176
DEBUG_printf(("mimeFilter2(mime=%p, src=%p(%s/%s), srcsize=" CUPS_LLFMT
177
", dst=%p(%s/%s), cost=%p(%d))", mime,
178
src, src ? src->super : "???", src ? src->type : "???",
179
CUPS_LLCAST srcsize,
180
dst, dst ? dst->super : "???", dst ? dst->type : "???",
181
cost, cost ? *cost : 0));
182
183
if (cost)
184
*cost = 0;
185
186
if (!mime || !src || !dst)
187
return (NULL);
188
189
/*
190
* (Re)build the source lookup array as needed...
191
*/
192
193
if (!mime->srcs)
194
{
195
mime_filter_t *current; /* Current filter */
196
197
mime->srcs = cupsArrayNew((cups_array_func_t)mime_compare_srcs, NULL);
198
199
for (current = mimeFirstFilter(mime);
200
current;
201
current = mimeNextFilter(mime))
202
cupsArrayAdd(mime->srcs, current);
203
}
204
205
/*
206
* Find the filters...
207
*/
208
209
filters = mime_find_filters(mime, src, srcsize, dst, cost, NULL);
210
211
DEBUG_printf(("1mimeFilter2: Returning %d filter(s), cost %d:",
212
cupsArrayCount(filters), cost ? *cost : -1));
213
#ifdef DEBUG
214
{
215
mime_filter_t *filter; /* Current filter */
216
217
for (filter = (mime_filter_t *)cupsArrayFirst(filters);
218
filter;
219
filter = (mime_filter_t *)cupsArrayNext(filters))
220
DEBUG_printf(("1mimeFilter2: %s/%s %s/%s %d %s", filter->src->super,
221
filter->src->type, filter->dst->super, filter->dst->type,
222
filter->cost, filter->filter));
223
}
224
#endif /* DEBUG */
225
226
return (filters);
227
}
228
229
230
/*
231
* 'mimeFilterLookup()' - Lookup a filter.
232
*/
233
234
mime_filter_t * /* O - Filter for src->dst */
235
mimeFilterLookup(mime_t *mime, /* I - MIME database */
236
mime_type_t *src, /* I - Source type */
237
mime_type_t *dst) /* I - Destination type */
238
{
239
mime_filter_t key, /* Key record for filter search */
240
*filter; /* Matching filter */
241
242
243
DEBUG_printf(("2mimeFilterLookup(mime=%p, src=%p(%s/%s), dst=%p(%s/%s))", mime,
244
src, src ? src->super : "???", src ? src->type : "???",
245
dst, dst ? dst->super : "???", dst ? dst->type : "???"));
246
247
key.src = src;
248
key.dst = dst;
249
250
filter = (mime_filter_t *)cupsArrayFind(mime->filters, &key);
251
DEBUG_printf(("3mimeFilterLookup: Returning %p(%s).", filter,
252
filter ? filter->filter : "???"));
253
return (filter);
254
}
255
256
257
/*
258
* 'mime_compare_filters()' - Compare two filters.
259
*/
260
261
static int /* O - Comparison result */
262
mime_compare_filters(mime_filter_t *f0, /* I - First filter */
263
mime_filter_t *f1) /* I - Second filter */
264
{
265
int i; /* Result of comparison */
266
267
268
if ((i = strcmp(f0->src->super, f1->src->super)) == 0)
269
if ((i = strcmp(f0->src->type, f1->src->type)) == 0)
270
if ((i = strcmp(f0->dst->super, f1->dst->super)) == 0)
271
i = strcmp(f0->dst->type, f1->dst->type);
272
273
return (i);
274
}
275
276
277
/*
278
* 'mime_compare_srcs()' - Compare two filter source types.
279
*/
280
281
static int /* O - Comparison result */
282
mime_compare_srcs(mime_filter_t *f0, /* I - First filter */
283
mime_filter_t *f1) /* I - Second filter */
284
{
285
int i; /* Result of comparison */
286
287
288
if ((i = strcmp(f0->src->super, f1->src->super)) == 0)
289
i = strcmp(f0->src->type, f1->src->type);
290
291
return (i);
292
}
293
294
295
/*
296
* 'mime_find_filters()' - Find the filters to convert from one type to another.
297
*/
298
299
static cups_array_t * /* O - Array of filters to run */
300
mime_find_filters(
301
mime_t *mime, /* I - MIME database */
302
mime_type_t *src, /* I - Source file type */
303
size_t srcsize, /* I - Size of source file */
304
mime_type_t *dst, /* I - Destination file type */
305
int *cost, /* O - Cost of filters */
306
_mime_typelist_t *list) /* I - Source types we've used */
307
{
308
int tempcost, /* Temporary cost */
309
mincost; /* Current minimum */
310
cups_array_t *temp, /* Temporary filter */
311
*mintemp; /* Current minimum */
312
mime_filter_t *current, /* Current filter */
313
srckey; /* Source type key */
314
_mime_typelist_t listnode, /* New list node */
315
*listptr; /* Pointer in list */
316
317
318
DEBUG_printf(("2mime_find_filters(mime=%p, src=%p(%s/%s), srcsize=" CUPS_LLFMT
319
", dst=%p(%s/%s), cost=%p, list=%p)", mime, src, src->super,
320
src->type, CUPS_LLCAST srcsize, dst, dst->super, dst->type,
321
cost, list));
322
323
/*
324
* See if there is a filter that can convert the files directly...
325
*/
326
327
if ((current = mimeFilterLookup(mime, src, dst)) != NULL &&
328
(current->maxsize == 0 || srcsize <= current->maxsize))
329
{
330
/*
331
* Got a direct filter!
332
*/
333
334
DEBUG_puts("3mime_find_filters: Direct filter found.");
335
336
if ((mintemp = cupsArrayNew(NULL, NULL)) == NULL)
337
{
338
DEBUG_puts("3mime_find_filters: Returning NULL (out of memory).");
339
return (NULL);
340
}
341
342
cupsArrayAdd(mintemp, current);
343
344
mincost = current->cost;
345
346
if (!cost)
347
{
348
DEBUG_printf(("3mime_find_filters: Returning 1 filter, cost %d:",
349
mincost));
350
DEBUG_printf(("3mime_find_filters: %s/%s %s/%s %d %s",
351
current->src->super, current->src->type,
352
current->dst->super, current->dst->type,
353
current->cost, current->filter));
354
return (mintemp);
355
}
356
}
357
else
358
{
359
/*
360
* No direct filter...
361
*/
362
363
mintemp = NULL;
364
mincost = 9999999;
365
}
366
367
/*
368
* Initialize this node in the type list...
369
*/
370
371
listnode.next = list;
372
373
/*
374
* OK, now look for filters from the source type to any other type...
375
*/
376
377
srckey.src = src;
378
379
for (current = (mime_filter_t *)cupsArrayFind(mime->srcs, &srckey);
380
current && current->src == src;
381
current = (mime_filter_t *)cupsArrayNext(mime->srcs))
382
{
383
/*
384
* See if we have already tried the destination type as a source
385
* type (this avoids extra filter looping...)
386
*/
387
388
mime_type_t *current_dst; /* Current destination type */
389
390
if (current->maxsize > 0 && srcsize > current->maxsize)
391
continue;
392
393
for (listptr = list, current_dst = current->dst;
394
listptr;
395
listptr = listptr->next)
396
if (current_dst == listptr->src)
397
break;
398
399
if (listptr)
400
continue;
401
402
/*
403
* See if we have any filters that can convert from the destination type
404
* of this filter to the final type...
405
*/
406
407
listnode.src = current->src;
408
409
cupsArraySave(mime->srcs);
410
temp = mime_find_filters(mime, current->dst, srcsize, dst, &tempcost,
411
&listnode);
412
cupsArrayRestore(mime->srcs);
413
414
if (!temp)
415
continue;
416
417
if (!cost)
418
{
419
DEBUG_printf(("3mime_find_filters: Returning %d filter(s), cost %d:",
420
cupsArrayCount(temp), tempcost));
421
422
#ifdef DEBUG
423
for (current = (mime_filter_t *)cupsArrayFirst(temp);
424
current;
425
current = (mime_filter_t *)cupsArrayNext(temp))
426
DEBUG_printf(("3mime_find_filters: %s/%s %s/%s %d %s",
427
current->src->super, current->src->type,
428
current->dst->super, current->dst->type,
429
current->cost, current->filter));
430
#endif /* DEBUG */
431
432
return (temp);
433
}
434
435
/*
436
* Found a match; see if this one is less costly than the last (if
437
* any...)
438
*/
439
440
tempcost += current->cost;
441
442
if (tempcost < mincost)
443
{
444
cupsArrayDelete(mintemp);
445
446
/*
447
* Hey, we got a match! Add the current filter to the beginning of the
448
* filter list...
449
*/
450
451
mintemp = temp;
452
mincost = tempcost;
453
cupsArrayInsert(mintemp, current);
454
}
455
else
456
cupsArrayDelete(temp);
457
}
458
459
if (mintemp)
460
{
461
/*
462
* Hey, we got a match!
463
*/
464
465
DEBUG_printf(("3mime_find_filters: Returning %d filter(s), cost %d:",
466
cupsArrayCount(mintemp), mincost));
467
468
#ifdef DEBUG
469
for (current = (mime_filter_t *)cupsArrayFirst(mintemp);
470
current;
471
current = (mime_filter_t *)cupsArrayNext(mintemp))
472
DEBUG_printf(("3mime_find_filters: %s/%s %s/%s %d %s",
473
current->src->super, current->src->type,
474
current->dst->super, current->dst->type,
475
current->cost, current->filter));
476
#endif /* DEBUG */
477
478
if (cost)
479
*cost = mincost;
480
481
return (mintemp);
482
}
483
484
DEBUG_puts("3mime_find_filters: Returning NULL (no matches).");
485
486
return (NULL);
487
}
488
489