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