Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
srohatgi01
GitHub Repository: srohatgi01/cups
Path: blob/master/systemv/cupstestppd.c
1090 views
1
/*
2
* PPD test program for CUPS.
3
*
4
* THIS PROGRAM IS DEPRECATED AND WILL BE REMOVED IN A FUTURE VERSION OF CUPS.
5
*
6
* Copyright © 2007-2018 by Apple Inc.
7
* Copyright © 1997-2007 by Easy Software Products, all rights reserved.
8
*
9
* Licensed under Apache License v2.0. See the file "LICENSE" for more
10
* information.
11
*
12
* PostScript is a trademark of Adobe Systems, Inc.
13
*/
14
15
/*
16
* Include necessary headers...
17
*/
18
19
#include <cups/cups-private.h>
20
#include <cups/dir.h>
21
#include <cups/ppd-private.h>
22
#include <cups/raster.h>
23
#include <math.h>
24
#ifdef _WIN32
25
# define X_OK 0
26
#endif /* _WIN32 */
27
28
29
/*
30
* Error warning overrides...
31
*/
32
33
enum
34
{
35
WARN_NONE = 0,
36
WARN_CONSTRAINTS = 1,
37
WARN_DEFAULTS = 2,
38
WARN_FILTERS = 4,
39
WARN_PROFILES = 8,
40
WARN_TRANSLATIONS = 16,
41
WARN_DUPLEX = 32,
42
WARN_SIZES = 64,
43
WARN_FILENAME = 128,
44
WARN_ALL = 255
45
};
46
47
48
/*
49
* Error codes...
50
*/
51
52
enum
53
{
54
ERROR_NONE = 0,
55
ERROR_USAGE,
56
ERROR_FILE_OPEN,
57
ERROR_PPD_FORMAT,
58
ERROR_CONFORMANCE
59
};
60
61
62
/*
63
* Line endings...
64
*/
65
66
enum
67
{
68
EOL_NONE = 0,
69
EOL_CR,
70
EOL_LF,
71
EOL_CRLF
72
};
73
74
75
/*
76
* File permissions...
77
*/
78
79
#define MODE_WRITE 0022 /* Group/other write */
80
#define MODE_MASK 0555 /* Owner/group/other read+exec/search */
81
#define MODE_DATAFILE 0444 /* Owner/group/other read */
82
#define MODE_DIRECTORY 0555 /* Owner/group/other read+search */
83
#define MODE_PROGRAM 0555 /* Owner/group/other read+exec */
84
85
86
/*
87
* Local functions...
88
*/
89
90
static void check_basics(const char *filename);
91
static int check_constraints(ppd_file_t *ppd, int errors, int verbose,
92
int warn);
93
static int check_case(ppd_file_t *ppd, int errors, int verbose);
94
static int check_defaults(ppd_file_t *ppd, int errors, int verbose,
95
int warn);
96
static int check_duplex(ppd_file_t *ppd, int errors, int verbose,
97
int warn);
98
static int check_filters(ppd_file_t *ppd, const char *root, int errors,
99
int verbose, int warn);
100
static int check_profiles(ppd_file_t *ppd, const char *root, int errors,
101
int verbose, int warn);
102
static int check_sizes(ppd_file_t *ppd, int errors, int verbose, int warn);
103
static int check_translations(ppd_file_t *ppd, int errors, int verbose,
104
int warn);
105
static void show_conflicts(ppd_file_t *ppd, const char *prefix);
106
static int test_raster(ppd_file_t *ppd, int verbose);
107
static void usage(void) _CUPS_NORETURN;
108
static int valid_path(const char *keyword, const char *path, int errors,
109
int verbose, int warn);
110
static int valid_utf8(const char *s);
111
112
113
/*
114
* 'main()' - Main entry for test program.
115
*/
116
117
int /* O - Exit status */
118
main(int argc, /* I - Number of command-line args */
119
char *argv[]) /* I - Command-line arguments */
120
{
121
int i, j, k, m, n; /* Looping vars */
122
size_t len; /* Length of option name */
123
char *opt; /* Option character */
124
const char *ptr; /* Pointer into string */
125
cups_file_t *fp; /* PPD file */
126
int files; /* Number of files */
127
int verbose; /* Want verbose output? */
128
int warn; /* Which errors to just warn about */
129
int ignore; /* Which errors to ignore */
130
int status; /* Exit status */
131
int errors; /* Number of conformance errors */
132
int ppdversion; /* PPD spec version in PPD file */
133
ppd_status_t error; /* Status of ppdOpen*() */
134
int line; /* Line number for error */
135
char *root; /* Root directory */
136
int xdpi, /* X resolution */
137
ydpi; /* Y resolution */
138
ppd_file_t *ppd; /* PPD file record */
139
ppd_attr_t *attr; /* PPD attribute */
140
ppd_size_t *size; /* Size record */
141
ppd_group_t *group; /* UI group */
142
ppd_option_t *option; /* Standard UI option */
143
ppd_group_t *group2; /* UI group */
144
ppd_option_t *option2; /* Standard UI option */
145
ppd_choice_t *choice; /* Standard UI option choice */
146
struct lconv *loc; /* Locale data */
147
static char *uis[] = { "BOOLEAN", "PICKONE", "PICKMANY" };
148
static char *sections[] = { "ANY", "DOCUMENT", "EXIT",
149
"JCL", "PAGE", "PROLOG" };
150
151
152
_cupsSetLocale(argv);
153
loc = localeconv();
154
155
/*
156
* Display PPD files for each file listed on the command-line...
157
*/
158
159
ppdSetConformance(PPD_CONFORM_STRICT);
160
161
verbose = 0;
162
ppd = NULL;
163
files = 0;
164
status = ERROR_NONE;
165
root = "";
166
warn = WARN_NONE;
167
ignore = WARN_NONE;
168
169
for (i = 1; i < argc; i ++)
170
if (!strcmp(argv[i], "--help"))
171
usage();
172
else if (argv[i][0] == '-' && argv[i][1])
173
{
174
for (opt = argv[i] + 1; *opt; opt ++)
175
switch (*opt)
176
{
177
case 'I' : /* Ignore errors */
178
i ++;
179
180
if (i >= argc)
181
usage();
182
183
if (!strcmp(argv[i], "none"))
184
ignore = WARN_NONE;
185
else if (!strcmp(argv[i], "filename"))
186
ignore |= WARN_FILENAME;
187
else if (!strcmp(argv[i], "filters"))
188
ignore |= WARN_FILTERS;
189
else if (!strcmp(argv[i], "profiles"))
190
ignore |= WARN_PROFILES;
191
else if (!strcmp(argv[i], "all"))
192
ignore = WARN_FILTERS | WARN_PROFILES;
193
else
194
usage();
195
break;
196
197
case 'R' : /* Alternate root directory */
198
i ++;
199
200
if (i >= argc)
201
usage();
202
203
root = argv[i];
204
break;
205
206
case 'W' : /* Turn errors into warnings */
207
i ++;
208
209
if (i >= argc)
210
usage();
211
212
if (!strcmp(argv[i], "none"))
213
warn = WARN_NONE;
214
else if (!strcmp(argv[i], "constraints"))
215
warn |= WARN_CONSTRAINTS;
216
else if (!strcmp(argv[i], "defaults"))
217
warn |= WARN_DEFAULTS;
218
else if (!strcmp(argv[i], "duplex"))
219
warn |= WARN_DUPLEX;
220
else if (!strcmp(argv[i], "filters"))
221
warn |= WARN_FILTERS;
222
else if (!strcmp(argv[i], "profiles"))
223
warn |= WARN_PROFILES;
224
else if (!strcmp(argv[i], "sizes"))
225
warn |= WARN_SIZES;
226
else if (!strcmp(argv[i], "translations"))
227
warn |= WARN_TRANSLATIONS;
228
else if (!strcmp(argv[i], "all"))
229
warn = WARN_ALL;
230
else
231
usage();
232
break;
233
234
case 'q' : /* Quiet mode */
235
if (verbose > 0)
236
{
237
_cupsLangPuts(stderr,
238
_("cupstestppd: The -q option is incompatible "
239
"with the -v option."));
240
return (1);
241
}
242
243
verbose --;
244
break;
245
246
case 'r' : /* Relaxed mode */
247
ppdSetConformance(PPD_CONFORM_RELAXED);
248
break;
249
250
case 'v' : /* Verbose mode */
251
if (verbose < 0)
252
{
253
_cupsLangPuts(stderr,
254
_("cupstestppd: The -v option is incompatible "
255
"with the -q option."));
256
return (1);
257
}
258
259
verbose ++;
260
break;
261
262
default :
263
usage();
264
}
265
}
266
else
267
{
268
/*
269
* Open the PPD file...
270
*/
271
272
if (files && verbose >= 0)
273
puts("");
274
275
files ++;
276
277
if (argv[i][0] == '-')
278
{
279
/*
280
* Read from stdin...
281
*/
282
283
ppd = _ppdOpen(cupsFileStdin(), _PPD_LOCALIZATION_ALL);
284
285
if (verbose >= 0)
286
printf("%s:", (ppd && ppd->pcfilename) ? ppd->pcfilename : "(stdin)");
287
}
288
else
289
{
290
/*
291
* Read from a file...
292
*/
293
294
if (verbose >= 0)
295
printf("%s:", argv[i]);
296
297
if ((fp = cupsFileOpen(argv[i], "r")) != NULL)
298
{
299
ppd = _ppdOpen(fp, _PPD_LOCALIZATION_ALL);
300
cupsFileClose(fp);
301
}
302
else
303
{
304
status = ERROR_FILE_OPEN;
305
306
if (verbose >= 0)
307
{
308
_cupsLangPuts(stdout, _(" FAIL"));
309
_cupsLangPrintf(stdout,
310
_(" **FAIL** Unable to open PPD file - %s on "
311
"line %d."), strerror(errno), 0);
312
continue;
313
}
314
}
315
}
316
317
if (ppd == NULL)
318
{
319
error = ppdLastError(&line);
320
321
if (error <= PPD_ALLOC_ERROR)
322
{
323
status = ERROR_FILE_OPEN;
324
325
if (verbose >= 0)
326
{
327
_cupsLangPuts(stdout, _(" FAIL"));
328
_cupsLangPrintf(stdout,
329
_(" **FAIL** Unable to open PPD file - %s on "
330
"line %d."), strerror(errno), 0);
331
}
332
}
333
else
334
{
335
status = ERROR_PPD_FORMAT;
336
337
if (verbose >= 0)
338
{
339
_cupsLangPuts(stdout, _(" FAIL"));
340
_cupsLangPrintf(stdout,
341
_(" **FAIL** Unable to open PPD file - "
342
"%s on line %d."),
343
ppdErrorString(error), line);
344
345
switch (error)
346
{
347
case PPD_MISSING_PPDADOBE4 :
348
_cupsLangPuts(stdout,
349
_(" REF: Page 42, section "
350
"5.2."));
351
break;
352
case PPD_MISSING_VALUE :
353
_cupsLangPuts(stdout,
354
_(" REF: Page 20, section "
355
"3.4."));
356
break;
357
case PPD_BAD_OPEN_GROUP :
358
case PPD_NESTED_OPEN_GROUP :
359
_cupsLangPuts(stdout,
360
_(" REF: Pages 45-46, section "
361
"5.2."));
362
break;
363
case PPD_BAD_OPEN_UI :
364
case PPD_NESTED_OPEN_UI :
365
_cupsLangPuts(stdout,
366
_(" REF: Pages 42-45, section "
367
"5.2."));
368
break;
369
case PPD_BAD_ORDER_DEPENDENCY :
370
_cupsLangPuts(stdout,
371
_(" REF: Pages 48-49, section "
372
"5.2."));
373
break;
374
case PPD_BAD_UI_CONSTRAINTS :
375
_cupsLangPuts(stdout,
376
_(" REF: Pages 52-54, section "
377
"5.2."));
378
break;
379
case PPD_MISSING_ASTERISK :
380
_cupsLangPuts(stdout,
381
_(" REF: Page 15, section "
382
"3.2."));
383
break;
384
case PPD_LINE_TOO_LONG :
385
_cupsLangPuts(stdout,
386
_(" REF: Page 15, section "
387
"3.1."));
388
break;
389
case PPD_ILLEGAL_CHARACTER :
390
_cupsLangPuts(stdout,
391
_(" REF: Page 15, section "
392
"3.1."));
393
break;
394
case PPD_ILLEGAL_MAIN_KEYWORD :
395
_cupsLangPuts(stdout,
396
_(" REF: Pages 16-17, section "
397
"3.2."));
398
break;
399
case PPD_ILLEGAL_OPTION_KEYWORD :
400
_cupsLangPuts(stdout,
401
_(" REF: Page 19, section "
402
"3.3."));
403
break;
404
case PPD_ILLEGAL_TRANSLATION :
405
_cupsLangPuts(stdout,
406
_(" REF: Page 27, section "
407
"3.5."));
408
break;
409
default :
410
break;
411
}
412
413
check_basics(argv[i]);
414
}
415
}
416
417
continue;
418
}
419
420
/*
421
* Show the header and then perform basic conformance tests (limited
422
* only by what the CUPS PPD functions actually load...)
423
*/
424
425
errors = 0;
426
ppdversion = 43;
427
428
if (verbose > 0)
429
_cupsLangPuts(stdout,
430
_("\n DETAILED CONFORMANCE TEST RESULTS"));
431
432
if ((attr = ppdFindAttr(ppd, "FormatVersion", NULL)) != NULL &&
433
attr->value)
434
ppdversion = (int)(10 * _cupsStrScand(attr->value, NULL, loc) + 0.5);
435
436
if ((attr = ppdFindAttr(ppd, "cupsFilter2", NULL)) != NULL)
437
{
438
do
439
{
440
if (strstr(attr->value, "application/vnd.cups-raster"))
441
{
442
if (!test_raster(ppd, verbose))
443
errors ++;
444
break;
445
}
446
}
447
while ((attr = ppdFindNextAttr(ppd, "cupsFilter2", NULL)) != NULL);
448
}
449
else
450
{
451
for (j = 0; j < ppd->num_filters; j ++)
452
if (strstr(ppd->filters[j], "application/vnd.cups-raster"))
453
{
454
if (!test_raster(ppd, verbose))
455
errors ++;
456
break;
457
}
458
}
459
460
/*
461
* Look for default keywords with no matching option...
462
*/
463
464
if (!(warn & WARN_DEFAULTS))
465
errors = check_defaults(ppd, errors, verbose, 0);
466
467
if ((attr = ppdFindAttr(ppd, "DefaultImageableArea", NULL)) == NULL)
468
{
469
if (verbose >= 0)
470
{
471
if (!errors && !verbose)
472
_cupsLangPuts(stdout, _(" FAIL"));
473
474
_cupsLangPuts(stdout,
475
_(" **FAIL** REQUIRED DefaultImageableArea\n"
476
" REF: Page 102, section 5.15."));
477
}
478
479
errors ++;
480
}
481
else if (ppdPageSize(ppd, attr->value) == NULL &&
482
strcmp(attr->value, "Unknown"))
483
{
484
if (verbose >= 0)
485
{
486
if (!errors && !verbose)
487
_cupsLangPuts(stdout, _(" FAIL"));
488
489
_cupsLangPrintf(stdout,
490
_(" **FAIL** Bad DefaultImageableArea %s\n"
491
" REF: Page 102, section 5.15."),
492
attr->value);
493
}
494
495
errors ++;
496
}
497
else
498
{
499
if (verbose > 0)
500
_cupsLangPuts(stdout, _(" PASS DefaultImageableArea"));
501
}
502
503
if ((attr = ppdFindAttr(ppd, "DefaultPaperDimension", NULL)) == NULL)
504
{
505
if (verbose >= 0)
506
{
507
if (!errors && !verbose)
508
_cupsLangPuts(stdout, _(" FAIL"));
509
510
_cupsLangPuts(stdout,
511
_(" **FAIL** REQUIRED DefaultPaperDimension\n"
512
" REF: Page 103, section 5.15."));
513
}
514
515
errors ++;
516
}
517
else if (ppdPageSize(ppd, attr->value) == NULL &&
518
strcmp(attr->value, "Unknown"))
519
{
520
if (verbose >= 0)
521
{
522
if (!errors && !verbose)
523
_cupsLangPuts(stdout, _(" FAIL"));
524
525
_cupsLangPrintf(stdout,
526
_(" **FAIL** Bad DefaultPaperDimension %s\n"
527
" REF: Page 103, section 5.15."),
528
attr->value);
529
}
530
531
errors ++;
532
}
533
else if (verbose > 0)
534
_cupsLangPuts(stdout, _(" PASS DefaultPaperDimension"));
535
536
for (j = 0, group = ppd->groups; j < ppd->num_groups; j ++, group ++)
537
for (k = 0, option = group->options;
538
k < group->num_options;
539
k ++, option ++)
540
{
541
/*
542
* Verify that we have a default choice...
543
*/
544
545
if (option->defchoice[0])
546
{
547
if (ppdFindChoice(option, option->defchoice) == NULL &&
548
strcmp(option->defchoice, "Unknown"))
549
{
550
if (verbose >= 0)
551
{
552
if (!errors && !verbose)
553
_cupsLangPuts(stdout, _(" FAIL"));
554
555
_cupsLangPrintf(stdout,
556
_(" **FAIL** Bad Default%s %s\n"
557
" REF: Page 40, section 4.5."),
558
option->keyword, option->defchoice);
559
}
560
561
errors ++;
562
}
563
else if (verbose > 0)
564
_cupsLangPrintf(stdout,
565
_(" PASS Default%s"),
566
option->keyword);
567
}
568
else
569
{
570
if (verbose >= 0)
571
{
572
if (!errors && !verbose)
573
_cupsLangPuts(stdout, _(" FAIL"));
574
575
_cupsLangPrintf(stdout,
576
_(" **FAIL** REQUIRED Default%s\n"
577
" REF: Page 40, section 4.5."),
578
option->keyword);
579
}
580
581
errors ++;
582
}
583
}
584
585
if ((attr = ppdFindAttr(ppd, "FileVersion", NULL)) != NULL)
586
{
587
for (ptr = attr->value; *ptr; ptr ++)
588
if (!isdigit(*ptr & 255) && *ptr != '.')
589
break;
590
591
if (*ptr)
592
{
593
if (verbose >= 0)
594
{
595
if (!errors && !verbose)
596
_cupsLangPuts(stdout, _(" FAIL"));
597
598
_cupsLangPrintf(stdout,
599
_(" **FAIL** Bad FileVersion \"%s\"\n"
600
" REF: Page 56, section 5.3."),
601
attr->value);
602
}
603
604
errors ++;
605
}
606
else if (verbose > 0)
607
_cupsLangPuts(stdout, _(" PASS FileVersion"));
608
}
609
else
610
{
611
if (verbose >= 0)
612
{
613
if (!errors && !verbose)
614
_cupsLangPuts(stdout, _(" FAIL"));
615
616
_cupsLangPuts(stdout,
617
_(" **FAIL** REQUIRED FileVersion\n"
618
" REF: Page 56, section 5.3."));
619
}
620
621
errors ++;
622
}
623
624
if ((attr = ppdFindAttr(ppd, "FormatVersion", NULL)) != NULL)
625
{
626
ptr = attr->value;
627
if (*ptr == '4' && ptr[1] == '.')
628
{
629
630
for (ptr += 2; *ptr; ptr ++)
631
if (!isdigit(*ptr & 255))
632
break;
633
}
634
635
if (*ptr)
636
{
637
if (verbose >= 0)
638
{
639
if (!errors && !verbose)
640
_cupsLangPuts(stdout, _(" FAIL"));
641
642
_cupsLangPrintf(stdout,
643
_(" **FAIL** Bad FormatVersion \"%s\"\n"
644
" REF: Page 56, section 5.3."),
645
attr->value);
646
}
647
648
errors ++;
649
}
650
else if (verbose > 0)
651
_cupsLangPuts(stdout, _(" PASS FormatVersion"));
652
}
653
else
654
{
655
if (verbose >= 0)
656
{
657
if (!errors && !verbose)
658
_cupsLangPuts(stdout, _(" FAIL"));
659
660
_cupsLangPuts(stdout,
661
_(" **FAIL** REQUIRED FormatVersion\n"
662
" REF: Page 56, section 5.3."));
663
}
664
665
errors ++;
666
}
667
668
if (ppd->lang_encoding != NULL)
669
{
670
if (verbose > 0)
671
_cupsLangPuts(stdout, _(" PASS LanguageEncoding"));
672
}
673
else if (ppdversion > 40)
674
{
675
if (verbose >= 0)
676
{
677
if (!errors && !verbose)
678
_cupsLangPuts(stdout, _(" FAIL"));
679
680
_cupsLangPuts(stdout,
681
_(" **FAIL** REQUIRED LanguageEncoding\n"
682
" REF: Pages 56-57, section 5.3."));
683
}
684
685
errors ++;
686
}
687
688
if (ppd->lang_version != NULL)
689
{
690
if (verbose > 0)
691
_cupsLangPuts(stdout, _(" PASS LanguageVersion"));
692
}
693
else
694
{
695
if (verbose >= 0)
696
{
697
if (!errors && !verbose)
698
_cupsLangPuts(stdout, _(" FAIL"));
699
700
_cupsLangPuts(stdout,
701
_(" **FAIL** REQUIRED LanguageVersion\n"
702
" REF: Pages 57-58, section 5.3."));
703
}
704
705
errors ++;
706
}
707
708
if (ppd->manufacturer != NULL)
709
{
710
if (!_cups_strncasecmp(ppd->manufacturer, "Hewlett-Packard", 15) ||
711
!_cups_strncasecmp(ppd->manufacturer, "Hewlett Packard", 15))
712
{
713
if (verbose >= 0)
714
{
715
if (!errors && !verbose)
716
_cupsLangPuts(stdout, _(" FAIL"));
717
718
_cupsLangPrintf(stdout,
719
_(" **FAIL** Bad Manufacturer (should be "
720
"\"%s\")\n"
721
" REF: Page 211, table D.1."),
722
"HP");
723
}
724
725
errors ++;
726
}
727
else if (!_cups_strncasecmp(ppd->manufacturer, "OkiData", 7) ||
728
!_cups_strncasecmp(ppd->manufacturer, "Oki Data", 8))
729
{
730
if (verbose >= 0)
731
{
732
if (!errors && !verbose)
733
_cupsLangPuts(stdout, _(" FAIL"));
734
735
_cupsLangPrintf(stdout,
736
_(" **FAIL** Bad Manufacturer (should be "
737
"\"%s\")\n"
738
" REF: Page 211, table D.1."),
739
"Oki");
740
}
741
742
errors ++;
743
}
744
else if (verbose > 0)
745
_cupsLangPuts(stdout, _(" PASS Manufacturer"));
746
}
747
else if (ppdversion >= 43)
748
{
749
if (verbose >= 0)
750
{
751
if (!errors && !verbose)
752
_cupsLangPuts(stdout, _(" FAIL"));
753
754
_cupsLangPuts(stdout,
755
_(" **FAIL** REQUIRED Manufacturer\n"
756
" REF: Pages 58-59, section 5.3."));
757
}
758
759
errors ++;
760
}
761
762
if (ppd->modelname != NULL)
763
{
764
for (ptr = ppd->modelname; *ptr; ptr ++)
765
if (!isalnum(*ptr & 255) && !strchr(" ./-+", *ptr))
766
break;
767
768
if (*ptr)
769
{
770
if (verbose >= 0)
771
{
772
if (!errors && !verbose)
773
_cupsLangPuts(stdout, _(" FAIL"));
774
775
_cupsLangPrintf(stdout,
776
_(" **FAIL** Bad ModelName - \"%c\" not "
777
"allowed in string.\n"
778
" REF: Pages 59-60, section 5.3."),
779
*ptr);
780
}
781
782
errors ++;
783
}
784
else if (verbose > 0)
785
_cupsLangPuts(stdout, _(" PASS ModelName"));
786
}
787
else
788
{
789
if (verbose >= 0)
790
{
791
if (!errors && !verbose)
792
_cupsLangPuts(stdout, _(" FAIL"));
793
794
_cupsLangPuts(stdout,
795
_(" **FAIL** REQUIRED ModelName\n"
796
" REF: Pages 59-60, section 5.3."));
797
}
798
799
errors ++;
800
}
801
802
if (ppd->nickname != NULL)
803
{
804
if (verbose > 0)
805
_cupsLangPuts(stdout, _(" PASS NickName"));
806
}
807
else
808
{
809
if (verbose >= 0)
810
{
811
if (!errors && !verbose)
812
_cupsLangPuts(stdout, _(" FAIL"));
813
814
_cupsLangPuts(stdout,
815
_(" **FAIL** REQUIRED NickName\n"
816
" REF: Page 60, section 5.3."));
817
}
818
819
errors ++;
820
}
821
822
if (ppdFindOption(ppd, "PageSize") != NULL)
823
{
824
if (verbose > 0)
825
_cupsLangPuts(stdout, _(" PASS PageSize"));
826
}
827
else
828
{
829
if (verbose >= 0)
830
{
831
if (!errors && !verbose)
832
_cupsLangPuts(stdout, _(" FAIL"));
833
834
_cupsLangPuts(stdout,
835
_(" **FAIL** REQUIRED PageSize\n"
836
" REF: Pages 99-100, section 5.14."));
837
}
838
839
errors ++;
840
}
841
842
if (ppdFindOption(ppd, "PageRegion") != NULL)
843
{
844
if (verbose > 0)
845
_cupsLangPuts(stdout, _(" PASS PageRegion"));
846
}
847
else
848
{
849
if (verbose >= 0)
850
{
851
if (!errors && !verbose)
852
_cupsLangPuts(stdout, _(" FAIL"));
853
854
_cupsLangPuts(stdout,
855
_(" **FAIL** REQUIRED PageRegion\n"
856
" REF: Page 100, section 5.14."));
857
}
858
859
errors ++;
860
}
861
862
if (ppd->pcfilename != NULL)
863
{
864
if (verbose > 0)
865
_cupsLangPuts(stdout, _(" PASS PCFileName"));
866
}
867
else if (!(ignore & WARN_FILENAME))
868
{
869
if (verbose >= 0)
870
{
871
if (!errors && !verbose)
872
_cupsLangPuts(stdout, _(" FAIL"));
873
874
_cupsLangPuts(stdout,
875
_(" **FAIL** REQUIRED PCFileName\n"
876
" REF: Pages 61-62, section 5.3."));
877
}
878
879
errors ++;
880
}
881
882
if (ppd->product != NULL)
883
{
884
if (ppd->product[0] != '(' ||
885
ppd->product[strlen(ppd->product) - 1] != ')')
886
{
887
if (verbose >= 0)
888
{
889
if (!errors && !verbose)
890
_cupsLangPuts(stdout, _(" FAIL"));
891
892
_cupsLangPuts(stdout,
893
_(" **FAIL** Bad Product - not \"(string)\".\n"
894
" REF: Page 62, section 5.3."));
895
}
896
897
errors ++;
898
}
899
else if (verbose > 0)
900
_cupsLangPuts(stdout, _(" PASS Product"));
901
}
902
else
903
{
904
if (verbose >= 0)
905
{
906
if (!errors && !verbose)
907
_cupsLangPuts(stdout, _(" FAIL"));
908
909
_cupsLangPuts(stdout,
910
_(" **FAIL** REQUIRED Product\n"
911
" REF: Page 62, section 5.3."));
912
}
913
914
errors ++;
915
}
916
917
if ((attr = ppdFindAttr(ppd, "PSVersion", NULL)) != NULL &&
918
attr->value != NULL)
919
{
920
char junkstr[255]; /* Temp string */
921
int junkint; /* Temp integer */
922
923
924
if (sscanf(attr->value, "(%254[^)\n])%d", junkstr, &junkint) != 2)
925
{
926
if (verbose >= 0)
927
{
928
if (!errors && !verbose)
929
_cupsLangPuts(stdout, _(" FAIL"));
930
931
_cupsLangPuts(stdout,
932
_(" **FAIL** Bad PSVersion - not \"(string) "
933
"int\".\n"
934
" REF: Pages 62-64, section 5.3."));
935
}
936
937
errors ++;
938
}
939
else if (verbose > 0)
940
_cupsLangPuts(stdout, _(" PASS PSVersion"));
941
}
942
else
943
{
944
if (verbose >= 0)
945
{
946
if (!errors && !verbose)
947
_cupsLangPuts(stdout, _(" FAIL"));
948
949
_cupsLangPuts(stdout,
950
_(" **FAIL** REQUIRED PSVersion\n"
951
" REF: Pages 62-64, section 5.3."));
952
}
953
954
errors ++;
955
}
956
957
if (ppd->shortnickname != NULL)
958
{
959
if (strlen(ppd->shortnickname) > 31)
960
{
961
if (verbose >= 0)
962
{
963
if (!errors && !verbose)
964
_cupsLangPuts(stdout, _(" FAIL"));
965
966
_cupsLangPuts(stdout,
967
_(" **FAIL** Bad ShortNickName - longer "
968
"than 31 chars.\n"
969
" REF: Pages 64-65, section 5.3."));
970
}
971
972
errors ++;
973
}
974
else if (verbose > 0)
975
_cupsLangPuts(stdout, _(" PASS ShortNickName"));
976
}
977
else if (ppdversion >= 43)
978
{
979
if (verbose >= 0)
980
{
981
if (!errors && !verbose)
982
_cupsLangPuts(stdout, _(" FAIL"));
983
984
_cupsLangPuts(stdout,
985
_(" **FAIL** REQUIRED ShortNickName\n"
986
" REF: Page 64-65, section 5.3."));
987
}
988
989
errors ++;
990
}
991
992
if (ppd->patches != NULL && strchr(ppd->patches, '\"') &&
993
strstr(ppd->patches, "*End"))
994
{
995
if (verbose >= 0)
996
{
997
if (!errors && !verbose)
998
_cupsLangPuts(stdout, _(" FAIL"));
999
1000
_cupsLangPuts(stdout,
1001
_(" **FAIL** Bad JobPatchFile attribute in file\n"
1002
" REF: Page 24, section 3.4."));
1003
}
1004
1005
errors ++;
1006
}
1007
1008
/*
1009
* Check for page sizes without the corresponding ImageableArea or
1010
* PaperDimension values...
1011
*/
1012
1013
if (ppd->num_sizes == 0)
1014
{
1015
if (verbose >= 0)
1016
{
1017
if (!errors && !verbose)
1018
_cupsLangPuts(stdout, _(" FAIL"));
1019
1020
_cupsLangPuts(stdout,
1021
_(" **FAIL** REQUIRED PageSize\n"
1022
" REF: Page 41, section 5.\n"
1023
" REF: Page 99, section 5.14."));
1024
}
1025
1026
errors ++;
1027
}
1028
else
1029
{
1030
for (j = 0, size = ppd->sizes; j < ppd->num_sizes; j ++, size ++)
1031
{
1032
/*
1033
* Don't check custom size...
1034
*/
1035
1036
if (!strcmp(size->name, "Custom"))
1037
continue;
1038
1039
/*
1040
* Check for ImageableArea...
1041
*/
1042
1043
if (size->left == 0.0 && size->bottom == 0.0 &&
1044
size->right == 0.0 && size->top == 0.0)
1045
{
1046
if (verbose >= 0)
1047
{
1048
if (!errors && !verbose)
1049
_cupsLangPuts(stdout, _(" FAIL"));
1050
1051
_cupsLangPrintf(stdout,
1052
_(" **FAIL** REQUIRED ImageableArea for "
1053
"PageSize %s\n"
1054
" REF: Page 41, section 5.\n"
1055
" REF: Page 102, section 5.15."),
1056
size->name);
1057
}
1058
1059
errors ++;
1060
}
1061
1062
/*
1063
* Check for PaperDimension...
1064
*/
1065
1066
if (size->width <= 0.0 && size->length <= 0.0)
1067
{
1068
if (verbose >= 0)
1069
{
1070
if (!errors && !verbose)
1071
_cupsLangPuts(stdout, _(" FAIL"));
1072
1073
_cupsLangPrintf(stdout,
1074
_(" **FAIL** REQUIRED PaperDimension "
1075
"for PageSize %s\n"
1076
" REF: Page 41, section 5.\n"
1077
" REF: Page 103, section 5.15."),
1078
size->name);
1079
}
1080
1081
errors ++;
1082
}
1083
}
1084
}
1085
1086
/*
1087
* Check for valid Resolution, JCLResolution, or SetResolution values...
1088
*/
1089
1090
if ((option = ppdFindOption(ppd, "Resolution")) == NULL)
1091
if ((option = ppdFindOption(ppd, "JCLResolution")) == NULL)
1092
option = ppdFindOption(ppd, "SetResolution");
1093
1094
if (option != NULL)
1095
{
1096
for (j = option->num_choices, choice = option->choices;
1097
j > 0;
1098
j --, choice ++)
1099
{
1100
/*
1101
* Verify that all resolution options are of the form NNNdpi
1102
* or NNNxNNNdpi...
1103
*/
1104
1105
xdpi = strtol(choice->choice, (char **)&ptr, 10);
1106
if (ptr > choice->choice && xdpi > 0)
1107
{
1108
if (*ptr == 'x')
1109
ydpi = strtol(ptr + 1, (char **)&ptr, 10);
1110
else
1111
ydpi = xdpi;
1112
}
1113
else
1114
ydpi = xdpi;
1115
1116
if (xdpi <= 0 || xdpi > 99999 || ydpi <= 0 || ydpi > 99999 ||
1117
strcmp(ptr, "dpi"))
1118
{
1119
if (verbose >= 0)
1120
{
1121
if (!errors && !verbose)
1122
_cupsLangPuts(stdout, _(" FAIL"));
1123
1124
_cupsLangPrintf(stdout,
1125
_(" **FAIL** Bad option %s choice %s\n"
1126
" REF: Page 84, section 5.9"),
1127
option->keyword, choice->choice);
1128
}
1129
1130
errors ++;
1131
}
1132
}
1133
}
1134
1135
if ((attr = ppdFindAttr(ppd, "1284DeviceID", NULL)) &&
1136
strcmp(attr->name, "1284DeviceID"))
1137
{
1138
if (verbose >= 0)
1139
{
1140
if (!errors && !verbose)
1141
_cupsLangPuts(stdout, _(" FAIL"));
1142
1143
_cupsLangPrintf(stdout,
1144
_(" **FAIL** %s must be 1284DeviceID\n"
1145
" REF: Page 72, section 5.5"),
1146
attr->name);
1147
}
1148
1149
errors ++;
1150
}
1151
1152
errors = check_case(ppd, errors, verbose);
1153
1154
if (!(warn & WARN_CONSTRAINTS))
1155
errors = check_constraints(ppd, errors, verbose, 0);
1156
1157
if (!(warn & WARN_FILTERS) && !(ignore & WARN_FILTERS))
1158
errors = check_filters(ppd, root, errors, verbose, 0);
1159
1160
if (!(warn & WARN_PROFILES) && !(ignore & WARN_PROFILES))
1161
errors = check_profiles(ppd, root, errors, verbose, 0);
1162
1163
if (!(warn & WARN_SIZES))
1164
errors = check_sizes(ppd, errors, verbose, 0);
1165
1166
if (!(warn & WARN_TRANSLATIONS))
1167
errors = check_translations(ppd, errors, verbose, 0);
1168
1169
if (!(warn & WARN_DUPLEX))
1170
errors = check_duplex(ppd, errors, verbose, 0);
1171
1172
if ((attr = ppdFindAttr(ppd, "cupsLanguages", NULL)) != NULL &&
1173
attr->value)
1174
{
1175
/*
1176
* This file contains localizations, check for conformance of the
1177
* base translation...
1178
*/
1179
1180
if ((attr = ppdFindAttr(ppd, "LanguageEncoding", NULL)) != NULL)
1181
{
1182
if (!attr->value || strcmp(attr->value, "ISOLatin1"))
1183
{
1184
if (!errors && !verbose)
1185
_cupsLangPuts(stdout, _(" FAIL"));
1186
1187
if (verbose >= 0)
1188
_cupsLangPrintf(stdout,
1189
_(" **FAIL** Bad LanguageEncoding %s - "
1190
"must be ISOLatin1."),
1191
attr->value ? attr->value : "(null)");
1192
1193
errors ++;
1194
}
1195
1196
if (!ppd->lang_version || strcmp(ppd->lang_version, "English"))
1197
{
1198
if (!errors && !verbose)
1199
_cupsLangPuts(stdout, _(" FAIL"));
1200
1201
if (verbose >= 0)
1202
_cupsLangPrintf(stdout,
1203
_(" **FAIL** Bad LanguageVersion %s - "
1204
"must be English."),
1205
ppd->lang_version ? ppd->lang_version : "(null)");
1206
1207
errors ++;
1208
}
1209
1210
/*
1211
* Loop through all options and choices...
1212
*/
1213
1214
for (option = ppdFirstOption(ppd);
1215
option;
1216
option = ppdNextOption(ppd))
1217
{
1218
/*
1219
* Check for special characters outside A0 to BF, F7, or F8
1220
* that are used for languages other than English.
1221
*/
1222
1223
for (ptr = option->text; *ptr; ptr ++)
1224
if ((*ptr & 0x80) && (*ptr & 0xe0) != 0xa0 &&
1225
(*ptr & 0xff) != 0xf7 && (*ptr & 0xff) != 0xf8)
1226
break;
1227
1228
if (*ptr)
1229
{
1230
if (!errors && !verbose)
1231
_cupsLangPuts(stdout, _(" FAIL"));
1232
1233
if (verbose >= 0)
1234
_cupsLangPrintf(stdout,
1235
_(" **FAIL** Default translation "
1236
"string for option %s contains 8-bit "
1237
"characters."),
1238
option->keyword);
1239
1240
errors ++;
1241
}
1242
1243
for (j = 0; j < option->num_choices; j ++)
1244
{
1245
/*
1246
* Check for special characters outside A0 to BF, F7, or F8
1247
* that are used for languages other than English.
1248
*/
1249
1250
for (ptr = option->choices[j].text; *ptr; ptr ++)
1251
if ((*ptr & 0x80) && (*ptr & 0xe0) != 0xa0 &&
1252
(*ptr & 0xff) != 0xf7 && (*ptr & 0xff) != 0xf8)
1253
break;
1254
1255
if (*ptr)
1256
{
1257
if (!errors && !verbose)
1258
_cupsLangPuts(stdout, _(" FAIL"));
1259
1260
if (verbose >= 0)
1261
_cupsLangPrintf(stdout,
1262
_(" **FAIL** Default translation "
1263
"string for option %s choice %s contains "
1264
"8-bit characters."),
1265
option->keyword,
1266
option->choices[j].choice);
1267
1268
errors ++;
1269
}
1270
}
1271
}
1272
}
1273
}
1274
1275
/*
1276
* Final pass/fail notification...
1277
*/
1278
1279
if (errors)
1280
status = ERROR_CONFORMANCE;
1281
else if (!verbose)
1282
_cupsLangPuts(stdout, _(" PASS"));
1283
1284
if (verbose >= 0)
1285
{
1286
check_basics(argv[i]);
1287
1288
if (warn & WARN_DEFAULTS)
1289
errors = check_defaults(ppd, errors, verbose, 1);
1290
1291
if (warn & WARN_CONSTRAINTS)
1292
errors = check_constraints(ppd, errors, verbose, 1);
1293
1294
if ((warn & WARN_FILTERS) && !(ignore & WARN_FILTERS))
1295
errors = check_filters(ppd, root, errors, verbose, 1);
1296
1297
if ((warn & WARN_PROFILES) && !(ignore & WARN_PROFILES))
1298
errors = check_profiles(ppd, root, errors, verbose, 1);
1299
1300
if (warn & WARN_SIZES)
1301
errors = check_sizes(ppd, errors, verbose, 1);
1302
else
1303
errors = check_sizes(ppd, errors, verbose, 2);
1304
1305
if (warn & WARN_TRANSLATIONS)
1306
errors = check_translations(ppd, errors, verbose, 1);
1307
1308
if (warn & WARN_DUPLEX)
1309
errors = check_duplex(ppd, errors, verbose, 1);
1310
1311
/*
1312
* Look for legacy duplex keywords...
1313
*/
1314
1315
if ((option = ppdFindOption(ppd, "JCLDuplex")) == NULL)
1316
if ((option = ppdFindOption(ppd, "EFDuplex")) == NULL)
1317
option = ppdFindOption(ppd, "KD03Duplex");
1318
1319
if (option)
1320
_cupsLangPrintf(stdout,
1321
_(" WARN Duplex option keyword %s may not "
1322
"work as expected and should be named Duplex.\n"
1323
" REF: Page 122, section 5.17"),
1324
option->keyword);
1325
1326
/*
1327
* Look for default keywords with no corresponding option...
1328
*/
1329
1330
for (j = 0; j < ppd->num_attrs; j ++)
1331
{
1332
attr = ppd->attrs[j];
1333
1334
if (!strcmp(attr->name, "DefaultColorSpace") ||
1335
!strcmp(attr->name, "DefaultColorSep") ||
1336
!strcmp(attr->name, "DefaultFont") ||
1337
!strcmp(attr->name, "DefaultHalftoneType") ||
1338
!strcmp(attr->name, "DefaultImageableArea") ||
1339
!strcmp(attr->name, "DefaultLeadingEdge") ||
1340
!strcmp(attr->name, "DefaultOutputOrder") ||
1341
!strcmp(attr->name, "DefaultPaperDimension") ||
1342
!strcmp(attr->name, "DefaultResolution") ||
1343
!strcmp(attr->name, "DefaultScreenProc") ||
1344
!strcmp(attr->name, "DefaultTransfer"))
1345
continue;
1346
1347
if (!strncmp(attr->name, "Default", 7) &&
1348
!ppdFindOption(ppd, attr->name + 7))
1349
_cupsLangPrintf(stdout,
1350
_(" WARN %s has no corresponding "
1351
"options."),
1352
attr->name);
1353
}
1354
1355
if (ppdversion < 43)
1356
{
1357
_cupsLangPrintf(stdout,
1358
_(" WARN Obsolete PPD version %.1f.\n"
1359
" REF: Page 42, section 5.2."),
1360
0.1f * ppdversion);
1361
}
1362
1363
if (!ppd->lang_encoding && ppdversion < 41)
1364
{
1365
_cupsLangPuts(stdout,
1366
_(" WARN LanguageEncoding required by PPD "
1367
"4.3 spec.\n"
1368
" REF: Pages 56-57, section 5.3."));
1369
}
1370
1371
if (!ppd->manufacturer && ppdversion < 43)
1372
{
1373
_cupsLangPuts(stdout,
1374
_(" WARN Manufacturer required by PPD "
1375
"4.3 spec.\n"
1376
" REF: Pages 58-59, section 5.3."));
1377
}
1378
1379
/*
1380
* Treat a PCFileName attribute longer than 12 characters as
1381
* a warning and not a hard error...
1382
*/
1383
1384
if (!(ignore & WARN_FILENAME) && ppd->pcfilename)
1385
{
1386
if (strlen(ppd->pcfilename) > 12)
1387
{
1388
_cupsLangPuts(stdout,
1389
_(" WARN PCFileName longer than 8.3 in "
1390
"violation of PPD spec.\n"
1391
" REF: Pages 61-62, section "
1392
"5.3."));
1393
}
1394
1395
if (!_cups_strcasecmp(ppd->pcfilename, "unused.ppd"))
1396
_cupsLangPuts(stdout,
1397
_(" WARN PCFileName should contain a "
1398
"unique filename.\n"
1399
" REF: Pages 61-62, section "
1400
"5.3."));
1401
}
1402
1403
if (!ppd->shortnickname && ppdversion < 43)
1404
{
1405
_cupsLangPuts(stdout,
1406
_(" WARN ShortNickName required by PPD "
1407
"4.3 spec.\n"
1408
" REF: Pages 64-65, section 5.3."));
1409
}
1410
1411
/*
1412
* Check the Protocols line and flag PJL + BCP since TBCP is
1413
* usually used with PJL...
1414
*/
1415
1416
if (ppd->protocols)
1417
{
1418
if (strstr(ppd->protocols, "PJL") &&
1419
strstr(ppd->protocols, "BCP") &&
1420
!strstr(ppd->protocols, "TBCP"))
1421
{
1422
_cupsLangPuts(stdout,
1423
_(" WARN Protocols contains both PJL "
1424
"and BCP; expected TBCP.\n"
1425
" REF: Pages 78-79, section 5.7."));
1426
}
1427
1428
if (strstr(ppd->protocols, "PJL") &&
1429
(!ppd->jcl_begin || !ppd->jcl_end || !ppd->jcl_ps))
1430
{
1431
_cupsLangPuts(stdout,
1432
_(" WARN Protocols contains PJL but JCL "
1433
"attributes are not set.\n"
1434
" REF: Pages 78-79, section 5.7."));
1435
}
1436
}
1437
1438
/*
1439
* Check for options with a common prefix, e.g. Duplex and Duplexer,
1440
* which are errors according to the spec but won't cause problems
1441
* with CUPS specifically...
1442
*/
1443
1444
for (j = 0, group = ppd->groups; j < ppd->num_groups; j ++, group ++)
1445
for (k = 0, option = group->options;
1446
k < group->num_options;
1447
k ++, option ++)
1448
{
1449
len = strlen(option->keyword);
1450
1451
for (m = 0, group2 = ppd->groups;
1452
m < ppd->num_groups;
1453
m ++, group2 ++)
1454
for (n = 0, option2 = group2->options;
1455
n < group2->num_options;
1456
n ++, option2 ++)
1457
if (option != option2 &&
1458
len < strlen(option2->keyword) &&
1459
!strncmp(option->keyword, option2->keyword, len))
1460
{
1461
_cupsLangPrintf(stdout,
1462
_(" WARN %s shares a common "
1463
"prefix with %s\n"
1464
" REF: Page 15, section "
1465
"3.2."),
1466
option->keyword, option2->keyword);
1467
}
1468
}
1469
}
1470
1471
if (verbose > 0)
1472
{
1473
if (errors)
1474
_cupsLangPrintf(stdout, _(" %d ERRORS FOUND"), errors);
1475
else
1476
_cupsLangPuts(stdout, _(" NO ERRORS FOUND"));
1477
}
1478
1479
/*
1480
* Then list the options, if "-v" was provided...
1481
*/
1482
1483
if (verbose > 1)
1484
{
1485
_cupsLangPrintf(stdout,
1486
"\n"
1487
" language_level = %d\n"
1488
" color_device = %s\n"
1489
" variable_sizes = %s\n"
1490
" landscape = %d",
1491
ppd->language_level,
1492
ppd->color_device ? "TRUE" : "FALSE",
1493
ppd->variable_sizes ? "TRUE" : "FALSE",
1494
ppd->landscape);
1495
1496
switch (ppd->colorspace)
1497
{
1498
case PPD_CS_CMYK :
1499
_cupsLangPuts(stdout, " colorspace = PPD_CS_CMYK");
1500
break;
1501
case PPD_CS_CMY :
1502
_cupsLangPuts(stdout, " colorspace = PPD_CS_CMY");
1503
break;
1504
case PPD_CS_GRAY :
1505
_cupsLangPuts(stdout, " colorspace = PPD_CS_GRAY");
1506
break;
1507
case PPD_CS_RGB :
1508
_cupsLangPuts(stdout, " colorspace = PPD_CS_RGB");
1509
break;
1510
default :
1511
_cupsLangPuts(stdout, " colorspace = <unknown>");
1512
break;
1513
}
1514
1515
_cupsLangPrintf(stdout, " num_emulations = %d",
1516
ppd->num_emulations);
1517
for (j = 0; j < ppd->num_emulations; j ++)
1518
_cupsLangPrintf(stdout, " emulations[%d] = %s",
1519
j, ppd->emulations[j].name);
1520
1521
_cupsLangPrintf(stdout, " lang_encoding = %s",
1522
ppd->lang_encoding);
1523
_cupsLangPrintf(stdout, " lang_version = %s",
1524
ppd->lang_version);
1525
_cupsLangPrintf(stdout, " modelname = %s", ppd->modelname);
1526
_cupsLangPrintf(stdout, " ttrasterizer = %s",
1527
ppd->ttrasterizer == NULL ? "None" : ppd->ttrasterizer);
1528
_cupsLangPrintf(stdout, " manufacturer = %s",
1529
ppd->manufacturer);
1530
_cupsLangPrintf(stdout, " product = %s", ppd->product);
1531
_cupsLangPrintf(stdout, " nickname = %s", ppd->nickname);
1532
_cupsLangPrintf(stdout, " shortnickname = %s",
1533
ppd->shortnickname);
1534
_cupsLangPrintf(stdout, " patches = %d bytes",
1535
ppd->patches == NULL ? 0 : (int)strlen(ppd->patches));
1536
1537
_cupsLangPrintf(stdout, " num_groups = %d", ppd->num_groups);
1538
for (j = 0, group = ppd->groups; j < ppd->num_groups; j ++, group ++)
1539
{
1540
_cupsLangPrintf(stdout, " group[%d] = %s",
1541
j, group->text);
1542
1543
for (k = 0, option = group->options; k < group->num_options; k ++, option ++)
1544
{
1545
_cupsLangPrintf(stdout,
1546
" options[%d] = %s (%s) %s %s %.0f "
1547
"(%d choices)",
1548
k, option->keyword, option->text, uis[option->ui],
1549
sections[option->section], option->order,
1550
option->num_choices);
1551
1552
if (!strcmp(option->keyword, "PageSize") ||
1553
!strcmp(option->keyword, "PageRegion"))
1554
{
1555
for (m = option->num_choices, choice = option->choices;
1556
m > 0;
1557
m --, choice ++)
1558
{
1559
size = ppdPageSize(ppd, choice->choice);
1560
1561
if (size == NULL)
1562
_cupsLangPrintf(stdout,
1563
" %s (%s) = ERROR%s",
1564
choice->choice, choice->text,
1565
!strcmp(option->defchoice, choice->choice)
1566
? " *" : "");
1567
else
1568
_cupsLangPrintf(stdout,
1569
" %s (%s) = %.2fx%.2fin "
1570
"(%.1f,%.1f,%.1f,%.1f)%s",
1571
choice->choice, choice->text,
1572
size->width / 72.0, size->length / 72.0,
1573
size->left / 72.0, size->bottom / 72.0,
1574
size->right / 72.0, size->top / 72.0,
1575
!strcmp(option->defchoice, choice->choice)
1576
? " *" : "");
1577
}
1578
}
1579
else
1580
{
1581
for (m = option->num_choices, choice = option->choices;
1582
m > 0;
1583
m --, choice ++)
1584
{
1585
_cupsLangPrintf(stdout, " %s (%s)%s",
1586
choice->choice, choice->text,
1587
!strcmp(option->defchoice, choice->choice)
1588
? " *" : "");
1589
}
1590
}
1591
}
1592
}
1593
1594
_cupsLangPrintf(stdout, " num_consts = %d",
1595
ppd->num_consts);
1596
for (j = 0; j < ppd->num_consts; j ++)
1597
_cupsLangPrintf(stdout,
1598
" consts[%d] = *%s %s *%s %s",
1599
j, ppd->consts[j].option1, ppd->consts[j].choice1,
1600
ppd->consts[j].option2, ppd->consts[j].choice2);
1601
1602
_cupsLangPrintf(stdout, " num_profiles = %d",
1603
ppd->num_profiles);
1604
for (j = 0; j < ppd->num_profiles; j ++)
1605
_cupsLangPrintf(stdout,
1606
" profiles[%d] = %s/%s %.3f %.3f "
1607
"[ %.3f %.3f %.3f %.3f %.3f %.3f %.3f %.3f %.3f ]",
1608
j, ppd->profiles[j].resolution,
1609
ppd->profiles[j].media_type,
1610
ppd->profiles[j].gamma, ppd->profiles[j].density,
1611
ppd->profiles[j].matrix[0][0],
1612
ppd->profiles[j].matrix[0][1],
1613
ppd->profiles[j].matrix[0][2],
1614
ppd->profiles[j].matrix[1][0],
1615
ppd->profiles[j].matrix[1][1],
1616
ppd->profiles[j].matrix[1][2],
1617
ppd->profiles[j].matrix[2][0],
1618
ppd->profiles[j].matrix[2][1],
1619
ppd->profiles[j].matrix[2][2]);
1620
1621
_cupsLangPrintf(stdout, " num_fonts = %d", ppd->num_fonts);
1622
for (j = 0; j < ppd->num_fonts; j ++)
1623
_cupsLangPrintf(stdout, " fonts[%d] = %s",
1624
j, ppd->fonts[j]);
1625
1626
_cupsLangPrintf(stdout, " num_attrs = %d", ppd->num_attrs);
1627
for (j = 0; j < ppd->num_attrs; j ++)
1628
_cupsLangPrintf(stdout,
1629
" attrs[%d] = %s %s%s%s: \"%s\"", j,
1630
ppd->attrs[j]->name, ppd->attrs[j]->spec,
1631
ppd->attrs[j]->text[0] ? "/" : "",
1632
ppd->attrs[j]->text,
1633
ppd->attrs[j]->value ?
1634
ppd->attrs[j]->value : "(null)");
1635
}
1636
1637
ppdClose(ppd);
1638
}
1639
1640
if (!files)
1641
usage();
1642
1643
return (status);
1644
}
1645
1646
1647
/*
1648
* 'check_basics()' - Check for CR LF, mixed line endings, and blank lines.
1649
*/
1650
1651
static void
1652
check_basics(const char *filename) /* I - PPD file to check */
1653
{
1654
cups_file_t *fp; /* File pointer */
1655
int ch; /* Current character */
1656
int col, /* Current column */
1657
whitespace; /* Only seen whitespace? */
1658
int eol; /* Line endings */
1659
int linenum; /* Line number */
1660
int mixed; /* Mixed line endings? */
1661
1662
1663
if ((fp = cupsFileOpen(filename, "r")) == NULL)
1664
return;
1665
1666
linenum = 1;
1667
col = 0;
1668
eol = EOL_NONE;
1669
mixed = 0;
1670
whitespace = 1;
1671
1672
while ((ch = cupsFileGetChar(fp)) != EOF)
1673
{
1674
if (ch == '\r' || ch == '\n')
1675
{
1676
if (ch == '\n')
1677
{
1678
if (eol == EOL_NONE)
1679
eol = EOL_LF;
1680
else if (eol != EOL_LF)
1681
mixed = 1;
1682
}
1683
else if (ch == '\r')
1684
{
1685
if (cupsFilePeekChar(fp) == '\n')
1686
{
1687
cupsFileGetChar(fp);
1688
1689
if (eol == EOL_NONE)
1690
eol = EOL_CRLF;
1691
else if (eol != EOL_CRLF)
1692
mixed = 1;
1693
}
1694
else if (eol == EOL_NONE)
1695
eol = EOL_CR;
1696
else if (eol != EOL_CR)
1697
mixed = 1;
1698
}
1699
1700
if (col > 0 && whitespace)
1701
_cupsLangPrintf(stdout,
1702
_(" WARN Line %d only contains whitespace."),
1703
linenum);
1704
1705
linenum ++;
1706
col = 0;
1707
whitespace = 1;
1708
}
1709
else
1710
{
1711
if (ch != ' ' && ch != '\t')
1712
whitespace = 0;
1713
1714
col ++;
1715
}
1716
}
1717
1718
if (mixed)
1719
_cupsLangPuts(stdout,
1720
_(" WARN File contains a mix of CR, LF, and "
1721
"CR LF line endings."));
1722
1723
if (eol == EOL_CRLF)
1724
_cupsLangPuts(stdout,
1725
_(" WARN Non-Windows PPD files should use lines "
1726
"ending with only LF, not CR LF."));
1727
1728
cupsFileClose(fp);
1729
}
1730
1731
1732
/*
1733
* 'check_constraints()' - Check UIConstraints in the PPD file.
1734
*/
1735
1736
static int /* O - Errors found */
1737
check_constraints(ppd_file_t *ppd, /* I - PPD file */
1738
int errors, /* I - Errors found */
1739
int verbose, /* I - Verbosity level */
1740
int warn) /* I - Warnings only? */
1741
{
1742
int i; /* Looping var */
1743
const char *prefix; /* WARN/FAIL prefix */
1744
ppd_const_t *c; /* Current UIConstraints data */
1745
ppd_attr_t *constattr; /* Current cupsUIConstraints attribute */
1746
const char *vptr; /* Pointer into constraint value */
1747
char option[PPD_MAX_NAME],
1748
/* Option name/MainKeyword */
1749
choice[PPD_MAX_NAME],
1750
/* Choice/OptionKeyword */
1751
*ptr; /* Pointer into option or choice */
1752
int num_options; /* Number of options */
1753
cups_option_t *options; /* Options */
1754
ppd_option_t *o; /* PPD option */
1755
1756
1757
prefix = warn ? " WARN " : "**FAIL**";
1758
1759
1760
/*
1761
* See what kind of constraint data we have in the PPD...
1762
*/
1763
1764
if ((constattr = ppdFindAttr(ppd, "cupsUIConstraints", NULL)) != NULL)
1765
{
1766
/*
1767
* Check new-style cupsUIConstraints data...
1768
*/
1769
1770
for (; constattr;
1771
constattr = ppdFindNextAttr(ppd, "cupsUIConstraints", NULL))
1772
{
1773
if (!constattr->value)
1774
{
1775
if (!warn && !errors && !verbose)
1776
_cupsLangPuts(stdout, _(" FAIL"));
1777
1778
_cupsLangPrintf(stdout,
1779
_(" %s Empty cupsUIConstraints %s"),
1780
prefix, constattr->spec);
1781
1782
if (!warn)
1783
errors ++;
1784
1785
continue;
1786
}
1787
1788
for (i = 0, vptr = strchr(constattr->value, '*');
1789
vptr;
1790
i ++, vptr = strchr(vptr + 1, '*'));
1791
1792
if (i == 0)
1793
{
1794
if (!warn && !errors && !verbose)
1795
_cupsLangPuts(stdout, _(" FAIL"));
1796
1797
_cupsLangPrintf(stdout,
1798
_(" %s Bad cupsUIConstraints %s: \"%s\""),
1799
prefix, constattr->spec, constattr->value);
1800
1801
if (!warn)
1802
errors ++;
1803
1804
continue;
1805
}
1806
1807
cupsArraySave(ppd->sorted_attrs);
1808
1809
if (constattr->spec[0] &&
1810
!ppdFindAttr(ppd, "cupsUIResolver", constattr->spec))
1811
{
1812
if (!warn && !errors && !verbose)
1813
_cupsLangPuts(stdout, _(" FAIL"));
1814
1815
_cupsLangPrintf(stdout,
1816
_(" %s Missing cupsUIResolver %s"),
1817
prefix, constattr->spec);
1818
1819
if (!warn)
1820
errors ++;
1821
}
1822
1823
cupsArrayRestore(ppd->sorted_attrs);
1824
1825
num_options = 0;
1826
options = NULL;
1827
1828
for (vptr = strchr(constattr->value, '*');
1829
vptr;
1830
vptr = strchr(vptr, '*'))
1831
{
1832
/*
1833
* Extract "*Option Choice" or just "*Option"...
1834
*/
1835
1836
for (vptr ++, ptr = option; *vptr && !isspace(*vptr & 255); vptr ++)
1837
if (ptr < (option + sizeof(option) - 1))
1838
*ptr++ = *vptr;
1839
1840
*ptr = '\0';
1841
1842
while (isspace(*vptr & 255))
1843
vptr ++;
1844
1845
if (*vptr == '*')
1846
choice[0] = '\0';
1847
else
1848
{
1849
for (ptr = choice; *vptr && !isspace(*vptr & 255); vptr ++)
1850
if (ptr < (choice + sizeof(choice) - 1))
1851
*ptr++ = *vptr;
1852
1853
*ptr = '\0';
1854
}
1855
1856
if (!_cups_strncasecmp(option, "Custom", 6) && !_cups_strcasecmp(choice, "True"))
1857
{
1858
_cups_strcpy(option, option + 6);
1859
strlcpy(choice, "Custom", sizeof(choice));
1860
}
1861
1862
if ((o = ppdFindOption(ppd, option)) == NULL)
1863
{
1864
if (!warn && !errors && !verbose)
1865
_cupsLangPuts(stdout, _(" FAIL"));
1866
1867
_cupsLangPrintf(stdout,
1868
_(" %s Missing option %s in "
1869
"cupsUIConstraints %s: \"%s\""),
1870
prefix, option, constattr->spec, constattr->value);
1871
1872
if (!warn)
1873
errors ++;
1874
1875
continue;
1876
}
1877
1878
if (choice[0] && !ppdFindChoice(o, choice))
1879
{
1880
if (!warn && !errors && !verbose)
1881
_cupsLangPuts(stdout, _(" FAIL"));
1882
1883
_cupsLangPrintf(stdout,
1884
_(" %s Missing choice *%s %s in "
1885
"cupsUIConstraints %s: \"%s\""),
1886
prefix, option, choice, constattr->spec,
1887
constattr->value);
1888
1889
if (!warn)
1890
errors ++;
1891
1892
continue;
1893
}
1894
1895
if (choice[0])
1896
num_options = cupsAddOption(option, choice, num_options, &options);
1897
else
1898
{
1899
for (i = 0; i < o->num_choices; i ++)
1900
if (_cups_strcasecmp(o->choices[i].choice, "None") &&
1901
_cups_strcasecmp(o->choices[i].choice, "Off") &&
1902
_cups_strcasecmp(o->choices[i].choice, "False"))
1903
{
1904
num_options = cupsAddOption(option, o->choices[i].choice,
1905
num_options, &options);
1906
break;
1907
}
1908
}
1909
}
1910
1911
/*
1912
* Resolvers must list at least two options...
1913
*/
1914
1915
if (num_options < 2)
1916
{
1917
if (!warn && !errors && !verbose)
1918
_cupsLangPuts(stdout, _(" FAIL"));
1919
1920
_cupsLangPrintf(stdout,
1921
_(" %s cupsUIResolver %s does not list at least "
1922
"two different options."),
1923
prefix, constattr->spec);
1924
1925
if (!warn)
1926
errors ++;
1927
}
1928
1929
/*
1930
* Test the resolver...
1931
*/
1932
1933
if (!cupsResolveConflicts(ppd, NULL, NULL, &num_options, &options))
1934
{
1935
if (!warn && !errors && !verbose)
1936
_cupsLangPuts(stdout, _(" FAIL"));
1937
1938
_cupsLangPrintf(stdout,
1939
_(" %s cupsUIResolver %s causes a loop."),
1940
prefix, constattr->spec);
1941
1942
if (!warn)
1943
errors ++;
1944
}
1945
1946
cupsFreeOptions(num_options, options);
1947
}
1948
}
1949
else
1950
{
1951
/*
1952
* Check old-style [Non]UIConstraints data...
1953
*/
1954
1955
for (i = ppd->num_consts, c = ppd->consts; i > 0; i --, c ++)
1956
{
1957
if (!_cups_strncasecmp(c->option1, "Custom", 6) &&
1958
!_cups_strcasecmp(c->choice1, "True"))
1959
{
1960
strlcpy(option, c->option1 + 6, sizeof(option));
1961
strlcpy(choice, "Custom", sizeof(choice));
1962
}
1963
else
1964
{
1965
strlcpy(option, c->option1, sizeof(option));
1966
strlcpy(choice, c->choice1, sizeof(choice));
1967
}
1968
1969
if ((o = ppdFindOption(ppd, option)) == NULL)
1970
{
1971
if (!warn && !errors && !verbose)
1972
_cupsLangPuts(stdout, _(" FAIL"));
1973
1974
_cupsLangPrintf(stdout,
1975
_(" %s Missing option %s in "
1976
"UIConstraints \"*%s %s *%s %s\"."),
1977
prefix, c->option1,
1978
c->option1, c->choice1, c->option2, c->choice2);
1979
1980
if (!warn)
1981
errors ++;
1982
}
1983
else if (choice[0] && !ppdFindChoice(o, choice))
1984
{
1985
if (!warn && !errors && !verbose)
1986
_cupsLangPuts(stdout, _(" FAIL"));
1987
1988
_cupsLangPrintf(stdout,
1989
_(" %s Missing choice *%s %s in "
1990
"UIConstraints \"*%s %s *%s %s\"."),
1991
prefix, c->option1, c->choice1,
1992
c->option1, c->choice1, c->option2, c->choice2);
1993
1994
if (!warn)
1995
errors ++;
1996
}
1997
1998
if (!_cups_strncasecmp(c->option2, "Custom", 6) &&
1999
!_cups_strcasecmp(c->choice2, "True"))
2000
{
2001
strlcpy(option, c->option2 + 6, sizeof(option));
2002
strlcpy(choice, "Custom", sizeof(choice));
2003
}
2004
else
2005
{
2006
strlcpy(option, c->option2, sizeof(option));
2007
strlcpy(choice, c->choice2, sizeof(choice));
2008
}
2009
2010
if ((o = ppdFindOption(ppd, option)) == NULL)
2011
{
2012
if (!warn && !errors && !verbose)
2013
_cupsLangPuts(stdout, _(" FAIL"));
2014
2015
_cupsLangPrintf(stdout,
2016
_(" %s Missing option %s in "
2017
"UIConstraints \"*%s %s *%s %s\"."),
2018
prefix, c->option2,
2019
c->option1, c->choice1, c->option2, c->choice2);
2020
2021
if (!warn)
2022
errors ++;
2023
}
2024
else if (choice[0] && !ppdFindChoice(o, choice))
2025
{
2026
if (!warn && !errors && !verbose)
2027
_cupsLangPuts(stdout, _(" FAIL"));
2028
2029
_cupsLangPrintf(stdout,
2030
_(" %s Missing choice *%s %s in "
2031
"UIConstraints \"*%s %s *%s %s\"."),
2032
prefix, c->option2, c->choice2,
2033
c->option1, c->choice1, c->option2, c->choice2);
2034
2035
if (!warn)
2036
errors ++;
2037
}
2038
}
2039
}
2040
2041
return (errors);
2042
}
2043
2044
2045
/*
2046
* 'check_case()' - Check that there are no duplicate groups, options,
2047
* or choices that differ only by case.
2048
*/
2049
2050
static int /* O - Errors found */
2051
check_case(ppd_file_t *ppd, /* I - PPD file */
2052
int errors, /* I - Errors found */
2053
int verbose) /* I - Verbosity level */
2054
{
2055
int i, j; /* Looping vars */
2056
ppd_group_t *groupa, /* First group */
2057
*groupb; /* Second group */
2058
ppd_option_t *optiona, /* First option */
2059
*optionb; /* Second option */
2060
ppd_choice_t *choicea, /* First choice */
2061
*choiceb; /* Second choice */
2062
2063
2064
/*
2065
* Check that the groups do not have any duplicate names...
2066
*/
2067
2068
for (i = ppd->num_groups, groupa = ppd->groups; i > 1; i --, groupa ++)
2069
for (j = i - 1, groupb = groupa + 1; j > 0; j --, groupb ++)
2070
if (!_cups_strcasecmp(groupa->name, groupb->name))
2071
{
2072
if (!errors && !verbose)
2073
_cupsLangPuts(stdout, _(" FAIL"));
2074
2075
if (verbose >= 0)
2076
_cupsLangPrintf(stdout,
2077
_(" **FAIL** Group names %s and %s differ only "
2078
"by case."),
2079
groupa->name, groupb->name);
2080
2081
errors ++;
2082
}
2083
2084
/*
2085
* Check that the options do not have any duplicate names...
2086
*/
2087
2088
for (optiona = ppdFirstOption(ppd); optiona; optiona = ppdNextOption(ppd))
2089
{
2090
cupsArraySave(ppd->options);
2091
for (optionb = ppdNextOption(ppd); optionb; optionb = ppdNextOption(ppd))
2092
if (!_cups_strcasecmp(optiona->keyword, optionb->keyword))
2093
{
2094
if (!errors && !verbose)
2095
_cupsLangPuts(stdout, _(" FAIL"));
2096
2097
if (verbose >= 0)
2098
_cupsLangPrintf(stdout,
2099
_(" **FAIL** Option names %s and %s differ only "
2100
"by case."),
2101
optiona->keyword, optionb->keyword);
2102
2103
errors ++;
2104
}
2105
cupsArrayRestore(ppd->options);
2106
2107
/*
2108
* Then the choices...
2109
*/
2110
2111
for (i = optiona->num_choices, choicea = optiona->choices;
2112
i > 1;
2113
i --, choicea ++)
2114
for (j = i - 1, choiceb = choicea + 1; j > 0; j --, choiceb ++)
2115
if (!strcmp(choicea->choice, choiceb->choice))
2116
{
2117
if (!errors && !verbose)
2118
_cupsLangPuts(stdout, _(" FAIL"));
2119
2120
if (verbose >= 0)
2121
_cupsLangPrintf(stdout,
2122
_(" **FAIL** Multiple occurrences of "
2123
"option %s choice name %s."),
2124
optiona->keyword, choicea->choice);
2125
2126
errors ++;
2127
2128
choicea ++;
2129
i --;
2130
break;
2131
}
2132
else if (!_cups_strcasecmp(choicea->choice, choiceb->choice))
2133
{
2134
if (!errors && !verbose)
2135
_cupsLangPuts(stdout, _(" FAIL"));
2136
2137
if (verbose >= 0)
2138
_cupsLangPrintf(stdout,
2139
_(" **FAIL** Option %s choice names %s and "
2140
"%s differ only by case."),
2141
optiona->keyword, choicea->choice, choiceb->choice);
2142
2143
errors ++;
2144
}
2145
}
2146
2147
/*
2148
* Return the number of errors found...
2149
*/
2150
2151
return (errors);
2152
}
2153
2154
2155
/*
2156
* 'check_defaults()' - Check default option keywords in the PPD file.
2157
*/
2158
2159
static int /* O - Errors found */
2160
check_defaults(ppd_file_t *ppd, /* I - PPD file */
2161
int errors, /* I - Errors found */
2162
int verbose, /* I - Verbosity level */
2163
int warn) /* I - Warnings only? */
2164
{
2165
int j, k; /* Looping vars */
2166
ppd_attr_t *attr; /* PPD attribute */
2167
ppd_option_t *option; /* Standard UI option */
2168
const char *prefix; /* WARN/FAIL prefix */
2169
2170
2171
prefix = warn ? " WARN " : "**FAIL**";
2172
2173
ppdMarkDefaults(ppd);
2174
if (ppdConflicts(ppd))
2175
{
2176
if (!warn && !errors && !verbose)
2177
_cupsLangPuts(stdout, _(" FAIL"));
2178
2179
if (verbose >= 0)
2180
_cupsLangPrintf(stdout,
2181
_(" %s Default choices conflicting."), prefix);
2182
2183
show_conflicts(ppd, prefix);
2184
2185
if (!warn)
2186
errors ++;
2187
}
2188
2189
for (j = 0; j < ppd->num_attrs; j ++)
2190
{
2191
attr = ppd->attrs[j];
2192
2193
if (!strcmp(attr->name, "DefaultColorSpace") ||
2194
!strcmp(attr->name, "DefaultFont") ||
2195
!strcmp(attr->name, "DefaultHalftoneType") ||
2196
!strcmp(attr->name, "DefaultImageableArea") ||
2197
!strcmp(attr->name, "DefaultLeadingEdge") ||
2198
!strcmp(attr->name, "DefaultOutputOrder") ||
2199
!strcmp(attr->name, "DefaultPaperDimension") ||
2200
!strcmp(attr->name, "DefaultResolution") ||
2201
!strcmp(attr->name, "DefaultTransfer"))
2202
continue;
2203
2204
if (!strncmp(attr->name, "Default", 7))
2205
{
2206
if ((option = ppdFindOption(ppd, attr->name + 7)) != NULL &&
2207
strcmp(attr->value, "Unknown"))
2208
{
2209
/*
2210
* Check that the default option value matches a choice...
2211
*/
2212
2213
for (k = 0; k < option->num_choices; k ++)
2214
if (!strcmp(option->choices[k].choice, attr->value))
2215
break;
2216
2217
if (k >= option->num_choices)
2218
{
2219
if (!warn && !errors && !verbose)
2220
_cupsLangPuts(stdout, _(" FAIL"));
2221
2222
if (verbose >= 0)
2223
_cupsLangPrintf(stdout,
2224
_(" %s %s %s does not exist."),
2225
prefix, attr->name, attr->value);
2226
2227
if (!warn)
2228
errors ++;
2229
}
2230
}
2231
}
2232
}
2233
2234
return (errors);
2235
}
2236
2237
2238
/*
2239
* 'check_duplex()' - Check duplex keywords in the PPD file.
2240
*/
2241
2242
static int /* O - Errors found */
2243
check_duplex(ppd_file_t *ppd, /* I - PPD file */
2244
int errors, /* I - Error found */
2245
int verbose, /* I - Verbosity level */
2246
int warn) /* I - Warnings only? */
2247
{
2248
int i; /* Looping var */
2249
ppd_option_t *option; /* PPD option */
2250
ppd_choice_t *choice; /* Current choice */
2251
const char *prefix; /* Message prefix */
2252
2253
2254
prefix = warn ? " WARN " : "**FAIL**";
2255
2256
/*
2257
* Check for a duplex option, and for standard values...
2258
*/
2259
2260
if ((option = ppdFindOption(ppd, "Duplex")) != NULL)
2261
{
2262
if (!ppdFindChoice(option, "None"))
2263
{
2264
if (verbose >= 0)
2265
{
2266
if (!warn && !errors && !verbose)
2267
_cupsLangPuts(stdout, _(" FAIL"));
2268
2269
_cupsLangPrintf(stdout,
2270
_(" %s REQUIRED %s does not define "
2271
"choice None.\n"
2272
" REF: Page 122, section 5.17"),
2273
prefix, option->keyword);
2274
}
2275
2276
if (!warn)
2277
errors ++;
2278
}
2279
2280
for (i = option->num_choices, choice = option->choices;
2281
i > 0;
2282
i --, choice ++)
2283
if (strcmp(choice->choice, "None") &&
2284
strcmp(choice->choice, "DuplexNoTumble") &&
2285
strcmp(choice->choice, "DuplexTumble") &&
2286
strcmp(choice->choice, "SimplexTumble"))
2287
{
2288
if (verbose >= 0)
2289
{
2290
if (!warn && !errors && !verbose)
2291
_cupsLangPuts(stdout, _(" FAIL"));
2292
2293
_cupsLangPrintf(stdout,
2294
_(" %s Bad %s choice %s.\n"
2295
" REF: Page 122, section 5.17"),
2296
prefix, option->keyword, choice->choice);
2297
}
2298
2299
if (!warn)
2300
errors ++;
2301
}
2302
}
2303
2304
return (errors);
2305
}
2306
2307
2308
/*
2309
* 'check_filters()' - Check filters in the PPD file.
2310
*/
2311
2312
static int /* O - Errors found */
2313
check_filters(ppd_file_t *ppd, /* I - PPD file */
2314
const char *root, /* I - Root directory */
2315
int errors, /* I - Errors found */
2316
int verbose, /* I - Verbosity level */
2317
int warn) /* I - Warnings only? */
2318
{
2319
ppd_attr_t *attr; /* PPD attribute */
2320
const char *ptr; /* Pointer into string */
2321
char super[16], /* Super-type for filter */
2322
type[256], /* Type for filter */
2323
dstsuper[16], /* Destination super-type for filter */
2324
dsttype[256], /* Destination type for filter */
2325
program[1024], /* Program/filter name */
2326
pathprog[1024]; /* Complete path to program/filter */
2327
int cost; /* Cost of filter */
2328
const char *prefix; /* WARN/FAIL prefix */
2329
struct stat fileinfo; /* File information */
2330
2331
2332
prefix = warn ? " WARN " : "**FAIL**";
2333
2334
/*
2335
* cupsFilter
2336
*/
2337
2338
for (attr = ppdFindAttr(ppd, "cupsFilter", NULL);
2339
attr;
2340
attr = ppdFindNextAttr(ppd, "cupsFilter", NULL))
2341
{
2342
if (strcmp(attr->name, "cupsFilter"))
2343
{
2344
if (!warn && !errors && !verbose)
2345
_cupsLangPuts(stdout, _(" FAIL"));
2346
2347
if (verbose >= 0)
2348
_cupsLangPrintf(stdout,
2349
_(" %s Bad spelling of %s - should be %s."),
2350
prefix, attr->name, "cupsFilter");
2351
2352
if (!warn)
2353
errors ++;
2354
}
2355
2356
if (!attr->value ||
2357
sscanf(attr->value, "%15[^/]/%255s%d%*[ \t]%1023[^\n]", super, type,
2358
&cost, program) != 4)
2359
{
2360
if (!warn && !errors && !verbose)
2361
_cupsLangPuts(stdout, _(" FAIL"));
2362
2363
if (verbose >= 0)
2364
_cupsLangPrintf(stdout,
2365
_(" %s Bad cupsFilter value \"%s\"."),
2366
prefix, attr->value);
2367
2368
if (!warn)
2369
errors ++;
2370
2371
continue;
2372
}
2373
2374
if (!strncmp(program, "maxsize(", 8))
2375
{
2376
char *mptr; /* Pointer into maxsize(nnnn) program */
2377
2378
strtoll(program + 8, &mptr, 10);
2379
2380
if (*mptr != ')')
2381
{
2382
if (!warn && !errors && !verbose)
2383
_cupsLangPuts(stdout, _(" FAIL"));
2384
2385
if (verbose >= 0)
2386
_cupsLangPrintf(stdout,
2387
_(" %s Bad cupsFilter value \"%s\"."),
2388
prefix, attr->value);
2389
2390
if (!warn)
2391
errors ++;
2392
2393
continue;
2394
}
2395
2396
mptr ++;
2397
while (_cups_isspace(*mptr))
2398
mptr ++;
2399
2400
_cups_strcpy(program, mptr);
2401
}
2402
2403
if (strcmp(program, "-"))
2404
{
2405
if (program[0] == '/')
2406
snprintf(pathprog, sizeof(pathprog), "%s%s", root, program);
2407
else
2408
{
2409
if ((ptr = getenv("CUPS_SERVERBIN")) == NULL)
2410
ptr = CUPS_SERVERBIN;
2411
2412
if (*ptr == '/' || !*root)
2413
snprintf(pathprog, sizeof(pathprog), "%s%s/filter/%s", root, ptr,
2414
program);
2415
else
2416
snprintf(pathprog, sizeof(pathprog), "%s/%s/filter/%s", root, ptr,
2417
program);
2418
}
2419
2420
if (stat(pathprog, &fileinfo))
2421
{
2422
if (!warn && !errors && !verbose)
2423
_cupsLangPuts(stdout, _(" FAIL"));
2424
2425
if (verbose >= 0)
2426
_cupsLangPrintf(stdout, _(" %s Missing %s file \"%s\"."),
2427
prefix, "cupsFilter", pathprog);
2428
2429
if (!warn)
2430
errors ++;
2431
}
2432
else if (fileinfo.st_uid != 0 ||
2433
(fileinfo.st_mode & MODE_WRITE) ||
2434
(fileinfo.st_mode & MODE_MASK) != MODE_PROGRAM)
2435
{
2436
if (!warn && !errors && !verbose)
2437
_cupsLangPuts(stdout, _(" FAIL"));
2438
2439
if (verbose >= 0)
2440
_cupsLangPrintf(stdout,
2441
_(" %s Bad permissions on %s file \"%s\"."),
2442
prefix, "cupsFilter", pathprog);
2443
2444
if (!warn)
2445
errors ++;
2446
}
2447
else
2448
errors = valid_path("cupsFilter", pathprog, errors, verbose, warn);
2449
}
2450
}
2451
2452
/*
2453
* cupsFilter2
2454
*/
2455
2456
for (attr = ppdFindAttr(ppd, "cupsFilter2", NULL);
2457
attr;
2458
attr = ppdFindNextAttr(ppd, "cupsFilter2", NULL))
2459
{
2460
if (strcmp(attr->name, "cupsFilter2"))
2461
{
2462
if (!warn && !errors && !verbose)
2463
_cupsLangPuts(stdout, _(" FAIL"));
2464
2465
if (verbose >= 0)
2466
_cupsLangPrintf(stdout,
2467
_(" %s Bad spelling of %s - should be %s."),
2468
prefix, attr->name, "cupsFilter2");
2469
2470
if (!warn)
2471
errors ++;
2472
}
2473
2474
if (!attr->value ||
2475
sscanf(attr->value, "%15[^/]/%255s%*[ \t]%15[^/]/%255s%d%*[ \t]%1023[^\n]",
2476
super, type, dstsuper, dsttype, &cost, program) != 6)
2477
{
2478
if (!warn && !errors && !verbose)
2479
_cupsLangPuts(stdout, _(" FAIL"));
2480
2481
if (verbose >= 0)
2482
_cupsLangPrintf(stdout,
2483
_(" %s Bad cupsFilter2 value \"%s\"."),
2484
prefix, attr->value);
2485
2486
if (!warn)
2487
errors ++;
2488
2489
continue;
2490
}
2491
2492
if (!strncmp(program, "maxsize(", 8))
2493
{
2494
char *mptr; /* Pointer into maxsize(nnnn) program */
2495
2496
strtoll(program + 8, &mptr, 10);
2497
2498
if (*mptr != ')')
2499
{
2500
if (!warn && !errors && !verbose)
2501
_cupsLangPuts(stdout, _(" FAIL"));
2502
2503
if (verbose >= 0)
2504
_cupsLangPrintf(stdout,
2505
_(" %s Bad cupsFilter2 value \"%s\"."),
2506
prefix, attr->value);
2507
2508
if (!warn)
2509
errors ++;
2510
2511
continue;
2512
}
2513
2514
mptr ++;
2515
while (_cups_isspace(*mptr))
2516
mptr ++;
2517
2518
_cups_strcpy(program, mptr);
2519
}
2520
2521
if (strcmp(program, "-"))
2522
{
2523
if (strncmp(program, "maxsize(", 8) &&
2524
(ptr = strchr(program + 8, ')')) != NULL)
2525
{
2526
ptr ++;
2527
while (_cups_isspace(*ptr))
2528
ptr ++;
2529
2530
_cups_strcpy(program, ptr);
2531
}
2532
2533
if (program[0] == '/')
2534
snprintf(pathprog, sizeof(pathprog), "%s%s", root, program);
2535
else
2536
{
2537
if ((ptr = getenv("CUPS_SERVERBIN")) == NULL)
2538
ptr = CUPS_SERVERBIN;
2539
2540
if (*ptr == '/' || !*root)
2541
snprintf(pathprog, sizeof(pathprog), "%s%s/filter/%s", root, ptr,
2542
program);
2543
else
2544
snprintf(pathprog, sizeof(pathprog), "%s/%s/filter/%s", root, ptr,
2545
program);
2546
}
2547
2548
if (stat(pathprog, &fileinfo))
2549
{
2550
if (!warn && !errors && !verbose)
2551
_cupsLangPuts(stdout, _(" FAIL"));
2552
2553
if (verbose >= 0)
2554
_cupsLangPrintf(stdout, _(" %s Missing %s file \"%s\"."),
2555
prefix, "cupsFilter2", pathprog);
2556
2557
if (!warn)
2558
errors ++;
2559
}
2560
else if (fileinfo.st_uid != 0 ||
2561
(fileinfo.st_mode & MODE_WRITE) ||
2562
(fileinfo.st_mode & MODE_MASK) != MODE_PROGRAM)
2563
{
2564
if (!warn && !errors && !verbose)
2565
_cupsLangPuts(stdout, _(" FAIL"));
2566
2567
if (verbose >= 0)
2568
_cupsLangPrintf(stdout,
2569
_(" %s Bad permissions on %s file \"%s\"."),
2570
prefix, "cupsFilter2", pathprog);
2571
2572
if (!warn)
2573
errors ++;
2574
}
2575
else
2576
errors = valid_path("cupsFilter2", pathprog, errors, verbose, warn);
2577
}
2578
}
2579
2580
/*
2581
* cupsPreFilter
2582
*/
2583
2584
for (attr = ppdFindAttr(ppd, "cupsPreFilter", NULL);
2585
attr;
2586
attr = ppdFindNextAttr(ppd, "cupsPreFilter", NULL))
2587
{
2588
if (strcmp(attr->name, "cupsPreFilter"))
2589
{
2590
if (!warn && !errors && !verbose)
2591
_cupsLangPuts(stdout, _(" FAIL"));
2592
2593
if (verbose >= 0)
2594
_cupsLangPrintf(stdout,
2595
_(" %s Bad spelling of %s - should be %s."),
2596
prefix, attr->name, "cupsPreFilter");
2597
2598
if (!warn)
2599
errors ++;
2600
}
2601
2602
if (!attr->value ||
2603
sscanf(attr->value, "%15[^/]/%255s%d%*[ \t]%1023[^\n]", super, type,
2604
&cost, program) != 4)
2605
{
2606
if (!warn && !errors && !verbose)
2607
_cupsLangPuts(stdout, _(" FAIL"));
2608
2609
if (verbose >= 0)
2610
_cupsLangPrintf(stdout,
2611
_(" %s Bad cupsPreFilter value \"%s\"."),
2612
prefix, attr->value ? attr->value : "");
2613
2614
if (!warn)
2615
errors ++;
2616
}
2617
else if (strcmp(program, "-"))
2618
{
2619
if (program[0] == '/')
2620
snprintf(pathprog, sizeof(pathprog), "%s%s", root, program);
2621
else
2622
{
2623
if ((ptr = getenv("CUPS_SERVERBIN")) == NULL)
2624
ptr = CUPS_SERVERBIN;
2625
2626
if (*ptr == '/' || !*root)
2627
snprintf(pathprog, sizeof(pathprog), "%s%s/filter/%s", root, ptr,
2628
program);
2629
else
2630
snprintf(pathprog, sizeof(pathprog), "%s/%s/filter/%s", root, ptr,
2631
program);
2632
}
2633
2634
if (stat(pathprog, &fileinfo))
2635
{
2636
if (!warn && !errors && !verbose)
2637
_cupsLangPuts(stdout, _(" FAIL"));
2638
2639
if (verbose >= 0)
2640
_cupsLangPrintf(stdout, _(" %s Missing %s file \"%s\"."),
2641
prefix, "cupsPreFilter", pathprog);
2642
2643
if (!warn)
2644
errors ++;
2645
}
2646
else if (fileinfo.st_uid != 0 ||
2647
(fileinfo.st_mode & MODE_WRITE) ||
2648
(fileinfo.st_mode & MODE_MASK) != MODE_PROGRAM)
2649
{
2650
if (!warn && !errors && !verbose)
2651
_cupsLangPuts(stdout, _(" FAIL"));
2652
2653
if (verbose >= 0)
2654
_cupsLangPrintf(stdout,
2655
_(" %s Bad permissions on %s file \"%s\"."),
2656
prefix, "cupsPreFilter", pathprog);
2657
2658
if (!warn)
2659
errors ++;
2660
}
2661
else
2662
errors = valid_path("cupsPreFilter", pathprog, errors, verbose, warn);
2663
}
2664
}
2665
2666
#ifdef __APPLE__
2667
/*
2668
* APDialogExtension
2669
*/
2670
2671
for (attr = ppdFindAttr(ppd, "APDialogExtension", NULL);
2672
attr != NULL;
2673
attr = ppdFindNextAttr(ppd, "APDialogExtension", NULL))
2674
{
2675
if (strcmp(attr->name, "APDialogExtension"))
2676
{
2677
if (!warn && !errors && !verbose)
2678
_cupsLangPuts(stdout, _(" FAIL"));
2679
2680
if (verbose >= 0)
2681
_cupsLangPrintf(stdout,
2682
_(" %s Bad spelling of %s - should be %s."),
2683
prefix, attr->name, "APDialogExtension");
2684
2685
if (!warn)
2686
errors ++;
2687
}
2688
2689
snprintf(pathprog, sizeof(pathprog), "%s%s", root,
2690
attr->value ? attr->value : "(null)");
2691
2692
if (!attr->value || stat(pathprog, &fileinfo))
2693
{
2694
if (!warn && !errors && !verbose)
2695
_cupsLangPuts(stdout, _(" FAIL"));
2696
2697
if (verbose >= 0)
2698
_cupsLangPrintf(stdout, _(" %s Missing %s file \"%s\"."),
2699
prefix, "APDialogExtension", pathprog);
2700
2701
if (!warn)
2702
errors ++;
2703
}
2704
else if (fileinfo.st_uid != 0 ||
2705
(fileinfo.st_mode & MODE_WRITE) ||
2706
(fileinfo.st_mode & MODE_MASK) != MODE_DIRECTORY)
2707
{
2708
if (!warn && !errors && !verbose)
2709
_cupsLangPuts(stdout, _(" FAIL"));
2710
2711
if (verbose >= 0)
2712
_cupsLangPrintf(stdout,
2713
_(" %s Bad permissions on %s file \"%s\"."),
2714
prefix, "APDialogExtension", pathprog);
2715
2716
if (!warn)
2717
errors ++;
2718
}
2719
else
2720
errors = valid_path("APDialogExtension", pathprog, errors, verbose,
2721
warn);
2722
}
2723
2724
/*
2725
* APPrinterIconPath
2726
*/
2727
2728
if ((attr = ppdFindAttr(ppd, "APPrinterIconPath", NULL)) != NULL)
2729
{
2730
if (strcmp(attr->name, "APPrinterIconPath"))
2731
{
2732
if (!warn && !errors && !verbose)
2733
_cupsLangPuts(stdout, _(" FAIL"));
2734
2735
if (verbose >= 0)
2736
_cupsLangPrintf(stdout,
2737
_(" %s Bad spelling of %s - should be %s."),
2738
prefix, attr->name, "APPrinterIconPath");
2739
2740
if (!warn)
2741
errors ++;
2742
}
2743
2744
snprintf(pathprog, sizeof(pathprog), "%s%s", root,
2745
attr->value ? attr->value : "(null)");
2746
2747
if (!attr->value || stat(pathprog, &fileinfo))
2748
{
2749
if (!warn && !errors && !verbose)
2750
_cupsLangPuts(stdout, _(" FAIL"));
2751
2752
if (verbose >= 0)
2753
_cupsLangPrintf(stdout, _(" %s Missing %s file \"%s\"."),
2754
prefix, "APPrinterIconPath", pathprog);
2755
2756
if (!warn)
2757
errors ++;
2758
}
2759
else if (fileinfo.st_uid != 0 ||
2760
(fileinfo.st_mode & MODE_WRITE) ||
2761
(fileinfo.st_mode & MODE_MASK) != MODE_DATAFILE)
2762
{
2763
if (!warn && !errors && !verbose)
2764
_cupsLangPuts(stdout, _(" FAIL"));
2765
2766
if (verbose >= 0)
2767
_cupsLangPrintf(stdout,
2768
_(" %s Bad permissions on %s file \"%s\"."),
2769
prefix, "APPrinterIconPath", pathprog);
2770
2771
if (!warn)
2772
errors ++;
2773
}
2774
else
2775
errors = valid_path("APPrinterIconPath", pathprog, errors, verbose,
2776
warn);
2777
}
2778
2779
/*
2780
* APPrinterLowInkTool
2781
*/
2782
2783
if ((attr = ppdFindAttr(ppd, "APPrinterLowInkTool", NULL)) != NULL)
2784
{
2785
if (strcmp(attr->name, "APPrinterLowInkTool"))
2786
{
2787
if (!warn && !errors && !verbose)
2788
_cupsLangPuts(stdout, _(" FAIL"));
2789
2790
if (verbose >= 0)
2791
_cupsLangPrintf(stdout,
2792
_(" %s Bad spelling of %s - should be %s."),
2793
prefix, attr->name, "APPrinterLowInkTool");
2794
2795
if (!warn)
2796
errors ++;
2797
}
2798
2799
snprintf(pathprog, sizeof(pathprog), "%s%s", root,
2800
attr->value ? attr->value : "(null)");
2801
2802
if (!attr->value || stat(pathprog, &fileinfo))
2803
{
2804
if (!warn && !errors && !verbose)
2805
_cupsLangPuts(stdout, _(" FAIL"));
2806
2807
if (verbose >= 0)
2808
_cupsLangPrintf(stdout, _(" %s Missing %s file \"%s\"."),
2809
prefix, "APPrinterLowInkTool", pathprog);
2810
2811
if (!warn)
2812
errors ++;
2813
}
2814
else if (fileinfo.st_uid != 0 ||
2815
(fileinfo.st_mode & MODE_WRITE) ||
2816
(fileinfo.st_mode & MODE_MASK) != MODE_DIRECTORY)
2817
{
2818
if (!warn && !errors && !verbose)
2819
_cupsLangPuts(stdout, _(" FAIL"));
2820
2821
if (verbose >= 0)
2822
_cupsLangPrintf(stdout,
2823
_(" %s Bad permissions on %s file \"%s\"."),
2824
prefix, "APPrinterLowInkTool", pathprog);
2825
2826
if (!warn)
2827
errors ++;
2828
}
2829
else
2830
errors = valid_path("APPrinterLowInkTool", pathprog, errors, verbose,
2831
warn);
2832
}
2833
2834
/*
2835
* APPrinterUtilityPath
2836
*/
2837
2838
if ((attr = ppdFindAttr(ppd, "APPrinterUtilityPath", NULL)) != NULL)
2839
{
2840
if (strcmp(attr->name, "APPrinterUtilityPath"))
2841
{
2842
if (!warn && !errors && !verbose)
2843
_cupsLangPuts(stdout, _(" FAIL"));
2844
2845
if (verbose >= 0)
2846
_cupsLangPrintf(stdout,
2847
_(" %s Bad spelling of %s - should be %s."),
2848
prefix, attr->name, "APPrinterUtilityPath");
2849
2850
if (!warn)
2851
errors ++;
2852
}
2853
2854
snprintf(pathprog, sizeof(pathprog), "%s%s", root,
2855
attr->value ? attr->value : "(null)");
2856
2857
if (!attr->value || stat(pathprog, &fileinfo))
2858
{
2859
if (!warn && !errors && !verbose)
2860
_cupsLangPuts(stdout, _(" FAIL"));
2861
2862
if (verbose >= 0)
2863
_cupsLangPrintf(stdout, _(" %s Missing %s file \"%s\"."),
2864
prefix, "APPrinterUtilityPath", pathprog);
2865
2866
if (!warn)
2867
errors ++;
2868
}
2869
else if (fileinfo.st_uid != 0 ||
2870
(fileinfo.st_mode & MODE_WRITE) ||
2871
(fileinfo.st_mode & MODE_MASK) != MODE_DIRECTORY)
2872
{
2873
if (!warn && !errors && !verbose)
2874
_cupsLangPuts(stdout, _(" FAIL"));
2875
2876
if (verbose >= 0)
2877
_cupsLangPrintf(stdout,
2878
_(" %s Bad permissions on %s file \"%s\"."),
2879
prefix, "APPrinterUtilityPath", pathprog);
2880
2881
if (!warn)
2882
errors ++;
2883
}
2884
else
2885
errors = valid_path("APPrinterUtilityPath", pathprog, errors, verbose,
2886
warn);
2887
}
2888
2889
/*
2890
* APScanAppBundleID and APScanAppPath
2891
*/
2892
2893
if ((attr = ppdFindAttr(ppd, "APScanAppPath", NULL)) != NULL)
2894
{
2895
if (strcmp(attr->name, "APScanAppPath"))
2896
{
2897
if (!warn && !errors && !verbose)
2898
_cupsLangPuts(stdout, _(" FAIL"));
2899
2900
if (verbose >= 0)
2901
_cupsLangPrintf(stdout,
2902
_(" %s Bad spelling of %s - should be %s."),
2903
prefix, attr->name, "APScanAppPath");
2904
2905
if (!warn)
2906
errors ++;
2907
}
2908
2909
if (!attr->value || stat(attr->value, &fileinfo))
2910
{
2911
if (!warn && !errors && !verbose)
2912
_cupsLangPuts(stdout, _(" FAIL"));
2913
2914
if (verbose >= 0)
2915
_cupsLangPrintf(stdout, _(" %s Missing %s file \"%s\"."),
2916
prefix, "APScanAppPath",
2917
attr->value ? attr->value : "<NULL>");
2918
2919
if (!warn)
2920
errors ++;
2921
}
2922
else if (fileinfo.st_uid != 0 ||
2923
(fileinfo.st_mode & MODE_WRITE) ||
2924
(fileinfo.st_mode & MODE_MASK) != MODE_DIRECTORY)
2925
{
2926
if (!warn && !errors && !verbose)
2927
_cupsLangPuts(stdout, _(" FAIL"));
2928
2929
if (verbose >= 0)
2930
_cupsLangPrintf(stdout,
2931
_(" %s Bad permissions on %s file \"%s\"."),
2932
prefix, "APScanAppPath", attr->value);
2933
2934
if (!warn)
2935
errors ++;
2936
}
2937
else
2938
errors = valid_path("APScanAppPath", attr->value, errors, verbose,
2939
warn);
2940
2941
if (ppdFindAttr(ppd, "APScanAppBundleID", NULL))
2942
{
2943
if (!warn && !errors && !verbose)
2944
_cupsLangPuts(stdout, _(" FAIL"));
2945
2946
if (verbose >= 0)
2947
_cupsLangPrintf(stdout, _(" %s Cannot provide both "
2948
"APScanAppPath and APScanAppBundleID."),
2949
prefix);
2950
2951
if (!warn)
2952
errors ++;
2953
}
2954
}
2955
#endif /* __APPLE__ */
2956
2957
return (errors);
2958
}
2959
2960
2961
/*
2962
* 'check_profiles()' - Check ICC color profiles in the PPD file.
2963
*/
2964
2965
static int /* O - Errors found */
2966
check_profiles(ppd_file_t *ppd, /* I - PPD file */
2967
const char *root, /* I - Root directory */
2968
int errors, /* I - Errors found */
2969
int verbose, /* I - Verbosity level */
2970
int warn) /* I - Warnings only? */
2971
{
2972
int i; /* Looping var */
2973
ppd_attr_t *attr; /* PPD attribute */
2974
const char *ptr; /* Pointer into string */
2975
const char *prefix; /* WARN/FAIL prefix */
2976
char filename[1024]; /* Profile filename */
2977
struct stat fileinfo; /* File information */
2978
int num_profiles = 0; /* Number of profiles */
2979
unsigned hash, /* Current hash value */
2980
hashes[1000]; /* Hash values of profile names */
2981
const char *specs[1000]; /* Specifiers for profiles */
2982
2983
2984
prefix = warn ? " WARN " : "**FAIL**";
2985
2986
for (attr = ppdFindAttr(ppd, "cupsICCProfile", NULL);
2987
attr;
2988
attr = ppdFindNextAttr(ppd, "cupsICCProfile", NULL))
2989
{
2990
/*
2991
* Check for valid selector...
2992
*/
2993
2994
for (i = 0, ptr = strchr(attr->spec, '.'); ptr; ptr = strchr(ptr + 1, '.'))
2995
i ++;
2996
2997
if (!attr->value || i < 2)
2998
{
2999
if (!warn && !errors && !verbose)
3000
_cupsLangPuts(stdout, _(" FAIL"));
3001
3002
if (verbose >= 0)
3003
_cupsLangPrintf(stdout,
3004
_(" %s Bad cupsICCProfile %s."),
3005
prefix, attr->spec);
3006
3007
if (!warn)
3008
errors ++;
3009
3010
continue;
3011
}
3012
3013
/*
3014
* Check for valid profile filename...
3015
*/
3016
3017
if (attr->value[0] == '/')
3018
snprintf(filename, sizeof(filename), "%s%s", root, attr->value);
3019
else
3020
{
3021
if ((ptr = getenv("CUPS_DATADIR")) == NULL)
3022
ptr = CUPS_DATADIR;
3023
3024
if (*ptr == '/' || !*root)
3025
snprintf(filename, sizeof(filename), "%s%s/profiles/%s", root, ptr,
3026
attr->value);
3027
else
3028
snprintf(filename, sizeof(filename), "%s/%s/profiles/%s", root, ptr,
3029
attr->value);
3030
}
3031
3032
if (stat(filename, &fileinfo))
3033
{
3034
if (!warn && !errors && !verbose)
3035
_cupsLangPuts(stdout, _(" FAIL"));
3036
3037
if (verbose >= 0)
3038
_cupsLangPrintf(stdout, _(" %s Missing %s file \"%s\"."),
3039
prefix, "cupsICCProfile", filename);
3040
3041
if (!warn)
3042
errors ++;
3043
}
3044
else if (fileinfo.st_uid != 0 ||
3045
(fileinfo.st_mode & MODE_WRITE) ||
3046
(fileinfo.st_mode & MODE_MASK) != MODE_DATAFILE)
3047
{
3048
if (!warn && !errors && !verbose)
3049
_cupsLangPuts(stdout, _(" FAIL"));
3050
3051
if (verbose >= 0)
3052
_cupsLangPrintf(stdout,
3053
_(" %s Bad permissions on %s file \"%s\"."),
3054
prefix, "cupsICCProfile", filename);
3055
3056
if (!warn)
3057
errors ++;
3058
}
3059
else
3060
errors = valid_path("cupsICCProfile", filename, errors, verbose, warn);
3061
3062
/*
3063
* Check for hash collisions...
3064
*/
3065
3066
hash = _ppdHashName(attr->spec);
3067
3068
if (num_profiles > 0)
3069
{
3070
for (i = 0; i < num_profiles; i ++)
3071
if (hashes[i] == hash)
3072
break;
3073
3074
if (i < num_profiles)
3075
{
3076
if (!warn && !errors && !verbose)
3077
_cupsLangPuts(stdout, _(" FAIL"));
3078
3079
if (verbose >= 0)
3080
_cupsLangPrintf(stdout,
3081
_(" %s cupsICCProfile %s hash value "
3082
"collides with %s."), prefix, attr->spec,
3083
specs[i]);
3084
3085
if (!warn)
3086
errors ++;
3087
}
3088
}
3089
3090
/*
3091
* Remember up to 1000 profiles...
3092
*/
3093
3094
if (num_profiles < 1000)
3095
{
3096
hashes[num_profiles] = hash;
3097
specs[num_profiles] = attr->spec;
3098
num_profiles ++;
3099
}
3100
}
3101
3102
return (errors);
3103
}
3104
3105
3106
/*
3107
* 'check_sizes()' - Check media sizes in the PPD file.
3108
*/
3109
3110
static int /* O - Errors found */
3111
check_sizes(ppd_file_t *ppd, /* I - PPD file */
3112
int errors, /* I - Errors found */
3113
int verbose, /* I - Verbosity level */
3114
int warn) /* I - Warnings only? */
3115
{
3116
int i; /* Looping var */
3117
ppd_size_t *size; /* Current size */
3118
int width, /* Custom width */
3119
length; /* Custom length */
3120
const char *prefix; /* WARN/FAIL prefix */
3121
ppd_option_t *page_size, /* PageSize option */
3122
*page_region; /* PageRegion option */
3123
pwg_media_t *pwg_media; /* PWG media */
3124
char buf[PPD_MAX_NAME]; /* PapeSize name that is supposed to be */
3125
const char *ptr; /* Pointer into string */
3126
int width_2540ths, /* PageSize width in 2540ths */
3127
length_2540ths; /* PageSize length in 2540ths */
3128
int is_ok; /* Flag for PageSize name verification */
3129
double width_tmp, /* Width after rounded up */
3130
length_tmp, /* Length after rounded up */
3131
width_inch, /* Width in inches */
3132
length_inch, /* Length in inches */
3133
width_mm, /* Width in millimeters */
3134
length_mm; /* Length in millimeters */
3135
3136
3137
prefix = warn ? " WARN " : "**FAIL**";
3138
3139
if ((page_size = ppdFindOption(ppd, "PageSize")) == NULL && warn != 2)
3140
{
3141
if (!warn && !errors && !verbose)
3142
_cupsLangPuts(stdout, _(" FAIL"));
3143
3144
if (verbose >= 0)
3145
_cupsLangPrintf(stdout,
3146
_(" %s Missing REQUIRED PageSize option.\n"
3147
" REF: Page 99, section 5.14."),
3148
prefix);
3149
3150
if (!warn)
3151
errors ++;
3152
}
3153
3154
if ((page_region = ppdFindOption(ppd, "PageRegion")) == NULL && warn != 2)
3155
{
3156
if (!warn && !errors && !verbose)
3157
_cupsLangPuts(stdout, _(" FAIL"));
3158
3159
if (verbose >= 0)
3160
_cupsLangPrintf(stdout,
3161
_(" %s Missing REQUIRED PageRegion option.\n"
3162
" REF: Page 100, section 5.14."),
3163
prefix);
3164
3165
if (!warn)
3166
errors ++;
3167
}
3168
3169
for (i = ppd->num_sizes, size = ppd->sizes; i > 0; i --, size ++)
3170
{
3171
/*
3172
* Check that the size name is standard...
3173
*/
3174
3175
if (!strcmp(size->name, "Custom"))
3176
{
3177
/*
3178
* Skip custom page size...
3179
*/
3180
3181
continue;
3182
}
3183
3184
if (warn != 2 && size->name[0] == 'w' &&
3185
sscanf(size->name, "w%dh%d", &width, &length) == 2)
3186
{
3187
/*
3188
* Validate device-specific size wNNNhNNN should have proper width and
3189
* length...
3190
*/
3191
3192
if (fabs(width - size->width) >= 1.0 ||
3193
fabs(length - size->length) >= 1.0)
3194
{
3195
if (!warn && !errors && !verbose)
3196
_cupsLangPuts(stdout, _(" FAIL"));
3197
3198
if (verbose >= 0)
3199
_cupsLangPrintf(stdout,
3200
_(" %s Size \"%s\" has unexpected dimensions "
3201
"(%gx%g)."),
3202
prefix, size->name, size->width, size->length);
3203
3204
if (!warn)
3205
errors ++;
3206
}
3207
}
3208
3209
/*
3210
* Verify that the size is defined for both PageSize and PageRegion...
3211
*/
3212
3213
if (warn != 2 && !ppdFindChoice(page_size, size->name))
3214
{
3215
if (!warn && !errors && !verbose)
3216
_cupsLangPuts(stdout, _(" FAIL"));
3217
3218
if (verbose >= 0)
3219
_cupsLangPrintf(stdout,
3220
_(" %s Size \"%s\" defined for %s but not for "
3221
"%s."),
3222
prefix, size->name, "PageRegion", "PageSize");
3223
3224
if (!warn)
3225
errors ++;
3226
}
3227
else if (warn != 2 && !ppdFindChoice(page_region, size->name))
3228
{
3229
if (!warn && !errors && !verbose)
3230
_cupsLangPuts(stdout, _(" FAIL"));
3231
3232
if (verbose >= 0)
3233
_cupsLangPrintf(stdout,
3234
_(" %s Size \"%s\" defined for %s but not for "
3235
"%s."),
3236
prefix, size->name, "PageSize", "PageRegion");
3237
3238
if (!warn)
3239
errors ++;
3240
}
3241
3242
/*
3243
* Verify that the size name is Adobe standard name if it's a standard size
3244
* and the dimentional name if it's not a standard size. Suffix should be
3245
* .Fullbleed, etc., or numeric, e.g., Letter, Letter.Fullbleed,
3246
* Letter.Transverse, Letter1, Letter2, 4x8, 55x91mm, 55x91mm.Fullbleed, etc.
3247
*/
3248
3249
if (warn != 0)
3250
{
3251
is_ok = 1;
3252
width_2540ths = (size->length > size->width) ?
3253
PWG_FROM_POINTS(size->width) :
3254
PWG_FROM_POINTS(size->length);
3255
length_2540ths = (size->length > size->width) ?
3256
PWG_FROM_POINTS(size->length) :
3257
PWG_FROM_POINTS(size->width);
3258
pwg_media = pwgMediaForSize(width_2540ths, length_2540ths);
3259
3260
if (pwg_media &&
3261
(abs(pwg_media->width - width_2540ths) > 34 ||
3262
abs(pwg_media->length - length_2540ths) > 34))
3263
pwg_media = NULL; /* Only flag matches within a point */
3264
3265
if (pwg_media && pwg_media->ppd &&
3266
(pwg_media->ppd[0] < 'a' || pwg_media->ppd[0] > 'z'))
3267
{
3268
size_t ppdlen = strlen(pwg_media->ppd);
3269
/* Length of standard PPD name */
3270
3271
strlcpy(buf, pwg_media->ppd, sizeof(buf));
3272
3273
if (strcmp(size->name, buf) && size->width > size->length)
3274
{
3275
if (!strcmp(pwg_media->ppd, "DoublePostcardRotated"))
3276
strlcpy(buf, "DoublePostcard", sizeof(buf));
3277
else if (strstr(size->name, ".Transverse"))
3278
snprintf(buf, sizeof(buf), "%s.Transverse", pwg_media->ppd);
3279
else
3280
snprintf(buf, sizeof(buf), "%sRotated", pwg_media->ppd);
3281
3282
ppdlen = strlen(buf);
3283
}
3284
3285
if (size->left == 0 && size->bottom == 0 &&
3286
size->right == size->width && size->top == size->length)
3287
{
3288
strlcat(buf, ".Fullbleed", sizeof(buf) - strlen(buf));
3289
if (_cups_strcasecmp(size->name, buf))
3290
{
3291
/*
3292
* Allow an additional qualifier such as ".WithTab"...
3293
*/
3294
3295
size_t buflen = strlen(buf);/* Length of full bleed name */
3296
3297
if (_cups_strncasecmp(size->name, buf, buflen) ||
3298
size->name[buflen] != '.')
3299
is_ok = 0;
3300
}
3301
}
3302
else if (!strncmp(size->name, pwg_media->ppd, ppdlen))
3303
{
3304
/*
3305
* Check for a proper qualifier (number, "Small", or .something)...
3306
*/
3307
3308
ptr = size->name + ppdlen;
3309
3310
if (isdigit(*ptr & 255))
3311
{
3312
for (ptr ++; *ptr; ptr ++)
3313
{
3314
if (!isdigit(*ptr & 255))
3315
{
3316
is_ok = 0;
3317
break;
3318
}
3319
}
3320
}
3321
else if (*ptr != '.' && *ptr && strcmp(ptr, "Small"))
3322
is_ok = 0;
3323
}
3324
else
3325
{
3326
/*
3327
* Check for EnvSizeName as well...
3328
*/
3329
3330
if (strncmp(pwg_media->ppd, "Env", 3) &&
3331
!strncmp(size->name, "Env", 3))
3332
snprintf(buf, sizeof(buf), "Env%s", pwg_media->ppd);
3333
3334
if (strcmp(size->name, buf))
3335
is_ok = 0;
3336
}
3337
3338
if (!is_ok)
3339
_cupsLangPrintf(stdout,
3340
_(" %s Size \"%s\" should be the Adobe "
3341
"standard name \"%s\"."),
3342
prefix, size->name, buf);
3343
}
3344
else
3345
{
3346
width_tmp = (fabs(size->width - ceil(size->width)) < 0.1) ?
3347
ceil(size->width) : size->width;
3348
length_tmp = (fabs(size->length - ceil(size->length)) < 0.1) ?
3349
ceil(size->length) : size->length;
3350
3351
if (fmod(width_tmp, 9.0) == 0.0 && fmod(length_tmp, 9.0) == 0.0)
3352
{
3353
width_inch = width_tmp / 72.0;
3354
length_inch = length_tmp / 72.0;
3355
3356
snprintf(buf, sizeof(buf), "%gx%g", width_inch, length_inch);
3357
}
3358
else
3359
{
3360
width_mm = size->width / 72.0 * 25.4;
3361
length_mm = size->length / 72.0 * 25.4;
3362
3363
snprintf(buf, sizeof(buf), "%.0fx%.0fmm", width_mm, length_mm);
3364
}
3365
3366
if (size->left == 0 && size->bottom == 0 &&
3367
size->right == size->width && size->top == size->length)
3368
strlcat(buf, ".Fullbleed", sizeof(buf));
3369
else if (size->width > size->length)
3370
strlcat(buf, ".Transverse", sizeof(buf));
3371
3372
if (_cups_strcasecmp(size->name, buf))
3373
{
3374
size_t buflen = strlen(buf);
3375
/* Length of proposed name */
3376
3377
if (_cups_strncasecmp(size->name, buf, buflen) ||
3378
(strcmp(size->name + buflen, "in") &&
3379
size->name[buflen] != '.'))
3380
{
3381
char altbuf[PPD_MAX_NAME];
3382
/* Alternate "wNNNhNNN" name */
3383
size_t altlen; /* Length of alternate name */
3384
3385
snprintf(altbuf, sizeof(altbuf), "w%.0fh%.0f", size->width,
3386
size->length);
3387
altlen = strlen(altbuf);
3388
if (_cups_strncasecmp(size->name, altbuf, altlen) ||
3389
(size->name[altlen] && size->name[altlen] != '.'))
3390
_cupsLangPrintf(stdout,
3391
_(" %s Size \"%s\" should be \"%s\"."),
3392
prefix, size->name, buf);
3393
}
3394
}
3395
}
3396
}
3397
}
3398
3399
return (errors);
3400
}
3401
3402
3403
/*
3404
* 'check_translations()' - Check translations in the PPD file.
3405
*/
3406
3407
static int /* O - Errors found */
3408
check_translations(ppd_file_t *ppd, /* I - PPD file */
3409
int errors, /* I - Errors found */
3410
int verbose, /* I - Verbosity level */
3411
int warn) /* I - Warnings only? */
3412
{
3413
int j; /* Looping var */
3414
ppd_attr_t *attr; /* PPD attribute */
3415
cups_array_t *languages; /* Array of languages */
3416
int langlen; /* Length of language */
3417
char *language, /* Current language */
3418
keyword[PPD_MAX_NAME], /* Localization keyword (full) */
3419
llkeyword[PPD_MAX_NAME],/* Localization keyword (base) */
3420
ckeyword[PPD_MAX_NAME], /* Custom option keyword (full) */
3421
cllkeyword[PPD_MAX_NAME];
3422
/* Custom option keyword (base) */
3423
ppd_option_t *option; /* Standard UI option */
3424
ppd_coption_t *coption; /* Custom option */
3425
ppd_cparam_t *cparam; /* Custom parameter */
3426
char ll[3]; /* Base language */
3427
const char *prefix; /* WARN/FAIL prefix */
3428
const char *text; /* Pointer into UI text */
3429
3430
3431
prefix = warn ? " WARN " : "**FAIL**";
3432
3433
if ((languages = _ppdGetLanguages(ppd)) != NULL)
3434
{
3435
/*
3436
* This file contains localizations, check them...
3437
*/
3438
3439
for (language = (char *)cupsArrayFirst(languages);
3440
language;
3441
language = (char *)cupsArrayNext(languages))
3442
{
3443
langlen = (int)strlen(language);
3444
if (langlen != 2 && langlen != 5)
3445
{
3446
if (!warn && !errors && !verbose)
3447
_cupsLangPuts(stdout, _(" FAIL"));
3448
3449
if (verbose >= 0)
3450
_cupsLangPrintf(stdout,
3451
_(" %s Bad language \"%s\"."),
3452
prefix, language);
3453
3454
if (!warn)
3455
errors ++;
3456
3457
continue;
3458
}
3459
3460
if (!strcmp(language, "en"))
3461
continue;
3462
3463
strlcpy(ll, language, sizeof(ll));
3464
3465
/*
3466
* Loop through all options and choices...
3467
*/
3468
3469
for (option = ppdFirstOption(ppd);
3470
option;
3471
option = ppdNextOption(ppd))
3472
{
3473
if (!strcmp(option->keyword, "PageRegion"))
3474
continue;
3475
3476
snprintf(keyword, sizeof(keyword), "%s.Translation", language);
3477
snprintf(llkeyword, sizeof(llkeyword), "%s.Translation", ll);
3478
3479
if ((attr = ppdFindAttr(ppd, keyword, option->keyword)) == NULL &&
3480
(attr = ppdFindAttr(ppd, llkeyword, option->keyword)) == NULL)
3481
{
3482
if (!warn && !errors && !verbose)
3483
_cupsLangPuts(stdout, _(" FAIL"));
3484
3485
if (verbose >= 0)
3486
_cupsLangPrintf(stdout,
3487
_(" %s Missing \"%s\" translation "
3488
"string for option %s."),
3489
prefix, language, option->keyword);
3490
3491
if (!warn)
3492
errors ++;
3493
}
3494
else if (!valid_utf8(attr->text))
3495
{
3496
if (!warn && !errors && !verbose)
3497
_cupsLangPuts(stdout, _(" FAIL"));
3498
3499
if (verbose >= 0)
3500
_cupsLangPrintf(stdout,
3501
_(" %s Bad UTF-8 \"%s\" translation "
3502
"string for option %s."),
3503
prefix, language, option->keyword);
3504
3505
if (!warn)
3506
errors ++;
3507
}
3508
3509
snprintf(keyword, sizeof(keyword), "%s.%s", language,
3510
option->keyword);
3511
snprintf(llkeyword, sizeof(llkeyword), "%s.%s", ll,
3512
option->keyword);
3513
3514
for (j = 0; j < option->num_choices; j ++)
3515
{
3516
/*
3517
* First see if this choice is a number; if so, don't require
3518
* translation...
3519
*/
3520
3521
for (text = option->choices[j].text; *text; text ++)
3522
if (!strchr("0123456789-+.", *text))
3523
break;
3524
3525
if (!*text)
3526
continue;
3527
3528
/*
3529
* Check custom choices differently...
3530
*/
3531
3532
if (!_cups_strcasecmp(option->choices[j].choice, "Custom") &&
3533
(coption = ppdFindCustomOption(ppd,
3534
option->keyword)) != NULL)
3535
{
3536
snprintf(ckeyword, sizeof(ckeyword), "%s.Custom%s",
3537
language, option->keyword);
3538
3539
if ((attr = ppdFindAttr(ppd, ckeyword, "True")) != NULL &&
3540
!valid_utf8(attr->text))
3541
{
3542
if (!warn && !errors && !verbose)
3543
_cupsLangPuts(stdout, _(" FAIL"));
3544
3545
if (verbose >= 0)
3546
_cupsLangPrintf(stdout,
3547
_(" %s Bad UTF-8 \"%s\" "
3548
"translation string for option %s, "
3549
"choice %s."),
3550
prefix, language,
3551
ckeyword + 1 + strlen(language),
3552
"True");
3553
3554
if (!warn)
3555
errors ++;
3556
}
3557
3558
if (_cups_strcasecmp(option->keyword, "PageSize"))
3559
{
3560
for (cparam = (ppd_cparam_t *)cupsArrayFirst(coption->params);
3561
cparam;
3562
cparam = (ppd_cparam_t *)cupsArrayNext(coption->params))
3563
{
3564
snprintf(ckeyword, sizeof(ckeyword), "%s.ParamCustom%s",
3565
language, option->keyword);
3566
snprintf(cllkeyword, sizeof(cllkeyword), "%s.ParamCustom%s",
3567
ll, option->keyword);
3568
3569
if ((attr = ppdFindAttr(ppd, ckeyword,
3570
cparam->name)) == NULL &&
3571
(attr = ppdFindAttr(ppd, cllkeyword,
3572
cparam->name)) == NULL)
3573
{
3574
if (!warn && !errors && !verbose)
3575
_cupsLangPuts(stdout, _(" FAIL"));
3576
3577
if (verbose >= 0)
3578
_cupsLangPrintf(stdout,
3579
_(" %s Missing \"%s\" "
3580
"translation string for option %s, "
3581
"choice %s."),
3582
prefix, language,
3583
ckeyword + 1 + strlen(language),
3584
cparam->name);
3585
3586
if (!warn)
3587
errors ++;
3588
}
3589
else if (!valid_utf8(attr->text))
3590
{
3591
if (!warn && !errors && !verbose)
3592
_cupsLangPuts(stdout, _(" FAIL"));
3593
3594
if (verbose >= 0)
3595
_cupsLangPrintf(stdout,
3596
_(" %s Bad UTF-8 \"%s\" "
3597
"translation string for option %s, "
3598
"choice %s."),
3599
prefix, language,
3600
ckeyword + 1 + strlen(language),
3601
cparam->name);
3602
3603
if (!warn)
3604
errors ++;
3605
}
3606
}
3607
}
3608
}
3609
else if ((attr = ppdFindAttr(ppd, keyword,
3610
option->choices[j].choice)) == NULL &&
3611
(attr = ppdFindAttr(ppd, llkeyword,
3612
option->choices[j].choice)) == NULL)
3613
{
3614
if (!warn && !errors && !verbose)
3615
_cupsLangPuts(stdout, _(" FAIL"));
3616
3617
if (verbose >= 0)
3618
_cupsLangPrintf(stdout,
3619
_(" %s Missing \"%s\" "
3620
"translation string for option %s, "
3621
"choice %s."),
3622
prefix, language, option->keyword,
3623
option->choices[j].choice);
3624
3625
if (!warn)
3626
errors ++;
3627
}
3628
else if (!valid_utf8(attr->text))
3629
{
3630
if (!warn && !errors && !verbose)
3631
_cupsLangPuts(stdout, _(" FAIL"));
3632
3633
if (verbose >= 0)
3634
_cupsLangPrintf(stdout,
3635
_(" %s Bad UTF-8 \"%s\" "
3636
"translation string for option %s, "
3637
"choice %s."),
3638
prefix, language, option->keyword,
3639
option->choices[j].choice);
3640
3641
if (!warn)
3642
errors ++;
3643
}
3644
}
3645
}
3646
}
3647
3648
/*
3649
* Verify that we have the base language for each localized one...
3650
*/
3651
3652
for (language = (char *)cupsArrayFirst(languages);
3653
language;
3654
language = (char *)cupsArrayNext(languages))
3655
if (language[2])
3656
{
3657
/*
3658
* Lookup the base language...
3659
*/
3660
3661
cupsArraySave(languages);
3662
3663
strlcpy(ll, language, sizeof(ll));
3664
3665
if (!cupsArrayFind(languages, ll) &&
3666
strcmp(ll, "zh") && strcmp(ll, "en"))
3667
{
3668
if (!warn && !errors && !verbose)
3669
_cupsLangPuts(stdout, _(" FAIL"));
3670
3671
if (verbose >= 0)
3672
_cupsLangPrintf(stdout,
3673
_(" %s No base translation \"%s\" "
3674
"is included in file."), prefix, ll);
3675
3676
if (!warn)
3677
errors ++;
3678
}
3679
3680
cupsArrayRestore(languages);
3681
}
3682
3683
/*
3684
* Free memory used for the languages...
3685
*/
3686
3687
_ppdFreeLanguages(languages);
3688
}
3689
3690
return (errors);
3691
}
3692
3693
3694
/*
3695
* 'show_conflicts()' - Show option conflicts in a PPD file.
3696
*/
3697
3698
static void
3699
show_conflicts(ppd_file_t *ppd, /* I - PPD to check */
3700
const char *prefix) /* I - Prefix string */
3701
{
3702
int i, j; /* Looping variables */
3703
ppd_const_t *c; /* Current constraint */
3704
ppd_option_t *o1, *o2; /* Options */
3705
ppd_choice_t *c1, *c2; /* Choices */
3706
3707
3708
/*
3709
* Loop through all of the UI constraints and report any options
3710
* that conflict...
3711
*/
3712
3713
for (i = ppd->num_consts, c = ppd->consts; i > 0; i --, c ++)
3714
{
3715
/*
3716
* Grab pointers to the first option...
3717
*/
3718
3719
o1 = ppdFindOption(ppd, c->option1);
3720
3721
if (o1 == NULL)
3722
continue;
3723
else if (c->choice1[0] != '\0')
3724
{
3725
/*
3726
* This constraint maps to a specific choice.
3727
*/
3728
3729
c1 = ppdFindChoice(o1, c->choice1);
3730
}
3731
else
3732
{
3733
/*
3734
* This constraint applies to any choice for this option.
3735
*/
3736
3737
for (j = o1->num_choices, c1 = o1->choices; j > 0; j --, c1 ++)
3738
if (c1->marked)
3739
break;
3740
3741
if (j == 0 ||
3742
!_cups_strcasecmp(c1->choice, "None") ||
3743
!_cups_strcasecmp(c1->choice, "Off") ||
3744
!_cups_strcasecmp(c1->choice, "False"))
3745
c1 = NULL;
3746
}
3747
3748
/*
3749
* Grab pointers to the second option...
3750
*/
3751
3752
o2 = ppdFindOption(ppd, c->option2);
3753
3754
if (o2 == NULL)
3755
continue;
3756
else if (c->choice2[0] != '\0')
3757
{
3758
/*
3759
* This constraint maps to a specific choice.
3760
*/
3761
3762
c2 = ppdFindChoice(o2, c->choice2);
3763
}
3764
else
3765
{
3766
/*
3767
* This constraint applies to any choice for this option.
3768
*/
3769
3770
for (j = o2->num_choices, c2 = o2->choices; j > 0; j --, c2 ++)
3771
if (c2->marked)
3772
break;
3773
3774
if (j == 0 ||
3775
!_cups_strcasecmp(c2->choice, "None") ||
3776
!_cups_strcasecmp(c2->choice, "Off") ||
3777
!_cups_strcasecmp(c2->choice, "False"))
3778
c2 = NULL;
3779
}
3780
3781
/*
3782
* If both options are marked then there is a conflict...
3783
*/
3784
3785
if (c1 != NULL && c1->marked && c2 != NULL && c2->marked)
3786
_cupsLangPrintf(stdout,
3787
_(" %s \"%s %s\" conflicts with \"%s %s\"\n"
3788
" (constraint=\"%s %s %s %s\")."),
3789
prefix, o1->keyword, c1->choice, o2->keyword, c2->choice,
3790
c->option1, c->choice1, c->option2, c->choice2);
3791
}
3792
}
3793
3794
3795
/*
3796
* 'test_raster()' - Test PostScript commands for raster printers.
3797
*/
3798
3799
static int /* O - 1 on success, 0 on failure */
3800
test_raster(ppd_file_t *ppd, /* I - PPD file */
3801
int verbose) /* I - Verbosity */
3802
{
3803
cups_page_header2_t header; /* Page header */
3804
3805
3806
ppdMarkDefaults(ppd);
3807
if (cupsRasterInterpretPPD(&header, ppd, 0, NULL, 0))
3808
{
3809
if (!verbose)
3810
_cupsLangPuts(stdout, _(" FAIL"));
3811
3812
if (verbose >= 0)
3813
_cupsLangPrintf(stdout,
3814
_(" **FAIL** Default option code cannot be "
3815
"interpreted: %s"), cupsRasterErrorString());
3816
3817
return (0);
3818
}
3819
3820
/*
3821
* Try a test of custom page size code, if available...
3822
*/
3823
3824
if (!ppdPageSize(ppd, "Custom.612x792"))
3825
return (1);
3826
3827
ppdMarkOption(ppd, "PageSize", "Custom.612x792");
3828
3829
if (cupsRasterInterpretPPD(&header, ppd, 0, NULL, 0))
3830
{
3831
if (!verbose)
3832
_cupsLangPuts(stdout, _(" FAIL"));
3833
3834
if (verbose >= 0)
3835
_cupsLangPrintf(stdout,
3836
_(" **FAIL** Default option code cannot be "
3837
"interpreted: %s"), cupsRasterErrorString());
3838
3839
return (0);
3840
}
3841
3842
return (1);
3843
}
3844
3845
3846
/*
3847
* 'usage()' - Show program usage.
3848
*/
3849
3850
static void
3851
usage(void)
3852
{
3853
_cupsLangPuts(stdout, _("Warning: This program will be removed in a future version of CUPS."));
3854
_cupsLangPuts(stdout, _("Usage: cupstestppd [options] filename1.ppd[.gz] [... filenameN.ppd[.gz]]\n"
3855
" program | cupstestppd [options] -"));
3856
_cupsLangPuts(stdout, _("Options:"));
3857
_cupsLangPuts(stdout, _("-I {filename,filters,none,profiles}\n"
3858
" Ignore specific warnings"));
3859
_cupsLangPuts(stdout, _("-R root-directory Set alternate root"));
3860
_cupsLangPuts(stdout, _("-W {all,none,constraints,defaults,duplex,filters,profiles,sizes,translations}\n"
3861
" Issue warnings instead of errors"));
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"));
3866
3867
exit(ERROR_USAGE);
3868
}
3869
3870
3871
/*
3872
* 'valid_path()' - Check whether a path has the correct capitalization.
3873
*/
3874
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? */
3881
{
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 */
3887
3888
3889
prefix = warn ? " WARN " : "**FAIL**";
3890
3891
/*
3892
* Loop over the components of the path, checking that the entry exists with
3893
* the same capitalization...
3894
*/
3895
3896
strlcpy(temp, path, sizeof(temp));
3897
3898
while ((ptr = strrchr(temp, '/')) != NULL)
3899
{
3900
/*
3901
* Chop off the trailing component so temp == dirname and ptr == basename.
3902
*/
3903
3904
*ptr++ = '\0';
3905
3906
/*
3907
* Try opening the directory containing the base name...
3908
*/
3909
3910
if (temp[0])
3911
dir = cupsDirOpen(temp);
3912
else
3913
dir = cupsDirOpen("/");
3914
3915
if (!dir)
3916
dentry = NULL;
3917
else
3918
{
3919
while ((dentry = cupsDirRead(dir)) != NULL)
3920
{
3921
if (!strcmp(dentry->filename, ptr))
3922
break;
3923
}
3924
3925
cupsDirClose(dir);
3926
}
3927
3928
/*
3929
* Display an error if the filename doesn't exist with the same
3930
* capitalization...
3931
*/
3932
3933
if (!dentry)
3934
{
3935
if (!warn && !errors && !verbose)
3936
_cupsLangPuts(stdout, _(" FAIL"));
3937
3938
if (verbose >= 0)
3939
_cupsLangPrintf(stdout,
3940
_(" %s %s file \"%s\" has the wrong "
3941
"capitalization."), prefix, keyword, path);
3942
3943
if (!warn)
3944
errors ++;
3945
3946
break;
3947
}
3948
}
3949
3950
return (errors);
3951
}
3952
3953
3954
/*
3955
* 'valid_utf8()' - Check whether a string contains valid UTF-8 text.
3956
*/
3957
3958
static int /* O - 1 if valid, 0 if not */
3959
valid_utf8(const char *s) /* I - String to check */
3960
{
3961
while (*s)
3962
{
3963
if (*s & 0x80)
3964
{
3965
/*
3966
* Check for valid UTF-8 sequence...
3967
*/
3968
3969
if ((*s & 0xc0) == 0x80)
3970
return (0); /* Illegal suffix byte */
3971
else if ((*s & 0xe0) == 0xc0)
3972
{
3973
/*
3974
* 2-byte sequence...
3975
*/
3976
3977
s ++;
3978
3979
if ((*s & 0xc0) != 0x80)
3980
return (0); /* Missing suffix byte */
3981
}
3982
else if ((*s & 0xf0) == 0xe0)
3983
{
3984
/*
3985
* 3-byte sequence...
3986
*/
3987
3988
s ++;
3989
3990
if ((*s & 0xc0) != 0x80)
3991
return (0); /* Missing suffix byte */
3992
3993
s ++;
3994
3995
if ((*s & 0xc0) != 0x80)
3996
return (0); /* Missing suffix byte */
3997
}
3998
else if ((*s & 0xf8) == 0xf0)
3999
{
4000
/*
4001
* 4-byte sequence...
4002
*/
4003
4004
s ++;
4005
4006
if ((*s & 0xc0) != 0x80)
4007
return (0); /* Missing suffix byte */
4008
4009
s ++;
4010
4011
if ((*s & 0xc0) != 0x80)
4012
return (0); /* Missing suffix byte */
4013
4014
s ++;
4015
4016
if ((*s & 0xc0) != 0x80)
4017
return (0); /* Missing suffix byte */
4018
}
4019
else
4020
return (0); /* Bad sequence */
4021
}
4022
4023
s ++;
4024
}
4025
4026
return (1);
4027
}
4028
4029