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