xref: /aosp_15_r20/external/libcups/backend/ipp.c (revision 5e7646d21f1134fb0638875d812ef646c12ab91e)
1*5e7646d2SAndroid Build Coastguard Worker /*
2*5e7646d2SAndroid Build Coastguard Worker  * IPP backend for CUPS.
3*5e7646d2SAndroid Build Coastguard Worker  *
4*5e7646d2SAndroid Build Coastguard Worker  * Copyright © 2021 by OpenPrinting
5*5e7646d2SAndroid Build Coastguard Worker  * Copyright © 2007-2021 by Apple Inc.
6*5e7646d2SAndroid Build Coastguard Worker  * Copyright © 1997-2007 by Easy Software Products, all rights reserved.
7*5e7646d2SAndroid Build Coastguard Worker  *
8*5e7646d2SAndroid Build Coastguard Worker  * Licensed under Apache License v2.0.  See the file "LICENSE" for more
9*5e7646d2SAndroid Build Coastguard Worker  * information.
10*5e7646d2SAndroid Build Coastguard Worker  */
11*5e7646d2SAndroid Build Coastguard Worker 
12*5e7646d2SAndroid Build Coastguard Worker /*
13*5e7646d2SAndroid Build Coastguard Worker  * Include necessary headers.
14*5e7646d2SAndroid Build Coastguard Worker  */
15*5e7646d2SAndroid Build Coastguard Worker 
16*5e7646d2SAndroid Build Coastguard Worker #include "backend-private.h"
17*5e7646d2SAndroid Build Coastguard Worker #include <cups/ppd-private.h>
18*5e7646d2SAndroid Build Coastguard Worker #include <cups/array-private.h>
19*5e7646d2SAndroid Build Coastguard Worker #include <sys/types.h>
20*5e7646d2SAndroid Build Coastguard Worker #include <sys/stat.h>
21*5e7646d2SAndroid Build Coastguard Worker #include <sys/wait.h>
22*5e7646d2SAndroid Build Coastguard Worker #if defined(HAVE_GSSAPI) && defined(HAVE_XPC)
23*5e7646d2SAndroid Build Coastguard Worker #  include <xpc/xpc.h>
24*5e7646d2SAndroid Build Coastguard Worker #  define kPMPrintUIToolAgent	"com.apple.printuitool.agent"
25*5e7646d2SAndroid Build Coastguard Worker #  define kPMStartJob		100
26*5e7646d2SAndroid Build Coastguard Worker #  define kPMWaitForJob		101
27*5e7646d2SAndroid Build Coastguard Worker extern void	xpc_connection_set_target_uid(xpc_connection_t connection,
28*5e7646d2SAndroid Build Coastguard Worker 		                              uid_t uid);
29*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_GSSAPI && HAVE_XPC */
30*5e7646d2SAndroid Build Coastguard Worker 
31*5e7646d2SAndroid Build Coastguard Worker 
32*5e7646d2SAndroid Build Coastguard Worker /*
33*5e7646d2SAndroid Build Coastguard Worker  * Bits for job-state-reasons we care about...
34*5e7646d2SAndroid Build Coastguard Worker  */
35*5e7646d2SAndroid Build Coastguard Worker 
36*5e7646d2SAndroid Build Coastguard Worker #define _CUPS_JSR_ACCOUNT_AUTHORIZATION_FAILED	0x01
37*5e7646d2SAndroid Build Coastguard Worker #define _CUPS_JSR_ACCOUNT_CLOSED		0x02
38*5e7646d2SAndroid Build Coastguard Worker #define _CUPS_JSR_ACCOUNT_INFO_NEEDED		0x04
39*5e7646d2SAndroid Build Coastguard Worker #define _CUPS_JSR_ACCOUNT_LIMIT_REACHED		0x08
40*5e7646d2SAndroid Build Coastguard Worker #define _CUPS_JSR_JOB_PASSWORD_WAIT		0x10
41*5e7646d2SAndroid Build Coastguard Worker #define _CUPS_JSR_JOB_RELEASE_WAIT		0x20
42*5e7646d2SAndroid Build Coastguard Worker #define _CUPS_JSR_DOCUMENT_FORMAT_ERROR		0x40
43*5e7646d2SAndroid Build Coastguard Worker #define _CUPS_JSR_DOCUMENT_UNPRINTABLE		0x80
44*5e7646d2SAndroid Build Coastguard Worker 
45*5e7646d2SAndroid Build Coastguard Worker 
46*5e7646d2SAndroid Build Coastguard Worker /*
47*5e7646d2SAndroid Build Coastguard Worker  * Types...
48*5e7646d2SAndroid Build Coastguard Worker  */
49*5e7646d2SAndroid Build Coastguard Worker 
50*5e7646d2SAndroid Build Coastguard Worker typedef struct _cups_monitor_s		/**** Monitoring data ****/
51*5e7646d2SAndroid Build Coastguard Worker {
52*5e7646d2SAndroid Build Coastguard Worker   const char		*uri,		/* Printer URI */
53*5e7646d2SAndroid Build Coastguard Worker 			*hostname,	/* Hostname */
54*5e7646d2SAndroid Build Coastguard Worker 			*user,		/* Username */
55*5e7646d2SAndroid Build Coastguard Worker 			*resource;	/* Resource path */
56*5e7646d2SAndroid Build Coastguard Worker   int			port,		/* Port number */
57*5e7646d2SAndroid Build Coastguard Worker 			version,	/* IPP version */
58*5e7646d2SAndroid Build Coastguard Worker 			job_id,		/* Job ID for submitted job */
59*5e7646d2SAndroid Build Coastguard Worker 			job_reasons,	/* Job state reasons bits */
60*5e7646d2SAndroid Build Coastguard Worker 			create_job,	/* Support Create-Job? */
61*5e7646d2SAndroid Build Coastguard Worker 			get_job_attrs;	/* Support Get-Job-Attributes? */
62*5e7646d2SAndroid Build Coastguard Worker   const char		*job_name;	/* Job name for submitted job */
63*5e7646d2SAndroid Build Coastguard Worker   http_encryption_t	encryption;	/* Use encryption? */
64*5e7646d2SAndroid Build Coastguard Worker   ipp_jstate_t		job_state;	/* Current job state */
65*5e7646d2SAndroid Build Coastguard Worker   ipp_pstate_t		printer_state;	/* Current printer state */
66*5e7646d2SAndroid Build Coastguard Worker   int			retryable;	/* Is this a job that should be retried? */
67*5e7646d2SAndroid Build Coastguard Worker } _cups_monitor_t;
68*5e7646d2SAndroid Build Coastguard Worker 
69*5e7646d2SAndroid Build Coastguard Worker 
70*5e7646d2SAndroid Build Coastguard Worker /*
71*5e7646d2SAndroid Build Coastguard Worker  * Globals...
72*5e7646d2SAndroid Build Coastguard Worker  */
73*5e7646d2SAndroid Build Coastguard Worker 
74*5e7646d2SAndroid Build Coastguard Worker static const char 	*auth_info_required;
75*5e7646d2SAndroid Build Coastguard Worker 					/* New auth-info-required value */
76*5e7646d2SAndroid Build Coastguard Worker #if defined(HAVE_GSSAPI) && defined(HAVE_XPC)
77*5e7646d2SAndroid Build Coastguard Worker static pid_t		child_pid = 0;	/* Child process ID */
78*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_GSSAPI && HAVE_XPC */
79*5e7646d2SAndroid Build Coastguard Worker static const char * const jattrs[] =	/* Job attributes we want */
80*5e7646d2SAndroid Build Coastguard Worker {
81*5e7646d2SAndroid Build Coastguard Worker   "job-id",
82*5e7646d2SAndroid Build Coastguard Worker   "job-impressions-completed",
83*5e7646d2SAndroid Build Coastguard Worker   "job-media-sheets-completed",
84*5e7646d2SAndroid Build Coastguard Worker   "job-name",
85*5e7646d2SAndroid Build Coastguard Worker   "job-originating-user-name",
86*5e7646d2SAndroid Build Coastguard Worker   "job-state",
87*5e7646d2SAndroid Build Coastguard Worker   "job-state-reasons"
88*5e7646d2SAndroid Build Coastguard Worker };
89*5e7646d2SAndroid Build Coastguard Worker static int		job_canceled = 0,
90*5e7646d2SAndroid Build Coastguard Worker 					/* Job cancelled? */
91*5e7646d2SAndroid Build Coastguard Worker 			uri_credentials = 0;
92*5e7646d2SAndroid Build Coastguard Worker 					/* Credentials supplied in URI? */
93*5e7646d2SAndroid Build Coastguard Worker static char		username[256] = "",
94*5e7646d2SAndroid Build Coastguard Worker 					/* Username for device URI */
95*5e7646d2SAndroid Build Coastguard Worker 			*password = NULL;
96*5e7646d2SAndroid Build Coastguard Worker 					/* Password for device URI */
97*5e7646d2SAndroid Build Coastguard Worker static const char * const pattrs[] =	/* Printer attributes we want */
98*5e7646d2SAndroid Build Coastguard Worker {
99*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_LIBZ
100*5e7646d2SAndroid Build Coastguard Worker   "compression-supported",
101*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_LIBZ */
102*5e7646d2SAndroid Build Coastguard Worker   "copies-supported",
103*5e7646d2SAndroid Build Coastguard Worker   "cups-version",
104*5e7646d2SAndroid Build Coastguard Worker   "document-format-supported",
105*5e7646d2SAndroid Build Coastguard Worker   "job-password-encryption-supported",
106*5e7646d2SAndroid Build Coastguard Worker   "marker-colors",
107*5e7646d2SAndroid Build Coastguard Worker   "marker-high-levels",
108*5e7646d2SAndroid Build Coastguard Worker   "marker-levels",
109*5e7646d2SAndroid Build Coastguard Worker   "marker-low-levels",
110*5e7646d2SAndroid Build Coastguard Worker   "marker-message",
111*5e7646d2SAndroid Build Coastguard Worker   "marker-names",
112*5e7646d2SAndroid Build Coastguard Worker   "marker-types",
113*5e7646d2SAndroid Build Coastguard Worker   "media-col-supported",
114*5e7646d2SAndroid Build Coastguard Worker   "multiple-document-handling-supported",
115*5e7646d2SAndroid Build Coastguard Worker   "operations-supported",
116*5e7646d2SAndroid Build Coastguard Worker   "print-color-mode-supported",
117*5e7646d2SAndroid Build Coastguard Worker   "printer-alert",
118*5e7646d2SAndroid Build Coastguard Worker   "printer-alert-description",
119*5e7646d2SAndroid Build Coastguard Worker   "printer-is-accepting-jobs",
120*5e7646d2SAndroid Build Coastguard Worker   "printer-mandatory-job-attributes",
121*5e7646d2SAndroid Build Coastguard Worker   "printer-state",
122*5e7646d2SAndroid Build Coastguard Worker   "printer-state-message",
123*5e7646d2SAndroid Build Coastguard Worker   "printer-state-reasons"
124*5e7646d2SAndroid Build Coastguard Worker };
125*5e7646d2SAndroid Build Coastguard Worker static const char * const remote_job_states[] =
126*5e7646d2SAndroid Build Coastguard Worker {					/* Remote job state keywords */
127*5e7646d2SAndroid Build Coastguard Worker   "+cups-remote-pending",
128*5e7646d2SAndroid Build Coastguard Worker   "+cups-remote-pending-held",
129*5e7646d2SAndroid Build Coastguard Worker   "+cups-remote-processing",
130*5e7646d2SAndroid Build Coastguard Worker   "+cups-remote-stopped",
131*5e7646d2SAndroid Build Coastguard Worker   "+cups-remote-canceled",
132*5e7646d2SAndroid Build Coastguard Worker   "+cups-remote-aborted",
133*5e7646d2SAndroid Build Coastguard Worker   "+cups-remote-completed"
134*5e7646d2SAndroid Build Coastguard Worker };
135*5e7646d2SAndroid Build Coastguard Worker static _cups_mutex_t	report_mutex = _CUPS_MUTEX_INITIALIZER;
136*5e7646d2SAndroid Build Coastguard Worker 					/* Mutex to control access */
137*5e7646d2SAndroid Build Coastguard Worker static int		num_attr_cache = 0;
138*5e7646d2SAndroid Build Coastguard Worker 					/* Number of cached attributes */
139*5e7646d2SAndroid Build Coastguard Worker static cups_option_t	*attr_cache = NULL;
140*5e7646d2SAndroid Build Coastguard Worker 					/* Cached attributes */
141*5e7646d2SAndroid Build Coastguard Worker static cups_array_t	*state_reasons;	/* Array of printe-state-reasons keywords */
142*5e7646d2SAndroid Build Coastguard Worker static char		tmpfilename[1024] = "";
143*5e7646d2SAndroid Build Coastguard Worker 					/* Temporary spool file name */
144*5e7646d2SAndroid Build Coastguard Worker static char		mandatory_attrs[1024] = "";
145*5e7646d2SAndroid Build Coastguard Worker 					/* cupsMandatory value */
146*5e7646d2SAndroid Build Coastguard Worker 
147*5e7646d2SAndroid Build Coastguard Worker 
148*5e7646d2SAndroid Build Coastguard Worker /*
149*5e7646d2SAndroid Build Coastguard Worker  * Local functions...
150*5e7646d2SAndroid Build Coastguard Worker  */
151*5e7646d2SAndroid Build Coastguard Worker 
152*5e7646d2SAndroid Build Coastguard Worker static void		cancel_job(http_t *http, const char *uri, int id,
153*5e7646d2SAndroid Build Coastguard Worker 			           const char *resource, const char *user,
154*5e7646d2SAndroid Build Coastguard Worker 				   int version);
155*5e7646d2SAndroid Build Coastguard Worker static ipp_pstate_t	check_printer_state(http_t *http, const char *uri,
156*5e7646d2SAndroid Build Coastguard Worker 		                            const char *resource,
157*5e7646d2SAndroid Build Coastguard Worker 					    const char *user, int version);
158*5e7646d2SAndroid Build Coastguard Worker static void		debug_attributes(ipp_t *ipp);
159*5e7646d2SAndroid Build Coastguard Worker static void		*monitor_printer(_cups_monitor_t *monitor);
160*5e7646d2SAndroid Build Coastguard Worker static ipp_t		*new_request(ipp_op_t op, int version, const char *uri,
161*5e7646d2SAndroid Build Coastguard Worker 			             const char *user, const char *title,
162*5e7646d2SAndroid Build Coastguard Worker 				     int num_options, cups_option_t *options,
163*5e7646d2SAndroid Build Coastguard Worker 				     const char *compression, int copies,
164*5e7646d2SAndroid Build Coastguard Worker 				     const char *format, _ppd_cache_t *pc,
165*5e7646d2SAndroid Build Coastguard Worker 				     ppd_file_t *ppd,
166*5e7646d2SAndroid Build Coastguard Worker 				     ipp_attribute_t *media_col_sup,
167*5e7646d2SAndroid Build Coastguard Worker 				     ipp_attribute_t *doc_handling_sup,
168*5e7646d2SAndroid Build Coastguard Worker 				     ipp_attribute_t *print_color_mode_sup);
169*5e7646d2SAndroid Build Coastguard Worker static const char	*password_cb(const char *prompt, http_t *http,
170*5e7646d2SAndroid Build Coastguard Worker 			             const char *method, const char *resource,
171*5e7646d2SAndroid Build Coastguard Worker 			             int *user_data);
172*5e7646d2SAndroid Build Coastguard Worker static const char	*quote_string(const char *s, char *q, size_t qsize);
173*5e7646d2SAndroid Build Coastguard Worker static void		report_attr(ipp_attribute_t *attr);
174*5e7646d2SAndroid Build Coastguard Worker static void		report_printer_state(ipp_t *ipp);
175*5e7646d2SAndroid Build Coastguard Worker #if defined(HAVE_GSSAPI) && defined(HAVE_XPC)
176*5e7646d2SAndroid Build Coastguard Worker static int		run_as_user(char *argv[], uid_t uid,
177*5e7646d2SAndroid Build Coastguard Worker 			            const char *device_uri, int fd);
178*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_GSSAPI && HAVE_XPC */
179*5e7646d2SAndroid Build Coastguard Worker static void		sigterm_handler(int sig);
180*5e7646d2SAndroid Build Coastguard Worker static int		timeout_cb(http_t *http, void *user_data);
181*5e7646d2SAndroid Build Coastguard Worker static void		update_reasons(ipp_attribute_t *attr, const char *s);
182*5e7646d2SAndroid Build Coastguard Worker 
183*5e7646d2SAndroid Build Coastguard Worker 
184*5e7646d2SAndroid Build Coastguard Worker /*
185*5e7646d2SAndroid Build Coastguard Worker  * 'main()' - Send a file to the printer or server.
186*5e7646d2SAndroid Build Coastguard Worker  *
187*5e7646d2SAndroid Build Coastguard Worker  * Usage:
188*5e7646d2SAndroid Build Coastguard Worker  *
189*5e7646d2SAndroid Build Coastguard Worker  *    printer-uri job-id user title copies options [file]
190*5e7646d2SAndroid Build Coastguard Worker  */
191*5e7646d2SAndroid Build Coastguard Worker 
192*5e7646d2SAndroid Build Coastguard Worker int					/* O - Exit status */
main(int argc,char * argv[])193*5e7646d2SAndroid Build Coastguard Worker main(int  argc,				/* I - Number of command-line args */
194*5e7646d2SAndroid Build Coastguard Worker      char *argv[])			/* I - Command-line arguments */
195*5e7646d2SAndroid Build Coastguard Worker {
196*5e7646d2SAndroid Build Coastguard Worker   int		i;			/* Looping var */
197*5e7646d2SAndroid Build Coastguard Worker   int		send_options;		/* Send job options? */
198*5e7646d2SAndroid Build Coastguard Worker   int		num_options;		/* Number of printer options */
199*5e7646d2SAndroid Build Coastguard Worker   cups_option_t	*options;		/* Printer options */
200*5e7646d2SAndroid Build Coastguard Worker   const char	*device_uri;		/* Device URI */
201*5e7646d2SAndroid Build Coastguard Worker   char		scheme[255],		/* Scheme in URI */
202*5e7646d2SAndroid Build Coastguard Worker 		hostname[1024],		/* Hostname */
203*5e7646d2SAndroid Build Coastguard Worker 		resource[1024],		/* Resource info (printer name) */
204*5e7646d2SAndroid Build Coastguard Worker 		addrname[256],		/* Address name */
205*5e7646d2SAndroid Build Coastguard Worker 		*optptr,		/* Pointer to URI options */
206*5e7646d2SAndroid Build Coastguard Worker 		*name,			/* Name of option */
207*5e7646d2SAndroid Build Coastguard Worker 		*value,			/* Value of option */
208*5e7646d2SAndroid Build Coastguard Worker 		sep;			/* Separator character */
209*5e7646d2SAndroid Build Coastguard Worker   int		password_tries = 0;	/* Password tries */
210*5e7646d2SAndroid Build Coastguard Worker   http_addrlist_t *addrlist;		/* Address of printer */
211*5e7646d2SAndroid Build Coastguard Worker   int		snmp_enabled = 1;	/* Is SNMP enabled? */
212*5e7646d2SAndroid Build Coastguard Worker   int		snmp_fd,		/* SNMP socket */
213*5e7646d2SAndroid Build Coastguard Worker 		start_count,		/* Page count via SNMP at start */
214*5e7646d2SAndroid Build Coastguard Worker 		page_count,		/* Page count via SNMP */
215*5e7646d2SAndroid Build Coastguard Worker 		have_supplies;		/* Printer supports supply levels? */
216*5e7646d2SAndroid Build Coastguard Worker   int		num_files;		/* Number of files to print */
217*5e7646d2SAndroid Build Coastguard Worker   char		**files,		/* Files to print */
218*5e7646d2SAndroid Build Coastguard Worker 		*compatfile = NULL;	/* Compatibility filename */
219*5e7646d2SAndroid Build Coastguard Worker   off_t		compatsize = 0;		/* Size of compatibility file */
220*5e7646d2SAndroid Build Coastguard Worker   int		port;			/* Port number (not used) */
221*5e7646d2SAndroid Build Coastguard Worker   char		uri[HTTP_MAX_URI];	/* Updated URI without user/pass */
222*5e7646d2SAndroid Build Coastguard Worker   char		print_job_name[1024];	/* Update job-name for Print-Job */
223*5e7646d2SAndroid Build Coastguard Worker   http_status_t	http_status;		/* Status of HTTP request */
224*5e7646d2SAndroid Build Coastguard Worker   ipp_status_t	ipp_status;		/* Status of IPP request */
225*5e7646d2SAndroid Build Coastguard Worker   http_t	*http;			/* HTTP connection */
226*5e7646d2SAndroid Build Coastguard Worker   ipp_t		*request,		/* IPP request */
227*5e7646d2SAndroid Build Coastguard Worker 		*response,		/* IPP response */
228*5e7646d2SAndroid Build Coastguard Worker 		*supported;		/* get-printer-attributes response */
229*5e7646d2SAndroid Build Coastguard Worker   time_t	start_time;		/* Time of first connect */
230*5e7646d2SAndroid Build Coastguard Worker   int		contimeout;		/* Connection timeout */
231*5e7646d2SAndroid Build Coastguard Worker   int		delay,			/* Delay for retries */
232*5e7646d2SAndroid Build Coastguard Worker 		prev_delay;		/* Previous delay */
233*5e7646d2SAndroid Build Coastguard Worker   const char	*compression;		/* Compression mode */
234*5e7646d2SAndroid Build Coastguard Worker   int		waitjob,			/* Wait for job complete? */
235*5e7646d2SAndroid Build Coastguard Worker 		waitjob_tries = 0,	/* Number of times we've waited */
236*5e7646d2SAndroid Build Coastguard Worker 		waitprinter;		/* Wait for printer ready? */
237*5e7646d2SAndroid Build Coastguard Worker   _cups_monitor_t monitor;		/* Monitoring data */
238*5e7646d2SAndroid Build Coastguard Worker   ipp_attribute_t *job_id_attr;		/* job-id attribute */
239*5e7646d2SAndroid Build Coastguard Worker   int		job_id;			/* job-id value */
240*5e7646d2SAndroid Build Coastguard Worker   ipp_attribute_t *job_sheets;		/* job-media-sheets-completed */
241*5e7646d2SAndroid Build Coastguard Worker   ipp_attribute_t *job_state;		/* job-state */
242*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_LIBZ
243*5e7646d2SAndroid Build Coastguard Worker   ipp_attribute_t *compression_sup;	/* compression-supported */
244*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_LIBZ */
245*5e7646d2SAndroid Build Coastguard Worker   ipp_attribute_t *copies_sup;		/* copies-supported */
246*5e7646d2SAndroid Build Coastguard Worker   ipp_attribute_t *cups_version;	/* cups-version */
247*5e7646d2SAndroid Build Coastguard Worker   ipp_attribute_t *encryption_sup;	/* job-password-encryption-supported */
248*5e7646d2SAndroid Build Coastguard Worker   ipp_attribute_t *format_sup;		/* document-format-supported */
249*5e7646d2SAndroid Build Coastguard Worker   ipp_attribute_t *job_auth;		/* job-authorization-uri */
250*5e7646d2SAndroid Build Coastguard Worker   ipp_attribute_t *media_col_sup;	/* media-col-supported */
251*5e7646d2SAndroid Build Coastguard Worker   ipp_attribute_t *operations_sup;	/* operations-supported */
252*5e7646d2SAndroid Build Coastguard Worker   ipp_attribute_t *doc_handling_sup;	/* multiple-document-handling-supported */
253*5e7646d2SAndroid Build Coastguard Worker   ipp_attribute_t *printer_state;	/* printer-state attribute */
254*5e7646d2SAndroid Build Coastguard Worker   ipp_attribute_t *printer_accepting;	/* printer-is-accepting-jobs */
255*5e7646d2SAndroid Build Coastguard Worker   ipp_attribute_t *print_color_mode_sup;/* Does printer support print-color-mode? */
256*5e7646d2SAndroid Build Coastguard Worker   int		create_job = 0,		/* Does printer support Create-Job? */
257*5e7646d2SAndroid Build Coastguard Worker 		get_job_attrs = 0,	/* Does printer support Get-Job-Attributes? */
258*5e7646d2SAndroid Build Coastguard Worker 		send_document = 0,	/* Does printer support Send-Document? */
259*5e7646d2SAndroid Build Coastguard Worker 		validate_job = 0,	/* Does printer support Validate-Job? */
260*5e7646d2SAndroid Build Coastguard Worker 		validate_retried = 0,	/* Was Validate-Job request retried? */
261*5e7646d2SAndroid Build Coastguard Worker 		copies,			/* Number of copies for job */
262*5e7646d2SAndroid Build Coastguard Worker 		copies_remaining;	/* Number of copies remaining */
263*5e7646d2SAndroid Build Coastguard Worker   const char	*content_type,		/* CONTENT_TYPE environment variable */
264*5e7646d2SAndroid Build Coastguard Worker 		*final_content_type,	/* FINAL_CONTENT_TYPE environment var */
265*5e7646d2SAndroid Build Coastguard Worker 		*document_format;	/* document-format value */
266*5e7646d2SAndroid Build Coastguard Worker   int		fd;			/* File descriptor */
267*5e7646d2SAndroid Build Coastguard Worker   off_t		bytes = 0;		/* Bytes copied */
268*5e7646d2SAndroid Build Coastguard Worker   char		buffer[16384];		/* Copy buffer */
269*5e7646d2SAndroid Build Coastguard Worker #if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
270*5e7646d2SAndroid Build Coastguard Worker   struct sigaction action;		/* Actions for POSIX signals */
271*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_SIGACTION && !HAVE_SIGSET */
272*5e7646d2SAndroid Build Coastguard Worker   int		version;		/* IPP version */
273*5e7646d2SAndroid Build Coastguard Worker   ppd_file_t	*ppd = NULL;		/* PPD file */
274*5e7646d2SAndroid Build Coastguard Worker   _ppd_cache_t	*pc = NULL;		/* PPD cache and mapping data */
275*5e7646d2SAndroid Build Coastguard Worker   fd_set	input;			/* Input set for select() */
276*5e7646d2SAndroid Build Coastguard Worker 
277*5e7646d2SAndroid Build Coastguard Worker 
278*5e7646d2SAndroid Build Coastguard Worker  /*
279*5e7646d2SAndroid Build Coastguard Worker   * Make sure status messages are not buffered...
280*5e7646d2SAndroid Build Coastguard Worker   */
281*5e7646d2SAndroid Build Coastguard Worker 
282*5e7646d2SAndroid Build Coastguard Worker   setbuf(stderr, NULL);
283*5e7646d2SAndroid Build Coastguard Worker 
284*5e7646d2SAndroid Build Coastguard Worker  /*
285*5e7646d2SAndroid Build Coastguard Worker   * Ignore SIGPIPE and catch SIGTERM signals...
286*5e7646d2SAndroid Build Coastguard Worker   */
287*5e7646d2SAndroid Build Coastguard Worker 
288*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_SIGSET
289*5e7646d2SAndroid Build Coastguard Worker   sigset(SIGPIPE, SIG_IGN);
290*5e7646d2SAndroid Build Coastguard Worker   sigset(SIGTERM, sigterm_handler);
291*5e7646d2SAndroid Build Coastguard Worker #elif defined(HAVE_SIGACTION)
292*5e7646d2SAndroid Build Coastguard Worker   memset(&action, 0, sizeof(action));
293*5e7646d2SAndroid Build Coastguard Worker   action.sa_handler = SIG_IGN;
294*5e7646d2SAndroid Build Coastguard Worker   sigaction(SIGPIPE, &action, NULL);
295*5e7646d2SAndroid Build Coastguard Worker 
296*5e7646d2SAndroid Build Coastguard Worker   sigemptyset(&action.sa_mask);
297*5e7646d2SAndroid Build Coastguard Worker   sigaddset(&action.sa_mask, SIGTERM);
298*5e7646d2SAndroid Build Coastguard Worker   action.sa_handler = sigterm_handler;
299*5e7646d2SAndroid Build Coastguard Worker   sigaction(SIGTERM, &action, NULL);
300*5e7646d2SAndroid Build Coastguard Worker #else
301*5e7646d2SAndroid Build Coastguard Worker   signal(SIGPIPE, SIG_IGN);
302*5e7646d2SAndroid Build Coastguard Worker   signal(SIGTERM, sigterm_handler);
303*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_SIGSET */
304*5e7646d2SAndroid Build Coastguard Worker 
305*5e7646d2SAndroid Build Coastguard Worker  /*
306*5e7646d2SAndroid Build Coastguard Worker   * Check command-line...
307*5e7646d2SAndroid Build Coastguard Worker   */
308*5e7646d2SAndroid Build Coastguard Worker 
309*5e7646d2SAndroid Build Coastguard Worker   if (argc == 1)
310*5e7646d2SAndroid Build Coastguard Worker   {
311*5e7646d2SAndroid Build Coastguard Worker     char *s;
312*5e7646d2SAndroid Build Coastguard Worker 
313*5e7646d2SAndroid Build Coastguard Worker     if ((s = strrchr(argv[0], '/')) != NULL)
314*5e7646d2SAndroid Build Coastguard Worker       s ++;
315*5e7646d2SAndroid Build Coastguard Worker     else
316*5e7646d2SAndroid Build Coastguard Worker       s = argv[0];
317*5e7646d2SAndroid Build Coastguard Worker 
318*5e7646d2SAndroid Build Coastguard Worker     printf("network %s \"Unknown\" \"%s (%s)\"\n",
319*5e7646d2SAndroid Build Coastguard Worker            s, _cupsLangString(cupsLangDefault(),
320*5e7646d2SAndroid Build Coastguard Worker 	                      _("Internet Printing Protocol")), s);
321*5e7646d2SAndroid Build Coastguard Worker     return (CUPS_BACKEND_OK);
322*5e7646d2SAndroid Build Coastguard Worker   }
323*5e7646d2SAndroid Build Coastguard Worker   else if (argc < 6)
324*5e7646d2SAndroid Build Coastguard Worker   {
325*5e7646d2SAndroid Build Coastguard Worker     _cupsLangPrintf(stderr,
326*5e7646d2SAndroid Build Coastguard Worker                     _("Usage: %s job-id user title copies options [file]"),
327*5e7646d2SAndroid Build Coastguard Worker 		    argv[0]);
328*5e7646d2SAndroid Build Coastguard Worker     return (CUPS_BACKEND_STOP);
329*5e7646d2SAndroid Build Coastguard Worker   }
330*5e7646d2SAndroid Build Coastguard Worker 
331*5e7646d2SAndroid Build Coastguard Worker  /*
332*5e7646d2SAndroid Build Coastguard Worker   * Get the device URI...
333*5e7646d2SAndroid Build Coastguard Worker   */
334*5e7646d2SAndroid Build Coastguard Worker 
335*5e7646d2SAndroid Build Coastguard Worker   while ((device_uri = cupsBackendDeviceURI(argv)) == NULL)
336*5e7646d2SAndroid Build Coastguard Worker   {
337*5e7646d2SAndroid Build Coastguard Worker     _cupsLangPrintFilter(stderr, "INFO", _("Unable to locate printer."));
338*5e7646d2SAndroid Build Coastguard Worker     sleep(10);
339*5e7646d2SAndroid Build Coastguard Worker 
340*5e7646d2SAndroid Build Coastguard Worker     if (getenv("CLASS") != NULL)
341*5e7646d2SAndroid Build Coastguard Worker       return (CUPS_BACKEND_FAILED);
342*5e7646d2SAndroid Build Coastguard Worker   }
343*5e7646d2SAndroid Build Coastguard Worker 
344*5e7646d2SAndroid Build Coastguard Worker   if ((auth_info_required = getenv("AUTH_INFO_REQUIRED")) == NULL)
345*5e7646d2SAndroid Build Coastguard Worker     auth_info_required = "none";
346*5e7646d2SAndroid Build Coastguard Worker 
347*5e7646d2SAndroid Build Coastguard Worker   state_reasons = _cupsArrayNewStrings(getenv("PRINTER_STATE_REASONS"), ',');
348*5e7646d2SAndroid Build Coastguard Worker 
349*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_GSSAPI
350*5e7646d2SAndroid Build Coastguard Worker  /*
351*5e7646d2SAndroid Build Coastguard Worker   * For Kerberos, become the printing user (if we can) to get the credentials
352*5e7646d2SAndroid Build Coastguard Worker   * that way.
353*5e7646d2SAndroid Build Coastguard Worker   */
354*5e7646d2SAndroid Build Coastguard Worker 
355*5e7646d2SAndroid Build Coastguard Worker   if (!getuid() && (value = getenv("AUTH_UID")) != NULL)
356*5e7646d2SAndroid Build Coastguard Worker   {
357*5e7646d2SAndroid Build Coastguard Worker     uid_t	uid = (uid_t)atoi(value);
358*5e7646d2SAndroid Build Coastguard Worker 					/* User ID */
359*5e7646d2SAndroid Build Coastguard Worker 
360*5e7646d2SAndroid Build Coastguard Worker #  ifdef HAVE_XPC
361*5e7646d2SAndroid Build Coastguard Worker     if (uid > 0)
362*5e7646d2SAndroid Build Coastguard Worker     {
363*5e7646d2SAndroid Build Coastguard Worker       if (argc == 6)
364*5e7646d2SAndroid Build Coastguard Worker         return (run_as_user(argv, uid, device_uri, 0));
365*5e7646d2SAndroid Build Coastguard Worker       else
366*5e7646d2SAndroid Build Coastguard Worker       {
367*5e7646d2SAndroid Build Coastguard Worker         int status = 0;			/* Exit status */
368*5e7646d2SAndroid Build Coastguard Worker 
369*5e7646d2SAndroid Build Coastguard Worker         for (i = 6; i < argc && !status && !job_canceled; i ++)
370*5e7646d2SAndroid Build Coastguard Worker 	{
371*5e7646d2SAndroid Build Coastguard Worker 	  if ((fd = open(argv[i], O_RDONLY)) >= 0)
372*5e7646d2SAndroid Build Coastguard Worker 	  {
373*5e7646d2SAndroid Build Coastguard Worker 	    status = run_as_user(argv, uid, device_uri, fd);
374*5e7646d2SAndroid Build Coastguard Worker 	    close(fd);
375*5e7646d2SAndroid Build Coastguard Worker 	  }
376*5e7646d2SAndroid Build Coastguard Worker 	  else
377*5e7646d2SAndroid Build Coastguard Worker 	  {
378*5e7646d2SAndroid Build Coastguard Worker 	    _cupsLangPrintError("ERROR", _("Unable to open print file"));
379*5e7646d2SAndroid Build Coastguard Worker 	    status = CUPS_BACKEND_FAILED;
380*5e7646d2SAndroid Build Coastguard Worker 	  }
381*5e7646d2SAndroid Build Coastguard Worker 	}
382*5e7646d2SAndroid Build Coastguard Worker 
383*5e7646d2SAndroid Build Coastguard Worker 	return (status);
384*5e7646d2SAndroid Build Coastguard Worker       }
385*5e7646d2SAndroid Build Coastguard Worker     }
386*5e7646d2SAndroid Build Coastguard Worker 
387*5e7646d2SAndroid Build Coastguard Worker #  else /* No XPC, just try to run as the user ID */
388*5e7646d2SAndroid Build Coastguard Worker     if (uid > 0)
389*5e7646d2SAndroid Build Coastguard Worker       setuid(uid);
390*5e7646d2SAndroid Build Coastguard Worker #  endif /* HAVE_XPC */
391*5e7646d2SAndroid Build Coastguard Worker   }
392*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_GSSAPI */
393*5e7646d2SAndroid Build Coastguard Worker 
394*5e7646d2SAndroid Build Coastguard Worker  /*
395*5e7646d2SAndroid Build Coastguard Worker   * Get the (final) content type...
396*5e7646d2SAndroid Build Coastguard Worker   */
397*5e7646d2SAndroid Build Coastguard Worker 
398*5e7646d2SAndroid Build Coastguard Worker   if ((content_type = getenv("CONTENT_TYPE")) == NULL)
399*5e7646d2SAndroid Build Coastguard Worker     content_type = "application/octet-stream";
400*5e7646d2SAndroid Build Coastguard Worker 
401*5e7646d2SAndroid Build Coastguard Worker   if ((final_content_type = getenv("FINAL_CONTENT_TYPE")) == NULL)
402*5e7646d2SAndroid Build Coastguard Worker   {
403*5e7646d2SAndroid Build Coastguard Worker     final_content_type = content_type;
404*5e7646d2SAndroid Build Coastguard Worker 
405*5e7646d2SAndroid Build Coastguard Worker     if (!strncmp(final_content_type, "printer/", 8))
406*5e7646d2SAndroid Build Coastguard Worker       final_content_type = "application/vnd.cups-raw";
407*5e7646d2SAndroid Build Coastguard Worker   }
408*5e7646d2SAndroid Build Coastguard Worker 
409*5e7646d2SAndroid Build Coastguard Worker  /*
410*5e7646d2SAndroid Build Coastguard Worker   * Extract the hostname and printer name from the URI...
411*5e7646d2SAndroid Build Coastguard Worker   */
412*5e7646d2SAndroid Build Coastguard Worker 
413*5e7646d2SAndroid Build Coastguard Worker   httpSeparateURI(HTTP_URI_CODING_ALL, device_uri, scheme, sizeof(scheme),
414*5e7646d2SAndroid Build Coastguard Worker                   username, sizeof(username), hostname, sizeof(hostname), &port,
415*5e7646d2SAndroid Build Coastguard Worker 		  resource, sizeof(resource));
416*5e7646d2SAndroid Build Coastguard Worker 
417*5e7646d2SAndroid Build Coastguard Worker   if (!port)
418*5e7646d2SAndroid Build Coastguard Worker     port = IPP_PORT;			/* Default to port 631 */
419*5e7646d2SAndroid Build Coastguard Worker 
420*5e7646d2SAndroid Build Coastguard Worker   if (!strcmp(scheme, "https") || !strcmp(scheme, "ipps"))
421*5e7646d2SAndroid Build Coastguard Worker     cupsSetEncryption(HTTP_ENCRYPTION_ALWAYS);
422*5e7646d2SAndroid Build Coastguard Worker   else
423*5e7646d2SAndroid Build Coastguard Worker     cupsSetEncryption(HTTP_ENCRYPTION_IF_REQUESTED);
424*5e7646d2SAndroid Build Coastguard Worker 
425*5e7646d2SAndroid Build Coastguard Worker  /*
426*5e7646d2SAndroid Build Coastguard Worker   * See if there are any options...
427*5e7646d2SAndroid Build Coastguard Worker   */
428*5e7646d2SAndroid Build Coastguard Worker 
429*5e7646d2SAndroid Build Coastguard Worker   compression = NULL;
430*5e7646d2SAndroid Build Coastguard Worker   version     = 20;
431*5e7646d2SAndroid Build Coastguard Worker   waitjob     = 1;
432*5e7646d2SAndroid Build Coastguard Worker   waitprinter = 1;
433*5e7646d2SAndroid Build Coastguard Worker   contimeout  = 7 * 24 * 60 * 60;
434*5e7646d2SAndroid Build Coastguard Worker 
435*5e7646d2SAndroid Build Coastguard Worker   if ((optptr = strchr(resource, '?')) != NULL)
436*5e7646d2SAndroid Build Coastguard Worker   {
437*5e7646d2SAndroid Build Coastguard Worker    /*
438*5e7646d2SAndroid Build Coastguard Worker     * Yup, terminate the device name string and move to the first
439*5e7646d2SAndroid Build Coastguard Worker     * character of the optptr...
440*5e7646d2SAndroid Build Coastguard Worker     */
441*5e7646d2SAndroid Build Coastguard Worker 
442*5e7646d2SAndroid Build Coastguard Worker     *optptr++ = '\0';
443*5e7646d2SAndroid Build Coastguard Worker 
444*5e7646d2SAndroid Build Coastguard Worker    /*
445*5e7646d2SAndroid Build Coastguard Worker     * Then parse the optptr...
446*5e7646d2SAndroid Build Coastguard Worker     */
447*5e7646d2SAndroid Build Coastguard Worker 
448*5e7646d2SAndroid Build Coastguard Worker     while (*optptr)
449*5e7646d2SAndroid Build Coastguard Worker     {
450*5e7646d2SAndroid Build Coastguard Worker      /*
451*5e7646d2SAndroid Build Coastguard Worker       * Get the name...
452*5e7646d2SAndroid Build Coastguard Worker       */
453*5e7646d2SAndroid Build Coastguard Worker 
454*5e7646d2SAndroid Build Coastguard Worker       name = optptr;
455*5e7646d2SAndroid Build Coastguard Worker 
456*5e7646d2SAndroid Build Coastguard Worker       while (*optptr && *optptr != '=' && *optptr != '+' && *optptr != '&')
457*5e7646d2SAndroid Build Coastguard Worker         optptr ++;
458*5e7646d2SAndroid Build Coastguard Worker 
459*5e7646d2SAndroid Build Coastguard Worker       if ((sep = *optptr) != '\0')
460*5e7646d2SAndroid Build Coastguard Worker         *optptr++ = '\0';
461*5e7646d2SAndroid Build Coastguard Worker 
462*5e7646d2SAndroid Build Coastguard Worker       if (sep == '=')
463*5e7646d2SAndroid Build Coastguard Worker       {
464*5e7646d2SAndroid Build Coastguard Worker        /*
465*5e7646d2SAndroid Build Coastguard Worker         * Get the value...
466*5e7646d2SAndroid Build Coastguard Worker 	*/
467*5e7646d2SAndroid Build Coastguard Worker 
468*5e7646d2SAndroid Build Coastguard Worker         value = optptr;
469*5e7646d2SAndroid Build Coastguard Worker 
470*5e7646d2SAndroid Build Coastguard Worker 	while (*optptr && *optptr != '+' && *optptr != '&')
471*5e7646d2SAndroid Build Coastguard Worker 	  optptr ++;
472*5e7646d2SAndroid Build Coastguard Worker 
473*5e7646d2SAndroid Build Coastguard Worker         if (*optptr)
474*5e7646d2SAndroid Build Coastguard Worker 	  *optptr++ = '\0';
475*5e7646d2SAndroid Build Coastguard Worker       }
476*5e7646d2SAndroid Build Coastguard Worker       else
477*5e7646d2SAndroid Build Coastguard Worker         value = (char *)"";
478*5e7646d2SAndroid Build Coastguard Worker 
479*5e7646d2SAndroid Build Coastguard Worker      /*
480*5e7646d2SAndroid Build Coastguard Worker       * Process the option...
481*5e7646d2SAndroid Build Coastguard Worker       */
482*5e7646d2SAndroid Build Coastguard Worker 
483*5e7646d2SAndroid Build Coastguard Worker       if (!_cups_strcasecmp(name, "waitjob"))
484*5e7646d2SAndroid Build Coastguard Worker       {
485*5e7646d2SAndroid Build Coastguard Worker        /*
486*5e7646d2SAndroid Build Coastguard Worker         * Wait for job completion?
487*5e7646d2SAndroid Build Coastguard Worker 	*/
488*5e7646d2SAndroid Build Coastguard Worker 
489*5e7646d2SAndroid Build Coastguard Worker         waitjob = !_cups_strcasecmp(value, "on") ||
490*5e7646d2SAndroid Build Coastguard Worker 	          !_cups_strcasecmp(value, "yes") ||
491*5e7646d2SAndroid Build Coastguard Worker 	          !_cups_strcasecmp(value, "true");
492*5e7646d2SAndroid Build Coastguard Worker       }
493*5e7646d2SAndroid Build Coastguard Worker       else if (!_cups_strcasecmp(name, "waitprinter"))
494*5e7646d2SAndroid Build Coastguard Worker       {
495*5e7646d2SAndroid Build Coastguard Worker        /*
496*5e7646d2SAndroid Build Coastguard Worker         * Wait for printer idle?
497*5e7646d2SAndroid Build Coastguard Worker 	*/
498*5e7646d2SAndroid Build Coastguard Worker 
499*5e7646d2SAndroid Build Coastguard Worker         waitprinter = !_cups_strcasecmp(value, "on") ||
500*5e7646d2SAndroid Build Coastguard Worker 	              !_cups_strcasecmp(value, "yes") ||
501*5e7646d2SAndroid Build Coastguard Worker 	              !_cups_strcasecmp(value, "true");
502*5e7646d2SAndroid Build Coastguard Worker       }
503*5e7646d2SAndroid Build Coastguard Worker       else if (!_cups_strcasecmp(name, "encryption"))
504*5e7646d2SAndroid Build Coastguard Worker       {
505*5e7646d2SAndroid Build Coastguard Worker        /*
506*5e7646d2SAndroid Build Coastguard Worker         * Enable/disable encryption?
507*5e7646d2SAndroid Build Coastguard Worker 	*/
508*5e7646d2SAndroid Build Coastguard Worker 
509*5e7646d2SAndroid Build Coastguard Worker         if (!_cups_strcasecmp(value, "always"))
510*5e7646d2SAndroid Build Coastguard Worker 	  cupsSetEncryption(HTTP_ENCRYPTION_ALWAYS);
511*5e7646d2SAndroid Build Coastguard Worker         else if (!_cups_strcasecmp(value, "required"))
512*5e7646d2SAndroid Build Coastguard Worker 	  cupsSetEncryption(HTTP_ENCRYPTION_REQUIRED);
513*5e7646d2SAndroid Build Coastguard Worker         else if (!_cups_strcasecmp(value, "never"))
514*5e7646d2SAndroid Build Coastguard Worker 	  cupsSetEncryption(HTTP_ENCRYPTION_NEVER);
515*5e7646d2SAndroid Build Coastguard Worker         else if (!_cups_strcasecmp(value, "ifrequested"))
516*5e7646d2SAndroid Build Coastguard Worker 	  cupsSetEncryption(HTTP_ENCRYPTION_IF_REQUESTED);
517*5e7646d2SAndroid Build Coastguard Worker 	else
518*5e7646d2SAndroid Build Coastguard Worker 	{
519*5e7646d2SAndroid Build Coastguard Worker 	  _cupsLangPrintFilter(stderr, "ERROR",
520*5e7646d2SAndroid Build Coastguard Worker 			       _("Unknown encryption option value: \"%s\"."),
521*5e7646d2SAndroid Build Coastguard Worker 			       value);
522*5e7646d2SAndroid Build Coastguard Worker         }
523*5e7646d2SAndroid Build Coastguard Worker       }
524*5e7646d2SAndroid Build Coastguard Worker       else if (!_cups_strcasecmp(name, "snmp"))
525*5e7646d2SAndroid Build Coastguard Worker       {
526*5e7646d2SAndroid Build Coastguard Worker         /*
527*5e7646d2SAndroid Build Coastguard Worker          * Enable/disable SNMP stuff...
528*5e7646d2SAndroid Build Coastguard Worker          */
529*5e7646d2SAndroid Build Coastguard Worker 
530*5e7646d2SAndroid Build Coastguard Worker          snmp_enabled = !value[0] || !_cups_strcasecmp(value, "on") ||
531*5e7646d2SAndroid Build Coastguard Worker                         !_cups_strcasecmp(value, "yes") ||
532*5e7646d2SAndroid Build Coastguard Worker                         !_cups_strcasecmp(value, "true");
533*5e7646d2SAndroid Build Coastguard Worker       }
534*5e7646d2SAndroid Build Coastguard Worker       else if (!_cups_strcasecmp(name, "version"))
535*5e7646d2SAndroid Build Coastguard Worker       {
536*5e7646d2SAndroid Build Coastguard Worker         if (!strcmp(value, "1.0"))
537*5e7646d2SAndroid Build Coastguard Worker 	  version = 10;
538*5e7646d2SAndroid Build Coastguard Worker 	else if (!strcmp(value, "1.1"))
539*5e7646d2SAndroid Build Coastguard Worker 	  version = 11;
540*5e7646d2SAndroid Build Coastguard Worker 	else if (!strcmp(value, "2.0"))
541*5e7646d2SAndroid Build Coastguard Worker 	  version = 20;
542*5e7646d2SAndroid Build Coastguard Worker 	else if (!strcmp(value, "2.1"))
543*5e7646d2SAndroid Build Coastguard Worker 	  version = 21;
544*5e7646d2SAndroid Build Coastguard Worker 	else if (!strcmp(value, "2.2"))
545*5e7646d2SAndroid Build Coastguard Worker 	  version = 22;
546*5e7646d2SAndroid Build Coastguard Worker 	else
547*5e7646d2SAndroid Build Coastguard Worker 	{
548*5e7646d2SAndroid Build Coastguard Worker 	  _cupsLangPrintFilter(stderr, "ERROR",
549*5e7646d2SAndroid Build Coastguard Worker 			       _("Unknown version option value: \"%s\"."),
550*5e7646d2SAndroid Build Coastguard Worker 			       value);
551*5e7646d2SAndroid Build Coastguard Worker 	}
552*5e7646d2SAndroid Build Coastguard Worker       }
553*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_LIBZ
554*5e7646d2SAndroid Build Coastguard Worker       else if (!_cups_strcasecmp(name, "compression"))
555*5e7646d2SAndroid Build Coastguard Worker       {
556*5e7646d2SAndroid Build Coastguard Worker         if (!_cups_strcasecmp(value, "true") || !_cups_strcasecmp(value, "yes") ||
557*5e7646d2SAndroid Build Coastguard Worker 	    !_cups_strcasecmp(value, "on") || !_cups_strcasecmp(value, "gzip"))
558*5e7646d2SAndroid Build Coastguard Worker 	  compression = "gzip";
559*5e7646d2SAndroid Build Coastguard Worker         else if (!_cups_strcasecmp(value, "deflate"))
560*5e7646d2SAndroid Build Coastguard Worker 	  compression = "deflate";
561*5e7646d2SAndroid Build Coastguard Worker         else if (!_cups_strcasecmp(value, "false") ||
562*5e7646d2SAndroid Build Coastguard Worker                  !_cups_strcasecmp(value, "no") ||
563*5e7646d2SAndroid Build Coastguard Worker 		 !_cups_strcasecmp(value, "off") ||
564*5e7646d2SAndroid Build Coastguard Worker 		 !_cups_strcasecmp(value, "none"))
565*5e7646d2SAndroid Build Coastguard Worker 	  compression = "none";
566*5e7646d2SAndroid Build Coastguard Worker       }
567*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_LIBZ */
568*5e7646d2SAndroid Build Coastguard Worker       else if (!_cups_strcasecmp(name, "contimeout"))
569*5e7646d2SAndroid Build Coastguard Worker       {
570*5e7646d2SAndroid Build Coastguard Worker        /*
571*5e7646d2SAndroid Build Coastguard Worker         * Set the connection timeout...
572*5e7646d2SAndroid Build Coastguard Worker 	*/
573*5e7646d2SAndroid Build Coastguard Worker 
574*5e7646d2SAndroid Build Coastguard Worker 	if (atoi(value) > 0)
575*5e7646d2SAndroid Build Coastguard Worker 	  contimeout = atoi(value);
576*5e7646d2SAndroid Build Coastguard Worker       }
577*5e7646d2SAndroid Build Coastguard Worker       else
578*5e7646d2SAndroid Build Coastguard Worker       {
579*5e7646d2SAndroid Build Coastguard Worker        /*
580*5e7646d2SAndroid Build Coastguard Worker         * Unknown option...
581*5e7646d2SAndroid Build Coastguard Worker 	*/
582*5e7646d2SAndroid Build Coastguard Worker 
583*5e7646d2SAndroid Build Coastguard Worker 	_cupsLangPrintFilter(stderr, "ERROR",
584*5e7646d2SAndroid Build Coastguard Worker 	                     _("Unknown option \"%s\" with value \"%s\"."),
585*5e7646d2SAndroid Build Coastguard Worker 			     name, value);
586*5e7646d2SAndroid Build Coastguard Worker       }
587*5e7646d2SAndroid Build Coastguard Worker     }
588*5e7646d2SAndroid Build Coastguard Worker   }
589*5e7646d2SAndroid Build Coastguard Worker 
590*5e7646d2SAndroid Build Coastguard Worker  /*
591*5e7646d2SAndroid Build Coastguard Worker   * If we have 7 arguments, print the file named on the command-line.
592*5e7646d2SAndroid Build Coastguard Worker   * Otherwise, copy stdin to a temporary file and print the temporary
593*5e7646d2SAndroid Build Coastguard Worker   * file.
594*5e7646d2SAndroid Build Coastguard Worker   */
595*5e7646d2SAndroid Build Coastguard Worker 
596*5e7646d2SAndroid Build Coastguard Worker   if (argc == 6)
597*5e7646d2SAndroid Build Coastguard Worker   {
598*5e7646d2SAndroid Build Coastguard Worker     num_files    = 0;
599*5e7646d2SAndroid Build Coastguard Worker     files        = NULL;
600*5e7646d2SAndroid Build Coastguard Worker     send_options = !_cups_strcasecmp(final_content_type, "application/pdf") ||
601*5e7646d2SAndroid Build Coastguard Worker                    !_cups_strcasecmp(final_content_type, "application/vnd.cups-pdf") ||
602*5e7646d2SAndroid Build Coastguard Worker                    !_cups_strncasecmp(final_content_type, "image/", 6);
603*5e7646d2SAndroid Build Coastguard Worker 
604*5e7646d2SAndroid Build Coastguard Worker     fputs("DEBUG: Sending stdin for job...\n", stderr);
605*5e7646d2SAndroid Build Coastguard Worker   }
606*5e7646d2SAndroid Build Coastguard Worker   else
607*5e7646d2SAndroid Build Coastguard Worker   {
608*5e7646d2SAndroid Build Coastguard Worker    /*
609*5e7646d2SAndroid Build Coastguard Worker     * Point to the files on the command-line...
610*5e7646d2SAndroid Build Coastguard Worker     */
611*5e7646d2SAndroid Build Coastguard Worker 
612*5e7646d2SAndroid Build Coastguard Worker     num_files    = argc - 6;
613*5e7646d2SAndroid Build Coastguard Worker     files        = argv + 6;
614*5e7646d2SAndroid Build Coastguard Worker     send_options = 1;
615*5e7646d2SAndroid Build Coastguard Worker 
616*5e7646d2SAndroid Build Coastguard Worker     fprintf(stderr, "DEBUG: %d files to send in job...\n", num_files);
617*5e7646d2SAndroid Build Coastguard Worker   }
618*5e7646d2SAndroid Build Coastguard Worker 
619*5e7646d2SAndroid Build Coastguard Worker  /*
620*5e7646d2SAndroid Build Coastguard Worker   * Set the authentication info, if any...
621*5e7646d2SAndroid Build Coastguard Worker   */
622*5e7646d2SAndroid Build Coastguard Worker 
623*5e7646d2SAndroid Build Coastguard Worker   cupsSetPasswordCB2((cups_password_cb2_t)password_cb, &password_tries);
624*5e7646d2SAndroid Build Coastguard Worker 
625*5e7646d2SAndroid Build Coastguard Worker   if (username[0])
626*5e7646d2SAndroid Build Coastguard Worker   {
627*5e7646d2SAndroid Build Coastguard Worker    /*
628*5e7646d2SAndroid Build Coastguard Worker     * Use authentication information in the device URI...
629*5e7646d2SAndroid Build Coastguard Worker     */
630*5e7646d2SAndroid Build Coastguard Worker 
631*5e7646d2SAndroid Build Coastguard Worker     if ((password = strchr(username, ':')) != NULL)
632*5e7646d2SAndroid Build Coastguard Worker       *password++ = '\0';
633*5e7646d2SAndroid Build Coastguard Worker 
634*5e7646d2SAndroid Build Coastguard Worker     cupsSetUser(username);
635*5e7646d2SAndroid Build Coastguard Worker     uri_credentials = 1;
636*5e7646d2SAndroid Build Coastguard Worker   }
637*5e7646d2SAndroid Build Coastguard Worker   else
638*5e7646d2SAndroid Build Coastguard Worker   {
639*5e7646d2SAndroid Build Coastguard Worker    /*
640*5e7646d2SAndroid Build Coastguard Worker     * Try loading authentication information from the environment.
641*5e7646d2SAndroid Build Coastguard Worker     */
642*5e7646d2SAndroid Build Coastguard Worker 
643*5e7646d2SAndroid Build Coastguard Worker     const char *ptr = getenv("AUTH_USERNAME");
644*5e7646d2SAndroid Build Coastguard Worker 
645*5e7646d2SAndroid Build Coastguard Worker     if (ptr)
646*5e7646d2SAndroid Build Coastguard Worker     {
647*5e7646d2SAndroid Build Coastguard Worker       strlcpy(username, ptr, sizeof(username));
648*5e7646d2SAndroid Build Coastguard Worker       cupsSetUser(ptr);
649*5e7646d2SAndroid Build Coastguard Worker     }
650*5e7646d2SAndroid Build Coastguard Worker 
651*5e7646d2SAndroid Build Coastguard Worker     password = getenv("AUTH_PASSWORD");
652*5e7646d2SAndroid Build Coastguard Worker   }
653*5e7646d2SAndroid Build Coastguard Worker 
654*5e7646d2SAndroid Build Coastguard Worker  /*
655*5e7646d2SAndroid Build Coastguard Worker   * Try finding the remote server...
656*5e7646d2SAndroid Build Coastguard Worker   */
657*5e7646d2SAndroid Build Coastguard Worker 
658*5e7646d2SAndroid Build Coastguard Worker   start_time = time(NULL);
659*5e7646d2SAndroid Build Coastguard Worker 
660*5e7646d2SAndroid Build Coastguard Worker   addrlist = backendLookup(hostname, port, &job_canceled);
661*5e7646d2SAndroid Build Coastguard Worker 
662*5e7646d2SAndroid Build Coastguard Worker   http = httpConnect2(hostname, port, addrlist, AF_UNSPEC, cupsEncryption(), 1,
663*5e7646d2SAndroid Build Coastguard Worker                       0, NULL);
664*5e7646d2SAndroid Build Coastguard Worker   httpSetTimeout(http, 30.0, timeout_cb, NULL);
665*5e7646d2SAndroid Build Coastguard Worker 
666*5e7646d2SAndroid Build Coastguard Worker  /*
667*5e7646d2SAndroid Build Coastguard Worker   * See if the printer supports SNMP...
668*5e7646d2SAndroid Build Coastguard Worker   */
669*5e7646d2SAndroid Build Coastguard Worker 
670*5e7646d2SAndroid Build Coastguard Worker   if (snmp_enabled)
671*5e7646d2SAndroid Build Coastguard Worker     snmp_fd = _cupsSNMPOpen(addrlist->addr.addr.sa_family);
672*5e7646d2SAndroid Build Coastguard Worker   else
673*5e7646d2SAndroid Build Coastguard Worker     snmp_fd = -1;
674*5e7646d2SAndroid Build Coastguard Worker 
675*5e7646d2SAndroid Build Coastguard Worker   if (snmp_fd >= 0)
676*5e7646d2SAndroid Build Coastguard Worker     have_supplies = !backendSNMPSupplies(snmp_fd, &(addrlist->addr),
677*5e7646d2SAndroid Build Coastguard Worker                                          &start_count, NULL);
678*5e7646d2SAndroid Build Coastguard Worker   else
679*5e7646d2SAndroid Build Coastguard Worker     have_supplies = start_count = 0;
680*5e7646d2SAndroid Build Coastguard Worker 
681*5e7646d2SAndroid Build Coastguard Worker  /*
682*5e7646d2SAndroid Build Coastguard Worker   * Wait for data from the filter...
683*5e7646d2SAndroid Build Coastguard Worker   */
684*5e7646d2SAndroid Build Coastguard Worker 
685*5e7646d2SAndroid Build Coastguard Worker   if (num_files == 0)
686*5e7646d2SAndroid Build Coastguard Worker   {
687*5e7646d2SAndroid Build Coastguard Worker     if (!backendWaitLoop(snmp_fd, &(addrlist->addr), 0, backendNetworkSideCB))
688*5e7646d2SAndroid Build Coastguard Worker       return (CUPS_BACKEND_OK);
689*5e7646d2SAndroid Build Coastguard Worker     else if ((bytes = read(0, buffer, sizeof(buffer))) <= 0)
690*5e7646d2SAndroid Build Coastguard Worker       return (CUPS_BACKEND_OK);
691*5e7646d2SAndroid Build Coastguard Worker   }
692*5e7646d2SAndroid Build Coastguard Worker 
693*5e7646d2SAndroid Build Coastguard Worker  /*
694*5e7646d2SAndroid Build Coastguard Worker   * Try connecting to the remote server...
695*5e7646d2SAndroid Build Coastguard Worker   */
696*5e7646d2SAndroid Build Coastguard Worker 
697*5e7646d2SAndroid Build Coastguard Worker   delay = _cupsNextDelay(0, &prev_delay);
698*5e7646d2SAndroid Build Coastguard Worker 
699*5e7646d2SAndroid Build Coastguard Worker   do
700*5e7646d2SAndroid Build Coastguard Worker   {
701*5e7646d2SAndroid Build Coastguard Worker     fprintf(stderr, "DEBUG: Connecting to %s:%d\n", hostname, port);
702*5e7646d2SAndroid Build Coastguard Worker     _cupsLangPrintFilter(stderr, "INFO", _("Connecting to printer."));
703*5e7646d2SAndroid Build Coastguard Worker 
704*5e7646d2SAndroid Build Coastguard Worker     if (httpReconnect2(http, 30000, NULL))
705*5e7646d2SAndroid Build Coastguard Worker     {
706*5e7646d2SAndroid Build Coastguard Worker       int error = errno;		/* Connection error */
707*5e7646d2SAndroid Build Coastguard Worker 
708*5e7646d2SAndroid Build Coastguard Worker       if (http->status == HTTP_STATUS_CUPS_PKI_ERROR)
709*5e7646d2SAndroid Build Coastguard Worker 	update_reasons(NULL, "+cups-certificate-error");
710*5e7646d2SAndroid Build Coastguard Worker 
711*5e7646d2SAndroid Build Coastguard Worker       if (job_canceled)
712*5e7646d2SAndroid Build Coastguard Worker 	break;
713*5e7646d2SAndroid Build Coastguard Worker 
714*5e7646d2SAndroid Build Coastguard Worker       if (getenv("CLASS") != NULL)
715*5e7646d2SAndroid Build Coastguard Worker       {
716*5e7646d2SAndroid Build Coastguard Worker        /*
717*5e7646d2SAndroid Build Coastguard Worker         * If the CLASS environment variable is set, the job was submitted
718*5e7646d2SAndroid Build Coastguard Worker 	* to a class and not to a specific queue.  In this case, we want
719*5e7646d2SAndroid Build Coastguard Worker 	* to abort immediately so that the job can be requeued on the next
720*5e7646d2SAndroid Build Coastguard Worker 	* available printer in the class.
721*5e7646d2SAndroid Build Coastguard Worker 	*/
722*5e7646d2SAndroid Build Coastguard Worker 
723*5e7646d2SAndroid Build Coastguard Worker         _cupsLangPrintFilter(stderr, "INFO",
724*5e7646d2SAndroid Build Coastguard Worker 			     _("Unable to contact printer, queuing on next "
725*5e7646d2SAndroid Build Coastguard Worker 			       "printer in class."));
726*5e7646d2SAndroid Build Coastguard Worker 
727*5e7646d2SAndroid Build Coastguard Worker        /*
728*5e7646d2SAndroid Build Coastguard Worker         * Sleep 5 seconds to keep the job from requeuing too rapidly...
729*5e7646d2SAndroid Build Coastguard Worker 	*/
730*5e7646d2SAndroid Build Coastguard Worker 
731*5e7646d2SAndroid Build Coastguard Worker 	sleep(5);
732*5e7646d2SAndroid Build Coastguard Worker 
733*5e7646d2SAndroid Build Coastguard Worker 	update_reasons(NULL, "-connecting-to-device");
734*5e7646d2SAndroid Build Coastguard Worker 
735*5e7646d2SAndroid Build Coastguard Worker         return (CUPS_BACKEND_FAILED);
736*5e7646d2SAndroid Build Coastguard Worker       }
737*5e7646d2SAndroid Build Coastguard Worker 
738*5e7646d2SAndroid Build Coastguard Worker       fprintf(stderr, "DEBUG: Connection error: %s\n", strerror(errno));
739*5e7646d2SAndroid Build Coastguard Worker 
740*5e7646d2SAndroid Build Coastguard Worker       if (errno == ECONNREFUSED || errno == EHOSTDOWN || errno == EHOSTUNREACH || errno == ETIMEDOUT || errno == ENOTCONN)
741*5e7646d2SAndroid Build Coastguard Worker       {
742*5e7646d2SAndroid Build Coastguard Worker         if (contimeout && (time(NULL) - start_time) > contimeout)
743*5e7646d2SAndroid Build Coastguard Worker 	{
744*5e7646d2SAndroid Build Coastguard Worker 	  _cupsLangPrintFilter(stderr, "ERROR",
745*5e7646d2SAndroid Build Coastguard Worker 	                       _("The printer is not responding."));
746*5e7646d2SAndroid Build Coastguard Worker 	  update_reasons(NULL, "-connecting-to-device");
747*5e7646d2SAndroid Build Coastguard Worker 	  return (CUPS_BACKEND_FAILED);
748*5e7646d2SAndroid Build Coastguard Worker 	}
749*5e7646d2SAndroid Build Coastguard Worker 
750*5e7646d2SAndroid Build Coastguard Worker 	switch (error)
751*5e7646d2SAndroid Build Coastguard Worker 	{
752*5e7646d2SAndroid Build Coastguard Worker 	  case EHOSTDOWN :
753*5e7646d2SAndroid Build Coastguard Worker 	      _cupsLangPrintFilter(stderr, "WARNING",
754*5e7646d2SAndroid Build Coastguard Worker 			           _("The printer may not exist or "
755*5e7646d2SAndroid Build Coastguard Worker 				     "is unavailable at this time."));
756*5e7646d2SAndroid Build Coastguard Worker 	      break;
757*5e7646d2SAndroid Build Coastguard Worker 
758*5e7646d2SAndroid Build Coastguard Worker 	  case EHOSTUNREACH :
759*5e7646d2SAndroid Build Coastguard Worker 	  default :
760*5e7646d2SAndroid Build Coastguard Worker 	      _cupsLangPrintFilter(stderr, "WARNING",
761*5e7646d2SAndroid Build Coastguard Worker 				   _("The printer is unreachable at this "
762*5e7646d2SAndroid Build Coastguard Worker 				     "time."));
763*5e7646d2SAndroid Build Coastguard Worker 	      break;
764*5e7646d2SAndroid Build Coastguard Worker 
765*5e7646d2SAndroid Build Coastguard Worker 	  case ECONNREFUSED :
766*5e7646d2SAndroid Build Coastguard Worker 	      _cupsLangPrintFilter(stderr, "WARNING",
767*5e7646d2SAndroid Build Coastguard Worker 	                           _("The printer is in use."));
768*5e7646d2SAndroid Build Coastguard Worker 	      break;
769*5e7646d2SAndroid Build Coastguard Worker         }
770*5e7646d2SAndroid Build Coastguard Worker 
771*5e7646d2SAndroid Build Coastguard Worker 	sleep((unsigned)delay);
772*5e7646d2SAndroid Build Coastguard Worker 
773*5e7646d2SAndroid Build Coastguard Worker         delay = _cupsNextDelay(delay, &prev_delay);
774*5e7646d2SAndroid Build Coastguard Worker       }
775*5e7646d2SAndroid Build Coastguard Worker       else
776*5e7646d2SAndroid Build Coastguard Worker       {
777*5e7646d2SAndroid Build Coastguard Worker 	_cupsLangPrintFilter(stderr, "ERROR",
778*5e7646d2SAndroid Build Coastguard Worker 	                     _("The printer is not responding."));
779*5e7646d2SAndroid Build Coastguard Worker 	sleep(30);
780*5e7646d2SAndroid Build Coastguard Worker       }
781*5e7646d2SAndroid Build Coastguard Worker 
782*5e7646d2SAndroid Build Coastguard Worker       if (job_canceled)
783*5e7646d2SAndroid Build Coastguard Worker 	break;
784*5e7646d2SAndroid Build Coastguard Worker     }
785*5e7646d2SAndroid Build Coastguard Worker     else
786*5e7646d2SAndroid Build Coastguard Worker       update_reasons(NULL, "-cups-certificate-error");
787*5e7646d2SAndroid Build Coastguard Worker   }
788*5e7646d2SAndroid Build Coastguard Worker   while (http->fd < 0);
789*5e7646d2SAndroid Build Coastguard Worker 
790*5e7646d2SAndroid Build Coastguard Worker   if (job_canceled)
791*5e7646d2SAndroid Build Coastguard Worker     return (CUPS_BACKEND_OK);
792*5e7646d2SAndroid Build Coastguard Worker   else if (!http)
793*5e7646d2SAndroid Build Coastguard Worker     return (CUPS_BACKEND_FAILED);
794*5e7646d2SAndroid Build Coastguard Worker 
795*5e7646d2SAndroid Build Coastguard Worker   if (httpIsEncrypted(http))
796*5e7646d2SAndroid Build Coastguard Worker   {
797*5e7646d2SAndroid Build Coastguard Worker    /*
798*5e7646d2SAndroid Build Coastguard Worker     * Validate TLS credentials...
799*5e7646d2SAndroid Build Coastguard Worker     */
800*5e7646d2SAndroid Build Coastguard Worker 
801*5e7646d2SAndroid Build Coastguard Worker     cups_array_t	*creds;		/* TLS credentials */
802*5e7646d2SAndroid Build Coastguard Worker     cups_array_t	*lcreds = NULL;	/* Loaded credentials */
803*5e7646d2SAndroid Build Coastguard Worker     http_trust_t	trust;		/* Trust level */
804*5e7646d2SAndroid Build Coastguard Worker     char		credinfo[1024],	/* Information on credentials */
805*5e7646d2SAndroid Build Coastguard Worker 			lcredinfo[1024];/* Information on saved credentials */
806*5e7646d2SAndroid Build Coastguard Worker     static const char	* const trusts[] = { NULL, "+cups-pki-invalid", "+cups-pki-changed", "+cups-pki-expired", NULL, "+cups-pki-unknown" };
807*5e7646d2SAndroid Build Coastguard Worker 					/* Trust keywords */
808*5e7646d2SAndroid Build Coastguard Worker     static const char	* const trust_msgs[] =
809*5e7646d2SAndroid Build Coastguard Worker     {
810*5e7646d2SAndroid Build Coastguard Worker       "Credentials are OK/trusted",
811*5e7646d2SAndroid Build Coastguard Worker       "Credentials are invalid",
812*5e7646d2SAndroid Build Coastguard Worker       "Credentials have changed",
813*5e7646d2SAndroid Build Coastguard Worker       "Credentials are expired",
814*5e7646d2SAndroid Build Coastguard Worker       "Credentials have been renewed",
815*5e7646d2SAndroid Build Coastguard Worker       "Credentials are unknown/new"
816*5e7646d2SAndroid Build Coastguard Worker     };
817*5e7646d2SAndroid Build Coastguard Worker 
818*5e7646d2SAndroid Build Coastguard Worker     fputs("DEBUG: Connection is encrypted.\n", stderr);
819*5e7646d2SAndroid Build Coastguard Worker 
820*5e7646d2SAndroid Build Coastguard Worker     if (!httpCopyCredentials(http, &creds))
821*5e7646d2SAndroid Build Coastguard Worker     {
822*5e7646d2SAndroid Build Coastguard Worker       trust = httpCredentialsGetTrust(creds, hostname);
823*5e7646d2SAndroid Build Coastguard Worker       httpCredentialsString(creds, credinfo, sizeof(credinfo));
824*5e7646d2SAndroid Build Coastguard Worker 
825*5e7646d2SAndroid Build Coastguard Worker       fprintf(stderr, "DEBUG: %s (%s)\n", trust_msgs[trust], cupsLastErrorString());
826*5e7646d2SAndroid Build Coastguard Worker       fprintf(stderr, "DEBUG: Printer credentials: %s\n", credinfo);
827*5e7646d2SAndroid Build Coastguard Worker 
828*5e7646d2SAndroid Build Coastguard Worker       if (!httpLoadCredentials(NULL, &lcreds, hostname))
829*5e7646d2SAndroid Build Coastguard Worker       {
830*5e7646d2SAndroid Build Coastguard Worker         httpCredentialsString(lcreds, lcredinfo, sizeof(lcredinfo));
831*5e7646d2SAndroid Build Coastguard Worker 	fprintf(stderr, "DEBUG: Stored credentials: %s\n", lcredinfo);
832*5e7646d2SAndroid Build Coastguard Worker       }
833*5e7646d2SAndroid Build Coastguard Worker       else
834*5e7646d2SAndroid Build Coastguard Worker         fputs("DEBUG: No stored credentials.\n", stderr);
835*5e7646d2SAndroid Build Coastguard Worker 
836*5e7646d2SAndroid Build Coastguard Worker       update_reasons(NULL, "-cups-pki-invalid,cups-pki-changed,cups-pki-expired,cups-pki-unknown");
837*5e7646d2SAndroid Build Coastguard Worker       if (trusts[trust])
838*5e7646d2SAndroid Build Coastguard Worker       {
839*5e7646d2SAndroid Build Coastguard Worker         update_reasons(NULL, trusts[trust]);
840*5e7646d2SAndroid Build Coastguard Worker         return (CUPS_BACKEND_STOP);
841*5e7646d2SAndroid Build Coastguard Worker       }
842*5e7646d2SAndroid Build Coastguard Worker 
843*5e7646d2SAndroid Build Coastguard Worker       if (!lcreds)
844*5e7646d2SAndroid Build Coastguard Worker       {
845*5e7646d2SAndroid Build Coastguard Worker        /*
846*5e7646d2SAndroid Build Coastguard Worker         * Could not load the credentials, let's save the ones we have so we
847*5e7646d2SAndroid Build Coastguard Worker         * can detect changes...
848*5e7646d2SAndroid Build Coastguard Worker         */
849*5e7646d2SAndroid Build Coastguard Worker 
850*5e7646d2SAndroid Build Coastguard Worker         httpSaveCredentials(NULL, creds, hostname);
851*5e7646d2SAndroid Build Coastguard Worker       }
852*5e7646d2SAndroid Build Coastguard Worker 
853*5e7646d2SAndroid Build Coastguard Worker       httpFreeCredentials(lcreds);
854*5e7646d2SAndroid Build Coastguard Worker       httpFreeCredentials(creds);
855*5e7646d2SAndroid Build Coastguard Worker     }
856*5e7646d2SAndroid Build Coastguard Worker     else
857*5e7646d2SAndroid Build Coastguard Worker     {
858*5e7646d2SAndroid Build Coastguard Worker       fputs("DEBUG: No printer credentials.\n", stderr);
859*5e7646d2SAndroid Build Coastguard Worker 
860*5e7646d2SAndroid Build Coastguard Worker       update_reasons(NULL, "cups-pki-unknown");
861*5e7646d2SAndroid Build Coastguard Worker       return (CUPS_BACKEND_STOP);
862*5e7646d2SAndroid Build Coastguard Worker     }
863*5e7646d2SAndroid Build Coastguard Worker   }
864*5e7646d2SAndroid Build Coastguard Worker 
865*5e7646d2SAndroid Build Coastguard Worker   update_reasons(NULL, "-connecting-to-device");
866*5e7646d2SAndroid Build Coastguard Worker   _cupsLangPrintFilter(stderr, "INFO", _("Connected to printer."));
867*5e7646d2SAndroid Build Coastguard Worker 
868*5e7646d2SAndroid Build Coastguard Worker   fprintf(stderr, "DEBUG: Connected to %s:%d...\n",
869*5e7646d2SAndroid Build Coastguard Worker 	  httpAddrString(http->hostaddr, addrname, sizeof(addrname)),
870*5e7646d2SAndroid Build Coastguard Worker 	  httpAddrPort(http->hostaddr));
871*5e7646d2SAndroid Build Coastguard Worker 
872*5e7646d2SAndroid Build Coastguard Worker  /*
873*5e7646d2SAndroid Build Coastguard Worker   * Build a URI for the printer and fill the standard IPP attributes for
874*5e7646d2SAndroid Build Coastguard Worker   * an IPP_PRINT_FILE request.  We can't use the URI in argv[0] because it
875*5e7646d2SAndroid Build Coastguard Worker   * might contain username:password information...
876*5e7646d2SAndroid Build Coastguard Worker   */
877*5e7646d2SAndroid Build Coastguard Worker 
878*5e7646d2SAndroid Build Coastguard Worker   httpAssembleURI(HTTP_URI_CODING_ALL, uri, sizeof(uri), scheme, NULL, hostname,
879*5e7646d2SAndroid Build Coastguard Worker 		  port, resource);
880*5e7646d2SAndroid Build Coastguard Worker 
881*5e7646d2SAndroid Build Coastguard Worker  /*
882*5e7646d2SAndroid Build Coastguard Worker   * First validate the destination and see if the device supports multiple
883*5e7646d2SAndroid Build Coastguard Worker   * copies...
884*5e7646d2SAndroid Build Coastguard Worker   */
885*5e7646d2SAndroid Build Coastguard Worker 
886*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_LIBZ
887*5e7646d2SAndroid Build Coastguard Worker   compression_sup      = NULL;
888*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_LIBZ */
889*5e7646d2SAndroid Build Coastguard Worker   copies_sup           = NULL;
890*5e7646d2SAndroid Build Coastguard Worker   cups_version         = NULL;
891*5e7646d2SAndroid Build Coastguard Worker   encryption_sup       = NULL;
892*5e7646d2SAndroid Build Coastguard Worker   format_sup           = NULL;
893*5e7646d2SAndroid Build Coastguard Worker   media_col_sup        = NULL;
894*5e7646d2SAndroid Build Coastguard Worker   supported            = NULL;
895*5e7646d2SAndroid Build Coastguard Worker   operations_sup       = NULL;
896*5e7646d2SAndroid Build Coastguard Worker   doc_handling_sup     = NULL;
897*5e7646d2SAndroid Build Coastguard Worker   print_color_mode_sup = NULL;
898*5e7646d2SAndroid Build Coastguard Worker 
899*5e7646d2SAndroid Build Coastguard Worker   do
900*5e7646d2SAndroid Build Coastguard Worker   {
901*5e7646d2SAndroid Build Coastguard Worker    /*
902*5e7646d2SAndroid Build Coastguard Worker     * Check for side-channel requests...
903*5e7646d2SAndroid Build Coastguard Worker     */
904*5e7646d2SAndroid Build Coastguard Worker 
905*5e7646d2SAndroid Build Coastguard Worker     backendCheckSideChannel(snmp_fd, http->hostaddr);
906*5e7646d2SAndroid Build Coastguard Worker 
907*5e7646d2SAndroid Build Coastguard Worker    /*
908*5e7646d2SAndroid Build Coastguard Worker     * Build the IPP request...
909*5e7646d2SAndroid Build Coastguard Worker     */
910*5e7646d2SAndroid Build Coastguard Worker 
911*5e7646d2SAndroid Build Coastguard Worker     request = ippNewRequest(IPP_OP_GET_PRINTER_ATTRIBUTES);
912*5e7646d2SAndroid Build Coastguard Worker     ippSetVersion(request, version / 10, version % 10);
913*5e7646d2SAndroid Build Coastguard Worker     ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
914*5e7646d2SAndroid Build Coastguard Worker         	 NULL, uri);
915*5e7646d2SAndroid Build Coastguard Worker 
916*5e7646d2SAndroid Build Coastguard Worker     ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
917*5e7646d2SAndroid Build Coastguard Worker                   "requested-attributes", sizeof(pattrs) / sizeof(pattrs[0]),
918*5e7646d2SAndroid Build Coastguard Worker 		  NULL, pattrs);
919*5e7646d2SAndroid Build Coastguard Worker 
920*5e7646d2SAndroid Build Coastguard Worker    /*
921*5e7646d2SAndroid Build Coastguard Worker     * Do the request...
922*5e7646d2SAndroid Build Coastguard Worker     */
923*5e7646d2SAndroid Build Coastguard Worker 
924*5e7646d2SAndroid Build Coastguard Worker     fputs("DEBUG: Getting supported attributes...\n", stderr);
925*5e7646d2SAndroid Build Coastguard Worker 
926*5e7646d2SAndroid Build Coastguard Worker     if (http->version < HTTP_VERSION_1_1)
927*5e7646d2SAndroid Build Coastguard Worker     {
928*5e7646d2SAndroid Build Coastguard Worker       fprintf(stderr, "DEBUG: Printer responded with HTTP version %d.%d.\n",
929*5e7646d2SAndroid Build Coastguard Worker               http->version / 100, http->version % 100);
930*5e7646d2SAndroid Build Coastguard Worker       update_reasons(NULL, "+cups-ipp-conformance-failure-report,"
931*5e7646d2SAndroid Build Coastguard Worker 			   "cups-ipp-wrong-http-version");
932*5e7646d2SAndroid Build Coastguard Worker     }
933*5e7646d2SAndroid Build Coastguard Worker 
934*5e7646d2SAndroid Build Coastguard Worker     supported  = cupsDoRequest(http, request, resource);
935*5e7646d2SAndroid Build Coastguard Worker     ipp_status = cupsLastError();
936*5e7646d2SAndroid Build Coastguard Worker 
937*5e7646d2SAndroid Build Coastguard Worker     fprintf(stderr, "DEBUG: Get-Printer-Attributes: %s (%s)\n",
938*5e7646d2SAndroid Build Coastguard Worker             ippErrorString(ipp_status), cupsLastErrorString());
939*5e7646d2SAndroid Build Coastguard Worker 
940*5e7646d2SAndroid Build Coastguard Worker     if (ipp_status <= IPP_STATUS_OK_CONFLICTING)
941*5e7646d2SAndroid Build Coastguard Worker       password_tries = 0;
942*5e7646d2SAndroid Build Coastguard Worker     else
943*5e7646d2SAndroid Build Coastguard Worker     {
944*5e7646d2SAndroid Build Coastguard Worker       fprintf(stderr, "DEBUG: Get-Printer-Attributes returned %s.\n",
945*5e7646d2SAndroid Build Coastguard Worker               ippErrorString(ipp_status));
946*5e7646d2SAndroid Build Coastguard Worker 
947*5e7646d2SAndroid Build Coastguard Worker       if (ipp_status == IPP_STATUS_ERROR_BUSY ||
948*5e7646d2SAndroid Build Coastguard Worker 	  ipp_status == IPP_STATUS_ERROR_SERVICE_UNAVAILABLE)
949*5e7646d2SAndroid Build Coastguard Worker       {
950*5e7646d2SAndroid Build Coastguard Worker         if (contimeout && (time(NULL) - start_time) > contimeout)
951*5e7646d2SAndroid Build Coastguard Worker 	{
952*5e7646d2SAndroid Build Coastguard Worker 	  _cupsLangPrintFilter(stderr, "ERROR",
953*5e7646d2SAndroid Build Coastguard Worker 	                       _("The printer is not responding."));
954*5e7646d2SAndroid Build Coastguard Worker 	  return (CUPS_BACKEND_FAILED);
955*5e7646d2SAndroid Build Coastguard Worker 	}
956*5e7646d2SAndroid Build Coastguard Worker 
957*5e7646d2SAndroid Build Coastguard Worker 	_cupsLangPrintFilter(stderr, "INFO", _("The printer is in use."));
958*5e7646d2SAndroid Build Coastguard Worker 
959*5e7646d2SAndroid Build Coastguard Worker         report_printer_state(supported);
960*5e7646d2SAndroid Build Coastguard Worker 
961*5e7646d2SAndroid Build Coastguard Worker 	sleep((unsigned)delay);
962*5e7646d2SAndroid Build Coastguard Worker 
963*5e7646d2SAndroid Build Coastguard Worker         delay = _cupsNextDelay(delay, &prev_delay);
964*5e7646d2SAndroid Build Coastguard Worker       }
965*5e7646d2SAndroid Build Coastguard Worker       else if ((ipp_status == IPP_STATUS_ERROR_BAD_REQUEST ||
966*5e7646d2SAndroid Build Coastguard Worker 	        ipp_status == IPP_STATUS_ERROR_VERSION_NOT_SUPPORTED) && version > 10)
967*5e7646d2SAndroid Build Coastguard Worker       {
968*5e7646d2SAndroid Build Coastguard Worker        /*
969*5e7646d2SAndroid Build Coastguard Worker 	* Switch to IPP/1.1 or IPP/1.0...
970*5e7646d2SAndroid Build Coastguard Worker 	*/
971*5e7646d2SAndroid Build Coastguard Worker 
972*5e7646d2SAndroid Build Coastguard Worker         if (version >= 20)
973*5e7646d2SAndroid Build Coastguard Worker 	{
974*5e7646d2SAndroid Build Coastguard Worker 	  _cupsLangPrintFilter(stderr, "INFO", _("Preparing to print."));
975*5e7646d2SAndroid Build Coastguard Worker 	  fprintf(stderr,
976*5e7646d2SAndroid Build Coastguard Worker 	          "DEBUG: The printer does not support IPP/%d.%d, trying "
977*5e7646d2SAndroid Build Coastguard Worker 	          "IPP/1.1.\n", version / 10, version % 10);
978*5e7646d2SAndroid Build Coastguard Worker 	  version = 11;
979*5e7646d2SAndroid Build Coastguard Worker 	}
980*5e7646d2SAndroid Build Coastguard Worker 	else
981*5e7646d2SAndroid Build Coastguard Worker 	{
982*5e7646d2SAndroid Build Coastguard Worker 	  _cupsLangPrintFilter(stderr, "INFO", _("Preparing to print."));
983*5e7646d2SAndroid Build Coastguard Worker 	  fprintf(stderr,
984*5e7646d2SAndroid Build Coastguard Worker 	          "DEBUG: The printer does not support IPP/%d.%d, trying "
985*5e7646d2SAndroid Build Coastguard Worker 	          "IPP/1.0.\n", version / 10, version % 10);
986*5e7646d2SAndroid Build Coastguard Worker 	  version = 10;
987*5e7646d2SAndroid Build Coastguard Worker         }
988*5e7646d2SAndroid Build Coastguard Worker 
989*5e7646d2SAndroid Build Coastguard Worker 	httpReconnect2(http, 30000, NULL);
990*5e7646d2SAndroid Build Coastguard Worker       }
991*5e7646d2SAndroid Build Coastguard Worker       else if (ipp_status == IPP_STATUS_ERROR_NOT_FOUND)
992*5e7646d2SAndroid Build Coastguard Worker       {
993*5e7646d2SAndroid Build Coastguard Worker         _cupsLangPrintFilter(stderr, "ERROR",
994*5e7646d2SAndroid Build Coastguard Worker 			     _("The printer configuration is incorrect or the "
995*5e7646d2SAndroid Build Coastguard Worker 			       "printer no longer exists."));
996*5e7646d2SAndroid Build Coastguard Worker 
997*5e7646d2SAndroid Build Coastguard Worker 	ippDelete(supported);
998*5e7646d2SAndroid Build Coastguard Worker 
999*5e7646d2SAndroid Build Coastguard Worker 	return (CUPS_BACKEND_STOP);
1000*5e7646d2SAndroid Build Coastguard Worker       }
1001*5e7646d2SAndroid Build Coastguard Worker       else if (ipp_status == IPP_STATUS_ERROR_FORBIDDEN ||
1002*5e7646d2SAndroid Build Coastguard Worker                ipp_status == IPP_STATUS_ERROR_CUPS_AUTHENTICATION_CANCELED)
1003*5e7646d2SAndroid Build Coastguard Worker       {
1004*5e7646d2SAndroid Build Coastguard Worker         const char *www_auth = httpGetField(http, HTTP_FIELD_WWW_AUTHENTICATE);
1005*5e7646d2SAndroid Build Coastguard Worker         				/* WWW-Authenticate field value */
1006*5e7646d2SAndroid Build Coastguard Worker 
1007*5e7646d2SAndroid Build Coastguard Worker 	if (!strncmp(www_auth, "Negotiate", 9))
1008*5e7646d2SAndroid Build Coastguard Worker 	  auth_info_required = "negotiate";
1009*5e7646d2SAndroid Build Coastguard Worker         else if (www_auth[0])
1010*5e7646d2SAndroid Build Coastguard Worker           auth_info_required = "username,password";
1011*5e7646d2SAndroid Build Coastguard Worker 
1012*5e7646d2SAndroid Build Coastguard Worker 	fprintf(stderr, "ATTR: auth-info-required=%s\n", auth_info_required);
1013*5e7646d2SAndroid Build Coastguard Worker 	return (CUPS_BACKEND_AUTH_REQUIRED);
1014*5e7646d2SAndroid Build Coastguard Worker       }
1015*5e7646d2SAndroid Build Coastguard Worker       else if (ipp_status != IPP_STATUS_ERROR_NOT_AUTHORIZED)
1016*5e7646d2SAndroid Build Coastguard Worker       {
1017*5e7646d2SAndroid Build Coastguard Worker 	_cupsLangPrintFilter(stderr, "ERROR",
1018*5e7646d2SAndroid Build Coastguard Worker 	                     _("Unable to get printer status."));
1019*5e7646d2SAndroid Build Coastguard Worker         sleep(10);
1020*5e7646d2SAndroid Build Coastguard Worker 
1021*5e7646d2SAndroid Build Coastguard Worker 	httpReconnect2(http, 30000, NULL);
1022*5e7646d2SAndroid Build Coastguard Worker       }
1023*5e7646d2SAndroid Build Coastguard Worker 
1024*5e7646d2SAndroid Build Coastguard Worker       ippDelete(supported);
1025*5e7646d2SAndroid Build Coastguard Worker       supported = NULL;
1026*5e7646d2SAndroid Build Coastguard Worker       continue;
1027*5e7646d2SAndroid Build Coastguard Worker     }
1028*5e7646d2SAndroid Build Coastguard Worker 
1029*5e7646d2SAndroid Build Coastguard Worker     if (!getenv("CLASS"))
1030*5e7646d2SAndroid Build Coastguard Worker     {
1031*5e7646d2SAndroid Build Coastguard Worker      /*
1032*5e7646d2SAndroid Build Coastguard Worker       * Check printer-is-accepting-jobs = false and printer-state-reasons for the
1033*5e7646d2SAndroid Build Coastguard Worker       * "spool-area-full" keyword...
1034*5e7646d2SAndroid Build Coastguard Worker       */
1035*5e7646d2SAndroid Build Coastguard Worker 
1036*5e7646d2SAndroid Build Coastguard Worker       int busy = 0;
1037*5e7646d2SAndroid Build Coastguard Worker 
1038*5e7646d2SAndroid Build Coastguard Worker       if ((printer_accepting = ippFindAttribute(supported,
1039*5e7646d2SAndroid Build Coastguard Worker 						"printer-is-accepting-jobs",
1040*5e7646d2SAndroid Build Coastguard Worker 						IPP_TAG_BOOLEAN)) != NULL &&
1041*5e7646d2SAndroid Build Coastguard Worker 	  !printer_accepting->values[0].boolean)
1042*5e7646d2SAndroid Build Coastguard Worker         busy = 1;
1043*5e7646d2SAndroid Build Coastguard Worker       else if (!printer_accepting)
1044*5e7646d2SAndroid Build Coastguard Worker         update_reasons(NULL, "+cups-ipp-conformance-failure-report,"
1045*5e7646d2SAndroid Build Coastguard Worker 			     "cups-ipp-missing-printer-is-accepting-jobs");
1046*5e7646d2SAndroid Build Coastguard Worker 
1047*5e7646d2SAndroid Build Coastguard Worker       if ((printer_state = ippFindAttribute(supported,
1048*5e7646d2SAndroid Build Coastguard Worker 					    "printer-state-reasons",
1049*5e7646d2SAndroid Build Coastguard Worker 					    IPP_TAG_KEYWORD)) == NULL)
1050*5e7646d2SAndroid Build Coastguard Worker       {
1051*5e7646d2SAndroid Build Coastguard Worker         update_reasons(NULL, "+cups-ipp-conformance-failure-report,"
1052*5e7646d2SAndroid Build Coastguard Worker 			     "cups-ipp-missing-printer-state-reasons");
1053*5e7646d2SAndroid Build Coastguard Worker       }
1054*5e7646d2SAndroid Build Coastguard Worker       else if (!busy)
1055*5e7646d2SAndroid Build Coastguard Worker       {
1056*5e7646d2SAndroid Build Coastguard Worker 	for (i = 0; i < printer_state->num_values; i ++)
1057*5e7646d2SAndroid Build Coastguard Worker 	{
1058*5e7646d2SAndroid Build Coastguard Worker 	  if (!strcmp(printer_state->values[0].string.text,
1059*5e7646d2SAndroid Build Coastguard Worker 	              "spool-area-full") ||
1060*5e7646d2SAndroid Build Coastguard Worker 	      !strncmp(printer_state->values[0].string.text, "spool-area-full-",
1061*5e7646d2SAndroid Build Coastguard Worker 		       16))
1062*5e7646d2SAndroid Build Coastguard Worker 	  {
1063*5e7646d2SAndroid Build Coastguard Worker 	    busy = 1;
1064*5e7646d2SAndroid Build Coastguard Worker 	    break;
1065*5e7646d2SAndroid Build Coastguard Worker 	  }
1066*5e7646d2SAndroid Build Coastguard Worker 	}
1067*5e7646d2SAndroid Build Coastguard Worker       }
1068*5e7646d2SAndroid Build Coastguard Worker 
1069*5e7646d2SAndroid Build Coastguard Worker       if (busy)
1070*5e7646d2SAndroid Build Coastguard Worker       {
1071*5e7646d2SAndroid Build Coastguard Worker 	_cupsLangPrintFilter(stderr, "INFO", _("The printer is in use."));
1072*5e7646d2SAndroid Build Coastguard Worker 
1073*5e7646d2SAndroid Build Coastguard Worker 	report_printer_state(supported);
1074*5e7646d2SAndroid Build Coastguard Worker 
1075*5e7646d2SAndroid Build Coastguard Worker 	sleep((unsigned)delay);
1076*5e7646d2SAndroid Build Coastguard Worker 
1077*5e7646d2SAndroid Build Coastguard Worker 	delay = _cupsNextDelay(delay, &prev_delay);
1078*5e7646d2SAndroid Build Coastguard Worker 
1079*5e7646d2SAndroid Build Coastguard Worker 	ippDelete(supported);
1080*5e7646d2SAndroid Build Coastguard Worker 	supported  = NULL;
1081*5e7646d2SAndroid Build Coastguard Worker 	ipp_status = IPP_STATUS_ERROR_BUSY;
1082*5e7646d2SAndroid Build Coastguard Worker 	continue;
1083*5e7646d2SAndroid Build Coastguard Worker       }
1084*5e7646d2SAndroid Build Coastguard Worker     }
1085*5e7646d2SAndroid Build Coastguard Worker 
1086*5e7646d2SAndroid Build Coastguard Worker    /*
1087*5e7646d2SAndroid Build Coastguard Worker     * Check for supported attributes...
1088*5e7646d2SAndroid Build Coastguard Worker     */
1089*5e7646d2SAndroid Build Coastguard Worker 
1090*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_LIBZ
1091*5e7646d2SAndroid Build Coastguard Worker     if ((compression_sup = ippFindAttribute(supported, "compression-supported",
1092*5e7646d2SAndroid Build Coastguard Worker                                             IPP_TAG_KEYWORD)) != NULL)
1093*5e7646d2SAndroid Build Coastguard Worker     {
1094*5e7646d2SAndroid Build Coastguard Worker      /*
1095*5e7646d2SAndroid Build Coastguard Worker       * Check whether the requested compression is supported and/or default to
1096*5e7646d2SAndroid Build Coastguard Worker       * compression if supported...
1097*5e7646d2SAndroid Build Coastguard Worker       */
1098*5e7646d2SAndroid Build Coastguard Worker 
1099*5e7646d2SAndroid Build Coastguard Worker       if (compression && !ippContainsString(compression_sup, compression))
1100*5e7646d2SAndroid Build Coastguard Worker       {
1101*5e7646d2SAndroid Build Coastguard Worker         fprintf(stderr, "DEBUG: Printer does not support the requested "
1102*5e7646d2SAndroid Build Coastguard Worker                         "compression value \"%s\".\n", compression);
1103*5e7646d2SAndroid Build Coastguard Worker         compression = NULL;
1104*5e7646d2SAndroid Build Coastguard Worker       }
1105*5e7646d2SAndroid Build Coastguard Worker       else if (!compression && (!strcmp(final_content_type, "image/pwg-raster") || !strcmp(final_content_type, "image/urf")))
1106*5e7646d2SAndroid Build Coastguard Worker       {
1107*5e7646d2SAndroid Build Coastguard Worker         if (ippContainsString(compression_sup, "gzip"))
1108*5e7646d2SAndroid Build Coastguard Worker           compression = "gzip";
1109*5e7646d2SAndroid Build Coastguard Worker         else if (ippContainsString(compression_sup, "deflate"))
1110*5e7646d2SAndroid Build Coastguard Worker           compression = "deflate";
1111*5e7646d2SAndroid Build Coastguard Worker 
1112*5e7646d2SAndroid Build Coastguard Worker         if (compression)
1113*5e7646d2SAndroid Build Coastguard Worker           fprintf(stderr, "DEBUG: Automatically using \"%s\" compression.\n",
1114*5e7646d2SAndroid Build Coastguard Worker                   compression);
1115*5e7646d2SAndroid Build Coastguard Worker       }
1116*5e7646d2SAndroid Build Coastguard Worker     }
1117*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_LIBZ */
1118*5e7646d2SAndroid Build Coastguard Worker 
1119*5e7646d2SAndroid Build Coastguard Worker     if ((copies_sup = ippFindAttribute(supported, "copies-supported",
1120*5e7646d2SAndroid Build Coastguard Worker 	                               IPP_TAG_RANGE)) != NULL)
1121*5e7646d2SAndroid Build Coastguard Worker     {
1122*5e7646d2SAndroid Build Coastguard Worker      /*
1123*5e7646d2SAndroid Build Coastguard Worker       * Has the "copies-supported" attribute - does it have an upper
1124*5e7646d2SAndroid Build Coastguard Worker       * bound > 1?
1125*5e7646d2SAndroid Build Coastguard Worker       */
1126*5e7646d2SAndroid Build Coastguard Worker 
1127*5e7646d2SAndroid Build Coastguard Worker       fprintf(stderr, "DEBUG: copies-supported=%d-%d\n",
1128*5e7646d2SAndroid Build Coastguard Worker 	      copies_sup->values[0].range.lower,
1129*5e7646d2SAndroid Build Coastguard Worker 	      copies_sup->values[0].range.upper);
1130*5e7646d2SAndroid Build Coastguard Worker 
1131*5e7646d2SAndroid Build Coastguard Worker       if (copies_sup->values[0].range.upper <= 1)
1132*5e7646d2SAndroid Build Coastguard Worker 	copies_sup = NULL; /* No */
1133*5e7646d2SAndroid Build Coastguard Worker     }
1134*5e7646d2SAndroid Build Coastguard Worker 
1135*5e7646d2SAndroid Build Coastguard Worker     if ((cups_version = ippFindAttribute(supported, "cups-version", IPP_TAG_TEXT)) != NULL)
1136*5e7646d2SAndroid Build Coastguard Worker     {
1137*5e7646d2SAndroid Build Coastguard Worker       const char *val = ippGetString(cups_version, 0, NULL);
1138*5e7646d2SAndroid Build Coastguard Worker 
1139*5e7646d2SAndroid Build Coastguard Worker       fprintf(stderr, "DEBUG: cups-version = \"%s\"\n", val);
1140*5e7646d2SAndroid Build Coastguard Worker       if (!strcmp(val, "cups-version"))
1141*5e7646d2SAndroid Build Coastguard Worker         cups_version = NULL;		/* Bogus cups-version value returned by buggy printers! */
1142*5e7646d2SAndroid Build Coastguard Worker     }
1143*5e7646d2SAndroid Build Coastguard Worker 
1144*5e7646d2SAndroid Build Coastguard Worker     encryption_sup = ippFindAttribute(supported, "job-password-encryption-supported", IPP_TAG_KEYWORD);
1145*5e7646d2SAndroid Build Coastguard Worker 
1146*5e7646d2SAndroid Build Coastguard Worker     if ((format_sup = ippFindAttribute(supported, "document-format-supported",
1147*5e7646d2SAndroid Build Coastguard Worker 	                               IPP_TAG_MIMETYPE)) != NULL)
1148*5e7646d2SAndroid Build Coastguard Worker     {
1149*5e7646d2SAndroid Build Coastguard Worker       fprintf(stderr, "DEBUG: document-format-supported (%d values)\n",
1150*5e7646d2SAndroid Build Coastguard Worker 	      format_sup->num_values);
1151*5e7646d2SAndroid Build Coastguard Worker       for (i = 0; i < format_sup->num_values; i ++)
1152*5e7646d2SAndroid Build Coastguard Worker 	fprintf(stderr, "DEBUG: [%d] = \"%s\"\n", i,
1153*5e7646d2SAndroid Build Coastguard Worker 	        format_sup->values[i].string.text);
1154*5e7646d2SAndroid Build Coastguard Worker     }
1155*5e7646d2SAndroid Build Coastguard Worker 
1156*5e7646d2SAndroid Build Coastguard Worker     if ((media_col_sup = ippFindAttribute(supported, "media-col-supported",
1157*5e7646d2SAndroid Build Coastguard Worker 	                                  IPP_TAG_KEYWORD)) != NULL)
1158*5e7646d2SAndroid Build Coastguard Worker     {
1159*5e7646d2SAndroid Build Coastguard Worker       fprintf(stderr, "DEBUG: media-col-supported (%d values)\n",
1160*5e7646d2SAndroid Build Coastguard Worker 	      media_col_sup->num_values);
1161*5e7646d2SAndroid Build Coastguard Worker       for (i = 0; i < media_col_sup->num_values; i ++)
1162*5e7646d2SAndroid Build Coastguard Worker 	fprintf(stderr, "DEBUG: [%d] = \"%s\"\n", i,
1163*5e7646d2SAndroid Build Coastguard Worker 	        media_col_sup->values[i].string.text);
1164*5e7646d2SAndroid Build Coastguard Worker     }
1165*5e7646d2SAndroid Build Coastguard Worker 
1166*5e7646d2SAndroid Build Coastguard Worker     print_color_mode_sup = ippFindAttribute(supported, "print-color-mode-supported", IPP_TAG_KEYWORD);
1167*5e7646d2SAndroid Build Coastguard Worker 
1168*5e7646d2SAndroid Build Coastguard Worker     if ((operations_sup = ippFindAttribute(supported, "operations-supported",
1169*5e7646d2SAndroid Build Coastguard Worker 					   IPP_TAG_ENUM)) != NULL)
1170*5e7646d2SAndroid Build Coastguard Worker     {
1171*5e7646d2SAndroid Build Coastguard Worker       fprintf(stderr, "DEBUG: operations-supported (%d values)\n",
1172*5e7646d2SAndroid Build Coastguard Worker               operations_sup->num_values);
1173*5e7646d2SAndroid Build Coastguard Worker       for (i = 0; i < operations_sup->num_values; i ++)
1174*5e7646d2SAndroid Build Coastguard Worker         fprintf(stderr, "DEBUG: [%d] = %s\n", i,
1175*5e7646d2SAndroid Build Coastguard Worker                 ippOpString(operations_sup->values[i].integer));
1176*5e7646d2SAndroid Build Coastguard Worker 
1177*5e7646d2SAndroid Build Coastguard Worker       for (i = 0; i < operations_sup->num_values; i ++)
1178*5e7646d2SAndroid Build Coastguard Worker         if (operations_sup->values[i].integer == IPP_OP_PRINT_JOB)
1179*5e7646d2SAndroid Build Coastguard Worker 	  break;
1180*5e7646d2SAndroid Build Coastguard Worker 
1181*5e7646d2SAndroid Build Coastguard Worker       if (i >= operations_sup->num_values)
1182*5e7646d2SAndroid Build Coastguard Worker 	update_reasons(NULL, "+cups-ipp-conformance-failure-report,"
1183*5e7646d2SAndroid Build Coastguard Worker 			     "cups-ipp-missing-print-job");
1184*5e7646d2SAndroid Build Coastguard Worker 
1185*5e7646d2SAndroid Build Coastguard Worker       for (i = 0; i < operations_sup->num_values; i ++)
1186*5e7646d2SAndroid Build Coastguard Worker         if (operations_sup->values[i].integer == IPP_OP_CANCEL_JOB)
1187*5e7646d2SAndroid Build Coastguard Worker 	  break;
1188*5e7646d2SAndroid Build Coastguard Worker 
1189*5e7646d2SAndroid Build Coastguard Worker       if (i >= operations_sup->num_values)
1190*5e7646d2SAndroid Build Coastguard Worker 	update_reasons(NULL, "+cups-ipp-conformance-failure-report,"
1191*5e7646d2SAndroid Build Coastguard Worker 			     "cups-ipp-missing-cancel-job");
1192*5e7646d2SAndroid Build Coastguard Worker 
1193*5e7646d2SAndroid Build Coastguard Worker       for (i = 0; i < operations_sup->num_values; i ++)
1194*5e7646d2SAndroid Build Coastguard Worker         if (operations_sup->values[i].integer == IPP_OP_GET_JOB_ATTRIBUTES)
1195*5e7646d2SAndroid Build Coastguard Worker 	  break;
1196*5e7646d2SAndroid Build Coastguard Worker 
1197*5e7646d2SAndroid Build Coastguard Worker       if (i >= operations_sup->num_values)
1198*5e7646d2SAndroid Build Coastguard Worker 	update_reasons(NULL, "+cups-ipp-conformance-failure-report,"
1199*5e7646d2SAndroid Build Coastguard Worker                              "cups-ipp-missing-get-job-attributes");
1200*5e7646d2SAndroid Build Coastguard Worker 
1201*5e7646d2SAndroid Build Coastguard Worker       for (i = 0; i < operations_sup->num_values; i ++)
1202*5e7646d2SAndroid Build Coastguard Worker         if (operations_sup->values[i].integer == IPP_OP_GET_PRINTER_ATTRIBUTES)
1203*5e7646d2SAndroid Build Coastguard Worker 	  break;
1204*5e7646d2SAndroid Build Coastguard Worker 
1205*5e7646d2SAndroid Build Coastguard Worker       if (i >= operations_sup->num_values)
1206*5e7646d2SAndroid Build Coastguard Worker 	update_reasons(NULL, "+cups-ipp-conformance-failure-report,"
1207*5e7646d2SAndroid Build Coastguard Worker 			     "cups-ipp-missing-get-printer-attributes");
1208*5e7646d2SAndroid Build Coastguard Worker 
1209*5e7646d2SAndroid Build Coastguard Worker       for (i = 0; i < operations_sup->num_values; i ++)
1210*5e7646d2SAndroid Build Coastguard Worker       {
1211*5e7646d2SAndroid Build Coastguard Worker         if (operations_sup->values[i].integer == IPP_OP_VALIDATE_JOB)
1212*5e7646d2SAndroid Build Coastguard Worker 	  validate_job = 1;
1213*5e7646d2SAndroid Build Coastguard Worker         else if (operations_sup->values[i].integer == IPP_OP_CREATE_JOB)
1214*5e7646d2SAndroid Build Coastguard Worker 	  create_job = 1;
1215*5e7646d2SAndroid Build Coastguard Worker         else if (operations_sup->values[i].integer == IPP_OP_SEND_DOCUMENT)
1216*5e7646d2SAndroid Build Coastguard Worker 	  send_document = 1;
1217*5e7646d2SAndroid Build Coastguard Worker         else if (operations_sup->values[i].integer == IPP_OP_GET_JOB_ATTRIBUTES)
1218*5e7646d2SAndroid Build Coastguard Worker 	  get_job_attrs = 1;
1219*5e7646d2SAndroid Build Coastguard Worker       }
1220*5e7646d2SAndroid Build Coastguard Worker 
1221*5e7646d2SAndroid Build Coastguard Worker       if (create_job && !send_document)
1222*5e7646d2SAndroid Build Coastguard Worker       {
1223*5e7646d2SAndroid Build Coastguard Worker         fputs("DEBUG: Printer supports Create-Job but not Send-Document.\n",
1224*5e7646d2SAndroid Build Coastguard Worker               stderr);
1225*5e7646d2SAndroid Build Coastguard Worker         create_job = 0;
1226*5e7646d2SAndroid Build Coastguard Worker 
1227*5e7646d2SAndroid Build Coastguard Worker 	update_reasons(NULL, "+cups-ipp-conformance-failure-report,"
1228*5e7646d2SAndroid Build Coastguard Worker                              "cups-ipp-missing-send-document");
1229*5e7646d2SAndroid Build Coastguard Worker       }
1230*5e7646d2SAndroid Build Coastguard Worker 
1231*5e7646d2SAndroid Build Coastguard Worker       if (!validate_job)
1232*5e7646d2SAndroid Build Coastguard Worker 	update_reasons(NULL, "+cups-ipp-conformance-failure-report,"
1233*5e7646d2SAndroid Build Coastguard Worker                              "cups-ipp-missing-validate-job");
1234*5e7646d2SAndroid Build Coastguard Worker     }
1235*5e7646d2SAndroid Build Coastguard Worker     else
1236*5e7646d2SAndroid Build Coastguard Worker       update_reasons(NULL, "+cups-ipp-conformance-failure-report,"
1237*5e7646d2SAndroid Build Coastguard Worker 			   "cups-ipp-missing-operations-supported");
1238*5e7646d2SAndroid Build Coastguard Worker 
1239*5e7646d2SAndroid Build Coastguard Worker     doc_handling_sup = ippFindAttribute(supported,
1240*5e7646d2SAndroid Build Coastguard Worker 					"multiple-document-handling-supported",
1241*5e7646d2SAndroid Build Coastguard Worker 					IPP_TAG_KEYWORD);
1242*5e7646d2SAndroid Build Coastguard Worker 
1243*5e7646d2SAndroid Build Coastguard Worker     report_printer_state(supported);
1244*5e7646d2SAndroid Build Coastguard Worker   }
1245*5e7646d2SAndroid Build Coastguard Worker   while (!job_canceled && ipp_status > IPP_STATUS_OK_CONFLICTING);
1246*5e7646d2SAndroid Build Coastguard Worker 
1247*5e7646d2SAndroid Build Coastguard Worker   if (job_canceled)
1248*5e7646d2SAndroid Build Coastguard Worker     return (CUPS_BACKEND_OK);
1249*5e7646d2SAndroid Build Coastguard Worker 
1250*5e7646d2SAndroid Build Coastguard Worker  /*
1251*5e7646d2SAndroid Build Coastguard Worker   * See if the printer is accepting jobs and is not stopped; if either
1252*5e7646d2SAndroid Build Coastguard Worker   * condition is true and we are printing to a class, requeue the job...
1253*5e7646d2SAndroid Build Coastguard Worker   */
1254*5e7646d2SAndroid Build Coastguard Worker 
1255*5e7646d2SAndroid Build Coastguard Worker   if (getenv("CLASS") != NULL)
1256*5e7646d2SAndroid Build Coastguard Worker   {
1257*5e7646d2SAndroid Build Coastguard Worker     printer_state     = ippFindAttribute(supported, "printer-state",
1258*5e7646d2SAndroid Build Coastguard Worker                                 	 IPP_TAG_ENUM);
1259*5e7646d2SAndroid Build Coastguard Worker     printer_accepting = ippFindAttribute(supported, "printer-is-accepting-jobs",
1260*5e7646d2SAndroid Build Coastguard Worker                                 	 IPP_TAG_BOOLEAN);
1261*5e7646d2SAndroid Build Coastguard Worker 
1262*5e7646d2SAndroid Build Coastguard Worker     if (printer_state == NULL ||
1263*5e7646d2SAndroid Build Coastguard Worker 	(printer_state->values[0].integer > IPP_PSTATE_PROCESSING &&
1264*5e7646d2SAndroid Build Coastguard Worker 	 waitprinter) ||
1265*5e7646d2SAndroid Build Coastguard Worker 	printer_accepting == NULL ||
1266*5e7646d2SAndroid Build Coastguard Worker 	!printer_accepting->values[0].boolean)
1267*5e7646d2SAndroid Build Coastguard Worker     {
1268*5e7646d2SAndroid Build Coastguard Worker      /*
1269*5e7646d2SAndroid Build Coastguard Worker       * If the CLASS environment variable is set, the job was submitted
1270*5e7646d2SAndroid Build Coastguard Worker       * to a class and not to a specific queue.  In this case, we want
1271*5e7646d2SAndroid Build Coastguard Worker       * to abort immediately so that the job can be requeued on the next
1272*5e7646d2SAndroid Build Coastguard Worker       * available printer in the class.
1273*5e7646d2SAndroid Build Coastguard Worker       */
1274*5e7646d2SAndroid Build Coastguard Worker 
1275*5e7646d2SAndroid Build Coastguard Worker       _cupsLangPrintFilter(stderr, "INFO",
1276*5e7646d2SAndroid Build Coastguard Worker                            _("Unable to contact printer, queuing on next "
1277*5e7646d2SAndroid Build Coastguard Worker 		             "printer in class."));
1278*5e7646d2SAndroid Build Coastguard Worker 
1279*5e7646d2SAndroid Build Coastguard Worker       ippDelete(supported);
1280*5e7646d2SAndroid Build Coastguard Worker       httpClose(http);
1281*5e7646d2SAndroid Build Coastguard Worker 
1282*5e7646d2SAndroid Build Coastguard Worker      /*
1283*5e7646d2SAndroid Build Coastguard Worker       * Sleep 5 seconds to keep the job from requeuing too rapidly...
1284*5e7646d2SAndroid Build Coastguard Worker       */
1285*5e7646d2SAndroid Build Coastguard Worker 
1286*5e7646d2SAndroid Build Coastguard Worker       sleep(5);
1287*5e7646d2SAndroid Build Coastguard Worker 
1288*5e7646d2SAndroid Build Coastguard Worker       return (CUPS_BACKEND_FAILED);
1289*5e7646d2SAndroid Build Coastguard Worker     }
1290*5e7646d2SAndroid Build Coastguard Worker   }
1291*5e7646d2SAndroid Build Coastguard Worker 
1292*5e7646d2SAndroid Build Coastguard Worker  /*
1293*5e7646d2SAndroid Build Coastguard Worker   * See if the printer supports multiple copies...
1294*5e7646d2SAndroid Build Coastguard Worker   */
1295*5e7646d2SAndroid Build Coastguard Worker 
1296*5e7646d2SAndroid Build Coastguard Worker   copies = atoi(argv[4]);
1297*5e7646d2SAndroid Build Coastguard Worker 
1298*5e7646d2SAndroid Build Coastguard Worker   if (copies_sup || argc < 7)
1299*5e7646d2SAndroid Build Coastguard Worker     copies_remaining = 1;
1300*5e7646d2SAndroid Build Coastguard Worker   else
1301*5e7646d2SAndroid Build Coastguard Worker     copies_remaining = copies;
1302*5e7646d2SAndroid Build Coastguard Worker 
1303*5e7646d2SAndroid Build Coastguard Worker  /*
1304*5e7646d2SAndroid Build Coastguard Worker   * Prepare remaining printing options...
1305*5e7646d2SAndroid Build Coastguard Worker   */
1306*5e7646d2SAndroid Build Coastguard Worker 
1307*5e7646d2SAndroid Build Coastguard Worker   options = NULL;
1308*5e7646d2SAndroid Build Coastguard Worker 
1309*5e7646d2SAndroid Build Coastguard Worker   if (send_options)
1310*5e7646d2SAndroid Build Coastguard Worker   {
1311*5e7646d2SAndroid Build Coastguard Worker     num_options = cupsParseOptions(argv[5], 0, &options);
1312*5e7646d2SAndroid Build Coastguard Worker 
1313*5e7646d2SAndroid Build Coastguard Worker     if (!cups_version && media_col_sup)
1314*5e7646d2SAndroid Build Coastguard Worker     {
1315*5e7646d2SAndroid Build Coastguard Worker      /*
1316*5e7646d2SAndroid Build Coastguard Worker       * Load the PPD file and generate PWG attribute mapping information...
1317*5e7646d2SAndroid Build Coastguard Worker       */
1318*5e7646d2SAndroid Build Coastguard Worker 
1319*5e7646d2SAndroid Build Coastguard Worker       ppd_attr_t *mandatory;		/* cupsMandatory value */
1320*5e7646d2SAndroid Build Coastguard Worker 
1321*5e7646d2SAndroid Build Coastguard Worker       ppd = ppdOpenFile(getenv("PPD"));
1322*5e7646d2SAndroid Build Coastguard Worker       pc  = _ppdCacheCreateWithPPD(ppd);
1323*5e7646d2SAndroid Build Coastguard Worker 
1324*5e7646d2SAndroid Build Coastguard Worker       ppdMarkDefaults(ppd);
1325*5e7646d2SAndroid Build Coastguard Worker       cupsMarkOptions(ppd, num_options, options);
1326*5e7646d2SAndroid Build Coastguard Worker 
1327*5e7646d2SAndroid Build Coastguard Worker       if ((mandatory = ppdFindAttr(ppd, "cupsMandatory", NULL)) != NULL)
1328*5e7646d2SAndroid Build Coastguard Worker         strlcpy(mandatory_attrs, mandatory->value, sizeof(mandatory_attrs));
1329*5e7646d2SAndroid Build Coastguard Worker     }
1330*5e7646d2SAndroid Build Coastguard Worker 
1331*5e7646d2SAndroid Build Coastguard Worker    /*
1332*5e7646d2SAndroid Build Coastguard Worker     * Validate job-password/-encryption...
1333*5e7646d2SAndroid Build Coastguard Worker     */
1334*5e7646d2SAndroid Build Coastguard Worker 
1335*5e7646d2SAndroid Build Coastguard Worker     if (cupsGetOption("job-password", num_options, options))
1336*5e7646d2SAndroid Build Coastguard Worker     {
1337*5e7646d2SAndroid Build Coastguard Worker       const char *keyword;		/* job-password-encryption value */
1338*5e7646d2SAndroid Build Coastguard Worker       static const char * const hashes[] =
1339*5e7646d2SAndroid Build Coastguard Worker       {					/* List of supported hash algorithms, in order of preference */
1340*5e7646d2SAndroid Build Coastguard Worker         "sha-512",
1341*5e7646d2SAndroid Build Coastguard Worker         "sha-384",
1342*5e7646d2SAndroid Build Coastguard Worker         "sha-512_256",
1343*5e7646d2SAndroid Build Coastguard Worker         "sha-512-224",
1344*5e7646d2SAndroid Build Coastguard Worker         "sha-256",
1345*5e7646d2SAndroid Build Coastguard Worker         "sha-224",
1346*5e7646d2SAndroid Build Coastguard Worker         "sha",
1347*5e7646d2SAndroid Build Coastguard Worker         "none"
1348*5e7646d2SAndroid Build Coastguard Worker       };
1349*5e7646d2SAndroid Build Coastguard Worker 
1350*5e7646d2SAndroid Build Coastguard Worker       if ((keyword = cupsGetOption("job-password-encryption", num_options, options)) == NULL || !ippContainsString(encryption_sup, keyword))
1351*5e7646d2SAndroid Build Coastguard Worker       {
1352*5e7646d2SAndroid Build Coastguard Worker        /*
1353*5e7646d2SAndroid Build Coastguard Worker         * Either no job-password-encryption or the value isn't supported by
1354*5e7646d2SAndroid Build Coastguard Worker         * the printer...
1355*5e7646d2SAndroid Build Coastguard Worker         */
1356*5e7646d2SAndroid Build Coastguard Worker 
1357*5e7646d2SAndroid Build Coastguard Worker         for (i = 0; i < (int)(sizeof(hashes) / sizeof(hashes[0])); i ++)
1358*5e7646d2SAndroid Build Coastguard Worker           if (ippContainsString(encryption_sup, hashes[i]))
1359*5e7646d2SAndroid Build Coastguard Worker             break;
1360*5e7646d2SAndroid Build Coastguard Worker 
1361*5e7646d2SAndroid Build Coastguard Worker         if (i < (int)(sizeof(hashes) / sizeof(hashes[0])))
1362*5e7646d2SAndroid Build Coastguard Worker           num_options = cupsAddOption("job-password-encryption", hashes[i], num_options, &options);
1363*5e7646d2SAndroid Build Coastguard Worker       }
1364*5e7646d2SAndroid Build Coastguard Worker     }
1365*5e7646d2SAndroid Build Coastguard Worker   }
1366*5e7646d2SAndroid Build Coastguard Worker   else
1367*5e7646d2SAndroid Build Coastguard Worker     num_options = 0;
1368*5e7646d2SAndroid Build Coastguard Worker 
1369*5e7646d2SAndroid Build Coastguard Worker   document_format = NULL;
1370*5e7646d2SAndroid Build Coastguard Worker 
1371*5e7646d2SAndroid Build Coastguard Worker   if (format_sup != NULL)
1372*5e7646d2SAndroid Build Coastguard Worker   {
1373*5e7646d2SAndroid Build Coastguard Worker     if (ippContainsString(format_sup, final_content_type))
1374*5e7646d2SAndroid Build Coastguard Worker       document_format = final_content_type;
1375*5e7646d2SAndroid Build Coastguard Worker     else if (ippContainsString(format_sup, "application/octet-stream"))
1376*5e7646d2SAndroid Build Coastguard Worker       document_format = "application/octet-stream";
1377*5e7646d2SAndroid Build Coastguard Worker   }
1378*5e7646d2SAndroid Build Coastguard Worker 
1379*5e7646d2SAndroid Build Coastguard Worker   fprintf(stderr, "DEBUG: final_content_type=\"%s\", document_format=\"%s\"\n",
1380*5e7646d2SAndroid Build Coastguard Worker           final_content_type, document_format ? document_format : "(null)");
1381*5e7646d2SAndroid Build Coastguard Worker 
1382*5e7646d2SAndroid Build Coastguard Worker  /*
1383*5e7646d2SAndroid Build Coastguard Worker   * If the printer does not support HTTP/1.1 (which IPP requires), copy stdin
1384*5e7646d2SAndroid Build Coastguard Worker   * to a temporary file so that we can do a HTTP/1.0 submission...
1385*5e7646d2SAndroid Build Coastguard Worker   *
1386*5e7646d2SAndroid Build Coastguard Worker   * (I hate compatibility hacks!)
1387*5e7646d2SAndroid Build Coastguard Worker   */
1388*5e7646d2SAndroid Build Coastguard Worker 
1389*5e7646d2SAndroid Build Coastguard Worker   if (http->version < HTTP_VERSION_1_1 && num_files == 0)
1390*5e7646d2SAndroid Build Coastguard Worker   {
1391*5e7646d2SAndroid Build Coastguard Worker     if ((fd = cupsTempFd(tmpfilename, sizeof(tmpfilename))) < 0)
1392*5e7646d2SAndroid Build Coastguard Worker     {
1393*5e7646d2SAndroid Build Coastguard Worker       perror("DEBUG: Unable to create temporary file");
1394*5e7646d2SAndroid Build Coastguard Worker       return (CUPS_BACKEND_FAILED);
1395*5e7646d2SAndroid Build Coastguard Worker     }
1396*5e7646d2SAndroid Build Coastguard Worker 
1397*5e7646d2SAndroid Build Coastguard Worker     _cupsLangPrintFilter(stderr, "INFO", _("Copying print data."));
1398*5e7646d2SAndroid Build Coastguard Worker 
1399*5e7646d2SAndroid Build Coastguard Worker     if ((compatsize = write(fd, buffer, (size_t)bytes)) < 0)
1400*5e7646d2SAndroid Build Coastguard Worker     {
1401*5e7646d2SAndroid Build Coastguard Worker       perror("DEBUG: Unable to write temporary file");
1402*5e7646d2SAndroid Build Coastguard Worker       return (CUPS_BACKEND_FAILED);
1403*5e7646d2SAndroid Build Coastguard Worker     }
1404*5e7646d2SAndroid Build Coastguard Worker 
1405*5e7646d2SAndroid Build Coastguard Worker     if ((bytes = backendRunLoop(-1, fd, snmp_fd, &(addrlist->addr), 0, 0,
1406*5e7646d2SAndroid Build Coastguard Worker 		                backendNetworkSideCB)) < 0)
1407*5e7646d2SAndroid Build Coastguard Worker       return (CUPS_BACKEND_FAILED);
1408*5e7646d2SAndroid Build Coastguard Worker 
1409*5e7646d2SAndroid Build Coastguard Worker     compatsize += bytes;
1410*5e7646d2SAndroid Build Coastguard Worker 
1411*5e7646d2SAndroid Build Coastguard Worker     close(fd);
1412*5e7646d2SAndroid Build Coastguard Worker 
1413*5e7646d2SAndroid Build Coastguard Worker     compatfile = tmpfilename;
1414*5e7646d2SAndroid Build Coastguard Worker     files      = &compatfile;
1415*5e7646d2SAndroid Build Coastguard Worker     num_files  = 1;
1416*5e7646d2SAndroid Build Coastguard Worker   }
1417*5e7646d2SAndroid Build Coastguard Worker   else if (http->version < HTTP_VERSION_1_1 && num_files == 1)
1418*5e7646d2SAndroid Build Coastguard Worker   {
1419*5e7646d2SAndroid Build Coastguard Worker     struct stat	fileinfo;		/* File information */
1420*5e7646d2SAndroid Build Coastguard Worker 
1421*5e7646d2SAndroid Build Coastguard Worker     if (!stat(files[0], &fileinfo))
1422*5e7646d2SAndroid Build Coastguard Worker       compatsize = fileinfo.st_size;
1423*5e7646d2SAndroid Build Coastguard Worker   }
1424*5e7646d2SAndroid Build Coastguard Worker 
1425*5e7646d2SAndroid Build Coastguard Worker  /*
1426*5e7646d2SAndroid Build Coastguard Worker   * If the printer only claims to support IPP/1.0, or if the user specifically
1427*5e7646d2SAndroid Build Coastguard Worker   * included version=1.0 in the URI, then do not try to use Create-Job or
1428*5e7646d2SAndroid Build Coastguard Worker   * Send-Document.  This is another dreaded compatibility hack, but
1429*5e7646d2SAndroid Build Coastguard Worker   * unfortunately there are enough broken printers out there that we need
1430*5e7646d2SAndroid Build Coastguard Worker   * this for now...
1431*5e7646d2SAndroid Build Coastguard Worker   */
1432*5e7646d2SAndroid Build Coastguard Worker 
1433*5e7646d2SAndroid Build Coastguard Worker   if (version == 10)
1434*5e7646d2SAndroid Build Coastguard Worker     create_job = send_document = 0;
1435*5e7646d2SAndroid Build Coastguard Worker 
1436*5e7646d2SAndroid Build Coastguard Worker  /*
1437*5e7646d2SAndroid Build Coastguard Worker   * Start monitoring the printer in the background...
1438*5e7646d2SAndroid Build Coastguard Worker   */
1439*5e7646d2SAndroid Build Coastguard Worker 
1440*5e7646d2SAndroid Build Coastguard Worker   monitor.uri           = uri;
1441*5e7646d2SAndroid Build Coastguard Worker   monitor.hostname      = hostname;
1442*5e7646d2SAndroid Build Coastguard Worker   monitor.user          = argv[2];
1443*5e7646d2SAndroid Build Coastguard Worker   monitor.resource      = resource;
1444*5e7646d2SAndroid Build Coastguard Worker   monitor.port          = port;
1445*5e7646d2SAndroid Build Coastguard Worker   monitor.version       = version;
1446*5e7646d2SAndroid Build Coastguard Worker   monitor.job_id        = 0;
1447*5e7646d2SAndroid Build Coastguard Worker   monitor.create_job    = create_job;
1448*5e7646d2SAndroid Build Coastguard Worker   monitor.get_job_attrs = get_job_attrs;
1449*5e7646d2SAndroid Build Coastguard Worker   monitor.encryption    = cupsEncryption();
1450*5e7646d2SAndroid Build Coastguard Worker   monitor.job_state     = IPP_JSTATE_PENDING;
1451*5e7646d2SAndroid Build Coastguard Worker   monitor.printer_state = IPP_PSTATE_IDLE;
1452*5e7646d2SAndroid Build Coastguard Worker   monitor.retryable     = argc == 6 && document_format && strcmp(document_format, "image/pwg-raster") && strcmp(document_format, "image/urf");
1453*5e7646d2SAndroid Build Coastguard Worker 
1454*5e7646d2SAndroid Build Coastguard Worker   fprintf(stderr, "DEBUG: retryable=%d\n", monitor.retryable);
1455*5e7646d2SAndroid Build Coastguard Worker 
1456*5e7646d2SAndroid Build Coastguard Worker   if (create_job)
1457*5e7646d2SAndroid Build Coastguard Worker   {
1458*5e7646d2SAndroid Build Coastguard Worker     monitor.job_name = argv[3];
1459*5e7646d2SAndroid Build Coastguard Worker   }
1460*5e7646d2SAndroid Build Coastguard Worker   else
1461*5e7646d2SAndroid Build Coastguard Worker   {
1462*5e7646d2SAndroid Build Coastguard Worker     snprintf(print_job_name, sizeof(print_job_name), "%s - %s", argv[1],
1463*5e7646d2SAndroid Build Coastguard Worker              argv[3]);
1464*5e7646d2SAndroid Build Coastguard Worker     monitor.job_name = print_job_name;
1465*5e7646d2SAndroid Build Coastguard Worker   }
1466*5e7646d2SAndroid Build Coastguard Worker 
1467*5e7646d2SAndroid Build Coastguard Worker   _cupsThreadCreate((_cups_thread_func_t)monitor_printer, &monitor);
1468*5e7646d2SAndroid Build Coastguard Worker 
1469*5e7646d2SAndroid Build Coastguard Worker  /*
1470*5e7646d2SAndroid Build Coastguard Worker   * Validate access to the printer...
1471*5e7646d2SAndroid Build Coastguard Worker   */
1472*5e7646d2SAndroid Build Coastguard Worker 
1473*5e7646d2SAndroid Build Coastguard Worker   while (!job_canceled && validate_job)
1474*5e7646d2SAndroid Build Coastguard Worker   {
1475*5e7646d2SAndroid Build Coastguard Worker     request = new_request(IPP_OP_VALIDATE_JOB, version, uri, argv[2],
1476*5e7646d2SAndroid Build Coastguard Worker                           monitor.job_name, num_options, options, compression,
1477*5e7646d2SAndroid Build Coastguard Worker 			  copies_sup ? copies : 1, document_format, pc, ppd,
1478*5e7646d2SAndroid Build Coastguard Worker 			  media_col_sup, doc_handling_sup, print_color_mode_sup);
1479*5e7646d2SAndroid Build Coastguard Worker 
1480*5e7646d2SAndroid Build Coastguard Worker     response = cupsDoRequest(http, request, resource);
1481*5e7646d2SAndroid Build Coastguard Worker 
1482*5e7646d2SAndroid Build Coastguard Worker     ipp_status = cupsLastError();
1483*5e7646d2SAndroid Build Coastguard Worker 
1484*5e7646d2SAndroid Build Coastguard Worker     fprintf(stderr, "DEBUG: Validate-Job: %s (%s)\n",
1485*5e7646d2SAndroid Build Coastguard Worker             ippErrorString(ipp_status), cupsLastErrorString());
1486*5e7646d2SAndroid Build Coastguard Worker     debug_attributes(response);
1487*5e7646d2SAndroid Build Coastguard Worker 
1488*5e7646d2SAndroid Build Coastguard Worker     if ((job_auth = ippFindAttribute(response, "job-authorization-uri",
1489*5e7646d2SAndroid Build Coastguard Worker 				     IPP_TAG_URI)) != NULL)
1490*5e7646d2SAndroid Build Coastguard Worker       num_options = cupsAddOption("job-authorization-uri",
1491*5e7646d2SAndroid Build Coastguard Worker                                   ippGetString(job_auth, 0, NULL), num_options,
1492*5e7646d2SAndroid Build Coastguard Worker                                   &options);
1493*5e7646d2SAndroid Build Coastguard Worker 
1494*5e7646d2SAndroid Build Coastguard Worker     if (ipp_status == IPP_STATUS_OK_IGNORED_OR_SUBSTITUTED || ipp_status == IPP_STATUS_OK_CONFLICTING)
1495*5e7646d2SAndroid Build Coastguard Worker     {
1496*5e7646d2SAndroid Build Coastguard Worker      /*
1497*5e7646d2SAndroid Build Coastguard Worker       * One or more options are not supported...
1498*5e7646d2SAndroid Build Coastguard Worker       */
1499*5e7646d2SAndroid Build Coastguard Worker 
1500*5e7646d2SAndroid Build Coastguard Worker       ipp_attribute_t	*attr;		/* Unsupported attribute */
1501*5e7646d2SAndroid Build Coastguard Worker 
1502*5e7646d2SAndroid Build Coastguard Worker       if ((attr = ippFindAttribute(response, "sides", IPP_TAG_ZERO)) != NULL)
1503*5e7646d2SAndroid Build Coastguard Worker       {
1504*5e7646d2SAndroid Build Coastguard Worker        /*
1505*5e7646d2SAndroid Build Coastguard Worker         * The sides value is not supported, revert to one-sided as needed...
1506*5e7646d2SAndroid Build Coastguard Worker         */
1507*5e7646d2SAndroid Build Coastguard Worker 
1508*5e7646d2SAndroid Build Coastguard Worker         const char *sides = cupsGetOption("sides", num_options, options);
1509*5e7646d2SAndroid Build Coastguard Worker 
1510*5e7646d2SAndroid Build Coastguard Worker         if (!sides || !strncmp(sides, "two-sided-", 10))
1511*5e7646d2SAndroid Build Coastguard Worker         {
1512*5e7646d2SAndroid Build Coastguard Worker           fputs("DEBUG: Unable to do two-sided printing, setting sides to 'one-sided'.\n", stderr);
1513*5e7646d2SAndroid Build Coastguard Worker           num_options = cupsAddOption("sides", "one-sided", num_options, &options);
1514*5e7646d2SAndroid Build Coastguard Worker         }
1515*5e7646d2SAndroid Build Coastguard Worker       }
1516*5e7646d2SAndroid Build Coastguard Worker     }
1517*5e7646d2SAndroid Build Coastguard Worker 
1518*5e7646d2SAndroid Build Coastguard Worker     ippDelete(response);
1519*5e7646d2SAndroid Build Coastguard Worker 
1520*5e7646d2SAndroid Build Coastguard Worker     if (job_canceled)
1521*5e7646d2SAndroid Build Coastguard Worker       break;
1522*5e7646d2SAndroid Build Coastguard Worker 
1523*5e7646d2SAndroid Build Coastguard Worker     if (ipp_status == IPP_STATUS_ERROR_SERVICE_UNAVAILABLE ||
1524*5e7646d2SAndroid Build Coastguard Worker         ipp_status == IPP_STATUS_ERROR_BUSY)
1525*5e7646d2SAndroid Build Coastguard Worker     {
1526*5e7646d2SAndroid Build Coastguard Worker       _cupsLangPrintFilter(stderr, "INFO", _("The printer is in use."));
1527*5e7646d2SAndroid Build Coastguard Worker       sleep(10);
1528*5e7646d2SAndroid Build Coastguard Worker     }
1529*5e7646d2SAndroid Build Coastguard Worker     else if (ipp_status == IPP_STATUS_ERROR_DOCUMENT_FORMAT_NOT_SUPPORTED ||
1530*5e7646d2SAndroid Build Coastguard Worker              ipp_status == IPP_STATUS_ERROR_ATTRIBUTES_OR_VALUES ||
1531*5e7646d2SAndroid Build Coastguard Worker              ipp_status == IPP_STATUS_ERROR_CUPS_ACCOUNT_INFO_NEEDED ||
1532*5e7646d2SAndroid Build Coastguard Worker              ipp_status == IPP_STATUS_ERROR_CUPS_ACCOUNT_CLOSED ||
1533*5e7646d2SAndroid Build Coastguard Worker              ipp_status == IPP_STATUS_ERROR_CUPS_ACCOUNT_LIMIT_REACHED ||
1534*5e7646d2SAndroid Build Coastguard Worker              ipp_status == IPP_STATUS_ERROR_CUPS_ACCOUNT_AUTHORIZATION_FAILED)
1535*5e7646d2SAndroid Build Coastguard Worker       goto cleanup;
1536*5e7646d2SAndroid Build Coastguard Worker     else if (ipp_status == IPP_STATUS_ERROR_FORBIDDEN ||
1537*5e7646d2SAndroid Build Coastguard Worker              ipp_status == IPP_STATUS_ERROR_NOT_AUTHORIZED ||
1538*5e7646d2SAndroid Build Coastguard Worker 	     ipp_status == IPP_STATUS_ERROR_CUPS_AUTHENTICATION_CANCELED)
1539*5e7646d2SAndroid Build Coastguard Worker     {
1540*5e7646d2SAndroid Build Coastguard Worker       const char *www_auth = httpGetField(http, HTTP_FIELD_WWW_AUTHENTICATE);
1541*5e7646d2SAndroid Build Coastguard Worker 					/* WWW-Authenticate field value */
1542*5e7646d2SAndroid Build Coastguard Worker 
1543*5e7646d2SAndroid Build Coastguard Worker       if (!strncmp(www_auth, "Negotiate", 9))
1544*5e7646d2SAndroid Build Coastguard Worker 	auth_info_required = "negotiate";
1545*5e7646d2SAndroid Build Coastguard Worker       else if (www_auth[0])
1546*5e7646d2SAndroid Build Coastguard Worker 	auth_info_required = "username,password";
1547*5e7646d2SAndroid Build Coastguard Worker 
1548*5e7646d2SAndroid Build Coastguard Worker       goto cleanup;
1549*5e7646d2SAndroid Build Coastguard Worker     }
1550*5e7646d2SAndroid Build Coastguard Worker     else if (ipp_status == IPP_STATUS_ERROR_OPERATION_NOT_SUPPORTED)
1551*5e7646d2SAndroid Build Coastguard Worker     {
1552*5e7646d2SAndroid Build Coastguard Worker      /*
1553*5e7646d2SAndroid Build Coastguard Worker       * This is all too common...
1554*5e7646d2SAndroid Build Coastguard Worker       */
1555*5e7646d2SAndroid Build Coastguard Worker 
1556*5e7646d2SAndroid Build Coastguard Worker       update_reasons(NULL, "+cups-ipp-conformance-failure-report,"
1557*5e7646d2SAndroid Build Coastguard Worker 			   "cups-ipp-missing-validate-job");
1558*5e7646d2SAndroid Build Coastguard Worker       break;
1559*5e7646d2SAndroid Build Coastguard Worker     }
1560*5e7646d2SAndroid Build Coastguard Worker     else if (ipp_status < IPP_STATUS_REDIRECTION_OTHER_SITE ||
1561*5e7646d2SAndroid Build Coastguard Worker              ipp_status == IPP_STATUS_ERROR_BAD_REQUEST)
1562*5e7646d2SAndroid Build Coastguard Worker       break;
1563*5e7646d2SAndroid Build Coastguard Worker     else if (job_auth == NULL && ipp_status > IPP_STATUS_ERROR_BAD_REQUEST)
1564*5e7646d2SAndroid Build Coastguard Worker     {
1565*5e7646d2SAndroid Build Coastguard Worker       if (!validate_retried)
1566*5e7646d2SAndroid Build Coastguard Worker       {
1567*5e7646d2SAndroid Build Coastguard Worker         // Retry Validate-Job operation once, to work around known printer bug...
1568*5e7646d2SAndroid Build Coastguard Worker         validate_retried = 1;
1569*5e7646d2SAndroid Build Coastguard Worker         sleep(10);
1570*5e7646d2SAndroid Build Coastguard Worker         continue;
1571*5e7646d2SAndroid Build Coastguard Worker       }
1572*5e7646d2SAndroid Build Coastguard Worker 
1573*5e7646d2SAndroid Build Coastguard Worker       goto cleanup;
1574*5e7646d2SAndroid Build Coastguard Worker     }
1575*5e7646d2SAndroid Build Coastguard Worker   }
1576*5e7646d2SAndroid Build Coastguard Worker 
1577*5e7646d2SAndroid Build Coastguard Worker  /*
1578*5e7646d2SAndroid Build Coastguard Worker   * Then issue the print-job request...
1579*5e7646d2SAndroid Build Coastguard Worker   */
1580*5e7646d2SAndroid Build Coastguard Worker 
1581*5e7646d2SAndroid Build Coastguard Worker   job_id = 0;
1582*5e7646d2SAndroid Build Coastguard Worker 
1583*5e7646d2SAndroid Build Coastguard Worker   while (!job_canceled && copies_remaining > 0)
1584*5e7646d2SAndroid Build Coastguard Worker   {
1585*5e7646d2SAndroid Build Coastguard Worker    /*
1586*5e7646d2SAndroid Build Coastguard Worker     * Check for side-channel requests...
1587*5e7646d2SAndroid Build Coastguard Worker     */
1588*5e7646d2SAndroid Build Coastguard Worker 
1589*5e7646d2SAndroid Build Coastguard Worker     backendCheckSideChannel(snmp_fd, http->hostaddr);
1590*5e7646d2SAndroid Build Coastguard Worker 
1591*5e7646d2SAndroid Build Coastguard Worker    /*
1592*5e7646d2SAndroid Build Coastguard Worker     * Build the IPP job creation request...
1593*5e7646d2SAndroid Build Coastguard Worker     */
1594*5e7646d2SAndroid Build Coastguard Worker 
1595*5e7646d2SAndroid Build Coastguard Worker     if (job_canceled)
1596*5e7646d2SAndroid Build Coastguard Worker       break;
1597*5e7646d2SAndroid Build Coastguard Worker 
1598*5e7646d2SAndroid Build Coastguard Worker     request = new_request((num_files > 1 || create_job) ? IPP_OP_CREATE_JOB :
1599*5e7646d2SAndroid Build Coastguard Worker                                                           IPP_OP_PRINT_JOB,
1600*5e7646d2SAndroid Build Coastguard Worker 			  version, uri, argv[2], monitor.job_name, num_options,
1601*5e7646d2SAndroid Build Coastguard Worker 			  options, compression, copies_sup ? copies : 1,
1602*5e7646d2SAndroid Build Coastguard Worker 			  document_format, pc, ppd, media_col_sup,
1603*5e7646d2SAndroid Build Coastguard Worker 			  doc_handling_sup, print_color_mode_sup);
1604*5e7646d2SAndroid Build Coastguard Worker 
1605*5e7646d2SAndroid Build Coastguard Worker    /*
1606*5e7646d2SAndroid Build Coastguard Worker     * Do the request...
1607*5e7646d2SAndroid Build Coastguard Worker     */
1608*5e7646d2SAndroid Build Coastguard Worker 
1609*5e7646d2SAndroid Build Coastguard Worker     if (num_files > 1 || create_job)
1610*5e7646d2SAndroid Build Coastguard Worker       response = cupsDoRequest(http, request, resource);
1611*5e7646d2SAndroid Build Coastguard Worker     else
1612*5e7646d2SAndroid Build Coastguard Worker     {
1613*5e7646d2SAndroid Build Coastguard Worker       size_t	length = 0;		/* Length of request */
1614*5e7646d2SAndroid Build Coastguard Worker 
1615*5e7646d2SAndroid Build Coastguard Worker       if (compatsize > 0)
1616*5e7646d2SAndroid Build Coastguard Worker       {
1617*5e7646d2SAndroid Build Coastguard Worker         fputs("DEBUG: Sending file using HTTP/1.0 Content-Length...\n", stderr);
1618*5e7646d2SAndroid Build Coastguard Worker         length = ippLength(request) + (size_t)compatsize;
1619*5e7646d2SAndroid Build Coastguard Worker       }
1620*5e7646d2SAndroid Build Coastguard Worker       else
1621*5e7646d2SAndroid Build Coastguard Worker         fputs("DEBUG: Sending file using HTTP/1.1 chunking...\n", stderr);
1622*5e7646d2SAndroid Build Coastguard Worker 
1623*5e7646d2SAndroid Build Coastguard Worker       http_status = cupsSendRequest(http, request, resource, length);
1624*5e7646d2SAndroid Build Coastguard Worker       if (http_status == HTTP_STATUS_CONTINUE && request->state == IPP_STATE_DATA)
1625*5e7646d2SAndroid Build Coastguard Worker       {
1626*5e7646d2SAndroid Build Coastguard Worker 	if (compression && strcmp(compression, "none"))
1627*5e7646d2SAndroid Build Coastguard Worker 	  httpSetField(http, HTTP_FIELD_CONTENT_ENCODING, compression);
1628*5e7646d2SAndroid Build Coastguard Worker 
1629*5e7646d2SAndroid Build Coastguard Worker         if (num_files == 1)
1630*5e7646d2SAndroid Build Coastguard Worker         {
1631*5e7646d2SAndroid Build Coastguard Worker 	  if ((fd = open(files[0], O_RDONLY)) < 0)
1632*5e7646d2SAndroid Build Coastguard Worker 	  {
1633*5e7646d2SAndroid Build Coastguard Worker 	    _cupsLangPrintError("ERROR", _("Unable to open print file"));
1634*5e7646d2SAndroid Build Coastguard Worker 	    return (CUPS_BACKEND_FAILED);
1635*5e7646d2SAndroid Build Coastguard Worker 	  }
1636*5e7646d2SAndroid Build Coastguard Worker 	}
1637*5e7646d2SAndroid Build Coastguard Worker 	else
1638*5e7646d2SAndroid Build Coastguard Worker 	{
1639*5e7646d2SAndroid Build Coastguard Worker 	  fd          = 0;
1640*5e7646d2SAndroid Build Coastguard Worker 	  http_status = cupsWriteRequestData(http, buffer, (size_t)bytes);
1641*5e7646d2SAndroid Build Coastguard Worker         }
1642*5e7646d2SAndroid Build Coastguard Worker 
1643*5e7646d2SAndroid Build Coastguard Worker         while (http_status == HTTP_STATUS_CONTINUE &&
1644*5e7646d2SAndroid Build Coastguard Worker                (!job_canceled || compatsize > 0))
1645*5e7646d2SAndroid Build Coastguard Worker 	{
1646*5e7646d2SAndroid Build Coastguard Worker 	 /*
1647*5e7646d2SAndroid Build Coastguard Worker 	  * Check for side-channel requests and more print data...
1648*5e7646d2SAndroid Build Coastguard Worker 	  */
1649*5e7646d2SAndroid Build Coastguard Worker 
1650*5e7646d2SAndroid Build Coastguard Worker           FD_ZERO(&input);
1651*5e7646d2SAndroid Build Coastguard Worker 	  FD_SET(fd, &input);
1652*5e7646d2SAndroid Build Coastguard Worker 	  FD_SET(snmp_fd, &input);
1653*5e7646d2SAndroid Build Coastguard Worker 	  FD_SET(CUPS_SC_FD, &input);
1654*5e7646d2SAndroid Build Coastguard Worker 
1655*5e7646d2SAndroid Build Coastguard Worker           while (select(fd > snmp_fd ? fd + 1 : snmp_fd + 1, &input, NULL, NULL,
1656*5e7646d2SAndroid Build Coastguard Worker 	                NULL) <= 0 && !job_canceled);
1657*5e7646d2SAndroid Build Coastguard Worker 
1658*5e7646d2SAndroid Build Coastguard Worker 	  if (FD_ISSET(snmp_fd, &input))
1659*5e7646d2SAndroid Build Coastguard Worker 	    backendCheckSideChannel(snmp_fd, http->hostaddr);
1660*5e7646d2SAndroid Build Coastguard Worker 
1661*5e7646d2SAndroid Build Coastguard Worker           if (FD_ISSET(fd, &input))
1662*5e7646d2SAndroid Build Coastguard Worker           {
1663*5e7646d2SAndroid Build Coastguard Worker             if ((bytes = read(fd, buffer, sizeof(buffer))) > 0)
1664*5e7646d2SAndroid Build Coastguard Worker             {
1665*5e7646d2SAndroid Build Coastguard Worker 	      fprintf(stderr, "DEBUG: Read %d bytes...\n", (int)bytes);
1666*5e7646d2SAndroid Build Coastguard Worker 
1667*5e7646d2SAndroid Build Coastguard Worker 	      if ((http_status = cupsWriteRequestData(http, buffer, (size_t)bytes))
1668*5e7646d2SAndroid Build Coastguard Worker 	              != HTTP_STATUS_CONTINUE)
1669*5e7646d2SAndroid Build Coastguard Worker 		break;
1670*5e7646d2SAndroid Build Coastguard Worker 	    }
1671*5e7646d2SAndroid Build Coastguard Worker 	    else if (bytes == 0 || (errno != EINTR && errno != EAGAIN))
1672*5e7646d2SAndroid Build Coastguard Worker 	      break;
1673*5e7646d2SAndroid Build Coastguard Worker 	  }
1674*5e7646d2SAndroid Build Coastguard Worker 	}
1675*5e7646d2SAndroid Build Coastguard Worker 
1676*5e7646d2SAndroid Build Coastguard Worker 	if (http_status == HTTP_STATUS_ERROR)
1677*5e7646d2SAndroid Build Coastguard Worker 	  fprintf(stderr, "DEBUG: Error writing document data for "
1678*5e7646d2SAndroid Build Coastguard Worker 			  "Print-Job: %s\n", strerror(httpError(http)));
1679*5e7646d2SAndroid Build Coastguard Worker 
1680*5e7646d2SAndroid Build Coastguard Worker         if (num_files == 1)
1681*5e7646d2SAndroid Build Coastguard Worker 	  close(fd);
1682*5e7646d2SAndroid Build Coastguard Worker       }
1683*5e7646d2SAndroid Build Coastguard Worker 
1684*5e7646d2SAndroid Build Coastguard Worker       response = cupsGetResponse(http, resource);
1685*5e7646d2SAndroid Build Coastguard Worker       ippDelete(request);
1686*5e7646d2SAndroid Build Coastguard Worker     }
1687*5e7646d2SAndroid Build Coastguard Worker 
1688*5e7646d2SAndroid Build Coastguard Worker     ipp_status = cupsLastError();
1689*5e7646d2SAndroid Build Coastguard Worker 
1690*5e7646d2SAndroid Build Coastguard Worker     fprintf(stderr, "DEBUG: %s: %s (%s)\n",
1691*5e7646d2SAndroid Build Coastguard Worker             (num_files > 1 || create_job) ? "Create-Job" : "Print-Job",
1692*5e7646d2SAndroid Build Coastguard Worker             ippErrorString(ipp_status), cupsLastErrorString());
1693*5e7646d2SAndroid Build Coastguard Worker     debug_attributes(response);
1694*5e7646d2SAndroid Build Coastguard Worker 
1695*5e7646d2SAndroid Build Coastguard Worker     if (ipp_status > IPP_STATUS_OK_CONFLICTING)
1696*5e7646d2SAndroid Build Coastguard Worker     {
1697*5e7646d2SAndroid Build Coastguard Worker       job_id = 0;
1698*5e7646d2SAndroid Build Coastguard Worker 
1699*5e7646d2SAndroid Build Coastguard Worker       if (job_canceled)
1700*5e7646d2SAndroid Build Coastguard Worker         break;
1701*5e7646d2SAndroid Build Coastguard Worker 
1702*5e7646d2SAndroid Build Coastguard Worker       if (ipp_status == IPP_STATUS_ERROR_SERVICE_UNAVAILABLE ||
1703*5e7646d2SAndroid Build Coastguard Worker           ipp_status == IPP_STATUS_ERROR_NOT_POSSIBLE ||
1704*5e7646d2SAndroid Build Coastguard Worker 	  ipp_status == IPP_STATUS_ERROR_BUSY)
1705*5e7646d2SAndroid Build Coastguard Worker       {
1706*5e7646d2SAndroid Build Coastguard Worker 	_cupsLangPrintFilter(stderr, "INFO", _("The printer is in use."));
1707*5e7646d2SAndroid Build Coastguard Worker 	sleep(10);
1708*5e7646d2SAndroid Build Coastguard Worker 
1709*5e7646d2SAndroid Build Coastguard Worker 	if (num_files == 0)
1710*5e7646d2SAndroid Build Coastguard Worker 	{
1711*5e7646d2SAndroid Build Coastguard Worker 	 /*
1712*5e7646d2SAndroid Build Coastguard Worker 	  * We can't re-submit when we have no files to print, so exit
1713*5e7646d2SAndroid Build Coastguard Worker 	  * immediately with the right status code...
1714*5e7646d2SAndroid Build Coastguard Worker 	  */
1715*5e7646d2SAndroid Build Coastguard Worker 
1716*5e7646d2SAndroid Build Coastguard Worker 	  goto cleanup;
1717*5e7646d2SAndroid Build Coastguard Worker 	}
1718*5e7646d2SAndroid Build Coastguard Worker       }
1719*5e7646d2SAndroid Build Coastguard Worker       else if (ipp_status == IPP_STATUS_ERROR_JOB_CANCELED ||
1720*5e7646d2SAndroid Build Coastguard Worker                ipp_status == IPP_STATUS_ERROR_NOT_AUTHORIZED ||
1721*5e7646d2SAndroid Build Coastguard Worker                ipp_status == IPP_STATUS_ERROR_ATTRIBUTES_OR_VALUES ||
1722*5e7646d2SAndroid Build Coastguard Worker 	       ipp_status == IPP_STATUS_ERROR_CUPS_ACCOUNT_INFO_NEEDED ||
1723*5e7646d2SAndroid Build Coastguard Worker 	       ipp_status == IPP_STATUS_ERROR_CUPS_ACCOUNT_CLOSED ||
1724*5e7646d2SAndroid Build Coastguard Worker 	       ipp_status == IPP_STATUS_ERROR_CUPS_ACCOUNT_LIMIT_REACHED ||
1725*5e7646d2SAndroid Build Coastguard Worker 	       ipp_status == IPP_STATUS_ERROR_CUPS_ACCOUNT_AUTHORIZATION_FAILED)
1726*5e7646d2SAndroid Build Coastguard Worker         goto cleanup;
1727*5e7646d2SAndroid Build Coastguard Worker       else
1728*5e7646d2SAndroid Build Coastguard Worker       {
1729*5e7646d2SAndroid Build Coastguard Worker        /*
1730*5e7646d2SAndroid Build Coastguard Worker 	* Update auth-info-required as needed...
1731*5e7646d2SAndroid Build Coastguard Worker 	*/
1732*5e7646d2SAndroid Build Coastguard Worker 
1733*5e7646d2SAndroid Build Coastguard Worker         _cupsLangPrintFilter(stderr, "ERROR",
1734*5e7646d2SAndroid Build Coastguard Worker 	                     _("Print job was not accepted."));
1735*5e7646d2SAndroid Build Coastguard Worker 
1736*5e7646d2SAndroid Build Coastguard Worker         if (ipp_status == IPP_STATUS_ERROR_FORBIDDEN ||
1737*5e7646d2SAndroid Build Coastguard Worker             ipp_status == IPP_STATUS_ERROR_CUPS_AUTHENTICATION_CANCELED)
1738*5e7646d2SAndroid Build Coastguard Worker 	{
1739*5e7646d2SAndroid Build Coastguard Worker 	  const char *www_auth = httpGetField(http, HTTP_FIELD_WWW_AUTHENTICATE);
1740*5e7646d2SAndroid Build Coastguard Worker 					/* WWW-Authenticate field value */
1741*5e7646d2SAndroid Build Coastguard Worker 
1742*5e7646d2SAndroid Build Coastguard Worker 	  if (!strncmp(www_auth, "Negotiate", 9))
1743*5e7646d2SAndroid Build Coastguard Worker 	    auth_info_required = "negotiate";
1744*5e7646d2SAndroid Build Coastguard Worker 	  else if (www_auth[0])
1745*5e7646d2SAndroid Build Coastguard Worker 	    auth_info_required = "username,password";
1746*5e7646d2SAndroid Build Coastguard Worker 	}
1747*5e7646d2SAndroid Build Coastguard Worker 	else if (ipp_status == IPP_STATUS_ERROR_REQUEST_VALUE)
1748*5e7646d2SAndroid Build Coastguard Worker 	{
1749*5e7646d2SAndroid Build Coastguard Worker 	 /*
1750*5e7646d2SAndroid Build Coastguard Worker 	  * Print file is too large, abort this job...
1751*5e7646d2SAndroid Build Coastguard Worker 	  */
1752*5e7646d2SAndroid Build Coastguard Worker 
1753*5e7646d2SAndroid Build Coastguard Worker 	  goto cleanup;
1754*5e7646d2SAndroid Build Coastguard Worker 	}
1755*5e7646d2SAndroid Build Coastguard Worker 	else
1756*5e7646d2SAndroid Build Coastguard Worker 	  sleep(10);
1757*5e7646d2SAndroid Build Coastguard Worker 
1758*5e7646d2SAndroid Build Coastguard Worker 	if (num_files == 0)
1759*5e7646d2SAndroid Build Coastguard Worker 	{
1760*5e7646d2SAndroid Build Coastguard Worker 	 /*
1761*5e7646d2SAndroid Build Coastguard Worker 	  * We can't re-submit when we have no files to print, so exit
1762*5e7646d2SAndroid Build Coastguard Worker 	  * immediately with the right status code...
1763*5e7646d2SAndroid Build Coastguard Worker 	  */
1764*5e7646d2SAndroid Build Coastguard Worker 
1765*5e7646d2SAndroid Build Coastguard Worker 	  goto cleanup;
1766*5e7646d2SAndroid Build Coastguard Worker 	}
1767*5e7646d2SAndroid Build Coastguard Worker       }
1768*5e7646d2SAndroid Build Coastguard Worker     }
1769*5e7646d2SAndroid Build Coastguard Worker     else if ((job_id_attr = ippFindAttribute(response, "job-id",
1770*5e7646d2SAndroid Build Coastguard Worker                                              IPP_TAG_INTEGER)) == NULL)
1771*5e7646d2SAndroid Build Coastguard Worker     {
1772*5e7646d2SAndroid Build Coastguard Worker       fputs("DEBUG: Print job accepted - job ID unknown.\n", stderr);
1773*5e7646d2SAndroid Build Coastguard Worker       update_reasons(NULL, "+cups-ipp-conformance-failure-report,"
1774*5e7646d2SAndroid Build Coastguard Worker 			   "cups-ipp-missing-job-id");
1775*5e7646d2SAndroid Build Coastguard Worker       job_id = 0;
1776*5e7646d2SAndroid Build Coastguard Worker     }
1777*5e7646d2SAndroid Build Coastguard Worker     else
1778*5e7646d2SAndroid Build Coastguard Worker     {
1779*5e7646d2SAndroid Build Coastguard Worker       password_tries = 0;
1780*5e7646d2SAndroid Build Coastguard Worker       monitor.job_id = job_id = job_id_attr->values[0].integer;
1781*5e7646d2SAndroid Build Coastguard Worker       fprintf(stderr, "DEBUG: Print job accepted - job ID %d.\n", job_id);
1782*5e7646d2SAndroid Build Coastguard Worker     }
1783*5e7646d2SAndroid Build Coastguard Worker 
1784*5e7646d2SAndroid Build Coastguard Worker     ippDelete(response);
1785*5e7646d2SAndroid Build Coastguard Worker 
1786*5e7646d2SAndroid Build Coastguard Worker     if (job_canceled)
1787*5e7646d2SAndroid Build Coastguard Worker       break;
1788*5e7646d2SAndroid Build Coastguard Worker 
1789*5e7646d2SAndroid Build Coastguard Worker     if (job_id && (num_files > 1 || create_job))
1790*5e7646d2SAndroid Build Coastguard Worker     {
1791*5e7646d2SAndroid Build Coastguard Worker       for (i = 0; num_files == 0 || i < num_files; i ++)
1792*5e7646d2SAndroid Build Coastguard Worker       {
1793*5e7646d2SAndroid Build Coastguard Worker        /*
1794*5e7646d2SAndroid Build Coastguard Worker 	* Check for side-channel requests...
1795*5e7646d2SAndroid Build Coastguard Worker 	*/
1796*5e7646d2SAndroid Build Coastguard Worker 
1797*5e7646d2SAndroid Build Coastguard Worker 	backendCheckSideChannel(snmp_fd, http->hostaddr);
1798*5e7646d2SAndroid Build Coastguard Worker 
1799*5e7646d2SAndroid Build Coastguard Worker        /*
1800*5e7646d2SAndroid Build Coastguard Worker         * Send the next file in the job...
1801*5e7646d2SAndroid Build Coastguard Worker 	*/
1802*5e7646d2SAndroid Build Coastguard Worker 
1803*5e7646d2SAndroid Build Coastguard Worker 	request = ippNewRequest(IPP_OP_SEND_DOCUMENT);
1804*5e7646d2SAndroid Build Coastguard Worker 	ippSetVersion(request, version / 10, version % 10);
1805*5e7646d2SAndroid Build Coastguard Worker 
1806*5e7646d2SAndroid Build Coastguard Worker 	ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
1807*5e7646d2SAndroid Build Coastguard Worker         	     NULL, uri);
1808*5e7646d2SAndroid Build Coastguard Worker 
1809*5e7646d2SAndroid Build Coastguard Worker         ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER, "job-id",
1810*5e7646d2SAndroid Build Coastguard Worker 	              job_id);
1811*5e7646d2SAndroid Build Coastguard Worker 
1812*5e7646d2SAndroid Build Coastguard Worker 	if (argv[2][0])
1813*5e7646d2SAndroid Build Coastguard Worker 	  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
1814*5e7646d2SAndroid Build Coastguard Worker                        "requesting-user-name", NULL, argv[2]);
1815*5e7646d2SAndroid Build Coastguard Worker 
1816*5e7646d2SAndroid Build Coastguard Worker 	ippAddBoolean(request, IPP_TAG_OPERATION, "last-document",
1817*5e7646d2SAndroid Build Coastguard Worker         	      (i + 1) >= num_files);
1818*5e7646d2SAndroid Build Coastguard Worker 
1819*5e7646d2SAndroid Build Coastguard Worker 	if (document_format)
1820*5e7646d2SAndroid Build Coastguard Worker 	  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_MIMETYPE,
1821*5e7646d2SAndroid Build Coastguard Worker 		       "document-format", NULL, document_format);
1822*5e7646d2SAndroid Build Coastguard Worker 
1823*5e7646d2SAndroid Build Coastguard Worker         if (compression)
1824*5e7646d2SAndroid Build Coastguard Worker 	  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
1825*5e7646d2SAndroid Build Coastguard Worker 		       "compression", NULL, compression);
1826*5e7646d2SAndroid Build Coastguard Worker 
1827*5e7646d2SAndroid Build Coastguard Worker 	fprintf(stderr, "DEBUG: Sending file %d using chunking...\n", i + 1);
1828*5e7646d2SAndroid Build Coastguard Worker 	fprintf(stderr, "DEBUG: IPP/%d.%d %s #%d\n", version / 10, version % 10, ippOpString(ippGetOperation(request)), ippGetRequestId(request));
1829*5e7646d2SAndroid Build Coastguard Worker 	debug_attributes(request);
1830*5e7646d2SAndroid Build Coastguard Worker 
1831*5e7646d2SAndroid Build Coastguard Worker 	http_status = cupsSendRequest(http, request, resource, 0);
1832*5e7646d2SAndroid Build Coastguard Worker 	if (http_status == HTTP_STATUS_CONTINUE && request->state == IPP_STATE_DATA)
1833*5e7646d2SAndroid Build Coastguard Worker 	{
1834*5e7646d2SAndroid Build Coastguard Worker 	  if (compression && strcmp(compression, "none"))
1835*5e7646d2SAndroid Build Coastguard Worker 	    httpSetField(http, HTTP_FIELD_CONTENT_ENCODING, compression);
1836*5e7646d2SAndroid Build Coastguard Worker 
1837*5e7646d2SAndroid Build Coastguard Worker 	  if (num_files == 0)
1838*5e7646d2SAndroid Build Coastguard Worker 	  {
1839*5e7646d2SAndroid Build Coastguard Worker 	    fd          = 0;
1840*5e7646d2SAndroid Build Coastguard Worker 	    http_status = cupsWriteRequestData(http, buffer, (size_t)bytes);
1841*5e7646d2SAndroid Build Coastguard Worker 	  }
1842*5e7646d2SAndroid Build Coastguard Worker 	  else
1843*5e7646d2SAndroid Build Coastguard Worker 	  {
1844*5e7646d2SAndroid Build Coastguard Worker 	    if ((fd = open(files[i], O_RDONLY)) < 0)
1845*5e7646d2SAndroid Build Coastguard Worker 	    {
1846*5e7646d2SAndroid Build Coastguard Worker 	      _cupsLangPrintError("ERROR", _("Unable to open print file"));
1847*5e7646d2SAndroid Build Coastguard Worker 	      return (CUPS_BACKEND_FAILED);
1848*5e7646d2SAndroid Build Coastguard Worker 	    }
1849*5e7646d2SAndroid Build Coastguard Worker 	  }
1850*5e7646d2SAndroid Build Coastguard Worker 	}
1851*5e7646d2SAndroid Build Coastguard Worker 	else
1852*5e7646d2SAndroid Build Coastguard Worker 	  fd = -1;
1853*5e7646d2SAndroid Build Coastguard Worker 
1854*5e7646d2SAndroid Build Coastguard Worker 	if (fd >= 0)
1855*5e7646d2SAndroid Build Coastguard Worker 	{
1856*5e7646d2SAndroid Build Coastguard Worker 	  while (!job_canceled && http_status == HTTP_STATUS_CONTINUE &&
1857*5e7646d2SAndroid Build Coastguard Worker 	         (bytes = read(fd, buffer, sizeof(buffer))) > 0)
1858*5e7646d2SAndroid Build Coastguard Worker 	  {
1859*5e7646d2SAndroid Build Coastguard Worker 	    if ((http_status = cupsWriteRequestData(http, buffer, (size_t)bytes))
1860*5e7646d2SAndroid Build Coastguard Worker 	            != HTTP_STATUS_CONTINUE)
1861*5e7646d2SAndroid Build Coastguard Worker 	      break;
1862*5e7646d2SAndroid Build Coastguard Worker 	    else
1863*5e7646d2SAndroid Build Coastguard Worker 	    {
1864*5e7646d2SAndroid Build Coastguard Worker 	     /*
1865*5e7646d2SAndroid Build Coastguard Worker 	      * Check for side-channel requests...
1866*5e7646d2SAndroid Build Coastguard Worker 	      */
1867*5e7646d2SAndroid Build Coastguard Worker 
1868*5e7646d2SAndroid Build Coastguard Worker 	      backendCheckSideChannel(snmp_fd, http->hostaddr);
1869*5e7646d2SAndroid Build Coastguard Worker 	    }
1870*5e7646d2SAndroid Build Coastguard Worker 	  }
1871*5e7646d2SAndroid Build Coastguard Worker 
1872*5e7646d2SAndroid Build Coastguard Worker           if (fd > 0)
1873*5e7646d2SAndroid Build Coastguard Worker 	    close(fd);
1874*5e7646d2SAndroid Build Coastguard Worker 	}
1875*5e7646d2SAndroid Build Coastguard Worker 
1876*5e7646d2SAndroid Build Coastguard Worker         if (http_status == HTTP_STATUS_ERROR)
1877*5e7646d2SAndroid Build Coastguard Worker           fprintf(stderr, "DEBUG: Error writing document data for "
1878*5e7646d2SAndroid Build Coastguard Worker                           "Send-Document: %s\n", strerror(httpError(http)));
1879*5e7646d2SAndroid Build Coastguard Worker 
1880*5e7646d2SAndroid Build Coastguard Worker 	response = cupsGetResponse(http, resource);
1881*5e7646d2SAndroid Build Coastguard Worker 	ippDelete(request);
1882*5e7646d2SAndroid Build Coastguard Worker 
1883*5e7646d2SAndroid Build Coastguard Worker 	fprintf(stderr, "DEBUG: Send-Document: %s (%s)\n", ippErrorString(cupsLastError()), cupsLastErrorString());
1884*5e7646d2SAndroid Build Coastguard Worker         debug_attributes(response);
1885*5e7646d2SAndroid Build Coastguard Worker 
1886*5e7646d2SAndroid Build Coastguard Worker 	if (cupsLastError() > IPP_STATUS_OK_CONFLICTING && !job_canceled)
1887*5e7646d2SAndroid Build Coastguard Worker 	{
1888*5e7646d2SAndroid Build Coastguard Worker 	  ipp_attribute_t *reasons = ippFindAttribute(response, "job-state-reasons", IPP_TAG_KEYWORD);
1889*5e7646d2SAndroid Build Coastguard Worker 					/* job-state-reasons values */
1890*5e7646d2SAndroid Build Coastguard Worker 
1891*5e7646d2SAndroid Build Coastguard Worker 	  ipp_status = cupsLastError();
1892*5e7646d2SAndroid Build Coastguard Worker 
1893*5e7646d2SAndroid Build Coastguard Worker           if (ippContainsString(reasons, "document-format-error"))
1894*5e7646d2SAndroid Build Coastguard Worker             ipp_status = IPP_STATUS_ERROR_DOCUMENT_FORMAT_ERROR;
1895*5e7646d2SAndroid Build Coastguard Worker           else if (ippContainsString(reasons, "document-unprintable"))
1896*5e7646d2SAndroid Build Coastguard Worker             ipp_status = IPP_STATUS_ERROR_DOCUMENT_UNPRINTABLE;
1897*5e7646d2SAndroid Build Coastguard Worker 
1898*5e7646d2SAndroid Build Coastguard Worker 	  ippDelete(response);
1899*5e7646d2SAndroid Build Coastguard Worker 	  _cupsLangPrintFilter(stderr, "ERROR", _("Unable to add document to print job."));
1900*5e7646d2SAndroid Build Coastguard Worker 	  break;
1901*5e7646d2SAndroid Build Coastguard Worker 	}
1902*5e7646d2SAndroid Build Coastguard Worker 	else
1903*5e7646d2SAndroid Build Coastguard Worker 	{
1904*5e7646d2SAndroid Build Coastguard Worker 	  ippDelete(response);
1905*5e7646d2SAndroid Build Coastguard Worker 
1906*5e7646d2SAndroid Build Coastguard Worker 	  password_tries = 0;
1907*5e7646d2SAndroid Build Coastguard Worker 
1908*5e7646d2SAndroid Build Coastguard Worker 	  if (num_files == 0 || fd < 0)
1909*5e7646d2SAndroid Build Coastguard Worker 	    break;
1910*5e7646d2SAndroid Build Coastguard Worker 	}
1911*5e7646d2SAndroid Build Coastguard Worker       }
1912*5e7646d2SAndroid Build Coastguard Worker     }
1913*5e7646d2SAndroid Build Coastguard Worker 
1914*5e7646d2SAndroid Build Coastguard Worker     if (job_canceled)
1915*5e7646d2SAndroid Build Coastguard Worker       break;
1916*5e7646d2SAndroid Build Coastguard Worker 
1917*5e7646d2SAndroid Build Coastguard Worker     if (ipp_status <= IPP_STATUS_OK_CONFLICTING && argc > 6)
1918*5e7646d2SAndroid Build Coastguard Worker     {
1919*5e7646d2SAndroid Build Coastguard Worker       fprintf(stderr, "PAGE: 1 %d\n", copies_sup ? atoi(argv[4]) : 1);
1920*5e7646d2SAndroid Build Coastguard Worker       copies_remaining --;
1921*5e7646d2SAndroid Build Coastguard Worker     }
1922*5e7646d2SAndroid Build Coastguard Worker     else if ((ipp_status == IPP_STATUS_ERROR_DOCUMENT_FORMAT_NOT_SUPPORTED || ipp_status == IPP_STATUS_ERROR_DOCUMENT_FORMAT_ERROR || ipp_status == IPP_STATUS_ERROR_DOCUMENT_UNPRINTABLE) &&
1923*5e7646d2SAndroid Build Coastguard Worker              argc == 6 &&
1924*5e7646d2SAndroid Build Coastguard Worker              document_format && strcmp(document_format, "image/pwg-raster") && strcmp(document_format, "image/urf"))
1925*5e7646d2SAndroid Build Coastguard Worker     {
1926*5e7646d2SAndroid Build Coastguard Worker      /*
1927*5e7646d2SAndroid Build Coastguard Worker       * Need to reprocess the job as raster...
1928*5e7646d2SAndroid Build Coastguard Worker       */
1929*5e7646d2SAndroid Build Coastguard Worker 
1930*5e7646d2SAndroid Build Coastguard Worker       fputs("JOBSTATE: cups-retry-as-raster\n", stderr);
1931*5e7646d2SAndroid Build Coastguard Worker       if (job_id > 0)
1932*5e7646d2SAndroid Build Coastguard Worker 	cancel_job(http, uri, job_id, resource, argv[2], version);
1933*5e7646d2SAndroid Build Coastguard Worker 
1934*5e7646d2SAndroid Build Coastguard Worker       goto cleanup;
1935*5e7646d2SAndroid Build Coastguard Worker     }
1936*5e7646d2SAndroid Build Coastguard Worker     else if (ipp_status == IPP_STATUS_ERROR_SERVICE_UNAVAILABLE ||
1937*5e7646d2SAndroid Build Coastguard Worker              ipp_status == IPP_STATUS_ERROR_NOT_POSSIBLE ||
1938*5e7646d2SAndroid Build Coastguard Worker 	     ipp_status == IPP_STATUS_ERROR_BUSY)
1939*5e7646d2SAndroid Build Coastguard Worker     {
1940*5e7646d2SAndroid Build Coastguard Worker       if (argc == 6)
1941*5e7646d2SAndroid Build Coastguard Worker       {
1942*5e7646d2SAndroid Build Coastguard Worker        /*
1943*5e7646d2SAndroid Build Coastguard Worker         * Need to reprocess the entire job; if we have a job ID, cancel the
1944*5e7646d2SAndroid Build Coastguard Worker         * job first...
1945*5e7646d2SAndroid Build Coastguard Worker         */
1946*5e7646d2SAndroid Build Coastguard Worker 
1947*5e7646d2SAndroid Build Coastguard Worker 	if (job_id > 0)
1948*5e7646d2SAndroid Build Coastguard Worker 	  cancel_job(http, uri, job_id, resource, argv[2], version);
1949*5e7646d2SAndroid Build Coastguard Worker 
1950*5e7646d2SAndroid Build Coastguard Worker         goto cleanup;
1951*5e7646d2SAndroid Build Coastguard Worker       }
1952*5e7646d2SAndroid Build Coastguard Worker       continue;
1953*5e7646d2SAndroid Build Coastguard Worker     }
1954*5e7646d2SAndroid Build Coastguard Worker     else if (ipp_status == IPP_STATUS_ERROR_REQUEST_VALUE ||
1955*5e7646d2SAndroid Build Coastguard Worker              ipp_status == IPP_STATUS_ERROR_JOB_CANCELED ||
1956*5e7646d2SAndroid Build Coastguard Worker              ipp_status == IPP_STATUS_ERROR_NOT_AUTHORIZED ||
1957*5e7646d2SAndroid Build Coastguard Worker              ipp_status == IPP_STATUS_ERROR_CUPS_ACCOUNT_INFO_NEEDED ||
1958*5e7646d2SAndroid Build Coastguard Worker              ipp_status == IPP_STATUS_ERROR_CUPS_ACCOUNT_CLOSED ||
1959*5e7646d2SAndroid Build Coastguard Worker              ipp_status == IPP_STATUS_ERROR_CUPS_ACCOUNT_LIMIT_REACHED ||
1960*5e7646d2SAndroid Build Coastguard Worker              ipp_status == IPP_STATUS_ERROR_CUPS_ACCOUNT_AUTHORIZATION_FAILED ||
1961*5e7646d2SAndroid Build Coastguard Worker              ipp_status == IPP_STATUS_ERROR_INTERNAL)
1962*5e7646d2SAndroid Build Coastguard Worker     {
1963*5e7646d2SAndroid Build Coastguard Worker      /*
1964*5e7646d2SAndroid Build Coastguard Worker       * Print file is too large, job was canceled, we need new
1965*5e7646d2SAndroid Build Coastguard Worker       * authentication data, or we had some sort of error...
1966*5e7646d2SAndroid Build Coastguard Worker       */
1967*5e7646d2SAndroid Build Coastguard Worker 
1968*5e7646d2SAndroid Build Coastguard Worker       goto cleanup;
1969*5e7646d2SAndroid Build Coastguard Worker     }
1970*5e7646d2SAndroid Build Coastguard Worker     else if (ipp_status == IPP_STATUS_ERROR_CUPS_UPGRADE_REQUIRED)
1971*5e7646d2SAndroid Build Coastguard Worker     {
1972*5e7646d2SAndroid Build Coastguard Worker      /*
1973*5e7646d2SAndroid Build Coastguard Worker       * Server is configured incorrectly; the policy for Create-Job and
1974*5e7646d2SAndroid Build Coastguard Worker       * Send-Document has to be the same (auth or no auth, encryption or
1975*5e7646d2SAndroid Build Coastguard Worker       * no encryption).  Force the queue to stop since printing will never
1976*5e7646d2SAndroid Build Coastguard Worker       * work.
1977*5e7646d2SAndroid Build Coastguard Worker       */
1978*5e7646d2SAndroid Build Coastguard Worker 
1979*5e7646d2SAndroid Build Coastguard Worker       fputs("DEBUG: The server or printer is configured incorrectly.\n",
1980*5e7646d2SAndroid Build Coastguard Worker             stderr);
1981*5e7646d2SAndroid Build Coastguard Worker       fputs("DEBUG: The policy for Create-Job and Send-Document must have the "
1982*5e7646d2SAndroid Build Coastguard Worker             "same authentication and encryption requirements.\n", stderr);
1983*5e7646d2SAndroid Build Coastguard Worker 
1984*5e7646d2SAndroid Build Coastguard Worker       ipp_status = IPP_STATUS_ERROR_INTERNAL;
1985*5e7646d2SAndroid Build Coastguard Worker 
1986*5e7646d2SAndroid Build Coastguard Worker       if (job_id > 0)
1987*5e7646d2SAndroid Build Coastguard Worker 	cancel_job(http, uri, job_id, resource, argv[2], version);
1988*5e7646d2SAndroid Build Coastguard Worker 
1989*5e7646d2SAndroid Build Coastguard Worker       goto cleanup;
1990*5e7646d2SAndroid Build Coastguard Worker     }
1991*5e7646d2SAndroid Build Coastguard Worker     else if (ipp_status == IPP_STATUS_ERROR_NOT_FOUND)
1992*5e7646d2SAndroid Build Coastguard Worker     {
1993*5e7646d2SAndroid Build Coastguard Worker      /*
1994*5e7646d2SAndroid Build Coastguard Worker       * Printer does not actually implement support for Create-Job/
1995*5e7646d2SAndroid Build Coastguard Worker       * Send-Document, so log the conformance issue and stop the printer.
1996*5e7646d2SAndroid Build Coastguard Worker       */
1997*5e7646d2SAndroid Build Coastguard Worker 
1998*5e7646d2SAndroid Build Coastguard Worker       fputs("DEBUG: This printer claims to support Create-Job and "
1999*5e7646d2SAndroid Build Coastguard Worker             "Send-Document, but those operations failed.\n", stderr);
2000*5e7646d2SAndroid Build Coastguard Worker       fputs("DEBUG: Add '?version=1.0' to the device URI to use legacy "
2001*5e7646d2SAndroid Build Coastguard Worker             "compatibility mode.\n", stderr);
2002*5e7646d2SAndroid Build Coastguard Worker       update_reasons(NULL, "+cups-ipp-conformance-failure-report,"
2003*5e7646d2SAndroid Build Coastguard Worker 			   "cups-ipp-missing-send-document");
2004*5e7646d2SAndroid Build Coastguard Worker 
2005*5e7646d2SAndroid Build Coastguard Worker       ipp_status = IPP_STATUS_ERROR_INTERNAL;	/* Force queue to stop */
2006*5e7646d2SAndroid Build Coastguard Worker 
2007*5e7646d2SAndroid Build Coastguard Worker       goto cleanup;
2008*5e7646d2SAndroid Build Coastguard Worker     }
2009*5e7646d2SAndroid Build Coastguard Worker     else
2010*5e7646d2SAndroid Build Coastguard Worker       copies_remaining --;
2011*5e7646d2SAndroid Build Coastguard Worker 
2012*5e7646d2SAndroid Build Coastguard Worker    /*
2013*5e7646d2SAndroid Build Coastguard Worker     * Wait for the job to complete...
2014*5e7646d2SAndroid Build Coastguard Worker     */
2015*5e7646d2SAndroid Build Coastguard Worker 
2016*5e7646d2SAndroid Build Coastguard Worker     if (!job_id || !waitjob || !get_job_attrs)
2017*5e7646d2SAndroid Build Coastguard Worker       continue;
2018*5e7646d2SAndroid Build Coastguard Worker 
2019*5e7646d2SAndroid Build Coastguard Worker     fputs("STATE: +cups-waiting-for-job-completed\n", stderr);
2020*5e7646d2SAndroid Build Coastguard Worker 
2021*5e7646d2SAndroid Build Coastguard Worker     _cupsLangPrintFilter(stderr, "INFO", _("Waiting for job to complete."));
2022*5e7646d2SAndroid Build Coastguard Worker 
2023*5e7646d2SAndroid Build Coastguard Worker     for (delay = _cupsNextDelay(0, &prev_delay); !job_canceled;)
2024*5e7646d2SAndroid Build Coastguard Worker     {
2025*5e7646d2SAndroid Build Coastguard Worker      /*
2026*5e7646d2SAndroid Build Coastguard Worker       * Check for side-channel requests...
2027*5e7646d2SAndroid Build Coastguard Worker       */
2028*5e7646d2SAndroid Build Coastguard Worker 
2029*5e7646d2SAndroid Build Coastguard Worker       backendCheckSideChannel(snmp_fd, http->hostaddr);
2030*5e7646d2SAndroid Build Coastguard Worker 
2031*5e7646d2SAndroid Build Coastguard Worker      /*
2032*5e7646d2SAndroid Build Coastguard Worker       * Check printer state...
2033*5e7646d2SAndroid Build Coastguard Worker       */
2034*5e7646d2SAndroid Build Coastguard Worker 
2035*5e7646d2SAndroid Build Coastguard Worker       check_printer_state(http, uri, resource, argv[2], version);
2036*5e7646d2SAndroid Build Coastguard Worker 
2037*5e7646d2SAndroid Build Coastguard Worker       if (cupsLastError() <= IPP_STATUS_OK_CONFLICTING)
2038*5e7646d2SAndroid Build Coastguard Worker         password_tries = 0;
2039*5e7646d2SAndroid Build Coastguard Worker 
2040*5e7646d2SAndroid Build Coastguard Worker      /*
2041*5e7646d2SAndroid Build Coastguard Worker       * Build an IPP_OP_GET_JOB_ATTRIBUTES request...
2042*5e7646d2SAndroid Build Coastguard Worker       */
2043*5e7646d2SAndroid Build Coastguard Worker 
2044*5e7646d2SAndroid Build Coastguard Worker       request = ippNewRequest(IPP_OP_GET_JOB_ATTRIBUTES);
2045*5e7646d2SAndroid Build Coastguard Worker       ippSetVersion(request, version / 10, version % 10);
2046*5e7646d2SAndroid Build Coastguard Worker 
2047*5e7646d2SAndroid Build Coastguard Worker       ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
2048*5e7646d2SAndroid Build Coastguard Worker         	   NULL, uri);
2049*5e7646d2SAndroid Build Coastguard Worker 
2050*5e7646d2SAndroid Build Coastguard Worker       ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER, "job-id",
2051*5e7646d2SAndroid Build Coastguard Worker         	    job_id);
2052*5e7646d2SAndroid Build Coastguard Worker 
2053*5e7646d2SAndroid Build Coastguard Worker       if (argv[2][0])
2054*5e7646d2SAndroid Build Coastguard Worker 	ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
2055*5e7646d2SAndroid Build Coastguard Worker 	             "requesting-user-name", NULL, argv[2]);
2056*5e7646d2SAndroid Build Coastguard Worker 
2057*5e7646d2SAndroid Build Coastguard Worker       ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
2058*5e7646d2SAndroid Build Coastguard Worker                     "requested-attributes", sizeof(jattrs) / sizeof(jattrs[0]),
2059*5e7646d2SAndroid Build Coastguard Worker 		    NULL, jattrs);
2060*5e7646d2SAndroid Build Coastguard Worker 
2061*5e7646d2SAndroid Build Coastguard Worker       fprintf(stderr, "DEBUG: IPP/%d.%d %s #%d\n", version / 10, version % 10, ippOpString(ippGetOperation(request)), ippGetRequestId(request));
2062*5e7646d2SAndroid Build Coastguard Worker       debug_attributes(request);
2063*5e7646d2SAndroid Build Coastguard Worker 
2064*5e7646d2SAndroid Build Coastguard Worker      /*
2065*5e7646d2SAndroid Build Coastguard Worker       * Do the request...
2066*5e7646d2SAndroid Build Coastguard Worker       */
2067*5e7646d2SAndroid Build Coastguard Worker 
2068*5e7646d2SAndroid Build Coastguard Worker       httpReconnect2(http, 30000, NULL);
2069*5e7646d2SAndroid Build Coastguard Worker       response   = cupsDoRequest(http, request, resource);
2070*5e7646d2SAndroid Build Coastguard Worker       ipp_status = cupsLastError();
2071*5e7646d2SAndroid Build Coastguard Worker 
2072*5e7646d2SAndroid Build Coastguard Worker       if (ipp_status == IPP_STATUS_ERROR_NOT_FOUND || ipp_status == IPP_STATUS_ERROR_NOT_POSSIBLE)
2073*5e7646d2SAndroid Build Coastguard Worker       {
2074*5e7646d2SAndroid Build Coastguard Worker        /*
2075*5e7646d2SAndroid Build Coastguard Worker         * Job has gone away and/or the server has no job history...
2076*5e7646d2SAndroid Build Coastguard Worker 	*/
2077*5e7646d2SAndroid Build Coastguard Worker 
2078*5e7646d2SAndroid Build Coastguard Worker 	update_reasons(NULL, "+cups-ipp-conformance-failure-report,"
2079*5e7646d2SAndroid Build Coastguard Worker 			     "cups-ipp-missing-job-history");
2080*5e7646d2SAndroid Build Coastguard Worker         ippDelete(response);
2081*5e7646d2SAndroid Build Coastguard Worker 
2082*5e7646d2SAndroid Build Coastguard Worker 	ipp_status = IPP_STATUS_OK;
2083*5e7646d2SAndroid Build Coastguard Worker         break;
2084*5e7646d2SAndroid Build Coastguard Worker       }
2085*5e7646d2SAndroid Build Coastguard Worker 
2086*5e7646d2SAndroid Build Coastguard Worker       fprintf(stderr, "DEBUG: Get-Job-Attributes: %s (%s)\n",
2087*5e7646d2SAndroid Build Coastguard Worker 	      ippErrorString(ipp_status), cupsLastErrorString());
2088*5e7646d2SAndroid Build Coastguard Worker       debug_attributes(response);
2089*5e7646d2SAndroid Build Coastguard Worker 
2090*5e7646d2SAndroid Build Coastguard Worker       if (ipp_status <= IPP_STATUS_OK_CONFLICTING)
2091*5e7646d2SAndroid Build Coastguard Worker 	password_tries = 0;
2092*5e7646d2SAndroid Build Coastguard Worker       else
2093*5e7646d2SAndroid Build Coastguard Worker       {
2094*5e7646d2SAndroid Build Coastguard Worker 	if (ipp_status != IPP_STATUS_ERROR_SERVICE_UNAVAILABLE &&
2095*5e7646d2SAndroid Build Coastguard Worker 	    ipp_status != IPP_STATUS_ERROR_BUSY)
2096*5e7646d2SAndroid Build Coastguard Worker 	{
2097*5e7646d2SAndroid Build Coastguard Worker 	  ippDelete(response);
2098*5e7646d2SAndroid Build Coastguard Worker           ipp_status = IPP_STATUS_OK;
2099*5e7646d2SAndroid Build Coastguard Worker           break;
2100*5e7646d2SAndroid Build Coastguard Worker 	}
2101*5e7646d2SAndroid Build Coastguard Worker 	else if (ipp_status == IPP_STATUS_ERROR_INTERNAL)
2102*5e7646d2SAndroid Build Coastguard Worker 	{
2103*5e7646d2SAndroid Build Coastguard Worker 	  waitjob_tries ++;
2104*5e7646d2SAndroid Build Coastguard Worker 
2105*5e7646d2SAndroid Build Coastguard Worker 	  if (waitjob_tries > 4)
2106*5e7646d2SAndroid Build Coastguard Worker 	  {
2107*5e7646d2SAndroid Build Coastguard Worker 	    ippDelete(response);
2108*5e7646d2SAndroid Build Coastguard Worker 	    ipp_status = IPP_STATUS_OK;
2109*5e7646d2SAndroid Build Coastguard Worker 	    break;
2110*5e7646d2SAndroid Build Coastguard Worker 	  }
2111*5e7646d2SAndroid Build Coastguard Worker 	}
2112*5e7646d2SAndroid Build Coastguard Worker       }
2113*5e7646d2SAndroid Build Coastguard Worker 
2114*5e7646d2SAndroid Build Coastguard Worker       if (response)
2115*5e7646d2SAndroid Build Coastguard Worker       {
2116*5e7646d2SAndroid Build Coastguard Worker 	if ((job_state = ippFindAttribute(response, "job-state",
2117*5e7646d2SAndroid Build Coastguard Worker 	                                  IPP_TAG_ENUM)) != NULL)
2118*5e7646d2SAndroid Build Coastguard Worker 	{
2119*5e7646d2SAndroid Build Coastguard Worker          /*
2120*5e7646d2SAndroid Build Coastguard Worker 	  * Reflect the remote job state in the local queue...
2121*5e7646d2SAndroid Build Coastguard Worker 	  */
2122*5e7646d2SAndroid Build Coastguard Worker 
2123*5e7646d2SAndroid Build Coastguard Worker 	  if (cups_version &&
2124*5e7646d2SAndroid Build Coastguard Worker 	      job_state->values[0].integer >= IPP_JSTATE_PENDING &&
2125*5e7646d2SAndroid Build Coastguard Worker 	      job_state->values[0].integer <= IPP_JSTATE_COMPLETED)
2126*5e7646d2SAndroid Build Coastguard Worker 	    update_reasons(NULL,
2127*5e7646d2SAndroid Build Coastguard Worker 	                   remote_job_states[job_state->values[0].integer -
2128*5e7646d2SAndroid Build Coastguard Worker 			                     IPP_JSTATE_PENDING]);
2129*5e7646d2SAndroid Build Coastguard Worker 
2130*5e7646d2SAndroid Build Coastguard Worker 	  if ((job_sheets = ippFindAttribute(response, "job-impressions-completed", IPP_TAG_INTEGER)) == NULL)
2131*5e7646d2SAndroid Build Coastguard Worker 	    job_sheets = ippFindAttribute(response, "job-media-sheets-completed", IPP_TAG_INTEGER);
2132*5e7646d2SAndroid Build Coastguard Worker 
2133*5e7646d2SAndroid Build Coastguard Worker 	  if (job_sheets)
2134*5e7646d2SAndroid Build Coastguard Worker 	    fprintf(stderr, "PAGE: total %d\n",
2135*5e7646d2SAndroid Build Coastguard Worker 		    job_sheets->values[0].integer);
2136*5e7646d2SAndroid Build Coastguard Worker 
2137*5e7646d2SAndroid Build Coastguard Worker 	 /*
2138*5e7646d2SAndroid Build Coastguard Worker           * Stop polling if the job is finished or pending-held...
2139*5e7646d2SAndroid Build Coastguard Worker 	  */
2140*5e7646d2SAndroid Build Coastguard Worker 
2141*5e7646d2SAndroid Build Coastguard Worker           if (job_state->values[0].integer > IPP_JSTATE_STOPPED || job_state->values[0].integer == IPP_JSTATE_HELD)
2142*5e7646d2SAndroid Build Coastguard Worker 	  {
2143*5e7646d2SAndroid Build Coastguard Worker 	    ippDelete(response);
2144*5e7646d2SAndroid Build Coastguard Worker 	    break;
2145*5e7646d2SAndroid Build Coastguard Worker 	  }
2146*5e7646d2SAndroid Build Coastguard Worker 	}
2147*5e7646d2SAndroid Build Coastguard Worker 	else if (ipp_status != IPP_STATUS_ERROR_SERVICE_UNAVAILABLE &&
2148*5e7646d2SAndroid Build Coastguard Worker 		 ipp_status != IPP_STATUS_ERROR_NOT_POSSIBLE &&
2149*5e7646d2SAndroid Build Coastguard Worker 		 ipp_status != IPP_STATUS_ERROR_BUSY)
2150*5e7646d2SAndroid Build Coastguard Worker 	{
2151*5e7646d2SAndroid Build Coastguard Worker 	 /*
2152*5e7646d2SAndroid Build Coastguard Worker 	  * If the printer does not return a job-state attribute, it does not
2153*5e7646d2SAndroid Build Coastguard Worker 	  * conform to the IPP specification - break out immediately and fail
2154*5e7646d2SAndroid Build Coastguard Worker 	  * the job...
2155*5e7646d2SAndroid Build Coastguard Worker 	  */
2156*5e7646d2SAndroid Build Coastguard Worker 
2157*5e7646d2SAndroid Build Coastguard Worker 	  update_reasons(NULL, "+cups-ipp-conformance-failure-report,"
2158*5e7646d2SAndroid Build Coastguard Worker 			       "cups-ipp-missing-job-state");
2159*5e7646d2SAndroid Build Coastguard Worker 	  ipp_status = IPP_STATUS_ERROR_INTERNAL;
2160*5e7646d2SAndroid Build Coastguard Worker 	  break;
2161*5e7646d2SAndroid Build Coastguard Worker 	}
2162*5e7646d2SAndroid Build Coastguard Worker       }
2163*5e7646d2SAndroid Build Coastguard Worker 
2164*5e7646d2SAndroid Build Coastguard Worker       ippDelete(response);
2165*5e7646d2SAndroid Build Coastguard Worker 
2166*5e7646d2SAndroid Build Coastguard Worker      /*
2167*5e7646d2SAndroid Build Coastguard Worker       * Wait before polling again...
2168*5e7646d2SAndroid Build Coastguard Worker       */
2169*5e7646d2SAndroid Build Coastguard Worker 
2170*5e7646d2SAndroid Build Coastguard Worker       sleep((unsigned)delay);
2171*5e7646d2SAndroid Build Coastguard Worker 
2172*5e7646d2SAndroid Build Coastguard Worker       delay = _cupsNextDelay(delay, &prev_delay);
2173*5e7646d2SAndroid Build Coastguard Worker     }
2174*5e7646d2SAndroid Build Coastguard Worker   }
2175*5e7646d2SAndroid Build Coastguard Worker 
2176*5e7646d2SAndroid Build Coastguard Worker  /*
2177*5e7646d2SAndroid Build Coastguard Worker   * Cancel the job as needed...
2178*5e7646d2SAndroid Build Coastguard Worker   */
2179*5e7646d2SAndroid Build Coastguard Worker 
2180*5e7646d2SAndroid Build Coastguard Worker   if (job_canceled > 0 && job_id > 0)
2181*5e7646d2SAndroid Build Coastguard Worker   {
2182*5e7646d2SAndroid Build Coastguard Worker     cancel_job(http, uri, job_id, resource, argv[2], version);
2183*5e7646d2SAndroid Build Coastguard Worker 
2184*5e7646d2SAndroid Build Coastguard Worker     if (cupsLastError() > IPP_STATUS_OK_CONFLICTING)
2185*5e7646d2SAndroid Build Coastguard Worker       _cupsLangPrintFilter(stderr, "ERROR", _("Unable to cancel print job."));
2186*5e7646d2SAndroid Build Coastguard Worker   }
2187*5e7646d2SAndroid Build Coastguard Worker 
2188*5e7646d2SAndroid Build Coastguard Worker  /*
2189*5e7646d2SAndroid Build Coastguard Worker   * Check the printer state and report it if necessary...
2190*5e7646d2SAndroid Build Coastguard Worker   */
2191*5e7646d2SAndroid Build Coastguard Worker 
2192*5e7646d2SAndroid Build Coastguard Worker   check_printer_state(http, uri, resource, argv[2], version);
2193*5e7646d2SAndroid Build Coastguard Worker 
2194*5e7646d2SAndroid Build Coastguard Worker   if (cupsLastError() <= IPP_STATUS_OK_CONFLICTING)
2195*5e7646d2SAndroid Build Coastguard Worker     password_tries = 0;
2196*5e7646d2SAndroid Build Coastguard Worker 
2197*5e7646d2SAndroid Build Coastguard Worker  /*
2198*5e7646d2SAndroid Build Coastguard Worker   * Collect the final page count as needed...
2199*5e7646d2SAndroid Build Coastguard Worker   */
2200*5e7646d2SAndroid Build Coastguard Worker 
2201*5e7646d2SAndroid Build Coastguard Worker   if (have_supplies &&
2202*5e7646d2SAndroid Build Coastguard Worker       !backendSNMPSupplies(snmp_fd, &(http->addrlist->addr), &page_count,
2203*5e7646d2SAndroid Build Coastguard Worker                            NULL) &&
2204*5e7646d2SAndroid Build Coastguard Worker       page_count > start_count)
2205*5e7646d2SAndroid Build Coastguard Worker     fprintf(stderr, "PAGE: total %d\n", page_count - start_count);
2206*5e7646d2SAndroid Build Coastguard Worker 
2207*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_GSSAPI
2208*5e7646d2SAndroid Build Coastguard Worker  /*
2209*5e7646d2SAndroid Build Coastguard Worker   * See if we used Kerberos at all...
2210*5e7646d2SAndroid Build Coastguard Worker   */
2211*5e7646d2SAndroid Build Coastguard Worker 
2212*5e7646d2SAndroid Build Coastguard Worker   if (http->gssctx)
2213*5e7646d2SAndroid Build Coastguard Worker     auth_info_required = "negotiate";
2214*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_GSSAPI */
2215*5e7646d2SAndroid Build Coastguard Worker 
2216*5e7646d2SAndroid Build Coastguard Worker  /*
2217*5e7646d2SAndroid Build Coastguard Worker   * Free memory...
2218*5e7646d2SAndroid Build Coastguard Worker   */
2219*5e7646d2SAndroid Build Coastguard Worker 
2220*5e7646d2SAndroid Build Coastguard Worker   cleanup:
2221*5e7646d2SAndroid Build Coastguard Worker 
2222*5e7646d2SAndroid Build Coastguard Worker   cupsFreeOptions(num_options, options);
2223*5e7646d2SAndroid Build Coastguard Worker   _ppdCacheDestroy(pc);
2224*5e7646d2SAndroid Build Coastguard Worker   ppdClose(ppd);
2225*5e7646d2SAndroid Build Coastguard Worker 
2226*5e7646d2SAndroid Build Coastguard Worker   httpClose(http);
2227*5e7646d2SAndroid Build Coastguard Worker 
2228*5e7646d2SAndroid Build Coastguard Worker   ippDelete(supported);
2229*5e7646d2SAndroid Build Coastguard Worker 
2230*5e7646d2SAndroid Build Coastguard Worker  /*
2231*5e7646d2SAndroid Build Coastguard Worker   * Remove the temporary file(s) if necessary...
2232*5e7646d2SAndroid Build Coastguard Worker   */
2233*5e7646d2SAndroid Build Coastguard Worker 
2234*5e7646d2SAndroid Build Coastguard Worker   if (tmpfilename[0])
2235*5e7646d2SAndroid Build Coastguard Worker     unlink(tmpfilename);
2236*5e7646d2SAndroid Build Coastguard Worker 
2237*5e7646d2SAndroid Build Coastguard Worker  /*
2238*5e7646d2SAndroid Build Coastguard Worker   * Return the queue status...
2239*5e7646d2SAndroid Build Coastguard Worker   */
2240*5e7646d2SAndroid Build Coastguard Worker 
2241*5e7646d2SAndroid Build Coastguard Worker   if (ipp_status == IPP_STATUS_ERROR_NOT_AUTHORIZED || ipp_status == IPP_STATUS_ERROR_FORBIDDEN ||
2242*5e7646d2SAndroid Build Coastguard Worker       ipp_status == IPP_STATUS_ERROR_CUPS_AUTHENTICATION_CANCELED ||
2243*5e7646d2SAndroid Build Coastguard Worker       ipp_status <= IPP_STATUS_OK_CONFLICTING)
2244*5e7646d2SAndroid Build Coastguard Worker     fprintf(stderr, "ATTR: auth-info-required=%s\n", auth_info_required);
2245*5e7646d2SAndroid Build Coastguard Worker 
2246*5e7646d2SAndroid Build Coastguard Worker   if (ipp_status == IPP_STATUS_ERROR_CUPS_ACCOUNT_INFO_NEEDED)
2247*5e7646d2SAndroid Build Coastguard Worker     fputs("JOBSTATE: account-info-needed\n", stderr);
2248*5e7646d2SAndroid Build Coastguard Worker   else if (ipp_status == IPP_STATUS_ERROR_CUPS_ACCOUNT_CLOSED)
2249*5e7646d2SAndroid Build Coastguard Worker     fputs("JOBSTATE: account-closed\n", stderr);
2250*5e7646d2SAndroid Build Coastguard Worker   else if (ipp_status == IPP_STATUS_ERROR_CUPS_ACCOUNT_LIMIT_REACHED)
2251*5e7646d2SAndroid Build Coastguard Worker     fputs("JOBSTATE: account-limit-reached\n", stderr);
2252*5e7646d2SAndroid Build Coastguard Worker   else if (ipp_status == IPP_STATUS_ERROR_CUPS_ACCOUNT_AUTHORIZATION_FAILED)
2253*5e7646d2SAndroid Build Coastguard Worker     fputs("JOBSTATE: account-authorization-failed\n", stderr);
2254*5e7646d2SAndroid Build Coastguard Worker 
2255*5e7646d2SAndroid Build Coastguard Worker   // job_canceled can be -1 which should not be treated as CUPS_BACKEND_OK
2256*5e7646d2SAndroid Build Coastguard Worker   if (job_canceled > 0)
2257*5e7646d2SAndroid Build Coastguard Worker     return (CUPS_BACKEND_OK);
2258*5e7646d2SAndroid Build Coastguard Worker   else if (ipp_status == IPP_STATUS_ERROR_NOT_AUTHORIZED || ipp_status == IPP_STATUS_ERROR_FORBIDDEN || ipp_status == IPP_STATUS_ERROR_CUPS_AUTHENTICATION_CANCELED)
2259*5e7646d2SAndroid Build Coastguard Worker     return (CUPS_BACKEND_AUTH_REQUIRED);
2260*5e7646d2SAndroid Build Coastguard Worker   else if (ipp_status == IPP_STATUS_ERROR_CUPS_ACCOUNT_LIMIT_REACHED ||
2261*5e7646d2SAndroid Build Coastguard Worker 	   ipp_status == IPP_STATUS_ERROR_CUPS_ACCOUNT_INFO_NEEDED ||
2262*5e7646d2SAndroid Build Coastguard Worker 	   ipp_status == IPP_STATUS_ERROR_CUPS_ACCOUNT_CLOSED ||
2263*5e7646d2SAndroid Build Coastguard Worker 	   ipp_status == IPP_STATUS_ERROR_CUPS_ACCOUNT_AUTHORIZATION_FAILED)
2264*5e7646d2SAndroid Build Coastguard Worker     return (CUPS_BACKEND_HOLD);
2265*5e7646d2SAndroid Build Coastguard Worker   else if (ipp_status == IPP_STATUS_ERROR_INTERNAL)
2266*5e7646d2SAndroid Build Coastguard Worker     return (CUPS_BACKEND_STOP);
2267*5e7646d2SAndroid Build Coastguard Worker   else if (ipp_status == IPP_STATUS_ERROR_CONFLICTING || ipp_status == IPP_STATUS_ERROR_REQUEST_ENTITY || ipp_status == IPP_STATUS_ERROR_REQUEST_VALUE)
2268*5e7646d2SAndroid Build Coastguard Worker     return (CUPS_BACKEND_FAILED);
2269*5e7646d2SAndroid Build Coastguard Worker   else if (ipp_status == IPP_STATUS_ERROR_REQUEST_VALUE ||
2270*5e7646d2SAndroid Build Coastguard Worker 	   ipp_status == IPP_STATUS_ERROR_ATTRIBUTES_OR_VALUES ||
2271*5e7646d2SAndroid Build Coastguard Worker            ipp_status == IPP_STATUS_ERROR_DOCUMENT_FORMAT_NOT_SUPPORTED || job_canceled < 0)
2272*5e7646d2SAndroid Build Coastguard Worker   {
2273*5e7646d2SAndroid Build Coastguard Worker     if (ipp_status == IPP_STATUS_ERROR_REQUEST_VALUE)
2274*5e7646d2SAndroid Build Coastguard Worker       _cupsLangPrintFilter(stderr, "ERROR", _("Print job too large."));
2275*5e7646d2SAndroid Build Coastguard Worker     else if (ipp_status == IPP_STATUS_ERROR_DOCUMENT_FORMAT_NOT_SUPPORTED)
2276*5e7646d2SAndroid Build Coastguard Worker       _cupsLangPrintFilter(stderr, "ERROR",
2277*5e7646d2SAndroid Build Coastguard Worker                            _("Printer cannot print supplied content."));
2278*5e7646d2SAndroid Build Coastguard Worker     else if (ipp_status == IPP_STATUS_ERROR_ATTRIBUTES_OR_VALUES)
2279*5e7646d2SAndroid Build Coastguard Worker       _cupsLangPrintFilter(stderr, "ERROR",
2280*5e7646d2SAndroid Build Coastguard Worker                            _("Printer cannot print with supplied options."));
2281*5e7646d2SAndroid Build Coastguard Worker     else
2282*5e7646d2SAndroid Build Coastguard Worker       _cupsLangPrintFilter(stderr, "ERROR", _("Print job canceled at printer."));
2283*5e7646d2SAndroid Build Coastguard Worker 
2284*5e7646d2SAndroid Build Coastguard Worker     return (CUPS_BACKEND_CANCEL);
2285*5e7646d2SAndroid Build Coastguard Worker   }
2286*5e7646d2SAndroid Build Coastguard Worker   else if (ipp_status > IPP_STATUS_OK_CONFLICTING && ipp_status != IPP_STATUS_ERROR_JOB_CANCELED)
2287*5e7646d2SAndroid Build Coastguard Worker     return (CUPS_BACKEND_RETRY_CURRENT);
2288*5e7646d2SAndroid Build Coastguard Worker   else
2289*5e7646d2SAndroid Build Coastguard Worker     return (CUPS_BACKEND_OK);
2290*5e7646d2SAndroid Build Coastguard Worker }
2291*5e7646d2SAndroid Build Coastguard Worker 
2292*5e7646d2SAndroid Build Coastguard Worker 
2293*5e7646d2SAndroid Build Coastguard Worker /*
2294*5e7646d2SAndroid Build Coastguard Worker  * 'cancel_job()' - Cancel a print job.
2295*5e7646d2SAndroid Build Coastguard Worker  */
2296*5e7646d2SAndroid Build Coastguard Worker 
2297*5e7646d2SAndroid Build Coastguard Worker static void
cancel_job(http_t * http,const char * uri,int id,const char * resource,const char * user,int version)2298*5e7646d2SAndroid Build Coastguard Worker cancel_job(http_t     *http,		/* I - HTTP connection */
2299*5e7646d2SAndroid Build Coastguard Worker            const char *uri,		/* I - printer-uri */
2300*5e7646d2SAndroid Build Coastguard Worker 	   int        id,		/* I - job-id */
2301*5e7646d2SAndroid Build Coastguard Worker 	   const char *resource,	/* I - Resource path */
2302*5e7646d2SAndroid Build Coastguard Worker 	   const char *user,		/* I - requesting-user-name */
2303*5e7646d2SAndroid Build Coastguard Worker 	   int        version)		/* I - IPP version */
2304*5e7646d2SAndroid Build Coastguard Worker {
2305*5e7646d2SAndroid Build Coastguard Worker   ipp_t	*request;			/* Cancel-Job request */
2306*5e7646d2SAndroid Build Coastguard Worker 
2307*5e7646d2SAndroid Build Coastguard Worker 
2308*5e7646d2SAndroid Build Coastguard Worker   _cupsLangPrintFilter(stderr, "INFO", _("Canceling print job."));
2309*5e7646d2SAndroid Build Coastguard Worker 
2310*5e7646d2SAndroid Build Coastguard Worker   request = ippNewRequest(IPP_OP_CANCEL_JOB);
2311*5e7646d2SAndroid Build Coastguard Worker   ippSetVersion(request, version / 10, version % 10);
2312*5e7646d2SAndroid Build Coastguard Worker 
2313*5e7646d2SAndroid Build Coastguard Worker   ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
2314*5e7646d2SAndroid Build Coastguard Worker                NULL, uri);
2315*5e7646d2SAndroid Build Coastguard Worker   ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER, "job-id", id);
2316*5e7646d2SAndroid Build Coastguard Worker 
2317*5e7646d2SAndroid Build Coastguard Worker   if (user && user[0])
2318*5e7646d2SAndroid Build Coastguard Worker     ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
2319*5e7646d2SAndroid Build Coastguard Worker                  "requesting-user-name", NULL, user);
2320*5e7646d2SAndroid Build Coastguard Worker 
2321*5e7646d2SAndroid Build Coastguard Worker  /*
2322*5e7646d2SAndroid Build Coastguard Worker   * Do the request...
2323*5e7646d2SAndroid Build Coastguard Worker   */
2324*5e7646d2SAndroid Build Coastguard Worker 
2325*5e7646d2SAndroid Build Coastguard Worker   ippDelete(cupsDoRequest(http, request, resource));
2326*5e7646d2SAndroid Build Coastguard Worker }
2327*5e7646d2SAndroid Build Coastguard Worker 
2328*5e7646d2SAndroid Build Coastguard Worker 
2329*5e7646d2SAndroid Build Coastguard Worker /*
2330*5e7646d2SAndroid Build Coastguard Worker  * 'check_printer_state()' - Check the printer state.
2331*5e7646d2SAndroid Build Coastguard Worker  */
2332*5e7646d2SAndroid Build Coastguard Worker 
2333*5e7646d2SAndroid Build Coastguard Worker static ipp_pstate_t			/* O - Current printer-state */
check_printer_state(http_t * http,const char * uri,const char * resource,const char * user,int version)2334*5e7646d2SAndroid Build Coastguard Worker check_printer_state(
2335*5e7646d2SAndroid Build Coastguard Worker     http_t      *http,			/* I - HTTP connection */
2336*5e7646d2SAndroid Build Coastguard Worker     const char  *uri,			/* I - Printer URI */
2337*5e7646d2SAndroid Build Coastguard Worker     const char  *resource,		/* I - Resource path */
2338*5e7646d2SAndroid Build Coastguard Worker     const char  *user,			/* I - Username, if any */
2339*5e7646d2SAndroid Build Coastguard Worker     int         version)		/* I - IPP version */
2340*5e7646d2SAndroid Build Coastguard Worker  {
2341*5e7646d2SAndroid Build Coastguard Worker   ipp_t		*request,		/* IPP request */
2342*5e7646d2SAndroid Build Coastguard Worker 		*response;		/* IPP response */
2343*5e7646d2SAndroid Build Coastguard Worker   ipp_attribute_t *attr;		/* Attribute in response */
2344*5e7646d2SAndroid Build Coastguard Worker   ipp_pstate_t	printer_state = IPP_PSTATE_STOPPED;
2345*5e7646d2SAndroid Build Coastguard Worker 					/* Current printer-state */
2346*5e7646d2SAndroid Build Coastguard Worker 
2347*5e7646d2SAndroid Build Coastguard Worker 
2348*5e7646d2SAndroid Build Coastguard Worker  /*
2349*5e7646d2SAndroid Build Coastguard Worker   * Send a Get-Printer-Attributes request and log the results...
2350*5e7646d2SAndroid Build Coastguard Worker   */
2351*5e7646d2SAndroid Build Coastguard Worker 
2352*5e7646d2SAndroid Build Coastguard Worker   request = ippNewRequest(IPP_OP_GET_PRINTER_ATTRIBUTES);
2353*5e7646d2SAndroid Build Coastguard Worker   ippSetVersion(request, version / 10, version % 10);
2354*5e7646d2SAndroid Build Coastguard Worker 
2355*5e7646d2SAndroid Build Coastguard Worker   ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
2356*5e7646d2SAndroid Build Coastguard Worker 	       NULL, uri);
2357*5e7646d2SAndroid Build Coastguard Worker 
2358*5e7646d2SAndroid Build Coastguard Worker   if (user && user[0])
2359*5e7646d2SAndroid Build Coastguard Worker     ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
2360*5e7646d2SAndroid Build Coastguard Worker 		 "requesting-user-name", NULL, user);
2361*5e7646d2SAndroid Build Coastguard Worker 
2362*5e7646d2SAndroid Build Coastguard Worker   ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
2363*5e7646d2SAndroid Build Coastguard Worker 		"requested-attributes",
2364*5e7646d2SAndroid Build Coastguard Worker 		(int)(sizeof(pattrs) / sizeof(pattrs[0])), NULL, pattrs);
2365*5e7646d2SAndroid Build Coastguard Worker 
2366*5e7646d2SAndroid Build Coastguard Worker   fprintf(stderr, "DEBUG: IPP/%d.%d %s #%d\n", version / 10, version % 10, ippOpString(ippGetOperation(request)), ippGetRequestId(request));
2367*5e7646d2SAndroid Build Coastguard Worker   debug_attributes(request);
2368*5e7646d2SAndroid Build Coastguard Worker 
2369*5e7646d2SAndroid Build Coastguard Worker   if ((response = cupsDoRequest(http, request, resource)) != NULL)
2370*5e7646d2SAndroid Build Coastguard Worker   {
2371*5e7646d2SAndroid Build Coastguard Worker     report_printer_state(response);
2372*5e7646d2SAndroid Build Coastguard Worker 
2373*5e7646d2SAndroid Build Coastguard Worker     if ((attr = ippFindAttribute(response, "printer-state",
2374*5e7646d2SAndroid Build Coastguard Worker 				 IPP_TAG_ENUM)) != NULL)
2375*5e7646d2SAndroid Build Coastguard Worker       printer_state = (ipp_pstate_t)attr->values[0].integer;
2376*5e7646d2SAndroid Build Coastguard Worker   }
2377*5e7646d2SAndroid Build Coastguard Worker 
2378*5e7646d2SAndroid Build Coastguard Worker   fprintf(stderr, "DEBUG: Get-Printer-Attributes: %s (%s)\n",
2379*5e7646d2SAndroid Build Coastguard Worker 	  ippErrorString(cupsLastError()), cupsLastErrorString());
2380*5e7646d2SAndroid Build Coastguard Worker   debug_attributes(response);
2381*5e7646d2SAndroid Build Coastguard Worker   ippDelete(response);
2382*5e7646d2SAndroid Build Coastguard Worker 
2383*5e7646d2SAndroid Build Coastguard Worker  /*
2384*5e7646d2SAndroid Build Coastguard Worker   * Return the printer-state value...
2385*5e7646d2SAndroid Build Coastguard Worker   */
2386*5e7646d2SAndroid Build Coastguard Worker 
2387*5e7646d2SAndroid Build Coastguard Worker   return (printer_state);
2388*5e7646d2SAndroid Build Coastguard Worker }
2389*5e7646d2SAndroid Build Coastguard Worker 
2390*5e7646d2SAndroid Build Coastguard Worker 
2391*5e7646d2SAndroid Build Coastguard Worker /*
2392*5e7646d2SAndroid Build Coastguard Worker  * 'debug_attributes()' - Print out the request or response attributes as DEBUG
2393*5e7646d2SAndroid Build Coastguard Worker  * messages...
2394*5e7646d2SAndroid Build Coastguard Worker  */
2395*5e7646d2SAndroid Build Coastguard Worker 
2396*5e7646d2SAndroid Build Coastguard Worker static void
debug_attributes(ipp_t * ipp)2397*5e7646d2SAndroid Build Coastguard Worker debug_attributes(ipp_t *ipp)		/* I - Request or response message */
2398*5e7646d2SAndroid Build Coastguard Worker {
2399*5e7646d2SAndroid Build Coastguard Worker   ipp_tag_t	group;			/* Current group */
2400*5e7646d2SAndroid Build Coastguard Worker   ipp_attribute_t *attr;		/* Current attribute */
2401*5e7646d2SAndroid Build Coastguard Worker   char		buffer[1024];		/* Value buffer */
2402*5e7646d2SAndroid Build Coastguard Worker 
2403*5e7646d2SAndroid Build Coastguard Worker 
2404*5e7646d2SAndroid Build Coastguard Worker   for (group = IPP_TAG_ZERO, attr = ippFirstAttribute(ipp);
2405*5e7646d2SAndroid Build Coastguard Worker        attr;
2406*5e7646d2SAndroid Build Coastguard Worker        attr = ippNextAttribute(ipp))
2407*5e7646d2SAndroid Build Coastguard Worker   {
2408*5e7646d2SAndroid Build Coastguard Worker     const char *name = ippGetName(attr);
2409*5e7646d2SAndroid Build Coastguard Worker 
2410*5e7646d2SAndroid Build Coastguard Worker     if (!name)
2411*5e7646d2SAndroid Build Coastguard Worker     {
2412*5e7646d2SAndroid Build Coastguard Worker       group = IPP_TAG_ZERO;
2413*5e7646d2SAndroid Build Coastguard Worker       continue;
2414*5e7646d2SAndroid Build Coastguard Worker     }
2415*5e7646d2SAndroid Build Coastguard Worker 
2416*5e7646d2SAndroid Build Coastguard Worker     if (group != ippGetGroupTag(attr))
2417*5e7646d2SAndroid Build Coastguard Worker     {
2418*5e7646d2SAndroid Build Coastguard Worker       group = ippGetGroupTag(attr);
2419*5e7646d2SAndroid Build Coastguard Worker       fprintf(stderr, "DEBUG: ---- %s ----\n", ippTagString(group));
2420*5e7646d2SAndroid Build Coastguard Worker     }
2421*5e7646d2SAndroid Build Coastguard Worker 
2422*5e7646d2SAndroid Build Coastguard Worker     if (!strcmp(name, "job-password"))
2423*5e7646d2SAndroid Build Coastguard Worker       strlcpy(buffer, "---", sizeof(buffer));
2424*5e7646d2SAndroid Build Coastguard Worker     else
2425*5e7646d2SAndroid Build Coastguard Worker       ippAttributeString(attr, buffer, sizeof(buffer));
2426*5e7646d2SAndroid Build Coastguard Worker 
2427*5e7646d2SAndroid Build Coastguard Worker     fprintf(stderr, "DEBUG: %s %s%s %s\n", name,
2428*5e7646d2SAndroid Build Coastguard Worker             ippGetCount(attr) > 1 ? "1setOf " : "",
2429*5e7646d2SAndroid Build Coastguard Worker             ippTagString(ippGetValueTag(attr)), buffer);
2430*5e7646d2SAndroid Build Coastguard Worker   }
2431*5e7646d2SAndroid Build Coastguard Worker 
2432*5e7646d2SAndroid Build Coastguard Worker   fprintf(stderr, "DEBUG: ---- %s ----\n", ippTagString(IPP_TAG_END));
2433*5e7646d2SAndroid Build Coastguard Worker }
2434*5e7646d2SAndroid Build Coastguard Worker 
2435*5e7646d2SAndroid Build Coastguard Worker 
2436*5e7646d2SAndroid Build Coastguard Worker /*
2437*5e7646d2SAndroid Build Coastguard Worker  * 'monitor_printer()' - Monitor the printer state.
2438*5e7646d2SAndroid Build Coastguard Worker  */
2439*5e7646d2SAndroid Build Coastguard Worker 
2440*5e7646d2SAndroid Build Coastguard Worker static void *				/* O - Thread exit code */
monitor_printer(_cups_monitor_t * monitor)2441*5e7646d2SAndroid Build Coastguard Worker monitor_printer(
2442*5e7646d2SAndroid Build Coastguard Worker     _cups_monitor_t *monitor)		/* I - Monitoring data */
2443*5e7646d2SAndroid Build Coastguard Worker {
2444*5e7646d2SAndroid Build Coastguard Worker   http_t	*http;			/* Connection to printer */
2445*5e7646d2SAndroid Build Coastguard Worker   ipp_t		*request,		/* IPP request */
2446*5e7646d2SAndroid Build Coastguard Worker 		*response;		/* IPP response */
2447*5e7646d2SAndroid Build Coastguard Worker   ipp_attribute_t *attr;		/* Attribute in response */
2448*5e7646d2SAndroid Build Coastguard Worker   int		delay,			/* Current delay */
2449*5e7646d2SAndroid Build Coastguard Worker 		prev_delay;		/* Previous delay */
2450*5e7646d2SAndroid Build Coastguard Worker   ipp_op_t	job_op;			/* Operation to use */
2451*5e7646d2SAndroid Build Coastguard Worker   int		job_id;			/* Job ID */
2452*5e7646d2SAndroid Build Coastguard Worker   const char	*job_name;		/* Job name */
2453*5e7646d2SAndroid Build Coastguard Worker   ipp_jstate_t	job_state;		/* Job state */
2454*5e7646d2SAndroid Build Coastguard Worker   const char	*job_user;		/* Job originating user name */
2455*5e7646d2SAndroid Build Coastguard Worker   int		password_tries = 0;	/* Password tries */
2456*5e7646d2SAndroid Build Coastguard Worker 
2457*5e7646d2SAndroid Build Coastguard Worker 
2458*5e7646d2SAndroid Build Coastguard Worker  /*
2459*5e7646d2SAndroid Build Coastguard Worker   * Make a copy of the printer connection...
2460*5e7646d2SAndroid Build Coastguard Worker   */
2461*5e7646d2SAndroid Build Coastguard Worker 
2462*5e7646d2SAndroid Build Coastguard Worker   http = httpConnect2(monitor->hostname, monitor->port, NULL, AF_UNSPEC,
2463*5e7646d2SAndroid Build Coastguard Worker                       monitor->encryption, 1, 0, NULL);
2464*5e7646d2SAndroid Build Coastguard Worker   httpSetTimeout(http, 30.0, timeout_cb, NULL);
2465*5e7646d2SAndroid Build Coastguard Worker   if (username[0])
2466*5e7646d2SAndroid Build Coastguard Worker     cupsSetUser(username);
2467*5e7646d2SAndroid Build Coastguard Worker 
2468*5e7646d2SAndroid Build Coastguard Worker   cupsSetPasswordCB2((cups_password_cb2_t)password_cb, &password_tries);
2469*5e7646d2SAndroid Build Coastguard Worker 
2470*5e7646d2SAndroid Build Coastguard Worker  /*
2471*5e7646d2SAndroid Build Coastguard Worker   * Loop until the job is canceled, aborted, or completed.
2472*5e7646d2SAndroid Build Coastguard Worker   */
2473*5e7646d2SAndroid Build Coastguard Worker 
2474*5e7646d2SAndroid Build Coastguard Worker   delay = _cupsNextDelay(0, &prev_delay);
2475*5e7646d2SAndroid Build Coastguard Worker 
2476*5e7646d2SAndroid Build Coastguard Worker   monitor->job_reasons = 0;
2477*5e7646d2SAndroid Build Coastguard Worker 
2478*5e7646d2SAndroid Build Coastguard Worker   while (monitor->job_state < IPP_JSTATE_CANCELED && !job_canceled)
2479*5e7646d2SAndroid Build Coastguard Worker   {
2480*5e7646d2SAndroid Build Coastguard Worker    /*
2481*5e7646d2SAndroid Build Coastguard Worker     * Reconnect to the printer as needed...
2482*5e7646d2SAndroid Build Coastguard Worker     */
2483*5e7646d2SAndroid Build Coastguard Worker 
2484*5e7646d2SAndroid Build Coastguard Worker     if (httpGetFd(http) < 0)
2485*5e7646d2SAndroid Build Coastguard Worker       httpReconnect2(http, 30000, NULL);
2486*5e7646d2SAndroid Build Coastguard Worker 
2487*5e7646d2SAndroid Build Coastguard Worker     if (httpGetFd(http) >= 0)
2488*5e7646d2SAndroid Build Coastguard Worker     {
2489*5e7646d2SAndroid Build Coastguard Worker      /*
2490*5e7646d2SAndroid Build Coastguard Worker       * Connected, so check on the printer state...
2491*5e7646d2SAndroid Build Coastguard Worker       */
2492*5e7646d2SAndroid Build Coastguard Worker 
2493*5e7646d2SAndroid Build Coastguard Worker       monitor->printer_state = check_printer_state(http, monitor->uri,
2494*5e7646d2SAndroid Build Coastguard Worker                                                    monitor->resource,
2495*5e7646d2SAndroid Build Coastguard Worker 						   monitor->user,
2496*5e7646d2SAndroid Build Coastguard Worker 						   monitor->version);
2497*5e7646d2SAndroid Build Coastguard Worker       if (cupsLastError() <= IPP_STATUS_OK_CONFLICTING)
2498*5e7646d2SAndroid Build Coastguard Worker         password_tries = 0;
2499*5e7646d2SAndroid Build Coastguard Worker 
2500*5e7646d2SAndroid Build Coastguard Worker       if (monitor->job_id == 0 && monitor->create_job)
2501*5e7646d2SAndroid Build Coastguard Worker       {
2502*5e7646d2SAndroid Build Coastguard Worker        /*
2503*5e7646d2SAndroid Build Coastguard Worker         * No job-id yet, so continue...
2504*5e7646d2SAndroid Build Coastguard Worker 	*/
2505*5e7646d2SAndroid Build Coastguard Worker 
2506*5e7646d2SAndroid Build Coastguard Worker         goto monitor_sleep;
2507*5e7646d2SAndroid Build Coastguard Worker       }
2508*5e7646d2SAndroid Build Coastguard Worker 
2509*5e7646d2SAndroid Build Coastguard Worker      /*
2510*5e7646d2SAndroid Build Coastguard Worker       * Check the status of the job itself...
2511*5e7646d2SAndroid Build Coastguard Worker       */
2512*5e7646d2SAndroid Build Coastguard Worker 
2513*5e7646d2SAndroid Build Coastguard Worker       job_op  = (monitor->job_id > 0 && monitor->get_job_attrs) ?
2514*5e7646d2SAndroid Build Coastguard Worker                     IPP_OP_GET_JOB_ATTRIBUTES : IPP_OP_GET_JOBS;
2515*5e7646d2SAndroid Build Coastguard Worker       request = ippNewRequest(job_op);
2516*5e7646d2SAndroid Build Coastguard Worker       ippSetVersion(request, monitor->version / 10, monitor->version % 10);
2517*5e7646d2SAndroid Build Coastguard Worker 
2518*5e7646d2SAndroid Build Coastguard Worker       ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
2519*5e7646d2SAndroid Build Coastguard Worker 		   NULL, monitor->uri);
2520*5e7646d2SAndroid Build Coastguard Worker       if (job_op == IPP_OP_GET_JOB_ATTRIBUTES)
2521*5e7646d2SAndroid Build Coastguard Worker 	ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER, "job-id",
2522*5e7646d2SAndroid Build Coastguard Worker 		      monitor->job_id);
2523*5e7646d2SAndroid Build Coastguard Worker 
2524*5e7646d2SAndroid Build Coastguard Worker       if (monitor->user && monitor->user[0])
2525*5e7646d2SAndroid Build Coastguard Worker 	ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
2526*5e7646d2SAndroid Build Coastguard Worker 		     "requesting-user-name", NULL, monitor->user);
2527*5e7646d2SAndroid Build Coastguard Worker 
2528*5e7646d2SAndroid Build Coastguard Worker       ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
2529*5e7646d2SAndroid Build Coastguard Worker 		    "requested-attributes",
2530*5e7646d2SAndroid Build Coastguard Worker 		    (int)(sizeof(jattrs) / sizeof(jattrs[0])), NULL, jattrs);
2531*5e7646d2SAndroid Build Coastguard Worker 
2532*5e7646d2SAndroid Build Coastguard Worker      /*
2533*5e7646d2SAndroid Build Coastguard Worker       * Do the request...
2534*5e7646d2SAndroid Build Coastguard Worker       */
2535*5e7646d2SAndroid Build Coastguard Worker 
2536*5e7646d2SAndroid Build Coastguard Worker       response = cupsDoRequest(http, request, monitor->resource);
2537*5e7646d2SAndroid Build Coastguard Worker 
2538*5e7646d2SAndroid Build Coastguard Worker       fprintf(stderr, "DEBUG: (monitor) %s: %s (%s)\n", ippOpString(job_op),
2539*5e7646d2SAndroid Build Coastguard Worker 	      ippErrorString(cupsLastError()), cupsLastErrorString());
2540*5e7646d2SAndroid Build Coastguard Worker 
2541*5e7646d2SAndroid Build Coastguard Worker       if (cupsLastError() <= IPP_STATUS_OK_CONFLICTING)
2542*5e7646d2SAndroid Build Coastguard Worker         password_tries = 0;
2543*5e7646d2SAndroid Build Coastguard Worker 
2544*5e7646d2SAndroid Build Coastguard Worker       if (job_op == IPP_OP_GET_JOB_ATTRIBUTES)
2545*5e7646d2SAndroid Build Coastguard Worker       {
2546*5e7646d2SAndroid Build Coastguard Worker 	if ((attr = ippFindAttribute(response, "job-state",
2547*5e7646d2SAndroid Build Coastguard Worker 				     IPP_TAG_ENUM)) != NULL)
2548*5e7646d2SAndroid Build Coastguard Worker 	  monitor->job_state = (ipp_jstate_t)attr->values[0].integer;
2549*5e7646d2SAndroid Build Coastguard Worker 	else
2550*5e7646d2SAndroid Build Coastguard Worker 	  monitor->job_state = IPP_JSTATE_COMPLETED;
2551*5e7646d2SAndroid Build Coastguard Worker       }
2552*5e7646d2SAndroid Build Coastguard Worker       else if (response)
2553*5e7646d2SAndroid Build Coastguard Worker       {
2554*5e7646d2SAndroid Build Coastguard Worker         for (attr = response->attrs; attr; attr = attr->next)
2555*5e7646d2SAndroid Build Coastguard Worker         {
2556*5e7646d2SAndroid Build Coastguard Worker           job_id    = 0;
2557*5e7646d2SAndroid Build Coastguard Worker           job_name  = NULL;
2558*5e7646d2SAndroid Build Coastguard Worker           job_state = IPP_JSTATE_PENDING;
2559*5e7646d2SAndroid Build Coastguard Worker           job_user  = NULL;
2560*5e7646d2SAndroid Build Coastguard Worker 
2561*5e7646d2SAndroid Build Coastguard Worker           while (attr && attr->group_tag != IPP_TAG_JOB)
2562*5e7646d2SAndroid Build Coastguard Worker             attr = attr->next;
2563*5e7646d2SAndroid Build Coastguard Worker 
2564*5e7646d2SAndroid Build Coastguard Worker           if (!attr)
2565*5e7646d2SAndroid Build Coastguard Worker             break;
2566*5e7646d2SAndroid Build Coastguard Worker 
2567*5e7646d2SAndroid Build Coastguard Worker           while (attr && attr->group_tag == IPP_TAG_JOB)
2568*5e7646d2SAndroid Build Coastguard Worker           {
2569*5e7646d2SAndroid Build Coastguard Worker             if (!strcmp(attr->name, "job-id") &&
2570*5e7646d2SAndroid Build Coastguard Worker                 attr->value_tag == IPP_TAG_INTEGER)
2571*5e7646d2SAndroid Build Coastguard Worker               job_id = attr->values[0].integer;
2572*5e7646d2SAndroid Build Coastguard Worker             else if (!strcmp(attr->name, "job-name") &&
2573*5e7646d2SAndroid Build Coastguard Worker 		     (attr->value_tag == IPP_TAG_NAME ||
2574*5e7646d2SAndroid Build Coastguard Worker 		      attr->value_tag == IPP_TAG_NAMELANG))
2575*5e7646d2SAndroid Build Coastguard Worker               job_name = attr->values[0].string.text;
2576*5e7646d2SAndroid Build Coastguard Worker             else if (!strcmp(attr->name, "job-state") &&
2577*5e7646d2SAndroid Build Coastguard Worker 		     attr->value_tag == IPP_TAG_ENUM)
2578*5e7646d2SAndroid Build Coastguard Worker               job_state = (ipp_jstate_t)attr->values[0].integer;
2579*5e7646d2SAndroid Build Coastguard Worker             else if (!strcmp(attr->name, "job-originating-user-name") &&
2580*5e7646d2SAndroid Build Coastguard Worker 		     (attr->value_tag == IPP_TAG_NAME ||
2581*5e7646d2SAndroid Build Coastguard Worker 		      attr->value_tag == IPP_TAG_NAMELANG))
2582*5e7646d2SAndroid Build Coastguard Worker               job_user = attr->values[0].string.text;
2583*5e7646d2SAndroid Build Coastguard Worker 
2584*5e7646d2SAndroid Build Coastguard Worker             attr = attr->next;
2585*5e7646d2SAndroid Build Coastguard Worker           }
2586*5e7646d2SAndroid Build Coastguard Worker 
2587*5e7646d2SAndroid Build Coastguard Worker           if (job_id > 0 && job_name && !strcmp(job_name, monitor->job_name) &&
2588*5e7646d2SAndroid Build Coastguard Worker               job_user && monitor->user && !strcmp(job_user, monitor->user))
2589*5e7646d2SAndroid Build Coastguard Worker           {
2590*5e7646d2SAndroid Build Coastguard Worker             monitor->job_id    = job_id;
2591*5e7646d2SAndroid Build Coastguard Worker             monitor->job_state = job_state;
2592*5e7646d2SAndroid Build Coastguard Worker             break;
2593*5e7646d2SAndroid Build Coastguard Worker           }
2594*5e7646d2SAndroid Build Coastguard Worker 
2595*5e7646d2SAndroid Build Coastguard Worker           if (!attr)
2596*5e7646d2SAndroid Build Coastguard Worker             break;
2597*5e7646d2SAndroid Build Coastguard Worker         }
2598*5e7646d2SAndroid Build Coastguard Worker       }
2599*5e7646d2SAndroid Build Coastguard Worker 
2600*5e7646d2SAndroid Build Coastguard Worker       fprintf(stderr, "DEBUG: (monitor) job-state = %s\n", ippEnumString("job-state", (int)monitor->job_state));
2601*5e7646d2SAndroid Build Coastguard Worker 
2602*5e7646d2SAndroid Build Coastguard Worker       if (!job_canceled &&
2603*5e7646d2SAndroid Build Coastguard Worker           (monitor->job_state == IPP_JSTATE_CANCELED ||
2604*5e7646d2SAndroid Build Coastguard Worker 	   monitor->job_state == IPP_JSTATE_ABORTED))
2605*5e7646d2SAndroid Build Coastguard Worker       {
2606*5e7646d2SAndroid Build Coastguard Worker 	job_canceled = -1;
2607*5e7646d2SAndroid Build Coastguard Worker 	fprintf(stderr, "DEBUG: (monitor) job_canceled = -1\n");
2608*5e7646d2SAndroid Build Coastguard Worker       }
2609*5e7646d2SAndroid Build Coastguard Worker 
2610*5e7646d2SAndroid Build Coastguard Worker       if ((attr = ippFindAttribute(response, "job-state-reasons",
2611*5e7646d2SAndroid Build Coastguard Worker                                    IPP_TAG_KEYWORD)) != NULL)
2612*5e7646d2SAndroid Build Coastguard Worker       {
2613*5e7646d2SAndroid Build Coastguard Worker         int	i, new_reasons = 0;	/* Looping var, new reasons */
2614*5e7646d2SAndroid Build Coastguard Worker 
2615*5e7646d2SAndroid Build Coastguard Worker         for (i = 0; i < attr->num_values; i ++)
2616*5e7646d2SAndroid Build Coastguard Worker         {
2617*5e7646d2SAndroid Build Coastguard Worker           if (!strcmp(attr->values[i].string.text, "account-authorization-failed"))
2618*5e7646d2SAndroid Build Coastguard Worker             new_reasons |= _CUPS_JSR_ACCOUNT_AUTHORIZATION_FAILED;
2619*5e7646d2SAndroid Build Coastguard Worker           else if (!strcmp(attr->values[i].string.text, "account-closed"))
2620*5e7646d2SAndroid Build Coastguard Worker             new_reasons |= _CUPS_JSR_ACCOUNT_CLOSED;
2621*5e7646d2SAndroid Build Coastguard Worker           else if (!strcmp(attr->values[i].string.text, "account-info-needed"))
2622*5e7646d2SAndroid Build Coastguard Worker             new_reasons |= _CUPS_JSR_ACCOUNT_INFO_NEEDED;
2623*5e7646d2SAndroid Build Coastguard Worker           else if (!strcmp(attr->values[i].string.text, "account-limit-reached"))
2624*5e7646d2SAndroid Build Coastguard Worker             new_reasons |= _CUPS_JSR_ACCOUNT_LIMIT_REACHED;
2625*5e7646d2SAndroid Build Coastguard Worker           else if (!strcmp(attr->values[i].string.text, "job-password-wait"))
2626*5e7646d2SAndroid Build Coastguard Worker             new_reasons |= _CUPS_JSR_JOB_PASSWORD_WAIT;
2627*5e7646d2SAndroid Build Coastguard Worker           else if (!strcmp(attr->values[i].string.text, "job-release-wait"))
2628*5e7646d2SAndroid Build Coastguard Worker             new_reasons |= _CUPS_JSR_JOB_RELEASE_WAIT;
2629*5e7646d2SAndroid Build Coastguard Worker           else if (!strcmp(attr->values[i].string.text, "document-format-error"))
2630*5e7646d2SAndroid Build Coastguard Worker             new_reasons |= _CUPS_JSR_DOCUMENT_FORMAT_ERROR;
2631*5e7646d2SAndroid Build Coastguard Worker           else if (!strcmp(attr->values[i].string.text, "document-unprintable"))
2632*5e7646d2SAndroid Build Coastguard Worker             new_reasons |= _CUPS_JSR_DOCUMENT_UNPRINTABLE;
2633*5e7646d2SAndroid Build Coastguard Worker 
2634*5e7646d2SAndroid Build Coastguard Worker 	  if (!job_canceled && (!strncmp(attr->values[i].string.text, "job-canceled-", 13) || !strcmp(attr->values[i].string.text, "aborted-by-system")))
2635*5e7646d2SAndroid Build Coastguard Worker             job_canceled = 1;
2636*5e7646d2SAndroid Build Coastguard Worker         }
2637*5e7646d2SAndroid Build Coastguard Worker 
2638*5e7646d2SAndroid Build Coastguard Worker         if (new_reasons != monitor->job_reasons)
2639*5e7646d2SAndroid Build Coastguard Worker         {
2640*5e7646d2SAndroid Build Coastguard Worker 	  if (new_reasons & _CUPS_JSR_ACCOUNT_AUTHORIZATION_FAILED)
2641*5e7646d2SAndroid Build Coastguard Worker 	    fputs("JOBSTATE: account-authorization-failed\n", stderr);
2642*5e7646d2SAndroid Build Coastguard Worker 	  else if (new_reasons & _CUPS_JSR_ACCOUNT_CLOSED)
2643*5e7646d2SAndroid Build Coastguard Worker 	    fputs("JOBSTATE: account-closed\n", stderr);
2644*5e7646d2SAndroid Build Coastguard Worker 	  else if (new_reasons & _CUPS_JSR_ACCOUNT_INFO_NEEDED)
2645*5e7646d2SAndroid Build Coastguard Worker 	    fputs("JOBSTATE: account-info-needed\n", stderr);
2646*5e7646d2SAndroid Build Coastguard Worker 	  else if (new_reasons & _CUPS_JSR_ACCOUNT_LIMIT_REACHED)
2647*5e7646d2SAndroid Build Coastguard Worker 	    fputs("JOBSTATE: account-limit-reached\n", stderr);
2648*5e7646d2SAndroid Build Coastguard Worker 	  else if (new_reasons & _CUPS_JSR_JOB_PASSWORD_WAIT)
2649*5e7646d2SAndroid Build Coastguard Worker 	    fputs("JOBSTATE: job-password-wait\n", stderr);
2650*5e7646d2SAndroid Build Coastguard Worker 	  else if (new_reasons & _CUPS_JSR_JOB_RELEASE_WAIT)
2651*5e7646d2SAndroid Build Coastguard Worker 	    fputs("JOBSTATE: job-release-wait\n", stderr);
2652*5e7646d2SAndroid Build Coastguard Worker           else if (new_reasons & (_CUPS_JSR_DOCUMENT_FORMAT_ERROR | _CUPS_JSR_DOCUMENT_UNPRINTABLE))
2653*5e7646d2SAndroid Build Coastguard Worker           {
2654*5e7646d2SAndroid Build Coastguard Worker             if (monitor->retryable)
2655*5e7646d2SAndroid Build Coastguard Worker             {
2656*5e7646d2SAndroid Build Coastguard Worker              /*
2657*5e7646d2SAndroid Build Coastguard Worker               * Can't print this, so retry as raster...
2658*5e7646d2SAndroid Build Coastguard Worker               */
2659*5e7646d2SAndroid Build Coastguard Worker 
2660*5e7646d2SAndroid Build Coastguard Worker               job_canceled = 1;
2661*5e7646d2SAndroid Build Coastguard Worker               fputs("JOBSTATE: cups-retry-as-raster\n", stderr);
2662*5e7646d2SAndroid Build Coastguard Worker 	    }
2663*5e7646d2SAndroid Build Coastguard Worker 	    else if (new_reasons & _CUPS_JSR_DOCUMENT_FORMAT_ERROR)
2664*5e7646d2SAndroid Build Coastguard Worker 	    {
2665*5e7646d2SAndroid Build Coastguard Worker 	      fputs("JOBSTATE: document-format-error\n", stderr);
2666*5e7646d2SAndroid Build Coastguard Worker 	    }
2667*5e7646d2SAndroid Build Coastguard Worker 	    else
2668*5e7646d2SAndroid Build Coastguard Worker 	    {
2669*5e7646d2SAndroid Build Coastguard Worker 	      fputs("JOBSTATE: document-unprintable\n", stderr);
2670*5e7646d2SAndroid Build Coastguard Worker 	    }
2671*5e7646d2SAndroid Build Coastguard Worker           }
2672*5e7646d2SAndroid Build Coastguard Worker 	  else
2673*5e7646d2SAndroid Build Coastguard Worker 	    fputs("JOBSTATE: job-printing\n", stderr);
2674*5e7646d2SAndroid Build Coastguard Worker 
2675*5e7646d2SAndroid Build Coastguard Worker 	  monitor->job_reasons = new_reasons;
2676*5e7646d2SAndroid Build Coastguard Worker         }
2677*5e7646d2SAndroid Build Coastguard Worker       }
2678*5e7646d2SAndroid Build Coastguard Worker 
2679*5e7646d2SAndroid Build Coastguard Worker       ippDelete(response);
2680*5e7646d2SAndroid Build Coastguard Worker 
2681*5e7646d2SAndroid Build Coastguard Worker       fprintf(stderr, "DEBUG: (monitor) job-state = %s\n", ippEnumString("job-state", (int)monitor->job_state));
2682*5e7646d2SAndroid Build Coastguard Worker 
2683*5e7646d2SAndroid Build Coastguard Worker       if (!job_canceled &&
2684*5e7646d2SAndroid Build Coastguard Worker           (monitor->job_state == IPP_JSTATE_CANCELED ||
2685*5e7646d2SAndroid Build Coastguard Worker 	   monitor->job_state == IPP_JSTATE_ABORTED))
2686*5e7646d2SAndroid Build Coastguard Worker 	job_canceled = -1;
2687*5e7646d2SAndroid Build Coastguard Worker     }
2688*5e7646d2SAndroid Build Coastguard Worker 
2689*5e7646d2SAndroid Build Coastguard Worker    /*
2690*5e7646d2SAndroid Build Coastguard Worker     * Sleep for N seconds...
2691*5e7646d2SAndroid Build Coastguard Worker     */
2692*5e7646d2SAndroid Build Coastguard Worker 
2693*5e7646d2SAndroid Build Coastguard Worker     monitor_sleep:
2694*5e7646d2SAndroid Build Coastguard Worker 
2695*5e7646d2SAndroid Build Coastguard Worker     sleep((unsigned)delay);
2696*5e7646d2SAndroid Build Coastguard Worker 
2697*5e7646d2SAndroid Build Coastguard Worker     delay = _cupsNextDelay(delay, &prev_delay);
2698*5e7646d2SAndroid Build Coastguard Worker   }
2699*5e7646d2SAndroid Build Coastguard Worker 
2700*5e7646d2SAndroid Build Coastguard Worker  /*
2701*5e7646d2SAndroid Build Coastguard Worker   * Cancel the job if necessary...
2702*5e7646d2SAndroid Build Coastguard Worker   */
2703*5e7646d2SAndroid Build Coastguard Worker 
2704*5e7646d2SAndroid Build Coastguard Worker   if (job_canceled > 0 && monitor->job_id > 0)
2705*5e7646d2SAndroid Build Coastguard Worker   {
2706*5e7646d2SAndroid Build Coastguard Worker     if (httpGetFd(http) < 0)
2707*5e7646d2SAndroid Build Coastguard Worker       httpReconnect2(http, 30000, NULL);
2708*5e7646d2SAndroid Build Coastguard Worker 
2709*5e7646d2SAndroid Build Coastguard Worker     if (httpGetFd(http) >= 0)
2710*5e7646d2SAndroid Build Coastguard Worker     {
2711*5e7646d2SAndroid Build Coastguard Worker       cancel_job(http, monitor->uri, monitor->job_id, monitor->resource,
2712*5e7646d2SAndroid Build Coastguard Worker                  monitor->user, monitor->version);
2713*5e7646d2SAndroid Build Coastguard Worker 
2714*5e7646d2SAndroid Build Coastguard Worker       if (cupsLastError() > IPP_STATUS_OK_CONFLICTING)
2715*5e7646d2SAndroid Build Coastguard Worker       {
2716*5e7646d2SAndroid Build Coastguard Worker 	fprintf(stderr, "DEBUG: (monitor) cancel_job() = %s\n", cupsLastErrorString());
2717*5e7646d2SAndroid Build Coastguard Worker 	_cupsLangPrintFilter(stderr, "ERROR", _("Unable to cancel print job."));
2718*5e7646d2SAndroid Build Coastguard Worker       }
2719*5e7646d2SAndroid Build Coastguard Worker     }
2720*5e7646d2SAndroid Build Coastguard Worker   }
2721*5e7646d2SAndroid Build Coastguard Worker 
2722*5e7646d2SAndroid Build Coastguard Worker  /*
2723*5e7646d2SAndroid Build Coastguard Worker   * Cleanup and return...
2724*5e7646d2SAndroid Build Coastguard Worker   */
2725*5e7646d2SAndroid Build Coastguard Worker 
2726*5e7646d2SAndroid Build Coastguard Worker   httpClose(http);
2727*5e7646d2SAndroid Build Coastguard Worker 
2728*5e7646d2SAndroid Build Coastguard Worker   return (NULL);
2729*5e7646d2SAndroid Build Coastguard Worker }
2730*5e7646d2SAndroid Build Coastguard Worker 
2731*5e7646d2SAndroid Build Coastguard Worker 
2732*5e7646d2SAndroid Build Coastguard Worker /*
2733*5e7646d2SAndroid Build Coastguard Worker  * 'new_request()' - Create a new print creation or validation request.
2734*5e7646d2SAndroid Build Coastguard Worker  */
2735*5e7646d2SAndroid Build Coastguard Worker 
2736*5e7646d2SAndroid Build Coastguard Worker static ipp_t *				/* O - Request data */
new_request(ipp_op_t op,int version,const char * uri,const char * user,const char * title,int num_options,cups_option_t * options,const char * compression,int copies,const char * format,_ppd_cache_t * pc,ppd_file_t * ppd,ipp_attribute_t * media_col_sup,ipp_attribute_t * doc_handling_sup,ipp_attribute_t * print_color_mode_sup)2737*5e7646d2SAndroid Build Coastguard Worker new_request(
2738*5e7646d2SAndroid Build Coastguard Worker     ipp_op_t        op,			/* I - IPP operation code */
2739*5e7646d2SAndroid Build Coastguard Worker     int             version,		/* I - IPP version number */
2740*5e7646d2SAndroid Build Coastguard Worker     const char      *uri,		/* I - printer-uri value */
2741*5e7646d2SAndroid Build Coastguard Worker     const char      *user,		/* I - requesting-user-name value */
2742*5e7646d2SAndroid Build Coastguard Worker     const char      *title,		/* I - job-name value */
2743*5e7646d2SAndroid Build Coastguard Worker     int             num_options,	/* I - Number of options to send */
2744*5e7646d2SAndroid Build Coastguard Worker     cups_option_t   *options,		/* I - Options to send */
2745*5e7646d2SAndroid Build Coastguard Worker     const char      *compression,	/* I - compression value or NULL */
2746*5e7646d2SAndroid Build Coastguard Worker     int             copies,		/* I - copies value or 0 */
2747*5e7646d2SAndroid Build Coastguard Worker     const char      *format,		/* I - document-format value or NULL */
2748*5e7646d2SAndroid Build Coastguard Worker     _ppd_cache_t    *pc,		/* I - PPD cache and mapping data */
2749*5e7646d2SAndroid Build Coastguard Worker     ppd_file_t      *ppd,		/* I - PPD file data */
2750*5e7646d2SAndroid Build Coastguard Worker     ipp_attribute_t *media_col_sup,	/* I - media-col-supported values */
2751*5e7646d2SAndroid Build Coastguard Worker     ipp_attribute_t *doc_handling_sup,  /* I - multiple-document-handling-supported values */
2752*5e7646d2SAndroid Build Coastguard Worker     ipp_attribute_t *print_color_mode_sup)
2753*5e7646d2SAndroid Build Coastguard Worker 					/* I - Printer supports print-color-mode */
2754*5e7646d2SAndroid Build Coastguard Worker {
2755*5e7646d2SAndroid Build Coastguard Worker   ipp_t		*request;		/* Request data */
2756*5e7646d2SAndroid Build Coastguard Worker   const char	*keyword;		/* PWG keyword */
2757*5e7646d2SAndroid Build Coastguard Worker 
2758*5e7646d2SAndroid Build Coastguard Worker 
2759*5e7646d2SAndroid Build Coastguard Worker  /*
2760*5e7646d2SAndroid Build Coastguard Worker   * Create the IPP request...
2761*5e7646d2SAndroid Build Coastguard Worker   */
2762*5e7646d2SAndroid Build Coastguard Worker 
2763*5e7646d2SAndroid Build Coastguard Worker   request = ippNewRequest(op);
2764*5e7646d2SAndroid Build Coastguard Worker   ippSetVersion(request, version / 10, version % 10);
2765*5e7646d2SAndroid Build Coastguard Worker 
2766*5e7646d2SAndroid Build Coastguard Worker   fprintf(stderr, "DEBUG: %s IPP/%d.%d\n",
2767*5e7646d2SAndroid Build Coastguard Worker 	  ippOpString(request->request.op.operation_id),
2768*5e7646d2SAndroid Build Coastguard Worker 	  request->request.op.version[0],
2769*5e7646d2SAndroid Build Coastguard Worker 	  request->request.op.version[1]);
2770*5e7646d2SAndroid Build Coastguard Worker 
2771*5e7646d2SAndroid Build Coastguard Worker  /*
2772*5e7646d2SAndroid Build Coastguard Worker   * Add standard attributes...
2773*5e7646d2SAndroid Build Coastguard Worker   */
2774*5e7646d2SAndroid Build Coastguard Worker 
2775*5e7646d2SAndroid Build Coastguard Worker   ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, uri);
2776*5e7646d2SAndroid Build Coastguard Worker   fprintf(stderr, "DEBUG: printer-uri=\"%s\"\n", uri);
2777*5e7646d2SAndroid Build Coastguard Worker 
2778*5e7646d2SAndroid Build Coastguard Worker   if (user && *user)
2779*5e7646d2SAndroid Build Coastguard Worker   {
2780*5e7646d2SAndroid Build Coastguard Worker     ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, user);
2781*5e7646d2SAndroid Build Coastguard Worker     fprintf(stderr, "DEBUG: requesting-user-name=\"%s\"\n", user);
2782*5e7646d2SAndroid Build Coastguard Worker   }
2783*5e7646d2SAndroid Build Coastguard Worker 
2784*5e7646d2SAndroid Build Coastguard Worker   if (title && *title)
2785*5e7646d2SAndroid Build Coastguard Worker   {
2786*5e7646d2SAndroid Build Coastguard Worker     ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "job-name", NULL, title);
2787*5e7646d2SAndroid Build Coastguard Worker     fprintf(stderr, "DEBUG: job-name=\"%s\"\n", title);
2788*5e7646d2SAndroid Build Coastguard Worker   }
2789*5e7646d2SAndroid Build Coastguard Worker 
2790*5e7646d2SAndroid Build Coastguard Worker   if (format && op != IPP_OP_CREATE_JOB)
2791*5e7646d2SAndroid Build Coastguard Worker   {
2792*5e7646d2SAndroid Build Coastguard Worker     ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_MIMETYPE, "document-format", NULL, format);
2793*5e7646d2SAndroid Build Coastguard Worker     fprintf(stderr, "DEBUG: document-format=\"%s\"\n", format);
2794*5e7646d2SAndroid Build Coastguard Worker   }
2795*5e7646d2SAndroid Build Coastguard Worker 
2796*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_LIBZ
2797*5e7646d2SAndroid Build Coastguard Worker   if (compression && op != IPP_OP_CREATE_JOB && op != IPP_OP_VALIDATE_JOB)
2798*5e7646d2SAndroid Build Coastguard Worker   {
2799*5e7646d2SAndroid Build Coastguard Worker     ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, "compression", NULL, compression);
2800*5e7646d2SAndroid Build Coastguard Worker     fprintf(stderr, "DEBUG: compression=\"%s\"\n", compression);
2801*5e7646d2SAndroid Build Coastguard Worker   }
2802*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_LIBZ */
2803*5e7646d2SAndroid Build Coastguard Worker 
2804*5e7646d2SAndroid Build Coastguard Worker  /*
2805*5e7646d2SAndroid Build Coastguard Worker   * Handle options on the command-line...
2806*5e7646d2SAndroid Build Coastguard Worker   */
2807*5e7646d2SAndroid Build Coastguard Worker 
2808*5e7646d2SAndroid Build Coastguard Worker   if (num_options > 0)
2809*5e7646d2SAndroid Build Coastguard Worker   {
2810*5e7646d2SAndroid Build Coastguard Worker     if (pc)
2811*5e7646d2SAndroid Build Coastguard Worker     {
2812*5e7646d2SAndroid Build Coastguard Worker      /*
2813*5e7646d2SAndroid Build Coastguard Worker       * Send standard IPP attributes...
2814*5e7646d2SAndroid Build Coastguard Worker       */
2815*5e7646d2SAndroid Build Coastguard Worker 
2816*5e7646d2SAndroid Build Coastguard Worker       fputs("DEBUG: Adding standard IPP operation/job attributes.\n", stderr);
2817*5e7646d2SAndroid Build Coastguard Worker 
2818*5e7646d2SAndroid Build Coastguard Worker       copies = _cupsConvertOptions(request, ppd, pc, media_col_sup, doc_handling_sup, print_color_mode_sup, user, format, copies, num_options, options);
2819*5e7646d2SAndroid Build Coastguard Worker 
2820*5e7646d2SAndroid Build Coastguard Worker      /*
2821*5e7646d2SAndroid Build Coastguard Worker       * Map FaxOut options...
2822*5e7646d2SAndroid Build Coastguard Worker       */
2823*5e7646d2SAndroid Build Coastguard Worker 
2824*5e7646d2SAndroid Build Coastguard Worker       if ((keyword = cupsGetOption("phone", num_options, options)) != NULL)
2825*5e7646d2SAndroid Build Coastguard Worker       {
2826*5e7646d2SAndroid Build Coastguard Worker 	ipp_t	*destination;		/* destination collection */
2827*5e7646d2SAndroid Build Coastguard Worker 	char	phone[1024],		/* Phone number string */
2828*5e7646d2SAndroid Build Coastguard Worker 		*ptr,			/* Pointer into string */
2829*5e7646d2SAndroid Build Coastguard Worker 		tel_uri[1024];		/* tel: URI */
2830*5e7646d2SAndroid Build Coastguard Worker         static const char * const allowed = "0123456789#*-+.()pw";
2831*5e7646d2SAndroid Build Coastguard Worker 					/* Allowed characters */
2832*5e7646d2SAndroid Build Coastguard Worker 
2833*5e7646d2SAndroid Build Coastguard Worker         destination = ippNew();
2834*5e7646d2SAndroid Build Coastguard Worker 
2835*5e7646d2SAndroid Build Coastguard Worker        /*
2836*5e7646d2SAndroid Build Coastguard Worker         * Unescape and filter out spaces and other characters that are not
2837*5e7646d2SAndroid Build Coastguard Worker         * allowed in a tel: URI.
2838*5e7646d2SAndroid Build Coastguard Worker         */
2839*5e7646d2SAndroid Build Coastguard Worker 
2840*5e7646d2SAndroid Build Coastguard Worker         _httpDecodeURI(phone, keyword, sizeof(phone));
2841*5e7646d2SAndroid Build Coastguard Worker         ptr = phone;
2842*5e7646d2SAndroid Build Coastguard Worker 
2843*5e7646d2SAndroid Build Coastguard Worker         /*
2844*5e7646d2SAndroid Build Coastguard Worker          * Weed out "Custom." in the beginning, this allows to put the
2845*5e7646d2SAndroid Build Coastguard Worker          * "phone" option as custom string option into the PPD so that
2846*5e7646d2SAndroid Build Coastguard Worker          * print dialogs not supporting fax display the option and
2847*5e7646d2SAndroid Build Coastguard Worker          * allow entering the phone number. Print dialogs also send "None"
2848*5e7646d2SAndroid Build Coastguard Worker          * if no phone number got entered, filter this, too.
2849*5e7646d2SAndroid Build Coastguard Worker          */
2850*5e7646d2SAndroid Build Coastguard Worker         if (!_cups_strcasecmp(phone, "None"))
2851*5e7646d2SAndroid Build Coastguard Worker           *ptr = '\0';
2852*5e7646d2SAndroid Build Coastguard Worker         if (!_cups_strncasecmp(phone, "Custom.", 7))
2853*5e7646d2SAndroid Build Coastguard Worker           _cups_strcpy(ptr, ptr + 7);
2854*5e7646d2SAndroid Build Coastguard Worker 
2855*5e7646d2SAndroid Build Coastguard Worker         for (; *ptr;)
2856*5e7646d2SAndroid Build Coastguard Worker 	{
2857*5e7646d2SAndroid Build Coastguard Worker 	  if (*ptr == ',')
2858*5e7646d2SAndroid Build Coastguard Worker 	    *ptr = 'p';
2859*5e7646d2SAndroid Build Coastguard Worker 	  else if (!strchr(allowed, *ptr))
2860*5e7646d2SAndroid Build Coastguard Worker 	    _cups_strcpy(ptr, ptr + 1);
2861*5e7646d2SAndroid Build Coastguard Worker 	  else
2862*5e7646d2SAndroid Build Coastguard Worker 	    ptr ++;
2863*5e7646d2SAndroid Build Coastguard Worker         }
2864*5e7646d2SAndroid Build Coastguard Worker 
2865*5e7646d2SAndroid Build Coastguard Worker         if (strlen(phone) > 0)
2866*5e7646d2SAndroid Build Coastguard Worker         {
2867*5e7646d2SAndroid Build Coastguard Worker           httpAssembleURI(HTTP_URI_CODING_ALL, tel_uri, sizeof(tel_uri), "tel", NULL, NULL, 0, phone);
2868*5e7646d2SAndroid Build Coastguard Worker           ippAddString(destination, IPP_TAG_JOB, IPP_TAG_URI, "destination-uri", NULL, tel_uri);
2869*5e7646d2SAndroid Build Coastguard Worker           fprintf(stderr, "DEBUG: Faxing to phone %s; destination-uri: %s\n", phone, tel_uri);
2870*5e7646d2SAndroid Build Coastguard Worker 
2871*5e7646d2SAndroid Build Coastguard Worker           if ((keyword = cupsGetOption("faxPrefix", num_options, options)) != NULL && *keyword)
2872*5e7646d2SAndroid Build Coastguard Worker           {
2873*5e7646d2SAndroid Build Coastguard Worker             char	predial[1024];		/* Pre-dial string */
2874*5e7646d2SAndroid Build Coastguard Worker 
2875*5e7646d2SAndroid Build Coastguard Worker             _httpDecodeURI(predial, keyword, sizeof(predial));
2876*5e7646d2SAndroid Build Coastguard Worker             ptr = predial;
2877*5e7646d2SAndroid Build Coastguard Worker             if (!_cups_strcasecmp(ptr, "None"))
2878*5e7646d2SAndroid Build Coastguard Worker               *ptr = '\0';
2879*5e7646d2SAndroid Build Coastguard Worker             if (!_cups_strncasecmp(ptr, "Custom.", 7))
2880*5e7646d2SAndroid Build Coastguard Worker               ptr += 7;
2881*5e7646d2SAndroid Build Coastguard Worker             if (strlen(ptr) > 0)
2882*5e7646d2SAndroid Build Coastguard Worker             {
2883*5e7646d2SAndroid Build Coastguard Worker               ippAddString(destination, IPP_TAG_JOB, IPP_TAG_TEXT, "pre-dial-string", NULL, ptr);
2884*5e7646d2SAndroid Build Coastguard Worker               fprintf(stderr, "DEBUG: Pre-dialing %s; pre-dial-string: %s\n", ptr, ptr);
2885*5e7646d2SAndroid Build Coastguard Worker             }
2886*5e7646d2SAndroid Build Coastguard Worker             else
2887*5e7646d2SAndroid Build Coastguard Worker               fprintf(stderr, "WARNING: Pre-dial number for fax not valid! Sending fax without pre-dial number.\n");
2888*5e7646d2SAndroid Build Coastguard Worker           }
2889*5e7646d2SAndroid Build Coastguard Worker 
2890*5e7646d2SAndroid Build Coastguard Worker           ippAddCollection(request, IPP_TAG_JOB, "destination-uris", destination);
2891*5e7646d2SAndroid Build Coastguard Worker           ippDelete(destination);
2892*5e7646d2SAndroid Build Coastguard Worker         }
2893*5e7646d2SAndroid Build Coastguard Worker         else
2894*5e7646d2SAndroid Build Coastguard Worker           fprintf(stderr, "ERROR: Phone number for fax not valid! Fax cannot be sent.\n");
2895*5e7646d2SAndroid Build Coastguard Worker       }
2896*5e7646d2SAndroid Build Coastguard Worker     }
2897*5e7646d2SAndroid Build Coastguard Worker     else
2898*5e7646d2SAndroid Build Coastguard Worker     {
2899*5e7646d2SAndroid Build Coastguard Worker      /*
2900*5e7646d2SAndroid Build Coastguard Worker       * When talking to another CUPS server, send all options...
2901*5e7646d2SAndroid Build Coastguard Worker       */
2902*5e7646d2SAndroid Build Coastguard Worker 
2903*5e7646d2SAndroid Build Coastguard Worker       fputs("DEBUG: Adding all operation/job attributes.\n", stderr);
2904*5e7646d2SAndroid Build Coastguard Worker       cupsEncodeOptions2(request, num_options, options, IPP_TAG_OPERATION);
2905*5e7646d2SAndroid Build Coastguard Worker       cupsEncodeOptions2(request, num_options, options, IPP_TAG_JOB);
2906*5e7646d2SAndroid Build Coastguard Worker     }
2907*5e7646d2SAndroid Build Coastguard Worker 
2908*5e7646d2SAndroid Build Coastguard Worker     if (copies > 1 && (!pc || copies <= pc->max_copies))
2909*5e7646d2SAndroid Build Coastguard Worker       ippAddInteger(request, IPP_TAG_JOB, IPP_TAG_INTEGER, "copies", copies);
2910*5e7646d2SAndroid Build Coastguard Worker   }
2911*5e7646d2SAndroid Build Coastguard Worker 
2912*5e7646d2SAndroid Build Coastguard Worker   fprintf(stderr, "DEBUG: IPP/%d.%d %s #%d\n", version / 10, version % 10, ippOpString(ippGetOperation(request)), ippGetRequestId(request));
2913*5e7646d2SAndroid Build Coastguard Worker   debug_attributes(request);
2914*5e7646d2SAndroid Build Coastguard Worker 
2915*5e7646d2SAndroid Build Coastguard Worker   return (request);
2916*5e7646d2SAndroid Build Coastguard Worker }
2917*5e7646d2SAndroid Build Coastguard Worker 
2918*5e7646d2SAndroid Build Coastguard Worker 
2919*5e7646d2SAndroid Build Coastguard Worker /*
2920*5e7646d2SAndroid Build Coastguard Worker  * 'password_cb()' - Disable the password prompt for cupsDoFileRequest().
2921*5e7646d2SAndroid Build Coastguard Worker  */
2922*5e7646d2SAndroid Build Coastguard Worker 
2923*5e7646d2SAndroid Build Coastguard Worker static const char *			/* O - Password  */
password_cb(const char * prompt,http_t * http,const char * method,const char * resource,int * password_tries)2924*5e7646d2SAndroid Build Coastguard Worker password_cb(const char *prompt,		/* I - Prompt (not used) */
2925*5e7646d2SAndroid Build Coastguard Worker             http_t     *http,		/* I - Connection */
2926*5e7646d2SAndroid Build Coastguard Worker             const char *method,		/* I - Request method (not used) */
2927*5e7646d2SAndroid Build Coastguard Worker             const char *resource,	/* I - Resource path (not used) */
2928*5e7646d2SAndroid Build Coastguard Worker             int        *password_tries)	/* I - Password tries */
2929*5e7646d2SAndroid Build Coastguard Worker {
2930*5e7646d2SAndroid Build Coastguard Worker   char	def_username[HTTP_MAX_VALUE];	/* Default username */
2931*5e7646d2SAndroid Build Coastguard Worker 
2932*5e7646d2SAndroid Build Coastguard Worker 
2933*5e7646d2SAndroid Build Coastguard Worker   fprintf(stderr, "DEBUG: password_cb(prompt=\"%s\", http=%p, method=\"%s\", "
2934*5e7646d2SAndroid Build Coastguard Worker                   "resource=\"%s\", password_tries=%p(%d)), password=%p\n",
2935*5e7646d2SAndroid Build Coastguard Worker           prompt, http, method, resource, password_tries, *password_tries,
2936*5e7646d2SAndroid Build Coastguard Worker           password);
2937*5e7646d2SAndroid Build Coastguard Worker 
2938*5e7646d2SAndroid Build Coastguard Worker   (void)prompt;
2939*5e7646d2SAndroid Build Coastguard Worker   (void)method;
2940*5e7646d2SAndroid Build Coastguard Worker   (void)resource;
2941*5e7646d2SAndroid Build Coastguard Worker 
2942*5e7646d2SAndroid Build Coastguard Worker   if (!uri_credentials)
2943*5e7646d2SAndroid Build Coastguard Worker   {
2944*5e7646d2SAndroid Build Coastguard Worker    /*
2945*5e7646d2SAndroid Build Coastguard Worker     * Remember that we need to authenticate...
2946*5e7646d2SAndroid Build Coastguard Worker     */
2947*5e7646d2SAndroid Build Coastguard Worker 
2948*5e7646d2SAndroid Build Coastguard Worker     auth_info_required = "username,password";
2949*5e7646d2SAndroid Build Coastguard Worker 
2950*5e7646d2SAndroid Build Coastguard Worker     if (httpGetSubField(http, HTTP_FIELD_WWW_AUTHENTICATE, "username",
2951*5e7646d2SAndroid Build Coastguard Worker 			def_username))
2952*5e7646d2SAndroid Build Coastguard Worker     {
2953*5e7646d2SAndroid Build Coastguard Worker       char	quoted[HTTP_MAX_VALUE * 2 + 4];
2954*5e7646d2SAndroid Build Coastguard Worker 					  /* Quoted string */
2955*5e7646d2SAndroid Build Coastguard Worker 
2956*5e7646d2SAndroid Build Coastguard Worker       fprintf(stderr, "ATTR: auth-info-default=%s,\n",
2957*5e7646d2SAndroid Build Coastguard Worker 	      quote_string(def_username, quoted, sizeof(quoted)));
2958*5e7646d2SAndroid Build Coastguard Worker     }
2959*5e7646d2SAndroid Build Coastguard Worker   }
2960*5e7646d2SAndroid Build Coastguard Worker 
2961*5e7646d2SAndroid Build Coastguard Worker   if (password && *password && *password_tries < 3)
2962*5e7646d2SAndroid Build Coastguard Worker   {
2963*5e7646d2SAndroid Build Coastguard Worker     (*password_tries) ++;
2964*5e7646d2SAndroid Build Coastguard Worker 
2965*5e7646d2SAndroid Build Coastguard Worker     cupsSetUser(username);
2966*5e7646d2SAndroid Build Coastguard Worker 
2967*5e7646d2SAndroid Build Coastguard Worker     return (password);
2968*5e7646d2SAndroid Build Coastguard Worker   }
2969*5e7646d2SAndroid Build Coastguard Worker   else
2970*5e7646d2SAndroid Build Coastguard Worker   {
2971*5e7646d2SAndroid Build Coastguard Worker    /*
2972*5e7646d2SAndroid Build Coastguard Worker     * Give up after 3 tries or if we don't have a password to begin with...
2973*5e7646d2SAndroid Build Coastguard Worker     */
2974*5e7646d2SAndroid Build Coastguard Worker 
2975*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
2976*5e7646d2SAndroid Build Coastguard Worker   }
2977*5e7646d2SAndroid Build Coastguard Worker }
2978*5e7646d2SAndroid Build Coastguard Worker 
2979*5e7646d2SAndroid Build Coastguard Worker 
2980*5e7646d2SAndroid Build Coastguard Worker /*
2981*5e7646d2SAndroid Build Coastguard Worker  * 'quote_string()' - Quote a string value.
2982*5e7646d2SAndroid Build Coastguard Worker  */
2983*5e7646d2SAndroid Build Coastguard Worker 
2984*5e7646d2SAndroid Build Coastguard Worker static const char *			/* O - Quoted string */
quote_string(const char * s,char * q,size_t qsize)2985*5e7646d2SAndroid Build Coastguard Worker quote_string(const char *s,		/* I - String */
2986*5e7646d2SAndroid Build Coastguard Worker              char       *q,		/* I - Quoted string buffer */
2987*5e7646d2SAndroid Build Coastguard Worker              size_t     qsize)		/* I - Size of quoted string buffer */
2988*5e7646d2SAndroid Build Coastguard Worker {
2989*5e7646d2SAndroid Build Coastguard Worker   char	*qptr,				/* Pointer into string buffer */
2990*5e7646d2SAndroid Build Coastguard Worker 	*qend;				/* End of string buffer */
2991*5e7646d2SAndroid Build Coastguard Worker 
2992*5e7646d2SAndroid Build Coastguard Worker 
2993*5e7646d2SAndroid Build Coastguard Worker   qptr = q;
2994*5e7646d2SAndroid Build Coastguard Worker   qend = q + qsize - 5;
2995*5e7646d2SAndroid Build Coastguard Worker 
2996*5e7646d2SAndroid Build Coastguard Worker   if (qend < q)
2997*5e7646d2SAndroid Build Coastguard Worker   {
2998*5e7646d2SAndroid Build Coastguard Worker     *q = '\0';
2999*5e7646d2SAndroid Build Coastguard Worker     return (q);
3000*5e7646d2SAndroid Build Coastguard Worker   }
3001*5e7646d2SAndroid Build Coastguard Worker 
3002*5e7646d2SAndroid Build Coastguard Worker   *qptr++ = '\'';
3003*5e7646d2SAndroid Build Coastguard Worker   *qptr++ = '\"';
3004*5e7646d2SAndroid Build Coastguard Worker 
3005*5e7646d2SAndroid Build Coastguard Worker   while (*s && qptr < qend)
3006*5e7646d2SAndroid Build Coastguard Worker   {
3007*5e7646d2SAndroid Build Coastguard Worker     if (*s == '\\' || *s == '\"' || *s == '\'')
3008*5e7646d2SAndroid Build Coastguard Worker     {
3009*5e7646d2SAndroid Build Coastguard Worker       if (qptr < (qend - 4))
3010*5e7646d2SAndroid Build Coastguard Worker       {
3011*5e7646d2SAndroid Build Coastguard Worker 	*qptr++ = '\\';
3012*5e7646d2SAndroid Build Coastguard Worker 	*qptr++ = '\\';
3013*5e7646d2SAndroid Build Coastguard Worker 	*qptr++ = '\\';
3014*5e7646d2SAndroid Build Coastguard Worker       }
3015*5e7646d2SAndroid Build Coastguard Worker       else
3016*5e7646d2SAndroid Build Coastguard Worker         break;
3017*5e7646d2SAndroid Build Coastguard Worker     }
3018*5e7646d2SAndroid Build Coastguard Worker 
3019*5e7646d2SAndroid Build Coastguard Worker     *qptr++ = *s++;
3020*5e7646d2SAndroid Build Coastguard Worker   }
3021*5e7646d2SAndroid Build Coastguard Worker 
3022*5e7646d2SAndroid Build Coastguard Worker   *qptr++ = '\"';
3023*5e7646d2SAndroid Build Coastguard Worker   *qptr++ = '\'';
3024*5e7646d2SAndroid Build Coastguard Worker   *qptr   = '\0';
3025*5e7646d2SAndroid Build Coastguard Worker 
3026*5e7646d2SAndroid Build Coastguard Worker   return (q);
3027*5e7646d2SAndroid Build Coastguard Worker }
3028*5e7646d2SAndroid Build Coastguard Worker 
3029*5e7646d2SAndroid Build Coastguard Worker 
3030*5e7646d2SAndroid Build Coastguard Worker /*
3031*5e7646d2SAndroid Build Coastguard Worker  * 'report_attr()' - Report an IPP attribute value.
3032*5e7646d2SAndroid Build Coastguard Worker  */
3033*5e7646d2SAndroid Build Coastguard Worker 
3034*5e7646d2SAndroid Build Coastguard Worker static void
report_attr(ipp_attribute_t * attr)3035*5e7646d2SAndroid Build Coastguard Worker report_attr(ipp_attribute_t *attr)	/* I - Attribute */
3036*5e7646d2SAndroid Build Coastguard Worker {
3037*5e7646d2SAndroid Build Coastguard Worker   int		i;			/* Looping var */
3038*5e7646d2SAndroid Build Coastguard Worker   char		value[1024],		/* Value string */
3039*5e7646d2SAndroid Build Coastguard Worker 		*valptr;		/* Pointer into value string */
3040*5e7646d2SAndroid Build Coastguard Worker   const char	*cached;		/* Cached attribute */
3041*5e7646d2SAndroid Build Coastguard Worker 
3042*5e7646d2SAndroid Build Coastguard Worker 
3043*5e7646d2SAndroid Build Coastguard Worker  /*
3044*5e7646d2SAndroid Build Coastguard Worker   * Convert the attribute values into quoted strings...
3045*5e7646d2SAndroid Build Coastguard Worker   */
3046*5e7646d2SAndroid Build Coastguard Worker 
3047*5e7646d2SAndroid Build Coastguard Worker   for (i = 0, valptr = value;
3048*5e7646d2SAndroid Build Coastguard Worker        i < attr->num_values && valptr < (value + sizeof(value) - 10);
3049*5e7646d2SAndroid Build Coastguard Worker        i ++)
3050*5e7646d2SAndroid Build Coastguard Worker   {
3051*5e7646d2SAndroid Build Coastguard Worker     if (i > 0)
3052*5e7646d2SAndroid Build Coastguard Worker       *valptr++ = ',';
3053*5e7646d2SAndroid Build Coastguard Worker 
3054*5e7646d2SAndroid Build Coastguard Worker     switch (attr->value_tag)
3055*5e7646d2SAndroid Build Coastguard Worker     {
3056*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_INTEGER :
3057*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_ENUM :
3058*5e7646d2SAndroid Build Coastguard Worker           snprintf(valptr, sizeof(value) - (size_t)(valptr - value), "%d", attr->values[i].integer);
3059*5e7646d2SAndroid Build Coastguard Worker 	  valptr += strlen(valptr);
3060*5e7646d2SAndroid Build Coastguard Worker 	  break;
3061*5e7646d2SAndroid Build Coastguard Worker 
3062*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_TEXT :
3063*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_NAME :
3064*5e7646d2SAndroid Build Coastguard Worker       case IPP_TAG_KEYWORD :
3065*5e7646d2SAndroid Build Coastguard Worker           quote_string(attr->values[i].string.text, valptr, (size_t)(value + sizeof(value) - valptr));
3066*5e7646d2SAndroid Build Coastguard Worker           valptr += strlen(valptr);
3067*5e7646d2SAndroid Build Coastguard Worker           break;
3068*5e7646d2SAndroid Build Coastguard Worker 
3069*5e7646d2SAndroid Build Coastguard Worker       default :
3070*5e7646d2SAndroid Build Coastguard Worker          /*
3071*5e7646d2SAndroid Build Coastguard Worker 	  * Unsupported value type...
3072*5e7646d2SAndroid Build Coastguard Worker 	  */
3073*5e7646d2SAndroid Build Coastguard Worker 
3074*5e7646d2SAndroid Build Coastguard Worker           return;
3075*5e7646d2SAndroid Build Coastguard Worker     }
3076*5e7646d2SAndroid Build Coastguard Worker   }
3077*5e7646d2SAndroid Build Coastguard Worker 
3078*5e7646d2SAndroid Build Coastguard Worker   *valptr = '\0';
3079*5e7646d2SAndroid Build Coastguard Worker 
3080*5e7646d2SAndroid Build Coastguard Worker   _cupsMutexLock(&report_mutex);
3081*5e7646d2SAndroid Build Coastguard Worker 
3082*5e7646d2SAndroid Build Coastguard Worker   if ((cached = cupsGetOption(attr->name, num_attr_cache,
3083*5e7646d2SAndroid Build Coastguard Worker                               attr_cache)) == NULL || strcmp(cached, value))
3084*5e7646d2SAndroid Build Coastguard Worker   {
3085*5e7646d2SAndroid Build Coastguard Worker    /*
3086*5e7646d2SAndroid Build Coastguard Worker     * Tell the scheduler about the new values...
3087*5e7646d2SAndroid Build Coastguard Worker     */
3088*5e7646d2SAndroid Build Coastguard Worker 
3089*5e7646d2SAndroid Build Coastguard Worker     num_attr_cache = cupsAddOption(attr->name, value, num_attr_cache,
3090*5e7646d2SAndroid Build Coastguard Worker                                    &attr_cache);
3091*5e7646d2SAndroid Build Coastguard Worker     fprintf(stderr, "ATTR: %s=%s\n", attr->name, value);
3092*5e7646d2SAndroid Build Coastguard Worker   }
3093*5e7646d2SAndroid Build Coastguard Worker 
3094*5e7646d2SAndroid Build Coastguard Worker   _cupsMutexUnlock(&report_mutex);
3095*5e7646d2SAndroid Build Coastguard Worker }
3096*5e7646d2SAndroid Build Coastguard Worker 
3097*5e7646d2SAndroid Build Coastguard Worker 
3098*5e7646d2SAndroid Build Coastguard Worker /*
3099*5e7646d2SAndroid Build Coastguard Worker  * 'report_printer_state()' - Report the printer state.
3100*5e7646d2SAndroid Build Coastguard Worker  */
3101*5e7646d2SAndroid Build Coastguard Worker 
3102*5e7646d2SAndroid Build Coastguard Worker static void
report_printer_state(ipp_t * ipp)3103*5e7646d2SAndroid Build Coastguard Worker report_printer_state(ipp_t *ipp)	/* I - IPP response */
3104*5e7646d2SAndroid Build Coastguard Worker {
3105*5e7646d2SAndroid Build Coastguard Worker   ipp_attribute_t	*pa,		/* printer-alert */
3106*5e7646d2SAndroid Build Coastguard Worker 			*pam,		/* printer-alert-message */
3107*5e7646d2SAndroid Build Coastguard Worker 			*pmja,		/* printer-mandatory-job-attributes */
3108*5e7646d2SAndroid Build Coastguard Worker 			*psm,		/* printer-state-message */
3109*5e7646d2SAndroid Build Coastguard Worker 			*reasons,	/* printer-state-reasons */
3110*5e7646d2SAndroid Build Coastguard Worker 			*marker;	/* marker-* attributes */
3111*5e7646d2SAndroid Build Coastguard Worker   char			value[1024],	/* State/message string */
3112*5e7646d2SAndroid Build Coastguard Worker 			*valptr;	/* Pointer into string */
3113*5e7646d2SAndroid Build Coastguard Worker   static int		ipp_supplies = -1;
3114*5e7646d2SAndroid Build Coastguard Worker 					/* Report supply levels? */
3115*5e7646d2SAndroid Build Coastguard Worker 
3116*5e7646d2SAndroid Build Coastguard Worker 
3117*5e7646d2SAndroid Build Coastguard Worker  /*
3118*5e7646d2SAndroid Build Coastguard Worker   * Report alerts and messages...
3119*5e7646d2SAndroid Build Coastguard Worker   */
3120*5e7646d2SAndroid Build Coastguard Worker 
3121*5e7646d2SAndroid Build Coastguard Worker   if ((pa = ippFindAttribute(ipp, "printer-alert", IPP_TAG_STRING)) != NULL)
3122*5e7646d2SAndroid Build Coastguard Worker     report_attr(pa);
3123*5e7646d2SAndroid Build Coastguard Worker 
3124*5e7646d2SAndroid Build Coastguard Worker   if ((pam = ippFindAttribute(ipp, "printer-alert-message",
3125*5e7646d2SAndroid Build Coastguard Worker                               IPP_TAG_TEXT)) != NULL)
3126*5e7646d2SAndroid Build Coastguard Worker     report_attr(pam);
3127*5e7646d2SAndroid Build Coastguard Worker 
3128*5e7646d2SAndroid Build Coastguard Worker   if ((pmja = ippFindAttribute(ipp, "printer-mandatory-job-attributes", IPP_TAG_KEYWORD)) != NULL)
3129*5e7646d2SAndroid Build Coastguard Worker   {
3130*5e7646d2SAndroid Build Coastguard Worker     int	i,				/* Looping var */
3131*5e7646d2SAndroid Build Coastguard Worker 	count = ippGetCount(pmja);	/* Number of values */
3132*5e7646d2SAndroid Build Coastguard Worker 
3133*5e7646d2SAndroid Build Coastguard Worker     for (i = 0, valptr = value; i < count; i ++, valptr += strlen(valptr))
3134*5e7646d2SAndroid Build Coastguard Worker     {
3135*5e7646d2SAndroid Build Coastguard Worker       if (i)
3136*5e7646d2SAndroid Build Coastguard Worker         snprintf(valptr, sizeof(value) - (size_t)(valptr - value), " %s", ippGetString(pmja, i, NULL));
3137*5e7646d2SAndroid Build Coastguard Worker       else
3138*5e7646d2SAndroid Build Coastguard Worker         strlcpy(value, ippGetString(pmja, i, NULL), sizeof(value));
3139*5e7646d2SAndroid Build Coastguard Worker     }
3140*5e7646d2SAndroid Build Coastguard Worker 
3141*5e7646d2SAndroid Build Coastguard Worker     if (strcmp(value, mandatory_attrs))
3142*5e7646d2SAndroid Build Coastguard Worker     {
3143*5e7646d2SAndroid Build Coastguard Worker       strlcpy(mandatory_attrs, value, sizeof(mandatory_attrs));
3144*5e7646d2SAndroid Build Coastguard Worker       fprintf(stderr, "PPD: cupsMandatory=\"%s\"\n", value);
3145*5e7646d2SAndroid Build Coastguard Worker     }
3146*5e7646d2SAndroid Build Coastguard Worker   }
3147*5e7646d2SAndroid Build Coastguard Worker 
3148*5e7646d2SAndroid Build Coastguard Worker   if ((psm = ippFindAttribute(ipp, "printer-state-message",
3149*5e7646d2SAndroid Build Coastguard Worker                               IPP_TAG_TEXT)) != NULL)
3150*5e7646d2SAndroid Build Coastguard Worker   {
3151*5e7646d2SAndroid Build Coastguard Worker     char	*ptr;			/* Pointer into message */
3152*5e7646d2SAndroid Build Coastguard Worker 
3153*5e7646d2SAndroid Build Coastguard Worker 
3154*5e7646d2SAndroid Build Coastguard Worker     strlcpy(value, "INFO: ", sizeof(value));
3155*5e7646d2SAndroid Build Coastguard Worker     for (ptr = psm->values[0].string.text, valptr = value + 6;
3156*5e7646d2SAndroid Build Coastguard Worker          *ptr && valptr < (value + sizeof(value) - 6);
3157*5e7646d2SAndroid Build Coastguard Worker 	 ptr ++)
3158*5e7646d2SAndroid Build Coastguard Worker     {
3159*5e7646d2SAndroid Build Coastguard Worker       if (*ptr < ' ' && *ptr > 0 && *ptr != '\t')
3160*5e7646d2SAndroid Build Coastguard Worker       {
3161*5e7646d2SAndroid Build Coastguard Worker        /*
3162*5e7646d2SAndroid Build Coastguard Worker         * Substitute "<XX>" for the control character...
3163*5e7646d2SAndroid Build Coastguard Worker 	*/
3164*5e7646d2SAndroid Build Coastguard Worker 
3165*5e7646d2SAndroid Build Coastguard Worker         snprintf(valptr, sizeof(value) - (size_t)(valptr - value), "<%02X>", *ptr);
3166*5e7646d2SAndroid Build Coastguard Worker 	valptr += 4;
3167*5e7646d2SAndroid Build Coastguard Worker       }
3168*5e7646d2SAndroid Build Coastguard Worker       else
3169*5e7646d2SAndroid Build Coastguard Worker         *valptr++ = *ptr;
3170*5e7646d2SAndroid Build Coastguard Worker     }
3171*5e7646d2SAndroid Build Coastguard Worker 
3172*5e7646d2SAndroid Build Coastguard Worker     *valptr++ = '\n';
3173*5e7646d2SAndroid Build Coastguard Worker     *valptr   = '\0';
3174*5e7646d2SAndroid Build Coastguard Worker 
3175*5e7646d2SAndroid Build Coastguard Worker     fputs(value, stderr);
3176*5e7646d2SAndroid Build Coastguard Worker   }
3177*5e7646d2SAndroid Build Coastguard Worker 
3178*5e7646d2SAndroid Build Coastguard Worker  /*
3179*5e7646d2SAndroid Build Coastguard Worker   * Now report printer-state-reasons, filtering out some of the reasons we never
3180*5e7646d2SAndroid Build Coastguard Worker   * want to set...
3181*5e7646d2SAndroid Build Coastguard Worker   */
3182*5e7646d2SAndroid Build Coastguard Worker 
3183*5e7646d2SAndroid Build Coastguard Worker   if ((reasons = ippFindAttribute(ipp, "printer-state-reasons",
3184*5e7646d2SAndroid Build Coastguard Worker                                   IPP_TAG_KEYWORD)) == NULL)
3185*5e7646d2SAndroid Build Coastguard Worker     return;
3186*5e7646d2SAndroid Build Coastguard Worker 
3187*5e7646d2SAndroid Build Coastguard Worker   update_reasons(reasons, NULL);
3188*5e7646d2SAndroid Build Coastguard Worker 
3189*5e7646d2SAndroid Build Coastguard Worker  /*
3190*5e7646d2SAndroid Build Coastguard Worker   * Relay the current marker-* attribute values...
3191*5e7646d2SAndroid Build Coastguard Worker   */
3192*5e7646d2SAndroid Build Coastguard Worker 
3193*5e7646d2SAndroid Build Coastguard Worker   if (ipp_supplies < 0)
3194*5e7646d2SAndroid Build Coastguard Worker   {
3195*5e7646d2SAndroid Build Coastguard Worker     ppd_file_t	*ppd;			/* PPD file */
3196*5e7646d2SAndroid Build Coastguard Worker     ppd_attr_t	*ppdattr;		/* Attribute in PPD file */
3197*5e7646d2SAndroid Build Coastguard Worker 
3198*5e7646d2SAndroid Build Coastguard Worker     if ((ppd = ppdOpenFile(getenv("PPD"))) != NULL &&
3199*5e7646d2SAndroid Build Coastguard Worker         (ppdattr = ppdFindAttr(ppd, "cupsIPPSupplies", NULL)) != NULL &&
3200*5e7646d2SAndroid Build Coastguard Worker         ppdattr->value && _cups_strcasecmp(ppdattr->value, "true"))
3201*5e7646d2SAndroid Build Coastguard Worker       ipp_supplies = 0;
3202*5e7646d2SAndroid Build Coastguard Worker     else
3203*5e7646d2SAndroid Build Coastguard Worker       ipp_supplies = 1;
3204*5e7646d2SAndroid Build Coastguard Worker 
3205*5e7646d2SAndroid Build Coastguard Worker     ppdClose(ppd);
3206*5e7646d2SAndroid Build Coastguard Worker   }
3207*5e7646d2SAndroid Build Coastguard Worker 
3208*5e7646d2SAndroid Build Coastguard Worker   if (ipp_supplies > 0)
3209*5e7646d2SAndroid Build Coastguard Worker   {
3210*5e7646d2SAndroid Build Coastguard Worker     if ((marker = ippFindAttribute(ipp, "marker-colors", IPP_TAG_NAME)) != NULL)
3211*5e7646d2SAndroid Build Coastguard Worker       report_attr(marker);
3212*5e7646d2SAndroid Build Coastguard Worker     if ((marker = ippFindAttribute(ipp, "marker-high-levels",
3213*5e7646d2SAndroid Build Coastguard Worker                                    IPP_TAG_INTEGER)) != NULL)
3214*5e7646d2SAndroid Build Coastguard Worker       report_attr(marker);
3215*5e7646d2SAndroid Build Coastguard Worker     if ((marker = ippFindAttribute(ipp, "marker-levels",
3216*5e7646d2SAndroid Build Coastguard Worker                                    IPP_TAG_INTEGER)) != NULL)
3217*5e7646d2SAndroid Build Coastguard Worker       report_attr(marker);
3218*5e7646d2SAndroid Build Coastguard Worker     if ((marker = ippFindAttribute(ipp, "marker-low-levels",
3219*5e7646d2SAndroid Build Coastguard Worker                                    IPP_TAG_INTEGER)) != NULL)
3220*5e7646d2SAndroid Build Coastguard Worker       report_attr(marker);
3221*5e7646d2SAndroid Build Coastguard Worker     if ((marker = ippFindAttribute(ipp, "marker-message",
3222*5e7646d2SAndroid Build Coastguard Worker                                    IPP_TAG_TEXT)) != NULL)
3223*5e7646d2SAndroid Build Coastguard Worker       report_attr(marker);
3224*5e7646d2SAndroid Build Coastguard Worker     if ((marker = ippFindAttribute(ipp, "marker-names", IPP_TAG_NAME)) != NULL)
3225*5e7646d2SAndroid Build Coastguard Worker       report_attr(marker);
3226*5e7646d2SAndroid Build Coastguard Worker     if ((marker = ippFindAttribute(ipp, "marker-types",
3227*5e7646d2SAndroid Build Coastguard Worker                                    IPP_TAG_KEYWORD)) != NULL)
3228*5e7646d2SAndroid Build Coastguard Worker       report_attr(marker);
3229*5e7646d2SAndroid Build Coastguard Worker   }
3230*5e7646d2SAndroid Build Coastguard Worker }
3231*5e7646d2SAndroid Build Coastguard Worker 
3232*5e7646d2SAndroid Build Coastguard Worker 
3233*5e7646d2SAndroid Build Coastguard Worker #if defined(HAVE_GSSAPI) && defined(HAVE_XPC)
3234*5e7646d2SAndroid Build Coastguard Worker /*
3235*5e7646d2SAndroid Build Coastguard Worker  * 'run_as_user()' - Run the IPP backend as the printing user.
3236*5e7646d2SAndroid Build Coastguard Worker  *
3237*5e7646d2SAndroid Build Coastguard Worker  * This function uses an XPC-based user agent to run the backend as the printing
3238*5e7646d2SAndroid Build Coastguard Worker  * user. We need to do this in order to have access to the user's Kerberos
3239*5e7646d2SAndroid Build Coastguard Worker  * credentials.
3240*5e7646d2SAndroid Build Coastguard Worker  */
3241*5e7646d2SAndroid Build Coastguard Worker 
3242*5e7646d2SAndroid Build Coastguard Worker static int				/* O - Exit status */
run_as_user(char * argv[],uid_t uid,const char * device_uri,int fd)3243*5e7646d2SAndroid Build Coastguard Worker run_as_user(char       *argv[],		/* I - Command-line arguments */
3244*5e7646d2SAndroid Build Coastguard Worker 	    uid_t      uid,		/* I - User ID */
3245*5e7646d2SAndroid Build Coastguard Worker 	    const char *device_uri,	/* I - Device URI */
3246*5e7646d2SAndroid Build Coastguard Worker 	    int        fd)		/* I - File to print */
3247*5e7646d2SAndroid Build Coastguard Worker {
3248*5e7646d2SAndroid Build Coastguard Worker   const char		*auth_negotiate,/* AUTH_NEGOTIATE env var */
3249*5e7646d2SAndroid Build Coastguard Worker 			*content_type;	/* [FINAL_]CONTENT_TYPE env vars */
3250*5e7646d2SAndroid Build Coastguard Worker   xpc_connection_t	conn;		/* Connection to XPC service */
3251*5e7646d2SAndroid Build Coastguard Worker   xpc_object_t		request;	/* Request message dictionary */
3252*5e7646d2SAndroid Build Coastguard Worker   __block xpc_object_t	response;	/* Response message dictionary */
3253*5e7646d2SAndroid Build Coastguard Worker   dispatch_semaphore_t	sem;		/* Semaphore for waiting for response */
3254*5e7646d2SAndroid Build Coastguard Worker   int			status = CUPS_BACKEND_FAILED;
3255*5e7646d2SAndroid Build Coastguard Worker 					/* Status of request */
3256*5e7646d2SAndroid Build Coastguard Worker 
3257*5e7646d2SAndroid Build Coastguard Worker 
3258*5e7646d2SAndroid Build Coastguard Worker   fprintf(stderr, "DEBUG: Running IPP backend as UID %d.\n", (int)uid);
3259*5e7646d2SAndroid Build Coastguard Worker 
3260*5e7646d2SAndroid Build Coastguard Worker  /*
3261*5e7646d2SAndroid Build Coastguard Worker   * Connect to the user agent for the specified UID...
3262*5e7646d2SAndroid Build Coastguard Worker   */
3263*5e7646d2SAndroid Build Coastguard Worker 
3264*5e7646d2SAndroid Build Coastguard Worker   conn = xpc_connection_create_mach_service(kPMPrintUIToolAgent,
3265*5e7646d2SAndroid Build Coastguard Worker                                             dispatch_get_global_queue(0, 0), 0);
3266*5e7646d2SAndroid Build Coastguard Worker   if (!conn)
3267*5e7646d2SAndroid Build Coastguard Worker   {
3268*5e7646d2SAndroid Build Coastguard Worker     _cupsLangPrintFilter(stderr, "ERROR",
3269*5e7646d2SAndroid Build Coastguard Worker                          _("Unable to start backend process."));
3270*5e7646d2SAndroid Build Coastguard Worker     fputs("DEBUG: Unable to create connection to agent.\n", stderr);
3271*5e7646d2SAndroid Build Coastguard Worker     goto cleanup;
3272*5e7646d2SAndroid Build Coastguard Worker   }
3273*5e7646d2SAndroid Build Coastguard Worker 
3274*5e7646d2SAndroid Build Coastguard Worker   xpc_connection_set_event_handler(conn,
3275*5e7646d2SAndroid Build Coastguard Worker                                    ^(xpc_object_t event)
3276*5e7646d2SAndroid Build Coastguard Worker 				   {
3277*5e7646d2SAndroid Build Coastguard Worker 				     xpc_type_t messageType = xpc_get_type(event);
3278*5e7646d2SAndroid Build Coastguard Worker 
3279*5e7646d2SAndroid Build Coastguard Worker 				     if (messageType == XPC_TYPE_ERROR)
3280*5e7646d2SAndroid Build Coastguard Worker 				     {
3281*5e7646d2SAndroid Build Coastguard Worker 				       if (event == XPC_ERROR_CONNECTION_INTERRUPTED)
3282*5e7646d2SAndroid Build Coastguard Worker 					 fprintf(stderr, "DEBUG: Interrupted connection to service %s.\n",
3283*5e7646d2SAndroid Build Coastguard Worker 					         xpc_connection_get_name(conn));
3284*5e7646d2SAndroid Build Coastguard Worker 				       else if (event == XPC_ERROR_CONNECTION_INVALID)
3285*5e7646d2SAndroid Build Coastguard Worker 				         fprintf(stderr, "DEBUG: Connection invalid for service %s.\n",
3286*5e7646d2SAndroid Build Coastguard Worker 					         xpc_connection_get_name(conn));
3287*5e7646d2SAndroid Build Coastguard Worker 				       else
3288*5e7646d2SAndroid Build Coastguard Worker 				         fprintf(stderr, "DEBUG: Unxpected error for service %s: %s\n",
3289*5e7646d2SAndroid Build Coastguard Worker 					         xpc_connection_get_name(conn),
3290*5e7646d2SAndroid Build Coastguard Worker 						 xpc_dictionary_get_string(event, XPC_ERROR_KEY_DESCRIPTION));
3291*5e7646d2SAndroid Build Coastguard Worker 				     }
3292*5e7646d2SAndroid Build Coastguard Worker 				   });
3293*5e7646d2SAndroid Build Coastguard Worker   xpc_connection_set_target_uid(conn, uid);
3294*5e7646d2SAndroid Build Coastguard Worker   xpc_connection_resume(conn);
3295*5e7646d2SAndroid Build Coastguard Worker 
3296*5e7646d2SAndroid Build Coastguard Worker  /*
3297*5e7646d2SAndroid Build Coastguard Worker   * Try starting the backend...
3298*5e7646d2SAndroid Build Coastguard Worker   */
3299*5e7646d2SAndroid Build Coastguard Worker 
3300*5e7646d2SAndroid Build Coastguard Worker   request = xpc_dictionary_create(NULL, NULL, 0);
3301*5e7646d2SAndroid Build Coastguard Worker   xpc_dictionary_set_int64(request, "command", kPMStartJob);
3302*5e7646d2SAndroid Build Coastguard Worker   xpc_dictionary_set_string(request, "device-uri", device_uri);
3303*5e7646d2SAndroid Build Coastguard Worker   xpc_dictionary_set_string(request, "job-id", argv[1]);
3304*5e7646d2SAndroid Build Coastguard Worker   xpc_dictionary_set_string(request, "user", argv[2]);
3305*5e7646d2SAndroid Build Coastguard Worker   xpc_dictionary_set_string(request, "title", argv[3]);
3306*5e7646d2SAndroid Build Coastguard Worker   xpc_dictionary_set_string(request, "copies", argv[4]);
3307*5e7646d2SAndroid Build Coastguard Worker   xpc_dictionary_set_string(request, "options", argv[5]);
3308*5e7646d2SAndroid Build Coastguard Worker   xpc_dictionary_set_string(request, "auth-info-required",
3309*5e7646d2SAndroid Build Coastguard Worker                             getenv("AUTH_INFO_REQUIRED"));
3310*5e7646d2SAndroid Build Coastguard Worker   if ((auth_negotiate = getenv("AUTH_NEGOTIATE")) != NULL)
3311*5e7646d2SAndroid Build Coastguard Worker     xpc_dictionary_set_string(request, "auth-negotiate", auth_negotiate);
3312*5e7646d2SAndroid Build Coastguard Worker   if ((content_type = getenv("CONTENT_TYPE")) != NULL)
3313*5e7646d2SAndroid Build Coastguard Worker     xpc_dictionary_set_string(request, "content-type", content_type);
3314*5e7646d2SAndroid Build Coastguard Worker   if ((content_type = getenv("FINAL_CONTENT_TYPE")) != NULL)
3315*5e7646d2SAndroid Build Coastguard Worker     xpc_dictionary_set_string(request, "final-content-type", content_type);
3316*5e7646d2SAndroid Build Coastguard Worker   xpc_dictionary_set_fd(request, "stdin", fd);
3317*5e7646d2SAndroid Build Coastguard Worker   xpc_dictionary_set_fd(request, "stderr", 2);
3318*5e7646d2SAndroid Build Coastguard Worker   xpc_dictionary_set_fd(request, "side-channel", CUPS_SC_FD);
3319*5e7646d2SAndroid Build Coastguard Worker 
3320*5e7646d2SAndroid Build Coastguard Worker   sem      = dispatch_semaphore_create(0);
3321*5e7646d2SAndroid Build Coastguard Worker   response = NULL;
3322*5e7646d2SAndroid Build Coastguard Worker 
3323*5e7646d2SAndroid Build Coastguard Worker   xpc_connection_send_message_with_reply(conn, request,
3324*5e7646d2SAndroid Build Coastguard Worker                                          dispatch_get_global_queue(0,0),
3325*5e7646d2SAndroid Build Coastguard Worker 					 ^(xpc_object_t reply)
3326*5e7646d2SAndroid Build Coastguard Worker 					 {
3327*5e7646d2SAndroid Build Coastguard Worker 					   /* Save the response and wake up */
3328*5e7646d2SAndroid Build Coastguard Worker 					   if (xpc_get_type(reply)
3329*5e7646d2SAndroid Build Coastguard Worker 					           == XPC_TYPE_DICTIONARY)
3330*5e7646d2SAndroid Build Coastguard Worker 					     response = xpc_retain(reply);
3331*5e7646d2SAndroid Build Coastguard Worker 
3332*5e7646d2SAndroid Build Coastguard Worker 					   dispatch_semaphore_signal(sem);
3333*5e7646d2SAndroid Build Coastguard Worker 					 });
3334*5e7646d2SAndroid Build Coastguard Worker 
3335*5e7646d2SAndroid Build Coastguard Worker   dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
3336*5e7646d2SAndroid Build Coastguard Worker   xpc_release(request);
3337*5e7646d2SAndroid Build Coastguard Worker   dispatch_release(sem);
3338*5e7646d2SAndroid Build Coastguard Worker 
3339*5e7646d2SAndroid Build Coastguard Worker   if (response)
3340*5e7646d2SAndroid Build Coastguard Worker   {
3341*5e7646d2SAndroid Build Coastguard Worker     child_pid = (pid_t)xpc_dictionary_get_int64(response, "child-pid");
3342*5e7646d2SAndroid Build Coastguard Worker 
3343*5e7646d2SAndroid Build Coastguard Worker     xpc_release(response);
3344*5e7646d2SAndroid Build Coastguard Worker 
3345*5e7646d2SAndroid Build Coastguard Worker     if (child_pid)
3346*5e7646d2SAndroid Build Coastguard Worker       fprintf(stderr, "DEBUG: Child PID=%d.\n", (int)child_pid);
3347*5e7646d2SAndroid Build Coastguard Worker     else
3348*5e7646d2SAndroid Build Coastguard Worker     {
3349*5e7646d2SAndroid Build Coastguard Worker       _cupsLangPrintFilter(stderr, "ERROR",
3350*5e7646d2SAndroid Build Coastguard Worker                            _("Unable to start backend process."));
3351*5e7646d2SAndroid Build Coastguard Worker       fputs("DEBUG: No child PID.\n", stderr);
3352*5e7646d2SAndroid Build Coastguard Worker       goto cleanup;
3353*5e7646d2SAndroid Build Coastguard Worker     }
3354*5e7646d2SAndroid Build Coastguard Worker   }
3355*5e7646d2SAndroid Build Coastguard Worker   else
3356*5e7646d2SAndroid Build Coastguard Worker   {
3357*5e7646d2SAndroid Build Coastguard Worker     _cupsLangPrintFilter(stderr, "ERROR",
3358*5e7646d2SAndroid Build Coastguard Worker                          _("Unable to start backend process."));
3359*5e7646d2SAndroid Build Coastguard Worker     fputs("DEBUG: No reply from agent.\n", stderr);
3360*5e7646d2SAndroid Build Coastguard Worker     goto cleanup;
3361*5e7646d2SAndroid Build Coastguard Worker   }
3362*5e7646d2SAndroid Build Coastguard Worker 
3363*5e7646d2SAndroid Build Coastguard Worker  /*
3364*5e7646d2SAndroid Build Coastguard Worker   * Then wait for the backend to finish...
3365*5e7646d2SAndroid Build Coastguard Worker   */
3366*5e7646d2SAndroid Build Coastguard Worker 
3367*5e7646d2SAndroid Build Coastguard Worker   request = xpc_dictionary_create(NULL, NULL, 0);
3368*5e7646d2SAndroid Build Coastguard Worker   xpc_dictionary_set_int64(request, "command", kPMWaitForJob);
3369*5e7646d2SAndroid Build Coastguard Worker   xpc_dictionary_set_fd(request, "stderr", 2);
3370*5e7646d2SAndroid Build Coastguard Worker 
3371*5e7646d2SAndroid Build Coastguard Worker   sem      = dispatch_semaphore_create(0);
3372*5e7646d2SAndroid Build Coastguard Worker   response = NULL;
3373*5e7646d2SAndroid Build Coastguard Worker 
3374*5e7646d2SAndroid Build Coastguard Worker   xpc_connection_send_message_with_reply(conn, request,
3375*5e7646d2SAndroid Build Coastguard Worker                                          dispatch_get_global_queue(0,0),
3376*5e7646d2SAndroid Build Coastguard Worker 					 ^(xpc_object_t reply)
3377*5e7646d2SAndroid Build Coastguard Worker 					 {
3378*5e7646d2SAndroid Build Coastguard Worker 					   /* Save the response and wake up */
3379*5e7646d2SAndroid Build Coastguard Worker 					   if (xpc_get_type(reply)
3380*5e7646d2SAndroid Build Coastguard Worker 					           == XPC_TYPE_DICTIONARY)
3381*5e7646d2SAndroid Build Coastguard Worker 					     response = xpc_retain(reply);
3382*5e7646d2SAndroid Build Coastguard Worker 
3383*5e7646d2SAndroid Build Coastguard Worker 					   dispatch_semaphore_signal(sem);
3384*5e7646d2SAndroid Build Coastguard Worker 					 });
3385*5e7646d2SAndroid Build Coastguard Worker 
3386*5e7646d2SAndroid Build Coastguard Worker   dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
3387*5e7646d2SAndroid Build Coastguard Worker   xpc_release(request);
3388*5e7646d2SAndroid Build Coastguard Worker   dispatch_release(sem);
3389*5e7646d2SAndroid Build Coastguard Worker 
3390*5e7646d2SAndroid Build Coastguard Worker   if (response)
3391*5e7646d2SAndroid Build Coastguard Worker   {
3392*5e7646d2SAndroid Build Coastguard Worker     status = (int)xpc_dictionary_get_int64(response, "status");
3393*5e7646d2SAndroid Build Coastguard Worker 
3394*5e7646d2SAndroid Build Coastguard Worker     if (status == SIGTERM || status == SIGKILL || status == SIGPIPE)
3395*5e7646d2SAndroid Build Coastguard Worker     {
3396*5e7646d2SAndroid Build Coastguard Worker       fprintf(stderr, "DEBUG: Child terminated on signal %d.\n", status);
3397*5e7646d2SAndroid Build Coastguard Worker       status = CUPS_BACKEND_FAILED;
3398*5e7646d2SAndroid Build Coastguard Worker     }
3399*5e7646d2SAndroid Build Coastguard Worker     else if (WIFSIGNALED(status))
3400*5e7646d2SAndroid Build Coastguard Worker     {
3401*5e7646d2SAndroid Build Coastguard Worker       fprintf(stderr, "DEBUG: Child crashed on signal %d.\n", status);
3402*5e7646d2SAndroid Build Coastguard Worker       status = CUPS_BACKEND_STOP;
3403*5e7646d2SAndroid Build Coastguard Worker     }
3404*5e7646d2SAndroid Build Coastguard Worker     else if (WIFEXITED(status))
3405*5e7646d2SAndroid Build Coastguard Worker     {
3406*5e7646d2SAndroid Build Coastguard Worker       status = WEXITSTATUS(status);
3407*5e7646d2SAndroid Build Coastguard Worker       fprintf(stderr, "DEBUG: Child exited with status %d.\n", status);
3408*5e7646d2SAndroid Build Coastguard Worker     }
3409*5e7646d2SAndroid Build Coastguard Worker 
3410*5e7646d2SAndroid Build Coastguard Worker     xpc_release(response);
3411*5e7646d2SAndroid Build Coastguard Worker   }
3412*5e7646d2SAndroid Build Coastguard Worker   else
3413*5e7646d2SAndroid Build Coastguard Worker     _cupsLangPrintFilter(stderr, "ERROR",
3414*5e7646d2SAndroid Build Coastguard Worker                          _("Unable to get backend exit status."));
3415*5e7646d2SAndroid Build Coastguard Worker 
3416*5e7646d2SAndroid Build Coastguard Worker   cleanup:
3417*5e7646d2SAndroid Build Coastguard Worker 
3418*5e7646d2SAndroid Build Coastguard Worker   if (conn)
3419*5e7646d2SAndroid Build Coastguard Worker   {
3420*5e7646d2SAndroid Build Coastguard Worker     xpc_connection_cancel(conn);
3421*5e7646d2SAndroid Build Coastguard Worker     xpc_release(conn);
3422*5e7646d2SAndroid Build Coastguard Worker   }
3423*5e7646d2SAndroid Build Coastguard Worker 
3424*5e7646d2SAndroid Build Coastguard Worker   return (status);
3425*5e7646d2SAndroid Build Coastguard Worker }
3426*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_GSSAPI && HAVE_XPC */
3427*5e7646d2SAndroid Build Coastguard Worker 
3428*5e7646d2SAndroid Build Coastguard Worker 
3429*5e7646d2SAndroid Build Coastguard Worker /*
3430*5e7646d2SAndroid Build Coastguard Worker  * 'sigterm_handler()' - Handle 'terminate' signals that stop the backend.
3431*5e7646d2SAndroid Build Coastguard Worker  */
3432*5e7646d2SAndroid Build Coastguard Worker 
3433*5e7646d2SAndroid Build Coastguard Worker static void
sigterm_handler(int sig)3434*5e7646d2SAndroid Build Coastguard Worker sigterm_handler(int sig)		/* I - Signal */
3435*5e7646d2SAndroid Build Coastguard Worker {
3436*5e7646d2SAndroid Build Coastguard Worker   (void)sig;	/* remove compiler warnings... */
3437*5e7646d2SAndroid Build Coastguard Worker 
3438*5e7646d2SAndroid Build Coastguard Worker   backendMessage("DEBUG: Got SIGTERM.\n");
3439*5e7646d2SAndroid Build Coastguard Worker 
3440*5e7646d2SAndroid Build Coastguard Worker #if defined(HAVE_GSSAPI) && defined(HAVE_XPC)
3441*5e7646d2SAndroid Build Coastguard Worker   if (child_pid)
3442*5e7646d2SAndroid Build Coastguard Worker   {
3443*5e7646d2SAndroid Build Coastguard Worker     kill(child_pid, sig);
3444*5e7646d2SAndroid Build Coastguard Worker     child_pid = 0;
3445*5e7646d2SAndroid Build Coastguard Worker   }
3446*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_GSSAPI && HAVE_XPC */
3447*5e7646d2SAndroid Build Coastguard Worker 
3448*5e7646d2SAndroid Build Coastguard Worker   if (!job_canceled)
3449*5e7646d2SAndroid Build Coastguard Worker   {
3450*5e7646d2SAndroid Build Coastguard Worker    /*
3451*5e7646d2SAndroid Build Coastguard Worker     * Flag that the job should be canceled...
3452*5e7646d2SAndroid Build Coastguard Worker     */
3453*5e7646d2SAndroid Build Coastguard Worker 
3454*5e7646d2SAndroid Build Coastguard Worker     backendMessage("DEBUG: sigterm_handler: job_canceled = 1.\n");
3455*5e7646d2SAndroid Build Coastguard Worker 
3456*5e7646d2SAndroid Build Coastguard Worker     job_canceled = 1;
3457*5e7646d2SAndroid Build Coastguard Worker     return;
3458*5e7646d2SAndroid Build Coastguard Worker   }
3459*5e7646d2SAndroid Build Coastguard Worker 
3460*5e7646d2SAndroid Build Coastguard Worker  /*
3461*5e7646d2SAndroid Build Coastguard Worker   * The scheduler already tried to cancel us once, now just terminate
3462*5e7646d2SAndroid Build Coastguard Worker   * after removing our temp file!
3463*5e7646d2SAndroid Build Coastguard Worker   */
3464*5e7646d2SAndroid Build Coastguard Worker 
3465*5e7646d2SAndroid Build Coastguard Worker   if (tmpfilename[0])
3466*5e7646d2SAndroid Build Coastguard Worker     unlink(tmpfilename);
3467*5e7646d2SAndroid Build Coastguard Worker 
3468*5e7646d2SAndroid Build Coastguard Worker   _exit(1);
3469*5e7646d2SAndroid Build Coastguard Worker }
3470*5e7646d2SAndroid Build Coastguard Worker 
3471*5e7646d2SAndroid Build Coastguard Worker 
3472*5e7646d2SAndroid Build Coastguard Worker /*
3473*5e7646d2SAndroid Build Coastguard Worker  * 'timeout_cb()' - Handle HTTP timeouts.
3474*5e7646d2SAndroid Build Coastguard Worker  */
3475*5e7646d2SAndroid Build Coastguard Worker 
3476*5e7646d2SAndroid Build Coastguard Worker static int				/* O - 1 to continue, 0 to cancel */
timeout_cb(http_t * http,void * user_data)3477*5e7646d2SAndroid Build Coastguard Worker timeout_cb(http_t *http,		/* I - Connection to server (unused) */
3478*5e7646d2SAndroid Build Coastguard Worker            void   *user_data)		/* I - User data (unused) */
3479*5e7646d2SAndroid Build Coastguard Worker {
3480*5e7646d2SAndroid Build Coastguard Worker   (void)http;
3481*5e7646d2SAndroid Build Coastguard Worker   (void)user_data;
3482*5e7646d2SAndroid Build Coastguard Worker 
3483*5e7646d2SAndroid Build Coastguard Worker   return (!job_canceled);
3484*5e7646d2SAndroid Build Coastguard Worker }
3485*5e7646d2SAndroid Build Coastguard Worker 
3486*5e7646d2SAndroid Build Coastguard Worker 
3487*5e7646d2SAndroid Build Coastguard Worker /*
3488*5e7646d2SAndroid Build Coastguard Worker  * 'update_reasons()' - Update the printer-state-reasons values.
3489*5e7646d2SAndroid Build Coastguard Worker  */
3490*5e7646d2SAndroid Build Coastguard Worker 
3491*5e7646d2SAndroid Build Coastguard Worker static void
update_reasons(ipp_attribute_t * attr,const char * s)3492*5e7646d2SAndroid Build Coastguard Worker update_reasons(ipp_attribute_t *attr,	/* I - printer-state-reasons or NULL */
3493*5e7646d2SAndroid Build Coastguard Worker                const char      *s)	/* I - STATE: string or NULL */
3494*5e7646d2SAndroid Build Coastguard Worker {
3495*5e7646d2SAndroid Build Coastguard Worker   char		op;			/* Add (+), remove (-), replace (\0) */
3496*5e7646d2SAndroid Build Coastguard Worker   cups_array_t	*new_reasons;		/* New reasons array */
3497*5e7646d2SAndroid Build Coastguard Worker   char		*reason,		/* Current reason */
3498*5e7646d2SAndroid Build Coastguard Worker 		add[2048],		/* Reasons added string */
3499*5e7646d2SAndroid Build Coastguard Worker 		*addptr,		/* Pointer into add string */
3500*5e7646d2SAndroid Build Coastguard Worker 		rem[2048],		/* Reasons removed string */
3501*5e7646d2SAndroid Build Coastguard Worker 		*remptr;		/* Pointer into remove string */
3502*5e7646d2SAndroid Build Coastguard Worker   const char	*addprefix,		/* Current add string prefix */
3503*5e7646d2SAndroid Build Coastguard Worker 		*remprefix;		/* Current remove string prefix */
3504*5e7646d2SAndroid Build Coastguard Worker 
3505*5e7646d2SAndroid Build Coastguard Worker 
3506*5e7646d2SAndroid Build Coastguard Worker   fprintf(stderr, "DEBUG: update_reasons(attr=%d(%s%s), s=\"%s\")\n",
3507*5e7646d2SAndroid Build Coastguard Worker 	  attr ? attr->num_values : 0, attr ? attr->values[0].string.text : "",
3508*5e7646d2SAndroid Build Coastguard Worker 	  attr && attr->num_values > 1 ? ",..." : "", s ? s : "(null)");
3509*5e7646d2SAndroid Build Coastguard Worker 
3510*5e7646d2SAndroid Build Coastguard Worker  /*
3511*5e7646d2SAndroid Build Coastguard Worker   * Create an array of new reason keyword strings...
3512*5e7646d2SAndroid Build Coastguard Worker   */
3513*5e7646d2SAndroid Build Coastguard Worker 
3514*5e7646d2SAndroid Build Coastguard Worker   if (attr)
3515*5e7646d2SAndroid Build Coastguard Worker   {
3516*5e7646d2SAndroid Build Coastguard Worker     int	i;				/* Looping var */
3517*5e7646d2SAndroid Build Coastguard Worker 
3518*5e7646d2SAndroid Build Coastguard Worker     new_reasons = cupsArrayNew((cups_array_func_t)strcmp, NULL);
3519*5e7646d2SAndroid Build Coastguard Worker     op          = '\0';
3520*5e7646d2SAndroid Build Coastguard Worker 
3521*5e7646d2SAndroid Build Coastguard Worker     for (i = 0; i < attr->num_values; i ++)
3522*5e7646d2SAndroid Build Coastguard Worker     {
3523*5e7646d2SAndroid Build Coastguard Worker       reason = attr->values[i].string.text;
3524*5e7646d2SAndroid Build Coastguard Worker 
3525*5e7646d2SAndroid Build Coastguard Worker       if (strcmp(reason, "none") &&
3526*5e7646d2SAndroid Build Coastguard Worker 	  strcmp(reason, "none-report") &&
3527*5e7646d2SAndroid Build Coastguard Worker 	  strcmp(reason, "paused") &&
3528*5e7646d2SAndroid Build Coastguard Worker 	  strncmp(reason, "spool-area-full", 15) &&
3529*5e7646d2SAndroid Build Coastguard Worker 	  strcmp(reason, "com.apple.print.recoverable-warning") &&
3530*5e7646d2SAndroid Build Coastguard Worker 	  strncmp(reason, "cups-", 5))
3531*5e7646d2SAndroid Build Coastguard Worker 	cupsArrayAdd(new_reasons, reason);
3532*5e7646d2SAndroid Build Coastguard Worker     }
3533*5e7646d2SAndroid Build Coastguard Worker   }
3534*5e7646d2SAndroid Build Coastguard Worker   else if (s)
3535*5e7646d2SAndroid Build Coastguard Worker   {
3536*5e7646d2SAndroid Build Coastguard Worker     if (*s == '+' || *s == '-')
3537*5e7646d2SAndroid Build Coastguard Worker       op = *s++;
3538*5e7646d2SAndroid Build Coastguard Worker     else
3539*5e7646d2SAndroid Build Coastguard Worker       op = '\0';
3540*5e7646d2SAndroid Build Coastguard Worker 
3541*5e7646d2SAndroid Build Coastguard Worker     new_reasons = _cupsArrayNewStrings(s, ',');
3542*5e7646d2SAndroid Build Coastguard Worker   }
3543*5e7646d2SAndroid Build Coastguard Worker   else
3544*5e7646d2SAndroid Build Coastguard Worker     return;
3545*5e7646d2SAndroid Build Coastguard Worker 
3546*5e7646d2SAndroid Build Coastguard Worker  /*
3547*5e7646d2SAndroid Build Coastguard Worker   * Compute the changes...
3548*5e7646d2SAndroid Build Coastguard Worker   */
3549*5e7646d2SAndroid Build Coastguard Worker 
3550*5e7646d2SAndroid Build Coastguard Worker   add[0]    = '\0';
3551*5e7646d2SAndroid Build Coastguard Worker   addprefix = "STATE: +";
3552*5e7646d2SAndroid Build Coastguard Worker   addptr    = add;
3553*5e7646d2SAndroid Build Coastguard Worker   rem[0]    = '\0';
3554*5e7646d2SAndroid Build Coastguard Worker   remprefix = "STATE: -";
3555*5e7646d2SAndroid Build Coastguard Worker   remptr    = rem;
3556*5e7646d2SAndroid Build Coastguard Worker 
3557*5e7646d2SAndroid Build Coastguard Worker   fprintf(stderr, "DEBUG2: op='%c', new_reasons=%d, state_reasons=%d\n",
3558*5e7646d2SAndroid Build Coastguard Worker           op ? op : ' ', cupsArrayCount(new_reasons),
3559*5e7646d2SAndroid Build Coastguard Worker 	  cupsArrayCount(state_reasons));
3560*5e7646d2SAndroid Build Coastguard Worker 
3561*5e7646d2SAndroid Build Coastguard Worker   _cupsMutexLock(&report_mutex);
3562*5e7646d2SAndroid Build Coastguard Worker 
3563*5e7646d2SAndroid Build Coastguard Worker   if (op == '+')
3564*5e7646d2SAndroid Build Coastguard Worker   {
3565*5e7646d2SAndroid Build Coastguard Worker    /*
3566*5e7646d2SAndroid Build Coastguard Worker     * Add reasons...
3567*5e7646d2SAndroid Build Coastguard Worker     */
3568*5e7646d2SAndroid Build Coastguard Worker 
3569*5e7646d2SAndroid Build Coastguard Worker     for (reason = (char *)cupsArrayFirst(new_reasons);
3570*5e7646d2SAndroid Build Coastguard Worker 	 reason;
3571*5e7646d2SAndroid Build Coastguard Worker 	 reason = (char *)cupsArrayNext(new_reasons))
3572*5e7646d2SAndroid Build Coastguard Worker     {
3573*5e7646d2SAndroid Build Coastguard Worker       if (!cupsArrayFind(state_reasons, reason))
3574*5e7646d2SAndroid Build Coastguard Worker       {
3575*5e7646d2SAndroid Build Coastguard Worker         if (!strncmp(reason, "cups-remote-", 12))
3576*5e7646d2SAndroid Build Coastguard Worker 	{
3577*5e7646d2SAndroid Build Coastguard Worker 	 /*
3578*5e7646d2SAndroid Build Coastguard Worker 	  * If we are setting cups-remote-xxx, remove all other cups-remote-xxx
3579*5e7646d2SAndroid Build Coastguard Worker 	  * keywords...
3580*5e7646d2SAndroid Build Coastguard Worker 	  */
3581*5e7646d2SAndroid Build Coastguard Worker 
3582*5e7646d2SAndroid Build Coastguard Worker 	  char	*temp;		/* Current reason in state_reasons */
3583*5e7646d2SAndroid Build Coastguard Worker 
3584*5e7646d2SAndroid Build Coastguard Worker 	  cupsArraySave(state_reasons);
3585*5e7646d2SAndroid Build Coastguard Worker 
3586*5e7646d2SAndroid Build Coastguard Worker 	  for (temp = (char *)cupsArrayFirst(state_reasons);
3587*5e7646d2SAndroid Build Coastguard Worker 	       temp;
3588*5e7646d2SAndroid Build Coastguard Worker 	       temp = (char *)cupsArrayNext(state_reasons))
3589*5e7646d2SAndroid Build Coastguard Worker 	    if (!strncmp(temp, "cups-remote-", 12))
3590*5e7646d2SAndroid Build Coastguard Worker 	    {
3591*5e7646d2SAndroid Build Coastguard Worker 	      snprintf(remptr, sizeof(rem) - (size_t)(remptr - rem), "%s%s", remprefix, temp);
3592*5e7646d2SAndroid Build Coastguard Worker 	      remptr    += strlen(remptr);
3593*5e7646d2SAndroid Build Coastguard Worker 	      remprefix = ",";
3594*5e7646d2SAndroid Build Coastguard Worker 
3595*5e7646d2SAndroid Build Coastguard Worker 	      cupsArrayRemove(state_reasons, temp);
3596*5e7646d2SAndroid Build Coastguard Worker 	      break;
3597*5e7646d2SAndroid Build Coastguard Worker 	    }
3598*5e7646d2SAndroid Build Coastguard Worker 
3599*5e7646d2SAndroid Build Coastguard Worker 	  cupsArrayRestore(state_reasons);
3600*5e7646d2SAndroid Build Coastguard Worker 	}
3601*5e7646d2SAndroid Build Coastguard Worker 
3602*5e7646d2SAndroid Build Coastguard Worker         cupsArrayAdd(state_reasons, reason);
3603*5e7646d2SAndroid Build Coastguard Worker 
3604*5e7646d2SAndroid Build Coastguard Worker         snprintf(addptr, sizeof(add) - (size_t)(addptr - add), "%s%s", addprefix, reason);
3605*5e7646d2SAndroid Build Coastguard Worker 	addptr    += strlen(addptr);
3606*5e7646d2SAndroid Build Coastguard Worker 	addprefix = ",";
3607*5e7646d2SAndroid Build Coastguard Worker       }
3608*5e7646d2SAndroid Build Coastguard Worker     }
3609*5e7646d2SAndroid Build Coastguard Worker   }
3610*5e7646d2SAndroid Build Coastguard Worker   else if (op == '-')
3611*5e7646d2SAndroid Build Coastguard Worker   {
3612*5e7646d2SAndroid Build Coastguard Worker    /*
3613*5e7646d2SAndroid Build Coastguard Worker     * Remove reasons...
3614*5e7646d2SAndroid Build Coastguard Worker     */
3615*5e7646d2SAndroid Build Coastguard Worker 
3616*5e7646d2SAndroid Build Coastguard Worker     for (reason = (char *)cupsArrayFirst(new_reasons);
3617*5e7646d2SAndroid Build Coastguard Worker 	 reason;
3618*5e7646d2SAndroid Build Coastguard Worker 	 reason = (char *)cupsArrayNext(new_reasons))
3619*5e7646d2SAndroid Build Coastguard Worker     {
3620*5e7646d2SAndroid Build Coastguard Worker       if (cupsArrayFind(state_reasons, reason))
3621*5e7646d2SAndroid Build Coastguard Worker       {
3622*5e7646d2SAndroid Build Coastguard Worker 	snprintf(remptr, sizeof(rem) - (size_t)(remptr - rem), "%s%s", remprefix, reason);
3623*5e7646d2SAndroid Build Coastguard Worker 	remptr    += strlen(remptr);
3624*5e7646d2SAndroid Build Coastguard Worker 	remprefix = ",";
3625*5e7646d2SAndroid Build Coastguard Worker 
3626*5e7646d2SAndroid Build Coastguard Worker         cupsArrayRemove(state_reasons, reason);
3627*5e7646d2SAndroid Build Coastguard Worker       }
3628*5e7646d2SAndroid Build Coastguard Worker     }
3629*5e7646d2SAndroid Build Coastguard Worker   }
3630*5e7646d2SAndroid Build Coastguard Worker   else
3631*5e7646d2SAndroid Build Coastguard Worker   {
3632*5e7646d2SAndroid Build Coastguard Worker    /*
3633*5e7646d2SAndroid Build Coastguard Worker     * Replace reasons...
3634*5e7646d2SAndroid Build Coastguard Worker     */
3635*5e7646d2SAndroid Build Coastguard Worker 
3636*5e7646d2SAndroid Build Coastguard Worker     for (reason = (char *)cupsArrayFirst(state_reasons);
3637*5e7646d2SAndroid Build Coastguard Worker 	 reason;
3638*5e7646d2SAndroid Build Coastguard Worker 	 reason = (char *)cupsArrayNext(state_reasons))
3639*5e7646d2SAndroid Build Coastguard Worker     {
3640*5e7646d2SAndroid Build Coastguard Worker       if (strncmp(reason, "cups-", 5) && !cupsArrayFind(new_reasons, reason))
3641*5e7646d2SAndroid Build Coastguard Worker       {
3642*5e7646d2SAndroid Build Coastguard Worker 	snprintf(remptr, sizeof(rem) - (size_t)(remptr - rem), "%s%s", remprefix, reason);
3643*5e7646d2SAndroid Build Coastguard Worker 	remptr    += strlen(remptr);
3644*5e7646d2SAndroid Build Coastguard Worker 	remprefix = ",";
3645*5e7646d2SAndroid Build Coastguard Worker 
3646*5e7646d2SAndroid Build Coastguard Worker         cupsArrayRemove(state_reasons, reason);
3647*5e7646d2SAndroid Build Coastguard Worker       }
3648*5e7646d2SAndroid Build Coastguard Worker     }
3649*5e7646d2SAndroid Build Coastguard Worker 
3650*5e7646d2SAndroid Build Coastguard Worker     for (reason = (char *)cupsArrayFirst(new_reasons);
3651*5e7646d2SAndroid Build Coastguard Worker 	 reason;
3652*5e7646d2SAndroid Build Coastguard Worker 	 reason = (char *)cupsArrayNext(new_reasons))
3653*5e7646d2SAndroid Build Coastguard Worker     {
3654*5e7646d2SAndroid Build Coastguard Worker       if (!cupsArrayFind(state_reasons, reason))
3655*5e7646d2SAndroid Build Coastguard Worker       {
3656*5e7646d2SAndroid Build Coastguard Worker         cupsArrayAdd(state_reasons, reason);
3657*5e7646d2SAndroid Build Coastguard Worker 
3658*5e7646d2SAndroid Build Coastguard Worker         snprintf(addptr, sizeof(add) - (size_t)(addptr - add), "%s%s", addprefix, reason);
3659*5e7646d2SAndroid Build Coastguard Worker 	addptr    += strlen(addptr);
3660*5e7646d2SAndroid Build Coastguard Worker 	addprefix = ",";
3661*5e7646d2SAndroid Build Coastguard Worker       }
3662*5e7646d2SAndroid Build Coastguard Worker     }
3663*5e7646d2SAndroid Build Coastguard Worker   }
3664*5e7646d2SAndroid Build Coastguard Worker 
3665*5e7646d2SAndroid Build Coastguard Worker   cupsArrayDelete(new_reasons);
3666*5e7646d2SAndroid Build Coastguard Worker 
3667*5e7646d2SAndroid Build Coastguard Worker   _cupsMutexUnlock(&report_mutex);
3668*5e7646d2SAndroid Build Coastguard Worker 
3669*5e7646d2SAndroid Build Coastguard Worker  /*
3670*5e7646d2SAndroid Build Coastguard Worker   * Report changes and return...
3671*5e7646d2SAndroid Build Coastguard Worker   */
3672*5e7646d2SAndroid Build Coastguard Worker 
3673*5e7646d2SAndroid Build Coastguard Worker   if (add[0] && rem[0])
3674*5e7646d2SAndroid Build Coastguard Worker     fprintf(stderr, "%s\n%s\n", add, rem);
3675*5e7646d2SAndroid Build Coastguard Worker   else if (add[0])
3676*5e7646d2SAndroid Build Coastguard Worker     fprintf(stderr, "%s\n", add);
3677*5e7646d2SAndroid Build Coastguard Worker   else if (rem[0])
3678*5e7646d2SAndroid Build Coastguard Worker     fprintf(stderr, "%s\n", rem);
3679*5e7646d2SAndroid Build Coastguard Worker }
3680