]> git.ipfire.org Git - thirdparty/cups.git/blame - cups/pwg-file.c
Merge changes from CUPS 1.5svn-r9567
[thirdparty/cups.git] / cups / pwg-file.c
CommitLineData
54afec33
MS
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
71e16022 27#include "cups-private.h"
54afec33
MS
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 */
cc754834 45 num_bins, /* Number of bins in file */
54afec33
MS
46 num_sizes, /* Number of sizes in file */
47 num_sources, /* Number of sources in file */
48 num_types; /* Number of types in file */
c7017ecc 49 char line[2048], /* Current line */
54afec33 50 *value, /* Pointer to value in line */
c7017ecc 51 *valueptr, /* Pointer into value */
54afec33
MS
52 pwg_keyword[128], /* PWG keyword */
53 ppd_keyword[PPD_MAX_NAME];
54 /* PPD keyword */
c7017ecc
MS
55 _pwg_output_mode_t output_mode; /* Output mode for preset */
56 _pwg_print_quality_t print_quality; /* Print quality for preset */
54afec33
MS
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;
cc754834 97 num_bins = 0;
54afec33
MS
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 }
cc754834
MS
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 }
54afec33
MS
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 }
4220952d
MS
241 else if (!strcasecmp(line, "SourceOption"))
242 {
243 pwg->source_option = _cupsStrAlloc(value);
244 }
54afec33
MS
245 else if (!strcasecmp(line, "NumSources"))
246 {
247 if (num_sources > 0)
248 {
249 DEBUG_puts("_pwgCreateWithFile: NumSources listed multiple times.");
250 _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PWG mapping file."), 1);
251 goto create_error;
252 }
253
254 if ((num_sources = atoi(value)) <= 0 || num_sources > 65536)
255 {
256 DEBUG_printf(("_pwgCreateWithFile: Bad NumSources value %d on line %d.",
257 num_sources, linenum));
258 _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PWG mapping file."), 1);
259 goto create_error;
260 }
261
262 if ((pwg->sources = calloc(num_sources, sizeof(_pwg_map_t))) == NULL)
263 {
264 DEBUG_printf(("_pwgCreateWithFile: Unable to allocate %d sources.",
265 num_sources));
266 _cupsSetError(IPP_INTERNAL_ERROR, strerror(errno), 0);
267 goto create_error;
268 }
269 }
270 else if (!strcasecmp(line, "Source"))
271 {
272 if (sscanf(value, "%127s%40s", pwg_keyword, ppd_keyword) != 2)
273 {
274 DEBUG_printf(("_pwgCreateWithFile: Bad Source on line %d.", linenum));
275 _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PWG mapping file."), 1);
276 goto create_error;
277 }
278
279 if (pwg->num_sources >= num_sources)
280 {
281 DEBUG_printf(("_pwgCreateWithFile: Too many Source's on line %d.",
282 linenum));
283 _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PWG mapping file."), 1);
284 goto create_error;
285 }
286
287 map = pwg->sources + pwg->num_sources;
288 map->pwg = _cupsStrAlloc(pwg_keyword);
289 map->ppd = _cupsStrAlloc(ppd_keyword);
290
291 pwg->num_sources ++;
292 }
293 else if (!strcasecmp(line, "NumTypes"))
294 {
295 if (num_types > 0)
296 {
297 DEBUG_puts("_pwgCreateWithFile: NumTypes listed multiple times.");
298 _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PWG mapping file."), 1);
299 goto create_error;
300 }
301
302 if ((num_types = atoi(value)) <= 0 || num_types > 65536)
303 {
304 DEBUG_printf(("_pwgCreateWithFile: Bad NumTypes value %d on line %d.",
305 num_types, linenum));
306 _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PWG mapping file."), 1);
307 goto create_error;
308 }
309
310 if ((pwg->types = calloc(num_types, sizeof(_pwg_map_t))) == NULL)
311 {
312 DEBUG_printf(("_pwgCreateWithFile: Unable to allocate %d types.",
313 num_types));
314 _cupsSetError(IPP_INTERNAL_ERROR, strerror(errno), 0);
315 goto create_error;
316 }
317 }
318 else if (!strcasecmp(line, "Type"))
319 {
320 if (sscanf(value, "%127s%40s", pwg_keyword, ppd_keyword) != 2)
321 {
322 DEBUG_printf(("_pwgCreateWithFile: Bad Type on line %d.", linenum));
323 _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PWG mapping file."), 1);
324 goto create_error;
325 }
326
327 if (pwg->num_types >= num_types)
328 {
329 DEBUG_printf(("_pwgCreateWithFile: Too many Type's on line %d.",
330 linenum));
331 _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PWG mapping file."), 1);
332 goto create_error;
333 }
334
335 map = pwg->types + pwg->num_types;
336 map->pwg = _cupsStrAlloc(pwg_keyword);
337 map->ppd = _cupsStrAlloc(ppd_keyword);
338
339 pwg->num_types ++;
340 }
c7017ecc
MS
341 else if (!strcasecmp(line, "Preset"))
342 {
343 /*
344 * Preset output-mode print-quality name=value ...
345 */
346
347 output_mode = (_pwg_output_mode_t)strtol(value, &valueptr, 10);
348 print_quality = (_pwg_print_quality_t)strtol(valueptr, &valueptr, 10);
349
350 if (output_mode < _PWG_OUTPUT_MODE_MONOCHROME ||
351 output_mode >= _PWG_OUTPUT_MODE_MAX ||
352 print_quality < _PWG_PRINT_QUALITY_DRAFT ||
353 print_quality >= _PWG_PRINT_QUALITY_MAX ||
354 valueptr == value || !*valueptr)
355 {
356 DEBUG_printf(("_pwgCreateWithFile: Bad Preset on line %d.", linenum));
357 _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PWG mapping file."), 1);
358 goto create_error;
359 }
360
361 pwg->num_presets[output_mode][print_quality] =
362 cupsParseOptions(valueptr, 0,
363 pwg->presets[output_mode] + print_quality);
364 }
365 else if (!strcasecmp(line, "SidesOption"))
366 pwg->sides_option = _cupsStrAlloc(value);
367 else if (!strcasecmp(line, "Sides1Sided"))
368 pwg->sides_1sided = _cupsStrAlloc(value);
369 else if (!strcasecmp(line, "Sides2SidedLong"))
370 pwg->sides_2sided_long = _cupsStrAlloc(value);
371 else if (!strcasecmp(line, "Sides2SidedShort"))
372 pwg->sides_2sided_short = _cupsStrAlloc(value);
54afec33
MS
373 else
374 {
375 DEBUG_printf(("_pwgCreateWithFile: Unknown %s on line %d.", line,
376 linenum));
377 _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PWG mapping file."), 1);
378 goto create_error;
379 }
380 }
381
382 if (pwg->num_sizes < num_sizes)
383 {
384 DEBUG_printf(("_pwgCreateWithFile: Not enough sizes (%d < %d).",
385 pwg->num_sizes, num_sizes));
386 _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PWG mapping file."), 1);
387 goto create_error;
388 }
389
390 if (pwg->num_sources < num_sources)
391 {
392 DEBUG_printf(("_pwgCreateWithFile: Not enough sources (%d < %d).",
393 pwg->num_sources, num_sources));
394 _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PWG mapping file."), 1);
395 goto create_error;
396 }
397
398 if (pwg->num_types < num_types)
399 {
400 DEBUG_printf(("_pwgCreateWithFile: Not enough types (%d < %d).",
401 pwg->num_types, num_types));
402 _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PWG mapping file."), 1);
403 goto create_error;
404 }
405
406 cupsFileClose(fp);
407
408 return (pwg);
409
410 /*
411 * If we get here the file was bad - free any data and return...
412 */
413
414 create_error:
415
416 cupsFileClose(fp);
417 _pwgDestroy(pwg);
418
419 return (NULL);
420}
421
422
423/*
424 * '_pwgDestroy()' - Free all memory used for PWG mapping data.
425 */
426
427void
428_pwgDestroy(_pwg_t *pwg) /* I - PWG mapping data */
429{
430 int i; /* Looping var */
431 _pwg_map_t *map; /* Current map */
432 _pwg_size_t *size; /* Current size */
433
434
435 /*
436 * Range check input...
437 */
438
439 if (!pwg)
440 return;
441
442 /*
443 * Free memory as needed...
444 */
445
cc754834
MS
446 if (pwg->bins)
447 {
448 for (i = pwg->num_bins, map = pwg->bins; i > 0; i --, map ++)
449 {
450 _cupsStrFree(map->pwg);
451 _cupsStrFree(map->ppd);
452 }
453
454 free(pwg->bins);
455 }
456
54afec33
MS
457 if (pwg->sizes)
458 {
459 for (i = pwg->num_sizes, size = pwg->sizes; i > 0; i --, size ++)
460 {
461 _cupsStrFree(size->map.pwg);
462 _cupsStrFree(size->map.ppd);
463 }
464
465 free(pwg->sizes);
466 }
467
4220952d
MS
468 if (pwg->source_option)
469 _cupsStrFree(pwg->source_option);
470
54afec33
MS
471 if (pwg->sources)
472 {
473 for (i = pwg->num_sources, map = pwg->sources; i > 0; i --, map ++)
474 {
475 _cupsStrFree(map->pwg);
476 _cupsStrFree(map->ppd);
477 }
478
479 free(pwg->sources);
480 }
481
482 if (pwg->types)
483 {
484 for (i = pwg->num_types, map = pwg->types; i > 0; i --, map ++)
485 {
486 _cupsStrFree(map->pwg);
487 _cupsStrFree(map->ppd);
488 }
489
490 free(pwg->types);
491 }
492
493 if (pwg->custom_max_keyword)
494 _cupsStrFree(pwg->custom_max_keyword);
495
496 if (pwg->custom_min_keyword)
497 _cupsStrFree(pwg->custom_min_keyword);
498
499 free(pwg);
500}
501
502
503/*
504 * '_pwgWriteFile()' - Write PWG mapping data to a file.
505 */
506
507int /* O - 1 on success, 0 on failure */
508_pwgWriteFile(_pwg_t *pwg, /* I - PWG mapping data */
509 const char *filename) /* I - File to write */
510{
c7017ecc 511 int i, j, k; /* Looping vars */
54afec33
MS
512 cups_file_t *fp; /* Output file */
513 _pwg_size_t *size; /* Current size */
514 _pwg_map_t *map; /* Current map */
c7017ecc 515 cups_option_t *option; /* Current option */
54afec33
MS
516
517
518 /*
519 * Range check input...
520 */
521
522 if (!pwg || !filename)
523 {
524 _cupsSetError(IPP_INTERNAL_ERROR, strerror(EINVAL), 0);
525 return (0);
526 }
527
528 /*
529 * Open the file and write with compression...
530 */
531
532 if ((fp = cupsFileOpen(filename, "w9")) == NULL)
533 {
534 _cupsSetError(IPP_INTERNAL_ERROR, strerror(errno), 0);
535 return (0);
536 }
537
538 /*
539 * Standard header...
540 */
541
542 cupsFilePuts(fp, "#CUPS-PWGPPD\n");
543
cc754834
MS
544 /*
545 * Output bins...
546 */
547
548 if (pwg->num_bins > 0)
549 {
550 cupsFilePrintf(fp, "NumBins %d\n", pwg->num_bins);
551 for (i = pwg->num_bins, map = pwg->bins; i > 0; i --, map ++)
552 cupsFilePrintf(fp, "Bin %s %s\n", map->pwg, map->ppd);
553 }
554
54afec33
MS
555 /*
556 * Media sizes...
557 */
558
559 cupsFilePrintf(fp, "NumSizes %d\n", pwg->num_sizes);
560 for (i = pwg->num_sizes, size = pwg->sizes; i > 0; i --, size ++)
561 cupsFilePrintf(fp, "Size %s %s %d %d %d %d %d %d\n", size->map.pwg,
562 size->map.ppd, size->width, size->length, size->left,
563 size->bottom, size->right, size->top);
564 if (pwg->custom_max_width > 0)
565 cupsFilePrintf(fp, "CustomSize %d %d %d %d %d %d %d %d\n",
566 pwg->custom_max_width, pwg->custom_max_length,
567 pwg->custom_min_width, pwg->custom_min_length,
568 pwg->custom_size.left, pwg->custom_size.bottom,
569 pwg->custom_size.right, pwg->custom_size.top);
570
571 /*
572 * Media sources...
573 */
574
4220952d
MS
575 if (pwg->source_option)
576 cupsFilePrintf(fp, "SourceOption %s\n", pwg->source_option);
577
54afec33
MS
578 if (pwg->num_sources > 0)
579 {
580 cupsFilePrintf(fp, "NumSources %d\n", pwg->num_sources);
581 for (i = pwg->num_sources, map = pwg->sources; i > 0; i --, map ++)
582 cupsFilePrintf(fp, "Source %s %s\n", map->pwg, map->ppd);
583 }
584
585 /*
586 * Media types...
587 */
588
589 if (pwg->num_types > 0)
590 {
591 cupsFilePrintf(fp, "NumTypes %d\n", pwg->num_types);
592 for (i = pwg->num_types, map = pwg->types; i > 0; i --, map ++)
593 cupsFilePrintf(fp, "Type %s %s\n", map->pwg, map->ppd);
594 }
595
c7017ecc
MS
596 /*
597 * Presets...
598 */
599
600 for (i = _PWG_OUTPUT_MODE_MONOCHROME; i < _PWG_OUTPUT_MODE_MAX; i ++)
030ae6a1 601 for (j = _PWG_PRINT_QUALITY_DRAFT; j < _PWG_PRINT_QUALITY_MAX; j ++)
c7017ecc
MS
602 if (pwg->num_presets[i][j])
603 {
604 cupsFilePrintf(fp, "Preset %d %d", i, j);
605 for (k = pwg->num_presets[i][j], option = pwg->presets[i][j];
606 k > 0;
607 k --, option ++)
608 cupsFilePrintf(fp, " %s=%s", option->name, option->value);
609 cupsFilePutChar(fp, '\n');
610 }
611
612 /*
613 * Duplex/sides...
614 */
615
616 if (pwg->sides_option)
617 cupsFilePrintf(fp, "SidesOption %s\n", pwg->sides_option);
618
619 if (pwg->sides_1sided)
620 cupsFilePrintf(fp, "Sides1Sided %s\n", pwg->sides_1sided);
621
622 if (pwg->sides_2sided_long)
623 cupsFilePrintf(fp, "Sides2SidedLong %s\n", pwg->sides_2sided_long);
624
625 if (pwg->sides_2sided_short)
626 cupsFilePrintf(fp, "Sides2SidedShort %s\n", pwg->sides_2sided_short);
627
54afec33
MS
628 /*
629 * Close and return...
630 */
631
632 return (!cupsFileClose(fp));
633}
634
635
636/*
637 * End of "$Id$".
638 */