2 * Destination job support for CUPS.
4 * Copyright 2012-2016 by Apple Inc.
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/".
12 * This file is subject to the Apple OS-Developed Software exception.
16 * Include necessary headers...
19 #include "cups-private.h"
23 * 'cupsCancelDestJob()' - Cancel a job on a destination.
25 * The "job_id" is the number returned by cupsCreateDestJob.
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.
31 * @since CUPS 1.6/macOS 10.8@
35 cupsCancelDestJob(http_t
*http
, /* I - Connection to destination */
36 cups_dest_t
*dest
, /* I - Destination */
37 int job_id
) /* I - Job ID */
39 cups_dinfo_t
*info
; /* Destination information */
42 if ((info
= cupsCopyDestInfo(http
, dest
)) != NULL
)
44 ipp_t
*request
; /* Cancel-Job request */
46 request
= ippNewRequest(IPP_OP_CANCEL_JOB
);
48 ippSetVersion(request
, info
->version
/ 10, info
->version
% 10);
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());
54 ippDelete(cupsDoRequest(http
, request
, info
->resource
));
55 cupsFreeDestInfo(info
);
58 return (cupsLastError());
63 * 'cupsCloseDestJob()' - Close a job and start printing.
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@
69 * @since CUPS 1.6/macOS 10.8@
72 ipp_status_t
/* O - IPP status code */
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 */
79 int i
; /* Looping var */
80 ipp_t
*request
= NULL
;/* Close-Job/Send-Document request */
81 ipp_attribute_t
*attr
; /* operations-supported attribute */
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
));
87 * Range check input...
90 if (!http
|| !dest
|| !info
|| job_id
<= 0)
92 _cupsSetError(IPP_STATUS_ERROR_INTERNAL
, strerror(EINVAL
), 0);
93 DEBUG_puts("1cupsCloseDestJob: Bad arguments.");
94 return (IPP_STATUS_ERROR_INTERNAL
);
98 * Build a Close-Job or empty Send-Document request...
101 if ((attr
= ippFindAttribute(info
->attrs
, "operations-supported",
102 IPP_TAG_ENUM
)) != NULL
)
104 for (i
= 0; i
< attr
->num_values
; i
++)
105 if (attr
->values
[i
].integer
== IPP_OP_CLOSE_JOB
)
107 request
= ippNewRequest(IPP_OP_CLOSE_JOB
);
113 request
= ippNewRequest(IPP_OP_SEND_DOCUMENT
);
117 _cupsSetError(IPP_STATUS_ERROR_INTERNAL
, strerror(ENOMEM
), 0);
118 DEBUG_puts("1cupsCloseDestJob: Unable to create Close-Job/Send-Document "
120 return (IPP_STATUS_ERROR_INTERNAL
);
123 ippSetVersion(request
, info
->version
/ 10, info
->version
% 10);
125 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
, "printer-uri",
127 ippAddInteger(request
, IPP_TAG_OPERATION
, IPP_TAG_INTEGER
, "job-id",
129 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_NAME
, "requesting-user-name",
131 if (ippGetOperation(request
) == IPP_OP_SEND_DOCUMENT
)
132 ippAddBoolean(request
, IPP_TAG_OPERATION
, "last-document", 1);
135 * Send the request and return the status...
138 ippDelete(cupsDoRequest(http
, request
, info
->resource
));
140 DEBUG_printf(("1cupsCloseDestJob: %s (%s)", ippErrorString(cupsLastError()),
141 cupsLastErrorString()));
143 return (cupsLastError());
148 * 'cupsCreateDestJob()' - Create a job on a destination.
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".
153 * @since CUPS 1.6/macOS 10.8@
156 ipp_status_t
/* O - IPP status code */
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 */
166 ipp_t
*request
, /* Create-Job request */
167 *response
; /* Create-Job response */
168 ipp_attribute_t
*attr
; /* job-id attribute */
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
));
175 * Range check input...
181 if (!http
|| !dest
|| !info
|| !job_id
)
183 _cupsSetError(IPP_STATUS_ERROR_INTERNAL
, strerror(EINVAL
), 0);
184 DEBUG_puts("1cupsCreateDestJob: Bad arguments.");
185 return (IPP_STATUS_ERROR_INTERNAL
);
189 * Build a Create-Job request...
192 if ((request
= ippNewRequest(IPP_OP_CREATE_JOB
)) == NULL
)
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
);
199 ippSetVersion(request
, info
->version
/ 10, info
->version
% 10);
201 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
, "printer-uri",
203 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_NAME
, "requesting-user-name",
206 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_NAME
, "job-name", NULL
,
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
);
214 * Send the request and get the job-id...
217 response
= cupsDoRequest(http
, request
, info
->resource
);
219 if ((attr
= ippFindAttribute(response
, "job-id", IPP_TAG_INTEGER
)) != NULL
)
221 *job_id
= attr
->values
[0].integer
;
222 DEBUG_printf(("1cupsCreateDestJob: job-id=%d", *job_id
));
228 * Return the status code from the Create-Job request...
231 DEBUG_printf(("1cupsCreateDestJob: %s (%s)", ippErrorString(cupsLastError()),
232 cupsLastErrorString()));
234 return (cupsLastError());
239 * 'cupsFinishDestDocument()' - Finish the current document.
241 * Returns @code IPP_STATUS_OK@ or @code IPP_STATUS_OK_SUBST@ on success.
243 * @since CUPS 1.6/macOS 10.8@
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 */
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
));
255 * Range check input...
258 if (!http
|| !dest
|| !info
)
260 _cupsSetError(IPP_STATUS_ERROR_INTERNAL
, strerror(EINVAL
), 0);
261 DEBUG_puts("1cupsFinishDestDocument: Bad arguments.");
262 return (IPP_STATUS_ERROR_INTERNAL
);
266 * Get the response at the end of the document and return it...
269 ippDelete(cupsGetResponse(http
, info
->resource
));
271 DEBUG_printf(("1cupsFinishDestDocument: %s (%s)",
272 ippErrorString(cupsLastError()), cupsLastErrorString()));
274 return (cupsLastError());
279 * 'cupsStartDestDocument()' - Start a new document.
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.
288 * @since CUPS 1.6/macOS 10.8@
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 */
303 ipp_t
*request
; /* Send-Document request */
304 http_status_t status
; /* HTTP status */
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
));
310 * Range check input...
313 if (!http
|| !dest
|| !info
|| job_id
<= 0)
315 _cupsSetError(IPP_STATUS_ERROR_INTERNAL
, strerror(EINVAL
), 0);
316 DEBUG_puts("1cupsStartDestDocument: Bad arguments.");
317 return (HTTP_STATUS_ERROR
);
321 * Create a Send-Document request...
324 if ((request
= ippNewRequest(IPP_OP_SEND_DOCUMENT
)) == NULL
)
326 _cupsSetError(IPP_STATUS_ERROR_INTERNAL
, strerror(ENOMEM
), 0);
327 DEBUG_puts("1cupsStartDestDocument: Unable to create Send-Document "
329 return (HTTP_STATUS_ERROR
);
332 ippSetVersion(request
, info
->version
/ 10, info
->version
% 10);
334 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
, "printer-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",
340 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_NAME
, "document-name",
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
);
347 cupsEncodeOptions2(request
, num_options
, options
, IPP_TAG_OPERATION
);
348 cupsEncodeOptions2(request
, num_options
, options
, IPP_TAG_DOCUMENT
);
351 * Send and delete the request, then return the status...
354 status
= cupsSendRequest(http
, request
, info
->resource
, CUPS_LENGTH_VARIABLE
);