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