1*5e7646d2SAndroid Build Coastguard Worker /*
2*5e7646d2SAndroid Build Coastguard Worker * PPD file routines for CUPS.
3*5e7646d2SAndroid Build Coastguard Worker *
4*5e7646d2SAndroid Build Coastguard Worker * Copyright © 2007-2019 by Apple Inc.
5*5e7646d2SAndroid Build Coastguard Worker * Copyright © 1997-2007 by Easy Software Products, all rights reserved.
6*5e7646d2SAndroid Build Coastguard Worker *
7*5e7646d2SAndroid Build Coastguard Worker * Licensed under Apache License v2.0. See the file "LICENSE" for more
8*5e7646d2SAndroid Build Coastguard Worker * information.
9*5e7646d2SAndroid Build Coastguard Worker *
10*5e7646d2SAndroid Build Coastguard Worker * PostScript is a trademark of Adobe Systems, Inc.
11*5e7646d2SAndroid Build Coastguard Worker */
12*5e7646d2SAndroid Build Coastguard Worker
13*5e7646d2SAndroid Build Coastguard Worker /*
14*5e7646d2SAndroid Build Coastguard Worker * Include necessary headers.
15*5e7646d2SAndroid Build Coastguard Worker */
16*5e7646d2SAndroid Build Coastguard Worker
17*5e7646d2SAndroid Build Coastguard Worker #include "cups-private.h"
18*5e7646d2SAndroid Build Coastguard Worker #include "ppd-private.h"
19*5e7646d2SAndroid Build Coastguard Worker #include "debug-internal.h"
20*5e7646d2SAndroid Build Coastguard Worker
21*5e7646d2SAndroid Build Coastguard Worker
22*5e7646d2SAndroid Build Coastguard Worker /*
23*5e7646d2SAndroid Build Coastguard Worker * Definitions...
24*5e7646d2SAndroid Build Coastguard Worker */
25*5e7646d2SAndroid Build Coastguard Worker
26*5e7646d2SAndroid Build Coastguard Worker #define PPD_KEYWORD 1 /* Line contained a keyword */
27*5e7646d2SAndroid Build Coastguard Worker #define PPD_OPTION 2 /* Line contained an option name */
28*5e7646d2SAndroid Build Coastguard Worker #define PPD_TEXT 4 /* Line contained human-readable text */
29*5e7646d2SAndroid Build Coastguard Worker #define PPD_STRING 8 /* Line contained a string or code */
30*5e7646d2SAndroid Build Coastguard Worker
31*5e7646d2SAndroid Build Coastguard Worker #define PPD_HASHSIZE 512 /* Size of hash */
32*5e7646d2SAndroid Build Coastguard Worker
33*5e7646d2SAndroid Build Coastguard Worker
34*5e7646d2SAndroid Build Coastguard Worker /*
35*5e7646d2SAndroid Build Coastguard Worker * Line buffer structure...
36*5e7646d2SAndroid Build Coastguard Worker */
37*5e7646d2SAndroid Build Coastguard Worker
38*5e7646d2SAndroid Build Coastguard Worker typedef struct _ppd_line_s
39*5e7646d2SAndroid Build Coastguard Worker {
40*5e7646d2SAndroid Build Coastguard Worker char *buffer; /* Pointer to buffer */
41*5e7646d2SAndroid Build Coastguard Worker size_t bufsize; /* Size of the buffer */
42*5e7646d2SAndroid Build Coastguard Worker } _ppd_line_t;
43*5e7646d2SAndroid Build Coastguard Worker
44*5e7646d2SAndroid Build Coastguard Worker
45*5e7646d2SAndroid Build Coastguard Worker /*
46*5e7646d2SAndroid Build Coastguard Worker * Local globals...
47*5e7646d2SAndroid Build Coastguard Worker */
48*5e7646d2SAndroid Build Coastguard Worker
49*5e7646d2SAndroid Build Coastguard Worker static _cups_threadkey_t ppd_globals_key = _CUPS_THREADKEY_INITIALIZER;
50*5e7646d2SAndroid Build Coastguard Worker /* Thread local storage key */
51*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_PTHREAD_H
52*5e7646d2SAndroid Build Coastguard Worker static pthread_once_t ppd_globals_key_once = PTHREAD_ONCE_INIT;
53*5e7646d2SAndroid Build Coastguard Worker /* One-time initialization object */
54*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_PTHREAD_H */
55*5e7646d2SAndroid Build Coastguard Worker
56*5e7646d2SAndroid Build Coastguard Worker
57*5e7646d2SAndroid Build Coastguard Worker /*
58*5e7646d2SAndroid Build Coastguard Worker * Local functions...
59*5e7646d2SAndroid Build Coastguard Worker */
60*5e7646d2SAndroid Build Coastguard Worker
61*5e7646d2SAndroid Build Coastguard Worker static ppd_attr_t *ppd_add_attr(ppd_file_t *ppd, const char *name,
62*5e7646d2SAndroid Build Coastguard Worker const char *spec, const char *text,
63*5e7646d2SAndroid Build Coastguard Worker const char *value);
64*5e7646d2SAndroid Build Coastguard Worker static ppd_choice_t *ppd_add_choice(ppd_option_t *option, const char *name);
65*5e7646d2SAndroid Build Coastguard Worker static ppd_size_t *ppd_add_size(ppd_file_t *ppd, const char *name);
66*5e7646d2SAndroid Build Coastguard Worker static int ppd_compare_attrs(ppd_attr_t *a, ppd_attr_t *b);
67*5e7646d2SAndroid Build Coastguard Worker static int ppd_compare_choices(ppd_choice_t *a, ppd_choice_t *b);
68*5e7646d2SAndroid Build Coastguard Worker static int ppd_compare_coptions(ppd_coption_t *a,
69*5e7646d2SAndroid Build Coastguard Worker ppd_coption_t *b);
70*5e7646d2SAndroid Build Coastguard Worker static int ppd_compare_options(ppd_option_t *a, ppd_option_t *b);
71*5e7646d2SAndroid Build Coastguard Worker static int ppd_decode(char *string);
72*5e7646d2SAndroid Build Coastguard Worker static void ppd_free_filters(ppd_file_t *ppd);
73*5e7646d2SAndroid Build Coastguard Worker static void ppd_free_group(ppd_group_t *group);
74*5e7646d2SAndroid Build Coastguard Worker static void ppd_free_option(ppd_option_t *option);
75*5e7646d2SAndroid Build Coastguard Worker static ppd_coption_t *ppd_get_coption(ppd_file_t *ppd, const char *name);
76*5e7646d2SAndroid Build Coastguard Worker static ppd_cparam_t *ppd_get_cparam(ppd_coption_t *opt,
77*5e7646d2SAndroid Build Coastguard Worker const char *param,
78*5e7646d2SAndroid Build Coastguard Worker const char *text);
79*5e7646d2SAndroid Build Coastguard Worker static ppd_group_t *ppd_get_group(ppd_file_t *ppd, const char *name,
80*5e7646d2SAndroid Build Coastguard Worker const char *text, _ppd_globals_t *pg,
81*5e7646d2SAndroid Build Coastguard Worker cups_encoding_t encoding);
82*5e7646d2SAndroid Build Coastguard Worker static ppd_option_t *ppd_get_option(ppd_group_t *group, const char *name);
83*5e7646d2SAndroid Build Coastguard Worker static _ppd_globals_t *ppd_globals_alloc(void);
84*5e7646d2SAndroid Build Coastguard Worker #if defined(HAVE_PTHREAD_H) || defined(_WIN32)
85*5e7646d2SAndroid Build Coastguard Worker static void ppd_globals_free(_ppd_globals_t *g);
86*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_PTHREAD_H || _WIN32 */
87*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_PTHREAD_H
88*5e7646d2SAndroid Build Coastguard Worker static void ppd_globals_init(void);
89*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_PTHREAD_H */
90*5e7646d2SAndroid Build Coastguard Worker static int ppd_hash_option(ppd_option_t *option);
91*5e7646d2SAndroid Build Coastguard Worker static int ppd_read(cups_file_t *fp, _ppd_line_t *line,
92*5e7646d2SAndroid Build Coastguard Worker char *keyword, char *option, char *text,
93*5e7646d2SAndroid Build Coastguard Worker char **string, int ignoreblank,
94*5e7646d2SAndroid Build Coastguard Worker _ppd_globals_t *pg);
95*5e7646d2SAndroid Build Coastguard Worker static int ppd_update_filters(ppd_file_t *ppd,
96*5e7646d2SAndroid Build Coastguard Worker _ppd_globals_t *pg);
97*5e7646d2SAndroid Build Coastguard Worker
98*5e7646d2SAndroid Build Coastguard Worker
99*5e7646d2SAndroid Build Coastguard Worker /*
100*5e7646d2SAndroid Build Coastguard Worker * 'ppdClose()' - Free all memory used by the PPD file.
101*5e7646d2SAndroid Build Coastguard Worker */
102*5e7646d2SAndroid Build Coastguard Worker
103*5e7646d2SAndroid Build Coastguard Worker void
ppdClose(ppd_file_t * ppd)104*5e7646d2SAndroid Build Coastguard Worker ppdClose(ppd_file_t *ppd) /* I - PPD file record */
105*5e7646d2SAndroid Build Coastguard Worker {
106*5e7646d2SAndroid Build Coastguard Worker int i; /* Looping var */
107*5e7646d2SAndroid Build Coastguard Worker ppd_group_t *group; /* Current group */
108*5e7646d2SAndroid Build Coastguard Worker char **font; /* Current font */
109*5e7646d2SAndroid Build Coastguard Worker ppd_attr_t **attr; /* Current attribute */
110*5e7646d2SAndroid Build Coastguard Worker ppd_coption_t *coption; /* Current custom option */
111*5e7646d2SAndroid Build Coastguard Worker ppd_cparam_t *cparam; /* Current custom parameter */
112*5e7646d2SAndroid Build Coastguard Worker
113*5e7646d2SAndroid Build Coastguard Worker
114*5e7646d2SAndroid Build Coastguard Worker /*
115*5e7646d2SAndroid Build Coastguard Worker * Range check arguments...
116*5e7646d2SAndroid Build Coastguard Worker */
117*5e7646d2SAndroid Build Coastguard Worker
118*5e7646d2SAndroid Build Coastguard Worker if (!ppd)
119*5e7646d2SAndroid Build Coastguard Worker return;
120*5e7646d2SAndroid Build Coastguard Worker
121*5e7646d2SAndroid Build Coastguard Worker /*
122*5e7646d2SAndroid Build Coastguard Worker * Free all strings at the top level...
123*5e7646d2SAndroid Build Coastguard Worker */
124*5e7646d2SAndroid Build Coastguard Worker
125*5e7646d2SAndroid Build Coastguard Worker free(ppd->lang_encoding);
126*5e7646d2SAndroid Build Coastguard Worker free(ppd->nickname);
127*5e7646d2SAndroid Build Coastguard Worker free(ppd->patches);
128*5e7646d2SAndroid Build Coastguard Worker free(ppd->emulations);
129*5e7646d2SAndroid Build Coastguard Worker free(ppd->jcl_begin);
130*5e7646d2SAndroid Build Coastguard Worker free(ppd->jcl_end);
131*5e7646d2SAndroid Build Coastguard Worker free(ppd->jcl_ps);
132*5e7646d2SAndroid Build Coastguard Worker
133*5e7646d2SAndroid Build Coastguard Worker /*
134*5e7646d2SAndroid Build Coastguard Worker * Free any UI groups, subgroups, and options...
135*5e7646d2SAndroid Build Coastguard Worker */
136*5e7646d2SAndroid Build Coastguard Worker
137*5e7646d2SAndroid Build Coastguard Worker if (ppd->num_groups > 0)
138*5e7646d2SAndroid Build Coastguard Worker {
139*5e7646d2SAndroid Build Coastguard Worker for (i = ppd->num_groups, group = ppd->groups; i > 0; i --, group ++)
140*5e7646d2SAndroid Build Coastguard Worker ppd_free_group(group);
141*5e7646d2SAndroid Build Coastguard Worker
142*5e7646d2SAndroid Build Coastguard Worker free(ppd->groups);
143*5e7646d2SAndroid Build Coastguard Worker }
144*5e7646d2SAndroid Build Coastguard Worker
145*5e7646d2SAndroid Build Coastguard Worker cupsArrayDelete(ppd->options);
146*5e7646d2SAndroid Build Coastguard Worker cupsArrayDelete(ppd->marked);
147*5e7646d2SAndroid Build Coastguard Worker
148*5e7646d2SAndroid Build Coastguard Worker /*
149*5e7646d2SAndroid Build Coastguard Worker * Free any page sizes...
150*5e7646d2SAndroid Build Coastguard Worker */
151*5e7646d2SAndroid Build Coastguard Worker
152*5e7646d2SAndroid Build Coastguard Worker if (ppd->num_sizes > 0)
153*5e7646d2SAndroid Build Coastguard Worker free(ppd->sizes);
154*5e7646d2SAndroid Build Coastguard Worker
155*5e7646d2SAndroid Build Coastguard Worker /*
156*5e7646d2SAndroid Build Coastguard Worker * Free any constraints...
157*5e7646d2SAndroid Build Coastguard Worker */
158*5e7646d2SAndroid Build Coastguard Worker
159*5e7646d2SAndroid Build Coastguard Worker if (ppd->num_consts > 0)
160*5e7646d2SAndroid Build Coastguard Worker free(ppd->consts);
161*5e7646d2SAndroid Build Coastguard Worker
162*5e7646d2SAndroid Build Coastguard Worker /*
163*5e7646d2SAndroid Build Coastguard Worker * Free any filters...
164*5e7646d2SAndroid Build Coastguard Worker */
165*5e7646d2SAndroid Build Coastguard Worker
166*5e7646d2SAndroid Build Coastguard Worker ppd_free_filters(ppd);
167*5e7646d2SAndroid Build Coastguard Worker
168*5e7646d2SAndroid Build Coastguard Worker /*
169*5e7646d2SAndroid Build Coastguard Worker * Free any fonts...
170*5e7646d2SAndroid Build Coastguard Worker */
171*5e7646d2SAndroid Build Coastguard Worker
172*5e7646d2SAndroid Build Coastguard Worker if (ppd->num_fonts > 0)
173*5e7646d2SAndroid Build Coastguard Worker {
174*5e7646d2SAndroid Build Coastguard Worker for (i = ppd->num_fonts, font = ppd->fonts; i > 0; i --, font ++)
175*5e7646d2SAndroid Build Coastguard Worker free(*font);
176*5e7646d2SAndroid Build Coastguard Worker
177*5e7646d2SAndroid Build Coastguard Worker free(ppd->fonts);
178*5e7646d2SAndroid Build Coastguard Worker }
179*5e7646d2SAndroid Build Coastguard Worker
180*5e7646d2SAndroid Build Coastguard Worker /*
181*5e7646d2SAndroid Build Coastguard Worker * Free any profiles...
182*5e7646d2SAndroid Build Coastguard Worker */
183*5e7646d2SAndroid Build Coastguard Worker
184*5e7646d2SAndroid Build Coastguard Worker if (ppd->num_profiles > 0)
185*5e7646d2SAndroid Build Coastguard Worker free(ppd->profiles);
186*5e7646d2SAndroid Build Coastguard Worker
187*5e7646d2SAndroid Build Coastguard Worker /*
188*5e7646d2SAndroid Build Coastguard Worker * Free any attributes...
189*5e7646d2SAndroid Build Coastguard Worker */
190*5e7646d2SAndroid Build Coastguard Worker
191*5e7646d2SAndroid Build Coastguard Worker if (ppd->num_attrs > 0)
192*5e7646d2SAndroid Build Coastguard Worker {
193*5e7646d2SAndroid Build Coastguard Worker for (i = ppd->num_attrs, attr = ppd->attrs; i > 0; i --, attr ++)
194*5e7646d2SAndroid Build Coastguard Worker {
195*5e7646d2SAndroid Build Coastguard Worker free((*attr)->value);
196*5e7646d2SAndroid Build Coastguard Worker free(*attr);
197*5e7646d2SAndroid Build Coastguard Worker }
198*5e7646d2SAndroid Build Coastguard Worker
199*5e7646d2SAndroid Build Coastguard Worker free(ppd->attrs);
200*5e7646d2SAndroid Build Coastguard Worker }
201*5e7646d2SAndroid Build Coastguard Worker
202*5e7646d2SAndroid Build Coastguard Worker cupsArrayDelete(ppd->sorted_attrs);
203*5e7646d2SAndroid Build Coastguard Worker
204*5e7646d2SAndroid Build Coastguard Worker /*
205*5e7646d2SAndroid Build Coastguard Worker * Free custom options...
206*5e7646d2SAndroid Build Coastguard Worker */
207*5e7646d2SAndroid Build Coastguard Worker
208*5e7646d2SAndroid Build Coastguard Worker for (coption = (ppd_coption_t *)cupsArrayFirst(ppd->coptions);
209*5e7646d2SAndroid Build Coastguard Worker coption;
210*5e7646d2SAndroid Build Coastguard Worker coption = (ppd_coption_t *)cupsArrayNext(ppd->coptions))
211*5e7646d2SAndroid Build Coastguard Worker {
212*5e7646d2SAndroid Build Coastguard Worker for (cparam = (ppd_cparam_t *)cupsArrayFirst(coption->params);
213*5e7646d2SAndroid Build Coastguard Worker cparam;
214*5e7646d2SAndroid Build Coastguard Worker cparam = (ppd_cparam_t *)cupsArrayNext(coption->params))
215*5e7646d2SAndroid Build Coastguard Worker {
216*5e7646d2SAndroid Build Coastguard Worker switch (cparam->type)
217*5e7646d2SAndroid Build Coastguard Worker {
218*5e7646d2SAndroid Build Coastguard Worker case PPD_CUSTOM_PASSCODE :
219*5e7646d2SAndroid Build Coastguard Worker case PPD_CUSTOM_PASSWORD :
220*5e7646d2SAndroid Build Coastguard Worker case PPD_CUSTOM_STRING :
221*5e7646d2SAndroid Build Coastguard Worker free(cparam->current.custom_string);
222*5e7646d2SAndroid Build Coastguard Worker break;
223*5e7646d2SAndroid Build Coastguard Worker
224*5e7646d2SAndroid Build Coastguard Worker default :
225*5e7646d2SAndroid Build Coastguard Worker break;
226*5e7646d2SAndroid Build Coastguard Worker }
227*5e7646d2SAndroid Build Coastguard Worker
228*5e7646d2SAndroid Build Coastguard Worker free(cparam);
229*5e7646d2SAndroid Build Coastguard Worker }
230*5e7646d2SAndroid Build Coastguard Worker
231*5e7646d2SAndroid Build Coastguard Worker cupsArrayDelete(coption->params);
232*5e7646d2SAndroid Build Coastguard Worker
233*5e7646d2SAndroid Build Coastguard Worker free(coption);
234*5e7646d2SAndroid Build Coastguard Worker }
235*5e7646d2SAndroid Build Coastguard Worker
236*5e7646d2SAndroid Build Coastguard Worker cupsArrayDelete(ppd->coptions);
237*5e7646d2SAndroid Build Coastguard Worker
238*5e7646d2SAndroid Build Coastguard Worker /*
239*5e7646d2SAndroid Build Coastguard Worker * Free constraints...
240*5e7646d2SAndroid Build Coastguard Worker */
241*5e7646d2SAndroid Build Coastguard Worker
242*5e7646d2SAndroid Build Coastguard Worker if (ppd->cups_uiconstraints)
243*5e7646d2SAndroid Build Coastguard Worker {
244*5e7646d2SAndroid Build Coastguard Worker _ppd_cups_uiconsts_t *consts; /* Current constraints */
245*5e7646d2SAndroid Build Coastguard Worker
246*5e7646d2SAndroid Build Coastguard Worker
247*5e7646d2SAndroid Build Coastguard Worker for (consts = (_ppd_cups_uiconsts_t *)cupsArrayFirst(ppd->cups_uiconstraints);
248*5e7646d2SAndroid Build Coastguard Worker consts;
249*5e7646d2SAndroid Build Coastguard Worker consts = (_ppd_cups_uiconsts_t *)cupsArrayNext(ppd->cups_uiconstraints))
250*5e7646d2SAndroid Build Coastguard Worker {
251*5e7646d2SAndroid Build Coastguard Worker free(consts->constraints);
252*5e7646d2SAndroid Build Coastguard Worker free(consts);
253*5e7646d2SAndroid Build Coastguard Worker }
254*5e7646d2SAndroid Build Coastguard Worker
255*5e7646d2SAndroid Build Coastguard Worker cupsArrayDelete(ppd->cups_uiconstraints);
256*5e7646d2SAndroid Build Coastguard Worker }
257*5e7646d2SAndroid Build Coastguard Worker
258*5e7646d2SAndroid Build Coastguard Worker /*
259*5e7646d2SAndroid Build Coastguard Worker * Free any PPD cache/mapping data...
260*5e7646d2SAndroid Build Coastguard Worker */
261*5e7646d2SAndroid Build Coastguard Worker
262*5e7646d2SAndroid Build Coastguard Worker if (ppd->cache)
263*5e7646d2SAndroid Build Coastguard Worker _ppdCacheDestroy(ppd->cache);
264*5e7646d2SAndroid Build Coastguard Worker
265*5e7646d2SAndroid Build Coastguard Worker /*
266*5e7646d2SAndroid Build Coastguard Worker * Free the whole record...
267*5e7646d2SAndroid Build Coastguard Worker */
268*5e7646d2SAndroid Build Coastguard Worker
269*5e7646d2SAndroid Build Coastguard Worker free(ppd);
270*5e7646d2SAndroid Build Coastguard Worker }
271*5e7646d2SAndroid Build Coastguard Worker
272*5e7646d2SAndroid Build Coastguard Worker
273*5e7646d2SAndroid Build Coastguard Worker /*
274*5e7646d2SAndroid Build Coastguard Worker * 'ppdErrorString()' - Returns the text associated with a status.
275*5e7646d2SAndroid Build Coastguard Worker *
276*5e7646d2SAndroid Build Coastguard Worker * @since CUPS 1.1.19/macOS 10.3@
277*5e7646d2SAndroid Build Coastguard Worker */
278*5e7646d2SAndroid Build Coastguard Worker
279*5e7646d2SAndroid Build Coastguard Worker const char * /* O - Status string */
ppdErrorString(ppd_status_t status)280*5e7646d2SAndroid Build Coastguard Worker ppdErrorString(ppd_status_t status) /* I - PPD status */
281*5e7646d2SAndroid Build Coastguard Worker {
282*5e7646d2SAndroid Build Coastguard Worker static const char * const messages[] =/* Status messages */
283*5e7646d2SAndroid Build Coastguard Worker {
284*5e7646d2SAndroid Build Coastguard Worker _("OK"),
285*5e7646d2SAndroid Build Coastguard Worker _("Unable to open PPD file"),
286*5e7646d2SAndroid Build Coastguard Worker _("NULL PPD file pointer"),
287*5e7646d2SAndroid Build Coastguard Worker _("Memory allocation error"),
288*5e7646d2SAndroid Build Coastguard Worker _("Missing PPD-Adobe-4.x header"),
289*5e7646d2SAndroid Build Coastguard Worker _("Missing value string"),
290*5e7646d2SAndroid Build Coastguard Worker _("Internal error"),
291*5e7646d2SAndroid Build Coastguard Worker _("Bad OpenGroup"),
292*5e7646d2SAndroid Build Coastguard Worker _("OpenGroup without a CloseGroup first"),
293*5e7646d2SAndroid Build Coastguard Worker _("Bad OpenUI/JCLOpenUI"),
294*5e7646d2SAndroid Build Coastguard Worker _("OpenUI/JCLOpenUI without a CloseUI/JCLCloseUI first"),
295*5e7646d2SAndroid Build Coastguard Worker _("Bad OrderDependency"),
296*5e7646d2SAndroid Build Coastguard Worker _("Bad UIConstraints"),
297*5e7646d2SAndroid Build Coastguard Worker _("Missing asterisk in column 1"),
298*5e7646d2SAndroid Build Coastguard Worker _("Line longer than the maximum allowed (255 characters)"),
299*5e7646d2SAndroid Build Coastguard Worker _("Illegal control character"),
300*5e7646d2SAndroid Build Coastguard Worker _("Illegal main keyword string"),
301*5e7646d2SAndroid Build Coastguard Worker _("Illegal option keyword string"),
302*5e7646d2SAndroid Build Coastguard Worker _("Illegal translation string"),
303*5e7646d2SAndroid Build Coastguard Worker _("Illegal whitespace character"),
304*5e7646d2SAndroid Build Coastguard Worker _("Bad custom parameter"),
305*5e7646d2SAndroid Build Coastguard Worker _("Missing option keyword"),
306*5e7646d2SAndroid Build Coastguard Worker _("Bad value string"),
307*5e7646d2SAndroid Build Coastguard Worker _("Missing CloseGroup"),
308*5e7646d2SAndroid Build Coastguard Worker _("Bad CloseUI/JCLCloseUI"),
309*5e7646d2SAndroid Build Coastguard Worker _("Missing CloseUI/JCLCloseUI")
310*5e7646d2SAndroid Build Coastguard Worker };
311*5e7646d2SAndroid Build Coastguard Worker
312*5e7646d2SAndroid Build Coastguard Worker
313*5e7646d2SAndroid Build Coastguard Worker if (status < PPD_OK || status >= PPD_MAX_STATUS)
314*5e7646d2SAndroid Build Coastguard Worker return (_cupsLangString(cupsLangDefault(), _("Unknown")));
315*5e7646d2SAndroid Build Coastguard Worker else
316*5e7646d2SAndroid Build Coastguard Worker return (_cupsLangString(cupsLangDefault(), messages[status]));
317*5e7646d2SAndroid Build Coastguard Worker }
318*5e7646d2SAndroid Build Coastguard Worker
319*5e7646d2SAndroid Build Coastguard Worker
320*5e7646d2SAndroid Build Coastguard Worker /*
321*5e7646d2SAndroid Build Coastguard Worker * '_ppdGetEncoding()' - Get the CUPS encoding value for the given
322*5e7646d2SAndroid Build Coastguard Worker * LanguageEncoding.
323*5e7646d2SAndroid Build Coastguard Worker */
324*5e7646d2SAndroid Build Coastguard Worker
325*5e7646d2SAndroid Build Coastguard Worker cups_encoding_t /* O - CUPS encoding value */
_ppdGetEncoding(const char * name)326*5e7646d2SAndroid Build Coastguard Worker _ppdGetEncoding(const char *name) /* I - LanguageEncoding string */
327*5e7646d2SAndroid Build Coastguard Worker {
328*5e7646d2SAndroid Build Coastguard Worker if (!_cups_strcasecmp(name, "ISOLatin1"))
329*5e7646d2SAndroid Build Coastguard Worker return (CUPS_ISO8859_1);
330*5e7646d2SAndroid Build Coastguard Worker else if (!_cups_strcasecmp(name, "ISOLatin2"))
331*5e7646d2SAndroid Build Coastguard Worker return (CUPS_ISO8859_2);
332*5e7646d2SAndroid Build Coastguard Worker else if (!_cups_strcasecmp(name, "ISOLatin5"))
333*5e7646d2SAndroid Build Coastguard Worker return (CUPS_ISO8859_5);
334*5e7646d2SAndroid Build Coastguard Worker else if (!_cups_strcasecmp(name, "JIS83-RKSJ"))
335*5e7646d2SAndroid Build Coastguard Worker return (CUPS_JIS_X0213);
336*5e7646d2SAndroid Build Coastguard Worker else if (!_cups_strcasecmp(name, "MacStandard"))
337*5e7646d2SAndroid Build Coastguard Worker return (CUPS_MAC_ROMAN);
338*5e7646d2SAndroid Build Coastguard Worker else if (!_cups_strcasecmp(name, "WindowsANSI"))
339*5e7646d2SAndroid Build Coastguard Worker return (CUPS_WINDOWS_1252);
340*5e7646d2SAndroid Build Coastguard Worker else
341*5e7646d2SAndroid Build Coastguard Worker return (CUPS_UTF8);
342*5e7646d2SAndroid Build Coastguard Worker }
343*5e7646d2SAndroid Build Coastguard Worker
344*5e7646d2SAndroid Build Coastguard Worker
345*5e7646d2SAndroid Build Coastguard Worker /*
346*5e7646d2SAndroid Build Coastguard Worker * '_ppdGlobals()' - Return a pointer to thread local storage
347*5e7646d2SAndroid Build Coastguard Worker */
348*5e7646d2SAndroid Build Coastguard Worker
349*5e7646d2SAndroid Build Coastguard Worker _ppd_globals_t * /* O - Pointer to global data */
_ppdGlobals(void)350*5e7646d2SAndroid Build Coastguard Worker _ppdGlobals(void)
351*5e7646d2SAndroid Build Coastguard Worker {
352*5e7646d2SAndroid Build Coastguard Worker _ppd_globals_t *pg; /* Pointer to global data */
353*5e7646d2SAndroid Build Coastguard Worker
354*5e7646d2SAndroid Build Coastguard Worker
355*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_PTHREAD_H
356*5e7646d2SAndroid Build Coastguard Worker /*
357*5e7646d2SAndroid Build Coastguard Worker * Initialize the global data exactly once...
358*5e7646d2SAndroid Build Coastguard Worker */
359*5e7646d2SAndroid Build Coastguard Worker
360*5e7646d2SAndroid Build Coastguard Worker pthread_once(&ppd_globals_key_once, ppd_globals_init);
361*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_PTHREAD_H */
362*5e7646d2SAndroid Build Coastguard Worker
363*5e7646d2SAndroid Build Coastguard Worker /*
364*5e7646d2SAndroid Build Coastguard Worker * See if we have allocated the data yet...
365*5e7646d2SAndroid Build Coastguard Worker */
366*5e7646d2SAndroid Build Coastguard Worker
367*5e7646d2SAndroid Build Coastguard Worker if ((pg = (_ppd_globals_t *)_cupsThreadGetData(ppd_globals_key)) == NULL)
368*5e7646d2SAndroid Build Coastguard Worker {
369*5e7646d2SAndroid Build Coastguard Worker /*
370*5e7646d2SAndroid Build Coastguard Worker * No, allocate memory as set the pointer for the key...
371*5e7646d2SAndroid Build Coastguard Worker */
372*5e7646d2SAndroid Build Coastguard Worker
373*5e7646d2SAndroid Build Coastguard Worker if ((pg = ppd_globals_alloc()) != NULL)
374*5e7646d2SAndroid Build Coastguard Worker _cupsThreadSetData(ppd_globals_key, pg);
375*5e7646d2SAndroid Build Coastguard Worker }
376*5e7646d2SAndroid Build Coastguard Worker
377*5e7646d2SAndroid Build Coastguard Worker /*
378*5e7646d2SAndroid Build Coastguard Worker * Return the pointer to the data...
379*5e7646d2SAndroid Build Coastguard Worker */
380*5e7646d2SAndroid Build Coastguard Worker
381*5e7646d2SAndroid Build Coastguard Worker return (pg);
382*5e7646d2SAndroid Build Coastguard Worker }
383*5e7646d2SAndroid Build Coastguard Worker
384*5e7646d2SAndroid Build Coastguard Worker
385*5e7646d2SAndroid Build Coastguard Worker /*
386*5e7646d2SAndroid Build Coastguard Worker * 'ppdLastError()' - Return the status from the last ppdOpen*().
387*5e7646d2SAndroid Build Coastguard Worker *
388*5e7646d2SAndroid Build Coastguard Worker * @since CUPS 1.1.19/macOS 10.3@
389*5e7646d2SAndroid Build Coastguard Worker */
390*5e7646d2SAndroid Build Coastguard Worker
391*5e7646d2SAndroid Build Coastguard Worker ppd_status_t /* O - Status code */
ppdLastError(int * line)392*5e7646d2SAndroid Build Coastguard Worker ppdLastError(int *line) /* O - Line number */
393*5e7646d2SAndroid Build Coastguard Worker {
394*5e7646d2SAndroid Build Coastguard Worker _ppd_globals_t *pg = _ppdGlobals();
395*5e7646d2SAndroid Build Coastguard Worker /* Global data */
396*5e7646d2SAndroid Build Coastguard Worker
397*5e7646d2SAndroid Build Coastguard Worker
398*5e7646d2SAndroid Build Coastguard Worker if (line)
399*5e7646d2SAndroid Build Coastguard Worker *line = pg->ppd_line;
400*5e7646d2SAndroid Build Coastguard Worker
401*5e7646d2SAndroid Build Coastguard Worker return (pg->ppd_status);
402*5e7646d2SAndroid Build Coastguard Worker }
403*5e7646d2SAndroid Build Coastguard Worker
404*5e7646d2SAndroid Build Coastguard Worker
405*5e7646d2SAndroid Build Coastguard Worker /*
406*5e7646d2SAndroid Build Coastguard Worker * '_ppdOpen()' - Read a PPD file into memory.
407*5e7646d2SAndroid Build Coastguard Worker *
408*5e7646d2SAndroid Build Coastguard Worker * @since CUPS 1.2/macOS 10.5@
409*5e7646d2SAndroid Build Coastguard Worker */
410*5e7646d2SAndroid Build Coastguard Worker
411*5e7646d2SAndroid Build Coastguard Worker ppd_file_t * /* O - PPD file record or @code NULL@ if the PPD file could not be opened. */
_ppdOpen(cups_file_t * fp,_ppd_localization_t localization)412*5e7646d2SAndroid Build Coastguard Worker _ppdOpen(
413*5e7646d2SAndroid Build Coastguard Worker cups_file_t *fp, /* I - File to read from */
414*5e7646d2SAndroid Build Coastguard Worker _ppd_localization_t localization) /* I - Localization to load */
415*5e7646d2SAndroid Build Coastguard Worker {
416*5e7646d2SAndroid Build Coastguard Worker int i, j, k; /* Looping vars */
417*5e7646d2SAndroid Build Coastguard Worker _ppd_line_t line; /* Line buffer */
418*5e7646d2SAndroid Build Coastguard Worker ppd_file_t *ppd; /* PPD file record */
419*5e7646d2SAndroid Build Coastguard Worker ppd_group_t *group, /* Current group */
420*5e7646d2SAndroid Build Coastguard Worker *subgroup; /* Current sub-group */
421*5e7646d2SAndroid Build Coastguard Worker ppd_option_t *option; /* Current option */
422*5e7646d2SAndroid Build Coastguard Worker ppd_choice_t *choice; /* Current choice */
423*5e7646d2SAndroid Build Coastguard Worker ppd_const_t *constraint; /* Current constraint */
424*5e7646d2SAndroid Build Coastguard Worker ppd_size_t *size; /* Current page size */
425*5e7646d2SAndroid Build Coastguard Worker int mask; /* Line data mask */
426*5e7646d2SAndroid Build Coastguard Worker char keyword[PPD_MAX_NAME],
427*5e7646d2SAndroid Build Coastguard Worker /* Keyword from file */
428*5e7646d2SAndroid Build Coastguard Worker name[PPD_MAX_NAME],
429*5e7646d2SAndroid Build Coastguard Worker /* Option from file */
430*5e7646d2SAndroid Build Coastguard Worker text[PPD_MAX_LINE],
431*5e7646d2SAndroid Build Coastguard Worker /* Human-readable text from file */
432*5e7646d2SAndroid Build Coastguard Worker *string, /* Code/text from file */
433*5e7646d2SAndroid Build Coastguard Worker *sptr, /* Pointer into string */
434*5e7646d2SAndroid Build Coastguard Worker *temp, /* Temporary string pointer */
435*5e7646d2SAndroid Build Coastguard Worker **tempfonts; /* Temporary fonts pointer */
436*5e7646d2SAndroid Build Coastguard Worker float order; /* Order dependency number */
437*5e7646d2SAndroid Build Coastguard Worker ppd_section_t section; /* Order dependency section */
438*5e7646d2SAndroid Build Coastguard Worker ppd_profile_t *profile; /* Pointer to color profile */
439*5e7646d2SAndroid Build Coastguard Worker char **filter; /* Pointer to filter */
440*5e7646d2SAndroid Build Coastguard Worker struct lconv *loc; /* Locale data */
441*5e7646d2SAndroid Build Coastguard Worker int ui_keyword; /* Is this line a UI keyword? */
442*5e7646d2SAndroid Build Coastguard Worker cups_lang_t *lang; /* Language data */
443*5e7646d2SAndroid Build Coastguard Worker cups_encoding_t encoding; /* Encoding of PPD file */
444*5e7646d2SAndroid Build Coastguard Worker _ppd_globals_t *pg = _ppdGlobals();
445*5e7646d2SAndroid Build Coastguard Worker /* Global data */
446*5e7646d2SAndroid Build Coastguard Worker char custom_name[PPD_MAX_NAME];
447*5e7646d2SAndroid Build Coastguard Worker /* CustomFoo attribute name */
448*5e7646d2SAndroid Build Coastguard Worker ppd_attr_t *custom_attr; /* CustomFoo attribute */
449*5e7646d2SAndroid Build Coastguard Worker char ll[7], /* Base language + '.' */
450*5e7646d2SAndroid Build Coastguard Worker ll_CC[7]; /* Language w/country + '.' */
451*5e7646d2SAndroid Build Coastguard Worker size_t ll_len = 0, /* Base language length */
452*5e7646d2SAndroid Build Coastguard Worker ll_CC_len = 0; /* Language w/country length */
453*5e7646d2SAndroid Build Coastguard Worker static const char * const ui_keywords[] =
454*5e7646d2SAndroid Build Coastguard Worker {
455*5e7646d2SAndroid Build Coastguard Worker #ifdef CUPS_USE_FULL_UI_KEYWORDS_LIST
456*5e7646d2SAndroid Build Coastguard Worker /*
457*5e7646d2SAndroid Build Coastguard Worker * Adobe defines some 41 keywords as "UI", meaning that they are
458*5e7646d2SAndroid Build Coastguard Worker * user interface elements and that they should be treated as such
459*5e7646d2SAndroid Build Coastguard Worker * even if the PPD creator doesn't use Open/CloseUI around them.
460*5e7646d2SAndroid Build Coastguard Worker *
461*5e7646d2SAndroid Build Coastguard Worker * Since this can cause previously invisible options to appear and
462*5e7646d2SAndroid Build Coastguard Worker * confuse users, the default is to only treat the PageSize and
463*5e7646d2SAndroid Build Coastguard Worker * PageRegion keywords this way.
464*5e7646d2SAndroid Build Coastguard Worker */
465*5e7646d2SAndroid Build Coastguard Worker /* Boolean keywords */
466*5e7646d2SAndroid Build Coastguard Worker "BlackSubstitution",
467*5e7646d2SAndroid Build Coastguard Worker "Booklet",
468*5e7646d2SAndroid Build Coastguard Worker "Collate",
469*5e7646d2SAndroid Build Coastguard Worker "ManualFeed",
470*5e7646d2SAndroid Build Coastguard Worker "MirrorPrint",
471*5e7646d2SAndroid Build Coastguard Worker "NegativePrint",
472*5e7646d2SAndroid Build Coastguard Worker "Sorter",
473*5e7646d2SAndroid Build Coastguard Worker "TraySwitch",
474*5e7646d2SAndroid Build Coastguard Worker
475*5e7646d2SAndroid Build Coastguard Worker /* PickOne keywords */
476*5e7646d2SAndroid Build Coastguard Worker "AdvanceMedia",
477*5e7646d2SAndroid Build Coastguard Worker "BindColor",
478*5e7646d2SAndroid Build Coastguard Worker "BindEdge",
479*5e7646d2SAndroid Build Coastguard Worker "BindType",
480*5e7646d2SAndroid Build Coastguard Worker "BindWhen",
481*5e7646d2SAndroid Build Coastguard Worker "BitsPerPixel",
482*5e7646d2SAndroid Build Coastguard Worker "ColorModel",
483*5e7646d2SAndroid Build Coastguard Worker "CutMedia",
484*5e7646d2SAndroid Build Coastguard Worker "Duplex",
485*5e7646d2SAndroid Build Coastguard Worker "FoldType",
486*5e7646d2SAndroid Build Coastguard Worker "FoldWhen",
487*5e7646d2SAndroid Build Coastguard Worker "InputSlot",
488*5e7646d2SAndroid Build Coastguard Worker "JCLFrameBufferSize",
489*5e7646d2SAndroid Build Coastguard Worker "JCLResolution",
490*5e7646d2SAndroid Build Coastguard Worker "Jog",
491*5e7646d2SAndroid Build Coastguard Worker "MediaColor",
492*5e7646d2SAndroid Build Coastguard Worker "MediaType",
493*5e7646d2SAndroid Build Coastguard Worker "MediaWeight",
494*5e7646d2SAndroid Build Coastguard Worker "OutputBin",
495*5e7646d2SAndroid Build Coastguard Worker "OutputMode",
496*5e7646d2SAndroid Build Coastguard Worker "OutputOrder",
497*5e7646d2SAndroid Build Coastguard Worker "PageRegion",
498*5e7646d2SAndroid Build Coastguard Worker "PageSize",
499*5e7646d2SAndroid Build Coastguard Worker "Resolution",
500*5e7646d2SAndroid Build Coastguard Worker "Separations",
501*5e7646d2SAndroid Build Coastguard Worker "Signature",
502*5e7646d2SAndroid Build Coastguard Worker "Slipsheet",
503*5e7646d2SAndroid Build Coastguard Worker "Smoothing",
504*5e7646d2SAndroid Build Coastguard Worker "StapleLocation",
505*5e7646d2SAndroid Build Coastguard Worker "StapleOrientation",
506*5e7646d2SAndroid Build Coastguard Worker "StapleWhen",
507*5e7646d2SAndroid Build Coastguard Worker "StapleX",
508*5e7646d2SAndroid Build Coastguard Worker "StapleY"
509*5e7646d2SAndroid Build Coastguard Worker #else /* !CUPS_USE_FULL_UI_KEYWORDS_LIST */
510*5e7646d2SAndroid Build Coastguard Worker "PageRegion",
511*5e7646d2SAndroid Build Coastguard Worker "PageSize"
512*5e7646d2SAndroid Build Coastguard Worker #endif /* CUPS_USE_FULL_UI_KEYWORDS_LIST */
513*5e7646d2SAndroid Build Coastguard Worker };
514*5e7646d2SAndroid Build Coastguard Worker static const char * const color_keywords[] = /* Keywords associated with color profiles */
515*5e7646d2SAndroid Build Coastguard Worker {
516*5e7646d2SAndroid Build Coastguard Worker ".cupsICCProfile",
517*5e7646d2SAndroid Build Coastguard Worker ".ColorModel",
518*5e7646d2SAndroid Build Coastguard Worker };
519*5e7646d2SAndroid Build Coastguard Worker
520*5e7646d2SAndroid Build Coastguard Worker
521*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("_ppdOpen(fp=%p)", fp));
522*5e7646d2SAndroid Build Coastguard Worker
523*5e7646d2SAndroid Build Coastguard Worker /*
524*5e7646d2SAndroid Build Coastguard Worker * Default to "OK" status...
525*5e7646d2SAndroid Build Coastguard Worker */
526*5e7646d2SAndroid Build Coastguard Worker
527*5e7646d2SAndroid Build Coastguard Worker pg->ppd_status = PPD_OK;
528*5e7646d2SAndroid Build Coastguard Worker pg->ppd_line = 0;
529*5e7646d2SAndroid Build Coastguard Worker
530*5e7646d2SAndroid Build Coastguard Worker /*
531*5e7646d2SAndroid Build Coastguard Worker * Range check input...
532*5e7646d2SAndroid Build Coastguard Worker */
533*5e7646d2SAndroid Build Coastguard Worker
534*5e7646d2SAndroid Build Coastguard Worker if (fp == NULL)
535*5e7646d2SAndroid Build Coastguard Worker {
536*5e7646d2SAndroid Build Coastguard Worker pg->ppd_status = PPD_NULL_FILE;
537*5e7646d2SAndroid Build Coastguard Worker return (NULL);
538*5e7646d2SAndroid Build Coastguard Worker }
539*5e7646d2SAndroid Build Coastguard Worker
540*5e7646d2SAndroid Build Coastguard Worker /*
541*5e7646d2SAndroid Build Coastguard Worker * If only loading a single localization set up the strings to match...
542*5e7646d2SAndroid Build Coastguard Worker */
543*5e7646d2SAndroid Build Coastguard Worker
544*5e7646d2SAndroid Build Coastguard Worker if (localization == _PPD_LOCALIZATION_DEFAULT)
545*5e7646d2SAndroid Build Coastguard Worker {
546*5e7646d2SAndroid Build Coastguard Worker if ((lang = cupsLangDefault()) == NULL)
547*5e7646d2SAndroid Build Coastguard Worker return (NULL);
548*5e7646d2SAndroid Build Coastguard Worker
549*5e7646d2SAndroid Build Coastguard Worker snprintf(ll_CC, sizeof(ll_CC), "%s.", lang->language);
550*5e7646d2SAndroid Build Coastguard Worker
551*5e7646d2SAndroid Build Coastguard Worker /*
552*5e7646d2SAndroid Build Coastguard Worker * <rdar://problem/22130168>
553*5e7646d2SAndroid Build Coastguard Worker * <rdar://problem/27245567>
554*5e7646d2SAndroid Build Coastguard Worker *
555*5e7646d2SAndroid Build Coastguard Worker * Need to use a different base language for some locales...
556*5e7646d2SAndroid Build Coastguard Worker */
557*5e7646d2SAndroid Build Coastguard Worker
558*5e7646d2SAndroid Build Coastguard Worker if (!strcmp(lang->language, "zh_HK"))
559*5e7646d2SAndroid Build Coastguard Worker { /* Traditional Chinese + variants */
560*5e7646d2SAndroid Build Coastguard Worker strlcpy(ll_CC, "zh_TW.", sizeof(ll_CC));
561*5e7646d2SAndroid Build Coastguard Worker strlcpy(ll, "zh_", sizeof(ll));
562*5e7646d2SAndroid Build Coastguard Worker }
563*5e7646d2SAndroid Build Coastguard Worker else if (!strncmp(lang->language, "zh", 2))
564*5e7646d2SAndroid Build Coastguard Worker strlcpy(ll, "zh_", sizeof(ll)); /* Any Chinese variant */
565*5e7646d2SAndroid Build Coastguard Worker else if (!strncmp(lang->language, "jp", 2))
566*5e7646d2SAndroid Build Coastguard Worker { /* Any Japanese variant */
567*5e7646d2SAndroid Build Coastguard Worker strlcpy(ll_CC, "ja", sizeof(ll_CC));
568*5e7646d2SAndroid Build Coastguard Worker strlcpy(ll, "jp", sizeof(ll));
569*5e7646d2SAndroid Build Coastguard Worker }
570*5e7646d2SAndroid Build Coastguard Worker else if (!strncmp(lang->language, "nb", 2) || !strncmp(lang->language, "no", 2))
571*5e7646d2SAndroid Build Coastguard Worker { /* Any Norwegian variant */
572*5e7646d2SAndroid Build Coastguard Worker strlcpy(ll_CC, "nb", sizeof(ll_CC));
573*5e7646d2SAndroid Build Coastguard Worker strlcpy(ll, "no", sizeof(ll));
574*5e7646d2SAndroid Build Coastguard Worker }
575*5e7646d2SAndroid Build Coastguard Worker else
576*5e7646d2SAndroid Build Coastguard Worker snprintf(ll, sizeof(ll), "%2.2s.", lang->language);
577*5e7646d2SAndroid Build Coastguard Worker
578*5e7646d2SAndroid Build Coastguard Worker ll_CC_len = strlen(ll_CC);
579*5e7646d2SAndroid Build Coastguard Worker ll_len = strlen(ll);
580*5e7646d2SAndroid Build Coastguard Worker
581*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("2_ppdOpen: Loading localizations matching \"%s\" and \"%s\"",
582*5e7646d2SAndroid Build Coastguard Worker ll_CC, ll));
583*5e7646d2SAndroid Build Coastguard Worker }
584*5e7646d2SAndroid Build Coastguard Worker
585*5e7646d2SAndroid Build Coastguard Worker /*
586*5e7646d2SAndroid Build Coastguard Worker * Grab the first line and make sure it reads '*PPD-Adobe: "major.minor"'...
587*5e7646d2SAndroid Build Coastguard Worker */
588*5e7646d2SAndroid Build Coastguard Worker
589*5e7646d2SAndroid Build Coastguard Worker line.buffer = NULL;
590*5e7646d2SAndroid Build Coastguard Worker line.bufsize = 0;
591*5e7646d2SAndroid Build Coastguard Worker
592*5e7646d2SAndroid Build Coastguard Worker mask = ppd_read(fp, &line, keyword, name, text, &string, 0, pg);
593*5e7646d2SAndroid Build Coastguard Worker
594*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("2_ppdOpen: mask=%x, keyword=\"%s\"...", mask, keyword));
595*5e7646d2SAndroid Build Coastguard Worker
596*5e7646d2SAndroid Build Coastguard Worker if (mask == 0 ||
597*5e7646d2SAndroid Build Coastguard Worker strcmp(keyword, "PPD-Adobe") ||
598*5e7646d2SAndroid Build Coastguard Worker string == NULL || string[0] != '4')
599*5e7646d2SAndroid Build Coastguard Worker {
600*5e7646d2SAndroid Build Coastguard Worker /*
601*5e7646d2SAndroid Build Coastguard Worker * Either this is not a PPD file, or it is not a 4.x PPD file.
602*5e7646d2SAndroid Build Coastguard Worker */
603*5e7646d2SAndroid Build Coastguard Worker
604*5e7646d2SAndroid Build Coastguard Worker if (pg->ppd_status == PPD_OK)
605*5e7646d2SAndroid Build Coastguard Worker pg->ppd_status = PPD_MISSING_PPDADOBE4;
606*5e7646d2SAndroid Build Coastguard Worker
607*5e7646d2SAndroid Build Coastguard Worker free(string);
608*5e7646d2SAndroid Build Coastguard Worker free(line.buffer);
609*5e7646d2SAndroid Build Coastguard Worker
610*5e7646d2SAndroid Build Coastguard Worker return (NULL);
611*5e7646d2SAndroid Build Coastguard Worker }
612*5e7646d2SAndroid Build Coastguard Worker
613*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("2_ppdOpen: keyword=%s, string=%p", keyword, string));
614*5e7646d2SAndroid Build Coastguard Worker
615*5e7646d2SAndroid Build Coastguard Worker /*
616*5e7646d2SAndroid Build Coastguard Worker * Allocate memory for the PPD file record...
617*5e7646d2SAndroid Build Coastguard Worker */
618*5e7646d2SAndroid Build Coastguard Worker
619*5e7646d2SAndroid Build Coastguard Worker if ((ppd = calloc(1, sizeof(ppd_file_t))) == NULL)
620*5e7646d2SAndroid Build Coastguard Worker {
621*5e7646d2SAndroid Build Coastguard Worker pg->ppd_status = PPD_ALLOC_ERROR;
622*5e7646d2SAndroid Build Coastguard Worker
623*5e7646d2SAndroid Build Coastguard Worker free(string);
624*5e7646d2SAndroid Build Coastguard Worker free(line.buffer);
625*5e7646d2SAndroid Build Coastguard Worker
626*5e7646d2SAndroid Build Coastguard Worker return (NULL);
627*5e7646d2SAndroid Build Coastguard Worker }
628*5e7646d2SAndroid Build Coastguard Worker
629*5e7646d2SAndroid Build Coastguard Worker free(string);
630*5e7646d2SAndroid Build Coastguard Worker string = NULL;
631*5e7646d2SAndroid Build Coastguard Worker
632*5e7646d2SAndroid Build Coastguard Worker ppd->language_level = 2;
633*5e7646d2SAndroid Build Coastguard Worker ppd->color_device = 0;
634*5e7646d2SAndroid Build Coastguard Worker ppd->colorspace = PPD_CS_N;
635*5e7646d2SAndroid Build Coastguard Worker ppd->landscape = -90;
636*5e7646d2SAndroid Build Coastguard Worker ppd->coptions = cupsArrayNew((cups_array_func_t)ppd_compare_coptions, NULL);
637*5e7646d2SAndroid Build Coastguard Worker
638*5e7646d2SAndroid Build Coastguard Worker /*
639*5e7646d2SAndroid Build Coastguard Worker * Read lines from the PPD file and add them to the file record...
640*5e7646d2SAndroid Build Coastguard Worker */
641*5e7646d2SAndroid Build Coastguard Worker
642*5e7646d2SAndroid Build Coastguard Worker group = NULL;
643*5e7646d2SAndroid Build Coastguard Worker subgroup = NULL;
644*5e7646d2SAndroid Build Coastguard Worker option = NULL;
645*5e7646d2SAndroid Build Coastguard Worker choice = NULL;
646*5e7646d2SAndroid Build Coastguard Worker ui_keyword = 0;
647*5e7646d2SAndroid Build Coastguard Worker encoding = CUPS_ISO8859_1;
648*5e7646d2SAndroid Build Coastguard Worker loc = localeconv();
649*5e7646d2SAndroid Build Coastguard Worker
650*5e7646d2SAndroid Build Coastguard Worker while ((mask = ppd_read(fp, &line, keyword, name, text, &string, 1, pg)) != 0)
651*5e7646d2SAndroid Build Coastguard Worker {
652*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("2_ppdOpen: mask=%x, keyword=\"%s\", name=\"%s\", "
653*5e7646d2SAndroid Build Coastguard Worker "text=\"%s\", string=%d chars...", mask, keyword, name, text,
654*5e7646d2SAndroid Build Coastguard Worker string ? (int)strlen(string) : 0));
655*5e7646d2SAndroid Build Coastguard Worker
656*5e7646d2SAndroid Build Coastguard Worker if (strncmp(keyword, "Default", 7) && !string &&
657*5e7646d2SAndroid Build Coastguard Worker pg->ppd_conform != PPD_CONFORM_RELAXED)
658*5e7646d2SAndroid Build Coastguard Worker {
659*5e7646d2SAndroid Build Coastguard Worker /*
660*5e7646d2SAndroid Build Coastguard Worker * Need a string value!
661*5e7646d2SAndroid Build Coastguard Worker */
662*5e7646d2SAndroid Build Coastguard Worker
663*5e7646d2SAndroid Build Coastguard Worker pg->ppd_status = PPD_MISSING_VALUE;
664*5e7646d2SAndroid Build Coastguard Worker
665*5e7646d2SAndroid Build Coastguard Worker goto error;
666*5e7646d2SAndroid Build Coastguard Worker }
667*5e7646d2SAndroid Build Coastguard Worker else if (!string)
668*5e7646d2SAndroid Build Coastguard Worker continue;
669*5e7646d2SAndroid Build Coastguard Worker
670*5e7646d2SAndroid Build Coastguard Worker /*
671*5e7646d2SAndroid Build Coastguard Worker * Certain main keywords (as defined by the PPD spec) may be used
672*5e7646d2SAndroid Build Coastguard Worker * without the usual OpenUI/CloseUI stuff. Presumably this is just
673*5e7646d2SAndroid Build Coastguard Worker * so that Adobe wouldn't completely break compatibility with PPD
674*5e7646d2SAndroid Build Coastguard Worker * files prior to v4.0 of the spec, but it is hopelessly
675*5e7646d2SAndroid Build Coastguard Worker * inconsistent... Catch these main keywords and automatically
676*5e7646d2SAndroid Build Coastguard Worker * create the corresponding option, as needed...
677*5e7646d2SAndroid Build Coastguard Worker */
678*5e7646d2SAndroid Build Coastguard Worker
679*5e7646d2SAndroid Build Coastguard Worker if (ui_keyword)
680*5e7646d2SAndroid Build Coastguard Worker {
681*5e7646d2SAndroid Build Coastguard Worker /*
682*5e7646d2SAndroid Build Coastguard Worker * Previous line was a UI keyword...
683*5e7646d2SAndroid Build Coastguard Worker */
684*5e7646d2SAndroid Build Coastguard Worker
685*5e7646d2SAndroid Build Coastguard Worker option = NULL;
686*5e7646d2SAndroid Build Coastguard Worker ui_keyword = 0;
687*5e7646d2SAndroid Build Coastguard Worker }
688*5e7646d2SAndroid Build Coastguard Worker
689*5e7646d2SAndroid Build Coastguard Worker /*
690*5e7646d2SAndroid Build Coastguard Worker * If we are filtering out keyword localizations, see if this line needs to
691*5e7646d2SAndroid Build Coastguard Worker * be used...
692*5e7646d2SAndroid Build Coastguard Worker */
693*5e7646d2SAndroid Build Coastguard Worker
694*5e7646d2SAndroid Build Coastguard Worker if (localization != _PPD_LOCALIZATION_ALL &&
695*5e7646d2SAndroid Build Coastguard Worker (temp = strchr(keyword, '.')) != NULL &&
696*5e7646d2SAndroid Build Coastguard Worker ((temp - keyword) == 2 || (temp - keyword) == 5) &&
697*5e7646d2SAndroid Build Coastguard Worker _cups_isalpha(keyword[0]) &&
698*5e7646d2SAndroid Build Coastguard Worker _cups_isalpha(keyword[1]) &&
699*5e7646d2SAndroid Build Coastguard Worker (keyword[2] == '.' ||
700*5e7646d2SAndroid Build Coastguard Worker (keyword[2] == '_' && _cups_isalpha(keyword[3]) &&
701*5e7646d2SAndroid Build Coastguard Worker _cups_isalpha(keyword[4]) && keyword[5] == '.')))
702*5e7646d2SAndroid Build Coastguard Worker {
703*5e7646d2SAndroid Build Coastguard Worker if (localization == _PPD_LOCALIZATION_NONE ||
704*5e7646d2SAndroid Build Coastguard Worker (localization == _PPD_LOCALIZATION_DEFAULT &&
705*5e7646d2SAndroid Build Coastguard Worker strncmp(ll_CC, keyword, ll_CC_len) &&
706*5e7646d2SAndroid Build Coastguard Worker strncmp(ll, keyword, ll_len)))
707*5e7646d2SAndroid Build Coastguard Worker {
708*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("2_ppdOpen: Ignoring localization: \"%s\"\n", keyword));
709*5e7646d2SAndroid Build Coastguard Worker free(string);
710*5e7646d2SAndroid Build Coastguard Worker string = NULL;
711*5e7646d2SAndroid Build Coastguard Worker continue;
712*5e7646d2SAndroid Build Coastguard Worker }
713*5e7646d2SAndroid Build Coastguard Worker else if (localization == _PPD_LOCALIZATION_ICC_PROFILES)
714*5e7646d2SAndroid Build Coastguard Worker {
715*5e7646d2SAndroid Build Coastguard Worker /*
716*5e7646d2SAndroid Build Coastguard Worker * Only load localizations for the color profile related keywords...
717*5e7646d2SAndroid Build Coastguard Worker */
718*5e7646d2SAndroid Build Coastguard Worker
719*5e7646d2SAndroid Build Coastguard Worker for (i = 0;
720*5e7646d2SAndroid Build Coastguard Worker i < (int)(sizeof(color_keywords) / sizeof(color_keywords[0]));
721*5e7646d2SAndroid Build Coastguard Worker i ++)
722*5e7646d2SAndroid Build Coastguard Worker {
723*5e7646d2SAndroid Build Coastguard Worker if (!_cups_strcasecmp(temp, color_keywords[i]))
724*5e7646d2SAndroid Build Coastguard Worker break;
725*5e7646d2SAndroid Build Coastguard Worker }
726*5e7646d2SAndroid Build Coastguard Worker
727*5e7646d2SAndroid Build Coastguard Worker if (i >= (int)(sizeof(color_keywords) / sizeof(color_keywords[0])))
728*5e7646d2SAndroid Build Coastguard Worker {
729*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("2_ppdOpen: Ignoring localization: \"%s\"\n", keyword));
730*5e7646d2SAndroid Build Coastguard Worker free(string);
731*5e7646d2SAndroid Build Coastguard Worker string = NULL;
732*5e7646d2SAndroid Build Coastguard Worker continue;
733*5e7646d2SAndroid Build Coastguard Worker }
734*5e7646d2SAndroid Build Coastguard Worker }
735*5e7646d2SAndroid Build Coastguard Worker }
736*5e7646d2SAndroid Build Coastguard Worker
737*5e7646d2SAndroid Build Coastguard Worker if (option == NULL &&
738*5e7646d2SAndroid Build Coastguard Worker (mask & (PPD_KEYWORD | PPD_OPTION | PPD_STRING)) ==
739*5e7646d2SAndroid Build Coastguard Worker (PPD_KEYWORD | PPD_OPTION | PPD_STRING))
740*5e7646d2SAndroid Build Coastguard Worker {
741*5e7646d2SAndroid Build Coastguard Worker for (i = 0; i < (int)(sizeof(ui_keywords) / sizeof(ui_keywords[0])); i ++)
742*5e7646d2SAndroid Build Coastguard Worker if (!strcmp(keyword, ui_keywords[i]))
743*5e7646d2SAndroid Build Coastguard Worker break;
744*5e7646d2SAndroid Build Coastguard Worker
745*5e7646d2SAndroid Build Coastguard Worker if (i < (int)(sizeof(ui_keywords) / sizeof(ui_keywords[0])))
746*5e7646d2SAndroid Build Coastguard Worker {
747*5e7646d2SAndroid Build Coastguard Worker /*
748*5e7646d2SAndroid Build Coastguard Worker * Create the option in the appropriate group...
749*5e7646d2SAndroid Build Coastguard Worker */
750*5e7646d2SAndroid Build Coastguard Worker
751*5e7646d2SAndroid Build Coastguard Worker ui_keyword = 1;
752*5e7646d2SAndroid Build Coastguard Worker
753*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("2_ppdOpen: FOUND ADOBE UI KEYWORD %s WITHOUT OPENUI!",
754*5e7646d2SAndroid Build Coastguard Worker keyword));
755*5e7646d2SAndroid Build Coastguard Worker
756*5e7646d2SAndroid Build Coastguard Worker if (!group)
757*5e7646d2SAndroid Build Coastguard Worker {
758*5e7646d2SAndroid Build Coastguard Worker if ((group = ppd_get_group(ppd, "General", _("General"), pg,
759*5e7646d2SAndroid Build Coastguard Worker encoding)) == NULL)
760*5e7646d2SAndroid Build Coastguard Worker goto error;
761*5e7646d2SAndroid Build Coastguard Worker
762*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("2_ppdOpen: Adding to group %s...", group->text));
763*5e7646d2SAndroid Build Coastguard Worker option = ppd_get_option(group, keyword);
764*5e7646d2SAndroid Build Coastguard Worker group = NULL;
765*5e7646d2SAndroid Build Coastguard Worker }
766*5e7646d2SAndroid Build Coastguard Worker else
767*5e7646d2SAndroid Build Coastguard Worker option = ppd_get_option(group, keyword);
768*5e7646d2SAndroid Build Coastguard Worker
769*5e7646d2SAndroid Build Coastguard Worker if (option == NULL)
770*5e7646d2SAndroid Build Coastguard Worker {
771*5e7646d2SAndroid Build Coastguard Worker pg->ppd_status = PPD_ALLOC_ERROR;
772*5e7646d2SAndroid Build Coastguard Worker
773*5e7646d2SAndroid Build Coastguard Worker goto error;
774*5e7646d2SAndroid Build Coastguard Worker }
775*5e7646d2SAndroid Build Coastguard Worker
776*5e7646d2SAndroid Build Coastguard Worker /*
777*5e7646d2SAndroid Build Coastguard Worker * Now fill in the initial information for the option...
778*5e7646d2SAndroid Build Coastguard Worker */
779*5e7646d2SAndroid Build Coastguard Worker
780*5e7646d2SAndroid Build Coastguard Worker if (!strncmp(keyword, "JCL", 3))
781*5e7646d2SAndroid Build Coastguard Worker option->section = PPD_ORDER_JCL;
782*5e7646d2SAndroid Build Coastguard Worker else
783*5e7646d2SAndroid Build Coastguard Worker option->section = PPD_ORDER_ANY;
784*5e7646d2SAndroid Build Coastguard Worker
785*5e7646d2SAndroid Build Coastguard Worker option->order = 10.0f;
786*5e7646d2SAndroid Build Coastguard Worker
787*5e7646d2SAndroid Build Coastguard Worker if (i < 8)
788*5e7646d2SAndroid Build Coastguard Worker option->ui = PPD_UI_BOOLEAN;
789*5e7646d2SAndroid Build Coastguard Worker else
790*5e7646d2SAndroid Build Coastguard Worker option->ui = PPD_UI_PICKONE;
791*5e7646d2SAndroid Build Coastguard Worker
792*5e7646d2SAndroid Build Coastguard Worker for (j = 0; j < ppd->num_attrs; j ++)
793*5e7646d2SAndroid Build Coastguard Worker if (!strncmp(ppd->attrs[j]->name, "Default", 7) &&
794*5e7646d2SAndroid Build Coastguard Worker !strcmp(ppd->attrs[j]->name + 7, keyword) &&
795*5e7646d2SAndroid Build Coastguard Worker ppd->attrs[j]->value)
796*5e7646d2SAndroid Build Coastguard Worker {
797*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("2_ppdOpen: Setting Default%s to %s via attribute...",
798*5e7646d2SAndroid Build Coastguard Worker option->keyword, ppd->attrs[j]->value));
799*5e7646d2SAndroid Build Coastguard Worker strlcpy(option->defchoice, ppd->attrs[j]->value,
800*5e7646d2SAndroid Build Coastguard Worker sizeof(option->defchoice));
801*5e7646d2SAndroid Build Coastguard Worker break;
802*5e7646d2SAndroid Build Coastguard Worker }
803*5e7646d2SAndroid Build Coastguard Worker
804*5e7646d2SAndroid Build Coastguard Worker if (!strcmp(keyword, "PageSize"))
805*5e7646d2SAndroid Build Coastguard Worker strlcpy(option->text, _("Media Size"), sizeof(option->text));
806*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(keyword, "MediaType"))
807*5e7646d2SAndroid Build Coastguard Worker strlcpy(option->text, _("Media Type"), sizeof(option->text));
808*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(keyword, "InputSlot"))
809*5e7646d2SAndroid Build Coastguard Worker strlcpy(option->text, _("Media Source"), sizeof(option->text));
810*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(keyword, "ColorModel"))
811*5e7646d2SAndroid Build Coastguard Worker strlcpy(option->text, _("Output Mode"), sizeof(option->text));
812*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(keyword, "Resolution"))
813*5e7646d2SAndroid Build Coastguard Worker strlcpy(option->text, _("Resolution"), sizeof(option->text));
814*5e7646d2SAndroid Build Coastguard Worker else
815*5e7646d2SAndroid Build Coastguard Worker strlcpy(option->text, keyword, sizeof(option->text));
816*5e7646d2SAndroid Build Coastguard Worker }
817*5e7646d2SAndroid Build Coastguard Worker }
818*5e7646d2SAndroid Build Coastguard Worker
819*5e7646d2SAndroid Build Coastguard Worker if (!strcmp(keyword, "LanguageLevel"))
820*5e7646d2SAndroid Build Coastguard Worker ppd->language_level = atoi(string);
821*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(keyword, "LanguageEncoding"))
822*5e7646d2SAndroid Build Coastguard Worker {
823*5e7646d2SAndroid Build Coastguard Worker /*
824*5e7646d2SAndroid Build Coastguard Worker * Say all PPD files are UTF-8, since we convert to UTF-8...
825*5e7646d2SAndroid Build Coastguard Worker */
826*5e7646d2SAndroid Build Coastguard Worker
827*5e7646d2SAndroid Build Coastguard Worker ppd->lang_encoding = strdup("UTF-8");
828*5e7646d2SAndroid Build Coastguard Worker encoding = _ppdGetEncoding(string);
829*5e7646d2SAndroid Build Coastguard Worker }
830*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(keyword, "LanguageVersion"))
831*5e7646d2SAndroid Build Coastguard Worker ppd->lang_version = string;
832*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(keyword, "Manufacturer"))
833*5e7646d2SAndroid Build Coastguard Worker ppd->manufacturer = string;
834*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(keyword, "ModelName"))
835*5e7646d2SAndroid Build Coastguard Worker ppd->modelname = string;
836*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(keyword, "Protocols"))
837*5e7646d2SAndroid Build Coastguard Worker ppd->protocols = string;
838*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(keyword, "PCFileName"))
839*5e7646d2SAndroid Build Coastguard Worker ppd->pcfilename = string;
840*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(keyword, "NickName"))
841*5e7646d2SAndroid Build Coastguard Worker {
842*5e7646d2SAndroid Build Coastguard Worker if (encoding != CUPS_UTF8)
843*5e7646d2SAndroid Build Coastguard Worker {
844*5e7646d2SAndroid Build Coastguard Worker cups_utf8_t utf8[256]; /* UTF-8 version of NickName */
845*5e7646d2SAndroid Build Coastguard Worker
846*5e7646d2SAndroid Build Coastguard Worker
847*5e7646d2SAndroid Build Coastguard Worker cupsCharsetToUTF8(utf8, string, sizeof(utf8), encoding);
848*5e7646d2SAndroid Build Coastguard Worker ppd->nickname = strdup((char *)utf8);
849*5e7646d2SAndroid Build Coastguard Worker }
850*5e7646d2SAndroid Build Coastguard Worker else
851*5e7646d2SAndroid Build Coastguard Worker ppd->nickname = strdup(string);
852*5e7646d2SAndroid Build Coastguard Worker }
853*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(keyword, "Product"))
854*5e7646d2SAndroid Build Coastguard Worker ppd->product = string;
855*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(keyword, "ShortNickName"))
856*5e7646d2SAndroid Build Coastguard Worker ppd->shortnickname = string;
857*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(keyword, "TTRasterizer"))
858*5e7646d2SAndroid Build Coastguard Worker ppd->ttrasterizer = string;
859*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(keyword, "JCLBegin"))
860*5e7646d2SAndroid Build Coastguard Worker {
861*5e7646d2SAndroid Build Coastguard Worker ppd->jcl_begin = strdup(string);
862*5e7646d2SAndroid Build Coastguard Worker ppd_decode(ppd->jcl_begin); /* Decode quoted string */
863*5e7646d2SAndroid Build Coastguard Worker }
864*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(keyword, "JCLEnd"))
865*5e7646d2SAndroid Build Coastguard Worker {
866*5e7646d2SAndroid Build Coastguard Worker ppd->jcl_end = strdup(string);
867*5e7646d2SAndroid Build Coastguard Worker ppd_decode(ppd->jcl_end); /* Decode quoted string */
868*5e7646d2SAndroid Build Coastguard Worker }
869*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(keyword, "JCLToPSInterpreter"))
870*5e7646d2SAndroid Build Coastguard Worker {
871*5e7646d2SAndroid Build Coastguard Worker ppd->jcl_ps = strdup(string);
872*5e7646d2SAndroid Build Coastguard Worker ppd_decode(ppd->jcl_ps); /* Decode quoted string */
873*5e7646d2SAndroid Build Coastguard Worker }
874*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(keyword, "AccurateScreensSupport"))
875*5e7646d2SAndroid Build Coastguard Worker ppd->accurate_screens = !strcasecmp(string, "True");
876*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(keyword, "ColorDevice"))
877*5e7646d2SAndroid Build Coastguard Worker ppd->color_device = !strcasecmp(string, "True");
878*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(keyword, "ContoneOnly"))
879*5e7646d2SAndroid Build Coastguard Worker ppd->contone_only = !strcasecmp(string, "True");
880*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(keyword, "cupsFlipDuplex"))
881*5e7646d2SAndroid Build Coastguard Worker ppd->flip_duplex = !strcasecmp(string, "True");
882*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(keyword, "cupsManualCopies"))
883*5e7646d2SAndroid Build Coastguard Worker ppd->manual_copies = !strcasecmp(string, "True");
884*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(keyword, "cupsModelNumber"))
885*5e7646d2SAndroid Build Coastguard Worker ppd->model_number = atoi(string);
886*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(keyword, "cupsColorProfile"))
887*5e7646d2SAndroid Build Coastguard Worker {
888*5e7646d2SAndroid Build Coastguard Worker if (ppd->num_profiles == 0)
889*5e7646d2SAndroid Build Coastguard Worker profile = malloc(sizeof(ppd_profile_t));
890*5e7646d2SAndroid Build Coastguard Worker else
891*5e7646d2SAndroid Build Coastguard Worker profile = realloc(ppd->profiles, sizeof(ppd_profile_t) * (size_t)(ppd->num_profiles + 1));
892*5e7646d2SAndroid Build Coastguard Worker
893*5e7646d2SAndroid Build Coastguard Worker if (!profile)
894*5e7646d2SAndroid Build Coastguard Worker {
895*5e7646d2SAndroid Build Coastguard Worker pg->ppd_status = PPD_ALLOC_ERROR;
896*5e7646d2SAndroid Build Coastguard Worker
897*5e7646d2SAndroid Build Coastguard Worker goto error;
898*5e7646d2SAndroid Build Coastguard Worker }
899*5e7646d2SAndroid Build Coastguard Worker
900*5e7646d2SAndroid Build Coastguard Worker ppd->profiles = profile;
901*5e7646d2SAndroid Build Coastguard Worker profile += ppd->num_profiles;
902*5e7646d2SAndroid Build Coastguard Worker ppd->num_profiles ++;
903*5e7646d2SAndroid Build Coastguard Worker
904*5e7646d2SAndroid Build Coastguard Worker memset(profile, 0, sizeof(ppd_profile_t));
905*5e7646d2SAndroid Build Coastguard Worker strlcpy(profile->resolution, name, sizeof(profile->resolution));
906*5e7646d2SAndroid Build Coastguard Worker strlcpy(profile->media_type, text, sizeof(profile->media_type));
907*5e7646d2SAndroid Build Coastguard Worker
908*5e7646d2SAndroid Build Coastguard Worker profile->density = (float)_cupsStrScand(string, &sptr, loc);
909*5e7646d2SAndroid Build Coastguard Worker profile->gamma = (float)_cupsStrScand(sptr, &sptr, loc);
910*5e7646d2SAndroid Build Coastguard Worker profile->matrix[0][0] = (float)_cupsStrScand(sptr, &sptr, loc);
911*5e7646d2SAndroid Build Coastguard Worker profile->matrix[0][1] = (float)_cupsStrScand(sptr, &sptr, loc);
912*5e7646d2SAndroid Build Coastguard Worker profile->matrix[0][2] = (float)_cupsStrScand(sptr, &sptr, loc);
913*5e7646d2SAndroid Build Coastguard Worker profile->matrix[1][0] = (float)_cupsStrScand(sptr, &sptr, loc);
914*5e7646d2SAndroid Build Coastguard Worker profile->matrix[1][1] = (float)_cupsStrScand(sptr, &sptr, loc);
915*5e7646d2SAndroid Build Coastguard Worker profile->matrix[1][2] = (float)_cupsStrScand(sptr, &sptr, loc);
916*5e7646d2SAndroid Build Coastguard Worker profile->matrix[2][0] = (float)_cupsStrScand(sptr, &sptr, loc);
917*5e7646d2SAndroid Build Coastguard Worker profile->matrix[2][1] = (float)_cupsStrScand(sptr, &sptr, loc);
918*5e7646d2SAndroid Build Coastguard Worker profile->matrix[2][2] = (float)_cupsStrScand(sptr, &sptr, loc);
919*5e7646d2SAndroid Build Coastguard Worker }
920*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(keyword, "cupsFilter"))
921*5e7646d2SAndroid Build Coastguard Worker {
922*5e7646d2SAndroid Build Coastguard Worker if (ppd->num_filters == 0)
923*5e7646d2SAndroid Build Coastguard Worker filter = malloc(sizeof(char *));
924*5e7646d2SAndroid Build Coastguard Worker else
925*5e7646d2SAndroid Build Coastguard Worker filter = realloc(ppd->filters, sizeof(char *) * (size_t)(ppd->num_filters + 1));
926*5e7646d2SAndroid Build Coastguard Worker
927*5e7646d2SAndroid Build Coastguard Worker if (filter == NULL)
928*5e7646d2SAndroid Build Coastguard Worker {
929*5e7646d2SAndroid Build Coastguard Worker pg->ppd_status = PPD_ALLOC_ERROR;
930*5e7646d2SAndroid Build Coastguard Worker
931*5e7646d2SAndroid Build Coastguard Worker goto error;
932*5e7646d2SAndroid Build Coastguard Worker }
933*5e7646d2SAndroid Build Coastguard Worker
934*5e7646d2SAndroid Build Coastguard Worker ppd->filters = filter;
935*5e7646d2SAndroid Build Coastguard Worker filter += ppd->num_filters;
936*5e7646d2SAndroid Build Coastguard Worker ppd->num_filters ++;
937*5e7646d2SAndroid Build Coastguard Worker
938*5e7646d2SAndroid Build Coastguard Worker /*
939*5e7646d2SAndroid Build Coastguard Worker * Make a copy of the filter string...
940*5e7646d2SAndroid Build Coastguard Worker */
941*5e7646d2SAndroid Build Coastguard Worker
942*5e7646d2SAndroid Build Coastguard Worker *filter = strdup(string);
943*5e7646d2SAndroid Build Coastguard Worker }
944*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(keyword, "Throughput"))
945*5e7646d2SAndroid Build Coastguard Worker ppd->throughput = atoi(string);
946*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(keyword, "Font"))
947*5e7646d2SAndroid Build Coastguard Worker {
948*5e7646d2SAndroid Build Coastguard Worker /*
949*5e7646d2SAndroid Build Coastguard Worker * Add this font to the list of available fonts...
950*5e7646d2SAndroid Build Coastguard Worker */
951*5e7646d2SAndroid Build Coastguard Worker
952*5e7646d2SAndroid Build Coastguard Worker if (ppd->num_fonts == 0)
953*5e7646d2SAndroid Build Coastguard Worker tempfonts = (char **)malloc(sizeof(char *));
954*5e7646d2SAndroid Build Coastguard Worker else
955*5e7646d2SAndroid Build Coastguard Worker tempfonts = (char **)realloc(ppd->fonts, sizeof(char *) * (size_t)(ppd->num_fonts + 1));
956*5e7646d2SAndroid Build Coastguard Worker
957*5e7646d2SAndroid Build Coastguard Worker if (tempfonts == NULL)
958*5e7646d2SAndroid Build Coastguard Worker {
959*5e7646d2SAndroid Build Coastguard Worker pg->ppd_status = PPD_ALLOC_ERROR;
960*5e7646d2SAndroid Build Coastguard Worker
961*5e7646d2SAndroid Build Coastguard Worker goto error;
962*5e7646d2SAndroid Build Coastguard Worker }
963*5e7646d2SAndroid Build Coastguard Worker
964*5e7646d2SAndroid Build Coastguard Worker ppd->fonts = tempfonts;
965*5e7646d2SAndroid Build Coastguard Worker ppd->fonts[ppd->num_fonts] = strdup(name);
966*5e7646d2SAndroid Build Coastguard Worker ppd->num_fonts ++;
967*5e7646d2SAndroid Build Coastguard Worker }
968*5e7646d2SAndroid Build Coastguard Worker else if (!strncmp(keyword, "ParamCustom", 11))
969*5e7646d2SAndroid Build Coastguard Worker {
970*5e7646d2SAndroid Build Coastguard Worker ppd_coption_t *coption; /* Custom option */
971*5e7646d2SAndroid Build Coastguard Worker ppd_cparam_t *cparam; /* Custom parameter */
972*5e7646d2SAndroid Build Coastguard Worker int corder; /* Order number */
973*5e7646d2SAndroid Build Coastguard Worker char ctype[33], /* Data type */
974*5e7646d2SAndroid Build Coastguard Worker cminimum[65], /* Minimum value */
975*5e7646d2SAndroid Build Coastguard Worker cmaximum[65]; /* Maximum value */
976*5e7646d2SAndroid Build Coastguard Worker
977*5e7646d2SAndroid Build Coastguard Worker
978*5e7646d2SAndroid Build Coastguard Worker /*
979*5e7646d2SAndroid Build Coastguard Worker * Get the custom option and parameter...
980*5e7646d2SAndroid Build Coastguard Worker */
981*5e7646d2SAndroid Build Coastguard Worker
982*5e7646d2SAndroid Build Coastguard Worker if ((coption = ppd_get_coption(ppd, keyword + 11)) == NULL)
983*5e7646d2SAndroid Build Coastguard Worker {
984*5e7646d2SAndroid Build Coastguard Worker pg->ppd_status = PPD_ALLOC_ERROR;
985*5e7646d2SAndroid Build Coastguard Worker
986*5e7646d2SAndroid Build Coastguard Worker goto error;
987*5e7646d2SAndroid Build Coastguard Worker }
988*5e7646d2SAndroid Build Coastguard Worker
989*5e7646d2SAndroid Build Coastguard Worker if ((cparam = ppd_get_cparam(coption, name, text)) == NULL)
990*5e7646d2SAndroid Build Coastguard Worker {
991*5e7646d2SAndroid Build Coastguard Worker pg->ppd_status = PPD_ALLOC_ERROR;
992*5e7646d2SAndroid Build Coastguard Worker
993*5e7646d2SAndroid Build Coastguard Worker goto error;
994*5e7646d2SAndroid Build Coastguard Worker }
995*5e7646d2SAndroid Build Coastguard Worker
996*5e7646d2SAndroid Build Coastguard Worker if (cparam->type != PPD_CUSTOM_UNKNOWN)
997*5e7646d2SAndroid Build Coastguard Worker {
998*5e7646d2SAndroid Build Coastguard Worker pg->ppd_status = PPD_BAD_CUSTOM_PARAM;
999*5e7646d2SAndroid Build Coastguard Worker
1000*5e7646d2SAndroid Build Coastguard Worker goto error;
1001*5e7646d2SAndroid Build Coastguard Worker }
1002*5e7646d2SAndroid Build Coastguard Worker
1003*5e7646d2SAndroid Build Coastguard Worker /*
1004*5e7646d2SAndroid Build Coastguard Worker * Get the parameter data...
1005*5e7646d2SAndroid Build Coastguard Worker */
1006*5e7646d2SAndroid Build Coastguard Worker
1007*5e7646d2SAndroid Build Coastguard Worker if (!string ||
1008*5e7646d2SAndroid Build Coastguard Worker sscanf(string, "%d%32s%64s%64s", &corder, ctype, cminimum,
1009*5e7646d2SAndroid Build Coastguard Worker cmaximum) != 4)
1010*5e7646d2SAndroid Build Coastguard Worker {
1011*5e7646d2SAndroid Build Coastguard Worker pg->ppd_status = PPD_BAD_CUSTOM_PARAM;
1012*5e7646d2SAndroid Build Coastguard Worker
1013*5e7646d2SAndroid Build Coastguard Worker goto error;
1014*5e7646d2SAndroid Build Coastguard Worker }
1015*5e7646d2SAndroid Build Coastguard Worker
1016*5e7646d2SAndroid Build Coastguard Worker cparam->order = corder;
1017*5e7646d2SAndroid Build Coastguard Worker
1018*5e7646d2SAndroid Build Coastguard Worker if (!strcmp(ctype, "curve"))
1019*5e7646d2SAndroid Build Coastguard Worker {
1020*5e7646d2SAndroid Build Coastguard Worker cparam->type = PPD_CUSTOM_CURVE;
1021*5e7646d2SAndroid Build Coastguard Worker cparam->minimum.custom_curve = (float)_cupsStrScand(cminimum, NULL, loc);
1022*5e7646d2SAndroid Build Coastguard Worker cparam->maximum.custom_curve = (float)_cupsStrScand(cmaximum, NULL, loc);
1023*5e7646d2SAndroid Build Coastguard Worker }
1024*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(ctype, "int"))
1025*5e7646d2SAndroid Build Coastguard Worker {
1026*5e7646d2SAndroid Build Coastguard Worker cparam->type = PPD_CUSTOM_INT;
1027*5e7646d2SAndroid Build Coastguard Worker cparam->minimum.custom_int = atoi(cminimum);
1028*5e7646d2SAndroid Build Coastguard Worker cparam->maximum.custom_int = atoi(cmaximum);
1029*5e7646d2SAndroid Build Coastguard Worker }
1030*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(ctype, "invcurve"))
1031*5e7646d2SAndroid Build Coastguard Worker {
1032*5e7646d2SAndroid Build Coastguard Worker cparam->type = PPD_CUSTOM_INVCURVE;
1033*5e7646d2SAndroid Build Coastguard Worker cparam->minimum.custom_invcurve = (float)_cupsStrScand(cminimum, NULL, loc);
1034*5e7646d2SAndroid Build Coastguard Worker cparam->maximum.custom_invcurve = (float)_cupsStrScand(cmaximum, NULL, loc);
1035*5e7646d2SAndroid Build Coastguard Worker }
1036*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(ctype, "passcode"))
1037*5e7646d2SAndroid Build Coastguard Worker {
1038*5e7646d2SAndroid Build Coastguard Worker cparam->type = PPD_CUSTOM_PASSCODE;
1039*5e7646d2SAndroid Build Coastguard Worker cparam->minimum.custom_passcode = atoi(cminimum);
1040*5e7646d2SAndroid Build Coastguard Worker cparam->maximum.custom_passcode = atoi(cmaximum);
1041*5e7646d2SAndroid Build Coastguard Worker }
1042*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(ctype, "password"))
1043*5e7646d2SAndroid Build Coastguard Worker {
1044*5e7646d2SAndroid Build Coastguard Worker cparam->type = PPD_CUSTOM_PASSWORD;
1045*5e7646d2SAndroid Build Coastguard Worker cparam->minimum.custom_password = atoi(cminimum);
1046*5e7646d2SAndroid Build Coastguard Worker cparam->maximum.custom_password = atoi(cmaximum);
1047*5e7646d2SAndroid Build Coastguard Worker }
1048*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(ctype, "points"))
1049*5e7646d2SAndroid Build Coastguard Worker {
1050*5e7646d2SAndroid Build Coastguard Worker cparam->type = PPD_CUSTOM_POINTS;
1051*5e7646d2SAndroid Build Coastguard Worker cparam->minimum.custom_points = (float)_cupsStrScand(cminimum, NULL, loc);
1052*5e7646d2SAndroid Build Coastguard Worker cparam->maximum.custom_points = (float)_cupsStrScand(cmaximum, NULL, loc);
1053*5e7646d2SAndroid Build Coastguard Worker }
1054*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(ctype, "real"))
1055*5e7646d2SAndroid Build Coastguard Worker {
1056*5e7646d2SAndroid Build Coastguard Worker cparam->type = PPD_CUSTOM_REAL;
1057*5e7646d2SAndroid Build Coastguard Worker cparam->minimum.custom_real = (float)_cupsStrScand(cminimum, NULL, loc);
1058*5e7646d2SAndroid Build Coastguard Worker cparam->maximum.custom_real = (float)_cupsStrScand(cmaximum, NULL, loc);
1059*5e7646d2SAndroid Build Coastguard Worker }
1060*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(ctype, "string"))
1061*5e7646d2SAndroid Build Coastguard Worker {
1062*5e7646d2SAndroid Build Coastguard Worker cparam->type = PPD_CUSTOM_STRING;
1063*5e7646d2SAndroid Build Coastguard Worker cparam->minimum.custom_string = atoi(cminimum);
1064*5e7646d2SAndroid Build Coastguard Worker cparam->maximum.custom_string = atoi(cmaximum);
1065*5e7646d2SAndroid Build Coastguard Worker }
1066*5e7646d2SAndroid Build Coastguard Worker else
1067*5e7646d2SAndroid Build Coastguard Worker {
1068*5e7646d2SAndroid Build Coastguard Worker pg->ppd_status = PPD_BAD_CUSTOM_PARAM;
1069*5e7646d2SAndroid Build Coastguard Worker
1070*5e7646d2SAndroid Build Coastguard Worker goto error;
1071*5e7646d2SAndroid Build Coastguard Worker }
1072*5e7646d2SAndroid Build Coastguard Worker
1073*5e7646d2SAndroid Build Coastguard Worker /*
1074*5e7646d2SAndroid Build Coastguard Worker * Now special-case for CustomPageSize...
1075*5e7646d2SAndroid Build Coastguard Worker */
1076*5e7646d2SAndroid Build Coastguard Worker
1077*5e7646d2SAndroid Build Coastguard Worker if (!strcmp(coption->keyword, "PageSize"))
1078*5e7646d2SAndroid Build Coastguard Worker {
1079*5e7646d2SAndroid Build Coastguard Worker if (!strcmp(name, "Width"))
1080*5e7646d2SAndroid Build Coastguard Worker {
1081*5e7646d2SAndroid Build Coastguard Worker ppd->custom_min[0] = cparam->minimum.custom_points;
1082*5e7646d2SAndroid Build Coastguard Worker ppd->custom_max[0] = cparam->maximum.custom_points;
1083*5e7646d2SAndroid Build Coastguard Worker }
1084*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(name, "Height"))
1085*5e7646d2SAndroid Build Coastguard Worker {
1086*5e7646d2SAndroid Build Coastguard Worker ppd->custom_min[1] = cparam->minimum.custom_points;
1087*5e7646d2SAndroid Build Coastguard Worker ppd->custom_max[1] = cparam->maximum.custom_points;
1088*5e7646d2SAndroid Build Coastguard Worker }
1089*5e7646d2SAndroid Build Coastguard Worker }
1090*5e7646d2SAndroid Build Coastguard Worker }
1091*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(keyword, "HWMargins"))
1092*5e7646d2SAndroid Build Coastguard Worker {
1093*5e7646d2SAndroid Build Coastguard Worker for (i = 0, sptr = string; i < 4; i ++)
1094*5e7646d2SAndroid Build Coastguard Worker ppd->custom_margins[i] = (float)_cupsStrScand(sptr, &sptr, loc);
1095*5e7646d2SAndroid Build Coastguard Worker }
1096*5e7646d2SAndroid Build Coastguard Worker else if (!strncmp(keyword, "Custom", 6) && !strcmp(name, "True") && !option)
1097*5e7646d2SAndroid Build Coastguard Worker {
1098*5e7646d2SAndroid Build Coastguard Worker ppd_option_t *custom_option; /* Custom option */
1099*5e7646d2SAndroid Build Coastguard Worker
1100*5e7646d2SAndroid Build Coastguard Worker DEBUG_puts("2_ppdOpen: Processing Custom option...");
1101*5e7646d2SAndroid Build Coastguard Worker
1102*5e7646d2SAndroid Build Coastguard Worker /*
1103*5e7646d2SAndroid Build Coastguard Worker * Get the option and custom option...
1104*5e7646d2SAndroid Build Coastguard Worker */
1105*5e7646d2SAndroid Build Coastguard Worker
1106*5e7646d2SAndroid Build Coastguard Worker if (!ppd_get_coption(ppd, keyword + 6))
1107*5e7646d2SAndroid Build Coastguard Worker {
1108*5e7646d2SAndroid Build Coastguard Worker pg->ppd_status = PPD_ALLOC_ERROR;
1109*5e7646d2SAndroid Build Coastguard Worker
1110*5e7646d2SAndroid Build Coastguard Worker goto error;
1111*5e7646d2SAndroid Build Coastguard Worker }
1112*5e7646d2SAndroid Build Coastguard Worker
1113*5e7646d2SAndroid Build Coastguard Worker if (option && !_cups_strcasecmp(option->keyword, keyword + 6))
1114*5e7646d2SAndroid Build Coastguard Worker custom_option = option;
1115*5e7646d2SAndroid Build Coastguard Worker else
1116*5e7646d2SAndroid Build Coastguard Worker custom_option = ppdFindOption(ppd, keyword + 6);
1117*5e7646d2SAndroid Build Coastguard Worker
1118*5e7646d2SAndroid Build Coastguard Worker if (custom_option)
1119*5e7646d2SAndroid Build Coastguard Worker {
1120*5e7646d2SAndroid Build Coastguard Worker /*
1121*5e7646d2SAndroid Build Coastguard Worker * Add the "custom" option...
1122*5e7646d2SAndroid Build Coastguard Worker */
1123*5e7646d2SAndroid Build Coastguard Worker
1124*5e7646d2SAndroid Build Coastguard Worker if ((choice = ppdFindChoice(custom_option, "Custom")) == NULL)
1125*5e7646d2SAndroid Build Coastguard Worker if ((choice = ppd_add_choice(custom_option, "Custom")) == NULL)
1126*5e7646d2SAndroid Build Coastguard Worker {
1127*5e7646d2SAndroid Build Coastguard Worker DEBUG_puts("1_ppdOpen: Unable to add Custom choice!");
1128*5e7646d2SAndroid Build Coastguard Worker
1129*5e7646d2SAndroid Build Coastguard Worker pg->ppd_status = PPD_ALLOC_ERROR;
1130*5e7646d2SAndroid Build Coastguard Worker
1131*5e7646d2SAndroid Build Coastguard Worker goto error;
1132*5e7646d2SAndroid Build Coastguard Worker }
1133*5e7646d2SAndroid Build Coastguard Worker
1134*5e7646d2SAndroid Build Coastguard Worker strlcpy(choice->text, text[0] ? text : _("Custom"),
1135*5e7646d2SAndroid Build Coastguard Worker sizeof(choice->text));
1136*5e7646d2SAndroid Build Coastguard Worker
1137*5e7646d2SAndroid Build Coastguard Worker choice->code = strdup(string);
1138*5e7646d2SAndroid Build Coastguard Worker
1139*5e7646d2SAndroid Build Coastguard Worker if (custom_option->section == PPD_ORDER_JCL)
1140*5e7646d2SAndroid Build Coastguard Worker ppd_decode(choice->code);
1141*5e7646d2SAndroid Build Coastguard Worker }
1142*5e7646d2SAndroid Build Coastguard Worker
1143*5e7646d2SAndroid Build Coastguard Worker /*
1144*5e7646d2SAndroid Build Coastguard Worker * Now process custom page sizes specially...
1145*5e7646d2SAndroid Build Coastguard Worker */
1146*5e7646d2SAndroid Build Coastguard Worker
1147*5e7646d2SAndroid Build Coastguard Worker if (!strcmp(keyword, "CustomPageSize"))
1148*5e7646d2SAndroid Build Coastguard Worker {
1149*5e7646d2SAndroid Build Coastguard Worker /*
1150*5e7646d2SAndroid Build Coastguard Worker * Add a "Custom" page size entry...
1151*5e7646d2SAndroid Build Coastguard Worker */
1152*5e7646d2SAndroid Build Coastguard Worker
1153*5e7646d2SAndroid Build Coastguard Worker ppd->variable_sizes = 1;
1154*5e7646d2SAndroid Build Coastguard Worker
1155*5e7646d2SAndroid Build Coastguard Worker ppd_add_size(ppd, "Custom");
1156*5e7646d2SAndroid Build Coastguard Worker
1157*5e7646d2SAndroid Build Coastguard Worker if (option && !_cups_strcasecmp(option->keyword, "PageRegion"))
1158*5e7646d2SAndroid Build Coastguard Worker custom_option = option;
1159*5e7646d2SAndroid Build Coastguard Worker else
1160*5e7646d2SAndroid Build Coastguard Worker custom_option = ppdFindOption(ppd, "PageRegion");
1161*5e7646d2SAndroid Build Coastguard Worker
1162*5e7646d2SAndroid Build Coastguard Worker if (custom_option)
1163*5e7646d2SAndroid Build Coastguard Worker {
1164*5e7646d2SAndroid Build Coastguard Worker if ((choice = ppdFindChoice(custom_option, "Custom")) == NULL)
1165*5e7646d2SAndroid Build Coastguard Worker if ((choice = ppd_add_choice(custom_option, "Custom")) == NULL)
1166*5e7646d2SAndroid Build Coastguard Worker {
1167*5e7646d2SAndroid Build Coastguard Worker DEBUG_puts("1_ppdOpen: Unable to add Custom choice!");
1168*5e7646d2SAndroid Build Coastguard Worker
1169*5e7646d2SAndroid Build Coastguard Worker pg->ppd_status = PPD_ALLOC_ERROR;
1170*5e7646d2SAndroid Build Coastguard Worker
1171*5e7646d2SAndroid Build Coastguard Worker goto error;
1172*5e7646d2SAndroid Build Coastguard Worker }
1173*5e7646d2SAndroid Build Coastguard Worker
1174*5e7646d2SAndroid Build Coastguard Worker strlcpy(choice->text, text[0] ? text : _("Custom"),
1175*5e7646d2SAndroid Build Coastguard Worker sizeof(choice->text));
1176*5e7646d2SAndroid Build Coastguard Worker }
1177*5e7646d2SAndroid Build Coastguard Worker }
1178*5e7646d2SAndroid Build Coastguard Worker }
1179*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(keyword, "LandscapeOrientation"))
1180*5e7646d2SAndroid Build Coastguard Worker {
1181*5e7646d2SAndroid Build Coastguard Worker if (!strcmp(string, "Minus90"))
1182*5e7646d2SAndroid Build Coastguard Worker ppd->landscape = -90;
1183*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(string, "Plus90"))
1184*5e7646d2SAndroid Build Coastguard Worker ppd->landscape = 90;
1185*5e7646d2SAndroid Build Coastguard Worker }
1186*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(keyword, "Emulators") && string && ppd->num_emulations == 0)
1187*5e7646d2SAndroid Build Coastguard Worker {
1188*5e7646d2SAndroid Build Coastguard Worker /*
1189*5e7646d2SAndroid Build Coastguard Worker * Issue #5562: Samsung printer drivers incorrectly use Emulators keyword
1190*5e7646d2SAndroid Build Coastguard Worker * to configure themselves
1191*5e7646d2SAndroid Build Coastguard Worker *
1192*5e7646d2SAndroid Build Coastguard Worker * The Emulators keyword was loaded but never used by anything in CUPS,
1193*5e7646d2SAndroid Build Coastguard Worker * and has no valid purpose in CUPS. The old code was removed due to a
1194*5e7646d2SAndroid Build Coastguard Worker * memory leak (Issue #5475), so the following (new) code supports a single
1195*5e7646d2SAndroid Build Coastguard Worker * name for the Emulators keyword, allowing these drivers to work until we
1196*5e7646d2SAndroid Build Coastguard Worker * remove PPD and driver support entirely in a future version of CUPS.
1197*5e7646d2SAndroid Build Coastguard Worker */
1198*5e7646d2SAndroid Build Coastguard Worker
1199*5e7646d2SAndroid Build Coastguard Worker ppd->num_emulations = 1;
1200*5e7646d2SAndroid Build Coastguard Worker ppd->emulations = calloc(1, sizeof(ppd_emul_t));
1201*5e7646d2SAndroid Build Coastguard Worker
1202*5e7646d2SAndroid Build Coastguard Worker strlcpy(ppd->emulations[0].name, string, sizeof(ppd->emulations[0].name));
1203*5e7646d2SAndroid Build Coastguard Worker }
1204*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(keyword, "JobPatchFile"))
1205*5e7646d2SAndroid Build Coastguard Worker {
1206*5e7646d2SAndroid Build Coastguard Worker /*
1207*5e7646d2SAndroid Build Coastguard Worker * CUPS STR #3421: Check for "*JobPatchFile: int: string"
1208*5e7646d2SAndroid Build Coastguard Worker */
1209*5e7646d2SAndroid Build Coastguard Worker
1210*5e7646d2SAndroid Build Coastguard Worker if (isdigit(*string & 255))
1211*5e7646d2SAndroid Build Coastguard Worker {
1212*5e7646d2SAndroid Build Coastguard Worker for (sptr = string + 1; isdigit(*sptr & 255); sptr ++);
1213*5e7646d2SAndroid Build Coastguard Worker
1214*5e7646d2SAndroid Build Coastguard Worker if (*sptr == ':')
1215*5e7646d2SAndroid Build Coastguard Worker {
1216*5e7646d2SAndroid Build Coastguard Worker /*
1217*5e7646d2SAndroid Build Coastguard Worker * Found "*JobPatchFile: int: string"...
1218*5e7646d2SAndroid Build Coastguard Worker */
1219*5e7646d2SAndroid Build Coastguard Worker
1220*5e7646d2SAndroid Build Coastguard Worker pg->ppd_status = PPD_BAD_VALUE;
1221*5e7646d2SAndroid Build Coastguard Worker
1222*5e7646d2SAndroid Build Coastguard Worker goto error;
1223*5e7646d2SAndroid Build Coastguard Worker }
1224*5e7646d2SAndroid Build Coastguard Worker }
1225*5e7646d2SAndroid Build Coastguard Worker
1226*5e7646d2SAndroid Build Coastguard Worker if (!name[0] && pg->ppd_conform == PPD_CONFORM_STRICT)
1227*5e7646d2SAndroid Build Coastguard Worker {
1228*5e7646d2SAndroid Build Coastguard Worker /*
1229*5e7646d2SAndroid Build Coastguard Worker * Found "*JobPatchFile: string"...
1230*5e7646d2SAndroid Build Coastguard Worker */
1231*5e7646d2SAndroid Build Coastguard Worker
1232*5e7646d2SAndroid Build Coastguard Worker pg->ppd_status = PPD_MISSING_OPTION_KEYWORD;
1233*5e7646d2SAndroid Build Coastguard Worker
1234*5e7646d2SAndroid Build Coastguard Worker goto error;
1235*5e7646d2SAndroid Build Coastguard Worker }
1236*5e7646d2SAndroid Build Coastguard Worker
1237*5e7646d2SAndroid Build Coastguard Worker if (ppd->patches == NULL)
1238*5e7646d2SAndroid Build Coastguard Worker ppd->patches = strdup(string);
1239*5e7646d2SAndroid Build Coastguard Worker else
1240*5e7646d2SAndroid Build Coastguard Worker {
1241*5e7646d2SAndroid Build Coastguard Worker temp = realloc(ppd->patches, strlen(ppd->patches) +
1242*5e7646d2SAndroid Build Coastguard Worker strlen(string) + 1);
1243*5e7646d2SAndroid Build Coastguard Worker if (temp == NULL)
1244*5e7646d2SAndroid Build Coastguard Worker {
1245*5e7646d2SAndroid Build Coastguard Worker pg->ppd_status = PPD_ALLOC_ERROR;
1246*5e7646d2SAndroid Build Coastguard Worker
1247*5e7646d2SAndroid Build Coastguard Worker goto error;
1248*5e7646d2SAndroid Build Coastguard Worker }
1249*5e7646d2SAndroid Build Coastguard Worker
1250*5e7646d2SAndroid Build Coastguard Worker ppd->patches = temp;
1251*5e7646d2SAndroid Build Coastguard Worker
1252*5e7646d2SAndroid Build Coastguard Worker memcpy(ppd->patches + strlen(ppd->patches), string, strlen(string) + 1);
1253*5e7646d2SAndroid Build Coastguard Worker }
1254*5e7646d2SAndroid Build Coastguard Worker }
1255*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(keyword, "OpenUI"))
1256*5e7646d2SAndroid Build Coastguard Worker {
1257*5e7646d2SAndroid Build Coastguard Worker /*
1258*5e7646d2SAndroid Build Coastguard Worker * Don't allow nesting of options...
1259*5e7646d2SAndroid Build Coastguard Worker */
1260*5e7646d2SAndroid Build Coastguard Worker
1261*5e7646d2SAndroid Build Coastguard Worker if (option && pg->ppd_conform == PPD_CONFORM_STRICT)
1262*5e7646d2SAndroid Build Coastguard Worker {
1263*5e7646d2SAndroid Build Coastguard Worker pg->ppd_status = PPD_NESTED_OPEN_UI;
1264*5e7646d2SAndroid Build Coastguard Worker
1265*5e7646d2SAndroid Build Coastguard Worker goto error;
1266*5e7646d2SAndroid Build Coastguard Worker }
1267*5e7646d2SAndroid Build Coastguard Worker
1268*5e7646d2SAndroid Build Coastguard Worker /*
1269*5e7646d2SAndroid Build Coastguard Worker * Add an option record to the current sub-group, group, or file...
1270*5e7646d2SAndroid Build Coastguard Worker */
1271*5e7646d2SAndroid Build Coastguard Worker
1272*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("2_ppdOpen: name=\"%s\" (%d)", name, (int)strlen(name)));
1273*5e7646d2SAndroid Build Coastguard Worker
1274*5e7646d2SAndroid Build Coastguard Worker if (name[0] == '*')
1275*5e7646d2SAndroid Build Coastguard Worker _cups_strcpy(name, name + 1); /* Eliminate leading asterisk */
1276*5e7646d2SAndroid Build Coastguard Worker
1277*5e7646d2SAndroid Build Coastguard Worker for (i = (int)strlen(name) - 1; i > 0 && _cups_isspace(name[i]); i --)
1278*5e7646d2SAndroid Build Coastguard Worker name[i] = '\0'; /* Eliminate trailing spaces */
1279*5e7646d2SAndroid Build Coastguard Worker
1280*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("2_ppdOpen: OpenUI of %s in group %s...", name,
1281*5e7646d2SAndroid Build Coastguard Worker group ? group->text : "(null)"));
1282*5e7646d2SAndroid Build Coastguard Worker
1283*5e7646d2SAndroid Build Coastguard Worker if (subgroup != NULL)
1284*5e7646d2SAndroid Build Coastguard Worker option = ppd_get_option(subgroup, name);
1285*5e7646d2SAndroid Build Coastguard Worker else if (group == NULL)
1286*5e7646d2SAndroid Build Coastguard Worker {
1287*5e7646d2SAndroid Build Coastguard Worker if ((group = ppd_get_group(ppd, "General", _("General"), pg,
1288*5e7646d2SAndroid Build Coastguard Worker encoding)) == NULL)
1289*5e7646d2SAndroid Build Coastguard Worker goto error;
1290*5e7646d2SAndroid Build Coastguard Worker
1291*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("2_ppdOpen: Adding to group %s...", group->text));
1292*5e7646d2SAndroid Build Coastguard Worker option = ppd_get_option(group, name);
1293*5e7646d2SAndroid Build Coastguard Worker group = NULL;
1294*5e7646d2SAndroid Build Coastguard Worker }
1295*5e7646d2SAndroid Build Coastguard Worker else
1296*5e7646d2SAndroid Build Coastguard Worker option = ppd_get_option(group, name);
1297*5e7646d2SAndroid Build Coastguard Worker
1298*5e7646d2SAndroid Build Coastguard Worker if (option == NULL)
1299*5e7646d2SAndroid Build Coastguard Worker {
1300*5e7646d2SAndroid Build Coastguard Worker pg->ppd_status = PPD_ALLOC_ERROR;
1301*5e7646d2SAndroid Build Coastguard Worker
1302*5e7646d2SAndroid Build Coastguard Worker goto error;
1303*5e7646d2SAndroid Build Coastguard Worker }
1304*5e7646d2SAndroid Build Coastguard Worker
1305*5e7646d2SAndroid Build Coastguard Worker /*
1306*5e7646d2SAndroid Build Coastguard Worker * Now fill in the initial information for the option...
1307*5e7646d2SAndroid Build Coastguard Worker */
1308*5e7646d2SAndroid Build Coastguard Worker
1309*5e7646d2SAndroid Build Coastguard Worker if (string && !strcmp(string, "PickMany"))
1310*5e7646d2SAndroid Build Coastguard Worker option->ui = PPD_UI_PICKMANY;
1311*5e7646d2SAndroid Build Coastguard Worker else if (string && !strcmp(string, "Boolean"))
1312*5e7646d2SAndroid Build Coastguard Worker option->ui = PPD_UI_BOOLEAN;
1313*5e7646d2SAndroid Build Coastguard Worker else if (string && !strcmp(string, "PickOne"))
1314*5e7646d2SAndroid Build Coastguard Worker option->ui = PPD_UI_PICKONE;
1315*5e7646d2SAndroid Build Coastguard Worker else if (pg->ppd_conform == PPD_CONFORM_STRICT)
1316*5e7646d2SAndroid Build Coastguard Worker {
1317*5e7646d2SAndroid Build Coastguard Worker pg->ppd_status = PPD_BAD_OPEN_UI;
1318*5e7646d2SAndroid Build Coastguard Worker
1319*5e7646d2SAndroid Build Coastguard Worker goto error;
1320*5e7646d2SAndroid Build Coastguard Worker }
1321*5e7646d2SAndroid Build Coastguard Worker else
1322*5e7646d2SAndroid Build Coastguard Worker option->ui = PPD_UI_PICKONE;
1323*5e7646d2SAndroid Build Coastguard Worker
1324*5e7646d2SAndroid Build Coastguard Worker for (j = 0; j < ppd->num_attrs; j ++)
1325*5e7646d2SAndroid Build Coastguard Worker if (!strncmp(ppd->attrs[j]->name, "Default", 7) &&
1326*5e7646d2SAndroid Build Coastguard Worker !strcmp(ppd->attrs[j]->name + 7, name) &&
1327*5e7646d2SAndroid Build Coastguard Worker ppd->attrs[j]->value)
1328*5e7646d2SAndroid Build Coastguard Worker {
1329*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("2_ppdOpen: Setting Default%s to %s via attribute...",
1330*5e7646d2SAndroid Build Coastguard Worker option->keyword, ppd->attrs[j]->value));
1331*5e7646d2SAndroid Build Coastguard Worker strlcpy(option->defchoice, ppd->attrs[j]->value,
1332*5e7646d2SAndroid Build Coastguard Worker sizeof(option->defchoice));
1333*5e7646d2SAndroid Build Coastguard Worker break;
1334*5e7646d2SAndroid Build Coastguard Worker }
1335*5e7646d2SAndroid Build Coastguard Worker
1336*5e7646d2SAndroid Build Coastguard Worker if (text[0])
1337*5e7646d2SAndroid Build Coastguard Worker cupsCharsetToUTF8((cups_utf8_t *)option->text, text,
1338*5e7646d2SAndroid Build Coastguard Worker sizeof(option->text), encoding);
1339*5e7646d2SAndroid Build Coastguard Worker else
1340*5e7646d2SAndroid Build Coastguard Worker {
1341*5e7646d2SAndroid Build Coastguard Worker if (!strcmp(name, "PageSize"))
1342*5e7646d2SAndroid Build Coastguard Worker strlcpy(option->text, _("Media Size"), sizeof(option->text));
1343*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(name, "MediaType"))
1344*5e7646d2SAndroid Build Coastguard Worker strlcpy(option->text, _("Media Type"), sizeof(option->text));
1345*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(name, "InputSlot"))
1346*5e7646d2SAndroid Build Coastguard Worker strlcpy(option->text, _("Media Source"), sizeof(option->text));
1347*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(name, "ColorModel"))
1348*5e7646d2SAndroid Build Coastguard Worker strlcpy(option->text, _("Output Mode"), sizeof(option->text));
1349*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(name, "Resolution"))
1350*5e7646d2SAndroid Build Coastguard Worker strlcpy(option->text, _("Resolution"), sizeof(option->text));
1351*5e7646d2SAndroid Build Coastguard Worker else
1352*5e7646d2SAndroid Build Coastguard Worker strlcpy(option->text, name, sizeof(option->text));
1353*5e7646d2SAndroid Build Coastguard Worker }
1354*5e7646d2SAndroid Build Coastguard Worker
1355*5e7646d2SAndroid Build Coastguard Worker option->section = PPD_ORDER_ANY;
1356*5e7646d2SAndroid Build Coastguard Worker
1357*5e7646d2SAndroid Build Coastguard Worker free(string);
1358*5e7646d2SAndroid Build Coastguard Worker string = NULL;
1359*5e7646d2SAndroid Build Coastguard Worker
1360*5e7646d2SAndroid Build Coastguard Worker /*
1361*5e7646d2SAndroid Build Coastguard Worker * Add a custom option choice if we have already seen a CustomFoo
1362*5e7646d2SAndroid Build Coastguard Worker * attribute...
1363*5e7646d2SAndroid Build Coastguard Worker */
1364*5e7646d2SAndroid Build Coastguard Worker
1365*5e7646d2SAndroid Build Coastguard Worker if (!_cups_strcasecmp(name, "PageRegion"))
1366*5e7646d2SAndroid Build Coastguard Worker strlcpy(custom_name, "CustomPageSize", sizeof(custom_name));
1367*5e7646d2SAndroid Build Coastguard Worker else
1368*5e7646d2SAndroid Build Coastguard Worker snprintf(custom_name, sizeof(custom_name), "Custom%s", name);
1369*5e7646d2SAndroid Build Coastguard Worker
1370*5e7646d2SAndroid Build Coastguard Worker if ((custom_attr = ppdFindAttr(ppd, custom_name, "True")) != NULL)
1371*5e7646d2SAndroid Build Coastguard Worker {
1372*5e7646d2SAndroid Build Coastguard Worker if ((choice = ppdFindChoice(option, "Custom")) == NULL)
1373*5e7646d2SAndroid Build Coastguard Worker if ((choice = ppd_add_choice(option, "Custom")) == NULL)
1374*5e7646d2SAndroid Build Coastguard Worker {
1375*5e7646d2SAndroid Build Coastguard Worker DEBUG_puts("1_ppdOpen: Unable to add Custom choice!");
1376*5e7646d2SAndroid Build Coastguard Worker
1377*5e7646d2SAndroid Build Coastguard Worker pg->ppd_status = PPD_ALLOC_ERROR;
1378*5e7646d2SAndroid Build Coastguard Worker
1379*5e7646d2SAndroid Build Coastguard Worker goto error;
1380*5e7646d2SAndroid Build Coastguard Worker }
1381*5e7646d2SAndroid Build Coastguard Worker
1382*5e7646d2SAndroid Build Coastguard Worker strlcpy(choice->text,
1383*5e7646d2SAndroid Build Coastguard Worker custom_attr->text[0] ? custom_attr->text : _("Custom"),
1384*5e7646d2SAndroid Build Coastguard Worker sizeof(choice->text));
1385*5e7646d2SAndroid Build Coastguard Worker choice->code = strdup(custom_attr->value);
1386*5e7646d2SAndroid Build Coastguard Worker }
1387*5e7646d2SAndroid Build Coastguard Worker }
1388*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(keyword, "JCLOpenUI"))
1389*5e7646d2SAndroid Build Coastguard Worker {
1390*5e7646d2SAndroid Build Coastguard Worker /*
1391*5e7646d2SAndroid Build Coastguard Worker * Don't allow nesting of options...
1392*5e7646d2SAndroid Build Coastguard Worker */
1393*5e7646d2SAndroid Build Coastguard Worker
1394*5e7646d2SAndroid Build Coastguard Worker if (option && pg->ppd_conform == PPD_CONFORM_STRICT)
1395*5e7646d2SAndroid Build Coastguard Worker {
1396*5e7646d2SAndroid Build Coastguard Worker pg->ppd_status = PPD_NESTED_OPEN_UI;
1397*5e7646d2SAndroid Build Coastguard Worker
1398*5e7646d2SAndroid Build Coastguard Worker goto error;
1399*5e7646d2SAndroid Build Coastguard Worker }
1400*5e7646d2SAndroid Build Coastguard Worker
1401*5e7646d2SAndroid Build Coastguard Worker /*
1402*5e7646d2SAndroid Build Coastguard Worker * Find the JCL group, and add if needed...
1403*5e7646d2SAndroid Build Coastguard Worker */
1404*5e7646d2SAndroid Build Coastguard Worker
1405*5e7646d2SAndroid Build Coastguard Worker group = ppd_get_group(ppd, "JCL", _("JCL"), pg, encoding);
1406*5e7646d2SAndroid Build Coastguard Worker
1407*5e7646d2SAndroid Build Coastguard Worker if (group == NULL)
1408*5e7646d2SAndroid Build Coastguard Worker goto error;
1409*5e7646d2SAndroid Build Coastguard Worker
1410*5e7646d2SAndroid Build Coastguard Worker /*
1411*5e7646d2SAndroid Build Coastguard Worker * Add an option record to the current JCLs...
1412*5e7646d2SAndroid Build Coastguard Worker */
1413*5e7646d2SAndroid Build Coastguard Worker
1414*5e7646d2SAndroid Build Coastguard Worker if (name[0] == '*')
1415*5e7646d2SAndroid Build Coastguard Worker _cups_strcpy(name, name + 1);
1416*5e7646d2SAndroid Build Coastguard Worker
1417*5e7646d2SAndroid Build Coastguard Worker option = ppd_get_option(group, name);
1418*5e7646d2SAndroid Build Coastguard Worker
1419*5e7646d2SAndroid Build Coastguard Worker if (option == NULL)
1420*5e7646d2SAndroid Build Coastguard Worker {
1421*5e7646d2SAndroid Build Coastguard Worker pg->ppd_status = PPD_ALLOC_ERROR;
1422*5e7646d2SAndroid Build Coastguard Worker
1423*5e7646d2SAndroid Build Coastguard Worker goto error;
1424*5e7646d2SAndroid Build Coastguard Worker }
1425*5e7646d2SAndroid Build Coastguard Worker
1426*5e7646d2SAndroid Build Coastguard Worker /*
1427*5e7646d2SAndroid Build Coastguard Worker * Now fill in the initial information for the option...
1428*5e7646d2SAndroid Build Coastguard Worker */
1429*5e7646d2SAndroid Build Coastguard Worker
1430*5e7646d2SAndroid Build Coastguard Worker if (string && !strcmp(string, "PickMany"))
1431*5e7646d2SAndroid Build Coastguard Worker option->ui = PPD_UI_PICKMANY;
1432*5e7646d2SAndroid Build Coastguard Worker else if (string && !strcmp(string, "Boolean"))
1433*5e7646d2SAndroid Build Coastguard Worker option->ui = PPD_UI_BOOLEAN;
1434*5e7646d2SAndroid Build Coastguard Worker else if (string && !strcmp(string, "PickOne"))
1435*5e7646d2SAndroid Build Coastguard Worker option->ui = PPD_UI_PICKONE;
1436*5e7646d2SAndroid Build Coastguard Worker else
1437*5e7646d2SAndroid Build Coastguard Worker {
1438*5e7646d2SAndroid Build Coastguard Worker pg->ppd_status = PPD_BAD_OPEN_UI;
1439*5e7646d2SAndroid Build Coastguard Worker
1440*5e7646d2SAndroid Build Coastguard Worker goto error;
1441*5e7646d2SAndroid Build Coastguard Worker }
1442*5e7646d2SAndroid Build Coastguard Worker
1443*5e7646d2SAndroid Build Coastguard Worker for (j = 0; j < ppd->num_attrs; j ++)
1444*5e7646d2SAndroid Build Coastguard Worker if (!strncmp(ppd->attrs[j]->name, "Default", 7) &&
1445*5e7646d2SAndroid Build Coastguard Worker !strcmp(ppd->attrs[j]->name + 7, name) &&
1446*5e7646d2SAndroid Build Coastguard Worker ppd->attrs[j]->value)
1447*5e7646d2SAndroid Build Coastguard Worker {
1448*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("2_ppdOpen: Setting Default%s to %s via attribute...",
1449*5e7646d2SAndroid Build Coastguard Worker option->keyword, ppd->attrs[j]->value));
1450*5e7646d2SAndroid Build Coastguard Worker strlcpy(option->defchoice, ppd->attrs[j]->value,
1451*5e7646d2SAndroid Build Coastguard Worker sizeof(option->defchoice));
1452*5e7646d2SAndroid Build Coastguard Worker break;
1453*5e7646d2SAndroid Build Coastguard Worker }
1454*5e7646d2SAndroid Build Coastguard Worker
1455*5e7646d2SAndroid Build Coastguard Worker if (text[0])
1456*5e7646d2SAndroid Build Coastguard Worker cupsCharsetToUTF8((cups_utf8_t *)option->text, text,
1457*5e7646d2SAndroid Build Coastguard Worker sizeof(option->text), encoding);
1458*5e7646d2SAndroid Build Coastguard Worker else
1459*5e7646d2SAndroid Build Coastguard Worker strlcpy(option->text, name, sizeof(option->text));
1460*5e7646d2SAndroid Build Coastguard Worker
1461*5e7646d2SAndroid Build Coastguard Worker option->section = PPD_ORDER_JCL;
1462*5e7646d2SAndroid Build Coastguard Worker group = NULL;
1463*5e7646d2SAndroid Build Coastguard Worker
1464*5e7646d2SAndroid Build Coastguard Worker free(string);
1465*5e7646d2SAndroid Build Coastguard Worker string = NULL;
1466*5e7646d2SAndroid Build Coastguard Worker
1467*5e7646d2SAndroid Build Coastguard Worker /*
1468*5e7646d2SAndroid Build Coastguard Worker * Add a custom option choice if we have already seen a CustomFoo
1469*5e7646d2SAndroid Build Coastguard Worker * attribute...
1470*5e7646d2SAndroid Build Coastguard Worker */
1471*5e7646d2SAndroid Build Coastguard Worker
1472*5e7646d2SAndroid Build Coastguard Worker snprintf(custom_name, sizeof(custom_name), "Custom%s", name);
1473*5e7646d2SAndroid Build Coastguard Worker
1474*5e7646d2SAndroid Build Coastguard Worker if ((custom_attr = ppdFindAttr(ppd, custom_name, "True")) != NULL)
1475*5e7646d2SAndroid Build Coastguard Worker {
1476*5e7646d2SAndroid Build Coastguard Worker if ((choice = ppd_add_choice(option, "Custom")) == NULL)
1477*5e7646d2SAndroid Build Coastguard Worker {
1478*5e7646d2SAndroid Build Coastguard Worker DEBUG_puts("1_ppdOpen: Unable to add Custom choice!");
1479*5e7646d2SAndroid Build Coastguard Worker
1480*5e7646d2SAndroid Build Coastguard Worker pg->ppd_status = PPD_ALLOC_ERROR;
1481*5e7646d2SAndroid Build Coastguard Worker
1482*5e7646d2SAndroid Build Coastguard Worker goto error;
1483*5e7646d2SAndroid Build Coastguard Worker }
1484*5e7646d2SAndroid Build Coastguard Worker
1485*5e7646d2SAndroid Build Coastguard Worker strlcpy(choice->text,
1486*5e7646d2SAndroid Build Coastguard Worker custom_attr->text[0] ? custom_attr->text : _("Custom"),
1487*5e7646d2SAndroid Build Coastguard Worker sizeof(choice->text));
1488*5e7646d2SAndroid Build Coastguard Worker choice->code = strdup(custom_attr->value);
1489*5e7646d2SAndroid Build Coastguard Worker }
1490*5e7646d2SAndroid Build Coastguard Worker }
1491*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(keyword, "CloseUI"))
1492*5e7646d2SAndroid Build Coastguard Worker {
1493*5e7646d2SAndroid Build Coastguard Worker if ((!option || option->section == PPD_ORDER_JCL) && pg->ppd_conform == PPD_CONFORM_STRICT)
1494*5e7646d2SAndroid Build Coastguard Worker {
1495*5e7646d2SAndroid Build Coastguard Worker pg->ppd_status = PPD_BAD_CLOSE_UI;
1496*5e7646d2SAndroid Build Coastguard Worker
1497*5e7646d2SAndroid Build Coastguard Worker goto error;
1498*5e7646d2SAndroid Build Coastguard Worker }
1499*5e7646d2SAndroid Build Coastguard Worker
1500*5e7646d2SAndroid Build Coastguard Worker if (option && (!_cups_strcasecmp(option->defchoice, "custom") || !_cups_strncasecmp(option->defchoice, "custom.", 7)))
1501*5e7646d2SAndroid Build Coastguard Worker {
1502*5e7646d2SAndroid Build Coastguard Worker /*
1503*5e7646d2SAndroid Build Coastguard Worker * "*DefaultOption: Custom..." may set the default to a custom value
1504*5e7646d2SAndroid Build Coastguard Worker * or (for a very small number of incompatible PPD files) select a
1505*5e7646d2SAndroid Build Coastguard Worker * standard choice for the option, which CUPS renames to "_Custom..."
1506*5e7646d2SAndroid Build Coastguard Worker * to avoid compatibility issues. See which this is...
1507*5e7646d2SAndroid Build Coastguard Worker */
1508*5e7646d2SAndroid Build Coastguard Worker
1509*5e7646d2SAndroid Build Coastguard Worker char tchoice[PPD_MAX_NAME]; /* Temporary choice name */
1510*5e7646d2SAndroid Build Coastguard Worker
1511*5e7646d2SAndroid Build Coastguard Worker snprintf(tchoice, sizeof(tchoice), "_%s", option->defchoice);
1512*5e7646d2SAndroid Build Coastguard Worker
1513*5e7646d2SAndroid Build Coastguard Worker if (ppdFindChoice(option, tchoice))
1514*5e7646d2SAndroid Build Coastguard Worker {
1515*5e7646d2SAndroid Build Coastguard Worker strlcpy(option->defchoice, tchoice, sizeof(option->defchoice));
1516*5e7646d2SAndroid Build Coastguard Worker
1517*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("2_ppdOpen: Reset Default%s to %s...", option->keyword, tchoice));
1518*5e7646d2SAndroid Build Coastguard Worker }
1519*5e7646d2SAndroid Build Coastguard Worker }
1520*5e7646d2SAndroid Build Coastguard Worker
1521*5e7646d2SAndroid Build Coastguard Worker option = NULL;
1522*5e7646d2SAndroid Build Coastguard Worker
1523*5e7646d2SAndroid Build Coastguard Worker free(string);
1524*5e7646d2SAndroid Build Coastguard Worker string = NULL;
1525*5e7646d2SAndroid Build Coastguard Worker }
1526*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(keyword, "JCLCloseUI"))
1527*5e7646d2SAndroid Build Coastguard Worker {
1528*5e7646d2SAndroid Build Coastguard Worker if ((!option || option->section != PPD_ORDER_JCL) && pg->ppd_conform == PPD_CONFORM_STRICT)
1529*5e7646d2SAndroid Build Coastguard Worker {
1530*5e7646d2SAndroid Build Coastguard Worker pg->ppd_status = PPD_BAD_CLOSE_UI;
1531*5e7646d2SAndroid Build Coastguard Worker
1532*5e7646d2SAndroid Build Coastguard Worker goto error;
1533*5e7646d2SAndroid Build Coastguard Worker }
1534*5e7646d2SAndroid Build Coastguard Worker
1535*5e7646d2SAndroid Build Coastguard Worker if (option && (!_cups_strcasecmp(option->defchoice, "custom") || !_cups_strncasecmp(option->defchoice, "custom.", 7)))
1536*5e7646d2SAndroid Build Coastguard Worker {
1537*5e7646d2SAndroid Build Coastguard Worker /*
1538*5e7646d2SAndroid Build Coastguard Worker * "*DefaultOption: Custom..." may set the default to a custom value
1539*5e7646d2SAndroid Build Coastguard Worker * or (for a very small number of incompatible PPD files) select a
1540*5e7646d2SAndroid Build Coastguard Worker * standard choice for the option, which CUPS renames to "_Custom..."
1541*5e7646d2SAndroid Build Coastguard Worker * to avoid compatibility issues. See which this is...
1542*5e7646d2SAndroid Build Coastguard Worker */
1543*5e7646d2SAndroid Build Coastguard Worker
1544*5e7646d2SAndroid Build Coastguard Worker char tchoice[PPD_MAX_NAME]; /* Temporary choice name */
1545*5e7646d2SAndroid Build Coastguard Worker
1546*5e7646d2SAndroid Build Coastguard Worker snprintf(tchoice, sizeof(tchoice), "_%s", option->defchoice);
1547*5e7646d2SAndroid Build Coastguard Worker
1548*5e7646d2SAndroid Build Coastguard Worker if (ppdFindChoice(option, tchoice))
1549*5e7646d2SAndroid Build Coastguard Worker {
1550*5e7646d2SAndroid Build Coastguard Worker strlcpy(option->defchoice, tchoice, sizeof(option->defchoice));
1551*5e7646d2SAndroid Build Coastguard Worker
1552*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("2_ppdOpen: Reset Default%s to %s...", option->keyword, tchoice));
1553*5e7646d2SAndroid Build Coastguard Worker }
1554*5e7646d2SAndroid Build Coastguard Worker }
1555*5e7646d2SAndroid Build Coastguard Worker
1556*5e7646d2SAndroid Build Coastguard Worker option = NULL;
1557*5e7646d2SAndroid Build Coastguard Worker
1558*5e7646d2SAndroid Build Coastguard Worker free(string);
1559*5e7646d2SAndroid Build Coastguard Worker string = NULL;
1560*5e7646d2SAndroid Build Coastguard Worker }
1561*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(keyword, "OpenGroup"))
1562*5e7646d2SAndroid Build Coastguard Worker {
1563*5e7646d2SAndroid Build Coastguard Worker /*
1564*5e7646d2SAndroid Build Coastguard Worker * Open a new group...
1565*5e7646d2SAndroid Build Coastguard Worker */
1566*5e7646d2SAndroid Build Coastguard Worker
1567*5e7646d2SAndroid Build Coastguard Worker if (group != NULL)
1568*5e7646d2SAndroid Build Coastguard Worker {
1569*5e7646d2SAndroid Build Coastguard Worker pg->ppd_status = PPD_NESTED_OPEN_GROUP;
1570*5e7646d2SAndroid Build Coastguard Worker
1571*5e7646d2SAndroid Build Coastguard Worker goto error;
1572*5e7646d2SAndroid Build Coastguard Worker }
1573*5e7646d2SAndroid Build Coastguard Worker
1574*5e7646d2SAndroid Build Coastguard Worker if (!string)
1575*5e7646d2SAndroid Build Coastguard Worker {
1576*5e7646d2SAndroid Build Coastguard Worker pg->ppd_status = PPD_BAD_OPEN_GROUP;
1577*5e7646d2SAndroid Build Coastguard Worker
1578*5e7646d2SAndroid Build Coastguard Worker goto error;
1579*5e7646d2SAndroid Build Coastguard Worker }
1580*5e7646d2SAndroid Build Coastguard Worker
1581*5e7646d2SAndroid Build Coastguard Worker /*
1582*5e7646d2SAndroid Build Coastguard Worker * Separate the group name from the text (name/text)...
1583*5e7646d2SAndroid Build Coastguard Worker */
1584*5e7646d2SAndroid Build Coastguard Worker
1585*5e7646d2SAndroid Build Coastguard Worker if ((sptr = strchr(string, '/')) != NULL)
1586*5e7646d2SAndroid Build Coastguard Worker *sptr++ = '\0';
1587*5e7646d2SAndroid Build Coastguard Worker else
1588*5e7646d2SAndroid Build Coastguard Worker sptr = string;
1589*5e7646d2SAndroid Build Coastguard Worker
1590*5e7646d2SAndroid Build Coastguard Worker /*
1591*5e7646d2SAndroid Build Coastguard Worker * Fix up the text...
1592*5e7646d2SAndroid Build Coastguard Worker */
1593*5e7646d2SAndroid Build Coastguard Worker
1594*5e7646d2SAndroid Build Coastguard Worker ppd_decode(sptr);
1595*5e7646d2SAndroid Build Coastguard Worker
1596*5e7646d2SAndroid Build Coastguard Worker /*
1597*5e7646d2SAndroid Build Coastguard Worker * Find/add the group...
1598*5e7646d2SAndroid Build Coastguard Worker */
1599*5e7646d2SAndroid Build Coastguard Worker
1600*5e7646d2SAndroid Build Coastguard Worker group = ppd_get_group(ppd, string, sptr, pg, encoding);
1601*5e7646d2SAndroid Build Coastguard Worker
1602*5e7646d2SAndroid Build Coastguard Worker if (group == NULL)
1603*5e7646d2SAndroid Build Coastguard Worker goto error;
1604*5e7646d2SAndroid Build Coastguard Worker
1605*5e7646d2SAndroid Build Coastguard Worker free(string);
1606*5e7646d2SAndroid Build Coastguard Worker string = NULL;
1607*5e7646d2SAndroid Build Coastguard Worker }
1608*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(keyword, "CloseGroup"))
1609*5e7646d2SAndroid Build Coastguard Worker {
1610*5e7646d2SAndroid Build Coastguard Worker group = NULL;
1611*5e7646d2SAndroid Build Coastguard Worker
1612*5e7646d2SAndroid Build Coastguard Worker free(string);
1613*5e7646d2SAndroid Build Coastguard Worker string = NULL;
1614*5e7646d2SAndroid Build Coastguard Worker }
1615*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(keyword, "OrderDependency"))
1616*5e7646d2SAndroid Build Coastguard Worker {
1617*5e7646d2SAndroid Build Coastguard Worker order = (float)_cupsStrScand(string, &sptr, loc);
1618*5e7646d2SAndroid Build Coastguard Worker
1619*5e7646d2SAndroid Build Coastguard Worker if (!sptr || sscanf(sptr, "%40s%40s", name, keyword) != 2)
1620*5e7646d2SAndroid Build Coastguard Worker {
1621*5e7646d2SAndroid Build Coastguard Worker pg->ppd_status = PPD_BAD_ORDER_DEPENDENCY;
1622*5e7646d2SAndroid Build Coastguard Worker
1623*5e7646d2SAndroid Build Coastguard Worker goto error;
1624*5e7646d2SAndroid Build Coastguard Worker }
1625*5e7646d2SAndroid Build Coastguard Worker
1626*5e7646d2SAndroid Build Coastguard Worker if (keyword[0] == '*')
1627*5e7646d2SAndroid Build Coastguard Worker _cups_strcpy(keyword, keyword + 1);
1628*5e7646d2SAndroid Build Coastguard Worker
1629*5e7646d2SAndroid Build Coastguard Worker if (!strcmp(name, "ExitServer"))
1630*5e7646d2SAndroid Build Coastguard Worker section = PPD_ORDER_EXIT;
1631*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(name, "Prolog"))
1632*5e7646d2SAndroid Build Coastguard Worker section = PPD_ORDER_PROLOG;
1633*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(name, "DocumentSetup"))
1634*5e7646d2SAndroid Build Coastguard Worker section = PPD_ORDER_DOCUMENT;
1635*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(name, "PageSetup"))
1636*5e7646d2SAndroid Build Coastguard Worker section = PPD_ORDER_PAGE;
1637*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(name, "JCLSetup"))
1638*5e7646d2SAndroid Build Coastguard Worker section = PPD_ORDER_JCL;
1639*5e7646d2SAndroid Build Coastguard Worker else
1640*5e7646d2SAndroid Build Coastguard Worker section = PPD_ORDER_ANY;
1641*5e7646d2SAndroid Build Coastguard Worker
1642*5e7646d2SAndroid Build Coastguard Worker if (option == NULL)
1643*5e7646d2SAndroid Build Coastguard Worker {
1644*5e7646d2SAndroid Build Coastguard Worker ppd_group_t *gtemp;
1645*5e7646d2SAndroid Build Coastguard Worker
1646*5e7646d2SAndroid Build Coastguard Worker
1647*5e7646d2SAndroid Build Coastguard Worker /*
1648*5e7646d2SAndroid Build Coastguard Worker * Only valid for Non-UI options...
1649*5e7646d2SAndroid Build Coastguard Worker */
1650*5e7646d2SAndroid Build Coastguard Worker
1651*5e7646d2SAndroid Build Coastguard Worker for (i = ppd->num_groups, gtemp = ppd->groups; i > 0; i --, gtemp ++)
1652*5e7646d2SAndroid Build Coastguard Worker if (gtemp->text[0] == '\0')
1653*5e7646d2SAndroid Build Coastguard Worker break;
1654*5e7646d2SAndroid Build Coastguard Worker
1655*5e7646d2SAndroid Build Coastguard Worker if (i > 0)
1656*5e7646d2SAndroid Build Coastguard Worker for (i = 0; i < gtemp->num_options; i ++)
1657*5e7646d2SAndroid Build Coastguard Worker if (!strcmp(keyword, gtemp->options[i].keyword))
1658*5e7646d2SAndroid Build Coastguard Worker {
1659*5e7646d2SAndroid Build Coastguard Worker gtemp->options[i].section = section;
1660*5e7646d2SAndroid Build Coastguard Worker gtemp->options[i].order = order;
1661*5e7646d2SAndroid Build Coastguard Worker break;
1662*5e7646d2SAndroid Build Coastguard Worker }
1663*5e7646d2SAndroid Build Coastguard Worker }
1664*5e7646d2SAndroid Build Coastguard Worker else
1665*5e7646d2SAndroid Build Coastguard Worker {
1666*5e7646d2SAndroid Build Coastguard Worker option->section = section;
1667*5e7646d2SAndroid Build Coastguard Worker option->order = order;
1668*5e7646d2SAndroid Build Coastguard Worker }
1669*5e7646d2SAndroid Build Coastguard Worker
1670*5e7646d2SAndroid Build Coastguard Worker free(string);
1671*5e7646d2SAndroid Build Coastguard Worker string = NULL;
1672*5e7646d2SAndroid Build Coastguard Worker }
1673*5e7646d2SAndroid Build Coastguard Worker else if (!strncmp(keyword, "Default", 7))
1674*5e7646d2SAndroid Build Coastguard Worker {
1675*5e7646d2SAndroid Build Coastguard Worker if (string == NULL)
1676*5e7646d2SAndroid Build Coastguard Worker continue;
1677*5e7646d2SAndroid Build Coastguard Worker
1678*5e7646d2SAndroid Build Coastguard Worker /*
1679*5e7646d2SAndroid Build Coastguard Worker * Drop UI text, if any, from value...
1680*5e7646d2SAndroid Build Coastguard Worker */
1681*5e7646d2SAndroid Build Coastguard Worker
1682*5e7646d2SAndroid Build Coastguard Worker if (strchr(string, '/') != NULL)
1683*5e7646d2SAndroid Build Coastguard Worker *strchr(string, '/') = '\0';
1684*5e7646d2SAndroid Build Coastguard Worker
1685*5e7646d2SAndroid Build Coastguard Worker /*
1686*5e7646d2SAndroid Build Coastguard Worker * Assign the default value as appropriate...
1687*5e7646d2SAndroid Build Coastguard Worker */
1688*5e7646d2SAndroid Build Coastguard Worker
1689*5e7646d2SAndroid Build Coastguard Worker if (!strcmp(keyword, "DefaultColorSpace"))
1690*5e7646d2SAndroid Build Coastguard Worker {
1691*5e7646d2SAndroid Build Coastguard Worker /*
1692*5e7646d2SAndroid Build Coastguard Worker * Set default colorspace...
1693*5e7646d2SAndroid Build Coastguard Worker */
1694*5e7646d2SAndroid Build Coastguard Worker
1695*5e7646d2SAndroid Build Coastguard Worker if (!strcmp(string, "CMY"))
1696*5e7646d2SAndroid Build Coastguard Worker ppd->colorspace = PPD_CS_CMY;
1697*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(string, "CMYK"))
1698*5e7646d2SAndroid Build Coastguard Worker ppd->colorspace = PPD_CS_CMYK;
1699*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(string, "RGB"))
1700*5e7646d2SAndroid Build Coastguard Worker ppd->colorspace = PPD_CS_RGB;
1701*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(string, "RGBK"))
1702*5e7646d2SAndroid Build Coastguard Worker ppd->colorspace = PPD_CS_RGBK;
1703*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(string, "N"))
1704*5e7646d2SAndroid Build Coastguard Worker ppd->colorspace = PPD_CS_N;
1705*5e7646d2SAndroid Build Coastguard Worker else
1706*5e7646d2SAndroid Build Coastguard Worker ppd->colorspace = PPD_CS_GRAY;
1707*5e7646d2SAndroid Build Coastguard Worker }
1708*5e7646d2SAndroid Build Coastguard Worker else if (option && !strcmp(keyword + 7, option->keyword))
1709*5e7646d2SAndroid Build Coastguard Worker {
1710*5e7646d2SAndroid Build Coastguard Worker /*
1711*5e7646d2SAndroid Build Coastguard Worker * Set the default as part of the current option...
1712*5e7646d2SAndroid Build Coastguard Worker */
1713*5e7646d2SAndroid Build Coastguard Worker
1714*5e7646d2SAndroid Build Coastguard Worker strlcpy(option->defchoice, string, sizeof(option->defchoice));
1715*5e7646d2SAndroid Build Coastguard Worker
1716*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("2_ppdOpen: Set %s to %s...", keyword, option->defchoice));
1717*5e7646d2SAndroid Build Coastguard Worker }
1718*5e7646d2SAndroid Build Coastguard Worker else
1719*5e7646d2SAndroid Build Coastguard Worker {
1720*5e7646d2SAndroid Build Coastguard Worker /*
1721*5e7646d2SAndroid Build Coastguard Worker * Lookup option and set if it has been defined...
1722*5e7646d2SAndroid Build Coastguard Worker */
1723*5e7646d2SAndroid Build Coastguard Worker
1724*5e7646d2SAndroid Build Coastguard Worker ppd_option_t *toption; /* Temporary option */
1725*5e7646d2SAndroid Build Coastguard Worker
1726*5e7646d2SAndroid Build Coastguard Worker if ((toption = ppdFindOption(ppd, keyword + 7)) != NULL)
1727*5e7646d2SAndroid Build Coastguard Worker {
1728*5e7646d2SAndroid Build Coastguard Worker if (!_cups_strcasecmp(string, "custom") || !_cups_strncasecmp(string, "custom.", 7))
1729*5e7646d2SAndroid Build Coastguard Worker {
1730*5e7646d2SAndroid Build Coastguard Worker /*
1731*5e7646d2SAndroid Build Coastguard Worker * "*DefaultOption: Custom..." may set the default to a custom value
1732*5e7646d2SAndroid Build Coastguard Worker * or (for a very small number of incompatible PPD files) select a
1733*5e7646d2SAndroid Build Coastguard Worker * standard choice for the option, which CUPS renames to "_Custom..."
1734*5e7646d2SAndroid Build Coastguard Worker * to avoid compatibility issues. See which this is...
1735*5e7646d2SAndroid Build Coastguard Worker */
1736*5e7646d2SAndroid Build Coastguard Worker
1737*5e7646d2SAndroid Build Coastguard Worker snprintf(toption->defchoice, sizeof(toption->defchoice), "_%s", string);
1738*5e7646d2SAndroid Build Coastguard Worker if (!ppdFindChoice(toption, toption->defchoice))
1739*5e7646d2SAndroid Build Coastguard Worker strlcpy(toption->defchoice, string, sizeof(toption->defchoice));
1740*5e7646d2SAndroid Build Coastguard Worker }
1741*5e7646d2SAndroid Build Coastguard Worker else
1742*5e7646d2SAndroid Build Coastguard Worker {
1743*5e7646d2SAndroid Build Coastguard Worker strlcpy(toption->defchoice, string, sizeof(toption->defchoice));
1744*5e7646d2SAndroid Build Coastguard Worker }
1745*5e7646d2SAndroid Build Coastguard Worker
1746*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("2_ppdOpen: Set %s to %s...", keyword, toption->defchoice));
1747*5e7646d2SAndroid Build Coastguard Worker }
1748*5e7646d2SAndroid Build Coastguard Worker }
1749*5e7646d2SAndroid Build Coastguard Worker }
1750*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(keyword, "UIConstraints") ||
1751*5e7646d2SAndroid Build Coastguard Worker !strcmp(keyword, "NonUIConstraints"))
1752*5e7646d2SAndroid Build Coastguard Worker {
1753*5e7646d2SAndroid Build Coastguard Worker if (!string)
1754*5e7646d2SAndroid Build Coastguard Worker {
1755*5e7646d2SAndroid Build Coastguard Worker pg->ppd_status = PPD_BAD_UI_CONSTRAINTS;
1756*5e7646d2SAndroid Build Coastguard Worker goto error;
1757*5e7646d2SAndroid Build Coastguard Worker }
1758*5e7646d2SAndroid Build Coastguard Worker
1759*5e7646d2SAndroid Build Coastguard Worker if (ppd->num_consts == 0)
1760*5e7646d2SAndroid Build Coastguard Worker constraint = calloc(2, sizeof(ppd_const_t));
1761*5e7646d2SAndroid Build Coastguard Worker else
1762*5e7646d2SAndroid Build Coastguard Worker constraint = realloc(ppd->consts, (size_t)(ppd->num_consts + 2) * sizeof(ppd_const_t));
1763*5e7646d2SAndroid Build Coastguard Worker
1764*5e7646d2SAndroid Build Coastguard Worker if (constraint == NULL)
1765*5e7646d2SAndroid Build Coastguard Worker {
1766*5e7646d2SAndroid Build Coastguard Worker pg->ppd_status = PPD_ALLOC_ERROR;
1767*5e7646d2SAndroid Build Coastguard Worker
1768*5e7646d2SAndroid Build Coastguard Worker goto error;
1769*5e7646d2SAndroid Build Coastguard Worker }
1770*5e7646d2SAndroid Build Coastguard Worker
1771*5e7646d2SAndroid Build Coastguard Worker ppd->consts = constraint;
1772*5e7646d2SAndroid Build Coastguard Worker constraint += ppd->num_consts;
1773*5e7646d2SAndroid Build Coastguard Worker ppd->num_consts ++;
1774*5e7646d2SAndroid Build Coastguard Worker
1775*5e7646d2SAndroid Build Coastguard Worker switch (sscanf(string, "%40s%40s%40s%40s", constraint->option1,
1776*5e7646d2SAndroid Build Coastguard Worker constraint->choice1, constraint->option2,
1777*5e7646d2SAndroid Build Coastguard Worker constraint->choice2))
1778*5e7646d2SAndroid Build Coastguard Worker {
1779*5e7646d2SAndroid Build Coastguard Worker default : /* Error */
1780*5e7646d2SAndroid Build Coastguard Worker pg->ppd_status = PPD_BAD_UI_CONSTRAINTS;
1781*5e7646d2SAndroid Build Coastguard Worker goto error;
1782*5e7646d2SAndroid Build Coastguard Worker
1783*5e7646d2SAndroid Build Coastguard Worker case 2 : /* Two options... */
1784*5e7646d2SAndroid Build Coastguard Worker /*
1785*5e7646d2SAndroid Build Coastguard Worker * Check for broken constraints like "* Option"...
1786*5e7646d2SAndroid Build Coastguard Worker */
1787*5e7646d2SAndroid Build Coastguard Worker
1788*5e7646d2SAndroid Build Coastguard Worker if (pg->ppd_conform == PPD_CONFORM_STRICT &&
1789*5e7646d2SAndroid Build Coastguard Worker (!strcmp(constraint->option1, "*") ||
1790*5e7646d2SAndroid Build Coastguard Worker !strcmp(constraint->choice1, "*")))
1791*5e7646d2SAndroid Build Coastguard Worker {
1792*5e7646d2SAndroid Build Coastguard Worker pg->ppd_status = PPD_BAD_UI_CONSTRAINTS;
1793*5e7646d2SAndroid Build Coastguard Worker goto error;
1794*5e7646d2SAndroid Build Coastguard Worker }
1795*5e7646d2SAndroid Build Coastguard Worker
1796*5e7646d2SAndroid Build Coastguard Worker /*
1797*5e7646d2SAndroid Build Coastguard Worker * The following strcpy's are safe, as optionN and
1798*5e7646d2SAndroid Build Coastguard Worker * choiceN are all the same size (size defined by PPD spec...)
1799*5e7646d2SAndroid Build Coastguard Worker */
1800*5e7646d2SAndroid Build Coastguard Worker
1801*5e7646d2SAndroid Build Coastguard Worker if (constraint->option1[0] == '*')
1802*5e7646d2SAndroid Build Coastguard Worker _cups_strcpy(constraint->option1, constraint->option1 + 1);
1803*5e7646d2SAndroid Build Coastguard Worker else if (pg->ppd_conform == PPD_CONFORM_STRICT)
1804*5e7646d2SAndroid Build Coastguard Worker {
1805*5e7646d2SAndroid Build Coastguard Worker pg->ppd_status = PPD_BAD_UI_CONSTRAINTS;
1806*5e7646d2SAndroid Build Coastguard Worker goto error;
1807*5e7646d2SAndroid Build Coastguard Worker }
1808*5e7646d2SAndroid Build Coastguard Worker
1809*5e7646d2SAndroid Build Coastguard Worker if (constraint->choice1[0] == '*')
1810*5e7646d2SAndroid Build Coastguard Worker _cups_strcpy(constraint->option2, constraint->choice1 + 1);
1811*5e7646d2SAndroid Build Coastguard Worker else if (pg->ppd_conform == PPD_CONFORM_STRICT)
1812*5e7646d2SAndroid Build Coastguard Worker {
1813*5e7646d2SAndroid Build Coastguard Worker pg->ppd_status = PPD_BAD_UI_CONSTRAINTS;
1814*5e7646d2SAndroid Build Coastguard Worker goto error;
1815*5e7646d2SAndroid Build Coastguard Worker }
1816*5e7646d2SAndroid Build Coastguard Worker
1817*5e7646d2SAndroid Build Coastguard Worker constraint->choice1[0] = '\0';
1818*5e7646d2SAndroid Build Coastguard Worker constraint->choice2[0] = '\0';
1819*5e7646d2SAndroid Build Coastguard Worker break;
1820*5e7646d2SAndroid Build Coastguard Worker
1821*5e7646d2SAndroid Build Coastguard Worker case 3 : /* Two options, one choice... */
1822*5e7646d2SAndroid Build Coastguard Worker /*
1823*5e7646d2SAndroid Build Coastguard Worker * Check for broken constraints like "* Option"...
1824*5e7646d2SAndroid Build Coastguard Worker */
1825*5e7646d2SAndroid Build Coastguard Worker
1826*5e7646d2SAndroid Build Coastguard Worker if (pg->ppd_conform == PPD_CONFORM_STRICT &&
1827*5e7646d2SAndroid Build Coastguard Worker (!strcmp(constraint->option1, "*") ||
1828*5e7646d2SAndroid Build Coastguard Worker !strcmp(constraint->choice1, "*") ||
1829*5e7646d2SAndroid Build Coastguard Worker !strcmp(constraint->option2, "*")))
1830*5e7646d2SAndroid Build Coastguard Worker {
1831*5e7646d2SAndroid Build Coastguard Worker pg->ppd_status = PPD_BAD_UI_CONSTRAINTS;
1832*5e7646d2SAndroid Build Coastguard Worker goto error;
1833*5e7646d2SAndroid Build Coastguard Worker }
1834*5e7646d2SAndroid Build Coastguard Worker
1835*5e7646d2SAndroid Build Coastguard Worker /*
1836*5e7646d2SAndroid Build Coastguard Worker * The following _cups_strcpy's are safe, as optionN and
1837*5e7646d2SAndroid Build Coastguard Worker * choiceN are all the same size (size defined by PPD spec...)
1838*5e7646d2SAndroid Build Coastguard Worker */
1839*5e7646d2SAndroid Build Coastguard Worker
1840*5e7646d2SAndroid Build Coastguard Worker if (constraint->option1[0] == '*')
1841*5e7646d2SAndroid Build Coastguard Worker _cups_strcpy(constraint->option1, constraint->option1 + 1);
1842*5e7646d2SAndroid Build Coastguard Worker else if (pg->ppd_conform == PPD_CONFORM_STRICT)
1843*5e7646d2SAndroid Build Coastguard Worker {
1844*5e7646d2SAndroid Build Coastguard Worker pg->ppd_status = PPD_BAD_UI_CONSTRAINTS;
1845*5e7646d2SAndroid Build Coastguard Worker goto error;
1846*5e7646d2SAndroid Build Coastguard Worker }
1847*5e7646d2SAndroid Build Coastguard Worker
1848*5e7646d2SAndroid Build Coastguard Worker if (constraint->choice1[0] == '*')
1849*5e7646d2SAndroid Build Coastguard Worker {
1850*5e7646d2SAndroid Build Coastguard Worker if (pg->ppd_conform == PPD_CONFORM_STRICT &&
1851*5e7646d2SAndroid Build Coastguard Worker constraint->option2[0] == '*')
1852*5e7646d2SAndroid Build Coastguard Worker {
1853*5e7646d2SAndroid Build Coastguard Worker pg->ppd_status = PPD_BAD_UI_CONSTRAINTS;
1854*5e7646d2SAndroid Build Coastguard Worker goto error;
1855*5e7646d2SAndroid Build Coastguard Worker }
1856*5e7646d2SAndroid Build Coastguard Worker
1857*5e7646d2SAndroid Build Coastguard Worker _cups_strcpy(constraint->choice2, constraint->option2);
1858*5e7646d2SAndroid Build Coastguard Worker _cups_strcpy(constraint->option2, constraint->choice1 + 1);
1859*5e7646d2SAndroid Build Coastguard Worker constraint->choice1[0] = '\0';
1860*5e7646d2SAndroid Build Coastguard Worker }
1861*5e7646d2SAndroid Build Coastguard Worker else
1862*5e7646d2SAndroid Build Coastguard Worker {
1863*5e7646d2SAndroid Build Coastguard Worker if (constraint->option2[0] == '*')
1864*5e7646d2SAndroid Build Coastguard Worker _cups_strcpy(constraint->option2, constraint->option2 + 1);
1865*5e7646d2SAndroid Build Coastguard Worker else if (pg->ppd_conform == PPD_CONFORM_STRICT)
1866*5e7646d2SAndroid Build Coastguard Worker {
1867*5e7646d2SAndroid Build Coastguard Worker pg->ppd_status = PPD_BAD_UI_CONSTRAINTS;
1868*5e7646d2SAndroid Build Coastguard Worker goto error;
1869*5e7646d2SAndroid Build Coastguard Worker }
1870*5e7646d2SAndroid Build Coastguard Worker
1871*5e7646d2SAndroid Build Coastguard Worker constraint->choice2[0] = '\0';
1872*5e7646d2SAndroid Build Coastguard Worker }
1873*5e7646d2SAndroid Build Coastguard Worker break;
1874*5e7646d2SAndroid Build Coastguard Worker
1875*5e7646d2SAndroid Build Coastguard Worker case 4 : /* Two options, two choices... */
1876*5e7646d2SAndroid Build Coastguard Worker /*
1877*5e7646d2SAndroid Build Coastguard Worker * Check for broken constraints like "* Option"...
1878*5e7646d2SAndroid Build Coastguard Worker */
1879*5e7646d2SAndroid Build Coastguard Worker
1880*5e7646d2SAndroid Build Coastguard Worker if (pg->ppd_conform == PPD_CONFORM_STRICT &&
1881*5e7646d2SAndroid Build Coastguard Worker (!strcmp(constraint->option1, "*") ||
1882*5e7646d2SAndroid Build Coastguard Worker !strcmp(constraint->choice1, "*") ||
1883*5e7646d2SAndroid Build Coastguard Worker !strcmp(constraint->option2, "*") ||
1884*5e7646d2SAndroid Build Coastguard Worker !strcmp(constraint->choice2, "*")))
1885*5e7646d2SAndroid Build Coastguard Worker {
1886*5e7646d2SAndroid Build Coastguard Worker pg->ppd_status = PPD_BAD_UI_CONSTRAINTS;
1887*5e7646d2SAndroid Build Coastguard Worker goto error;
1888*5e7646d2SAndroid Build Coastguard Worker }
1889*5e7646d2SAndroid Build Coastguard Worker
1890*5e7646d2SAndroid Build Coastguard Worker if (constraint->option1[0] == '*')
1891*5e7646d2SAndroid Build Coastguard Worker _cups_strcpy(constraint->option1, constraint->option1 + 1);
1892*5e7646d2SAndroid Build Coastguard Worker else if (pg->ppd_conform == PPD_CONFORM_STRICT)
1893*5e7646d2SAndroid Build Coastguard Worker {
1894*5e7646d2SAndroid Build Coastguard Worker pg->ppd_status = PPD_BAD_UI_CONSTRAINTS;
1895*5e7646d2SAndroid Build Coastguard Worker goto error;
1896*5e7646d2SAndroid Build Coastguard Worker }
1897*5e7646d2SAndroid Build Coastguard Worker
1898*5e7646d2SAndroid Build Coastguard Worker if (pg->ppd_conform == PPD_CONFORM_STRICT &&
1899*5e7646d2SAndroid Build Coastguard Worker constraint->choice1[0] == '*')
1900*5e7646d2SAndroid Build Coastguard Worker {
1901*5e7646d2SAndroid Build Coastguard Worker pg->ppd_status = PPD_BAD_UI_CONSTRAINTS;
1902*5e7646d2SAndroid Build Coastguard Worker goto error;
1903*5e7646d2SAndroid Build Coastguard Worker }
1904*5e7646d2SAndroid Build Coastguard Worker
1905*5e7646d2SAndroid Build Coastguard Worker if (constraint->option2[0] == '*')
1906*5e7646d2SAndroid Build Coastguard Worker _cups_strcpy(constraint->option2, constraint->option2 + 1);
1907*5e7646d2SAndroid Build Coastguard Worker else if (pg->ppd_conform == PPD_CONFORM_STRICT)
1908*5e7646d2SAndroid Build Coastguard Worker {
1909*5e7646d2SAndroid Build Coastguard Worker pg->ppd_status = PPD_BAD_UI_CONSTRAINTS;
1910*5e7646d2SAndroid Build Coastguard Worker goto error;
1911*5e7646d2SAndroid Build Coastguard Worker }
1912*5e7646d2SAndroid Build Coastguard Worker
1913*5e7646d2SAndroid Build Coastguard Worker if (pg->ppd_conform == PPD_CONFORM_STRICT &&
1914*5e7646d2SAndroid Build Coastguard Worker constraint->choice2[0] == '*')
1915*5e7646d2SAndroid Build Coastguard Worker {
1916*5e7646d2SAndroid Build Coastguard Worker pg->ppd_status = PPD_BAD_UI_CONSTRAINTS;
1917*5e7646d2SAndroid Build Coastguard Worker goto error;
1918*5e7646d2SAndroid Build Coastguard Worker }
1919*5e7646d2SAndroid Build Coastguard Worker break;
1920*5e7646d2SAndroid Build Coastguard Worker }
1921*5e7646d2SAndroid Build Coastguard Worker
1922*5e7646d2SAndroid Build Coastguard Worker /*
1923*5e7646d2SAndroid Build Coastguard Worker * Don't add this one as an attribute...
1924*5e7646d2SAndroid Build Coastguard Worker */
1925*5e7646d2SAndroid Build Coastguard Worker
1926*5e7646d2SAndroid Build Coastguard Worker free(string);
1927*5e7646d2SAndroid Build Coastguard Worker string = NULL;
1928*5e7646d2SAndroid Build Coastguard Worker }
1929*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(keyword, "PaperDimension"))
1930*5e7646d2SAndroid Build Coastguard Worker {
1931*5e7646d2SAndroid Build Coastguard Worker if (!_cups_strcasecmp(name, "custom") || !_cups_strncasecmp(name, "custom.", 7))
1932*5e7646d2SAndroid Build Coastguard Worker {
1933*5e7646d2SAndroid Build Coastguard Worker char cname[PPD_MAX_NAME]; /* Rewrite with a leading underscore */
1934*5e7646d2SAndroid Build Coastguard Worker snprintf(cname, sizeof(cname), "_%s", name);
1935*5e7646d2SAndroid Build Coastguard Worker strlcpy(name, cname, sizeof(name));
1936*5e7646d2SAndroid Build Coastguard Worker }
1937*5e7646d2SAndroid Build Coastguard Worker
1938*5e7646d2SAndroid Build Coastguard Worker if ((size = ppdPageSize(ppd, name)) == NULL)
1939*5e7646d2SAndroid Build Coastguard Worker size = ppd_add_size(ppd, name);
1940*5e7646d2SAndroid Build Coastguard Worker
1941*5e7646d2SAndroid Build Coastguard Worker if (size == NULL)
1942*5e7646d2SAndroid Build Coastguard Worker {
1943*5e7646d2SAndroid Build Coastguard Worker /*
1944*5e7646d2SAndroid Build Coastguard Worker * Unable to add or find size!
1945*5e7646d2SAndroid Build Coastguard Worker */
1946*5e7646d2SAndroid Build Coastguard Worker
1947*5e7646d2SAndroid Build Coastguard Worker pg->ppd_status = PPD_ALLOC_ERROR;
1948*5e7646d2SAndroid Build Coastguard Worker
1949*5e7646d2SAndroid Build Coastguard Worker goto error;
1950*5e7646d2SAndroid Build Coastguard Worker }
1951*5e7646d2SAndroid Build Coastguard Worker
1952*5e7646d2SAndroid Build Coastguard Worker size->width = (float)_cupsStrScand(string, &sptr, loc);
1953*5e7646d2SAndroid Build Coastguard Worker size->length = (float)_cupsStrScand(sptr, NULL, loc);
1954*5e7646d2SAndroid Build Coastguard Worker
1955*5e7646d2SAndroid Build Coastguard Worker free(string);
1956*5e7646d2SAndroid Build Coastguard Worker string = NULL;
1957*5e7646d2SAndroid Build Coastguard Worker }
1958*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(keyword, "ImageableArea"))
1959*5e7646d2SAndroid Build Coastguard Worker {
1960*5e7646d2SAndroid Build Coastguard Worker if (!_cups_strcasecmp(name, "custom") || !_cups_strncasecmp(name, "custom.", 7))
1961*5e7646d2SAndroid Build Coastguard Worker {
1962*5e7646d2SAndroid Build Coastguard Worker char cname[PPD_MAX_NAME]; /* Rewrite with a leading underscore */
1963*5e7646d2SAndroid Build Coastguard Worker snprintf(cname, sizeof(cname), "_%s", name);
1964*5e7646d2SAndroid Build Coastguard Worker strlcpy(name, cname, sizeof(name));
1965*5e7646d2SAndroid Build Coastguard Worker }
1966*5e7646d2SAndroid Build Coastguard Worker
1967*5e7646d2SAndroid Build Coastguard Worker if ((size = ppdPageSize(ppd, name)) == NULL)
1968*5e7646d2SAndroid Build Coastguard Worker size = ppd_add_size(ppd, name);
1969*5e7646d2SAndroid Build Coastguard Worker
1970*5e7646d2SAndroid Build Coastguard Worker if (size == NULL)
1971*5e7646d2SAndroid Build Coastguard Worker {
1972*5e7646d2SAndroid Build Coastguard Worker /*
1973*5e7646d2SAndroid Build Coastguard Worker * Unable to add or find size!
1974*5e7646d2SAndroid Build Coastguard Worker */
1975*5e7646d2SAndroid Build Coastguard Worker
1976*5e7646d2SAndroid Build Coastguard Worker pg->ppd_status = PPD_ALLOC_ERROR;
1977*5e7646d2SAndroid Build Coastguard Worker
1978*5e7646d2SAndroid Build Coastguard Worker goto error;
1979*5e7646d2SAndroid Build Coastguard Worker }
1980*5e7646d2SAndroid Build Coastguard Worker
1981*5e7646d2SAndroid Build Coastguard Worker size->left = (float)_cupsStrScand(string, &sptr, loc);
1982*5e7646d2SAndroid Build Coastguard Worker size->bottom = (float)_cupsStrScand(sptr, &sptr, loc);
1983*5e7646d2SAndroid Build Coastguard Worker size->right = (float)_cupsStrScand(sptr, &sptr, loc);
1984*5e7646d2SAndroid Build Coastguard Worker size->top = (float)_cupsStrScand(sptr, NULL, loc);
1985*5e7646d2SAndroid Build Coastguard Worker
1986*5e7646d2SAndroid Build Coastguard Worker free(string);
1987*5e7646d2SAndroid Build Coastguard Worker string = NULL;
1988*5e7646d2SAndroid Build Coastguard Worker }
1989*5e7646d2SAndroid Build Coastguard Worker else if (option != NULL &&
1990*5e7646d2SAndroid Build Coastguard Worker (mask & (PPD_KEYWORD | PPD_OPTION | PPD_STRING)) ==
1991*5e7646d2SAndroid Build Coastguard Worker (PPD_KEYWORD | PPD_OPTION | PPD_STRING) &&
1992*5e7646d2SAndroid Build Coastguard Worker !strcmp(keyword, option->keyword))
1993*5e7646d2SAndroid Build Coastguard Worker {
1994*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("2_ppdOpen: group=%p, subgroup=%p", group, subgroup));
1995*5e7646d2SAndroid Build Coastguard Worker
1996*5e7646d2SAndroid Build Coastguard Worker if (!_cups_strcasecmp(name, "custom") || !_cups_strncasecmp(name, "custom.", 7))
1997*5e7646d2SAndroid Build Coastguard Worker {
1998*5e7646d2SAndroid Build Coastguard Worker char cname[PPD_MAX_NAME]; /* Rewrite with a leading underscore */
1999*5e7646d2SAndroid Build Coastguard Worker snprintf(cname, sizeof(cname), "_%s", name);
2000*5e7646d2SAndroid Build Coastguard Worker strlcpy(name, cname, sizeof(name));
2001*5e7646d2SAndroid Build Coastguard Worker }
2002*5e7646d2SAndroid Build Coastguard Worker
2003*5e7646d2SAndroid Build Coastguard Worker if (!strcmp(keyword, "PageSize"))
2004*5e7646d2SAndroid Build Coastguard Worker {
2005*5e7646d2SAndroid Build Coastguard Worker /*
2006*5e7646d2SAndroid Build Coastguard Worker * Add a page size...
2007*5e7646d2SAndroid Build Coastguard Worker */
2008*5e7646d2SAndroid Build Coastguard Worker
2009*5e7646d2SAndroid Build Coastguard Worker if (ppdPageSize(ppd, name) == NULL)
2010*5e7646d2SAndroid Build Coastguard Worker ppd_add_size(ppd, name);
2011*5e7646d2SAndroid Build Coastguard Worker }
2012*5e7646d2SAndroid Build Coastguard Worker
2013*5e7646d2SAndroid Build Coastguard Worker /*
2014*5e7646d2SAndroid Build Coastguard Worker * Add the option choice...
2015*5e7646d2SAndroid Build Coastguard Worker */
2016*5e7646d2SAndroid Build Coastguard Worker
2017*5e7646d2SAndroid Build Coastguard Worker if ((choice = ppd_add_choice(option, name)) == NULL)
2018*5e7646d2SAndroid Build Coastguard Worker {
2019*5e7646d2SAndroid Build Coastguard Worker pg->ppd_status = PPD_ALLOC_ERROR;
2020*5e7646d2SAndroid Build Coastguard Worker
2021*5e7646d2SAndroid Build Coastguard Worker goto error;
2022*5e7646d2SAndroid Build Coastguard Worker }
2023*5e7646d2SAndroid Build Coastguard Worker
2024*5e7646d2SAndroid Build Coastguard Worker if (text[0])
2025*5e7646d2SAndroid Build Coastguard Worker cupsCharsetToUTF8((cups_utf8_t *)choice->text, text,
2026*5e7646d2SAndroid Build Coastguard Worker sizeof(choice->text), encoding);
2027*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(name, "True"))
2028*5e7646d2SAndroid Build Coastguard Worker strlcpy(choice->text, _("Yes"), sizeof(choice->text));
2029*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(name, "False"))
2030*5e7646d2SAndroid Build Coastguard Worker strlcpy(choice->text, _("No"), sizeof(choice->text));
2031*5e7646d2SAndroid Build Coastguard Worker else
2032*5e7646d2SAndroid Build Coastguard Worker strlcpy(choice->text, name, sizeof(choice->text));
2033*5e7646d2SAndroid Build Coastguard Worker
2034*5e7646d2SAndroid Build Coastguard Worker if (option->section == PPD_ORDER_JCL)
2035*5e7646d2SAndroid Build Coastguard Worker ppd_decode(string); /* Decode quoted string */
2036*5e7646d2SAndroid Build Coastguard Worker
2037*5e7646d2SAndroid Build Coastguard Worker choice->code = string;
2038*5e7646d2SAndroid Build Coastguard Worker string = NULL; /* Don't add as an attribute below */
2039*5e7646d2SAndroid Build Coastguard Worker }
2040*5e7646d2SAndroid Build Coastguard Worker
2041*5e7646d2SAndroid Build Coastguard Worker /*
2042*5e7646d2SAndroid Build Coastguard Worker * Add remaining lines with keywords and string values as attributes...
2043*5e7646d2SAndroid Build Coastguard Worker */
2044*5e7646d2SAndroid Build Coastguard Worker
2045*5e7646d2SAndroid Build Coastguard Worker if (string &&
2046*5e7646d2SAndroid Build Coastguard Worker (mask & (PPD_KEYWORD | PPD_STRING)) == (PPD_KEYWORD | PPD_STRING))
2047*5e7646d2SAndroid Build Coastguard Worker ppd_add_attr(ppd, keyword, name, text, string);
2048*5e7646d2SAndroid Build Coastguard Worker else
2049*5e7646d2SAndroid Build Coastguard Worker free(string);
2050*5e7646d2SAndroid Build Coastguard Worker }
2051*5e7646d2SAndroid Build Coastguard Worker
2052*5e7646d2SAndroid Build Coastguard Worker /*
2053*5e7646d2SAndroid Build Coastguard Worker * Check for a missing CloseUI/JCLCloseUI...
2054*5e7646d2SAndroid Build Coastguard Worker */
2055*5e7646d2SAndroid Build Coastguard Worker
2056*5e7646d2SAndroid Build Coastguard Worker if (option && pg->ppd_conform == PPD_CONFORM_STRICT)
2057*5e7646d2SAndroid Build Coastguard Worker {
2058*5e7646d2SAndroid Build Coastguard Worker pg->ppd_status = PPD_MISSING_CLOSE_UI;
2059*5e7646d2SAndroid Build Coastguard Worker goto error;
2060*5e7646d2SAndroid Build Coastguard Worker }
2061*5e7646d2SAndroid Build Coastguard Worker
2062*5e7646d2SAndroid Build Coastguard Worker /*
2063*5e7646d2SAndroid Build Coastguard Worker * Check for a missing CloseGroup...
2064*5e7646d2SAndroid Build Coastguard Worker */
2065*5e7646d2SAndroid Build Coastguard Worker
2066*5e7646d2SAndroid Build Coastguard Worker if (group && pg->ppd_conform == PPD_CONFORM_STRICT)
2067*5e7646d2SAndroid Build Coastguard Worker {
2068*5e7646d2SAndroid Build Coastguard Worker pg->ppd_status = PPD_MISSING_CLOSE_GROUP;
2069*5e7646d2SAndroid Build Coastguard Worker goto error;
2070*5e7646d2SAndroid Build Coastguard Worker }
2071*5e7646d2SAndroid Build Coastguard Worker
2072*5e7646d2SAndroid Build Coastguard Worker free(line.buffer);
2073*5e7646d2SAndroid Build Coastguard Worker
2074*5e7646d2SAndroid Build Coastguard Worker /*
2075*5e7646d2SAndroid Build Coastguard Worker * Reset language preferences...
2076*5e7646d2SAndroid Build Coastguard Worker */
2077*5e7646d2SAndroid Build Coastguard Worker
2078*5e7646d2SAndroid Build Coastguard Worker #ifdef DEBUG
2079*5e7646d2SAndroid Build Coastguard Worker if (!cupsFileEOF(fp))
2080*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("1_ppdOpen: Premature EOF at %lu...\n",
2081*5e7646d2SAndroid Build Coastguard Worker (unsigned long)cupsFileTell(fp)));
2082*5e7646d2SAndroid Build Coastguard Worker #endif /* DEBUG */
2083*5e7646d2SAndroid Build Coastguard Worker
2084*5e7646d2SAndroid Build Coastguard Worker if (pg->ppd_status != PPD_OK)
2085*5e7646d2SAndroid Build Coastguard Worker {
2086*5e7646d2SAndroid Build Coastguard Worker /*
2087*5e7646d2SAndroid Build Coastguard Worker * Had an error reading the PPD file, cannot continue!
2088*5e7646d2SAndroid Build Coastguard Worker */
2089*5e7646d2SAndroid Build Coastguard Worker
2090*5e7646d2SAndroid Build Coastguard Worker ppdClose(ppd);
2091*5e7646d2SAndroid Build Coastguard Worker
2092*5e7646d2SAndroid Build Coastguard Worker return (NULL);
2093*5e7646d2SAndroid Build Coastguard Worker }
2094*5e7646d2SAndroid Build Coastguard Worker
2095*5e7646d2SAndroid Build Coastguard Worker /*
2096*5e7646d2SAndroid Build Coastguard Worker * Update the filters array as needed...
2097*5e7646d2SAndroid Build Coastguard Worker */
2098*5e7646d2SAndroid Build Coastguard Worker
2099*5e7646d2SAndroid Build Coastguard Worker if (!ppd_update_filters(ppd, pg))
2100*5e7646d2SAndroid Build Coastguard Worker {
2101*5e7646d2SAndroid Build Coastguard Worker ppdClose(ppd);
2102*5e7646d2SAndroid Build Coastguard Worker
2103*5e7646d2SAndroid Build Coastguard Worker return (NULL);
2104*5e7646d2SAndroid Build Coastguard Worker }
2105*5e7646d2SAndroid Build Coastguard Worker
2106*5e7646d2SAndroid Build Coastguard Worker /*
2107*5e7646d2SAndroid Build Coastguard Worker * Create the sorted options array and set the option back-pointer for
2108*5e7646d2SAndroid Build Coastguard Worker * each choice and custom option...
2109*5e7646d2SAndroid Build Coastguard Worker */
2110*5e7646d2SAndroid Build Coastguard Worker
2111*5e7646d2SAndroid Build Coastguard Worker ppd->options = cupsArrayNew2((cups_array_func_t)ppd_compare_options, NULL,
2112*5e7646d2SAndroid Build Coastguard Worker (cups_ahash_func_t)ppd_hash_option,
2113*5e7646d2SAndroid Build Coastguard Worker PPD_HASHSIZE);
2114*5e7646d2SAndroid Build Coastguard Worker
2115*5e7646d2SAndroid Build Coastguard Worker for (i = ppd->num_groups, group = ppd->groups;
2116*5e7646d2SAndroid Build Coastguard Worker i > 0;
2117*5e7646d2SAndroid Build Coastguard Worker i --, group ++)
2118*5e7646d2SAndroid Build Coastguard Worker {
2119*5e7646d2SAndroid Build Coastguard Worker for (j = group->num_options, option = group->options;
2120*5e7646d2SAndroid Build Coastguard Worker j > 0;
2121*5e7646d2SAndroid Build Coastguard Worker j --, option ++)
2122*5e7646d2SAndroid Build Coastguard Worker {
2123*5e7646d2SAndroid Build Coastguard Worker ppd_coption_t *coption; /* Custom option */
2124*5e7646d2SAndroid Build Coastguard Worker
2125*5e7646d2SAndroid Build Coastguard Worker
2126*5e7646d2SAndroid Build Coastguard Worker cupsArrayAdd(ppd->options, option);
2127*5e7646d2SAndroid Build Coastguard Worker
2128*5e7646d2SAndroid Build Coastguard Worker for (k = 0; k < option->num_choices; k ++)
2129*5e7646d2SAndroid Build Coastguard Worker option->choices[k].option = option;
2130*5e7646d2SAndroid Build Coastguard Worker
2131*5e7646d2SAndroid Build Coastguard Worker if ((coption = ppdFindCustomOption(ppd, option->keyword)) != NULL)
2132*5e7646d2SAndroid Build Coastguard Worker coption->option = option;
2133*5e7646d2SAndroid Build Coastguard Worker }
2134*5e7646d2SAndroid Build Coastguard Worker }
2135*5e7646d2SAndroid Build Coastguard Worker
2136*5e7646d2SAndroid Build Coastguard Worker /*
2137*5e7646d2SAndroid Build Coastguard Worker * Create an array to track the marked choices...
2138*5e7646d2SAndroid Build Coastguard Worker */
2139*5e7646d2SAndroid Build Coastguard Worker
2140*5e7646d2SAndroid Build Coastguard Worker ppd->marked = cupsArrayNew((cups_array_func_t)ppd_compare_choices, NULL);
2141*5e7646d2SAndroid Build Coastguard Worker
2142*5e7646d2SAndroid Build Coastguard Worker /*
2143*5e7646d2SAndroid Build Coastguard Worker * Return the PPD file structure...
2144*5e7646d2SAndroid Build Coastguard Worker */
2145*5e7646d2SAndroid Build Coastguard Worker
2146*5e7646d2SAndroid Build Coastguard Worker return (ppd);
2147*5e7646d2SAndroid Build Coastguard Worker
2148*5e7646d2SAndroid Build Coastguard Worker /*
2149*5e7646d2SAndroid Build Coastguard Worker * Common exit point for errors to save code size...
2150*5e7646d2SAndroid Build Coastguard Worker */
2151*5e7646d2SAndroid Build Coastguard Worker
2152*5e7646d2SAndroid Build Coastguard Worker error:
2153*5e7646d2SAndroid Build Coastguard Worker
2154*5e7646d2SAndroid Build Coastguard Worker free(string);
2155*5e7646d2SAndroid Build Coastguard Worker free(line.buffer);
2156*5e7646d2SAndroid Build Coastguard Worker
2157*5e7646d2SAndroid Build Coastguard Worker ppdClose(ppd);
2158*5e7646d2SAndroid Build Coastguard Worker
2159*5e7646d2SAndroid Build Coastguard Worker return (NULL);
2160*5e7646d2SAndroid Build Coastguard Worker }
2161*5e7646d2SAndroid Build Coastguard Worker
2162*5e7646d2SAndroid Build Coastguard Worker
2163*5e7646d2SAndroid Build Coastguard Worker /*
2164*5e7646d2SAndroid Build Coastguard Worker * 'ppdOpen()' - Read a PPD file into memory.
2165*5e7646d2SAndroid Build Coastguard Worker */
2166*5e7646d2SAndroid Build Coastguard Worker
2167*5e7646d2SAndroid Build Coastguard Worker ppd_file_t * /* O - PPD file record */
ppdOpen(FILE * fp)2168*5e7646d2SAndroid Build Coastguard Worker ppdOpen(FILE *fp) /* I - File to read from */
2169*5e7646d2SAndroid Build Coastguard Worker {
2170*5e7646d2SAndroid Build Coastguard Worker ppd_file_t *ppd; /* PPD file record */
2171*5e7646d2SAndroid Build Coastguard Worker cups_file_t *cf; /* CUPS file */
2172*5e7646d2SAndroid Build Coastguard Worker
2173*5e7646d2SAndroid Build Coastguard Worker
2174*5e7646d2SAndroid Build Coastguard Worker /*
2175*5e7646d2SAndroid Build Coastguard Worker * Reopen the stdio file as a CUPS file...
2176*5e7646d2SAndroid Build Coastguard Worker */
2177*5e7646d2SAndroid Build Coastguard Worker
2178*5e7646d2SAndroid Build Coastguard Worker if ((cf = cupsFileOpenFd(fileno(fp), "r")) == NULL)
2179*5e7646d2SAndroid Build Coastguard Worker return (NULL);
2180*5e7646d2SAndroid Build Coastguard Worker
2181*5e7646d2SAndroid Build Coastguard Worker /*
2182*5e7646d2SAndroid Build Coastguard Worker * Load the PPD file using the newer API...
2183*5e7646d2SAndroid Build Coastguard Worker */
2184*5e7646d2SAndroid Build Coastguard Worker
2185*5e7646d2SAndroid Build Coastguard Worker ppd = _ppdOpen(cf, _PPD_LOCALIZATION_DEFAULT);
2186*5e7646d2SAndroid Build Coastguard Worker
2187*5e7646d2SAndroid Build Coastguard Worker /*
2188*5e7646d2SAndroid Build Coastguard Worker * Close the CUPS file and return the PPD...
2189*5e7646d2SAndroid Build Coastguard Worker */
2190*5e7646d2SAndroid Build Coastguard Worker
2191*5e7646d2SAndroid Build Coastguard Worker cupsFileClose(cf);
2192*5e7646d2SAndroid Build Coastguard Worker
2193*5e7646d2SAndroid Build Coastguard Worker return (ppd);
2194*5e7646d2SAndroid Build Coastguard Worker }
2195*5e7646d2SAndroid Build Coastguard Worker
2196*5e7646d2SAndroid Build Coastguard Worker
2197*5e7646d2SAndroid Build Coastguard Worker /*
2198*5e7646d2SAndroid Build Coastguard Worker * 'ppdOpen2()' - Read a PPD file into memory.
2199*5e7646d2SAndroid Build Coastguard Worker *
2200*5e7646d2SAndroid Build Coastguard Worker * @since CUPS 1.2/macOS 10.5@
2201*5e7646d2SAndroid Build Coastguard Worker */
2202*5e7646d2SAndroid Build Coastguard Worker
2203*5e7646d2SAndroid Build Coastguard Worker ppd_file_t * /* O - PPD file record or @code NULL@ if the PPD file could not be opened. */
ppdOpen2(cups_file_t * fp)2204*5e7646d2SAndroid Build Coastguard Worker ppdOpen2(cups_file_t *fp) /* I - File to read from */
2205*5e7646d2SAndroid Build Coastguard Worker {
2206*5e7646d2SAndroid Build Coastguard Worker return _ppdOpen(fp, _PPD_LOCALIZATION_DEFAULT);
2207*5e7646d2SAndroid Build Coastguard Worker }
2208*5e7646d2SAndroid Build Coastguard Worker
2209*5e7646d2SAndroid Build Coastguard Worker
2210*5e7646d2SAndroid Build Coastguard Worker /*
2211*5e7646d2SAndroid Build Coastguard Worker * 'ppdOpenFd()' - Read a PPD file into memory.
2212*5e7646d2SAndroid Build Coastguard Worker */
2213*5e7646d2SAndroid Build Coastguard Worker
2214*5e7646d2SAndroid Build Coastguard Worker ppd_file_t * /* O - PPD file record or @code NULL@ if the PPD file could not be opened. */
ppdOpenFd(int fd)2215*5e7646d2SAndroid Build Coastguard Worker ppdOpenFd(int fd) /* I - File to read from */
2216*5e7646d2SAndroid Build Coastguard Worker {
2217*5e7646d2SAndroid Build Coastguard Worker cups_file_t *fp; /* CUPS file pointer */
2218*5e7646d2SAndroid Build Coastguard Worker ppd_file_t *ppd; /* PPD file record */
2219*5e7646d2SAndroid Build Coastguard Worker _ppd_globals_t *pg = _ppdGlobals();
2220*5e7646d2SAndroid Build Coastguard Worker /* Global data */
2221*5e7646d2SAndroid Build Coastguard Worker
2222*5e7646d2SAndroid Build Coastguard Worker
2223*5e7646d2SAndroid Build Coastguard Worker /*
2224*5e7646d2SAndroid Build Coastguard Worker * Set the line number to 0...
2225*5e7646d2SAndroid Build Coastguard Worker */
2226*5e7646d2SAndroid Build Coastguard Worker
2227*5e7646d2SAndroid Build Coastguard Worker pg->ppd_line = 0;
2228*5e7646d2SAndroid Build Coastguard Worker
2229*5e7646d2SAndroid Build Coastguard Worker /*
2230*5e7646d2SAndroid Build Coastguard Worker * Range check input...
2231*5e7646d2SAndroid Build Coastguard Worker */
2232*5e7646d2SAndroid Build Coastguard Worker
2233*5e7646d2SAndroid Build Coastguard Worker if (fd < 0)
2234*5e7646d2SAndroid Build Coastguard Worker {
2235*5e7646d2SAndroid Build Coastguard Worker pg->ppd_status = PPD_NULL_FILE;
2236*5e7646d2SAndroid Build Coastguard Worker
2237*5e7646d2SAndroid Build Coastguard Worker return (NULL);
2238*5e7646d2SAndroid Build Coastguard Worker }
2239*5e7646d2SAndroid Build Coastguard Worker
2240*5e7646d2SAndroid Build Coastguard Worker /*
2241*5e7646d2SAndroid Build Coastguard Worker * Try to open the file and parse it...
2242*5e7646d2SAndroid Build Coastguard Worker */
2243*5e7646d2SAndroid Build Coastguard Worker
2244*5e7646d2SAndroid Build Coastguard Worker if ((fp = cupsFileOpenFd(fd, "r")) != NULL)
2245*5e7646d2SAndroid Build Coastguard Worker {
2246*5e7646d2SAndroid Build Coastguard Worker ppd = ppdOpen2(fp);
2247*5e7646d2SAndroid Build Coastguard Worker
2248*5e7646d2SAndroid Build Coastguard Worker cupsFileClose(fp);
2249*5e7646d2SAndroid Build Coastguard Worker }
2250*5e7646d2SAndroid Build Coastguard Worker else
2251*5e7646d2SAndroid Build Coastguard Worker {
2252*5e7646d2SAndroid Build Coastguard Worker pg->ppd_status = PPD_FILE_OPEN_ERROR;
2253*5e7646d2SAndroid Build Coastguard Worker ppd = NULL;
2254*5e7646d2SAndroid Build Coastguard Worker }
2255*5e7646d2SAndroid Build Coastguard Worker
2256*5e7646d2SAndroid Build Coastguard Worker return (ppd);
2257*5e7646d2SAndroid Build Coastguard Worker }
2258*5e7646d2SAndroid Build Coastguard Worker
2259*5e7646d2SAndroid Build Coastguard Worker
2260*5e7646d2SAndroid Build Coastguard Worker /*
2261*5e7646d2SAndroid Build Coastguard Worker * '_ppdOpenFile()' - Read a PPD file into memory.
2262*5e7646d2SAndroid Build Coastguard Worker */
2263*5e7646d2SAndroid Build Coastguard Worker
2264*5e7646d2SAndroid Build Coastguard Worker ppd_file_t * /* O - PPD file record or @code NULL@ if the PPD file could not be opened. */
_ppdOpenFile(const char * filename,_ppd_localization_t localization)2265*5e7646d2SAndroid Build Coastguard Worker _ppdOpenFile(const char *filename, /* I - File to read from */
2266*5e7646d2SAndroid Build Coastguard Worker _ppd_localization_t localization) /* I - Localization to load */
2267*5e7646d2SAndroid Build Coastguard Worker {
2268*5e7646d2SAndroid Build Coastguard Worker cups_file_t *fp; /* File pointer */
2269*5e7646d2SAndroid Build Coastguard Worker ppd_file_t *ppd; /* PPD file record */
2270*5e7646d2SAndroid Build Coastguard Worker _ppd_globals_t *pg = _ppdGlobals();
2271*5e7646d2SAndroid Build Coastguard Worker /* Global data */
2272*5e7646d2SAndroid Build Coastguard Worker
2273*5e7646d2SAndroid Build Coastguard Worker
2274*5e7646d2SAndroid Build Coastguard Worker /*
2275*5e7646d2SAndroid Build Coastguard Worker * Set the line number to 0...
2276*5e7646d2SAndroid Build Coastguard Worker */
2277*5e7646d2SAndroid Build Coastguard Worker
2278*5e7646d2SAndroid Build Coastguard Worker pg->ppd_line = 0;
2279*5e7646d2SAndroid Build Coastguard Worker
2280*5e7646d2SAndroid Build Coastguard Worker /*
2281*5e7646d2SAndroid Build Coastguard Worker * Range check input...
2282*5e7646d2SAndroid Build Coastguard Worker */
2283*5e7646d2SAndroid Build Coastguard Worker
2284*5e7646d2SAndroid Build Coastguard Worker if (filename == NULL)
2285*5e7646d2SAndroid Build Coastguard Worker {
2286*5e7646d2SAndroid Build Coastguard Worker pg->ppd_status = PPD_NULL_FILE;
2287*5e7646d2SAndroid Build Coastguard Worker
2288*5e7646d2SAndroid Build Coastguard Worker return (NULL);
2289*5e7646d2SAndroid Build Coastguard Worker }
2290*5e7646d2SAndroid Build Coastguard Worker
2291*5e7646d2SAndroid Build Coastguard Worker /*
2292*5e7646d2SAndroid Build Coastguard Worker * Try to open the file and parse it...
2293*5e7646d2SAndroid Build Coastguard Worker */
2294*5e7646d2SAndroid Build Coastguard Worker
2295*5e7646d2SAndroid Build Coastguard Worker if ((fp = cupsFileOpen(filename, "r")) != NULL)
2296*5e7646d2SAndroid Build Coastguard Worker {
2297*5e7646d2SAndroid Build Coastguard Worker ppd = _ppdOpen(fp, localization);
2298*5e7646d2SAndroid Build Coastguard Worker
2299*5e7646d2SAndroid Build Coastguard Worker cupsFileClose(fp);
2300*5e7646d2SAndroid Build Coastguard Worker }
2301*5e7646d2SAndroid Build Coastguard Worker else
2302*5e7646d2SAndroid Build Coastguard Worker {
2303*5e7646d2SAndroid Build Coastguard Worker pg->ppd_status = PPD_FILE_OPEN_ERROR;
2304*5e7646d2SAndroid Build Coastguard Worker ppd = NULL;
2305*5e7646d2SAndroid Build Coastguard Worker }
2306*5e7646d2SAndroid Build Coastguard Worker
2307*5e7646d2SAndroid Build Coastguard Worker return (ppd);
2308*5e7646d2SAndroid Build Coastguard Worker }
2309*5e7646d2SAndroid Build Coastguard Worker
2310*5e7646d2SAndroid Build Coastguard Worker
2311*5e7646d2SAndroid Build Coastguard Worker /*
2312*5e7646d2SAndroid Build Coastguard Worker * 'ppdOpenFile()' - Read a PPD file into memory.
2313*5e7646d2SAndroid Build Coastguard Worker */
2314*5e7646d2SAndroid Build Coastguard Worker
2315*5e7646d2SAndroid Build Coastguard Worker ppd_file_t * /* O - PPD file record or @code NULL@ if the PPD file could not be opened. */
ppdOpenFile(const char * filename)2316*5e7646d2SAndroid Build Coastguard Worker ppdOpenFile(const char *filename) /* I - File to read from */
2317*5e7646d2SAndroid Build Coastguard Worker {
2318*5e7646d2SAndroid Build Coastguard Worker return _ppdOpenFile(filename, _PPD_LOCALIZATION_DEFAULT);
2319*5e7646d2SAndroid Build Coastguard Worker }
2320*5e7646d2SAndroid Build Coastguard Worker
2321*5e7646d2SAndroid Build Coastguard Worker
2322*5e7646d2SAndroid Build Coastguard Worker /*
2323*5e7646d2SAndroid Build Coastguard Worker * 'ppdSetConformance()' - Set the conformance level for PPD files.
2324*5e7646d2SAndroid Build Coastguard Worker *
2325*5e7646d2SAndroid Build Coastguard Worker * @since CUPS 1.1.20/macOS 10.4@
2326*5e7646d2SAndroid Build Coastguard Worker */
2327*5e7646d2SAndroid Build Coastguard Worker
2328*5e7646d2SAndroid Build Coastguard Worker void
ppdSetConformance(ppd_conform_t c)2329*5e7646d2SAndroid Build Coastguard Worker ppdSetConformance(ppd_conform_t c) /* I - Conformance level */
2330*5e7646d2SAndroid Build Coastguard Worker {
2331*5e7646d2SAndroid Build Coastguard Worker _ppd_globals_t *pg = _ppdGlobals();
2332*5e7646d2SAndroid Build Coastguard Worker /* Global data */
2333*5e7646d2SAndroid Build Coastguard Worker
2334*5e7646d2SAndroid Build Coastguard Worker
2335*5e7646d2SAndroid Build Coastguard Worker pg->ppd_conform = c;
2336*5e7646d2SAndroid Build Coastguard Worker }
2337*5e7646d2SAndroid Build Coastguard Worker
2338*5e7646d2SAndroid Build Coastguard Worker
2339*5e7646d2SAndroid Build Coastguard Worker /*
2340*5e7646d2SAndroid Build Coastguard Worker * 'ppd_add_attr()' - Add an attribute to the PPD data.
2341*5e7646d2SAndroid Build Coastguard Worker */
2342*5e7646d2SAndroid Build Coastguard Worker
2343*5e7646d2SAndroid Build Coastguard Worker static ppd_attr_t * /* O - New attribute */
ppd_add_attr(ppd_file_t * ppd,const char * name,const char * spec,const char * text,const char * value)2344*5e7646d2SAndroid Build Coastguard Worker ppd_add_attr(ppd_file_t *ppd, /* I - PPD file data */
2345*5e7646d2SAndroid Build Coastguard Worker const char *name, /* I - Attribute name */
2346*5e7646d2SAndroid Build Coastguard Worker const char *spec, /* I - Specifier string, if any */
2347*5e7646d2SAndroid Build Coastguard Worker const char *text, /* I - Text string, if any */
2348*5e7646d2SAndroid Build Coastguard Worker const char *value) /* I - Value of attribute */
2349*5e7646d2SAndroid Build Coastguard Worker {
2350*5e7646d2SAndroid Build Coastguard Worker ppd_attr_t **ptr, /* New array */
2351*5e7646d2SAndroid Build Coastguard Worker *temp; /* New attribute */
2352*5e7646d2SAndroid Build Coastguard Worker
2353*5e7646d2SAndroid Build Coastguard Worker
2354*5e7646d2SAndroid Build Coastguard Worker /*
2355*5e7646d2SAndroid Build Coastguard Worker * Range check input...
2356*5e7646d2SAndroid Build Coastguard Worker */
2357*5e7646d2SAndroid Build Coastguard Worker
2358*5e7646d2SAndroid Build Coastguard Worker if (ppd == NULL || name == NULL || spec == NULL)
2359*5e7646d2SAndroid Build Coastguard Worker return (NULL);
2360*5e7646d2SAndroid Build Coastguard Worker
2361*5e7646d2SAndroid Build Coastguard Worker /*
2362*5e7646d2SAndroid Build Coastguard Worker * Create the array as needed...
2363*5e7646d2SAndroid Build Coastguard Worker */
2364*5e7646d2SAndroid Build Coastguard Worker
2365*5e7646d2SAndroid Build Coastguard Worker if (!ppd->sorted_attrs)
2366*5e7646d2SAndroid Build Coastguard Worker ppd->sorted_attrs = cupsArrayNew((cups_array_func_t)ppd_compare_attrs,
2367*5e7646d2SAndroid Build Coastguard Worker NULL);
2368*5e7646d2SAndroid Build Coastguard Worker
2369*5e7646d2SAndroid Build Coastguard Worker /*
2370*5e7646d2SAndroid Build Coastguard Worker * Allocate memory for the new attribute...
2371*5e7646d2SAndroid Build Coastguard Worker */
2372*5e7646d2SAndroid Build Coastguard Worker
2373*5e7646d2SAndroid Build Coastguard Worker if (ppd->num_attrs == 0)
2374*5e7646d2SAndroid Build Coastguard Worker ptr = malloc(sizeof(ppd_attr_t *));
2375*5e7646d2SAndroid Build Coastguard Worker else
2376*5e7646d2SAndroid Build Coastguard Worker ptr = realloc(ppd->attrs, (size_t)(ppd->num_attrs + 1) * sizeof(ppd_attr_t *));
2377*5e7646d2SAndroid Build Coastguard Worker
2378*5e7646d2SAndroid Build Coastguard Worker if (ptr == NULL)
2379*5e7646d2SAndroid Build Coastguard Worker return (NULL);
2380*5e7646d2SAndroid Build Coastguard Worker
2381*5e7646d2SAndroid Build Coastguard Worker ppd->attrs = ptr;
2382*5e7646d2SAndroid Build Coastguard Worker ptr += ppd->num_attrs;
2383*5e7646d2SAndroid Build Coastguard Worker
2384*5e7646d2SAndroid Build Coastguard Worker if ((temp = calloc(1, sizeof(ppd_attr_t))) == NULL)
2385*5e7646d2SAndroid Build Coastguard Worker return (NULL);
2386*5e7646d2SAndroid Build Coastguard Worker
2387*5e7646d2SAndroid Build Coastguard Worker *ptr = temp;
2388*5e7646d2SAndroid Build Coastguard Worker
2389*5e7646d2SAndroid Build Coastguard Worker ppd->num_attrs ++;
2390*5e7646d2SAndroid Build Coastguard Worker
2391*5e7646d2SAndroid Build Coastguard Worker /*
2392*5e7646d2SAndroid Build Coastguard Worker * Copy data over...
2393*5e7646d2SAndroid Build Coastguard Worker */
2394*5e7646d2SAndroid Build Coastguard Worker
2395*5e7646d2SAndroid Build Coastguard Worker if (!_cups_strcasecmp(spec, "custom") || !_cups_strncasecmp(spec, "custom.", 7))
2396*5e7646d2SAndroid Build Coastguard Worker {
2397*5e7646d2SAndroid Build Coastguard Worker temp->spec[0] = '_';
2398*5e7646d2SAndroid Build Coastguard Worker strlcpy(temp->spec + 1, spec, sizeof(temp->spec) - 1);
2399*5e7646d2SAndroid Build Coastguard Worker }
2400*5e7646d2SAndroid Build Coastguard Worker else {
2401*5e7646d2SAndroid Build Coastguard Worker strlcpy(temp->spec, spec, sizeof(temp->spec));
2402*5e7646d2SAndroid Build Coastguard Worker }
2403*5e7646d2SAndroid Build Coastguard Worker
2404*5e7646d2SAndroid Build Coastguard Worker strlcpy(temp->name, name, sizeof(temp->name));
2405*5e7646d2SAndroid Build Coastguard Worker strlcpy(temp->text, text, sizeof(temp->text));
2406*5e7646d2SAndroid Build Coastguard Worker temp->value = (char *)value;
2407*5e7646d2SAndroid Build Coastguard Worker
2408*5e7646d2SAndroid Build Coastguard Worker /*
2409*5e7646d2SAndroid Build Coastguard Worker * Add the attribute to the sorted array...
2410*5e7646d2SAndroid Build Coastguard Worker */
2411*5e7646d2SAndroid Build Coastguard Worker
2412*5e7646d2SAndroid Build Coastguard Worker cupsArrayAdd(ppd->sorted_attrs, temp);
2413*5e7646d2SAndroid Build Coastguard Worker
2414*5e7646d2SAndroid Build Coastguard Worker /*
2415*5e7646d2SAndroid Build Coastguard Worker * Return the attribute...
2416*5e7646d2SAndroid Build Coastguard Worker */
2417*5e7646d2SAndroid Build Coastguard Worker
2418*5e7646d2SAndroid Build Coastguard Worker return (temp);
2419*5e7646d2SAndroid Build Coastguard Worker }
2420*5e7646d2SAndroid Build Coastguard Worker
2421*5e7646d2SAndroid Build Coastguard Worker
2422*5e7646d2SAndroid Build Coastguard Worker /*
2423*5e7646d2SAndroid Build Coastguard Worker * 'ppd_add_choice()' - Add a choice to an option.
2424*5e7646d2SAndroid Build Coastguard Worker */
2425*5e7646d2SAndroid Build Coastguard Worker
2426*5e7646d2SAndroid Build Coastguard Worker static ppd_choice_t * /* O - Named choice */
ppd_add_choice(ppd_option_t * option,const char * name)2427*5e7646d2SAndroid Build Coastguard Worker ppd_add_choice(ppd_option_t *option, /* I - Option */
2428*5e7646d2SAndroid Build Coastguard Worker const char *name) /* I - Name of choice */
2429*5e7646d2SAndroid Build Coastguard Worker {
2430*5e7646d2SAndroid Build Coastguard Worker ppd_choice_t *choice; /* Choice */
2431*5e7646d2SAndroid Build Coastguard Worker
2432*5e7646d2SAndroid Build Coastguard Worker
2433*5e7646d2SAndroid Build Coastguard Worker if (option->num_choices == 0)
2434*5e7646d2SAndroid Build Coastguard Worker choice = malloc(sizeof(ppd_choice_t));
2435*5e7646d2SAndroid Build Coastguard Worker else
2436*5e7646d2SAndroid Build Coastguard Worker choice = realloc(option->choices, sizeof(ppd_choice_t) * (size_t)(option->num_choices + 1));
2437*5e7646d2SAndroid Build Coastguard Worker
2438*5e7646d2SAndroid Build Coastguard Worker if (choice == NULL)
2439*5e7646d2SAndroid Build Coastguard Worker return (NULL);
2440*5e7646d2SAndroid Build Coastguard Worker
2441*5e7646d2SAndroid Build Coastguard Worker option->choices = choice;
2442*5e7646d2SAndroid Build Coastguard Worker choice += option->num_choices;
2443*5e7646d2SAndroid Build Coastguard Worker option->num_choices ++;
2444*5e7646d2SAndroid Build Coastguard Worker
2445*5e7646d2SAndroid Build Coastguard Worker memset(choice, 0, sizeof(ppd_choice_t));
2446*5e7646d2SAndroid Build Coastguard Worker strlcpy(choice->choice, name, sizeof(choice->choice));
2447*5e7646d2SAndroid Build Coastguard Worker
2448*5e7646d2SAndroid Build Coastguard Worker return (choice);
2449*5e7646d2SAndroid Build Coastguard Worker }
2450*5e7646d2SAndroid Build Coastguard Worker
2451*5e7646d2SAndroid Build Coastguard Worker
2452*5e7646d2SAndroid Build Coastguard Worker /*
2453*5e7646d2SAndroid Build Coastguard Worker * 'ppd_add_size()' - Add a page size.
2454*5e7646d2SAndroid Build Coastguard Worker */
2455*5e7646d2SAndroid Build Coastguard Worker
2456*5e7646d2SAndroid Build Coastguard Worker static ppd_size_t * /* O - Named size */
ppd_add_size(ppd_file_t * ppd,const char * name)2457*5e7646d2SAndroid Build Coastguard Worker ppd_add_size(ppd_file_t *ppd, /* I - PPD file */
2458*5e7646d2SAndroid Build Coastguard Worker const char *name) /* I - Name of size */
2459*5e7646d2SAndroid Build Coastguard Worker {
2460*5e7646d2SAndroid Build Coastguard Worker ppd_size_t *size; /* Size */
2461*5e7646d2SAndroid Build Coastguard Worker
2462*5e7646d2SAndroid Build Coastguard Worker
2463*5e7646d2SAndroid Build Coastguard Worker if (ppd->num_sizes == 0)
2464*5e7646d2SAndroid Build Coastguard Worker size = malloc(sizeof(ppd_size_t));
2465*5e7646d2SAndroid Build Coastguard Worker else
2466*5e7646d2SAndroid Build Coastguard Worker size = realloc(ppd->sizes, sizeof(ppd_size_t) * (size_t)(ppd->num_sizes + 1));
2467*5e7646d2SAndroid Build Coastguard Worker
2468*5e7646d2SAndroid Build Coastguard Worker if (size == NULL)
2469*5e7646d2SAndroid Build Coastguard Worker return (NULL);
2470*5e7646d2SAndroid Build Coastguard Worker
2471*5e7646d2SAndroid Build Coastguard Worker ppd->sizes = size;
2472*5e7646d2SAndroid Build Coastguard Worker size += ppd->num_sizes;
2473*5e7646d2SAndroid Build Coastguard Worker ppd->num_sizes ++;
2474*5e7646d2SAndroid Build Coastguard Worker
2475*5e7646d2SAndroid Build Coastguard Worker memset(size, 0, sizeof(ppd_size_t));
2476*5e7646d2SAndroid Build Coastguard Worker strlcpy(size->name, name, sizeof(size->name));
2477*5e7646d2SAndroid Build Coastguard Worker
2478*5e7646d2SAndroid Build Coastguard Worker return (size);
2479*5e7646d2SAndroid Build Coastguard Worker }
2480*5e7646d2SAndroid Build Coastguard Worker
2481*5e7646d2SAndroid Build Coastguard Worker
2482*5e7646d2SAndroid Build Coastguard Worker /*
2483*5e7646d2SAndroid Build Coastguard Worker * 'ppd_compare_attrs()' - Compare two attributes.
2484*5e7646d2SAndroid Build Coastguard Worker */
2485*5e7646d2SAndroid Build Coastguard Worker
2486*5e7646d2SAndroid Build Coastguard Worker static int /* O - Result of comparison */
ppd_compare_attrs(ppd_attr_t * a,ppd_attr_t * b)2487*5e7646d2SAndroid Build Coastguard Worker ppd_compare_attrs(ppd_attr_t *a, /* I - First attribute */
2488*5e7646d2SAndroid Build Coastguard Worker ppd_attr_t *b) /* I - Second attribute */
2489*5e7646d2SAndroid Build Coastguard Worker {
2490*5e7646d2SAndroid Build Coastguard Worker return (_cups_strcasecmp(a->name, b->name));
2491*5e7646d2SAndroid Build Coastguard Worker }
2492*5e7646d2SAndroid Build Coastguard Worker
2493*5e7646d2SAndroid Build Coastguard Worker
2494*5e7646d2SAndroid Build Coastguard Worker /*
2495*5e7646d2SAndroid Build Coastguard Worker * 'ppd_compare_choices()' - Compare two choices...
2496*5e7646d2SAndroid Build Coastguard Worker */
2497*5e7646d2SAndroid Build Coastguard Worker
2498*5e7646d2SAndroid Build Coastguard Worker static int /* O - Result of comparison */
ppd_compare_choices(ppd_choice_t * a,ppd_choice_t * b)2499*5e7646d2SAndroid Build Coastguard Worker ppd_compare_choices(ppd_choice_t *a, /* I - First choice */
2500*5e7646d2SAndroid Build Coastguard Worker ppd_choice_t *b) /* I - Second choice */
2501*5e7646d2SAndroid Build Coastguard Worker {
2502*5e7646d2SAndroid Build Coastguard Worker return (strcmp(a->option->keyword, b->option->keyword));
2503*5e7646d2SAndroid Build Coastguard Worker }
2504*5e7646d2SAndroid Build Coastguard Worker
2505*5e7646d2SAndroid Build Coastguard Worker
2506*5e7646d2SAndroid Build Coastguard Worker /*
2507*5e7646d2SAndroid Build Coastguard Worker * 'ppd_compare_coptions()' - Compare two custom options.
2508*5e7646d2SAndroid Build Coastguard Worker */
2509*5e7646d2SAndroid Build Coastguard Worker
2510*5e7646d2SAndroid Build Coastguard Worker static int /* O - Result of comparison */
ppd_compare_coptions(ppd_coption_t * a,ppd_coption_t * b)2511*5e7646d2SAndroid Build Coastguard Worker ppd_compare_coptions(ppd_coption_t *a, /* I - First option */
2512*5e7646d2SAndroid Build Coastguard Worker ppd_coption_t *b) /* I - Second option */
2513*5e7646d2SAndroid Build Coastguard Worker {
2514*5e7646d2SAndroid Build Coastguard Worker return (_cups_strcasecmp(a->keyword, b->keyword));
2515*5e7646d2SAndroid Build Coastguard Worker }
2516*5e7646d2SAndroid Build Coastguard Worker
2517*5e7646d2SAndroid Build Coastguard Worker
2518*5e7646d2SAndroid Build Coastguard Worker /*
2519*5e7646d2SAndroid Build Coastguard Worker * 'ppd_compare_options()' - Compare two options.
2520*5e7646d2SAndroid Build Coastguard Worker */
2521*5e7646d2SAndroid Build Coastguard Worker
2522*5e7646d2SAndroid Build Coastguard Worker static int /* O - Result of comparison */
ppd_compare_options(ppd_option_t * a,ppd_option_t * b)2523*5e7646d2SAndroid Build Coastguard Worker ppd_compare_options(ppd_option_t *a, /* I - First option */
2524*5e7646d2SAndroid Build Coastguard Worker ppd_option_t *b) /* I - Second option */
2525*5e7646d2SAndroid Build Coastguard Worker {
2526*5e7646d2SAndroid Build Coastguard Worker return (_cups_strcasecmp(a->keyword, b->keyword));
2527*5e7646d2SAndroid Build Coastguard Worker }
2528*5e7646d2SAndroid Build Coastguard Worker
2529*5e7646d2SAndroid Build Coastguard Worker
2530*5e7646d2SAndroid Build Coastguard Worker /*
2531*5e7646d2SAndroid Build Coastguard Worker * 'ppd_decode()' - Decode a string value...
2532*5e7646d2SAndroid Build Coastguard Worker */
2533*5e7646d2SAndroid Build Coastguard Worker
2534*5e7646d2SAndroid Build Coastguard Worker static int /* O - Length of decoded string */
ppd_decode(char * string)2535*5e7646d2SAndroid Build Coastguard Worker ppd_decode(char *string) /* I - String to decode */
2536*5e7646d2SAndroid Build Coastguard Worker {
2537*5e7646d2SAndroid Build Coastguard Worker char *inptr, /* Input pointer */
2538*5e7646d2SAndroid Build Coastguard Worker *outptr; /* Output pointer */
2539*5e7646d2SAndroid Build Coastguard Worker
2540*5e7646d2SAndroid Build Coastguard Worker
2541*5e7646d2SAndroid Build Coastguard Worker inptr = string;
2542*5e7646d2SAndroid Build Coastguard Worker outptr = string;
2543*5e7646d2SAndroid Build Coastguard Worker
2544*5e7646d2SAndroid Build Coastguard Worker while (*inptr != '\0')
2545*5e7646d2SAndroid Build Coastguard Worker if (*inptr == '<' && isxdigit(inptr[1] & 255))
2546*5e7646d2SAndroid Build Coastguard Worker {
2547*5e7646d2SAndroid Build Coastguard Worker /*
2548*5e7646d2SAndroid Build Coastguard Worker * Convert hex to 8-bit values...
2549*5e7646d2SAndroid Build Coastguard Worker */
2550*5e7646d2SAndroid Build Coastguard Worker
2551*5e7646d2SAndroid Build Coastguard Worker inptr ++;
2552*5e7646d2SAndroid Build Coastguard Worker while (isxdigit(*inptr & 255))
2553*5e7646d2SAndroid Build Coastguard Worker {
2554*5e7646d2SAndroid Build Coastguard Worker if (_cups_isalpha(*inptr))
2555*5e7646d2SAndroid Build Coastguard Worker *outptr = (char)((tolower(*inptr) - 'a' + 10) << 4);
2556*5e7646d2SAndroid Build Coastguard Worker else
2557*5e7646d2SAndroid Build Coastguard Worker *outptr = (char)((*inptr - '0') << 4);
2558*5e7646d2SAndroid Build Coastguard Worker
2559*5e7646d2SAndroid Build Coastguard Worker inptr ++;
2560*5e7646d2SAndroid Build Coastguard Worker
2561*5e7646d2SAndroid Build Coastguard Worker if (!isxdigit(*inptr & 255))
2562*5e7646d2SAndroid Build Coastguard Worker break;
2563*5e7646d2SAndroid Build Coastguard Worker
2564*5e7646d2SAndroid Build Coastguard Worker if (_cups_isalpha(*inptr))
2565*5e7646d2SAndroid Build Coastguard Worker *outptr |= (char)(tolower(*inptr) - 'a' + 10);
2566*5e7646d2SAndroid Build Coastguard Worker else
2567*5e7646d2SAndroid Build Coastguard Worker *outptr |= (char)(*inptr - '0');
2568*5e7646d2SAndroid Build Coastguard Worker
2569*5e7646d2SAndroid Build Coastguard Worker inptr ++;
2570*5e7646d2SAndroid Build Coastguard Worker outptr ++;
2571*5e7646d2SAndroid Build Coastguard Worker }
2572*5e7646d2SAndroid Build Coastguard Worker
2573*5e7646d2SAndroid Build Coastguard Worker while (*inptr != '>' && *inptr != '\0')
2574*5e7646d2SAndroid Build Coastguard Worker inptr ++;
2575*5e7646d2SAndroid Build Coastguard Worker while (*inptr == '>')
2576*5e7646d2SAndroid Build Coastguard Worker inptr ++;
2577*5e7646d2SAndroid Build Coastguard Worker }
2578*5e7646d2SAndroid Build Coastguard Worker else
2579*5e7646d2SAndroid Build Coastguard Worker *outptr++ = *inptr++;
2580*5e7646d2SAndroid Build Coastguard Worker
2581*5e7646d2SAndroid Build Coastguard Worker *outptr = '\0';
2582*5e7646d2SAndroid Build Coastguard Worker
2583*5e7646d2SAndroid Build Coastguard Worker return ((int)(outptr - string));
2584*5e7646d2SAndroid Build Coastguard Worker }
2585*5e7646d2SAndroid Build Coastguard Worker
2586*5e7646d2SAndroid Build Coastguard Worker
2587*5e7646d2SAndroid Build Coastguard Worker /*
2588*5e7646d2SAndroid Build Coastguard Worker * 'ppd_free_filters()' - Free the filters array.
2589*5e7646d2SAndroid Build Coastguard Worker */
2590*5e7646d2SAndroid Build Coastguard Worker
2591*5e7646d2SAndroid Build Coastguard Worker static void
ppd_free_filters(ppd_file_t * ppd)2592*5e7646d2SAndroid Build Coastguard Worker ppd_free_filters(ppd_file_t *ppd) /* I - PPD file */
2593*5e7646d2SAndroid Build Coastguard Worker {
2594*5e7646d2SAndroid Build Coastguard Worker int i; /* Looping var */
2595*5e7646d2SAndroid Build Coastguard Worker char **filter; /* Current filter */
2596*5e7646d2SAndroid Build Coastguard Worker
2597*5e7646d2SAndroid Build Coastguard Worker
2598*5e7646d2SAndroid Build Coastguard Worker if (ppd->num_filters > 0)
2599*5e7646d2SAndroid Build Coastguard Worker {
2600*5e7646d2SAndroid Build Coastguard Worker for (i = ppd->num_filters, filter = ppd->filters; i > 0; i --, filter ++)
2601*5e7646d2SAndroid Build Coastguard Worker free(*filter);
2602*5e7646d2SAndroid Build Coastguard Worker
2603*5e7646d2SAndroid Build Coastguard Worker free(ppd->filters);
2604*5e7646d2SAndroid Build Coastguard Worker
2605*5e7646d2SAndroid Build Coastguard Worker ppd->num_filters = 0;
2606*5e7646d2SAndroid Build Coastguard Worker ppd->filters = NULL;
2607*5e7646d2SAndroid Build Coastguard Worker }
2608*5e7646d2SAndroid Build Coastguard Worker }
2609*5e7646d2SAndroid Build Coastguard Worker
2610*5e7646d2SAndroid Build Coastguard Worker
2611*5e7646d2SAndroid Build Coastguard Worker /*
2612*5e7646d2SAndroid Build Coastguard Worker * 'ppd_free_group()' - Free a single UI group.
2613*5e7646d2SAndroid Build Coastguard Worker */
2614*5e7646d2SAndroid Build Coastguard Worker
2615*5e7646d2SAndroid Build Coastguard Worker static void
ppd_free_group(ppd_group_t * group)2616*5e7646d2SAndroid Build Coastguard Worker ppd_free_group(ppd_group_t *group) /* I - Group to free */
2617*5e7646d2SAndroid Build Coastguard Worker {
2618*5e7646d2SAndroid Build Coastguard Worker int i; /* Looping var */
2619*5e7646d2SAndroid Build Coastguard Worker ppd_option_t *option; /* Current option */
2620*5e7646d2SAndroid Build Coastguard Worker ppd_group_t *subgroup; /* Current sub-group */
2621*5e7646d2SAndroid Build Coastguard Worker
2622*5e7646d2SAndroid Build Coastguard Worker
2623*5e7646d2SAndroid Build Coastguard Worker if (group->num_options > 0)
2624*5e7646d2SAndroid Build Coastguard Worker {
2625*5e7646d2SAndroid Build Coastguard Worker for (i = group->num_options, option = group->options;
2626*5e7646d2SAndroid Build Coastguard Worker i > 0;
2627*5e7646d2SAndroid Build Coastguard Worker i --, option ++)
2628*5e7646d2SAndroid Build Coastguard Worker ppd_free_option(option);
2629*5e7646d2SAndroid Build Coastguard Worker
2630*5e7646d2SAndroid Build Coastguard Worker free(group->options);
2631*5e7646d2SAndroid Build Coastguard Worker }
2632*5e7646d2SAndroid Build Coastguard Worker
2633*5e7646d2SAndroid Build Coastguard Worker if (group->num_subgroups > 0)
2634*5e7646d2SAndroid Build Coastguard Worker {
2635*5e7646d2SAndroid Build Coastguard Worker for (i = group->num_subgroups, subgroup = group->subgroups;
2636*5e7646d2SAndroid Build Coastguard Worker i > 0;
2637*5e7646d2SAndroid Build Coastguard Worker i --, subgroup ++)
2638*5e7646d2SAndroid Build Coastguard Worker ppd_free_group(subgroup);
2639*5e7646d2SAndroid Build Coastguard Worker
2640*5e7646d2SAndroid Build Coastguard Worker free(group->subgroups);
2641*5e7646d2SAndroid Build Coastguard Worker }
2642*5e7646d2SAndroid Build Coastguard Worker }
2643*5e7646d2SAndroid Build Coastguard Worker
2644*5e7646d2SAndroid Build Coastguard Worker
2645*5e7646d2SAndroid Build Coastguard Worker /*
2646*5e7646d2SAndroid Build Coastguard Worker * 'ppd_free_option()' - Free a single option.
2647*5e7646d2SAndroid Build Coastguard Worker */
2648*5e7646d2SAndroid Build Coastguard Worker
2649*5e7646d2SAndroid Build Coastguard Worker static void
ppd_free_option(ppd_option_t * option)2650*5e7646d2SAndroid Build Coastguard Worker ppd_free_option(ppd_option_t *option) /* I - Option to free */
2651*5e7646d2SAndroid Build Coastguard Worker {
2652*5e7646d2SAndroid Build Coastguard Worker int i; /* Looping var */
2653*5e7646d2SAndroid Build Coastguard Worker ppd_choice_t *choice; /* Current choice */
2654*5e7646d2SAndroid Build Coastguard Worker
2655*5e7646d2SAndroid Build Coastguard Worker
2656*5e7646d2SAndroid Build Coastguard Worker if (option->num_choices > 0)
2657*5e7646d2SAndroid Build Coastguard Worker {
2658*5e7646d2SAndroid Build Coastguard Worker for (i = option->num_choices, choice = option->choices;
2659*5e7646d2SAndroid Build Coastguard Worker i > 0;
2660*5e7646d2SAndroid Build Coastguard Worker i --, choice ++)
2661*5e7646d2SAndroid Build Coastguard Worker {
2662*5e7646d2SAndroid Build Coastguard Worker free(choice->code);
2663*5e7646d2SAndroid Build Coastguard Worker }
2664*5e7646d2SAndroid Build Coastguard Worker
2665*5e7646d2SAndroid Build Coastguard Worker free(option->choices);
2666*5e7646d2SAndroid Build Coastguard Worker }
2667*5e7646d2SAndroid Build Coastguard Worker }
2668*5e7646d2SAndroid Build Coastguard Worker
2669*5e7646d2SAndroid Build Coastguard Worker
2670*5e7646d2SAndroid Build Coastguard Worker /*
2671*5e7646d2SAndroid Build Coastguard Worker * 'ppd_get_coption()' - Get a custom option record.
2672*5e7646d2SAndroid Build Coastguard Worker */
2673*5e7646d2SAndroid Build Coastguard Worker
2674*5e7646d2SAndroid Build Coastguard Worker static ppd_coption_t * /* O - Custom option... */
ppd_get_coption(ppd_file_t * ppd,const char * name)2675*5e7646d2SAndroid Build Coastguard Worker ppd_get_coption(ppd_file_t *ppd, /* I - PPD file */
2676*5e7646d2SAndroid Build Coastguard Worker const char *name) /* I - Name of option */
2677*5e7646d2SAndroid Build Coastguard Worker {
2678*5e7646d2SAndroid Build Coastguard Worker ppd_coption_t *copt; /* New custom option */
2679*5e7646d2SAndroid Build Coastguard Worker
2680*5e7646d2SAndroid Build Coastguard Worker
2681*5e7646d2SAndroid Build Coastguard Worker /*
2682*5e7646d2SAndroid Build Coastguard Worker * See if the option already exists...
2683*5e7646d2SAndroid Build Coastguard Worker */
2684*5e7646d2SAndroid Build Coastguard Worker
2685*5e7646d2SAndroid Build Coastguard Worker if ((copt = ppdFindCustomOption(ppd, name)) != NULL)
2686*5e7646d2SAndroid Build Coastguard Worker return (copt);
2687*5e7646d2SAndroid Build Coastguard Worker
2688*5e7646d2SAndroid Build Coastguard Worker /*
2689*5e7646d2SAndroid Build Coastguard Worker * Not found, so create the custom option record...
2690*5e7646d2SAndroid Build Coastguard Worker */
2691*5e7646d2SAndroid Build Coastguard Worker
2692*5e7646d2SAndroid Build Coastguard Worker if ((copt = calloc(1, sizeof(ppd_coption_t))) == NULL)
2693*5e7646d2SAndroid Build Coastguard Worker return (NULL);
2694*5e7646d2SAndroid Build Coastguard Worker
2695*5e7646d2SAndroid Build Coastguard Worker strlcpy(copt->keyword, name, sizeof(copt->keyword));
2696*5e7646d2SAndroid Build Coastguard Worker
2697*5e7646d2SAndroid Build Coastguard Worker copt->params = cupsArrayNew((cups_array_func_t)NULL, NULL);
2698*5e7646d2SAndroid Build Coastguard Worker
2699*5e7646d2SAndroid Build Coastguard Worker cupsArrayAdd(ppd->coptions, copt);
2700*5e7646d2SAndroid Build Coastguard Worker
2701*5e7646d2SAndroid Build Coastguard Worker /*
2702*5e7646d2SAndroid Build Coastguard Worker * Return the new record...
2703*5e7646d2SAndroid Build Coastguard Worker */
2704*5e7646d2SAndroid Build Coastguard Worker
2705*5e7646d2SAndroid Build Coastguard Worker return (copt);
2706*5e7646d2SAndroid Build Coastguard Worker }
2707*5e7646d2SAndroid Build Coastguard Worker
2708*5e7646d2SAndroid Build Coastguard Worker
2709*5e7646d2SAndroid Build Coastguard Worker /*
2710*5e7646d2SAndroid Build Coastguard Worker * 'ppd_get_cparam()' - Get a custom parameter record.
2711*5e7646d2SAndroid Build Coastguard Worker */
2712*5e7646d2SAndroid Build Coastguard Worker
2713*5e7646d2SAndroid Build Coastguard Worker static ppd_cparam_t * /* O - Extended option... */
ppd_get_cparam(ppd_coption_t * opt,const char * param,const char * text)2714*5e7646d2SAndroid Build Coastguard Worker ppd_get_cparam(ppd_coption_t *opt, /* I - PPD file */
2715*5e7646d2SAndroid Build Coastguard Worker const char *param, /* I - Name of parameter */
2716*5e7646d2SAndroid Build Coastguard Worker const char *text) /* I - Human-readable text */
2717*5e7646d2SAndroid Build Coastguard Worker {
2718*5e7646d2SAndroid Build Coastguard Worker ppd_cparam_t *cparam; /* New custom parameter */
2719*5e7646d2SAndroid Build Coastguard Worker
2720*5e7646d2SAndroid Build Coastguard Worker
2721*5e7646d2SAndroid Build Coastguard Worker /*
2722*5e7646d2SAndroid Build Coastguard Worker * See if the parameter already exists...
2723*5e7646d2SAndroid Build Coastguard Worker */
2724*5e7646d2SAndroid Build Coastguard Worker
2725*5e7646d2SAndroid Build Coastguard Worker if ((cparam = ppdFindCustomParam(opt, param)) != NULL)
2726*5e7646d2SAndroid Build Coastguard Worker return (cparam);
2727*5e7646d2SAndroid Build Coastguard Worker
2728*5e7646d2SAndroid Build Coastguard Worker /*
2729*5e7646d2SAndroid Build Coastguard Worker * Not found, so create the custom parameter record...
2730*5e7646d2SAndroid Build Coastguard Worker */
2731*5e7646d2SAndroid Build Coastguard Worker
2732*5e7646d2SAndroid Build Coastguard Worker if ((cparam = calloc(1, sizeof(ppd_cparam_t))) == NULL)
2733*5e7646d2SAndroid Build Coastguard Worker return (NULL);
2734*5e7646d2SAndroid Build Coastguard Worker
2735*5e7646d2SAndroid Build Coastguard Worker cparam->type = PPD_CUSTOM_UNKNOWN;
2736*5e7646d2SAndroid Build Coastguard Worker strlcpy(cparam->name, param, sizeof(cparam->name));
2737*5e7646d2SAndroid Build Coastguard Worker strlcpy(cparam->text, text[0] ? text : param, sizeof(cparam->text));
2738*5e7646d2SAndroid Build Coastguard Worker
2739*5e7646d2SAndroid Build Coastguard Worker /*
2740*5e7646d2SAndroid Build Coastguard Worker * Add this record to the array...
2741*5e7646d2SAndroid Build Coastguard Worker */
2742*5e7646d2SAndroid Build Coastguard Worker
2743*5e7646d2SAndroid Build Coastguard Worker cupsArrayAdd(opt->params, cparam);
2744*5e7646d2SAndroid Build Coastguard Worker
2745*5e7646d2SAndroid Build Coastguard Worker /*
2746*5e7646d2SAndroid Build Coastguard Worker * Return the new record...
2747*5e7646d2SAndroid Build Coastguard Worker */
2748*5e7646d2SAndroid Build Coastguard Worker
2749*5e7646d2SAndroid Build Coastguard Worker return (cparam);
2750*5e7646d2SAndroid Build Coastguard Worker }
2751*5e7646d2SAndroid Build Coastguard Worker
2752*5e7646d2SAndroid Build Coastguard Worker
2753*5e7646d2SAndroid Build Coastguard Worker /*
2754*5e7646d2SAndroid Build Coastguard Worker * 'ppd_get_group()' - Find or create the named group as needed.
2755*5e7646d2SAndroid Build Coastguard Worker */
2756*5e7646d2SAndroid Build Coastguard Worker
2757*5e7646d2SAndroid Build Coastguard Worker static ppd_group_t * /* O - Named group */
ppd_get_group(ppd_file_t * ppd,const char * name,const char * text,_ppd_globals_t * pg,cups_encoding_t encoding)2758*5e7646d2SAndroid Build Coastguard Worker ppd_get_group(ppd_file_t *ppd, /* I - PPD file */
2759*5e7646d2SAndroid Build Coastguard Worker const char *name, /* I - Name of group */
2760*5e7646d2SAndroid Build Coastguard Worker const char *text, /* I - Text for group */
2761*5e7646d2SAndroid Build Coastguard Worker _ppd_globals_t *pg, /* I - Global data */
2762*5e7646d2SAndroid Build Coastguard Worker cups_encoding_t encoding) /* I - Encoding of text */
2763*5e7646d2SAndroid Build Coastguard Worker {
2764*5e7646d2SAndroid Build Coastguard Worker int i; /* Looping var */
2765*5e7646d2SAndroid Build Coastguard Worker ppd_group_t *group; /* Group */
2766*5e7646d2SAndroid Build Coastguard Worker
2767*5e7646d2SAndroid Build Coastguard Worker
2768*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("7ppd_get_group(ppd=%p, name=\"%s\", text=\"%s\", cg=%p)",
2769*5e7646d2SAndroid Build Coastguard Worker ppd, name, text, pg));
2770*5e7646d2SAndroid Build Coastguard Worker
2771*5e7646d2SAndroid Build Coastguard Worker for (i = ppd->num_groups, group = ppd->groups; i > 0; i --, group ++)
2772*5e7646d2SAndroid Build Coastguard Worker if (!strcmp(group->name, name))
2773*5e7646d2SAndroid Build Coastguard Worker break;
2774*5e7646d2SAndroid Build Coastguard Worker
2775*5e7646d2SAndroid Build Coastguard Worker if (i == 0)
2776*5e7646d2SAndroid Build Coastguard Worker {
2777*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("8ppd_get_group: Adding group %s...", name));
2778*5e7646d2SAndroid Build Coastguard Worker
2779*5e7646d2SAndroid Build Coastguard Worker if (pg->ppd_conform == PPD_CONFORM_STRICT && strlen(text) >= sizeof(group->text))
2780*5e7646d2SAndroid Build Coastguard Worker {
2781*5e7646d2SAndroid Build Coastguard Worker pg->ppd_status = PPD_ILLEGAL_TRANSLATION;
2782*5e7646d2SAndroid Build Coastguard Worker
2783*5e7646d2SAndroid Build Coastguard Worker return (NULL);
2784*5e7646d2SAndroid Build Coastguard Worker }
2785*5e7646d2SAndroid Build Coastguard Worker
2786*5e7646d2SAndroid Build Coastguard Worker if (ppd->num_groups == 0)
2787*5e7646d2SAndroid Build Coastguard Worker group = malloc(sizeof(ppd_group_t));
2788*5e7646d2SAndroid Build Coastguard Worker else
2789*5e7646d2SAndroid Build Coastguard Worker group = realloc(ppd->groups, (size_t)(ppd->num_groups + 1) * sizeof(ppd_group_t));
2790*5e7646d2SAndroid Build Coastguard Worker
2791*5e7646d2SAndroid Build Coastguard Worker if (group == NULL)
2792*5e7646d2SAndroid Build Coastguard Worker {
2793*5e7646d2SAndroid Build Coastguard Worker pg->ppd_status = PPD_ALLOC_ERROR;
2794*5e7646d2SAndroid Build Coastguard Worker
2795*5e7646d2SAndroid Build Coastguard Worker return (NULL);
2796*5e7646d2SAndroid Build Coastguard Worker }
2797*5e7646d2SAndroid Build Coastguard Worker
2798*5e7646d2SAndroid Build Coastguard Worker ppd->groups = group;
2799*5e7646d2SAndroid Build Coastguard Worker group += ppd->num_groups;
2800*5e7646d2SAndroid Build Coastguard Worker ppd->num_groups ++;
2801*5e7646d2SAndroid Build Coastguard Worker
2802*5e7646d2SAndroid Build Coastguard Worker memset(group, 0, sizeof(ppd_group_t));
2803*5e7646d2SAndroid Build Coastguard Worker strlcpy(group->name, name, sizeof(group->name));
2804*5e7646d2SAndroid Build Coastguard Worker
2805*5e7646d2SAndroid Build Coastguard Worker cupsCharsetToUTF8((cups_utf8_t *)group->text, text,
2806*5e7646d2SAndroid Build Coastguard Worker sizeof(group->text), encoding);
2807*5e7646d2SAndroid Build Coastguard Worker }
2808*5e7646d2SAndroid Build Coastguard Worker
2809*5e7646d2SAndroid Build Coastguard Worker return (group);
2810*5e7646d2SAndroid Build Coastguard Worker }
2811*5e7646d2SAndroid Build Coastguard Worker
2812*5e7646d2SAndroid Build Coastguard Worker
2813*5e7646d2SAndroid Build Coastguard Worker /*
2814*5e7646d2SAndroid Build Coastguard Worker * 'ppd_get_option()' - Find or create the named option as needed.
2815*5e7646d2SAndroid Build Coastguard Worker */
2816*5e7646d2SAndroid Build Coastguard Worker
2817*5e7646d2SAndroid Build Coastguard Worker static ppd_option_t * /* O - Named option */
ppd_get_option(ppd_group_t * group,const char * name)2818*5e7646d2SAndroid Build Coastguard Worker ppd_get_option(ppd_group_t *group, /* I - Group */
2819*5e7646d2SAndroid Build Coastguard Worker const char *name) /* I - Name of option */
2820*5e7646d2SAndroid Build Coastguard Worker {
2821*5e7646d2SAndroid Build Coastguard Worker int i; /* Looping var */
2822*5e7646d2SAndroid Build Coastguard Worker ppd_option_t *option; /* Option */
2823*5e7646d2SAndroid Build Coastguard Worker
2824*5e7646d2SAndroid Build Coastguard Worker
2825*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("7ppd_get_option(group=%p(\"%s\"), name=\"%s\")",
2826*5e7646d2SAndroid Build Coastguard Worker group, group->name, name));
2827*5e7646d2SAndroid Build Coastguard Worker
2828*5e7646d2SAndroid Build Coastguard Worker for (i = group->num_options, option = group->options; i > 0; i --, option ++)
2829*5e7646d2SAndroid Build Coastguard Worker if (!strcmp(option->keyword, name))
2830*5e7646d2SAndroid Build Coastguard Worker break;
2831*5e7646d2SAndroid Build Coastguard Worker
2832*5e7646d2SAndroid Build Coastguard Worker if (i == 0)
2833*5e7646d2SAndroid Build Coastguard Worker {
2834*5e7646d2SAndroid Build Coastguard Worker if (group->num_options == 0)
2835*5e7646d2SAndroid Build Coastguard Worker option = malloc(sizeof(ppd_option_t));
2836*5e7646d2SAndroid Build Coastguard Worker else
2837*5e7646d2SAndroid Build Coastguard Worker option = realloc(group->options, (size_t)(group->num_options + 1) * sizeof(ppd_option_t));
2838*5e7646d2SAndroid Build Coastguard Worker
2839*5e7646d2SAndroid Build Coastguard Worker if (option == NULL)
2840*5e7646d2SAndroid Build Coastguard Worker return (NULL);
2841*5e7646d2SAndroid Build Coastguard Worker
2842*5e7646d2SAndroid Build Coastguard Worker group->options = option;
2843*5e7646d2SAndroid Build Coastguard Worker option += group->num_options;
2844*5e7646d2SAndroid Build Coastguard Worker group->num_options ++;
2845*5e7646d2SAndroid Build Coastguard Worker
2846*5e7646d2SAndroid Build Coastguard Worker memset(option, 0, sizeof(ppd_option_t));
2847*5e7646d2SAndroid Build Coastguard Worker strlcpy(option->keyword, name, sizeof(option->keyword));
2848*5e7646d2SAndroid Build Coastguard Worker }
2849*5e7646d2SAndroid Build Coastguard Worker
2850*5e7646d2SAndroid Build Coastguard Worker return (option);
2851*5e7646d2SAndroid Build Coastguard Worker }
2852*5e7646d2SAndroid Build Coastguard Worker
2853*5e7646d2SAndroid Build Coastguard Worker
2854*5e7646d2SAndroid Build Coastguard Worker /*
2855*5e7646d2SAndroid Build Coastguard Worker * 'ppd_globals_alloc()' - Allocate and initialize global data.
2856*5e7646d2SAndroid Build Coastguard Worker */
2857*5e7646d2SAndroid Build Coastguard Worker
2858*5e7646d2SAndroid Build Coastguard Worker static _ppd_globals_t * /* O - Pointer to global data */
ppd_globals_alloc(void)2859*5e7646d2SAndroid Build Coastguard Worker ppd_globals_alloc(void)
2860*5e7646d2SAndroid Build Coastguard Worker {
2861*5e7646d2SAndroid Build Coastguard Worker return ((_ppd_globals_t *)calloc(1, sizeof(_ppd_globals_t)));
2862*5e7646d2SAndroid Build Coastguard Worker }
2863*5e7646d2SAndroid Build Coastguard Worker
2864*5e7646d2SAndroid Build Coastguard Worker
2865*5e7646d2SAndroid Build Coastguard Worker /*
2866*5e7646d2SAndroid Build Coastguard Worker * 'ppd_globals_free()' - Free global data.
2867*5e7646d2SAndroid Build Coastguard Worker */
2868*5e7646d2SAndroid Build Coastguard Worker
2869*5e7646d2SAndroid Build Coastguard Worker #if defined(HAVE_PTHREAD_H) || defined(_WIN32)
2870*5e7646d2SAndroid Build Coastguard Worker static void
ppd_globals_free(_ppd_globals_t * pg)2871*5e7646d2SAndroid Build Coastguard Worker ppd_globals_free(_ppd_globals_t *pg) /* I - Pointer to global data */
2872*5e7646d2SAndroid Build Coastguard Worker {
2873*5e7646d2SAndroid Build Coastguard Worker free(pg);
2874*5e7646d2SAndroid Build Coastguard Worker }
2875*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_PTHREAD_H || _WIN32 */
2876*5e7646d2SAndroid Build Coastguard Worker
2877*5e7646d2SAndroid Build Coastguard Worker
2878*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_PTHREAD_H
2879*5e7646d2SAndroid Build Coastguard Worker /*
2880*5e7646d2SAndroid Build Coastguard Worker * 'ppd_globals_init()' - Initialize per-thread globals...
2881*5e7646d2SAndroid Build Coastguard Worker */
2882*5e7646d2SAndroid Build Coastguard Worker
2883*5e7646d2SAndroid Build Coastguard Worker static void
ppd_globals_init(void)2884*5e7646d2SAndroid Build Coastguard Worker ppd_globals_init(void)
2885*5e7646d2SAndroid Build Coastguard Worker {
2886*5e7646d2SAndroid Build Coastguard Worker /*
2887*5e7646d2SAndroid Build Coastguard Worker * Register the global data for this thread...
2888*5e7646d2SAndroid Build Coastguard Worker */
2889*5e7646d2SAndroid Build Coastguard Worker
2890*5e7646d2SAndroid Build Coastguard Worker pthread_key_create(&ppd_globals_key, (void (*)(void *))ppd_globals_free);
2891*5e7646d2SAndroid Build Coastguard Worker }
2892*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_PTHREAD_H */
2893*5e7646d2SAndroid Build Coastguard Worker
2894*5e7646d2SAndroid Build Coastguard Worker
2895*5e7646d2SAndroid Build Coastguard Worker /*
2896*5e7646d2SAndroid Build Coastguard Worker * 'ppd_hash_option()' - Generate a hash of the option name...
2897*5e7646d2SAndroid Build Coastguard Worker */
2898*5e7646d2SAndroid Build Coastguard Worker
2899*5e7646d2SAndroid Build Coastguard Worker static int /* O - Hash index */
ppd_hash_option(ppd_option_t * option)2900*5e7646d2SAndroid Build Coastguard Worker ppd_hash_option(ppd_option_t *option) /* I - Option */
2901*5e7646d2SAndroid Build Coastguard Worker {
2902*5e7646d2SAndroid Build Coastguard Worker int hash = 0; /* Hash index */
2903*5e7646d2SAndroid Build Coastguard Worker const char *k; /* Pointer into keyword */
2904*5e7646d2SAndroid Build Coastguard Worker
2905*5e7646d2SAndroid Build Coastguard Worker
2906*5e7646d2SAndroid Build Coastguard Worker for (hash = option->keyword[0], k = option->keyword + 1; *k;)
2907*5e7646d2SAndroid Build Coastguard Worker hash = (int)(33U * (unsigned)hash) + *k++;
2908*5e7646d2SAndroid Build Coastguard Worker
2909*5e7646d2SAndroid Build Coastguard Worker return (hash & 511);
2910*5e7646d2SAndroid Build Coastguard Worker }
2911*5e7646d2SAndroid Build Coastguard Worker
2912*5e7646d2SAndroid Build Coastguard Worker
2913*5e7646d2SAndroid Build Coastguard Worker /*
2914*5e7646d2SAndroid Build Coastguard Worker * 'ppd_read()' - Read a line from a PPD file, skipping comment lines as
2915*5e7646d2SAndroid Build Coastguard Worker * necessary.
2916*5e7646d2SAndroid Build Coastguard Worker */
2917*5e7646d2SAndroid Build Coastguard Worker
2918*5e7646d2SAndroid Build Coastguard Worker static int /* O - Bitmask of fields read */
ppd_read(cups_file_t * fp,_ppd_line_t * line,char * keyword,char * option,char * text,char ** string,int ignoreblank,_ppd_globals_t * pg)2919*5e7646d2SAndroid Build Coastguard Worker ppd_read(cups_file_t *fp, /* I - File to read from */
2920*5e7646d2SAndroid Build Coastguard Worker _ppd_line_t *line, /* I - Line buffer */
2921*5e7646d2SAndroid Build Coastguard Worker char *keyword, /* O - Keyword from line */
2922*5e7646d2SAndroid Build Coastguard Worker char *option, /* O - Option from line */
2923*5e7646d2SAndroid Build Coastguard Worker char *text, /* O - Human-readable text from line */
2924*5e7646d2SAndroid Build Coastguard Worker char **string, /* O - Code/string data */
2925*5e7646d2SAndroid Build Coastguard Worker int ignoreblank, /* I - Ignore blank lines? */
2926*5e7646d2SAndroid Build Coastguard Worker _ppd_globals_t *pg) /* I - Global data */
2927*5e7646d2SAndroid Build Coastguard Worker {
2928*5e7646d2SAndroid Build Coastguard Worker int ch, /* Character from file */
2929*5e7646d2SAndroid Build Coastguard Worker col, /* Column in line */
2930*5e7646d2SAndroid Build Coastguard Worker colon, /* Colon seen? */
2931*5e7646d2SAndroid Build Coastguard Worker endquote, /* Waiting for an end quote */
2932*5e7646d2SAndroid Build Coastguard Worker mask, /* Mask to be returned */
2933*5e7646d2SAndroid Build Coastguard Worker startline, /* Start line */
2934*5e7646d2SAndroid Build Coastguard Worker textlen; /* Length of text */
2935*5e7646d2SAndroid Build Coastguard Worker char *keyptr, /* Keyword pointer */
2936*5e7646d2SAndroid Build Coastguard Worker *optptr, /* Option pointer */
2937*5e7646d2SAndroid Build Coastguard Worker *textptr, /* Text pointer */
2938*5e7646d2SAndroid Build Coastguard Worker *strptr, /* Pointer into string */
2939*5e7646d2SAndroid Build Coastguard Worker *lineptr; /* Current position in line buffer */
2940*5e7646d2SAndroid Build Coastguard Worker
2941*5e7646d2SAndroid Build Coastguard Worker
2942*5e7646d2SAndroid Build Coastguard Worker /*
2943*5e7646d2SAndroid Build Coastguard Worker * Now loop until we have a valid line...
2944*5e7646d2SAndroid Build Coastguard Worker */
2945*5e7646d2SAndroid Build Coastguard Worker
2946*5e7646d2SAndroid Build Coastguard Worker *string = NULL;
2947*5e7646d2SAndroid Build Coastguard Worker col = 0;
2948*5e7646d2SAndroid Build Coastguard Worker startline = pg->ppd_line + 1;
2949*5e7646d2SAndroid Build Coastguard Worker
2950*5e7646d2SAndroid Build Coastguard Worker if (!line->buffer)
2951*5e7646d2SAndroid Build Coastguard Worker {
2952*5e7646d2SAndroid Build Coastguard Worker line->bufsize = 1024;
2953*5e7646d2SAndroid Build Coastguard Worker line->buffer = malloc(1024);
2954*5e7646d2SAndroid Build Coastguard Worker
2955*5e7646d2SAndroid Build Coastguard Worker if (!line->buffer)
2956*5e7646d2SAndroid Build Coastguard Worker return (0);
2957*5e7646d2SAndroid Build Coastguard Worker }
2958*5e7646d2SAndroid Build Coastguard Worker
2959*5e7646d2SAndroid Build Coastguard Worker do
2960*5e7646d2SAndroid Build Coastguard Worker {
2961*5e7646d2SAndroid Build Coastguard Worker /*
2962*5e7646d2SAndroid Build Coastguard Worker * Read the line...
2963*5e7646d2SAndroid Build Coastguard Worker */
2964*5e7646d2SAndroid Build Coastguard Worker
2965*5e7646d2SAndroid Build Coastguard Worker lineptr = line->buffer;
2966*5e7646d2SAndroid Build Coastguard Worker endquote = 0;
2967*5e7646d2SAndroid Build Coastguard Worker colon = 0;
2968*5e7646d2SAndroid Build Coastguard Worker
2969*5e7646d2SAndroid Build Coastguard Worker while ((ch = cupsFileGetChar(fp)) != EOF)
2970*5e7646d2SAndroid Build Coastguard Worker {
2971*5e7646d2SAndroid Build Coastguard Worker if (lineptr >= (line->buffer + line->bufsize - 1))
2972*5e7646d2SAndroid Build Coastguard Worker {
2973*5e7646d2SAndroid Build Coastguard Worker /*
2974*5e7646d2SAndroid Build Coastguard Worker * Expand the line buffer...
2975*5e7646d2SAndroid Build Coastguard Worker */
2976*5e7646d2SAndroid Build Coastguard Worker
2977*5e7646d2SAndroid Build Coastguard Worker char *temp; /* Temporary line pointer */
2978*5e7646d2SAndroid Build Coastguard Worker
2979*5e7646d2SAndroid Build Coastguard Worker
2980*5e7646d2SAndroid Build Coastguard Worker line->bufsize += 1024;
2981*5e7646d2SAndroid Build Coastguard Worker if (line->bufsize > 262144)
2982*5e7646d2SAndroid Build Coastguard Worker {
2983*5e7646d2SAndroid Build Coastguard Worker /*
2984*5e7646d2SAndroid Build Coastguard Worker * Don't allow lines longer than 256k!
2985*5e7646d2SAndroid Build Coastguard Worker */
2986*5e7646d2SAndroid Build Coastguard Worker
2987*5e7646d2SAndroid Build Coastguard Worker pg->ppd_line = startline;
2988*5e7646d2SAndroid Build Coastguard Worker pg->ppd_status = PPD_LINE_TOO_LONG;
2989*5e7646d2SAndroid Build Coastguard Worker
2990*5e7646d2SAndroid Build Coastguard Worker return (0);
2991*5e7646d2SAndroid Build Coastguard Worker }
2992*5e7646d2SAndroid Build Coastguard Worker
2993*5e7646d2SAndroid Build Coastguard Worker temp = realloc(line->buffer, line->bufsize);
2994*5e7646d2SAndroid Build Coastguard Worker if (!temp)
2995*5e7646d2SAndroid Build Coastguard Worker {
2996*5e7646d2SAndroid Build Coastguard Worker pg->ppd_line = startline;
2997*5e7646d2SAndroid Build Coastguard Worker pg->ppd_status = PPD_LINE_TOO_LONG;
2998*5e7646d2SAndroid Build Coastguard Worker
2999*5e7646d2SAndroid Build Coastguard Worker return (0);
3000*5e7646d2SAndroid Build Coastguard Worker }
3001*5e7646d2SAndroid Build Coastguard Worker
3002*5e7646d2SAndroid Build Coastguard Worker lineptr = temp + (lineptr - line->buffer);
3003*5e7646d2SAndroid Build Coastguard Worker line->buffer = temp;
3004*5e7646d2SAndroid Build Coastguard Worker }
3005*5e7646d2SAndroid Build Coastguard Worker
3006*5e7646d2SAndroid Build Coastguard Worker if (ch == '\r' || ch == '\n')
3007*5e7646d2SAndroid Build Coastguard Worker {
3008*5e7646d2SAndroid Build Coastguard Worker /*
3009*5e7646d2SAndroid Build Coastguard Worker * Line feed or carriage return...
3010*5e7646d2SAndroid Build Coastguard Worker */
3011*5e7646d2SAndroid Build Coastguard Worker
3012*5e7646d2SAndroid Build Coastguard Worker pg->ppd_line ++;
3013*5e7646d2SAndroid Build Coastguard Worker col = 0;
3014*5e7646d2SAndroid Build Coastguard Worker
3015*5e7646d2SAndroid Build Coastguard Worker if (ch == '\r')
3016*5e7646d2SAndroid Build Coastguard Worker {
3017*5e7646d2SAndroid Build Coastguard Worker /*
3018*5e7646d2SAndroid Build Coastguard Worker * Check for a trailing line feed...
3019*5e7646d2SAndroid Build Coastguard Worker */
3020*5e7646d2SAndroid Build Coastguard Worker
3021*5e7646d2SAndroid Build Coastguard Worker if ((ch = cupsFilePeekChar(fp)) == EOF)
3022*5e7646d2SAndroid Build Coastguard Worker {
3023*5e7646d2SAndroid Build Coastguard Worker ch = '\n';
3024*5e7646d2SAndroid Build Coastguard Worker break;
3025*5e7646d2SAndroid Build Coastguard Worker }
3026*5e7646d2SAndroid Build Coastguard Worker
3027*5e7646d2SAndroid Build Coastguard Worker if (ch == 0x0a)
3028*5e7646d2SAndroid Build Coastguard Worker cupsFileGetChar(fp);
3029*5e7646d2SAndroid Build Coastguard Worker }
3030*5e7646d2SAndroid Build Coastguard Worker
3031*5e7646d2SAndroid Build Coastguard Worker if (lineptr == line->buffer && ignoreblank)
3032*5e7646d2SAndroid Build Coastguard Worker continue; /* Skip blank lines */
3033*5e7646d2SAndroid Build Coastguard Worker
3034*5e7646d2SAndroid Build Coastguard Worker ch = '\n';
3035*5e7646d2SAndroid Build Coastguard Worker
3036*5e7646d2SAndroid Build Coastguard Worker if (!endquote) /* Continue for multi-line text */
3037*5e7646d2SAndroid Build Coastguard Worker break;
3038*5e7646d2SAndroid Build Coastguard Worker
3039*5e7646d2SAndroid Build Coastguard Worker *lineptr++ = '\n';
3040*5e7646d2SAndroid Build Coastguard Worker }
3041*5e7646d2SAndroid Build Coastguard Worker else if (ch < ' ' && ch != '\t' && pg->ppd_conform == PPD_CONFORM_STRICT)
3042*5e7646d2SAndroid Build Coastguard Worker {
3043*5e7646d2SAndroid Build Coastguard Worker /*
3044*5e7646d2SAndroid Build Coastguard Worker * Other control characters...
3045*5e7646d2SAndroid Build Coastguard Worker */
3046*5e7646d2SAndroid Build Coastguard Worker
3047*5e7646d2SAndroid Build Coastguard Worker pg->ppd_line = startline;
3048*5e7646d2SAndroid Build Coastguard Worker pg->ppd_status = PPD_ILLEGAL_CHARACTER;
3049*5e7646d2SAndroid Build Coastguard Worker
3050*5e7646d2SAndroid Build Coastguard Worker return (0);
3051*5e7646d2SAndroid Build Coastguard Worker }
3052*5e7646d2SAndroid Build Coastguard Worker else if (ch != 0x1a)
3053*5e7646d2SAndroid Build Coastguard Worker {
3054*5e7646d2SAndroid Build Coastguard Worker /*
3055*5e7646d2SAndroid Build Coastguard Worker * Any other character...
3056*5e7646d2SAndroid Build Coastguard Worker */
3057*5e7646d2SAndroid Build Coastguard Worker
3058*5e7646d2SAndroid Build Coastguard Worker *lineptr++ = (char)ch;
3059*5e7646d2SAndroid Build Coastguard Worker col ++;
3060*5e7646d2SAndroid Build Coastguard Worker
3061*5e7646d2SAndroid Build Coastguard Worker if (col > (PPD_MAX_LINE - 1))
3062*5e7646d2SAndroid Build Coastguard Worker {
3063*5e7646d2SAndroid Build Coastguard Worker /*
3064*5e7646d2SAndroid Build Coastguard Worker * Line is too long...
3065*5e7646d2SAndroid Build Coastguard Worker */
3066*5e7646d2SAndroid Build Coastguard Worker
3067*5e7646d2SAndroid Build Coastguard Worker pg->ppd_line = startline;
3068*5e7646d2SAndroid Build Coastguard Worker pg->ppd_status = PPD_LINE_TOO_LONG;
3069*5e7646d2SAndroid Build Coastguard Worker
3070*5e7646d2SAndroid Build Coastguard Worker return (0);
3071*5e7646d2SAndroid Build Coastguard Worker }
3072*5e7646d2SAndroid Build Coastguard Worker
3073*5e7646d2SAndroid Build Coastguard Worker if (ch == ':' && strncmp(line->buffer, "*%", 2) != 0)
3074*5e7646d2SAndroid Build Coastguard Worker colon = 1;
3075*5e7646d2SAndroid Build Coastguard Worker
3076*5e7646d2SAndroid Build Coastguard Worker if (ch == '\"' && colon)
3077*5e7646d2SAndroid Build Coastguard Worker endquote = !endquote;
3078*5e7646d2SAndroid Build Coastguard Worker }
3079*5e7646d2SAndroid Build Coastguard Worker }
3080*5e7646d2SAndroid Build Coastguard Worker
3081*5e7646d2SAndroid Build Coastguard Worker if (endquote)
3082*5e7646d2SAndroid Build Coastguard Worker {
3083*5e7646d2SAndroid Build Coastguard Worker /*
3084*5e7646d2SAndroid Build Coastguard Worker * Didn't finish this quoted string...
3085*5e7646d2SAndroid Build Coastguard Worker */
3086*5e7646d2SAndroid Build Coastguard Worker
3087*5e7646d2SAndroid Build Coastguard Worker while ((ch = cupsFileGetChar(fp)) != EOF)
3088*5e7646d2SAndroid Build Coastguard Worker if (ch == '\"')
3089*5e7646d2SAndroid Build Coastguard Worker break;
3090*5e7646d2SAndroid Build Coastguard Worker else if (ch == '\r' || ch == '\n')
3091*5e7646d2SAndroid Build Coastguard Worker {
3092*5e7646d2SAndroid Build Coastguard Worker pg->ppd_line ++;
3093*5e7646d2SAndroid Build Coastguard Worker col = 0;
3094*5e7646d2SAndroid Build Coastguard Worker
3095*5e7646d2SAndroid Build Coastguard Worker if (ch == '\r')
3096*5e7646d2SAndroid Build Coastguard Worker {
3097*5e7646d2SAndroid Build Coastguard Worker /*
3098*5e7646d2SAndroid Build Coastguard Worker * Check for a trailing line feed...
3099*5e7646d2SAndroid Build Coastguard Worker */
3100*5e7646d2SAndroid Build Coastguard Worker
3101*5e7646d2SAndroid Build Coastguard Worker if ((ch = cupsFilePeekChar(fp)) == EOF)
3102*5e7646d2SAndroid Build Coastguard Worker break;
3103*5e7646d2SAndroid Build Coastguard Worker if (ch == 0x0a)
3104*5e7646d2SAndroid Build Coastguard Worker cupsFileGetChar(fp);
3105*5e7646d2SAndroid Build Coastguard Worker }
3106*5e7646d2SAndroid Build Coastguard Worker }
3107*5e7646d2SAndroid Build Coastguard Worker else if (ch < ' ' && ch != '\t' && pg->ppd_conform == PPD_CONFORM_STRICT)
3108*5e7646d2SAndroid Build Coastguard Worker {
3109*5e7646d2SAndroid Build Coastguard Worker /*
3110*5e7646d2SAndroid Build Coastguard Worker * Other control characters...
3111*5e7646d2SAndroid Build Coastguard Worker */
3112*5e7646d2SAndroid Build Coastguard Worker
3113*5e7646d2SAndroid Build Coastguard Worker pg->ppd_line = startline;
3114*5e7646d2SAndroid Build Coastguard Worker pg->ppd_status = PPD_ILLEGAL_CHARACTER;
3115*5e7646d2SAndroid Build Coastguard Worker
3116*5e7646d2SAndroid Build Coastguard Worker return (0);
3117*5e7646d2SAndroid Build Coastguard Worker }
3118*5e7646d2SAndroid Build Coastguard Worker else if (ch != 0x1a)
3119*5e7646d2SAndroid Build Coastguard Worker {
3120*5e7646d2SAndroid Build Coastguard Worker col ++;
3121*5e7646d2SAndroid Build Coastguard Worker
3122*5e7646d2SAndroid Build Coastguard Worker if (col > (PPD_MAX_LINE - 1))
3123*5e7646d2SAndroid Build Coastguard Worker {
3124*5e7646d2SAndroid Build Coastguard Worker /*
3125*5e7646d2SAndroid Build Coastguard Worker * Line is too long...
3126*5e7646d2SAndroid Build Coastguard Worker */
3127*5e7646d2SAndroid Build Coastguard Worker
3128*5e7646d2SAndroid Build Coastguard Worker pg->ppd_line = startline;
3129*5e7646d2SAndroid Build Coastguard Worker pg->ppd_status = PPD_LINE_TOO_LONG;
3130*5e7646d2SAndroid Build Coastguard Worker
3131*5e7646d2SAndroid Build Coastguard Worker return (0);
3132*5e7646d2SAndroid Build Coastguard Worker }
3133*5e7646d2SAndroid Build Coastguard Worker }
3134*5e7646d2SAndroid Build Coastguard Worker }
3135*5e7646d2SAndroid Build Coastguard Worker
3136*5e7646d2SAndroid Build Coastguard Worker if (ch != '\n')
3137*5e7646d2SAndroid Build Coastguard Worker {
3138*5e7646d2SAndroid Build Coastguard Worker /*
3139*5e7646d2SAndroid Build Coastguard Worker * Didn't finish this line...
3140*5e7646d2SAndroid Build Coastguard Worker */
3141*5e7646d2SAndroid Build Coastguard Worker
3142*5e7646d2SAndroid Build Coastguard Worker while ((ch = cupsFileGetChar(fp)) != EOF)
3143*5e7646d2SAndroid Build Coastguard Worker if (ch == '\r' || ch == '\n')
3144*5e7646d2SAndroid Build Coastguard Worker {
3145*5e7646d2SAndroid Build Coastguard Worker /*
3146*5e7646d2SAndroid Build Coastguard Worker * Line feed or carriage return...
3147*5e7646d2SAndroid Build Coastguard Worker */
3148*5e7646d2SAndroid Build Coastguard Worker
3149*5e7646d2SAndroid Build Coastguard Worker pg->ppd_line ++;
3150*5e7646d2SAndroid Build Coastguard Worker col = 0;
3151*5e7646d2SAndroid Build Coastguard Worker
3152*5e7646d2SAndroid Build Coastguard Worker if (ch == '\r')
3153*5e7646d2SAndroid Build Coastguard Worker {
3154*5e7646d2SAndroid Build Coastguard Worker /*
3155*5e7646d2SAndroid Build Coastguard Worker * Check for a trailing line feed...
3156*5e7646d2SAndroid Build Coastguard Worker */
3157*5e7646d2SAndroid Build Coastguard Worker
3158*5e7646d2SAndroid Build Coastguard Worker if ((ch = cupsFilePeekChar(fp)) == EOF)
3159*5e7646d2SAndroid Build Coastguard Worker break;
3160*5e7646d2SAndroid Build Coastguard Worker if (ch == 0x0a)
3161*5e7646d2SAndroid Build Coastguard Worker cupsFileGetChar(fp);
3162*5e7646d2SAndroid Build Coastguard Worker }
3163*5e7646d2SAndroid Build Coastguard Worker
3164*5e7646d2SAndroid Build Coastguard Worker break;
3165*5e7646d2SAndroid Build Coastguard Worker }
3166*5e7646d2SAndroid Build Coastguard Worker else if (ch < ' ' && ch != '\t' && pg->ppd_conform == PPD_CONFORM_STRICT)
3167*5e7646d2SAndroid Build Coastguard Worker {
3168*5e7646d2SAndroid Build Coastguard Worker /*
3169*5e7646d2SAndroid Build Coastguard Worker * Other control characters...
3170*5e7646d2SAndroid Build Coastguard Worker */
3171*5e7646d2SAndroid Build Coastguard Worker
3172*5e7646d2SAndroid Build Coastguard Worker pg->ppd_line = startline;
3173*5e7646d2SAndroid Build Coastguard Worker pg->ppd_status = PPD_ILLEGAL_CHARACTER;
3174*5e7646d2SAndroid Build Coastguard Worker
3175*5e7646d2SAndroid Build Coastguard Worker return (0);
3176*5e7646d2SAndroid Build Coastguard Worker }
3177*5e7646d2SAndroid Build Coastguard Worker else if (ch != 0x1a)
3178*5e7646d2SAndroid Build Coastguard Worker {
3179*5e7646d2SAndroid Build Coastguard Worker col ++;
3180*5e7646d2SAndroid Build Coastguard Worker
3181*5e7646d2SAndroid Build Coastguard Worker if (col > (PPD_MAX_LINE - 1))
3182*5e7646d2SAndroid Build Coastguard Worker {
3183*5e7646d2SAndroid Build Coastguard Worker /*
3184*5e7646d2SAndroid Build Coastguard Worker * Line is too long...
3185*5e7646d2SAndroid Build Coastguard Worker */
3186*5e7646d2SAndroid Build Coastguard Worker
3187*5e7646d2SAndroid Build Coastguard Worker pg->ppd_line = startline;
3188*5e7646d2SAndroid Build Coastguard Worker pg->ppd_status = PPD_LINE_TOO_LONG;
3189*5e7646d2SAndroid Build Coastguard Worker
3190*5e7646d2SAndroid Build Coastguard Worker return (0);
3191*5e7646d2SAndroid Build Coastguard Worker }
3192*5e7646d2SAndroid Build Coastguard Worker }
3193*5e7646d2SAndroid Build Coastguard Worker }
3194*5e7646d2SAndroid Build Coastguard Worker
3195*5e7646d2SAndroid Build Coastguard Worker if (lineptr > line->buffer && lineptr[-1] == '\n')
3196*5e7646d2SAndroid Build Coastguard Worker lineptr --;
3197*5e7646d2SAndroid Build Coastguard Worker
3198*5e7646d2SAndroid Build Coastguard Worker *lineptr = '\0';
3199*5e7646d2SAndroid Build Coastguard Worker
3200*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("9ppd_read: LINE=\"%s\"", line->buffer));
3201*5e7646d2SAndroid Build Coastguard Worker
3202*5e7646d2SAndroid Build Coastguard Worker /*
3203*5e7646d2SAndroid Build Coastguard Worker * The dynamically created PPDs for older style macOS
3204*5e7646d2SAndroid Build Coastguard Worker * drivers include a large blob of data inserted as comments
3205*5e7646d2SAndroid Build Coastguard Worker * at the end of the file. As an optimization we can stop
3206*5e7646d2SAndroid Build Coastguard Worker * reading the PPD when we get to the start of this data.
3207*5e7646d2SAndroid Build Coastguard Worker */
3208*5e7646d2SAndroid Build Coastguard Worker
3209*5e7646d2SAndroid Build Coastguard Worker if (!strcmp(line->buffer, "*%APLWORKSET START"))
3210*5e7646d2SAndroid Build Coastguard Worker return (0);
3211*5e7646d2SAndroid Build Coastguard Worker
3212*5e7646d2SAndroid Build Coastguard Worker if (ch == EOF && lineptr == line->buffer)
3213*5e7646d2SAndroid Build Coastguard Worker return (0);
3214*5e7646d2SAndroid Build Coastguard Worker
3215*5e7646d2SAndroid Build Coastguard Worker /*
3216*5e7646d2SAndroid Build Coastguard Worker * Now parse it...
3217*5e7646d2SAndroid Build Coastguard Worker */
3218*5e7646d2SAndroid Build Coastguard Worker
3219*5e7646d2SAndroid Build Coastguard Worker mask = 0;
3220*5e7646d2SAndroid Build Coastguard Worker lineptr = line->buffer + 1;
3221*5e7646d2SAndroid Build Coastguard Worker
3222*5e7646d2SAndroid Build Coastguard Worker keyword[0] = '\0';
3223*5e7646d2SAndroid Build Coastguard Worker option[0] = '\0';
3224*5e7646d2SAndroid Build Coastguard Worker text[0] = '\0';
3225*5e7646d2SAndroid Build Coastguard Worker *string = NULL;
3226*5e7646d2SAndroid Build Coastguard Worker
3227*5e7646d2SAndroid Build Coastguard Worker if ((!line->buffer[0] || /* Blank line */
3228*5e7646d2SAndroid Build Coastguard Worker !strncmp(line->buffer, "*%", 2) || /* Comment line */
3229*5e7646d2SAndroid Build Coastguard Worker !strcmp(line->buffer, "*End")) && /* End of multi-line string */
3230*5e7646d2SAndroid Build Coastguard Worker ignoreblank) /* Ignore these? */
3231*5e7646d2SAndroid Build Coastguard Worker {
3232*5e7646d2SAndroid Build Coastguard Worker startline = pg->ppd_line + 1;
3233*5e7646d2SAndroid Build Coastguard Worker continue;
3234*5e7646d2SAndroid Build Coastguard Worker }
3235*5e7646d2SAndroid Build Coastguard Worker
3236*5e7646d2SAndroid Build Coastguard Worker if (!strcmp(line->buffer, "*")) /* (Bad) comment line */
3237*5e7646d2SAndroid Build Coastguard Worker {
3238*5e7646d2SAndroid Build Coastguard Worker if (pg->ppd_conform == PPD_CONFORM_RELAXED)
3239*5e7646d2SAndroid Build Coastguard Worker {
3240*5e7646d2SAndroid Build Coastguard Worker startline = pg->ppd_line + 1;
3241*5e7646d2SAndroid Build Coastguard Worker continue;
3242*5e7646d2SAndroid Build Coastguard Worker }
3243*5e7646d2SAndroid Build Coastguard Worker else
3244*5e7646d2SAndroid Build Coastguard Worker {
3245*5e7646d2SAndroid Build Coastguard Worker pg->ppd_line = startline;
3246*5e7646d2SAndroid Build Coastguard Worker pg->ppd_status = PPD_ILLEGAL_MAIN_KEYWORD;
3247*5e7646d2SAndroid Build Coastguard Worker
3248*5e7646d2SAndroid Build Coastguard Worker return (0);
3249*5e7646d2SAndroid Build Coastguard Worker }
3250*5e7646d2SAndroid Build Coastguard Worker }
3251*5e7646d2SAndroid Build Coastguard Worker
3252*5e7646d2SAndroid Build Coastguard Worker if (line->buffer[0] != '*') /* All lines start with an asterisk */
3253*5e7646d2SAndroid Build Coastguard Worker {
3254*5e7646d2SAndroid Build Coastguard Worker /*
3255*5e7646d2SAndroid Build Coastguard Worker * Allow lines consisting of just whitespace...
3256*5e7646d2SAndroid Build Coastguard Worker */
3257*5e7646d2SAndroid Build Coastguard Worker
3258*5e7646d2SAndroid Build Coastguard Worker for (lineptr = line->buffer; *lineptr; lineptr ++)
3259*5e7646d2SAndroid Build Coastguard Worker if (*lineptr && !_cups_isspace(*lineptr))
3260*5e7646d2SAndroid Build Coastguard Worker break;
3261*5e7646d2SAndroid Build Coastguard Worker
3262*5e7646d2SAndroid Build Coastguard Worker if (*lineptr)
3263*5e7646d2SAndroid Build Coastguard Worker {
3264*5e7646d2SAndroid Build Coastguard Worker pg->ppd_status = PPD_MISSING_ASTERISK;
3265*5e7646d2SAndroid Build Coastguard Worker return (0);
3266*5e7646d2SAndroid Build Coastguard Worker }
3267*5e7646d2SAndroid Build Coastguard Worker else if (ignoreblank)
3268*5e7646d2SAndroid Build Coastguard Worker continue;
3269*5e7646d2SAndroid Build Coastguard Worker else
3270*5e7646d2SAndroid Build Coastguard Worker return (0);
3271*5e7646d2SAndroid Build Coastguard Worker }
3272*5e7646d2SAndroid Build Coastguard Worker
3273*5e7646d2SAndroid Build Coastguard Worker /*
3274*5e7646d2SAndroid Build Coastguard Worker * Get a keyword...
3275*5e7646d2SAndroid Build Coastguard Worker */
3276*5e7646d2SAndroid Build Coastguard Worker
3277*5e7646d2SAndroid Build Coastguard Worker keyptr = keyword;
3278*5e7646d2SAndroid Build Coastguard Worker
3279*5e7646d2SAndroid Build Coastguard Worker while (*lineptr && *lineptr != ':' && !_cups_isspace(*lineptr))
3280*5e7646d2SAndroid Build Coastguard Worker {
3281*5e7646d2SAndroid Build Coastguard Worker if (*lineptr <= ' ' || *lineptr > 126 || *lineptr == '/' ||
3282*5e7646d2SAndroid Build Coastguard Worker (keyptr - keyword) >= (PPD_MAX_NAME - 1))
3283*5e7646d2SAndroid Build Coastguard Worker {
3284*5e7646d2SAndroid Build Coastguard Worker pg->ppd_status = PPD_ILLEGAL_MAIN_KEYWORD;
3285*5e7646d2SAndroid Build Coastguard Worker return (0);
3286*5e7646d2SAndroid Build Coastguard Worker }
3287*5e7646d2SAndroid Build Coastguard Worker
3288*5e7646d2SAndroid Build Coastguard Worker *keyptr++ = *lineptr++;
3289*5e7646d2SAndroid Build Coastguard Worker }
3290*5e7646d2SAndroid Build Coastguard Worker
3291*5e7646d2SAndroid Build Coastguard Worker *keyptr = '\0';
3292*5e7646d2SAndroid Build Coastguard Worker
3293*5e7646d2SAndroid Build Coastguard Worker if (!strcmp(keyword, "End"))
3294*5e7646d2SAndroid Build Coastguard Worker continue;
3295*5e7646d2SAndroid Build Coastguard Worker
3296*5e7646d2SAndroid Build Coastguard Worker mask |= PPD_KEYWORD;
3297*5e7646d2SAndroid Build Coastguard Worker
3298*5e7646d2SAndroid Build Coastguard Worker if (_cups_isspace(*lineptr))
3299*5e7646d2SAndroid Build Coastguard Worker {
3300*5e7646d2SAndroid Build Coastguard Worker /*
3301*5e7646d2SAndroid Build Coastguard Worker * Get an option name...
3302*5e7646d2SAndroid Build Coastguard Worker */
3303*5e7646d2SAndroid Build Coastguard Worker
3304*5e7646d2SAndroid Build Coastguard Worker while (_cups_isspace(*lineptr))
3305*5e7646d2SAndroid Build Coastguard Worker lineptr ++;
3306*5e7646d2SAndroid Build Coastguard Worker
3307*5e7646d2SAndroid Build Coastguard Worker optptr = option;
3308*5e7646d2SAndroid Build Coastguard Worker
3309*5e7646d2SAndroid Build Coastguard Worker while (*lineptr && !_cups_isspace(*lineptr) && *lineptr != ':' &&
3310*5e7646d2SAndroid Build Coastguard Worker *lineptr != '/')
3311*5e7646d2SAndroid Build Coastguard Worker {
3312*5e7646d2SAndroid Build Coastguard Worker if (*lineptr <= ' ' || *lineptr > 126 ||
3313*5e7646d2SAndroid Build Coastguard Worker (optptr - option) >= (PPD_MAX_NAME - 1))
3314*5e7646d2SAndroid Build Coastguard Worker {
3315*5e7646d2SAndroid Build Coastguard Worker pg->ppd_status = PPD_ILLEGAL_OPTION_KEYWORD;
3316*5e7646d2SAndroid Build Coastguard Worker return (0);
3317*5e7646d2SAndroid Build Coastguard Worker }
3318*5e7646d2SAndroid Build Coastguard Worker
3319*5e7646d2SAndroid Build Coastguard Worker *optptr++ = *lineptr++;
3320*5e7646d2SAndroid Build Coastguard Worker }
3321*5e7646d2SAndroid Build Coastguard Worker
3322*5e7646d2SAndroid Build Coastguard Worker *optptr = '\0';
3323*5e7646d2SAndroid Build Coastguard Worker
3324*5e7646d2SAndroid Build Coastguard Worker if (_cups_isspace(*lineptr) && pg->ppd_conform == PPD_CONFORM_STRICT)
3325*5e7646d2SAndroid Build Coastguard Worker {
3326*5e7646d2SAndroid Build Coastguard Worker pg->ppd_status = PPD_ILLEGAL_WHITESPACE;
3327*5e7646d2SAndroid Build Coastguard Worker return (0);
3328*5e7646d2SAndroid Build Coastguard Worker }
3329*5e7646d2SAndroid Build Coastguard Worker
3330*5e7646d2SAndroid Build Coastguard Worker while (_cups_isspace(*lineptr))
3331*5e7646d2SAndroid Build Coastguard Worker lineptr ++;
3332*5e7646d2SAndroid Build Coastguard Worker
3333*5e7646d2SAndroid Build Coastguard Worker mask |= PPD_OPTION;
3334*5e7646d2SAndroid Build Coastguard Worker
3335*5e7646d2SAndroid Build Coastguard Worker if (*lineptr == '/')
3336*5e7646d2SAndroid Build Coastguard Worker {
3337*5e7646d2SAndroid Build Coastguard Worker /*
3338*5e7646d2SAndroid Build Coastguard Worker * Get human-readable text...
3339*5e7646d2SAndroid Build Coastguard Worker */
3340*5e7646d2SAndroid Build Coastguard Worker
3341*5e7646d2SAndroid Build Coastguard Worker lineptr ++;
3342*5e7646d2SAndroid Build Coastguard Worker
3343*5e7646d2SAndroid Build Coastguard Worker textptr = text;
3344*5e7646d2SAndroid Build Coastguard Worker
3345*5e7646d2SAndroid Build Coastguard Worker while (*lineptr != '\0' && *lineptr != '\n' && *lineptr != ':')
3346*5e7646d2SAndroid Build Coastguard Worker {
3347*5e7646d2SAndroid Build Coastguard Worker if (((unsigned char)*lineptr < ' ' && *lineptr != '\t') ||
3348*5e7646d2SAndroid Build Coastguard Worker (textptr - text) >= (PPD_MAX_LINE - 1))
3349*5e7646d2SAndroid Build Coastguard Worker {
3350*5e7646d2SAndroid Build Coastguard Worker pg->ppd_status = PPD_ILLEGAL_TRANSLATION;
3351*5e7646d2SAndroid Build Coastguard Worker return (0);
3352*5e7646d2SAndroid Build Coastguard Worker }
3353*5e7646d2SAndroid Build Coastguard Worker
3354*5e7646d2SAndroid Build Coastguard Worker *textptr++ = *lineptr++;
3355*5e7646d2SAndroid Build Coastguard Worker }
3356*5e7646d2SAndroid Build Coastguard Worker
3357*5e7646d2SAndroid Build Coastguard Worker *textptr = '\0';
3358*5e7646d2SAndroid Build Coastguard Worker textlen = ppd_decode(text);
3359*5e7646d2SAndroid Build Coastguard Worker
3360*5e7646d2SAndroid Build Coastguard Worker if (textlen > PPD_MAX_TEXT && pg->ppd_conform == PPD_CONFORM_STRICT)
3361*5e7646d2SAndroid Build Coastguard Worker {
3362*5e7646d2SAndroid Build Coastguard Worker pg->ppd_status = PPD_ILLEGAL_TRANSLATION;
3363*5e7646d2SAndroid Build Coastguard Worker return (0);
3364*5e7646d2SAndroid Build Coastguard Worker }
3365*5e7646d2SAndroid Build Coastguard Worker
3366*5e7646d2SAndroid Build Coastguard Worker mask |= PPD_TEXT;
3367*5e7646d2SAndroid Build Coastguard Worker }
3368*5e7646d2SAndroid Build Coastguard Worker }
3369*5e7646d2SAndroid Build Coastguard Worker
3370*5e7646d2SAndroid Build Coastguard Worker if (_cups_isspace(*lineptr) && pg->ppd_conform == PPD_CONFORM_STRICT)
3371*5e7646d2SAndroid Build Coastguard Worker {
3372*5e7646d2SAndroid Build Coastguard Worker pg->ppd_status = PPD_ILLEGAL_WHITESPACE;
3373*5e7646d2SAndroid Build Coastguard Worker return (0);
3374*5e7646d2SAndroid Build Coastguard Worker }
3375*5e7646d2SAndroid Build Coastguard Worker
3376*5e7646d2SAndroid Build Coastguard Worker while (_cups_isspace(*lineptr))
3377*5e7646d2SAndroid Build Coastguard Worker lineptr ++;
3378*5e7646d2SAndroid Build Coastguard Worker
3379*5e7646d2SAndroid Build Coastguard Worker if (*lineptr == ':')
3380*5e7646d2SAndroid Build Coastguard Worker {
3381*5e7646d2SAndroid Build Coastguard Worker /*
3382*5e7646d2SAndroid Build Coastguard Worker * Get string after triming leading and trailing whitespace...
3383*5e7646d2SAndroid Build Coastguard Worker */
3384*5e7646d2SAndroid Build Coastguard Worker
3385*5e7646d2SAndroid Build Coastguard Worker lineptr ++;
3386*5e7646d2SAndroid Build Coastguard Worker while (_cups_isspace(*lineptr))
3387*5e7646d2SAndroid Build Coastguard Worker lineptr ++;
3388*5e7646d2SAndroid Build Coastguard Worker
3389*5e7646d2SAndroid Build Coastguard Worker strptr = lineptr + strlen(lineptr) - 1;
3390*5e7646d2SAndroid Build Coastguard Worker while (strptr >= lineptr && _cups_isspace(*strptr))
3391*5e7646d2SAndroid Build Coastguard Worker *strptr-- = '\0';
3392*5e7646d2SAndroid Build Coastguard Worker
3393*5e7646d2SAndroid Build Coastguard Worker if (*strptr == '\"')
3394*5e7646d2SAndroid Build Coastguard Worker {
3395*5e7646d2SAndroid Build Coastguard Worker /*
3396*5e7646d2SAndroid Build Coastguard Worker * Quoted string by itself, remove quotes...
3397*5e7646d2SAndroid Build Coastguard Worker */
3398*5e7646d2SAndroid Build Coastguard Worker
3399*5e7646d2SAndroid Build Coastguard Worker *strptr = '\0';
3400*5e7646d2SAndroid Build Coastguard Worker lineptr ++;
3401*5e7646d2SAndroid Build Coastguard Worker }
3402*5e7646d2SAndroid Build Coastguard Worker
3403*5e7646d2SAndroid Build Coastguard Worker *string = strdup(lineptr);
3404*5e7646d2SAndroid Build Coastguard Worker
3405*5e7646d2SAndroid Build Coastguard Worker mask |= PPD_STRING;
3406*5e7646d2SAndroid Build Coastguard Worker }
3407*5e7646d2SAndroid Build Coastguard Worker }
3408*5e7646d2SAndroid Build Coastguard Worker while (mask == 0);
3409*5e7646d2SAndroid Build Coastguard Worker
3410*5e7646d2SAndroid Build Coastguard Worker return (mask);
3411*5e7646d2SAndroid Build Coastguard Worker }
3412*5e7646d2SAndroid Build Coastguard Worker
3413*5e7646d2SAndroid Build Coastguard Worker
3414*5e7646d2SAndroid Build Coastguard Worker /*
3415*5e7646d2SAndroid Build Coastguard Worker * 'ppd_update_filters()' - Update the filters array as needed.
3416*5e7646d2SAndroid Build Coastguard Worker *
3417*5e7646d2SAndroid Build Coastguard Worker * This function re-populates the filters array with cupsFilter2 entries that
3418*5e7646d2SAndroid Build Coastguard Worker * have been stripped of the destination MIME media types and any maxsize hints.
3419*5e7646d2SAndroid Build Coastguard Worker *
3420*5e7646d2SAndroid Build Coastguard Worker * (All for backwards-compatibility)
3421*5e7646d2SAndroid Build Coastguard Worker */
3422*5e7646d2SAndroid Build Coastguard Worker
3423*5e7646d2SAndroid Build Coastguard Worker static int /* O - 1 on success, 0 on failure */
ppd_update_filters(ppd_file_t * ppd,_ppd_globals_t * pg)3424*5e7646d2SAndroid Build Coastguard Worker ppd_update_filters(ppd_file_t *ppd, /* I - PPD file */
3425*5e7646d2SAndroid Build Coastguard Worker _ppd_globals_t *pg) /* I - Global data */
3426*5e7646d2SAndroid Build Coastguard Worker {
3427*5e7646d2SAndroid Build Coastguard Worker ppd_attr_t *attr; /* Current cupsFilter2 value */
3428*5e7646d2SAndroid Build Coastguard Worker char srcsuper[16], /* Source MIME media type */
3429*5e7646d2SAndroid Build Coastguard Worker srctype[256],
3430*5e7646d2SAndroid Build Coastguard Worker dstsuper[16], /* Destination MIME media type */
3431*5e7646d2SAndroid Build Coastguard Worker dsttype[256],
3432*5e7646d2SAndroid Build Coastguard Worker program[1024], /* Command to run */
3433*5e7646d2SAndroid Build Coastguard Worker *ptr, /* Pointer into command to run */
3434*5e7646d2SAndroid Build Coastguard Worker buffer[1024], /* Re-written cupsFilter value */
3435*5e7646d2SAndroid Build Coastguard Worker **filter; /* Current filter */
3436*5e7646d2SAndroid Build Coastguard Worker int cost; /* Cost of filter */
3437*5e7646d2SAndroid Build Coastguard Worker
3438*5e7646d2SAndroid Build Coastguard Worker
3439*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("4ppd_update_filters(ppd=%p, cg=%p)", ppd, pg));
3440*5e7646d2SAndroid Build Coastguard Worker
3441*5e7646d2SAndroid Build Coastguard Worker /*
3442*5e7646d2SAndroid Build Coastguard Worker * See if we have any cupsFilter2 lines...
3443*5e7646d2SAndroid Build Coastguard Worker */
3444*5e7646d2SAndroid Build Coastguard Worker
3445*5e7646d2SAndroid Build Coastguard Worker if ((attr = ppdFindAttr(ppd, "cupsFilter2", NULL)) == NULL)
3446*5e7646d2SAndroid Build Coastguard Worker {
3447*5e7646d2SAndroid Build Coastguard Worker DEBUG_puts("5ppd_update_filters: No cupsFilter2 keywords present.");
3448*5e7646d2SAndroid Build Coastguard Worker return (1);
3449*5e7646d2SAndroid Build Coastguard Worker }
3450*5e7646d2SAndroid Build Coastguard Worker
3451*5e7646d2SAndroid Build Coastguard Worker /*
3452*5e7646d2SAndroid Build Coastguard Worker * Yes, free the cupsFilter-defined filters and re-build...
3453*5e7646d2SAndroid Build Coastguard Worker */
3454*5e7646d2SAndroid Build Coastguard Worker
3455*5e7646d2SAndroid Build Coastguard Worker ppd_free_filters(ppd);
3456*5e7646d2SAndroid Build Coastguard Worker
3457*5e7646d2SAndroid Build Coastguard Worker do
3458*5e7646d2SAndroid Build Coastguard Worker {
3459*5e7646d2SAndroid Build Coastguard Worker /*
3460*5e7646d2SAndroid Build Coastguard Worker * Parse the cupsFilter2 string:
3461*5e7646d2SAndroid Build Coastguard Worker *
3462*5e7646d2SAndroid Build Coastguard Worker * src/type dst/type cost program
3463*5e7646d2SAndroid Build Coastguard Worker * src/type dst/type cost maxsize(n) program
3464*5e7646d2SAndroid Build Coastguard Worker */
3465*5e7646d2SAndroid Build Coastguard Worker
3466*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("5ppd_update_filters: cupsFilter2=\"%s\"", attr->value));
3467*5e7646d2SAndroid Build Coastguard Worker
3468*5e7646d2SAndroid Build Coastguard Worker if (sscanf(attr->value, "%15[^/]/%255s%*[ \t]%15[^/]/%255s%d%*[ \t]%1023[^\n]",
3469*5e7646d2SAndroid Build Coastguard Worker srcsuper, srctype, dstsuper, dsttype, &cost, program) != 6)
3470*5e7646d2SAndroid Build Coastguard Worker {
3471*5e7646d2SAndroid Build Coastguard Worker DEBUG_puts("5ppd_update_filters: Bad cupsFilter2 line.");
3472*5e7646d2SAndroid Build Coastguard Worker pg->ppd_status = PPD_BAD_VALUE;
3473*5e7646d2SAndroid Build Coastguard Worker
3474*5e7646d2SAndroid Build Coastguard Worker return (0);
3475*5e7646d2SAndroid Build Coastguard Worker }
3476*5e7646d2SAndroid Build Coastguard Worker
3477*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("5ppd_update_filters: srcsuper=\"%s\", srctype=\"%s\", "
3478*5e7646d2SAndroid Build Coastguard Worker "dstsuper=\"%s\", dsttype=\"%s\", cost=%d, program=\"%s\"",
3479*5e7646d2SAndroid Build Coastguard Worker srcsuper, srctype, dstsuper, dsttype, cost, program));
3480*5e7646d2SAndroid Build Coastguard Worker
3481*5e7646d2SAndroid Build Coastguard Worker if (!strncmp(program, "maxsize(", 8) &&
3482*5e7646d2SAndroid Build Coastguard Worker (ptr = strchr(program + 8, ')')) != NULL)
3483*5e7646d2SAndroid Build Coastguard Worker {
3484*5e7646d2SAndroid Build Coastguard Worker DEBUG_puts("5ppd_update_filters: Found maxsize(nnn).");
3485*5e7646d2SAndroid Build Coastguard Worker
3486*5e7646d2SAndroid Build Coastguard Worker ptr ++;
3487*5e7646d2SAndroid Build Coastguard Worker while (_cups_isspace(*ptr))
3488*5e7646d2SAndroid Build Coastguard Worker ptr ++;
3489*5e7646d2SAndroid Build Coastguard Worker
3490*5e7646d2SAndroid Build Coastguard Worker _cups_strcpy(program, ptr);
3491*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("5ppd_update_filters: New program=\"%s\"", program));
3492*5e7646d2SAndroid Build Coastguard Worker }
3493*5e7646d2SAndroid Build Coastguard Worker
3494*5e7646d2SAndroid Build Coastguard Worker /*
3495*5e7646d2SAndroid Build Coastguard Worker * Convert to cupsFilter format:
3496*5e7646d2SAndroid Build Coastguard Worker *
3497*5e7646d2SAndroid Build Coastguard Worker * src/type cost program
3498*5e7646d2SAndroid Build Coastguard Worker */
3499*5e7646d2SAndroid Build Coastguard Worker
3500*5e7646d2SAndroid Build Coastguard Worker snprintf(buffer, sizeof(buffer), "%s/%s %d %s", srcsuper, srctype, cost,
3501*5e7646d2SAndroid Build Coastguard Worker program);
3502*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("5ppd_update_filters: Adding \"%s\".", buffer));
3503*5e7646d2SAndroid Build Coastguard Worker
3504*5e7646d2SAndroid Build Coastguard Worker /*
3505*5e7646d2SAndroid Build Coastguard Worker * Add a cupsFilter-compatible string to the filters array.
3506*5e7646d2SAndroid Build Coastguard Worker */
3507*5e7646d2SAndroid Build Coastguard Worker
3508*5e7646d2SAndroid Build Coastguard Worker if (ppd->num_filters == 0)
3509*5e7646d2SAndroid Build Coastguard Worker filter = malloc(sizeof(char *));
3510*5e7646d2SAndroid Build Coastguard Worker else
3511*5e7646d2SAndroid Build Coastguard Worker filter = realloc(ppd->filters, sizeof(char *) * (size_t)(ppd->num_filters + 1));
3512*5e7646d2SAndroid Build Coastguard Worker
3513*5e7646d2SAndroid Build Coastguard Worker if (filter == NULL)
3514*5e7646d2SAndroid Build Coastguard Worker {
3515*5e7646d2SAndroid Build Coastguard Worker DEBUG_puts("5ppd_update_filters: Out of memory.");
3516*5e7646d2SAndroid Build Coastguard Worker pg->ppd_status = PPD_ALLOC_ERROR;
3517*5e7646d2SAndroid Build Coastguard Worker
3518*5e7646d2SAndroid Build Coastguard Worker return (0);
3519*5e7646d2SAndroid Build Coastguard Worker }
3520*5e7646d2SAndroid Build Coastguard Worker
3521*5e7646d2SAndroid Build Coastguard Worker ppd->filters = filter;
3522*5e7646d2SAndroid Build Coastguard Worker filter += ppd->num_filters;
3523*5e7646d2SAndroid Build Coastguard Worker ppd->num_filters ++;
3524*5e7646d2SAndroid Build Coastguard Worker
3525*5e7646d2SAndroid Build Coastguard Worker *filter = strdup(buffer);
3526*5e7646d2SAndroid Build Coastguard Worker }
3527*5e7646d2SAndroid Build Coastguard Worker while ((attr = ppdFindNextAttr(ppd, "cupsFilter2", NULL)) != NULL);
3528*5e7646d2SAndroid Build Coastguard Worker
3529*5e7646d2SAndroid Build Coastguard Worker DEBUG_puts("5ppd_update_filters: Completed OK.");
3530*5e7646d2SAndroid Build Coastguard Worker return (1);
3531*5e7646d2SAndroid Build Coastguard Worker }
3532