1*5e7646d2SAndroid Build Coastguard Worker /*
2*5e7646d2SAndroid Build Coastguard Worker * IPP routines for the CUPS scheduler.
3*5e7646d2SAndroid Build Coastguard Worker *
4*5e7646d2SAndroid Build Coastguard Worker * Copyright © 2007-2021 by Apple Inc.
5*5e7646d2SAndroid Build Coastguard Worker * Copyright © 1997-2007 by Easy Software Products, all rights reserved.
6*5e7646d2SAndroid Build Coastguard Worker *
7*5e7646d2SAndroid Build Coastguard Worker * This file contains Kerberos support code, copyright 2006 by
8*5e7646d2SAndroid Build Coastguard Worker * Jelmer Vernooij.
9*5e7646d2SAndroid Build Coastguard Worker *
10*5e7646d2SAndroid Build Coastguard Worker * Licensed under Apache License v2.0. See the file "LICENSE" for more
11*5e7646d2SAndroid Build Coastguard Worker * information.
12*5e7646d2SAndroid Build Coastguard Worker */
13*5e7646d2SAndroid Build Coastguard Worker
14*5e7646d2SAndroid Build Coastguard Worker /*
15*5e7646d2SAndroid Build Coastguard Worker * Include necessary headers...
16*5e7646d2SAndroid Build Coastguard Worker */
17*5e7646d2SAndroid Build Coastguard Worker
18*5e7646d2SAndroid Build Coastguard Worker #include "cupsd.h"
19*5e7646d2SAndroid Build Coastguard Worker #include <cups/ppd-private.h>
20*5e7646d2SAndroid Build Coastguard Worker
21*5e7646d2SAndroid Build Coastguard Worker #ifdef __APPLE__
22*5e7646d2SAndroid Build Coastguard Worker # ifdef HAVE_MEMBERSHIP_H
23*5e7646d2SAndroid Build Coastguard Worker # include <membership.h>
24*5e7646d2SAndroid Build Coastguard Worker # endif /* HAVE_MEMBERSHIP_H */
25*5e7646d2SAndroid Build Coastguard Worker extern int mbr_user_name_to_uuid(const char* name, uuid_t uu);
26*5e7646d2SAndroid Build Coastguard Worker extern int mbr_group_name_to_uuid(const char* name, uuid_t uu);
27*5e7646d2SAndroid Build Coastguard Worker extern int mbr_check_membership_by_id(uuid_t user, gid_t group, int* ismember);
28*5e7646d2SAndroid Build Coastguard Worker #endif /* __APPLE__ */
29*5e7646d2SAndroid Build Coastguard Worker
30*5e7646d2SAndroid Build Coastguard Worker
31*5e7646d2SAndroid Build Coastguard Worker /*
32*5e7646d2SAndroid Build Coastguard Worker * Local functions...
33*5e7646d2SAndroid Build Coastguard Worker */
34*5e7646d2SAndroid Build Coastguard Worker
35*5e7646d2SAndroid Build Coastguard Worker static void accept_jobs(cupsd_client_t *con, ipp_attribute_t *uri);
36*5e7646d2SAndroid Build Coastguard Worker static void add_class(cupsd_client_t *con, ipp_attribute_t *uri);
37*5e7646d2SAndroid Build Coastguard Worker static int add_file(cupsd_client_t *con, cupsd_job_t *job,
38*5e7646d2SAndroid Build Coastguard Worker mime_type_t *filetype, int compression);
39*5e7646d2SAndroid Build Coastguard Worker static cupsd_job_t *add_job(cupsd_client_t *con, cupsd_printer_t *printer,
40*5e7646d2SAndroid Build Coastguard Worker mime_type_t *filetype);
41*5e7646d2SAndroid Build Coastguard Worker static void add_job_subscriptions(cupsd_client_t *con, cupsd_job_t *job);
42*5e7646d2SAndroid Build Coastguard Worker static void add_job_uuid(cupsd_job_t *job);
43*5e7646d2SAndroid Build Coastguard Worker static void add_printer(cupsd_client_t *con, ipp_attribute_t *uri);
44*5e7646d2SAndroid Build Coastguard Worker static void add_printer_state_reasons(cupsd_client_t *con,
45*5e7646d2SAndroid Build Coastguard Worker cupsd_printer_t *p);
46*5e7646d2SAndroid Build Coastguard Worker static void add_queued_job_count(cupsd_client_t *con, cupsd_printer_t *p);
47*5e7646d2SAndroid Build Coastguard Worker static void apply_printer_defaults(cupsd_printer_t *printer,
48*5e7646d2SAndroid Build Coastguard Worker cupsd_job_t *job);
49*5e7646d2SAndroid Build Coastguard Worker static void authenticate_job(cupsd_client_t *con, ipp_attribute_t *uri);
50*5e7646d2SAndroid Build Coastguard Worker static void cancel_all_jobs(cupsd_client_t *con, ipp_attribute_t *uri);
51*5e7646d2SAndroid Build Coastguard Worker static void cancel_job(cupsd_client_t *con, ipp_attribute_t *uri);
52*5e7646d2SAndroid Build Coastguard Worker static void cancel_subscription(cupsd_client_t *con, int id);
53*5e7646d2SAndroid Build Coastguard Worker static int check_rss_recipient(const char *recipient);
54*5e7646d2SAndroid Build Coastguard Worker static int check_quotas(cupsd_client_t *con, cupsd_printer_t *p);
55*5e7646d2SAndroid Build Coastguard Worker static void close_job(cupsd_client_t *con, ipp_attribute_t *uri);
56*5e7646d2SAndroid Build Coastguard Worker static void copy_attrs(ipp_t *to, ipp_t *from, cups_array_t *ra,
57*5e7646d2SAndroid Build Coastguard Worker ipp_tag_t group, int quickcopy,
58*5e7646d2SAndroid Build Coastguard Worker cups_array_t *exclude);
59*5e7646d2SAndroid Build Coastguard Worker static int copy_banner(cupsd_client_t *con, cupsd_job_t *job,
60*5e7646d2SAndroid Build Coastguard Worker const char *name);
61*5e7646d2SAndroid Build Coastguard Worker static int copy_file(const char *from, const char *to, mode_t mode);
62*5e7646d2SAndroid Build Coastguard Worker static int copy_model(cupsd_client_t *con, const char *from,
63*5e7646d2SAndroid Build Coastguard Worker const char *to);
64*5e7646d2SAndroid Build Coastguard Worker static void copy_job_attrs(cupsd_client_t *con,
65*5e7646d2SAndroid Build Coastguard Worker cupsd_job_t *job,
66*5e7646d2SAndroid Build Coastguard Worker cups_array_t *ra, cups_array_t *exclude);
67*5e7646d2SAndroid Build Coastguard Worker static void copy_printer_attrs(cupsd_client_t *con,
68*5e7646d2SAndroid Build Coastguard Worker cupsd_printer_t *printer,
69*5e7646d2SAndroid Build Coastguard Worker cups_array_t *ra);
70*5e7646d2SAndroid Build Coastguard Worker static void copy_subscription_attrs(cupsd_client_t *con,
71*5e7646d2SAndroid Build Coastguard Worker cupsd_subscription_t *sub,
72*5e7646d2SAndroid Build Coastguard Worker cups_array_t *ra,
73*5e7646d2SAndroid Build Coastguard Worker cups_array_t *exclude);
74*5e7646d2SAndroid Build Coastguard Worker static void create_job(cupsd_client_t *con, ipp_attribute_t *uri);
75*5e7646d2SAndroid Build Coastguard Worker static void *create_local_bg_thread(cupsd_printer_t *printer);
76*5e7646d2SAndroid Build Coastguard Worker static void create_local_printer(cupsd_client_t *con);
77*5e7646d2SAndroid Build Coastguard Worker static cups_array_t *create_requested_array(ipp_t *request);
78*5e7646d2SAndroid Build Coastguard Worker static void create_subscriptions(cupsd_client_t *con, ipp_attribute_t *uri);
79*5e7646d2SAndroid Build Coastguard Worker static void delete_printer(cupsd_client_t *con, ipp_attribute_t *uri);
80*5e7646d2SAndroid Build Coastguard Worker static void get_default(cupsd_client_t *con);
81*5e7646d2SAndroid Build Coastguard Worker static void get_devices(cupsd_client_t *con);
82*5e7646d2SAndroid Build Coastguard Worker static void get_document(cupsd_client_t *con, ipp_attribute_t *uri);
83*5e7646d2SAndroid Build Coastguard Worker static void get_jobs(cupsd_client_t *con, ipp_attribute_t *uri);
84*5e7646d2SAndroid Build Coastguard Worker static void get_job_attrs(cupsd_client_t *con, ipp_attribute_t *uri);
85*5e7646d2SAndroid Build Coastguard Worker static void get_notifications(cupsd_client_t *con);
86*5e7646d2SAndroid Build Coastguard Worker static void get_ppd(cupsd_client_t *con, ipp_attribute_t *uri);
87*5e7646d2SAndroid Build Coastguard Worker static void get_ppds(cupsd_client_t *con);
88*5e7646d2SAndroid Build Coastguard Worker static void get_printers(cupsd_client_t *con, int type);
89*5e7646d2SAndroid Build Coastguard Worker static void get_printer_attrs(cupsd_client_t *con, ipp_attribute_t *uri);
90*5e7646d2SAndroid Build Coastguard Worker static void get_printer_supported(cupsd_client_t *con, ipp_attribute_t *uri);
91*5e7646d2SAndroid Build Coastguard Worker static void get_subscription_attrs(cupsd_client_t *con, int sub_id);
92*5e7646d2SAndroid Build Coastguard Worker static void get_subscriptions(cupsd_client_t *con, ipp_attribute_t *uri);
93*5e7646d2SAndroid Build Coastguard Worker static const char *get_username(cupsd_client_t *con);
94*5e7646d2SAndroid Build Coastguard Worker static void hold_job(cupsd_client_t *con, ipp_attribute_t *uri);
95*5e7646d2SAndroid Build Coastguard Worker static void hold_new_jobs(cupsd_client_t *con, ipp_attribute_t *uri);
96*5e7646d2SAndroid Build Coastguard Worker static void move_job(cupsd_client_t *con, ipp_attribute_t *uri);
97*5e7646d2SAndroid Build Coastguard Worker static int ppd_parse_line(const char *line, char *option, int olen,
98*5e7646d2SAndroid Build Coastguard Worker char *choice, int clen);
99*5e7646d2SAndroid Build Coastguard Worker static void print_job(cupsd_client_t *con, ipp_attribute_t *uri);
100*5e7646d2SAndroid Build Coastguard Worker static void read_job_ticket(cupsd_client_t *con);
101*5e7646d2SAndroid Build Coastguard Worker static void reject_jobs(cupsd_client_t *con, ipp_attribute_t *uri);
102*5e7646d2SAndroid Build Coastguard Worker static void release_held_new_jobs(cupsd_client_t *con,
103*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *uri);
104*5e7646d2SAndroid Build Coastguard Worker static void release_job(cupsd_client_t *con, ipp_attribute_t *uri);
105*5e7646d2SAndroid Build Coastguard Worker static void renew_subscription(cupsd_client_t *con, int sub_id);
106*5e7646d2SAndroid Build Coastguard Worker static void restart_job(cupsd_client_t *con, ipp_attribute_t *uri);
107*5e7646d2SAndroid Build Coastguard Worker static void save_auth_info(cupsd_client_t *con, cupsd_job_t *job,
108*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *auth_info);
109*5e7646d2SAndroid Build Coastguard Worker static void send_document(cupsd_client_t *con, ipp_attribute_t *uri);
110*5e7646d2SAndroid Build Coastguard Worker static void send_http_error(cupsd_client_t *con, http_status_t status,
111*5e7646d2SAndroid Build Coastguard Worker cupsd_printer_t *printer);
112*5e7646d2SAndroid Build Coastguard Worker static void send_ipp_status(cupsd_client_t *con, ipp_status_t status, const char *message, ...) _CUPS_FORMAT(3, 4);
113*5e7646d2SAndroid Build Coastguard Worker static void set_default(cupsd_client_t *con, ipp_attribute_t *uri);
114*5e7646d2SAndroid Build Coastguard Worker static void set_job_attrs(cupsd_client_t *con, ipp_attribute_t *uri);
115*5e7646d2SAndroid Build Coastguard Worker static void set_printer_attrs(cupsd_client_t *con, ipp_attribute_t *uri);
116*5e7646d2SAndroid Build Coastguard Worker static int set_printer_defaults(cupsd_client_t *con, cupsd_printer_t *printer);
117*5e7646d2SAndroid Build Coastguard Worker static void start_printer(cupsd_client_t *con, ipp_attribute_t *uri);
118*5e7646d2SAndroid Build Coastguard Worker static void stop_printer(cupsd_client_t *con, ipp_attribute_t *uri);
119*5e7646d2SAndroid Build Coastguard Worker static void url_encode_attr(ipp_attribute_t *attr, char *buffer, size_t bufsize);
120*5e7646d2SAndroid Build Coastguard Worker static char *url_encode_string(const char *s, char *buffer, size_t bufsize);
121*5e7646d2SAndroid Build Coastguard Worker static int user_allowed(cupsd_printer_t *p, const char *username);
122*5e7646d2SAndroid Build Coastguard Worker static void validate_job(cupsd_client_t *con, ipp_attribute_t *uri);
123*5e7646d2SAndroid Build Coastguard Worker static int validate_name(const char *name);
124*5e7646d2SAndroid Build Coastguard Worker static int validate_user(cupsd_job_t *job, cupsd_client_t *con, const char *owner, char *username, size_t userlen);
125*5e7646d2SAndroid Build Coastguard Worker
126*5e7646d2SAndroid Build Coastguard Worker
127*5e7646d2SAndroid Build Coastguard Worker /*
128*5e7646d2SAndroid Build Coastguard Worker * 'cupsdProcessIPPRequest()' - Process an incoming IPP request.
129*5e7646d2SAndroid Build Coastguard Worker */
130*5e7646d2SAndroid Build Coastguard Worker
131*5e7646d2SAndroid Build Coastguard Worker int /* O - 1 on success, 0 on failure */
cupsdProcessIPPRequest(cupsd_client_t * con)132*5e7646d2SAndroid Build Coastguard Worker cupsdProcessIPPRequest(
133*5e7646d2SAndroid Build Coastguard Worker cupsd_client_t *con) /* I - Client connection */
134*5e7646d2SAndroid Build Coastguard Worker {
135*5e7646d2SAndroid Build Coastguard Worker ipp_tag_t group; /* Current group tag */
136*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *attr; /* Current attribute */
137*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *charset; /* Character set attribute */
138*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *language; /* Language attribute */
139*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *uri = NULL; /* Printer or job URI attribute */
140*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *username; /* requesting-user-name attr */
141*5e7646d2SAndroid Build Coastguard Worker int sub_id; /* Subscription ID */
142*5e7646d2SAndroid Build Coastguard Worker int valid = 1; /* Valid request? */
143*5e7646d2SAndroid Build Coastguard Worker
144*5e7646d2SAndroid Build Coastguard Worker
145*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdProcessIPPRequest(%p[%d]): operation_id=%04x(%s)", con, con->number, con->request->request.op.operation_id, ippOpString(con->request->request.op.operation_id));
146*5e7646d2SAndroid Build Coastguard Worker
147*5e7646d2SAndroid Build Coastguard Worker if (LogLevel >= CUPSD_LOG_DEBUG2)
148*5e7646d2SAndroid Build Coastguard Worker {
149*5e7646d2SAndroid Build Coastguard Worker for (group = IPP_TAG_ZERO, attr = ippFirstAttribute(con->request); attr; attr = ippNextAttribute(con->request))
150*5e7646d2SAndroid Build Coastguard Worker {
151*5e7646d2SAndroid Build Coastguard Worker const char *name; /* Attribute name */
152*5e7646d2SAndroid Build Coastguard Worker char value[1024]; /* Attribute value */
153*5e7646d2SAndroid Build Coastguard Worker
154*5e7646d2SAndroid Build Coastguard Worker if (group != ippGetGroupTag(attr))
155*5e7646d2SAndroid Build Coastguard Worker {
156*5e7646d2SAndroid Build Coastguard Worker group = ippGetGroupTag(attr);
157*5e7646d2SAndroid Build Coastguard Worker if (group != IPP_TAG_ZERO)
158*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdProcessIPPRequest: %s", ippTagString(group));
159*5e7646d2SAndroid Build Coastguard Worker }
160*5e7646d2SAndroid Build Coastguard Worker
161*5e7646d2SAndroid Build Coastguard Worker if ((name = ippGetName(attr)) == NULL)
162*5e7646d2SAndroid Build Coastguard Worker continue;
163*5e7646d2SAndroid Build Coastguard Worker
164*5e7646d2SAndroid Build Coastguard Worker ippAttributeString(attr, value, sizeof(value));
165*5e7646d2SAndroid Build Coastguard Worker
166*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdProcessIPPRequest: %s %s%s '%s'", name, ippGetCount(attr) > 1 ? "1setOf " : "", ippTagString(ippGetValueTag(attr)), value);
167*5e7646d2SAndroid Build Coastguard Worker }
168*5e7646d2SAndroid Build Coastguard Worker }
169*5e7646d2SAndroid Build Coastguard Worker
170*5e7646d2SAndroid Build Coastguard Worker /*
171*5e7646d2SAndroid Build Coastguard Worker * First build an empty response message for this request...
172*5e7646d2SAndroid Build Coastguard Worker */
173*5e7646d2SAndroid Build Coastguard Worker
174*5e7646d2SAndroid Build Coastguard Worker con->response = ippNew();
175*5e7646d2SAndroid Build Coastguard Worker
176*5e7646d2SAndroid Build Coastguard Worker con->response->request.status.version[0] = con->request->request.op.version[0];
177*5e7646d2SAndroid Build Coastguard Worker con->response->request.status.version[1] = con->request->request.op.version[1];
178*5e7646d2SAndroid Build Coastguard Worker con->response->request.status.request_id = con->request->request.op.request_id;
179*5e7646d2SAndroid Build Coastguard Worker
180*5e7646d2SAndroid Build Coastguard Worker /*
181*5e7646d2SAndroid Build Coastguard Worker * Then validate the request header and required attributes...
182*5e7646d2SAndroid Build Coastguard Worker */
183*5e7646d2SAndroid Build Coastguard Worker
184*5e7646d2SAndroid Build Coastguard Worker if (con->request->request.any.version[0] != 1 && con->request->request.any.version[0] != 2)
185*5e7646d2SAndroid Build Coastguard Worker {
186*5e7646d2SAndroid Build Coastguard Worker /*
187*5e7646d2SAndroid Build Coastguard Worker * Return an error, since we only support IPP 1.x and 2.x.
188*5e7646d2SAndroid Build Coastguard Worker */
189*5e7646d2SAndroid Build Coastguard Worker
190*5e7646d2SAndroid Build Coastguard Worker cupsdAddEvent(CUPSD_EVENT_SERVER_AUDIT, NULL, NULL, "%04X %s Bad request version number %d.%d.", IPP_STATUS_ERROR_VERSION_NOT_SUPPORTED, con->http->hostname, con->request->request.any.version[0], con->request->request.any.version[1]);
191*5e7646d2SAndroid Build Coastguard Worker
192*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_STATUS_ERROR_VERSION_NOT_SUPPORTED, _("Bad request version number %d.%d."), con->request->request.any.version[0], con->request->request.any.version[1]);
193*5e7646d2SAndroid Build Coastguard Worker }
194*5e7646d2SAndroid Build Coastguard Worker else if (con->request->request.any.request_id < 1)
195*5e7646d2SAndroid Build Coastguard Worker {
196*5e7646d2SAndroid Build Coastguard Worker /*
197*5e7646d2SAndroid Build Coastguard Worker * Return an error, since request IDs must be between 1 and 2^31-1
198*5e7646d2SAndroid Build Coastguard Worker */
199*5e7646d2SAndroid Build Coastguard Worker
200*5e7646d2SAndroid Build Coastguard Worker cupsdAddEvent(CUPSD_EVENT_SERVER_AUDIT, NULL, NULL, "%04X %s Bad request ID %d.", IPP_STATUS_ERROR_BAD_REQUEST, con->http->hostname, con->request->request.any.request_id);
201*5e7646d2SAndroid Build Coastguard Worker
202*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_STATUS_ERROR_BAD_REQUEST, _("Bad request ID %d."), con->request->request.any.request_id);
203*5e7646d2SAndroid Build Coastguard Worker }
204*5e7646d2SAndroid Build Coastguard Worker else if (!con->request->attrs)
205*5e7646d2SAndroid Build Coastguard Worker {
206*5e7646d2SAndroid Build Coastguard Worker cupsdAddEvent(CUPSD_EVENT_SERVER_AUDIT, NULL, NULL, "%04X %s No attributes in request.", IPP_STATUS_ERROR_BAD_REQUEST, con->http->hostname);
207*5e7646d2SAndroid Build Coastguard Worker
208*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_STATUS_ERROR_BAD_REQUEST, _("No attributes in request."));
209*5e7646d2SAndroid Build Coastguard Worker }
210*5e7646d2SAndroid Build Coastguard Worker else
211*5e7646d2SAndroid Build Coastguard Worker {
212*5e7646d2SAndroid Build Coastguard Worker /*
213*5e7646d2SAndroid Build Coastguard Worker * Make sure that the attributes are provided in the correct order and
214*5e7646d2SAndroid Build Coastguard Worker * don't repeat groups...
215*5e7646d2SAndroid Build Coastguard Worker */
216*5e7646d2SAndroid Build Coastguard Worker
217*5e7646d2SAndroid Build Coastguard Worker for (attr = con->request->attrs, group = attr->group_tag;
218*5e7646d2SAndroid Build Coastguard Worker attr;
219*5e7646d2SAndroid Build Coastguard Worker attr = attr->next)
220*5e7646d2SAndroid Build Coastguard Worker if (attr->group_tag < group && attr->group_tag != IPP_TAG_ZERO)
221*5e7646d2SAndroid Build Coastguard Worker {
222*5e7646d2SAndroid Build Coastguard Worker /*
223*5e7646d2SAndroid Build Coastguard Worker * Out of order; return an error...
224*5e7646d2SAndroid Build Coastguard Worker */
225*5e7646d2SAndroid Build Coastguard Worker
226*5e7646d2SAndroid Build Coastguard Worker cupsdAddEvent(CUPSD_EVENT_SERVER_AUDIT, NULL, NULL, "%04X %s Attribute groups are out of order", IPP_STATUS_ERROR_BAD_REQUEST, con->http->hostname);
227*5e7646d2SAndroid Build Coastguard Worker
228*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_STATUS_ERROR_BAD_REQUEST, _("Attribute groups are out of order (%x < %x)."), attr->group_tag, group);
229*5e7646d2SAndroid Build Coastguard Worker break;
230*5e7646d2SAndroid Build Coastguard Worker }
231*5e7646d2SAndroid Build Coastguard Worker else
232*5e7646d2SAndroid Build Coastguard Worker group = attr->group_tag;
233*5e7646d2SAndroid Build Coastguard Worker
234*5e7646d2SAndroid Build Coastguard Worker if (!attr)
235*5e7646d2SAndroid Build Coastguard Worker {
236*5e7646d2SAndroid Build Coastguard Worker /*
237*5e7646d2SAndroid Build Coastguard Worker * Then make sure that the first three attributes are:
238*5e7646d2SAndroid Build Coastguard Worker *
239*5e7646d2SAndroid Build Coastguard Worker * attributes-charset
240*5e7646d2SAndroid Build Coastguard Worker * attributes-natural-language
241*5e7646d2SAndroid Build Coastguard Worker * printer-uri/job-uri
242*5e7646d2SAndroid Build Coastguard Worker */
243*5e7646d2SAndroid Build Coastguard Worker
244*5e7646d2SAndroid Build Coastguard Worker attr = con->request->attrs;
245*5e7646d2SAndroid Build Coastguard Worker if (attr && attr->name && !strcmp(attr->name, "attributes-charset") && (attr->value_tag & IPP_TAG_MASK) == IPP_TAG_CHARSET && attr->group_tag == IPP_TAG_OPERATION)
246*5e7646d2SAndroid Build Coastguard Worker charset = attr;
247*5e7646d2SAndroid Build Coastguard Worker else
248*5e7646d2SAndroid Build Coastguard Worker charset = NULL;
249*5e7646d2SAndroid Build Coastguard Worker
250*5e7646d2SAndroid Build Coastguard Worker if (attr)
251*5e7646d2SAndroid Build Coastguard Worker attr = attr->next;
252*5e7646d2SAndroid Build Coastguard Worker
253*5e7646d2SAndroid Build Coastguard Worker if (attr && attr->name && !strcmp(attr->name, "attributes-natural-language") && (attr->value_tag & IPP_TAG_MASK) == IPP_TAG_LANGUAGE && attr->group_tag == IPP_TAG_OPERATION)
254*5e7646d2SAndroid Build Coastguard Worker {
255*5e7646d2SAndroid Build Coastguard Worker language = attr;
256*5e7646d2SAndroid Build Coastguard Worker
257*5e7646d2SAndroid Build Coastguard Worker /*
258*5e7646d2SAndroid Build Coastguard Worker * Reset language for this request if different from Accept-Language.
259*5e7646d2SAndroid Build Coastguard Worker */
260*5e7646d2SAndroid Build Coastguard Worker
261*5e7646d2SAndroid Build Coastguard Worker if (!con->language ||
262*5e7646d2SAndroid Build Coastguard Worker strcmp(attr->values[0].string.text, con->language->language))
263*5e7646d2SAndroid Build Coastguard Worker {
264*5e7646d2SAndroid Build Coastguard Worker cupsLangFree(con->language);
265*5e7646d2SAndroid Build Coastguard Worker con->language = cupsLangGet(attr->values[0].string.text);
266*5e7646d2SAndroid Build Coastguard Worker }
267*5e7646d2SAndroid Build Coastguard Worker }
268*5e7646d2SAndroid Build Coastguard Worker else
269*5e7646d2SAndroid Build Coastguard Worker language = NULL;
270*5e7646d2SAndroid Build Coastguard Worker
271*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippFindAttribute(con->request, "printer-uri", IPP_TAG_URI)) != NULL && attr->group_tag == IPP_TAG_OPERATION)
272*5e7646d2SAndroid Build Coastguard Worker uri = attr;
273*5e7646d2SAndroid Build Coastguard Worker else if ((attr = ippFindAttribute(con->request, "job-uri", IPP_TAG_URI)) != NULL && attr->group_tag == IPP_TAG_OPERATION)
274*5e7646d2SAndroid Build Coastguard Worker uri = attr;
275*5e7646d2SAndroid Build Coastguard Worker else if (con->request->request.op.operation_id == CUPS_GET_PPD && (attr = ippFindAttribute(con->request, "ppd-name", IPP_TAG_NAME)) != NULL && attr->group_tag == IPP_TAG_OPERATION)
276*5e7646d2SAndroid Build Coastguard Worker uri = attr;
277*5e7646d2SAndroid Build Coastguard Worker else
278*5e7646d2SAndroid Build Coastguard Worker uri = NULL;
279*5e7646d2SAndroid Build Coastguard Worker
280*5e7646d2SAndroid Build Coastguard Worker if (charset)
281*5e7646d2SAndroid Build Coastguard Worker ippAddString(con->response, IPP_TAG_OPERATION, IPP_TAG_CHARSET, "attributes-charset", NULL, charset->values[0].string.text);
282*5e7646d2SAndroid Build Coastguard Worker else
283*5e7646d2SAndroid Build Coastguard Worker ippAddString(con->response, IPP_TAG_OPERATION, IPP_TAG_CHARSET, "attributes-charset", NULL, "utf-8");
284*5e7646d2SAndroid Build Coastguard Worker
285*5e7646d2SAndroid Build Coastguard Worker if (language)
286*5e7646d2SAndroid Build Coastguard Worker ippAddString(con->response, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE, "attributes-natural-language", NULL, language->values[0].string.text);
287*5e7646d2SAndroid Build Coastguard Worker else
288*5e7646d2SAndroid Build Coastguard Worker ippAddString(con->response, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE, "attributes-natural-language", NULL, DefaultLanguage);
289*5e7646d2SAndroid Build Coastguard Worker
290*5e7646d2SAndroid Build Coastguard Worker if (charset && _cups_strcasecmp(charset->values[0].string.text, "us-ascii") && _cups_strcasecmp(charset->values[0].string.text, "utf-8"))
291*5e7646d2SAndroid Build Coastguard Worker {
292*5e7646d2SAndroid Build Coastguard Worker /*
293*5e7646d2SAndroid Build Coastguard Worker * Bad character set...
294*5e7646d2SAndroid Build Coastguard Worker */
295*5e7646d2SAndroid Build Coastguard Worker
296*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_ERROR, "Unsupported character set \"%s\"",
297*5e7646d2SAndroid Build Coastguard Worker charset->values[0].string.text);
298*5e7646d2SAndroid Build Coastguard Worker cupsdAddEvent(CUPSD_EVENT_SERVER_AUDIT, NULL, NULL, "%04X %s Unsupported attributes-charset value \"%s\".", IPP_STATUS_ERROR_CHARSET, con->http->hostname, charset->values[0].string.text);
299*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_STATUS_ERROR_CHARSET, _("Unsupported character set \"%s\"."), charset->values[0].string.text);
300*5e7646d2SAndroid Build Coastguard Worker }
301*5e7646d2SAndroid Build Coastguard Worker else if (!charset || !language ||
302*5e7646d2SAndroid Build Coastguard Worker (!uri &&
303*5e7646d2SAndroid Build Coastguard Worker con->request->request.op.operation_id != CUPS_GET_DEFAULT &&
304*5e7646d2SAndroid Build Coastguard Worker con->request->request.op.operation_id != CUPS_GET_PRINTERS &&
305*5e7646d2SAndroid Build Coastguard Worker con->request->request.op.operation_id != CUPS_GET_CLASSES &&
306*5e7646d2SAndroid Build Coastguard Worker con->request->request.op.operation_id != CUPS_GET_DEVICES &&
307*5e7646d2SAndroid Build Coastguard Worker con->request->request.op.operation_id != CUPS_GET_PPDS))
308*5e7646d2SAndroid Build Coastguard Worker {
309*5e7646d2SAndroid Build Coastguard Worker /*
310*5e7646d2SAndroid Build Coastguard Worker * Return an error, since attributes-charset,
311*5e7646d2SAndroid Build Coastguard Worker * attributes-natural-language, and printer-uri/job-uri are required
312*5e7646d2SAndroid Build Coastguard Worker * for all operations.
313*5e7646d2SAndroid Build Coastguard Worker */
314*5e7646d2SAndroid Build Coastguard Worker
315*5e7646d2SAndroid Build Coastguard Worker if (!charset)
316*5e7646d2SAndroid Build Coastguard Worker {
317*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_ERROR, "Missing attributes-charset attribute.");
318*5e7646d2SAndroid Build Coastguard Worker
319*5e7646d2SAndroid Build Coastguard Worker cupsdAddEvent(CUPSD_EVENT_SERVER_AUDIT, NULL, NULL, "%04X %s Missing attributes-charset attribute.", IPP_STATUS_ERROR_BAD_REQUEST, con->http->hostname);
320*5e7646d2SAndroid Build Coastguard Worker }
321*5e7646d2SAndroid Build Coastguard Worker
322*5e7646d2SAndroid Build Coastguard Worker if (!language)
323*5e7646d2SAndroid Build Coastguard Worker {
324*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_ERROR,
325*5e7646d2SAndroid Build Coastguard Worker "Missing attributes-natural-language attribute.");
326*5e7646d2SAndroid Build Coastguard Worker
327*5e7646d2SAndroid Build Coastguard Worker cupsdAddEvent(CUPSD_EVENT_SERVER_AUDIT, NULL, NULL, "%04X %s Missing attributes-natural-language attribute.", IPP_STATUS_ERROR_BAD_REQUEST, con->http->hostname);
328*5e7646d2SAndroid Build Coastguard Worker }
329*5e7646d2SAndroid Build Coastguard Worker
330*5e7646d2SAndroid Build Coastguard Worker if (!uri)
331*5e7646d2SAndroid Build Coastguard Worker {
332*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_ERROR, "Missing printer-uri, job-uri, or ppd-name attribute.");
333*5e7646d2SAndroid Build Coastguard Worker
334*5e7646d2SAndroid Build Coastguard Worker cupsdAddEvent(CUPSD_EVENT_SERVER_AUDIT, NULL, NULL, "%04X %s Missing printer-uri, job-uri, or ppd-name attribute.", IPP_STATUS_ERROR_BAD_REQUEST, con->http->hostname);
335*5e7646d2SAndroid Build Coastguard Worker }
336*5e7646d2SAndroid Build Coastguard Worker
337*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG, "Request attributes follow...");
338*5e7646d2SAndroid Build Coastguard Worker
339*5e7646d2SAndroid Build Coastguard Worker for (attr = con->request->attrs; attr; attr = attr->next)
340*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG,
341*5e7646d2SAndroid Build Coastguard Worker "attr \"%s\": group_tag = %x, value_tag = %x",
342*5e7646d2SAndroid Build Coastguard Worker attr->name ? attr->name : "(null)", attr->group_tag,
343*5e7646d2SAndroid Build Coastguard Worker attr->value_tag);
344*5e7646d2SAndroid Build Coastguard Worker
345*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG, "End of attributes...");
346*5e7646d2SAndroid Build Coastguard Worker
347*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_BAD_REQUEST,
348*5e7646d2SAndroid Build Coastguard Worker _("Missing required attributes."));
349*5e7646d2SAndroid Build Coastguard Worker }
350*5e7646d2SAndroid Build Coastguard Worker else
351*5e7646d2SAndroid Build Coastguard Worker {
352*5e7646d2SAndroid Build Coastguard Worker /*
353*5e7646d2SAndroid Build Coastguard Worker * OK, all the checks pass so far; validate "requesting-user-name"
354*5e7646d2SAndroid Build Coastguard Worker * attribute value...
355*5e7646d2SAndroid Build Coastguard Worker */
356*5e7646d2SAndroid Build Coastguard Worker
357*5e7646d2SAndroid Build Coastguard Worker if ((username = ippFindAttribute(con->request, "requesting-user-name", IPP_TAG_ZERO)) != NULL)
358*5e7646d2SAndroid Build Coastguard Worker {
359*5e7646d2SAndroid Build Coastguard Worker /*
360*5e7646d2SAndroid Build Coastguard Worker * Validate "requesting-user-name"...
361*5e7646d2SAndroid Build Coastguard Worker */
362*5e7646d2SAndroid Build Coastguard Worker
363*5e7646d2SAndroid Build Coastguard Worker if (username->group_tag != IPP_TAG_OPERATION && StrictConformance)
364*5e7646d2SAndroid Build Coastguard Worker {
365*5e7646d2SAndroid Build Coastguard Worker cupsdAddEvent(CUPSD_EVENT_SERVER_AUDIT, NULL, NULL, "%04X %s \"requesting-user-name\" attribute in wrong group.", IPP_STATUS_ERROR_BAD_REQUEST, con->http->hostname);
366*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_STATUS_ERROR_BAD_REQUEST, _("\"requesting-user-name\" attribute in wrong group."));
367*5e7646d2SAndroid Build Coastguard Worker valid = 0;
368*5e7646d2SAndroid Build Coastguard Worker }
369*5e7646d2SAndroid Build Coastguard Worker else if (username->value_tag != IPP_TAG_NAME && username->value_tag != IPP_TAG_NAMELANG)
370*5e7646d2SAndroid Build Coastguard Worker {
371*5e7646d2SAndroid Build Coastguard Worker cupsdAddEvent(CUPSD_EVENT_SERVER_AUDIT, NULL, NULL, "%04X %s \"requesting-user-name\" attribute with wrong syntax.", IPP_STATUS_ERROR_ATTRIBUTES_OR_VALUES, con->http->hostname);
372*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_STATUS_ERROR_ATTRIBUTES_OR_VALUES, _("\"requesting-user-name\" attribute with wrong syntax."));
373*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippCopyAttribute(con->response, username, 0)) != NULL)
374*5e7646d2SAndroid Build Coastguard Worker attr->group_tag = IPP_TAG_UNSUPPORTED_GROUP;
375*5e7646d2SAndroid Build Coastguard Worker valid = 0;
376*5e7646d2SAndroid Build Coastguard Worker }
377*5e7646d2SAndroid Build Coastguard Worker else if (!ippValidateAttribute(username))
378*5e7646d2SAndroid Build Coastguard Worker {
379*5e7646d2SAndroid Build Coastguard Worker cupsdAddEvent(CUPSD_EVENT_SERVER_AUDIT, NULL, NULL, "%04X %s \"requesting-user-name\" attribute with bad value.", IPP_STATUS_ERROR_ATTRIBUTES_OR_VALUES, con->http->hostname);
380*5e7646d2SAndroid Build Coastguard Worker
381*5e7646d2SAndroid Build Coastguard Worker if (StrictConformance)
382*5e7646d2SAndroid Build Coastguard Worker {
383*5e7646d2SAndroid Build Coastguard Worker /*
384*5e7646d2SAndroid Build Coastguard Worker * Throw an error...
385*5e7646d2SAndroid Build Coastguard Worker */
386*5e7646d2SAndroid Build Coastguard Worker
387*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_STATUS_ERROR_ATTRIBUTES_OR_VALUES, _("\"requesting-user-name\" attribute with wrong syntax."));
388*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippCopyAttribute(con->response, username, 0)) != NULL)
389*5e7646d2SAndroid Build Coastguard Worker attr->group_tag = IPP_TAG_UNSUPPORTED_GROUP;
390*5e7646d2SAndroid Build Coastguard Worker valid = 0;
391*5e7646d2SAndroid Build Coastguard Worker }
392*5e7646d2SAndroid Build Coastguard Worker else
393*5e7646d2SAndroid Build Coastguard Worker {
394*5e7646d2SAndroid Build Coastguard Worker /*
395*5e7646d2SAndroid Build Coastguard Worker * Map bad "requesting-user-name" to 'anonymous'...
396*5e7646d2SAndroid Build Coastguard Worker */
397*5e7646d2SAndroid Build Coastguard Worker
398*5e7646d2SAndroid Build Coastguard Worker ippSetString(con->request, &username, 0, "anonymous");
399*5e7646d2SAndroid Build Coastguard Worker }
400*5e7646d2SAndroid Build Coastguard Worker }
401*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(username->values[0].string.text, "root") && _cups_strcasecmp(con->http->hostname, "localhost") && strcmp(con->username, "root"))
402*5e7646d2SAndroid Build Coastguard Worker {
403*5e7646d2SAndroid Build Coastguard Worker /*
404*5e7646d2SAndroid Build Coastguard Worker * Remote unauthenticated user masquerading as local root...
405*5e7646d2SAndroid Build Coastguard Worker */
406*5e7646d2SAndroid Build Coastguard Worker
407*5e7646d2SAndroid Build Coastguard Worker ippSetString(con->request, &username, 0, RemoteRoot);
408*5e7646d2SAndroid Build Coastguard Worker }
409*5e7646d2SAndroid Build Coastguard Worker }
410*5e7646d2SAndroid Build Coastguard Worker
411*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippFindAttribute(con->request, "notify-subscription-id", IPP_TAG_INTEGER)) != NULL)
412*5e7646d2SAndroid Build Coastguard Worker sub_id = attr->values[0].integer;
413*5e7646d2SAndroid Build Coastguard Worker else
414*5e7646d2SAndroid Build Coastguard Worker sub_id = 0;
415*5e7646d2SAndroid Build Coastguard Worker
416*5e7646d2SAndroid Build Coastguard Worker if (valid)
417*5e7646d2SAndroid Build Coastguard Worker {
418*5e7646d2SAndroid Build Coastguard Worker /*
419*5e7646d2SAndroid Build Coastguard Worker * Try processing the operation...
420*5e7646d2SAndroid Build Coastguard Worker */
421*5e7646d2SAndroid Build Coastguard Worker
422*5e7646d2SAndroid Build Coastguard Worker if (uri)
423*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG, "%s %s", ippOpString(con->request->request.op.operation_id), uri->values[0].string.text);
424*5e7646d2SAndroid Build Coastguard Worker else
425*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG, "%s", ippOpString(con->request->request.op.operation_id));
426*5e7646d2SAndroid Build Coastguard Worker
427*5e7646d2SAndroid Build Coastguard Worker switch (con->request->request.op.operation_id)
428*5e7646d2SAndroid Build Coastguard Worker {
429*5e7646d2SAndroid Build Coastguard Worker case IPP_OP_PRINT_JOB :
430*5e7646d2SAndroid Build Coastguard Worker print_job(con, uri);
431*5e7646d2SAndroid Build Coastguard Worker break;
432*5e7646d2SAndroid Build Coastguard Worker
433*5e7646d2SAndroid Build Coastguard Worker case IPP_OP_VALIDATE_JOB :
434*5e7646d2SAndroid Build Coastguard Worker validate_job(con, uri);
435*5e7646d2SAndroid Build Coastguard Worker break;
436*5e7646d2SAndroid Build Coastguard Worker
437*5e7646d2SAndroid Build Coastguard Worker case IPP_OP_CREATE_JOB :
438*5e7646d2SAndroid Build Coastguard Worker create_job(con, uri);
439*5e7646d2SAndroid Build Coastguard Worker break;
440*5e7646d2SAndroid Build Coastguard Worker
441*5e7646d2SAndroid Build Coastguard Worker case IPP_OP_SEND_DOCUMENT :
442*5e7646d2SAndroid Build Coastguard Worker send_document(con, uri);
443*5e7646d2SAndroid Build Coastguard Worker break;
444*5e7646d2SAndroid Build Coastguard Worker
445*5e7646d2SAndroid Build Coastguard Worker case IPP_OP_CANCEL_JOB :
446*5e7646d2SAndroid Build Coastguard Worker cancel_job(con, uri);
447*5e7646d2SAndroid Build Coastguard Worker break;
448*5e7646d2SAndroid Build Coastguard Worker
449*5e7646d2SAndroid Build Coastguard Worker case IPP_OP_GET_JOB_ATTRIBUTES :
450*5e7646d2SAndroid Build Coastguard Worker get_job_attrs(con, uri);
451*5e7646d2SAndroid Build Coastguard Worker break;
452*5e7646d2SAndroid Build Coastguard Worker
453*5e7646d2SAndroid Build Coastguard Worker case IPP_OP_GET_JOBS :
454*5e7646d2SAndroid Build Coastguard Worker get_jobs(con, uri);
455*5e7646d2SAndroid Build Coastguard Worker break;
456*5e7646d2SAndroid Build Coastguard Worker
457*5e7646d2SAndroid Build Coastguard Worker case IPP_OP_GET_PRINTER_ATTRIBUTES :
458*5e7646d2SAndroid Build Coastguard Worker get_printer_attrs(con, uri);
459*5e7646d2SAndroid Build Coastguard Worker break;
460*5e7646d2SAndroid Build Coastguard Worker
461*5e7646d2SAndroid Build Coastguard Worker case IPP_OP_GET_PRINTER_SUPPORTED_VALUES :
462*5e7646d2SAndroid Build Coastguard Worker get_printer_supported(con, uri);
463*5e7646d2SAndroid Build Coastguard Worker break;
464*5e7646d2SAndroid Build Coastguard Worker
465*5e7646d2SAndroid Build Coastguard Worker case IPP_OP_HOLD_JOB :
466*5e7646d2SAndroid Build Coastguard Worker hold_job(con, uri);
467*5e7646d2SAndroid Build Coastguard Worker break;
468*5e7646d2SAndroid Build Coastguard Worker
469*5e7646d2SAndroid Build Coastguard Worker case IPP_OP_RELEASE_JOB :
470*5e7646d2SAndroid Build Coastguard Worker release_job(con, uri);
471*5e7646d2SAndroid Build Coastguard Worker break;
472*5e7646d2SAndroid Build Coastguard Worker
473*5e7646d2SAndroid Build Coastguard Worker case IPP_OP_RESTART_JOB :
474*5e7646d2SAndroid Build Coastguard Worker restart_job(con, uri);
475*5e7646d2SAndroid Build Coastguard Worker break;
476*5e7646d2SAndroid Build Coastguard Worker
477*5e7646d2SAndroid Build Coastguard Worker case IPP_OP_PAUSE_PRINTER :
478*5e7646d2SAndroid Build Coastguard Worker stop_printer(con, uri);
479*5e7646d2SAndroid Build Coastguard Worker break;
480*5e7646d2SAndroid Build Coastguard Worker
481*5e7646d2SAndroid Build Coastguard Worker case IPP_OP_RESUME_PRINTER :
482*5e7646d2SAndroid Build Coastguard Worker start_printer(con, uri);
483*5e7646d2SAndroid Build Coastguard Worker break;
484*5e7646d2SAndroid Build Coastguard Worker
485*5e7646d2SAndroid Build Coastguard Worker case IPP_OP_PURGE_JOBS :
486*5e7646d2SAndroid Build Coastguard Worker case IPP_OP_CANCEL_JOBS :
487*5e7646d2SAndroid Build Coastguard Worker case IPP_OP_CANCEL_MY_JOBS :
488*5e7646d2SAndroid Build Coastguard Worker cancel_all_jobs(con, uri);
489*5e7646d2SAndroid Build Coastguard Worker break;
490*5e7646d2SAndroid Build Coastguard Worker
491*5e7646d2SAndroid Build Coastguard Worker case IPP_OP_SET_JOB_ATTRIBUTES :
492*5e7646d2SAndroid Build Coastguard Worker set_job_attrs(con, uri);
493*5e7646d2SAndroid Build Coastguard Worker break;
494*5e7646d2SAndroid Build Coastguard Worker
495*5e7646d2SAndroid Build Coastguard Worker case IPP_OP_SET_PRINTER_ATTRIBUTES :
496*5e7646d2SAndroid Build Coastguard Worker set_printer_attrs(con, uri);
497*5e7646d2SAndroid Build Coastguard Worker break;
498*5e7646d2SAndroid Build Coastguard Worker
499*5e7646d2SAndroid Build Coastguard Worker case IPP_OP_HOLD_NEW_JOBS :
500*5e7646d2SAndroid Build Coastguard Worker hold_new_jobs(con, uri);
501*5e7646d2SAndroid Build Coastguard Worker break;
502*5e7646d2SAndroid Build Coastguard Worker
503*5e7646d2SAndroid Build Coastguard Worker case IPP_OP_RELEASE_HELD_NEW_JOBS :
504*5e7646d2SAndroid Build Coastguard Worker release_held_new_jobs(con, uri);
505*5e7646d2SAndroid Build Coastguard Worker break;
506*5e7646d2SAndroid Build Coastguard Worker
507*5e7646d2SAndroid Build Coastguard Worker case IPP_OP_CLOSE_JOB :
508*5e7646d2SAndroid Build Coastguard Worker close_job(con, uri);
509*5e7646d2SAndroid Build Coastguard Worker break;
510*5e7646d2SAndroid Build Coastguard Worker
511*5e7646d2SAndroid Build Coastguard Worker case IPP_OP_CUPS_GET_DEFAULT :
512*5e7646d2SAndroid Build Coastguard Worker get_default(con);
513*5e7646d2SAndroid Build Coastguard Worker break;
514*5e7646d2SAndroid Build Coastguard Worker
515*5e7646d2SAndroid Build Coastguard Worker case IPP_OP_CUPS_GET_PRINTERS :
516*5e7646d2SAndroid Build Coastguard Worker get_printers(con, 0);
517*5e7646d2SAndroid Build Coastguard Worker break;
518*5e7646d2SAndroid Build Coastguard Worker
519*5e7646d2SAndroid Build Coastguard Worker case IPP_OP_CUPS_GET_CLASSES :
520*5e7646d2SAndroid Build Coastguard Worker get_printers(con, CUPS_PRINTER_CLASS);
521*5e7646d2SAndroid Build Coastguard Worker break;
522*5e7646d2SAndroid Build Coastguard Worker
523*5e7646d2SAndroid Build Coastguard Worker case IPP_OP_CUPS_ADD_MODIFY_PRINTER :
524*5e7646d2SAndroid Build Coastguard Worker add_printer(con, uri);
525*5e7646d2SAndroid Build Coastguard Worker break;
526*5e7646d2SAndroid Build Coastguard Worker
527*5e7646d2SAndroid Build Coastguard Worker case IPP_OP_CUPS_DELETE_PRINTER :
528*5e7646d2SAndroid Build Coastguard Worker delete_printer(con, uri);
529*5e7646d2SAndroid Build Coastguard Worker break;
530*5e7646d2SAndroid Build Coastguard Worker
531*5e7646d2SAndroid Build Coastguard Worker case IPP_OP_CUPS_ADD_MODIFY_CLASS :
532*5e7646d2SAndroid Build Coastguard Worker add_class(con, uri);
533*5e7646d2SAndroid Build Coastguard Worker break;
534*5e7646d2SAndroid Build Coastguard Worker
535*5e7646d2SAndroid Build Coastguard Worker case IPP_OP_CUPS_DELETE_CLASS :
536*5e7646d2SAndroid Build Coastguard Worker delete_printer(con, uri);
537*5e7646d2SAndroid Build Coastguard Worker break;
538*5e7646d2SAndroid Build Coastguard Worker
539*5e7646d2SAndroid Build Coastguard Worker case IPP_OP_CUPS_ACCEPT_JOBS :
540*5e7646d2SAndroid Build Coastguard Worker case IPP_OP_ENABLE_PRINTER :
541*5e7646d2SAndroid Build Coastguard Worker accept_jobs(con, uri);
542*5e7646d2SAndroid Build Coastguard Worker break;
543*5e7646d2SAndroid Build Coastguard Worker
544*5e7646d2SAndroid Build Coastguard Worker case IPP_OP_CUPS_REJECT_JOBS :
545*5e7646d2SAndroid Build Coastguard Worker case IPP_OP_DISABLE_PRINTER :
546*5e7646d2SAndroid Build Coastguard Worker reject_jobs(con, uri);
547*5e7646d2SAndroid Build Coastguard Worker break;
548*5e7646d2SAndroid Build Coastguard Worker
549*5e7646d2SAndroid Build Coastguard Worker case IPP_OP_CUPS_SET_DEFAULT :
550*5e7646d2SAndroid Build Coastguard Worker set_default(con, uri);
551*5e7646d2SAndroid Build Coastguard Worker break;
552*5e7646d2SAndroid Build Coastguard Worker
553*5e7646d2SAndroid Build Coastguard Worker case IPP_OP_CUPS_GET_DEVICES :
554*5e7646d2SAndroid Build Coastguard Worker get_devices(con);
555*5e7646d2SAndroid Build Coastguard Worker break;
556*5e7646d2SAndroid Build Coastguard Worker
557*5e7646d2SAndroid Build Coastguard Worker case IPP_OP_CUPS_GET_DOCUMENT :
558*5e7646d2SAndroid Build Coastguard Worker get_document(con, uri);
559*5e7646d2SAndroid Build Coastguard Worker break;
560*5e7646d2SAndroid Build Coastguard Worker
561*5e7646d2SAndroid Build Coastguard Worker case IPP_OP_CUPS_GET_PPD :
562*5e7646d2SAndroid Build Coastguard Worker get_ppd(con, uri);
563*5e7646d2SAndroid Build Coastguard Worker break;
564*5e7646d2SAndroid Build Coastguard Worker
565*5e7646d2SAndroid Build Coastguard Worker case IPP_OP_CUPS_GET_PPDS :
566*5e7646d2SAndroid Build Coastguard Worker get_ppds(con);
567*5e7646d2SAndroid Build Coastguard Worker break;
568*5e7646d2SAndroid Build Coastguard Worker
569*5e7646d2SAndroid Build Coastguard Worker case IPP_OP_CUPS_MOVE_JOB :
570*5e7646d2SAndroid Build Coastguard Worker move_job(con, uri);
571*5e7646d2SAndroid Build Coastguard Worker break;
572*5e7646d2SAndroid Build Coastguard Worker
573*5e7646d2SAndroid Build Coastguard Worker case IPP_OP_CUPS_AUTHENTICATE_JOB :
574*5e7646d2SAndroid Build Coastguard Worker authenticate_job(con, uri);
575*5e7646d2SAndroid Build Coastguard Worker break;
576*5e7646d2SAndroid Build Coastguard Worker
577*5e7646d2SAndroid Build Coastguard Worker case IPP_OP_CREATE_PRINTER_SUBSCRIPTIONS :
578*5e7646d2SAndroid Build Coastguard Worker case IPP_OP_CREATE_JOB_SUBSCRIPTIONS :
579*5e7646d2SAndroid Build Coastguard Worker create_subscriptions(con, uri);
580*5e7646d2SAndroid Build Coastguard Worker break;
581*5e7646d2SAndroid Build Coastguard Worker
582*5e7646d2SAndroid Build Coastguard Worker case IPP_OP_GET_SUBSCRIPTION_ATTRIBUTES :
583*5e7646d2SAndroid Build Coastguard Worker get_subscription_attrs(con, sub_id);
584*5e7646d2SAndroid Build Coastguard Worker break;
585*5e7646d2SAndroid Build Coastguard Worker
586*5e7646d2SAndroid Build Coastguard Worker case IPP_OP_GET_SUBSCRIPTIONS :
587*5e7646d2SAndroid Build Coastguard Worker get_subscriptions(con, uri);
588*5e7646d2SAndroid Build Coastguard Worker break;
589*5e7646d2SAndroid Build Coastguard Worker
590*5e7646d2SAndroid Build Coastguard Worker case IPP_OP_RENEW_SUBSCRIPTION :
591*5e7646d2SAndroid Build Coastguard Worker renew_subscription(con, sub_id);
592*5e7646d2SAndroid Build Coastguard Worker break;
593*5e7646d2SAndroid Build Coastguard Worker
594*5e7646d2SAndroid Build Coastguard Worker case IPP_OP_CANCEL_SUBSCRIPTION :
595*5e7646d2SAndroid Build Coastguard Worker cancel_subscription(con, sub_id);
596*5e7646d2SAndroid Build Coastguard Worker break;
597*5e7646d2SAndroid Build Coastguard Worker
598*5e7646d2SAndroid Build Coastguard Worker case IPP_OP_GET_NOTIFICATIONS :
599*5e7646d2SAndroid Build Coastguard Worker get_notifications(con);
600*5e7646d2SAndroid Build Coastguard Worker break;
601*5e7646d2SAndroid Build Coastguard Worker
602*5e7646d2SAndroid Build Coastguard Worker case IPP_OP_CUPS_CREATE_LOCAL_PRINTER :
603*5e7646d2SAndroid Build Coastguard Worker create_local_printer(con);
604*5e7646d2SAndroid Build Coastguard Worker break;
605*5e7646d2SAndroid Build Coastguard Worker
606*5e7646d2SAndroid Build Coastguard Worker default :
607*5e7646d2SAndroid Build Coastguard Worker cupsdAddEvent(CUPSD_EVENT_SERVER_AUDIT, NULL, NULL, "%04X %s Operation %04X (%s) not supported.", IPP_STATUS_ERROR_OPERATION_NOT_SUPPORTED, con->http->hostname, con->request->request.op.operation_id, ippOpString(con->request->request.op.operation_id));
608*5e7646d2SAndroid Build Coastguard Worker
609*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_STATUS_ERROR_OPERATION_NOT_SUPPORTED, _("%s not supported."), ippOpString(con->request->request.op.operation_id));
610*5e7646d2SAndroid Build Coastguard Worker break;
611*5e7646d2SAndroid Build Coastguard Worker }
612*5e7646d2SAndroid Build Coastguard Worker }
613*5e7646d2SAndroid Build Coastguard Worker }
614*5e7646d2SAndroid Build Coastguard Worker }
615*5e7646d2SAndroid Build Coastguard Worker }
616*5e7646d2SAndroid Build Coastguard Worker
617*5e7646d2SAndroid Build Coastguard Worker if (con->response)
618*5e7646d2SAndroid Build Coastguard Worker {
619*5e7646d2SAndroid Build Coastguard Worker /*
620*5e7646d2SAndroid Build Coastguard Worker * Sending data from the scheduler...
621*5e7646d2SAndroid Build Coastguard Worker */
622*5e7646d2SAndroid Build Coastguard Worker
623*5e7646d2SAndroid Build Coastguard Worker cupsdLogClient(con, con->response->request.status.status_code >= IPP_STATUS_ERROR_BAD_REQUEST && con->response->request.status.status_code != IPP_STATUS_ERROR_NOT_FOUND ? CUPSD_LOG_ERROR : CUPSD_LOG_DEBUG, "Returning IPP %s for %s (%s) from %s.", ippErrorString(con->response->request.status.status_code), ippOpString(con->request->request.op.operation_id), uri ? uri->values[0].string.text : "no URI", con->http->hostname);
624*5e7646d2SAndroid Build Coastguard Worker
625*5e7646d2SAndroid Build Coastguard Worker httpClearFields(con->http);
626*5e7646d2SAndroid Build Coastguard Worker
627*5e7646d2SAndroid Build Coastguard Worker #ifdef CUPSD_USE_CHUNKING
628*5e7646d2SAndroid Build Coastguard Worker /*
629*5e7646d2SAndroid Build Coastguard Worker * Because older versions of CUPS (1.1.17 and older) and some IPP
630*5e7646d2SAndroid Build Coastguard Worker * clients do not implement chunking properly, we cannot use
631*5e7646d2SAndroid Build Coastguard Worker * chunking by default. This may become the default in future
632*5e7646d2SAndroid Build Coastguard Worker * CUPS releases, or we might add a configuration directive for
633*5e7646d2SAndroid Build Coastguard Worker * it.
634*5e7646d2SAndroid Build Coastguard Worker */
635*5e7646d2SAndroid Build Coastguard Worker
636*5e7646d2SAndroid Build Coastguard Worker if (con->http->version == HTTP_1_1)
637*5e7646d2SAndroid Build Coastguard Worker {
638*5e7646d2SAndroid Build Coastguard Worker cupsdLogClient(con, CUPSD_LOG_DEBUG, "Transfer-Encoding: chunked");
639*5e7646d2SAndroid Build Coastguard Worker cupsdSetLength(con->http, 0);
640*5e7646d2SAndroid Build Coastguard Worker }
641*5e7646d2SAndroid Build Coastguard Worker else
642*5e7646d2SAndroid Build Coastguard Worker #endif /* CUPSD_USE_CHUNKING */
643*5e7646d2SAndroid Build Coastguard Worker {
644*5e7646d2SAndroid Build Coastguard Worker size_t length; /* Length of response */
645*5e7646d2SAndroid Build Coastguard Worker
646*5e7646d2SAndroid Build Coastguard Worker
647*5e7646d2SAndroid Build Coastguard Worker length = ippLength(con->response);
648*5e7646d2SAndroid Build Coastguard Worker
649*5e7646d2SAndroid Build Coastguard Worker if (con->file >= 0 && !con->pipe_pid)
650*5e7646d2SAndroid Build Coastguard Worker {
651*5e7646d2SAndroid Build Coastguard Worker struct stat fileinfo; /* File information */
652*5e7646d2SAndroid Build Coastguard Worker
653*5e7646d2SAndroid Build Coastguard Worker if (!fstat(con->file, &fileinfo))
654*5e7646d2SAndroid Build Coastguard Worker length += (size_t)fileinfo.st_size;
655*5e7646d2SAndroid Build Coastguard Worker }
656*5e7646d2SAndroid Build Coastguard Worker
657*5e7646d2SAndroid Build Coastguard Worker cupsdLogClient(con, CUPSD_LOG_DEBUG, "Content-Length: " CUPS_LLFMT, CUPS_LLCAST length);
658*5e7646d2SAndroid Build Coastguard Worker httpSetLength(con->http, length);
659*5e7646d2SAndroid Build Coastguard Worker }
660*5e7646d2SAndroid Build Coastguard Worker
661*5e7646d2SAndroid Build Coastguard Worker if (cupsdSendHeader(con, HTTP_OK, "application/ipp", CUPSD_AUTH_NONE))
662*5e7646d2SAndroid Build Coastguard Worker {
663*5e7646d2SAndroid Build Coastguard Worker /*
664*5e7646d2SAndroid Build Coastguard Worker * Tell the caller the response header was sent successfully...
665*5e7646d2SAndroid Build Coastguard Worker */
666*5e7646d2SAndroid Build Coastguard Worker
667*5e7646d2SAndroid Build Coastguard Worker cupsdAddSelect(httpGetFd(con->http), (cupsd_selfunc_t)cupsdReadClient, (cupsd_selfunc_t)cupsdWriteClient, con);
668*5e7646d2SAndroid Build Coastguard Worker
669*5e7646d2SAndroid Build Coastguard Worker return (1);
670*5e7646d2SAndroid Build Coastguard Worker }
671*5e7646d2SAndroid Build Coastguard Worker else
672*5e7646d2SAndroid Build Coastguard Worker {
673*5e7646d2SAndroid Build Coastguard Worker /*
674*5e7646d2SAndroid Build Coastguard Worker * Tell the caller the response header could not be sent...
675*5e7646d2SAndroid Build Coastguard Worker */
676*5e7646d2SAndroid Build Coastguard Worker
677*5e7646d2SAndroid Build Coastguard Worker return (0);
678*5e7646d2SAndroid Build Coastguard Worker }
679*5e7646d2SAndroid Build Coastguard Worker }
680*5e7646d2SAndroid Build Coastguard Worker else
681*5e7646d2SAndroid Build Coastguard Worker {
682*5e7646d2SAndroid Build Coastguard Worker /*
683*5e7646d2SAndroid Build Coastguard Worker * Sending data from a subprocess like cups-deviced; tell the caller
684*5e7646d2SAndroid Build Coastguard Worker * everything is A-OK so far...
685*5e7646d2SAndroid Build Coastguard Worker */
686*5e7646d2SAndroid Build Coastguard Worker
687*5e7646d2SAndroid Build Coastguard Worker return (1);
688*5e7646d2SAndroid Build Coastguard Worker }
689*5e7646d2SAndroid Build Coastguard Worker }
690*5e7646d2SAndroid Build Coastguard Worker
691*5e7646d2SAndroid Build Coastguard Worker
692*5e7646d2SAndroid Build Coastguard Worker /*
693*5e7646d2SAndroid Build Coastguard Worker * 'cupsdTimeoutJob()' - Timeout a job waiting on job files.
694*5e7646d2SAndroid Build Coastguard Worker */
695*5e7646d2SAndroid Build Coastguard Worker
696*5e7646d2SAndroid Build Coastguard Worker int /* O - 0 on success, -1 on error */
cupsdTimeoutJob(cupsd_job_t * job)697*5e7646d2SAndroid Build Coastguard Worker cupsdTimeoutJob(cupsd_job_t *job) /* I - Job to timeout */
698*5e7646d2SAndroid Build Coastguard Worker {
699*5e7646d2SAndroid Build Coastguard Worker cupsd_printer_t *printer; /* Destination printer or class */
700*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *attr; /* job-sheets attribute */
701*5e7646d2SAndroid Build Coastguard Worker int kbytes; /* Kilobytes in banner */
702*5e7646d2SAndroid Build Coastguard Worker
703*5e7646d2SAndroid Build Coastguard Worker
704*5e7646d2SAndroid Build Coastguard Worker job->pending_timeout = 0;
705*5e7646d2SAndroid Build Coastguard Worker
706*5e7646d2SAndroid Build Coastguard Worker /*
707*5e7646d2SAndroid Build Coastguard Worker * See if we need to add the ending sheet...
708*5e7646d2SAndroid Build Coastguard Worker */
709*5e7646d2SAndroid Build Coastguard Worker
710*5e7646d2SAndroid Build Coastguard Worker if (!cupsdLoadJob(job))
711*5e7646d2SAndroid Build Coastguard Worker return (-1);
712*5e7646d2SAndroid Build Coastguard Worker
713*5e7646d2SAndroid Build Coastguard Worker printer = cupsdFindDest(job->dest);
714*5e7646d2SAndroid Build Coastguard Worker attr = ippFindAttribute(job->attrs, "job-sheets", IPP_TAG_NAME);
715*5e7646d2SAndroid Build Coastguard Worker
716*5e7646d2SAndroid Build Coastguard Worker if (printer && !(printer->type & CUPS_PRINTER_REMOTE) &&
717*5e7646d2SAndroid Build Coastguard Worker attr && attr->num_values > 1)
718*5e7646d2SAndroid Build Coastguard Worker {
719*5e7646d2SAndroid Build Coastguard Worker /*
720*5e7646d2SAndroid Build Coastguard Worker * Yes...
721*5e7646d2SAndroid Build Coastguard Worker */
722*5e7646d2SAndroid Build Coastguard Worker
723*5e7646d2SAndroid Build Coastguard Worker cupsdLogJob(job, CUPSD_LOG_INFO, "Adding end banner page \"%s\".",
724*5e7646d2SAndroid Build Coastguard Worker attr->values[1].string.text);
725*5e7646d2SAndroid Build Coastguard Worker
726*5e7646d2SAndroid Build Coastguard Worker if ((kbytes = copy_banner(NULL, job, attr->values[1].string.text)) < 0)
727*5e7646d2SAndroid Build Coastguard Worker return (-1);
728*5e7646d2SAndroid Build Coastguard Worker
729*5e7646d2SAndroid Build Coastguard Worker cupsdUpdateQuota(printer, job->username, 0, kbytes);
730*5e7646d2SAndroid Build Coastguard Worker }
731*5e7646d2SAndroid Build Coastguard Worker
732*5e7646d2SAndroid Build Coastguard Worker return (0);
733*5e7646d2SAndroid Build Coastguard Worker }
734*5e7646d2SAndroid Build Coastguard Worker
735*5e7646d2SAndroid Build Coastguard Worker
736*5e7646d2SAndroid Build Coastguard Worker /*
737*5e7646d2SAndroid Build Coastguard Worker * 'accept_jobs()' - Accept print jobs to a printer.
738*5e7646d2SAndroid Build Coastguard Worker */
739*5e7646d2SAndroid Build Coastguard Worker
740*5e7646d2SAndroid Build Coastguard Worker static void
accept_jobs(cupsd_client_t * con,ipp_attribute_t * uri)741*5e7646d2SAndroid Build Coastguard Worker accept_jobs(cupsd_client_t *con, /* I - Client connection */
742*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *uri) /* I - Printer or class URI */
743*5e7646d2SAndroid Build Coastguard Worker {
744*5e7646d2SAndroid Build Coastguard Worker http_status_t status; /* Policy status */
745*5e7646d2SAndroid Build Coastguard Worker cups_ptype_t dtype; /* Destination type (printer/class) */
746*5e7646d2SAndroid Build Coastguard Worker cupsd_printer_t *printer; /* Printer data */
747*5e7646d2SAndroid Build Coastguard Worker
748*5e7646d2SAndroid Build Coastguard Worker
749*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG2, "accept_jobs(%p[%d], %s)", con,
750*5e7646d2SAndroid Build Coastguard Worker con->number, uri->values[0].string.text);
751*5e7646d2SAndroid Build Coastguard Worker
752*5e7646d2SAndroid Build Coastguard Worker /*
753*5e7646d2SAndroid Build Coastguard Worker * Is the destination valid?
754*5e7646d2SAndroid Build Coastguard Worker */
755*5e7646d2SAndroid Build Coastguard Worker
756*5e7646d2SAndroid Build Coastguard Worker if (!cupsdValidateDest(uri->values[0].string.text, &dtype, &printer))
757*5e7646d2SAndroid Build Coastguard Worker {
758*5e7646d2SAndroid Build Coastguard Worker /*
759*5e7646d2SAndroid Build Coastguard Worker * Bad URI...
760*5e7646d2SAndroid Build Coastguard Worker */
761*5e7646d2SAndroid Build Coastguard Worker
762*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_NOT_FOUND,
763*5e7646d2SAndroid Build Coastguard Worker _("The printer or class does not exist."));
764*5e7646d2SAndroid Build Coastguard Worker return;
765*5e7646d2SAndroid Build Coastguard Worker }
766*5e7646d2SAndroid Build Coastguard Worker
767*5e7646d2SAndroid Build Coastguard Worker /*
768*5e7646d2SAndroid Build Coastguard Worker * Check policy...
769*5e7646d2SAndroid Build Coastguard Worker */
770*5e7646d2SAndroid Build Coastguard Worker
771*5e7646d2SAndroid Build Coastguard Worker if ((status = cupsdCheckPolicy(printer->op_policy_ptr, con, NULL)) != HTTP_OK)
772*5e7646d2SAndroid Build Coastguard Worker {
773*5e7646d2SAndroid Build Coastguard Worker send_http_error(con, status, printer);
774*5e7646d2SAndroid Build Coastguard Worker return;
775*5e7646d2SAndroid Build Coastguard Worker }
776*5e7646d2SAndroid Build Coastguard Worker
777*5e7646d2SAndroid Build Coastguard Worker /*
778*5e7646d2SAndroid Build Coastguard Worker * Accept jobs sent to the printer...
779*5e7646d2SAndroid Build Coastguard Worker */
780*5e7646d2SAndroid Build Coastguard Worker
781*5e7646d2SAndroid Build Coastguard Worker printer->accepting = 1;
782*5e7646d2SAndroid Build Coastguard Worker printer->state_message[0] = '\0';
783*5e7646d2SAndroid Build Coastguard Worker
784*5e7646d2SAndroid Build Coastguard Worker cupsdAddEvent(CUPSD_EVENT_PRINTER_STATE, printer, NULL,
785*5e7646d2SAndroid Build Coastguard Worker "Now accepting jobs.");
786*5e7646d2SAndroid Build Coastguard Worker
787*5e7646d2SAndroid Build Coastguard Worker if (dtype & CUPS_PRINTER_CLASS)
788*5e7646d2SAndroid Build Coastguard Worker {
789*5e7646d2SAndroid Build Coastguard Worker cupsdMarkDirty(CUPSD_DIRTY_CLASSES);
790*5e7646d2SAndroid Build Coastguard Worker
791*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_INFO, "Class \"%s\" now accepting jobs (\"%s\").",
792*5e7646d2SAndroid Build Coastguard Worker printer->name, get_username(con));
793*5e7646d2SAndroid Build Coastguard Worker }
794*5e7646d2SAndroid Build Coastguard Worker else
795*5e7646d2SAndroid Build Coastguard Worker {
796*5e7646d2SAndroid Build Coastguard Worker cupsdMarkDirty(CUPSD_DIRTY_PRINTERS);
797*5e7646d2SAndroid Build Coastguard Worker
798*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_INFO,
799*5e7646d2SAndroid Build Coastguard Worker "Printer \"%s\" now accepting jobs (\"%s\").",
800*5e7646d2SAndroid Build Coastguard Worker printer->name, get_username(con));
801*5e7646d2SAndroid Build Coastguard Worker }
802*5e7646d2SAndroid Build Coastguard Worker
803*5e7646d2SAndroid Build Coastguard Worker /*
804*5e7646d2SAndroid Build Coastguard Worker * Everything was ok, so return OK status...
805*5e7646d2SAndroid Build Coastguard Worker */
806*5e7646d2SAndroid Build Coastguard Worker
807*5e7646d2SAndroid Build Coastguard Worker con->response->request.status.status_code = IPP_OK;
808*5e7646d2SAndroid Build Coastguard Worker }
809*5e7646d2SAndroid Build Coastguard Worker
810*5e7646d2SAndroid Build Coastguard Worker
811*5e7646d2SAndroid Build Coastguard Worker /*
812*5e7646d2SAndroid Build Coastguard Worker * 'add_class()' - Add a class to the system.
813*5e7646d2SAndroid Build Coastguard Worker */
814*5e7646d2SAndroid Build Coastguard Worker
815*5e7646d2SAndroid Build Coastguard Worker static void
add_class(cupsd_client_t * con,ipp_attribute_t * uri)816*5e7646d2SAndroid Build Coastguard Worker add_class(cupsd_client_t *con, /* I - Client connection */
817*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *uri) /* I - URI of class */
818*5e7646d2SAndroid Build Coastguard Worker {
819*5e7646d2SAndroid Build Coastguard Worker http_status_t status; /* Policy status */
820*5e7646d2SAndroid Build Coastguard Worker int i; /* Looping var */
821*5e7646d2SAndroid Build Coastguard Worker char scheme[HTTP_MAX_URI], /* Method portion of URI */
822*5e7646d2SAndroid Build Coastguard Worker username[HTTP_MAX_URI], /* Username portion of URI */
823*5e7646d2SAndroid Build Coastguard Worker host[HTTP_MAX_URI], /* Host portion of URI */
824*5e7646d2SAndroid Build Coastguard Worker resource[HTTP_MAX_URI]; /* Resource portion of URI */
825*5e7646d2SAndroid Build Coastguard Worker int port; /* Port portion of URI */
826*5e7646d2SAndroid Build Coastguard Worker cupsd_printer_t *pclass, /* Class */
827*5e7646d2SAndroid Build Coastguard Worker *member; /* Member printer/class */
828*5e7646d2SAndroid Build Coastguard Worker cups_ptype_t dtype; /* Destination type */
829*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *attr; /* Printer attribute */
830*5e7646d2SAndroid Build Coastguard Worker int modify; /* Non-zero if we just modified */
831*5e7646d2SAndroid Build Coastguard Worker int need_restart_job; /* Need to restart job? */
832*5e7646d2SAndroid Build Coastguard Worker
833*5e7646d2SAndroid Build Coastguard Worker
834*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG2, "add_class(%p[%d], %s)", con,
835*5e7646d2SAndroid Build Coastguard Worker con->number, uri->values[0].string.text);
836*5e7646d2SAndroid Build Coastguard Worker
837*5e7646d2SAndroid Build Coastguard Worker /*
838*5e7646d2SAndroid Build Coastguard Worker * Do we have a valid URI?
839*5e7646d2SAndroid Build Coastguard Worker */
840*5e7646d2SAndroid Build Coastguard Worker
841*5e7646d2SAndroid Build Coastguard Worker httpSeparateURI(HTTP_URI_CODING_ALL, uri->values[0].string.text, scheme,
842*5e7646d2SAndroid Build Coastguard Worker sizeof(scheme), username, sizeof(username), host,
843*5e7646d2SAndroid Build Coastguard Worker sizeof(host), &port, resource, sizeof(resource));
844*5e7646d2SAndroid Build Coastguard Worker
845*5e7646d2SAndroid Build Coastguard Worker
846*5e7646d2SAndroid Build Coastguard Worker if (strncmp(resource, "/classes/", 9) || strlen(resource) == 9)
847*5e7646d2SAndroid Build Coastguard Worker {
848*5e7646d2SAndroid Build Coastguard Worker /*
849*5e7646d2SAndroid Build Coastguard Worker * No, return an error...
850*5e7646d2SAndroid Build Coastguard Worker */
851*5e7646d2SAndroid Build Coastguard Worker
852*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_BAD_REQUEST,
853*5e7646d2SAndroid Build Coastguard Worker _("The printer-uri must be of the form "
854*5e7646d2SAndroid Build Coastguard Worker "\"ipp://HOSTNAME/classes/CLASSNAME\"."));
855*5e7646d2SAndroid Build Coastguard Worker return;
856*5e7646d2SAndroid Build Coastguard Worker }
857*5e7646d2SAndroid Build Coastguard Worker
858*5e7646d2SAndroid Build Coastguard Worker /*
859*5e7646d2SAndroid Build Coastguard Worker * Do we have a valid printer name?
860*5e7646d2SAndroid Build Coastguard Worker */
861*5e7646d2SAndroid Build Coastguard Worker
862*5e7646d2SAndroid Build Coastguard Worker if (!validate_name(resource + 9))
863*5e7646d2SAndroid Build Coastguard Worker {
864*5e7646d2SAndroid Build Coastguard Worker /*
865*5e7646d2SAndroid Build Coastguard Worker * No, return an error...
866*5e7646d2SAndroid Build Coastguard Worker */
867*5e7646d2SAndroid Build Coastguard Worker
868*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_BAD_REQUEST,
869*5e7646d2SAndroid Build Coastguard Worker _("The printer-uri \"%s\" contains invalid characters."),
870*5e7646d2SAndroid Build Coastguard Worker uri->values[0].string.text);
871*5e7646d2SAndroid Build Coastguard Worker return;
872*5e7646d2SAndroid Build Coastguard Worker }
873*5e7646d2SAndroid Build Coastguard Worker
874*5e7646d2SAndroid Build Coastguard Worker /*
875*5e7646d2SAndroid Build Coastguard Worker * See if the class already exists; if not, create a new class...
876*5e7646d2SAndroid Build Coastguard Worker */
877*5e7646d2SAndroid Build Coastguard Worker
878*5e7646d2SAndroid Build Coastguard Worker if ((pclass = cupsdFindClass(resource + 9)) == NULL)
879*5e7646d2SAndroid Build Coastguard Worker {
880*5e7646d2SAndroid Build Coastguard Worker /*
881*5e7646d2SAndroid Build Coastguard Worker * Class doesn't exist; see if we have a printer of the same name...
882*5e7646d2SAndroid Build Coastguard Worker */
883*5e7646d2SAndroid Build Coastguard Worker
884*5e7646d2SAndroid Build Coastguard Worker if (cupsdFindPrinter(resource + 9))
885*5e7646d2SAndroid Build Coastguard Worker {
886*5e7646d2SAndroid Build Coastguard Worker /*
887*5e7646d2SAndroid Build Coastguard Worker * Yes, return an error...
888*5e7646d2SAndroid Build Coastguard Worker */
889*5e7646d2SAndroid Build Coastguard Worker
890*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_NOT_POSSIBLE,
891*5e7646d2SAndroid Build Coastguard Worker _("A printer named \"%s\" already exists."),
892*5e7646d2SAndroid Build Coastguard Worker resource + 9);
893*5e7646d2SAndroid Build Coastguard Worker return;
894*5e7646d2SAndroid Build Coastguard Worker }
895*5e7646d2SAndroid Build Coastguard Worker
896*5e7646d2SAndroid Build Coastguard Worker /*
897*5e7646d2SAndroid Build Coastguard Worker * No, check the default policy and then add the class...
898*5e7646d2SAndroid Build Coastguard Worker */
899*5e7646d2SAndroid Build Coastguard Worker
900*5e7646d2SAndroid Build Coastguard Worker if ((status = cupsdCheckPolicy(DefaultPolicyPtr, con, NULL)) != HTTP_OK)
901*5e7646d2SAndroid Build Coastguard Worker {
902*5e7646d2SAndroid Build Coastguard Worker send_http_error(con, status, NULL);
903*5e7646d2SAndroid Build Coastguard Worker return;
904*5e7646d2SAndroid Build Coastguard Worker }
905*5e7646d2SAndroid Build Coastguard Worker
906*5e7646d2SAndroid Build Coastguard Worker pclass = cupsdAddClass(resource + 9);
907*5e7646d2SAndroid Build Coastguard Worker modify = 0;
908*5e7646d2SAndroid Build Coastguard Worker
909*5e7646d2SAndroid Build Coastguard Worker pclass->printer_id = NextPrinterId ++;
910*5e7646d2SAndroid Build Coastguard Worker }
911*5e7646d2SAndroid Build Coastguard Worker else if ((status = cupsdCheckPolicy(pclass->op_policy_ptr, con,
912*5e7646d2SAndroid Build Coastguard Worker NULL)) != HTTP_OK)
913*5e7646d2SAndroid Build Coastguard Worker {
914*5e7646d2SAndroid Build Coastguard Worker send_http_error(con, status, pclass);
915*5e7646d2SAndroid Build Coastguard Worker return;
916*5e7646d2SAndroid Build Coastguard Worker }
917*5e7646d2SAndroid Build Coastguard Worker else
918*5e7646d2SAndroid Build Coastguard Worker modify = 1;
919*5e7646d2SAndroid Build Coastguard Worker
920*5e7646d2SAndroid Build Coastguard Worker /*
921*5e7646d2SAndroid Build Coastguard Worker * Look for attributes and copy them over as needed...
922*5e7646d2SAndroid Build Coastguard Worker */
923*5e7646d2SAndroid Build Coastguard Worker
924*5e7646d2SAndroid Build Coastguard Worker need_restart_job = 0;
925*5e7646d2SAndroid Build Coastguard Worker
926*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippFindAttribute(con->request, "printer-location", IPP_TAG_TEXT)) != NULL)
927*5e7646d2SAndroid Build Coastguard Worker cupsdSetString(&pclass->location, attr->values[0].string.text);
928*5e7646d2SAndroid Build Coastguard Worker
929*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippFindAttribute(con->request, "printer-geo-location", IPP_TAG_URI)) != NULL && !strncmp(attr->values[0].string.text, "geo:", 4))
930*5e7646d2SAndroid Build Coastguard Worker cupsdSetString(&pclass->geo_location, attr->values[0].string.text);
931*5e7646d2SAndroid Build Coastguard Worker
932*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippFindAttribute(con->request, "printer-organization", IPP_TAG_TEXT)) != NULL)
933*5e7646d2SAndroid Build Coastguard Worker cupsdSetString(&pclass->organization, attr->values[0].string.text);
934*5e7646d2SAndroid Build Coastguard Worker
935*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippFindAttribute(con->request, "printer-organizational-unit", IPP_TAG_TEXT)) != NULL)
936*5e7646d2SAndroid Build Coastguard Worker cupsdSetString(&pclass->organizational_unit, attr->values[0].string.text);
937*5e7646d2SAndroid Build Coastguard Worker
938*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippFindAttribute(con->request, "printer-info",
939*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_TEXT)) != NULL)
940*5e7646d2SAndroid Build Coastguard Worker cupsdSetString(&pclass->info, attr->values[0].string.text);
941*5e7646d2SAndroid Build Coastguard Worker
942*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippFindAttribute(con->request, "printer-is-accepting-jobs",
943*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_BOOLEAN)) != NULL &&
944*5e7646d2SAndroid Build Coastguard Worker attr->values[0].boolean != pclass->accepting)
945*5e7646d2SAndroid Build Coastguard Worker {
946*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_INFO,
947*5e7646d2SAndroid Build Coastguard Worker "Setting %s printer-is-accepting-jobs to %d (was %d.)",
948*5e7646d2SAndroid Build Coastguard Worker pclass->name, attr->values[0].boolean, pclass->accepting);
949*5e7646d2SAndroid Build Coastguard Worker
950*5e7646d2SAndroid Build Coastguard Worker pclass->accepting = attr->values[0].boolean;
951*5e7646d2SAndroid Build Coastguard Worker
952*5e7646d2SAndroid Build Coastguard Worker cupsdAddEvent(CUPSD_EVENT_PRINTER_STATE, pclass, NULL, "%s accepting jobs.",
953*5e7646d2SAndroid Build Coastguard Worker pclass->accepting ? "Now" : "No longer");
954*5e7646d2SAndroid Build Coastguard Worker }
955*5e7646d2SAndroid Build Coastguard Worker
956*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippFindAttribute(con->request, "printer-is-shared", IPP_TAG_BOOLEAN)) != NULL)
957*5e7646d2SAndroid Build Coastguard Worker {
958*5e7646d2SAndroid Build Coastguard Worker if (pclass->type & CUPS_PRINTER_REMOTE)
959*5e7646d2SAndroid Build Coastguard Worker {
960*5e7646d2SAndroid Build Coastguard Worker /*
961*5e7646d2SAndroid Build Coastguard Worker * Cannot re-share remote printers.
962*5e7646d2SAndroid Build Coastguard Worker */
963*5e7646d2SAndroid Build Coastguard Worker
964*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_BAD_REQUEST, _("Cannot change printer-is-shared for remote queues."));
965*5e7646d2SAndroid Build Coastguard Worker if (!modify)
966*5e7646d2SAndroid Build Coastguard Worker cupsdDeletePrinter(pclass, 0);
967*5e7646d2SAndroid Build Coastguard Worker
968*5e7646d2SAndroid Build Coastguard Worker return;
969*5e7646d2SAndroid Build Coastguard Worker }
970*5e7646d2SAndroid Build Coastguard Worker
971*5e7646d2SAndroid Build Coastguard Worker if (pclass->shared && !ippGetBoolean(attr, 0))
972*5e7646d2SAndroid Build Coastguard Worker cupsdDeregisterPrinter(pclass, 1);
973*5e7646d2SAndroid Build Coastguard Worker
974*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_INFO,
975*5e7646d2SAndroid Build Coastguard Worker "Setting %s printer-is-shared to %d (was %d.)",
976*5e7646d2SAndroid Build Coastguard Worker pclass->name, attr->values[0].boolean, pclass->shared);
977*5e7646d2SAndroid Build Coastguard Worker
978*5e7646d2SAndroid Build Coastguard Worker pclass->shared = ippGetBoolean(attr, 0);
979*5e7646d2SAndroid Build Coastguard Worker }
980*5e7646d2SAndroid Build Coastguard Worker
981*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippFindAttribute(con->request, "printer-state",
982*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_ENUM)) != NULL)
983*5e7646d2SAndroid Build Coastguard Worker {
984*5e7646d2SAndroid Build Coastguard Worker if (attr->values[0].integer != IPP_PRINTER_IDLE &&
985*5e7646d2SAndroid Build Coastguard Worker attr->values[0].integer != IPP_PRINTER_STOPPED)
986*5e7646d2SAndroid Build Coastguard Worker {
987*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_BAD_REQUEST,
988*5e7646d2SAndroid Build Coastguard Worker _("Attempt to set %s printer-state to bad value %d."),
989*5e7646d2SAndroid Build Coastguard Worker pclass->name, attr->values[0].integer);
990*5e7646d2SAndroid Build Coastguard Worker if (!modify)
991*5e7646d2SAndroid Build Coastguard Worker cupsdDeletePrinter(pclass, 0);
992*5e7646d2SAndroid Build Coastguard Worker
993*5e7646d2SAndroid Build Coastguard Worker return;
994*5e7646d2SAndroid Build Coastguard Worker }
995*5e7646d2SAndroid Build Coastguard Worker
996*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_INFO, "Setting %s printer-state to %d (was %d.)",
997*5e7646d2SAndroid Build Coastguard Worker pclass->name, attr->values[0].integer, pclass->state);
998*5e7646d2SAndroid Build Coastguard Worker
999*5e7646d2SAndroid Build Coastguard Worker if (attr->values[0].integer == IPP_PRINTER_STOPPED)
1000*5e7646d2SAndroid Build Coastguard Worker cupsdStopPrinter(pclass, 0);
1001*5e7646d2SAndroid Build Coastguard Worker else
1002*5e7646d2SAndroid Build Coastguard Worker {
1003*5e7646d2SAndroid Build Coastguard Worker cupsdSetPrinterState(pclass, (ipp_pstate_t)(attr->values[0].integer), 0);
1004*5e7646d2SAndroid Build Coastguard Worker need_restart_job = 1;
1005*5e7646d2SAndroid Build Coastguard Worker }
1006*5e7646d2SAndroid Build Coastguard Worker }
1007*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippFindAttribute(con->request, "printer-state-message",
1008*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_TEXT)) != NULL)
1009*5e7646d2SAndroid Build Coastguard Worker {
1010*5e7646d2SAndroid Build Coastguard Worker strlcpy(pclass->state_message, attr->values[0].string.text,
1011*5e7646d2SAndroid Build Coastguard Worker sizeof(pclass->state_message));
1012*5e7646d2SAndroid Build Coastguard Worker
1013*5e7646d2SAndroid Build Coastguard Worker cupsdAddEvent(CUPSD_EVENT_PRINTER_STATE, pclass, NULL, "%s",
1014*5e7646d2SAndroid Build Coastguard Worker pclass->state_message);
1015*5e7646d2SAndroid Build Coastguard Worker }
1016*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippFindAttribute(con->request, "member-uris",
1017*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_URI)) != NULL)
1018*5e7646d2SAndroid Build Coastguard Worker {
1019*5e7646d2SAndroid Build Coastguard Worker /*
1020*5e7646d2SAndroid Build Coastguard Worker * Clear the printer array as needed...
1021*5e7646d2SAndroid Build Coastguard Worker */
1022*5e7646d2SAndroid Build Coastguard Worker
1023*5e7646d2SAndroid Build Coastguard Worker need_restart_job = 1;
1024*5e7646d2SAndroid Build Coastguard Worker
1025*5e7646d2SAndroid Build Coastguard Worker if (pclass->num_printers > 0)
1026*5e7646d2SAndroid Build Coastguard Worker {
1027*5e7646d2SAndroid Build Coastguard Worker free(pclass->printers);
1028*5e7646d2SAndroid Build Coastguard Worker pclass->num_printers = 0;
1029*5e7646d2SAndroid Build Coastguard Worker }
1030*5e7646d2SAndroid Build Coastguard Worker
1031*5e7646d2SAndroid Build Coastguard Worker /*
1032*5e7646d2SAndroid Build Coastguard Worker * Add each printer or class that is listed...
1033*5e7646d2SAndroid Build Coastguard Worker */
1034*5e7646d2SAndroid Build Coastguard Worker
1035*5e7646d2SAndroid Build Coastguard Worker for (i = 0; i < attr->num_values; i ++)
1036*5e7646d2SAndroid Build Coastguard Worker {
1037*5e7646d2SAndroid Build Coastguard Worker /*
1038*5e7646d2SAndroid Build Coastguard Worker * Search for the printer or class URI...
1039*5e7646d2SAndroid Build Coastguard Worker */
1040*5e7646d2SAndroid Build Coastguard Worker
1041*5e7646d2SAndroid Build Coastguard Worker if (!cupsdValidateDest(attr->values[i].string.text, &dtype, &member))
1042*5e7646d2SAndroid Build Coastguard Worker {
1043*5e7646d2SAndroid Build Coastguard Worker /*
1044*5e7646d2SAndroid Build Coastguard Worker * Bad URI...
1045*5e7646d2SAndroid Build Coastguard Worker */
1046*5e7646d2SAndroid Build Coastguard Worker
1047*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_NOT_FOUND,
1048*5e7646d2SAndroid Build Coastguard Worker _("The printer or class does not exist."));
1049*5e7646d2SAndroid Build Coastguard Worker if (!modify)
1050*5e7646d2SAndroid Build Coastguard Worker cupsdDeletePrinter(pclass, 0);
1051*5e7646d2SAndroid Build Coastguard Worker
1052*5e7646d2SAndroid Build Coastguard Worker return;
1053*5e7646d2SAndroid Build Coastguard Worker }
1054*5e7646d2SAndroid Build Coastguard Worker else if (dtype & CUPS_PRINTER_CLASS)
1055*5e7646d2SAndroid Build Coastguard Worker {
1056*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_BAD_REQUEST,
1057*5e7646d2SAndroid Build Coastguard Worker _("Nested classes are not allowed."));
1058*5e7646d2SAndroid Build Coastguard Worker if (!modify)
1059*5e7646d2SAndroid Build Coastguard Worker cupsdDeletePrinter(pclass, 0);
1060*5e7646d2SAndroid Build Coastguard Worker
1061*5e7646d2SAndroid Build Coastguard Worker return;
1062*5e7646d2SAndroid Build Coastguard Worker }
1063*5e7646d2SAndroid Build Coastguard Worker
1064*5e7646d2SAndroid Build Coastguard Worker /*
1065*5e7646d2SAndroid Build Coastguard Worker * Add it to the class...
1066*5e7646d2SAndroid Build Coastguard Worker */
1067*5e7646d2SAndroid Build Coastguard Worker
1068*5e7646d2SAndroid Build Coastguard Worker cupsdAddPrinterToClass(pclass, member);
1069*5e7646d2SAndroid Build Coastguard Worker }
1070*5e7646d2SAndroid Build Coastguard Worker }
1071*5e7646d2SAndroid Build Coastguard Worker
1072*5e7646d2SAndroid Build Coastguard Worker if (!set_printer_defaults(con, pclass))
1073*5e7646d2SAndroid Build Coastguard Worker {
1074*5e7646d2SAndroid Build Coastguard Worker if (!modify)
1075*5e7646d2SAndroid Build Coastguard Worker cupsdDeletePrinter(pclass, 0);
1076*5e7646d2SAndroid Build Coastguard Worker
1077*5e7646d2SAndroid Build Coastguard Worker return;
1078*5e7646d2SAndroid Build Coastguard Worker }
1079*5e7646d2SAndroid Build Coastguard Worker
1080*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippFindAttribute(con->request, "auth-info-required",
1081*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_KEYWORD)) != NULL)
1082*5e7646d2SAndroid Build Coastguard Worker cupsdSetAuthInfoRequired(pclass, NULL, attr);
1083*5e7646d2SAndroid Build Coastguard Worker
1084*5e7646d2SAndroid Build Coastguard Worker pclass->config_time = time(NULL);
1085*5e7646d2SAndroid Build Coastguard Worker
1086*5e7646d2SAndroid Build Coastguard Worker /*
1087*5e7646d2SAndroid Build Coastguard Worker * Update the printer class attributes and return...
1088*5e7646d2SAndroid Build Coastguard Worker */
1089*5e7646d2SAndroid Build Coastguard Worker
1090*5e7646d2SAndroid Build Coastguard Worker cupsdSetPrinterAttrs(pclass);
1091*5e7646d2SAndroid Build Coastguard Worker cupsdMarkDirty(CUPSD_DIRTY_CLASSES);
1092*5e7646d2SAndroid Build Coastguard Worker
1093*5e7646d2SAndroid Build Coastguard Worker if (need_restart_job && pclass->job)
1094*5e7646d2SAndroid Build Coastguard Worker {
1095*5e7646d2SAndroid Build Coastguard Worker /*
1096*5e7646d2SAndroid Build Coastguard Worker * Reset the current job to a "pending" status...
1097*5e7646d2SAndroid Build Coastguard Worker */
1098*5e7646d2SAndroid Build Coastguard Worker
1099*5e7646d2SAndroid Build Coastguard Worker cupsdSetJobState(pclass->job, IPP_JOB_PENDING, CUPSD_JOB_FORCE,
1100*5e7646d2SAndroid Build Coastguard Worker "Job restarted because the class was modified.");
1101*5e7646d2SAndroid Build Coastguard Worker }
1102*5e7646d2SAndroid Build Coastguard Worker
1103*5e7646d2SAndroid Build Coastguard Worker cupsdMarkDirty(CUPSD_DIRTY_PRINTCAP);
1104*5e7646d2SAndroid Build Coastguard Worker
1105*5e7646d2SAndroid Build Coastguard Worker if (modify)
1106*5e7646d2SAndroid Build Coastguard Worker {
1107*5e7646d2SAndroid Build Coastguard Worker cupsdAddEvent(CUPSD_EVENT_PRINTER_MODIFIED,
1108*5e7646d2SAndroid Build Coastguard Worker pclass, NULL, "Class \"%s\" modified by \"%s\".",
1109*5e7646d2SAndroid Build Coastguard Worker pclass->name, get_username(con));
1110*5e7646d2SAndroid Build Coastguard Worker
1111*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_INFO, "Class \"%s\" modified by \"%s\".",
1112*5e7646d2SAndroid Build Coastguard Worker pclass->name, get_username(con));
1113*5e7646d2SAndroid Build Coastguard Worker }
1114*5e7646d2SAndroid Build Coastguard Worker else
1115*5e7646d2SAndroid Build Coastguard Worker {
1116*5e7646d2SAndroid Build Coastguard Worker cupsdAddEvent(CUPSD_EVENT_PRINTER_ADDED,
1117*5e7646d2SAndroid Build Coastguard Worker pclass, NULL, "New class \"%s\" added by \"%s\".",
1118*5e7646d2SAndroid Build Coastguard Worker pclass->name, get_username(con));
1119*5e7646d2SAndroid Build Coastguard Worker
1120*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_INFO, "New class \"%s\" added by \"%s\".",
1121*5e7646d2SAndroid Build Coastguard Worker pclass->name, get_username(con));
1122*5e7646d2SAndroid Build Coastguard Worker }
1123*5e7646d2SAndroid Build Coastguard Worker
1124*5e7646d2SAndroid Build Coastguard Worker con->response->request.status.status_code = IPP_OK;
1125*5e7646d2SAndroid Build Coastguard Worker }
1126*5e7646d2SAndroid Build Coastguard Worker
1127*5e7646d2SAndroid Build Coastguard Worker
1128*5e7646d2SAndroid Build Coastguard Worker /*
1129*5e7646d2SAndroid Build Coastguard Worker * 'add_file()' - Add a file to a job.
1130*5e7646d2SAndroid Build Coastguard Worker */
1131*5e7646d2SAndroid Build Coastguard Worker
1132*5e7646d2SAndroid Build Coastguard Worker static int /* O - 0 on success, -1 on error */
add_file(cupsd_client_t * con,cupsd_job_t * job,mime_type_t * filetype,int compression)1133*5e7646d2SAndroid Build Coastguard Worker add_file(cupsd_client_t *con, /* I - Connection to client */
1134*5e7646d2SAndroid Build Coastguard Worker cupsd_job_t *job, /* I - Job to add to */
1135*5e7646d2SAndroid Build Coastguard Worker mime_type_t *filetype, /* I - Type of file */
1136*5e7646d2SAndroid Build Coastguard Worker int compression) /* I - Compression */
1137*5e7646d2SAndroid Build Coastguard Worker {
1138*5e7646d2SAndroid Build Coastguard Worker mime_type_t **filetypes; /* New filetypes array... */
1139*5e7646d2SAndroid Build Coastguard Worker int *compressions; /* New compressions array... */
1140*5e7646d2SAndroid Build Coastguard Worker
1141*5e7646d2SAndroid Build Coastguard Worker
1142*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG2,
1143*5e7646d2SAndroid Build Coastguard Worker "add_file(con=%p[%d], job=%d, filetype=%s/%s, "
1144*5e7646d2SAndroid Build Coastguard Worker "compression=%d)", con, con ? con->number : -1, job->id,
1145*5e7646d2SAndroid Build Coastguard Worker filetype->super, filetype->type, compression);
1146*5e7646d2SAndroid Build Coastguard Worker
1147*5e7646d2SAndroid Build Coastguard Worker /*
1148*5e7646d2SAndroid Build Coastguard Worker * Add the file to the job...
1149*5e7646d2SAndroid Build Coastguard Worker */
1150*5e7646d2SAndroid Build Coastguard Worker
1151*5e7646d2SAndroid Build Coastguard Worker if (job->num_files == 0)
1152*5e7646d2SAndroid Build Coastguard Worker {
1153*5e7646d2SAndroid Build Coastguard Worker compressions = (int *)malloc(sizeof(int));
1154*5e7646d2SAndroid Build Coastguard Worker filetypes = (mime_type_t **)malloc(sizeof(mime_type_t *));
1155*5e7646d2SAndroid Build Coastguard Worker }
1156*5e7646d2SAndroid Build Coastguard Worker else
1157*5e7646d2SAndroid Build Coastguard Worker {
1158*5e7646d2SAndroid Build Coastguard Worker compressions = (int *)realloc(job->compressions,
1159*5e7646d2SAndroid Build Coastguard Worker (size_t)(job->num_files + 1) * sizeof(int));
1160*5e7646d2SAndroid Build Coastguard Worker filetypes = (mime_type_t **)realloc(job->filetypes,
1161*5e7646d2SAndroid Build Coastguard Worker (size_t)(job->num_files + 1) *
1162*5e7646d2SAndroid Build Coastguard Worker sizeof(mime_type_t *));
1163*5e7646d2SAndroid Build Coastguard Worker }
1164*5e7646d2SAndroid Build Coastguard Worker
1165*5e7646d2SAndroid Build Coastguard Worker if (compressions)
1166*5e7646d2SAndroid Build Coastguard Worker job->compressions = compressions;
1167*5e7646d2SAndroid Build Coastguard Worker
1168*5e7646d2SAndroid Build Coastguard Worker if (filetypes)
1169*5e7646d2SAndroid Build Coastguard Worker job->filetypes = filetypes;
1170*5e7646d2SAndroid Build Coastguard Worker
1171*5e7646d2SAndroid Build Coastguard Worker if (!compressions || !filetypes)
1172*5e7646d2SAndroid Build Coastguard Worker {
1173*5e7646d2SAndroid Build Coastguard Worker cupsdSetJobState(job, IPP_JOB_ABORTED, CUPSD_JOB_PURGE,
1174*5e7646d2SAndroid Build Coastguard Worker "Job aborted because the scheduler ran out of memory.");
1175*5e7646d2SAndroid Build Coastguard Worker
1176*5e7646d2SAndroid Build Coastguard Worker if (con)
1177*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_INTERNAL_ERROR,
1178*5e7646d2SAndroid Build Coastguard Worker _("Unable to allocate memory for file types."));
1179*5e7646d2SAndroid Build Coastguard Worker
1180*5e7646d2SAndroid Build Coastguard Worker return (-1);
1181*5e7646d2SAndroid Build Coastguard Worker }
1182*5e7646d2SAndroid Build Coastguard Worker
1183*5e7646d2SAndroid Build Coastguard Worker job->compressions[job->num_files] = compression;
1184*5e7646d2SAndroid Build Coastguard Worker job->filetypes[job->num_files] = filetype;
1185*5e7646d2SAndroid Build Coastguard Worker
1186*5e7646d2SAndroid Build Coastguard Worker job->num_files ++;
1187*5e7646d2SAndroid Build Coastguard Worker
1188*5e7646d2SAndroid Build Coastguard Worker job->dirty = 1;
1189*5e7646d2SAndroid Build Coastguard Worker cupsdMarkDirty(CUPSD_DIRTY_JOBS);
1190*5e7646d2SAndroid Build Coastguard Worker
1191*5e7646d2SAndroid Build Coastguard Worker return (0);
1192*5e7646d2SAndroid Build Coastguard Worker }
1193*5e7646d2SAndroid Build Coastguard Worker
1194*5e7646d2SAndroid Build Coastguard Worker
1195*5e7646d2SAndroid Build Coastguard Worker /*
1196*5e7646d2SAndroid Build Coastguard Worker * 'add_job()' - Add a job to a print queue.
1197*5e7646d2SAndroid Build Coastguard Worker */
1198*5e7646d2SAndroid Build Coastguard Worker
1199*5e7646d2SAndroid Build Coastguard Worker static cupsd_job_t * /* O - Job object */
add_job(cupsd_client_t * con,cupsd_printer_t * printer,mime_type_t * filetype)1200*5e7646d2SAndroid Build Coastguard Worker add_job(cupsd_client_t *con, /* I - Client connection */
1201*5e7646d2SAndroid Build Coastguard Worker cupsd_printer_t *printer, /* I - Destination printer */
1202*5e7646d2SAndroid Build Coastguard Worker mime_type_t *filetype) /* I - First print file type, if any */
1203*5e7646d2SAndroid Build Coastguard Worker {
1204*5e7646d2SAndroid Build Coastguard Worker http_status_t status; /* Policy status */
1205*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *attr, /* Current attribute */
1206*5e7646d2SAndroid Build Coastguard Worker *auth_info; /* auth-info attribute */
1207*5e7646d2SAndroid Build Coastguard Worker const char *mandatory; /* Current mandatory job attribute */
1208*5e7646d2SAndroid Build Coastguard Worker const char *val; /* Default option value */
1209*5e7646d2SAndroid Build Coastguard Worker int priority; /* Job priority */
1210*5e7646d2SAndroid Build Coastguard Worker cupsd_job_t *job; /* Current job */
1211*5e7646d2SAndroid Build Coastguard Worker char job_uri[HTTP_MAX_URI]; /* Job URI */
1212*5e7646d2SAndroid Build Coastguard Worker int kbytes; /* Size of print file */
1213*5e7646d2SAndroid Build Coastguard Worker int i; /* Looping var */
1214*5e7646d2SAndroid Build Coastguard Worker int lowerpagerange; /* Page range bound */
1215*5e7646d2SAndroid Build Coastguard Worker int exact; /* Did we have an exact match? */
1216*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *media_col, /* media-col attribute */
1217*5e7646d2SAndroid Build Coastguard Worker *media_margin; /* media-*-margin attribute */
1218*5e7646d2SAndroid Build Coastguard Worker ipp_t *unsup_col; /* media-col in unsupported response */
1219*5e7646d2SAndroid Build Coastguard Worker static const char * const readonly[] =/* List of read-only attributes */
1220*5e7646d2SAndroid Build Coastguard Worker {
1221*5e7646d2SAndroid Build Coastguard Worker "date-time-at-completed",
1222*5e7646d2SAndroid Build Coastguard Worker "date-time-at-creation",
1223*5e7646d2SAndroid Build Coastguard Worker "date-time-at-processing",
1224*5e7646d2SAndroid Build Coastguard Worker "job-detailed-status-messages",
1225*5e7646d2SAndroid Build Coastguard Worker "job-document-access-errors",
1226*5e7646d2SAndroid Build Coastguard Worker "job-id",
1227*5e7646d2SAndroid Build Coastguard Worker "job-impressions-completed",
1228*5e7646d2SAndroid Build Coastguard Worker "job-k-octets-completed",
1229*5e7646d2SAndroid Build Coastguard Worker "job-media-sheets-completed",
1230*5e7646d2SAndroid Build Coastguard Worker "job-pages-completed",
1231*5e7646d2SAndroid Build Coastguard Worker "job-printer-up-time",
1232*5e7646d2SAndroid Build Coastguard Worker "job-printer-uri",
1233*5e7646d2SAndroid Build Coastguard Worker "job-state",
1234*5e7646d2SAndroid Build Coastguard Worker "job-state-message",
1235*5e7646d2SAndroid Build Coastguard Worker "job-state-reasons",
1236*5e7646d2SAndroid Build Coastguard Worker "job-uri",
1237*5e7646d2SAndroid Build Coastguard Worker "number-of-documents",
1238*5e7646d2SAndroid Build Coastguard Worker "number-of-intervening-jobs",
1239*5e7646d2SAndroid Build Coastguard Worker "output-device-assigned",
1240*5e7646d2SAndroid Build Coastguard Worker "time-at-completed",
1241*5e7646d2SAndroid Build Coastguard Worker "time-at-creation",
1242*5e7646d2SAndroid Build Coastguard Worker "time-at-processing"
1243*5e7646d2SAndroid Build Coastguard Worker };
1244*5e7646d2SAndroid Build Coastguard Worker
1245*5e7646d2SAndroid Build Coastguard Worker
1246*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG2, "add_job(%p[%d], %p(%s), %p(%s/%s))",
1247*5e7646d2SAndroid Build Coastguard Worker con, con->number, printer, printer->name,
1248*5e7646d2SAndroid Build Coastguard Worker filetype, filetype ? filetype->super : "none",
1249*5e7646d2SAndroid Build Coastguard Worker filetype ? filetype->type : "none");
1250*5e7646d2SAndroid Build Coastguard Worker
1251*5e7646d2SAndroid Build Coastguard Worker /*
1252*5e7646d2SAndroid Build Coastguard Worker * Check remote printing to non-shared printer...
1253*5e7646d2SAndroid Build Coastguard Worker */
1254*5e7646d2SAndroid Build Coastguard Worker
1255*5e7646d2SAndroid Build Coastguard Worker if (!printer->shared &&
1256*5e7646d2SAndroid Build Coastguard Worker _cups_strcasecmp(con->http->hostname, "localhost") &&
1257*5e7646d2SAndroid Build Coastguard Worker _cups_strcasecmp(con->http->hostname, ServerName))
1258*5e7646d2SAndroid Build Coastguard Worker {
1259*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_NOT_AUTHORIZED,
1260*5e7646d2SAndroid Build Coastguard Worker _("The printer or class is not shared."));
1261*5e7646d2SAndroid Build Coastguard Worker return (NULL);
1262*5e7646d2SAndroid Build Coastguard Worker }
1263*5e7646d2SAndroid Build Coastguard Worker
1264*5e7646d2SAndroid Build Coastguard Worker /*
1265*5e7646d2SAndroid Build Coastguard Worker * Check policy...
1266*5e7646d2SAndroid Build Coastguard Worker */
1267*5e7646d2SAndroid Build Coastguard Worker
1268*5e7646d2SAndroid Build Coastguard Worker auth_info = ippFindAttribute(con->request, "auth-info", IPP_TAG_TEXT);
1269*5e7646d2SAndroid Build Coastguard Worker
1270*5e7646d2SAndroid Build Coastguard Worker if ((status = cupsdCheckPolicy(printer->op_policy_ptr, con, NULL)) != HTTP_OK)
1271*5e7646d2SAndroid Build Coastguard Worker {
1272*5e7646d2SAndroid Build Coastguard Worker send_http_error(con, status, printer);
1273*5e7646d2SAndroid Build Coastguard Worker return (NULL);
1274*5e7646d2SAndroid Build Coastguard Worker }
1275*5e7646d2SAndroid Build Coastguard Worker else if (printer->num_auth_info_required == 1 &&
1276*5e7646d2SAndroid Build Coastguard Worker !strcmp(printer->auth_info_required[0], "negotiate") &&
1277*5e7646d2SAndroid Build Coastguard Worker !con->username[0])
1278*5e7646d2SAndroid Build Coastguard Worker {
1279*5e7646d2SAndroid Build Coastguard Worker send_http_error(con, HTTP_UNAUTHORIZED, printer);
1280*5e7646d2SAndroid Build Coastguard Worker return (NULL);
1281*5e7646d2SAndroid Build Coastguard Worker }
1282*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_SSL
1283*5e7646d2SAndroid Build Coastguard Worker else if (auth_info && !con->http->tls &&
1284*5e7646d2SAndroid Build Coastguard Worker !httpAddrLocalhost(con->http->hostaddr))
1285*5e7646d2SAndroid Build Coastguard Worker {
1286*5e7646d2SAndroid Build Coastguard Worker /*
1287*5e7646d2SAndroid Build Coastguard Worker * Require encryption of auth-info over non-local connections...
1288*5e7646d2SAndroid Build Coastguard Worker */
1289*5e7646d2SAndroid Build Coastguard Worker
1290*5e7646d2SAndroid Build Coastguard Worker send_http_error(con, HTTP_UPGRADE_REQUIRED, printer);
1291*5e7646d2SAndroid Build Coastguard Worker return (NULL);
1292*5e7646d2SAndroid Build Coastguard Worker }
1293*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_SSL */
1294*5e7646d2SAndroid Build Coastguard Worker
1295*5e7646d2SAndroid Build Coastguard Worker /*
1296*5e7646d2SAndroid Build Coastguard Worker * See if the printer is accepting jobs...
1297*5e7646d2SAndroid Build Coastguard Worker */
1298*5e7646d2SAndroid Build Coastguard Worker
1299*5e7646d2SAndroid Build Coastguard Worker if (!printer->accepting)
1300*5e7646d2SAndroid Build Coastguard Worker {
1301*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_NOT_ACCEPTING,
1302*5e7646d2SAndroid Build Coastguard Worker _("Destination \"%s\" is not accepting jobs."),
1303*5e7646d2SAndroid Build Coastguard Worker printer->name);
1304*5e7646d2SAndroid Build Coastguard Worker return (NULL);
1305*5e7646d2SAndroid Build Coastguard Worker }
1306*5e7646d2SAndroid Build Coastguard Worker
1307*5e7646d2SAndroid Build Coastguard Worker /*
1308*5e7646d2SAndroid Build Coastguard Worker * Validate job template attributes; for now just document-format,
1309*5e7646d2SAndroid Build Coastguard Worker * copies, job-sheets, number-up, page-ranges, mandatory attributes, and
1310*5e7646d2SAndroid Build Coastguard Worker * media...
1311*5e7646d2SAndroid Build Coastguard Worker */
1312*5e7646d2SAndroid Build Coastguard Worker
1313*5e7646d2SAndroid Build Coastguard Worker for (i = 0; i < (int)(sizeof(readonly) / sizeof(readonly[0])); i ++)
1314*5e7646d2SAndroid Build Coastguard Worker {
1315*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippFindAttribute(con->request, readonly[i], IPP_TAG_ZERO)) != NULL)
1316*5e7646d2SAndroid Build Coastguard Worker {
1317*5e7646d2SAndroid Build Coastguard Worker ippDeleteAttribute(con->request, attr);
1318*5e7646d2SAndroid Build Coastguard Worker
1319*5e7646d2SAndroid Build Coastguard Worker if (StrictConformance)
1320*5e7646d2SAndroid Build Coastguard Worker {
1321*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_BAD_REQUEST, _("The '%s' Job Status attribute cannot be supplied in a job creation request."), readonly[i]);
1322*5e7646d2SAndroid Build Coastguard Worker return (NULL);
1323*5e7646d2SAndroid Build Coastguard Worker }
1324*5e7646d2SAndroid Build Coastguard Worker
1325*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_INFO, "Unexpected '%s' Job Status attribute in a job creation request.", readonly[i]);
1326*5e7646d2SAndroid Build Coastguard Worker }
1327*5e7646d2SAndroid Build Coastguard Worker }
1328*5e7646d2SAndroid Build Coastguard Worker
1329*5e7646d2SAndroid Build Coastguard Worker if (printer->pc)
1330*5e7646d2SAndroid Build Coastguard Worker {
1331*5e7646d2SAndroid Build Coastguard Worker for (mandatory = (char *)cupsArrayFirst(printer->pc->mandatory);
1332*5e7646d2SAndroid Build Coastguard Worker mandatory;
1333*5e7646d2SAndroid Build Coastguard Worker mandatory = (char *)cupsArrayNext(printer->pc->mandatory))
1334*5e7646d2SAndroid Build Coastguard Worker {
1335*5e7646d2SAndroid Build Coastguard Worker if (!ippFindAttribute(con->request, mandatory, IPP_TAG_ZERO))
1336*5e7646d2SAndroid Build Coastguard Worker {
1337*5e7646d2SAndroid Build Coastguard Worker /*
1338*5e7646d2SAndroid Build Coastguard Worker * Missing a required attribute...
1339*5e7646d2SAndroid Build Coastguard Worker */
1340*5e7646d2SAndroid Build Coastguard Worker
1341*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_CONFLICT,
1342*5e7646d2SAndroid Build Coastguard Worker _("The \"%s\" attribute is required for print jobs."),
1343*5e7646d2SAndroid Build Coastguard Worker mandatory);
1344*5e7646d2SAndroid Build Coastguard Worker return (NULL);
1345*5e7646d2SAndroid Build Coastguard Worker }
1346*5e7646d2SAndroid Build Coastguard Worker }
1347*5e7646d2SAndroid Build Coastguard Worker }
1348*5e7646d2SAndroid Build Coastguard Worker
1349*5e7646d2SAndroid Build Coastguard Worker if (filetype && printer->filetypes &&
1350*5e7646d2SAndroid Build Coastguard Worker !cupsArrayFind(printer->filetypes, filetype))
1351*5e7646d2SAndroid Build Coastguard Worker {
1352*5e7646d2SAndroid Build Coastguard Worker char mimetype[MIME_MAX_SUPER + MIME_MAX_TYPE + 2];
1353*5e7646d2SAndroid Build Coastguard Worker /* MIME media type string */
1354*5e7646d2SAndroid Build Coastguard Worker
1355*5e7646d2SAndroid Build Coastguard Worker
1356*5e7646d2SAndroid Build Coastguard Worker snprintf(mimetype, sizeof(mimetype), "%s/%s", filetype->super,
1357*5e7646d2SAndroid Build Coastguard Worker filetype->type);
1358*5e7646d2SAndroid Build Coastguard Worker
1359*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_DOCUMENT_FORMAT,
1360*5e7646d2SAndroid Build Coastguard Worker _("Unsupported format \"%s\"."), mimetype);
1361*5e7646d2SAndroid Build Coastguard Worker
1362*5e7646d2SAndroid Build Coastguard Worker ippAddString(con->response, IPP_TAG_UNSUPPORTED_GROUP, IPP_TAG_MIMETYPE,
1363*5e7646d2SAndroid Build Coastguard Worker "document-format", NULL, mimetype);
1364*5e7646d2SAndroid Build Coastguard Worker
1365*5e7646d2SAndroid Build Coastguard Worker return (NULL);
1366*5e7646d2SAndroid Build Coastguard Worker }
1367*5e7646d2SAndroid Build Coastguard Worker
1368*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippFindAttribute(con->request, "copies",
1369*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_INTEGER)) != NULL)
1370*5e7646d2SAndroid Build Coastguard Worker {
1371*5e7646d2SAndroid Build Coastguard Worker if (attr->values[0].integer < 1 || attr->values[0].integer > MaxCopies)
1372*5e7646d2SAndroid Build Coastguard Worker {
1373*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_ATTRIBUTES, _("Bad copies value %d."),
1374*5e7646d2SAndroid Build Coastguard Worker attr->values[0].integer);
1375*5e7646d2SAndroid Build Coastguard Worker ippAddInteger(con->response, IPP_TAG_UNSUPPORTED_GROUP, IPP_TAG_INTEGER,
1376*5e7646d2SAndroid Build Coastguard Worker "copies", attr->values[0].integer);
1377*5e7646d2SAndroid Build Coastguard Worker return (NULL);
1378*5e7646d2SAndroid Build Coastguard Worker }
1379*5e7646d2SAndroid Build Coastguard Worker }
1380*5e7646d2SAndroid Build Coastguard Worker
1381*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippFindAttribute(con->request, "job-sheets",
1382*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_ZERO)) != NULL)
1383*5e7646d2SAndroid Build Coastguard Worker {
1384*5e7646d2SAndroid Build Coastguard Worker if (attr->value_tag != IPP_TAG_KEYWORD &&
1385*5e7646d2SAndroid Build Coastguard Worker attr->value_tag != IPP_TAG_NAME)
1386*5e7646d2SAndroid Build Coastguard Worker {
1387*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_BAD_REQUEST, _("Bad job-sheets value type."));
1388*5e7646d2SAndroid Build Coastguard Worker return (NULL);
1389*5e7646d2SAndroid Build Coastguard Worker }
1390*5e7646d2SAndroid Build Coastguard Worker
1391*5e7646d2SAndroid Build Coastguard Worker if (attr->num_values > 2)
1392*5e7646d2SAndroid Build Coastguard Worker {
1393*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_BAD_REQUEST,
1394*5e7646d2SAndroid Build Coastguard Worker _("Too many job-sheets values (%d > 2)."),
1395*5e7646d2SAndroid Build Coastguard Worker attr->num_values);
1396*5e7646d2SAndroid Build Coastguard Worker return (NULL);
1397*5e7646d2SAndroid Build Coastguard Worker }
1398*5e7646d2SAndroid Build Coastguard Worker
1399*5e7646d2SAndroid Build Coastguard Worker for (i = 0; i < attr->num_values; i ++)
1400*5e7646d2SAndroid Build Coastguard Worker if (strcmp(attr->values[i].string.text, "none") &&
1401*5e7646d2SAndroid Build Coastguard Worker !cupsdFindBanner(attr->values[i].string.text))
1402*5e7646d2SAndroid Build Coastguard Worker {
1403*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_BAD_REQUEST, _("Bad job-sheets value \"%s\"."),
1404*5e7646d2SAndroid Build Coastguard Worker attr->values[i].string.text);
1405*5e7646d2SAndroid Build Coastguard Worker return (NULL);
1406*5e7646d2SAndroid Build Coastguard Worker }
1407*5e7646d2SAndroid Build Coastguard Worker }
1408*5e7646d2SAndroid Build Coastguard Worker
1409*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippFindAttribute(con->request, "number-up",
1410*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_INTEGER)) != NULL)
1411*5e7646d2SAndroid Build Coastguard Worker {
1412*5e7646d2SAndroid Build Coastguard Worker if (attr->values[0].integer != 1 &&
1413*5e7646d2SAndroid Build Coastguard Worker attr->values[0].integer != 2 &&
1414*5e7646d2SAndroid Build Coastguard Worker attr->values[0].integer != 4 &&
1415*5e7646d2SAndroid Build Coastguard Worker attr->values[0].integer != 6 &&
1416*5e7646d2SAndroid Build Coastguard Worker attr->values[0].integer != 9 &&
1417*5e7646d2SAndroid Build Coastguard Worker attr->values[0].integer != 16)
1418*5e7646d2SAndroid Build Coastguard Worker {
1419*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_ATTRIBUTES, _("Bad number-up value %d."),
1420*5e7646d2SAndroid Build Coastguard Worker attr->values[0].integer);
1421*5e7646d2SAndroid Build Coastguard Worker ippAddInteger(con->response, IPP_TAG_UNSUPPORTED_GROUP, IPP_TAG_INTEGER,
1422*5e7646d2SAndroid Build Coastguard Worker "number-up", attr->values[0].integer);
1423*5e7646d2SAndroid Build Coastguard Worker return (NULL);
1424*5e7646d2SAndroid Build Coastguard Worker }
1425*5e7646d2SAndroid Build Coastguard Worker }
1426*5e7646d2SAndroid Build Coastguard Worker
1427*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippFindAttribute(con->request, "page-ranges",
1428*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_RANGE)) != NULL)
1429*5e7646d2SAndroid Build Coastguard Worker {
1430*5e7646d2SAndroid Build Coastguard Worker for (i = 0, lowerpagerange = 1; i < attr->num_values; i ++)
1431*5e7646d2SAndroid Build Coastguard Worker {
1432*5e7646d2SAndroid Build Coastguard Worker if (attr->values[i].range.lower < lowerpagerange ||
1433*5e7646d2SAndroid Build Coastguard Worker attr->values[i].range.lower > attr->values[i].range.upper)
1434*5e7646d2SAndroid Build Coastguard Worker {
1435*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_BAD_REQUEST,
1436*5e7646d2SAndroid Build Coastguard Worker _("Bad page-ranges values %d-%d."),
1437*5e7646d2SAndroid Build Coastguard Worker attr->values[i].range.lower,
1438*5e7646d2SAndroid Build Coastguard Worker attr->values[i].range.upper);
1439*5e7646d2SAndroid Build Coastguard Worker return (NULL);
1440*5e7646d2SAndroid Build Coastguard Worker }
1441*5e7646d2SAndroid Build Coastguard Worker
1442*5e7646d2SAndroid Build Coastguard Worker lowerpagerange = attr->values[i].range.upper + 1;
1443*5e7646d2SAndroid Build Coastguard Worker }
1444*5e7646d2SAndroid Build Coastguard Worker }
1445*5e7646d2SAndroid Build Coastguard Worker
1446*5e7646d2SAndroid Build Coastguard Worker /*
1447*5e7646d2SAndroid Build Coastguard Worker * Do media selection as needed...
1448*5e7646d2SAndroid Build Coastguard Worker */
1449*5e7646d2SAndroid Build Coastguard Worker
1450*5e7646d2SAndroid Build Coastguard Worker if (!ippFindAttribute(con->request, "PageRegion", IPP_TAG_ZERO) &&
1451*5e7646d2SAndroid Build Coastguard Worker !ippFindAttribute(con->request, "PageSize", IPP_TAG_ZERO) &&
1452*5e7646d2SAndroid Build Coastguard Worker _ppdCacheGetPageSize(printer->pc, con->request, NULL, &exact))
1453*5e7646d2SAndroid Build Coastguard Worker {
1454*5e7646d2SAndroid Build Coastguard Worker if (!exact &&
1455*5e7646d2SAndroid Build Coastguard Worker (media_col = ippFindAttribute(con->request, "media-col",
1456*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_BEGIN_COLLECTION)) != NULL)
1457*5e7646d2SAndroid Build Coastguard Worker {
1458*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_OK_SUBST, _("Unsupported margins."));
1459*5e7646d2SAndroid Build Coastguard Worker
1460*5e7646d2SAndroid Build Coastguard Worker unsup_col = ippNew();
1461*5e7646d2SAndroid Build Coastguard Worker if ((media_margin = ippFindAttribute(media_col->values[0].collection,
1462*5e7646d2SAndroid Build Coastguard Worker "media-bottom-margin",
1463*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_INTEGER)) != NULL)
1464*5e7646d2SAndroid Build Coastguard Worker ippAddInteger(unsup_col, IPP_TAG_ZERO, IPP_TAG_INTEGER,
1465*5e7646d2SAndroid Build Coastguard Worker "media-bottom-margin", media_margin->values[0].integer);
1466*5e7646d2SAndroid Build Coastguard Worker
1467*5e7646d2SAndroid Build Coastguard Worker if ((media_margin = ippFindAttribute(media_col->values[0].collection,
1468*5e7646d2SAndroid Build Coastguard Worker "media-left-margin",
1469*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_INTEGER)) != NULL)
1470*5e7646d2SAndroid Build Coastguard Worker ippAddInteger(unsup_col, IPP_TAG_ZERO, IPP_TAG_INTEGER,
1471*5e7646d2SAndroid Build Coastguard Worker "media-left-margin", media_margin->values[0].integer);
1472*5e7646d2SAndroid Build Coastguard Worker
1473*5e7646d2SAndroid Build Coastguard Worker if ((media_margin = ippFindAttribute(media_col->values[0].collection,
1474*5e7646d2SAndroid Build Coastguard Worker "media-right-margin",
1475*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_INTEGER)) != NULL)
1476*5e7646d2SAndroid Build Coastguard Worker ippAddInteger(unsup_col, IPP_TAG_ZERO, IPP_TAG_INTEGER,
1477*5e7646d2SAndroid Build Coastguard Worker "media-right-margin", media_margin->values[0].integer);
1478*5e7646d2SAndroid Build Coastguard Worker
1479*5e7646d2SAndroid Build Coastguard Worker if ((media_margin = ippFindAttribute(media_col->values[0].collection,
1480*5e7646d2SAndroid Build Coastguard Worker "media-top-margin",
1481*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_INTEGER)) != NULL)
1482*5e7646d2SAndroid Build Coastguard Worker ippAddInteger(unsup_col, IPP_TAG_ZERO, IPP_TAG_INTEGER,
1483*5e7646d2SAndroid Build Coastguard Worker "media-top-margin", media_margin->values[0].integer);
1484*5e7646d2SAndroid Build Coastguard Worker
1485*5e7646d2SAndroid Build Coastguard Worker ippAddCollection(con->response, IPP_TAG_UNSUPPORTED_GROUP, "media-col",
1486*5e7646d2SAndroid Build Coastguard Worker unsup_col);
1487*5e7646d2SAndroid Build Coastguard Worker ippDelete(unsup_col);
1488*5e7646d2SAndroid Build Coastguard Worker }
1489*5e7646d2SAndroid Build Coastguard Worker }
1490*5e7646d2SAndroid Build Coastguard Worker
1491*5e7646d2SAndroid Build Coastguard Worker /*
1492*5e7646d2SAndroid Build Coastguard Worker * Make sure we aren't over our limit...
1493*5e7646d2SAndroid Build Coastguard Worker */
1494*5e7646d2SAndroid Build Coastguard Worker
1495*5e7646d2SAndroid Build Coastguard Worker if (MaxJobs && cupsArrayCount(Jobs) >= MaxJobs)
1496*5e7646d2SAndroid Build Coastguard Worker cupsdCleanJobs();
1497*5e7646d2SAndroid Build Coastguard Worker
1498*5e7646d2SAndroid Build Coastguard Worker if (MaxJobs && cupsArrayCount(Jobs) >= MaxJobs)
1499*5e7646d2SAndroid Build Coastguard Worker {
1500*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_NOT_POSSIBLE, _("Too many active jobs."));
1501*5e7646d2SAndroid Build Coastguard Worker return (NULL);
1502*5e7646d2SAndroid Build Coastguard Worker }
1503*5e7646d2SAndroid Build Coastguard Worker
1504*5e7646d2SAndroid Build Coastguard Worker if ((i = check_quotas(con, printer)) < 0)
1505*5e7646d2SAndroid Build Coastguard Worker {
1506*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_NOT_POSSIBLE, _("Quota limit reached."));
1507*5e7646d2SAndroid Build Coastguard Worker return (NULL);
1508*5e7646d2SAndroid Build Coastguard Worker }
1509*5e7646d2SAndroid Build Coastguard Worker else if (i == 0)
1510*5e7646d2SAndroid Build Coastguard Worker {
1511*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_NOT_AUTHORIZED, _("Not allowed to print."));
1512*5e7646d2SAndroid Build Coastguard Worker return (NULL);
1513*5e7646d2SAndroid Build Coastguard Worker }
1514*5e7646d2SAndroid Build Coastguard Worker
1515*5e7646d2SAndroid Build Coastguard Worker /*
1516*5e7646d2SAndroid Build Coastguard Worker * Create the job and set things up...
1517*5e7646d2SAndroid Build Coastguard Worker */
1518*5e7646d2SAndroid Build Coastguard Worker
1519*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippFindAttribute(con->request, "job-priority",
1520*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_INTEGER)) != NULL)
1521*5e7646d2SAndroid Build Coastguard Worker priority = attr->values[0].integer;
1522*5e7646d2SAndroid Build Coastguard Worker else
1523*5e7646d2SAndroid Build Coastguard Worker {
1524*5e7646d2SAndroid Build Coastguard Worker if ((val = cupsGetOption("job-priority", printer->num_options,
1525*5e7646d2SAndroid Build Coastguard Worker printer->options)) != NULL)
1526*5e7646d2SAndroid Build Coastguard Worker priority = atoi(val);
1527*5e7646d2SAndroid Build Coastguard Worker else
1528*5e7646d2SAndroid Build Coastguard Worker priority = 50;
1529*5e7646d2SAndroid Build Coastguard Worker
1530*5e7646d2SAndroid Build Coastguard Worker ippAddInteger(con->request, IPP_TAG_JOB, IPP_TAG_INTEGER, "job-priority",
1531*5e7646d2SAndroid Build Coastguard Worker priority);
1532*5e7646d2SAndroid Build Coastguard Worker }
1533*5e7646d2SAndroid Build Coastguard Worker
1534*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippFindAttribute(con->request, "job-name", IPP_TAG_ZERO)) == NULL)
1535*5e7646d2SAndroid Build Coastguard Worker ippAddString(con->request, IPP_TAG_JOB, IPP_TAG_NAME, "job-name", NULL, "Untitled");
1536*5e7646d2SAndroid Build Coastguard Worker else if ((attr->value_tag != IPP_TAG_NAME &&
1537*5e7646d2SAndroid Build Coastguard Worker attr->value_tag != IPP_TAG_NAMELANG) ||
1538*5e7646d2SAndroid Build Coastguard Worker attr->num_values != 1)
1539*5e7646d2SAndroid Build Coastguard Worker {
1540*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_ATTRIBUTES,
1541*5e7646d2SAndroid Build Coastguard Worker _("Bad job-name value: Wrong type or count."));
1542*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippCopyAttribute(con->response, attr, 0)) != NULL)
1543*5e7646d2SAndroid Build Coastguard Worker attr->group_tag = IPP_TAG_UNSUPPORTED_GROUP;
1544*5e7646d2SAndroid Build Coastguard Worker
1545*5e7646d2SAndroid Build Coastguard Worker if (StrictConformance)
1546*5e7646d2SAndroid Build Coastguard Worker return (NULL);
1547*5e7646d2SAndroid Build Coastguard Worker
1548*5e7646d2SAndroid Build Coastguard Worker /* Don't use invalid attribute */
1549*5e7646d2SAndroid Build Coastguard Worker ippDeleteAttribute(con->request, attr);
1550*5e7646d2SAndroid Build Coastguard Worker
1551*5e7646d2SAndroid Build Coastguard Worker ippAddString(con->request, IPP_TAG_JOB, IPP_TAG_NAME, "job-name", NULL, "Untitled");
1552*5e7646d2SAndroid Build Coastguard Worker }
1553*5e7646d2SAndroid Build Coastguard Worker else if (!ippValidateAttribute(attr))
1554*5e7646d2SAndroid Build Coastguard Worker {
1555*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_ATTRIBUTES, _("Bad job-name value: %s"),
1556*5e7646d2SAndroid Build Coastguard Worker cupsLastErrorString());
1557*5e7646d2SAndroid Build Coastguard Worker
1558*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippCopyAttribute(con->response, attr, 0)) != NULL)
1559*5e7646d2SAndroid Build Coastguard Worker attr->group_tag = IPP_TAG_UNSUPPORTED_GROUP;
1560*5e7646d2SAndroid Build Coastguard Worker
1561*5e7646d2SAndroid Build Coastguard Worker if (StrictConformance)
1562*5e7646d2SAndroid Build Coastguard Worker return (NULL);
1563*5e7646d2SAndroid Build Coastguard Worker
1564*5e7646d2SAndroid Build Coastguard Worker /* Don't use invalid attribute */
1565*5e7646d2SAndroid Build Coastguard Worker ippDeleteAttribute(con->request, attr);
1566*5e7646d2SAndroid Build Coastguard Worker
1567*5e7646d2SAndroid Build Coastguard Worker ippAddString(con->request, IPP_TAG_JOB, IPP_TAG_NAME, "job-name", NULL, "Untitled");
1568*5e7646d2SAndroid Build Coastguard Worker }
1569*5e7646d2SAndroid Build Coastguard Worker
1570*5e7646d2SAndroid Build Coastguard Worker attr = ippFindAttribute(con->request, "requesting-user-name", IPP_TAG_NAME);
1571*5e7646d2SAndroid Build Coastguard Worker
1572*5e7646d2SAndroid Build Coastguard Worker if ((job = cupsdAddJob(priority, printer->name)) == NULL)
1573*5e7646d2SAndroid Build Coastguard Worker {
1574*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_INTERNAL_ERROR,
1575*5e7646d2SAndroid Build Coastguard Worker _("Unable to add job for destination \"%s\"."),
1576*5e7646d2SAndroid Build Coastguard Worker printer->name);
1577*5e7646d2SAndroid Build Coastguard Worker return (NULL);
1578*5e7646d2SAndroid Build Coastguard Worker }
1579*5e7646d2SAndroid Build Coastguard Worker
1580*5e7646d2SAndroid Build Coastguard Worker job->dtype = printer->type & (CUPS_PRINTER_CLASS | CUPS_PRINTER_REMOTE);
1581*5e7646d2SAndroid Build Coastguard Worker job->attrs = con->request;
1582*5e7646d2SAndroid Build Coastguard Worker job->dirty = 1;
1583*5e7646d2SAndroid Build Coastguard Worker con->request = ippNewRequest(job->attrs->request.op.operation_id);
1584*5e7646d2SAndroid Build Coastguard Worker
1585*5e7646d2SAndroid Build Coastguard Worker cupsdMarkDirty(CUPSD_DIRTY_JOBS);
1586*5e7646d2SAndroid Build Coastguard Worker
1587*5e7646d2SAndroid Build Coastguard Worker add_job_uuid(job);
1588*5e7646d2SAndroid Build Coastguard Worker apply_printer_defaults(printer, job);
1589*5e7646d2SAndroid Build Coastguard Worker
1590*5e7646d2SAndroid Build Coastguard Worker if (con->username[0])
1591*5e7646d2SAndroid Build Coastguard Worker {
1592*5e7646d2SAndroid Build Coastguard Worker cupsdSetString(&job->username, con->username);
1593*5e7646d2SAndroid Build Coastguard Worker
1594*5e7646d2SAndroid Build Coastguard Worker if (attr)
1595*5e7646d2SAndroid Build Coastguard Worker ippSetString(job->attrs, &attr, 0, con->username);
1596*5e7646d2SAndroid Build Coastguard Worker }
1597*5e7646d2SAndroid Build Coastguard Worker else if (attr)
1598*5e7646d2SAndroid Build Coastguard Worker {
1599*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG,
1600*5e7646d2SAndroid Build Coastguard Worker "add_job: requesting-user-name=\"%s\"",
1601*5e7646d2SAndroid Build Coastguard Worker attr->values[0].string.text);
1602*5e7646d2SAndroid Build Coastguard Worker
1603*5e7646d2SAndroid Build Coastguard Worker cupsdSetString(&job->username, attr->values[0].string.text);
1604*5e7646d2SAndroid Build Coastguard Worker }
1605*5e7646d2SAndroid Build Coastguard Worker else
1606*5e7646d2SAndroid Build Coastguard Worker cupsdSetString(&job->username, "anonymous");
1607*5e7646d2SAndroid Build Coastguard Worker
1608*5e7646d2SAndroid Build Coastguard Worker if (!attr)
1609*5e7646d2SAndroid Build Coastguard Worker ippAddString(job->attrs, IPP_TAG_JOB, IPP_TAG_NAME,
1610*5e7646d2SAndroid Build Coastguard Worker "job-originating-user-name", NULL, job->username);
1611*5e7646d2SAndroid Build Coastguard Worker else
1612*5e7646d2SAndroid Build Coastguard Worker {
1613*5e7646d2SAndroid Build Coastguard Worker ippSetGroupTag(job->attrs, &attr, IPP_TAG_JOB);
1614*5e7646d2SAndroid Build Coastguard Worker ippSetName(job->attrs, &attr, "job-originating-user-name");
1615*5e7646d2SAndroid Build Coastguard Worker }
1616*5e7646d2SAndroid Build Coastguard Worker
1617*5e7646d2SAndroid Build Coastguard Worker if (con->username[0] || auth_info)
1618*5e7646d2SAndroid Build Coastguard Worker {
1619*5e7646d2SAndroid Build Coastguard Worker save_auth_info(con, job, auth_info);
1620*5e7646d2SAndroid Build Coastguard Worker
1621*5e7646d2SAndroid Build Coastguard Worker /*
1622*5e7646d2SAndroid Build Coastguard Worker * Remove the auth-info attribute from the attribute data...
1623*5e7646d2SAndroid Build Coastguard Worker */
1624*5e7646d2SAndroid Build Coastguard Worker
1625*5e7646d2SAndroid Build Coastguard Worker if (auth_info)
1626*5e7646d2SAndroid Build Coastguard Worker ippDeleteAttribute(job->attrs, auth_info);
1627*5e7646d2SAndroid Build Coastguard Worker }
1628*5e7646d2SAndroid Build Coastguard Worker
1629*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippFindAttribute(con->request, "job-name", IPP_TAG_NAME)) != NULL)
1630*5e7646d2SAndroid Build Coastguard Worker cupsdSetString(&(job->name), attr->values[0].string.text);
1631*5e7646d2SAndroid Build Coastguard Worker
1632*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippFindAttribute(job->attrs, "job-originating-host-name",
1633*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_ZERO)) != NULL)
1634*5e7646d2SAndroid Build Coastguard Worker {
1635*5e7646d2SAndroid Build Coastguard Worker /*
1636*5e7646d2SAndroid Build Coastguard Worker * Request contains a job-originating-host-name attribute; validate it...
1637*5e7646d2SAndroid Build Coastguard Worker */
1638*5e7646d2SAndroid Build Coastguard Worker
1639*5e7646d2SAndroid Build Coastguard Worker if (attr->value_tag != IPP_TAG_NAME ||
1640*5e7646d2SAndroid Build Coastguard Worker attr->num_values != 1 ||
1641*5e7646d2SAndroid Build Coastguard Worker strcmp(con->http->hostname, "localhost"))
1642*5e7646d2SAndroid Build Coastguard Worker {
1643*5e7646d2SAndroid Build Coastguard Worker /*
1644*5e7646d2SAndroid Build Coastguard Worker * Can't override the value if we aren't connected via localhost.
1645*5e7646d2SAndroid Build Coastguard Worker * Also, we can only have 1 value and it must be a name value.
1646*5e7646d2SAndroid Build Coastguard Worker */
1647*5e7646d2SAndroid Build Coastguard Worker
1648*5e7646d2SAndroid Build Coastguard Worker ippDeleteAttribute(job->attrs, attr);
1649*5e7646d2SAndroid Build Coastguard Worker ippAddString(job->attrs, IPP_TAG_JOB, IPP_TAG_NAME, "job-originating-host-name", NULL, con->http->hostname);
1650*5e7646d2SAndroid Build Coastguard Worker }
1651*5e7646d2SAndroid Build Coastguard Worker else
1652*5e7646d2SAndroid Build Coastguard Worker ippSetGroupTag(job->attrs, &attr, IPP_TAG_JOB);
1653*5e7646d2SAndroid Build Coastguard Worker }
1654*5e7646d2SAndroid Build Coastguard Worker else
1655*5e7646d2SAndroid Build Coastguard Worker {
1656*5e7646d2SAndroid Build Coastguard Worker /*
1657*5e7646d2SAndroid Build Coastguard Worker * No job-originating-host-name attribute, so use the hostname from
1658*5e7646d2SAndroid Build Coastguard Worker * the connection...
1659*5e7646d2SAndroid Build Coastguard Worker */
1660*5e7646d2SAndroid Build Coastguard Worker
1661*5e7646d2SAndroid Build Coastguard Worker ippAddString(job->attrs, IPP_TAG_JOB, IPP_TAG_NAME,
1662*5e7646d2SAndroid Build Coastguard Worker "job-originating-host-name", NULL, con->http->hostname);
1663*5e7646d2SAndroid Build Coastguard Worker }
1664*5e7646d2SAndroid Build Coastguard Worker
1665*5e7646d2SAndroid Build Coastguard Worker ippAddOutOfBand(job->attrs, IPP_TAG_JOB, IPP_TAG_NOVALUE, "date-time-at-completed");
1666*5e7646d2SAndroid Build Coastguard Worker ippAddDate(job->attrs, IPP_TAG_JOB, "date-time-at-creation", ippTimeToDate(time(NULL)));
1667*5e7646d2SAndroid Build Coastguard Worker ippAddOutOfBand(job->attrs, IPP_TAG_JOB, IPP_TAG_NOVALUE, "date-time-at-processing");
1668*5e7646d2SAndroid Build Coastguard Worker ippAddOutOfBand(job->attrs, IPP_TAG_JOB, IPP_TAG_NOVALUE, "time-at-completed");
1669*5e7646d2SAndroid Build Coastguard Worker ippAddInteger(job->attrs, IPP_TAG_JOB, IPP_TAG_INTEGER, "time-at-creation", time(NULL));
1670*5e7646d2SAndroid Build Coastguard Worker ippAddOutOfBand(job->attrs, IPP_TAG_JOB, IPP_TAG_NOVALUE, "time-at-processing");
1671*5e7646d2SAndroid Build Coastguard Worker
1672*5e7646d2SAndroid Build Coastguard Worker /*
1673*5e7646d2SAndroid Build Coastguard Worker * Add remaining job attributes...
1674*5e7646d2SAndroid Build Coastguard Worker */
1675*5e7646d2SAndroid Build Coastguard Worker
1676*5e7646d2SAndroid Build Coastguard Worker ippAddInteger(job->attrs, IPP_TAG_JOB, IPP_TAG_INTEGER, "job-id", job->id);
1677*5e7646d2SAndroid Build Coastguard Worker job->state = ippAddInteger(job->attrs, IPP_TAG_JOB, IPP_TAG_ENUM,
1678*5e7646d2SAndroid Build Coastguard Worker "job-state", IPP_JOB_STOPPED);
1679*5e7646d2SAndroid Build Coastguard Worker job->state_value = (ipp_jstate_t)job->state->values[0].integer;
1680*5e7646d2SAndroid Build Coastguard Worker job->reasons = ippAddString(job->attrs, IPP_TAG_JOB, IPP_TAG_KEYWORD,
1681*5e7646d2SAndroid Build Coastguard Worker "job-state-reasons", NULL, "job-incoming");
1682*5e7646d2SAndroid Build Coastguard Worker job->impressions = ippAddInteger(job->attrs, IPP_TAG_JOB, IPP_TAG_INTEGER, "job-impressions-completed", 0);
1683*5e7646d2SAndroid Build Coastguard Worker job->sheets = ippAddInteger(job->attrs, IPP_TAG_JOB, IPP_TAG_INTEGER,
1684*5e7646d2SAndroid Build Coastguard Worker "job-media-sheets-completed", 0);
1685*5e7646d2SAndroid Build Coastguard Worker ippAddString(job->attrs, IPP_TAG_JOB, IPP_TAG_URI, "job-printer-uri", NULL,
1686*5e7646d2SAndroid Build Coastguard Worker printer->uri);
1687*5e7646d2SAndroid Build Coastguard Worker
1688*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippFindAttribute(job->attrs, "job-k-octets", IPP_TAG_INTEGER)) != NULL)
1689*5e7646d2SAndroid Build Coastguard Worker attr->values[0].integer = 0;
1690*5e7646d2SAndroid Build Coastguard Worker else
1691*5e7646d2SAndroid Build Coastguard Worker ippAddInteger(job->attrs, IPP_TAG_JOB, IPP_TAG_INTEGER, "job-k-octets", 0);
1692*5e7646d2SAndroid Build Coastguard Worker
1693*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippFindAttribute(job->attrs, "job-hold-until",
1694*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_KEYWORD)) == NULL)
1695*5e7646d2SAndroid Build Coastguard Worker attr = ippFindAttribute(job->attrs, "job-hold-until", IPP_TAG_NAME);
1696*5e7646d2SAndroid Build Coastguard Worker if (!attr)
1697*5e7646d2SAndroid Build Coastguard Worker {
1698*5e7646d2SAndroid Build Coastguard Worker if ((val = cupsGetOption("job-hold-until", printer->num_options,
1699*5e7646d2SAndroid Build Coastguard Worker printer->options)) == NULL)
1700*5e7646d2SAndroid Build Coastguard Worker val = "no-hold";
1701*5e7646d2SAndroid Build Coastguard Worker
1702*5e7646d2SAndroid Build Coastguard Worker attr = ippAddString(job->attrs, IPP_TAG_JOB, IPP_TAG_KEYWORD,
1703*5e7646d2SAndroid Build Coastguard Worker "job-hold-until", NULL, val);
1704*5e7646d2SAndroid Build Coastguard Worker }
1705*5e7646d2SAndroid Build Coastguard Worker
1706*5e7646d2SAndroid Build Coastguard Worker if (printer->holding_new_jobs)
1707*5e7646d2SAndroid Build Coastguard Worker {
1708*5e7646d2SAndroid Build Coastguard Worker /*
1709*5e7646d2SAndroid Build Coastguard Worker * Hold all new jobs on this printer...
1710*5e7646d2SAndroid Build Coastguard Worker */
1711*5e7646d2SAndroid Build Coastguard Worker
1712*5e7646d2SAndroid Build Coastguard Worker if (attr && strcmp(attr->values[0].string.text, "no-hold"))
1713*5e7646d2SAndroid Build Coastguard Worker cupsdSetJobHoldUntil(job, ippGetString(attr, 0, NULL), 0);
1714*5e7646d2SAndroid Build Coastguard Worker else
1715*5e7646d2SAndroid Build Coastguard Worker cupsdSetJobHoldUntil(job, "indefinite", 0);
1716*5e7646d2SAndroid Build Coastguard Worker
1717*5e7646d2SAndroid Build Coastguard Worker job->state->values[0].integer = IPP_JOB_HELD;
1718*5e7646d2SAndroid Build Coastguard Worker job->state_value = IPP_JOB_HELD;
1719*5e7646d2SAndroid Build Coastguard Worker
1720*5e7646d2SAndroid Build Coastguard Worker ippSetString(job->attrs, &job->reasons, 0, "job-held-on-create");
1721*5e7646d2SAndroid Build Coastguard Worker }
1722*5e7646d2SAndroid Build Coastguard Worker else if (attr && strcmp(attr->values[0].string.text, "no-hold"))
1723*5e7646d2SAndroid Build Coastguard Worker {
1724*5e7646d2SAndroid Build Coastguard Worker /*
1725*5e7646d2SAndroid Build Coastguard Worker * Hold job until specified time...
1726*5e7646d2SAndroid Build Coastguard Worker */
1727*5e7646d2SAndroid Build Coastguard Worker
1728*5e7646d2SAndroid Build Coastguard Worker cupsdSetJobHoldUntil(job, attr->values[0].string.text, 0);
1729*5e7646d2SAndroid Build Coastguard Worker
1730*5e7646d2SAndroid Build Coastguard Worker job->state->values[0].integer = IPP_JOB_HELD;
1731*5e7646d2SAndroid Build Coastguard Worker job->state_value = IPP_JOB_HELD;
1732*5e7646d2SAndroid Build Coastguard Worker
1733*5e7646d2SAndroid Build Coastguard Worker ippSetString(job->attrs, &job->reasons, 0, "job-hold-until-specified");
1734*5e7646d2SAndroid Build Coastguard Worker }
1735*5e7646d2SAndroid Build Coastguard Worker else if (job->attrs->request.op.operation_id == IPP_CREATE_JOB)
1736*5e7646d2SAndroid Build Coastguard Worker {
1737*5e7646d2SAndroid Build Coastguard Worker job->hold_until = time(NULL) + MultipleOperationTimeout;
1738*5e7646d2SAndroid Build Coastguard Worker job->state->values[0].integer = IPP_JOB_HELD;
1739*5e7646d2SAndroid Build Coastguard Worker job->state_value = IPP_JOB_HELD;
1740*5e7646d2SAndroid Build Coastguard Worker }
1741*5e7646d2SAndroid Build Coastguard Worker else
1742*5e7646d2SAndroid Build Coastguard Worker {
1743*5e7646d2SAndroid Build Coastguard Worker job->state->values[0].integer = IPP_JOB_PENDING;
1744*5e7646d2SAndroid Build Coastguard Worker job->state_value = IPP_JOB_PENDING;
1745*5e7646d2SAndroid Build Coastguard Worker
1746*5e7646d2SAndroid Build Coastguard Worker ippSetString(job->attrs, &job->reasons, 0, "none");
1747*5e7646d2SAndroid Build Coastguard Worker }
1748*5e7646d2SAndroid Build Coastguard Worker
1749*5e7646d2SAndroid Build Coastguard Worker if (!(printer->type & CUPS_PRINTER_REMOTE) || Classification)
1750*5e7646d2SAndroid Build Coastguard Worker {
1751*5e7646d2SAndroid Build Coastguard Worker /*
1752*5e7646d2SAndroid Build Coastguard Worker * Add job sheets options...
1753*5e7646d2SAndroid Build Coastguard Worker */
1754*5e7646d2SAndroid Build Coastguard Worker
1755*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippFindAttribute(job->attrs, "job-sheets",
1756*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_ZERO)) == NULL)
1757*5e7646d2SAndroid Build Coastguard Worker {
1758*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG,
1759*5e7646d2SAndroid Build Coastguard Worker "Adding default job-sheets values \"%s,%s\"...",
1760*5e7646d2SAndroid Build Coastguard Worker printer->job_sheets[0], printer->job_sheets[1]);
1761*5e7646d2SAndroid Build Coastguard Worker
1762*5e7646d2SAndroid Build Coastguard Worker attr = ippAddStrings(job->attrs, IPP_TAG_JOB, IPP_TAG_NAME, "job-sheets",
1763*5e7646d2SAndroid Build Coastguard Worker 2, NULL, NULL);
1764*5e7646d2SAndroid Build Coastguard Worker ippSetString(job->attrs, &attr, 0, printer->job_sheets[0]);
1765*5e7646d2SAndroid Build Coastguard Worker ippSetString(job->attrs, &attr, 1, printer->job_sheets[1]);
1766*5e7646d2SAndroid Build Coastguard Worker }
1767*5e7646d2SAndroid Build Coastguard Worker
1768*5e7646d2SAndroid Build Coastguard Worker job->job_sheets = attr;
1769*5e7646d2SAndroid Build Coastguard Worker
1770*5e7646d2SAndroid Build Coastguard Worker /*
1771*5e7646d2SAndroid Build Coastguard Worker * Enforce classification level if set...
1772*5e7646d2SAndroid Build Coastguard Worker */
1773*5e7646d2SAndroid Build Coastguard Worker
1774*5e7646d2SAndroid Build Coastguard Worker if (Classification)
1775*5e7646d2SAndroid Build Coastguard Worker {
1776*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_INFO,
1777*5e7646d2SAndroid Build Coastguard Worker "Classification=\"%s\", ClassifyOverride=%d",
1778*5e7646d2SAndroid Build Coastguard Worker Classification ? Classification : "(null)",
1779*5e7646d2SAndroid Build Coastguard Worker ClassifyOverride);
1780*5e7646d2SAndroid Build Coastguard Worker
1781*5e7646d2SAndroid Build Coastguard Worker if (ClassifyOverride)
1782*5e7646d2SAndroid Build Coastguard Worker {
1783*5e7646d2SAndroid Build Coastguard Worker if (!strcmp(attr->values[0].string.text, "none") &&
1784*5e7646d2SAndroid Build Coastguard Worker (attr->num_values == 1 ||
1785*5e7646d2SAndroid Build Coastguard Worker !strcmp(attr->values[1].string.text, "none")))
1786*5e7646d2SAndroid Build Coastguard Worker {
1787*5e7646d2SAndroid Build Coastguard Worker /*
1788*5e7646d2SAndroid Build Coastguard Worker * Force the leading banner to have the classification on it...
1789*5e7646d2SAndroid Build Coastguard Worker */
1790*5e7646d2SAndroid Build Coastguard Worker
1791*5e7646d2SAndroid Build Coastguard Worker ippSetString(job->attrs, &attr, 0, Classification);
1792*5e7646d2SAndroid Build Coastguard Worker
1793*5e7646d2SAndroid Build Coastguard Worker cupsdLogJob(job, CUPSD_LOG_NOTICE, "CLASSIFICATION FORCED "
1794*5e7646d2SAndroid Build Coastguard Worker "job-sheets=\"%s,none\", "
1795*5e7646d2SAndroid Build Coastguard Worker "job-originating-user-name=\"%s\"",
1796*5e7646d2SAndroid Build Coastguard Worker Classification, job->username);
1797*5e7646d2SAndroid Build Coastguard Worker }
1798*5e7646d2SAndroid Build Coastguard Worker else if (attr->num_values == 2 &&
1799*5e7646d2SAndroid Build Coastguard Worker strcmp(attr->values[0].string.text,
1800*5e7646d2SAndroid Build Coastguard Worker attr->values[1].string.text) &&
1801*5e7646d2SAndroid Build Coastguard Worker strcmp(attr->values[0].string.text, "none") &&
1802*5e7646d2SAndroid Build Coastguard Worker strcmp(attr->values[1].string.text, "none"))
1803*5e7646d2SAndroid Build Coastguard Worker {
1804*5e7646d2SAndroid Build Coastguard Worker /*
1805*5e7646d2SAndroid Build Coastguard Worker * Can't put two different security markings on the same document!
1806*5e7646d2SAndroid Build Coastguard Worker */
1807*5e7646d2SAndroid Build Coastguard Worker
1808*5e7646d2SAndroid Build Coastguard Worker ippSetString(job->attrs, &attr, 1, attr->values[0].string.text);
1809*5e7646d2SAndroid Build Coastguard Worker
1810*5e7646d2SAndroid Build Coastguard Worker cupsdLogJob(job, CUPSD_LOG_NOTICE, "CLASSIFICATION FORCED "
1811*5e7646d2SAndroid Build Coastguard Worker "job-sheets=\"%s,%s\", "
1812*5e7646d2SAndroid Build Coastguard Worker "job-originating-user-name=\"%s\"",
1813*5e7646d2SAndroid Build Coastguard Worker attr->values[0].string.text,
1814*5e7646d2SAndroid Build Coastguard Worker attr->values[1].string.text, job->username);
1815*5e7646d2SAndroid Build Coastguard Worker }
1816*5e7646d2SAndroid Build Coastguard Worker else if (strcmp(attr->values[0].string.text, Classification) &&
1817*5e7646d2SAndroid Build Coastguard Worker strcmp(attr->values[0].string.text, "none") &&
1818*5e7646d2SAndroid Build Coastguard Worker (attr->num_values == 1 ||
1819*5e7646d2SAndroid Build Coastguard Worker (strcmp(attr->values[1].string.text, Classification) &&
1820*5e7646d2SAndroid Build Coastguard Worker strcmp(attr->values[1].string.text, "none"))))
1821*5e7646d2SAndroid Build Coastguard Worker {
1822*5e7646d2SAndroid Build Coastguard Worker if (attr->num_values == 1)
1823*5e7646d2SAndroid Build Coastguard Worker cupsdLogJob(job, CUPSD_LOG_NOTICE,
1824*5e7646d2SAndroid Build Coastguard Worker "CLASSIFICATION OVERRIDDEN "
1825*5e7646d2SAndroid Build Coastguard Worker "job-sheets=\"%s\", "
1826*5e7646d2SAndroid Build Coastguard Worker "job-originating-user-name=\"%s\"",
1827*5e7646d2SAndroid Build Coastguard Worker attr->values[0].string.text, job->username);
1828*5e7646d2SAndroid Build Coastguard Worker else
1829*5e7646d2SAndroid Build Coastguard Worker cupsdLogJob(job, CUPSD_LOG_NOTICE,
1830*5e7646d2SAndroid Build Coastguard Worker "CLASSIFICATION OVERRIDDEN "
1831*5e7646d2SAndroid Build Coastguard Worker "job-sheets=\"%s,%s\",fffff "
1832*5e7646d2SAndroid Build Coastguard Worker "job-originating-user-name=\"%s\"",
1833*5e7646d2SAndroid Build Coastguard Worker attr->values[0].string.text,
1834*5e7646d2SAndroid Build Coastguard Worker attr->values[1].string.text, job->username);
1835*5e7646d2SAndroid Build Coastguard Worker }
1836*5e7646d2SAndroid Build Coastguard Worker }
1837*5e7646d2SAndroid Build Coastguard Worker else if (strcmp(attr->values[0].string.text, Classification) &&
1838*5e7646d2SAndroid Build Coastguard Worker (attr->num_values == 1 ||
1839*5e7646d2SAndroid Build Coastguard Worker strcmp(attr->values[1].string.text, Classification)))
1840*5e7646d2SAndroid Build Coastguard Worker {
1841*5e7646d2SAndroid Build Coastguard Worker /*
1842*5e7646d2SAndroid Build Coastguard Worker * Force the banner to have the classification on it...
1843*5e7646d2SAndroid Build Coastguard Worker */
1844*5e7646d2SAndroid Build Coastguard Worker
1845*5e7646d2SAndroid Build Coastguard Worker if (attr->num_values > 1 &&
1846*5e7646d2SAndroid Build Coastguard Worker !strcmp(attr->values[0].string.text, attr->values[1].string.text))
1847*5e7646d2SAndroid Build Coastguard Worker {
1848*5e7646d2SAndroid Build Coastguard Worker ippSetString(job->attrs, &attr, 0, Classification);
1849*5e7646d2SAndroid Build Coastguard Worker ippSetString(job->attrs, &attr, 1, Classification);
1850*5e7646d2SAndroid Build Coastguard Worker }
1851*5e7646d2SAndroid Build Coastguard Worker else
1852*5e7646d2SAndroid Build Coastguard Worker {
1853*5e7646d2SAndroid Build Coastguard Worker if (attr->num_values == 1 ||
1854*5e7646d2SAndroid Build Coastguard Worker strcmp(attr->values[0].string.text, "none"))
1855*5e7646d2SAndroid Build Coastguard Worker ippSetString(job->attrs, &attr, 0, Classification);
1856*5e7646d2SAndroid Build Coastguard Worker
1857*5e7646d2SAndroid Build Coastguard Worker if (attr->num_values > 1 &&
1858*5e7646d2SAndroid Build Coastguard Worker strcmp(attr->values[1].string.text, "none"))
1859*5e7646d2SAndroid Build Coastguard Worker ippSetString(job->attrs, &attr, 1, Classification);
1860*5e7646d2SAndroid Build Coastguard Worker }
1861*5e7646d2SAndroid Build Coastguard Worker
1862*5e7646d2SAndroid Build Coastguard Worker if (attr->num_values > 1)
1863*5e7646d2SAndroid Build Coastguard Worker cupsdLogJob(job, CUPSD_LOG_NOTICE,
1864*5e7646d2SAndroid Build Coastguard Worker "CLASSIFICATION FORCED "
1865*5e7646d2SAndroid Build Coastguard Worker "job-sheets=\"%s,%s\", "
1866*5e7646d2SAndroid Build Coastguard Worker "job-originating-user-name=\"%s\"",
1867*5e7646d2SAndroid Build Coastguard Worker attr->values[0].string.text,
1868*5e7646d2SAndroid Build Coastguard Worker attr->values[1].string.text, job->username);
1869*5e7646d2SAndroid Build Coastguard Worker else
1870*5e7646d2SAndroid Build Coastguard Worker cupsdLogJob(job, CUPSD_LOG_NOTICE,
1871*5e7646d2SAndroid Build Coastguard Worker "CLASSIFICATION FORCED "
1872*5e7646d2SAndroid Build Coastguard Worker "job-sheets=\"%s\", "
1873*5e7646d2SAndroid Build Coastguard Worker "job-originating-user-name=\"%s\"",
1874*5e7646d2SAndroid Build Coastguard Worker Classification, job->username);
1875*5e7646d2SAndroid Build Coastguard Worker }
1876*5e7646d2SAndroid Build Coastguard Worker }
1877*5e7646d2SAndroid Build Coastguard Worker
1878*5e7646d2SAndroid Build Coastguard Worker /*
1879*5e7646d2SAndroid Build Coastguard Worker * See if we need to add the starting sheet...
1880*5e7646d2SAndroid Build Coastguard Worker */
1881*5e7646d2SAndroid Build Coastguard Worker
1882*5e7646d2SAndroid Build Coastguard Worker if (!(printer->type & CUPS_PRINTER_REMOTE))
1883*5e7646d2SAndroid Build Coastguard Worker {
1884*5e7646d2SAndroid Build Coastguard Worker cupsdLogJob(job, CUPSD_LOG_INFO, "Adding start banner page \"%s\".",
1885*5e7646d2SAndroid Build Coastguard Worker attr->values[0].string.text);
1886*5e7646d2SAndroid Build Coastguard Worker
1887*5e7646d2SAndroid Build Coastguard Worker if ((kbytes = copy_banner(con, job, attr->values[0].string.text)) < 0)
1888*5e7646d2SAndroid Build Coastguard Worker {
1889*5e7646d2SAndroid Build Coastguard Worker cupsdSetJobState(job, IPP_JOB_ABORTED, CUPSD_JOB_PURGE,
1890*5e7646d2SAndroid Build Coastguard Worker "Aborting job because the start banner could not be "
1891*5e7646d2SAndroid Build Coastguard Worker "copied.");
1892*5e7646d2SAndroid Build Coastguard Worker return (NULL);
1893*5e7646d2SAndroid Build Coastguard Worker }
1894*5e7646d2SAndroid Build Coastguard Worker
1895*5e7646d2SAndroid Build Coastguard Worker cupsdUpdateQuota(printer, job->username, 0, kbytes);
1896*5e7646d2SAndroid Build Coastguard Worker }
1897*5e7646d2SAndroid Build Coastguard Worker }
1898*5e7646d2SAndroid Build Coastguard Worker else if ((attr = ippFindAttribute(job->attrs, "job-sheets",
1899*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_ZERO)) != NULL)
1900*5e7646d2SAndroid Build Coastguard Worker job->job_sheets = attr;
1901*5e7646d2SAndroid Build Coastguard Worker
1902*5e7646d2SAndroid Build Coastguard Worker /*
1903*5e7646d2SAndroid Build Coastguard Worker * Fill in the response info...
1904*5e7646d2SAndroid Build Coastguard Worker */
1905*5e7646d2SAndroid Build Coastguard Worker
1906*5e7646d2SAndroid Build Coastguard Worker httpAssembleURIf(HTTP_URI_CODING_ALL, job_uri, sizeof(job_uri), "ipp", NULL, con->clientname, con->clientport, "/jobs/%d", job->id);
1907*5e7646d2SAndroid Build Coastguard Worker ippAddString(con->response, IPP_TAG_JOB, IPP_TAG_URI, "job-uri", NULL, job_uri);
1908*5e7646d2SAndroid Build Coastguard Worker
1909*5e7646d2SAndroid Build Coastguard Worker ippAddInteger(con->response, IPP_TAG_JOB, IPP_TAG_INTEGER, "job-id", job->id);
1910*5e7646d2SAndroid Build Coastguard Worker
1911*5e7646d2SAndroid Build Coastguard Worker ippAddInteger(con->response, IPP_TAG_JOB, IPP_TAG_ENUM, "job-state", (int)job->state_value);
1912*5e7646d2SAndroid Build Coastguard Worker ippAddString(con->response, IPP_TAG_JOB, IPP_TAG_TEXT, "job-state-message", NULL, "");
1913*5e7646d2SAndroid Build Coastguard Worker ippAddString(con->response, IPP_TAG_JOB, IPP_TAG_KEYWORD, "job-state-reasons", NULL, job->reasons->values[0].string.text);
1914*5e7646d2SAndroid Build Coastguard Worker
1915*5e7646d2SAndroid Build Coastguard Worker con->response->request.status.status_code = IPP_OK;
1916*5e7646d2SAndroid Build Coastguard Worker
1917*5e7646d2SAndroid Build Coastguard Worker /*
1918*5e7646d2SAndroid Build Coastguard Worker * Add any job subscriptions...
1919*5e7646d2SAndroid Build Coastguard Worker */
1920*5e7646d2SAndroid Build Coastguard Worker
1921*5e7646d2SAndroid Build Coastguard Worker add_job_subscriptions(con, job);
1922*5e7646d2SAndroid Build Coastguard Worker
1923*5e7646d2SAndroid Build Coastguard Worker /*
1924*5e7646d2SAndroid Build Coastguard Worker * Set all but the first two attributes to the job attributes group...
1925*5e7646d2SAndroid Build Coastguard Worker */
1926*5e7646d2SAndroid Build Coastguard Worker
1927*5e7646d2SAndroid Build Coastguard Worker for (attr = job->attrs->attrs->next->next; attr; attr = attr->next)
1928*5e7646d2SAndroid Build Coastguard Worker attr->group_tag = IPP_TAG_JOB;
1929*5e7646d2SAndroid Build Coastguard Worker
1930*5e7646d2SAndroid Build Coastguard Worker /*
1931*5e7646d2SAndroid Build Coastguard Worker * Fire the "job created" event...
1932*5e7646d2SAndroid Build Coastguard Worker */
1933*5e7646d2SAndroid Build Coastguard Worker
1934*5e7646d2SAndroid Build Coastguard Worker cupsdAddEvent(CUPSD_EVENT_JOB_CREATED, printer, job, "Job created.");
1935*5e7646d2SAndroid Build Coastguard Worker
1936*5e7646d2SAndroid Build Coastguard Worker /*
1937*5e7646d2SAndroid Build Coastguard Worker * Return the new job...
1938*5e7646d2SAndroid Build Coastguard Worker */
1939*5e7646d2SAndroid Build Coastguard Worker
1940*5e7646d2SAndroid Build Coastguard Worker return (job);
1941*5e7646d2SAndroid Build Coastguard Worker }
1942*5e7646d2SAndroid Build Coastguard Worker
1943*5e7646d2SAndroid Build Coastguard Worker
1944*5e7646d2SAndroid Build Coastguard Worker /*
1945*5e7646d2SAndroid Build Coastguard Worker * 'add_job_subscriptions()' - Add any subscriptions for a job.
1946*5e7646d2SAndroid Build Coastguard Worker */
1947*5e7646d2SAndroid Build Coastguard Worker
1948*5e7646d2SAndroid Build Coastguard Worker static void
add_job_subscriptions(cupsd_client_t * con,cupsd_job_t * job)1949*5e7646d2SAndroid Build Coastguard Worker add_job_subscriptions(
1950*5e7646d2SAndroid Build Coastguard Worker cupsd_client_t *con, /* I - Client connection */
1951*5e7646d2SAndroid Build Coastguard Worker cupsd_job_t *job) /* I - Newly created job */
1952*5e7646d2SAndroid Build Coastguard Worker {
1953*5e7646d2SAndroid Build Coastguard Worker int i; /* Looping var */
1954*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *prev, /* Previous attribute */
1955*5e7646d2SAndroid Build Coastguard Worker *next, /* Next attribute */
1956*5e7646d2SAndroid Build Coastguard Worker *attr; /* Current attribute */
1957*5e7646d2SAndroid Build Coastguard Worker cupsd_subscription_t *sub; /* Subscription object */
1958*5e7646d2SAndroid Build Coastguard Worker const char *recipient, /* notify-recipient-uri */
1959*5e7646d2SAndroid Build Coastguard Worker *pullmethod; /* notify-pull-method */
1960*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *user_data; /* notify-user-data */
1961*5e7646d2SAndroid Build Coastguard Worker int interval; /* notify-time-interval */
1962*5e7646d2SAndroid Build Coastguard Worker unsigned mask; /* notify-events */
1963*5e7646d2SAndroid Build Coastguard Worker
1964*5e7646d2SAndroid Build Coastguard Worker
1965*5e7646d2SAndroid Build Coastguard Worker /*
1966*5e7646d2SAndroid Build Coastguard Worker * Find the first subscription group attribute; return if we have
1967*5e7646d2SAndroid Build Coastguard Worker * none...
1968*5e7646d2SAndroid Build Coastguard Worker */
1969*5e7646d2SAndroid Build Coastguard Worker
1970*5e7646d2SAndroid Build Coastguard Worker for (attr = job->attrs->attrs; attr; attr = attr->next)
1971*5e7646d2SAndroid Build Coastguard Worker if (attr->group_tag == IPP_TAG_SUBSCRIPTION)
1972*5e7646d2SAndroid Build Coastguard Worker break;
1973*5e7646d2SAndroid Build Coastguard Worker
1974*5e7646d2SAndroid Build Coastguard Worker if (!attr)
1975*5e7646d2SAndroid Build Coastguard Worker return;
1976*5e7646d2SAndroid Build Coastguard Worker
1977*5e7646d2SAndroid Build Coastguard Worker /*
1978*5e7646d2SAndroid Build Coastguard Worker * Process the subscription attributes in the request...
1979*5e7646d2SAndroid Build Coastguard Worker */
1980*5e7646d2SAndroid Build Coastguard Worker
1981*5e7646d2SAndroid Build Coastguard Worker while (attr)
1982*5e7646d2SAndroid Build Coastguard Worker {
1983*5e7646d2SAndroid Build Coastguard Worker recipient = NULL;
1984*5e7646d2SAndroid Build Coastguard Worker pullmethod = NULL;
1985*5e7646d2SAndroid Build Coastguard Worker user_data = NULL;
1986*5e7646d2SAndroid Build Coastguard Worker interval = 0;
1987*5e7646d2SAndroid Build Coastguard Worker mask = CUPSD_EVENT_NONE;
1988*5e7646d2SAndroid Build Coastguard Worker
1989*5e7646d2SAndroid Build Coastguard Worker while (attr && attr->group_tag != IPP_TAG_ZERO)
1990*5e7646d2SAndroid Build Coastguard Worker {
1991*5e7646d2SAndroid Build Coastguard Worker if (!strcmp(attr->name, "notify-recipient-uri") &&
1992*5e7646d2SAndroid Build Coastguard Worker attr->value_tag == IPP_TAG_URI)
1993*5e7646d2SAndroid Build Coastguard Worker {
1994*5e7646d2SAndroid Build Coastguard Worker /*
1995*5e7646d2SAndroid Build Coastguard Worker * Validate the recipient scheme against the ServerBin/notifier
1996*5e7646d2SAndroid Build Coastguard Worker * directory...
1997*5e7646d2SAndroid Build Coastguard Worker */
1998*5e7646d2SAndroid Build Coastguard Worker
1999*5e7646d2SAndroid Build Coastguard Worker char notifier[1024], /* Notifier filename */
2000*5e7646d2SAndroid Build Coastguard Worker scheme[HTTP_MAX_URI], /* Scheme portion of URI */
2001*5e7646d2SAndroid Build Coastguard Worker userpass[HTTP_MAX_URI], /* Username portion of URI */
2002*5e7646d2SAndroid Build Coastguard Worker host[HTTP_MAX_URI], /* Host portion of URI */
2003*5e7646d2SAndroid Build Coastguard Worker resource[HTTP_MAX_URI]; /* Resource portion of URI */
2004*5e7646d2SAndroid Build Coastguard Worker int port; /* Port portion of URI */
2005*5e7646d2SAndroid Build Coastguard Worker struct stat info; /* File information */
2006*5e7646d2SAndroid Build Coastguard Worker
2007*5e7646d2SAndroid Build Coastguard Worker recipient = attr->values[0].string.text;
2008*5e7646d2SAndroid Build Coastguard Worker
2009*5e7646d2SAndroid Build Coastguard Worker if (httpSeparateURI(HTTP_URI_CODING_ALL, recipient,
2010*5e7646d2SAndroid Build Coastguard Worker scheme, sizeof(scheme), userpass, sizeof(userpass),
2011*5e7646d2SAndroid Build Coastguard Worker host, sizeof(host), &port,
2012*5e7646d2SAndroid Build Coastguard Worker resource, sizeof(resource)) < HTTP_URI_OK)
2013*5e7646d2SAndroid Build Coastguard Worker {
2014*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_NOT_POSSIBLE,
2015*5e7646d2SAndroid Build Coastguard Worker _("Bad notify-recipient-uri \"%s\"."), recipient);
2016*5e7646d2SAndroid Build Coastguard Worker ippAddInteger(con->response, IPP_TAG_SUBSCRIPTION, IPP_TAG_ENUM,
2017*5e7646d2SAndroid Build Coastguard Worker "notify-status-code", IPP_URI_SCHEME);
2018*5e7646d2SAndroid Build Coastguard Worker return;
2019*5e7646d2SAndroid Build Coastguard Worker }
2020*5e7646d2SAndroid Build Coastguard Worker
2021*5e7646d2SAndroid Build Coastguard Worker snprintf(notifier, sizeof(notifier), "%s/notifier/%s", ServerBin, scheme);
2022*5e7646d2SAndroid Build Coastguard Worker if (access(notifier, X_OK) || stat(notifier, &info) || !S_ISREG(info.st_mode))
2023*5e7646d2SAndroid Build Coastguard Worker {
2024*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_NOT_POSSIBLE,
2025*5e7646d2SAndroid Build Coastguard Worker _("notify-recipient-uri URI \"%s\" uses unknown "
2026*5e7646d2SAndroid Build Coastguard Worker "scheme."), recipient);
2027*5e7646d2SAndroid Build Coastguard Worker ippAddInteger(con->response, IPP_TAG_SUBSCRIPTION, IPP_TAG_ENUM,
2028*5e7646d2SAndroid Build Coastguard Worker "notify-status-code", IPP_URI_SCHEME);
2029*5e7646d2SAndroid Build Coastguard Worker return;
2030*5e7646d2SAndroid Build Coastguard Worker }
2031*5e7646d2SAndroid Build Coastguard Worker
2032*5e7646d2SAndroid Build Coastguard Worker if (!strcmp(scheme, "rss") && !check_rss_recipient(recipient))
2033*5e7646d2SAndroid Build Coastguard Worker {
2034*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_NOT_POSSIBLE,
2035*5e7646d2SAndroid Build Coastguard Worker _("notify-recipient-uri URI \"%s\" is already used."),
2036*5e7646d2SAndroid Build Coastguard Worker recipient);
2037*5e7646d2SAndroid Build Coastguard Worker ippAddInteger(con->response, IPP_TAG_SUBSCRIPTION, IPP_TAG_ENUM,
2038*5e7646d2SAndroid Build Coastguard Worker "notify-status-code", IPP_ATTRIBUTES);
2039*5e7646d2SAndroid Build Coastguard Worker return;
2040*5e7646d2SAndroid Build Coastguard Worker }
2041*5e7646d2SAndroid Build Coastguard Worker }
2042*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(attr->name, "notify-pull-method") &&
2043*5e7646d2SAndroid Build Coastguard Worker attr->value_tag == IPP_TAG_KEYWORD)
2044*5e7646d2SAndroid Build Coastguard Worker {
2045*5e7646d2SAndroid Build Coastguard Worker pullmethod = attr->values[0].string.text;
2046*5e7646d2SAndroid Build Coastguard Worker
2047*5e7646d2SAndroid Build Coastguard Worker if (strcmp(pullmethod, "ippget"))
2048*5e7646d2SAndroid Build Coastguard Worker {
2049*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_NOT_POSSIBLE,
2050*5e7646d2SAndroid Build Coastguard Worker _("Bad notify-pull-method \"%s\"."), pullmethod);
2051*5e7646d2SAndroid Build Coastguard Worker ippAddInteger(con->response, IPP_TAG_SUBSCRIPTION, IPP_TAG_ENUM,
2052*5e7646d2SAndroid Build Coastguard Worker "notify-status-code", IPP_ATTRIBUTES);
2053*5e7646d2SAndroid Build Coastguard Worker return;
2054*5e7646d2SAndroid Build Coastguard Worker }
2055*5e7646d2SAndroid Build Coastguard Worker }
2056*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(attr->name, "notify-charset") &&
2057*5e7646d2SAndroid Build Coastguard Worker attr->value_tag == IPP_TAG_CHARSET &&
2058*5e7646d2SAndroid Build Coastguard Worker strcmp(attr->values[0].string.text, "us-ascii") &&
2059*5e7646d2SAndroid Build Coastguard Worker strcmp(attr->values[0].string.text, "utf-8"))
2060*5e7646d2SAndroid Build Coastguard Worker {
2061*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_CHARSET,
2062*5e7646d2SAndroid Build Coastguard Worker _("Character set \"%s\" not supported."),
2063*5e7646d2SAndroid Build Coastguard Worker attr->values[0].string.text);
2064*5e7646d2SAndroid Build Coastguard Worker return;
2065*5e7646d2SAndroid Build Coastguard Worker }
2066*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(attr->name, "notify-natural-language") &&
2067*5e7646d2SAndroid Build Coastguard Worker (attr->value_tag != IPP_TAG_LANGUAGE ||
2068*5e7646d2SAndroid Build Coastguard Worker strcmp(attr->values[0].string.text, DefaultLanguage)))
2069*5e7646d2SAndroid Build Coastguard Worker {
2070*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_CHARSET,
2071*5e7646d2SAndroid Build Coastguard Worker _("Language \"%s\" not supported."),
2072*5e7646d2SAndroid Build Coastguard Worker attr->values[0].string.text);
2073*5e7646d2SAndroid Build Coastguard Worker return;
2074*5e7646d2SAndroid Build Coastguard Worker }
2075*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(attr->name, "notify-user-data") &&
2076*5e7646d2SAndroid Build Coastguard Worker attr->value_tag == IPP_TAG_STRING)
2077*5e7646d2SAndroid Build Coastguard Worker {
2078*5e7646d2SAndroid Build Coastguard Worker if (attr->num_values > 1 || attr->values[0].unknown.length > 63)
2079*5e7646d2SAndroid Build Coastguard Worker {
2080*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_REQUEST_VALUE,
2081*5e7646d2SAndroid Build Coastguard Worker _("The notify-user-data value is too large "
2082*5e7646d2SAndroid Build Coastguard Worker "(%d > 63 octets)."),
2083*5e7646d2SAndroid Build Coastguard Worker attr->values[0].unknown.length);
2084*5e7646d2SAndroid Build Coastguard Worker return;
2085*5e7646d2SAndroid Build Coastguard Worker }
2086*5e7646d2SAndroid Build Coastguard Worker
2087*5e7646d2SAndroid Build Coastguard Worker user_data = attr;
2088*5e7646d2SAndroid Build Coastguard Worker }
2089*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(attr->name, "notify-events") &&
2090*5e7646d2SAndroid Build Coastguard Worker attr->value_tag == IPP_TAG_KEYWORD)
2091*5e7646d2SAndroid Build Coastguard Worker {
2092*5e7646d2SAndroid Build Coastguard Worker for (i = 0; i < attr->num_values; i ++)
2093*5e7646d2SAndroid Build Coastguard Worker mask |= cupsdEventValue(attr->values[i].string.text);
2094*5e7646d2SAndroid Build Coastguard Worker }
2095*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(attr->name, "notify-lease-duration"))
2096*5e7646d2SAndroid Build Coastguard Worker {
2097*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_BAD_REQUEST,
2098*5e7646d2SAndroid Build Coastguard Worker _("The notify-lease-duration attribute cannot be "
2099*5e7646d2SAndroid Build Coastguard Worker "used with job subscriptions."));
2100*5e7646d2SAndroid Build Coastguard Worker return;
2101*5e7646d2SAndroid Build Coastguard Worker }
2102*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(attr->name, "notify-time-interval") &&
2103*5e7646d2SAndroid Build Coastguard Worker attr->value_tag == IPP_TAG_INTEGER)
2104*5e7646d2SAndroid Build Coastguard Worker interval = attr->values[0].integer;
2105*5e7646d2SAndroid Build Coastguard Worker
2106*5e7646d2SAndroid Build Coastguard Worker attr = attr->next;
2107*5e7646d2SAndroid Build Coastguard Worker }
2108*5e7646d2SAndroid Build Coastguard Worker
2109*5e7646d2SAndroid Build Coastguard Worker if (!recipient && !pullmethod)
2110*5e7646d2SAndroid Build Coastguard Worker break;
2111*5e7646d2SAndroid Build Coastguard Worker
2112*5e7646d2SAndroid Build Coastguard Worker if (mask == CUPSD_EVENT_NONE)
2113*5e7646d2SAndroid Build Coastguard Worker mask = CUPSD_EVENT_JOB_COMPLETED;
2114*5e7646d2SAndroid Build Coastguard Worker
2115*5e7646d2SAndroid Build Coastguard Worker if ((sub = cupsdAddSubscription(mask, cupsdFindDest(job->dest), job,
2116*5e7646d2SAndroid Build Coastguard Worker recipient, 0)) != NULL)
2117*5e7646d2SAndroid Build Coastguard Worker {
2118*5e7646d2SAndroid Build Coastguard Worker sub->interval = interval;
2119*5e7646d2SAndroid Build Coastguard Worker
2120*5e7646d2SAndroid Build Coastguard Worker cupsdSetString(&sub->owner, job->username);
2121*5e7646d2SAndroid Build Coastguard Worker
2122*5e7646d2SAndroid Build Coastguard Worker if (user_data)
2123*5e7646d2SAndroid Build Coastguard Worker {
2124*5e7646d2SAndroid Build Coastguard Worker sub->user_data_len = user_data->values[0].unknown.length;
2125*5e7646d2SAndroid Build Coastguard Worker memcpy(sub->user_data, user_data->values[0].unknown.data,
2126*5e7646d2SAndroid Build Coastguard Worker (size_t)sub->user_data_len);
2127*5e7646d2SAndroid Build Coastguard Worker }
2128*5e7646d2SAndroid Build Coastguard Worker
2129*5e7646d2SAndroid Build Coastguard Worker ippAddSeparator(con->response);
2130*5e7646d2SAndroid Build Coastguard Worker ippAddInteger(con->response, IPP_TAG_SUBSCRIPTION, IPP_TAG_INTEGER,
2131*5e7646d2SAndroid Build Coastguard Worker "notify-subscription-id", sub->id);
2132*5e7646d2SAndroid Build Coastguard Worker
2133*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG, "Added subscription %d for job %d",
2134*5e7646d2SAndroid Build Coastguard Worker sub->id, job->id);
2135*5e7646d2SAndroid Build Coastguard Worker }
2136*5e7646d2SAndroid Build Coastguard Worker
2137*5e7646d2SAndroid Build Coastguard Worker if (attr)
2138*5e7646d2SAndroid Build Coastguard Worker attr = attr->next;
2139*5e7646d2SAndroid Build Coastguard Worker }
2140*5e7646d2SAndroid Build Coastguard Worker
2141*5e7646d2SAndroid Build Coastguard Worker cupsdMarkDirty(CUPSD_DIRTY_SUBSCRIPTIONS);
2142*5e7646d2SAndroid Build Coastguard Worker
2143*5e7646d2SAndroid Build Coastguard Worker /*
2144*5e7646d2SAndroid Build Coastguard Worker * Remove all of the subscription attributes from the job request...
2145*5e7646d2SAndroid Build Coastguard Worker *
2146*5e7646d2SAndroid Build Coastguard Worker * TODO: Optimize this since subscription groups have to come at the
2147*5e7646d2SAndroid Build Coastguard Worker * end of the request...
2148*5e7646d2SAndroid Build Coastguard Worker */
2149*5e7646d2SAndroid Build Coastguard Worker
2150*5e7646d2SAndroid Build Coastguard Worker for (attr = job->attrs->attrs, prev = NULL; attr; attr = next)
2151*5e7646d2SAndroid Build Coastguard Worker {
2152*5e7646d2SAndroid Build Coastguard Worker next = attr->next;
2153*5e7646d2SAndroid Build Coastguard Worker
2154*5e7646d2SAndroid Build Coastguard Worker if (attr->group_tag == IPP_TAG_SUBSCRIPTION ||
2155*5e7646d2SAndroid Build Coastguard Worker attr->group_tag == IPP_TAG_ZERO)
2156*5e7646d2SAndroid Build Coastguard Worker {
2157*5e7646d2SAndroid Build Coastguard Worker /*
2158*5e7646d2SAndroid Build Coastguard Worker * Free and remove this attribute...
2159*5e7646d2SAndroid Build Coastguard Worker */
2160*5e7646d2SAndroid Build Coastguard Worker
2161*5e7646d2SAndroid Build Coastguard Worker ippDeleteAttribute(NULL, attr);
2162*5e7646d2SAndroid Build Coastguard Worker
2163*5e7646d2SAndroid Build Coastguard Worker if (prev)
2164*5e7646d2SAndroid Build Coastguard Worker prev->next = next;
2165*5e7646d2SAndroid Build Coastguard Worker else
2166*5e7646d2SAndroid Build Coastguard Worker job->attrs->attrs = next;
2167*5e7646d2SAndroid Build Coastguard Worker }
2168*5e7646d2SAndroid Build Coastguard Worker else
2169*5e7646d2SAndroid Build Coastguard Worker prev = attr;
2170*5e7646d2SAndroid Build Coastguard Worker }
2171*5e7646d2SAndroid Build Coastguard Worker
2172*5e7646d2SAndroid Build Coastguard Worker job->attrs->last = prev;
2173*5e7646d2SAndroid Build Coastguard Worker job->attrs->current = prev;
2174*5e7646d2SAndroid Build Coastguard Worker }
2175*5e7646d2SAndroid Build Coastguard Worker
2176*5e7646d2SAndroid Build Coastguard Worker
2177*5e7646d2SAndroid Build Coastguard Worker /*
2178*5e7646d2SAndroid Build Coastguard Worker * 'add_job_uuid()' - Add job-uuid attribute to a job.
2179*5e7646d2SAndroid Build Coastguard Worker *
2180*5e7646d2SAndroid Build Coastguard Worker * See RFC 4122 for the definition of UUIDs and the format.
2181*5e7646d2SAndroid Build Coastguard Worker */
2182*5e7646d2SAndroid Build Coastguard Worker
2183*5e7646d2SAndroid Build Coastguard Worker static void
add_job_uuid(cupsd_job_t * job)2184*5e7646d2SAndroid Build Coastguard Worker add_job_uuid(cupsd_job_t *job) /* I - Job */
2185*5e7646d2SAndroid Build Coastguard Worker {
2186*5e7646d2SAndroid Build Coastguard Worker char uuid[64]; /* job-uuid string */
2187*5e7646d2SAndroid Build Coastguard Worker
2188*5e7646d2SAndroid Build Coastguard Worker
2189*5e7646d2SAndroid Build Coastguard Worker /*
2190*5e7646d2SAndroid Build Coastguard Worker * Add a job-uuid attribute if none exists...
2191*5e7646d2SAndroid Build Coastguard Worker */
2192*5e7646d2SAndroid Build Coastguard Worker
2193*5e7646d2SAndroid Build Coastguard Worker if (!ippFindAttribute(job->attrs, "job-uuid", IPP_TAG_URI))
2194*5e7646d2SAndroid Build Coastguard Worker ippAddString(job->attrs, IPP_TAG_JOB, IPP_TAG_URI, "job-uuid", NULL,
2195*5e7646d2SAndroid Build Coastguard Worker httpAssembleUUID(ServerName, RemotePort, job->dest, job->id,
2196*5e7646d2SAndroid Build Coastguard Worker uuid, sizeof(uuid)));
2197*5e7646d2SAndroid Build Coastguard Worker }
2198*5e7646d2SAndroid Build Coastguard Worker
2199*5e7646d2SAndroid Build Coastguard Worker
2200*5e7646d2SAndroid Build Coastguard Worker /*
2201*5e7646d2SAndroid Build Coastguard Worker * 'add_printer()' - Add a printer to the system.
2202*5e7646d2SAndroid Build Coastguard Worker */
2203*5e7646d2SAndroid Build Coastguard Worker
2204*5e7646d2SAndroid Build Coastguard Worker static void
add_printer(cupsd_client_t * con,ipp_attribute_t * uri)2205*5e7646d2SAndroid Build Coastguard Worker add_printer(cupsd_client_t *con, /* I - Client connection */
2206*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *uri) /* I - URI of printer */
2207*5e7646d2SAndroid Build Coastguard Worker {
2208*5e7646d2SAndroid Build Coastguard Worker http_status_t status; /* Policy status */
2209*5e7646d2SAndroid Build Coastguard Worker int i; /* Looping var */
2210*5e7646d2SAndroid Build Coastguard Worker char scheme[HTTP_MAX_URI], /* Method portion of URI */
2211*5e7646d2SAndroid Build Coastguard Worker username[HTTP_MAX_URI], /* Username portion of URI */
2212*5e7646d2SAndroid Build Coastguard Worker host[HTTP_MAX_URI], /* Host portion of URI */
2213*5e7646d2SAndroid Build Coastguard Worker resource[HTTP_MAX_URI]; /* Resource portion of URI */
2214*5e7646d2SAndroid Build Coastguard Worker int port; /* Port portion of URI */
2215*5e7646d2SAndroid Build Coastguard Worker cupsd_printer_t *printer; /* Printer/class */
2216*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *attr; /* Printer attribute */
2217*5e7646d2SAndroid Build Coastguard Worker cups_file_t *fp; /* Script/PPD file */
2218*5e7646d2SAndroid Build Coastguard Worker char line[1024]; /* Line from file... */
2219*5e7646d2SAndroid Build Coastguard Worker char srcfile[1024], /* Source Script/PPD file */
2220*5e7646d2SAndroid Build Coastguard Worker dstfile[1024]; /* Destination Script/PPD file */
2221*5e7646d2SAndroid Build Coastguard Worker int modify; /* Non-zero if we are modifying */
2222*5e7646d2SAndroid Build Coastguard Worker int changed_driver, /* Changed the PPD? */
2223*5e7646d2SAndroid Build Coastguard Worker need_restart_job, /* Need to restart job? */
2224*5e7646d2SAndroid Build Coastguard Worker set_device_uri, /* Did we set the device URI? */
2225*5e7646d2SAndroid Build Coastguard Worker set_port_monitor; /* Did we set the port monitor? */
2226*5e7646d2SAndroid Build Coastguard Worker
2227*5e7646d2SAndroid Build Coastguard Worker
2228*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG2, "add_printer(%p[%d], %s)", con,
2229*5e7646d2SAndroid Build Coastguard Worker con->number, uri->values[0].string.text);
2230*5e7646d2SAndroid Build Coastguard Worker
2231*5e7646d2SAndroid Build Coastguard Worker /*
2232*5e7646d2SAndroid Build Coastguard Worker * Do we have a valid URI?
2233*5e7646d2SAndroid Build Coastguard Worker */
2234*5e7646d2SAndroid Build Coastguard Worker
2235*5e7646d2SAndroid Build Coastguard Worker httpSeparateURI(HTTP_URI_CODING_ALL, uri->values[0].string.text, scheme,
2236*5e7646d2SAndroid Build Coastguard Worker sizeof(scheme), username, sizeof(username), host,
2237*5e7646d2SAndroid Build Coastguard Worker sizeof(host), &port, resource, sizeof(resource));
2238*5e7646d2SAndroid Build Coastguard Worker
2239*5e7646d2SAndroid Build Coastguard Worker if (strncmp(resource, "/printers/", 10) || strlen(resource) == 10)
2240*5e7646d2SAndroid Build Coastguard Worker {
2241*5e7646d2SAndroid Build Coastguard Worker /*
2242*5e7646d2SAndroid Build Coastguard Worker * No, return an error...
2243*5e7646d2SAndroid Build Coastguard Worker */
2244*5e7646d2SAndroid Build Coastguard Worker
2245*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_BAD_REQUEST,
2246*5e7646d2SAndroid Build Coastguard Worker _("The printer-uri must be of the form "
2247*5e7646d2SAndroid Build Coastguard Worker "\"ipp://HOSTNAME/printers/PRINTERNAME\"."));
2248*5e7646d2SAndroid Build Coastguard Worker return;
2249*5e7646d2SAndroid Build Coastguard Worker }
2250*5e7646d2SAndroid Build Coastguard Worker
2251*5e7646d2SAndroid Build Coastguard Worker /*
2252*5e7646d2SAndroid Build Coastguard Worker * Do we have a valid printer name?
2253*5e7646d2SAndroid Build Coastguard Worker */
2254*5e7646d2SAndroid Build Coastguard Worker
2255*5e7646d2SAndroid Build Coastguard Worker if (!validate_name(resource + 10))
2256*5e7646d2SAndroid Build Coastguard Worker {
2257*5e7646d2SAndroid Build Coastguard Worker /*
2258*5e7646d2SAndroid Build Coastguard Worker * No, return an error...
2259*5e7646d2SAndroid Build Coastguard Worker */
2260*5e7646d2SAndroid Build Coastguard Worker
2261*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_BAD_REQUEST,
2262*5e7646d2SAndroid Build Coastguard Worker _("The printer-uri \"%s\" contains invalid characters."),
2263*5e7646d2SAndroid Build Coastguard Worker uri->values[0].string.text);
2264*5e7646d2SAndroid Build Coastguard Worker return;
2265*5e7646d2SAndroid Build Coastguard Worker }
2266*5e7646d2SAndroid Build Coastguard Worker
2267*5e7646d2SAndroid Build Coastguard Worker /*
2268*5e7646d2SAndroid Build Coastguard Worker * See if the printer already exists; if not, create a new printer...
2269*5e7646d2SAndroid Build Coastguard Worker */
2270*5e7646d2SAndroid Build Coastguard Worker
2271*5e7646d2SAndroid Build Coastguard Worker if ((printer = cupsdFindPrinter(resource + 10)) == NULL)
2272*5e7646d2SAndroid Build Coastguard Worker {
2273*5e7646d2SAndroid Build Coastguard Worker /*
2274*5e7646d2SAndroid Build Coastguard Worker * Printer doesn't exist; see if we have a class of the same name...
2275*5e7646d2SAndroid Build Coastguard Worker */
2276*5e7646d2SAndroid Build Coastguard Worker
2277*5e7646d2SAndroid Build Coastguard Worker if (cupsdFindClass(resource + 10))
2278*5e7646d2SAndroid Build Coastguard Worker {
2279*5e7646d2SAndroid Build Coastguard Worker /*
2280*5e7646d2SAndroid Build Coastguard Worker * Yes, return an error...
2281*5e7646d2SAndroid Build Coastguard Worker */
2282*5e7646d2SAndroid Build Coastguard Worker
2283*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_NOT_POSSIBLE,
2284*5e7646d2SAndroid Build Coastguard Worker _("A class named \"%s\" already exists."),
2285*5e7646d2SAndroid Build Coastguard Worker resource + 10);
2286*5e7646d2SAndroid Build Coastguard Worker return;
2287*5e7646d2SAndroid Build Coastguard Worker }
2288*5e7646d2SAndroid Build Coastguard Worker
2289*5e7646d2SAndroid Build Coastguard Worker /*
2290*5e7646d2SAndroid Build Coastguard Worker * No, check the default policy then add the printer...
2291*5e7646d2SAndroid Build Coastguard Worker */
2292*5e7646d2SAndroid Build Coastguard Worker
2293*5e7646d2SAndroid Build Coastguard Worker if ((status = cupsdCheckPolicy(DefaultPolicyPtr, con, NULL)) != HTTP_OK)
2294*5e7646d2SAndroid Build Coastguard Worker {
2295*5e7646d2SAndroid Build Coastguard Worker send_http_error(con, status, NULL);
2296*5e7646d2SAndroid Build Coastguard Worker return;
2297*5e7646d2SAndroid Build Coastguard Worker }
2298*5e7646d2SAndroid Build Coastguard Worker
2299*5e7646d2SAndroid Build Coastguard Worker printer = cupsdAddPrinter(resource + 10);
2300*5e7646d2SAndroid Build Coastguard Worker modify = 0;
2301*5e7646d2SAndroid Build Coastguard Worker
2302*5e7646d2SAndroid Build Coastguard Worker printer->printer_id = NextPrinterId ++;
2303*5e7646d2SAndroid Build Coastguard Worker }
2304*5e7646d2SAndroid Build Coastguard Worker else if ((status = cupsdCheckPolicy(printer->op_policy_ptr, con,
2305*5e7646d2SAndroid Build Coastguard Worker NULL)) != HTTP_OK)
2306*5e7646d2SAndroid Build Coastguard Worker {
2307*5e7646d2SAndroid Build Coastguard Worker send_http_error(con, status, printer);
2308*5e7646d2SAndroid Build Coastguard Worker return;
2309*5e7646d2SAndroid Build Coastguard Worker }
2310*5e7646d2SAndroid Build Coastguard Worker else
2311*5e7646d2SAndroid Build Coastguard Worker modify = 1;
2312*5e7646d2SAndroid Build Coastguard Worker
2313*5e7646d2SAndroid Build Coastguard Worker /*
2314*5e7646d2SAndroid Build Coastguard Worker * Look for attributes and copy them over as needed...
2315*5e7646d2SAndroid Build Coastguard Worker */
2316*5e7646d2SAndroid Build Coastguard Worker
2317*5e7646d2SAndroid Build Coastguard Worker changed_driver = 0;
2318*5e7646d2SAndroid Build Coastguard Worker need_restart_job = 0;
2319*5e7646d2SAndroid Build Coastguard Worker
2320*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippFindAttribute(con->request, "printer-is-temporary", IPP_TAG_BOOLEAN)) != NULL)
2321*5e7646d2SAndroid Build Coastguard Worker printer->temporary = ippGetBoolean(attr, 0);
2322*5e7646d2SAndroid Build Coastguard Worker
2323*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippFindAttribute(con->request, "printer-location",
2324*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_TEXT)) != NULL)
2325*5e7646d2SAndroid Build Coastguard Worker cupsdSetString(&printer->location, attr->values[0].string.text);
2326*5e7646d2SAndroid Build Coastguard Worker
2327*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippFindAttribute(con->request, "printer-geo-location", IPP_TAG_URI)) != NULL && !strncmp(attr->values[0].string.text, "geo:", 4))
2328*5e7646d2SAndroid Build Coastguard Worker cupsdSetString(&printer->geo_location, attr->values[0].string.text);
2329*5e7646d2SAndroid Build Coastguard Worker
2330*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippFindAttribute(con->request, "printer-organization", IPP_TAG_TEXT)) != NULL)
2331*5e7646d2SAndroid Build Coastguard Worker cupsdSetString(&printer->organization, attr->values[0].string.text);
2332*5e7646d2SAndroid Build Coastguard Worker
2333*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippFindAttribute(con->request, "printer-organizational-unit", IPP_TAG_TEXT)) != NULL)
2334*5e7646d2SAndroid Build Coastguard Worker cupsdSetString(&printer->organizational_unit, attr->values[0].string.text);
2335*5e7646d2SAndroid Build Coastguard Worker
2336*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippFindAttribute(con->request, "printer-info",
2337*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_TEXT)) != NULL)
2338*5e7646d2SAndroid Build Coastguard Worker cupsdSetString(&printer->info, attr->values[0].string.text);
2339*5e7646d2SAndroid Build Coastguard Worker
2340*5e7646d2SAndroid Build Coastguard Worker set_device_uri = 0;
2341*5e7646d2SAndroid Build Coastguard Worker
2342*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippFindAttribute(con->request, "device-uri",
2343*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_URI)) != NULL)
2344*5e7646d2SAndroid Build Coastguard Worker {
2345*5e7646d2SAndroid Build Coastguard Worker /*
2346*5e7646d2SAndroid Build Coastguard Worker * Do we have a valid device URI?
2347*5e7646d2SAndroid Build Coastguard Worker */
2348*5e7646d2SAndroid Build Coastguard Worker
2349*5e7646d2SAndroid Build Coastguard Worker http_uri_status_t uri_status; /* URI separation status */
2350*5e7646d2SAndroid Build Coastguard Worker char old_device_uri[1024];
2351*5e7646d2SAndroid Build Coastguard Worker /* Old device URI */
2352*5e7646d2SAndroid Build Coastguard Worker
2353*5e7646d2SAndroid Build Coastguard Worker need_restart_job = 1;
2354*5e7646d2SAndroid Build Coastguard Worker
2355*5e7646d2SAndroid Build Coastguard Worker uri_status = httpSeparateURI(HTTP_URI_CODING_ALL,
2356*5e7646d2SAndroid Build Coastguard Worker attr->values[0].string.text,
2357*5e7646d2SAndroid Build Coastguard Worker scheme, sizeof(scheme),
2358*5e7646d2SAndroid Build Coastguard Worker username, sizeof(username),
2359*5e7646d2SAndroid Build Coastguard Worker host, sizeof(host), &port,
2360*5e7646d2SAndroid Build Coastguard Worker resource, sizeof(resource));
2361*5e7646d2SAndroid Build Coastguard Worker
2362*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG, "%s device-uri: %s", printer->name, httpURIStatusString(uri_status));
2363*5e7646d2SAndroid Build Coastguard Worker
2364*5e7646d2SAndroid Build Coastguard Worker if (uri_status < HTTP_URI_OK)
2365*5e7646d2SAndroid Build Coastguard Worker {
2366*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_NOT_POSSIBLE, _("Bad device-uri \"%s\"."),
2367*5e7646d2SAndroid Build Coastguard Worker attr->values[0].string.text);
2368*5e7646d2SAndroid Build Coastguard Worker if (!modify)
2369*5e7646d2SAndroid Build Coastguard Worker cupsdDeletePrinter(printer, 0);
2370*5e7646d2SAndroid Build Coastguard Worker
2371*5e7646d2SAndroid Build Coastguard Worker return;
2372*5e7646d2SAndroid Build Coastguard Worker }
2373*5e7646d2SAndroid Build Coastguard Worker
2374*5e7646d2SAndroid Build Coastguard Worker if (!strcmp(scheme, "file"))
2375*5e7646d2SAndroid Build Coastguard Worker {
2376*5e7646d2SAndroid Build Coastguard Worker /*
2377*5e7646d2SAndroid Build Coastguard Worker * See if the administrator has enabled file devices...
2378*5e7646d2SAndroid Build Coastguard Worker */
2379*5e7646d2SAndroid Build Coastguard Worker
2380*5e7646d2SAndroid Build Coastguard Worker if (!FileDevice && strcmp(resource, "/dev/null"))
2381*5e7646d2SAndroid Build Coastguard Worker {
2382*5e7646d2SAndroid Build Coastguard Worker /*
2383*5e7646d2SAndroid Build Coastguard Worker * File devices are disabled and the URL is not file:/dev/null...
2384*5e7646d2SAndroid Build Coastguard Worker */
2385*5e7646d2SAndroid Build Coastguard Worker
2386*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_NOT_POSSIBLE,
2387*5e7646d2SAndroid Build Coastguard Worker _("File device URIs have been disabled. "
2388*5e7646d2SAndroid Build Coastguard Worker "To enable, see the FileDevice directive in "
2389*5e7646d2SAndroid Build Coastguard Worker "\"%s/cups-files.conf\"."),
2390*5e7646d2SAndroid Build Coastguard Worker ServerRoot);
2391*5e7646d2SAndroid Build Coastguard Worker if (!modify)
2392*5e7646d2SAndroid Build Coastguard Worker cupsdDeletePrinter(printer, 0);
2393*5e7646d2SAndroid Build Coastguard Worker
2394*5e7646d2SAndroid Build Coastguard Worker return;
2395*5e7646d2SAndroid Build Coastguard Worker }
2396*5e7646d2SAndroid Build Coastguard Worker }
2397*5e7646d2SAndroid Build Coastguard Worker else
2398*5e7646d2SAndroid Build Coastguard Worker {
2399*5e7646d2SAndroid Build Coastguard Worker /*
2400*5e7646d2SAndroid Build Coastguard Worker * See if the backend exists and is executable...
2401*5e7646d2SAndroid Build Coastguard Worker */
2402*5e7646d2SAndroid Build Coastguard Worker
2403*5e7646d2SAndroid Build Coastguard Worker snprintf(srcfile, sizeof(srcfile), "%s/backend/%s", ServerBin, scheme);
2404*5e7646d2SAndroid Build Coastguard Worker if (access(srcfile, X_OK))
2405*5e7646d2SAndroid Build Coastguard Worker {
2406*5e7646d2SAndroid Build Coastguard Worker /*
2407*5e7646d2SAndroid Build Coastguard Worker * Could not find device in list!
2408*5e7646d2SAndroid Build Coastguard Worker */
2409*5e7646d2SAndroid Build Coastguard Worker
2410*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_NOT_POSSIBLE,
2411*5e7646d2SAndroid Build Coastguard Worker _("Bad device-uri scheme \"%s\"."), scheme);
2412*5e7646d2SAndroid Build Coastguard Worker if (!modify)
2413*5e7646d2SAndroid Build Coastguard Worker cupsdDeletePrinter(printer, 0);
2414*5e7646d2SAndroid Build Coastguard Worker
2415*5e7646d2SAndroid Build Coastguard Worker return;
2416*5e7646d2SAndroid Build Coastguard Worker }
2417*5e7646d2SAndroid Build Coastguard Worker }
2418*5e7646d2SAndroid Build Coastguard Worker
2419*5e7646d2SAndroid Build Coastguard Worker if (printer->sanitized_device_uri)
2420*5e7646d2SAndroid Build Coastguard Worker strlcpy(old_device_uri, printer->sanitized_device_uri,
2421*5e7646d2SAndroid Build Coastguard Worker sizeof(old_device_uri));
2422*5e7646d2SAndroid Build Coastguard Worker else
2423*5e7646d2SAndroid Build Coastguard Worker old_device_uri[0] = '\0';
2424*5e7646d2SAndroid Build Coastguard Worker
2425*5e7646d2SAndroid Build Coastguard Worker cupsdSetDeviceURI(printer, attr->values[0].string.text);
2426*5e7646d2SAndroid Build Coastguard Worker
2427*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_INFO,
2428*5e7646d2SAndroid Build Coastguard Worker "Setting %s device-uri to \"%s\" (was \"%s\".)",
2429*5e7646d2SAndroid Build Coastguard Worker printer->name, printer->sanitized_device_uri,
2430*5e7646d2SAndroid Build Coastguard Worker old_device_uri);
2431*5e7646d2SAndroid Build Coastguard Worker
2432*5e7646d2SAndroid Build Coastguard Worker set_device_uri = 1;
2433*5e7646d2SAndroid Build Coastguard Worker }
2434*5e7646d2SAndroid Build Coastguard Worker
2435*5e7646d2SAndroid Build Coastguard Worker set_port_monitor = 0;
2436*5e7646d2SAndroid Build Coastguard Worker
2437*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippFindAttribute(con->request, "port-monitor",
2438*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_NAME)) != NULL)
2439*5e7646d2SAndroid Build Coastguard Worker {
2440*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *supported; /* port-monitor-supported attribute */
2441*5e7646d2SAndroid Build Coastguard Worker
2442*5e7646d2SAndroid Build Coastguard Worker
2443*5e7646d2SAndroid Build Coastguard Worker need_restart_job = 1;
2444*5e7646d2SAndroid Build Coastguard Worker
2445*5e7646d2SAndroid Build Coastguard Worker supported = ippFindAttribute(printer->ppd_attrs, "port-monitor-supported",
2446*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_NAME);
2447*5e7646d2SAndroid Build Coastguard Worker if (supported)
2448*5e7646d2SAndroid Build Coastguard Worker {
2449*5e7646d2SAndroid Build Coastguard Worker for (i = 0; i < supported->num_values; i ++)
2450*5e7646d2SAndroid Build Coastguard Worker if (!strcmp(supported->values[i].string.text,
2451*5e7646d2SAndroid Build Coastguard Worker attr->values[0].string.text))
2452*5e7646d2SAndroid Build Coastguard Worker break;
2453*5e7646d2SAndroid Build Coastguard Worker }
2454*5e7646d2SAndroid Build Coastguard Worker
2455*5e7646d2SAndroid Build Coastguard Worker if (!supported || i >= supported->num_values)
2456*5e7646d2SAndroid Build Coastguard Worker {
2457*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_NOT_POSSIBLE, _("Bad port-monitor \"%s\"."),
2458*5e7646d2SAndroid Build Coastguard Worker attr->values[0].string.text);
2459*5e7646d2SAndroid Build Coastguard Worker if (!modify)
2460*5e7646d2SAndroid Build Coastguard Worker cupsdDeletePrinter(printer, 0);
2461*5e7646d2SAndroid Build Coastguard Worker
2462*5e7646d2SAndroid Build Coastguard Worker return;
2463*5e7646d2SAndroid Build Coastguard Worker }
2464*5e7646d2SAndroid Build Coastguard Worker
2465*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_INFO,
2466*5e7646d2SAndroid Build Coastguard Worker "Setting %s port-monitor to \"%s\" (was \"%s\".)",
2467*5e7646d2SAndroid Build Coastguard Worker printer->name, attr->values[0].string.text,
2468*5e7646d2SAndroid Build Coastguard Worker printer->port_monitor ? printer->port_monitor : "none");
2469*5e7646d2SAndroid Build Coastguard Worker
2470*5e7646d2SAndroid Build Coastguard Worker if (strcmp(attr->values[0].string.text, "none"))
2471*5e7646d2SAndroid Build Coastguard Worker cupsdSetString(&printer->port_monitor, attr->values[0].string.text);
2472*5e7646d2SAndroid Build Coastguard Worker else
2473*5e7646d2SAndroid Build Coastguard Worker cupsdClearString(&printer->port_monitor);
2474*5e7646d2SAndroid Build Coastguard Worker
2475*5e7646d2SAndroid Build Coastguard Worker set_port_monitor = 1;
2476*5e7646d2SAndroid Build Coastguard Worker }
2477*5e7646d2SAndroid Build Coastguard Worker
2478*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippFindAttribute(con->request, "printer-is-accepting-jobs",
2479*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_BOOLEAN)) != NULL &&
2480*5e7646d2SAndroid Build Coastguard Worker attr->values[0].boolean != printer->accepting)
2481*5e7646d2SAndroid Build Coastguard Worker {
2482*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_INFO,
2483*5e7646d2SAndroid Build Coastguard Worker "Setting %s printer-is-accepting-jobs to %d (was %d.)",
2484*5e7646d2SAndroid Build Coastguard Worker printer->name, attr->values[0].boolean, printer->accepting);
2485*5e7646d2SAndroid Build Coastguard Worker
2486*5e7646d2SAndroid Build Coastguard Worker printer->accepting = attr->values[0].boolean;
2487*5e7646d2SAndroid Build Coastguard Worker
2488*5e7646d2SAndroid Build Coastguard Worker cupsdAddEvent(CUPSD_EVENT_PRINTER_STATE, printer, NULL,
2489*5e7646d2SAndroid Build Coastguard Worker "%s accepting jobs.",
2490*5e7646d2SAndroid Build Coastguard Worker printer->accepting ? "Now" : "No longer");
2491*5e7646d2SAndroid Build Coastguard Worker }
2492*5e7646d2SAndroid Build Coastguard Worker
2493*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippFindAttribute(con->request, "printer-is-shared", IPP_TAG_BOOLEAN)) != NULL)
2494*5e7646d2SAndroid Build Coastguard Worker {
2495*5e7646d2SAndroid Build Coastguard Worker if (ippGetBoolean(attr, 0) &&
2496*5e7646d2SAndroid Build Coastguard Worker printer->num_auth_info_required == 1 &&
2497*5e7646d2SAndroid Build Coastguard Worker !strcmp(printer->auth_info_required[0], "negotiate"))
2498*5e7646d2SAndroid Build Coastguard Worker {
2499*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_BAD_REQUEST,
2500*5e7646d2SAndroid Build Coastguard Worker _("Cannot share a remote Kerberized printer."));
2501*5e7646d2SAndroid Build Coastguard Worker if (!modify)
2502*5e7646d2SAndroid Build Coastguard Worker cupsdDeletePrinter(printer, 0);
2503*5e7646d2SAndroid Build Coastguard Worker
2504*5e7646d2SAndroid Build Coastguard Worker return;
2505*5e7646d2SAndroid Build Coastguard Worker }
2506*5e7646d2SAndroid Build Coastguard Worker
2507*5e7646d2SAndroid Build Coastguard Worker if (printer->type & CUPS_PRINTER_REMOTE)
2508*5e7646d2SAndroid Build Coastguard Worker {
2509*5e7646d2SAndroid Build Coastguard Worker /*
2510*5e7646d2SAndroid Build Coastguard Worker * Cannot re-share remote printers.
2511*5e7646d2SAndroid Build Coastguard Worker */
2512*5e7646d2SAndroid Build Coastguard Worker
2513*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_BAD_REQUEST, _("Cannot change printer-is-shared for remote queues."));
2514*5e7646d2SAndroid Build Coastguard Worker if (!modify)
2515*5e7646d2SAndroid Build Coastguard Worker cupsdDeletePrinter(printer, 0);
2516*5e7646d2SAndroid Build Coastguard Worker
2517*5e7646d2SAndroid Build Coastguard Worker return;
2518*5e7646d2SAndroid Build Coastguard Worker }
2519*5e7646d2SAndroid Build Coastguard Worker
2520*5e7646d2SAndroid Build Coastguard Worker if (printer->shared && !ippGetBoolean(attr, 0))
2521*5e7646d2SAndroid Build Coastguard Worker cupsdDeregisterPrinter(printer, 1);
2522*5e7646d2SAndroid Build Coastguard Worker
2523*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_INFO,
2524*5e7646d2SAndroid Build Coastguard Worker "Setting %s printer-is-shared to %d (was %d.)",
2525*5e7646d2SAndroid Build Coastguard Worker printer->name, attr->values[0].boolean, printer->shared);
2526*5e7646d2SAndroid Build Coastguard Worker
2527*5e7646d2SAndroid Build Coastguard Worker printer->shared = ippGetBoolean(attr, 0);
2528*5e7646d2SAndroid Build Coastguard Worker if (printer->shared && printer->temporary)
2529*5e7646d2SAndroid Build Coastguard Worker printer->temporary = 0;
2530*5e7646d2SAndroid Build Coastguard Worker }
2531*5e7646d2SAndroid Build Coastguard Worker
2532*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippFindAttribute(con->request, "printer-state",
2533*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_ENUM)) != NULL)
2534*5e7646d2SAndroid Build Coastguard Worker {
2535*5e7646d2SAndroid Build Coastguard Worker if (attr->values[0].integer != IPP_PRINTER_IDLE &&
2536*5e7646d2SAndroid Build Coastguard Worker attr->values[0].integer != IPP_PRINTER_STOPPED)
2537*5e7646d2SAndroid Build Coastguard Worker {
2538*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_BAD_REQUEST, _("Bad printer-state value %d."),
2539*5e7646d2SAndroid Build Coastguard Worker attr->values[0].integer);
2540*5e7646d2SAndroid Build Coastguard Worker if (!modify)
2541*5e7646d2SAndroid Build Coastguard Worker cupsdDeletePrinter(printer, 0);
2542*5e7646d2SAndroid Build Coastguard Worker
2543*5e7646d2SAndroid Build Coastguard Worker return;
2544*5e7646d2SAndroid Build Coastguard Worker }
2545*5e7646d2SAndroid Build Coastguard Worker
2546*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_INFO, "Setting %s printer-state to %d (was %d.)",
2547*5e7646d2SAndroid Build Coastguard Worker printer->name, attr->values[0].integer, printer->state);
2548*5e7646d2SAndroid Build Coastguard Worker
2549*5e7646d2SAndroid Build Coastguard Worker if (attr->values[0].integer == IPP_PRINTER_STOPPED)
2550*5e7646d2SAndroid Build Coastguard Worker cupsdStopPrinter(printer, 0);
2551*5e7646d2SAndroid Build Coastguard Worker else
2552*5e7646d2SAndroid Build Coastguard Worker {
2553*5e7646d2SAndroid Build Coastguard Worker need_restart_job = 1;
2554*5e7646d2SAndroid Build Coastguard Worker cupsdSetPrinterState(printer, (ipp_pstate_t)(attr->values[0].integer), 0);
2555*5e7646d2SAndroid Build Coastguard Worker }
2556*5e7646d2SAndroid Build Coastguard Worker }
2557*5e7646d2SAndroid Build Coastguard Worker
2558*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippFindAttribute(con->request, "printer-state-message",
2559*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_TEXT)) != NULL)
2560*5e7646d2SAndroid Build Coastguard Worker {
2561*5e7646d2SAndroid Build Coastguard Worker strlcpy(printer->state_message, attr->values[0].string.text,
2562*5e7646d2SAndroid Build Coastguard Worker sizeof(printer->state_message));
2563*5e7646d2SAndroid Build Coastguard Worker
2564*5e7646d2SAndroid Build Coastguard Worker cupsdAddEvent(CUPSD_EVENT_PRINTER_STATE, printer, NULL, "%s",
2565*5e7646d2SAndroid Build Coastguard Worker printer->state_message);
2566*5e7646d2SAndroid Build Coastguard Worker }
2567*5e7646d2SAndroid Build Coastguard Worker
2568*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippFindAttribute(con->request, "printer-state-reasons",
2569*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_KEYWORD)) != NULL)
2570*5e7646d2SAndroid Build Coastguard Worker {
2571*5e7646d2SAndroid Build Coastguard Worker if (attr->num_values >
2572*5e7646d2SAndroid Build Coastguard Worker (int)(sizeof(printer->reasons) / sizeof(printer->reasons[0])))
2573*5e7646d2SAndroid Build Coastguard Worker {
2574*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_NOT_POSSIBLE,
2575*5e7646d2SAndroid Build Coastguard Worker _("Too many printer-state-reasons values (%d > %d)."),
2576*5e7646d2SAndroid Build Coastguard Worker attr->num_values,
2577*5e7646d2SAndroid Build Coastguard Worker (int)(sizeof(printer->reasons) /
2578*5e7646d2SAndroid Build Coastguard Worker sizeof(printer->reasons[0])));
2579*5e7646d2SAndroid Build Coastguard Worker if (!modify)
2580*5e7646d2SAndroid Build Coastguard Worker cupsdDeletePrinter(printer, 0);
2581*5e7646d2SAndroid Build Coastguard Worker
2582*5e7646d2SAndroid Build Coastguard Worker return;
2583*5e7646d2SAndroid Build Coastguard Worker }
2584*5e7646d2SAndroid Build Coastguard Worker
2585*5e7646d2SAndroid Build Coastguard Worker for (i = 0; i < printer->num_reasons; i ++)
2586*5e7646d2SAndroid Build Coastguard Worker _cupsStrFree(printer->reasons[i]);
2587*5e7646d2SAndroid Build Coastguard Worker
2588*5e7646d2SAndroid Build Coastguard Worker printer->num_reasons = 0;
2589*5e7646d2SAndroid Build Coastguard Worker for (i = 0; i < attr->num_values; i ++)
2590*5e7646d2SAndroid Build Coastguard Worker {
2591*5e7646d2SAndroid Build Coastguard Worker if (!strcmp(attr->values[i].string.text, "none"))
2592*5e7646d2SAndroid Build Coastguard Worker continue;
2593*5e7646d2SAndroid Build Coastguard Worker
2594*5e7646d2SAndroid Build Coastguard Worker printer->reasons[printer->num_reasons] = _cupsStrAlloc(attr->values[i].string.text);
2595*5e7646d2SAndroid Build Coastguard Worker printer->num_reasons ++;
2596*5e7646d2SAndroid Build Coastguard Worker
2597*5e7646d2SAndroid Build Coastguard Worker if (!strcmp(attr->values[i].string.text, "paused") &&
2598*5e7646d2SAndroid Build Coastguard Worker printer->state != IPP_PRINTER_STOPPED)
2599*5e7646d2SAndroid Build Coastguard Worker {
2600*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_INFO,
2601*5e7646d2SAndroid Build Coastguard Worker "Setting %s printer-state to %d (was %d.)",
2602*5e7646d2SAndroid Build Coastguard Worker printer->name, IPP_PRINTER_STOPPED, printer->state);
2603*5e7646d2SAndroid Build Coastguard Worker cupsdStopPrinter(printer, 0);
2604*5e7646d2SAndroid Build Coastguard Worker }
2605*5e7646d2SAndroid Build Coastguard Worker }
2606*5e7646d2SAndroid Build Coastguard Worker
2607*5e7646d2SAndroid Build Coastguard Worker if (PrintcapFormat == PRINTCAP_PLIST)
2608*5e7646d2SAndroid Build Coastguard Worker cupsdMarkDirty(CUPSD_DIRTY_PRINTCAP);
2609*5e7646d2SAndroid Build Coastguard Worker
2610*5e7646d2SAndroid Build Coastguard Worker cupsdAddEvent(CUPSD_EVENT_PRINTER_STATE, printer, NULL,
2611*5e7646d2SAndroid Build Coastguard Worker "Printer \"%s\" state changed.", printer->name);
2612*5e7646d2SAndroid Build Coastguard Worker }
2613*5e7646d2SAndroid Build Coastguard Worker
2614*5e7646d2SAndroid Build Coastguard Worker if (!set_printer_defaults(con, printer))
2615*5e7646d2SAndroid Build Coastguard Worker {
2616*5e7646d2SAndroid Build Coastguard Worker if (!modify)
2617*5e7646d2SAndroid Build Coastguard Worker cupsdDeletePrinter(printer, 0);
2618*5e7646d2SAndroid Build Coastguard Worker
2619*5e7646d2SAndroid Build Coastguard Worker return;
2620*5e7646d2SAndroid Build Coastguard Worker }
2621*5e7646d2SAndroid Build Coastguard Worker
2622*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippFindAttribute(con->request, "auth-info-required",
2623*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_KEYWORD)) != NULL)
2624*5e7646d2SAndroid Build Coastguard Worker cupsdSetAuthInfoRequired(printer, NULL, attr);
2625*5e7646d2SAndroid Build Coastguard Worker
2626*5e7646d2SAndroid Build Coastguard Worker /*
2627*5e7646d2SAndroid Build Coastguard Worker * See if we have all required attributes...
2628*5e7646d2SAndroid Build Coastguard Worker */
2629*5e7646d2SAndroid Build Coastguard Worker
2630*5e7646d2SAndroid Build Coastguard Worker if (!printer->device_uri)
2631*5e7646d2SAndroid Build Coastguard Worker cupsdSetString(&printer->device_uri, "file:///dev/null");
2632*5e7646d2SAndroid Build Coastguard Worker
2633*5e7646d2SAndroid Build Coastguard Worker /*
2634*5e7646d2SAndroid Build Coastguard Worker * See if we have a PPD file attached to the request...
2635*5e7646d2SAndroid Build Coastguard Worker */
2636*5e7646d2SAndroid Build Coastguard Worker
2637*5e7646d2SAndroid Build Coastguard Worker if (con->filename)
2638*5e7646d2SAndroid Build Coastguard Worker {
2639*5e7646d2SAndroid Build Coastguard Worker need_restart_job = 1;
2640*5e7646d2SAndroid Build Coastguard Worker changed_driver = 1;
2641*5e7646d2SAndroid Build Coastguard Worker
2642*5e7646d2SAndroid Build Coastguard Worker strlcpy(srcfile, con->filename, sizeof(srcfile));
2643*5e7646d2SAndroid Build Coastguard Worker
2644*5e7646d2SAndroid Build Coastguard Worker if ((fp = cupsFileOpen(srcfile, "rb")))
2645*5e7646d2SAndroid Build Coastguard Worker {
2646*5e7646d2SAndroid Build Coastguard Worker /*
2647*5e7646d2SAndroid Build Coastguard Worker * Yes; get the first line from it...
2648*5e7646d2SAndroid Build Coastguard Worker */
2649*5e7646d2SAndroid Build Coastguard Worker
2650*5e7646d2SAndroid Build Coastguard Worker line[0] = '\0';
2651*5e7646d2SAndroid Build Coastguard Worker cupsFileGets(fp, line, sizeof(line));
2652*5e7646d2SAndroid Build Coastguard Worker cupsFileClose(fp);
2653*5e7646d2SAndroid Build Coastguard Worker
2654*5e7646d2SAndroid Build Coastguard Worker /*
2655*5e7646d2SAndroid Build Coastguard Worker * Then see what kind of file it is...
2656*5e7646d2SAndroid Build Coastguard Worker */
2657*5e7646d2SAndroid Build Coastguard Worker
2658*5e7646d2SAndroid Build Coastguard Worker if (strncmp(line, "*PPD-Adobe", 10))
2659*5e7646d2SAndroid Build Coastguard Worker {
2660*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_STATUS_ERROR_DOCUMENT_FORMAT_NOT_SUPPORTED, _("Bad PPD file."));
2661*5e7646d2SAndroid Build Coastguard Worker if (!modify)
2662*5e7646d2SAndroid Build Coastguard Worker cupsdDeletePrinter(printer, 0);
2663*5e7646d2SAndroid Build Coastguard Worker
2664*5e7646d2SAndroid Build Coastguard Worker return;
2665*5e7646d2SAndroid Build Coastguard Worker }
2666*5e7646d2SAndroid Build Coastguard Worker
2667*5e7646d2SAndroid Build Coastguard Worker snprintf(dstfile, sizeof(dstfile), "%s/ppd/%s.ppd", ServerRoot,
2668*5e7646d2SAndroid Build Coastguard Worker printer->name);
2669*5e7646d2SAndroid Build Coastguard Worker
2670*5e7646d2SAndroid Build Coastguard Worker /*
2671*5e7646d2SAndroid Build Coastguard Worker * The new file is a PPD file, so move the file over to the ppd
2672*5e7646d2SAndroid Build Coastguard Worker * directory...
2673*5e7646d2SAndroid Build Coastguard Worker */
2674*5e7646d2SAndroid Build Coastguard Worker
2675*5e7646d2SAndroid Build Coastguard Worker if (copy_file(srcfile, dstfile, ConfigFilePerm))
2676*5e7646d2SAndroid Build Coastguard Worker {
2677*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_INTERNAL_ERROR, _("Unable to copy PPD file - %s"), strerror(errno));
2678*5e7646d2SAndroid Build Coastguard Worker if (!modify)
2679*5e7646d2SAndroid Build Coastguard Worker cupsdDeletePrinter(printer, 0);
2680*5e7646d2SAndroid Build Coastguard Worker
2681*5e7646d2SAndroid Build Coastguard Worker return;
2682*5e7646d2SAndroid Build Coastguard Worker }
2683*5e7646d2SAndroid Build Coastguard Worker
2684*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG, "Copied PPD file successfully");
2685*5e7646d2SAndroid Build Coastguard Worker }
2686*5e7646d2SAndroid Build Coastguard Worker }
2687*5e7646d2SAndroid Build Coastguard Worker else if ((attr = ippFindAttribute(con->request, "ppd-name", IPP_TAG_NAME)) != NULL)
2688*5e7646d2SAndroid Build Coastguard Worker {
2689*5e7646d2SAndroid Build Coastguard Worker const char *ppd_name = ippGetString(attr, 0, NULL);
2690*5e7646d2SAndroid Build Coastguard Worker /* ppd-name value */
2691*5e7646d2SAndroid Build Coastguard Worker
2692*5e7646d2SAndroid Build Coastguard Worker need_restart_job = 1;
2693*5e7646d2SAndroid Build Coastguard Worker changed_driver = 1;
2694*5e7646d2SAndroid Build Coastguard Worker
2695*5e7646d2SAndroid Build Coastguard Worker if (!strcmp(ppd_name, "everywhere"))
2696*5e7646d2SAndroid Build Coastguard Worker {
2697*5e7646d2SAndroid Build Coastguard Worker // Create IPP Everywhere PPD...
2698*5e7646d2SAndroid Build Coastguard Worker if (!printer->device_uri || (strncmp(printer->device_uri, "dnssd://", 8) && strncmp(printer->device_uri, "ipp://", 6) && strncmp(printer->device_uri, "ipps://", 7) && strncmp(printer->device_uri, "ippusb://", 9)))
2699*5e7646d2SAndroid Build Coastguard Worker {
2700*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_INTERNAL_ERROR, _("IPP Everywhere driver requires an IPP connection."));
2701*5e7646d2SAndroid Build Coastguard Worker if (!modify)
2702*5e7646d2SAndroid Build Coastguard Worker cupsdDeletePrinter(printer, 0);
2703*5e7646d2SAndroid Build Coastguard Worker
2704*5e7646d2SAndroid Build Coastguard Worker return;
2705*5e7646d2SAndroid Build Coastguard Worker }
2706*5e7646d2SAndroid Build Coastguard Worker
2707*5e7646d2SAndroid Build Coastguard Worker // Run a background thread to create the PPD...
2708*5e7646d2SAndroid Build Coastguard Worker _cupsThreadCreate((_cups_thread_func_t)create_local_bg_thread, printer);
2709*5e7646d2SAndroid Build Coastguard Worker }
2710*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(ppd_name, "raw"))
2711*5e7646d2SAndroid Build Coastguard Worker {
2712*5e7646d2SAndroid Build Coastguard Worker /*
2713*5e7646d2SAndroid Build Coastguard Worker * Raw driver, remove any existing PPD file.
2714*5e7646d2SAndroid Build Coastguard Worker */
2715*5e7646d2SAndroid Build Coastguard Worker
2716*5e7646d2SAndroid Build Coastguard Worker snprintf(dstfile, sizeof(dstfile), "%s/ppd/%s.ppd", ServerRoot, printer->name);
2717*5e7646d2SAndroid Build Coastguard Worker unlink(dstfile);
2718*5e7646d2SAndroid Build Coastguard Worker }
2719*5e7646d2SAndroid Build Coastguard Worker else if (strstr(ppd_name, "../"))
2720*5e7646d2SAndroid Build Coastguard Worker {
2721*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_STATUS_ERROR_ATTRIBUTES_OR_VALUES, _("Invalid ppd-name value."));
2722*5e7646d2SAndroid Build Coastguard Worker if (!modify)
2723*5e7646d2SAndroid Build Coastguard Worker cupsdDeletePrinter(printer, 0);
2724*5e7646d2SAndroid Build Coastguard Worker
2725*5e7646d2SAndroid Build Coastguard Worker return;
2726*5e7646d2SAndroid Build Coastguard Worker }
2727*5e7646d2SAndroid Build Coastguard Worker else
2728*5e7646d2SAndroid Build Coastguard Worker {
2729*5e7646d2SAndroid Build Coastguard Worker /*
2730*5e7646d2SAndroid Build Coastguard Worker * PPD model file...
2731*5e7646d2SAndroid Build Coastguard Worker */
2732*5e7646d2SAndroid Build Coastguard Worker
2733*5e7646d2SAndroid Build Coastguard Worker snprintf(dstfile, sizeof(dstfile), "%s/ppd/%s.ppd", ServerRoot, printer->name);
2734*5e7646d2SAndroid Build Coastguard Worker
2735*5e7646d2SAndroid Build Coastguard Worker if (copy_model(con, ppd_name, dstfile))
2736*5e7646d2SAndroid Build Coastguard Worker {
2737*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_INTERNAL_ERROR, _("Unable to copy PPD file."));
2738*5e7646d2SAndroid Build Coastguard Worker if (!modify)
2739*5e7646d2SAndroid Build Coastguard Worker cupsdDeletePrinter(printer, 0);
2740*5e7646d2SAndroid Build Coastguard Worker
2741*5e7646d2SAndroid Build Coastguard Worker return;
2742*5e7646d2SAndroid Build Coastguard Worker }
2743*5e7646d2SAndroid Build Coastguard Worker
2744*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG, "Copied PPD file successfully");
2745*5e7646d2SAndroid Build Coastguard Worker }
2746*5e7646d2SAndroid Build Coastguard Worker }
2747*5e7646d2SAndroid Build Coastguard Worker
2748*5e7646d2SAndroid Build Coastguard Worker if (changed_driver)
2749*5e7646d2SAndroid Build Coastguard Worker {
2750*5e7646d2SAndroid Build Coastguard Worker /*
2751*5e7646d2SAndroid Build Coastguard Worker * If we changed the PPD, then remove the printer's cache file and clear the
2752*5e7646d2SAndroid Build Coastguard Worker * printer-state-reasons...
2753*5e7646d2SAndroid Build Coastguard Worker */
2754*5e7646d2SAndroid Build Coastguard Worker
2755*5e7646d2SAndroid Build Coastguard Worker char cache_name[1024]; /* Cache filename for printer attrs */
2756*5e7646d2SAndroid Build Coastguard Worker
2757*5e7646d2SAndroid Build Coastguard Worker snprintf(cache_name, sizeof(cache_name), "%s/%s.data", CacheDir, printer->name);
2758*5e7646d2SAndroid Build Coastguard Worker unlink(cache_name);
2759*5e7646d2SAndroid Build Coastguard Worker
2760*5e7646d2SAndroid Build Coastguard Worker cupsdSetPrinterReasons(printer, "none");
2761*5e7646d2SAndroid Build Coastguard Worker
2762*5e7646d2SAndroid Build Coastguard Worker /*
2763*5e7646d2SAndroid Build Coastguard Worker * (Re)register color profiles...
2764*5e7646d2SAndroid Build Coastguard Worker */
2765*5e7646d2SAndroid Build Coastguard Worker
2766*5e7646d2SAndroid Build Coastguard Worker cupsdRegisterColor(printer);
2767*5e7646d2SAndroid Build Coastguard Worker }
2768*5e7646d2SAndroid Build Coastguard Worker
2769*5e7646d2SAndroid Build Coastguard Worker /*
2770*5e7646d2SAndroid Build Coastguard Worker * If we set the device URI but not the port monitor, check which port
2771*5e7646d2SAndroid Build Coastguard Worker * monitor to use by default...
2772*5e7646d2SAndroid Build Coastguard Worker */
2773*5e7646d2SAndroid Build Coastguard Worker
2774*5e7646d2SAndroid Build Coastguard Worker if (set_device_uri && !set_port_monitor)
2775*5e7646d2SAndroid Build Coastguard Worker {
2776*5e7646d2SAndroid Build Coastguard Worker ppd_file_t *ppd; /* PPD file */
2777*5e7646d2SAndroid Build Coastguard Worker ppd_attr_t *ppdattr; /* cupsPortMonitor attribute */
2778*5e7646d2SAndroid Build Coastguard Worker
2779*5e7646d2SAndroid Build Coastguard Worker
2780*5e7646d2SAndroid Build Coastguard Worker httpSeparateURI(HTTP_URI_CODING_ALL, printer->device_uri, scheme,
2781*5e7646d2SAndroid Build Coastguard Worker sizeof(scheme), username, sizeof(username), host,
2782*5e7646d2SAndroid Build Coastguard Worker sizeof(host), &port, resource, sizeof(resource));
2783*5e7646d2SAndroid Build Coastguard Worker
2784*5e7646d2SAndroid Build Coastguard Worker snprintf(srcfile, sizeof(srcfile), "%s/ppd/%s.ppd", ServerRoot,
2785*5e7646d2SAndroid Build Coastguard Worker printer->name);
2786*5e7646d2SAndroid Build Coastguard Worker if ((ppd = _ppdOpenFile(srcfile, _PPD_LOCALIZATION_NONE)) != NULL)
2787*5e7646d2SAndroid Build Coastguard Worker {
2788*5e7646d2SAndroid Build Coastguard Worker for (ppdattr = ppdFindAttr(ppd, "cupsPortMonitor", NULL);
2789*5e7646d2SAndroid Build Coastguard Worker ppdattr;
2790*5e7646d2SAndroid Build Coastguard Worker ppdattr = ppdFindNextAttr(ppd, "cupsPortMonitor", NULL))
2791*5e7646d2SAndroid Build Coastguard Worker if (!strcmp(scheme, ppdattr->spec))
2792*5e7646d2SAndroid Build Coastguard Worker {
2793*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_INFO,
2794*5e7646d2SAndroid Build Coastguard Worker "Setting %s port-monitor to \"%s\" (was \"%s\".)",
2795*5e7646d2SAndroid Build Coastguard Worker printer->name, ppdattr->value,
2796*5e7646d2SAndroid Build Coastguard Worker printer->port_monitor ? printer->port_monitor
2797*5e7646d2SAndroid Build Coastguard Worker : "none");
2798*5e7646d2SAndroid Build Coastguard Worker
2799*5e7646d2SAndroid Build Coastguard Worker if (strcmp(ppdattr->value, "none"))
2800*5e7646d2SAndroid Build Coastguard Worker cupsdSetString(&printer->port_monitor, ppdattr->value);
2801*5e7646d2SAndroid Build Coastguard Worker else
2802*5e7646d2SAndroid Build Coastguard Worker cupsdClearString(&printer->port_monitor);
2803*5e7646d2SAndroid Build Coastguard Worker
2804*5e7646d2SAndroid Build Coastguard Worker break;
2805*5e7646d2SAndroid Build Coastguard Worker }
2806*5e7646d2SAndroid Build Coastguard Worker
2807*5e7646d2SAndroid Build Coastguard Worker ppdClose(ppd);
2808*5e7646d2SAndroid Build Coastguard Worker }
2809*5e7646d2SAndroid Build Coastguard Worker }
2810*5e7646d2SAndroid Build Coastguard Worker
2811*5e7646d2SAndroid Build Coastguard Worker printer->config_time = time(NULL);
2812*5e7646d2SAndroid Build Coastguard Worker
2813*5e7646d2SAndroid Build Coastguard Worker /*
2814*5e7646d2SAndroid Build Coastguard Worker * Update the printer attributes and return...
2815*5e7646d2SAndroid Build Coastguard Worker */
2816*5e7646d2SAndroid Build Coastguard Worker
2817*5e7646d2SAndroid Build Coastguard Worker if (!printer->temporary)
2818*5e7646d2SAndroid Build Coastguard Worker {
2819*5e7646d2SAndroid Build Coastguard Worker if (!printer->printer_id)
2820*5e7646d2SAndroid Build Coastguard Worker printer->printer_id = NextPrinterId ++;
2821*5e7646d2SAndroid Build Coastguard Worker
2822*5e7646d2SAndroid Build Coastguard Worker cupsdMarkDirty(CUPSD_DIRTY_PRINTERS);
2823*5e7646d2SAndroid Build Coastguard Worker }
2824*5e7646d2SAndroid Build Coastguard Worker
2825*5e7646d2SAndroid Build Coastguard Worker cupsdSetPrinterAttrs(printer);
2826*5e7646d2SAndroid Build Coastguard Worker
2827*5e7646d2SAndroid Build Coastguard Worker if (need_restart_job && printer->job)
2828*5e7646d2SAndroid Build Coastguard Worker {
2829*5e7646d2SAndroid Build Coastguard Worker /*
2830*5e7646d2SAndroid Build Coastguard Worker * Restart the current job...
2831*5e7646d2SAndroid Build Coastguard Worker */
2832*5e7646d2SAndroid Build Coastguard Worker
2833*5e7646d2SAndroid Build Coastguard Worker cupsdSetJobState(printer->job, IPP_JOB_PENDING, CUPSD_JOB_FORCE,
2834*5e7646d2SAndroid Build Coastguard Worker "Job restarted because the printer was modified.");
2835*5e7646d2SAndroid Build Coastguard Worker }
2836*5e7646d2SAndroid Build Coastguard Worker
2837*5e7646d2SAndroid Build Coastguard Worker cupsdMarkDirty(CUPSD_DIRTY_PRINTCAP);
2838*5e7646d2SAndroid Build Coastguard Worker
2839*5e7646d2SAndroid Build Coastguard Worker if (modify)
2840*5e7646d2SAndroid Build Coastguard Worker {
2841*5e7646d2SAndroid Build Coastguard Worker cupsdAddEvent(CUPSD_EVENT_PRINTER_MODIFIED,
2842*5e7646d2SAndroid Build Coastguard Worker printer, NULL, "Printer \"%s\" modified by \"%s\".",
2843*5e7646d2SAndroid Build Coastguard Worker printer->name, get_username(con));
2844*5e7646d2SAndroid Build Coastguard Worker
2845*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_INFO, "Printer \"%s\" modified by \"%s\".",
2846*5e7646d2SAndroid Build Coastguard Worker printer->name, get_username(con));
2847*5e7646d2SAndroid Build Coastguard Worker }
2848*5e7646d2SAndroid Build Coastguard Worker else
2849*5e7646d2SAndroid Build Coastguard Worker {
2850*5e7646d2SAndroid Build Coastguard Worker cupsdAddEvent(CUPSD_EVENT_PRINTER_ADDED,
2851*5e7646d2SAndroid Build Coastguard Worker printer, NULL, "New printer \"%s\" added by \"%s\".",
2852*5e7646d2SAndroid Build Coastguard Worker printer->name, get_username(con));
2853*5e7646d2SAndroid Build Coastguard Worker
2854*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_INFO, "New printer \"%s\" added by \"%s\".",
2855*5e7646d2SAndroid Build Coastguard Worker printer->name, get_username(con));
2856*5e7646d2SAndroid Build Coastguard Worker }
2857*5e7646d2SAndroid Build Coastguard Worker
2858*5e7646d2SAndroid Build Coastguard Worker con->response->request.status.status_code = IPP_OK;
2859*5e7646d2SAndroid Build Coastguard Worker }
2860*5e7646d2SAndroid Build Coastguard Worker
2861*5e7646d2SAndroid Build Coastguard Worker
2862*5e7646d2SAndroid Build Coastguard Worker /*
2863*5e7646d2SAndroid Build Coastguard Worker * 'add_printer_state_reasons()' - Add the "printer-state-reasons" attribute
2864*5e7646d2SAndroid Build Coastguard Worker * based upon the printer state...
2865*5e7646d2SAndroid Build Coastguard Worker */
2866*5e7646d2SAndroid Build Coastguard Worker
2867*5e7646d2SAndroid Build Coastguard Worker static void
add_printer_state_reasons(cupsd_client_t * con,cupsd_printer_t * p)2868*5e7646d2SAndroid Build Coastguard Worker add_printer_state_reasons(
2869*5e7646d2SAndroid Build Coastguard Worker cupsd_client_t *con, /* I - Client connection */
2870*5e7646d2SAndroid Build Coastguard Worker cupsd_printer_t *p) /* I - Printer info */
2871*5e7646d2SAndroid Build Coastguard Worker {
2872*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG2,
2873*5e7646d2SAndroid Build Coastguard Worker "add_printer_state_reasons(%p[%d], %p[%s])",
2874*5e7646d2SAndroid Build Coastguard Worker con, con->number, p, p->name);
2875*5e7646d2SAndroid Build Coastguard Worker
2876*5e7646d2SAndroid Build Coastguard Worker if (p->num_reasons == 0)
2877*5e7646d2SAndroid Build Coastguard Worker ippAddString(con->response, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
2878*5e7646d2SAndroid Build Coastguard Worker "printer-state-reasons", NULL, "none");
2879*5e7646d2SAndroid Build Coastguard Worker else
2880*5e7646d2SAndroid Build Coastguard Worker ippAddStrings(con->response, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
2881*5e7646d2SAndroid Build Coastguard Worker "printer-state-reasons", p->num_reasons, NULL,
2882*5e7646d2SAndroid Build Coastguard Worker (const char * const *)p->reasons);
2883*5e7646d2SAndroid Build Coastguard Worker }
2884*5e7646d2SAndroid Build Coastguard Worker
2885*5e7646d2SAndroid Build Coastguard Worker
2886*5e7646d2SAndroid Build Coastguard Worker /*
2887*5e7646d2SAndroid Build Coastguard Worker * 'add_queued_job_count()' - Add the "queued-job-count" attribute for
2888*5e7646d2SAndroid Build Coastguard Worker * the specified printer or class.
2889*5e7646d2SAndroid Build Coastguard Worker */
2890*5e7646d2SAndroid Build Coastguard Worker
2891*5e7646d2SAndroid Build Coastguard Worker static void
add_queued_job_count(cupsd_client_t * con,cupsd_printer_t * p)2892*5e7646d2SAndroid Build Coastguard Worker add_queued_job_count(
2893*5e7646d2SAndroid Build Coastguard Worker cupsd_client_t *con, /* I - Client connection */
2894*5e7646d2SAndroid Build Coastguard Worker cupsd_printer_t *p) /* I - Printer or class */
2895*5e7646d2SAndroid Build Coastguard Worker {
2896*5e7646d2SAndroid Build Coastguard Worker int count; /* Number of jobs on destination */
2897*5e7646d2SAndroid Build Coastguard Worker
2898*5e7646d2SAndroid Build Coastguard Worker
2899*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG2, "add_queued_job_count(%p[%d], %p[%s])",
2900*5e7646d2SAndroid Build Coastguard Worker con, con->number, p, p->name);
2901*5e7646d2SAndroid Build Coastguard Worker
2902*5e7646d2SAndroid Build Coastguard Worker count = cupsdGetPrinterJobCount(p->name);
2903*5e7646d2SAndroid Build Coastguard Worker
2904*5e7646d2SAndroid Build Coastguard Worker ippAddInteger(con->response, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
2905*5e7646d2SAndroid Build Coastguard Worker "queued-job-count", count);
2906*5e7646d2SAndroid Build Coastguard Worker }
2907*5e7646d2SAndroid Build Coastguard Worker
2908*5e7646d2SAndroid Build Coastguard Worker
2909*5e7646d2SAndroid Build Coastguard Worker /*
2910*5e7646d2SAndroid Build Coastguard Worker * 'apply_printer_defaults()' - Apply printer default options to a job.
2911*5e7646d2SAndroid Build Coastguard Worker */
2912*5e7646d2SAndroid Build Coastguard Worker
2913*5e7646d2SAndroid Build Coastguard Worker static void
apply_printer_defaults(cupsd_printer_t * printer,cupsd_job_t * job)2914*5e7646d2SAndroid Build Coastguard Worker apply_printer_defaults(
2915*5e7646d2SAndroid Build Coastguard Worker cupsd_printer_t *printer, /* I - Printer */
2916*5e7646d2SAndroid Build Coastguard Worker cupsd_job_t *job) /* I - Job */
2917*5e7646d2SAndroid Build Coastguard Worker {
2918*5e7646d2SAndroid Build Coastguard Worker int i, /* Looping var */
2919*5e7646d2SAndroid Build Coastguard Worker num_options; /* Number of default options */
2920*5e7646d2SAndroid Build Coastguard Worker cups_option_t *options, /* Default options */
2921*5e7646d2SAndroid Build Coastguard Worker *option; /* Current option */
2922*5e7646d2SAndroid Build Coastguard Worker
2923*5e7646d2SAndroid Build Coastguard Worker
2924*5e7646d2SAndroid Build Coastguard Worker cupsdLogJob(job, CUPSD_LOG_DEBUG, "Applying default options...");
2925*5e7646d2SAndroid Build Coastguard Worker
2926*5e7646d2SAndroid Build Coastguard Worker /*
2927*5e7646d2SAndroid Build Coastguard Worker * Collect all of the default options and add the missing ones to the
2928*5e7646d2SAndroid Build Coastguard Worker * job object...
2929*5e7646d2SAndroid Build Coastguard Worker */
2930*5e7646d2SAndroid Build Coastguard Worker
2931*5e7646d2SAndroid Build Coastguard Worker for (i = printer->num_options, num_options = 0, options = NULL,
2932*5e7646d2SAndroid Build Coastguard Worker option = printer->options;
2933*5e7646d2SAndroid Build Coastguard Worker i > 0;
2934*5e7646d2SAndroid Build Coastguard Worker i --, option ++)
2935*5e7646d2SAndroid Build Coastguard Worker if (!ippFindAttribute(job->attrs, option->name, IPP_TAG_ZERO))
2936*5e7646d2SAndroid Build Coastguard Worker {
2937*5e7646d2SAndroid Build Coastguard Worker if (!strcmp(option->name, "print-quality") && ippFindAttribute(job->attrs, "cupsPrintQuality", IPP_TAG_NAME))
2938*5e7646d2SAndroid Build Coastguard Worker continue; /* Don't override cupsPrintQuality */
2939*5e7646d2SAndroid Build Coastguard Worker
2940*5e7646d2SAndroid Build Coastguard Worker cupsdLogJob(job, CUPSD_LOG_DEBUG, "Adding default %s=%s", option->name, option->value);
2941*5e7646d2SAndroid Build Coastguard Worker
2942*5e7646d2SAndroid Build Coastguard Worker num_options = cupsAddOption(option->name, option->value, num_options, &options);
2943*5e7646d2SAndroid Build Coastguard Worker }
2944*5e7646d2SAndroid Build Coastguard Worker
2945*5e7646d2SAndroid Build Coastguard Worker /*
2946*5e7646d2SAndroid Build Coastguard Worker * Encode these options as attributes in the job object...
2947*5e7646d2SAndroid Build Coastguard Worker */
2948*5e7646d2SAndroid Build Coastguard Worker
2949*5e7646d2SAndroid Build Coastguard Worker cupsEncodeOptions2(job->attrs, num_options, options, IPP_TAG_JOB);
2950*5e7646d2SAndroid Build Coastguard Worker cupsFreeOptions(num_options, options);
2951*5e7646d2SAndroid Build Coastguard Worker }
2952*5e7646d2SAndroid Build Coastguard Worker
2953*5e7646d2SAndroid Build Coastguard Worker
2954*5e7646d2SAndroid Build Coastguard Worker /*
2955*5e7646d2SAndroid Build Coastguard Worker * 'authenticate_job()' - Set job authentication info.
2956*5e7646d2SAndroid Build Coastguard Worker */
2957*5e7646d2SAndroid Build Coastguard Worker
2958*5e7646d2SAndroid Build Coastguard Worker static void
authenticate_job(cupsd_client_t * con,ipp_attribute_t * uri)2959*5e7646d2SAndroid Build Coastguard Worker authenticate_job(cupsd_client_t *con, /* I - Client connection */
2960*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *uri) /* I - Job URI */
2961*5e7646d2SAndroid Build Coastguard Worker {
2962*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *attr, /* job-id attribute */
2963*5e7646d2SAndroid Build Coastguard Worker *auth_info; /* auth-info attribute */
2964*5e7646d2SAndroid Build Coastguard Worker int jobid; /* Job ID */
2965*5e7646d2SAndroid Build Coastguard Worker cupsd_job_t *job; /* Current job */
2966*5e7646d2SAndroid Build Coastguard Worker char scheme[HTTP_MAX_URI],
2967*5e7646d2SAndroid Build Coastguard Worker /* Method portion of URI */
2968*5e7646d2SAndroid Build Coastguard Worker username[HTTP_MAX_URI],
2969*5e7646d2SAndroid Build Coastguard Worker /* Username portion of URI */
2970*5e7646d2SAndroid Build Coastguard Worker host[HTTP_MAX_URI],
2971*5e7646d2SAndroid Build Coastguard Worker /* Host portion of URI */
2972*5e7646d2SAndroid Build Coastguard Worker resource[HTTP_MAX_URI];
2973*5e7646d2SAndroid Build Coastguard Worker /* Resource portion of URI */
2974*5e7646d2SAndroid Build Coastguard Worker int port; /* Port portion of URI */
2975*5e7646d2SAndroid Build Coastguard Worker
2976*5e7646d2SAndroid Build Coastguard Worker
2977*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG2, "authenticate_job(%p[%d], %s)",
2978*5e7646d2SAndroid Build Coastguard Worker con, con->number, uri->values[0].string.text);
2979*5e7646d2SAndroid Build Coastguard Worker
2980*5e7646d2SAndroid Build Coastguard Worker /*
2981*5e7646d2SAndroid Build Coastguard Worker * Start with "everything is OK" status...
2982*5e7646d2SAndroid Build Coastguard Worker */
2983*5e7646d2SAndroid Build Coastguard Worker
2984*5e7646d2SAndroid Build Coastguard Worker con->response->request.status.status_code = IPP_OK;
2985*5e7646d2SAndroid Build Coastguard Worker
2986*5e7646d2SAndroid Build Coastguard Worker /*
2987*5e7646d2SAndroid Build Coastguard Worker * See if we have a job URI or a printer URI...
2988*5e7646d2SAndroid Build Coastguard Worker */
2989*5e7646d2SAndroid Build Coastguard Worker
2990*5e7646d2SAndroid Build Coastguard Worker if (!strcmp(uri->name, "printer-uri"))
2991*5e7646d2SAndroid Build Coastguard Worker {
2992*5e7646d2SAndroid Build Coastguard Worker /*
2993*5e7646d2SAndroid Build Coastguard Worker * Got a printer URI; see if we also have a job-id attribute...
2994*5e7646d2SAndroid Build Coastguard Worker */
2995*5e7646d2SAndroid Build Coastguard Worker
2996*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippFindAttribute(con->request, "job-id",
2997*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_INTEGER)) == NULL)
2998*5e7646d2SAndroid Build Coastguard Worker {
2999*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_BAD_REQUEST,
3000*5e7646d2SAndroid Build Coastguard Worker _("Got a printer-uri attribute but no job-id."));
3001*5e7646d2SAndroid Build Coastguard Worker return;
3002*5e7646d2SAndroid Build Coastguard Worker }
3003*5e7646d2SAndroid Build Coastguard Worker
3004*5e7646d2SAndroid Build Coastguard Worker jobid = attr->values[0].integer;
3005*5e7646d2SAndroid Build Coastguard Worker }
3006*5e7646d2SAndroid Build Coastguard Worker else
3007*5e7646d2SAndroid Build Coastguard Worker {
3008*5e7646d2SAndroid Build Coastguard Worker /*
3009*5e7646d2SAndroid Build Coastguard Worker * Got a job URI; parse it to get the job ID...
3010*5e7646d2SAndroid Build Coastguard Worker */
3011*5e7646d2SAndroid Build Coastguard Worker
3012*5e7646d2SAndroid Build Coastguard Worker httpSeparateURI(HTTP_URI_CODING_ALL, uri->values[0].string.text, scheme,
3013*5e7646d2SAndroid Build Coastguard Worker sizeof(scheme), username, sizeof(username), host,
3014*5e7646d2SAndroid Build Coastguard Worker sizeof(host), &port, resource, sizeof(resource));
3015*5e7646d2SAndroid Build Coastguard Worker
3016*5e7646d2SAndroid Build Coastguard Worker if (strncmp(resource, "/jobs/", 6))
3017*5e7646d2SAndroid Build Coastguard Worker {
3018*5e7646d2SAndroid Build Coastguard Worker /*
3019*5e7646d2SAndroid Build Coastguard Worker * Not a valid URI!
3020*5e7646d2SAndroid Build Coastguard Worker */
3021*5e7646d2SAndroid Build Coastguard Worker
3022*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_BAD_REQUEST, _("Bad job-uri \"%s\"."),
3023*5e7646d2SAndroid Build Coastguard Worker uri->values[0].string.text);
3024*5e7646d2SAndroid Build Coastguard Worker return;
3025*5e7646d2SAndroid Build Coastguard Worker }
3026*5e7646d2SAndroid Build Coastguard Worker
3027*5e7646d2SAndroid Build Coastguard Worker jobid = atoi(resource + 6);
3028*5e7646d2SAndroid Build Coastguard Worker }
3029*5e7646d2SAndroid Build Coastguard Worker
3030*5e7646d2SAndroid Build Coastguard Worker /*
3031*5e7646d2SAndroid Build Coastguard Worker * See if the job exists...
3032*5e7646d2SAndroid Build Coastguard Worker */
3033*5e7646d2SAndroid Build Coastguard Worker
3034*5e7646d2SAndroid Build Coastguard Worker if ((job = cupsdFindJob(jobid)) == NULL)
3035*5e7646d2SAndroid Build Coastguard Worker {
3036*5e7646d2SAndroid Build Coastguard Worker /*
3037*5e7646d2SAndroid Build Coastguard Worker * Nope - return a "not found" error...
3038*5e7646d2SAndroid Build Coastguard Worker */
3039*5e7646d2SAndroid Build Coastguard Worker
3040*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_NOT_FOUND, _("Job #%d does not exist."), jobid);
3041*5e7646d2SAndroid Build Coastguard Worker return;
3042*5e7646d2SAndroid Build Coastguard Worker }
3043*5e7646d2SAndroid Build Coastguard Worker
3044*5e7646d2SAndroid Build Coastguard Worker /*
3045*5e7646d2SAndroid Build Coastguard Worker * See if the job has been completed...
3046*5e7646d2SAndroid Build Coastguard Worker */
3047*5e7646d2SAndroid Build Coastguard Worker
3048*5e7646d2SAndroid Build Coastguard Worker if (job->state_value != IPP_JOB_HELD)
3049*5e7646d2SAndroid Build Coastguard Worker {
3050*5e7646d2SAndroid Build Coastguard Worker /*
3051*5e7646d2SAndroid Build Coastguard Worker * Return a "not-possible" error...
3052*5e7646d2SAndroid Build Coastguard Worker */
3053*5e7646d2SAndroid Build Coastguard Worker
3054*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_NOT_POSSIBLE,
3055*5e7646d2SAndroid Build Coastguard Worker _("Job #%d is not held for authentication."),
3056*5e7646d2SAndroid Build Coastguard Worker jobid);
3057*5e7646d2SAndroid Build Coastguard Worker return;
3058*5e7646d2SAndroid Build Coastguard Worker }
3059*5e7646d2SAndroid Build Coastguard Worker
3060*5e7646d2SAndroid Build Coastguard Worker /*
3061*5e7646d2SAndroid Build Coastguard Worker * See if we have already authenticated...
3062*5e7646d2SAndroid Build Coastguard Worker */
3063*5e7646d2SAndroid Build Coastguard Worker
3064*5e7646d2SAndroid Build Coastguard Worker auth_info = ippFindAttribute(con->request, "auth-info", IPP_TAG_TEXT);
3065*5e7646d2SAndroid Build Coastguard Worker
3066*5e7646d2SAndroid Build Coastguard Worker if (!con->username[0] && !auth_info)
3067*5e7646d2SAndroid Build Coastguard Worker {
3068*5e7646d2SAndroid Build Coastguard Worker cupsd_printer_t *printer; /* Job destination */
3069*5e7646d2SAndroid Build Coastguard Worker
3070*5e7646d2SAndroid Build Coastguard Worker /*
3071*5e7646d2SAndroid Build Coastguard Worker * No auth data. If we need to authenticate via Kerberos, send a
3072*5e7646d2SAndroid Build Coastguard Worker * HTTP auth challenge, otherwise just return an IPP error...
3073*5e7646d2SAndroid Build Coastguard Worker */
3074*5e7646d2SAndroid Build Coastguard Worker
3075*5e7646d2SAndroid Build Coastguard Worker printer = cupsdFindDest(job->dest);
3076*5e7646d2SAndroid Build Coastguard Worker
3077*5e7646d2SAndroid Build Coastguard Worker if (printer && printer->num_auth_info_required > 0 &&
3078*5e7646d2SAndroid Build Coastguard Worker !strcmp(printer->auth_info_required[0], "negotiate"))
3079*5e7646d2SAndroid Build Coastguard Worker send_http_error(con, HTTP_UNAUTHORIZED, printer);
3080*5e7646d2SAndroid Build Coastguard Worker else
3081*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_NOT_AUTHORIZED,
3082*5e7646d2SAndroid Build Coastguard Worker _("No authentication information provided."));
3083*5e7646d2SAndroid Build Coastguard Worker return;
3084*5e7646d2SAndroid Build Coastguard Worker }
3085*5e7646d2SAndroid Build Coastguard Worker
3086*5e7646d2SAndroid Build Coastguard Worker /*
3087*5e7646d2SAndroid Build Coastguard Worker * See if the job is owned by the requesting user...
3088*5e7646d2SAndroid Build Coastguard Worker */
3089*5e7646d2SAndroid Build Coastguard Worker
3090*5e7646d2SAndroid Build Coastguard Worker if (!validate_user(job, con, job->username, username, sizeof(username)))
3091*5e7646d2SAndroid Build Coastguard Worker {
3092*5e7646d2SAndroid Build Coastguard Worker send_http_error(con, con->username[0] ? HTTP_FORBIDDEN : HTTP_UNAUTHORIZED,
3093*5e7646d2SAndroid Build Coastguard Worker cupsdFindDest(job->dest));
3094*5e7646d2SAndroid Build Coastguard Worker return;
3095*5e7646d2SAndroid Build Coastguard Worker }
3096*5e7646d2SAndroid Build Coastguard Worker
3097*5e7646d2SAndroid Build Coastguard Worker /*
3098*5e7646d2SAndroid Build Coastguard Worker * Save the authentication information for this job...
3099*5e7646d2SAndroid Build Coastguard Worker */
3100*5e7646d2SAndroid Build Coastguard Worker
3101*5e7646d2SAndroid Build Coastguard Worker save_auth_info(con, job, auth_info);
3102*5e7646d2SAndroid Build Coastguard Worker
3103*5e7646d2SAndroid Build Coastguard Worker /*
3104*5e7646d2SAndroid Build Coastguard Worker * Reset the job-hold-until value to "no-hold"...
3105*5e7646d2SAndroid Build Coastguard Worker */
3106*5e7646d2SAndroid Build Coastguard Worker
3107*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippFindAttribute(job->attrs, "job-hold-until",
3108*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_KEYWORD)) == NULL)
3109*5e7646d2SAndroid Build Coastguard Worker attr = ippFindAttribute(job->attrs, "job-hold-until", IPP_TAG_NAME);
3110*5e7646d2SAndroid Build Coastguard Worker
3111*5e7646d2SAndroid Build Coastguard Worker if (attr)
3112*5e7646d2SAndroid Build Coastguard Worker {
3113*5e7646d2SAndroid Build Coastguard Worker ippSetValueTag(job->attrs, &attr, IPP_TAG_KEYWORD);
3114*5e7646d2SAndroid Build Coastguard Worker ippSetString(job->attrs, &attr, 0, "no-hold");
3115*5e7646d2SAndroid Build Coastguard Worker }
3116*5e7646d2SAndroid Build Coastguard Worker
3117*5e7646d2SAndroid Build Coastguard Worker /*
3118*5e7646d2SAndroid Build Coastguard Worker * Release the job and return...
3119*5e7646d2SAndroid Build Coastguard Worker */
3120*5e7646d2SAndroid Build Coastguard Worker
3121*5e7646d2SAndroid Build Coastguard Worker cupsdReleaseJob(job);
3122*5e7646d2SAndroid Build Coastguard Worker
3123*5e7646d2SAndroid Build Coastguard Worker cupsdAddEvent(CUPSD_EVENT_JOB_STATE, NULL, job, "Job authenticated by user");
3124*5e7646d2SAndroid Build Coastguard Worker
3125*5e7646d2SAndroid Build Coastguard Worker cupsdLogJob(job, CUPSD_LOG_INFO, "Authenticated by \"%s\".", con->username);
3126*5e7646d2SAndroid Build Coastguard Worker
3127*5e7646d2SAndroid Build Coastguard Worker cupsdCheckJobs();
3128*5e7646d2SAndroid Build Coastguard Worker }
3129*5e7646d2SAndroid Build Coastguard Worker
3130*5e7646d2SAndroid Build Coastguard Worker
3131*5e7646d2SAndroid Build Coastguard Worker /*
3132*5e7646d2SAndroid Build Coastguard Worker * 'cancel_all_jobs()' - Cancel all or selected print jobs.
3133*5e7646d2SAndroid Build Coastguard Worker */
3134*5e7646d2SAndroid Build Coastguard Worker
3135*5e7646d2SAndroid Build Coastguard Worker static void
cancel_all_jobs(cupsd_client_t * con,ipp_attribute_t * uri)3136*5e7646d2SAndroid Build Coastguard Worker cancel_all_jobs(cupsd_client_t *con, /* I - Client connection */
3137*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *uri) /* I - Job or Printer URI */
3138*5e7646d2SAndroid Build Coastguard Worker {
3139*5e7646d2SAndroid Build Coastguard Worker int i; /* Looping var */
3140*5e7646d2SAndroid Build Coastguard Worker http_status_t status; /* Policy status */
3141*5e7646d2SAndroid Build Coastguard Worker cups_ptype_t dtype; /* Destination type */
3142*5e7646d2SAndroid Build Coastguard Worker char scheme[HTTP_MAX_URI], /* Scheme portion of URI */
3143*5e7646d2SAndroid Build Coastguard Worker userpass[HTTP_MAX_URI], /* Username portion of URI */
3144*5e7646d2SAndroid Build Coastguard Worker hostname[HTTP_MAX_URI], /* Host portion of URI */
3145*5e7646d2SAndroid Build Coastguard Worker resource[HTTP_MAX_URI]; /* Resource portion of URI */
3146*5e7646d2SAndroid Build Coastguard Worker int port; /* Port portion of URI */
3147*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *attr; /* Attribute in request */
3148*5e7646d2SAndroid Build Coastguard Worker const char *username = NULL; /* Username */
3149*5e7646d2SAndroid Build Coastguard Worker cupsd_jobaction_t purge = CUPSD_JOB_DEFAULT;
3150*5e7646d2SAndroid Build Coastguard Worker /* Purge? */
3151*5e7646d2SAndroid Build Coastguard Worker cupsd_printer_t *printer; /* Printer */
3152*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *job_ids; /* job-ids attribute */
3153*5e7646d2SAndroid Build Coastguard Worker cupsd_job_t *job; /* Job */
3154*5e7646d2SAndroid Build Coastguard Worker
3155*5e7646d2SAndroid Build Coastguard Worker
3156*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG2, "cancel_all_jobs(%p[%d], %s)", con,
3157*5e7646d2SAndroid Build Coastguard Worker con->number, uri->values[0].string.text);
3158*5e7646d2SAndroid Build Coastguard Worker
3159*5e7646d2SAndroid Build Coastguard Worker /*
3160*5e7646d2SAndroid Build Coastguard Worker * Get the jobs to cancel/purge...
3161*5e7646d2SAndroid Build Coastguard Worker */
3162*5e7646d2SAndroid Build Coastguard Worker
3163*5e7646d2SAndroid Build Coastguard Worker switch (con->request->request.op.operation_id)
3164*5e7646d2SAndroid Build Coastguard Worker {
3165*5e7646d2SAndroid Build Coastguard Worker case IPP_PURGE_JOBS :
3166*5e7646d2SAndroid Build Coastguard Worker /*
3167*5e7646d2SAndroid Build Coastguard Worker * Get the username (if any) for the jobs we want to cancel (only if
3168*5e7646d2SAndroid Build Coastguard Worker * "my-jobs" is specified...
3169*5e7646d2SAndroid Build Coastguard Worker */
3170*5e7646d2SAndroid Build Coastguard Worker
3171*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippFindAttribute(con->request, "my-jobs",
3172*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_BOOLEAN)) != NULL &&
3173*5e7646d2SAndroid Build Coastguard Worker attr->values[0].boolean)
3174*5e7646d2SAndroid Build Coastguard Worker {
3175*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippFindAttribute(con->request, "requesting-user-name",
3176*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_NAME)) != NULL)
3177*5e7646d2SAndroid Build Coastguard Worker username = attr->values[0].string.text;
3178*5e7646d2SAndroid Build Coastguard Worker else
3179*5e7646d2SAndroid Build Coastguard Worker {
3180*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_BAD_REQUEST,
3181*5e7646d2SAndroid Build Coastguard Worker _("Missing requesting-user-name attribute."));
3182*5e7646d2SAndroid Build Coastguard Worker return;
3183*5e7646d2SAndroid Build Coastguard Worker }
3184*5e7646d2SAndroid Build Coastguard Worker }
3185*5e7646d2SAndroid Build Coastguard Worker
3186*5e7646d2SAndroid Build Coastguard Worker /*
3187*5e7646d2SAndroid Build Coastguard Worker * Look for the "purge-jobs" attribute...
3188*5e7646d2SAndroid Build Coastguard Worker */
3189*5e7646d2SAndroid Build Coastguard Worker
3190*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippFindAttribute(con->request, "purge-jobs",
3191*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_BOOLEAN)) != NULL)
3192*5e7646d2SAndroid Build Coastguard Worker purge = attr->values[0].boolean ? CUPSD_JOB_PURGE : CUPSD_JOB_DEFAULT;
3193*5e7646d2SAndroid Build Coastguard Worker else
3194*5e7646d2SAndroid Build Coastguard Worker purge = CUPSD_JOB_PURGE;
3195*5e7646d2SAndroid Build Coastguard Worker break;
3196*5e7646d2SAndroid Build Coastguard Worker
3197*5e7646d2SAndroid Build Coastguard Worker case IPP_CANCEL_MY_JOBS :
3198*5e7646d2SAndroid Build Coastguard Worker if (con->username[0])
3199*5e7646d2SAndroid Build Coastguard Worker username = con->username;
3200*5e7646d2SAndroid Build Coastguard Worker else if ((attr = ippFindAttribute(con->request, "requesting-user-name",
3201*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_NAME)) != NULL)
3202*5e7646d2SAndroid Build Coastguard Worker username = attr->values[0].string.text;
3203*5e7646d2SAndroid Build Coastguard Worker else
3204*5e7646d2SAndroid Build Coastguard Worker {
3205*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_BAD_REQUEST,
3206*5e7646d2SAndroid Build Coastguard Worker _("Missing requesting-user-name attribute."));
3207*5e7646d2SAndroid Build Coastguard Worker return;
3208*5e7646d2SAndroid Build Coastguard Worker }
3209*5e7646d2SAndroid Build Coastguard Worker
3210*5e7646d2SAndroid Build Coastguard Worker default :
3211*5e7646d2SAndroid Build Coastguard Worker break;
3212*5e7646d2SAndroid Build Coastguard Worker }
3213*5e7646d2SAndroid Build Coastguard Worker
3214*5e7646d2SAndroid Build Coastguard Worker job_ids = ippFindAttribute(con->request, "job-ids", IPP_TAG_INTEGER);
3215*5e7646d2SAndroid Build Coastguard Worker
3216*5e7646d2SAndroid Build Coastguard Worker /*
3217*5e7646d2SAndroid Build Coastguard Worker * See if we have a printer URI...
3218*5e7646d2SAndroid Build Coastguard Worker */
3219*5e7646d2SAndroid Build Coastguard Worker
3220*5e7646d2SAndroid Build Coastguard Worker if (strcmp(uri->name, "printer-uri"))
3221*5e7646d2SAndroid Build Coastguard Worker {
3222*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_BAD_REQUEST,
3223*5e7646d2SAndroid Build Coastguard Worker _("The printer-uri attribute is required."));
3224*5e7646d2SAndroid Build Coastguard Worker return;
3225*5e7646d2SAndroid Build Coastguard Worker }
3226*5e7646d2SAndroid Build Coastguard Worker
3227*5e7646d2SAndroid Build Coastguard Worker /*
3228*5e7646d2SAndroid Build Coastguard Worker * And if the destination is valid...
3229*5e7646d2SAndroid Build Coastguard Worker */
3230*5e7646d2SAndroid Build Coastguard Worker
3231*5e7646d2SAndroid Build Coastguard Worker if (!cupsdValidateDest(uri->values[0].string.text, &dtype, &printer))
3232*5e7646d2SAndroid Build Coastguard Worker {
3233*5e7646d2SAndroid Build Coastguard Worker /*
3234*5e7646d2SAndroid Build Coastguard Worker * Bad URI?
3235*5e7646d2SAndroid Build Coastguard Worker */
3236*5e7646d2SAndroid Build Coastguard Worker
3237*5e7646d2SAndroid Build Coastguard Worker httpSeparateURI(HTTP_URI_CODING_ALL, uri->values[0].string.text,
3238*5e7646d2SAndroid Build Coastguard Worker scheme, sizeof(scheme), userpass, sizeof(userpass),
3239*5e7646d2SAndroid Build Coastguard Worker hostname, sizeof(hostname), &port,
3240*5e7646d2SAndroid Build Coastguard Worker resource, sizeof(resource));
3241*5e7646d2SAndroid Build Coastguard Worker
3242*5e7646d2SAndroid Build Coastguard Worker if ((!strncmp(resource, "/printers/", 10) && resource[10]) ||
3243*5e7646d2SAndroid Build Coastguard Worker (!strncmp(resource, "/classes/", 9) && resource[9]))
3244*5e7646d2SAndroid Build Coastguard Worker {
3245*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_NOT_FOUND,
3246*5e7646d2SAndroid Build Coastguard Worker _("The printer or class does not exist."));
3247*5e7646d2SAndroid Build Coastguard Worker return;
3248*5e7646d2SAndroid Build Coastguard Worker }
3249*5e7646d2SAndroid Build Coastguard Worker
3250*5e7646d2SAndroid Build Coastguard Worker /*
3251*5e7646d2SAndroid Build Coastguard Worker * Check policy...
3252*5e7646d2SAndroid Build Coastguard Worker */
3253*5e7646d2SAndroid Build Coastguard Worker
3254*5e7646d2SAndroid Build Coastguard Worker if ((status = cupsdCheckPolicy(DefaultPolicyPtr, con, NULL)) != HTTP_OK)
3255*5e7646d2SAndroid Build Coastguard Worker {
3256*5e7646d2SAndroid Build Coastguard Worker send_http_error(con, status, NULL);
3257*5e7646d2SAndroid Build Coastguard Worker return;
3258*5e7646d2SAndroid Build Coastguard Worker }
3259*5e7646d2SAndroid Build Coastguard Worker
3260*5e7646d2SAndroid Build Coastguard Worker if (job_ids)
3261*5e7646d2SAndroid Build Coastguard Worker {
3262*5e7646d2SAndroid Build Coastguard Worker for (i = 0; i < job_ids->num_values; i ++)
3263*5e7646d2SAndroid Build Coastguard Worker {
3264*5e7646d2SAndroid Build Coastguard Worker if ((job = cupsdFindJob(job_ids->values[i].integer)) == NULL)
3265*5e7646d2SAndroid Build Coastguard Worker break;
3266*5e7646d2SAndroid Build Coastguard Worker
3267*5e7646d2SAndroid Build Coastguard Worker if (con->request->request.op.operation_id == IPP_CANCEL_MY_JOBS &&
3268*5e7646d2SAndroid Build Coastguard Worker _cups_strcasecmp(job->username, username))
3269*5e7646d2SAndroid Build Coastguard Worker break;
3270*5e7646d2SAndroid Build Coastguard Worker }
3271*5e7646d2SAndroid Build Coastguard Worker
3272*5e7646d2SAndroid Build Coastguard Worker if (i < job_ids->num_values)
3273*5e7646d2SAndroid Build Coastguard Worker {
3274*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_NOT_FOUND, _("Job #%d does not exist."),
3275*5e7646d2SAndroid Build Coastguard Worker job_ids->values[i].integer);
3276*5e7646d2SAndroid Build Coastguard Worker return;
3277*5e7646d2SAndroid Build Coastguard Worker }
3278*5e7646d2SAndroid Build Coastguard Worker
3279*5e7646d2SAndroid Build Coastguard Worker for (i = 0; i < job_ids->num_values; i ++)
3280*5e7646d2SAndroid Build Coastguard Worker {
3281*5e7646d2SAndroid Build Coastguard Worker job = cupsdFindJob(job_ids->values[i].integer);
3282*5e7646d2SAndroid Build Coastguard Worker
3283*5e7646d2SAndroid Build Coastguard Worker cupsdSetJobState(job, IPP_JOB_CANCELED, purge,
3284*5e7646d2SAndroid Build Coastguard Worker purge == CUPSD_JOB_PURGE ? "Job purged by user." :
3285*5e7646d2SAndroid Build Coastguard Worker "Job canceled by user.");
3286*5e7646d2SAndroid Build Coastguard Worker }
3287*5e7646d2SAndroid Build Coastguard Worker
3288*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_INFO, "Selected jobs were %s by \"%s\".",
3289*5e7646d2SAndroid Build Coastguard Worker purge == CUPSD_JOB_PURGE ? "purged" : "canceled",
3290*5e7646d2SAndroid Build Coastguard Worker get_username(con));
3291*5e7646d2SAndroid Build Coastguard Worker }
3292*5e7646d2SAndroid Build Coastguard Worker else
3293*5e7646d2SAndroid Build Coastguard Worker {
3294*5e7646d2SAndroid Build Coastguard Worker /*
3295*5e7646d2SAndroid Build Coastguard Worker * Cancel all jobs on all printers...
3296*5e7646d2SAndroid Build Coastguard Worker */
3297*5e7646d2SAndroid Build Coastguard Worker
3298*5e7646d2SAndroid Build Coastguard Worker cupsdCancelJobs(NULL, username, purge != CUPSD_JOB_DEFAULT);
3299*5e7646d2SAndroid Build Coastguard Worker
3300*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_INFO, "All jobs were %s by \"%s\".",
3301*5e7646d2SAndroid Build Coastguard Worker purge == CUPSD_JOB_PURGE ? "purged" : "canceled",
3302*5e7646d2SAndroid Build Coastguard Worker get_username(con));
3303*5e7646d2SAndroid Build Coastguard Worker }
3304*5e7646d2SAndroid Build Coastguard Worker }
3305*5e7646d2SAndroid Build Coastguard Worker else
3306*5e7646d2SAndroid Build Coastguard Worker {
3307*5e7646d2SAndroid Build Coastguard Worker /*
3308*5e7646d2SAndroid Build Coastguard Worker * Check policy...
3309*5e7646d2SAndroid Build Coastguard Worker */
3310*5e7646d2SAndroid Build Coastguard Worker
3311*5e7646d2SAndroid Build Coastguard Worker if ((status = cupsdCheckPolicy(printer->op_policy_ptr, con,
3312*5e7646d2SAndroid Build Coastguard Worker NULL)) != HTTP_OK)
3313*5e7646d2SAndroid Build Coastguard Worker {
3314*5e7646d2SAndroid Build Coastguard Worker send_http_error(con, status, printer);
3315*5e7646d2SAndroid Build Coastguard Worker return;
3316*5e7646d2SAndroid Build Coastguard Worker }
3317*5e7646d2SAndroid Build Coastguard Worker
3318*5e7646d2SAndroid Build Coastguard Worker if (job_ids)
3319*5e7646d2SAndroid Build Coastguard Worker {
3320*5e7646d2SAndroid Build Coastguard Worker for (i = 0; i < job_ids->num_values; i ++)
3321*5e7646d2SAndroid Build Coastguard Worker {
3322*5e7646d2SAndroid Build Coastguard Worker if ((job = cupsdFindJob(job_ids->values[i].integer)) == NULL ||
3323*5e7646d2SAndroid Build Coastguard Worker _cups_strcasecmp(job->dest, printer->name))
3324*5e7646d2SAndroid Build Coastguard Worker break;
3325*5e7646d2SAndroid Build Coastguard Worker
3326*5e7646d2SAndroid Build Coastguard Worker if (con->request->request.op.operation_id == IPP_CANCEL_MY_JOBS &&
3327*5e7646d2SAndroid Build Coastguard Worker _cups_strcasecmp(job->username, username))
3328*5e7646d2SAndroid Build Coastguard Worker break;
3329*5e7646d2SAndroid Build Coastguard Worker }
3330*5e7646d2SAndroid Build Coastguard Worker
3331*5e7646d2SAndroid Build Coastguard Worker if (i < job_ids->num_values)
3332*5e7646d2SAndroid Build Coastguard Worker {
3333*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_NOT_FOUND, _("Job #%d does not exist."),
3334*5e7646d2SAndroid Build Coastguard Worker job_ids->values[i].integer);
3335*5e7646d2SAndroid Build Coastguard Worker return;
3336*5e7646d2SAndroid Build Coastguard Worker }
3337*5e7646d2SAndroid Build Coastguard Worker
3338*5e7646d2SAndroid Build Coastguard Worker for (i = 0; i < job_ids->num_values; i ++)
3339*5e7646d2SAndroid Build Coastguard Worker {
3340*5e7646d2SAndroid Build Coastguard Worker job = cupsdFindJob(job_ids->values[i].integer);
3341*5e7646d2SAndroid Build Coastguard Worker
3342*5e7646d2SAndroid Build Coastguard Worker cupsdSetJobState(job, IPP_JOB_CANCELED, purge,
3343*5e7646d2SAndroid Build Coastguard Worker purge == CUPSD_JOB_PURGE ? "Job purged by user." :
3344*5e7646d2SAndroid Build Coastguard Worker "Job canceled by user.");
3345*5e7646d2SAndroid Build Coastguard Worker }
3346*5e7646d2SAndroid Build Coastguard Worker
3347*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_INFO, "Selected jobs were %s by \"%s\".",
3348*5e7646d2SAndroid Build Coastguard Worker purge == CUPSD_JOB_PURGE ? "purged" : "canceled",
3349*5e7646d2SAndroid Build Coastguard Worker get_username(con));
3350*5e7646d2SAndroid Build Coastguard Worker }
3351*5e7646d2SAndroid Build Coastguard Worker else
3352*5e7646d2SAndroid Build Coastguard Worker {
3353*5e7646d2SAndroid Build Coastguard Worker /*
3354*5e7646d2SAndroid Build Coastguard Worker * Cancel all of the jobs on the named printer...
3355*5e7646d2SAndroid Build Coastguard Worker */
3356*5e7646d2SAndroid Build Coastguard Worker
3357*5e7646d2SAndroid Build Coastguard Worker cupsdCancelJobs(printer->name, username, purge != CUPSD_JOB_DEFAULT);
3358*5e7646d2SAndroid Build Coastguard Worker
3359*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_INFO, "All jobs on \"%s\" were %s by \"%s\".",
3360*5e7646d2SAndroid Build Coastguard Worker printer->name,
3361*5e7646d2SAndroid Build Coastguard Worker purge == CUPSD_JOB_PURGE ? "purged" : "canceled",
3362*5e7646d2SAndroid Build Coastguard Worker get_username(con));
3363*5e7646d2SAndroid Build Coastguard Worker }
3364*5e7646d2SAndroid Build Coastguard Worker }
3365*5e7646d2SAndroid Build Coastguard Worker
3366*5e7646d2SAndroid Build Coastguard Worker con->response->request.status.status_code = IPP_OK;
3367*5e7646d2SAndroid Build Coastguard Worker
3368*5e7646d2SAndroid Build Coastguard Worker cupsdCheckJobs();
3369*5e7646d2SAndroid Build Coastguard Worker }
3370*5e7646d2SAndroid Build Coastguard Worker
3371*5e7646d2SAndroid Build Coastguard Worker
3372*5e7646d2SAndroid Build Coastguard Worker /*
3373*5e7646d2SAndroid Build Coastguard Worker * 'cancel_job()' - Cancel a print job.
3374*5e7646d2SAndroid Build Coastguard Worker */
3375*5e7646d2SAndroid Build Coastguard Worker
3376*5e7646d2SAndroid Build Coastguard Worker static void
cancel_job(cupsd_client_t * con,ipp_attribute_t * uri)3377*5e7646d2SAndroid Build Coastguard Worker cancel_job(cupsd_client_t *con, /* I - Client connection */
3378*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *uri) /* I - Job or Printer URI */
3379*5e7646d2SAndroid Build Coastguard Worker {
3380*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *attr; /* Current attribute */
3381*5e7646d2SAndroid Build Coastguard Worker int jobid; /* Job ID */
3382*5e7646d2SAndroid Build Coastguard Worker char scheme[HTTP_MAX_URI], /* Scheme portion of URI */
3383*5e7646d2SAndroid Build Coastguard Worker username[HTTP_MAX_URI], /* Username portion of URI */
3384*5e7646d2SAndroid Build Coastguard Worker host[HTTP_MAX_URI], /* Host portion of URI */
3385*5e7646d2SAndroid Build Coastguard Worker resource[HTTP_MAX_URI]; /* Resource portion of URI */
3386*5e7646d2SAndroid Build Coastguard Worker int port; /* Port portion of URI */
3387*5e7646d2SAndroid Build Coastguard Worker cupsd_job_t *job; /* Job information */
3388*5e7646d2SAndroid Build Coastguard Worker cups_ptype_t dtype; /* Destination type (printer/class) */
3389*5e7646d2SAndroid Build Coastguard Worker cupsd_printer_t *printer; /* Printer data */
3390*5e7646d2SAndroid Build Coastguard Worker cupsd_jobaction_t purge; /* Purge the job? */
3391*5e7646d2SAndroid Build Coastguard Worker
3392*5e7646d2SAndroid Build Coastguard Worker
3393*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG2, "cancel_job(%p[%d], %s)", con,
3394*5e7646d2SAndroid Build Coastguard Worker con->number, uri->values[0].string.text);
3395*5e7646d2SAndroid Build Coastguard Worker
3396*5e7646d2SAndroid Build Coastguard Worker /*
3397*5e7646d2SAndroid Build Coastguard Worker * See if we have a job URI or a printer URI...
3398*5e7646d2SAndroid Build Coastguard Worker */
3399*5e7646d2SAndroid Build Coastguard Worker
3400*5e7646d2SAndroid Build Coastguard Worker if (!strcmp(uri->name, "printer-uri"))
3401*5e7646d2SAndroid Build Coastguard Worker {
3402*5e7646d2SAndroid Build Coastguard Worker /*
3403*5e7646d2SAndroid Build Coastguard Worker * Got a printer URI; see if we also have a job-id attribute...
3404*5e7646d2SAndroid Build Coastguard Worker */
3405*5e7646d2SAndroid Build Coastguard Worker
3406*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippFindAttribute(con->request, "job-id",
3407*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_INTEGER)) == NULL)
3408*5e7646d2SAndroid Build Coastguard Worker {
3409*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_BAD_REQUEST,
3410*5e7646d2SAndroid Build Coastguard Worker _("Got a printer-uri attribute but no job-id."));
3411*5e7646d2SAndroid Build Coastguard Worker return;
3412*5e7646d2SAndroid Build Coastguard Worker }
3413*5e7646d2SAndroid Build Coastguard Worker
3414*5e7646d2SAndroid Build Coastguard Worker if ((jobid = attr->values[0].integer) == 0)
3415*5e7646d2SAndroid Build Coastguard Worker {
3416*5e7646d2SAndroid Build Coastguard Worker /*
3417*5e7646d2SAndroid Build Coastguard Worker * Find the current job on the specified printer...
3418*5e7646d2SAndroid Build Coastguard Worker */
3419*5e7646d2SAndroid Build Coastguard Worker
3420*5e7646d2SAndroid Build Coastguard Worker if (!cupsdValidateDest(uri->values[0].string.text, &dtype, &printer))
3421*5e7646d2SAndroid Build Coastguard Worker {
3422*5e7646d2SAndroid Build Coastguard Worker /*
3423*5e7646d2SAndroid Build Coastguard Worker * Bad URI...
3424*5e7646d2SAndroid Build Coastguard Worker */
3425*5e7646d2SAndroid Build Coastguard Worker
3426*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_NOT_FOUND,
3427*5e7646d2SAndroid Build Coastguard Worker _("The printer or class does not exist."));
3428*5e7646d2SAndroid Build Coastguard Worker return;
3429*5e7646d2SAndroid Build Coastguard Worker }
3430*5e7646d2SAndroid Build Coastguard Worker
3431*5e7646d2SAndroid Build Coastguard Worker /*
3432*5e7646d2SAndroid Build Coastguard Worker * See if there are any pending jobs...
3433*5e7646d2SAndroid Build Coastguard Worker */
3434*5e7646d2SAndroid Build Coastguard Worker
3435*5e7646d2SAndroid Build Coastguard Worker for (job = (cupsd_job_t *)cupsArrayFirst(ActiveJobs);
3436*5e7646d2SAndroid Build Coastguard Worker job;
3437*5e7646d2SAndroid Build Coastguard Worker job = (cupsd_job_t *)cupsArrayNext(ActiveJobs))
3438*5e7646d2SAndroid Build Coastguard Worker if (job->state_value <= IPP_JOB_PROCESSING &&
3439*5e7646d2SAndroid Build Coastguard Worker !_cups_strcasecmp(job->dest, printer->name))
3440*5e7646d2SAndroid Build Coastguard Worker break;
3441*5e7646d2SAndroid Build Coastguard Worker
3442*5e7646d2SAndroid Build Coastguard Worker if (job)
3443*5e7646d2SAndroid Build Coastguard Worker jobid = job->id;
3444*5e7646d2SAndroid Build Coastguard Worker else
3445*5e7646d2SAndroid Build Coastguard Worker {
3446*5e7646d2SAndroid Build Coastguard Worker /*
3447*5e7646d2SAndroid Build Coastguard Worker * No, try stopped jobs...
3448*5e7646d2SAndroid Build Coastguard Worker */
3449*5e7646d2SAndroid Build Coastguard Worker
3450*5e7646d2SAndroid Build Coastguard Worker for (job = (cupsd_job_t *)cupsArrayFirst(ActiveJobs);
3451*5e7646d2SAndroid Build Coastguard Worker job;
3452*5e7646d2SAndroid Build Coastguard Worker job = (cupsd_job_t *)cupsArrayNext(ActiveJobs))
3453*5e7646d2SAndroid Build Coastguard Worker if (job->state_value == IPP_JOB_STOPPED &&
3454*5e7646d2SAndroid Build Coastguard Worker !_cups_strcasecmp(job->dest, printer->name))
3455*5e7646d2SAndroid Build Coastguard Worker break;
3456*5e7646d2SAndroid Build Coastguard Worker
3457*5e7646d2SAndroid Build Coastguard Worker if (job)
3458*5e7646d2SAndroid Build Coastguard Worker jobid = job->id;
3459*5e7646d2SAndroid Build Coastguard Worker else
3460*5e7646d2SAndroid Build Coastguard Worker {
3461*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_NOT_POSSIBLE, _("No active jobs on %s."),
3462*5e7646d2SAndroid Build Coastguard Worker printer->name);
3463*5e7646d2SAndroid Build Coastguard Worker return;
3464*5e7646d2SAndroid Build Coastguard Worker }
3465*5e7646d2SAndroid Build Coastguard Worker }
3466*5e7646d2SAndroid Build Coastguard Worker }
3467*5e7646d2SAndroid Build Coastguard Worker }
3468*5e7646d2SAndroid Build Coastguard Worker else
3469*5e7646d2SAndroid Build Coastguard Worker {
3470*5e7646d2SAndroid Build Coastguard Worker /*
3471*5e7646d2SAndroid Build Coastguard Worker * Got a job URI; parse it to get the job ID...
3472*5e7646d2SAndroid Build Coastguard Worker */
3473*5e7646d2SAndroid Build Coastguard Worker
3474*5e7646d2SAndroid Build Coastguard Worker httpSeparateURI(HTTP_URI_CODING_ALL, uri->values[0].string.text, scheme,
3475*5e7646d2SAndroid Build Coastguard Worker sizeof(scheme), username, sizeof(username), host,
3476*5e7646d2SAndroid Build Coastguard Worker sizeof(host), &port, resource, sizeof(resource));
3477*5e7646d2SAndroid Build Coastguard Worker
3478*5e7646d2SAndroid Build Coastguard Worker if (strncmp(resource, "/jobs/", 6))
3479*5e7646d2SAndroid Build Coastguard Worker {
3480*5e7646d2SAndroid Build Coastguard Worker /*
3481*5e7646d2SAndroid Build Coastguard Worker * Not a valid URI!
3482*5e7646d2SAndroid Build Coastguard Worker */
3483*5e7646d2SAndroid Build Coastguard Worker
3484*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_BAD_REQUEST, _("Bad job-uri \"%s\"."),
3485*5e7646d2SAndroid Build Coastguard Worker uri->values[0].string.text);
3486*5e7646d2SAndroid Build Coastguard Worker return;
3487*5e7646d2SAndroid Build Coastguard Worker }
3488*5e7646d2SAndroid Build Coastguard Worker
3489*5e7646d2SAndroid Build Coastguard Worker jobid = atoi(resource + 6);
3490*5e7646d2SAndroid Build Coastguard Worker }
3491*5e7646d2SAndroid Build Coastguard Worker
3492*5e7646d2SAndroid Build Coastguard Worker /*
3493*5e7646d2SAndroid Build Coastguard Worker * Look for the "purge-job" attribute...
3494*5e7646d2SAndroid Build Coastguard Worker */
3495*5e7646d2SAndroid Build Coastguard Worker
3496*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippFindAttribute(con->request, "purge-job",
3497*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_BOOLEAN)) != NULL)
3498*5e7646d2SAndroid Build Coastguard Worker purge = attr->values[0].boolean ? CUPSD_JOB_PURGE : CUPSD_JOB_DEFAULT;
3499*5e7646d2SAndroid Build Coastguard Worker else
3500*5e7646d2SAndroid Build Coastguard Worker purge = CUPSD_JOB_DEFAULT;
3501*5e7646d2SAndroid Build Coastguard Worker
3502*5e7646d2SAndroid Build Coastguard Worker /*
3503*5e7646d2SAndroid Build Coastguard Worker * See if the job exists...
3504*5e7646d2SAndroid Build Coastguard Worker */
3505*5e7646d2SAndroid Build Coastguard Worker
3506*5e7646d2SAndroid Build Coastguard Worker if ((job = cupsdFindJob(jobid)) == NULL)
3507*5e7646d2SAndroid Build Coastguard Worker {
3508*5e7646d2SAndroid Build Coastguard Worker /*
3509*5e7646d2SAndroid Build Coastguard Worker * Nope - return a "not found" error...
3510*5e7646d2SAndroid Build Coastguard Worker */
3511*5e7646d2SAndroid Build Coastguard Worker
3512*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_NOT_FOUND, _("Job #%d does not exist."), jobid);
3513*5e7646d2SAndroid Build Coastguard Worker return;
3514*5e7646d2SAndroid Build Coastguard Worker }
3515*5e7646d2SAndroid Build Coastguard Worker
3516*5e7646d2SAndroid Build Coastguard Worker /*
3517*5e7646d2SAndroid Build Coastguard Worker * See if the job is owned by the requesting user...
3518*5e7646d2SAndroid Build Coastguard Worker */
3519*5e7646d2SAndroid Build Coastguard Worker
3520*5e7646d2SAndroid Build Coastguard Worker if (!validate_user(job, con, job->username, username, sizeof(username)))
3521*5e7646d2SAndroid Build Coastguard Worker {
3522*5e7646d2SAndroid Build Coastguard Worker send_http_error(con, con->username[0] ? HTTP_FORBIDDEN : HTTP_UNAUTHORIZED,
3523*5e7646d2SAndroid Build Coastguard Worker cupsdFindDest(job->dest));
3524*5e7646d2SAndroid Build Coastguard Worker return;
3525*5e7646d2SAndroid Build Coastguard Worker }
3526*5e7646d2SAndroid Build Coastguard Worker
3527*5e7646d2SAndroid Build Coastguard Worker /*
3528*5e7646d2SAndroid Build Coastguard Worker * See if the job is already completed, canceled, or aborted; if so,
3529*5e7646d2SAndroid Build Coastguard Worker * we can't cancel...
3530*5e7646d2SAndroid Build Coastguard Worker */
3531*5e7646d2SAndroid Build Coastguard Worker
3532*5e7646d2SAndroid Build Coastguard Worker if (job->state_value >= IPP_JOB_CANCELED && purge != CUPSD_JOB_PURGE)
3533*5e7646d2SAndroid Build Coastguard Worker {
3534*5e7646d2SAndroid Build Coastguard Worker switch (job->state_value)
3535*5e7646d2SAndroid Build Coastguard Worker {
3536*5e7646d2SAndroid Build Coastguard Worker case IPP_JOB_CANCELED :
3537*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_NOT_POSSIBLE,
3538*5e7646d2SAndroid Build Coastguard Worker _("Job #%d is already canceled - can\'t cancel."),
3539*5e7646d2SAndroid Build Coastguard Worker jobid);
3540*5e7646d2SAndroid Build Coastguard Worker break;
3541*5e7646d2SAndroid Build Coastguard Worker
3542*5e7646d2SAndroid Build Coastguard Worker case IPP_JOB_ABORTED :
3543*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_NOT_POSSIBLE,
3544*5e7646d2SAndroid Build Coastguard Worker _("Job #%d is already aborted - can\'t cancel."),
3545*5e7646d2SAndroid Build Coastguard Worker jobid);
3546*5e7646d2SAndroid Build Coastguard Worker break;
3547*5e7646d2SAndroid Build Coastguard Worker
3548*5e7646d2SAndroid Build Coastguard Worker default :
3549*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_NOT_POSSIBLE,
3550*5e7646d2SAndroid Build Coastguard Worker _("Job #%d is already completed - can\'t cancel."),
3551*5e7646d2SAndroid Build Coastguard Worker jobid);
3552*5e7646d2SAndroid Build Coastguard Worker break;
3553*5e7646d2SAndroid Build Coastguard Worker }
3554*5e7646d2SAndroid Build Coastguard Worker
3555*5e7646d2SAndroid Build Coastguard Worker return;
3556*5e7646d2SAndroid Build Coastguard Worker }
3557*5e7646d2SAndroid Build Coastguard Worker
3558*5e7646d2SAndroid Build Coastguard Worker /*
3559*5e7646d2SAndroid Build Coastguard Worker * Cancel the job and return...
3560*5e7646d2SAndroid Build Coastguard Worker */
3561*5e7646d2SAndroid Build Coastguard Worker
3562*5e7646d2SAndroid Build Coastguard Worker cupsdSetJobState(job, IPP_JOB_CANCELED, purge,
3563*5e7646d2SAndroid Build Coastguard Worker purge == CUPSD_JOB_PURGE ? "Job purged by \"%s\"" :
3564*5e7646d2SAndroid Build Coastguard Worker "Job canceled by \"%s\"",
3565*5e7646d2SAndroid Build Coastguard Worker username);
3566*5e7646d2SAndroid Build Coastguard Worker cupsdCheckJobs();
3567*5e7646d2SAndroid Build Coastguard Worker
3568*5e7646d2SAndroid Build Coastguard Worker if (purge == CUPSD_JOB_PURGE)
3569*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_INFO, "[Job %d] Purged by \"%s\".", jobid,
3570*5e7646d2SAndroid Build Coastguard Worker username);
3571*5e7646d2SAndroid Build Coastguard Worker else
3572*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_INFO, "[Job %d] Canceled by \"%s\".", jobid,
3573*5e7646d2SAndroid Build Coastguard Worker username);
3574*5e7646d2SAndroid Build Coastguard Worker
3575*5e7646d2SAndroid Build Coastguard Worker con->response->request.status.status_code = IPP_OK;
3576*5e7646d2SAndroid Build Coastguard Worker }
3577*5e7646d2SAndroid Build Coastguard Worker
3578*5e7646d2SAndroid Build Coastguard Worker
3579*5e7646d2SAndroid Build Coastguard Worker /*
3580*5e7646d2SAndroid Build Coastguard Worker * 'cancel_subscription()' - Cancel a subscription.
3581*5e7646d2SAndroid Build Coastguard Worker */
3582*5e7646d2SAndroid Build Coastguard Worker
3583*5e7646d2SAndroid Build Coastguard Worker static void
cancel_subscription(cupsd_client_t * con,int sub_id)3584*5e7646d2SAndroid Build Coastguard Worker cancel_subscription(
3585*5e7646d2SAndroid Build Coastguard Worker cupsd_client_t *con, /* I - Client connection */
3586*5e7646d2SAndroid Build Coastguard Worker int sub_id) /* I - Subscription ID */
3587*5e7646d2SAndroid Build Coastguard Worker {
3588*5e7646d2SAndroid Build Coastguard Worker http_status_t status; /* Policy status */
3589*5e7646d2SAndroid Build Coastguard Worker cupsd_subscription_t *sub; /* Subscription */
3590*5e7646d2SAndroid Build Coastguard Worker
3591*5e7646d2SAndroid Build Coastguard Worker
3592*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG2,
3593*5e7646d2SAndroid Build Coastguard Worker "cancel_subscription(con=%p[%d], sub_id=%d)",
3594*5e7646d2SAndroid Build Coastguard Worker con, con->number, sub_id);
3595*5e7646d2SAndroid Build Coastguard Worker
3596*5e7646d2SAndroid Build Coastguard Worker /*
3597*5e7646d2SAndroid Build Coastguard Worker * Is the subscription ID valid?
3598*5e7646d2SAndroid Build Coastguard Worker */
3599*5e7646d2SAndroid Build Coastguard Worker
3600*5e7646d2SAndroid Build Coastguard Worker if ((sub = cupsdFindSubscription(sub_id)) == NULL)
3601*5e7646d2SAndroid Build Coastguard Worker {
3602*5e7646d2SAndroid Build Coastguard Worker /*
3603*5e7646d2SAndroid Build Coastguard Worker * Bad subscription ID...
3604*5e7646d2SAndroid Build Coastguard Worker */
3605*5e7646d2SAndroid Build Coastguard Worker
3606*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_NOT_FOUND,
3607*5e7646d2SAndroid Build Coastguard Worker _("Subscription #%d does not exist."), sub_id);
3608*5e7646d2SAndroid Build Coastguard Worker return;
3609*5e7646d2SAndroid Build Coastguard Worker }
3610*5e7646d2SAndroid Build Coastguard Worker
3611*5e7646d2SAndroid Build Coastguard Worker /*
3612*5e7646d2SAndroid Build Coastguard Worker * Check policy...
3613*5e7646d2SAndroid Build Coastguard Worker */
3614*5e7646d2SAndroid Build Coastguard Worker
3615*5e7646d2SAndroid Build Coastguard Worker if ((status = cupsdCheckPolicy(sub->dest ? sub->dest->op_policy_ptr :
3616*5e7646d2SAndroid Build Coastguard Worker DefaultPolicyPtr,
3617*5e7646d2SAndroid Build Coastguard Worker con, sub->owner)) != HTTP_OK)
3618*5e7646d2SAndroid Build Coastguard Worker {
3619*5e7646d2SAndroid Build Coastguard Worker send_http_error(con, status, sub->dest);
3620*5e7646d2SAndroid Build Coastguard Worker return;
3621*5e7646d2SAndroid Build Coastguard Worker }
3622*5e7646d2SAndroid Build Coastguard Worker
3623*5e7646d2SAndroid Build Coastguard Worker /*
3624*5e7646d2SAndroid Build Coastguard Worker * Cancel the subscription...
3625*5e7646d2SAndroid Build Coastguard Worker */
3626*5e7646d2SAndroid Build Coastguard Worker
3627*5e7646d2SAndroid Build Coastguard Worker cupsdDeleteSubscription(sub, 1);
3628*5e7646d2SAndroid Build Coastguard Worker
3629*5e7646d2SAndroid Build Coastguard Worker con->response->request.status.status_code = IPP_OK;
3630*5e7646d2SAndroid Build Coastguard Worker }
3631*5e7646d2SAndroid Build Coastguard Worker
3632*5e7646d2SAndroid Build Coastguard Worker
3633*5e7646d2SAndroid Build Coastguard Worker /*
3634*5e7646d2SAndroid Build Coastguard Worker * 'check_rss_recipient()' - Check that we do not have a duplicate RSS feed URI.
3635*5e7646d2SAndroid Build Coastguard Worker */
3636*5e7646d2SAndroid Build Coastguard Worker
3637*5e7646d2SAndroid Build Coastguard Worker static int /* O - 1 if OK, 0 if not */
check_rss_recipient(const char * recipient)3638*5e7646d2SAndroid Build Coastguard Worker check_rss_recipient(
3639*5e7646d2SAndroid Build Coastguard Worker const char *recipient) /* I - Recipient URI */
3640*5e7646d2SAndroid Build Coastguard Worker {
3641*5e7646d2SAndroid Build Coastguard Worker cupsd_subscription_t *sub; /* Current subscription */
3642*5e7646d2SAndroid Build Coastguard Worker
3643*5e7646d2SAndroid Build Coastguard Worker
3644*5e7646d2SAndroid Build Coastguard Worker for (sub = (cupsd_subscription_t *)cupsArrayFirst(Subscriptions);
3645*5e7646d2SAndroid Build Coastguard Worker sub;
3646*5e7646d2SAndroid Build Coastguard Worker sub = (cupsd_subscription_t *)cupsArrayNext(Subscriptions))
3647*5e7646d2SAndroid Build Coastguard Worker if (sub->recipient)
3648*5e7646d2SAndroid Build Coastguard Worker {
3649*5e7646d2SAndroid Build Coastguard Worker /*
3650*5e7646d2SAndroid Build Coastguard Worker * Compare the URIs up to the first ?...
3651*5e7646d2SAndroid Build Coastguard Worker */
3652*5e7646d2SAndroid Build Coastguard Worker
3653*5e7646d2SAndroid Build Coastguard Worker const char *r1, *r2;
3654*5e7646d2SAndroid Build Coastguard Worker
3655*5e7646d2SAndroid Build Coastguard Worker for (r1 = recipient, r2 = sub->recipient;
3656*5e7646d2SAndroid Build Coastguard Worker *r1 == *r2 && *r1 && *r1 != '?' && *r2 && *r2 != '?';
3657*5e7646d2SAndroid Build Coastguard Worker r1 ++, r2 ++);
3658*5e7646d2SAndroid Build Coastguard Worker
3659*5e7646d2SAndroid Build Coastguard Worker if (*r1 == *r2)
3660*5e7646d2SAndroid Build Coastguard Worker return (0);
3661*5e7646d2SAndroid Build Coastguard Worker }
3662*5e7646d2SAndroid Build Coastguard Worker
3663*5e7646d2SAndroid Build Coastguard Worker return (1);
3664*5e7646d2SAndroid Build Coastguard Worker }
3665*5e7646d2SAndroid Build Coastguard Worker
3666*5e7646d2SAndroid Build Coastguard Worker
3667*5e7646d2SAndroid Build Coastguard Worker /*
3668*5e7646d2SAndroid Build Coastguard Worker * 'check_quotas()' - Check quotas for a printer and user.
3669*5e7646d2SAndroid Build Coastguard Worker */
3670*5e7646d2SAndroid Build Coastguard Worker
3671*5e7646d2SAndroid Build Coastguard Worker static int /* O - 1 if OK, 0 if forbidden,
3672*5e7646d2SAndroid Build Coastguard Worker -1 if limit reached */
check_quotas(cupsd_client_t * con,cupsd_printer_t * p)3673*5e7646d2SAndroid Build Coastguard Worker check_quotas(cupsd_client_t *con, /* I - Client connection */
3674*5e7646d2SAndroid Build Coastguard Worker cupsd_printer_t *p) /* I - Printer or class */
3675*5e7646d2SAndroid Build Coastguard Worker {
3676*5e7646d2SAndroid Build Coastguard Worker char username[33], /* Username */
3677*5e7646d2SAndroid Build Coastguard Worker *name; /* Current user name */
3678*5e7646d2SAndroid Build Coastguard Worker cupsd_quota_t *q; /* Quota data */
3679*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_MBR_UID_TO_UUID
3680*5e7646d2SAndroid Build Coastguard Worker /*
3681*5e7646d2SAndroid Build Coastguard Worker * Use Apple membership APIs which require that all names represent
3682*5e7646d2SAndroid Build Coastguard Worker * valid user account or group records accessible by the server.
3683*5e7646d2SAndroid Build Coastguard Worker */
3684*5e7646d2SAndroid Build Coastguard Worker
3685*5e7646d2SAndroid Build Coastguard Worker uuid_t usr_uuid; /* UUID for job requesting user */
3686*5e7646d2SAndroid Build Coastguard Worker uuid_t usr2_uuid; /* UUID for ACL user name entry */
3687*5e7646d2SAndroid Build Coastguard Worker uuid_t grp_uuid; /* UUID for ACL group name entry */
3688*5e7646d2SAndroid Build Coastguard Worker int mbr_err; /* Error from membership function */
3689*5e7646d2SAndroid Build Coastguard Worker int is_member; /* Is this user a member? */
3690*5e7646d2SAndroid Build Coastguard Worker #else
3691*5e7646d2SAndroid Build Coastguard Worker /*
3692*5e7646d2SAndroid Build Coastguard Worker * Use standard POSIX APIs for checking users and groups...
3693*5e7646d2SAndroid Build Coastguard Worker */
3694*5e7646d2SAndroid Build Coastguard Worker
3695*5e7646d2SAndroid Build Coastguard Worker struct passwd *pw; /* User password data */
3696*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_MBR_UID_TO_UUID */
3697*5e7646d2SAndroid Build Coastguard Worker
3698*5e7646d2SAndroid Build Coastguard Worker
3699*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG2, "check_quotas(%p[%d], %p[%s])",
3700*5e7646d2SAndroid Build Coastguard Worker con, con->number, p, p->name);
3701*5e7646d2SAndroid Build Coastguard Worker
3702*5e7646d2SAndroid Build Coastguard Worker /*
3703*5e7646d2SAndroid Build Coastguard Worker * Figure out who is printing...
3704*5e7646d2SAndroid Build Coastguard Worker */
3705*5e7646d2SAndroid Build Coastguard Worker
3706*5e7646d2SAndroid Build Coastguard Worker strlcpy(username, get_username(con), sizeof(username));
3707*5e7646d2SAndroid Build Coastguard Worker
3708*5e7646d2SAndroid Build Coastguard Worker if ((name = strchr(username, '@')) != NULL)
3709*5e7646d2SAndroid Build Coastguard Worker *name = '\0'; /* Strip @REALM */
3710*5e7646d2SAndroid Build Coastguard Worker
3711*5e7646d2SAndroid Build Coastguard Worker /*
3712*5e7646d2SAndroid Build Coastguard Worker * Check global active job limits for printers and users...
3713*5e7646d2SAndroid Build Coastguard Worker */
3714*5e7646d2SAndroid Build Coastguard Worker
3715*5e7646d2SAndroid Build Coastguard Worker if (MaxJobsPerPrinter)
3716*5e7646d2SAndroid Build Coastguard Worker {
3717*5e7646d2SAndroid Build Coastguard Worker /*
3718*5e7646d2SAndroid Build Coastguard Worker * Check if there are too many pending jobs on this printer...
3719*5e7646d2SAndroid Build Coastguard Worker */
3720*5e7646d2SAndroid Build Coastguard Worker
3721*5e7646d2SAndroid Build Coastguard Worker if (cupsdGetPrinterJobCount(p->name) >= MaxJobsPerPrinter)
3722*5e7646d2SAndroid Build Coastguard Worker {
3723*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_INFO, "Too many jobs for printer \"%s\"...",
3724*5e7646d2SAndroid Build Coastguard Worker p->name);
3725*5e7646d2SAndroid Build Coastguard Worker return (-1);
3726*5e7646d2SAndroid Build Coastguard Worker }
3727*5e7646d2SAndroid Build Coastguard Worker }
3728*5e7646d2SAndroid Build Coastguard Worker
3729*5e7646d2SAndroid Build Coastguard Worker if (MaxJobsPerUser)
3730*5e7646d2SAndroid Build Coastguard Worker {
3731*5e7646d2SAndroid Build Coastguard Worker /*
3732*5e7646d2SAndroid Build Coastguard Worker * Check if there are too many pending jobs for this user...
3733*5e7646d2SAndroid Build Coastguard Worker */
3734*5e7646d2SAndroid Build Coastguard Worker
3735*5e7646d2SAndroid Build Coastguard Worker if (cupsdGetUserJobCount(username) >= MaxJobsPerUser)
3736*5e7646d2SAndroid Build Coastguard Worker {
3737*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_INFO, "Too many jobs for user \"%s\"...",
3738*5e7646d2SAndroid Build Coastguard Worker username);
3739*5e7646d2SAndroid Build Coastguard Worker return (-1);
3740*5e7646d2SAndroid Build Coastguard Worker }
3741*5e7646d2SAndroid Build Coastguard Worker }
3742*5e7646d2SAndroid Build Coastguard Worker
3743*5e7646d2SAndroid Build Coastguard Worker /*
3744*5e7646d2SAndroid Build Coastguard Worker * Check against users...
3745*5e7646d2SAndroid Build Coastguard Worker */
3746*5e7646d2SAndroid Build Coastguard Worker
3747*5e7646d2SAndroid Build Coastguard Worker if (cupsArrayCount(p->users) == 0 && p->k_limit == 0 && p->page_limit == 0)
3748*5e7646d2SAndroid Build Coastguard Worker return (1);
3749*5e7646d2SAndroid Build Coastguard Worker
3750*5e7646d2SAndroid Build Coastguard Worker if (cupsArrayCount(p->users))
3751*5e7646d2SAndroid Build Coastguard Worker {
3752*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_MBR_UID_TO_UUID
3753*5e7646d2SAndroid Build Coastguard Worker /*
3754*5e7646d2SAndroid Build Coastguard Worker * Get UUID for job requesting user...
3755*5e7646d2SAndroid Build Coastguard Worker */
3756*5e7646d2SAndroid Build Coastguard Worker
3757*5e7646d2SAndroid Build Coastguard Worker if (mbr_user_name_to_uuid((char *)username, usr_uuid))
3758*5e7646d2SAndroid Build Coastguard Worker {
3759*5e7646d2SAndroid Build Coastguard Worker /*
3760*5e7646d2SAndroid Build Coastguard Worker * Unknown user...
3761*5e7646d2SAndroid Build Coastguard Worker */
3762*5e7646d2SAndroid Build Coastguard Worker
3763*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG,
3764*5e7646d2SAndroid Build Coastguard Worker "check_quotas: UUID lookup failed for user \"%s\"",
3765*5e7646d2SAndroid Build Coastguard Worker username);
3766*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_INFO,
3767*5e7646d2SAndroid Build Coastguard Worker "Denying user \"%s\" access to printer \"%s\" "
3768*5e7646d2SAndroid Build Coastguard Worker "(unknown user)...",
3769*5e7646d2SAndroid Build Coastguard Worker username, p->name);
3770*5e7646d2SAndroid Build Coastguard Worker return (0);
3771*5e7646d2SAndroid Build Coastguard Worker }
3772*5e7646d2SAndroid Build Coastguard Worker #else
3773*5e7646d2SAndroid Build Coastguard Worker /*
3774*5e7646d2SAndroid Build Coastguard Worker * Get UID and GID of requesting user...
3775*5e7646d2SAndroid Build Coastguard Worker */
3776*5e7646d2SAndroid Build Coastguard Worker
3777*5e7646d2SAndroid Build Coastguard Worker pw = getpwnam(username);
3778*5e7646d2SAndroid Build Coastguard Worker endpwent();
3779*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_MBR_UID_TO_UUID */
3780*5e7646d2SAndroid Build Coastguard Worker
3781*5e7646d2SAndroid Build Coastguard Worker for (name = (char *)cupsArrayFirst(p->users);
3782*5e7646d2SAndroid Build Coastguard Worker name;
3783*5e7646d2SAndroid Build Coastguard Worker name = (char *)cupsArrayNext(p->users))
3784*5e7646d2SAndroid Build Coastguard Worker if (name[0] == '@')
3785*5e7646d2SAndroid Build Coastguard Worker {
3786*5e7646d2SAndroid Build Coastguard Worker /*
3787*5e7646d2SAndroid Build Coastguard Worker * Check group membership...
3788*5e7646d2SAndroid Build Coastguard Worker */
3789*5e7646d2SAndroid Build Coastguard Worker
3790*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_MBR_UID_TO_UUID
3791*5e7646d2SAndroid Build Coastguard Worker if (name[1] == '#')
3792*5e7646d2SAndroid Build Coastguard Worker {
3793*5e7646d2SAndroid Build Coastguard Worker if (uuid_parse(name + 2, grp_uuid))
3794*5e7646d2SAndroid Build Coastguard Worker uuid_clear(grp_uuid);
3795*5e7646d2SAndroid Build Coastguard Worker }
3796*5e7646d2SAndroid Build Coastguard Worker else if ((mbr_err = mbr_group_name_to_uuid(name + 1, grp_uuid)) != 0)
3797*5e7646d2SAndroid Build Coastguard Worker {
3798*5e7646d2SAndroid Build Coastguard Worker /*
3799*5e7646d2SAndroid Build Coastguard Worker * Invalid ACL entries are ignored for matching; just record a
3800*5e7646d2SAndroid Build Coastguard Worker * warning in the log...
3801*5e7646d2SAndroid Build Coastguard Worker */
3802*5e7646d2SAndroid Build Coastguard Worker
3803*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG,
3804*5e7646d2SAndroid Build Coastguard Worker "check_quotas: UUID lookup failed for ACL entry "
3805*5e7646d2SAndroid Build Coastguard Worker "\"%s\" (err=%d)", name, mbr_err);
3806*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_WARN,
3807*5e7646d2SAndroid Build Coastguard Worker "Access control entry \"%s\" not a valid group name; "
3808*5e7646d2SAndroid Build Coastguard Worker "entry ignored", name);
3809*5e7646d2SAndroid Build Coastguard Worker }
3810*5e7646d2SAndroid Build Coastguard Worker
3811*5e7646d2SAndroid Build Coastguard Worker if ((mbr_err = mbr_check_membership(usr_uuid, grp_uuid,
3812*5e7646d2SAndroid Build Coastguard Worker &is_member)) != 0)
3813*5e7646d2SAndroid Build Coastguard Worker {
3814*5e7646d2SAndroid Build Coastguard Worker /*
3815*5e7646d2SAndroid Build Coastguard Worker * At this point, there should be no errors, but check anyways...
3816*5e7646d2SAndroid Build Coastguard Worker */
3817*5e7646d2SAndroid Build Coastguard Worker
3818*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG,
3819*5e7646d2SAndroid Build Coastguard Worker "check_quotas: group \"%s\" membership check "
3820*5e7646d2SAndroid Build Coastguard Worker "failed (err=%d)", name + 1, mbr_err);
3821*5e7646d2SAndroid Build Coastguard Worker is_member = 0;
3822*5e7646d2SAndroid Build Coastguard Worker }
3823*5e7646d2SAndroid Build Coastguard Worker
3824*5e7646d2SAndroid Build Coastguard Worker /*
3825*5e7646d2SAndroid Build Coastguard Worker * Stop if we found a match...
3826*5e7646d2SAndroid Build Coastguard Worker */
3827*5e7646d2SAndroid Build Coastguard Worker
3828*5e7646d2SAndroid Build Coastguard Worker if (is_member)
3829*5e7646d2SAndroid Build Coastguard Worker break;
3830*5e7646d2SAndroid Build Coastguard Worker
3831*5e7646d2SAndroid Build Coastguard Worker #else
3832*5e7646d2SAndroid Build Coastguard Worker if (cupsdCheckGroup(username, pw, name + 1))
3833*5e7646d2SAndroid Build Coastguard Worker break;
3834*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_MBR_UID_TO_UUID */
3835*5e7646d2SAndroid Build Coastguard Worker }
3836*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_MBR_UID_TO_UUID
3837*5e7646d2SAndroid Build Coastguard Worker else
3838*5e7646d2SAndroid Build Coastguard Worker {
3839*5e7646d2SAndroid Build Coastguard Worker if (name[0] == '#')
3840*5e7646d2SAndroid Build Coastguard Worker {
3841*5e7646d2SAndroid Build Coastguard Worker if (uuid_parse(name + 1, usr2_uuid))
3842*5e7646d2SAndroid Build Coastguard Worker uuid_clear(usr2_uuid);
3843*5e7646d2SAndroid Build Coastguard Worker }
3844*5e7646d2SAndroid Build Coastguard Worker else if ((mbr_err = mbr_user_name_to_uuid(name, usr2_uuid)) != 0)
3845*5e7646d2SAndroid Build Coastguard Worker {
3846*5e7646d2SAndroid Build Coastguard Worker /*
3847*5e7646d2SAndroid Build Coastguard Worker * Invalid ACL entries are ignored for matching; just record a
3848*5e7646d2SAndroid Build Coastguard Worker * warning in the log...
3849*5e7646d2SAndroid Build Coastguard Worker */
3850*5e7646d2SAndroid Build Coastguard Worker
3851*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG,
3852*5e7646d2SAndroid Build Coastguard Worker "check_quotas: UUID lookup failed for ACL entry "
3853*5e7646d2SAndroid Build Coastguard Worker "\"%s\" (err=%d)", name, mbr_err);
3854*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_WARN,
3855*5e7646d2SAndroid Build Coastguard Worker "Access control entry \"%s\" not a valid user name; "
3856*5e7646d2SAndroid Build Coastguard Worker "entry ignored", name);
3857*5e7646d2SAndroid Build Coastguard Worker }
3858*5e7646d2SAndroid Build Coastguard Worker
3859*5e7646d2SAndroid Build Coastguard Worker if (!uuid_compare(usr_uuid, usr2_uuid))
3860*5e7646d2SAndroid Build Coastguard Worker break;
3861*5e7646d2SAndroid Build Coastguard Worker }
3862*5e7646d2SAndroid Build Coastguard Worker #else
3863*5e7646d2SAndroid Build Coastguard Worker else if (!_cups_strcasecmp(username, name))
3864*5e7646d2SAndroid Build Coastguard Worker break;
3865*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_MBR_UID_TO_UUID */
3866*5e7646d2SAndroid Build Coastguard Worker
3867*5e7646d2SAndroid Build Coastguard Worker if ((name != NULL) == p->deny_users)
3868*5e7646d2SAndroid Build Coastguard Worker {
3869*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_INFO,
3870*5e7646d2SAndroid Build Coastguard Worker "Denying user \"%s\" access to printer \"%s\"...",
3871*5e7646d2SAndroid Build Coastguard Worker username, p->name);
3872*5e7646d2SAndroid Build Coastguard Worker return (0);
3873*5e7646d2SAndroid Build Coastguard Worker }
3874*5e7646d2SAndroid Build Coastguard Worker }
3875*5e7646d2SAndroid Build Coastguard Worker
3876*5e7646d2SAndroid Build Coastguard Worker /*
3877*5e7646d2SAndroid Build Coastguard Worker * Check quotas...
3878*5e7646d2SAndroid Build Coastguard Worker */
3879*5e7646d2SAndroid Build Coastguard Worker
3880*5e7646d2SAndroid Build Coastguard Worker if (p->k_limit || p->page_limit)
3881*5e7646d2SAndroid Build Coastguard Worker {
3882*5e7646d2SAndroid Build Coastguard Worker if ((q = cupsdUpdateQuota(p, username, 0, 0)) == NULL)
3883*5e7646d2SAndroid Build Coastguard Worker {
3884*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_ERROR,
3885*5e7646d2SAndroid Build Coastguard Worker "Unable to allocate quota data for user \"%s\"",
3886*5e7646d2SAndroid Build Coastguard Worker username);
3887*5e7646d2SAndroid Build Coastguard Worker return (-1);
3888*5e7646d2SAndroid Build Coastguard Worker }
3889*5e7646d2SAndroid Build Coastguard Worker
3890*5e7646d2SAndroid Build Coastguard Worker if ((q->k_count >= p->k_limit && p->k_limit) ||
3891*5e7646d2SAndroid Build Coastguard Worker (q->page_count >= p->page_limit && p->page_limit))
3892*5e7646d2SAndroid Build Coastguard Worker {
3893*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_INFO, "User \"%s\" is over the quota limit...",
3894*5e7646d2SAndroid Build Coastguard Worker username);
3895*5e7646d2SAndroid Build Coastguard Worker return (-1);
3896*5e7646d2SAndroid Build Coastguard Worker }
3897*5e7646d2SAndroid Build Coastguard Worker }
3898*5e7646d2SAndroid Build Coastguard Worker
3899*5e7646d2SAndroid Build Coastguard Worker /*
3900*5e7646d2SAndroid Build Coastguard Worker * If we have gotten this far, we're done!
3901*5e7646d2SAndroid Build Coastguard Worker */
3902*5e7646d2SAndroid Build Coastguard Worker
3903*5e7646d2SAndroid Build Coastguard Worker return (1);
3904*5e7646d2SAndroid Build Coastguard Worker }
3905*5e7646d2SAndroid Build Coastguard Worker
3906*5e7646d2SAndroid Build Coastguard Worker
3907*5e7646d2SAndroid Build Coastguard Worker /*
3908*5e7646d2SAndroid Build Coastguard Worker * 'close_job()' - Close a multi-file job.
3909*5e7646d2SAndroid Build Coastguard Worker */
3910*5e7646d2SAndroid Build Coastguard Worker
3911*5e7646d2SAndroid Build Coastguard Worker static void
close_job(cupsd_client_t * con,ipp_attribute_t * uri)3912*5e7646d2SAndroid Build Coastguard Worker close_job(cupsd_client_t *con, /* I - Client connection */
3913*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *uri) /* I - Printer URI */
3914*5e7646d2SAndroid Build Coastguard Worker {
3915*5e7646d2SAndroid Build Coastguard Worker cupsd_job_t *job; /* Job */
3916*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *attr; /* Attribute */
3917*5e7646d2SAndroid Build Coastguard Worker char job_uri[HTTP_MAX_URI],
3918*5e7646d2SAndroid Build Coastguard Worker /* Job URI */
3919*5e7646d2SAndroid Build Coastguard Worker username[256]; /* User name */
3920*5e7646d2SAndroid Build Coastguard Worker
3921*5e7646d2SAndroid Build Coastguard Worker
3922*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG2, "close_job(%p[%d], %s)", con,
3923*5e7646d2SAndroid Build Coastguard Worker con->number, uri->values[0].string.text);
3924*5e7646d2SAndroid Build Coastguard Worker
3925*5e7646d2SAndroid Build Coastguard Worker /*
3926*5e7646d2SAndroid Build Coastguard Worker * See if we have a job URI or a printer URI...
3927*5e7646d2SAndroid Build Coastguard Worker */
3928*5e7646d2SAndroid Build Coastguard Worker
3929*5e7646d2SAndroid Build Coastguard Worker if (strcmp(uri->name, "printer-uri"))
3930*5e7646d2SAndroid Build Coastguard Worker {
3931*5e7646d2SAndroid Build Coastguard Worker /*
3932*5e7646d2SAndroid Build Coastguard Worker * job-uri is not supported by Close-Job!
3933*5e7646d2SAndroid Build Coastguard Worker */
3934*5e7646d2SAndroid Build Coastguard Worker
3935*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_BAD_REQUEST,
3936*5e7646d2SAndroid Build Coastguard Worker _("Close-Job doesn't support the job-uri attribute."));
3937*5e7646d2SAndroid Build Coastguard Worker return;
3938*5e7646d2SAndroid Build Coastguard Worker }
3939*5e7646d2SAndroid Build Coastguard Worker
3940*5e7646d2SAndroid Build Coastguard Worker /*
3941*5e7646d2SAndroid Build Coastguard Worker * Got a printer URI; see if we also have a job-id attribute...
3942*5e7646d2SAndroid Build Coastguard Worker */
3943*5e7646d2SAndroid Build Coastguard Worker
3944*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippFindAttribute(con->request, "job-id",
3945*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_INTEGER)) == NULL)
3946*5e7646d2SAndroid Build Coastguard Worker {
3947*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_BAD_REQUEST,
3948*5e7646d2SAndroid Build Coastguard Worker _("Got a printer-uri attribute but no job-id."));
3949*5e7646d2SAndroid Build Coastguard Worker return;
3950*5e7646d2SAndroid Build Coastguard Worker }
3951*5e7646d2SAndroid Build Coastguard Worker
3952*5e7646d2SAndroid Build Coastguard Worker if ((job = cupsdFindJob(attr->values[0].integer)) == NULL)
3953*5e7646d2SAndroid Build Coastguard Worker {
3954*5e7646d2SAndroid Build Coastguard Worker /*
3955*5e7646d2SAndroid Build Coastguard Worker * Nope - return a "not found" error...
3956*5e7646d2SAndroid Build Coastguard Worker */
3957*5e7646d2SAndroid Build Coastguard Worker
3958*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_NOT_FOUND, _("Job #%d does not exist."),
3959*5e7646d2SAndroid Build Coastguard Worker attr->values[0].integer);
3960*5e7646d2SAndroid Build Coastguard Worker return;
3961*5e7646d2SAndroid Build Coastguard Worker }
3962*5e7646d2SAndroid Build Coastguard Worker
3963*5e7646d2SAndroid Build Coastguard Worker /*
3964*5e7646d2SAndroid Build Coastguard Worker * See if the job is owned by the requesting user...
3965*5e7646d2SAndroid Build Coastguard Worker */
3966*5e7646d2SAndroid Build Coastguard Worker
3967*5e7646d2SAndroid Build Coastguard Worker if (!validate_user(job, con, job->username, username, sizeof(username)))
3968*5e7646d2SAndroid Build Coastguard Worker {
3969*5e7646d2SAndroid Build Coastguard Worker send_http_error(con, con->username[0] ? HTTP_FORBIDDEN : HTTP_UNAUTHORIZED,
3970*5e7646d2SAndroid Build Coastguard Worker cupsdFindDest(job->dest));
3971*5e7646d2SAndroid Build Coastguard Worker return;
3972*5e7646d2SAndroid Build Coastguard Worker }
3973*5e7646d2SAndroid Build Coastguard Worker
3974*5e7646d2SAndroid Build Coastguard Worker /*
3975*5e7646d2SAndroid Build Coastguard Worker * Add any ending sheet...
3976*5e7646d2SAndroid Build Coastguard Worker */
3977*5e7646d2SAndroid Build Coastguard Worker
3978*5e7646d2SAndroid Build Coastguard Worker if (cupsdTimeoutJob(job))
3979*5e7646d2SAndroid Build Coastguard Worker return;
3980*5e7646d2SAndroid Build Coastguard Worker
3981*5e7646d2SAndroid Build Coastguard Worker if (job->state_value == IPP_JOB_STOPPED)
3982*5e7646d2SAndroid Build Coastguard Worker {
3983*5e7646d2SAndroid Build Coastguard Worker job->state->values[0].integer = IPP_JOB_PENDING;
3984*5e7646d2SAndroid Build Coastguard Worker job->state_value = IPP_JOB_PENDING;
3985*5e7646d2SAndroid Build Coastguard Worker }
3986*5e7646d2SAndroid Build Coastguard Worker else if (job->state_value == IPP_JOB_HELD)
3987*5e7646d2SAndroid Build Coastguard Worker {
3988*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippFindAttribute(job->attrs, "job-hold-until",
3989*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_KEYWORD)) == NULL)
3990*5e7646d2SAndroid Build Coastguard Worker attr = ippFindAttribute(job->attrs, "job-hold-until", IPP_TAG_NAME);
3991*5e7646d2SAndroid Build Coastguard Worker
3992*5e7646d2SAndroid Build Coastguard Worker if (!attr || !strcmp(attr->values[0].string.text, "no-hold"))
3993*5e7646d2SAndroid Build Coastguard Worker {
3994*5e7646d2SAndroid Build Coastguard Worker job->state->values[0].integer = IPP_JOB_PENDING;
3995*5e7646d2SAndroid Build Coastguard Worker job->state_value = IPP_JOB_PENDING;
3996*5e7646d2SAndroid Build Coastguard Worker }
3997*5e7646d2SAndroid Build Coastguard Worker }
3998*5e7646d2SAndroid Build Coastguard Worker
3999*5e7646d2SAndroid Build Coastguard Worker job->dirty = 1;
4000*5e7646d2SAndroid Build Coastguard Worker cupsdMarkDirty(CUPSD_DIRTY_JOBS);
4001*5e7646d2SAndroid Build Coastguard Worker
4002*5e7646d2SAndroid Build Coastguard Worker /*
4003*5e7646d2SAndroid Build Coastguard Worker * Fill in the response info...
4004*5e7646d2SAndroid Build Coastguard Worker */
4005*5e7646d2SAndroid Build Coastguard Worker
4006*5e7646d2SAndroid Build Coastguard Worker httpAssembleURIf(HTTP_URI_CODING_ALL, job_uri, sizeof(job_uri), "ipp", NULL,
4007*5e7646d2SAndroid Build Coastguard Worker con->clientname, con->clientport, "/jobs/%d", job->id);
4008*5e7646d2SAndroid Build Coastguard Worker ippAddString(con->response, IPP_TAG_JOB, IPP_TAG_URI, "job-uri", NULL,
4009*5e7646d2SAndroid Build Coastguard Worker job_uri);
4010*5e7646d2SAndroid Build Coastguard Worker
4011*5e7646d2SAndroid Build Coastguard Worker ippAddInteger(con->response, IPP_TAG_JOB, IPP_TAG_INTEGER, "job-id", job->id);
4012*5e7646d2SAndroid Build Coastguard Worker
4013*5e7646d2SAndroid Build Coastguard Worker ippAddInteger(con->response, IPP_TAG_JOB, IPP_TAG_ENUM, "job-state", (int)job->state_value);
4014*5e7646d2SAndroid Build Coastguard Worker
4015*5e7646d2SAndroid Build Coastguard Worker con->response->request.status.status_code = IPP_OK;
4016*5e7646d2SAndroid Build Coastguard Worker
4017*5e7646d2SAndroid Build Coastguard Worker /*
4018*5e7646d2SAndroid Build Coastguard Worker * Start the job if necessary...
4019*5e7646d2SAndroid Build Coastguard Worker */
4020*5e7646d2SAndroid Build Coastguard Worker
4021*5e7646d2SAndroid Build Coastguard Worker cupsdCheckJobs();
4022*5e7646d2SAndroid Build Coastguard Worker }
4023*5e7646d2SAndroid Build Coastguard Worker
4024*5e7646d2SAndroid Build Coastguard Worker
4025*5e7646d2SAndroid Build Coastguard Worker /*
4026*5e7646d2SAndroid Build Coastguard Worker * 'copy_attrs()' - Copy attributes from one request to another.
4027*5e7646d2SAndroid Build Coastguard Worker */
4028*5e7646d2SAndroid Build Coastguard Worker
4029*5e7646d2SAndroid Build Coastguard Worker static void
copy_attrs(ipp_t * to,ipp_t * from,cups_array_t * ra,ipp_tag_t group,int quickcopy,cups_array_t * exclude)4030*5e7646d2SAndroid Build Coastguard Worker copy_attrs(ipp_t *to, /* I - Destination request */
4031*5e7646d2SAndroid Build Coastguard Worker ipp_t *from, /* I - Source request */
4032*5e7646d2SAndroid Build Coastguard Worker cups_array_t *ra, /* I - Requested attributes */
4033*5e7646d2SAndroid Build Coastguard Worker ipp_tag_t group, /* I - Group to copy */
4034*5e7646d2SAndroid Build Coastguard Worker int quickcopy, /* I - Do a quick copy? */
4035*5e7646d2SAndroid Build Coastguard Worker cups_array_t *exclude) /* I - Attributes to exclude? */
4036*5e7646d2SAndroid Build Coastguard Worker {
4037*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *fromattr; /* Source attribute */
4038*5e7646d2SAndroid Build Coastguard Worker
4039*5e7646d2SAndroid Build Coastguard Worker
4040*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG2,
4041*5e7646d2SAndroid Build Coastguard Worker "copy_attrs(to=%p, from=%p, ra=%p, group=%x, quickcopy=%d)",
4042*5e7646d2SAndroid Build Coastguard Worker to, from, ra, group, quickcopy);
4043*5e7646d2SAndroid Build Coastguard Worker
4044*5e7646d2SAndroid Build Coastguard Worker if (!to || !from)
4045*5e7646d2SAndroid Build Coastguard Worker return;
4046*5e7646d2SAndroid Build Coastguard Worker
4047*5e7646d2SAndroid Build Coastguard Worker for (fromattr = from->attrs; fromattr; fromattr = fromattr->next)
4048*5e7646d2SAndroid Build Coastguard Worker {
4049*5e7646d2SAndroid Build Coastguard Worker /*
4050*5e7646d2SAndroid Build Coastguard Worker * Filter attributes as needed...
4051*5e7646d2SAndroid Build Coastguard Worker */
4052*5e7646d2SAndroid Build Coastguard Worker
4053*5e7646d2SAndroid Build Coastguard Worker if ((group != IPP_TAG_ZERO && fromattr->group_tag != group &&
4054*5e7646d2SAndroid Build Coastguard Worker fromattr->group_tag != IPP_TAG_ZERO) || !fromattr->name)
4055*5e7646d2SAndroid Build Coastguard Worker continue;
4056*5e7646d2SAndroid Build Coastguard Worker
4057*5e7646d2SAndroid Build Coastguard Worker if (!strcmp(fromattr->name, "document-password") ||
4058*5e7646d2SAndroid Build Coastguard Worker !strcmp(fromattr->name, "job-authorization-uri") ||
4059*5e7646d2SAndroid Build Coastguard Worker !strcmp(fromattr->name, "job-password") ||
4060*5e7646d2SAndroid Build Coastguard Worker !strcmp(fromattr->name, "job-password-encryption") ||
4061*5e7646d2SAndroid Build Coastguard Worker !strcmp(fromattr->name, "job-printer-uri"))
4062*5e7646d2SAndroid Build Coastguard Worker continue;
4063*5e7646d2SAndroid Build Coastguard Worker
4064*5e7646d2SAndroid Build Coastguard Worker if (exclude &&
4065*5e7646d2SAndroid Build Coastguard Worker (cupsArrayFind(exclude, fromattr->name) ||
4066*5e7646d2SAndroid Build Coastguard Worker cupsArrayFind(exclude, "all")))
4067*5e7646d2SAndroid Build Coastguard Worker {
4068*5e7646d2SAndroid Build Coastguard Worker /*
4069*5e7646d2SAndroid Build Coastguard Worker * We need to exclude this attribute for security reasons; we require the
4070*5e7646d2SAndroid Build Coastguard Worker * job-id attribute regardless of the security settings for IPP
4071*5e7646d2SAndroid Build Coastguard Worker * conformance.
4072*5e7646d2SAndroid Build Coastguard Worker *
4073*5e7646d2SAndroid Build Coastguard Worker * The job-printer-uri attribute is handled by copy_job_attrs().
4074*5e7646d2SAndroid Build Coastguard Worker *
4075*5e7646d2SAndroid Build Coastguard Worker * Subscription attribute security is handled by copy_subscription_attrs().
4076*5e7646d2SAndroid Build Coastguard Worker */
4077*5e7646d2SAndroid Build Coastguard Worker
4078*5e7646d2SAndroid Build Coastguard Worker if (strcmp(fromattr->name, "job-id"))
4079*5e7646d2SAndroid Build Coastguard Worker continue;
4080*5e7646d2SAndroid Build Coastguard Worker }
4081*5e7646d2SAndroid Build Coastguard Worker
4082*5e7646d2SAndroid Build Coastguard Worker if (!ra || cupsArrayFind(ra, fromattr->name))
4083*5e7646d2SAndroid Build Coastguard Worker {
4084*5e7646d2SAndroid Build Coastguard Worker /*
4085*5e7646d2SAndroid Build Coastguard Worker * Don't send collection attributes by default to IPP/1.x clients
4086*5e7646d2SAndroid Build Coastguard Worker * since many do not support collections. Also don't send
4087*5e7646d2SAndroid Build Coastguard Worker * media-col-database unless specifically requested by the client.
4088*5e7646d2SAndroid Build Coastguard Worker */
4089*5e7646d2SAndroid Build Coastguard Worker
4090*5e7646d2SAndroid Build Coastguard Worker if (fromattr->value_tag == IPP_TAG_BEGIN_COLLECTION &&
4091*5e7646d2SAndroid Build Coastguard Worker !ra &&
4092*5e7646d2SAndroid Build Coastguard Worker (to->request.status.version[0] == 1 ||
4093*5e7646d2SAndroid Build Coastguard Worker !strcmp(fromattr->name, "media-col-database")))
4094*5e7646d2SAndroid Build Coastguard Worker continue;
4095*5e7646d2SAndroid Build Coastguard Worker
4096*5e7646d2SAndroid Build Coastguard Worker ippCopyAttribute(to, fromattr, quickcopy);
4097*5e7646d2SAndroid Build Coastguard Worker }
4098*5e7646d2SAndroid Build Coastguard Worker }
4099*5e7646d2SAndroid Build Coastguard Worker }
4100*5e7646d2SAndroid Build Coastguard Worker
4101*5e7646d2SAndroid Build Coastguard Worker
4102*5e7646d2SAndroid Build Coastguard Worker /*
4103*5e7646d2SAndroid Build Coastguard Worker * 'copy_banner()' - Copy a banner file to the requests directory for the
4104*5e7646d2SAndroid Build Coastguard Worker * specified job.
4105*5e7646d2SAndroid Build Coastguard Worker */
4106*5e7646d2SAndroid Build Coastguard Worker
4107*5e7646d2SAndroid Build Coastguard Worker static int /* O - Size of banner file in kbytes */
copy_banner(cupsd_client_t * con,cupsd_job_t * job,const char * name)4108*5e7646d2SAndroid Build Coastguard Worker copy_banner(cupsd_client_t *con, /* I - Client connection */
4109*5e7646d2SAndroid Build Coastguard Worker cupsd_job_t *job, /* I - Job information */
4110*5e7646d2SAndroid Build Coastguard Worker const char *name) /* I - Name of banner */
4111*5e7646d2SAndroid Build Coastguard Worker {
4112*5e7646d2SAndroid Build Coastguard Worker int i; /* Looping var */
4113*5e7646d2SAndroid Build Coastguard Worker int kbytes; /* Size of banner file in kbytes */
4114*5e7646d2SAndroid Build Coastguard Worker char filename[1024]; /* Job filename */
4115*5e7646d2SAndroid Build Coastguard Worker cupsd_banner_t *banner; /* Pointer to banner */
4116*5e7646d2SAndroid Build Coastguard Worker cups_file_t *in; /* Input file */
4117*5e7646d2SAndroid Build Coastguard Worker cups_file_t *out; /* Output file */
4118*5e7646d2SAndroid Build Coastguard Worker int ch; /* Character from file */
4119*5e7646d2SAndroid Build Coastguard Worker char attrname[255], /* Name of attribute */
4120*5e7646d2SAndroid Build Coastguard Worker *s; /* Pointer into name */
4121*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *attr; /* Attribute */
4122*5e7646d2SAndroid Build Coastguard Worker
4123*5e7646d2SAndroid Build Coastguard Worker
4124*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG2,
4125*5e7646d2SAndroid Build Coastguard Worker "copy_banner(con=%p[%d], job=%p[%d], name=\"%s\")",
4126*5e7646d2SAndroid Build Coastguard Worker con, con ? con->number : -1, job, job->id,
4127*5e7646d2SAndroid Build Coastguard Worker name ? name : "(null)");
4128*5e7646d2SAndroid Build Coastguard Worker
4129*5e7646d2SAndroid Build Coastguard Worker /*
4130*5e7646d2SAndroid Build Coastguard Worker * Find the banner; return if not found or "none"...
4131*5e7646d2SAndroid Build Coastguard Worker */
4132*5e7646d2SAndroid Build Coastguard Worker
4133*5e7646d2SAndroid Build Coastguard Worker if (!name || !strcmp(name, "none") ||
4134*5e7646d2SAndroid Build Coastguard Worker (banner = cupsdFindBanner(name)) == NULL)
4135*5e7646d2SAndroid Build Coastguard Worker return (0);
4136*5e7646d2SAndroid Build Coastguard Worker
4137*5e7646d2SAndroid Build Coastguard Worker /*
4138*5e7646d2SAndroid Build Coastguard Worker * Open the banner and job files...
4139*5e7646d2SAndroid Build Coastguard Worker */
4140*5e7646d2SAndroid Build Coastguard Worker
4141*5e7646d2SAndroid Build Coastguard Worker if (add_file(con, job, banner->filetype, 0))
4142*5e7646d2SAndroid Build Coastguard Worker return (-1);
4143*5e7646d2SAndroid Build Coastguard Worker
4144*5e7646d2SAndroid Build Coastguard Worker snprintf(filename, sizeof(filename), "%s/d%05d-%03d", RequestRoot, job->id,
4145*5e7646d2SAndroid Build Coastguard Worker job->num_files);
4146*5e7646d2SAndroid Build Coastguard Worker if ((out = cupsFileOpen(filename, "w")) == NULL)
4147*5e7646d2SAndroid Build Coastguard Worker {
4148*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_ERROR,
4149*5e7646d2SAndroid Build Coastguard Worker "Unable to create banner job file %s - %s",
4150*5e7646d2SAndroid Build Coastguard Worker filename, strerror(errno));
4151*5e7646d2SAndroid Build Coastguard Worker job->num_files --;
4152*5e7646d2SAndroid Build Coastguard Worker return (0);
4153*5e7646d2SAndroid Build Coastguard Worker }
4154*5e7646d2SAndroid Build Coastguard Worker
4155*5e7646d2SAndroid Build Coastguard Worker fchmod(cupsFileNumber(out), 0640);
4156*5e7646d2SAndroid Build Coastguard Worker fchown(cupsFileNumber(out), RunUser, Group);
4157*5e7646d2SAndroid Build Coastguard Worker
4158*5e7646d2SAndroid Build Coastguard Worker /*
4159*5e7646d2SAndroid Build Coastguard Worker * Try the localized banner file under the subdirectory...
4160*5e7646d2SAndroid Build Coastguard Worker */
4161*5e7646d2SAndroid Build Coastguard Worker
4162*5e7646d2SAndroid Build Coastguard Worker strlcpy(attrname, job->attrs->attrs->next->values[0].string.text,
4163*5e7646d2SAndroid Build Coastguard Worker sizeof(attrname));
4164*5e7646d2SAndroid Build Coastguard Worker if (strlen(attrname) > 2 && attrname[2] == '-')
4165*5e7646d2SAndroid Build Coastguard Worker {
4166*5e7646d2SAndroid Build Coastguard Worker /*
4167*5e7646d2SAndroid Build Coastguard Worker * Convert ll-cc to ll_CC...
4168*5e7646d2SAndroid Build Coastguard Worker */
4169*5e7646d2SAndroid Build Coastguard Worker
4170*5e7646d2SAndroid Build Coastguard Worker attrname[2] = '_';
4171*5e7646d2SAndroid Build Coastguard Worker attrname[3] = (char)toupper(attrname[3] & 255);
4172*5e7646d2SAndroid Build Coastguard Worker attrname[4] = (char)toupper(attrname[4] & 255);
4173*5e7646d2SAndroid Build Coastguard Worker }
4174*5e7646d2SAndroid Build Coastguard Worker
4175*5e7646d2SAndroid Build Coastguard Worker snprintf(filename, sizeof(filename), "%s/banners/%s/%s", DataDir,
4176*5e7646d2SAndroid Build Coastguard Worker attrname, name);
4177*5e7646d2SAndroid Build Coastguard Worker
4178*5e7646d2SAndroid Build Coastguard Worker if (access(filename, 0) && strlen(attrname) > 2)
4179*5e7646d2SAndroid Build Coastguard Worker {
4180*5e7646d2SAndroid Build Coastguard Worker /*
4181*5e7646d2SAndroid Build Coastguard Worker * Wasn't able to find "ll_CC" locale file; try the non-national
4182*5e7646d2SAndroid Build Coastguard Worker * localization banner directory.
4183*5e7646d2SAndroid Build Coastguard Worker */
4184*5e7646d2SAndroid Build Coastguard Worker
4185*5e7646d2SAndroid Build Coastguard Worker attrname[2] = '\0';
4186*5e7646d2SAndroid Build Coastguard Worker
4187*5e7646d2SAndroid Build Coastguard Worker snprintf(filename, sizeof(filename), "%s/banners/%s/%s", DataDir,
4188*5e7646d2SAndroid Build Coastguard Worker attrname, name);
4189*5e7646d2SAndroid Build Coastguard Worker }
4190*5e7646d2SAndroid Build Coastguard Worker
4191*5e7646d2SAndroid Build Coastguard Worker if (access(filename, 0))
4192*5e7646d2SAndroid Build Coastguard Worker {
4193*5e7646d2SAndroid Build Coastguard Worker /*
4194*5e7646d2SAndroid Build Coastguard Worker * Use the non-localized banner file.
4195*5e7646d2SAndroid Build Coastguard Worker */
4196*5e7646d2SAndroid Build Coastguard Worker
4197*5e7646d2SAndroid Build Coastguard Worker snprintf(filename, sizeof(filename), "%s/banners/%s", DataDir, name);
4198*5e7646d2SAndroid Build Coastguard Worker }
4199*5e7646d2SAndroid Build Coastguard Worker
4200*5e7646d2SAndroid Build Coastguard Worker if ((in = cupsFileOpen(filename, "r")) == NULL)
4201*5e7646d2SAndroid Build Coastguard Worker {
4202*5e7646d2SAndroid Build Coastguard Worker cupsFileClose(out);
4203*5e7646d2SAndroid Build Coastguard Worker unlink(filename);
4204*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_ERROR,
4205*5e7646d2SAndroid Build Coastguard Worker "Unable to open banner template file %s - %s",
4206*5e7646d2SAndroid Build Coastguard Worker filename, strerror(errno));
4207*5e7646d2SAndroid Build Coastguard Worker job->num_files --;
4208*5e7646d2SAndroid Build Coastguard Worker return (0);
4209*5e7646d2SAndroid Build Coastguard Worker }
4210*5e7646d2SAndroid Build Coastguard Worker
4211*5e7646d2SAndroid Build Coastguard Worker /*
4212*5e7646d2SAndroid Build Coastguard Worker * Parse the file to the end...
4213*5e7646d2SAndroid Build Coastguard Worker */
4214*5e7646d2SAndroid Build Coastguard Worker
4215*5e7646d2SAndroid Build Coastguard Worker while ((ch = cupsFileGetChar(in)) != EOF)
4216*5e7646d2SAndroid Build Coastguard Worker if (ch == '{')
4217*5e7646d2SAndroid Build Coastguard Worker {
4218*5e7646d2SAndroid Build Coastguard Worker /*
4219*5e7646d2SAndroid Build Coastguard Worker * Get an attribute name...
4220*5e7646d2SAndroid Build Coastguard Worker */
4221*5e7646d2SAndroid Build Coastguard Worker
4222*5e7646d2SAndroid Build Coastguard Worker for (s = attrname; (ch = cupsFileGetChar(in)) != EOF;)
4223*5e7646d2SAndroid Build Coastguard Worker if (!isalpha(ch & 255) && ch != '-' && ch != '?')
4224*5e7646d2SAndroid Build Coastguard Worker break;
4225*5e7646d2SAndroid Build Coastguard Worker else if (s < (attrname + sizeof(attrname) - 1))
4226*5e7646d2SAndroid Build Coastguard Worker *s++ = (char)ch;
4227*5e7646d2SAndroid Build Coastguard Worker else
4228*5e7646d2SAndroid Build Coastguard Worker break;
4229*5e7646d2SAndroid Build Coastguard Worker
4230*5e7646d2SAndroid Build Coastguard Worker *s = '\0';
4231*5e7646d2SAndroid Build Coastguard Worker
4232*5e7646d2SAndroid Build Coastguard Worker if (ch != '}')
4233*5e7646d2SAndroid Build Coastguard Worker {
4234*5e7646d2SAndroid Build Coastguard Worker /*
4235*5e7646d2SAndroid Build Coastguard Worker * Ignore { followed by stuff that is not an attribute name...
4236*5e7646d2SAndroid Build Coastguard Worker */
4237*5e7646d2SAndroid Build Coastguard Worker
4238*5e7646d2SAndroid Build Coastguard Worker cupsFilePrintf(out, "{%s%c", attrname, ch);
4239*5e7646d2SAndroid Build Coastguard Worker continue;
4240*5e7646d2SAndroid Build Coastguard Worker }
4241*5e7646d2SAndroid Build Coastguard Worker
4242*5e7646d2SAndroid Build Coastguard Worker /*
4243*5e7646d2SAndroid Build Coastguard Worker * See if it is defined...
4244*5e7646d2SAndroid Build Coastguard Worker */
4245*5e7646d2SAndroid Build Coastguard Worker
4246*5e7646d2SAndroid Build Coastguard Worker if (attrname[0] == '?')
4247*5e7646d2SAndroid Build Coastguard Worker s = attrname + 1;
4248*5e7646d2SAndroid Build Coastguard Worker else
4249*5e7646d2SAndroid Build Coastguard Worker s = attrname;
4250*5e7646d2SAndroid Build Coastguard Worker
4251*5e7646d2SAndroid Build Coastguard Worker if (!strcmp(s, "printer-name"))
4252*5e7646d2SAndroid Build Coastguard Worker {
4253*5e7646d2SAndroid Build Coastguard Worker cupsFilePuts(out, job->dest);
4254*5e7646d2SAndroid Build Coastguard Worker continue;
4255*5e7646d2SAndroid Build Coastguard Worker }
4256*5e7646d2SAndroid Build Coastguard Worker else if ((attr = ippFindAttribute(job->attrs, s, IPP_TAG_ZERO)) == NULL)
4257*5e7646d2SAndroid Build Coastguard Worker {
4258*5e7646d2SAndroid Build Coastguard Worker /*
4259*5e7646d2SAndroid Build Coastguard Worker * See if we have a leading question mark...
4260*5e7646d2SAndroid Build Coastguard Worker */
4261*5e7646d2SAndroid Build Coastguard Worker
4262*5e7646d2SAndroid Build Coastguard Worker if (attrname[0] != '?')
4263*5e7646d2SAndroid Build Coastguard Worker {
4264*5e7646d2SAndroid Build Coastguard Worker /*
4265*5e7646d2SAndroid Build Coastguard Worker * Nope, write to file as-is; probably a PostScript procedure...
4266*5e7646d2SAndroid Build Coastguard Worker */
4267*5e7646d2SAndroid Build Coastguard Worker
4268*5e7646d2SAndroid Build Coastguard Worker cupsFilePrintf(out, "{%s}", attrname);
4269*5e7646d2SAndroid Build Coastguard Worker }
4270*5e7646d2SAndroid Build Coastguard Worker
4271*5e7646d2SAndroid Build Coastguard Worker continue;
4272*5e7646d2SAndroid Build Coastguard Worker }
4273*5e7646d2SAndroid Build Coastguard Worker
4274*5e7646d2SAndroid Build Coastguard Worker /*
4275*5e7646d2SAndroid Build Coastguard Worker * Output value(s)...
4276*5e7646d2SAndroid Build Coastguard Worker */
4277*5e7646d2SAndroid Build Coastguard Worker
4278*5e7646d2SAndroid Build Coastguard Worker for (i = 0; i < attr->num_values; i ++)
4279*5e7646d2SAndroid Build Coastguard Worker {
4280*5e7646d2SAndroid Build Coastguard Worker if (i)
4281*5e7646d2SAndroid Build Coastguard Worker cupsFilePutChar(out, ',');
4282*5e7646d2SAndroid Build Coastguard Worker
4283*5e7646d2SAndroid Build Coastguard Worker switch (attr->value_tag)
4284*5e7646d2SAndroid Build Coastguard Worker {
4285*5e7646d2SAndroid Build Coastguard Worker case IPP_TAG_INTEGER :
4286*5e7646d2SAndroid Build Coastguard Worker case IPP_TAG_ENUM :
4287*5e7646d2SAndroid Build Coastguard Worker if (!strncmp(s, "time-at-", 8))
4288*5e7646d2SAndroid Build Coastguard Worker {
4289*5e7646d2SAndroid Build Coastguard Worker struct timeval tv; /* Time value */
4290*5e7646d2SAndroid Build Coastguard Worker
4291*5e7646d2SAndroid Build Coastguard Worker tv.tv_sec = attr->values[i].integer;
4292*5e7646d2SAndroid Build Coastguard Worker tv.tv_usec = 0;
4293*5e7646d2SAndroid Build Coastguard Worker
4294*5e7646d2SAndroid Build Coastguard Worker cupsFilePuts(out, cupsdGetDateTime(&tv, CUPSD_TIME_STANDARD));
4295*5e7646d2SAndroid Build Coastguard Worker }
4296*5e7646d2SAndroid Build Coastguard Worker else
4297*5e7646d2SAndroid Build Coastguard Worker cupsFilePrintf(out, "%d", attr->values[i].integer);
4298*5e7646d2SAndroid Build Coastguard Worker break;
4299*5e7646d2SAndroid Build Coastguard Worker
4300*5e7646d2SAndroid Build Coastguard Worker case IPP_TAG_BOOLEAN :
4301*5e7646d2SAndroid Build Coastguard Worker cupsFilePrintf(out, "%d", attr->values[i].boolean);
4302*5e7646d2SAndroid Build Coastguard Worker break;
4303*5e7646d2SAndroid Build Coastguard Worker
4304*5e7646d2SAndroid Build Coastguard Worker case IPP_TAG_NOVALUE :
4305*5e7646d2SAndroid Build Coastguard Worker cupsFilePuts(out, "novalue");
4306*5e7646d2SAndroid Build Coastguard Worker break;
4307*5e7646d2SAndroid Build Coastguard Worker
4308*5e7646d2SAndroid Build Coastguard Worker case IPP_TAG_RANGE :
4309*5e7646d2SAndroid Build Coastguard Worker cupsFilePrintf(out, "%d-%d", attr->values[i].range.lower,
4310*5e7646d2SAndroid Build Coastguard Worker attr->values[i].range.upper);
4311*5e7646d2SAndroid Build Coastguard Worker break;
4312*5e7646d2SAndroid Build Coastguard Worker
4313*5e7646d2SAndroid Build Coastguard Worker case IPP_TAG_RESOLUTION :
4314*5e7646d2SAndroid Build Coastguard Worker cupsFilePrintf(out, "%dx%d%s", attr->values[i].resolution.xres,
4315*5e7646d2SAndroid Build Coastguard Worker attr->values[i].resolution.yres,
4316*5e7646d2SAndroid Build Coastguard Worker attr->values[i].resolution.units == IPP_RES_PER_INCH ?
4317*5e7646d2SAndroid Build Coastguard Worker "dpi" : "dpcm");
4318*5e7646d2SAndroid Build Coastguard Worker break;
4319*5e7646d2SAndroid Build Coastguard Worker
4320*5e7646d2SAndroid Build Coastguard Worker case IPP_TAG_URI :
4321*5e7646d2SAndroid Build Coastguard Worker case IPP_TAG_STRING :
4322*5e7646d2SAndroid Build Coastguard Worker case IPP_TAG_TEXT :
4323*5e7646d2SAndroid Build Coastguard Worker case IPP_TAG_NAME :
4324*5e7646d2SAndroid Build Coastguard Worker case IPP_TAG_KEYWORD :
4325*5e7646d2SAndroid Build Coastguard Worker case IPP_TAG_CHARSET :
4326*5e7646d2SAndroid Build Coastguard Worker case IPP_TAG_LANGUAGE :
4327*5e7646d2SAndroid Build Coastguard Worker if (!_cups_strcasecmp(banner->filetype->type, "postscript"))
4328*5e7646d2SAndroid Build Coastguard Worker {
4329*5e7646d2SAndroid Build Coastguard Worker /*
4330*5e7646d2SAndroid Build Coastguard Worker * Need to quote strings for PS banners...
4331*5e7646d2SAndroid Build Coastguard Worker */
4332*5e7646d2SAndroid Build Coastguard Worker
4333*5e7646d2SAndroid Build Coastguard Worker const char *p;
4334*5e7646d2SAndroid Build Coastguard Worker
4335*5e7646d2SAndroid Build Coastguard Worker for (p = attr->values[i].string.text; *p; p ++)
4336*5e7646d2SAndroid Build Coastguard Worker {
4337*5e7646d2SAndroid Build Coastguard Worker if (*p == '(' || *p == ')' || *p == '\\')
4338*5e7646d2SAndroid Build Coastguard Worker {
4339*5e7646d2SAndroid Build Coastguard Worker cupsFilePutChar(out, '\\');
4340*5e7646d2SAndroid Build Coastguard Worker cupsFilePutChar(out, *p);
4341*5e7646d2SAndroid Build Coastguard Worker }
4342*5e7646d2SAndroid Build Coastguard Worker else if (*p < 32 || *p > 126)
4343*5e7646d2SAndroid Build Coastguard Worker cupsFilePrintf(out, "\\%03o", *p & 255);
4344*5e7646d2SAndroid Build Coastguard Worker else
4345*5e7646d2SAndroid Build Coastguard Worker cupsFilePutChar(out, *p);
4346*5e7646d2SAndroid Build Coastguard Worker }
4347*5e7646d2SAndroid Build Coastguard Worker }
4348*5e7646d2SAndroid Build Coastguard Worker else
4349*5e7646d2SAndroid Build Coastguard Worker cupsFilePuts(out, attr->values[i].string.text);
4350*5e7646d2SAndroid Build Coastguard Worker break;
4351*5e7646d2SAndroid Build Coastguard Worker
4352*5e7646d2SAndroid Build Coastguard Worker default :
4353*5e7646d2SAndroid Build Coastguard Worker break; /* anti-compiler-warning-code */
4354*5e7646d2SAndroid Build Coastguard Worker }
4355*5e7646d2SAndroid Build Coastguard Worker }
4356*5e7646d2SAndroid Build Coastguard Worker }
4357*5e7646d2SAndroid Build Coastguard Worker else if (ch == '\\') /* Quoted char */
4358*5e7646d2SAndroid Build Coastguard Worker {
4359*5e7646d2SAndroid Build Coastguard Worker ch = cupsFileGetChar(in);
4360*5e7646d2SAndroid Build Coastguard Worker
4361*5e7646d2SAndroid Build Coastguard Worker if (ch != '{') /* Only do special handling for \{ */
4362*5e7646d2SAndroid Build Coastguard Worker cupsFilePutChar(out, '\\');
4363*5e7646d2SAndroid Build Coastguard Worker
4364*5e7646d2SAndroid Build Coastguard Worker cupsFilePutChar(out, ch);
4365*5e7646d2SAndroid Build Coastguard Worker }
4366*5e7646d2SAndroid Build Coastguard Worker else
4367*5e7646d2SAndroid Build Coastguard Worker cupsFilePutChar(out, ch);
4368*5e7646d2SAndroid Build Coastguard Worker
4369*5e7646d2SAndroid Build Coastguard Worker cupsFileClose(in);
4370*5e7646d2SAndroid Build Coastguard Worker
4371*5e7646d2SAndroid Build Coastguard Worker kbytes = (cupsFileTell(out) + 1023) / 1024;
4372*5e7646d2SAndroid Build Coastguard Worker
4373*5e7646d2SAndroid Build Coastguard Worker job->koctets += kbytes;
4374*5e7646d2SAndroid Build Coastguard Worker
4375*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippFindAttribute(job->attrs, "job-k-octets", IPP_TAG_INTEGER)) != NULL)
4376*5e7646d2SAndroid Build Coastguard Worker attr->values[0].integer += kbytes;
4377*5e7646d2SAndroid Build Coastguard Worker
4378*5e7646d2SAndroid Build Coastguard Worker cupsFileClose(out);
4379*5e7646d2SAndroid Build Coastguard Worker
4380*5e7646d2SAndroid Build Coastguard Worker return (kbytes);
4381*5e7646d2SAndroid Build Coastguard Worker }
4382*5e7646d2SAndroid Build Coastguard Worker
4383*5e7646d2SAndroid Build Coastguard Worker
4384*5e7646d2SAndroid Build Coastguard Worker /*
4385*5e7646d2SAndroid Build Coastguard Worker * 'copy_file()' - Copy a PPD file...
4386*5e7646d2SAndroid Build Coastguard Worker */
4387*5e7646d2SAndroid Build Coastguard Worker
4388*5e7646d2SAndroid Build Coastguard Worker static int /* O - 0 = success, -1 = error */
copy_file(const char * from,const char * to,mode_t mode)4389*5e7646d2SAndroid Build Coastguard Worker copy_file(const char *from, /* I - Source file */
4390*5e7646d2SAndroid Build Coastguard Worker const char *to, /* I - Destination file */
4391*5e7646d2SAndroid Build Coastguard Worker mode_t mode) /* I - Permissions */
4392*5e7646d2SAndroid Build Coastguard Worker {
4393*5e7646d2SAndroid Build Coastguard Worker cups_file_t *src, /* Source file */
4394*5e7646d2SAndroid Build Coastguard Worker *dst; /* Destination file */
4395*5e7646d2SAndroid Build Coastguard Worker int bytes; /* Bytes to read/write */
4396*5e7646d2SAndroid Build Coastguard Worker char buffer[2048]; /* Copy buffer */
4397*5e7646d2SAndroid Build Coastguard Worker
4398*5e7646d2SAndroid Build Coastguard Worker
4399*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG2, "copy_file(\"%s\", \"%s\")", from, to);
4400*5e7646d2SAndroid Build Coastguard Worker
4401*5e7646d2SAndroid Build Coastguard Worker /*
4402*5e7646d2SAndroid Build Coastguard Worker * Open the source and destination file for a copy...
4403*5e7646d2SAndroid Build Coastguard Worker */
4404*5e7646d2SAndroid Build Coastguard Worker
4405*5e7646d2SAndroid Build Coastguard Worker if ((src = cupsFileOpen(from, "rb")) == NULL)
4406*5e7646d2SAndroid Build Coastguard Worker return (-1);
4407*5e7646d2SAndroid Build Coastguard Worker
4408*5e7646d2SAndroid Build Coastguard Worker if ((dst = cupsdCreateConfFile(to, mode)) == NULL)
4409*5e7646d2SAndroid Build Coastguard Worker {
4410*5e7646d2SAndroid Build Coastguard Worker cupsFileClose(src);
4411*5e7646d2SAndroid Build Coastguard Worker return (-1);
4412*5e7646d2SAndroid Build Coastguard Worker }
4413*5e7646d2SAndroid Build Coastguard Worker
4414*5e7646d2SAndroid Build Coastguard Worker /*
4415*5e7646d2SAndroid Build Coastguard Worker * Copy the source file to the destination...
4416*5e7646d2SAndroid Build Coastguard Worker */
4417*5e7646d2SAndroid Build Coastguard Worker
4418*5e7646d2SAndroid Build Coastguard Worker while ((bytes = cupsFileRead(src, buffer, sizeof(buffer))) > 0)
4419*5e7646d2SAndroid Build Coastguard Worker if (cupsFileWrite(dst, buffer, (size_t)bytes) < bytes)
4420*5e7646d2SAndroid Build Coastguard Worker {
4421*5e7646d2SAndroid Build Coastguard Worker cupsFileClose(src);
4422*5e7646d2SAndroid Build Coastguard Worker cupsFileClose(dst);
4423*5e7646d2SAndroid Build Coastguard Worker return (-1);
4424*5e7646d2SAndroid Build Coastguard Worker }
4425*5e7646d2SAndroid Build Coastguard Worker
4426*5e7646d2SAndroid Build Coastguard Worker /*
4427*5e7646d2SAndroid Build Coastguard Worker * Close both files and return...
4428*5e7646d2SAndroid Build Coastguard Worker */
4429*5e7646d2SAndroid Build Coastguard Worker
4430*5e7646d2SAndroid Build Coastguard Worker cupsFileClose(src);
4431*5e7646d2SAndroid Build Coastguard Worker
4432*5e7646d2SAndroid Build Coastguard Worker return (cupsdCloseCreatedConfFile(dst, to));
4433*5e7646d2SAndroid Build Coastguard Worker }
4434*5e7646d2SAndroid Build Coastguard Worker
4435*5e7646d2SAndroid Build Coastguard Worker
4436*5e7646d2SAndroid Build Coastguard Worker /*
4437*5e7646d2SAndroid Build Coastguard Worker * 'copy_model()' - Copy a PPD model file, substituting default values
4438*5e7646d2SAndroid Build Coastguard Worker * as needed...
4439*5e7646d2SAndroid Build Coastguard Worker */
4440*5e7646d2SAndroid Build Coastguard Worker
4441*5e7646d2SAndroid Build Coastguard Worker static int /* O - 0 = success, -1 = error */
copy_model(cupsd_client_t * con,const char * from,const char * to)4442*5e7646d2SAndroid Build Coastguard Worker copy_model(cupsd_client_t *con, /* I - Client connection */
4443*5e7646d2SAndroid Build Coastguard Worker const char *from, /* I - Source file */
4444*5e7646d2SAndroid Build Coastguard Worker const char *to) /* I - Destination file */
4445*5e7646d2SAndroid Build Coastguard Worker {
4446*5e7646d2SAndroid Build Coastguard Worker fd_set input; /* select() input set */
4447*5e7646d2SAndroid Build Coastguard Worker struct timeval timeout; /* select() timeout */
4448*5e7646d2SAndroid Build Coastguard Worker int maxfd; /* Max file descriptor for select() */
4449*5e7646d2SAndroid Build Coastguard Worker char tempfile[1024]; /* Temporary PPD file */
4450*5e7646d2SAndroid Build Coastguard Worker int tempfd; /* Temporary PPD file descriptor */
4451*5e7646d2SAndroid Build Coastguard Worker int temppid; /* Process ID of cups-driverd */
4452*5e7646d2SAndroid Build Coastguard Worker int temppipe[2]; /* Temporary pipes */
4453*5e7646d2SAndroid Build Coastguard Worker char *argv[4], /* Command-line arguments */
4454*5e7646d2SAndroid Build Coastguard Worker *envp[MAX_ENV]; /* Environment */
4455*5e7646d2SAndroid Build Coastguard Worker cups_file_t *src, /* Source file */
4456*5e7646d2SAndroid Build Coastguard Worker *dst; /* Destination file */
4457*5e7646d2SAndroid Build Coastguard Worker ppd_file_t *ppd; /* PPD file */
4458*5e7646d2SAndroid Build Coastguard Worker int bytes, /* Bytes from pipe */
4459*5e7646d2SAndroid Build Coastguard Worker total; /* Total bytes from pipe */
4460*5e7646d2SAndroid Build Coastguard Worker char buffer[2048]; /* Copy buffer */
4461*5e7646d2SAndroid Build Coastguard Worker int i; /* Looping var */
4462*5e7646d2SAndroid Build Coastguard Worker char option[PPD_MAX_NAME], /* Option name */
4463*5e7646d2SAndroid Build Coastguard Worker choice[PPD_MAX_NAME]; /* Choice name */
4464*5e7646d2SAndroid Build Coastguard Worker ppd_size_t *size; /* Default size */
4465*5e7646d2SAndroid Build Coastguard Worker int num_defaults; /* Number of default options */
4466*5e7646d2SAndroid Build Coastguard Worker cups_option_t *defaults; /* Default options */
4467*5e7646d2SAndroid Build Coastguard Worker char cups_protocol[PPD_MAX_LINE];
4468*5e7646d2SAndroid Build Coastguard Worker /* cupsProtocol attribute */
4469*5e7646d2SAndroid Build Coastguard Worker
4470*5e7646d2SAndroid Build Coastguard Worker
4471*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG2, "copy_model(con=%p, from=\"%s\", to=\"%s\")", con, from, to);
4472*5e7646d2SAndroid Build Coastguard Worker
4473*5e7646d2SAndroid Build Coastguard Worker /*
4474*5e7646d2SAndroid Build Coastguard Worker * Run cups-driverd to get the PPD file...
4475*5e7646d2SAndroid Build Coastguard Worker */
4476*5e7646d2SAndroid Build Coastguard Worker
4477*5e7646d2SAndroid Build Coastguard Worker argv[0] = "cups-driverd";
4478*5e7646d2SAndroid Build Coastguard Worker argv[1] = "cat";
4479*5e7646d2SAndroid Build Coastguard Worker argv[2] = (char *)from;
4480*5e7646d2SAndroid Build Coastguard Worker argv[3] = NULL;
4481*5e7646d2SAndroid Build Coastguard Worker
4482*5e7646d2SAndroid Build Coastguard Worker cupsdLoadEnv(envp, (int)(sizeof(envp) / sizeof(envp[0])));
4483*5e7646d2SAndroid Build Coastguard Worker
4484*5e7646d2SAndroid Build Coastguard Worker snprintf(buffer, sizeof(buffer), "%s/daemon/cups-driverd", ServerBin);
4485*5e7646d2SAndroid Build Coastguard Worker snprintf(tempfile, sizeof(tempfile), "%s/%d.ppd", TempDir, con->number);
4486*5e7646d2SAndroid Build Coastguard Worker tempfd = open(tempfile, O_WRONLY | O_CREAT | O_TRUNC, 0600);
4487*5e7646d2SAndroid Build Coastguard Worker if (tempfd < 0 || cupsdOpenPipe(temppipe))
4488*5e7646d2SAndroid Build Coastguard Worker return (-1);
4489*5e7646d2SAndroid Build Coastguard Worker
4490*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG,
4491*5e7646d2SAndroid Build Coastguard Worker "copy_model: Running \"cups-driverd cat %s\"...", from);
4492*5e7646d2SAndroid Build Coastguard Worker
4493*5e7646d2SAndroid Build Coastguard Worker if (!cupsdStartProcess(buffer, argv, envp, -1, temppipe[1], CGIPipes[1],
4494*5e7646d2SAndroid Build Coastguard Worker -1, -1, 0, DefaultProfile, NULL, &temppid))
4495*5e7646d2SAndroid Build Coastguard Worker {
4496*5e7646d2SAndroid Build Coastguard Worker close(tempfd);
4497*5e7646d2SAndroid Build Coastguard Worker unlink(tempfile);
4498*5e7646d2SAndroid Build Coastguard Worker
4499*5e7646d2SAndroid Build Coastguard Worker return (-1);
4500*5e7646d2SAndroid Build Coastguard Worker }
4501*5e7646d2SAndroid Build Coastguard Worker
4502*5e7646d2SAndroid Build Coastguard Worker close(temppipe[1]);
4503*5e7646d2SAndroid Build Coastguard Worker
4504*5e7646d2SAndroid Build Coastguard Worker /*
4505*5e7646d2SAndroid Build Coastguard Worker * Wait up to 30 seconds for the PPD file to be copied...
4506*5e7646d2SAndroid Build Coastguard Worker */
4507*5e7646d2SAndroid Build Coastguard Worker
4508*5e7646d2SAndroid Build Coastguard Worker total = 0;
4509*5e7646d2SAndroid Build Coastguard Worker
4510*5e7646d2SAndroid Build Coastguard Worker if (temppipe[0] > CGIPipes[0])
4511*5e7646d2SAndroid Build Coastguard Worker maxfd = temppipe[0] + 1;
4512*5e7646d2SAndroid Build Coastguard Worker else
4513*5e7646d2SAndroid Build Coastguard Worker maxfd = CGIPipes[0] + 1;
4514*5e7646d2SAndroid Build Coastguard Worker
4515*5e7646d2SAndroid Build Coastguard Worker for (;;)
4516*5e7646d2SAndroid Build Coastguard Worker {
4517*5e7646d2SAndroid Build Coastguard Worker /*
4518*5e7646d2SAndroid Build Coastguard Worker * See if we have data ready...
4519*5e7646d2SAndroid Build Coastguard Worker */
4520*5e7646d2SAndroid Build Coastguard Worker
4521*5e7646d2SAndroid Build Coastguard Worker FD_ZERO(&input);
4522*5e7646d2SAndroid Build Coastguard Worker FD_SET(temppipe[0], &input);
4523*5e7646d2SAndroid Build Coastguard Worker FD_SET(CGIPipes[0], &input);
4524*5e7646d2SAndroid Build Coastguard Worker
4525*5e7646d2SAndroid Build Coastguard Worker timeout.tv_sec = 30;
4526*5e7646d2SAndroid Build Coastguard Worker timeout.tv_usec = 0;
4527*5e7646d2SAndroid Build Coastguard Worker
4528*5e7646d2SAndroid Build Coastguard Worker if ((i = select(maxfd, &input, NULL, NULL, &timeout)) < 0)
4529*5e7646d2SAndroid Build Coastguard Worker {
4530*5e7646d2SAndroid Build Coastguard Worker if (errno == EINTR)
4531*5e7646d2SAndroid Build Coastguard Worker continue;
4532*5e7646d2SAndroid Build Coastguard Worker else
4533*5e7646d2SAndroid Build Coastguard Worker break;
4534*5e7646d2SAndroid Build Coastguard Worker }
4535*5e7646d2SAndroid Build Coastguard Worker else if (i == 0)
4536*5e7646d2SAndroid Build Coastguard Worker {
4537*5e7646d2SAndroid Build Coastguard Worker /*
4538*5e7646d2SAndroid Build Coastguard Worker * We have timed out...
4539*5e7646d2SAndroid Build Coastguard Worker */
4540*5e7646d2SAndroid Build Coastguard Worker
4541*5e7646d2SAndroid Build Coastguard Worker break;
4542*5e7646d2SAndroid Build Coastguard Worker }
4543*5e7646d2SAndroid Build Coastguard Worker
4544*5e7646d2SAndroid Build Coastguard Worker if (FD_ISSET(temppipe[0], &input))
4545*5e7646d2SAndroid Build Coastguard Worker {
4546*5e7646d2SAndroid Build Coastguard Worker /*
4547*5e7646d2SAndroid Build Coastguard Worker * Read the PPD file from the pipe, and write it to the PPD file.
4548*5e7646d2SAndroid Build Coastguard Worker */
4549*5e7646d2SAndroid Build Coastguard Worker
4550*5e7646d2SAndroid Build Coastguard Worker if ((bytes = read(temppipe[0], buffer, sizeof(buffer))) > 0)
4551*5e7646d2SAndroid Build Coastguard Worker {
4552*5e7646d2SAndroid Build Coastguard Worker if (write(tempfd, buffer, (size_t)bytes) < bytes)
4553*5e7646d2SAndroid Build Coastguard Worker break;
4554*5e7646d2SAndroid Build Coastguard Worker
4555*5e7646d2SAndroid Build Coastguard Worker total += bytes;
4556*5e7646d2SAndroid Build Coastguard Worker }
4557*5e7646d2SAndroid Build Coastguard Worker else
4558*5e7646d2SAndroid Build Coastguard Worker break;
4559*5e7646d2SAndroid Build Coastguard Worker }
4560*5e7646d2SAndroid Build Coastguard Worker
4561*5e7646d2SAndroid Build Coastguard Worker if (FD_ISSET(CGIPipes[0], &input))
4562*5e7646d2SAndroid Build Coastguard Worker cupsdUpdateCGI();
4563*5e7646d2SAndroid Build Coastguard Worker }
4564*5e7646d2SAndroid Build Coastguard Worker
4565*5e7646d2SAndroid Build Coastguard Worker close(temppipe[0]);
4566*5e7646d2SAndroid Build Coastguard Worker close(tempfd);
4567*5e7646d2SAndroid Build Coastguard Worker
4568*5e7646d2SAndroid Build Coastguard Worker if (!total)
4569*5e7646d2SAndroid Build Coastguard Worker {
4570*5e7646d2SAndroid Build Coastguard Worker /*
4571*5e7646d2SAndroid Build Coastguard Worker * No data from cups-deviced...
4572*5e7646d2SAndroid Build Coastguard Worker */
4573*5e7646d2SAndroid Build Coastguard Worker
4574*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_ERROR, "copy_model: empty PPD file");
4575*5e7646d2SAndroid Build Coastguard Worker unlink(tempfile);
4576*5e7646d2SAndroid Build Coastguard Worker return (-1);
4577*5e7646d2SAndroid Build Coastguard Worker }
4578*5e7646d2SAndroid Build Coastguard Worker
4579*5e7646d2SAndroid Build Coastguard Worker /*
4580*5e7646d2SAndroid Build Coastguard Worker * Open the source file for a copy...
4581*5e7646d2SAndroid Build Coastguard Worker */
4582*5e7646d2SAndroid Build Coastguard Worker
4583*5e7646d2SAndroid Build Coastguard Worker if ((src = cupsFileOpen(tempfile, "rb")) == NULL)
4584*5e7646d2SAndroid Build Coastguard Worker {
4585*5e7646d2SAndroid Build Coastguard Worker unlink(tempfile);
4586*5e7646d2SAndroid Build Coastguard Worker return (-1);
4587*5e7646d2SAndroid Build Coastguard Worker }
4588*5e7646d2SAndroid Build Coastguard Worker
4589*5e7646d2SAndroid Build Coastguard Worker /*
4590*5e7646d2SAndroid Build Coastguard Worker * Read the source file and see what page sizes are supported...
4591*5e7646d2SAndroid Build Coastguard Worker */
4592*5e7646d2SAndroid Build Coastguard Worker
4593*5e7646d2SAndroid Build Coastguard Worker if ((ppd = _ppdOpen(src, _PPD_LOCALIZATION_NONE)) == NULL)
4594*5e7646d2SAndroid Build Coastguard Worker {
4595*5e7646d2SAndroid Build Coastguard Worker cupsFileClose(src);
4596*5e7646d2SAndroid Build Coastguard Worker unlink(tempfile);
4597*5e7646d2SAndroid Build Coastguard Worker return (-1);
4598*5e7646d2SAndroid Build Coastguard Worker }
4599*5e7646d2SAndroid Build Coastguard Worker
4600*5e7646d2SAndroid Build Coastguard Worker /*
4601*5e7646d2SAndroid Build Coastguard Worker * Open the destination (if possible) and set the default options...
4602*5e7646d2SAndroid Build Coastguard Worker */
4603*5e7646d2SAndroid Build Coastguard Worker
4604*5e7646d2SAndroid Build Coastguard Worker num_defaults = 0;
4605*5e7646d2SAndroid Build Coastguard Worker defaults = NULL;
4606*5e7646d2SAndroid Build Coastguard Worker cups_protocol[0] = '\0';
4607*5e7646d2SAndroid Build Coastguard Worker
4608*5e7646d2SAndroid Build Coastguard Worker if ((dst = cupsFileOpen(to, "rb")) != NULL)
4609*5e7646d2SAndroid Build Coastguard Worker {
4610*5e7646d2SAndroid Build Coastguard Worker /*
4611*5e7646d2SAndroid Build Coastguard Worker * Read all of the default lines from the old PPD...
4612*5e7646d2SAndroid Build Coastguard Worker */
4613*5e7646d2SAndroid Build Coastguard Worker
4614*5e7646d2SAndroid Build Coastguard Worker while (cupsFileGets(dst, buffer, sizeof(buffer)))
4615*5e7646d2SAndroid Build Coastguard Worker if (!strncmp(buffer, "*Default", 8))
4616*5e7646d2SAndroid Build Coastguard Worker {
4617*5e7646d2SAndroid Build Coastguard Worker /*
4618*5e7646d2SAndroid Build Coastguard Worker * Add the default option...
4619*5e7646d2SAndroid Build Coastguard Worker */
4620*5e7646d2SAndroid Build Coastguard Worker
4621*5e7646d2SAndroid Build Coastguard Worker if (!ppd_parse_line(buffer, option, sizeof(option),
4622*5e7646d2SAndroid Build Coastguard Worker choice, sizeof(choice)))
4623*5e7646d2SAndroid Build Coastguard Worker {
4624*5e7646d2SAndroid Build Coastguard Worker ppd_option_t *ppdo; /* PPD option */
4625*5e7646d2SAndroid Build Coastguard Worker
4626*5e7646d2SAndroid Build Coastguard Worker
4627*5e7646d2SAndroid Build Coastguard Worker /*
4628*5e7646d2SAndroid Build Coastguard Worker * Only add the default if the default hasn't already been
4629*5e7646d2SAndroid Build Coastguard Worker * set and the choice exists in the new PPD...
4630*5e7646d2SAndroid Build Coastguard Worker */
4631*5e7646d2SAndroid Build Coastguard Worker
4632*5e7646d2SAndroid Build Coastguard Worker if (!cupsGetOption(option, num_defaults, defaults) &&
4633*5e7646d2SAndroid Build Coastguard Worker (ppdo = ppdFindOption(ppd, option)) != NULL &&
4634*5e7646d2SAndroid Build Coastguard Worker ppdFindChoice(ppdo, choice))
4635*5e7646d2SAndroid Build Coastguard Worker num_defaults = cupsAddOption(option, choice, num_defaults,
4636*5e7646d2SAndroid Build Coastguard Worker &defaults);
4637*5e7646d2SAndroid Build Coastguard Worker }
4638*5e7646d2SAndroid Build Coastguard Worker }
4639*5e7646d2SAndroid Build Coastguard Worker else if (!strncmp(buffer, "*cupsProtocol:", 14))
4640*5e7646d2SAndroid Build Coastguard Worker strlcpy(cups_protocol, buffer, sizeof(cups_protocol));
4641*5e7646d2SAndroid Build Coastguard Worker
4642*5e7646d2SAndroid Build Coastguard Worker cupsFileClose(dst);
4643*5e7646d2SAndroid Build Coastguard Worker }
4644*5e7646d2SAndroid Build Coastguard Worker else if ((size = ppdPageSize(ppd, DefaultPaperSize)) != NULL)
4645*5e7646d2SAndroid Build Coastguard Worker {
4646*5e7646d2SAndroid Build Coastguard Worker /*
4647*5e7646d2SAndroid Build Coastguard Worker * Add the default media sizes...
4648*5e7646d2SAndroid Build Coastguard Worker */
4649*5e7646d2SAndroid Build Coastguard Worker
4650*5e7646d2SAndroid Build Coastguard Worker num_defaults = cupsAddOption("PageSize", size->name,
4651*5e7646d2SAndroid Build Coastguard Worker num_defaults, &defaults);
4652*5e7646d2SAndroid Build Coastguard Worker num_defaults = cupsAddOption("PageRegion", size->name,
4653*5e7646d2SAndroid Build Coastguard Worker num_defaults, &defaults);
4654*5e7646d2SAndroid Build Coastguard Worker num_defaults = cupsAddOption("PaperDimension", size->name,
4655*5e7646d2SAndroid Build Coastguard Worker num_defaults, &defaults);
4656*5e7646d2SAndroid Build Coastguard Worker num_defaults = cupsAddOption("ImageableArea", size->name,
4657*5e7646d2SAndroid Build Coastguard Worker num_defaults, &defaults);
4658*5e7646d2SAndroid Build Coastguard Worker }
4659*5e7646d2SAndroid Build Coastguard Worker
4660*5e7646d2SAndroid Build Coastguard Worker ppdClose(ppd);
4661*5e7646d2SAndroid Build Coastguard Worker
4662*5e7646d2SAndroid Build Coastguard Worker /*
4663*5e7646d2SAndroid Build Coastguard Worker * Open the destination file for a copy...
4664*5e7646d2SAndroid Build Coastguard Worker */
4665*5e7646d2SAndroid Build Coastguard Worker
4666*5e7646d2SAndroid Build Coastguard Worker if ((dst = cupsdCreateConfFile(to, ConfigFilePerm)) == NULL)
4667*5e7646d2SAndroid Build Coastguard Worker {
4668*5e7646d2SAndroid Build Coastguard Worker cupsFreeOptions(num_defaults, defaults);
4669*5e7646d2SAndroid Build Coastguard Worker cupsFileClose(src);
4670*5e7646d2SAndroid Build Coastguard Worker unlink(tempfile);
4671*5e7646d2SAndroid Build Coastguard Worker return (-1);
4672*5e7646d2SAndroid Build Coastguard Worker }
4673*5e7646d2SAndroid Build Coastguard Worker
4674*5e7646d2SAndroid Build Coastguard Worker /*
4675*5e7646d2SAndroid Build Coastguard Worker * Copy the source file to the destination...
4676*5e7646d2SAndroid Build Coastguard Worker */
4677*5e7646d2SAndroid Build Coastguard Worker
4678*5e7646d2SAndroid Build Coastguard Worker cupsFileRewind(src);
4679*5e7646d2SAndroid Build Coastguard Worker
4680*5e7646d2SAndroid Build Coastguard Worker while (cupsFileGets(src, buffer, sizeof(buffer)))
4681*5e7646d2SAndroid Build Coastguard Worker {
4682*5e7646d2SAndroid Build Coastguard Worker if (!strncmp(buffer, "*Default", 8))
4683*5e7646d2SAndroid Build Coastguard Worker {
4684*5e7646d2SAndroid Build Coastguard Worker /*
4685*5e7646d2SAndroid Build Coastguard Worker * Check for an previous default option choice...
4686*5e7646d2SAndroid Build Coastguard Worker */
4687*5e7646d2SAndroid Build Coastguard Worker
4688*5e7646d2SAndroid Build Coastguard Worker if (!ppd_parse_line(buffer, option, sizeof(option),
4689*5e7646d2SAndroid Build Coastguard Worker choice, sizeof(choice)))
4690*5e7646d2SAndroid Build Coastguard Worker {
4691*5e7646d2SAndroid Build Coastguard Worker const char *val; /* Default option value */
4692*5e7646d2SAndroid Build Coastguard Worker
4693*5e7646d2SAndroid Build Coastguard Worker
4694*5e7646d2SAndroid Build Coastguard Worker if ((val = cupsGetOption(option, num_defaults, defaults)) != NULL)
4695*5e7646d2SAndroid Build Coastguard Worker {
4696*5e7646d2SAndroid Build Coastguard Worker /*
4697*5e7646d2SAndroid Build Coastguard Worker * Substitute the previous choice...
4698*5e7646d2SAndroid Build Coastguard Worker */
4699*5e7646d2SAndroid Build Coastguard Worker
4700*5e7646d2SAndroid Build Coastguard Worker snprintf(buffer, sizeof(buffer), "*Default%s: %s", option, val);
4701*5e7646d2SAndroid Build Coastguard Worker }
4702*5e7646d2SAndroid Build Coastguard Worker }
4703*5e7646d2SAndroid Build Coastguard Worker }
4704*5e7646d2SAndroid Build Coastguard Worker
4705*5e7646d2SAndroid Build Coastguard Worker cupsFilePrintf(dst, "%s\n", buffer);
4706*5e7646d2SAndroid Build Coastguard Worker }
4707*5e7646d2SAndroid Build Coastguard Worker
4708*5e7646d2SAndroid Build Coastguard Worker if (cups_protocol[0])
4709*5e7646d2SAndroid Build Coastguard Worker cupsFilePrintf(dst, "%s\n", cups_protocol);
4710*5e7646d2SAndroid Build Coastguard Worker
4711*5e7646d2SAndroid Build Coastguard Worker cupsFreeOptions(num_defaults, defaults);
4712*5e7646d2SAndroid Build Coastguard Worker
4713*5e7646d2SAndroid Build Coastguard Worker /*
4714*5e7646d2SAndroid Build Coastguard Worker * Close both files and return...
4715*5e7646d2SAndroid Build Coastguard Worker */
4716*5e7646d2SAndroid Build Coastguard Worker
4717*5e7646d2SAndroid Build Coastguard Worker cupsFileClose(src);
4718*5e7646d2SAndroid Build Coastguard Worker
4719*5e7646d2SAndroid Build Coastguard Worker unlink(tempfile);
4720*5e7646d2SAndroid Build Coastguard Worker
4721*5e7646d2SAndroid Build Coastguard Worker return (cupsdCloseCreatedConfFile(dst, to));
4722*5e7646d2SAndroid Build Coastguard Worker }
4723*5e7646d2SAndroid Build Coastguard Worker
4724*5e7646d2SAndroid Build Coastguard Worker
4725*5e7646d2SAndroid Build Coastguard Worker /*
4726*5e7646d2SAndroid Build Coastguard Worker * 'copy_job_attrs()' - Copy job attributes.
4727*5e7646d2SAndroid Build Coastguard Worker */
4728*5e7646d2SAndroid Build Coastguard Worker
4729*5e7646d2SAndroid Build Coastguard Worker static void
copy_job_attrs(cupsd_client_t * con,cupsd_job_t * job,cups_array_t * ra,cups_array_t * exclude)4730*5e7646d2SAndroid Build Coastguard Worker copy_job_attrs(cupsd_client_t *con, /* I - Client connection */
4731*5e7646d2SAndroid Build Coastguard Worker cupsd_job_t *job, /* I - Job */
4732*5e7646d2SAndroid Build Coastguard Worker cups_array_t *ra, /* I - Requested attributes array */
4733*5e7646d2SAndroid Build Coastguard Worker cups_array_t *exclude) /* I - Private attributes array */
4734*5e7646d2SAndroid Build Coastguard Worker {
4735*5e7646d2SAndroid Build Coastguard Worker char job_uri[HTTP_MAX_URI]; /* Job URI */
4736*5e7646d2SAndroid Build Coastguard Worker
4737*5e7646d2SAndroid Build Coastguard Worker
4738*5e7646d2SAndroid Build Coastguard Worker /*
4739*5e7646d2SAndroid Build Coastguard Worker * Send the requested attributes for each job...
4740*5e7646d2SAndroid Build Coastguard Worker */
4741*5e7646d2SAndroid Build Coastguard Worker
4742*5e7646d2SAndroid Build Coastguard Worker if (!cupsArrayFind(exclude, "all"))
4743*5e7646d2SAndroid Build Coastguard Worker {
4744*5e7646d2SAndroid Build Coastguard Worker if ((!exclude || !cupsArrayFind(exclude, "number-of-documents")) &&
4745*5e7646d2SAndroid Build Coastguard Worker (!ra || cupsArrayFind(ra, "number-of-documents")))
4746*5e7646d2SAndroid Build Coastguard Worker ippAddInteger(con->response, IPP_TAG_JOB, IPP_TAG_INTEGER,
4747*5e7646d2SAndroid Build Coastguard Worker "number-of-documents", job->num_files);
4748*5e7646d2SAndroid Build Coastguard Worker
4749*5e7646d2SAndroid Build Coastguard Worker if ((!exclude || !cupsArrayFind(exclude, "job-media-progress")) &&
4750*5e7646d2SAndroid Build Coastguard Worker (!ra || cupsArrayFind(ra, "job-media-progress")))
4751*5e7646d2SAndroid Build Coastguard Worker ippAddInteger(con->response, IPP_TAG_JOB, IPP_TAG_INTEGER,
4752*5e7646d2SAndroid Build Coastguard Worker "job-media-progress", job->progress);
4753*5e7646d2SAndroid Build Coastguard Worker
4754*5e7646d2SAndroid Build Coastguard Worker if ((!exclude || !cupsArrayFind(exclude, "job-more-info")) &&
4755*5e7646d2SAndroid Build Coastguard Worker (!ra || cupsArrayFind(ra, "job-more-info")))
4756*5e7646d2SAndroid Build Coastguard Worker {
4757*5e7646d2SAndroid Build Coastguard Worker httpAssembleURIf(HTTP_URI_CODING_ALL, job_uri, sizeof(job_uri), "http",
4758*5e7646d2SAndroid Build Coastguard Worker NULL, con->clientname, con->clientport, "/jobs/%d",
4759*5e7646d2SAndroid Build Coastguard Worker job->id);
4760*5e7646d2SAndroid Build Coastguard Worker ippAddString(con->response, IPP_TAG_JOB, IPP_TAG_URI,
4761*5e7646d2SAndroid Build Coastguard Worker "job-more-info", NULL, job_uri);
4762*5e7646d2SAndroid Build Coastguard Worker }
4763*5e7646d2SAndroid Build Coastguard Worker
4764*5e7646d2SAndroid Build Coastguard Worker if (job->state_value > IPP_JOB_PROCESSING &&
4765*5e7646d2SAndroid Build Coastguard Worker (!exclude || !cupsArrayFind(exclude, "job-preserved")) &&
4766*5e7646d2SAndroid Build Coastguard Worker (!ra || cupsArrayFind(ra, "job-preserved")))
4767*5e7646d2SAndroid Build Coastguard Worker ippAddBoolean(con->response, IPP_TAG_JOB, "job-preserved",
4768*5e7646d2SAndroid Build Coastguard Worker job->num_files > 0);
4769*5e7646d2SAndroid Build Coastguard Worker
4770*5e7646d2SAndroid Build Coastguard Worker if ((!exclude || !cupsArrayFind(exclude, "job-printer-up-time")) &&
4771*5e7646d2SAndroid Build Coastguard Worker (!ra || cupsArrayFind(ra, "job-printer-up-time")))
4772*5e7646d2SAndroid Build Coastguard Worker ippAddInteger(con->response, IPP_TAG_JOB, IPP_TAG_INTEGER,
4773*5e7646d2SAndroid Build Coastguard Worker "job-printer-up-time", time(NULL));
4774*5e7646d2SAndroid Build Coastguard Worker }
4775*5e7646d2SAndroid Build Coastguard Worker
4776*5e7646d2SAndroid Build Coastguard Worker if (!ra || cupsArrayFind(ra, "job-printer-uri"))
4777*5e7646d2SAndroid Build Coastguard Worker {
4778*5e7646d2SAndroid Build Coastguard Worker httpAssembleURIf(HTTP_URI_CODING_ALL, job_uri, sizeof(job_uri), "ipp", NULL,
4779*5e7646d2SAndroid Build Coastguard Worker con->clientname, con->clientport,
4780*5e7646d2SAndroid Build Coastguard Worker (job->dtype & CUPS_PRINTER_CLASS) ? "/classes/%s" :
4781*5e7646d2SAndroid Build Coastguard Worker "/printers/%s",
4782*5e7646d2SAndroid Build Coastguard Worker job->dest);
4783*5e7646d2SAndroid Build Coastguard Worker ippAddString(con->response, IPP_TAG_JOB, IPP_TAG_URI,
4784*5e7646d2SAndroid Build Coastguard Worker "job-printer-uri", NULL, job_uri);
4785*5e7646d2SAndroid Build Coastguard Worker }
4786*5e7646d2SAndroid Build Coastguard Worker
4787*5e7646d2SAndroid Build Coastguard Worker if (!ra || cupsArrayFind(ra, "job-uri"))
4788*5e7646d2SAndroid Build Coastguard Worker {
4789*5e7646d2SAndroid Build Coastguard Worker httpAssembleURIf(HTTP_URI_CODING_ALL, job_uri, sizeof(job_uri), "ipp", NULL,
4790*5e7646d2SAndroid Build Coastguard Worker con->clientname, con->clientport, "/jobs/%d",
4791*5e7646d2SAndroid Build Coastguard Worker job->id);
4792*5e7646d2SAndroid Build Coastguard Worker ippAddString(con->response, IPP_TAG_JOB, IPP_TAG_URI,
4793*5e7646d2SAndroid Build Coastguard Worker "job-uri", NULL, job_uri);
4794*5e7646d2SAndroid Build Coastguard Worker }
4795*5e7646d2SAndroid Build Coastguard Worker
4796*5e7646d2SAndroid Build Coastguard Worker if (job->attrs)
4797*5e7646d2SAndroid Build Coastguard Worker {
4798*5e7646d2SAndroid Build Coastguard Worker copy_attrs(con->response, job->attrs, ra, IPP_TAG_JOB, 0, exclude);
4799*5e7646d2SAndroid Build Coastguard Worker }
4800*5e7646d2SAndroid Build Coastguard Worker else
4801*5e7646d2SAndroid Build Coastguard Worker {
4802*5e7646d2SAndroid Build Coastguard Worker /*
4803*5e7646d2SAndroid Build Coastguard Worker * Generate attributes from the job structure...
4804*5e7646d2SAndroid Build Coastguard Worker */
4805*5e7646d2SAndroid Build Coastguard Worker
4806*5e7646d2SAndroid Build Coastguard Worker if (job->completed_time && (!ra || cupsArrayFind(ra, "date-time-at-completed")))
4807*5e7646d2SAndroid Build Coastguard Worker ippAddDate(con->response, IPP_TAG_JOB, "date-time-at-completed", ippTimeToDate(job->completed_time));
4808*5e7646d2SAndroid Build Coastguard Worker
4809*5e7646d2SAndroid Build Coastguard Worker if (job->creation_time && (!ra || cupsArrayFind(ra, "date-time-at-creation")))
4810*5e7646d2SAndroid Build Coastguard Worker ippAddDate(con->response, IPP_TAG_JOB, "date-time-at-creation", ippTimeToDate(job->creation_time));
4811*5e7646d2SAndroid Build Coastguard Worker
4812*5e7646d2SAndroid Build Coastguard Worker if (!ra || cupsArrayFind(ra, "job-id"))
4813*5e7646d2SAndroid Build Coastguard Worker ippAddInteger(con->response, IPP_TAG_JOB, IPP_TAG_INTEGER, "job-id", job->id);
4814*5e7646d2SAndroid Build Coastguard Worker
4815*5e7646d2SAndroid Build Coastguard Worker if (!ra || cupsArrayFind(ra, "job-k-octets"))
4816*5e7646d2SAndroid Build Coastguard Worker ippAddInteger(con->response, IPP_TAG_JOB, IPP_TAG_INTEGER, "job-k-octets", job->koctets);
4817*5e7646d2SAndroid Build Coastguard Worker
4818*5e7646d2SAndroid Build Coastguard Worker if (job->name && (!ra || cupsArrayFind(ra, "job-name")))
4819*5e7646d2SAndroid Build Coastguard Worker ippAddString(con->response, IPP_TAG_JOB, IPP_TAG_NAME, "job-name", NULL, job->name);
4820*5e7646d2SAndroid Build Coastguard Worker
4821*5e7646d2SAndroid Build Coastguard Worker if (job->username && (!ra || cupsArrayFind(ra, "job-originating-user-name")))
4822*5e7646d2SAndroid Build Coastguard Worker ippAddString(con->response, IPP_TAG_JOB, IPP_TAG_NAME, "job-originating-user-name", NULL, job->username);
4823*5e7646d2SAndroid Build Coastguard Worker
4824*5e7646d2SAndroid Build Coastguard Worker if (!ra || cupsArrayFind(ra, "job-state"))
4825*5e7646d2SAndroid Build Coastguard Worker ippAddInteger(con->response, IPP_TAG_JOB, IPP_TAG_ENUM, "job-state", (int)job->state_value);
4826*5e7646d2SAndroid Build Coastguard Worker
4827*5e7646d2SAndroid Build Coastguard Worker if (!ra || cupsArrayFind(ra, "job-state-reasons"))
4828*5e7646d2SAndroid Build Coastguard Worker {
4829*5e7646d2SAndroid Build Coastguard Worker switch (job->state_value)
4830*5e7646d2SAndroid Build Coastguard Worker {
4831*5e7646d2SAndroid Build Coastguard Worker default : /* Should never get here for processing, pending, held, or stopped jobs since they don't get unloaded... */
4832*5e7646d2SAndroid Build Coastguard Worker break;
4833*5e7646d2SAndroid Build Coastguard Worker case IPP_JSTATE_ABORTED :
4834*5e7646d2SAndroid Build Coastguard Worker ippAddString(con->response, IPP_TAG_JOB, IPP_TAG_KEYWORD, "job-state-reasons", NULL, "job-aborted-by-system");
4835*5e7646d2SAndroid Build Coastguard Worker break;
4836*5e7646d2SAndroid Build Coastguard Worker case IPP_JSTATE_CANCELED :
4837*5e7646d2SAndroid Build Coastguard Worker ippAddString(con->response, IPP_TAG_JOB, IPP_TAG_KEYWORD, "job-state-reasons", NULL, "job-canceled-by-user");
4838*5e7646d2SAndroid Build Coastguard Worker break;
4839*5e7646d2SAndroid Build Coastguard Worker case IPP_JSTATE_COMPLETED :
4840*5e7646d2SAndroid Build Coastguard Worker ippAddString(con->response, IPP_TAG_JOB, IPP_TAG_KEYWORD, "job-state-reasons", NULL, "job-completed-successfully");
4841*5e7646d2SAndroid Build Coastguard Worker break;
4842*5e7646d2SAndroid Build Coastguard Worker }
4843*5e7646d2SAndroid Build Coastguard Worker }
4844*5e7646d2SAndroid Build Coastguard Worker
4845*5e7646d2SAndroid Build Coastguard Worker if (job->completed_time && (!ra || cupsArrayFind(ra, "time-at-completed")))
4846*5e7646d2SAndroid Build Coastguard Worker ippAddInteger(con->response, IPP_TAG_JOB, IPP_TAG_INTEGER, "time-at-completed", (int)job->completed_time);
4847*5e7646d2SAndroid Build Coastguard Worker
4848*5e7646d2SAndroid Build Coastguard Worker if (job->creation_time && (!ra || cupsArrayFind(ra, "time-at-creation")))
4849*5e7646d2SAndroid Build Coastguard Worker ippAddInteger(con->response, IPP_TAG_JOB, IPP_TAG_INTEGER, "time-at-creation", (int)job->creation_time);
4850*5e7646d2SAndroid Build Coastguard Worker }
4851*5e7646d2SAndroid Build Coastguard Worker }
4852*5e7646d2SAndroid Build Coastguard Worker
4853*5e7646d2SAndroid Build Coastguard Worker
4854*5e7646d2SAndroid Build Coastguard Worker /*
4855*5e7646d2SAndroid Build Coastguard Worker * 'copy_printer_attrs()' - Copy printer attributes.
4856*5e7646d2SAndroid Build Coastguard Worker */
4857*5e7646d2SAndroid Build Coastguard Worker
4858*5e7646d2SAndroid Build Coastguard Worker static void
copy_printer_attrs(cupsd_client_t * con,cupsd_printer_t * printer,cups_array_t * ra)4859*5e7646d2SAndroid Build Coastguard Worker copy_printer_attrs(
4860*5e7646d2SAndroid Build Coastguard Worker cupsd_client_t *con, /* I - Client connection */
4861*5e7646d2SAndroid Build Coastguard Worker cupsd_printer_t *printer, /* I - Printer */
4862*5e7646d2SAndroid Build Coastguard Worker cups_array_t *ra) /* I - Requested attributes array */
4863*5e7646d2SAndroid Build Coastguard Worker {
4864*5e7646d2SAndroid Build Coastguard Worker char uri[HTTP_MAX_URI]; /* URI value */
4865*5e7646d2SAndroid Build Coastguard Worker time_t curtime; /* Current time */
4866*5e7646d2SAndroid Build Coastguard Worker int i; /* Looping var */
4867*5e7646d2SAndroid Build Coastguard Worker int is_encrypted = httpIsEncrypted(con->http);
4868*5e7646d2SAndroid Build Coastguard Worker /* Is the connection encrypted? */
4869*5e7646d2SAndroid Build Coastguard Worker
4870*5e7646d2SAndroid Build Coastguard Worker
4871*5e7646d2SAndroid Build Coastguard Worker /*
4872*5e7646d2SAndroid Build Coastguard Worker * Copy the printer attributes to the response using requested-attributes
4873*5e7646d2SAndroid Build Coastguard Worker * and document-format attributes that may be provided by the client.
4874*5e7646d2SAndroid Build Coastguard Worker */
4875*5e7646d2SAndroid Build Coastguard Worker
4876*5e7646d2SAndroid Build Coastguard Worker _cupsRWLockRead(&printer->lock);
4877*5e7646d2SAndroid Build Coastguard Worker
4878*5e7646d2SAndroid Build Coastguard Worker curtime = time(NULL);
4879*5e7646d2SAndroid Build Coastguard Worker
4880*5e7646d2SAndroid Build Coastguard Worker if (!ra || cupsArrayFind(ra, "marker-change-time"))
4881*5e7646d2SAndroid Build Coastguard Worker ippAddInteger(con->response, IPP_TAG_PRINTER, IPP_TAG_INTEGER, "marker-change-time", printer->marker_time);
4882*5e7646d2SAndroid Build Coastguard Worker
4883*5e7646d2SAndroid Build Coastguard Worker if (printer->num_printers > 0 && (!ra || cupsArrayFind(ra, "member-uris")))
4884*5e7646d2SAndroid Build Coastguard Worker {
4885*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *member_uris; /* member-uris attribute */
4886*5e7646d2SAndroid Build Coastguard Worker cupsd_printer_t *p2; /* Printer in class */
4887*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *p2_uri; /* printer-uri-supported for class printer */
4888*5e7646d2SAndroid Build Coastguard Worker
4889*5e7646d2SAndroid Build Coastguard Worker
4890*5e7646d2SAndroid Build Coastguard Worker if ((member_uris = ippAddStrings(con->response, IPP_TAG_PRINTER, IPP_TAG_URI, "member-uris", printer->num_printers, NULL, NULL)) != NULL)
4891*5e7646d2SAndroid Build Coastguard Worker {
4892*5e7646d2SAndroid Build Coastguard Worker for (i = 0; i < printer->num_printers; i ++)
4893*5e7646d2SAndroid Build Coastguard Worker {
4894*5e7646d2SAndroid Build Coastguard Worker p2 = printer->printers[i];
4895*5e7646d2SAndroid Build Coastguard Worker
4896*5e7646d2SAndroid Build Coastguard Worker if ((p2_uri = ippFindAttribute(p2->attrs, "printer-uri-supported", IPP_TAG_URI)) != NULL)
4897*5e7646d2SAndroid Build Coastguard Worker {
4898*5e7646d2SAndroid Build Coastguard Worker member_uris->values[i].string.text = _cupsStrAlloc(p2_uri->values[0].string.text);
4899*5e7646d2SAndroid Build Coastguard Worker }
4900*5e7646d2SAndroid Build Coastguard Worker else
4901*5e7646d2SAndroid Build Coastguard Worker {
4902*5e7646d2SAndroid Build Coastguard Worker httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), is_encrypted ? "ipps" : "ipp", NULL, con->clientname, con->clientport, (p2->type & CUPS_PRINTER_CLASS) ? "/classes/%s" : "/printers/%s", p2->name);
4903*5e7646d2SAndroid Build Coastguard Worker member_uris->values[i].string.text = _cupsStrAlloc(uri);
4904*5e7646d2SAndroid Build Coastguard Worker }
4905*5e7646d2SAndroid Build Coastguard Worker }
4906*5e7646d2SAndroid Build Coastguard Worker }
4907*5e7646d2SAndroid Build Coastguard Worker }
4908*5e7646d2SAndroid Build Coastguard Worker
4909*5e7646d2SAndroid Build Coastguard Worker if (printer->alert && (!ra || cupsArrayFind(ra, "printer-alert")))
4910*5e7646d2SAndroid Build Coastguard Worker ippAddOctetString(con->response, IPP_TAG_PRINTER, "printer-alert", printer->alert, (int)strlen(printer->alert));
4911*5e7646d2SAndroid Build Coastguard Worker
4912*5e7646d2SAndroid Build Coastguard Worker if (printer->alert_description && (!ra || cupsArrayFind(ra, "printer-alert-description")))
4913*5e7646d2SAndroid Build Coastguard Worker ippAddString(con->response, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-alert-description", NULL, printer->alert_description);
4914*5e7646d2SAndroid Build Coastguard Worker
4915*5e7646d2SAndroid Build Coastguard Worker if (!ra || cupsArrayFind(ra, "printer-config-change-date-time"))
4916*5e7646d2SAndroid Build Coastguard Worker ippAddDate(con->response, IPP_TAG_PRINTER, "printer-config-change-date-time", ippTimeToDate(printer->config_time));
4917*5e7646d2SAndroid Build Coastguard Worker
4918*5e7646d2SAndroid Build Coastguard Worker if (!ra || cupsArrayFind(ra, "printer-config-change-time"))
4919*5e7646d2SAndroid Build Coastguard Worker ippAddInteger(con->response, IPP_TAG_PRINTER, IPP_TAG_INTEGER, "printer-config-change-time", printer->config_time);
4920*5e7646d2SAndroid Build Coastguard Worker
4921*5e7646d2SAndroid Build Coastguard Worker if (!ra || cupsArrayFind(ra, "printer-current-time"))
4922*5e7646d2SAndroid Build Coastguard Worker ippAddDate(con->response, IPP_TAG_PRINTER, "printer-current-time", ippTimeToDate(curtime));
4923*5e7646d2SAndroid Build Coastguard Worker
4924*5e7646d2SAndroid Build Coastguard Worker #if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
4925*5e7646d2SAndroid Build Coastguard Worker if (!ra || cupsArrayFind(ra, "printer-dns-sd-name"))
4926*5e7646d2SAndroid Build Coastguard Worker {
4927*5e7646d2SAndroid Build Coastguard Worker if (printer->reg_name)
4928*5e7646d2SAndroid Build Coastguard Worker ippAddString(con->response, IPP_TAG_PRINTER, IPP_TAG_NAME, "printer-dns-sd-name", NULL, printer->reg_name);
4929*5e7646d2SAndroid Build Coastguard Worker else
4930*5e7646d2SAndroid Build Coastguard Worker ippAddInteger(con->response, IPP_TAG_PRINTER, IPP_TAG_NOVALUE, "printer-dns-sd-name", 0);
4931*5e7646d2SAndroid Build Coastguard Worker }
4932*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_DNSSD || HAVE_AVAHI */
4933*5e7646d2SAndroid Build Coastguard Worker
4934*5e7646d2SAndroid Build Coastguard Worker if (!ra || cupsArrayFind(ra, "printer-error-policy"))
4935*5e7646d2SAndroid Build Coastguard Worker ippAddString(con->response, IPP_TAG_PRINTER, IPP_TAG_NAME, "printer-error-policy", NULL, printer->error_policy);
4936*5e7646d2SAndroid Build Coastguard Worker
4937*5e7646d2SAndroid Build Coastguard Worker if (!ra || cupsArrayFind(ra, "printer-error-policy-supported"))
4938*5e7646d2SAndroid Build Coastguard Worker {
4939*5e7646d2SAndroid Build Coastguard Worker static const char * const errors[] =/* printer-error-policy-supported values */
4940*5e7646d2SAndroid Build Coastguard Worker {
4941*5e7646d2SAndroid Build Coastguard Worker "abort-job",
4942*5e7646d2SAndroid Build Coastguard Worker "retry-current-job",
4943*5e7646d2SAndroid Build Coastguard Worker "retry-job",
4944*5e7646d2SAndroid Build Coastguard Worker "stop-printer"
4945*5e7646d2SAndroid Build Coastguard Worker };
4946*5e7646d2SAndroid Build Coastguard Worker
4947*5e7646d2SAndroid Build Coastguard Worker if (printer->type & CUPS_PRINTER_CLASS)
4948*5e7646d2SAndroid Build Coastguard Worker ippAddString(con->response, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_NAME), "printer-error-policy-supported", NULL, "retry-current-job");
4949*5e7646d2SAndroid Build Coastguard Worker else
4950*5e7646d2SAndroid Build Coastguard Worker ippAddStrings(con->response, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_NAME), "printer-error-policy-supported", sizeof(errors) / sizeof(errors[0]), NULL, errors);
4951*5e7646d2SAndroid Build Coastguard Worker }
4952*5e7646d2SAndroid Build Coastguard Worker
4953*5e7646d2SAndroid Build Coastguard Worker if (!ra || cupsArrayFind(ra, "printer-icons"))
4954*5e7646d2SAndroid Build Coastguard Worker {
4955*5e7646d2SAndroid Build Coastguard Worker httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), is_encrypted ? "https" : "http", NULL, con->clientname, con->clientport, "/icons/%s.png", printer->name);
4956*5e7646d2SAndroid Build Coastguard Worker ippAddString(con->response, IPP_TAG_PRINTER, IPP_TAG_URI, "printer-icons", NULL, uri);
4957*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG2, "printer-icons=\"%s\"", uri);
4958*5e7646d2SAndroid Build Coastguard Worker }
4959*5e7646d2SAndroid Build Coastguard Worker
4960*5e7646d2SAndroid Build Coastguard Worker if (!ra || cupsArrayFind(ra, "printer-is-accepting-jobs"))
4961*5e7646d2SAndroid Build Coastguard Worker ippAddBoolean(con->response, IPP_TAG_PRINTER, "printer-is-accepting-jobs", (char)printer->accepting);
4962*5e7646d2SAndroid Build Coastguard Worker
4963*5e7646d2SAndroid Build Coastguard Worker if (!ra || cupsArrayFind(ra, "printer-is-shared"))
4964*5e7646d2SAndroid Build Coastguard Worker ippAddBoolean(con->response, IPP_TAG_PRINTER, "printer-is-shared", (char)printer->shared);
4965*5e7646d2SAndroid Build Coastguard Worker
4966*5e7646d2SAndroid Build Coastguard Worker if (!ra || cupsArrayFind(ra, "printer-is-temporary"))
4967*5e7646d2SAndroid Build Coastguard Worker ippAddBoolean(con->response, IPP_TAG_PRINTER, "printer-is-temporary", (char)printer->temporary);
4968*5e7646d2SAndroid Build Coastguard Worker
4969*5e7646d2SAndroid Build Coastguard Worker if (!ra || cupsArrayFind(ra, "printer-more-info"))
4970*5e7646d2SAndroid Build Coastguard Worker {
4971*5e7646d2SAndroid Build Coastguard Worker httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), is_encrypted ? "https" : "http", NULL, con->clientname, con->clientport, (printer->type & CUPS_PRINTER_CLASS) ? "/classes/%s" : "/printers/%s", printer->name);
4972*5e7646d2SAndroid Build Coastguard Worker ippAddString(con->response, IPP_TAG_PRINTER, IPP_TAG_URI, "printer-more-info", NULL, uri);
4973*5e7646d2SAndroid Build Coastguard Worker }
4974*5e7646d2SAndroid Build Coastguard Worker
4975*5e7646d2SAndroid Build Coastguard Worker if (!ra || cupsArrayFind(ra, "printer-op-policy"))
4976*5e7646d2SAndroid Build Coastguard Worker ippAddString(con->response, IPP_TAG_PRINTER, IPP_TAG_NAME, "printer-op-policy", NULL, printer->op_policy);
4977*5e7646d2SAndroid Build Coastguard Worker
4978*5e7646d2SAndroid Build Coastguard Worker if (!ra || cupsArrayFind(ra, "printer-state"))
4979*5e7646d2SAndroid Build Coastguard Worker ippAddInteger(con->response, IPP_TAG_PRINTER, IPP_TAG_ENUM, "printer-state", (int)printer->state);
4980*5e7646d2SAndroid Build Coastguard Worker
4981*5e7646d2SAndroid Build Coastguard Worker if (!ra || cupsArrayFind(ra, "printer-state-change-date-time"))
4982*5e7646d2SAndroid Build Coastguard Worker ippAddDate(con->response, IPP_TAG_PRINTER, "printer-state-change-date-time", ippTimeToDate(printer->state_time));
4983*5e7646d2SAndroid Build Coastguard Worker
4984*5e7646d2SAndroid Build Coastguard Worker if (!ra || cupsArrayFind(ra, "printer-state-change-time"))
4985*5e7646d2SAndroid Build Coastguard Worker ippAddInteger(con->response, IPP_TAG_PRINTER, IPP_TAG_INTEGER, "printer-state-change-time", printer->state_time);
4986*5e7646d2SAndroid Build Coastguard Worker
4987*5e7646d2SAndroid Build Coastguard Worker if (!ra || cupsArrayFind(ra, "printer-state-message"))
4988*5e7646d2SAndroid Build Coastguard Worker ippAddString(con->response, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-state-message", NULL, printer->state_message);
4989*5e7646d2SAndroid Build Coastguard Worker
4990*5e7646d2SAndroid Build Coastguard Worker if (!ra || cupsArrayFind(ra, "printer-state-reasons"))
4991*5e7646d2SAndroid Build Coastguard Worker add_printer_state_reasons(con, printer);
4992*5e7646d2SAndroid Build Coastguard Worker
4993*5e7646d2SAndroid Build Coastguard Worker if (!ra || cupsArrayFind(ra, "printer-strings-uri"))
4994*5e7646d2SAndroid Build Coastguard Worker {
4995*5e7646d2SAndroid Build Coastguard Worker httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), is_encrypted ? "https" : "http", NULL, con->clientname, con->clientport, "/strings/%s.strings", printer->name);
4996*5e7646d2SAndroid Build Coastguard Worker ippAddString(con->response, IPP_TAG_PRINTER, IPP_TAG_URI, "printer-strings-uri", NULL, uri);
4997*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG2, "printer-strings-uri=\"%s\"", uri);
4998*5e7646d2SAndroid Build Coastguard Worker }
4999*5e7646d2SAndroid Build Coastguard Worker
5000*5e7646d2SAndroid Build Coastguard Worker if (!ra || cupsArrayFind(ra, "printer-type"))
5001*5e7646d2SAndroid Build Coastguard Worker {
5002*5e7646d2SAndroid Build Coastguard Worker cups_ptype_t type; /* printer-type value */
5003*5e7646d2SAndroid Build Coastguard Worker
5004*5e7646d2SAndroid Build Coastguard Worker /*
5005*5e7646d2SAndroid Build Coastguard Worker * Add the CUPS-specific printer-type attribute...
5006*5e7646d2SAndroid Build Coastguard Worker */
5007*5e7646d2SAndroid Build Coastguard Worker
5008*5e7646d2SAndroid Build Coastguard Worker type = printer->type;
5009*5e7646d2SAndroid Build Coastguard Worker
5010*5e7646d2SAndroid Build Coastguard Worker if (printer == DefaultPrinter)
5011*5e7646d2SAndroid Build Coastguard Worker type |= CUPS_PRINTER_DEFAULT;
5012*5e7646d2SAndroid Build Coastguard Worker
5013*5e7646d2SAndroid Build Coastguard Worker if (!printer->accepting)
5014*5e7646d2SAndroid Build Coastguard Worker type |= CUPS_PRINTER_REJECTING;
5015*5e7646d2SAndroid Build Coastguard Worker
5016*5e7646d2SAndroid Build Coastguard Worker if (!printer->shared)
5017*5e7646d2SAndroid Build Coastguard Worker type |= CUPS_PRINTER_NOT_SHARED;
5018*5e7646d2SAndroid Build Coastguard Worker
5019*5e7646d2SAndroid Build Coastguard Worker ippAddInteger(con->response, IPP_TAG_PRINTER, IPP_TAG_ENUM, "printer-type", (int)type);
5020*5e7646d2SAndroid Build Coastguard Worker }
5021*5e7646d2SAndroid Build Coastguard Worker
5022*5e7646d2SAndroid Build Coastguard Worker if (!ra || cupsArrayFind(ra, "printer-up-time"))
5023*5e7646d2SAndroid Build Coastguard Worker ippAddInteger(con->response, IPP_TAG_PRINTER, IPP_TAG_INTEGER, "printer-up-time", curtime);
5024*5e7646d2SAndroid Build Coastguard Worker
5025*5e7646d2SAndroid Build Coastguard Worker if (!ra || cupsArrayFind(ra, "printer-uri-supported"))
5026*5e7646d2SAndroid Build Coastguard Worker {
5027*5e7646d2SAndroid Build Coastguard Worker httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), is_encrypted ? "ipps" : "ipp", NULL, con->clientname, con->clientport, (printer->type & CUPS_PRINTER_CLASS) ? "/classes/%s" : "/printers/%s", printer->name);
5028*5e7646d2SAndroid Build Coastguard Worker ippAddString(con->response, IPP_TAG_PRINTER, IPP_TAG_URI, "printer-uri-supported", NULL, uri);
5029*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG2, "printer-uri-supported=\"%s\"", uri);
5030*5e7646d2SAndroid Build Coastguard Worker }
5031*5e7646d2SAndroid Build Coastguard Worker
5032*5e7646d2SAndroid Build Coastguard Worker if (!ra || cupsArrayFind(ra, "queued-job-count"))
5033*5e7646d2SAndroid Build Coastguard Worker add_queued_job_count(con, printer);
5034*5e7646d2SAndroid Build Coastguard Worker
5035*5e7646d2SAndroid Build Coastguard Worker if (!ra || cupsArrayFind(ra, "uri-security-supported"))
5036*5e7646d2SAndroid Build Coastguard Worker ippAddString(con->response, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "uri-security-supported", NULL, is_encrypted ? "tls" : "none");
5037*5e7646d2SAndroid Build Coastguard Worker
5038*5e7646d2SAndroid Build Coastguard Worker copy_attrs(con->response, printer->attrs, ra, IPP_TAG_ZERO, 0, NULL);
5039*5e7646d2SAndroid Build Coastguard Worker if (printer->ppd_attrs)
5040*5e7646d2SAndroid Build Coastguard Worker copy_attrs(con->response, printer->ppd_attrs, ra, IPP_TAG_ZERO, 0, NULL);
5041*5e7646d2SAndroid Build Coastguard Worker copy_attrs(con->response, CommonData, ra, IPP_TAG_ZERO, IPP_TAG_COPY, NULL);
5042*5e7646d2SAndroid Build Coastguard Worker
5043*5e7646d2SAndroid Build Coastguard Worker _cupsRWUnlock(&printer->lock);
5044*5e7646d2SAndroid Build Coastguard Worker }
5045*5e7646d2SAndroid Build Coastguard Worker
5046*5e7646d2SAndroid Build Coastguard Worker
5047*5e7646d2SAndroid Build Coastguard Worker /*
5048*5e7646d2SAndroid Build Coastguard Worker * 'copy_subscription_attrs()' - Copy subscription attributes.
5049*5e7646d2SAndroid Build Coastguard Worker */
5050*5e7646d2SAndroid Build Coastguard Worker
5051*5e7646d2SAndroid Build Coastguard Worker static void
copy_subscription_attrs(cupsd_client_t * con,cupsd_subscription_t * sub,cups_array_t * ra,cups_array_t * exclude)5052*5e7646d2SAndroid Build Coastguard Worker copy_subscription_attrs(
5053*5e7646d2SAndroid Build Coastguard Worker cupsd_client_t *con, /* I - Client connection */
5054*5e7646d2SAndroid Build Coastguard Worker cupsd_subscription_t *sub, /* I - Subscription */
5055*5e7646d2SAndroid Build Coastguard Worker cups_array_t *ra, /* I - Requested attributes array */
5056*5e7646d2SAndroid Build Coastguard Worker cups_array_t *exclude) /* I - Private attributes array */
5057*5e7646d2SAndroid Build Coastguard Worker {
5058*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *attr; /* Current attribute */
5059*5e7646d2SAndroid Build Coastguard Worker char printer_uri[HTTP_MAX_URI];
5060*5e7646d2SAndroid Build Coastguard Worker /* Printer URI */
5061*5e7646d2SAndroid Build Coastguard Worker int count; /* Number of events */
5062*5e7646d2SAndroid Build Coastguard Worker unsigned mask; /* Current event mask */
5063*5e7646d2SAndroid Build Coastguard Worker const char *name; /* Current event name */
5064*5e7646d2SAndroid Build Coastguard Worker
5065*5e7646d2SAndroid Build Coastguard Worker
5066*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG2,
5067*5e7646d2SAndroid Build Coastguard Worker "copy_subscription_attrs(con=%p, sub=%p, ra=%p, exclude=%p)",
5068*5e7646d2SAndroid Build Coastguard Worker con, sub, ra, exclude);
5069*5e7646d2SAndroid Build Coastguard Worker
5070*5e7646d2SAndroid Build Coastguard Worker /*
5071*5e7646d2SAndroid Build Coastguard Worker * Copy the subscription attributes to the response using the
5072*5e7646d2SAndroid Build Coastguard Worker * requested-attributes attribute that may be provided by the client.
5073*5e7646d2SAndroid Build Coastguard Worker */
5074*5e7646d2SAndroid Build Coastguard Worker
5075*5e7646d2SAndroid Build Coastguard Worker if (!exclude || !cupsArrayFind(exclude, "all"))
5076*5e7646d2SAndroid Build Coastguard Worker {
5077*5e7646d2SAndroid Build Coastguard Worker if ((!exclude || !cupsArrayFind(exclude, "notify-events")) &&
5078*5e7646d2SAndroid Build Coastguard Worker (!ra || cupsArrayFind(ra, "notify-events")))
5079*5e7646d2SAndroid Build Coastguard Worker {
5080*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG2, "copy_subscription_attrs: notify-events");
5081*5e7646d2SAndroid Build Coastguard Worker
5082*5e7646d2SAndroid Build Coastguard Worker if ((name = cupsdEventName((cupsd_eventmask_t)sub->mask)) != NULL)
5083*5e7646d2SAndroid Build Coastguard Worker {
5084*5e7646d2SAndroid Build Coastguard Worker /*
5085*5e7646d2SAndroid Build Coastguard Worker * Simple event list...
5086*5e7646d2SAndroid Build Coastguard Worker */
5087*5e7646d2SAndroid Build Coastguard Worker
5088*5e7646d2SAndroid Build Coastguard Worker ippAddString(con->response, IPP_TAG_SUBSCRIPTION, IPP_CONST_TAG(IPP_TAG_KEYWORD), "notify-events", NULL, name);
5089*5e7646d2SAndroid Build Coastguard Worker }
5090*5e7646d2SAndroid Build Coastguard Worker else
5091*5e7646d2SAndroid Build Coastguard Worker {
5092*5e7646d2SAndroid Build Coastguard Worker /*
5093*5e7646d2SAndroid Build Coastguard Worker * Complex event list...
5094*5e7646d2SAndroid Build Coastguard Worker */
5095*5e7646d2SAndroid Build Coastguard Worker
5096*5e7646d2SAndroid Build Coastguard Worker for (mask = 1, count = 0; mask < CUPSD_EVENT_ALL; mask <<= 1)
5097*5e7646d2SAndroid Build Coastguard Worker if (sub->mask & mask)
5098*5e7646d2SAndroid Build Coastguard Worker count ++;
5099*5e7646d2SAndroid Build Coastguard Worker
5100*5e7646d2SAndroid Build Coastguard Worker attr = ippAddStrings(con->response, IPP_TAG_SUBSCRIPTION, IPP_CONST_TAG(IPP_TAG_KEYWORD), "notify-events", count, NULL, NULL);
5101*5e7646d2SAndroid Build Coastguard Worker
5102*5e7646d2SAndroid Build Coastguard Worker for (mask = 1, count = 0; mask < CUPSD_EVENT_ALL; mask <<= 1)
5103*5e7646d2SAndroid Build Coastguard Worker if (sub->mask & mask)
5104*5e7646d2SAndroid Build Coastguard Worker {
5105*5e7646d2SAndroid Build Coastguard Worker attr->values[count].string.text = (char *)cupsdEventName((cupsd_eventmask_t)mask);
5106*5e7646d2SAndroid Build Coastguard Worker
5107*5e7646d2SAndroid Build Coastguard Worker count ++;
5108*5e7646d2SAndroid Build Coastguard Worker }
5109*5e7646d2SAndroid Build Coastguard Worker }
5110*5e7646d2SAndroid Build Coastguard Worker }
5111*5e7646d2SAndroid Build Coastguard Worker
5112*5e7646d2SAndroid Build Coastguard Worker if ((!exclude || !cupsArrayFind(exclude, "notify-lease-duration")) &&
5113*5e7646d2SAndroid Build Coastguard Worker (!sub->job && (!ra || cupsArrayFind(ra, "notify-lease-duration"))))
5114*5e7646d2SAndroid Build Coastguard Worker ippAddInteger(con->response, IPP_TAG_SUBSCRIPTION, IPP_TAG_INTEGER,
5115*5e7646d2SAndroid Build Coastguard Worker "notify-lease-duration", sub->lease);
5116*5e7646d2SAndroid Build Coastguard Worker
5117*5e7646d2SAndroid Build Coastguard Worker if ((!exclude || !cupsArrayFind(exclude, "notify-recipient-uri")) &&
5118*5e7646d2SAndroid Build Coastguard Worker (sub->recipient && (!ra || cupsArrayFind(ra, "notify-recipient-uri"))))
5119*5e7646d2SAndroid Build Coastguard Worker ippAddString(con->response, IPP_TAG_SUBSCRIPTION, IPP_TAG_URI,
5120*5e7646d2SAndroid Build Coastguard Worker "notify-recipient-uri", NULL, sub->recipient);
5121*5e7646d2SAndroid Build Coastguard Worker else if ((!exclude || !cupsArrayFind(exclude, "notify-pull-method")) &&
5122*5e7646d2SAndroid Build Coastguard Worker (!ra || cupsArrayFind(ra, "notify-pull-method")))
5123*5e7646d2SAndroid Build Coastguard Worker ippAddString(con->response, IPP_TAG_SUBSCRIPTION, IPP_TAG_KEYWORD,
5124*5e7646d2SAndroid Build Coastguard Worker "notify-pull-method", NULL, "ippget");
5125*5e7646d2SAndroid Build Coastguard Worker
5126*5e7646d2SAndroid Build Coastguard Worker if ((!exclude || !cupsArrayFind(exclude, "notify-subscriber-user-name")) &&
5127*5e7646d2SAndroid Build Coastguard Worker (!ra || cupsArrayFind(ra, "notify-subscriber-user-name")))
5128*5e7646d2SAndroid Build Coastguard Worker ippAddString(con->response, IPP_TAG_SUBSCRIPTION, IPP_TAG_NAME,
5129*5e7646d2SAndroid Build Coastguard Worker "notify-subscriber-user-name", NULL, sub->owner);
5130*5e7646d2SAndroid Build Coastguard Worker
5131*5e7646d2SAndroid Build Coastguard Worker if ((!exclude || !cupsArrayFind(exclude, "notify-time-interval")) &&
5132*5e7646d2SAndroid Build Coastguard Worker (!ra || cupsArrayFind(ra, "notify-time-interval")))
5133*5e7646d2SAndroid Build Coastguard Worker ippAddInteger(con->response, IPP_TAG_SUBSCRIPTION, IPP_TAG_INTEGER,
5134*5e7646d2SAndroid Build Coastguard Worker "notify-time-interval", sub->interval);
5135*5e7646d2SAndroid Build Coastguard Worker
5136*5e7646d2SAndroid Build Coastguard Worker if (sub->user_data_len > 0 &&
5137*5e7646d2SAndroid Build Coastguard Worker (!exclude || !cupsArrayFind(exclude, "notify-user-data")) &&
5138*5e7646d2SAndroid Build Coastguard Worker (!ra || cupsArrayFind(ra, "notify-user-data")))
5139*5e7646d2SAndroid Build Coastguard Worker ippAddOctetString(con->response, IPP_TAG_SUBSCRIPTION, "notify-user-data",
5140*5e7646d2SAndroid Build Coastguard Worker sub->user_data, sub->user_data_len);
5141*5e7646d2SAndroid Build Coastguard Worker }
5142*5e7646d2SAndroid Build Coastguard Worker
5143*5e7646d2SAndroid Build Coastguard Worker if (sub->job && (!ra || cupsArrayFind(ra, "notify-job-id")))
5144*5e7646d2SAndroid Build Coastguard Worker ippAddInteger(con->response, IPP_TAG_SUBSCRIPTION, IPP_TAG_INTEGER,
5145*5e7646d2SAndroid Build Coastguard Worker "notify-job-id", sub->job->id);
5146*5e7646d2SAndroid Build Coastguard Worker
5147*5e7646d2SAndroid Build Coastguard Worker if (sub->dest && (!ra || cupsArrayFind(ra, "notify-printer-uri")))
5148*5e7646d2SAndroid Build Coastguard Worker {
5149*5e7646d2SAndroid Build Coastguard Worker httpAssembleURIf(HTTP_URI_CODING_ALL, printer_uri, sizeof(printer_uri),
5150*5e7646d2SAndroid Build Coastguard Worker "ipp", NULL, con->clientname, con->clientport,
5151*5e7646d2SAndroid Build Coastguard Worker "/printers/%s", sub->dest->name);
5152*5e7646d2SAndroid Build Coastguard Worker ippAddString(con->response, IPP_TAG_SUBSCRIPTION, IPP_TAG_URI,
5153*5e7646d2SAndroid Build Coastguard Worker "notify-printer-uri", NULL, printer_uri);
5154*5e7646d2SAndroid Build Coastguard Worker }
5155*5e7646d2SAndroid Build Coastguard Worker
5156*5e7646d2SAndroid Build Coastguard Worker if (!ra || cupsArrayFind(ra, "notify-subscription-id"))
5157*5e7646d2SAndroid Build Coastguard Worker ippAddInteger(con->response, IPP_TAG_SUBSCRIPTION, IPP_TAG_INTEGER,
5158*5e7646d2SAndroid Build Coastguard Worker "notify-subscription-id", sub->id);
5159*5e7646d2SAndroid Build Coastguard Worker }
5160*5e7646d2SAndroid Build Coastguard Worker
5161*5e7646d2SAndroid Build Coastguard Worker
5162*5e7646d2SAndroid Build Coastguard Worker /*
5163*5e7646d2SAndroid Build Coastguard Worker * 'create_job()' - Print a file to a printer or class.
5164*5e7646d2SAndroid Build Coastguard Worker */
5165*5e7646d2SAndroid Build Coastguard Worker
5166*5e7646d2SAndroid Build Coastguard Worker static void
create_job(cupsd_client_t * con,ipp_attribute_t * uri)5167*5e7646d2SAndroid Build Coastguard Worker create_job(cupsd_client_t *con, /* I - Client connection */
5168*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *uri) /* I - Printer URI */
5169*5e7646d2SAndroid Build Coastguard Worker {
5170*5e7646d2SAndroid Build Coastguard Worker int i; /* Looping var */
5171*5e7646d2SAndroid Build Coastguard Worker cupsd_printer_t *printer; /* Printer */
5172*5e7646d2SAndroid Build Coastguard Worker cupsd_job_t *job; /* New job */
5173*5e7646d2SAndroid Build Coastguard Worker static const char * const forbidden_attrs[] =
5174*5e7646d2SAndroid Build Coastguard Worker { /* List of forbidden attributes */
5175*5e7646d2SAndroid Build Coastguard Worker "compression",
5176*5e7646d2SAndroid Build Coastguard Worker "document-format",
5177*5e7646d2SAndroid Build Coastguard Worker "document-name",
5178*5e7646d2SAndroid Build Coastguard Worker "document-natural-language"
5179*5e7646d2SAndroid Build Coastguard Worker };
5180*5e7646d2SAndroid Build Coastguard Worker
5181*5e7646d2SAndroid Build Coastguard Worker
5182*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG2, "create_job(%p[%d], %s)", con,
5183*5e7646d2SAndroid Build Coastguard Worker con->number, uri->values[0].string.text);
5184*5e7646d2SAndroid Build Coastguard Worker
5185*5e7646d2SAndroid Build Coastguard Worker /*
5186*5e7646d2SAndroid Build Coastguard Worker * Is the destination valid?
5187*5e7646d2SAndroid Build Coastguard Worker */
5188*5e7646d2SAndroid Build Coastguard Worker
5189*5e7646d2SAndroid Build Coastguard Worker if (!cupsdValidateDest(uri->values[0].string.text, NULL, &printer))
5190*5e7646d2SAndroid Build Coastguard Worker {
5191*5e7646d2SAndroid Build Coastguard Worker /*
5192*5e7646d2SAndroid Build Coastguard Worker * Bad URI...
5193*5e7646d2SAndroid Build Coastguard Worker */
5194*5e7646d2SAndroid Build Coastguard Worker
5195*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_NOT_FOUND,
5196*5e7646d2SAndroid Build Coastguard Worker _("The printer or class does not exist."));
5197*5e7646d2SAndroid Build Coastguard Worker return;
5198*5e7646d2SAndroid Build Coastguard Worker }
5199*5e7646d2SAndroid Build Coastguard Worker
5200*5e7646d2SAndroid Build Coastguard Worker /*
5201*5e7646d2SAndroid Build Coastguard Worker * Check for invalid Create-Job attributes and log a warning or error depending
5202*5e7646d2SAndroid Build Coastguard Worker * on whether cupsd is running in "strict conformance" mode...
5203*5e7646d2SAndroid Build Coastguard Worker */
5204*5e7646d2SAndroid Build Coastguard Worker
5205*5e7646d2SAndroid Build Coastguard Worker for (i = 0;
5206*5e7646d2SAndroid Build Coastguard Worker i < (int)(sizeof(forbidden_attrs) / sizeof(forbidden_attrs[0]));
5207*5e7646d2SAndroid Build Coastguard Worker i ++)
5208*5e7646d2SAndroid Build Coastguard Worker if (ippFindAttribute(con->request, forbidden_attrs[i], IPP_TAG_ZERO))
5209*5e7646d2SAndroid Build Coastguard Worker {
5210*5e7646d2SAndroid Build Coastguard Worker if (StrictConformance)
5211*5e7646d2SAndroid Build Coastguard Worker {
5212*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_BAD_REQUEST,
5213*5e7646d2SAndroid Build Coastguard Worker _("The '%s' operation attribute cannot be supplied in a "
5214*5e7646d2SAndroid Build Coastguard Worker "Create-Job request."), forbidden_attrs[i]);
5215*5e7646d2SAndroid Build Coastguard Worker return;
5216*5e7646d2SAndroid Build Coastguard Worker }
5217*5e7646d2SAndroid Build Coastguard Worker
5218*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_WARN,
5219*5e7646d2SAndroid Build Coastguard Worker "Unexpected '%s' operation attribute in a Create-Job "
5220*5e7646d2SAndroid Build Coastguard Worker "request.", forbidden_attrs[i]);
5221*5e7646d2SAndroid Build Coastguard Worker }
5222*5e7646d2SAndroid Build Coastguard Worker
5223*5e7646d2SAndroid Build Coastguard Worker /*
5224*5e7646d2SAndroid Build Coastguard Worker * Create the job object...
5225*5e7646d2SAndroid Build Coastguard Worker */
5226*5e7646d2SAndroid Build Coastguard Worker
5227*5e7646d2SAndroid Build Coastguard Worker if ((job = add_job(con, printer, NULL)) == NULL)
5228*5e7646d2SAndroid Build Coastguard Worker return;
5229*5e7646d2SAndroid Build Coastguard Worker
5230*5e7646d2SAndroid Build Coastguard Worker job->pending_timeout = 1;
5231*5e7646d2SAndroid Build Coastguard Worker
5232*5e7646d2SAndroid Build Coastguard Worker /*
5233*5e7646d2SAndroid Build Coastguard Worker * Save and log the job...
5234*5e7646d2SAndroid Build Coastguard Worker */
5235*5e7646d2SAndroid Build Coastguard Worker
5236*5e7646d2SAndroid Build Coastguard Worker cupsdLogJob(job, CUPSD_LOG_INFO, "Queued on \"%s\" by \"%s\".",
5237*5e7646d2SAndroid Build Coastguard Worker job->dest, job->username);
5238*5e7646d2SAndroid Build Coastguard Worker }
5239*5e7646d2SAndroid Build Coastguard Worker
5240*5e7646d2SAndroid Build Coastguard Worker
5241*5e7646d2SAndroid Build Coastguard Worker /*
5242*5e7646d2SAndroid Build Coastguard Worker * 'create_local_bg_thread()' - Background thread for creating a local print queue.
5243*5e7646d2SAndroid Build Coastguard Worker */
5244*5e7646d2SAndroid Build Coastguard Worker
5245*5e7646d2SAndroid Build Coastguard Worker static void * /* O - Exit status */
create_local_bg_thread(cupsd_printer_t * printer)5246*5e7646d2SAndroid Build Coastguard Worker create_local_bg_thread(
5247*5e7646d2SAndroid Build Coastguard Worker cupsd_printer_t *printer) /* I - Printer */
5248*5e7646d2SAndroid Build Coastguard Worker {
5249*5e7646d2SAndroid Build Coastguard Worker cups_file_t *from, /* Source file */
5250*5e7646d2SAndroid Build Coastguard Worker *to; /* Destination file */
5251*5e7646d2SAndroid Build Coastguard Worker char fromppd[1024], /* Source PPD */
5252*5e7646d2SAndroid Build Coastguard Worker toppd[1024], /* Destination PPD */
5253*5e7646d2SAndroid Build Coastguard Worker scheme[32], /* URI scheme */
5254*5e7646d2SAndroid Build Coastguard Worker userpass[256], /* User:pass */
5255*5e7646d2SAndroid Build Coastguard Worker host[256], /* Hostname */
5256*5e7646d2SAndroid Build Coastguard Worker resource[1024], /* Resource path */
5257*5e7646d2SAndroid Build Coastguard Worker line[1024]; /* Line from PPD */
5258*5e7646d2SAndroid Build Coastguard Worker int port; /* Port number */
5259*5e7646d2SAndroid Build Coastguard Worker http_encryption_t encryption; /* Type of encryption to use */
5260*5e7646d2SAndroid Build Coastguard Worker http_t *http; /* Connection to printer */
5261*5e7646d2SAndroid Build Coastguard Worker ipp_t *request, /* Request to printer */
5262*5e7646d2SAndroid Build Coastguard Worker *response; /* Response from printer */
5263*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *attr; /* Attribute in response */
5264*5e7646d2SAndroid Build Coastguard Worker ipp_status_t status; /* Status code */
5265*5e7646d2SAndroid Build Coastguard Worker static const char * const pattrs[] = /* Printer attributes we need */
5266*5e7646d2SAndroid Build Coastguard Worker {
5267*5e7646d2SAndroid Build Coastguard Worker "all",
5268*5e7646d2SAndroid Build Coastguard Worker "media-col-database"
5269*5e7646d2SAndroid Build Coastguard Worker };
5270*5e7646d2SAndroid Build Coastguard Worker
5271*5e7646d2SAndroid Build Coastguard Worker
5272*5e7646d2SAndroid Build Coastguard Worker /*
5273*5e7646d2SAndroid Build Coastguard Worker * Try connecting to the printer...
5274*5e7646d2SAndroid Build Coastguard Worker */
5275*5e7646d2SAndroid Build Coastguard Worker
5276*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG, "%s: Generating PPD file from \"%s\"...", printer->name, printer->device_uri);
5277*5e7646d2SAndroid Build Coastguard Worker
5278*5e7646d2SAndroid Build Coastguard Worker if (httpSeparateURI(HTTP_URI_CODING_ALL, printer->device_uri, scheme, sizeof(scheme), userpass, sizeof(userpass), host, sizeof(host), &port, resource, sizeof(resource)) < HTTP_URI_STATUS_OK)
5279*5e7646d2SAndroid Build Coastguard Worker {
5280*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_ERROR, "%s: Bad device URI \"%s\".", printer->name, printer->device_uri);
5281*5e7646d2SAndroid Build Coastguard Worker return (NULL);
5282*5e7646d2SAndroid Build Coastguard Worker }
5283*5e7646d2SAndroid Build Coastguard Worker
5284*5e7646d2SAndroid Build Coastguard Worker if (!strcmp(scheme, "ipps") || port == 443)
5285*5e7646d2SAndroid Build Coastguard Worker encryption = HTTP_ENCRYPTION_ALWAYS;
5286*5e7646d2SAndroid Build Coastguard Worker else
5287*5e7646d2SAndroid Build Coastguard Worker encryption = HTTP_ENCRYPTION_IF_REQUESTED;
5288*5e7646d2SAndroid Build Coastguard Worker
5289*5e7646d2SAndroid Build Coastguard Worker if ((http = httpConnect2(host, port, NULL, AF_UNSPEC, encryption, 1, 30000, NULL)) == NULL)
5290*5e7646d2SAndroid Build Coastguard Worker {
5291*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_ERROR, "%s: Unable to connect to %s:%d: %s", printer->name, host, port, cupsLastErrorString());
5292*5e7646d2SAndroid Build Coastguard Worker return (NULL);
5293*5e7646d2SAndroid Build Coastguard Worker }
5294*5e7646d2SAndroid Build Coastguard Worker
5295*5e7646d2SAndroid Build Coastguard Worker /*
5296*5e7646d2SAndroid Build Coastguard Worker * Query the printer for its capabilities...
5297*5e7646d2SAndroid Build Coastguard Worker */
5298*5e7646d2SAndroid Build Coastguard Worker
5299*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG, "%s: Connected to %s:%d, sending Get-Printer-Attributes request...", printer->name, host, port);
5300*5e7646d2SAndroid Build Coastguard Worker
5301*5e7646d2SAndroid Build Coastguard Worker request = ippNewRequest(IPP_OP_GET_PRINTER_ATTRIBUTES);
5302*5e7646d2SAndroid Build Coastguard Worker ippSetVersion(request, 2, 0);
5303*5e7646d2SAndroid Build Coastguard Worker ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, printer->device_uri);
5304*5e7646d2SAndroid Build Coastguard Worker ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, "requested-attributes", (int)(sizeof(pattrs) / sizeof(pattrs[0])), NULL, pattrs);
5305*5e7646d2SAndroid Build Coastguard Worker
5306*5e7646d2SAndroid Build Coastguard Worker response = cupsDoRequest(http, request, resource);
5307*5e7646d2SAndroid Build Coastguard Worker status = cupsLastError();
5308*5e7646d2SAndroid Build Coastguard Worker
5309*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG, "%s: Get-Printer-Attributes returned %s (%s)", printer->name, ippErrorString(cupsLastError()), cupsLastErrorString());
5310*5e7646d2SAndroid Build Coastguard Worker
5311*5e7646d2SAndroid Build Coastguard Worker if (status == IPP_STATUS_ERROR_BAD_REQUEST || status == IPP_STATUS_ERROR_VERSION_NOT_SUPPORTED)
5312*5e7646d2SAndroid Build Coastguard Worker {
5313*5e7646d2SAndroid Build Coastguard Worker /*
5314*5e7646d2SAndroid Build Coastguard Worker * Try request using IPP/1.1, in case we are talking to an old CUPS server or
5315*5e7646d2SAndroid Build Coastguard Worker * printer...
5316*5e7646d2SAndroid Build Coastguard Worker */
5317*5e7646d2SAndroid Build Coastguard Worker
5318*5e7646d2SAndroid Build Coastguard Worker ippDelete(response);
5319*5e7646d2SAndroid Build Coastguard Worker
5320*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG, "%s: Re-sending Get-Printer-Attributes request using IPP/1.1...", printer->name);
5321*5e7646d2SAndroid Build Coastguard Worker
5322*5e7646d2SAndroid Build Coastguard Worker request = ippNewRequest(IPP_OP_GET_PRINTER_ATTRIBUTES);
5323*5e7646d2SAndroid Build Coastguard Worker ippSetVersion(request, 1, 1);
5324*5e7646d2SAndroid Build Coastguard Worker ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, printer->device_uri);
5325*5e7646d2SAndroid Build Coastguard Worker ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, "requested-attributes", NULL, "all");
5326*5e7646d2SAndroid Build Coastguard Worker
5327*5e7646d2SAndroid Build Coastguard Worker response = cupsDoRequest(http, request, resource);
5328*5e7646d2SAndroid Build Coastguard Worker
5329*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG, "%s: IPP/1.1 Get-Printer-Attributes returned %s (%s)", printer->name, ippErrorString(cupsLastError()), cupsLastErrorString());
5330*5e7646d2SAndroid Build Coastguard Worker }
5331*5e7646d2SAndroid Build Coastguard Worker
5332*5e7646d2SAndroid Build Coastguard Worker // TODO: Grab printer icon file...
5333*5e7646d2SAndroid Build Coastguard Worker httpClose(http);
5334*5e7646d2SAndroid Build Coastguard Worker
5335*5e7646d2SAndroid Build Coastguard Worker /*
5336*5e7646d2SAndroid Build Coastguard Worker * Write the PPD for the queue...
5337*5e7646d2SAndroid Build Coastguard Worker */
5338*5e7646d2SAndroid Build Coastguard Worker
5339*5e7646d2SAndroid Build Coastguard Worker if (_ppdCreateFromIPP(fromppd, sizeof(fromppd), response))
5340*5e7646d2SAndroid Build Coastguard Worker {
5341*5e7646d2SAndroid Build Coastguard Worker _cupsRWLockWrite(&printer->lock);
5342*5e7646d2SAndroid Build Coastguard Worker
5343*5e7646d2SAndroid Build Coastguard Worker if ((!printer->info || !*(printer->info)) && (attr = ippFindAttribute(response, "printer-info", IPP_TAG_TEXT)) != NULL)
5344*5e7646d2SAndroid Build Coastguard Worker cupsdSetString(&printer->info, ippGetString(attr, 0, NULL));
5345*5e7646d2SAndroid Build Coastguard Worker
5346*5e7646d2SAndroid Build Coastguard Worker if ((!printer->location || !*(printer->location)) && (attr = ippFindAttribute(response, "printer-location", IPP_TAG_TEXT)) != NULL)
5347*5e7646d2SAndroid Build Coastguard Worker cupsdSetString(&printer->location, ippGetString(attr, 0, NULL));
5348*5e7646d2SAndroid Build Coastguard Worker
5349*5e7646d2SAndroid Build Coastguard Worker if ((!printer->geo_location || !*(printer->geo_location)) && (attr = ippFindAttribute(response, "printer-geo-location", IPP_TAG_URI)) != NULL)
5350*5e7646d2SAndroid Build Coastguard Worker cupsdSetString(&printer->geo_location, ippGetString(attr, 0, NULL));
5351*5e7646d2SAndroid Build Coastguard Worker
5352*5e7646d2SAndroid Build Coastguard Worker _cupsRWUnlock(&printer->lock);
5353*5e7646d2SAndroid Build Coastguard Worker
5354*5e7646d2SAndroid Build Coastguard Worker if ((from = cupsFileOpen(fromppd, "r")) == NULL)
5355*5e7646d2SAndroid Build Coastguard Worker {
5356*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_ERROR, "%s: Unable to read generated PPD: %s", printer->name, strerror(errno));
5357*5e7646d2SAndroid Build Coastguard Worker return (NULL);
5358*5e7646d2SAndroid Build Coastguard Worker }
5359*5e7646d2SAndroid Build Coastguard Worker
5360*5e7646d2SAndroid Build Coastguard Worker snprintf(toppd, sizeof(toppd), "%s/ppd/%s.ppd", ServerRoot, printer->name);
5361*5e7646d2SAndroid Build Coastguard Worker if ((to = cupsdCreateConfFile(toppd, ConfigFilePerm)) == NULL)
5362*5e7646d2SAndroid Build Coastguard Worker {
5363*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_ERROR, "%s: Unable to create PPD for printer: %s", printer->name, strerror(errno));
5364*5e7646d2SAndroid Build Coastguard Worker cupsFileClose(from);
5365*5e7646d2SAndroid Build Coastguard Worker return (NULL);
5366*5e7646d2SAndroid Build Coastguard Worker }
5367*5e7646d2SAndroid Build Coastguard Worker
5368*5e7646d2SAndroid Build Coastguard Worker while (cupsFileGets(from, line, sizeof(line)))
5369*5e7646d2SAndroid Build Coastguard Worker cupsFilePrintf(to, "%s\n", line);
5370*5e7646d2SAndroid Build Coastguard Worker
5371*5e7646d2SAndroid Build Coastguard Worker cupsFileClose(from);
5372*5e7646d2SAndroid Build Coastguard Worker if (!cupsdCloseCreatedConfFile(to, toppd))
5373*5e7646d2SAndroid Build Coastguard Worker {
5374*5e7646d2SAndroid Build Coastguard Worker printer->config_time = time(NULL);
5375*5e7646d2SAndroid Build Coastguard Worker printer->state = IPP_PSTATE_IDLE;
5376*5e7646d2SAndroid Build Coastguard Worker printer->accepting = 1;
5377*5e7646d2SAndroid Build Coastguard Worker
5378*5e7646d2SAndroid Build Coastguard Worker cupsdSetPrinterAttrs(printer);
5379*5e7646d2SAndroid Build Coastguard Worker
5380*5e7646d2SAndroid Build Coastguard Worker cupsdAddEvent(CUPSD_EVENT_PRINTER_CONFIG, printer, NULL, "Printer \"%s\" is now available.", printer->name);
5381*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_INFO, "Printer \"%s\" is now available.", printer->name);
5382*5e7646d2SAndroid Build Coastguard Worker }
5383*5e7646d2SAndroid Build Coastguard Worker }
5384*5e7646d2SAndroid Build Coastguard Worker else
5385*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_ERROR, "%s: PPD creation failed: %s", printer->name, cupsLastErrorString());
5386*5e7646d2SAndroid Build Coastguard Worker
5387*5e7646d2SAndroid Build Coastguard Worker return (NULL);
5388*5e7646d2SAndroid Build Coastguard Worker }
5389*5e7646d2SAndroid Build Coastguard Worker
5390*5e7646d2SAndroid Build Coastguard Worker
5391*5e7646d2SAndroid Build Coastguard Worker /*
5392*5e7646d2SAndroid Build Coastguard Worker * 'create_local_printer()' - Create a local (temporary) print queue.
5393*5e7646d2SAndroid Build Coastguard Worker */
5394*5e7646d2SAndroid Build Coastguard Worker
5395*5e7646d2SAndroid Build Coastguard Worker static void
create_local_printer(cupsd_client_t * con)5396*5e7646d2SAndroid Build Coastguard Worker create_local_printer(
5397*5e7646d2SAndroid Build Coastguard Worker cupsd_client_t *con) /* I - Client connection */
5398*5e7646d2SAndroid Build Coastguard Worker {
5399*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *device_uri, /* device-uri attribute */
5400*5e7646d2SAndroid Build Coastguard Worker *printer_geo_location, /* printer-geo-location attribute */
5401*5e7646d2SAndroid Build Coastguard Worker *printer_info, /* printer-info attribute */
5402*5e7646d2SAndroid Build Coastguard Worker *printer_location, /* printer-location attribute */
5403*5e7646d2SAndroid Build Coastguard Worker *printer_name; /* printer-name attribute */
5404*5e7646d2SAndroid Build Coastguard Worker cupsd_printer_t *printer; /* New printer */
5405*5e7646d2SAndroid Build Coastguard Worker http_status_t status; /* Policy status */
5406*5e7646d2SAndroid Build Coastguard Worker char name[128], /* Sanitized printer name */
5407*5e7646d2SAndroid Build Coastguard Worker *nameptr, /* Pointer into name */
5408*5e7646d2SAndroid Build Coastguard Worker uri[1024]; /* printer-uri-supported value */
5409*5e7646d2SAndroid Build Coastguard Worker const char *ptr; /* Pointer into attribute value */
5410*5e7646d2SAndroid Build Coastguard Worker
5411*5e7646d2SAndroid Build Coastguard Worker
5412*5e7646d2SAndroid Build Coastguard Worker /*
5413*5e7646d2SAndroid Build Coastguard Worker * Require local access to create a local printer...
5414*5e7646d2SAndroid Build Coastguard Worker */
5415*5e7646d2SAndroid Build Coastguard Worker
5416*5e7646d2SAndroid Build Coastguard Worker if (!httpAddrLocalhost(httpGetAddress(con->http)))
5417*5e7646d2SAndroid Build Coastguard Worker {
5418*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_STATUS_ERROR_FORBIDDEN, _("Only local users can create a local printer."));
5419*5e7646d2SAndroid Build Coastguard Worker return;
5420*5e7646d2SAndroid Build Coastguard Worker }
5421*5e7646d2SAndroid Build Coastguard Worker
5422*5e7646d2SAndroid Build Coastguard Worker /*
5423*5e7646d2SAndroid Build Coastguard Worker * Check any other policy limits...
5424*5e7646d2SAndroid Build Coastguard Worker */
5425*5e7646d2SAndroid Build Coastguard Worker
5426*5e7646d2SAndroid Build Coastguard Worker if ((status = cupsdCheckPolicy(DefaultPolicyPtr, con, NULL)) != HTTP_OK)
5427*5e7646d2SAndroid Build Coastguard Worker {
5428*5e7646d2SAndroid Build Coastguard Worker send_http_error(con, status, NULL);
5429*5e7646d2SAndroid Build Coastguard Worker return;
5430*5e7646d2SAndroid Build Coastguard Worker }
5431*5e7646d2SAndroid Build Coastguard Worker
5432*5e7646d2SAndroid Build Coastguard Worker /*
5433*5e7646d2SAndroid Build Coastguard Worker * Grab needed attributes...
5434*5e7646d2SAndroid Build Coastguard Worker */
5435*5e7646d2SAndroid Build Coastguard Worker
5436*5e7646d2SAndroid Build Coastguard Worker if ((printer_name = ippFindAttribute(con->request, "printer-name", IPP_TAG_ZERO)) == NULL || ippGetGroupTag(printer_name) != IPP_TAG_PRINTER || ippGetValueTag(printer_name) != IPP_TAG_NAME)
5437*5e7646d2SAndroid Build Coastguard Worker {
5438*5e7646d2SAndroid Build Coastguard Worker if (!printer_name)
5439*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_STATUS_ERROR_BAD_REQUEST, _("Missing required attribute \"%s\"."), "printer-name");
5440*5e7646d2SAndroid Build Coastguard Worker else if (ippGetGroupTag(printer_name) != IPP_TAG_PRINTER)
5441*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_STATUS_ERROR_BAD_REQUEST, _("Attribute \"%s\" is in the wrong group."), "printer-name");
5442*5e7646d2SAndroid Build Coastguard Worker else
5443*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_STATUS_ERROR_BAD_REQUEST, _("Attribute \"%s\" is the wrong value type."), "printer-name");
5444*5e7646d2SAndroid Build Coastguard Worker
5445*5e7646d2SAndroid Build Coastguard Worker return;
5446*5e7646d2SAndroid Build Coastguard Worker }
5447*5e7646d2SAndroid Build Coastguard Worker
5448*5e7646d2SAndroid Build Coastguard Worker for (nameptr = name, ptr = ippGetString(printer_name, 0, NULL); *ptr && nameptr < (name + sizeof(name) - 1); ptr ++)
5449*5e7646d2SAndroid Build Coastguard Worker {
5450*5e7646d2SAndroid Build Coastguard Worker /*
5451*5e7646d2SAndroid Build Coastguard Worker * Sanitize the printer name...
5452*5e7646d2SAndroid Build Coastguard Worker */
5453*5e7646d2SAndroid Build Coastguard Worker
5454*5e7646d2SAndroid Build Coastguard Worker if (_cups_isalnum(*ptr))
5455*5e7646d2SAndroid Build Coastguard Worker *nameptr++ = *ptr;
5456*5e7646d2SAndroid Build Coastguard Worker else if (nameptr == name || nameptr[-1] != '_')
5457*5e7646d2SAndroid Build Coastguard Worker *nameptr++ = '_';
5458*5e7646d2SAndroid Build Coastguard Worker }
5459*5e7646d2SAndroid Build Coastguard Worker
5460*5e7646d2SAndroid Build Coastguard Worker *nameptr = '\0';
5461*5e7646d2SAndroid Build Coastguard Worker
5462*5e7646d2SAndroid Build Coastguard Worker if ((device_uri = ippFindAttribute(con->request, "device-uri", IPP_TAG_ZERO)) == NULL || ippGetGroupTag(device_uri) != IPP_TAG_PRINTER || ippGetValueTag(device_uri) != IPP_TAG_URI)
5463*5e7646d2SAndroid Build Coastguard Worker {
5464*5e7646d2SAndroid Build Coastguard Worker if (!device_uri)
5465*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_STATUS_ERROR_BAD_REQUEST, _("Missing required attribute \"%s\"."), "device-uri");
5466*5e7646d2SAndroid Build Coastguard Worker else if (ippGetGroupTag(device_uri) != IPP_TAG_PRINTER)
5467*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_STATUS_ERROR_BAD_REQUEST, _("Attribute \"%s\" is in the wrong group."), "device-uri");
5468*5e7646d2SAndroid Build Coastguard Worker else
5469*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_STATUS_ERROR_BAD_REQUEST, _("Attribute \"%s\" is the wrong value type."), "device-uri");
5470*5e7646d2SAndroid Build Coastguard Worker
5471*5e7646d2SAndroid Build Coastguard Worker return;
5472*5e7646d2SAndroid Build Coastguard Worker }
5473*5e7646d2SAndroid Build Coastguard Worker
5474*5e7646d2SAndroid Build Coastguard Worker printer_geo_location = ippFindAttribute(con->request, "printer-geo-location", IPP_TAG_URI);
5475*5e7646d2SAndroid Build Coastguard Worker printer_info = ippFindAttribute(con->request, "printer-info", IPP_TAG_TEXT);
5476*5e7646d2SAndroid Build Coastguard Worker printer_location = ippFindAttribute(con->request, "printer-location", IPP_TAG_TEXT);
5477*5e7646d2SAndroid Build Coastguard Worker
5478*5e7646d2SAndroid Build Coastguard Worker /*
5479*5e7646d2SAndroid Build Coastguard Worker * See if the printer already exists...
5480*5e7646d2SAndroid Build Coastguard Worker */
5481*5e7646d2SAndroid Build Coastguard Worker
5482*5e7646d2SAndroid Build Coastguard Worker if ((printer = cupsdFindDest(name)) != NULL)
5483*5e7646d2SAndroid Build Coastguard Worker {
5484*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_STATUS_ERROR_NOT_POSSIBLE, _("Printer \"%s\" already exists."), name);
5485*5e7646d2SAndroid Build Coastguard Worker goto add_printer_attributes;
5486*5e7646d2SAndroid Build Coastguard Worker }
5487*5e7646d2SAndroid Build Coastguard Worker
5488*5e7646d2SAndroid Build Coastguard Worker /*
5489*5e7646d2SAndroid Build Coastguard Worker * Create the printer...
5490*5e7646d2SAndroid Build Coastguard Worker */
5491*5e7646d2SAndroid Build Coastguard Worker
5492*5e7646d2SAndroid Build Coastguard Worker if ((printer = cupsdAddPrinter(name)) == NULL)
5493*5e7646d2SAndroid Build Coastguard Worker {
5494*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_STATUS_ERROR_INTERNAL, _("Unable to create printer."));
5495*5e7646d2SAndroid Build Coastguard Worker return;
5496*5e7646d2SAndroid Build Coastguard Worker }
5497*5e7646d2SAndroid Build Coastguard Worker
5498*5e7646d2SAndroid Build Coastguard Worker printer->shared = 0;
5499*5e7646d2SAndroid Build Coastguard Worker printer->temporary = 1;
5500*5e7646d2SAndroid Build Coastguard Worker
5501*5e7646d2SAndroid Build Coastguard Worker cupsdSetDeviceURI(printer, ippGetString(device_uri, 0, NULL));
5502*5e7646d2SAndroid Build Coastguard Worker
5503*5e7646d2SAndroid Build Coastguard Worker if (printer_geo_location)
5504*5e7646d2SAndroid Build Coastguard Worker cupsdSetString(&printer->geo_location, ippGetString(printer_geo_location, 0, NULL));
5505*5e7646d2SAndroid Build Coastguard Worker if (printer_info)
5506*5e7646d2SAndroid Build Coastguard Worker cupsdSetString(&printer->info, ippGetString(printer_info, 0, NULL));
5507*5e7646d2SAndroid Build Coastguard Worker if (printer_location)
5508*5e7646d2SAndroid Build Coastguard Worker cupsdSetString(&printer->location, ippGetString(printer_location, 0, NULL));
5509*5e7646d2SAndroid Build Coastguard Worker
5510*5e7646d2SAndroid Build Coastguard Worker cupsdSetPrinterAttrs(printer);
5511*5e7646d2SAndroid Build Coastguard Worker
5512*5e7646d2SAndroid Build Coastguard Worker /*
5513*5e7646d2SAndroid Build Coastguard Worker * Run a background thread to create the PPD...
5514*5e7646d2SAndroid Build Coastguard Worker */
5515*5e7646d2SAndroid Build Coastguard Worker
5516*5e7646d2SAndroid Build Coastguard Worker _cupsThreadCreate((_cups_thread_func_t)create_local_bg_thread, printer);
5517*5e7646d2SAndroid Build Coastguard Worker
5518*5e7646d2SAndroid Build Coastguard Worker /*
5519*5e7646d2SAndroid Build Coastguard Worker * Return printer attributes...
5520*5e7646d2SAndroid Build Coastguard Worker */
5521*5e7646d2SAndroid Build Coastguard Worker
5522*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_STATUS_OK, _("Local printer created."));
5523*5e7646d2SAndroid Build Coastguard Worker
5524*5e7646d2SAndroid Build Coastguard Worker add_printer_attributes:
5525*5e7646d2SAndroid Build Coastguard Worker
5526*5e7646d2SAndroid Build Coastguard Worker ippAddBoolean(con->response, IPP_TAG_PRINTER, "printer-is-accepting-jobs", (char)printer->accepting);
5527*5e7646d2SAndroid Build Coastguard Worker ippAddInteger(con->response, IPP_TAG_PRINTER, IPP_TAG_ENUM, "printer-state", (int)printer->state);
5528*5e7646d2SAndroid Build Coastguard Worker add_printer_state_reasons(con, printer);
5529*5e7646d2SAndroid Build Coastguard Worker
5530*5e7646d2SAndroid Build Coastguard Worker httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), httpIsEncrypted(con->http) ? "ipps" : "ipp", NULL, con->clientname, con->clientport, "/printers/%s", printer->name);
5531*5e7646d2SAndroid Build Coastguard Worker ippAddString(con->response, IPP_TAG_PRINTER, IPP_TAG_URI, "printer-uri-supported", NULL, uri);
5532*5e7646d2SAndroid Build Coastguard Worker }
5533*5e7646d2SAndroid Build Coastguard Worker
5534*5e7646d2SAndroid Build Coastguard Worker
5535*5e7646d2SAndroid Build Coastguard Worker /*
5536*5e7646d2SAndroid Build Coastguard Worker * 'create_requested_array()' - Create an array for the requested-attributes.
5537*5e7646d2SAndroid Build Coastguard Worker */
5538*5e7646d2SAndroid Build Coastguard Worker
5539*5e7646d2SAndroid Build Coastguard Worker static cups_array_t * /* O - Array of attributes or NULL */
create_requested_array(ipp_t * request)5540*5e7646d2SAndroid Build Coastguard Worker create_requested_array(ipp_t *request) /* I - IPP request */
5541*5e7646d2SAndroid Build Coastguard Worker {
5542*5e7646d2SAndroid Build Coastguard Worker cups_array_t *ra; /* Requested attributes array */
5543*5e7646d2SAndroid Build Coastguard Worker
5544*5e7646d2SAndroid Build Coastguard Worker
5545*5e7646d2SAndroid Build Coastguard Worker /*
5546*5e7646d2SAndroid Build Coastguard Worker * Create the array for standard attributes...
5547*5e7646d2SAndroid Build Coastguard Worker */
5548*5e7646d2SAndroid Build Coastguard Worker
5549*5e7646d2SAndroid Build Coastguard Worker ra = ippCreateRequestedArray(request);
5550*5e7646d2SAndroid Build Coastguard Worker
5551*5e7646d2SAndroid Build Coastguard Worker /*
5552*5e7646d2SAndroid Build Coastguard Worker * Add CUPS defaults as needed...
5553*5e7646d2SAndroid Build Coastguard Worker */
5554*5e7646d2SAndroid Build Coastguard Worker
5555*5e7646d2SAndroid Build Coastguard Worker if (cupsArrayFind(ra, "printer-defaults"))
5556*5e7646d2SAndroid Build Coastguard Worker {
5557*5e7646d2SAndroid Build Coastguard Worker /*
5558*5e7646d2SAndroid Build Coastguard Worker * Include user-set defaults...
5559*5e7646d2SAndroid Build Coastguard Worker */
5560*5e7646d2SAndroid Build Coastguard Worker
5561*5e7646d2SAndroid Build Coastguard Worker char *name; /* Option name */
5562*5e7646d2SAndroid Build Coastguard Worker
5563*5e7646d2SAndroid Build Coastguard Worker cupsArrayRemove(ra, "printer-defaults");
5564*5e7646d2SAndroid Build Coastguard Worker
5565*5e7646d2SAndroid Build Coastguard Worker for (name = (char *)cupsArrayFirst(CommonDefaults);
5566*5e7646d2SAndroid Build Coastguard Worker name;
5567*5e7646d2SAndroid Build Coastguard Worker name = (char *)cupsArrayNext(CommonDefaults))
5568*5e7646d2SAndroid Build Coastguard Worker if (!cupsArrayFind(ra, name))
5569*5e7646d2SAndroid Build Coastguard Worker cupsArrayAdd(ra, name);
5570*5e7646d2SAndroid Build Coastguard Worker }
5571*5e7646d2SAndroid Build Coastguard Worker
5572*5e7646d2SAndroid Build Coastguard Worker return (ra);
5573*5e7646d2SAndroid Build Coastguard Worker }
5574*5e7646d2SAndroid Build Coastguard Worker
5575*5e7646d2SAndroid Build Coastguard Worker
5576*5e7646d2SAndroid Build Coastguard Worker /*
5577*5e7646d2SAndroid Build Coastguard Worker * 'create_subscriptions()' - Create one or more notification subscriptions.
5578*5e7646d2SAndroid Build Coastguard Worker */
5579*5e7646d2SAndroid Build Coastguard Worker
5580*5e7646d2SAndroid Build Coastguard Worker static void
create_subscriptions(cupsd_client_t * con,ipp_attribute_t * uri)5581*5e7646d2SAndroid Build Coastguard Worker create_subscriptions(
5582*5e7646d2SAndroid Build Coastguard Worker cupsd_client_t *con, /* I - Client connection */
5583*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *uri) /* I - Printer URI */
5584*5e7646d2SAndroid Build Coastguard Worker {
5585*5e7646d2SAndroid Build Coastguard Worker http_status_t status; /* Policy status */
5586*5e7646d2SAndroid Build Coastguard Worker int i; /* Looping var */
5587*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *attr; /* Current attribute */
5588*5e7646d2SAndroid Build Coastguard Worker cups_ptype_t dtype; /* Destination type (printer/class) */
5589*5e7646d2SAndroid Build Coastguard Worker char scheme[HTTP_MAX_URI],
5590*5e7646d2SAndroid Build Coastguard Worker /* Scheme portion of URI */
5591*5e7646d2SAndroid Build Coastguard Worker userpass[HTTP_MAX_URI],
5592*5e7646d2SAndroid Build Coastguard Worker /* Username portion of URI */
5593*5e7646d2SAndroid Build Coastguard Worker host[HTTP_MAX_URI],
5594*5e7646d2SAndroid Build Coastguard Worker /* Host portion of URI */
5595*5e7646d2SAndroid Build Coastguard Worker resource[HTTP_MAX_URI];
5596*5e7646d2SAndroid Build Coastguard Worker /* Resource portion of URI */
5597*5e7646d2SAndroid Build Coastguard Worker int port; /* Port portion of URI */
5598*5e7646d2SAndroid Build Coastguard Worker cupsd_printer_t *printer; /* Printer/class */
5599*5e7646d2SAndroid Build Coastguard Worker cupsd_job_t *job; /* Job */
5600*5e7646d2SAndroid Build Coastguard Worker int jobid; /* Job ID */
5601*5e7646d2SAndroid Build Coastguard Worker cupsd_subscription_t *sub; /* Subscription object */
5602*5e7646d2SAndroid Build Coastguard Worker const char *username, /* requesting-user-name or
5603*5e7646d2SAndroid Build Coastguard Worker authenticated username */
5604*5e7646d2SAndroid Build Coastguard Worker *recipient, /* notify-recipient-uri */
5605*5e7646d2SAndroid Build Coastguard Worker *pullmethod; /* notify-pull-method */
5606*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *user_data; /* notify-user-data */
5607*5e7646d2SAndroid Build Coastguard Worker int interval, /* notify-time-interval */
5608*5e7646d2SAndroid Build Coastguard Worker lease; /* notify-lease-duration */
5609*5e7646d2SAndroid Build Coastguard Worker unsigned mask; /* notify-events */
5610*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *notify_events,/* notify-events(-default) */
5611*5e7646d2SAndroid Build Coastguard Worker *notify_lease; /* notify-lease-duration(-default) */
5612*5e7646d2SAndroid Build Coastguard Worker
5613*5e7646d2SAndroid Build Coastguard Worker
5614*5e7646d2SAndroid Build Coastguard Worker #ifdef DEBUG
5615*5e7646d2SAndroid Build Coastguard Worker for (attr = con->request->attrs; attr; attr = attr->next)
5616*5e7646d2SAndroid Build Coastguard Worker {
5617*5e7646d2SAndroid Build Coastguard Worker if (attr->group_tag != IPP_TAG_ZERO)
5618*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG2, "g%04x v%04x %s", attr->group_tag,
5619*5e7646d2SAndroid Build Coastguard Worker attr->value_tag, attr->name);
5620*5e7646d2SAndroid Build Coastguard Worker else
5621*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG2, "----SEP----");
5622*5e7646d2SAndroid Build Coastguard Worker }
5623*5e7646d2SAndroid Build Coastguard Worker #endif /* DEBUG */
5624*5e7646d2SAndroid Build Coastguard Worker
5625*5e7646d2SAndroid Build Coastguard Worker /*
5626*5e7646d2SAndroid Build Coastguard Worker * Is the destination valid?
5627*5e7646d2SAndroid Build Coastguard Worker */
5628*5e7646d2SAndroid Build Coastguard Worker
5629*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG, "create_subscriptions(con=%p(%d), uri=\"%s\")", con, con->number, uri->values[0].string.text);
5630*5e7646d2SAndroid Build Coastguard Worker
5631*5e7646d2SAndroid Build Coastguard Worker httpSeparateURI(HTTP_URI_CODING_ALL, uri->values[0].string.text, scheme,
5632*5e7646d2SAndroid Build Coastguard Worker sizeof(scheme), userpass, sizeof(userpass), host,
5633*5e7646d2SAndroid Build Coastguard Worker sizeof(host), &port, resource, sizeof(resource));
5634*5e7646d2SAndroid Build Coastguard Worker
5635*5e7646d2SAndroid Build Coastguard Worker if (!strcmp(resource, "/"))
5636*5e7646d2SAndroid Build Coastguard Worker {
5637*5e7646d2SAndroid Build Coastguard Worker dtype = (cups_ptype_t)0;
5638*5e7646d2SAndroid Build Coastguard Worker printer = NULL;
5639*5e7646d2SAndroid Build Coastguard Worker }
5640*5e7646d2SAndroid Build Coastguard Worker else if (!strncmp(resource, "/printers", 9) && strlen(resource) <= 10)
5641*5e7646d2SAndroid Build Coastguard Worker {
5642*5e7646d2SAndroid Build Coastguard Worker dtype = (cups_ptype_t)0;
5643*5e7646d2SAndroid Build Coastguard Worker printer = NULL;
5644*5e7646d2SAndroid Build Coastguard Worker }
5645*5e7646d2SAndroid Build Coastguard Worker else if (!strncmp(resource, "/classes", 8) && strlen(resource) <= 9)
5646*5e7646d2SAndroid Build Coastguard Worker {
5647*5e7646d2SAndroid Build Coastguard Worker dtype = CUPS_PRINTER_CLASS;
5648*5e7646d2SAndroid Build Coastguard Worker printer = NULL;
5649*5e7646d2SAndroid Build Coastguard Worker }
5650*5e7646d2SAndroid Build Coastguard Worker else if (!cupsdValidateDest(uri->values[0].string.text, &dtype, &printer))
5651*5e7646d2SAndroid Build Coastguard Worker {
5652*5e7646d2SAndroid Build Coastguard Worker /*
5653*5e7646d2SAndroid Build Coastguard Worker * Bad URI...
5654*5e7646d2SAndroid Build Coastguard Worker */
5655*5e7646d2SAndroid Build Coastguard Worker
5656*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_NOT_FOUND,
5657*5e7646d2SAndroid Build Coastguard Worker _("The printer or class does not exist."));
5658*5e7646d2SAndroid Build Coastguard Worker return;
5659*5e7646d2SAndroid Build Coastguard Worker }
5660*5e7646d2SAndroid Build Coastguard Worker
5661*5e7646d2SAndroid Build Coastguard Worker /*
5662*5e7646d2SAndroid Build Coastguard Worker * Check policy...
5663*5e7646d2SAndroid Build Coastguard Worker */
5664*5e7646d2SAndroid Build Coastguard Worker
5665*5e7646d2SAndroid Build Coastguard Worker if (printer)
5666*5e7646d2SAndroid Build Coastguard Worker {
5667*5e7646d2SAndroid Build Coastguard Worker if ((status = cupsdCheckPolicy(printer->op_policy_ptr, con,
5668*5e7646d2SAndroid Build Coastguard Worker NULL)) != HTTP_OK)
5669*5e7646d2SAndroid Build Coastguard Worker {
5670*5e7646d2SAndroid Build Coastguard Worker send_http_error(con, status, printer);
5671*5e7646d2SAndroid Build Coastguard Worker return;
5672*5e7646d2SAndroid Build Coastguard Worker }
5673*5e7646d2SAndroid Build Coastguard Worker }
5674*5e7646d2SAndroid Build Coastguard Worker else if ((status = cupsdCheckPolicy(DefaultPolicyPtr, con, NULL)) != HTTP_OK)
5675*5e7646d2SAndroid Build Coastguard Worker {
5676*5e7646d2SAndroid Build Coastguard Worker send_http_error(con, status, NULL);
5677*5e7646d2SAndroid Build Coastguard Worker return;
5678*5e7646d2SAndroid Build Coastguard Worker }
5679*5e7646d2SAndroid Build Coastguard Worker
5680*5e7646d2SAndroid Build Coastguard Worker /*
5681*5e7646d2SAndroid Build Coastguard Worker * Get the user that is requesting the subscription...
5682*5e7646d2SAndroid Build Coastguard Worker */
5683*5e7646d2SAndroid Build Coastguard Worker
5684*5e7646d2SAndroid Build Coastguard Worker username = get_username(con);
5685*5e7646d2SAndroid Build Coastguard Worker
5686*5e7646d2SAndroid Build Coastguard Worker /*
5687*5e7646d2SAndroid Build Coastguard Worker * Find the first subscription group attribute; return if we have
5688*5e7646d2SAndroid Build Coastguard Worker * none...
5689*5e7646d2SAndroid Build Coastguard Worker */
5690*5e7646d2SAndroid Build Coastguard Worker
5691*5e7646d2SAndroid Build Coastguard Worker for (attr = con->request->attrs; attr; attr = attr->next)
5692*5e7646d2SAndroid Build Coastguard Worker if (attr->group_tag == IPP_TAG_SUBSCRIPTION)
5693*5e7646d2SAndroid Build Coastguard Worker break;
5694*5e7646d2SAndroid Build Coastguard Worker
5695*5e7646d2SAndroid Build Coastguard Worker if (!attr)
5696*5e7646d2SAndroid Build Coastguard Worker {
5697*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_BAD_REQUEST,
5698*5e7646d2SAndroid Build Coastguard Worker _("No subscription attributes in request."));
5699*5e7646d2SAndroid Build Coastguard Worker return;
5700*5e7646d2SAndroid Build Coastguard Worker }
5701*5e7646d2SAndroid Build Coastguard Worker
5702*5e7646d2SAndroid Build Coastguard Worker /*
5703*5e7646d2SAndroid Build Coastguard Worker * Process the subscription attributes in the request...
5704*5e7646d2SAndroid Build Coastguard Worker */
5705*5e7646d2SAndroid Build Coastguard Worker
5706*5e7646d2SAndroid Build Coastguard Worker con->response->request.status.status_code = IPP_BAD_REQUEST;
5707*5e7646d2SAndroid Build Coastguard Worker
5708*5e7646d2SAndroid Build Coastguard Worker while (attr)
5709*5e7646d2SAndroid Build Coastguard Worker {
5710*5e7646d2SAndroid Build Coastguard Worker recipient = NULL;
5711*5e7646d2SAndroid Build Coastguard Worker pullmethod = NULL;
5712*5e7646d2SAndroid Build Coastguard Worker user_data = NULL;
5713*5e7646d2SAndroid Build Coastguard Worker interval = 0;
5714*5e7646d2SAndroid Build Coastguard Worker lease = DefaultLeaseDuration;
5715*5e7646d2SAndroid Build Coastguard Worker jobid = 0;
5716*5e7646d2SAndroid Build Coastguard Worker mask = CUPSD_EVENT_NONE;
5717*5e7646d2SAndroid Build Coastguard Worker
5718*5e7646d2SAndroid Build Coastguard Worker if (printer)
5719*5e7646d2SAndroid Build Coastguard Worker {
5720*5e7646d2SAndroid Build Coastguard Worker notify_events = ippFindAttribute(printer->attrs, "notify-events-default",
5721*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_KEYWORD);
5722*5e7646d2SAndroid Build Coastguard Worker notify_lease = ippFindAttribute(printer->attrs,
5723*5e7646d2SAndroid Build Coastguard Worker "notify-lease-duration-default",
5724*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_INTEGER);
5725*5e7646d2SAndroid Build Coastguard Worker
5726*5e7646d2SAndroid Build Coastguard Worker if (notify_lease)
5727*5e7646d2SAndroid Build Coastguard Worker lease = notify_lease->values[0].integer;
5728*5e7646d2SAndroid Build Coastguard Worker }
5729*5e7646d2SAndroid Build Coastguard Worker else
5730*5e7646d2SAndroid Build Coastguard Worker {
5731*5e7646d2SAndroid Build Coastguard Worker notify_events = NULL;
5732*5e7646d2SAndroid Build Coastguard Worker notify_lease = NULL;
5733*5e7646d2SAndroid Build Coastguard Worker }
5734*5e7646d2SAndroid Build Coastguard Worker
5735*5e7646d2SAndroid Build Coastguard Worker while (attr && attr->group_tag != IPP_TAG_ZERO)
5736*5e7646d2SAndroid Build Coastguard Worker {
5737*5e7646d2SAndroid Build Coastguard Worker if (!strcmp(attr->name, "notify-recipient-uri") &&
5738*5e7646d2SAndroid Build Coastguard Worker attr->value_tag == IPP_TAG_URI)
5739*5e7646d2SAndroid Build Coastguard Worker {
5740*5e7646d2SAndroid Build Coastguard Worker /*
5741*5e7646d2SAndroid Build Coastguard Worker * Validate the recipient scheme against the ServerBin/notifier
5742*5e7646d2SAndroid Build Coastguard Worker * directory...
5743*5e7646d2SAndroid Build Coastguard Worker */
5744*5e7646d2SAndroid Build Coastguard Worker
5745*5e7646d2SAndroid Build Coastguard Worker char notifier[1024]; /* Notifier filename */
5746*5e7646d2SAndroid Build Coastguard Worker
5747*5e7646d2SAndroid Build Coastguard Worker
5748*5e7646d2SAndroid Build Coastguard Worker recipient = attr->values[0].string.text;
5749*5e7646d2SAndroid Build Coastguard Worker
5750*5e7646d2SAndroid Build Coastguard Worker if (httpSeparateURI(HTTP_URI_CODING_ALL, recipient,
5751*5e7646d2SAndroid Build Coastguard Worker scheme, sizeof(scheme), userpass, sizeof(userpass),
5752*5e7646d2SAndroid Build Coastguard Worker host, sizeof(host), &port,
5753*5e7646d2SAndroid Build Coastguard Worker resource, sizeof(resource)) < HTTP_URI_OK)
5754*5e7646d2SAndroid Build Coastguard Worker {
5755*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_NOT_POSSIBLE,
5756*5e7646d2SAndroid Build Coastguard Worker _("Bad notify-recipient-uri \"%s\"."), recipient);
5757*5e7646d2SAndroid Build Coastguard Worker ippAddInteger(con->response, IPP_TAG_SUBSCRIPTION, IPP_TAG_ENUM,
5758*5e7646d2SAndroid Build Coastguard Worker "notify-status-code", IPP_URI_SCHEME);
5759*5e7646d2SAndroid Build Coastguard Worker return;
5760*5e7646d2SAndroid Build Coastguard Worker }
5761*5e7646d2SAndroid Build Coastguard Worker
5762*5e7646d2SAndroid Build Coastguard Worker snprintf(notifier, sizeof(notifier), "%s/notifier/%s", ServerBin,
5763*5e7646d2SAndroid Build Coastguard Worker scheme);
5764*5e7646d2SAndroid Build Coastguard Worker if (access(notifier, X_OK) || !strcmp(scheme, ".") || !strcmp(scheme, ".."))
5765*5e7646d2SAndroid Build Coastguard Worker {
5766*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_NOT_POSSIBLE,
5767*5e7646d2SAndroid Build Coastguard Worker _("notify-recipient-uri URI \"%s\" uses unknown "
5768*5e7646d2SAndroid Build Coastguard Worker "scheme."), recipient);
5769*5e7646d2SAndroid Build Coastguard Worker ippAddInteger(con->response, IPP_TAG_SUBSCRIPTION, IPP_TAG_ENUM,
5770*5e7646d2SAndroid Build Coastguard Worker "notify-status-code", IPP_URI_SCHEME);
5771*5e7646d2SAndroid Build Coastguard Worker return;
5772*5e7646d2SAndroid Build Coastguard Worker }
5773*5e7646d2SAndroid Build Coastguard Worker
5774*5e7646d2SAndroid Build Coastguard Worker if (!strcmp(scheme, "rss") && !check_rss_recipient(recipient))
5775*5e7646d2SAndroid Build Coastguard Worker {
5776*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_NOT_POSSIBLE,
5777*5e7646d2SAndroid Build Coastguard Worker _("notify-recipient-uri URI \"%s\" is already used."),
5778*5e7646d2SAndroid Build Coastguard Worker recipient);
5779*5e7646d2SAndroid Build Coastguard Worker ippAddInteger(con->response, IPP_TAG_SUBSCRIPTION, IPP_TAG_ENUM,
5780*5e7646d2SAndroid Build Coastguard Worker "notify-status-code", IPP_ATTRIBUTES);
5781*5e7646d2SAndroid Build Coastguard Worker return;
5782*5e7646d2SAndroid Build Coastguard Worker }
5783*5e7646d2SAndroid Build Coastguard Worker }
5784*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(attr->name, "notify-pull-method") &&
5785*5e7646d2SAndroid Build Coastguard Worker attr->value_tag == IPP_TAG_KEYWORD)
5786*5e7646d2SAndroid Build Coastguard Worker {
5787*5e7646d2SAndroid Build Coastguard Worker pullmethod = attr->values[0].string.text;
5788*5e7646d2SAndroid Build Coastguard Worker
5789*5e7646d2SAndroid Build Coastguard Worker if (strcmp(pullmethod, "ippget"))
5790*5e7646d2SAndroid Build Coastguard Worker {
5791*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_NOT_POSSIBLE,
5792*5e7646d2SAndroid Build Coastguard Worker _("Bad notify-pull-method \"%s\"."), pullmethod);
5793*5e7646d2SAndroid Build Coastguard Worker ippAddInteger(con->response, IPP_TAG_SUBSCRIPTION, IPP_TAG_ENUM,
5794*5e7646d2SAndroid Build Coastguard Worker "notify-status-code", IPP_ATTRIBUTES);
5795*5e7646d2SAndroid Build Coastguard Worker return;
5796*5e7646d2SAndroid Build Coastguard Worker }
5797*5e7646d2SAndroid Build Coastguard Worker }
5798*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(attr->name, "notify-charset") &&
5799*5e7646d2SAndroid Build Coastguard Worker attr->value_tag == IPP_TAG_CHARSET &&
5800*5e7646d2SAndroid Build Coastguard Worker strcmp(attr->values[0].string.text, "us-ascii") &&
5801*5e7646d2SAndroid Build Coastguard Worker strcmp(attr->values[0].string.text, "utf-8"))
5802*5e7646d2SAndroid Build Coastguard Worker {
5803*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_CHARSET,
5804*5e7646d2SAndroid Build Coastguard Worker _("Character set \"%s\" not supported."),
5805*5e7646d2SAndroid Build Coastguard Worker attr->values[0].string.text);
5806*5e7646d2SAndroid Build Coastguard Worker return;
5807*5e7646d2SAndroid Build Coastguard Worker }
5808*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(attr->name, "notify-natural-language") &&
5809*5e7646d2SAndroid Build Coastguard Worker (attr->value_tag != IPP_TAG_LANGUAGE ||
5810*5e7646d2SAndroid Build Coastguard Worker strcmp(attr->values[0].string.text, DefaultLanguage)))
5811*5e7646d2SAndroid Build Coastguard Worker {
5812*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_CHARSET,
5813*5e7646d2SAndroid Build Coastguard Worker _("Language \"%s\" not supported."),
5814*5e7646d2SAndroid Build Coastguard Worker attr->values[0].string.text);
5815*5e7646d2SAndroid Build Coastguard Worker return;
5816*5e7646d2SAndroid Build Coastguard Worker }
5817*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(attr->name, "notify-user-data") &&
5818*5e7646d2SAndroid Build Coastguard Worker attr->value_tag == IPP_TAG_STRING)
5819*5e7646d2SAndroid Build Coastguard Worker {
5820*5e7646d2SAndroid Build Coastguard Worker if (attr->num_values > 1 || attr->values[0].unknown.length > 63)
5821*5e7646d2SAndroid Build Coastguard Worker {
5822*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_REQUEST_VALUE,
5823*5e7646d2SAndroid Build Coastguard Worker _("The notify-user-data value is too large "
5824*5e7646d2SAndroid Build Coastguard Worker "(%d > 63 octets)."),
5825*5e7646d2SAndroid Build Coastguard Worker attr->values[0].unknown.length);
5826*5e7646d2SAndroid Build Coastguard Worker return;
5827*5e7646d2SAndroid Build Coastguard Worker }
5828*5e7646d2SAndroid Build Coastguard Worker
5829*5e7646d2SAndroid Build Coastguard Worker user_data = attr;
5830*5e7646d2SAndroid Build Coastguard Worker }
5831*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(attr->name, "notify-events") &&
5832*5e7646d2SAndroid Build Coastguard Worker attr->value_tag == IPP_TAG_KEYWORD)
5833*5e7646d2SAndroid Build Coastguard Worker notify_events = attr;
5834*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(attr->name, "notify-lease-duration") &&
5835*5e7646d2SAndroid Build Coastguard Worker attr->value_tag == IPP_TAG_INTEGER)
5836*5e7646d2SAndroid Build Coastguard Worker lease = attr->values[0].integer;
5837*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(attr->name, "notify-time-interval") &&
5838*5e7646d2SAndroid Build Coastguard Worker attr->value_tag == IPP_TAG_INTEGER)
5839*5e7646d2SAndroid Build Coastguard Worker interval = attr->values[0].integer;
5840*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(attr->name, "notify-job-id") &&
5841*5e7646d2SAndroid Build Coastguard Worker attr->value_tag == IPP_TAG_INTEGER)
5842*5e7646d2SAndroid Build Coastguard Worker jobid = attr->values[0].integer;
5843*5e7646d2SAndroid Build Coastguard Worker
5844*5e7646d2SAndroid Build Coastguard Worker attr = attr->next;
5845*5e7646d2SAndroid Build Coastguard Worker }
5846*5e7646d2SAndroid Build Coastguard Worker
5847*5e7646d2SAndroid Build Coastguard Worker if (notify_events)
5848*5e7646d2SAndroid Build Coastguard Worker {
5849*5e7646d2SAndroid Build Coastguard Worker for (i = 0; i < notify_events->num_values; i ++)
5850*5e7646d2SAndroid Build Coastguard Worker mask |= cupsdEventValue(notify_events->values[i].string.text);
5851*5e7646d2SAndroid Build Coastguard Worker }
5852*5e7646d2SAndroid Build Coastguard Worker
5853*5e7646d2SAndroid Build Coastguard Worker if (recipient)
5854*5e7646d2SAndroid Build Coastguard Worker {
5855*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG, "recipient=\"%s\"", recipient);
5856*5e7646d2SAndroid Build Coastguard Worker
5857*5e7646d2SAndroid Build Coastguard Worker
5858*5e7646d2SAndroid Build Coastguard Worker if (!strncmp(recipient, "mailto:", 7) && user_data)
5859*5e7646d2SAndroid Build Coastguard Worker {
5860*5e7646d2SAndroid Build Coastguard Worker char temp[64]; /* Temporary string */
5861*5e7646d2SAndroid Build Coastguard Worker
5862*5e7646d2SAndroid Build Coastguard Worker memcpy(temp, user_data->values[0].unknown.data, (size_t)user_data->values[0].unknown.length);
5863*5e7646d2SAndroid Build Coastguard Worker temp[user_data->values[0].unknown.length] = '\0';
5864*5e7646d2SAndroid Build Coastguard Worker
5865*5e7646d2SAndroid Build Coastguard Worker if (httpSeparateURI(HTTP_URI_CODING_ALL, temp, scheme, sizeof(scheme), userpass, sizeof(userpass), host, sizeof(host), &port, resource, sizeof(resource)) < HTTP_URI_OK)
5866*5e7646d2SAndroid Build Coastguard Worker {
5867*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_NOT_POSSIBLE, _("Bad notify-user-data \"%s\"."), temp);
5868*5e7646d2SAndroid Build Coastguard Worker ippAddInteger(con->response, IPP_TAG_SUBSCRIPTION, IPP_TAG_ENUM, "notify-status-code", IPP_STATUS_ERROR_ATTRIBUTES_OR_VALUES);
5869*5e7646d2SAndroid Build Coastguard Worker return;
5870*5e7646d2SAndroid Build Coastguard Worker }
5871*5e7646d2SAndroid Build Coastguard Worker }
5872*5e7646d2SAndroid Build Coastguard Worker }
5873*5e7646d2SAndroid Build Coastguard Worker
5874*5e7646d2SAndroid Build Coastguard Worker if (pullmethod)
5875*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG, "pullmethod=\"%s\"", pullmethod);
5876*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG, "notify-lease-duration=%d", lease);
5877*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG, "notify-time-interval=%d", interval);
5878*5e7646d2SAndroid Build Coastguard Worker
5879*5e7646d2SAndroid Build Coastguard Worker if (!recipient && !pullmethod)
5880*5e7646d2SAndroid Build Coastguard Worker break;
5881*5e7646d2SAndroid Build Coastguard Worker
5882*5e7646d2SAndroid Build Coastguard Worker if (mask == CUPSD_EVENT_NONE)
5883*5e7646d2SAndroid Build Coastguard Worker {
5884*5e7646d2SAndroid Build Coastguard Worker if (jobid)
5885*5e7646d2SAndroid Build Coastguard Worker mask = CUPSD_EVENT_JOB_COMPLETED;
5886*5e7646d2SAndroid Build Coastguard Worker else if (printer)
5887*5e7646d2SAndroid Build Coastguard Worker mask = CUPSD_EVENT_PRINTER_STATE_CHANGED;
5888*5e7646d2SAndroid Build Coastguard Worker else
5889*5e7646d2SAndroid Build Coastguard Worker {
5890*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_BAD_REQUEST,
5891*5e7646d2SAndroid Build Coastguard Worker _("notify-events not specified."));
5892*5e7646d2SAndroid Build Coastguard Worker return;
5893*5e7646d2SAndroid Build Coastguard Worker }
5894*5e7646d2SAndroid Build Coastguard Worker }
5895*5e7646d2SAndroid Build Coastguard Worker
5896*5e7646d2SAndroid Build Coastguard Worker if (MaxLeaseDuration && (lease == 0 || lease > MaxLeaseDuration))
5897*5e7646d2SAndroid Build Coastguard Worker {
5898*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_INFO,
5899*5e7646d2SAndroid Build Coastguard Worker "create_subscriptions: Limiting notify-lease-duration to "
5900*5e7646d2SAndroid Build Coastguard Worker "%d seconds.",
5901*5e7646d2SAndroid Build Coastguard Worker MaxLeaseDuration);
5902*5e7646d2SAndroid Build Coastguard Worker lease = MaxLeaseDuration;
5903*5e7646d2SAndroid Build Coastguard Worker }
5904*5e7646d2SAndroid Build Coastguard Worker
5905*5e7646d2SAndroid Build Coastguard Worker if (jobid)
5906*5e7646d2SAndroid Build Coastguard Worker {
5907*5e7646d2SAndroid Build Coastguard Worker if ((job = cupsdFindJob(jobid)) == NULL)
5908*5e7646d2SAndroid Build Coastguard Worker {
5909*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_NOT_FOUND, _("Job #%d does not exist."),
5910*5e7646d2SAndroid Build Coastguard Worker jobid);
5911*5e7646d2SAndroid Build Coastguard Worker return;
5912*5e7646d2SAndroid Build Coastguard Worker }
5913*5e7646d2SAndroid Build Coastguard Worker }
5914*5e7646d2SAndroid Build Coastguard Worker else
5915*5e7646d2SAndroid Build Coastguard Worker job = NULL;
5916*5e7646d2SAndroid Build Coastguard Worker
5917*5e7646d2SAndroid Build Coastguard Worker if ((sub = cupsdAddSubscription(mask, printer, job, recipient, 0)) == NULL)
5918*5e7646d2SAndroid Build Coastguard Worker {
5919*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_TOO_MANY_SUBSCRIPTIONS,
5920*5e7646d2SAndroid Build Coastguard Worker _("There are too many subscriptions."));
5921*5e7646d2SAndroid Build Coastguard Worker return;
5922*5e7646d2SAndroid Build Coastguard Worker }
5923*5e7646d2SAndroid Build Coastguard Worker
5924*5e7646d2SAndroid Build Coastguard Worker if (job)
5925*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG, "Added subscription #%d for job %d.",
5926*5e7646d2SAndroid Build Coastguard Worker sub->id, job->id);
5927*5e7646d2SAndroid Build Coastguard Worker else if (printer)
5928*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG,
5929*5e7646d2SAndroid Build Coastguard Worker "Added subscription #%d for printer \"%s\".",
5930*5e7646d2SAndroid Build Coastguard Worker sub->id, printer->name);
5931*5e7646d2SAndroid Build Coastguard Worker else
5932*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG, "Added subscription #%d for server.",
5933*5e7646d2SAndroid Build Coastguard Worker sub->id);
5934*5e7646d2SAndroid Build Coastguard Worker
5935*5e7646d2SAndroid Build Coastguard Worker sub->interval = interval;
5936*5e7646d2SAndroid Build Coastguard Worker sub->lease = lease;
5937*5e7646d2SAndroid Build Coastguard Worker sub->expire = lease ? time(NULL) + lease : 0;
5938*5e7646d2SAndroid Build Coastguard Worker
5939*5e7646d2SAndroid Build Coastguard Worker cupsdSetString(&sub->owner, username);
5940*5e7646d2SAndroid Build Coastguard Worker
5941*5e7646d2SAndroid Build Coastguard Worker if (user_data)
5942*5e7646d2SAndroid Build Coastguard Worker {
5943*5e7646d2SAndroid Build Coastguard Worker sub->user_data_len = user_data->values[0].unknown.length;
5944*5e7646d2SAndroid Build Coastguard Worker memcpy(sub->user_data, user_data->values[0].unknown.data,
5945*5e7646d2SAndroid Build Coastguard Worker (size_t)sub->user_data_len);
5946*5e7646d2SAndroid Build Coastguard Worker }
5947*5e7646d2SAndroid Build Coastguard Worker
5948*5e7646d2SAndroid Build Coastguard Worker ippAddSeparator(con->response);
5949*5e7646d2SAndroid Build Coastguard Worker ippAddInteger(con->response, IPP_TAG_SUBSCRIPTION, IPP_TAG_INTEGER,
5950*5e7646d2SAndroid Build Coastguard Worker "notify-subscription-id", sub->id);
5951*5e7646d2SAndroid Build Coastguard Worker
5952*5e7646d2SAndroid Build Coastguard Worker con->response->request.status.status_code = IPP_OK;
5953*5e7646d2SAndroid Build Coastguard Worker
5954*5e7646d2SAndroid Build Coastguard Worker if (attr)
5955*5e7646d2SAndroid Build Coastguard Worker attr = attr->next;
5956*5e7646d2SAndroid Build Coastguard Worker }
5957*5e7646d2SAndroid Build Coastguard Worker
5958*5e7646d2SAndroid Build Coastguard Worker cupsdMarkDirty(CUPSD_DIRTY_SUBSCRIPTIONS);
5959*5e7646d2SAndroid Build Coastguard Worker }
5960*5e7646d2SAndroid Build Coastguard Worker
5961*5e7646d2SAndroid Build Coastguard Worker
5962*5e7646d2SAndroid Build Coastguard Worker /*
5963*5e7646d2SAndroid Build Coastguard Worker * 'delete_printer()' - Remove a printer or class from the system.
5964*5e7646d2SAndroid Build Coastguard Worker */
5965*5e7646d2SAndroid Build Coastguard Worker
5966*5e7646d2SAndroid Build Coastguard Worker static void
delete_printer(cupsd_client_t * con,ipp_attribute_t * uri)5967*5e7646d2SAndroid Build Coastguard Worker delete_printer(cupsd_client_t *con, /* I - Client connection */
5968*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *uri) /* I - URI of printer or class */
5969*5e7646d2SAndroid Build Coastguard Worker {
5970*5e7646d2SAndroid Build Coastguard Worker http_status_t status; /* Policy status */
5971*5e7646d2SAndroid Build Coastguard Worker cups_ptype_t dtype; /* Destination type (printer/class) */
5972*5e7646d2SAndroid Build Coastguard Worker cupsd_printer_t *printer; /* Printer/class */
5973*5e7646d2SAndroid Build Coastguard Worker char filename[1024]; /* Script/PPD filename */
5974*5e7646d2SAndroid Build Coastguard Worker int temporary; /* Temporary queue? */
5975*5e7646d2SAndroid Build Coastguard Worker
5976*5e7646d2SAndroid Build Coastguard Worker
5977*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG2, "delete_printer(%p[%d], %s)", con,
5978*5e7646d2SAndroid Build Coastguard Worker con->number, uri->values[0].string.text);
5979*5e7646d2SAndroid Build Coastguard Worker
5980*5e7646d2SAndroid Build Coastguard Worker /*
5981*5e7646d2SAndroid Build Coastguard Worker * Do we have a valid URI?
5982*5e7646d2SAndroid Build Coastguard Worker */
5983*5e7646d2SAndroid Build Coastguard Worker
5984*5e7646d2SAndroid Build Coastguard Worker if (!cupsdValidateDest(uri->values[0].string.text, &dtype, &printer))
5985*5e7646d2SAndroid Build Coastguard Worker {
5986*5e7646d2SAndroid Build Coastguard Worker /*
5987*5e7646d2SAndroid Build Coastguard Worker * Bad URI...
5988*5e7646d2SAndroid Build Coastguard Worker */
5989*5e7646d2SAndroid Build Coastguard Worker
5990*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_NOT_FOUND,
5991*5e7646d2SAndroid Build Coastguard Worker _("The printer or class does not exist."));
5992*5e7646d2SAndroid Build Coastguard Worker return;
5993*5e7646d2SAndroid Build Coastguard Worker }
5994*5e7646d2SAndroid Build Coastguard Worker
5995*5e7646d2SAndroid Build Coastguard Worker /*
5996*5e7646d2SAndroid Build Coastguard Worker * Check policy...
5997*5e7646d2SAndroid Build Coastguard Worker */
5998*5e7646d2SAndroid Build Coastguard Worker
5999*5e7646d2SAndroid Build Coastguard Worker if ((status = cupsdCheckPolicy(DefaultPolicyPtr, con, NULL)) != HTTP_OK)
6000*5e7646d2SAndroid Build Coastguard Worker {
6001*5e7646d2SAndroid Build Coastguard Worker send_http_error(con, status, NULL);
6002*5e7646d2SAndroid Build Coastguard Worker return;
6003*5e7646d2SAndroid Build Coastguard Worker }
6004*5e7646d2SAndroid Build Coastguard Worker
6005*5e7646d2SAndroid Build Coastguard Worker /*
6006*5e7646d2SAndroid Build Coastguard Worker * Remove old jobs...
6007*5e7646d2SAndroid Build Coastguard Worker */
6008*5e7646d2SAndroid Build Coastguard Worker
6009*5e7646d2SAndroid Build Coastguard Worker cupsdCancelJobs(printer->name, NULL, 1);
6010*5e7646d2SAndroid Build Coastguard Worker
6011*5e7646d2SAndroid Build Coastguard Worker /*
6012*5e7646d2SAndroid Build Coastguard Worker * Remove old subscriptions and send a "deleted printer" event...
6013*5e7646d2SAndroid Build Coastguard Worker */
6014*5e7646d2SAndroid Build Coastguard Worker
6015*5e7646d2SAndroid Build Coastguard Worker cupsdAddEvent(CUPSD_EVENT_PRINTER_DELETED, printer, NULL,
6016*5e7646d2SAndroid Build Coastguard Worker "%s \"%s\" deleted by \"%s\".",
6017*5e7646d2SAndroid Build Coastguard Worker (dtype & CUPS_PRINTER_CLASS) ? "Class" : "Printer",
6018*5e7646d2SAndroid Build Coastguard Worker printer->name, get_username(con));
6019*5e7646d2SAndroid Build Coastguard Worker
6020*5e7646d2SAndroid Build Coastguard Worker cupsdExpireSubscriptions(printer, NULL);
6021*5e7646d2SAndroid Build Coastguard Worker
6022*5e7646d2SAndroid Build Coastguard Worker /*
6023*5e7646d2SAndroid Build Coastguard Worker * Remove any old PPD or script files...
6024*5e7646d2SAndroid Build Coastguard Worker */
6025*5e7646d2SAndroid Build Coastguard Worker
6026*5e7646d2SAndroid Build Coastguard Worker snprintf(filename, sizeof(filename), "%s/ppd/%s.ppd", ServerRoot,
6027*5e7646d2SAndroid Build Coastguard Worker printer->name);
6028*5e7646d2SAndroid Build Coastguard Worker unlink(filename);
6029*5e7646d2SAndroid Build Coastguard Worker snprintf(filename, sizeof(filename), "%s/ppd/%s.ppd.O", ServerRoot,
6030*5e7646d2SAndroid Build Coastguard Worker printer->name);
6031*5e7646d2SAndroid Build Coastguard Worker unlink(filename);
6032*5e7646d2SAndroid Build Coastguard Worker
6033*5e7646d2SAndroid Build Coastguard Worker snprintf(filename, sizeof(filename), "%s/%s.png", CacheDir, printer->name);
6034*5e7646d2SAndroid Build Coastguard Worker unlink(filename);
6035*5e7646d2SAndroid Build Coastguard Worker
6036*5e7646d2SAndroid Build Coastguard Worker snprintf(filename, sizeof(filename), "%s/%s.data", CacheDir, printer->name);
6037*5e7646d2SAndroid Build Coastguard Worker unlink(filename);
6038*5e7646d2SAndroid Build Coastguard Worker
6039*5e7646d2SAndroid Build Coastguard Worker /*
6040*5e7646d2SAndroid Build Coastguard Worker * Unregister color profiles...
6041*5e7646d2SAndroid Build Coastguard Worker */
6042*5e7646d2SAndroid Build Coastguard Worker
6043*5e7646d2SAndroid Build Coastguard Worker cupsdUnregisterColor(printer);
6044*5e7646d2SAndroid Build Coastguard Worker
6045*5e7646d2SAndroid Build Coastguard Worker temporary = printer->temporary;
6046*5e7646d2SAndroid Build Coastguard Worker
6047*5e7646d2SAndroid Build Coastguard Worker if (dtype & CUPS_PRINTER_CLASS)
6048*5e7646d2SAndroid Build Coastguard Worker {
6049*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_INFO, "Class \"%s\" deleted by \"%s\".",
6050*5e7646d2SAndroid Build Coastguard Worker printer->name, get_username(con));
6051*5e7646d2SAndroid Build Coastguard Worker
6052*5e7646d2SAndroid Build Coastguard Worker cupsdDeletePrinter(printer, 0);
6053*5e7646d2SAndroid Build Coastguard Worker if (!temporary)
6054*5e7646d2SAndroid Build Coastguard Worker cupsdMarkDirty(CUPSD_DIRTY_CLASSES);
6055*5e7646d2SAndroid Build Coastguard Worker }
6056*5e7646d2SAndroid Build Coastguard Worker else
6057*5e7646d2SAndroid Build Coastguard Worker {
6058*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_INFO, "Printer \"%s\" deleted by \"%s\".",
6059*5e7646d2SAndroid Build Coastguard Worker printer->name, get_username(con));
6060*5e7646d2SAndroid Build Coastguard Worker
6061*5e7646d2SAndroid Build Coastguard Worker if (cupsdDeletePrinter(printer, 0) && !temporary)
6062*5e7646d2SAndroid Build Coastguard Worker cupsdMarkDirty(CUPSD_DIRTY_CLASSES);
6063*5e7646d2SAndroid Build Coastguard Worker
6064*5e7646d2SAndroid Build Coastguard Worker if (!temporary)
6065*5e7646d2SAndroid Build Coastguard Worker cupsdMarkDirty(CUPSD_DIRTY_PRINTERS);
6066*5e7646d2SAndroid Build Coastguard Worker }
6067*5e7646d2SAndroid Build Coastguard Worker
6068*5e7646d2SAndroid Build Coastguard Worker if (!temporary)
6069*5e7646d2SAndroid Build Coastguard Worker cupsdMarkDirty(CUPSD_DIRTY_PRINTCAP);
6070*5e7646d2SAndroid Build Coastguard Worker
6071*5e7646d2SAndroid Build Coastguard Worker /*
6072*5e7646d2SAndroid Build Coastguard Worker * Return with no errors...
6073*5e7646d2SAndroid Build Coastguard Worker */
6074*5e7646d2SAndroid Build Coastguard Worker
6075*5e7646d2SAndroid Build Coastguard Worker con->response->request.status.status_code = IPP_OK;
6076*5e7646d2SAndroid Build Coastguard Worker }
6077*5e7646d2SAndroid Build Coastguard Worker
6078*5e7646d2SAndroid Build Coastguard Worker
6079*5e7646d2SAndroid Build Coastguard Worker /*
6080*5e7646d2SAndroid Build Coastguard Worker * 'get_default()' - Get the default destination.
6081*5e7646d2SAndroid Build Coastguard Worker */
6082*5e7646d2SAndroid Build Coastguard Worker
6083*5e7646d2SAndroid Build Coastguard Worker static void
get_default(cupsd_client_t * con)6084*5e7646d2SAndroid Build Coastguard Worker get_default(cupsd_client_t *con) /* I - Client connection */
6085*5e7646d2SAndroid Build Coastguard Worker {
6086*5e7646d2SAndroid Build Coastguard Worker http_status_t status; /* Policy status */
6087*5e7646d2SAndroid Build Coastguard Worker cups_array_t *ra; /* Requested attributes array */
6088*5e7646d2SAndroid Build Coastguard Worker
6089*5e7646d2SAndroid Build Coastguard Worker
6090*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_default(%p[%d])", con, con->number);
6091*5e7646d2SAndroid Build Coastguard Worker
6092*5e7646d2SAndroid Build Coastguard Worker /*
6093*5e7646d2SAndroid Build Coastguard Worker * Check policy...
6094*5e7646d2SAndroid Build Coastguard Worker */
6095*5e7646d2SAndroid Build Coastguard Worker
6096*5e7646d2SAndroid Build Coastguard Worker if ((status = cupsdCheckPolicy(DefaultPolicyPtr, con, NULL)) != HTTP_OK)
6097*5e7646d2SAndroid Build Coastguard Worker {
6098*5e7646d2SAndroid Build Coastguard Worker send_http_error(con, status, NULL);
6099*5e7646d2SAndroid Build Coastguard Worker return;
6100*5e7646d2SAndroid Build Coastguard Worker }
6101*5e7646d2SAndroid Build Coastguard Worker
6102*5e7646d2SAndroid Build Coastguard Worker if (DefaultPrinter)
6103*5e7646d2SAndroid Build Coastguard Worker {
6104*5e7646d2SAndroid Build Coastguard Worker ra = create_requested_array(con->request);
6105*5e7646d2SAndroid Build Coastguard Worker
6106*5e7646d2SAndroid Build Coastguard Worker copy_printer_attrs(con, DefaultPrinter, ra);
6107*5e7646d2SAndroid Build Coastguard Worker
6108*5e7646d2SAndroid Build Coastguard Worker cupsArrayDelete(ra);
6109*5e7646d2SAndroid Build Coastguard Worker
6110*5e7646d2SAndroid Build Coastguard Worker con->response->request.status.status_code = IPP_OK;
6111*5e7646d2SAndroid Build Coastguard Worker }
6112*5e7646d2SAndroid Build Coastguard Worker else
6113*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_NOT_FOUND, _("No default printer."));
6114*5e7646d2SAndroid Build Coastguard Worker }
6115*5e7646d2SAndroid Build Coastguard Worker
6116*5e7646d2SAndroid Build Coastguard Worker
6117*5e7646d2SAndroid Build Coastguard Worker /*
6118*5e7646d2SAndroid Build Coastguard Worker * 'get_devices()' - Get the list of available devices on the local system.
6119*5e7646d2SAndroid Build Coastguard Worker */
6120*5e7646d2SAndroid Build Coastguard Worker
6121*5e7646d2SAndroid Build Coastguard Worker static void
get_devices(cupsd_client_t * con)6122*5e7646d2SAndroid Build Coastguard Worker get_devices(cupsd_client_t *con) /* I - Client connection */
6123*5e7646d2SAndroid Build Coastguard Worker {
6124*5e7646d2SAndroid Build Coastguard Worker http_status_t status; /* Policy status */
6125*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *limit, /* limit attribute */
6126*5e7646d2SAndroid Build Coastguard Worker *timeout, /* timeout attribute */
6127*5e7646d2SAndroid Build Coastguard Worker *requested, /* requested-attributes attribute */
6128*5e7646d2SAndroid Build Coastguard Worker *exclude, /* exclude-schemes attribute */
6129*5e7646d2SAndroid Build Coastguard Worker *include; /* include-schemes attribute */
6130*5e7646d2SAndroid Build Coastguard Worker char command[1024], /* cups-deviced command */
6131*5e7646d2SAndroid Build Coastguard Worker options[2048], /* Options to pass to command */
6132*5e7646d2SAndroid Build Coastguard Worker requested_str[256],
6133*5e7646d2SAndroid Build Coastguard Worker /* String for requested attributes */
6134*5e7646d2SAndroid Build Coastguard Worker exclude_str[512],
6135*5e7646d2SAndroid Build Coastguard Worker /* String for excluded schemes */
6136*5e7646d2SAndroid Build Coastguard Worker include_str[512];
6137*5e7646d2SAndroid Build Coastguard Worker /* String for included schemes */
6138*5e7646d2SAndroid Build Coastguard Worker
6139*5e7646d2SAndroid Build Coastguard Worker
6140*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_devices(%p[%d])", con, con->number);
6141*5e7646d2SAndroid Build Coastguard Worker
6142*5e7646d2SAndroid Build Coastguard Worker /*
6143*5e7646d2SAndroid Build Coastguard Worker * Check policy...
6144*5e7646d2SAndroid Build Coastguard Worker */
6145*5e7646d2SAndroid Build Coastguard Worker
6146*5e7646d2SAndroid Build Coastguard Worker if ((status = cupsdCheckPolicy(DefaultPolicyPtr, con, NULL)) != HTTP_OK)
6147*5e7646d2SAndroid Build Coastguard Worker {
6148*5e7646d2SAndroid Build Coastguard Worker send_http_error(con, status, NULL);
6149*5e7646d2SAndroid Build Coastguard Worker return;
6150*5e7646d2SAndroid Build Coastguard Worker }
6151*5e7646d2SAndroid Build Coastguard Worker
6152*5e7646d2SAndroid Build Coastguard Worker /*
6153*5e7646d2SAndroid Build Coastguard Worker * Run cups-deviced command with the given options...
6154*5e7646d2SAndroid Build Coastguard Worker */
6155*5e7646d2SAndroid Build Coastguard Worker
6156*5e7646d2SAndroid Build Coastguard Worker limit = ippFindAttribute(con->request, "limit", IPP_TAG_INTEGER);
6157*5e7646d2SAndroid Build Coastguard Worker timeout = ippFindAttribute(con->request, "timeout", IPP_TAG_INTEGER);
6158*5e7646d2SAndroid Build Coastguard Worker requested = ippFindAttribute(con->request, "requested-attributes",
6159*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_KEYWORD);
6160*5e7646d2SAndroid Build Coastguard Worker exclude = ippFindAttribute(con->request, "exclude-schemes", IPP_TAG_NAME);
6161*5e7646d2SAndroid Build Coastguard Worker include = ippFindAttribute(con->request, "include-schemes", IPP_TAG_NAME);
6162*5e7646d2SAndroid Build Coastguard Worker
6163*5e7646d2SAndroid Build Coastguard Worker if (requested)
6164*5e7646d2SAndroid Build Coastguard Worker url_encode_attr(requested, requested_str, sizeof(requested_str));
6165*5e7646d2SAndroid Build Coastguard Worker else
6166*5e7646d2SAndroid Build Coastguard Worker strlcpy(requested_str, "requested-attributes=all", sizeof(requested_str));
6167*5e7646d2SAndroid Build Coastguard Worker
6168*5e7646d2SAndroid Build Coastguard Worker if (exclude)
6169*5e7646d2SAndroid Build Coastguard Worker url_encode_attr(exclude, exclude_str, sizeof(exclude_str));
6170*5e7646d2SAndroid Build Coastguard Worker else
6171*5e7646d2SAndroid Build Coastguard Worker exclude_str[0] = '\0';
6172*5e7646d2SAndroid Build Coastguard Worker
6173*5e7646d2SAndroid Build Coastguard Worker if (include)
6174*5e7646d2SAndroid Build Coastguard Worker url_encode_attr(include, include_str, sizeof(include_str));
6175*5e7646d2SAndroid Build Coastguard Worker else
6176*5e7646d2SAndroid Build Coastguard Worker include_str[0] = '\0';
6177*5e7646d2SAndroid Build Coastguard Worker
6178*5e7646d2SAndroid Build Coastguard Worker snprintf(command, sizeof(command), "%s/daemon/cups-deviced", ServerBin);
6179*5e7646d2SAndroid Build Coastguard Worker snprintf(options, sizeof(options),
6180*5e7646d2SAndroid Build Coastguard Worker "%d+%d+%d+%d+%s%s%s%s%s",
6181*5e7646d2SAndroid Build Coastguard Worker con->request->request.op.request_id,
6182*5e7646d2SAndroid Build Coastguard Worker limit ? limit->values[0].integer : 0,
6183*5e7646d2SAndroid Build Coastguard Worker timeout ? timeout->values[0].integer : 15,
6184*5e7646d2SAndroid Build Coastguard Worker (int)User,
6185*5e7646d2SAndroid Build Coastguard Worker requested_str,
6186*5e7646d2SAndroid Build Coastguard Worker exclude_str[0] ? "%20" : "", exclude_str,
6187*5e7646d2SAndroid Build Coastguard Worker include_str[0] ? "%20" : "", include_str);
6188*5e7646d2SAndroid Build Coastguard Worker
6189*5e7646d2SAndroid Build Coastguard Worker if (cupsdSendCommand(con, command, options, 1))
6190*5e7646d2SAndroid Build Coastguard Worker {
6191*5e7646d2SAndroid Build Coastguard Worker /*
6192*5e7646d2SAndroid Build Coastguard Worker * Command started successfully, don't send an IPP response here...
6193*5e7646d2SAndroid Build Coastguard Worker */
6194*5e7646d2SAndroid Build Coastguard Worker
6195*5e7646d2SAndroid Build Coastguard Worker ippDelete(con->response);
6196*5e7646d2SAndroid Build Coastguard Worker con->response = NULL;
6197*5e7646d2SAndroid Build Coastguard Worker }
6198*5e7646d2SAndroid Build Coastguard Worker else
6199*5e7646d2SAndroid Build Coastguard Worker {
6200*5e7646d2SAndroid Build Coastguard Worker /*
6201*5e7646d2SAndroid Build Coastguard Worker * Command failed, return "internal error" so the user knows something
6202*5e7646d2SAndroid Build Coastguard Worker * went wrong...
6203*5e7646d2SAndroid Build Coastguard Worker */
6204*5e7646d2SAndroid Build Coastguard Worker
6205*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_INTERNAL_ERROR,
6206*5e7646d2SAndroid Build Coastguard Worker _("cups-deviced failed to execute."));
6207*5e7646d2SAndroid Build Coastguard Worker }
6208*5e7646d2SAndroid Build Coastguard Worker }
6209*5e7646d2SAndroid Build Coastguard Worker
6210*5e7646d2SAndroid Build Coastguard Worker
6211*5e7646d2SAndroid Build Coastguard Worker /*
6212*5e7646d2SAndroid Build Coastguard Worker * 'get_document()' - Get a copy of a job file.
6213*5e7646d2SAndroid Build Coastguard Worker */
6214*5e7646d2SAndroid Build Coastguard Worker
6215*5e7646d2SAndroid Build Coastguard Worker static void
get_document(cupsd_client_t * con,ipp_attribute_t * uri)6216*5e7646d2SAndroid Build Coastguard Worker get_document(cupsd_client_t *con, /* I - Client connection */
6217*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *uri) /* I - Job URI */
6218*5e7646d2SAndroid Build Coastguard Worker {
6219*5e7646d2SAndroid Build Coastguard Worker http_status_t status; /* Policy status */
6220*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *attr; /* Current attribute */
6221*5e7646d2SAndroid Build Coastguard Worker int jobid; /* Job ID */
6222*5e7646d2SAndroid Build Coastguard Worker int docnum; /* Document number */
6223*5e7646d2SAndroid Build Coastguard Worker cupsd_job_t *job; /* Current job */
6224*5e7646d2SAndroid Build Coastguard Worker char scheme[HTTP_MAX_URI], /* Method portion of URI */
6225*5e7646d2SAndroid Build Coastguard Worker username[HTTP_MAX_URI], /* Username portion of URI */
6226*5e7646d2SAndroid Build Coastguard Worker host[HTTP_MAX_URI], /* Host portion of URI */
6227*5e7646d2SAndroid Build Coastguard Worker resource[HTTP_MAX_URI]; /* Resource portion of URI */
6228*5e7646d2SAndroid Build Coastguard Worker int port; /* Port portion of URI */
6229*5e7646d2SAndroid Build Coastguard Worker char filename[1024], /* Filename for document */
6230*5e7646d2SAndroid Build Coastguard Worker format[1024]; /* Format for document */
6231*5e7646d2SAndroid Build Coastguard Worker
6232*5e7646d2SAndroid Build Coastguard Worker
6233*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_document(%p[%d], %s)", con,
6234*5e7646d2SAndroid Build Coastguard Worker con->number, uri->values[0].string.text);
6235*5e7646d2SAndroid Build Coastguard Worker
6236*5e7646d2SAndroid Build Coastguard Worker /*
6237*5e7646d2SAndroid Build Coastguard Worker * See if we have a job URI or a printer URI...
6238*5e7646d2SAndroid Build Coastguard Worker */
6239*5e7646d2SAndroid Build Coastguard Worker
6240*5e7646d2SAndroid Build Coastguard Worker if (!strcmp(uri->name, "printer-uri"))
6241*5e7646d2SAndroid Build Coastguard Worker {
6242*5e7646d2SAndroid Build Coastguard Worker /*
6243*5e7646d2SAndroid Build Coastguard Worker * Got a printer URI; see if we also have a job-id attribute...
6244*5e7646d2SAndroid Build Coastguard Worker */
6245*5e7646d2SAndroid Build Coastguard Worker
6246*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippFindAttribute(con->request, "job-id",
6247*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_INTEGER)) == NULL)
6248*5e7646d2SAndroid Build Coastguard Worker {
6249*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_BAD_REQUEST,
6250*5e7646d2SAndroid Build Coastguard Worker _("Got a printer-uri attribute but no job-id."));
6251*5e7646d2SAndroid Build Coastguard Worker return;
6252*5e7646d2SAndroid Build Coastguard Worker }
6253*5e7646d2SAndroid Build Coastguard Worker
6254*5e7646d2SAndroid Build Coastguard Worker jobid = attr->values[0].integer;
6255*5e7646d2SAndroid Build Coastguard Worker }
6256*5e7646d2SAndroid Build Coastguard Worker else
6257*5e7646d2SAndroid Build Coastguard Worker {
6258*5e7646d2SAndroid Build Coastguard Worker /*
6259*5e7646d2SAndroid Build Coastguard Worker * Got a job URI; parse it to get the job ID...
6260*5e7646d2SAndroid Build Coastguard Worker */
6261*5e7646d2SAndroid Build Coastguard Worker
6262*5e7646d2SAndroid Build Coastguard Worker httpSeparateURI(HTTP_URI_CODING_ALL, uri->values[0].string.text, scheme,
6263*5e7646d2SAndroid Build Coastguard Worker sizeof(scheme), username, sizeof(username), host,
6264*5e7646d2SAndroid Build Coastguard Worker sizeof(host), &port, resource, sizeof(resource));
6265*5e7646d2SAndroid Build Coastguard Worker
6266*5e7646d2SAndroid Build Coastguard Worker if (strncmp(resource, "/jobs/", 6))
6267*5e7646d2SAndroid Build Coastguard Worker {
6268*5e7646d2SAndroid Build Coastguard Worker /*
6269*5e7646d2SAndroid Build Coastguard Worker * Not a valid URI!
6270*5e7646d2SAndroid Build Coastguard Worker */
6271*5e7646d2SAndroid Build Coastguard Worker
6272*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_BAD_REQUEST, _("Bad job-uri \"%s\"."),
6273*5e7646d2SAndroid Build Coastguard Worker uri->values[0].string.text);
6274*5e7646d2SAndroid Build Coastguard Worker return;
6275*5e7646d2SAndroid Build Coastguard Worker }
6276*5e7646d2SAndroid Build Coastguard Worker
6277*5e7646d2SAndroid Build Coastguard Worker jobid = atoi(resource + 6);
6278*5e7646d2SAndroid Build Coastguard Worker }
6279*5e7646d2SAndroid Build Coastguard Worker
6280*5e7646d2SAndroid Build Coastguard Worker /*
6281*5e7646d2SAndroid Build Coastguard Worker * See if the job exists...
6282*5e7646d2SAndroid Build Coastguard Worker */
6283*5e7646d2SAndroid Build Coastguard Worker
6284*5e7646d2SAndroid Build Coastguard Worker if ((job = cupsdFindJob(jobid)) == NULL)
6285*5e7646d2SAndroid Build Coastguard Worker {
6286*5e7646d2SAndroid Build Coastguard Worker /*
6287*5e7646d2SAndroid Build Coastguard Worker * Nope - return a "not found" error...
6288*5e7646d2SAndroid Build Coastguard Worker */
6289*5e7646d2SAndroid Build Coastguard Worker
6290*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_NOT_FOUND, _("Job #%d does not exist."), jobid);
6291*5e7646d2SAndroid Build Coastguard Worker return;
6292*5e7646d2SAndroid Build Coastguard Worker }
6293*5e7646d2SAndroid Build Coastguard Worker
6294*5e7646d2SAndroid Build Coastguard Worker /*
6295*5e7646d2SAndroid Build Coastguard Worker * Check policy...
6296*5e7646d2SAndroid Build Coastguard Worker */
6297*5e7646d2SAndroid Build Coastguard Worker
6298*5e7646d2SAndroid Build Coastguard Worker if ((status = cupsdCheckPolicy(DefaultPolicyPtr, con,
6299*5e7646d2SAndroid Build Coastguard Worker job->username)) != HTTP_OK)
6300*5e7646d2SAndroid Build Coastguard Worker {
6301*5e7646d2SAndroid Build Coastguard Worker send_http_error(con, status, NULL);
6302*5e7646d2SAndroid Build Coastguard Worker return;
6303*5e7646d2SAndroid Build Coastguard Worker }
6304*5e7646d2SAndroid Build Coastguard Worker
6305*5e7646d2SAndroid Build Coastguard Worker /*
6306*5e7646d2SAndroid Build Coastguard Worker * Get the document number...
6307*5e7646d2SAndroid Build Coastguard Worker */
6308*5e7646d2SAndroid Build Coastguard Worker
6309*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippFindAttribute(con->request, "document-number",
6310*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_INTEGER)) == NULL)
6311*5e7646d2SAndroid Build Coastguard Worker {
6312*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_BAD_REQUEST,
6313*5e7646d2SAndroid Build Coastguard Worker _("Missing document-number attribute."));
6314*5e7646d2SAndroid Build Coastguard Worker return;
6315*5e7646d2SAndroid Build Coastguard Worker }
6316*5e7646d2SAndroid Build Coastguard Worker
6317*5e7646d2SAndroid Build Coastguard Worker if ((docnum = attr->values[0].integer) < 1 || docnum > job->num_files ||
6318*5e7646d2SAndroid Build Coastguard Worker attr->num_values > 1)
6319*5e7646d2SAndroid Build Coastguard Worker {
6320*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_NOT_FOUND,
6321*5e7646d2SAndroid Build Coastguard Worker _("Document #%d does not exist in job #%d."), docnum,
6322*5e7646d2SAndroid Build Coastguard Worker jobid);
6323*5e7646d2SAndroid Build Coastguard Worker return;
6324*5e7646d2SAndroid Build Coastguard Worker }
6325*5e7646d2SAndroid Build Coastguard Worker
6326*5e7646d2SAndroid Build Coastguard Worker snprintf(filename, sizeof(filename), "%s/d%05d-%03d", RequestRoot, jobid,
6327*5e7646d2SAndroid Build Coastguard Worker docnum);
6328*5e7646d2SAndroid Build Coastguard Worker if ((con->file = open(filename, O_RDONLY)) == -1)
6329*5e7646d2SAndroid Build Coastguard Worker {
6330*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_ERROR,
6331*5e7646d2SAndroid Build Coastguard Worker "Unable to open document %d in job %d - %s", docnum, jobid,
6332*5e7646d2SAndroid Build Coastguard Worker strerror(errno));
6333*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_NOT_FOUND,
6334*5e7646d2SAndroid Build Coastguard Worker _("Unable to open document #%d in job #%d."), docnum,
6335*5e7646d2SAndroid Build Coastguard Worker jobid);
6336*5e7646d2SAndroid Build Coastguard Worker return;
6337*5e7646d2SAndroid Build Coastguard Worker }
6338*5e7646d2SAndroid Build Coastguard Worker
6339*5e7646d2SAndroid Build Coastguard Worker fcntl(con->file, F_SETFD, fcntl(con->file, F_GETFD) | FD_CLOEXEC);
6340*5e7646d2SAndroid Build Coastguard Worker
6341*5e7646d2SAndroid Build Coastguard Worker cupsdLoadJob(job);
6342*5e7646d2SAndroid Build Coastguard Worker
6343*5e7646d2SAndroid Build Coastguard Worker snprintf(format, sizeof(format), "%s/%s", job->filetypes[docnum - 1]->super,
6344*5e7646d2SAndroid Build Coastguard Worker job->filetypes[docnum - 1]->type);
6345*5e7646d2SAndroid Build Coastguard Worker
6346*5e7646d2SAndroid Build Coastguard Worker ippAddString(con->response, IPP_TAG_JOB, IPP_TAG_MIMETYPE, "document-format",
6347*5e7646d2SAndroid Build Coastguard Worker NULL, format);
6348*5e7646d2SAndroid Build Coastguard Worker ippAddInteger(con->response, IPP_TAG_JOB, IPP_TAG_INTEGER, "document-number",
6349*5e7646d2SAndroid Build Coastguard Worker docnum);
6350*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippFindAttribute(job->attrs, "document-name",
6351*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_NAME)) != NULL)
6352*5e7646d2SAndroid Build Coastguard Worker ippAddString(con->response, IPP_TAG_JOB, IPP_TAG_NAME, "document-name",
6353*5e7646d2SAndroid Build Coastguard Worker NULL, attr->values[0].string.text);
6354*5e7646d2SAndroid Build Coastguard Worker }
6355*5e7646d2SAndroid Build Coastguard Worker
6356*5e7646d2SAndroid Build Coastguard Worker
6357*5e7646d2SAndroid Build Coastguard Worker /*
6358*5e7646d2SAndroid Build Coastguard Worker * 'get_job_attrs()' - Get job attributes.
6359*5e7646d2SAndroid Build Coastguard Worker */
6360*5e7646d2SAndroid Build Coastguard Worker
6361*5e7646d2SAndroid Build Coastguard Worker static void
get_job_attrs(cupsd_client_t * con,ipp_attribute_t * uri)6362*5e7646d2SAndroid Build Coastguard Worker get_job_attrs(cupsd_client_t *con, /* I - Client connection */
6363*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *uri) /* I - Job URI */
6364*5e7646d2SAndroid Build Coastguard Worker {
6365*5e7646d2SAndroid Build Coastguard Worker http_status_t status; /* Policy status */
6366*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *attr; /* Current attribute */
6367*5e7646d2SAndroid Build Coastguard Worker int jobid; /* Job ID */
6368*5e7646d2SAndroid Build Coastguard Worker cupsd_job_t *job; /* Current job */
6369*5e7646d2SAndroid Build Coastguard Worker cupsd_printer_t *printer; /* Current printer */
6370*5e7646d2SAndroid Build Coastguard Worker cupsd_policy_t *policy; /* Current security policy */
6371*5e7646d2SAndroid Build Coastguard Worker char scheme[HTTP_MAX_URI], /* Scheme portion of URI */
6372*5e7646d2SAndroid Build Coastguard Worker username[HTTP_MAX_URI], /* Username portion of URI */
6373*5e7646d2SAndroid Build Coastguard Worker host[HTTP_MAX_URI], /* Host portion of URI */
6374*5e7646d2SAndroid Build Coastguard Worker resource[HTTP_MAX_URI]; /* Resource portion of URI */
6375*5e7646d2SAndroid Build Coastguard Worker int port; /* Port portion of URI */
6376*5e7646d2SAndroid Build Coastguard Worker cups_array_t *ra, /* Requested attributes array */
6377*5e7646d2SAndroid Build Coastguard Worker *exclude; /* Private attributes array */
6378*5e7646d2SAndroid Build Coastguard Worker
6379*5e7646d2SAndroid Build Coastguard Worker
6380*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_job_attrs(%p[%d], %s)", con,
6381*5e7646d2SAndroid Build Coastguard Worker con->number, uri->values[0].string.text);
6382*5e7646d2SAndroid Build Coastguard Worker
6383*5e7646d2SAndroid Build Coastguard Worker /*
6384*5e7646d2SAndroid Build Coastguard Worker * See if we have a job URI or a printer URI...
6385*5e7646d2SAndroid Build Coastguard Worker */
6386*5e7646d2SAndroid Build Coastguard Worker
6387*5e7646d2SAndroid Build Coastguard Worker if (!strcmp(uri->name, "printer-uri"))
6388*5e7646d2SAndroid Build Coastguard Worker {
6389*5e7646d2SAndroid Build Coastguard Worker /*
6390*5e7646d2SAndroid Build Coastguard Worker * Got a printer URI; see if we also have a job-id attribute...
6391*5e7646d2SAndroid Build Coastguard Worker */
6392*5e7646d2SAndroid Build Coastguard Worker
6393*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippFindAttribute(con->request, "job-id",
6394*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_INTEGER)) == NULL)
6395*5e7646d2SAndroid Build Coastguard Worker {
6396*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_BAD_REQUEST,
6397*5e7646d2SAndroid Build Coastguard Worker _("Got a printer-uri attribute but no job-id."));
6398*5e7646d2SAndroid Build Coastguard Worker return;
6399*5e7646d2SAndroid Build Coastguard Worker }
6400*5e7646d2SAndroid Build Coastguard Worker
6401*5e7646d2SAndroid Build Coastguard Worker jobid = attr->values[0].integer;
6402*5e7646d2SAndroid Build Coastguard Worker }
6403*5e7646d2SAndroid Build Coastguard Worker else
6404*5e7646d2SAndroid Build Coastguard Worker {
6405*5e7646d2SAndroid Build Coastguard Worker /*
6406*5e7646d2SAndroid Build Coastguard Worker * Got a job URI; parse it to get the job ID...
6407*5e7646d2SAndroid Build Coastguard Worker */
6408*5e7646d2SAndroid Build Coastguard Worker
6409*5e7646d2SAndroid Build Coastguard Worker httpSeparateURI(HTTP_URI_CODING_ALL, uri->values[0].string.text, scheme,
6410*5e7646d2SAndroid Build Coastguard Worker sizeof(scheme), username, sizeof(username), host,
6411*5e7646d2SAndroid Build Coastguard Worker sizeof(host), &port, resource, sizeof(resource));
6412*5e7646d2SAndroid Build Coastguard Worker
6413*5e7646d2SAndroid Build Coastguard Worker if (strncmp(resource, "/jobs/", 6))
6414*5e7646d2SAndroid Build Coastguard Worker {
6415*5e7646d2SAndroid Build Coastguard Worker /*
6416*5e7646d2SAndroid Build Coastguard Worker * Not a valid URI!
6417*5e7646d2SAndroid Build Coastguard Worker */
6418*5e7646d2SAndroid Build Coastguard Worker
6419*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_BAD_REQUEST, _("Bad job-uri \"%s\"."),
6420*5e7646d2SAndroid Build Coastguard Worker uri->values[0].string.text);
6421*5e7646d2SAndroid Build Coastguard Worker return;
6422*5e7646d2SAndroid Build Coastguard Worker }
6423*5e7646d2SAndroid Build Coastguard Worker
6424*5e7646d2SAndroid Build Coastguard Worker jobid = atoi(resource + 6);
6425*5e7646d2SAndroid Build Coastguard Worker }
6426*5e7646d2SAndroid Build Coastguard Worker
6427*5e7646d2SAndroid Build Coastguard Worker /*
6428*5e7646d2SAndroid Build Coastguard Worker * See if the job exists...
6429*5e7646d2SAndroid Build Coastguard Worker */
6430*5e7646d2SAndroid Build Coastguard Worker
6431*5e7646d2SAndroid Build Coastguard Worker if ((job = cupsdFindJob(jobid)) == NULL)
6432*5e7646d2SAndroid Build Coastguard Worker {
6433*5e7646d2SAndroid Build Coastguard Worker /*
6434*5e7646d2SAndroid Build Coastguard Worker * Nope - return a "not found" error...
6435*5e7646d2SAndroid Build Coastguard Worker */
6436*5e7646d2SAndroid Build Coastguard Worker
6437*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_NOT_FOUND, _("Job #%d does not exist."), jobid);
6438*5e7646d2SAndroid Build Coastguard Worker return;
6439*5e7646d2SAndroid Build Coastguard Worker }
6440*5e7646d2SAndroid Build Coastguard Worker
6441*5e7646d2SAndroid Build Coastguard Worker /*
6442*5e7646d2SAndroid Build Coastguard Worker * Check policy...
6443*5e7646d2SAndroid Build Coastguard Worker */
6444*5e7646d2SAndroid Build Coastguard Worker
6445*5e7646d2SAndroid Build Coastguard Worker if ((printer = job->printer) == NULL)
6446*5e7646d2SAndroid Build Coastguard Worker printer = cupsdFindDest(job->dest);
6447*5e7646d2SAndroid Build Coastguard Worker
6448*5e7646d2SAndroid Build Coastguard Worker if (printer)
6449*5e7646d2SAndroid Build Coastguard Worker policy = printer->op_policy_ptr;
6450*5e7646d2SAndroid Build Coastguard Worker else
6451*5e7646d2SAndroid Build Coastguard Worker policy = DefaultPolicyPtr;
6452*5e7646d2SAndroid Build Coastguard Worker
6453*5e7646d2SAndroid Build Coastguard Worker if ((status = cupsdCheckPolicy(policy, con, job->username)) != HTTP_OK)
6454*5e7646d2SAndroid Build Coastguard Worker {
6455*5e7646d2SAndroid Build Coastguard Worker send_http_error(con, status, NULL);
6456*5e7646d2SAndroid Build Coastguard Worker return;
6457*5e7646d2SAndroid Build Coastguard Worker }
6458*5e7646d2SAndroid Build Coastguard Worker
6459*5e7646d2SAndroid Build Coastguard Worker exclude = cupsdGetPrivateAttrs(policy, con, printer, job->username);
6460*5e7646d2SAndroid Build Coastguard Worker
6461*5e7646d2SAndroid Build Coastguard Worker /*
6462*5e7646d2SAndroid Build Coastguard Worker * Copy attributes...
6463*5e7646d2SAndroid Build Coastguard Worker */
6464*5e7646d2SAndroid Build Coastguard Worker
6465*5e7646d2SAndroid Build Coastguard Worker cupsdLoadJob(job);
6466*5e7646d2SAndroid Build Coastguard Worker
6467*5e7646d2SAndroid Build Coastguard Worker ra = create_requested_array(con->request);
6468*5e7646d2SAndroid Build Coastguard Worker copy_job_attrs(con, job, ra, exclude);
6469*5e7646d2SAndroid Build Coastguard Worker cupsArrayDelete(ra);
6470*5e7646d2SAndroid Build Coastguard Worker
6471*5e7646d2SAndroid Build Coastguard Worker con->response->request.status.status_code = IPP_OK;
6472*5e7646d2SAndroid Build Coastguard Worker }
6473*5e7646d2SAndroid Build Coastguard Worker
6474*5e7646d2SAndroid Build Coastguard Worker
6475*5e7646d2SAndroid Build Coastguard Worker /*
6476*5e7646d2SAndroid Build Coastguard Worker * 'get_jobs()' - Get a list of jobs for the specified printer.
6477*5e7646d2SAndroid Build Coastguard Worker */
6478*5e7646d2SAndroid Build Coastguard Worker
6479*5e7646d2SAndroid Build Coastguard Worker static void
get_jobs(cupsd_client_t * con,ipp_attribute_t * uri)6480*5e7646d2SAndroid Build Coastguard Worker get_jobs(cupsd_client_t *con, /* I - Client connection */
6481*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *uri) /* I - Printer URI */
6482*5e7646d2SAndroid Build Coastguard Worker {
6483*5e7646d2SAndroid Build Coastguard Worker http_status_t status; /* Policy status */
6484*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *attr; /* Current attribute */
6485*5e7646d2SAndroid Build Coastguard Worker const char *dest; /* Destination */
6486*5e7646d2SAndroid Build Coastguard Worker cups_ptype_t dtype; /* Destination type (printer/class) */
6487*5e7646d2SAndroid Build Coastguard Worker cups_ptype_t dmask; /* Destination type mask */
6488*5e7646d2SAndroid Build Coastguard Worker char scheme[HTTP_MAX_URI], /* Scheme portion of URI */
6489*5e7646d2SAndroid Build Coastguard Worker username[HTTP_MAX_URI], /* Username portion of URI */
6490*5e7646d2SAndroid Build Coastguard Worker host[HTTP_MAX_URI], /* Host portion of URI */
6491*5e7646d2SAndroid Build Coastguard Worker resource[HTTP_MAX_URI]; /* Resource portion of URI */
6492*5e7646d2SAndroid Build Coastguard Worker int port; /* Port portion of URI */
6493*5e7646d2SAndroid Build Coastguard Worker int job_comparison; /* Job comparison */
6494*5e7646d2SAndroid Build Coastguard Worker ipp_jstate_t job_state; /* job-state value */
6495*5e7646d2SAndroid Build Coastguard Worker int first_job_id = 1, /* First job ID */
6496*5e7646d2SAndroid Build Coastguard Worker first_index = 1, /* First index */
6497*5e7646d2SAndroid Build Coastguard Worker limit = 0, /* Maximum number of jobs to return */
6498*5e7646d2SAndroid Build Coastguard Worker count, /* Number of jobs that match */
6499*5e7646d2SAndroid Build Coastguard Worker need_load_job = 0; /* Do we need to load the job? */
6500*5e7646d2SAndroid Build Coastguard Worker const char *job_attr; /* Job attribute requested */
6501*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *job_ids; /* job-ids attribute */
6502*5e7646d2SAndroid Build Coastguard Worker cupsd_job_t *job; /* Current job pointer */
6503*5e7646d2SAndroid Build Coastguard Worker cupsd_printer_t *printer; /* Printer */
6504*5e7646d2SAndroid Build Coastguard Worker cups_array_t *list; /* Which job list... */
6505*5e7646d2SAndroid Build Coastguard Worker int delete_list = 0; /* Delete the list afterwards? */
6506*5e7646d2SAndroid Build Coastguard Worker cups_array_t *ra, /* Requested attributes array */
6507*5e7646d2SAndroid Build Coastguard Worker *exclude; /* Private attributes array */
6508*5e7646d2SAndroid Build Coastguard Worker cupsd_policy_t *policy; /* Current policy */
6509*5e7646d2SAndroid Build Coastguard Worker
6510*5e7646d2SAndroid Build Coastguard Worker
6511*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_jobs(%p[%d], %s)", con, con->number,
6512*5e7646d2SAndroid Build Coastguard Worker uri->values[0].string.text);
6513*5e7646d2SAndroid Build Coastguard Worker
6514*5e7646d2SAndroid Build Coastguard Worker /*
6515*5e7646d2SAndroid Build Coastguard Worker * Is the destination valid?
6516*5e7646d2SAndroid Build Coastguard Worker */
6517*5e7646d2SAndroid Build Coastguard Worker
6518*5e7646d2SAndroid Build Coastguard Worker if (strcmp(uri->name, "printer-uri"))
6519*5e7646d2SAndroid Build Coastguard Worker {
6520*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_BAD_REQUEST, _("No printer-uri in request."));
6521*5e7646d2SAndroid Build Coastguard Worker return;
6522*5e7646d2SAndroid Build Coastguard Worker }
6523*5e7646d2SAndroid Build Coastguard Worker
6524*5e7646d2SAndroid Build Coastguard Worker httpSeparateURI(HTTP_URI_CODING_ALL, uri->values[0].string.text, scheme,
6525*5e7646d2SAndroid Build Coastguard Worker sizeof(scheme), username, sizeof(username), host,
6526*5e7646d2SAndroid Build Coastguard Worker sizeof(host), &port, resource, sizeof(resource));
6527*5e7646d2SAndroid Build Coastguard Worker
6528*5e7646d2SAndroid Build Coastguard Worker if (!strcmp(resource, "/") || !strcmp(resource, "/jobs"))
6529*5e7646d2SAndroid Build Coastguard Worker {
6530*5e7646d2SAndroid Build Coastguard Worker dest = NULL;
6531*5e7646d2SAndroid Build Coastguard Worker dtype = (cups_ptype_t)0;
6532*5e7646d2SAndroid Build Coastguard Worker dmask = (cups_ptype_t)0;
6533*5e7646d2SAndroid Build Coastguard Worker printer = NULL;
6534*5e7646d2SAndroid Build Coastguard Worker }
6535*5e7646d2SAndroid Build Coastguard Worker else if (!strncmp(resource, "/printers", 9) && strlen(resource) <= 10)
6536*5e7646d2SAndroid Build Coastguard Worker {
6537*5e7646d2SAndroid Build Coastguard Worker dest = NULL;
6538*5e7646d2SAndroid Build Coastguard Worker dtype = (cups_ptype_t)0;
6539*5e7646d2SAndroid Build Coastguard Worker dmask = CUPS_PRINTER_CLASS;
6540*5e7646d2SAndroid Build Coastguard Worker printer = NULL;
6541*5e7646d2SAndroid Build Coastguard Worker }
6542*5e7646d2SAndroid Build Coastguard Worker else if (!strncmp(resource, "/classes", 8) && strlen(resource) <= 9)
6543*5e7646d2SAndroid Build Coastguard Worker {
6544*5e7646d2SAndroid Build Coastguard Worker dest = NULL;
6545*5e7646d2SAndroid Build Coastguard Worker dtype = CUPS_PRINTER_CLASS;
6546*5e7646d2SAndroid Build Coastguard Worker dmask = CUPS_PRINTER_CLASS;
6547*5e7646d2SAndroid Build Coastguard Worker printer = NULL;
6548*5e7646d2SAndroid Build Coastguard Worker }
6549*5e7646d2SAndroid Build Coastguard Worker else if ((dest = cupsdValidateDest(uri->values[0].string.text, &dtype,
6550*5e7646d2SAndroid Build Coastguard Worker &printer)) == NULL)
6551*5e7646d2SAndroid Build Coastguard Worker {
6552*5e7646d2SAndroid Build Coastguard Worker /*
6553*5e7646d2SAndroid Build Coastguard Worker * Bad URI...
6554*5e7646d2SAndroid Build Coastguard Worker */
6555*5e7646d2SAndroid Build Coastguard Worker
6556*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_NOT_FOUND,
6557*5e7646d2SAndroid Build Coastguard Worker _("The printer or class does not exist."));
6558*5e7646d2SAndroid Build Coastguard Worker return;
6559*5e7646d2SAndroid Build Coastguard Worker }
6560*5e7646d2SAndroid Build Coastguard Worker else
6561*5e7646d2SAndroid Build Coastguard Worker {
6562*5e7646d2SAndroid Build Coastguard Worker dtype &= CUPS_PRINTER_CLASS;
6563*5e7646d2SAndroid Build Coastguard Worker dmask = CUPS_PRINTER_CLASS;
6564*5e7646d2SAndroid Build Coastguard Worker }
6565*5e7646d2SAndroid Build Coastguard Worker
6566*5e7646d2SAndroid Build Coastguard Worker /*
6567*5e7646d2SAndroid Build Coastguard Worker * Check policy...
6568*5e7646d2SAndroid Build Coastguard Worker */
6569*5e7646d2SAndroid Build Coastguard Worker
6570*5e7646d2SAndroid Build Coastguard Worker if (printer)
6571*5e7646d2SAndroid Build Coastguard Worker policy = printer->op_policy_ptr;
6572*5e7646d2SAndroid Build Coastguard Worker else
6573*5e7646d2SAndroid Build Coastguard Worker policy = DefaultPolicyPtr;
6574*5e7646d2SAndroid Build Coastguard Worker
6575*5e7646d2SAndroid Build Coastguard Worker if ((status = cupsdCheckPolicy(policy, con, NULL)) != HTTP_OK)
6576*5e7646d2SAndroid Build Coastguard Worker {
6577*5e7646d2SAndroid Build Coastguard Worker send_http_error(con, status, NULL);
6578*5e7646d2SAndroid Build Coastguard Worker return;
6579*5e7646d2SAndroid Build Coastguard Worker }
6580*5e7646d2SAndroid Build Coastguard Worker
6581*5e7646d2SAndroid Build Coastguard Worker job_ids = ippFindAttribute(con->request, "job-ids", IPP_TAG_INTEGER);
6582*5e7646d2SAndroid Build Coastguard Worker
6583*5e7646d2SAndroid Build Coastguard Worker /*
6584*5e7646d2SAndroid Build Coastguard Worker * See if the "which-jobs" attribute have been specified...
6585*5e7646d2SAndroid Build Coastguard Worker */
6586*5e7646d2SAndroid Build Coastguard Worker
6587*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippFindAttribute(con->request, "which-jobs",
6588*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_KEYWORD)) != NULL && job_ids)
6589*5e7646d2SAndroid Build Coastguard Worker {
6590*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_CONFLICT,
6591*5e7646d2SAndroid Build Coastguard Worker _("The %s attribute cannot be provided with job-ids."),
6592*5e7646d2SAndroid Build Coastguard Worker "which-jobs");
6593*5e7646d2SAndroid Build Coastguard Worker return;
6594*5e7646d2SAndroid Build Coastguard Worker }
6595*5e7646d2SAndroid Build Coastguard Worker else if (!attr || !strcmp(attr->values[0].string.text, "not-completed"))
6596*5e7646d2SAndroid Build Coastguard Worker {
6597*5e7646d2SAndroid Build Coastguard Worker job_comparison = -1;
6598*5e7646d2SAndroid Build Coastguard Worker job_state = IPP_JOB_STOPPED;
6599*5e7646d2SAndroid Build Coastguard Worker list = ActiveJobs;
6600*5e7646d2SAndroid Build Coastguard Worker }
6601*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(attr->values[0].string.text, "completed"))
6602*5e7646d2SAndroid Build Coastguard Worker {
6603*5e7646d2SAndroid Build Coastguard Worker job_comparison = 1;
6604*5e7646d2SAndroid Build Coastguard Worker job_state = IPP_JOB_CANCELED;
6605*5e7646d2SAndroid Build Coastguard Worker list = cupsdGetCompletedJobs(printer);
6606*5e7646d2SAndroid Build Coastguard Worker delete_list = 1;
6607*5e7646d2SAndroid Build Coastguard Worker }
6608*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(attr->values[0].string.text, "aborted"))
6609*5e7646d2SAndroid Build Coastguard Worker {
6610*5e7646d2SAndroid Build Coastguard Worker job_comparison = 0;
6611*5e7646d2SAndroid Build Coastguard Worker job_state = IPP_JOB_ABORTED;
6612*5e7646d2SAndroid Build Coastguard Worker list = cupsdGetCompletedJobs(printer);
6613*5e7646d2SAndroid Build Coastguard Worker delete_list = 1;
6614*5e7646d2SAndroid Build Coastguard Worker }
6615*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(attr->values[0].string.text, "all"))
6616*5e7646d2SAndroid Build Coastguard Worker {
6617*5e7646d2SAndroid Build Coastguard Worker job_comparison = 1;
6618*5e7646d2SAndroid Build Coastguard Worker job_state = IPP_JOB_PENDING;
6619*5e7646d2SAndroid Build Coastguard Worker list = Jobs;
6620*5e7646d2SAndroid Build Coastguard Worker }
6621*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(attr->values[0].string.text, "canceled"))
6622*5e7646d2SAndroid Build Coastguard Worker {
6623*5e7646d2SAndroid Build Coastguard Worker job_comparison = 0;
6624*5e7646d2SAndroid Build Coastguard Worker job_state = IPP_JOB_CANCELED;
6625*5e7646d2SAndroid Build Coastguard Worker list = cupsdGetCompletedJobs(printer);
6626*5e7646d2SAndroid Build Coastguard Worker delete_list = 1;
6627*5e7646d2SAndroid Build Coastguard Worker }
6628*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(attr->values[0].string.text, "pending"))
6629*5e7646d2SAndroid Build Coastguard Worker {
6630*5e7646d2SAndroid Build Coastguard Worker job_comparison = 0;
6631*5e7646d2SAndroid Build Coastguard Worker job_state = IPP_JOB_PENDING;
6632*5e7646d2SAndroid Build Coastguard Worker list = ActiveJobs;
6633*5e7646d2SAndroid Build Coastguard Worker }
6634*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(attr->values[0].string.text, "pending-held"))
6635*5e7646d2SAndroid Build Coastguard Worker {
6636*5e7646d2SAndroid Build Coastguard Worker job_comparison = 0;
6637*5e7646d2SAndroid Build Coastguard Worker job_state = IPP_JOB_HELD;
6638*5e7646d2SAndroid Build Coastguard Worker list = ActiveJobs;
6639*5e7646d2SAndroid Build Coastguard Worker }
6640*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(attr->values[0].string.text, "processing"))
6641*5e7646d2SAndroid Build Coastguard Worker {
6642*5e7646d2SAndroid Build Coastguard Worker job_comparison = 0;
6643*5e7646d2SAndroid Build Coastguard Worker job_state = IPP_JOB_PROCESSING;
6644*5e7646d2SAndroid Build Coastguard Worker list = PrintingJobs;
6645*5e7646d2SAndroid Build Coastguard Worker }
6646*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(attr->values[0].string.text, "processing-stopped"))
6647*5e7646d2SAndroid Build Coastguard Worker {
6648*5e7646d2SAndroid Build Coastguard Worker job_comparison = 0;
6649*5e7646d2SAndroid Build Coastguard Worker job_state = IPP_JOB_STOPPED;
6650*5e7646d2SAndroid Build Coastguard Worker list = ActiveJobs;
6651*5e7646d2SAndroid Build Coastguard Worker }
6652*5e7646d2SAndroid Build Coastguard Worker else
6653*5e7646d2SAndroid Build Coastguard Worker {
6654*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_ATTRIBUTES,
6655*5e7646d2SAndroid Build Coastguard Worker _("The which-jobs value \"%s\" is not supported."),
6656*5e7646d2SAndroid Build Coastguard Worker attr->values[0].string.text);
6657*5e7646d2SAndroid Build Coastguard Worker ippAddString(con->response, IPP_TAG_UNSUPPORTED_GROUP, IPP_TAG_KEYWORD,
6658*5e7646d2SAndroid Build Coastguard Worker "which-jobs", NULL, attr->values[0].string.text);
6659*5e7646d2SAndroid Build Coastguard Worker return;
6660*5e7646d2SAndroid Build Coastguard Worker }
6661*5e7646d2SAndroid Build Coastguard Worker
6662*5e7646d2SAndroid Build Coastguard Worker /*
6663*5e7646d2SAndroid Build Coastguard Worker * See if they want to limit the number of jobs reported...
6664*5e7646d2SAndroid Build Coastguard Worker */
6665*5e7646d2SAndroid Build Coastguard Worker
6666*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippFindAttribute(con->request, "limit", IPP_TAG_INTEGER)) != NULL)
6667*5e7646d2SAndroid Build Coastguard Worker {
6668*5e7646d2SAndroid Build Coastguard Worker if (job_ids)
6669*5e7646d2SAndroid Build Coastguard Worker {
6670*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_CONFLICT,
6671*5e7646d2SAndroid Build Coastguard Worker _("The %s attribute cannot be provided with job-ids."),
6672*5e7646d2SAndroid Build Coastguard Worker "limit");
6673*5e7646d2SAndroid Build Coastguard Worker return;
6674*5e7646d2SAndroid Build Coastguard Worker }
6675*5e7646d2SAndroid Build Coastguard Worker
6676*5e7646d2SAndroid Build Coastguard Worker limit = attr->values[0].integer;
6677*5e7646d2SAndroid Build Coastguard Worker }
6678*5e7646d2SAndroid Build Coastguard Worker
6679*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippFindAttribute(con->request, "first-index", IPP_TAG_INTEGER)) != NULL)
6680*5e7646d2SAndroid Build Coastguard Worker {
6681*5e7646d2SAndroid Build Coastguard Worker if (job_ids)
6682*5e7646d2SAndroid Build Coastguard Worker {
6683*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_CONFLICT,
6684*5e7646d2SAndroid Build Coastguard Worker _("The %s attribute cannot be provided with job-ids."),
6685*5e7646d2SAndroid Build Coastguard Worker "first-index");
6686*5e7646d2SAndroid Build Coastguard Worker return;
6687*5e7646d2SAndroid Build Coastguard Worker }
6688*5e7646d2SAndroid Build Coastguard Worker
6689*5e7646d2SAndroid Build Coastguard Worker first_index = attr->values[0].integer;
6690*5e7646d2SAndroid Build Coastguard Worker }
6691*5e7646d2SAndroid Build Coastguard Worker else if ((attr = ippFindAttribute(con->request, "first-job-id", IPP_TAG_INTEGER)) != NULL)
6692*5e7646d2SAndroid Build Coastguard Worker {
6693*5e7646d2SAndroid Build Coastguard Worker if (job_ids)
6694*5e7646d2SAndroid Build Coastguard Worker {
6695*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_CONFLICT,
6696*5e7646d2SAndroid Build Coastguard Worker _("The %s attribute cannot be provided with job-ids."),
6697*5e7646d2SAndroid Build Coastguard Worker "first-job-id");
6698*5e7646d2SAndroid Build Coastguard Worker return;
6699*5e7646d2SAndroid Build Coastguard Worker }
6700*5e7646d2SAndroid Build Coastguard Worker
6701*5e7646d2SAndroid Build Coastguard Worker first_job_id = attr->values[0].integer;
6702*5e7646d2SAndroid Build Coastguard Worker }
6703*5e7646d2SAndroid Build Coastguard Worker
6704*5e7646d2SAndroid Build Coastguard Worker /*
6705*5e7646d2SAndroid Build Coastguard Worker * See if we only want to see jobs for a specific user...
6706*5e7646d2SAndroid Build Coastguard Worker */
6707*5e7646d2SAndroid Build Coastguard Worker
6708*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippFindAttribute(con->request, "my-jobs", IPP_TAG_BOOLEAN)) != NULL && job_ids)
6709*5e7646d2SAndroid Build Coastguard Worker {
6710*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_CONFLICT,
6711*5e7646d2SAndroid Build Coastguard Worker _("The %s attribute cannot be provided with job-ids."),
6712*5e7646d2SAndroid Build Coastguard Worker "my-jobs");
6713*5e7646d2SAndroid Build Coastguard Worker return;
6714*5e7646d2SAndroid Build Coastguard Worker }
6715*5e7646d2SAndroid Build Coastguard Worker else if (attr && attr->values[0].boolean)
6716*5e7646d2SAndroid Build Coastguard Worker strlcpy(username, get_username(con), sizeof(username));
6717*5e7646d2SAndroid Build Coastguard Worker else
6718*5e7646d2SAndroid Build Coastguard Worker username[0] = '\0';
6719*5e7646d2SAndroid Build Coastguard Worker
6720*5e7646d2SAndroid Build Coastguard Worker ra = create_requested_array(con->request);
6721*5e7646d2SAndroid Build Coastguard Worker for (job_attr = (char *)cupsArrayFirst(ra); job_attr; job_attr = (char *)cupsArrayNext(ra))
6722*5e7646d2SAndroid Build Coastguard Worker if (strcmp(job_attr, "job-id") &&
6723*5e7646d2SAndroid Build Coastguard Worker strcmp(job_attr, "job-k-octets") &&
6724*5e7646d2SAndroid Build Coastguard Worker strcmp(job_attr, "job-media-progress") &&
6725*5e7646d2SAndroid Build Coastguard Worker strcmp(job_attr, "job-more-info") &&
6726*5e7646d2SAndroid Build Coastguard Worker strcmp(job_attr, "job-name") &&
6727*5e7646d2SAndroid Build Coastguard Worker strcmp(job_attr, "job-originating-user-name") &&
6728*5e7646d2SAndroid Build Coastguard Worker strcmp(job_attr, "job-preserved") &&
6729*5e7646d2SAndroid Build Coastguard Worker strcmp(job_attr, "job-printer-up-time") &&
6730*5e7646d2SAndroid Build Coastguard Worker strcmp(job_attr, "job-printer-uri") &&
6731*5e7646d2SAndroid Build Coastguard Worker strcmp(job_attr, "job-state") &&
6732*5e7646d2SAndroid Build Coastguard Worker strcmp(job_attr, "job-state-reasons") &&
6733*5e7646d2SAndroid Build Coastguard Worker strcmp(job_attr, "job-uri") &&
6734*5e7646d2SAndroid Build Coastguard Worker strcmp(job_attr, "time-at-completed") &&
6735*5e7646d2SAndroid Build Coastguard Worker strcmp(job_attr, "time-at-creation") &&
6736*5e7646d2SAndroid Build Coastguard Worker strcmp(job_attr, "number-of-documents"))
6737*5e7646d2SAndroid Build Coastguard Worker {
6738*5e7646d2SAndroid Build Coastguard Worker need_load_job = 1;
6739*5e7646d2SAndroid Build Coastguard Worker break;
6740*5e7646d2SAndroid Build Coastguard Worker }
6741*5e7646d2SAndroid Build Coastguard Worker
6742*5e7646d2SAndroid Build Coastguard Worker if (need_load_job && (limit == 0 || limit > 500) && (list == Jobs || delete_list))
6743*5e7646d2SAndroid Build Coastguard Worker {
6744*5e7646d2SAndroid Build Coastguard Worker /*
6745*5e7646d2SAndroid Build Coastguard Worker * Limit expensive Get-Jobs for job history to 500 jobs...
6746*5e7646d2SAndroid Build Coastguard Worker */
6747*5e7646d2SAndroid Build Coastguard Worker
6748*5e7646d2SAndroid Build Coastguard Worker ippAddInteger(con->response, IPP_TAG_OPERATION, IPP_TAG_INTEGER, "limit", 500);
6749*5e7646d2SAndroid Build Coastguard Worker
6750*5e7646d2SAndroid Build Coastguard Worker if (limit)
6751*5e7646d2SAndroid Build Coastguard Worker ippAddInteger(con->response, IPP_TAG_UNSUPPORTED_GROUP, IPP_TAG_INTEGER, "limit", limit);
6752*5e7646d2SAndroid Build Coastguard Worker
6753*5e7646d2SAndroid Build Coastguard Worker limit = 500;
6754*5e7646d2SAndroid Build Coastguard Worker
6755*5e7646d2SAndroid Build Coastguard Worker cupsdLogClient(con, CUPSD_LOG_INFO, "Limiting Get-Jobs response to %d jobs.", limit);
6756*5e7646d2SAndroid Build Coastguard Worker }
6757*5e7646d2SAndroid Build Coastguard Worker
6758*5e7646d2SAndroid Build Coastguard Worker /*
6759*5e7646d2SAndroid Build Coastguard Worker * OK, build a list of jobs for this printer...
6760*5e7646d2SAndroid Build Coastguard Worker */
6761*5e7646d2SAndroid Build Coastguard Worker
6762*5e7646d2SAndroid Build Coastguard Worker if (job_ids)
6763*5e7646d2SAndroid Build Coastguard Worker {
6764*5e7646d2SAndroid Build Coastguard Worker int i; /* Looping var */
6765*5e7646d2SAndroid Build Coastguard Worker
6766*5e7646d2SAndroid Build Coastguard Worker for (i = 0; i < job_ids->num_values; i ++)
6767*5e7646d2SAndroid Build Coastguard Worker {
6768*5e7646d2SAndroid Build Coastguard Worker if (!cupsdFindJob(job_ids->values[i].integer))
6769*5e7646d2SAndroid Build Coastguard Worker break;
6770*5e7646d2SAndroid Build Coastguard Worker }
6771*5e7646d2SAndroid Build Coastguard Worker
6772*5e7646d2SAndroid Build Coastguard Worker if (i < job_ids->num_values)
6773*5e7646d2SAndroid Build Coastguard Worker {
6774*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_NOT_FOUND, _("Job #%d does not exist."),
6775*5e7646d2SAndroid Build Coastguard Worker job_ids->values[i].integer);
6776*5e7646d2SAndroid Build Coastguard Worker return;
6777*5e7646d2SAndroid Build Coastguard Worker }
6778*5e7646d2SAndroid Build Coastguard Worker
6779*5e7646d2SAndroid Build Coastguard Worker for (i = 0; i < job_ids->num_values; i ++)
6780*5e7646d2SAndroid Build Coastguard Worker {
6781*5e7646d2SAndroid Build Coastguard Worker job = cupsdFindJob(job_ids->values[i].integer);
6782*5e7646d2SAndroid Build Coastguard Worker
6783*5e7646d2SAndroid Build Coastguard Worker if (need_load_job && !job->attrs)
6784*5e7646d2SAndroid Build Coastguard Worker {
6785*5e7646d2SAndroid Build Coastguard Worker cupsdLoadJob(job);
6786*5e7646d2SAndroid Build Coastguard Worker
6787*5e7646d2SAndroid Build Coastguard Worker if (!job->attrs)
6788*5e7646d2SAndroid Build Coastguard Worker {
6789*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_jobs: No attributes for job %d", job->id);
6790*5e7646d2SAndroid Build Coastguard Worker continue;
6791*5e7646d2SAndroid Build Coastguard Worker }
6792*5e7646d2SAndroid Build Coastguard Worker }
6793*5e7646d2SAndroid Build Coastguard Worker
6794*5e7646d2SAndroid Build Coastguard Worker if (i > 0)
6795*5e7646d2SAndroid Build Coastguard Worker ippAddSeparator(con->response);
6796*5e7646d2SAndroid Build Coastguard Worker
6797*5e7646d2SAndroid Build Coastguard Worker exclude = cupsdGetPrivateAttrs(job->printer ?
6798*5e7646d2SAndroid Build Coastguard Worker job->printer->op_policy_ptr :
6799*5e7646d2SAndroid Build Coastguard Worker policy, con, job->printer,
6800*5e7646d2SAndroid Build Coastguard Worker job->username);
6801*5e7646d2SAndroid Build Coastguard Worker
6802*5e7646d2SAndroid Build Coastguard Worker copy_job_attrs(con, job, ra, exclude);
6803*5e7646d2SAndroid Build Coastguard Worker }
6804*5e7646d2SAndroid Build Coastguard Worker }
6805*5e7646d2SAndroid Build Coastguard Worker else
6806*5e7646d2SAndroid Build Coastguard Worker {
6807*5e7646d2SAndroid Build Coastguard Worker if (first_index > 1)
6808*5e7646d2SAndroid Build Coastguard Worker job = (cupsd_job_t *)cupsArrayIndex(list, first_index - 1);
6809*5e7646d2SAndroid Build Coastguard Worker else
6810*5e7646d2SAndroid Build Coastguard Worker job = (cupsd_job_t *)cupsArrayFirst(list);
6811*5e7646d2SAndroid Build Coastguard Worker
6812*5e7646d2SAndroid Build Coastguard Worker for (count = 0; (limit <= 0 || count < limit) && job; job = (cupsd_job_t *)cupsArrayNext(list))
6813*5e7646d2SAndroid Build Coastguard Worker {
6814*5e7646d2SAndroid Build Coastguard Worker /*
6815*5e7646d2SAndroid Build Coastguard Worker * Filter out jobs that don't match...
6816*5e7646d2SAndroid Build Coastguard Worker */
6817*5e7646d2SAndroid Build Coastguard Worker
6818*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG2,
6819*5e7646d2SAndroid Build Coastguard Worker "get_jobs: job->id=%d, dest=\"%s\", username=\"%s\", "
6820*5e7646d2SAndroid Build Coastguard Worker "state_value=%d, attrs=%p", job->id, job->dest,
6821*5e7646d2SAndroid Build Coastguard Worker job->username, job->state_value, job->attrs);
6822*5e7646d2SAndroid Build Coastguard Worker
6823*5e7646d2SAndroid Build Coastguard Worker if (!job->dest || !job->username)
6824*5e7646d2SAndroid Build Coastguard Worker cupsdLoadJob(job);
6825*5e7646d2SAndroid Build Coastguard Worker
6826*5e7646d2SAndroid Build Coastguard Worker if (!job->dest || !job->username)
6827*5e7646d2SAndroid Build Coastguard Worker continue;
6828*5e7646d2SAndroid Build Coastguard Worker
6829*5e7646d2SAndroid Build Coastguard Worker if ((dest && strcmp(job->dest, dest)) &&
6830*5e7646d2SAndroid Build Coastguard Worker (!job->printer || !dest || strcmp(job->printer->name, dest)))
6831*5e7646d2SAndroid Build Coastguard Worker continue;
6832*5e7646d2SAndroid Build Coastguard Worker if ((job->dtype & dmask) != dtype &&
6833*5e7646d2SAndroid Build Coastguard Worker (!job->printer || (job->printer->type & dmask) != dtype))
6834*5e7646d2SAndroid Build Coastguard Worker continue;
6835*5e7646d2SAndroid Build Coastguard Worker
6836*5e7646d2SAndroid Build Coastguard Worker if ((job_comparison < 0 && job->state_value > job_state) ||
6837*5e7646d2SAndroid Build Coastguard Worker (job_comparison == 0 && job->state_value != job_state) ||
6838*5e7646d2SAndroid Build Coastguard Worker (job_comparison > 0 && job->state_value < job_state))
6839*5e7646d2SAndroid Build Coastguard Worker continue;
6840*5e7646d2SAndroid Build Coastguard Worker
6841*5e7646d2SAndroid Build Coastguard Worker if (job->id < first_job_id)
6842*5e7646d2SAndroid Build Coastguard Worker continue;
6843*5e7646d2SAndroid Build Coastguard Worker
6844*5e7646d2SAndroid Build Coastguard Worker if (need_load_job && !job->attrs)
6845*5e7646d2SAndroid Build Coastguard Worker {
6846*5e7646d2SAndroid Build Coastguard Worker cupsdLoadJob(job);
6847*5e7646d2SAndroid Build Coastguard Worker
6848*5e7646d2SAndroid Build Coastguard Worker if (!job->attrs)
6849*5e7646d2SAndroid Build Coastguard Worker {
6850*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_jobs: No attributes for job %d", job->id);
6851*5e7646d2SAndroid Build Coastguard Worker continue;
6852*5e7646d2SAndroid Build Coastguard Worker }
6853*5e7646d2SAndroid Build Coastguard Worker }
6854*5e7646d2SAndroid Build Coastguard Worker
6855*5e7646d2SAndroid Build Coastguard Worker if (username[0] && _cups_strcasecmp(username, job->username))
6856*5e7646d2SAndroid Build Coastguard Worker continue;
6857*5e7646d2SAndroid Build Coastguard Worker
6858*5e7646d2SAndroid Build Coastguard Worker if (count > 0)
6859*5e7646d2SAndroid Build Coastguard Worker ippAddSeparator(con->response);
6860*5e7646d2SAndroid Build Coastguard Worker
6861*5e7646d2SAndroid Build Coastguard Worker count ++;
6862*5e7646d2SAndroid Build Coastguard Worker
6863*5e7646d2SAndroid Build Coastguard Worker exclude = cupsdGetPrivateAttrs(job->printer ?
6864*5e7646d2SAndroid Build Coastguard Worker job->printer->op_policy_ptr :
6865*5e7646d2SAndroid Build Coastguard Worker policy, con, job->printer,
6866*5e7646d2SAndroid Build Coastguard Worker job->username);
6867*5e7646d2SAndroid Build Coastguard Worker
6868*5e7646d2SAndroid Build Coastguard Worker copy_job_attrs(con, job, ra, exclude);
6869*5e7646d2SAndroid Build Coastguard Worker }
6870*5e7646d2SAndroid Build Coastguard Worker
6871*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_jobs: count=%d", count);
6872*5e7646d2SAndroid Build Coastguard Worker }
6873*5e7646d2SAndroid Build Coastguard Worker
6874*5e7646d2SAndroid Build Coastguard Worker cupsArrayDelete(ra);
6875*5e7646d2SAndroid Build Coastguard Worker
6876*5e7646d2SAndroid Build Coastguard Worker if (delete_list)
6877*5e7646d2SAndroid Build Coastguard Worker cupsArrayDelete(list);
6878*5e7646d2SAndroid Build Coastguard Worker
6879*5e7646d2SAndroid Build Coastguard Worker con->response->request.status.status_code = IPP_OK;
6880*5e7646d2SAndroid Build Coastguard Worker }
6881*5e7646d2SAndroid Build Coastguard Worker
6882*5e7646d2SAndroid Build Coastguard Worker
6883*5e7646d2SAndroid Build Coastguard Worker /*
6884*5e7646d2SAndroid Build Coastguard Worker * 'get_notifications()' - Get events for a subscription.
6885*5e7646d2SAndroid Build Coastguard Worker */
6886*5e7646d2SAndroid Build Coastguard Worker
6887*5e7646d2SAndroid Build Coastguard Worker static void
get_notifications(cupsd_client_t * con)6888*5e7646d2SAndroid Build Coastguard Worker get_notifications(cupsd_client_t *con) /* I - Client connection */
6889*5e7646d2SAndroid Build Coastguard Worker {
6890*5e7646d2SAndroid Build Coastguard Worker int i, j; /* Looping vars */
6891*5e7646d2SAndroid Build Coastguard Worker http_status_t status; /* Policy status */
6892*5e7646d2SAndroid Build Coastguard Worker cupsd_subscription_t *sub; /* Subscription */
6893*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *ids, /* notify-subscription-ids */
6894*5e7646d2SAndroid Build Coastguard Worker *sequences; /* notify-sequence-numbers */
6895*5e7646d2SAndroid Build Coastguard Worker int min_seq; /* Minimum sequence number */
6896*5e7646d2SAndroid Build Coastguard Worker int interval; /* Poll interval */
6897*5e7646d2SAndroid Build Coastguard Worker
6898*5e7646d2SAndroid Build Coastguard Worker
6899*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_notifications(con=%p[%d])",
6900*5e7646d2SAndroid Build Coastguard Worker con, con->number);
6901*5e7646d2SAndroid Build Coastguard Worker
6902*5e7646d2SAndroid Build Coastguard Worker /*
6903*5e7646d2SAndroid Build Coastguard Worker * Get subscription attributes...
6904*5e7646d2SAndroid Build Coastguard Worker */
6905*5e7646d2SAndroid Build Coastguard Worker
6906*5e7646d2SAndroid Build Coastguard Worker ids = ippFindAttribute(con->request, "notify-subscription-ids",
6907*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_INTEGER);
6908*5e7646d2SAndroid Build Coastguard Worker sequences = ippFindAttribute(con->request, "notify-sequence-numbers",
6909*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_INTEGER);
6910*5e7646d2SAndroid Build Coastguard Worker
6911*5e7646d2SAndroid Build Coastguard Worker if (!ids)
6912*5e7646d2SAndroid Build Coastguard Worker {
6913*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_BAD_REQUEST,
6914*5e7646d2SAndroid Build Coastguard Worker _("Missing notify-subscription-ids attribute."));
6915*5e7646d2SAndroid Build Coastguard Worker return;
6916*5e7646d2SAndroid Build Coastguard Worker }
6917*5e7646d2SAndroid Build Coastguard Worker
6918*5e7646d2SAndroid Build Coastguard Worker /*
6919*5e7646d2SAndroid Build Coastguard Worker * Are the subscription IDs valid?
6920*5e7646d2SAndroid Build Coastguard Worker */
6921*5e7646d2SAndroid Build Coastguard Worker
6922*5e7646d2SAndroid Build Coastguard Worker for (i = 0, interval = 60; i < ids->num_values; i ++)
6923*5e7646d2SAndroid Build Coastguard Worker {
6924*5e7646d2SAndroid Build Coastguard Worker if ((sub = cupsdFindSubscription(ids->values[i].integer)) == NULL)
6925*5e7646d2SAndroid Build Coastguard Worker {
6926*5e7646d2SAndroid Build Coastguard Worker /*
6927*5e7646d2SAndroid Build Coastguard Worker * Bad subscription ID...
6928*5e7646d2SAndroid Build Coastguard Worker */
6929*5e7646d2SAndroid Build Coastguard Worker
6930*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_NOT_FOUND, _("Subscription #%d does not exist."),
6931*5e7646d2SAndroid Build Coastguard Worker ids->values[i].integer);
6932*5e7646d2SAndroid Build Coastguard Worker return;
6933*5e7646d2SAndroid Build Coastguard Worker }
6934*5e7646d2SAndroid Build Coastguard Worker
6935*5e7646d2SAndroid Build Coastguard Worker /*
6936*5e7646d2SAndroid Build Coastguard Worker * Check policy...
6937*5e7646d2SAndroid Build Coastguard Worker */
6938*5e7646d2SAndroid Build Coastguard Worker
6939*5e7646d2SAndroid Build Coastguard Worker if ((status = cupsdCheckPolicy(sub->dest ? sub->dest->op_policy_ptr :
6940*5e7646d2SAndroid Build Coastguard Worker DefaultPolicyPtr,
6941*5e7646d2SAndroid Build Coastguard Worker con, sub->owner)) != HTTP_OK)
6942*5e7646d2SAndroid Build Coastguard Worker {
6943*5e7646d2SAndroid Build Coastguard Worker send_http_error(con, status, sub->dest);
6944*5e7646d2SAndroid Build Coastguard Worker return;
6945*5e7646d2SAndroid Build Coastguard Worker }
6946*5e7646d2SAndroid Build Coastguard Worker
6947*5e7646d2SAndroid Build Coastguard Worker /*
6948*5e7646d2SAndroid Build Coastguard Worker * Check the subscription type and update the interval accordingly.
6949*5e7646d2SAndroid Build Coastguard Worker */
6950*5e7646d2SAndroid Build Coastguard Worker
6951*5e7646d2SAndroid Build Coastguard Worker if (sub->job && sub->job->state_value == IPP_JOB_PROCESSING &&
6952*5e7646d2SAndroid Build Coastguard Worker interval > 10)
6953*5e7646d2SAndroid Build Coastguard Worker interval = 10;
6954*5e7646d2SAndroid Build Coastguard Worker else if (sub->job && sub->job->state_value >= IPP_JOB_STOPPED)
6955*5e7646d2SAndroid Build Coastguard Worker interval = 0;
6956*5e7646d2SAndroid Build Coastguard Worker else if (sub->dest && sub->dest->state == IPP_PRINTER_PROCESSING &&
6957*5e7646d2SAndroid Build Coastguard Worker interval > 30)
6958*5e7646d2SAndroid Build Coastguard Worker interval = 30;
6959*5e7646d2SAndroid Build Coastguard Worker }
6960*5e7646d2SAndroid Build Coastguard Worker
6961*5e7646d2SAndroid Build Coastguard Worker /*
6962*5e7646d2SAndroid Build Coastguard Worker * Tell the client to poll again in N seconds...
6963*5e7646d2SAndroid Build Coastguard Worker */
6964*5e7646d2SAndroid Build Coastguard Worker
6965*5e7646d2SAndroid Build Coastguard Worker if (interval > 0)
6966*5e7646d2SAndroid Build Coastguard Worker ippAddInteger(con->response, IPP_TAG_OPERATION, IPP_TAG_INTEGER,
6967*5e7646d2SAndroid Build Coastguard Worker "notify-get-interval", interval);
6968*5e7646d2SAndroid Build Coastguard Worker
6969*5e7646d2SAndroid Build Coastguard Worker ippAddInteger(con->response, IPP_TAG_OPERATION, IPP_TAG_INTEGER,
6970*5e7646d2SAndroid Build Coastguard Worker "printer-up-time", time(NULL));
6971*5e7646d2SAndroid Build Coastguard Worker
6972*5e7646d2SAndroid Build Coastguard Worker /*
6973*5e7646d2SAndroid Build Coastguard Worker * Copy the subscription event attributes to the response.
6974*5e7646d2SAndroid Build Coastguard Worker */
6975*5e7646d2SAndroid Build Coastguard Worker
6976*5e7646d2SAndroid Build Coastguard Worker con->response->request.status.status_code =
6977*5e7646d2SAndroid Build Coastguard Worker interval ? IPP_OK : IPP_OK_EVENTS_COMPLETE;
6978*5e7646d2SAndroid Build Coastguard Worker
6979*5e7646d2SAndroid Build Coastguard Worker for (i = 0; i < ids->num_values; i ++)
6980*5e7646d2SAndroid Build Coastguard Worker {
6981*5e7646d2SAndroid Build Coastguard Worker /*
6982*5e7646d2SAndroid Build Coastguard Worker * Get the subscription and sequence number...
6983*5e7646d2SAndroid Build Coastguard Worker */
6984*5e7646d2SAndroid Build Coastguard Worker
6985*5e7646d2SAndroid Build Coastguard Worker sub = cupsdFindSubscription(ids->values[i].integer);
6986*5e7646d2SAndroid Build Coastguard Worker
6987*5e7646d2SAndroid Build Coastguard Worker if (sequences && i < sequences->num_values)
6988*5e7646d2SAndroid Build Coastguard Worker min_seq = sequences->values[i].integer;
6989*5e7646d2SAndroid Build Coastguard Worker else
6990*5e7646d2SAndroid Build Coastguard Worker min_seq = 1;
6991*5e7646d2SAndroid Build Coastguard Worker
6992*5e7646d2SAndroid Build Coastguard Worker /*
6993*5e7646d2SAndroid Build Coastguard Worker * If we don't have any new events, nothing to do here...
6994*5e7646d2SAndroid Build Coastguard Worker */
6995*5e7646d2SAndroid Build Coastguard Worker
6996*5e7646d2SAndroid Build Coastguard Worker if (min_seq > (sub->first_event_id + cupsArrayCount(sub->events)))
6997*5e7646d2SAndroid Build Coastguard Worker continue;
6998*5e7646d2SAndroid Build Coastguard Worker
6999*5e7646d2SAndroid Build Coastguard Worker /*
7000*5e7646d2SAndroid Build Coastguard Worker * Otherwise copy all of the new events...
7001*5e7646d2SAndroid Build Coastguard Worker */
7002*5e7646d2SAndroid Build Coastguard Worker
7003*5e7646d2SAndroid Build Coastguard Worker if (sub->first_event_id > min_seq)
7004*5e7646d2SAndroid Build Coastguard Worker j = 0;
7005*5e7646d2SAndroid Build Coastguard Worker else
7006*5e7646d2SAndroid Build Coastguard Worker j = min_seq - sub->first_event_id;
7007*5e7646d2SAndroid Build Coastguard Worker
7008*5e7646d2SAndroid Build Coastguard Worker for (; j < cupsArrayCount(sub->events); j ++)
7009*5e7646d2SAndroid Build Coastguard Worker {
7010*5e7646d2SAndroid Build Coastguard Worker ippAddSeparator(con->response);
7011*5e7646d2SAndroid Build Coastguard Worker
7012*5e7646d2SAndroid Build Coastguard Worker copy_attrs(con->response,
7013*5e7646d2SAndroid Build Coastguard Worker ((cupsd_event_t *)cupsArrayIndex(sub->events, j))->attrs, NULL,
7014*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_EVENT_NOTIFICATION, 0, NULL);
7015*5e7646d2SAndroid Build Coastguard Worker }
7016*5e7646d2SAndroid Build Coastguard Worker }
7017*5e7646d2SAndroid Build Coastguard Worker }
7018*5e7646d2SAndroid Build Coastguard Worker
7019*5e7646d2SAndroid Build Coastguard Worker
7020*5e7646d2SAndroid Build Coastguard Worker /*
7021*5e7646d2SAndroid Build Coastguard Worker * 'get_ppd()' - Get a named PPD from the local system.
7022*5e7646d2SAndroid Build Coastguard Worker */
7023*5e7646d2SAndroid Build Coastguard Worker
7024*5e7646d2SAndroid Build Coastguard Worker static void
get_ppd(cupsd_client_t * con,ipp_attribute_t * uri)7025*5e7646d2SAndroid Build Coastguard Worker get_ppd(cupsd_client_t *con, /* I - Client connection */
7026*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *uri) /* I - Printer URI or PPD name */
7027*5e7646d2SAndroid Build Coastguard Worker {
7028*5e7646d2SAndroid Build Coastguard Worker http_status_t status; /* Policy status */
7029*5e7646d2SAndroid Build Coastguard Worker cupsd_printer_t *dest; /* Destination */
7030*5e7646d2SAndroid Build Coastguard Worker cups_ptype_t dtype; /* Destination type */
7031*5e7646d2SAndroid Build Coastguard Worker
7032*5e7646d2SAndroid Build Coastguard Worker
7033*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_ppd(%p[%d], %p[%s=%s])", con,
7034*5e7646d2SAndroid Build Coastguard Worker con->number, uri, uri->name, uri->values[0].string.text);
7035*5e7646d2SAndroid Build Coastguard Worker
7036*5e7646d2SAndroid Build Coastguard Worker if (!strcmp(ippGetName(uri), "ppd-name"))
7037*5e7646d2SAndroid Build Coastguard Worker {
7038*5e7646d2SAndroid Build Coastguard Worker /*
7039*5e7646d2SAndroid Build Coastguard Worker * Return a PPD file from cups-driverd...
7040*5e7646d2SAndroid Build Coastguard Worker */
7041*5e7646d2SAndroid Build Coastguard Worker
7042*5e7646d2SAndroid Build Coastguard Worker const char *ppd_name = ippGetString(uri, 0, NULL);
7043*5e7646d2SAndroid Build Coastguard Worker /* ppd-name value */
7044*5e7646d2SAndroid Build Coastguard Worker char command[1024], /* cups-driverd command */
7045*5e7646d2SAndroid Build Coastguard Worker options[1024], /* Options to pass to command */
7046*5e7646d2SAndroid Build Coastguard Worker oppd_name[1024]; /* Escaped ppd-name */
7047*5e7646d2SAndroid Build Coastguard Worker
7048*5e7646d2SAndroid Build Coastguard Worker /*
7049*5e7646d2SAndroid Build Coastguard Worker * Check policy...
7050*5e7646d2SAndroid Build Coastguard Worker */
7051*5e7646d2SAndroid Build Coastguard Worker
7052*5e7646d2SAndroid Build Coastguard Worker if ((status = cupsdCheckPolicy(DefaultPolicyPtr, con, NULL)) != HTTP_OK)
7053*5e7646d2SAndroid Build Coastguard Worker {
7054*5e7646d2SAndroid Build Coastguard Worker send_http_error(con, status, NULL);
7055*5e7646d2SAndroid Build Coastguard Worker return;
7056*5e7646d2SAndroid Build Coastguard Worker }
7057*5e7646d2SAndroid Build Coastguard Worker
7058*5e7646d2SAndroid Build Coastguard Worker /*
7059*5e7646d2SAndroid Build Coastguard Worker * Check ppd-name value...
7060*5e7646d2SAndroid Build Coastguard Worker */
7061*5e7646d2SAndroid Build Coastguard Worker
7062*5e7646d2SAndroid Build Coastguard Worker if (strstr(ppd_name, "../"))
7063*5e7646d2SAndroid Build Coastguard Worker {
7064*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_STATUS_ERROR_ATTRIBUTES_OR_VALUES, _("Invalid ppd-name value."));
7065*5e7646d2SAndroid Build Coastguard Worker return;
7066*5e7646d2SAndroid Build Coastguard Worker }
7067*5e7646d2SAndroid Build Coastguard Worker
7068*5e7646d2SAndroid Build Coastguard Worker /*
7069*5e7646d2SAndroid Build Coastguard Worker * Run cups-driverd command with the given options...
7070*5e7646d2SAndroid Build Coastguard Worker */
7071*5e7646d2SAndroid Build Coastguard Worker
7072*5e7646d2SAndroid Build Coastguard Worker snprintf(command, sizeof(command), "%s/daemon/cups-driverd", ServerBin);
7073*5e7646d2SAndroid Build Coastguard Worker url_encode_string(ppd_name, oppd_name, sizeof(oppd_name));
7074*5e7646d2SAndroid Build Coastguard Worker snprintf(options, sizeof(options), "get+%d+%s", ippGetRequestId(con->request), oppd_name);
7075*5e7646d2SAndroid Build Coastguard Worker
7076*5e7646d2SAndroid Build Coastguard Worker if (cupsdSendCommand(con, command, options, 0))
7077*5e7646d2SAndroid Build Coastguard Worker {
7078*5e7646d2SAndroid Build Coastguard Worker /*
7079*5e7646d2SAndroid Build Coastguard Worker * Command started successfully, don't send an IPP response here...
7080*5e7646d2SAndroid Build Coastguard Worker */
7081*5e7646d2SAndroid Build Coastguard Worker
7082*5e7646d2SAndroid Build Coastguard Worker ippDelete(con->response);
7083*5e7646d2SAndroid Build Coastguard Worker con->response = NULL;
7084*5e7646d2SAndroid Build Coastguard Worker }
7085*5e7646d2SAndroid Build Coastguard Worker else
7086*5e7646d2SAndroid Build Coastguard Worker {
7087*5e7646d2SAndroid Build Coastguard Worker /*
7088*5e7646d2SAndroid Build Coastguard Worker * Command failed, return "internal error" so the user knows something
7089*5e7646d2SAndroid Build Coastguard Worker * went wrong...
7090*5e7646d2SAndroid Build Coastguard Worker */
7091*5e7646d2SAndroid Build Coastguard Worker
7092*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_INTERNAL_ERROR, _("cups-driverd failed to execute."));
7093*5e7646d2SAndroid Build Coastguard Worker }
7094*5e7646d2SAndroid Build Coastguard Worker }
7095*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(ippGetName(uri), "printer-uri") && cupsdValidateDest(ippGetString(uri, 0, NULL), &dtype, &dest))
7096*5e7646d2SAndroid Build Coastguard Worker {
7097*5e7646d2SAndroid Build Coastguard Worker int i; /* Looping var */
7098*5e7646d2SAndroid Build Coastguard Worker char filename[1024]; /* PPD filename */
7099*5e7646d2SAndroid Build Coastguard Worker
7100*5e7646d2SAndroid Build Coastguard Worker /*
7101*5e7646d2SAndroid Build Coastguard Worker * Check policy...
7102*5e7646d2SAndroid Build Coastguard Worker */
7103*5e7646d2SAndroid Build Coastguard Worker
7104*5e7646d2SAndroid Build Coastguard Worker if ((status = cupsdCheckPolicy(dest->op_policy_ptr, con, NULL)) != HTTP_OK)
7105*5e7646d2SAndroid Build Coastguard Worker {
7106*5e7646d2SAndroid Build Coastguard Worker send_http_error(con, status, dest);
7107*5e7646d2SAndroid Build Coastguard Worker return;
7108*5e7646d2SAndroid Build Coastguard Worker }
7109*5e7646d2SAndroid Build Coastguard Worker
7110*5e7646d2SAndroid Build Coastguard Worker /*
7111*5e7646d2SAndroid Build Coastguard Worker * See if we need the PPD for a class or remote printer...
7112*5e7646d2SAndroid Build Coastguard Worker */
7113*5e7646d2SAndroid Build Coastguard Worker
7114*5e7646d2SAndroid Build Coastguard Worker snprintf(filename, sizeof(filename), "%s/ppd/%s.ppd", ServerRoot, dest->name);
7115*5e7646d2SAndroid Build Coastguard Worker
7116*5e7646d2SAndroid Build Coastguard Worker if ((dtype & CUPS_PRINTER_REMOTE) && access(filename, 0))
7117*5e7646d2SAndroid Build Coastguard Worker {
7118*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_STATUS_CUPS_SEE_OTHER, _("See remote printer."));
7119*5e7646d2SAndroid Build Coastguard Worker ippAddString(con->response, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, dest->uri);
7120*5e7646d2SAndroid Build Coastguard Worker return;
7121*5e7646d2SAndroid Build Coastguard Worker }
7122*5e7646d2SAndroid Build Coastguard Worker else if (dtype & CUPS_PRINTER_CLASS)
7123*5e7646d2SAndroid Build Coastguard Worker {
7124*5e7646d2SAndroid Build Coastguard Worker for (i = 0; i < dest->num_printers; i ++)
7125*5e7646d2SAndroid Build Coastguard Worker if (!(dest->printers[i]->type & CUPS_PRINTER_CLASS))
7126*5e7646d2SAndroid Build Coastguard Worker {
7127*5e7646d2SAndroid Build Coastguard Worker snprintf(filename, sizeof(filename), "%s/ppd/%s.ppd", ServerRoot, dest->printers[i]->name);
7128*5e7646d2SAndroid Build Coastguard Worker
7129*5e7646d2SAndroid Build Coastguard Worker if (!access(filename, 0))
7130*5e7646d2SAndroid Build Coastguard Worker break;
7131*5e7646d2SAndroid Build Coastguard Worker }
7132*5e7646d2SAndroid Build Coastguard Worker
7133*5e7646d2SAndroid Build Coastguard Worker if (i < dest->num_printers)
7134*5e7646d2SAndroid Build Coastguard Worker dest = dest->printers[i];
7135*5e7646d2SAndroid Build Coastguard Worker else
7136*5e7646d2SAndroid Build Coastguard Worker {
7137*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_STATUS_CUPS_SEE_OTHER, _("See remote printer."));
7138*5e7646d2SAndroid Build Coastguard Worker ippAddString(con->response, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, dest->printers[0]->uri);
7139*5e7646d2SAndroid Build Coastguard Worker return;
7140*5e7646d2SAndroid Build Coastguard Worker }
7141*5e7646d2SAndroid Build Coastguard Worker }
7142*5e7646d2SAndroid Build Coastguard Worker
7143*5e7646d2SAndroid Build Coastguard Worker /*
7144*5e7646d2SAndroid Build Coastguard Worker * Found the printer with the PPD file, now see if there is one...
7145*5e7646d2SAndroid Build Coastguard Worker */
7146*5e7646d2SAndroid Build Coastguard Worker
7147*5e7646d2SAndroid Build Coastguard Worker if ((con->file = open(filename, O_RDONLY)) < 0)
7148*5e7646d2SAndroid Build Coastguard Worker {
7149*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_STATUS_ERROR_NOT_FOUND, _("The PPD file \"%s\" could not be opened: %s"), ippGetString(uri, 0, NULL), strerror(errno));
7150*5e7646d2SAndroid Build Coastguard Worker return;
7151*5e7646d2SAndroid Build Coastguard Worker }
7152*5e7646d2SAndroid Build Coastguard Worker
7153*5e7646d2SAndroid Build Coastguard Worker fcntl(con->file, F_SETFD, fcntl(con->file, F_GETFD) | FD_CLOEXEC);
7154*5e7646d2SAndroid Build Coastguard Worker
7155*5e7646d2SAndroid Build Coastguard Worker con->pipe_pid = 0;
7156*5e7646d2SAndroid Build Coastguard Worker
7157*5e7646d2SAndroid Build Coastguard Worker ippSetStatusCode(con->response, IPP_STATUS_OK);
7158*5e7646d2SAndroid Build Coastguard Worker }
7159*5e7646d2SAndroid Build Coastguard Worker else
7160*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_STATUS_ERROR_NOT_FOUND, _("The PPD file \"%s\" could not be found."), ippGetString(uri, 0, NULL));
7161*5e7646d2SAndroid Build Coastguard Worker }
7162*5e7646d2SAndroid Build Coastguard Worker
7163*5e7646d2SAndroid Build Coastguard Worker
7164*5e7646d2SAndroid Build Coastguard Worker /*
7165*5e7646d2SAndroid Build Coastguard Worker * 'get_ppds()' - Get the list of PPD files on the local system.
7166*5e7646d2SAndroid Build Coastguard Worker */
7167*5e7646d2SAndroid Build Coastguard Worker
7168*5e7646d2SAndroid Build Coastguard Worker static void
get_ppds(cupsd_client_t * con)7169*5e7646d2SAndroid Build Coastguard Worker get_ppds(cupsd_client_t *con) /* I - Client connection */
7170*5e7646d2SAndroid Build Coastguard Worker {
7171*5e7646d2SAndroid Build Coastguard Worker http_status_t status; /* Policy status */
7172*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *limit, /* Limit attribute */
7173*5e7646d2SAndroid Build Coastguard Worker *device, /* ppd-device-id attribute */
7174*5e7646d2SAndroid Build Coastguard Worker *language, /* ppd-natural-language attribute */
7175*5e7646d2SAndroid Build Coastguard Worker *make, /* ppd-make attribute */
7176*5e7646d2SAndroid Build Coastguard Worker *model, /* ppd-make-and-model attribute */
7177*5e7646d2SAndroid Build Coastguard Worker *model_number, /* ppd-model-number attribute */
7178*5e7646d2SAndroid Build Coastguard Worker *product, /* ppd-product attribute */
7179*5e7646d2SAndroid Build Coastguard Worker *psversion, /* ppd-psverion attribute */
7180*5e7646d2SAndroid Build Coastguard Worker *type, /* ppd-type attribute */
7181*5e7646d2SAndroid Build Coastguard Worker *requested, /* requested-attributes attribute */
7182*5e7646d2SAndroid Build Coastguard Worker *exclude, /* exclude-schemes attribute */
7183*5e7646d2SAndroid Build Coastguard Worker *include; /* include-schemes attribute */
7184*5e7646d2SAndroid Build Coastguard Worker char command[1024], /* cups-driverd command */
7185*5e7646d2SAndroid Build Coastguard Worker options[4096], /* Options to pass to command */
7186*5e7646d2SAndroid Build Coastguard Worker device_str[256],/* Escaped ppd-device-id string */
7187*5e7646d2SAndroid Build Coastguard Worker language_str[256],
7188*5e7646d2SAndroid Build Coastguard Worker /* Escaped ppd-natural-language */
7189*5e7646d2SAndroid Build Coastguard Worker make_str[256], /* Escaped ppd-make string */
7190*5e7646d2SAndroid Build Coastguard Worker model_str[256], /* Escaped ppd-make-and-model string */
7191*5e7646d2SAndroid Build Coastguard Worker model_number_str[256],
7192*5e7646d2SAndroid Build Coastguard Worker /* ppd-model-number string */
7193*5e7646d2SAndroid Build Coastguard Worker product_str[256],
7194*5e7646d2SAndroid Build Coastguard Worker /* Escaped ppd-product string */
7195*5e7646d2SAndroid Build Coastguard Worker psversion_str[256],
7196*5e7646d2SAndroid Build Coastguard Worker /* Escaped ppd-psversion string */
7197*5e7646d2SAndroid Build Coastguard Worker type_str[256], /* Escaped ppd-type string */
7198*5e7646d2SAndroid Build Coastguard Worker requested_str[256],
7199*5e7646d2SAndroid Build Coastguard Worker /* String for requested attributes */
7200*5e7646d2SAndroid Build Coastguard Worker exclude_str[512],
7201*5e7646d2SAndroid Build Coastguard Worker /* String for excluded schemes */
7202*5e7646d2SAndroid Build Coastguard Worker include_str[512];
7203*5e7646d2SAndroid Build Coastguard Worker /* String for included schemes */
7204*5e7646d2SAndroid Build Coastguard Worker
7205*5e7646d2SAndroid Build Coastguard Worker
7206*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_ppds(%p[%d])", con, con->number);
7207*5e7646d2SAndroid Build Coastguard Worker
7208*5e7646d2SAndroid Build Coastguard Worker /*
7209*5e7646d2SAndroid Build Coastguard Worker * Check policy...
7210*5e7646d2SAndroid Build Coastguard Worker */
7211*5e7646d2SAndroid Build Coastguard Worker
7212*5e7646d2SAndroid Build Coastguard Worker if ((status = cupsdCheckPolicy(DefaultPolicyPtr, con, NULL)) != HTTP_OK)
7213*5e7646d2SAndroid Build Coastguard Worker {
7214*5e7646d2SAndroid Build Coastguard Worker send_http_error(con, status, NULL);
7215*5e7646d2SAndroid Build Coastguard Worker return;
7216*5e7646d2SAndroid Build Coastguard Worker }
7217*5e7646d2SAndroid Build Coastguard Worker
7218*5e7646d2SAndroid Build Coastguard Worker /*
7219*5e7646d2SAndroid Build Coastguard Worker * Run cups-driverd command with the given options...
7220*5e7646d2SAndroid Build Coastguard Worker */
7221*5e7646d2SAndroid Build Coastguard Worker
7222*5e7646d2SAndroid Build Coastguard Worker limit = ippFindAttribute(con->request, "limit", IPP_TAG_INTEGER);
7223*5e7646d2SAndroid Build Coastguard Worker device = ippFindAttribute(con->request, "ppd-device-id", IPP_TAG_TEXT);
7224*5e7646d2SAndroid Build Coastguard Worker language = ippFindAttribute(con->request, "ppd-natural-language",
7225*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_LANGUAGE);
7226*5e7646d2SAndroid Build Coastguard Worker make = ippFindAttribute(con->request, "ppd-make", IPP_TAG_TEXT);
7227*5e7646d2SAndroid Build Coastguard Worker model = ippFindAttribute(con->request, "ppd-make-and-model",
7228*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_TEXT);
7229*5e7646d2SAndroid Build Coastguard Worker model_number = ippFindAttribute(con->request, "ppd-model-number",
7230*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_INTEGER);
7231*5e7646d2SAndroid Build Coastguard Worker product = ippFindAttribute(con->request, "ppd-product", IPP_TAG_TEXT);
7232*5e7646d2SAndroid Build Coastguard Worker psversion = ippFindAttribute(con->request, "ppd-psversion", IPP_TAG_TEXT);
7233*5e7646d2SAndroid Build Coastguard Worker type = ippFindAttribute(con->request, "ppd-type", IPP_TAG_KEYWORD);
7234*5e7646d2SAndroid Build Coastguard Worker requested = ippFindAttribute(con->request, "requested-attributes",
7235*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_KEYWORD);
7236*5e7646d2SAndroid Build Coastguard Worker exclude = ippFindAttribute(con->request, "exclude-schemes",
7237*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_NAME);
7238*5e7646d2SAndroid Build Coastguard Worker include = ippFindAttribute(con->request, "include-schemes",
7239*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_NAME);
7240*5e7646d2SAndroid Build Coastguard Worker
7241*5e7646d2SAndroid Build Coastguard Worker if (requested)
7242*5e7646d2SAndroid Build Coastguard Worker url_encode_attr(requested, requested_str, sizeof(requested_str));
7243*5e7646d2SAndroid Build Coastguard Worker else
7244*5e7646d2SAndroid Build Coastguard Worker strlcpy(requested_str, "requested-attributes=all", sizeof(requested_str));
7245*5e7646d2SAndroid Build Coastguard Worker
7246*5e7646d2SAndroid Build Coastguard Worker if (device)
7247*5e7646d2SAndroid Build Coastguard Worker url_encode_attr(device, device_str, sizeof(device_str));
7248*5e7646d2SAndroid Build Coastguard Worker else
7249*5e7646d2SAndroid Build Coastguard Worker device_str[0] = '\0';
7250*5e7646d2SAndroid Build Coastguard Worker
7251*5e7646d2SAndroid Build Coastguard Worker if (language)
7252*5e7646d2SAndroid Build Coastguard Worker url_encode_attr(language, language_str, sizeof(language_str));
7253*5e7646d2SAndroid Build Coastguard Worker else
7254*5e7646d2SAndroid Build Coastguard Worker language_str[0] = '\0';
7255*5e7646d2SAndroid Build Coastguard Worker
7256*5e7646d2SAndroid Build Coastguard Worker if (make)
7257*5e7646d2SAndroid Build Coastguard Worker url_encode_attr(make, make_str, sizeof(make_str));
7258*5e7646d2SAndroid Build Coastguard Worker else
7259*5e7646d2SAndroid Build Coastguard Worker make_str[0] = '\0';
7260*5e7646d2SAndroid Build Coastguard Worker
7261*5e7646d2SAndroid Build Coastguard Worker if (model)
7262*5e7646d2SAndroid Build Coastguard Worker url_encode_attr(model, model_str, sizeof(model_str));
7263*5e7646d2SAndroid Build Coastguard Worker else
7264*5e7646d2SAndroid Build Coastguard Worker model_str[0] = '\0';
7265*5e7646d2SAndroid Build Coastguard Worker
7266*5e7646d2SAndroid Build Coastguard Worker if (model_number)
7267*5e7646d2SAndroid Build Coastguard Worker snprintf(model_number_str, sizeof(model_number_str), "ppd-model-number=%d",
7268*5e7646d2SAndroid Build Coastguard Worker model_number->values[0].integer);
7269*5e7646d2SAndroid Build Coastguard Worker else
7270*5e7646d2SAndroid Build Coastguard Worker model_number_str[0] = '\0';
7271*5e7646d2SAndroid Build Coastguard Worker
7272*5e7646d2SAndroid Build Coastguard Worker if (product)
7273*5e7646d2SAndroid Build Coastguard Worker url_encode_attr(product, product_str, sizeof(product_str));
7274*5e7646d2SAndroid Build Coastguard Worker else
7275*5e7646d2SAndroid Build Coastguard Worker product_str[0] = '\0';
7276*5e7646d2SAndroid Build Coastguard Worker
7277*5e7646d2SAndroid Build Coastguard Worker if (psversion)
7278*5e7646d2SAndroid Build Coastguard Worker url_encode_attr(psversion, psversion_str, sizeof(psversion_str));
7279*5e7646d2SAndroid Build Coastguard Worker else
7280*5e7646d2SAndroid Build Coastguard Worker psversion_str[0] = '\0';
7281*5e7646d2SAndroid Build Coastguard Worker
7282*5e7646d2SAndroid Build Coastguard Worker if (type)
7283*5e7646d2SAndroid Build Coastguard Worker url_encode_attr(type, type_str, sizeof(type_str));
7284*5e7646d2SAndroid Build Coastguard Worker else
7285*5e7646d2SAndroid Build Coastguard Worker type_str[0] = '\0';
7286*5e7646d2SAndroid Build Coastguard Worker
7287*5e7646d2SAndroid Build Coastguard Worker if (exclude)
7288*5e7646d2SAndroid Build Coastguard Worker url_encode_attr(exclude, exclude_str, sizeof(exclude_str));
7289*5e7646d2SAndroid Build Coastguard Worker else
7290*5e7646d2SAndroid Build Coastguard Worker exclude_str[0] = '\0';
7291*5e7646d2SAndroid Build Coastguard Worker
7292*5e7646d2SAndroid Build Coastguard Worker if (include)
7293*5e7646d2SAndroid Build Coastguard Worker url_encode_attr(include, include_str, sizeof(include_str));
7294*5e7646d2SAndroid Build Coastguard Worker else
7295*5e7646d2SAndroid Build Coastguard Worker include_str[0] = '\0';
7296*5e7646d2SAndroid Build Coastguard Worker
7297*5e7646d2SAndroid Build Coastguard Worker snprintf(command, sizeof(command), "%s/daemon/cups-driverd", ServerBin);
7298*5e7646d2SAndroid Build Coastguard Worker snprintf(options, sizeof(options),
7299*5e7646d2SAndroid Build Coastguard Worker "list+%d+%d+%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
7300*5e7646d2SAndroid Build Coastguard Worker con->request->request.op.request_id,
7301*5e7646d2SAndroid Build Coastguard Worker limit ? limit->values[0].integer : 0,
7302*5e7646d2SAndroid Build Coastguard Worker requested_str,
7303*5e7646d2SAndroid Build Coastguard Worker device ? "%20" : "", device_str,
7304*5e7646d2SAndroid Build Coastguard Worker language ? "%20" : "", language_str,
7305*5e7646d2SAndroid Build Coastguard Worker make ? "%20" : "", make_str,
7306*5e7646d2SAndroid Build Coastguard Worker model ? "%20" : "", model_str,
7307*5e7646d2SAndroid Build Coastguard Worker model_number ? "%20" : "", model_number_str,
7308*5e7646d2SAndroid Build Coastguard Worker product ? "%20" : "", product_str,
7309*5e7646d2SAndroid Build Coastguard Worker psversion ? "%20" : "", psversion_str,
7310*5e7646d2SAndroid Build Coastguard Worker type ? "%20" : "", type_str,
7311*5e7646d2SAndroid Build Coastguard Worker exclude_str[0] ? "%20" : "", exclude_str,
7312*5e7646d2SAndroid Build Coastguard Worker include_str[0] ? "%20" : "", include_str);
7313*5e7646d2SAndroid Build Coastguard Worker
7314*5e7646d2SAndroid Build Coastguard Worker if (cupsdSendCommand(con, command, options, 0))
7315*5e7646d2SAndroid Build Coastguard Worker {
7316*5e7646d2SAndroid Build Coastguard Worker /*
7317*5e7646d2SAndroid Build Coastguard Worker * Command started successfully, don't send an IPP response here...
7318*5e7646d2SAndroid Build Coastguard Worker */
7319*5e7646d2SAndroid Build Coastguard Worker
7320*5e7646d2SAndroid Build Coastguard Worker ippDelete(con->response);
7321*5e7646d2SAndroid Build Coastguard Worker con->response = NULL;
7322*5e7646d2SAndroid Build Coastguard Worker }
7323*5e7646d2SAndroid Build Coastguard Worker else
7324*5e7646d2SAndroid Build Coastguard Worker {
7325*5e7646d2SAndroid Build Coastguard Worker /*
7326*5e7646d2SAndroid Build Coastguard Worker * Command failed, return "internal error" so the user knows something
7327*5e7646d2SAndroid Build Coastguard Worker * went wrong...
7328*5e7646d2SAndroid Build Coastguard Worker */
7329*5e7646d2SAndroid Build Coastguard Worker
7330*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_INTERNAL_ERROR,
7331*5e7646d2SAndroid Build Coastguard Worker _("cups-driverd failed to execute."));
7332*5e7646d2SAndroid Build Coastguard Worker }
7333*5e7646d2SAndroid Build Coastguard Worker }
7334*5e7646d2SAndroid Build Coastguard Worker
7335*5e7646d2SAndroid Build Coastguard Worker
7336*5e7646d2SAndroid Build Coastguard Worker /*
7337*5e7646d2SAndroid Build Coastguard Worker * 'get_printer_attrs()' - Get printer attributes.
7338*5e7646d2SAndroid Build Coastguard Worker */
7339*5e7646d2SAndroid Build Coastguard Worker
7340*5e7646d2SAndroid Build Coastguard Worker static void
get_printer_attrs(cupsd_client_t * con,ipp_attribute_t * uri)7341*5e7646d2SAndroid Build Coastguard Worker get_printer_attrs(cupsd_client_t *con, /* I - Client connection */
7342*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *uri) /* I - Printer URI */
7343*5e7646d2SAndroid Build Coastguard Worker {
7344*5e7646d2SAndroid Build Coastguard Worker http_status_t status; /* Policy status */
7345*5e7646d2SAndroid Build Coastguard Worker cups_ptype_t dtype; /* Destination type (printer/class) */
7346*5e7646d2SAndroid Build Coastguard Worker cupsd_printer_t *printer; /* Printer/class */
7347*5e7646d2SAndroid Build Coastguard Worker cups_array_t *ra; /* Requested attributes array */
7348*5e7646d2SAndroid Build Coastguard Worker
7349*5e7646d2SAndroid Build Coastguard Worker
7350*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_printer_attrs(%p[%d], %s)", con,
7351*5e7646d2SAndroid Build Coastguard Worker con->number, uri->values[0].string.text);
7352*5e7646d2SAndroid Build Coastguard Worker
7353*5e7646d2SAndroid Build Coastguard Worker /*
7354*5e7646d2SAndroid Build Coastguard Worker * Is the destination valid?
7355*5e7646d2SAndroid Build Coastguard Worker */
7356*5e7646d2SAndroid Build Coastguard Worker
7357*5e7646d2SAndroid Build Coastguard Worker if (!cupsdValidateDest(uri->values[0].string.text, &dtype, &printer))
7358*5e7646d2SAndroid Build Coastguard Worker {
7359*5e7646d2SAndroid Build Coastguard Worker /*
7360*5e7646d2SAndroid Build Coastguard Worker * Bad URI...
7361*5e7646d2SAndroid Build Coastguard Worker */
7362*5e7646d2SAndroid Build Coastguard Worker
7363*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_NOT_FOUND,
7364*5e7646d2SAndroid Build Coastguard Worker _("The printer or class does not exist."));
7365*5e7646d2SAndroid Build Coastguard Worker return;
7366*5e7646d2SAndroid Build Coastguard Worker }
7367*5e7646d2SAndroid Build Coastguard Worker
7368*5e7646d2SAndroid Build Coastguard Worker /*
7369*5e7646d2SAndroid Build Coastguard Worker * Check policy...
7370*5e7646d2SAndroid Build Coastguard Worker */
7371*5e7646d2SAndroid Build Coastguard Worker
7372*5e7646d2SAndroid Build Coastguard Worker if ((status = cupsdCheckPolicy(printer->op_policy_ptr, con, NULL)) != HTTP_OK)
7373*5e7646d2SAndroid Build Coastguard Worker {
7374*5e7646d2SAndroid Build Coastguard Worker send_http_error(con, status, printer);
7375*5e7646d2SAndroid Build Coastguard Worker return;
7376*5e7646d2SAndroid Build Coastguard Worker }
7377*5e7646d2SAndroid Build Coastguard Worker
7378*5e7646d2SAndroid Build Coastguard Worker /*
7379*5e7646d2SAndroid Build Coastguard Worker * Send the attributes...
7380*5e7646d2SAndroid Build Coastguard Worker */
7381*5e7646d2SAndroid Build Coastguard Worker
7382*5e7646d2SAndroid Build Coastguard Worker ra = create_requested_array(con->request);
7383*5e7646d2SAndroid Build Coastguard Worker
7384*5e7646d2SAndroid Build Coastguard Worker copy_printer_attrs(con, printer, ra);
7385*5e7646d2SAndroid Build Coastguard Worker
7386*5e7646d2SAndroid Build Coastguard Worker cupsArrayDelete(ra);
7387*5e7646d2SAndroid Build Coastguard Worker
7388*5e7646d2SAndroid Build Coastguard Worker con->response->request.status.status_code = IPP_OK;
7389*5e7646d2SAndroid Build Coastguard Worker }
7390*5e7646d2SAndroid Build Coastguard Worker
7391*5e7646d2SAndroid Build Coastguard Worker
7392*5e7646d2SAndroid Build Coastguard Worker /*
7393*5e7646d2SAndroid Build Coastguard Worker * 'get_printer_supported()' - Get printer supported values.
7394*5e7646d2SAndroid Build Coastguard Worker */
7395*5e7646d2SAndroid Build Coastguard Worker
7396*5e7646d2SAndroid Build Coastguard Worker static void
get_printer_supported(cupsd_client_t * con,ipp_attribute_t * uri)7397*5e7646d2SAndroid Build Coastguard Worker get_printer_supported(
7398*5e7646d2SAndroid Build Coastguard Worker cupsd_client_t *con, /* I - Client connection */
7399*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *uri) /* I - Printer URI */
7400*5e7646d2SAndroid Build Coastguard Worker {
7401*5e7646d2SAndroid Build Coastguard Worker http_status_t status; /* Policy status */
7402*5e7646d2SAndroid Build Coastguard Worker cups_ptype_t dtype; /* Destination type (printer/class) */
7403*5e7646d2SAndroid Build Coastguard Worker cupsd_printer_t *printer; /* Printer/class */
7404*5e7646d2SAndroid Build Coastguard Worker
7405*5e7646d2SAndroid Build Coastguard Worker
7406*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_printer_supported(%p[%d], %s)", con,
7407*5e7646d2SAndroid Build Coastguard Worker con->number, uri->values[0].string.text);
7408*5e7646d2SAndroid Build Coastguard Worker
7409*5e7646d2SAndroid Build Coastguard Worker /*
7410*5e7646d2SAndroid Build Coastguard Worker * Is the destination valid?
7411*5e7646d2SAndroid Build Coastguard Worker */
7412*5e7646d2SAndroid Build Coastguard Worker
7413*5e7646d2SAndroid Build Coastguard Worker if (!cupsdValidateDest(uri->values[0].string.text, &dtype, &printer))
7414*5e7646d2SAndroid Build Coastguard Worker {
7415*5e7646d2SAndroid Build Coastguard Worker /*
7416*5e7646d2SAndroid Build Coastguard Worker * Bad URI...
7417*5e7646d2SAndroid Build Coastguard Worker */
7418*5e7646d2SAndroid Build Coastguard Worker
7419*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_NOT_FOUND,
7420*5e7646d2SAndroid Build Coastguard Worker _("The printer or class does not exist."));
7421*5e7646d2SAndroid Build Coastguard Worker return;
7422*5e7646d2SAndroid Build Coastguard Worker }
7423*5e7646d2SAndroid Build Coastguard Worker
7424*5e7646d2SAndroid Build Coastguard Worker /*
7425*5e7646d2SAndroid Build Coastguard Worker * Check policy...
7426*5e7646d2SAndroid Build Coastguard Worker */
7427*5e7646d2SAndroid Build Coastguard Worker
7428*5e7646d2SAndroid Build Coastguard Worker if ((status = cupsdCheckPolicy(printer->op_policy_ptr, con, NULL)) != HTTP_OK)
7429*5e7646d2SAndroid Build Coastguard Worker {
7430*5e7646d2SAndroid Build Coastguard Worker send_http_error(con, status, printer);
7431*5e7646d2SAndroid Build Coastguard Worker return;
7432*5e7646d2SAndroid Build Coastguard Worker }
7433*5e7646d2SAndroid Build Coastguard Worker
7434*5e7646d2SAndroid Build Coastguard Worker /*
7435*5e7646d2SAndroid Build Coastguard Worker * Return a list of attributes that can be set via Set-Printer-Attributes.
7436*5e7646d2SAndroid Build Coastguard Worker */
7437*5e7646d2SAndroid Build Coastguard Worker
7438*5e7646d2SAndroid Build Coastguard Worker ippAddInteger(con->response, IPP_TAG_PRINTER, IPP_TAG_ADMINDEFINE,
7439*5e7646d2SAndroid Build Coastguard Worker "printer-geo-location", 0);
7440*5e7646d2SAndroid Build Coastguard Worker ippAddInteger(con->response, IPP_TAG_PRINTER, IPP_TAG_ADMINDEFINE,
7441*5e7646d2SAndroid Build Coastguard Worker "printer-info", 0);
7442*5e7646d2SAndroid Build Coastguard Worker ippAddInteger(con->response, IPP_TAG_PRINTER, IPP_TAG_ADMINDEFINE,
7443*5e7646d2SAndroid Build Coastguard Worker "printer-location", 0);
7444*5e7646d2SAndroid Build Coastguard Worker ippAddInteger(con->response, IPP_TAG_PRINTER, IPP_TAG_ADMINDEFINE,
7445*5e7646d2SAndroid Build Coastguard Worker "printer-organization", 0);
7446*5e7646d2SAndroid Build Coastguard Worker ippAddInteger(con->response, IPP_TAG_PRINTER, IPP_TAG_ADMINDEFINE,
7447*5e7646d2SAndroid Build Coastguard Worker "printer-organizational-unit", 0);
7448*5e7646d2SAndroid Build Coastguard Worker
7449*5e7646d2SAndroid Build Coastguard Worker con->response->request.status.status_code = IPP_OK;
7450*5e7646d2SAndroid Build Coastguard Worker }
7451*5e7646d2SAndroid Build Coastguard Worker
7452*5e7646d2SAndroid Build Coastguard Worker
7453*5e7646d2SAndroid Build Coastguard Worker /*
7454*5e7646d2SAndroid Build Coastguard Worker * 'get_printers()' - Get a list of printers or classes.
7455*5e7646d2SAndroid Build Coastguard Worker */
7456*5e7646d2SAndroid Build Coastguard Worker
7457*5e7646d2SAndroid Build Coastguard Worker static void
get_printers(cupsd_client_t * con,int type)7458*5e7646d2SAndroid Build Coastguard Worker get_printers(cupsd_client_t *con, /* I - Client connection */
7459*5e7646d2SAndroid Build Coastguard Worker int type) /* I - 0 or CUPS_PRINTER_CLASS */
7460*5e7646d2SAndroid Build Coastguard Worker {
7461*5e7646d2SAndroid Build Coastguard Worker http_status_t status; /* Policy status */
7462*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *attr; /* Current attribute */
7463*5e7646d2SAndroid Build Coastguard Worker int limit; /* Max number of printers to return */
7464*5e7646d2SAndroid Build Coastguard Worker int count; /* Number of printers that match */
7465*5e7646d2SAndroid Build Coastguard Worker int printer_id; /* Printer we are interested in */
7466*5e7646d2SAndroid Build Coastguard Worker cupsd_printer_t *printer; /* Current printer pointer */
7467*5e7646d2SAndroid Build Coastguard Worker cups_ptype_t printer_type, /* printer-type attribute */
7468*5e7646d2SAndroid Build Coastguard Worker printer_mask; /* printer-type-mask attribute */
7469*5e7646d2SAndroid Build Coastguard Worker char *location; /* Location string */
7470*5e7646d2SAndroid Build Coastguard Worker const char *username; /* Current user */
7471*5e7646d2SAndroid Build Coastguard Worker char *first_printer_name; /* first-printer-name attribute */
7472*5e7646d2SAndroid Build Coastguard Worker cups_array_t *ra; /* Requested attributes array */
7473*5e7646d2SAndroid Build Coastguard Worker int local; /* Local connection? */
7474*5e7646d2SAndroid Build Coastguard Worker
7475*5e7646d2SAndroid Build Coastguard Worker
7476*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_printers(%p[%d], %x)", con,
7477*5e7646d2SAndroid Build Coastguard Worker con->number, type);
7478*5e7646d2SAndroid Build Coastguard Worker
7479*5e7646d2SAndroid Build Coastguard Worker /*
7480*5e7646d2SAndroid Build Coastguard Worker * Check policy...
7481*5e7646d2SAndroid Build Coastguard Worker */
7482*5e7646d2SAndroid Build Coastguard Worker
7483*5e7646d2SAndroid Build Coastguard Worker if ((status = cupsdCheckPolicy(DefaultPolicyPtr, con, NULL)) != HTTP_OK)
7484*5e7646d2SAndroid Build Coastguard Worker {
7485*5e7646d2SAndroid Build Coastguard Worker send_http_error(con, status, NULL);
7486*5e7646d2SAndroid Build Coastguard Worker return;
7487*5e7646d2SAndroid Build Coastguard Worker }
7488*5e7646d2SAndroid Build Coastguard Worker
7489*5e7646d2SAndroid Build Coastguard Worker /*
7490*5e7646d2SAndroid Build Coastguard Worker * Check for printers...
7491*5e7646d2SAndroid Build Coastguard Worker */
7492*5e7646d2SAndroid Build Coastguard Worker
7493*5e7646d2SAndroid Build Coastguard Worker if (!Printers || !cupsArrayCount(Printers))
7494*5e7646d2SAndroid Build Coastguard Worker {
7495*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_NOT_FOUND, _("No destinations added."));
7496*5e7646d2SAndroid Build Coastguard Worker return;
7497*5e7646d2SAndroid Build Coastguard Worker }
7498*5e7646d2SAndroid Build Coastguard Worker
7499*5e7646d2SAndroid Build Coastguard Worker /*
7500*5e7646d2SAndroid Build Coastguard Worker * See if they want to limit the number of printers reported...
7501*5e7646d2SAndroid Build Coastguard Worker */
7502*5e7646d2SAndroid Build Coastguard Worker
7503*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippFindAttribute(con->request, "limit",
7504*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_INTEGER)) != NULL)
7505*5e7646d2SAndroid Build Coastguard Worker limit = attr->values[0].integer;
7506*5e7646d2SAndroid Build Coastguard Worker else
7507*5e7646d2SAndroid Build Coastguard Worker limit = 10000000;
7508*5e7646d2SAndroid Build Coastguard Worker
7509*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippFindAttribute(con->request, "first-printer-name",
7510*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_NAME)) != NULL)
7511*5e7646d2SAndroid Build Coastguard Worker first_printer_name = attr->values[0].string.text;
7512*5e7646d2SAndroid Build Coastguard Worker else
7513*5e7646d2SAndroid Build Coastguard Worker first_printer_name = NULL;
7514*5e7646d2SAndroid Build Coastguard Worker
7515*5e7646d2SAndroid Build Coastguard Worker /*
7516*5e7646d2SAndroid Build Coastguard Worker * Support filtering...
7517*5e7646d2SAndroid Build Coastguard Worker */
7518*5e7646d2SAndroid Build Coastguard Worker
7519*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippFindAttribute(con->request, "printer-id", IPP_TAG_INTEGER)) != NULL)
7520*5e7646d2SAndroid Build Coastguard Worker {
7521*5e7646d2SAndroid Build Coastguard Worker if ((printer_id = ippGetInteger(attr, 0)) <= 0)
7522*5e7646d2SAndroid Build Coastguard Worker {
7523*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_STATUS_ERROR_ATTRIBUTES_OR_VALUES, _("Bad \"printer-id\" value %d."), printer_id);
7524*5e7646d2SAndroid Build Coastguard Worker return;
7525*5e7646d2SAndroid Build Coastguard Worker }
7526*5e7646d2SAndroid Build Coastguard Worker }
7527*5e7646d2SAndroid Build Coastguard Worker else
7528*5e7646d2SAndroid Build Coastguard Worker printer_id = 0;
7529*5e7646d2SAndroid Build Coastguard Worker
7530*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippFindAttribute(con->request, "printer-type",
7531*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_ENUM)) != NULL)
7532*5e7646d2SAndroid Build Coastguard Worker printer_type = (cups_ptype_t)attr->values[0].integer;
7533*5e7646d2SAndroid Build Coastguard Worker else
7534*5e7646d2SAndroid Build Coastguard Worker printer_type = (cups_ptype_t)0;
7535*5e7646d2SAndroid Build Coastguard Worker
7536*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippFindAttribute(con->request, "printer-type-mask",
7537*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_ENUM)) != NULL)
7538*5e7646d2SAndroid Build Coastguard Worker printer_mask = (cups_ptype_t)attr->values[0].integer;
7539*5e7646d2SAndroid Build Coastguard Worker else
7540*5e7646d2SAndroid Build Coastguard Worker printer_mask = (cups_ptype_t)0;
7541*5e7646d2SAndroid Build Coastguard Worker
7542*5e7646d2SAndroid Build Coastguard Worker local = httpAddrLocalhost(&(con->clientaddr));
7543*5e7646d2SAndroid Build Coastguard Worker
7544*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippFindAttribute(con->request, "printer-location",
7545*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_TEXT)) != NULL)
7546*5e7646d2SAndroid Build Coastguard Worker location = attr->values[0].string.text;
7547*5e7646d2SAndroid Build Coastguard Worker else
7548*5e7646d2SAndroid Build Coastguard Worker location = NULL;
7549*5e7646d2SAndroid Build Coastguard Worker
7550*5e7646d2SAndroid Build Coastguard Worker if (con->username[0])
7551*5e7646d2SAndroid Build Coastguard Worker username = con->username;
7552*5e7646d2SAndroid Build Coastguard Worker else if ((attr = ippFindAttribute(con->request, "requesting-user-name",
7553*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_NAME)) != NULL)
7554*5e7646d2SAndroid Build Coastguard Worker username = attr->values[0].string.text;
7555*5e7646d2SAndroid Build Coastguard Worker else
7556*5e7646d2SAndroid Build Coastguard Worker username = NULL;
7557*5e7646d2SAndroid Build Coastguard Worker
7558*5e7646d2SAndroid Build Coastguard Worker ra = create_requested_array(con->request);
7559*5e7646d2SAndroid Build Coastguard Worker
7560*5e7646d2SAndroid Build Coastguard Worker /*
7561*5e7646d2SAndroid Build Coastguard Worker * OK, build a list of printers for this printer...
7562*5e7646d2SAndroid Build Coastguard Worker */
7563*5e7646d2SAndroid Build Coastguard Worker
7564*5e7646d2SAndroid Build Coastguard Worker if (first_printer_name)
7565*5e7646d2SAndroid Build Coastguard Worker {
7566*5e7646d2SAndroid Build Coastguard Worker if ((printer = cupsdFindDest(first_printer_name)) == NULL)
7567*5e7646d2SAndroid Build Coastguard Worker printer = (cupsd_printer_t *)cupsArrayFirst(Printers);
7568*5e7646d2SAndroid Build Coastguard Worker }
7569*5e7646d2SAndroid Build Coastguard Worker else
7570*5e7646d2SAndroid Build Coastguard Worker printer = (cupsd_printer_t *)cupsArrayFirst(Printers);
7571*5e7646d2SAndroid Build Coastguard Worker
7572*5e7646d2SAndroid Build Coastguard Worker for (count = 0;
7573*5e7646d2SAndroid Build Coastguard Worker count < limit && printer;
7574*5e7646d2SAndroid Build Coastguard Worker printer = (cupsd_printer_t *)cupsArrayNext(Printers))
7575*5e7646d2SAndroid Build Coastguard Worker {
7576*5e7646d2SAndroid Build Coastguard Worker if (!local && !printer->shared)
7577*5e7646d2SAndroid Build Coastguard Worker continue;
7578*5e7646d2SAndroid Build Coastguard Worker
7579*5e7646d2SAndroid Build Coastguard Worker if (printer_id && printer->printer_id != printer_id)
7580*5e7646d2SAndroid Build Coastguard Worker continue;
7581*5e7646d2SAndroid Build Coastguard Worker
7582*5e7646d2SAndroid Build Coastguard Worker if ((!type || (printer->type & CUPS_PRINTER_CLASS) == type) &&
7583*5e7646d2SAndroid Build Coastguard Worker (printer->type & printer_mask) == printer_type &&
7584*5e7646d2SAndroid Build Coastguard Worker (!location ||
7585*5e7646d2SAndroid Build Coastguard Worker (printer->location && !_cups_strcasecmp(printer->location, location))))
7586*5e7646d2SAndroid Build Coastguard Worker {
7587*5e7646d2SAndroid Build Coastguard Worker /*
7588*5e7646d2SAndroid Build Coastguard Worker * If a username is specified, see if it is allowed or denied
7589*5e7646d2SAndroid Build Coastguard Worker * access...
7590*5e7646d2SAndroid Build Coastguard Worker */
7591*5e7646d2SAndroid Build Coastguard Worker
7592*5e7646d2SAndroid Build Coastguard Worker if (cupsArrayCount(printer->users) && username &&
7593*5e7646d2SAndroid Build Coastguard Worker !user_allowed(printer, username))
7594*5e7646d2SAndroid Build Coastguard Worker continue;
7595*5e7646d2SAndroid Build Coastguard Worker
7596*5e7646d2SAndroid Build Coastguard Worker /*
7597*5e7646d2SAndroid Build Coastguard Worker * Add the group separator as needed...
7598*5e7646d2SAndroid Build Coastguard Worker */
7599*5e7646d2SAndroid Build Coastguard Worker
7600*5e7646d2SAndroid Build Coastguard Worker if (count > 0)
7601*5e7646d2SAndroid Build Coastguard Worker ippAddSeparator(con->response);
7602*5e7646d2SAndroid Build Coastguard Worker
7603*5e7646d2SAndroid Build Coastguard Worker count ++;
7604*5e7646d2SAndroid Build Coastguard Worker
7605*5e7646d2SAndroid Build Coastguard Worker /*
7606*5e7646d2SAndroid Build Coastguard Worker * Send the attributes...
7607*5e7646d2SAndroid Build Coastguard Worker */
7608*5e7646d2SAndroid Build Coastguard Worker
7609*5e7646d2SAndroid Build Coastguard Worker copy_printer_attrs(con, printer, ra);
7610*5e7646d2SAndroid Build Coastguard Worker }
7611*5e7646d2SAndroid Build Coastguard Worker }
7612*5e7646d2SAndroid Build Coastguard Worker
7613*5e7646d2SAndroid Build Coastguard Worker cupsArrayDelete(ra);
7614*5e7646d2SAndroid Build Coastguard Worker
7615*5e7646d2SAndroid Build Coastguard Worker con->response->request.status.status_code = IPP_OK;
7616*5e7646d2SAndroid Build Coastguard Worker }
7617*5e7646d2SAndroid Build Coastguard Worker
7618*5e7646d2SAndroid Build Coastguard Worker
7619*5e7646d2SAndroid Build Coastguard Worker /*
7620*5e7646d2SAndroid Build Coastguard Worker * 'get_subscription_attrs()' - Get subscription attributes.
7621*5e7646d2SAndroid Build Coastguard Worker */
7622*5e7646d2SAndroid Build Coastguard Worker
7623*5e7646d2SAndroid Build Coastguard Worker static void
get_subscription_attrs(cupsd_client_t * con,int sub_id)7624*5e7646d2SAndroid Build Coastguard Worker get_subscription_attrs(
7625*5e7646d2SAndroid Build Coastguard Worker cupsd_client_t *con, /* I - Client connection */
7626*5e7646d2SAndroid Build Coastguard Worker int sub_id) /* I - Subscription ID */
7627*5e7646d2SAndroid Build Coastguard Worker {
7628*5e7646d2SAndroid Build Coastguard Worker http_status_t status; /* Policy status */
7629*5e7646d2SAndroid Build Coastguard Worker cupsd_subscription_t *sub; /* Subscription */
7630*5e7646d2SAndroid Build Coastguard Worker cupsd_policy_t *policy; /* Current security policy */
7631*5e7646d2SAndroid Build Coastguard Worker cups_array_t *ra, /* Requested attributes array */
7632*5e7646d2SAndroid Build Coastguard Worker *exclude; /* Private attributes array */
7633*5e7646d2SAndroid Build Coastguard Worker
7634*5e7646d2SAndroid Build Coastguard Worker
7635*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG2,
7636*5e7646d2SAndroid Build Coastguard Worker "get_subscription_attrs(con=%p[%d], sub_id=%d)",
7637*5e7646d2SAndroid Build Coastguard Worker con, con->number, sub_id);
7638*5e7646d2SAndroid Build Coastguard Worker
7639*5e7646d2SAndroid Build Coastguard Worker /*
7640*5e7646d2SAndroid Build Coastguard Worker * Expire subscriptions as needed...
7641*5e7646d2SAndroid Build Coastguard Worker */
7642*5e7646d2SAndroid Build Coastguard Worker
7643*5e7646d2SAndroid Build Coastguard Worker cupsdExpireSubscriptions(NULL, NULL);
7644*5e7646d2SAndroid Build Coastguard Worker
7645*5e7646d2SAndroid Build Coastguard Worker /*
7646*5e7646d2SAndroid Build Coastguard Worker * Is the subscription ID valid?
7647*5e7646d2SAndroid Build Coastguard Worker */
7648*5e7646d2SAndroid Build Coastguard Worker
7649*5e7646d2SAndroid Build Coastguard Worker if ((sub = cupsdFindSubscription(sub_id)) == NULL)
7650*5e7646d2SAndroid Build Coastguard Worker {
7651*5e7646d2SAndroid Build Coastguard Worker /*
7652*5e7646d2SAndroid Build Coastguard Worker * Bad subscription ID...
7653*5e7646d2SAndroid Build Coastguard Worker */
7654*5e7646d2SAndroid Build Coastguard Worker
7655*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_NOT_FOUND, _("Subscription #%d does not exist."),
7656*5e7646d2SAndroid Build Coastguard Worker sub_id);
7657*5e7646d2SAndroid Build Coastguard Worker return;
7658*5e7646d2SAndroid Build Coastguard Worker }
7659*5e7646d2SAndroid Build Coastguard Worker
7660*5e7646d2SAndroid Build Coastguard Worker /*
7661*5e7646d2SAndroid Build Coastguard Worker * Check policy...
7662*5e7646d2SAndroid Build Coastguard Worker */
7663*5e7646d2SAndroid Build Coastguard Worker
7664*5e7646d2SAndroid Build Coastguard Worker if (sub->dest)
7665*5e7646d2SAndroid Build Coastguard Worker policy = sub->dest->op_policy_ptr;
7666*5e7646d2SAndroid Build Coastguard Worker else
7667*5e7646d2SAndroid Build Coastguard Worker policy = DefaultPolicyPtr;
7668*5e7646d2SAndroid Build Coastguard Worker
7669*5e7646d2SAndroid Build Coastguard Worker if ((status = cupsdCheckPolicy(policy, con, sub->owner)) != HTTP_OK)
7670*5e7646d2SAndroid Build Coastguard Worker {
7671*5e7646d2SAndroid Build Coastguard Worker send_http_error(con, status, sub->dest);
7672*5e7646d2SAndroid Build Coastguard Worker return;
7673*5e7646d2SAndroid Build Coastguard Worker }
7674*5e7646d2SAndroid Build Coastguard Worker
7675*5e7646d2SAndroid Build Coastguard Worker exclude = cupsdGetPrivateAttrs(policy, con, sub->dest, sub->owner);
7676*5e7646d2SAndroid Build Coastguard Worker
7677*5e7646d2SAndroid Build Coastguard Worker /*
7678*5e7646d2SAndroid Build Coastguard Worker * Copy the subscription attributes to the response using the
7679*5e7646d2SAndroid Build Coastguard Worker * requested-attributes attribute that may be provided by the client.
7680*5e7646d2SAndroid Build Coastguard Worker */
7681*5e7646d2SAndroid Build Coastguard Worker
7682*5e7646d2SAndroid Build Coastguard Worker ra = create_requested_array(con->request);
7683*5e7646d2SAndroid Build Coastguard Worker
7684*5e7646d2SAndroid Build Coastguard Worker copy_subscription_attrs(con, sub, ra, exclude);
7685*5e7646d2SAndroid Build Coastguard Worker
7686*5e7646d2SAndroid Build Coastguard Worker cupsArrayDelete(ra);
7687*5e7646d2SAndroid Build Coastguard Worker
7688*5e7646d2SAndroid Build Coastguard Worker con->response->request.status.status_code = IPP_OK;
7689*5e7646d2SAndroid Build Coastguard Worker }
7690*5e7646d2SAndroid Build Coastguard Worker
7691*5e7646d2SAndroid Build Coastguard Worker
7692*5e7646d2SAndroid Build Coastguard Worker /*
7693*5e7646d2SAndroid Build Coastguard Worker * 'get_subscriptions()' - Get subscriptions.
7694*5e7646d2SAndroid Build Coastguard Worker */
7695*5e7646d2SAndroid Build Coastguard Worker
7696*5e7646d2SAndroid Build Coastguard Worker static void
get_subscriptions(cupsd_client_t * con,ipp_attribute_t * uri)7697*5e7646d2SAndroid Build Coastguard Worker get_subscriptions(cupsd_client_t *con, /* I - Client connection */
7698*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *uri) /* I - Printer/job URI */
7699*5e7646d2SAndroid Build Coastguard Worker {
7700*5e7646d2SAndroid Build Coastguard Worker http_status_t status; /* Policy status */
7701*5e7646d2SAndroid Build Coastguard Worker int count; /* Number of subscriptions */
7702*5e7646d2SAndroid Build Coastguard Worker int limit; /* Limit */
7703*5e7646d2SAndroid Build Coastguard Worker cupsd_subscription_t *sub; /* Subscription */
7704*5e7646d2SAndroid Build Coastguard Worker cups_array_t *ra; /* Requested attributes array */
7705*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *attr; /* Attribute */
7706*5e7646d2SAndroid Build Coastguard Worker cups_ptype_t dtype; /* Destination type (printer/class) */
7707*5e7646d2SAndroid Build Coastguard Worker char scheme[HTTP_MAX_URI],
7708*5e7646d2SAndroid Build Coastguard Worker /* Scheme portion of URI */
7709*5e7646d2SAndroid Build Coastguard Worker username[HTTP_MAX_URI],
7710*5e7646d2SAndroid Build Coastguard Worker /* Username portion of URI */
7711*5e7646d2SAndroid Build Coastguard Worker host[HTTP_MAX_URI],
7712*5e7646d2SAndroid Build Coastguard Worker /* Host portion of URI */
7713*5e7646d2SAndroid Build Coastguard Worker resource[HTTP_MAX_URI];
7714*5e7646d2SAndroid Build Coastguard Worker /* Resource portion of URI */
7715*5e7646d2SAndroid Build Coastguard Worker int port; /* Port portion of URI */
7716*5e7646d2SAndroid Build Coastguard Worker cupsd_job_t *job; /* Job pointer */
7717*5e7646d2SAndroid Build Coastguard Worker cupsd_printer_t *printer; /* Printer */
7718*5e7646d2SAndroid Build Coastguard Worker cupsd_policy_t *policy; /* Policy */
7719*5e7646d2SAndroid Build Coastguard Worker cups_array_t *exclude; /* Private attributes array */
7720*5e7646d2SAndroid Build Coastguard Worker
7721*5e7646d2SAndroid Build Coastguard Worker
7722*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG2,
7723*5e7646d2SAndroid Build Coastguard Worker "get_subscriptions(con=%p[%d], uri=%s)",
7724*5e7646d2SAndroid Build Coastguard Worker con, con->number, uri->values[0].string.text);
7725*5e7646d2SAndroid Build Coastguard Worker
7726*5e7646d2SAndroid Build Coastguard Worker /*
7727*5e7646d2SAndroid Build Coastguard Worker * Is the destination valid?
7728*5e7646d2SAndroid Build Coastguard Worker */
7729*5e7646d2SAndroid Build Coastguard Worker
7730*5e7646d2SAndroid Build Coastguard Worker httpSeparateURI(HTTP_URI_CODING_ALL, uri->values[0].string.text, scheme,
7731*5e7646d2SAndroid Build Coastguard Worker sizeof(scheme), username, sizeof(username), host,
7732*5e7646d2SAndroid Build Coastguard Worker sizeof(host), &port, resource, sizeof(resource));
7733*5e7646d2SAndroid Build Coastguard Worker
7734*5e7646d2SAndroid Build Coastguard Worker if (!strcmp(resource, "/") ||
7735*5e7646d2SAndroid Build Coastguard Worker (!strncmp(resource, "/jobs", 5) && strlen(resource) <= 6) ||
7736*5e7646d2SAndroid Build Coastguard Worker (!strncmp(resource, "/printers", 9) && strlen(resource) <= 10) ||
7737*5e7646d2SAndroid Build Coastguard Worker (!strncmp(resource, "/classes", 8) && strlen(resource) <= 9))
7738*5e7646d2SAndroid Build Coastguard Worker {
7739*5e7646d2SAndroid Build Coastguard Worker printer = NULL;
7740*5e7646d2SAndroid Build Coastguard Worker job = NULL;
7741*5e7646d2SAndroid Build Coastguard Worker }
7742*5e7646d2SAndroid Build Coastguard Worker else if (!strncmp(resource, "/jobs/", 6) && resource[6])
7743*5e7646d2SAndroid Build Coastguard Worker {
7744*5e7646d2SAndroid Build Coastguard Worker printer = NULL;
7745*5e7646d2SAndroid Build Coastguard Worker job = cupsdFindJob(atoi(resource + 6));
7746*5e7646d2SAndroid Build Coastguard Worker
7747*5e7646d2SAndroid Build Coastguard Worker if (!job)
7748*5e7646d2SAndroid Build Coastguard Worker {
7749*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_NOT_FOUND, _("Job #%d does not exist."),
7750*5e7646d2SAndroid Build Coastguard Worker atoi(resource + 6));
7751*5e7646d2SAndroid Build Coastguard Worker return;
7752*5e7646d2SAndroid Build Coastguard Worker }
7753*5e7646d2SAndroid Build Coastguard Worker }
7754*5e7646d2SAndroid Build Coastguard Worker else if (!cupsdValidateDest(uri->values[0].string.text, &dtype, &printer))
7755*5e7646d2SAndroid Build Coastguard Worker {
7756*5e7646d2SAndroid Build Coastguard Worker /*
7757*5e7646d2SAndroid Build Coastguard Worker * Bad URI...
7758*5e7646d2SAndroid Build Coastguard Worker */
7759*5e7646d2SAndroid Build Coastguard Worker
7760*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_NOT_FOUND,
7761*5e7646d2SAndroid Build Coastguard Worker _("The printer or class does not exist."));
7762*5e7646d2SAndroid Build Coastguard Worker return;
7763*5e7646d2SAndroid Build Coastguard Worker }
7764*5e7646d2SAndroid Build Coastguard Worker else if ((attr = ippFindAttribute(con->request, "notify-job-id",
7765*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_INTEGER)) != NULL)
7766*5e7646d2SAndroid Build Coastguard Worker {
7767*5e7646d2SAndroid Build Coastguard Worker job = cupsdFindJob(attr->values[0].integer);
7768*5e7646d2SAndroid Build Coastguard Worker
7769*5e7646d2SAndroid Build Coastguard Worker if (!job)
7770*5e7646d2SAndroid Build Coastguard Worker {
7771*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_NOT_FOUND, _("Job #%d does not exist."),
7772*5e7646d2SAndroid Build Coastguard Worker attr->values[0].integer);
7773*5e7646d2SAndroid Build Coastguard Worker return;
7774*5e7646d2SAndroid Build Coastguard Worker }
7775*5e7646d2SAndroid Build Coastguard Worker }
7776*5e7646d2SAndroid Build Coastguard Worker else
7777*5e7646d2SAndroid Build Coastguard Worker job = NULL;
7778*5e7646d2SAndroid Build Coastguard Worker
7779*5e7646d2SAndroid Build Coastguard Worker /*
7780*5e7646d2SAndroid Build Coastguard Worker * Check policy...
7781*5e7646d2SAndroid Build Coastguard Worker */
7782*5e7646d2SAndroid Build Coastguard Worker
7783*5e7646d2SAndroid Build Coastguard Worker if (printer)
7784*5e7646d2SAndroid Build Coastguard Worker policy = printer->op_policy_ptr;
7785*5e7646d2SAndroid Build Coastguard Worker else
7786*5e7646d2SAndroid Build Coastguard Worker policy = DefaultPolicyPtr;
7787*5e7646d2SAndroid Build Coastguard Worker
7788*5e7646d2SAndroid Build Coastguard Worker if ((status = cupsdCheckPolicy(policy, con, NULL)) != HTTP_OK)
7789*5e7646d2SAndroid Build Coastguard Worker {
7790*5e7646d2SAndroid Build Coastguard Worker send_http_error(con, status, printer);
7791*5e7646d2SAndroid Build Coastguard Worker return;
7792*5e7646d2SAndroid Build Coastguard Worker }
7793*5e7646d2SAndroid Build Coastguard Worker
7794*5e7646d2SAndroid Build Coastguard Worker /*
7795*5e7646d2SAndroid Build Coastguard Worker * Expire subscriptions as needed...
7796*5e7646d2SAndroid Build Coastguard Worker */
7797*5e7646d2SAndroid Build Coastguard Worker
7798*5e7646d2SAndroid Build Coastguard Worker cupsdExpireSubscriptions(NULL, NULL);
7799*5e7646d2SAndroid Build Coastguard Worker
7800*5e7646d2SAndroid Build Coastguard Worker /*
7801*5e7646d2SAndroid Build Coastguard Worker * Copy the subscription attributes to the response using the
7802*5e7646d2SAndroid Build Coastguard Worker * requested-attributes attribute that may be provided by the client.
7803*5e7646d2SAndroid Build Coastguard Worker */
7804*5e7646d2SAndroid Build Coastguard Worker
7805*5e7646d2SAndroid Build Coastguard Worker ra = create_requested_array(con->request);
7806*5e7646d2SAndroid Build Coastguard Worker
7807*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippFindAttribute(con->request, "limit",
7808*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_INTEGER)) != NULL)
7809*5e7646d2SAndroid Build Coastguard Worker limit = attr->values[0].integer;
7810*5e7646d2SAndroid Build Coastguard Worker else
7811*5e7646d2SAndroid Build Coastguard Worker limit = 0;
7812*5e7646d2SAndroid Build Coastguard Worker
7813*5e7646d2SAndroid Build Coastguard Worker /*
7814*5e7646d2SAndroid Build Coastguard Worker * See if we only want to see subscriptions for a specific user...
7815*5e7646d2SAndroid Build Coastguard Worker */
7816*5e7646d2SAndroid Build Coastguard Worker
7817*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippFindAttribute(con->request, "my-subscriptions",
7818*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_BOOLEAN)) != NULL &&
7819*5e7646d2SAndroid Build Coastguard Worker attr->values[0].boolean)
7820*5e7646d2SAndroid Build Coastguard Worker strlcpy(username, get_username(con), sizeof(username));
7821*5e7646d2SAndroid Build Coastguard Worker else
7822*5e7646d2SAndroid Build Coastguard Worker username[0] = '\0';
7823*5e7646d2SAndroid Build Coastguard Worker
7824*5e7646d2SAndroid Build Coastguard Worker for (sub = (cupsd_subscription_t *)cupsArrayFirst(Subscriptions), count = 0;
7825*5e7646d2SAndroid Build Coastguard Worker sub;
7826*5e7646d2SAndroid Build Coastguard Worker sub = (cupsd_subscription_t *)cupsArrayNext(Subscriptions))
7827*5e7646d2SAndroid Build Coastguard Worker if ((!printer || sub->dest == printer) && (!job || sub->job == job) &&
7828*5e7646d2SAndroid Build Coastguard Worker (!username[0] || !_cups_strcasecmp(username, sub->owner)))
7829*5e7646d2SAndroid Build Coastguard Worker {
7830*5e7646d2SAndroid Build Coastguard Worker ippAddSeparator(con->response);
7831*5e7646d2SAndroid Build Coastguard Worker
7832*5e7646d2SAndroid Build Coastguard Worker exclude = cupsdGetPrivateAttrs(sub->dest ? sub->dest->op_policy_ptr :
7833*5e7646d2SAndroid Build Coastguard Worker policy, con, sub->dest,
7834*5e7646d2SAndroid Build Coastguard Worker sub->owner);
7835*5e7646d2SAndroid Build Coastguard Worker
7836*5e7646d2SAndroid Build Coastguard Worker copy_subscription_attrs(con, sub, ra, exclude);
7837*5e7646d2SAndroid Build Coastguard Worker
7838*5e7646d2SAndroid Build Coastguard Worker count ++;
7839*5e7646d2SAndroid Build Coastguard Worker if (limit && count >= limit)
7840*5e7646d2SAndroid Build Coastguard Worker break;
7841*5e7646d2SAndroid Build Coastguard Worker }
7842*5e7646d2SAndroid Build Coastguard Worker
7843*5e7646d2SAndroid Build Coastguard Worker cupsArrayDelete(ra);
7844*5e7646d2SAndroid Build Coastguard Worker
7845*5e7646d2SAndroid Build Coastguard Worker if (count)
7846*5e7646d2SAndroid Build Coastguard Worker con->response->request.status.status_code = IPP_OK;
7847*5e7646d2SAndroid Build Coastguard Worker else
7848*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_NOT_FOUND, _("No subscriptions found."));
7849*5e7646d2SAndroid Build Coastguard Worker }
7850*5e7646d2SAndroid Build Coastguard Worker
7851*5e7646d2SAndroid Build Coastguard Worker
7852*5e7646d2SAndroid Build Coastguard Worker /*
7853*5e7646d2SAndroid Build Coastguard Worker * 'get_username()' - Get the username associated with a request.
7854*5e7646d2SAndroid Build Coastguard Worker */
7855*5e7646d2SAndroid Build Coastguard Worker
7856*5e7646d2SAndroid Build Coastguard Worker static const char * /* O - Username */
get_username(cupsd_client_t * con)7857*5e7646d2SAndroid Build Coastguard Worker get_username(cupsd_client_t *con) /* I - Connection */
7858*5e7646d2SAndroid Build Coastguard Worker {
7859*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *attr; /* Attribute */
7860*5e7646d2SAndroid Build Coastguard Worker
7861*5e7646d2SAndroid Build Coastguard Worker
7862*5e7646d2SAndroid Build Coastguard Worker if (con->username[0])
7863*5e7646d2SAndroid Build Coastguard Worker return (con->username);
7864*5e7646d2SAndroid Build Coastguard Worker else if ((attr = ippFindAttribute(con->request, "requesting-user-name",
7865*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_NAME)) != NULL)
7866*5e7646d2SAndroid Build Coastguard Worker return (attr->values[0].string.text);
7867*5e7646d2SAndroid Build Coastguard Worker else
7868*5e7646d2SAndroid Build Coastguard Worker return ("anonymous");
7869*5e7646d2SAndroid Build Coastguard Worker }
7870*5e7646d2SAndroid Build Coastguard Worker
7871*5e7646d2SAndroid Build Coastguard Worker
7872*5e7646d2SAndroid Build Coastguard Worker /*
7873*5e7646d2SAndroid Build Coastguard Worker * 'hold_job()' - Hold a print job.
7874*5e7646d2SAndroid Build Coastguard Worker */
7875*5e7646d2SAndroid Build Coastguard Worker
7876*5e7646d2SAndroid Build Coastguard Worker static void
hold_job(cupsd_client_t * con,ipp_attribute_t * uri)7877*5e7646d2SAndroid Build Coastguard Worker hold_job(cupsd_client_t *con, /* I - Client connection */
7878*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *uri) /* I - Job or Printer URI */
7879*5e7646d2SAndroid Build Coastguard Worker {
7880*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *attr; /* Current job-hold-until */
7881*5e7646d2SAndroid Build Coastguard Worker const char *when; /* New value */
7882*5e7646d2SAndroid Build Coastguard Worker int jobid; /* Job ID */
7883*5e7646d2SAndroid Build Coastguard Worker char scheme[HTTP_MAX_URI], /* Method portion of URI */
7884*5e7646d2SAndroid Build Coastguard Worker username[HTTP_MAX_URI], /* Username portion of URI */
7885*5e7646d2SAndroid Build Coastguard Worker host[HTTP_MAX_URI], /* Host portion of URI */
7886*5e7646d2SAndroid Build Coastguard Worker resource[HTTP_MAX_URI]; /* Resource portion of URI */
7887*5e7646d2SAndroid Build Coastguard Worker int port; /* Port portion of URI */
7888*5e7646d2SAndroid Build Coastguard Worker cupsd_job_t *job; /* Job information */
7889*5e7646d2SAndroid Build Coastguard Worker
7890*5e7646d2SAndroid Build Coastguard Worker
7891*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG2, "hold_job(%p[%d], %s)", con, con->number,
7892*5e7646d2SAndroid Build Coastguard Worker uri->values[0].string.text);
7893*5e7646d2SAndroid Build Coastguard Worker
7894*5e7646d2SAndroid Build Coastguard Worker /*
7895*5e7646d2SAndroid Build Coastguard Worker * See if we have a job URI or a printer URI...
7896*5e7646d2SAndroid Build Coastguard Worker */
7897*5e7646d2SAndroid Build Coastguard Worker
7898*5e7646d2SAndroid Build Coastguard Worker if (!strcmp(uri->name, "printer-uri"))
7899*5e7646d2SAndroid Build Coastguard Worker {
7900*5e7646d2SAndroid Build Coastguard Worker /*
7901*5e7646d2SAndroid Build Coastguard Worker * Got a printer URI; see if we also have a job-id attribute...
7902*5e7646d2SAndroid Build Coastguard Worker */
7903*5e7646d2SAndroid Build Coastguard Worker
7904*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippFindAttribute(con->request, "job-id",
7905*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_INTEGER)) == NULL)
7906*5e7646d2SAndroid Build Coastguard Worker {
7907*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_BAD_REQUEST,
7908*5e7646d2SAndroid Build Coastguard Worker _("Got a printer-uri attribute but no job-id."));
7909*5e7646d2SAndroid Build Coastguard Worker return;
7910*5e7646d2SAndroid Build Coastguard Worker }
7911*5e7646d2SAndroid Build Coastguard Worker
7912*5e7646d2SAndroid Build Coastguard Worker jobid = attr->values[0].integer;
7913*5e7646d2SAndroid Build Coastguard Worker }
7914*5e7646d2SAndroid Build Coastguard Worker else
7915*5e7646d2SAndroid Build Coastguard Worker {
7916*5e7646d2SAndroid Build Coastguard Worker /*
7917*5e7646d2SAndroid Build Coastguard Worker * Got a job URI; parse it to get the job ID...
7918*5e7646d2SAndroid Build Coastguard Worker */
7919*5e7646d2SAndroid Build Coastguard Worker
7920*5e7646d2SAndroid Build Coastguard Worker httpSeparateURI(HTTP_URI_CODING_ALL, uri->values[0].string.text, scheme,
7921*5e7646d2SAndroid Build Coastguard Worker sizeof(scheme), username, sizeof(username), host,
7922*5e7646d2SAndroid Build Coastguard Worker sizeof(host), &port, resource, sizeof(resource));
7923*5e7646d2SAndroid Build Coastguard Worker
7924*5e7646d2SAndroid Build Coastguard Worker if (strncmp(resource, "/jobs/", 6))
7925*5e7646d2SAndroid Build Coastguard Worker {
7926*5e7646d2SAndroid Build Coastguard Worker /*
7927*5e7646d2SAndroid Build Coastguard Worker * Not a valid URI!
7928*5e7646d2SAndroid Build Coastguard Worker */
7929*5e7646d2SAndroid Build Coastguard Worker
7930*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_BAD_REQUEST,
7931*5e7646d2SAndroid Build Coastguard Worker _("Bad job-uri \"%s\"."),
7932*5e7646d2SAndroid Build Coastguard Worker uri->values[0].string.text);
7933*5e7646d2SAndroid Build Coastguard Worker return;
7934*5e7646d2SAndroid Build Coastguard Worker }
7935*5e7646d2SAndroid Build Coastguard Worker
7936*5e7646d2SAndroid Build Coastguard Worker jobid = atoi(resource + 6);
7937*5e7646d2SAndroid Build Coastguard Worker }
7938*5e7646d2SAndroid Build Coastguard Worker
7939*5e7646d2SAndroid Build Coastguard Worker /*
7940*5e7646d2SAndroid Build Coastguard Worker * See if the job exists...
7941*5e7646d2SAndroid Build Coastguard Worker */
7942*5e7646d2SAndroid Build Coastguard Worker
7943*5e7646d2SAndroid Build Coastguard Worker if ((job = cupsdFindJob(jobid)) == NULL)
7944*5e7646d2SAndroid Build Coastguard Worker {
7945*5e7646d2SAndroid Build Coastguard Worker /*
7946*5e7646d2SAndroid Build Coastguard Worker * Nope - return a "not found" error...
7947*5e7646d2SAndroid Build Coastguard Worker */
7948*5e7646d2SAndroid Build Coastguard Worker
7949*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_NOT_FOUND, _("Job #%d does not exist."), jobid);
7950*5e7646d2SAndroid Build Coastguard Worker return;
7951*5e7646d2SAndroid Build Coastguard Worker }
7952*5e7646d2SAndroid Build Coastguard Worker
7953*5e7646d2SAndroid Build Coastguard Worker /*
7954*5e7646d2SAndroid Build Coastguard Worker * See if the job is owned by the requesting user...
7955*5e7646d2SAndroid Build Coastguard Worker */
7956*5e7646d2SAndroid Build Coastguard Worker
7957*5e7646d2SAndroid Build Coastguard Worker if (!validate_user(job, con, job->username, username, sizeof(username)))
7958*5e7646d2SAndroid Build Coastguard Worker {
7959*5e7646d2SAndroid Build Coastguard Worker send_http_error(con, con->username[0] ? HTTP_FORBIDDEN : HTTP_UNAUTHORIZED,
7960*5e7646d2SAndroid Build Coastguard Worker cupsdFindDest(job->dest));
7961*5e7646d2SAndroid Build Coastguard Worker return;
7962*5e7646d2SAndroid Build Coastguard Worker }
7963*5e7646d2SAndroid Build Coastguard Worker
7964*5e7646d2SAndroid Build Coastguard Worker /*
7965*5e7646d2SAndroid Build Coastguard Worker * See if the job is in a state that allows holding...
7966*5e7646d2SAndroid Build Coastguard Worker */
7967*5e7646d2SAndroid Build Coastguard Worker
7968*5e7646d2SAndroid Build Coastguard Worker if (job->state_value > IPP_JOB_STOPPED)
7969*5e7646d2SAndroid Build Coastguard Worker {
7970*5e7646d2SAndroid Build Coastguard Worker /*
7971*5e7646d2SAndroid Build Coastguard Worker * Return a "not-possible" error...
7972*5e7646d2SAndroid Build Coastguard Worker */
7973*5e7646d2SAndroid Build Coastguard Worker
7974*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_NOT_POSSIBLE,
7975*5e7646d2SAndroid Build Coastguard Worker _("Job #%d is finished and cannot be altered."),
7976*5e7646d2SAndroid Build Coastguard Worker job->id);
7977*5e7646d2SAndroid Build Coastguard Worker return;
7978*5e7646d2SAndroid Build Coastguard Worker }
7979*5e7646d2SAndroid Build Coastguard Worker
7980*5e7646d2SAndroid Build Coastguard Worker /*
7981*5e7646d2SAndroid Build Coastguard Worker * Hold the job and return...
7982*5e7646d2SAndroid Build Coastguard Worker */
7983*5e7646d2SAndroid Build Coastguard Worker
7984*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippFindAttribute(con->request, "job-hold-until", IPP_TAG_ZERO)) != NULL)
7985*5e7646d2SAndroid Build Coastguard Worker {
7986*5e7646d2SAndroid Build Coastguard Worker if ((ippGetValueTag(attr) != IPP_TAG_KEYWORD && ippGetValueTag(attr) != IPP_TAG_NAME && ippGetValueTag(attr) != IPP_TAG_NAMELANG) || ippGetCount(attr) != 1 || !ippValidateAttribute(attr))
7987*5e7646d2SAndroid Build Coastguard Worker {
7988*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_STATUS_ERROR_ATTRIBUTES_OR_VALUES, _("Unsupported 'job-hold-until' value."));
7989*5e7646d2SAndroid Build Coastguard Worker ippCopyAttribute(con->response, attr, 0);
7990*5e7646d2SAndroid Build Coastguard Worker return;
7991*5e7646d2SAndroid Build Coastguard Worker }
7992*5e7646d2SAndroid Build Coastguard Worker
7993*5e7646d2SAndroid Build Coastguard Worker when = ippGetString(attr, 0, NULL);
7994*5e7646d2SAndroid Build Coastguard Worker
7995*5e7646d2SAndroid Build Coastguard Worker cupsdAddEvent(CUPSD_EVENT_JOB_CONFIG_CHANGED, cupsdFindDest(job->dest), job,
7996*5e7646d2SAndroid Build Coastguard Worker "Job job-hold-until value changed by user.");
7997*5e7646d2SAndroid Build Coastguard Worker }
7998*5e7646d2SAndroid Build Coastguard Worker else
7999*5e7646d2SAndroid Build Coastguard Worker when = "indefinite";
8000*5e7646d2SAndroid Build Coastguard Worker
8001*5e7646d2SAndroid Build Coastguard Worker cupsdSetJobHoldUntil(job, when, 1);
8002*5e7646d2SAndroid Build Coastguard Worker cupsdSetJobState(job, IPP_JOB_HELD, CUPSD_JOB_DEFAULT, "Job held by \"%s\".",
8003*5e7646d2SAndroid Build Coastguard Worker username);
8004*5e7646d2SAndroid Build Coastguard Worker
8005*5e7646d2SAndroid Build Coastguard Worker con->response->request.status.status_code = IPP_OK;
8006*5e7646d2SAndroid Build Coastguard Worker }
8007*5e7646d2SAndroid Build Coastguard Worker
8008*5e7646d2SAndroid Build Coastguard Worker
8009*5e7646d2SAndroid Build Coastguard Worker /*
8010*5e7646d2SAndroid Build Coastguard Worker * 'hold_new_jobs()' - Hold pending/new jobs on a printer or class.
8011*5e7646d2SAndroid Build Coastguard Worker */
8012*5e7646d2SAndroid Build Coastguard Worker
8013*5e7646d2SAndroid Build Coastguard Worker static void
hold_new_jobs(cupsd_client_t * con,ipp_attribute_t * uri)8014*5e7646d2SAndroid Build Coastguard Worker hold_new_jobs(cupsd_client_t *con, /* I - Connection */
8015*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *uri) /* I - Printer URI */
8016*5e7646d2SAndroid Build Coastguard Worker {
8017*5e7646d2SAndroid Build Coastguard Worker http_status_t status; /* Policy status */
8018*5e7646d2SAndroid Build Coastguard Worker cups_ptype_t dtype; /* Destination type (printer/class) */
8019*5e7646d2SAndroid Build Coastguard Worker cupsd_printer_t *printer; /* Printer data */
8020*5e7646d2SAndroid Build Coastguard Worker
8021*5e7646d2SAndroid Build Coastguard Worker
8022*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG2, "hold_new_jobs(%p[%d], %s)", con,
8023*5e7646d2SAndroid Build Coastguard Worker con->number, uri->values[0].string.text);
8024*5e7646d2SAndroid Build Coastguard Worker
8025*5e7646d2SAndroid Build Coastguard Worker /*
8026*5e7646d2SAndroid Build Coastguard Worker * Is the destination valid?
8027*5e7646d2SAndroid Build Coastguard Worker */
8028*5e7646d2SAndroid Build Coastguard Worker
8029*5e7646d2SAndroid Build Coastguard Worker if (!cupsdValidateDest(uri->values[0].string.text, &dtype, &printer))
8030*5e7646d2SAndroid Build Coastguard Worker {
8031*5e7646d2SAndroid Build Coastguard Worker /*
8032*5e7646d2SAndroid Build Coastguard Worker * Bad URI...
8033*5e7646d2SAndroid Build Coastguard Worker */
8034*5e7646d2SAndroid Build Coastguard Worker
8035*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_NOT_FOUND,
8036*5e7646d2SAndroid Build Coastguard Worker _("The printer or class does not exist."));
8037*5e7646d2SAndroid Build Coastguard Worker return;
8038*5e7646d2SAndroid Build Coastguard Worker }
8039*5e7646d2SAndroid Build Coastguard Worker
8040*5e7646d2SAndroid Build Coastguard Worker /*
8041*5e7646d2SAndroid Build Coastguard Worker * Check policy...
8042*5e7646d2SAndroid Build Coastguard Worker */
8043*5e7646d2SAndroid Build Coastguard Worker
8044*5e7646d2SAndroid Build Coastguard Worker if ((status = cupsdCheckPolicy(printer->op_policy_ptr, con, NULL)) != HTTP_OK)
8045*5e7646d2SAndroid Build Coastguard Worker {
8046*5e7646d2SAndroid Build Coastguard Worker send_http_error(con, status, printer);
8047*5e7646d2SAndroid Build Coastguard Worker return;
8048*5e7646d2SAndroid Build Coastguard Worker }
8049*5e7646d2SAndroid Build Coastguard Worker
8050*5e7646d2SAndroid Build Coastguard Worker /*
8051*5e7646d2SAndroid Build Coastguard Worker * Hold pending/new jobs sent to the printer...
8052*5e7646d2SAndroid Build Coastguard Worker */
8053*5e7646d2SAndroid Build Coastguard Worker
8054*5e7646d2SAndroid Build Coastguard Worker printer->holding_new_jobs = 1;
8055*5e7646d2SAndroid Build Coastguard Worker
8056*5e7646d2SAndroid Build Coastguard Worker cupsdSetPrinterReasons(printer, "+hold-new-jobs");
8057*5e7646d2SAndroid Build Coastguard Worker
8058*5e7646d2SAndroid Build Coastguard Worker if (dtype & CUPS_PRINTER_CLASS)
8059*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_INFO,
8060*5e7646d2SAndroid Build Coastguard Worker "Class \"%s\" now holding pending/new jobs (\"%s\").",
8061*5e7646d2SAndroid Build Coastguard Worker printer->name, get_username(con));
8062*5e7646d2SAndroid Build Coastguard Worker else
8063*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_INFO,
8064*5e7646d2SAndroid Build Coastguard Worker "Printer \"%s\" now holding pending/new jobs (\"%s\").",
8065*5e7646d2SAndroid Build Coastguard Worker printer->name, get_username(con));
8066*5e7646d2SAndroid Build Coastguard Worker
8067*5e7646d2SAndroid Build Coastguard Worker /*
8068*5e7646d2SAndroid Build Coastguard Worker * Everything was ok, so return OK status...
8069*5e7646d2SAndroid Build Coastguard Worker */
8070*5e7646d2SAndroid Build Coastguard Worker
8071*5e7646d2SAndroid Build Coastguard Worker con->response->request.status.status_code = IPP_OK;
8072*5e7646d2SAndroid Build Coastguard Worker }
8073*5e7646d2SAndroid Build Coastguard Worker
8074*5e7646d2SAndroid Build Coastguard Worker
8075*5e7646d2SAndroid Build Coastguard Worker /*
8076*5e7646d2SAndroid Build Coastguard Worker * 'move_job()' - Move a job to a new destination.
8077*5e7646d2SAndroid Build Coastguard Worker */
8078*5e7646d2SAndroid Build Coastguard Worker
8079*5e7646d2SAndroid Build Coastguard Worker static void
move_job(cupsd_client_t * con,ipp_attribute_t * uri)8080*5e7646d2SAndroid Build Coastguard Worker move_job(cupsd_client_t *con, /* I - Client connection */
8081*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *uri) /* I - Job URI */
8082*5e7646d2SAndroid Build Coastguard Worker {
8083*5e7646d2SAndroid Build Coastguard Worker http_status_t status; /* Policy status */
8084*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *attr; /* Current attribute */
8085*5e7646d2SAndroid Build Coastguard Worker int jobid; /* Job ID */
8086*5e7646d2SAndroid Build Coastguard Worker cupsd_job_t *job; /* Current job */
8087*5e7646d2SAndroid Build Coastguard Worker const char *src; /* Source printer/class */
8088*5e7646d2SAndroid Build Coastguard Worker cups_ptype_t stype, /* Source type (printer or class) */
8089*5e7646d2SAndroid Build Coastguard Worker dtype; /* Destination type (printer/class) */
8090*5e7646d2SAndroid Build Coastguard Worker char scheme[HTTP_MAX_URI], /* Scheme portion of URI */
8091*5e7646d2SAndroid Build Coastguard Worker username[HTTP_MAX_URI], /* Username portion of URI */
8092*5e7646d2SAndroid Build Coastguard Worker host[HTTP_MAX_URI], /* Host portion of URI */
8093*5e7646d2SAndroid Build Coastguard Worker resource[HTTP_MAX_URI]; /* Resource portion of URI */
8094*5e7646d2SAndroid Build Coastguard Worker int port; /* Port portion of URI */
8095*5e7646d2SAndroid Build Coastguard Worker cupsd_printer_t *sprinter, /* Source printer */
8096*5e7646d2SAndroid Build Coastguard Worker *dprinter; /* Destination printer */
8097*5e7646d2SAndroid Build Coastguard Worker
8098*5e7646d2SAndroid Build Coastguard Worker
8099*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG2, "move_job(%p[%d], %s)", con, con->number,
8100*5e7646d2SAndroid Build Coastguard Worker uri->values[0].string.text);
8101*5e7646d2SAndroid Build Coastguard Worker
8102*5e7646d2SAndroid Build Coastguard Worker /*
8103*5e7646d2SAndroid Build Coastguard Worker * Get the new printer or class...
8104*5e7646d2SAndroid Build Coastguard Worker */
8105*5e7646d2SAndroid Build Coastguard Worker
8106*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippFindAttribute(con->request, "job-printer-uri",
8107*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_URI)) == NULL)
8108*5e7646d2SAndroid Build Coastguard Worker {
8109*5e7646d2SAndroid Build Coastguard Worker /*
8110*5e7646d2SAndroid Build Coastguard Worker * Need job-printer-uri...
8111*5e7646d2SAndroid Build Coastguard Worker */
8112*5e7646d2SAndroid Build Coastguard Worker
8113*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_BAD_REQUEST,
8114*5e7646d2SAndroid Build Coastguard Worker _("job-printer-uri attribute missing."));
8115*5e7646d2SAndroid Build Coastguard Worker return;
8116*5e7646d2SAndroid Build Coastguard Worker }
8117*5e7646d2SAndroid Build Coastguard Worker
8118*5e7646d2SAndroid Build Coastguard Worker if (!cupsdValidateDest(attr->values[0].string.text, &dtype, &dprinter))
8119*5e7646d2SAndroid Build Coastguard Worker {
8120*5e7646d2SAndroid Build Coastguard Worker /*
8121*5e7646d2SAndroid Build Coastguard Worker * Bad URI...
8122*5e7646d2SAndroid Build Coastguard Worker */
8123*5e7646d2SAndroid Build Coastguard Worker
8124*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_NOT_FOUND,
8125*5e7646d2SAndroid Build Coastguard Worker _("The printer or class does not exist."));
8126*5e7646d2SAndroid Build Coastguard Worker return;
8127*5e7646d2SAndroid Build Coastguard Worker }
8128*5e7646d2SAndroid Build Coastguard Worker
8129*5e7646d2SAndroid Build Coastguard Worker /*
8130*5e7646d2SAndroid Build Coastguard Worker * See if we have a job URI or a printer URI...
8131*5e7646d2SAndroid Build Coastguard Worker */
8132*5e7646d2SAndroid Build Coastguard Worker
8133*5e7646d2SAndroid Build Coastguard Worker httpSeparateURI(HTTP_URI_CODING_ALL, uri->values[0].string.text, scheme,
8134*5e7646d2SAndroid Build Coastguard Worker sizeof(scheme), username, sizeof(username), host,
8135*5e7646d2SAndroid Build Coastguard Worker sizeof(host), &port, resource, sizeof(resource));
8136*5e7646d2SAndroid Build Coastguard Worker
8137*5e7646d2SAndroid Build Coastguard Worker if (!strcmp(uri->name, "printer-uri"))
8138*5e7646d2SAndroid Build Coastguard Worker {
8139*5e7646d2SAndroid Build Coastguard Worker /*
8140*5e7646d2SAndroid Build Coastguard Worker * Got a printer URI; see if we also have a job-id attribute...
8141*5e7646d2SAndroid Build Coastguard Worker */
8142*5e7646d2SAndroid Build Coastguard Worker
8143*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippFindAttribute(con->request, "job-id",
8144*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_INTEGER)) == NULL)
8145*5e7646d2SAndroid Build Coastguard Worker {
8146*5e7646d2SAndroid Build Coastguard Worker /*
8147*5e7646d2SAndroid Build Coastguard Worker * Move all jobs...
8148*5e7646d2SAndroid Build Coastguard Worker */
8149*5e7646d2SAndroid Build Coastguard Worker
8150*5e7646d2SAndroid Build Coastguard Worker if ((src = cupsdValidateDest(uri->values[0].string.text, &stype,
8151*5e7646d2SAndroid Build Coastguard Worker &sprinter)) == NULL)
8152*5e7646d2SAndroid Build Coastguard Worker {
8153*5e7646d2SAndroid Build Coastguard Worker /*
8154*5e7646d2SAndroid Build Coastguard Worker * Bad URI...
8155*5e7646d2SAndroid Build Coastguard Worker */
8156*5e7646d2SAndroid Build Coastguard Worker
8157*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_NOT_FOUND,
8158*5e7646d2SAndroid Build Coastguard Worker _("The printer or class does not exist."));
8159*5e7646d2SAndroid Build Coastguard Worker return;
8160*5e7646d2SAndroid Build Coastguard Worker }
8161*5e7646d2SAndroid Build Coastguard Worker
8162*5e7646d2SAndroid Build Coastguard Worker job = NULL;
8163*5e7646d2SAndroid Build Coastguard Worker }
8164*5e7646d2SAndroid Build Coastguard Worker else
8165*5e7646d2SAndroid Build Coastguard Worker {
8166*5e7646d2SAndroid Build Coastguard Worker /*
8167*5e7646d2SAndroid Build Coastguard Worker * Otherwise, just move a single job...
8168*5e7646d2SAndroid Build Coastguard Worker */
8169*5e7646d2SAndroid Build Coastguard Worker
8170*5e7646d2SAndroid Build Coastguard Worker if ((job = cupsdFindJob(attr->values[0].integer)) == NULL)
8171*5e7646d2SAndroid Build Coastguard Worker {
8172*5e7646d2SAndroid Build Coastguard Worker /*
8173*5e7646d2SAndroid Build Coastguard Worker * Nope - return a "not found" error...
8174*5e7646d2SAndroid Build Coastguard Worker */
8175*5e7646d2SAndroid Build Coastguard Worker
8176*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_NOT_FOUND,
8177*5e7646d2SAndroid Build Coastguard Worker _("Job #%d does not exist."), attr->values[0].integer);
8178*5e7646d2SAndroid Build Coastguard Worker return;
8179*5e7646d2SAndroid Build Coastguard Worker }
8180*5e7646d2SAndroid Build Coastguard Worker else
8181*5e7646d2SAndroid Build Coastguard Worker {
8182*5e7646d2SAndroid Build Coastguard Worker /*
8183*5e7646d2SAndroid Build Coastguard Worker * Job found, initialize source pointers...
8184*5e7646d2SAndroid Build Coastguard Worker */
8185*5e7646d2SAndroid Build Coastguard Worker
8186*5e7646d2SAndroid Build Coastguard Worker src = NULL;
8187*5e7646d2SAndroid Build Coastguard Worker sprinter = NULL;
8188*5e7646d2SAndroid Build Coastguard Worker }
8189*5e7646d2SAndroid Build Coastguard Worker }
8190*5e7646d2SAndroid Build Coastguard Worker }
8191*5e7646d2SAndroid Build Coastguard Worker else
8192*5e7646d2SAndroid Build Coastguard Worker {
8193*5e7646d2SAndroid Build Coastguard Worker /*
8194*5e7646d2SAndroid Build Coastguard Worker * Got a job URI; parse it to get the job ID...
8195*5e7646d2SAndroid Build Coastguard Worker */
8196*5e7646d2SAndroid Build Coastguard Worker
8197*5e7646d2SAndroid Build Coastguard Worker if (strncmp(resource, "/jobs/", 6))
8198*5e7646d2SAndroid Build Coastguard Worker {
8199*5e7646d2SAndroid Build Coastguard Worker /*
8200*5e7646d2SAndroid Build Coastguard Worker * Not a valid URI!
8201*5e7646d2SAndroid Build Coastguard Worker */
8202*5e7646d2SAndroid Build Coastguard Worker
8203*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_BAD_REQUEST, _("Bad job-uri \"%s\"."),
8204*5e7646d2SAndroid Build Coastguard Worker uri->values[0].string.text);
8205*5e7646d2SAndroid Build Coastguard Worker return;
8206*5e7646d2SAndroid Build Coastguard Worker }
8207*5e7646d2SAndroid Build Coastguard Worker
8208*5e7646d2SAndroid Build Coastguard Worker /*
8209*5e7646d2SAndroid Build Coastguard Worker * See if the job exists...
8210*5e7646d2SAndroid Build Coastguard Worker */
8211*5e7646d2SAndroid Build Coastguard Worker
8212*5e7646d2SAndroid Build Coastguard Worker jobid = atoi(resource + 6);
8213*5e7646d2SAndroid Build Coastguard Worker
8214*5e7646d2SAndroid Build Coastguard Worker if ((job = cupsdFindJob(jobid)) == NULL)
8215*5e7646d2SAndroid Build Coastguard Worker {
8216*5e7646d2SAndroid Build Coastguard Worker /*
8217*5e7646d2SAndroid Build Coastguard Worker * Nope - return a "not found" error...
8218*5e7646d2SAndroid Build Coastguard Worker */
8219*5e7646d2SAndroid Build Coastguard Worker
8220*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_NOT_FOUND, _("Job #%d does not exist."), jobid);
8221*5e7646d2SAndroid Build Coastguard Worker return;
8222*5e7646d2SAndroid Build Coastguard Worker }
8223*5e7646d2SAndroid Build Coastguard Worker else
8224*5e7646d2SAndroid Build Coastguard Worker {
8225*5e7646d2SAndroid Build Coastguard Worker /*
8226*5e7646d2SAndroid Build Coastguard Worker * Job found, initialize source pointers...
8227*5e7646d2SAndroid Build Coastguard Worker */
8228*5e7646d2SAndroid Build Coastguard Worker
8229*5e7646d2SAndroid Build Coastguard Worker src = NULL;
8230*5e7646d2SAndroid Build Coastguard Worker sprinter = NULL;
8231*5e7646d2SAndroid Build Coastguard Worker }
8232*5e7646d2SAndroid Build Coastguard Worker }
8233*5e7646d2SAndroid Build Coastguard Worker
8234*5e7646d2SAndroid Build Coastguard Worker /*
8235*5e7646d2SAndroid Build Coastguard Worker * Check the policy of the destination printer...
8236*5e7646d2SAndroid Build Coastguard Worker */
8237*5e7646d2SAndroid Build Coastguard Worker
8238*5e7646d2SAndroid Build Coastguard Worker if ((status = cupsdCheckPolicy(dprinter->op_policy_ptr, con,
8239*5e7646d2SAndroid Build Coastguard Worker job ? job->username : NULL)) != HTTP_OK)
8240*5e7646d2SAndroid Build Coastguard Worker {
8241*5e7646d2SAndroid Build Coastguard Worker send_http_error(con, status, dprinter);
8242*5e7646d2SAndroid Build Coastguard Worker return;
8243*5e7646d2SAndroid Build Coastguard Worker }
8244*5e7646d2SAndroid Build Coastguard Worker
8245*5e7646d2SAndroid Build Coastguard Worker /*
8246*5e7646d2SAndroid Build Coastguard Worker * Now move the job or jobs...
8247*5e7646d2SAndroid Build Coastguard Worker */
8248*5e7646d2SAndroid Build Coastguard Worker
8249*5e7646d2SAndroid Build Coastguard Worker if (job)
8250*5e7646d2SAndroid Build Coastguard Worker {
8251*5e7646d2SAndroid Build Coastguard Worker /*
8252*5e7646d2SAndroid Build Coastguard Worker * See if the job has been completed...
8253*5e7646d2SAndroid Build Coastguard Worker */
8254*5e7646d2SAndroid Build Coastguard Worker
8255*5e7646d2SAndroid Build Coastguard Worker if (job->state_value > IPP_JOB_STOPPED)
8256*5e7646d2SAndroid Build Coastguard Worker {
8257*5e7646d2SAndroid Build Coastguard Worker /*
8258*5e7646d2SAndroid Build Coastguard Worker * Return a "not-possible" error...
8259*5e7646d2SAndroid Build Coastguard Worker */
8260*5e7646d2SAndroid Build Coastguard Worker
8261*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_NOT_POSSIBLE,
8262*5e7646d2SAndroid Build Coastguard Worker _("Job #%d is finished and cannot be altered."),
8263*5e7646d2SAndroid Build Coastguard Worker job->id);
8264*5e7646d2SAndroid Build Coastguard Worker return;
8265*5e7646d2SAndroid Build Coastguard Worker }
8266*5e7646d2SAndroid Build Coastguard Worker
8267*5e7646d2SAndroid Build Coastguard Worker /*
8268*5e7646d2SAndroid Build Coastguard Worker * See if the job is owned by the requesting user...
8269*5e7646d2SAndroid Build Coastguard Worker */
8270*5e7646d2SAndroid Build Coastguard Worker
8271*5e7646d2SAndroid Build Coastguard Worker if (!validate_user(job, con, job->username, username, sizeof(username)))
8272*5e7646d2SAndroid Build Coastguard Worker {
8273*5e7646d2SAndroid Build Coastguard Worker send_http_error(con, con->username[0] ? HTTP_FORBIDDEN : HTTP_UNAUTHORIZED,
8274*5e7646d2SAndroid Build Coastguard Worker cupsdFindDest(job->dest));
8275*5e7646d2SAndroid Build Coastguard Worker return;
8276*5e7646d2SAndroid Build Coastguard Worker }
8277*5e7646d2SAndroid Build Coastguard Worker
8278*5e7646d2SAndroid Build Coastguard Worker /*
8279*5e7646d2SAndroid Build Coastguard Worker * Move the job to a different printer or class...
8280*5e7646d2SAndroid Build Coastguard Worker */
8281*5e7646d2SAndroid Build Coastguard Worker
8282*5e7646d2SAndroid Build Coastguard Worker cupsdMoveJob(job, dprinter);
8283*5e7646d2SAndroid Build Coastguard Worker }
8284*5e7646d2SAndroid Build Coastguard Worker else
8285*5e7646d2SAndroid Build Coastguard Worker {
8286*5e7646d2SAndroid Build Coastguard Worker /*
8287*5e7646d2SAndroid Build Coastguard Worker * Got the source printer, now look through the jobs...
8288*5e7646d2SAndroid Build Coastguard Worker */
8289*5e7646d2SAndroid Build Coastguard Worker
8290*5e7646d2SAndroid Build Coastguard Worker for (job = (cupsd_job_t *)cupsArrayFirst(Jobs);
8291*5e7646d2SAndroid Build Coastguard Worker job;
8292*5e7646d2SAndroid Build Coastguard Worker job = (cupsd_job_t *)cupsArrayNext(Jobs))
8293*5e7646d2SAndroid Build Coastguard Worker {
8294*5e7646d2SAndroid Build Coastguard Worker /*
8295*5e7646d2SAndroid Build Coastguard Worker * See if the job is pointing at the source printer or has not been
8296*5e7646d2SAndroid Build Coastguard Worker * completed...
8297*5e7646d2SAndroid Build Coastguard Worker */
8298*5e7646d2SAndroid Build Coastguard Worker
8299*5e7646d2SAndroid Build Coastguard Worker if (_cups_strcasecmp(job->dest, src) ||
8300*5e7646d2SAndroid Build Coastguard Worker job->state_value > IPP_JOB_STOPPED)
8301*5e7646d2SAndroid Build Coastguard Worker continue;
8302*5e7646d2SAndroid Build Coastguard Worker
8303*5e7646d2SAndroid Build Coastguard Worker /*
8304*5e7646d2SAndroid Build Coastguard Worker * See if the job can be moved by the requesting user...
8305*5e7646d2SAndroid Build Coastguard Worker */
8306*5e7646d2SAndroid Build Coastguard Worker
8307*5e7646d2SAndroid Build Coastguard Worker if (!validate_user(job, con, job->username, username, sizeof(username)))
8308*5e7646d2SAndroid Build Coastguard Worker continue;
8309*5e7646d2SAndroid Build Coastguard Worker
8310*5e7646d2SAndroid Build Coastguard Worker /*
8311*5e7646d2SAndroid Build Coastguard Worker * Move the job to a different printer or class...
8312*5e7646d2SAndroid Build Coastguard Worker */
8313*5e7646d2SAndroid Build Coastguard Worker
8314*5e7646d2SAndroid Build Coastguard Worker cupsdMoveJob(job, dprinter);
8315*5e7646d2SAndroid Build Coastguard Worker }
8316*5e7646d2SAndroid Build Coastguard Worker }
8317*5e7646d2SAndroid Build Coastguard Worker
8318*5e7646d2SAndroid Build Coastguard Worker /*
8319*5e7646d2SAndroid Build Coastguard Worker * Start jobs if possible...
8320*5e7646d2SAndroid Build Coastguard Worker */
8321*5e7646d2SAndroid Build Coastguard Worker
8322*5e7646d2SAndroid Build Coastguard Worker cupsdCheckJobs();
8323*5e7646d2SAndroid Build Coastguard Worker
8324*5e7646d2SAndroid Build Coastguard Worker /*
8325*5e7646d2SAndroid Build Coastguard Worker * Return with "everything is OK" status...
8326*5e7646d2SAndroid Build Coastguard Worker */
8327*5e7646d2SAndroid Build Coastguard Worker
8328*5e7646d2SAndroid Build Coastguard Worker con->response->request.status.status_code = IPP_OK;
8329*5e7646d2SAndroid Build Coastguard Worker }
8330*5e7646d2SAndroid Build Coastguard Worker
8331*5e7646d2SAndroid Build Coastguard Worker
8332*5e7646d2SAndroid Build Coastguard Worker /*
8333*5e7646d2SAndroid Build Coastguard Worker * 'ppd_parse_line()' - Parse a PPD default line.
8334*5e7646d2SAndroid Build Coastguard Worker */
8335*5e7646d2SAndroid Build Coastguard Worker
8336*5e7646d2SAndroid Build Coastguard Worker static int /* O - 0 on success, -1 on failure */
ppd_parse_line(const char * line,char * option,int olen,char * choice,int clen)8337*5e7646d2SAndroid Build Coastguard Worker ppd_parse_line(const char *line, /* I - Line */
8338*5e7646d2SAndroid Build Coastguard Worker char *option, /* O - Option name */
8339*5e7646d2SAndroid Build Coastguard Worker int olen, /* I - Size of option name */
8340*5e7646d2SAndroid Build Coastguard Worker char *choice, /* O - Choice name */
8341*5e7646d2SAndroid Build Coastguard Worker int clen) /* I - Size of choice name */
8342*5e7646d2SAndroid Build Coastguard Worker {
8343*5e7646d2SAndroid Build Coastguard Worker /*
8344*5e7646d2SAndroid Build Coastguard Worker * Verify this is a default option line...
8345*5e7646d2SAndroid Build Coastguard Worker */
8346*5e7646d2SAndroid Build Coastguard Worker
8347*5e7646d2SAndroid Build Coastguard Worker if (strncmp(line, "*Default", 8))
8348*5e7646d2SAndroid Build Coastguard Worker return (-1);
8349*5e7646d2SAndroid Build Coastguard Worker
8350*5e7646d2SAndroid Build Coastguard Worker /*
8351*5e7646d2SAndroid Build Coastguard Worker * Read the option name...
8352*5e7646d2SAndroid Build Coastguard Worker */
8353*5e7646d2SAndroid Build Coastguard Worker
8354*5e7646d2SAndroid Build Coastguard Worker for (line += 8, olen --;
8355*5e7646d2SAndroid Build Coastguard Worker *line > ' ' && *line < 0x7f && *line != ':' && *line != '/';
8356*5e7646d2SAndroid Build Coastguard Worker line ++)
8357*5e7646d2SAndroid Build Coastguard Worker if (olen > 0)
8358*5e7646d2SAndroid Build Coastguard Worker {
8359*5e7646d2SAndroid Build Coastguard Worker *option++ = *line;
8360*5e7646d2SAndroid Build Coastguard Worker olen --;
8361*5e7646d2SAndroid Build Coastguard Worker }
8362*5e7646d2SAndroid Build Coastguard Worker
8363*5e7646d2SAndroid Build Coastguard Worker *option = '\0';
8364*5e7646d2SAndroid Build Coastguard Worker
8365*5e7646d2SAndroid Build Coastguard Worker /*
8366*5e7646d2SAndroid Build Coastguard Worker * Skip everything else up to the colon (:)...
8367*5e7646d2SAndroid Build Coastguard Worker */
8368*5e7646d2SAndroid Build Coastguard Worker
8369*5e7646d2SAndroid Build Coastguard Worker while (*line && *line != ':')
8370*5e7646d2SAndroid Build Coastguard Worker line ++;
8371*5e7646d2SAndroid Build Coastguard Worker
8372*5e7646d2SAndroid Build Coastguard Worker if (!*line)
8373*5e7646d2SAndroid Build Coastguard Worker return (-1);
8374*5e7646d2SAndroid Build Coastguard Worker
8375*5e7646d2SAndroid Build Coastguard Worker line ++;
8376*5e7646d2SAndroid Build Coastguard Worker
8377*5e7646d2SAndroid Build Coastguard Worker /*
8378*5e7646d2SAndroid Build Coastguard Worker * Now grab the option choice, skipping leading whitespace...
8379*5e7646d2SAndroid Build Coastguard Worker */
8380*5e7646d2SAndroid Build Coastguard Worker
8381*5e7646d2SAndroid Build Coastguard Worker while (isspace(*line & 255))
8382*5e7646d2SAndroid Build Coastguard Worker line ++;
8383*5e7646d2SAndroid Build Coastguard Worker
8384*5e7646d2SAndroid Build Coastguard Worker for (clen --;
8385*5e7646d2SAndroid Build Coastguard Worker *line > ' ' && *line < 0x7f && *line != ':' && *line != '/';
8386*5e7646d2SAndroid Build Coastguard Worker line ++)
8387*5e7646d2SAndroid Build Coastguard Worker if (clen > 0)
8388*5e7646d2SAndroid Build Coastguard Worker {
8389*5e7646d2SAndroid Build Coastguard Worker *choice++ = *line;
8390*5e7646d2SAndroid Build Coastguard Worker clen --;
8391*5e7646d2SAndroid Build Coastguard Worker }
8392*5e7646d2SAndroid Build Coastguard Worker
8393*5e7646d2SAndroid Build Coastguard Worker *choice = '\0';
8394*5e7646d2SAndroid Build Coastguard Worker
8395*5e7646d2SAndroid Build Coastguard Worker /*
8396*5e7646d2SAndroid Build Coastguard Worker * Return with no errors...
8397*5e7646d2SAndroid Build Coastguard Worker */
8398*5e7646d2SAndroid Build Coastguard Worker
8399*5e7646d2SAndroid Build Coastguard Worker return (0);
8400*5e7646d2SAndroid Build Coastguard Worker }
8401*5e7646d2SAndroid Build Coastguard Worker
8402*5e7646d2SAndroid Build Coastguard Worker
8403*5e7646d2SAndroid Build Coastguard Worker /*
8404*5e7646d2SAndroid Build Coastguard Worker * 'print_job()' - Print a file to a printer or class.
8405*5e7646d2SAndroid Build Coastguard Worker */
8406*5e7646d2SAndroid Build Coastguard Worker
8407*5e7646d2SAndroid Build Coastguard Worker static void
print_job(cupsd_client_t * con,ipp_attribute_t * uri)8408*5e7646d2SAndroid Build Coastguard Worker print_job(cupsd_client_t *con, /* I - Client connection */
8409*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *uri) /* I - Printer URI */
8410*5e7646d2SAndroid Build Coastguard Worker {
8411*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *attr; /* Current attribute */
8412*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *doc_name; /* document-name attribute */
8413*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *format; /* Document-format attribute */
8414*5e7646d2SAndroid Build Coastguard Worker const char *default_format; /* document-format-default value */
8415*5e7646d2SAndroid Build Coastguard Worker cupsd_job_t *job; /* New job */
8416*5e7646d2SAndroid Build Coastguard Worker char filename[1024]; /* Job filename */
8417*5e7646d2SAndroid Build Coastguard Worker mime_type_t *filetype; /* Type of file */
8418*5e7646d2SAndroid Build Coastguard Worker char super[MIME_MAX_SUPER], /* Supertype of file */
8419*5e7646d2SAndroid Build Coastguard Worker type[MIME_MAX_TYPE], /* Subtype of file */
8420*5e7646d2SAndroid Build Coastguard Worker mimetype[MIME_MAX_SUPER + MIME_MAX_TYPE + 2];
8421*5e7646d2SAndroid Build Coastguard Worker /* Textual name of mime type */
8422*5e7646d2SAndroid Build Coastguard Worker cupsd_printer_t *printer; /* Printer data */
8423*5e7646d2SAndroid Build Coastguard Worker struct stat fileinfo; /* File information */
8424*5e7646d2SAndroid Build Coastguard Worker int kbytes; /* Size of file */
8425*5e7646d2SAndroid Build Coastguard Worker int compression; /* Document compression */
8426*5e7646d2SAndroid Build Coastguard Worker
8427*5e7646d2SAndroid Build Coastguard Worker
8428*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG2, "print_job(%p[%d], %s)", con, con->number,
8429*5e7646d2SAndroid Build Coastguard Worker uri->values[0].string.text);
8430*5e7646d2SAndroid Build Coastguard Worker
8431*5e7646d2SAndroid Build Coastguard Worker /*
8432*5e7646d2SAndroid Build Coastguard Worker * Validate print file attributes, for now just document-format and
8433*5e7646d2SAndroid Build Coastguard Worker * compression (CUPS only supports "none" and "gzip")...
8434*5e7646d2SAndroid Build Coastguard Worker */
8435*5e7646d2SAndroid Build Coastguard Worker
8436*5e7646d2SAndroid Build Coastguard Worker compression = CUPS_FILE_NONE;
8437*5e7646d2SAndroid Build Coastguard Worker
8438*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippFindAttribute(con->request, "compression",
8439*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_KEYWORD)) != NULL)
8440*5e7646d2SAndroid Build Coastguard Worker {
8441*5e7646d2SAndroid Build Coastguard Worker if (strcmp(attr->values[0].string.text, "none")
8442*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_LIBZ
8443*5e7646d2SAndroid Build Coastguard Worker && strcmp(attr->values[0].string.text, "gzip")
8444*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_LIBZ */
8445*5e7646d2SAndroid Build Coastguard Worker )
8446*5e7646d2SAndroid Build Coastguard Worker {
8447*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_ATTRIBUTES,
8448*5e7646d2SAndroid Build Coastguard Worker _("Unsupported compression \"%s\"."),
8449*5e7646d2SAndroid Build Coastguard Worker attr->values[0].string.text);
8450*5e7646d2SAndroid Build Coastguard Worker ippAddString(con->response, IPP_TAG_UNSUPPORTED_GROUP, IPP_TAG_KEYWORD,
8451*5e7646d2SAndroid Build Coastguard Worker "compression", NULL, attr->values[0].string.text);
8452*5e7646d2SAndroid Build Coastguard Worker return;
8453*5e7646d2SAndroid Build Coastguard Worker }
8454*5e7646d2SAndroid Build Coastguard Worker
8455*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_LIBZ
8456*5e7646d2SAndroid Build Coastguard Worker if (!strcmp(attr->values[0].string.text, "gzip"))
8457*5e7646d2SAndroid Build Coastguard Worker compression = CUPS_FILE_GZIP;
8458*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_LIBZ */
8459*5e7646d2SAndroid Build Coastguard Worker }
8460*5e7646d2SAndroid Build Coastguard Worker
8461*5e7646d2SAndroid Build Coastguard Worker /*
8462*5e7646d2SAndroid Build Coastguard Worker * Do we have a file to print?
8463*5e7646d2SAndroid Build Coastguard Worker */
8464*5e7646d2SAndroid Build Coastguard Worker
8465*5e7646d2SAndroid Build Coastguard Worker if (!con->filename)
8466*5e7646d2SAndroid Build Coastguard Worker {
8467*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_BAD_REQUEST, _("No file in print request."));
8468*5e7646d2SAndroid Build Coastguard Worker return;
8469*5e7646d2SAndroid Build Coastguard Worker }
8470*5e7646d2SAndroid Build Coastguard Worker
8471*5e7646d2SAndroid Build Coastguard Worker /*
8472*5e7646d2SAndroid Build Coastguard Worker * Is the destination valid?
8473*5e7646d2SAndroid Build Coastguard Worker */
8474*5e7646d2SAndroid Build Coastguard Worker
8475*5e7646d2SAndroid Build Coastguard Worker if (!cupsdValidateDest(uri->values[0].string.text, NULL, &printer))
8476*5e7646d2SAndroid Build Coastguard Worker {
8477*5e7646d2SAndroid Build Coastguard Worker /*
8478*5e7646d2SAndroid Build Coastguard Worker * Bad URI...
8479*5e7646d2SAndroid Build Coastguard Worker */
8480*5e7646d2SAndroid Build Coastguard Worker
8481*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_NOT_FOUND,
8482*5e7646d2SAndroid Build Coastguard Worker _("The printer or class does not exist."));
8483*5e7646d2SAndroid Build Coastguard Worker return;
8484*5e7646d2SAndroid Build Coastguard Worker }
8485*5e7646d2SAndroid Build Coastguard Worker
8486*5e7646d2SAndroid Build Coastguard Worker /*
8487*5e7646d2SAndroid Build Coastguard Worker * Is it a format we support?
8488*5e7646d2SAndroid Build Coastguard Worker */
8489*5e7646d2SAndroid Build Coastguard Worker
8490*5e7646d2SAndroid Build Coastguard Worker doc_name = ippFindAttribute(con->request, "document-name", IPP_TAG_NAME);
8491*5e7646d2SAndroid Build Coastguard Worker if (doc_name)
8492*5e7646d2SAndroid Build Coastguard Worker ippSetName(con->request, &doc_name, "document-name-supplied");
8493*5e7646d2SAndroid Build Coastguard Worker
8494*5e7646d2SAndroid Build Coastguard Worker if ((format = ippFindAttribute(con->request, "document-format",
8495*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_MIMETYPE)) != NULL)
8496*5e7646d2SAndroid Build Coastguard Worker {
8497*5e7646d2SAndroid Build Coastguard Worker /*
8498*5e7646d2SAndroid Build Coastguard Worker * Grab format from client...
8499*5e7646d2SAndroid Build Coastguard Worker */
8500*5e7646d2SAndroid Build Coastguard Worker
8501*5e7646d2SAndroid Build Coastguard Worker if (sscanf(format->values[0].string.text, "%15[^/]/%255[^;]", super,
8502*5e7646d2SAndroid Build Coastguard Worker type) != 2)
8503*5e7646d2SAndroid Build Coastguard Worker {
8504*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_BAD_REQUEST,
8505*5e7646d2SAndroid Build Coastguard Worker _("Bad document-format \"%s\"."),
8506*5e7646d2SAndroid Build Coastguard Worker format->values[0].string.text);
8507*5e7646d2SAndroid Build Coastguard Worker return;
8508*5e7646d2SAndroid Build Coastguard Worker }
8509*5e7646d2SAndroid Build Coastguard Worker
8510*5e7646d2SAndroid Build Coastguard Worker ippAddString(con->request, IPP_TAG_JOB, IPP_TAG_MIMETYPE, "document-format-supplied", NULL, ippGetString(format, 0, NULL));
8511*5e7646d2SAndroid Build Coastguard Worker }
8512*5e7646d2SAndroid Build Coastguard Worker else if ((default_format = cupsGetOption("document-format",
8513*5e7646d2SAndroid Build Coastguard Worker printer->num_options,
8514*5e7646d2SAndroid Build Coastguard Worker printer->options)) != NULL)
8515*5e7646d2SAndroid Build Coastguard Worker {
8516*5e7646d2SAndroid Build Coastguard Worker /*
8517*5e7646d2SAndroid Build Coastguard Worker * Use default document format...
8518*5e7646d2SAndroid Build Coastguard Worker */
8519*5e7646d2SAndroid Build Coastguard Worker
8520*5e7646d2SAndroid Build Coastguard Worker if (sscanf(default_format, "%15[^/]/%255[^;]", super, type) != 2)
8521*5e7646d2SAndroid Build Coastguard Worker {
8522*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_BAD_REQUEST,
8523*5e7646d2SAndroid Build Coastguard Worker _("Bad document-format \"%s\"."),
8524*5e7646d2SAndroid Build Coastguard Worker default_format);
8525*5e7646d2SAndroid Build Coastguard Worker return;
8526*5e7646d2SAndroid Build Coastguard Worker }
8527*5e7646d2SAndroid Build Coastguard Worker }
8528*5e7646d2SAndroid Build Coastguard Worker else
8529*5e7646d2SAndroid Build Coastguard Worker {
8530*5e7646d2SAndroid Build Coastguard Worker /*
8531*5e7646d2SAndroid Build Coastguard Worker * Auto-type it!
8532*5e7646d2SAndroid Build Coastguard Worker */
8533*5e7646d2SAndroid Build Coastguard Worker
8534*5e7646d2SAndroid Build Coastguard Worker strlcpy(super, "application", sizeof(super));
8535*5e7646d2SAndroid Build Coastguard Worker strlcpy(type, "octet-stream", sizeof(type));
8536*5e7646d2SAndroid Build Coastguard Worker }
8537*5e7646d2SAndroid Build Coastguard Worker
8538*5e7646d2SAndroid Build Coastguard Worker if (!strcmp(super, "application") && !strcmp(type, "octet-stream"))
8539*5e7646d2SAndroid Build Coastguard Worker {
8540*5e7646d2SAndroid Build Coastguard Worker /*
8541*5e7646d2SAndroid Build Coastguard Worker * Auto-type the file...
8542*5e7646d2SAndroid Build Coastguard Worker */
8543*5e7646d2SAndroid Build Coastguard Worker
8544*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG, "[Job ???] Auto-typing file...");
8545*5e7646d2SAndroid Build Coastguard Worker
8546*5e7646d2SAndroid Build Coastguard Worker
8547*5e7646d2SAndroid Build Coastguard Worker filetype = mimeFileType(MimeDatabase, con->filename,
8548*5e7646d2SAndroid Build Coastguard Worker doc_name ? doc_name->values[0].string.text : NULL,
8549*5e7646d2SAndroid Build Coastguard Worker &compression);
8550*5e7646d2SAndroid Build Coastguard Worker
8551*5e7646d2SAndroid Build Coastguard Worker if (!filetype)
8552*5e7646d2SAndroid Build Coastguard Worker filetype = mimeType(MimeDatabase, super, type);
8553*5e7646d2SAndroid Build Coastguard Worker
8554*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_INFO, "[Job ???] Request file type is %s/%s.",
8555*5e7646d2SAndroid Build Coastguard Worker filetype->super, filetype->type);
8556*5e7646d2SAndroid Build Coastguard Worker
8557*5e7646d2SAndroid Build Coastguard Worker snprintf(mimetype, sizeof(mimetype), "%s/%s", filetype->super, filetype->type);
8558*5e7646d2SAndroid Build Coastguard Worker ippAddString(con->request, IPP_TAG_JOB, IPP_TAG_MIMETYPE, "document-format-detected", NULL, mimetype);
8559*5e7646d2SAndroid Build Coastguard Worker }
8560*5e7646d2SAndroid Build Coastguard Worker else
8561*5e7646d2SAndroid Build Coastguard Worker filetype = mimeType(MimeDatabase, super, type);
8562*5e7646d2SAndroid Build Coastguard Worker
8563*5e7646d2SAndroid Build Coastguard Worker if (filetype &&
8564*5e7646d2SAndroid Build Coastguard Worker (!format ||
8565*5e7646d2SAndroid Build Coastguard Worker (!strcmp(super, "application") && !strcmp(type, "octet-stream"))))
8566*5e7646d2SAndroid Build Coastguard Worker {
8567*5e7646d2SAndroid Build Coastguard Worker /*
8568*5e7646d2SAndroid Build Coastguard Worker * Replace the document-format attribute value with the auto-typed or
8569*5e7646d2SAndroid Build Coastguard Worker * default one.
8570*5e7646d2SAndroid Build Coastguard Worker */
8571*5e7646d2SAndroid Build Coastguard Worker
8572*5e7646d2SAndroid Build Coastguard Worker snprintf(mimetype, sizeof(mimetype), "%s/%s", filetype->super,
8573*5e7646d2SAndroid Build Coastguard Worker filetype->type);
8574*5e7646d2SAndroid Build Coastguard Worker
8575*5e7646d2SAndroid Build Coastguard Worker if (format)
8576*5e7646d2SAndroid Build Coastguard Worker ippSetString(con->request, &format, 0, mimetype);
8577*5e7646d2SAndroid Build Coastguard Worker else
8578*5e7646d2SAndroid Build Coastguard Worker ippAddString(con->request, IPP_TAG_JOB, IPP_TAG_MIMETYPE,
8579*5e7646d2SAndroid Build Coastguard Worker "document-format", NULL, mimetype);
8580*5e7646d2SAndroid Build Coastguard Worker }
8581*5e7646d2SAndroid Build Coastguard Worker else if (!filetype)
8582*5e7646d2SAndroid Build Coastguard Worker {
8583*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_DOCUMENT_FORMAT,
8584*5e7646d2SAndroid Build Coastguard Worker _("Unsupported document-format \"%s\"."),
8585*5e7646d2SAndroid Build Coastguard Worker format ? format->values[0].string.text :
8586*5e7646d2SAndroid Build Coastguard Worker "application/octet-stream");
8587*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_INFO,
8588*5e7646d2SAndroid Build Coastguard Worker "Hint: Do you have the raw file printing rules enabled?");
8589*5e7646d2SAndroid Build Coastguard Worker
8590*5e7646d2SAndroid Build Coastguard Worker if (format)
8591*5e7646d2SAndroid Build Coastguard Worker ippAddString(con->response, IPP_TAG_UNSUPPORTED_GROUP, IPP_TAG_MIMETYPE,
8592*5e7646d2SAndroid Build Coastguard Worker "document-format", NULL, format->values[0].string.text);
8593*5e7646d2SAndroid Build Coastguard Worker
8594*5e7646d2SAndroid Build Coastguard Worker return;
8595*5e7646d2SAndroid Build Coastguard Worker }
8596*5e7646d2SAndroid Build Coastguard Worker
8597*5e7646d2SAndroid Build Coastguard Worker /*
8598*5e7646d2SAndroid Build Coastguard Worker * Read any embedded job ticket info from PS files...
8599*5e7646d2SAndroid Build Coastguard Worker */
8600*5e7646d2SAndroid Build Coastguard Worker
8601*5e7646d2SAndroid Build Coastguard Worker if (!_cups_strcasecmp(filetype->super, "application") &&
8602*5e7646d2SAndroid Build Coastguard Worker (!_cups_strcasecmp(filetype->type, "postscript") ||
8603*5e7646d2SAndroid Build Coastguard Worker !_cups_strcasecmp(filetype->type, "pdf")))
8604*5e7646d2SAndroid Build Coastguard Worker read_job_ticket(con);
8605*5e7646d2SAndroid Build Coastguard Worker
8606*5e7646d2SAndroid Build Coastguard Worker /*
8607*5e7646d2SAndroid Build Coastguard Worker * Create the job object...
8608*5e7646d2SAndroid Build Coastguard Worker */
8609*5e7646d2SAndroid Build Coastguard Worker
8610*5e7646d2SAndroid Build Coastguard Worker if ((job = add_job(con, printer, filetype)) == NULL)
8611*5e7646d2SAndroid Build Coastguard Worker return;
8612*5e7646d2SAndroid Build Coastguard Worker
8613*5e7646d2SAndroid Build Coastguard Worker /*
8614*5e7646d2SAndroid Build Coastguard Worker * Update quota data...
8615*5e7646d2SAndroid Build Coastguard Worker */
8616*5e7646d2SAndroid Build Coastguard Worker
8617*5e7646d2SAndroid Build Coastguard Worker if (stat(con->filename, &fileinfo))
8618*5e7646d2SAndroid Build Coastguard Worker kbytes = 0;
8619*5e7646d2SAndroid Build Coastguard Worker else
8620*5e7646d2SAndroid Build Coastguard Worker kbytes = (fileinfo.st_size + 1023) / 1024;
8621*5e7646d2SAndroid Build Coastguard Worker
8622*5e7646d2SAndroid Build Coastguard Worker cupsdUpdateQuota(printer, job->username, 0, kbytes);
8623*5e7646d2SAndroid Build Coastguard Worker
8624*5e7646d2SAndroid Build Coastguard Worker job->koctets += kbytes;
8625*5e7646d2SAndroid Build Coastguard Worker
8626*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippFindAttribute(job->attrs, "job-k-octets", IPP_TAG_INTEGER)) != NULL)
8627*5e7646d2SAndroid Build Coastguard Worker attr->values[0].integer += kbytes;
8628*5e7646d2SAndroid Build Coastguard Worker
8629*5e7646d2SAndroid Build Coastguard Worker /*
8630*5e7646d2SAndroid Build Coastguard Worker * Add the job file...
8631*5e7646d2SAndroid Build Coastguard Worker */
8632*5e7646d2SAndroid Build Coastguard Worker
8633*5e7646d2SAndroid Build Coastguard Worker if (add_file(con, job, filetype, compression))
8634*5e7646d2SAndroid Build Coastguard Worker return;
8635*5e7646d2SAndroid Build Coastguard Worker
8636*5e7646d2SAndroid Build Coastguard Worker snprintf(filename, sizeof(filename), "%s/d%05d-%03d", RequestRoot, job->id, job->num_files);
8637*5e7646d2SAndroid Build Coastguard Worker if (rename(con->filename, filename))
8638*5e7646d2SAndroid Build Coastguard Worker {
8639*5e7646d2SAndroid Build Coastguard Worker cupsdLogJob(job, CUPSD_LOG_ERROR, "Unable to rename job document file \"%s\": %s", filename, strerror(errno));
8640*5e7646d2SAndroid Build Coastguard Worker
8641*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_INTERNAL_ERROR, _("Unable to rename job document file."));
8642*5e7646d2SAndroid Build Coastguard Worker return;
8643*5e7646d2SAndroid Build Coastguard Worker }
8644*5e7646d2SAndroid Build Coastguard Worker
8645*5e7646d2SAndroid Build Coastguard Worker cupsdClearString(&con->filename);
8646*5e7646d2SAndroid Build Coastguard Worker
8647*5e7646d2SAndroid Build Coastguard Worker /*
8648*5e7646d2SAndroid Build Coastguard Worker * See if we need to add the ending sheet...
8649*5e7646d2SAndroid Build Coastguard Worker */
8650*5e7646d2SAndroid Build Coastguard Worker
8651*5e7646d2SAndroid Build Coastguard Worker if (cupsdTimeoutJob(job))
8652*5e7646d2SAndroid Build Coastguard Worker return;
8653*5e7646d2SAndroid Build Coastguard Worker
8654*5e7646d2SAndroid Build Coastguard Worker /*
8655*5e7646d2SAndroid Build Coastguard Worker * Log and save the job...
8656*5e7646d2SAndroid Build Coastguard Worker */
8657*5e7646d2SAndroid Build Coastguard Worker
8658*5e7646d2SAndroid Build Coastguard Worker cupsdLogJob(job, CUPSD_LOG_INFO,
8659*5e7646d2SAndroid Build Coastguard Worker "File of type %s/%s queued by \"%s\".",
8660*5e7646d2SAndroid Build Coastguard Worker filetype->super, filetype->type, job->username);
8661*5e7646d2SAndroid Build Coastguard Worker cupsdLogJob(job, CUPSD_LOG_DEBUG, "hold_until=%d", (int)job->hold_until);
8662*5e7646d2SAndroid Build Coastguard Worker cupsdLogJob(job, CUPSD_LOG_INFO, "Queued on \"%s\" by \"%s\".",
8663*5e7646d2SAndroid Build Coastguard Worker job->dest, job->username);
8664*5e7646d2SAndroid Build Coastguard Worker
8665*5e7646d2SAndroid Build Coastguard Worker /*
8666*5e7646d2SAndroid Build Coastguard Worker * Start the job if possible...
8667*5e7646d2SAndroid Build Coastguard Worker */
8668*5e7646d2SAndroid Build Coastguard Worker
8669*5e7646d2SAndroid Build Coastguard Worker cupsdCheckJobs();
8670*5e7646d2SAndroid Build Coastguard Worker }
8671*5e7646d2SAndroid Build Coastguard Worker
8672*5e7646d2SAndroid Build Coastguard Worker
8673*5e7646d2SAndroid Build Coastguard Worker /*
8674*5e7646d2SAndroid Build Coastguard Worker * 'read_job_ticket()' - Read a job ticket embedded in a print file.
8675*5e7646d2SAndroid Build Coastguard Worker *
8676*5e7646d2SAndroid Build Coastguard Worker * This function only gets called when printing a single PDF or PostScript
8677*5e7646d2SAndroid Build Coastguard Worker * file using the Print-Job operation. It doesn't work for Create-Job +
8678*5e7646d2SAndroid Build Coastguard Worker * Send-File, since the job attributes need to be set at job creation
8679*5e7646d2SAndroid Build Coastguard Worker * time for banners to work. The embedded job ticket stuff is here
8680*5e7646d2SAndroid Build Coastguard Worker * primarily to allow the Windows printer driver for CUPS to pass in JCL
8681*5e7646d2SAndroid Build Coastguard Worker * options and IPP attributes which otherwise would be lost.
8682*5e7646d2SAndroid Build Coastguard Worker *
8683*5e7646d2SAndroid Build Coastguard Worker * The format of a job ticket is simple:
8684*5e7646d2SAndroid Build Coastguard Worker *
8685*5e7646d2SAndroid Build Coastguard Worker * %cupsJobTicket: attr1=value1 attr2=value2 ... attrN=valueN
8686*5e7646d2SAndroid Build Coastguard Worker *
8687*5e7646d2SAndroid Build Coastguard Worker * %cupsJobTicket: attr1=value1
8688*5e7646d2SAndroid Build Coastguard Worker * %cupsJobTicket: attr2=value2
8689*5e7646d2SAndroid Build Coastguard Worker * ...
8690*5e7646d2SAndroid Build Coastguard Worker * %cupsJobTicket: attrN=valueN
8691*5e7646d2SAndroid Build Coastguard Worker *
8692*5e7646d2SAndroid Build Coastguard Worker * Job ticket lines must appear immediately after the first line that
8693*5e7646d2SAndroid Build Coastguard Worker * specifies PostScript (%!PS-Adobe-3.0) or PDF (%PDF) format, and CUPS
8694*5e7646d2SAndroid Build Coastguard Worker * stops looking for job ticket info when it finds a line that does not begin
8695*5e7646d2SAndroid Build Coastguard Worker * with "%cupsJobTicket:".
8696*5e7646d2SAndroid Build Coastguard Worker *
8697*5e7646d2SAndroid Build Coastguard Worker * The maximum length of a job ticket line, including the prefix, is
8698*5e7646d2SAndroid Build Coastguard Worker * 255 characters to conform with the Adobe DSC.
8699*5e7646d2SAndroid Build Coastguard Worker *
8700*5e7646d2SAndroid Build Coastguard Worker * Read-only attributes are rejected with a notice to the error log in
8701*5e7646d2SAndroid Build Coastguard Worker * case a malicious user tries anything. Since the job ticket is read
8702*5e7646d2SAndroid Build Coastguard Worker * prior to attribute validation in print_job(), job ticket attributes
8703*5e7646d2SAndroid Build Coastguard Worker * will go through the same validation as IPP attributes...
8704*5e7646d2SAndroid Build Coastguard Worker */
8705*5e7646d2SAndroid Build Coastguard Worker
8706*5e7646d2SAndroid Build Coastguard Worker static void
read_job_ticket(cupsd_client_t * con)8707*5e7646d2SAndroid Build Coastguard Worker read_job_ticket(cupsd_client_t *con) /* I - Client connection */
8708*5e7646d2SAndroid Build Coastguard Worker {
8709*5e7646d2SAndroid Build Coastguard Worker cups_file_t *fp; /* File to read from */
8710*5e7646d2SAndroid Build Coastguard Worker char line[256]; /* Line data */
8711*5e7646d2SAndroid Build Coastguard Worker int num_options; /* Number of options */
8712*5e7646d2SAndroid Build Coastguard Worker cups_option_t *options; /* Options */
8713*5e7646d2SAndroid Build Coastguard Worker ipp_t *ticket; /* New attributes */
8714*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *attr, /* Current attribute */
8715*5e7646d2SAndroid Build Coastguard Worker *attr2, /* Job attribute */
8716*5e7646d2SAndroid Build Coastguard Worker *prev2; /* Previous job attribute */
8717*5e7646d2SAndroid Build Coastguard Worker
8718*5e7646d2SAndroid Build Coastguard Worker
8719*5e7646d2SAndroid Build Coastguard Worker /*
8720*5e7646d2SAndroid Build Coastguard Worker * First open the print file...
8721*5e7646d2SAndroid Build Coastguard Worker */
8722*5e7646d2SAndroid Build Coastguard Worker
8723*5e7646d2SAndroid Build Coastguard Worker if ((fp = cupsFileOpen(con->filename, "rb")) == NULL)
8724*5e7646d2SAndroid Build Coastguard Worker {
8725*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_ERROR,
8726*5e7646d2SAndroid Build Coastguard Worker "Unable to open print file for job ticket - %s",
8727*5e7646d2SAndroid Build Coastguard Worker strerror(errno));
8728*5e7646d2SAndroid Build Coastguard Worker return;
8729*5e7646d2SAndroid Build Coastguard Worker }
8730*5e7646d2SAndroid Build Coastguard Worker
8731*5e7646d2SAndroid Build Coastguard Worker /*
8732*5e7646d2SAndroid Build Coastguard Worker * Skip the first line...
8733*5e7646d2SAndroid Build Coastguard Worker */
8734*5e7646d2SAndroid Build Coastguard Worker
8735*5e7646d2SAndroid Build Coastguard Worker if (cupsFileGets(fp, line, sizeof(line)) == NULL)
8736*5e7646d2SAndroid Build Coastguard Worker {
8737*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_ERROR,
8738*5e7646d2SAndroid Build Coastguard Worker "Unable to read from print file for job ticket - %s",
8739*5e7646d2SAndroid Build Coastguard Worker strerror(errno));
8740*5e7646d2SAndroid Build Coastguard Worker cupsFileClose(fp);
8741*5e7646d2SAndroid Build Coastguard Worker return;
8742*5e7646d2SAndroid Build Coastguard Worker }
8743*5e7646d2SAndroid Build Coastguard Worker
8744*5e7646d2SAndroid Build Coastguard Worker if (strncmp(line, "%!PS-Adobe-", 11) && strncmp(line, "%PDF-", 5))
8745*5e7646d2SAndroid Build Coastguard Worker {
8746*5e7646d2SAndroid Build Coastguard Worker /*
8747*5e7646d2SAndroid Build Coastguard Worker * Not a DSC-compliant file, so no job ticket info will be available...
8748*5e7646d2SAndroid Build Coastguard Worker */
8749*5e7646d2SAndroid Build Coastguard Worker
8750*5e7646d2SAndroid Build Coastguard Worker cupsFileClose(fp);
8751*5e7646d2SAndroid Build Coastguard Worker return;
8752*5e7646d2SAndroid Build Coastguard Worker }
8753*5e7646d2SAndroid Build Coastguard Worker
8754*5e7646d2SAndroid Build Coastguard Worker /*
8755*5e7646d2SAndroid Build Coastguard Worker * Read job ticket info from the file...
8756*5e7646d2SAndroid Build Coastguard Worker */
8757*5e7646d2SAndroid Build Coastguard Worker
8758*5e7646d2SAndroid Build Coastguard Worker num_options = 0;
8759*5e7646d2SAndroid Build Coastguard Worker options = NULL;
8760*5e7646d2SAndroid Build Coastguard Worker
8761*5e7646d2SAndroid Build Coastguard Worker while (cupsFileGets(fp, line, sizeof(line)))
8762*5e7646d2SAndroid Build Coastguard Worker {
8763*5e7646d2SAndroid Build Coastguard Worker /*
8764*5e7646d2SAndroid Build Coastguard Worker * Stop at the first non-ticket line...
8765*5e7646d2SAndroid Build Coastguard Worker */
8766*5e7646d2SAndroid Build Coastguard Worker
8767*5e7646d2SAndroid Build Coastguard Worker if (strncmp(line, "%cupsJobTicket:", 15))
8768*5e7646d2SAndroid Build Coastguard Worker break;
8769*5e7646d2SAndroid Build Coastguard Worker
8770*5e7646d2SAndroid Build Coastguard Worker /*
8771*5e7646d2SAndroid Build Coastguard Worker * Add the options to the option array...
8772*5e7646d2SAndroid Build Coastguard Worker */
8773*5e7646d2SAndroid Build Coastguard Worker
8774*5e7646d2SAndroid Build Coastguard Worker num_options = cupsParseOptions(line + 15, num_options, &options);
8775*5e7646d2SAndroid Build Coastguard Worker }
8776*5e7646d2SAndroid Build Coastguard Worker
8777*5e7646d2SAndroid Build Coastguard Worker /*
8778*5e7646d2SAndroid Build Coastguard Worker * Done with the file; see if we have any options...
8779*5e7646d2SAndroid Build Coastguard Worker */
8780*5e7646d2SAndroid Build Coastguard Worker
8781*5e7646d2SAndroid Build Coastguard Worker cupsFileClose(fp);
8782*5e7646d2SAndroid Build Coastguard Worker
8783*5e7646d2SAndroid Build Coastguard Worker if (num_options == 0)
8784*5e7646d2SAndroid Build Coastguard Worker return;
8785*5e7646d2SAndroid Build Coastguard Worker
8786*5e7646d2SAndroid Build Coastguard Worker /*
8787*5e7646d2SAndroid Build Coastguard Worker * OK, convert the options to an attribute list, and apply them to
8788*5e7646d2SAndroid Build Coastguard Worker * the request...
8789*5e7646d2SAndroid Build Coastguard Worker */
8790*5e7646d2SAndroid Build Coastguard Worker
8791*5e7646d2SAndroid Build Coastguard Worker ticket = ippNew();
8792*5e7646d2SAndroid Build Coastguard Worker cupsEncodeOptions(ticket, num_options, options);
8793*5e7646d2SAndroid Build Coastguard Worker
8794*5e7646d2SAndroid Build Coastguard Worker /*
8795*5e7646d2SAndroid Build Coastguard Worker * See what the user wants to change.
8796*5e7646d2SAndroid Build Coastguard Worker */
8797*5e7646d2SAndroid Build Coastguard Worker
8798*5e7646d2SAndroid Build Coastguard Worker for (attr = ticket->attrs; attr; attr = attr->next)
8799*5e7646d2SAndroid Build Coastguard Worker {
8800*5e7646d2SAndroid Build Coastguard Worker if (attr->group_tag != IPP_TAG_JOB || !attr->name)
8801*5e7646d2SAndroid Build Coastguard Worker continue;
8802*5e7646d2SAndroid Build Coastguard Worker
8803*5e7646d2SAndroid Build Coastguard Worker if (!strncmp(attr->name, "date-time-at-", 13) ||
8804*5e7646d2SAndroid Build Coastguard Worker !strcmp(attr->name, "job-impressions-completed") ||
8805*5e7646d2SAndroid Build Coastguard Worker !strcmp(attr->name, "job-media-sheets-completed") ||
8806*5e7646d2SAndroid Build Coastguard Worker !strncmp(attr->name, "job-k-octets", 12) ||
8807*5e7646d2SAndroid Build Coastguard Worker !strcmp(attr->name, "job-id") ||
8808*5e7646d2SAndroid Build Coastguard Worker !strcmp(attr->name, "job-originating-host-name") ||
8809*5e7646d2SAndroid Build Coastguard Worker !strcmp(attr->name, "job-originating-user-name") ||
8810*5e7646d2SAndroid Build Coastguard Worker !strcmp(attr->name, "job-pages-completed") ||
8811*5e7646d2SAndroid Build Coastguard Worker !strcmp(attr->name, "job-printer-uri") ||
8812*5e7646d2SAndroid Build Coastguard Worker !strncmp(attr->name, "job-state", 9) ||
8813*5e7646d2SAndroid Build Coastguard Worker !strcmp(attr->name, "job-uri") ||
8814*5e7646d2SAndroid Build Coastguard Worker !strncmp(attr->name, "time-at-", 8))
8815*5e7646d2SAndroid Build Coastguard Worker continue; /* Read-only attrs */
8816*5e7646d2SAndroid Build Coastguard Worker
8817*5e7646d2SAndroid Build Coastguard Worker if ((attr2 = ippFindAttribute(con->request, attr->name,
8818*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_ZERO)) != NULL)
8819*5e7646d2SAndroid Build Coastguard Worker {
8820*5e7646d2SAndroid Build Coastguard Worker /*
8821*5e7646d2SAndroid Build Coastguard Worker * Some other value; first free the old value...
8822*5e7646d2SAndroid Build Coastguard Worker */
8823*5e7646d2SAndroid Build Coastguard Worker
8824*5e7646d2SAndroid Build Coastguard Worker if (con->request->attrs == attr2)
8825*5e7646d2SAndroid Build Coastguard Worker {
8826*5e7646d2SAndroid Build Coastguard Worker con->request->attrs = attr2->next;
8827*5e7646d2SAndroid Build Coastguard Worker prev2 = NULL;
8828*5e7646d2SAndroid Build Coastguard Worker }
8829*5e7646d2SAndroid Build Coastguard Worker else
8830*5e7646d2SAndroid Build Coastguard Worker {
8831*5e7646d2SAndroid Build Coastguard Worker for (prev2 = con->request->attrs; prev2; prev2 = prev2->next)
8832*5e7646d2SAndroid Build Coastguard Worker if (prev2->next == attr2)
8833*5e7646d2SAndroid Build Coastguard Worker {
8834*5e7646d2SAndroid Build Coastguard Worker prev2->next = attr2->next;
8835*5e7646d2SAndroid Build Coastguard Worker break;
8836*5e7646d2SAndroid Build Coastguard Worker }
8837*5e7646d2SAndroid Build Coastguard Worker }
8838*5e7646d2SAndroid Build Coastguard Worker
8839*5e7646d2SAndroid Build Coastguard Worker if (con->request->last == attr2)
8840*5e7646d2SAndroid Build Coastguard Worker con->request->last = prev2;
8841*5e7646d2SAndroid Build Coastguard Worker
8842*5e7646d2SAndroid Build Coastguard Worker ippDeleteAttribute(NULL, attr2);
8843*5e7646d2SAndroid Build Coastguard Worker }
8844*5e7646d2SAndroid Build Coastguard Worker
8845*5e7646d2SAndroid Build Coastguard Worker /*
8846*5e7646d2SAndroid Build Coastguard Worker * Add new option by copying it...
8847*5e7646d2SAndroid Build Coastguard Worker */
8848*5e7646d2SAndroid Build Coastguard Worker
8849*5e7646d2SAndroid Build Coastguard Worker ippCopyAttribute(con->request, attr, 0);
8850*5e7646d2SAndroid Build Coastguard Worker }
8851*5e7646d2SAndroid Build Coastguard Worker
8852*5e7646d2SAndroid Build Coastguard Worker /*
8853*5e7646d2SAndroid Build Coastguard Worker * Then free the attribute list and option array...
8854*5e7646d2SAndroid Build Coastguard Worker */
8855*5e7646d2SAndroid Build Coastguard Worker
8856*5e7646d2SAndroid Build Coastguard Worker ippDelete(ticket);
8857*5e7646d2SAndroid Build Coastguard Worker cupsFreeOptions(num_options, options);
8858*5e7646d2SAndroid Build Coastguard Worker }
8859*5e7646d2SAndroid Build Coastguard Worker
8860*5e7646d2SAndroid Build Coastguard Worker
8861*5e7646d2SAndroid Build Coastguard Worker /*
8862*5e7646d2SAndroid Build Coastguard Worker * 'reject_jobs()' - Reject print jobs to a printer.
8863*5e7646d2SAndroid Build Coastguard Worker */
8864*5e7646d2SAndroid Build Coastguard Worker
8865*5e7646d2SAndroid Build Coastguard Worker static void
reject_jobs(cupsd_client_t * con,ipp_attribute_t * uri)8866*5e7646d2SAndroid Build Coastguard Worker reject_jobs(cupsd_client_t *con, /* I - Client connection */
8867*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *uri) /* I - Printer or class URI */
8868*5e7646d2SAndroid Build Coastguard Worker {
8869*5e7646d2SAndroid Build Coastguard Worker http_status_t status; /* Policy status */
8870*5e7646d2SAndroid Build Coastguard Worker cups_ptype_t dtype; /* Destination type (printer/class) */
8871*5e7646d2SAndroid Build Coastguard Worker cupsd_printer_t *printer; /* Printer data */
8872*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *attr; /* printer-state-message text */
8873*5e7646d2SAndroid Build Coastguard Worker
8874*5e7646d2SAndroid Build Coastguard Worker
8875*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG2, "reject_jobs(%p[%d], %s)", con,
8876*5e7646d2SAndroid Build Coastguard Worker con->number, uri->values[0].string.text);
8877*5e7646d2SAndroid Build Coastguard Worker
8878*5e7646d2SAndroid Build Coastguard Worker /*
8879*5e7646d2SAndroid Build Coastguard Worker * Is the destination valid?
8880*5e7646d2SAndroid Build Coastguard Worker */
8881*5e7646d2SAndroid Build Coastguard Worker
8882*5e7646d2SAndroid Build Coastguard Worker if (!cupsdValidateDest(uri->values[0].string.text, &dtype, &printer))
8883*5e7646d2SAndroid Build Coastguard Worker {
8884*5e7646d2SAndroid Build Coastguard Worker /*
8885*5e7646d2SAndroid Build Coastguard Worker * Bad URI...
8886*5e7646d2SAndroid Build Coastguard Worker */
8887*5e7646d2SAndroid Build Coastguard Worker
8888*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_NOT_FOUND,
8889*5e7646d2SAndroid Build Coastguard Worker _("The printer or class does not exist."));
8890*5e7646d2SAndroid Build Coastguard Worker return;
8891*5e7646d2SAndroid Build Coastguard Worker }
8892*5e7646d2SAndroid Build Coastguard Worker
8893*5e7646d2SAndroid Build Coastguard Worker /*
8894*5e7646d2SAndroid Build Coastguard Worker * Check policy...
8895*5e7646d2SAndroid Build Coastguard Worker */
8896*5e7646d2SAndroid Build Coastguard Worker
8897*5e7646d2SAndroid Build Coastguard Worker if ((status = cupsdCheckPolicy(printer->op_policy_ptr, con, NULL)) != HTTP_OK)
8898*5e7646d2SAndroid Build Coastguard Worker {
8899*5e7646d2SAndroid Build Coastguard Worker send_http_error(con, status, printer);
8900*5e7646d2SAndroid Build Coastguard Worker return;
8901*5e7646d2SAndroid Build Coastguard Worker }
8902*5e7646d2SAndroid Build Coastguard Worker
8903*5e7646d2SAndroid Build Coastguard Worker /*
8904*5e7646d2SAndroid Build Coastguard Worker * Reject jobs sent to the printer...
8905*5e7646d2SAndroid Build Coastguard Worker */
8906*5e7646d2SAndroid Build Coastguard Worker
8907*5e7646d2SAndroid Build Coastguard Worker printer->accepting = 0;
8908*5e7646d2SAndroid Build Coastguard Worker
8909*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippFindAttribute(con->request, "printer-state-message",
8910*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_TEXT)) == NULL)
8911*5e7646d2SAndroid Build Coastguard Worker strlcpy(printer->state_message, "Rejecting Jobs",
8912*5e7646d2SAndroid Build Coastguard Worker sizeof(printer->state_message));
8913*5e7646d2SAndroid Build Coastguard Worker else
8914*5e7646d2SAndroid Build Coastguard Worker strlcpy(printer->state_message, attr->values[0].string.text,
8915*5e7646d2SAndroid Build Coastguard Worker sizeof(printer->state_message));
8916*5e7646d2SAndroid Build Coastguard Worker
8917*5e7646d2SAndroid Build Coastguard Worker cupsdAddEvent(CUPSD_EVENT_PRINTER_STATE, printer, NULL,
8918*5e7646d2SAndroid Build Coastguard Worker "No longer accepting jobs.");
8919*5e7646d2SAndroid Build Coastguard Worker
8920*5e7646d2SAndroid Build Coastguard Worker if (dtype & CUPS_PRINTER_CLASS)
8921*5e7646d2SAndroid Build Coastguard Worker {
8922*5e7646d2SAndroid Build Coastguard Worker cupsdMarkDirty(CUPSD_DIRTY_CLASSES);
8923*5e7646d2SAndroid Build Coastguard Worker
8924*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_INFO, "Class \"%s\" rejecting jobs (\"%s\").",
8925*5e7646d2SAndroid Build Coastguard Worker printer->name, get_username(con));
8926*5e7646d2SAndroid Build Coastguard Worker }
8927*5e7646d2SAndroid Build Coastguard Worker else
8928*5e7646d2SAndroid Build Coastguard Worker {
8929*5e7646d2SAndroid Build Coastguard Worker cupsdMarkDirty(CUPSD_DIRTY_PRINTERS);
8930*5e7646d2SAndroid Build Coastguard Worker
8931*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_INFO, "Printer \"%s\" rejecting jobs (\"%s\").",
8932*5e7646d2SAndroid Build Coastguard Worker printer->name, get_username(con));
8933*5e7646d2SAndroid Build Coastguard Worker }
8934*5e7646d2SAndroid Build Coastguard Worker
8935*5e7646d2SAndroid Build Coastguard Worker /*
8936*5e7646d2SAndroid Build Coastguard Worker * Everything was ok, so return OK status...
8937*5e7646d2SAndroid Build Coastguard Worker */
8938*5e7646d2SAndroid Build Coastguard Worker
8939*5e7646d2SAndroid Build Coastguard Worker con->response->request.status.status_code = IPP_OK;
8940*5e7646d2SAndroid Build Coastguard Worker }
8941*5e7646d2SAndroid Build Coastguard Worker
8942*5e7646d2SAndroid Build Coastguard Worker
8943*5e7646d2SAndroid Build Coastguard Worker /*
8944*5e7646d2SAndroid Build Coastguard Worker * 'release_held_new_jobs()' - Release pending/new jobs on a printer or class.
8945*5e7646d2SAndroid Build Coastguard Worker */
8946*5e7646d2SAndroid Build Coastguard Worker
8947*5e7646d2SAndroid Build Coastguard Worker static void
release_held_new_jobs(cupsd_client_t * con,ipp_attribute_t * uri)8948*5e7646d2SAndroid Build Coastguard Worker release_held_new_jobs(
8949*5e7646d2SAndroid Build Coastguard Worker cupsd_client_t *con, /* I - Connection */
8950*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *uri) /* I - Printer URI */
8951*5e7646d2SAndroid Build Coastguard Worker {
8952*5e7646d2SAndroid Build Coastguard Worker http_status_t status; /* Policy status */
8953*5e7646d2SAndroid Build Coastguard Worker cups_ptype_t dtype; /* Destination type (printer/class) */
8954*5e7646d2SAndroid Build Coastguard Worker cupsd_printer_t *printer; /* Printer data */
8955*5e7646d2SAndroid Build Coastguard Worker
8956*5e7646d2SAndroid Build Coastguard Worker
8957*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG2, "release_held_new_jobs(%p[%d], %s)", con,
8958*5e7646d2SAndroid Build Coastguard Worker con->number, uri->values[0].string.text);
8959*5e7646d2SAndroid Build Coastguard Worker
8960*5e7646d2SAndroid Build Coastguard Worker /*
8961*5e7646d2SAndroid Build Coastguard Worker * Is the destination valid?
8962*5e7646d2SAndroid Build Coastguard Worker */
8963*5e7646d2SAndroid Build Coastguard Worker
8964*5e7646d2SAndroid Build Coastguard Worker if (!cupsdValidateDest(uri->values[0].string.text, &dtype, &printer))
8965*5e7646d2SAndroid Build Coastguard Worker {
8966*5e7646d2SAndroid Build Coastguard Worker /*
8967*5e7646d2SAndroid Build Coastguard Worker * Bad URI...
8968*5e7646d2SAndroid Build Coastguard Worker */
8969*5e7646d2SAndroid Build Coastguard Worker
8970*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_NOT_FOUND,
8971*5e7646d2SAndroid Build Coastguard Worker _("The printer or class does not exist."));
8972*5e7646d2SAndroid Build Coastguard Worker return;
8973*5e7646d2SAndroid Build Coastguard Worker }
8974*5e7646d2SAndroid Build Coastguard Worker
8975*5e7646d2SAndroid Build Coastguard Worker /*
8976*5e7646d2SAndroid Build Coastguard Worker * Check policy...
8977*5e7646d2SAndroid Build Coastguard Worker */
8978*5e7646d2SAndroid Build Coastguard Worker
8979*5e7646d2SAndroid Build Coastguard Worker if ((status = cupsdCheckPolicy(printer->op_policy_ptr, con, NULL)) != HTTP_OK)
8980*5e7646d2SAndroid Build Coastguard Worker {
8981*5e7646d2SAndroid Build Coastguard Worker send_http_error(con, status, printer);
8982*5e7646d2SAndroid Build Coastguard Worker return;
8983*5e7646d2SAndroid Build Coastguard Worker }
8984*5e7646d2SAndroid Build Coastguard Worker
8985*5e7646d2SAndroid Build Coastguard Worker /*
8986*5e7646d2SAndroid Build Coastguard Worker * Hold pending/new jobs sent to the printer...
8987*5e7646d2SAndroid Build Coastguard Worker */
8988*5e7646d2SAndroid Build Coastguard Worker
8989*5e7646d2SAndroid Build Coastguard Worker printer->holding_new_jobs = 0;
8990*5e7646d2SAndroid Build Coastguard Worker
8991*5e7646d2SAndroid Build Coastguard Worker cupsdSetPrinterReasons(printer, "-hold-new-jobs");
8992*5e7646d2SAndroid Build Coastguard Worker
8993*5e7646d2SAndroid Build Coastguard Worker if (dtype & CUPS_PRINTER_CLASS)
8994*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_INFO,
8995*5e7646d2SAndroid Build Coastguard Worker "Class \"%s\" now printing pending/new jobs (\"%s\").",
8996*5e7646d2SAndroid Build Coastguard Worker printer->name, get_username(con));
8997*5e7646d2SAndroid Build Coastguard Worker else
8998*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_INFO,
8999*5e7646d2SAndroid Build Coastguard Worker "Printer \"%s\" now printing pending/new jobs (\"%s\").",
9000*5e7646d2SAndroid Build Coastguard Worker printer->name, get_username(con));
9001*5e7646d2SAndroid Build Coastguard Worker
9002*5e7646d2SAndroid Build Coastguard Worker cupsdCheckJobs();
9003*5e7646d2SAndroid Build Coastguard Worker
9004*5e7646d2SAndroid Build Coastguard Worker /*
9005*5e7646d2SAndroid Build Coastguard Worker * Everything was ok, so return OK status...
9006*5e7646d2SAndroid Build Coastguard Worker */
9007*5e7646d2SAndroid Build Coastguard Worker
9008*5e7646d2SAndroid Build Coastguard Worker con->response->request.status.status_code = IPP_OK;
9009*5e7646d2SAndroid Build Coastguard Worker }
9010*5e7646d2SAndroid Build Coastguard Worker
9011*5e7646d2SAndroid Build Coastguard Worker
9012*5e7646d2SAndroid Build Coastguard Worker /*
9013*5e7646d2SAndroid Build Coastguard Worker * 'release_job()' - Release a held print job.
9014*5e7646d2SAndroid Build Coastguard Worker */
9015*5e7646d2SAndroid Build Coastguard Worker
9016*5e7646d2SAndroid Build Coastguard Worker static void
release_job(cupsd_client_t * con,ipp_attribute_t * uri)9017*5e7646d2SAndroid Build Coastguard Worker release_job(cupsd_client_t *con, /* I - Client connection */
9018*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *uri) /* I - Job or Printer URI */
9019*5e7646d2SAndroid Build Coastguard Worker {
9020*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *attr; /* Current attribute */
9021*5e7646d2SAndroid Build Coastguard Worker int jobid; /* Job ID */
9022*5e7646d2SAndroid Build Coastguard Worker char scheme[HTTP_MAX_URI], /* Method portion of URI */
9023*5e7646d2SAndroid Build Coastguard Worker username[HTTP_MAX_URI], /* Username portion of URI */
9024*5e7646d2SAndroid Build Coastguard Worker host[HTTP_MAX_URI], /* Host portion of URI */
9025*5e7646d2SAndroid Build Coastguard Worker resource[HTTP_MAX_URI]; /* Resource portion of URI */
9026*5e7646d2SAndroid Build Coastguard Worker int port; /* Port portion of URI */
9027*5e7646d2SAndroid Build Coastguard Worker cupsd_job_t *job; /* Job information */
9028*5e7646d2SAndroid Build Coastguard Worker
9029*5e7646d2SAndroid Build Coastguard Worker
9030*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG2, "release_job(%p[%d], %s)", con,
9031*5e7646d2SAndroid Build Coastguard Worker con->number, uri->values[0].string.text);
9032*5e7646d2SAndroid Build Coastguard Worker
9033*5e7646d2SAndroid Build Coastguard Worker /*
9034*5e7646d2SAndroid Build Coastguard Worker * See if we have a job URI or a printer URI...
9035*5e7646d2SAndroid Build Coastguard Worker */
9036*5e7646d2SAndroid Build Coastguard Worker
9037*5e7646d2SAndroid Build Coastguard Worker if (!strcmp(uri->name, "printer-uri"))
9038*5e7646d2SAndroid Build Coastguard Worker {
9039*5e7646d2SAndroid Build Coastguard Worker /*
9040*5e7646d2SAndroid Build Coastguard Worker * Got a printer URI; see if we also have a job-id attribute...
9041*5e7646d2SAndroid Build Coastguard Worker */
9042*5e7646d2SAndroid Build Coastguard Worker
9043*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippFindAttribute(con->request, "job-id",
9044*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_INTEGER)) == NULL)
9045*5e7646d2SAndroid Build Coastguard Worker {
9046*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_BAD_REQUEST,
9047*5e7646d2SAndroid Build Coastguard Worker _("Got a printer-uri attribute but no job-id."));
9048*5e7646d2SAndroid Build Coastguard Worker return;
9049*5e7646d2SAndroid Build Coastguard Worker }
9050*5e7646d2SAndroid Build Coastguard Worker
9051*5e7646d2SAndroid Build Coastguard Worker jobid = attr->values[0].integer;
9052*5e7646d2SAndroid Build Coastguard Worker }
9053*5e7646d2SAndroid Build Coastguard Worker else
9054*5e7646d2SAndroid Build Coastguard Worker {
9055*5e7646d2SAndroid Build Coastguard Worker /*
9056*5e7646d2SAndroid Build Coastguard Worker * Got a job URI; parse it to get the job ID...
9057*5e7646d2SAndroid Build Coastguard Worker */
9058*5e7646d2SAndroid Build Coastguard Worker
9059*5e7646d2SAndroid Build Coastguard Worker httpSeparateURI(HTTP_URI_CODING_ALL, uri->values[0].string.text, scheme,
9060*5e7646d2SAndroid Build Coastguard Worker sizeof(scheme), username, sizeof(username), host,
9061*5e7646d2SAndroid Build Coastguard Worker sizeof(host), &port, resource, sizeof(resource));
9062*5e7646d2SAndroid Build Coastguard Worker
9063*5e7646d2SAndroid Build Coastguard Worker if (strncmp(resource, "/jobs/", 6))
9064*5e7646d2SAndroid Build Coastguard Worker {
9065*5e7646d2SAndroid Build Coastguard Worker /*
9066*5e7646d2SAndroid Build Coastguard Worker * Not a valid URI!
9067*5e7646d2SAndroid Build Coastguard Worker */
9068*5e7646d2SAndroid Build Coastguard Worker
9069*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_BAD_REQUEST, _("Bad job-uri \"%s\"."),
9070*5e7646d2SAndroid Build Coastguard Worker uri->values[0].string.text);
9071*5e7646d2SAndroid Build Coastguard Worker return;
9072*5e7646d2SAndroid Build Coastguard Worker }
9073*5e7646d2SAndroid Build Coastguard Worker
9074*5e7646d2SAndroid Build Coastguard Worker jobid = atoi(resource + 6);
9075*5e7646d2SAndroid Build Coastguard Worker }
9076*5e7646d2SAndroid Build Coastguard Worker
9077*5e7646d2SAndroid Build Coastguard Worker /*
9078*5e7646d2SAndroid Build Coastguard Worker * See if the job exists...
9079*5e7646d2SAndroid Build Coastguard Worker */
9080*5e7646d2SAndroid Build Coastguard Worker
9081*5e7646d2SAndroid Build Coastguard Worker if ((job = cupsdFindJob(jobid)) == NULL)
9082*5e7646d2SAndroid Build Coastguard Worker {
9083*5e7646d2SAndroid Build Coastguard Worker /*
9084*5e7646d2SAndroid Build Coastguard Worker * Nope - return a "not found" error...
9085*5e7646d2SAndroid Build Coastguard Worker */
9086*5e7646d2SAndroid Build Coastguard Worker
9087*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_NOT_FOUND, _("Job #%d does not exist."), jobid);
9088*5e7646d2SAndroid Build Coastguard Worker return;
9089*5e7646d2SAndroid Build Coastguard Worker }
9090*5e7646d2SAndroid Build Coastguard Worker
9091*5e7646d2SAndroid Build Coastguard Worker /*
9092*5e7646d2SAndroid Build Coastguard Worker * See if job is "held"...
9093*5e7646d2SAndroid Build Coastguard Worker */
9094*5e7646d2SAndroid Build Coastguard Worker
9095*5e7646d2SAndroid Build Coastguard Worker if (job->state_value != IPP_JOB_HELD)
9096*5e7646d2SAndroid Build Coastguard Worker {
9097*5e7646d2SAndroid Build Coastguard Worker /*
9098*5e7646d2SAndroid Build Coastguard Worker * Nope - return a "not possible" error...
9099*5e7646d2SAndroid Build Coastguard Worker */
9100*5e7646d2SAndroid Build Coastguard Worker
9101*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_NOT_POSSIBLE, _("Job #%d is not held."), jobid);
9102*5e7646d2SAndroid Build Coastguard Worker return;
9103*5e7646d2SAndroid Build Coastguard Worker }
9104*5e7646d2SAndroid Build Coastguard Worker
9105*5e7646d2SAndroid Build Coastguard Worker /*
9106*5e7646d2SAndroid Build Coastguard Worker * See if the job is owned by the requesting user...
9107*5e7646d2SAndroid Build Coastguard Worker */
9108*5e7646d2SAndroid Build Coastguard Worker
9109*5e7646d2SAndroid Build Coastguard Worker if (!validate_user(job, con, job->username, username, sizeof(username)))
9110*5e7646d2SAndroid Build Coastguard Worker {
9111*5e7646d2SAndroid Build Coastguard Worker send_http_error(con, con->username[0] ? HTTP_FORBIDDEN : HTTP_UNAUTHORIZED,
9112*5e7646d2SAndroid Build Coastguard Worker cupsdFindDest(job->dest));
9113*5e7646d2SAndroid Build Coastguard Worker return;
9114*5e7646d2SAndroid Build Coastguard Worker }
9115*5e7646d2SAndroid Build Coastguard Worker
9116*5e7646d2SAndroid Build Coastguard Worker /*
9117*5e7646d2SAndroid Build Coastguard Worker * Reset the job-hold-until value to "no-hold"...
9118*5e7646d2SAndroid Build Coastguard Worker */
9119*5e7646d2SAndroid Build Coastguard Worker
9120*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippFindAttribute(job->attrs, "job-hold-until",
9121*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_KEYWORD)) == NULL)
9122*5e7646d2SAndroid Build Coastguard Worker attr = ippFindAttribute(job->attrs, "job-hold-until", IPP_TAG_NAME);
9123*5e7646d2SAndroid Build Coastguard Worker
9124*5e7646d2SAndroid Build Coastguard Worker if (attr)
9125*5e7646d2SAndroid Build Coastguard Worker {
9126*5e7646d2SAndroid Build Coastguard Worker ippSetValueTag(job->attrs, &attr, IPP_TAG_KEYWORD);
9127*5e7646d2SAndroid Build Coastguard Worker ippSetString(job->attrs, &attr, 0, "no-hold");
9128*5e7646d2SAndroid Build Coastguard Worker
9129*5e7646d2SAndroid Build Coastguard Worker cupsdAddEvent(CUPSD_EVENT_JOB_CONFIG_CHANGED, cupsdFindDest(job->dest), job,
9130*5e7646d2SAndroid Build Coastguard Worker "Job job-hold-until value changed by user.");
9131*5e7646d2SAndroid Build Coastguard Worker ippSetString(job->attrs, &job->reasons, 0, "none");
9132*5e7646d2SAndroid Build Coastguard Worker }
9133*5e7646d2SAndroid Build Coastguard Worker
9134*5e7646d2SAndroid Build Coastguard Worker /*
9135*5e7646d2SAndroid Build Coastguard Worker * Release the job and return...
9136*5e7646d2SAndroid Build Coastguard Worker */
9137*5e7646d2SAndroid Build Coastguard Worker
9138*5e7646d2SAndroid Build Coastguard Worker cupsdReleaseJob(job);
9139*5e7646d2SAndroid Build Coastguard Worker
9140*5e7646d2SAndroid Build Coastguard Worker cupsdAddEvent(CUPSD_EVENT_JOB_STATE, cupsdFindDest(job->dest), job,
9141*5e7646d2SAndroid Build Coastguard Worker "Job released by user.");
9142*5e7646d2SAndroid Build Coastguard Worker
9143*5e7646d2SAndroid Build Coastguard Worker cupsdLogJob(job, CUPSD_LOG_INFO, "Released by \"%s\".", username);
9144*5e7646d2SAndroid Build Coastguard Worker
9145*5e7646d2SAndroid Build Coastguard Worker con->response->request.status.status_code = IPP_OK;
9146*5e7646d2SAndroid Build Coastguard Worker
9147*5e7646d2SAndroid Build Coastguard Worker cupsdCheckJobs();
9148*5e7646d2SAndroid Build Coastguard Worker }
9149*5e7646d2SAndroid Build Coastguard Worker
9150*5e7646d2SAndroid Build Coastguard Worker
9151*5e7646d2SAndroid Build Coastguard Worker /*
9152*5e7646d2SAndroid Build Coastguard Worker * 'renew_subscription()' - Renew an existing subscription...
9153*5e7646d2SAndroid Build Coastguard Worker */
9154*5e7646d2SAndroid Build Coastguard Worker
9155*5e7646d2SAndroid Build Coastguard Worker static void
renew_subscription(cupsd_client_t * con,int sub_id)9156*5e7646d2SAndroid Build Coastguard Worker renew_subscription(
9157*5e7646d2SAndroid Build Coastguard Worker cupsd_client_t *con, /* I - Client connection */
9158*5e7646d2SAndroid Build Coastguard Worker int sub_id) /* I - Subscription ID */
9159*5e7646d2SAndroid Build Coastguard Worker {
9160*5e7646d2SAndroid Build Coastguard Worker http_status_t status; /* Policy status */
9161*5e7646d2SAndroid Build Coastguard Worker cupsd_subscription_t *sub; /* Subscription */
9162*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *lease; /* notify-lease-duration */
9163*5e7646d2SAndroid Build Coastguard Worker
9164*5e7646d2SAndroid Build Coastguard Worker
9165*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG2,
9166*5e7646d2SAndroid Build Coastguard Worker "renew_subscription(con=%p[%d], sub_id=%d)",
9167*5e7646d2SAndroid Build Coastguard Worker con, con->number, sub_id);
9168*5e7646d2SAndroid Build Coastguard Worker
9169*5e7646d2SAndroid Build Coastguard Worker /*
9170*5e7646d2SAndroid Build Coastguard Worker * Is the subscription ID valid?
9171*5e7646d2SAndroid Build Coastguard Worker */
9172*5e7646d2SAndroid Build Coastguard Worker
9173*5e7646d2SAndroid Build Coastguard Worker if ((sub = cupsdFindSubscription(sub_id)) == NULL)
9174*5e7646d2SAndroid Build Coastguard Worker {
9175*5e7646d2SAndroid Build Coastguard Worker /*
9176*5e7646d2SAndroid Build Coastguard Worker * Bad subscription ID...
9177*5e7646d2SAndroid Build Coastguard Worker */
9178*5e7646d2SAndroid Build Coastguard Worker
9179*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_NOT_FOUND, _("Subscription #%d does not exist."),
9180*5e7646d2SAndroid Build Coastguard Worker sub_id);
9181*5e7646d2SAndroid Build Coastguard Worker return;
9182*5e7646d2SAndroid Build Coastguard Worker }
9183*5e7646d2SAndroid Build Coastguard Worker
9184*5e7646d2SAndroid Build Coastguard Worker if (sub->job)
9185*5e7646d2SAndroid Build Coastguard Worker {
9186*5e7646d2SAndroid Build Coastguard Worker /*
9187*5e7646d2SAndroid Build Coastguard Worker * Job subscriptions cannot be renewed...
9188*5e7646d2SAndroid Build Coastguard Worker */
9189*5e7646d2SAndroid Build Coastguard Worker
9190*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_NOT_POSSIBLE,
9191*5e7646d2SAndroid Build Coastguard Worker _("Job subscriptions cannot be renewed."));
9192*5e7646d2SAndroid Build Coastguard Worker return;
9193*5e7646d2SAndroid Build Coastguard Worker }
9194*5e7646d2SAndroid Build Coastguard Worker
9195*5e7646d2SAndroid Build Coastguard Worker /*
9196*5e7646d2SAndroid Build Coastguard Worker * Check policy...
9197*5e7646d2SAndroid Build Coastguard Worker */
9198*5e7646d2SAndroid Build Coastguard Worker
9199*5e7646d2SAndroid Build Coastguard Worker if ((status = cupsdCheckPolicy(sub->dest ? sub->dest->op_policy_ptr :
9200*5e7646d2SAndroid Build Coastguard Worker DefaultPolicyPtr,
9201*5e7646d2SAndroid Build Coastguard Worker con, sub->owner)) != HTTP_OK)
9202*5e7646d2SAndroid Build Coastguard Worker {
9203*5e7646d2SAndroid Build Coastguard Worker send_http_error(con, status, sub->dest);
9204*5e7646d2SAndroid Build Coastguard Worker return;
9205*5e7646d2SAndroid Build Coastguard Worker }
9206*5e7646d2SAndroid Build Coastguard Worker
9207*5e7646d2SAndroid Build Coastguard Worker /*
9208*5e7646d2SAndroid Build Coastguard Worker * Renew the subscription...
9209*5e7646d2SAndroid Build Coastguard Worker */
9210*5e7646d2SAndroid Build Coastguard Worker
9211*5e7646d2SAndroid Build Coastguard Worker lease = ippFindAttribute(con->request, "notify-lease-duration",
9212*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_INTEGER);
9213*5e7646d2SAndroid Build Coastguard Worker
9214*5e7646d2SAndroid Build Coastguard Worker sub->lease = lease ? lease->values[0].integer : DefaultLeaseDuration;
9215*5e7646d2SAndroid Build Coastguard Worker
9216*5e7646d2SAndroid Build Coastguard Worker if (MaxLeaseDuration && (sub->lease == 0 || sub->lease > MaxLeaseDuration))
9217*5e7646d2SAndroid Build Coastguard Worker {
9218*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_INFO,
9219*5e7646d2SAndroid Build Coastguard Worker "renew_subscription: Limiting notify-lease-duration to "
9220*5e7646d2SAndroid Build Coastguard Worker "%d seconds.",
9221*5e7646d2SAndroid Build Coastguard Worker MaxLeaseDuration);
9222*5e7646d2SAndroid Build Coastguard Worker sub->lease = MaxLeaseDuration;
9223*5e7646d2SAndroid Build Coastguard Worker }
9224*5e7646d2SAndroid Build Coastguard Worker
9225*5e7646d2SAndroid Build Coastguard Worker sub->expire = sub->lease ? time(NULL) + sub->lease : 0;
9226*5e7646d2SAndroid Build Coastguard Worker
9227*5e7646d2SAndroid Build Coastguard Worker cupsdMarkDirty(CUPSD_DIRTY_SUBSCRIPTIONS);
9228*5e7646d2SAndroid Build Coastguard Worker
9229*5e7646d2SAndroid Build Coastguard Worker con->response->request.status.status_code = IPP_OK;
9230*5e7646d2SAndroid Build Coastguard Worker
9231*5e7646d2SAndroid Build Coastguard Worker ippAddInteger(con->response, IPP_TAG_SUBSCRIPTION, IPP_TAG_INTEGER,
9232*5e7646d2SAndroid Build Coastguard Worker "notify-lease-duration", sub->lease);
9233*5e7646d2SAndroid Build Coastguard Worker }
9234*5e7646d2SAndroid Build Coastguard Worker
9235*5e7646d2SAndroid Build Coastguard Worker
9236*5e7646d2SAndroid Build Coastguard Worker /*
9237*5e7646d2SAndroid Build Coastguard Worker * 'restart_job()' - Restart an old print job.
9238*5e7646d2SAndroid Build Coastguard Worker */
9239*5e7646d2SAndroid Build Coastguard Worker
9240*5e7646d2SAndroid Build Coastguard Worker static void
restart_job(cupsd_client_t * con,ipp_attribute_t * uri)9241*5e7646d2SAndroid Build Coastguard Worker restart_job(cupsd_client_t *con, /* I - Client connection */
9242*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *uri) /* I - Job or Printer URI */
9243*5e7646d2SAndroid Build Coastguard Worker {
9244*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *attr; /* Current attribute */
9245*5e7646d2SAndroid Build Coastguard Worker int jobid; /* Job ID */
9246*5e7646d2SAndroid Build Coastguard Worker cupsd_job_t *job; /* Job information */
9247*5e7646d2SAndroid Build Coastguard Worker char scheme[HTTP_MAX_URI], /* Method portion of URI */
9248*5e7646d2SAndroid Build Coastguard Worker username[HTTP_MAX_URI], /* Username portion of URI */
9249*5e7646d2SAndroid Build Coastguard Worker host[HTTP_MAX_URI], /* Host portion of URI */
9250*5e7646d2SAndroid Build Coastguard Worker resource[HTTP_MAX_URI]; /* Resource portion of URI */
9251*5e7646d2SAndroid Build Coastguard Worker int port; /* Port portion of URI */
9252*5e7646d2SAndroid Build Coastguard Worker
9253*5e7646d2SAndroid Build Coastguard Worker
9254*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG2, "restart_job(%p[%d], %s)", con,
9255*5e7646d2SAndroid Build Coastguard Worker con->number, uri->values[0].string.text);
9256*5e7646d2SAndroid Build Coastguard Worker
9257*5e7646d2SAndroid Build Coastguard Worker /*
9258*5e7646d2SAndroid Build Coastguard Worker * See if we have a job URI or a printer URI...
9259*5e7646d2SAndroid Build Coastguard Worker */
9260*5e7646d2SAndroid Build Coastguard Worker
9261*5e7646d2SAndroid Build Coastguard Worker if (!strcmp(uri->name, "printer-uri"))
9262*5e7646d2SAndroid Build Coastguard Worker {
9263*5e7646d2SAndroid Build Coastguard Worker /*
9264*5e7646d2SAndroid Build Coastguard Worker * Got a printer URI; see if we also have a job-id attribute...
9265*5e7646d2SAndroid Build Coastguard Worker */
9266*5e7646d2SAndroid Build Coastguard Worker
9267*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippFindAttribute(con->request, "job-id",
9268*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_INTEGER)) == NULL)
9269*5e7646d2SAndroid Build Coastguard Worker {
9270*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_BAD_REQUEST,
9271*5e7646d2SAndroid Build Coastguard Worker _("Got a printer-uri attribute but no job-id."));
9272*5e7646d2SAndroid Build Coastguard Worker return;
9273*5e7646d2SAndroid Build Coastguard Worker }
9274*5e7646d2SAndroid Build Coastguard Worker
9275*5e7646d2SAndroid Build Coastguard Worker jobid = attr->values[0].integer;
9276*5e7646d2SAndroid Build Coastguard Worker }
9277*5e7646d2SAndroid Build Coastguard Worker else
9278*5e7646d2SAndroid Build Coastguard Worker {
9279*5e7646d2SAndroid Build Coastguard Worker /*
9280*5e7646d2SAndroid Build Coastguard Worker * Got a job URI; parse it to get the job ID...
9281*5e7646d2SAndroid Build Coastguard Worker */
9282*5e7646d2SAndroid Build Coastguard Worker
9283*5e7646d2SAndroid Build Coastguard Worker httpSeparateURI(HTTP_URI_CODING_ALL, uri->values[0].string.text, scheme,
9284*5e7646d2SAndroid Build Coastguard Worker sizeof(scheme), username, sizeof(username), host,
9285*5e7646d2SAndroid Build Coastguard Worker sizeof(host), &port, resource, sizeof(resource));
9286*5e7646d2SAndroid Build Coastguard Worker
9287*5e7646d2SAndroid Build Coastguard Worker if (strncmp(resource, "/jobs/", 6))
9288*5e7646d2SAndroid Build Coastguard Worker {
9289*5e7646d2SAndroid Build Coastguard Worker /*
9290*5e7646d2SAndroid Build Coastguard Worker * Not a valid URI!
9291*5e7646d2SAndroid Build Coastguard Worker */
9292*5e7646d2SAndroid Build Coastguard Worker
9293*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_BAD_REQUEST, _("Bad job-uri \"%s\"."),
9294*5e7646d2SAndroid Build Coastguard Worker uri->values[0].string.text);
9295*5e7646d2SAndroid Build Coastguard Worker return;
9296*5e7646d2SAndroid Build Coastguard Worker }
9297*5e7646d2SAndroid Build Coastguard Worker
9298*5e7646d2SAndroid Build Coastguard Worker jobid = atoi(resource + 6);
9299*5e7646d2SAndroid Build Coastguard Worker }
9300*5e7646d2SAndroid Build Coastguard Worker
9301*5e7646d2SAndroid Build Coastguard Worker /*
9302*5e7646d2SAndroid Build Coastguard Worker * See if the job exists...
9303*5e7646d2SAndroid Build Coastguard Worker */
9304*5e7646d2SAndroid Build Coastguard Worker
9305*5e7646d2SAndroid Build Coastguard Worker if ((job = cupsdFindJob(jobid)) == NULL)
9306*5e7646d2SAndroid Build Coastguard Worker {
9307*5e7646d2SAndroid Build Coastguard Worker /*
9308*5e7646d2SAndroid Build Coastguard Worker * Nope - return a "not found" error...
9309*5e7646d2SAndroid Build Coastguard Worker */
9310*5e7646d2SAndroid Build Coastguard Worker
9311*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_NOT_FOUND, _("Job #%d does not exist."), jobid);
9312*5e7646d2SAndroid Build Coastguard Worker return;
9313*5e7646d2SAndroid Build Coastguard Worker }
9314*5e7646d2SAndroid Build Coastguard Worker
9315*5e7646d2SAndroid Build Coastguard Worker /*
9316*5e7646d2SAndroid Build Coastguard Worker * See if job is in any of the "completed" states...
9317*5e7646d2SAndroid Build Coastguard Worker */
9318*5e7646d2SAndroid Build Coastguard Worker
9319*5e7646d2SAndroid Build Coastguard Worker if (job->state_value <= IPP_JOB_PROCESSING)
9320*5e7646d2SAndroid Build Coastguard Worker {
9321*5e7646d2SAndroid Build Coastguard Worker /*
9322*5e7646d2SAndroid Build Coastguard Worker * Nope - return a "not possible" error...
9323*5e7646d2SAndroid Build Coastguard Worker */
9324*5e7646d2SAndroid Build Coastguard Worker
9325*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_NOT_POSSIBLE, _("Job #%d is not complete."),
9326*5e7646d2SAndroid Build Coastguard Worker jobid);
9327*5e7646d2SAndroid Build Coastguard Worker return;
9328*5e7646d2SAndroid Build Coastguard Worker }
9329*5e7646d2SAndroid Build Coastguard Worker
9330*5e7646d2SAndroid Build Coastguard Worker /*
9331*5e7646d2SAndroid Build Coastguard Worker * See if we have retained the job files...
9332*5e7646d2SAndroid Build Coastguard Worker */
9333*5e7646d2SAndroid Build Coastguard Worker
9334*5e7646d2SAndroid Build Coastguard Worker cupsdLoadJob(job);
9335*5e7646d2SAndroid Build Coastguard Worker
9336*5e7646d2SAndroid Build Coastguard Worker if (!job->attrs || job->num_files == 0)
9337*5e7646d2SAndroid Build Coastguard Worker {
9338*5e7646d2SAndroid Build Coastguard Worker /*
9339*5e7646d2SAndroid Build Coastguard Worker * Nope - return a "not possible" error...
9340*5e7646d2SAndroid Build Coastguard Worker */
9341*5e7646d2SAndroid Build Coastguard Worker
9342*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_NOT_POSSIBLE,
9343*5e7646d2SAndroid Build Coastguard Worker _("Job #%d cannot be restarted - no files."), jobid);
9344*5e7646d2SAndroid Build Coastguard Worker return;
9345*5e7646d2SAndroid Build Coastguard Worker }
9346*5e7646d2SAndroid Build Coastguard Worker
9347*5e7646d2SAndroid Build Coastguard Worker /*
9348*5e7646d2SAndroid Build Coastguard Worker * See if the job is owned by the requesting user...
9349*5e7646d2SAndroid Build Coastguard Worker */
9350*5e7646d2SAndroid Build Coastguard Worker
9351*5e7646d2SAndroid Build Coastguard Worker if (!validate_user(job, con, job->username, username, sizeof(username)))
9352*5e7646d2SAndroid Build Coastguard Worker {
9353*5e7646d2SAndroid Build Coastguard Worker send_http_error(con, con->username[0] ? HTTP_FORBIDDEN : HTTP_UNAUTHORIZED,
9354*5e7646d2SAndroid Build Coastguard Worker cupsdFindDest(job->dest));
9355*5e7646d2SAndroid Build Coastguard Worker return;
9356*5e7646d2SAndroid Build Coastguard Worker }
9357*5e7646d2SAndroid Build Coastguard Worker
9358*5e7646d2SAndroid Build Coastguard Worker /*
9359*5e7646d2SAndroid Build Coastguard Worker * See if the job-hold-until attribute is specified...
9360*5e7646d2SAndroid Build Coastguard Worker */
9361*5e7646d2SAndroid Build Coastguard Worker
9362*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippFindAttribute(con->request, "job-hold-until",
9363*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_KEYWORD)) == NULL)
9364*5e7646d2SAndroid Build Coastguard Worker attr = ippFindAttribute(con->request, "job-hold-until", IPP_TAG_NAME);
9365*5e7646d2SAndroid Build Coastguard Worker
9366*5e7646d2SAndroid Build Coastguard Worker if (attr && strcmp(attr->values[0].string.text, "no-hold"))
9367*5e7646d2SAndroid Build Coastguard Worker {
9368*5e7646d2SAndroid Build Coastguard Worker /*
9369*5e7646d2SAndroid Build Coastguard Worker * Return the job to a held state...
9370*5e7646d2SAndroid Build Coastguard Worker */
9371*5e7646d2SAndroid Build Coastguard Worker
9372*5e7646d2SAndroid Build Coastguard Worker cupsdLogJob(job, CUPSD_LOG_DEBUG,
9373*5e7646d2SAndroid Build Coastguard Worker "Restarted by \"%s\" with job-hold-until=%s.",
9374*5e7646d2SAndroid Build Coastguard Worker username, attr->values[0].string.text);
9375*5e7646d2SAndroid Build Coastguard Worker cupsdSetJobHoldUntil(job, attr->values[0].string.text, 1);
9376*5e7646d2SAndroid Build Coastguard Worker cupsdSetJobState(job, IPP_JOB_HELD, CUPSD_JOB_DEFAULT,
9377*5e7646d2SAndroid Build Coastguard Worker "Job restarted by user with job-hold-until=%s",
9378*5e7646d2SAndroid Build Coastguard Worker attr->values[0].string.text);
9379*5e7646d2SAndroid Build Coastguard Worker }
9380*5e7646d2SAndroid Build Coastguard Worker else
9381*5e7646d2SAndroid Build Coastguard Worker {
9382*5e7646d2SAndroid Build Coastguard Worker /*
9383*5e7646d2SAndroid Build Coastguard Worker * Restart the job...
9384*5e7646d2SAndroid Build Coastguard Worker */
9385*5e7646d2SAndroid Build Coastguard Worker
9386*5e7646d2SAndroid Build Coastguard Worker cupsdRestartJob(job);
9387*5e7646d2SAndroid Build Coastguard Worker cupsdCheckJobs();
9388*5e7646d2SAndroid Build Coastguard Worker }
9389*5e7646d2SAndroid Build Coastguard Worker
9390*5e7646d2SAndroid Build Coastguard Worker cupsdLogJob(job, CUPSD_LOG_INFO, "Restarted by \"%s\".", username);
9391*5e7646d2SAndroid Build Coastguard Worker
9392*5e7646d2SAndroid Build Coastguard Worker con->response->request.status.status_code = IPP_OK;
9393*5e7646d2SAndroid Build Coastguard Worker }
9394*5e7646d2SAndroid Build Coastguard Worker
9395*5e7646d2SAndroid Build Coastguard Worker
9396*5e7646d2SAndroid Build Coastguard Worker /*
9397*5e7646d2SAndroid Build Coastguard Worker * 'save_auth_info()' - Save authentication information for a job.
9398*5e7646d2SAndroid Build Coastguard Worker */
9399*5e7646d2SAndroid Build Coastguard Worker
9400*5e7646d2SAndroid Build Coastguard Worker static void
save_auth_info(cupsd_client_t * con,cupsd_job_t * job,ipp_attribute_t * auth_info)9401*5e7646d2SAndroid Build Coastguard Worker save_auth_info(
9402*5e7646d2SAndroid Build Coastguard Worker cupsd_client_t *con, /* I - Client connection */
9403*5e7646d2SAndroid Build Coastguard Worker cupsd_job_t *job, /* I - Job */
9404*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *auth_info) /* I - auth-info attribute, if any */
9405*5e7646d2SAndroid Build Coastguard Worker {
9406*5e7646d2SAndroid Build Coastguard Worker int i; /* Looping var */
9407*5e7646d2SAndroid Build Coastguard Worker char filename[1024]; /* Job authentication filename */
9408*5e7646d2SAndroid Build Coastguard Worker cups_file_t *fp; /* Job authentication file */
9409*5e7646d2SAndroid Build Coastguard Worker char line[65536]; /* Line for file */
9410*5e7646d2SAndroid Build Coastguard Worker cupsd_printer_t *dest; /* Destination printer/class */
9411*5e7646d2SAndroid Build Coastguard Worker
9412*5e7646d2SAndroid Build Coastguard Worker
9413*5e7646d2SAndroid Build Coastguard Worker /*
9414*5e7646d2SAndroid Build Coastguard Worker * This function saves the in-memory authentication information for
9415*5e7646d2SAndroid Build Coastguard Worker * a job so that it can be used to authenticate with a remote host.
9416*5e7646d2SAndroid Build Coastguard Worker * The information is stored in a file that is readable only by the
9417*5e7646d2SAndroid Build Coastguard Worker * root user. The fields are Base-64 encoded, each on a separate line,
9418*5e7646d2SAndroid Build Coastguard Worker * followed by random number (up to 1024) of newlines to limit the
9419*5e7646d2SAndroid Build Coastguard Worker * amount of information that is exposed.
9420*5e7646d2SAndroid Build Coastguard Worker *
9421*5e7646d2SAndroid Build Coastguard Worker * Because of the potential for exposing of authentication information,
9422*5e7646d2SAndroid Build Coastguard Worker * this functionality is only enabled when running cupsd as root.
9423*5e7646d2SAndroid Build Coastguard Worker *
9424*5e7646d2SAndroid Build Coastguard Worker * This caching only works for the Basic and BasicDigest authentication
9425*5e7646d2SAndroid Build Coastguard Worker * types. Digest authentication cannot be cached this way, and in
9426*5e7646d2SAndroid Build Coastguard Worker * the future Kerberos authentication may make all of this obsolete.
9427*5e7646d2SAndroid Build Coastguard Worker *
9428*5e7646d2SAndroid Build Coastguard Worker * Authentication information is saved whenever an authenticated
9429*5e7646d2SAndroid Build Coastguard Worker * Print-Job, Create-Job, or CUPS-Authenticate-Job operation is
9430*5e7646d2SAndroid Build Coastguard Worker * performed.
9431*5e7646d2SAndroid Build Coastguard Worker *
9432*5e7646d2SAndroid Build Coastguard Worker * This information is deleted after a job is completed or canceled,
9433*5e7646d2SAndroid Build Coastguard Worker * so reprints may require subsequent re-authentication.
9434*5e7646d2SAndroid Build Coastguard Worker */
9435*5e7646d2SAndroid Build Coastguard Worker
9436*5e7646d2SAndroid Build Coastguard Worker if (RunUser)
9437*5e7646d2SAndroid Build Coastguard Worker return;
9438*5e7646d2SAndroid Build Coastguard Worker
9439*5e7646d2SAndroid Build Coastguard Worker if ((dest = cupsdFindDest(job->dest)) == NULL)
9440*5e7646d2SAndroid Build Coastguard Worker return;
9441*5e7646d2SAndroid Build Coastguard Worker
9442*5e7646d2SAndroid Build Coastguard Worker /*
9443*5e7646d2SAndroid Build Coastguard Worker * Create the authentication file and change permissions...
9444*5e7646d2SAndroid Build Coastguard Worker */
9445*5e7646d2SAndroid Build Coastguard Worker
9446*5e7646d2SAndroid Build Coastguard Worker snprintf(filename, sizeof(filename), "%s/a%05d", RequestRoot, job->id);
9447*5e7646d2SAndroid Build Coastguard Worker if ((fp = cupsFileOpen(filename, "w")) == NULL)
9448*5e7646d2SAndroid Build Coastguard Worker {
9449*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_ERROR,
9450*5e7646d2SAndroid Build Coastguard Worker "Unable to save authentication info to \"%s\" - %s",
9451*5e7646d2SAndroid Build Coastguard Worker filename, strerror(errno));
9452*5e7646d2SAndroid Build Coastguard Worker return;
9453*5e7646d2SAndroid Build Coastguard Worker }
9454*5e7646d2SAndroid Build Coastguard Worker
9455*5e7646d2SAndroid Build Coastguard Worker fchown(cupsFileNumber(fp), 0, 0);
9456*5e7646d2SAndroid Build Coastguard Worker fchmod(cupsFileNumber(fp), 0400);
9457*5e7646d2SAndroid Build Coastguard Worker
9458*5e7646d2SAndroid Build Coastguard Worker cupsFilePuts(fp, "CUPSD-AUTH-V3\n");
9459*5e7646d2SAndroid Build Coastguard Worker
9460*5e7646d2SAndroid Build Coastguard Worker for (i = 0;
9461*5e7646d2SAndroid Build Coastguard Worker i < (int)(sizeof(job->auth_env) / sizeof(job->auth_env[0]));
9462*5e7646d2SAndroid Build Coastguard Worker i ++)
9463*5e7646d2SAndroid Build Coastguard Worker cupsdClearString(job->auth_env + i);
9464*5e7646d2SAndroid Build Coastguard Worker
9465*5e7646d2SAndroid Build Coastguard Worker if (auth_info && auth_info->num_values == dest->num_auth_info_required)
9466*5e7646d2SAndroid Build Coastguard Worker {
9467*5e7646d2SAndroid Build Coastguard Worker /*
9468*5e7646d2SAndroid Build Coastguard Worker * Write 1 to 3 auth values...
9469*5e7646d2SAndroid Build Coastguard Worker */
9470*5e7646d2SAndroid Build Coastguard Worker
9471*5e7646d2SAndroid Build Coastguard Worker for (i = 0;
9472*5e7646d2SAndroid Build Coastguard Worker i < auth_info->num_values &&
9473*5e7646d2SAndroid Build Coastguard Worker i < (int)(sizeof(job->auth_env) / sizeof(job->auth_env[0]));
9474*5e7646d2SAndroid Build Coastguard Worker i ++)
9475*5e7646d2SAndroid Build Coastguard Worker {
9476*5e7646d2SAndroid Build Coastguard Worker if (strcmp(dest->auth_info_required[i], "negotiate"))
9477*5e7646d2SAndroid Build Coastguard Worker {
9478*5e7646d2SAndroid Build Coastguard Worker httpEncode64_2(line, sizeof(line), auth_info->values[i].string.text, (int)strlen(auth_info->values[i].string.text));
9479*5e7646d2SAndroid Build Coastguard Worker cupsFilePutConf(fp, dest->auth_info_required[i], line);
9480*5e7646d2SAndroid Build Coastguard Worker }
9481*5e7646d2SAndroid Build Coastguard Worker else
9482*5e7646d2SAndroid Build Coastguard Worker cupsFilePutConf(fp, dest->auth_info_required[i],
9483*5e7646d2SAndroid Build Coastguard Worker auth_info->values[i].string.text);
9484*5e7646d2SAndroid Build Coastguard Worker
9485*5e7646d2SAndroid Build Coastguard Worker if (!strcmp(dest->auth_info_required[i], "username"))
9486*5e7646d2SAndroid Build Coastguard Worker cupsdSetStringf(job->auth_env + i, "AUTH_USERNAME=%s",
9487*5e7646d2SAndroid Build Coastguard Worker auth_info->values[i].string.text);
9488*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(dest->auth_info_required[i], "domain"))
9489*5e7646d2SAndroid Build Coastguard Worker cupsdSetStringf(job->auth_env + i, "AUTH_DOMAIN=%s",
9490*5e7646d2SAndroid Build Coastguard Worker auth_info->values[i].string.text);
9491*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(dest->auth_info_required[i], "password"))
9492*5e7646d2SAndroid Build Coastguard Worker cupsdSetStringf(job->auth_env + i, "AUTH_PASSWORD=%s",
9493*5e7646d2SAndroid Build Coastguard Worker auth_info->values[i].string.text);
9494*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(dest->auth_info_required[i], "negotiate"))
9495*5e7646d2SAndroid Build Coastguard Worker cupsdSetStringf(job->auth_env + i, "AUTH_NEGOTIATE=%s",
9496*5e7646d2SAndroid Build Coastguard Worker auth_info->values[i].string.text);
9497*5e7646d2SAndroid Build Coastguard Worker else
9498*5e7646d2SAndroid Build Coastguard Worker i --;
9499*5e7646d2SAndroid Build Coastguard Worker }
9500*5e7646d2SAndroid Build Coastguard Worker }
9501*5e7646d2SAndroid Build Coastguard Worker else if (auth_info && auth_info->num_values == 2 &&
9502*5e7646d2SAndroid Build Coastguard Worker dest->num_auth_info_required == 1 &&
9503*5e7646d2SAndroid Build Coastguard Worker !strcmp(dest->auth_info_required[0], "negotiate"))
9504*5e7646d2SAndroid Build Coastguard Worker {
9505*5e7646d2SAndroid Build Coastguard Worker /*
9506*5e7646d2SAndroid Build Coastguard Worker * Allow fallback to username+password for Kerberized queues...
9507*5e7646d2SAndroid Build Coastguard Worker */
9508*5e7646d2SAndroid Build Coastguard Worker
9509*5e7646d2SAndroid Build Coastguard Worker httpEncode64_2(line, sizeof(line), auth_info->values[0].string.text, (int)strlen(auth_info->values[0].string.text));
9510*5e7646d2SAndroid Build Coastguard Worker cupsFilePutConf(fp, "username", line);
9511*5e7646d2SAndroid Build Coastguard Worker
9512*5e7646d2SAndroid Build Coastguard Worker cupsdSetStringf(job->auth_env + 0, "AUTH_USERNAME=%s",
9513*5e7646d2SAndroid Build Coastguard Worker auth_info->values[0].string.text);
9514*5e7646d2SAndroid Build Coastguard Worker
9515*5e7646d2SAndroid Build Coastguard Worker httpEncode64_2(line, sizeof(line), auth_info->values[1].string.text, (int)strlen(auth_info->values[1].string.text));
9516*5e7646d2SAndroid Build Coastguard Worker cupsFilePutConf(fp, "password", line);
9517*5e7646d2SAndroid Build Coastguard Worker
9518*5e7646d2SAndroid Build Coastguard Worker cupsdSetStringf(job->auth_env + 1, "AUTH_PASSWORD=%s",
9519*5e7646d2SAndroid Build Coastguard Worker auth_info->values[1].string.text);
9520*5e7646d2SAndroid Build Coastguard Worker }
9521*5e7646d2SAndroid Build Coastguard Worker else if (con->username[0])
9522*5e7646d2SAndroid Build Coastguard Worker {
9523*5e7646d2SAndroid Build Coastguard Worker /*
9524*5e7646d2SAndroid Build Coastguard Worker * Write the authenticated username...
9525*5e7646d2SAndroid Build Coastguard Worker */
9526*5e7646d2SAndroid Build Coastguard Worker
9527*5e7646d2SAndroid Build Coastguard Worker httpEncode64_2(line, sizeof(line), con->username, (int)strlen(con->username));
9528*5e7646d2SAndroid Build Coastguard Worker cupsFilePutConf(fp, "username", line);
9529*5e7646d2SAndroid Build Coastguard Worker
9530*5e7646d2SAndroid Build Coastguard Worker cupsdSetStringf(job->auth_env + 0, "AUTH_USERNAME=%s", con->username);
9531*5e7646d2SAndroid Build Coastguard Worker
9532*5e7646d2SAndroid Build Coastguard Worker /*
9533*5e7646d2SAndroid Build Coastguard Worker * Write the authenticated password...
9534*5e7646d2SAndroid Build Coastguard Worker */
9535*5e7646d2SAndroid Build Coastguard Worker
9536*5e7646d2SAndroid Build Coastguard Worker httpEncode64_2(line, sizeof(line), con->password, (int)strlen(con->password));
9537*5e7646d2SAndroid Build Coastguard Worker cupsFilePutConf(fp, "password", line);
9538*5e7646d2SAndroid Build Coastguard Worker
9539*5e7646d2SAndroid Build Coastguard Worker cupsdSetStringf(job->auth_env + 1, "AUTH_PASSWORD=%s", con->password);
9540*5e7646d2SAndroid Build Coastguard Worker }
9541*5e7646d2SAndroid Build Coastguard Worker
9542*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_GSSAPI
9543*5e7646d2SAndroid Build Coastguard Worker if (con->gss_uid > 0)
9544*5e7646d2SAndroid Build Coastguard Worker {
9545*5e7646d2SAndroid Build Coastguard Worker cupsFilePrintf(fp, "uid %d\n", (int)con->gss_uid);
9546*5e7646d2SAndroid Build Coastguard Worker cupsdSetStringf(&job->auth_uid, "AUTH_UID=%d", (int)con->gss_uid);
9547*5e7646d2SAndroid Build Coastguard Worker }
9548*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_GSSAPI */
9549*5e7646d2SAndroid Build Coastguard Worker
9550*5e7646d2SAndroid Build Coastguard Worker /*
9551*5e7646d2SAndroid Build Coastguard Worker * Write a random number of newlines to the end of the file...
9552*5e7646d2SAndroid Build Coastguard Worker */
9553*5e7646d2SAndroid Build Coastguard Worker
9554*5e7646d2SAndroid Build Coastguard Worker for (i = (CUPS_RAND() % 1024); i >= 0; i --)
9555*5e7646d2SAndroid Build Coastguard Worker cupsFilePutChar(fp, '\n');
9556*5e7646d2SAndroid Build Coastguard Worker
9557*5e7646d2SAndroid Build Coastguard Worker /*
9558*5e7646d2SAndroid Build Coastguard Worker * Close the file and return...
9559*5e7646d2SAndroid Build Coastguard Worker */
9560*5e7646d2SAndroid Build Coastguard Worker
9561*5e7646d2SAndroid Build Coastguard Worker cupsFileClose(fp);
9562*5e7646d2SAndroid Build Coastguard Worker }
9563*5e7646d2SAndroid Build Coastguard Worker
9564*5e7646d2SAndroid Build Coastguard Worker
9565*5e7646d2SAndroid Build Coastguard Worker /*
9566*5e7646d2SAndroid Build Coastguard Worker * 'send_document()' - Send a file to a printer or class.
9567*5e7646d2SAndroid Build Coastguard Worker */
9568*5e7646d2SAndroid Build Coastguard Worker
9569*5e7646d2SAndroid Build Coastguard Worker static void
send_document(cupsd_client_t * con,ipp_attribute_t * uri)9570*5e7646d2SAndroid Build Coastguard Worker send_document(cupsd_client_t *con, /* I - Client connection */
9571*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *uri) /* I - Printer URI */
9572*5e7646d2SAndroid Build Coastguard Worker {
9573*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *attr; /* Current attribute */
9574*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *format; /* Request's document-format attribute */
9575*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *jformat; /* Job's document-format attribute */
9576*5e7646d2SAndroid Build Coastguard Worker const char *default_format;/* document-format-default value */
9577*5e7646d2SAndroid Build Coastguard Worker int jobid; /* Job ID number */
9578*5e7646d2SAndroid Build Coastguard Worker cupsd_job_t *job; /* Current job */
9579*5e7646d2SAndroid Build Coastguard Worker char job_uri[HTTP_MAX_URI],
9580*5e7646d2SAndroid Build Coastguard Worker /* Job URI */
9581*5e7646d2SAndroid Build Coastguard Worker scheme[HTTP_MAX_URI],
9582*5e7646d2SAndroid Build Coastguard Worker /* Method portion of URI */
9583*5e7646d2SAndroid Build Coastguard Worker username[HTTP_MAX_URI],
9584*5e7646d2SAndroid Build Coastguard Worker /* Username portion of URI */
9585*5e7646d2SAndroid Build Coastguard Worker host[HTTP_MAX_URI],
9586*5e7646d2SAndroid Build Coastguard Worker /* Host portion of URI */
9587*5e7646d2SAndroid Build Coastguard Worker resource[HTTP_MAX_URI];
9588*5e7646d2SAndroid Build Coastguard Worker /* Resource portion of URI */
9589*5e7646d2SAndroid Build Coastguard Worker int port; /* Port portion of URI */
9590*5e7646d2SAndroid Build Coastguard Worker mime_type_t *filetype; /* Type of file */
9591*5e7646d2SAndroid Build Coastguard Worker char super[MIME_MAX_SUPER],
9592*5e7646d2SAndroid Build Coastguard Worker /* Supertype of file */
9593*5e7646d2SAndroid Build Coastguard Worker type[MIME_MAX_TYPE],
9594*5e7646d2SAndroid Build Coastguard Worker /* Subtype of file */
9595*5e7646d2SAndroid Build Coastguard Worker mimetype[MIME_MAX_SUPER + MIME_MAX_TYPE + 2];
9596*5e7646d2SAndroid Build Coastguard Worker /* Textual name of mime type */
9597*5e7646d2SAndroid Build Coastguard Worker char filename[1024]; /* Job filename */
9598*5e7646d2SAndroid Build Coastguard Worker cupsd_printer_t *printer; /* Current printer */
9599*5e7646d2SAndroid Build Coastguard Worker struct stat fileinfo; /* File information */
9600*5e7646d2SAndroid Build Coastguard Worker int kbytes; /* Size of file */
9601*5e7646d2SAndroid Build Coastguard Worker int compression; /* Type of compression */
9602*5e7646d2SAndroid Build Coastguard Worker int start_job; /* Start the job? */
9603*5e7646d2SAndroid Build Coastguard Worker
9604*5e7646d2SAndroid Build Coastguard Worker
9605*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG2, "send_document(%p[%d], %s)", con,
9606*5e7646d2SAndroid Build Coastguard Worker con->number, uri->values[0].string.text);
9607*5e7646d2SAndroid Build Coastguard Worker
9608*5e7646d2SAndroid Build Coastguard Worker /*
9609*5e7646d2SAndroid Build Coastguard Worker * See if we have a job URI or a printer URI...
9610*5e7646d2SAndroid Build Coastguard Worker */
9611*5e7646d2SAndroid Build Coastguard Worker
9612*5e7646d2SAndroid Build Coastguard Worker if (!strcmp(uri->name, "printer-uri"))
9613*5e7646d2SAndroid Build Coastguard Worker {
9614*5e7646d2SAndroid Build Coastguard Worker /*
9615*5e7646d2SAndroid Build Coastguard Worker * Got a printer URI; see if we also have a job-id attribute...
9616*5e7646d2SAndroid Build Coastguard Worker */
9617*5e7646d2SAndroid Build Coastguard Worker
9618*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippFindAttribute(con->request, "job-id",
9619*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_INTEGER)) == NULL)
9620*5e7646d2SAndroid Build Coastguard Worker {
9621*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_BAD_REQUEST,
9622*5e7646d2SAndroid Build Coastguard Worker _("Got a printer-uri attribute but no job-id."));
9623*5e7646d2SAndroid Build Coastguard Worker return;
9624*5e7646d2SAndroid Build Coastguard Worker }
9625*5e7646d2SAndroid Build Coastguard Worker
9626*5e7646d2SAndroid Build Coastguard Worker jobid = attr->values[0].integer;
9627*5e7646d2SAndroid Build Coastguard Worker }
9628*5e7646d2SAndroid Build Coastguard Worker else
9629*5e7646d2SAndroid Build Coastguard Worker {
9630*5e7646d2SAndroid Build Coastguard Worker /*
9631*5e7646d2SAndroid Build Coastguard Worker * Got a job URI; parse it to get the job ID...
9632*5e7646d2SAndroid Build Coastguard Worker */
9633*5e7646d2SAndroid Build Coastguard Worker
9634*5e7646d2SAndroid Build Coastguard Worker httpSeparateURI(HTTP_URI_CODING_ALL, uri->values[0].string.text, scheme,
9635*5e7646d2SAndroid Build Coastguard Worker sizeof(scheme), username, sizeof(username), host,
9636*5e7646d2SAndroid Build Coastguard Worker sizeof(host), &port, resource, sizeof(resource));
9637*5e7646d2SAndroid Build Coastguard Worker
9638*5e7646d2SAndroid Build Coastguard Worker if (strncmp(resource, "/jobs/", 6))
9639*5e7646d2SAndroid Build Coastguard Worker {
9640*5e7646d2SAndroid Build Coastguard Worker /*
9641*5e7646d2SAndroid Build Coastguard Worker * Not a valid URI!
9642*5e7646d2SAndroid Build Coastguard Worker */
9643*5e7646d2SAndroid Build Coastguard Worker
9644*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_BAD_REQUEST, _("Bad job-uri \"%s\"."),
9645*5e7646d2SAndroid Build Coastguard Worker uri->values[0].string.text);
9646*5e7646d2SAndroid Build Coastguard Worker return;
9647*5e7646d2SAndroid Build Coastguard Worker }
9648*5e7646d2SAndroid Build Coastguard Worker
9649*5e7646d2SAndroid Build Coastguard Worker jobid = atoi(resource + 6);
9650*5e7646d2SAndroid Build Coastguard Worker }
9651*5e7646d2SAndroid Build Coastguard Worker
9652*5e7646d2SAndroid Build Coastguard Worker /*
9653*5e7646d2SAndroid Build Coastguard Worker * See if the job exists...
9654*5e7646d2SAndroid Build Coastguard Worker */
9655*5e7646d2SAndroid Build Coastguard Worker
9656*5e7646d2SAndroid Build Coastguard Worker if ((job = cupsdFindJob(jobid)) == NULL)
9657*5e7646d2SAndroid Build Coastguard Worker {
9658*5e7646d2SAndroid Build Coastguard Worker /*
9659*5e7646d2SAndroid Build Coastguard Worker * Nope - return a "not found" error...
9660*5e7646d2SAndroid Build Coastguard Worker */
9661*5e7646d2SAndroid Build Coastguard Worker
9662*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_NOT_FOUND, _("Job #%d does not exist."), jobid);
9663*5e7646d2SAndroid Build Coastguard Worker return;
9664*5e7646d2SAndroid Build Coastguard Worker }
9665*5e7646d2SAndroid Build Coastguard Worker
9666*5e7646d2SAndroid Build Coastguard Worker printer = cupsdFindDest(job->dest);
9667*5e7646d2SAndroid Build Coastguard Worker
9668*5e7646d2SAndroid Build Coastguard Worker /*
9669*5e7646d2SAndroid Build Coastguard Worker * See if the job is owned by the requesting user...
9670*5e7646d2SAndroid Build Coastguard Worker */
9671*5e7646d2SAndroid Build Coastguard Worker
9672*5e7646d2SAndroid Build Coastguard Worker if (!validate_user(job, con, job->username, username, sizeof(username)))
9673*5e7646d2SAndroid Build Coastguard Worker {
9674*5e7646d2SAndroid Build Coastguard Worker send_http_error(con, con->username[0] ? HTTP_FORBIDDEN : HTTP_UNAUTHORIZED,
9675*5e7646d2SAndroid Build Coastguard Worker cupsdFindDest(job->dest));
9676*5e7646d2SAndroid Build Coastguard Worker return;
9677*5e7646d2SAndroid Build Coastguard Worker }
9678*5e7646d2SAndroid Build Coastguard Worker
9679*5e7646d2SAndroid Build Coastguard Worker /*
9680*5e7646d2SAndroid Build Coastguard Worker * OK, see if the client is sending the document compressed - CUPS
9681*5e7646d2SAndroid Build Coastguard Worker * only supports "none" and "gzip".
9682*5e7646d2SAndroid Build Coastguard Worker */
9683*5e7646d2SAndroid Build Coastguard Worker
9684*5e7646d2SAndroid Build Coastguard Worker compression = CUPS_FILE_NONE;
9685*5e7646d2SAndroid Build Coastguard Worker
9686*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippFindAttribute(con->request, "compression",
9687*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_KEYWORD)) != NULL)
9688*5e7646d2SAndroid Build Coastguard Worker {
9689*5e7646d2SAndroid Build Coastguard Worker if (strcmp(attr->values[0].string.text, "none")
9690*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_LIBZ
9691*5e7646d2SAndroid Build Coastguard Worker && strcmp(attr->values[0].string.text, "gzip")
9692*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_LIBZ */
9693*5e7646d2SAndroid Build Coastguard Worker )
9694*5e7646d2SAndroid Build Coastguard Worker {
9695*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_ATTRIBUTES, _("Unsupported compression \"%s\"."),
9696*5e7646d2SAndroid Build Coastguard Worker attr->values[0].string.text);
9697*5e7646d2SAndroid Build Coastguard Worker ippAddString(con->response, IPP_TAG_UNSUPPORTED_GROUP, IPP_TAG_KEYWORD,
9698*5e7646d2SAndroid Build Coastguard Worker "compression", NULL, attr->values[0].string.text);
9699*5e7646d2SAndroid Build Coastguard Worker return;
9700*5e7646d2SAndroid Build Coastguard Worker }
9701*5e7646d2SAndroid Build Coastguard Worker
9702*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_LIBZ
9703*5e7646d2SAndroid Build Coastguard Worker if (!strcmp(attr->values[0].string.text, "gzip"))
9704*5e7646d2SAndroid Build Coastguard Worker compression = CUPS_FILE_GZIP;
9705*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_LIBZ */
9706*5e7646d2SAndroid Build Coastguard Worker }
9707*5e7646d2SAndroid Build Coastguard Worker
9708*5e7646d2SAndroid Build Coastguard Worker /*
9709*5e7646d2SAndroid Build Coastguard Worker * Do we have a file to print?
9710*5e7646d2SAndroid Build Coastguard Worker */
9711*5e7646d2SAndroid Build Coastguard Worker
9712*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippFindAttribute(con->request, "last-document",
9713*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_BOOLEAN)) == NULL)
9714*5e7646d2SAndroid Build Coastguard Worker {
9715*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_BAD_REQUEST,
9716*5e7646d2SAndroid Build Coastguard Worker _("Missing last-document attribute in request."));
9717*5e7646d2SAndroid Build Coastguard Worker return;
9718*5e7646d2SAndroid Build Coastguard Worker }
9719*5e7646d2SAndroid Build Coastguard Worker
9720*5e7646d2SAndroid Build Coastguard Worker if (!con->filename)
9721*5e7646d2SAndroid Build Coastguard Worker {
9722*5e7646d2SAndroid Build Coastguard Worker /*
9723*5e7646d2SAndroid Build Coastguard Worker * Check for an empty request with "last-document" set to true, which is
9724*5e7646d2SAndroid Build Coastguard Worker * used to close an "open" job by RFC 2911, section 3.3.2.
9725*5e7646d2SAndroid Build Coastguard Worker */
9726*5e7646d2SAndroid Build Coastguard Worker
9727*5e7646d2SAndroid Build Coastguard Worker if (job->num_files > 0 && attr->values[0].boolean)
9728*5e7646d2SAndroid Build Coastguard Worker goto last_document;
9729*5e7646d2SAndroid Build Coastguard Worker
9730*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_BAD_REQUEST, _("No file in print request."));
9731*5e7646d2SAndroid Build Coastguard Worker return;
9732*5e7646d2SAndroid Build Coastguard Worker }
9733*5e7646d2SAndroid Build Coastguard Worker
9734*5e7646d2SAndroid Build Coastguard Worker /*
9735*5e7646d2SAndroid Build Coastguard Worker * Is it a format we support?
9736*5e7646d2SAndroid Build Coastguard Worker */
9737*5e7646d2SAndroid Build Coastguard Worker
9738*5e7646d2SAndroid Build Coastguard Worker cupsdLoadJob(job);
9739*5e7646d2SAndroid Build Coastguard Worker
9740*5e7646d2SAndroid Build Coastguard Worker if ((format = ippFindAttribute(con->request, "document-format",
9741*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_MIMETYPE)) != NULL)
9742*5e7646d2SAndroid Build Coastguard Worker {
9743*5e7646d2SAndroid Build Coastguard Worker /*
9744*5e7646d2SAndroid Build Coastguard Worker * Grab format from client...
9745*5e7646d2SAndroid Build Coastguard Worker */
9746*5e7646d2SAndroid Build Coastguard Worker
9747*5e7646d2SAndroid Build Coastguard Worker if (sscanf(format->values[0].string.text, "%15[^/]/%255[^;]",
9748*5e7646d2SAndroid Build Coastguard Worker super, type) != 2)
9749*5e7646d2SAndroid Build Coastguard Worker {
9750*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_BAD_REQUEST, _("Bad document-format \"%s\"."),
9751*5e7646d2SAndroid Build Coastguard Worker format->values[0].string.text);
9752*5e7646d2SAndroid Build Coastguard Worker return;
9753*5e7646d2SAndroid Build Coastguard Worker }
9754*5e7646d2SAndroid Build Coastguard Worker
9755*5e7646d2SAndroid Build Coastguard Worker ippAddString(job->attrs, IPP_TAG_JOB, IPP_TAG_MIMETYPE, "document-format-supplied", NULL, ippGetString(format, 0, NULL));
9756*5e7646d2SAndroid Build Coastguard Worker }
9757*5e7646d2SAndroid Build Coastguard Worker else if ((default_format = cupsGetOption("document-format",
9758*5e7646d2SAndroid Build Coastguard Worker printer->num_options,
9759*5e7646d2SAndroid Build Coastguard Worker printer->options)) != NULL)
9760*5e7646d2SAndroid Build Coastguard Worker {
9761*5e7646d2SAndroid Build Coastguard Worker /*
9762*5e7646d2SAndroid Build Coastguard Worker * Use default document format...
9763*5e7646d2SAndroid Build Coastguard Worker */
9764*5e7646d2SAndroid Build Coastguard Worker
9765*5e7646d2SAndroid Build Coastguard Worker if (sscanf(default_format, "%15[^/]/%255[^;]", super, type) != 2)
9766*5e7646d2SAndroid Build Coastguard Worker {
9767*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_BAD_REQUEST,
9768*5e7646d2SAndroid Build Coastguard Worker _("Bad document-format-default \"%s\"."), default_format);
9769*5e7646d2SAndroid Build Coastguard Worker return;
9770*5e7646d2SAndroid Build Coastguard Worker }
9771*5e7646d2SAndroid Build Coastguard Worker }
9772*5e7646d2SAndroid Build Coastguard Worker else
9773*5e7646d2SAndroid Build Coastguard Worker {
9774*5e7646d2SAndroid Build Coastguard Worker /*
9775*5e7646d2SAndroid Build Coastguard Worker * No document format attribute? Auto-type it!
9776*5e7646d2SAndroid Build Coastguard Worker */
9777*5e7646d2SAndroid Build Coastguard Worker
9778*5e7646d2SAndroid Build Coastguard Worker strlcpy(super, "application", sizeof(super));
9779*5e7646d2SAndroid Build Coastguard Worker strlcpy(type, "octet-stream", sizeof(type));
9780*5e7646d2SAndroid Build Coastguard Worker }
9781*5e7646d2SAndroid Build Coastguard Worker
9782*5e7646d2SAndroid Build Coastguard Worker if (!strcmp(super, "application") && !strcmp(type, "octet-stream"))
9783*5e7646d2SAndroid Build Coastguard Worker {
9784*5e7646d2SAndroid Build Coastguard Worker /*
9785*5e7646d2SAndroid Build Coastguard Worker * Auto-type the file...
9786*5e7646d2SAndroid Build Coastguard Worker */
9787*5e7646d2SAndroid Build Coastguard Worker
9788*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *doc_name; /* document-name attribute */
9789*5e7646d2SAndroid Build Coastguard Worker
9790*5e7646d2SAndroid Build Coastguard Worker
9791*5e7646d2SAndroid Build Coastguard Worker cupsdLogJob(job, CUPSD_LOG_DEBUG, "Auto-typing file...");
9792*5e7646d2SAndroid Build Coastguard Worker
9793*5e7646d2SAndroid Build Coastguard Worker doc_name = ippFindAttribute(con->request, "document-name", IPP_TAG_NAME);
9794*5e7646d2SAndroid Build Coastguard Worker filetype = mimeFileType(MimeDatabase, con->filename,
9795*5e7646d2SAndroid Build Coastguard Worker doc_name ? doc_name->values[0].string.text : NULL,
9796*5e7646d2SAndroid Build Coastguard Worker &compression);
9797*5e7646d2SAndroid Build Coastguard Worker
9798*5e7646d2SAndroid Build Coastguard Worker if (!filetype)
9799*5e7646d2SAndroid Build Coastguard Worker filetype = mimeType(MimeDatabase, super, type);
9800*5e7646d2SAndroid Build Coastguard Worker
9801*5e7646d2SAndroid Build Coastguard Worker if (filetype)
9802*5e7646d2SAndroid Build Coastguard Worker cupsdLogJob(job, CUPSD_LOG_DEBUG, "Request file type is %s/%s.",
9803*5e7646d2SAndroid Build Coastguard Worker filetype->super, filetype->type);
9804*5e7646d2SAndroid Build Coastguard Worker
9805*5e7646d2SAndroid Build Coastguard Worker snprintf(mimetype, sizeof(mimetype), "%s/%s", filetype->super, filetype->type);
9806*5e7646d2SAndroid Build Coastguard Worker ippAddString(job->attrs, IPP_TAG_JOB, IPP_TAG_MIMETYPE, "document-format-detected", NULL, mimetype);
9807*5e7646d2SAndroid Build Coastguard Worker }
9808*5e7646d2SAndroid Build Coastguard Worker else
9809*5e7646d2SAndroid Build Coastguard Worker filetype = mimeType(MimeDatabase, super, type);
9810*5e7646d2SAndroid Build Coastguard Worker
9811*5e7646d2SAndroid Build Coastguard Worker if (filetype)
9812*5e7646d2SAndroid Build Coastguard Worker {
9813*5e7646d2SAndroid Build Coastguard Worker /*
9814*5e7646d2SAndroid Build Coastguard Worker * Replace the document-format attribute value with the auto-typed or
9815*5e7646d2SAndroid Build Coastguard Worker * default one.
9816*5e7646d2SAndroid Build Coastguard Worker */
9817*5e7646d2SAndroid Build Coastguard Worker
9818*5e7646d2SAndroid Build Coastguard Worker snprintf(mimetype, sizeof(mimetype), "%s/%s", filetype->super,
9819*5e7646d2SAndroid Build Coastguard Worker filetype->type);
9820*5e7646d2SAndroid Build Coastguard Worker
9821*5e7646d2SAndroid Build Coastguard Worker if ((jformat = ippFindAttribute(job->attrs, "document-format",
9822*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_MIMETYPE)) != NULL)
9823*5e7646d2SAndroid Build Coastguard Worker ippSetString(job->attrs, &jformat, 0, mimetype);
9824*5e7646d2SAndroid Build Coastguard Worker else
9825*5e7646d2SAndroid Build Coastguard Worker ippAddString(job->attrs, IPP_TAG_JOB, IPP_TAG_MIMETYPE,
9826*5e7646d2SAndroid Build Coastguard Worker "document-format", NULL, mimetype);
9827*5e7646d2SAndroid Build Coastguard Worker }
9828*5e7646d2SAndroid Build Coastguard Worker else if (!filetype)
9829*5e7646d2SAndroid Build Coastguard Worker {
9830*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_DOCUMENT_FORMAT,
9831*5e7646d2SAndroid Build Coastguard Worker _("Unsupported document-format \"%s/%s\"."), super, type);
9832*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_INFO,
9833*5e7646d2SAndroid Build Coastguard Worker "Hint: Do you have the raw file printing rules enabled?");
9834*5e7646d2SAndroid Build Coastguard Worker
9835*5e7646d2SAndroid Build Coastguard Worker if (format)
9836*5e7646d2SAndroid Build Coastguard Worker ippAddString(con->response, IPP_TAG_UNSUPPORTED_GROUP, IPP_TAG_MIMETYPE,
9837*5e7646d2SAndroid Build Coastguard Worker "document-format", NULL, format->values[0].string.text);
9838*5e7646d2SAndroid Build Coastguard Worker
9839*5e7646d2SAndroid Build Coastguard Worker return;
9840*5e7646d2SAndroid Build Coastguard Worker }
9841*5e7646d2SAndroid Build Coastguard Worker
9842*5e7646d2SAndroid Build Coastguard Worker if (printer->filetypes && !cupsArrayFind(printer->filetypes, filetype))
9843*5e7646d2SAndroid Build Coastguard Worker {
9844*5e7646d2SAndroid Build Coastguard Worker snprintf(mimetype, sizeof(mimetype), "%s/%s", filetype->super,
9845*5e7646d2SAndroid Build Coastguard Worker filetype->type);
9846*5e7646d2SAndroid Build Coastguard Worker
9847*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_DOCUMENT_FORMAT,
9848*5e7646d2SAndroid Build Coastguard Worker _("Unsupported document-format \"%s\"."), mimetype);
9849*5e7646d2SAndroid Build Coastguard Worker
9850*5e7646d2SAndroid Build Coastguard Worker ippAddString(con->response, IPP_TAG_UNSUPPORTED_GROUP, IPP_TAG_MIMETYPE,
9851*5e7646d2SAndroid Build Coastguard Worker "document-format", NULL, mimetype);
9852*5e7646d2SAndroid Build Coastguard Worker
9853*5e7646d2SAndroid Build Coastguard Worker return;
9854*5e7646d2SAndroid Build Coastguard Worker }
9855*5e7646d2SAndroid Build Coastguard Worker
9856*5e7646d2SAndroid Build Coastguard Worker /*
9857*5e7646d2SAndroid Build Coastguard Worker * Add the file to the job...
9858*5e7646d2SAndroid Build Coastguard Worker */
9859*5e7646d2SAndroid Build Coastguard Worker
9860*5e7646d2SAndroid Build Coastguard Worker if (add_file(con, job, filetype, compression))
9861*5e7646d2SAndroid Build Coastguard Worker return;
9862*5e7646d2SAndroid Build Coastguard Worker
9863*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippFindAttribute(con->request, "document-name", IPP_TAG_NAME)) != NULL)
9864*5e7646d2SAndroid Build Coastguard Worker ippAddString(job->attrs, IPP_TAG_JOB, IPP_TAG_NAME, "document-name-supplied", NULL, ippGetString(attr, 0, NULL));
9865*5e7646d2SAndroid Build Coastguard Worker
9866*5e7646d2SAndroid Build Coastguard Worker if (stat(con->filename, &fileinfo))
9867*5e7646d2SAndroid Build Coastguard Worker kbytes = 0;
9868*5e7646d2SAndroid Build Coastguard Worker else
9869*5e7646d2SAndroid Build Coastguard Worker kbytes = (fileinfo.st_size + 1023) / 1024;
9870*5e7646d2SAndroid Build Coastguard Worker
9871*5e7646d2SAndroid Build Coastguard Worker cupsdUpdateQuota(printer, job->username, 0, kbytes);
9872*5e7646d2SAndroid Build Coastguard Worker
9873*5e7646d2SAndroid Build Coastguard Worker job->koctets += kbytes;
9874*5e7646d2SAndroid Build Coastguard Worker
9875*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippFindAttribute(job->attrs, "job-k-octets", IPP_TAG_INTEGER)) != NULL)
9876*5e7646d2SAndroid Build Coastguard Worker attr->values[0].integer += kbytes;
9877*5e7646d2SAndroid Build Coastguard Worker
9878*5e7646d2SAndroid Build Coastguard Worker snprintf(filename, sizeof(filename), "%s/d%05d-%03d", RequestRoot, job->id, job->num_files);
9879*5e7646d2SAndroid Build Coastguard Worker if (rename(con->filename, filename))
9880*5e7646d2SAndroid Build Coastguard Worker {
9881*5e7646d2SAndroid Build Coastguard Worker cupsdLogJob(job, CUPSD_LOG_ERROR, "Unable to rename job document file \"%s\": %s", filename, strerror(errno));
9882*5e7646d2SAndroid Build Coastguard Worker
9883*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_INTERNAL_ERROR, _("Unable to rename job document file."));
9884*5e7646d2SAndroid Build Coastguard Worker return;
9885*5e7646d2SAndroid Build Coastguard Worker }
9886*5e7646d2SAndroid Build Coastguard Worker
9887*5e7646d2SAndroid Build Coastguard Worker cupsdClearString(&con->filename);
9888*5e7646d2SAndroid Build Coastguard Worker
9889*5e7646d2SAndroid Build Coastguard Worker cupsdLogJob(job, CUPSD_LOG_INFO, "File of type %s/%s queued by \"%s\".",
9890*5e7646d2SAndroid Build Coastguard Worker filetype->super, filetype->type, job->username);
9891*5e7646d2SAndroid Build Coastguard Worker
9892*5e7646d2SAndroid Build Coastguard Worker /*
9893*5e7646d2SAndroid Build Coastguard Worker * Start the job if this is the last document...
9894*5e7646d2SAndroid Build Coastguard Worker */
9895*5e7646d2SAndroid Build Coastguard Worker
9896*5e7646d2SAndroid Build Coastguard Worker last_document:
9897*5e7646d2SAndroid Build Coastguard Worker
9898*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippFindAttribute(con->request, "last-document",
9899*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_BOOLEAN)) != NULL &&
9900*5e7646d2SAndroid Build Coastguard Worker attr->values[0].boolean)
9901*5e7646d2SAndroid Build Coastguard Worker {
9902*5e7646d2SAndroid Build Coastguard Worker /*
9903*5e7646d2SAndroid Build Coastguard Worker * See if we need to add the ending sheet...
9904*5e7646d2SAndroid Build Coastguard Worker */
9905*5e7646d2SAndroid Build Coastguard Worker
9906*5e7646d2SAndroid Build Coastguard Worker if (cupsdTimeoutJob(job))
9907*5e7646d2SAndroid Build Coastguard Worker return;
9908*5e7646d2SAndroid Build Coastguard Worker
9909*5e7646d2SAndroid Build Coastguard Worker if (job->state_value == IPP_JOB_STOPPED)
9910*5e7646d2SAndroid Build Coastguard Worker {
9911*5e7646d2SAndroid Build Coastguard Worker job->state->values[0].integer = IPP_JOB_PENDING;
9912*5e7646d2SAndroid Build Coastguard Worker job->state_value = IPP_JOB_PENDING;
9913*5e7646d2SAndroid Build Coastguard Worker
9914*5e7646d2SAndroid Build Coastguard Worker ippSetString(job->attrs, &job->reasons, 0, "none");
9915*5e7646d2SAndroid Build Coastguard Worker }
9916*5e7646d2SAndroid Build Coastguard Worker else if (job->state_value == IPP_JOB_HELD)
9917*5e7646d2SAndroid Build Coastguard Worker {
9918*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippFindAttribute(job->attrs, "job-hold-until",
9919*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_KEYWORD)) == NULL)
9920*5e7646d2SAndroid Build Coastguard Worker attr = ippFindAttribute(job->attrs, "job-hold-until", IPP_TAG_NAME);
9921*5e7646d2SAndroid Build Coastguard Worker
9922*5e7646d2SAndroid Build Coastguard Worker if (!attr || !strcmp(attr->values[0].string.text, "no-hold"))
9923*5e7646d2SAndroid Build Coastguard Worker {
9924*5e7646d2SAndroid Build Coastguard Worker job->state->values[0].integer = IPP_JOB_PENDING;
9925*5e7646d2SAndroid Build Coastguard Worker job->state_value = IPP_JOB_PENDING;
9926*5e7646d2SAndroid Build Coastguard Worker
9927*5e7646d2SAndroid Build Coastguard Worker ippSetString(job->attrs, &job->reasons, 0, "none");
9928*5e7646d2SAndroid Build Coastguard Worker }
9929*5e7646d2SAndroid Build Coastguard Worker else
9930*5e7646d2SAndroid Build Coastguard Worker ippSetString(job->attrs, &job->reasons, 0, "job-hold-until-specified");
9931*5e7646d2SAndroid Build Coastguard Worker }
9932*5e7646d2SAndroid Build Coastguard Worker
9933*5e7646d2SAndroid Build Coastguard Worker job->dirty = 1;
9934*5e7646d2SAndroid Build Coastguard Worker cupsdMarkDirty(CUPSD_DIRTY_JOBS);
9935*5e7646d2SAndroid Build Coastguard Worker
9936*5e7646d2SAndroid Build Coastguard Worker start_job = 1;
9937*5e7646d2SAndroid Build Coastguard Worker }
9938*5e7646d2SAndroid Build Coastguard Worker else
9939*5e7646d2SAndroid Build Coastguard Worker {
9940*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippFindAttribute(job->attrs, "job-hold-until",
9941*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_KEYWORD)) == NULL)
9942*5e7646d2SAndroid Build Coastguard Worker attr = ippFindAttribute(job->attrs, "job-hold-until", IPP_TAG_NAME);
9943*5e7646d2SAndroid Build Coastguard Worker
9944*5e7646d2SAndroid Build Coastguard Worker if (!attr || !strcmp(attr->values[0].string.text, "no-hold"))
9945*5e7646d2SAndroid Build Coastguard Worker {
9946*5e7646d2SAndroid Build Coastguard Worker job->state->values[0].integer = IPP_JOB_HELD;
9947*5e7646d2SAndroid Build Coastguard Worker job->state_value = IPP_JOB_HELD;
9948*5e7646d2SAndroid Build Coastguard Worker job->hold_until = time(NULL) + MultipleOperationTimeout;
9949*5e7646d2SAndroid Build Coastguard Worker
9950*5e7646d2SAndroid Build Coastguard Worker ippSetString(job->attrs, &job->reasons, 0, "job-incoming");
9951*5e7646d2SAndroid Build Coastguard Worker
9952*5e7646d2SAndroid Build Coastguard Worker job->dirty = 1;
9953*5e7646d2SAndroid Build Coastguard Worker cupsdMarkDirty(CUPSD_DIRTY_JOBS);
9954*5e7646d2SAndroid Build Coastguard Worker }
9955*5e7646d2SAndroid Build Coastguard Worker
9956*5e7646d2SAndroid Build Coastguard Worker start_job = 0;
9957*5e7646d2SAndroid Build Coastguard Worker }
9958*5e7646d2SAndroid Build Coastguard Worker
9959*5e7646d2SAndroid Build Coastguard Worker /*
9960*5e7646d2SAndroid Build Coastguard Worker * Fill in the response info...
9961*5e7646d2SAndroid Build Coastguard Worker */
9962*5e7646d2SAndroid Build Coastguard Worker
9963*5e7646d2SAndroid Build Coastguard Worker httpAssembleURIf(HTTP_URI_CODING_ALL, job_uri, sizeof(job_uri), "ipp", NULL, con->clientname, con->clientport, "/jobs/%d", jobid);
9964*5e7646d2SAndroid Build Coastguard Worker ippAddString(con->response, IPP_TAG_JOB, IPP_TAG_URI, "job-uri", NULL, job_uri);
9965*5e7646d2SAndroid Build Coastguard Worker
9966*5e7646d2SAndroid Build Coastguard Worker ippAddInteger(con->response, IPP_TAG_JOB, IPP_TAG_INTEGER, "job-id", jobid);
9967*5e7646d2SAndroid Build Coastguard Worker
9968*5e7646d2SAndroid Build Coastguard Worker ippAddInteger(con->response, IPP_TAG_JOB, IPP_TAG_ENUM, "job-state", (int)job->state_value);
9969*5e7646d2SAndroid Build Coastguard Worker ippAddString(con->response, IPP_TAG_JOB, IPP_TAG_KEYWORD, "job-state-reasons", NULL, job->reasons->values[0].string.text);
9970*5e7646d2SAndroid Build Coastguard Worker
9971*5e7646d2SAndroid Build Coastguard Worker con->response->request.status.status_code = IPP_OK;
9972*5e7646d2SAndroid Build Coastguard Worker
9973*5e7646d2SAndroid Build Coastguard Worker /*
9974*5e7646d2SAndroid Build Coastguard Worker * Start the job if necessary...
9975*5e7646d2SAndroid Build Coastguard Worker */
9976*5e7646d2SAndroid Build Coastguard Worker
9977*5e7646d2SAndroid Build Coastguard Worker if (start_job)
9978*5e7646d2SAndroid Build Coastguard Worker cupsdCheckJobs();
9979*5e7646d2SAndroid Build Coastguard Worker }
9980*5e7646d2SAndroid Build Coastguard Worker
9981*5e7646d2SAndroid Build Coastguard Worker
9982*5e7646d2SAndroid Build Coastguard Worker /*
9983*5e7646d2SAndroid Build Coastguard Worker * 'send_http_error()' - Send a HTTP error back to the IPP client.
9984*5e7646d2SAndroid Build Coastguard Worker */
9985*5e7646d2SAndroid Build Coastguard Worker
9986*5e7646d2SAndroid Build Coastguard Worker static void
send_http_error(cupsd_client_t * con,http_status_t status,cupsd_printer_t * printer)9987*5e7646d2SAndroid Build Coastguard Worker send_http_error(
9988*5e7646d2SAndroid Build Coastguard Worker cupsd_client_t *con, /* I - Client connection */
9989*5e7646d2SAndroid Build Coastguard Worker http_status_t status, /* I - HTTP status code */
9990*5e7646d2SAndroid Build Coastguard Worker cupsd_printer_t *printer) /* I - Printer, if any */
9991*5e7646d2SAndroid Build Coastguard Worker {
9992*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *uri; /* Request URI, if any */
9993*5e7646d2SAndroid Build Coastguard Worker
9994*5e7646d2SAndroid Build Coastguard Worker
9995*5e7646d2SAndroid Build Coastguard Worker if ((uri = ippFindAttribute(con->request, "printer-uri",
9996*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_URI)) == NULL)
9997*5e7646d2SAndroid Build Coastguard Worker uri = ippFindAttribute(con->request, "job-uri", IPP_TAG_URI);
9998*5e7646d2SAndroid Build Coastguard Worker
9999*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(status == HTTP_FORBIDDEN ? CUPSD_LOG_ERROR : CUPSD_LOG_DEBUG,
10000*5e7646d2SAndroid Build Coastguard Worker "[Client %d] Returning HTTP %s for %s (%s) from %s",
10001*5e7646d2SAndroid Build Coastguard Worker con->number, httpStatus(status),
10002*5e7646d2SAndroid Build Coastguard Worker con->request ?
10003*5e7646d2SAndroid Build Coastguard Worker ippOpString(con->request->request.op.operation_id) :
10004*5e7646d2SAndroid Build Coastguard Worker "no operation-id",
10005*5e7646d2SAndroid Build Coastguard Worker uri ? uri->values[0].string.text : "no URI",
10006*5e7646d2SAndroid Build Coastguard Worker con->http->hostname);
10007*5e7646d2SAndroid Build Coastguard Worker
10008*5e7646d2SAndroid Build Coastguard Worker if (printer)
10009*5e7646d2SAndroid Build Coastguard Worker {
10010*5e7646d2SAndroid Build Coastguard Worker int auth_type; /* Type of authentication required */
10011*5e7646d2SAndroid Build Coastguard Worker
10012*5e7646d2SAndroid Build Coastguard Worker
10013*5e7646d2SAndroid Build Coastguard Worker auth_type = CUPSD_AUTH_NONE;
10014*5e7646d2SAndroid Build Coastguard Worker
10015*5e7646d2SAndroid Build Coastguard Worker if (status == HTTP_UNAUTHORIZED &&
10016*5e7646d2SAndroid Build Coastguard Worker printer->num_auth_info_required > 0 &&
10017*5e7646d2SAndroid Build Coastguard Worker !strcmp(printer->auth_info_required[0], "negotiate") &&
10018*5e7646d2SAndroid Build Coastguard Worker con->request &&
10019*5e7646d2SAndroid Build Coastguard Worker (con->request->request.op.operation_id == IPP_PRINT_JOB ||
10020*5e7646d2SAndroid Build Coastguard Worker con->request->request.op.operation_id == IPP_CREATE_JOB ||
10021*5e7646d2SAndroid Build Coastguard Worker con->request->request.op.operation_id == CUPS_AUTHENTICATE_JOB))
10022*5e7646d2SAndroid Build Coastguard Worker {
10023*5e7646d2SAndroid Build Coastguard Worker /*
10024*5e7646d2SAndroid Build Coastguard Worker * Creating and authenticating jobs requires Kerberos...
10025*5e7646d2SAndroid Build Coastguard Worker */
10026*5e7646d2SAndroid Build Coastguard Worker
10027*5e7646d2SAndroid Build Coastguard Worker auth_type = CUPSD_AUTH_NEGOTIATE;
10028*5e7646d2SAndroid Build Coastguard Worker }
10029*5e7646d2SAndroid Build Coastguard Worker else
10030*5e7646d2SAndroid Build Coastguard Worker {
10031*5e7646d2SAndroid Build Coastguard Worker /*
10032*5e7646d2SAndroid Build Coastguard Worker * Use policy/location-defined authentication requirements...
10033*5e7646d2SAndroid Build Coastguard Worker */
10034*5e7646d2SAndroid Build Coastguard Worker
10035*5e7646d2SAndroid Build Coastguard Worker char resource[HTTP_MAX_URI]; /* Resource portion of URI */
10036*5e7646d2SAndroid Build Coastguard Worker cupsd_location_t *auth; /* Pointer to authentication element */
10037*5e7646d2SAndroid Build Coastguard Worker
10038*5e7646d2SAndroid Build Coastguard Worker
10039*5e7646d2SAndroid Build Coastguard Worker if (printer->type & CUPS_PRINTER_CLASS)
10040*5e7646d2SAndroid Build Coastguard Worker snprintf(resource, sizeof(resource), "/classes/%s", printer->name);
10041*5e7646d2SAndroid Build Coastguard Worker else
10042*5e7646d2SAndroid Build Coastguard Worker snprintf(resource, sizeof(resource), "/printers/%s", printer->name);
10043*5e7646d2SAndroid Build Coastguard Worker
10044*5e7646d2SAndroid Build Coastguard Worker if ((auth = cupsdFindBest(resource, HTTP_POST)) == NULL ||
10045*5e7646d2SAndroid Build Coastguard Worker auth->type == CUPSD_AUTH_NONE)
10046*5e7646d2SAndroid Build Coastguard Worker auth = cupsdFindPolicyOp(printer->op_policy_ptr,
10047*5e7646d2SAndroid Build Coastguard Worker con->request ?
10048*5e7646d2SAndroid Build Coastguard Worker con->request->request.op.operation_id :
10049*5e7646d2SAndroid Build Coastguard Worker IPP_PRINT_JOB);
10050*5e7646d2SAndroid Build Coastguard Worker
10051*5e7646d2SAndroid Build Coastguard Worker if (auth)
10052*5e7646d2SAndroid Build Coastguard Worker {
10053*5e7646d2SAndroid Build Coastguard Worker if (auth->type == CUPSD_AUTH_DEFAULT)
10054*5e7646d2SAndroid Build Coastguard Worker auth_type = cupsdDefaultAuthType();
10055*5e7646d2SAndroid Build Coastguard Worker else
10056*5e7646d2SAndroid Build Coastguard Worker auth_type = auth->type;
10057*5e7646d2SAndroid Build Coastguard Worker }
10058*5e7646d2SAndroid Build Coastguard Worker }
10059*5e7646d2SAndroid Build Coastguard Worker
10060*5e7646d2SAndroid Build Coastguard Worker cupsdSendError(con, status, auth_type);
10061*5e7646d2SAndroid Build Coastguard Worker }
10062*5e7646d2SAndroid Build Coastguard Worker else
10063*5e7646d2SAndroid Build Coastguard Worker cupsdSendError(con, status, CUPSD_AUTH_NONE);
10064*5e7646d2SAndroid Build Coastguard Worker
10065*5e7646d2SAndroid Build Coastguard Worker ippDelete(con->response);
10066*5e7646d2SAndroid Build Coastguard Worker con->response = NULL;
10067*5e7646d2SAndroid Build Coastguard Worker
10068*5e7646d2SAndroid Build Coastguard Worker return;
10069*5e7646d2SAndroid Build Coastguard Worker }
10070*5e7646d2SAndroid Build Coastguard Worker
10071*5e7646d2SAndroid Build Coastguard Worker
10072*5e7646d2SAndroid Build Coastguard Worker /*
10073*5e7646d2SAndroid Build Coastguard Worker * 'send_ipp_status()' - Send a status back to the IPP client.
10074*5e7646d2SAndroid Build Coastguard Worker */
10075*5e7646d2SAndroid Build Coastguard Worker
10076*5e7646d2SAndroid Build Coastguard Worker static void
send_ipp_status(cupsd_client_t * con,ipp_status_t status,const char * message,...)10077*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(cupsd_client_t *con, /* I - Client connection */
10078*5e7646d2SAndroid Build Coastguard Worker ipp_status_t status, /* I - IPP status code */
10079*5e7646d2SAndroid Build Coastguard Worker const char *message,/* I - Status message */
10080*5e7646d2SAndroid Build Coastguard Worker ...) /* I - Additional args as needed */
10081*5e7646d2SAndroid Build Coastguard Worker {
10082*5e7646d2SAndroid Build Coastguard Worker va_list ap; /* Pointer to additional args */
10083*5e7646d2SAndroid Build Coastguard Worker char formatted[1024]; /* Formatted errror message */
10084*5e7646d2SAndroid Build Coastguard Worker
10085*5e7646d2SAndroid Build Coastguard Worker
10086*5e7646d2SAndroid Build Coastguard Worker va_start(ap, message);
10087*5e7646d2SAndroid Build Coastguard Worker vsnprintf(formatted, sizeof(formatted),
10088*5e7646d2SAndroid Build Coastguard Worker _cupsLangString(con->language, message), ap);
10089*5e7646d2SAndroid Build Coastguard Worker va_end(ap);
10090*5e7646d2SAndroid Build Coastguard Worker
10091*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG, "%s %s: %s",
10092*5e7646d2SAndroid Build Coastguard Worker ippOpString(con->request->request.op.operation_id),
10093*5e7646d2SAndroid Build Coastguard Worker ippErrorString(status), formatted);
10094*5e7646d2SAndroid Build Coastguard Worker
10095*5e7646d2SAndroid Build Coastguard Worker con->response->request.status.status_code = status;
10096*5e7646d2SAndroid Build Coastguard Worker
10097*5e7646d2SAndroid Build Coastguard Worker if (ippFindAttribute(con->response, "attributes-charset",
10098*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_ZERO) == NULL)
10099*5e7646d2SAndroid Build Coastguard Worker ippAddString(con->response, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
10100*5e7646d2SAndroid Build Coastguard Worker "attributes-charset", NULL, "utf-8");
10101*5e7646d2SAndroid Build Coastguard Worker
10102*5e7646d2SAndroid Build Coastguard Worker if (ippFindAttribute(con->response, "attributes-natural-language",
10103*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_ZERO) == NULL)
10104*5e7646d2SAndroid Build Coastguard Worker ippAddString(con->response, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
10105*5e7646d2SAndroid Build Coastguard Worker "attributes-natural-language", NULL, DefaultLanguage);
10106*5e7646d2SAndroid Build Coastguard Worker
10107*5e7646d2SAndroid Build Coastguard Worker ippAddString(con->response, IPP_TAG_OPERATION, IPP_TAG_TEXT,
10108*5e7646d2SAndroid Build Coastguard Worker "status-message", NULL, formatted);
10109*5e7646d2SAndroid Build Coastguard Worker }
10110*5e7646d2SAndroid Build Coastguard Worker
10111*5e7646d2SAndroid Build Coastguard Worker
10112*5e7646d2SAndroid Build Coastguard Worker /*
10113*5e7646d2SAndroid Build Coastguard Worker * 'set_default()' - Set the default destination...
10114*5e7646d2SAndroid Build Coastguard Worker */
10115*5e7646d2SAndroid Build Coastguard Worker
10116*5e7646d2SAndroid Build Coastguard Worker static void
set_default(cupsd_client_t * con,ipp_attribute_t * uri)10117*5e7646d2SAndroid Build Coastguard Worker set_default(cupsd_client_t *con, /* I - Client connection */
10118*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *uri) /* I - Printer URI */
10119*5e7646d2SAndroid Build Coastguard Worker {
10120*5e7646d2SAndroid Build Coastguard Worker http_status_t status; /* Policy status */
10121*5e7646d2SAndroid Build Coastguard Worker cups_ptype_t dtype; /* Destination type (printer/class) */
10122*5e7646d2SAndroid Build Coastguard Worker cupsd_printer_t *printer, /* Printer */
10123*5e7646d2SAndroid Build Coastguard Worker *oldprinter; /* Old default printer */
10124*5e7646d2SAndroid Build Coastguard Worker
10125*5e7646d2SAndroid Build Coastguard Worker
10126*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG2, "set_default(%p[%d], %s)", con,
10127*5e7646d2SAndroid Build Coastguard Worker con->number, uri->values[0].string.text);
10128*5e7646d2SAndroid Build Coastguard Worker
10129*5e7646d2SAndroid Build Coastguard Worker /*
10130*5e7646d2SAndroid Build Coastguard Worker * Is the destination valid?
10131*5e7646d2SAndroid Build Coastguard Worker */
10132*5e7646d2SAndroid Build Coastguard Worker
10133*5e7646d2SAndroid Build Coastguard Worker if (!cupsdValidateDest(uri->values[0].string.text, &dtype, &printer))
10134*5e7646d2SAndroid Build Coastguard Worker {
10135*5e7646d2SAndroid Build Coastguard Worker /*
10136*5e7646d2SAndroid Build Coastguard Worker * Bad URI...
10137*5e7646d2SAndroid Build Coastguard Worker */
10138*5e7646d2SAndroid Build Coastguard Worker
10139*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_NOT_FOUND,
10140*5e7646d2SAndroid Build Coastguard Worker _("The printer or class does not exist."));
10141*5e7646d2SAndroid Build Coastguard Worker return;
10142*5e7646d2SAndroid Build Coastguard Worker }
10143*5e7646d2SAndroid Build Coastguard Worker
10144*5e7646d2SAndroid Build Coastguard Worker /*
10145*5e7646d2SAndroid Build Coastguard Worker * Check policy...
10146*5e7646d2SAndroid Build Coastguard Worker */
10147*5e7646d2SAndroid Build Coastguard Worker
10148*5e7646d2SAndroid Build Coastguard Worker if ((status = cupsdCheckPolicy(DefaultPolicyPtr, con, NULL)) != HTTP_OK)
10149*5e7646d2SAndroid Build Coastguard Worker {
10150*5e7646d2SAndroid Build Coastguard Worker send_http_error(con, status, NULL);
10151*5e7646d2SAndroid Build Coastguard Worker return;
10152*5e7646d2SAndroid Build Coastguard Worker }
10153*5e7646d2SAndroid Build Coastguard Worker
10154*5e7646d2SAndroid Build Coastguard Worker /*
10155*5e7646d2SAndroid Build Coastguard Worker * Set it as the default...
10156*5e7646d2SAndroid Build Coastguard Worker */
10157*5e7646d2SAndroid Build Coastguard Worker
10158*5e7646d2SAndroid Build Coastguard Worker oldprinter = DefaultPrinter;
10159*5e7646d2SAndroid Build Coastguard Worker DefaultPrinter = printer;
10160*5e7646d2SAndroid Build Coastguard Worker
10161*5e7646d2SAndroid Build Coastguard Worker if (oldprinter)
10162*5e7646d2SAndroid Build Coastguard Worker cupsdAddEvent(CUPSD_EVENT_PRINTER_STATE, oldprinter, NULL,
10163*5e7646d2SAndroid Build Coastguard Worker "%s is no longer the default printer.", oldprinter->name);
10164*5e7646d2SAndroid Build Coastguard Worker
10165*5e7646d2SAndroid Build Coastguard Worker cupsdAddEvent(CUPSD_EVENT_PRINTER_STATE, printer, NULL,
10166*5e7646d2SAndroid Build Coastguard Worker "%s is now the default printer.", printer->name);
10167*5e7646d2SAndroid Build Coastguard Worker
10168*5e7646d2SAndroid Build Coastguard Worker cupsdMarkDirty(CUPSD_DIRTY_PRINTERS | CUPSD_DIRTY_CLASSES |
10169*5e7646d2SAndroid Build Coastguard Worker CUPSD_DIRTY_PRINTCAP);
10170*5e7646d2SAndroid Build Coastguard Worker
10171*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_INFO,
10172*5e7646d2SAndroid Build Coastguard Worker "Default destination set to \"%s\" by \"%s\".",
10173*5e7646d2SAndroid Build Coastguard Worker printer->name, get_username(con));
10174*5e7646d2SAndroid Build Coastguard Worker
10175*5e7646d2SAndroid Build Coastguard Worker /*
10176*5e7646d2SAndroid Build Coastguard Worker * Everything was ok, so return OK status...
10177*5e7646d2SAndroid Build Coastguard Worker */
10178*5e7646d2SAndroid Build Coastguard Worker
10179*5e7646d2SAndroid Build Coastguard Worker con->response->request.status.status_code = IPP_OK;
10180*5e7646d2SAndroid Build Coastguard Worker }
10181*5e7646d2SAndroid Build Coastguard Worker
10182*5e7646d2SAndroid Build Coastguard Worker
10183*5e7646d2SAndroid Build Coastguard Worker /*
10184*5e7646d2SAndroid Build Coastguard Worker * 'set_job_attrs()' - Set job attributes.
10185*5e7646d2SAndroid Build Coastguard Worker */
10186*5e7646d2SAndroid Build Coastguard Worker
10187*5e7646d2SAndroid Build Coastguard Worker static void
set_job_attrs(cupsd_client_t * con,ipp_attribute_t * uri)10188*5e7646d2SAndroid Build Coastguard Worker set_job_attrs(cupsd_client_t *con, /* I - Client connection */
10189*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *uri) /* I - Job URI */
10190*5e7646d2SAndroid Build Coastguard Worker {
10191*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *attr, /* Current attribute */
10192*5e7646d2SAndroid Build Coastguard Worker *attr2; /* Job attribute */
10193*5e7646d2SAndroid Build Coastguard Worker int jobid; /* Job ID */
10194*5e7646d2SAndroid Build Coastguard Worker cupsd_job_t *job; /* Current job */
10195*5e7646d2SAndroid Build Coastguard Worker char scheme[HTTP_MAX_URI],
10196*5e7646d2SAndroid Build Coastguard Worker /* Method portion of URI */
10197*5e7646d2SAndroid Build Coastguard Worker username[HTTP_MAX_URI],
10198*5e7646d2SAndroid Build Coastguard Worker /* Username portion of URI */
10199*5e7646d2SAndroid Build Coastguard Worker host[HTTP_MAX_URI],
10200*5e7646d2SAndroid Build Coastguard Worker /* Host portion of URI */
10201*5e7646d2SAndroid Build Coastguard Worker resource[HTTP_MAX_URI];
10202*5e7646d2SAndroid Build Coastguard Worker /* Resource portion of URI */
10203*5e7646d2SAndroid Build Coastguard Worker int port; /* Port portion of URI */
10204*5e7646d2SAndroid Build Coastguard Worker int event; /* Events? */
10205*5e7646d2SAndroid Build Coastguard Worker int check_jobs; /* Check jobs? */
10206*5e7646d2SAndroid Build Coastguard Worker
10207*5e7646d2SAndroid Build Coastguard Worker
10208*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG2, "set_job_attrs(%p[%d], %s)", con,
10209*5e7646d2SAndroid Build Coastguard Worker con->number, uri->values[0].string.text);
10210*5e7646d2SAndroid Build Coastguard Worker
10211*5e7646d2SAndroid Build Coastguard Worker /*
10212*5e7646d2SAndroid Build Coastguard Worker * Start with "everything is OK" status...
10213*5e7646d2SAndroid Build Coastguard Worker */
10214*5e7646d2SAndroid Build Coastguard Worker
10215*5e7646d2SAndroid Build Coastguard Worker con->response->request.status.status_code = IPP_OK;
10216*5e7646d2SAndroid Build Coastguard Worker
10217*5e7646d2SAndroid Build Coastguard Worker /*
10218*5e7646d2SAndroid Build Coastguard Worker * See if we have a job URI or a printer URI...
10219*5e7646d2SAndroid Build Coastguard Worker */
10220*5e7646d2SAndroid Build Coastguard Worker
10221*5e7646d2SAndroid Build Coastguard Worker if (!strcmp(uri->name, "printer-uri"))
10222*5e7646d2SAndroid Build Coastguard Worker {
10223*5e7646d2SAndroid Build Coastguard Worker /*
10224*5e7646d2SAndroid Build Coastguard Worker * Got a printer URI; see if we also have a job-id attribute...
10225*5e7646d2SAndroid Build Coastguard Worker */
10226*5e7646d2SAndroid Build Coastguard Worker
10227*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippFindAttribute(con->request, "job-id",
10228*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_INTEGER)) == NULL)
10229*5e7646d2SAndroid Build Coastguard Worker {
10230*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_BAD_REQUEST,
10231*5e7646d2SAndroid Build Coastguard Worker _("Got a printer-uri attribute but no job-id."));
10232*5e7646d2SAndroid Build Coastguard Worker return;
10233*5e7646d2SAndroid Build Coastguard Worker }
10234*5e7646d2SAndroid Build Coastguard Worker
10235*5e7646d2SAndroid Build Coastguard Worker jobid = attr->values[0].integer;
10236*5e7646d2SAndroid Build Coastguard Worker }
10237*5e7646d2SAndroid Build Coastguard Worker else
10238*5e7646d2SAndroid Build Coastguard Worker {
10239*5e7646d2SAndroid Build Coastguard Worker /*
10240*5e7646d2SAndroid Build Coastguard Worker * Got a job URI; parse it to get the job ID...
10241*5e7646d2SAndroid Build Coastguard Worker */
10242*5e7646d2SAndroid Build Coastguard Worker
10243*5e7646d2SAndroid Build Coastguard Worker httpSeparateURI(HTTP_URI_CODING_ALL, uri->values[0].string.text, scheme,
10244*5e7646d2SAndroid Build Coastguard Worker sizeof(scheme), username, sizeof(username), host,
10245*5e7646d2SAndroid Build Coastguard Worker sizeof(host), &port, resource, sizeof(resource));
10246*5e7646d2SAndroid Build Coastguard Worker
10247*5e7646d2SAndroid Build Coastguard Worker if (strncmp(resource, "/jobs/", 6))
10248*5e7646d2SAndroid Build Coastguard Worker {
10249*5e7646d2SAndroid Build Coastguard Worker /*
10250*5e7646d2SAndroid Build Coastguard Worker * Not a valid URI!
10251*5e7646d2SAndroid Build Coastguard Worker */
10252*5e7646d2SAndroid Build Coastguard Worker
10253*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_BAD_REQUEST, _("Bad job-uri \"%s\"."),
10254*5e7646d2SAndroid Build Coastguard Worker uri->values[0].string.text);
10255*5e7646d2SAndroid Build Coastguard Worker return;
10256*5e7646d2SAndroid Build Coastguard Worker }
10257*5e7646d2SAndroid Build Coastguard Worker
10258*5e7646d2SAndroid Build Coastguard Worker jobid = atoi(resource + 6);
10259*5e7646d2SAndroid Build Coastguard Worker }
10260*5e7646d2SAndroid Build Coastguard Worker
10261*5e7646d2SAndroid Build Coastguard Worker /*
10262*5e7646d2SAndroid Build Coastguard Worker * See if the job exists...
10263*5e7646d2SAndroid Build Coastguard Worker */
10264*5e7646d2SAndroid Build Coastguard Worker
10265*5e7646d2SAndroid Build Coastguard Worker if ((job = cupsdFindJob(jobid)) == NULL)
10266*5e7646d2SAndroid Build Coastguard Worker {
10267*5e7646d2SAndroid Build Coastguard Worker /*
10268*5e7646d2SAndroid Build Coastguard Worker * Nope - return a "not found" error...
10269*5e7646d2SAndroid Build Coastguard Worker */
10270*5e7646d2SAndroid Build Coastguard Worker
10271*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_NOT_FOUND, _("Job #%d does not exist."), jobid);
10272*5e7646d2SAndroid Build Coastguard Worker return;
10273*5e7646d2SAndroid Build Coastguard Worker }
10274*5e7646d2SAndroid Build Coastguard Worker
10275*5e7646d2SAndroid Build Coastguard Worker /*
10276*5e7646d2SAndroid Build Coastguard Worker * See if the job has been completed...
10277*5e7646d2SAndroid Build Coastguard Worker */
10278*5e7646d2SAndroid Build Coastguard Worker
10279*5e7646d2SAndroid Build Coastguard Worker if (job->state_value > IPP_JOB_STOPPED)
10280*5e7646d2SAndroid Build Coastguard Worker {
10281*5e7646d2SAndroid Build Coastguard Worker /*
10282*5e7646d2SAndroid Build Coastguard Worker * Return a "not-possible" error...
10283*5e7646d2SAndroid Build Coastguard Worker */
10284*5e7646d2SAndroid Build Coastguard Worker
10285*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_NOT_POSSIBLE,
10286*5e7646d2SAndroid Build Coastguard Worker _("Job #%d is finished and cannot be altered."), jobid);
10287*5e7646d2SAndroid Build Coastguard Worker return;
10288*5e7646d2SAndroid Build Coastguard Worker }
10289*5e7646d2SAndroid Build Coastguard Worker
10290*5e7646d2SAndroid Build Coastguard Worker /*
10291*5e7646d2SAndroid Build Coastguard Worker * See if the job is owned by the requesting user...
10292*5e7646d2SAndroid Build Coastguard Worker */
10293*5e7646d2SAndroid Build Coastguard Worker
10294*5e7646d2SAndroid Build Coastguard Worker if (!validate_user(job, con, job->username, username, sizeof(username)))
10295*5e7646d2SAndroid Build Coastguard Worker {
10296*5e7646d2SAndroid Build Coastguard Worker send_http_error(con, con->username[0] ? HTTP_FORBIDDEN : HTTP_UNAUTHORIZED,
10297*5e7646d2SAndroid Build Coastguard Worker cupsdFindDest(job->dest));
10298*5e7646d2SAndroid Build Coastguard Worker return;
10299*5e7646d2SAndroid Build Coastguard Worker }
10300*5e7646d2SAndroid Build Coastguard Worker
10301*5e7646d2SAndroid Build Coastguard Worker /*
10302*5e7646d2SAndroid Build Coastguard Worker * See what the user wants to change.
10303*5e7646d2SAndroid Build Coastguard Worker */
10304*5e7646d2SAndroid Build Coastguard Worker
10305*5e7646d2SAndroid Build Coastguard Worker cupsdLoadJob(job);
10306*5e7646d2SAndroid Build Coastguard Worker
10307*5e7646d2SAndroid Build Coastguard Worker check_jobs = 0;
10308*5e7646d2SAndroid Build Coastguard Worker event = 0;
10309*5e7646d2SAndroid Build Coastguard Worker
10310*5e7646d2SAndroid Build Coastguard Worker for (attr = con->request->attrs; attr; attr = attr->next)
10311*5e7646d2SAndroid Build Coastguard Worker {
10312*5e7646d2SAndroid Build Coastguard Worker if (attr->group_tag != IPP_TAG_JOB || !attr->name)
10313*5e7646d2SAndroid Build Coastguard Worker continue;
10314*5e7646d2SAndroid Build Coastguard Worker
10315*5e7646d2SAndroid Build Coastguard Worker if (!strcmp(attr->name, "attributes-charset") ||
10316*5e7646d2SAndroid Build Coastguard Worker !strcmp(attr->name, "attributes-natural-language") ||
10317*5e7646d2SAndroid Build Coastguard Worker !strncmp(attr->name, "date-time-at-", 13) ||
10318*5e7646d2SAndroid Build Coastguard Worker !strncmp(attr->name, "document-compression", 20) ||
10319*5e7646d2SAndroid Build Coastguard Worker !strncmp(attr->name, "document-format", 15) ||
10320*5e7646d2SAndroid Build Coastguard Worker !strcmp(attr->name, "job-detailed-status-messages") ||
10321*5e7646d2SAndroid Build Coastguard Worker !strcmp(attr->name, "job-document-access-errors") ||
10322*5e7646d2SAndroid Build Coastguard Worker !strcmp(attr->name, "job-id") ||
10323*5e7646d2SAndroid Build Coastguard Worker !strcmp(attr->name, "job-impressions-completed") ||
10324*5e7646d2SAndroid Build Coastguard Worker !strcmp(attr->name, "job-k-octets-completed") ||
10325*5e7646d2SAndroid Build Coastguard Worker !strcmp(attr->name, "job-media-sheets-completed") ||
10326*5e7646d2SAndroid Build Coastguard Worker !strcmp(attr->name, "job-originating-host-name") ||
10327*5e7646d2SAndroid Build Coastguard Worker !strcmp(attr->name, "job-originating-user-name") ||
10328*5e7646d2SAndroid Build Coastguard Worker !strcmp(attr->name, "job-pages-completed") ||
10329*5e7646d2SAndroid Build Coastguard Worker !strcmp(attr->name, "job-printer-up-time") ||
10330*5e7646d2SAndroid Build Coastguard Worker !strcmp(attr->name, "job-printer-uri") ||
10331*5e7646d2SAndroid Build Coastguard Worker !strcmp(attr->name, "job-sheets") ||
10332*5e7646d2SAndroid Build Coastguard Worker !strcmp(attr->name, "job-state-message") ||
10333*5e7646d2SAndroid Build Coastguard Worker !strcmp(attr->name, "job-state-reasons") ||
10334*5e7646d2SAndroid Build Coastguard Worker !strcmp(attr->name, "job-uri") ||
10335*5e7646d2SAndroid Build Coastguard Worker !strcmp(attr->name, "number-of-documents") ||
10336*5e7646d2SAndroid Build Coastguard Worker !strcmp(attr->name, "number-of-intervening-jobs") ||
10337*5e7646d2SAndroid Build Coastguard Worker !strcmp(attr->name, "output-device-assigned") ||
10338*5e7646d2SAndroid Build Coastguard Worker !strncmp(attr->name, "time-at-", 8))
10339*5e7646d2SAndroid Build Coastguard Worker {
10340*5e7646d2SAndroid Build Coastguard Worker /*
10341*5e7646d2SAndroid Build Coastguard Worker * Read-only attrs!
10342*5e7646d2SAndroid Build Coastguard Worker */
10343*5e7646d2SAndroid Build Coastguard Worker
10344*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_ATTRIBUTES_NOT_SETTABLE,
10345*5e7646d2SAndroid Build Coastguard Worker _("%s cannot be changed."), attr->name);
10346*5e7646d2SAndroid Build Coastguard Worker
10347*5e7646d2SAndroid Build Coastguard Worker attr2 = ippCopyAttribute(con->response, attr, 0);
10348*5e7646d2SAndroid Build Coastguard Worker ippSetGroupTag(con->response, &attr2, IPP_TAG_UNSUPPORTED_GROUP);
10349*5e7646d2SAndroid Build Coastguard Worker continue;
10350*5e7646d2SAndroid Build Coastguard Worker }
10351*5e7646d2SAndroid Build Coastguard Worker
10352*5e7646d2SAndroid Build Coastguard Worker if (!ippValidateAttribute(attr))
10353*5e7646d2SAndroid Build Coastguard Worker {
10354*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_STATUS_ERROR_ATTRIBUTES_OR_VALUES, _("Bad '%s' value."), attr->name);
10355*5e7646d2SAndroid Build Coastguard Worker ippCopyAttribute(con->response, attr, 0);
10356*5e7646d2SAndroid Build Coastguard Worker return;
10357*5e7646d2SAndroid Build Coastguard Worker }
10358*5e7646d2SAndroid Build Coastguard Worker
10359*5e7646d2SAndroid Build Coastguard Worker if (!strcmp(attr->name, "job-hold-until"))
10360*5e7646d2SAndroid Build Coastguard Worker {
10361*5e7646d2SAndroid Build Coastguard Worker const char *when = ippGetString(attr, 0, NULL);
10362*5e7646d2SAndroid Build Coastguard Worker /* job-hold-until value */
10363*5e7646d2SAndroid Build Coastguard Worker
10364*5e7646d2SAndroid Build Coastguard Worker if ((ippGetValueTag(attr) != IPP_TAG_KEYWORD && ippGetValueTag(attr) != IPP_TAG_NAME && ippGetValueTag(attr) != IPP_TAG_NAMELANG) || ippGetCount(attr) != 1)
10365*5e7646d2SAndroid Build Coastguard Worker {
10366*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_STATUS_ERROR_ATTRIBUTES_OR_VALUES, _("Unsupported 'job-hold-until' value."));
10367*5e7646d2SAndroid Build Coastguard Worker ippCopyAttribute(con->response, attr, 0);
10368*5e7646d2SAndroid Build Coastguard Worker return;
10369*5e7646d2SAndroid Build Coastguard Worker }
10370*5e7646d2SAndroid Build Coastguard Worker
10371*5e7646d2SAndroid Build Coastguard Worker cupsdLogJob(job, CUPSD_LOG_DEBUG, "Setting job-hold-until to %s", when);
10372*5e7646d2SAndroid Build Coastguard Worker cupsdSetJobHoldUntil(job, when, 0);
10373*5e7646d2SAndroid Build Coastguard Worker
10374*5e7646d2SAndroid Build Coastguard Worker if (!strcmp(when, "no-hold"))
10375*5e7646d2SAndroid Build Coastguard Worker {
10376*5e7646d2SAndroid Build Coastguard Worker cupsdReleaseJob(job);
10377*5e7646d2SAndroid Build Coastguard Worker check_jobs = 1;
10378*5e7646d2SAndroid Build Coastguard Worker }
10379*5e7646d2SAndroid Build Coastguard Worker else
10380*5e7646d2SAndroid Build Coastguard Worker cupsdSetJobState(job, IPP_JOB_HELD, CUPSD_JOB_DEFAULT, "Job held by \"%s\".", username);
10381*5e7646d2SAndroid Build Coastguard Worker
10382*5e7646d2SAndroid Build Coastguard Worker event |= CUPSD_EVENT_JOB_CONFIG_CHANGED | CUPSD_EVENT_JOB_STATE;
10383*5e7646d2SAndroid Build Coastguard Worker }
10384*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(attr->name, "job-priority"))
10385*5e7646d2SAndroid Build Coastguard Worker {
10386*5e7646d2SAndroid Build Coastguard Worker /*
10387*5e7646d2SAndroid Build Coastguard Worker * Change the job priority...
10388*5e7646d2SAndroid Build Coastguard Worker */
10389*5e7646d2SAndroid Build Coastguard Worker
10390*5e7646d2SAndroid Build Coastguard Worker if (attr->value_tag != IPP_TAG_INTEGER)
10391*5e7646d2SAndroid Build Coastguard Worker {
10392*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_REQUEST_VALUE, _("Bad job-priority value."));
10393*5e7646d2SAndroid Build Coastguard Worker
10394*5e7646d2SAndroid Build Coastguard Worker attr2 = ippCopyAttribute(con->response, attr, 0);
10395*5e7646d2SAndroid Build Coastguard Worker ippSetGroupTag(con->response, &attr2, IPP_TAG_UNSUPPORTED_GROUP);
10396*5e7646d2SAndroid Build Coastguard Worker }
10397*5e7646d2SAndroid Build Coastguard Worker else if (job->state_value >= IPP_JOB_PROCESSING)
10398*5e7646d2SAndroid Build Coastguard Worker {
10399*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_NOT_POSSIBLE,
10400*5e7646d2SAndroid Build Coastguard Worker _("Job is completed and cannot be changed."));
10401*5e7646d2SAndroid Build Coastguard Worker return;
10402*5e7646d2SAndroid Build Coastguard Worker }
10403*5e7646d2SAndroid Build Coastguard Worker else if (con->response->request.status.status_code == IPP_OK)
10404*5e7646d2SAndroid Build Coastguard Worker {
10405*5e7646d2SAndroid Build Coastguard Worker cupsdLogJob(job, CUPSD_LOG_DEBUG, "Setting job-priority to %d",
10406*5e7646d2SAndroid Build Coastguard Worker attr->values[0].integer);
10407*5e7646d2SAndroid Build Coastguard Worker cupsdSetJobPriority(job, attr->values[0].integer);
10408*5e7646d2SAndroid Build Coastguard Worker
10409*5e7646d2SAndroid Build Coastguard Worker check_jobs = 1;
10410*5e7646d2SAndroid Build Coastguard Worker event |= CUPSD_EVENT_JOB_CONFIG_CHANGED |
10411*5e7646d2SAndroid Build Coastguard Worker CUPSD_EVENT_PRINTER_QUEUE_ORDER_CHANGED;
10412*5e7646d2SAndroid Build Coastguard Worker }
10413*5e7646d2SAndroid Build Coastguard Worker }
10414*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(attr->name, "job-state"))
10415*5e7646d2SAndroid Build Coastguard Worker {
10416*5e7646d2SAndroid Build Coastguard Worker /*
10417*5e7646d2SAndroid Build Coastguard Worker * Change the job state...
10418*5e7646d2SAndroid Build Coastguard Worker */
10419*5e7646d2SAndroid Build Coastguard Worker
10420*5e7646d2SAndroid Build Coastguard Worker if (attr->value_tag != IPP_TAG_ENUM)
10421*5e7646d2SAndroid Build Coastguard Worker {
10422*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_REQUEST_VALUE, _("Bad job-state value."));
10423*5e7646d2SAndroid Build Coastguard Worker
10424*5e7646d2SAndroid Build Coastguard Worker attr2 = ippCopyAttribute(con->response, attr, 0);
10425*5e7646d2SAndroid Build Coastguard Worker ippSetGroupTag(con->response, &attr2, IPP_TAG_UNSUPPORTED_GROUP);
10426*5e7646d2SAndroid Build Coastguard Worker }
10427*5e7646d2SAndroid Build Coastguard Worker else
10428*5e7646d2SAndroid Build Coastguard Worker {
10429*5e7646d2SAndroid Build Coastguard Worker switch (attr->values[0].integer)
10430*5e7646d2SAndroid Build Coastguard Worker {
10431*5e7646d2SAndroid Build Coastguard Worker case IPP_JOB_PENDING :
10432*5e7646d2SAndroid Build Coastguard Worker case IPP_JOB_HELD :
10433*5e7646d2SAndroid Build Coastguard Worker if (job->state_value > IPP_JOB_HELD)
10434*5e7646d2SAndroid Build Coastguard Worker {
10435*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_NOT_POSSIBLE,
10436*5e7646d2SAndroid Build Coastguard Worker _("Job state cannot be changed."));
10437*5e7646d2SAndroid Build Coastguard Worker return;
10438*5e7646d2SAndroid Build Coastguard Worker }
10439*5e7646d2SAndroid Build Coastguard Worker else if (con->response->request.status.status_code == IPP_OK)
10440*5e7646d2SAndroid Build Coastguard Worker {
10441*5e7646d2SAndroid Build Coastguard Worker cupsdLogJob(job, CUPSD_LOG_DEBUG, "Setting job-state to %d",
10442*5e7646d2SAndroid Build Coastguard Worker attr->values[0].integer);
10443*5e7646d2SAndroid Build Coastguard Worker cupsdSetJobState(job, (ipp_jstate_t)attr->values[0].integer, CUPSD_JOB_DEFAULT, "Job state changed by \"%s\"", username);
10444*5e7646d2SAndroid Build Coastguard Worker check_jobs = 1;
10445*5e7646d2SAndroid Build Coastguard Worker }
10446*5e7646d2SAndroid Build Coastguard Worker break;
10447*5e7646d2SAndroid Build Coastguard Worker
10448*5e7646d2SAndroid Build Coastguard Worker case IPP_JOB_PROCESSING :
10449*5e7646d2SAndroid Build Coastguard Worker case IPP_JOB_STOPPED :
10450*5e7646d2SAndroid Build Coastguard Worker if (job->state_value != (ipp_jstate_t)attr->values[0].integer)
10451*5e7646d2SAndroid Build Coastguard Worker {
10452*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_NOT_POSSIBLE,
10453*5e7646d2SAndroid Build Coastguard Worker _("Job state cannot be changed."));
10454*5e7646d2SAndroid Build Coastguard Worker return;
10455*5e7646d2SAndroid Build Coastguard Worker }
10456*5e7646d2SAndroid Build Coastguard Worker break;
10457*5e7646d2SAndroid Build Coastguard Worker
10458*5e7646d2SAndroid Build Coastguard Worker case IPP_JOB_CANCELED :
10459*5e7646d2SAndroid Build Coastguard Worker case IPP_JOB_ABORTED :
10460*5e7646d2SAndroid Build Coastguard Worker case IPP_JOB_COMPLETED :
10461*5e7646d2SAndroid Build Coastguard Worker if (job->state_value > IPP_JOB_PROCESSING)
10462*5e7646d2SAndroid Build Coastguard Worker {
10463*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_NOT_POSSIBLE,
10464*5e7646d2SAndroid Build Coastguard Worker _("Job state cannot be changed."));
10465*5e7646d2SAndroid Build Coastguard Worker return;
10466*5e7646d2SAndroid Build Coastguard Worker }
10467*5e7646d2SAndroid Build Coastguard Worker else if (con->response->request.status.status_code == IPP_OK)
10468*5e7646d2SAndroid Build Coastguard Worker {
10469*5e7646d2SAndroid Build Coastguard Worker cupsdLogJob(job, CUPSD_LOG_DEBUG, "Setting job-state to %d",
10470*5e7646d2SAndroid Build Coastguard Worker attr->values[0].integer);
10471*5e7646d2SAndroid Build Coastguard Worker cupsdSetJobState(job, (ipp_jstate_t)attr->values[0].integer,
10472*5e7646d2SAndroid Build Coastguard Worker CUPSD_JOB_DEFAULT,
10473*5e7646d2SAndroid Build Coastguard Worker "Job state changed by \"%s\"", username);
10474*5e7646d2SAndroid Build Coastguard Worker check_jobs = 1;
10475*5e7646d2SAndroid Build Coastguard Worker }
10476*5e7646d2SAndroid Build Coastguard Worker break;
10477*5e7646d2SAndroid Build Coastguard Worker }
10478*5e7646d2SAndroid Build Coastguard Worker }
10479*5e7646d2SAndroid Build Coastguard Worker }
10480*5e7646d2SAndroid Build Coastguard Worker else if (con->response->request.status.status_code != IPP_OK)
10481*5e7646d2SAndroid Build Coastguard Worker continue;
10482*5e7646d2SAndroid Build Coastguard Worker else if ((attr2 = ippFindAttribute(job->attrs, attr->name,
10483*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_ZERO)) != NULL)
10484*5e7646d2SAndroid Build Coastguard Worker {
10485*5e7646d2SAndroid Build Coastguard Worker /*
10486*5e7646d2SAndroid Build Coastguard Worker * Some other value; first free the old value...
10487*5e7646d2SAndroid Build Coastguard Worker */
10488*5e7646d2SAndroid Build Coastguard Worker
10489*5e7646d2SAndroid Build Coastguard Worker if (job->attrs->prev)
10490*5e7646d2SAndroid Build Coastguard Worker job->attrs->prev->next = attr2->next;
10491*5e7646d2SAndroid Build Coastguard Worker else
10492*5e7646d2SAndroid Build Coastguard Worker job->attrs->attrs = attr2->next;
10493*5e7646d2SAndroid Build Coastguard Worker
10494*5e7646d2SAndroid Build Coastguard Worker if (job->attrs->last == attr2)
10495*5e7646d2SAndroid Build Coastguard Worker job->attrs->last = job->attrs->prev;
10496*5e7646d2SAndroid Build Coastguard Worker
10497*5e7646d2SAndroid Build Coastguard Worker ippDeleteAttribute(NULL, attr2);
10498*5e7646d2SAndroid Build Coastguard Worker
10499*5e7646d2SAndroid Build Coastguard Worker /*
10500*5e7646d2SAndroid Build Coastguard Worker * Then copy the attribute...
10501*5e7646d2SAndroid Build Coastguard Worker */
10502*5e7646d2SAndroid Build Coastguard Worker
10503*5e7646d2SAndroid Build Coastguard Worker ippCopyAttribute(job->attrs, attr, 0);
10504*5e7646d2SAndroid Build Coastguard Worker }
10505*5e7646d2SAndroid Build Coastguard Worker else if (attr->value_tag == IPP_TAG_DELETEATTR)
10506*5e7646d2SAndroid Build Coastguard Worker {
10507*5e7646d2SAndroid Build Coastguard Worker /*
10508*5e7646d2SAndroid Build Coastguard Worker * Delete the attribute...
10509*5e7646d2SAndroid Build Coastguard Worker */
10510*5e7646d2SAndroid Build Coastguard Worker
10511*5e7646d2SAndroid Build Coastguard Worker if ((attr2 = ippFindAttribute(job->attrs, attr->name,
10512*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_ZERO)) != NULL)
10513*5e7646d2SAndroid Build Coastguard Worker {
10514*5e7646d2SAndroid Build Coastguard Worker if (job->attrs->prev)
10515*5e7646d2SAndroid Build Coastguard Worker job->attrs->prev->next = attr2->next;
10516*5e7646d2SAndroid Build Coastguard Worker else
10517*5e7646d2SAndroid Build Coastguard Worker job->attrs->attrs = attr2->next;
10518*5e7646d2SAndroid Build Coastguard Worker
10519*5e7646d2SAndroid Build Coastguard Worker if (attr2 == job->attrs->last)
10520*5e7646d2SAndroid Build Coastguard Worker job->attrs->last = job->attrs->prev;
10521*5e7646d2SAndroid Build Coastguard Worker
10522*5e7646d2SAndroid Build Coastguard Worker ippDeleteAttribute(NULL, attr2);
10523*5e7646d2SAndroid Build Coastguard Worker
10524*5e7646d2SAndroid Build Coastguard Worker event |= CUPSD_EVENT_JOB_CONFIG_CHANGED;
10525*5e7646d2SAndroid Build Coastguard Worker }
10526*5e7646d2SAndroid Build Coastguard Worker }
10527*5e7646d2SAndroid Build Coastguard Worker else
10528*5e7646d2SAndroid Build Coastguard Worker {
10529*5e7646d2SAndroid Build Coastguard Worker /*
10530*5e7646d2SAndroid Build Coastguard Worker * Add new option by copying it...
10531*5e7646d2SAndroid Build Coastguard Worker */
10532*5e7646d2SAndroid Build Coastguard Worker
10533*5e7646d2SAndroid Build Coastguard Worker ippCopyAttribute(job->attrs, attr, 0);
10534*5e7646d2SAndroid Build Coastguard Worker
10535*5e7646d2SAndroid Build Coastguard Worker event |= CUPSD_EVENT_JOB_CONFIG_CHANGED;
10536*5e7646d2SAndroid Build Coastguard Worker }
10537*5e7646d2SAndroid Build Coastguard Worker }
10538*5e7646d2SAndroid Build Coastguard Worker
10539*5e7646d2SAndroid Build Coastguard Worker /*
10540*5e7646d2SAndroid Build Coastguard Worker * Save the job...
10541*5e7646d2SAndroid Build Coastguard Worker */
10542*5e7646d2SAndroid Build Coastguard Worker
10543*5e7646d2SAndroid Build Coastguard Worker job->dirty = 1;
10544*5e7646d2SAndroid Build Coastguard Worker cupsdMarkDirty(CUPSD_DIRTY_JOBS);
10545*5e7646d2SAndroid Build Coastguard Worker
10546*5e7646d2SAndroid Build Coastguard Worker /*
10547*5e7646d2SAndroid Build Coastguard Worker * Send events as needed...
10548*5e7646d2SAndroid Build Coastguard Worker */
10549*5e7646d2SAndroid Build Coastguard Worker
10550*5e7646d2SAndroid Build Coastguard Worker if (event & CUPSD_EVENT_PRINTER_QUEUE_ORDER_CHANGED)
10551*5e7646d2SAndroid Build Coastguard Worker cupsdAddEvent(CUPSD_EVENT_PRINTER_QUEUE_ORDER_CHANGED,
10552*5e7646d2SAndroid Build Coastguard Worker cupsdFindDest(job->dest), job,
10553*5e7646d2SAndroid Build Coastguard Worker "Job priority changed by user.");
10554*5e7646d2SAndroid Build Coastguard Worker
10555*5e7646d2SAndroid Build Coastguard Worker if (event & CUPSD_EVENT_JOB_STATE)
10556*5e7646d2SAndroid Build Coastguard Worker cupsdAddEvent(CUPSD_EVENT_JOB_STATE, cupsdFindDest(job->dest), job,
10557*5e7646d2SAndroid Build Coastguard Worker job->state_value == IPP_JOB_HELD ?
10558*5e7646d2SAndroid Build Coastguard Worker "Job held by user." : "Job restarted by user.");
10559*5e7646d2SAndroid Build Coastguard Worker
10560*5e7646d2SAndroid Build Coastguard Worker if (event & CUPSD_EVENT_JOB_CONFIG_CHANGED)
10561*5e7646d2SAndroid Build Coastguard Worker cupsdAddEvent(CUPSD_EVENT_JOB_CONFIG_CHANGED, cupsdFindDest(job->dest), job,
10562*5e7646d2SAndroid Build Coastguard Worker "Job options changed by user.");
10563*5e7646d2SAndroid Build Coastguard Worker
10564*5e7646d2SAndroid Build Coastguard Worker /*
10565*5e7646d2SAndroid Build Coastguard Worker * Start jobs if possible...
10566*5e7646d2SAndroid Build Coastguard Worker */
10567*5e7646d2SAndroid Build Coastguard Worker
10568*5e7646d2SAndroid Build Coastguard Worker if (check_jobs)
10569*5e7646d2SAndroid Build Coastguard Worker cupsdCheckJobs();
10570*5e7646d2SAndroid Build Coastguard Worker }
10571*5e7646d2SAndroid Build Coastguard Worker
10572*5e7646d2SAndroid Build Coastguard Worker
10573*5e7646d2SAndroid Build Coastguard Worker /*
10574*5e7646d2SAndroid Build Coastguard Worker * 'set_printer_attrs()' - Set printer attributes.
10575*5e7646d2SAndroid Build Coastguard Worker */
10576*5e7646d2SAndroid Build Coastguard Worker
10577*5e7646d2SAndroid Build Coastguard Worker static void
set_printer_attrs(cupsd_client_t * con,ipp_attribute_t * uri)10578*5e7646d2SAndroid Build Coastguard Worker set_printer_attrs(cupsd_client_t *con, /* I - Client connection */
10579*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *uri) /* I - Printer */
10580*5e7646d2SAndroid Build Coastguard Worker {
10581*5e7646d2SAndroid Build Coastguard Worker http_status_t status; /* Policy status */
10582*5e7646d2SAndroid Build Coastguard Worker cups_ptype_t dtype; /* Destination type (printer/class) */
10583*5e7646d2SAndroid Build Coastguard Worker cupsd_printer_t *printer; /* Printer/class */
10584*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *attr; /* Printer attribute */
10585*5e7646d2SAndroid Build Coastguard Worker int changed = 0; /* Was anything changed? */
10586*5e7646d2SAndroid Build Coastguard Worker
10587*5e7646d2SAndroid Build Coastguard Worker
10588*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG2, "set_printer_attrs(%p[%d], %s)", con,
10589*5e7646d2SAndroid Build Coastguard Worker con->number, uri->values[0].string.text);
10590*5e7646d2SAndroid Build Coastguard Worker
10591*5e7646d2SAndroid Build Coastguard Worker /*
10592*5e7646d2SAndroid Build Coastguard Worker * Is the destination valid?
10593*5e7646d2SAndroid Build Coastguard Worker */
10594*5e7646d2SAndroid Build Coastguard Worker
10595*5e7646d2SAndroid Build Coastguard Worker if (!cupsdValidateDest(uri->values[0].string.text, &dtype, &printer))
10596*5e7646d2SAndroid Build Coastguard Worker {
10597*5e7646d2SAndroid Build Coastguard Worker /*
10598*5e7646d2SAndroid Build Coastguard Worker * Bad URI...
10599*5e7646d2SAndroid Build Coastguard Worker */
10600*5e7646d2SAndroid Build Coastguard Worker
10601*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_NOT_FOUND,
10602*5e7646d2SAndroid Build Coastguard Worker _("The printer or class does not exist."));
10603*5e7646d2SAndroid Build Coastguard Worker return;
10604*5e7646d2SAndroid Build Coastguard Worker }
10605*5e7646d2SAndroid Build Coastguard Worker
10606*5e7646d2SAndroid Build Coastguard Worker /*
10607*5e7646d2SAndroid Build Coastguard Worker * Check policy...
10608*5e7646d2SAndroid Build Coastguard Worker */
10609*5e7646d2SAndroid Build Coastguard Worker
10610*5e7646d2SAndroid Build Coastguard Worker if ((status = cupsdCheckPolicy(printer->op_policy_ptr, con, NULL)) != HTTP_OK)
10611*5e7646d2SAndroid Build Coastguard Worker {
10612*5e7646d2SAndroid Build Coastguard Worker send_http_error(con, status, printer);
10613*5e7646d2SAndroid Build Coastguard Worker return;
10614*5e7646d2SAndroid Build Coastguard Worker }
10615*5e7646d2SAndroid Build Coastguard Worker
10616*5e7646d2SAndroid Build Coastguard Worker /*
10617*5e7646d2SAndroid Build Coastguard Worker * Return a list of attributes that can be set via Set-Printer-Attributes.
10618*5e7646d2SAndroid Build Coastguard Worker */
10619*5e7646d2SAndroid Build Coastguard Worker
10620*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippFindAttribute(con->request, "printer-location",
10621*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_TEXT)) != NULL)
10622*5e7646d2SAndroid Build Coastguard Worker {
10623*5e7646d2SAndroid Build Coastguard Worker cupsdSetString(&printer->location, attr->values[0].string.text);
10624*5e7646d2SAndroid Build Coastguard Worker changed = 1;
10625*5e7646d2SAndroid Build Coastguard Worker }
10626*5e7646d2SAndroid Build Coastguard Worker
10627*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippFindAttribute(con->request, "printer-geo-location", IPP_TAG_URI)) != NULL && !strncmp(attr->values[0].string.text, "geo:", 4))
10628*5e7646d2SAndroid Build Coastguard Worker {
10629*5e7646d2SAndroid Build Coastguard Worker cupsdSetString(&printer->geo_location, attr->values[0].string.text);
10630*5e7646d2SAndroid Build Coastguard Worker changed = 1;
10631*5e7646d2SAndroid Build Coastguard Worker }
10632*5e7646d2SAndroid Build Coastguard Worker
10633*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippFindAttribute(con->request, "printer-organization", IPP_TAG_TEXT)) != NULL)
10634*5e7646d2SAndroid Build Coastguard Worker {
10635*5e7646d2SAndroid Build Coastguard Worker cupsdSetString(&printer->organization, attr->values[0].string.text);
10636*5e7646d2SAndroid Build Coastguard Worker changed = 1;
10637*5e7646d2SAndroid Build Coastguard Worker }
10638*5e7646d2SAndroid Build Coastguard Worker
10639*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippFindAttribute(con->request, "printer-organizational-unit", IPP_TAG_TEXT)) != NULL)
10640*5e7646d2SAndroid Build Coastguard Worker {
10641*5e7646d2SAndroid Build Coastguard Worker cupsdSetString(&printer->organizational_unit, attr->values[0].string.text);
10642*5e7646d2SAndroid Build Coastguard Worker changed = 1;
10643*5e7646d2SAndroid Build Coastguard Worker }
10644*5e7646d2SAndroid Build Coastguard Worker
10645*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippFindAttribute(con->request, "printer-info",
10646*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_TEXT)) != NULL)
10647*5e7646d2SAndroid Build Coastguard Worker {
10648*5e7646d2SAndroid Build Coastguard Worker cupsdSetString(&printer->info, attr->values[0].string.text);
10649*5e7646d2SAndroid Build Coastguard Worker changed = 1;
10650*5e7646d2SAndroid Build Coastguard Worker }
10651*5e7646d2SAndroid Build Coastguard Worker
10652*5e7646d2SAndroid Build Coastguard Worker /*
10653*5e7646d2SAndroid Build Coastguard Worker * Update the printer attributes and return...
10654*5e7646d2SAndroid Build Coastguard Worker */
10655*5e7646d2SAndroid Build Coastguard Worker
10656*5e7646d2SAndroid Build Coastguard Worker if (changed)
10657*5e7646d2SAndroid Build Coastguard Worker {
10658*5e7646d2SAndroid Build Coastguard Worker printer->config_time = time(NULL);
10659*5e7646d2SAndroid Build Coastguard Worker
10660*5e7646d2SAndroid Build Coastguard Worker cupsdSetPrinterAttrs(printer);
10661*5e7646d2SAndroid Build Coastguard Worker cupsdMarkDirty(CUPSD_DIRTY_PRINTERS);
10662*5e7646d2SAndroid Build Coastguard Worker
10663*5e7646d2SAndroid Build Coastguard Worker cupsdAddEvent(CUPSD_EVENT_PRINTER_CONFIG, printer, NULL,
10664*5e7646d2SAndroid Build Coastguard Worker "Printer \"%s\" description or location changed by \"%s\".",
10665*5e7646d2SAndroid Build Coastguard Worker printer->name, get_username(con));
10666*5e7646d2SAndroid Build Coastguard Worker
10667*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_INFO,
10668*5e7646d2SAndroid Build Coastguard Worker "Printer \"%s\" description or location changed by \"%s\".",
10669*5e7646d2SAndroid Build Coastguard Worker printer->name, get_username(con));
10670*5e7646d2SAndroid Build Coastguard Worker }
10671*5e7646d2SAndroid Build Coastguard Worker
10672*5e7646d2SAndroid Build Coastguard Worker con->response->request.status.status_code = IPP_OK;
10673*5e7646d2SAndroid Build Coastguard Worker }
10674*5e7646d2SAndroid Build Coastguard Worker
10675*5e7646d2SAndroid Build Coastguard Worker
10676*5e7646d2SAndroid Build Coastguard Worker /*
10677*5e7646d2SAndroid Build Coastguard Worker * 'set_printer_defaults()' - Set printer default options from a request.
10678*5e7646d2SAndroid Build Coastguard Worker */
10679*5e7646d2SAndroid Build Coastguard Worker
10680*5e7646d2SAndroid Build Coastguard Worker static int /* O - 1 on success, 0 on failure */
set_printer_defaults(cupsd_client_t * con,cupsd_printer_t * printer)10681*5e7646d2SAndroid Build Coastguard Worker set_printer_defaults(
10682*5e7646d2SAndroid Build Coastguard Worker cupsd_client_t *con, /* I - Client connection */
10683*5e7646d2SAndroid Build Coastguard Worker cupsd_printer_t *printer) /* I - Printer */
10684*5e7646d2SAndroid Build Coastguard Worker {
10685*5e7646d2SAndroid Build Coastguard Worker int i; /* Looping var */
10686*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *attr; /* Current attribute */
10687*5e7646d2SAndroid Build Coastguard Worker size_t namelen; /* Length of attribute name */
10688*5e7646d2SAndroid Build Coastguard Worker char name[256], /* New attribute name */
10689*5e7646d2SAndroid Build Coastguard Worker value[256]; /* String version of integer attrs */
10690*5e7646d2SAndroid Build Coastguard Worker
10691*5e7646d2SAndroid Build Coastguard Worker
10692*5e7646d2SAndroid Build Coastguard Worker for (attr = con->request->attrs; attr; attr = attr->next)
10693*5e7646d2SAndroid Build Coastguard Worker {
10694*5e7646d2SAndroid Build Coastguard Worker /*
10695*5e7646d2SAndroid Build Coastguard Worker * Skip non-printer attributes...
10696*5e7646d2SAndroid Build Coastguard Worker */
10697*5e7646d2SAndroid Build Coastguard Worker
10698*5e7646d2SAndroid Build Coastguard Worker if (attr->group_tag != IPP_TAG_PRINTER || !attr->name)
10699*5e7646d2SAndroid Build Coastguard Worker continue;
10700*5e7646d2SAndroid Build Coastguard Worker
10701*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG2, "set_printer_defaults: %s", attr->name);
10702*5e7646d2SAndroid Build Coastguard Worker
10703*5e7646d2SAndroid Build Coastguard Worker if (!strcmp(attr->name, "job-sheets-default"))
10704*5e7646d2SAndroid Build Coastguard Worker {
10705*5e7646d2SAndroid Build Coastguard Worker /*
10706*5e7646d2SAndroid Build Coastguard Worker * Only allow keywords and names...
10707*5e7646d2SAndroid Build Coastguard Worker */
10708*5e7646d2SAndroid Build Coastguard Worker
10709*5e7646d2SAndroid Build Coastguard Worker if (attr->value_tag != IPP_TAG_NAME && attr->value_tag != IPP_TAG_KEYWORD)
10710*5e7646d2SAndroid Build Coastguard Worker continue;
10711*5e7646d2SAndroid Build Coastguard Worker
10712*5e7646d2SAndroid Build Coastguard Worker /*
10713*5e7646d2SAndroid Build Coastguard Worker * Only allow job-sheets-default to be set when running without a
10714*5e7646d2SAndroid Build Coastguard Worker * system high classification level...
10715*5e7646d2SAndroid Build Coastguard Worker */
10716*5e7646d2SAndroid Build Coastguard Worker
10717*5e7646d2SAndroid Build Coastguard Worker if (Classification)
10718*5e7646d2SAndroid Build Coastguard Worker continue;
10719*5e7646d2SAndroid Build Coastguard Worker
10720*5e7646d2SAndroid Build Coastguard Worker cupsdSetString(&printer->job_sheets[0], attr->values[0].string.text);
10721*5e7646d2SAndroid Build Coastguard Worker
10722*5e7646d2SAndroid Build Coastguard Worker if (attr->num_values > 1)
10723*5e7646d2SAndroid Build Coastguard Worker cupsdSetString(&printer->job_sheets[1], attr->values[1].string.text);
10724*5e7646d2SAndroid Build Coastguard Worker else
10725*5e7646d2SAndroid Build Coastguard Worker cupsdSetString(&printer->job_sheets[1], "none");
10726*5e7646d2SAndroid Build Coastguard Worker }
10727*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(attr->name, "requesting-user-name-allowed"))
10728*5e7646d2SAndroid Build Coastguard Worker {
10729*5e7646d2SAndroid Build Coastguard Worker cupsdFreeStrings(&(printer->users));
10730*5e7646d2SAndroid Build Coastguard Worker
10731*5e7646d2SAndroid Build Coastguard Worker printer->deny_users = 0;
10732*5e7646d2SAndroid Build Coastguard Worker
10733*5e7646d2SAndroid Build Coastguard Worker if (attr->value_tag == IPP_TAG_NAME &&
10734*5e7646d2SAndroid Build Coastguard Worker (attr->num_values > 1 ||
10735*5e7646d2SAndroid Build Coastguard Worker strcmp(attr->values[0].string.text, "all")))
10736*5e7646d2SAndroid Build Coastguard Worker {
10737*5e7646d2SAndroid Build Coastguard Worker for (i = 0; i < attr->num_values; i ++)
10738*5e7646d2SAndroid Build Coastguard Worker cupsdAddString(&(printer->users), attr->values[i].string.text);
10739*5e7646d2SAndroid Build Coastguard Worker }
10740*5e7646d2SAndroid Build Coastguard Worker }
10741*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(attr->name, "requesting-user-name-denied"))
10742*5e7646d2SAndroid Build Coastguard Worker {
10743*5e7646d2SAndroid Build Coastguard Worker cupsdFreeStrings(&(printer->users));
10744*5e7646d2SAndroid Build Coastguard Worker
10745*5e7646d2SAndroid Build Coastguard Worker printer->deny_users = 1;
10746*5e7646d2SAndroid Build Coastguard Worker
10747*5e7646d2SAndroid Build Coastguard Worker if (attr->value_tag == IPP_TAG_NAME &&
10748*5e7646d2SAndroid Build Coastguard Worker (attr->num_values > 1 ||
10749*5e7646d2SAndroid Build Coastguard Worker strcmp(attr->values[0].string.text, "none")))
10750*5e7646d2SAndroid Build Coastguard Worker {
10751*5e7646d2SAndroid Build Coastguard Worker for (i = 0; i < attr->num_values; i ++)
10752*5e7646d2SAndroid Build Coastguard Worker cupsdAddString(&(printer->users), attr->values[i].string.text);
10753*5e7646d2SAndroid Build Coastguard Worker }
10754*5e7646d2SAndroid Build Coastguard Worker }
10755*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(attr->name, "job-quota-period"))
10756*5e7646d2SAndroid Build Coastguard Worker {
10757*5e7646d2SAndroid Build Coastguard Worker if (attr->value_tag != IPP_TAG_INTEGER)
10758*5e7646d2SAndroid Build Coastguard Worker continue;
10759*5e7646d2SAndroid Build Coastguard Worker
10760*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG, "Setting job-quota-period to %d...",
10761*5e7646d2SAndroid Build Coastguard Worker attr->values[0].integer);
10762*5e7646d2SAndroid Build Coastguard Worker cupsdFreeQuotas(printer);
10763*5e7646d2SAndroid Build Coastguard Worker
10764*5e7646d2SAndroid Build Coastguard Worker printer->quota_period = attr->values[0].integer;
10765*5e7646d2SAndroid Build Coastguard Worker }
10766*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(attr->name, "job-k-limit"))
10767*5e7646d2SAndroid Build Coastguard Worker {
10768*5e7646d2SAndroid Build Coastguard Worker if (attr->value_tag != IPP_TAG_INTEGER)
10769*5e7646d2SAndroid Build Coastguard Worker continue;
10770*5e7646d2SAndroid Build Coastguard Worker
10771*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG, "Setting job-k-limit to %d...",
10772*5e7646d2SAndroid Build Coastguard Worker attr->values[0].integer);
10773*5e7646d2SAndroid Build Coastguard Worker cupsdFreeQuotas(printer);
10774*5e7646d2SAndroid Build Coastguard Worker
10775*5e7646d2SAndroid Build Coastguard Worker printer->k_limit = attr->values[0].integer;
10776*5e7646d2SAndroid Build Coastguard Worker }
10777*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(attr->name, "job-page-limit"))
10778*5e7646d2SAndroid Build Coastguard Worker {
10779*5e7646d2SAndroid Build Coastguard Worker if (attr->value_tag != IPP_TAG_INTEGER)
10780*5e7646d2SAndroid Build Coastguard Worker continue;
10781*5e7646d2SAndroid Build Coastguard Worker
10782*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG, "Setting job-page-limit to %d...",
10783*5e7646d2SAndroid Build Coastguard Worker attr->values[0].integer);
10784*5e7646d2SAndroid Build Coastguard Worker cupsdFreeQuotas(printer);
10785*5e7646d2SAndroid Build Coastguard Worker
10786*5e7646d2SAndroid Build Coastguard Worker printer->page_limit = attr->values[0].integer;
10787*5e7646d2SAndroid Build Coastguard Worker }
10788*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(attr->name, "printer-op-policy"))
10789*5e7646d2SAndroid Build Coastguard Worker {
10790*5e7646d2SAndroid Build Coastguard Worker cupsd_policy_t *p; /* Policy */
10791*5e7646d2SAndroid Build Coastguard Worker
10792*5e7646d2SAndroid Build Coastguard Worker
10793*5e7646d2SAndroid Build Coastguard Worker if (attr->value_tag != IPP_TAG_NAME)
10794*5e7646d2SAndroid Build Coastguard Worker continue;
10795*5e7646d2SAndroid Build Coastguard Worker
10796*5e7646d2SAndroid Build Coastguard Worker if ((p = cupsdFindPolicy(attr->values[0].string.text)) != NULL)
10797*5e7646d2SAndroid Build Coastguard Worker {
10798*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG,
10799*5e7646d2SAndroid Build Coastguard Worker "Setting printer-op-policy to \"%s\"...",
10800*5e7646d2SAndroid Build Coastguard Worker attr->values[0].string.text);
10801*5e7646d2SAndroid Build Coastguard Worker cupsdSetString(&printer->op_policy, attr->values[0].string.text);
10802*5e7646d2SAndroid Build Coastguard Worker printer->op_policy_ptr = p;
10803*5e7646d2SAndroid Build Coastguard Worker }
10804*5e7646d2SAndroid Build Coastguard Worker else
10805*5e7646d2SAndroid Build Coastguard Worker {
10806*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_NOT_POSSIBLE,
10807*5e7646d2SAndroid Build Coastguard Worker _("Unknown printer-op-policy \"%s\"."),
10808*5e7646d2SAndroid Build Coastguard Worker attr->values[0].string.text);
10809*5e7646d2SAndroid Build Coastguard Worker return (0);
10810*5e7646d2SAndroid Build Coastguard Worker }
10811*5e7646d2SAndroid Build Coastguard Worker }
10812*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(attr->name, "printer-error-policy"))
10813*5e7646d2SAndroid Build Coastguard Worker {
10814*5e7646d2SAndroid Build Coastguard Worker if (attr->value_tag != IPP_TAG_NAME && attr->value_tag != IPP_TAG_KEYWORD)
10815*5e7646d2SAndroid Build Coastguard Worker continue;
10816*5e7646d2SAndroid Build Coastguard Worker
10817*5e7646d2SAndroid Build Coastguard Worker if (strcmp(attr->values[0].string.text, "retry-current-job") &&
10818*5e7646d2SAndroid Build Coastguard Worker ((printer->type & CUPS_PRINTER_CLASS) ||
10819*5e7646d2SAndroid Build Coastguard Worker (strcmp(attr->values[0].string.text, "abort-job") &&
10820*5e7646d2SAndroid Build Coastguard Worker strcmp(attr->values[0].string.text, "retry-job") &&
10821*5e7646d2SAndroid Build Coastguard Worker strcmp(attr->values[0].string.text, "stop-printer"))))
10822*5e7646d2SAndroid Build Coastguard Worker {
10823*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_NOT_POSSIBLE,
10824*5e7646d2SAndroid Build Coastguard Worker _("Unknown printer-error-policy \"%s\"."),
10825*5e7646d2SAndroid Build Coastguard Worker attr->values[0].string.text);
10826*5e7646d2SAndroid Build Coastguard Worker return (0);
10827*5e7646d2SAndroid Build Coastguard Worker }
10828*5e7646d2SAndroid Build Coastguard Worker
10829*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG,
10830*5e7646d2SAndroid Build Coastguard Worker "Setting printer-error-policy to \"%s\"...",
10831*5e7646d2SAndroid Build Coastguard Worker attr->values[0].string.text);
10832*5e7646d2SAndroid Build Coastguard Worker cupsdSetString(&printer->error_policy, attr->values[0].string.text);
10833*5e7646d2SAndroid Build Coastguard Worker }
10834*5e7646d2SAndroid Build Coastguard Worker
10835*5e7646d2SAndroid Build Coastguard Worker /*
10836*5e7646d2SAndroid Build Coastguard Worker * Skip any other non-default attributes...
10837*5e7646d2SAndroid Build Coastguard Worker */
10838*5e7646d2SAndroid Build Coastguard Worker
10839*5e7646d2SAndroid Build Coastguard Worker namelen = strlen(attr->name);
10840*5e7646d2SAndroid Build Coastguard Worker if (namelen < 9 || strcmp(attr->name + namelen - 8, "-default") ||
10841*5e7646d2SAndroid Build Coastguard Worker namelen > (sizeof(name) - 1) || attr->num_values != 1)
10842*5e7646d2SAndroid Build Coastguard Worker continue;
10843*5e7646d2SAndroid Build Coastguard Worker
10844*5e7646d2SAndroid Build Coastguard Worker /*
10845*5e7646d2SAndroid Build Coastguard Worker * OK, anything else must be a user-defined default...
10846*5e7646d2SAndroid Build Coastguard Worker */
10847*5e7646d2SAndroid Build Coastguard Worker
10848*5e7646d2SAndroid Build Coastguard Worker strlcpy(name, attr->name, sizeof(name));
10849*5e7646d2SAndroid Build Coastguard Worker name[namelen - 8] = '\0'; /* Strip "-default" */
10850*5e7646d2SAndroid Build Coastguard Worker
10851*5e7646d2SAndroid Build Coastguard Worker switch (attr->value_tag)
10852*5e7646d2SAndroid Build Coastguard Worker {
10853*5e7646d2SAndroid Build Coastguard Worker case IPP_TAG_DELETEATTR :
10854*5e7646d2SAndroid Build Coastguard Worker printer->num_options = cupsRemoveOption(name,
10855*5e7646d2SAndroid Build Coastguard Worker printer->num_options,
10856*5e7646d2SAndroid Build Coastguard Worker &(printer->options));
10857*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG,
10858*5e7646d2SAndroid Build Coastguard Worker "Deleting %s", attr->name);
10859*5e7646d2SAndroid Build Coastguard Worker break;
10860*5e7646d2SAndroid Build Coastguard Worker
10861*5e7646d2SAndroid Build Coastguard Worker case IPP_TAG_NAME :
10862*5e7646d2SAndroid Build Coastguard Worker case IPP_TAG_TEXT :
10863*5e7646d2SAndroid Build Coastguard Worker case IPP_TAG_KEYWORD :
10864*5e7646d2SAndroid Build Coastguard Worker case IPP_TAG_URI :
10865*5e7646d2SAndroid Build Coastguard Worker printer->num_options = cupsAddOption(name,
10866*5e7646d2SAndroid Build Coastguard Worker attr->values[0].string.text,
10867*5e7646d2SAndroid Build Coastguard Worker printer->num_options,
10868*5e7646d2SAndroid Build Coastguard Worker &(printer->options));
10869*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG,
10870*5e7646d2SAndroid Build Coastguard Worker "Setting %s to \"%s\"...", attr->name,
10871*5e7646d2SAndroid Build Coastguard Worker attr->values[0].string.text);
10872*5e7646d2SAndroid Build Coastguard Worker break;
10873*5e7646d2SAndroid Build Coastguard Worker
10874*5e7646d2SAndroid Build Coastguard Worker case IPP_TAG_BOOLEAN :
10875*5e7646d2SAndroid Build Coastguard Worker printer->num_options = cupsAddOption(name,
10876*5e7646d2SAndroid Build Coastguard Worker attr->values[0].boolean ?
10877*5e7646d2SAndroid Build Coastguard Worker "true" : "false",
10878*5e7646d2SAndroid Build Coastguard Worker printer->num_options,
10879*5e7646d2SAndroid Build Coastguard Worker &(printer->options));
10880*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG,
10881*5e7646d2SAndroid Build Coastguard Worker "Setting %s to %s...", attr->name,
10882*5e7646d2SAndroid Build Coastguard Worker attr->values[0].boolean ? "true" : "false");
10883*5e7646d2SAndroid Build Coastguard Worker break;
10884*5e7646d2SAndroid Build Coastguard Worker
10885*5e7646d2SAndroid Build Coastguard Worker case IPP_TAG_INTEGER :
10886*5e7646d2SAndroid Build Coastguard Worker case IPP_TAG_ENUM :
10887*5e7646d2SAndroid Build Coastguard Worker printer->num_options = cupsAddIntegerOption(name, attr->values[0].integer, printer->num_options, &(printer->options));
10888*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG,
10889*5e7646d2SAndroid Build Coastguard Worker "Setting %s to %s...", attr->name, value);
10890*5e7646d2SAndroid Build Coastguard Worker break;
10891*5e7646d2SAndroid Build Coastguard Worker
10892*5e7646d2SAndroid Build Coastguard Worker case IPP_TAG_RANGE :
10893*5e7646d2SAndroid Build Coastguard Worker snprintf(value, sizeof(value), "%d-%d", attr->values[0].range.lower, attr->values[0].range.upper);
10894*5e7646d2SAndroid Build Coastguard Worker printer->num_options = cupsAddOption(name, value,
10895*5e7646d2SAndroid Build Coastguard Worker printer->num_options,
10896*5e7646d2SAndroid Build Coastguard Worker &(printer->options));
10897*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG,
10898*5e7646d2SAndroid Build Coastguard Worker "Setting %s to %s...", attr->name, value);
10899*5e7646d2SAndroid Build Coastguard Worker break;
10900*5e7646d2SAndroid Build Coastguard Worker
10901*5e7646d2SAndroid Build Coastguard Worker case IPP_TAG_RESOLUTION :
10902*5e7646d2SAndroid Build Coastguard Worker snprintf(value, sizeof(value), "%dx%d%s", attr->values[0].resolution.xres, attr->values[0].resolution.yres, attr->values[0].resolution.units == IPP_RES_PER_INCH ? "dpi" : "dpcm");
10903*5e7646d2SAndroid Build Coastguard Worker printer->num_options = cupsAddOption(name, value,
10904*5e7646d2SAndroid Build Coastguard Worker printer->num_options,
10905*5e7646d2SAndroid Build Coastguard Worker &(printer->options));
10906*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG,
10907*5e7646d2SAndroid Build Coastguard Worker "Setting %s to %s...", attr->name, value);
10908*5e7646d2SAndroid Build Coastguard Worker break;
10909*5e7646d2SAndroid Build Coastguard Worker
10910*5e7646d2SAndroid Build Coastguard Worker default :
10911*5e7646d2SAndroid Build Coastguard Worker /* Do nothing for other values */
10912*5e7646d2SAndroid Build Coastguard Worker break;
10913*5e7646d2SAndroid Build Coastguard Worker }
10914*5e7646d2SAndroid Build Coastguard Worker }
10915*5e7646d2SAndroid Build Coastguard Worker
10916*5e7646d2SAndroid Build Coastguard Worker return (1);
10917*5e7646d2SAndroid Build Coastguard Worker }
10918*5e7646d2SAndroid Build Coastguard Worker
10919*5e7646d2SAndroid Build Coastguard Worker
10920*5e7646d2SAndroid Build Coastguard Worker /*
10921*5e7646d2SAndroid Build Coastguard Worker * 'start_printer()' - Start a printer.
10922*5e7646d2SAndroid Build Coastguard Worker */
10923*5e7646d2SAndroid Build Coastguard Worker
10924*5e7646d2SAndroid Build Coastguard Worker static void
start_printer(cupsd_client_t * con,ipp_attribute_t * uri)10925*5e7646d2SAndroid Build Coastguard Worker start_printer(cupsd_client_t *con, /* I - Client connection */
10926*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *uri) /* I - Printer URI */
10927*5e7646d2SAndroid Build Coastguard Worker {
10928*5e7646d2SAndroid Build Coastguard Worker int i; /* Temporary variable */
10929*5e7646d2SAndroid Build Coastguard Worker http_status_t status; /* Policy status */
10930*5e7646d2SAndroid Build Coastguard Worker cups_ptype_t dtype; /* Destination type (printer/class) */
10931*5e7646d2SAndroid Build Coastguard Worker cupsd_printer_t *printer; /* Printer data */
10932*5e7646d2SAndroid Build Coastguard Worker
10933*5e7646d2SAndroid Build Coastguard Worker
10934*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG2, "start_printer(%p[%d], %s)", con,
10935*5e7646d2SAndroid Build Coastguard Worker con->number, uri->values[0].string.text);
10936*5e7646d2SAndroid Build Coastguard Worker
10937*5e7646d2SAndroid Build Coastguard Worker /*
10938*5e7646d2SAndroid Build Coastguard Worker * Is the destination valid?
10939*5e7646d2SAndroid Build Coastguard Worker */
10940*5e7646d2SAndroid Build Coastguard Worker
10941*5e7646d2SAndroid Build Coastguard Worker if (!cupsdValidateDest(uri->values[0].string.text, &dtype, &printer))
10942*5e7646d2SAndroid Build Coastguard Worker {
10943*5e7646d2SAndroid Build Coastguard Worker /*
10944*5e7646d2SAndroid Build Coastguard Worker * Bad URI...
10945*5e7646d2SAndroid Build Coastguard Worker */
10946*5e7646d2SAndroid Build Coastguard Worker
10947*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_NOT_FOUND,
10948*5e7646d2SAndroid Build Coastguard Worker _("The printer or class does not exist."));
10949*5e7646d2SAndroid Build Coastguard Worker return;
10950*5e7646d2SAndroid Build Coastguard Worker }
10951*5e7646d2SAndroid Build Coastguard Worker
10952*5e7646d2SAndroid Build Coastguard Worker /*
10953*5e7646d2SAndroid Build Coastguard Worker * Check policy...
10954*5e7646d2SAndroid Build Coastguard Worker */
10955*5e7646d2SAndroid Build Coastguard Worker
10956*5e7646d2SAndroid Build Coastguard Worker if ((status = cupsdCheckPolicy(printer->op_policy_ptr, con, NULL)) != HTTP_OK)
10957*5e7646d2SAndroid Build Coastguard Worker {
10958*5e7646d2SAndroid Build Coastguard Worker send_http_error(con, status, printer);
10959*5e7646d2SAndroid Build Coastguard Worker return;
10960*5e7646d2SAndroid Build Coastguard Worker }
10961*5e7646d2SAndroid Build Coastguard Worker
10962*5e7646d2SAndroid Build Coastguard Worker /*
10963*5e7646d2SAndroid Build Coastguard Worker * Start the printer...
10964*5e7646d2SAndroid Build Coastguard Worker */
10965*5e7646d2SAndroid Build Coastguard Worker
10966*5e7646d2SAndroid Build Coastguard Worker printer->state_message[0] = '\0';
10967*5e7646d2SAndroid Build Coastguard Worker
10968*5e7646d2SAndroid Build Coastguard Worker cupsdStartPrinter(printer, 1);
10969*5e7646d2SAndroid Build Coastguard Worker
10970*5e7646d2SAndroid Build Coastguard Worker if (dtype & CUPS_PRINTER_CLASS)
10971*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_INFO, "Class \"%s\" started by \"%s\".",
10972*5e7646d2SAndroid Build Coastguard Worker printer->name, get_username(con));
10973*5e7646d2SAndroid Build Coastguard Worker else
10974*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_INFO, "Printer \"%s\" started by \"%s\".",
10975*5e7646d2SAndroid Build Coastguard Worker printer->name, get_username(con));
10976*5e7646d2SAndroid Build Coastguard Worker
10977*5e7646d2SAndroid Build Coastguard Worker cupsdCheckJobs();
10978*5e7646d2SAndroid Build Coastguard Worker
10979*5e7646d2SAndroid Build Coastguard Worker /*
10980*5e7646d2SAndroid Build Coastguard Worker * Check quotas...
10981*5e7646d2SAndroid Build Coastguard Worker */
10982*5e7646d2SAndroid Build Coastguard Worker
10983*5e7646d2SAndroid Build Coastguard Worker if ((i = check_quotas(con, printer)) < 0)
10984*5e7646d2SAndroid Build Coastguard Worker {
10985*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_NOT_POSSIBLE, _("Quota limit reached."));
10986*5e7646d2SAndroid Build Coastguard Worker return;
10987*5e7646d2SAndroid Build Coastguard Worker }
10988*5e7646d2SAndroid Build Coastguard Worker else if (i == 0)
10989*5e7646d2SAndroid Build Coastguard Worker {
10990*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_NOT_AUTHORIZED, _("Not allowed to print."));
10991*5e7646d2SAndroid Build Coastguard Worker return;
10992*5e7646d2SAndroid Build Coastguard Worker }
10993*5e7646d2SAndroid Build Coastguard Worker
10994*5e7646d2SAndroid Build Coastguard Worker /*
10995*5e7646d2SAndroid Build Coastguard Worker * Everything was ok, so return OK status...
10996*5e7646d2SAndroid Build Coastguard Worker */
10997*5e7646d2SAndroid Build Coastguard Worker
10998*5e7646d2SAndroid Build Coastguard Worker con->response->request.status.status_code = IPP_OK;
10999*5e7646d2SAndroid Build Coastguard Worker }
11000*5e7646d2SAndroid Build Coastguard Worker
11001*5e7646d2SAndroid Build Coastguard Worker
11002*5e7646d2SAndroid Build Coastguard Worker /*
11003*5e7646d2SAndroid Build Coastguard Worker * 'stop_printer()' - Stop a printer.
11004*5e7646d2SAndroid Build Coastguard Worker */
11005*5e7646d2SAndroid Build Coastguard Worker
11006*5e7646d2SAndroid Build Coastguard Worker static void
stop_printer(cupsd_client_t * con,ipp_attribute_t * uri)11007*5e7646d2SAndroid Build Coastguard Worker stop_printer(cupsd_client_t *con, /* I - Client connection */
11008*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *uri) /* I - Printer URI */
11009*5e7646d2SAndroid Build Coastguard Worker {
11010*5e7646d2SAndroid Build Coastguard Worker http_status_t status; /* Policy status */
11011*5e7646d2SAndroid Build Coastguard Worker cups_ptype_t dtype; /* Destination type (printer/class) */
11012*5e7646d2SAndroid Build Coastguard Worker cupsd_printer_t *printer; /* Printer data */
11013*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *attr; /* printer-state-message attribute */
11014*5e7646d2SAndroid Build Coastguard Worker
11015*5e7646d2SAndroid Build Coastguard Worker
11016*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG2, "stop_printer(%p[%d], %s)", con,
11017*5e7646d2SAndroid Build Coastguard Worker con->number, uri->values[0].string.text);
11018*5e7646d2SAndroid Build Coastguard Worker
11019*5e7646d2SAndroid Build Coastguard Worker /*
11020*5e7646d2SAndroid Build Coastguard Worker * Is the destination valid?
11021*5e7646d2SAndroid Build Coastguard Worker */
11022*5e7646d2SAndroid Build Coastguard Worker
11023*5e7646d2SAndroid Build Coastguard Worker if (!cupsdValidateDest(uri->values[0].string.text, &dtype, &printer))
11024*5e7646d2SAndroid Build Coastguard Worker {
11025*5e7646d2SAndroid Build Coastguard Worker /*
11026*5e7646d2SAndroid Build Coastguard Worker * Bad URI...
11027*5e7646d2SAndroid Build Coastguard Worker */
11028*5e7646d2SAndroid Build Coastguard Worker
11029*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_NOT_FOUND,
11030*5e7646d2SAndroid Build Coastguard Worker _("The printer or class does not exist."));
11031*5e7646d2SAndroid Build Coastguard Worker return;
11032*5e7646d2SAndroid Build Coastguard Worker }
11033*5e7646d2SAndroid Build Coastguard Worker
11034*5e7646d2SAndroid Build Coastguard Worker /*
11035*5e7646d2SAndroid Build Coastguard Worker * Check policy...
11036*5e7646d2SAndroid Build Coastguard Worker */
11037*5e7646d2SAndroid Build Coastguard Worker
11038*5e7646d2SAndroid Build Coastguard Worker if ((status = cupsdCheckPolicy(printer->op_policy_ptr, con, NULL)) != HTTP_OK)
11039*5e7646d2SAndroid Build Coastguard Worker {
11040*5e7646d2SAndroid Build Coastguard Worker send_http_error(con, status, printer);
11041*5e7646d2SAndroid Build Coastguard Worker return;
11042*5e7646d2SAndroid Build Coastguard Worker }
11043*5e7646d2SAndroid Build Coastguard Worker
11044*5e7646d2SAndroid Build Coastguard Worker /*
11045*5e7646d2SAndroid Build Coastguard Worker * Stop the printer...
11046*5e7646d2SAndroid Build Coastguard Worker */
11047*5e7646d2SAndroid Build Coastguard Worker
11048*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippFindAttribute(con->request, "printer-state-message",
11049*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_TEXT)) == NULL)
11050*5e7646d2SAndroid Build Coastguard Worker strlcpy(printer->state_message, "Paused", sizeof(printer->state_message));
11051*5e7646d2SAndroid Build Coastguard Worker else
11052*5e7646d2SAndroid Build Coastguard Worker {
11053*5e7646d2SAndroid Build Coastguard Worker strlcpy(printer->state_message, attr->values[0].string.text,
11054*5e7646d2SAndroid Build Coastguard Worker sizeof(printer->state_message));
11055*5e7646d2SAndroid Build Coastguard Worker }
11056*5e7646d2SAndroid Build Coastguard Worker
11057*5e7646d2SAndroid Build Coastguard Worker cupsdStopPrinter(printer, 1);
11058*5e7646d2SAndroid Build Coastguard Worker
11059*5e7646d2SAndroid Build Coastguard Worker if (dtype & CUPS_PRINTER_CLASS)
11060*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_INFO, "Class \"%s\" stopped by \"%s\".",
11061*5e7646d2SAndroid Build Coastguard Worker printer->name, get_username(con));
11062*5e7646d2SAndroid Build Coastguard Worker else
11063*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_INFO, "Printer \"%s\" stopped by \"%s\".",
11064*5e7646d2SAndroid Build Coastguard Worker printer->name, get_username(con));
11065*5e7646d2SAndroid Build Coastguard Worker
11066*5e7646d2SAndroid Build Coastguard Worker /*
11067*5e7646d2SAndroid Build Coastguard Worker * Everything was ok, so return OK status...
11068*5e7646d2SAndroid Build Coastguard Worker */
11069*5e7646d2SAndroid Build Coastguard Worker
11070*5e7646d2SAndroid Build Coastguard Worker con->response->request.status.status_code = IPP_OK;
11071*5e7646d2SAndroid Build Coastguard Worker }
11072*5e7646d2SAndroid Build Coastguard Worker
11073*5e7646d2SAndroid Build Coastguard Worker
11074*5e7646d2SAndroid Build Coastguard Worker /*
11075*5e7646d2SAndroid Build Coastguard Worker * 'url_encode_attr()' - URL-encode a string attribute.
11076*5e7646d2SAndroid Build Coastguard Worker */
11077*5e7646d2SAndroid Build Coastguard Worker
11078*5e7646d2SAndroid Build Coastguard Worker static void
url_encode_attr(ipp_attribute_t * attr,char * buffer,size_t bufsize)11079*5e7646d2SAndroid Build Coastguard Worker url_encode_attr(ipp_attribute_t *attr, /* I - Attribute */
11080*5e7646d2SAndroid Build Coastguard Worker char *buffer,/* I - String buffer */
11081*5e7646d2SAndroid Build Coastguard Worker size_t bufsize)/* I - Size of buffer */
11082*5e7646d2SAndroid Build Coastguard Worker {
11083*5e7646d2SAndroid Build Coastguard Worker int i; /* Looping var */
11084*5e7646d2SAndroid Build Coastguard Worker char *bufptr, /* Pointer into buffer */
11085*5e7646d2SAndroid Build Coastguard Worker *bufend; /* End of buffer */
11086*5e7646d2SAndroid Build Coastguard Worker
11087*5e7646d2SAndroid Build Coastguard Worker
11088*5e7646d2SAndroid Build Coastguard Worker strlcpy(buffer, attr->name, bufsize);
11089*5e7646d2SAndroid Build Coastguard Worker bufptr = buffer + strlen(buffer);
11090*5e7646d2SAndroid Build Coastguard Worker bufend = buffer + bufsize - 1;
11091*5e7646d2SAndroid Build Coastguard Worker
11092*5e7646d2SAndroid Build Coastguard Worker for (i = 0; i < attr->num_values; i ++)
11093*5e7646d2SAndroid Build Coastguard Worker {
11094*5e7646d2SAndroid Build Coastguard Worker if (bufptr >= bufend)
11095*5e7646d2SAndroid Build Coastguard Worker break;
11096*5e7646d2SAndroid Build Coastguard Worker
11097*5e7646d2SAndroid Build Coastguard Worker if (i)
11098*5e7646d2SAndroid Build Coastguard Worker *bufptr++ = ',';
11099*5e7646d2SAndroid Build Coastguard Worker else
11100*5e7646d2SAndroid Build Coastguard Worker *bufptr++ = '=';
11101*5e7646d2SAndroid Build Coastguard Worker
11102*5e7646d2SAndroid Build Coastguard Worker if (bufptr >= bufend)
11103*5e7646d2SAndroid Build Coastguard Worker break;
11104*5e7646d2SAndroid Build Coastguard Worker
11105*5e7646d2SAndroid Build Coastguard Worker *bufptr++ = '\'';
11106*5e7646d2SAndroid Build Coastguard Worker
11107*5e7646d2SAndroid Build Coastguard Worker bufptr = url_encode_string(attr->values[i].string.text, bufptr, (size_t)(bufend - bufptr + 1));
11108*5e7646d2SAndroid Build Coastguard Worker
11109*5e7646d2SAndroid Build Coastguard Worker if (bufptr >= bufend)
11110*5e7646d2SAndroid Build Coastguard Worker break;
11111*5e7646d2SAndroid Build Coastguard Worker
11112*5e7646d2SAndroid Build Coastguard Worker *bufptr++ = '\'';
11113*5e7646d2SAndroid Build Coastguard Worker }
11114*5e7646d2SAndroid Build Coastguard Worker
11115*5e7646d2SAndroid Build Coastguard Worker *bufptr = '\0';
11116*5e7646d2SAndroid Build Coastguard Worker }
11117*5e7646d2SAndroid Build Coastguard Worker
11118*5e7646d2SAndroid Build Coastguard Worker
11119*5e7646d2SAndroid Build Coastguard Worker /*
11120*5e7646d2SAndroid Build Coastguard Worker * 'url_encode_string()' - URL-encode a string.
11121*5e7646d2SAndroid Build Coastguard Worker */
11122*5e7646d2SAndroid Build Coastguard Worker
11123*5e7646d2SAndroid Build Coastguard Worker static char * /* O - End of string */
url_encode_string(const char * s,char * buffer,size_t bufsize)11124*5e7646d2SAndroid Build Coastguard Worker url_encode_string(const char *s, /* I - String */
11125*5e7646d2SAndroid Build Coastguard Worker char *buffer, /* I - String buffer */
11126*5e7646d2SAndroid Build Coastguard Worker size_t bufsize) /* I - Size of buffer */
11127*5e7646d2SAndroid Build Coastguard Worker {
11128*5e7646d2SAndroid Build Coastguard Worker char *bufptr, /* Pointer into buffer */
11129*5e7646d2SAndroid Build Coastguard Worker *bufend; /* End of buffer */
11130*5e7646d2SAndroid Build Coastguard Worker static const char *hex = "0123456789ABCDEF";
11131*5e7646d2SAndroid Build Coastguard Worker /* Hex digits */
11132*5e7646d2SAndroid Build Coastguard Worker
11133*5e7646d2SAndroid Build Coastguard Worker
11134*5e7646d2SAndroid Build Coastguard Worker bufptr = buffer;
11135*5e7646d2SAndroid Build Coastguard Worker bufend = buffer + bufsize - 1;
11136*5e7646d2SAndroid Build Coastguard Worker
11137*5e7646d2SAndroid Build Coastguard Worker while (*s && bufptr < bufend)
11138*5e7646d2SAndroid Build Coastguard Worker {
11139*5e7646d2SAndroid Build Coastguard Worker if (*s == ' ' || *s == '%' || *s == '+')
11140*5e7646d2SAndroid Build Coastguard Worker {
11141*5e7646d2SAndroid Build Coastguard Worker if (bufptr >= (bufend - 2))
11142*5e7646d2SAndroid Build Coastguard Worker break;
11143*5e7646d2SAndroid Build Coastguard Worker
11144*5e7646d2SAndroid Build Coastguard Worker *bufptr++ = '%';
11145*5e7646d2SAndroid Build Coastguard Worker *bufptr++ = hex[(*s >> 4) & 15];
11146*5e7646d2SAndroid Build Coastguard Worker *bufptr++ = hex[*s & 15];
11147*5e7646d2SAndroid Build Coastguard Worker
11148*5e7646d2SAndroid Build Coastguard Worker s ++;
11149*5e7646d2SAndroid Build Coastguard Worker }
11150*5e7646d2SAndroid Build Coastguard Worker else if (*s == '\'' || *s == '\\')
11151*5e7646d2SAndroid Build Coastguard Worker {
11152*5e7646d2SAndroid Build Coastguard Worker if (bufptr >= (bufend - 1))
11153*5e7646d2SAndroid Build Coastguard Worker break;
11154*5e7646d2SAndroid Build Coastguard Worker
11155*5e7646d2SAndroid Build Coastguard Worker *bufptr++ = '\\';
11156*5e7646d2SAndroid Build Coastguard Worker *bufptr++ = *s++;
11157*5e7646d2SAndroid Build Coastguard Worker }
11158*5e7646d2SAndroid Build Coastguard Worker else
11159*5e7646d2SAndroid Build Coastguard Worker *bufptr++ = *s++;
11160*5e7646d2SAndroid Build Coastguard Worker }
11161*5e7646d2SAndroid Build Coastguard Worker
11162*5e7646d2SAndroid Build Coastguard Worker *bufptr = '\0';
11163*5e7646d2SAndroid Build Coastguard Worker
11164*5e7646d2SAndroid Build Coastguard Worker return (bufptr);
11165*5e7646d2SAndroid Build Coastguard Worker }
11166*5e7646d2SAndroid Build Coastguard Worker
11167*5e7646d2SAndroid Build Coastguard Worker
11168*5e7646d2SAndroid Build Coastguard Worker /*
11169*5e7646d2SAndroid Build Coastguard Worker * 'user_allowed()' - See if a user is allowed to print to a queue.
11170*5e7646d2SAndroid Build Coastguard Worker */
11171*5e7646d2SAndroid Build Coastguard Worker
11172*5e7646d2SAndroid Build Coastguard Worker static int /* O - 0 if not allowed, 1 if allowed */
user_allowed(cupsd_printer_t * p,const char * username)11173*5e7646d2SAndroid Build Coastguard Worker user_allowed(cupsd_printer_t *p, /* I - Printer or class */
11174*5e7646d2SAndroid Build Coastguard Worker const char *username) /* I - Username */
11175*5e7646d2SAndroid Build Coastguard Worker {
11176*5e7646d2SAndroid Build Coastguard Worker struct passwd *pw; /* User password data */
11177*5e7646d2SAndroid Build Coastguard Worker char baseuser[256], /* Base username */
11178*5e7646d2SAndroid Build Coastguard Worker *baseptr, /* Pointer to "@" in base username */
11179*5e7646d2SAndroid Build Coastguard Worker *name; /* Current user name */
11180*5e7646d2SAndroid Build Coastguard Worker
11181*5e7646d2SAndroid Build Coastguard Worker
11182*5e7646d2SAndroid Build Coastguard Worker if (cupsArrayCount(p->users) == 0)
11183*5e7646d2SAndroid Build Coastguard Worker return (1);
11184*5e7646d2SAndroid Build Coastguard Worker
11185*5e7646d2SAndroid Build Coastguard Worker if (!strcmp(username, "root"))
11186*5e7646d2SAndroid Build Coastguard Worker return (1);
11187*5e7646d2SAndroid Build Coastguard Worker
11188*5e7646d2SAndroid Build Coastguard Worker if (strchr(username, '@'))
11189*5e7646d2SAndroid Build Coastguard Worker {
11190*5e7646d2SAndroid Build Coastguard Worker /*
11191*5e7646d2SAndroid Build Coastguard Worker * Strip @REALM for username check...
11192*5e7646d2SAndroid Build Coastguard Worker */
11193*5e7646d2SAndroid Build Coastguard Worker
11194*5e7646d2SAndroid Build Coastguard Worker strlcpy(baseuser, username, sizeof(baseuser));
11195*5e7646d2SAndroid Build Coastguard Worker
11196*5e7646d2SAndroid Build Coastguard Worker if ((baseptr = strchr(baseuser, '@')) != NULL)
11197*5e7646d2SAndroid Build Coastguard Worker *baseptr = '\0';
11198*5e7646d2SAndroid Build Coastguard Worker
11199*5e7646d2SAndroid Build Coastguard Worker username = baseuser;
11200*5e7646d2SAndroid Build Coastguard Worker }
11201*5e7646d2SAndroid Build Coastguard Worker
11202*5e7646d2SAndroid Build Coastguard Worker pw = getpwnam(username);
11203*5e7646d2SAndroid Build Coastguard Worker endpwent();
11204*5e7646d2SAndroid Build Coastguard Worker
11205*5e7646d2SAndroid Build Coastguard Worker for (name = (char *)cupsArrayFirst(p->users);
11206*5e7646d2SAndroid Build Coastguard Worker name;
11207*5e7646d2SAndroid Build Coastguard Worker name = (char *)cupsArrayNext(p->users))
11208*5e7646d2SAndroid Build Coastguard Worker {
11209*5e7646d2SAndroid Build Coastguard Worker if (name[0] == '@')
11210*5e7646d2SAndroid Build Coastguard Worker {
11211*5e7646d2SAndroid Build Coastguard Worker /*
11212*5e7646d2SAndroid Build Coastguard Worker * Check group membership...
11213*5e7646d2SAndroid Build Coastguard Worker */
11214*5e7646d2SAndroid Build Coastguard Worker
11215*5e7646d2SAndroid Build Coastguard Worker if (cupsdCheckGroup(username, pw, name + 1))
11216*5e7646d2SAndroid Build Coastguard Worker break;
11217*5e7646d2SAndroid Build Coastguard Worker }
11218*5e7646d2SAndroid Build Coastguard Worker else if (name[0] == '#')
11219*5e7646d2SAndroid Build Coastguard Worker {
11220*5e7646d2SAndroid Build Coastguard Worker /*
11221*5e7646d2SAndroid Build Coastguard Worker * Check UUID...
11222*5e7646d2SAndroid Build Coastguard Worker */
11223*5e7646d2SAndroid Build Coastguard Worker
11224*5e7646d2SAndroid Build Coastguard Worker if (cupsdCheckGroup(username, pw, name))
11225*5e7646d2SAndroid Build Coastguard Worker break;
11226*5e7646d2SAndroid Build Coastguard Worker }
11227*5e7646d2SAndroid Build Coastguard Worker else if (!_cups_strcasecmp(username, name))
11228*5e7646d2SAndroid Build Coastguard Worker break;
11229*5e7646d2SAndroid Build Coastguard Worker }
11230*5e7646d2SAndroid Build Coastguard Worker
11231*5e7646d2SAndroid Build Coastguard Worker return ((name != NULL) != p->deny_users);
11232*5e7646d2SAndroid Build Coastguard Worker }
11233*5e7646d2SAndroid Build Coastguard Worker
11234*5e7646d2SAndroid Build Coastguard Worker
11235*5e7646d2SAndroid Build Coastguard Worker /*
11236*5e7646d2SAndroid Build Coastguard Worker * 'validate_job()' - Validate printer options and destination.
11237*5e7646d2SAndroid Build Coastguard Worker */
11238*5e7646d2SAndroid Build Coastguard Worker
11239*5e7646d2SAndroid Build Coastguard Worker static void
validate_job(cupsd_client_t * con,ipp_attribute_t * uri)11240*5e7646d2SAndroid Build Coastguard Worker validate_job(cupsd_client_t *con, /* I - Client connection */
11241*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *uri) /* I - Printer URI */
11242*5e7646d2SAndroid Build Coastguard Worker {
11243*5e7646d2SAndroid Build Coastguard Worker http_status_t status; /* Policy status */
11244*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *attr; /* Current attribute */
11245*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_SSL
11246*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *auth_info; /* auth-info attribute */
11247*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_SSL */
11248*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *format, /* Document-format attribute */
11249*5e7646d2SAndroid Build Coastguard Worker *name; /* Job-name attribute */
11250*5e7646d2SAndroid Build Coastguard Worker cups_ptype_t dtype; /* Destination type (printer/class) */
11251*5e7646d2SAndroid Build Coastguard Worker char super[MIME_MAX_SUPER],
11252*5e7646d2SAndroid Build Coastguard Worker /* Supertype of file */
11253*5e7646d2SAndroid Build Coastguard Worker type[MIME_MAX_TYPE];
11254*5e7646d2SAndroid Build Coastguard Worker /* Subtype of file */
11255*5e7646d2SAndroid Build Coastguard Worker cupsd_printer_t *printer; /* Printer */
11256*5e7646d2SAndroid Build Coastguard Worker
11257*5e7646d2SAndroid Build Coastguard Worker
11258*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG2, "validate_job(%p[%d], %s)", con,
11259*5e7646d2SAndroid Build Coastguard Worker con->number, uri->values[0].string.text);
11260*5e7646d2SAndroid Build Coastguard Worker
11261*5e7646d2SAndroid Build Coastguard Worker /*
11262*5e7646d2SAndroid Build Coastguard Worker * OK, see if the client is sending the document compressed - CUPS
11263*5e7646d2SAndroid Build Coastguard Worker * doesn't support compression yet...
11264*5e7646d2SAndroid Build Coastguard Worker */
11265*5e7646d2SAndroid Build Coastguard Worker
11266*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippFindAttribute(con->request, "compression",
11267*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_KEYWORD)) != NULL)
11268*5e7646d2SAndroid Build Coastguard Worker {
11269*5e7646d2SAndroid Build Coastguard Worker if (strcmp(attr->values[0].string.text, "none")
11270*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_LIBZ
11271*5e7646d2SAndroid Build Coastguard Worker && strcmp(attr->values[0].string.text, "gzip")
11272*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_LIBZ */
11273*5e7646d2SAndroid Build Coastguard Worker )
11274*5e7646d2SAndroid Build Coastguard Worker {
11275*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_ATTRIBUTES,
11276*5e7646d2SAndroid Build Coastguard Worker _("Unsupported 'compression' value \"%s\"."),
11277*5e7646d2SAndroid Build Coastguard Worker attr->values[0].string.text);
11278*5e7646d2SAndroid Build Coastguard Worker ippAddString(con->response, IPP_TAG_UNSUPPORTED_GROUP, IPP_TAG_KEYWORD,
11279*5e7646d2SAndroid Build Coastguard Worker "compression", NULL, attr->values[0].string.text);
11280*5e7646d2SAndroid Build Coastguard Worker return;
11281*5e7646d2SAndroid Build Coastguard Worker }
11282*5e7646d2SAndroid Build Coastguard Worker }
11283*5e7646d2SAndroid Build Coastguard Worker
11284*5e7646d2SAndroid Build Coastguard Worker /*
11285*5e7646d2SAndroid Build Coastguard Worker * Is it a format we support?
11286*5e7646d2SAndroid Build Coastguard Worker */
11287*5e7646d2SAndroid Build Coastguard Worker
11288*5e7646d2SAndroid Build Coastguard Worker if ((format = ippFindAttribute(con->request, "document-format",
11289*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_MIMETYPE)) != NULL)
11290*5e7646d2SAndroid Build Coastguard Worker {
11291*5e7646d2SAndroid Build Coastguard Worker if (sscanf(format->values[0].string.text, "%15[^/]/%255[^;]",
11292*5e7646d2SAndroid Build Coastguard Worker super, type) != 2)
11293*5e7646d2SAndroid Build Coastguard Worker {
11294*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_BAD_REQUEST,
11295*5e7646d2SAndroid Build Coastguard Worker _("Bad 'document-format' value \"%s\"."),
11296*5e7646d2SAndroid Build Coastguard Worker format->values[0].string.text);
11297*5e7646d2SAndroid Build Coastguard Worker return;
11298*5e7646d2SAndroid Build Coastguard Worker }
11299*5e7646d2SAndroid Build Coastguard Worker
11300*5e7646d2SAndroid Build Coastguard Worker if ((strcmp(super, "application") || strcmp(type, "octet-stream")) &&
11301*5e7646d2SAndroid Build Coastguard Worker !mimeType(MimeDatabase, super, type))
11302*5e7646d2SAndroid Build Coastguard Worker {
11303*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_INFO,
11304*5e7646d2SAndroid Build Coastguard Worker "Hint: Do you have the raw file printing rules enabled?");
11305*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_DOCUMENT_FORMAT,
11306*5e7646d2SAndroid Build Coastguard Worker _("Unsupported 'document-format' value \"%s\"."),
11307*5e7646d2SAndroid Build Coastguard Worker format->values[0].string.text);
11308*5e7646d2SAndroid Build Coastguard Worker ippAddString(con->response, IPP_TAG_UNSUPPORTED_GROUP, IPP_TAG_MIMETYPE,
11309*5e7646d2SAndroid Build Coastguard Worker "document-format", NULL, format->values[0].string.text);
11310*5e7646d2SAndroid Build Coastguard Worker return;
11311*5e7646d2SAndroid Build Coastguard Worker }
11312*5e7646d2SAndroid Build Coastguard Worker }
11313*5e7646d2SAndroid Build Coastguard Worker
11314*5e7646d2SAndroid Build Coastguard Worker /*
11315*5e7646d2SAndroid Build Coastguard Worker * Is the job-hold-until value valid?
11316*5e7646d2SAndroid Build Coastguard Worker */
11317*5e7646d2SAndroid Build Coastguard Worker
11318*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippFindAttribute(con->request, "job-hold-until", IPP_TAG_ZERO)) != NULL && ((ippGetValueTag(attr) != IPP_TAG_KEYWORD && ippGetValueTag(attr) != IPP_TAG_NAME && ippGetValueTag(attr) != IPP_TAG_NAMELANG) || ippGetCount(attr) != 1 || !ippValidateAttribute(attr)))
11319*5e7646d2SAndroid Build Coastguard Worker {
11320*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_STATUS_ERROR_ATTRIBUTES_OR_VALUES, _("Unsupported 'job-hold-until' value."));
11321*5e7646d2SAndroid Build Coastguard Worker ippCopyAttribute(con->response, attr, 0);
11322*5e7646d2SAndroid Build Coastguard Worker return;
11323*5e7646d2SAndroid Build Coastguard Worker }
11324*5e7646d2SAndroid Build Coastguard Worker
11325*5e7646d2SAndroid Build Coastguard Worker /*
11326*5e7646d2SAndroid Build Coastguard Worker * Is the job-name valid?
11327*5e7646d2SAndroid Build Coastguard Worker */
11328*5e7646d2SAndroid Build Coastguard Worker
11329*5e7646d2SAndroid Build Coastguard Worker if ((name = ippFindAttribute(con->request, "job-name", IPP_TAG_ZERO)) != NULL)
11330*5e7646d2SAndroid Build Coastguard Worker {
11331*5e7646d2SAndroid Build Coastguard Worker if ((name->value_tag != IPP_TAG_NAME && name->value_tag != IPP_TAG_NAMELANG) ||
11332*5e7646d2SAndroid Build Coastguard Worker name->num_values != 1 || !ippValidateAttribute(name))
11333*5e7646d2SAndroid Build Coastguard Worker {
11334*5e7646d2SAndroid Build Coastguard Worker if (StrictConformance)
11335*5e7646d2SAndroid Build Coastguard Worker {
11336*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_STATUS_ERROR_ATTRIBUTES_OR_VALUES, _("Unsupported 'job-name' value."));
11337*5e7646d2SAndroid Build Coastguard Worker ippCopyAttribute(con->response, name, 0);
11338*5e7646d2SAndroid Build Coastguard Worker return;
11339*5e7646d2SAndroid Build Coastguard Worker }
11340*5e7646d2SAndroid Build Coastguard Worker else
11341*5e7646d2SAndroid Build Coastguard Worker {
11342*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_WARN, "Unsupported 'job-name' value, deleting from request.");
11343*5e7646d2SAndroid Build Coastguard Worker ippDeleteAttribute(con->request, name);
11344*5e7646d2SAndroid Build Coastguard Worker }
11345*5e7646d2SAndroid Build Coastguard Worker }
11346*5e7646d2SAndroid Build Coastguard Worker }
11347*5e7646d2SAndroid Build Coastguard Worker
11348*5e7646d2SAndroid Build Coastguard Worker /*
11349*5e7646d2SAndroid Build Coastguard Worker * Is the destination valid?
11350*5e7646d2SAndroid Build Coastguard Worker */
11351*5e7646d2SAndroid Build Coastguard Worker
11352*5e7646d2SAndroid Build Coastguard Worker if (!cupsdValidateDest(uri->values[0].string.text, &dtype, &printer))
11353*5e7646d2SAndroid Build Coastguard Worker {
11354*5e7646d2SAndroid Build Coastguard Worker /*
11355*5e7646d2SAndroid Build Coastguard Worker * Bad URI...
11356*5e7646d2SAndroid Build Coastguard Worker */
11357*5e7646d2SAndroid Build Coastguard Worker
11358*5e7646d2SAndroid Build Coastguard Worker send_ipp_status(con, IPP_NOT_FOUND,
11359*5e7646d2SAndroid Build Coastguard Worker _("The printer or class does not exist."));
11360*5e7646d2SAndroid Build Coastguard Worker return;
11361*5e7646d2SAndroid Build Coastguard Worker }
11362*5e7646d2SAndroid Build Coastguard Worker
11363*5e7646d2SAndroid Build Coastguard Worker /*
11364*5e7646d2SAndroid Build Coastguard Worker * Check policy...
11365*5e7646d2SAndroid Build Coastguard Worker */
11366*5e7646d2SAndroid Build Coastguard Worker
11367*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_SSL
11368*5e7646d2SAndroid Build Coastguard Worker auth_info = ippFindAttribute(con->request, "auth-info", IPP_TAG_TEXT);
11369*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_SSL */
11370*5e7646d2SAndroid Build Coastguard Worker
11371*5e7646d2SAndroid Build Coastguard Worker if ((status = cupsdCheckPolicy(printer->op_policy_ptr, con, NULL)) != HTTP_OK)
11372*5e7646d2SAndroid Build Coastguard Worker {
11373*5e7646d2SAndroid Build Coastguard Worker send_http_error(con, status, printer);
11374*5e7646d2SAndroid Build Coastguard Worker return;
11375*5e7646d2SAndroid Build Coastguard Worker }
11376*5e7646d2SAndroid Build Coastguard Worker else if (printer->num_auth_info_required == 1 &&
11377*5e7646d2SAndroid Build Coastguard Worker !strcmp(printer->auth_info_required[0], "negotiate") &&
11378*5e7646d2SAndroid Build Coastguard Worker !con->username[0])
11379*5e7646d2SAndroid Build Coastguard Worker {
11380*5e7646d2SAndroid Build Coastguard Worker send_http_error(con, HTTP_UNAUTHORIZED, printer);
11381*5e7646d2SAndroid Build Coastguard Worker return;
11382*5e7646d2SAndroid Build Coastguard Worker }
11383*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_SSL
11384*5e7646d2SAndroid Build Coastguard Worker else if (auth_info && !con->http->tls &&
11385*5e7646d2SAndroid Build Coastguard Worker !httpAddrLocalhost(con->http->hostaddr))
11386*5e7646d2SAndroid Build Coastguard Worker {
11387*5e7646d2SAndroid Build Coastguard Worker /*
11388*5e7646d2SAndroid Build Coastguard Worker * Require encryption of auth-info over non-local connections...
11389*5e7646d2SAndroid Build Coastguard Worker */
11390*5e7646d2SAndroid Build Coastguard Worker
11391*5e7646d2SAndroid Build Coastguard Worker send_http_error(con, HTTP_UPGRADE_REQUIRED, printer);
11392*5e7646d2SAndroid Build Coastguard Worker return;
11393*5e7646d2SAndroid Build Coastguard Worker }
11394*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_SSL */
11395*5e7646d2SAndroid Build Coastguard Worker
11396*5e7646d2SAndroid Build Coastguard Worker /*
11397*5e7646d2SAndroid Build Coastguard Worker * Everything was ok, so return OK status...
11398*5e7646d2SAndroid Build Coastguard Worker */
11399*5e7646d2SAndroid Build Coastguard Worker
11400*5e7646d2SAndroid Build Coastguard Worker con->response->request.status.status_code = IPP_OK;
11401*5e7646d2SAndroid Build Coastguard Worker }
11402*5e7646d2SAndroid Build Coastguard Worker
11403*5e7646d2SAndroid Build Coastguard Worker
11404*5e7646d2SAndroid Build Coastguard Worker /*
11405*5e7646d2SAndroid Build Coastguard Worker * 'validate_name()' - Make sure the printer name only contains valid chars.
11406*5e7646d2SAndroid Build Coastguard Worker */
11407*5e7646d2SAndroid Build Coastguard Worker
11408*5e7646d2SAndroid Build Coastguard Worker static int /* O - 0 if name is no good, 1 if good */
validate_name(const char * name)11409*5e7646d2SAndroid Build Coastguard Worker validate_name(const char *name) /* I - Name to check */
11410*5e7646d2SAndroid Build Coastguard Worker {
11411*5e7646d2SAndroid Build Coastguard Worker const char *ptr; /* Pointer into name */
11412*5e7646d2SAndroid Build Coastguard Worker
11413*5e7646d2SAndroid Build Coastguard Worker
11414*5e7646d2SAndroid Build Coastguard Worker /*
11415*5e7646d2SAndroid Build Coastguard Worker * Scan the whole name...
11416*5e7646d2SAndroid Build Coastguard Worker */
11417*5e7646d2SAndroid Build Coastguard Worker
11418*5e7646d2SAndroid Build Coastguard Worker for (ptr = name; *ptr; ptr ++)
11419*5e7646d2SAndroid Build Coastguard Worker if ((*ptr > 0 && *ptr <= ' ') || *ptr == 127 || *ptr == '/' || *ptr == '#')
11420*5e7646d2SAndroid Build Coastguard Worker return (0);
11421*5e7646d2SAndroid Build Coastguard Worker
11422*5e7646d2SAndroid Build Coastguard Worker /*
11423*5e7646d2SAndroid Build Coastguard Worker * All the characters are good; validate the length, too...
11424*5e7646d2SAndroid Build Coastguard Worker */
11425*5e7646d2SAndroid Build Coastguard Worker
11426*5e7646d2SAndroid Build Coastguard Worker return ((ptr - name) < 128);
11427*5e7646d2SAndroid Build Coastguard Worker }
11428*5e7646d2SAndroid Build Coastguard Worker
11429*5e7646d2SAndroid Build Coastguard Worker
11430*5e7646d2SAndroid Build Coastguard Worker /*
11431*5e7646d2SAndroid Build Coastguard Worker * 'validate_user()' - Validate the user for the request.
11432*5e7646d2SAndroid Build Coastguard Worker */
11433*5e7646d2SAndroid Build Coastguard Worker
11434*5e7646d2SAndroid Build Coastguard Worker static int /* O - 1 if permitted, 0 otherwise */
validate_user(cupsd_job_t * job,cupsd_client_t * con,const char * owner,char * username,size_t userlen)11435*5e7646d2SAndroid Build Coastguard Worker validate_user(cupsd_job_t *job, /* I - Job */
11436*5e7646d2SAndroid Build Coastguard Worker cupsd_client_t *con, /* I - Client connection */
11437*5e7646d2SAndroid Build Coastguard Worker const char *owner, /* I - Owner of job/resource */
11438*5e7646d2SAndroid Build Coastguard Worker char *username, /* O - Authenticated username */
11439*5e7646d2SAndroid Build Coastguard Worker size_t userlen) /* I - Length of username */
11440*5e7646d2SAndroid Build Coastguard Worker {
11441*5e7646d2SAndroid Build Coastguard Worker cupsd_printer_t *printer; /* Printer for job */
11442*5e7646d2SAndroid Build Coastguard Worker
11443*5e7646d2SAndroid Build Coastguard Worker
11444*5e7646d2SAndroid Build Coastguard Worker cupsdLogMessage(CUPSD_LOG_DEBUG2, "validate_user(job=%d, con=%d, owner=\"%s\", username=%p, userlen=" CUPS_LLFMT ")", job->id, con ? con->number : 0, owner ? owner : "(null)", username, CUPS_LLCAST userlen);
11445*5e7646d2SAndroid Build Coastguard Worker
11446*5e7646d2SAndroid Build Coastguard Worker /*
11447*5e7646d2SAndroid Build Coastguard Worker * Validate input...
11448*5e7646d2SAndroid Build Coastguard Worker */
11449*5e7646d2SAndroid Build Coastguard Worker
11450*5e7646d2SAndroid Build Coastguard Worker if (!con || !owner || !username || userlen <= 0)
11451*5e7646d2SAndroid Build Coastguard Worker return (0);
11452*5e7646d2SAndroid Build Coastguard Worker
11453*5e7646d2SAndroid Build Coastguard Worker /*
11454*5e7646d2SAndroid Build Coastguard Worker * Get the best authenticated username that is available.
11455*5e7646d2SAndroid Build Coastguard Worker */
11456*5e7646d2SAndroid Build Coastguard Worker
11457*5e7646d2SAndroid Build Coastguard Worker strlcpy(username, get_username(con), userlen);
11458*5e7646d2SAndroid Build Coastguard Worker
11459*5e7646d2SAndroid Build Coastguard Worker /*
11460*5e7646d2SAndroid Build Coastguard Worker * Check the username against the owner...
11461*5e7646d2SAndroid Build Coastguard Worker */
11462*5e7646d2SAndroid Build Coastguard Worker
11463*5e7646d2SAndroid Build Coastguard Worker printer = cupsdFindDest(job->dest);
11464*5e7646d2SAndroid Build Coastguard Worker
11465*5e7646d2SAndroid Build Coastguard Worker return (cupsdCheckPolicy(printer ? printer->op_policy_ptr : DefaultPolicyPtr,
11466*5e7646d2SAndroid Build Coastguard Worker con, owner) == HTTP_OK);
11467*5e7646d2SAndroid Build Coastguard Worker }
11468