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