]> git.ipfire.org Git - thirdparty/cups.git/blob - cups/ipp-support.c
b22b4727be7b53ca59b66a2ee5d4c26669f54bb3
[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 * _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 "0x00",
104 "0x01",
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 "0x0f",
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 "0x1e",
136 "0x1f",
137
138 /* 0x0020 - 0x002f */
139 "0x20",
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 "0x32",
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 "Identify-Printer"
170 },
171 * const ipp_cups_ops[] =
172 {
173 "CUPS-Get-Default",
174 "CUPS-Get-Printers",
175 "CUPS-Add-Modify-Printer",
176 "CUPS-Delete-Printer",
177 "CUPS-Get-Classes",
178 "CUPS-Add-Modify-Class",
179 "CUPS-Delete-Class",
180 "CUPS-Accept-Jobs",
181 "CUPS-Reject-Jobs",
182 "CUPS-Set-Default",
183 "CUPS-Get-Devices",
184 "CUPS-Get-PPDs",
185 "CUPS-Move-Job",
186 "CUPS-Authenticate-Job",
187 "CUPS-Get-PPD"
188 },
189 * const ipp_cups_ops2[] =
190 {
191 "CUPS-Get-Document"
192 },
193 * const ipp_tag_names[] =
194 { /* Value/group tag names */
195 "zero", /* 0x00 */
196 "operation-attributes-tag",
197 /* 0x01 */
198 "job-attributes-tag", /* 0x02 */
199 "end-of-attributes-tag",
200 /* 0x03 */
201 "printer-attributes-tag",
202 /* 0x04 */
203 "unsupported-attributes-tag",
204 /* 0x05 */
205 "subscription-attributes-tag",
206 /* 0x06 */
207 "event-notification-attributes-tag",
208 /* 0x07 */
209 "0x08", /* 0x08 */
210 "document-attributes-tag",
211 /* 0x09 */
212 "0x0a", /* 0x0a */
213 "0x0b", /* 0x0b */
214 "0x0c", /* 0x0c */
215 "0x0d", /* 0x0d */
216 "0x0e", /* 0x0e */
217 "0x0f", /* 0x0f */
218 "unsupported", /* 0x10 */
219 "default", /* 0x11 */
220 "unknown", /* 0x12 */
221 "no-value", /* 0x13 */
222 "0x14", /* 0x14 */
223 "not-settable", /* 0x15 */
224 "delete-attribute", /* 0x16 */
225 "admin-define", /* 0x17 */
226 "0x18", /* 0x18 */
227 "0x19", /* 0x19 */
228 "0x1a", /* 0x1a */
229 "0x1b", /* 0x1b */
230 "0x1c", /* 0x1c */
231 "0x1d", /* 0x1d */
232 "0x1e", /* 0x1e */
233 "0x1f", /* 0x1f */
234 "0x20", /* 0x20 */
235 "integer", /* 0x21 */
236 "boolean", /* 0x22 */
237 "enum", /* 0x23 */
238 "0x24", /* 0x24 */
239 "0x25", /* 0x25 */
240 "0x26", /* 0x26 */
241 "0x27", /* 0x27 */
242 "0x28", /* 0x28 */
243 "0x29", /* 0x29 */
244 "0x2a", /* 0x2a */
245 "0x2b", /* 0x2b */
246 "0x2c", /* 0x2c */
247 "0x2d", /* 0x2d */
248 "0x2e", /* 0x2e */
249 "0x2f", /* 0x2f */
250 "octetString", /* 0x30 */
251 "dateTime", /* 0x31 */
252 "resolution", /* 0x32 */
253 "rangeOfInteger", /* 0x33 */
254 "collection", /* 0x34 */
255 "textWithLanguage", /* 0x35 */
256 "nameWithLanguage", /* 0x36 */
257 "endCollection", /* 0x37 */
258 "0x38", /* 0x38 */
259 "0x39", /* 0x39 */
260 "0x3a", /* 0x3a */
261 "0x3b", /* 0x3b */
262 "0x3c", /* 0x3c */
263 "0x3d", /* 0x3d */
264 "0x3e", /* 0x3e */
265 "0x3f", /* 0x3f */
266 "0x40", /* 0x40 */
267 "textWithoutLanguage",/* 0x41 */
268 "nameWithoutLanguage",/* 0x42 */
269 "0x43", /* 0x43 */
270 "keyword", /* 0x44 */
271 "uri", /* 0x45 */
272 "uriScheme", /* 0x46 */
273 "charset", /* 0x47 */
274 "naturalLanguage", /* 0x48 */
275 "mimeMediaType", /* 0x49 */
276 "memberAttrName" /* 0x4a */
277 };
278 static const char * const job_states[] =
279 { /* job-state enums */
280 "pending",
281 "pending-held",
282 "processing",
283 "processing-stopped",
284 "canceled",
285 "aborted",
286 "completed"
287 };
288 static const char * const printer_states[] =
289 { /* printer-state enums */
290 "idle",
291 "processing",
292 "stopped",
293 };
294
295
296 /*
297 * Local functions...
298 */
299
300 static size_t ipp_col_string(ipp_t *col, char *buffer, size_t bufsize);
301
302
303 /*
304 * '_ippAttrString()' - Convert the attribute's value to a string.
305 *
306 * Returns the number of bytes that would be written, not including the
307 * trailing nul. The buffer pointer can be NULL to get the required length,
308 * just like (v)snprintf.
309 */
310
311 size_t /* O - Number of bytes less nul */
312 _ippAttrString(ipp_attribute_t *attr, /* I - Attribute */
313 char *buffer, /* I - String buffer or NULL */
314 size_t bufsize) /* I - Size of string buffer */
315 {
316 int i; /* Looping var */
317 char *bufptr, /* Pointer into buffer */
318 *bufend, /* End of buffer */
319 temp[256]; /* Temporary string */
320 const char *ptr; /* Pointer into string */
321 ipp_value_t *val; /* Current value */
322
323
324 if (!attr || !attr->name)
325 {
326 if (buffer)
327 *buffer = '\0';
328
329 return (0);
330 }
331
332 bufptr = buffer;
333 if (buffer)
334 bufend = buffer + bufsize - 1;
335 else
336 bufend = NULL;
337
338 for (i = attr->num_values, val = attr->values; i > 0; i --, val ++)
339 {
340 if (val > attr->values)
341 {
342 if (buffer && bufptr < bufend)
343 *bufptr++ = ',';
344 else
345 bufptr ++;
346 }
347
348 switch (attr->value_tag & ~IPP_TAG_COPY)
349 {
350 case IPP_TAG_ENUM :
351 if (!strcmp(attr->name, "printer-state") &&
352 val->integer >= IPP_PRINTER_IDLE &&
353 val->integer <= IPP_PRINTER_STOPPED)
354 {
355 ptr = printer_states[val->integer - IPP_PRINTER_IDLE];
356
357 if (buffer && bufptr < bufend)
358 strlcpy(bufptr, ptr, bufend - bufptr + 1);
359
360 bufptr += strlen(ptr);
361 break;
362 }
363 else if (!strcmp(attr->name, "job-state") &&
364 val->integer >= IPP_JOB_PENDING &&
365 val->integer <= IPP_JOB_COMPLETED)
366 {
367 ptr = job_states[val->integer - IPP_JOB_PENDING];
368
369 if (buffer && bufptr < bufend)
370 strlcpy(bufptr, ptr, bufend - bufptr + 1);
371
372 bufptr += strlen(ptr);
373 break;
374 }
375 else if (!strcmp(attr->name, "operations-supported"))
376 {
377 ptr = ippOpString(val->integer);
378
379 if (buffer && bufptr < bufend)
380 strlcpy(bufptr, ptr, bufend - bufptr + 1);
381
382 bufptr += strlen(ptr);
383 break;
384 }
385
386 case IPP_TAG_INTEGER :
387 if (buffer && bufptr < bufend)
388 bufptr += snprintf(bufptr, bufend - bufptr + 1, "%d", val->integer);
389 else
390 bufptr += snprintf(temp, sizeof(temp), "%d", val->integer);
391 break;
392
393 case IPP_TAG_BOOLEAN :
394 if (buffer && bufptr < bufend)
395 strlcpy(bufptr, val->boolean ? "true" : "false",
396 bufend - bufptr + 1);
397
398 bufptr += val->boolean ? 4 : 5;
399 break;
400
401 case IPP_TAG_RANGE :
402 if (buffer && bufptr < bufend)
403 bufptr += snprintf(bufptr, bufend - bufptr + 1, "%d-%d",
404 val->range.lower, val->range.upper);
405 else
406 bufptr += snprintf(temp, sizeof(temp), "%d-%d", val->range.lower,
407 val->range.upper);
408 break;
409
410 case IPP_TAG_RESOLUTION :
411 if (buffer && bufptr < bufend)
412 bufptr += snprintf(bufptr, bufend - bufptr + 1, "%dx%d%s",
413 val->resolution.xres, val->resolution.yres,
414 val->resolution.units == IPP_RES_PER_INCH ?
415 "dpi" : "dpc");
416 else
417 bufptr += snprintf(temp, sizeof(temp), "%dx%d%s",
418 val->resolution.xres, val->resolution.yres,
419 val->resolution.units == IPP_RES_PER_INCH ?
420 "dpi" : "dpc");
421 break;
422
423 case IPP_TAG_DATE :
424 {
425 unsigned year; /* Year */
426
427 year = (val->date[0] << 8) + val->date[1];
428
429 if (val->date[9] == 0 && val->date[10] == 0)
430 snprintf(temp, sizeof(temp), "%04u-%02u-%02uT%02u:%02u:%02uZ",
431 year, val->date[2], val->date[3], val->date[4],
432 val->date[5], val->date[6]);
433 else
434 snprintf(temp, sizeof(temp),
435 "%04u-%02u-%02uT%02u:%02u:%02u%c%02u%02u",
436 year, val->date[2], val->date[3], val->date[4],
437 val->date[5], val->date[6], val->date[8], val->date[9],
438 val->date[10]);
439
440 if (buffer && bufptr < bufend)
441 strlcpy(bufptr, temp, bufend - bufptr + 1);
442
443 bufptr += strlen(temp);
444 }
445 break;
446
447 case IPP_TAG_TEXT :
448 case IPP_TAG_NAME :
449 case IPP_TAG_KEYWORD :
450 case IPP_TAG_CHARSET :
451 case IPP_TAG_URI :
452 case IPP_TAG_URISCHEME :
453 case IPP_TAG_MIMETYPE :
454 case IPP_TAG_LANGUAGE :
455 case IPP_TAG_TEXTLANG :
456 case IPP_TAG_NAMELANG :
457 if (!val->string.text)
458 break;
459
460 for (ptr = val->string.text; *ptr; ptr ++)
461 {
462 if (*ptr == '\\' || *ptr == '\"')
463 {
464 if (buffer && bufptr < bufend)
465 *bufptr = '\\';
466 bufptr ++;
467 }
468
469 if (buffer && bufptr < bufend)
470 *bufptr = *ptr;
471 bufptr ++;
472 }
473 break;
474
475 case IPP_TAG_BEGIN_COLLECTION :
476 if (buffer && bufptr < bufend)
477 bufptr += ipp_col_string(val->collection, bufptr,
478 bufend - bufptr + 1);
479 else
480 bufptr += ipp_col_string(val->collection, NULL, 0);
481 break;
482
483 case IPP_TAG_STRING :
484 for (ptr = val->string.text; *ptr; ptr ++)
485 {
486 if (*ptr == '\\' || _cups_isspace(*ptr))
487 {
488 if (buffer && bufptr < bufend)
489 *bufptr = '\\';
490 bufptr ++;
491
492 if (buffer && bufptr < bufend)
493 *bufptr = *ptr;
494 bufptr ++;
495 }
496 else if (!isprint(*ptr & 255))
497 {
498 if (buffer && bufptr < bufend)
499 bufptr += snprintf(bufptr, bufend - bufptr + 1, "\\%03o",
500 *ptr & 255);
501 else
502 bufptr += snprintf(temp, sizeof(temp), "\\%03o",
503 *ptr & 255);
504 }
505 else
506 {
507 if (buffer && bufptr < bufend)
508 *bufptr = *ptr;
509 bufptr ++;
510 }
511 }
512 break;
513
514 default :
515 ptr = ippTagString(attr->value_tag);
516 if (buffer && bufptr < bufend)
517 strlcpy(bufptr, ptr, bufend - bufptr + 1);
518 bufptr += strlen(ptr);
519 break;
520 }
521 }
522
523 if (buffer && bufptr < bufend)
524 *bufptr = '\0';
525 else if (bufend)
526 *bufend = '\0';
527
528 return (bufptr - buffer);
529 }
530
531
532 /*
533 * 'ippErrorString()' - Return a name for the given status code.
534 */
535
536 const char * /* O - Text string */
537 ippErrorString(ipp_status_t error) /* I - Error status */
538 {
539 _cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */
540
541
542 /*
543 * See if the error code is a known value...
544 */
545
546 if (error >= IPP_OK && error <= IPP_OK_EVENTS_COMPLETE)
547 return (ipp_status_oks[error]);
548 else if (error == IPP_REDIRECTION_OTHER_SITE)
549 return ("redirection-other-site");
550 else if (error == CUPS_SEE_OTHER)
551 return ("cups-see-other");
552 else if (error >= IPP_BAD_REQUEST && error <= IPP_PRINT_SUPPORT_FILE_NOT_FOUND)
553 return (ipp_status_400s[error - IPP_BAD_REQUEST]);
554 else if (error >= IPP_INTERNAL_ERROR && error <= IPP_PRINTER_IS_DEACTIVATED)
555 return (ipp_status_500s[error - IPP_INTERNAL_ERROR]);
556 else if (error >= IPP_AUTHENTICATION_CANCELED && error <= IPP_UPGRADE_REQUIRED)
557 return (ipp_status_1000s[error - IPP_AUTHENTICATION_CANCELED]);
558
559 /*
560 * No, build an "0xxxxx" error string...
561 */
562
563 sprintf(cg->ipp_unknown, "0x%04x", error);
564
565 return (cg->ipp_unknown);
566 }
567
568
569 /*
570 * 'ippErrorValue()' - Return a status code for the given name.
571 *
572 * @since CUPS 1.2/Mac OS X 10.5@
573 */
574
575 ipp_status_t /* O - IPP status code */
576 ippErrorValue(const char *name) /* I - Name */
577 {
578 int i;
579
580
581 for (i = 0; i < (sizeof(ipp_status_oks) / sizeof(ipp_status_oks[0])); i ++)
582 if (!_cups_strcasecmp(name, ipp_status_oks[i]))
583 return ((ipp_status_t)i);
584
585 if (!_cups_strcasecmp(name, "redirection-other-site"))
586 return (IPP_REDIRECTION_OTHER_SITE);
587
588 if (!_cups_strcasecmp(name, "cups-see-other"))
589 return (CUPS_SEE_OTHER);
590
591 for (i = 0; i < (sizeof(ipp_status_400s) / sizeof(ipp_status_400s[0])); i ++)
592 if (!_cups_strcasecmp(name, ipp_status_400s[i]))
593 return ((ipp_status_t)(i + 0x400));
594
595 for (i = 0; i < (sizeof(ipp_status_500s) / sizeof(ipp_status_500s[0])); i ++)
596 if (!_cups_strcasecmp(name, ipp_status_500s[i]))
597 return ((ipp_status_t)(i + 0x500));
598
599 for (i = 0; i < (sizeof(ipp_status_1000s) / sizeof(ipp_status_1000s[0])); i ++)
600 if (!_cups_strcasecmp(name, ipp_status_1000s[i]))
601 return ((ipp_status_t)(i + 0x1000));
602
603 return ((ipp_status_t)-1);
604 }
605
606
607 /*
608 * 'ippOpString()' - Return a name for the given operation id.
609 *
610 * @since CUPS 1.2/Mac OS X 10.5@
611 */
612
613 const char * /* O - Name */
614 ippOpString(ipp_op_t op) /* I - Operation ID */
615 {
616 _cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */
617
618
619 /*
620 * See if the operation ID is a known value...
621 */
622
623 if (op >= IPP_PRINT_JOB && op <= IPP_CLOSE_JOB)
624 return (ipp_std_ops[op]);
625 else if (op == IPP_PRIVATE)
626 return ("windows-ext");
627 else if (op >= CUPS_GET_DEFAULT && op <= CUPS_GET_PPD)
628 return (ipp_cups_ops[op - CUPS_GET_DEFAULT]);
629 else if (op == CUPS_GET_DOCUMENT)
630 return (ipp_cups_ops2[0]);
631
632 /*
633 * No, build an "0xxxxx" operation string...
634 */
635
636 sprintf(cg->ipp_unknown, "0x%04x", op);
637
638 return (cg->ipp_unknown);
639 }
640
641
642 /*
643 * 'ippOpValue()' - Return an operation id for the given name.
644 *
645 * @since CUPS 1.2/Mac OS X 10.5@
646 */
647
648 ipp_op_t /* O - Operation ID */
649 ippOpValue(const char *name) /* I - Textual name */
650 {
651 int i;
652
653
654 if (!strncmp(name, "0x", 2))
655 return ((ipp_op_t)strtol(name + 2, NULL, 16));
656
657 for (i = 0; i < (sizeof(ipp_std_ops) / sizeof(ipp_std_ops[0])); i ++)
658 if (!_cups_strcasecmp(name, ipp_std_ops[i]))
659 return ((ipp_op_t)i);
660
661 if (!_cups_strcasecmp(name, "windows-ext"))
662 return (IPP_PRIVATE);
663
664 for (i = 0; i < (sizeof(ipp_cups_ops) / sizeof(ipp_cups_ops[0])); i ++)
665 if (!_cups_strcasecmp(name, ipp_cups_ops[i]))
666 return ((ipp_op_t)(i + 0x4001));
667
668 for (i = 0; i < (sizeof(ipp_cups_ops2) / sizeof(ipp_cups_ops2[0])); i ++)
669 if (!_cups_strcasecmp(name, ipp_cups_ops2[i]))
670 return ((ipp_op_t)(i + 0x4027));
671
672 if (!_cups_strcasecmp(name, "CUPS-Add-Class"))
673 return (CUPS_ADD_MODIFY_CLASS);
674
675 if (!_cups_strcasecmp(name, "CUPS-Add-Printer"))
676 return (CUPS_ADD_MODIFY_PRINTER);
677
678 return ((ipp_op_t)-1);
679 }
680
681
682 /*
683 * 'ippPort()' - Return the default IPP port number.
684 */
685
686 int /* O - Port number */
687 ippPort(void)
688 {
689 _cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */
690
691
692 DEBUG_puts("ippPort()");
693
694 if (!cg->ipp_port)
695 _cupsSetDefaults();
696
697 DEBUG_printf(("1ippPort: Returning %d...", cg->ipp_port));
698
699 return (cg->ipp_port);
700 }
701
702
703 /*
704 * 'ippSetPort()' - Set the default port number.
705 */
706
707 void
708 ippSetPort(int p) /* I - Port number to use */
709 {
710 DEBUG_printf(("ippSetPort(p=%d)", p));
711
712 _cupsGlobals()->ipp_port = p;
713 }
714
715
716 /*
717 * 'ippTagString()' - Return the tag name corresponding to a tag value.
718 *
719 * The returned names are defined in RFC 2911 and 3382.
720 *
721 * @since CUPS 1.4/Mac OS X 10.6@
722 */
723
724 const char * /* O - Tag name */
725 ippTagString(ipp_tag_t tag) /* I - Tag value */
726 {
727 tag &= IPP_TAG_MASK;
728
729 if (tag < (ipp_tag_t)(sizeof(ipp_tag_names) / sizeof(ipp_tag_names[0])))
730 return (ipp_tag_names[tag]);
731 else
732 return ("UNKNOWN");
733 }
734
735
736 /*
737 * 'ippTagValue()' - Return the tag value corresponding to a tag name.
738 *
739 * The tag names are defined in RFC 2911 and 3382.
740 *
741 * @since CUPS 1.4/Mac OS X 10.6@
742 */
743
744 ipp_tag_t /* O - Tag value */
745 ippTagValue(const char *name) /* I - Tag name */
746 {
747 int i; /* Looping var */
748
749
750 for (i = 0; i < (sizeof(ipp_tag_names) / sizeof(ipp_tag_names[0])); i ++)
751 if (!_cups_strcasecmp(name, ipp_tag_names[i]))
752 return ((ipp_tag_t)i);
753
754 if (!_cups_strcasecmp(name, "operation"))
755 return (IPP_TAG_OPERATION);
756 else if (!_cups_strcasecmp(name, "job"))
757 return (IPP_TAG_JOB);
758 else if (!_cups_strcasecmp(name, "printer"))
759 return (IPP_TAG_PRINTER);
760 else if (!_cups_strcasecmp(name, "unsupported"))
761 return (IPP_TAG_UNSUPPORTED_GROUP);
762 else if (!_cups_strcasecmp(name, "subscription"))
763 return (IPP_TAG_SUBSCRIPTION);
764 else if (!_cups_strcasecmp(name, "event"))
765 return (IPP_TAG_EVENT_NOTIFICATION);
766 else if (!_cups_strcasecmp(name, "language"))
767 return (IPP_TAG_LANGUAGE);
768 else if (!_cups_strcasecmp(name, "mimetype"))
769 return (IPP_TAG_MIMETYPE);
770 else if (!_cups_strcasecmp(name, "name"))
771 return (IPP_TAG_NAME);
772 else if (!_cups_strcasecmp(name, "text"))
773 return (IPP_TAG_TEXT);
774 else if (!_cups_strcasecmp(name, "begCollection"))
775 return (IPP_TAG_BEGIN_COLLECTION);
776 else
777 return (IPP_TAG_ZERO);
778 }
779
780
781 /*
782 * 'ipp_col_string()' - Convert a collection to a string.
783 */
784
785 static size_t /* O - Number of bytes */
786 ipp_col_string(ipp_t *col, /* I - Collection attribute */
787 char *buffer, /* I - Buffer or NULL */
788 size_t bufsize) /* I - Size of buffer */
789 {
790 char *bufptr, /* Position in buffer */
791 *bufend, /* End of buffer */
792 temp[256]; /* Temporary string */
793 ipp_attribute_t *attr; /* Current member attribute */
794
795
796 bufptr = buffer;
797 bufend = buffer + bufsize - 1;
798
799 if (buffer && bufptr < bufend)
800 *bufptr = '{';
801 bufptr ++;
802
803 for (attr = col->attrs; attr; attr = attr->next)
804 {
805 if (!attr->name)
806 continue;
807
808 if (buffer && bufptr < bufend)
809 bufptr += snprintf(bufptr, bufend - bufptr + 1, "%s=", attr->name);
810 else
811 bufptr += strlen(attr->name) + 1;
812
813 if (buffer && bufptr < bufend)
814 bufptr += _ippAttrString(attr, bufptr, bufend - bufptr + 1);
815 else
816 bufptr += _ippAttrString(attr, temp, sizeof(temp));
817 }
818
819 if (buffer && bufptr < bufend)
820 *bufptr = '}';
821 bufptr ++;
822
823 return (bufptr - buffer);
824 }
825
826
827 /*
828 * End of "$Id: ipp-support.c 9371 2010-11-17 06:21:32Z mike $".
829 */