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