]> git.ipfire.org Git - thirdparty/cups.git/blob - cups/pwg-file.c
6ebd4aaeb29ac23dec79ebebc538fd753926f9f7
[thirdparty/cups.git] / cups / pwg-file.c
1 /*
2 * "$Id$"
3 *
4 * PWG load/save API implementation for CUPS.
5 *
6 * Copyright 2010 by Apple Inc.
7 *
8 * These coded instructions, statements, and computer programs are the
9 * property of Apple Inc. and are protected by Federal copyright
10 * law. Distribution and use rights are outlined in the file "LICENSE.txt"
11 * which should have been included with this file. If this file is
12 * file is missing or damaged, see the license at "http://www.cups.org/".
13 *
14 * This file is subject to the Apple OS-Developed Software exception.
15 *
16 * Contents:
17 *
18 * _pwgCreateWithFile() - Create PWG mapping data from a written file.
19 * _pwgDestroy() - Free all memory used for PWG mapping data.
20 * _pwgWriteFile() - Write PWG mapping data to a file.
21 */
22
23 /*
24 * Include necessary headers...
25 */
26
27 #include "cups-private.h"
28 #include <math.h>
29
30
31 /*
32 * '_pwgCreateWithFile()' - Create PWG mapping data from a written file.
33 *
34 * Use the @link _pwgWriteFile@ function to write PWG mapping data to a file.
35 */
36
37 _pwg_t * /* O - PWG mapping data */
38 _pwgCreateWithFile(const char *filename)/* I - File to read */
39 {
40 cups_file_t *fp; /* File */
41 _pwg_t *pwg; /* PWG mapping data */
42 _pwg_size_t *size; /* Current size */
43 _pwg_map_t *map; /* Current map */
44 int linenum, /* Current line number */
45 num_bins, /* Number of bins in file */
46 num_sizes, /* Number of sizes in file */
47 num_sources, /* Number of sources in file */
48 num_types; /* Number of types in file */
49 char line[2048], /* Current line */
50 *value, /* Pointer to value in line */
51 *valueptr, /* Pointer into value */
52 pwg_keyword[128], /* PWG keyword */
53 ppd_keyword[PPD_MAX_NAME];
54 /* PPD keyword */
55 _pwg_output_mode_t output_mode; /* Output mode for preset */
56 _pwg_print_quality_t print_quality; /* Print quality for preset */
57
58
59 DEBUG_printf(("_pwgCreateWithFile(filename=\"%s\")", filename));
60
61 /*
62 * Range check input...
63 */
64
65 if (!filename)
66 {
67 _cupsSetError(IPP_INTERNAL_ERROR, strerror(EINVAL), 0);
68 return (NULL);
69 }
70
71 /*
72 * Open the file...
73 */
74
75 if ((fp = cupsFileOpen(filename, "r")) == NULL)
76 {
77 _cupsSetError(IPP_INTERNAL_ERROR, strerror(errno), 0);
78 return (NULL);
79 }
80
81 /*
82 * Allocate the mapping data structure...
83 */
84
85 if ((pwg = calloc(1, sizeof(_pwg_t))) == NULL)
86 {
87 DEBUG_puts("_pwgCreateWithFile: Unable to allocate pwg_t.");
88 _cupsSetError(IPP_INTERNAL_ERROR, strerror(errno), 0);
89 goto create_error;
90 }
91
92 /*
93 * Read the file...
94 */
95
96 linenum = 0;
97 num_bins = 0;
98 num_sizes = 0;
99 num_sources = 0;
100 num_types = 0;
101
102 while (cupsFileGetConf(fp, line, sizeof(line), &value, &linenum))
103 {
104 DEBUG_printf(("_pwgCreateWithFile: line=\"%s\", value=\"%s\", linenum=%d",
105 line, value, linenum));
106
107 if (!value)
108 {
109 DEBUG_printf(("_pwgCreateWithFile: Missing value on line %d.", linenum));
110 _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PWG mapping file."), 1);
111 goto create_error;
112 }
113 else if (!strcasecmp(line, "NumBins"))
114 {
115 if (num_bins > 0)
116 {
117 DEBUG_puts("_pwgCreateWithFile: NumBins listed multiple times.");
118 _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PWG mapping file."), 1);
119 goto create_error;
120 }
121
122 if ((num_bins = atoi(value)) <= 0 || num_bins > 65536)
123 {
124 DEBUG_printf(("_pwgCreateWithFile: Bad NumBins value %d on line %d.",
125 num_sizes, linenum));
126 _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PWG mapping file."), 1);
127 goto create_error;
128 }
129
130 if ((pwg->bins = calloc(num_bins, sizeof(_pwg_map_t))) == NULL)
131 {
132 DEBUG_printf(("_pwgCreateWithFile: Unable to allocate %d bins.",
133 num_sizes));
134 _cupsSetError(IPP_INTERNAL_ERROR, strerror(errno), 0);
135 goto create_error;
136 }
137 }
138 else if (!strcasecmp(line, "Bin"))
139 {
140 if (sscanf(value, "%127s%40s", pwg_keyword, ppd_keyword) != 2)
141 {
142 DEBUG_printf(("_pwgCreateWithFile: Bad Bin on line %d.", linenum));
143 _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PWG mapping file."), 1);
144 goto create_error;
145 }
146
147 if (pwg->num_bins >= num_bins)
148 {
149 DEBUG_printf(("_pwgCreateWithFile: Too many Bin's on line %d.",
150 linenum));
151 _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PWG mapping file."), 1);
152 goto create_error;
153 }
154
155 map = pwg->bins + pwg->num_bins;
156 map->pwg = _cupsStrAlloc(pwg_keyword);
157 map->ppd = _cupsStrAlloc(ppd_keyword);
158
159 pwg->num_bins ++;
160 }
161 else if (!strcasecmp(line, "NumSizes"))
162 {
163 if (num_sizes > 0)
164 {
165 DEBUG_puts("_pwgCreateWithFile: NumSizes listed multiple times.");
166 _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PWG mapping file."), 1);
167 goto create_error;
168 }
169
170 if ((num_sizes = atoi(value)) <= 0 || num_sizes > 65536)
171 {
172 DEBUG_printf(("_pwgCreateWithFile: Bad NumSizes value %d on line %d.",
173 num_sizes, linenum));
174 _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PWG mapping file."), 1);
175 goto create_error;
176 }
177
178 if ((pwg->sizes = calloc(num_sizes, sizeof(_pwg_size_t))) == NULL)
179 {
180 DEBUG_printf(("_pwgCreateWithFile: Unable to allocate %d sizes.",
181 num_sizes));
182 _cupsSetError(IPP_INTERNAL_ERROR, strerror(errno), 0);
183 goto create_error;
184 }
185 }
186 else if (!strcasecmp(line, "Size"))
187 {
188 if (pwg->num_sizes >= num_sizes)
189 {
190 DEBUG_printf(("_pwgCreateWithFile: Too many Size's on line %d.",
191 linenum));
192 _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PWG mapping file."), 1);
193 goto create_error;
194 }
195
196 size = pwg->sizes + pwg->num_sizes;
197
198 if (sscanf(value, "%127s%40s%d%d%d%d%d%d", pwg_keyword, ppd_keyword,
199 &(size->width), &(size->length), &(size->left),
200 &(size->bottom), &(size->right), &(size->top)) != 8)
201 {
202 DEBUG_printf(("_pwgCreateWithFile: Bad Size on line %d.", linenum));
203 _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PWG mapping file."), 1);
204 goto create_error;
205 }
206
207 size->map.pwg = _cupsStrAlloc(pwg_keyword);
208 size->map.ppd = _cupsStrAlloc(ppd_keyword);
209
210 pwg->num_sizes ++;
211 }
212 else if (!strcasecmp(line, "CustomSize"))
213 {
214 if (pwg->custom_max_width > 0)
215 {
216 DEBUG_printf(("_pwgCreateWithFile: Too many CustomSize's on line %d.",
217 linenum));
218 _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PWG mapping file."), 1);
219 goto create_error;
220 }
221
222 if (sscanf(value, "%d%d%d%d%d%d%d%d", &(pwg->custom_max_width),
223 &(pwg->custom_max_length), &(pwg->custom_min_width),
224 &(pwg->custom_min_length), &(pwg->custom_size.left),
225 &(pwg->custom_size.bottom), &(pwg->custom_size.right),
226 &(pwg->custom_size.top)) != 8)
227 {
228 DEBUG_printf(("_pwgCreateWithFile: Bad CustomSize on line %d.", linenum));
229 _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PWG mapping file."), 1);
230 goto create_error;
231 }
232
233 _pwgGenerateSize(pwg_keyword, sizeof(pwg_keyword), "custom", "max",
234 pwg->custom_max_width, pwg->custom_max_length);
235 pwg->custom_max_keyword = _cupsStrAlloc(pwg_keyword);
236
237 _pwgGenerateSize(pwg_keyword, sizeof(pwg_keyword), "custom", "min",
238 pwg->custom_min_width, pwg->custom_min_length);
239 pwg->custom_min_keyword = _cupsStrAlloc(pwg_keyword);
240 }
241 else if (!strcasecmp(line, "NumSources"))
242 {
243 if (num_sources > 0)
244 {
245 DEBUG_puts("_pwgCreateWithFile: NumSources listed multiple times.");
246 _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PWG mapping file."), 1);
247 goto create_error;
248 }
249
250 if ((num_sources = atoi(value)) <= 0 || num_sources > 65536)
251 {
252 DEBUG_printf(("_pwgCreateWithFile: Bad NumSources value %d on line %d.",
253 num_sources, linenum));
254 _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PWG mapping file."), 1);
255 goto create_error;
256 }
257
258 if ((pwg->sources = calloc(num_sources, sizeof(_pwg_map_t))) == NULL)
259 {
260 DEBUG_printf(("_pwgCreateWithFile: Unable to allocate %d sources.",
261 num_sources));
262 _cupsSetError(IPP_INTERNAL_ERROR, strerror(errno), 0);
263 goto create_error;
264 }
265 }
266 else if (!strcasecmp(line, "Source"))
267 {
268 if (sscanf(value, "%127s%40s", pwg_keyword, ppd_keyword) != 2)
269 {
270 DEBUG_printf(("_pwgCreateWithFile: Bad Source on line %d.", linenum));
271 _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PWG mapping file."), 1);
272 goto create_error;
273 }
274
275 if (pwg->num_sources >= num_sources)
276 {
277 DEBUG_printf(("_pwgCreateWithFile: Too many Source's on line %d.",
278 linenum));
279 _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PWG mapping file."), 1);
280 goto create_error;
281 }
282
283 map = pwg->sources + pwg->num_sources;
284 map->pwg = _cupsStrAlloc(pwg_keyword);
285 map->ppd = _cupsStrAlloc(ppd_keyword);
286
287 pwg->num_sources ++;
288 }
289 else if (!strcasecmp(line, "NumTypes"))
290 {
291 if (num_types > 0)
292 {
293 DEBUG_puts("_pwgCreateWithFile: NumTypes listed multiple times.");
294 _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PWG mapping file."), 1);
295 goto create_error;
296 }
297
298 if ((num_types = atoi(value)) <= 0 || num_types > 65536)
299 {
300 DEBUG_printf(("_pwgCreateWithFile: Bad NumTypes value %d on line %d.",
301 num_types, linenum));
302 _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PWG mapping file."), 1);
303 goto create_error;
304 }
305
306 if ((pwg->types = calloc(num_types, sizeof(_pwg_map_t))) == NULL)
307 {
308 DEBUG_printf(("_pwgCreateWithFile: Unable to allocate %d types.",
309 num_types));
310 _cupsSetError(IPP_INTERNAL_ERROR, strerror(errno), 0);
311 goto create_error;
312 }
313 }
314 else if (!strcasecmp(line, "Type"))
315 {
316 if (sscanf(value, "%127s%40s", pwg_keyword, ppd_keyword) != 2)
317 {
318 DEBUG_printf(("_pwgCreateWithFile: Bad Type on line %d.", linenum));
319 _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PWG mapping file."), 1);
320 goto create_error;
321 }
322
323 if (pwg->num_types >= num_types)
324 {
325 DEBUG_printf(("_pwgCreateWithFile: Too many Type's on line %d.",
326 linenum));
327 _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PWG mapping file."), 1);
328 goto create_error;
329 }
330
331 map = pwg->types + pwg->num_types;
332 map->pwg = _cupsStrAlloc(pwg_keyword);
333 map->ppd = _cupsStrAlloc(ppd_keyword);
334
335 pwg->num_types ++;
336 }
337 else if (!strcasecmp(line, "Preset"))
338 {
339 /*
340 * Preset output-mode print-quality name=value ...
341 */
342
343 output_mode = (_pwg_output_mode_t)strtol(value, &valueptr, 10);
344 print_quality = (_pwg_print_quality_t)strtol(valueptr, &valueptr, 10);
345
346 if (output_mode < _PWG_OUTPUT_MODE_MONOCHROME ||
347 output_mode >= _PWG_OUTPUT_MODE_MAX ||
348 print_quality < _PWG_PRINT_QUALITY_DRAFT ||
349 print_quality >= _PWG_PRINT_QUALITY_MAX ||
350 valueptr == value || !*valueptr)
351 {
352 DEBUG_printf(("_pwgCreateWithFile: Bad Preset on line %d.", linenum));
353 _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PWG mapping file."), 1);
354 goto create_error;
355 }
356
357 pwg->num_presets[output_mode][print_quality] =
358 cupsParseOptions(valueptr, 0,
359 pwg->presets[output_mode] + print_quality);
360 }
361 else if (!strcasecmp(line, "SidesOption"))
362 pwg->sides_option = _cupsStrAlloc(value);
363 else if (!strcasecmp(line, "Sides1Sided"))
364 pwg->sides_1sided = _cupsStrAlloc(value);
365 else if (!strcasecmp(line, "Sides2SidedLong"))
366 pwg->sides_2sided_long = _cupsStrAlloc(value);
367 else if (!strcasecmp(line, "Sides2SidedShort"))
368 pwg->sides_2sided_short = _cupsStrAlloc(value);
369 else
370 {
371 DEBUG_printf(("_pwgCreateWithFile: Unknown %s on line %d.", line,
372 linenum));
373 _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PWG mapping file."), 1);
374 goto create_error;
375 }
376 }
377
378 if (pwg->num_sizes < num_sizes)
379 {
380 DEBUG_printf(("_pwgCreateWithFile: Not enough sizes (%d < %d).",
381 pwg->num_sizes, num_sizes));
382 _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PWG mapping file."), 1);
383 goto create_error;
384 }
385
386 if (pwg->num_sources < num_sources)
387 {
388 DEBUG_printf(("_pwgCreateWithFile: Not enough sources (%d < %d).",
389 pwg->num_sources, num_sources));
390 _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PWG mapping file."), 1);
391 goto create_error;
392 }
393
394 if (pwg->num_types < num_types)
395 {
396 DEBUG_printf(("_pwgCreateWithFile: Not enough types (%d < %d).",
397 pwg->num_types, num_types));
398 _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PWG mapping file."), 1);
399 goto create_error;
400 }
401
402 cupsFileClose(fp);
403
404 return (pwg);
405
406 /*
407 * If we get here the file was bad - free any data and return...
408 */
409
410 create_error:
411
412 cupsFileClose(fp);
413 _pwgDestroy(pwg);
414
415 return (NULL);
416 }
417
418
419 /*
420 * '_pwgDestroy()' - Free all memory used for PWG mapping data.
421 */
422
423 void
424 _pwgDestroy(_pwg_t *pwg) /* I - PWG mapping data */
425 {
426 int i; /* Looping var */
427 _pwg_map_t *map; /* Current map */
428 _pwg_size_t *size; /* Current size */
429
430
431 /*
432 * Range check input...
433 */
434
435 if (!pwg)
436 return;
437
438 /*
439 * Free memory as needed...
440 */
441
442 if (pwg->bins)
443 {
444 for (i = pwg->num_bins, map = pwg->bins; i > 0; i --, map ++)
445 {
446 _cupsStrFree(map->pwg);
447 _cupsStrFree(map->ppd);
448 }
449
450 free(pwg->bins);
451 }
452
453 if (pwg->sizes)
454 {
455 for (i = pwg->num_sizes, size = pwg->sizes; i > 0; i --, size ++)
456 {
457 _cupsStrFree(size->map.pwg);
458 _cupsStrFree(size->map.ppd);
459 }
460
461 free(pwg->sizes);
462 }
463
464 if (pwg->sources)
465 {
466 for (i = pwg->num_sources, map = pwg->sources; i > 0; i --, map ++)
467 {
468 _cupsStrFree(map->pwg);
469 _cupsStrFree(map->ppd);
470 }
471
472 free(pwg->sources);
473 }
474
475 if (pwg->types)
476 {
477 for (i = pwg->num_types, map = pwg->types; i > 0; i --, map ++)
478 {
479 _cupsStrFree(map->pwg);
480 _cupsStrFree(map->ppd);
481 }
482
483 free(pwg->types);
484 }
485
486 if (pwg->custom_max_keyword)
487 _cupsStrFree(pwg->custom_max_keyword);
488
489 if (pwg->custom_min_keyword)
490 _cupsStrFree(pwg->custom_min_keyword);
491
492 free(pwg);
493 }
494
495
496 /*
497 * '_pwgWriteFile()' - Write PWG mapping data to a file.
498 */
499
500 int /* O - 1 on success, 0 on failure */
501 _pwgWriteFile(_pwg_t *pwg, /* I - PWG mapping data */
502 const char *filename) /* I - File to write */
503 {
504 int i, j, k; /* Looping vars */
505 cups_file_t *fp; /* Output file */
506 _pwg_size_t *size; /* Current size */
507 _pwg_map_t *map; /* Current map */
508 cups_option_t *option; /* Current option */
509
510
511 /*
512 * Range check input...
513 */
514
515 if (!pwg || !filename)
516 {
517 _cupsSetError(IPP_INTERNAL_ERROR, strerror(EINVAL), 0);
518 return (0);
519 }
520
521 /*
522 * Open the file and write with compression...
523 */
524
525 if ((fp = cupsFileOpen(filename, "w9")) == NULL)
526 {
527 _cupsSetError(IPP_INTERNAL_ERROR, strerror(errno), 0);
528 return (0);
529 }
530
531 /*
532 * Standard header...
533 */
534
535 cupsFilePuts(fp, "#CUPS-PWGPPD\n");
536
537 /*
538 * Output bins...
539 */
540
541 if (pwg->num_bins > 0)
542 {
543 cupsFilePrintf(fp, "NumBins %d\n", pwg->num_bins);
544 for (i = pwg->num_bins, map = pwg->bins; i > 0; i --, map ++)
545 cupsFilePrintf(fp, "Bin %s %s\n", map->pwg, map->ppd);
546 }
547
548 /*
549 * Media sizes...
550 */
551
552 cupsFilePrintf(fp, "NumSizes %d\n", pwg->num_sizes);
553 for (i = pwg->num_sizes, size = pwg->sizes; i > 0; i --, size ++)
554 cupsFilePrintf(fp, "Size %s %s %d %d %d %d %d %d\n", size->map.pwg,
555 size->map.ppd, size->width, size->length, size->left,
556 size->bottom, size->right, size->top);
557 if (pwg->custom_max_width > 0)
558 cupsFilePrintf(fp, "CustomSize %d %d %d %d %d %d %d %d\n",
559 pwg->custom_max_width, pwg->custom_max_length,
560 pwg->custom_min_width, pwg->custom_min_length,
561 pwg->custom_size.left, pwg->custom_size.bottom,
562 pwg->custom_size.right, pwg->custom_size.top);
563
564 /*
565 * Media sources...
566 */
567
568 if (pwg->num_sources > 0)
569 {
570 cupsFilePrintf(fp, "NumSources %d\n", pwg->num_sources);
571 for (i = pwg->num_sources, map = pwg->sources; i > 0; i --, map ++)
572 cupsFilePrintf(fp, "Source %s %s\n", map->pwg, map->ppd);
573 }
574
575 /*
576 * Media types...
577 */
578
579 if (pwg->num_types > 0)
580 {
581 cupsFilePrintf(fp, "NumTypes %d\n", pwg->num_types);
582 for (i = pwg->num_types, map = pwg->types; i > 0; i --, map ++)
583 cupsFilePrintf(fp, "Type %s %s\n", map->pwg, map->ppd);
584 }
585
586 /*
587 * Presets...
588 */
589
590 for (i = _PWG_OUTPUT_MODE_MONOCHROME; i < _PWG_OUTPUT_MODE_MAX; i ++)
591 for (j = _PWG_PRINT_QUALITY_DRAFT; i < _PWG_PRINT_QUALITY_MAX; i ++)
592 if (pwg->num_presets[i][j])
593 {
594 cupsFilePrintf(fp, "Preset %d %d", i, j);
595 for (k = pwg->num_presets[i][j], option = pwg->presets[i][j];
596 k > 0;
597 k --, option ++)
598 cupsFilePrintf(fp, " %s=%s", option->name, option->value);
599 cupsFilePutChar(fp, '\n');
600 }
601
602 /*
603 * Duplex/sides...
604 */
605
606 if (pwg->sides_option)
607 cupsFilePrintf(fp, "SidesOption %s\n", pwg->sides_option);
608
609 if (pwg->sides_1sided)
610 cupsFilePrintf(fp, "Sides1Sided %s\n", pwg->sides_1sided);
611
612 if (pwg->sides_2sided_long)
613 cupsFilePrintf(fp, "Sides2SidedLong %s\n", pwg->sides_2sided_long);
614
615 if (pwg->sides_2sided_short)
616 cupsFilePrintf(fp, "Sides2SidedShort %s\n", pwg->sides_2sided_short);
617
618 /*
619 * Close and return...
620 */
621
622 return (!cupsFileClose(fp));
623 }
624
625
626 /*
627 * End of "$Id$".
628 */