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