2 * "$Id: encode.c 4918 2006-01-12 05:14:40Z mike $"
4 * Option encoding routines for the Common UNIX Printing System (CUPS).
6 * Copyright 1997-2005 by Easy Software Products.
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
15 * Attn: CUPS Licensing Information
16 * Easy Software Products
17 * 44141 Airport View Drive, Suite 204
18 * Hollywood, Maryland 20636 USA
20 * Voice: (301) 373-9600
21 * EMail: cups-info@cups.org
22 * WWW: http://www.cups.org
24 * This file is subject to the Apple OS-Developed Software exception.
28 * cupsEncodeOptions() - Encode printer options into IPP attributes.
29 * cupsEncodeOptions2() - Encode printer options into IPP attributes for
34 * Include necessary headers...
45 * Local list of option names and the value tags they should use...
55 static const _ipp_option_t ipp_options
[] =
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
}
104 * 'cupsEncodeOptions()' - Encode printer options into IPP attributes.
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.
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 */
116 DEBUG_printf(("cupsEncodeOptions(%p, %d, %p)\n", ipp
, num_options
, options
));
119 * Add the options in the proper groups & order...
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
);
129 * 'cupsEncodeOptions2()' - Encode printer options into IPP attributes for a group.
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.
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 */
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 */
155 DEBUG_printf(("cupsEncodeOptions2(ipp=%p, num_options=%d, options=%p, group_tag=%x)\n",
156 ipp
, num_options
, options
, group_tag
));
159 * Range check input...
162 if (ipp
== NULL
|| num_options
< 1 || options
== NULL
)
166 * Do special handling for the document-format/raw options...
169 if (group_tag
== IPP_TAG_OPERATION
)
172 * Handle the document format stuff first...
175 if ((val
= (char *)cupsGetOption("document-format", num_options
, options
)) != NULL
)
176 ippAddString(ipp
, IPP_TAG_OPERATION
, IPP_TAG_MIMETYPE
, "document-format",
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");
182 ippAddString(ipp
, IPP_TAG_OPERATION
, IPP_TAG_MIMETYPE
, "document-format",
183 NULL
, "application/octet-stream");
187 * Then loop through the options...
190 for (i
= 0; i
< num_options
; i
++)
193 * Skip document format options that are handled above...
196 if (!strcasecmp(options
[i
].name
, "raw") ||
197 !strcasecmp(options
[i
].name
, "document-format") ||
202 * Figure out the proper value and group tags for this option...
205 for (j
= 0; j
< (int)(sizeof(ipp_options
) / sizeof(ipp_options
[0])); j
++)
206 if (!strcasecmp(options
[i
].name
, ipp_options
[j
].name
))
209 if (j
< (int)(sizeof(ipp_options
) / sizeof(ipp_options
[0])))
211 if (ipp_options
[j
].group_tag
!= group_tag
)
214 value_tag
= ipp_options
[j
].value_tag
;
216 else if (group_tag
!= IPP_TAG_JOB
)
218 else if (!strcasecmp(options
[i
].value
, "true") ||
219 !strcasecmp(options
[i
].value
, "false"))
220 value_tag
= IPP_TAG_BOOLEAN
;
222 value_tag
= IPP_TAG_NAME
;
225 * Count the number of values...
228 for (count
= 1, sep
= options
[i
].value
; *sep
; sep
++)
233 * Skip quoted option value...
238 while (*sep
&& *sep
!= '\'')
244 else if (*sep
== '\"')
247 * Skip quoted option value...
252 while (*sep
&& *sep
!= '\"')
258 else if (*sep
== ',')
260 else if (*sep
== '\\' && sep
[1])
264 DEBUG_printf(("cupsEncodeOptions2: option = \'%s\', count = %d\n",
265 options
[i
].name
, count
));
268 * Allocate memory for the attribute values...
271 if ((attr
= _ipp_add_attr(ipp
, count
)) == NULL
)
277 DEBUG_puts("cupsEncodeOptions2: Ran out of memory for attributes!");
282 * Now figure out what type of value we have...
285 attr
->group_tag
= group_tag
;
286 attr
->value_tag
= value_tag
;
289 * Copy the name over...
292 if ((attr
->name
= strdup(options
[i
].name
)) == NULL
)
298 DEBUG_puts("cupsEncodeOptions2: Ran out of memory for name!");
305 * Make a copy of the value we can fiddle with...
308 if ((copy
= strdup(options
[i
].value
)) == NULL
)
314 DEBUG_puts("cupsEncodeOptions2: Ran out of memory for value copy!");
323 * Since we have a single value, use the value directly...
326 val
= options
[i
].value
;
331 * Scan the value string for values...
334 for (j
= 0; j
< count
; val
= sep
, j
++)
337 * Find the end of this value and mark it if needed...
340 if ((sep
= strchr(val
, ',')) != NULL
)
343 sep
= val
+ strlen(val
);
346 * Copy the option value(s) over as needed by the type...
349 switch (attr
->value_tag
)
351 case IPP_TAG_INTEGER
:
354 * Integer/enumeration value...
357 attr
->values
[j
].integer
= strtol(val
, &s
, 0);
359 DEBUG_printf(("cupsEncodeOptions2: Added integer option value %d...\n",
360 attr
->values
[j
].integer
));
363 case IPP_TAG_BOOLEAN
:
364 if (!strcasecmp(val
, "true") ||
365 !strcasecmp(val
, "on") ||
366 !strcasecmp(val
, "yes"))
369 * Boolean value - true...
372 attr
->values
[j
].boolean
= 1;
374 DEBUG_puts("cupsEncodeOptions2: Added boolean true value...");
379 * Boolean value - false...
382 attr
->values
[j
].boolean
= 0;
384 DEBUG_puts("cupsEncodeOptions2: Added boolean false value...");
395 attr
->values
[j
].range
.lower
= 1;
399 attr
->values
[j
].range
.lower
= strtol(val
, &s
, 0);
404 attr
->values
[j
].range
.upper
= strtol(s
+ 1, NULL
, 0);
406 attr
->values
[j
].range
.upper
= 2147483647;
409 attr
->values
[j
].range
.upper
= attr
->values
[j
].range
.lower
;
411 DEBUG_printf(("cupsEncodeOptions2: Added range option value %d-%d...\n",
412 attr
->values
[j
].range
.lower
,
413 attr
->values
[j
].range
.upper
));
416 case IPP_TAG_RESOLUTION
:
421 attr
->values
[j
].resolution
.xres
= strtol(val
, &s
, 0);
424 attr
->values
[j
].resolution
.yres
= strtol(s
+ 1, &s
, 0);
426 attr
->values
[j
].resolution
.yres
= attr
->values
[j
].resolution
.xres
;
428 if (strcasecmp(s
, "dpc") == 0)
429 attr
->values
[j
].resolution
.units
= IPP_RES_PER_CM
;
431 attr
->values
[j
].resolution
.units
= IPP_RES_PER_INCH
;
433 DEBUG_printf(("cupsEncodeOptions2: Added resolution option value %s...\n",
437 case IPP_TAG_STRING
:
442 attr
->values
[j
].unknown
.length
= strlen(val
);
443 attr
->values
[j
].unknown
.data
= strdup(val
);
445 DEBUG_printf(("cupsEncodeOptions2: Added octet-string value \"%s\"...\n",
446 attr
->values
[j
].unknown
.data
));
450 if ((attr
->values
[j
].string
.text
= strdup(val
)) == NULL
)
456 DEBUG_puts("cupsEncodeOptions2: Ran out of memory for string!");
460 DEBUG_printf(("cupsEncodeOptions2: Added string value \"%s\"...\n",
470 * End of "$Id: encode.c 4918 2006-01-12 05:14:40Z mike $".