]> git.ipfire.org Git - thirdparty/cups.git/blob - cups/ipp-support.c
Merge changes from CUPS 1.6svn-r10127.
[thirdparty/cups.git] / cups / ipp-support.c
1 /*
2 * "$Id: ipp-support.c 9371 2010-11-17 06:21:32Z mike $"
3 *
4 * Internet Printing Protocol support functions for CUPS.
5 *
6 * Copyright 2007-2011 by Apple Inc.
7 * Copyright 1997-2007 by Easy Software Products, all rights reserved.
8 *
9 * These coded instructions, statements, and computer programs are the
10 * property of Apple Inc. and are protected by Federal copyright
11 * law. Distribution and use rights are outlined in the file "LICENSE.txt"
12 * which should have been included with this file. If this file is
13 * file is missing or damaged, see the license at "http://www.cups.org/".
14 *
15 * This file is subject to the Apple OS-Developed Software exception.
16 *
17 * Contents:
18 *
19 * ippAttributeString() - Convert the attribute's value to a string.
20 * 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.
32 */
33
34 /*
35 * Include necessary headers...
36 */
37
38 #include "cups-private.h"
39
40
41 /*
42 * Local globals...
43 */
44
45 static const char * const ipp_status_oks[] = /* "OK" status codes */
46 { /* (name) = abandoned standard value */
47 "successful-ok",
48 "successful-ok-ignored-or-substituted-attributes",
49 "successful-ok-conflicting-attributes",
50 "successful-ok-ignored-subscriptions",
51 "(successful-ok-ignored-notifications)",
52 "successful-ok-too-many-events",
53 "(successful-ok-but-cancel-subscription)",
54 "successful-ok-events-complete"
55 },
56 * const ipp_status_400s[] = /* Client errors */
57 { /* (name) = abandoned standard value */
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",
80 "(client-error-ignored-all-notifications)",
81 "(client-error-client-print-support-file-not-found)"
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",
95 "server-error-printer-is-deactivated",
96 "server-error-too-many-jobs",
97 "server-error-too-many-documents"
98 },
99 * const ipp_status_1000s[] = /* CUPS internal */
100 {
101 "cups-authorization-canceled",
102 "cups-pki-error",
103 "cups-upgrade-required"
104 };
105 static const char * const ipp_std_ops[] =
106 {
107 /* 0x0000 - 0x000f */
108 "0x00",
109 "0x01",
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",
123 "0x0f",
124
125 /* 0x0010 - 0x001f */
126 "Pause-Printer",
127 "Resume-Printer",
128 "Purge-Jobs",
129 "Set-Printer-Attributes",
130 "Set-Job-Attributes",
131 "Get-Printer-Supported-Values",
132 "Create-Printer-Subscription",
133 "Create-Job-Subscription",
134 "Get-Subscription-Attributes",
135 "Get-Subscriptions",
136 "Renew-Subscription",
137 "Cancel-Subscription",
138 "Get-Notifications",
139 "(Send-Notifications)",
140 "(Get-Resource-Attributes)",
141 "(Get-Resource-Data)",
142
143 /* 0x0020 - 0x002f */
144 "(Get-Resources)",
145 "(Get-Printer-Support-Files)",
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
161 /* 0x0030 - 0x003b */
162 "Promote-Job",
163 "Schedule-Job-After",
164 "0x32",
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",
173 "Close-Job",
174 "Identify-Printer"
175 },
176 * const ipp_cups_ops[] =
177 {
178 "CUPS-Get-Default",
179 "CUPS-Get-Printers",
180 "CUPS-Add-Modify-Printer",
181 "CUPS-Delete-Printer",
182 "CUPS-Get-Classes",
183 "CUPS-Add-Modify-Class",
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",
191 "CUPS-Authenticate-Job",
192 "CUPS-Get-PPD"
193 },
194 * const ipp_cups_ops2[] =
195 {
196 "CUPS-Get-Document"
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 */
214 "(resource-attributes-tag)",
215 /* 0x08 */
216 "document-attributes-tag",
217 /* 0x09 */
218 "0x0a", /* 0x0a */
219 "0x0b", /* 0x0b */
220 "0x0c", /* 0x0c */
221 "0x0d", /* 0x0d */
222 "0x0e", /* 0x0e */
223 "0x0f", /* 0x0f */
224 "unsupported", /* 0x10 */
225 "default", /* 0x11 */
226 "unknown", /* 0x12 */
227 "no-value", /* 0x13 */
228 "0x14", /* 0x14 */
229 "not-settable", /* 0x15 */
230 "delete-attribute", /* 0x16 */
231 "admin-define", /* 0x17 */
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 */
241 "integer", /* 0x21 */
242 "boolean", /* 0x22 */
243 "enum", /* 0x23 */
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 */
256 "octetString", /* 0x30 */
257 "dateTime", /* 0x31 */
258 "resolution", /* 0x32 */
259 "rangeOfInteger", /* 0x33 */
260 "collection", /* 0x34 */
261 "textWithLanguage", /* 0x35 */
262 "nameWithLanguage", /* 0x36 */
263 "endCollection", /* 0x37 */
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 */
273 "textWithoutLanguage",/* 0x41 */
274 "nameWithoutLanguage",/* 0x42 */
275 "0x43", /* 0x43 */
276 "keyword", /* 0x44 */
277 "uri", /* 0x45 */
278 "uriScheme", /* 0x46 */
279 "charset", /* 0x47 */
280 "naturalLanguage", /* 0x48 */
281 "mimeMediaType", /* 0x49 */
282 "memberAttrName" /* 0x4a */
283 };
284 static 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 };
393
394
395 /*
396 * Local functions...
397 */
398
399 static size_t ipp_col_string(ipp_t *col, char *buffer, size_t bufsize);
400
401
402 /*
403 * 'ippAttributeString()' - Convert the attribute's value to a string.
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.
408 *
409 * @since CUPS 1.6@
410 */
411
412 size_t /* O - Number of bytes less nul */
413 ippAttributeString(
414 ipp_attribute_t *attr, /* I - Attribute */
415 char *buffer, /* I - String buffer or NULL */
416 size_t bufsize) /* I - Size of string buffer */
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 */
423 _ipp_value_t *val; /* Current value */
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 {
444 if (buffer && bufptr < bufend)
445 *bufptr++ = ',';
446 else
447 bufptr ++;
448 }
449
450 switch (attr->value_tag & ~IPP_TAG_COPY)
451 {
452 case IPP_TAG_ENUM :
453 ptr = ippEnumString(attr->name, val->integer);
454
455 if (buffer && bufptr < bufend)
456 strlcpy(bufptr, ptr, bufend - bufptr + 1);
457
458 bufptr += strlen(ptr);
459 break;
460
461 case IPP_TAG_INTEGER :
462 if (buffer && bufptr < bufend)
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 :
469 if (buffer && bufptr < bufend)
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 :
477 if (buffer && bufptr < bufend)
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 :
486 if (buffer && bufptr < bufend)
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 ?
490 "dpi" : "dpc");
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 ?
495 "dpi" : "dpc");
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
515 if (buffer && bufptr < bufend)
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 :
527 case IPP_TAG_URISCHEME :
528 case IPP_TAG_MIMETYPE :
529 case IPP_TAG_LANGUAGE :
530 case IPP_TAG_TEXTLANG :
531 case IPP_TAG_NAMELANG :
532 if (!val->string.text)
533 break;
534
535 for (ptr = val->string.text; *ptr; ptr ++)
536 {
537 if (*ptr == '\\' || *ptr == '\"' || *ptr == '[')
538 {
539 if (buffer && bufptr < bufend)
540 *bufptr = '\\';
541 bufptr ++;
542 }
543
544 if (buffer && bufptr < bufend)
545 *bufptr = *ptr;
546 bufptr ++;
547 }
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 }
567 break;
568
569 case IPP_TAG_BEGIN_COLLECTION :
570 if (buffer && bufptr < bufend)
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 {
580 if (*ptr == '\\' || _cups_isspace(*ptr))
581 {
582 if (buffer && bufptr < bufend)
583 *bufptr = '\\';
584 bufptr ++;
585
586 if (buffer && bufptr < bufend)
587 *bufptr = *ptr;
588 bufptr ++;
589 }
590 else if (!isprint(*ptr & 255))
591 {
592 if (buffer && bufptr < bufend)
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 {
601 if (buffer && bufptr < bufend)
602 *bufptr = *ptr;
603 bufptr ++;
604 }
605 }
606 break;
607
608 default :
609 ptr = ippTagString(attr->value_tag);
610 if (buffer && bufptr < bufend)
611 strlcpy(bufptr, ptr, bufend - bufptr + 1);
612 bufptr += strlen(ptr);
613 break;
614 }
615 }
616
617 if (buffer && bufptr < bufend)
618 *bufptr = '\0';
619 else if (bufend)
620 *bufend = '\0';
621
622 return (bufptr - buffer);
623 }
624
625
626 /*
627 * 'ippEnumString()' - Return a string corresponding to the enum value.
628 */
629
630 const char * /* O - Enum string */
631 ippEnumString(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
698 int /* O - Enum value or -1 if unknown */
699 ippEnumValue(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
779 /*
780 * 'ippErrorString()' - Return a name for the given status code.
781 */
782
783 const char * /* O - Text string */
784 ippErrorString(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
793 if (error >= IPP_OK && error <= IPP_OK_EVENTS_COMPLETE)
794 return (ipp_status_oks[error]);
795 else if (error == IPP_REDIRECTION_OTHER_SITE)
796 return ("redirection-other-site");
797 else if (error == CUPS_SEE_OTHER)
798 return ("cups-see-other");
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]);
803 else if (error >= IPP_AUTHENTICATION_CANCELED && error <= IPP_UPGRADE_REQUIRED)
804 return (ipp_status_1000s[error - IPP_AUTHENTICATION_CANCELED]);
805
806 /*
807 * No, build an "0xxxxx" error string...
808 */
809
810 sprintf(cg->ipp_unknown, "0x%04x", error);
811
812 return (cg->ipp_unknown);
813 }
814
815
816 /*
817 * 'ippErrorValue()' - Return a status code for the given name.
818 *
819 * @since CUPS 1.2/Mac OS X 10.5@
820 */
821
822 ipp_status_t /* O - IPP status code */
823 ippErrorValue(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 ++)
829 if (!_cups_strcasecmp(name, ipp_status_oks[i]))
830 return ((ipp_status_t)i);
831
832 if (!_cups_strcasecmp(name, "redirection-other-site"))
833 return (IPP_REDIRECTION_OTHER_SITE);
834
835 if (!_cups_strcasecmp(name, "cups-see-other"))
836 return (CUPS_SEE_OTHER);
837
838 for (i = 0; i < (sizeof(ipp_status_400s) / sizeof(ipp_status_400s[0])); i ++)
839 if (!_cups_strcasecmp(name, ipp_status_400s[i]))
840 return ((ipp_status_t)(i + 0x400));
841
842 for (i = 0; i < (sizeof(ipp_status_500s) / sizeof(ipp_status_500s[0])); i ++)
843 if (!_cups_strcasecmp(name, ipp_status_500s[i]))
844 return ((ipp_status_t)(i + 0x500));
845
846 for (i = 0; i < (sizeof(ipp_status_1000s) / sizeof(ipp_status_1000s[0])); i ++)
847 if (!_cups_strcasecmp(name, ipp_status_1000s[i]))
848 return ((ipp_status_t)(i + 0x1000));
849
850 return ((ipp_status_t)-1);
851 }
852
853
854 /*
855 * 'ippOpString()' - Return a name for the given operation id.
856 *
857 * @since CUPS 1.2/Mac OS X 10.5@
858 */
859
860 const char * /* O - Name */
861 ippOpString(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
870 if (op >= IPP_PRINT_JOB && op <= IPP_CLOSE_JOB)
871 return (ipp_std_ops[op]);
872 else if (op == IPP_PRIVATE)
873 return ("windows-ext");
874 else if (op >= CUPS_GET_DEFAULT && op <= CUPS_GET_PPD)
875 return (ipp_cups_ops[op - CUPS_GET_DEFAULT]);
876 else if (op == CUPS_GET_DOCUMENT)
877 return (ipp_cups_ops2[0]);
878
879 /*
880 * No, build an "0xxxxx" operation string...
881 */
882
883 sprintf(cg->ipp_unknown, "0x%04x", op);
884
885 return (cg->ipp_unknown);
886 }
887
888
889 /*
890 * 'ippOpValue()' - Return an operation id for the given name.
891 *
892 * @since CUPS 1.2/Mac OS X 10.5@
893 */
894
895 ipp_op_t /* O - Operation ID */
896 ippOpValue(const char *name) /* I - Textual name */
897 {
898 int i;
899
900
901 if (!strncmp(name, "0x", 2))
902 return ((ipp_op_t)strtol(name + 2, NULL, 16));
903
904 for (i = 0; i < (sizeof(ipp_std_ops) / sizeof(ipp_std_ops[0])); i ++)
905 if (!_cups_strcasecmp(name, ipp_std_ops[i]))
906 return ((ipp_op_t)i);
907
908 if (!_cups_strcasecmp(name, "windows-ext"))
909 return (IPP_PRIVATE);
910
911 for (i = 0; i < (sizeof(ipp_cups_ops) / sizeof(ipp_cups_ops[0])); i ++)
912 if (!_cups_strcasecmp(name, ipp_cups_ops[i]))
913 return ((ipp_op_t)(i + 0x4001));
914
915 for (i = 0; i < (sizeof(ipp_cups_ops2) / sizeof(ipp_cups_ops2[0])); i ++)
916 if (!_cups_strcasecmp(name, ipp_cups_ops2[i]))
917 return ((ipp_op_t)(i + 0x4027));
918
919 if (!_cups_strcasecmp(name, "CUPS-Add-Class"))
920 return (CUPS_ADD_MODIFY_CLASS);
921
922 if (!_cups_strcasecmp(name, "CUPS-Add-Printer"))
923 return (CUPS_ADD_MODIFY_PRINTER);
924
925 return ((ipp_op_t)-1);
926 }
927
928
929 /*
930 * 'ippPort()' - Return the default IPP port number.
931 */
932
933 int /* O - Port number */
934 ippPort(void)
935 {
936 _cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */
937
938
939 DEBUG_puts("ippPort()");
940
941 if (!cg->ipp_port)
942 _cupsSetDefaults();
943
944 DEBUG_printf(("1ippPort: Returning %d...", cg->ipp_port));
945
946 return (cg->ipp_port);
947 }
948
949
950 /*
951 * 'ippSetPort()' - Set the default port number.
952 */
953
954 void
955 ippSetPort(int p) /* I - Port number to use */
956 {
957 DEBUG_printf(("ippSetPort(p=%d)", p));
958
959 _cupsGlobals()->ipp_port = p;
960 }
961
962
963 /*
964 * 'ippTagString()' - Return the tag name corresponding to a tag value.
965 *
966 * The returned names are defined in RFC 2911 and 3382.
967 *
968 * @since CUPS 1.4/Mac OS X 10.6@
969 */
970
971 const char * /* O - Tag name */
972 ippTagString(ipp_tag_t tag) /* I - Tag value */
973 {
974 tag &= IPP_TAG_MASK;
975
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 *
988 * @since CUPS 1.4/Mac OS X 10.6@
989 */
990
991 ipp_tag_t /* O - Tag value */
992 ippTagValue(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 ++)
998 if (!_cups_strcasecmp(name, ipp_tag_names[i]))
999 return ((ipp_tag_t)i);
1000
1001 if (!_cups_strcasecmp(name, "operation"))
1002 return (IPP_TAG_OPERATION);
1003 else if (!_cups_strcasecmp(name, "job"))
1004 return (IPP_TAG_JOB);
1005 else if (!_cups_strcasecmp(name, "printer"))
1006 return (IPP_TAG_PRINTER);
1007 else if (!_cups_strcasecmp(name, "unsupported"))
1008 return (IPP_TAG_UNSUPPORTED_GROUP);
1009 else if (!_cups_strcasecmp(name, "subscription"))
1010 return (IPP_TAG_SUBSCRIPTION);
1011 else if (!_cups_strcasecmp(name, "event"))
1012 return (IPP_TAG_EVENT_NOTIFICATION);
1013 else if (!_cups_strcasecmp(name, "language"))
1014 return (IPP_TAG_LANGUAGE);
1015 else if (!_cups_strcasecmp(name, "mimetype"))
1016 return (IPP_TAG_MIMETYPE);
1017 else if (!_cups_strcasecmp(name, "name"))
1018 return (IPP_TAG_NAME);
1019 else if (!_cups_strcasecmp(name, "text"))
1020 return (IPP_TAG_TEXT);
1021 else if (!_cups_strcasecmp(name, "begCollection"))
1022 return (IPP_TAG_BEGIN_COLLECTION);
1023 else
1024 return (IPP_TAG_ZERO);
1025 }
1026
1027
1028 /*
1029 * 'ipp_col_string()' - Convert a collection to a string.
1030 */
1031
1032 static size_t /* O - Number of bytes */
1033 ipp_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 */
1039 prefix = '{', /* Prefix character */
1040 temp[256]; /* Temporary string */
1041 ipp_attribute_t *attr; /* Current member attribute */
1042
1043
1044 bufptr = buffer;
1045 bufend = buffer + bufsize - 1;
1046
1047 for (attr = col->attrs; attr; attr = attr->next)
1048 {
1049 if (!attr->name)
1050 continue;
1051
1052 if (buffer && bufptr < bufend)
1053 *bufptr = prefix;
1054 bufptr ++;
1055 prefix = ' ';
1056
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)
1063 bufptr += ippAttributeString(attr, bufptr, bufend - bufptr + 1);
1064 else
1065 bufptr += ippAttributeString(attr, temp, sizeof(temp));
1066 }
1067
1068 if (prefix == '{')
1069 {
1070 if (buffer && bufptr < bufend)
1071 *bufptr = prefix;
1072 bufptr ++;
1073 }
1074
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 $".
1085 */