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