]> git.ipfire.org Git - thirdparty/cups.git/blob - cups/ipp-support.c
Merge changes from CUPS 1.7svn-r10861.
[thirdparty/cups.git] / cups / ipp-support.c
1 /*
2 * "$Id: ipp-support.c 9371 2010-11-17 06:21:32Z mike $"
3 *
4 * Internet Printing Protocol support functions for CUPS.
5 *
6 * Copyright 2007-2013 by Apple Inc.
7 * Copyright 1997-2007 by Easy Software Products, all rights reserved.
8 *
9 * These coded instructions, statements, and computer programs are the
10 * property of Apple Inc. and are protected by Federal copyright
11 * law. Distribution and use rights are outlined in the file "LICENSE.txt"
12 * which should have been included with this file. If this file is
13 * file is missing or damaged, see the license at "http://www.cups.org/".
14 *
15 * This file is subject to the Apple OS-Developed Software exception.
16 *
17 * Contents:
18 *
19 * ippAttributeString() - Convert the attribute's value to a string.
20 * ippCreateRequestedArray() - Create a CUPS array of attribute names from
21 * the given requested-attributes attribute.
22 * ippEnumString() - Return a string corresponding to the enum
23 * value.
24 * ippEnumValue() - Return the value associated with a given enum
25 * string.
26 * ippErrorString() - Return a name for the given status code.
27 * ippErrorValue() - Return a status code for the given name.
28 * ippOpString() - Return a name for the given operation id.
29 * ippOpValue() - Return an operation id for the given name.
30 * ippPort() - Return the default IPP port number.
31 * ippSetPort() - Set the default port number.
32 * ippTagString() - Return the tag name corresponding to a tag
33 * value.
34 * ippTagValue() - Return the tag value corresponding to a tag
35 * name.
36 * ipp_col_string() - Convert a collection to a string.
37 */
38
39 /*
40 * Include necessary headers...
41 */
42
43 #include "cups-private.h"
44
45
46 /*
47 * Local globals...
48 */
49
50 static const char * const ipp_status_oks[] = /* "OK" status codes */
51 { /* (name) = abandoned standard value */
52 "successful-ok",
53 "successful-ok-ignored-or-substituted-attributes",
54 "successful-ok-conflicting-attributes",
55 "successful-ok-ignored-subscriptions",
56 "(successful-ok-ignored-notifications)",
57 "successful-ok-too-many-events",
58 "(successful-ok-but-cancel-subscription)",
59 "successful-ok-events-complete"
60 },
61 * const ipp_status_400s[] = /* Client errors */
62 { /* (name) = abandoned standard value */
63 "client-error-bad-request",
64 "client-error-forbidden",
65 "client-error-not-authenticated",
66 "client-error-not-authorized",
67 "client-error-not-possible",
68 "client-error-timeout",
69 "client-error-not-found",
70 "client-error-gone",
71 "client-error-request-entity-too-large",
72 "client-error-request-value-too-long",
73 "client-error-document-format-not-supported",
74 "client-error-attributes-or-values-not-supported",
75 "client-error-uri-scheme-not-supported",
76 "client-error-charset-not-supported",
77 "client-error-conflicting-attributes",
78 "client-error-compression-not-supported",
79 "client-error-compression-error",
80 "client-error-document-format-error",
81 "client-error-document-access-error",
82 "client-error-attributes-not-settable",
83 "client-error-ignored-all-subscriptions",
84 "client-error-too-many-subscriptions",
85 "(client-error-ignored-all-notifications)",
86 "(client-error-client-print-support-file-not-found)",
87 "client-error-document-password-error",
88 "client-error-document-permission-error",
89 "client-error-document-security-error",
90 "client-error-document-unprintable-error"
91 },
92 * const ipp_status_480s[] = /* Vendor client errors */
93 {
94 /* 0x0480 - 0x048F */
95 "0x0480",
96 "0x0481",
97 "0x0482",
98 "0x0483",
99 "0x0484",
100 "0x0485",
101 "0x0486",
102 "0x0487",
103 "0x0488",
104 "0x0489",
105 "0x048A",
106 "0x048B",
107 "0x048C",
108 "0x048D",
109 "0x048E",
110 "0x048F",
111 /* 0x0490 - 0x049F */
112 "0x0490",
113 "0x0491",
114 "0x0492",
115 "0x0493",
116 "0x0494",
117 "0x0495",
118 "0x0496",
119 "0x0497",
120 "0x0498",
121 "0x0499",
122 "0x049A",
123 "0x049B",
124 "cups-error-account-info-needed",
125 "cups-error-account-closed",
126 "cups-error-account-limit-reached",
127 "cups-error-account-authorization-failed"
128 },
129 * const ipp_status_500s[] = /* Server errors */
130 {
131 "server-error-internal-error",
132 "server-error-operation-not-supported",
133 "server-error-service-unavailable",
134 "server-error-version-not-supported",
135 "server-error-device-error",
136 "server-error-temporary-error",
137 "server-error-not-accepting-jobs",
138 "server-error-busy",
139 "server-error-job-canceled",
140 "server-error-multiple-document-jobs-not-supported",
141 "server-error-printer-is-deactivated",
142 "server-error-too-many-jobs",
143 "server-error-too-many-documents"
144 },
145 * const ipp_status_1000s[] = /* CUPS internal */
146 {
147 "cups-authentication-canceled",
148 "cups-pki-error",
149 "cups-upgrade-required"
150 };
151 static const char * const ipp_std_ops[] =
152 {
153 /* 0x0000 - 0x000f */
154 "0x0000",
155 "0x0001",
156 "Print-Job",
157 "Print-URI",
158 "Validate-Job",
159 "Create-Job",
160 "Send-Document",
161 "Send-URI",
162 "Cancel-Job",
163 "Get-Job-Attributes",
164 "Get-Jobs",
165 "Get-Printer-Attributes",
166 "Hold-Job",
167 "Release-Job",
168 "Restart-Job",
169 "0x000f",
170
171 /* 0x0010 - 0x001f */
172 "Pause-Printer",
173 "Resume-Printer",
174 "Purge-Jobs",
175 "Set-Printer-Attributes",
176 "Set-Job-Attributes",
177 "Get-Printer-Supported-Values",
178 "Create-Printer-Subscription",
179 "Create-Job-Subscription",
180 "Get-Subscription-Attributes",
181 "Get-Subscriptions",
182 "Renew-Subscription",
183 "Cancel-Subscription",
184 "Get-Notifications",
185 "(Send-Notifications)",
186 "(Get-Resource-Attributes)",
187 "(Get-Resource-Data)",
188
189 /* 0x0020 - 0x002f */
190 "(Get-Resources)",
191 "(Get-Printer-Support-Files)",
192 "Enable-Printer",
193 "Disable-Printer",
194 "Pause-Printer-After-Current-Job",
195 "Hold-New-Jobs",
196 "Release-Held-New-Jobs",
197 "Deactivate-Printer",
198 "Activate-Printer",
199 "Restart-Printer",
200 "Shutdown-Printer",
201 "Startup-Printer",
202 "Reprocess-Job",
203 "Cancel-Current-Job",
204 "Suspend-Current-Job",
205 "Resume-Job",
206
207 /* 0x0030 - 0x003d */
208 "Promote-Job",
209 "Schedule-Job-After",
210 "0x0032",
211 "Cancel-Document",
212 "Get-Document-Attributes",
213 "Get-Documents",
214 "Delete-Document",
215 "Set-Document-Attributes",
216 "Cancel-Jobs",
217 "Cancel-My-Jobs",
218 "Resubmit-Job",
219 "Close-Job",
220 "Identify-Printer",
221 "Validate-Document"
222 },
223 * const ipp_cups_ops[] =
224 {
225 "CUPS-Get-Default",
226 "CUPS-Get-Printers",
227 "CUPS-Add-Modify-Printer",
228 "CUPS-Delete-Printer",
229 "CUPS-Get-Classes",
230 "CUPS-Add-Modify-Class",
231 "CUPS-Delete-Class",
232 "CUPS-Accept-Jobs",
233 "CUPS-Reject-Jobs",
234 "CUPS-Set-Default",
235 "CUPS-Get-Devices",
236 "CUPS-Get-PPDs",
237 "CUPS-Move-Job",
238 "CUPS-Authenticate-Job",
239 "CUPS-Get-PPD"
240 },
241 * const ipp_cups_ops2[] =
242 {
243 "CUPS-Get-Document"
244 },
245 * const ipp_tag_names[] =
246 { /* Value/group tag names */
247 "zero", /* 0x00 */
248 "operation-attributes-tag",
249 /* 0x01 */
250 "job-attributes-tag", /* 0x02 */
251 "end-of-attributes-tag",
252 /* 0x03 */
253 "printer-attributes-tag",
254 /* 0x04 */
255 "unsupported-attributes-tag",
256 /* 0x05 */
257 "subscription-attributes-tag",
258 /* 0x06 */
259 "event-notification-attributes-tag",
260 /* 0x07 */
261 "(resource-attributes-tag)",
262 /* 0x08 */
263 "document-attributes-tag",
264 /* 0x09 */
265 "0x0a", /* 0x0a */
266 "0x0b", /* 0x0b */
267 "0x0c", /* 0x0c */
268 "0x0d", /* 0x0d */
269 "0x0e", /* 0x0e */
270 "0x0f", /* 0x0f */
271 "unsupported", /* 0x10 */
272 "default", /* 0x11 */
273 "unknown", /* 0x12 */
274 "no-value", /* 0x13 */
275 "0x14", /* 0x14 */
276 "not-settable", /* 0x15 */
277 "delete-attribute", /* 0x16 */
278 "admin-define", /* 0x17 */
279 "0x18", /* 0x18 */
280 "0x19", /* 0x19 */
281 "0x1a", /* 0x1a */
282 "0x1b", /* 0x1b */
283 "0x1c", /* 0x1c */
284 "0x1d", /* 0x1d */
285 "0x1e", /* 0x1e */
286 "0x1f", /* 0x1f */
287 "0x20", /* 0x20 */
288 "integer", /* 0x21 */
289 "boolean", /* 0x22 */
290 "enum", /* 0x23 */
291 "0x24", /* 0x24 */
292 "0x25", /* 0x25 */
293 "0x26", /* 0x26 */
294 "0x27", /* 0x27 */
295 "0x28", /* 0x28 */
296 "0x29", /* 0x29 */
297 "0x2a", /* 0x2a */
298 "0x2b", /* 0x2b */
299 "0x2c", /* 0x2c */
300 "0x2d", /* 0x2d */
301 "0x2e", /* 0x2e */
302 "0x2f", /* 0x2f */
303 "octetString", /* 0x30 */
304 "dateTime", /* 0x31 */
305 "resolution", /* 0x32 */
306 "rangeOfInteger", /* 0x33 */
307 "collection", /* 0x34 */
308 "textWithLanguage", /* 0x35 */
309 "nameWithLanguage", /* 0x36 */
310 "endCollection", /* 0x37 */
311 "0x38", /* 0x38 */
312 "0x39", /* 0x39 */
313 "0x3a", /* 0x3a */
314 "0x3b", /* 0x3b */
315 "0x3c", /* 0x3c */
316 "0x3d", /* 0x3d */
317 "0x3e", /* 0x3e */
318 "0x3f", /* 0x3f */
319 "0x40", /* 0x40 */
320 "textWithoutLanguage",/* 0x41 */
321 "nameWithoutLanguage",/* 0x42 */
322 "0x43", /* 0x43 */
323 "keyword", /* 0x44 */
324 "uri", /* 0x45 */
325 "uriScheme", /* 0x46 */
326 "charset", /* 0x47 */
327 "naturalLanguage", /* 0x48 */
328 "mimeMediaType", /* 0x49 */
329 "memberAttrName" /* 0x4a */
330 };
331 static const char * const ipp_document_states[] =
332 { /* document-state-enums */
333 "pending",
334 "4",
335 "processing",
336 "6",
337 "canceled",
338 "aborted",
339 "completed"
340 },
341 * const ipp_finishings[] =
342 { /* finishings enums */
343 "none",
344 "staple",
345 "punch",
346 "cover",
347 "bind",
348 "saddle-stitch",
349 "edge-stitch",
350 "fold",
351 "trim",
352 "bale",
353 "booklet-maker",
354 "jog-offset",
355 "15",
356 "16",
357 "17",
358 "18",
359 "19",
360 "staple-top-left",
361 "staple-bottom-left",
362 "staple-top-right",
363 "staple-bottom-right",
364 "edge-stitch-left",
365 "edge-stitch-top",
366 "edge-stitch-right",
367 "edge-stitch-bottom",
368 "staple-dual-left",
369 "staple-dual-top",
370 "staple-dual-right",
371 "staple-dual-bottom",
372 "32",
373 "33",
374 "34",
375 "35",
376 "36",
377 "37",
378 "38",
379 "39",
380 "40",
381 "41",
382 "42",
383 "43",
384 "44",
385 "45",
386 "46",
387 "47",
388 "48",
389 "49",
390 "bind-left",
391 "bind-top",
392 "bind-right",
393 "bind-bottom",
394 "54",
395 "55",
396 "56",
397 "57",
398 "58",
399 "59",
400 "trim-after-pages",
401 "trim-after-documents",
402 "trim-after-copies",
403 "trim-after-job"
404 },
405 * const ipp_finishings_vendor[] =
406 {
407 /* 0x40000000 to 0x4000000F */
408 "0x40000000",
409 "0x40000001",
410 "0x40000002",
411 "0x40000003",
412 "0x40000004",
413 "0x40000005",
414 "0x40000006",
415 "0x40000007",
416 "0x40000008",
417 "0x40000009",
418 "0x4000000A",
419 "0x4000000B",
420 "0x4000000C",
421 "0x4000000D",
422 "0x4000000E",
423 "0x4000000F",
424 /* 0x40000010 to 0x4000001F */
425 "0x40000010",
426 "0x40000011",
427 "0x40000012",
428 "0x40000013",
429 "0x40000014",
430 "0x40000015",
431 "0x40000016",
432 "0x40000017",
433 "0x40000018",
434 "0x40000019",
435 "0x4000001A",
436 "0x4000001B",
437 "0x4000001C",
438 "0x4000001D",
439 "0x4000001E",
440 "0x4000001F",
441 /* 0x40000020 to 0x4000002F */
442 "0x40000020",
443 "0x40000021",
444 "0x40000022",
445 "0x40000023",
446 "0x40000024",
447 "0x40000025",
448 "0x40000026",
449 "0x40000027",
450 "0x40000028",
451 "0x40000029",
452 "0x4000002A",
453 "0x4000002B",
454 "0x4000002C",
455 "0x4000002D",
456 "0x4000002E",
457 "0x4000002F",
458 /* 0x40000030 to 0x4000003F */
459 "0x40000030",
460 "0x40000031",
461 "0x40000032",
462 "0x40000033",
463 "0x40000034",
464 "0x40000035",
465 "0x40000036",
466 "0x40000037",
467 "0x40000038",
468 "0x40000039",
469 "0x4000003A",
470 "0x4000003B",
471 "0x4000003C",
472 "0x4000003D",
473 "0x4000003E",
474 "0x4000003F",
475 /* 0x40000040 - 0x4000004F */
476 "0x40000040",
477 "0x40000041",
478 "0x40000042",
479 "0x40000043",
480 "0x40000044",
481 "0x40000045",
482 "punch-top-left",
483 "punch-bottom-left",
484 "punch-top-right",
485 "punch-bottom-right",
486 "punch-dual-left",
487 "punch-dual-top",
488 "punch-dual-right",
489 "punch-dual-bottom",
490 "punch-triple-left",
491 "punch-triple-top",
492 /* 0x40000050 - 0x40000055 */
493 "punch-triple-right",
494 "punch-triple-bottom",
495 "punch-quad-left",
496 "punch-quad-top",
497 "punch-quad-right",
498 "punch-quad-bottom",
499 },
500 * const ipp_job_collation_types[] =
501 { /* job-collation-type enums */
502 "uncollated-sheets",
503 "collated-documents",
504 "uncollated-documents"
505 },
506 * const ipp_job_states[] =
507 { /* job-state enums */
508 "pending",
509 "pending-held",
510 "processing",
511 "processing-stopped",
512 "canceled",
513 "aborted",
514 "completed"
515 },
516 * const ipp_orientation_requesteds[] =
517 { /* orientation-requested enums */
518 "portrait",
519 "landscape",
520 "reverse-landscape",
521 "reverse-portrait"
522 },
523 * const ipp_print_qualities[] =
524 { /* print-quality enums */
525 "draft",
526 "normal",
527 "high"
528 },
529 * const ipp_printer_states[] =
530 { /* printer-state enums */
531 "idle",
532 "processing",
533 "stopped",
534 };
535
536
537 /*
538 * Local functions...
539 */
540
541 static size_t ipp_col_string(ipp_t *col, char *buffer, size_t bufsize);
542
543
544 /*
545 * 'ippAttributeString()' - Convert the attribute's value to a string.
546 *
547 * Returns the number of bytes that would be written, not including the
548 * trailing nul. The buffer pointer can be NULL to get the required length,
549 * just like (v)snprintf.
550 *
551 * @since CUPS 1.6/OS X 10.8@
552 */
553
554 size_t /* O - Number of bytes less nul */
555 ippAttributeString(
556 ipp_attribute_t *attr, /* I - Attribute */
557 char *buffer, /* I - String buffer or NULL */
558 size_t bufsize) /* I - Size of string buffer */
559 {
560 int i; /* Looping var */
561 char *bufptr, /* Pointer into buffer */
562 *bufend, /* End of buffer */
563 temp[256]; /* Temporary string */
564 const char *ptr, /* Pointer into string */
565 *end; /* Pointer to end of string */
566 _ipp_value_t *val; /* Current value */
567
568
569 if (!attr || !attr->name)
570 {
571 if (buffer)
572 *buffer = '\0';
573
574 return (0);
575 }
576
577 bufptr = buffer;
578 if (buffer)
579 bufend = buffer + bufsize - 1;
580 else
581 bufend = NULL;
582
583 for (i = attr->num_values, val = attr->values; i > 0; i --, val ++)
584 {
585 if (val > attr->values)
586 {
587 if (buffer && bufptr < bufend)
588 *bufptr++ = ',';
589 else
590 bufptr ++;
591 }
592
593 switch (attr->value_tag & ~IPP_TAG_COPY)
594 {
595 case IPP_TAG_ENUM :
596 ptr = ippEnumString(attr->name, val->integer);
597
598 if (buffer && bufptr < bufend)
599 strlcpy(bufptr, ptr, bufend - bufptr + 1);
600
601 bufptr += strlen(ptr);
602 break;
603
604 case IPP_TAG_INTEGER :
605 if (buffer && bufptr < bufend)
606 bufptr += snprintf(bufptr, bufend - bufptr + 1, "%d", val->integer);
607 else
608 bufptr += snprintf(temp, sizeof(temp), "%d", val->integer);
609 break;
610
611 case IPP_TAG_BOOLEAN :
612 if (buffer && bufptr < bufend)
613 strlcpy(bufptr, val->boolean ? "true" : "false",
614 bufend - bufptr + 1);
615
616 bufptr += val->boolean ? 4 : 5;
617 break;
618
619 case IPP_TAG_RANGE :
620 if (buffer && bufptr < bufend)
621 bufptr += snprintf(bufptr, bufend - bufptr + 1, "%d-%d",
622 val->range.lower, val->range.upper);
623 else
624 bufptr += snprintf(temp, sizeof(temp), "%d-%d", val->range.lower,
625 val->range.upper);
626 break;
627
628 case IPP_TAG_RESOLUTION :
629 if (buffer && bufptr < bufend)
630 bufptr += snprintf(bufptr, bufend - bufptr + 1, "%dx%d%s",
631 val->resolution.xres, val->resolution.yres,
632 val->resolution.units == IPP_RES_PER_INCH ?
633 "dpi" : "dpcm");
634 else
635 bufptr += snprintf(temp, sizeof(temp), "%dx%d%s",
636 val->resolution.xres, val->resolution.yres,
637 val->resolution.units == IPP_RES_PER_INCH ?
638 "dpi" : "dpcm");
639 break;
640
641 case IPP_TAG_DATE :
642 {
643 unsigned year; /* Year */
644
645 year = (val->date[0] << 8) + val->date[1];
646
647 if (val->date[9] == 0 && val->date[10] == 0)
648 snprintf(temp, sizeof(temp), "%04u-%02u-%02uT%02u:%02u:%02uZ",
649 year, val->date[2], val->date[3], val->date[4],
650 val->date[5], val->date[6]);
651 else
652 snprintf(temp, sizeof(temp),
653 "%04u-%02u-%02uT%02u:%02u:%02u%c%02u%02u",
654 year, val->date[2], val->date[3], val->date[4],
655 val->date[5], val->date[6], val->date[8], val->date[9],
656 val->date[10]);
657
658 if (buffer && bufptr < bufend)
659 strlcpy(bufptr, temp, bufend - bufptr + 1);
660
661 bufptr += strlen(temp);
662 }
663 break;
664
665 case IPP_TAG_TEXT :
666 case IPP_TAG_NAME :
667 case IPP_TAG_KEYWORD :
668 case IPP_TAG_CHARSET :
669 case IPP_TAG_URI :
670 case IPP_TAG_URISCHEME :
671 case IPP_TAG_MIMETYPE :
672 case IPP_TAG_LANGUAGE :
673 case IPP_TAG_TEXTLANG :
674 case IPP_TAG_NAMELANG :
675 if (!val->string.text)
676 break;
677
678 for (ptr = val->string.text; *ptr; ptr ++)
679 {
680 if (*ptr == '\\' || *ptr == '\"' || *ptr == '[')
681 {
682 if (buffer && bufptr < bufend)
683 *bufptr = '\\';
684 bufptr ++;
685 }
686
687 if (buffer && bufptr < bufend)
688 *bufptr = *ptr;
689 bufptr ++;
690 }
691
692 if (val->string.language)
693 {
694 /*
695 * Add "[language]" to end of string...
696 */
697
698 if (buffer && bufptr < bufend)
699 *bufptr = '[';
700 bufptr ++;
701
702 if (buffer && bufptr < bufend)
703 strlcpy(bufptr, val->string.language, bufend - bufptr);
704 bufptr += strlen(val->string.language);
705
706 if (buffer && bufptr < bufend)
707 *bufptr = ']';
708 bufptr ++;
709 }
710 break;
711
712 case IPP_TAG_BEGIN_COLLECTION :
713 if (buffer && bufptr < bufend)
714 bufptr += ipp_col_string(val->collection, bufptr,
715 bufend - bufptr + 1);
716 else
717 bufptr += ipp_col_string(val->collection, NULL, 0);
718 break;
719
720 case IPP_TAG_STRING :
721 for (ptr = val->unknown.data, end = ptr + val->unknown.length;
722 ptr < end; ptr ++)
723 {
724 if (*ptr == '\\' || _cups_isspace(*ptr))
725 {
726 if (buffer && bufptr < bufend)
727 *bufptr = '\\';
728 bufptr ++;
729
730 if (buffer && bufptr < bufend)
731 *bufptr = *ptr;
732 bufptr ++;
733 }
734 else if (!isprint(*ptr & 255))
735 {
736 if (buffer && bufptr < bufend)
737 bufptr += snprintf(bufptr, bufend - bufptr + 1, "\\%03o",
738 *ptr & 255);
739 else
740 bufptr += snprintf(temp, sizeof(temp), "\\%03o",
741 *ptr & 255);
742 }
743 else
744 {
745 if (buffer && bufptr < bufend)
746 *bufptr = *ptr;
747 bufptr ++;
748 }
749 }
750 break;
751
752 default :
753 ptr = ippTagString(attr->value_tag);
754 if (buffer && bufptr < bufend)
755 strlcpy(bufptr, ptr, bufend - bufptr + 1);
756 bufptr += strlen(ptr);
757 break;
758 }
759 }
760
761 if (buffer && bufptr < bufend)
762 *bufptr = '\0';
763 else if (bufend)
764 *bufend = '\0';
765
766 return (bufptr - buffer);
767 }
768
769
770 /*
771 * 'ippCreateRequestedArray()' - Create a CUPS array of attribute names from the
772 * given requested-attributes attribute.
773 *
774 * This function creates a (sorted) CUPS array of attribute names matching the
775 * list of "requested-attribute" values supplied in an IPP request. All IANA-
776 * registered values are supported in addition to the CUPS IPP extension
777 * attributes.
778 *
779 * The @code request@ parameter specifies the request message that was read from
780 * the client.
781 *
782 * @code NULL@ is returned if all attributes should be returned. Otherwise, the
783 * result is a sorted array of attribute names, where @code cupsArrayFind(array,
784 * "attribute-name")@ will return a non-NULL pointer. The array must be freed
785 * using the @code cupsArrayDelete@ function.
786 *
787 * @since CUPS 1.7@
788 */
789
790 cups_array_t * /* O - CUPS array or @code NULL@ if all */
791 ippCreateRequestedArray(ipp_t *request) /* I - IPP request */
792 {
793 int i, j, /* Looping vars */
794 count, /* Number of values */
795 added; /* Was name added? */
796 ipp_attribute_t *requested; /* requested-attributes attribute */
797 cups_array_t *ra; /* Requested attributes array */
798 const char *value; /* Current value */
799 /* The following lists come from the current IANA IPP registry of attributes */
800 static const char * const document_description[] =
801 { /* document-description group */
802 "compression",
803 "copies-actual",
804 "cover-back-actual",
805 "cover-front-actual",
806 "current-page-order",
807 "date-time-at-completed",
808 "date-time-at-creation",
809 "date-time-at-processing",
810 "detailed-status-messages",
811 "document-access-errors",
812 "document-charset",
813 "document-digital-signature",
814 "document-format",
815 "document-format-details",
816 "document-format-detected",
817 "document-format-version",
818 "document-format-version-detected",
819 "document-job-id",
820 "document-job-uri",
821 "document-message",
822 "document-metadata",
823 "document-name",
824 "document-natural-language",
825 "document-number",
826 "document-printer-uri",
827 "document-state",
828 "document-state-message",
829 "document-state-reasons",
830 "document-uri",
831 "document-uuid",
832 "errors-count",
833 "finishings-actual",
834 "finishings-col-actual",
835 "force-front-side-actual",
836 "imposition-template-actual",
837 "impressions",
838 "impressions-completed",
839 "impressions-completed-current-copy",
840 "insert-sheet-actual",
841 "k-octets",
842 "k-octets-processed",
843 "last-document",
844 "media-actual",
845 "media-col-actual",
846 "media-input-tray-check-actual",
847 "media-sheets",
848 "media-sheets-completed",
849 "more-info",
850 "number-up-actual",
851 "orientation-requested-actual",
852 "output-bin-actual",
853 "output-device-assigned",
854 "overrides-actual",
855 "page-delivery-actual",
856 "page-order-received-actual",
857 "page-ranges-actual",
858 "pages",
859 "pages-completed",
860 "pages-completed-current-copy",
861 "presentation-direction-number-up-actual",
862 "print-color-mode-actual",
863 "print-content-optimize-actual",
864 "print-quality-actual",
865 "print-rendering-intent-actual",
866 "printer-resolution-actual",
867 "printer-up-time",
868 "separator-sheets-actual",
869 "sheet-completed-copy-number",
870 "sides-actual",
871 "time-at-completed",
872 "time-at-creation",
873 "time-at-processing",
874 "x-image-position-actual",
875 "x-image-shift-actual",
876 "x-side1-image-shift-actual",
877 "x-side2-image-shift-actual",
878 "y-image-position-actual",
879 "y-image-shift-actual",
880 "y-side1-image-shift-actual",
881 "y-side2-image-shift-actual"
882 };
883 static const char * const document_template[] =
884 { /* document-template group */
885 "copies",
886 "copies-default",
887 "copies-supported",
888 "cover-back",
889 "cover-back-default",
890 "cover-back-supported",
891 "cover-front",
892 "cover-front-default",
893 "cover-front-supported",
894 "feed-orientation",
895 "feed-orientation-default",
896 "feed-orientation-supported",
897 "finishings",
898 "finishings-col",
899 "finishings-col-default",
900 "finishings-col-supported",
901 "finishings-default",
902 "finishings-supported",
903 "font-name-requested",
904 "font-name-requested-default",
905 "font-name-requested-supported",
906 "font-size-requested",
907 "font-size-requested-default",
908 "font-size-requested-supported",
909 "force-front-side",
910 "force-front-side-default",
911 "force-front-side-supported",
912 "imposition-template",
913 "imposition-template-default",
914 "imposition-template-supported",
915 "insert-after-page-number-supported",
916 "insert-count-supported",
917 "insert-sheet",
918 "insert-sheet-default",
919 "insert-sheet-supported",
920 "max-stitching-locations-supported",
921 "media",
922 "media-back-coating-supported",
923 "media-bottom-margin-supported",
924 "media-col",
925 "media-col-default",
926 "media-col-supported",
927 "media-color-supported",
928 "media-default",
929 "media-front-coating-supported",
930 "media-grain-supported",
931 "media-hole-count-supported",
932 "media-info-supported",
933 "media-input-tray-check",
934 "media-input-tray-check-default",
935 "media-input-tray-check-supported",
936 "media-key-supported",
937 "media-left-margin-supported",
938 "media-order-count-supported",
939 "media-pre-printed-supported",
940 "media-recycled-supported",
941 "media-right-margin-supported",
942 "media-size-supported",
943 "media-source-supported",
944 "media-supported",
945 "media-thickness-supported",
946 "media-top-margin-supported",
947 "media-type-supported",
948 "media-weight-metric-supported",
949 "multiple-document-handling",
950 "multiple-document-handling-default",
951 "multiple-document-handling-supported",
952 "number-up",
953 "number-up-default",
954 "number-up-supported",
955 "orientation-requested",
956 "orientation-requested-default",
957 "orientation-requested-supported",
958 "overrides",
959 "overrides-supported",
960 "page-delivery",
961 "page-delivery-default",
962 "page-delivery-supported",
963 "page-order-received",
964 "page-order-received-default",
965 "page-order-received-supported",
966 "page-ranges",
967 "page-ranges-supported",
968 "pages-per-subset",
969 "pages-per-subset-supported",
970 "pdl-init-file",
971 "pdl-init-file-default",
972 "pdl-init-file-entry-supported",
973 "pdl-init-file-location-supported",
974 "pdl-init-file-name-subdirectory-supported",
975 "pdl-init-file-name-supported",
976 "pdl-init-file-supported",
977 "presentation-direction-number-up",
978 "presentation-direction-number-up-default",
979 "presentation-direction-number-up-supported",
980 "print-color-mode",
981 "print-color-mode-default",
982 "print-color-mode-supported",
983 "print-content-optimize",
984 "print-content-optimize-default",
985 "print-content-optimize-supported",
986 "print-quality",
987 "print-quality-default",
988 "print-quality-supported",
989 "print-rendering-intent",
990 "print-rendering-intent-default",
991 "print-rendering-intent-supported",
992 "printer-resolution",
993 "printer-resolution-default",
994 "printer-resolution-supported",
995 "separator-sheets",
996 "separator-sheets-default",
997 "separator-sheets-supported",
998 "sheet-collate",
999 "sheet-collate-default",
1000 "sheet-collate-supported",
1001 "sides",
1002 "sides-default",
1003 "sides-supported",
1004 "stitching-locations-supported",
1005 "stitching-offset-supported",
1006 "x-image-position",
1007 "x-image-position-default",
1008 "x-image-position-supported",
1009 "x-image-shift",
1010 "x-image-shift-default",
1011 "x-image-shift-supported",
1012 "x-side1-image-shift",
1013 "x-side1-image-shift-default",
1014 "x-side1-image-shift-supported",
1015 "x-side2-image-shift",
1016 "x-side2-image-shift-default",
1017 "x-side2-image-shift-supported",
1018 "y-image-position",
1019 "y-image-position-default",
1020 "y-image-position-supported",
1021 "y-image-shift",
1022 "y-image-shift-default",
1023 "y-image-shift-supported",
1024 "y-side1-image-shift",
1025 "y-side1-image-shift-default",
1026 "y-side1-image-shift-supported",
1027 "y-side2-image-shift",
1028 "y-side2-image-shift-default",
1029 "y-side2-image-shift-supported"
1030 };
1031 static const char * const job_description[] =
1032 { /* job-description group */
1033 "compression-supplied",
1034 "copies-actual",
1035 "cover-back-actual",
1036 "cover-front-actual",
1037 "current-page-order",
1038 "date-time-at-completed",
1039 "date-time-at-creation",
1040 "date-time-at-processing",
1041 "destination-statuses",
1042 "document-charset-supplied",
1043 "document-digital-signature-supplied",
1044 "document-format-details-supplied",
1045 "document-format-supplied",
1046 "document-message-supplied",
1047 "document-metadata",
1048 "document-name-supplied",
1049 "document-natural-language-supplied",
1050 "document-overrides-actual",
1051 "errors-count",
1052 "finishings-actual",
1053 "finishings-col-actual",
1054 "force-front-side-actual",
1055 "imposition-template-actual",
1056 "impressions-completed-current-copy",
1057 "insert-sheet-actual",
1058 "job-account-id-actual",
1059 "job-accounting-sheets-actual",
1060 "job-accounting-user-id-actual",
1061 "job-attribute-fidelity",
1062 "job-charge-info", /* CUPS extension */
1063 "job-collation-type",
1064 "job-collation-type-actual",
1065 "job-copies-actual",
1066 "job-cover-back-actual",
1067 "job-cover-front-actual",
1068 "job-detailed-status-message",
1069 "job-document-access-errors",
1070 "job-error-sheet-actual",
1071 "job-finishings-actual",
1072 "job-finishings-col-actual",
1073 "job-hold-until-actual",
1074 "job-id",
1075 "job-impressions",
1076 "job-impressions-completed",
1077 "job-k-octets",
1078 "job-k-octets-processed",
1079 "job-mandatory-attributes",
1080 "job-media-progress", /* CUPS extension */
1081 "job-media-sheets",
1082 "job-media-sheets-completed",
1083 "job-message-from-operator",
1084 "job-more-info",
1085 "job-name",
1086 "job-originating-host-name", /* CUPS extension */
1087 "job-originating-user-name",
1088 "job-originating-user-uri",
1089 "job-pages",
1090 "job-pages-completed",
1091 "job-pages-completed-current-copy",
1092 "job-printer-state-message", /* CUPS extension */
1093 "job-printer-state-reasons", /* CUPS extension */
1094 "job-printer-up-time",
1095 "job-printer-uri",
1096 "job-priority-actual",
1097 "job-save-printer-make-and-model",
1098 "job-sheet-message-actual",
1099 "job-sheets-actual",
1100 "job-sheets-col-actual",
1101 "job-state",
1102 "job-state-message",
1103 "job-state-reasons",
1104 "job-uri",
1105 "job-uuid",
1106 "media-actual",
1107 "media-col-actual",
1108 "media-check-input-tray-actual",
1109 "multiple-document-handling-actual",
1110 "number-of-documents",
1111 "number-of-intervening-jobs",
1112 "number-up-actual",
1113 "orientation-requested-actual",
1114 "original-requesting-user-name",
1115 "output-bin-actual",
1116 "output-device-assigned",
1117 "overrides-actual",
1118 "page-delivery-actual",
1119 "page-order-received-actual",
1120 "page-ranges-actual",
1121 "presentation-direction-number-up-actual",
1122 "print-color-mode-actual",
1123 "print-content-optimize-actual",
1124 "print-quality-actual",
1125 "print-rendering-intent-actual",
1126 "printer-resolution-actual",
1127 "separator-sheets-actual",
1128 "sheet-collate-actual",
1129 "sheet-completed-copy-number",
1130 "sheet-completed-document-number",
1131 "sides-actual",
1132 "time-at-completed",
1133 "time-at-creation",
1134 "time-at-processing",
1135 "warnings-count",
1136 "x-image-position-actual",
1137 "x-image-shift-actual",
1138 "x-side1-image-shift-actual",
1139 "x-side2-image-shift-actual",
1140 "y-image-position-actual",
1141 "y-image-shift-actual",
1142 "y-side1-image-shift-actual",
1143 "y-side2-image-shift-actual"
1144 };
1145 static const char * const job_template[] =
1146 { /* job-template group */
1147 "confirmation-sheet-print", /* IPP FaxOut */
1148 "confirmation-sheet-print-default",
1149 "copies",
1150 "copies-default",
1151 "copies-supported",
1152 "cover-back",
1153 "cover-back-default",
1154 "cover-back-supported",
1155 "cover-front",
1156 "cover-front-default",
1157 "cover-front-supported",
1158 "cover-sheet-info", /* IPP FaxOut */
1159 "cover-sheet-info-default",
1160 "cover-sheet-info-supported",
1161 "destination-uri-schemes-supported",/* IPP FaxOut */
1162 "destination-uris", /* IPP FaxOut */
1163 "destination-uris-supported",
1164 "feed-orientation",
1165 "feed-orientation-default",
1166 "feed-orientation-supported",
1167 "finishings",
1168 "finishings-col",
1169 "finishings-col-default",
1170 "finishings-col-supported",
1171 "finishings-default",
1172 "finishings-supported",
1173 "font-name-requested",
1174 "font-name-requested-default",
1175 "font-name-requested-supported",
1176 "font-size-requested",
1177 "font-size-requested-default",
1178 "font-size-requested-supported",
1179 "force-front-side",
1180 "force-front-side-default",
1181 "force-front-side-supported",
1182 "imposition-template",
1183 "imposition-template-default",
1184 "imposition-template-supported",
1185 "insert-after-page-number-supported",
1186 "insert-count-supported",
1187 "insert-sheet",
1188 "insert-sheet-default",
1189 "insert-sheet-supported",
1190 "job-account-id",
1191 "job-account-id-default",
1192 "job-account-id-supported",
1193 "job-accounting-sheets"
1194 "job-accounting-sheets-default"
1195 "job-accounting-sheets-supported"
1196 "job-accounting-user-id",
1197 "job-accounting-user-id-default",
1198 "job-accounting-user-id-supported",
1199 "job-copies",
1200 "job-copies-default",
1201 "job-copies-supported",
1202 "job-cover-back",
1203 "job-cover-back-default",
1204 "job-cover-back-supported",
1205 "job-cover-front",
1206 "job-cover-front-default",
1207 "job-cover-front-supported",
1208 "job-delay-output-until",
1209 "job-delay-output-until-default",
1210 "job-delay-output-until-supported",
1211 "job-delay-output-until-time",
1212 "job-delay-output-until-time-default",
1213 "job-delay-output-until-time-supported",
1214 "job-error-action",
1215 "job-error-action-default",
1216 "job-error-action-supported",
1217 "job-error-sheet",
1218 "job-error-sheet-default",
1219 "job-error-sheet-supported",
1220 "job-finishings",
1221 "job-finishings-col",
1222 "job-finishings-col-default",
1223 "job-finishings-col-supported",
1224 "job-finishings-default",
1225 "job-finishings-supported",
1226 "job-hold-until",
1227 "job-hold-until-default",
1228 "job-hold-until-supported",
1229 "job-hold-until-time",
1230 "job-hold-until-time-default",
1231 "job-hold-until-time-supported",
1232 "job-message-to-operator",
1233 "job-message-to-operator-default",
1234 "job-message-to-operator-supported",
1235 "job-phone-number",
1236 "job-phone-number-default",
1237 "job-phone-number-supported",
1238 "job-priority",
1239 "job-priority-default",
1240 "job-priority-supported",
1241 "job-recipient-name",
1242 "job-recipient-name-default",
1243 "job-recipient-name-supported",
1244 "job-save-disposition",
1245 "job-save-disposition-default",
1246 "job-save-disposition-supported",
1247 "job-sheets",
1248 "job-sheets-col",
1249 "job-sheets-col-default",
1250 "job-sheets-col-supported",
1251 "job-sheets-default",
1252 "job-sheets-supported",
1253 "logo-uri-schemes-supported",
1254 "max-save-info-supported",
1255 "max-stitching-locations-supported",
1256 "media",
1257 "media-back-coating-supported",
1258 "media-bottom-margin-supported",
1259 "media-col",
1260 "media-col-default",
1261 "media-col-supported",
1262 "media-color-supported",
1263 "media-default",
1264 "media-front-coating-supported",
1265 "media-grain-supported",
1266 "media-hole-count-supported",
1267 "media-info-supported",
1268 "media-input-tray-check",
1269 "media-input-tray-check-default",
1270 "media-input-tray-check-supported",
1271 "media-key-supported",
1272 "media-left-margin-supported",
1273 "media-order-count-supported",
1274 "media-pre-printed-supported",
1275 "media-recycled-supported",
1276 "media-right-margin-supported",
1277 "media-size-supported",
1278 "media-source-supported",
1279 "media-supported",
1280 "media-thickness-supported",
1281 "media-top-margin-supported",
1282 "media-type-supported",
1283 "media-weight-metric-supported",
1284 "multiple-document-handling",
1285 "multiple-document-handling-default",
1286 "multiple-document-handling-supported",
1287 "number-of-retries", /* IPP FaxOut */
1288 "number-of-retries-default",
1289 "number-of-retries-supported",
1290 "number-up",
1291 "number-up-default",
1292 "number-up-supported",
1293 "orientation-requested",
1294 "orientation-requested-default",
1295 "orientation-requested-supported",
1296 "output-bin",
1297 "output-bin-default",
1298 "output-bin-supported",
1299 "output-device",
1300 "output-device-default",
1301 "output-device-supported",
1302 "overrides",
1303 "overrides-supported",
1304 "page-delivery",
1305 "page-delivery-default",
1306 "page-delivery-supported",
1307 "page-order-received",
1308 "page-order-received-default",
1309 "page-order-received-supported",
1310 "page-ranges",
1311 "page-ranges-supported",
1312 "pages-per-subset",
1313 "pages-per-subset-supported",
1314 "pdl-init-file",
1315 "pdl-init-file-default",
1316 "pdl-init-file-entry-supported",
1317 "pdl-init-file-location-supported",
1318 "pdl-init-file-name-subdirectory-supported",
1319 "pdl-init-file-name-supported",
1320 "pdl-init-file-supported",
1321 "presentation-direction-number-up",
1322 "presentation-direction-number-up-default",
1323 "presentation-direction-number-up-supported",
1324 "print-color-mode",
1325 "print-color-mode-default",
1326 "print-color-mode-supported",
1327 "print-content-optimize",
1328 "print-content-optimize-default",
1329 "print-content-optimize-supported",
1330 "print-quality",
1331 "print-quality-default",
1332 "print-quality-supported",
1333 "print-rendering-intent",
1334 "print-rendering-intent-default",
1335 "print-rendering-intent-supported",
1336 "printer-resolution",
1337 "printer-resolution-default",
1338 "printer-resolution-supported",
1339 "proof-print",
1340 "proof-print-default",
1341 "proof-print-supported",
1342 "retry-interval", /* IPP FaxOut */
1343 "retry-interval-default",
1344 "retry-interval-supported",
1345 "retry-timeout", /* IPP FaxOut */
1346 "retry-timeout-default",
1347 "retry-timeout-supported",
1348 "save-disposition-supported",
1349 "save-document-format-default",
1350 "save-document-format-supported",
1351 "save-location-default",
1352 "save-location-supported",
1353 "save-name-subdirectory-supported",
1354 "save-name-supported",
1355 "separator-sheets",
1356 "separator-sheets-default",
1357 "separator-sheets-supported",
1358 "sheet-collate",
1359 "sheet-collate-default",
1360 "sheet-collate-supported",
1361 "sides",
1362 "sides-default",
1363 "sides-supported",
1364 "stitching-locations-supported",
1365 "stitching-offset-supported",
1366 "x-image-position",
1367 "x-image-position-default",
1368 "x-image-position-supported",
1369 "x-image-shift",
1370 "x-image-shift-default",
1371 "x-image-shift-supported",
1372 "x-side1-image-shift",
1373 "x-side1-image-shift-default",
1374 "x-side1-image-shift-supported",
1375 "x-side2-image-shift",
1376 "x-side2-image-shift-default",
1377 "x-side2-image-shift-supported",
1378 "y-image-position",
1379 "y-image-position-default",
1380 "y-image-position-supported",
1381 "y-image-shift",
1382 "y-image-shift-default",
1383 "y-image-shift-supported",
1384 "y-side1-image-shift",
1385 "y-side1-image-shift-default",
1386 "y-side1-image-shift-supported",
1387 "y-side2-image-shift",
1388 "y-side2-image-shift-default",
1389 "y-side2-image-shift-supported"
1390 };
1391 static const char * const printer_description[] =
1392 { /* printer-description group */
1393 "auth-info-required", /* CUPS extension */
1394 "charset-configured",
1395 "charset-supported",
1396 "color-supported",
1397 "compression-supported",
1398 "device-service-count",
1399 "device-uri", /* CUPS extension */
1400 "device-uuid",
1401 "document-charset-default",
1402 "document-charset-supported",
1403 "document-creation-attributes-supported",
1404 "document-digital-signature-default",
1405 "document-digital-signature-supported",
1406 "document-format-default",
1407 "document-format-details-default",
1408 "document-format-details-supported",
1409 "document-format-supported",
1410 "document-format-varying-attributes",
1411 "document-format-version-default",
1412 "document-format-version-supported",
1413 "document-natural-language-default",
1414 "document-natural-language-supported",
1415 "document-password-supported",
1416 "generated-natural-language-supported",
1417 "identify-actions-default",
1418 "identify-actions-supported",
1419 "input-source-supported",
1420 "ipp-features-supported",
1421 "ipp-versions-supported",
1422 "ippget-event-life",
1423 "job-authorization-uri-supported", /* CUPS extension */
1424 "job-constraints-supported",
1425 "job-creation-attributes-supported",
1426 "job-finishings-col-ready",
1427 "job-finishings-ready",
1428 "job-ids-supported",
1429 "job-impressions-supported",
1430 "job-k-limit", /* CUPS extension */
1431 "job-k-octets-supported",
1432 "job-media-sheets-supported",
1433 "job-page-limit", /* CUPS extension */
1434 "job-password-encryption-supported",
1435 "job-password-supported",
1436 "job-quota-period", /* CUPS extension */
1437 "job-resolvers-supported",
1438 "job-settable-attributes-supported",
1439 "job-spooling-supported",
1440 "marker-change-time", /* CUPS extension */
1441 "marker-colors", /* CUPS extension */
1442 "marker-high-levels", /* CUPS extension */
1443 "marker-levels", /* CUPS extension */
1444 "marker-low-levels", /* CUPS extension */
1445 "marker-message", /* CUPS extension */
1446 "marker-names", /* CUPS extension */
1447 "marker-types", /* CUPS extension */
1448 "media-col-ready",
1449 "media-ready",
1450 "member-names", /* CUPS extension */
1451 "member-uris", /* CUPS extension */
1452 "multiple-destination-uris-supported",/* IPP FaxOut */
1453 "multiple-document-jobs-supported",
1454 "multiple-operation-time-out",
1455 "multiple-operation-time-out-action",
1456 "natural-language-configured",
1457 "operations-supported",
1458 "pages-per-minute",
1459 "pages-per-minute-color",
1460 "pdl-override-supported",
1461 "port-monitor", /* CUPS extension */
1462 "port-monitor-supported", /* CUPS extension */
1463 "preferred-attributes-supported",
1464 "printer-alert",
1465 "printer-alert-description",
1466 "printer-charge-info",
1467 "printer-charge-info-uri",
1468 "printer-commands", /* CUPS extension */
1469 "printer-current-time",
1470 "printer-detailed-status-messages",
1471 "printer-device-id",
1472 "printer-dns-sd-name", /* CUPS extension */
1473 "printer-driver-installer",
1474 "printer-fax-log-uri", /* IPP FaxOut */
1475 "printer-fax-modem-info", /* IPP FaxOut */
1476 "printer-fax-modem-name", /* IPP FaxOut */
1477 "printer-fax-modem-number", /* IPP FaxOut */
1478 "printer-geo-location",
1479 "printer-get-attributes-supported",
1480 "printer-icc-profiles",
1481 "printer-icons",
1482 "printer-info",
1483 "printer-is-accepting-jobs",
1484 "printer-location",
1485 "printer-make-and-model",
1486 "printer-mandatory-job-attributes",
1487 "printer-message-date-time",
1488 "printer-message-from-operator",
1489 "printer-message-time",
1490 "printer-more-info",
1491 "printer-more-info-manufacturer",
1492 "printer-name",
1493 "printer-organization",
1494 "printer-organizational-unit",
1495 "printer-settable-attributes-supported",
1496 "printer-state",
1497 "printer-state-change-date-time",
1498 "printer-state-change-time",
1499 "printer-state-message",
1500 "printer-state-reasons",
1501 "printer-supply",
1502 "printer-supply-description",
1503 "printer-supply-info-uri",
1504 "printer-type", /* CUPS extension */
1505 "printer-up-time",
1506 "printer-uri-supported",
1507 "printer-uuid",
1508 "printer-xri-supported",
1509 "pwg-raster-document-resolution-supported",
1510 "pwg-raster-document-sheet-back",
1511 "pwg-raster-document-type-supported",
1512 "queued-job-count",
1513 "reference-uri-schemes-supported",
1514 "repertoire-supported",
1515 "requesting-user-name-allowed", /* CUPS extension */
1516 "requesting-user-name-denied", /* CUPS extension */
1517 "requesting-user-uri-supported",
1518 "subordinate-printers-supported",
1519 "uri-authentication-supported",
1520 "uri-security-supported",
1521 "user-defined-value-supported",
1522 "which-jobs-supported",
1523 "xri-authentication-supported",
1524 "xri-security-supported",
1525 "xri-uri-scheme-supported"
1526 };
1527 static const char * const subscription_description[] =
1528 { /* subscription-description group */
1529 "notify-job-id",
1530 "notify-lease-expiration-time",
1531 "notify-printer-up-time",
1532 "notify-printer-uri",
1533 "notify-sequence-number",
1534 "notify-subscriber-user-name",
1535 "notify-subscriber-user-uri",
1536 "notify-subscription-id",
1537 "subscriptions-uuid"
1538 };
1539 static const char * const subscription_template[] =
1540 { /* subscription-template group */
1541 "notify-attributes",
1542 "notify-attributes-supported",
1543 "notify-charset",
1544 "notify-events",
1545 "notify-events-default",
1546 "notify-events-supported",
1547 "notify-lease-duration",
1548 "notify-lease-duration-default",
1549 "notify-lease-duration-supported",
1550 "notify-max-events-supported",
1551 "notify-natural-language",
1552 "notify-pull-method",
1553 "notify-pull-method-supported",
1554 "notify-recipient-uri",
1555 "notify-schemes-supported",
1556 "notify-time-interval",
1557 "notify-user-data"
1558 };
1559
1560
1561 /*
1562 * Get the requested-attributes attribute...
1563 */
1564
1565 if ((requested = ippFindAttribute(request, "requested-attributes",
1566 IPP_TAG_KEYWORD)) == NULL)
1567 {
1568 /*
1569 * The Get-Jobs operation defaults to "job-id" and "job-uri", all others
1570 * default to "all"...
1571 */
1572
1573 if (ippGetOperation(request) == IPP_GET_JOBS)
1574 {
1575 ra = cupsArrayNew((cups_array_func_t)strcmp, NULL);
1576 cupsArrayAdd(ra, "job-id");
1577 cupsArrayAdd(ra, "job-uri");
1578
1579 return (ra);
1580 }
1581 else
1582 return (NULL);
1583 }
1584
1585 /*
1586 * If the attribute contains a single "all" keyword, return NULL...
1587 */
1588
1589 count = ippGetCount(requested);
1590 if (count == 1 && !strcmp(ippGetString(requested, 0, NULL), "all"))
1591 return (NULL);
1592
1593 /*
1594 * Create an array using "strcmp" as the comparison function...
1595 */
1596
1597 ra = cupsArrayNew((cups_array_func_t)strcmp, NULL);
1598
1599 for (i = 0; i < count; i ++)
1600 {
1601 added = 0;
1602 value = ippGetString(requested, i, NULL);
1603
1604 if (!strcmp(value, "document-description") || !strcmp(value, "all"))
1605 {
1606 for (j = 0;
1607 j < (int)(sizeof(document_description) /
1608 sizeof(document_description[0]));
1609 j ++)
1610 cupsArrayAdd(ra, (void *)document_description[j]);
1611
1612 added = 1;
1613 }
1614
1615 if (!strcmp(value, "document-template") || !strcmp(value, "all"))
1616 {
1617 for (j = 0;
1618 j < (int)(sizeof(document_template) / sizeof(document_template[0]));
1619 j ++)
1620 cupsArrayAdd(ra, (void *)document_template[j]);
1621
1622 added = 1;
1623 }
1624
1625 if (!strcmp(value, "job-description") || !strcmp(value, "all"))
1626 {
1627 for (j = 0;
1628 j < (int)(sizeof(job_description) / sizeof(job_description[0]));
1629 j ++)
1630 cupsArrayAdd(ra, (void *)job_description[j]);
1631
1632 added = 1;
1633 }
1634
1635 if (!strcmp(value, "job-template") || !strcmp(value, "all"))
1636 {
1637 for (j = 0;
1638 j < (int)(sizeof(job_template) / sizeof(job_template[0]));
1639 j ++)
1640 cupsArrayAdd(ra, (void *)job_template[j]);
1641
1642 added = 1;
1643 }
1644
1645 if (!strcmp(value, "printer-description") || !strcmp(value, "all"))
1646 {
1647 for (j = 0;
1648 j < (int)(sizeof(printer_description) /
1649 sizeof(printer_description[0]));
1650 j ++)
1651 cupsArrayAdd(ra, (void *)printer_description[j]);
1652
1653 added = 1;
1654 }
1655
1656 if (!strcmp(value, "subscription-description") || !strcmp(value, "all"))
1657 {
1658 for (j = 0;
1659 j < (int)(sizeof(subscription_description) /
1660 sizeof(subscription_description[0]));
1661 j ++)
1662 cupsArrayAdd(ra, (void *)subscription_description[j]);
1663
1664 added = 1;
1665 }
1666
1667 if (!strcmp(value, "subscription-template") || !strcmp(value, "all"))
1668 {
1669 for (j = 0;
1670 j < (int)(sizeof(subscription_template) /
1671 sizeof(subscription_template[0]));
1672 j ++)
1673 cupsArrayAdd(ra, (void *)subscription_template[j]);
1674
1675 added = 1;
1676 }
1677
1678 if (!added)
1679 cupsArrayAdd(ra, (void *)value);
1680 }
1681
1682 return (ra);
1683 }
1684
1685
1686 /*
1687 * 'ippEnumString()' - Return a string corresponding to the enum value.
1688 */
1689
1690 const char * /* O - Enum string */
1691 ippEnumString(const char *attrname, /* I - Attribute name */
1692 int enumvalue) /* I - Enum value */
1693 {
1694 _cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */
1695
1696
1697 /*
1698 * Check for standard enum values...
1699 */
1700
1701 if (!strcmp(attrname, "document-state") &&
1702 enumvalue >= 3 &&
1703 enumvalue < (3 + (int)(sizeof(ipp_document_states) /
1704 sizeof(ipp_document_states[0]))))
1705 return (ipp_document_states[enumvalue - 3]);
1706 else if (!strcmp(attrname, "finishings") ||
1707 !strcmp(attrname, "finishings-actual") ||
1708 !strcmp(attrname, "finishings-default") ||
1709 !strcmp(attrname, "finishings-ready") ||
1710 !strcmp(attrname, "finishings-supported"))
1711 {
1712 if (enumvalue >= 3 &&
1713 enumvalue < (3 + (int)(sizeof(ipp_finishings) /
1714 sizeof(ipp_finishings[0]))))
1715 return (ipp_finishings[enumvalue - 3]);
1716 else if (enumvalue >= 0x40000000 &&
1717 enumvalue <= (0x40000000 + (int)(sizeof(ipp_finishings_vendor) /
1718 sizeof(ipp_finishings_vendor[0]))))
1719 return (ipp_finishings_vendor[enumvalue - 0x40000000]);
1720 }
1721 else if ((!strcmp(attrname, "job-collation-type") ||
1722 !strcmp(attrname, "job-collation-type-actual")) &&
1723 enumvalue >= 3 &&
1724 enumvalue < (3 + (int)(sizeof(ipp_job_collation_types) /
1725 sizeof(ipp_job_collation_types[0]))))
1726 return (ipp_job_collation_types[enumvalue - 3]);
1727 else if (!strcmp(attrname, "job-state") &&
1728 enumvalue >= IPP_JOB_PENDING && enumvalue <= IPP_JOB_COMPLETED)
1729 return (ipp_job_states[enumvalue - IPP_JOB_PENDING]);
1730 else if (!strcmp(attrname, "operations-supported"))
1731 return (ippOpString((ipp_op_t)enumvalue));
1732 else if ((!strcmp(attrname, "orientation-requested") ||
1733 !strcmp(attrname, "orientation-requested-actual") ||
1734 !strcmp(attrname, "orientation-requested-default") ||
1735 !strcmp(attrname, "orientation-requested-supported")) &&
1736 enumvalue >= 3 &&
1737 enumvalue < (3 + (int)(sizeof(ipp_orientation_requesteds) /
1738 sizeof(ipp_orientation_requesteds[0]))))
1739 return (ipp_orientation_requesteds[enumvalue - 3]);
1740 else if ((!strcmp(attrname, "print-quality") ||
1741 !strcmp(attrname, "print-quality-actual") ||
1742 !strcmp(attrname, "print-quality-default") ||
1743 !strcmp(attrname, "print-quality-supported")) &&
1744 enumvalue >= 3 &&
1745 enumvalue < (3 + (int)(sizeof(ipp_print_qualities) /
1746 sizeof(ipp_print_qualities[0]))))
1747 return (ipp_print_qualities[enumvalue - 3]);
1748 else if (!strcmp(attrname, "printer-state") &&
1749 enumvalue >= IPP_PRINTER_IDLE && enumvalue <= IPP_PRINTER_STOPPED)
1750 return (ipp_printer_states[enumvalue - IPP_PRINTER_IDLE]);
1751
1752 /*
1753 * Not a standard enum value, just return the decimal equivalent...
1754 */
1755
1756 snprintf(cg->ipp_unknown, sizeof(cg->ipp_unknown), "%d", enumvalue);
1757 return (cg->ipp_unknown);
1758 }
1759
1760
1761 /*
1762 * 'ippEnumValue()' - Return the value associated with a given enum string.
1763 */
1764
1765 int /* O - Enum value or -1 if unknown */
1766 ippEnumValue(const char *attrname, /* I - Attribute name */
1767 const char *enumstring) /* I - Enum string */
1768 {
1769 int i, /* Looping var */
1770 num_strings; /* Number of strings to compare */
1771 const char * const *strings; /* Strings to compare */
1772
1773
1774 /*
1775 * If the string is just a number, return it...
1776 */
1777
1778 if (isdigit(*enumstring & 255))
1779 return (strtol(enumstring, NULL, 0));
1780
1781 /*
1782 * Otherwise look up the string...
1783 */
1784
1785 if (!strcmp(attrname, "document-state"))
1786 {
1787 num_strings = (int)(sizeof(ipp_document_states) / sizeof(ipp_document_states[0]));
1788 strings = ipp_document_states;
1789 }
1790 else if (!strcmp(attrname, "finishings") ||
1791 !strcmp(attrname, "finishings-actual") ||
1792 !strcmp(attrname, "finishings-default") ||
1793 !strcmp(attrname, "finishings-ready") ||
1794 !strcmp(attrname, "finishings-supported"))
1795 {
1796 for (i = 0;
1797 i < (int)(sizeof(ipp_finishings_vendor) /
1798 sizeof(ipp_finishings_vendor[0]));
1799 i ++)
1800 if (!strcmp(enumstring, ipp_finishings_vendor[i]))
1801 return (i + 0x40000000);
1802
1803 num_strings = (int)(sizeof(ipp_finishings) / sizeof(ipp_finishings[0]));
1804 strings = ipp_finishings;
1805 }
1806 else if (!strcmp(attrname, "job-collation-type") ||
1807 !strcmp(attrname, "job-collation-type-actual"))
1808 {
1809 num_strings = (int)(sizeof(ipp_job_collation_types) /
1810 sizeof(ipp_job_collation_types[0]));
1811 strings = ipp_job_collation_types;
1812 }
1813 else if (!strcmp(attrname, "job-state"))
1814 {
1815 num_strings = (int)(sizeof(ipp_job_states) / sizeof(ipp_job_states[0]));
1816 strings = ipp_job_states;
1817 }
1818 else if (!strcmp(attrname, "operations-supported"))
1819 return (ippOpValue(enumstring));
1820 else if (!strcmp(attrname, "orientation-requested") ||
1821 !strcmp(attrname, "orientation-requested-actual") ||
1822 !strcmp(attrname, "orientation-requested-default") ||
1823 !strcmp(attrname, "orientation-requested-supported"))
1824 {
1825 num_strings = (int)(sizeof(ipp_orientation_requesteds) /
1826 sizeof(ipp_orientation_requesteds[0]));
1827 strings = ipp_orientation_requesteds;
1828 }
1829 else if (!strcmp(attrname, "print-quality") ||
1830 !strcmp(attrname, "print-quality-actual") ||
1831 !strcmp(attrname, "print-quality-default") ||
1832 !strcmp(attrname, "print-quality-supported"))
1833 {
1834 num_strings = (int)(sizeof(ipp_print_qualities) / sizeof(ipp_print_qualities[0]));
1835 strings = ipp_print_qualities;
1836 }
1837 else if (!strcmp(attrname, "printer-state"))
1838 {
1839 num_strings = (int)(sizeof(ipp_printer_states) / sizeof(ipp_printer_states[0]));
1840 strings = ipp_printer_states;
1841 }
1842 else
1843 return (-1);
1844
1845 for (i = 0; i < num_strings; i ++)
1846 if (!strcmp(enumstring, strings[i]))
1847 return (i + 3);
1848
1849 return (-1);
1850 }
1851
1852
1853 /*
1854 * 'ippErrorString()' - Return a name for the given status code.
1855 */
1856
1857 const char * /* O - Text string */
1858 ippErrorString(ipp_status_t error) /* I - Error status */
1859 {
1860 _cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */
1861
1862
1863 /*
1864 * See if the error code is a known value...
1865 */
1866
1867 if (error >= IPP_STATUS_OK && error <= IPP_STATUS_OK_EVENTS_COMPLETE)
1868 return (ipp_status_oks[error]);
1869 else if (error == IPP_STATUS_REDIRECTION_OTHER_SITE)
1870 return ("redirection-other-site");
1871 else if (error == IPP_STATUS_CUPS_SEE_OTHER)
1872 return ("cups-see-other");
1873 else if (error >= IPP_STATUS_ERROR_BAD_REQUEST &&
1874 error <= IPP_STATUS_ERROR_DOCUMENT_UNPRINTABLE)
1875 return (ipp_status_400s[error - IPP_STATUS_ERROR_BAD_REQUEST]);
1876 else if (error >= 0x480 &&
1877 error <= IPP_STATUS_ERROR_CUPS_ACCOUNT_AUTHORIZATION_FAILED)
1878 return (ipp_status_480s[error - 0x0480]);
1879 else if (error >= IPP_STATUS_ERROR_INTERNAL &&
1880 error <= IPP_STATUS_ERROR_TOO_MANY_DOCUMENTS)
1881 return (ipp_status_500s[error - IPP_STATUS_ERROR_INTERNAL]);
1882 else if (error >= IPP_STATUS_ERROR_CUPS_AUTHENTICATION_CANCELED &&
1883 error <= IPP_STATUS_ERROR_CUPS_UPGRADE_REQUIRED)
1884 return (ipp_status_1000s[error -
1885 IPP_STATUS_ERROR_CUPS_AUTHENTICATION_CANCELED]);
1886
1887 /*
1888 * No, build an "0xxxxx" error string...
1889 */
1890
1891 sprintf(cg->ipp_unknown, "0x%04x", error);
1892
1893 return (cg->ipp_unknown);
1894 }
1895
1896
1897 /*
1898 * 'ippErrorValue()' - Return a status code for the given name.
1899 *
1900 * @since CUPS 1.2/OS X 10.5@
1901 */
1902
1903 ipp_status_t /* O - IPP status code */
1904 ippErrorValue(const char *name) /* I - Name */
1905 {
1906 int i;
1907
1908
1909 for (i = 0; i < (sizeof(ipp_status_oks) / sizeof(ipp_status_oks[0])); i ++)
1910 if (!_cups_strcasecmp(name, ipp_status_oks[i]))
1911 return ((ipp_status_t)i);
1912
1913 if (!_cups_strcasecmp(name, "redirection-other-site"))
1914 return (IPP_STATUS_REDIRECTION_OTHER_SITE);
1915
1916 if (!_cups_strcasecmp(name, "cups-see-other"))
1917 return (IPP_STATUS_CUPS_SEE_OTHER);
1918
1919 for (i = 0; i < (sizeof(ipp_status_400s) / sizeof(ipp_status_400s[0])); i ++)
1920 if (!_cups_strcasecmp(name, ipp_status_400s[i]))
1921 return ((ipp_status_t)(i + 0x400));
1922
1923 for (i = 0; i < (sizeof(ipp_status_480s) / sizeof(ipp_status_480s[0])); i ++)
1924 if (!_cups_strcasecmp(name, ipp_status_480s[i]))
1925 return ((ipp_status_t)(i + 0x480));
1926
1927 for (i = 0; i < (sizeof(ipp_status_500s) / sizeof(ipp_status_500s[0])); i ++)
1928 if (!_cups_strcasecmp(name, ipp_status_500s[i]))
1929 return ((ipp_status_t)(i + 0x500));
1930
1931 for (i = 0; i < (sizeof(ipp_status_1000s) / sizeof(ipp_status_1000s[0])); i ++)
1932 if (!_cups_strcasecmp(name, ipp_status_1000s[i]))
1933 return ((ipp_status_t)(i + 0x1000));
1934
1935 return ((ipp_status_t)-1);
1936 }
1937
1938
1939 /*
1940 * 'ippOpString()' - Return a name for the given operation id.
1941 *
1942 * @since CUPS 1.2/OS X 10.5@
1943 */
1944
1945 const char * /* O - Name */
1946 ippOpString(ipp_op_t op) /* I - Operation ID */
1947 {
1948 _cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */
1949
1950
1951 /*
1952 * See if the operation ID is a known value...
1953 */
1954
1955 if (op >= IPP_OP_PRINT_JOB && op <= IPP_OP_VALIDATE_DOCUMENT)
1956 return (ipp_std_ops[op]);
1957 else if (op == IPP_OP_PRIVATE)
1958 return ("windows-ext");
1959 else if (op >= IPP_OP_CUPS_GET_DEFAULT && op <= IPP_OP_CUPS_GET_PPD)
1960 return (ipp_cups_ops[op - CUPS_GET_DEFAULT]);
1961 else if (op == IPP_OP_CUPS_GET_DOCUMENT)
1962 return (ipp_cups_ops2[0]);
1963
1964 /*
1965 * No, build an "0xxxxx" operation string...
1966 */
1967
1968 sprintf(cg->ipp_unknown, "0x%04x", op);
1969
1970 return (cg->ipp_unknown);
1971 }
1972
1973
1974 /*
1975 * 'ippOpValue()' - Return an operation id for the given name.
1976 *
1977 * @since CUPS 1.2/OS X 10.5@
1978 */
1979
1980 ipp_op_t /* O - Operation ID */
1981 ippOpValue(const char *name) /* I - Textual name */
1982 {
1983 int i;
1984
1985
1986 if (!strncmp(name, "0x", 2))
1987 return ((ipp_op_t)strtol(name + 2, NULL, 16));
1988
1989 for (i = 0; i < (sizeof(ipp_std_ops) / sizeof(ipp_std_ops[0])); i ++)
1990 if (!_cups_strcasecmp(name, ipp_std_ops[i]))
1991 return ((ipp_op_t)i);
1992
1993 if (!_cups_strcasecmp(name, "windows-ext"))
1994 return (IPP_OP_PRIVATE);
1995
1996 for (i = 0; i < (sizeof(ipp_cups_ops) / sizeof(ipp_cups_ops[0])); i ++)
1997 if (!_cups_strcasecmp(name, ipp_cups_ops[i]))
1998 return ((ipp_op_t)(i + 0x4001));
1999
2000 for (i = 0; i < (sizeof(ipp_cups_ops2) / sizeof(ipp_cups_ops2[0])); i ++)
2001 if (!_cups_strcasecmp(name, ipp_cups_ops2[i]))
2002 return ((ipp_op_t)(i + 0x4027));
2003
2004 if (!_cups_strcasecmp(name, "CUPS-Add-Class"))
2005 return (IPP_OP_CUPS_ADD_MODIFY_CLASS);
2006
2007 if (!_cups_strcasecmp(name, "CUPS-Add-Printer"))
2008 return (IPP_OP_CUPS_ADD_MODIFY_PRINTER);
2009
2010 return (IPP_OP_CUPS_INVALID);
2011 }
2012
2013
2014 /*
2015 * 'ippPort()' - Return the default IPP port number.
2016 */
2017
2018 int /* O - Port number */
2019 ippPort(void)
2020 {
2021 _cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */
2022
2023
2024 DEBUG_puts("ippPort()");
2025
2026 if (!cg->ipp_port)
2027 _cupsSetDefaults();
2028
2029 DEBUG_printf(("1ippPort: Returning %d...", cg->ipp_port));
2030
2031 return (cg->ipp_port);
2032 }
2033
2034
2035 /*
2036 * 'ippSetPort()' - Set the default port number.
2037 */
2038
2039 void
2040 ippSetPort(int p) /* I - Port number to use */
2041 {
2042 DEBUG_printf(("ippSetPort(p=%d)", p));
2043
2044 _cupsGlobals()->ipp_port = p;
2045 }
2046
2047
2048 /*
2049 * 'ippTagString()' - Return the tag name corresponding to a tag value.
2050 *
2051 * The returned names are defined in RFC 2911 and 3382.
2052 *
2053 * @since CUPS 1.4/OS X 10.6@
2054 */
2055
2056 const char * /* O - Tag name */
2057 ippTagString(ipp_tag_t tag) /* I - Tag value */
2058 {
2059 tag &= IPP_TAG_MASK;
2060
2061 if (tag < (ipp_tag_t)(sizeof(ipp_tag_names) / sizeof(ipp_tag_names[0])))
2062 return (ipp_tag_names[tag]);
2063 else
2064 return ("UNKNOWN");
2065 }
2066
2067
2068 /*
2069 * 'ippTagValue()' - Return the tag value corresponding to a tag name.
2070 *
2071 * The tag names are defined in RFC 2911 and 3382.
2072 *
2073 * @since CUPS 1.4/OS X 10.6@
2074 */
2075
2076 ipp_tag_t /* O - Tag value */
2077 ippTagValue(const char *name) /* I - Tag name */
2078 {
2079 int i; /* Looping var */
2080
2081
2082 for (i = 0; i < (sizeof(ipp_tag_names) / sizeof(ipp_tag_names[0])); i ++)
2083 if (!_cups_strcasecmp(name, ipp_tag_names[i]))
2084 return ((ipp_tag_t)i);
2085
2086 if (!_cups_strcasecmp(name, "operation"))
2087 return (IPP_TAG_OPERATION);
2088 else if (!_cups_strcasecmp(name, "job"))
2089 return (IPP_TAG_JOB);
2090 else if (!_cups_strcasecmp(name, "printer"))
2091 return (IPP_TAG_PRINTER);
2092 else if (!_cups_strcasecmp(name, "unsupported"))
2093 return (IPP_TAG_UNSUPPORTED_GROUP);
2094 else if (!_cups_strcasecmp(name, "subscription"))
2095 return (IPP_TAG_SUBSCRIPTION);
2096 else if (!_cups_strcasecmp(name, "event"))
2097 return (IPP_TAG_EVENT_NOTIFICATION);
2098 else if (!_cups_strcasecmp(name, "language"))
2099 return (IPP_TAG_LANGUAGE);
2100 else if (!_cups_strcasecmp(name, "mimetype"))
2101 return (IPP_TAG_MIMETYPE);
2102 else if (!_cups_strcasecmp(name, "name"))
2103 return (IPP_TAG_NAME);
2104 else if (!_cups_strcasecmp(name, "text"))
2105 return (IPP_TAG_TEXT);
2106 else if (!_cups_strcasecmp(name, "begCollection"))
2107 return (IPP_TAG_BEGIN_COLLECTION);
2108 else
2109 return (IPP_TAG_ZERO);
2110 }
2111
2112
2113 /*
2114 * 'ipp_col_string()' - Convert a collection to a string.
2115 */
2116
2117 static size_t /* O - Number of bytes */
2118 ipp_col_string(ipp_t *col, /* I - Collection attribute */
2119 char *buffer, /* I - Buffer or NULL */
2120 size_t bufsize) /* I - Size of buffer */
2121 {
2122 char *bufptr, /* Position in buffer */
2123 *bufend, /* End of buffer */
2124 prefix = '{', /* Prefix character */
2125 temp[256]; /* Temporary string */
2126 ipp_attribute_t *attr; /* Current member attribute */
2127
2128
2129 bufptr = buffer;
2130 bufend = buffer + bufsize - 1;
2131
2132 for (attr = col->attrs; attr; attr = attr->next)
2133 {
2134 if (!attr->name)
2135 continue;
2136
2137 if (buffer && bufptr < bufend)
2138 *bufptr = prefix;
2139 bufptr ++;
2140 prefix = ' ';
2141
2142 if (buffer && bufptr < bufend)
2143 bufptr += snprintf(bufptr, bufend - bufptr + 1, "%s=", attr->name);
2144 else
2145 bufptr += strlen(attr->name) + 1;
2146
2147 if (buffer && bufptr < bufend)
2148 bufptr += ippAttributeString(attr, bufptr, bufend - bufptr + 1);
2149 else
2150 bufptr += ippAttributeString(attr, temp, sizeof(temp));
2151 }
2152
2153 if (prefix == '{')
2154 {
2155 if (buffer && bufptr < bufend)
2156 *bufptr = prefix;
2157 bufptr ++;
2158 }
2159
2160 if (buffer && bufptr < bufend)
2161 *bufptr = '}';
2162 bufptr ++;
2163
2164 return (bufptr - buffer);
2165 }
2166
2167
2168 /*
2169 * End of "$Id: ipp-support.c 9371 2010-11-17 06:21:32Z mike $".
2170 */