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