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