xref: /aosp_15_r20/external/libcups/tools/ipptool.c (revision 5e7646d21f1134fb0638875d812ef646c12ab91e)
1*5e7646d2SAndroid Build Coastguard Worker /*
2*5e7646d2SAndroid Build Coastguard Worker  * ipptool command for CUPS.
3*5e7646d2SAndroid Build Coastguard Worker  *
4*5e7646d2SAndroid Build Coastguard Worker  * Copyright © 2021 by OpenPrinting.
5*5e7646d2SAndroid Build Coastguard Worker  * Copyright © 2020 by The Printer Working Group.
6*5e7646d2SAndroid Build Coastguard Worker  * Copyright © 2007-2021 by Apple Inc.
7*5e7646d2SAndroid Build Coastguard Worker  * Copyright © 1997-2007 by Easy Software Products.
8*5e7646d2SAndroid Build Coastguard Worker  *
9*5e7646d2SAndroid Build Coastguard Worker  * Licensed under Apache License v2.0.  See the file "LICENSE" for more
10*5e7646d2SAndroid Build Coastguard Worker  * information.
11*5e7646d2SAndroid Build Coastguard Worker  */
12*5e7646d2SAndroid Build Coastguard Worker 
13*5e7646d2SAndroid Build Coastguard Worker /*
14*5e7646d2SAndroid Build Coastguard Worker  * Include necessary headers...
15*5e7646d2SAndroid Build Coastguard Worker  */
16*5e7646d2SAndroid Build Coastguard Worker 
17*5e7646d2SAndroid Build Coastguard Worker #include <cups/cups-private.h>
18*5e7646d2SAndroid Build Coastguard Worker #include <regex.h>
19*5e7646d2SAndroid Build Coastguard Worker #include <sys/stat.h>
20*5e7646d2SAndroid Build Coastguard Worker #ifdef _WIN32
21*5e7646d2SAndroid Build Coastguard Worker #  include <windows.h>
22*5e7646d2SAndroid Build Coastguard Worker #  ifndef R_OK
23*5e7646d2SAndroid Build Coastguard Worker #    define R_OK 0
24*5e7646d2SAndroid Build Coastguard Worker #  endif /* !R_OK */
25*5e7646d2SAndroid Build Coastguard Worker #else
26*5e7646d2SAndroid Build Coastguard Worker #  include <signal.h>
27*5e7646d2SAndroid Build Coastguard Worker #  include <termios.h>
28*5e7646d2SAndroid Build Coastguard Worker #endif /* _WIN32 */
29*5e7646d2SAndroid Build Coastguard Worker #ifndef O_BINARY
30*5e7646d2SAndroid Build Coastguard Worker #  define O_BINARY 0
31*5e7646d2SAndroid Build Coastguard Worker #endif /* !O_BINARY */
32*5e7646d2SAndroid Build Coastguard Worker 
33*5e7646d2SAndroid Build Coastguard Worker 
34*5e7646d2SAndroid Build Coastguard Worker /*
35*5e7646d2SAndroid Build Coastguard Worker  * Limits...
36*5e7646d2SAndroid Build Coastguard Worker  */
37*5e7646d2SAndroid Build Coastguard Worker 
38*5e7646d2SAndroid Build Coastguard Worker #define MAX_EXPECT	200		// Maximum number of EXPECT directives
39*5e7646d2SAndroid Build Coastguard Worker #define MAX_DISPLAY	200		// Maximum number of DISPLAY directives
40*5e7646d2SAndroid Build Coastguard Worker #define MAX_MONITOR	10		// Maximum number of MONITOR-PRINTER-STATE EXPECT directives
41*5e7646d2SAndroid Build Coastguard Worker 
42*5e7646d2SAndroid Build Coastguard Worker 
43*5e7646d2SAndroid Build Coastguard Worker /*
44*5e7646d2SAndroid Build Coastguard Worker  * Types...
45*5e7646d2SAndroid Build Coastguard Worker  */
46*5e7646d2SAndroid Build Coastguard Worker 
47*5e7646d2SAndroid Build Coastguard Worker typedef enum ipptool_transfer_e		/**** How to send request data ****/
48*5e7646d2SAndroid Build Coastguard Worker {
49*5e7646d2SAndroid Build Coastguard Worker   IPPTOOL_TRANSFER_AUTO,		/* Chunk for files, length for static */
50*5e7646d2SAndroid Build Coastguard Worker   IPPTOOL_TRANSFER_CHUNKED,		/* Chunk always */
51*5e7646d2SAndroid Build Coastguard Worker   IPPTOOL_TRANSFER_LENGTH		/* Length always */
52*5e7646d2SAndroid Build Coastguard Worker } ipptool_transfer_t;
53*5e7646d2SAndroid Build Coastguard Worker 
54*5e7646d2SAndroid Build Coastguard Worker typedef enum ipptool_output_e		/**** Output mode ****/
55*5e7646d2SAndroid Build Coastguard Worker {
56*5e7646d2SAndroid Build Coastguard Worker   IPPTOOL_OUTPUT_QUIET,			/* No output */
57*5e7646d2SAndroid Build Coastguard Worker   IPPTOOL_OUTPUT_TEST,			/* Traditional CUPS test output */
58*5e7646d2SAndroid Build Coastguard Worker   IPPTOOL_OUTPUT_PLIST,			/* XML plist test output */
59*5e7646d2SAndroid Build Coastguard Worker   IPPTOOL_OUTPUT_IPPSERVER,		/* ippserver attribute file output */
60*5e7646d2SAndroid Build Coastguard Worker   IPPTOOL_OUTPUT_LIST,			/* Tabular list output */
61*5e7646d2SAndroid Build Coastguard Worker   IPPTOOL_OUTPUT_CSV			/* Comma-separated values output */
62*5e7646d2SAndroid Build Coastguard Worker } ipptool_output_t;
63*5e7646d2SAndroid Build Coastguard Worker 
64*5e7646d2SAndroid Build Coastguard Worker typedef enum ipptool_with_e		/**** WITH flags ****/
65*5e7646d2SAndroid Build Coastguard Worker {
66*5e7646d2SAndroid Build Coastguard Worker   IPPTOOL_WITH_LITERAL = 0,		/* Match string is a literal value */
67*5e7646d2SAndroid Build Coastguard Worker   IPPTOOL_WITH_ALL = 1,			/* Must match all values */
68*5e7646d2SAndroid Build Coastguard Worker   IPPTOOL_WITH_REGEX = 2,		/* Match string is a regular expression */
69*5e7646d2SAndroid Build Coastguard Worker   IPPTOOL_WITH_HOSTNAME = 4,		/* Match string is a URI hostname */
70*5e7646d2SAndroid Build Coastguard Worker   IPPTOOL_WITH_RESOURCE = 8,		/* Match string is a URI resource */
71*5e7646d2SAndroid Build Coastguard Worker   IPPTOOL_WITH_SCHEME = 16		/* Match string is a URI scheme */
72*5e7646d2SAndroid Build Coastguard Worker } ipptool_with_t;
73*5e7646d2SAndroid Build Coastguard Worker 
74*5e7646d2SAndroid Build Coastguard Worker typedef struct ipptool_expect_s		/**** Expected attribute info ****/
75*5e7646d2SAndroid Build Coastguard Worker {
76*5e7646d2SAndroid Build Coastguard Worker   int		optional,		/* Optional attribute? */
77*5e7646d2SAndroid Build Coastguard Worker 		not_expect,		/* Don't expect attribute? */
78*5e7646d2SAndroid Build Coastguard Worker 		expect_all;		/* Expect all attributes to match/not match */
79*5e7646d2SAndroid Build Coastguard Worker   char		*name,			/* Attribute name */
80*5e7646d2SAndroid Build Coastguard Worker 		*of_type,		/* Type name */
81*5e7646d2SAndroid Build Coastguard Worker 		*same_count_as,		/* Parallel attribute name */
82*5e7646d2SAndroid Build Coastguard Worker 		*if_defined,		/* Only required if variable defined */
83*5e7646d2SAndroid Build Coastguard Worker 		*if_not_defined,	/* Only required if variable is not defined */
84*5e7646d2SAndroid Build Coastguard Worker 		*with_value,		/* Attribute must include this value */
85*5e7646d2SAndroid Build Coastguard Worker 		*with_value_from,	/* Attribute must have one of the values in this attribute */
86*5e7646d2SAndroid Build Coastguard Worker 		*define_match,		/* Variable to define on match */
87*5e7646d2SAndroid Build Coastguard Worker 		*define_no_match,	/* Variable to define on no-match */
88*5e7646d2SAndroid Build Coastguard Worker 		*define_value,		/* Variable to define with value */
89*5e7646d2SAndroid Build Coastguard Worker 		*display_match;		/* Message to display on a match */
90*5e7646d2SAndroid Build Coastguard Worker   int		repeat_limit,		/* Maximum number of times to repeat */
91*5e7646d2SAndroid Build Coastguard Worker 		repeat_match,		/* Repeat test on match */
92*5e7646d2SAndroid Build Coastguard Worker 		repeat_no_match,	/* Repeat test on no match */
93*5e7646d2SAndroid Build Coastguard Worker 		with_distinct,		/* WITH-DISTINCT-VALUES? */
94*5e7646d2SAndroid Build Coastguard Worker 		with_flags,		/* WITH flags */
95*5e7646d2SAndroid Build Coastguard Worker 		count;			/* Expected count if > 0 */
96*5e7646d2SAndroid Build Coastguard Worker   ipp_tag_t	in_group;		/* IN-GROUP value */
97*5e7646d2SAndroid Build Coastguard Worker } ipptool_expect_t;
98*5e7646d2SAndroid Build Coastguard Worker 
99*5e7646d2SAndroid Build Coastguard Worker typedef struct ipptool_status_s		/**** Status info ****/
100*5e7646d2SAndroid Build Coastguard Worker {
101*5e7646d2SAndroid Build Coastguard Worker   ipp_status_t	status;			/* Expected status code */
102*5e7646d2SAndroid Build Coastguard Worker   char		*if_defined,		/* Only if variable is defined */
103*5e7646d2SAndroid Build Coastguard Worker 		*if_not_defined,	/* Only if variable is not defined */
104*5e7646d2SAndroid Build Coastguard Worker 		*define_match,		/* Variable to define on match */
105*5e7646d2SAndroid Build Coastguard Worker 		*define_no_match,	/* Variable to define on no-match */
106*5e7646d2SAndroid Build Coastguard Worker 		*define_value;		/* Variable to define with value */
107*5e7646d2SAndroid Build Coastguard Worker   int		repeat_limit,		/* Maximum number of times to repeat */
108*5e7646d2SAndroid Build Coastguard Worker 		repeat_match,		/* Repeat the test when it does not match */
109*5e7646d2SAndroid Build Coastguard Worker 		repeat_no_match;	/* Repeat the test when it matches */
110*5e7646d2SAndroid Build Coastguard Worker } ipptool_status_t;
111*5e7646d2SAndroid Build Coastguard Worker 
112*5e7646d2SAndroid Build Coastguard Worker typedef struct ipptool_test_s		/**** Test Data ****/
113*5e7646d2SAndroid Build Coastguard Worker {
114*5e7646d2SAndroid Build Coastguard Worker   /* Global Options */
115*5e7646d2SAndroid Build Coastguard Worker   _ipp_vars_t	*vars;			/* Variables */
116*5e7646d2SAndroid Build Coastguard Worker   http_encryption_t encryption;		/* Encryption for connection */
117*5e7646d2SAndroid Build Coastguard Worker   int		family;			/* Address family */
118*5e7646d2SAndroid Build Coastguard Worker   ipptool_output_t output;		/* Output mode */
119*5e7646d2SAndroid Build Coastguard Worker   int		repeat_on_busy;		/* Repeat tests on server-error-busy */
120*5e7646d2SAndroid Build Coastguard Worker   int		stop_after_include_error;
121*5e7646d2SAndroid Build Coastguard Worker 					/* Stop after include errors? */
122*5e7646d2SAndroid Build Coastguard Worker   double	timeout;		/* Timeout for connection */
123*5e7646d2SAndroid Build Coastguard Worker   int		validate_headers,	/* Validate HTTP headers in response? */
124*5e7646d2SAndroid Build Coastguard Worker                 verbosity;		/* Show all attributes? */
125*5e7646d2SAndroid Build Coastguard Worker 
126*5e7646d2SAndroid Build Coastguard Worker   /* Test Defaults */
127*5e7646d2SAndroid Build Coastguard Worker   int		def_ignore_errors;	/* Default IGNORE-ERRORS value */
128*5e7646d2SAndroid Build Coastguard Worker   ipptool_transfer_t def_transfer;	/* Default TRANSFER value */
129*5e7646d2SAndroid Build Coastguard Worker   int		def_version;		/* Default IPP version */
130*5e7646d2SAndroid Build Coastguard Worker 
131*5e7646d2SAndroid Build Coastguard Worker   /* Global State */
132*5e7646d2SAndroid Build Coastguard Worker   http_t	*http;			/* HTTP connection to printer/server */
133*5e7646d2SAndroid Build Coastguard Worker   cups_file_t	*outfile;		/* Output file */
134*5e7646d2SAndroid Build Coastguard Worker   int		show_header,		/* Show the test header? */
135*5e7646d2SAndroid Build Coastguard Worker 		xml_header;		/* 1 if XML plist header was written */
136*5e7646d2SAndroid Build Coastguard Worker   int		pass,			/* Have we passed all tests? */
137*5e7646d2SAndroid Build Coastguard Worker 		test_count,		/* Number of tests (total) */
138*5e7646d2SAndroid Build Coastguard Worker 		pass_count,		/* Number of tests that passed */
139*5e7646d2SAndroid Build Coastguard Worker 		fail_count,		/* Number of tests that failed */
140*5e7646d2SAndroid Build Coastguard Worker 		skip_count;		/* Number of tests that were skipped */
141*5e7646d2SAndroid Build Coastguard Worker 
142*5e7646d2SAndroid Build Coastguard Worker   /* Per-Test State */
143*5e7646d2SAndroid Build Coastguard Worker   cups_array_t	*errors;		/* Errors array */
144*5e7646d2SAndroid Build Coastguard Worker   int		prev_pass,		/* Result of previous test */
145*5e7646d2SAndroid Build Coastguard Worker 		skip_previous;		/* Skip on previous test failure? */
146*5e7646d2SAndroid Build Coastguard Worker   char		compression[16];	/* COMPRESSION value */
147*5e7646d2SAndroid Build Coastguard Worker   useconds_t	delay;                  /* Initial delay */
148*5e7646d2SAndroid Build Coastguard Worker   int		num_displayed;		/* Number of displayed attributes */
149*5e7646d2SAndroid Build Coastguard Worker   char		*displayed[MAX_DISPLAY];/* Displayed attributes */
150*5e7646d2SAndroid Build Coastguard Worker   int		num_expects;		/* Number of expected attributes */
151*5e7646d2SAndroid Build Coastguard Worker   ipptool_expect_t expects[MAX_EXPECT],	/* Expected attributes */
152*5e7646d2SAndroid Build Coastguard Worker 		*expect,		/* Current expected attribute */
153*5e7646d2SAndroid Build Coastguard Worker 		*last_expect;		/* Last EXPECT (for predicates) */
154*5e7646d2SAndroid Build Coastguard Worker   char		file[1024],		/* Data filename */
155*5e7646d2SAndroid Build Coastguard Worker 		file_id[1024];		/* File identifier */
156*5e7646d2SAndroid Build Coastguard Worker   int		ignore_errors;		/* Ignore test failures? */
157*5e7646d2SAndroid Build Coastguard Worker   char		name[1024];		/* Test name */
158*5e7646d2SAndroid Build Coastguard Worker   char		pause[1024];		/* PAUSE value */
159*5e7646d2SAndroid Build Coastguard Worker   useconds_t	repeat_interval;	/* Repeat interval (delay) */
160*5e7646d2SAndroid Build Coastguard Worker   int		request_id;		/* Current request ID */
161*5e7646d2SAndroid Build Coastguard Worker   char		resource[512];		/* Resource for request */
162*5e7646d2SAndroid Build Coastguard Worker   int		pass_test,		/* Pass this test? */
163*5e7646d2SAndroid Build Coastguard Worker 		skip_test,		/* Skip this test? */
164*5e7646d2SAndroid Build Coastguard Worker 		num_statuses;		/* Number of valid status codes */
165*5e7646d2SAndroid Build Coastguard Worker   ipptool_status_t statuses[100],	/* Valid status codes */
166*5e7646d2SAndroid Build Coastguard Worker 		*last_status;		/* Last STATUS (for predicates) */
167*5e7646d2SAndroid Build Coastguard Worker   char		test_id[1024];		/* Test identifier */
168*5e7646d2SAndroid Build Coastguard Worker   ipptool_transfer_t transfer;		/* To chunk or not to chunk */
169*5e7646d2SAndroid Build Coastguard Worker   int		version;		/* IPP version number to use */
170*5e7646d2SAndroid Build Coastguard Worker   _cups_thread_t monitor_thread;	/* Monitoring thread ID */
171*5e7646d2SAndroid Build Coastguard Worker   int		monitor_done;		/* Set to 1 to stop monitor thread */
172*5e7646d2SAndroid Build Coastguard Worker   char		*monitor_uri;		/* MONITOR-PRINTER-STATE URI */
173*5e7646d2SAndroid Build Coastguard Worker   useconds_t	monitor_delay,		/* MONITOR-PRINTER-STATE DELAY value, if any */
174*5e7646d2SAndroid Build Coastguard Worker 		monitor_interval;	/* MONITOR-PRINTER-STATE DELAY interval */
175*5e7646d2SAndroid Build Coastguard Worker   int		num_monitor_expects;	/* Number MONITOR-PRINTER-STATE EXPECTs */
176*5e7646d2SAndroid Build Coastguard Worker   ipptool_expect_t monitor_expects[MAX_MONITOR];
177*5e7646d2SAndroid Build Coastguard Worker 					/* MONITOR-PRINTER-STATE EXPECTs */
178*5e7646d2SAndroid Build Coastguard Worker } ipptool_test_t;
179*5e7646d2SAndroid Build Coastguard Worker 
180*5e7646d2SAndroid Build Coastguard Worker 
181*5e7646d2SAndroid Build Coastguard Worker /*
182*5e7646d2SAndroid Build Coastguard Worker  * Globals...
183*5e7646d2SAndroid Build Coastguard Worker  */
184*5e7646d2SAndroid Build Coastguard Worker 
185*5e7646d2SAndroid Build Coastguard Worker static int	Cancel = 0;		/* Cancel test? */
186*5e7646d2SAndroid Build Coastguard Worker 
187*5e7646d2SAndroid Build Coastguard Worker 
188*5e7646d2SAndroid Build Coastguard Worker /*
189*5e7646d2SAndroid Build Coastguard Worker  * Local functions...
190*5e7646d2SAndroid Build Coastguard Worker  */
191*5e7646d2SAndroid Build Coastguard Worker 
192*5e7646d2SAndroid Build Coastguard Worker static void	add_stringf(cups_array_t *a, const char *s, ...) _CUPS_FORMAT(2, 3);
193*5e7646d2SAndroid Build Coastguard Worker static int      compare_uris(const char *a, const char *b);
194*5e7646d2SAndroid Build Coastguard Worker static void	copy_hex_string(char *buffer, unsigned char *data, int datalen, size_t bufsize);
195*5e7646d2SAndroid Build Coastguard Worker static void	*do_monitor_printer_state(ipptool_test_t *data);
196*5e7646d2SAndroid Build Coastguard Worker static int	do_test(_ipp_file_t *f, ipptool_test_t *data);
197*5e7646d2SAndroid Build Coastguard Worker static int	do_tests(const char *testfile, ipptool_test_t *data);
198*5e7646d2SAndroid Build Coastguard Worker static int	error_cb(_ipp_file_t *f, ipptool_test_t *data, const char *error);
199*5e7646d2SAndroid Build Coastguard Worker static int      expect_matches(ipptool_expect_t *expect, ipp_attribute_t *attr);
200*5e7646d2SAndroid Build Coastguard Worker static char	*get_filename(const char *testfile, char *dst, const char *src, size_t dstsize);
201*5e7646d2SAndroid Build Coastguard Worker static const char *get_string(ipp_attribute_t *attr, int element, int flags, char *buffer, size_t bufsize);
202*5e7646d2SAndroid Build Coastguard Worker static void	init_data(ipptool_test_t *data);
203*5e7646d2SAndroid Build Coastguard Worker static char	*iso_date(const ipp_uchar_t *date);
204*5e7646d2SAndroid Build Coastguard Worker static int	parse_monitor_printer_state(_ipp_file_t *f, ipptool_test_t *data);
205*5e7646d2SAndroid Build Coastguard Worker static void	pause_message(const char *message);
206*5e7646d2SAndroid Build Coastguard Worker static void	print_attr(cups_file_t *outfile, ipptool_output_t output, ipp_attribute_t *attr, ipp_tag_t *group);
207*5e7646d2SAndroid Build Coastguard Worker static ipp_attribute_t *print_csv(ipptool_test_t *data, ipp_t *ipp, ipp_attribute_t *attr, int num_displayed, char **displayed, size_t *widths);
208*5e7646d2SAndroid Build Coastguard Worker static void	print_fatal_error(ipptool_test_t *data, const char *s, ...) _CUPS_FORMAT(2, 3);
209*5e7646d2SAndroid Build Coastguard Worker static void	print_ippserver_attr(ipptool_test_t *data, ipp_attribute_t *attr, int indent);
210*5e7646d2SAndroid Build Coastguard Worker static void	print_ippserver_string(ipptool_test_t *data, const char *s, size_t len);
211*5e7646d2SAndroid Build Coastguard Worker static ipp_attribute_t *print_line(ipptool_test_t *data, ipp_t *ipp, ipp_attribute_t *attr, int num_displayed, char **displayed, size_t *widths);
212*5e7646d2SAndroid Build Coastguard Worker static void	print_xml_header(ipptool_test_t *data);
213*5e7646d2SAndroid Build Coastguard Worker static void	print_xml_string(cups_file_t *outfile, const char *element, const char *s);
214*5e7646d2SAndroid Build Coastguard Worker static void	print_xml_trailer(ipptool_test_t *data, int success, const char *message);
215*5e7646d2SAndroid Build Coastguard Worker #ifndef _WIN32
216*5e7646d2SAndroid Build Coastguard Worker static void	sigterm_handler(int sig);
217*5e7646d2SAndroid Build Coastguard Worker #endif /* _WIN32 */
218*5e7646d2SAndroid Build Coastguard Worker static int	timeout_cb(http_t *http, void *user_data);
219*5e7646d2SAndroid Build Coastguard Worker static int	token_cb(_ipp_file_t *f, _ipp_vars_t *vars, ipptool_test_t *data, const char *token);
220*5e7646d2SAndroid Build Coastguard Worker static void	usage(void) _CUPS_NORETURN;
221*5e7646d2SAndroid Build Coastguard Worker static int	with_distinct_values(cups_array_t *errors, ipp_attribute_t *attr);
222*5e7646d2SAndroid Build Coastguard Worker static const char *with_flags_string(int flags);
223*5e7646d2SAndroid Build Coastguard Worker static int      with_value(ipptool_test_t *data, cups_array_t *errors, char *value, int flags, ipp_attribute_t *attr, char *matchbuf, size_t matchlen);
224*5e7646d2SAndroid Build Coastguard Worker static int      with_value_from(cups_array_t *errors, ipp_attribute_t *fromattr, ipp_attribute_t *attr, char *matchbuf, size_t matchlen);
225*5e7646d2SAndroid Build Coastguard Worker 
226*5e7646d2SAndroid Build Coastguard Worker 
227*5e7646d2SAndroid Build Coastguard Worker /*
228*5e7646d2SAndroid Build Coastguard Worker  * 'main()' - Parse options and do tests.
229*5e7646d2SAndroid Build Coastguard Worker  */
230*5e7646d2SAndroid Build Coastguard Worker 
231*5e7646d2SAndroid Build Coastguard Worker int					/* O - Exit status */
main(int argc,char * argv[])232*5e7646d2SAndroid Build Coastguard Worker main(int  argc,				/* I - Number of command-line args */
233*5e7646d2SAndroid Build Coastguard Worker      char *argv[])			/* I - Command-line arguments */
234*5e7646d2SAndroid Build Coastguard Worker {
235*5e7646d2SAndroid Build Coastguard Worker   int			i;		/* Looping var */
236*5e7646d2SAndroid Build Coastguard Worker   int			status;		/* Status of tests... */
237*5e7646d2SAndroid Build Coastguard Worker   char			*opt,		/* Current option */
238*5e7646d2SAndroid Build Coastguard Worker 			name[1024],	/* Name/value buffer */
239*5e7646d2SAndroid Build Coastguard Worker 			*value,		/* Pointer to value */
240*5e7646d2SAndroid Build Coastguard Worker 			filename[1024],	/* Real filename */
241*5e7646d2SAndroid Build Coastguard Worker 			testname[1024];	/* Real test filename */
242*5e7646d2SAndroid Build Coastguard Worker   const char		*ext,		/* Extension on filename */
243*5e7646d2SAndroid Build Coastguard Worker 			*testfile;	/* Test file to use */
244*5e7646d2SAndroid Build Coastguard Worker   int			interval,	/* Test interval in microseconds */
245*5e7646d2SAndroid Build Coastguard Worker 			repeat;		/* Repeat count */
246*5e7646d2SAndroid Build Coastguard Worker   _ipp_vars_t		vars;		/* Variables */
247*5e7646d2SAndroid Build Coastguard Worker   ipptool_test_t	data;		/* Test data */
248*5e7646d2SAndroid Build Coastguard Worker   _cups_globals_t	*cg = _cupsGlobals();
249*5e7646d2SAndroid Build Coastguard Worker 					/* Global data */
250*5e7646d2SAndroid Build Coastguard Worker 
251*5e7646d2SAndroid Build Coastguard Worker 
252*5e7646d2SAndroid Build Coastguard Worker #ifndef _WIN32
253*5e7646d2SAndroid Build Coastguard Worker  /*
254*5e7646d2SAndroid Build Coastguard Worker   * Catch SIGINT and SIGTERM...
255*5e7646d2SAndroid Build Coastguard Worker   */
256*5e7646d2SAndroid Build Coastguard Worker 
257*5e7646d2SAndroid Build Coastguard Worker   signal(SIGINT, sigterm_handler);
258*5e7646d2SAndroid Build Coastguard Worker   signal(SIGTERM, sigterm_handler);
259*5e7646d2SAndroid Build Coastguard Worker #endif /* !_WIN32 */
260*5e7646d2SAndroid Build Coastguard Worker 
261*5e7646d2SAndroid Build Coastguard Worker  /*
262*5e7646d2SAndroid Build Coastguard Worker   * Initialize the locale and variables...
263*5e7646d2SAndroid Build Coastguard Worker   */
264*5e7646d2SAndroid Build Coastguard Worker 
265*5e7646d2SAndroid Build Coastguard Worker   _cupsSetLocale(argv);
266*5e7646d2SAndroid Build Coastguard Worker 
267*5e7646d2SAndroid Build Coastguard Worker   init_data(&data);
268*5e7646d2SAndroid Build Coastguard Worker 
269*5e7646d2SAndroid Build Coastguard Worker   _ippVarsInit(&vars, NULL, (_ipp_ferror_cb_t)error_cb, (_ipp_ftoken_cb_t)token_cb);
270*5e7646d2SAndroid Build Coastguard Worker   data.vars = &vars;
271*5e7646d2SAndroid Build Coastguard Worker 
272*5e7646d2SAndroid Build Coastguard Worker   _ippVarsSet(data.vars, "date-start", iso_date(ippTimeToDate(time(NULL))));
273*5e7646d2SAndroid Build Coastguard Worker 
274*5e7646d2SAndroid Build Coastguard Worker  /*
275*5e7646d2SAndroid Build Coastguard Worker   * We need at least:
276*5e7646d2SAndroid Build Coastguard Worker   *
277*5e7646d2SAndroid Build Coastguard Worker   *     ipptool URI testfile
278*5e7646d2SAndroid Build Coastguard Worker   */
279*5e7646d2SAndroid Build Coastguard Worker 
280*5e7646d2SAndroid Build Coastguard Worker   interval = 0;
281*5e7646d2SAndroid Build Coastguard Worker   repeat   = 0;
282*5e7646d2SAndroid Build Coastguard Worker   status   = 0;
283*5e7646d2SAndroid Build Coastguard Worker   testfile = NULL;
284*5e7646d2SAndroid Build Coastguard Worker 
285*5e7646d2SAndroid Build Coastguard Worker   for (i = 1; i < argc; i ++)
286*5e7646d2SAndroid Build Coastguard Worker   {
287*5e7646d2SAndroid Build Coastguard Worker     if (!strcmp(argv[i], "--help"))
288*5e7646d2SAndroid Build Coastguard Worker     {
289*5e7646d2SAndroid Build Coastguard Worker       usage();
290*5e7646d2SAndroid Build Coastguard Worker     }
291*5e7646d2SAndroid Build Coastguard Worker     else if (!strcmp(argv[i], "--ippserver"))
292*5e7646d2SAndroid Build Coastguard Worker     {
293*5e7646d2SAndroid Build Coastguard Worker       i ++;
294*5e7646d2SAndroid Build Coastguard Worker 
295*5e7646d2SAndroid Build Coastguard Worker       if (i >= argc)
296*5e7646d2SAndroid Build Coastguard Worker       {
297*5e7646d2SAndroid Build Coastguard Worker 	_cupsLangPuts(stderr, _("ipptool: Missing filename for \"--ippserver\"."));
298*5e7646d2SAndroid Build Coastguard Worker 	usage();
299*5e7646d2SAndroid Build Coastguard Worker       }
300*5e7646d2SAndroid Build Coastguard Worker 
301*5e7646d2SAndroid Build Coastguard Worker       if (data.outfile != cupsFileStdout())
302*5e7646d2SAndroid Build Coastguard Worker 	usage();
303*5e7646d2SAndroid Build Coastguard Worker 
304*5e7646d2SAndroid Build Coastguard Worker       if ((data.outfile = cupsFileOpen(argv[i], "w")) == NULL)
305*5e7646d2SAndroid Build Coastguard Worker       {
306*5e7646d2SAndroid Build Coastguard Worker 	_cupsLangPrintf(stderr, _("%s: Unable to open \"%s\": %s"), "ipptool", argv[i], strerror(errno));
307*5e7646d2SAndroid Build Coastguard Worker 	exit(1);
308*5e7646d2SAndroid Build Coastguard Worker       }
309*5e7646d2SAndroid Build Coastguard Worker 
310*5e7646d2SAndroid Build Coastguard Worker       data.output = IPPTOOL_OUTPUT_IPPSERVER;
311*5e7646d2SAndroid Build Coastguard Worker     }
312*5e7646d2SAndroid Build Coastguard Worker     else if (!strcmp(argv[i], "--stop-after-include-error"))
313*5e7646d2SAndroid Build Coastguard Worker     {
314*5e7646d2SAndroid Build Coastguard Worker       data.stop_after_include_error = 1;
315*5e7646d2SAndroid Build Coastguard Worker     }
316*5e7646d2SAndroid Build Coastguard Worker     else if (!strcmp(argv[i], "--version"))
317*5e7646d2SAndroid Build Coastguard Worker     {
318*5e7646d2SAndroid Build Coastguard Worker       puts(CUPS_SVERSION);
319*5e7646d2SAndroid Build Coastguard Worker       return (0);
320*5e7646d2SAndroid Build Coastguard Worker     }
321*5e7646d2SAndroid Build Coastguard Worker     else if (argv[i][0] == '-')
322*5e7646d2SAndroid Build Coastguard Worker     {
323*5e7646d2SAndroid Build Coastguard Worker       for (opt = argv[i] + 1; *opt; opt ++)
324*5e7646d2SAndroid Build Coastguard Worker       {
325*5e7646d2SAndroid Build Coastguard Worker         switch (*opt)
326*5e7646d2SAndroid Build Coastguard Worker         {
327*5e7646d2SAndroid Build Coastguard Worker 	  case '4' : /* Connect using IPv4 only */
328*5e7646d2SAndroid Build Coastguard Worker 	      data.family = AF_INET;
329*5e7646d2SAndroid Build Coastguard Worker 	      break;
330*5e7646d2SAndroid Build Coastguard Worker 
331*5e7646d2SAndroid Build Coastguard Worker #ifdef AF_INET6
332*5e7646d2SAndroid Build Coastguard Worker 	  case '6' : /* Connect using IPv6 only */
333*5e7646d2SAndroid Build Coastguard Worker 	      data.family = AF_INET6;
334*5e7646d2SAndroid Build Coastguard Worker 	      break;
335*5e7646d2SAndroid Build Coastguard Worker #endif /* AF_INET6 */
336*5e7646d2SAndroid Build Coastguard Worker 
337*5e7646d2SAndroid Build Coastguard Worker           case 'C' : /* Enable HTTP chunking */
338*5e7646d2SAndroid Build Coastguard Worker               data.def_transfer = IPPTOOL_TRANSFER_CHUNKED;
339*5e7646d2SAndroid Build Coastguard Worker               break;
340*5e7646d2SAndroid Build Coastguard Worker 
341*5e7646d2SAndroid Build Coastguard Worker 	  case 'E' : /* Encrypt with TLS */
342*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_TLS
343*5e7646d2SAndroid Build Coastguard Worker 	      data.encryption = HTTP_ENCRYPT_REQUIRED;
344*5e7646d2SAndroid Build Coastguard Worker #else
345*5e7646d2SAndroid Build Coastguard Worker 	      _cupsLangPrintf(stderr, _("%s: Sorry, no encryption support."),
346*5e7646d2SAndroid Build Coastguard Worker 			      argv[0]);
347*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_TLS */
348*5e7646d2SAndroid Build Coastguard Worker 	      break;
349*5e7646d2SAndroid Build Coastguard Worker 
350*5e7646d2SAndroid Build Coastguard Worker           case 'I' : /* Ignore errors */
351*5e7646d2SAndroid Build Coastguard Worker 	      data.def_ignore_errors = 1;
352*5e7646d2SAndroid Build Coastguard Worker 	      break;
353*5e7646d2SAndroid Build Coastguard Worker 
354*5e7646d2SAndroid Build Coastguard Worker           case 'L' : /* Disable HTTP chunking */
355*5e7646d2SAndroid Build Coastguard Worker               data.def_transfer = IPPTOOL_TRANSFER_LENGTH;
356*5e7646d2SAndroid Build Coastguard Worker               break;
357*5e7646d2SAndroid Build Coastguard Worker 
358*5e7646d2SAndroid Build Coastguard Worker           case 'P' : /* Output to plist file */
359*5e7646d2SAndroid Build Coastguard Worker 	      i ++;
360*5e7646d2SAndroid Build Coastguard Worker 
361*5e7646d2SAndroid Build Coastguard Worker 	      if (i >= argc)
362*5e7646d2SAndroid Build Coastguard Worker 	      {
363*5e7646d2SAndroid Build Coastguard Worker 		_cupsLangPrintf(stderr, _("%s: Missing filename for \"-P\"."), "ipptool");
364*5e7646d2SAndroid Build Coastguard Worker 		usage();
365*5e7646d2SAndroid Build Coastguard Worker               }
366*5e7646d2SAndroid Build Coastguard Worker 
367*5e7646d2SAndroid Build Coastguard Worker               if (data.outfile != cupsFileStdout())
368*5e7646d2SAndroid Build Coastguard Worker                 usage();
369*5e7646d2SAndroid Build Coastguard Worker 
370*5e7646d2SAndroid Build Coastguard Worker               if ((data.outfile = cupsFileOpen(argv[i], "w")) == NULL)
371*5e7646d2SAndroid Build Coastguard Worker               {
372*5e7646d2SAndroid Build Coastguard Worker                 _cupsLangPrintf(stderr, _("%s: Unable to open \"%s\": %s"), "ipptool", argv[i], strerror(errno));
373*5e7646d2SAndroid Build Coastguard Worker                 exit(1);
374*5e7646d2SAndroid Build Coastguard Worker               }
375*5e7646d2SAndroid Build Coastguard Worker 
376*5e7646d2SAndroid Build Coastguard Worker 	      data.output = IPPTOOL_OUTPUT_PLIST;
377*5e7646d2SAndroid Build Coastguard Worker 
378*5e7646d2SAndroid Build Coastguard Worker               if (interval || repeat)
379*5e7646d2SAndroid Build Coastguard Worker 	      {
380*5e7646d2SAndroid Build Coastguard Worker 	        _cupsLangPuts(stderr, _("ipptool: \"-i\" and \"-n\" are incompatible with \"-P\" and \"-X\"."));
381*5e7646d2SAndroid Build Coastguard Worker 		usage();
382*5e7646d2SAndroid Build Coastguard Worker 	      }
383*5e7646d2SAndroid Build Coastguard Worker               break;
384*5e7646d2SAndroid Build Coastguard Worker 
385*5e7646d2SAndroid Build Coastguard Worker           case 'R' : /* Repeat on server-error-busy */
386*5e7646d2SAndroid Build Coastguard Worker               data.repeat_on_busy = 1;
387*5e7646d2SAndroid Build Coastguard Worker               break;
388*5e7646d2SAndroid Build Coastguard Worker 
389*5e7646d2SAndroid Build Coastguard Worker 	  case 'S' : /* Encrypt with SSL */
390*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_TLS
391*5e7646d2SAndroid Build Coastguard Worker 	      data.encryption = HTTP_ENCRYPT_ALWAYS;
392*5e7646d2SAndroid Build Coastguard Worker #else
393*5e7646d2SAndroid Build Coastguard Worker 	      _cupsLangPrintf(stderr, _("%s: Sorry, no encryption support."), "ipptool");
394*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_TLS */
395*5e7646d2SAndroid Build Coastguard Worker 	      break;
396*5e7646d2SAndroid Build Coastguard Worker 
397*5e7646d2SAndroid Build Coastguard Worker 	  case 'T' : /* Set timeout */
398*5e7646d2SAndroid Build Coastguard Worker 	      i ++;
399*5e7646d2SAndroid Build Coastguard Worker 
400*5e7646d2SAndroid Build Coastguard Worker 	      if (i >= argc)
401*5e7646d2SAndroid Build Coastguard Worker 	      {
402*5e7646d2SAndroid Build Coastguard Worker 		_cupsLangPrintf(stderr, _("%s: Missing timeout for \"-T\"."), "ipptool");
403*5e7646d2SAndroid Build Coastguard Worker 		usage();
404*5e7646d2SAndroid Build Coastguard Worker               }
405*5e7646d2SAndroid Build Coastguard Worker 
406*5e7646d2SAndroid Build Coastguard Worker 	      data.timeout = _cupsStrScand(argv[i], NULL, localeconv());
407*5e7646d2SAndroid Build Coastguard Worker 	      break;
408*5e7646d2SAndroid Build Coastguard Worker 
409*5e7646d2SAndroid Build Coastguard Worker 	  case 'V' : /* Set IPP version */
410*5e7646d2SAndroid Build Coastguard Worker 	      i ++;
411*5e7646d2SAndroid Build Coastguard Worker 
412*5e7646d2SAndroid Build Coastguard Worker 	      if (i >= argc)
413*5e7646d2SAndroid Build Coastguard Worker 	      {
414*5e7646d2SAndroid Build Coastguard Worker 		_cupsLangPrintf(stderr, _("%s: Missing version for \"-V\"."), "ipptool");
415*5e7646d2SAndroid Build Coastguard Worker 		usage();
416*5e7646d2SAndroid Build Coastguard Worker               }
417*5e7646d2SAndroid Build Coastguard Worker 
418*5e7646d2SAndroid Build Coastguard Worker 	      if (!strcmp(argv[i], "1.0"))
419*5e7646d2SAndroid Build Coastguard Worker 	      {
420*5e7646d2SAndroid Build Coastguard Worker 	        data.def_version = 10;
421*5e7646d2SAndroid Build Coastguard Worker 	      }
422*5e7646d2SAndroid Build Coastguard Worker 	      else if (!strcmp(argv[i], "1.1"))
423*5e7646d2SAndroid Build Coastguard Worker 	      {
424*5e7646d2SAndroid Build Coastguard Worker 	        data.def_version = 11;
425*5e7646d2SAndroid Build Coastguard Worker 	      }
426*5e7646d2SAndroid Build Coastguard Worker 	      else if (!strcmp(argv[i], "2.0"))
427*5e7646d2SAndroid Build Coastguard Worker 	      {
428*5e7646d2SAndroid Build Coastguard Worker 	        data.def_version = 20;
429*5e7646d2SAndroid Build Coastguard Worker 	      }
430*5e7646d2SAndroid Build Coastguard Worker 	      else if (!strcmp(argv[i], "2.1"))
431*5e7646d2SAndroid Build Coastguard Worker 	      {
432*5e7646d2SAndroid Build Coastguard Worker 	        data.def_version = 21;
433*5e7646d2SAndroid Build Coastguard Worker 	      }
434*5e7646d2SAndroid Build Coastguard Worker 	      else if (!strcmp(argv[i], "2.2"))
435*5e7646d2SAndroid Build Coastguard Worker 	      {
436*5e7646d2SAndroid Build Coastguard Worker 	        data.def_version = 22;
437*5e7646d2SAndroid Build Coastguard Worker 	      }
438*5e7646d2SAndroid Build Coastguard Worker 	      else
439*5e7646d2SAndroid Build Coastguard Worker 	      {
440*5e7646d2SAndroid Build Coastguard Worker 		_cupsLangPrintf(stderr, _("%s: Bad version %s for \"-V\"."), "ipptool", argv[i]);
441*5e7646d2SAndroid Build Coastguard Worker 		usage();
442*5e7646d2SAndroid Build Coastguard Worker 	      }
443*5e7646d2SAndroid Build Coastguard Worker 	      break;
444*5e7646d2SAndroid Build Coastguard Worker 
445*5e7646d2SAndroid Build Coastguard Worker           case 'X' : /* Produce XML output */
446*5e7646d2SAndroid Build Coastguard Worker 	      data.output = IPPTOOL_OUTPUT_PLIST;
447*5e7646d2SAndroid Build Coastguard Worker 
448*5e7646d2SAndroid Build Coastguard Worker               if (interval || repeat)
449*5e7646d2SAndroid Build Coastguard Worker 	      {
450*5e7646d2SAndroid Build Coastguard Worker 	        _cupsLangPuts(stderr, _("ipptool: \"-i\" and \"-n\" are incompatible with \"-P\" and \"-X\"."));
451*5e7646d2SAndroid Build Coastguard Worker 		usage();
452*5e7646d2SAndroid Build Coastguard Worker 	      }
453*5e7646d2SAndroid Build Coastguard Worker 	      break;
454*5e7646d2SAndroid Build Coastguard Worker 
455*5e7646d2SAndroid Build Coastguard Worker           case 'c' : /* CSV output */
456*5e7646d2SAndroid Build Coastguard Worker               data.output = IPPTOOL_OUTPUT_CSV;
457*5e7646d2SAndroid Build Coastguard Worker               break;
458*5e7646d2SAndroid Build Coastguard Worker 
459*5e7646d2SAndroid Build Coastguard Worker           case 'd' : /* Define a variable */
460*5e7646d2SAndroid Build Coastguard Worker 	      i ++;
461*5e7646d2SAndroid Build Coastguard Worker 
462*5e7646d2SAndroid Build Coastguard Worker 	      if (i >= argc)
463*5e7646d2SAndroid Build Coastguard Worker 	      {
464*5e7646d2SAndroid Build Coastguard Worker 		_cupsLangPuts(stderr, _("ipptool: Missing name=value for \"-d\"."));
465*5e7646d2SAndroid Build Coastguard Worker 		usage();
466*5e7646d2SAndroid Build Coastguard Worker               }
467*5e7646d2SAndroid Build Coastguard Worker 
468*5e7646d2SAndroid Build Coastguard Worker               strlcpy(name, argv[i], sizeof(name));
469*5e7646d2SAndroid Build Coastguard Worker 	      if ((value = strchr(name, '=')) != NULL)
470*5e7646d2SAndroid Build Coastguard Worker 	        *value++ = '\0';
471*5e7646d2SAndroid Build Coastguard Worker 	      else
472*5e7646d2SAndroid Build Coastguard Worker 	        value = name + strlen(name);
473*5e7646d2SAndroid Build Coastguard Worker 
474*5e7646d2SAndroid Build Coastguard Worker 	      _ippVarsSet(data.vars, name, value);
475*5e7646d2SAndroid Build Coastguard Worker 	      break;
476*5e7646d2SAndroid Build Coastguard Worker 
477*5e7646d2SAndroid Build Coastguard Worker           case 'f' : /* Set the default test filename */
478*5e7646d2SAndroid Build Coastguard Worker 	      i ++;
479*5e7646d2SAndroid Build Coastguard Worker 
480*5e7646d2SAndroid Build Coastguard Worker 	      if (i >= argc)
481*5e7646d2SAndroid Build Coastguard Worker 	      {
482*5e7646d2SAndroid Build Coastguard Worker 		_cupsLangPuts(stderr, _("ipptool: Missing filename for \"-f\"."));
483*5e7646d2SAndroid Build Coastguard Worker 		usage();
484*5e7646d2SAndroid Build Coastguard Worker               }
485*5e7646d2SAndroid Build Coastguard Worker 
486*5e7646d2SAndroid Build Coastguard Worker               if (access(argv[i], 0))
487*5e7646d2SAndroid Build Coastguard Worker               {
488*5e7646d2SAndroid Build Coastguard Worker                /*
489*5e7646d2SAndroid Build Coastguard Worker                 * Try filename.gz...
490*5e7646d2SAndroid Build Coastguard Worker                 */
491*5e7646d2SAndroid Build Coastguard Worker 
492*5e7646d2SAndroid Build Coastguard Worker 		snprintf(filename, sizeof(filename), "%s.gz", argv[i]);
493*5e7646d2SAndroid Build Coastguard Worker                 if (access(filename, 0) && filename[0] != '/'
494*5e7646d2SAndroid Build Coastguard Worker #ifdef _WIN32
495*5e7646d2SAndroid Build Coastguard Worker                     && (!isalpha(filename[0] & 255) || filename[1] != ':')
496*5e7646d2SAndroid Build Coastguard Worker #endif /* _WIN32 */
497*5e7646d2SAndroid Build Coastguard Worker                     )
498*5e7646d2SAndroid Build Coastguard Worker 		{
499*5e7646d2SAndroid Build Coastguard Worker 		  snprintf(filename, sizeof(filename), "%s/ipptool/%s", cg->cups_datadir, argv[i]);
500*5e7646d2SAndroid Build Coastguard Worker 		  if (access(filename, 0))
501*5e7646d2SAndroid Build Coastguard Worker 		  {
502*5e7646d2SAndroid Build Coastguard Worker 		    snprintf(filename, sizeof(filename), "%s/ipptool/%s.gz", cg->cups_datadir, argv[i]);
503*5e7646d2SAndroid Build Coastguard Worker 		    if (access(filename, 0))
504*5e7646d2SAndroid Build Coastguard Worker 		      strlcpy(filename, argv[i], sizeof(filename));
505*5e7646d2SAndroid Build Coastguard Worker 		  }
506*5e7646d2SAndroid Build Coastguard Worker 		}
507*5e7646d2SAndroid Build Coastguard Worker 	      }
508*5e7646d2SAndroid Build Coastguard Worker               else
509*5e7646d2SAndroid Build Coastguard Worker 		strlcpy(filename, argv[i], sizeof(filename));
510*5e7646d2SAndroid Build Coastguard Worker 
511*5e7646d2SAndroid Build Coastguard Worker 	      _ippVarsSet(data.vars, "filename", filename);
512*5e7646d2SAndroid Build Coastguard Worker 
513*5e7646d2SAndroid Build Coastguard Worker               if ((ext = strrchr(filename, '.')) != NULL)
514*5e7646d2SAndroid Build Coastguard Worker               {
515*5e7646d2SAndroid Build Coastguard Worker                /*
516*5e7646d2SAndroid Build Coastguard Worker                 * Guess the MIME media type based on the extension...
517*5e7646d2SAndroid Build Coastguard Worker                 */
518*5e7646d2SAndroid Build Coastguard Worker 
519*5e7646d2SAndroid Build Coastguard Worker                 if (!_cups_strcasecmp(ext, ".gif"))
520*5e7646d2SAndroid Build Coastguard Worker                   _ippVarsSet(data.vars, "filetype", "image/gif");
521*5e7646d2SAndroid Build Coastguard Worker                 else if (!_cups_strcasecmp(ext, ".htm") ||
522*5e7646d2SAndroid Build Coastguard Worker                          !_cups_strcasecmp(ext, ".htm.gz") ||
523*5e7646d2SAndroid Build Coastguard Worker                          !_cups_strcasecmp(ext, ".html") ||
524*5e7646d2SAndroid Build Coastguard Worker                          !_cups_strcasecmp(ext, ".html.gz"))
525*5e7646d2SAndroid Build Coastguard Worker                   _ippVarsSet(data.vars, "filetype", "text/html");
526*5e7646d2SAndroid Build Coastguard Worker                 else if (!_cups_strcasecmp(ext, ".jpg") ||
527*5e7646d2SAndroid Build Coastguard Worker                          !_cups_strcasecmp(ext, ".jpeg"))
528*5e7646d2SAndroid Build Coastguard Worker                   _ippVarsSet(data.vars, "filetype", "image/jpeg");
529*5e7646d2SAndroid Build Coastguard Worker                 else if (!_cups_strcasecmp(ext, ".pcl") ||
530*5e7646d2SAndroid Build Coastguard Worker                          !_cups_strcasecmp(ext, ".pcl.gz"))
531*5e7646d2SAndroid Build Coastguard Worker                   _ippVarsSet(data.vars, "filetype", "application/vnd.hp-PCL");
532*5e7646d2SAndroid Build Coastguard Worker                 else if (!_cups_strcasecmp(ext, ".pdf"))
533*5e7646d2SAndroid Build Coastguard Worker                   _ippVarsSet(data.vars, "filetype", "application/pdf");
534*5e7646d2SAndroid Build Coastguard Worker                 else if (!_cups_strcasecmp(ext, ".png"))
535*5e7646d2SAndroid Build Coastguard Worker                   _ippVarsSet(data.vars, "filetype", "image/png");
536*5e7646d2SAndroid Build Coastguard Worker                 else if (!_cups_strcasecmp(ext, ".ps") ||
537*5e7646d2SAndroid Build Coastguard Worker                          !_cups_strcasecmp(ext, ".ps.gz"))
538*5e7646d2SAndroid Build Coastguard Worker                   _ippVarsSet(data.vars, "filetype", "application/postscript");
539*5e7646d2SAndroid Build Coastguard Worker                 else if (!_cups_strcasecmp(ext, ".pwg") ||
540*5e7646d2SAndroid Build Coastguard Worker                          !_cups_strcasecmp(ext, ".pwg.gz") ||
541*5e7646d2SAndroid Build Coastguard Worker                          !_cups_strcasecmp(ext, ".ras") ||
542*5e7646d2SAndroid Build Coastguard Worker                          !_cups_strcasecmp(ext, ".ras.gz"))
543*5e7646d2SAndroid Build Coastguard Worker                   _ippVarsSet(data.vars, "filetype", "image/pwg-raster");
544*5e7646d2SAndroid Build Coastguard Worker                 else if (!_cups_strcasecmp(ext, ".tif") ||
545*5e7646d2SAndroid Build Coastguard Worker                          !_cups_strcasecmp(ext, ".tiff"))
546*5e7646d2SAndroid Build Coastguard Worker                   _ippVarsSet(data.vars, "filetype", "image/tiff");
547*5e7646d2SAndroid Build Coastguard Worker                 else if (!_cups_strcasecmp(ext, ".txt") ||
548*5e7646d2SAndroid Build Coastguard Worker                          !_cups_strcasecmp(ext, ".txt.gz"))
549*5e7646d2SAndroid Build Coastguard Worker                   _ippVarsSet(data.vars, "filetype", "text/plain");
550*5e7646d2SAndroid Build Coastguard Worker                 else if (!_cups_strcasecmp(ext, ".urf") ||
551*5e7646d2SAndroid Build Coastguard Worker                          !_cups_strcasecmp(ext, ".urf.gz"))
552*5e7646d2SAndroid Build Coastguard Worker                   _ippVarsSet(data.vars, "filetype", "image/urf");
553*5e7646d2SAndroid Build Coastguard Worker                 else if (!_cups_strcasecmp(ext, ".xps"))
554*5e7646d2SAndroid Build Coastguard Worker                   _ippVarsSet(data.vars, "filetype", "application/openxps");
555*5e7646d2SAndroid Build Coastguard Worker                 else
556*5e7646d2SAndroid Build Coastguard Worker 		  _ippVarsSet(data.vars, "filetype", "application/octet-stream");
557*5e7646d2SAndroid Build Coastguard Worker               }
558*5e7646d2SAndroid Build Coastguard Worker               else
559*5e7646d2SAndroid Build Coastguard Worker               {
560*5e7646d2SAndroid Build Coastguard Worker                /*
561*5e7646d2SAndroid Build Coastguard Worker                 * Use the "auto-type" MIME media type...
562*5e7646d2SAndroid Build Coastguard Worker                 */
563*5e7646d2SAndroid Build Coastguard Worker 
564*5e7646d2SAndroid Build Coastguard Worker 		_ippVarsSet(data.vars, "filetype", "application/octet-stream");
565*5e7646d2SAndroid Build Coastguard Worker               }
566*5e7646d2SAndroid Build Coastguard Worker 	      break;
567*5e7646d2SAndroid Build Coastguard Worker 
568*5e7646d2SAndroid Build Coastguard Worker           case 'h' : /* Validate response headers */
569*5e7646d2SAndroid Build Coastguard Worker               data.validate_headers = 1;
570*5e7646d2SAndroid Build Coastguard Worker               break;
571*5e7646d2SAndroid Build Coastguard Worker 
572*5e7646d2SAndroid Build Coastguard Worker           case 'i' : /* Test every N seconds */
573*5e7646d2SAndroid Build Coastguard Worker 	      i ++;
574*5e7646d2SAndroid Build Coastguard Worker 
575*5e7646d2SAndroid Build Coastguard Worker 	      if (i >= argc)
576*5e7646d2SAndroid Build Coastguard Worker 	      {
577*5e7646d2SAndroid Build Coastguard Worker 		_cupsLangPuts(stderr, _("ipptool: Missing seconds for \"-i\"."));
578*5e7646d2SAndroid Build Coastguard Worker 		usage();
579*5e7646d2SAndroid Build Coastguard Worker               }
580*5e7646d2SAndroid Build Coastguard Worker 	      else
581*5e7646d2SAndroid Build Coastguard Worker 	      {
582*5e7646d2SAndroid Build Coastguard Worker 		interval = (int)(_cupsStrScand(argv[i], NULL, localeconv()) * 1000000.0);
583*5e7646d2SAndroid Build Coastguard Worker 		if (interval <= 0)
584*5e7646d2SAndroid Build Coastguard Worker 		{
585*5e7646d2SAndroid Build Coastguard Worker 		  _cupsLangPuts(stderr, _("ipptool: Invalid seconds for \"-i\"."));
586*5e7646d2SAndroid Build Coastguard Worker 		  usage();
587*5e7646d2SAndroid Build Coastguard Worker 		}
588*5e7646d2SAndroid Build Coastguard Worker               }
589*5e7646d2SAndroid Build Coastguard Worker 
590*5e7646d2SAndroid Build Coastguard Worker               if ((data.output == IPPTOOL_OUTPUT_PLIST || data.output == IPPTOOL_OUTPUT_IPPSERVER) && interval)
591*5e7646d2SAndroid Build Coastguard Worker 	      {
592*5e7646d2SAndroid Build Coastguard Worker 	        _cupsLangPuts(stderr, _("ipptool: \"-i\" and \"-n\" are incompatible with \"--ippserver\", \"-P\", and \"-X\"."));
593*5e7646d2SAndroid Build Coastguard Worker 		usage();
594*5e7646d2SAndroid Build Coastguard Worker 	      }
595*5e7646d2SAndroid Build Coastguard Worker 	      break;
596*5e7646d2SAndroid Build Coastguard Worker 
597*5e7646d2SAndroid Build Coastguard Worker           case 'l' : /* List as a table */
598*5e7646d2SAndroid Build Coastguard Worker               data.output = IPPTOOL_OUTPUT_LIST;
599*5e7646d2SAndroid Build Coastguard Worker               break;
600*5e7646d2SAndroid Build Coastguard Worker 
601*5e7646d2SAndroid Build Coastguard Worker           case 'n' : /* Repeat count */
602*5e7646d2SAndroid Build Coastguard Worker               i ++;
603*5e7646d2SAndroid Build Coastguard Worker 
604*5e7646d2SAndroid Build Coastguard Worker 	      if (i >= argc)
605*5e7646d2SAndroid Build Coastguard Worker 	      {
606*5e7646d2SAndroid Build Coastguard Worker 		_cupsLangPuts(stderr, _("ipptool: Missing count for \"-n\"."));
607*5e7646d2SAndroid Build Coastguard Worker 		usage();
608*5e7646d2SAndroid Build Coastguard Worker               }
609*5e7646d2SAndroid Build Coastguard Worker 	      else
610*5e7646d2SAndroid Build Coastguard Worker 		repeat = atoi(argv[i]);
611*5e7646d2SAndroid Build Coastguard Worker 
612*5e7646d2SAndroid Build Coastguard Worker               if ((data.output == IPPTOOL_OUTPUT_PLIST || data.output == IPPTOOL_OUTPUT_IPPSERVER) && repeat)
613*5e7646d2SAndroid Build Coastguard Worker 	      {
614*5e7646d2SAndroid Build Coastguard Worker 	        _cupsLangPuts(stderr, _("ipptool: \"-i\" and \"-n\" are incompatible with \"--ippserver\", \"-P\", and \"-X\"."));
615*5e7646d2SAndroid Build Coastguard Worker 		usage();
616*5e7646d2SAndroid Build Coastguard Worker 	      }
617*5e7646d2SAndroid Build Coastguard Worker 	      break;
618*5e7646d2SAndroid Build Coastguard Worker 
619*5e7646d2SAndroid Build Coastguard Worker           case 'q' : /* Be quiet */
620*5e7646d2SAndroid Build Coastguard Worker               data.output = IPPTOOL_OUTPUT_QUIET;
621*5e7646d2SAndroid Build Coastguard Worker               break;
622*5e7646d2SAndroid Build Coastguard Worker 
623*5e7646d2SAndroid Build Coastguard Worker           case 't' : /* CUPS test output */
624*5e7646d2SAndroid Build Coastguard Worker               data.output = IPPTOOL_OUTPUT_TEST;
625*5e7646d2SAndroid Build Coastguard Worker               break;
626*5e7646d2SAndroid Build Coastguard Worker 
627*5e7646d2SAndroid Build Coastguard Worker           case 'v' : /* Be verbose */
628*5e7646d2SAndroid Build Coastguard Worker 	      data.verbosity ++;
629*5e7646d2SAndroid Build Coastguard Worker 	      break;
630*5e7646d2SAndroid Build Coastguard Worker 
631*5e7646d2SAndroid Build Coastguard Worker 	  default :
632*5e7646d2SAndroid Build Coastguard Worker 	      _cupsLangPrintf(stderr, _("%s: Unknown option \"-%c\"."), "ipptool", *opt);
633*5e7646d2SAndroid Build Coastguard Worker 	      usage();
634*5e7646d2SAndroid Build Coastguard Worker 	}
635*5e7646d2SAndroid Build Coastguard Worker       }
636*5e7646d2SAndroid Build Coastguard Worker     }
637*5e7646d2SAndroid Build Coastguard Worker     else if (!strncmp(argv[i], "ipp://", 6) || !strncmp(argv[i], "http://", 7)
638*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_TLS
639*5e7646d2SAndroid Build Coastguard Worker 	     || !strncmp(argv[i], "ipps://", 7) || !strncmp(argv[i], "https://", 8)
640*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_TLS */
641*5e7646d2SAndroid Build Coastguard Worker 	     )
642*5e7646d2SAndroid Build Coastguard Worker     {
643*5e7646d2SAndroid Build Coastguard Worker      /*
644*5e7646d2SAndroid Build Coastguard Worker       * Set URI...
645*5e7646d2SAndroid Build Coastguard Worker       */
646*5e7646d2SAndroid Build Coastguard Worker 
647*5e7646d2SAndroid Build Coastguard Worker       if (data.vars->uri)
648*5e7646d2SAndroid Build Coastguard Worker       {
649*5e7646d2SAndroid Build Coastguard Worker         _cupsLangPuts(stderr, _("ipptool: May only specify a single URI."));
650*5e7646d2SAndroid Build Coastguard Worker         usage();
651*5e7646d2SAndroid Build Coastguard Worker       }
652*5e7646d2SAndroid Build Coastguard Worker 
653*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_TLS
654*5e7646d2SAndroid Build Coastguard Worker       if (!strncmp(argv[i], "ipps://", 7) || !strncmp(argv[i], "https://", 8))
655*5e7646d2SAndroid Build Coastguard Worker         data.encryption = HTTP_ENCRYPT_ALWAYS;
656*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_TLS */
657*5e7646d2SAndroid Build Coastguard Worker 
658*5e7646d2SAndroid Build Coastguard Worker       if (!_ippVarsSet(data.vars, "uri", argv[i]))
659*5e7646d2SAndroid Build Coastguard Worker       {
660*5e7646d2SAndroid Build Coastguard Worker         _cupsLangPrintf(stderr, _("ipptool: Bad URI \"%s\"."), argv[i]);
661*5e7646d2SAndroid Build Coastguard Worker         return (1);
662*5e7646d2SAndroid Build Coastguard Worker       }
663*5e7646d2SAndroid Build Coastguard Worker 
664*5e7646d2SAndroid Build Coastguard Worker       if (data.vars->username[0] && data.vars->password)
665*5e7646d2SAndroid Build Coastguard Worker 	cupsSetPasswordCB2(_ippVarsPasswordCB, data.vars);
666*5e7646d2SAndroid Build Coastguard Worker     }
667*5e7646d2SAndroid Build Coastguard Worker     else
668*5e7646d2SAndroid Build Coastguard Worker     {
669*5e7646d2SAndroid Build Coastguard Worker      /*
670*5e7646d2SAndroid Build Coastguard Worker       * Run test...
671*5e7646d2SAndroid Build Coastguard Worker       */
672*5e7646d2SAndroid Build Coastguard Worker 
673*5e7646d2SAndroid Build Coastguard Worker       if (!data.vars->uri)
674*5e7646d2SAndroid Build Coastguard Worker       {
675*5e7646d2SAndroid Build Coastguard Worker         _cupsLangPuts(stderr, _("ipptool: URI required before test file."));
676*5e7646d2SAndroid Build Coastguard Worker         _cupsLangPuts(stderr, argv[i]);
677*5e7646d2SAndroid Build Coastguard Worker 	usage();
678*5e7646d2SAndroid Build Coastguard Worker       }
679*5e7646d2SAndroid Build Coastguard Worker 
680*5e7646d2SAndroid Build Coastguard Worker       if (access(argv[i], 0) && argv[i][0] != '/'
681*5e7646d2SAndroid Build Coastguard Worker #ifdef _WIN32
682*5e7646d2SAndroid Build Coastguard Worker           && (!isalpha(argv[i][0] & 255) || argv[i][1] != ':')
683*5e7646d2SAndroid Build Coastguard Worker #endif /* _WIN32 */
684*5e7646d2SAndroid Build Coastguard Worker           )
685*5e7646d2SAndroid Build Coastguard Worker       {
686*5e7646d2SAndroid Build Coastguard Worker         snprintf(testname, sizeof(testname), "%s/ipptool/%s", cg->cups_datadir, argv[i]);
687*5e7646d2SAndroid Build Coastguard Worker         if (access(testname, 0))
688*5e7646d2SAndroid Build Coastguard Worker           testfile = argv[i];
689*5e7646d2SAndroid Build Coastguard Worker         else
690*5e7646d2SAndroid Build Coastguard Worker           testfile = testname;
691*5e7646d2SAndroid Build Coastguard Worker       }
692*5e7646d2SAndroid Build Coastguard Worker       else
693*5e7646d2SAndroid Build Coastguard Worker         testfile = argv[i];
694*5e7646d2SAndroid Build Coastguard Worker 
695*5e7646d2SAndroid Build Coastguard Worker       if (access(testfile, 0))
696*5e7646d2SAndroid Build Coastguard Worker       {
697*5e7646d2SAndroid Build Coastguard Worker         _cupsLangPrintf(stderr, _("%s: Unable to open \"%s\": %s"), "ipptool", testfile, strerror(errno));
698*5e7646d2SAndroid Build Coastguard Worker         status = 1;
699*5e7646d2SAndroid Build Coastguard Worker       }
700*5e7646d2SAndroid Build Coastguard Worker       else if (!do_tests(testfile, &data))
701*5e7646d2SAndroid Build Coastguard Worker         status = 1;
702*5e7646d2SAndroid Build Coastguard Worker     }
703*5e7646d2SAndroid Build Coastguard Worker   }
704*5e7646d2SAndroid Build Coastguard Worker 
705*5e7646d2SAndroid Build Coastguard Worker   if (!data.vars->uri || !testfile)
706*5e7646d2SAndroid Build Coastguard Worker     usage();
707*5e7646d2SAndroid Build Coastguard Worker 
708*5e7646d2SAndroid Build Coastguard Worker  /*
709*5e7646d2SAndroid Build Coastguard Worker   * Loop if the interval is set...
710*5e7646d2SAndroid Build Coastguard Worker   */
711*5e7646d2SAndroid Build Coastguard Worker 
712*5e7646d2SAndroid Build Coastguard Worker   if (data.output == IPPTOOL_OUTPUT_PLIST)
713*5e7646d2SAndroid Build Coastguard Worker     print_xml_trailer(&data, !status, NULL);
714*5e7646d2SAndroid Build Coastguard Worker   else if (interval > 0 && repeat > 0)
715*5e7646d2SAndroid Build Coastguard Worker   {
716*5e7646d2SAndroid Build Coastguard Worker     while (repeat > 1)
717*5e7646d2SAndroid Build Coastguard Worker     {
718*5e7646d2SAndroid Build Coastguard Worker       usleep((useconds_t)interval);
719*5e7646d2SAndroid Build Coastguard Worker       do_tests(testfile, &data);
720*5e7646d2SAndroid Build Coastguard Worker       repeat --;
721*5e7646d2SAndroid Build Coastguard Worker     }
722*5e7646d2SAndroid Build Coastguard Worker   }
723*5e7646d2SAndroid Build Coastguard Worker   else if (interval > 0)
724*5e7646d2SAndroid Build Coastguard Worker   {
725*5e7646d2SAndroid Build Coastguard Worker     for (;;)
726*5e7646d2SAndroid Build Coastguard Worker     {
727*5e7646d2SAndroid Build Coastguard Worker       usleep((useconds_t)interval);
728*5e7646d2SAndroid Build Coastguard Worker       do_tests(testfile, &data);
729*5e7646d2SAndroid Build Coastguard Worker     }
730*5e7646d2SAndroid Build Coastguard Worker   }
731*5e7646d2SAndroid Build Coastguard Worker 
732*5e7646d2SAndroid Build Coastguard Worker   if ((data.output == IPPTOOL_OUTPUT_TEST || (data.output == IPPTOOL_OUTPUT_PLIST && data.outfile)) && data.test_count > 1)
733*5e7646d2SAndroid Build Coastguard Worker   {
734*5e7646d2SAndroid Build Coastguard Worker    /*
735*5e7646d2SAndroid Build Coastguard Worker     * Show a summary report if there were multiple tests...
736*5e7646d2SAndroid Build Coastguard Worker     */
737*5e7646d2SAndroid Build Coastguard Worker 
738*5e7646d2SAndroid Build Coastguard Worker     cupsFilePrintf(cupsFileStdout(), "\nSummary: %d tests, %d passed, %d failed, %d skipped\nScore: %d%%\n", data.test_count, data.pass_count, data.fail_count, data.skip_count, 100 * (data.pass_count + data.skip_count) / data.test_count);
739*5e7646d2SAndroid Build Coastguard Worker   }
740*5e7646d2SAndroid Build Coastguard Worker 
741*5e7646d2SAndroid Build Coastguard Worker   cupsFileClose(data.outfile);
742*5e7646d2SAndroid Build Coastguard Worker 
743*5e7646d2SAndroid Build Coastguard Worker  /*
744*5e7646d2SAndroid Build Coastguard Worker   * Exit...
745*5e7646d2SAndroid Build Coastguard Worker   */
746*5e7646d2SAndroid Build Coastguard Worker 
747*5e7646d2SAndroid Build Coastguard Worker   return (status);
748*5e7646d2SAndroid Build Coastguard Worker }
749*5e7646d2SAndroid Build Coastguard Worker 
750*5e7646d2SAndroid Build Coastguard Worker 
751*5e7646d2SAndroid Build Coastguard Worker /*
752*5e7646d2SAndroid Build Coastguard Worker  * 'add_stringf()' - Add a formatted string to an array.
753*5e7646d2SAndroid Build Coastguard Worker  */
754*5e7646d2SAndroid Build Coastguard Worker 
755*5e7646d2SAndroid Build Coastguard Worker static void
add_stringf(cups_array_t * a,const char * s,...)756*5e7646d2SAndroid Build Coastguard Worker add_stringf(cups_array_t *a,		/* I - Array */
757*5e7646d2SAndroid Build Coastguard Worker             const char   *s,		/* I - Printf-style format string */
758*5e7646d2SAndroid Build Coastguard Worker             ...)			/* I - Additional args as needed */
759*5e7646d2SAndroid Build Coastguard Worker {
760*5e7646d2SAndroid Build Coastguard Worker   char		buffer[10240];		/* Format buffer */
761*5e7646d2SAndroid Build Coastguard Worker   va_list	ap;			/* Argument pointer */
762*5e7646d2SAndroid Build Coastguard Worker 
763*5e7646d2SAndroid Build Coastguard Worker 
764*5e7646d2SAndroid Build Coastguard Worker  /*
765*5e7646d2SAndroid Build Coastguard Worker   * Don't bother is the array is NULL...
766*5e7646d2SAndroid Build Coastguard Worker   */
767*5e7646d2SAndroid Build Coastguard Worker 
768*5e7646d2SAndroid Build Coastguard Worker   if (!a)
769*5e7646d2SAndroid Build Coastguard Worker     return;
770*5e7646d2SAndroid Build Coastguard Worker 
771*5e7646d2SAndroid Build Coastguard Worker  /*
772*5e7646d2SAndroid Build Coastguard Worker   * Format the message...
773*5e7646d2SAndroid Build Coastguard Worker   */
774*5e7646d2SAndroid Build Coastguard Worker 
775*5e7646d2SAndroid Build Coastguard Worker   va_start(ap, s);
776*5e7646d2SAndroid Build Coastguard Worker   vsnprintf(buffer, sizeof(buffer), s, ap);
777*5e7646d2SAndroid Build Coastguard Worker   va_end(ap);
778*5e7646d2SAndroid Build Coastguard Worker 
779*5e7646d2SAndroid Build Coastguard Worker  /*
780*5e7646d2SAndroid Build Coastguard Worker   * Add it to the array...
781*5e7646d2SAndroid Build Coastguard Worker   */
782*5e7646d2SAndroid Build Coastguard Worker 
783*5e7646d2SAndroid Build Coastguard Worker   cupsArrayAdd(a, buffer);
784*5e7646d2SAndroid Build Coastguard Worker }
785*5e7646d2SAndroid Build Coastguard Worker 
786*5e7646d2SAndroid Build Coastguard Worker 
787*5e7646d2SAndroid Build Coastguard Worker /*
788*5e7646d2SAndroid Build Coastguard Worker  * 'compare_uris()' - Compare two URIs...
789*5e7646d2SAndroid Build Coastguard Worker  */
790*5e7646d2SAndroid Build Coastguard Worker 
791*5e7646d2SAndroid Build Coastguard Worker static int                              /* O - Result of comparison */
compare_uris(const char * a,const char * b)792*5e7646d2SAndroid Build Coastguard Worker compare_uris(const char *a,             /* I - First URI */
793*5e7646d2SAndroid Build Coastguard Worker              const char *b)             /* I - Second URI */
794*5e7646d2SAndroid Build Coastguard Worker {
795*5e7646d2SAndroid Build Coastguard Worker   char  ascheme[32],                    /* Components of first URI */
796*5e7646d2SAndroid Build Coastguard Worker         auserpass[256],
797*5e7646d2SAndroid Build Coastguard Worker         ahost[256],
798*5e7646d2SAndroid Build Coastguard Worker         aresource[256];
799*5e7646d2SAndroid Build Coastguard Worker   int   aport;
800*5e7646d2SAndroid Build Coastguard Worker   char  bscheme[32],                    /* Components of second URI */
801*5e7646d2SAndroid Build Coastguard Worker         buserpass[256],
802*5e7646d2SAndroid Build Coastguard Worker         bhost[256],
803*5e7646d2SAndroid Build Coastguard Worker         bresource[256];
804*5e7646d2SAndroid Build Coastguard Worker   int   bport;
805*5e7646d2SAndroid Build Coastguard Worker   char  *ptr;                           /* Pointer into string */
806*5e7646d2SAndroid Build Coastguard Worker   int   result;                         /* Result of comparison */
807*5e7646d2SAndroid Build Coastguard Worker 
808*5e7646d2SAndroid Build Coastguard Worker 
809*5e7646d2SAndroid Build Coastguard Worker  /*
810*5e7646d2SAndroid Build Coastguard Worker   * Separate the URIs into their components...
811*5e7646d2SAndroid Build Coastguard Worker   */
812*5e7646d2SAndroid Build Coastguard Worker 
813*5e7646d2SAndroid Build Coastguard Worker   if (httpSeparateURI(HTTP_URI_CODING_ALL, a, ascheme, sizeof(ascheme), auserpass, sizeof(auserpass), ahost, sizeof(ahost), &aport, aresource, sizeof(aresource)) < HTTP_URI_STATUS_OK)
814*5e7646d2SAndroid Build Coastguard Worker     return (-1);
815*5e7646d2SAndroid Build Coastguard Worker 
816*5e7646d2SAndroid Build Coastguard Worker   if (httpSeparateURI(HTTP_URI_CODING_ALL, b, bscheme, sizeof(bscheme), buserpass, sizeof(buserpass), bhost, sizeof(bhost), &bport, bresource, sizeof(bresource)) < HTTP_URI_STATUS_OK)
817*5e7646d2SAndroid Build Coastguard Worker     return (-1);
818*5e7646d2SAndroid Build Coastguard Worker 
819*5e7646d2SAndroid Build Coastguard Worker  /*
820*5e7646d2SAndroid Build Coastguard Worker   * Strip trailing dots from the host components, if present...
821*5e7646d2SAndroid Build Coastguard Worker   */
822*5e7646d2SAndroid Build Coastguard Worker 
823*5e7646d2SAndroid Build Coastguard Worker   if ((ptr = ahost + strlen(ahost) - 1) > ahost && *ptr == '.')
824*5e7646d2SAndroid Build Coastguard Worker     *ptr = '\0';
825*5e7646d2SAndroid Build Coastguard Worker 
826*5e7646d2SAndroid Build Coastguard Worker   if ((ptr = bhost + strlen(bhost) - 1) > bhost && *ptr == '.')
827*5e7646d2SAndroid Build Coastguard Worker     *ptr = '\0';
828*5e7646d2SAndroid Build Coastguard Worker 
829*5e7646d2SAndroid Build Coastguard Worker  /*
830*5e7646d2SAndroid Build Coastguard Worker   * Compare each component...
831*5e7646d2SAndroid Build Coastguard Worker   */
832*5e7646d2SAndroid Build Coastguard Worker 
833*5e7646d2SAndroid Build Coastguard Worker   if ((result = _cups_strcasecmp(ascheme, bscheme)) != 0)
834*5e7646d2SAndroid Build Coastguard Worker     return (result);
835*5e7646d2SAndroid Build Coastguard Worker 
836*5e7646d2SAndroid Build Coastguard Worker   if ((result = strcmp(auserpass, buserpass)) != 0)
837*5e7646d2SAndroid Build Coastguard Worker     return (result);
838*5e7646d2SAndroid Build Coastguard Worker 
839*5e7646d2SAndroid Build Coastguard Worker   if ((result = _cups_strcasecmp(ahost, bhost)) != 0)
840*5e7646d2SAndroid Build Coastguard Worker     return (result);
841*5e7646d2SAndroid Build Coastguard Worker 
842*5e7646d2SAndroid Build Coastguard Worker   if (aport != bport)
843*5e7646d2SAndroid Build Coastguard Worker     return (aport - bport);
844*5e7646d2SAndroid Build Coastguard Worker 
845*5e7646d2SAndroid Build Coastguard Worker   if (!_cups_strcasecmp(ascheme, "mailto") || !_cups_strcasecmp(ascheme, "urn"))
846*5e7646d2SAndroid Build Coastguard Worker     return (_cups_strcasecmp(aresource, bresource));
847*5e7646d2SAndroid Build Coastguard Worker   else
848*5e7646d2SAndroid Build Coastguard Worker     return (strcmp(aresource, bresource));
849*5e7646d2SAndroid Build Coastguard Worker }
850*5e7646d2SAndroid Build Coastguard Worker 
851*5e7646d2SAndroid Build Coastguard Worker 
852*5e7646d2SAndroid Build Coastguard Worker /*
853*5e7646d2SAndroid Build Coastguard Worker  * 'copy_hex_string()' - Copy an octetString to a C string and encode as hex if
854*5e7646d2SAndroid Build Coastguard Worker  *                       needed.
855*5e7646d2SAndroid Build Coastguard Worker  */
856*5e7646d2SAndroid Build Coastguard Worker 
857*5e7646d2SAndroid Build Coastguard Worker static void
copy_hex_string(char * buffer,unsigned char * data,int datalen,size_t bufsize)858*5e7646d2SAndroid Build Coastguard Worker copy_hex_string(char          *buffer,	/* I - String buffer */
859*5e7646d2SAndroid Build Coastguard Worker 		unsigned char *data,	/* I - octetString data */
860*5e7646d2SAndroid Build Coastguard Worker 		int           datalen,	/* I - octetString length */
861*5e7646d2SAndroid Build Coastguard Worker 		size_t        bufsize)	/* I - Size of string buffer */
862*5e7646d2SAndroid Build Coastguard Worker {
863*5e7646d2SAndroid Build Coastguard Worker   char		*bufptr,		/* Pointer into string buffer */
864*5e7646d2SAndroid Build Coastguard Worker 		*bufend = buffer + bufsize - 2;
865*5e7646d2SAndroid Build Coastguard Worker 					/* End of string buffer */
866*5e7646d2SAndroid Build Coastguard Worker   unsigned char	*dataptr,		/* Pointer into octetString data */
867*5e7646d2SAndroid Build Coastguard Worker 		*dataend = data + datalen;
868*5e7646d2SAndroid Build Coastguard Worker 					/* End of octetString data */
869*5e7646d2SAndroid Build Coastguard Worker   static const char *hexdigits = "0123456789ABCDEF";
870*5e7646d2SAndroid Build Coastguard Worker 					/* Hex digits */
871*5e7646d2SAndroid Build Coastguard Worker 
872*5e7646d2SAndroid Build Coastguard Worker 
873*5e7646d2SAndroid Build Coastguard Worker  /*
874*5e7646d2SAndroid Build Coastguard Worker   * First see if there are any non-ASCII bytes in the octetString...
875*5e7646d2SAndroid Build Coastguard Worker   */
876*5e7646d2SAndroid Build Coastguard Worker 
877*5e7646d2SAndroid Build Coastguard Worker   for (dataptr = data; dataptr < dataend; dataptr ++)
878*5e7646d2SAndroid Build Coastguard Worker     if (*dataptr < 0x20 || *dataptr >= 0x7f)
879*5e7646d2SAndroid Build Coastguard Worker       break;
880*5e7646d2SAndroid Build Coastguard Worker 
881*5e7646d2SAndroid Build Coastguard Worker   if (dataptr < dataend)
882*5e7646d2SAndroid Build Coastguard Worker   {
883*5e7646d2SAndroid Build Coastguard Worker    /*
884*5e7646d2SAndroid Build Coastguard Worker     * Yes, encode as hex...
885*5e7646d2SAndroid Build Coastguard Worker     */
886*5e7646d2SAndroid Build Coastguard Worker 
887*5e7646d2SAndroid Build Coastguard Worker     *buffer = '<';
888*5e7646d2SAndroid Build Coastguard Worker 
889*5e7646d2SAndroid Build Coastguard Worker     for (bufptr = buffer + 1, dataptr = data; bufptr < bufend && dataptr < dataend; dataptr ++)
890*5e7646d2SAndroid Build Coastguard Worker     {
891*5e7646d2SAndroid Build Coastguard Worker       *bufptr++ = hexdigits[*dataptr >> 4];
892*5e7646d2SAndroid Build Coastguard Worker       *bufptr++ = hexdigits[*dataptr & 15];
893*5e7646d2SAndroid Build Coastguard Worker     }
894*5e7646d2SAndroid Build Coastguard Worker 
895*5e7646d2SAndroid Build Coastguard Worker     if (bufptr < bufend)
896*5e7646d2SAndroid Build Coastguard Worker       *bufptr++ = '>';
897*5e7646d2SAndroid Build Coastguard Worker 
898*5e7646d2SAndroid Build Coastguard Worker     *bufptr = '\0';
899*5e7646d2SAndroid Build Coastguard Worker   }
900*5e7646d2SAndroid Build Coastguard Worker   else
901*5e7646d2SAndroid Build Coastguard Worker   {
902*5e7646d2SAndroid Build Coastguard Worker    /*
903*5e7646d2SAndroid Build Coastguard Worker     * No, copy as a string...
904*5e7646d2SAndroid Build Coastguard Worker     */
905*5e7646d2SAndroid Build Coastguard Worker 
906*5e7646d2SAndroid Build Coastguard Worker     if ((size_t)datalen > bufsize)
907*5e7646d2SAndroid Build Coastguard Worker       datalen = (int)bufsize - 1;
908*5e7646d2SAndroid Build Coastguard Worker 
909*5e7646d2SAndroid Build Coastguard Worker     memcpy(buffer, data, (size_t)datalen);
910*5e7646d2SAndroid Build Coastguard Worker     buffer[datalen] = '\0';
911*5e7646d2SAndroid Build Coastguard Worker   }
912*5e7646d2SAndroid Build Coastguard Worker }
913*5e7646d2SAndroid Build Coastguard Worker 
914*5e7646d2SAndroid Build Coastguard Worker 
915*5e7646d2SAndroid Build Coastguard Worker /*
916*5e7646d2SAndroid Build Coastguard Worker  * 'do_monitor_printer_state()' - Do the MONITOR-PRINTER-STATE tests in the background.
917*5e7646d2SAndroid Build Coastguard Worker  */
918*5e7646d2SAndroid Build Coastguard Worker 
919*5e7646d2SAndroid Build Coastguard Worker static void *				// O - Thread exit status
do_monitor_printer_state(ipptool_test_t * data)920*5e7646d2SAndroid Build Coastguard Worker do_monitor_printer_state(
921*5e7646d2SAndroid Build Coastguard Worker     ipptool_test_t *data)		// I - Test data
922*5e7646d2SAndroid Build Coastguard Worker {
923*5e7646d2SAndroid Build Coastguard Worker   int		i, j;			// Looping vars
924*5e7646d2SAndroid Build Coastguard Worker   char		scheme[32],		// URI scheme
925*5e7646d2SAndroid Build Coastguard Worker 		userpass[32],		// URI username:password
926*5e7646d2SAndroid Build Coastguard Worker 		host[256],		// URI hostname/IP address
927*5e7646d2SAndroid Build Coastguard Worker 		resource[256];		// URI resource path
928*5e7646d2SAndroid Build Coastguard Worker   int		port;			// URI port number
929*5e7646d2SAndroid Build Coastguard Worker   http_encryption_t encryption;		// Encryption to use
930*5e7646d2SAndroid Build Coastguard Worker   http_t	*http;			// Connection to printer
931*5e7646d2SAndroid Build Coastguard Worker   ipp_t		*request,		// IPP request
932*5e7646d2SAndroid Build Coastguard Worker 		*response = NULL;	// IPP response
933*5e7646d2SAndroid Build Coastguard Worker   http_status_t	status;			// Request status
934*5e7646d2SAndroid Build Coastguard Worker   ipp_attribute_t *found;		// Found attribute
935*5e7646d2SAndroid Build Coastguard Worker   ipptool_expect_t *expect;		// Current EXPECT test
936*5e7646d2SAndroid Build Coastguard Worker   char		buffer[131072];		// Copy buffer
937*5e7646d2SAndroid Build Coastguard Worker   int		num_pattrs;		// Number of printer attributes
938*5e7646d2SAndroid Build Coastguard Worker   const char	*pattrs[100];		// Printer attributes we care about
939*5e7646d2SAndroid Build Coastguard Worker 
940*5e7646d2SAndroid Build Coastguard Worker 
941*5e7646d2SAndroid Build Coastguard Worker   // Connect to the printer...
942*5e7646d2SAndroid Build Coastguard Worker   if (httpSeparateURI(HTTP_URI_CODING_ALL, data->monitor_uri, scheme, sizeof(scheme), userpass, sizeof(userpass), host, sizeof(host), &port, resource, sizeof(resource)) < HTTP_URI_STATUS_OK)
943*5e7646d2SAndroid Build Coastguard Worker   {
944*5e7646d2SAndroid Build Coastguard Worker     print_fatal_error(data, "Bad printer URI \"%s\".", data->monitor_uri);
945*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
946*5e7646d2SAndroid Build Coastguard Worker   }
947*5e7646d2SAndroid Build Coastguard Worker 
948*5e7646d2SAndroid Build Coastguard Worker   if (!_cups_strcasecmp(scheme, "https") || !_cups_strcasecmp(scheme, "ipps") || port == 443)
949*5e7646d2SAndroid Build Coastguard Worker     encryption = HTTP_ENCRYPTION_ALWAYS;
950*5e7646d2SAndroid Build Coastguard Worker   else
951*5e7646d2SAndroid Build Coastguard Worker     encryption = data->encryption;
952*5e7646d2SAndroid Build Coastguard Worker 
953*5e7646d2SAndroid Build Coastguard Worker   if ((http = httpConnect2(host, port, NULL, data->family, encryption, 1, 30000, NULL)) == NULL)
954*5e7646d2SAndroid Build Coastguard Worker   {
955*5e7646d2SAndroid Build Coastguard Worker     print_fatal_error(data, "Unable to connect to \"%s\" on port %d - %s", host, port, cupsLastErrorString());
956*5e7646d2SAndroid Build Coastguard Worker     return (0);
957*5e7646d2SAndroid Build Coastguard Worker   }
958*5e7646d2SAndroid Build Coastguard Worker 
959*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_LIBZ
960*5e7646d2SAndroid Build Coastguard Worker   httpSetDefaultField(http, HTTP_FIELD_ACCEPT_ENCODING, "deflate, gzip, identity");
961*5e7646d2SAndroid Build Coastguard Worker #else
962*5e7646d2SAndroid Build Coastguard Worker   httpSetDefaultField(http, HTTP_FIELD_ACCEPT_ENCODING, "identity");
963*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_LIBZ */
964*5e7646d2SAndroid Build Coastguard Worker 
965*5e7646d2SAndroid Build Coastguard Worker   if (data->timeout > 0.0)
966*5e7646d2SAndroid Build Coastguard Worker     httpSetTimeout(http, data->timeout, timeout_cb, NULL);
967*5e7646d2SAndroid Build Coastguard Worker 
968*5e7646d2SAndroid Build Coastguard Worker   // Wait for the initial delay as needed...
969*5e7646d2SAndroid Build Coastguard Worker   if (data->monitor_delay)
970*5e7646d2SAndroid Build Coastguard Worker     usleep(data->monitor_delay);
971*5e7646d2SAndroid Build Coastguard Worker 
972*5e7646d2SAndroid Build Coastguard Worker   // Create a query request that we'll reuse...
973*5e7646d2SAndroid Build Coastguard Worker   request = ippNewRequest(IPP_OP_GET_PRINTER_ATTRIBUTES);
974*5e7646d2SAndroid Build Coastguard Worker   ippSetRequestId(request, data->request_id * 100 - 1);
975*5e7646d2SAndroid Build Coastguard Worker   ippSetVersion(request, data->version / 10, data->version % 10);
976*5e7646d2SAndroid Build Coastguard Worker   ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, data->monitor_uri);
977*5e7646d2SAndroid Build Coastguard Worker   ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsUser());
978*5e7646d2SAndroid Build Coastguard Worker 
979*5e7646d2SAndroid Build Coastguard Worker   for (i = data->num_monitor_expects, expect = data->monitor_expects, num_pattrs = 0; i > 0; i --, expect ++)
980*5e7646d2SAndroid Build Coastguard Worker   {
981*5e7646d2SAndroid Build Coastguard Worker     // Add EXPECT attribute names...
982*5e7646d2SAndroid Build Coastguard Worker     for (j = 0; j < num_pattrs; j ++)
983*5e7646d2SAndroid Build Coastguard Worker     {
984*5e7646d2SAndroid Build Coastguard Worker       if (!strcmp(expect->name, pattrs[j]))
985*5e7646d2SAndroid Build Coastguard Worker         break;
986*5e7646d2SAndroid Build Coastguard Worker     }
987*5e7646d2SAndroid Build Coastguard Worker 
988*5e7646d2SAndroid Build Coastguard Worker     if (j >= num_pattrs && num_pattrs < (int)(sizeof(pattrs) / sizeof(pattrs[0])))
989*5e7646d2SAndroid Build Coastguard Worker       pattrs[num_pattrs ++] = expect->name;
990*5e7646d2SAndroid Build Coastguard Worker   }
991*5e7646d2SAndroid Build Coastguard Worker 
992*5e7646d2SAndroid Build Coastguard Worker   if (num_pattrs > 0)
993*5e7646d2SAndroid Build Coastguard Worker     ippAddStrings(request, IPP_TAG_OPERATION, IPP_CONST_TAG(IPP_TAG_KEYWORD), "requested-attributes", num_pattrs, NULL, pattrs);
994*5e7646d2SAndroid Build Coastguard Worker 
995*5e7646d2SAndroid Build Coastguard Worker   // Loop until we need to stop...
996*5e7646d2SAndroid Build Coastguard Worker   while (!data->monitor_done && !Cancel)
997*5e7646d2SAndroid Build Coastguard Worker   {
998*5e7646d2SAndroid Build Coastguard Worker     // Poll the printer state...
999*5e7646d2SAndroid Build Coastguard Worker     ippSetRequestId(request, ippGetRequestId(request) + 1);
1000*5e7646d2SAndroid Build Coastguard Worker 
1001*5e7646d2SAndroid Build Coastguard Worker     if ((status = cupsSendRequest(http, request, resource, ippLength(request))) != HTTP_STATUS_ERROR)
1002*5e7646d2SAndroid Build Coastguard Worker     {
1003*5e7646d2SAndroid Build Coastguard Worker       response = cupsGetResponse(http, resource);
1004*5e7646d2SAndroid Build Coastguard Worker       status   = httpGetStatus(http);
1005*5e7646d2SAndroid Build Coastguard Worker     }
1006*5e7646d2SAndroid Build Coastguard Worker 
1007*5e7646d2SAndroid Build Coastguard Worker     if (!data->monitor_done && !Cancel && status == HTTP_STATUS_ERROR && httpError(data->http) != EINVAL &&
1008*5e7646d2SAndroid Build Coastguard Worker #ifdef _WIN32
1009*5e7646d2SAndroid Build Coastguard Worker 	httpError(data->http) != WSAETIMEDOUT)
1010*5e7646d2SAndroid Build Coastguard Worker #else
1011*5e7646d2SAndroid Build Coastguard Worker 	httpError(data->http) != ETIMEDOUT)
1012*5e7646d2SAndroid Build Coastguard Worker #endif // _WIN32
1013*5e7646d2SAndroid Build Coastguard Worker     {
1014*5e7646d2SAndroid Build Coastguard Worker       if (httpReconnect2(http, 30000, NULL))
1015*5e7646d2SAndroid Build Coastguard Worker 	break;
1016*5e7646d2SAndroid Build Coastguard Worker     }
1017*5e7646d2SAndroid Build Coastguard Worker     else if (status == HTTP_STATUS_ERROR || status == HTTP_STATUS_CUPS_AUTHORIZATION_CANCELED)
1018*5e7646d2SAndroid Build Coastguard Worker     {
1019*5e7646d2SAndroid Build Coastguard Worker       break;
1020*5e7646d2SAndroid Build Coastguard Worker     }
1021*5e7646d2SAndroid Build Coastguard Worker     else if (status != HTTP_STATUS_OK)
1022*5e7646d2SAndroid Build Coastguard Worker     {
1023*5e7646d2SAndroid Build Coastguard Worker       httpFlush(http);
1024*5e7646d2SAndroid Build Coastguard Worker 
1025*5e7646d2SAndroid Build Coastguard Worker       if (status == HTTP_STATUS_UNAUTHORIZED)
1026*5e7646d2SAndroid Build Coastguard Worker 	continue;
1027*5e7646d2SAndroid Build Coastguard Worker 
1028*5e7646d2SAndroid Build Coastguard Worker       break;
1029*5e7646d2SAndroid Build Coastguard Worker     }
1030*5e7646d2SAndroid Build Coastguard Worker 
1031*5e7646d2SAndroid Build Coastguard Worker     for (i = data->num_monitor_expects, expect = data->monitor_expects; i > 0; i --, expect ++)
1032*5e7646d2SAndroid Build Coastguard Worker     {
1033*5e7646d2SAndroid Build Coastguard Worker       if (expect->if_defined && !_ippVarsGet(data->vars, expect->if_defined))
1034*5e7646d2SAndroid Build Coastguard Worker 	continue;
1035*5e7646d2SAndroid Build Coastguard Worker 
1036*5e7646d2SAndroid Build Coastguard Worker       if (expect->if_not_defined && _ippVarsGet(data->vars, expect->if_not_defined))
1037*5e7646d2SAndroid Build Coastguard Worker 	continue;
1038*5e7646d2SAndroid Build Coastguard Worker 
1039*5e7646d2SAndroid Build Coastguard Worker       found = ippFindAttribute(response, expect->name, IPP_TAG_ZERO);
1040*5e7646d2SAndroid Build Coastguard Worker 
1041*5e7646d2SAndroid Build Coastguard Worker       if ((found && expect->not_expect) ||
1042*5e7646d2SAndroid Build Coastguard Worker 	  (!found && !(expect->not_expect || expect->optional)) ||
1043*5e7646d2SAndroid Build Coastguard Worker 	  (found && !expect_matches(expect, found)) ||
1044*5e7646d2SAndroid Build Coastguard Worker 	  (expect->in_group && ippGetGroupTag(found) != expect->in_group) ||
1045*5e7646d2SAndroid Build Coastguard Worker 	  (expect->with_distinct && !with_distinct_values(NULL, found)))
1046*5e7646d2SAndroid Build Coastguard Worker       {
1047*5e7646d2SAndroid Build Coastguard Worker 	if (expect->define_no_match)
1048*5e7646d2SAndroid Build Coastguard Worker 	{
1049*5e7646d2SAndroid Build Coastguard Worker 	  _ippVarsSet(data->vars, expect->define_no_match, "1");
1050*5e7646d2SAndroid Build Coastguard Worker 	  data->monitor_done = 1;
1051*5e7646d2SAndroid Build Coastguard Worker 	}
1052*5e7646d2SAndroid Build Coastguard Worker 	break;
1053*5e7646d2SAndroid Build Coastguard Worker       }
1054*5e7646d2SAndroid Build Coastguard Worker 
1055*5e7646d2SAndroid Build Coastguard Worker       if (found)
1056*5e7646d2SAndroid Build Coastguard Worker 	ippAttributeString(found, buffer, sizeof(buffer));
1057*5e7646d2SAndroid Build Coastguard Worker 
1058*5e7646d2SAndroid Build Coastguard Worker       if (found && !with_value(data, NULL, expect->with_value, expect->with_flags, found, buffer, sizeof(buffer)))
1059*5e7646d2SAndroid Build Coastguard Worker       {
1060*5e7646d2SAndroid Build Coastguard Worker 	if (expect->define_no_match)
1061*5e7646d2SAndroid Build Coastguard Worker 	{
1062*5e7646d2SAndroid Build Coastguard Worker 	  _ippVarsSet(data->vars, expect->define_no_match, "1");
1063*5e7646d2SAndroid Build Coastguard Worker 	  data->monitor_done = 1;
1064*5e7646d2SAndroid Build Coastguard Worker 	}
1065*5e7646d2SAndroid Build Coastguard Worker 	break;
1066*5e7646d2SAndroid Build Coastguard Worker       }
1067*5e7646d2SAndroid Build Coastguard Worker 
1068*5e7646d2SAndroid Build Coastguard Worker       if (found && expect->count > 0 && ippGetCount(found) != expect->count)
1069*5e7646d2SAndroid Build Coastguard Worker       {
1070*5e7646d2SAndroid Build Coastguard Worker 	if (expect->define_no_match)
1071*5e7646d2SAndroid Build Coastguard Worker 	{
1072*5e7646d2SAndroid Build Coastguard Worker 	  _ippVarsSet(data->vars, expect->define_no_match, "1");
1073*5e7646d2SAndroid Build Coastguard Worker 	  data->monitor_done = 1;
1074*5e7646d2SAndroid Build Coastguard Worker 	}
1075*5e7646d2SAndroid Build Coastguard Worker 	break;
1076*5e7646d2SAndroid Build Coastguard Worker       }
1077*5e7646d2SAndroid Build Coastguard Worker 
1078*5e7646d2SAndroid Build Coastguard Worker       if (found && expect->display_match && (data->output == IPPTOOL_OUTPUT_TEST || (data->output == IPPTOOL_OUTPUT_PLIST && data->outfile != cupsFileStdout())))
1079*5e7646d2SAndroid Build Coastguard Worker 	cupsFilePrintf(cupsFileStdout(), "CONT]\n\n%s\n\n    %-68.68s [", expect->display_match, data->name);
1080*5e7646d2SAndroid Build Coastguard Worker 
1081*5e7646d2SAndroid Build Coastguard Worker       if (found && expect->define_match)
1082*5e7646d2SAndroid Build Coastguard Worker       {
1083*5e7646d2SAndroid Build Coastguard Worker 	_ippVarsSet(data->vars, expect->define_match, "1");
1084*5e7646d2SAndroid Build Coastguard Worker 	data->monitor_done = 1;
1085*5e7646d2SAndroid Build Coastguard Worker       }
1086*5e7646d2SAndroid Build Coastguard Worker 
1087*5e7646d2SAndroid Build Coastguard Worker       if (found && expect->define_value)
1088*5e7646d2SAndroid Build Coastguard Worker       {
1089*5e7646d2SAndroid Build Coastguard Worker 	if (!expect->with_value)
1090*5e7646d2SAndroid Build Coastguard Worker 	{
1091*5e7646d2SAndroid Build Coastguard Worker 	  int last = ippGetCount(found) - 1;
1092*5e7646d2SAndroid Build Coastguard Worker 					// Last element in attribute
1093*5e7646d2SAndroid Build Coastguard Worker 
1094*5e7646d2SAndroid Build Coastguard Worker 	  switch (ippGetValueTag(found))
1095*5e7646d2SAndroid Build Coastguard Worker 	  {
1096*5e7646d2SAndroid Build Coastguard Worker 	    case IPP_TAG_ENUM :
1097*5e7646d2SAndroid Build Coastguard Worker 	    case IPP_TAG_INTEGER :
1098*5e7646d2SAndroid Build Coastguard Worker 		snprintf(buffer, sizeof(buffer), "%d", ippGetInteger(found, last));
1099*5e7646d2SAndroid Build Coastguard Worker 		break;
1100*5e7646d2SAndroid Build Coastguard Worker 
1101*5e7646d2SAndroid Build Coastguard Worker 	    case IPP_TAG_BOOLEAN :
1102*5e7646d2SAndroid Build Coastguard Worker 		if (ippGetBoolean(found, last))
1103*5e7646d2SAndroid Build Coastguard Worker 		  strlcpy(buffer, "true", sizeof(buffer));
1104*5e7646d2SAndroid Build Coastguard Worker 		else
1105*5e7646d2SAndroid Build Coastguard Worker 		  strlcpy(buffer, "false", sizeof(buffer));
1106*5e7646d2SAndroid Build Coastguard Worker 		break;
1107*5e7646d2SAndroid Build Coastguard Worker 
1108*5e7646d2SAndroid Build Coastguard Worker 	    case IPP_TAG_CHARSET :
1109*5e7646d2SAndroid Build Coastguard Worker 	    case IPP_TAG_KEYWORD :
1110*5e7646d2SAndroid Build Coastguard Worker 	    case IPP_TAG_LANGUAGE :
1111*5e7646d2SAndroid Build Coastguard Worker 	    case IPP_TAG_MIMETYPE :
1112*5e7646d2SAndroid Build Coastguard Worker 	    case IPP_TAG_NAME :
1113*5e7646d2SAndroid Build Coastguard Worker 	    case IPP_TAG_NAMELANG :
1114*5e7646d2SAndroid Build Coastguard Worker 	    case IPP_TAG_TEXT :
1115*5e7646d2SAndroid Build Coastguard Worker 	    case IPP_TAG_TEXTLANG :
1116*5e7646d2SAndroid Build Coastguard Worker 	    case IPP_TAG_URI :
1117*5e7646d2SAndroid Build Coastguard Worker 	    case IPP_TAG_URISCHEME :
1118*5e7646d2SAndroid Build Coastguard Worker 		strlcpy(buffer, ippGetString(found, last, NULL), sizeof(buffer));
1119*5e7646d2SAndroid Build Coastguard Worker 		break;
1120*5e7646d2SAndroid Build Coastguard Worker 
1121*5e7646d2SAndroid Build Coastguard Worker 	    default :
1122*5e7646d2SAndroid Build Coastguard Worker 		ippAttributeString(found, buffer, sizeof(buffer));
1123*5e7646d2SAndroid Build Coastguard Worker 		break;
1124*5e7646d2SAndroid Build Coastguard Worker 	  }
1125*5e7646d2SAndroid Build Coastguard Worker 	}
1126*5e7646d2SAndroid Build Coastguard Worker 
1127*5e7646d2SAndroid Build Coastguard Worker 	_ippVarsSet(data->vars, expect->define_value, buffer);
1128*5e7646d2SAndroid Build Coastguard Worker 	data->monitor_done = 1;
1129*5e7646d2SAndroid Build Coastguard Worker       }
1130*5e7646d2SAndroid Build Coastguard Worker     }
1131*5e7646d2SAndroid Build Coastguard Worker 
1132*5e7646d2SAndroid Build Coastguard Worker     if (i == 0)
1133*5e7646d2SAndroid Build Coastguard Worker       data->monitor_done = 1;		// All tests passed
1134*5e7646d2SAndroid Build Coastguard Worker 
1135*5e7646d2SAndroid Build Coastguard Worker     ippDelete(response);
1136*5e7646d2SAndroid Build Coastguard Worker     response = NULL;
1137*5e7646d2SAndroid Build Coastguard Worker 
1138*5e7646d2SAndroid Build Coastguard Worker     // Sleep between requests...
1139*5e7646d2SAndroid Build Coastguard Worker     if (data->monitor_done || Cancel)
1140*5e7646d2SAndroid Build Coastguard Worker       break;
1141*5e7646d2SAndroid Build Coastguard Worker 
1142*5e7646d2SAndroid Build Coastguard Worker     usleep(data->monitor_interval);
1143*5e7646d2SAndroid Build Coastguard Worker   }
1144*5e7646d2SAndroid Build Coastguard Worker 
1145*5e7646d2SAndroid Build Coastguard Worker   // Close the connection to the printer and return...
1146*5e7646d2SAndroid Build Coastguard Worker   httpClose(http);
1147*5e7646d2SAndroid Build Coastguard Worker   ippDelete(request);
1148*5e7646d2SAndroid Build Coastguard Worker   ippDelete(response);
1149*5e7646d2SAndroid Build Coastguard Worker 
1150*5e7646d2SAndroid Build Coastguard Worker   return (NULL);
1151*5e7646d2SAndroid Build Coastguard Worker }
1152*5e7646d2SAndroid Build Coastguard Worker 
1153*5e7646d2SAndroid Build Coastguard Worker 
1154*5e7646d2SAndroid Build Coastguard Worker /*
1155*5e7646d2SAndroid Build Coastguard Worker  * 'do_test()' - Do a single test from the test file.
1156*5e7646d2SAndroid Build Coastguard Worker  */
1157*5e7646d2SAndroid Build Coastguard Worker 
1158*5e7646d2SAndroid Build Coastguard Worker static int				/* O - 1 on success, 0 on failure */
do_test(_ipp_file_t * f,ipptool_test_t * data)1159*5e7646d2SAndroid Build Coastguard Worker do_test(_ipp_file_t    *f,		/* I - IPP data file */
1160*5e7646d2SAndroid Build Coastguard Worker         ipptool_test_t *data)		/* I - Test data */
1161*5e7646d2SAndroid Build Coastguard Worker 
1162*5e7646d2SAndroid Build Coastguard Worker {
1163*5e7646d2SAndroid Build Coastguard Worker   int	        i,			/* Looping var */
1164*5e7646d2SAndroid Build Coastguard Worker 		status_ok,		/* Did we get a matching status? */
1165*5e7646d2SAndroid Build Coastguard Worker 		repeat_count = 0,	/* Repeat count */
1166*5e7646d2SAndroid Build Coastguard Worker 		repeat_test;		/* Repeat the test? */
1167*5e7646d2SAndroid Build Coastguard Worker   ipptool_expect_t *expect;		/* Current expected attribute */
1168*5e7646d2SAndroid Build Coastguard Worker   ipp_t		*request,		/* IPP request */
1169*5e7646d2SAndroid Build Coastguard Worker 		*response;		/* IPP response */
1170*5e7646d2SAndroid Build Coastguard Worker   size_t	length;			/* Length of IPP request */
1171*5e7646d2SAndroid Build Coastguard Worker   http_status_t	status;			/* HTTP status */
1172*5e7646d2SAndroid Build Coastguard Worker   cups_array_t	*a;			/* Duplicate attribute array */
1173*5e7646d2SAndroid Build Coastguard Worker   ipp_tag_t	group;			/* Current group */
1174*5e7646d2SAndroid Build Coastguard Worker   ipp_attribute_t *attrptr,		/* Attribute pointer */
1175*5e7646d2SAndroid Build Coastguard Worker 		*found;			/* Found attribute */
1176*5e7646d2SAndroid Build Coastguard Worker   char		temp[1024];		/* Temporary string */
1177*5e7646d2SAndroid Build Coastguard Worker   cups_file_t	*reqfile;		/* File to send */
1178*5e7646d2SAndroid Build Coastguard Worker   ssize_t	bytes;			/* Bytes read/written */
1179*5e7646d2SAndroid Build Coastguard Worker   char		buffer[131072];		/* Copy buffer */
1180*5e7646d2SAndroid Build Coastguard Worker   size_t	widths[200];		/* Width of columns */
1181*5e7646d2SAndroid Build Coastguard Worker   const char	*error;			/* Current error */
1182*5e7646d2SAndroid Build Coastguard Worker 
1183*5e7646d2SAndroid Build Coastguard Worker 
1184*5e7646d2SAndroid Build Coastguard Worker   if (Cancel)
1185*5e7646d2SAndroid Build Coastguard Worker     return (0);
1186*5e7646d2SAndroid Build Coastguard Worker 
1187*5e7646d2SAndroid Build Coastguard Worker  /*
1188*5e7646d2SAndroid Build Coastguard Worker   * Show any PAUSE message, as needed...
1189*5e7646d2SAndroid Build Coastguard Worker   */
1190*5e7646d2SAndroid Build Coastguard Worker 
1191*5e7646d2SAndroid Build Coastguard Worker   if (data->pause[0])
1192*5e7646d2SAndroid Build Coastguard Worker   {
1193*5e7646d2SAndroid Build Coastguard Worker     if (!data->skip_test && !data->pass_test)
1194*5e7646d2SAndroid Build Coastguard Worker       pause_message(data->pause);
1195*5e7646d2SAndroid Build Coastguard Worker 
1196*5e7646d2SAndroid Build Coastguard Worker     data->pause[0] = '\0';
1197*5e7646d2SAndroid Build Coastguard Worker   }
1198*5e7646d2SAndroid Build Coastguard Worker 
1199*5e7646d2SAndroid Build Coastguard Worker  /*
1200*5e7646d2SAndroid Build Coastguard Worker   * Start the background thread as needed...
1201*5e7646d2SAndroid Build Coastguard Worker   */
1202*5e7646d2SAndroid Build Coastguard Worker 
1203*5e7646d2SAndroid Build Coastguard Worker   if (data->monitor_uri)
1204*5e7646d2SAndroid Build Coastguard Worker   {
1205*5e7646d2SAndroid Build Coastguard Worker     data->monitor_done   = 0;
1206*5e7646d2SAndroid Build Coastguard Worker     data->monitor_thread = _cupsThreadCreate((_cups_thread_func_t)do_monitor_printer_state, data);
1207*5e7646d2SAndroid Build Coastguard Worker   }
1208*5e7646d2SAndroid Build Coastguard Worker 
1209*5e7646d2SAndroid Build Coastguard Worker  /*
1210*5e7646d2SAndroid Build Coastguard Worker   * Take over control of the attributes in the request...
1211*5e7646d2SAndroid Build Coastguard Worker   */
1212*5e7646d2SAndroid Build Coastguard Worker 
1213*5e7646d2SAndroid Build Coastguard Worker   request  = f->attrs;
1214*5e7646d2SAndroid Build Coastguard Worker   f->attrs = NULL;
1215*5e7646d2SAndroid Build Coastguard Worker 
1216*5e7646d2SAndroid Build Coastguard Worker  /*
1217*5e7646d2SAndroid Build Coastguard Worker   * Submit the IPP request...
1218*5e7646d2SAndroid Build Coastguard Worker   */
1219*5e7646d2SAndroid Build Coastguard Worker 
1220*5e7646d2SAndroid Build Coastguard Worker   data->test_count ++;
1221*5e7646d2SAndroid Build Coastguard Worker 
1222*5e7646d2SAndroid Build Coastguard Worker   ippSetVersion(request, data->version / 10, data->version % 10);
1223*5e7646d2SAndroid Build Coastguard Worker   ippSetRequestId(request, data->request_id);
1224*5e7646d2SAndroid Build Coastguard Worker 
1225*5e7646d2SAndroid Build Coastguard Worker   if (data->output == IPPTOOL_OUTPUT_PLIST)
1226*5e7646d2SAndroid Build Coastguard Worker   {
1227*5e7646d2SAndroid Build Coastguard Worker     cupsFilePuts(data->outfile, "<dict>\n");
1228*5e7646d2SAndroid Build Coastguard Worker     cupsFilePuts(data->outfile, "<key>Name</key>\n");
1229*5e7646d2SAndroid Build Coastguard Worker     print_xml_string(data->outfile, "string", data->name);
1230*5e7646d2SAndroid Build Coastguard Worker     if (data->file_id[0])
1231*5e7646d2SAndroid Build Coastguard Worker     {
1232*5e7646d2SAndroid Build Coastguard Worker       cupsFilePuts(data->outfile, "<key>FileId</key>\n");
1233*5e7646d2SAndroid Build Coastguard Worker       print_xml_string(data->outfile, "string", data->file_id);
1234*5e7646d2SAndroid Build Coastguard Worker     }
1235*5e7646d2SAndroid Build Coastguard Worker     if (data->test_id[0])
1236*5e7646d2SAndroid Build Coastguard Worker     {
1237*5e7646d2SAndroid Build Coastguard Worker       cupsFilePuts(data->outfile, "<key>TestId</key>\n");
1238*5e7646d2SAndroid Build Coastguard Worker       print_xml_string(data->outfile, "string", data->test_id);
1239*5e7646d2SAndroid Build Coastguard Worker     }
1240*5e7646d2SAndroid Build Coastguard Worker     cupsFilePuts(data->outfile, "<key>Version</key>\n");
1241*5e7646d2SAndroid Build Coastguard Worker     cupsFilePrintf(data->outfile, "<string>%d.%d</string>\n", data->version / 10, data->version % 10);
1242*5e7646d2SAndroid Build Coastguard Worker     cupsFilePuts(data->outfile, "<key>Operation</key>\n");
1243*5e7646d2SAndroid Build Coastguard Worker     print_xml_string(data->outfile, "string", ippOpString(ippGetOperation(request)));
1244*5e7646d2SAndroid Build Coastguard Worker     cupsFilePuts(data->outfile, "<key>RequestId</key>\n");
1245*5e7646d2SAndroid Build Coastguard Worker     cupsFilePrintf(data->outfile, "<integer>%d</integer>\n", data->request_id);
1246*5e7646d2SAndroid Build Coastguard Worker     cupsFilePuts(data->outfile, "<key>RequestAttributes</key>\n");
1247*5e7646d2SAndroid Build Coastguard Worker     cupsFilePuts(data->outfile, "<array>\n");
1248*5e7646d2SAndroid Build Coastguard Worker     if (ippFirstAttribute(request))
1249*5e7646d2SAndroid Build Coastguard Worker     {
1250*5e7646d2SAndroid Build Coastguard Worker       cupsFilePuts(data->outfile, "<dict>\n");
1251*5e7646d2SAndroid Build Coastguard Worker       for (attrptr = ippFirstAttribute(request), group = ippGetGroupTag(attrptr); attrptr; attrptr = ippNextAttribute(request))
1252*5e7646d2SAndroid Build Coastguard Worker 	print_attr(data->outfile, data->output, attrptr, &group);
1253*5e7646d2SAndroid Build Coastguard Worker       cupsFilePuts(data->outfile, "</dict>\n");
1254*5e7646d2SAndroid Build Coastguard Worker     }
1255*5e7646d2SAndroid Build Coastguard Worker     cupsFilePuts(data->outfile, "</array>\n");
1256*5e7646d2SAndroid Build Coastguard Worker   }
1257*5e7646d2SAndroid Build Coastguard Worker 
1258*5e7646d2SAndroid Build Coastguard Worker   if (data->output == IPPTOOL_OUTPUT_TEST || (data->output == IPPTOOL_OUTPUT_PLIST && data->outfile != cupsFileStdout()))
1259*5e7646d2SAndroid Build Coastguard Worker   {
1260*5e7646d2SAndroid Build Coastguard Worker     if (data->verbosity)
1261*5e7646d2SAndroid Build Coastguard Worker     {
1262*5e7646d2SAndroid Build Coastguard Worker       cupsFilePrintf(cupsFileStdout(), "    %s:\n", ippOpString(ippGetOperation(request)));
1263*5e7646d2SAndroid Build Coastguard Worker 
1264*5e7646d2SAndroid Build Coastguard Worker       for (attrptr = ippFirstAttribute(request); attrptr; attrptr = ippNextAttribute(request))
1265*5e7646d2SAndroid Build Coastguard Worker 	print_attr(cupsFileStdout(), IPPTOOL_OUTPUT_TEST, attrptr, NULL);
1266*5e7646d2SAndroid Build Coastguard Worker     }
1267*5e7646d2SAndroid Build Coastguard Worker 
1268*5e7646d2SAndroid Build Coastguard Worker     cupsFilePrintf(cupsFileStdout(), "    %-68.68s [", data->name);
1269*5e7646d2SAndroid Build Coastguard Worker   }
1270*5e7646d2SAndroid Build Coastguard Worker 
1271*5e7646d2SAndroid Build Coastguard Worker   if ((data->skip_previous && !data->prev_pass) || data->skip_test || data->pass_test)
1272*5e7646d2SAndroid Build Coastguard Worker   {
1273*5e7646d2SAndroid Build Coastguard Worker     if (!data->pass_test)
1274*5e7646d2SAndroid Build Coastguard Worker       data->skip_count ++;
1275*5e7646d2SAndroid Build Coastguard Worker 
1276*5e7646d2SAndroid Build Coastguard Worker     ippDelete(request);
1277*5e7646d2SAndroid Build Coastguard Worker     request  = NULL;
1278*5e7646d2SAndroid Build Coastguard Worker     response = NULL;
1279*5e7646d2SAndroid Build Coastguard Worker 
1280*5e7646d2SAndroid Build Coastguard Worker     if (data->output == IPPTOOL_OUTPUT_PLIST)
1281*5e7646d2SAndroid Build Coastguard Worker     {
1282*5e7646d2SAndroid Build Coastguard Worker       cupsFilePuts(data->outfile, "<key>Successful</key>\n");
1283*5e7646d2SAndroid Build Coastguard Worker       cupsFilePuts(data->outfile, "<true />\n");
1284*5e7646d2SAndroid Build Coastguard Worker       cupsFilePuts(data->outfile, "<key>Skipped</key>\n");
1285*5e7646d2SAndroid Build Coastguard Worker       if (data->pass_test)
1286*5e7646d2SAndroid Build Coastguard Worker 	cupsFilePuts(data->outfile, "<false />\n");
1287*5e7646d2SAndroid Build Coastguard Worker       else
1288*5e7646d2SAndroid Build Coastguard Worker 	cupsFilePuts(data->outfile, "<true />\n");
1289*5e7646d2SAndroid Build Coastguard Worker       cupsFilePuts(data->outfile, "<key>StatusCode</key>\n");
1290*5e7646d2SAndroid Build Coastguard Worker       if (data->pass_test)
1291*5e7646d2SAndroid Build Coastguard Worker 	print_xml_string(data->outfile, "string", "pass");
1292*5e7646d2SAndroid Build Coastguard Worker       else
1293*5e7646d2SAndroid Build Coastguard Worker 	print_xml_string(data->outfile, "string", "skip");
1294*5e7646d2SAndroid Build Coastguard Worker       cupsFilePuts(data->outfile, "<key>ResponseAttributes</key>\n");
1295*5e7646d2SAndroid Build Coastguard Worker       cupsFilePuts(data->outfile, "<dict />\n");
1296*5e7646d2SAndroid Build Coastguard Worker     }
1297*5e7646d2SAndroid Build Coastguard Worker 
1298*5e7646d2SAndroid Build Coastguard Worker     if (data->output == IPPTOOL_OUTPUT_TEST || (data->output == IPPTOOL_OUTPUT_PLIST && data->outfile != cupsFileStdout()))
1299*5e7646d2SAndroid Build Coastguard Worker     {
1300*5e7646d2SAndroid Build Coastguard Worker       if (data->pass_test)
1301*5e7646d2SAndroid Build Coastguard Worker 	cupsFilePuts(cupsFileStdout(), "PASS]\n");
1302*5e7646d2SAndroid Build Coastguard Worker       else
1303*5e7646d2SAndroid Build Coastguard Worker 	cupsFilePuts(cupsFileStdout(), "SKIP]\n");
1304*5e7646d2SAndroid Build Coastguard Worker     }
1305*5e7646d2SAndroid Build Coastguard Worker 
1306*5e7646d2SAndroid Build Coastguard Worker     goto skip_error;
1307*5e7646d2SAndroid Build Coastguard Worker   }
1308*5e7646d2SAndroid Build Coastguard Worker 
1309*5e7646d2SAndroid Build Coastguard Worker   data->vars->password_tries = 0;
1310*5e7646d2SAndroid Build Coastguard Worker 
1311*5e7646d2SAndroid Build Coastguard Worker   do
1312*5e7646d2SAndroid Build Coastguard Worker   {
1313*5e7646d2SAndroid Build Coastguard Worker     if (data->delay > 0)
1314*5e7646d2SAndroid Build Coastguard Worker       usleep(data->delay);
1315*5e7646d2SAndroid Build Coastguard Worker 
1316*5e7646d2SAndroid Build Coastguard Worker     data->delay = data->repeat_interval;
1317*5e7646d2SAndroid Build Coastguard Worker     repeat_count ++;
1318*5e7646d2SAndroid Build Coastguard Worker 
1319*5e7646d2SAndroid Build Coastguard Worker     status = HTTP_STATUS_OK;
1320*5e7646d2SAndroid Build Coastguard Worker 
1321*5e7646d2SAndroid Build Coastguard Worker     if (data->transfer == IPPTOOL_TRANSFER_CHUNKED || (data->transfer == IPPTOOL_TRANSFER_AUTO && data->file[0]))
1322*5e7646d2SAndroid Build Coastguard Worker     {
1323*5e7646d2SAndroid Build Coastguard Worker      /*
1324*5e7646d2SAndroid Build Coastguard Worker       * Send request using chunking - a 0 length means "chunk".
1325*5e7646d2SAndroid Build Coastguard Worker       */
1326*5e7646d2SAndroid Build Coastguard Worker 
1327*5e7646d2SAndroid Build Coastguard Worker       length = 0;
1328*5e7646d2SAndroid Build Coastguard Worker     }
1329*5e7646d2SAndroid Build Coastguard Worker     else
1330*5e7646d2SAndroid Build Coastguard Worker     {
1331*5e7646d2SAndroid Build Coastguard Worker      /*
1332*5e7646d2SAndroid Build Coastguard Worker       * Send request using content length...
1333*5e7646d2SAndroid Build Coastguard Worker       */
1334*5e7646d2SAndroid Build Coastguard Worker 
1335*5e7646d2SAndroid Build Coastguard Worker       length = ippLength(request);
1336*5e7646d2SAndroid Build Coastguard Worker 
1337*5e7646d2SAndroid Build Coastguard Worker       if (data->file[0] && (reqfile = cupsFileOpen(data->file, "r")) != NULL)
1338*5e7646d2SAndroid Build Coastguard Worker       {
1339*5e7646d2SAndroid Build Coastguard Worker        /*
1340*5e7646d2SAndroid Build Coastguard Worker 	* Read the file to get the uncompressed file size...
1341*5e7646d2SAndroid Build Coastguard Worker 	*/
1342*5e7646d2SAndroid Build Coastguard Worker 
1343*5e7646d2SAndroid Build Coastguard Worker 	while ((bytes = cupsFileRead(reqfile, buffer, sizeof(buffer))) > 0)
1344*5e7646d2SAndroid Build Coastguard Worker 	  length += (size_t)bytes;
1345*5e7646d2SAndroid Build Coastguard Worker 
1346*5e7646d2SAndroid Build Coastguard Worker 	cupsFileClose(reqfile);
1347*5e7646d2SAndroid Build Coastguard Worker       }
1348*5e7646d2SAndroid Build Coastguard Worker     }
1349*5e7646d2SAndroid Build Coastguard Worker 
1350*5e7646d2SAndroid Build Coastguard Worker    /*
1351*5e7646d2SAndroid Build Coastguard Worker     * Send the request...
1352*5e7646d2SAndroid Build Coastguard Worker     */
1353*5e7646d2SAndroid Build Coastguard Worker 
1354*5e7646d2SAndroid Build Coastguard Worker     data->prev_pass = 1;
1355*5e7646d2SAndroid Build Coastguard Worker     repeat_test     = 0;
1356*5e7646d2SAndroid Build Coastguard Worker     response        = NULL;
1357*5e7646d2SAndroid Build Coastguard Worker 
1358*5e7646d2SAndroid Build Coastguard Worker     if (status != HTTP_STATUS_ERROR)
1359*5e7646d2SAndroid Build Coastguard Worker     {
1360*5e7646d2SAndroid Build Coastguard Worker       while (!response && !Cancel && data->prev_pass)
1361*5e7646d2SAndroid Build Coastguard Worker       {
1362*5e7646d2SAndroid Build Coastguard Worker         ippSetRequestId(request, ++ data->request_id);
1363*5e7646d2SAndroid Build Coastguard Worker 
1364*5e7646d2SAndroid Build Coastguard Worker 	status = cupsSendRequest(data->http, request, data->resource, length);
1365*5e7646d2SAndroid Build Coastguard Worker 
1366*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_LIBZ
1367*5e7646d2SAndroid Build Coastguard Worker 	if (data->compression[0])
1368*5e7646d2SAndroid Build Coastguard Worker 	  httpSetField(data->http, HTTP_FIELD_CONTENT_ENCODING, data->compression);
1369*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_LIBZ */
1370*5e7646d2SAndroid Build Coastguard Worker 
1371*5e7646d2SAndroid Build Coastguard Worker 	if (!Cancel && status == HTTP_STATUS_CONTINUE && ippGetState(request) == IPP_DATA && data->file[0])
1372*5e7646d2SAndroid Build Coastguard Worker 	{
1373*5e7646d2SAndroid Build Coastguard Worker 	  if ((reqfile = cupsFileOpen(data->file, "r")) != NULL)
1374*5e7646d2SAndroid Build Coastguard Worker 	  {
1375*5e7646d2SAndroid Build Coastguard Worker 	    while (!Cancel && (bytes = cupsFileRead(reqfile, buffer, sizeof(buffer))) > 0)
1376*5e7646d2SAndroid Build Coastguard Worker 	    {
1377*5e7646d2SAndroid Build Coastguard Worker 	      if ((status = cupsWriteRequestData(data->http, buffer, (size_t)bytes)) != HTTP_STATUS_CONTINUE)
1378*5e7646d2SAndroid Build Coastguard Worker 		break;
1379*5e7646d2SAndroid Build Coastguard Worker             }
1380*5e7646d2SAndroid Build Coastguard Worker 
1381*5e7646d2SAndroid Build Coastguard Worker 	    cupsFileClose(reqfile);
1382*5e7646d2SAndroid Build Coastguard Worker 	  }
1383*5e7646d2SAndroid Build Coastguard Worker 	  else
1384*5e7646d2SAndroid Build Coastguard Worker 	  {
1385*5e7646d2SAndroid Build Coastguard Worker 	    snprintf(buffer, sizeof(buffer), "%s: %s", data->file, strerror(errno));
1386*5e7646d2SAndroid Build Coastguard Worker 	    _cupsSetError(IPP_INTERNAL_ERROR, buffer, 0);
1387*5e7646d2SAndroid Build Coastguard Worker 
1388*5e7646d2SAndroid Build Coastguard Worker 	    status = HTTP_STATUS_ERROR;
1389*5e7646d2SAndroid Build Coastguard Worker 	  }
1390*5e7646d2SAndroid Build Coastguard Worker 	}
1391*5e7646d2SAndroid Build Coastguard Worker 
1392*5e7646d2SAndroid Build Coastguard Worker        /*
1393*5e7646d2SAndroid Build Coastguard Worker 	* Get the server's response...
1394*5e7646d2SAndroid Build Coastguard Worker 	*/
1395*5e7646d2SAndroid Build Coastguard Worker 
1396*5e7646d2SAndroid Build Coastguard Worker 	if (!Cancel && status != HTTP_STATUS_ERROR)
1397*5e7646d2SAndroid Build Coastguard Worker 	{
1398*5e7646d2SAndroid Build Coastguard Worker 	  response = cupsGetResponse(data->http, data->resource);
1399*5e7646d2SAndroid Build Coastguard Worker 	  status   = httpGetStatus(data->http);
1400*5e7646d2SAndroid Build Coastguard Worker 	}
1401*5e7646d2SAndroid Build Coastguard Worker 
1402*5e7646d2SAndroid Build Coastguard Worker 	if (!Cancel && status == HTTP_STATUS_ERROR && httpError(data->http) != EINVAL &&
1403*5e7646d2SAndroid Build Coastguard Worker #ifdef _WIN32
1404*5e7646d2SAndroid Build Coastguard Worker 	    httpError(data->http) != WSAETIMEDOUT)
1405*5e7646d2SAndroid Build Coastguard Worker #else
1406*5e7646d2SAndroid Build Coastguard Worker 	    httpError(data->http) != ETIMEDOUT)
1407*5e7646d2SAndroid Build Coastguard Worker #endif /* _WIN32 */
1408*5e7646d2SAndroid Build Coastguard Worker 	{
1409*5e7646d2SAndroid Build Coastguard Worker 	  if (httpReconnect2(data->http, 30000, NULL))
1410*5e7646d2SAndroid Build Coastguard Worker 	    data->prev_pass = 0;
1411*5e7646d2SAndroid Build Coastguard Worker 	}
1412*5e7646d2SAndroid Build Coastguard Worker 	else if (status == HTTP_STATUS_ERROR || status == HTTP_STATUS_CUPS_AUTHORIZATION_CANCELED)
1413*5e7646d2SAndroid Build Coastguard Worker 	{
1414*5e7646d2SAndroid Build Coastguard Worker 	  data->prev_pass = 0;
1415*5e7646d2SAndroid Build Coastguard Worker 	  break;
1416*5e7646d2SAndroid Build Coastguard Worker 	}
1417*5e7646d2SAndroid Build Coastguard Worker 	else if (status != HTTP_STATUS_OK)
1418*5e7646d2SAndroid Build Coastguard Worker 	{
1419*5e7646d2SAndroid Build Coastguard Worker 	  httpFlush(data->http);
1420*5e7646d2SAndroid Build Coastguard Worker 
1421*5e7646d2SAndroid Build Coastguard Worker 	  if (status == HTTP_STATUS_UNAUTHORIZED)
1422*5e7646d2SAndroid Build Coastguard Worker 	    continue;
1423*5e7646d2SAndroid Build Coastguard Worker 
1424*5e7646d2SAndroid Build Coastguard Worker 	  break;
1425*5e7646d2SAndroid Build Coastguard Worker 	}
1426*5e7646d2SAndroid Build Coastguard Worker       }
1427*5e7646d2SAndroid Build Coastguard Worker     }
1428*5e7646d2SAndroid Build Coastguard Worker 
1429*5e7646d2SAndroid Build Coastguard Worker     if (!Cancel && status == HTTP_STATUS_ERROR && httpError(data->http) != EINVAL &&
1430*5e7646d2SAndroid Build Coastguard Worker #ifdef _WIN32
1431*5e7646d2SAndroid Build Coastguard Worker 	httpError(data->http) != WSAETIMEDOUT)
1432*5e7646d2SAndroid Build Coastguard Worker #else
1433*5e7646d2SAndroid Build Coastguard Worker 	httpError(data->http) != ETIMEDOUT)
1434*5e7646d2SAndroid Build Coastguard Worker #endif /* _WIN32 */
1435*5e7646d2SAndroid Build Coastguard Worker     {
1436*5e7646d2SAndroid Build Coastguard Worker       if (httpReconnect2(data->http, 30000, NULL))
1437*5e7646d2SAndroid Build Coastguard Worker 	data->prev_pass = 0;
1438*5e7646d2SAndroid Build Coastguard Worker     }
1439*5e7646d2SAndroid Build Coastguard Worker     else if (status == HTTP_STATUS_ERROR)
1440*5e7646d2SAndroid Build Coastguard Worker     {
1441*5e7646d2SAndroid Build Coastguard Worker       if (!Cancel)
1442*5e7646d2SAndroid Build Coastguard Worker 	httpReconnect2(data->http, 30000, NULL);
1443*5e7646d2SAndroid Build Coastguard Worker 
1444*5e7646d2SAndroid Build Coastguard Worker       data->prev_pass = 0;
1445*5e7646d2SAndroid Build Coastguard Worker     }
1446*5e7646d2SAndroid Build Coastguard Worker     else if (status != HTTP_STATUS_OK)
1447*5e7646d2SAndroid Build Coastguard Worker     {
1448*5e7646d2SAndroid Build Coastguard Worker       httpFlush(data->http);
1449*5e7646d2SAndroid Build Coastguard Worker       data->prev_pass = 0;
1450*5e7646d2SAndroid Build Coastguard Worker     }
1451*5e7646d2SAndroid Build Coastguard Worker 
1452*5e7646d2SAndroid Build Coastguard Worker    /*
1453*5e7646d2SAndroid Build Coastguard Worker     * Check results of request...
1454*5e7646d2SAndroid Build Coastguard Worker     */
1455*5e7646d2SAndroid Build Coastguard Worker 
1456*5e7646d2SAndroid Build Coastguard Worker     cupsArrayClear(data->errors);
1457*5e7646d2SAndroid Build Coastguard Worker 
1458*5e7646d2SAndroid Build Coastguard Worker     if (httpGetVersion(data->http) != HTTP_1_1)
1459*5e7646d2SAndroid Build Coastguard Worker     {
1460*5e7646d2SAndroid Build Coastguard Worker       int version = (int)httpGetVersion(data->http);
1461*5e7646d2SAndroid Build Coastguard Worker 
1462*5e7646d2SAndroid Build Coastguard Worker       add_stringf(data->errors, "Bad HTTP version (%d.%d)", version / 100, version % 100);
1463*5e7646d2SAndroid Build Coastguard Worker     }
1464*5e7646d2SAndroid Build Coastguard Worker 
1465*5e7646d2SAndroid Build Coastguard Worker     if (data->validate_headers)
1466*5e7646d2SAndroid Build Coastguard Worker     {
1467*5e7646d2SAndroid Build Coastguard Worker       const char *header;               /* HTTP header value */
1468*5e7646d2SAndroid Build Coastguard Worker 
1469*5e7646d2SAndroid Build Coastguard Worker       if ((header = httpGetField(data->http, HTTP_FIELD_CONTENT_TYPE)) == NULL || _cups_strcasecmp(header, "application/ipp"))
1470*5e7646d2SAndroid Build Coastguard Worker 	add_stringf(data->errors, "Bad HTTP Content-Type in response (%s)", header && *header ? header : "<missing>");
1471*5e7646d2SAndroid Build Coastguard Worker 
1472*5e7646d2SAndroid Build Coastguard Worker       if ((header = httpGetField(data->http, HTTP_FIELD_DATE)) != NULL && *header && httpGetDateTime(header) == 0)
1473*5e7646d2SAndroid Build Coastguard Worker 	add_stringf(data->errors, "Bad HTTP Date in response (%s)", header);
1474*5e7646d2SAndroid Build Coastguard Worker     }
1475*5e7646d2SAndroid Build Coastguard Worker 
1476*5e7646d2SAndroid Build Coastguard Worker     if (!response)
1477*5e7646d2SAndroid Build Coastguard Worker     {
1478*5e7646d2SAndroid Build Coastguard Worker      /*
1479*5e7646d2SAndroid Build Coastguard Worker       * No response, log error...
1480*5e7646d2SAndroid Build Coastguard Worker       */
1481*5e7646d2SAndroid Build Coastguard Worker 
1482*5e7646d2SAndroid Build Coastguard Worker       add_stringf(data->errors, "IPP request failed with status %s (%s)", ippErrorString(cupsLastError()), cupsLastErrorString());
1483*5e7646d2SAndroid Build Coastguard Worker     }
1484*5e7646d2SAndroid Build Coastguard Worker     else
1485*5e7646d2SAndroid Build Coastguard Worker     {
1486*5e7646d2SAndroid Build Coastguard Worker      /*
1487*5e7646d2SAndroid Build Coastguard Worker       * Collect common attribute values...
1488*5e7646d2SAndroid Build Coastguard Worker       */
1489*5e7646d2SAndroid Build Coastguard Worker 
1490*5e7646d2SAndroid Build Coastguard Worker       if ((attrptr = ippFindAttribute(response, "job-id", IPP_TAG_INTEGER)) != NULL)
1491*5e7646d2SAndroid Build Coastguard Worker       {
1492*5e7646d2SAndroid Build Coastguard Worker 	snprintf(temp, sizeof(temp), "%d", ippGetInteger(attrptr, 0));
1493*5e7646d2SAndroid Build Coastguard Worker 	_ippVarsSet(data->vars, "job-id", temp);
1494*5e7646d2SAndroid Build Coastguard Worker       }
1495*5e7646d2SAndroid Build Coastguard Worker 
1496*5e7646d2SAndroid Build Coastguard Worker       if ((attrptr = ippFindAttribute(response, "job-uri", IPP_TAG_URI)) != NULL)
1497*5e7646d2SAndroid Build Coastguard Worker 	_ippVarsSet(data->vars, "job-uri", ippGetString(attrptr, 0, NULL));
1498*5e7646d2SAndroid Build Coastguard Worker 
1499*5e7646d2SAndroid Build Coastguard Worker       if ((attrptr = ippFindAttribute(response, "notify-subscription-id", IPP_TAG_INTEGER)) != NULL)
1500*5e7646d2SAndroid Build Coastguard Worker       {
1501*5e7646d2SAndroid Build Coastguard Worker 	snprintf(temp, sizeof(temp), "%d", ippGetInteger(attrptr, 0));
1502*5e7646d2SAndroid Build Coastguard Worker 	_ippVarsSet(data->vars, "notify-subscription-id", temp);
1503*5e7646d2SAndroid Build Coastguard Worker       }
1504*5e7646d2SAndroid Build Coastguard Worker 
1505*5e7646d2SAndroid Build Coastguard Worker      /*
1506*5e7646d2SAndroid Build Coastguard Worker       * Check response, validating groups and attributes and logging errors
1507*5e7646d2SAndroid Build Coastguard Worker       * as needed...
1508*5e7646d2SAndroid Build Coastguard Worker       */
1509*5e7646d2SAndroid Build Coastguard Worker 
1510*5e7646d2SAndroid Build Coastguard Worker       if (ippGetState(response) != IPP_DATA)
1511*5e7646d2SAndroid Build Coastguard Worker 	add_stringf(data->errors, "Missing end-of-attributes-tag in response (RFC 2910 section 3.5.1)");
1512*5e7646d2SAndroid Build Coastguard Worker 
1513*5e7646d2SAndroid Build Coastguard Worker       if (data->version)
1514*5e7646d2SAndroid Build Coastguard Worker       {
1515*5e7646d2SAndroid Build Coastguard Worker         int major, minor;		/* IPP version */
1516*5e7646d2SAndroid Build Coastguard Worker 
1517*5e7646d2SAndroid Build Coastguard Worker         major = ippGetVersion(response, &minor);
1518*5e7646d2SAndroid Build Coastguard Worker 
1519*5e7646d2SAndroid Build Coastguard Worker         if (major != (data->version / 10) || minor != (data->version % 10))
1520*5e7646d2SAndroid Build Coastguard Worker 	  add_stringf(data->errors, "Bad version %d.%d in response - expected %d.%d (RFC 8011 section 4.1.8).", major, minor, data->version / 10, data->version % 10);
1521*5e7646d2SAndroid Build Coastguard Worker       }
1522*5e7646d2SAndroid Build Coastguard Worker 
1523*5e7646d2SAndroid Build Coastguard Worker       if (ippGetRequestId(response) != data->request_id)
1524*5e7646d2SAndroid Build Coastguard Worker 	add_stringf(data->errors, "Bad request ID %d in response - expected %d (RFC 8011 section 4.1.1)", ippGetRequestId(response), data->request_id);
1525*5e7646d2SAndroid Build Coastguard Worker 
1526*5e7646d2SAndroid Build Coastguard Worker       attrptr = ippFirstAttribute(response);
1527*5e7646d2SAndroid Build Coastguard Worker       if (!attrptr)
1528*5e7646d2SAndroid Build Coastguard Worker       {
1529*5e7646d2SAndroid Build Coastguard Worker 	add_stringf(data->errors, "Missing first attribute \"attributes-charset (charset)\" in group operation-attributes-tag (RFC 8011 section 4.1.4).");
1530*5e7646d2SAndroid Build Coastguard Worker       }
1531*5e7646d2SAndroid Build Coastguard Worker       else
1532*5e7646d2SAndroid Build Coastguard Worker       {
1533*5e7646d2SAndroid Build Coastguard Worker 	if (!ippGetName(attrptr) || ippGetValueTag(attrptr) != IPP_TAG_CHARSET || ippGetGroupTag(attrptr) != IPP_TAG_OPERATION || ippGetCount(attrptr) != 1 ||strcmp(ippGetName(attrptr), "attributes-charset"))
1534*5e7646d2SAndroid Build Coastguard Worker 	  add_stringf(data->errors, "Bad first attribute \"%s (%s%s)\" in group %s, expected \"attributes-charset (charset)\" in group operation-attributes-tag (RFC 8011 section 4.1.4).", ippGetName(attrptr) ? ippGetName(attrptr) : "(null)", ippGetCount(attrptr) > 1 ? "1setOf " : "", ippTagString(ippGetValueTag(attrptr)), ippTagString(ippGetGroupTag(attrptr)));
1535*5e7646d2SAndroid Build Coastguard Worker 
1536*5e7646d2SAndroid Build Coastguard Worker 	attrptr = ippNextAttribute(response);
1537*5e7646d2SAndroid Build Coastguard Worker 	if (!attrptr)
1538*5e7646d2SAndroid Build Coastguard Worker 	  add_stringf(data->errors, "Missing second attribute \"attributes-natural-language (naturalLanguage)\" in group operation-attributes-tag (RFC 8011 section 4.1.4).");
1539*5e7646d2SAndroid Build Coastguard Worker 	else if (!ippGetName(attrptr) || ippGetValueTag(attrptr) != IPP_TAG_LANGUAGE || ippGetGroupTag(attrptr) != IPP_TAG_OPERATION || ippGetCount(attrptr) != 1 || strcmp(ippGetName(attrptr), "attributes-natural-language"))
1540*5e7646d2SAndroid Build Coastguard Worker 	  add_stringf(data->errors, "Bad first attribute \"%s (%s%s)\" in group %s, expected \"attributes-natural-language (naturalLanguage)\" in group operation-attributes-tag (RFC 8011 section 4.1.4).", ippGetName(attrptr) ? ippGetName(attrptr) : "(null)", ippGetCount(attrptr) > 1 ? "1setOf " : "", ippTagString(ippGetValueTag(attrptr)), ippTagString(ippGetGroupTag(attrptr)));
1541*5e7646d2SAndroid Build Coastguard Worker       }
1542*5e7646d2SAndroid Build Coastguard Worker 
1543*5e7646d2SAndroid Build Coastguard Worker       if ((attrptr = ippFindAttribute(response, "status-message", IPP_TAG_ZERO)) != NULL)
1544*5e7646d2SAndroid Build Coastguard Worker       {
1545*5e7646d2SAndroid Build Coastguard Worker         const char *status_message = ippGetString(attrptr, 0, NULL);
1546*5e7646d2SAndroid Build Coastguard Worker 						/* String value */
1547*5e7646d2SAndroid Build Coastguard Worker 
1548*5e7646d2SAndroid Build Coastguard Worker 	if (ippGetValueTag(attrptr) != IPP_TAG_TEXT)
1549*5e7646d2SAndroid Build Coastguard Worker 	  add_stringf(data->errors, "status-message (text(255)) has wrong value tag %s (RFC 8011 section 4.1.6.2).", ippTagString(ippGetValueTag(attrptr)));
1550*5e7646d2SAndroid Build Coastguard Worker 	if (ippGetGroupTag(attrptr) != IPP_TAG_OPERATION)
1551*5e7646d2SAndroid Build Coastguard Worker 	  add_stringf(data->errors, "status-message (text(255)) has wrong group tag %s (RFC 8011 section 4.1.6.2).", ippTagString(ippGetGroupTag(attrptr)));
1552*5e7646d2SAndroid Build Coastguard Worker 	if (ippGetCount(attrptr) != 1)
1553*5e7646d2SAndroid Build Coastguard Worker 	  add_stringf(data->errors, "status-message (text(255)) has %d values (RFC 8011 section 4.1.6.2).", ippGetCount(attrptr));
1554*5e7646d2SAndroid Build Coastguard Worker 	if (status_message && strlen(status_message) > 255)
1555*5e7646d2SAndroid Build Coastguard Worker 	  add_stringf(data->errors, "status-message (text(255)) has bad length %d (RFC 8011 section 4.1.6.2).", (int)strlen(status_message));
1556*5e7646d2SAndroid Build Coastguard Worker       }
1557*5e7646d2SAndroid Build Coastguard Worker 
1558*5e7646d2SAndroid Build Coastguard Worker       if ((attrptr = ippFindAttribute(response, "detailed-status-message",
1559*5e7646d2SAndroid Build Coastguard Worker 				       IPP_TAG_ZERO)) != NULL)
1560*5e7646d2SAndroid Build Coastguard Worker       {
1561*5e7646d2SAndroid Build Coastguard Worker         const char *detailed_status_message = ippGetString(attrptr, 0, NULL);
1562*5e7646d2SAndroid Build Coastguard Worker 						/* String value */
1563*5e7646d2SAndroid Build Coastguard Worker 
1564*5e7646d2SAndroid Build Coastguard Worker 	if (ippGetValueTag(attrptr) != IPP_TAG_TEXT)
1565*5e7646d2SAndroid Build Coastguard Worker 	  add_stringf(data->errors, "detailed-status-message (text(MAX)) has wrong value tag %s (RFC 8011 section 4.1.6.3).", ippTagString(ippGetValueTag(attrptr)));
1566*5e7646d2SAndroid Build Coastguard Worker 	if (ippGetGroupTag(attrptr) != IPP_TAG_OPERATION)
1567*5e7646d2SAndroid Build Coastguard Worker 	  add_stringf(data->errors, "detailed-status-message (text(MAX)) has wrong group tag %s (RFC 8011 section 4.1.6.3).", ippTagString(ippGetGroupTag(attrptr)));
1568*5e7646d2SAndroid Build Coastguard Worker 	if (ippGetCount(attrptr) != 1)
1569*5e7646d2SAndroid Build Coastguard Worker 	  add_stringf(data->errors, "detailed-status-message (text(MAX)) has %d values (RFC 8011 section 4.1.6.3).", ippGetCount(attrptr));
1570*5e7646d2SAndroid Build Coastguard Worker 	if (detailed_status_message && strlen(detailed_status_message) > 1023)
1571*5e7646d2SAndroid Build Coastguard Worker 	  add_stringf(data->errors, "detailed-status-message (text(MAX)) has bad length %d (RFC 8011 section 4.1.6.3).", (int)strlen(detailed_status_message));
1572*5e7646d2SAndroid Build Coastguard Worker       }
1573*5e7646d2SAndroid Build Coastguard Worker 
1574*5e7646d2SAndroid Build Coastguard Worker       a = cupsArrayNew((cups_array_func_t)strcmp, NULL);
1575*5e7646d2SAndroid Build Coastguard Worker 
1576*5e7646d2SAndroid Build Coastguard Worker       for (attrptr = ippFirstAttribute(response), group = ippGetGroupTag(attrptr);
1577*5e7646d2SAndroid Build Coastguard Worker 	   attrptr;
1578*5e7646d2SAndroid Build Coastguard Worker 	   attrptr = ippNextAttribute(response))
1579*5e7646d2SAndroid Build Coastguard Worker       {
1580*5e7646d2SAndroid Build Coastguard Worker 	if (ippGetGroupTag(attrptr) != group)
1581*5e7646d2SAndroid Build Coastguard Worker 	{
1582*5e7646d2SAndroid Build Coastguard Worker 	  int out_of_order = 0;	/* Are attribute groups out-of-order? */
1583*5e7646d2SAndroid Build Coastguard Worker 	  cupsArrayClear(a);
1584*5e7646d2SAndroid Build Coastguard Worker 
1585*5e7646d2SAndroid Build Coastguard Worker 	  switch (ippGetGroupTag(attrptr))
1586*5e7646d2SAndroid Build Coastguard Worker 	  {
1587*5e7646d2SAndroid Build Coastguard Worker 	    case IPP_TAG_ZERO :
1588*5e7646d2SAndroid Build Coastguard Worker 		break;
1589*5e7646d2SAndroid Build Coastguard Worker 
1590*5e7646d2SAndroid Build Coastguard Worker 	    case IPP_TAG_OPERATION :
1591*5e7646d2SAndroid Build Coastguard Worker 		out_of_order = 1;
1592*5e7646d2SAndroid Build Coastguard Worker 		break;
1593*5e7646d2SAndroid Build Coastguard Worker 
1594*5e7646d2SAndroid Build Coastguard Worker 	    case IPP_TAG_UNSUPPORTED_GROUP :
1595*5e7646d2SAndroid Build Coastguard Worker 		if (group != IPP_TAG_OPERATION)
1596*5e7646d2SAndroid Build Coastguard Worker 		  out_of_order = 1;
1597*5e7646d2SAndroid Build Coastguard Worker 		break;
1598*5e7646d2SAndroid Build Coastguard Worker 
1599*5e7646d2SAndroid Build Coastguard Worker 	    case IPP_TAG_JOB :
1600*5e7646d2SAndroid Build Coastguard Worker 	    case IPP_TAG_PRINTER :
1601*5e7646d2SAndroid Build Coastguard Worker 		if (group != IPP_TAG_OPERATION && group != IPP_TAG_UNSUPPORTED_GROUP)
1602*5e7646d2SAndroid Build Coastguard Worker 		  out_of_order = 1;
1603*5e7646d2SAndroid Build Coastguard Worker 		break;
1604*5e7646d2SAndroid Build Coastguard Worker 
1605*5e7646d2SAndroid Build Coastguard Worker 	    case IPP_TAG_SUBSCRIPTION :
1606*5e7646d2SAndroid Build Coastguard Worker 		if (group > ippGetGroupTag(attrptr) && group != IPP_TAG_DOCUMENT)
1607*5e7646d2SAndroid Build Coastguard Worker 		  out_of_order = 1;
1608*5e7646d2SAndroid Build Coastguard Worker 		break;
1609*5e7646d2SAndroid Build Coastguard Worker 
1610*5e7646d2SAndroid Build Coastguard Worker 	    default :
1611*5e7646d2SAndroid Build Coastguard Worker 		if (group > ippGetGroupTag(attrptr))
1612*5e7646d2SAndroid Build Coastguard Worker 		  out_of_order = 1;
1613*5e7646d2SAndroid Build Coastguard Worker 		break;
1614*5e7646d2SAndroid Build Coastguard Worker 	  }
1615*5e7646d2SAndroid Build Coastguard Worker 
1616*5e7646d2SAndroid Build Coastguard Worker 	  if (out_of_order)
1617*5e7646d2SAndroid Build Coastguard Worker 	    add_stringf(data->errors, "Attribute groups out of order (%s < %s)", ippTagString(ippGetGroupTag(attrptr)), ippTagString(group));
1618*5e7646d2SAndroid Build Coastguard Worker 
1619*5e7646d2SAndroid Build Coastguard Worker 	  if (ippGetGroupTag(attrptr) != IPP_TAG_ZERO)
1620*5e7646d2SAndroid Build Coastguard Worker 	    group = ippGetGroupTag(attrptr);
1621*5e7646d2SAndroid Build Coastguard Worker 	}
1622*5e7646d2SAndroid Build Coastguard Worker 
1623*5e7646d2SAndroid Build Coastguard Worker 	if (!ippValidateAttribute(attrptr))
1624*5e7646d2SAndroid Build Coastguard Worker 	  cupsArrayAdd(data->errors, (void *)cupsLastErrorString());
1625*5e7646d2SAndroid Build Coastguard Worker 
1626*5e7646d2SAndroid Build Coastguard Worker 	if (ippGetName(attrptr))
1627*5e7646d2SAndroid Build Coastguard Worker 	{
1628*5e7646d2SAndroid Build Coastguard Worker 	  if (cupsArrayFind(a, (void *)ippGetName(attrptr)) && data->output < IPPTOOL_OUTPUT_LIST)
1629*5e7646d2SAndroid Build Coastguard Worker 	    add_stringf(data->errors, "Duplicate \"%s\" attribute in %s group", ippGetName(attrptr), ippTagString(group));
1630*5e7646d2SAndroid Build Coastguard Worker 
1631*5e7646d2SAndroid Build Coastguard Worker 	  cupsArrayAdd(a, (void *)ippGetName(attrptr));
1632*5e7646d2SAndroid Build Coastguard Worker 	}
1633*5e7646d2SAndroid Build Coastguard Worker       }
1634*5e7646d2SAndroid Build Coastguard Worker 
1635*5e7646d2SAndroid Build Coastguard Worker       cupsArrayDelete(a);
1636*5e7646d2SAndroid Build Coastguard Worker 
1637*5e7646d2SAndroid Build Coastguard Worker      /*
1638*5e7646d2SAndroid Build Coastguard Worker       * Now check the test-defined expected status-code and attribute
1639*5e7646d2SAndroid Build Coastguard Worker       * values...
1640*5e7646d2SAndroid Build Coastguard Worker       */
1641*5e7646d2SAndroid Build Coastguard Worker 
1642*5e7646d2SAndroid Build Coastguard Worker       if (ippGetStatusCode(response) == IPP_STATUS_ERROR_BUSY && data->repeat_on_busy)
1643*5e7646d2SAndroid Build Coastguard Worker       {
1644*5e7646d2SAndroid Build Coastguard Worker         // Repeat on a server-error-busy status code...
1645*5e7646d2SAndroid Build Coastguard Worker         status_ok   = 1;
1646*5e7646d2SAndroid Build Coastguard Worker         repeat_test = 1;
1647*5e7646d2SAndroid Build Coastguard Worker       }
1648*5e7646d2SAndroid Build Coastguard Worker 
1649*5e7646d2SAndroid Build Coastguard Worker       for (i = 0, status_ok = 0; i < data->num_statuses; i ++)
1650*5e7646d2SAndroid Build Coastguard Worker       {
1651*5e7646d2SAndroid Build Coastguard Worker 	if (data->statuses[i].if_defined &&
1652*5e7646d2SAndroid Build Coastguard Worker 	    !_ippVarsGet(data->vars, data->statuses[i].if_defined))
1653*5e7646d2SAndroid Build Coastguard Worker 	  continue;
1654*5e7646d2SAndroid Build Coastguard Worker 
1655*5e7646d2SAndroid Build Coastguard Worker 	if (data->statuses[i].if_not_defined &&
1656*5e7646d2SAndroid Build Coastguard Worker 	    _ippVarsGet(data->vars, data->statuses[i].if_not_defined))
1657*5e7646d2SAndroid Build Coastguard Worker 	  continue;
1658*5e7646d2SAndroid Build Coastguard Worker 
1659*5e7646d2SAndroid Build Coastguard Worker 	if (ippGetStatusCode(response) == data->statuses[i].status)
1660*5e7646d2SAndroid Build Coastguard Worker 	{
1661*5e7646d2SAndroid Build Coastguard Worker 	  status_ok = 1;
1662*5e7646d2SAndroid Build Coastguard Worker 
1663*5e7646d2SAndroid Build Coastguard Worker 	  if (data->statuses[i].repeat_match && repeat_count < data->statuses[i].repeat_limit)
1664*5e7646d2SAndroid Build Coastguard Worker 	    repeat_test = 1;
1665*5e7646d2SAndroid Build Coastguard Worker 
1666*5e7646d2SAndroid Build Coastguard Worker 	  if (data->statuses[i].define_match)
1667*5e7646d2SAndroid Build Coastguard Worker 	    _ippVarsSet(data->vars, data->statuses[i].define_match, "1");
1668*5e7646d2SAndroid Build Coastguard Worker 	}
1669*5e7646d2SAndroid Build Coastguard Worker 	else
1670*5e7646d2SAndroid Build Coastguard Worker 	{
1671*5e7646d2SAndroid Build Coastguard Worker 	  if (data->statuses[i].repeat_no_match && repeat_count < data->statuses[i].repeat_limit)
1672*5e7646d2SAndroid Build Coastguard Worker 	    repeat_test = 1;
1673*5e7646d2SAndroid Build Coastguard Worker 
1674*5e7646d2SAndroid Build Coastguard Worker 	  if (data->statuses[i].define_no_match)
1675*5e7646d2SAndroid Build Coastguard Worker 	  {
1676*5e7646d2SAndroid Build Coastguard Worker 	    _ippVarsSet(data->vars, data->statuses[i].define_no_match, "1");
1677*5e7646d2SAndroid Build Coastguard Worker 	    status_ok = 1;
1678*5e7646d2SAndroid Build Coastguard Worker 	  }
1679*5e7646d2SAndroid Build Coastguard Worker 	}
1680*5e7646d2SAndroid Build Coastguard Worker       }
1681*5e7646d2SAndroid Build Coastguard Worker 
1682*5e7646d2SAndroid Build Coastguard Worker       if (!status_ok && data->num_statuses > 0)
1683*5e7646d2SAndroid Build Coastguard Worker       {
1684*5e7646d2SAndroid Build Coastguard Worker 	for (i = 0; i < data->num_statuses; i ++)
1685*5e7646d2SAndroid Build Coastguard Worker 	{
1686*5e7646d2SAndroid Build Coastguard Worker 	  if (data->statuses[i].if_defined &&
1687*5e7646d2SAndroid Build Coastguard Worker 	      !_ippVarsGet(data->vars, data->statuses[i].if_defined))
1688*5e7646d2SAndroid Build Coastguard Worker 	    continue;
1689*5e7646d2SAndroid Build Coastguard Worker 
1690*5e7646d2SAndroid Build Coastguard Worker 	  if (data->statuses[i].if_not_defined &&
1691*5e7646d2SAndroid Build Coastguard Worker 	      _ippVarsGet(data->vars, data->statuses[i].if_not_defined))
1692*5e7646d2SAndroid Build Coastguard Worker 	    continue;
1693*5e7646d2SAndroid Build Coastguard Worker 
1694*5e7646d2SAndroid Build Coastguard Worker 	  if (!data->statuses[i].repeat_match || repeat_count >= data->statuses[i].repeat_limit)
1695*5e7646d2SAndroid Build Coastguard Worker 	    add_stringf(data->errors, "EXPECTED: STATUS %s (got %s)", ippErrorString(data->statuses[i].status), ippErrorString(cupsLastError()));
1696*5e7646d2SAndroid Build Coastguard Worker 	}
1697*5e7646d2SAndroid Build Coastguard Worker 
1698*5e7646d2SAndroid Build Coastguard Worker 	if ((attrptr = ippFindAttribute(response, "status-message", IPP_TAG_TEXT)) != NULL)
1699*5e7646d2SAndroid Build Coastguard Worker 	  add_stringf(data->errors, "status-message=\"%s\"", ippGetString(attrptr, 0, NULL));
1700*5e7646d2SAndroid Build Coastguard Worker       }
1701*5e7646d2SAndroid Build Coastguard Worker 
1702*5e7646d2SAndroid Build Coastguard Worker       for (i = data->num_expects, expect = data->expects; i > 0; i --, expect ++)
1703*5e7646d2SAndroid Build Coastguard Worker       {
1704*5e7646d2SAndroid Build Coastguard Worker 	ipp_attribute_t *group_found;	/* Found parent attribute for group tests */
1705*5e7646d2SAndroid Build Coastguard Worker 
1706*5e7646d2SAndroid Build Coastguard Worker 	if (expect->if_defined && !_ippVarsGet(data->vars, expect->if_defined))
1707*5e7646d2SAndroid Build Coastguard Worker 	  continue;
1708*5e7646d2SAndroid Build Coastguard Worker 
1709*5e7646d2SAndroid Build Coastguard Worker 	if (expect->if_not_defined &&
1710*5e7646d2SAndroid Build Coastguard Worker 	    _ippVarsGet(data->vars, expect->if_not_defined))
1711*5e7646d2SAndroid Build Coastguard Worker 	  continue;
1712*5e7646d2SAndroid Build Coastguard Worker 
1713*5e7646d2SAndroid Build Coastguard Worker 	if ((found = ippFindAttribute(response, expect->name, IPP_TAG_ZERO)) != NULL && expect->in_group && expect->in_group != ippGetGroupTag(found))
1714*5e7646d2SAndroid Build Coastguard Worker 	{
1715*5e7646d2SAndroid Build Coastguard Worker 	  while ((found = ippFindNextAttribute(response, expect->name, IPP_TAG_ZERO)) != NULL)
1716*5e7646d2SAndroid Build Coastguard Worker 	    if (expect->in_group == ippGetGroupTag(found))
1717*5e7646d2SAndroid Build Coastguard Worker 	      break;
1718*5e7646d2SAndroid Build Coastguard Worker 	}
1719*5e7646d2SAndroid Build Coastguard Worker 
1720*5e7646d2SAndroid Build Coastguard Worker 	do
1721*5e7646d2SAndroid Build Coastguard Worker 	{
1722*5e7646d2SAndroid Build Coastguard Worker 	  group_found = found;
1723*5e7646d2SAndroid Build Coastguard Worker 
1724*5e7646d2SAndroid Build Coastguard Worker           if (expect->in_group && strchr(expect->name, '/'))
1725*5e7646d2SAndroid Build Coastguard Worker           {
1726*5e7646d2SAndroid Build Coastguard Worker             char	group_name[256],/* Parent attribute name */
1727*5e7646d2SAndroid Build Coastguard Worker 			*group_ptr;	/* Pointer into parent attribute name */
1728*5e7646d2SAndroid Build Coastguard Worker 
1729*5e7646d2SAndroid Build Coastguard Worker 	    strlcpy(group_name, expect->name, sizeof(group_name));
1730*5e7646d2SAndroid Build Coastguard Worker 	    if ((group_ptr = strchr(group_name, '/')) != NULL)
1731*5e7646d2SAndroid Build Coastguard Worker 	      *group_ptr = '\0';
1732*5e7646d2SAndroid Build Coastguard Worker 
1733*5e7646d2SAndroid Build Coastguard Worker 	    group_found = ippFindAttribute(response, group_name, IPP_TAG_ZERO);
1734*5e7646d2SAndroid Build Coastguard Worker 	  }
1735*5e7646d2SAndroid Build Coastguard Worker 
1736*5e7646d2SAndroid Build Coastguard Worker 	  if ((found && expect->not_expect) ||
1737*5e7646d2SAndroid Build Coastguard Worker 	      (!found && !(expect->not_expect || expect->optional)) ||
1738*5e7646d2SAndroid Build Coastguard Worker 	      (found && !expect_matches(expect, found)) ||
1739*5e7646d2SAndroid Build Coastguard Worker 	      (group_found && expect->in_group && ippGetGroupTag(group_found) != expect->in_group) ||
1740*5e7646d2SAndroid Build Coastguard Worker 	      (expect->with_distinct && !with_distinct_values(NULL, found)))
1741*5e7646d2SAndroid Build Coastguard Worker 	  {
1742*5e7646d2SAndroid Build Coastguard Worker 	    if (expect->define_no_match)
1743*5e7646d2SAndroid Build Coastguard Worker 	      _ippVarsSet(data->vars, expect->define_no_match, "1");
1744*5e7646d2SAndroid Build Coastguard Worker 	    else if (!expect->define_match && !expect->define_value)
1745*5e7646d2SAndroid Build Coastguard Worker 	    {
1746*5e7646d2SAndroid Build Coastguard Worker 	      if (found && expect->not_expect && !expect->with_value && !expect->with_value_from)
1747*5e7646d2SAndroid Build Coastguard Worker 		add_stringf(data->errors, "NOT EXPECTED: %s", expect->name);
1748*5e7646d2SAndroid Build Coastguard Worker 	      else if (!found && !(expect->not_expect || expect->optional))
1749*5e7646d2SAndroid Build Coastguard Worker 		add_stringf(data->errors, "EXPECTED: %s", expect->name);
1750*5e7646d2SAndroid Build Coastguard Worker 	      else if (found)
1751*5e7646d2SAndroid Build Coastguard Worker 	      {
1752*5e7646d2SAndroid Build Coastguard Worker 		if (!expect_matches(expect, found))
1753*5e7646d2SAndroid Build Coastguard Worker 		  add_stringf(data->errors, "EXPECTED: %s OF-TYPE %s (got %s)",
1754*5e7646d2SAndroid Build Coastguard Worker 			      expect->name, expect->of_type,
1755*5e7646d2SAndroid Build Coastguard Worker 			      ippTagString(ippGetValueTag(found)));
1756*5e7646d2SAndroid Build Coastguard Worker 
1757*5e7646d2SAndroid Build Coastguard Worker 		if (expect->in_group && ippGetGroupTag(group_found) != expect->in_group)
1758*5e7646d2SAndroid Build Coastguard Worker 		  add_stringf(data->errors, "EXPECTED: %s IN-GROUP %s (got %s).",
1759*5e7646d2SAndroid Build Coastguard Worker 			      expect->name, ippTagString(expect->in_group),
1760*5e7646d2SAndroid Build Coastguard Worker 			      ippTagString(ippGetGroupTag(group_found)));
1761*5e7646d2SAndroid Build Coastguard Worker 
1762*5e7646d2SAndroid Build Coastguard Worker                 if (expect->with_distinct)
1763*5e7646d2SAndroid Build Coastguard Worker                   with_distinct_values(data->errors, found);
1764*5e7646d2SAndroid Build Coastguard Worker 	      }
1765*5e7646d2SAndroid Build Coastguard Worker 	    }
1766*5e7646d2SAndroid Build Coastguard Worker 
1767*5e7646d2SAndroid Build Coastguard Worker 	    if (expect->repeat_no_match && repeat_count < expect->repeat_limit)
1768*5e7646d2SAndroid Build Coastguard Worker 	      repeat_test = 1;
1769*5e7646d2SAndroid Build Coastguard Worker 	    break;
1770*5e7646d2SAndroid Build Coastguard Worker 	  }
1771*5e7646d2SAndroid Build Coastguard Worker 
1772*5e7646d2SAndroid Build Coastguard Worker 	  if (found)
1773*5e7646d2SAndroid Build Coastguard Worker 	    ippAttributeString(found, buffer, sizeof(buffer));
1774*5e7646d2SAndroid Build Coastguard Worker 
1775*5e7646d2SAndroid Build Coastguard Worker 	  if (found && expect->with_value_from && !with_value_from(NULL, ippFindAttribute(response, expect->with_value_from, IPP_TAG_ZERO), found, buffer, sizeof(buffer)))
1776*5e7646d2SAndroid Build Coastguard Worker 	  {
1777*5e7646d2SAndroid Build Coastguard Worker 	    if (expect->define_no_match)
1778*5e7646d2SAndroid Build Coastguard Worker 	      _ippVarsSet(data->vars, expect->define_no_match, "1");
1779*5e7646d2SAndroid Build Coastguard Worker 	    else if (!expect->define_match && !expect->define_value && ((!expect->repeat_match && !expect->repeat_no_match) || repeat_count >= expect->repeat_limit))
1780*5e7646d2SAndroid Build Coastguard Worker 	    {
1781*5e7646d2SAndroid Build Coastguard Worker 	      add_stringf(data->errors, "EXPECTED: %s WITH-VALUES-FROM %s", expect->name, expect->with_value_from);
1782*5e7646d2SAndroid Build Coastguard Worker 
1783*5e7646d2SAndroid Build Coastguard Worker 	      with_value_from(data->errors, ippFindAttribute(response, expect->with_value_from, IPP_TAG_ZERO), found, buffer, sizeof(buffer));
1784*5e7646d2SAndroid Build Coastguard Worker 	    }
1785*5e7646d2SAndroid Build Coastguard Worker 
1786*5e7646d2SAndroid Build Coastguard Worker 	    if (expect->repeat_no_match && repeat_count < expect->repeat_limit)
1787*5e7646d2SAndroid Build Coastguard Worker 	      repeat_test = 1;
1788*5e7646d2SAndroid Build Coastguard Worker 
1789*5e7646d2SAndroid Build Coastguard Worker 	    break;
1790*5e7646d2SAndroid Build Coastguard Worker 	  }
1791*5e7646d2SAndroid Build Coastguard Worker 	  else if (found && !with_value(data, NULL, expect->with_value, expect->with_flags, found, buffer, sizeof(buffer)))
1792*5e7646d2SAndroid Build Coastguard Worker 	  {
1793*5e7646d2SAndroid Build Coastguard Worker 	    if (expect->define_no_match)
1794*5e7646d2SAndroid Build Coastguard Worker 	      _ippVarsSet(data->vars, expect->define_no_match, "1");
1795*5e7646d2SAndroid Build Coastguard Worker 	    else if (!expect->define_match && !expect->define_value &&
1796*5e7646d2SAndroid Build Coastguard Worker 		     !expect->repeat_match && (!expect->repeat_no_match || repeat_count >= expect->repeat_limit))
1797*5e7646d2SAndroid Build Coastguard Worker 	    {
1798*5e7646d2SAndroid Build Coastguard Worker 	      if (expect->with_flags & IPPTOOL_WITH_REGEX)
1799*5e7646d2SAndroid Build Coastguard Worker 		add_stringf(data->errors, "EXPECTED: %s %s /%s/", expect->name, with_flags_string(expect->with_flags), expect->with_value);
1800*5e7646d2SAndroid Build Coastguard Worker 	      else
1801*5e7646d2SAndroid Build Coastguard Worker 		add_stringf(data->errors, "EXPECTED: %s %s \"%s\"", expect->name, with_flags_string(expect->with_flags), expect->with_value);
1802*5e7646d2SAndroid Build Coastguard Worker 
1803*5e7646d2SAndroid Build Coastguard Worker 	      with_value(data, data->errors, expect->with_value, expect->with_flags, found, buffer, sizeof(buffer));
1804*5e7646d2SAndroid Build Coastguard Worker 	    }
1805*5e7646d2SAndroid Build Coastguard Worker 
1806*5e7646d2SAndroid Build Coastguard Worker 	    if (expect->repeat_no_match &&
1807*5e7646d2SAndroid Build Coastguard Worker 		repeat_count < expect->repeat_limit)
1808*5e7646d2SAndroid Build Coastguard Worker 	      repeat_test = 1;
1809*5e7646d2SAndroid Build Coastguard Worker 
1810*5e7646d2SAndroid Build Coastguard Worker 	    break;
1811*5e7646d2SAndroid Build Coastguard Worker 	  }
1812*5e7646d2SAndroid Build Coastguard Worker 
1813*5e7646d2SAndroid Build Coastguard Worker 	  if (found && expect->count > 0 && ippGetCount(found) != expect->count)
1814*5e7646d2SAndroid Build Coastguard Worker 	  {
1815*5e7646d2SAndroid Build Coastguard Worker 	    if (expect->define_no_match)
1816*5e7646d2SAndroid Build Coastguard Worker 	      _ippVarsSet(data->vars, expect->define_no_match, "1");
1817*5e7646d2SAndroid Build Coastguard Worker 	    else if (!expect->define_match && !expect->define_value)
1818*5e7646d2SAndroid Build Coastguard Worker 	    {
1819*5e7646d2SAndroid Build Coastguard Worker 	      add_stringf(data->errors, "EXPECTED: %s COUNT %d (got %d)", expect->name, expect->count, ippGetCount(found));
1820*5e7646d2SAndroid Build Coastguard Worker 	    }
1821*5e7646d2SAndroid Build Coastguard Worker 
1822*5e7646d2SAndroid Build Coastguard Worker 	    if (expect->repeat_no_match &&
1823*5e7646d2SAndroid Build Coastguard Worker 		repeat_count < expect->repeat_limit)
1824*5e7646d2SAndroid Build Coastguard Worker 	      repeat_test = 1;
1825*5e7646d2SAndroid Build Coastguard Worker 
1826*5e7646d2SAndroid Build Coastguard Worker 	    break;
1827*5e7646d2SAndroid Build Coastguard Worker 	  }
1828*5e7646d2SAndroid Build Coastguard Worker 
1829*5e7646d2SAndroid Build Coastguard Worker 	  if (found && expect->same_count_as)
1830*5e7646d2SAndroid Build Coastguard Worker 	  {
1831*5e7646d2SAndroid Build Coastguard Worker 	    attrptr = ippFindAttribute(response, expect->same_count_as,
1832*5e7646d2SAndroid Build Coastguard Worker 				       IPP_TAG_ZERO);
1833*5e7646d2SAndroid Build Coastguard Worker 
1834*5e7646d2SAndroid Build Coastguard Worker 	    if (!attrptr || ippGetCount(attrptr) != ippGetCount(found))
1835*5e7646d2SAndroid Build Coastguard Worker 	    {
1836*5e7646d2SAndroid Build Coastguard Worker 	      if (expect->define_no_match)
1837*5e7646d2SAndroid Build Coastguard Worker 		_ippVarsSet(data->vars, expect->define_no_match, "1");
1838*5e7646d2SAndroid Build Coastguard Worker 	      else if (!expect->define_match && !expect->define_value)
1839*5e7646d2SAndroid Build Coastguard Worker 	      {
1840*5e7646d2SAndroid Build Coastguard Worker 		if (!attrptr)
1841*5e7646d2SAndroid Build Coastguard Worker 		  add_stringf(data->errors, "EXPECTED: %s (%d values) SAME-COUNT-AS %s (not returned)", expect->name, ippGetCount(found), expect->same_count_as);
1842*5e7646d2SAndroid Build Coastguard Worker 		else if (ippGetCount(attrptr) != ippGetCount(found))
1843*5e7646d2SAndroid Build Coastguard Worker 		  add_stringf(data->errors, "EXPECTED: %s (%d values) SAME-COUNT-AS %s (%d values)", expect->name, ippGetCount(found), expect->same_count_as, ippGetCount(attrptr));
1844*5e7646d2SAndroid Build Coastguard Worker 	      }
1845*5e7646d2SAndroid Build Coastguard Worker 
1846*5e7646d2SAndroid Build Coastguard Worker 	      if (expect->repeat_no_match &&
1847*5e7646d2SAndroid Build Coastguard Worker 		  repeat_count < expect->repeat_limit)
1848*5e7646d2SAndroid Build Coastguard Worker 		repeat_test = 1;
1849*5e7646d2SAndroid Build Coastguard Worker 
1850*5e7646d2SAndroid Build Coastguard Worker 	      break;
1851*5e7646d2SAndroid Build Coastguard Worker 	    }
1852*5e7646d2SAndroid Build Coastguard Worker 	  }
1853*5e7646d2SAndroid Build Coastguard Worker 
1854*5e7646d2SAndroid Build Coastguard Worker 	  if (found && expect->display_match && (data->output == IPPTOOL_OUTPUT_TEST || (data->output == IPPTOOL_OUTPUT_PLIST && data->outfile != cupsFileStdout())))
1855*5e7646d2SAndroid Build Coastguard Worker 	    cupsFilePrintf(cupsFileStdout(), "\n%s\n\n", expect->display_match);
1856*5e7646d2SAndroid Build Coastguard Worker 
1857*5e7646d2SAndroid Build Coastguard Worker 	  if (found && expect->define_match)
1858*5e7646d2SAndroid Build Coastguard Worker 	    _ippVarsSet(data->vars, expect->define_match, "1");
1859*5e7646d2SAndroid Build Coastguard Worker 
1860*5e7646d2SAndroid Build Coastguard Worker 	  if (found && expect->define_value)
1861*5e7646d2SAndroid Build Coastguard Worker 	  {
1862*5e7646d2SAndroid Build Coastguard Worker 	    if (!expect->with_value)
1863*5e7646d2SAndroid Build Coastguard Worker 	    {
1864*5e7646d2SAndroid Build Coastguard Worker 	      int last = ippGetCount(found) - 1;
1865*5e7646d2SAndroid Build Coastguard Worker 					/* Last element in attribute */
1866*5e7646d2SAndroid Build Coastguard Worker 
1867*5e7646d2SAndroid Build Coastguard Worker 	      switch (ippGetValueTag(found))
1868*5e7646d2SAndroid Build Coastguard Worker 	      {
1869*5e7646d2SAndroid Build Coastguard Worker 		case IPP_TAG_ENUM :
1870*5e7646d2SAndroid Build Coastguard Worker 		case IPP_TAG_INTEGER :
1871*5e7646d2SAndroid Build Coastguard Worker 		    snprintf(buffer, sizeof(buffer), "%d", ippGetInteger(found, last));
1872*5e7646d2SAndroid Build Coastguard Worker 		    break;
1873*5e7646d2SAndroid Build Coastguard Worker 
1874*5e7646d2SAndroid Build Coastguard Worker 		case IPP_TAG_BOOLEAN :
1875*5e7646d2SAndroid Build Coastguard Worker 		    if (ippGetBoolean(found, last))
1876*5e7646d2SAndroid Build Coastguard Worker 		      strlcpy(buffer, "true", sizeof(buffer));
1877*5e7646d2SAndroid Build Coastguard Worker 		    else
1878*5e7646d2SAndroid Build Coastguard Worker 		      strlcpy(buffer, "false", sizeof(buffer));
1879*5e7646d2SAndroid Build Coastguard Worker 		    break;
1880*5e7646d2SAndroid Build Coastguard Worker 
1881*5e7646d2SAndroid Build Coastguard Worker 		case IPP_TAG_RESOLUTION :
1882*5e7646d2SAndroid Build Coastguard Worker 		    {
1883*5e7646d2SAndroid Build Coastguard Worker 		      int	xres,	/* Horizontal resolution */
1884*5e7646d2SAndroid Build Coastguard Worker 				yres;	/* Vertical resolution */
1885*5e7646d2SAndroid Build Coastguard Worker 		      ipp_res_t	units;	/* Resolution units */
1886*5e7646d2SAndroid Build Coastguard Worker 
1887*5e7646d2SAndroid Build Coastguard Worker 		      xres = ippGetResolution(found, last, &yres, &units);
1888*5e7646d2SAndroid Build Coastguard Worker 
1889*5e7646d2SAndroid Build Coastguard Worker 		      if (xres == yres)
1890*5e7646d2SAndroid Build Coastguard Worker 			snprintf(buffer, sizeof(buffer), "%d%s", xres, units == IPP_RES_PER_INCH ? "dpi" : "dpcm");
1891*5e7646d2SAndroid Build Coastguard Worker 		      else
1892*5e7646d2SAndroid Build Coastguard Worker 			snprintf(buffer, sizeof(buffer), "%dx%d%s", xres, yres, units == IPP_RES_PER_INCH ? "dpi" : "dpcm");
1893*5e7646d2SAndroid Build Coastguard Worker 		    }
1894*5e7646d2SAndroid Build Coastguard Worker 		    break;
1895*5e7646d2SAndroid Build Coastguard Worker 
1896*5e7646d2SAndroid Build Coastguard Worker 		case IPP_TAG_CHARSET :
1897*5e7646d2SAndroid Build Coastguard Worker 		case IPP_TAG_KEYWORD :
1898*5e7646d2SAndroid Build Coastguard Worker 		case IPP_TAG_LANGUAGE :
1899*5e7646d2SAndroid Build Coastguard Worker 		case IPP_TAG_MIMETYPE :
1900*5e7646d2SAndroid Build Coastguard Worker 		case IPP_TAG_NAME :
1901*5e7646d2SAndroid Build Coastguard Worker 		case IPP_TAG_NAMELANG :
1902*5e7646d2SAndroid Build Coastguard Worker 		case IPP_TAG_TEXT :
1903*5e7646d2SAndroid Build Coastguard Worker 		case IPP_TAG_TEXTLANG :
1904*5e7646d2SAndroid Build Coastguard Worker 		case IPP_TAG_URI :
1905*5e7646d2SAndroid Build Coastguard Worker 		case IPP_TAG_URISCHEME :
1906*5e7646d2SAndroid Build Coastguard Worker 		    strlcpy(buffer, ippGetString(found, last, NULL), sizeof(buffer));
1907*5e7646d2SAndroid Build Coastguard Worker 		    break;
1908*5e7646d2SAndroid Build Coastguard Worker 
1909*5e7646d2SAndroid Build Coastguard Worker 		default :
1910*5e7646d2SAndroid Build Coastguard Worker 		    ippAttributeString(found, buffer, sizeof(buffer));
1911*5e7646d2SAndroid Build Coastguard Worker 		    break;
1912*5e7646d2SAndroid Build Coastguard Worker 	      }
1913*5e7646d2SAndroid Build Coastguard Worker 	    }
1914*5e7646d2SAndroid Build Coastguard Worker 
1915*5e7646d2SAndroid Build Coastguard Worker 	    _ippVarsSet(data->vars, expect->define_value, buffer);
1916*5e7646d2SAndroid Build Coastguard Worker 	  }
1917*5e7646d2SAndroid Build Coastguard Worker 
1918*5e7646d2SAndroid Build Coastguard Worker 	  if (found && expect->repeat_match &&
1919*5e7646d2SAndroid Build Coastguard Worker 	      repeat_count < expect->repeat_limit)
1920*5e7646d2SAndroid Build Coastguard Worker 	    repeat_test = 1;
1921*5e7646d2SAndroid Build Coastguard Worker 	}
1922*5e7646d2SAndroid Build Coastguard Worker 	while (expect->expect_all && (found = ippFindNextAttribute(response, expect->name, IPP_TAG_ZERO)) != NULL);
1923*5e7646d2SAndroid Build Coastguard Worker       }
1924*5e7646d2SAndroid Build Coastguard Worker     }
1925*5e7646d2SAndroid Build Coastguard Worker 
1926*5e7646d2SAndroid Build Coastguard Worker    /*
1927*5e7646d2SAndroid Build Coastguard Worker     * If we are going to repeat this test, display intermediate results...
1928*5e7646d2SAndroid Build Coastguard Worker     */
1929*5e7646d2SAndroid Build Coastguard Worker 
1930*5e7646d2SAndroid Build Coastguard Worker     if (repeat_test)
1931*5e7646d2SAndroid Build Coastguard Worker     {
1932*5e7646d2SAndroid Build Coastguard Worker       if (data->output == IPPTOOL_OUTPUT_TEST || (data->output == IPPTOOL_OUTPUT_PLIST && data->outfile != cupsFileStdout()))
1933*5e7646d2SAndroid Build Coastguard Worker       {
1934*5e7646d2SAndroid Build Coastguard Worker 	cupsFilePrintf(cupsFileStdout(), "%04d]\n", repeat_count);
1935*5e7646d2SAndroid Build Coastguard Worker \
1936*5e7646d2SAndroid Build Coastguard Worker 	if (data->num_displayed > 0)
1937*5e7646d2SAndroid Build Coastguard Worker 	{
1938*5e7646d2SAndroid Build Coastguard Worker 	  for (attrptr = ippFirstAttribute(response); attrptr; attrptr = ippNextAttribute(response))
1939*5e7646d2SAndroid Build Coastguard Worker 	  {
1940*5e7646d2SAndroid Build Coastguard Worker 	    const char *attrname = ippGetName(attrptr);
1941*5e7646d2SAndroid Build Coastguard Worker 	    if (attrname)
1942*5e7646d2SAndroid Build Coastguard Worker 	    {
1943*5e7646d2SAndroid Build Coastguard Worker 	      for (i = 0; i < data->num_displayed; i ++)
1944*5e7646d2SAndroid Build Coastguard Worker 	      {
1945*5e7646d2SAndroid Build Coastguard Worker 		if (!strcmp(data->displayed[i], attrname))
1946*5e7646d2SAndroid Build Coastguard Worker 		{
1947*5e7646d2SAndroid Build Coastguard Worker 		  print_attr(cupsFileStdout(), IPPTOOL_OUTPUT_TEST, attrptr, NULL);
1948*5e7646d2SAndroid Build Coastguard Worker 		  break;
1949*5e7646d2SAndroid Build Coastguard Worker 		}
1950*5e7646d2SAndroid Build Coastguard Worker 	      }
1951*5e7646d2SAndroid Build Coastguard Worker 	    }
1952*5e7646d2SAndroid Build Coastguard Worker 	  }
1953*5e7646d2SAndroid Build Coastguard Worker 	}
1954*5e7646d2SAndroid Build Coastguard Worker       }
1955*5e7646d2SAndroid Build Coastguard Worker 
1956*5e7646d2SAndroid Build Coastguard Worker       if (data->output == IPPTOOL_OUTPUT_TEST || (data->output == IPPTOOL_OUTPUT_PLIST && data->outfile != cupsFileStdout()))
1957*5e7646d2SAndroid Build Coastguard Worker       {
1958*5e7646d2SAndroid Build Coastguard Worker 	cupsFilePrintf(cupsFileStdout(), "    %-68.68s [", data->name);
1959*5e7646d2SAndroid Build Coastguard Worker       }
1960*5e7646d2SAndroid Build Coastguard Worker 
1961*5e7646d2SAndroid Build Coastguard Worker       ippDelete(response);
1962*5e7646d2SAndroid Build Coastguard Worker       response = NULL;
1963*5e7646d2SAndroid Build Coastguard Worker     }
1964*5e7646d2SAndroid Build Coastguard Worker   }
1965*5e7646d2SAndroid Build Coastguard Worker   while (repeat_test);
1966*5e7646d2SAndroid Build Coastguard Worker 
1967*5e7646d2SAndroid Build Coastguard Worker   ippDelete(request);
1968*5e7646d2SAndroid Build Coastguard Worker 
1969*5e7646d2SAndroid Build Coastguard Worker   request = NULL;
1970*5e7646d2SAndroid Build Coastguard Worker 
1971*5e7646d2SAndroid Build Coastguard Worker   if (cupsArrayCount(data->errors) > 0)
1972*5e7646d2SAndroid Build Coastguard Worker     data->prev_pass = data->pass = 0;
1973*5e7646d2SAndroid Build Coastguard Worker 
1974*5e7646d2SAndroid Build Coastguard Worker   if (data->prev_pass)
1975*5e7646d2SAndroid Build Coastguard Worker     data->pass_count ++;
1976*5e7646d2SAndroid Build Coastguard Worker   else
1977*5e7646d2SAndroid Build Coastguard Worker     data->fail_count ++;
1978*5e7646d2SAndroid Build Coastguard Worker 
1979*5e7646d2SAndroid Build Coastguard Worker   if (data->output == IPPTOOL_OUTPUT_PLIST)
1980*5e7646d2SAndroid Build Coastguard Worker   {
1981*5e7646d2SAndroid Build Coastguard Worker     cupsFilePuts(data->outfile, "<key>Successful</key>\n");
1982*5e7646d2SAndroid Build Coastguard Worker     cupsFilePuts(data->outfile, data->prev_pass ? "<true />\n" : "<false />\n");
1983*5e7646d2SAndroid Build Coastguard Worker     cupsFilePuts(data->outfile, "<key>StatusCode</key>\n");
1984*5e7646d2SAndroid Build Coastguard Worker     print_xml_string(data->outfile, "string", ippErrorString(cupsLastError()));
1985*5e7646d2SAndroid Build Coastguard Worker     cupsFilePuts(data->outfile, "<key>ResponseAttributes</key>\n");
1986*5e7646d2SAndroid Build Coastguard Worker     cupsFilePuts(data->outfile, "<array>\n");
1987*5e7646d2SAndroid Build Coastguard Worker     cupsFilePuts(data->outfile, "<dict>\n");
1988*5e7646d2SAndroid Build Coastguard Worker     for (attrptr = ippFirstAttribute(response), group = ippGetGroupTag(attrptr);
1989*5e7646d2SAndroid Build Coastguard Worker 	 attrptr;
1990*5e7646d2SAndroid Build Coastguard Worker 	 attrptr = ippNextAttribute(response))
1991*5e7646d2SAndroid Build Coastguard Worker       print_attr(data->outfile, data->output, attrptr, &group);
1992*5e7646d2SAndroid Build Coastguard Worker     cupsFilePuts(data->outfile, "</dict>\n");
1993*5e7646d2SAndroid Build Coastguard Worker     cupsFilePuts(data->outfile, "</array>\n");
1994*5e7646d2SAndroid Build Coastguard Worker   }
1995*5e7646d2SAndroid Build Coastguard Worker   else if (data->output == IPPTOOL_OUTPUT_IPPSERVER && response)
1996*5e7646d2SAndroid Build Coastguard Worker   {
1997*5e7646d2SAndroid Build Coastguard Worker     for (attrptr = ippFirstAttribute(response); attrptr; attrptr = ippNextAttribute(response))
1998*5e7646d2SAndroid Build Coastguard Worker     {
1999*5e7646d2SAndroid Build Coastguard Worker       if (!ippGetName(attrptr) || ippGetGroupTag(attrptr) != IPP_TAG_PRINTER)
2000*5e7646d2SAndroid Build Coastguard Worker 	continue;
2001*5e7646d2SAndroid Build Coastguard Worker 
2002*5e7646d2SAndroid Build Coastguard Worker       print_ippserver_attr(data, attrptr, 0);
2003*5e7646d2SAndroid Build Coastguard Worker     }
2004*5e7646d2SAndroid Build Coastguard Worker   }
2005*5e7646d2SAndroid Build Coastguard Worker 
2006*5e7646d2SAndroid Build Coastguard Worker   if (data->output == IPPTOOL_OUTPUT_TEST || (data->output == IPPTOOL_OUTPUT_PLIST && data->outfile != cupsFileStdout()))
2007*5e7646d2SAndroid Build Coastguard Worker   {
2008*5e7646d2SAndroid Build Coastguard Worker     cupsFilePuts(cupsFileStdout(), data->prev_pass ? "PASS]\n" : "FAIL]\n");
2009*5e7646d2SAndroid Build Coastguard Worker 
2010*5e7646d2SAndroid Build Coastguard Worker     if (!data->prev_pass || (data->verbosity && response))
2011*5e7646d2SAndroid Build Coastguard Worker     {
2012*5e7646d2SAndroid Build Coastguard Worker       cupsFilePrintf(cupsFileStdout(), "        RECEIVED: %lu bytes in response\n", (unsigned long)ippLength(response));
2013*5e7646d2SAndroid Build Coastguard Worker       cupsFilePrintf(cupsFileStdout(), "        status-code = %s (%s)\n", ippErrorString(cupsLastError()), cupsLastErrorString());
2014*5e7646d2SAndroid Build Coastguard Worker 
2015*5e7646d2SAndroid Build Coastguard Worker       if (data->verbosity && response)
2016*5e7646d2SAndroid Build Coastguard Worker       {
2017*5e7646d2SAndroid Build Coastguard Worker 	for (attrptr = ippFirstAttribute(response); attrptr; attrptr = ippNextAttribute(response))
2018*5e7646d2SAndroid Build Coastguard Worker 	  print_attr(cupsFileStdout(), IPPTOOL_OUTPUT_TEST, attrptr, NULL);
2019*5e7646d2SAndroid Build Coastguard Worker       }
2020*5e7646d2SAndroid Build Coastguard Worker     }
2021*5e7646d2SAndroid Build Coastguard Worker   }
2022*5e7646d2SAndroid Build Coastguard Worker   else if (!data->prev_pass && data->output != IPPTOOL_OUTPUT_QUIET)
2023*5e7646d2SAndroid Build Coastguard Worker     fprintf(stderr, "%s\n", cupsLastErrorString());
2024*5e7646d2SAndroid Build Coastguard Worker 
2025*5e7646d2SAndroid Build Coastguard Worker   if (data->prev_pass && data->output >= IPPTOOL_OUTPUT_LIST && !data->verbosity && data->num_displayed > 0)
2026*5e7646d2SAndroid Build Coastguard Worker   {
2027*5e7646d2SAndroid Build Coastguard Worker     size_t	width;			/* Length of value */
2028*5e7646d2SAndroid Build Coastguard Worker 
2029*5e7646d2SAndroid Build Coastguard Worker     for (i = 0; i < data->num_displayed; i ++)
2030*5e7646d2SAndroid Build Coastguard Worker     {
2031*5e7646d2SAndroid Build Coastguard Worker       widths[i] = strlen(data->displayed[i]);
2032*5e7646d2SAndroid Build Coastguard Worker 
2033*5e7646d2SAndroid Build Coastguard Worker       for (attrptr = ippFindAttribute(response, data->displayed[i], IPP_TAG_ZERO);
2034*5e7646d2SAndroid Build Coastguard Worker 	   attrptr;
2035*5e7646d2SAndroid Build Coastguard Worker 	   attrptr = ippFindNextAttribute(response, data->displayed[i], IPP_TAG_ZERO))
2036*5e7646d2SAndroid Build Coastguard Worker       {
2037*5e7646d2SAndroid Build Coastguard Worker 	width = ippAttributeString(attrptr, NULL, 0);
2038*5e7646d2SAndroid Build Coastguard Worker 	if (width > widths[i])
2039*5e7646d2SAndroid Build Coastguard Worker 	  widths[i] = width;
2040*5e7646d2SAndroid Build Coastguard Worker       }
2041*5e7646d2SAndroid Build Coastguard Worker     }
2042*5e7646d2SAndroid Build Coastguard Worker 
2043*5e7646d2SAndroid Build Coastguard Worker     if (data->output == IPPTOOL_OUTPUT_CSV)
2044*5e7646d2SAndroid Build Coastguard Worker       print_csv(data, NULL, NULL, data->num_displayed, data->displayed, widths);
2045*5e7646d2SAndroid Build Coastguard Worker     else
2046*5e7646d2SAndroid Build Coastguard Worker       print_line(data, NULL, NULL, data->num_displayed, data->displayed, widths);
2047*5e7646d2SAndroid Build Coastguard Worker 
2048*5e7646d2SAndroid Build Coastguard Worker     attrptr = ippFirstAttribute(response);
2049*5e7646d2SAndroid Build Coastguard Worker 
2050*5e7646d2SAndroid Build Coastguard Worker     while (attrptr)
2051*5e7646d2SAndroid Build Coastguard Worker     {
2052*5e7646d2SAndroid Build Coastguard Worker       while (attrptr && ippGetGroupTag(attrptr) <= IPP_TAG_OPERATION)
2053*5e7646d2SAndroid Build Coastguard Worker 	attrptr = ippNextAttribute(response);
2054*5e7646d2SAndroid Build Coastguard Worker 
2055*5e7646d2SAndroid Build Coastguard Worker       if (attrptr)
2056*5e7646d2SAndroid Build Coastguard Worker       {
2057*5e7646d2SAndroid Build Coastguard Worker 	if (data->output == IPPTOOL_OUTPUT_CSV)
2058*5e7646d2SAndroid Build Coastguard Worker 	  attrptr = print_csv(data, response, attrptr, data->num_displayed, data->displayed, widths);
2059*5e7646d2SAndroid Build Coastguard Worker 	else
2060*5e7646d2SAndroid Build Coastguard Worker 	  attrptr = print_line(data, response, attrptr, data->num_displayed, data->displayed, widths);
2061*5e7646d2SAndroid Build Coastguard Worker 
2062*5e7646d2SAndroid Build Coastguard Worker 	while (attrptr && ippGetGroupTag(attrptr) > IPP_TAG_OPERATION)
2063*5e7646d2SAndroid Build Coastguard Worker 	  attrptr = ippNextAttribute(response);
2064*5e7646d2SAndroid Build Coastguard Worker       }
2065*5e7646d2SAndroid Build Coastguard Worker     }
2066*5e7646d2SAndroid Build Coastguard Worker   }
2067*5e7646d2SAndroid Build Coastguard Worker   else if (!data->prev_pass)
2068*5e7646d2SAndroid Build Coastguard Worker   {
2069*5e7646d2SAndroid Build Coastguard Worker     if (data->output == IPPTOOL_OUTPUT_PLIST)
2070*5e7646d2SAndroid Build Coastguard Worker     {
2071*5e7646d2SAndroid Build Coastguard Worker       cupsFilePuts(data->outfile, "<key>Errors</key>\n");
2072*5e7646d2SAndroid Build Coastguard Worker       cupsFilePuts(data->outfile, "<array>\n");
2073*5e7646d2SAndroid Build Coastguard Worker 
2074*5e7646d2SAndroid Build Coastguard Worker       for (error = (char *)cupsArrayFirst(data->errors);
2075*5e7646d2SAndroid Build Coastguard Worker 	   error;
2076*5e7646d2SAndroid Build Coastguard Worker 	   error = (char *)cupsArrayNext(data->errors))
2077*5e7646d2SAndroid Build Coastguard Worker 	print_xml_string(data->outfile, "string", error);
2078*5e7646d2SAndroid Build Coastguard Worker 
2079*5e7646d2SAndroid Build Coastguard Worker       cupsFilePuts(data->outfile, "</array>\n");
2080*5e7646d2SAndroid Build Coastguard Worker     }
2081*5e7646d2SAndroid Build Coastguard Worker 
2082*5e7646d2SAndroid Build Coastguard Worker     if (data->output == IPPTOOL_OUTPUT_TEST || (data->output == IPPTOOL_OUTPUT_PLIST && data->outfile != cupsFileStdout()))
2083*5e7646d2SAndroid Build Coastguard Worker     {
2084*5e7646d2SAndroid Build Coastguard Worker       for (error = (char *)cupsArrayFirst(data->errors);
2085*5e7646d2SAndroid Build Coastguard Worker 	   error;
2086*5e7646d2SAndroid Build Coastguard Worker 	   error = (char *)cupsArrayNext(data->errors))
2087*5e7646d2SAndroid Build Coastguard Worker 	cupsFilePrintf(cupsFileStdout(), "        %s\n", error);
2088*5e7646d2SAndroid Build Coastguard Worker     }
2089*5e7646d2SAndroid Build Coastguard Worker   }
2090*5e7646d2SAndroid Build Coastguard Worker 
2091*5e7646d2SAndroid Build Coastguard Worker   if (data->num_displayed > 0 && !data->verbosity && response && (data->output == IPPTOOL_OUTPUT_TEST || (data->output == IPPTOOL_OUTPUT_PLIST && data->outfile != cupsFileStdout())))
2092*5e7646d2SAndroid Build Coastguard Worker   {
2093*5e7646d2SAndroid Build Coastguard Worker     for (attrptr = ippFirstAttribute(response); attrptr; attrptr = ippNextAttribute(response))
2094*5e7646d2SAndroid Build Coastguard Worker     {
2095*5e7646d2SAndroid Build Coastguard Worker       if (ippGetName(attrptr))
2096*5e7646d2SAndroid Build Coastguard Worker       {
2097*5e7646d2SAndroid Build Coastguard Worker 	for (i = 0; i < data->num_displayed; i ++)
2098*5e7646d2SAndroid Build Coastguard Worker 	{
2099*5e7646d2SAndroid Build Coastguard Worker 	  if (!strcmp(data->displayed[i], ippGetName(attrptr)))
2100*5e7646d2SAndroid Build Coastguard Worker 	  {
2101*5e7646d2SAndroid Build Coastguard Worker 	    print_attr(data->outfile, data->output, attrptr, NULL);
2102*5e7646d2SAndroid Build Coastguard Worker 	    break;
2103*5e7646d2SAndroid Build Coastguard Worker 	  }
2104*5e7646d2SAndroid Build Coastguard Worker 	}
2105*5e7646d2SAndroid Build Coastguard Worker       }
2106*5e7646d2SAndroid Build Coastguard Worker     }
2107*5e7646d2SAndroid Build Coastguard Worker   }
2108*5e7646d2SAndroid Build Coastguard Worker 
2109*5e7646d2SAndroid Build Coastguard Worker   skip_error:
2110*5e7646d2SAndroid Build Coastguard Worker 
2111*5e7646d2SAndroid Build Coastguard Worker   if (data->monitor_thread)
2112*5e7646d2SAndroid Build Coastguard Worker   {
2113*5e7646d2SAndroid Build Coastguard Worker     data->monitor_done = 1;
2114*5e7646d2SAndroid Build Coastguard Worker     _cupsThreadWait(data->monitor_thread);
2115*5e7646d2SAndroid Build Coastguard Worker   }
2116*5e7646d2SAndroid Build Coastguard Worker 
2117*5e7646d2SAndroid Build Coastguard Worker   if (data->output == IPPTOOL_OUTPUT_PLIST)
2118*5e7646d2SAndroid Build Coastguard Worker     cupsFilePuts(data->outfile, "</dict>\n");
2119*5e7646d2SAndroid Build Coastguard Worker 
2120*5e7646d2SAndroid Build Coastguard Worker   ippDelete(response);
2121*5e7646d2SAndroid Build Coastguard Worker   response = NULL;
2122*5e7646d2SAndroid Build Coastguard Worker 
2123*5e7646d2SAndroid Build Coastguard Worker   for (i = 0; i < data->num_statuses; i ++)
2124*5e7646d2SAndroid Build Coastguard Worker   {
2125*5e7646d2SAndroid Build Coastguard Worker     free(data->statuses[i].if_defined);
2126*5e7646d2SAndroid Build Coastguard Worker     free(data->statuses[i].if_not_defined);
2127*5e7646d2SAndroid Build Coastguard Worker     free(data->statuses[i].define_match);
2128*5e7646d2SAndroid Build Coastguard Worker     free(data->statuses[i].define_no_match);
2129*5e7646d2SAndroid Build Coastguard Worker   }
2130*5e7646d2SAndroid Build Coastguard Worker   data->num_statuses = 0;
2131*5e7646d2SAndroid Build Coastguard Worker 
2132*5e7646d2SAndroid Build Coastguard Worker   for (i = data->num_expects, expect = data->expects; i > 0; i --, expect ++)
2133*5e7646d2SAndroid Build Coastguard Worker   {
2134*5e7646d2SAndroid Build Coastguard Worker     free(expect->name);
2135*5e7646d2SAndroid Build Coastguard Worker     free(expect->of_type);
2136*5e7646d2SAndroid Build Coastguard Worker     free(expect->same_count_as);
2137*5e7646d2SAndroid Build Coastguard Worker     free(expect->if_defined);
2138*5e7646d2SAndroid Build Coastguard Worker     free(expect->if_not_defined);
2139*5e7646d2SAndroid Build Coastguard Worker     free(expect->with_value);
2140*5e7646d2SAndroid Build Coastguard Worker     free(expect->define_match);
2141*5e7646d2SAndroid Build Coastguard Worker     free(expect->define_no_match);
2142*5e7646d2SAndroid Build Coastguard Worker     free(expect->define_value);
2143*5e7646d2SAndroid Build Coastguard Worker     free(expect->display_match);
2144*5e7646d2SAndroid Build Coastguard Worker   }
2145*5e7646d2SAndroid Build Coastguard Worker   data->num_expects = 0;
2146*5e7646d2SAndroid Build Coastguard Worker 
2147*5e7646d2SAndroid Build Coastguard Worker   for (i = 0; i < data->num_displayed; i ++)
2148*5e7646d2SAndroid Build Coastguard Worker     free(data->displayed[i]);
2149*5e7646d2SAndroid Build Coastguard Worker   data->num_displayed = 0;
2150*5e7646d2SAndroid Build Coastguard Worker 
2151*5e7646d2SAndroid Build Coastguard Worker   free(data->monitor_uri);
2152*5e7646d2SAndroid Build Coastguard Worker   data->monitor_uri = NULL;
2153*5e7646d2SAndroid Build Coastguard Worker 
2154*5e7646d2SAndroid Build Coastguard Worker   for (i = data->num_monitor_expects, expect = data->monitor_expects; i > 0; i --, expect ++)
2155*5e7646d2SAndroid Build Coastguard Worker   {
2156*5e7646d2SAndroid Build Coastguard Worker     free(expect->name);
2157*5e7646d2SAndroid Build Coastguard Worker     free(expect->of_type);
2158*5e7646d2SAndroid Build Coastguard Worker     free(expect->same_count_as);
2159*5e7646d2SAndroid Build Coastguard Worker     free(expect->if_defined);
2160*5e7646d2SAndroid Build Coastguard Worker     free(expect->if_not_defined);
2161*5e7646d2SAndroid Build Coastguard Worker     free(expect->with_value);
2162*5e7646d2SAndroid Build Coastguard Worker     free(expect->define_match);
2163*5e7646d2SAndroid Build Coastguard Worker     free(expect->define_no_match);
2164*5e7646d2SAndroid Build Coastguard Worker     free(expect->define_value);
2165*5e7646d2SAndroid Build Coastguard Worker     free(expect->display_match);
2166*5e7646d2SAndroid Build Coastguard Worker   }
2167*5e7646d2SAndroid Build Coastguard Worker   data->num_monitor_expects = 0;
2168*5e7646d2SAndroid Build Coastguard Worker 
2169*5e7646d2SAndroid Build Coastguard Worker   return (data->ignore_errors || data->prev_pass);
2170*5e7646d2SAndroid Build Coastguard Worker }
2171*5e7646d2SAndroid Build Coastguard Worker 
2172*5e7646d2SAndroid Build Coastguard Worker 
2173*5e7646d2SAndroid Build Coastguard Worker /*
2174*5e7646d2SAndroid Build Coastguard Worker  * 'do_tests()' - Do tests as specified in the test file.
2175*5e7646d2SAndroid Build Coastguard Worker  */
2176*5e7646d2SAndroid Build Coastguard Worker 
2177*5e7646d2SAndroid Build Coastguard Worker static int				/* O - 1 on success, 0 on failure */
do_tests(const char * testfile,ipptool_test_t * data)2178*5e7646d2SAndroid Build Coastguard Worker do_tests(const char     *testfile,	/* I - Test file to use */
2179*5e7646d2SAndroid Build Coastguard Worker          ipptool_test_t *data)		/* I - Test data */
2180*5e7646d2SAndroid Build Coastguard Worker {
2181*5e7646d2SAndroid Build Coastguard Worker   http_encryption_t encryption;		/* Encryption mode */
2182*5e7646d2SAndroid Build Coastguard Worker 
2183*5e7646d2SAndroid Build Coastguard Worker 
2184*5e7646d2SAndroid Build Coastguard Worker  /*
2185*5e7646d2SAndroid Build Coastguard Worker   * Connect to the printer/server...
2186*5e7646d2SAndroid Build Coastguard Worker   */
2187*5e7646d2SAndroid Build Coastguard Worker 
2188*5e7646d2SAndroid Build Coastguard Worker   if (!_cups_strcasecmp(data->vars->scheme, "https") || !_cups_strcasecmp(data->vars->scheme, "ipps") || data->vars->port == 443)
2189*5e7646d2SAndroid Build Coastguard Worker     encryption = HTTP_ENCRYPTION_ALWAYS;
2190*5e7646d2SAndroid Build Coastguard Worker   else
2191*5e7646d2SAndroid Build Coastguard Worker     encryption = data->encryption;
2192*5e7646d2SAndroid Build Coastguard Worker 
2193*5e7646d2SAndroid Build Coastguard Worker   if ((data->http = httpConnect2(data->vars->host, data->vars->port, NULL, data->family, encryption, 1, 30000, NULL)) == NULL)
2194*5e7646d2SAndroid Build Coastguard Worker   {
2195*5e7646d2SAndroid Build Coastguard Worker     print_fatal_error(data, "Unable to connect to \"%s\" on port %d - %s", data->vars->host, data->vars->port, cupsLastErrorString());
2196*5e7646d2SAndroid Build Coastguard Worker     return (0);
2197*5e7646d2SAndroid Build Coastguard Worker   }
2198*5e7646d2SAndroid Build Coastguard Worker 
2199*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_LIBZ
2200*5e7646d2SAndroid Build Coastguard Worker   httpSetDefaultField(data->http, HTTP_FIELD_ACCEPT_ENCODING, "deflate, gzip, identity");
2201*5e7646d2SAndroid Build Coastguard Worker #else
2202*5e7646d2SAndroid Build Coastguard Worker   httpSetDefaultField(data->http, HTTP_FIELD_ACCEPT_ENCODING, "identity");
2203*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_LIBZ */
2204*5e7646d2SAndroid Build Coastguard Worker 
2205*5e7646d2SAndroid Build Coastguard Worker   if (data->timeout > 0.0)
2206*5e7646d2SAndroid Build Coastguard Worker     httpSetTimeout(data->http, data->timeout, timeout_cb, NULL);
2207*5e7646d2SAndroid Build Coastguard Worker 
2208*5e7646d2SAndroid Build Coastguard Worker  /*
2209*5e7646d2SAndroid Build Coastguard Worker   * Run tests...
2210*5e7646d2SAndroid Build Coastguard Worker   */
2211*5e7646d2SAndroid Build Coastguard Worker 
2212*5e7646d2SAndroid Build Coastguard Worker   _ippFileParse(data->vars, testfile, (void *)data);
2213*5e7646d2SAndroid Build Coastguard Worker 
2214*5e7646d2SAndroid Build Coastguard Worker  /*
2215*5e7646d2SAndroid Build Coastguard Worker   * Close connection and return...
2216*5e7646d2SAndroid Build Coastguard Worker   */
2217*5e7646d2SAndroid Build Coastguard Worker 
2218*5e7646d2SAndroid Build Coastguard Worker   httpClose(data->http);
2219*5e7646d2SAndroid Build Coastguard Worker   data->http = NULL;
2220*5e7646d2SAndroid Build Coastguard Worker 
2221*5e7646d2SAndroid Build Coastguard Worker   return (data->pass);
2222*5e7646d2SAndroid Build Coastguard Worker }
2223*5e7646d2SAndroid Build Coastguard Worker 
2224*5e7646d2SAndroid Build Coastguard Worker 
2225*5e7646d2SAndroid Build Coastguard Worker /*
2226*5e7646d2SAndroid Build Coastguard Worker  * 'error_cb()' - Print/add an error message.
2227*5e7646d2SAndroid Build Coastguard Worker  */
2228*5e7646d2SAndroid Build Coastguard Worker 
2229*5e7646d2SAndroid Build Coastguard Worker static int				/* O - 1 to continue, 0 to stop */
error_cb(_ipp_file_t * f,ipptool_test_t * data,const char * error)2230*5e7646d2SAndroid Build Coastguard Worker error_cb(_ipp_file_t      *f,		/* I - IPP file data */
2231*5e7646d2SAndroid Build Coastguard Worker          ipptool_test_t *data,	/* I - Test data */
2232*5e7646d2SAndroid Build Coastguard Worker          const char       *error)	/* I - Error message */
2233*5e7646d2SAndroid Build Coastguard Worker {
2234*5e7646d2SAndroid Build Coastguard Worker   (void)f;
2235*5e7646d2SAndroid Build Coastguard Worker 
2236*5e7646d2SAndroid Build Coastguard Worker   print_fatal_error(data, "%s", error);
2237*5e7646d2SAndroid Build Coastguard Worker 
2238*5e7646d2SAndroid Build Coastguard Worker   return (1);
2239*5e7646d2SAndroid Build Coastguard Worker }
2240*5e7646d2SAndroid Build Coastguard Worker 
2241*5e7646d2SAndroid Build Coastguard Worker 
2242*5e7646d2SAndroid Build Coastguard Worker /*
2243*5e7646d2SAndroid Build Coastguard Worker  * 'expect_matches()' - Return true if the tag matches the specification.
2244*5e7646d2SAndroid Build Coastguard Worker  */
2245*5e7646d2SAndroid Build Coastguard Worker 
2246*5e7646d2SAndroid Build Coastguard Worker static int				/* O - 1 if matches, 0 otherwise */
expect_matches(ipptool_expect_t * expect,ipp_attribute_t * attr)2247*5e7646d2SAndroid Build Coastguard Worker expect_matches(
2248*5e7646d2SAndroid Build Coastguard Worker     ipptool_expect_t *expect,		/* I - Expected attribute */
2249*5e7646d2SAndroid Build Coastguard Worker     ipp_attribute_t  *attr)		/* I - Attribute */
2250*5e7646d2SAndroid Build Coastguard Worker {
2251*5e7646d2SAndroid Build Coastguard Worker   int		i,			/* Looping var */
2252*5e7646d2SAndroid Build Coastguard Worker 		count,			/* Number of values */
2253*5e7646d2SAndroid Build Coastguard Worker 		match;			/* Match? */
2254*5e7646d2SAndroid Build Coastguard Worker   char		*of_type,		/* Type name to match */
2255*5e7646d2SAndroid Build Coastguard Worker 		*paren,			/* Pointer to opening parenthesis */
2256*5e7646d2SAndroid Build Coastguard Worker 		*next,			/* Next name to match */
2257*5e7646d2SAndroid Build Coastguard Worker 		sep;			/* Separator character */
2258*5e7646d2SAndroid Build Coastguard Worker   ipp_tag_t	value_tag;		/* Syntax/value tag */
2259*5e7646d2SAndroid Build Coastguard Worker   int		lower, upper;		/* Lower and upper bounds for syntax */
2260*5e7646d2SAndroid Build Coastguard Worker 
2261*5e7646d2SAndroid Build Coastguard Worker 
2262*5e7646d2SAndroid Build Coastguard Worker  /*
2263*5e7646d2SAndroid Build Coastguard Worker   * If we don't expect a particular type, return immediately...
2264*5e7646d2SAndroid Build Coastguard Worker   */
2265*5e7646d2SAndroid Build Coastguard Worker 
2266*5e7646d2SAndroid Build Coastguard Worker   if (!expect->of_type)
2267*5e7646d2SAndroid Build Coastguard Worker     return (1);
2268*5e7646d2SAndroid Build Coastguard Worker 
2269*5e7646d2SAndroid Build Coastguard Worker  /*
2270*5e7646d2SAndroid Build Coastguard Worker   * Parse the "of_type" value since the string can contain multiple attribute
2271*5e7646d2SAndroid Build Coastguard Worker   * types separated by "," or "|"...
2272*5e7646d2SAndroid Build Coastguard Worker   */
2273*5e7646d2SAndroid Build Coastguard Worker 
2274*5e7646d2SAndroid Build Coastguard Worker   value_tag = ippGetValueTag(attr);
2275*5e7646d2SAndroid Build Coastguard Worker   count     = ippGetCount(attr);
2276*5e7646d2SAndroid Build Coastguard Worker 
2277*5e7646d2SAndroid Build Coastguard Worker   for (of_type = expect->of_type, match = 0; !match && *of_type; of_type = next)
2278*5e7646d2SAndroid Build Coastguard Worker   {
2279*5e7646d2SAndroid Build Coastguard Worker    /*
2280*5e7646d2SAndroid Build Coastguard Worker     * Find the next separator, and set it (temporarily) to nul if present.
2281*5e7646d2SAndroid Build Coastguard Worker     */
2282*5e7646d2SAndroid Build Coastguard Worker 
2283*5e7646d2SAndroid Build Coastguard Worker     for (next = of_type; *next && *next != '|' && *next != ','; next ++);
2284*5e7646d2SAndroid Build Coastguard Worker 
2285*5e7646d2SAndroid Build Coastguard Worker     if ((sep = *next) != '\0')
2286*5e7646d2SAndroid Build Coastguard Worker       *next = '\0';
2287*5e7646d2SAndroid Build Coastguard Worker 
2288*5e7646d2SAndroid Build Coastguard Worker    /*
2289*5e7646d2SAndroid Build Coastguard Worker     * Support some meta-types to make it easier to write the test file.
2290*5e7646d2SAndroid Build Coastguard Worker     */
2291*5e7646d2SAndroid Build Coastguard Worker 
2292*5e7646d2SAndroid Build Coastguard Worker     if ((paren = strchr(of_type, '(')) != NULL)
2293*5e7646d2SAndroid Build Coastguard Worker     {
2294*5e7646d2SAndroid Build Coastguard Worker       char *ptr;			// Pointer into syntax string
2295*5e7646d2SAndroid Build Coastguard Worker 
2296*5e7646d2SAndroid Build Coastguard Worker       *paren = '\0';
2297*5e7646d2SAndroid Build Coastguard Worker 
2298*5e7646d2SAndroid Build Coastguard Worker       if (!strncmp(paren + 1, "MIN:", 4))
2299*5e7646d2SAndroid Build Coastguard Worker       {
2300*5e7646d2SAndroid Build Coastguard Worker         lower = INT_MIN;
2301*5e7646d2SAndroid Build Coastguard Worker         ptr   = paren + 5;
2302*5e7646d2SAndroid Build Coastguard Worker       }
2303*5e7646d2SAndroid Build Coastguard Worker       else if ((ptr = strchr(paren + 1, ':')) != NULL)
2304*5e7646d2SAndroid Build Coastguard Worker       {
2305*5e7646d2SAndroid Build Coastguard Worker         lower = atoi(paren + 1);
2306*5e7646d2SAndroid Build Coastguard Worker       }
2307*5e7646d2SAndroid Build Coastguard Worker       else
2308*5e7646d2SAndroid Build Coastguard Worker       {
2309*5e7646d2SAndroid Build Coastguard Worker         lower = 0;
2310*5e7646d2SAndroid Build Coastguard Worker         ptr   = paren + 1;
2311*5e7646d2SAndroid Build Coastguard Worker       }
2312*5e7646d2SAndroid Build Coastguard Worker 
2313*5e7646d2SAndroid Build Coastguard Worker       if (!strcmp(ptr, "MAX)"))
2314*5e7646d2SAndroid Build Coastguard Worker         upper = INT_MAX;
2315*5e7646d2SAndroid Build Coastguard Worker       else
2316*5e7646d2SAndroid Build Coastguard Worker         upper = atoi(ptr);
2317*5e7646d2SAndroid Build Coastguard Worker     }
2318*5e7646d2SAndroid Build Coastguard Worker     else
2319*5e7646d2SAndroid Build Coastguard Worker     {
2320*5e7646d2SAndroid Build Coastguard Worker       lower = INT_MIN;
2321*5e7646d2SAndroid Build Coastguard Worker       upper = INT_MAX;
2322*5e7646d2SAndroid Build Coastguard Worker     }
2323*5e7646d2SAndroid Build Coastguard Worker 
2324*5e7646d2SAndroid Build Coastguard Worker     if (!strcmp(of_type, "text"))
2325*5e7646d2SAndroid Build Coastguard Worker     {
2326*5e7646d2SAndroid Build Coastguard Worker       if (upper == INT_MAX)
2327*5e7646d2SAndroid Build Coastguard Worker         upper = 1023;
2328*5e7646d2SAndroid Build Coastguard Worker 
2329*5e7646d2SAndroid Build Coastguard Worker       if (value_tag == IPP_TAG_TEXTLANG || value_tag == IPP_TAG_TEXT)
2330*5e7646d2SAndroid Build Coastguard Worker       {
2331*5e7646d2SAndroid Build Coastguard Worker         for (i = 0; i < count; i ++)
2332*5e7646d2SAndroid Build Coastguard Worker 	{
2333*5e7646d2SAndroid Build Coastguard Worker 	  if (strlen(ippGetString(attr, i, NULL)) > (size_t)upper)
2334*5e7646d2SAndroid Build Coastguard Worker 	    break;
2335*5e7646d2SAndroid Build Coastguard Worker 	}
2336*5e7646d2SAndroid Build Coastguard Worker 
2337*5e7646d2SAndroid Build Coastguard Worker 	match = (i == count);
2338*5e7646d2SAndroid Build Coastguard Worker       }
2339*5e7646d2SAndroid Build Coastguard Worker     }
2340*5e7646d2SAndroid Build Coastguard Worker     else if (!strcmp(of_type, "name"))
2341*5e7646d2SAndroid Build Coastguard Worker     {
2342*5e7646d2SAndroid Build Coastguard Worker       if (upper == INT_MAX)
2343*5e7646d2SAndroid Build Coastguard Worker         upper = 255;
2344*5e7646d2SAndroid Build Coastguard Worker 
2345*5e7646d2SAndroid Build Coastguard Worker       if (value_tag == IPP_TAG_NAMELANG || value_tag == IPP_TAG_NAME)
2346*5e7646d2SAndroid Build Coastguard Worker       {
2347*5e7646d2SAndroid Build Coastguard Worker         for (i = 0; i < count; i ++)
2348*5e7646d2SAndroid Build Coastguard Worker 	{
2349*5e7646d2SAndroid Build Coastguard Worker 	  if (strlen(ippGetString(attr, i, NULL)) > (size_t)upper)
2350*5e7646d2SAndroid Build Coastguard Worker 	    break;
2351*5e7646d2SAndroid Build Coastguard Worker 	}
2352*5e7646d2SAndroid Build Coastguard Worker 
2353*5e7646d2SAndroid Build Coastguard Worker 	match = (i == count);
2354*5e7646d2SAndroid Build Coastguard Worker       }
2355*5e7646d2SAndroid Build Coastguard Worker     }
2356*5e7646d2SAndroid Build Coastguard Worker     else if (!strcmp(of_type, "collection"))
2357*5e7646d2SAndroid Build Coastguard Worker     {
2358*5e7646d2SAndroid Build Coastguard Worker       match = value_tag == IPP_TAG_BEGIN_COLLECTION;
2359*5e7646d2SAndroid Build Coastguard Worker     }
2360*5e7646d2SAndroid Build Coastguard Worker     else if (value_tag == ippTagValue(of_type))
2361*5e7646d2SAndroid Build Coastguard Worker     {
2362*5e7646d2SAndroid Build Coastguard Worker       switch (value_tag)
2363*5e7646d2SAndroid Build Coastguard Worker       {
2364*5e7646d2SAndroid Build Coastguard Worker         case IPP_TAG_KEYWORD :
2365*5e7646d2SAndroid Build Coastguard Worker         case IPP_TAG_URI :
2366*5e7646d2SAndroid Build Coastguard Worker             if (upper == INT_MAX)
2367*5e7646d2SAndroid Build Coastguard Worker             {
2368*5e7646d2SAndroid Build Coastguard Worker               if (value_tag == IPP_TAG_KEYWORD)
2369*5e7646d2SAndroid Build Coastguard Worker 		upper = 255;
2370*5e7646d2SAndroid Build Coastguard Worker 	      else
2371*5e7646d2SAndroid Build Coastguard Worker 	        upper = 1023;
2372*5e7646d2SAndroid Build Coastguard Worker 	    }
2373*5e7646d2SAndroid Build Coastguard Worker 
2374*5e7646d2SAndroid Build Coastguard Worker 	    for (i = 0; i < count; i ++)
2375*5e7646d2SAndroid Build Coastguard Worker 	    {
2376*5e7646d2SAndroid Build Coastguard Worker 	      if (strlen(ippGetString(attr, i, NULL)) > (size_t)upper)
2377*5e7646d2SAndroid Build Coastguard Worker 		break;
2378*5e7646d2SAndroid Build Coastguard Worker 	    }
2379*5e7646d2SAndroid Build Coastguard Worker 
2380*5e7646d2SAndroid Build Coastguard Worker 	    match = (i == count);
2381*5e7646d2SAndroid Build Coastguard Worker 	    break;
2382*5e7646d2SAndroid Build Coastguard Worker 
2383*5e7646d2SAndroid Build Coastguard Worker         case IPP_TAG_STRING :
2384*5e7646d2SAndroid Build Coastguard Worker             if (upper == INT_MAX)
2385*5e7646d2SAndroid Build Coastguard Worker 	      upper = 1023;
2386*5e7646d2SAndroid Build Coastguard Worker 
2387*5e7646d2SAndroid Build Coastguard Worker 	    for (i = 0; i < count; i ++)
2388*5e7646d2SAndroid Build Coastguard Worker 	    {
2389*5e7646d2SAndroid Build Coastguard Worker 	      int	datalen;	// Length of octetString value
2390*5e7646d2SAndroid Build Coastguard Worker 
2391*5e7646d2SAndroid Build Coastguard Worker 	      ippGetOctetString(attr, i, &datalen);
2392*5e7646d2SAndroid Build Coastguard Worker 
2393*5e7646d2SAndroid Build Coastguard Worker 	      if (datalen > upper)
2394*5e7646d2SAndroid Build Coastguard Worker 		break;
2395*5e7646d2SAndroid Build Coastguard Worker 	    }
2396*5e7646d2SAndroid Build Coastguard Worker 
2397*5e7646d2SAndroid Build Coastguard Worker 	    match = (i == count);
2398*5e7646d2SAndroid Build Coastguard Worker 	    break;
2399*5e7646d2SAndroid Build Coastguard Worker 
2400*5e7646d2SAndroid Build Coastguard Worker 	case IPP_TAG_INTEGER :
2401*5e7646d2SAndroid Build Coastguard Worker 	    for (i = 0; i < count; i ++)
2402*5e7646d2SAndroid Build Coastguard Worker 	    {
2403*5e7646d2SAndroid Build Coastguard Worker 	      int value = ippGetInteger(attr, i);
2404*5e7646d2SAndroid Build Coastguard Worker 					// Integer value
2405*5e7646d2SAndroid Build Coastguard Worker 
2406*5e7646d2SAndroid Build Coastguard Worker 	      if (value < lower || value > upper)
2407*5e7646d2SAndroid Build Coastguard Worker 		break;
2408*5e7646d2SAndroid Build Coastguard Worker 	    }
2409*5e7646d2SAndroid Build Coastguard Worker 
2410*5e7646d2SAndroid Build Coastguard Worker 	    match = (i == count);
2411*5e7646d2SAndroid Build Coastguard Worker 	    break;
2412*5e7646d2SAndroid Build Coastguard Worker 
2413*5e7646d2SAndroid Build Coastguard Worker 	case IPP_TAG_RANGE :
2414*5e7646d2SAndroid Build Coastguard Worker 	    for (i = 0; i < count; i ++)
2415*5e7646d2SAndroid Build Coastguard Worker 	    {
2416*5e7646d2SAndroid Build Coastguard Worker 	      int vupper, vlower = ippGetRange(attr, i, &vupper);
2417*5e7646d2SAndroid Build Coastguard Worker 					// Range value
2418*5e7646d2SAndroid Build Coastguard Worker 
2419*5e7646d2SAndroid Build Coastguard Worker 	      if (vlower < lower || vlower > upper || vupper < lower || vupper > upper)
2420*5e7646d2SAndroid Build Coastguard Worker 		break;
2421*5e7646d2SAndroid Build Coastguard Worker 	    }
2422*5e7646d2SAndroid Build Coastguard Worker 
2423*5e7646d2SAndroid Build Coastguard Worker 	    match = (i == count);
2424*5e7646d2SAndroid Build Coastguard Worker 	    break;
2425*5e7646d2SAndroid Build Coastguard Worker 
2426*5e7646d2SAndroid Build Coastguard Worker 	default :
2427*5e7646d2SAndroid Build Coastguard Worker 	    // No other constraints, so this is a match
2428*5e7646d2SAndroid Build Coastguard Worker 	    match = 1;
2429*5e7646d2SAndroid Build Coastguard Worker 	    break;
2430*5e7646d2SAndroid Build Coastguard Worker       }
2431*5e7646d2SAndroid Build Coastguard Worker     }
2432*5e7646d2SAndroid Build Coastguard Worker 
2433*5e7646d2SAndroid Build Coastguard Worker    /*
2434*5e7646d2SAndroid Build Coastguard Worker     * Restore the separators if we have them...
2435*5e7646d2SAndroid Build Coastguard Worker     */
2436*5e7646d2SAndroid Build Coastguard Worker 
2437*5e7646d2SAndroid Build Coastguard Worker     if (paren)
2438*5e7646d2SAndroid Build Coastguard Worker       *paren = '(';
2439*5e7646d2SAndroid Build Coastguard Worker 
2440*5e7646d2SAndroid Build Coastguard Worker     if (sep)
2441*5e7646d2SAndroid Build Coastguard Worker       *next++ = sep;
2442*5e7646d2SAndroid Build Coastguard Worker   }
2443*5e7646d2SAndroid Build Coastguard Worker 
2444*5e7646d2SAndroid Build Coastguard Worker   return (match);
2445*5e7646d2SAndroid Build Coastguard Worker }
2446*5e7646d2SAndroid Build Coastguard Worker 
2447*5e7646d2SAndroid Build Coastguard Worker 
2448*5e7646d2SAndroid Build Coastguard Worker /*
2449*5e7646d2SAndroid Build Coastguard Worker  * 'get_filename()' - Get a filename based on the current test file.
2450*5e7646d2SAndroid Build Coastguard Worker  */
2451*5e7646d2SAndroid Build Coastguard Worker 
2452*5e7646d2SAndroid Build Coastguard Worker static char *				/* O - Filename */
get_filename(const char * testfile,char * dst,const char * src,size_t dstsize)2453*5e7646d2SAndroid Build Coastguard Worker get_filename(const char *testfile,	/* I - Current test file */
2454*5e7646d2SAndroid Build Coastguard Worker              char       *dst,		/* I - Destination filename */
2455*5e7646d2SAndroid Build Coastguard Worker 	     const char *src,		/* I - Source filename */
2456*5e7646d2SAndroid Build Coastguard Worker              size_t     dstsize)	/* I - Size of destination buffer */
2457*5e7646d2SAndroid Build Coastguard Worker {
2458*5e7646d2SAndroid Build Coastguard Worker   char			*dstptr;	/* Pointer into destination */
2459*5e7646d2SAndroid Build Coastguard Worker   _cups_globals_t	*cg = _cupsGlobals();
2460*5e7646d2SAndroid Build Coastguard Worker 					/* Global data */
2461*5e7646d2SAndroid Build Coastguard Worker 
2462*5e7646d2SAndroid Build Coastguard Worker 
2463*5e7646d2SAndroid Build Coastguard Worker   if (*src == '<' && src[strlen(src) - 1] == '>')
2464*5e7646d2SAndroid Build Coastguard Worker   {
2465*5e7646d2SAndroid Build Coastguard Worker    /*
2466*5e7646d2SAndroid Build Coastguard Worker     * Map <filename> to CUPS_DATADIR/ipptool/filename...
2467*5e7646d2SAndroid Build Coastguard Worker     */
2468*5e7646d2SAndroid Build Coastguard Worker 
2469*5e7646d2SAndroid Build Coastguard Worker     snprintf(dst, dstsize, "%s/ipptool/%s", cg->cups_datadir, src + 1);
2470*5e7646d2SAndroid Build Coastguard Worker     dstptr = dst + strlen(dst) - 1;
2471*5e7646d2SAndroid Build Coastguard Worker     if (*dstptr == '>')
2472*5e7646d2SAndroid Build Coastguard Worker       *dstptr = '\0';
2473*5e7646d2SAndroid Build Coastguard Worker   }
2474*5e7646d2SAndroid Build Coastguard Worker   else if (!access(src, R_OK) || *src == '/'
2475*5e7646d2SAndroid Build Coastguard Worker #ifdef _WIN32
2476*5e7646d2SAndroid Build Coastguard Worker            || (isalpha(*src & 255) && src[1] == ':')
2477*5e7646d2SAndroid Build Coastguard Worker #endif /* _WIN32 */
2478*5e7646d2SAndroid Build Coastguard Worker            )
2479*5e7646d2SAndroid Build Coastguard Worker   {
2480*5e7646d2SAndroid Build Coastguard Worker    /*
2481*5e7646d2SAndroid Build Coastguard Worker     * Use the path as-is...
2482*5e7646d2SAndroid Build Coastguard Worker     */
2483*5e7646d2SAndroid Build Coastguard Worker 
2484*5e7646d2SAndroid Build Coastguard Worker     strlcpy(dst, src, dstsize);
2485*5e7646d2SAndroid Build Coastguard Worker   }
2486*5e7646d2SAndroid Build Coastguard Worker   else
2487*5e7646d2SAndroid Build Coastguard Worker   {
2488*5e7646d2SAndroid Build Coastguard Worker    /*
2489*5e7646d2SAndroid Build Coastguard Worker     * Make path relative to testfile...
2490*5e7646d2SAndroid Build Coastguard Worker     */
2491*5e7646d2SAndroid Build Coastguard Worker 
2492*5e7646d2SAndroid Build Coastguard Worker     strlcpy(dst, testfile, dstsize);
2493*5e7646d2SAndroid Build Coastguard Worker     if ((dstptr = strrchr(dst, '/')) != NULL)
2494*5e7646d2SAndroid Build Coastguard Worker       dstptr ++;
2495*5e7646d2SAndroid Build Coastguard Worker     else
2496*5e7646d2SAndroid Build Coastguard Worker       dstptr = dst; /* Should never happen */
2497*5e7646d2SAndroid Build Coastguard Worker 
2498*5e7646d2SAndroid Build Coastguard Worker     strlcpy(dstptr, src, dstsize - (size_t)(dstptr - dst));
2499*5e7646d2SAndroid Build Coastguard Worker 
2500*5e7646d2SAndroid Build Coastguard Worker #if _WIN32
2501*5e7646d2SAndroid Build Coastguard Worker     if (_access(dst, 0))
2502*5e7646d2SAndroid Build Coastguard Worker     {
2503*5e7646d2SAndroid Build Coastguard Worker      /*
2504*5e7646d2SAndroid Build Coastguard Worker       * Not available relative to the testfile, see if it can be found on the
2505*5e7646d2SAndroid Build Coastguard Worker       * desktop...
2506*5e7646d2SAndroid Build Coastguard Worker       */
2507*5e7646d2SAndroid Build Coastguard Worker       const char *userprofile = getenv("USERPROFILE");
2508*5e7646d2SAndroid Build Coastguard Worker 					/* User home directory */
2509*5e7646d2SAndroid Build Coastguard Worker 
2510*5e7646d2SAndroid Build Coastguard Worker       if (userprofile)
2511*5e7646d2SAndroid Build Coastguard Worker         snprintf(dst, dstsize, "%s/Desktop/%s", userprofile, src);
2512*5e7646d2SAndroid Build Coastguard Worker     }
2513*5e7646d2SAndroid Build Coastguard Worker #endif /* _WIN32 */
2514*5e7646d2SAndroid Build Coastguard Worker   }
2515*5e7646d2SAndroid Build Coastguard Worker 
2516*5e7646d2SAndroid Build Coastguard Worker   return (dst);
2517*5e7646d2SAndroid Build Coastguard Worker }
2518*5e7646d2SAndroid Build Coastguard Worker 
2519*5e7646d2SAndroid Build Coastguard Worker 
2520*5e7646d2SAndroid Build Coastguard Worker /*
2521*5e7646d2SAndroid Build Coastguard Worker  * 'get_string()' - Get a pointer to a string value or the portion of interest.
2522*5e7646d2SAndroid Build Coastguard Worker  */
2523*5e7646d2SAndroid Build Coastguard Worker 
2524*5e7646d2SAndroid Build Coastguard Worker static const char *			/* O - Pointer to string */
get_string(ipp_attribute_t * attr,int element,int flags,char * buffer,size_t bufsize)2525*5e7646d2SAndroid Build Coastguard Worker get_string(ipp_attribute_t *attr,	/* I - IPP attribute */
2526*5e7646d2SAndroid Build Coastguard Worker            int             element,	/* I - Element to fetch */
2527*5e7646d2SAndroid Build Coastguard Worker            int             flags,	/* I - Value ("with") flags */
2528*5e7646d2SAndroid Build Coastguard Worker            char            *buffer,	/* I - Temporary buffer */
2529*5e7646d2SAndroid Build Coastguard Worker 	   size_t          bufsize)	/* I - Size of temporary buffer */
2530*5e7646d2SAndroid Build Coastguard Worker {
2531*5e7646d2SAndroid Build Coastguard Worker   const char	*value;			/* Value */
2532*5e7646d2SAndroid Build Coastguard Worker   char		*ptr,			/* Pointer into value */
2533*5e7646d2SAndroid Build Coastguard Worker 		scheme[256],		/* URI scheme */
2534*5e7646d2SAndroid Build Coastguard Worker 		userpass[256],		/* Username/password */
2535*5e7646d2SAndroid Build Coastguard Worker 		hostname[256],		/* Hostname */
2536*5e7646d2SAndroid Build Coastguard Worker 		resource[1024];		/* Resource */
2537*5e7646d2SAndroid Build Coastguard Worker   int		port;			/* Port number */
2538*5e7646d2SAndroid Build Coastguard Worker 
2539*5e7646d2SAndroid Build Coastguard Worker 
2540*5e7646d2SAndroid Build Coastguard Worker   value = ippGetString(attr, element, NULL);
2541*5e7646d2SAndroid Build Coastguard Worker 
2542*5e7646d2SAndroid Build Coastguard Worker   if (flags & IPPTOOL_WITH_HOSTNAME)
2543*5e7646d2SAndroid Build Coastguard Worker   {
2544*5e7646d2SAndroid Build Coastguard Worker     if (httpSeparateURI(HTTP_URI_CODING_ALL, value, scheme, sizeof(scheme), userpass, sizeof(userpass), buffer, (int)bufsize, &port, resource, sizeof(resource)) < HTTP_URI_STATUS_OK)
2545*5e7646d2SAndroid Build Coastguard Worker       buffer[0] = '\0';
2546*5e7646d2SAndroid Build Coastguard Worker 
2547*5e7646d2SAndroid Build Coastguard Worker     ptr = buffer + strlen(buffer) - 1;
2548*5e7646d2SAndroid Build Coastguard Worker     if (ptr >= buffer && *ptr == '.')
2549*5e7646d2SAndroid Build Coastguard Worker       *ptr = '\0';			/* Drop trailing "." */
2550*5e7646d2SAndroid Build Coastguard Worker 
2551*5e7646d2SAndroid Build Coastguard Worker     return (buffer);
2552*5e7646d2SAndroid Build Coastguard Worker   }
2553*5e7646d2SAndroid Build Coastguard Worker   else if (flags & IPPTOOL_WITH_RESOURCE)
2554*5e7646d2SAndroid Build Coastguard Worker   {
2555*5e7646d2SAndroid Build Coastguard Worker     if (httpSeparateURI(HTTP_URI_CODING_ALL, value, scheme, sizeof(scheme), userpass, sizeof(userpass), hostname, sizeof(hostname), &port, buffer, (int)bufsize) < HTTP_URI_STATUS_OK)
2556*5e7646d2SAndroid Build Coastguard Worker       buffer[0] = '\0';
2557*5e7646d2SAndroid Build Coastguard Worker 
2558*5e7646d2SAndroid Build Coastguard Worker     return (buffer);
2559*5e7646d2SAndroid Build Coastguard Worker   }
2560*5e7646d2SAndroid Build Coastguard Worker   else if (flags & IPPTOOL_WITH_SCHEME)
2561*5e7646d2SAndroid Build Coastguard Worker   {
2562*5e7646d2SAndroid Build Coastguard Worker     if (httpSeparateURI(HTTP_URI_CODING_ALL, value, buffer, (int)bufsize, userpass, sizeof(userpass), hostname, sizeof(hostname), &port, resource, sizeof(resource)) < HTTP_URI_STATUS_OK)
2563*5e7646d2SAndroid Build Coastguard Worker       buffer[0] = '\0';
2564*5e7646d2SAndroid Build Coastguard Worker 
2565*5e7646d2SAndroid Build Coastguard Worker     return (buffer);
2566*5e7646d2SAndroid Build Coastguard Worker   }
2567*5e7646d2SAndroid Build Coastguard Worker   else if (ippGetValueTag(attr) == IPP_TAG_URI && (!strncmp(value, "ipp://", 6) || !strncmp(value, "http://", 7) || !strncmp(value, "ipps://", 7) || !strncmp(value, "https://", 8)))
2568*5e7646d2SAndroid Build Coastguard Worker   {
2569*5e7646d2SAndroid Build Coastguard Worker     http_uri_status_t status = httpSeparateURI(HTTP_URI_CODING_ALL, value, scheme, sizeof(scheme), userpass, sizeof(userpass), hostname, sizeof(hostname), &port, resource, sizeof(resource));
2570*5e7646d2SAndroid Build Coastguard Worker 
2571*5e7646d2SAndroid Build Coastguard Worker     if (status < HTTP_URI_STATUS_OK)
2572*5e7646d2SAndroid Build Coastguard Worker     {
2573*5e7646d2SAndroid Build Coastguard Worker      /*
2574*5e7646d2SAndroid Build Coastguard Worker       * Bad URI...
2575*5e7646d2SAndroid Build Coastguard Worker       */
2576*5e7646d2SAndroid Build Coastguard Worker 
2577*5e7646d2SAndroid Build Coastguard Worker       buffer[0] = '\0';
2578*5e7646d2SAndroid Build Coastguard Worker     }
2579*5e7646d2SAndroid Build Coastguard Worker     else
2580*5e7646d2SAndroid Build Coastguard Worker     {
2581*5e7646d2SAndroid Build Coastguard Worker      /*
2582*5e7646d2SAndroid Build Coastguard Worker       * Normalize URI with no trailing dot...
2583*5e7646d2SAndroid Build Coastguard Worker       */
2584*5e7646d2SAndroid Build Coastguard Worker 
2585*5e7646d2SAndroid Build Coastguard Worker       if ((ptr = hostname + strlen(hostname) - 1) >= hostname && *ptr == '.')
2586*5e7646d2SAndroid Build Coastguard Worker 	*ptr = '\0';
2587*5e7646d2SAndroid Build Coastguard Worker 
2588*5e7646d2SAndroid Build Coastguard Worker       httpAssembleURI(HTTP_URI_CODING_ALL, buffer, (int)bufsize, scheme, userpass, hostname, port, resource);
2589*5e7646d2SAndroid Build Coastguard Worker     }
2590*5e7646d2SAndroid Build Coastguard Worker 
2591*5e7646d2SAndroid Build Coastguard Worker     return (buffer);
2592*5e7646d2SAndroid Build Coastguard Worker   }
2593*5e7646d2SAndroid Build Coastguard Worker   else
2594*5e7646d2SAndroid Build Coastguard Worker     return (value);
2595*5e7646d2SAndroid Build Coastguard Worker }
2596*5e7646d2SAndroid Build Coastguard Worker 
2597*5e7646d2SAndroid Build Coastguard Worker 
2598*5e7646d2SAndroid Build Coastguard Worker /*
2599*5e7646d2SAndroid Build Coastguard Worker  * 'init_data()' - Initialize test data.
2600*5e7646d2SAndroid Build Coastguard Worker  */
2601*5e7646d2SAndroid Build Coastguard Worker 
2602*5e7646d2SAndroid Build Coastguard Worker static void
init_data(ipptool_test_t * data)2603*5e7646d2SAndroid Build Coastguard Worker init_data(ipptool_test_t *data)	/* I - Data */
2604*5e7646d2SAndroid Build Coastguard Worker {
2605*5e7646d2SAndroid Build Coastguard Worker   memset(data, 0, sizeof(ipptool_test_t));
2606*5e7646d2SAndroid Build Coastguard Worker 
2607*5e7646d2SAndroid Build Coastguard Worker   data->output       = IPPTOOL_OUTPUT_LIST;
2608*5e7646d2SAndroid Build Coastguard Worker   data->outfile      = cupsFileStdout();
2609*5e7646d2SAndroid Build Coastguard Worker   data->family       = AF_UNSPEC;
2610*5e7646d2SAndroid Build Coastguard Worker   data->def_transfer = IPPTOOL_TRANSFER_AUTO;
2611*5e7646d2SAndroid Build Coastguard Worker   data->def_version  = 11;
2612*5e7646d2SAndroid Build Coastguard Worker   data->errors       = cupsArrayNew3(NULL, NULL, NULL, 0, (cups_acopy_func_t)strdup, (cups_afree_func_t)free);
2613*5e7646d2SAndroid Build Coastguard Worker   data->pass         = 1;
2614*5e7646d2SAndroid Build Coastguard Worker   data->prev_pass    = 1;
2615*5e7646d2SAndroid Build Coastguard Worker   data->request_id   = (CUPS_RAND() % 1000) * 137;
2616*5e7646d2SAndroid Build Coastguard Worker   data->show_header  = 1;
2617*5e7646d2SAndroid Build Coastguard Worker }
2618*5e7646d2SAndroid Build Coastguard Worker 
2619*5e7646d2SAndroid Build Coastguard Worker 
2620*5e7646d2SAndroid Build Coastguard Worker /*
2621*5e7646d2SAndroid Build Coastguard Worker  * 'iso_date()' - Return an ISO 8601 date/time string for the given IPP dateTime
2622*5e7646d2SAndroid Build Coastguard Worker  *                value.
2623*5e7646d2SAndroid Build Coastguard Worker  */
2624*5e7646d2SAndroid Build Coastguard Worker 
2625*5e7646d2SAndroid Build Coastguard Worker static char *				/* O - ISO 8601 date/time string */
iso_date(const ipp_uchar_t * date)2626*5e7646d2SAndroid Build Coastguard Worker iso_date(const ipp_uchar_t *date)	/* I - IPP (RFC 1903) date/time value */
2627*5e7646d2SAndroid Build Coastguard Worker {
2628*5e7646d2SAndroid Build Coastguard Worker   time_t	utctime;		/* UTC time since 1970 */
2629*5e7646d2SAndroid Build Coastguard Worker   struct tm	utcdate;		/* UTC date/time */
2630*5e7646d2SAndroid Build Coastguard Worker   static char	buffer[255];		/* String buffer */
2631*5e7646d2SAndroid Build Coastguard Worker 
2632*5e7646d2SAndroid Build Coastguard Worker 
2633*5e7646d2SAndroid Build Coastguard Worker   utctime = ippDateToTime(date);
2634*5e7646d2SAndroid Build Coastguard Worker   gmtime_r(&utctime, &utcdate);
2635*5e7646d2SAndroid Build Coastguard Worker 
2636*5e7646d2SAndroid Build Coastguard Worker   snprintf(buffer, sizeof(buffer), "%04d-%02d-%02dT%02d:%02d:%02dZ",
2637*5e7646d2SAndroid Build Coastguard Worker 	   utcdate.tm_year + 1900, utcdate.tm_mon + 1, utcdate.tm_mday,
2638*5e7646d2SAndroid Build Coastguard Worker 	   utcdate.tm_hour, utcdate.tm_min, utcdate.tm_sec);
2639*5e7646d2SAndroid Build Coastguard Worker 
2640*5e7646d2SAndroid Build Coastguard Worker   return (buffer);
2641*5e7646d2SAndroid Build Coastguard Worker }
2642*5e7646d2SAndroid Build Coastguard Worker 
2643*5e7646d2SAndroid Build Coastguard Worker 
2644*5e7646d2SAndroid Build Coastguard Worker /*
2645*5e7646d2SAndroid Build Coastguard Worker  * 'parse_monitor_printer_state()' - Parse the MONITOR-PRINTER-STATE directive.
2646*5e7646d2SAndroid Build Coastguard Worker  *
2647*5e7646d2SAndroid Build Coastguard Worker  * MONITOR-PRINTER-STATE [printer-uri] {
2648*5e7646d2SAndroid Build Coastguard Worker  *     DELAY nnn
2649*5e7646d2SAndroid Build Coastguard Worker  *     EXPECT attribute-name ...
2650*5e7646d2SAndroid Build Coastguard Worker  * }
2651*5e7646d2SAndroid Build Coastguard Worker  */
2652*5e7646d2SAndroid Build Coastguard Worker 
2653*5e7646d2SAndroid Build Coastguard Worker static int				/* O - 1 to continue, 0 to stop */
parse_monitor_printer_state(_ipp_file_t * f,ipptool_test_t * data)2654*5e7646d2SAndroid Build Coastguard Worker parse_monitor_printer_state(
2655*5e7646d2SAndroid Build Coastguard Worker     _ipp_file_t    *f,			/* I - IPP file data */
2656*5e7646d2SAndroid Build Coastguard Worker     ipptool_test_t *data)		/* I - Test data */
2657*5e7646d2SAndroid Build Coastguard Worker {
2658*5e7646d2SAndroid Build Coastguard Worker   char	token[256],			/* Token string */
2659*5e7646d2SAndroid Build Coastguard Worker 	name[1024],			/* Name string */
2660*5e7646d2SAndroid Build Coastguard Worker 	temp[1024],			/* Temporary string */
2661*5e7646d2SAndroid Build Coastguard Worker 	value[1024],			/* Value string */
2662*5e7646d2SAndroid Build Coastguard Worker 	*ptr;				/* Pointer into value */
2663*5e7646d2SAndroid Build Coastguard Worker 
2664*5e7646d2SAndroid Build Coastguard Worker 
2665*5e7646d2SAndroid Build Coastguard Worker   if (!_ippFileReadToken(f, temp, sizeof(temp)))
2666*5e7646d2SAndroid Build Coastguard Worker   {
2667*5e7646d2SAndroid Build Coastguard Worker     print_fatal_error(data, "Missing printer URI on line %d of \"%s\".", f->linenum, f->filename);
2668*5e7646d2SAndroid Build Coastguard Worker     return (0);
2669*5e7646d2SAndroid Build Coastguard Worker   }
2670*5e7646d2SAndroid Build Coastguard Worker 
2671*5e7646d2SAndroid Build Coastguard Worker   if (strcmp(temp, "{"))
2672*5e7646d2SAndroid Build Coastguard Worker   {
2673*5e7646d2SAndroid Build Coastguard Worker     // Got a printer URI so copy it...
2674*5e7646d2SAndroid Build Coastguard Worker     _ippVarsExpand(data->vars, value, temp, sizeof(value));
2675*5e7646d2SAndroid Build Coastguard Worker     data->monitor_uri = strdup(value);
2676*5e7646d2SAndroid Build Coastguard Worker 
2677*5e7646d2SAndroid Build Coastguard Worker     // Then see if we have an opening brace...
2678*5e7646d2SAndroid Build Coastguard Worker     if (!_ippFileReadToken(f, temp, sizeof(temp)) || strcmp(temp, "{"))
2679*5e7646d2SAndroid Build Coastguard Worker     {
2680*5e7646d2SAndroid Build Coastguard Worker       print_fatal_error(data, "Missing opening brace on line %d of \"%s\".", f->linenum, f->filename);
2681*5e7646d2SAndroid Build Coastguard Worker       return (0);
2682*5e7646d2SAndroid Build Coastguard Worker     }
2683*5e7646d2SAndroid Build Coastguard Worker   }
2684*5e7646d2SAndroid Build Coastguard Worker   else
2685*5e7646d2SAndroid Build Coastguard Worker   {
2686*5e7646d2SAndroid Build Coastguard Worker     // Use the default printer URI...
2687*5e7646d2SAndroid Build Coastguard Worker     data->monitor_uri = strdup(data->vars->uri);
2688*5e7646d2SAndroid Build Coastguard Worker   }
2689*5e7646d2SAndroid Build Coastguard Worker 
2690*5e7646d2SAndroid Build Coastguard Worker   // Loop until we get a closing brace...
2691*5e7646d2SAndroid Build Coastguard Worker   while (_ippFileReadToken(f, token, sizeof(token)))
2692*5e7646d2SAndroid Build Coastguard Worker   {
2693*5e7646d2SAndroid Build Coastguard Worker     if (_cups_strcasecmp(token, "COUNT") &&
2694*5e7646d2SAndroid Build Coastguard Worker 	_cups_strcasecmp(token, "DEFINE-MATCH") &&
2695*5e7646d2SAndroid Build Coastguard Worker 	_cups_strcasecmp(token, "DEFINE-NO-MATCH") &&
2696*5e7646d2SAndroid Build Coastguard Worker 	_cups_strcasecmp(token, "DEFINE-VALUE") &&
2697*5e7646d2SAndroid Build Coastguard Worker 	_cups_strcasecmp(token, "DISPLAY-MATCH") &&
2698*5e7646d2SAndroid Build Coastguard Worker 	_cups_strcasecmp(token, "IF-DEFINED") &&
2699*5e7646d2SAndroid Build Coastguard Worker 	_cups_strcasecmp(token, "IF-NOT-DEFINED") &&
2700*5e7646d2SAndroid Build Coastguard Worker 	_cups_strcasecmp(token, "IN-GROUP") &&
2701*5e7646d2SAndroid Build Coastguard Worker 	_cups_strcasecmp(token, "OF-TYPE") &&
2702*5e7646d2SAndroid Build Coastguard Worker 	_cups_strcasecmp(token, "WITH-DISTINCT-VALUES") &&
2703*5e7646d2SAndroid Build Coastguard Worker 	_cups_strcasecmp(token, "WITH-VALUE"))
2704*5e7646d2SAndroid Build Coastguard Worker       data->last_expect = NULL;
2705*5e7646d2SAndroid Build Coastguard Worker 
2706*5e7646d2SAndroid Build Coastguard Worker     if (!strcmp(token, "}"))
2707*5e7646d2SAndroid Build Coastguard Worker       return (1);
2708*5e7646d2SAndroid Build Coastguard Worker     else if (!_cups_strcasecmp(token, "EXPECT"))
2709*5e7646d2SAndroid Build Coastguard Worker     {
2710*5e7646d2SAndroid Build Coastguard Worker      /*
2711*5e7646d2SAndroid Build Coastguard Worker       * Expected attributes...
2712*5e7646d2SAndroid Build Coastguard Worker       */
2713*5e7646d2SAndroid Build Coastguard Worker 
2714*5e7646d2SAndroid Build Coastguard Worker       if (data->num_monitor_expects >= (int)(sizeof(data->monitor_expects) / sizeof(data->monitor_expects[0])))
2715*5e7646d2SAndroid Build Coastguard Worker       {
2716*5e7646d2SAndroid Build Coastguard Worker 	print_fatal_error(data, "Too many EXPECT's on line %d of \"%s\".", f->linenum, f->filename);
2717*5e7646d2SAndroid Build Coastguard Worker 	return (0);
2718*5e7646d2SAndroid Build Coastguard Worker       }
2719*5e7646d2SAndroid Build Coastguard Worker 
2720*5e7646d2SAndroid Build Coastguard Worker       if (!_ippFileReadToken(f, name, sizeof(name)))
2721*5e7646d2SAndroid Build Coastguard Worker       {
2722*5e7646d2SAndroid Build Coastguard Worker 	print_fatal_error(data, "Missing EXPECT name on line %d of \"%s\".", f->linenum, f->filename);
2723*5e7646d2SAndroid Build Coastguard Worker 	return (0);
2724*5e7646d2SAndroid Build Coastguard Worker       }
2725*5e7646d2SAndroid Build Coastguard Worker 
2726*5e7646d2SAndroid Build Coastguard Worker       data->last_expect = data->monitor_expects + data->num_monitor_expects;
2727*5e7646d2SAndroid Build Coastguard Worker       data->num_monitor_expects ++;
2728*5e7646d2SAndroid Build Coastguard Worker 
2729*5e7646d2SAndroid Build Coastguard Worker       memset(data->last_expect, 0, sizeof(ipptool_expect_t));
2730*5e7646d2SAndroid Build Coastguard Worker       data->last_expect->repeat_limit = 1000;
2731*5e7646d2SAndroid Build Coastguard Worker 
2732*5e7646d2SAndroid Build Coastguard Worker       if (name[0] == '!')
2733*5e7646d2SAndroid Build Coastguard Worker       {
2734*5e7646d2SAndroid Build Coastguard Worker 	data->last_expect->not_expect = 1;
2735*5e7646d2SAndroid Build Coastguard Worker 	data->last_expect->name       = strdup(name + 1);
2736*5e7646d2SAndroid Build Coastguard Worker       }
2737*5e7646d2SAndroid Build Coastguard Worker       else if (name[0] == '?')
2738*5e7646d2SAndroid Build Coastguard Worker       {
2739*5e7646d2SAndroid Build Coastguard Worker 	data->last_expect->optional = 1;
2740*5e7646d2SAndroid Build Coastguard Worker 	data->last_expect->name     = strdup(name + 1);
2741*5e7646d2SAndroid Build Coastguard Worker       }
2742*5e7646d2SAndroid Build Coastguard Worker       else
2743*5e7646d2SAndroid Build Coastguard Worker 	data->last_expect->name = strdup(name);
2744*5e7646d2SAndroid Build Coastguard Worker     }
2745*5e7646d2SAndroid Build Coastguard Worker     else if (!_cups_strcasecmp(token, "COUNT"))
2746*5e7646d2SAndroid Build Coastguard Worker     {
2747*5e7646d2SAndroid Build Coastguard Worker       int	count;			/* Count value */
2748*5e7646d2SAndroid Build Coastguard Worker 
2749*5e7646d2SAndroid Build Coastguard Worker       if (!_ippFileReadToken(f, temp, sizeof(temp)))
2750*5e7646d2SAndroid Build Coastguard Worker       {
2751*5e7646d2SAndroid Build Coastguard Worker 	print_fatal_error(data, "Missing COUNT number on line %d of \"%s\".", f->linenum, f->filename);
2752*5e7646d2SAndroid Build Coastguard Worker 	return (0);
2753*5e7646d2SAndroid Build Coastguard Worker       }
2754*5e7646d2SAndroid Build Coastguard Worker 
2755*5e7646d2SAndroid Build Coastguard Worker       if ((count = atoi(temp)) <= 0)
2756*5e7646d2SAndroid Build Coastguard Worker       {
2757*5e7646d2SAndroid Build Coastguard Worker 	print_fatal_error(data, "Bad COUNT \"%s\" on line %d of \"%s\".", temp, f->linenum, f->filename);
2758*5e7646d2SAndroid Build Coastguard Worker 	return (0);
2759*5e7646d2SAndroid Build Coastguard Worker       }
2760*5e7646d2SAndroid Build Coastguard Worker 
2761*5e7646d2SAndroid Build Coastguard Worker       if (data->last_expect)
2762*5e7646d2SAndroid Build Coastguard Worker       {
2763*5e7646d2SAndroid Build Coastguard Worker 	data->last_expect->count = count;
2764*5e7646d2SAndroid Build Coastguard Worker       }
2765*5e7646d2SAndroid Build Coastguard Worker       else
2766*5e7646d2SAndroid Build Coastguard Worker       {
2767*5e7646d2SAndroid Build Coastguard Worker 	print_fatal_error(data, "COUNT without a preceding EXPECT on line %d of \"%s\".", f->linenum, f->filename);
2768*5e7646d2SAndroid Build Coastguard Worker 	return (0);
2769*5e7646d2SAndroid Build Coastguard Worker       }
2770*5e7646d2SAndroid Build Coastguard Worker     }
2771*5e7646d2SAndroid Build Coastguard Worker     else if (!_cups_strcasecmp(token, "DEFINE-MATCH"))
2772*5e7646d2SAndroid Build Coastguard Worker     {
2773*5e7646d2SAndroid Build Coastguard Worker       if (!_ippFileReadToken(f, temp, sizeof(temp)))
2774*5e7646d2SAndroid Build Coastguard Worker       {
2775*5e7646d2SAndroid Build Coastguard Worker 	print_fatal_error(data, "Missing DEFINE-MATCH variable on line %d of \"%s\".", f->linenum, f->filename);
2776*5e7646d2SAndroid Build Coastguard Worker 	return (0);
2777*5e7646d2SAndroid Build Coastguard Worker       }
2778*5e7646d2SAndroid Build Coastguard Worker 
2779*5e7646d2SAndroid Build Coastguard Worker       if (data->last_expect)
2780*5e7646d2SAndroid Build Coastguard Worker       {
2781*5e7646d2SAndroid Build Coastguard Worker 	data->last_expect->define_match = strdup(temp);
2782*5e7646d2SAndroid Build Coastguard Worker       }
2783*5e7646d2SAndroid Build Coastguard Worker       else
2784*5e7646d2SAndroid Build Coastguard Worker       {
2785*5e7646d2SAndroid Build Coastguard Worker 	print_fatal_error(data, "DEFINE-MATCH without a preceding EXPECT on line %d of \"%s\".", f->linenum, f->filename);
2786*5e7646d2SAndroid Build Coastguard Worker 	return (0);
2787*5e7646d2SAndroid Build Coastguard Worker       }
2788*5e7646d2SAndroid Build Coastguard Worker     }
2789*5e7646d2SAndroid Build Coastguard Worker     else if (!_cups_strcasecmp(token, "DEFINE-NO-MATCH"))
2790*5e7646d2SAndroid Build Coastguard Worker     {
2791*5e7646d2SAndroid Build Coastguard Worker       if (!_ippFileReadToken(f, temp, sizeof(temp)))
2792*5e7646d2SAndroid Build Coastguard Worker       {
2793*5e7646d2SAndroid Build Coastguard Worker 	print_fatal_error(data, "Missing DEFINE-NO-MATCH variable on line %d of \"%s\".", f->linenum, f->filename);
2794*5e7646d2SAndroid Build Coastguard Worker 	return (0);
2795*5e7646d2SAndroid Build Coastguard Worker       }
2796*5e7646d2SAndroid Build Coastguard Worker 
2797*5e7646d2SAndroid Build Coastguard Worker       if (data->last_expect)
2798*5e7646d2SAndroid Build Coastguard Worker       {
2799*5e7646d2SAndroid Build Coastguard Worker 	data->last_expect->define_no_match = strdup(temp);
2800*5e7646d2SAndroid Build Coastguard Worker       }
2801*5e7646d2SAndroid Build Coastguard Worker       else
2802*5e7646d2SAndroid Build Coastguard Worker       {
2803*5e7646d2SAndroid Build Coastguard Worker 	print_fatal_error(data, "DEFINE-NO-MATCH without a preceding EXPECT on line %d of \"%s\".", f->linenum, f->filename);
2804*5e7646d2SAndroid Build Coastguard Worker 	return (0);
2805*5e7646d2SAndroid Build Coastguard Worker       }
2806*5e7646d2SAndroid Build Coastguard Worker     }
2807*5e7646d2SAndroid Build Coastguard Worker     else if (!_cups_strcasecmp(token, "DEFINE-VALUE"))
2808*5e7646d2SAndroid Build Coastguard Worker     {
2809*5e7646d2SAndroid Build Coastguard Worker       if (!_ippFileReadToken(f, temp, sizeof(temp)))
2810*5e7646d2SAndroid Build Coastguard Worker       {
2811*5e7646d2SAndroid Build Coastguard Worker 	print_fatal_error(data, "Missing DEFINE-VALUE variable on line %d of \"%s\".", f->linenum, f->filename);
2812*5e7646d2SAndroid Build Coastguard Worker 	return (0);
2813*5e7646d2SAndroid Build Coastguard Worker       }
2814*5e7646d2SAndroid Build Coastguard Worker 
2815*5e7646d2SAndroid Build Coastguard Worker       if (data->last_expect)
2816*5e7646d2SAndroid Build Coastguard Worker       {
2817*5e7646d2SAndroid Build Coastguard Worker 	data->last_expect->define_value = strdup(temp);
2818*5e7646d2SAndroid Build Coastguard Worker       }
2819*5e7646d2SAndroid Build Coastguard Worker       else
2820*5e7646d2SAndroid Build Coastguard Worker       {
2821*5e7646d2SAndroid Build Coastguard Worker 	print_fatal_error(data, "DEFINE-VALUE without a preceding EXPECT on line %d of \"%s\".", f->linenum, f->filename);
2822*5e7646d2SAndroid Build Coastguard Worker 	return (0);
2823*5e7646d2SAndroid Build Coastguard Worker       }
2824*5e7646d2SAndroid Build Coastguard Worker     }
2825*5e7646d2SAndroid Build Coastguard Worker     else if (!_cups_strcasecmp(token, "DISPLAY-MATCH"))
2826*5e7646d2SAndroid Build Coastguard Worker     {
2827*5e7646d2SAndroid Build Coastguard Worker       if (!_ippFileReadToken(f, temp, sizeof(temp)))
2828*5e7646d2SAndroid Build Coastguard Worker       {
2829*5e7646d2SAndroid Build Coastguard Worker 	print_fatal_error(data, "Missing DISPLAY-MATCH message on line %d of \"%s\".", f->linenum, f->filename);
2830*5e7646d2SAndroid Build Coastguard Worker 	return (0);
2831*5e7646d2SAndroid Build Coastguard Worker       }
2832*5e7646d2SAndroid Build Coastguard Worker 
2833*5e7646d2SAndroid Build Coastguard Worker       if (data->last_expect)
2834*5e7646d2SAndroid Build Coastguard Worker       {
2835*5e7646d2SAndroid Build Coastguard Worker 	data->last_expect->display_match = strdup(temp);
2836*5e7646d2SAndroid Build Coastguard Worker       }
2837*5e7646d2SAndroid Build Coastguard Worker       else
2838*5e7646d2SAndroid Build Coastguard Worker       {
2839*5e7646d2SAndroid Build Coastguard Worker 	print_fatal_error(data, "DISPLAY-MATCH without a preceding EXPECT on line %d of \"%s\".", f->linenum, f->filename);
2840*5e7646d2SAndroid Build Coastguard Worker 	return (0);
2841*5e7646d2SAndroid Build Coastguard Worker       }
2842*5e7646d2SAndroid Build Coastguard Worker     }
2843*5e7646d2SAndroid Build Coastguard Worker     else if (!_cups_strcasecmp(token, "DELAY"))
2844*5e7646d2SAndroid Build Coastguard Worker     {
2845*5e7646d2SAndroid Build Coastguard Worker      /*
2846*5e7646d2SAndroid Build Coastguard Worker       * Delay before operation...
2847*5e7646d2SAndroid Build Coastguard Worker       */
2848*5e7646d2SAndroid Build Coastguard Worker 
2849*5e7646d2SAndroid Build Coastguard Worker       double dval;                    /* Delay value */
2850*5e7646d2SAndroid Build Coastguard Worker 
2851*5e7646d2SAndroid Build Coastguard Worker       if (!_ippFileReadToken(f, temp, sizeof(temp)))
2852*5e7646d2SAndroid Build Coastguard Worker       {
2853*5e7646d2SAndroid Build Coastguard Worker 	print_fatal_error(data, "Missing DELAY value on line %d of \"%s\".", f->linenum, f->filename);
2854*5e7646d2SAndroid Build Coastguard Worker 	return (0);
2855*5e7646d2SAndroid Build Coastguard Worker       }
2856*5e7646d2SAndroid Build Coastguard Worker 
2857*5e7646d2SAndroid Build Coastguard Worker       _ippVarsExpand(data->vars, value, temp, sizeof(value));
2858*5e7646d2SAndroid Build Coastguard Worker 
2859*5e7646d2SAndroid Build Coastguard Worker       if ((dval = _cupsStrScand(value, &ptr, localeconv())) < 0.0 || (*ptr && *ptr != ','))
2860*5e7646d2SAndroid Build Coastguard Worker       {
2861*5e7646d2SAndroid Build Coastguard Worker 	print_fatal_error(data, "Bad DELAY value \"%s\" on line %d of \"%s\".", value, f->linenum, f->filename);
2862*5e7646d2SAndroid Build Coastguard Worker 	return (0);
2863*5e7646d2SAndroid Build Coastguard Worker       }
2864*5e7646d2SAndroid Build Coastguard Worker 
2865*5e7646d2SAndroid Build Coastguard Worker       data->monitor_delay = (useconds_t)(1000000.0 * dval);
2866*5e7646d2SAndroid Build Coastguard Worker 
2867*5e7646d2SAndroid Build Coastguard Worker       if (*ptr == ',')
2868*5e7646d2SAndroid Build Coastguard Worker       {
2869*5e7646d2SAndroid Build Coastguard Worker 	if ((dval = _cupsStrScand(ptr + 1, &ptr, localeconv())) <= 0.0 || *ptr)
2870*5e7646d2SAndroid Build Coastguard Worker 	{
2871*5e7646d2SAndroid Build Coastguard Worker 	  print_fatal_error(data, "Bad DELAY value \"%s\" on line %d of \"%s\".", value, f->linenum, f->filename);
2872*5e7646d2SAndroid Build Coastguard Worker 	  return (0);
2873*5e7646d2SAndroid Build Coastguard Worker 	}
2874*5e7646d2SAndroid Build Coastguard Worker 
2875*5e7646d2SAndroid Build Coastguard Worker 	data->monitor_interval = (useconds_t)(1000000.0 * dval);
2876*5e7646d2SAndroid Build Coastguard Worker       }
2877*5e7646d2SAndroid Build Coastguard Worker       else
2878*5e7646d2SAndroid Build Coastguard Worker 	data->monitor_interval = data->monitor_delay;
2879*5e7646d2SAndroid Build Coastguard Worker     }
2880*5e7646d2SAndroid Build Coastguard Worker     else if (!_cups_strcasecmp(token, "OF-TYPE"))
2881*5e7646d2SAndroid Build Coastguard Worker     {
2882*5e7646d2SAndroid Build Coastguard Worker       if (!_ippFileReadToken(f, temp, sizeof(temp)))
2883*5e7646d2SAndroid Build Coastguard Worker       {
2884*5e7646d2SAndroid Build Coastguard Worker 	print_fatal_error(data, "Missing OF-TYPE value tag(s) on line %d of \"%s\".", f->linenum, f->filename);
2885*5e7646d2SAndroid Build Coastguard Worker 	return (0);
2886*5e7646d2SAndroid Build Coastguard Worker       }
2887*5e7646d2SAndroid Build Coastguard Worker 
2888*5e7646d2SAndroid Build Coastguard Worker       if (data->last_expect)
2889*5e7646d2SAndroid Build Coastguard Worker       {
2890*5e7646d2SAndroid Build Coastguard Worker 	data->last_expect->of_type = strdup(temp);
2891*5e7646d2SAndroid Build Coastguard Worker       }
2892*5e7646d2SAndroid Build Coastguard Worker       else
2893*5e7646d2SAndroid Build Coastguard Worker       {
2894*5e7646d2SAndroid Build Coastguard Worker 	print_fatal_error(data, "OF-TYPE without a preceding EXPECT on line %d of \"%s\".", f->linenum, f->filename);
2895*5e7646d2SAndroid Build Coastguard Worker 	return (0);
2896*5e7646d2SAndroid Build Coastguard Worker       }
2897*5e7646d2SAndroid Build Coastguard Worker     }
2898*5e7646d2SAndroid Build Coastguard Worker     else if (!_cups_strcasecmp(token, "IN-GROUP"))
2899*5e7646d2SAndroid Build Coastguard Worker     {
2900*5e7646d2SAndroid Build Coastguard Worker       ipp_tag_t	in_group;		/* IN-GROUP value */
2901*5e7646d2SAndroid Build Coastguard Worker 
2902*5e7646d2SAndroid Build Coastguard Worker       if (!_ippFileReadToken(f, temp, sizeof(temp)))
2903*5e7646d2SAndroid Build Coastguard Worker       {
2904*5e7646d2SAndroid Build Coastguard Worker 	print_fatal_error(data, "Missing IN-GROUP group tag on line %d of \"%s\".", f->linenum, f->filename);
2905*5e7646d2SAndroid Build Coastguard Worker 	return (0);
2906*5e7646d2SAndroid Build Coastguard Worker       }
2907*5e7646d2SAndroid Build Coastguard Worker 
2908*5e7646d2SAndroid Build Coastguard Worker       if ((in_group = ippTagValue(temp)) == IPP_TAG_ZERO || in_group >= IPP_TAG_UNSUPPORTED_VALUE)
2909*5e7646d2SAndroid Build Coastguard Worker       {
2910*5e7646d2SAndroid Build Coastguard Worker 	print_fatal_error(data, "Bad IN-GROUP group tag \"%s\" on line %d of \"%s\".", temp, f->linenum, f->filename);
2911*5e7646d2SAndroid Build Coastguard Worker 	return (0);
2912*5e7646d2SAndroid Build Coastguard Worker       }
2913*5e7646d2SAndroid Build Coastguard Worker       else if (data->last_expect)
2914*5e7646d2SAndroid Build Coastguard Worker       {
2915*5e7646d2SAndroid Build Coastguard Worker 	data->last_expect->in_group = in_group;
2916*5e7646d2SAndroid Build Coastguard Worker       }
2917*5e7646d2SAndroid Build Coastguard Worker       else
2918*5e7646d2SAndroid Build Coastguard Worker       {
2919*5e7646d2SAndroid Build Coastguard Worker 	print_fatal_error(data, "IN-GROUP without a preceding EXPECT on line %d of \"%s\".", f->linenum, f->filename);
2920*5e7646d2SAndroid Build Coastguard Worker 	return (0);
2921*5e7646d2SAndroid Build Coastguard Worker       }
2922*5e7646d2SAndroid Build Coastguard Worker     }
2923*5e7646d2SAndroid Build Coastguard Worker     else if (!_cups_strcasecmp(token, "IF-DEFINED"))
2924*5e7646d2SAndroid Build Coastguard Worker     {
2925*5e7646d2SAndroid Build Coastguard Worker       if (!_ippFileReadToken(f, temp, sizeof(temp)))
2926*5e7646d2SAndroid Build Coastguard Worker       {
2927*5e7646d2SAndroid Build Coastguard Worker 	print_fatal_error(data, "Missing IF-DEFINED name on line %d of \"%s\".", f->linenum, f->filename);
2928*5e7646d2SAndroid Build Coastguard Worker 	return (0);
2929*5e7646d2SAndroid Build Coastguard Worker       }
2930*5e7646d2SAndroid Build Coastguard Worker 
2931*5e7646d2SAndroid Build Coastguard Worker       if (data->last_expect)
2932*5e7646d2SAndroid Build Coastguard Worker       {
2933*5e7646d2SAndroid Build Coastguard Worker 	data->last_expect->if_defined = strdup(temp);
2934*5e7646d2SAndroid Build Coastguard Worker       }
2935*5e7646d2SAndroid Build Coastguard Worker       else
2936*5e7646d2SAndroid Build Coastguard Worker       {
2937*5e7646d2SAndroid Build Coastguard Worker 	print_fatal_error(data, "IF-DEFINED without a preceding EXPECT on line %d of \"%s\".", f->linenum, f->filename);
2938*5e7646d2SAndroid Build Coastguard Worker 	return (0);
2939*5e7646d2SAndroid Build Coastguard Worker       }
2940*5e7646d2SAndroid Build Coastguard Worker     }
2941*5e7646d2SAndroid Build Coastguard Worker     else if (!_cups_strcasecmp(token, "IF-NOT-DEFINED"))
2942*5e7646d2SAndroid Build Coastguard Worker     {
2943*5e7646d2SAndroid Build Coastguard Worker       if (!_ippFileReadToken(f, temp, sizeof(temp)))
2944*5e7646d2SAndroid Build Coastguard Worker       {
2945*5e7646d2SAndroid Build Coastguard Worker 	print_fatal_error(data, "Missing IF-NOT-DEFINED name on line %d of \"%s\".", f->linenum, f->filename);
2946*5e7646d2SAndroid Build Coastguard Worker 	return (0);
2947*5e7646d2SAndroid Build Coastguard Worker       }
2948*5e7646d2SAndroid Build Coastguard Worker 
2949*5e7646d2SAndroid Build Coastguard Worker       if (data->last_expect)
2950*5e7646d2SAndroid Build Coastguard Worker       {
2951*5e7646d2SAndroid Build Coastguard Worker 	data->last_expect->if_not_defined = strdup(temp);
2952*5e7646d2SAndroid Build Coastguard Worker       }
2953*5e7646d2SAndroid Build Coastguard Worker       else
2954*5e7646d2SAndroid Build Coastguard Worker       {
2955*5e7646d2SAndroid Build Coastguard Worker 	print_fatal_error(data, "IF-NOT-DEFINED without a preceding EXPECT on line %d of \"%s\".", f->linenum, f->filename);
2956*5e7646d2SAndroid Build Coastguard Worker 	return (0);
2957*5e7646d2SAndroid Build Coastguard Worker       }
2958*5e7646d2SAndroid Build Coastguard Worker     }
2959*5e7646d2SAndroid Build Coastguard Worker     else if (!_cups_strcasecmp(token, "WITH-DISTINCT-VALUES"))
2960*5e7646d2SAndroid Build Coastguard Worker     {
2961*5e7646d2SAndroid Build Coastguard Worker       if (data->last_expect)
2962*5e7646d2SAndroid Build Coastguard Worker       {
2963*5e7646d2SAndroid Build Coastguard Worker         data->last_expect->with_distinct = 1;
2964*5e7646d2SAndroid Build Coastguard Worker       }
2965*5e7646d2SAndroid Build Coastguard Worker       else
2966*5e7646d2SAndroid Build Coastguard Worker       {
2967*5e7646d2SAndroid Build Coastguard Worker 	print_fatal_error(data, "%s without a preceding EXPECT on line %d of \"%s\".", token, f->linenum, f->filename);
2968*5e7646d2SAndroid Build Coastguard Worker 	return (0);
2969*5e7646d2SAndroid Build Coastguard Worker       }
2970*5e7646d2SAndroid Build Coastguard Worker     }
2971*5e7646d2SAndroid Build Coastguard Worker     else if (!_cups_strcasecmp(token, "WITH-VALUE"))
2972*5e7646d2SAndroid Build Coastguard Worker     {
2973*5e7646d2SAndroid Build Coastguard Worker       off_t	lastpos;		/* Last file position */
2974*5e7646d2SAndroid Build Coastguard Worker       int	lastline;		/* Last line number */
2975*5e7646d2SAndroid Build Coastguard Worker 
2976*5e7646d2SAndroid Build Coastguard Worker       if (!_ippFileReadToken(f, temp, sizeof(temp)))
2977*5e7646d2SAndroid Build Coastguard Worker       {
2978*5e7646d2SAndroid Build Coastguard Worker 	print_fatal_error(data, "Missing %s value on line %d of \"%s\".", token, f->linenum, f->filename);
2979*5e7646d2SAndroid Build Coastguard Worker 	return (0);
2980*5e7646d2SAndroid Build Coastguard Worker       }
2981*5e7646d2SAndroid Build Coastguard Worker 
2982*5e7646d2SAndroid Build Coastguard Worker      /*
2983*5e7646d2SAndroid Build Coastguard Worker       * Read additional comma-delimited values - needed since legacy test files
2984*5e7646d2SAndroid Build Coastguard Worker       * will have unquoted WITH-VALUE values with commas...
2985*5e7646d2SAndroid Build Coastguard Worker       */
2986*5e7646d2SAndroid Build Coastguard Worker 
2987*5e7646d2SAndroid Build Coastguard Worker       ptr = temp + strlen(temp);
2988*5e7646d2SAndroid Build Coastguard Worker 
2989*5e7646d2SAndroid Build Coastguard Worker       for (;;)
2990*5e7646d2SAndroid Build Coastguard Worker       {
2991*5e7646d2SAndroid Build Coastguard Worker         lastpos  = cupsFileTell(f->fp);
2992*5e7646d2SAndroid Build Coastguard Worker         lastline = f->linenum;
2993*5e7646d2SAndroid Build Coastguard Worker         ptr      += strlen(ptr);
2994*5e7646d2SAndroid Build Coastguard Worker 
2995*5e7646d2SAndroid Build Coastguard Worker 	if (!_ippFileReadToken(f, ptr, (sizeof(temp) - (size_t)(ptr - temp))))
2996*5e7646d2SAndroid Build Coastguard Worker 	  break;
2997*5e7646d2SAndroid Build Coastguard Worker 
2998*5e7646d2SAndroid Build Coastguard Worker         if (!strcmp(ptr, ","))
2999*5e7646d2SAndroid Build Coastguard Worker         {
3000*5e7646d2SAndroid Build Coastguard Worker          /*
3001*5e7646d2SAndroid Build Coastguard Worker           * Append a value...
3002*5e7646d2SAndroid Build Coastguard Worker           */
3003*5e7646d2SAndroid Build Coastguard Worker 
3004*5e7646d2SAndroid Build Coastguard Worker 	  ptr += strlen(ptr);
3005*5e7646d2SAndroid Build Coastguard Worker 
3006*5e7646d2SAndroid Build Coastguard Worker 	  if (!_ippFileReadToken(f, ptr, (sizeof(temp) - (size_t)(ptr - temp))))
3007*5e7646d2SAndroid Build Coastguard Worker 	    break;
3008*5e7646d2SAndroid Build Coastguard Worker         }
3009*5e7646d2SAndroid Build Coastguard Worker         else
3010*5e7646d2SAndroid Build Coastguard Worker         {
3011*5e7646d2SAndroid Build Coastguard Worker          /*
3012*5e7646d2SAndroid Build Coastguard Worker           * Not another value, stop here...
3013*5e7646d2SAndroid Build Coastguard Worker           */
3014*5e7646d2SAndroid Build Coastguard Worker 
3015*5e7646d2SAndroid Build Coastguard Worker           cupsFileSeek(f->fp, lastpos);
3016*5e7646d2SAndroid Build Coastguard Worker           f->linenum = lastline;
3017*5e7646d2SAndroid Build Coastguard Worker           *ptr = '\0';
3018*5e7646d2SAndroid Build Coastguard Worker           break;
3019*5e7646d2SAndroid Build Coastguard Worker 	}
3020*5e7646d2SAndroid Build Coastguard Worker       }
3021*5e7646d2SAndroid Build Coastguard Worker 
3022*5e7646d2SAndroid Build Coastguard Worker       if (data->last_expect)
3023*5e7646d2SAndroid Build Coastguard Worker       {
3024*5e7646d2SAndroid Build Coastguard Worker        /*
3025*5e7646d2SAndroid Build Coastguard Worker 	* Expand any variables in the value and then save it.
3026*5e7646d2SAndroid Build Coastguard Worker 	*/
3027*5e7646d2SAndroid Build Coastguard Worker 
3028*5e7646d2SAndroid Build Coastguard Worker 	_ippVarsExpand(data->vars, value, temp, sizeof(value));
3029*5e7646d2SAndroid Build Coastguard Worker 
3030*5e7646d2SAndroid Build Coastguard Worker 	ptr = value + strlen(value) - 1;
3031*5e7646d2SAndroid Build Coastguard Worker 
3032*5e7646d2SAndroid Build Coastguard Worker 	if (value[0] == '/' && ptr > value && *ptr == '/')
3033*5e7646d2SAndroid Build Coastguard Worker 	{
3034*5e7646d2SAndroid Build Coastguard Worker 	 /*
3035*5e7646d2SAndroid Build Coastguard Worker 	  * WITH-VALUE is a POSIX extended regular expression.
3036*5e7646d2SAndroid Build Coastguard Worker 	  */
3037*5e7646d2SAndroid Build Coastguard Worker 
3038*5e7646d2SAndroid Build Coastguard Worker 	  data->last_expect->with_value = calloc(1, (size_t)(ptr - value));
3039*5e7646d2SAndroid Build Coastguard Worker 	  data->last_expect->with_flags |= IPPTOOL_WITH_REGEX;
3040*5e7646d2SAndroid Build Coastguard Worker 
3041*5e7646d2SAndroid Build Coastguard Worker 	  if (data->last_expect->with_value)
3042*5e7646d2SAndroid Build Coastguard Worker 	    memcpy(data->last_expect->with_value, value + 1, (size_t)(ptr - value - 1));
3043*5e7646d2SAndroid Build Coastguard Worker 	}
3044*5e7646d2SAndroid Build Coastguard Worker 	else
3045*5e7646d2SAndroid Build Coastguard Worker 	{
3046*5e7646d2SAndroid Build Coastguard Worker 	 /*
3047*5e7646d2SAndroid Build Coastguard Worker 	  * WITH-VALUE is a literal value...
3048*5e7646d2SAndroid Build Coastguard Worker 	  */
3049*5e7646d2SAndroid Build Coastguard Worker 
3050*5e7646d2SAndroid Build Coastguard Worker 	  for (ptr = value; *ptr; ptr ++)
3051*5e7646d2SAndroid Build Coastguard Worker 	  {
3052*5e7646d2SAndroid Build Coastguard Worker 	    if (*ptr == '\\' && ptr[1])
3053*5e7646d2SAndroid Build Coastguard Worker 	    {
3054*5e7646d2SAndroid Build Coastguard Worker 	     /*
3055*5e7646d2SAndroid Build Coastguard Worker 	      * Remove \ from \foo...
3056*5e7646d2SAndroid Build Coastguard Worker 	      */
3057*5e7646d2SAndroid Build Coastguard Worker 
3058*5e7646d2SAndroid Build Coastguard Worker 	      _cups_strcpy(ptr, ptr + 1);
3059*5e7646d2SAndroid Build Coastguard Worker 	    }
3060*5e7646d2SAndroid Build Coastguard Worker 	  }
3061*5e7646d2SAndroid Build Coastguard Worker 
3062*5e7646d2SAndroid Build Coastguard Worker 	  data->last_expect->with_value = strdup(value);
3063*5e7646d2SAndroid Build Coastguard Worker 	  data->last_expect->with_flags |= IPPTOOL_WITH_LITERAL;
3064*5e7646d2SAndroid Build Coastguard Worker 	}
3065*5e7646d2SAndroid Build Coastguard Worker       }
3066*5e7646d2SAndroid Build Coastguard Worker       else
3067*5e7646d2SAndroid Build Coastguard Worker       {
3068*5e7646d2SAndroid Build Coastguard Worker 	print_fatal_error(data, "%s without a preceding EXPECT on line %d of \"%s\".", token, f->linenum, f->filename);
3069*5e7646d2SAndroid Build Coastguard Worker 	return (0);
3070*5e7646d2SAndroid Build Coastguard Worker       }
3071*5e7646d2SAndroid Build Coastguard Worker     }
3072*5e7646d2SAndroid Build Coastguard Worker   }
3073*5e7646d2SAndroid Build Coastguard Worker 
3074*5e7646d2SAndroid Build Coastguard Worker   print_fatal_error(data, "Missing closing brace on line %d of \"%s\".", f->linenum, f->filename);
3075*5e7646d2SAndroid Build Coastguard Worker 
3076*5e7646d2SAndroid Build Coastguard Worker   return (0);
3077*5e7646d2SAndroid Build Coastguard Worker }
3078*5e7646d2SAndroid Build Coastguard Worker 
3079*5e7646d2SAndroid Build Coastguard Worker 
3080*5e7646d2SAndroid Build Coastguard Worker /*
3081*5e7646d2SAndroid Build Coastguard Worker  * 'pause_message()' - Display the message and pause until the user presses a key.
3082*5e7646d2SAndroid Build Coastguard Worker  */
3083*5e7646d2SAndroid Build Coastguard Worker 
3084*5e7646d2SAndroid Build Coastguard Worker static void
pause_message(const char * message)3085*5e7646d2SAndroid Build Coastguard Worker pause_message(const char *message)	/* I - Message */
3086*5e7646d2SAndroid Build Coastguard Worker {
3087*5e7646d2SAndroid Build Coastguard Worker #ifdef _WIN32
3088*5e7646d2SAndroid Build Coastguard Worker   HANDLE	tty;			/* Console handle */
3089*5e7646d2SAndroid Build Coastguard Worker   DWORD		mode;			/* Console mode */
3090*5e7646d2SAndroid Build Coastguard Worker   char		key;			/* Key press */
3091*5e7646d2SAndroid Build Coastguard Worker   DWORD		bytes;			/* Bytes read for key press */
3092*5e7646d2SAndroid Build Coastguard Worker 
3093*5e7646d2SAndroid Build Coastguard Worker 
3094*5e7646d2SAndroid Build Coastguard Worker  /*
3095*5e7646d2SAndroid Build Coastguard Worker   * Disable input echo and set raw input...
3096*5e7646d2SAndroid Build Coastguard Worker   */
3097*5e7646d2SAndroid Build Coastguard Worker 
3098*5e7646d2SAndroid Build Coastguard Worker   if ((tty = GetStdHandle(STD_INPUT_HANDLE)) == INVALID_HANDLE_VALUE)
3099*5e7646d2SAndroid Build Coastguard Worker     return;
3100*5e7646d2SAndroid Build Coastguard Worker 
3101*5e7646d2SAndroid Build Coastguard Worker   if (!GetConsoleMode(tty, &mode))
3102*5e7646d2SAndroid Build Coastguard Worker     return;
3103*5e7646d2SAndroid Build Coastguard Worker 
3104*5e7646d2SAndroid Build Coastguard Worker   if (!SetConsoleMode(tty, 0))
3105*5e7646d2SAndroid Build Coastguard Worker     return;
3106*5e7646d2SAndroid Build Coastguard Worker 
3107*5e7646d2SAndroid Build Coastguard Worker #else
3108*5e7646d2SAndroid Build Coastguard Worker   int			tty;		/* /dev/tty - never read from stdin */
3109*5e7646d2SAndroid Build Coastguard Worker   struct termios	original,	/* Original input mode */
3110*5e7646d2SAndroid Build Coastguard Worker 			noecho;		/* No echo input mode */
3111*5e7646d2SAndroid Build Coastguard Worker   char			key;		/* Current key press */
3112*5e7646d2SAndroid Build Coastguard Worker 
3113*5e7646d2SAndroid Build Coastguard Worker 
3114*5e7646d2SAndroid Build Coastguard Worker  /*
3115*5e7646d2SAndroid Build Coastguard Worker   * Disable input echo and set raw input...
3116*5e7646d2SAndroid Build Coastguard Worker   */
3117*5e7646d2SAndroid Build Coastguard Worker 
3118*5e7646d2SAndroid Build Coastguard Worker   if ((tty = open("/dev/tty", O_RDONLY)) < 0)
3119*5e7646d2SAndroid Build Coastguard Worker     return;
3120*5e7646d2SAndroid Build Coastguard Worker 
3121*5e7646d2SAndroid Build Coastguard Worker   if (tcgetattr(tty, &original))
3122*5e7646d2SAndroid Build Coastguard Worker   {
3123*5e7646d2SAndroid Build Coastguard Worker     close(tty);
3124*5e7646d2SAndroid Build Coastguard Worker     return;
3125*5e7646d2SAndroid Build Coastguard Worker   }
3126*5e7646d2SAndroid Build Coastguard Worker 
3127*5e7646d2SAndroid Build Coastguard Worker   noecho = original;
3128*5e7646d2SAndroid Build Coastguard Worker   noecho.c_lflag &= (tcflag_t)~(ICANON | ECHO | ECHOE | ISIG);
3129*5e7646d2SAndroid Build Coastguard Worker 
3130*5e7646d2SAndroid Build Coastguard Worker   if (tcsetattr(tty, TCSAFLUSH, &noecho))
3131*5e7646d2SAndroid Build Coastguard Worker   {
3132*5e7646d2SAndroid Build Coastguard Worker     close(tty);
3133*5e7646d2SAndroid Build Coastguard Worker     return;
3134*5e7646d2SAndroid Build Coastguard Worker   }
3135*5e7646d2SAndroid Build Coastguard Worker #endif /* _WIN32 */
3136*5e7646d2SAndroid Build Coastguard Worker 
3137*5e7646d2SAndroid Build Coastguard Worker  /*
3138*5e7646d2SAndroid Build Coastguard Worker   * Display the prompt...
3139*5e7646d2SAndroid Build Coastguard Worker   */
3140*5e7646d2SAndroid Build Coastguard Worker 
3141*5e7646d2SAndroid Build Coastguard Worker   cupsFilePrintf(cupsFileStdout(), "\n%s\n\n---- PRESS ANY KEY ----", message);
3142*5e7646d2SAndroid Build Coastguard Worker 
3143*5e7646d2SAndroid Build Coastguard Worker #ifdef _WIN32
3144*5e7646d2SAndroid Build Coastguard Worker  /*
3145*5e7646d2SAndroid Build Coastguard Worker   * Read a key...
3146*5e7646d2SAndroid Build Coastguard Worker   */
3147*5e7646d2SAndroid Build Coastguard Worker 
3148*5e7646d2SAndroid Build Coastguard Worker   ReadFile(tty, &key, 1, &bytes, NULL);
3149*5e7646d2SAndroid Build Coastguard Worker 
3150*5e7646d2SAndroid Build Coastguard Worker  /*
3151*5e7646d2SAndroid Build Coastguard Worker   * Cleanup...
3152*5e7646d2SAndroid Build Coastguard Worker   */
3153*5e7646d2SAndroid Build Coastguard Worker 
3154*5e7646d2SAndroid Build Coastguard Worker   SetConsoleMode(tty, mode);
3155*5e7646d2SAndroid Build Coastguard Worker 
3156*5e7646d2SAndroid Build Coastguard Worker #else
3157*5e7646d2SAndroid Build Coastguard Worker  /*
3158*5e7646d2SAndroid Build Coastguard Worker   * Read a key...
3159*5e7646d2SAndroid Build Coastguard Worker   */
3160*5e7646d2SAndroid Build Coastguard Worker 
3161*5e7646d2SAndroid Build Coastguard Worker   read(tty, &key, 1);
3162*5e7646d2SAndroid Build Coastguard Worker 
3163*5e7646d2SAndroid Build Coastguard Worker  /*
3164*5e7646d2SAndroid Build Coastguard Worker   * Cleanup...
3165*5e7646d2SAndroid Build Coastguard Worker   */
3166*5e7646d2SAndroid Build Coastguard Worker 
3167*5e7646d2SAndroid Build Coastguard Worker   tcsetattr(tty, TCSAFLUSH, &original);
3168*5e7646d2SAndroid Build Coastguard Worker   close(tty);
3169*5e7646d2SAndroid Build Coastguard Worker #endif /* _WIN32 */
3170*5e7646d2SAndroid Build Coastguard Worker 
3171*5e7646d2SAndroid Build Coastguard Worker  /*
3172*5e7646d2SAndroid Build Coastguard Worker   * Erase the "press any key" prompt...
3173*5e7646d2SAndroid Build Coastguard Worker   */
3174*5e7646d2SAndroid Build Coastguard Worker 
3175*5e7646d2SAndroid Build Coastguard Worker   cupsFilePuts(cupsFileStdout(), "\r                       \r");
3176*5e7646d2SAndroid Build Coastguard Worker }
3177*5e7646d2SAndroid Build Coastguard Worker 
3178*5e7646d2SAndroid Build Coastguard Worker 
3179*5e7646d2SAndroid Build Coastguard Worker /*
3180*5e7646d2SAndroid Build Coastguard Worker  * 'print_attr()' - Print an attribute on the screen.
3181*5e7646d2SAndroid Build Coastguard Worker  */
3182*5e7646d2SAndroid Build Coastguard Worker 
3183*5e7646d2SAndroid Build Coastguard Worker static void
print_attr(cups_file_t * outfile,ipptool_output_t output,ipp_attribute_t * attr,ipp_tag_t * group)3184*5e7646d2SAndroid Build Coastguard Worker print_attr(cups_file_t      *outfile,	/* I  - Output file */
3185*5e7646d2SAndroid Build Coastguard Worker            ipptool_output_t output,	/* I  - Output format */
3186*5e7646d2SAndroid Build Coastguard Worker            ipp_attribute_t  *attr,	/* I  - Attribute to print */
3187*5e7646d2SAndroid Build Coastguard Worker            ipp_tag_t        *group)	/* IO - Current group */
3188*5e7646d2SAndroid Build Coastguard Worker {
3189*5e7646d2SAndroid Build Coastguard Worker   int			i,		/* Looping var */
3190*5e7646d2SAndroid Build Coastguard Worker 			count;		/* Number of values */
3191*5e7646d2SAndroid Build Coastguard Worker   ipp_attribute_t	*colattr;	/* Collection attribute */
3192*5e7646d2SAndroid Build Coastguard Worker 
3193*5e7646d2SAndroid Build Coastguard Worker 
3194*5e7646d2SAndroid Build Coastguard Worker   if (output == IPPTOOL_OUTPUT_PLIST)
3195*5e7646d2SAndroid Build Coastguard Worker   {
3196*5e7646d2SAndroid Build Coastguard Worker     if (!ippGetName(attr) || (group && *group != ippGetGroupTag(attr)))
3197*5e7646d2SAndroid Build Coastguard Worker     {
3198*5e7646d2SAndroid Build Coastguard Worker       if (ippGetGroupTag(attr) != IPP_TAG_ZERO)
3199*5e7646d2SAndroid Build Coastguard Worker       {
3200*5e7646d2SAndroid Build Coastguard Worker 	cupsFilePuts(outfile, "</dict>\n");
3201*5e7646d2SAndroid Build Coastguard Worker 	cupsFilePuts(outfile, "<dict>\n");
3202*5e7646d2SAndroid Build Coastguard Worker       }
3203*5e7646d2SAndroid Build Coastguard Worker 
3204*5e7646d2SAndroid Build Coastguard Worker       if (group)
3205*5e7646d2SAndroid Build Coastguard Worker         *group = ippGetGroupTag(attr);
3206*5e7646d2SAndroid Build Coastguard Worker     }
3207*5e7646d2SAndroid Build Coastguard Worker 
3208*5e7646d2SAndroid Build Coastguard Worker     if (!ippGetName(attr))
3209*5e7646d2SAndroid Build Coastguard Worker       return;
3210*5e7646d2SAndroid Build Coastguard Worker 
3211*5e7646d2SAndroid Build Coastguard Worker     print_xml_string(outfile, "key", ippGetName(attr));
3212*5e7646d2SAndroid Build Coastguard Worker     if ((count = ippGetCount(attr)) > 1)
3213*5e7646d2SAndroid Build Coastguard Worker       cupsFilePuts(outfile, "<array>\n");
3214*5e7646d2SAndroid Build Coastguard Worker 
3215*5e7646d2SAndroid Build Coastguard Worker     switch (ippGetValueTag(attr))
3216*5e7646d2SAndroid Build Coastguard Worker     {
3217*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_INTEGER :
3218*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_ENUM :
3219*5e7646d2SAndroid Build Coastguard Worker 	  for (i = 0; i < count; i ++)
3220*5e7646d2SAndroid Build Coastguard Worker 	    cupsFilePrintf(outfile, "<integer>%d</integer>\n", ippGetInteger(attr, i));
3221*5e7646d2SAndroid Build Coastguard Worker 	  break;
3222*5e7646d2SAndroid Build Coastguard Worker 
3223*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_BOOLEAN :
3224*5e7646d2SAndroid Build Coastguard Worker 	  for (i = 0; i < count; i ++)
3225*5e7646d2SAndroid Build Coastguard Worker 	    cupsFilePuts(outfile, ippGetBoolean(attr, i) ? "<true />\n" : "<false />\n");
3226*5e7646d2SAndroid Build Coastguard Worker 	  break;
3227*5e7646d2SAndroid Build Coastguard Worker 
3228*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_RANGE :
3229*5e7646d2SAndroid Build Coastguard Worker 	  for (i = 0; i < count; i ++)
3230*5e7646d2SAndroid Build Coastguard Worker 	  {
3231*5e7646d2SAndroid Build Coastguard Worker 	    int lower, upper;		/* Lower and upper ranges */
3232*5e7646d2SAndroid Build Coastguard Worker 
3233*5e7646d2SAndroid Build Coastguard Worker 	    lower = ippGetRange(attr, i, &upper);
3234*5e7646d2SAndroid Build Coastguard Worker 	    cupsFilePrintf(outfile, "<dict><key>lower</key><integer>%d</integer><key>upper</key><integer>%d</integer></dict>\n", lower, upper);
3235*5e7646d2SAndroid Build Coastguard Worker 	  }
3236*5e7646d2SAndroid Build Coastguard Worker 	  break;
3237*5e7646d2SAndroid Build Coastguard Worker 
3238*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_RESOLUTION :
3239*5e7646d2SAndroid Build Coastguard Worker 	  for (i = 0; i < count; i ++)
3240*5e7646d2SAndroid Build Coastguard Worker 	  {
3241*5e7646d2SAndroid Build Coastguard Worker 	    int		xres, yres;	/* Resolution values */
3242*5e7646d2SAndroid Build Coastguard Worker 	    ipp_res_t	units;		/* Resolution units */
3243*5e7646d2SAndroid Build Coastguard Worker 
3244*5e7646d2SAndroid Build Coastguard Worker             xres = ippGetResolution(attr, i, &yres, &units);
3245*5e7646d2SAndroid Build Coastguard Worker 	    cupsFilePrintf(outfile, "<dict><key>xres</key><integer>%d</integer><key>yres</key><integer>%d</integer><key>units</key><string>%s</string></dict>\n", xres, yres, units == IPP_RES_PER_INCH ? "dpi" : "dpcm");
3246*5e7646d2SAndroid Build Coastguard Worker 	  }
3247*5e7646d2SAndroid Build Coastguard Worker 	  break;
3248*5e7646d2SAndroid Build Coastguard Worker 
3249*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_DATE :
3250*5e7646d2SAndroid Build Coastguard Worker 	  for (i = 0; i < count; i ++)
3251*5e7646d2SAndroid Build Coastguard Worker 	    cupsFilePrintf(outfile, "<date>%s</date>\n", iso_date(ippGetDate(attr, i)));
3252*5e7646d2SAndroid Build Coastguard Worker 	  break;
3253*5e7646d2SAndroid Build Coastguard Worker 
3254*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_STRING :
3255*5e7646d2SAndroid Build Coastguard Worker           for (i = 0; i < count; i ++)
3256*5e7646d2SAndroid Build Coastguard Worker           {
3257*5e7646d2SAndroid Build Coastguard Worker             int		datalen;	/* Length of data */
3258*5e7646d2SAndroid Build Coastguard Worker             void	*data = ippGetOctetString(attr, i, &datalen);
3259*5e7646d2SAndroid Build Coastguard Worker 					/* Data */
3260*5e7646d2SAndroid Build Coastguard Worker 	    char	buffer[IPP_MAX_LENGTH * 5 / 4 + 1];
3261*5e7646d2SAndroid Build Coastguard Worker 					/* Base64 output buffer */
3262*5e7646d2SAndroid Build Coastguard Worker 
3263*5e7646d2SAndroid Build Coastguard Worker 	    cupsFilePrintf(outfile, "<data>%s</data>\n", httpEncode64_2(buffer, sizeof(buffer), data, datalen));
3264*5e7646d2SAndroid Build Coastguard Worker           }
3265*5e7646d2SAndroid Build Coastguard Worker           break;
3266*5e7646d2SAndroid Build Coastguard Worker 
3267*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_TEXT :
3268*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_NAME :
3269*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_KEYWORD :
3270*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_URI :
3271*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_URISCHEME :
3272*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_CHARSET :
3273*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_LANGUAGE :
3274*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_MIMETYPE :
3275*5e7646d2SAndroid Build Coastguard Worker 	  for (i = 0; i < count; i ++)
3276*5e7646d2SAndroid Build Coastguard Worker 	    print_xml_string(outfile, "string", ippGetString(attr, i, NULL));
3277*5e7646d2SAndroid Build Coastguard Worker 	  break;
3278*5e7646d2SAndroid Build Coastguard Worker 
3279*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_TEXTLANG :
3280*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_NAMELANG :
3281*5e7646d2SAndroid Build Coastguard Worker 	  for (i = 0; i < count; i ++)
3282*5e7646d2SAndroid Build Coastguard Worker 	  {
3283*5e7646d2SAndroid Build Coastguard Worker 	    const char *s,		/* String */
3284*5e7646d2SAndroid Build Coastguard Worker 			*lang;		/* Language */
3285*5e7646d2SAndroid Build Coastguard Worker 
3286*5e7646d2SAndroid Build Coastguard Worker             s = ippGetString(attr, i, &lang);
3287*5e7646d2SAndroid Build Coastguard Worker 	    cupsFilePuts(outfile, "<dict><key>language</key><string>");
3288*5e7646d2SAndroid Build Coastguard Worker 	    print_xml_string(outfile, NULL, lang);
3289*5e7646d2SAndroid Build Coastguard Worker 	    cupsFilePuts(outfile, "</string><key>string</key><string>");
3290*5e7646d2SAndroid Build Coastguard Worker 	    print_xml_string(outfile, NULL, s);
3291*5e7646d2SAndroid Build Coastguard Worker 	    cupsFilePuts(outfile, "</string></dict>\n");
3292*5e7646d2SAndroid Build Coastguard Worker 	  }
3293*5e7646d2SAndroid Build Coastguard Worker 	  break;
3294*5e7646d2SAndroid Build Coastguard Worker 
3295*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_BEGIN_COLLECTION :
3296*5e7646d2SAndroid Build Coastguard Worker 	  for (i = 0; i < count; i ++)
3297*5e7646d2SAndroid Build Coastguard Worker 	  {
3298*5e7646d2SAndroid Build Coastguard Worker 	    ipp_t *col = ippGetCollection(attr, i);
3299*5e7646d2SAndroid Build Coastguard Worker 					/* Collection value */
3300*5e7646d2SAndroid Build Coastguard Worker 
3301*5e7646d2SAndroid Build Coastguard Worker 	    cupsFilePuts(outfile, "<dict>\n");
3302*5e7646d2SAndroid Build Coastguard Worker 	    for (colattr = ippFirstAttribute(col); colattr; colattr = ippNextAttribute(col))
3303*5e7646d2SAndroid Build Coastguard Worker 	      print_attr(outfile, output, colattr, NULL);
3304*5e7646d2SAndroid Build Coastguard Worker 	    cupsFilePuts(outfile, "</dict>\n");
3305*5e7646d2SAndroid Build Coastguard Worker 	  }
3306*5e7646d2SAndroid Build Coastguard Worker 	  break;
3307*5e7646d2SAndroid Build Coastguard Worker 
3308*5e7646d2SAndroid Build Coastguard Worker       default :
3309*5e7646d2SAndroid Build Coastguard Worker 	  cupsFilePrintf(outfile, "<string>&lt;&lt;%s&gt;&gt;</string>\n", ippTagString(ippGetValueTag(attr)));
3310*5e7646d2SAndroid Build Coastguard Worker 	  break;
3311*5e7646d2SAndroid Build Coastguard Worker     }
3312*5e7646d2SAndroid Build Coastguard Worker 
3313*5e7646d2SAndroid Build Coastguard Worker     if (count > 1)
3314*5e7646d2SAndroid Build Coastguard Worker       cupsFilePuts(outfile, "</array>\n");
3315*5e7646d2SAndroid Build Coastguard Worker   }
3316*5e7646d2SAndroid Build Coastguard Worker   else
3317*5e7646d2SAndroid Build Coastguard Worker   {
3318*5e7646d2SAndroid Build Coastguard Worker     char	buffer[131072];		/* Value buffer */
3319*5e7646d2SAndroid Build Coastguard Worker 
3320*5e7646d2SAndroid Build Coastguard Worker     if (output == IPPTOOL_OUTPUT_TEST)
3321*5e7646d2SAndroid Build Coastguard Worker     {
3322*5e7646d2SAndroid Build Coastguard Worker       if (!ippGetName(attr))
3323*5e7646d2SAndroid Build Coastguard Worker       {
3324*5e7646d2SAndroid Build Coastguard Worker         cupsFilePuts(outfile, "        -- separator --\n");
3325*5e7646d2SAndroid Build Coastguard Worker         return;
3326*5e7646d2SAndroid Build Coastguard Worker       }
3327*5e7646d2SAndroid Build Coastguard Worker 
3328*5e7646d2SAndroid Build Coastguard Worker       cupsFilePrintf(outfile, "        %s (%s%s) = ", ippGetName(attr), ippGetCount(attr) > 1 ? "1setOf " : "", ippTagString(ippGetValueTag(attr)));
3329*5e7646d2SAndroid Build Coastguard Worker     }
3330*5e7646d2SAndroid Build Coastguard Worker 
3331*5e7646d2SAndroid Build Coastguard Worker     ippAttributeString(attr, buffer, sizeof(buffer));
3332*5e7646d2SAndroid Build Coastguard Worker     cupsFilePrintf(outfile, "%s\n", buffer);
3333*5e7646d2SAndroid Build Coastguard Worker   }
3334*5e7646d2SAndroid Build Coastguard Worker }
3335*5e7646d2SAndroid Build Coastguard Worker 
3336*5e7646d2SAndroid Build Coastguard Worker 
3337*5e7646d2SAndroid Build Coastguard Worker /*
3338*5e7646d2SAndroid Build Coastguard Worker  * 'print_csv()' - Print a line of CSV text.
3339*5e7646d2SAndroid Build Coastguard Worker  */
3340*5e7646d2SAndroid Build Coastguard Worker 
3341*5e7646d2SAndroid Build Coastguard Worker static ipp_attribute_t *		/* O - Next attribute */
print_csv(ipptool_test_t * data,ipp_t * ipp,ipp_attribute_t * attr,int num_displayed,char ** displayed,size_t * widths)3342*5e7646d2SAndroid Build Coastguard Worker print_csv(
3343*5e7646d2SAndroid Build Coastguard Worker     ipptool_test_t  *data,		/* I - Test data */
3344*5e7646d2SAndroid Build Coastguard Worker     ipp_t           *ipp,		/* I - Response message */
3345*5e7646d2SAndroid Build Coastguard Worker     ipp_attribute_t *attr,		/* I - First attribute for line */
3346*5e7646d2SAndroid Build Coastguard Worker     int             num_displayed,	/* I - Number of attributes to display */
3347*5e7646d2SAndroid Build Coastguard Worker     char            **displayed,	/* I - Attributes to display */
3348*5e7646d2SAndroid Build Coastguard Worker     size_t          *widths)		/* I - Column widths */
3349*5e7646d2SAndroid Build Coastguard Worker {
3350*5e7646d2SAndroid Build Coastguard Worker   int		i;			/* Looping var */
3351*5e7646d2SAndroid Build Coastguard Worker   size_t	maxlength;		/* Max length of all columns */
3352*5e7646d2SAndroid Build Coastguard Worker   ipp_attribute_t *current = attr;	/* Current attribute */
3353*5e7646d2SAndroid Build Coastguard Worker   char		*values[MAX_DISPLAY],	/* Strings to display */
3354*5e7646d2SAndroid Build Coastguard Worker 		*valptr;		/* Pointer into value */
3355*5e7646d2SAndroid Build Coastguard Worker 
3356*5e7646d2SAndroid Build Coastguard Worker  /*
3357*5e7646d2SAndroid Build Coastguard Worker   * Get the maximum string length we have to show and allocate...
3358*5e7646d2SAndroid Build Coastguard Worker   */
3359*5e7646d2SAndroid Build Coastguard Worker 
3360*5e7646d2SAndroid Build Coastguard Worker   for (i = 1, maxlength = widths[0]; i < num_displayed; i ++)
3361*5e7646d2SAndroid Build Coastguard Worker     if (widths[i] > maxlength)
3362*5e7646d2SAndroid Build Coastguard Worker       maxlength = widths[i];
3363*5e7646d2SAndroid Build Coastguard Worker 
3364*5e7646d2SAndroid Build Coastguard Worker   maxlength += 2;
3365*5e7646d2SAndroid Build Coastguard Worker 
3366*5e7646d2SAndroid Build Coastguard Worker  /*
3367*5e7646d2SAndroid Build Coastguard Worker   * Loop through the attributes to display...
3368*5e7646d2SAndroid Build Coastguard Worker   */
3369*5e7646d2SAndroid Build Coastguard Worker 
3370*5e7646d2SAndroid Build Coastguard Worker   if (attr)
3371*5e7646d2SAndroid Build Coastguard Worker   {
3372*5e7646d2SAndroid Build Coastguard Worker     // Collect the values...
3373*5e7646d2SAndroid Build Coastguard Worker     memset(values, 0, sizeof(values));
3374*5e7646d2SAndroid Build Coastguard Worker 
3375*5e7646d2SAndroid Build Coastguard Worker     for (; current; current = ippNextAttribute(ipp))
3376*5e7646d2SAndroid Build Coastguard Worker     {
3377*5e7646d2SAndroid Build Coastguard Worker       if (!ippGetName(current))
3378*5e7646d2SAndroid Build Coastguard Worker 	break;
3379*5e7646d2SAndroid Build Coastguard Worker 
3380*5e7646d2SAndroid Build Coastguard Worker       for (i = 0; i < num_displayed; i ++)
3381*5e7646d2SAndroid Build Coastguard Worker       {
3382*5e7646d2SAndroid Build Coastguard Worker         if (!strcmp(ippGetName(current), displayed[i]))
3383*5e7646d2SAndroid Build Coastguard Worker         {
3384*5e7646d2SAndroid Build Coastguard Worker           if ((values[i] = (char *)calloc(1, maxlength)) != NULL)
3385*5e7646d2SAndroid Build Coastguard Worker 	    ippAttributeString(current, values[i], maxlength);
3386*5e7646d2SAndroid Build Coastguard Worker           break;
3387*5e7646d2SAndroid Build Coastguard Worker 	}
3388*5e7646d2SAndroid Build Coastguard Worker       }
3389*5e7646d2SAndroid Build Coastguard Worker     }
3390*5e7646d2SAndroid Build Coastguard Worker 
3391*5e7646d2SAndroid Build Coastguard Worker     // Output the line...
3392*5e7646d2SAndroid Build Coastguard Worker     for (i = 0; i < num_displayed; i ++)
3393*5e7646d2SAndroid Build Coastguard Worker     {
3394*5e7646d2SAndroid Build Coastguard Worker       if (i)
3395*5e7646d2SAndroid Build Coastguard Worker         cupsFilePutChar(data->outfile, ',');
3396*5e7646d2SAndroid Build Coastguard Worker 
3397*5e7646d2SAndroid Build Coastguard Worker       if (!values[i])
3398*5e7646d2SAndroid Build Coastguard Worker         continue;
3399*5e7646d2SAndroid Build Coastguard Worker 
3400*5e7646d2SAndroid Build Coastguard Worker       if (strchr(values[i], ',') != NULL || strchr(values[i], '\"') != NULL || strchr(values[i], '\\') != NULL)
3401*5e7646d2SAndroid Build Coastguard Worker       {
3402*5e7646d2SAndroid Build Coastguard Worker         // Quoted value...
3403*5e7646d2SAndroid Build Coastguard Worker         cupsFilePutChar(data->outfile, '\"');
3404*5e7646d2SAndroid Build Coastguard Worker         for (valptr = values[i]; *valptr; valptr ++)
3405*5e7646d2SAndroid Build Coastguard Worker         {
3406*5e7646d2SAndroid Build Coastguard Worker           if (*valptr == '\\' || *valptr == '\"')
3407*5e7646d2SAndroid Build Coastguard Worker             cupsFilePutChar(data->outfile, '\\');
3408*5e7646d2SAndroid Build Coastguard Worker           cupsFilePutChar(data->outfile, *valptr);
3409*5e7646d2SAndroid Build Coastguard Worker         }
3410*5e7646d2SAndroid Build Coastguard Worker         cupsFilePutChar(data->outfile, '\"');
3411*5e7646d2SAndroid Build Coastguard Worker       }
3412*5e7646d2SAndroid Build Coastguard Worker       else
3413*5e7646d2SAndroid Build Coastguard Worker       {
3414*5e7646d2SAndroid Build Coastguard Worker         // Unquoted value...
3415*5e7646d2SAndroid Build Coastguard Worker         cupsFilePuts(data->outfile, values[i]);
3416*5e7646d2SAndroid Build Coastguard Worker       }
3417*5e7646d2SAndroid Build Coastguard Worker 
3418*5e7646d2SAndroid Build Coastguard Worker       free(values[i]);
3419*5e7646d2SAndroid Build Coastguard Worker     }
3420*5e7646d2SAndroid Build Coastguard Worker     cupsFilePutChar(data->outfile, '\n');
3421*5e7646d2SAndroid Build Coastguard Worker   }
3422*5e7646d2SAndroid Build Coastguard Worker   else
3423*5e7646d2SAndroid Build Coastguard Worker   {
3424*5e7646d2SAndroid Build Coastguard Worker     // Show column headings...
3425*5e7646d2SAndroid Build Coastguard Worker     for (i = 0; i < num_displayed; i ++)
3426*5e7646d2SAndroid Build Coastguard Worker     {
3427*5e7646d2SAndroid Build Coastguard Worker       if (i)
3428*5e7646d2SAndroid Build Coastguard Worker         cupsFilePutChar(data->outfile, ',');
3429*5e7646d2SAndroid Build Coastguard Worker 
3430*5e7646d2SAndroid Build Coastguard Worker       cupsFilePuts(data->outfile, displayed[i]);
3431*5e7646d2SAndroid Build Coastguard Worker     }
3432*5e7646d2SAndroid Build Coastguard Worker     cupsFilePutChar(data->outfile, '\n');
3433*5e7646d2SAndroid Build Coastguard Worker   }
3434*5e7646d2SAndroid Build Coastguard Worker 
3435*5e7646d2SAndroid Build Coastguard Worker   return (current);
3436*5e7646d2SAndroid Build Coastguard Worker }
3437*5e7646d2SAndroid Build Coastguard Worker 
3438*5e7646d2SAndroid Build Coastguard Worker 
3439*5e7646d2SAndroid Build Coastguard Worker /*
3440*5e7646d2SAndroid Build Coastguard Worker  * 'print_fatal_error()' - Print a fatal error message.
3441*5e7646d2SAndroid Build Coastguard Worker  */
3442*5e7646d2SAndroid Build Coastguard Worker 
3443*5e7646d2SAndroid Build Coastguard Worker static void
print_fatal_error(ipptool_test_t * data,const char * s,...)3444*5e7646d2SAndroid Build Coastguard Worker print_fatal_error(
3445*5e7646d2SAndroid Build Coastguard Worker     ipptool_test_t *data,		/* I - Test data */
3446*5e7646d2SAndroid Build Coastguard Worker     const char       *s,		/* I - Printf-style format string */
3447*5e7646d2SAndroid Build Coastguard Worker     ...)				/* I - Additional arguments as needed */
3448*5e7646d2SAndroid Build Coastguard Worker {
3449*5e7646d2SAndroid Build Coastguard Worker   char		buffer[10240];		/* Format buffer */
3450*5e7646d2SAndroid Build Coastguard Worker   va_list	ap;			/* Pointer to arguments */
3451*5e7646d2SAndroid Build Coastguard Worker 
3452*5e7646d2SAndroid Build Coastguard Worker 
3453*5e7646d2SAndroid Build Coastguard Worker  /*
3454*5e7646d2SAndroid Build Coastguard Worker   * Format the error message...
3455*5e7646d2SAndroid Build Coastguard Worker   */
3456*5e7646d2SAndroid Build Coastguard Worker 
3457*5e7646d2SAndroid Build Coastguard Worker   va_start(ap, s);
3458*5e7646d2SAndroid Build Coastguard Worker   vsnprintf(buffer, sizeof(buffer), s, ap);
3459*5e7646d2SAndroid Build Coastguard Worker   va_end(ap);
3460*5e7646d2SAndroid Build Coastguard Worker 
3461*5e7646d2SAndroid Build Coastguard Worker  /*
3462*5e7646d2SAndroid Build Coastguard Worker   * Then output it...
3463*5e7646d2SAndroid Build Coastguard Worker   */
3464*5e7646d2SAndroid Build Coastguard Worker 
3465*5e7646d2SAndroid Build Coastguard Worker   if (data->output == IPPTOOL_OUTPUT_PLIST)
3466*5e7646d2SAndroid Build Coastguard Worker   {
3467*5e7646d2SAndroid Build Coastguard Worker     print_xml_header(data);
3468*5e7646d2SAndroid Build Coastguard Worker     print_xml_trailer(data, 0, buffer);
3469*5e7646d2SAndroid Build Coastguard Worker   }
3470*5e7646d2SAndroid Build Coastguard Worker 
3471*5e7646d2SAndroid Build Coastguard Worker   _cupsLangPrintf(stderr, "ipptool: %s", buffer);
3472*5e7646d2SAndroid Build Coastguard Worker }
3473*5e7646d2SAndroid Build Coastguard Worker 
3474*5e7646d2SAndroid Build Coastguard Worker 
3475*5e7646d2SAndroid Build Coastguard Worker /*
3476*5e7646d2SAndroid Build Coastguard Worker  * 'print_ippserver_attr()' - Print a attribute suitable for use by ippserver.
3477*5e7646d2SAndroid Build Coastguard Worker  */
3478*5e7646d2SAndroid Build Coastguard Worker 
3479*5e7646d2SAndroid Build Coastguard Worker static void
print_ippserver_attr(ipptool_test_t * data,ipp_attribute_t * attr,int indent)3480*5e7646d2SAndroid Build Coastguard Worker print_ippserver_attr(
3481*5e7646d2SAndroid Build Coastguard Worker     ipptool_test_t *data,		/* I - Test data */
3482*5e7646d2SAndroid Build Coastguard Worker     ipp_attribute_t  *attr,		/* I - Attribute to print */
3483*5e7646d2SAndroid Build Coastguard Worker     int              indent)		/* I - Indentation level */
3484*5e7646d2SAndroid Build Coastguard Worker {
3485*5e7646d2SAndroid Build Coastguard Worker   int			i,		/* Looping var */
3486*5e7646d2SAndroid Build Coastguard Worker 			count = ippGetCount(attr);
3487*5e7646d2SAndroid Build Coastguard Worker 					/* Number of values */
3488*5e7646d2SAndroid Build Coastguard Worker   ipp_attribute_t	*colattr;	/* Collection attribute */
3489*5e7646d2SAndroid Build Coastguard Worker 
3490*5e7646d2SAndroid Build Coastguard Worker 
3491*5e7646d2SAndroid Build Coastguard Worker   if (indent == 0)
3492*5e7646d2SAndroid Build Coastguard Worker     cupsFilePrintf(data->outfile, "ATTR %s %s", ippTagString(ippGetValueTag(attr)), ippGetName(attr));
3493*5e7646d2SAndroid Build Coastguard Worker   else
3494*5e7646d2SAndroid Build Coastguard Worker     cupsFilePrintf(data->outfile, "%*sMEMBER %s %s", indent, "", ippTagString(ippGetValueTag(attr)), ippGetName(attr));
3495*5e7646d2SAndroid Build Coastguard Worker 
3496*5e7646d2SAndroid Build Coastguard Worker   switch (ippGetValueTag(attr))
3497*5e7646d2SAndroid Build Coastguard Worker   {
3498*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_INTEGER :
3499*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_ENUM :
3500*5e7646d2SAndroid Build Coastguard Worker 	for (i = 0; i < count; i ++)
3501*5e7646d2SAndroid Build Coastguard Worker 	  cupsFilePrintf(data->outfile, "%s%d", i ? "," : " ", ippGetInteger(attr, i));
3502*5e7646d2SAndroid Build Coastguard Worker 	break;
3503*5e7646d2SAndroid Build Coastguard Worker 
3504*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_BOOLEAN :
3505*5e7646d2SAndroid Build Coastguard Worker 	cupsFilePuts(data->outfile, ippGetBoolean(attr, 0) ? " true" : " false");
3506*5e7646d2SAndroid Build Coastguard Worker 
3507*5e7646d2SAndroid Build Coastguard Worker 	for (i = 1; i < count; i ++)
3508*5e7646d2SAndroid Build Coastguard Worker 	  cupsFilePuts(data->outfile, ippGetBoolean(attr, 1) ? ",true" : ",false");
3509*5e7646d2SAndroid Build Coastguard Worker 	break;
3510*5e7646d2SAndroid Build Coastguard Worker 
3511*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_RANGE :
3512*5e7646d2SAndroid Build Coastguard Worker 	for (i = 0; i < count; i ++)
3513*5e7646d2SAndroid Build Coastguard Worker 	{
3514*5e7646d2SAndroid Build Coastguard Worker 	  int upper, lower = ippGetRange(attr, i, &upper);
3515*5e7646d2SAndroid Build Coastguard Worker 
3516*5e7646d2SAndroid Build Coastguard Worker 	  cupsFilePrintf(data->outfile, "%s%d-%d", i ? "," : " ", lower, upper);
3517*5e7646d2SAndroid Build Coastguard Worker 	}
3518*5e7646d2SAndroid Build Coastguard Worker 	break;
3519*5e7646d2SAndroid Build Coastguard Worker 
3520*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_RESOLUTION :
3521*5e7646d2SAndroid Build Coastguard Worker 	for (i = 0; i < count; i ++)
3522*5e7646d2SAndroid Build Coastguard Worker 	{
3523*5e7646d2SAndroid Build Coastguard Worker 	  ipp_res_t units;
3524*5e7646d2SAndroid Build Coastguard Worker 	  int yres, xres = ippGetResolution(attr, i, &yres, &units);
3525*5e7646d2SAndroid Build Coastguard Worker 
3526*5e7646d2SAndroid Build Coastguard Worker 	  cupsFilePrintf(data->outfile, "%s%dx%d%s", i ? "," : " ", xres, yres, units == IPP_RES_PER_INCH ? "dpi" : "dpcm");
3527*5e7646d2SAndroid Build Coastguard Worker 	}
3528*5e7646d2SAndroid Build Coastguard Worker 	break;
3529*5e7646d2SAndroid Build Coastguard Worker 
3530*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_DATE :
3531*5e7646d2SAndroid Build Coastguard Worker 	for (i = 0; i < count; i ++)
3532*5e7646d2SAndroid Build Coastguard Worker 	  cupsFilePrintf(data->outfile, "%s%s", i ? "," : " ", iso_date(ippGetDate(attr, i)));
3533*5e7646d2SAndroid Build Coastguard Worker 	break;
3534*5e7646d2SAndroid Build Coastguard Worker 
3535*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_STRING :
3536*5e7646d2SAndroid Build Coastguard Worker 	for (i = 0; i < count; i ++)
3537*5e7646d2SAndroid Build Coastguard Worker 	{
3538*5e7646d2SAndroid Build Coastguard Worker 	  int len;
3539*5e7646d2SAndroid Build Coastguard Worker 	  const char *s = (const char *)ippGetOctetString(attr, i, &len);
3540*5e7646d2SAndroid Build Coastguard Worker 
3541*5e7646d2SAndroid Build Coastguard Worker 	  cupsFilePuts(data->outfile, i ? "," : " ");
3542*5e7646d2SAndroid Build Coastguard Worker 	  print_ippserver_string(data, s, (size_t)len);
3543*5e7646d2SAndroid Build Coastguard Worker 	}
3544*5e7646d2SAndroid Build Coastguard Worker 	break;
3545*5e7646d2SAndroid Build Coastguard Worker 
3546*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_TEXT :
3547*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_TEXTLANG :
3548*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_NAME :
3549*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_NAMELANG :
3550*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_KEYWORD :
3551*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_URI :
3552*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_URISCHEME :
3553*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_CHARSET :
3554*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_LANGUAGE :
3555*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_MIMETYPE :
3556*5e7646d2SAndroid Build Coastguard Worker 	for (i = 0; i < count; i ++)
3557*5e7646d2SAndroid Build Coastguard Worker 	{
3558*5e7646d2SAndroid Build Coastguard Worker 	  const char *s = ippGetString(attr, i, NULL);
3559*5e7646d2SAndroid Build Coastguard Worker 
3560*5e7646d2SAndroid Build Coastguard Worker 	  cupsFilePuts(data->outfile, i ? "," : " ");
3561*5e7646d2SAndroid Build Coastguard Worker 	  print_ippserver_string(data, s, strlen(s));
3562*5e7646d2SAndroid Build Coastguard Worker 	}
3563*5e7646d2SAndroid Build Coastguard Worker 	break;
3564*5e7646d2SAndroid Build Coastguard Worker 
3565*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_BEGIN_COLLECTION :
3566*5e7646d2SAndroid Build Coastguard Worker 	for (i = 0; i < count; i ++)
3567*5e7646d2SAndroid Build Coastguard Worker 	{
3568*5e7646d2SAndroid Build Coastguard Worker 	  ipp_t *col = ippGetCollection(attr, i);
3569*5e7646d2SAndroid Build Coastguard Worker 
3570*5e7646d2SAndroid Build Coastguard Worker 	  cupsFilePuts(data->outfile, i ? ",{\n" : " {\n");
3571*5e7646d2SAndroid Build Coastguard Worker 	  for (colattr = ippFirstAttribute(col); colattr; colattr = ippNextAttribute(col))
3572*5e7646d2SAndroid Build Coastguard Worker 	    print_ippserver_attr(data, colattr, indent + 4);
3573*5e7646d2SAndroid Build Coastguard Worker 	  cupsFilePrintf(data->outfile, "%*s}", indent, "");
3574*5e7646d2SAndroid Build Coastguard Worker 	}
3575*5e7646d2SAndroid Build Coastguard Worker 	break;
3576*5e7646d2SAndroid Build Coastguard Worker 
3577*5e7646d2SAndroid Build Coastguard Worker     default :
3578*5e7646d2SAndroid Build Coastguard Worker         /* Out-of-band value */
3579*5e7646d2SAndroid Build Coastguard Worker 	break;
3580*5e7646d2SAndroid Build Coastguard Worker   }
3581*5e7646d2SAndroid Build Coastguard Worker 
3582*5e7646d2SAndroid Build Coastguard Worker   cupsFilePuts(data->outfile, "\n");
3583*5e7646d2SAndroid Build Coastguard Worker }
3584*5e7646d2SAndroid Build Coastguard Worker 
3585*5e7646d2SAndroid Build Coastguard Worker 
3586*5e7646d2SAndroid Build Coastguard Worker /*
3587*5e7646d2SAndroid Build Coastguard Worker  * 'print_ippserver_string()' - Print a string suitable for use by ippserver.
3588*5e7646d2SAndroid Build Coastguard Worker  */
3589*5e7646d2SAndroid Build Coastguard Worker 
3590*5e7646d2SAndroid Build Coastguard Worker static void
print_ippserver_string(ipptool_test_t * data,const char * s,size_t len)3591*5e7646d2SAndroid Build Coastguard Worker print_ippserver_string(
3592*5e7646d2SAndroid Build Coastguard Worker     ipptool_test_t *data,		/* I - Test data */
3593*5e7646d2SAndroid Build Coastguard Worker     const char       *s,		/* I - String to print */
3594*5e7646d2SAndroid Build Coastguard Worker     size_t           len)		/* I - Length of string */
3595*5e7646d2SAndroid Build Coastguard Worker {
3596*5e7646d2SAndroid Build Coastguard Worker   cupsFilePutChar(data->outfile, '\"');
3597*5e7646d2SAndroid Build Coastguard Worker   while (len > 0)
3598*5e7646d2SAndroid Build Coastguard Worker   {
3599*5e7646d2SAndroid Build Coastguard Worker     if (*s == '\"')
3600*5e7646d2SAndroid Build Coastguard Worker       cupsFilePutChar(data->outfile, '\\');
3601*5e7646d2SAndroid Build Coastguard Worker     cupsFilePutChar(data->outfile, *s);
3602*5e7646d2SAndroid Build Coastguard Worker 
3603*5e7646d2SAndroid Build Coastguard Worker     s ++;
3604*5e7646d2SAndroid Build Coastguard Worker     len --;
3605*5e7646d2SAndroid Build Coastguard Worker   }
3606*5e7646d2SAndroid Build Coastguard Worker   cupsFilePutChar(data->outfile, '\"');
3607*5e7646d2SAndroid Build Coastguard Worker }
3608*5e7646d2SAndroid Build Coastguard Worker 
3609*5e7646d2SAndroid Build Coastguard Worker 
3610*5e7646d2SAndroid Build Coastguard Worker /*
3611*5e7646d2SAndroid Build Coastguard Worker  * 'print_line()' - Print a line of formatted or CSV text.
3612*5e7646d2SAndroid Build Coastguard Worker  */
3613*5e7646d2SAndroid Build Coastguard Worker 
3614*5e7646d2SAndroid Build Coastguard Worker static ipp_attribute_t *		/* O - Next attribute */
print_line(ipptool_test_t * data,ipp_t * ipp,ipp_attribute_t * attr,int num_displayed,char ** displayed,size_t * widths)3615*5e7646d2SAndroid Build Coastguard Worker print_line(
3616*5e7646d2SAndroid Build Coastguard Worker     ipptool_test_t *data,		/* I - Test data */
3617*5e7646d2SAndroid Build Coastguard Worker     ipp_t            *ipp,		/* I - Response message */
3618*5e7646d2SAndroid Build Coastguard Worker     ipp_attribute_t  *attr,		/* I - First attribute for line */
3619*5e7646d2SAndroid Build Coastguard Worker     int              num_displayed,	/* I - Number of attributes to display */
3620*5e7646d2SAndroid Build Coastguard Worker     char             **displayed,	/* I - Attributes to display */
3621*5e7646d2SAndroid Build Coastguard Worker     size_t           *widths)		/* I - Column widths */
3622*5e7646d2SAndroid Build Coastguard Worker {
3623*5e7646d2SAndroid Build Coastguard Worker   int		i;			/* Looping var */
3624*5e7646d2SAndroid Build Coastguard Worker   size_t	maxlength;		/* Max length of all columns */
3625*5e7646d2SAndroid Build Coastguard Worker   ipp_attribute_t *current = attr;	/* Current attribute */
3626*5e7646d2SAndroid Build Coastguard Worker   char		*values[MAX_DISPLAY];	/* Strings to display */
3627*5e7646d2SAndroid Build Coastguard Worker 
3628*5e7646d2SAndroid Build Coastguard Worker 
3629*5e7646d2SAndroid Build Coastguard Worker  /*
3630*5e7646d2SAndroid Build Coastguard Worker   * Get the maximum string length we have to show and allocate...
3631*5e7646d2SAndroid Build Coastguard Worker   */
3632*5e7646d2SAndroid Build Coastguard Worker 
3633*5e7646d2SAndroid Build Coastguard Worker   for (i = 1, maxlength = widths[0]; i < num_displayed; i ++)
3634*5e7646d2SAndroid Build Coastguard Worker     if (widths[i] > maxlength)
3635*5e7646d2SAndroid Build Coastguard Worker       maxlength = widths[i];
3636*5e7646d2SAndroid Build Coastguard Worker 
3637*5e7646d2SAndroid Build Coastguard Worker   maxlength += 2;
3638*5e7646d2SAndroid Build Coastguard Worker 
3639*5e7646d2SAndroid Build Coastguard Worker  /*
3640*5e7646d2SAndroid Build Coastguard Worker   * Loop through the attributes to display...
3641*5e7646d2SAndroid Build Coastguard Worker   */
3642*5e7646d2SAndroid Build Coastguard Worker 
3643*5e7646d2SAndroid Build Coastguard Worker   if (attr)
3644*5e7646d2SAndroid Build Coastguard Worker   {
3645*5e7646d2SAndroid Build Coastguard Worker     // Collect the values...
3646*5e7646d2SAndroid Build Coastguard Worker     memset(values, 0, sizeof(values));
3647*5e7646d2SAndroid Build Coastguard Worker 
3648*5e7646d2SAndroid Build Coastguard Worker     for (; current; current = ippNextAttribute(ipp))
3649*5e7646d2SAndroid Build Coastguard Worker     {
3650*5e7646d2SAndroid Build Coastguard Worker       if (!ippGetName(current))
3651*5e7646d2SAndroid Build Coastguard Worker 	break;
3652*5e7646d2SAndroid Build Coastguard Worker 
3653*5e7646d2SAndroid Build Coastguard Worker       for (i = 0; i < num_displayed; i ++)
3654*5e7646d2SAndroid Build Coastguard Worker       {
3655*5e7646d2SAndroid Build Coastguard Worker         if (!strcmp(ippGetName(current), displayed[i]))
3656*5e7646d2SAndroid Build Coastguard Worker         {
3657*5e7646d2SAndroid Build Coastguard Worker           if ((values[i] = (char *)calloc(1, maxlength)) != NULL)
3658*5e7646d2SAndroid Build Coastguard Worker 	    ippAttributeString(current, values[i], maxlength);
3659*5e7646d2SAndroid Build Coastguard Worker           break;
3660*5e7646d2SAndroid Build Coastguard Worker 	}
3661*5e7646d2SAndroid Build Coastguard Worker       }
3662*5e7646d2SAndroid Build Coastguard Worker     }
3663*5e7646d2SAndroid Build Coastguard Worker 
3664*5e7646d2SAndroid Build Coastguard Worker     // Output the line...
3665*5e7646d2SAndroid Build Coastguard Worker     for (i = 0; i < num_displayed; i ++)
3666*5e7646d2SAndroid Build Coastguard Worker     {
3667*5e7646d2SAndroid Build Coastguard Worker       if (i)
3668*5e7646d2SAndroid Build Coastguard Worker         cupsFilePutChar(data->outfile, ' ');
3669*5e7646d2SAndroid Build Coastguard Worker 
3670*5e7646d2SAndroid Build Coastguard Worker       cupsFilePrintf(data->outfile, "%*s", (int)-widths[i], values[i] ? values[i] : "");
3671*5e7646d2SAndroid Build Coastguard Worker       free(values[i]);
3672*5e7646d2SAndroid Build Coastguard Worker     }
3673*5e7646d2SAndroid Build Coastguard Worker     cupsFilePutChar(data->outfile, '\n');
3674*5e7646d2SAndroid Build Coastguard Worker   }
3675*5e7646d2SAndroid Build Coastguard Worker   else
3676*5e7646d2SAndroid Build Coastguard Worker   {
3677*5e7646d2SAndroid Build Coastguard Worker     // Show column headings...
3678*5e7646d2SAndroid Build Coastguard Worker     char *buffer = (char *)malloc(maxlength);
3679*5e7646d2SAndroid Build Coastguard Worker 					// Buffer for separator lines
3680*5e7646d2SAndroid Build Coastguard Worker 
3681*5e7646d2SAndroid Build Coastguard Worker     if (!buffer)
3682*5e7646d2SAndroid Build Coastguard Worker       return (current);
3683*5e7646d2SAndroid Build Coastguard Worker 
3684*5e7646d2SAndroid Build Coastguard Worker     for (i = 0; i < num_displayed; i ++)
3685*5e7646d2SAndroid Build Coastguard Worker     {
3686*5e7646d2SAndroid Build Coastguard Worker       if (i)
3687*5e7646d2SAndroid Build Coastguard Worker         cupsFilePutChar(data->outfile, ' ');
3688*5e7646d2SAndroid Build Coastguard Worker 
3689*5e7646d2SAndroid Build Coastguard Worker       cupsFilePrintf(data->outfile, "%*s", (int)-widths[i], displayed[i]);
3690*5e7646d2SAndroid Build Coastguard Worker     }
3691*5e7646d2SAndroid Build Coastguard Worker     cupsFilePutChar(data->outfile, '\n');
3692*5e7646d2SAndroid Build Coastguard Worker 
3693*5e7646d2SAndroid Build Coastguard Worker     for (i = 0; i < num_displayed; i ++)
3694*5e7646d2SAndroid Build Coastguard Worker     {
3695*5e7646d2SAndroid Build Coastguard Worker       if (i)
3696*5e7646d2SAndroid Build Coastguard Worker 	cupsFilePutChar(data->outfile, ' ');
3697*5e7646d2SAndroid Build Coastguard Worker 
3698*5e7646d2SAndroid Build Coastguard Worker       memset(buffer, '-', widths[i]);
3699*5e7646d2SAndroid Build Coastguard Worker       buffer[widths[i]] = '\0';
3700*5e7646d2SAndroid Build Coastguard Worker       cupsFilePuts(data->outfile, buffer);
3701*5e7646d2SAndroid Build Coastguard Worker     }
3702*5e7646d2SAndroid Build Coastguard Worker     cupsFilePutChar(data->outfile, '\n');
3703*5e7646d2SAndroid Build Coastguard Worker     free(buffer);
3704*5e7646d2SAndroid Build Coastguard Worker   }
3705*5e7646d2SAndroid Build Coastguard Worker 
3706*5e7646d2SAndroid Build Coastguard Worker   return (current);
3707*5e7646d2SAndroid Build Coastguard Worker }
3708*5e7646d2SAndroid Build Coastguard Worker 
3709*5e7646d2SAndroid Build Coastguard Worker 
3710*5e7646d2SAndroid Build Coastguard Worker /*
3711*5e7646d2SAndroid Build Coastguard Worker  * 'print_xml_header()' - Print a standard XML plist header.
3712*5e7646d2SAndroid Build Coastguard Worker  */
3713*5e7646d2SAndroid Build Coastguard Worker 
3714*5e7646d2SAndroid Build Coastguard Worker static void
print_xml_header(ipptool_test_t * data)3715*5e7646d2SAndroid Build Coastguard Worker print_xml_header(ipptool_test_t *data)/* I - Test data */
3716*5e7646d2SAndroid Build Coastguard Worker {
3717*5e7646d2SAndroid Build Coastguard Worker   if (!data->xml_header)
3718*5e7646d2SAndroid Build Coastguard Worker   {
3719*5e7646d2SAndroid Build Coastguard Worker     cupsFilePuts(data->outfile, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
3720*5e7646d2SAndroid Build Coastguard Worker     cupsFilePuts(data->outfile, "<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n");
3721*5e7646d2SAndroid Build Coastguard Worker     cupsFilePuts(data->outfile, "<plist version=\"1.0\">\n");
3722*5e7646d2SAndroid Build Coastguard Worker     cupsFilePuts(data->outfile, "<dict>\n");
3723*5e7646d2SAndroid Build Coastguard Worker     cupsFilePuts(data->outfile, "<key>ipptoolVersion</key>\n");
3724*5e7646d2SAndroid Build Coastguard Worker     cupsFilePuts(data->outfile, "<string>" CUPS_SVERSION "</string>\n");
3725*5e7646d2SAndroid Build Coastguard Worker     cupsFilePuts(data->outfile, "<key>Transfer</key>\n");
3726*5e7646d2SAndroid Build Coastguard Worker     cupsFilePrintf(data->outfile, "<string>%s</string>\n", data->transfer == IPPTOOL_TRANSFER_AUTO ? "auto" : data->transfer == IPPTOOL_TRANSFER_CHUNKED ? "chunked" : "length");
3727*5e7646d2SAndroid Build Coastguard Worker     cupsFilePuts(data->outfile, "<key>Tests</key>\n");
3728*5e7646d2SAndroid Build Coastguard Worker     cupsFilePuts(data->outfile, "<array>\n");
3729*5e7646d2SAndroid Build Coastguard Worker 
3730*5e7646d2SAndroid Build Coastguard Worker     data->xml_header = 1;
3731*5e7646d2SAndroid Build Coastguard Worker   }
3732*5e7646d2SAndroid Build Coastguard Worker }
3733*5e7646d2SAndroid Build Coastguard Worker 
3734*5e7646d2SAndroid Build Coastguard Worker 
3735*5e7646d2SAndroid Build Coastguard Worker /*
3736*5e7646d2SAndroid Build Coastguard Worker  * 'print_xml_string()' - Print an XML string with escaping.
3737*5e7646d2SAndroid Build Coastguard Worker  */
3738*5e7646d2SAndroid Build Coastguard Worker 
3739*5e7646d2SAndroid Build Coastguard Worker static void
print_xml_string(cups_file_t * outfile,const char * element,const char * s)3740*5e7646d2SAndroid Build Coastguard Worker print_xml_string(cups_file_t *outfile,	/* I - Test data */
3741*5e7646d2SAndroid Build Coastguard Worker 		 const char  *element,	/* I - Element name or NULL */
3742*5e7646d2SAndroid Build Coastguard Worker 		 const char  *s)	/* I - String to print */
3743*5e7646d2SAndroid Build Coastguard Worker {
3744*5e7646d2SAndroid Build Coastguard Worker   if (element)
3745*5e7646d2SAndroid Build Coastguard Worker     cupsFilePrintf(outfile, "<%s>", element);
3746*5e7646d2SAndroid Build Coastguard Worker 
3747*5e7646d2SAndroid Build Coastguard Worker   while (*s)
3748*5e7646d2SAndroid Build Coastguard Worker   {
3749*5e7646d2SAndroid Build Coastguard Worker     if (*s == '&')
3750*5e7646d2SAndroid Build Coastguard Worker       cupsFilePuts(outfile, "&amp;");
3751*5e7646d2SAndroid Build Coastguard Worker     else if (*s == '<')
3752*5e7646d2SAndroid Build Coastguard Worker       cupsFilePuts(outfile, "&lt;");
3753*5e7646d2SAndroid Build Coastguard Worker     else if (*s == '>')
3754*5e7646d2SAndroid Build Coastguard Worker       cupsFilePuts(outfile, "&gt;");
3755*5e7646d2SAndroid Build Coastguard Worker     else if ((*s & 0xe0) == 0xc0)
3756*5e7646d2SAndroid Build Coastguard Worker     {
3757*5e7646d2SAndroid Build Coastguard Worker      /*
3758*5e7646d2SAndroid Build Coastguard Worker       * Validate UTF-8 two-byte sequence...
3759*5e7646d2SAndroid Build Coastguard Worker       */
3760*5e7646d2SAndroid Build Coastguard Worker 
3761*5e7646d2SAndroid Build Coastguard Worker       if ((s[1] & 0xc0) != 0x80)
3762*5e7646d2SAndroid Build Coastguard Worker       {
3763*5e7646d2SAndroid Build Coastguard Worker         cupsFilePutChar(outfile, '?');
3764*5e7646d2SAndroid Build Coastguard Worker         s ++;
3765*5e7646d2SAndroid Build Coastguard Worker       }
3766*5e7646d2SAndroid Build Coastguard Worker       else
3767*5e7646d2SAndroid Build Coastguard Worker       {
3768*5e7646d2SAndroid Build Coastguard Worker         cupsFilePutChar(outfile, *s++);
3769*5e7646d2SAndroid Build Coastguard Worker         cupsFilePutChar(outfile, *s);
3770*5e7646d2SAndroid Build Coastguard Worker       }
3771*5e7646d2SAndroid Build Coastguard Worker     }
3772*5e7646d2SAndroid Build Coastguard Worker     else if ((*s & 0xf0) == 0xe0)
3773*5e7646d2SAndroid Build Coastguard Worker     {
3774*5e7646d2SAndroid Build Coastguard Worker      /*
3775*5e7646d2SAndroid Build Coastguard Worker       * Validate UTF-8 three-byte sequence...
3776*5e7646d2SAndroid Build Coastguard Worker       */
3777*5e7646d2SAndroid Build Coastguard Worker 
3778*5e7646d2SAndroid Build Coastguard Worker       if ((s[1] & 0xc0) != 0x80 || (s[2] & 0xc0) != 0x80)
3779*5e7646d2SAndroid Build Coastguard Worker       {
3780*5e7646d2SAndroid Build Coastguard Worker         cupsFilePutChar(outfile, '?');
3781*5e7646d2SAndroid Build Coastguard Worker         s += 2;
3782*5e7646d2SAndroid Build Coastguard Worker       }
3783*5e7646d2SAndroid Build Coastguard Worker       else
3784*5e7646d2SAndroid Build Coastguard Worker       {
3785*5e7646d2SAndroid Build Coastguard Worker         cupsFilePutChar(outfile, *s++);
3786*5e7646d2SAndroid Build Coastguard Worker         cupsFilePutChar(outfile, *s++);
3787*5e7646d2SAndroid Build Coastguard Worker         cupsFilePutChar(outfile, *s);
3788*5e7646d2SAndroid Build Coastguard Worker       }
3789*5e7646d2SAndroid Build Coastguard Worker     }
3790*5e7646d2SAndroid Build Coastguard Worker     else if ((*s & 0xf8) == 0xf0)
3791*5e7646d2SAndroid Build Coastguard Worker     {
3792*5e7646d2SAndroid Build Coastguard Worker      /*
3793*5e7646d2SAndroid Build Coastguard Worker       * Validate UTF-8 four-byte sequence...
3794*5e7646d2SAndroid Build Coastguard Worker       */
3795*5e7646d2SAndroid Build Coastguard Worker 
3796*5e7646d2SAndroid Build Coastguard Worker       if ((s[1] & 0xc0) != 0x80 || (s[2] & 0xc0) != 0x80 ||
3797*5e7646d2SAndroid Build Coastguard Worker           (s[3] & 0xc0) != 0x80)
3798*5e7646d2SAndroid Build Coastguard Worker       {
3799*5e7646d2SAndroid Build Coastguard Worker         cupsFilePutChar(outfile, '?');
3800*5e7646d2SAndroid Build Coastguard Worker         s += 3;
3801*5e7646d2SAndroid Build Coastguard Worker       }
3802*5e7646d2SAndroid Build Coastguard Worker       else
3803*5e7646d2SAndroid Build Coastguard Worker       {
3804*5e7646d2SAndroid Build Coastguard Worker         cupsFilePutChar(outfile, *s++);
3805*5e7646d2SAndroid Build Coastguard Worker         cupsFilePutChar(outfile, *s++);
3806*5e7646d2SAndroid Build Coastguard Worker         cupsFilePutChar(outfile, *s++);
3807*5e7646d2SAndroid Build Coastguard Worker         cupsFilePutChar(outfile, *s);
3808*5e7646d2SAndroid Build Coastguard Worker       }
3809*5e7646d2SAndroid Build Coastguard Worker     }
3810*5e7646d2SAndroid Build Coastguard Worker     else if ((*s & 0x80) || (*s < ' ' && !isspace(*s & 255)))
3811*5e7646d2SAndroid Build Coastguard Worker     {
3812*5e7646d2SAndroid Build Coastguard Worker      /*
3813*5e7646d2SAndroid Build Coastguard Worker       * Invalid control character...
3814*5e7646d2SAndroid Build Coastguard Worker       */
3815*5e7646d2SAndroid Build Coastguard Worker 
3816*5e7646d2SAndroid Build Coastguard Worker       cupsFilePutChar(outfile, '?');
3817*5e7646d2SAndroid Build Coastguard Worker     }
3818*5e7646d2SAndroid Build Coastguard Worker     else
3819*5e7646d2SAndroid Build Coastguard Worker       cupsFilePutChar(outfile, *s);
3820*5e7646d2SAndroid Build Coastguard Worker 
3821*5e7646d2SAndroid Build Coastguard Worker     s ++;
3822*5e7646d2SAndroid Build Coastguard Worker   }
3823*5e7646d2SAndroid Build Coastguard Worker 
3824*5e7646d2SAndroid Build Coastguard Worker   if (element)
3825*5e7646d2SAndroid Build Coastguard Worker     cupsFilePrintf(outfile, "</%s>\n", element);
3826*5e7646d2SAndroid Build Coastguard Worker }
3827*5e7646d2SAndroid Build Coastguard Worker 
3828*5e7646d2SAndroid Build Coastguard Worker 
3829*5e7646d2SAndroid Build Coastguard Worker /*
3830*5e7646d2SAndroid Build Coastguard Worker  * 'print_xml_trailer()' - Print the XML trailer with success/fail value.
3831*5e7646d2SAndroid Build Coastguard Worker  */
3832*5e7646d2SAndroid Build Coastguard Worker 
3833*5e7646d2SAndroid Build Coastguard Worker static void
print_xml_trailer(ipptool_test_t * data,int success,const char * message)3834*5e7646d2SAndroid Build Coastguard Worker print_xml_trailer(
3835*5e7646d2SAndroid Build Coastguard Worker     ipptool_test_t *data,		/* I - Test data */
3836*5e7646d2SAndroid Build Coastguard Worker     int              success,		/* I - 1 on success, 0 on failure */
3837*5e7646d2SAndroid Build Coastguard Worker     const char       *message)		/* I - Error message or NULL */
3838*5e7646d2SAndroid Build Coastguard Worker {
3839*5e7646d2SAndroid Build Coastguard Worker   if (data->xml_header)
3840*5e7646d2SAndroid Build Coastguard Worker   {
3841*5e7646d2SAndroid Build Coastguard Worker     cupsFilePuts(data->outfile, "</array>\n");
3842*5e7646d2SAndroid Build Coastguard Worker     cupsFilePuts(data->outfile, "<key>Successful</key>\n");
3843*5e7646d2SAndroid Build Coastguard Worker     cupsFilePuts(data->outfile, success ? "<true />\n" : "<false />\n");
3844*5e7646d2SAndroid Build Coastguard Worker     if (message)
3845*5e7646d2SAndroid Build Coastguard Worker     {
3846*5e7646d2SAndroid Build Coastguard Worker       cupsFilePuts(data->outfile, "<key>ErrorMessage</key>\n");
3847*5e7646d2SAndroid Build Coastguard Worker       print_xml_string(data->outfile, "string", message);
3848*5e7646d2SAndroid Build Coastguard Worker     }
3849*5e7646d2SAndroid Build Coastguard Worker     cupsFilePuts(data->outfile, "</dict>\n");
3850*5e7646d2SAndroid Build Coastguard Worker     cupsFilePuts(data->outfile, "</plist>\n");
3851*5e7646d2SAndroid Build Coastguard Worker 
3852*5e7646d2SAndroid Build Coastguard Worker     data->xml_header = 0;
3853*5e7646d2SAndroid Build Coastguard Worker   }
3854*5e7646d2SAndroid Build Coastguard Worker }
3855*5e7646d2SAndroid Build Coastguard Worker 
3856*5e7646d2SAndroid Build Coastguard Worker 
3857*5e7646d2SAndroid Build Coastguard Worker #ifndef _WIN32
3858*5e7646d2SAndroid Build Coastguard Worker /*
3859*5e7646d2SAndroid Build Coastguard Worker  * 'sigterm_handler()' - Handle SIGINT and SIGTERM.
3860*5e7646d2SAndroid Build Coastguard Worker  */
3861*5e7646d2SAndroid Build Coastguard Worker 
3862*5e7646d2SAndroid Build Coastguard Worker static void
sigterm_handler(int sig)3863*5e7646d2SAndroid Build Coastguard Worker sigterm_handler(int sig)		/* I - Signal number (unused) */
3864*5e7646d2SAndroid Build Coastguard Worker {
3865*5e7646d2SAndroid Build Coastguard Worker   (void)sig;
3866*5e7646d2SAndroid Build Coastguard Worker 
3867*5e7646d2SAndroid Build Coastguard Worker   Cancel = 1;
3868*5e7646d2SAndroid Build Coastguard Worker 
3869*5e7646d2SAndroid Build Coastguard Worker   signal(SIGINT, SIG_DFL);
3870*5e7646d2SAndroid Build Coastguard Worker   signal(SIGTERM, SIG_DFL);
3871*5e7646d2SAndroid Build Coastguard Worker }
3872*5e7646d2SAndroid Build Coastguard Worker #endif /* !_WIN32 */
3873*5e7646d2SAndroid Build Coastguard Worker 
3874*5e7646d2SAndroid Build Coastguard Worker 
3875*5e7646d2SAndroid Build Coastguard Worker /*
3876*5e7646d2SAndroid Build Coastguard Worker  * 'timeout_cb()' - Handle HTTP timeouts.
3877*5e7646d2SAndroid Build Coastguard Worker  */
3878*5e7646d2SAndroid Build Coastguard Worker 
3879*5e7646d2SAndroid Build Coastguard Worker static int				/* O - 1 to continue, 0 to cancel */
timeout_cb(http_t * http,void * user_data)3880*5e7646d2SAndroid Build Coastguard Worker timeout_cb(http_t *http,		/* I - Connection to server */
3881*5e7646d2SAndroid Build Coastguard Worker            void   *user_data)		/* I - User data (unused) */
3882*5e7646d2SAndroid Build Coastguard Worker {
3883*5e7646d2SAndroid Build Coastguard Worker   int		buffered = 0;		/* Bytes buffered but not yet sent */
3884*5e7646d2SAndroid Build Coastguard Worker 
3885*5e7646d2SAndroid Build Coastguard Worker 
3886*5e7646d2SAndroid Build Coastguard Worker   (void)user_data;
3887*5e7646d2SAndroid Build Coastguard Worker 
3888*5e7646d2SAndroid Build Coastguard Worker  /*
3889*5e7646d2SAndroid Build Coastguard Worker   * If the socket still have data waiting to be sent to the printer (as can
3890*5e7646d2SAndroid Build Coastguard Worker   * happen if the printer runs out of paper), continue to wait until the output
3891*5e7646d2SAndroid Build Coastguard Worker   * buffer is empty...
3892*5e7646d2SAndroid Build Coastguard Worker   */
3893*5e7646d2SAndroid Build Coastguard Worker 
3894*5e7646d2SAndroid Build Coastguard Worker #ifdef SO_NWRITE			/* macOS and some versions of Linux */
3895*5e7646d2SAndroid Build Coastguard Worker   socklen_t len = sizeof(buffered);	/* Size of return value */
3896*5e7646d2SAndroid Build Coastguard Worker 
3897*5e7646d2SAndroid Build Coastguard Worker   if (getsockopt(httpGetFd(http), SOL_SOCKET, SO_NWRITE, &buffered, &len))
3898*5e7646d2SAndroid Build Coastguard Worker     buffered = 0;
3899*5e7646d2SAndroid Build Coastguard Worker 
3900*5e7646d2SAndroid Build Coastguard Worker #elif defined(SIOCOUTQ)			/* Others except Windows */
3901*5e7646d2SAndroid Build Coastguard Worker   if (ioctl(httpGetFd(http), SIOCOUTQ, &buffered))
3902*5e7646d2SAndroid Build Coastguard Worker     buffered = 0;
3903*5e7646d2SAndroid Build Coastguard Worker 
3904*5e7646d2SAndroid Build Coastguard Worker #else					/* Windows (not possible) */
3905*5e7646d2SAndroid Build Coastguard Worker   (void)http;
3906*5e7646d2SAndroid Build Coastguard Worker #endif /* SO_NWRITE */
3907*5e7646d2SAndroid Build Coastguard Worker 
3908*5e7646d2SAndroid Build Coastguard Worker   return (buffered > 0);
3909*5e7646d2SAndroid Build Coastguard Worker }
3910*5e7646d2SAndroid Build Coastguard Worker 
3911*5e7646d2SAndroid Build Coastguard Worker 
3912*5e7646d2SAndroid Build Coastguard Worker /*
3913*5e7646d2SAndroid Build Coastguard Worker  * 'token_cb()' - Parse test file-specific tokens and run tests.
3914*5e7646d2SAndroid Build Coastguard Worker  */
3915*5e7646d2SAndroid Build Coastguard Worker 
3916*5e7646d2SAndroid Build Coastguard Worker static int				/* O - 1 to continue, 0 to stop */
token_cb(_ipp_file_t * f,_ipp_vars_t * vars,ipptool_test_t * data,const char * token)3917*5e7646d2SAndroid Build Coastguard Worker token_cb(_ipp_file_t    *f,		/* I - IPP file data */
3918*5e7646d2SAndroid Build Coastguard Worker          _ipp_vars_t    *vars,		/* I - IPP variables */
3919*5e7646d2SAndroid Build Coastguard Worker          ipptool_test_t *data,		/* I - Test data */
3920*5e7646d2SAndroid Build Coastguard Worker          const char     *token)		/* I - Current token */
3921*5e7646d2SAndroid Build Coastguard Worker {
3922*5e7646d2SAndroid Build Coastguard Worker   char	name[1024],			/* Name string */
3923*5e7646d2SAndroid Build Coastguard Worker 	temp[1024],			/* Temporary string */
3924*5e7646d2SAndroid Build Coastguard Worker 	value[1024],			/* Value string */
3925*5e7646d2SAndroid Build Coastguard Worker 	*ptr;				/* Pointer into value */
3926*5e7646d2SAndroid Build Coastguard Worker 
3927*5e7646d2SAndroid Build Coastguard Worker 
3928*5e7646d2SAndroid Build Coastguard Worker   if (!token)
3929*5e7646d2SAndroid Build Coastguard Worker   {
3930*5e7646d2SAndroid Build Coastguard Worker    /*
3931*5e7646d2SAndroid Build Coastguard Worker     * Initialize state as needed (nothing for now...)
3932*5e7646d2SAndroid Build Coastguard Worker     */
3933*5e7646d2SAndroid Build Coastguard Worker 
3934*5e7646d2SAndroid Build Coastguard Worker     return (1);
3935*5e7646d2SAndroid Build Coastguard Worker   }
3936*5e7646d2SAndroid Build Coastguard Worker   else if (f->attrs)
3937*5e7646d2SAndroid Build Coastguard Worker   {
3938*5e7646d2SAndroid Build Coastguard Worker    /*
3939*5e7646d2SAndroid Build Coastguard Worker     * Parse until we see a close brace...
3940*5e7646d2SAndroid Build Coastguard Worker     */
3941*5e7646d2SAndroid Build Coastguard Worker 
3942*5e7646d2SAndroid Build Coastguard Worker     if (_cups_strcasecmp(token, "COUNT") &&
3943*5e7646d2SAndroid Build Coastguard Worker 	_cups_strcasecmp(token, "DEFINE-MATCH") &&
3944*5e7646d2SAndroid Build Coastguard Worker 	_cups_strcasecmp(token, "DEFINE-NO-MATCH") &&
3945*5e7646d2SAndroid Build Coastguard Worker 	_cups_strcasecmp(token, "DEFINE-VALUE") &&
3946*5e7646d2SAndroid Build Coastguard Worker 	_cups_strcasecmp(token, "DISPLAY-MATCH") &&
3947*5e7646d2SAndroid Build Coastguard Worker 	_cups_strcasecmp(token, "IF-DEFINED") &&
3948*5e7646d2SAndroid Build Coastguard Worker 	_cups_strcasecmp(token, "IF-NOT-DEFINED") &&
3949*5e7646d2SAndroid Build Coastguard Worker 	_cups_strcasecmp(token, "IN-GROUP") &&
3950*5e7646d2SAndroid Build Coastguard Worker 	_cups_strcasecmp(token, "OF-TYPE") &&
3951*5e7646d2SAndroid Build Coastguard Worker 	_cups_strcasecmp(token, "REPEAT-LIMIT") &&
3952*5e7646d2SAndroid Build Coastguard Worker 	_cups_strcasecmp(token, "REPEAT-MATCH") &&
3953*5e7646d2SAndroid Build Coastguard Worker 	_cups_strcasecmp(token, "REPEAT-NO-MATCH") &&
3954*5e7646d2SAndroid Build Coastguard Worker 	_cups_strcasecmp(token, "SAME-COUNT-AS") &&
3955*5e7646d2SAndroid Build Coastguard Worker 	_cups_strcasecmp(token, "WITH-ALL-VALUES") &&
3956*5e7646d2SAndroid Build Coastguard Worker 	_cups_strcasecmp(token, "WITH-ALL-HOSTNAMES") &&
3957*5e7646d2SAndroid Build Coastguard Worker 	_cups_strcasecmp(token, "WITH-ALL-RESOURCES") &&
3958*5e7646d2SAndroid Build Coastguard Worker 	_cups_strcasecmp(token, "WITH-ALL-SCHEMES") &&
3959*5e7646d2SAndroid Build Coastguard Worker 	_cups_strcasecmp(token, "WITH-DISTINCT-VALUES") &&
3960*5e7646d2SAndroid Build Coastguard Worker 	_cups_strcasecmp(token, "WITH-HOSTNAME") &&
3961*5e7646d2SAndroid Build Coastguard Worker 	_cups_strcasecmp(token, "WITH-RESOURCE") &&
3962*5e7646d2SAndroid Build Coastguard Worker 	_cups_strcasecmp(token, "WITH-SCHEME") &&
3963*5e7646d2SAndroid Build Coastguard Worker 	_cups_strcasecmp(token, "WITH-VALUE") &&
3964*5e7646d2SAndroid Build Coastguard Worker 	_cups_strcasecmp(token, "WITH-VALUE-FROM"))
3965*5e7646d2SAndroid Build Coastguard Worker       data->last_expect = NULL;
3966*5e7646d2SAndroid Build Coastguard Worker 
3967*5e7646d2SAndroid Build Coastguard Worker     if (_cups_strcasecmp(token, "DEFINE-MATCH") &&
3968*5e7646d2SAndroid Build Coastguard Worker 	_cups_strcasecmp(token, "DEFINE-NO-MATCH") &&
3969*5e7646d2SAndroid Build Coastguard Worker 	_cups_strcasecmp(token, "IF-DEFINED") &&
3970*5e7646d2SAndroid Build Coastguard Worker 	_cups_strcasecmp(token, "IF-NOT-DEFINED") &&
3971*5e7646d2SAndroid Build Coastguard Worker 	_cups_strcasecmp(token, "REPEAT-LIMIT") &&
3972*5e7646d2SAndroid Build Coastguard Worker 	_cups_strcasecmp(token, "REPEAT-MATCH") &&
3973*5e7646d2SAndroid Build Coastguard Worker 	_cups_strcasecmp(token, "REPEAT-NO-MATCH"))
3974*5e7646d2SAndroid Build Coastguard Worker       data->last_status = NULL;
3975*5e7646d2SAndroid Build Coastguard Worker 
3976*5e7646d2SAndroid Build Coastguard Worker     if (!strcmp(token, "}"))
3977*5e7646d2SAndroid Build Coastguard Worker     {
3978*5e7646d2SAndroid Build Coastguard Worker       return (do_test(f, data));
3979*5e7646d2SAndroid Build Coastguard Worker     }
3980*5e7646d2SAndroid Build Coastguard Worker     else if (!strcmp(token, "MONITOR-PRINTER-STATE"))
3981*5e7646d2SAndroid Build Coastguard Worker     {
3982*5e7646d2SAndroid Build Coastguard Worker       if (data->monitor_uri)
3983*5e7646d2SAndroid Build Coastguard Worker       {
3984*5e7646d2SAndroid Build Coastguard Worker 	print_fatal_error(data, "Extra MONITOR-PRINTER-STATE seen on line %d of \"%s\".", f->linenum, f->filename);
3985*5e7646d2SAndroid Build Coastguard Worker 	return (0);
3986*5e7646d2SAndroid Build Coastguard Worker       }
3987*5e7646d2SAndroid Build Coastguard Worker 
3988*5e7646d2SAndroid Build Coastguard Worker       return (parse_monitor_printer_state(f, data));
3989*5e7646d2SAndroid Build Coastguard Worker     }
3990*5e7646d2SAndroid Build Coastguard Worker     else if (!strcmp(token, "COMPRESSION"))
3991*5e7646d2SAndroid Build Coastguard Worker     {
3992*5e7646d2SAndroid Build Coastguard Worker      /*
3993*5e7646d2SAndroid Build Coastguard Worker       * COMPRESSION none
3994*5e7646d2SAndroid Build Coastguard Worker       * COMPRESSION deflate
3995*5e7646d2SAndroid Build Coastguard Worker       * COMPRESSION gzip
3996*5e7646d2SAndroid Build Coastguard Worker       */
3997*5e7646d2SAndroid Build Coastguard Worker 
3998*5e7646d2SAndroid Build Coastguard Worker       if (_ippFileReadToken(f, temp, sizeof(temp)))
3999*5e7646d2SAndroid Build Coastguard Worker       {
4000*5e7646d2SAndroid Build Coastguard Worker 	_ippVarsExpand(vars, data->compression, temp, sizeof(data->compression));
4001*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_LIBZ
4002*5e7646d2SAndroid Build Coastguard Worker 	if (strcmp(data->compression, "none") && strcmp(data->compression, "deflate") &&
4003*5e7646d2SAndroid Build Coastguard Worker 	    strcmp(data->compression, "gzip"))
4004*5e7646d2SAndroid Build Coastguard Worker #else
4005*5e7646d2SAndroid Build Coastguard Worker 	if (strcmp(data->compression, "none"))
4006*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_LIBZ */
4007*5e7646d2SAndroid Build Coastguard Worker 	{
4008*5e7646d2SAndroid Build Coastguard Worker 	  print_fatal_error(data, "Unsupported COMPRESSION value \"%s\" on line %d of \"%s\".", data->compression, f->linenum, f->filename);
4009*5e7646d2SAndroid Build Coastguard Worker 	  return (0);
4010*5e7646d2SAndroid Build Coastguard Worker 	}
4011*5e7646d2SAndroid Build Coastguard Worker 
4012*5e7646d2SAndroid Build Coastguard Worker 	if (!strcmp(data->compression, "none"))
4013*5e7646d2SAndroid Build Coastguard Worker 	  data->compression[0] = '\0';
4014*5e7646d2SAndroid Build Coastguard Worker       }
4015*5e7646d2SAndroid Build Coastguard Worker       else
4016*5e7646d2SAndroid Build Coastguard Worker       {
4017*5e7646d2SAndroid Build Coastguard Worker 	print_fatal_error(data, "Missing COMPRESSION value on line %d of \"%s\".", f->linenum, f->filename);
4018*5e7646d2SAndroid Build Coastguard Worker 	return (0);
4019*5e7646d2SAndroid Build Coastguard Worker       }
4020*5e7646d2SAndroid Build Coastguard Worker     }
4021*5e7646d2SAndroid Build Coastguard Worker     else if (!strcmp(token, "DEFINE"))
4022*5e7646d2SAndroid Build Coastguard Worker     {
4023*5e7646d2SAndroid Build Coastguard Worker      /*
4024*5e7646d2SAndroid Build Coastguard Worker       * DEFINE name value
4025*5e7646d2SAndroid Build Coastguard Worker       */
4026*5e7646d2SAndroid Build Coastguard Worker 
4027*5e7646d2SAndroid Build Coastguard Worker       if (_ippFileReadToken(f, name, sizeof(name)) && _ippFileReadToken(f, temp, sizeof(temp)))
4028*5e7646d2SAndroid Build Coastguard Worker       {
4029*5e7646d2SAndroid Build Coastguard Worker 	_ippVarsExpand(vars, value, temp, sizeof(value));
4030*5e7646d2SAndroid Build Coastguard Worker 	_ippVarsSet(vars, name, value);
4031*5e7646d2SAndroid Build Coastguard Worker       }
4032*5e7646d2SAndroid Build Coastguard Worker       else
4033*5e7646d2SAndroid Build Coastguard Worker       {
4034*5e7646d2SAndroid Build Coastguard Worker 	print_fatal_error(data, "Missing DEFINE name and/or value on line %d of \"%s\".", f->linenum, f->filename);
4035*5e7646d2SAndroid Build Coastguard Worker 	return (0);
4036*5e7646d2SAndroid Build Coastguard Worker       }
4037*5e7646d2SAndroid Build Coastguard Worker     }
4038*5e7646d2SAndroid Build Coastguard Worker     else if (!strcmp(token, "IGNORE-ERRORS"))
4039*5e7646d2SAndroid Build Coastguard Worker     {
4040*5e7646d2SAndroid Build Coastguard Worker      /*
4041*5e7646d2SAndroid Build Coastguard Worker       * IGNORE-ERRORS yes
4042*5e7646d2SAndroid Build Coastguard Worker       * IGNORE-ERRORS no
4043*5e7646d2SAndroid Build Coastguard Worker       */
4044*5e7646d2SAndroid Build Coastguard Worker 
4045*5e7646d2SAndroid Build Coastguard Worker       if (_ippFileReadToken(f, temp, sizeof(temp)) && (!_cups_strcasecmp(temp, "yes") || !_cups_strcasecmp(temp, "no")))
4046*5e7646d2SAndroid Build Coastguard Worker       {
4047*5e7646d2SAndroid Build Coastguard Worker 	data->ignore_errors = !_cups_strcasecmp(temp, "yes");
4048*5e7646d2SAndroid Build Coastguard Worker       }
4049*5e7646d2SAndroid Build Coastguard Worker       else
4050*5e7646d2SAndroid Build Coastguard Worker       {
4051*5e7646d2SAndroid Build Coastguard Worker 	print_fatal_error(data, "Missing IGNORE-ERRORS value on line %d of \"%s\".", f->linenum, f->filename);
4052*5e7646d2SAndroid Build Coastguard Worker 	return (0);
4053*5e7646d2SAndroid Build Coastguard Worker       }
4054*5e7646d2SAndroid Build Coastguard Worker     }
4055*5e7646d2SAndroid Build Coastguard Worker     else if (!_cups_strcasecmp(token, "NAME"))
4056*5e7646d2SAndroid Build Coastguard Worker     {
4057*5e7646d2SAndroid Build Coastguard Worker      /*
4058*5e7646d2SAndroid Build Coastguard Worker       * Name of test...
4059*5e7646d2SAndroid Build Coastguard Worker       */
4060*5e7646d2SAndroid Build Coastguard Worker 
4061*5e7646d2SAndroid Build Coastguard Worker       _ippFileReadToken(f, temp, sizeof(temp));
4062*5e7646d2SAndroid Build Coastguard Worker       _ippVarsExpand(vars, data->name, temp, sizeof(data->name));
4063*5e7646d2SAndroid Build Coastguard Worker     }
4064*5e7646d2SAndroid Build Coastguard Worker     else if (!_cups_strcasecmp(token, "PAUSE"))
4065*5e7646d2SAndroid Build Coastguard Worker     {
4066*5e7646d2SAndroid Build Coastguard Worker      /*
4067*5e7646d2SAndroid Build Coastguard Worker       * Pause with a message...
4068*5e7646d2SAndroid Build Coastguard Worker       */
4069*5e7646d2SAndroid Build Coastguard Worker 
4070*5e7646d2SAndroid Build Coastguard Worker       if (_ippFileReadToken(f, temp, sizeof(temp)))
4071*5e7646d2SAndroid Build Coastguard Worker       {
4072*5e7646d2SAndroid Build Coastguard Worker         strlcpy(data->pause, temp, sizeof(data->pause));
4073*5e7646d2SAndroid Build Coastguard Worker       }
4074*5e7646d2SAndroid Build Coastguard Worker       else
4075*5e7646d2SAndroid Build Coastguard Worker       {
4076*5e7646d2SAndroid Build Coastguard Worker 	print_fatal_error(data, "Missing PAUSE message on line %d of \"%s\".", f->linenum, f->filename);
4077*5e7646d2SAndroid Build Coastguard Worker 	return (0);
4078*5e7646d2SAndroid Build Coastguard Worker       }
4079*5e7646d2SAndroid Build Coastguard Worker     }
4080*5e7646d2SAndroid Build Coastguard Worker     else if (!strcmp(token, "REQUEST-ID"))
4081*5e7646d2SAndroid Build Coastguard Worker     {
4082*5e7646d2SAndroid Build Coastguard Worker      /*
4083*5e7646d2SAndroid Build Coastguard Worker       * REQUEST-ID #
4084*5e7646d2SAndroid Build Coastguard Worker       * REQUEST-ID random
4085*5e7646d2SAndroid Build Coastguard Worker       */
4086*5e7646d2SAndroid Build Coastguard Worker 
4087*5e7646d2SAndroid Build Coastguard Worker       if (_ippFileReadToken(f, temp, sizeof(temp)))
4088*5e7646d2SAndroid Build Coastguard Worker       {
4089*5e7646d2SAndroid Build Coastguard Worker 	if (isdigit(temp[0] & 255))
4090*5e7646d2SAndroid Build Coastguard Worker 	{
4091*5e7646d2SAndroid Build Coastguard Worker 	  data->request_id = atoi(temp) - 1;
4092*5e7646d2SAndroid Build Coastguard Worker 	}
4093*5e7646d2SAndroid Build Coastguard Worker 	else if (!_cups_strcasecmp(temp, "random"))
4094*5e7646d2SAndroid Build Coastguard Worker 	{
4095*5e7646d2SAndroid Build Coastguard Worker 	  data->request_id = (CUPS_RAND() % 1000) * 137;
4096*5e7646d2SAndroid Build Coastguard Worker 	}
4097*5e7646d2SAndroid Build Coastguard Worker 	else
4098*5e7646d2SAndroid Build Coastguard Worker 	{
4099*5e7646d2SAndroid Build Coastguard Worker 	  print_fatal_error(data, "Bad REQUEST-ID value \"%s\" on line %d of \"%s\".", temp, f->linenum, f->filename);
4100*5e7646d2SAndroid Build Coastguard Worker 	  return (0);
4101*5e7646d2SAndroid Build Coastguard Worker 	}
4102*5e7646d2SAndroid Build Coastguard Worker       }
4103*5e7646d2SAndroid Build Coastguard Worker       else
4104*5e7646d2SAndroid Build Coastguard Worker       {
4105*5e7646d2SAndroid Build Coastguard Worker 	print_fatal_error(data, "Missing REQUEST-ID value on line %d of \"%s\".", f->linenum, f->filename);
4106*5e7646d2SAndroid Build Coastguard Worker 	return (0);
4107*5e7646d2SAndroid Build Coastguard Worker       }
4108*5e7646d2SAndroid Build Coastguard Worker     }
4109*5e7646d2SAndroid Build Coastguard Worker     else if (!strcmp(token, "PASS-IF-DEFINED"))
4110*5e7646d2SAndroid Build Coastguard Worker     {
4111*5e7646d2SAndroid Build Coastguard Worker      /*
4112*5e7646d2SAndroid Build Coastguard Worker       * PASS-IF-DEFINED variable
4113*5e7646d2SAndroid Build Coastguard Worker       */
4114*5e7646d2SAndroid Build Coastguard Worker 
4115*5e7646d2SAndroid Build Coastguard Worker       if (_ippFileReadToken(f, name, sizeof(name)))
4116*5e7646d2SAndroid Build Coastguard Worker       {
4117*5e7646d2SAndroid Build Coastguard Worker 	if (_ippVarsGet(vars, name))
4118*5e7646d2SAndroid Build Coastguard Worker 	  data->pass_test = 1;
4119*5e7646d2SAndroid Build Coastguard Worker       }
4120*5e7646d2SAndroid Build Coastguard Worker       else
4121*5e7646d2SAndroid Build Coastguard Worker       {
4122*5e7646d2SAndroid Build Coastguard Worker 	print_fatal_error(data, "Missing PASS-IF-DEFINED value on line %d of \"%s\".", f->linenum, f->filename);
4123*5e7646d2SAndroid Build Coastguard Worker 	return (0);
4124*5e7646d2SAndroid Build Coastguard Worker       }
4125*5e7646d2SAndroid Build Coastguard Worker     }
4126*5e7646d2SAndroid Build Coastguard Worker     else if (!strcmp(token, "PASS-IF-NOT-DEFINED"))
4127*5e7646d2SAndroid Build Coastguard Worker     {
4128*5e7646d2SAndroid Build Coastguard Worker      /*
4129*5e7646d2SAndroid Build Coastguard Worker       * PASS-IF-NOT-DEFINED variable
4130*5e7646d2SAndroid Build Coastguard Worker       */
4131*5e7646d2SAndroid Build Coastguard Worker 
4132*5e7646d2SAndroid Build Coastguard Worker       if (_ippFileReadToken(f, name, sizeof(name)))
4133*5e7646d2SAndroid Build Coastguard Worker       {
4134*5e7646d2SAndroid Build Coastguard Worker 	if (!_ippVarsGet(vars, name))
4135*5e7646d2SAndroid Build Coastguard Worker 	  data->pass_test = 1;
4136*5e7646d2SAndroid Build Coastguard Worker       }
4137*5e7646d2SAndroid Build Coastguard Worker       else
4138*5e7646d2SAndroid Build Coastguard Worker       {
4139*5e7646d2SAndroid Build Coastguard Worker 	print_fatal_error(data, "Missing PASS-IF-NOT-DEFINED value on line %d of \"%s\".", f->linenum, f->filename);
4140*5e7646d2SAndroid Build Coastguard Worker 	return (0);
4141*5e7646d2SAndroid Build Coastguard Worker       }
4142*5e7646d2SAndroid Build Coastguard Worker     }
4143*5e7646d2SAndroid Build Coastguard Worker     else if (!strcmp(token, "SKIP-IF-DEFINED"))
4144*5e7646d2SAndroid Build Coastguard Worker     {
4145*5e7646d2SAndroid Build Coastguard Worker      /*
4146*5e7646d2SAndroid Build Coastguard Worker       * SKIP-IF-DEFINED variable
4147*5e7646d2SAndroid Build Coastguard Worker       */
4148*5e7646d2SAndroid Build Coastguard Worker 
4149*5e7646d2SAndroid Build Coastguard Worker       if (_ippFileReadToken(f, name, sizeof(name)))
4150*5e7646d2SAndroid Build Coastguard Worker       {
4151*5e7646d2SAndroid Build Coastguard Worker 	if (_ippVarsGet(vars, name))
4152*5e7646d2SAndroid Build Coastguard Worker 	  data->skip_test = 1;
4153*5e7646d2SAndroid Build Coastguard Worker       }
4154*5e7646d2SAndroid Build Coastguard Worker       else
4155*5e7646d2SAndroid Build Coastguard Worker       {
4156*5e7646d2SAndroid Build Coastguard Worker 	print_fatal_error(data, "Missing SKIP-IF-DEFINED value on line %d of \"%s\".", f->linenum, f->filename);
4157*5e7646d2SAndroid Build Coastguard Worker 	return (0);
4158*5e7646d2SAndroid Build Coastguard Worker       }
4159*5e7646d2SAndroid Build Coastguard Worker     }
4160*5e7646d2SAndroid Build Coastguard Worker     else if (!strcmp(token, "SKIP-IF-MISSING"))
4161*5e7646d2SAndroid Build Coastguard Worker     {
4162*5e7646d2SAndroid Build Coastguard Worker      /*
4163*5e7646d2SAndroid Build Coastguard Worker       * SKIP-IF-MISSING filename
4164*5e7646d2SAndroid Build Coastguard Worker       */
4165*5e7646d2SAndroid Build Coastguard Worker 
4166*5e7646d2SAndroid Build Coastguard Worker       if (_ippFileReadToken(f, temp, sizeof(temp)))
4167*5e7646d2SAndroid Build Coastguard Worker       {
4168*5e7646d2SAndroid Build Coastguard Worker         char filename[1024];		/* Filename */
4169*5e7646d2SAndroid Build Coastguard Worker 
4170*5e7646d2SAndroid Build Coastguard Worker 	_ippVarsExpand(vars, value, temp, sizeof(value));
4171*5e7646d2SAndroid Build Coastguard Worker 	get_filename(f->filename, filename, temp, sizeof(filename));
4172*5e7646d2SAndroid Build Coastguard Worker 
4173*5e7646d2SAndroid Build Coastguard Worker 	if (access(filename, R_OK))
4174*5e7646d2SAndroid Build Coastguard Worker 	  data->skip_test = 1;
4175*5e7646d2SAndroid Build Coastguard Worker       }
4176*5e7646d2SAndroid Build Coastguard Worker       else
4177*5e7646d2SAndroid Build Coastguard Worker       {
4178*5e7646d2SAndroid Build Coastguard Worker 	print_fatal_error(data, "Missing SKIP-IF-MISSING filename on line %d of \"%s\".", f->linenum, f->filename);
4179*5e7646d2SAndroid Build Coastguard Worker 	return (0);
4180*5e7646d2SAndroid Build Coastguard Worker       }
4181*5e7646d2SAndroid Build Coastguard Worker     }
4182*5e7646d2SAndroid Build Coastguard Worker     else if (!strcmp(token, "SKIP-IF-NOT-DEFINED"))
4183*5e7646d2SAndroid Build Coastguard Worker     {
4184*5e7646d2SAndroid Build Coastguard Worker      /*
4185*5e7646d2SAndroid Build Coastguard Worker       * SKIP-IF-NOT-DEFINED variable
4186*5e7646d2SAndroid Build Coastguard Worker       */
4187*5e7646d2SAndroid Build Coastguard Worker 
4188*5e7646d2SAndroid Build Coastguard Worker       if (_ippFileReadToken(f, name, sizeof(name)))
4189*5e7646d2SAndroid Build Coastguard Worker       {
4190*5e7646d2SAndroid Build Coastguard Worker 	if (!_ippVarsGet(vars, name))
4191*5e7646d2SAndroid Build Coastguard Worker 	  data->skip_test = 1;
4192*5e7646d2SAndroid Build Coastguard Worker       }
4193*5e7646d2SAndroid Build Coastguard Worker       else
4194*5e7646d2SAndroid Build Coastguard Worker       {
4195*5e7646d2SAndroid Build Coastguard Worker 	print_fatal_error(data, "Missing SKIP-IF-NOT-DEFINED value on line %d of \"%s\".", f->linenum, f->filename);
4196*5e7646d2SAndroid Build Coastguard Worker 	return (0);
4197*5e7646d2SAndroid Build Coastguard Worker       }
4198*5e7646d2SAndroid Build Coastguard Worker     }
4199*5e7646d2SAndroid Build Coastguard Worker     else if (!strcmp(token, "SKIP-PREVIOUS-ERROR"))
4200*5e7646d2SAndroid Build Coastguard Worker     {
4201*5e7646d2SAndroid Build Coastguard Worker      /*
4202*5e7646d2SAndroid Build Coastguard Worker       * SKIP-PREVIOUS-ERROR yes
4203*5e7646d2SAndroid Build Coastguard Worker       * SKIP-PREVIOUS-ERROR no
4204*5e7646d2SAndroid Build Coastguard Worker       */
4205*5e7646d2SAndroid Build Coastguard Worker 
4206*5e7646d2SAndroid Build Coastguard Worker       if (_ippFileReadToken(f, temp, sizeof(temp)) && (!_cups_strcasecmp(temp, "yes") || !_cups_strcasecmp(temp, "no")))
4207*5e7646d2SAndroid Build Coastguard Worker       {
4208*5e7646d2SAndroid Build Coastguard Worker 	data->skip_previous = !_cups_strcasecmp(temp, "yes");
4209*5e7646d2SAndroid Build Coastguard Worker       }
4210*5e7646d2SAndroid Build Coastguard Worker       else
4211*5e7646d2SAndroid Build Coastguard Worker       {
4212*5e7646d2SAndroid Build Coastguard Worker 	print_fatal_error(data, "Missing SKIP-PREVIOUS-ERROR value on line %d of \"%s\".", f->linenum, f->filename);
4213*5e7646d2SAndroid Build Coastguard Worker 	return (0);
4214*5e7646d2SAndroid Build Coastguard Worker       }
4215*5e7646d2SAndroid Build Coastguard Worker     }
4216*5e7646d2SAndroid Build Coastguard Worker     else if (!strcmp(token, "TEST-ID"))
4217*5e7646d2SAndroid Build Coastguard Worker     {
4218*5e7646d2SAndroid Build Coastguard Worker      /*
4219*5e7646d2SAndroid Build Coastguard Worker       * TEST-ID "string"
4220*5e7646d2SAndroid Build Coastguard Worker       */
4221*5e7646d2SAndroid Build Coastguard Worker 
4222*5e7646d2SAndroid Build Coastguard Worker       if (_ippFileReadToken(f, temp, sizeof(temp)))
4223*5e7646d2SAndroid Build Coastguard Worker       {
4224*5e7646d2SAndroid Build Coastguard Worker 	_ippVarsExpand(vars, data->test_id, temp, sizeof(data->test_id));
4225*5e7646d2SAndroid Build Coastguard Worker       }
4226*5e7646d2SAndroid Build Coastguard Worker       else
4227*5e7646d2SAndroid Build Coastguard Worker       {
4228*5e7646d2SAndroid Build Coastguard Worker 	print_fatal_error(data, "Missing TEST-ID value on line %d of \"%s\".", f->linenum, f->filename);
4229*5e7646d2SAndroid Build Coastguard Worker 	return (0);
4230*5e7646d2SAndroid Build Coastguard Worker       }
4231*5e7646d2SAndroid Build Coastguard Worker     }
4232*5e7646d2SAndroid Build Coastguard Worker     else if (!strcmp(token, "TRANSFER"))
4233*5e7646d2SAndroid Build Coastguard Worker     {
4234*5e7646d2SAndroid Build Coastguard Worker      /*
4235*5e7646d2SAndroid Build Coastguard Worker       * TRANSFER auto
4236*5e7646d2SAndroid Build Coastguard Worker       * TRANSFER chunked
4237*5e7646d2SAndroid Build Coastguard Worker       * TRANSFER length
4238*5e7646d2SAndroid Build Coastguard Worker       */
4239*5e7646d2SAndroid Build Coastguard Worker 
4240*5e7646d2SAndroid Build Coastguard Worker       if (_ippFileReadToken(f, temp, sizeof(temp)))
4241*5e7646d2SAndroid Build Coastguard Worker       {
4242*5e7646d2SAndroid Build Coastguard Worker 	if (!strcmp(temp, "auto"))
4243*5e7646d2SAndroid Build Coastguard Worker 	{
4244*5e7646d2SAndroid Build Coastguard Worker 	  data->transfer = IPPTOOL_TRANSFER_AUTO;
4245*5e7646d2SAndroid Build Coastguard Worker 	}
4246*5e7646d2SAndroid Build Coastguard Worker 	else if (!strcmp(temp, "chunked"))
4247*5e7646d2SAndroid Build Coastguard Worker 	{
4248*5e7646d2SAndroid Build Coastguard Worker 	  data->transfer = IPPTOOL_TRANSFER_CHUNKED;
4249*5e7646d2SAndroid Build Coastguard Worker 	}
4250*5e7646d2SAndroid Build Coastguard Worker 	else if (!strcmp(temp, "length"))
4251*5e7646d2SAndroid Build Coastguard Worker 	{
4252*5e7646d2SAndroid Build Coastguard Worker 	  data->transfer = IPPTOOL_TRANSFER_LENGTH;
4253*5e7646d2SAndroid Build Coastguard Worker 	}
4254*5e7646d2SAndroid Build Coastguard Worker 	else
4255*5e7646d2SAndroid Build Coastguard Worker 	{
4256*5e7646d2SAndroid Build Coastguard Worker 	  print_fatal_error(data, "Bad TRANSFER value \"%s\" on line %d of \"%s\".", temp, f->linenum, f->filename);
4257*5e7646d2SAndroid Build Coastguard Worker 	  return (0);
4258*5e7646d2SAndroid Build Coastguard Worker 	}
4259*5e7646d2SAndroid Build Coastguard Worker       }
4260*5e7646d2SAndroid Build Coastguard Worker       else
4261*5e7646d2SAndroid Build Coastguard Worker       {
4262*5e7646d2SAndroid Build Coastguard Worker 	print_fatal_error(data, "Missing TRANSFER value on line %d of \"%s\".", f->linenum, f->filename);
4263*5e7646d2SAndroid Build Coastguard Worker 	return (0);
4264*5e7646d2SAndroid Build Coastguard Worker       }
4265*5e7646d2SAndroid Build Coastguard Worker     }
4266*5e7646d2SAndroid Build Coastguard Worker     else if (!_cups_strcasecmp(token, "VERSION"))
4267*5e7646d2SAndroid Build Coastguard Worker     {
4268*5e7646d2SAndroid Build Coastguard Worker       if (_ippFileReadToken(f, temp, sizeof(temp)))
4269*5e7646d2SAndroid Build Coastguard Worker       {
4270*5e7646d2SAndroid Build Coastguard Worker 	if (!strcmp(temp, "0.0"))
4271*5e7646d2SAndroid Build Coastguard Worker 	{
4272*5e7646d2SAndroid Build Coastguard Worker 	  data->version = 0;
4273*5e7646d2SAndroid Build Coastguard Worker 	}
4274*5e7646d2SAndroid Build Coastguard Worker 	else if (!strcmp(temp, "1.0"))
4275*5e7646d2SAndroid Build Coastguard Worker 	{
4276*5e7646d2SAndroid Build Coastguard Worker 	  data->version = 10;
4277*5e7646d2SAndroid Build Coastguard Worker 	}
4278*5e7646d2SAndroid Build Coastguard Worker 	else if (!strcmp(temp, "1.1"))
4279*5e7646d2SAndroid Build Coastguard Worker 	{
4280*5e7646d2SAndroid Build Coastguard Worker 	  data->version = 11;
4281*5e7646d2SAndroid Build Coastguard Worker 	}
4282*5e7646d2SAndroid Build Coastguard Worker 	else if (!strcmp(temp, "2.0"))
4283*5e7646d2SAndroid Build Coastguard Worker 	{
4284*5e7646d2SAndroid Build Coastguard Worker 	  data->version = 20;
4285*5e7646d2SAndroid Build Coastguard Worker 	}
4286*5e7646d2SAndroid Build Coastguard Worker 	else if (!strcmp(temp, "2.1"))
4287*5e7646d2SAndroid Build Coastguard Worker 	{
4288*5e7646d2SAndroid Build Coastguard Worker 	  data->version = 21;
4289*5e7646d2SAndroid Build Coastguard Worker 	}
4290*5e7646d2SAndroid Build Coastguard Worker 	else if (!strcmp(temp, "2.2"))
4291*5e7646d2SAndroid Build Coastguard Worker 	{
4292*5e7646d2SAndroid Build Coastguard Worker 	  data->version = 22;
4293*5e7646d2SAndroid Build Coastguard Worker 	}
4294*5e7646d2SAndroid Build Coastguard Worker 	else
4295*5e7646d2SAndroid Build Coastguard Worker 	{
4296*5e7646d2SAndroid Build Coastguard Worker 	  print_fatal_error(data, "Bad VERSION \"%s\" on line %d of \"%s\".", temp, f->linenum, f->filename);
4297*5e7646d2SAndroid Build Coastguard Worker 	  return (0);
4298*5e7646d2SAndroid Build Coastguard Worker 	}
4299*5e7646d2SAndroid Build Coastguard Worker       }
4300*5e7646d2SAndroid Build Coastguard Worker       else
4301*5e7646d2SAndroid Build Coastguard Worker       {
4302*5e7646d2SAndroid Build Coastguard Worker 	print_fatal_error(data, "Missing VERSION number on line %d of \"%s\".", f->linenum, f->filename);
4303*5e7646d2SAndroid Build Coastguard Worker 	return (0);
4304*5e7646d2SAndroid Build Coastguard Worker       }
4305*5e7646d2SAndroid Build Coastguard Worker     }
4306*5e7646d2SAndroid Build Coastguard Worker     else if (!_cups_strcasecmp(token, "RESOURCE"))
4307*5e7646d2SAndroid Build Coastguard Worker     {
4308*5e7646d2SAndroid Build Coastguard Worker      /*
4309*5e7646d2SAndroid Build Coastguard Worker       * Resource name...
4310*5e7646d2SAndroid Build Coastguard Worker       */
4311*5e7646d2SAndroid Build Coastguard Worker 
4312*5e7646d2SAndroid Build Coastguard Worker       if (!_ippFileReadToken(f, data->resource, sizeof(data->resource)))
4313*5e7646d2SAndroid Build Coastguard Worker       {
4314*5e7646d2SAndroid Build Coastguard Worker 	print_fatal_error(data, "Missing RESOURCE path on line %d of \"%s\".", f->linenum, f->filename);
4315*5e7646d2SAndroid Build Coastguard Worker 	return (0);
4316*5e7646d2SAndroid Build Coastguard Worker       }
4317*5e7646d2SAndroid Build Coastguard Worker     }
4318*5e7646d2SAndroid Build Coastguard Worker     else if (!_cups_strcasecmp(token, "OPERATION"))
4319*5e7646d2SAndroid Build Coastguard Worker     {
4320*5e7646d2SAndroid Build Coastguard Worker      /*
4321*5e7646d2SAndroid Build Coastguard Worker       * Operation...
4322*5e7646d2SAndroid Build Coastguard Worker       */
4323*5e7646d2SAndroid Build Coastguard Worker 
4324*5e7646d2SAndroid Build Coastguard Worker       ipp_op_t	op;			/* Operation code */
4325*5e7646d2SAndroid Build Coastguard Worker 
4326*5e7646d2SAndroid Build Coastguard Worker       if (!_ippFileReadToken(f, temp, sizeof(temp)))
4327*5e7646d2SAndroid Build Coastguard Worker       {
4328*5e7646d2SAndroid Build Coastguard Worker 	print_fatal_error(data, "Missing OPERATION code on line %d of \"%s\".", f->linenum, f->filename);
4329*5e7646d2SAndroid Build Coastguard Worker 	return (0);
4330*5e7646d2SAndroid Build Coastguard Worker       }
4331*5e7646d2SAndroid Build Coastguard Worker 
4332*5e7646d2SAndroid Build Coastguard Worker       _ippVarsExpand(vars, value, temp, sizeof(value));
4333*5e7646d2SAndroid Build Coastguard Worker 
4334*5e7646d2SAndroid Build Coastguard Worker       if ((op = ippOpValue(value)) == (ipp_op_t)-1 && (op = (ipp_op_t)strtol(value, NULL, 0)) == 0)
4335*5e7646d2SAndroid Build Coastguard Worker       {
4336*5e7646d2SAndroid Build Coastguard Worker 	print_fatal_error(data, "Bad OPERATION code \"%s\" on line %d of \"%s\".", temp, f->linenum, f->filename);
4337*5e7646d2SAndroid Build Coastguard Worker 	return (0);
4338*5e7646d2SAndroid Build Coastguard Worker       }
4339*5e7646d2SAndroid Build Coastguard Worker 
4340*5e7646d2SAndroid Build Coastguard Worker       ippSetOperation(f->attrs, op);
4341*5e7646d2SAndroid Build Coastguard Worker     }
4342*5e7646d2SAndroid Build Coastguard Worker     else if (!_cups_strcasecmp(token, "GROUP"))
4343*5e7646d2SAndroid Build Coastguard Worker     {
4344*5e7646d2SAndroid Build Coastguard Worker      /*
4345*5e7646d2SAndroid Build Coastguard Worker       * Attribute group...
4346*5e7646d2SAndroid Build Coastguard Worker       */
4347*5e7646d2SAndroid Build Coastguard Worker 
4348*5e7646d2SAndroid Build Coastguard Worker       ipp_tag_t	group_tag;		/* Group tag */
4349*5e7646d2SAndroid Build Coastguard Worker 
4350*5e7646d2SAndroid Build Coastguard Worker       if (!_ippFileReadToken(f, temp, sizeof(temp)))
4351*5e7646d2SAndroid Build Coastguard Worker       {
4352*5e7646d2SAndroid Build Coastguard Worker 	print_fatal_error(data, "Missing GROUP tag on line %d of \"%s\".", f->linenum, f->filename);
4353*5e7646d2SAndroid Build Coastguard Worker 	return (0);
4354*5e7646d2SAndroid Build Coastguard Worker       }
4355*5e7646d2SAndroid Build Coastguard Worker 
4356*5e7646d2SAndroid Build Coastguard Worker       if ((group_tag = ippTagValue(temp)) == IPP_TAG_ZERO || group_tag >= IPP_TAG_UNSUPPORTED_VALUE)
4357*5e7646d2SAndroid Build Coastguard Worker       {
4358*5e7646d2SAndroid Build Coastguard Worker 	print_fatal_error(data, "Bad GROUP tag \"%s\" on line %d of \"%s\".", temp, f->linenum, f->filename);
4359*5e7646d2SAndroid Build Coastguard Worker 	return (0);
4360*5e7646d2SAndroid Build Coastguard Worker       }
4361*5e7646d2SAndroid Build Coastguard Worker 
4362*5e7646d2SAndroid Build Coastguard Worker       if (group_tag == f->group_tag)
4363*5e7646d2SAndroid Build Coastguard Worker 	ippAddSeparator(f->attrs);
4364*5e7646d2SAndroid Build Coastguard Worker 
4365*5e7646d2SAndroid Build Coastguard Worker       f->group_tag = group_tag;
4366*5e7646d2SAndroid Build Coastguard Worker     }
4367*5e7646d2SAndroid Build Coastguard Worker     else if (!_cups_strcasecmp(token, "DELAY"))
4368*5e7646d2SAndroid Build Coastguard Worker     {
4369*5e7646d2SAndroid Build Coastguard Worker      /*
4370*5e7646d2SAndroid Build Coastguard Worker       * Delay before operation...
4371*5e7646d2SAndroid Build Coastguard Worker       */
4372*5e7646d2SAndroid Build Coastguard Worker 
4373*5e7646d2SAndroid Build Coastguard Worker       double dval;                    /* Delay value */
4374*5e7646d2SAndroid Build Coastguard Worker 
4375*5e7646d2SAndroid Build Coastguard Worker       if (!_ippFileReadToken(f, temp, sizeof(temp)))
4376*5e7646d2SAndroid Build Coastguard Worker       {
4377*5e7646d2SAndroid Build Coastguard Worker 	print_fatal_error(data, "Missing DELAY value on line %d of \"%s\".", f->linenum, f->filename);
4378*5e7646d2SAndroid Build Coastguard Worker 	return (0);
4379*5e7646d2SAndroid Build Coastguard Worker       }
4380*5e7646d2SAndroid Build Coastguard Worker 
4381*5e7646d2SAndroid Build Coastguard Worker       _ippVarsExpand(vars, value, temp, sizeof(value));
4382*5e7646d2SAndroid Build Coastguard Worker 
4383*5e7646d2SAndroid Build Coastguard Worker       if ((dval = _cupsStrScand(value, &ptr, localeconv())) < 0.0 || (*ptr && *ptr != ','))
4384*5e7646d2SAndroid Build Coastguard Worker       {
4385*5e7646d2SAndroid Build Coastguard Worker 	print_fatal_error(data, "Bad DELAY value \"%s\" on line %d of \"%s\".", value, f->linenum, f->filename);
4386*5e7646d2SAndroid Build Coastguard Worker 	return (0);
4387*5e7646d2SAndroid Build Coastguard Worker       }
4388*5e7646d2SAndroid Build Coastguard Worker 
4389*5e7646d2SAndroid Build Coastguard Worker       data->delay = (useconds_t)(1000000.0 * dval);
4390*5e7646d2SAndroid Build Coastguard Worker 
4391*5e7646d2SAndroid Build Coastguard Worker       if (*ptr == ',')
4392*5e7646d2SAndroid Build Coastguard Worker       {
4393*5e7646d2SAndroid Build Coastguard Worker 	if ((dval = _cupsStrScand(ptr + 1, &ptr, localeconv())) <= 0.0 || *ptr)
4394*5e7646d2SAndroid Build Coastguard Worker 	{
4395*5e7646d2SAndroid Build Coastguard Worker 	  print_fatal_error(data, "Bad DELAY value \"%s\" on line %d of \"%s\".", value, f->linenum, f->filename);
4396*5e7646d2SAndroid Build Coastguard Worker 	  return (0);
4397*5e7646d2SAndroid Build Coastguard Worker 	}
4398*5e7646d2SAndroid Build Coastguard Worker 
4399*5e7646d2SAndroid Build Coastguard Worker 	data->repeat_interval = (useconds_t)(1000000.0 * dval);
4400*5e7646d2SAndroid Build Coastguard Worker       }
4401*5e7646d2SAndroid Build Coastguard Worker       else
4402*5e7646d2SAndroid Build Coastguard Worker 	data->repeat_interval = data->delay;
4403*5e7646d2SAndroid Build Coastguard Worker     }
4404*5e7646d2SAndroid Build Coastguard Worker     else if (!_cups_strcasecmp(token, "FILE"))
4405*5e7646d2SAndroid Build Coastguard Worker     {
4406*5e7646d2SAndroid Build Coastguard Worker      /*
4407*5e7646d2SAndroid Build Coastguard Worker       * File...
4408*5e7646d2SAndroid Build Coastguard Worker       */
4409*5e7646d2SAndroid Build Coastguard Worker 
4410*5e7646d2SAndroid Build Coastguard Worker       if (!_ippFileReadToken(f, temp, sizeof(temp)))
4411*5e7646d2SAndroid Build Coastguard Worker       {
4412*5e7646d2SAndroid Build Coastguard Worker 	print_fatal_error(data, "Missing FILE filename on line %d of \"%s\".", f->linenum, f->filename);
4413*5e7646d2SAndroid Build Coastguard Worker 	return (0);
4414*5e7646d2SAndroid Build Coastguard Worker       }
4415*5e7646d2SAndroid Build Coastguard Worker 
4416*5e7646d2SAndroid Build Coastguard Worker       _ippVarsExpand(vars, value, temp, sizeof(value));
4417*5e7646d2SAndroid Build Coastguard Worker       get_filename(f->filename, data->file, value, sizeof(data->file));
4418*5e7646d2SAndroid Build Coastguard Worker 
4419*5e7646d2SAndroid Build Coastguard Worker       if (access(data->file, R_OK))
4420*5e7646d2SAndroid Build Coastguard Worker       {
4421*5e7646d2SAndroid Build Coastguard Worker 	print_fatal_error(data, "Filename \"%s\" (mapped to \"%s\") on line %d of \"%s\" cannot be read.", value, data->file, f->linenum, f->filename);
4422*5e7646d2SAndroid Build Coastguard Worker 	return (0);
4423*5e7646d2SAndroid Build Coastguard Worker       }
4424*5e7646d2SAndroid Build Coastguard Worker     }
4425*5e7646d2SAndroid Build Coastguard Worker     else if (!_cups_strcasecmp(token, "STATUS"))
4426*5e7646d2SAndroid Build Coastguard Worker     {
4427*5e7646d2SAndroid Build Coastguard Worker      /*
4428*5e7646d2SAndroid Build Coastguard Worker       * Status...
4429*5e7646d2SAndroid Build Coastguard Worker       */
4430*5e7646d2SAndroid Build Coastguard Worker 
4431*5e7646d2SAndroid Build Coastguard Worker       if (data->num_statuses >= (int)(sizeof(data->statuses) / sizeof(data->statuses[0])))
4432*5e7646d2SAndroid Build Coastguard Worker       {
4433*5e7646d2SAndroid Build Coastguard Worker 	print_fatal_error(data, "Too many STATUS's on line %d of \"%s\".", f->linenum, f->filename);
4434*5e7646d2SAndroid Build Coastguard Worker 	return (0);
4435*5e7646d2SAndroid Build Coastguard Worker       }
4436*5e7646d2SAndroid Build Coastguard Worker 
4437*5e7646d2SAndroid Build Coastguard Worker       if (!_ippFileReadToken(f, temp, sizeof(temp)))
4438*5e7646d2SAndroid Build Coastguard Worker       {
4439*5e7646d2SAndroid Build Coastguard Worker 	print_fatal_error(data, "Missing STATUS code on line %d of \"%s\".", f->linenum, f->filename);
4440*5e7646d2SAndroid Build Coastguard Worker 	return (0);
4441*5e7646d2SAndroid Build Coastguard Worker       }
4442*5e7646d2SAndroid Build Coastguard Worker 
4443*5e7646d2SAndroid Build Coastguard Worker       if ((data->statuses[data->num_statuses].status = ippErrorValue(temp)) == (ipp_status_t)-1 && (data->statuses[data->num_statuses].status = (ipp_status_t)strtol(temp, NULL, 0)) == 0)
4444*5e7646d2SAndroid Build Coastguard Worker       {
4445*5e7646d2SAndroid Build Coastguard Worker 	print_fatal_error(data, "Bad STATUS code \"%s\" on line %d of \"%s\".", temp, f->linenum, f->filename);
4446*5e7646d2SAndroid Build Coastguard Worker 	return (0);
4447*5e7646d2SAndroid Build Coastguard Worker       }
4448*5e7646d2SAndroid Build Coastguard Worker 
4449*5e7646d2SAndroid Build Coastguard Worker       data->last_status = data->statuses + data->num_statuses;
4450*5e7646d2SAndroid Build Coastguard Worker       data->num_statuses ++;
4451*5e7646d2SAndroid Build Coastguard Worker 
4452*5e7646d2SAndroid Build Coastguard Worker       data->last_status->define_match    = NULL;
4453*5e7646d2SAndroid Build Coastguard Worker       data->last_status->define_no_match = NULL;
4454*5e7646d2SAndroid Build Coastguard Worker       data->last_status->if_defined      = NULL;
4455*5e7646d2SAndroid Build Coastguard Worker       data->last_status->if_not_defined  = NULL;
4456*5e7646d2SAndroid Build Coastguard Worker       data->last_status->repeat_limit    = 1000;
4457*5e7646d2SAndroid Build Coastguard Worker       data->last_status->repeat_match    = 0;
4458*5e7646d2SAndroid Build Coastguard Worker       data->last_status->repeat_no_match = 0;
4459*5e7646d2SAndroid Build Coastguard Worker     }
4460*5e7646d2SAndroid Build Coastguard Worker     else if (!_cups_strcasecmp(token, "EXPECT") || !_cups_strcasecmp(token, "EXPECT-ALL"))
4461*5e7646d2SAndroid Build Coastguard Worker     {
4462*5e7646d2SAndroid Build Coastguard Worker      /*
4463*5e7646d2SAndroid Build Coastguard Worker       * Expected attributes...
4464*5e7646d2SAndroid Build Coastguard Worker       */
4465*5e7646d2SAndroid Build Coastguard Worker 
4466*5e7646d2SAndroid Build Coastguard Worker       int expect_all = !_cups_strcasecmp(token, "EXPECT-ALL");
4467*5e7646d2SAndroid Build Coastguard Worker 
4468*5e7646d2SAndroid Build Coastguard Worker       if (data->num_expects >= (int)(sizeof(data->expects) / sizeof(data->expects[0])))
4469*5e7646d2SAndroid Build Coastguard Worker       {
4470*5e7646d2SAndroid Build Coastguard Worker 	print_fatal_error(data, "Too many EXPECT's on line %d of \"%s\".", f->linenum, f->filename);
4471*5e7646d2SAndroid Build Coastguard Worker 	return (0);
4472*5e7646d2SAndroid Build Coastguard Worker       }
4473*5e7646d2SAndroid Build Coastguard Worker 
4474*5e7646d2SAndroid Build Coastguard Worker       if (!_ippFileReadToken(f, name, sizeof(name)))
4475*5e7646d2SAndroid Build Coastguard Worker       {
4476*5e7646d2SAndroid Build Coastguard Worker 	print_fatal_error(data, "Missing EXPECT name on line %d of \"%s\".", f->linenum, f->filename);
4477*5e7646d2SAndroid Build Coastguard Worker 	return (0);
4478*5e7646d2SAndroid Build Coastguard Worker       }
4479*5e7646d2SAndroid Build Coastguard Worker 
4480*5e7646d2SAndroid Build Coastguard Worker       data->last_expect = data->expects + data->num_expects;
4481*5e7646d2SAndroid Build Coastguard Worker       data->num_expects ++;
4482*5e7646d2SAndroid Build Coastguard Worker 
4483*5e7646d2SAndroid Build Coastguard Worker       memset(data->last_expect, 0, sizeof(ipptool_expect_t));
4484*5e7646d2SAndroid Build Coastguard Worker       data->last_expect->repeat_limit = 1000;
4485*5e7646d2SAndroid Build Coastguard Worker       data->last_expect->expect_all   = expect_all;
4486*5e7646d2SAndroid Build Coastguard Worker 
4487*5e7646d2SAndroid Build Coastguard Worker       if (name[0] == '!')
4488*5e7646d2SAndroid Build Coastguard Worker       {
4489*5e7646d2SAndroid Build Coastguard Worker 	data->last_expect->not_expect = 1;
4490*5e7646d2SAndroid Build Coastguard Worker 	data->last_expect->name       = strdup(name + 1);
4491*5e7646d2SAndroid Build Coastguard Worker       }
4492*5e7646d2SAndroid Build Coastguard Worker       else if (name[0] == '?')
4493*5e7646d2SAndroid Build Coastguard Worker       {
4494*5e7646d2SAndroid Build Coastguard Worker 	data->last_expect->optional = 1;
4495*5e7646d2SAndroid Build Coastguard Worker 	data->last_expect->name     = strdup(name + 1);
4496*5e7646d2SAndroid Build Coastguard Worker       }
4497*5e7646d2SAndroid Build Coastguard Worker       else
4498*5e7646d2SAndroid Build Coastguard Worker 	data->last_expect->name = strdup(name);
4499*5e7646d2SAndroid Build Coastguard Worker     }
4500*5e7646d2SAndroid Build Coastguard Worker     else if (!_cups_strcasecmp(token, "COUNT"))
4501*5e7646d2SAndroid Build Coastguard Worker     {
4502*5e7646d2SAndroid Build Coastguard Worker       int	count;			/* Count value */
4503*5e7646d2SAndroid Build Coastguard Worker 
4504*5e7646d2SAndroid Build Coastguard Worker       if (!_ippFileReadToken(f, temp, sizeof(temp)))
4505*5e7646d2SAndroid Build Coastguard Worker       {
4506*5e7646d2SAndroid Build Coastguard Worker 	print_fatal_error(data, "Missing COUNT number on line %d of \"%s\".", f->linenum, f->filename);
4507*5e7646d2SAndroid Build Coastguard Worker 	return (0);
4508*5e7646d2SAndroid Build Coastguard Worker       }
4509*5e7646d2SAndroid Build Coastguard Worker 
4510*5e7646d2SAndroid Build Coastguard Worker       if ((count = atoi(temp)) <= 0)
4511*5e7646d2SAndroid Build Coastguard Worker       {
4512*5e7646d2SAndroid Build Coastguard Worker 	print_fatal_error(data, "Bad COUNT \"%s\" on line %d of \"%s\".", temp, f->linenum, f->filename);
4513*5e7646d2SAndroid Build Coastguard Worker 	return (0);
4514*5e7646d2SAndroid Build Coastguard Worker       }
4515*5e7646d2SAndroid Build Coastguard Worker 
4516*5e7646d2SAndroid Build Coastguard Worker       if (data->last_expect)
4517*5e7646d2SAndroid Build Coastguard Worker       {
4518*5e7646d2SAndroid Build Coastguard Worker 	data->last_expect->count = count;
4519*5e7646d2SAndroid Build Coastguard Worker       }
4520*5e7646d2SAndroid Build Coastguard Worker       else
4521*5e7646d2SAndroid Build Coastguard Worker       {
4522*5e7646d2SAndroid Build Coastguard Worker 	print_fatal_error(data, "COUNT without a preceding EXPECT on line %d of \"%s\".", f->linenum, f->filename);
4523*5e7646d2SAndroid Build Coastguard Worker 	return (0);
4524*5e7646d2SAndroid Build Coastguard Worker       }
4525*5e7646d2SAndroid Build Coastguard Worker     }
4526*5e7646d2SAndroid Build Coastguard Worker     else if (!_cups_strcasecmp(token, "DEFINE-MATCH"))
4527*5e7646d2SAndroid Build Coastguard Worker     {
4528*5e7646d2SAndroid Build Coastguard Worker       if (!_ippFileReadToken(f, temp, sizeof(temp)))
4529*5e7646d2SAndroid Build Coastguard Worker       {
4530*5e7646d2SAndroid Build Coastguard Worker 	print_fatal_error(data, "Missing DEFINE-MATCH variable on line %d of \"%s\".", f->linenum, f->filename);
4531*5e7646d2SAndroid Build Coastguard Worker 	return (0);
4532*5e7646d2SAndroid Build Coastguard Worker       }
4533*5e7646d2SAndroid Build Coastguard Worker 
4534*5e7646d2SAndroid Build Coastguard Worker       if (data->last_expect)
4535*5e7646d2SAndroid Build Coastguard Worker       {
4536*5e7646d2SAndroid Build Coastguard Worker 	data->last_expect->define_match = strdup(temp);
4537*5e7646d2SAndroid Build Coastguard Worker       }
4538*5e7646d2SAndroid Build Coastguard Worker       else if (data->last_status)
4539*5e7646d2SAndroid Build Coastguard Worker       {
4540*5e7646d2SAndroid Build Coastguard Worker 	data->last_status->define_match = strdup(temp);
4541*5e7646d2SAndroid Build Coastguard Worker       }
4542*5e7646d2SAndroid Build Coastguard Worker       else
4543*5e7646d2SAndroid Build Coastguard Worker       {
4544*5e7646d2SAndroid Build Coastguard Worker 	print_fatal_error(data, "DEFINE-MATCH without a preceding EXPECT or STATUS on line %d of \"%s\".", f->linenum, f->filename);
4545*5e7646d2SAndroid Build Coastguard Worker 	return (0);
4546*5e7646d2SAndroid Build Coastguard Worker       }
4547*5e7646d2SAndroid Build Coastguard Worker     }
4548*5e7646d2SAndroid Build Coastguard Worker     else if (!_cups_strcasecmp(token, "DEFINE-NO-MATCH"))
4549*5e7646d2SAndroid Build Coastguard Worker     {
4550*5e7646d2SAndroid Build Coastguard Worker       if (!_ippFileReadToken(f, temp, sizeof(temp)))
4551*5e7646d2SAndroid Build Coastguard Worker       {
4552*5e7646d2SAndroid Build Coastguard Worker 	print_fatal_error(data, "Missing DEFINE-NO-MATCH variable on line %d of \"%s\".", f->linenum, f->filename);
4553*5e7646d2SAndroid Build Coastguard Worker 	return (0);
4554*5e7646d2SAndroid Build Coastguard Worker       }
4555*5e7646d2SAndroid Build Coastguard Worker 
4556*5e7646d2SAndroid Build Coastguard Worker       if (data->last_expect)
4557*5e7646d2SAndroid Build Coastguard Worker       {
4558*5e7646d2SAndroid Build Coastguard Worker 	data->last_expect->define_no_match = strdup(temp);
4559*5e7646d2SAndroid Build Coastguard Worker       }
4560*5e7646d2SAndroid Build Coastguard Worker       else if (data->last_status)
4561*5e7646d2SAndroid Build Coastguard Worker       {
4562*5e7646d2SAndroid Build Coastguard Worker 	data->last_status->define_no_match = strdup(temp);
4563*5e7646d2SAndroid Build Coastguard Worker       }
4564*5e7646d2SAndroid Build Coastguard Worker       else
4565*5e7646d2SAndroid Build Coastguard Worker       {
4566*5e7646d2SAndroid Build Coastguard Worker 	print_fatal_error(data, "DEFINE-NO-MATCH without a preceding EXPECT or STATUS on line %d of \"%s\".", f->linenum, f->filename);
4567*5e7646d2SAndroid Build Coastguard Worker 	return (0);
4568*5e7646d2SAndroid Build Coastguard Worker       }
4569*5e7646d2SAndroid Build Coastguard Worker     }
4570*5e7646d2SAndroid Build Coastguard Worker     else if (!_cups_strcasecmp(token, "DEFINE-VALUE"))
4571*5e7646d2SAndroid Build Coastguard Worker     {
4572*5e7646d2SAndroid Build Coastguard Worker       if (!_ippFileReadToken(f, temp, sizeof(temp)))
4573*5e7646d2SAndroid Build Coastguard Worker       {
4574*5e7646d2SAndroid Build Coastguard Worker 	print_fatal_error(data, "Missing DEFINE-VALUE variable on line %d of \"%s\".", f->linenum, f->filename);
4575*5e7646d2SAndroid Build Coastguard Worker 	return (0);
4576*5e7646d2SAndroid Build Coastguard Worker       }
4577*5e7646d2SAndroid Build Coastguard Worker 
4578*5e7646d2SAndroid Build Coastguard Worker       if (data->last_expect)
4579*5e7646d2SAndroid Build Coastguard Worker       {
4580*5e7646d2SAndroid Build Coastguard Worker 	data->last_expect->define_value = strdup(temp);
4581*5e7646d2SAndroid Build Coastguard Worker       }
4582*5e7646d2SAndroid Build Coastguard Worker       else
4583*5e7646d2SAndroid Build Coastguard Worker       {
4584*5e7646d2SAndroid Build Coastguard Worker 	print_fatal_error(data, "DEFINE-VALUE without a preceding EXPECT on line %d of \"%s\".", f->linenum, f->filename);
4585*5e7646d2SAndroid Build Coastguard Worker 	return (0);
4586*5e7646d2SAndroid Build Coastguard Worker       }
4587*5e7646d2SAndroid Build Coastguard Worker     }
4588*5e7646d2SAndroid Build Coastguard Worker     else if (!_cups_strcasecmp(token, "DISPLAY-MATCH"))
4589*5e7646d2SAndroid Build Coastguard Worker     {
4590*5e7646d2SAndroid Build Coastguard Worker       if (!_ippFileReadToken(f, temp, sizeof(temp)))
4591*5e7646d2SAndroid Build Coastguard Worker       {
4592*5e7646d2SAndroid Build Coastguard Worker 	print_fatal_error(data, "Missing DISPLAY-MATCH mesaage on line %d of \"%s\".", f->linenum, f->filename);
4593*5e7646d2SAndroid Build Coastguard Worker 	return (0);
4594*5e7646d2SAndroid Build Coastguard Worker       }
4595*5e7646d2SAndroid Build Coastguard Worker 
4596*5e7646d2SAndroid Build Coastguard Worker       if (data->last_expect)
4597*5e7646d2SAndroid Build Coastguard Worker       {
4598*5e7646d2SAndroid Build Coastguard Worker 	data->last_expect->display_match = strdup(temp);
4599*5e7646d2SAndroid Build Coastguard Worker       }
4600*5e7646d2SAndroid Build Coastguard Worker       else
4601*5e7646d2SAndroid Build Coastguard Worker       {
4602*5e7646d2SAndroid Build Coastguard Worker 	print_fatal_error(data, "DISPLAY-MATCH without a preceding EXPECT on line %d of \"%s\".", f->linenum, f->filename);
4603*5e7646d2SAndroid Build Coastguard Worker 	return (0);
4604*5e7646d2SAndroid Build Coastguard Worker       }
4605*5e7646d2SAndroid Build Coastguard Worker     }
4606*5e7646d2SAndroid Build Coastguard Worker     else if (!_cups_strcasecmp(token, "OF-TYPE"))
4607*5e7646d2SAndroid Build Coastguard Worker     {
4608*5e7646d2SAndroid Build Coastguard Worker       if (!_ippFileReadToken(f, temp, sizeof(temp)))
4609*5e7646d2SAndroid Build Coastguard Worker       {
4610*5e7646d2SAndroid Build Coastguard Worker 	print_fatal_error(data, "Missing OF-TYPE value tag(s) on line %d of \"%s\".", f->linenum, f->filename);
4611*5e7646d2SAndroid Build Coastguard Worker 	return (0);
4612*5e7646d2SAndroid Build Coastguard Worker       }
4613*5e7646d2SAndroid Build Coastguard Worker 
4614*5e7646d2SAndroid Build Coastguard Worker       if (data->last_expect)
4615*5e7646d2SAndroid Build Coastguard Worker       {
4616*5e7646d2SAndroid Build Coastguard Worker 	data->last_expect->of_type = strdup(temp);
4617*5e7646d2SAndroid Build Coastguard Worker       }
4618*5e7646d2SAndroid Build Coastguard Worker       else
4619*5e7646d2SAndroid Build Coastguard Worker       {
4620*5e7646d2SAndroid Build Coastguard Worker 	print_fatal_error(data, "OF-TYPE without a preceding EXPECT on line %d of \"%s\".", f->linenum, f->filename);
4621*5e7646d2SAndroid Build Coastguard Worker 	return (0);
4622*5e7646d2SAndroid Build Coastguard Worker       }
4623*5e7646d2SAndroid Build Coastguard Worker     }
4624*5e7646d2SAndroid Build Coastguard Worker     else if (!_cups_strcasecmp(token, "IN-GROUP"))
4625*5e7646d2SAndroid Build Coastguard Worker     {
4626*5e7646d2SAndroid Build Coastguard Worker       ipp_tag_t	in_group;		/* IN-GROUP value */
4627*5e7646d2SAndroid Build Coastguard Worker 
4628*5e7646d2SAndroid Build Coastguard Worker       if (!_ippFileReadToken(f, temp, sizeof(temp)))
4629*5e7646d2SAndroid Build Coastguard Worker       {
4630*5e7646d2SAndroid Build Coastguard Worker 	print_fatal_error(data, "Missing IN-GROUP group tag on line %d of \"%s\".", f->linenum, f->filename);
4631*5e7646d2SAndroid Build Coastguard Worker 	return (0);
4632*5e7646d2SAndroid Build Coastguard Worker       }
4633*5e7646d2SAndroid Build Coastguard Worker 
4634*5e7646d2SAndroid Build Coastguard Worker       if ((in_group = ippTagValue(temp)) == IPP_TAG_ZERO || in_group >= IPP_TAG_UNSUPPORTED_VALUE)
4635*5e7646d2SAndroid Build Coastguard Worker       {
4636*5e7646d2SAndroid Build Coastguard Worker 	print_fatal_error(data, "Bad IN-GROUP group tag \"%s\" on line %d of \"%s\".", temp, f->linenum, f->filename);
4637*5e7646d2SAndroid Build Coastguard Worker 	return (0);
4638*5e7646d2SAndroid Build Coastguard Worker       }
4639*5e7646d2SAndroid Build Coastguard Worker       else if (data->last_expect)
4640*5e7646d2SAndroid Build Coastguard Worker       {
4641*5e7646d2SAndroid Build Coastguard Worker 	data->last_expect->in_group = in_group;
4642*5e7646d2SAndroid Build Coastguard Worker       }
4643*5e7646d2SAndroid Build Coastguard Worker       else
4644*5e7646d2SAndroid Build Coastguard Worker       {
4645*5e7646d2SAndroid Build Coastguard Worker 	print_fatal_error(data, "IN-GROUP without a preceding EXPECT on line %d of \"%s\".", f->linenum, f->filename);
4646*5e7646d2SAndroid Build Coastguard Worker 	return (0);
4647*5e7646d2SAndroid Build Coastguard Worker       }
4648*5e7646d2SAndroid Build Coastguard Worker     }
4649*5e7646d2SAndroid Build Coastguard Worker     else if (!_cups_strcasecmp(token, "REPEAT-LIMIT"))
4650*5e7646d2SAndroid Build Coastguard Worker     {
4651*5e7646d2SAndroid Build Coastguard Worker       if (!_ippFileReadToken(f, temp, sizeof(temp)))
4652*5e7646d2SAndroid Build Coastguard Worker       {
4653*5e7646d2SAndroid Build Coastguard Worker 	print_fatal_error(data, "Missing REPEAT-LIMIT value on line %d of \"%s\".", f->linenum, f->filename);
4654*5e7646d2SAndroid Build Coastguard Worker 	return (0);
4655*5e7646d2SAndroid Build Coastguard Worker       }
4656*5e7646d2SAndroid Build Coastguard Worker       else if (atoi(temp) <= 0)
4657*5e7646d2SAndroid Build Coastguard Worker       {
4658*5e7646d2SAndroid Build Coastguard Worker 	print_fatal_error(data, "Bad REPEAT-LIMIT value on line %d of \"%s\".", f->linenum, f->filename);
4659*5e7646d2SAndroid Build Coastguard Worker 	return (0);
4660*5e7646d2SAndroid Build Coastguard Worker       }
4661*5e7646d2SAndroid Build Coastguard Worker 
4662*5e7646d2SAndroid Build Coastguard Worker       if (data->last_status)
4663*5e7646d2SAndroid Build Coastguard Worker       {
4664*5e7646d2SAndroid Build Coastguard Worker 	data->last_status->repeat_limit = atoi(temp);
4665*5e7646d2SAndroid Build Coastguard Worker       }
4666*5e7646d2SAndroid Build Coastguard Worker       else if (data->last_expect)
4667*5e7646d2SAndroid Build Coastguard Worker       {
4668*5e7646d2SAndroid Build Coastguard Worker 	data->last_expect->repeat_limit = atoi(temp);
4669*5e7646d2SAndroid Build Coastguard Worker       }
4670*5e7646d2SAndroid Build Coastguard Worker       else
4671*5e7646d2SAndroid Build Coastguard Worker       {
4672*5e7646d2SAndroid Build Coastguard Worker 	print_fatal_error(data, "REPEAT-LIMIT without a preceding EXPECT or STATUS on line %d of \"%s\".", f->linenum, f->filename);
4673*5e7646d2SAndroid Build Coastguard Worker 	return (0);
4674*5e7646d2SAndroid Build Coastguard Worker       }
4675*5e7646d2SAndroid Build Coastguard Worker     }
4676*5e7646d2SAndroid Build Coastguard Worker     else if (!_cups_strcasecmp(token, "REPEAT-MATCH"))
4677*5e7646d2SAndroid Build Coastguard Worker     {
4678*5e7646d2SAndroid Build Coastguard Worker       if (data->last_status)
4679*5e7646d2SAndroid Build Coastguard Worker       {
4680*5e7646d2SAndroid Build Coastguard Worker 	data->last_status->repeat_match = 1;
4681*5e7646d2SAndroid Build Coastguard Worker       }
4682*5e7646d2SAndroid Build Coastguard Worker       else if (data->last_expect)
4683*5e7646d2SAndroid Build Coastguard Worker       {
4684*5e7646d2SAndroid Build Coastguard Worker 	data->last_expect->repeat_match = 1;
4685*5e7646d2SAndroid Build Coastguard Worker       }
4686*5e7646d2SAndroid Build Coastguard Worker       else
4687*5e7646d2SAndroid Build Coastguard Worker       {
4688*5e7646d2SAndroid Build Coastguard Worker 	print_fatal_error(data, "REPEAT-MATCH without a preceding EXPECT or STATUS on line %d of \"%s\".", f->linenum, f->filename);
4689*5e7646d2SAndroid Build Coastguard Worker 	return (0);
4690*5e7646d2SAndroid Build Coastguard Worker       }
4691*5e7646d2SAndroid Build Coastguard Worker     }
4692*5e7646d2SAndroid Build Coastguard Worker     else if (!_cups_strcasecmp(token, "REPEAT-NO-MATCH"))
4693*5e7646d2SAndroid Build Coastguard Worker     {
4694*5e7646d2SAndroid Build Coastguard Worker       if (data->last_status)
4695*5e7646d2SAndroid Build Coastguard Worker       {
4696*5e7646d2SAndroid Build Coastguard Worker 	data->last_status->repeat_no_match = 1;
4697*5e7646d2SAndroid Build Coastguard Worker       }
4698*5e7646d2SAndroid Build Coastguard Worker       else if (data->last_expect)
4699*5e7646d2SAndroid Build Coastguard Worker       {
4700*5e7646d2SAndroid Build Coastguard Worker 	data->last_expect->repeat_no_match = 1;
4701*5e7646d2SAndroid Build Coastguard Worker       }
4702*5e7646d2SAndroid Build Coastguard Worker       else
4703*5e7646d2SAndroid Build Coastguard Worker       {
4704*5e7646d2SAndroid Build Coastguard Worker 	print_fatal_error(data, "REPEAT-NO-MATCH without a preceding EXPECT or STATUS on line %d of \"%s\".", f->linenum, f->filename);
4705*5e7646d2SAndroid Build Coastguard Worker 	return (0);
4706*5e7646d2SAndroid Build Coastguard Worker       }
4707*5e7646d2SAndroid Build Coastguard Worker     }
4708*5e7646d2SAndroid Build Coastguard Worker     else if (!_cups_strcasecmp(token, "SAME-COUNT-AS"))
4709*5e7646d2SAndroid Build Coastguard Worker     {
4710*5e7646d2SAndroid Build Coastguard Worker       if (!_ippFileReadToken(f, temp, sizeof(temp)))
4711*5e7646d2SAndroid Build Coastguard Worker       {
4712*5e7646d2SAndroid Build Coastguard Worker 	print_fatal_error(data, "Missing SAME-COUNT-AS name on line %d of \"%s\".", f->linenum, f->filename);
4713*5e7646d2SAndroid Build Coastguard Worker 	return (0);
4714*5e7646d2SAndroid Build Coastguard Worker       }
4715*5e7646d2SAndroid Build Coastguard Worker 
4716*5e7646d2SAndroid Build Coastguard Worker       if (data->last_expect)
4717*5e7646d2SAndroid Build Coastguard Worker       {
4718*5e7646d2SAndroid Build Coastguard Worker 	data->last_expect->same_count_as = strdup(temp);
4719*5e7646d2SAndroid Build Coastguard Worker       }
4720*5e7646d2SAndroid Build Coastguard Worker       else
4721*5e7646d2SAndroid Build Coastguard Worker       {
4722*5e7646d2SAndroid Build Coastguard Worker 	print_fatal_error(data, "SAME-COUNT-AS without a preceding EXPECT on line %d of \"%s\".", f->linenum, f->filename);
4723*5e7646d2SAndroid Build Coastguard Worker 	return (0);
4724*5e7646d2SAndroid Build Coastguard Worker       }
4725*5e7646d2SAndroid Build Coastguard Worker     }
4726*5e7646d2SAndroid Build Coastguard Worker     else if (!_cups_strcasecmp(token, "IF-DEFINED"))
4727*5e7646d2SAndroid Build Coastguard Worker     {
4728*5e7646d2SAndroid Build Coastguard Worker       if (!_ippFileReadToken(f, temp, sizeof(temp)))
4729*5e7646d2SAndroid Build Coastguard Worker       {
4730*5e7646d2SAndroid Build Coastguard Worker 	print_fatal_error(data, "Missing IF-DEFINED name on line %d of \"%s\".", f->linenum, f->filename);
4731*5e7646d2SAndroid Build Coastguard Worker 	return (0);
4732*5e7646d2SAndroid Build Coastguard Worker       }
4733*5e7646d2SAndroid Build Coastguard Worker 
4734*5e7646d2SAndroid Build Coastguard Worker       if (data->last_expect)
4735*5e7646d2SAndroid Build Coastguard Worker       {
4736*5e7646d2SAndroid Build Coastguard Worker 	data->last_expect->if_defined = strdup(temp);
4737*5e7646d2SAndroid Build Coastguard Worker       }
4738*5e7646d2SAndroid Build Coastguard Worker       else if (data->last_status)
4739*5e7646d2SAndroid Build Coastguard Worker       {
4740*5e7646d2SAndroid Build Coastguard Worker 	data->last_status->if_defined = strdup(temp);
4741*5e7646d2SAndroid Build Coastguard Worker       }
4742*5e7646d2SAndroid Build Coastguard Worker       else
4743*5e7646d2SAndroid Build Coastguard Worker       {
4744*5e7646d2SAndroid Build Coastguard Worker 	print_fatal_error(data, "IF-DEFINED without a preceding EXPECT or STATUS on line %d of \"%s\".", f->linenum, f->filename);
4745*5e7646d2SAndroid Build Coastguard Worker 	return (0);
4746*5e7646d2SAndroid Build Coastguard Worker       }
4747*5e7646d2SAndroid Build Coastguard Worker     }
4748*5e7646d2SAndroid Build Coastguard Worker     else if (!_cups_strcasecmp(token, "IF-NOT-DEFINED"))
4749*5e7646d2SAndroid Build Coastguard Worker     {
4750*5e7646d2SAndroid Build Coastguard Worker       if (!_ippFileReadToken(f, temp, sizeof(temp)))
4751*5e7646d2SAndroid Build Coastguard Worker       {
4752*5e7646d2SAndroid Build Coastguard Worker 	print_fatal_error(data, "Missing IF-NOT-DEFINED name on line %d of \"%s\".", f->linenum, f->filename);
4753*5e7646d2SAndroid Build Coastguard Worker 	return (0);
4754*5e7646d2SAndroid Build Coastguard Worker       }
4755*5e7646d2SAndroid Build Coastguard Worker 
4756*5e7646d2SAndroid Build Coastguard Worker       if (data->last_expect)
4757*5e7646d2SAndroid Build Coastguard Worker       {
4758*5e7646d2SAndroid Build Coastguard Worker 	data->last_expect->if_not_defined = strdup(temp);
4759*5e7646d2SAndroid Build Coastguard Worker       }
4760*5e7646d2SAndroid Build Coastguard Worker       else if (data->last_status)
4761*5e7646d2SAndroid Build Coastguard Worker       {
4762*5e7646d2SAndroid Build Coastguard Worker 	data->last_status->if_not_defined = strdup(temp);
4763*5e7646d2SAndroid Build Coastguard Worker       }
4764*5e7646d2SAndroid Build Coastguard Worker       else
4765*5e7646d2SAndroid Build Coastguard Worker       {
4766*5e7646d2SAndroid Build Coastguard Worker 	print_fatal_error(data, "IF-NOT-DEFINED without a preceding EXPECT or STATUS on line %d of \"%s\".", f->linenum, f->filename);
4767*5e7646d2SAndroid Build Coastguard Worker 	return (0);
4768*5e7646d2SAndroid Build Coastguard Worker       }
4769*5e7646d2SAndroid Build Coastguard Worker     }
4770*5e7646d2SAndroid Build Coastguard Worker     else if (!_cups_strcasecmp(token, "WITH-DISTINCT-VALUES"))
4771*5e7646d2SAndroid Build Coastguard Worker     {
4772*5e7646d2SAndroid Build Coastguard Worker       if (data->last_expect)
4773*5e7646d2SAndroid Build Coastguard Worker       {
4774*5e7646d2SAndroid Build Coastguard Worker         data->last_expect->with_distinct = 1;
4775*5e7646d2SAndroid Build Coastguard Worker       }
4776*5e7646d2SAndroid Build Coastguard Worker       else
4777*5e7646d2SAndroid Build Coastguard Worker       {
4778*5e7646d2SAndroid Build Coastguard Worker 	print_fatal_error(data, "%s without a preceding EXPECT on line %d of \"%s\".", token, f->linenum, f->filename);
4779*5e7646d2SAndroid Build Coastguard Worker 	return (0);
4780*5e7646d2SAndroid Build Coastguard Worker       }
4781*5e7646d2SAndroid Build Coastguard Worker     }
4782*5e7646d2SAndroid Build Coastguard Worker     else if (!_cups_strcasecmp(token, "WITH-ALL-VALUES") ||
4783*5e7646d2SAndroid Build Coastguard Worker 	     !_cups_strcasecmp(token, "WITH-ALL-HOSTNAMES") ||
4784*5e7646d2SAndroid Build Coastguard Worker 	     !_cups_strcasecmp(token, "WITH-ALL-RESOURCES") ||
4785*5e7646d2SAndroid Build Coastguard Worker 	     !_cups_strcasecmp(token, "WITH-ALL-SCHEMES") ||
4786*5e7646d2SAndroid Build Coastguard Worker 	     !_cups_strcasecmp(token, "WITH-HOSTNAME") ||
4787*5e7646d2SAndroid Build Coastguard Worker 	     !_cups_strcasecmp(token, "WITH-RESOURCE") ||
4788*5e7646d2SAndroid Build Coastguard Worker 	     !_cups_strcasecmp(token, "WITH-SCHEME") ||
4789*5e7646d2SAndroid Build Coastguard Worker 	     !_cups_strcasecmp(token, "WITH-VALUE"))
4790*5e7646d2SAndroid Build Coastguard Worker     {
4791*5e7646d2SAndroid Build Coastguard Worker       off_t	lastpos;		/* Last file position */
4792*5e7646d2SAndroid Build Coastguard Worker       int	lastline;		/* Last line number */
4793*5e7646d2SAndroid Build Coastguard Worker 
4794*5e7646d2SAndroid Build Coastguard Worker       if (data->last_expect)
4795*5e7646d2SAndroid Build Coastguard Worker       {
4796*5e7646d2SAndroid Build Coastguard Worker 	if (!_cups_strcasecmp(token, "WITH-ALL-HOSTNAMES") || !_cups_strcasecmp(token, "WITH-HOSTNAME"))
4797*5e7646d2SAndroid Build Coastguard Worker 	  data->last_expect->with_flags = IPPTOOL_WITH_HOSTNAME;
4798*5e7646d2SAndroid Build Coastguard Worker 	else if (!_cups_strcasecmp(token, "WITH-ALL-RESOURCES") || !_cups_strcasecmp(token, "WITH-RESOURCE"))
4799*5e7646d2SAndroid Build Coastguard Worker 	  data->last_expect->with_flags = IPPTOOL_WITH_RESOURCE;
4800*5e7646d2SAndroid Build Coastguard Worker 	else if (!_cups_strcasecmp(token, "WITH-ALL-SCHEMES") || !_cups_strcasecmp(token, "WITH-SCHEME"))
4801*5e7646d2SAndroid Build Coastguard Worker 	  data->last_expect->with_flags = IPPTOOL_WITH_SCHEME;
4802*5e7646d2SAndroid Build Coastguard Worker 
4803*5e7646d2SAndroid Build Coastguard Worker 	if (!_cups_strncasecmp(token, "WITH-ALL-", 9))
4804*5e7646d2SAndroid Build Coastguard Worker 	  data->last_expect->with_flags |= IPPTOOL_WITH_ALL;
4805*5e7646d2SAndroid Build Coastguard Worker       }
4806*5e7646d2SAndroid Build Coastguard Worker 
4807*5e7646d2SAndroid Build Coastguard Worker       if (!_ippFileReadToken(f, temp, sizeof(temp)))
4808*5e7646d2SAndroid Build Coastguard Worker       {
4809*5e7646d2SAndroid Build Coastguard Worker 	print_fatal_error(data, "Missing %s value on line %d of \"%s\".", token, f->linenum, f->filename);
4810*5e7646d2SAndroid Build Coastguard Worker 	return (0);
4811*5e7646d2SAndroid Build Coastguard Worker       }
4812*5e7646d2SAndroid Build Coastguard Worker 
4813*5e7646d2SAndroid Build Coastguard Worker      /*
4814*5e7646d2SAndroid Build Coastguard Worker       * Read additional comma-delimited values - needed since legacy test files
4815*5e7646d2SAndroid Build Coastguard Worker       * will have unquoted WITH-VALUE values with commas...
4816*5e7646d2SAndroid Build Coastguard Worker       */
4817*5e7646d2SAndroid Build Coastguard Worker 
4818*5e7646d2SAndroid Build Coastguard Worker       ptr = temp + strlen(temp);
4819*5e7646d2SAndroid Build Coastguard Worker 
4820*5e7646d2SAndroid Build Coastguard Worker       for (;;)
4821*5e7646d2SAndroid Build Coastguard Worker       {
4822*5e7646d2SAndroid Build Coastguard Worker         lastpos  = cupsFileTell(f->fp);
4823*5e7646d2SAndroid Build Coastguard Worker         lastline = f->linenum;
4824*5e7646d2SAndroid Build Coastguard Worker         ptr      += strlen(ptr);
4825*5e7646d2SAndroid Build Coastguard Worker 
4826*5e7646d2SAndroid Build Coastguard Worker 	if (!_ippFileReadToken(f, ptr, (sizeof(temp) - (size_t)(ptr - temp))))
4827*5e7646d2SAndroid Build Coastguard Worker 	  break;
4828*5e7646d2SAndroid Build Coastguard Worker 
4829*5e7646d2SAndroid Build Coastguard Worker         if (!strcmp(ptr, ","))
4830*5e7646d2SAndroid Build Coastguard Worker         {
4831*5e7646d2SAndroid Build Coastguard Worker          /*
4832*5e7646d2SAndroid Build Coastguard Worker           * Append a value...
4833*5e7646d2SAndroid Build Coastguard Worker           */
4834*5e7646d2SAndroid Build Coastguard Worker 
4835*5e7646d2SAndroid Build Coastguard Worker 	  ptr += strlen(ptr);
4836*5e7646d2SAndroid Build Coastguard Worker 
4837*5e7646d2SAndroid Build Coastguard Worker 	  if (!_ippFileReadToken(f, ptr, (sizeof(temp) - (size_t)(ptr - temp))))
4838*5e7646d2SAndroid Build Coastguard Worker 	    break;
4839*5e7646d2SAndroid Build Coastguard Worker         }
4840*5e7646d2SAndroid Build Coastguard Worker         else
4841*5e7646d2SAndroid Build Coastguard Worker         {
4842*5e7646d2SAndroid Build Coastguard Worker          /*
4843*5e7646d2SAndroid Build Coastguard Worker           * Not another value, stop here...
4844*5e7646d2SAndroid Build Coastguard Worker           */
4845*5e7646d2SAndroid Build Coastguard Worker 
4846*5e7646d2SAndroid Build Coastguard Worker           cupsFileSeek(f->fp, lastpos);
4847*5e7646d2SAndroid Build Coastguard Worker           f->linenum = lastline;
4848*5e7646d2SAndroid Build Coastguard Worker           *ptr = '\0';
4849*5e7646d2SAndroid Build Coastguard Worker           break;
4850*5e7646d2SAndroid Build Coastguard Worker 	}
4851*5e7646d2SAndroid Build Coastguard Worker       }
4852*5e7646d2SAndroid Build Coastguard Worker 
4853*5e7646d2SAndroid Build Coastguard Worker       if (data->last_expect)
4854*5e7646d2SAndroid Build Coastguard Worker       {
4855*5e7646d2SAndroid Build Coastguard Worker        /*
4856*5e7646d2SAndroid Build Coastguard Worker 	* Expand any variables in the value and then save it.
4857*5e7646d2SAndroid Build Coastguard Worker 	*/
4858*5e7646d2SAndroid Build Coastguard Worker 
4859*5e7646d2SAndroid Build Coastguard Worker 	_ippVarsExpand(vars, value, temp, sizeof(value));
4860*5e7646d2SAndroid Build Coastguard Worker 
4861*5e7646d2SAndroid Build Coastguard Worker 	ptr = value + strlen(value) - 1;
4862*5e7646d2SAndroid Build Coastguard Worker 
4863*5e7646d2SAndroid Build Coastguard Worker 	if (value[0] == '/' && ptr > value && *ptr == '/')
4864*5e7646d2SAndroid Build Coastguard Worker 	{
4865*5e7646d2SAndroid Build Coastguard Worker 	 /*
4866*5e7646d2SAndroid Build Coastguard Worker 	  * WITH-VALUE is a POSIX extended regular expression.
4867*5e7646d2SAndroid Build Coastguard Worker 	  */
4868*5e7646d2SAndroid Build Coastguard Worker 
4869*5e7646d2SAndroid Build Coastguard Worker 	  data->last_expect->with_value = calloc(1, (size_t)(ptr - value));
4870*5e7646d2SAndroid Build Coastguard Worker 	  data->last_expect->with_flags |= IPPTOOL_WITH_REGEX;
4871*5e7646d2SAndroid Build Coastguard Worker 
4872*5e7646d2SAndroid Build Coastguard Worker 	  if (data->last_expect->with_value)
4873*5e7646d2SAndroid Build Coastguard Worker 	    memcpy(data->last_expect->with_value, value + 1, (size_t)(ptr - value - 1));
4874*5e7646d2SAndroid Build Coastguard Worker 	}
4875*5e7646d2SAndroid Build Coastguard Worker 	else
4876*5e7646d2SAndroid Build Coastguard Worker 	{
4877*5e7646d2SAndroid Build Coastguard Worker 	 /*
4878*5e7646d2SAndroid Build Coastguard Worker 	  * WITH-VALUE is a literal value...
4879*5e7646d2SAndroid Build Coastguard Worker 	  */
4880*5e7646d2SAndroid Build Coastguard Worker 
4881*5e7646d2SAndroid Build Coastguard Worker 	  for (ptr = value; *ptr; ptr ++)
4882*5e7646d2SAndroid Build Coastguard Worker 	  {
4883*5e7646d2SAndroid Build Coastguard Worker 	    if (*ptr == '\\' && ptr[1])
4884*5e7646d2SAndroid Build Coastguard Worker 	    {
4885*5e7646d2SAndroid Build Coastguard Worker 	     /*
4886*5e7646d2SAndroid Build Coastguard Worker 	      * Remove \ from \foo...
4887*5e7646d2SAndroid Build Coastguard Worker 	      */
4888*5e7646d2SAndroid Build Coastguard Worker 
4889*5e7646d2SAndroid Build Coastguard Worker 	      _cups_strcpy(ptr, ptr + 1);
4890*5e7646d2SAndroid Build Coastguard Worker 	    }
4891*5e7646d2SAndroid Build Coastguard Worker 	  }
4892*5e7646d2SAndroid Build Coastguard Worker 
4893*5e7646d2SAndroid Build Coastguard Worker 	  data->last_expect->with_value = strdup(value);
4894*5e7646d2SAndroid Build Coastguard Worker 	  data->last_expect->with_flags |= IPPTOOL_WITH_LITERAL;
4895*5e7646d2SAndroid Build Coastguard Worker 	}
4896*5e7646d2SAndroid Build Coastguard Worker       }
4897*5e7646d2SAndroid Build Coastguard Worker       else
4898*5e7646d2SAndroid Build Coastguard Worker       {
4899*5e7646d2SAndroid Build Coastguard Worker 	print_fatal_error(data, "%s without a preceding EXPECT on line %d of \"%s\".", token, f->linenum, f->filename);
4900*5e7646d2SAndroid Build Coastguard Worker 	return (0);
4901*5e7646d2SAndroid Build Coastguard Worker       }
4902*5e7646d2SAndroid Build Coastguard Worker     }
4903*5e7646d2SAndroid Build Coastguard Worker     else if (!_cups_strcasecmp(token, "WITH-VALUE-FROM"))
4904*5e7646d2SAndroid Build Coastguard Worker     {
4905*5e7646d2SAndroid Build Coastguard Worker       if (!_ippFileReadToken(f, temp, sizeof(temp)))
4906*5e7646d2SAndroid Build Coastguard Worker       {
4907*5e7646d2SAndroid Build Coastguard Worker 	print_fatal_error(data, "Missing %s value on line %d of \"%s\".", token, f->linenum, f->filename);
4908*5e7646d2SAndroid Build Coastguard Worker 	return (0);
4909*5e7646d2SAndroid Build Coastguard Worker       }
4910*5e7646d2SAndroid Build Coastguard Worker 
4911*5e7646d2SAndroid Build Coastguard Worker       if (data->last_expect)
4912*5e7646d2SAndroid Build Coastguard Worker       {
4913*5e7646d2SAndroid Build Coastguard Worker        /*
4914*5e7646d2SAndroid Build Coastguard Worker 	* Expand any variables in the value and then save it.
4915*5e7646d2SAndroid Build Coastguard Worker 	*/
4916*5e7646d2SAndroid Build Coastguard Worker 
4917*5e7646d2SAndroid Build Coastguard Worker 	_ippVarsExpand(vars, value, temp, sizeof(value));
4918*5e7646d2SAndroid Build Coastguard Worker 
4919*5e7646d2SAndroid Build Coastguard Worker 	data->last_expect->with_value_from = strdup(value);
4920*5e7646d2SAndroid Build Coastguard Worker 	data->last_expect->with_flags      = IPPTOOL_WITH_LITERAL;
4921*5e7646d2SAndroid Build Coastguard Worker       }
4922*5e7646d2SAndroid Build Coastguard Worker       else
4923*5e7646d2SAndroid Build Coastguard Worker       {
4924*5e7646d2SAndroid Build Coastguard Worker 	print_fatal_error(data, "%s without a preceding EXPECT on line %d of \"%s\".", token, f->linenum, f->filename);
4925*5e7646d2SAndroid Build Coastguard Worker 	return (0);
4926*5e7646d2SAndroid Build Coastguard Worker       }
4927*5e7646d2SAndroid Build Coastguard Worker     }
4928*5e7646d2SAndroid Build Coastguard Worker     else if (!_cups_strcasecmp(token, "DISPLAY"))
4929*5e7646d2SAndroid Build Coastguard Worker     {
4930*5e7646d2SAndroid Build Coastguard Worker      /*
4931*5e7646d2SAndroid Build Coastguard Worker       * Display attributes...
4932*5e7646d2SAndroid Build Coastguard Worker       */
4933*5e7646d2SAndroid Build Coastguard Worker 
4934*5e7646d2SAndroid Build Coastguard Worker       if (data->num_displayed >= (int)(sizeof(data->displayed) / sizeof(data->displayed[0])))
4935*5e7646d2SAndroid Build Coastguard Worker       {
4936*5e7646d2SAndroid Build Coastguard Worker 	print_fatal_error(data, "Too many DISPLAY's on line %d of \"%s\".", f->linenum, f->filename);
4937*5e7646d2SAndroid Build Coastguard Worker 	return (0);
4938*5e7646d2SAndroid Build Coastguard Worker       }
4939*5e7646d2SAndroid Build Coastguard Worker 
4940*5e7646d2SAndroid Build Coastguard Worker       if (!_ippFileReadToken(f, temp, sizeof(temp)))
4941*5e7646d2SAndroid Build Coastguard Worker       {
4942*5e7646d2SAndroid Build Coastguard Worker 	print_fatal_error(data, "Missing DISPLAY name on line %d of \"%s\".", f->linenum, f->filename);
4943*5e7646d2SAndroid Build Coastguard Worker 	return (0);
4944*5e7646d2SAndroid Build Coastguard Worker       }
4945*5e7646d2SAndroid Build Coastguard Worker 
4946*5e7646d2SAndroid Build Coastguard Worker       data->displayed[data->num_displayed] = strdup(temp);
4947*5e7646d2SAndroid Build Coastguard Worker       data->num_displayed ++;
4948*5e7646d2SAndroid Build Coastguard Worker     }
4949*5e7646d2SAndroid Build Coastguard Worker     else
4950*5e7646d2SAndroid Build Coastguard Worker     {
4951*5e7646d2SAndroid Build Coastguard Worker       print_fatal_error(data, "Unexpected token %s seen on line %d of \"%s\".", token, f->linenum, f->filename);
4952*5e7646d2SAndroid Build Coastguard Worker       return (0);
4953*5e7646d2SAndroid Build Coastguard Worker     }
4954*5e7646d2SAndroid Build Coastguard Worker   }
4955*5e7646d2SAndroid Build Coastguard Worker   else
4956*5e7646d2SAndroid Build Coastguard Worker   {
4957*5e7646d2SAndroid Build Coastguard Worker    /*
4958*5e7646d2SAndroid Build Coastguard Worker     * Scan for the start of a test (open brace)...
4959*5e7646d2SAndroid Build Coastguard Worker     */
4960*5e7646d2SAndroid Build Coastguard Worker 
4961*5e7646d2SAndroid Build Coastguard Worker     if (!strcmp(token, "{"))
4962*5e7646d2SAndroid Build Coastguard Worker     {
4963*5e7646d2SAndroid Build Coastguard Worker      /*
4964*5e7646d2SAndroid Build Coastguard Worker       * Start new test...
4965*5e7646d2SAndroid Build Coastguard Worker       */
4966*5e7646d2SAndroid Build Coastguard Worker 
4967*5e7646d2SAndroid Build Coastguard Worker       if (data->show_header)
4968*5e7646d2SAndroid Build Coastguard Worker       {
4969*5e7646d2SAndroid Build Coastguard Worker 	if (data->output == IPPTOOL_OUTPUT_PLIST)
4970*5e7646d2SAndroid Build Coastguard Worker 	  print_xml_header(data);
4971*5e7646d2SAndroid Build Coastguard Worker 
4972*5e7646d2SAndroid Build Coastguard Worker 	if (data->output == IPPTOOL_OUTPUT_TEST || (data->output == IPPTOOL_OUTPUT_PLIST && data->outfile != cupsFileStdout()))
4973*5e7646d2SAndroid Build Coastguard Worker 	  cupsFilePrintf(cupsFileStdout(), "\"%s\":\n", f->filename);
4974*5e7646d2SAndroid Build Coastguard Worker 
4975*5e7646d2SAndroid Build Coastguard Worker 	data->show_header = 0;
4976*5e7646d2SAndroid Build Coastguard Worker       }
4977*5e7646d2SAndroid Build Coastguard Worker 
4978*5e7646d2SAndroid Build Coastguard Worker       data->compression[0] = '\0';
4979*5e7646d2SAndroid Build Coastguard Worker       data->delay          = 0;
4980*5e7646d2SAndroid Build Coastguard Worker       data->num_expects    = 0;
4981*5e7646d2SAndroid Build Coastguard Worker       data->last_expect    = NULL;
4982*5e7646d2SAndroid Build Coastguard Worker       data->file[0]        = '\0';
4983*5e7646d2SAndroid Build Coastguard Worker       data->ignore_errors  = data->def_ignore_errors;
4984*5e7646d2SAndroid Build Coastguard Worker       strlcpy(data->name, f->filename, sizeof(data->name));
4985*5e7646d2SAndroid Build Coastguard Worker       if ((ptr = strrchr(data->name, '.')) != NULL)
4986*5e7646d2SAndroid Build Coastguard Worker         *ptr = '\0';
4987*5e7646d2SAndroid Build Coastguard Worker       data->repeat_interval = 5000000;
4988*5e7646d2SAndroid Build Coastguard Worker       strlcpy(data->resource, data->vars->resource, sizeof(data->resource));
4989*5e7646d2SAndroid Build Coastguard Worker       data->skip_previous = 0;
4990*5e7646d2SAndroid Build Coastguard Worker       data->pass_test     = 0;
4991*5e7646d2SAndroid Build Coastguard Worker       data->skip_test     = 0;
4992*5e7646d2SAndroid Build Coastguard Worker       data->num_statuses  = 0;
4993*5e7646d2SAndroid Build Coastguard Worker       data->last_status   = NULL;
4994*5e7646d2SAndroid Build Coastguard Worker       data->test_id[0]    = '\0';
4995*5e7646d2SAndroid Build Coastguard Worker       data->transfer      = data->def_transfer;
4996*5e7646d2SAndroid Build Coastguard Worker       data->version       = data->def_version;
4997*5e7646d2SAndroid Build Coastguard Worker 
4998*5e7646d2SAndroid Build Coastguard Worker       free(data->monitor_uri);
4999*5e7646d2SAndroid Build Coastguard Worker       data->monitor_uri         = NULL;
5000*5e7646d2SAndroid Build Coastguard Worker       data->monitor_delay       = 0;
5001*5e7646d2SAndroid Build Coastguard Worker       data->monitor_interval    = 5000000;
5002*5e7646d2SAndroid Build Coastguard Worker       data->num_monitor_expects = 0;
5003*5e7646d2SAndroid Build Coastguard Worker 
5004*5e7646d2SAndroid Build Coastguard Worker       _ippVarsSet(vars, "date-current", iso_date(ippTimeToDate(time(NULL))));
5005*5e7646d2SAndroid Build Coastguard Worker 
5006*5e7646d2SAndroid Build Coastguard Worker       f->attrs     = ippNew();
5007*5e7646d2SAndroid Build Coastguard Worker       f->group_tag = IPP_TAG_ZERO;
5008*5e7646d2SAndroid Build Coastguard Worker     }
5009*5e7646d2SAndroid Build Coastguard Worker     else if (!strcmp(token, "DEFINE"))
5010*5e7646d2SAndroid Build Coastguard Worker     {
5011*5e7646d2SAndroid Build Coastguard Worker      /*
5012*5e7646d2SAndroid Build Coastguard Worker       * DEFINE name value
5013*5e7646d2SAndroid Build Coastguard Worker       */
5014*5e7646d2SAndroid Build Coastguard Worker 
5015*5e7646d2SAndroid Build Coastguard Worker       if (_ippFileReadToken(f, name, sizeof(name)) && _ippFileReadToken(f, temp, sizeof(temp)))
5016*5e7646d2SAndroid Build Coastguard Worker       {
5017*5e7646d2SAndroid Build Coastguard Worker         _ippVarsSet(vars, "date-current", iso_date(ippTimeToDate(time(NULL))));
5018*5e7646d2SAndroid Build Coastguard Worker         _ippVarsExpand(vars, value, temp, sizeof(value));
5019*5e7646d2SAndroid Build Coastguard Worker 	_ippVarsSet(vars, name, value);
5020*5e7646d2SAndroid Build Coastguard Worker       }
5021*5e7646d2SAndroid Build Coastguard Worker       else
5022*5e7646d2SAndroid Build Coastguard Worker       {
5023*5e7646d2SAndroid Build Coastguard Worker         print_fatal_error(data, "Missing DEFINE name and/or value on line %d of \"%s\".", f->linenum, f->filename);
5024*5e7646d2SAndroid Build Coastguard Worker 	return (0);
5025*5e7646d2SAndroid Build Coastguard Worker       }
5026*5e7646d2SAndroid Build Coastguard Worker     }
5027*5e7646d2SAndroid Build Coastguard Worker     else if (!strcmp(token, "DEFINE-DEFAULT"))
5028*5e7646d2SAndroid Build Coastguard Worker     {
5029*5e7646d2SAndroid Build Coastguard Worker      /*
5030*5e7646d2SAndroid Build Coastguard Worker       * DEFINE-DEFAULT name value
5031*5e7646d2SAndroid Build Coastguard Worker       */
5032*5e7646d2SAndroid Build Coastguard Worker 
5033*5e7646d2SAndroid Build Coastguard Worker       if (_ippFileReadToken(f, name, sizeof(name)) && _ippFileReadToken(f, temp, sizeof(temp)))
5034*5e7646d2SAndroid Build Coastguard Worker       {
5035*5e7646d2SAndroid Build Coastguard Worker         if (!_ippVarsGet(vars, name))
5036*5e7646d2SAndroid Build Coastguard Worker         {
5037*5e7646d2SAndroid Build Coastguard Worker           _ippVarsSet(vars, "date-current", iso_date(ippTimeToDate(time(NULL))));
5038*5e7646d2SAndroid Build Coastguard Worker 	  _ippVarsExpand(vars, value, temp, sizeof(value));
5039*5e7646d2SAndroid Build Coastguard Worker 	  _ippVarsSet(vars, name, value);
5040*5e7646d2SAndroid Build Coastguard Worker 	}
5041*5e7646d2SAndroid Build Coastguard Worker       }
5042*5e7646d2SAndroid Build Coastguard Worker       else
5043*5e7646d2SAndroid Build Coastguard Worker       {
5044*5e7646d2SAndroid Build Coastguard Worker         print_fatal_error(data, "Missing DEFINE-DEFAULT name and/or value on line %d of \"%s\".", f->linenum, f->filename);
5045*5e7646d2SAndroid Build Coastguard Worker 	return (0);
5046*5e7646d2SAndroid Build Coastguard Worker       }
5047*5e7646d2SAndroid Build Coastguard Worker     }
5048*5e7646d2SAndroid Build Coastguard Worker     else if (!strcmp(token, "FILE-ID"))
5049*5e7646d2SAndroid Build Coastguard Worker     {
5050*5e7646d2SAndroid Build Coastguard Worker      /*
5051*5e7646d2SAndroid Build Coastguard Worker       * FILE-ID "string"
5052*5e7646d2SAndroid Build Coastguard Worker       */
5053*5e7646d2SAndroid Build Coastguard Worker 
5054*5e7646d2SAndroid Build Coastguard Worker       if (_ippFileReadToken(f, temp, sizeof(temp)))
5055*5e7646d2SAndroid Build Coastguard Worker       {
5056*5e7646d2SAndroid Build Coastguard Worker         _ippVarsSet(vars, "date-current", iso_date(ippTimeToDate(time(NULL))));
5057*5e7646d2SAndroid Build Coastguard Worker         _ippVarsExpand(vars, data->file_id, temp, sizeof(data->file_id));
5058*5e7646d2SAndroid Build Coastguard Worker       }
5059*5e7646d2SAndroid Build Coastguard Worker       else
5060*5e7646d2SAndroid Build Coastguard Worker       {
5061*5e7646d2SAndroid Build Coastguard Worker         print_fatal_error(data, "Missing FILE-ID value on line %d of \"%s\".", f->linenum, f->filename);
5062*5e7646d2SAndroid Build Coastguard Worker         return (0);
5063*5e7646d2SAndroid Build Coastguard Worker       }
5064*5e7646d2SAndroid Build Coastguard Worker     }
5065*5e7646d2SAndroid Build Coastguard Worker     else if (!strcmp(token, "IGNORE-ERRORS"))
5066*5e7646d2SAndroid Build Coastguard Worker     {
5067*5e7646d2SAndroid Build Coastguard Worker      /*
5068*5e7646d2SAndroid Build Coastguard Worker       * IGNORE-ERRORS yes
5069*5e7646d2SAndroid Build Coastguard Worker       * IGNORE-ERRORS no
5070*5e7646d2SAndroid Build Coastguard Worker       */
5071*5e7646d2SAndroid Build Coastguard Worker 
5072*5e7646d2SAndroid Build Coastguard Worker       if (_ippFileReadToken(f, temp, sizeof(temp)) && (!_cups_strcasecmp(temp, "yes") || !_cups_strcasecmp(temp, "no")))
5073*5e7646d2SAndroid Build Coastguard Worker       {
5074*5e7646d2SAndroid Build Coastguard Worker         data->def_ignore_errors = !_cups_strcasecmp(temp, "yes");
5075*5e7646d2SAndroid Build Coastguard Worker       }
5076*5e7646d2SAndroid Build Coastguard Worker       else
5077*5e7646d2SAndroid Build Coastguard Worker       {
5078*5e7646d2SAndroid Build Coastguard Worker         print_fatal_error(data, "Missing IGNORE-ERRORS value on line %d of \"%s\".", f->linenum, f->filename);
5079*5e7646d2SAndroid Build Coastguard Worker         return (0);
5080*5e7646d2SAndroid Build Coastguard Worker       }
5081*5e7646d2SAndroid Build Coastguard Worker     }
5082*5e7646d2SAndroid Build Coastguard Worker     else if (!strcmp(token, "INCLUDE"))
5083*5e7646d2SAndroid Build Coastguard Worker     {
5084*5e7646d2SAndroid Build Coastguard Worker      /*
5085*5e7646d2SAndroid Build Coastguard Worker       * INCLUDE "filename"
5086*5e7646d2SAndroid Build Coastguard Worker       * INCLUDE <filename>
5087*5e7646d2SAndroid Build Coastguard Worker       */
5088*5e7646d2SAndroid Build Coastguard Worker 
5089*5e7646d2SAndroid Build Coastguard Worker       if (_ippFileReadToken(f, temp, sizeof(temp)))
5090*5e7646d2SAndroid Build Coastguard Worker       {
5091*5e7646d2SAndroid Build Coastguard Worker        /*
5092*5e7646d2SAndroid Build Coastguard Worker         * Map the filename to and then run the tests...
5093*5e7646d2SAndroid Build Coastguard Worker 	*/
5094*5e7646d2SAndroid Build Coastguard Worker 
5095*5e7646d2SAndroid Build Coastguard Worker         ipptool_test_t	inc_data;	/* Data for included file */
5096*5e7646d2SAndroid Build Coastguard Worker         char		filename[1024];	/* Mapped filename */
5097*5e7646d2SAndroid Build Coastguard Worker 
5098*5e7646d2SAndroid Build Coastguard Worker         memcpy(&inc_data, data, sizeof(inc_data));
5099*5e7646d2SAndroid Build Coastguard Worker         inc_data.http        = NULL;
5100*5e7646d2SAndroid Build Coastguard Worker 	inc_data.pass        = 1;
5101*5e7646d2SAndroid Build Coastguard Worker 	inc_data.prev_pass   = 1;
5102*5e7646d2SAndroid Build Coastguard Worker 	inc_data.show_header = 1;
5103*5e7646d2SAndroid Build Coastguard Worker 
5104*5e7646d2SAndroid Build Coastguard Worker         if (!do_tests(get_filename(f->filename, filename, temp, sizeof(filename)), &inc_data) && data->stop_after_include_error)
5105*5e7646d2SAndroid Build Coastguard Worker         {
5106*5e7646d2SAndroid Build Coastguard Worker           data->pass = data->prev_pass = 0;
5107*5e7646d2SAndroid Build Coastguard Worker           return (0);
5108*5e7646d2SAndroid Build Coastguard Worker 	}
5109*5e7646d2SAndroid Build Coastguard Worker       }
5110*5e7646d2SAndroid Build Coastguard Worker       else
5111*5e7646d2SAndroid Build Coastguard Worker       {
5112*5e7646d2SAndroid Build Coastguard Worker         print_fatal_error(data, "Missing INCLUDE filename on line %d of \"%s\".", f->linenum, f->filename);
5113*5e7646d2SAndroid Build Coastguard Worker         return (0);
5114*5e7646d2SAndroid Build Coastguard Worker       }
5115*5e7646d2SAndroid Build Coastguard Worker 
5116*5e7646d2SAndroid Build Coastguard Worker       data->show_header = 1;
5117*5e7646d2SAndroid Build Coastguard Worker     }
5118*5e7646d2SAndroid Build Coastguard Worker     else if (!strcmp(token, "INCLUDE-IF-DEFINED"))
5119*5e7646d2SAndroid Build Coastguard Worker     {
5120*5e7646d2SAndroid Build Coastguard Worker      /*
5121*5e7646d2SAndroid Build Coastguard Worker       * INCLUDE-IF-DEFINED name "filename"
5122*5e7646d2SAndroid Build Coastguard Worker       * INCLUDE-IF-DEFINED name <filename>
5123*5e7646d2SAndroid Build Coastguard Worker       */
5124*5e7646d2SAndroid Build Coastguard Worker 
5125*5e7646d2SAndroid Build Coastguard Worker       if (_ippFileReadToken(f, name, sizeof(name)) && _ippFileReadToken(f, temp, sizeof(temp)))
5126*5e7646d2SAndroid Build Coastguard Worker       {
5127*5e7646d2SAndroid Build Coastguard Worker        /*
5128*5e7646d2SAndroid Build Coastguard Worker         * Map the filename to and then run the tests...
5129*5e7646d2SAndroid Build Coastguard Worker 	*/
5130*5e7646d2SAndroid Build Coastguard Worker 
5131*5e7646d2SAndroid Build Coastguard Worker         ipptool_test_t inc_data;	/* Data for included file */
5132*5e7646d2SAndroid Build Coastguard Worker         char		filename[1024];	/* Mapped filename */
5133*5e7646d2SAndroid Build Coastguard Worker 
5134*5e7646d2SAndroid Build Coastguard Worker         memcpy(&inc_data, data, sizeof(inc_data));
5135*5e7646d2SAndroid Build Coastguard Worker         inc_data.http        = NULL;
5136*5e7646d2SAndroid Build Coastguard Worker 	inc_data.pass        = 1;
5137*5e7646d2SAndroid Build Coastguard Worker 	inc_data.prev_pass   = 1;
5138*5e7646d2SAndroid Build Coastguard Worker 	inc_data.show_header = 1;
5139*5e7646d2SAndroid Build Coastguard Worker 
5140*5e7646d2SAndroid Build Coastguard Worker         if (!do_tests(get_filename(f->filename, filename, temp, sizeof(filename)), &inc_data) && data->stop_after_include_error)
5141*5e7646d2SAndroid Build Coastguard Worker         {
5142*5e7646d2SAndroid Build Coastguard Worker           data->pass = data->prev_pass = 0;
5143*5e7646d2SAndroid Build Coastguard Worker           return (0);
5144*5e7646d2SAndroid Build Coastguard Worker 	}
5145*5e7646d2SAndroid Build Coastguard Worker       }
5146*5e7646d2SAndroid Build Coastguard Worker       else
5147*5e7646d2SAndroid Build Coastguard Worker       {
5148*5e7646d2SAndroid Build Coastguard Worker         print_fatal_error(data, "Missing INCLUDE-IF-DEFINED name or filename on line %d of \"%s\".", f->linenum, f->filename);
5149*5e7646d2SAndroid Build Coastguard Worker         return (0);
5150*5e7646d2SAndroid Build Coastguard Worker       }
5151*5e7646d2SAndroid Build Coastguard Worker 
5152*5e7646d2SAndroid Build Coastguard Worker       data->show_header = 1;
5153*5e7646d2SAndroid Build Coastguard Worker     }
5154*5e7646d2SAndroid Build Coastguard Worker     else if (!strcmp(token, "INCLUDE-IF-NOT-DEFINED"))
5155*5e7646d2SAndroid Build Coastguard Worker     {
5156*5e7646d2SAndroid Build Coastguard Worker      /*
5157*5e7646d2SAndroid Build Coastguard Worker       * INCLUDE-IF-NOT-DEFINED name "filename"
5158*5e7646d2SAndroid Build Coastguard Worker       * INCLUDE-IF-NOT-DEFINED name <filename>
5159*5e7646d2SAndroid Build Coastguard Worker       */
5160*5e7646d2SAndroid Build Coastguard Worker 
5161*5e7646d2SAndroid Build Coastguard Worker       if (_ippFileReadToken(f, name, sizeof(name)) && _ippFileReadToken(f, temp, sizeof(temp)))
5162*5e7646d2SAndroid Build Coastguard Worker       {
5163*5e7646d2SAndroid Build Coastguard Worker        /*
5164*5e7646d2SAndroid Build Coastguard Worker         * Map the filename to and then run the tests...
5165*5e7646d2SAndroid Build Coastguard Worker 	*/
5166*5e7646d2SAndroid Build Coastguard Worker 
5167*5e7646d2SAndroid Build Coastguard Worker         ipptool_test_t inc_data;	/* Data for included file */
5168*5e7646d2SAndroid Build Coastguard Worker         char		filename[1024];	/* Mapped filename */
5169*5e7646d2SAndroid Build Coastguard Worker 
5170*5e7646d2SAndroid Build Coastguard Worker         memcpy(&inc_data, data, sizeof(inc_data));
5171*5e7646d2SAndroid Build Coastguard Worker         inc_data.http        = NULL;
5172*5e7646d2SAndroid Build Coastguard Worker 	inc_data.pass        = 1;
5173*5e7646d2SAndroid Build Coastguard Worker 	inc_data.prev_pass   = 1;
5174*5e7646d2SAndroid Build Coastguard Worker 	inc_data.show_header = 1;
5175*5e7646d2SAndroid Build Coastguard Worker 
5176*5e7646d2SAndroid Build Coastguard Worker         if (!do_tests(get_filename(f->filename, filename, temp, sizeof(filename)), &inc_data) && data->stop_after_include_error)
5177*5e7646d2SAndroid Build Coastguard Worker         {
5178*5e7646d2SAndroid Build Coastguard Worker           data->pass = data->prev_pass = 0;
5179*5e7646d2SAndroid Build Coastguard Worker           return (0);
5180*5e7646d2SAndroid Build Coastguard Worker 	}
5181*5e7646d2SAndroid Build Coastguard Worker       }
5182*5e7646d2SAndroid Build Coastguard Worker       else
5183*5e7646d2SAndroid Build Coastguard Worker       {
5184*5e7646d2SAndroid Build Coastguard Worker         print_fatal_error(data, "Missing INCLUDE-IF-NOT-DEFINED name or filename on line %d of \"%s\".", f->linenum, f->filename);
5185*5e7646d2SAndroid Build Coastguard Worker         return (0);
5186*5e7646d2SAndroid Build Coastguard Worker       }
5187*5e7646d2SAndroid Build Coastguard Worker 
5188*5e7646d2SAndroid Build Coastguard Worker       data->show_header = 1;
5189*5e7646d2SAndroid Build Coastguard Worker     }
5190*5e7646d2SAndroid Build Coastguard Worker     else if (!strcmp(token, "SKIP-IF-DEFINED"))
5191*5e7646d2SAndroid Build Coastguard Worker     {
5192*5e7646d2SAndroid Build Coastguard Worker      /*
5193*5e7646d2SAndroid Build Coastguard Worker       * SKIP-IF-DEFINED variable
5194*5e7646d2SAndroid Build Coastguard Worker       */
5195*5e7646d2SAndroid Build Coastguard Worker 
5196*5e7646d2SAndroid Build Coastguard Worker       if (_ippFileReadToken(f, name, sizeof(name)))
5197*5e7646d2SAndroid Build Coastguard Worker       {
5198*5e7646d2SAndroid Build Coastguard Worker         if (_ippVarsGet(vars, name))
5199*5e7646d2SAndroid Build Coastguard Worker           data->skip_test = 1;
5200*5e7646d2SAndroid Build Coastguard Worker       }
5201*5e7646d2SAndroid Build Coastguard Worker       else
5202*5e7646d2SAndroid Build Coastguard Worker       {
5203*5e7646d2SAndroid Build Coastguard Worker         print_fatal_error(data, "Missing SKIP-IF-DEFINED variable on line %d of \"%s\".", f->linenum, f->filename);
5204*5e7646d2SAndroid Build Coastguard Worker         return (0);
5205*5e7646d2SAndroid Build Coastguard Worker       }
5206*5e7646d2SAndroid Build Coastguard Worker     }
5207*5e7646d2SAndroid Build Coastguard Worker     else if (!strcmp(token, "SKIP-IF-NOT-DEFINED"))
5208*5e7646d2SAndroid Build Coastguard Worker     {
5209*5e7646d2SAndroid Build Coastguard Worker      /*
5210*5e7646d2SAndroid Build Coastguard Worker       * SKIP-IF-NOT-DEFINED variable
5211*5e7646d2SAndroid Build Coastguard Worker       */
5212*5e7646d2SAndroid Build Coastguard Worker 
5213*5e7646d2SAndroid Build Coastguard Worker       if (_ippFileReadToken(f, name, sizeof(name)))
5214*5e7646d2SAndroid Build Coastguard Worker       {
5215*5e7646d2SAndroid Build Coastguard Worker         if (!_ippVarsGet(vars, name))
5216*5e7646d2SAndroid Build Coastguard Worker           data->skip_test = 1;
5217*5e7646d2SAndroid Build Coastguard Worker       }
5218*5e7646d2SAndroid Build Coastguard Worker       else
5219*5e7646d2SAndroid Build Coastguard Worker       {
5220*5e7646d2SAndroid Build Coastguard Worker         print_fatal_error(data, "Missing SKIP-IF-NOT-DEFINED variable on line %d of \"%s\".", f->linenum, f->filename);
5221*5e7646d2SAndroid Build Coastguard Worker         return (0);
5222*5e7646d2SAndroid Build Coastguard Worker       }
5223*5e7646d2SAndroid Build Coastguard Worker     }
5224*5e7646d2SAndroid Build Coastguard Worker     else if (!strcmp(token, "STOP-AFTER-INCLUDE-ERROR"))
5225*5e7646d2SAndroid Build Coastguard Worker     {
5226*5e7646d2SAndroid Build Coastguard Worker      /*
5227*5e7646d2SAndroid Build Coastguard Worker       * STOP-AFTER-INCLUDE-ERROR yes
5228*5e7646d2SAndroid Build Coastguard Worker       * STOP-AFTER-INCLUDE-ERROR no
5229*5e7646d2SAndroid Build Coastguard Worker       */
5230*5e7646d2SAndroid Build Coastguard Worker 
5231*5e7646d2SAndroid Build Coastguard Worker       if (_ippFileReadToken(f, temp, sizeof(temp)) && (!_cups_strcasecmp(temp, "yes") || !_cups_strcasecmp(temp, "no")))
5232*5e7646d2SAndroid Build Coastguard Worker       {
5233*5e7646d2SAndroid Build Coastguard Worker         data->stop_after_include_error = !_cups_strcasecmp(temp, "yes");
5234*5e7646d2SAndroid Build Coastguard Worker       }
5235*5e7646d2SAndroid Build Coastguard Worker       else
5236*5e7646d2SAndroid Build Coastguard Worker       {
5237*5e7646d2SAndroid Build Coastguard Worker         print_fatal_error(data, "Missing STOP-AFTER-INCLUDE-ERROR value on line %d of \"%s\".", f->linenum, f->filename);
5238*5e7646d2SAndroid Build Coastguard Worker         return (0);
5239*5e7646d2SAndroid Build Coastguard Worker       }
5240*5e7646d2SAndroid Build Coastguard Worker     }
5241*5e7646d2SAndroid Build Coastguard Worker     else if (!strcmp(token, "TRANSFER"))
5242*5e7646d2SAndroid Build Coastguard Worker     {
5243*5e7646d2SAndroid Build Coastguard Worker      /*
5244*5e7646d2SAndroid Build Coastguard Worker       * TRANSFER auto
5245*5e7646d2SAndroid Build Coastguard Worker       * TRANSFER chunked
5246*5e7646d2SAndroid Build Coastguard Worker       * TRANSFER length
5247*5e7646d2SAndroid Build Coastguard Worker       */
5248*5e7646d2SAndroid Build Coastguard Worker 
5249*5e7646d2SAndroid Build Coastguard Worker       if (_ippFileReadToken(f, temp, sizeof(temp)))
5250*5e7646d2SAndroid Build Coastguard Worker       {
5251*5e7646d2SAndroid Build Coastguard Worker         if (!strcmp(temp, "auto"))
5252*5e7646d2SAndroid Build Coastguard Worker 	  data->def_transfer = IPPTOOL_TRANSFER_AUTO;
5253*5e7646d2SAndroid Build Coastguard Worker 	else if (!strcmp(temp, "chunked"))
5254*5e7646d2SAndroid Build Coastguard Worker 	  data->def_transfer = IPPTOOL_TRANSFER_CHUNKED;
5255*5e7646d2SAndroid Build Coastguard Worker 	else if (!strcmp(temp, "length"))
5256*5e7646d2SAndroid Build Coastguard Worker 	  data->def_transfer = IPPTOOL_TRANSFER_LENGTH;
5257*5e7646d2SAndroid Build Coastguard Worker 	else
5258*5e7646d2SAndroid Build Coastguard Worker 	{
5259*5e7646d2SAndroid Build Coastguard Worker 	  print_fatal_error(data, "Bad TRANSFER value \"%s\" on line %d of \"%s\".", temp, f->linenum, f->filename);
5260*5e7646d2SAndroid Build Coastguard Worker 	  return (0);
5261*5e7646d2SAndroid Build Coastguard Worker 	}
5262*5e7646d2SAndroid Build Coastguard Worker       }
5263*5e7646d2SAndroid Build Coastguard Worker       else
5264*5e7646d2SAndroid Build Coastguard Worker       {
5265*5e7646d2SAndroid Build Coastguard Worker         print_fatal_error(data, "Missing TRANSFER value on line %d of \"%s\".", f->linenum, f->filename);
5266*5e7646d2SAndroid Build Coastguard Worker 	return (0);
5267*5e7646d2SAndroid Build Coastguard Worker       }
5268*5e7646d2SAndroid Build Coastguard Worker     }
5269*5e7646d2SAndroid Build Coastguard Worker     else if (!strcmp(token, "VERSION"))
5270*5e7646d2SAndroid Build Coastguard Worker     {
5271*5e7646d2SAndroid Build Coastguard Worker       if (_ippFileReadToken(f, temp, sizeof(temp)))
5272*5e7646d2SAndroid Build Coastguard Worker       {
5273*5e7646d2SAndroid Build Coastguard Worker         if (!strcmp(temp, "1.0"))
5274*5e7646d2SAndroid Build Coastguard Worker 	  data->def_version = 10;
5275*5e7646d2SAndroid Build Coastguard Worker 	else if (!strcmp(temp, "1.1"))
5276*5e7646d2SAndroid Build Coastguard Worker 	  data->def_version = 11;
5277*5e7646d2SAndroid Build Coastguard Worker 	else if (!strcmp(temp, "2.0"))
5278*5e7646d2SAndroid Build Coastguard Worker 	  data->def_version = 20;
5279*5e7646d2SAndroid Build Coastguard Worker 	else if (!strcmp(temp, "2.1"))
5280*5e7646d2SAndroid Build Coastguard Worker 	  data->def_version = 21;
5281*5e7646d2SAndroid Build Coastguard Worker 	else if (!strcmp(temp, "2.2"))
5282*5e7646d2SAndroid Build Coastguard Worker 	  data->def_version = 22;
5283*5e7646d2SAndroid Build Coastguard Worker 	else
5284*5e7646d2SAndroid Build Coastguard Worker 	{
5285*5e7646d2SAndroid Build Coastguard Worker 	  print_fatal_error(data, "Bad VERSION \"%s\" on line %d of \"%s\".", temp, f->linenum, f->filename);
5286*5e7646d2SAndroid Build Coastguard Worker 	  return (0);
5287*5e7646d2SAndroid Build Coastguard Worker 	}
5288*5e7646d2SAndroid Build Coastguard Worker       }
5289*5e7646d2SAndroid Build Coastguard Worker       else
5290*5e7646d2SAndroid Build Coastguard Worker       {
5291*5e7646d2SAndroid Build Coastguard Worker         print_fatal_error(data, "Missing VERSION number on line %d of \"%s\".", f->linenum, f->filename);
5292*5e7646d2SAndroid Build Coastguard Worker         return (0);
5293*5e7646d2SAndroid Build Coastguard Worker       }
5294*5e7646d2SAndroid Build Coastguard Worker     }
5295*5e7646d2SAndroid Build Coastguard Worker     else
5296*5e7646d2SAndroid Build Coastguard Worker     {
5297*5e7646d2SAndroid Build Coastguard Worker       print_fatal_error(data, "Unexpected token %s seen on line %d of \"%s\".", token, f->linenum, f->filename);
5298*5e7646d2SAndroid Build Coastguard Worker       return (0);
5299*5e7646d2SAndroid Build Coastguard Worker     }
5300*5e7646d2SAndroid Build Coastguard Worker   }
5301*5e7646d2SAndroid Build Coastguard Worker 
5302*5e7646d2SAndroid Build Coastguard Worker   return (1);
5303*5e7646d2SAndroid Build Coastguard Worker }
5304*5e7646d2SAndroid Build Coastguard Worker 
5305*5e7646d2SAndroid Build Coastguard Worker 
5306*5e7646d2SAndroid Build Coastguard Worker /*
5307*5e7646d2SAndroid Build Coastguard Worker  * 'usage()' - Show program usage.
5308*5e7646d2SAndroid Build Coastguard Worker  */
5309*5e7646d2SAndroid Build Coastguard Worker 
5310*5e7646d2SAndroid Build Coastguard Worker static void
usage(void)5311*5e7646d2SAndroid Build Coastguard Worker usage(void)
5312*5e7646d2SAndroid Build Coastguard Worker {
5313*5e7646d2SAndroid Build Coastguard Worker   _cupsLangPuts(stderr, _("Usage: ipptool [options] URI filename [ ... filenameN ]"));
5314*5e7646d2SAndroid Build Coastguard Worker   _cupsLangPuts(stderr, _("Options:"));
5315*5e7646d2SAndroid Build Coastguard Worker   _cupsLangPuts(stderr, _("--ippserver filename    Produce ippserver attribute file"));
5316*5e7646d2SAndroid Build Coastguard Worker   _cupsLangPuts(stderr, _("--stop-after-include-error\n"
5317*5e7646d2SAndroid Build Coastguard Worker                           "                        Stop tests after a failed INCLUDE"));
5318*5e7646d2SAndroid Build Coastguard Worker   _cupsLangPuts(stderr, _("--version               Show version"));
5319*5e7646d2SAndroid Build Coastguard Worker   _cupsLangPuts(stderr, _("-4                      Connect using IPv4"));
5320*5e7646d2SAndroid Build Coastguard Worker   _cupsLangPuts(stderr, _("-6                      Connect using IPv6"));
5321*5e7646d2SAndroid Build Coastguard Worker   _cupsLangPuts(stderr, _("-C                      Send requests using chunking (default)"));
5322*5e7646d2SAndroid Build Coastguard Worker   _cupsLangPuts(stderr, _("-E                      Test with encryption using HTTP Upgrade to TLS"));
5323*5e7646d2SAndroid Build Coastguard Worker   _cupsLangPuts(stderr, _("-I                      Ignore errors"));
5324*5e7646d2SAndroid Build Coastguard Worker   _cupsLangPuts(stderr, _("-L                      Send requests using content-length"));
5325*5e7646d2SAndroid Build Coastguard Worker   _cupsLangPuts(stderr, _("-P filename.plist       Produce XML plist to a file and test report to standard output"));
5326*5e7646d2SAndroid Build Coastguard Worker   _cupsLangPuts(stderr, _("-R                      Repeat tests on server-error-busy"));
5327*5e7646d2SAndroid Build Coastguard Worker   _cupsLangPuts(stderr, _("-S                      Test with encryption using HTTPS"));
5328*5e7646d2SAndroid Build Coastguard Worker   _cupsLangPuts(stderr, _("-T seconds              Set the receive/send timeout in seconds"));
5329*5e7646d2SAndroid Build Coastguard Worker   _cupsLangPuts(stderr, _("-V version              Set default IPP version"));
5330*5e7646d2SAndroid Build Coastguard Worker   _cupsLangPuts(stderr, _("-X                      Produce XML plist instead of plain text"));
5331*5e7646d2SAndroid Build Coastguard Worker   _cupsLangPuts(stderr, _("-c                      Produce CSV output"));
5332*5e7646d2SAndroid Build Coastguard Worker   _cupsLangPuts(stderr, _("-d name=value           Set named variable to value"));
5333*5e7646d2SAndroid Build Coastguard Worker   _cupsLangPuts(stderr, _("-f filename             Set default request filename"));
5334*5e7646d2SAndroid Build Coastguard Worker   _cupsLangPuts(stderr, _("-h                      Validate HTTP response headers"));
5335*5e7646d2SAndroid Build Coastguard Worker   _cupsLangPuts(stderr, _("-i seconds              Repeat the last file with the given time interval"));
5336*5e7646d2SAndroid Build Coastguard Worker   _cupsLangPuts(stderr, _("-l                      Produce plain text output"));
5337*5e7646d2SAndroid Build Coastguard Worker   _cupsLangPuts(stderr, _("-n count                Repeat the last file the given number of times"));
5338*5e7646d2SAndroid Build Coastguard Worker   _cupsLangPuts(stderr, _("-q                      Run silently"));
5339*5e7646d2SAndroid Build Coastguard Worker   _cupsLangPuts(stderr, _("-t                      Produce a test report"));
5340*5e7646d2SAndroid Build Coastguard Worker   _cupsLangPuts(stderr, _("-v                      Be verbose"));
5341*5e7646d2SAndroid Build Coastguard Worker 
5342*5e7646d2SAndroid Build Coastguard Worker   exit(1);
5343*5e7646d2SAndroid Build Coastguard Worker }
5344*5e7646d2SAndroid Build Coastguard Worker 
5345*5e7646d2SAndroid Build Coastguard Worker 
5346*5e7646d2SAndroid Build Coastguard Worker /*
5347*5e7646d2SAndroid Build Coastguard Worker  * 'with_distinct_values()' - Verify that an attribute contains unique values.
5348*5e7646d2SAndroid Build Coastguard Worker  */
5349*5e7646d2SAndroid Build Coastguard Worker 
5350*5e7646d2SAndroid Build Coastguard Worker static int				// O - 1 if distinct, 0 if duplicate
with_distinct_values(cups_array_t * errors,ipp_attribute_t * attr)5351*5e7646d2SAndroid Build Coastguard Worker with_distinct_values(
5352*5e7646d2SAndroid Build Coastguard Worker     cups_array_t    *errors,		// I - Array of errors
5353*5e7646d2SAndroid Build Coastguard Worker     ipp_attribute_t *attr)		// I - Attribute to test
5354*5e7646d2SAndroid Build Coastguard Worker {
5355*5e7646d2SAndroid Build Coastguard Worker   int		i,			// Looping var
5356*5e7646d2SAndroid Build Coastguard Worker 		count;			// Number of values
5357*5e7646d2SAndroid Build Coastguard Worker   ipp_tag_t	value_tag;		// Value syntax
5358*5e7646d2SAndroid Build Coastguard Worker   const char	*value;			// Current value
5359*5e7646d2SAndroid Build Coastguard Worker   char		buffer[8192];		// Temporary buffer
5360*5e7646d2SAndroid Build Coastguard Worker   cups_array_t	*values;		// Array of values as strings
5361*5e7646d2SAndroid Build Coastguard Worker 
5362*5e7646d2SAndroid Build Coastguard Worker 
5363*5e7646d2SAndroid Build Coastguard Worker   // If there is only 1 value, it must be distinct
5364*5e7646d2SAndroid Build Coastguard Worker   if ((count = ippGetCount(attr)) == 1)
5365*5e7646d2SAndroid Build Coastguard Worker     return (1);
5366*5e7646d2SAndroid Build Coastguard Worker 
5367*5e7646d2SAndroid Build Coastguard Worker   // Only check integers, enums, rangeOfInteger, resolution, and nul-terminated
5368*5e7646d2SAndroid Build Coastguard Worker   // strings...
5369*5e7646d2SAndroid Build Coastguard Worker   switch (value_tag = ippGetValueTag(attr))
5370*5e7646d2SAndroid Build Coastguard Worker   {
5371*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_INTEGER :
5372*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_ENUM :
5373*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_RANGE :
5374*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_RESOLUTION :
5375*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_KEYWORD :
5376*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_URISCHEME :
5377*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_CHARSET :
5378*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_LANGUAGE :
5379*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_MIMETYPE :
5380*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_BEGIN_COLLECTION :
5381*5e7646d2SAndroid Build Coastguard Worker         break;
5382*5e7646d2SAndroid Build Coastguard Worker 
5383*5e7646d2SAndroid Build Coastguard Worker     default :
5384*5e7646d2SAndroid Build Coastguard Worker         add_stringf(errors, "WITH-DISTINCT-VALUES %s not supported for 1setOf %s", ippGetName(attr), ippTagString(value_tag));
5385*5e7646d2SAndroid Build Coastguard Worker         return (0);
5386*5e7646d2SAndroid Build Coastguard Worker   }
5387*5e7646d2SAndroid Build Coastguard Worker 
5388*5e7646d2SAndroid Build Coastguard Worker   // Collect values and determine they are all unique...
5389*5e7646d2SAndroid Build Coastguard Worker   values = cupsArrayNew3((cups_array_func_t)strcmp, NULL, NULL, 0, (cups_acopy_func_t)strdup, (cups_afree_func_t)free);
5390*5e7646d2SAndroid Build Coastguard Worker 
5391*5e7646d2SAndroid Build Coastguard Worker   for (i = 0; i < count; i ++)
5392*5e7646d2SAndroid Build Coastguard Worker   {
5393*5e7646d2SAndroid Build Coastguard Worker     switch (value_tag)
5394*5e7646d2SAndroid Build Coastguard Worker     {
5395*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_INTEGER :
5396*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_ENUM :
5397*5e7646d2SAndroid Build Coastguard Worker           snprintf(buffer, sizeof(buffer), "%d", ippGetInteger(attr, i));
5398*5e7646d2SAndroid Build Coastguard Worker           value = buffer;
5399*5e7646d2SAndroid Build Coastguard Worker           break;
5400*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_RANGE :
5401*5e7646d2SAndroid Build Coastguard Worker           {
5402*5e7646d2SAndroid Build Coastguard Worker             int upper, lower = ippGetRange(attr, i, &upper);
5403*5e7646d2SAndroid Build Coastguard Worker 					// Range values
5404*5e7646d2SAndroid Build Coastguard Worker 
5405*5e7646d2SAndroid Build Coastguard Worker             snprintf(buffer, sizeof(buffer), "%d-%d", lower, upper);
5406*5e7646d2SAndroid Build Coastguard Worker             value = buffer;
5407*5e7646d2SAndroid Build Coastguard Worker 	  }
5408*5e7646d2SAndroid Build Coastguard Worker           break;
5409*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_RESOLUTION :
5410*5e7646d2SAndroid Build Coastguard Worker           {
5411*5e7646d2SAndroid Build Coastguard Worker             ipp_res_t units;		// Resolution units
5412*5e7646d2SAndroid Build Coastguard Worker             int yres, xres = ippGetResolution(attr, i, &yres, &units);
5413*5e7646d2SAndroid Build Coastguard Worker 					// Resolution values
5414*5e7646d2SAndroid Build Coastguard Worker 
5415*5e7646d2SAndroid Build Coastguard Worker             if (xres == yres)
5416*5e7646d2SAndroid Build Coastguard Worker               snprintf(buffer, sizeof(buffer), "%d%s", xres, units == IPP_RES_PER_INCH ? "dpi" : "dpcm");
5417*5e7646d2SAndroid Build Coastguard Worker 	    else
5418*5e7646d2SAndroid Build Coastguard Worker               snprintf(buffer, sizeof(buffer), "%dx%d%s", xres, yres, units == IPP_RES_PER_INCH ? "dpi" : "dpcm");
5419*5e7646d2SAndroid Build Coastguard Worker             value = buffer;
5420*5e7646d2SAndroid Build Coastguard Worker 	  }
5421*5e7646d2SAndroid Build Coastguard Worker           break;
5422*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_KEYWORD :
5423*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_URISCHEME :
5424*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_CHARSET :
5425*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_LANGUAGE :
5426*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_MIMETYPE :
5427*5e7646d2SAndroid Build Coastguard Worker           value = ippGetString(attr, i, NULL);
5428*5e7646d2SAndroid Build Coastguard Worker           break;
5429*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_BEGIN_COLLECTION :
5430*5e7646d2SAndroid Build Coastguard Worker           {
5431*5e7646d2SAndroid Build Coastguard Worker             ipp_t	*col = ippGetCollection(attr, i);
5432*5e7646d2SAndroid Build Coastguard Worker 					// Collection value
5433*5e7646d2SAndroid Build Coastguard Worker             ipp_attribute_t *member;	// Member attribute
5434*5e7646d2SAndroid Build Coastguard Worker             char	*bufptr,	// Pointer into buffer
5435*5e7646d2SAndroid Build Coastguard Worker 			*bufend,	// End of buffer
5436*5e7646d2SAndroid Build Coastguard Worker 			prefix;		// Prefix character
5437*5e7646d2SAndroid Build Coastguard Worker 
5438*5e7646d2SAndroid Build Coastguard Worker             for (prefix = '{', bufptr = buffer, bufend = buffer + sizeof(buffer) - 2, member = ippFirstAttribute(col); member && bufptr < bufend; member = ippNextAttribute(col))
5439*5e7646d2SAndroid Build Coastguard Worker             {
5440*5e7646d2SAndroid Build Coastguard Worker               *bufptr++ = prefix;
5441*5e7646d2SAndroid Build Coastguard Worker               prefix    = ' ';
5442*5e7646d2SAndroid Build Coastguard Worker 
5443*5e7646d2SAndroid Build Coastguard Worker               ippAttributeString(member, bufptr, (size_t)(bufend - bufptr));
5444*5e7646d2SAndroid Build Coastguard Worker               bufptr += strlen(bufptr);
5445*5e7646d2SAndroid Build Coastguard Worker             }
5446*5e7646d2SAndroid Build Coastguard Worker 
5447*5e7646d2SAndroid Build Coastguard Worker             *bufptr++ = '}';
5448*5e7646d2SAndroid Build Coastguard Worker             *bufptr   = '\0';
5449*5e7646d2SAndroid Build Coastguard Worker             value     = buffer;
5450*5e7646d2SAndroid Build Coastguard Worker           }
5451*5e7646d2SAndroid Build Coastguard Worker           break;
5452*5e7646d2SAndroid Build Coastguard Worker       default : // Should never happen
5453*5e7646d2SAndroid Build Coastguard Worker           value = "unsupported";
5454*5e7646d2SAndroid Build Coastguard Worker           break;
5455*5e7646d2SAndroid Build Coastguard Worker     }
5456*5e7646d2SAndroid Build Coastguard Worker 
5457*5e7646d2SAndroid Build Coastguard Worker     if (cupsArrayFind(values, (void *)value))
5458*5e7646d2SAndroid Build Coastguard Worker       add_stringf(errors, "DUPLICATE: %s=%s", ippGetName(attr), value);
5459*5e7646d2SAndroid Build Coastguard Worker     else
5460*5e7646d2SAndroid Build Coastguard Worker       cupsArrayAdd(values, (void *)value);
5461*5e7646d2SAndroid Build Coastguard Worker   }
5462*5e7646d2SAndroid Build Coastguard Worker 
5463*5e7646d2SAndroid Build Coastguard Worker   // Cleanup...
5464*5e7646d2SAndroid Build Coastguard Worker   i = cupsArrayCount(values) == count;
5465*5e7646d2SAndroid Build Coastguard Worker   cupsArrayDelete(values);
5466*5e7646d2SAndroid Build Coastguard Worker 
5467*5e7646d2SAndroid Build Coastguard Worker   return (i);
5468*5e7646d2SAndroid Build Coastguard Worker }
5469*5e7646d2SAndroid Build Coastguard Worker 
5470*5e7646d2SAndroid Build Coastguard Worker 
5471*5e7646d2SAndroid Build Coastguard Worker /*
5472*5e7646d2SAndroid Build Coastguard Worker  * 'with_flags_string()' - Return the "WITH-xxx" predicate that corresponds to
5473*5e7646d2SAndroid Build Coastguard Worker  *                         the flags.
5474*5e7646d2SAndroid Build Coastguard Worker  */
5475*5e7646d2SAndroid Build Coastguard Worker 
5476*5e7646d2SAndroid Build Coastguard Worker static const char *                     /* O - WITH-xxx string */
with_flags_string(int flags)5477*5e7646d2SAndroid Build Coastguard Worker with_flags_string(int flags)            /* I - WITH flags */
5478*5e7646d2SAndroid Build Coastguard Worker {
5479*5e7646d2SAndroid Build Coastguard Worker   if (flags & IPPTOOL_WITH_ALL)
5480*5e7646d2SAndroid Build Coastguard Worker   {
5481*5e7646d2SAndroid Build Coastguard Worker     if (flags & IPPTOOL_WITH_HOSTNAME)
5482*5e7646d2SAndroid Build Coastguard Worker       return ("WITH-ALL-HOSTNAMES");
5483*5e7646d2SAndroid Build Coastguard Worker     else if (flags & IPPTOOL_WITH_RESOURCE)
5484*5e7646d2SAndroid Build Coastguard Worker       return ("WITH-ALL-RESOURCES");
5485*5e7646d2SAndroid Build Coastguard Worker     else if (flags & IPPTOOL_WITH_SCHEME)
5486*5e7646d2SAndroid Build Coastguard Worker       return ("WITH-ALL-SCHEMES");
5487*5e7646d2SAndroid Build Coastguard Worker     else
5488*5e7646d2SAndroid Build Coastguard Worker       return ("WITH-ALL-VALUES");
5489*5e7646d2SAndroid Build Coastguard Worker   }
5490*5e7646d2SAndroid Build Coastguard Worker   else if (flags & IPPTOOL_WITH_HOSTNAME)
5491*5e7646d2SAndroid Build Coastguard Worker     return ("WITH-HOSTNAME");
5492*5e7646d2SAndroid Build Coastguard Worker   else if (flags & IPPTOOL_WITH_RESOURCE)
5493*5e7646d2SAndroid Build Coastguard Worker     return ("WITH-RESOURCE");
5494*5e7646d2SAndroid Build Coastguard Worker   else if (flags & IPPTOOL_WITH_SCHEME)
5495*5e7646d2SAndroid Build Coastguard Worker     return ("WITH-SCHEME");
5496*5e7646d2SAndroid Build Coastguard Worker   else
5497*5e7646d2SAndroid Build Coastguard Worker     return ("WITH-VALUE");
5498*5e7646d2SAndroid Build Coastguard Worker }
5499*5e7646d2SAndroid Build Coastguard Worker 
5500*5e7646d2SAndroid Build Coastguard Worker 
5501*5e7646d2SAndroid Build Coastguard Worker /*
5502*5e7646d2SAndroid Build Coastguard Worker  * 'with_value()' - Test a WITH-VALUE predicate.
5503*5e7646d2SAndroid Build Coastguard Worker  */
5504*5e7646d2SAndroid Build Coastguard Worker 
5505*5e7646d2SAndroid Build Coastguard Worker static int				/* O - 1 on match, 0 on non-match */
with_value(ipptool_test_t * data,cups_array_t * errors,char * value,int flags,ipp_attribute_t * attr,char * matchbuf,size_t matchlen)5506*5e7646d2SAndroid Build Coastguard Worker with_value(ipptool_test_t *data,	/* I - Test data */
5507*5e7646d2SAndroid Build Coastguard Worker            cups_array_t     *errors,	/* I - Errors array */
5508*5e7646d2SAndroid Build Coastguard Worker            char             *value,	/* I - Value string */
5509*5e7646d2SAndroid Build Coastguard Worker            int              flags,	/* I - Flags for match */
5510*5e7646d2SAndroid Build Coastguard Worker            ipp_attribute_t  *attr,	/* I - Attribute to compare */
5511*5e7646d2SAndroid Build Coastguard Worker 	   char             *matchbuf,	/* I - Buffer to hold matching value */
5512*5e7646d2SAndroid Build Coastguard Worker 	   size_t           matchlen)	/* I - Length of match buffer */
5513*5e7646d2SAndroid Build Coastguard Worker {
5514*5e7646d2SAndroid Build Coastguard Worker   int		i,			/* Looping var */
5515*5e7646d2SAndroid Build Coastguard Worker     		count,			/* Number of values */
5516*5e7646d2SAndroid Build Coastguard Worker 		match;			/* Match? */
5517*5e7646d2SAndroid Build Coastguard Worker   char		temp[1024],		/* Temporary value string */
5518*5e7646d2SAndroid Build Coastguard Worker 		*valptr;		/* Pointer into value */
5519*5e7646d2SAndroid Build Coastguard Worker   const char	*name;			/* Attribute name */
5520*5e7646d2SAndroid Build Coastguard Worker 
5521*5e7646d2SAndroid Build Coastguard Worker 
5522*5e7646d2SAndroid Build Coastguard Worker   *matchbuf = '\0';
5523*5e7646d2SAndroid Build Coastguard Worker   match     = (flags & IPPTOOL_WITH_ALL) ? 1 : 0;
5524*5e7646d2SAndroid Build Coastguard Worker 
5525*5e7646d2SAndroid Build Coastguard Worker  /*
5526*5e7646d2SAndroid Build Coastguard Worker   * NULL matches everything.
5527*5e7646d2SAndroid Build Coastguard Worker   */
5528*5e7646d2SAndroid Build Coastguard Worker 
5529*5e7646d2SAndroid Build Coastguard Worker   if (!value || !*value)
5530*5e7646d2SAndroid Build Coastguard Worker     return (1);
5531*5e7646d2SAndroid Build Coastguard Worker 
5532*5e7646d2SAndroid Build Coastguard Worker  /*
5533*5e7646d2SAndroid Build Coastguard Worker   * Compare the value string to the attribute value.
5534*5e7646d2SAndroid Build Coastguard Worker   */
5535*5e7646d2SAndroid Build Coastguard Worker 
5536*5e7646d2SAndroid Build Coastguard Worker   name  = ippGetName(attr);
5537*5e7646d2SAndroid Build Coastguard Worker   count = ippGetCount(attr);
5538*5e7646d2SAndroid Build Coastguard Worker 
5539*5e7646d2SAndroid Build Coastguard Worker   switch (ippGetValueTag(attr))
5540*5e7646d2SAndroid Build Coastguard Worker   {
5541*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_INTEGER :
5542*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_ENUM :
5543*5e7646d2SAndroid Build Coastguard Worker         for (i = 0; i < count; i ++)
5544*5e7646d2SAndroid Build Coastguard Worker         {
5545*5e7646d2SAndroid Build Coastguard Worker 	  char	op,			/* Comparison operator */
5546*5e7646d2SAndroid Build Coastguard Worker 	  	*nextptr;		/* Next pointer */
5547*5e7646d2SAndroid Build Coastguard Worker 	  int	intvalue,		/* Integer value */
5548*5e7646d2SAndroid Build Coastguard Worker 		attrvalue = ippGetInteger(attr, i),
5549*5e7646d2SAndroid Build Coastguard Worker 					/* Attribute value */
5550*5e7646d2SAndroid Build Coastguard Worker 	  	valmatch = 0;		/* Does the current value match? */
5551*5e7646d2SAndroid Build Coastguard Worker 
5552*5e7646d2SAndroid Build Coastguard Worker           valptr = value;
5553*5e7646d2SAndroid Build Coastguard Worker 
5554*5e7646d2SAndroid Build Coastguard Worker 	  while (isspace(*valptr & 255) || isdigit(*valptr & 255) ||
5555*5e7646d2SAndroid Build Coastguard Worker 		 *valptr == '-' || *valptr == ',' || *valptr == '<' ||
5556*5e7646d2SAndroid Build Coastguard Worker 		 *valptr == '=' || *valptr == '>')
5557*5e7646d2SAndroid Build Coastguard Worker 	  {
5558*5e7646d2SAndroid Build Coastguard Worker 	    op = '=';
5559*5e7646d2SAndroid Build Coastguard Worker 	    while (*valptr && !isdigit(*valptr & 255) && *valptr != '-')
5560*5e7646d2SAndroid Build Coastguard Worker 	    {
5561*5e7646d2SAndroid Build Coastguard Worker 	      if (*valptr == '<' || *valptr == '>' || *valptr == '=')
5562*5e7646d2SAndroid Build Coastguard Worker 		op = *valptr;
5563*5e7646d2SAndroid Build Coastguard Worker 	      valptr ++;
5564*5e7646d2SAndroid Build Coastguard Worker 	    }
5565*5e7646d2SAndroid Build Coastguard Worker 
5566*5e7646d2SAndroid Build Coastguard Worker             if (!*valptr)
5567*5e7646d2SAndroid Build Coastguard Worker 	      break;
5568*5e7646d2SAndroid Build Coastguard Worker 
5569*5e7646d2SAndroid Build Coastguard Worker 	    intvalue = (int)strtol(valptr, &nextptr, 0);
5570*5e7646d2SAndroid Build Coastguard Worker 	    if (nextptr == valptr)
5571*5e7646d2SAndroid Build Coastguard Worker 	      break;
5572*5e7646d2SAndroid Build Coastguard Worker 	    valptr = nextptr;
5573*5e7646d2SAndroid Build Coastguard Worker 
5574*5e7646d2SAndroid Build Coastguard Worker             if ((op == '=' && attrvalue == intvalue) ||
5575*5e7646d2SAndroid Build Coastguard Worker                 (op == '<' && attrvalue < intvalue) ||
5576*5e7646d2SAndroid Build Coastguard Worker                 (op == '>' && attrvalue > intvalue))
5577*5e7646d2SAndroid Build Coastguard Worker 	    {
5578*5e7646d2SAndroid Build Coastguard Worker 	      if (!matchbuf[0])
5579*5e7646d2SAndroid Build Coastguard Worker 		snprintf(matchbuf, matchlen, "%d", attrvalue);
5580*5e7646d2SAndroid Build Coastguard Worker 
5581*5e7646d2SAndroid Build Coastguard Worker 	      valmatch = 1;
5582*5e7646d2SAndroid Build Coastguard Worker 	      break;
5583*5e7646d2SAndroid Build Coastguard Worker 	    }
5584*5e7646d2SAndroid Build Coastguard Worker 	  }
5585*5e7646d2SAndroid Build Coastguard Worker 
5586*5e7646d2SAndroid Build Coastguard Worker           if (flags & IPPTOOL_WITH_ALL)
5587*5e7646d2SAndroid Build Coastguard Worker           {
5588*5e7646d2SAndroid Build Coastguard Worker             if (!valmatch)
5589*5e7646d2SAndroid Build Coastguard Worker             {
5590*5e7646d2SAndroid Build Coastguard Worker               match = 0;
5591*5e7646d2SAndroid Build Coastguard Worker               break;
5592*5e7646d2SAndroid Build Coastguard Worker             }
5593*5e7646d2SAndroid Build Coastguard Worker           }
5594*5e7646d2SAndroid Build Coastguard Worker           else if (valmatch)
5595*5e7646d2SAndroid Build Coastguard Worker           {
5596*5e7646d2SAndroid Build Coastguard Worker             match = 1;
5597*5e7646d2SAndroid Build Coastguard Worker             break;
5598*5e7646d2SAndroid Build Coastguard Worker           }
5599*5e7646d2SAndroid Build Coastguard Worker         }
5600*5e7646d2SAndroid Build Coastguard Worker 
5601*5e7646d2SAndroid Build Coastguard Worker         if (!match && errors)
5602*5e7646d2SAndroid Build Coastguard Worker 	{
5603*5e7646d2SAndroid Build Coastguard Worker 	  for (i = 0; i < count; i ++)
5604*5e7646d2SAndroid Build Coastguard Worker 	    add_stringf(data->errors, "GOT: %s=%d", name, ippGetInteger(attr, i));
5605*5e7646d2SAndroid Build Coastguard Worker 	}
5606*5e7646d2SAndroid Build Coastguard Worker 	break;
5607*5e7646d2SAndroid Build Coastguard Worker 
5608*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_RANGE :
5609*5e7646d2SAndroid Build Coastguard Worker         for (i = 0; i < count; i ++)
5610*5e7646d2SAndroid Build Coastguard Worker         {
5611*5e7646d2SAndroid Build Coastguard Worker 	  char	op,			/* Comparison operator */
5612*5e7646d2SAndroid Build Coastguard Worker 	  	*nextptr;		/* Next pointer */
5613*5e7646d2SAndroid Build Coastguard Worker 	  int	intvalue,		/* Integer value */
5614*5e7646d2SAndroid Build Coastguard Worker 	        lower,			/* Lower range */
5615*5e7646d2SAndroid Build Coastguard Worker 	        upper,			/* Upper range */
5616*5e7646d2SAndroid Build Coastguard Worker 	  	valmatch = 0;		/* Does the current value match? */
5617*5e7646d2SAndroid Build Coastguard Worker 
5618*5e7646d2SAndroid Build Coastguard Worker 	  lower = ippGetRange(attr, i, &upper);
5619*5e7646d2SAndroid Build Coastguard Worker           valptr = value;
5620*5e7646d2SAndroid Build Coastguard Worker 
5621*5e7646d2SAndroid Build Coastguard Worker 	  while (isspace(*valptr & 255) || isdigit(*valptr & 255) ||
5622*5e7646d2SAndroid Build Coastguard Worker 		 *valptr == '-' || *valptr == ',' || *valptr == '<' ||
5623*5e7646d2SAndroid Build Coastguard Worker 		 *valptr == '=' || *valptr == '>')
5624*5e7646d2SAndroid Build Coastguard Worker 	  {
5625*5e7646d2SAndroid Build Coastguard Worker 	    op = '=';
5626*5e7646d2SAndroid Build Coastguard Worker 	    while (*valptr && !isdigit(*valptr & 255) && *valptr != '-')
5627*5e7646d2SAndroid Build Coastguard Worker 	    {
5628*5e7646d2SAndroid Build Coastguard Worker 	      if (*valptr == '<' || *valptr == '>' || *valptr == '=')
5629*5e7646d2SAndroid Build Coastguard Worker 		op = *valptr;
5630*5e7646d2SAndroid Build Coastguard Worker 	      valptr ++;
5631*5e7646d2SAndroid Build Coastguard Worker 	    }
5632*5e7646d2SAndroid Build Coastguard Worker 
5633*5e7646d2SAndroid Build Coastguard Worker             if (!*valptr)
5634*5e7646d2SAndroid Build Coastguard Worker 	      break;
5635*5e7646d2SAndroid Build Coastguard Worker 
5636*5e7646d2SAndroid Build Coastguard Worker 	    intvalue = (int)strtol(valptr, &nextptr, 0);
5637*5e7646d2SAndroid Build Coastguard Worker 	    if (nextptr == valptr)
5638*5e7646d2SAndroid Build Coastguard Worker 	      break;
5639*5e7646d2SAndroid Build Coastguard Worker 	    valptr = nextptr;
5640*5e7646d2SAndroid Build Coastguard Worker 
5641*5e7646d2SAndroid Build Coastguard Worker             if ((op == '=' && (lower == intvalue || upper == intvalue)) ||
5642*5e7646d2SAndroid Build Coastguard Worker 		(op == '<' && upper < intvalue) ||
5643*5e7646d2SAndroid Build Coastguard Worker 		(op == '>' && upper > intvalue))
5644*5e7646d2SAndroid Build Coastguard Worker 	    {
5645*5e7646d2SAndroid Build Coastguard Worker 	      if (!matchbuf[0])
5646*5e7646d2SAndroid Build Coastguard Worker 		snprintf(matchbuf, matchlen, "%d-%d", lower, upper);
5647*5e7646d2SAndroid Build Coastguard Worker 
5648*5e7646d2SAndroid Build Coastguard Worker 	      valmatch = 1;
5649*5e7646d2SAndroid Build Coastguard Worker 	      break;
5650*5e7646d2SAndroid Build Coastguard Worker 	    }
5651*5e7646d2SAndroid Build Coastguard Worker 	  }
5652*5e7646d2SAndroid Build Coastguard Worker 
5653*5e7646d2SAndroid Build Coastguard Worker           if (flags & IPPTOOL_WITH_ALL)
5654*5e7646d2SAndroid Build Coastguard Worker           {
5655*5e7646d2SAndroid Build Coastguard Worker             if (!valmatch)
5656*5e7646d2SAndroid Build Coastguard Worker             {
5657*5e7646d2SAndroid Build Coastguard Worker               match = 0;
5658*5e7646d2SAndroid Build Coastguard Worker               break;
5659*5e7646d2SAndroid Build Coastguard Worker             }
5660*5e7646d2SAndroid Build Coastguard Worker           }
5661*5e7646d2SAndroid Build Coastguard Worker           else if (valmatch)
5662*5e7646d2SAndroid Build Coastguard Worker           {
5663*5e7646d2SAndroid Build Coastguard Worker             match = 1;
5664*5e7646d2SAndroid Build Coastguard Worker             break;
5665*5e7646d2SAndroid Build Coastguard Worker           }
5666*5e7646d2SAndroid Build Coastguard Worker         }
5667*5e7646d2SAndroid Build Coastguard Worker 
5668*5e7646d2SAndroid Build Coastguard Worker         if (!match && errors)
5669*5e7646d2SAndroid Build Coastguard Worker 	{
5670*5e7646d2SAndroid Build Coastguard Worker 	  for (i = 0; i < count; i ++)
5671*5e7646d2SAndroid Build Coastguard Worker 	  {
5672*5e7646d2SAndroid Build Coastguard Worker 	    int lower, upper;		/* Range values */
5673*5e7646d2SAndroid Build Coastguard Worker 
5674*5e7646d2SAndroid Build Coastguard Worker 	    lower = ippGetRange(attr, i, &upper);
5675*5e7646d2SAndroid Build Coastguard Worker 	    add_stringf(data->errors, "GOT: %s=%d-%d", name, lower, upper);
5676*5e7646d2SAndroid Build Coastguard Worker 	  }
5677*5e7646d2SAndroid Build Coastguard Worker 	}
5678*5e7646d2SAndroid Build Coastguard Worker 	break;
5679*5e7646d2SAndroid Build Coastguard Worker 
5680*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_BOOLEAN :
5681*5e7646d2SAndroid Build Coastguard Worker 	for (i = 0; i < count; i ++)
5682*5e7646d2SAndroid Build Coastguard Worker 	{
5683*5e7646d2SAndroid Build Coastguard Worker           if ((!strcmp(value, "true") || !strcmp(value, "1")) == ippGetBoolean(attr, i))
5684*5e7646d2SAndroid Build Coastguard Worker           {
5685*5e7646d2SAndroid Build Coastguard Worker             if (!matchbuf[0])
5686*5e7646d2SAndroid Build Coastguard Worker 	      strlcpy(matchbuf, value, matchlen);
5687*5e7646d2SAndroid Build Coastguard Worker 
5688*5e7646d2SAndroid Build Coastguard Worker 	    if (!(flags & IPPTOOL_WITH_ALL))
5689*5e7646d2SAndroid Build Coastguard Worker 	    {
5690*5e7646d2SAndroid Build Coastguard Worker 	      match = 1;
5691*5e7646d2SAndroid Build Coastguard Worker 	      break;
5692*5e7646d2SAndroid Build Coastguard Worker 	    }
5693*5e7646d2SAndroid Build Coastguard Worker 	  }
5694*5e7646d2SAndroid Build Coastguard Worker 	  else if (flags & IPPTOOL_WITH_ALL)
5695*5e7646d2SAndroid Build Coastguard Worker 	  {
5696*5e7646d2SAndroid Build Coastguard Worker 	    match = 0;
5697*5e7646d2SAndroid Build Coastguard Worker 	    break;
5698*5e7646d2SAndroid Build Coastguard Worker 	  }
5699*5e7646d2SAndroid Build Coastguard Worker 	}
5700*5e7646d2SAndroid Build Coastguard Worker 
5701*5e7646d2SAndroid Build Coastguard Worker 	if (!match && errors)
5702*5e7646d2SAndroid Build Coastguard Worker 	{
5703*5e7646d2SAndroid Build Coastguard Worker 	  for (i = 0; i < count; i ++)
5704*5e7646d2SAndroid Build Coastguard Worker 	    add_stringf(data->errors, "GOT: %s=%s", name, ippGetBoolean(attr, i) ? "true" : "false");
5705*5e7646d2SAndroid Build Coastguard Worker 	}
5706*5e7646d2SAndroid Build Coastguard Worker 	break;
5707*5e7646d2SAndroid Build Coastguard Worker 
5708*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_RESOLUTION :
5709*5e7646d2SAndroid Build Coastguard Worker 	for (i = 0; i < count; i ++)
5710*5e7646d2SAndroid Build Coastguard Worker 	{
5711*5e7646d2SAndroid Build Coastguard Worker 	  int		xres, yres;	/* Resolution values */
5712*5e7646d2SAndroid Build Coastguard Worker 	  ipp_res_t	units;		/* Resolution units */
5713*5e7646d2SAndroid Build Coastguard Worker 
5714*5e7646d2SAndroid Build Coastguard Worker 	  xres = ippGetResolution(attr, i, &yres, &units);
5715*5e7646d2SAndroid Build Coastguard Worker 	  if (xres == yres)
5716*5e7646d2SAndroid Build Coastguard Worker 	    snprintf(temp, sizeof(temp), "%d%s", xres, units == IPP_RES_PER_INCH ? "dpi" : "dpcm");
5717*5e7646d2SAndroid Build Coastguard Worker 	  else
5718*5e7646d2SAndroid Build Coastguard Worker 	    snprintf(temp, sizeof(temp), "%dx%d%s", xres, yres, units == IPP_RES_PER_INCH ? "dpi" : "dpcm");
5719*5e7646d2SAndroid Build Coastguard Worker 
5720*5e7646d2SAndroid Build Coastguard Worker           if (!strcmp(value, temp))
5721*5e7646d2SAndroid Build Coastguard Worker           {
5722*5e7646d2SAndroid Build Coastguard Worker             if (!matchbuf[0])
5723*5e7646d2SAndroid Build Coastguard Worker 	      strlcpy(matchbuf, value, matchlen);
5724*5e7646d2SAndroid Build Coastguard Worker 
5725*5e7646d2SAndroid Build Coastguard Worker 	    if (!(flags & IPPTOOL_WITH_ALL))
5726*5e7646d2SAndroid Build Coastguard Worker 	    {
5727*5e7646d2SAndroid Build Coastguard Worker 	      match = 1;
5728*5e7646d2SAndroid Build Coastguard Worker 	      break;
5729*5e7646d2SAndroid Build Coastguard Worker 	    }
5730*5e7646d2SAndroid Build Coastguard Worker 	  }
5731*5e7646d2SAndroid Build Coastguard Worker 	  else if (flags & IPPTOOL_WITH_ALL)
5732*5e7646d2SAndroid Build Coastguard Worker 	  {
5733*5e7646d2SAndroid Build Coastguard Worker 	    match = 0;
5734*5e7646d2SAndroid Build Coastguard Worker 	    break;
5735*5e7646d2SAndroid Build Coastguard Worker 	  }
5736*5e7646d2SAndroid Build Coastguard Worker 	}
5737*5e7646d2SAndroid Build Coastguard Worker 
5738*5e7646d2SAndroid Build Coastguard Worker 	if (!match && errors)
5739*5e7646d2SAndroid Build Coastguard Worker 	{
5740*5e7646d2SAndroid Build Coastguard Worker 	  for (i = 0; i < count; i ++)
5741*5e7646d2SAndroid Build Coastguard Worker 	  {
5742*5e7646d2SAndroid Build Coastguard Worker 	    int		xres, yres;	/* Resolution values */
5743*5e7646d2SAndroid Build Coastguard Worker 	    ipp_res_t	units;		/* Resolution units */
5744*5e7646d2SAndroid Build Coastguard Worker 
5745*5e7646d2SAndroid Build Coastguard Worker 	    xres = ippGetResolution(attr, i, &yres, &units);
5746*5e7646d2SAndroid Build Coastguard Worker 	    if (xres == yres)
5747*5e7646d2SAndroid Build Coastguard Worker 	      snprintf(temp, sizeof(temp), "%d%s", xres, units == IPP_RES_PER_INCH ? "dpi" : "dpcm");
5748*5e7646d2SAndroid Build Coastguard Worker 	    else
5749*5e7646d2SAndroid Build Coastguard Worker 	      snprintf(temp, sizeof(temp), "%dx%d%s", xres, yres, units == IPP_RES_PER_INCH ? "dpi" : "dpcm");
5750*5e7646d2SAndroid Build Coastguard Worker 
5751*5e7646d2SAndroid Build Coastguard Worker             if (strcmp(value, temp))
5752*5e7646d2SAndroid Build Coastguard Worker 	      add_stringf(data->errors, "GOT: %s=%s", name, temp);
5753*5e7646d2SAndroid Build Coastguard Worker 	  }
5754*5e7646d2SAndroid Build Coastguard Worker 	}
5755*5e7646d2SAndroid Build Coastguard Worker 	break;
5756*5e7646d2SAndroid Build Coastguard Worker 
5757*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_NOVALUE :
5758*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_UNKNOWN :
5759*5e7646d2SAndroid Build Coastguard Worker 	return (1);
5760*5e7646d2SAndroid Build Coastguard Worker 
5761*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_CHARSET :
5762*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_KEYWORD :
5763*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_LANGUAGE :
5764*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_MIMETYPE :
5765*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_NAME :
5766*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_NAMELANG :
5767*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_TEXT :
5768*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_TEXTLANG :
5769*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_URI :
5770*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_URISCHEME :
5771*5e7646d2SAndroid Build Coastguard Worker         if (flags & IPPTOOL_WITH_REGEX)
5772*5e7646d2SAndroid Build Coastguard Worker 	{
5773*5e7646d2SAndroid Build Coastguard Worker 	 /*
5774*5e7646d2SAndroid Build Coastguard Worker 	  * Value is an extended, case-sensitive POSIX regular expression...
5775*5e7646d2SAndroid Build Coastguard Worker 	  */
5776*5e7646d2SAndroid Build Coastguard Worker 
5777*5e7646d2SAndroid Build Coastguard Worker 	  regex_t	re;		/* Regular expression */
5778*5e7646d2SAndroid Build Coastguard Worker 
5779*5e7646d2SAndroid Build Coastguard Worker           if ((i = regcomp(&re, value, REG_EXTENDED | REG_NOSUB)) != 0)
5780*5e7646d2SAndroid Build Coastguard Worker 	  {
5781*5e7646d2SAndroid Build Coastguard Worker             regerror(i, &re, temp, sizeof(temp));
5782*5e7646d2SAndroid Build Coastguard Worker 
5783*5e7646d2SAndroid Build Coastguard Worker 	    print_fatal_error(data, "Unable to compile WITH-VALUE regular expression \"%s\" - %s", value, temp);
5784*5e7646d2SAndroid Build Coastguard Worker 	    return (0);
5785*5e7646d2SAndroid Build Coastguard Worker 	  }
5786*5e7646d2SAndroid Build Coastguard Worker 
5787*5e7646d2SAndroid Build Coastguard Worker          /*
5788*5e7646d2SAndroid Build Coastguard Worker 	  * See if ALL of the values match the given regular expression.
5789*5e7646d2SAndroid Build Coastguard Worker 	  */
5790*5e7646d2SAndroid Build Coastguard Worker 
5791*5e7646d2SAndroid Build Coastguard Worker 	  for (i = 0; i < count; i ++)
5792*5e7646d2SAndroid Build Coastguard Worker 	  {
5793*5e7646d2SAndroid Build Coastguard Worker 	    if (!regexec(&re, get_string(attr, i, flags, temp, sizeof(temp)),
5794*5e7646d2SAndroid Build Coastguard Worker 	                 0, NULL, 0))
5795*5e7646d2SAndroid Build Coastguard Worker 	    {
5796*5e7646d2SAndroid Build Coastguard Worker 	      if (!matchbuf[0])
5797*5e7646d2SAndroid Build Coastguard Worker 		strlcpy(matchbuf, get_string(attr, i, flags, temp, sizeof(temp)), matchlen);
5798*5e7646d2SAndroid Build Coastguard Worker 
5799*5e7646d2SAndroid Build Coastguard Worker 	      if (!(flags & IPPTOOL_WITH_ALL))
5800*5e7646d2SAndroid Build Coastguard Worker 	      {
5801*5e7646d2SAndroid Build Coastguard Worker 	        match = 1;
5802*5e7646d2SAndroid Build Coastguard Worker 	        break;
5803*5e7646d2SAndroid Build Coastguard Worker 	      }
5804*5e7646d2SAndroid Build Coastguard Worker 	    }
5805*5e7646d2SAndroid Build Coastguard Worker 	    else if (flags & IPPTOOL_WITH_ALL)
5806*5e7646d2SAndroid Build Coastguard Worker 	    {
5807*5e7646d2SAndroid Build Coastguard Worker 	      match = 0;
5808*5e7646d2SAndroid Build Coastguard Worker 	      break;
5809*5e7646d2SAndroid Build Coastguard Worker 	    }
5810*5e7646d2SAndroid Build Coastguard Worker 	  }
5811*5e7646d2SAndroid Build Coastguard Worker 
5812*5e7646d2SAndroid Build Coastguard Worker 	  regfree(&re);
5813*5e7646d2SAndroid Build Coastguard Worker 	}
5814*5e7646d2SAndroid Build Coastguard Worker 	else if (ippGetValueTag(attr) == IPP_TAG_URI && !(flags & (IPPTOOL_WITH_SCHEME | IPPTOOL_WITH_HOSTNAME | IPPTOOL_WITH_RESOURCE)))
5815*5e7646d2SAndroid Build Coastguard Worker 	{
5816*5e7646d2SAndroid Build Coastguard Worker 	 /*
5817*5e7646d2SAndroid Build Coastguard Worker 	  * Value is a literal URI string, see if the value(s) match...
5818*5e7646d2SAndroid Build Coastguard Worker 	  */
5819*5e7646d2SAndroid Build Coastguard Worker 
5820*5e7646d2SAndroid Build Coastguard Worker 	  for (i = 0; i < count; i ++)
5821*5e7646d2SAndroid Build Coastguard Worker 	  {
5822*5e7646d2SAndroid Build Coastguard Worker 	    if (!compare_uris(value, get_string(attr, i, flags, temp, sizeof(temp))))
5823*5e7646d2SAndroid Build Coastguard Worker 	    {
5824*5e7646d2SAndroid Build Coastguard Worker 	      if (!matchbuf[0])
5825*5e7646d2SAndroid Build Coastguard Worker 		strlcpy(matchbuf, get_string(attr, i, flags, temp, sizeof(temp)), matchlen);
5826*5e7646d2SAndroid Build Coastguard Worker 
5827*5e7646d2SAndroid Build Coastguard Worker 	      if (!(flags & IPPTOOL_WITH_ALL))
5828*5e7646d2SAndroid Build Coastguard Worker 	      {
5829*5e7646d2SAndroid Build Coastguard Worker 	        match = 1;
5830*5e7646d2SAndroid Build Coastguard Worker 	        break;
5831*5e7646d2SAndroid Build Coastguard Worker 	      }
5832*5e7646d2SAndroid Build Coastguard Worker 	    }
5833*5e7646d2SAndroid Build Coastguard Worker 	    else if (flags & IPPTOOL_WITH_ALL)
5834*5e7646d2SAndroid Build Coastguard Worker 	    {
5835*5e7646d2SAndroid Build Coastguard Worker 	      match = 0;
5836*5e7646d2SAndroid Build Coastguard Worker 	      break;
5837*5e7646d2SAndroid Build Coastguard Worker 	    }
5838*5e7646d2SAndroid Build Coastguard Worker 	  }
5839*5e7646d2SAndroid Build Coastguard Worker 	}
5840*5e7646d2SAndroid Build Coastguard Worker 	else
5841*5e7646d2SAndroid Build Coastguard Worker 	{
5842*5e7646d2SAndroid Build Coastguard Worker 	 /*
5843*5e7646d2SAndroid Build Coastguard Worker 	  * Value is a literal string, see if the value(s) match...
5844*5e7646d2SAndroid Build Coastguard Worker 	  */
5845*5e7646d2SAndroid Build Coastguard Worker 
5846*5e7646d2SAndroid Build Coastguard Worker 	  for (i = 0; i < count; i ++)
5847*5e7646d2SAndroid Build Coastguard Worker 	  {
5848*5e7646d2SAndroid Build Coastguard Worker 	    int result;
5849*5e7646d2SAndroid Build Coastguard Worker 
5850*5e7646d2SAndroid Build Coastguard Worker             switch (ippGetValueTag(attr))
5851*5e7646d2SAndroid Build Coastguard Worker             {
5852*5e7646d2SAndroid Build Coastguard Worker               case IPP_TAG_URI :
5853*5e7646d2SAndroid Build Coastguard Worker                  /*
5854*5e7646d2SAndroid Build Coastguard Worker                   * Some URI components are case-sensitive, some not...
5855*5e7646d2SAndroid Build Coastguard Worker                   */
5856*5e7646d2SAndroid Build Coastguard Worker 
5857*5e7646d2SAndroid Build Coastguard Worker                   if (flags & (IPPTOOL_WITH_SCHEME | IPPTOOL_WITH_HOSTNAME))
5858*5e7646d2SAndroid Build Coastguard Worker                     result = _cups_strcasecmp(value, get_string(attr, i, flags, temp, sizeof(temp)));
5859*5e7646d2SAndroid Build Coastguard Worker                   else
5860*5e7646d2SAndroid Build Coastguard Worker                     result = strcmp(value, get_string(attr, i, flags, temp, sizeof(temp)));
5861*5e7646d2SAndroid Build Coastguard Worker                   break;
5862*5e7646d2SAndroid Build Coastguard Worker 
5863*5e7646d2SAndroid Build Coastguard Worker               case IPP_TAG_MIMETYPE :
5864*5e7646d2SAndroid Build Coastguard Worker               case IPP_TAG_NAME :
5865*5e7646d2SAndroid Build Coastguard Worker               case IPP_TAG_NAMELANG :
5866*5e7646d2SAndroid Build Coastguard Worker               case IPP_TAG_TEXT :
5867*5e7646d2SAndroid Build Coastguard Worker               case IPP_TAG_TEXTLANG :
5868*5e7646d2SAndroid Build Coastguard Worker                  /*
5869*5e7646d2SAndroid Build Coastguard Worker                   * mimeMediaType, nameWithoutLanguage, nameWithLanguage,
5870*5e7646d2SAndroid Build Coastguard Worker                   * textWithoutLanguage, and textWithLanguage are defined to
5871*5e7646d2SAndroid Build Coastguard Worker                   * be case-insensitive strings...
5872*5e7646d2SAndroid Build Coastguard Worker                   */
5873*5e7646d2SAndroid Build Coastguard Worker 
5874*5e7646d2SAndroid Build Coastguard Worker                   result = _cups_strcasecmp(value, get_string(attr, i, flags, temp, sizeof(temp)));
5875*5e7646d2SAndroid Build Coastguard Worker                   break;
5876*5e7646d2SAndroid Build Coastguard Worker 
5877*5e7646d2SAndroid Build Coastguard Worker               default :
5878*5e7646d2SAndroid Build Coastguard Worker                  /*
5879*5e7646d2SAndroid Build Coastguard Worker                   * Other string syntaxes are defined as lowercased so we use
5880*5e7646d2SAndroid Build Coastguard Worker                   * case-sensitive comparisons to catch problems...
5881*5e7646d2SAndroid Build Coastguard Worker                   */
5882*5e7646d2SAndroid Build Coastguard Worker 
5883*5e7646d2SAndroid Build Coastguard Worker                   result = strcmp(value, get_string(attr, i, flags, temp, sizeof(temp)));
5884*5e7646d2SAndroid Build Coastguard Worker                   break;
5885*5e7646d2SAndroid Build Coastguard Worker             }
5886*5e7646d2SAndroid Build Coastguard Worker 
5887*5e7646d2SAndroid Build Coastguard Worker             if (!result)
5888*5e7646d2SAndroid Build Coastguard Worker 	    {
5889*5e7646d2SAndroid Build Coastguard Worker 	      if (!matchbuf[0])
5890*5e7646d2SAndroid Build Coastguard Worker 		strlcpy(matchbuf, get_string(attr, i, flags, temp, sizeof(temp)), matchlen);
5891*5e7646d2SAndroid Build Coastguard Worker 
5892*5e7646d2SAndroid Build Coastguard Worker 	      if (!(flags & IPPTOOL_WITH_ALL))
5893*5e7646d2SAndroid Build Coastguard Worker 	      {
5894*5e7646d2SAndroid Build Coastguard Worker 	        match = 1;
5895*5e7646d2SAndroid Build Coastguard Worker 	        break;
5896*5e7646d2SAndroid Build Coastguard Worker 	      }
5897*5e7646d2SAndroid Build Coastguard Worker 	    }
5898*5e7646d2SAndroid Build Coastguard Worker 	    else if (flags & IPPTOOL_WITH_ALL)
5899*5e7646d2SAndroid Build Coastguard Worker 	    {
5900*5e7646d2SAndroid Build Coastguard Worker 	      match = 0;
5901*5e7646d2SAndroid Build Coastguard Worker 	      break;
5902*5e7646d2SAndroid Build Coastguard Worker 	    }
5903*5e7646d2SAndroid Build Coastguard Worker 	  }
5904*5e7646d2SAndroid Build Coastguard Worker 	}
5905*5e7646d2SAndroid Build Coastguard Worker 
5906*5e7646d2SAndroid Build Coastguard Worker         if (!match && errors)
5907*5e7646d2SAndroid Build Coastguard Worker         {
5908*5e7646d2SAndroid Build Coastguard Worker 	  for (i = 0; i < count; i ++)
5909*5e7646d2SAndroid Build Coastguard Worker 	    add_stringf(data->errors, "GOT: %s=\"%s\"", name, ippGetString(attr, i, NULL));
5910*5e7646d2SAndroid Build Coastguard Worker         }
5911*5e7646d2SAndroid Build Coastguard Worker 	break;
5912*5e7646d2SAndroid Build Coastguard Worker 
5913*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_STRING :
5914*5e7646d2SAndroid Build Coastguard Worker         if (flags & IPPTOOL_WITH_REGEX)
5915*5e7646d2SAndroid Build Coastguard Worker 	{
5916*5e7646d2SAndroid Build Coastguard Worker 	 /*
5917*5e7646d2SAndroid Build Coastguard Worker 	  * Value is an extended, case-sensitive POSIX regular expression...
5918*5e7646d2SAndroid Build Coastguard Worker 	  */
5919*5e7646d2SAndroid Build Coastguard Worker 
5920*5e7646d2SAndroid Build Coastguard Worker 	  void		*adata;		/* Pointer to octetString data */
5921*5e7646d2SAndroid Build Coastguard Worker 	  int		adatalen;	/* Length of octetString */
5922*5e7646d2SAndroid Build Coastguard Worker 	  regex_t	re;		/* Regular expression */
5923*5e7646d2SAndroid Build Coastguard Worker 
5924*5e7646d2SAndroid Build Coastguard Worker           if ((i = regcomp(&re, value, REG_EXTENDED | REG_NOSUB)) != 0)
5925*5e7646d2SAndroid Build Coastguard Worker 	  {
5926*5e7646d2SAndroid Build Coastguard Worker             regerror(i, &re, temp, sizeof(temp));
5927*5e7646d2SAndroid Build Coastguard Worker 
5928*5e7646d2SAndroid Build Coastguard Worker 	    print_fatal_error(data, "Unable to compile WITH-VALUE regular expression \"%s\" - %s", value, temp);
5929*5e7646d2SAndroid Build Coastguard Worker 	    return (0);
5930*5e7646d2SAndroid Build Coastguard Worker 	  }
5931*5e7646d2SAndroid Build Coastguard Worker 
5932*5e7646d2SAndroid Build Coastguard Worker          /*
5933*5e7646d2SAndroid Build Coastguard Worker 	  * See if ALL of the values match the given regular expression.
5934*5e7646d2SAndroid Build Coastguard Worker 	  */
5935*5e7646d2SAndroid Build Coastguard Worker 
5936*5e7646d2SAndroid Build Coastguard Worker 	  for (i = 0; i < count; i ++)
5937*5e7646d2SAndroid Build Coastguard Worker 	  {
5938*5e7646d2SAndroid Build Coastguard Worker             if ((adata = ippGetOctetString(attr, i, &adatalen)) == NULL || adatalen >= (int)sizeof(temp))
5939*5e7646d2SAndroid Build Coastguard Worker             {
5940*5e7646d2SAndroid Build Coastguard Worker               match = 0;
5941*5e7646d2SAndroid Build Coastguard Worker               break;
5942*5e7646d2SAndroid Build Coastguard Worker             }
5943*5e7646d2SAndroid Build Coastguard Worker             memcpy(temp, adata, (size_t)adatalen);
5944*5e7646d2SAndroid Build Coastguard Worker             temp[adatalen] = '\0';
5945*5e7646d2SAndroid Build Coastguard Worker 
5946*5e7646d2SAndroid Build Coastguard Worker 	    if (!regexec(&re, temp, 0, NULL, 0))
5947*5e7646d2SAndroid Build Coastguard Worker 	    {
5948*5e7646d2SAndroid Build Coastguard Worker 	      if (!matchbuf[0])
5949*5e7646d2SAndroid Build Coastguard Worker 		strlcpy(matchbuf, temp, matchlen);
5950*5e7646d2SAndroid Build Coastguard Worker 
5951*5e7646d2SAndroid Build Coastguard Worker 	      if (!(flags & IPPTOOL_WITH_ALL))
5952*5e7646d2SAndroid Build Coastguard Worker 	      {
5953*5e7646d2SAndroid Build Coastguard Worker 	        match = 1;
5954*5e7646d2SAndroid Build Coastguard Worker 	        break;
5955*5e7646d2SAndroid Build Coastguard Worker 	      }
5956*5e7646d2SAndroid Build Coastguard Worker 	    }
5957*5e7646d2SAndroid Build Coastguard Worker 	    else if (flags & IPPTOOL_WITH_ALL)
5958*5e7646d2SAndroid Build Coastguard Worker 	    {
5959*5e7646d2SAndroid Build Coastguard Worker 	      match = 0;
5960*5e7646d2SAndroid Build Coastguard Worker 	      break;
5961*5e7646d2SAndroid Build Coastguard Worker 	    }
5962*5e7646d2SAndroid Build Coastguard Worker 	  }
5963*5e7646d2SAndroid Build Coastguard Worker 
5964*5e7646d2SAndroid Build Coastguard Worker 	  regfree(&re);
5965*5e7646d2SAndroid Build Coastguard Worker 
5966*5e7646d2SAndroid Build Coastguard Worker 	  if (!match && errors)
5967*5e7646d2SAndroid Build Coastguard Worker 	  {
5968*5e7646d2SAndroid Build Coastguard Worker 	    for (i = 0; i < count; i ++)
5969*5e7646d2SAndroid Build Coastguard Worker 	    {
5970*5e7646d2SAndroid Build Coastguard Worker 	      adata = ippGetOctetString(attr, i, &adatalen);
5971*5e7646d2SAndroid Build Coastguard Worker 	      copy_hex_string(temp, adata, adatalen, sizeof(temp));
5972*5e7646d2SAndroid Build Coastguard Worker 	      add_stringf(data->errors, "GOT: %s=\"%s\"", name, temp);
5973*5e7646d2SAndroid Build Coastguard Worker 	    }
5974*5e7646d2SAndroid Build Coastguard Worker 	  }
5975*5e7646d2SAndroid Build Coastguard Worker 	}
5976*5e7646d2SAndroid Build Coastguard Worker 	else
5977*5e7646d2SAndroid Build Coastguard Worker         {
5978*5e7646d2SAndroid Build Coastguard Worker          /*
5979*5e7646d2SAndroid Build Coastguard Worker           * Value is a literal or hex-encoded string...
5980*5e7646d2SAndroid Build Coastguard Worker           */
5981*5e7646d2SAndroid Build Coastguard Worker 
5982*5e7646d2SAndroid Build Coastguard Worker           unsigned char	withdata[1023],	/* WITH-VALUE data */
5983*5e7646d2SAndroid Build Coastguard Worker 			*adata;		/* Pointer to octetString data */
5984*5e7646d2SAndroid Build Coastguard Worker 	  int		withlen,	/* Length of WITH-VALUE data */
5985*5e7646d2SAndroid Build Coastguard Worker 			adatalen;	/* Length of octetString */
5986*5e7646d2SAndroid Build Coastguard Worker 
5987*5e7646d2SAndroid Build Coastguard Worker           if (*value == '<')
5988*5e7646d2SAndroid Build Coastguard Worker           {
5989*5e7646d2SAndroid Build Coastguard Worker            /*
5990*5e7646d2SAndroid Build Coastguard Worker             * Grab hex-encoded value...
5991*5e7646d2SAndroid Build Coastguard Worker             */
5992*5e7646d2SAndroid Build Coastguard Worker 
5993*5e7646d2SAndroid Build Coastguard Worker             if ((withlen = (int)strlen(value)) & 1 || withlen > (int)(2 * (sizeof(withdata) + 1)))
5994*5e7646d2SAndroid Build Coastguard Worker             {
5995*5e7646d2SAndroid Build Coastguard Worker 	      print_fatal_error(data, "Bad WITH-VALUE hex value.");
5996*5e7646d2SAndroid Build Coastguard Worker               return (0);
5997*5e7646d2SAndroid Build Coastguard Worker 	    }
5998*5e7646d2SAndroid Build Coastguard Worker 
5999*5e7646d2SAndroid Build Coastguard Worker 	    withlen = withlen / 2 - 1;
6000*5e7646d2SAndroid Build Coastguard Worker 
6001*5e7646d2SAndroid Build Coastguard Worker             for (valptr = value + 1, adata = withdata; *valptr; valptr += 2)
6002*5e7646d2SAndroid Build Coastguard Worker             {
6003*5e7646d2SAndroid Build Coastguard Worker               int ch;			/* Current character/byte */
6004*5e7646d2SAndroid Build Coastguard Worker 
6005*5e7646d2SAndroid Build Coastguard Worker 	      if (isdigit(valptr[0]))
6006*5e7646d2SAndroid Build Coastguard Worker 	        ch = (valptr[0] - '0') << 4;
6007*5e7646d2SAndroid Build Coastguard Worker 	      else if (isalpha(valptr[0]))
6008*5e7646d2SAndroid Build Coastguard Worker 	        ch = (tolower(valptr[0]) - 'a' + 10) << 4;
6009*5e7646d2SAndroid Build Coastguard Worker 	      else
6010*5e7646d2SAndroid Build Coastguard Worker 	        break;
6011*5e7646d2SAndroid Build Coastguard Worker 
6012*5e7646d2SAndroid Build Coastguard Worker 	      if (isdigit(valptr[1]))
6013*5e7646d2SAndroid Build Coastguard Worker 	        ch |= valptr[1] - '0';
6014*5e7646d2SAndroid Build Coastguard Worker 	      else if (isalpha(valptr[1]))
6015*5e7646d2SAndroid Build Coastguard Worker 	        ch |= tolower(valptr[1]) - 'a' + 10;
6016*5e7646d2SAndroid Build Coastguard Worker 	      else
6017*5e7646d2SAndroid Build Coastguard Worker 	        break;
6018*5e7646d2SAndroid Build Coastguard Worker 
6019*5e7646d2SAndroid Build Coastguard Worker 	      *adata++ = (unsigned char)ch;
6020*5e7646d2SAndroid Build Coastguard Worker 	    }
6021*5e7646d2SAndroid Build Coastguard Worker 
6022*5e7646d2SAndroid Build Coastguard Worker 	    if (*valptr)
6023*5e7646d2SAndroid Build Coastguard Worker 	    {
6024*5e7646d2SAndroid Build Coastguard Worker 	      print_fatal_error(data, "Bad WITH-VALUE hex value.");
6025*5e7646d2SAndroid Build Coastguard Worker               return (0);
6026*5e7646d2SAndroid Build Coastguard Worker 	    }
6027*5e7646d2SAndroid Build Coastguard Worker           }
6028*5e7646d2SAndroid Build Coastguard Worker           else
6029*5e7646d2SAndroid Build Coastguard Worker           {
6030*5e7646d2SAndroid Build Coastguard Worker            /*
6031*5e7646d2SAndroid Build Coastguard Worker             * Copy literal string value...
6032*5e7646d2SAndroid Build Coastguard Worker             */
6033*5e7646d2SAndroid Build Coastguard Worker 
6034*5e7646d2SAndroid Build Coastguard Worker             withlen = (int)strlen(value);
6035*5e7646d2SAndroid Build Coastguard Worker 
6036*5e7646d2SAndroid Build Coastguard Worker             memcpy(withdata, value, (size_t)withlen);
6037*5e7646d2SAndroid Build Coastguard Worker 	  }
6038*5e7646d2SAndroid Build Coastguard Worker 
6039*5e7646d2SAndroid Build Coastguard Worker 	  for (i = 0; i < count; i ++)
6040*5e7646d2SAndroid Build Coastguard Worker 	  {
6041*5e7646d2SAndroid Build Coastguard Worker 	    adata = ippGetOctetString(attr, i, &adatalen);
6042*5e7646d2SAndroid Build Coastguard Worker 
6043*5e7646d2SAndroid Build Coastguard Worker 	    if (withlen == adatalen && !memcmp(withdata, adata, (size_t)withlen))
6044*5e7646d2SAndroid Build Coastguard Worker 	    {
6045*5e7646d2SAndroid Build Coastguard Worker 	      if (!matchbuf[0])
6046*5e7646d2SAndroid Build Coastguard Worker                 copy_hex_string(matchbuf, adata, adatalen, matchlen);
6047*5e7646d2SAndroid Build Coastguard Worker 
6048*5e7646d2SAndroid Build Coastguard Worker 	      if (!(flags & IPPTOOL_WITH_ALL))
6049*5e7646d2SAndroid Build Coastguard Worker 	      {
6050*5e7646d2SAndroid Build Coastguard Worker 	        match = 1;
6051*5e7646d2SAndroid Build Coastguard Worker 	        break;
6052*5e7646d2SAndroid Build Coastguard Worker 	      }
6053*5e7646d2SAndroid Build Coastguard Worker 	    }
6054*5e7646d2SAndroid Build Coastguard Worker 	    else if (flags & IPPTOOL_WITH_ALL)
6055*5e7646d2SAndroid Build Coastguard Worker 	    {
6056*5e7646d2SAndroid Build Coastguard Worker 	      match = 0;
6057*5e7646d2SAndroid Build Coastguard Worker 	      break;
6058*5e7646d2SAndroid Build Coastguard Worker 	    }
6059*5e7646d2SAndroid Build Coastguard Worker 	  }
6060*5e7646d2SAndroid Build Coastguard Worker 
6061*5e7646d2SAndroid Build Coastguard Worker 	  if (!match && errors)
6062*5e7646d2SAndroid Build Coastguard Worker 	  {
6063*5e7646d2SAndroid Build Coastguard Worker 	    for (i = 0; i < count; i ++)
6064*5e7646d2SAndroid Build Coastguard Worker 	    {
6065*5e7646d2SAndroid Build Coastguard Worker 	      adata = ippGetOctetString(attr, i, &adatalen);
6066*5e7646d2SAndroid Build Coastguard Worker 	      copy_hex_string(temp, adata, adatalen, sizeof(temp));
6067*5e7646d2SAndroid Build Coastguard Worker 	      add_stringf(data->errors, "GOT: %s=\"%s\"", name, temp);
6068*5e7646d2SAndroid Build Coastguard Worker 	    }
6069*5e7646d2SAndroid Build Coastguard Worker 	  }
6070*5e7646d2SAndroid Build Coastguard Worker         }
6071*5e7646d2SAndroid Build Coastguard Worker         break;
6072*5e7646d2SAndroid Build Coastguard Worker 
6073*5e7646d2SAndroid Build Coastguard Worker     default :
6074*5e7646d2SAndroid Build Coastguard Worker         break;
6075*5e7646d2SAndroid Build Coastguard Worker   }
6076*5e7646d2SAndroid Build Coastguard Worker 
6077*5e7646d2SAndroid Build Coastguard Worker   return (match);
6078*5e7646d2SAndroid Build Coastguard Worker }
6079*5e7646d2SAndroid Build Coastguard Worker 
6080*5e7646d2SAndroid Build Coastguard Worker 
6081*5e7646d2SAndroid Build Coastguard Worker /*
6082*5e7646d2SAndroid Build Coastguard Worker  * 'with_value_from()' - Test a WITH-VALUE-FROM predicate.
6083*5e7646d2SAndroid Build Coastguard Worker  */
6084*5e7646d2SAndroid Build Coastguard Worker 
6085*5e7646d2SAndroid Build Coastguard Worker static int				/* O - 1 on match, 0 on non-match */
with_value_from(cups_array_t * errors,ipp_attribute_t * fromattr,ipp_attribute_t * attr,char * matchbuf,size_t matchlen)6086*5e7646d2SAndroid Build Coastguard Worker with_value_from(
6087*5e7646d2SAndroid Build Coastguard Worker     cups_array_t    *errors,		/* I - Errors array */
6088*5e7646d2SAndroid Build Coastguard Worker     ipp_attribute_t *fromattr,		/* I - "From" attribute */
6089*5e7646d2SAndroid Build Coastguard Worker     ipp_attribute_t *attr,		/* I - Attribute to compare */
6090*5e7646d2SAndroid Build Coastguard Worker     char            *matchbuf,		/* I - Buffer to hold matching value */
6091*5e7646d2SAndroid Build Coastguard Worker     size_t          matchlen)		/* I - Length of match buffer */
6092*5e7646d2SAndroid Build Coastguard Worker {
6093*5e7646d2SAndroid Build Coastguard Worker   int	i, j,				/* Looping vars */
6094*5e7646d2SAndroid Build Coastguard Worker 	count = ippGetCount(attr),	/* Number of attribute values */
6095*5e7646d2SAndroid Build Coastguard Worker 	match = 1;			/* Match? */
6096*5e7646d2SAndroid Build Coastguard Worker 
6097*5e7646d2SAndroid Build Coastguard Worker 
6098*5e7646d2SAndroid Build Coastguard Worker   *matchbuf = '\0';
6099*5e7646d2SAndroid Build Coastguard Worker 
6100*5e7646d2SAndroid Build Coastguard Worker  /*
6101*5e7646d2SAndroid Build Coastguard Worker   * Compare the from value(s) to the attribute value(s)...
6102*5e7646d2SAndroid Build Coastguard Worker   */
6103*5e7646d2SAndroid Build Coastguard Worker 
6104*5e7646d2SAndroid Build Coastguard Worker   switch (ippGetValueTag(attr))
6105*5e7646d2SAndroid Build Coastguard Worker   {
6106*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_INTEGER :
6107*5e7646d2SAndroid Build Coastguard Worker         if (ippGetValueTag(fromattr) != IPP_TAG_INTEGER && ippGetValueTag(fromattr) != IPP_TAG_RANGE)
6108*5e7646d2SAndroid Build Coastguard Worker 	  goto wrong_value_tag;
6109*5e7646d2SAndroid Build Coastguard Worker 
6110*5e7646d2SAndroid Build Coastguard Worker 	for (i = 0; i < count; i ++)
6111*5e7646d2SAndroid Build Coastguard Worker 	{
6112*5e7646d2SAndroid Build Coastguard Worker 	  int value = ippGetInteger(attr, i);
6113*5e7646d2SAndroid Build Coastguard Worker 					/* Current integer value */
6114*5e7646d2SAndroid Build Coastguard Worker 
6115*5e7646d2SAndroid Build Coastguard Worker 	  if (ippContainsInteger(fromattr, value))
6116*5e7646d2SAndroid Build Coastguard Worker 	  {
6117*5e7646d2SAndroid Build Coastguard Worker 	    if (!matchbuf[0])
6118*5e7646d2SAndroid Build Coastguard Worker 	      snprintf(matchbuf, matchlen, "%d", value);
6119*5e7646d2SAndroid Build Coastguard Worker 	  }
6120*5e7646d2SAndroid Build Coastguard Worker 	  else
6121*5e7646d2SAndroid Build Coastguard Worker 	  {
6122*5e7646d2SAndroid Build Coastguard Worker 	    add_stringf(errors, "GOT: %s=%d", ippGetName(attr), value);
6123*5e7646d2SAndroid Build Coastguard Worker 	    match = 0;
6124*5e7646d2SAndroid Build Coastguard Worker 	  }
6125*5e7646d2SAndroid Build Coastguard Worker 	}
6126*5e7646d2SAndroid Build Coastguard Worker 	break;
6127*5e7646d2SAndroid Build Coastguard Worker 
6128*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_ENUM :
6129*5e7646d2SAndroid Build Coastguard Worker         if (ippGetValueTag(fromattr) != IPP_TAG_ENUM)
6130*5e7646d2SAndroid Build Coastguard Worker 	  goto wrong_value_tag;
6131*5e7646d2SAndroid Build Coastguard Worker 
6132*5e7646d2SAndroid Build Coastguard Worker 	for (i = 0; i < count; i ++)
6133*5e7646d2SAndroid Build Coastguard Worker 	{
6134*5e7646d2SAndroid Build Coastguard Worker 	  int value = ippGetInteger(attr, i);
6135*5e7646d2SAndroid Build Coastguard Worker 					/* Current integer value */
6136*5e7646d2SAndroid Build Coastguard Worker 
6137*5e7646d2SAndroid Build Coastguard Worker 	  if (ippContainsInteger(fromattr, value))
6138*5e7646d2SAndroid Build Coastguard Worker 	  {
6139*5e7646d2SAndroid Build Coastguard Worker 	    if (!matchbuf[0])
6140*5e7646d2SAndroid Build Coastguard Worker 	      snprintf(matchbuf, matchlen, "%d", value);
6141*5e7646d2SAndroid Build Coastguard Worker 	  }
6142*5e7646d2SAndroid Build Coastguard Worker 	  else
6143*5e7646d2SAndroid Build Coastguard Worker 	  {
6144*5e7646d2SAndroid Build Coastguard Worker 	    add_stringf(errors, "GOT: %s=%d", ippGetName(attr), value);
6145*5e7646d2SAndroid Build Coastguard Worker 	    match = 0;
6146*5e7646d2SAndroid Build Coastguard Worker 	  }
6147*5e7646d2SAndroid Build Coastguard Worker 	}
6148*5e7646d2SAndroid Build Coastguard Worker 	break;
6149*5e7646d2SAndroid Build Coastguard Worker 
6150*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_RESOLUTION :
6151*5e7646d2SAndroid Build Coastguard Worker         if (ippGetValueTag(fromattr) != IPP_TAG_RESOLUTION)
6152*5e7646d2SAndroid Build Coastguard Worker 	  goto wrong_value_tag;
6153*5e7646d2SAndroid Build Coastguard Worker 
6154*5e7646d2SAndroid Build Coastguard Worker 	for (i = 0; i < count; i ++)
6155*5e7646d2SAndroid Build Coastguard Worker 	{
6156*5e7646d2SAndroid Build Coastguard Worker 	  int xres, yres;
6157*5e7646d2SAndroid Build Coastguard Worker 	  ipp_res_t units;
6158*5e7646d2SAndroid Build Coastguard Worker           int fromcount = ippGetCount(fromattr);
6159*5e7646d2SAndroid Build Coastguard Worker 	  int fromxres, fromyres;
6160*5e7646d2SAndroid Build Coastguard Worker 	  ipp_res_t fromunits;
6161*5e7646d2SAndroid Build Coastguard Worker 
6162*5e7646d2SAndroid Build Coastguard Worker 	  xres = ippGetResolution(attr, i, &yres, &units);
6163*5e7646d2SAndroid Build Coastguard Worker 
6164*5e7646d2SAndroid Build Coastguard Worker           for (j = 0; j < fromcount; j ++)
6165*5e7646d2SAndroid Build Coastguard Worker 	  {
6166*5e7646d2SAndroid Build Coastguard Worker 	    fromxres = ippGetResolution(fromattr, j, &fromyres, &fromunits);
6167*5e7646d2SAndroid Build Coastguard Worker 	    if (fromxres == xres && fromyres == yres && fromunits == units)
6168*5e7646d2SAndroid Build Coastguard Worker 	      break;
6169*5e7646d2SAndroid Build Coastguard Worker 	  }
6170*5e7646d2SAndroid Build Coastguard Worker 
6171*5e7646d2SAndroid Build Coastguard Worker 	  if (j < fromcount)
6172*5e7646d2SAndroid Build Coastguard Worker 	  {
6173*5e7646d2SAndroid Build Coastguard Worker 	    if (!matchbuf[0])
6174*5e7646d2SAndroid Build Coastguard Worker 	    {
6175*5e7646d2SAndroid Build Coastguard Worker 	      if (xres == yres)
6176*5e7646d2SAndroid Build Coastguard Worker 	        snprintf(matchbuf, matchlen, "%d%s", xres, units == IPP_RES_PER_INCH ? "dpi" : "dpcm");
6177*5e7646d2SAndroid Build Coastguard Worker 	      else
6178*5e7646d2SAndroid Build Coastguard Worker 	        snprintf(matchbuf, matchlen, "%dx%d%s", xres, yres, units == IPP_RES_PER_INCH ? "dpi" : "dpcm");
6179*5e7646d2SAndroid Build Coastguard Worker 	    }
6180*5e7646d2SAndroid Build Coastguard Worker 	  }
6181*5e7646d2SAndroid Build Coastguard Worker 	  else
6182*5e7646d2SAndroid Build Coastguard Worker 	  {
6183*5e7646d2SAndroid Build Coastguard Worker 	    if (xres == yres)
6184*5e7646d2SAndroid Build Coastguard Worker 	      add_stringf(errors, "GOT: %s=%d%s", ippGetName(attr), xres, units == IPP_RES_PER_INCH ? "dpi" : "dpcm");
6185*5e7646d2SAndroid Build Coastguard Worker 	    else
6186*5e7646d2SAndroid Build Coastguard Worker 	      add_stringf(errors, "GOT: %s=%dx%d%s", ippGetName(attr), xres, yres, units == IPP_RES_PER_INCH ? "dpi" : "dpcm");
6187*5e7646d2SAndroid Build Coastguard Worker 
6188*5e7646d2SAndroid Build Coastguard Worker 	    match = 0;
6189*5e7646d2SAndroid Build Coastguard Worker 	  }
6190*5e7646d2SAndroid Build Coastguard Worker 	}
6191*5e7646d2SAndroid Build Coastguard Worker 	break;
6192*5e7646d2SAndroid Build Coastguard Worker 
6193*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_NOVALUE :
6194*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_UNKNOWN :
6195*5e7646d2SAndroid Build Coastguard Worker 	return (1);
6196*5e7646d2SAndroid Build Coastguard Worker 
6197*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_CHARSET :
6198*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_KEYWORD :
6199*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_LANGUAGE :
6200*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_MIMETYPE :
6201*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_NAME :
6202*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_NAMELANG :
6203*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_TEXT :
6204*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_TEXTLANG :
6205*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_URISCHEME :
6206*5e7646d2SAndroid Build Coastguard Worker 	for (i = 0; i < count; i ++)
6207*5e7646d2SAndroid Build Coastguard Worker 	{
6208*5e7646d2SAndroid Build Coastguard Worker 	  const char *value = ippGetString(attr, i, NULL);
6209*5e7646d2SAndroid Build Coastguard Worker 					/* Current string value */
6210*5e7646d2SAndroid Build Coastguard Worker 
6211*5e7646d2SAndroid Build Coastguard Worker 	  if (ippContainsString(fromattr, value))
6212*5e7646d2SAndroid Build Coastguard Worker 	  {
6213*5e7646d2SAndroid Build Coastguard Worker 	    if (!matchbuf[0])
6214*5e7646d2SAndroid Build Coastguard Worker 	      strlcpy(matchbuf, value, matchlen);
6215*5e7646d2SAndroid Build Coastguard Worker 	  }
6216*5e7646d2SAndroid Build Coastguard Worker 	  else
6217*5e7646d2SAndroid Build Coastguard Worker 	  {
6218*5e7646d2SAndroid Build Coastguard Worker 	    add_stringf(errors, "GOT: %s='%s'", ippGetName(attr), value);
6219*5e7646d2SAndroid Build Coastguard Worker 	    match = 0;
6220*5e7646d2SAndroid Build Coastguard Worker 	  }
6221*5e7646d2SAndroid Build Coastguard Worker 	}
6222*5e7646d2SAndroid Build Coastguard Worker 	break;
6223*5e7646d2SAndroid Build Coastguard Worker 
6224*5e7646d2SAndroid Build Coastguard Worker     case IPP_TAG_URI :
6225*5e7646d2SAndroid Build Coastguard Worker 	for (i = 0; i < count; i ++)
6226*5e7646d2SAndroid Build Coastguard Worker 	{
6227*5e7646d2SAndroid Build Coastguard Worker 	  const char *value = ippGetString(attr, i, NULL);
6228*5e7646d2SAndroid Build Coastguard Worker 					/* Current string value */
6229*5e7646d2SAndroid Build Coastguard Worker           int fromcount = ippGetCount(fromattr);
6230*5e7646d2SAndroid Build Coastguard Worker 
6231*5e7646d2SAndroid Build Coastguard Worker           for (j = 0; j < fromcount; j ++)
6232*5e7646d2SAndroid Build Coastguard Worker           {
6233*5e7646d2SAndroid Build Coastguard Worker             if (!compare_uris(value, ippGetString(fromattr, j, NULL)))
6234*5e7646d2SAndroid Build Coastguard Worker             {
6235*5e7646d2SAndroid Build Coastguard Worker               if (!matchbuf[0])
6236*5e7646d2SAndroid Build Coastguard Worker                 strlcpy(matchbuf, value, matchlen);
6237*5e7646d2SAndroid Build Coastguard Worker               break;
6238*5e7646d2SAndroid Build Coastguard Worker             }
6239*5e7646d2SAndroid Build Coastguard Worker           }
6240*5e7646d2SAndroid Build Coastguard Worker 
6241*5e7646d2SAndroid Build Coastguard Worker 	  if (j >= fromcount)
6242*5e7646d2SAndroid Build Coastguard Worker 	  {
6243*5e7646d2SAndroid Build Coastguard Worker 	    add_stringf(errors, "GOT: %s='%s'", ippGetName(attr), value);
6244*5e7646d2SAndroid Build Coastguard Worker 	    match = 0;
6245*5e7646d2SAndroid Build Coastguard Worker 	  }
6246*5e7646d2SAndroid Build Coastguard Worker 	}
6247*5e7646d2SAndroid Build Coastguard Worker 	break;
6248*5e7646d2SAndroid Build Coastguard Worker 
6249*5e7646d2SAndroid Build Coastguard Worker     default :
6250*5e7646d2SAndroid Build Coastguard Worker         match = 0;
6251*5e7646d2SAndroid Build Coastguard Worker         break;
6252*5e7646d2SAndroid Build Coastguard Worker   }
6253*5e7646d2SAndroid Build Coastguard Worker 
6254*5e7646d2SAndroid Build Coastguard Worker   return (match);
6255*5e7646d2SAndroid Build Coastguard Worker 
6256*5e7646d2SAndroid Build Coastguard Worker   /* value tag mismatch between fromattr and attr */
6257*5e7646d2SAndroid Build Coastguard Worker   wrong_value_tag :
6258*5e7646d2SAndroid Build Coastguard Worker 
6259*5e7646d2SAndroid Build Coastguard Worker   add_stringf(errors, "GOT: %s OF-TYPE %s", ippGetName(attr), ippTagString(ippGetValueTag(attr)));
6260*5e7646d2SAndroid Build Coastguard Worker 
6261*5e7646d2SAndroid Build Coastguard Worker   return (0);
6262*5e7646d2SAndroid Build Coastguard Worker }
6263