]>
Commit | Line | Data |
---|---|---|
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 | #include "debug-internal.h" | |
15 | ||
16 | ||
17 | /* | |
18 | * 'cupsCancelDestJob()' - Cancel a job on a destination. | |
19 | * | |
20 | * The "job_id" is the number returned by cupsCreateDestJob. | |
21 | * | |
22 | * Returns @code IPP_STATUS_OK@ on success and | |
23 | * @code IPP_STATUS_ERROR_NOT_AUTHORIZED@ or | |
24 | * @code IPP_STATUS_ERROR_FORBIDDEN@ on failure. | |
25 | * | |
26 | * @since CUPS 1.6/macOS 10.8@ | |
27 | */ | |
28 | ||
29 | ipp_status_t /* O - Status of cancel operation */ | |
30 | cupsCancelDestJob(http_t *http, /* I - Connection to destination */ | |
31 | cups_dest_t *dest, /* I - Destination */ | |
32 | int job_id) /* I - Job ID */ | |
33 | { | |
34 | cups_dinfo_t *info; /* Destination information */ | |
35 | ||
36 | ||
37 | if ((info = cupsCopyDestInfo(http, dest)) != NULL) | |
38 | { | |
39 | ipp_t *request; /* Cancel-Job request */ | |
40 | ||
41 | request = ippNewRequest(IPP_OP_CANCEL_JOB); | |
42 | ||
43 | ippSetVersion(request, info->version / 10, info->version % 10); | |
44 | ||
45 | ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, info->uri); | |
46 | ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER, "job-id", job_id); | |
47 | ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsUser()); | |
48 | ||
49 | ippDelete(cupsDoRequest(http, request, info->resource)); | |
50 | cupsFreeDestInfo(info); | |
51 | } | |
52 | ||
53 | return (cupsLastError()); | |
54 | } | |
55 | ||
56 | ||
57 | /* | |
58 | * 'cupsCloseDestJob()' - Close a job and start printing. | |
59 | * | |
60 | * Use when the last call to cupsStartDocument passed 0 for "last_document". | |
61 | * "job_id" is the job ID returned by cupsCreateDestJob. Returns @code IPP_STATUS_OK@ | |
62 | * on success. | |
63 | * | |
64 | * @since CUPS 1.6/macOS 10.8@ | |
65 | */ | |
66 | ||
67 | ipp_status_t /* O - IPP status code */ | |
68 | cupsCloseDestJob( | |
69 | http_t *http, /* I - Connection to destination */ | |
70 | cups_dest_t *dest, /* I - Destination */ | |
71 | cups_dinfo_t *info, /* I - Destination information */ | |
72 | int job_id) /* I - Job ID */ | |
73 | { | |
74 | int i; /* Looping var */ | |
75 | ipp_t *request = NULL;/* Close-Job/Send-Document request */ | |
76 | ipp_attribute_t *attr; /* operations-supported attribute */ | |
77 | ||
78 | ||
79 | 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)); | |
80 | ||
81 | /* | |
82 | * Get the default connection as needed... | |
83 | */ | |
84 | ||
85 | if (!http) | |
86 | http = _cupsConnect(); | |
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/macOS 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)", (void *)http, (void *)dest, dest ? dest->name : NULL, dest ? dest->instance : NULL, (void *)info, (void *)job_id, title, num_options, (void *)options)); | |
175 | ||
176 | /* | |
177 | * Get the default connection as needed... | |
178 | */ | |
179 | ||
180 | if (!http) | |
181 | http = _cupsConnect(); | |
182 | ||
183 | /* | |
184 | * Range check input... | |
185 | */ | |
186 | ||
187 | if (job_id) | |
188 | *job_id = 0; | |
189 | ||
190 | if (!http || !dest || !info || !job_id) | |
191 | { | |
192 | _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(EINVAL), 0); | |
193 | DEBUG_puts("1cupsCreateDestJob: Bad arguments."); | |
194 | return (IPP_STATUS_ERROR_INTERNAL); | |
195 | } | |
196 | ||
197 | /* | |
198 | * Build a Create-Job request... | |
199 | */ | |
200 | ||
201 | if ((request = ippNewRequest(IPP_OP_CREATE_JOB)) == NULL) | |
202 | { | |
203 | _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(ENOMEM), 0); | |
204 | DEBUG_puts("1cupsCreateDestJob: Unable to create Create-Job request."); | |
205 | return (IPP_STATUS_ERROR_INTERNAL); | |
206 | } | |
207 | ||
208 | ippSetVersion(request, info->version / 10, info->version % 10); | |
209 | ||
210 | ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", | |
211 | NULL, info->uri); | |
212 | ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", | |
213 | NULL, cupsUser()); | |
214 | if (title) | |
215 | ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "job-name", NULL, | |
216 | title); | |
217 | ||
218 | cupsEncodeOptions2(request, num_options, options, IPP_TAG_OPERATION); | |
219 | cupsEncodeOptions2(request, num_options, options, IPP_TAG_JOB); | |
220 | cupsEncodeOptions2(request, num_options, options, IPP_TAG_SUBSCRIPTION); | |
221 | ||
222 | /* | |
223 | * Send the request and get the job-id... | |
224 | */ | |
225 | ||
226 | response = cupsDoRequest(http, request, info->resource); | |
227 | ||
228 | if ((attr = ippFindAttribute(response, "job-id", IPP_TAG_INTEGER)) != NULL) | |
229 | { | |
230 | *job_id = attr->values[0].integer; | |
231 | DEBUG_printf(("1cupsCreateDestJob: job-id=%d", *job_id)); | |
232 | } | |
233 | ||
234 | ippDelete(response); | |
235 | ||
236 | /* | |
237 | * Return the status code from the Create-Job request... | |
238 | */ | |
239 | ||
240 | DEBUG_printf(("1cupsCreateDestJob: %s (%s)", ippErrorString(cupsLastError()), | |
241 | cupsLastErrorString())); | |
242 | ||
243 | return (cupsLastError()); | |
244 | } | |
245 | ||
246 | ||
247 | /* | |
248 | * 'cupsFinishDestDocument()' - Finish the current document. | |
249 | * | |
250 | * Returns @code IPP_STATUS_OK@ or @code IPP_STATUS_OK_SUBST@ on success. | |
251 | * | |
252 | * @since CUPS 1.6/macOS 10.8@ | |
253 | */ | |
254 | ||
255 | ipp_status_t /* O - Status of document submission */ | |
256 | cupsFinishDestDocument( | |
257 | http_t *http, /* I - Connection to destination */ | |
258 | cups_dest_t *dest, /* I - Destination */ | |
259 | cups_dinfo_t *info) /* I - Destination information */ | |
260 | { | |
261 | 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)); | |
262 | ||
263 | /* | |
264 | * Get the default connection as needed... | |
265 | */ | |
266 | ||
267 | if (!http) | |
268 | http = _cupsConnect(); | |
269 | ||
270 | /* | |
271 | * Range check input... | |
272 | */ | |
273 | ||
274 | if (!http || !dest || !info) | |
275 | { | |
276 | _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(EINVAL), 0); | |
277 | DEBUG_puts("1cupsFinishDestDocument: Bad arguments."); | |
278 | return (IPP_STATUS_ERROR_INTERNAL); | |
279 | } | |
280 | ||
281 | /* | |
282 | * Get the response at the end of the document and return it... | |
283 | */ | |
284 | ||
285 | ippDelete(cupsGetResponse(http, info->resource)); | |
286 | ||
287 | DEBUG_printf(("1cupsFinishDestDocument: %s (%s)", | |
288 | ippErrorString(cupsLastError()), cupsLastErrorString())); | |
289 | ||
290 | return (cupsLastError()); | |
291 | } | |
292 | ||
293 | ||
294 | /* | |
295 | * 'cupsStartDestDocument()' - Start a new document. | |
296 | * | |
297 | * "job_id" is the job ID returned by cupsCreateDestJob. "docname" is the name | |
298 | * of the document/file being printed, "format" is the MIME media type for the | |
299 | * document (see CUPS_FORMAT_xxx constants), and "num_options" and "options" | |
300 | * are the options do be applied to the document. "last_document" should be 1 | |
301 | * if this is the last document to be submitted in the job. Returns | |
302 | * @code HTTP_CONTINUE@ on success. | |
303 | * | |
304 | * @since CUPS 1.6/macOS 10.8@ | |
305 | */ | |
306 | ||
307 | http_status_t /* O - Status of document creation */ | |
308 | cupsStartDestDocument( | |
309 | http_t *http, /* I - Connection to destination */ | |
310 | cups_dest_t *dest, /* I - Destination */ | |
311 | cups_dinfo_t *info, /* I - Destination information */ | |
312 | int job_id, /* I - Job ID */ | |
313 | const char *docname, /* I - Document name */ | |
314 | const char *format, /* I - Document format */ | |
315 | int num_options, /* I - Number of document options */ | |
316 | cups_option_t *options, /* I - Document options */ | |
317 | int last_document) /* I - 1 if this is the last document */ | |
318 | { | |
319 | ipp_t *request; /* Send-Document request */ | |
320 | http_status_t status; /* HTTP status */ | |
321 | ||
322 | ||
323 | 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)); | |
324 | ||
325 | /* | |
326 | * Get the default connection as needed... | |
327 | */ | |
328 | ||
329 | if (!http) | |
330 | http = _cupsConnect(); | |
331 | ||
332 | /* | |
333 | * Range check input... | |
334 | */ | |
335 | ||
336 | if (!http || !dest || !info || job_id <= 0) | |
337 | { | |
338 | _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(EINVAL), 0); | |
339 | DEBUG_puts("1cupsStartDestDocument: Bad arguments."); | |
340 | return (HTTP_STATUS_ERROR); | |
341 | } | |
342 | ||
343 | /* | |
344 | * Create a Send-Document request... | |
345 | */ | |
346 | ||
347 | if ((request = ippNewRequest(IPP_OP_SEND_DOCUMENT)) == NULL) | |
348 | { | |
349 | _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(ENOMEM), 0); | |
350 | DEBUG_puts("1cupsStartDestDocument: Unable to create Send-Document " | |
351 | "request."); | |
352 | return (HTTP_STATUS_ERROR); | |
353 | } | |
354 | ||
355 | ippSetVersion(request, info->version / 10, info->version % 10); | |
356 | ||
357 | ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", | |
358 | NULL, info->uri); | |
359 | ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER, "job-id", job_id); | |
360 | ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", | |
361 | NULL, cupsUser()); | |
362 | if (docname) | |
363 | ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "document-name", | |
364 | NULL, docname); | |
365 | if (format) | |
366 | ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_MIMETYPE, | |
367 | "document-format", NULL, format); | |
368 | ippAddBoolean(request, IPP_TAG_OPERATION, "last-document", (char)last_document); | |
369 | ||
370 | cupsEncodeOptions2(request, num_options, options, IPP_TAG_OPERATION); | |
371 | cupsEncodeOptions2(request, num_options, options, IPP_TAG_DOCUMENT); | |
372 | ||
373 | /* | |
374 | * Send and delete the request, then return the status... | |
375 | */ | |
376 | ||
377 | status = cupsSendRequest(http, request, info->resource, CUPS_LENGTH_VARIABLE); | |
378 | ||
379 | ippDelete(request); | |
380 | ||
381 | return (status); | |
382 | } |