]> git.ipfire.org Git - thirdparty/cups.git/blob - cups/dest-job.c
146887eead3e161b8329d4357adebd21f103b13c
[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/macOS 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/macOS 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)", (void *)http, (void *)dest, dest ? dest->name : NULL, dest ? dest->instance : NULL, (void *)info, job_id));
85
86 /*
87 * Range check input...
88 */
89
90 if (!http || !dest || !info || job_id <= 0)
91 {
92 _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(EINVAL), 0);
93 DEBUG_puts("1cupsCloseDestJob: Bad arguments.");
94 return (IPP_STATUS_ERROR_INTERNAL);
95 }
96
97 /*
98 * Build a Close-Job or empty Send-Document request...
99 */
100
101 if ((attr = ippFindAttribute(info->attrs, "operations-supported",
102 IPP_TAG_ENUM)) != NULL)
103 {
104 for (i = 0; i < attr->num_values; i ++)
105 if (attr->values[i].integer == IPP_OP_CLOSE_JOB)
106 {
107 request = ippNewRequest(IPP_OP_CLOSE_JOB);
108 break;
109 }
110 }
111
112 if (!request)
113 request = ippNewRequest(IPP_OP_SEND_DOCUMENT);
114
115 if (!request)
116 {
117 _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(ENOMEM), 0);
118 DEBUG_puts("1cupsCloseDestJob: Unable to create Close-Job/Send-Document "
119 "request.");
120 return (IPP_STATUS_ERROR_INTERNAL);
121 }
122
123 ippSetVersion(request, info->version / 10, info->version % 10);
124
125 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
126 NULL, info->uri);
127 ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER, "job-id",
128 job_id);
129 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
130 NULL, cupsUser());
131 if (ippGetOperation(request) == IPP_OP_SEND_DOCUMENT)
132 ippAddBoolean(request, IPP_TAG_OPERATION, "last-document", 1);
133
134 /*
135 * Send the request and return the status...
136 */
137
138 ippDelete(cupsDoRequest(http, request, info->resource));
139
140 DEBUG_printf(("1cupsCloseDestJob: %s (%s)", ippErrorString(cupsLastError()),
141 cupsLastErrorString()));
142
143 return (cupsLastError());
144 }
145
146
147 /*
148 * 'cupsCreateDestJob()' - Create a job on a destination.
149 *
150 * Returns @code IPP_STATUS_OK@ or @code IPP_STATUS_OK_SUBST@ on success, saving the job ID
151 * in the variable pointed to by "job_id".
152 *
153 * @since CUPS 1.6/macOS 10.8@
154 */
155
156 ipp_status_t /* O - IPP status code */
157 cupsCreateDestJob(
158 http_t *http, /* I - Connection to destination */
159 cups_dest_t *dest, /* I - Destination */
160 cups_dinfo_t *info, /* I - Destination information */
161 int *job_id, /* O - Job ID or 0 on error */
162 const char *title, /* I - Job name */
163 int num_options, /* I - Number of job options */
164 cups_option_t *options) /* I - Job options */
165 {
166 ipp_t *request, /* Create-Job request */
167 *response; /* Create-Job response */
168 ipp_attribute_t *attr; /* job-id attribute */
169
170
171 DEBUG_printf(("cupsCreateDestJob(http=%p, dest=%p(%s/%s), info=%p, "
172 "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));
173
174 /*
175 * Range check input...
176 */
177
178 if (job_id)
179 *job_id = 0;
180
181 if (!http || !dest || !info || !job_id)
182 {
183 _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(EINVAL), 0);
184 DEBUG_puts("1cupsCreateDestJob: Bad arguments.");
185 return (IPP_STATUS_ERROR_INTERNAL);
186 }
187
188 /*
189 * Build a Create-Job request...
190 */
191
192 if ((request = ippNewRequest(IPP_OP_CREATE_JOB)) == NULL)
193 {
194 _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(ENOMEM), 0);
195 DEBUG_puts("1cupsCreateDestJob: Unable to create Create-Job request.");
196 return (IPP_STATUS_ERROR_INTERNAL);
197 }
198
199 ippSetVersion(request, info->version / 10, info->version % 10);
200
201 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
202 NULL, info->uri);
203 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
204 NULL, cupsUser());
205 if (title)
206 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "job-name", NULL,
207 title);
208
209 cupsEncodeOptions2(request, num_options, options, IPP_TAG_OPERATION);
210 cupsEncodeOptions2(request, num_options, options, IPP_TAG_JOB);
211 cupsEncodeOptions2(request, num_options, options, IPP_TAG_SUBSCRIPTION);
212
213 /*
214 * Send the request and get the job-id...
215 */
216
217 response = cupsDoRequest(http, request, info->resource);
218
219 if ((attr = ippFindAttribute(response, "job-id", IPP_TAG_INTEGER)) != NULL)
220 {
221 *job_id = attr->values[0].integer;
222 DEBUG_printf(("1cupsCreateDestJob: job-id=%d", *job_id));
223 }
224
225 ippDelete(response);
226
227 /*
228 * Return the status code from the Create-Job request...
229 */
230
231 DEBUG_printf(("1cupsCreateDestJob: %s (%s)", ippErrorString(cupsLastError()),
232 cupsLastErrorString()));
233
234 return (cupsLastError());
235 }
236
237
238 /*
239 * 'cupsFinishDestDocument()' - Finish the current document.
240 *
241 * Returns @code IPP_STATUS_OK@ or @code IPP_STATUS_OK_SUBST@ on success.
242 *
243 * @since CUPS 1.6/macOS 10.8@
244 */
245
246 ipp_status_t /* O - Status of document submission */
247 cupsFinishDestDocument(
248 http_t *http, /* I - Connection to destination */
249 cups_dest_t *dest, /* I - Destination */
250 cups_dinfo_t *info) /* I - Destination information */
251 {
252 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));
253
254 /*
255 * Range check input...
256 */
257
258 if (!http || !dest || !info)
259 {
260 _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(EINVAL), 0);
261 DEBUG_puts("1cupsFinishDestDocument: Bad arguments.");
262 return (IPP_STATUS_ERROR_INTERNAL);
263 }
264
265 /*
266 * Get the response at the end of the document and return it...
267 */
268
269 ippDelete(cupsGetResponse(http, info->resource));
270
271 DEBUG_printf(("1cupsFinishDestDocument: %s (%s)",
272 ippErrorString(cupsLastError()), cupsLastErrorString()));
273
274 return (cupsLastError());
275 }
276
277
278 /*
279 * 'cupsStartDestDocument()' - Start a new document.
280 *
281 * "job_id" is the job ID returned by cupsCreateDestJob. "docname" is the name
282 * of the document/file being printed, "format" is the MIME media type for the
283 * document (see CUPS_FORMAT_xxx constants), and "num_options" and "options"
284 * are the options do be applied to the document. "last_document" should be 1
285 * if this is the last document to be submitted in the job. Returns
286 * @code HTTP_CONTINUE@ on success.
287 *
288 * @since CUPS 1.6/macOS 10.8@
289 */
290
291 http_status_t /* O - Status of document creation */
292 cupsStartDestDocument(
293 http_t *http, /* I - Connection to destination */
294 cups_dest_t *dest, /* I - Destination */
295 cups_dinfo_t *info, /* I - Destination information */
296 int job_id, /* I - Job ID */
297 const char *docname, /* I - Document name */
298 const char *format, /* I - Document format */
299 int num_options, /* I - Number of document options */
300 cups_option_t *options, /* I - Document options */
301 int last_document) /* I - 1 if this is the last document */
302 {
303 ipp_t *request; /* Send-Document request */
304 http_status_t status; /* HTTP status */
305
306
307 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));
308
309 /*
310 * Range check input...
311 */
312
313 if (!http || !dest || !info || job_id <= 0)
314 {
315 _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(EINVAL), 0);
316 DEBUG_puts("1cupsStartDestDocument: Bad arguments.");
317 return (HTTP_STATUS_ERROR);
318 }
319
320 /*
321 * Create a Send-Document request...
322 */
323
324 if ((request = ippNewRequest(IPP_OP_SEND_DOCUMENT)) == NULL)
325 {
326 _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(ENOMEM), 0);
327 DEBUG_puts("1cupsStartDestDocument: Unable to create Send-Document "
328 "request.");
329 return (HTTP_STATUS_ERROR);
330 }
331
332 ippSetVersion(request, info->version / 10, info->version % 10);
333
334 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
335 NULL, info->uri);
336 ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER, "job-id", job_id);
337 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
338 NULL, cupsUser());
339 if (docname)
340 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "document-name",
341 NULL, docname);
342 if (format)
343 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_MIMETYPE,
344 "document-format", NULL, format);
345 ippAddBoolean(request, IPP_TAG_OPERATION, "last-document", (char)last_document);
346
347 cupsEncodeOptions2(request, num_options, options, IPP_TAG_OPERATION);
348 cupsEncodeOptions2(request, num_options, options, IPP_TAG_DOCUMENT);
349
350 /*
351 * Send and delete the request, then return the status...
352 */
353
354 status = cupsSendRequest(http, request, info->resource, CUPS_LENGTH_VARIABLE);
355
356 ippDelete(request);
357
358 return (status);
359 }