4 * Destination job support for CUPS.
6 * Copyright 2012-2013 by Apple Inc.
8 * These coded instructions, statements, and computer programs are the
9 * property of Apple Inc. and are protected by Federal copyright
10 * law. Distribution and use rights are outlined in the file "LICENSE.txt"
11 * which should have been included with this file. If this file is
12 * file is missing or damaged, see the license at "http://www.cups.org/".
14 * This file is subject to the Apple OS-Developed Software exception.
18 * cupsCancelDestJob() - Cancel a job on a destination.
19 * cupsCloseDestJob() - Close a job and start printing.
20 * cupsCreateDestJob() - Create a job on a destination.
21 * cupsFinishDestDocument() - Finish the current document.
22 * cupsStartDestDocument() - Start a new document.
26 * Include necessary headers...
29 #include "cups-private.h"
33 * 'cupsCancelDestJob()' - Cancel a job on a destination.
35 * The "job_id" is the number returned by cupsCreateDestJob.
37 * Returns IPP_STATUS_OK on success and IPP_NOT_AUTHORIZED or IPP_FORBIDDEN on
40 * @since CUPS 1.6/OS X 10.8@
44 cupsCancelDestJob(http_t
*http
, /* I - Connection to destination */
45 cups_dest_t
*dest
, /* I - Destination */
46 int job_id
) /* I - Job ID */
48 return (IPP_STATUS_ERROR_NOT_FOUND
);
53 * 'cupsCloseDestJob()' - Close a job and start printing.
55 * Use when the last call to cupsStartDocument passed 0 for "last_document".
56 * "job_id" is the job ID returned by cupsCreateDestJob. Returns @code IPP_STATUS_OK@
59 * @since CUPS 1.6/OS X 10.8@
62 ipp_status_t
/* O - IPP status code */
64 http_t
*http
, /* I - Connection to destination */
65 cups_dest_t
*dest
, /* I - Destination */
66 cups_dinfo_t
*info
, /* I - Destination information */
67 int job_id
) /* I - Job ID */
69 int i
; /* Looping var */
70 ipp_t
*request
= NULL
;/* Close-Job/Send-Document request */
71 ipp_attribute_t
*attr
; /* operations-supported attribute */
74 DEBUG_printf(("cupsCloseDestJob(http=%p, dest=%p(%s/%s), info=%p, job_id=%d)",
75 http
, dest
, dest
? dest
->name
: NULL
,
76 dest
? dest
->instance
: NULL
, info
, job_id
));
79 * Range check input...
82 if (!http
|| !dest
|| !info
|| job_id
<= 0)
84 _cupsSetError(IPP_STATUS_ERROR_INTERNAL
, strerror(EINVAL
), 0);
85 DEBUG_puts("1cupsCloseDestJob: Bad arguments.");
86 return (IPP_STATUS_ERROR_INTERNAL
);
90 * Build a Close-Job or empty Send-Document request...
93 if ((attr
= ippFindAttribute(info
->attrs
, "operations-supported",
94 IPP_TAG_ENUM
)) != NULL
)
96 for (i
= 0; i
< attr
->num_values
; i
++)
97 if (attr
->values
[i
].integer
== IPP_OP_CLOSE_JOB
)
99 request
= ippNewRequest(IPP_OP_CLOSE_JOB
);
105 request
= ippNewRequest(IPP_OP_SEND_DOCUMENT
);
109 _cupsSetError(IPP_STATUS_ERROR_INTERNAL
, strerror(ENOMEM
), 0);
110 DEBUG_puts("1cupsCloseDestJob: Unable to create Close-Job/Send-Document "
112 return (IPP_STATUS_ERROR_INTERNAL
);
115 ippSetVersion(request
, info
->version
/ 10, info
->version
% 10);
117 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
, "printer-uri",
119 ippAddInteger(request
, IPP_TAG_OPERATION
, IPP_TAG_INTEGER
, "job-id",
121 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_NAME
, "requesting-user-name",
123 if (ippGetOperation(request
) == IPP_OP_SEND_DOCUMENT
)
124 ippAddBoolean(request
, IPP_TAG_OPERATION
, "last-document", 1);
127 * Send the request and return the status...
130 ippDelete(cupsDoRequest(http
, request
, info
->resource
));
132 DEBUG_printf(("1cupsCloseDestJob: %s (%s)", ippErrorString(cupsLastError()),
133 cupsLastErrorString()));
135 return (cupsLastError());
140 * 'cupsCreateDestJob()' - Create a job on a destination.
142 * Returns @code IPP_STATUS_OK@ or @code IPP_STATUS_OK_SUBST@ on success, saving the job ID
143 * in the variable pointed to by "job_id".
145 * @since CUPS 1.6/OS X 10.8@
148 ipp_status_t
/* O - IPP status code */
150 http_t
*http
, /* I - Connection to destination */
151 cups_dest_t
*dest
, /* I - Destination */
152 cups_dinfo_t
*info
, /* I - Destination information */
153 int *job_id
, /* O - Job ID or 0 on error */
154 const char *title
, /* I - Job name */
155 int num_options
, /* I - Number of job options */
156 cups_option_t
*options
) /* I - Job options */
158 ipp_t
*request
, /* Create-Job request */
159 *response
; /* Create-Job response */
160 ipp_attribute_t
*attr
; /* job-id attribute */
163 DEBUG_printf(("cupsCreateDestJob(http=%p, dest=%p(%s/%s), info=%p, "
164 "job_id=%p, title=\"%s\", num_options=%d, options=%p)",
165 http
, dest
, dest
? dest
->name
: NULL
,
166 dest
? dest
->instance
: NULL
, info
, job_id
, title
, num_options
,
170 * Range check input...
176 if (!http
|| !dest
|| !info
|| !job_id
)
178 _cupsSetError(IPP_STATUS_ERROR_INTERNAL
, strerror(EINVAL
), 0);
179 DEBUG_puts("1cupsCreateDestJob: Bad arguments.");
180 return (IPP_STATUS_ERROR_INTERNAL
);
184 * Build a Create-Job request...
187 if ((request
= ippNewRequest(IPP_OP_CREATE_JOB
)) == NULL
)
189 _cupsSetError(IPP_STATUS_ERROR_INTERNAL
, strerror(ENOMEM
), 0);
190 DEBUG_puts("1cupsCreateDestJob: Unable to create Create-Job request.");
191 return (IPP_STATUS_ERROR_INTERNAL
);
194 ippSetVersion(request
, info
->version
/ 10, info
->version
% 10);
196 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
, "printer-uri",
198 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_NAME
, "requesting-user-name",
201 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_NAME
, "job-name", NULL
,
204 cupsEncodeOptions2(request
, num_options
, options
, IPP_TAG_OPERATION
);
205 cupsEncodeOptions2(request
, num_options
, options
, IPP_TAG_JOB
);
206 cupsEncodeOptions2(request
, num_options
, options
, IPP_TAG_SUBSCRIPTION
);
209 * Send the request and get the job-id...
212 response
= cupsDoRequest(http
, request
, info
->resource
);
214 if ((attr
= ippFindAttribute(response
, "job-id", IPP_TAG_INTEGER
)) != NULL
)
216 *job_id
= attr
->values
[0].integer
;
217 DEBUG_printf(("1cupsCreateDestJob: job-id=%d", *job_id
));
223 * Return the status code from the Create-Job request...
226 DEBUG_printf(("1cupsCreateDestJob: %s (%s)", ippErrorString(cupsLastError()),
227 cupsLastErrorString()));
229 return (cupsLastError());
234 * 'cupsFinishDestDocument()' - Finish the current document.
236 * Returns @code IPP_STATUS_OK@ or @code IPP_STATUS_OK_SUBST@ on success.
238 * @since CUPS 1.6/OS X 10.8@
241 ipp_status_t
/* O - Status of document submission */
242 cupsFinishDestDocument(
243 http_t
*http
, /* I - Connection to destination */
244 cups_dest_t
*dest
, /* I - Destination */
245 cups_dinfo_t
*info
) /* I - Destination information */
247 DEBUG_printf(("cupsFinishDestDocument(http=%p, dest=%p(%s/%s), info=%p)",
248 http
, dest
, dest
? dest
->name
: NULL
,
249 dest
? dest
->instance
: NULL
, info
));
252 * Range check input...
255 if (!http
|| !dest
|| !info
)
257 _cupsSetError(IPP_STATUS_ERROR_INTERNAL
, strerror(EINVAL
), 0);
258 DEBUG_puts("1cupsFinishDestDocument: Bad arguments.");
259 return (IPP_STATUS_ERROR_INTERNAL
);
263 * Get the response at the end of the document and return it...
266 ippDelete(cupsGetResponse(http
, info
->resource
));
268 DEBUG_printf(("1cupsFinishDestDocument: %s (%s)",
269 ippErrorString(cupsLastError()), cupsLastErrorString()));
271 return (cupsLastError());
276 * 'cupsStartDestDocument()' - Start a new document.
278 * "job_id" is the job ID returned by cupsCreateDestJob. "docname" is the name
279 * of the document/file being printed, "format" is the MIME media type for the
280 * document (see CUPS_FORMAT_xxx constants), and "num_options" and "options"
281 * are the options do be applied to the document. "last_document" should be 1
282 * if this is the last document to be submitted in the job. Returns
283 * @code HTTP_CONTINUE@ on success.
285 * @since CUPS 1.6/OS X 10.8@
288 http_status_t
/* O - Status of document creation */
289 cupsStartDestDocument(
290 http_t
*http
, /* I - Connection to destination */
291 cups_dest_t
*dest
, /* I - Destination */
292 cups_dinfo_t
*info
, /* I - Destination information */
293 int job_id
, /* I - Job ID */
294 const char *docname
, /* I - Document name */
295 const char *format
, /* I - Document format */
296 int num_options
, /* I - Number of document options */
297 cups_option_t
*options
, /* I - Document options */
298 int last_document
) /* I - 1 if this is the last document */
300 ipp_t
*request
; /* Send-Document request */
301 http_status_t status
; /* HTTP status */
304 DEBUG_printf(("cupsStartDestDocument(http=%p, dest=%p(%s/%s), info=%p, "
305 "job_id=%d, docname=\"%s\", format=\"%s\", num_options=%d, "
306 "options=%p, last_document=%d)",
307 http
, dest
, dest
? dest
->name
: NULL
,
308 dest
? dest
->instance
: NULL
, info
, job_id
, docname
, format
,
309 num_options
, options
, last_document
));
312 * Range check input...
315 if (!http
|| !dest
|| !info
|| job_id
<= 0)
317 _cupsSetError(IPP_STATUS_ERROR_INTERNAL
, strerror(EINVAL
), 0);
318 DEBUG_puts("1cupsStartDestDocument: Bad arguments.");
319 return (HTTP_STATUS_ERROR
);
323 * Create a Send-Document request...
326 if ((request
= ippNewRequest(IPP_OP_SEND_DOCUMENT
)) == NULL
)
328 _cupsSetError(IPP_STATUS_ERROR_INTERNAL
, strerror(ENOMEM
), 0);
329 DEBUG_puts("1cupsStartDestDocument: Unable to create Send-Document "
331 return (HTTP_STATUS_ERROR
);
334 ippSetVersion(request
, info
->version
/ 10, info
->version
% 10);
336 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
, "printer-uri",
338 ippAddInteger(request
, IPP_TAG_OPERATION
, IPP_TAG_INTEGER
, "job-id", job_id
);
339 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_NAME
, "requesting-user-name",
342 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_NAME
, "document-name",
345 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_MIMETYPE
,
346 "document-format", NULL
, format
);
347 ippAddBoolean(request
, IPP_TAG_OPERATION
, "last-document", last_document
);
349 cupsEncodeOptions2(request
, num_options
, options
, IPP_TAG_OPERATION
);
350 cupsEncodeOptions2(request
, num_options
, options
, IPP_TAG_DOCUMENT
);
353 * Send and delete the request, then return the status...
356 status
= cupsSendRequest(http
, request
, info
->resource
, CUPS_LENGTH_VARIABLE
);