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