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