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