1 /* 2 * PPD test program for CUPS. 3 * 4 * Copyright 2007-2017 by Apple Inc. 5 * Copyright 1997-2006 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 #undef _CUPS_NO_DEPRECATED 21 #include "cups-private.h" 22 #include "ppd-private.h" 23 #include <sys/stat.h> 24 #ifdef WIN32 25 # include <io.h> 26 #else 27 # include <unistd.h> 28 # include <fcntl.h> 29 #endif /* WIN32 */ 30 #include <math.h> 31 32 33 /* 34 * Test data... 35 */ 36 37 static const char *default_code = 38 "[{\n" 39 "%%BeginFeature: *InstalledDuplexer False\n" 40 "%%EndFeature\n" 41 "} stopped cleartomark\n" 42 "[{\n" 43 "%%BeginFeature: *PageRegion Letter\n" 44 "PageRegion=Letter\n" 45 "%%EndFeature\n" 46 "} stopped cleartomark\n" 47 "[{\n" 48 "%%BeginFeature: *InputSlot Tray\n" 49 "InputSlot=Tray\n" 50 "%%EndFeature\n" 51 "} stopped cleartomark\n" 52 "[{\n" 53 "%%BeginFeature: *OutputBin Tray1\n" 54 "OutputBin=Tray1\n" 55 "%%EndFeature\n" 56 "} stopped cleartomark\n" 57 "[{\n" 58 "%%BeginFeature: *MediaType Plain\n" 59 "MediaType=Plain\n" 60 "%%EndFeature\n" 61 "} stopped cleartomark\n" 62 "[{\n" 63 "%%BeginFeature: *IntOption None\n" 64 "%%EndFeature\n" 65 "} stopped cleartomark\n" 66 "[{\n" 67 "%%BeginFeature: *StringOption None\n" 68 "%%EndFeature\n" 69 "} stopped cleartomark\n"; 70 71 static const char *custom_code = 72 "[{\n" 73 "%%BeginFeature: *InstalledDuplexer False\n" 74 "%%EndFeature\n" 75 "} stopped cleartomark\n" 76 "[{\n" 77 "%%BeginFeature: *InputSlot Tray\n" 78 "InputSlot=Tray\n" 79 "%%EndFeature\n" 80 "} stopped cleartomark\n" 81 "[{\n" 82 "%%BeginFeature: *MediaType Plain\n" 83 "MediaType=Plain\n" 84 "%%EndFeature\n" 85 "} stopped cleartomark\n" 86 "[{\n" 87 "%%BeginFeature: *OutputBin Tray1\n" 88 "OutputBin=Tray1\n" 89 "%%EndFeature\n" 90 "} stopped cleartomark\n" 91 "[{\n" 92 "%%BeginFeature: *IntOption None\n" 93 "%%EndFeature\n" 94 "} stopped cleartomark\n" 95 "[{\n" 96 "%%BeginFeature: *CustomStringOption True\n" 97 "(value\\0502\\051)\n" 98 "(value 1)\n" 99 "StringOption=Custom\n" 100 "%%EndFeature\n" 101 "} stopped cleartomark\n" 102 "[{\n" 103 "%%BeginFeature: *CustomPageSize True\n" 104 "400\n" 105 "500\n" 106 "0\n" 107 "0\n" 108 "0\n" 109 "PageSize=Custom\n" 110 "%%EndFeature\n" 111 "} stopped cleartomark\n"; 112 113 static const char *default2_code = 114 "[{\n" 115 "%%BeginFeature: *InstalledDuplexer False\n" 116 "%%EndFeature\n" 117 "} stopped cleartomark\n" 118 "[{\n" 119 "%%BeginFeature: *InputSlot Tray\n" 120 "InputSlot=Tray\n" 121 "%%EndFeature\n" 122 "} stopped cleartomark\n" 123 "[{\n" 124 "%%BeginFeature: *Quality Normal\n" 125 "Quality=Normal\n" 126 "%%EndFeature\n" 127 "} stopped cleartomark\n" 128 "[{\n" 129 "%%BeginFeature: *IntOption None\n" 130 "%%EndFeature\n" 131 "} stopped cleartomark\n" 132 "[{\n" 133 "%%BeginFeature: *StringOption None\n" 134 "%%EndFeature\n" 135 "} stopped cleartomark\n"; 136 137 138 /* 139 * 'main()' - Main entry. 140 */ 141 142 int /* O - Exit status */ 143 main(int argc, /* I - Number of command-line arguments */ 144 char *argv[]) /* I - Command-line arguments */ 145 { 146 int i; /* Looping var */ 147 ppd_file_t *ppd; /* PPD file loaded from disk */ 148 int status; /* Status of tests (0 = success, 1 = fail) */ 149 int conflicts; /* Number of conflicts */ 150 char *s; /* String */ 151 char buffer[8192]; /* String buffer */ 152 const char *text, /* Localized text */ 153 *val; /* Option value */ 154 int num_options; /* Number of options */ 155 cups_option_t *options; /* Options */ 156 ppd_size_t minsize, /* Minimum size */ 157 maxsize, /* Maximum size */ 158 *size; /* Current size */ 159 ppd_attr_t *attr; /* Current attribute */ 160 _ppd_cache_t *pc; /* PPD cache */ 161 162 163 status = 0; 164 165 if (argc == 1) 166 { 167 /* 168 * Setup directories for locale stuff... 169 */ 170 171 if (access("locale", 0)) 172 { 173 mkdir("locale", 0777); 174 mkdir("locale/fr", 0777); 175 symlink("../../../locale/cups_fr.po", "locale/fr/cups_fr.po"); 176 mkdir("locale/zh_TW", 0777); 177 symlink("../../../locale/cups_zh_TW.po", "locale/zh_TW/cups_zh_TW.po"); 178 } 179 180 putenv("LOCALEDIR=locale"); 181 putenv("SOFTWARE=CUPS"); 182 183 /* 184 * Do tests with test.ppd... 185 */ 186 187 fputs("ppdOpenFile(test.ppd): ", stdout); 188 189 if ((ppd = _ppdOpenFile("test.ppd", _PPD_LOCALIZATION_ALL)) != NULL) 190 puts("PASS"); 191 else 192 { 193 ppd_status_t err; /* Last error in file */ 194 int line; /* Line number in file */ 195 196 197 status ++; 198 err = ppdLastError(&line); 199 200 printf("FAIL (%s on line %d)\n", ppdErrorString(err), line); 201 } 202 203 fputs("ppdFindAttr(wildcard): ", stdout); 204 if ((attr = ppdFindAttr(ppd, "cupsTest", NULL)) == NULL) 205 { 206 status ++; 207 puts("FAIL (not found)"); 208 } 209 else if (strcmp(attr->name, "cupsTest") || strcmp(attr->spec, "Foo")) 210 { 211 status ++; 212 printf("FAIL (got \"%s %s\")\n", attr->name, attr->spec); 213 } 214 else 215 puts("PASS"); 216 217 fputs("ppdFindNextAttr(wildcard): ", stdout); 218 if ((attr = ppdFindNextAttr(ppd, "cupsTest", NULL)) == NULL) 219 { 220 status ++; 221 puts("FAIL (not found)"); 222 } 223 else if (strcmp(attr->name, "cupsTest") || strcmp(attr->spec, "Bar")) 224 { 225 status ++; 226 printf("FAIL (got \"%s %s\")\n", attr->name, attr->spec); 227 } 228 else 229 puts("PASS"); 230 231 fputs("ppdFindAttr(Foo): ", stdout); 232 if ((attr = ppdFindAttr(ppd, "cupsTest", "Foo")) == NULL) 233 { 234 status ++; 235 puts("FAIL (not found)"); 236 } 237 else if (strcmp(attr->name, "cupsTest") || strcmp(attr->spec, "Foo")) 238 { 239 status ++; 240 printf("FAIL (got \"%s %s\")\n", attr->name, attr->spec); 241 } 242 else 243 puts("PASS"); 244 245 fputs("ppdFindNextAttr(Foo): ", stdout); 246 if ((attr = ppdFindNextAttr(ppd, "cupsTest", "Foo")) != NULL) 247 { 248 status ++; 249 printf("FAIL (got \"%s %s\")\n", attr->name, attr->spec); 250 } 251 else 252 puts("PASS"); 253 254 fputs("ppdMarkDefaults: ", stdout); 255 ppdMarkDefaults(ppd); 256 257 if ((conflicts = ppdConflicts(ppd)) == 0) 258 puts("PASS"); 259 else 260 { 261 status ++; 262 printf("FAIL (%d conflicts)\n", conflicts); 263 } 264 265 fputs("ppdEmitString (defaults): ", stdout); 266 if ((s = ppdEmitString(ppd, PPD_ORDER_ANY, 0.0)) != NULL && 267 !strcmp(s, default_code)) 268 puts("PASS"); 269 else 270 { 271 status ++; 272 printf("FAIL (%d bytes instead of %d)\n", s ? (int)strlen(s) : 0, 273 (int)strlen(default_code)); 274 275 if (s) 276 puts(s); 277 } 278 279 if (s) 280 free(s); 281 282 fputs("ppdEmitString (custom size and string): ", stdout); 283 ppdMarkOption(ppd, "PageSize", "Custom.400x500"); 284 ppdMarkOption(ppd, "StringOption", "{String1=\"value 1\" String2=value(2)}"); 285 286 if ((s = ppdEmitString(ppd, PPD_ORDER_ANY, 0.0)) != NULL && 287 !strcmp(s, custom_code)) 288 puts("PASS"); 289 else 290 { 291 status ++; 292 printf("FAIL (%d bytes instead of %d)\n", s ? (int)strlen(s) : 0, 293 (int)strlen(custom_code)); 294 295 if (s) 296 puts(s); 297 } 298 299 if (s) 300 free(s); 301 302 /* 303 * Test constraints... 304 */ 305 306 fputs("cupsGetConflicts(InputSlot=Envelope): ", stdout); 307 ppdMarkOption(ppd, "PageSize", "Letter"); 308 309 num_options = cupsGetConflicts(ppd, "InputSlot", "Envelope", &options); 310 if (num_options != 2 || 311 (val = cupsGetOption("PageRegion", num_options, options)) == NULL || 312 _cups_strcasecmp(val, "Letter") || 313 (val = cupsGetOption("PageSize", num_options, options)) == NULL || 314 _cups_strcasecmp(val, "Letter")) 315 { 316 printf("FAIL (%d options:", num_options); 317 for (i = 0; i < num_options; i ++) 318 printf(" %s=%s", options[i].name, options[i].value); 319 puts(")"); 320 status ++; 321 } 322 else 323 puts("PASS"); 324 325 fputs("ppdConflicts(): ", stdout); 326 ppdMarkOption(ppd, "InputSlot", "Envelope"); 327 328 if ((conflicts = ppdConflicts(ppd)) == 2) 329 puts("PASS (2)"); 330 else 331 { 332 printf("FAIL (%d)\n", conflicts); 333 status ++; 334 } 335 336 fputs("cupsResolveConflicts(InputSlot=Envelope): ", stdout); 337 num_options = 0; 338 options = NULL; 339 if (!cupsResolveConflicts(ppd, "InputSlot", "Envelope", &num_options, 340 &options)) 341 { 342 puts("FAIL (Unable to resolve)"); 343 status ++; 344 } 345 else if (num_options != 2 || 346 !cupsGetOption("PageSize", num_options, options)) 347 { 348 printf("FAIL (%d options:", num_options); 349 for (i = 0; i < num_options; i ++) 350 printf(" %s=%s", options[i].name, options[i].value); 351 puts(")"); 352 status ++; 353 } 354 else 355 puts("PASS (Resolved by changing PageSize)"); 356 357 cupsFreeOptions(num_options, options); 358 359 fputs("cupsResolveConflicts(No option/choice): ", stdout); 360 num_options = 0; 361 options = NULL; 362 if (cupsResolveConflicts(ppd, NULL, NULL, &num_options, &options) && 363 num_options == 1 && !_cups_strcasecmp(options[0].name, "InputSlot") && 364 !_cups_strcasecmp(options[0].value, "Tray")) 365 puts("PASS (Resolved by changing InputSlot)"); 366 else if (num_options > 0) 367 { 368 printf("FAIL (%d options:", num_options); 369 for (i = 0; i < num_options; i ++) 370 printf(" %s=%s", options[i].name, options[i].value); 371 puts(")"); 372 status ++; 373 } 374 else 375 { 376 puts("FAIL (Unable to resolve)"); 377 status ++; 378 } 379 cupsFreeOptions(num_options, options); 380 381 fputs("ppdInstallableConflict(): ", stdout); 382 if (ppdInstallableConflict(ppd, "Duplex", "DuplexNoTumble") && 383 !ppdInstallableConflict(ppd, "Duplex", "None")) 384 puts("PASS"); 385 else if (!ppdInstallableConflict(ppd, "Duplex", "DuplexNoTumble")) 386 { 387 puts("FAIL (Duplex=DuplexNoTumble did not conflict)"); 388 status ++; 389 } 390 else 391 { 392 puts("FAIL (Duplex=None conflicted)"); 393 status ++; 394 } 395 396 /* 397 * ppdPageSizeLimits 398 */ 399 400 fputs("ppdPageSizeLimits: ", stdout); 401 if (ppdPageSizeLimits(ppd, &minsize, &maxsize)) 402 { 403 if (fabs(minsize.width - 36.0) > 0.001 || fabs(minsize.length - 36.0) > 0.001 || 404 fabs(maxsize.width - 1080.0) > 0.001 || fabs(maxsize.length - 86400.0) > 0.001) 405 { 406 printf("FAIL (got min=%.3fx%.3f, max=%.3fx%.3f, " 407 "expected min=36x36, max=1080x86400)\n", minsize.width, 408 minsize.length, maxsize.width, maxsize.length); 409 status ++; 410 } 411 else 412 puts("PASS"); 413 } 414 else 415 { 416 puts("FAIL (returned 0)"); 417 status ++; 418 } 419 420 /* 421 * cupsMarkOptions with PWG and IPP size names. 422 */ 423 424 fputs("cupsMarkOptions(media=iso-a4): ", stdout); 425 num_options = cupsAddOption("media", "iso-a4", 0, &options); 426 cupsMarkOptions(ppd, num_options, options); 427 cupsFreeOptions(num_options, options); 428 429 size = ppdPageSize(ppd, NULL); 430 if (!size || strcmp(size->name, "A4")) 431 { 432 printf("FAIL (%s)\n", size ? size->name : "unknown"); 433 status ++; 434 } 435 else 436 puts("PASS"); 437 438 fputs("cupsMarkOptions(media=na_letter_8.5x11in): ", stdout); 439 num_options = cupsAddOption("media", "na_letter_8.5x11in", 0, &options); 440 cupsMarkOptions(ppd, num_options, options); 441 cupsFreeOptions(num_options, options); 442 443 size = ppdPageSize(ppd, NULL); 444 if (!size || strcmp(size->name, "Letter")) 445 { 446 printf("FAIL (%s)\n", size ? size->name : "unknown"); 447 status ++; 448 } 449 else 450 puts("PASS"); 451 452 fputs("cupsMarkOptions(media=oe_letter-fullbleed_8.5x11in): ", stdout); 453 num_options = cupsAddOption("media", "oe_letter-fullbleed_8.5x11in", 0, 454 &options); 455 cupsMarkOptions(ppd, num_options, options); 456 cupsFreeOptions(num_options, options); 457 458 size = ppdPageSize(ppd, NULL); 459 if (!size || strcmp(size->name, "Letter.Fullbleed")) 460 { 461 printf("FAIL (%s)\n", size ? size->name : "unknown"); 462 status ++; 463 } 464 else 465 puts("PASS"); 466 467 fputs("cupsMarkOptions(media=A4): ", stdout); 468 num_options = cupsAddOption("media", "A4", 0, &options); 469 cupsMarkOptions(ppd, num_options, options); 470 cupsFreeOptions(num_options, options); 471 472 size = ppdPageSize(ppd, NULL); 473 if (!size || strcmp(size->name, "A4")) 474 { 475 printf("FAIL (%s)\n", size ? size->name : "unknown"); 476 status ++; 477 } 478 else 479 puts("PASS"); 480 481 /* 482 * Custom sizes... 483 */ 484 485 fputs("cupsMarkOptions(media=Custom.8x10in): ", stdout); 486 num_options = cupsAddOption("media", "Custom.8x10in", 0, &options); 487 cupsMarkOptions(ppd, num_options, options); 488 cupsFreeOptions(num_options, options); 489 490 size = ppdPageSize(ppd, NULL); 491 if (!size || strcmp(size->name, "Custom") || 492 fabs(size->width - 576.0) > 0.001 || 493 fabs(size->length - 720.0) > 0.001) 494 { 495 printf("FAIL (%s - %gx%g)\n", size ? size->name : "unknown", 496 size ? size->width : 0.0, size ? size->length : 0.0); 497 status ++; 498 } 499 else 500 puts("PASS"); 501 502 /* 503 * Test localization... 504 */ 505 506 fputs("ppdLocalizeIPPReason(text): ", stdout); 507 if (ppdLocalizeIPPReason(ppd, "foo", NULL, buffer, sizeof(buffer)) && 508 !strcmp(buffer, "Foo Reason")) 509 puts("PASS"); 510 else 511 { 512 status ++; 513 printf("FAIL (\"%s\" instead of \"Foo Reason\")\n", buffer); 514 } 515 516 fputs("ppdLocalizeIPPReason(http): ", stdout); 517 if (ppdLocalizeIPPReason(ppd, "foo", "http", buffer, sizeof(buffer)) && 518 !strcmp(buffer, "http://foo/bar.html")) 519 puts("PASS"); 520 else 521 { 522 status ++; 523 printf("FAIL (\"%s\" instead of \"http://foo/bar.html\")\n", buffer); 524 } 525 526 fputs("ppdLocalizeIPPReason(help): ", stdout); 527 if (ppdLocalizeIPPReason(ppd, "foo", "help", buffer, sizeof(buffer)) && 528 !strcmp(buffer, "help:anchor='foo'%20bookID=Vendor%20Help")) 529 puts("PASS"); 530 else 531 { 532 status ++; 533 printf("FAIL (\"%s\" instead of \"help:anchor='foo'%%20bookID=Vendor%%20Help\")\n", buffer); 534 } 535 536 fputs("ppdLocalizeIPPReason(file): ", stdout); 537 if (ppdLocalizeIPPReason(ppd, "foo", "file", buffer, sizeof(buffer)) && 538 !strcmp(buffer, "/help/foo/bar.html")) 539 puts("PASS"); 540 else 541 { 542 status ++; 543 printf("FAIL (\"%s\" instead of \"/help/foo/bar.html\")\n", buffer); 544 } 545 546 putenv("LANG=fr"); 547 putenv("LC_ALL=fr"); 548 putenv("LC_CTYPE=fr"); 549 putenv("LC_MESSAGES=fr"); 550 551 fputs("ppdLocalizeIPPReason(fr text): ", stdout); 552 if (ppdLocalizeIPPReason(ppd, "foo", NULL, buffer, sizeof(buffer)) && 553 !strcmp(buffer, "La Long Foo Reason")) 554 puts("PASS"); 555 else 556 { 557 status ++; 558 printf("FAIL (\"%s\" instead of \"La Long Foo Reason\")\n", buffer); 559 } 560 561 putenv("LANG=zh_TW"); 562 putenv("LC_ALL=zh_TW"); 563 putenv("LC_CTYPE=zh_TW"); 564 putenv("LC_MESSAGES=zh_TW"); 565 566 fputs("ppdLocalizeIPPReason(zh_TW text): ", stdout); 567 if (ppdLocalizeIPPReason(ppd, "foo", NULL, buffer, sizeof(buffer)) && 568 !strcmp(buffer, "Number 1 Foo Reason")) 569 puts("PASS"); 570 else 571 { 572 status ++; 573 printf("FAIL (\"%s\" instead of \"Number 1 Foo Reason\")\n", buffer); 574 } 575 576 /* 577 * cupsMarkerName localization... 578 */ 579 580 putenv("LANG=en"); 581 putenv("LC_ALL=en"); 582 putenv("LC_CTYPE=en"); 583 putenv("LC_MESSAGES=en"); 584 585 fputs("ppdLocalizeMarkerName(bogus): ", stdout); 586 587 if ((text = ppdLocalizeMarkerName(ppd, "bogus")) != NULL) 588 { 589 status ++; 590 printf("FAIL (\"%s\" instead of NULL)\n", text); 591 } 592 else 593 puts("PASS"); 594 595 fputs("ppdLocalizeMarkerName(cyan): ", stdout); 596 597 if ((text = ppdLocalizeMarkerName(ppd, "cyan")) != NULL && 598 !strcmp(text, "Cyan Toner")) 599 puts("PASS"); 600 else 601 { 602 status ++; 603 printf("FAIL (\"%s\" instead of \"Cyan Toner\")\n", 604 text ? text : "(null)"); 605 } 606 607 putenv("LANG=fr"); 608 putenv("LC_ALL=fr"); 609 putenv("LC_CTYPE=fr"); 610 putenv("LC_MESSAGES=fr"); 611 612 fputs("ppdLocalizeMarkerName(fr cyan): ", stdout); 613 if ((text = ppdLocalizeMarkerName(ppd, "cyan")) != NULL && 614 !strcmp(text, "La Toner Cyan")) 615 puts("PASS"); 616 else 617 { 618 status ++; 619 printf("FAIL (\"%s\" instead of \"La Toner Cyan\")\n", 620 text ? text : "(null)"); 621 } 622 623 putenv("LANG=zh_TW"); 624 putenv("LC_ALL=zh_TW"); 625 putenv("LC_CTYPE=zh_TW"); 626 putenv("LC_MESSAGES=zh_TW"); 627 628 fputs("ppdLocalizeMarkerName(zh_TW cyan): ", stdout); 629 if ((text = ppdLocalizeMarkerName(ppd, "cyan")) != NULL && 630 !strcmp(text, "Number 1 Cyan Toner")) 631 puts("PASS"); 632 else 633 { 634 status ++; 635 printf("FAIL (\"%s\" instead of \"Number 1 Cyan Toner\")\n", 636 text ? text : "(null)"); 637 } 638 639 ppdClose(ppd); 640 641 /* 642 * Test new constraints... 643 */ 644 645 fputs("ppdOpenFile(test2.ppd): ", stdout); 646 647 if ((ppd = ppdOpenFile("test2.ppd")) != NULL) 648 puts("PASS"); 649 else 650 { 651 ppd_status_t err; /* Last error in file */ 652 int line; /* Line number in file */ 653 654 655 status ++; 656 err = ppdLastError(&line); 657 658 printf("FAIL (%s on line %d)\n", ppdErrorString(err), line); 659 } 660 661 fputs("ppdMarkDefaults: ", stdout); 662 ppdMarkDefaults(ppd); 663 664 if ((conflicts = ppdConflicts(ppd)) == 0) 665 puts("PASS"); 666 else 667 { 668 status ++; 669 printf("FAIL (%d conflicts)\n", conflicts); 670 } 671 672 fputs("ppdEmitString (defaults): ", stdout); 673 if ((s = ppdEmitString(ppd, PPD_ORDER_ANY, 0.0)) != NULL && 674 !strcmp(s, default2_code)) 675 puts("PASS"); 676 else 677 { 678 status ++; 679 printf("FAIL (%d bytes instead of %d)\n", s ? (int)strlen(s) : 0, 680 (int)strlen(default2_code)); 681 682 if (s) 683 puts(s); 684 } 685 686 if (s) 687 free(s); 688 689 fputs("ppdConflicts(): ", stdout); 690 ppdMarkOption(ppd, "PageSize", "Env10"); 691 ppdMarkOption(ppd, "InputSlot", "Envelope"); 692 ppdMarkOption(ppd, "Quality", "Photo"); 693 694 if ((conflicts = ppdConflicts(ppd)) == 1) 695 puts("PASS (1)"); 696 else 697 { 698 printf("FAIL (%d)\n", conflicts); 699 status ++; 700 } 701 702 fputs("cupsResolveConflicts(Quality=Photo): ", stdout); 703 num_options = 0; 704 options = NULL; 705 if (cupsResolveConflicts(ppd, "Quality", "Photo", &num_options, 706 &options)) 707 { 708 printf("FAIL (%d options:", num_options); 709 for (i = 0; i < num_options; i ++) 710 printf(" %s=%s", options[i].name, options[i].value); 711 puts(")"); 712 status ++; 713 } 714 else 715 puts("PASS (Unable to resolve)"); 716 cupsFreeOptions(num_options, options); 717 718 fputs("cupsResolveConflicts(No option/choice): ", stdout); 719 num_options = 0; 720 options = NULL; 721 if (cupsResolveConflicts(ppd, NULL, NULL, &num_options, &options) && 722 num_options == 1 && !_cups_strcasecmp(options->name, "Quality") && 723 !_cups_strcasecmp(options->value, "Normal")) 724 puts("PASS"); 725 else if (num_options > 0) 726 { 727 printf("FAIL (%d options:", num_options); 728 for (i = 0; i < num_options; i ++) 729 printf(" %s=%s", options[i].name, options[i].value); 730 puts(")"); 731 status ++; 732 } 733 else 734 { 735 puts("FAIL (Unable to resolve!)"); 736 status ++; 737 } 738 cupsFreeOptions(num_options, options); 739 740 fputs("cupsResolveConflicts(loop test): ", stdout); 741 ppdMarkOption(ppd, "PageSize", "A4"); 742 ppdMarkOption(ppd, "InputSlot", "Tray"); 743 ppdMarkOption(ppd, "Quality", "Photo"); 744 num_options = 0; 745 options = NULL; 746 if (!cupsResolveConflicts(ppd, NULL, NULL, &num_options, &options)) 747 puts("PASS"); 748 else if (num_options > 0) 749 { 750 printf("FAIL (%d options:", num_options); 751 for (i = 0; i < num_options; i ++) 752 printf(" %s=%s", options[i].name, options[i].value); 753 puts(")"); 754 } 755 else 756 puts("FAIL (No conflicts!)"); 757 758 fputs("ppdInstallableConflict(): ", stdout); 759 if (ppdInstallableConflict(ppd, "Duplex", "DuplexNoTumble") && 760 !ppdInstallableConflict(ppd, "Duplex", "None")) 761 puts("PASS"); 762 else if (!ppdInstallableConflict(ppd, "Duplex", "DuplexNoTumble")) 763 { 764 puts("FAIL (Duplex=DuplexNoTumble did not conflict)"); 765 status ++; 766 } 767 else 768 { 769 puts("FAIL (Duplex=None conflicted)"); 770 status ++; 771 } 772 773 /* 774 * ppdPageSizeLimits 775 */ 776 777 ppdMarkDefaults(ppd); 778 779 fputs("ppdPageSizeLimits(default): ", stdout); 780 if (ppdPageSizeLimits(ppd, &minsize, &maxsize)) 781 { 782 if (fabs(minsize.width - 36.0) > 0.001 || fabs(minsize.length - 36.0) > 0.001 || 783 fabs(maxsize.width - 1080.0) > 0.001 || fabs(maxsize.length - 86400.0) > 0.001) 784 { 785 printf("FAIL (got min=%.0fx%.0f, max=%.0fx%.0f, " 786 "expected min=36x36, max=1080x86400)\n", minsize.width, 787 minsize.length, maxsize.width, maxsize.length); 788 status ++; 789 } 790 else 791 puts("PASS"); 792 } 793 else 794 { 795 puts("FAIL (returned 0)"); 796 status ++; 797 } 798 799 ppdMarkOption(ppd, "InputSlot", "Manual"); 800 801 fputs("ppdPageSizeLimits(InputSlot=Manual): ", stdout); 802 if (ppdPageSizeLimits(ppd, &minsize, &maxsize)) 803 { 804 if (fabs(minsize.width - 100.0) > 0.001 || fabs(minsize.length - 100.0) > 0.001 || 805 fabs(maxsize.width - 1000.0) > 0.001 || fabs(maxsize.length - 1000.0) > 0.001) 806 { 807 printf("FAIL (got min=%.0fx%.0f, max=%.0fx%.0f, " 808 "expected min=100x100, max=1000x1000)\n", minsize.width, 809 minsize.length, maxsize.width, maxsize.length); 810 status ++; 811 } 812 else 813 puts("PASS"); 814 } 815 else 816 { 817 puts("FAIL (returned 0)"); 818 status ++; 819 } 820 821 ppdMarkOption(ppd, "Quality", "Photo"); 822 823 fputs("ppdPageSizeLimits(Quality=Photo): ", stdout); 824 if (ppdPageSizeLimits(ppd, &minsize, &maxsize)) 825 { 826 if (fabs(minsize.width - 200.0) > 0.001 || fabs(minsize.length - 200.0) > 0.001 || 827 fabs(maxsize.width - 1000.0) > 0.001 || fabs(maxsize.length - 1000.0) > 0.001) 828 { 829 printf("FAIL (got min=%.0fx%.0f, max=%.0fx%.0f, " 830 "expected min=200x200, max=1000x1000)\n", minsize.width, 831 minsize.length, maxsize.width, maxsize.length); 832 status ++; 833 } 834 else 835 puts("PASS"); 836 } 837 else 838 { 839 puts("FAIL (returned 0)"); 840 status ++; 841 } 842 843 ppdMarkOption(ppd, "InputSlot", "Tray"); 844 845 fputs("ppdPageSizeLimits(Quality=Photo): ", stdout); 846 if (ppdPageSizeLimits(ppd, &minsize, &maxsize)) 847 { 848 if (fabs(minsize.width - 300.0) > 0.001 || fabs(minsize.length - 300.0) > 0.001 || 849 fabs(maxsize.width - 1080.0) > 0.001 || fabs(maxsize.length - 86400.0) > 0.001) 850 { 851 printf("FAIL (got min=%.0fx%.0f, max=%.0fx%.0f, " 852 "expected min=300x300, max=1080x86400)\n", minsize.width, 853 minsize.length, maxsize.width, maxsize.length); 854 status ++; 855 } 856 else 857 puts("PASS"); 858 } 859 else 860 { 861 puts("FAIL (returned 0)"); 862 status ++; 863 } 864 } 865 else if (!strncmp(argv[1], "ipp://", 6) || !strncmp(argv[1], "ipps://", 7)) 866 { 867 /* 868 * ipp://... or ipps://... 869 */ 870 871 http_t *http; /* Connection to printer */ 872 ipp_t *request, /* Get-Printer-Attributes request */ 873 *response; /* Get-Printer-Attributes response */ 874 char scheme[32], /* URI scheme */ 875 userpass[256], /* Username:password */ 876 host[256], /* Hostname */ 877 resource[256]; /* Resource path */ 878 int port; /* Port number */ 879 880 if (httpSeparateURI(HTTP_URI_CODING_ALL, argv[1], scheme, sizeof(scheme), userpass, sizeof(userpass), host, sizeof(host), &port, resource, sizeof(resource)) < HTTP_URI_STATUS_OK) 881 { 882 printf("Bad URI \"%s\".\n", argv[1]); 883 return (1); 884 } 885 886 http = httpConnect2(host, port, NULL, AF_UNSPEC, !strcmp(scheme, "ipps") ? HTTP_ENCRYPTION_ALWAYS : HTTP_ENCRYPTION_IF_REQUESTED, 1, 30000, NULL); 887 if (!http) 888 { 889 printf("Unable to connect to \"%s:%d\": %s\n", host, port, cupsLastErrorString()); 890 return (1); 891 } 892 893 request = ippNewRequest(IPP_OP_GET_PRINTER_ATTRIBUTES); 894 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, argv[1]); 895 response = cupsDoRequest(http, request, resource); 896 897 if (_ppdCreateFromIPP(buffer, sizeof(buffer), response)) 898 printf("Created PPD: %s\n", buffer); 899 else 900 puts("Unable to create PPD."); 901 902 ippDelete(response); 903 httpClose(http); 904 return (0); 905 } 906 else 907 { 908 const char *filename; /* PPD filename */ 909 struct stat fileinfo; /* File information */ 910 911 912 if (strchr(argv[1], ':')) 913 { 914 /* 915 * Server PPD... 916 */ 917 918 if ((filename = cupsGetServerPPD(CUPS_HTTP_DEFAULT, argv[1])) == NULL) 919 { 920 printf("%s: %s\n", argv[1], cupsLastErrorString()); 921 return (1); 922 } 923 } 924 else if (!strncmp(argv[1], "-d", 2)) 925 { 926 const char *printer; /* Printer name */ 927 928 if (argv[1][2]) 929 printer = argv[1] + 2; 930 else if (argv[2]) 931 printer = argv[2]; 932 else 933 { 934 puts("Usage: ./testppd -d printer"); 935 return (1); 936 } 937 938 filename = cupsGetPPD(printer); 939 940 if (!filename) 941 { 942 printf("%s: %s\n", printer, cupsLastErrorString()); 943 return (1); 944 } 945 } 946 else 947 filename = argv[1]; 948 949 if (lstat(filename, &fileinfo)) 950 { 951 printf("%s: %s\n", filename, strerror(errno)); 952 return (1); 953 } 954 955 if (S_ISLNK(fileinfo.st_mode)) 956 { 957 char realfile[1024]; /* Real file path */ 958 ssize_t realsize; /* Size of real file path */ 959 960 961 if ((realsize = readlink(filename, realfile, sizeof(realfile) - 1)) < 0) 962 strlcpy(realfile, "Unknown", sizeof(realfile)); 963 else 964 realfile[realsize] = '\0'; 965 966 if (stat(realfile, &fileinfo)) 967 printf("%s: symlink to \"%s\", %s\n", filename, realfile, 968 strerror(errno)); 969 else 970 printf("%s: symlink to \"%s\", %ld bytes\n", filename, realfile, 971 (long)fileinfo.st_size); 972 } 973 else 974 printf("%s: regular file, %ld bytes\n", filename, (long)fileinfo.st_size); 975 976 if ((ppd = ppdOpenFile(filename)) == NULL) 977 { 978 ppd_status_t err; /* Last error in file */ 979 int line; /* Line number in file */ 980 981 982 status ++; 983 err = ppdLastError(&line); 984 985 printf("%s: %s on line %d\n", argv[1], ppdErrorString(err), line); 986 } 987 else 988 { 989 int j, k; /* Looping vars */ 990 ppd_group_t *group; /* Option group */ 991 ppd_option_t *option; /* Option */ 992 ppd_coption_t *coption; /* Custom option */ 993 ppd_cparam_t *cparam; /* Custom parameter */ 994 ppd_const_t *c; /* UIConstraints */ 995 char lang[255], /* LANG environment variable */ 996 lc_all[255], /* LC_ALL environment variable */ 997 lc_ctype[255], /* LC_CTYPE environment variable */ 998 lc_messages[255];/* LC_MESSAGES environment variable */ 999 1000 1001 if (argc > 2) 1002 { 1003 snprintf(lang, sizeof(lang), "LANG=%s", argv[2]); 1004 putenv(lang); 1005 snprintf(lc_all, sizeof(lc_all), "LC_ALL=%s", argv[2]); 1006 putenv(lc_all); 1007 snprintf(lc_ctype, sizeof(lc_ctype), "LC_CTYPE=%s", argv[2]); 1008 putenv(lc_ctype); 1009 snprintf(lc_messages, sizeof(lc_messages), "LC_MESSAGES=%s", argv[2]); 1010 putenv(lc_messages); 1011 } 1012 1013 ppdLocalize(ppd); 1014 ppdMarkDefaults(ppd); 1015 1016 if (argc > 3) 1017 { 1018 text = ppdLocalizeIPPReason(ppd, argv[3], NULL, buffer, sizeof(buffer)); 1019 printf("ppdLocalizeIPPReason(%s)=%s\n", argv[3], 1020 text ? text : "(null)"); 1021 return (text == NULL); 1022 } 1023 1024 for (i = ppd->num_groups, group = ppd->groups; 1025 i > 0; 1026 i --, group ++) 1027 { 1028 printf("%s (%s):\n", group->name, group->text); 1029 1030 for (j = group->num_options, option = group->options; 1031 j > 0; 1032 j --, option ++) 1033 { 1034 printf(" %s (%s):\n", option->keyword, option->text); 1035 1036 for (k = 0; k < option->num_choices; k ++) 1037 printf(" - %s%s (%s)\n", 1038 option->choices[k].marked ? "*" : "", 1039 option->choices[k].choice, option->choices[k].text); 1040 1041 if ((coption = ppdFindCustomOption(ppd, option->keyword)) != NULL) 1042 { 1043 for (cparam = (ppd_cparam_t *)cupsArrayFirst(coption->params); 1044 cparam; 1045 cparam = (ppd_cparam_t *)cupsArrayNext(coption->params)) 1046 { 1047 switch (cparam->type) 1048 { 1049 case PPD_CUSTOM_CURVE : 1050 printf(" %s(%s): PPD_CUSTOM_CURVE (%g to %g)\n", 1051 cparam->name, cparam->text, 1052 cparam->minimum.custom_curve, 1053 cparam->maximum.custom_curve); 1054 break; 1055 1056 case PPD_CUSTOM_INT : 1057 printf(" %s(%s): PPD_CUSTOM_INT (%d to %d)\n", 1058 cparam->name, cparam->text, 1059 cparam->minimum.custom_int, 1060 cparam->maximum.custom_int); 1061 break; 1062 1063 case PPD_CUSTOM_INVCURVE : 1064 printf(" %s(%s): PPD_CUSTOM_INVCURVE (%g to %g)\n", 1065 cparam->name, cparam->text, 1066 cparam->minimum.custom_invcurve, 1067 cparam->maximum.custom_invcurve); 1068 break; 1069 1070 case PPD_CUSTOM_PASSCODE : 1071 printf(" %s(%s): PPD_CUSTOM_PASSCODE (%d to %d)\n", 1072 cparam->name, cparam->text, 1073 cparam->minimum.custom_passcode, 1074 cparam->maximum.custom_passcode); 1075 break; 1076 1077 case PPD_CUSTOM_PASSWORD : 1078 printf(" %s(%s): PPD_CUSTOM_PASSWORD (%d to %d)\n", 1079 cparam->name, cparam->text, 1080 cparam->minimum.custom_password, 1081 cparam->maximum.custom_password); 1082 break; 1083 1084 case PPD_CUSTOM_POINTS : 1085 printf(" %s(%s): PPD_CUSTOM_POINTS (%g to %g)\n", 1086 cparam->name, cparam->text, 1087 cparam->minimum.custom_points, 1088 cparam->maximum.custom_points); 1089 break; 1090 1091 case PPD_CUSTOM_REAL : 1092 printf(" %s(%s): PPD_CUSTOM_REAL (%g to %g)\n", 1093 cparam->name, cparam->text, 1094 cparam->minimum.custom_real, 1095 cparam->maximum.custom_real); 1096 break; 1097 1098 case PPD_CUSTOM_STRING : 1099 printf(" %s(%s): PPD_CUSTOM_STRING (%d to %d)\n", 1100 cparam->name, cparam->text, 1101 cparam->minimum.custom_string, 1102 cparam->maximum.custom_string); 1103 break; 1104 } 1105 } 1106 } 1107 } 1108 } 1109 1110 puts("\nSizes:"); 1111 for (i = ppd->num_sizes, size = ppd->sizes; i > 0; i --, size ++) 1112 printf(" %s = %gx%g, [%g %g %g %g]\n", size->name, size->width, 1113 size->length, size->left, size->bottom, size->right, size->top); 1114 1115 puts("\nConstraints:"); 1116 1117 for (i = ppd->num_consts, c = ppd->consts; i > 0; i --, c ++) 1118 printf(" *UIConstraints: *%s %s *%s %s\n", c->option1, c->choice1, 1119 c->option2, c->choice2); 1120 if (ppd->num_consts == 0) 1121 puts(" NO CONSTRAINTS"); 1122 1123 puts("\nFilters:"); 1124 1125 for (i = 0; i < ppd->num_filters; i ++) 1126 printf(" %s\n", ppd->filters[i]); 1127 1128 if (ppd->num_filters == 0) 1129 puts(" NO FILTERS"); 1130 1131 puts("\nAttributes:"); 1132 1133 for (attr = (ppd_attr_t *)cupsArrayFirst(ppd->sorted_attrs); 1134 attr; 1135 attr = (ppd_attr_t *)cupsArrayNext(ppd->sorted_attrs)) 1136 printf(" *%s %s/%s: \"%s\"\n", attr->name, attr->spec, 1137 attr->text, attr->value ? attr->value : ""); 1138 1139 puts("\nPPD Cache:"); 1140 if ((pc = _ppdCacheCreateWithPPD(ppd)) == NULL) 1141 printf(" Unable to create: %s\n", cupsLastErrorString()); 1142 else 1143 { 1144 _ppdCacheWriteFile(pc, "t.cache", NULL); 1145 puts(" Wrote t.cache."); 1146 } 1147 } 1148 1149 if (!strncmp(argv[1], "-d", 2)) 1150 unlink(filename); 1151 } 1152 1153 #ifdef __APPLE__ 1154 if (getenv("MallocStackLogging") && getenv("MallocStackLoggingNoCompact")) 1155 { 1156 char command[1024]; /* malloc_history command */ 1157 1158 snprintf(command, sizeof(command), "malloc_history %d -all_by_size", 1159 getpid()); 1160 fflush(stdout); 1161 system(command); 1162 } 1163 #endif /* __APPLE__ */ 1164 1165 ppdClose(ppd); 1166 1167 return (status); 1168 } 1169