2 * "$Id: cupstestppd.c 7807 2008-07-28 21:54:24Z mike $"
4 * PPD test program for CUPS.
6 * Copyright 2007-2011 by Apple Inc.
7 * Copyright 1997-2007 by Easy Software Products, all rights reserved.
9 * These coded instructions, statements, and computer programs are the
10 * property of Apple Inc. and are protected by Federal copyright
11 * law. Distribution and use rights are outlined in the file "LICENSE.txt"
12 * which should have been included with this file. If this file is
13 * file is missing or damaged, see the license at "http://www.cups.org/".
15 * PostScript is a trademark of Adobe Systems, Inc.
17 * This file is subject to the Apple OS-Developed Software exception.
21 * main() - Main entry for test program.
22 * check_basics() - Check for CR LF, mixed line endings, and blank
24 * check_constraints() - Check UIConstraints in the PPD file.
25 * check_case() - Check that there are no duplicate groups, options,
26 * or choices that differ only by case.
27 * check_defaults() - Check default option keywords in the PPD file.
28 * check_duplex() - Check duplex keywords in the PPD file.
29 * check_filters() - Check filters in the PPD file.
30 * check_profiles() - Check ICC color profiles in the PPD file.
31 * check_sizes() - Check media sizes in the PPD file.
32 * check_translations() - Check translations in the PPD file.
33 * show_conflicts() - Show option conflicts in a PPD file.
34 * test_raster() - Test PostScript commands for raster printers.
35 * usage() - Show program usage.
36 * valid_path() - Check whether a path has the correct capitalization.
37 * valid_utf8() - Check whether a string contains valid UTF-8 text.
41 * Include necessary headers...
44 #include <cups/cups-private.h>
46 #include <cups/ppd-private.h>
47 #include <cups/raster.h>
55 * Error warning overrides...
65 WARN_TRANSLATIONS
= 16,
101 * File permissions...
104 #define MODE_WRITE 0022 /* Group/other write */
105 #define MODE_MASK 0555 /* Owner/group/other read+exec/search */
106 #define MODE_DATAFILE 0444 /* Owner/group/other read */
107 #define MODE_DIRECTORY 0555 /* Owner/group/other read+search */
108 #define MODE_PROGRAM 0555 /* Owner/group/other read+exec */
115 static void check_basics(const char *filename
);
116 static int check_constraints(ppd_file_t
*ppd
, int errors
, int verbose
,
118 static int check_case(ppd_file_t
*ppd
, int errors
, int verbose
);
119 static int check_defaults(ppd_file_t
*ppd
, int errors
, int verbose
,
121 static int check_duplex(ppd_file_t
*ppd
, int errors
, int verbose
,
123 static int check_filters(ppd_file_t
*ppd
, const char *root
, int errors
,
124 int verbose
, int warn
);
125 static int check_profiles(ppd_file_t
*ppd
, const char *root
, int errors
,
126 int verbose
, int warn
);
127 static int check_sizes(ppd_file_t
*ppd
, int errors
, int verbose
, int warn
);
128 static int check_translations(ppd_file_t
*ppd
, int errors
, int verbose
,
130 static void show_conflicts(ppd_file_t
*ppd
, const char *prefix
);
131 static int test_raster(ppd_file_t
*ppd
, int verbose
);
132 static void usage(void);
133 static int valid_path(const char *keyword
, const char *path
, int errors
,
134 int verbose
, int warn
);
135 static int valid_utf8(const char *s
);
139 * 'main()' - Main entry for test program.
142 int /* O - Exit status */
143 main(int argc
, /* I - Number of command-line args */
144 char *argv
[]) /* I - Command-line arguments */
146 int i
, j
, k
, m
, n
; /* Looping vars */
147 int len
; /* Length of option name */
148 char *opt
; /* Option character */
149 const char *ptr
; /* Pointer into string */
150 int files
; /* Number of files */
151 int verbose
; /* Want verbose output? */
152 int warn
; /* Which errors to just warn about */
153 int ignore
; /* Which errors to ignore */
154 int status
; /* Exit status */
155 int errors
; /* Number of conformance errors */
156 int ppdversion
; /* PPD spec version in PPD file */
157 ppd_status_t error
; /* Status of ppdOpen*() */
158 int line
; /* Line number for error */
159 char *root
; /* Root directory */
160 int xdpi
, /* X resolution */
161 ydpi
; /* Y resolution */
162 ppd_file_t
*ppd
; /* PPD file record */
163 ppd_attr_t
*attr
; /* PPD attribute */
164 ppd_size_t
*size
; /* Size record */
165 ppd_group_t
*group
; /* UI group */
166 ppd_option_t
*option
; /* Standard UI option */
167 ppd_group_t
*group2
; /* UI group */
168 ppd_option_t
*option2
; /* Standard UI option */
169 ppd_choice_t
*choice
; /* Standard UI option choice */
170 struct lconv
*loc
; /* Locale data */
171 static char *uis
[] = { "BOOLEAN", "PICKONE", "PICKMANY" };
172 static char *sections
[] = { "ANY", "DOCUMENT", "EXIT",
173 "JCL", "PAGE", "PROLOG" };
176 _cupsSetLocale(argv
);
180 * Display PPD files for each file listed on the command-line...
183 ppdSetConformance(PPD_CONFORM_STRICT
);
193 for (i
= 1; i
< argc
; i
++)
194 if (argv
[i
][0] == '-' && argv
[i
][1])
196 for (opt
= argv
[i
] + 1; *opt
; opt
++)
199 case 'I' : /* Ignore errors */
205 if (!strcmp(argv
[i
], "none"))
207 else if (!strcmp(argv
[i
], "filename"))
208 ignore
|= WARN_FILENAME
;
209 else if (!strcmp(argv
[i
], "filters"))
210 ignore
|= WARN_FILTERS
;
211 else if (!strcmp(argv
[i
], "profiles"))
212 ignore
|= WARN_PROFILES
;
213 else if (!strcmp(argv
[i
], "all"))
214 ignore
= WARN_FILTERS
| WARN_PROFILES
;
219 case 'R' : /* Alternate root directory */
228 case 'W' : /* Turn errors into warnings */
234 if (!strcmp(argv
[i
], "none"))
236 else if (!strcmp(argv
[i
], "constraints"))
237 warn
|= WARN_CONSTRAINTS
;
238 else if (!strcmp(argv
[i
], "defaults"))
239 warn
|= WARN_DEFAULTS
;
240 else if (!strcmp(argv
[i
], "duplex"))
242 else if (!strcmp(argv
[i
], "filters"))
243 warn
|= WARN_FILTERS
;
244 else if (!strcmp(argv
[i
], "profiles"))
245 warn
|= WARN_PROFILES
;
246 else if (!strcmp(argv
[i
], "sizes"))
248 else if (!strcmp(argv
[i
], "translations"))
249 warn
|= WARN_TRANSLATIONS
;
250 else if (!strcmp(argv
[i
], "all"))
256 case 'q' : /* Quiet mode */
259 _cupsLangPuts(stderr
,
260 _("cupstestppd: The -q option is incompatible "
261 "with the -v option."));
268 case 'r' : /* Relaxed mode */
269 ppdSetConformance(PPD_CONFORM_RELAXED
);
272 case 'v' : /* Verbose mode */
275 _cupsLangPuts(stderr
,
276 _("cupstestppd: The -v option is incompatible "
277 "with the -q option."));
292 * Open the PPD file...
295 if (files
&& verbose
>= 0)
300 if (argv
[i
][0] == '-')
306 ppd
= ppdOpen(stdin
);
309 printf("%s:", (ppd
&& ppd
->pcfilename
) ? ppd
->pcfilename
: "(stdin)");
314 * Read from a file...
318 printf("%s:", argv
[i
]);
320 ppd
= ppdOpenFile(argv
[i
]);
325 error
= ppdLastError(&line
);
327 if (error
<= PPD_ALLOC_ERROR
)
329 status
= ERROR_FILE_OPEN
;
333 _cupsLangPuts(stdout
, _(" FAIL"));
334 _cupsLangPrintf(stdout
,
335 _(" **FAIL** Unable to open PPD file - %s"),
341 status
= ERROR_PPD_FORMAT
;
345 _cupsLangPuts(stdout
, _(" FAIL"));
346 _cupsLangPrintf(stdout
,
347 _(" **FAIL** Unable to open PPD file - "
349 ppdErrorString(error
), line
);
353 case PPD_MISSING_PPDADOBE4
:
354 _cupsLangPuts(stdout
,
355 _(" REF: Page 42, section "
358 case PPD_MISSING_VALUE
:
359 _cupsLangPuts(stdout
,
360 _(" REF: Page 20, section "
363 case PPD_BAD_OPEN_GROUP
:
364 case PPD_NESTED_OPEN_GROUP
:
365 _cupsLangPuts(stdout
,
366 _(" REF: Pages 45-46, section "
369 case PPD_BAD_OPEN_UI
:
370 case PPD_NESTED_OPEN_UI
:
371 _cupsLangPuts(stdout
,
372 _(" REF: Pages 42-45, section "
375 case PPD_BAD_ORDER_DEPENDENCY
:
376 _cupsLangPuts(stdout
,
377 _(" REF: Pages 48-49, section "
380 case PPD_BAD_UI_CONSTRAINTS
:
381 _cupsLangPuts(stdout
,
382 _(" REF: Pages 52-54, section "
385 case PPD_MISSING_ASTERISK
:
386 _cupsLangPuts(stdout
,
387 _(" REF: Page 15, section "
390 case PPD_LINE_TOO_LONG
:
391 _cupsLangPuts(stdout
,
392 _(" REF: Page 15, section "
395 case PPD_ILLEGAL_CHARACTER
:
396 _cupsLangPuts(stdout
,
397 _(" REF: Page 15, section "
400 case PPD_ILLEGAL_MAIN_KEYWORD
:
401 _cupsLangPuts(stdout
,
402 _(" REF: Pages 16-17, section "
405 case PPD_ILLEGAL_OPTION_KEYWORD
:
406 _cupsLangPuts(stdout
,
407 _(" REF: Page 19, section "
410 case PPD_ILLEGAL_TRANSLATION
:
411 _cupsLangPuts(stdout
,
412 _(" REF: Page 27, section "
419 check_basics(argv
[i
]);
427 * Show the header and then perform basic conformance tests (limited
428 * only by what the CUPS PPD functions actually load...)
435 _cupsLangPuts(stdout
,
436 _("\n DETAILED CONFORMANCE TEST RESULTS"));
438 if ((attr
= ppdFindAttr(ppd
, "FormatVersion", NULL
)) != NULL
&&
440 ppdversion
= (int)(10 * _cupsStrScand(attr
->value
, NULL
, loc
) + 0.5);
442 for (j
= 0; j
< ppd
->num_filters
; j
++)
443 if (strstr(ppd
->filters
[j
], "application/vnd.cups-raster"))
445 if (!test_raster(ppd
, verbose
))
451 * Look for default keywords with no matching option...
454 if (!(warn
& WARN_DEFAULTS
))
455 errors
= check_defaults(ppd
, errors
, verbose
, 0);
457 if ((attr
= ppdFindAttr(ppd
, "DefaultImageableArea", NULL
)) == NULL
)
461 if (!errors
&& !verbose
)
462 _cupsLangPuts(stdout
, _(" FAIL"));
464 _cupsLangPuts(stdout
,
465 _(" **FAIL** REQUIRED DefaultImageableArea\n"
466 " REF: Page 102, section 5.15."));
471 else if (ppdPageSize(ppd
, attr
->value
) == NULL
&&
472 strcmp(attr
->value
, "Unknown"))
476 if (!errors
&& !verbose
)
477 _cupsLangPuts(stdout
, _(" FAIL"));
479 _cupsLangPrintf(stdout
,
480 _(" **FAIL** BAD DefaultImageableArea %s\n"
481 " REF: Page 102, section 5.15."),
490 _cupsLangPuts(stdout
, _(" PASS DefaultImageableArea"));
493 if ((attr
= ppdFindAttr(ppd
, "DefaultPaperDimension", NULL
)) == NULL
)
497 if (!errors
&& !verbose
)
498 _cupsLangPuts(stdout
, _(" FAIL"));
500 _cupsLangPuts(stdout
,
501 _(" **FAIL** REQUIRED DefaultPaperDimension\n"
502 " REF: Page 103, section 5.15."));
507 else if (ppdPageSize(ppd
, attr
->value
) == NULL
&&
508 strcmp(attr
->value
, "Unknown"))
512 if (!errors
&& !verbose
)
513 _cupsLangPuts(stdout
, _(" FAIL"));
515 _cupsLangPrintf(stdout
,
516 _(" **FAIL** BAD DefaultPaperDimension %s\n"
517 " REF: Page 103, section 5.15."),
523 else if (verbose
> 0)
524 _cupsLangPuts(stdout
, _(" PASS DefaultPaperDimension"));
526 for (j
= 0, group
= ppd
->groups
; j
< ppd
->num_groups
; j
++, group
++)
527 for (k
= 0, option
= group
->options
;
528 k
< group
->num_options
;
532 * Verify that we have a default choice...
535 if (option
->defchoice
[0])
537 if (ppdFindChoice(option
, option
->defchoice
) == NULL
&&
538 strcmp(option
->defchoice
, "Unknown"))
542 if (!errors
&& !verbose
)
543 _cupsLangPuts(stdout
, _(" FAIL"));
545 _cupsLangPrintf(stdout
,
546 _(" **FAIL** BAD Default%s %s\n"
547 " REF: Page 40, section 4.5."),
548 option
->keyword
, option
->defchoice
);
553 else if (verbose
> 0)
554 _cupsLangPrintf(stdout
,
555 _(" PASS Default%s"),
562 if (!errors
&& !verbose
)
563 _cupsLangPuts(stdout
, _(" FAIL"));
565 _cupsLangPrintf(stdout
,
566 _(" **FAIL** REQUIRED Default%s\n"
567 " REF: Page 40, section 4.5."),
575 if ((attr
= ppdFindAttr(ppd
, "FileVersion", NULL
)) != NULL
)
577 for (ptr
= attr
->value
; *ptr
; ptr
++)
578 if (!isdigit(*ptr
& 255) && *ptr
!= '.')
585 if (!errors
&& !verbose
)
586 _cupsLangPuts(stdout
, _(" FAIL"));
588 _cupsLangPrintf(stdout
,
589 _(" **FAIL** Bad FileVersion \"%s\"\n"
590 " REF: Page 56, section 5.3."),
596 else if (verbose
> 0)
597 _cupsLangPuts(stdout
, _(" PASS FileVersion"));
603 if (!errors
&& !verbose
)
604 _cupsLangPuts(stdout
, _(" FAIL"));
606 _cupsLangPuts(stdout
,
607 _(" **FAIL** REQUIRED FileVersion\n"
608 " REF: Page 56, section 5.3."));
614 if ((attr
= ppdFindAttr(ppd
, "FormatVersion", NULL
)) != NULL
)
617 if (*ptr
== '4' && ptr
[1] == '.')
620 for (ptr
+= 2; *ptr
; ptr
++)
621 if (!isdigit(*ptr
& 255))
629 if (!errors
&& !verbose
)
630 _cupsLangPuts(stdout
, _(" FAIL"));
632 _cupsLangPrintf(stdout
,
633 _(" **FAIL** Bad FormatVersion \"%s\"\n"
634 " REF: Page 56, section 5.3."),
640 else if (verbose
> 0)
641 _cupsLangPuts(stdout
, _(" PASS FormatVersion"));
647 if (!errors
&& !verbose
)
648 _cupsLangPuts(stdout
, _(" FAIL"));
650 _cupsLangPuts(stdout
,
651 _(" **FAIL** REQUIRED FormatVersion\n"
652 " REF: Page 56, section 5.3."));
658 if (ppd
->lang_encoding
!= NULL
)
661 _cupsLangPuts(stdout
, _(" PASS LanguageEncoding"));
663 else if (ppdversion
> 40)
667 if (!errors
&& !verbose
)
668 _cupsLangPuts(stdout
, _(" FAIL"));
670 _cupsLangPuts(stdout
,
671 _(" **FAIL** REQUIRED LanguageEncoding\n"
672 " REF: Pages 56-57, section 5.3."));
678 if (ppd
->lang_version
!= NULL
)
681 _cupsLangPuts(stdout
, _(" PASS LanguageVersion"));
687 if (!errors
&& !verbose
)
688 _cupsLangPuts(stdout
, _(" FAIL"));
690 _cupsLangPuts(stdout
,
691 _(" **FAIL** REQUIRED LanguageVersion\n"
692 " REF: Pages 57-58, section 5.3."));
698 if (ppd
->manufacturer
!= NULL
)
700 if (!_cups_strncasecmp(ppd
->manufacturer
, "Hewlett-Packard", 15) ||
701 !_cups_strncasecmp(ppd
->manufacturer
, "Hewlett Packard", 15))
705 if (!errors
&& !verbose
)
706 _cupsLangPuts(stdout
, _(" FAIL"));
708 _cupsLangPuts(stdout
,
709 _(" **FAIL** BAD Manufacturer (should be "
711 " REF: Page 211, table D.1."));
716 else if (!_cups_strncasecmp(ppd
->manufacturer
, "OkiData", 7) ||
717 !_cups_strncasecmp(ppd
->manufacturer
, "Oki Data", 8))
721 if (!errors
&& !verbose
)
722 _cupsLangPuts(stdout
, _(" FAIL"));
724 _cupsLangPuts(stdout
,
725 _(" **FAIL** BAD Manufacturer (should be "
727 " REF: Page 211, table D.1."));
732 else if (verbose
> 0)
733 _cupsLangPuts(stdout
, _(" PASS Manufacturer"));
735 else if (ppdversion
>= 43)
739 if (!errors
&& !verbose
)
740 _cupsLangPuts(stdout
, _(" FAIL"));
742 _cupsLangPuts(stdout
,
743 _(" **FAIL** REQUIRED Manufacturer\n"
744 " REF: Pages 58-59, section 5.3."));
750 if (ppd
->modelname
!= NULL
)
752 for (ptr
= ppd
->modelname
; *ptr
; ptr
++)
753 if (!isalnum(*ptr
& 255) && !strchr(" ./-+", *ptr
))
760 if (!errors
&& !verbose
)
761 _cupsLangPuts(stdout
, _(" FAIL"));
763 _cupsLangPrintf(stdout
,
764 _(" **FAIL** BAD ModelName - \"%c\" not "
765 "allowed in string.\n"
766 " REF: Pages 59-60, section 5.3."),
772 else if (verbose
> 0)
773 _cupsLangPuts(stdout
, _(" PASS ModelName"));
779 if (!errors
&& !verbose
)
780 _cupsLangPuts(stdout
, _(" FAIL"));
782 _cupsLangPuts(stdout
,
783 _(" **FAIL** REQUIRED ModelName\n"
784 " REF: Pages 59-60, section 5.3."));
790 if (ppd
->nickname
!= NULL
)
793 _cupsLangPuts(stdout
, _(" PASS NickName"));
799 if (!errors
&& !verbose
)
800 _cupsLangPuts(stdout
, _(" FAIL"));
802 _cupsLangPuts(stdout
,
803 _(" **FAIL** REQUIRED NickName\n"
804 " REF: Page 60, section 5.3."));
810 if (ppdFindOption(ppd
, "PageSize") != NULL
)
813 _cupsLangPuts(stdout
, _(" PASS PageSize"));
819 if (!errors
&& !verbose
)
820 _cupsLangPuts(stdout
, _(" FAIL"));
822 _cupsLangPuts(stdout
,
823 _(" **FAIL** REQUIRED PageSize\n"
824 " REF: Pages 99-100, section 5.14."));
830 if (ppdFindOption(ppd
, "PageRegion") != NULL
)
833 _cupsLangPuts(stdout
, _(" PASS PageRegion"));
839 if (!errors
&& !verbose
)
840 _cupsLangPuts(stdout
, _(" FAIL"));
842 _cupsLangPuts(stdout
,
843 _(" **FAIL** REQUIRED PageRegion\n"
844 " REF: Page 100, section 5.14."));
850 if (ppd
->pcfilename
!= NULL
)
853 _cupsLangPuts(stdout
, _(" PASS PCFileName"));
855 else if (!(ignore
& WARN_FILENAME
))
859 if (!errors
&& !verbose
)
860 _cupsLangPuts(stdout
, _(" FAIL"));
862 _cupsLangPuts(stdout
,
863 _(" **FAIL** REQUIRED PCFileName\n"
864 " REF: Pages 61-62, section 5.3."));
870 if (ppd
->product
!= NULL
)
872 if (ppd
->product
[0] != '(' ||
873 ppd
->product
[strlen(ppd
->product
) - 1] != ')')
877 if (!errors
&& !verbose
)
878 _cupsLangPuts(stdout
, _(" FAIL"));
880 _cupsLangPuts(stdout
,
881 _(" **FAIL** BAD Product - not \"(string)\".\n"
882 " REF: Page 62, section 5.3."));
887 else if (verbose
> 0)
888 _cupsLangPuts(stdout
, _(" PASS Product"));
894 if (!errors
&& !verbose
)
895 _cupsLangPuts(stdout
, _(" FAIL"));
897 _cupsLangPuts(stdout
,
898 _(" **FAIL** REQUIRED Product\n"
899 " REF: Page 62, section 5.3."));
905 if ((attr
= ppdFindAttr(ppd
, "PSVersion", NULL
)) != NULL
&&
908 char junkstr
[255]; /* Temp string */
909 int junkint
; /* Temp integer */
912 if (sscanf(attr
->value
, "(%[^)])%d", junkstr
, &junkint
) != 2)
916 if (!errors
&& !verbose
)
917 _cupsLangPuts(stdout
, _(" FAIL"));
919 _cupsLangPuts(stdout
,
920 _(" **FAIL** BAD PSVersion - not \"(string) "
922 " REF: Pages 62-64, section 5.3."));
927 else if (verbose
> 0)
928 _cupsLangPuts(stdout
, _(" PASS PSVersion"));
934 if (!errors
&& !verbose
)
935 _cupsLangPuts(stdout
, _(" FAIL"));
937 _cupsLangPuts(stdout
,
938 _(" **FAIL** REQUIRED PSVersion\n"
939 " REF: Pages 62-64, section 5.3."));
945 if (ppd
->shortnickname
!= NULL
)
947 if (strlen(ppd
->shortnickname
) > 31)
951 if (!errors
&& !verbose
)
952 _cupsLangPuts(stdout
, _(" FAIL"));
954 _cupsLangPuts(stdout
,
955 _(" **FAIL** BAD ShortNickName - longer "
957 " REF: Pages 64-65, section 5.3."));
962 else if (verbose
> 0)
963 _cupsLangPuts(stdout
, _(" PASS ShortNickName"));
965 else if (ppdversion
>= 43)
969 if (!errors
&& !verbose
)
970 _cupsLangPuts(stdout
, _(" FAIL"));
972 _cupsLangPuts(stdout
,
973 _(" **FAIL** REQUIRED ShortNickName\n"
974 " REF: Page 64-65, section 5.3."));
980 if (ppd
->patches
!= NULL
&& strchr(ppd
->patches
, '\"') &&
981 strstr(ppd
->patches
, "*End"))
985 if (!errors
&& !verbose
)
986 _cupsLangPuts(stdout
, _(" FAIL"));
988 _cupsLangPuts(stdout
,
989 _(" **FAIL** BAD JobPatchFile attribute in file\n"
990 " REF: Page 24, section 3.4."));
997 * Check for page sizes without the corresponding ImageableArea or
998 * PaperDimension values...
1001 if (ppd
->num_sizes
== 0)
1005 if (!errors
&& !verbose
)
1006 _cupsLangPuts(stdout
, _(" FAIL"));
1008 _cupsLangPuts(stdout
,
1009 _(" **FAIL** REQUIRED PageSize\n"
1010 " REF: Page 41, section 5.\n"
1011 " REF: Page 99, section 5.14."));
1018 for (j
= 0, size
= ppd
->sizes
; j
< ppd
->num_sizes
; j
++, size
++)
1021 * Don't check custom size...
1024 if (!strcmp(size
->name
, "Custom"))
1028 * Check for ImageableArea...
1031 if (size
->left
== 0.0 && size
->bottom
== 0.0 &&
1032 size
->right
== 0.0 && size
->top
== 0.0)
1036 if (!errors
&& !verbose
)
1037 _cupsLangPuts(stdout
, _(" FAIL"));
1039 _cupsLangPrintf(stdout
,
1040 _(" **FAIL** REQUIRED ImageableArea for "
1042 " REF: Page 41, section 5.\n"
1043 " REF: Page 102, section 5.15."),
1051 * Check for PaperDimension...
1054 if (size
->width
== 0.0 && size
->length
== 0.0)
1058 if (!errors
&& !verbose
)
1059 _cupsLangPuts(stdout
, _(" FAIL"));
1061 _cupsLangPrintf(stdout
,
1062 _(" **FAIL** REQUIRED PaperDimension "
1064 " REF: Page 41, section 5.\n"
1065 " REF: Page 103, section 5.15."),
1075 * Check for valid Resolution, JCLResolution, or SetResolution values...
1078 if ((option
= ppdFindOption(ppd
, "Resolution")) == NULL
)
1079 if ((option
= ppdFindOption(ppd
, "JCLResolution")) == NULL
)
1080 option
= ppdFindOption(ppd
, "SetResolution");
1084 for (j
= option
->num_choices
, choice
= option
->choices
;
1089 * Verify that all resolution options are of the form NNNdpi
1093 xdpi
= strtol(choice
->choice
, (char **)&ptr
, 10);
1094 if (ptr
> choice
->choice
&& xdpi
> 0)
1097 ydpi
= strtol(ptr
+ 1, (char **)&ptr
, 10);
1104 if (xdpi
<= 0 || xdpi
> 99999 || ydpi
<= 0 || ydpi
> 99999 ||
1109 if (!errors
&& !verbose
)
1110 _cupsLangPuts(stdout
, _(" FAIL"));
1112 _cupsLangPrintf(stdout
,
1113 _(" **FAIL** Bad %s choice %s\n"
1114 " REF: Page 84, section 5.9"),
1115 option
->keyword
, choice
->choice
);
1123 if ((attr
= ppdFindAttr(ppd
, "1284DeviceID", NULL
)) &&
1124 strcmp(attr
->name
, "1284DeviceID"))
1128 if (!errors
&& !verbose
)
1129 _cupsLangPuts(stdout
, _(" FAIL"));
1131 _cupsLangPrintf(stdout
,
1132 _(" **FAIL** %s must be 1284DeviceID\n"
1133 " REF: Page 72, section 5.5"),
1140 errors
= check_case(ppd
, errors
, verbose
);
1142 if (!(warn
& WARN_CONSTRAINTS
))
1143 errors
= check_constraints(ppd
, errors
, verbose
, 0);
1145 if (!(warn
& WARN_FILTERS
) && !(ignore
& WARN_FILTERS
))
1146 errors
= check_filters(ppd
, root
, errors
, verbose
, 0);
1148 if (!(warn
& WARN_PROFILES
) && !(ignore
& WARN_PROFILES
))
1149 errors
= check_profiles(ppd
, root
, errors
, verbose
, 0);
1151 if (!(warn
& WARN_SIZES
))
1152 errors
= check_sizes(ppd
, errors
, verbose
, 0);
1154 if (!(warn
& WARN_TRANSLATIONS
))
1155 errors
= check_translations(ppd
, errors
, verbose
, 0);
1157 if (!(warn
& WARN_DUPLEX
))
1158 errors
= check_duplex(ppd
, errors
, verbose
, 0);
1160 if ((attr
= ppdFindAttr(ppd
, "cupsLanguages", NULL
)) != NULL
&&
1164 * This file contains localizations, check for conformance of the
1165 * base translation...
1168 if ((attr
= ppdFindAttr(ppd
, "LanguageEncoding", NULL
)) != NULL
)
1170 if (!attr
->value
|| strcmp(attr
->value
, "ISOLatin1"))
1172 if (!errors
&& !verbose
)
1173 _cupsLangPuts(stdout
, _(" FAIL"));
1176 _cupsLangPrintf(stdout
,
1177 _(" **FAIL** Bad LanguageEncoding %s - "
1178 "must be ISOLatin1."),
1179 attr
->value
? attr
->value
: "(null)");
1184 if (!ppd
->lang_version
|| strcmp(ppd
->lang_version
, "English"))
1186 if (!errors
&& !verbose
)
1187 _cupsLangPuts(stdout
, _(" FAIL"));
1190 _cupsLangPrintf(stdout
,
1191 _(" **FAIL** Bad LanguageVersion %s - "
1192 "must be English."),
1193 ppd
->lang_version
? ppd
->lang_version
: "(null)");
1199 * Loop through all options and choices...
1202 for (option
= ppdFirstOption(ppd
);
1204 option
= ppdNextOption(ppd
))
1207 * Check for special characters outside A0 to BF, F7, or F8
1208 * that are used for languages other than English.
1211 for (ptr
= option
->text
; *ptr
; ptr
++)
1212 if ((*ptr
& 0x80) && (*ptr
& 0xe0) != 0xa0 &&
1213 (*ptr
& 0xff) != 0xf7 && (*ptr
& 0xff) != 0xf8)
1218 if (!errors
&& !verbose
)
1219 _cupsLangPuts(stdout
, _(" FAIL"));
1222 _cupsLangPrintf(stdout
,
1223 _(" **FAIL** Default translation "
1224 "string for option %s contains 8-bit "
1231 for (j
= 0; j
< option
->num_choices
; j
++)
1234 * Check for special characters outside A0 to BF, F7, or F8
1235 * that are used for languages other than English.
1238 for (ptr
= option
->choices
[j
].text
; *ptr
; ptr
++)
1239 if ((*ptr
& 0x80) && (*ptr
& 0xe0) != 0xa0 &&
1240 (*ptr
& 0xff) != 0xf7 && (*ptr
& 0xff) != 0xf8)
1245 if (!errors
&& !verbose
)
1246 _cupsLangPuts(stdout
, _(" FAIL"));
1249 _cupsLangPrintf(stdout
,
1250 _(" **FAIL** Default translation "
1251 "string for option %s choice %s contains "
1252 "8-bit characters."),
1254 option
->choices
[j
].choice
);
1264 * Final pass/fail notification...
1268 status
= ERROR_CONFORMANCE
;
1270 _cupsLangPuts(stdout
, _(" PASS"));
1274 check_basics(argv
[i
]);
1276 if (warn
& WARN_DEFAULTS
)
1277 errors
= check_defaults(ppd
, errors
, verbose
, 1);
1279 if (warn
& WARN_CONSTRAINTS
)
1280 errors
= check_constraints(ppd
, errors
, verbose
, 1);
1282 if ((warn
& WARN_FILTERS
) && !(ignore
& WARN_FILTERS
))
1283 errors
= check_filters(ppd
, root
, errors
, verbose
, 1);
1285 if ((warn
& WARN_PROFILES
) && !(ignore
& WARN_PROFILES
))
1286 errors
= check_profiles(ppd
, root
, errors
, verbose
, 1);
1288 if (warn
& WARN_SIZES
)
1289 errors
= check_sizes(ppd
, errors
, verbose
, 1);
1291 errors
= check_sizes(ppd
, errors
, verbose
, 2);
1293 if (warn
& WARN_TRANSLATIONS
)
1294 errors
= check_translations(ppd
, errors
, verbose
, 1);
1296 if (warn
& WARN_DUPLEX
)
1297 errors
= check_duplex(ppd
, errors
, verbose
, 1);
1300 * Look for legacy duplex keywords...
1303 if ((option
= ppdFindOption(ppd
, "JCLDuplex")) == NULL
)
1304 if ((option
= ppdFindOption(ppd
, "EFDuplex")) == NULL
)
1305 option
= ppdFindOption(ppd
, "KD03Duplex");
1308 _cupsLangPrintf(stdout
,
1309 _(" WARN Duplex option keyword %s may not "
1310 "work as expected and should be named Duplex.\n"
1311 " REF: Page 122, section 5.17"),
1315 * Look for default keywords with no corresponding option...
1318 for (j
= 0; j
< ppd
->num_attrs
; j
++)
1320 attr
= ppd
->attrs
[j
];
1322 if (!strcmp(attr
->name
, "DefaultColorSpace") ||
1323 !strcmp(attr
->name
, "DefaultColorSep") ||
1324 !strcmp(attr
->name
, "DefaultFont") ||
1325 !strcmp(attr
->name
, "DefaultHalftoneType") ||
1326 !strcmp(attr
->name
, "DefaultImageableArea") ||
1327 !strcmp(attr
->name
, "DefaultLeadingEdge") ||
1328 !strcmp(attr
->name
, "DefaultOutputOrder") ||
1329 !strcmp(attr
->name
, "DefaultPaperDimension") ||
1330 !strcmp(attr
->name
, "DefaultResolution") ||
1331 !strcmp(attr
->name
, "DefaultScreenProc") ||
1332 !strcmp(attr
->name
, "DefaultTransfer"))
1335 if (!strncmp(attr
->name
, "Default", 7) &&
1336 !ppdFindOption(ppd
, attr
->name
+ 7))
1337 _cupsLangPrintf(stdout
,
1338 _(" WARN %s has no corresponding "
1343 if (ppdversion
< 43)
1345 _cupsLangPrintf(stdout
,
1346 _(" WARN Obsolete PPD version %.1f.\n"
1347 " REF: Page 42, section 5.2."),
1351 if (!ppd
->lang_encoding
&& ppdversion
< 41)
1353 _cupsLangPuts(stdout
,
1354 _(" WARN LanguageEncoding required by PPD "
1356 " REF: Pages 56-57, section 5.3."));
1359 if (!ppd
->manufacturer
&& ppdversion
< 43)
1361 _cupsLangPuts(stdout
,
1362 _(" WARN Manufacturer required by PPD "
1364 " REF: Pages 58-59, section 5.3."));
1368 * Treat a PCFileName attribute longer than 12 characters as
1369 * a warning and not a hard error...
1372 if (!(ignore
& WARN_FILENAME
) && ppd
->pcfilename
)
1374 if (strlen(ppd
->pcfilename
) > 12)
1376 _cupsLangPuts(stdout
,
1377 _(" WARN PCFileName longer than 8.3 in "
1378 "violation of PPD spec.\n"
1379 " REF: Pages 61-62, section "
1383 if (!_cups_strcasecmp(ppd
->pcfilename
, "unused.ppd"))
1384 _cupsLangPuts(stdout
,
1385 _(" WARN PCFileName should contain a "
1386 "unique filename.\n"
1387 " REF: Pages 61-62, section "
1391 if (!ppd
->shortnickname
&& ppdversion
< 43)
1393 _cupsLangPuts(stdout
,
1394 _(" WARN ShortNickName required by PPD "
1396 " REF: Pages 64-65, section 5.3."));
1400 * Check the Protocols line and flag PJL + BCP since TBCP is
1401 * usually used with PJL...
1406 if (strstr(ppd
->protocols
, "PJL") &&
1407 strstr(ppd
->protocols
, "BCP") &&
1408 !strstr(ppd
->protocols
, "TBCP"))
1410 _cupsLangPuts(stdout
,
1411 _(" WARN Protocols contains both PJL "
1412 "and BCP; expected TBCP.\n"
1413 " REF: Pages 78-79, section 5.7."));
1416 if (strstr(ppd
->protocols
, "PJL") &&
1417 (!ppd
->jcl_begin
|| !ppd
->jcl_end
|| !ppd
->jcl_ps
))
1419 _cupsLangPuts(stdout
,
1420 _(" WARN Protocols contains PJL but JCL "
1421 "attributes are not set.\n"
1422 " REF: Pages 78-79, section 5.7."));
1427 * Check for options with a common prefix, e.g. Duplex and Duplexer,
1428 * which are errors according to the spec but won't cause problems
1429 * with CUPS specifically...
1432 for (j
= 0, group
= ppd
->groups
; j
< ppd
->num_groups
; j
++, group
++)
1433 for (k
= 0, option
= group
->options
;
1434 k
< group
->num_options
;
1437 len
= (int)strlen(option
->keyword
);
1439 for (m
= 0, group2
= ppd
->groups
;
1440 m
< ppd
->num_groups
;
1442 for (n
= 0, option2
= group2
->options
;
1443 n
< group2
->num_options
;
1445 if (option
!= option2
&&
1446 len
< (int)strlen(option2
->keyword
) &&
1447 !strncmp(option
->keyword
, option2
->keyword
, len
))
1449 _cupsLangPrintf(stdout
,
1450 _(" WARN %s shares a common "
1452 " REF: Page 15, section "
1454 option
->keyword
, option2
->keyword
);
1462 _cupsLangPrintf(stdout
, _(" %d ERRORS FOUND"), errors
);
1464 _cupsLangPuts(stdout
, _(" NO ERRORS FOUND"));
1468 * Then list the options, if "-v" was provided...
1473 _cupsLangPrintf(stdout
,
1475 " language_level = %d\n"
1476 " color_device = %s\n"
1477 " variable_sizes = %s\n"
1479 ppd
->language_level
,
1480 ppd
->color_device
? "TRUE" : "FALSE",
1481 ppd
->variable_sizes
? "TRUE" : "FALSE",
1484 switch (ppd
->colorspace
)
1487 _cupsLangPuts(stdout
, " colorspace = PPD_CS_CMYK");
1490 _cupsLangPuts(stdout
, " colorspace = PPD_CS_CMY");
1493 _cupsLangPuts(stdout
, " colorspace = PPD_CS_GRAY");
1496 _cupsLangPuts(stdout
, " colorspace = PPD_CS_RGB");
1499 _cupsLangPuts(stdout
, " colorspace = <unknown>");
1503 _cupsLangPrintf(stdout
, " num_emulations = %d",
1504 ppd
->num_emulations
);
1505 for (j
= 0; j
< ppd
->num_emulations
; j
++)
1506 _cupsLangPrintf(stdout
, " emulations[%d] = %s",
1507 j
, ppd
->emulations
[j
].name
);
1509 _cupsLangPrintf(stdout
, " lang_encoding = %s",
1510 ppd
->lang_encoding
);
1511 _cupsLangPrintf(stdout
, " lang_version = %s",
1513 _cupsLangPrintf(stdout
, " modelname = %s", ppd
->modelname
);
1514 _cupsLangPrintf(stdout
, " ttrasterizer = %s",
1515 ppd
->ttrasterizer
== NULL
? "None" : ppd
->ttrasterizer
);
1516 _cupsLangPrintf(stdout
, " manufacturer = %s",
1518 _cupsLangPrintf(stdout
, " product = %s", ppd
->product
);
1519 _cupsLangPrintf(stdout
, " nickname = %s", ppd
->nickname
);
1520 _cupsLangPrintf(stdout
, " shortnickname = %s",
1521 ppd
->shortnickname
);
1522 _cupsLangPrintf(stdout
, " patches = %d bytes",
1523 ppd
->patches
== NULL
? 0 : (int)strlen(ppd
->patches
));
1525 _cupsLangPrintf(stdout
, " num_groups = %d", ppd
->num_groups
);
1526 for (j
= 0, group
= ppd
->groups
; j
< ppd
->num_groups
; j
++, group
++)
1528 _cupsLangPrintf(stdout
, " group[%d] = %s",
1531 for (k
= 0, option
= group
->options
; k
< group
->num_options
; k
++, option
++)
1533 _cupsLangPrintf(stdout
,
1534 " options[%d] = %s (%s) %s %s %.0f "
1536 k
, option
->keyword
, option
->text
, uis
[option
->ui
],
1537 sections
[option
->section
], option
->order
,
1538 option
->num_choices
);
1540 if (!strcmp(option
->keyword
, "PageSize") ||
1541 !strcmp(option
->keyword
, "PageRegion"))
1543 for (m
= option
->num_choices
, choice
= option
->choices
;
1547 size
= ppdPageSize(ppd
, choice
->choice
);
1550 _cupsLangPrintf(stdout
,
1551 " %s (%s) = ERROR%s",
1552 choice
->choice
, choice
->text
,
1553 !strcmp(option
->defchoice
, choice
->choice
)
1556 _cupsLangPrintf(stdout
,
1557 " %s (%s) = %.2fx%.2fin "
1558 "(%.1f,%.1f,%.1f,%.1f)%s",
1559 choice
->choice
, choice
->text
,
1560 size
->width
/ 72.0, size
->length
/ 72.0,
1561 size
->left
/ 72.0, size
->bottom
/ 72.0,
1562 size
->right
/ 72.0, size
->top
/ 72.0,
1563 !strcmp(option
->defchoice
, choice
->choice
)
1569 for (m
= option
->num_choices
, choice
= option
->choices
;
1573 _cupsLangPrintf(stdout
, " %s (%s)%s",
1574 choice
->choice
, choice
->text
,
1575 !strcmp(option
->defchoice
, choice
->choice
)
1582 _cupsLangPrintf(stdout
, " num_consts = %d",
1584 for (j
= 0; j
< ppd
->num_consts
; j
++)
1585 _cupsLangPrintf(stdout
,
1586 " consts[%d] = *%s %s *%s %s",
1587 j
, ppd
->consts
[j
].option1
, ppd
->consts
[j
].choice1
,
1588 ppd
->consts
[j
].option2
, ppd
->consts
[j
].choice2
);
1590 _cupsLangPrintf(stdout
, " num_profiles = %d",
1592 for (j
= 0; j
< ppd
->num_profiles
; j
++)
1593 _cupsLangPrintf(stdout
,
1594 " profiles[%d] = %s/%s %.3f %.3f "
1595 "[ %.3f %.3f %.3f %.3f %.3f %.3f %.3f %.3f %.3f ]",
1596 j
, ppd
->profiles
[j
].resolution
,
1597 ppd
->profiles
[j
].media_type
,
1598 ppd
->profiles
[j
].gamma
, ppd
->profiles
[j
].density
,
1599 ppd
->profiles
[j
].matrix
[0][0],
1600 ppd
->profiles
[j
].matrix
[0][1],
1601 ppd
->profiles
[j
].matrix
[0][2],
1602 ppd
->profiles
[j
].matrix
[1][0],
1603 ppd
->profiles
[j
].matrix
[1][1],
1604 ppd
->profiles
[j
].matrix
[1][2],
1605 ppd
->profiles
[j
].matrix
[2][0],
1606 ppd
->profiles
[j
].matrix
[2][1],
1607 ppd
->profiles
[j
].matrix
[2][2]);
1609 _cupsLangPrintf(stdout
, " num_fonts = %d", ppd
->num_fonts
);
1610 for (j
= 0; j
< ppd
->num_fonts
; j
++)
1611 _cupsLangPrintf(stdout
, " fonts[%d] = %s",
1614 _cupsLangPrintf(stdout
, " num_attrs = %d", ppd
->num_attrs
);
1615 for (j
= 0; j
< ppd
->num_attrs
; j
++)
1616 _cupsLangPrintf(stdout
,
1617 " attrs[%d] = %s %s%s%s: \"%s\"", j
,
1618 ppd
->attrs
[j
]->name
, ppd
->attrs
[j
]->spec
,
1619 ppd
->attrs
[j
]->text
[0] ? "/" : "",
1620 ppd
->attrs
[j
]->text
,
1621 ppd
->attrs
[j
]->value
?
1622 ppd
->attrs
[j
]->value
: "(null)");
1636 * 'check_basics()' - Check for CR LF, mixed line endings, and blank lines.
1640 check_basics(const char *filename
) /* I - PPD file to check */
1642 cups_file_t
*fp
; /* File pointer */
1643 int ch
; /* Current character */
1644 int col
, /* Current column */
1645 whitespace
; /* Only seen whitespace? */
1646 int eol
; /* Line endings */
1647 int linenum
; /* Line number */
1648 int mixed
; /* Mixed line endings? */
1651 if ((fp
= cupsFileOpen(filename
, "r")) == NULL
)
1660 while ((ch
= cupsFileGetChar(fp
)) != EOF
)
1662 if (ch
== '\r' || ch
== '\n')
1666 if (eol
== EOL_NONE
)
1668 else if (eol
!= EOL_LF
)
1671 else if (ch
== '\r')
1673 if (cupsFilePeekChar(fp
) == '\n')
1675 cupsFileGetChar(fp
);
1677 if (eol
== EOL_NONE
)
1679 else if (eol
!= EOL_CRLF
)
1682 else if (eol
== EOL_NONE
)
1684 else if (eol
!= EOL_CR
)
1688 if (col
> 0 && whitespace
)
1689 _cupsLangPrintf(stdout
,
1690 _(" WARN Line %d only contains whitespace."),
1699 if (ch
!= ' ' && ch
!= '\t')
1707 _cupsLangPuts(stdout
,
1708 _(" WARN File contains a mix of CR, LF, and "
1709 "CR LF line endings."));
1711 if (eol
== EOL_CRLF
)
1712 _cupsLangPuts(stdout
,
1713 _(" WARN Non-Windows PPD files should use lines "
1714 "ending with only LF, not CR LF."));
1721 * 'check_constraints()' - Check UIConstraints in the PPD file.
1724 static int /* O - Errors found */
1725 check_constraints(ppd_file_t
*ppd
, /* I - PPD file */
1726 int errors
, /* I - Errors found */
1727 int verbose
, /* I - Verbosity level */
1728 int warn
) /* I - Warnings only? */
1730 int i
; /* Looping var */
1731 const char *prefix
; /* WARN/FAIL prefix */
1732 ppd_const_t
*c
; /* Current UIConstraints data */
1733 ppd_attr_t
*constattr
; /* Current cupsUIConstraints attribute */
1734 const char *vptr
; /* Pointer into constraint value */
1735 char option
[PPD_MAX_NAME
],
1736 /* Option name/MainKeyword */
1737 choice
[PPD_MAX_NAME
],
1738 /* Choice/OptionKeyword */
1739 *ptr
; /* Pointer into option or choice */
1740 int num_options
; /* Number of options */
1741 cups_option_t
*options
; /* Options */
1742 ppd_option_t
*o
; /* PPD option */
1745 prefix
= warn
? " WARN " : "**FAIL**";
1749 * See what kind of constraint data we have in the PPD...
1752 if ((constattr
= ppdFindAttr(ppd
, "cupsUIConstraints", NULL
)) != NULL
)
1755 * Check new-style cupsUIConstraints data...
1759 constattr
= ppdFindNextAttr(ppd
, "cupsUIConstraints", NULL
))
1761 if (!constattr
->value
)
1763 if (!warn
&& !errors
&& !verbose
)
1764 _cupsLangPuts(stdout
, _(" FAIL"));
1766 _cupsLangPrintf(stdout
,
1767 _(" %s Empty cupsUIConstraints %s"),
1768 prefix
, constattr
->spec
);
1776 for (i
= 0, vptr
= strchr(constattr
->value
, '*');
1778 i
++, vptr
= strchr(vptr
+ 1, '*'));
1782 if (!warn
&& !errors
&& !verbose
)
1783 _cupsLangPuts(stdout
, _(" FAIL"));
1785 _cupsLangPrintf(stdout
,
1786 _(" %s Bad cupsUIConstraints %s: \"%s\""),
1787 prefix
, constattr
->spec
, constattr
->value
);
1795 cupsArraySave(ppd
->sorted_attrs
);
1797 if (constattr
->spec
[0] &&
1798 !ppdFindAttr(ppd
, "cupsUIResolver", constattr
->spec
))
1800 if (!warn
&& !errors
&& !verbose
)
1801 _cupsLangPuts(stdout
, _(" FAIL"));
1803 _cupsLangPrintf(stdout
,
1804 _(" %s Missing cupsUIResolver %s"),
1805 prefix
, constattr
->spec
);
1811 cupsArrayRestore(ppd
->sorted_attrs
);
1816 for (vptr
= strchr(constattr
->value
, '*');
1818 vptr
= strchr(vptr
, '*'))
1821 * Extract "*Option Choice" or just "*Option"...
1824 for (vptr
++, ptr
= option
; *vptr
&& !isspace(*vptr
& 255); vptr
++)
1825 if (ptr
< (option
+ sizeof(option
) - 1))
1830 while (isspace(*vptr
& 255))
1837 for (ptr
= choice
; *vptr
&& !isspace(*vptr
& 255); vptr
++)
1838 if (ptr
< (choice
+ sizeof(choice
) - 1))
1844 if (!_cups_strncasecmp(option
, "Custom", 6) && !_cups_strcasecmp(choice
, "True"))
1846 _cups_strcpy(option
, option
+ 6);
1847 strcpy(choice
, "Custom");
1850 if ((o
= ppdFindOption(ppd
, option
)) == NULL
)
1852 if (!warn
&& !errors
&& !verbose
)
1853 _cupsLangPuts(stdout
, _(" FAIL"));
1855 _cupsLangPrintf(stdout
,
1856 _(" %s Missing option %s in "
1857 "cupsUIConstraints %s: \"%s\""),
1858 prefix
, option
, constattr
->spec
, constattr
->value
);
1866 if (choice
[0] && !ppdFindChoice(o
, choice
))
1868 if (!warn
&& !errors
&& !verbose
)
1869 _cupsLangPuts(stdout
, _(" FAIL"));
1871 _cupsLangPrintf(stdout
,
1872 _(" %s Missing choice *%s %s in "
1873 "cupsUIConstraints %s: \"%s\""),
1874 prefix
, option
, choice
, constattr
->spec
,
1884 num_options
= cupsAddOption(option
, choice
, num_options
, &options
);
1887 for (i
= 0; i
< o
->num_choices
; i
++)
1888 if (_cups_strcasecmp(o
->choices
[i
].choice
, "None") &&
1889 _cups_strcasecmp(o
->choices
[i
].choice
, "Off") &&
1890 _cups_strcasecmp(o
->choices
[i
].choice
, "False"))
1892 num_options
= cupsAddOption(option
, o
->choices
[i
].choice
,
1893 num_options
, &options
);
1900 * Resolvers must list at least two options...
1903 if (num_options
< 2)
1905 if (!warn
&& !errors
&& !verbose
)
1906 _cupsLangPuts(stdout
, _(" FAIL"));
1908 _cupsLangPrintf(stdout
,
1909 _(" %s cupsUIResolver %s does not list at least "
1910 "two different options."),
1911 prefix
, constattr
->spec
);
1918 * Test the resolver...
1921 if (!cupsResolveConflicts(ppd
, NULL
, NULL
, &num_options
, &options
))
1923 if (!warn
&& !errors
&& !verbose
)
1924 _cupsLangPuts(stdout
, _(" FAIL"));
1926 _cupsLangPrintf(stdout
,
1927 _(" %s cupsUIResolver %s causes a loop."),
1928 prefix
, constattr
->spec
);
1934 cupsFreeOptions(num_options
, options
);
1940 * Check old-style [Non]UIConstraints data...
1943 for (i
= ppd
->num_consts
, c
= ppd
->consts
; i
> 0; i
--, c
++)
1945 if (!_cups_strncasecmp(c
->option1
, "Custom", 6) &&
1946 !_cups_strcasecmp(c
->choice1
, "True"))
1948 strcpy(option
, c
->option1
+ 6);
1949 strcpy(choice
, "Custom");
1953 strcpy(option
, c
->option1
);
1954 strcpy(choice
, c
->choice1
);
1957 if ((o
= ppdFindOption(ppd
, option
)) == NULL
)
1959 if (!warn
&& !errors
&& !verbose
)
1960 _cupsLangPuts(stdout
, _(" FAIL"));
1962 _cupsLangPrintf(stdout
,
1963 _(" %s Missing option %s in "
1964 "UIConstraints \"*%s %s *%s %s\"."),
1966 c
->option1
, c
->choice1
, c
->option2
, c
->choice2
);
1971 else if (choice
[0] && !ppdFindChoice(o
, choice
))
1973 if (!warn
&& !errors
&& !verbose
)
1974 _cupsLangPuts(stdout
, _(" FAIL"));
1976 _cupsLangPrintf(stdout
,
1977 _(" %s Missing choice *%s %s in "
1978 "UIConstraints \"*%s %s *%s %s\"."),
1979 prefix
, c
->option1
, c
->choice1
,
1980 c
->option1
, c
->choice1
, c
->option2
, c
->choice2
);
1986 if (!_cups_strncasecmp(c
->option2
, "Custom", 6) &&
1987 !_cups_strcasecmp(c
->choice2
, "True"))
1989 strcpy(option
, c
->option2
+ 6);
1990 strcpy(choice
, "Custom");
1994 strcpy(option
, c
->option2
);
1995 strcpy(choice
, c
->choice2
);
1998 if ((o
= ppdFindOption(ppd
, option
)) == NULL
)
2000 if (!warn
&& !errors
&& !verbose
)
2001 _cupsLangPuts(stdout
, _(" FAIL"));
2003 _cupsLangPrintf(stdout
,
2004 _(" %s Missing option %s in "
2005 "UIConstraints \"*%s %s *%s %s\"."),
2007 c
->option1
, c
->choice1
, c
->option2
, c
->choice2
);
2012 else if (choice
[0] && !ppdFindChoice(o
, choice
))
2014 if (!warn
&& !errors
&& !verbose
)
2015 _cupsLangPuts(stdout
, _(" FAIL"));
2017 _cupsLangPrintf(stdout
,
2018 _(" %s Missing choice *%s %s in "
2019 "UIConstraints \"*%s %s *%s %s\"."),
2020 prefix
, c
->option2
, c
->choice2
,
2021 c
->option1
, c
->choice1
, c
->option2
, c
->choice2
);
2034 * 'check_case()' - Check that there are no duplicate groups, options,
2035 * or choices that differ only by case.
2038 static int /* O - Errors found */
2039 check_case(ppd_file_t
*ppd
, /* I - PPD file */
2040 int errors
, /* I - Errors found */
2041 int verbose
) /* I - Verbosity level */
2043 int i
, j
; /* Looping vars */
2044 ppd_group_t
*groupa
, /* First group */
2045 *groupb
; /* Second group */
2046 ppd_option_t
*optiona
, /* First option */
2047 *optionb
; /* Second option */
2048 ppd_choice_t
*choicea
, /* First choice */
2049 *choiceb
; /* Second choice */
2053 * Check that the groups do not have any duplicate names...
2056 for (i
= ppd
->num_groups
, groupa
= ppd
->groups
; i
> 1; i
--, groupa
++)
2057 for (j
= i
- 1, groupb
= groupa
+ 1; j
> 0; j
--, groupb
++)
2058 if (!_cups_strcasecmp(groupa
->name
, groupb
->name
))
2060 if (!errors
&& !verbose
)
2061 _cupsLangPuts(stdout
, _(" FAIL"));
2064 _cupsLangPrintf(stdout
,
2065 _(" **FAIL** Group names %s and %s differ only "
2067 groupa
->name
, groupb
->name
);
2073 * Check that the options do not have any duplicate names...
2076 for (optiona
= ppdFirstOption(ppd
); optiona
; optiona
= ppdNextOption(ppd
))
2078 cupsArraySave(ppd
->options
);
2079 for (optionb
= ppdNextOption(ppd
); optionb
; optionb
= ppdNextOption(ppd
))
2080 if (!_cups_strcasecmp(optiona
->keyword
, optionb
->keyword
))
2082 if (!errors
&& !verbose
)
2083 _cupsLangPuts(stdout
, _(" FAIL"));
2086 _cupsLangPrintf(stdout
,
2087 _(" **FAIL** Option names %s and %s differ only "
2089 optiona
->keyword
, optionb
->keyword
);
2093 cupsArrayRestore(ppd
->options
);
2096 * Then the choices...
2099 for (i
= optiona
->num_choices
, choicea
= optiona
->choices
;
2102 for (j
= i
- 1, choiceb
= choicea
+ 1; j
> 0; j
--, choiceb
++)
2103 if (!strcmp(choicea
->choice
, choiceb
->choice
))
2105 if (!errors
&& !verbose
)
2106 _cupsLangPuts(stdout
, _(" FAIL"));
2109 _cupsLangPrintf(stdout
,
2110 _(" **FAIL** Multiple occurrences of %s "
2112 optiona
->keyword
, choicea
->choice
);
2120 else if (!_cups_strcasecmp(choicea
->choice
, choiceb
->choice
))
2122 if (!errors
&& !verbose
)
2123 _cupsLangPuts(stdout
, _(" FAIL"));
2126 _cupsLangPrintf(stdout
,
2127 _(" **FAIL** %s choice names %s and %s "
2128 "differ only by case."),
2129 optiona
->keyword
, choicea
->choice
, choiceb
->choice
);
2136 * Return the number of errors found...
2144 * 'check_defaults()' - Check default option keywords in the PPD file.
2147 static int /* O - Errors found */
2148 check_defaults(ppd_file_t
*ppd
, /* I - PPD file */
2149 int errors
, /* I - Errors found */
2150 int verbose
, /* I - Verbosity level */
2151 int warn
) /* I - Warnings only? */
2153 int j
, k
; /* Looping vars */
2154 ppd_attr_t
*attr
; /* PPD attribute */
2155 ppd_option_t
*option
; /* Standard UI option */
2156 const char *prefix
; /* WARN/FAIL prefix */
2159 prefix
= warn
? " WARN " : "**FAIL**";
2161 ppdMarkDefaults(ppd
);
2162 if (ppdConflicts(ppd
))
2164 if (!warn
&& !errors
&& !verbose
)
2165 _cupsLangPuts(stdout
, _(" FAIL"));
2168 _cupsLangPrintf(stdout
,
2169 _(" %s Default choices conflicting."), prefix
);
2171 show_conflicts(ppd
, prefix
);
2177 for (j
= 0; j
< ppd
->num_attrs
; j
++)
2179 attr
= ppd
->attrs
[j
];
2181 if (!strcmp(attr
->name
, "DefaultColorSpace") ||
2182 !strcmp(attr
->name
, "DefaultFont") ||
2183 !strcmp(attr
->name
, "DefaultHalftoneType") ||
2184 !strcmp(attr
->name
, "DefaultImageableArea") ||
2185 !strcmp(attr
->name
, "DefaultLeadingEdge") ||
2186 !strcmp(attr
->name
, "DefaultOutputOrder") ||
2187 !strcmp(attr
->name
, "DefaultPaperDimension") ||
2188 !strcmp(attr
->name
, "DefaultResolution") ||
2189 !strcmp(attr
->name
, "DefaultTransfer"))
2192 if (!strncmp(attr
->name
, "Default", 7))
2194 if ((option
= ppdFindOption(ppd
, attr
->name
+ 7)) != NULL
&&
2195 strcmp(attr
->value
, "Unknown"))
2198 * Check that the default option value matches a choice...
2201 for (k
= 0; k
< option
->num_choices
; k
++)
2202 if (!strcmp(option
->choices
[k
].choice
, attr
->value
))
2205 if (k
>= option
->num_choices
)
2207 if (!warn
&& !errors
&& !verbose
)
2208 _cupsLangPuts(stdout
, _(" FAIL"));
2211 _cupsLangPrintf(stdout
,
2212 _(" %s %s %s does not exist."),
2213 prefix
, attr
->name
, attr
->value
);
2227 * 'check_duplex()' - Check duplex keywords in the PPD file.
2230 static int /* O - Errors found */
2231 check_duplex(ppd_file_t
*ppd
, /* I - PPD file */
2232 int errors
, /* I - Error found */
2233 int verbose
, /* I - Verbosity level */
2234 int warn
) /* I - Warnings only? */
2236 int i
; /* Looping var */
2237 ppd_option_t
*option
; /* PPD option */
2238 ppd_choice_t
*choice
; /* Current choice */
2239 const char *prefix
; /* Message prefix */
2242 prefix
= warn
? " WARN " : "**FAIL**";
2245 * Check for a duplex option, and for standard values...
2248 if ((option
= ppdFindOption(ppd
, "Duplex")) != NULL
)
2250 if (!ppdFindChoice(option
, "None"))
2254 if (!warn
&& !errors
&& !verbose
)
2255 _cupsLangPuts(stdout
, _(" FAIL"));
2257 _cupsLangPrintf(stdout
,
2258 _(" %s REQUIRED %s does not define "
2260 " REF: Page 122, section 5.17"),
2261 prefix
, option
->keyword
);
2268 for (i
= option
->num_choices
, choice
= option
->choices
;
2271 if (strcmp(choice
->choice
, "None") &&
2272 strcmp(choice
->choice
, "DuplexNoTumble") &&
2273 strcmp(choice
->choice
, "DuplexTumble") &&
2274 strcmp(choice
->choice
, "SimplexTumble"))
2278 if (!warn
&& !errors
&& !verbose
)
2279 _cupsLangPuts(stdout
, _(" FAIL"));
2281 _cupsLangPrintf(stdout
,
2282 _(" %s Bad %s choice %s.\n"
2283 " REF: Page 122, section 5.17"),
2284 prefix
, option
->keyword
, choice
->choice
);
2297 * 'check_filters()' - Check filters in the PPD file.
2300 static int /* O - Errors found */
2301 check_filters(ppd_file_t
*ppd
, /* I - PPD file */
2302 const char *root
, /* I - Root directory */
2303 int errors
, /* I - Errors found */
2304 int verbose
, /* I - Verbosity level */
2305 int warn
) /* I - Warnings only? */
2307 int i
; /* Looping var */
2308 ppd_attr_t
*attr
; /* PPD attribute */
2309 const char *ptr
; /* Pointer into string */
2310 char super
[16], /* Super-type for filter */
2311 type
[256], /* Type for filter */
2312 program
[1024], /* Program/filter name */
2313 pathprog
[1024]; /* Complete path to program/filter */
2314 int cost
; /* Cost of filter */
2315 const char *prefix
; /* WARN/FAIL prefix */
2316 struct stat fileinfo
; /* File information */
2319 prefix
= warn
? " WARN " : "**FAIL**";
2325 for (i
= 0; i
< ppd
->num_filters
; i
++)
2327 if (sscanf(ppd
->filters
[i
], "%15[^/]/%255s%d%*[ \t]%1023[^\n]", super
, type
,
2328 &cost
, program
) != 4)
2330 if (!warn
&& !errors
&& !verbose
)
2331 _cupsLangPuts(stdout
, _(" FAIL"));
2334 _cupsLangPrintf(stdout
,
2335 _(" %s Bad cupsFilter value \"%s\"."),
2336 prefix
, ppd
->filters
[i
]);
2341 else if (strcmp(program
, "-"))
2343 if (program
[0] == '/')
2344 snprintf(pathprog
, sizeof(pathprog
), "%s%s", root
, program
);
2347 if ((ptr
= getenv("CUPS_SERVERBIN")) == NULL
)
2348 ptr
= CUPS_SERVERBIN
;
2350 if (*ptr
== '/' || !*root
)
2351 snprintf(pathprog
, sizeof(pathprog
), "%s%s/filter/%s", root
, ptr
,
2354 snprintf(pathprog
, sizeof(pathprog
), "%s/%s/filter/%s", root
, ptr
,
2358 if (stat(pathprog
, &fileinfo
))
2360 if (!warn
&& !errors
&& !verbose
)
2361 _cupsLangPuts(stdout
, _(" FAIL"));
2364 _cupsLangPrintf(stdout
, _(" %s Missing %s file \"%s\"."),
2365 prefix
, "cupsFilter", pathprog
);
2370 else if (fileinfo
.st_uid
!= 0 ||
2371 (fileinfo
.st_mode
& MODE_WRITE
) ||
2372 (fileinfo
.st_mode
& MODE_MASK
) != MODE_PROGRAM
)
2374 if (!warn
&& !errors
&& !verbose
)
2375 _cupsLangPuts(stdout
, _(" FAIL"));
2378 _cupsLangPrintf(stdout
,
2379 _(" %s Bad permissions on %s file \"%s\"."),
2380 prefix
, "cupsFilter", pathprog
);
2386 errors
= valid_path("cupsFilter", pathprog
, errors
, verbose
, warn
);
2394 for (attr
= ppdFindAttr(ppd
, "cupsPreFilter", NULL
);
2396 attr
= ppdFindNextAttr(ppd
, "cupsPreFilter", NULL
))
2398 if (strcmp(attr
->name
, "cupsPreFilter"))
2400 if (!warn
&& !errors
&& !verbose
)
2401 _cupsLangPuts(stdout
, _(" FAIL"));
2404 _cupsLangPrintf(stdout
,
2405 _(" %s Bad spelling of %s - should be %s."),
2406 prefix
, attr
->name
, "cupsPreFilter");
2413 sscanf(attr
->value
, "%15[^/]/%255s%d%*[ \t]%1023[^\n]", super
, type
,
2414 &cost
, program
) != 4)
2416 if (!warn
&& !errors
&& !verbose
)
2417 _cupsLangPuts(stdout
, _(" FAIL"));
2420 _cupsLangPrintf(stdout
,
2421 _(" %s Bad cupsPreFilter value \"%s\"."),
2422 prefix
, attr
->value
? attr
->value
: "");
2427 else if (strcmp(program
, "-"))
2429 if (program
[0] == '/')
2430 snprintf(pathprog
, sizeof(pathprog
), "%s%s", root
, program
);
2433 if ((ptr
= getenv("CUPS_SERVERBIN")) == NULL
)
2434 ptr
= CUPS_SERVERBIN
;
2436 if (*ptr
== '/' || !*root
)
2437 snprintf(pathprog
, sizeof(pathprog
), "%s%s/filter/%s", root
, ptr
,
2440 snprintf(pathprog
, sizeof(pathprog
), "%s/%s/filter/%s", root
, ptr
,
2444 if (stat(pathprog
, &fileinfo
))
2446 if (!warn
&& !errors
&& !verbose
)
2447 _cupsLangPuts(stdout
, _(" FAIL"));
2450 _cupsLangPrintf(stdout
, _(" %s Missing %s file \"%s\"."),
2451 prefix
, "cupsPreFilter", pathprog
);
2456 else if (fileinfo
.st_uid
!= 0 ||
2457 (fileinfo
.st_mode
& MODE_WRITE
) ||
2458 (fileinfo
.st_mode
& MODE_MASK
) != MODE_PROGRAM
)
2460 if (!warn
&& !errors
&& !verbose
)
2461 _cupsLangPuts(stdout
, _(" FAIL"));
2464 _cupsLangPrintf(stdout
,
2465 _(" %s Bad permissions on %s file \"%s\"."),
2466 prefix
, "cupsPreFilter", pathprog
);
2472 errors
= valid_path("cupsPreFilter", pathprog
, errors
, verbose
, warn
);
2481 for (attr
= ppdFindAttr(ppd
, "APDialogExtension", NULL
);
2483 attr
= ppdFindNextAttr(ppd
, "APDialogExtension", NULL
))
2485 if (strcmp(attr
->name
, "APDialogExtension"))
2487 if (!warn
&& !errors
&& !verbose
)
2488 _cupsLangPuts(stdout
, _(" FAIL"));
2491 _cupsLangPrintf(stdout
,
2492 _(" %s Bad spelling of %s - should be %s."),
2493 prefix
, attr
->name
, "APDialogExtension");
2499 snprintf(pathprog
, sizeof(pathprog
), "%s%s", root
,
2500 attr
->value
? attr
->value
: "(null)");
2502 if (!attr
->value
|| stat(pathprog
, &fileinfo
))
2504 if (!warn
&& !errors
&& !verbose
)
2505 _cupsLangPuts(stdout
, _(" FAIL"));
2508 _cupsLangPrintf(stdout
, _(" %s Missing %s file \"%s\"."),
2509 prefix
, "APDialogExtension", pathprog
);
2514 else if (fileinfo
.st_uid
!= 0 ||
2515 (fileinfo
.st_mode
& MODE_WRITE
) ||
2516 (fileinfo
.st_mode
& MODE_MASK
) != MODE_DIRECTORY
)
2518 if (!warn
&& !errors
&& !verbose
)
2519 _cupsLangPuts(stdout
, _(" FAIL"));
2522 _cupsLangPrintf(stdout
,
2523 _(" %s Bad permissions on %s file \"%s\"."),
2524 prefix
, "APDialogExtension", pathprog
);
2530 errors
= valid_path("APDialogExtension", pathprog
, errors
, verbose
,
2538 if ((attr
= ppdFindAttr(ppd
, "APPrinterIconPath", NULL
)) != NULL
)
2540 if (strcmp(attr
->name
, "APPrinterIconPath"))
2542 if (!warn
&& !errors
&& !verbose
)
2543 _cupsLangPuts(stdout
, _(" FAIL"));
2546 _cupsLangPrintf(stdout
,
2547 _(" %s Bad spelling of %s - should be %s."),
2548 prefix
, attr
->name
, "APPrinterIconPath");
2554 snprintf(pathprog
, sizeof(pathprog
), "%s%s", root
,
2555 attr
->value
? attr
->value
: "(null)");
2557 if (!attr
->value
|| stat(pathprog
, &fileinfo
))
2559 if (!warn
&& !errors
&& !verbose
)
2560 _cupsLangPuts(stdout
, _(" FAIL"));
2563 _cupsLangPrintf(stdout
, _(" %s Missing %s file \"%s\"."),
2564 prefix
, "APPrinterIconPath", pathprog
);
2569 else if (fileinfo
.st_uid
!= 0 ||
2570 (fileinfo
.st_mode
& MODE_WRITE
) ||
2571 (fileinfo
.st_mode
& MODE_MASK
) != MODE_DATAFILE
)
2573 if (!warn
&& !errors
&& !verbose
)
2574 _cupsLangPuts(stdout
, _(" FAIL"));
2577 _cupsLangPrintf(stdout
,
2578 _(" %s Bad permissions on %s file \"%s\"."),
2579 prefix
, "APPrinterIconPath", pathprog
);
2585 errors
= valid_path("APPrinterIconPath", pathprog
, errors
, verbose
,
2590 * APPrinterLowInkTool
2593 if ((attr
= ppdFindAttr(ppd
, "APPrinterLowInkTool", NULL
)) != NULL
)
2595 if (strcmp(attr
->name
, "APPrinterLowInkTool"))
2597 if (!warn
&& !errors
&& !verbose
)
2598 _cupsLangPuts(stdout
, _(" FAIL"));
2601 _cupsLangPrintf(stdout
,
2602 _(" %s Bad spelling of %s - should be %s."),
2603 prefix
, attr
->name
, "APPrinterLowInkTool");
2609 snprintf(pathprog
, sizeof(pathprog
), "%s%s", root
,
2610 attr
->value
? attr
->value
: "(null)");
2612 if (!attr
->value
|| stat(pathprog
, &fileinfo
))
2614 if (!warn
&& !errors
&& !verbose
)
2615 _cupsLangPuts(stdout
, _(" FAIL"));
2618 _cupsLangPrintf(stdout
, _(" %s Missing %s file \"%s\"."),
2619 prefix
, "APPrinterLowInkTool", pathprog
);
2624 else if (fileinfo
.st_uid
!= 0 ||
2625 (fileinfo
.st_mode
& MODE_WRITE
) ||
2626 (fileinfo
.st_mode
& MODE_MASK
) != MODE_DIRECTORY
)
2628 if (!warn
&& !errors
&& !verbose
)
2629 _cupsLangPuts(stdout
, _(" FAIL"));
2632 _cupsLangPrintf(stdout
,
2633 _(" %s Bad permissions on %s file \"%s\"."),
2634 prefix
, "APPrinterLowInkTool", pathprog
);
2640 errors
= valid_path("APPrinterLowInkTool", pathprog
, errors
, verbose
,
2645 * APPrinterUtilityPath
2648 if ((attr
= ppdFindAttr(ppd
, "APPrinterUtilityPath", NULL
)) != NULL
)
2650 if (strcmp(attr
->name
, "APPrinterUtilityPath"))
2652 if (!warn
&& !errors
&& !verbose
)
2653 _cupsLangPuts(stdout
, _(" FAIL"));
2656 _cupsLangPrintf(stdout
,
2657 _(" %s Bad spelling of %s - should be %s."),
2658 prefix
, attr
->name
, "APPrinterUtilityPath");
2664 snprintf(pathprog
, sizeof(pathprog
), "%s%s", root
,
2665 attr
->value
? attr
->value
: "(null)");
2667 if (!attr
->value
|| stat(pathprog
, &fileinfo
))
2669 if (!warn
&& !errors
&& !verbose
)
2670 _cupsLangPuts(stdout
, _(" FAIL"));
2673 _cupsLangPrintf(stdout
, _(" %s Missing %s file \"%s\"."),
2674 prefix
, "APPrinterUtilityPath", pathprog
);
2679 else if (fileinfo
.st_uid
!= 0 ||
2680 (fileinfo
.st_mode
& MODE_WRITE
) ||
2681 (fileinfo
.st_mode
& MODE_MASK
) != MODE_DIRECTORY
)
2683 if (!warn
&& !errors
&& !verbose
)
2684 _cupsLangPuts(stdout
, _(" FAIL"));
2687 _cupsLangPrintf(stdout
,
2688 _(" %s Bad permissions on %s file \"%s\"."),
2689 prefix
, "APPrinterUtilityPath", pathprog
);
2695 errors
= valid_path("APPrinterUtilityPath", pathprog
, errors
, verbose
,
2700 * APScanAppBundleID and APScanAppPath
2703 if ((attr
= ppdFindAttr(ppd
, "APScanAppPath", NULL
)) != NULL
)
2705 if (strcmp(attr
->name
, "APScanAppPath"))
2707 if (!warn
&& !errors
&& !verbose
)
2708 _cupsLangPuts(stdout
, _(" FAIL"));
2711 _cupsLangPrintf(stdout
,
2712 _(" %s Bad spelling of %s - should be %s."),
2713 prefix
, attr
->name
, "APScanAppPath");
2719 if (!attr
->value
|| stat(attr
->value
, &fileinfo
))
2721 if (!warn
&& !errors
&& !verbose
)
2722 _cupsLangPuts(stdout
, _(" FAIL"));
2725 _cupsLangPrintf(stdout
, _(" %s Missing %s file \"%s\"."),
2726 prefix
, "APScanAppPath",
2727 attr
->value
? attr
->value
: "<NULL>");
2732 else if (fileinfo
.st_uid
!= 0 ||
2733 (fileinfo
.st_mode
& MODE_WRITE
) ||
2734 (fileinfo
.st_mode
& MODE_MASK
) != MODE_DIRECTORY
)
2736 if (!warn
&& !errors
&& !verbose
)
2737 _cupsLangPuts(stdout
, _(" FAIL"));
2740 _cupsLangPrintf(stdout
,
2741 _(" %s Bad permissions on %s file \"%s\"."),
2742 prefix
, "APScanAppPath", attr
->value
);
2748 errors
= valid_path("APScanAppPath", attr
->value
, errors
, verbose
,
2751 if (ppdFindAttr(ppd
, "APScanAppBundleID", NULL
))
2753 if (!warn
&& !errors
&& !verbose
)
2754 _cupsLangPuts(stdout
, _(" FAIL"));
2757 _cupsLangPrintf(stdout
, _(" %s Cannot provide both "
2758 "APScanAppPath and APScanAppBundleID."),
2765 #endif /* __APPLE__ */
2772 * 'check_profiles()' - Check ICC color profiles in the PPD file.
2775 static int /* O - Errors found */
2776 check_profiles(ppd_file_t
*ppd
, /* I - PPD file */
2777 const char *root
, /* I - Root directory */
2778 int errors
, /* I - Errors found */
2779 int verbose
, /* I - Verbosity level */
2780 int warn
) /* I - Warnings only? */
2782 int i
; /* Looping var */
2783 ppd_attr_t
*attr
; /* PPD attribute */
2784 const char *ptr
; /* Pointer into string */
2785 const char *prefix
; /* WARN/FAIL prefix */
2786 char filename
[1024]; /* Profile filename */
2787 struct stat fileinfo
; /* File information */
2788 int num_profiles
= 0; /* Number of profiles */
2789 unsigned hash
, /* Current hash value */
2790 hashes
[1000]; /* Hash values of profile names */
2791 const char *specs
[1000]; /* Specifiers for profiles */
2794 prefix
= warn
? " WARN " : "**FAIL**";
2796 for (attr
= ppdFindAttr(ppd
, "cupsICCProfile", NULL
);
2798 attr
= ppdFindNextAttr(ppd
, "cupsICCProfile", NULL
))
2801 * Check for valid selector...
2804 for (i
= 0, ptr
= strchr(attr
->spec
, '.'); ptr
; ptr
= strchr(ptr
+ 1, '.'))
2807 if (!attr
->value
|| i
< 2)
2809 if (!warn
&& !errors
&& !verbose
)
2810 _cupsLangPuts(stdout
, _(" FAIL"));
2813 _cupsLangPrintf(stdout
,
2814 _(" %s Bad cupsICCProfile %s."),
2815 prefix
, attr
->spec
);
2824 * Check for valid profile filename...
2827 if (attr
->value
[0] == '/')
2828 snprintf(filename
, sizeof(filename
), "%s%s", root
, attr
->value
);
2831 if ((ptr
= getenv("CUPS_DATADIR")) == NULL
)
2834 if (*ptr
== '/' || !*root
)
2835 snprintf(filename
, sizeof(filename
), "%s%s/profiles/%s", root
, ptr
,
2838 snprintf(filename
, sizeof(filename
), "%s/%s/profiles/%s", root
, ptr
,
2842 if (stat(filename
, &fileinfo
))
2844 if (!warn
&& !errors
&& !verbose
)
2845 _cupsLangPuts(stdout
, _(" FAIL"));
2848 _cupsLangPrintf(stdout
, _(" %s Missing %s file \"%s\"."),
2849 prefix
, "cupsICCProfile", filename
);
2854 else if (fileinfo
.st_uid
!= 0 ||
2855 (fileinfo
.st_mode
& MODE_WRITE
) ||
2856 (fileinfo
.st_mode
& MODE_MASK
) != MODE_DATAFILE
)
2858 if (!warn
&& !errors
&& !verbose
)
2859 _cupsLangPuts(stdout
, _(" FAIL"));
2862 _cupsLangPrintf(stdout
,
2863 _(" %s Bad permissions on %s file \"%s\"."),
2864 prefix
, "cupsICCProfile", filename
);
2870 errors
= valid_path("cupsICCProfile", filename
, errors
, verbose
, warn
);
2873 * Check for hash collisions...
2876 hash
= _ppdHashName(attr
->spec
);
2878 if (num_profiles
> 0)
2880 for (i
= 0; i
< num_profiles
; i
++)
2881 if (hashes
[i
] == hash
)
2884 if (i
< num_profiles
)
2886 if (!warn
&& !errors
&& !verbose
)
2887 _cupsLangPuts(stdout
, _(" FAIL"));
2890 _cupsLangPrintf(stdout
,
2891 _(" %s cupsICCProfile %s hash value "
2892 "collides with %s."), prefix
, attr
->spec
,
2901 * Remember up to 1000 profiles...
2904 if (num_profiles
< 1000)
2906 hashes
[num_profiles
] = hash
;
2907 specs
[num_profiles
] = attr
->spec
;
2917 * 'check_sizes()' - Check media sizes in the PPD file.
2920 static int /* O - Errors found */
2921 check_sizes(ppd_file_t
*ppd
, /* I - PPD file */
2922 int errors
, /* I - Errors found */
2923 int verbose
, /* I - Verbosity level */
2924 int warn
) /* I - Warnings only? */
2926 int i
; /* Looping var */
2927 ppd_size_t
*size
; /* Current size */
2928 int width
, /* Custom width */
2929 length
; /* Custom length */
2930 const char *prefix
; /* WARN/FAIL prefix */
2931 ppd_option_t
*page_size
, /* PageSize option */
2932 *page_region
; /* PageRegion option */
2933 _pwg_media_t
*pwg_media
; /* PWG media */
2934 char buf
[1024]; /* PapeSize name that is supposed to be */
2935 const char *ptr
; /* Pointer into string */
2936 int width_2540ths
, /* PageSize width in 2540ths */
2937 length_2540ths
; /* PageSize length in 2540ths */
2938 int is_ok
; /* Flag for PageSize name verification */
2939 double width_tmp
, /* Width after rounded up */
2940 length_tmp
, /* Length after rounded up */
2941 width_inch
, /* Width in inches */
2942 length_inch
, /* Length in inches */
2943 width_mm
, /* Width in millimeters */
2944 length_mm
; /* Length in millimeters */
2947 prefix
= warn
? " WARN " : "**FAIL**";
2949 if ((page_size
= ppdFindOption(ppd
, "PageSize")) == NULL
&& warn
!= 2)
2951 if (!warn
&& !errors
&& !verbose
)
2952 _cupsLangPuts(stdout
, _(" FAIL"));
2955 _cupsLangPrintf(stdout
,
2956 _(" %s Missing REQUIRED PageSize option.\n"
2957 " REF: Page 99, section 5.14."),
2964 if ((page_region
= ppdFindOption(ppd
, "PageRegion")) == NULL
&& warn
!= 2)
2966 if (!warn
&& !errors
&& !verbose
)
2967 _cupsLangPuts(stdout
, _(" FAIL"));
2970 _cupsLangPrintf(stdout
,
2971 _(" %s Missing REQUIRED PageRegion option.\n"
2972 " REF: Page 100, section 5.14."),
2979 for (i
= ppd
->num_sizes
, size
= ppd
->sizes
; i
> 0; i
--, size
++)
2982 * Check that the size name is standard...
2985 if (!strcmp(size
->name
, "Custom"))
2988 * Skip custom page size...
2993 else if (warn
!= 2 && size
->name
[0] == 'w' &&
2994 sscanf(size
->name
, "w%dh%d", &width
, &length
) == 2)
2997 * Validate device-specific size wNNNhNNN should have proper width and
3001 if (fabs(width
- size
->width
) >= 1.0 ||
3002 fabs(length
- size
->length
) >= 1.0)
3004 if (!warn
&& !errors
&& !verbose
)
3005 _cupsLangPuts(stdout
, _(" FAIL"));
3008 _cupsLangPrintf(stdout
,
3009 _(" %s Size \"%s\" has unexpected dimensions "
3011 prefix
, size
->name
, size
->width
, size
->length
);
3019 * Verify that the size is defined for both PageSize and PageRegion...
3022 if (warn
!= 2 && !ppdFindChoice(page_size
, size
->name
))
3024 if (!warn
&& !errors
&& !verbose
)
3025 _cupsLangPuts(stdout
, _(" FAIL"));
3028 _cupsLangPrintf(stdout
,
3029 _(" %s Size \"%s\" defined for %s but not for "
3031 prefix
, size
->name
, "PageRegion", "PageSize");
3036 else if (warn
!= 2 && !ppdFindChoice(page_region
, size
->name
))
3038 if (!warn
&& !errors
&& !verbose
)
3039 _cupsLangPuts(stdout
, _(" FAIL"));
3042 _cupsLangPrintf(stdout
,
3043 _(" %s Size \"%s\" defined for %s but not for "
3045 prefix
, size
->name
, "PageSize", "PageRegion");
3052 * Verify that the size name is Adobe standard name if it's a standard size
3053 * and the dementional name if it's not a standard size. Suffix should be
3054 * .Fullbleed, etc., or numeric, e.g., Letter, Letter.Fullbleed,
3055 * Letter.Transverse, Letter1, Letter2, 4x8, 55x91mm, 55x91mm.Fullbleed, etc.
3061 width_2540ths
= (size
->length
> size
->width
) ?
3062 _PWG_FROMPTS(size
->width
) :
3063 _PWG_FROMPTS(size
->length
);
3064 length_2540ths
= (size
->length
> size
->width
) ?
3065 _PWG_FROMPTS(size
->length
) :
3066 _PWG_FROMPTS(size
->width
);
3067 pwg_media
= _pwgMediaForSize(width_2540ths
, length_2540ths
);
3069 if (pwg_media
&& pwg_media
->ppd
)
3071 strlcpy(buf
, pwg_media
->ppd
, sizeof(buf
));
3073 if (size
->left
== 0 && size
->bottom
== 0 &&
3074 size
->right
== size
->width
&& size
->top
== size
->length
)
3076 snprintf(buf
, sizeof(buf
), "%s.Fullbleed", pwg_media
->ppd
);
3077 if (strcmp(size
->name
, buf
))
3080 else if (size
->width
> size
->length
)
3082 if ((ptr
= pwg_media
->ppd
+ strlen(pwg_media
->ppd
) - 7)
3083 >= pwg_media
->ppd
&& !strcmp(ptr
, "Rotated"))
3085 if (strcmp(size
->name
, buf
))
3090 snprintf(buf
, sizeof(buf
), "%sRotated", pwg_media
->ppd
);
3091 if (strcmp(size
->name
, buf
))
3093 snprintf(buf
, sizeof(buf
), "%s.Transverse", pwg_media
->ppd
);
3094 if (strcmp(size
->name
, buf
))
3101 if ((!strncmp(size
->name
, pwg_media
->ppd
, strlen(pwg_media
->ppd
))))
3103 for (ptr
= size
->name
+ strlen(pwg_media
->ppd
); *ptr
; ptr
++)
3105 if (!isdigit(*ptr
& 255))
3117 _cupsLangPrintf(stdout
,
3118 _(" %s Size \"%s\" should be the Adobe "
3119 "standard name \"%s\"."),
3120 prefix
, size
->name
, buf
);
3124 width_tmp
= (fabs(size
->width
- ceil(size
->width
)) < 0.1) ?
3125 ceil(size
->width
) : size
->width
;
3126 length_tmp
= (fabs(size
->length
- ceil(size
->length
)) < 0.1) ?
3127 ceil(size
->length
) : size
->length
;
3129 if (fmod(width_tmp
, 18.0) == 0.0 && fmod(length_tmp
, 18.0) == 0.0)
3131 width_inch
= width_tmp
/ 72.0;
3132 length_inch
= length_tmp
/ 72.0;
3134 snprintf(buf
, sizeof(buf
), "%gx%g", width_inch
, length_inch
);
3138 width_mm
= size
->width
/ 72.0 * 25.4;
3139 length_mm
= size
->length
/ 72.0 * 25.4;
3141 snprintf(buf
, sizeof(buf
), "%.0fx%.0fmm", width_mm
, length_mm
);
3144 if (size
->left
== 0 && size
->bottom
== 0 &&
3145 size
->right
== size
->width
&& size
->top
== size
->length
)
3146 strlcat(buf
, ".Fullbleed", sizeof(buf
));
3147 else if (size
->width
> size
->length
)
3148 strlcat(buf
, ".Transverse", sizeof(buf
));
3150 if (strcmp(size
->name
, buf
))
3151 _cupsLangPrintf(stdout
,
3152 _(" %s Size \"%s\" should be \"%s\"."),
3153 prefix
, size
->name
, buf
);
3163 * 'check_translations()' - Check translations in the PPD file.
3166 static int /* O - Errors found */
3167 check_translations(ppd_file_t
*ppd
, /* I - PPD file */
3168 int errors
, /* I - Errors found */
3169 int verbose
, /* I - Verbosity level */
3170 int warn
) /* I - Warnings only? */
3172 int j
; /* Looping var */
3173 ppd_attr_t
*attr
; /* PPD attribute */
3174 cups_array_t
*languages
; /* Array of languages */
3175 int langlen
; /* Length of language */
3176 char *language
, /* Current language */
3177 keyword
[PPD_MAX_NAME
], /* Localization keyword (full) */
3178 llkeyword
[PPD_MAX_NAME
],/* Localization keyword (base) */
3179 ckeyword
[PPD_MAX_NAME
], /* Custom option keyword (full) */
3180 cllkeyword
[PPD_MAX_NAME
];
3181 /* Custom option keyword (base) */
3182 ppd_option_t
*option
; /* Standard UI option */
3183 ppd_coption_t
*coption
; /* Custom option */
3184 ppd_cparam_t
*cparam
; /* Custom parameter */
3185 char ll
[3]; /* Base language */
3186 const char *prefix
; /* WARN/FAIL prefix */
3187 const char *text
; /* Pointer into UI text */
3190 prefix
= warn
? " WARN " : "**FAIL**";
3192 if ((languages
= _ppdGetLanguages(ppd
)) != NULL
)
3195 * This file contains localizations, check them...
3198 for (language
= (char *)cupsArrayFirst(languages
);
3200 language
= (char *)cupsArrayNext(languages
))
3202 langlen
= (int)strlen(language
);
3203 if (langlen
!= 2 && langlen
!= 5)
3205 if (!warn
&& !errors
&& !verbose
)
3206 _cupsLangPuts(stdout
, _(" FAIL"));
3209 _cupsLangPrintf(stdout
,
3210 _(" %s Bad language \"%s\"."),
3219 if (!strcmp(language
, "en"))
3222 strlcpy(ll
, language
, sizeof(ll
));
3225 * Loop through all options and choices...
3228 for (option
= ppdFirstOption(ppd
);
3230 option
= ppdNextOption(ppd
))
3232 if (!strcmp(option
->keyword
, "PageRegion"))
3235 snprintf(keyword
, sizeof(keyword
), "%s.Translation", language
);
3236 snprintf(llkeyword
, sizeof(llkeyword
), "%s.Translation", ll
);
3238 if ((attr
= ppdFindAttr(ppd
, keyword
, option
->keyword
)) == NULL
&&
3239 (attr
= ppdFindAttr(ppd
, llkeyword
, option
->keyword
)) == NULL
)
3241 if (!warn
&& !errors
&& !verbose
)
3242 _cupsLangPuts(stdout
, _(" FAIL"));
3245 _cupsLangPrintf(stdout
,
3246 _(" %s Missing \"%s\" translation "
3247 "string for option %s."),
3248 prefix
, language
, option
->keyword
);
3253 else if (!valid_utf8(attr
->text
))
3255 if (!warn
&& !errors
&& !verbose
)
3256 _cupsLangPuts(stdout
, _(" FAIL"));
3259 _cupsLangPrintf(stdout
,
3260 _(" %s Bad UTF-8 \"%s\" translation "
3261 "string for option %s."),
3262 prefix
, language
, option
->keyword
);
3268 snprintf(keyword
, sizeof(keyword
), "%s.%s", language
,
3270 snprintf(llkeyword
, sizeof(llkeyword
), "%s.%s", ll
,
3273 for (j
= 0; j
< option
->num_choices
; j
++)
3276 * First see if this choice is a number; if so, don't require
3280 for (text
= option
->choices
[j
].text
; *text
; text
++)
3281 if (!strchr("0123456789-+.", *text
))
3288 * Check custom choices differently...
3291 if (!_cups_strcasecmp(option
->choices
[j
].choice
, "Custom") &&
3292 (coption
= ppdFindCustomOption(ppd
,
3293 option
->keyword
)) != NULL
)
3295 snprintf(ckeyword
, sizeof(ckeyword
), "%s.Custom%s",
3296 language
, option
->keyword
);
3298 if ((attr
= ppdFindAttr(ppd
, ckeyword
, "True")) != NULL
&&
3299 !valid_utf8(attr
->text
))
3301 if (!warn
&& !errors
&& !verbose
)
3302 _cupsLangPuts(stdout
, _(" FAIL"));
3305 _cupsLangPrintf(stdout
,
3306 _(" %s Bad UTF-8 \"%s\" "
3307 "translation string for option %s, "
3310 ckeyword
+ 1 + strlen(language
),
3317 if (_cups_strcasecmp(option
->keyword
, "PageSize"))
3319 for (cparam
= (ppd_cparam_t
*)cupsArrayFirst(coption
->params
);
3321 cparam
= (ppd_cparam_t
*)cupsArrayNext(coption
->params
))
3323 snprintf(ckeyword
, sizeof(ckeyword
), "%s.ParamCustom%s",
3324 language
, option
->keyword
);
3325 snprintf(cllkeyword
, sizeof(cllkeyword
), "%s.ParamCustom%s",
3326 ll
, option
->keyword
);
3328 if ((attr
= ppdFindAttr(ppd
, ckeyword
,
3329 cparam
->name
)) == NULL
&&
3330 (attr
= ppdFindAttr(ppd
, cllkeyword
,
3331 cparam
->name
)) == NULL
)
3333 if (!warn
&& !errors
&& !verbose
)
3334 _cupsLangPuts(stdout
, _(" FAIL"));
3337 _cupsLangPrintf(stdout
,
3338 _(" %s Missing \"%s\" "
3339 "translation string for option %s, "
3342 ckeyword
+ 1 + strlen(language
),
3348 else if (!valid_utf8(attr
->text
))
3350 if (!warn
&& !errors
&& !verbose
)
3351 _cupsLangPuts(stdout
, _(" FAIL"));
3354 _cupsLangPrintf(stdout
,
3355 _(" %s Bad UTF-8 \"%s\" "
3356 "translation string for option %s, "
3359 ckeyword
+ 1 + strlen(language
),
3368 else if ((attr
= ppdFindAttr(ppd
, keyword
,
3369 option
->choices
[j
].choice
)) == NULL
&&
3370 (attr
= ppdFindAttr(ppd
, llkeyword
,
3371 option
->choices
[j
].choice
)) == NULL
)
3373 if (!warn
&& !errors
&& !verbose
)
3374 _cupsLangPuts(stdout
, _(" FAIL"));
3377 _cupsLangPrintf(stdout
,
3378 _(" %s Missing \"%s\" "
3379 "translation string for option %s, "
3381 prefix
, language
, option
->keyword
,
3382 option
->choices
[j
].choice
);
3387 else if (!valid_utf8(attr
->text
))
3389 if (!warn
&& !errors
&& !verbose
)
3390 _cupsLangPuts(stdout
, _(" FAIL"));
3393 _cupsLangPrintf(stdout
,
3394 _(" %s Bad UTF-8 \"%s\" "
3395 "translation string for option %s, "
3397 prefix
, language
, option
->keyword
,
3398 option
->choices
[j
].choice
);
3408 * Verify that we have the base language for each localized one...
3411 for (language
= (char *)cupsArrayFirst(languages
);
3413 language
= (char *)cupsArrayNext(languages
))
3417 * Lookup the base language...
3420 cupsArraySave(languages
);
3422 strlcpy(ll
, language
, sizeof(ll
));
3424 if (!cupsArrayFind(languages
, ll
) &&
3425 strcmp(ll
, "zh") && strcmp(ll
, "en"))
3427 if (!warn
&& !errors
&& !verbose
)
3428 _cupsLangPuts(stdout
, _(" FAIL"));
3431 _cupsLangPrintf(stdout
,
3432 _(" %s No base translation \"%s\" "
3433 "is included in file."), prefix
, ll
);
3439 cupsArrayRestore(languages
);
3443 * Free memory used for the languages...
3446 _ppdFreeLanguages(languages
);
3454 * 'show_conflicts()' - Show option conflicts in a PPD file.
3458 show_conflicts(ppd_file_t
*ppd
, /* I - PPD to check */
3459 const char *prefix
) /* I - Prefix string */
3461 int i
, j
; /* Looping variables */
3462 ppd_const_t
*c
; /* Current constraint */
3463 ppd_option_t
*o1
, *o2
; /* Options */
3464 ppd_choice_t
*c1
, *c2
; /* Choices */
3468 * Loop through all of the UI constraints and report any options
3472 for (i
= ppd
->num_consts
, c
= ppd
->consts
; i
> 0; i
--, c
++)
3475 * Grab pointers to the first option...
3478 o1
= ppdFindOption(ppd
, c
->option1
);
3482 else if (c
->choice1
[0] != '\0')
3485 * This constraint maps to a specific choice.
3488 c1
= ppdFindChoice(o1
, c
->choice1
);
3493 * This constraint applies to any choice for this option.
3496 for (j
= o1
->num_choices
, c1
= o1
->choices
; j
> 0; j
--, c1
++)
3501 !_cups_strcasecmp(c1
->choice
, "None") ||
3502 !_cups_strcasecmp(c1
->choice
, "Off") ||
3503 !_cups_strcasecmp(c1
->choice
, "False"))
3508 * Grab pointers to the second option...
3511 o2
= ppdFindOption(ppd
, c
->option2
);
3515 else if (c
->choice2
[0] != '\0')
3518 * This constraint maps to a specific choice.
3521 c2
= ppdFindChoice(o2
, c
->choice2
);
3526 * This constraint applies to any choice for this option.
3529 for (j
= o2
->num_choices
, c2
= o2
->choices
; j
> 0; j
--, c2
++)
3534 !_cups_strcasecmp(c2
->choice
, "None") ||
3535 !_cups_strcasecmp(c2
->choice
, "Off") ||
3536 !_cups_strcasecmp(c2
->choice
, "False"))
3541 * If both options are marked then there is a conflict...
3544 if (c1
!= NULL
&& c1
->marked
&& c2
!= NULL
&& c2
->marked
)
3545 _cupsLangPrintf(stdout
,
3546 _(" %s \"%s %s\" conflicts with \"%s %s\"\n"
3547 " (constraint=\"%s %s %s %s\")."),
3548 prefix
, o1
->keyword
, c1
->choice
, o2
->keyword
, c2
->choice
,
3549 c
->option1
, c
->choice1
, c
->option2
, c
->choice2
);
3555 * 'test_raster()' - Test PostScript commands for raster printers.
3558 static int /* O - 1 on success, 0 on failure */
3559 test_raster(ppd_file_t
*ppd
, /* I - PPD file */
3560 int verbose
) /* I - Verbosity */
3562 cups_page_header2_t header
; /* Page header */
3565 ppdMarkDefaults(ppd
);
3566 if (cupsRasterInterpretPPD(&header
, ppd
, 0, NULL
, 0))
3569 _cupsLangPuts(stdout
, _(" FAIL"));
3572 _cupsLangPrintf(stdout
,
3573 _(" **FAIL** Default option code cannot be "
3574 "interpreted: %s"), cupsRasterErrorString());
3580 * Try a test of custom page size code, if available...
3583 if (!ppdPageSize(ppd
, "Custom.612x792"))
3586 ppdMarkOption(ppd
, "PageSize", "Custom.612x792");
3588 if (cupsRasterInterpretPPD(&header
, ppd
, 0, NULL
, 0))
3591 _cupsLangPuts(stdout
, _(" FAIL"));
3594 _cupsLangPrintf(stdout
,
3595 _(" **FAIL** Default option code cannot be "
3596 "interpreted: %s"), cupsRasterErrorString());
3606 * 'usage()' - Show program usage.
3612 _cupsLangPuts(stdout
, _("Usage: cupstestppd [options] filename1.ppd[.gz] "
3613 "[... filenameN.ppd[.gz]]"));
3614 _cupsLangPuts(stdout
, _(" program | cupstestppd [options] -"));
3615 _cupsLangPuts(stdout
, "");
3616 _cupsLangPuts(stdout
, _("Options:"));
3617 _cupsLangPuts(stdout
, "");
3618 _cupsLangPuts(stdout
, _(" -I {filename,filters,none,profiles}"));
3619 _cupsLangPuts(stdout
, _(" Ignore specific warnings."));
3620 _cupsLangPuts(stdout
, _(" -R root-directory Set alternate root."));
3621 _cupsLangPuts(stdout
, _(" -W {all,none,constraints,defaults,duplex,"
3622 "filters,profiles,sizes,translations}"));
3623 _cupsLangPuts(stdout
, _(" Issue warnings instead of "
3625 _cupsLangPuts(stdout
, _(" -q Run silently."));
3626 _cupsLangPuts(stdout
, _(" -r Use 'relaxed' open mode."));
3627 _cupsLangPuts(stdout
, _(" -v Be slightly verbose."));
3628 _cupsLangPuts(stdout
, _(" -vv Be very verbose."));
3635 * 'valid_path()' - Check whether a path has the correct capitalization.
3638 static int /* O - Errors found */
3639 valid_path(const char *keyword
, /* I - Keyword using path */
3640 const char *path
, /* I - Path to check */
3641 int errors
, /* I - Errors found */
3642 int verbose
, /* I - Verbosity level */
3643 int warn
) /* I - Warnings only? */
3645 cups_dir_t
*dir
; /* Current directory */
3646 cups_dentry_t
*dentry
; /* Current directory entry */
3647 char temp
[1024], /* Temporary path */
3648 *ptr
; /* Pointer into temporary path */
3649 const char *prefix
; /* WARN/FAIL prefix */
3652 prefix
= warn
? " WARN " : "**FAIL**";
3655 * Loop over the components of the path, checking that the entry exists with
3656 * the same capitalization...
3659 strlcpy(temp
, path
, sizeof(temp
));
3661 while ((ptr
= strrchr(temp
, '/')) != NULL
)
3664 * Chop off the trailing component so temp == dirname and ptr == basename.
3670 * Try opening the directory containing the base name...
3674 dir
= cupsDirOpen(temp
);
3676 dir
= cupsDirOpen("/");
3682 while ((dentry
= cupsDirRead(dir
)) != NULL
)
3684 if (!strcmp(dentry
->filename
, ptr
))
3692 * Display an error if the filename doesn't exist with the same
3698 if (!warn
&& !errors
&& !verbose
)
3699 _cupsLangPuts(stdout
, _(" FAIL"));
3702 _cupsLangPrintf(stdout
,
3703 _(" %s %s file \"%s\" has the wrong "
3704 "capitalization."), prefix
, keyword
, path
);
3718 * 'valid_utf8()' - Check whether a string contains valid UTF-8 text.
3721 static int /* O - 1 if valid, 0 if not */
3722 valid_utf8(const char *s
) /* I - String to check */
3729 * Check for valid UTF-8 sequence...
3732 if ((*s
& 0xc0) == 0x80)
3733 return (0); /* Illegal suffix byte */
3734 else if ((*s
& 0xe0) == 0xc0)
3737 * 2-byte sequence...
3742 if ((*s
& 0xc0) != 0x80)
3743 return (0); /* Missing suffix byte */
3745 else if ((*s
& 0xf0) == 0xe0)
3748 * 3-byte sequence...
3753 if ((*s
& 0xc0) != 0x80)
3754 return (0); /* Missing suffix byte */
3758 if ((*s
& 0xc0) != 0x80)
3759 return (0); /* Missing suffix byte */
3761 else if ((*s
& 0xf8) == 0xf0)
3764 * 4-byte sequence...
3769 if ((*s
& 0xc0) != 0x80)
3770 return (0); /* Missing suffix byte */
3774 if ((*s
& 0xc0) != 0x80)
3775 return (0); /* Missing suffix byte */
3779 if ((*s
& 0xc0) != 0x80)
3780 return (0); /* Missing suffix byte */
3783 return (0); /* Bad sequence */
3794 * End of "$Id: cupstestppd.c 7807 2008-07-28 21:54:24Z mike $".