]> git.ipfire.org Git - thirdparty/cups.git/blob - cups/ipp-support.c
Merge changes from CUPS 1.5svn-r9313.
[thirdparty/cups.git] / cups / ipp-support.c
1 /*
2 * "$Id: ipp-support.c 7847 2008-08-19 04:22:14Z mike $"
3 *
4 * Internet Printing Protocol support functions for CUPS.
5 *
6 * Copyright 2007-2010 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 * _ippAttrString() - Convert the attribute's value to a string.
20 * ippErrorString() - Return a name for the given status code.
21 * ippErrorValue() - Return a status code for the given name.
22 * ippOpString() - Return a name for the given operation id.
23 * ippOpValue() - Return an operation id for the given name.
24 * ippPort() - Return the default IPP port number.
25 * ippSetPort() - Set the default port number.
26 * ippTagString() - Return the tag name corresponding to a tag value.
27 * ippTagValue() - Return the tag value corresponding to a tag name.
28 * ipp_col_string() - Convert a collection to a string.
29 */
30
31 /*
32 * Include necessary headers...
33 */
34
35 #include "cups-private.h"
36
37
38 /*
39 * Local globals...
40 */
41
42 static const char * const ipp_status_oks[] = /* "OK" status codes */
43 {
44 "successful-ok",
45 "successful-ok-ignored-or-substituted-attributes",
46 "successful-ok-conflicting-attributes",
47 "successful-ok-ignored-subscriptions",
48 "successful-ok-ignored-notifications",
49 "successful-ok-too-many-events",
50 "successful-ok-but-cancel-subscription",
51 "successful-ok-events-complete"
52 },
53 * const ipp_status_400s[] = /* Client errors */
54 {
55 "client-error-bad-request",
56 "client-error-forbidden",
57 "client-error-not-authenticated",
58 "client-error-not-authorized",
59 "client-error-not-possible",
60 "client-error-timeout",
61 "client-error-not-found",
62 "client-error-gone",
63 "client-error-request-entity-too-large",
64 "client-error-request-value-too-long",
65 "client-error-document-format-not-supported",
66 "client-error-attributes-or-values-not-supported",
67 "client-error-uri-scheme-not-supported",
68 "client-error-charset-not-supported",
69 "client-error-conflicting-attributes",
70 "client-error-compression-not-supported",
71 "client-error-compression-error",
72 "client-error-document-format-error",
73 "client-error-document-access-error",
74 "client-error-attributes-not-settable",
75 "client-error-ignored-all-subscriptions",
76 "client-error-too-many-subscriptions",
77 "client-error-ignored-all-notifications",
78 "client-error-print-support-file-not-found"
79 },
80 * const ipp_status_500s[] = /* Server errors */
81 {
82 "server-error-internal-error",
83 "server-error-operation-not-supported",
84 "server-error-service-unavailable",
85 "server-error-version-not-supported",
86 "server-error-device-error",
87 "server-error-temporary-error",
88 "server-error-not-accepting-jobs",
89 "server-error-busy",
90 "server-error-job-canceled",
91 "server-error-multiple-document-jobs-not-supported",
92 "server-error-printer-is-deactivated"
93 },
94 * const ipp_status_1000s[] = /* CUPS internal */
95 {
96 "cups-authorization-canceled",
97 "cups-pki-error",
98 "cups-upgrade-required"
99 };
100 static char * const ipp_std_ops[] =
101 {
102 /* 0x0000 - 0x000f */
103 "unknown-00",
104 "unknown-01",
105 "Print-Job",
106 "Print-URI",
107 "Validate-Job",
108 "Create-Job",
109 "Send-Document",
110 "Send-URI",
111 "Cancel-Job",
112 "Get-Job-Attributes",
113 "Get-Jobs",
114 "Get-Printer-Attributes",
115 "Hold-Job",
116 "Release-Job",
117 "Restart-Job",
118 "unknown-0f",
119
120 /* 0x0010 - 0x001f */
121 "Pause-Printer",
122 "Resume-Printer",
123 "Purge-Jobs",
124 "Set-Printer-Attributes",
125 "Set-Job-Attributes",
126 "Get-Printer-Supported-Values",
127 "Create-Printer-Subscription",
128 "Create-Job-Subscription",
129 "Get-Subscription-Attributes",
130 "Get-Subscriptions",
131 "Renew-Subscription",
132 "Cancel-Subscription",
133 "Get-Notifications",
134 "Send-Notifications",
135 "unknown-1e",
136 "unknown-1f",
137
138 /* 0x0020 - 0x002f */
139 "unknown-20",
140 "Get-Printer-Support-Files",
141 "Enable-Printer",
142 "Disable-Printer",
143 "Pause-Printer-After-Current-Job",
144 "Hold-New-Jobs",
145 "Release-Held-New-Jobs",
146 "Deactivate-Printer",
147 "Activate-Printer",
148 "Restart-Printer",
149 "Shutdown-Printer",
150 "Startup-Printer",
151 "Reprocess-Job",
152 "Cancel-Current-Job",
153 "Suspend-Current-Job",
154 "Resume-Job",
155
156 /* 0x0030 - 0x003b */
157 "Promote-Job",
158 "Schedule-Job-After",
159 "unknown-32",
160 "Cancel-Document",
161 "Get-Document-Attributes",
162 "Get-Documents",
163 "Delete-Document",
164 "Set-Document-Attributes",
165 "Cancel-Jobs",
166 "Cancel-My-Jobs",
167 "Resubmit-Job",
168 "Close-Job"
169 },
170 * const ipp_cups_ops[] =
171 {
172 "CUPS-Get-Default",
173 "CUPS-Get-Printers",
174 "CUPS-Add-Modify-Printer",
175 "CUPS-Delete-Printer",
176 "CUPS-Get-Classes",
177 "CUPS-Add-Modify-Class",
178 "CUPS-Delete-Class",
179 "CUPS-Accept-Jobs",
180 "CUPS-Reject-Jobs",
181 "CUPS-Set-Default",
182 "CUPS-Get-Devices",
183 "CUPS-Get-PPDs",
184 "CUPS-Move-Job",
185 "CUPS-Authenticate-Job",
186 "CUPS-Get-PPD"
187 },
188 * const ipp_cups_ops2[] =
189 {
190 "CUPS-Get-Document"
191 },
192 * const ipp_tag_names[] =
193 { /* Value/group tag names */
194 "zero", /* 0x00 */
195 "operation-attributes-tag",
196 /* 0x01 */
197 "job-attributes-tag", /* 0x02 */
198 "end-of-attributes-tag",
199 /* 0x03 */
200 "printer-attributes-tag",
201 /* 0x04 */
202 "unsupported-attributes-tag",
203 /* 0x05 */
204 "subscription-attributes-tag",
205 /* 0x06 */
206 "event-notification-attributes-tag",
207 /* 0x07 */
208 "unknown-08", /* 0x08 */
209 "unknown-09", /* 0x09 */
210 "unknown-0a", /* 0x0a */
211 "unknown-0b", /* 0x0b */
212 "unknown-0c", /* 0x0c */
213 "unknown-0d", /* 0x0d */
214 "unknown-0e", /* 0x0e */
215 "unknown-0f", /* 0x0f */
216 "unsupported", /* 0x10 */
217 "default", /* 0x11 */
218 "unknown", /* 0x12 */
219 "no-value", /* 0x13 */
220 "unknown-14", /* 0x14 */
221 "not-settable", /* 0x15 */
222 "delete-attribute", /* 0x16 */
223 "admin-define", /* 0x17 */
224 "unknown-18", /* 0x18 */
225 "unknown-19", /* 0x19 */
226 "unknown-1a", /* 0x1a */
227 "unknown-1b", /* 0x1b */
228 "unknown-1c", /* 0x1c */
229 "unknown-1d", /* 0x1d */
230 "unknown-1e", /* 0x1e */
231 "unknown-1f", /* 0x1f */
232 "unknown-20", /* 0x20 */
233 "integer", /* 0x21 */
234 "boolean", /* 0x22 */
235 "enum", /* 0x23 */
236 "unknown-24", /* 0x24 */
237 "unknown-25", /* 0x25 */
238 "unknown-26", /* 0x26 */
239 "unknown-27", /* 0x27 */
240 "unknown-28", /* 0x28 */
241 "unknown-29", /* 0x29 */
242 "unknown-2a", /* 0x2a */
243 "unknown-2b", /* 0x2b */
244 "unknown-2c", /* 0x2c */
245 "unknown-2d", /* 0x2d */
246 "unknown-2e", /* 0x2e */
247 "unknown-2f", /* 0x2f */
248 "octetString", /* 0x30 */
249 "dateTime", /* 0x31 */
250 "resolution", /* 0x32 */
251 "rangeOfInteger", /* 0x33 */
252 "collection", /* 0x34 */
253 "textWithLanguage", /* 0x35 */
254 "nameWithLanguage", /* 0x36 */
255 "endCollection", /* 0x37 */
256 "unknown-38", /* 0x38 */
257 "unknown-39", /* 0x39 */
258 "unknown-3a", /* 0x3a */
259 "unknown-3b", /* 0x3b */
260 "unknown-3c", /* 0x3c */
261 "unknown-3d", /* 0x3d */
262 "unknown-3e", /* 0x3e */
263 "unknown-3f", /* 0x3f */
264 "unknown-40", /* 0x40 */
265 "textWithoutLanguage",/* 0x41 */
266 "nameWithoutLanguage",/* 0x42 */
267 "unknown-43", /* 0x43 */
268 "keyword", /* 0x44 */
269 "uri", /* 0x45 */
270 "uriScheme", /* 0x46 */
271 "charset", /* 0x47 */
272 "naturalLanguage", /* 0x48 */
273 "mimeMediaType", /* 0x49 */
274 "memberAttrName" /* 0x4a */
275 };
276 static const char * const job_states[] =
277 { /* job-state enums */
278 "pending",
279 "pending-held",
280 "processing",
281 "processing-stopped",
282 "canceled",
283 "aborted",
284 "completed"
285 };
286 static const char * const printer_states[] =
287 { /* printer-state enums */
288 "idle",
289 "processing",
290 "stopped",
291 };
292
293
294 /*
295 * Local functions...
296 */
297
298 static size_t ipp_col_string(ipp_t *col, char *buffer, size_t bufsize);
299
300
301 /*
302 * '_ippAttrString()' - Convert the attribute's value to a string.
303 *
304 * Returns the number of bytes that would be written, not including the
305 * trailing nul. The buffer pointer can be NULL to get the required length,
306 * just like (v)snprintf.
307 */
308
309 size_t /* O - Number of bytes less nul */
310 _ippAttrString(ipp_attribute_t *attr, /* I - Attribute */
311 char *buffer, /* I - String buffer or NULL */
312 size_t bufsize) /* I - Size of string buffer */
313 {
314 int i; /* Looping var */
315 char *bufptr, /* Pointer into buffer */
316 *bufend, /* End of buffer */
317 temp[256]; /* Temporary string */
318 const char *ptr; /* Pointer into string */
319 ipp_value_t *val; /* Current value */
320
321
322 if (!attr || !attr->name)
323 {
324 if (buffer)
325 *buffer = '\0';
326
327 return (0);
328 }
329
330 bufptr = buffer;
331 if (buffer)
332 bufend = buffer + bufsize - 1;
333 else
334 bufend = NULL;
335
336 for (i = attr->num_values, val = attr->values; i > 0; i --, val ++)
337 {
338 if (val > attr->values)
339 {
340 if (buffer && bufptr < bufend)
341 *bufptr++ = ',';
342 else
343 bufptr ++;
344 }
345
346 switch (attr->value_tag)
347 {
348 case IPP_TAG_ENUM :
349 if (!strcmp(attr->name, "printer-state") &&
350 val->integer >= IPP_PRINTER_IDLE &&
351 val->integer <= IPP_PRINTER_STOPPED)
352 {
353 ptr = printer_states[val->integer - IPP_PRINTER_IDLE];
354
355 if (buffer && bufptr < bufend)
356 strlcpy(bufptr, ptr, bufend - bufptr + 1);
357
358 bufptr += strlen(ptr);
359 break;
360 }
361 else if (!strcmp(attr->name, "job-state") &&
362 val->integer >= IPP_JOB_PENDING &&
363 val->integer <= IPP_JOB_COMPLETED)
364 {
365 ptr = job_states[val->integer - IPP_JOB_PENDING];
366
367 if (buffer && bufptr < bufend)
368 strlcpy(bufptr, ptr, bufend - bufptr + 1);
369
370 bufptr += strlen(ptr);
371 break;
372 }
373
374 case IPP_TAG_INTEGER :
375 if (buffer && bufptr < bufend)
376 bufptr += snprintf(bufptr, bufend - bufptr + 1, "%d", val->integer);
377 else
378 bufptr += snprintf(temp, sizeof(temp), "%d", val->integer);
379 break;
380
381 case IPP_TAG_BOOLEAN :
382 if (buffer && bufptr < bufend)
383 strlcpy(bufptr, val->boolean ? "true" : "false",
384 bufend - bufptr + 1);
385
386 bufptr += val->boolean ? 4 : 5;
387 break;
388
389 case IPP_TAG_RANGE :
390 if (buffer && bufptr < bufend)
391 bufptr += snprintf(bufptr, bufend - bufptr + 1, "%d-%d",
392 val->range.lower, val->range.upper);
393 else
394 bufptr += snprintf(temp, sizeof(temp), "%d-%d", val->range.lower,
395 val->range.upper);
396 break;
397
398 case IPP_TAG_RESOLUTION :
399 if (buffer && bufptr < bufend)
400 bufptr += snprintf(bufptr, bufend - bufptr + 1, "%dx%d%s",
401 val->resolution.xres, val->resolution.yres,
402 val->resolution.units == IPP_RES_PER_INCH ?
403 "dpi" : "dpc");
404 else
405 bufptr += snprintf(temp, sizeof(temp), "%dx%d%s",
406 val->resolution.xres, val->resolution.yres,
407 val->resolution.units == IPP_RES_PER_INCH ?
408 "dpi" : "dpc");
409 break;
410
411 case IPP_TAG_DATE :
412 {
413 unsigned year; /* Year */
414
415 year = (val->date[0] << 8) + val->date[1];
416
417 if (val->date[9] == 0 && val->date[10] == 0)
418 snprintf(temp, sizeof(temp), "%04u-%02u-%02uT%02u:%02u:%02uZ",
419 year, val->date[2], val->date[3], val->date[4],
420 val->date[5], val->date[6]);
421 else
422 snprintf(temp, sizeof(temp),
423 "%04u-%02u-%02uT%02u:%02u:%02u%c%02u%02u",
424 year, val->date[2], val->date[3], val->date[4],
425 val->date[5], val->date[6], val->date[8], val->date[9],
426 val->date[10]);
427
428 if (buffer && bufptr < bufend)
429 strlcpy(bufptr, temp, bufend - bufptr + 1);
430
431 bufptr += strlen(temp);
432 }
433 break;
434
435 case IPP_TAG_TEXT :
436 case IPP_TAG_NAME :
437 case IPP_TAG_KEYWORD :
438 case IPP_TAG_CHARSET :
439 case IPP_TAG_URI :
440 case IPP_TAG_MIMETYPE :
441 case IPP_TAG_LANGUAGE :
442 case IPP_TAG_TEXTLANG :
443 case IPP_TAG_NAMELANG :
444 if (!val->string.text)
445 break;
446
447 for (ptr = val->string.text; *ptr; ptr ++)
448 {
449 if (*ptr == '\\' || *ptr == '\"')
450 {
451 if (buffer && bufptr < bufend)
452 *bufptr = '\\';
453 bufptr ++;
454 }
455
456 if (buffer && bufptr < bufend)
457 *bufptr = *ptr;
458 bufptr ++;
459 }
460 break;
461
462 case IPP_TAG_BEGIN_COLLECTION :
463 if (buffer && bufptr < bufend)
464 bufptr += ipp_col_string(val->collection, bufptr,
465 bufend - bufptr + 1);
466 else
467 bufptr += ipp_col_string(val->collection, NULL, 0);
468 break;
469
470 case IPP_TAG_STRING :
471 for (ptr = val->string.text; *ptr; ptr ++)
472 {
473 if (*ptr == '\\' || _cups_isspace(*ptr))
474 {
475 if (buffer && bufptr < bufend)
476 *bufptr = '\\';
477 bufptr ++;
478
479 if (buffer && bufptr < bufend)
480 *bufptr = *ptr;
481 bufptr ++;
482 }
483 else if (!isprint(*ptr & 255))
484 {
485 if (buffer && bufptr < bufend)
486 bufptr += snprintf(bufptr, bufend - bufptr + 1, "\\%03o",
487 *ptr & 255);
488 else
489 bufptr += snprintf(temp, sizeof(temp), "\\%03o",
490 *ptr & 255);
491 }
492 else
493 {
494 if (buffer && bufptr < bufend)
495 *bufptr = *ptr;
496 bufptr ++;
497 }
498 }
499 break;
500
501 default :
502 ptr = ippTagString(attr->value_tag);
503 if (buffer && bufptr < bufend)
504 strlcpy(bufptr, ptr, bufend - bufptr + 1);
505 bufptr += strlen(ptr);
506 break;
507 }
508 }
509
510 if (buffer && bufptr < bufend)
511 *bufptr = '\0';
512 else if (bufend)
513 *bufend = '\0';
514
515 return (bufptr - buffer);
516 }
517
518
519 /*
520 * 'ippErrorString()' - Return a name for the given status code.
521 */
522
523 const char * /* O - Text string */
524 ippErrorString(ipp_status_t error) /* I - Error status */
525 {
526 _cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */
527
528
529 /*
530 * See if the error code is a known value...
531 */
532
533 if (error >= IPP_OK && error <= IPP_OK_EVENTS_COMPLETE)
534 return (ipp_status_oks[error]);
535 else if (error == IPP_REDIRECTION_OTHER_SITE)
536 return ("redirection-other-site");
537 else if (error == CUPS_SEE_OTHER)
538 return ("cups-see-other");
539 else if (error >= IPP_BAD_REQUEST && error <= IPP_PRINT_SUPPORT_FILE_NOT_FOUND)
540 return (ipp_status_400s[error - IPP_BAD_REQUEST]);
541 else if (error >= IPP_INTERNAL_ERROR && error <= IPP_PRINTER_IS_DEACTIVATED)
542 return (ipp_status_500s[error - IPP_INTERNAL_ERROR]);
543 else if (error >= IPP_AUTHORIZATION_CANCELED && error <= IPP_UPGRADE_REQUIRED)
544 return (ipp_status_1000s[error - IPP_AUTHORIZATION_CANCELED]);
545
546 /*
547 * No, build an "unknown-xxxx" error string...
548 */
549
550 sprintf(cg->ipp_unknown, "unknown-%04x", error);
551
552 return (cg->ipp_unknown);
553 }
554
555
556 /*
557 * 'ippErrorValue()' - Return a status code for the given name.
558 *
559 * @since CUPS 1.2/Mac OS X 10.5@
560 */
561
562 ipp_status_t /* O - IPP status code */
563 ippErrorValue(const char *name) /* I - Name */
564 {
565 int i;
566
567
568 for (i = 0; i < (sizeof(ipp_status_oks) / sizeof(ipp_status_oks[0])); i ++)
569 if (!strcasecmp(name, ipp_status_oks[i]))
570 return ((ipp_status_t)i);
571
572 if (!strcasecmp(name, "redirection-other-site"))
573 return (IPP_REDIRECTION_OTHER_SITE);
574
575 if (!strcasecmp(name, "cups-see-other"))
576 return (CUPS_SEE_OTHER);
577
578 for (i = 0; i < (sizeof(ipp_status_400s) / sizeof(ipp_status_400s[0])); i ++)
579 if (!strcasecmp(name, ipp_status_400s[i]))
580 return ((ipp_status_t)(i + 0x400));
581
582 for (i = 0; i < (sizeof(ipp_status_500s) / sizeof(ipp_status_500s[0])); i ++)
583 if (!strcasecmp(name, ipp_status_500s[i]))
584 return ((ipp_status_t)(i + 0x500));
585
586 for (i = 0; i < (sizeof(ipp_status_1000s) / sizeof(ipp_status_1000s[0])); i ++)
587 if (!strcasecmp(name, ipp_status_1000s[i]))
588 return ((ipp_status_t)(i + 0x1000));
589
590 return ((ipp_status_t)-1);
591 }
592
593
594 /*
595 * 'ippOpString()' - Return a name for the given operation id.
596 *
597 * @since CUPS 1.2/Mac OS X 10.5@
598 */
599
600 const char * /* O - Name */
601 ippOpString(ipp_op_t op) /* I - Operation ID */
602 {
603 _cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */
604
605
606 /*
607 * See if the operation ID is a known value...
608 */
609
610 if (op >= IPP_PRINT_JOB && op <= IPP_CLOSE_JOB)
611 return (ipp_std_ops[op]);
612 else if (op == IPP_PRIVATE)
613 return ("windows-ext");
614 else if (op >= CUPS_GET_DEFAULT && op <= CUPS_GET_PPD)
615 return (ipp_cups_ops[op - CUPS_GET_DEFAULT]);
616 else if (op == CUPS_GET_DOCUMENT)
617 return (ipp_cups_ops2[0]);
618
619 /*
620 * No, build an "unknown-xxxx" operation string...
621 */
622
623 sprintf(cg->ipp_unknown, "unknown-%04x", op);
624
625 return (cg->ipp_unknown);
626 }
627
628
629 /*
630 * 'ippOpValue()' - Return an operation id for the given name.
631 *
632 * @since CUPS 1.2/Mac OS X 10.5@
633 */
634
635 ipp_op_t /* O - Operation ID */
636 ippOpValue(const char *name) /* I - Textual name */
637 {
638 int i;
639
640
641 for (i = 0; i < (sizeof(ipp_std_ops) / sizeof(ipp_std_ops[0])); i ++)
642 if (!strcasecmp(name, ipp_std_ops[i]))
643 return ((ipp_op_t)i);
644
645 if (!strcasecmp(name, "windows-ext"))
646 return (IPP_PRIVATE);
647
648 for (i = 0; i < (sizeof(ipp_cups_ops) / sizeof(ipp_cups_ops[0])); i ++)
649 if (!strcasecmp(name, ipp_cups_ops[i]))
650 return ((ipp_op_t)(i + 0x4001));
651
652 for (i = 0; i < (sizeof(ipp_cups_ops2) / sizeof(ipp_cups_ops2[0])); i ++)
653 if (!strcasecmp(name, ipp_cups_ops2[i]))
654 return ((ipp_op_t)(i + 0x4027));
655
656 if (!strcasecmp(name, "CUPS-Add-Class"))
657 return (CUPS_ADD_MODIFY_CLASS);
658
659 if (!strcasecmp(name, "CUPS-Add-Printer"))
660 return (CUPS_ADD_MODIFY_PRINTER);
661
662 return ((ipp_op_t)-1);
663 }
664
665
666 /*
667 * 'ippPort()' - Return the default IPP port number.
668 */
669
670 int /* O - Port number */
671 ippPort(void)
672 {
673 _cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */
674
675
676 DEBUG_puts("ippPort()");
677
678 if (!cg->ipp_port)
679 _cupsSetDefaults();
680
681 DEBUG_printf(("1ippPort: Returning %d...", cg->ipp_port));
682
683 return (cg->ipp_port);
684 }
685
686
687 /*
688 * 'ippSetPort()' - Set the default port number.
689 */
690
691 void
692 ippSetPort(int p) /* I - Port number to use */
693 {
694 DEBUG_printf(("ippSetPort(p=%d)", p));
695
696 _cupsGlobals()->ipp_port = p;
697 }
698
699
700 /*
701 * 'ippTagString()' - Return the tag name corresponding to a tag value.
702 *
703 * The returned names are defined in RFC 2911 and 3382.
704 *
705 * @since CUPS 1.4/Mac OS X 10.6@
706 */
707
708 const char * /* O - Tag name */
709 ippTagString(ipp_tag_t tag) /* I - Tag value */
710 {
711 tag &= IPP_TAG_MASK;
712
713 if (tag < (ipp_tag_t)(sizeof(ipp_tag_names) / sizeof(ipp_tag_names[0])))
714 return (ipp_tag_names[tag]);
715 else
716 return ("UNKNOWN");
717 }
718
719
720 /*
721 * 'ippTagValue()' - Return the tag value corresponding to a tag name.
722 *
723 * The tag names are defined in RFC 2911 and 3382.
724 *
725 * @since CUPS 1.4/Mac OS X 10.6@
726 */
727
728 ipp_tag_t /* O - Tag value */
729 ippTagValue(const char *name) /* I - Tag name */
730 {
731 int i; /* Looping var */
732
733
734 for (i = 0; i < (sizeof(ipp_tag_names) / sizeof(ipp_tag_names[0])); i ++)
735 if (!strcasecmp(name, ipp_tag_names[i]))
736 return ((ipp_tag_t)i);
737
738 if (!strcasecmp(name, "operation"))
739 return (IPP_TAG_OPERATION);
740 else if (!strcasecmp(name, "job"))
741 return (IPP_TAG_JOB);
742 else if (!strcasecmp(name, "printer"))
743 return (IPP_TAG_PRINTER);
744 else if (!strcasecmp(name, "unsupported"))
745 return (IPP_TAG_UNSUPPORTED_GROUP);
746 else if (!strcasecmp(name, "subscription"))
747 return (IPP_TAG_SUBSCRIPTION);
748 else if (!strcasecmp(name, "event"))
749 return (IPP_TAG_EVENT_NOTIFICATION);
750 else if (!strcasecmp(name, "language"))
751 return (IPP_TAG_LANGUAGE);
752 else if (!strcasecmp(name, "mimetype"))
753 return (IPP_TAG_MIMETYPE);
754 else if (!strcasecmp(name, "name"))
755 return (IPP_TAG_NAME);
756 else if (!strcasecmp(name, "text"))
757 return (IPP_TAG_TEXT);
758 else if (!strcasecmp(name, "begCollection"))
759 return (IPP_TAG_BEGIN_COLLECTION);
760 else
761 return (IPP_TAG_ZERO);
762 }
763
764
765 /*
766 * End of "$Id: ipp-support.c 7847 2008-08-19 04:22:14Z mike $".
767 */