]> git.ipfire.org Git - thirdparty/cups.git/blob - cups/dest-job.c
403a1cf9a34af7a0945eec8018d1a1c08efdad10
[thirdparty/cups.git] / cups / dest-job.c
1 /*
2 * Destination job support for CUPS.
3 *
4 * Copyright 2012-2017 by Apple Inc.
5 *
6 * Licensed under Apache License v2.0. See the file "LICENSE" for more information.
7 */
8
9 /*
10 * Include necessary headers...
11 */
12
13 #include "cups-private.h"
14
15
16 /*
17 * 'cupsCancelDestJob()' - Cancel a job on a destination.
18 *
19 * The "job_id" is the number returned by cupsCreateDestJob.
20 *
21 * Returns @code IPP_STATUS_OK@ on success and
22 * @code IPP_STATUS_ERROR_NOT_AUTHORIZED@ or
23 * @code IPP_STATUS_ERROR_FORBIDDEN@ on failure.
24 *
25 * @since CUPS 1.6/macOS 10.8@
26 */
27
28 ipp_status_t /* O - Status of cancel operation */
29 cupsCancelDestJob(http_t *http, /* I - Connection to destination */
30 cups_dest_t *dest, /* I - Destination */
31 int job_id) /* I - Job ID */
32 {
33 cups_dinfo_t *info; /* Destination information */
34
35
36 if ((info = cupsCopyDestInfo(http, dest)) != NULL)
37 {
38 ipp_t *request; /* Cancel-Job request */
39
40 request = ippNewRequest(IPP_OP_CANCEL_JOB);
41
42 ippSetVersion(request, info->version / 10, info->version % 10);
43
44 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, info->uri);
45 ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER, "job-id", job_id);
46 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsUser());
47
48 ippDelete(cupsDoRequest(http, request, info->resource));
49 cupsFreeDestInfo(info);
50 }
51
52 return (cupsLastError());
53 }
54
55
56 /*
57 * 'cupsCloseDestJob()' - Close a job and start printing.
58 *
59 * Use when the last call to cupsStartDocument passed 0 for "last_document".
60 * "job_id" is the job ID returned by cupsCreateDestJob. Returns @code IPP_STATUS_OK@
61 * on success.
62 *
63 * @since CUPS 1.6/macOS 10.8@
64 */
65
66 ipp_status_t /* O - IPP status code */
67 cupsCloseDestJob(
68 http_t *http, /* I - Connection to destination */
69 cups_dest_t *dest, /* I - Destination */
70 cups_dinfo_t *info, /* I - Destination information */
71 int job_id) /* I - Job ID */
72 {
73 int i; /* Looping var */
74 ipp_t *request = NULL;/* Close-Job/Send-Document request */
75 ipp_attribute_t *attr; /* operations-supported attribute */
76
77
78 DEBUG_printf(("cupsCloseDestJob(http=%p, dest=%p(%s/%s), info=%p, job_id=%d)", (void *)http, (void *)dest, dest ? dest->name : NULL, dest ? dest->instance : NULL, (void *)info, job_id));
79
80 /*
81 * Get the default connection as needed...
82 */
83
84 if (!http)
85 http = _cupsConnect();
86
87 /*
88 * Range check input...
89 */
90
91 if (!http || !dest || !info || job_id <= 0)
92 {
93 _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(EINVAL), 0);
94 DEBUG_puts("1cupsCloseDestJob: Bad arguments.");
95 return (IPP_STATUS_ERROR_INTERNAL);
96 }
97
98 /*
99 * Build a Close-Job or empty Send-Document request...
100 */
101
102 if ((attr = ippFindAttribute(info->attrs, "operations-supported",
103 IPP_TAG_ENUM)) != NULL)
104 {
105 for (i = 0; i < attr->num_values; i ++)
106 if (attr->values[i].integer == IPP_OP_CLOSE_JOB)
107 {
108 request = ippNewRequest(IPP_OP_CLOSE_JOB);
109 break;
110 }
111 }
112
113 if (!request)
114 request = ippNewRequest(IPP_OP_SEND_DOCUMENT);
115
116 if (!request)
117 {
118 _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(ENOMEM), 0);
119 DEBUG_puts("1cupsCloseDestJob: Unable to create Close-Job/Send-Document "
120 "request.");
121 return (IPP_STATUS_ERROR_INTERNAL);
122 }
123
124 ippSetVersion(request, info->version / 10, info->version % 10);
125
126 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
127 NULL, info->uri);
128 ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER, "job-id",
129 job_id);
130 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
131 NULL, cupsUser());
132 if (ippGetOperation(request) == IPP_OP_SEND_DOCUMENT)
133 ippAddBoolean(request, IPP_TAG_OPERATION, "last-document", 1);
134
135 /*
136 * Send the request and return the status...
137 */
138
139 ippDelete(cupsDoRequest(http, request, info->resource));
140
141 DEBUG_printf(("1cupsCloseDestJob: %s (%s)", ippErrorString(cupsLastError()),
142 cupsLastErrorString()));
143
144 return (cupsLastError());
145 }
146
147
148 /*
149 * 'cupsCreateDestJob()' - Create a job on a destination.
150 *
151 * Returns @code IPP_STATUS_OK@ or @code IPP_STATUS_OK_SUBST@ on success, saving the job ID
152 * in the variable pointed to by "job_id".
153 *
154 * @since CUPS 1.6/macOS 10.8@
155 */
156
157 ipp_status_t /* O - IPP status code */
158 cupsCreateDestJob(
159 http_t *http, /* I - Connection to destination */
160 cups_dest_t *dest, /* I - Destination */
161 cups_dinfo_t *info, /* I - Destination information */
162 int *job_id, /* O - Job ID or 0 on error */
163 const char *title, /* I - Job name */
164 int num_options, /* I - Number of job options */
165 cups_option_t *options) /* I - Job options */
166 {
167 ipp_t *request, /* Create-Job request */
168 *response; /* Create-Job response */
169 ipp_attribute_t *attr; /* job-id attribute */
170
171
172 DEBUG_printf(("cupsCreateDestJob(http=%p, dest=%p(%s/%s), info=%p, "
173 "job_id=%p, title=\"%s\", num_options=%d, options=%p)", (void *)http, (void *)dest, dest ? dest->name : NULL, dest ? dest->instance : NULL, (void *)info, (void *)job_id, title, num_options, (void *)options));
174
175 /*
176 * Get the default connection as needed...
177 */
178
179 if (!http)
180 http = _cupsConnect();
181
182 /*
183 * Range check input...
184 */
185
186 if (job_id)
187 *job_id = 0;
188
189 if (!http || !dest || !info || !job_id)
190 {
191 _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(EINVAL), 0);
192 DEBUG_puts("1cupsCreateDestJob: Bad arguments.");
193 return (IPP_STATUS_ERROR_INTERNAL);
194 }
195
196 /*
197 * Build a Create-Job request...
198 */
199
200 if ((request = ippNewRequest(IPP_OP_CREATE_JOB)) == NULL)
201 {
202 _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(ENOMEM), 0);
203 DEBUG_puts("1cupsCreateDestJob: Unable to create Create-Job request.");
204 return (IPP_STATUS_ERROR_INTERNAL);
205 }
206
207 ippSetVersion(request, info->version / 10, info->version % 10);
208
209 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
210 NULL, info->uri);
211 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
212 NULL, cupsUser());
213 if (title)
214 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "job-name", NULL,
215 title);
216
217 cupsEncodeOptions2(request, num_options, options, IPP_TAG_OPERATION);
218 cupsEncodeOptions2(request, num_options, options, IPP_TAG_JOB);
219 cupsEncodeOptions2(request, num_options, options, IPP_TAG_SUBSCRIPTION);
220
221 /*
222 * Send the request and get the job-id...
223 */
224
225 response = cupsDoRequest(http, request, info->resource);
226
227 if ((attr = ippFindAttribute(response, "job-id", IPP_TAG_INTEGER)) != NULL)
228 {
229 *job_id = attr->values[0].integer;
230 DEBUG_printf(("1cupsCreateDestJob: job-id=%d", *job_id));
231 }
232
233 ippDelete(response);
234
235 /*
236 * Return the status code from the Create-Job request...
237 */
238
239 DEBUG_printf(("1cupsCreateDestJob: %s (%s)", ippErrorString(cupsLastError()),
240 cupsLastErrorString()));
241
242 return (cupsLastError());
243 }
244
245
246 /*
247 * 'cupsFinishDestDocument()' - Finish the current document.
248 *
249 * Returns @code IPP_STATUS_OK@ or @code IPP_STATUS_OK_SUBST@ on success.
250 *
251 * @since CUPS 1.6/macOS 10.8@
252 */
253
254 ipp_status_t /* O - Status of document submission */
255 cupsFinishDestDocument(
256 http_t *http, /* I - Connection to destination */
257 cups_dest_t *dest, /* I - Destination */
258 cups_dinfo_t *info) /* I - Destination information */
259 {
260 DEBUG_printf(("cupsFinishDestDocument(http=%p, dest=%p(%s/%s), info=%p)", (void *)http, (void *)dest, dest ? dest->name : NULL, dest ? dest->instance : NULL, (void *)info));
261
262 /*
263 * Get the default connection as needed...
264 */
265
266 if (!http)
267 http = _cupsConnect();
268
269 /*
270 * Range check input...
271 */
272
273 if (!http || !dest || !info)
274 {
275 _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(EINVAL), 0);
276 DEBUG_puts("1cupsFinishDestDocument: Bad arguments.");
277 return (IPP_STATUS_ERROR_INTERNAL);
278 }
279
280 /*
281 * Get the response at the end of the document and return it...
282 */
283
284 ippDelete(cupsGetResponse(http, info->resource));
285
286 DEBUG_printf(("1cupsFinishDestDocument: %s (%s)",
287 ippErrorString(cupsLastError()), cupsLastErrorString()));
288
289 return (cupsLastError());
290 }
291
292
293 /*
294 * 'cupsStartDestDocument()' - Start a new document.
295 *
296 * "job_id" is the job ID returned by cupsCreateDestJob. "docname" is the name
297 * of the document/file being printed, "format" is the MIME media type for the
298 * document (see CUPS_FORMAT_xxx constants), and "num_options" and "options"
299 * are the options do be applied to the document. "last_document" should be 1
300 * if this is the last document to be submitted in the job. Returns
301 * @code HTTP_CONTINUE@ on success.
302 *
303 * @since CUPS 1.6/macOS 10.8@
304 */
305
306 http_status_t /* O - Status of document creation */
307 cupsStartDestDocument(
308 http_t *http, /* I - Connection to destination */
309 cups_dest_t *dest, /* I - Destination */
310 cups_dinfo_t *info, /* I - Destination information */
311 int job_id, /* I - Job ID */
312 const char *docname, /* I - Document name */
313 const char *format, /* I - Document format */
314 int num_options, /* I - Number of document options */
315 cups_option_t *options, /* I - Document options */
316 int last_document) /* I - 1 if this is the last document */
317 {
318 ipp_t *request; /* Send-Document request */
319 http_status_t status; /* HTTP status */
320
321
322 DEBUG_printf(("cupsStartDestDocument(http=%p, dest=%p(%s/%s), info=%p, job_id=%d, docname=\"%s\", format=\"%s\", num_options=%d, options=%p, last_document=%d)", (void *)http, (void *)dest, dest ? dest->name : NULL, dest ? dest->instance : NULL, (void *)info, job_id, docname, format, num_options, (void *)options, last_document));
323
324 /*
325 * Get the default connection as needed...
326 */
327
328 if (!http)
329 http = _cupsConnect();
330
331 /*
332 * Range check input...
333 */
334
335 if (!http || !dest || !info || job_id <= 0)
336 {
337 _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(EINVAL), 0);
338 DEBUG_puts("1cupsStartDestDocument: Bad arguments.");
339 return (HTTP_STATUS_ERROR);
340 }
341
342 /*
343 * Create a Send-Document request...
344 */
345
346 if ((request = ippNewRequest(IPP_OP_SEND_DOCUMENT)) == NULL)
347 {
348 _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(ENOMEM), 0);
349 DEBUG_puts("1cupsStartDestDocument: Unable to create Send-Document "
350 "request.");
351 return (HTTP_STATUS_ERROR);
352 }
353
354 ippSetVersion(request, info->version / 10, info->version % 10);
355
356 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
357 NULL, info->uri);
358 ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER, "job-id", job_id);
359 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
360 NULL, cupsUser());
361 if (docname)
362 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "document-name",
363 NULL, docname);
364 if (format)
365 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_MIMETYPE,
366 "document-format", NULL, format);
367 ippAddBoolean(request, IPP_TAG_OPERATION, "last-document", (char)last_document);
368
369 cupsEncodeOptions2(request, num_options, options, IPP_TAG_OPERATION);
370 cupsEncodeOptions2(request, num_options, options, IPP_TAG_DOCUMENT);
371
372 /*
373 * Send and delete the request, then return the status...
374 */
375
376 status = cupsSendRequest(http, request, info->resource, CUPS_LENGTH_VARIABLE);
377
378 ippDelete(request);
379
380 return (status);
381 }