]> git.ipfire.org Git - thirdparty/cups.git/blob - cups/testipp.c
Merge changes from CUPS 1.5svn-r9105.
[thirdparty/cups.git] / cups / testipp.c
1 /*
2 * "$Id: testipp.c 6649 2007-07-11 21:46:42Z mike $"
3 *
4 * IPP test program for CUPS.
5 *
6 * Copyright 2007-2010 by Apple Inc.
7 * Copyright 1997-2005 by Easy Software Products.
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 * main() - Main entry.
20 * hex_dump() - Produce a hex dump of a buffer.
21 * print_attributes() - Print the attributes in a request...
22 * read_cb() - Read data from a buffer.
23 * write_cb() - Write data into a buffer.
24 */
25
26 /*
27 * Include necessary headers...
28 */
29
30 #include "file.h"
31 #include "string-private.h"
32 #include "ipp-private.h"
33 #ifdef WIN32
34 # include <io.h>
35 #else
36 # include <unistd.h>
37 # include <fcntl.h>
38 #endif /* WIN32 */
39
40
41 /*
42 * Local globals...
43 */
44
45 int rpos; /* Current position in buffer */
46 ipp_uchar_t wbuffer[8192]; /* Write buffer */
47 int wused; /* Number of bytes in buffer */
48 ipp_uchar_t collection[] = /* Collection buffer */
49 {
50 0x01, 0x01, /* IPP version */
51 0x00, 0x02, /* Print-Job operation */
52 0x00, 0x00, 0x00, 0x01, /* Request ID */
53
54 IPP_TAG_OPERATION,
55
56 IPP_TAG_CHARSET,
57 0x00, 0x12, /* Name length + name */
58 'a','t','t','r','i','b','u','t','e','s','-',
59 'c','h','a','r','s','e','t',
60 0x00, 0x05, /* Value length + value */
61 'u','t','f','-','8',
62
63 IPP_TAG_LANGUAGE,
64 0x00, 0x1b, /* Name length + name */
65 'a','t','t','r','i','b','u','t','e','s','-',
66 'n','a','t','u','r','a','l','-','l','a','n',
67 'g','u','a','g','e',
68 0x00, 0x02, /* Value length + value */
69 'e','n',
70
71 IPP_TAG_URI,
72 0x00, 0x0b, /* Name length + name */
73 'p','r','i','n','t','e','r','-','u','r','i',
74 0x00, 0x1c, /* Value length + value */
75 'i','p','p',':','/','/','l','o','c','a','l',
76 'h','o','s','t','/','p','r','i','n','t','e',
77 'r','s','/','f','o','o',
78
79 IPP_TAG_JOB, /* job group tag */
80
81 IPP_TAG_BEGIN_COLLECTION, /* begCollection tag */
82 0x00, 0x09, /* Name length + name */
83 'm', 'e', 'd', 'i', 'a', '-', 'c', 'o', 'l',
84 0x00, 0x00, /* No value */
85 IPP_TAG_MEMBERNAME, /* memberAttrName tag */
86 0x00, 0x00, /* No name */
87 0x00, 0x0a, /* Value length + value */
88 'm', 'e', 'd', 'i', 'a', '-', 's', 'i', 'z', 'e',
89 IPP_TAG_BEGIN_COLLECTION, /* begCollection tag */
90 0x00, 0x00, /* Name length + name */
91 0x00, 0x00, /* No value */
92 IPP_TAG_MEMBERNAME, /* memberAttrName tag */
93 0x00, 0x00, /* No name */
94 0x00, 0x0b, /* Value length + value */
95 'x', '-', 'd', 'i', 'm', 'e', 'n', 's', 'i', 'o', 'n',
96 IPP_TAG_INTEGER, /* integer tag */
97 0x00, 0x00, /* No name */
98 0x00, 0x04, /* Value length + value */
99 0x00, 0x00, 0x54, 0x56,
100 IPP_TAG_MEMBERNAME, /* memberAttrName tag */
101 0x00, 0x00, /* No name */
102 0x00, 0x0b, /* Value length + value */
103 'y', '-', 'd', 'i', 'm', 'e', 'n', 's', 'i', 'o', 'n',
104 IPP_TAG_INTEGER, /* integer tag */
105 0x00, 0x00, /* No name */
106 0x00, 0x04, /* Value length + value */
107 0x00, 0x00, 0x6d, 0x24,
108 IPP_TAG_END_COLLECTION, /* endCollection tag */
109 0x00, 0x00, /* No name */
110 0x00, 0x00, /* No value */
111 IPP_TAG_MEMBERNAME, /* memberAttrName tag */
112 0x00, 0x00, /* No name */
113 0x00, 0x0b, /* Value length + value */
114 'm', 'e', 'd', 'i', 'a', '-', 'c', 'o', 'l', 'o', 'r',
115 IPP_TAG_KEYWORD, /* keyword tag */
116 0x00, 0x00, /* No name */
117 0x00, 0x04, /* Value length + value */
118 'b', 'l', 'u', 'e',
119
120 IPP_TAG_MEMBERNAME, /* memberAttrName tag */
121 0x00, 0x00, /* No name */
122 0x00, 0x0a, /* Value length + value */
123 'm', 'e', 'd', 'i', 'a', '-', 't', 'y', 'p', 'e',
124 IPP_TAG_KEYWORD, /* keyword tag */
125 0x00, 0x00, /* No name */
126 0x00, 0x05, /* Value length + value */
127 'p', 'l', 'a', 'i', 'n',
128 IPP_TAG_END_COLLECTION, /* endCollection tag */
129 0x00, 0x00, /* No name */
130 0x00, 0x00, /* No value */
131
132 IPP_TAG_BEGIN_COLLECTION, /* begCollection tag */
133 0x00, 0x00, /* No name */
134 0x00, 0x00, /* No value */
135 IPP_TAG_MEMBERNAME, /* memberAttrName tag */
136 0x00, 0x00, /* No name */
137 0x00, 0x0a, /* Value length + value */
138 'm', 'e', 'd', 'i', 'a', '-', 's', 'i', 'z', 'e',
139 IPP_TAG_BEGIN_COLLECTION, /* begCollection tag */
140 0x00, 0x00, /* Name length + name */
141 0x00, 0x00, /* No value */
142 IPP_TAG_MEMBERNAME, /* memberAttrName tag */
143 0x00, 0x00, /* No name */
144 0x00, 0x0b, /* Value length + value */
145 'x', '-', 'd', 'i', 'm', 'e', 'n', 's', 'i', 'o', 'n',
146 IPP_TAG_INTEGER, /* integer tag */
147 0x00, 0x00, /* No name */
148 0x00, 0x04, /* Value length + value */
149 0x00, 0x00, 0x52, 0x08,
150 IPP_TAG_MEMBERNAME, /* memberAttrName tag */
151 0x00, 0x00, /* No name */
152 0x00, 0x0b, /* Value length + value */
153 'y', '-', 'd', 'i', 'm', 'e', 'n', 's', 'i', 'o', 'n',
154 IPP_TAG_INTEGER, /* integer tag */
155 0x00, 0x00, /* No name */
156 0x00, 0x04, /* Value length + value */
157 0x00, 0x00, 0x74, 0x04,
158 IPP_TAG_END_COLLECTION, /* endCollection tag */
159 0x00, 0x00, /* No name */
160 0x00, 0x00, /* No value */
161 IPP_TAG_MEMBERNAME, /* memberAttrName tag */
162 0x00, 0x00, /* No name */
163 0x00, 0x0b, /* Value length + value */
164 'm', 'e', 'd', 'i', 'a', '-', 'c', 'o', 'l', 'o', 'r',
165 IPP_TAG_KEYWORD, /* keyword tag */
166 0x00, 0x00, /* No name */
167 0x00, 0x05, /* Value length + value */
168 'p', 'l', 'a', 'i', 'd',
169
170 IPP_TAG_MEMBERNAME, /* memberAttrName tag */
171 0x00, 0x00, /* No name */
172 0x00, 0x0a, /* Value length + value */
173 'm', 'e', 'd', 'i', 'a', '-', 't', 'y', 'p', 'e',
174 IPP_TAG_KEYWORD, /* keyword tag */
175 0x00, 0x00, /* No name */
176 0x00, 0x06, /* Value length + value */
177 'g', 'l', 'o', 's', 's', 'y',
178 IPP_TAG_END_COLLECTION, /* endCollection tag */
179 0x00, 0x00, /* No name */
180 0x00, 0x00, /* No value */
181
182 IPP_TAG_END /* end tag */
183 };
184
185
186 /*
187 * Local functions...
188 */
189
190 void hex_dump(const char *title, ipp_uchar_t *buffer, int bytes);
191 void print_attributes(ipp_t *ipp, int indent);
192 ssize_t read_cb(void *data, ipp_uchar_t *buffer, size_t bytes);
193 ssize_t write_cb(void *data, ipp_uchar_t *buffer, size_t bytes);
194
195
196 /*
197 * 'main()' - Main entry.
198 */
199
200 int /* O - Exit status */
201 main(int argc, /* I - Number of command-line arguments */
202 char *argv[]) /* I - Command-line arguments */
203 {
204 ipp_t *cols[2], /* Collections */
205 *size; /* media-size collection */
206 ipp_t *request; /* Request */
207 ipp_attribute_t *media_col, /* media-col attribute */
208 *media_size, /* media-size attribute */
209 *attr; /* Other attribute */
210 ipp_state_t state; /* State */
211 int length; /* Length of data */
212 cups_file_t *fp; /* File pointer */
213 int i; /* Looping var */
214 int status; /* Status of tests (0 = success, 1 = fail) */
215
216
217 status = 0;
218
219 if (argc == 1)
220 {
221 /*
222 * Test request generation code...
223 */
224
225 printf("Create Sample Request: ");
226
227 request = ippNew();
228 request->request.op.version[0] = 0x01;
229 request->request.op.version[1] = 0x01;
230 request->request.op.operation_id = IPP_PRINT_JOB;
231 request->request.op.request_id = 1;
232
233 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
234 "attributes-charset", NULL, "utf-8");
235 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
236 "attributes-natural-language", NULL, "en");
237 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
238 "printer-uri", NULL, "ipp://localhost/printers/foo");
239
240 cols[0] = ippNew();
241 size = ippNew();
242 ippAddInteger(size, IPP_TAG_ZERO, IPP_TAG_INTEGER, "x-dimension", 21590);
243 ippAddInteger(size, IPP_TAG_ZERO, IPP_TAG_INTEGER, "y-dimension", 27940);
244 ippAddCollection(cols[0], IPP_TAG_JOB, "media-size", size);
245 ippDelete(size);
246 ippAddString(cols[0], IPP_TAG_JOB, IPP_TAG_KEYWORD, "media-color", NULL,
247 "blue");
248 ippAddString(cols[0], IPP_TAG_JOB, IPP_TAG_KEYWORD, "media-type", NULL,
249 "plain");
250
251 cols[1] = ippNew();
252 size = ippNew();
253 ippAddInteger(size, IPP_TAG_ZERO, IPP_TAG_INTEGER, "x-dimension", 21000);
254 ippAddInteger(size, IPP_TAG_ZERO, IPP_TAG_INTEGER, "y-dimension", 29700);
255 ippAddCollection(cols[1], IPP_TAG_JOB, "media-size", size);
256 ippDelete(size);
257 ippAddString(cols[1], IPP_TAG_JOB, IPP_TAG_KEYWORD, "media-color", NULL,
258 "plaid");
259 ippAddString(cols[1], IPP_TAG_JOB, IPP_TAG_KEYWORD, "media-type", NULL,
260 "glossy");
261
262 ippAddCollections(request, IPP_TAG_JOB, "media-col", 2,
263 (const ipp_t **)cols);
264 ippDelete(cols[0]);
265 ippDelete(cols[1]);
266
267 length = ippLength(request);
268 if (length != sizeof(collection))
269 {
270 printf("FAIL - wrong ippLength(), %d instead of %d bytes!\n",
271 length, (int)sizeof(collection));
272 status = 1;
273 }
274 else
275 puts("PASS");
276
277 /*
278 * Write test #1...
279 */
280
281 printf("Write Sample to Memory: ");
282
283 wused = 0;
284 while ((state = ippWriteIO(wbuffer, write_cb, 1, NULL,
285 request)) != IPP_DATA)
286 if (state == IPP_ERROR)
287 break;
288
289 if (state != IPP_DATA)
290 {
291 printf("FAIL - %d bytes written.\n", wused);
292 status = 1;
293 }
294 else if (wused != sizeof(collection))
295 {
296 printf("FAIL - wrote %d bytes, expected %d bytes!\n", wused,
297 (int)sizeof(collection));
298 hex_dump("Bytes Written", wbuffer, wused);
299 hex_dump("Baseline", collection, sizeof(collection));
300 status = 1;
301 }
302 else if (memcmp(wbuffer, collection, wused))
303 {
304 for (i = 0; i < wused; i ++)
305 if (wbuffer[i] != collection[i])
306 break;
307
308 printf("FAIL - output does not match baseline at 0x%04x!\n", i);
309 hex_dump("Bytes Written", wbuffer, wused);
310 hex_dump("Baseline", collection, sizeof(collection));
311 status = 1;
312 }
313 else
314 puts("PASS");
315
316 ippDelete(request);
317
318 /*
319 * Read the data back in and confirm...
320 */
321
322 printf("Read Sample from Memory: ");
323
324 request = ippNew();
325 rpos = 0;
326
327 while ((state = ippReadIO(wbuffer, read_cb, 1, NULL, request)) != IPP_DATA)
328 if (state == IPP_ERROR)
329 break;
330
331 length = ippLength(request);
332
333 if (state != IPP_DATA)
334 {
335 printf("FAIL - %d bytes read.\n", rpos);
336 status = 1;
337 }
338 else if (rpos != wused)
339 {
340 printf("FAIL - read %d bytes, expected %d bytes!\n", rpos, wused);
341 print_attributes(request, 8);
342 status = 1;
343 }
344 else if (length != sizeof(collection))
345 {
346 printf("FAIL - wrong ippLength(), %d instead of %d bytes!\n",
347 length, (int)sizeof(collection));
348 print_attributes(request, 8);
349 status = 1;
350 }
351 else
352 puts("PASS");
353
354 fputs("ippFindAttribute(media-col): ", stdout);
355 if ((media_col = ippFindAttribute(request, "media-col",
356 IPP_TAG_BEGIN_COLLECTION)) == NULL)
357 {
358 if ((media_col = ippFindAttribute(request, "media-col",
359 IPP_TAG_ZERO)) == NULL)
360 puts("FAIL (not found)");
361 else
362 printf("FAIL (wrong type - %s)\n", ippTagString(media_col->value_tag));
363
364 status = 1;
365 }
366 else if (media_col->num_values != 2)
367 {
368 printf("FAIL (wrong count - %d)\n", media_col->num_values);
369 status = 1;
370 }
371 else
372 puts("PASS");
373
374 if (media_col)
375 {
376 fputs("ippFindAttribute(media-size 1): ", stdout);
377 if ((media_size = ippFindAttribute(media_col->values[0].collection,
378 "media-size",
379 IPP_TAG_BEGIN_COLLECTION)) == NULL)
380 {
381 if ((media_size = ippFindAttribute(media_col->values[0].collection,
382 "media-col",
383 IPP_TAG_ZERO)) == NULL)
384 puts("FAIL (not found)");
385 else
386 printf("FAIL (wrong type - %s)\n",
387 ippTagString(media_size->value_tag));
388
389 status = 1;
390 }
391 else
392 {
393 if ((attr = ippFindAttribute(media_size->values[0].collection,
394 "x-dimension", IPP_TAG_INTEGER)) == NULL)
395 {
396 if ((attr = ippFindAttribute(media_size->values[0].collection,
397 "x-dimension", IPP_TAG_ZERO)) == NULL)
398 puts("FAIL (missing x-dimension)");
399 else
400 printf("FAIL (wrong type for x-dimension - %s)\n",
401 ippTagString(attr->value_tag));
402
403 status = 1;
404 }
405 else if (attr->values[0].integer != 21590)
406 {
407 printf("FAIL (wrong value for x-dimension - %d)\n",
408 attr->values[0].integer);
409 status = 1;
410 }
411 else if ((attr = ippFindAttribute(media_size->values[0].collection,
412 "y-dimension",
413 IPP_TAG_INTEGER)) == NULL)
414 {
415 if ((attr = ippFindAttribute(media_size->values[0].collection,
416 "y-dimension", IPP_TAG_ZERO)) == NULL)
417 puts("FAIL (missing y-dimension)");
418 else
419 printf("FAIL (wrong type for y-dimension - %s)\n",
420 ippTagString(attr->value_tag));
421
422 status = 1;
423 }
424 else if (attr->values[0].integer != 27940)
425 {
426 printf("FAIL (wrong value for y-dimension - %d)\n",
427 attr->values[0].integer);
428 status = 1;
429 }
430 else
431 puts("PASS");
432 }
433
434 fputs("ippFindAttribute(media-size 2): ", stdout);
435 if ((media_size = ippFindAttribute(media_col->values[1].collection,
436 "media-size",
437 IPP_TAG_BEGIN_COLLECTION)) == NULL)
438 {
439 if ((media_size = ippFindAttribute(media_col->values[1].collection,
440 "media-col",
441 IPP_TAG_ZERO)) == NULL)
442 puts("FAIL (not found)");
443 else
444 printf("FAIL (wrong type - %s)\n",
445 ippTagString(media_size->value_tag));
446
447 status = 1;
448 }
449 else
450 {
451 if ((attr = ippFindAttribute(media_size->values[0].collection,
452 "x-dimension",
453 IPP_TAG_INTEGER)) == NULL)
454 {
455 if ((attr = ippFindAttribute(media_size->values[0].collection,
456 "x-dimension", IPP_TAG_ZERO)) == NULL)
457 puts("FAIL (missing x-dimension)");
458 else
459 printf("FAIL (wrong type for x-dimension - %s)\n",
460 ippTagString(attr->value_tag));
461
462 status = 1;
463 }
464 else if (attr->values[0].integer != 21000)
465 {
466 printf("FAIL (wrong value for x-dimension - %d)\n",
467 attr->values[0].integer);
468 status = 1;
469 }
470 else if ((attr = ippFindAttribute(media_size->values[0].collection,
471 "y-dimension",
472 IPP_TAG_INTEGER)) == NULL)
473 {
474 if ((attr = ippFindAttribute(media_size->values[0].collection,
475 "y-dimension", IPP_TAG_ZERO)) == NULL)
476 puts("FAIL (missing y-dimension)");
477 else
478 printf("FAIL (wrong type for y-dimension - %s)\n",
479 ippTagString(attr->value_tag));
480
481 status = 1;
482 }
483 else if (attr->values[0].integer != 29700)
484 {
485 printf("FAIL (wrong value for y-dimension - %d)\n",
486 attr->values[0].integer);
487 status = 1;
488 }
489 else
490 puts("PASS");
491 }
492 }
493
494 ippDelete(request);
495
496 /*
497 * Test _ippFindOption() private API...
498 */
499
500 fputs("_ippFindOption(printer-type): ", stdout);
501 if (_ippFindOption("printer-type"))
502 puts("PASS");
503 else
504 {
505 puts("FAIL");
506 status = 1;
507 }
508
509 /*
510 * Summarize...
511 */
512
513 putchar('\n');
514
515 if (status)
516 puts("Core IPP tests failed.");
517 else
518 puts("Core IPP tests passed.");
519 }
520 else
521 {
522 /*
523 * Read IPP files...
524 */
525
526 for (i = 1; i < argc; i ++)
527 {
528 if ((fp = cupsFileOpen(argv[i], "r")) == NULL)
529 {
530 printf("Unable to open \"%s\" - %s\n", argv[i], strerror(errno));
531 status = 1;
532 continue;
533 }
534
535 request = ippNew();
536 while ((state = ippReadIO(fp, (ipp_iocb_t)cupsFileRead, 1, NULL,
537 request)) == IPP_ATTRIBUTE);
538
539 if (state != IPP_DATA)
540 {
541 printf("Error reading IPP message from \"%s\"!\n", argv[i]);
542 status = 1;
543 }
544 else
545 {
546 printf("\n%s:\n", argv[i]);
547 print_attributes(request, 4);
548 }
549
550 ippDelete(request);
551 cupsFileClose(fp);
552 }
553 }
554
555 return (status);
556 }
557
558
559 /*
560 * 'hex_dump()' - Produce a hex dump of a buffer.
561 */
562
563 void
564 hex_dump(const char *title, /* I - Title */
565 ipp_uchar_t *buffer, /* I - Buffer to dump */
566 int bytes) /* I - Number of bytes */
567 {
568 int i, j; /* Looping vars */
569 int ch; /* Current ASCII char */
570
571
572 /*
573 * Show lines of 16 bytes at a time...
574 */
575
576 printf(" %s:\n", title);
577
578 for (i = 0; i < bytes; i += 16)
579 {
580 /*
581 * Show the offset...
582 */
583
584 printf(" %04x ", i);
585
586 /*
587 * Then up to 16 bytes in hex...
588 */
589
590 for (j = 0; j < 16; j ++)
591 if ((i + j) < bytes)
592 printf(" %02x", buffer[i + j]);
593 else
594 printf(" ");
595
596 /*
597 * Then the ASCII representation of the bytes...
598 */
599
600 putchar(' ');
601 putchar(' ');
602
603 for (j = 0; j < 16 && (i + j) < bytes; j ++)
604 {
605 ch = buffer[i + j] & 127;
606
607 if (ch < ' ' || ch == 127)
608 putchar('.');
609 else
610 putchar(ch);
611 }
612
613 putchar('\n');
614 }
615 }
616
617
618 /*
619 * 'print_attributes()' - Print the attributes in a request...
620 */
621
622 void
623 print_attributes(ipp_t *ipp, /* I - IPP request */
624 int indent) /* I - Indentation */
625 {
626 int i; /* Looping var */
627 ipp_tag_t group; /* Current group */
628 ipp_attribute_t *attr; /* Current attribute */
629 ipp_value_t *val; /* Current value */
630 static const char * const tags[] = /* Value/group tag strings */
631 {
632 "reserved-00",
633 "operation-attributes-tag",
634 "job-attributes-tag",
635 "end-of-attributes-tag",
636 "printer-attributes-tag",
637 "unsupported-attributes-tag",
638 "subscription-attributes-tag",
639 "event-attributes-tag",
640 "reserved-08",
641 "reserved-09",
642 "reserved-0A",
643 "reserved-0B",
644 "reserved-0C",
645 "reserved-0D",
646 "reserved-0E",
647 "reserved-0F",
648 "unsupported",
649 "default",
650 "unknown",
651 "no-value",
652 "reserved-14",
653 "not-settable",
654 "delete-attr",
655 "admin-define",
656 "reserved-18",
657 "reserved-19",
658 "reserved-1A",
659 "reserved-1B",
660 "reserved-1C",
661 "reserved-1D",
662 "reserved-1E",
663 "reserved-1F",
664 "reserved-20",
665 "integer",
666 "boolean",
667 "enum",
668 "reserved-24",
669 "reserved-25",
670 "reserved-26",
671 "reserved-27",
672 "reserved-28",
673 "reserved-29",
674 "reserved-2a",
675 "reserved-2b",
676 "reserved-2c",
677 "reserved-2d",
678 "reserved-2e",
679 "reserved-2f",
680 "octetString",
681 "dateTime",
682 "resolution",
683 "rangeOfInteger",
684 "begCollection",
685 "textWithLanguage",
686 "nameWithLanguage",
687 "endCollection",
688 "reserved-38",
689 "reserved-39",
690 "reserved-3a",
691 "reserved-3b",
692 "reserved-3c",
693 "reserved-3d",
694 "reserved-3e",
695 "reserved-3f",
696 "reserved-40",
697 "textWithoutLanguage",
698 "nameWithoutLanguage",
699 "reserved-43",
700 "keyword",
701 "uri",
702 "uriScheme",
703 "charset",
704 "naturalLanguage",
705 "mimeMediaType",
706 "memberName"
707 };
708
709
710 for (group = IPP_TAG_ZERO, attr = ipp->attrs; attr; attr = attr->next)
711 {
712 if (!attr->name && indent == 4)
713 {
714 group = IPP_TAG_ZERO;
715 putchar('\n');
716 continue;
717 }
718
719 if (group != attr->group_tag)
720 {
721 group = attr->group_tag;
722
723 printf("\n%*s%s:\n\n", indent - 4, "", tags[group]);
724 }
725
726 printf("%*s%s (", indent, "", attr->name ? attr->name : "(null)");
727 if (attr->num_values > 1)
728 printf("1setOf ");
729 printf("%s):", tags[attr->value_tag]);
730
731 switch (attr->value_tag)
732 {
733 case IPP_TAG_ENUM :
734 case IPP_TAG_INTEGER :
735 for (i = 0, val = attr->values; i < attr->num_values; i ++, val ++)
736 printf(" %d", val->integer);
737 putchar('\n');
738 break;
739
740 case IPP_TAG_BOOLEAN :
741 for (i = 0, val = attr->values; i < attr->num_values; i ++, val ++)
742 printf(" %s", val->boolean ? "true" : "false");
743 putchar('\n');
744 break;
745
746 case IPP_TAG_RANGE :
747 for (i = 0, val = attr->values; i < attr->num_values; i ++, val ++)
748 printf(" %d-%d", val->range.lower, val->range.upper);
749 putchar('\n');
750 break;
751
752 case IPP_TAG_DATE :
753 {
754 time_t vtime; /* Date/Time value */
755 struct tm *vdate; /* Date info */
756 char vstring[256]; /* Formatted time */
757
758 for (i = 0, val = attr->values; i < attr->num_values; i ++, val ++)
759 {
760 vtime = ippDateToTime(val->date);
761 vdate = localtime(&vtime);
762 strftime(vstring, sizeof(vstring), "%c", vdate);
763 printf(" (%s)", vstring);
764 }
765 }
766 putchar('\n');
767 break;
768
769 case IPP_TAG_RESOLUTION :
770 for (i = 0, val = attr->values; i < attr->num_values; i ++, val ++)
771 printf(" %dx%d%s", val->resolution.xres, val->resolution.yres,
772 val->resolution.units == IPP_RES_PER_INCH ? "dpi" : "dpc");
773 putchar('\n');
774 break;
775
776 case IPP_TAG_STRING :
777 case IPP_TAG_TEXTLANG :
778 case IPP_TAG_NAMELANG :
779 case IPP_TAG_TEXT :
780 case IPP_TAG_NAME :
781 case IPP_TAG_KEYWORD :
782 case IPP_TAG_URI :
783 case IPP_TAG_URISCHEME :
784 case IPP_TAG_CHARSET :
785 case IPP_TAG_LANGUAGE :
786 case IPP_TAG_MIMETYPE :
787 for (i = 0, val = attr->values; i < attr->num_values; i ++, val ++)
788 printf(" \"%s\"", val->string.text);
789 putchar('\n');
790 break;
791
792 case IPP_TAG_BEGIN_COLLECTION :
793 putchar('\n');
794
795 for (i = 0, val = attr->values; i < attr->num_values; i ++, val ++)
796 {
797 if (i)
798 putchar('\n');
799 print_attributes(val->collection, indent + 4);
800 }
801 break;
802
803 default :
804 printf("UNKNOWN (%d values)\n", attr->num_values);
805 break;
806 }
807 }
808 }
809
810
811 /*
812 * 'read_cb()' - Read data from a buffer.
813 */
814
815 ssize_t /* O - Number of bytes read */
816 read_cb(void *data, /* I - Data */
817 ipp_uchar_t *buffer, /* O - Buffer to read */
818 size_t bytes) /* I - Number of bytes to read */
819 {
820 int count; /* Number of bytes */
821
822
823 /*
824 * Copy bytes from the data buffer to the read buffer...
825 */
826
827 for (count = bytes; count > 0 && rpos < wused; count --, rpos ++)
828 *buffer++ = wbuffer[rpos];
829
830 /*
831 * Return the number of bytes read...
832 */
833
834 return (bytes - count);
835 }
836
837
838 /*
839 * 'write_cb()' - Write data into a buffer.
840 */
841
842 ssize_t /* O - Number of bytes written */
843 write_cb(void *data, /* I - Data */
844 ipp_uchar_t *buffer, /* I - Buffer to write */
845 size_t bytes) /* I - Number of bytes to write */
846 {
847 int count; /* Number of bytes */
848
849
850 /*
851 * Loop until all bytes are written...
852 */
853
854 for (count = bytes; count > 0 && wused < sizeof(wbuffer); count --, wused ++)
855 wbuffer[wused] = *buffer++;
856
857 /*
858 * Return the number of bytes written...
859 */
860
861 return (bytes - count);
862 }
863
864
865 /*
866 * End of "$Id: testipp.c 6649 2007-07-11 21:46:42Z mike $".
867 */