]> git.ipfire.org Git - thirdparty/cups.git/blame - cups/ipp-support.c
Merge changes from CUPS 1.6svn-r10310.
[thirdparty/cups.git] / cups / ipp-support.c
CommitLineData
ef416fc2 1/*
1106b00e 2 * "$Id: ipp-support.c 9371 2010-11-17 06:21:32Z mike $"
ef416fc2 3 *
71e16022 4 * Internet Printing Protocol support functions for CUPS.
ef416fc2 5 *
3e7fe0ca 6 * Copyright 2007-2012 by Apple Inc.
b94498cf 7 * Copyright 1997-2007 by Easy Software Products, all rights reserved.
ef416fc2 8 *
9 * These coded instructions, statements, and computer programs are the
bc44d920 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/".
ef416fc2 14 *
15 * This file is subject to the Apple OS-Developed Software exception.
16 *
17 * Contents:
18 *
a2326b5b
MS
19 * ippAttributeString() - Convert the attribute's value to a string.
20 * ippEnumString() - Return a string corresponding to the enum value.
21 * ippEnumValue() - Return the value associated with a given enum
22 * string.
23 * ippErrorString() - Return a name for the given status code.
24 * ippErrorValue() - Return a status code for the given name.
25 * ippOpString() - Return a name for the given operation id.
26 * ippOpValue() - Return an operation id for the given name.
27 * ippPort() - Return the default IPP port number.
28 * ippSetPort() - Set the default port number.
29 * ippTagString() - Return the tag name corresponding to a tag value.
30 * ippTagValue() - Return the tag value corresponding to a tag name.
31 * ipp_col_string() - Convert a collection to a string.
ef416fc2 32 */
33
34/*
35 * Include necessary headers...
36 */
37
71e16022 38#include "cups-private.h"
ef416fc2 39
40
41/*
42 * Local globals...
43 */
44
45static const char * const ipp_status_oks[] = /* "OK" status codes */
a2326b5b 46 { /* (name) = abandoned standard value */
ef416fc2 47 "successful-ok",
48 "successful-ok-ignored-or-substituted-attributes",
49 "successful-ok-conflicting-attributes",
50 "successful-ok-ignored-subscriptions",
a2326b5b 51 "(successful-ok-ignored-notifications)",
ef416fc2 52 "successful-ok-too-many-events",
a2326b5b 53 "(successful-ok-but-cancel-subscription)",
bd7854cb 54 "successful-ok-events-complete"
ef416fc2 55 },
56 * const ipp_status_400s[] = /* Client errors */
a2326b5b 57 { /* (name) = abandoned standard value */
ef416fc2 58 "client-error-bad-request",
59 "client-error-forbidden",
60 "client-error-not-authenticated",
61 "client-error-not-authorized",
62 "client-error-not-possible",
63 "client-error-timeout",
64 "client-error-not-found",
65 "client-error-gone",
66 "client-error-request-entity-too-large",
67 "client-error-request-value-too-long",
68 "client-error-document-format-not-supported",
69 "client-error-attributes-or-values-not-supported",
70 "client-error-uri-scheme-not-supported",
71 "client-error-charset-not-supported",
72 "client-error-conflicting-attributes",
73 "client-error-compression-not-supported",
74 "client-error-compression-error",
75 "client-error-document-format-error",
76 "client-error-document-access-error",
77 "client-error-attributes-not-settable",
78 "client-error-ignored-all-subscriptions",
79 "client-error-too-many-subscriptions",
a2326b5b
MS
80 "(client-error-ignored-all-notifications)",
81 "(client-error-client-print-support-file-not-found)"
ef416fc2 82 },
83 * const ipp_status_500s[] = /* Server errors */
84 {
85 "server-error-internal-error",
86 "server-error-operation-not-supported",
87 "server-error-service-unavailable",
88 "server-error-version-not-supported",
89 "server-error-device-error",
90 "server-error-temporary-error",
91 "server-error-not-accepting-jobs",
92 "server-error-busy",
93 "server-error-job-canceled",
94 "server-error-multiple-document-jobs-not-supported",
a2326b5b
MS
95 "server-error-printer-is-deactivated",
96 "server-error-too-many-jobs",
97 "server-error-too-many-documents"
7cf5915e
MS
98 },
99 * const ipp_status_1000s[] = /* CUPS internal */
100 {
101 "cups-authorization-canceled",
102 "cups-pki-error",
103 "cups-upgrade-required"
ef416fc2 104 };
a2326b5b 105static const char * const ipp_std_ops[] =
ef416fc2 106 {
107 /* 0x0000 - 0x000f */
d7225fc2
MS
108 "0x00",
109 "0x01",
aaf19ab0
MS
110 "Print-Job",
111 "Print-URI",
112 "Validate-Job",
113 "Create-Job",
114 "Send-Document",
115 "Send-URI",
116 "Cancel-Job",
117 "Get-Job-Attributes",
118 "Get-Jobs",
119 "Get-Printer-Attributes",
120 "Hold-Job",
121 "Release-Job",
122 "Restart-Job",
d7225fc2 123 "0x0f",
ef416fc2 124
125 /* 0x0010 - 0x001f */
aaf19ab0
MS
126 "Pause-Printer",
127 "Resume-Printer",
128 "Purge-Jobs",
129 "Set-Printer-Attributes",
ef416fc2 130 "Set-Job-Attributes",
131 "Get-Printer-Supported-Values",
132 "Create-Printer-Subscription",
133 "Create-Job-Subscription",
134 "Get-Subscription-Attributes",
aaf19ab0
MS
135 "Get-Subscriptions",
136 "Renew-Subscription",
137 "Cancel-Subscription",
138 "Get-Notifications",
a2326b5b
MS
139 "(Send-Notifications)",
140 "(Get-Resource-Attributes)",
141 "(Get-Resource-Data)",
ef416fc2 142
143 /* 0x0020 - 0x002f */
a2326b5b
MS
144 "(Get-Resources)",
145 "(Get-Printer-Support-Files)",
ef416fc2 146 "Enable-Printer",
147 "Disable-Printer",
148 "Pause-Printer-After-Current-Job",
149 "Hold-New-Jobs",
150 "Release-Held-New-Jobs",
151 "Deactivate-Printer",
152 "Activate-Printer",
153 "Restart-Printer",
154 "Shutdown-Printer",
155 "Startup-Printer",
156 "Reprocess-Job",
157 "Cancel-Current-Job",
158 "Suspend-Current-Job",
159 "Resume-Job",
160
aaf19ab0 161 /* 0x0030 - 0x003b */
ef416fc2 162 "Promote-Job",
aaf19ab0 163 "Schedule-Job-After",
d7225fc2 164 "0x32",
aaf19ab0
MS
165 "Cancel-Document",
166 "Get-Document-Attributes",
167 "Get-Documents",
168 "Delete-Document",
169 "Set-Document-Attributes",
170 "Cancel-Jobs",
171 "Cancel-My-Jobs",
172 "Resubmit-Job",
771bd8cb
MS
173 "Close-Job",
174 "Identify-Printer"
ef416fc2 175 },
176 * const ipp_cups_ops[] =
177 {
178 "CUPS-Get-Default",
179 "CUPS-Get-Printers",
480ef0fe 180 "CUPS-Add-Modify-Printer",
ef416fc2 181 "CUPS-Delete-Printer",
182 "CUPS-Get-Classes",
480ef0fe 183 "CUPS-Add-Modify-Class",
ef416fc2 184 "CUPS-Delete-Class",
185 "CUPS-Accept-Jobs",
186 "CUPS-Reject-Jobs",
187 "CUPS-Set-Default",
188 "CUPS-Get-Devices",
189 "CUPS-Get-PPDs",
190 "CUPS-Move-Job",
b94498cf 191 "CUPS-Authenticate-Job",
192 "CUPS-Get-PPD"
2e4ff8af
MS
193 },
194 * const ipp_cups_ops2[] =
195 {
196 "CUPS-Get-Document"
1ff0402e
MS
197 },
198 * const ipp_tag_names[] =
199 { /* Value/group tag names */
200 "zero", /* 0x00 */
201 "operation-attributes-tag",
202 /* 0x01 */
203 "job-attributes-tag", /* 0x02 */
204 "end-of-attributes-tag",
205 /* 0x03 */
206 "printer-attributes-tag",
207 /* 0x04 */
208 "unsupported-attributes-tag",
209 /* 0x05 */
210 "subscription-attributes-tag",
211 /* 0x06 */
212 "event-notification-attributes-tag",
213 /* 0x07 */
a2326b5b
MS
214 "(resource-attributes-tag)",
215 /* 0x08 */
d7225fc2
MS
216 "document-attributes-tag",
217 /* 0x09 */
218 "0x0a", /* 0x0a */
219 "0x0b", /* 0x0b */
220 "0x0c", /* 0x0c */
221 "0x0d", /* 0x0d */
222 "0x0e", /* 0x0e */
223 "0x0f", /* 0x0f */
1ff0402e
MS
224 "unsupported", /* 0x10 */
225 "default", /* 0x11 */
226 "unknown", /* 0x12 */
227 "no-value", /* 0x13 */
d7225fc2 228 "0x14", /* 0x14 */
1ff0402e
MS
229 "not-settable", /* 0x15 */
230 "delete-attribute", /* 0x16 */
231 "admin-define", /* 0x17 */
d7225fc2
MS
232 "0x18", /* 0x18 */
233 "0x19", /* 0x19 */
234 "0x1a", /* 0x1a */
235 "0x1b", /* 0x1b */
236 "0x1c", /* 0x1c */
237 "0x1d", /* 0x1d */
238 "0x1e", /* 0x1e */
239 "0x1f", /* 0x1f */
240 "0x20", /* 0x20 */
1ff0402e
MS
241 "integer", /* 0x21 */
242 "boolean", /* 0x22 */
243 "enum", /* 0x23 */
d7225fc2
MS
244 "0x24", /* 0x24 */
245 "0x25", /* 0x25 */
246 "0x26", /* 0x26 */
247 "0x27", /* 0x27 */
248 "0x28", /* 0x28 */
249 "0x29", /* 0x29 */
250 "0x2a", /* 0x2a */
251 "0x2b", /* 0x2b */
252 "0x2c", /* 0x2c */
253 "0x2d", /* 0x2d */
254 "0x2e", /* 0x2e */
255 "0x2f", /* 0x2f */
1ff0402e
MS
256 "octetString", /* 0x30 */
257 "dateTime", /* 0x31 */
258 "resolution", /* 0x32 */
259 "rangeOfInteger", /* 0x33 */
f8b3a85b 260 "collection", /* 0x34 */
1ff0402e
MS
261 "textWithLanguage", /* 0x35 */
262 "nameWithLanguage", /* 0x36 */
263 "endCollection", /* 0x37 */
d7225fc2
MS
264 "0x38", /* 0x38 */
265 "0x39", /* 0x39 */
266 "0x3a", /* 0x3a */
267 "0x3b", /* 0x3b */
268 "0x3c", /* 0x3c */
269 "0x3d", /* 0x3d */
270 "0x3e", /* 0x3e */
271 "0x3f", /* 0x3f */
272 "0x40", /* 0x40 */
1ff0402e
MS
273 "textWithoutLanguage",/* 0x41 */
274 "nameWithoutLanguage",/* 0x42 */
d7225fc2 275 "0x43", /* 0x43 */
1ff0402e
MS
276 "keyword", /* 0x44 */
277 "uri", /* 0x45 */
278 "uriScheme", /* 0x46 */
279 "charset", /* 0x47 */
280 "naturalLanguage", /* 0x48 */
281 "mimeMediaType", /* 0x49 */
282 "memberAttrName" /* 0x4a */
ef416fc2 283 };
a2326b5b
MS
284static const char * const ipp_document_states[] =
285 { /* document-state-enums */
286 "pending",
287 "4",
288 "processing",
289 "6",
290 "canceled",
291 "aborted",
292 "completed"
293 },
294 * const ipp_finishings[] =
295 { /* finishings enums */
296 "none",
297 "staple",
298 "punch",
299 "cover",
300 "bind",
301 "saddle-stitch",
302 "edge-stitch",
303 "fold",
304 "trim",
305 "bale",
306 "booklet-maker",
307 "jog-offset",
308 "15",
309 "16",
310 "17",
311 "18",
312 "19",
313 "staple-top-left",
314 "staple-bottom-left",
315 "staple-top-right",
316 "staple-bottom-right",
317 "edge-stitch-left",
318 "edge-stitch-top",
319 "edge-stitch-right",
320 "edge-stitch-bottom",
321 "staple-dual-left",
322 "staple-dual-top",
323 "staple-dual-right",
324 "staple-dual-bottom",
325 "32",
326 "33",
327 "34",
328 "35",
329 "36",
330 "37",
331 "38",
332 "39",
333 "40",
334 "41",
335 "42",
336 "43",
337 "44",
338 "45",
339 "46",
340 "47",
341 "48",
342 "49",
343 "bind-left",
344 "bind-top",
345 "bind-right",
346 "bind-bottom",
347 "54",
348 "55",
349 "56",
350 "57",
351 "58",
352 "59",
353 "trim-after-pages",
354 "trim-after-documents",
355 "trim-after-copies",
356 "trim-after-job"
357 },
358 * const ipp_job_collation_types[] =
359 { /* job-collation-type enums */
360 "uncollated-sheets",
361 "collated-documents",
362 "uncollated-documents"
363 },
364 * const ipp_job_states[] =
365 { /* job-state enums */
366 "pending",
367 "pending-held",
368 "processing",
369 "processing-stopped",
370 "canceled",
371 "aborted",
372 "completed"
373 },
374 * const ipp_orientation_requesteds[] =
375 { /* orientation-requested enums */
376 "portrait",
377 "landscape",
378 "reverse-landscape",
379 "reverse-portrait"
380 },
381 * const ipp_print_qualities[] =
382 { /* print-quality enums */
383 "draft",
384 "normal",
385 "high"
386 },
387 * const ipp_printer_states[] =
388 { /* printer-state enums */
389 "idle",
390 "processing",
391 "stopped",
392 };
aaf19ab0
MS
393
394
395/*
396 * Local functions...
397 */
398
399static size_t ipp_col_string(ipp_t *col, char *buffer, size_t bufsize);
400
401
402/*
a2326b5b 403 * 'ippAttributeString()' - Convert the attribute's value to a string.
aaf19ab0
MS
404 *
405 * Returns the number of bytes that would be written, not including the
406 * trailing nul. The buffer pointer can be NULL to get the required length,
407 * just like (v)snprintf.
a2326b5b
MS
408 *
409 * @since CUPS 1.6@
aaf19ab0
MS
410 */
411
412size_t /* O - Number of bytes less nul */
a2326b5b
MS
413ippAttributeString(
414 ipp_attribute_t *attr, /* I - Attribute */
415 char *buffer, /* I - String buffer or NULL */
416 size_t bufsize) /* I - Size of string buffer */
aaf19ab0
MS
417{
418 int i; /* Looping var */
419 char *bufptr, /* Pointer into buffer */
420 *bufend, /* End of buffer */
421 temp[256]; /* Temporary string */
422 const char *ptr; /* Pointer into string */
a2326b5b 423 _ipp_value_t *val; /* Current value */
aaf19ab0
MS
424
425
426 if (!attr || !attr->name)
427 {
428 if (buffer)
429 *buffer = '\0';
430
431 return (0);
432 }
433
434 bufptr = buffer;
435 if (buffer)
436 bufend = buffer + bufsize - 1;
437 else
438 bufend = NULL;
439
440 for (i = attr->num_values, val = attr->values; i > 0; i --, val ++)
441 {
442 if (val > attr->values)
443 {
7cf5915e 444 if (buffer && bufptr < bufend)
aaf19ab0
MS
445 *bufptr++ = ',';
446 else
447 bufptr ++;
448 }
449
1106b00e 450 switch (attr->value_tag & ~IPP_TAG_COPY)
aaf19ab0
MS
451 {
452 case IPP_TAG_ENUM :
a2326b5b 453 ptr = ippEnumString(attr->name, val->integer);
aaf19ab0 454
a2326b5b
MS
455 if (buffer && bufptr < bufend)
456 strlcpy(bufptr, ptr, bufend - bufptr + 1);
9b66acc5 457
a2326b5b
MS
458 bufptr += strlen(ptr);
459 break;
aaf19ab0
MS
460
461 case IPP_TAG_INTEGER :
7cf5915e 462 if (buffer && bufptr < bufend)
aaf19ab0
MS
463 bufptr += snprintf(bufptr, bufend - bufptr + 1, "%d", val->integer);
464 else
465 bufptr += snprintf(temp, sizeof(temp), "%d", val->integer);
466 break;
467
468 case IPP_TAG_BOOLEAN :
7cf5915e 469 if (buffer && bufptr < bufend)
aaf19ab0
MS
470 strlcpy(bufptr, val->boolean ? "true" : "false",
471 bufend - bufptr + 1);
472
473 bufptr += val->boolean ? 4 : 5;
474 break;
475
476 case IPP_TAG_RANGE :
7cf5915e 477 if (buffer && bufptr < bufend)
aaf19ab0
MS
478 bufptr += snprintf(bufptr, bufend - bufptr + 1, "%d-%d",
479 val->range.lower, val->range.upper);
480 else
481 bufptr += snprintf(temp, sizeof(temp), "%d-%d", val->range.lower,
482 val->range.upper);
483 break;
484
485 case IPP_TAG_RESOLUTION :
7cf5915e 486 if (buffer && bufptr < bufend)
aaf19ab0
MS
487 bufptr += snprintf(bufptr, bufend - bufptr + 1, "%dx%d%s",
488 val->resolution.xres, val->resolution.yres,
489 val->resolution.units == IPP_RES_PER_INCH ?
3e7fe0ca 490 "dpi" : "dpcm");
aaf19ab0
MS
491 else
492 bufptr += snprintf(temp, sizeof(temp), "%dx%d%s",
493 val->resolution.xres, val->resolution.yres,
494 val->resolution.units == IPP_RES_PER_INCH ?
3e7fe0ca 495 "dpi" : "dpcm");
aaf19ab0
MS
496 break;
497
498 case IPP_TAG_DATE :
499 {
500 unsigned year; /* Year */
501
502 year = (val->date[0] << 8) + val->date[1];
503
504 if (val->date[9] == 0 && val->date[10] == 0)
505 snprintf(temp, sizeof(temp), "%04u-%02u-%02uT%02u:%02u:%02uZ",
506 year, val->date[2], val->date[3], val->date[4],
507 val->date[5], val->date[6]);
508 else
509 snprintf(temp, sizeof(temp),
510 "%04u-%02u-%02uT%02u:%02u:%02u%c%02u%02u",
511 year, val->date[2], val->date[3], val->date[4],
512 val->date[5], val->date[6], val->date[8], val->date[9],
513 val->date[10]);
514
7cf5915e 515 if (buffer && bufptr < bufend)
aaf19ab0
MS
516 strlcpy(bufptr, temp, bufend - bufptr + 1);
517
518 bufptr += strlen(temp);
519 }
520 break;
521
522 case IPP_TAG_TEXT :
523 case IPP_TAG_NAME :
524 case IPP_TAG_KEYWORD :
525 case IPP_TAG_CHARSET :
526 case IPP_TAG_URI :
d7225fc2 527 case IPP_TAG_URISCHEME :
aaf19ab0
MS
528 case IPP_TAG_MIMETYPE :
529 case IPP_TAG_LANGUAGE :
530 case IPP_TAG_TEXTLANG :
531 case IPP_TAG_NAMELANG :
7cf5915e
MS
532 if (!val->string.text)
533 break;
534
aaf19ab0
MS
535 for (ptr = val->string.text; *ptr; ptr ++)
536 {
a2326b5b 537 if (*ptr == '\\' || *ptr == '\"' || *ptr == '[')
aaf19ab0 538 {
7cf5915e 539 if (buffer && bufptr < bufend)
aaf19ab0
MS
540 *bufptr = '\\';
541 bufptr ++;
542 }
543
7cf5915e 544 if (buffer && bufptr < bufend)
aaf19ab0
MS
545 *bufptr = *ptr;
546 bufptr ++;
547 }
a2326b5b
MS
548
549 if (val->string.language)
550 {
551 /*
552 * Add "[language]" to end of string...
553 */
554
555 if (buffer && bufptr < bufend)
556 *bufptr = '[';
557 bufptr ++;
558
559 if (buffer && bufptr < bufend)
560 strlcpy(bufptr, val->string.language, bufend - bufptr);
561 bufptr += strlen(val->string.language);
562
563 if (buffer && bufptr < bufend)
564 *bufptr = ']';
565 bufptr ++;
566 }
aaf19ab0
MS
567 break;
568
569 case IPP_TAG_BEGIN_COLLECTION :
7cf5915e 570 if (buffer && bufptr < bufend)
aaf19ab0
MS
571 bufptr += ipp_col_string(val->collection, bufptr,
572 bufend - bufptr + 1);
573 else
574 bufptr += ipp_col_string(val->collection, NULL, 0);
575 break;
576
577 case IPP_TAG_STRING :
578 for (ptr = val->string.text; *ptr; ptr ++)
579 {
7cf5915e 580 if (*ptr == '\\' || _cups_isspace(*ptr))
aaf19ab0 581 {
7cf5915e 582 if (buffer && bufptr < bufend)
aaf19ab0
MS
583 *bufptr = '\\';
584 bufptr ++;
585
7cf5915e 586 if (buffer && bufptr < bufend)
aaf19ab0
MS
587 *bufptr = *ptr;
588 bufptr ++;
589 }
590 else if (!isprint(*ptr & 255))
591 {
7cf5915e 592 if (buffer && bufptr < bufend)
aaf19ab0
MS
593 bufptr += snprintf(bufptr, bufend - bufptr + 1, "\\%03o",
594 *ptr & 255);
595 else
596 bufptr += snprintf(temp, sizeof(temp), "\\%03o",
597 *ptr & 255);
598 }
599 else
600 {
7cf5915e 601 if (buffer && bufptr < bufend)
aaf19ab0
MS
602 *bufptr = *ptr;
603 bufptr ++;
604 }
605 }
606 break;
607
608 default :
609 ptr = ippTagString(attr->value_tag);
7cf5915e 610 if (buffer && bufptr < bufend)
aaf19ab0
MS
611 strlcpy(bufptr, ptr, bufend - bufptr + 1);
612 bufptr += strlen(ptr);
613 break;
614 }
615 }
616
7cf5915e 617 if (buffer && bufptr < bufend)
aaf19ab0
MS
618 *bufptr = '\0';
619 else if (bufend)
620 *bufend = '\0';
621
622 return (bufptr - buffer);
623}
ef416fc2 624
625
a2326b5b
MS
626/*
627 * 'ippEnumString()' - Return a string corresponding to the enum value.
628 */
629
630const char * /* O - Enum string */
631ippEnumString(const char *attrname, /* I - Attribute name */
632 int enumvalue) /* I - Enum value */
633{
634 _cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */
635
636
637 /*
638 * Check for standard enum values...
639 */
640
641 if (!strcmp(attrname, "document-state") &&
642 enumvalue >= 3 &&
643 enumvalue <= (3 + (int)(sizeof(ipp_document_states) /
644 sizeof(ipp_document_states[0]))))
645 return (ipp_document_states[enumvalue - 3]);
646 else if ((!strcmp(attrname, "finishings") ||
647 !strcmp(attrname, "finishings-actual") ||
648 !strcmp(attrname, "finishings-default") ||
649 !strcmp(attrname, "finishings-ready") ||
650 !strcmp(attrname, "finishings-supported")) &&
651 enumvalue >= 3 &&
652 enumvalue <= (3 + (int)(sizeof(ipp_finishings) / sizeof(ipp_finishings[0]))))
653 return (ipp_finishings[enumvalue - 3]);
654 else if ((!strcmp(attrname, "job-collation-type") ||
655 !strcmp(attrname, "job-collation-type-actual")) &&
656 enumvalue >= 3 &&
657 enumvalue <= (3 + (int)(sizeof(ipp_job_collation_types) /
658 sizeof(ipp_job_collation_types[0]))))
659 return (ipp_job_collation_types[enumvalue - 3]);
660 else if (!strcmp(attrname, "job-state") &&
661 enumvalue >= IPP_JOB_PENDING && enumvalue <= IPP_JOB_COMPLETED)
662 return (ipp_job_states[enumvalue - IPP_JOB_PENDING]);
663 else if (!strcmp(attrname, "operations-supported"))
664 return (ippOpString((ipp_op_t)enumvalue));
665 else if ((!strcmp(attrname, "orientation-requested") ||
666 !strcmp(attrname, "orientation-requested-actual") ||
667 !strcmp(attrname, "orientation-requested-default") ||
668 !strcmp(attrname, "orientation-requested-supported")) &&
669 enumvalue >= 3 &&
670 enumvalue <= (3 + (int)(sizeof(ipp_orientation_requesteds) /
671 sizeof(ipp_orientation_requesteds[0]))))
672 return (ipp_orientation_requesteds[enumvalue - 3]);
673 else if ((!strcmp(attrname, "print-quality") ||
674 !strcmp(attrname, "print-quality-actual") ||
675 !strcmp(attrname, "print-quality-default") ||
676 !strcmp(attrname, "print-quality-supported")) &&
677 enumvalue >= 3 &&
678 enumvalue <= (3 + (int)(sizeof(ipp_print_qualities) /
679 sizeof(ipp_print_qualities[0]))))
680 return (ipp_print_qualities[enumvalue - 3]);
681 else if (!strcmp(attrname, "printer-state") &&
682 enumvalue >= IPP_PRINTER_IDLE && enumvalue <= IPP_PRINTER_STOPPED)
683 return (ipp_printer_states[enumvalue - IPP_PRINTER_IDLE]);
684
685 /*
686 * Not a standard enum value, just return the decimal equivalent...
687 */
688
689 snprintf(cg->ipp_unknown, sizeof(cg->ipp_unknown), "%d", enumvalue);
690 return (cg->ipp_unknown);
691}
692
693
694/*
695 * 'ippEnumValue()' - Return the value associated with a given enum string.
696 */
697
698int /* O - Enum value or -1 if unknown */
699ippEnumValue(const char *attrname, /* I - Attribute name */
700 const char *enumstring) /* I - Enum string */
701{
702 int i, /* Looping var */
703 num_strings; /* Number of strings to compare */
704 const char * const *strings; /* Strings to compare */
705
706
707 /*
708 * If the string is just a number, return it...
709 */
710
711 if (isdigit(*enumstring & 255))
712 return (strtol(enumstring, NULL, 0));
713
714 /*
715 * Otherwise look up the string...
716 */
717
718 if (!strcmp(attrname, "document-state"))
719 {
720 num_strings = (int)(sizeof(ipp_document_states) / sizeof(ipp_document_states[0]));
721 strings = ipp_document_states;
722 }
723 else if (!strcmp(attrname, "finishings") ||
724 !strcmp(attrname, "finishings-actual") ||
725 !strcmp(attrname, "finishings-default") ||
726 !strcmp(attrname, "finishings-ready") ||
727 !strcmp(attrname, "finishings-supported"))
728 {
729 num_strings = (int)(sizeof(ipp_finishings) / sizeof(ipp_finishings[0]));
730 strings = ipp_finishings;
731 }
732 else if (!strcmp(attrname, "job-collation-type") ||
733 !strcmp(attrname, "job-collation-type-actual"))
734 {
735 num_strings = (int)(sizeof(ipp_job_collation_types) /
736 sizeof(ipp_job_collation_types[0]));
737 strings = ipp_job_collation_types;
738 }
739 else if (!strcmp(attrname, "job-state"))
740 {
741 num_strings = (int)(sizeof(ipp_job_states) / sizeof(ipp_job_states[0]));
742 strings = ipp_job_states;
743 }
744 else if (!strcmp(attrname, "operations-supported"))
745 return (ippOpValue(enumstring));
746 else if (!strcmp(attrname, "orientation-requested") ||
747 !strcmp(attrname, "orientation-requested-actual") ||
748 !strcmp(attrname, "orientation-requested-default") ||
749 !strcmp(attrname, "orientation-requested-supported"))
750 {
751 num_strings = (int)(sizeof(ipp_orientation_requesteds) /
752 sizeof(ipp_orientation_requesteds[0]));
753 strings = ipp_orientation_requesteds;
754 }
755 else if (!strcmp(attrname, "print-quality") ||
756 !strcmp(attrname, "print-quality-actual") ||
757 !strcmp(attrname, "print-quality-default") ||
758 !strcmp(attrname, "print-quality-supported"))
759 {
760 num_strings = (int)(sizeof(ipp_print_qualities) / sizeof(ipp_print_qualities[0]));
761 strings = ipp_print_qualities;
762 }
763 else if (!strcmp(attrname, "printer-state"))
764 {
765 num_strings = (int)(sizeof(ipp_printer_states) / sizeof(ipp_printer_states[0]));
766 strings = ipp_printer_states;
767 }
768 else
769 return (-1);
770
771 for (i = 0; i < num_strings; i ++)
772 if (!strcmp(enumstring, strings[i]))
773 return (i + 3);
774
775 return (-1);
776}
777
778
ef416fc2 779/*
780 * 'ippErrorString()' - Return a name for the given status code.
781 */
782
783const char * /* O - Text string */
784ippErrorString(ipp_status_t error) /* I - Error status */
785{
786 _cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */
787
788
789 /*
790 * See if the error code is a known value...
791 */
792
bd7854cb 793 if (error >= IPP_OK && error <= IPP_OK_EVENTS_COMPLETE)
ef416fc2 794 return (ipp_status_oks[error]);
795 else if (error == IPP_REDIRECTION_OTHER_SITE)
796 return ("redirection-other-site");
b94498cf 797 else if (error == CUPS_SEE_OTHER)
798 return ("cups-see-other");
ef416fc2 799 else if (error >= IPP_BAD_REQUEST && error <= IPP_PRINT_SUPPORT_FILE_NOT_FOUND)
800 return (ipp_status_400s[error - IPP_BAD_REQUEST]);
801 else if (error >= IPP_INTERNAL_ERROR && error <= IPP_PRINTER_IS_DEACTIVATED)
802 return (ipp_status_500s[error - IPP_INTERNAL_ERROR]);
6c48a6ca
MS
803 else if (error >= IPP_AUTHENTICATION_CANCELED && error <= IPP_UPGRADE_REQUIRED)
804 return (ipp_status_1000s[error - IPP_AUTHENTICATION_CANCELED]);
ef416fc2 805
806 /*
d7225fc2 807 * No, build an "0xxxxx" error string...
ef416fc2 808 */
809
d7225fc2 810 sprintf(cg->ipp_unknown, "0x%04x", error);
ef416fc2 811
812 return (cg->ipp_unknown);
813}
814
815
816/*
817 * 'ippErrorValue()' - Return a status code for the given name.
818 *
426c6a59 819 * @since CUPS 1.2/Mac OS X 10.5@
ef416fc2 820 */
821
822ipp_status_t /* O - IPP status code */
823ippErrorValue(const char *name) /* I - Name */
824{
825 int i;
826
827
828 for (i = 0; i < (sizeof(ipp_status_oks) / sizeof(ipp_status_oks[0])); i ++)
88f9aafc 829 if (!_cups_strcasecmp(name, ipp_status_oks[i]))
ef416fc2 830 return ((ipp_status_t)i);
831
88f9aafc 832 if (!_cups_strcasecmp(name, "redirection-other-site"))
ef416fc2 833 return (IPP_REDIRECTION_OTHER_SITE);
834
88f9aafc 835 if (!_cups_strcasecmp(name, "cups-see-other"))
b94498cf 836 return (CUPS_SEE_OTHER);
837
ef416fc2 838 for (i = 0; i < (sizeof(ipp_status_400s) / sizeof(ipp_status_400s[0])); i ++)
88f9aafc 839 if (!_cups_strcasecmp(name, ipp_status_400s[i]))
ef416fc2 840 return ((ipp_status_t)(i + 0x400));
841
842 for (i = 0; i < (sizeof(ipp_status_500s) / sizeof(ipp_status_500s[0])); i ++)
88f9aafc 843 if (!_cups_strcasecmp(name, ipp_status_500s[i]))
ef416fc2 844 return ((ipp_status_t)(i + 0x500));
845
7cf5915e 846 for (i = 0; i < (sizeof(ipp_status_1000s) / sizeof(ipp_status_1000s[0])); i ++)
88f9aafc 847 if (!_cups_strcasecmp(name, ipp_status_1000s[i]))
7cf5915e
MS
848 return ((ipp_status_t)(i + 0x1000));
849
ef416fc2 850 return ((ipp_status_t)-1);
851}
852
853
854/*
855 * 'ippOpString()' - Return a name for the given operation id.
856 *
426c6a59 857 * @since CUPS 1.2/Mac OS X 10.5@
ef416fc2 858 */
859
860const char * /* O - Name */
861ippOpString(ipp_op_t op) /* I - Operation ID */
862{
863 _cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */
864
865
866 /*
867 * See if the operation ID is a known value...
868 */
869
aaf19ab0 870 if (op >= IPP_PRINT_JOB && op <= IPP_CLOSE_JOB)
ef416fc2 871 return (ipp_std_ops[op]);
872 else if (op == IPP_PRIVATE)
873 return ("windows-ext");
b94498cf 874 else if (op >= CUPS_GET_DEFAULT && op <= CUPS_GET_PPD)
ef416fc2 875 return (ipp_cups_ops[op - CUPS_GET_DEFAULT]);
2e4ff8af
MS
876 else if (op == CUPS_GET_DOCUMENT)
877 return (ipp_cups_ops2[0]);
ef416fc2 878
879 /*
d7225fc2 880 * No, build an "0xxxxx" operation string...
ef416fc2 881 */
882
9b66acc5 883 sprintf(cg->ipp_unknown, "0x%04x", op);
ef416fc2 884
885 return (cg->ipp_unknown);
886}
887
888
889/*
890 * 'ippOpValue()' - Return an operation id for the given name.
891 *
426c6a59 892 * @since CUPS 1.2/Mac OS X 10.5@
ef416fc2 893 */
894
895ipp_op_t /* O - Operation ID */
896ippOpValue(const char *name) /* I - Textual name */
897{
898 int i;
899
900
9b66acc5
MS
901 if (!strncmp(name, "0x", 2))
902 return ((ipp_op_t)strtol(name + 2, NULL, 16));
903
ef416fc2 904 for (i = 0; i < (sizeof(ipp_std_ops) / sizeof(ipp_std_ops[0])); i ++)
88f9aafc 905 if (!_cups_strcasecmp(name, ipp_std_ops[i]))
ef416fc2 906 return ((ipp_op_t)i);
907
88f9aafc 908 if (!_cups_strcasecmp(name, "windows-ext"))
ef416fc2 909 return (IPP_PRIVATE);
910
911 for (i = 0; i < (sizeof(ipp_cups_ops) / sizeof(ipp_cups_ops[0])); i ++)
88f9aafc 912 if (!_cups_strcasecmp(name, ipp_cups_ops[i]))
ef416fc2 913 return ((ipp_op_t)(i + 0x4001));
914
2e4ff8af 915 for (i = 0; i < (sizeof(ipp_cups_ops2) / sizeof(ipp_cups_ops2[0])); i ++)
88f9aafc 916 if (!_cups_strcasecmp(name, ipp_cups_ops2[i]))
2e4ff8af
MS
917 return ((ipp_op_t)(i + 0x4027));
918
88f9aafc 919 if (!_cups_strcasecmp(name, "CUPS-Add-Class"))
480ef0fe 920 return (CUPS_ADD_MODIFY_CLASS);
921
88f9aafc 922 if (!_cups_strcasecmp(name, "CUPS-Add-Printer"))
480ef0fe 923 return (CUPS_ADD_MODIFY_PRINTER);
924
ef416fc2 925 return ((ipp_op_t)-1);
926}
927
928
929/*
930 * 'ippPort()' - Return the default IPP port number.
931 */
932
933int /* O - Port number */
934ippPort(void)
935{
ef416fc2 936 _cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */
937
938
d09495fa 939 DEBUG_puts("ippPort()");
940
941 if (!cg->ipp_port)
e07d4801 942 _cupsSetDefaults();
d09495fa 943
e07d4801 944 DEBUG_printf(("1ippPort: Returning %d...", cg->ipp_port));
d09495fa 945
ef416fc2 946 return (cg->ipp_port);
947}
948
949
950/*
951 * 'ippSetPort()' - Set the default port number.
952 */
953
954void
955ippSetPort(int p) /* I - Port number to use */
956{
e07d4801 957 DEBUG_printf(("ippSetPort(p=%d)", p));
d09495fa 958
ef416fc2 959 _cupsGlobals()->ipp_port = p;
960}
961
962
963/*
1ff0402e
MS
964 * 'ippTagString()' - Return the tag name corresponding to a tag value.
965 *
966 * The returned names are defined in RFC 2911 and 3382.
967 *
178cb736 968 * @since CUPS 1.4/Mac OS X 10.6@
1ff0402e
MS
969 */
970
971const char * /* O - Tag name */
972ippTagString(ipp_tag_t tag) /* I - Tag value */
973{
ed6e7faf
MS
974 tag &= IPP_TAG_MASK;
975
1ff0402e
MS
976 if (tag < (ipp_tag_t)(sizeof(ipp_tag_names) / sizeof(ipp_tag_names[0])))
977 return (ipp_tag_names[tag]);
978 else
979 return ("UNKNOWN");
980}
981
982
983/*
984 * 'ippTagValue()' - Return the tag value corresponding to a tag name.
985 *
986 * The tag names are defined in RFC 2911 and 3382.
987 *
178cb736 988 * @since CUPS 1.4/Mac OS X 10.6@
1ff0402e
MS
989 */
990
991ipp_tag_t /* O - Tag value */
992ippTagValue(const char *name) /* I - Tag name */
993{
994 int i; /* Looping var */
995
996
997 for (i = 0; i < (sizeof(ipp_tag_names) / sizeof(ipp_tag_names[0])); i ++)
88f9aafc 998 if (!_cups_strcasecmp(name, ipp_tag_names[i]))
1ff0402e
MS
999 return ((ipp_tag_t)i);
1000
88f9aafc 1001 if (!_cups_strcasecmp(name, "operation"))
1ff0402e 1002 return (IPP_TAG_OPERATION);
88f9aafc 1003 else if (!_cups_strcasecmp(name, "job"))
1ff0402e 1004 return (IPP_TAG_JOB);
88f9aafc 1005 else if (!_cups_strcasecmp(name, "printer"))
1ff0402e 1006 return (IPP_TAG_PRINTER);
88f9aafc 1007 else if (!_cups_strcasecmp(name, "unsupported"))
5a6b583a 1008 return (IPP_TAG_UNSUPPORTED_GROUP);
88f9aafc 1009 else if (!_cups_strcasecmp(name, "subscription"))
1ff0402e 1010 return (IPP_TAG_SUBSCRIPTION);
88f9aafc 1011 else if (!_cups_strcasecmp(name, "event"))
5a6b583a 1012 return (IPP_TAG_EVENT_NOTIFICATION);
88f9aafc 1013 else if (!_cups_strcasecmp(name, "language"))
1ff0402e 1014 return (IPP_TAG_LANGUAGE);
88f9aafc 1015 else if (!_cups_strcasecmp(name, "mimetype"))
1ff0402e 1016 return (IPP_TAG_MIMETYPE);
88f9aafc 1017 else if (!_cups_strcasecmp(name, "name"))
1ff0402e 1018 return (IPP_TAG_NAME);
88f9aafc 1019 else if (!_cups_strcasecmp(name, "text"))
1ff0402e 1020 return (IPP_TAG_TEXT);
88f9aafc 1021 else if (!_cups_strcasecmp(name, "begCollection"))
5a6b583a 1022 return (IPP_TAG_BEGIN_COLLECTION);
1ff0402e
MS
1023 else
1024 return (IPP_TAG_ZERO);
1025}
1026
1027
1028/*
1106b00e
MS
1029 * 'ipp_col_string()' - Convert a collection to a string.
1030 */
1031
1032static size_t /* O - Number of bytes */
1033ipp_col_string(ipp_t *col, /* I - Collection attribute */
1034 char *buffer, /* I - Buffer or NULL */
1035 size_t bufsize) /* I - Size of buffer */
1036{
1037 char *bufptr, /* Position in buffer */
1038 *bufend, /* End of buffer */
9c80ffa2 1039 prefix = '{', /* Prefix character */
1106b00e
MS
1040 temp[256]; /* Temporary string */
1041 ipp_attribute_t *attr; /* Current member attribute */
1042
1043
1044 bufptr = buffer;
1045 bufend = buffer + bufsize - 1;
1046
1106b00e
MS
1047 for (attr = col->attrs; attr; attr = attr->next)
1048 {
1049 if (!attr->name)
1050 continue;
1051
9c80ffa2
MS
1052 if (buffer && bufptr < bufend)
1053 *bufptr = prefix;
1054 bufptr ++;
1055 prefix = ' ';
1056
1106b00e
MS
1057 if (buffer && bufptr < bufend)
1058 bufptr += snprintf(bufptr, bufend - bufptr + 1, "%s=", attr->name);
1059 else
1060 bufptr += strlen(attr->name) + 1;
1061
1062 if (buffer && bufptr < bufend)
a2326b5b 1063 bufptr += ippAttributeString(attr, bufptr, bufend - bufptr + 1);
1106b00e 1064 else
a2326b5b 1065 bufptr += ippAttributeString(attr, temp, sizeof(temp));
1106b00e
MS
1066 }
1067
9c80ffa2
MS
1068 if (prefix == '{')
1069 {
1070 if (buffer && bufptr < bufend)
1071 *bufptr = prefix;
1072 bufptr ++;
1073 }
1074
1106b00e
MS
1075 if (buffer && bufptr < bufend)
1076 *bufptr = '}';
1077 bufptr ++;
1078
1079 return (bufptr - buffer);
1080}
1081
1082
1083/*
1084 * End of "$Id: ipp-support.c 9371 2010-11-17 06:21:32Z mike $".
ef416fc2 1085 */