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