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