]> git.ipfire.org Git - thirdparty/cups.git/blob - cups/encode.c
Load cups into easysw/current.
[thirdparty/cups.git] / cups / encode.c
1 /*
2 * "$Id: encode.c 4918 2006-01-12 05:14:40Z mike $"
3 *
4 * Option encoding routines for the Common UNIX Printing System (CUPS).
5 *
6 * Copyright 1997-2005 by Easy Software Products.
7 *
8 * These coded instructions, statements, and computer programs are the
9 * property of Easy Software Products and are protected by Federal
10 * copyright law. Distribution and use rights are outlined in the file
11 * "LICENSE.txt" which should have been included with this file. If this
12 * file is missing or damaged please contact Easy Software Products
13 * at:
14 *
15 * Attn: CUPS Licensing Information
16 * Easy Software Products
17 * 44141 Airport View Drive, Suite 204
18 * Hollywood, Maryland 20636 USA
19 *
20 * Voice: (301) 373-9600
21 * EMail: cups-info@cups.org
22 * WWW: http://www.cups.org
23 *
24 * This file is subject to the Apple OS-Developed Software exception.
25 *
26 * Contents:
27 *
28 * cupsEncodeOptions() - Encode printer options into IPP attributes.
29 * cupsEncodeOptions2() - Encode printer options into IPP attributes for
30 * a group.
31 */
32
33 /*
34 * Include necessary headers...
35 */
36
37 #include "cups.h"
38 #include <stdlib.h>
39 #include <ctype.h>
40 #include "string.h"
41 #include "debug.h"
42
43
44 /*
45 * Local list of option names and the value tags they should use...
46 */
47
48 typedef struct
49 {
50 const char *name;
51 ipp_tag_t value_tag;
52 ipp_tag_t group_tag;
53 } _ipp_option_t;
54
55 static const _ipp_option_t ipp_options[] =
56 {
57 { "blackplot", IPP_TAG_BOOLEAN, IPP_TAG_JOB },
58 { "brightness", IPP_TAG_INTEGER, IPP_TAG_JOB },
59 { "columns", IPP_TAG_INTEGER, IPP_TAG_JOB },
60 { "copies", IPP_TAG_INTEGER, IPP_TAG_JOB },
61 { "document-format", IPP_TAG_MIMETYPE, IPP_TAG_OPERATION },
62 { "finishings", IPP_TAG_ENUM, IPP_TAG_JOB },
63 { "fitplot", IPP_TAG_BOOLEAN, IPP_TAG_JOB },
64 { "gamma", IPP_TAG_INTEGER, IPP_TAG_JOB },
65 { "hue", IPP_TAG_INTEGER, IPP_TAG_JOB },
66 { "job-k-limit", IPP_TAG_INTEGER, IPP_TAG_JOB },
67 { "job-page-limit", IPP_TAG_INTEGER, IPP_TAG_JOB },
68 { "job-priority", IPP_TAG_INTEGER, IPP_TAG_JOB },
69 { "job-quota-period", IPP_TAG_INTEGER, IPP_TAG_JOB },
70 { "landscape", IPP_TAG_BOOLEAN, IPP_TAG_JOB },
71 { "media", IPP_TAG_KEYWORD, IPP_TAG_JOB },
72 { "mirror", IPP_TAG_BOOLEAN, IPP_TAG_JOB },
73 { "natural-scaling", IPP_TAG_INTEGER, IPP_TAG_JOB },
74 { "notify-charset", IPP_TAG_CHARSET, IPP_TAG_SUBSCRIPTION },
75 { "notify-events", IPP_TAG_KEYWORD, IPP_TAG_SUBSCRIPTION },
76 { "notify-lease-time", IPP_TAG_INTEGER, IPP_TAG_SUBSCRIPTION },
77 { "notify-natural-language", IPP_TAG_LANGUAGE, IPP_TAG_SUBSCRIPTION },
78 { "notify-pull-method", IPP_TAG_KEYWORD, IPP_TAG_SUBSCRIPTION },
79 { "notify-recipient", IPP_TAG_URI, IPP_TAG_SUBSCRIPTION },
80 { "notify-time-interval", IPP_TAG_INTEGER, IPP_TAG_SUBSCRIPTION },
81 { "notify-user-data", IPP_TAG_STRING, IPP_TAG_SUBSCRIPTION },
82 { "number-up", IPP_TAG_INTEGER, IPP_TAG_JOB },
83 { "orientation-requested", IPP_TAG_ENUM, IPP_TAG_JOB },
84 { "page-bottom", IPP_TAG_INTEGER, IPP_TAG_JOB },
85 { "page-left", IPP_TAG_INTEGER, IPP_TAG_JOB },
86 { "page-ranges", IPP_TAG_RANGE, IPP_TAG_JOB },
87 { "page-right", IPP_TAG_INTEGER, IPP_TAG_JOB },
88 { "page-top", IPP_TAG_INTEGER, IPP_TAG_JOB },
89 { "penwidth", IPP_TAG_INTEGER, IPP_TAG_JOB },
90 { "ppi", IPP_TAG_INTEGER, IPP_TAG_JOB },
91 { "prettyprint", IPP_TAG_BOOLEAN, IPP_TAG_JOB },
92 { "printer-resolution", IPP_TAG_RESOLUTION, IPP_TAG_JOB },
93 { "printer-uri", IPP_TAG_URI, IPP_TAG_OPERATION },
94 { "print-quality", IPP_TAG_ENUM, IPP_TAG_JOB },
95 { "raw", IPP_TAG_MIMETYPE, IPP_TAG_OPERATION },
96 { "saturation", IPP_TAG_INTEGER, IPP_TAG_JOB },
97 { "scaling", IPP_TAG_INTEGER, IPP_TAG_JOB },
98 { "sides", IPP_TAG_KEYWORD, IPP_TAG_JOB },
99 { "wrap", IPP_TAG_BOOLEAN, IPP_TAG_JOB }
100 };
101
102
103 /*
104 * 'cupsEncodeOptions()' - Encode printer options into IPP attributes.
105 *
106 * This function adds operation, job, and then subscription attributes,
107 * in that order. Use the cupsEncodeOptions2() function to add attributes
108 * for a single group.
109 */
110
111 void
112 cupsEncodeOptions(ipp_t *ipp, /* I - Request to add to */
113 int num_options, /* I - Number of options */
114 cups_option_t *options) /* I - Options */
115 {
116 DEBUG_printf(("cupsEncodeOptions(%p, %d, %p)\n", ipp, num_options, options));
117
118 /*
119 * Add the options in the proper groups & order...
120 */
121
122 cupsEncodeOptions2(ipp, num_options, options, IPP_TAG_OPERATION);
123 cupsEncodeOptions2(ipp, num_options, options, IPP_TAG_JOB);
124 cupsEncodeOptions2(ipp, num_options, options, IPP_TAG_SUBSCRIPTION);
125 }
126
127
128 /*
129 * 'cupsEncodeOptions2()' - Encode printer options into IPP attributes for a group.
130 *
131 * This function only adds attributes for a single group. Call this
132 * function multiple times for each group, or use cupsEncodeOptions()
133 * to add the standard groups.
134 *
135 * @since CUPS 1.2@
136 */
137
138 void
139 cupsEncodeOptions2(
140 ipp_t *ipp, /* I - Request to add to */
141 int num_options, /* I - Number of options */
142 cups_option_t *options, /* I - Options */
143 ipp_tag_t group_tag) /* I - Group to encode */
144 {
145 int i, j; /* Looping vars */
146 int count; /* Number of values */
147 char *s, /* Pointer into option value */
148 *val, /* Pointer to option value */
149 *copy, /* Copy of option value */
150 *sep; /* Option separator */
151 ipp_attribute_t *attr; /* IPP attribute */
152 ipp_tag_t value_tag; /* IPP value tag */
153
154
155 DEBUG_printf(("cupsEncodeOptions2(ipp=%p, num_options=%d, options=%p, group_tag=%x)\n",
156 ipp, num_options, options, group_tag));
157
158 /*
159 * Range check input...
160 */
161
162 if (ipp == NULL || num_options < 1 || options == NULL)
163 return;
164
165 /*
166 * Do special handling for the document-format/raw options...
167 */
168
169 if (group_tag == IPP_TAG_OPERATION)
170 {
171 /*
172 * Handle the document format stuff first...
173 */
174
175 if ((val = (char *)cupsGetOption("document-format", num_options, options)) != NULL)
176 ippAddString(ipp, IPP_TAG_OPERATION, IPP_TAG_MIMETYPE, "document-format",
177 NULL, val);
178 else if (cupsGetOption("raw", num_options, options))
179 ippAddString(ipp, IPP_TAG_OPERATION, IPP_TAG_MIMETYPE, "document-format",
180 NULL, "application/vnd.cups-raw");
181 else
182 ippAddString(ipp, IPP_TAG_OPERATION, IPP_TAG_MIMETYPE, "document-format",
183 NULL, "application/octet-stream");
184 }
185
186 /*
187 * Then loop through the options...
188 */
189
190 for (i = 0; i < num_options; i ++)
191 {
192 /*
193 * Skip document format options that are handled above...
194 */
195
196 if (!strcasecmp(options[i].name, "raw") ||
197 !strcasecmp(options[i].name, "document-format") ||
198 !options[i].name[0])
199 continue;
200
201 /*
202 * Figure out the proper value and group tags for this option...
203 */
204
205 for (j = 0; j < (int)(sizeof(ipp_options) / sizeof(ipp_options[0])); j ++)
206 if (!strcasecmp(options[i].name, ipp_options[j].name))
207 break;
208
209 if (j < (int)(sizeof(ipp_options) / sizeof(ipp_options[0])))
210 {
211 if (ipp_options[j].group_tag != group_tag)
212 continue;
213
214 value_tag = ipp_options[j].value_tag;
215 }
216 else if (group_tag != IPP_TAG_JOB)
217 continue;
218 else if (!strcasecmp(options[i].value, "true") ||
219 !strcasecmp(options[i].value, "false"))
220 value_tag = IPP_TAG_BOOLEAN;
221 else
222 value_tag = IPP_TAG_NAME;
223
224 /*
225 * Count the number of values...
226 */
227
228 for (count = 1, sep = options[i].value; *sep; sep ++)
229 {
230 if (*sep == '\'')
231 {
232 /*
233 * Skip quoted option value...
234 */
235
236 sep ++;
237
238 while (*sep && *sep != '\'')
239 sep ++;
240
241 if (!*sep)
242 sep --;
243 }
244 else if (*sep == '\"')
245 {
246 /*
247 * Skip quoted option value...
248 */
249
250 sep ++;
251
252 while (*sep && *sep != '\"')
253 sep ++;
254
255 if (!*sep)
256 sep --;
257 }
258 else if (*sep == ',')
259 count ++;
260 else if (*sep == '\\' && sep[1])
261 sep ++;
262 }
263
264 DEBUG_printf(("cupsEncodeOptions2: option = \'%s\', count = %d\n",
265 options[i].name, count));
266
267 /*
268 * Allocate memory for the attribute values...
269 */
270
271 if ((attr = _ipp_add_attr(ipp, count)) == NULL)
272 {
273 /*
274 * Ran out of memory!
275 */
276
277 DEBUG_puts("cupsEncodeOptions2: Ran out of memory for attributes!");
278 return;
279 }
280
281 /*
282 * Now figure out what type of value we have...
283 */
284
285 attr->group_tag = group_tag;
286 attr->value_tag = value_tag;
287
288 /*
289 * Copy the name over...
290 */
291
292 if ((attr->name = strdup(options[i].name)) == NULL)
293 {
294 /*
295 * Ran out of memory!
296 */
297
298 DEBUG_puts("cupsEncodeOptions2: Ran out of memory for name!");
299 return;
300 }
301
302 if (count > 1)
303 {
304 /*
305 * Make a copy of the value we can fiddle with...
306 */
307
308 if ((copy = strdup(options[i].value)) == NULL)
309 {
310 /*
311 * Ran out of memory!
312 */
313
314 DEBUG_puts("cupsEncodeOptions2: Ran out of memory for value copy!");
315 return;
316 }
317
318 val = copy;
319 }
320 else
321 {
322 /*
323 * Since we have a single value, use the value directly...
324 */
325
326 val = options[i].value;
327 copy = NULL;
328 }
329
330 /*
331 * Scan the value string for values...
332 */
333
334 for (j = 0; j < count; val = sep, j ++)
335 {
336 /*
337 * Find the end of this value and mark it if needed...
338 */
339
340 if ((sep = strchr(val, ',')) != NULL)
341 *sep++ = '\0';
342 else
343 sep = val + strlen(val);
344
345 /*
346 * Copy the option value(s) over as needed by the type...
347 */
348
349 switch (attr->value_tag)
350 {
351 case IPP_TAG_INTEGER :
352 case IPP_TAG_ENUM :
353 /*
354 * Integer/enumeration value...
355 */
356
357 attr->values[j].integer = strtol(val, &s, 0);
358
359 DEBUG_printf(("cupsEncodeOptions2: Added integer option value %d...\n",
360 attr->values[j].integer));
361 break;
362
363 case IPP_TAG_BOOLEAN :
364 if (!strcasecmp(val, "true") ||
365 !strcasecmp(val, "on") ||
366 !strcasecmp(val, "yes"))
367 {
368 /*
369 * Boolean value - true...
370 */
371
372 attr->values[j].boolean = 1;
373
374 DEBUG_puts("cupsEncodeOptions2: Added boolean true value...");
375 }
376 else
377 {
378 /*
379 * Boolean value - false...
380 */
381
382 attr->values[j].boolean = 0;
383
384 DEBUG_puts("cupsEncodeOptions2: Added boolean false value...");
385 }
386 break;
387
388 case IPP_TAG_RANGE :
389 /*
390 * Range...
391 */
392
393 if (*val == '-')
394 {
395 attr->values[j].range.lower = 1;
396 s = val;
397 }
398 else
399 attr->values[j].range.lower = strtol(val, &s, 0);
400
401 if (*s == '-')
402 {
403 if (s[1])
404 attr->values[j].range.upper = strtol(s + 1, NULL, 0);
405 else
406 attr->values[j].range.upper = 2147483647;
407 }
408 else
409 attr->values[j].range.upper = attr->values[j].range.lower;
410
411 DEBUG_printf(("cupsEncodeOptions2: Added range option value %d-%d...\n",
412 attr->values[j].range.lower,
413 attr->values[j].range.upper));
414 break;
415
416 case IPP_TAG_RESOLUTION :
417 /*
418 * Resolution...
419 */
420
421 attr->values[j].resolution.xres = strtol(val, &s, 0);
422
423 if (*s == 'x')
424 attr->values[j].resolution.yres = strtol(s + 1, &s, 0);
425 else
426 attr->values[j].resolution.yres = attr->values[j].resolution.xres;
427
428 if (strcasecmp(s, "dpc") == 0)
429 attr->values[j].resolution.units = IPP_RES_PER_CM;
430 else
431 attr->values[j].resolution.units = IPP_RES_PER_INCH;
432
433 DEBUG_printf(("cupsEncodeOptions2: Added resolution option value %s...\n",
434 val));
435 break;
436
437 case IPP_TAG_STRING :
438 /*
439 * octet-string
440 */
441
442 attr->values[j].unknown.length = strlen(val);
443 attr->values[j].unknown.data = strdup(val);
444
445 DEBUG_printf(("cupsEncodeOptions2: Added octet-string value \"%s\"...\n",
446 attr->values[j].unknown.data));
447 break;
448
449 default :
450 if ((attr->values[j].string.text = strdup(val)) == NULL)
451 {
452 /*
453 * Ran out of memory!
454 */
455
456 DEBUG_puts("cupsEncodeOptions2: Ran out of memory for string!");
457 return;
458 }
459
460 DEBUG_printf(("cupsEncodeOptions2: Added string value \"%s\"...\n",
461 val));
462 break;
463 }
464 }
465 }
466 }
467
468
469 /*
470 * End of "$Id: encode.c 4918 2006-01-12 05:14:40Z mike $".
471 */