2 * PPD test program for CUPS.
4 * Copyright 2007-2016 by Apple Inc.
5 * Copyright 1997-2007 by Easy Software Products, all rights reserved.
7 * Licensed under Apache License v2.0. See the file "LICENSE" for more information.
9 * PostScript is a trademark of Adobe Systems, Inc.
13 * Include necessary headers...
16 #include <cups/cups-private.h>
18 #include <cups/ppd-private.h>
19 #include <cups/raster.h>
27 * Error warning overrides...
37 WARN_TRANSLATIONS
= 16,
76 #define MODE_WRITE 0022 /* Group/other write */
77 #define MODE_MASK 0555 /* Owner/group/other read+exec/search */
78 #define MODE_DATAFILE 0444 /* Owner/group/other read */
79 #define MODE_DIRECTORY 0555 /* Owner/group/other read+search */
80 #define MODE_PROGRAM 0555 /* Owner/group/other read+exec */
87 static void check_basics(const char *filename
);
88 static int check_constraints(ppd_file_t
*ppd
, int errors
, int verbose
,
90 static int check_case(ppd_file_t
*ppd
, int errors
, int verbose
);
91 static int check_defaults(ppd_file_t
*ppd
, int errors
, int verbose
,
93 static int check_duplex(ppd_file_t
*ppd
, int errors
, int verbose
,
95 static int check_filters(ppd_file_t
*ppd
, const char *root
, int errors
,
96 int verbose
, int warn
);
97 static int check_profiles(ppd_file_t
*ppd
, const char *root
, int errors
,
98 int verbose
, int warn
);
99 static int check_sizes(ppd_file_t
*ppd
, int errors
, int verbose
, int warn
);
100 static int check_translations(ppd_file_t
*ppd
, int errors
, int verbose
,
102 static void show_conflicts(ppd_file_t
*ppd
, const char *prefix
);
103 static int test_raster(ppd_file_t
*ppd
, int verbose
);
104 static void usage(void) __attribute__((noreturn
));
105 static int valid_path(const char *keyword
, const char *path
, int errors
,
106 int verbose
, int warn
);
107 static int valid_utf8(const char *s
);
111 * 'main()' - Main entry for test program.
114 int /* O - Exit status */
115 main(int argc
, /* I - Number of command-line args */
116 char *argv
[]) /* I - Command-line arguments */
118 int i
, j
, k
, m
, n
; /* Looping vars */
119 size_t len
; /* Length of option name */
120 char *opt
; /* Option character */
121 const char *ptr
; /* Pointer into string */
122 cups_file_t
*fp
; /* PPD file */
123 int files
; /* Number of files */
124 int verbose
; /* Want verbose output? */
125 int warn
; /* Which errors to just warn about */
126 int ignore
; /* Which errors to ignore */
127 int status
; /* Exit status */
128 int errors
; /* Number of conformance errors */
129 int ppdversion
; /* PPD spec version in PPD file */
130 ppd_status_t error
; /* Status of ppdOpen*() */
131 int line
; /* Line number for error */
132 char *root
; /* Root directory */
133 int xdpi
, /* X resolution */
134 ydpi
; /* Y resolution */
135 ppd_file_t
*ppd
; /* PPD file record */
136 ppd_attr_t
*attr
; /* PPD attribute */
137 ppd_size_t
*size
; /* Size record */
138 ppd_group_t
*group
; /* UI group */
139 ppd_option_t
*option
; /* Standard UI option */
140 ppd_group_t
*group2
; /* UI group */
141 ppd_option_t
*option2
; /* Standard UI option */
142 ppd_choice_t
*choice
; /* Standard UI option choice */
143 struct lconv
*loc
; /* Locale data */
144 static char *uis
[] = { "BOOLEAN", "PICKONE", "PICKMANY" };
145 static char *sections
[] = { "ANY", "DOCUMENT", "EXIT",
146 "JCL", "PAGE", "PROLOG" };
149 _cupsSetLocale(argv
);
153 * Display PPD files for each file listed on the command-line...
156 ppdSetConformance(PPD_CONFORM_STRICT
);
166 for (i
= 1; i
< argc
; i
++)
167 if (argv
[i
][0] == '-' && argv
[i
][1])
169 for (opt
= argv
[i
] + 1; *opt
; opt
++)
172 case 'I' : /* Ignore errors */
178 if (!strcmp(argv
[i
], "none"))
180 else if (!strcmp(argv
[i
], "filename"))
181 ignore
|= WARN_FILENAME
;
182 else if (!strcmp(argv
[i
], "filters"))
183 ignore
|= WARN_FILTERS
;
184 else if (!strcmp(argv
[i
], "profiles"))
185 ignore
|= WARN_PROFILES
;
186 else if (!strcmp(argv
[i
], "all"))
187 ignore
= WARN_FILTERS
| WARN_PROFILES
;
192 case 'R' : /* Alternate root directory */
201 case 'W' : /* Turn errors into warnings */
207 if (!strcmp(argv
[i
], "none"))
209 else if (!strcmp(argv
[i
], "constraints"))
210 warn
|= WARN_CONSTRAINTS
;
211 else if (!strcmp(argv
[i
], "defaults"))
212 warn
|= WARN_DEFAULTS
;
213 else if (!strcmp(argv
[i
], "duplex"))
215 else if (!strcmp(argv
[i
], "filters"))
216 warn
|= WARN_FILTERS
;
217 else if (!strcmp(argv
[i
], "profiles"))
218 warn
|= WARN_PROFILES
;
219 else if (!strcmp(argv
[i
], "sizes"))
221 else if (!strcmp(argv
[i
], "translations"))
222 warn
|= WARN_TRANSLATIONS
;
223 else if (!strcmp(argv
[i
], "all"))
229 case 'q' : /* Quiet mode */
232 _cupsLangPuts(stderr
,
233 _("cupstestppd: The -q option is incompatible "
234 "with the -v option."));
241 case 'r' : /* Relaxed mode */
242 ppdSetConformance(PPD_CONFORM_RELAXED
);
245 case 'v' : /* Verbose mode */
248 _cupsLangPuts(stderr
,
249 _("cupstestppd: The -v option is incompatible "
250 "with the -q option."));
265 * Open the PPD file...
268 if (files
&& verbose
>= 0)
273 if (argv
[i
][0] == '-')
279 ppd
= _ppdOpen(cupsFileStdin(), _PPD_LOCALIZATION_ALL
);
282 printf("%s:", (ppd
&& ppd
->pcfilename
) ? ppd
->pcfilename
: "(stdin)");
287 * Read from a file...
291 printf("%s:", argv
[i
]);
293 if ((fp
= cupsFileOpen(argv
[i
], "r")) != NULL
)
295 ppd
= _ppdOpen(fp
, _PPD_LOCALIZATION_ALL
);
300 status
= ERROR_FILE_OPEN
;
304 _cupsLangPuts(stdout
, _(" FAIL"));
305 _cupsLangPrintf(stdout
,
306 _(" **FAIL** Unable to open PPD file - %s on "
307 "line %d."), strerror(errno
), 0);
315 error
= ppdLastError(&line
);
317 if (error
<= PPD_ALLOC_ERROR
)
319 status
= ERROR_FILE_OPEN
;
323 _cupsLangPuts(stdout
, _(" FAIL"));
324 _cupsLangPrintf(stdout
,
325 _(" **FAIL** Unable to open PPD file - %s on "
326 "line %d."), strerror(errno
), 0);
331 status
= ERROR_PPD_FORMAT
;
335 _cupsLangPuts(stdout
, _(" FAIL"));
336 _cupsLangPrintf(stdout
,
337 _(" **FAIL** Unable to open PPD file - "
339 ppdErrorString(error
), line
);
343 case PPD_MISSING_PPDADOBE4
:
344 _cupsLangPuts(stdout
,
345 _(" REF: Page 42, section "
348 case PPD_MISSING_VALUE
:
349 _cupsLangPuts(stdout
,
350 _(" REF: Page 20, section "
353 case PPD_BAD_OPEN_GROUP
:
354 case PPD_NESTED_OPEN_GROUP
:
355 _cupsLangPuts(stdout
,
356 _(" REF: Pages 45-46, section "
359 case PPD_BAD_OPEN_UI
:
360 case PPD_NESTED_OPEN_UI
:
361 _cupsLangPuts(stdout
,
362 _(" REF: Pages 42-45, section "
365 case PPD_BAD_ORDER_DEPENDENCY
:
366 _cupsLangPuts(stdout
,
367 _(" REF: Pages 48-49, section "
370 case PPD_BAD_UI_CONSTRAINTS
:
371 _cupsLangPuts(stdout
,
372 _(" REF: Pages 52-54, section "
375 case PPD_MISSING_ASTERISK
:
376 _cupsLangPuts(stdout
,
377 _(" REF: Page 15, section "
380 case PPD_LINE_TOO_LONG
:
381 _cupsLangPuts(stdout
,
382 _(" REF: Page 15, section "
385 case PPD_ILLEGAL_CHARACTER
:
386 _cupsLangPuts(stdout
,
387 _(" REF: Page 15, section "
390 case PPD_ILLEGAL_MAIN_KEYWORD
:
391 _cupsLangPuts(stdout
,
392 _(" REF: Pages 16-17, section "
395 case PPD_ILLEGAL_OPTION_KEYWORD
:
396 _cupsLangPuts(stdout
,
397 _(" REF: Page 19, section "
400 case PPD_ILLEGAL_TRANSLATION
:
401 _cupsLangPuts(stdout
,
402 _(" REF: Page 27, section "
409 check_basics(argv
[i
]);
417 * Show the header and then perform basic conformance tests (limited
418 * only by what the CUPS PPD functions actually load...)
425 _cupsLangPuts(stdout
,
426 _("\n DETAILED CONFORMANCE TEST RESULTS"));
428 if ((attr
= ppdFindAttr(ppd
, "FormatVersion", NULL
)) != NULL
&&
430 ppdversion
= (int)(10 * _cupsStrScand(attr
->value
, NULL
, loc
) + 0.5);
432 if ((attr
= ppdFindAttr(ppd
, "cupsFilter2", NULL
)) != NULL
)
436 if (strstr(attr
->value
, "application/vnd.cups-raster"))
438 if (!test_raster(ppd
, verbose
))
443 while ((attr
= ppdFindNextAttr(ppd
, "cupsFilter2", NULL
)) != NULL
);
447 for (j
= 0; j
< ppd
->num_filters
; j
++)
448 if (strstr(ppd
->filters
[j
], "application/vnd.cups-raster"))
450 if (!test_raster(ppd
, verbose
))
457 * Look for default keywords with no matching option...
460 if (!(warn
& WARN_DEFAULTS
))
461 errors
= check_defaults(ppd
, errors
, verbose
, 0);
463 if ((attr
= ppdFindAttr(ppd
, "DefaultImageableArea", NULL
)) == NULL
)
467 if (!errors
&& !verbose
)
468 _cupsLangPuts(stdout
, _(" FAIL"));
470 _cupsLangPuts(stdout
,
471 _(" **FAIL** REQUIRED DefaultImageableArea\n"
472 " REF: Page 102, section 5.15."));
477 else if (ppdPageSize(ppd
, attr
->value
) == NULL
&&
478 strcmp(attr
->value
, "Unknown"))
482 if (!errors
&& !verbose
)
483 _cupsLangPuts(stdout
, _(" FAIL"));
485 _cupsLangPrintf(stdout
,
486 _(" **FAIL** Bad DefaultImageableArea %s\n"
487 " REF: Page 102, section 5.15."),
496 _cupsLangPuts(stdout
, _(" PASS DefaultImageableArea"));
499 if ((attr
= ppdFindAttr(ppd
, "DefaultPaperDimension", NULL
)) == NULL
)
503 if (!errors
&& !verbose
)
504 _cupsLangPuts(stdout
, _(" FAIL"));
506 _cupsLangPuts(stdout
,
507 _(" **FAIL** REQUIRED DefaultPaperDimension\n"
508 " REF: Page 103, section 5.15."));
513 else if (ppdPageSize(ppd
, attr
->value
) == NULL
&&
514 strcmp(attr
->value
, "Unknown"))
518 if (!errors
&& !verbose
)
519 _cupsLangPuts(stdout
, _(" FAIL"));
521 _cupsLangPrintf(stdout
,
522 _(" **FAIL** Bad DefaultPaperDimension %s\n"
523 " REF: Page 103, section 5.15."),
529 else if (verbose
> 0)
530 _cupsLangPuts(stdout
, _(" PASS DefaultPaperDimension"));
532 for (j
= 0, group
= ppd
->groups
; j
< ppd
->num_groups
; j
++, group
++)
533 for (k
= 0, option
= group
->options
;
534 k
< group
->num_options
;
538 * Verify that we have a default choice...
541 if (option
->defchoice
[0])
543 if (ppdFindChoice(option
, option
->defchoice
) == NULL
&&
544 strcmp(option
->defchoice
, "Unknown"))
548 if (!errors
&& !verbose
)
549 _cupsLangPuts(stdout
, _(" FAIL"));
551 _cupsLangPrintf(stdout
,
552 _(" **FAIL** Bad Default%s %s\n"
553 " REF: Page 40, section 4.5."),
554 option
->keyword
, option
->defchoice
);
559 else if (verbose
> 0)
560 _cupsLangPrintf(stdout
,
561 _(" PASS Default%s"),
568 if (!errors
&& !verbose
)
569 _cupsLangPuts(stdout
, _(" FAIL"));
571 _cupsLangPrintf(stdout
,
572 _(" **FAIL** REQUIRED Default%s\n"
573 " REF: Page 40, section 4.5."),
581 if ((attr
= ppdFindAttr(ppd
, "FileVersion", NULL
)) != NULL
)
583 for (ptr
= attr
->value
; *ptr
; ptr
++)
584 if (!isdigit(*ptr
& 255) && *ptr
!= '.')
591 if (!errors
&& !verbose
)
592 _cupsLangPuts(stdout
, _(" FAIL"));
594 _cupsLangPrintf(stdout
,
595 _(" **FAIL** Bad FileVersion \"%s\"\n"
596 " REF: Page 56, section 5.3."),
602 else if (verbose
> 0)
603 _cupsLangPuts(stdout
, _(" PASS FileVersion"));
609 if (!errors
&& !verbose
)
610 _cupsLangPuts(stdout
, _(" FAIL"));
612 _cupsLangPuts(stdout
,
613 _(" **FAIL** REQUIRED FileVersion\n"
614 " REF: Page 56, section 5.3."));
620 if ((attr
= ppdFindAttr(ppd
, "FormatVersion", NULL
)) != NULL
)
623 if (*ptr
== '4' && ptr
[1] == '.')
626 for (ptr
+= 2; *ptr
; ptr
++)
627 if (!isdigit(*ptr
& 255))
635 if (!errors
&& !verbose
)
636 _cupsLangPuts(stdout
, _(" FAIL"));
638 _cupsLangPrintf(stdout
,
639 _(" **FAIL** Bad FormatVersion \"%s\"\n"
640 " REF: Page 56, section 5.3."),
646 else if (verbose
> 0)
647 _cupsLangPuts(stdout
, _(" PASS FormatVersion"));
653 if (!errors
&& !verbose
)
654 _cupsLangPuts(stdout
, _(" FAIL"));
656 _cupsLangPuts(stdout
,
657 _(" **FAIL** REQUIRED FormatVersion\n"
658 " REF: Page 56, section 5.3."));
664 if (ppd
->lang_encoding
!= NULL
)
667 _cupsLangPuts(stdout
, _(" PASS LanguageEncoding"));
669 else if (ppdversion
> 40)
673 if (!errors
&& !verbose
)
674 _cupsLangPuts(stdout
, _(" FAIL"));
676 _cupsLangPuts(stdout
,
677 _(" **FAIL** REQUIRED LanguageEncoding\n"
678 " REF: Pages 56-57, section 5.3."));
684 if (ppd
->lang_version
!= NULL
)
687 _cupsLangPuts(stdout
, _(" PASS LanguageVersion"));
693 if (!errors
&& !verbose
)
694 _cupsLangPuts(stdout
, _(" FAIL"));
696 _cupsLangPuts(stdout
,
697 _(" **FAIL** REQUIRED LanguageVersion\n"
698 " REF: Pages 57-58, section 5.3."));
704 if (ppd
->manufacturer
!= NULL
)
706 if (!_cups_strncasecmp(ppd
->manufacturer
, "Hewlett-Packard", 15) ||
707 !_cups_strncasecmp(ppd
->manufacturer
, "Hewlett Packard", 15))
711 if (!errors
&& !verbose
)
712 _cupsLangPuts(stdout
, _(" FAIL"));
714 _cupsLangPrintf(stdout
,
715 _(" **FAIL** Bad Manufacturer (should be "
717 " REF: Page 211, table D.1."),
723 else if (!_cups_strncasecmp(ppd
->manufacturer
, "OkiData", 7) ||
724 !_cups_strncasecmp(ppd
->manufacturer
, "Oki Data", 8))
728 if (!errors
&& !verbose
)
729 _cupsLangPuts(stdout
, _(" FAIL"));
731 _cupsLangPrintf(stdout
,
732 _(" **FAIL** Bad Manufacturer (should be "
734 " REF: Page 211, table D.1."),
740 else if (verbose
> 0)
741 _cupsLangPuts(stdout
, _(" PASS Manufacturer"));
743 else if (ppdversion
>= 43)
747 if (!errors
&& !verbose
)
748 _cupsLangPuts(stdout
, _(" FAIL"));
750 _cupsLangPuts(stdout
,
751 _(" **FAIL** REQUIRED Manufacturer\n"
752 " REF: Pages 58-59, section 5.3."));
758 if (ppd
->modelname
!= NULL
)
760 for (ptr
= ppd
->modelname
; *ptr
; ptr
++)
761 if (!isalnum(*ptr
& 255) && !strchr(" ./-+", *ptr
))
768 if (!errors
&& !verbose
)
769 _cupsLangPuts(stdout
, _(" FAIL"));
771 _cupsLangPrintf(stdout
,
772 _(" **FAIL** Bad ModelName - \"%c\" not "
773 "allowed in string.\n"
774 " REF: Pages 59-60, section 5.3."),
780 else if (verbose
> 0)
781 _cupsLangPuts(stdout
, _(" PASS ModelName"));
787 if (!errors
&& !verbose
)
788 _cupsLangPuts(stdout
, _(" FAIL"));
790 _cupsLangPuts(stdout
,
791 _(" **FAIL** REQUIRED ModelName\n"
792 " REF: Pages 59-60, section 5.3."));
798 if (ppd
->nickname
!= NULL
)
801 _cupsLangPuts(stdout
, _(" PASS NickName"));
807 if (!errors
&& !verbose
)
808 _cupsLangPuts(stdout
, _(" FAIL"));
810 _cupsLangPuts(stdout
,
811 _(" **FAIL** REQUIRED NickName\n"
812 " REF: Page 60, section 5.3."));
818 if (ppdFindOption(ppd
, "PageSize") != NULL
)
821 _cupsLangPuts(stdout
, _(" PASS PageSize"));
827 if (!errors
&& !verbose
)
828 _cupsLangPuts(stdout
, _(" FAIL"));
830 _cupsLangPuts(stdout
,
831 _(" **FAIL** REQUIRED PageSize\n"
832 " REF: Pages 99-100, section 5.14."));
838 if (ppdFindOption(ppd
, "PageRegion") != NULL
)
841 _cupsLangPuts(stdout
, _(" PASS PageRegion"));
847 if (!errors
&& !verbose
)
848 _cupsLangPuts(stdout
, _(" FAIL"));
850 _cupsLangPuts(stdout
,
851 _(" **FAIL** REQUIRED PageRegion\n"
852 " REF: Page 100, section 5.14."));
858 if (ppd
->pcfilename
!= NULL
)
861 _cupsLangPuts(stdout
, _(" PASS PCFileName"));
863 else if (!(ignore
& WARN_FILENAME
))
867 if (!errors
&& !verbose
)
868 _cupsLangPuts(stdout
, _(" FAIL"));
870 _cupsLangPuts(stdout
,
871 _(" **FAIL** REQUIRED PCFileName\n"
872 " REF: Pages 61-62, section 5.3."));
878 if (ppd
->product
!= NULL
)
880 if (ppd
->product
[0] != '(' ||
881 ppd
->product
[strlen(ppd
->product
) - 1] != ')')
885 if (!errors
&& !verbose
)
886 _cupsLangPuts(stdout
, _(" FAIL"));
888 _cupsLangPuts(stdout
,
889 _(" **FAIL** Bad Product - not \"(string)\".\n"
890 " REF: Page 62, section 5.3."));
895 else if (verbose
> 0)
896 _cupsLangPuts(stdout
, _(" PASS Product"));
902 if (!errors
&& !verbose
)
903 _cupsLangPuts(stdout
, _(" FAIL"));
905 _cupsLangPuts(stdout
,
906 _(" **FAIL** REQUIRED Product\n"
907 " REF: Page 62, section 5.3."));
913 if ((attr
= ppdFindAttr(ppd
, "PSVersion", NULL
)) != NULL
&&
916 char junkstr
[255]; /* Temp string */
917 int junkint
; /* Temp integer */
920 if (sscanf(attr
->value
, "(%254[^)\n])%d", junkstr
, &junkint
) != 2)
924 if (!errors
&& !verbose
)
925 _cupsLangPuts(stdout
, _(" FAIL"));
927 _cupsLangPuts(stdout
,
928 _(" **FAIL** Bad PSVersion - not \"(string) "
930 " REF: Pages 62-64, section 5.3."));
935 else if (verbose
> 0)
936 _cupsLangPuts(stdout
, _(" PASS PSVersion"));
942 if (!errors
&& !verbose
)
943 _cupsLangPuts(stdout
, _(" FAIL"));
945 _cupsLangPuts(stdout
,
946 _(" **FAIL** REQUIRED PSVersion\n"
947 " REF: Pages 62-64, section 5.3."));
953 if (ppd
->shortnickname
!= NULL
)
955 if (strlen(ppd
->shortnickname
) > 31)
959 if (!errors
&& !verbose
)
960 _cupsLangPuts(stdout
, _(" FAIL"));
962 _cupsLangPuts(stdout
,
963 _(" **FAIL** Bad ShortNickName - longer "
965 " REF: Pages 64-65, section 5.3."));
970 else if (verbose
> 0)
971 _cupsLangPuts(stdout
, _(" PASS ShortNickName"));
973 else if (ppdversion
>= 43)
977 if (!errors
&& !verbose
)
978 _cupsLangPuts(stdout
, _(" FAIL"));
980 _cupsLangPuts(stdout
,
981 _(" **FAIL** REQUIRED ShortNickName\n"
982 " REF: Page 64-65, section 5.3."));
988 if (ppd
->patches
!= NULL
&& strchr(ppd
->patches
, '\"') &&
989 strstr(ppd
->patches
, "*End"))
993 if (!errors
&& !verbose
)
994 _cupsLangPuts(stdout
, _(" FAIL"));
996 _cupsLangPuts(stdout
,
997 _(" **FAIL** Bad JobPatchFile attribute in file\n"
998 " REF: Page 24, section 3.4."));
1005 * Check for page sizes without the corresponding ImageableArea or
1006 * PaperDimension values...
1009 if (ppd
->num_sizes
== 0)
1013 if (!errors
&& !verbose
)
1014 _cupsLangPuts(stdout
, _(" FAIL"));
1016 _cupsLangPuts(stdout
,
1017 _(" **FAIL** REQUIRED PageSize\n"
1018 " REF: Page 41, section 5.\n"
1019 " REF: Page 99, section 5.14."));
1026 for (j
= 0, size
= ppd
->sizes
; j
< ppd
->num_sizes
; j
++, size
++)
1029 * Don't check custom size...
1032 if (!strcmp(size
->name
, "Custom"))
1036 * Check for ImageableArea...
1039 if (size
->left
== 0.0 && size
->bottom
== 0.0 &&
1040 size
->right
== 0.0 && size
->top
== 0.0)
1044 if (!errors
&& !verbose
)
1045 _cupsLangPuts(stdout
, _(" FAIL"));
1047 _cupsLangPrintf(stdout
,
1048 _(" **FAIL** REQUIRED ImageableArea for "
1050 " REF: Page 41, section 5.\n"
1051 " REF: Page 102, section 5.15."),
1059 * Check for PaperDimension...
1062 if (size
->width
<= 0.0 && size
->length
<= 0.0)
1066 if (!errors
&& !verbose
)
1067 _cupsLangPuts(stdout
, _(" FAIL"));
1069 _cupsLangPrintf(stdout
,
1070 _(" **FAIL** REQUIRED PaperDimension "
1072 " REF: Page 41, section 5.\n"
1073 " REF: Page 103, section 5.15."),
1083 * Check for valid Resolution, JCLResolution, or SetResolution values...
1086 if ((option
= ppdFindOption(ppd
, "Resolution")) == NULL
)
1087 if ((option
= ppdFindOption(ppd
, "JCLResolution")) == NULL
)
1088 option
= ppdFindOption(ppd
, "SetResolution");
1092 for (j
= option
->num_choices
, choice
= option
->choices
;
1097 * Verify that all resolution options are of the form NNNdpi
1101 xdpi
= strtol(choice
->choice
, (char **)&ptr
, 10);
1102 if (ptr
> choice
->choice
&& xdpi
> 0)
1105 ydpi
= strtol(ptr
+ 1, (char **)&ptr
, 10);
1112 if (xdpi
<= 0 || xdpi
> 99999 || ydpi
<= 0 || ydpi
> 99999 ||
1117 if (!errors
&& !verbose
)
1118 _cupsLangPuts(stdout
, _(" FAIL"));
1120 _cupsLangPrintf(stdout
,
1121 _(" **FAIL** Bad option %s choice %s\n"
1122 " REF: Page 84, section 5.9"),
1123 option
->keyword
, choice
->choice
);
1131 if ((attr
= ppdFindAttr(ppd
, "1284DeviceID", NULL
)) &&
1132 strcmp(attr
->name
, "1284DeviceID"))
1136 if (!errors
&& !verbose
)
1137 _cupsLangPuts(stdout
, _(" FAIL"));
1139 _cupsLangPrintf(stdout
,
1140 _(" **FAIL** %s must be 1284DeviceID\n"
1141 " REF: Page 72, section 5.5"),
1148 errors
= check_case(ppd
, errors
, verbose
);
1150 if (!(warn
& WARN_CONSTRAINTS
))
1151 errors
= check_constraints(ppd
, errors
, verbose
, 0);
1153 if (!(warn
& WARN_FILTERS
) && !(ignore
& WARN_FILTERS
))
1154 errors
= check_filters(ppd
, root
, errors
, verbose
, 0);
1156 if (!(warn
& WARN_PROFILES
) && !(ignore
& WARN_PROFILES
))
1157 errors
= check_profiles(ppd
, root
, errors
, verbose
, 0);
1159 if (!(warn
& WARN_SIZES
))
1160 errors
= check_sizes(ppd
, errors
, verbose
, 0);
1162 if (!(warn
& WARN_TRANSLATIONS
))
1163 errors
= check_translations(ppd
, errors
, verbose
, 0);
1165 if (!(warn
& WARN_DUPLEX
))
1166 errors
= check_duplex(ppd
, errors
, verbose
, 0);
1168 if ((attr
= ppdFindAttr(ppd
, "cupsLanguages", NULL
)) != NULL
&&
1172 * This file contains localizations, check for conformance of the
1173 * base translation...
1176 if ((attr
= ppdFindAttr(ppd
, "LanguageEncoding", NULL
)) != NULL
)
1178 if (!attr
->value
|| strcmp(attr
->value
, "ISOLatin1"))
1180 if (!errors
&& !verbose
)
1181 _cupsLangPuts(stdout
, _(" FAIL"));
1184 _cupsLangPrintf(stdout
,
1185 _(" **FAIL** Bad LanguageEncoding %s - "
1186 "must be ISOLatin1."),
1187 attr
->value
? attr
->value
: "(null)");
1192 if (!ppd
->lang_version
|| strcmp(ppd
->lang_version
, "English"))
1194 if (!errors
&& !verbose
)
1195 _cupsLangPuts(stdout
, _(" FAIL"));
1198 _cupsLangPrintf(stdout
,
1199 _(" **FAIL** Bad LanguageVersion %s - "
1200 "must be English."),
1201 ppd
->lang_version
? ppd
->lang_version
: "(null)");
1207 * Loop through all options and choices...
1210 for (option
= ppdFirstOption(ppd
);
1212 option
= ppdNextOption(ppd
))
1215 * Check for special characters outside A0 to BF, F7, or F8
1216 * that are used for languages other than English.
1219 for (ptr
= option
->text
; *ptr
; ptr
++)
1220 if ((*ptr
& 0x80) && (*ptr
& 0xe0) != 0xa0 &&
1221 (*ptr
& 0xff) != 0xf7 && (*ptr
& 0xff) != 0xf8)
1226 if (!errors
&& !verbose
)
1227 _cupsLangPuts(stdout
, _(" FAIL"));
1230 _cupsLangPrintf(stdout
,
1231 _(" **FAIL** Default translation "
1232 "string for option %s contains 8-bit "
1239 for (j
= 0; j
< option
->num_choices
; j
++)
1242 * Check for special characters outside A0 to BF, F7, or F8
1243 * that are used for languages other than English.
1246 for (ptr
= option
->choices
[j
].text
; *ptr
; ptr
++)
1247 if ((*ptr
& 0x80) && (*ptr
& 0xe0) != 0xa0 &&
1248 (*ptr
& 0xff) != 0xf7 && (*ptr
& 0xff) != 0xf8)
1253 if (!errors
&& !verbose
)
1254 _cupsLangPuts(stdout
, _(" FAIL"));
1257 _cupsLangPrintf(stdout
,
1258 _(" **FAIL** Default translation "
1259 "string for option %s choice %s contains "
1260 "8-bit characters."),
1262 option
->choices
[j
].choice
);
1272 * Final pass/fail notification...
1276 status
= ERROR_CONFORMANCE
;
1278 _cupsLangPuts(stdout
, _(" PASS"));
1282 check_basics(argv
[i
]);
1284 if (warn
& WARN_DEFAULTS
)
1285 errors
= check_defaults(ppd
, errors
, verbose
, 1);
1287 if (warn
& WARN_CONSTRAINTS
)
1288 errors
= check_constraints(ppd
, errors
, verbose
, 1);
1290 if ((warn
& WARN_FILTERS
) && !(ignore
& WARN_FILTERS
))
1291 errors
= check_filters(ppd
, root
, errors
, verbose
, 1);
1293 if ((warn
& WARN_PROFILES
) && !(ignore
& WARN_PROFILES
))
1294 errors
= check_profiles(ppd
, root
, errors
, verbose
, 1);
1296 if (warn
& WARN_SIZES
)
1297 errors
= check_sizes(ppd
, errors
, verbose
, 1);
1299 errors
= check_sizes(ppd
, errors
, verbose
, 2);
1301 if (warn
& WARN_TRANSLATIONS
)
1302 errors
= check_translations(ppd
, errors
, verbose
, 1);
1304 if (warn
& WARN_DUPLEX
)
1305 errors
= check_duplex(ppd
, errors
, verbose
, 1);
1308 * Look for legacy duplex keywords...
1311 if ((option
= ppdFindOption(ppd
, "JCLDuplex")) == NULL
)
1312 if ((option
= ppdFindOption(ppd
, "EFDuplex")) == NULL
)
1313 option
= ppdFindOption(ppd
, "KD03Duplex");
1316 _cupsLangPrintf(stdout
,
1317 _(" WARN Duplex option keyword %s may not "
1318 "work as expected and should be named Duplex.\n"
1319 " REF: Page 122, section 5.17"),
1323 * Look for default keywords with no corresponding option...
1326 for (j
= 0; j
< ppd
->num_attrs
; j
++)
1328 attr
= ppd
->attrs
[j
];
1330 if (!strcmp(attr
->name
, "DefaultColorSpace") ||
1331 !strcmp(attr
->name
, "DefaultColorSep") ||
1332 !strcmp(attr
->name
, "DefaultFont") ||
1333 !strcmp(attr
->name
, "DefaultHalftoneType") ||
1334 !strcmp(attr
->name
, "DefaultImageableArea") ||
1335 !strcmp(attr
->name
, "DefaultLeadingEdge") ||
1336 !strcmp(attr
->name
, "DefaultOutputOrder") ||
1337 !strcmp(attr
->name
, "DefaultPaperDimension") ||
1338 !strcmp(attr
->name
, "DefaultResolution") ||
1339 !strcmp(attr
->name
, "DefaultScreenProc") ||
1340 !strcmp(attr
->name
, "DefaultTransfer"))
1343 if (!strncmp(attr
->name
, "Default", 7) &&
1344 !ppdFindOption(ppd
, attr
->name
+ 7))
1345 _cupsLangPrintf(stdout
,
1346 _(" WARN %s has no corresponding "
1351 if (ppdversion
< 43)
1353 _cupsLangPrintf(stdout
,
1354 _(" WARN Obsolete PPD version %.1f.\n"
1355 " REF: Page 42, section 5.2."),
1359 if (!ppd
->lang_encoding
&& ppdversion
< 41)
1361 _cupsLangPuts(stdout
,
1362 _(" WARN LanguageEncoding required by PPD "
1364 " REF: Pages 56-57, section 5.3."));
1367 if (!ppd
->manufacturer
&& ppdversion
< 43)
1369 _cupsLangPuts(stdout
,
1370 _(" WARN Manufacturer required by PPD "
1372 " REF: Pages 58-59, section 5.3."));
1376 * Treat a PCFileName attribute longer than 12 characters as
1377 * a warning and not a hard error...
1380 if (!(ignore
& WARN_FILENAME
) && ppd
->pcfilename
)
1382 if (strlen(ppd
->pcfilename
) > 12)
1384 _cupsLangPuts(stdout
,
1385 _(" WARN PCFileName longer than 8.3 in "
1386 "violation of PPD spec.\n"
1387 " REF: Pages 61-62, section "
1391 if (!_cups_strcasecmp(ppd
->pcfilename
, "unused.ppd"))
1392 _cupsLangPuts(stdout
,
1393 _(" WARN PCFileName should contain a "
1394 "unique filename.\n"
1395 " REF: Pages 61-62, section "
1399 if (!ppd
->shortnickname
&& ppdversion
< 43)
1401 _cupsLangPuts(stdout
,
1402 _(" WARN ShortNickName required by PPD "
1404 " REF: Pages 64-65, section 5.3."));
1408 * Check the Protocols line and flag PJL + BCP since TBCP is
1409 * usually used with PJL...
1414 if (strstr(ppd
->protocols
, "PJL") &&
1415 strstr(ppd
->protocols
, "BCP") &&
1416 !strstr(ppd
->protocols
, "TBCP"))
1418 _cupsLangPuts(stdout
,
1419 _(" WARN Protocols contains both PJL "
1420 "and BCP; expected TBCP.\n"
1421 " REF: Pages 78-79, section 5.7."));
1424 if (strstr(ppd
->protocols
, "PJL") &&
1425 (!ppd
->jcl_begin
|| !ppd
->jcl_end
|| !ppd
->jcl_ps
))
1427 _cupsLangPuts(stdout
,
1428 _(" WARN Protocols contains PJL but JCL "
1429 "attributes are not set.\n"
1430 " REF: Pages 78-79, section 5.7."));
1435 * Check for options with a common prefix, e.g. Duplex and Duplexer,
1436 * which are errors according to the spec but won't cause problems
1437 * with CUPS specifically...
1440 for (j
= 0, group
= ppd
->groups
; j
< ppd
->num_groups
; j
++, group
++)
1441 for (k
= 0, option
= group
->options
;
1442 k
< group
->num_options
;
1445 len
= strlen(option
->keyword
);
1447 for (m
= 0, group2
= ppd
->groups
;
1448 m
< ppd
->num_groups
;
1450 for (n
= 0, option2
= group2
->options
;
1451 n
< group2
->num_options
;
1453 if (option
!= option2
&&
1454 len
< strlen(option2
->keyword
) &&
1455 !strncmp(option
->keyword
, option2
->keyword
, len
))
1457 _cupsLangPrintf(stdout
,
1458 _(" WARN %s shares a common "
1460 " REF: Page 15, section "
1462 option
->keyword
, option2
->keyword
);
1470 _cupsLangPrintf(stdout
, _(" %d ERRORS FOUND"), errors
);
1472 _cupsLangPuts(stdout
, _(" NO ERRORS FOUND"));
1476 * Then list the options, if "-v" was provided...
1481 _cupsLangPrintf(stdout
,
1483 " language_level = %d\n"
1484 " color_device = %s\n"
1485 " variable_sizes = %s\n"
1487 ppd
->language_level
,
1488 ppd
->color_device
? "TRUE" : "FALSE",
1489 ppd
->variable_sizes
? "TRUE" : "FALSE",
1492 switch (ppd
->colorspace
)
1495 _cupsLangPuts(stdout
, " colorspace = PPD_CS_CMYK");
1498 _cupsLangPuts(stdout
, " colorspace = PPD_CS_CMY");
1501 _cupsLangPuts(stdout
, " colorspace = PPD_CS_GRAY");
1504 _cupsLangPuts(stdout
, " colorspace = PPD_CS_RGB");
1507 _cupsLangPuts(stdout
, " colorspace = <unknown>");
1511 _cupsLangPrintf(stdout
, " num_emulations = %d",
1512 ppd
->num_emulations
);
1513 for (j
= 0; j
< ppd
->num_emulations
; j
++)
1514 _cupsLangPrintf(stdout
, " emulations[%d] = %s",
1515 j
, ppd
->emulations
[j
].name
);
1517 _cupsLangPrintf(stdout
, " lang_encoding = %s",
1518 ppd
->lang_encoding
);
1519 _cupsLangPrintf(stdout
, " lang_version = %s",
1521 _cupsLangPrintf(stdout
, " modelname = %s", ppd
->modelname
);
1522 _cupsLangPrintf(stdout
, " ttrasterizer = %s",
1523 ppd
->ttrasterizer
== NULL
? "None" : ppd
->ttrasterizer
);
1524 _cupsLangPrintf(stdout
, " manufacturer = %s",
1526 _cupsLangPrintf(stdout
, " product = %s", ppd
->product
);
1527 _cupsLangPrintf(stdout
, " nickname = %s", ppd
->nickname
);
1528 _cupsLangPrintf(stdout
, " shortnickname = %s",
1529 ppd
->shortnickname
);
1530 _cupsLangPrintf(stdout
, " patches = %d bytes",
1531 ppd
->patches
== NULL
? 0 : (int)strlen(ppd
->patches
));
1533 _cupsLangPrintf(stdout
, " num_groups = %d", ppd
->num_groups
);
1534 for (j
= 0, group
= ppd
->groups
; j
< ppd
->num_groups
; j
++, group
++)
1536 _cupsLangPrintf(stdout
, " group[%d] = %s",
1539 for (k
= 0, option
= group
->options
; k
< group
->num_options
; k
++, option
++)
1541 _cupsLangPrintf(stdout
,
1542 " options[%d] = %s (%s) %s %s %.0f "
1544 k
, option
->keyword
, option
->text
, uis
[option
->ui
],
1545 sections
[option
->section
], option
->order
,
1546 option
->num_choices
);
1548 if (!strcmp(option
->keyword
, "PageSize") ||
1549 !strcmp(option
->keyword
, "PageRegion"))
1551 for (m
= option
->num_choices
, choice
= option
->choices
;
1555 size
= ppdPageSize(ppd
, choice
->choice
);
1558 _cupsLangPrintf(stdout
,
1559 " %s (%s) = ERROR%s",
1560 choice
->choice
, choice
->text
,
1561 !strcmp(option
->defchoice
, choice
->choice
)
1564 _cupsLangPrintf(stdout
,
1565 " %s (%s) = %.2fx%.2fin "
1566 "(%.1f,%.1f,%.1f,%.1f)%s",
1567 choice
->choice
, choice
->text
,
1568 size
->width
/ 72.0, size
->length
/ 72.0,
1569 size
->left
/ 72.0, size
->bottom
/ 72.0,
1570 size
->right
/ 72.0, size
->top
/ 72.0,
1571 !strcmp(option
->defchoice
, choice
->choice
)
1577 for (m
= option
->num_choices
, choice
= option
->choices
;
1581 _cupsLangPrintf(stdout
, " %s (%s)%s",
1582 choice
->choice
, choice
->text
,
1583 !strcmp(option
->defchoice
, choice
->choice
)
1590 _cupsLangPrintf(stdout
, " num_consts = %d",
1592 for (j
= 0; j
< ppd
->num_consts
; j
++)
1593 _cupsLangPrintf(stdout
,
1594 " consts[%d] = *%s %s *%s %s",
1595 j
, ppd
->consts
[j
].option1
, ppd
->consts
[j
].choice1
,
1596 ppd
->consts
[j
].option2
, ppd
->consts
[j
].choice2
);
1598 _cupsLangPrintf(stdout
, " num_profiles = %d",
1600 for (j
= 0; j
< ppd
->num_profiles
; j
++)
1601 _cupsLangPrintf(stdout
,
1602 " profiles[%d] = %s/%s %.3f %.3f "
1603 "[ %.3f %.3f %.3f %.3f %.3f %.3f %.3f %.3f %.3f ]",
1604 j
, ppd
->profiles
[j
].resolution
,
1605 ppd
->profiles
[j
].media_type
,
1606 ppd
->profiles
[j
].gamma
, ppd
->profiles
[j
].density
,
1607 ppd
->profiles
[j
].matrix
[0][0],
1608 ppd
->profiles
[j
].matrix
[0][1],
1609 ppd
->profiles
[j
].matrix
[0][2],
1610 ppd
->profiles
[j
].matrix
[1][0],
1611 ppd
->profiles
[j
].matrix
[1][1],
1612 ppd
->profiles
[j
].matrix
[1][2],
1613 ppd
->profiles
[j
].matrix
[2][0],
1614 ppd
->profiles
[j
].matrix
[2][1],
1615 ppd
->profiles
[j
].matrix
[2][2]);
1617 _cupsLangPrintf(stdout
, " num_fonts = %d", ppd
->num_fonts
);
1618 for (j
= 0; j
< ppd
->num_fonts
; j
++)
1619 _cupsLangPrintf(stdout
, " fonts[%d] = %s",
1622 _cupsLangPrintf(stdout
, " num_attrs = %d", ppd
->num_attrs
);
1623 for (j
= 0; j
< ppd
->num_attrs
; j
++)
1624 _cupsLangPrintf(stdout
,
1625 " attrs[%d] = %s %s%s%s: \"%s\"", j
,
1626 ppd
->attrs
[j
]->name
, ppd
->attrs
[j
]->spec
,
1627 ppd
->attrs
[j
]->text
[0] ? "/" : "",
1628 ppd
->attrs
[j
]->text
,
1629 ppd
->attrs
[j
]->value
?
1630 ppd
->attrs
[j
]->value
: "(null)");
1644 * 'check_basics()' - Check for CR LF, mixed line endings, and blank lines.
1648 check_basics(const char *filename
) /* I - PPD file to check */
1650 cups_file_t
*fp
; /* File pointer */
1651 int ch
; /* Current character */
1652 int col
, /* Current column */
1653 whitespace
; /* Only seen whitespace? */
1654 int eol
; /* Line endings */
1655 int linenum
; /* Line number */
1656 int mixed
; /* Mixed line endings? */
1659 if ((fp
= cupsFileOpen(filename
, "r")) == NULL
)
1668 while ((ch
= cupsFileGetChar(fp
)) != EOF
)
1670 if (ch
== '\r' || ch
== '\n')
1674 if (eol
== EOL_NONE
)
1676 else if (eol
!= EOL_LF
)
1679 else if (ch
== '\r')
1681 if (cupsFilePeekChar(fp
) == '\n')
1683 cupsFileGetChar(fp
);
1685 if (eol
== EOL_NONE
)
1687 else if (eol
!= EOL_CRLF
)
1690 else if (eol
== EOL_NONE
)
1692 else if (eol
!= EOL_CR
)
1696 if (col
> 0 && whitespace
)
1697 _cupsLangPrintf(stdout
,
1698 _(" WARN Line %d only contains whitespace."),
1707 if (ch
!= ' ' && ch
!= '\t')
1715 _cupsLangPuts(stdout
,
1716 _(" WARN File contains a mix of CR, LF, and "
1717 "CR LF line endings."));
1719 if (eol
== EOL_CRLF
)
1720 _cupsLangPuts(stdout
,
1721 _(" WARN Non-Windows PPD files should use lines "
1722 "ending with only LF, not CR LF."));
1729 * 'check_constraints()' - Check UIConstraints in the PPD file.
1732 static int /* O - Errors found */
1733 check_constraints(ppd_file_t
*ppd
, /* I - PPD file */
1734 int errors
, /* I - Errors found */
1735 int verbose
, /* I - Verbosity level */
1736 int warn
) /* I - Warnings only? */
1738 int i
; /* Looping var */
1739 const char *prefix
; /* WARN/FAIL prefix */
1740 ppd_const_t
*c
; /* Current UIConstraints data */
1741 ppd_attr_t
*constattr
; /* Current cupsUIConstraints attribute */
1742 const char *vptr
; /* Pointer into constraint value */
1743 char option
[PPD_MAX_NAME
],
1744 /* Option name/MainKeyword */
1745 choice
[PPD_MAX_NAME
],
1746 /* Choice/OptionKeyword */
1747 *ptr
; /* Pointer into option or choice */
1748 int num_options
; /* Number of options */
1749 cups_option_t
*options
; /* Options */
1750 ppd_option_t
*o
; /* PPD option */
1753 prefix
= warn
? " WARN " : "**FAIL**";
1757 * See what kind of constraint data we have in the PPD...
1760 if ((constattr
= ppdFindAttr(ppd
, "cupsUIConstraints", NULL
)) != NULL
)
1763 * Check new-style cupsUIConstraints data...
1767 constattr
= ppdFindNextAttr(ppd
, "cupsUIConstraints", NULL
))
1769 if (!constattr
->value
)
1771 if (!warn
&& !errors
&& !verbose
)
1772 _cupsLangPuts(stdout
, _(" FAIL"));
1774 _cupsLangPrintf(stdout
,
1775 _(" %s Empty cupsUIConstraints %s"),
1776 prefix
, constattr
->spec
);
1784 for (i
= 0, vptr
= strchr(constattr
->value
, '*');
1786 i
++, vptr
= strchr(vptr
+ 1, '*'));
1790 if (!warn
&& !errors
&& !verbose
)
1791 _cupsLangPuts(stdout
, _(" FAIL"));
1793 _cupsLangPrintf(stdout
,
1794 _(" %s Bad cupsUIConstraints %s: \"%s\""),
1795 prefix
, constattr
->spec
, constattr
->value
);
1803 cupsArraySave(ppd
->sorted_attrs
);
1805 if (constattr
->spec
[0] &&
1806 !ppdFindAttr(ppd
, "cupsUIResolver", constattr
->spec
))
1808 if (!warn
&& !errors
&& !verbose
)
1809 _cupsLangPuts(stdout
, _(" FAIL"));
1811 _cupsLangPrintf(stdout
,
1812 _(" %s Missing cupsUIResolver %s"),
1813 prefix
, constattr
->spec
);
1819 cupsArrayRestore(ppd
->sorted_attrs
);
1824 for (vptr
= strchr(constattr
->value
, '*');
1826 vptr
= strchr(vptr
, '*'))
1829 * Extract "*Option Choice" or just "*Option"...
1832 for (vptr
++, ptr
= option
; *vptr
&& !isspace(*vptr
& 255); vptr
++)
1833 if (ptr
< (option
+ sizeof(option
) - 1))
1838 while (isspace(*vptr
& 255))
1845 for (ptr
= choice
; *vptr
&& !isspace(*vptr
& 255); vptr
++)
1846 if (ptr
< (choice
+ sizeof(choice
) - 1))
1852 if (!_cups_strncasecmp(option
, "Custom", 6) && !_cups_strcasecmp(choice
, "True"))
1854 _cups_strcpy(option
, option
+ 6);
1855 strlcpy(choice
, "Custom", sizeof(choice
));
1858 if ((o
= ppdFindOption(ppd
, option
)) == NULL
)
1860 if (!warn
&& !errors
&& !verbose
)
1861 _cupsLangPuts(stdout
, _(" FAIL"));
1863 _cupsLangPrintf(stdout
,
1864 _(" %s Missing option %s in "
1865 "cupsUIConstraints %s: \"%s\""),
1866 prefix
, option
, constattr
->spec
, constattr
->value
);
1874 if (choice
[0] && !ppdFindChoice(o
, choice
))
1876 if (!warn
&& !errors
&& !verbose
)
1877 _cupsLangPuts(stdout
, _(" FAIL"));
1879 _cupsLangPrintf(stdout
,
1880 _(" %s Missing choice *%s %s in "
1881 "cupsUIConstraints %s: \"%s\""),
1882 prefix
, option
, choice
, constattr
->spec
,
1892 num_options
= cupsAddOption(option
, choice
, num_options
, &options
);
1895 for (i
= 0; i
< o
->num_choices
; i
++)
1896 if (_cups_strcasecmp(o
->choices
[i
].choice
, "None") &&
1897 _cups_strcasecmp(o
->choices
[i
].choice
, "Off") &&
1898 _cups_strcasecmp(o
->choices
[i
].choice
, "False"))
1900 num_options
= cupsAddOption(option
, o
->choices
[i
].choice
,
1901 num_options
, &options
);
1908 * Resolvers must list at least two options...
1911 if (num_options
< 2)
1913 if (!warn
&& !errors
&& !verbose
)
1914 _cupsLangPuts(stdout
, _(" FAIL"));
1916 _cupsLangPrintf(stdout
,
1917 _(" %s cupsUIResolver %s does not list at least "
1918 "two different options."),
1919 prefix
, constattr
->spec
);
1926 * Test the resolver...
1929 if (!cupsResolveConflicts(ppd
, NULL
, NULL
, &num_options
, &options
))
1931 if (!warn
&& !errors
&& !verbose
)
1932 _cupsLangPuts(stdout
, _(" FAIL"));
1934 _cupsLangPrintf(stdout
,
1935 _(" %s cupsUIResolver %s causes a loop."),
1936 prefix
, constattr
->spec
);
1942 cupsFreeOptions(num_options
, options
);
1948 * Check old-style [Non]UIConstraints data...
1951 for (i
= ppd
->num_consts
, c
= ppd
->consts
; i
> 0; i
--, c
++)
1953 if (!_cups_strncasecmp(c
->option1
, "Custom", 6) &&
1954 !_cups_strcasecmp(c
->choice1
, "True"))
1956 strlcpy(option
, c
->option1
+ 6, sizeof(option
));
1957 strlcpy(choice
, "Custom", sizeof(choice
));
1961 strlcpy(option
, c
->option1
, sizeof(option
));
1962 strlcpy(choice
, c
->choice1
, sizeof(choice
));
1965 if ((o
= ppdFindOption(ppd
, option
)) == NULL
)
1967 if (!warn
&& !errors
&& !verbose
)
1968 _cupsLangPuts(stdout
, _(" FAIL"));
1970 _cupsLangPrintf(stdout
,
1971 _(" %s Missing option %s in "
1972 "UIConstraints \"*%s %s *%s %s\"."),
1974 c
->option1
, c
->choice1
, c
->option2
, c
->choice2
);
1979 else if (choice
[0] && !ppdFindChoice(o
, choice
))
1981 if (!warn
&& !errors
&& !verbose
)
1982 _cupsLangPuts(stdout
, _(" FAIL"));
1984 _cupsLangPrintf(stdout
,
1985 _(" %s Missing choice *%s %s in "
1986 "UIConstraints \"*%s %s *%s %s\"."),
1987 prefix
, c
->option1
, c
->choice1
,
1988 c
->option1
, c
->choice1
, c
->option2
, c
->choice2
);
1994 if (!_cups_strncasecmp(c
->option2
, "Custom", 6) &&
1995 !_cups_strcasecmp(c
->choice2
, "True"))
1997 strlcpy(option
, c
->option2
+ 6, sizeof(option
));
1998 strlcpy(choice
, "Custom", sizeof(choice
));
2002 strlcpy(option
, c
->option2
, sizeof(option
));
2003 strlcpy(choice
, c
->choice2
, sizeof(choice
));
2006 if ((o
= ppdFindOption(ppd
, option
)) == NULL
)
2008 if (!warn
&& !errors
&& !verbose
)
2009 _cupsLangPuts(stdout
, _(" FAIL"));
2011 _cupsLangPrintf(stdout
,
2012 _(" %s Missing option %s in "
2013 "UIConstraints \"*%s %s *%s %s\"."),
2015 c
->option1
, c
->choice1
, c
->option2
, c
->choice2
);
2020 else if (choice
[0] && !ppdFindChoice(o
, choice
))
2022 if (!warn
&& !errors
&& !verbose
)
2023 _cupsLangPuts(stdout
, _(" FAIL"));
2025 _cupsLangPrintf(stdout
,
2026 _(" %s Missing choice *%s %s in "
2027 "UIConstraints \"*%s %s *%s %s\"."),
2028 prefix
, c
->option2
, c
->choice2
,
2029 c
->option1
, c
->choice1
, c
->option2
, c
->choice2
);
2042 * 'check_case()' - Check that there are no duplicate groups, options,
2043 * or choices that differ only by case.
2046 static int /* O - Errors found */
2047 check_case(ppd_file_t
*ppd
, /* I - PPD file */
2048 int errors
, /* I - Errors found */
2049 int verbose
) /* I - Verbosity level */
2051 int i
, j
; /* Looping vars */
2052 ppd_group_t
*groupa
, /* First group */
2053 *groupb
; /* Second group */
2054 ppd_option_t
*optiona
, /* First option */
2055 *optionb
; /* Second option */
2056 ppd_choice_t
*choicea
, /* First choice */
2057 *choiceb
; /* Second choice */
2061 * Check that the groups do not have any duplicate names...
2064 for (i
= ppd
->num_groups
, groupa
= ppd
->groups
; i
> 1; i
--, groupa
++)
2065 for (j
= i
- 1, groupb
= groupa
+ 1; j
> 0; j
--, groupb
++)
2066 if (!_cups_strcasecmp(groupa
->name
, groupb
->name
))
2068 if (!errors
&& !verbose
)
2069 _cupsLangPuts(stdout
, _(" FAIL"));
2072 _cupsLangPrintf(stdout
,
2073 _(" **FAIL** Group names %s and %s differ only "
2075 groupa
->name
, groupb
->name
);
2081 * Check that the options do not have any duplicate names...
2084 for (optiona
= ppdFirstOption(ppd
); optiona
; optiona
= ppdNextOption(ppd
))
2086 cupsArraySave(ppd
->options
);
2087 for (optionb
= ppdNextOption(ppd
); optionb
; optionb
= ppdNextOption(ppd
))
2088 if (!_cups_strcasecmp(optiona
->keyword
, optionb
->keyword
))
2090 if (!errors
&& !verbose
)
2091 _cupsLangPuts(stdout
, _(" FAIL"));
2094 _cupsLangPrintf(stdout
,
2095 _(" **FAIL** Option names %s and %s differ only "
2097 optiona
->keyword
, optionb
->keyword
);
2101 cupsArrayRestore(ppd
->options
);
2104 * Then the choices...
2107 for (i
= optiona
->num_choices
, choicea
= optiona
->choices
;
2110 for (j
= i
- 1, choiceb
= choicea
+ 1; j
> 0; j
--, choiceb
++)
2111 if (!strcmp(choicea
->choice
, choiceb
->choice
))
2113 if (!errors
&& !verbose
)
2114 _cupsLangPuts(stdout
, _(" FAIL"));
2117 _cupsLangPrintf(stdout
,
2118 _(" **FAIL** Multiple occurrences of "
2119 "option %s choice name %s."),
2120 optiona
->keyword
, choicea
->choice
);
2128 else if (!_cups_strcasecmp(choicea
->choice
, choiceb
->choice
))
2130 if (!errors
&& !verbose
)
2131 _cupsLangPuts(stdout
, _(" FAIL"));
2134 _cupsLangPrintf(stdout
,
2135 _(" **FAIL** Option %s choice names %s and "
2136 "%s differ only by case."),
2137 optiona
->keyword
, choicea
->choice
, choiceb
->choice
);
2144 * Return the number of errors found...
2152 * 'check_defaults()' - Check default option keywords in the PPD file.
2155 static int /* O - Errors found */
2156 check_defaults(ppd_file_t
*ppd
, /* I - PPD file */
2157 int errors
, /* I - Errors found */
2158 int verbose
, /* I - Verbosity level */
2159 int warn
) /* I - Warnings only? */
2161 int j
, k
; /* Looping vars */
2162 ppd_attr_t
*attr
; /* PPD attribute */
2163 ppd_option_t
*option
; /* Standard UI option */
2164 const char *prefix
; /* WARN/FAIL prefix */
2167 prefix
= warn
? " WARN " : "**FAIL**";
2169 ppdMarkDefaults(ppd
);
2170 if (ppdConflicts(ppd
))
2172 if (!warn
&& !errors
&& !verbose
)
2173 _cupsLangPuts(stdout
, _(" FAIL"));
2176 _cupsLangPrintf(stdout
,
2177 _(" %s Default choices conflicting."), prefix
);
2179 show_conflicts(ppd
, prefix
);
2185 for (j
= 0; j
< ppd
->num_attrs
; j
++)
2187 attr
= ppd
->attrs
[j
];
2189 if (!strcmp(attr
->name
, "DefaultColorSpace") ||
2190 !strcmp(attr
->name
, "DefaultFont") ||
2191 !strcmp(attr
->name
, "DefaultHalftoneType") ||
2192 !strcmp(attr
->name
, "DefaultImageableArea") ||
2193 !strcmp(attr
->name
, "DefaultLeadingEdge") ||
2194 !strcmp(attr
->name
, "DefaultOutputOrder") ||
2195 !strcmp(attr
->name
, "DefaultPaperDimension") ||
2196 !strcmp(attr
->name
, "DefaultResolution") ||
2197 !strcmp(attr
->name
, "DefaultTransfer"))
2200 if (!strncmp(attr
->name
, "Default", 7))
2202 if ((option
= ppdFindOption(ppd
, attr
->name
+ 7)) != NULL
&&
2203 strcmp(attr
->value
, "Unknown"))
2206 * Check that the default option value matches a choice...
2209 for (k
= 0; k
< option
->num_choices
; k
++)
2210 if (!strcmp(option
->choices
[k
].choice
, attr
->value
))
2213 if (k
>= option
->num_choices
)
2215 if (!warn
&& !errors
&& !verbose
)
2216 _cupsLangPuts(stdout
, _(" FAIL"));
2219 _cupsLangPrintf(stdout
,
2220 _(" %s %s %s does not exist."),
2221 prefix
, attr
->name
, attr
->value
);
2235 * 'check_duplex()' - Check duplex keywords in the PPD file.
2238 static int /* O - Errors found */
2239 check_duplex(ppd_file_t
*ppd
, /* I - PPD file */
2240 int errors
, /* I - Error found */
2241 int verbose
, /* I - Verbosity level */
2242 int warn
) /* I - Warnings only? */
2244 int i
; /* Looping var */
2245 ppd_option_t
*option
; /* PPD option */
2246 ppd_choice_t
*choice
; /* Current choice */
2247 const char *prefix
; /* Message prefix */
2250 prefix
= warn
? " WARN " : "**FAIL**";
2253 * Check for a duplex option, and for standard values...
2256 if ((option
= ppdFindOption(ppd
, "Duplex")) != NULL
)
2258 if (!ppdFindChoice(option
, "None"))
2262 if (!warn
&& !errors
&& !verbose
)
2263 _cupsLangPuts(stdout
, _(" FAIL"));
2265 _cupsLangPrintf(stdout
,
2266 _(" %s REQUIRED %s does not define "
2268 " REF: Page 122, section 5.17"),
2269 prefix
, option
->keyword
);
2276 for (i
= option
->num_choices
, choice
= option
->choices
;
2279 if (strcmp(choice
->choice
, "None") &&
2280 strcmp(choice
->choice
, "DuplexNoTumble") &&
2281 strcmp(choice
->choice
, "DuplexTumble") &&
2282 strcmp(choice
->choice
, "SimplexTumble"))
2286 if (!warn
&& !errors
&& !verbose
)
2287 _cupsLangPuts(stdout
, _(" FAIL"));
2289 _cupsLangPrintf(stdout
,
2290 _(" %s Bad %s choice %s.\n"
2291 " REF: Page 122, section 5.17"),
2292 prefix
, option
->keyword
, choice
->choice
);
2305 * 'check_filters()' - Check filters in the PPD file.
2308 static int /* O - Errors found */
2309 check_filters(ppd_file_t
*ppd
, /* I - PPD file */
2310 const char *root
, /* I - Root directory */
2311 int errors
, /* I - Errors found */
2312 int verbose
, /* I - Verbosity level */
2313 int warn
) /* I - Warnings only? */
2315 ppd_attr_t
*attr
; /* PPD attribute */
2316 const char *ptr
; /* Pointer into string */
2317 char super
[16], /* Super-type for filter */
2318 type
[256], /* Type for filter */
2319 dstsuper
[16], /* Destination super-type for filter */
2320 dsttype
[256], /* Destination type for filter */
2321 program
[1024], /* Program/filter name */
2322 pathprog
[1024]; /* Complete path to program/filter */
2323 int cost
; /* Cost of filter */
2324 const char *prefix
; /* WARN/FAIL prefix */
2325 struct stat fileinfo
; /* File information */
2328 prefix
= warn
? " WARN " : "**FAIL**";
2334 for (attr
= ppdFindAttr(ppd
, "cupsFilter", NULL
);
2336 attr
= ppdFindNextAttr(ppd
, "cupsFilter", NULL
))
2338 if (strcmp(attr
->name
, "cupsFilter"))
2340 if (!warn
&& !errors
&& !verbose
)
2341 _cupsLangPuts(stdout
, _(" FAIL"));
2344 _cupsLangPrintf(stdout
,
2345 _(" %s Bad spelling of %s - should be %s."),
2346 prefix
, attr
->name
, "cupsFilter");
2353 sscanf(attr
->value
, "%15[^/]/%255s%d%*[ \t]%1023[^\n]", super
, type
,
2354 &cost
, program
) != 4)
2356 if (!warn
&& !errors
&& !verbose
)
2357 _cupsLangPuts(stdout
, _(" FAIL"));
2360 _cupsLangPrintf(stdout
,
2361 _(" %s Bad cupsFilter value \"%s\"."),
2362 prefix
, attr
->value
);
2370 if (!strncmp(program
, "maxsize(", 8))
2372 char *mptr
; /* Pointer into maxsize(nnnn) program */
2374 strtoll(program
+ 8, &mptr
, 10);
2378 if (!warn
&& !errors
&& !verbose
)
2379 _cupsLangPuts(stdout
, _(" FAIL"));
2382 _cupsLangPrintf(stdout
,
2383 _(" %s Bad cupsFilter value \"%s\"."),
2384 prefix
, attr
->value
);
2393 while (_cups_isspace(*mptr
))
2396 _cups_strcpy(program
, mptr
);
2399 if (strcmp(program
, "-"))
2401 if (program
[0] == '/')
2402 snprintf(pathprog
, sizeof(pathprog
), "%s%s", root
, program
);
2405 if ((ptr
= getenv("CUPS_SERVERBIN")) == NULL
)
2406 ptr
= CUPS_SERVERBIN
;
2408 if (*ptr
== '/' || !*root
)
2409 snprintf(pathprog
, sizeof(pathprog
), "%s%s/filter/%s", root
, ptr
,
2412 snprintf(pathprog
, sizeof(pathprog
), "%s/%s/filter/%s", root
, ptr
,
2416 if (stat(pathprog
, &fileinfo
))
2418 if (!warn
&& !errors
&& !verbose
)
2419 _cupsLangPuts(stdout
, _(" FAIL"));
2422 _cupsLangPrintf(stdout
, _(" %s Missing %s file \"%s\"."),
2423 prefix
, "cupsFilter", pathprog
);
2428 else if (fileinfo
.st_uid
!= 0 ||
2429 (fileinfo
.st_mode
& MODE_WRITE
) ||
2430 (fileinfo
.st_mode
& MODE_MASK
) != MODE_PROGRAM
)
2432 if (!warn
&& !errors
&& !verbose
)
2433 _cupsLangPuts(stdout
, _(" FAIL"));
2436 _cupsLangPrintf(stdout
,
2437 _(" %s Bad permissions on %s file \"%s\"."),
2438 prefix
, "cupsFilter", pathprog
);
2444 errors
= valid_path("cupsFilter", pathprog
, errors
, verbose
, warn
);
2452 for (attr
= ppdFindAttr(ppd
, "cupsFilter2", NULL
);
2454 attr
= ppdFindNextAttr(ppd
, "cupsFilter2", NULL
))
2456 if (strcmp(attr
->name
, "cupsFilter2"))
2458 if (!warn
&& !errors
&& !verbose
)
2459 _cupsLangPuts(stdout
, _(" FAIL"));
2462 _cupsLangPrintf(stdout
,
2463 _(" %s Bad spelling of %s - should be %s."),
2464 prefix
, attr
->name
, "cupsFilter2");
2471 sscanf(attr
->value
, "%15[^/]/%255s%*[ \t]%15[^/]/%255s%d%*[ \t]%1023[^\n]",
2472 super
, type
, dstsuper
, dsttype
, &cost
, program
) != 6)
2474 if (!warn
&& !errors
&& !verbose
)
2475 _cupsLangPuts(stdout
, _(" FAIL"));
2478 _cupsLangPrintf(stdout
,
2479 _(" %s Bad cupsFilter2 value \"%s\"."),
2480 prefix
, attr
->value
);
2488 if (!strncmp(program
, "maxsize(", 8))
2490 char *mptr
; /* Pointer into maxsize(nnnn) program */
2492 strtoll(program
+ 8, &mptr
, 10);
2496 if (!warn
&& !errors
&& !verbose
)
2497 _cupsLangPuts(stdout
, _(" FAIL"));
2500 _cupsLangPrintf(stdout
,
2501 _(" %s Bad cupsFilter2 value \"%s\"."),
2502 prefix
, attr
->value
);
2511 while (_cups_isspace(*mptr
))
2514 _cups_strcpy(program
, mptr
);
2517 if (strcmp(program
, "-"))
2519 if (strncmp(program
, "maxsize(", 8) &&
2520 (ptr
= strchr(program
+ 8, ')')) != NULL
)
2523 while (_cups_isspace(*ptr
))
2526 _cups_strcpy(program
, ptr
);
2529 if (program
[0] == '/')
2530 snprintf(pathprog
, sizeof(pathprog
), "%s%s", root
, program
);
2533 if ((ptr
= getenv("CUPS_SERVERBIN")) == NULL
)
2534 ptr
= CUPS_SERVERBIN
;
2536 if (*ptr
== '/' || !*root
)
2537 snprintf(pathprog
, sizeof(pathprog
), "%s%s/filter/%s", root
, ptr
,
2540 snprintf(pathprog
, sizeof(pathprog
), "%s/%s/filter/%s", root
, ptr
,
2544 if (stat(pathprog
, &fileinfo
))
2546 if (!warn
&& !errors
&& !verbose
)
2547 _cupsLangPuts(stdout
, _(" FAIL"));
2550 _cupsLangPrintf(stdout
, _(" %s Missing %s file \"%s\"."),
2551 prefix
, "cupsFilter2", pathprog
);
2556 else if (fileinfo
.st_uid
!= 0 ||
2557 (fileinfo
.st_mode
& MODE_WRITE
) ||
2558 (fileinfo
.st_mode
& MODE_MASK
) != MODE_PROGRAM
)
2560 if (!warn
&& !errors
&& !verbose
)
2561 _cupsLangPuts(stdout
, _(" FAIL"));
2564 _cupsLangPrintf(stdout
,
2565 _(" %s Bad permissions on %s file \"%s\"."),
2566 prefix
, "cupsFilter2", pathprog
);
2572 errors
= valid_path("cupsFilter2", pathprog
, errors
, verbose
, warn
);
2580 for (attr
= ppdFindAttr(ppd
, "cupsPreFilter", NULL
);
2582 attr
= ppdFindNextAttr(ppd
, "cupsPreFilter", NULL
))
2584 if (strcmp(attr
->name
, "cupsPreFilter"))
2586 if (!warn
&& !errors
&& !verbose
)
2587 _cupsLangPuts(stdout
, _(" FAIL"));
2590 _cupsLangPrintf(stdout
,
2591 _(" %s Bad spelling of %s - should be %s."),
2592 prefix
, attr
->name
, "cupsPreFilter");
2599 sscanf(attr
->value
, "%15[^/]/%255s%d%*[ \t]%1023[^\n]", super
, type
,
2600 &cost
, program
) != 4)
2602 if (!warn
&& !errors
&& !verbose
)
2603 _cupsLangPuts(stdout
, _(" FAIL"));
2606 _cupsLangPrintf(stdout
,
2607 _(" %s Bad cupsPreFilter value \"%s\"."),
2608 prefix
, attr
->value
? attr
->value
: "");
2613 else if (strcmp(program
, "-"))
2615 if (program
[0] == '/')
2616 snprintf(pathprog
, sizeof(pathprog
), "%s%s", root
, program
);
2619 if ((ptr
= getenv("CUPS_SERVERBIN")) == NULL
)
2620 ptr
= CUPS_SERVERBIN
;
2622 if (*ptr
== '/' || !*root
)
2623 snprintf(pathprog
, sizeof(pathprog
), "%s%s/filter/%s", root
, ptr
,
2626 snprintf(pathprog
, sizeof(pathprog
), "%s/%s/filter/%s", root
, ptr
,
2630 if (stat(pathprog
, &fileinfo
))
2632 if (!warn
&& !errors
&& !verbose
)
2633 _cupsLangPuts(stdout
, _(" FAIL"));
2636 _cupsLangPrintf(stdout
, _(" %s Missing %s file \"%s\"."),
2637 prefix
, "cupsPreFilter", pathprog
);
2642 else if (fileinfo
.st_uid
!= 0 ||
2643 (fileinfo
.st_mode
& MODE_WRITE
) ||
2644 (fileinfo
.st_mode
& MODE_MASK
) != MODE_PROGRAM
)
2646 if (!warn
&& !errors
&& !verbose
)
2647 _cupsLangPuts(stdout
, _(" FAIL"));
2650 _cupsLangPrintf(stdout
,
2651 _(" %s Bad permissions on %s file \"%s\"."),
2652 prefix
, "cupsPreFilter", pathprog
);
2658 errors
= valid_path("cupsPreFilter", pathprog
, errors
, verbose
, warn
);
2667 for (attr
= ppdFindAttr(ppd
, "APDialogExtension", NULL
);
2669 attr
= ppdFindNextAttr(ppd
, "APDialogExtension", NULL
))
2671 if (strcmp(attr
->name
, "APDialogExtension"))
2673 if (!warn
&& !errors
&& !verbose
)
2674 _cupsLangPuts(stdout
, _(" FAIL"));
2677 _cupsLangPrintf(stdout
,
2678 _(" %s Bad spelling of %s - should be %s."),
2679 prefix
, attr
->name
, "APDialogExtension");
2685 snprintf(pathprog
, sizeof(pathprog
), "%s%s", root
,
2686 attr
->value
? attr
->value
: "(null)");
2688 if (!attr
->value
|| stat(pathprog
, &fileinfo
))
2690 if (!warn
&& !errors
&& !verbose
)
2691 _cupsLangPuts(stdout
, _(" FAIL"));
2694 _cupsLangPrintf(stdout
, _(" %s Missing %s file \"%s\"."),
2695 prefix
, "APDialogExtension", pathprog
);
2700 else if (fileinfo
.st_uid
!= 0 ||
2701 (fileinfo
.st_mode
& MODE_WRITE
) ||
2702 (fileinfo
.st_mode
& MODE_MASK
) != MODE_DIRECTORY
)
2704 if (!warn
&& !errors
&& !verbose
)
2705 _cupsLangPuts(stdout
, _(" FAIL"));
2708 _cupsLangPrintf(stdout
,
2709 _(" %s Bad permissions on %s file \"%s\"."),
2710 prefix
, "APDialogExtension", pathprog
);
2716 errors
= valid_path("APDialogExtension", pathprog
, errors
, verbose
,
2724 if ((attr
= ppdFindAttr(ppd
, "APPrinterIconPath", NULL
)) != NULL
)
2726 if (strcmp(attr
->name
, "APPrinterIconPath"))
2728 if (!warn
&& !errors
&& !verbose
)
2729 _cupsLangPuts(stdout
, _(" FAIL"));
2732 _cupsLangPrintf(stdout
,
2733 _(" %s Bad spelling of %s - should be %s."),
2734 prefix
, attr
->name
, "APPrinterIconPath");
2740 snprintf(pathprog
, sizeof(pathprog
), "%s%s", root
,
2741 attr
->value
? attr
->value
: "(null)");
2743 if (!attr
->value
|| stat(pathprog
, &fileinfo
))
2745 if (!warn
&& !errors
&& !verbose
)
2746 _cupsLangPuts(stdout
, _(" FAIL"));
2749 _cupsLangPrintf(stdout
, _(" %s Missing %s file \"%s\"."),
2750 prefix
, "APPrinterIconPath", pathprog
);
2755 else if (fileinfo
.st_uid
!= 0 ||
2756 (fileinfo
.st_mode
& MODE_WRITE
) ||
2757 (fileinfo
.st_mode
& MODE_MASK
) != MODE_DATAFILE
)
2759 if (!warn
&& !errors
&& !verbose
)
2760 _cupsLangPuts(stdout
, _(" FAIL"));
2763 _cupsLangPrintf(stdout
,
2764 _(" %s Bad permissions on %s file \"%s\"."),
2765 prefix
, "APPrinterIconPath", pathprog
);
2771 errors
= valid_path("APPrinterIconPath", pathprog
, errors
, verbose
,
2776 * APPrinterLowInkTool
2779 if ((attr
= ppdFindAttr(ppd
, "APPrinterLowInkTool", NULL
)) != NULL
)
2781 if (strcmp(attr
->name
, "APPrinterLowInkTool"))
2783 if (!warn
&& !errors
&& !verbose
)
2784 _cupsLangPuts(stdout
, _(" FAIL"));
2787 _cupsLangPrintf(stdout
,
2788 _(" %s Bad spelling of %s - should be %s."),
2789 prefix
, attr
->name
, "APPrinterLowInkTool");
2795 snprintf(pathprog
, sizeof(pathprog
), "%s%s", root
,
2796 attr
->value
? attr
->value
: "(null)");
2798 if (!attr
->value
|| stat(pathprog
, &fileinfo
))
2800 if (!warn
&& !errors
&& !verbose
)
2801 _cupsLangPuts(stdout
, _(" FAIL"));
2804 _cupsLangPrintf(stdout
, _(" %s Missing %s file \"%s\"."),
2805 prefix
, "APPrinterLowInkTool", pathprog
);
2810 else if (fileinfo
.st_uid
!= 0 ||
2811 (fileinfo
.st_mode
& MODE_WRITE
) ||
2812 (fileinfo
.st_mode
& MODE_MASK
) != MODE_DIRECTORY
)
2814 if (!warn
&& !errors
&& !verbose
)
2815 _cupsLangPuts(stdout
, _(" FAIL"));
2818 _cupsLangPrintf(stdout
,
2819 _(" %s Bad permissions on %s file \"%s\"."),
2820 prefix
, "APPrinterLowInkTool", pathprog
);
2826 errors
= valid_path("APPrinterLowInkTool", pathprog
, errors
, verbose
,
2831 * APPrinterUtilityPath
2834 if ((attr
= ppdFindAttr(ppd
, "APPrinterUtilityPath", NULL
)) != NULL
)
2836 if (strcmp(attr
->name
, "APPrinterUtilityPath"))
2838 if (!warn
&& !errors
&& !verbose
)
2839 _cupsLangPuts(stdout
, _(" FAIL"));
2842 _cupsLangPrintf(stdout
,
2843 _(" %s Bad spelling of %s - should be %s."),
2844 prefix
, attr
->name
, "APPrinterUtilityPath");
2850 snprintf(pathprog
, sizeof(pathprog
), "%s%s", root
,
2851 attr
->value
? attr
->value
: "(null)");
2853 if (!attr
->value
|| stat(pathprog
, &fileinfo
))
2855 if (!warn
&& !errors
&& !verbose
)
2856 _cupsLangPuts(stdout
, _(" FAIL"));
2859 _cupsLangPrintf(stdout
, _(" %s Missing %s file \"%s\"."),
2860 prefix
, "APPrinterUtilityPath", pathprog
);
2865 else if (fileinfo
.st_uid
!= 0 ||
2866 (fileinfo
.st_mode
& MODE_WRITE
) ||
2867 (fileinfo
.st_mode
& MODE_MASK
) != MODE_DIRECTORY
)
2869 if (!warn
&& !errors
&& !verbose
)
2870 _cupsLangPuts(stdout
, _(" FAIL"));
2873 _cupsLangPrintf(stdout
,
2874 _(" %s Bad permissions on %s file \"%s\"."),
2875 prefix
, "APPrinterUtilityPath", pathprog
);
2881 errors
= valid_path("APPrinterUtilityPath", pathprog
, errors
, verbose
,
2886 * APScanAppBundleID and APScanAppPath
2889 if ((attr
= ppdFindAttr(ppd
, "APScanAppPath", NULL
)) != NULL
)
2891 if (strcmp(attr
->name
, "APScanAppPath"))
2893 if (!warn
&& !errors
&& !verbose
)
2894 _cupsLangPuts(stdout
, _(" FAIL"));
2897 _cupsLangPrintf(stdout
,
2898 _(" %s Bad spelling of %s - should be %s."),
2899 prefix
, attr
->name
, "APScanAppPath");
2905 if (!attr
->value
|| stat(attr
->value
, &fileinfo
))
2907 if (!warn
&& !errors
&& !verbose
)
2908 _cupsLangPuts(stdout
, _(" FAIL"));
2911 _cupsLangPrintf(stdout
, _(" %s Missing %s file \"%s\"."),
2912 prefix
, "APScanAppPath",
2913 attr
->value
? attr
->value
: "<NULL>");
2918 else if (fileinfo
.st_uid
!= 0 ||
2919 (fileinfo
.st_mode
& MODE_WRITE
) ||
2920 (fileinfo
.st_mode
& MODE_MASK
) != MODE_DIRECTORY
)
2922 if (!warn
&& !errors
&& !verbose
)
2923 _cupsLangPuts(stdout
, _(" FAIL"));
2926 _cupsLangPrintf(stdout
,
2927 _(" %s Bad permissions on %s file \"%s\"."),
2928 prefix
, "APScanAppPath", attr
->value
);
2934 errors
= valid_path("APScanAppPath", attr
->value
, errors
, verbose
,
2937 if (ppdFindAttr(ppd
, "APScanAppBundleID", NULL
))
2939 if (!warn
&& !errors
&& !verbose
)
2940 _cupsLangPuts(stdout
, _(" FAIL"));
2943 _cupsLangPrintf(stdout
, _(" %s Cannot provide both "
2944 "APScanAppPath and APScanAppBundleID."),
2951 #endif /* __APPLE__ */
2958 * 'check_profiles()' - Check ICC color profiles in the PPD file.
2961 static int /* O - Errors found */
2962 check_profiles(ppd_file_t
*ppd
, /* I - PPD file */
2963 const char *root
, /* I - Root directory */
2964 int errors
, /* I - Errors found */
2965 int verbose
, /* I - Verbosity level */
2966 int warn
) /* I - Warnings only? */
2968 int i
; /* Looping var */
2969 ppd_attr_t
*attr
; /* PPD attribute */
2970 const char *ptr
; /* Pointer into string */
2971 const char *prefix
; /* WARN/FAIL prefix */
2972 char filename
[1024]; /* Profile filename */
2973 struct stat fileinfo
; /* File information */
2974 int num_profiles
= 0; /* Number of profiles */
2975 unsigned hash
, /* Current hash value */
2976 hashes
[1000]; /* Hash values of profile names */
2977 const char *specs
[1000]; /* Specifiers for profiles */
2980 prefix
= warn
? " WARN " : "**FAIL**";
2982 for (attr
= ppdFindAttr(ppd
, "cupsICCProfile", NULL
);
2984 attr
= ppdFindNextAttr(ppd
, "cupsICCProfile", NULL
))
2987 * Check for valid selector...
2990 for (i
= 0, ptr
= strchr(attr
->spec
, '.'); ptr
; ptr
= strchr(ptr
+ 1, '.'))
2993 if (!attr
->value
|| i
< 2)
2995 if (!warn
&& !errors
&& !verbose
)
2996 _cupsLangPuts(stdout
, _(" FAIL"));
2999 _cupsLangPrintf(stdout
,
3000 _(" %s Bad cupsICCProfile %s."),
3001 prefix
, attr
->spec
);
3010 * Check for valid profile filename...
3013 if (attr
->value
[0] == '/')
3014 snprintf(filename
, sizeof(filename
), "%s%s", root
, attr
->value
);
3017 if ((ptr
= getenv("CUPS_DATADIR")) == NULL
)
3020 if (*ptr
== '/' || !*root
)
3021 snprintf(filename
, sizeof(filename
), "%s%s/profiles/%s", root
, ptr
,
3024 snprintf(filename
, sizeof(filename
), "%s/%s/profiles/%s", root
, ptr
,
3028 if (stat(filename
, &fileinfo
))
3030 if (!warn
&& !errors
&& !verbose
)
3031 _cupsLangPuts(stdout
, _(" FAIL"));
3034 _cupsLangPrintf(stdout
, _(" %s Missing %s file \"%s\"."),
3035 prefix
, "cupsICCProfile", filename
);
3040 else if (fileinfo
.st_uid
!= 0 ||
3041 (fileinfo
.st_mode
& MODE_WRITE
) ||
3042 (fileinfo
.st_mode
& MODE_MASK
) != MODE_DATAFILE
)
3044 if (!warn
&& !errors
&& !verbose
)
3045 _cupsLangPuts(stdout
, _(" FAIL"));
3048 _cupsLangPrintf(stdout
,
3049 _(" %s Bad permissions on %s file \"%s\"."),
3050 prefix
, "cupsICCProfile", filename
);
3056 errors
= valid_path("cupsICCProfile", filename
, errors
, verbose
, warn
);
3059 * Check for hash collisions...
3062 hash
= _ppdHashName(attr
->spec
);
3064 if (num_profiles
> 0)
3066 for (i
= 0; i
< num_profiles
; i
++)
3067 if (hashes
[i
] == hash
)
3070 if (i
< num_profiles
)
3072 if (!warn
&& !errors
&& !verbose
)
3073 _cupsLangPuts(stdout
, _(" FAIL"));
3076 _cupsLangPrintf(stdout
,
3077 _(" %s cupsICCProfile %s hash value "
3078 "collides with %s."), prefix
, attr
->spec
,
3087 * Remember up to 1000 profiles...
3090 if (num_profiles
< 1000)
3092 hashes
[num_profiles
] = hash
;
3093 specs
[num_profiles
] = attr
->spec
;
3103 * 'check_sizes()' - Check media sizes in the PPD file.
3106 static int /* O - Errors found */
3107 check_sizes(ppd_file_t
*ppd
, /* I - PPD file */
3108 int errors
, /* I - Errors found */
3109 int verbose
, /* I - Verbosity level */
3110 int warn
) /* I - Warnings only? */
3112 int i
; /* Looping var */
3113 ppd_size_t
*size
; /* Current size */
3114 int width
, /* Custom width */
3115 length
; /* Custom length */
3116 const char *prefix
; /* WARN/FAIL prefix */
3117 ppd_option_t
*page_size
, /* PageSize option */
3118 *page_region
; /* PageRegion option */
3119 pwg_media_t
*pwg_media
; /* PWG media */
3120 char buf
[PPD_MAX_NAME
]; /* PapeSize name that is supposed to be */
3121 const char *ptr
; /* Pointer into string */
3122 int width_2540ths
, /* PageSize width in 2540ths */
3123 length_2540ths
; /* PageSize length in 2540ths */
3124 int is_ok
; /* Flag for PageSize name verification */
3125 double width_tmp
, /* Width after rounded up */
3126 length_tmp
, /* Length after rounded up */
3127 width_inch
, /* Width in inches */
3128 length_inch
, /* Length in inches */
3129 width_mm
, /* Width in millimeters */
3130 length_mm
; /* Length in millimeters */
3133 prefix
= warn
? " WARN " : "**FAIL**";
3135 if ((page_size
= ppdFindOption(ppd
, "PageSize")) == NULL
&& warn
!= 2)
3137 if (!warn
&& !errors
&& !verbose
)
3138 _cupsLangPuts(stdout
, _(" FAIL"));
3141 _cupsLangPrintf(stdout
,
3142 _(" %s Missing REQUIRED PageSize option.\n"
3143 " REF: Page 99, section 5.14."),
3150 if ((page_region
= ppdFindOption(ppd
, "PageRegion")) == NULL
&& warn
!= 2)
3152 if (!warn
&& !errors
&& !verbose
)
3153 _cupsLangPuts(stdout
, _(" FAIL"));
3156 _cupsLangPrintf(stdout
,
3157 _(" %s Missing REQUIRED PageRegion option.\n"
3158 " REF: Page 100, section 5.14."),
3165 for (i
= ppd
->num_sizes
, size
= ppd
->sizes
; i
> 0; i
--, size
++)
3168 * Check that the size name is standard...
3171 if (!strcmp(size
->name
, "Custom"))
3174 * Skip custom page size...
3180 if (warn
!= 2 && size
->name
[0] == 'w' &&
3181 sscanf(size
->name
, "w%dh%d", &width
, &length
) == 2)
3184 * Validate device-specific size wNNNhNNN should have proper width and
3188 if (fabs(width
- size
->width
) >= 1.0 ||
3189 fabs(length
- size
->length
) >= 1.0)
3191 if (!warn
&& !errors
&& !verbose
)
3192 _cupsLangPuts(stdout
, _(" FAIL"));
3195 _cupsLangPrintf(stdout
,
3196 _(" %s Size \"%s\" has unexpected dimensions "
3198 prefix
, size
->name
, size
->width
, size
->length
);
3206 * Verify that the size is defined for both PageSize and PageRegion...
3209 if (warn
!= 2 && !ppdFindChoice(page_size
, size
->name
))
3211 if (!warn
&& !errors
&& !verbose
)
3212 _cupsLangPuts(stdout
, _(" FAIL"));
3215 _cupsLangPrintf(stdout
,
3216 _(" %s Size \"%s\" defined for %s but not for "
3218 prefix
, size
->name
, "PageRegion", "PageSize");
3223 else if (warn
!= 2 && !ppdFindChoice(page_region
, size
->name
))
3225 if (!warn
&& !errors
&& !verbose
)
3226 _cupsLangPuts(stdout
, _(" FAIL"));
3229 _cupsLangPrintf(stdout
,
3230 _(" %s Size \"%s\" defined for %s but not for "
3232 prefix
, size
->name
, "PageSize", "PageRegion");
3239 * Verify that the size name is Adobe standard name if it's a standard size
3240 * and the dimentional name if it's not a standard size. Suffix should be
3241 * .Fullbleed, etc., or numeric, e.g., Letter, Letter.Fullbleed,
3242 * Letter.Transverse, Letter1, Letter2, 4x8, 55x91mm, 55x91mm.Fullbleed, etc.
3248 width_2540ths
= (size
->length
> size
->width
) ?
3249 PWG_FROM_POINTS(size
->width
) :
3250 PWG_FROM_POINTS(size
->length
);
3251 length_2540ths
= (size
->length
> size
->width
) ?
3252 PWG_FROM_POINTS(size
->length
) :
3253 PWG_FROM_POINTS(size
->width
);
3254 pwg_media
= pwgMediaForSize(width_2540ths
, length_2540ths
);
3257 (abs(pwg_media
->width
- width_2540ths
) > 34 ||
3258 abs(pwg_media
->length
- length_2540ths
) > 34))
3259 pwg_media
= NULL
; /* Only flag matches within a point */
3261 if (pwg_media
&& pwg_media
->ppd
&&
3262 (pwg_media
->ppd
[0] < 'a' || pwg_media
->ppd
[0] > 'z'))
3264 size_t ppdlen
= strlen(pwg_media
->ppd
);
3265 /* Length of standard PPD name */
3267 strlcpy(buf
, pwg_media
->ppd
, sizeof(buf
));
3269 if (strcmp(size
->name
, buf
) && size
->width
> size
->length
)
3271 if (!strcmp(pwg_media
->ppd
, "DoublePostcardRotated"))
3272 strlcpy(buf
, "DoublePostcard", sizeof(buf
));
3273 else if (strstr(size
->name
, ".Transverse"))
3274 snprintf(buf
, sizeof(buf
), "%s.Transverse", pwg_media
->ppd
);
3276 snprintf(buf
, sizeof(buf
), "%sRotated", pwg_media
->ppd
);
3278 ppdlen
= strlen(buf
);
3281 if (size
->left
== 0 && size
->bottom
== 0 &&
3282 size
->right
== size
->width
&& size
->top
== size
->length
)
3284 strlcat(buf
, ".Fullbleed", sizeof(buf
) - strlen(buf
));
3285 if (_cups_strcasecmp(size
->name
, buf
))
3288 * Allow an additional qualifier such as ".WithTab"...
3291 size_t buflen
= strlen(buf
);/* Length of full bleed name */
3293 if (_cups_strncasecmp(size
->name
, buf
, buflen
) ||
3294 size
->name
[buflen
] != '.')
3298 else if (!strncmp(size
->name
, pwg_media
->ppd
, ppdlen
))
3301 * Check for a proper qualifier (number, "Small", or .something)...
3304 ptr
= size
->name
+ ppdlen
;
3306 if (isdigit(*ptr
& 255))
3308 for (ptr
++; *ptr
; ptr
++)
3310 if (!isdigit(*ptr
& 255))
3317 else if (*ptr
!= '.' && *ptr
&& strcmp(ptr
, "Small"))
3323 * Check for EnvSizeName as well...
3326 if (strncmp(pwg_media
->ppd
, "Env", 3) &&
3327 !strncmp(size
->name
, "Env", 3))
3328 snprintf(buf
, sizeof(buf
), "Env%s", pwg_media
->ppd
);
3330 if (strcmp(size
->name
, buf
))
3335 _cupsLangPrintf(stdout
,
3336 _(" %s Size \"%s\" should be the Adobe "
3337 "standard name \"%s\"."),
3338 prefix
, size
->name
, buf
);
3342 width_tmp
= (fabs(size
->width
- ceil(size
->width
)) < 0.1) ?
3343 ceil(size
->width
) : size
->width
;
3344 length_tmp
= (fabs(size
->length
- ceil(size
->length
)) < 0.1) ?
3345 ceil(size
->length
) : size
->length
;
3347 if (fmod(width_tmp
, 9.0) == 0.0 && fmod(length_tmp
, 9.0) == 0.0)
3349 width_inch
= width_tmp
/ 72.0;
3350 length_inch
= length_tmp
/ 72.0;
3352 snprintf(buf
, sizeof(buf
), "%gx%g", width_inch
, length_inch
);
3356 width_mm
= size
->width
/ 72.0 * 25.4;
3357 length_mm
= size
->length
/ 72.0 * 25.4;
3359 snprintf(buf
, sizeof(buf
), "%.0fx%.0fmm", width_mm
, length_mm
);
3362 if (size
->left
== 0 && size
->bottom
== 0 &&
3363 size
->right
== size
->width
&& size
->top
== size
->length
)
3364 strlcat(buf
, ".Fullbleed", sizeof(buf
));
3365 else if (size
->width
> size
->length
)
3366 strlcat(buf
, ".Transverse", sizeof(buf
));
3368 if (_cups_strcasecmp(size
->name
, buf
))
3370 size_t buflen
= strlen(buf
);
3371 /* Length of proposed name */
3373 if (_cups_strncasecmp(size
->name
, buf
, buflen
) ||
3374 (strcmp(size
->name
+ buflen
, "in") &&
3375 size
->name
[buflen
] != '.'))
3377 char altbuf
[PPD_MAX_NAME
];
3378 /* Alternate "wNNNhNNN" name */
3379 size_t altlen
; /* Length of alternate name */
3381 snprintf(altbuf
, sizeof(altbuf
), "w%.0fh%.0f", size
->width
,
3383 altlen
= strlen(altbuf
);
3384 if (_cups_strncasecmp(size
->name
, altbuf
, altlen
) ||
3385 (size
->name
[altlen
] && size
->name
[altlen
] != '.'))
3386 _cupsLangPrintf(stdout
,
3387 _(" %s Size \"%s\" should be \"%s\"."),
3388 prefix
, size
->name
, buf
);
3400 * 'check_translations()' - Check translations in the PPD file.
3403 static int /* O - Errors found */
3404 check_translations(ppd_file_t
*ppd
, /* I - PPD file */
3405 int errors
, /* I - Errors found */
3406 int verbose
, /* I - Verbosity level */
3407 int warn
) /* I - Warnings only? */
3409 int j
; /* Looping var */
3410 ppd_attr_t
*attr
; /* PPD attribute */
3411 cups_array_t
*languages
; /* Array of languages */
3412 int langlen
; /* Length of language */
3413 char *language
, /* Current language */
3414 keyword
[PPD_MAX_NAME
], /* Localization keyword (full) */
3415 llkeyword
[PPD_MAX_NAME
],/* Localization keyword (base) */
3416 ckeyword
[PPD_MAX_NAME
], /* Custom option keyword (full) */
3417 cllkeyword
[PPD_MAX_NAME
];
3418 /* Custom option keyword (base) */
3419 ppd_option_t
*option
; /* Standard UI option */
3420 ppd_coption_t
*coption
; /* Custom option */
3421 ppd_cparam_t
*cparam
; /* Custom parameter */
3422 char ll
[3]; /* Base language */
3423 const char *prefix
; /* WARN/FAIL prefix */
3424 const char *text
; /* Pointer into UI text */
3427 prefix
= warn
? " WARN " : "**FAIL**";
3429 if ((languages
= _ppdGetLanguages(ppd
)) != NULL
)
3432 * This file contains localizations, check them...
3435 for (language
= (char *)cupsArrayFirst(languages
);
3437 language
= (char *)cupsArrayNext(languages
))
3439 langlen
= (int)strlen(language
);
3440 if (langlen
!= 2 && langlen
!= 5)
3442 if (!warn
&& !errors
&& !verbose
)
3443 _cupsLangPuts(stdout
, _(" FAIL"));
3446 _cupsLangPrintf(stdout
,
3447 _(" %s Bad language \"%s\"."),
3456 if (!strcmp(language
, "en"))
3459 strlcpy(ll
, language
, sizeof(ll
));
3462 * Loop through all options and choices...
3465 for (option
= ppdFirstOption(ppd
);
3467 option
= ppdNextOption(ppd
))
3469 if (!strcmp(option
->keyword
, "PageRegion"))
3472 snprintf(keyword
, sizeof(keyword
), "%s.Translation", language
);
3473 snprintf(llkeyword
, sizeof(llkeyword
), "%s.Translation", ll
);
3475 if ((attr
= ppdFindAttr(ppd
, keyword
, option
->keyword
)) == NULL
&&
3476 (attr
= ppdFindAttr(ppd
, llkeyword
, option
->keyword
)) == NULL
)
3478 if (!warn
&& !errors
&& !verbose
)
3479 _cupsLangPuts(stdout
, _(" FAIL"));
3482 _cupsLangPrintf(stdout
,
3483 _(" %s Missing \"%s\" translation "
3484 "string for option %s."),
3485 prefix
, language
, option
->keyword
);
3490 else if (!valid_utf8(attr
->text
))
3492 if (!warn
&& !errors
&& !verbose
)
3493 _cupsLangPuts(stdout
, _(" FAIL"));
3496 _cupsLangPrintf(stdout
,
3497 _(" %s Bad UTF-8 \"%s\" translation "
3498 "string for option %s."),
3499 prefix
, language
, option
->keyword
);
3505 snprintf(keyword
, sizeof(keyword
), "%s.%s", language
,
3507 snprintf(llkeyword
, sizeof(llkeyword
), "%s.%s", ll
,
3510 for (j
= 0; j
< option
->num_choices
; j
++)
3513 * First see if this choice is a number; if so, don't require
3517 for (text
= option
->choices
[j
].text
; *text
; text
++)
3518 if (!strchr("0123456789-+.", *text
))
3525 * Check custom choices differently...
3528 if (!_cups_strcasecmp(option
->choices
[j
].choice
, "Custom") &&
3529 (coption
= ppdFindCustomOption(ppd
,
3530 option
->keyword
)) != NULL
)
3532 snprintf(ckeyword
, sizeof(ckeyword
), "%s.Custom%s",
3533 language
, option
->keyword
);
3535 if ((attr
= ppdFindAttr(ppd
, ckeyword
, "True")) != NULL
&&
3536 !valid_utf8(attr
->text
))
3538 if (!warn
&& !errors
&& !verbose
)
3539 _cupsLangPuts(stdout
, _(" FAIL"));
3542 _cupsLangPrintf(stdout
,
3543 _(" %s Bad UTF-8 \"%s\" "
3544 "translation string for option %s, "
3547 ckeyword
+ 1 + strlen(language
),
3554 if (_cups_strcasecmp(option
->keyword
, "PageSize"))
3556 for (cparam
= (ppd_cparam_t
*)cupsArrayFirst(coption
->params
);
3558 cparam
= (ppd_cparam_t
*)cupsArrayNext(coption
->params
))
3560 snprintf(ckeyword
, sizeof(ckeyword
), "%s.ParamCustom%s",
3561 language
, option
->keyword
);
3562 snprintf(cllkeyword
, sizeof(cllkeyword
), "%s.ParamCustom%s",
3563 ll
, option
->keyword
);
3565 if ((attr
= ppdFindAttr(ppd
, ckeyword
,
3566 cparam
->name
)) == NULL
&&
3567 (attr
= ppdFindAttr(ppd
, cllkeyword
,
3568 cparam
->name
)) == NULL
)
3570 if (!warn
&& !errors
&& !verbose
)
3571 _cupsLangPuts(stdout
, _(" FAIL"));
3574 _cupsLangPrintf(stdout
,
3575 _(" %s Missing \"%s\" "
3576 "translation string for option %s, "
3579 ckeyword
+ 1 + strlen(language
),
3585 else if (!valid_utf8(attr
->text
))
3587 if (!warn
&& !errors
&& !verbose
)
3588 _cupsLangPuts(stdout
, _(" FAIL"));
3591 _cupsLangPrintf(stdout
,
3592 _(" %s Bad UTF-8 \"%s\" "
3593 "translation string for option %s, "
3596 ckeyword
+ 1 + strlen(language
),
3605 else if ((attr
= ppdFindAttr(ppd
, keyword
,
3606 option
->choices
[j
].choice
)) == NULL
&&
3607 (attr
= ppdFindAttr(ppd
, llkeyword
,
3608 option
->choices
[j
].choice
)) == NULL
)
3610 if (!warn
&& !errors
&& !verbose
)
3611 _cupsLangPuts(stdout
, _(" FAIL"));
3614 _cupsLangPrintf(stdout
,
3615 _(" %s Missing \"%s\" "
3616 "translation string for option %s, "
3618 prefix
, language
, option
->keyword
,
3619 option
->choices
[j
].choice
);
3624 else if (!valid_utf8(attr
->text
))
3626 if (!warn
&& !errors
&& !verbose
)
3627 _cupsLangPuts(stdout
, _(" FAIL"));
3630 _cupsLangPrintf(stdout
,
3631 _(" %s Bad UTF-8 \"%s\" "
3632 "translation string for option %s, "
3634 prefix
, language
, option
->keyword
,
3635 option
->choices
[j
].choice
);
3645 * Verify that we have the base language for each localized one...
3648 for (language
= (char *)cupsArrayFirst(languages
);
3650 language
= (char *)cupsArrayNext(languages
))
3654 * Lookup the base language...
3657 cupsArraySave(languages
);
3659 strlcpy(ll
, language
, sizeof(ll
));
3661 if (!cupsArrayFind(languages
, ll
) &&
3662 strcmp(ll
, "zh") && strcmp(ll
, "en"))
3664 if (!warn
&& !errors
&& !verbose
)
3665 _cupsLangPuts(stdout
, _(" FAIL"));
3668 _cupsLangPrintf(stdout
,
3669 _(" %s No base translation \"%s\" "
3670 "is included in file."), prefix
, ll
);
3676 cupsArrayRestore(languages
);
3680 * Free memory used for the languages...
3683 _ppdFreeLanguages(languages
);
3691 * 'show_conflicts()' - Show option conflicts in a PPD file.
3695 show_conflicts(ppd_file_t
*ppd
, /* I - PPD to check */
3696 const char *prefix
) /* I - Prefix string */
3698 int i
, j
; /* Looping variables */
3699 ppd_const_t
*c
; /* Current constraint */
3700 ppd_option_t
*o1
, *o2
; /* Options */
3701 ppd_choice_t
*c1
, *c2
; /* Choices */
3705 * Loop through all of the UI constraints and report any options
3709 for (i
= ppd
->num_consts
, c
= ppd
->consts
; i
> 0; i
--, c
++)
3712 * Grab pointers to the first option...
3715 o1
= ppdFindOption(ppd
, c
->option1
);
3719 else if (c
->choice1
[0] != '\0')
3722 * This constraint maps to a specific choice.
3725 c1
= ppdFindChoice(o1
, c
->choice1
);
3730 * This constraint applies to any choice for this option.
3733 for (j
= o1
->num_choices
, c1
= o1
->choices
; j
> 0; j
--, c1
++)
3738 !_cups_strcasecmp(c1
->choice
, "None") ||
3739 !_cups_strcasecmp(c1
->choice
, "Off") ||
3740 !_cups_strcasecmp(c1
->choice
, "False"))
3745 * Grab pointers to the second option...
3748 o2
= ppdFindOption(ppd
, c
->option2
);
3752 else if (c
->choice2
[0] != '\0')
3755 * This constraint maps to a specific choice.
3758 c2
= ppdFindChoice(o2
, c
->choice2
);
3763 * This constraint applies to any choice for this option.
3766 for (j
= o2
->num_choices
, c2
= o2
->choices
; j
> 0; j
--, c2
++)
3771 !_cups_strcasecmp(c2
->choice
, "None") ||
3772 !_cups_strcasecmp(c2
->choice
, "Off") ||
3773 !_cups_strcasecmp(c2
->choice
, "False"))
3778 * If both options are marked then there is a conflict...
3781 if (c1
!= NULL
&& c1
->marked
&& c2
!= NULL
&& c2
->marked
)
3782 _cupsLangPrintf(stdout
,
3783 _(" %s \"%s %s\" conflicts with \"%s %s\"\n"
3784 " (constraint=\"%s %s %s %s\")."),
3785 prefix
, o1
->keyword
, c1
->choice
, o2
->keyword
, c2
->choice
,
3786 c
->option1
, c
->choice1
, c
->option2
, c
->choice2
);
3792 * 'test_raster()' - Test PostScript commands for raster printers.
3795 static int /* O - 1 on success, 0 on failure */
3796 test_raster(ppd_file_t
*ppd
, /* I - PPD file */
3797 int verbose
) /* I - Verbosity */
3799 cups_page_header2_t header
; /* Page header */
3802 ppdMarkDefaults(ppd
);
3803 if (cupsRasterInterpretPPD(&header
, ppd
, 0, NULL
, 0))
3806 _cupsLangPuts(stdout
, _(" FAIL"));
3809 _cupsLangPrintf(stdout
,
3810 _(" **FAIL** Default option code cannot be "
3811 "interpreted: %s"), cupsRasterErrorString());
3817 * Try a test of custom page size code, if available...
3820 if (!ppdPageSize(ppd
, "Custom.612x792"))
3823 ppdMarkOption(ppd
, "PageSize", "Custom.612x792");
3825 if (cupsRasterInterpretPPD(&header
, ppd
, 0, NULL
, 0))
3828 _cupsLangPuts(stdout
, _(" FAIL"));
3831 _cupsLangPrintf(stdout
,
3832 _(" **FAIL** Default option code cannot be "
3833 "interpreted: %s"), cupsRasterErrorString());
3843 * 'usage()' - Show program usage.
3849 _cupsLangPuts(stdout
, _("Usage: cupstestppd [options] filename1.ppd[.gz] "
3850 "[... filenameN.ppd[.gz]]"));
3851 _cupsLangPuts(stdout
, _(" program | cupstestppd [options] -"));
3852 _cupsLangPuts(stdout
, "");
3853 _cupsLangPuts(stdout
, _("Options:"));
3854 _cupsLangPuts(stdout
, "");
3855 _cupsLangPuts(stdout
, _(" -I {filename,filters,none,profiles}"));
3856 _cupsLangPuts(stdout
, _(" Ignore specific warnings."));
3857 _cupsLangPuts(stdout
, _(" -R root-directory Set alternate root."));
3858 _cupsLangPuts(stdout
, _(" -W {all,none,constraints,defaults,duplex,"
3859 "filters,profiles,sizes,translations}"));
3860 _cupsLangPuts(stdout
, _(" Issue warnings instead of "
3862 _cupsLangPuts(stdout
, _(" -q Run silently."));
3863 _cupsLangPuts(stdout
, _(" -r Use 'relaxed' open mode."));
3864 _cupsLangPuts(stdout
, _(" -v Be verbose."));
3865 _cupsLangPuts(stdout
, _(" -vv Be very verbose."));
3872 * 'valid_path()' - Check whether a path has the correct capitalization.
3875 static int /* O - Errors found */
3876 valid_path(const char *keyword
, /* I - Keyword using path */
3877 const char *path
, /* I - Path to check */
3878 int errors
, /* I - Errors found */
3879 int verbose
, /* I - Verbosity level */
3880 int warn
) /* I - Warnings only? */
3882 cups_dir_t
*dir
; /* Current directory */
3883 cups_dentry_t
*dentry
; /* Current directory entry */
3884 char temp
[1024], /* Temporary path */
3885 *ptr
; /* Pointer into temporary path */
3886 const char *prefix
; /* WARN/FAIL prefix */
3889 prefix
= warn
? " WARN " : "**FAIL**";
3892 * Loop over the components of the path, checking that the entry exists with
3893 * the same capitalization...
3896 strlcpy(temp
, path
, sizeof(temp
));
3898 while ((ptr
= strrchr(temp
, '/')) != NULL
)
3901 * Chop off the trailing component so temp == dirname and ptr == basename.
3907 * Try opening the directory containing the base name...
3911 dir
= cupsDirOpen(temp
);
3913 dir
= cupsDirOpen("/");
3919 while ((dentry
= cupsDirRead(dir
)) != NULL
)
3921 if (!strcmp(dentry
->filename
, ptr
))
3929 * Display an error if the filename doesn't exist with the same
3935 if (!warn
&& !errors
&& !verbose
)
3936 _cupsLangPuts(stdout
, _(" FAIL"));
3939 _cupsLangPrintf(stdout
,
3940 _(" %s %s file \"%s\" has the wrong "
3941 "capitalization."), prefix
, keyword
, path
);
3955 * 'valid_utf8()' - Check whether a string contains valid UTF-8 text.
3958 static int /* O - 1 if valid, 0 if not */
3959 valid_utf8(const char *s
) /* I - String to check */
3966 * Check for valid UTF-8 sequence...
3969 if ((*s
& 0xc0) == 0x80)
3970 return (0); /* Illegal suffix byte */
3971 else if ((*s
& 0xe0) == 0xc0)
3974 * 2-byte sequence...
3979 if ((*s
& 0xc0) != 0x80)
3980 return (0); /* Missing suffix byte */
3982 else if ((*s
& 0xf0) == 0xe0)
3985 * 3-byte sequence...
3990 if ((*s
& 0xc0) != 0x80)
3991 return (0); /* Missing suffix byte */
3995 if ((*s
& 0xc0) != 0x80)
3996 return (0); /* Missing suffix byte */
3998 else if ((*s
& 0xf8) == 0xf0)
4001 * 4-byte sequence...
4006 if ((*s
& 0xc0) != 0x80)
4007 return (0); /* Missing suffix byte */
4011 if ((*s
& 0xc0) != 0x80)
4012 return (0); /* Missing suffix byte */
4016 if ((*s
& 0xc0) != 0x80)
4017 return (0); /* Missing suffix byte */
4020 return (0); /* Bad sequence */