]> git.ipfire.org Git - thirdparty/cups.git/blobdiff - cups/dest-job.c
Changelog.
[thirdparty/cups.git] / cups / dest-job.c
index 31cac7903c11c3f429c394ab5652426e1a3630ae..f4e5b335c608dd82c24c29b70614dbf0a4231f27 100644 (file)
@@ -1,25 +1,9 @@
 /*
- * "$Id$"
+ * Destination job support for CUPS.
  *
- *   Destination job support for CUPS.
+ * Copyright 2012-2017 by Apple Inc.
  *
- *   Copyright 2012 by Apple Inc.
- *
- *   These coded instructions, statements, and computer programs are the
- *   property of Apple Inc. and are protected by Federal copyright
- *   law.  Distribution and use rights are outlined in the file "LICENSE.txt"
- *   which should have been included with this file.  If this file is
- *   file is missing or damaged, see the license at "http://www.cups.org/".
- *
- *   This file is subject to the Apple OS-Developed Software exception.
- *
- * Contents:
- *
- *   cupsCancelDestJob()      - Cancel a job on a destination.
- *   cupsCloseDestJob()       - Close a job and start printing.
- *   cupsCreateDestJob()      - Create a job on a destination.
- *   cupsFinishDestDocument() - Finish the current document.
- *   cupsStartDestDocument()  - Start a new document.
+ * Licensed under Apache License v2.0.  See the file "LICENSE" for more information.
  */
 
 /*
@@ -27,6 +11,7 @@
  */
 
 #include "cups-private.h"
+#include "debug-internal.h"
 
 
 /*
  *
  * The "job_id" is the number returned by cupsCreateDestJob.
  *
- * Returns IPP_OK on success and IPP_NOT_AUTHORIZED or IPP_FORBIDDEN on
- * failure.
+ * Returns @code IPP_STATUS_OK@ on success and
+ * @code IPP_STATUS_ERROR_NOT_AUTHORIZED@ or
+ * @code IPP_STATUS_ERROR_FORBIDDEN@ on failure.
  *
- * @since CUPS 1.6@
+ * @since CUPS 1.6/macOS 10.8@
  */
 
-ipp_status_t
+ipp_status_t                            /* O - Status of cancel operation */
 cupsCancelDestJob(http_t      *http,   /* I - Connection to destination */
                   cups_dest_t *dest,   /* I - Destination */
                   int         job_id)  /* I - Job ID */
 {
-  return (IPP_NOT_FOUND);
+  cups_dinfo_t *info;                  /* Destination information */
+
+
+  if ((info = cupsCopyDestInfo(http, dest)) != NULL)
+  {
+    ipp_t      *request;               /* Cancel-Job request */
+
+    request = ippNewRequest(IPP_OP_CANCEL_JOB);
+
+    ippSetVersion(request, info->version / 10, info->version % 10);
+
+    ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, info->uri);
+    ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER, "job-id", job_id);
+    ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsUser());
+
+    ippDelete(cupsDoRequest(http, request, info->resource));
+    cupsFreeDestInfo(info);
+  }
+
+  return (cupsLastError());
 }
 
 
@@ -53,29 +58,101 @@ cupsCancelDestJob(http_t      *http,       /* I - Connection to destination */
  * 'cupsCloseDestJob()' - Close a job and start printing.
  *
  * Use when the last call to cupsStartDocument passed 0 for "last_document".
- * "job_id" is the job ID returned by cupsCreateDestJob. Returns IPP_OK on
- * success.
+ * "job_id" is the job ID returned by cupsCreateDestJob. Returns @code IPP_STATUS_OK@
+ * on success.
  *
- * @since CUPS 1.6@
+ * @since CUPS 1.6/macOS 10.8@
  */
 
-ipp_status_t
+ipp_status_t                           /* O - IPP status code */
 cupsCloseDestJob(
-    http_t      *http,                 /* I - Connection to destination */
-    cups_dest_t *dest,                 /* I - Destination */
-    int         job_id)                        /* I - Job ID */
+    http_t       *http,                        /* I - Connection to destination */
+    cups_dest_t  *dest,                        /* I - Destination */
+    cups_dinfo_t *info,                /* I - Destination information */
+    int          job_id)               /* I - Job ID */
 {
-  return (IPP_NOT_FOUND);
+  int                  i;              /* Looping var */
+  ipp_t                        *request = NULL;/* Close-Job/Send-Document request */
+  ipp_attribute_t      *attr;          /* operations-supported attribute */
+
+
+  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));
+
+ /*
+  * Get the default connection as needed...
+  */
+
+  if (!http)
+    http = _cupsConnect();
+
+ /*
+  * Range check input...
+  */
+
+  if (!http || !dest || !info || job_id <= 0)
+  {
+    _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(EINVAL), 0);
+    DEBUG_puts("1cupsCloseDestJob: Bad arguments.");
+    return (IPP_STATUS_ERROR_INTERNAL);
+  }
+
+ /*
+  * Build a Close-Job or empty Send-Document request...
+  */
+
+  if ((attr = ippFindAttribute(info->attrs, "operations-supported",
+                               IPP_TAG_ENUM)) != NULL)
+  {
+    for (i = 0; i < attr->num_values; i ++)
+      if (attr->values[i].integer == IPP_OP_CLOSE_JOB)
+      {
+        request = ippNewRequest(IPP_OP_CLOSE_JOB);
+        break;
+      }
+  }
+
+  if (!request)
+    request = ippNewRequest(IPP_OP_SEND_DOCUMENT);
+
+  if (!request)
+  {
+    _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(ENOMEM), 0);
+    DEBUG_puts("1cupsCloseDestJob: Unable to create Close-Job/Send-Document "
+               "request.");
+    return (IPP_STATUS_ERROR_INTERNAL);
+  }
+
+  ippSetVersion(request, info->version / 10, info->version % 10);
+
+  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
+               NULL, info->uri);
+  ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER, "job-id",
+                job_id);
+  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
+               NULL, cupsUser());
+  if (ippGetOperation(request) == IPP_OP_SEND_DOCUMENT)
+    ippAddBoolean(request, IPP_TAG_OPERATION, "last-document", 1);
+
+ /*
+  * Send the request and return the status...
+  */
+
+  ippDelete(cupsDoRequest(http, request, info->resource));
+
+  DEBUG_printf(("1cupsCloseDestJob: %s (%s)", ippErrorString(cupsLastError()),
+                cupsLastErrorString()));
+
+  return (cupsLastError());
 }
 
 
 /*
  * 'cupsCreateDestJob()' - Create a job on a destination.
  *
- * Returns IPP_OK or IPP_OK_SUBST on success, saving the job ID in the variable
- * pointed to by "job_id".
+ * Returns @code IPP_STATUS_OK@ or @code IPP_STATUS_OK_SUBST@ on success, saving the job ID
+ * in the variable pointed to by "job_id".
  *
- * @since CUPS 1.6@
+ * @since CUPS 1.6/macOS 10.8@
  */
 
 ipp_status_t                           /* O - IPP status code */
@@ -88,26 +165,129 @@ cupsCreateDestJob(
     int           num_options,         /* I - Number of job options */
     cups_option_t *options)            /* I - Job options */
 {
-  *job_id = 0;
+  ipp_t                        *request,       /* Create-Job request */
+                       *response;      /* Create-Job response */
+  ipp_attribute_t      *attr;          /* job-id attribute */
+
+
+  DEBUG_printf(("cupsCreateDestJob(http=%p, dest=%p(%s/%s), info=%p, "
+                "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));
+
+ /*
+  * Get the default connection as needed...
+  */
+
+  if (!http)
+    http = _cupsConnect();
+
+ /*
+  * Range check input...
+  */
+
+  if (job_id)
+    *job_id = 0;
+
+  if (!http || !dest || !info || !job_id)
+  {
+    _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(EINVAL), 0);
+    DEBUG_puts("1cupsCreateDestJob: Bad arguments.");
+    return (IPP_STATUS_ERROR_INTERNAL);
+  }
+
+ /*
+  * Build a Create-Job request...
+  */
 
-  return (IPP_NOT_POSSIBLE);
+  if ((request = ippNewRequest(IPP_OP_CREATE_JOB)) == NULL)
+  {
+    _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(ENOMEM), 0);
+    DEBUG_puts("1cupsCreateDestJob: Unable to create Create-Job request.");
+    return (IPP_STATUS_ERROR_INTERNAL);
+  }
+
+  ippSetVersion(request, info->version / 10, info->version % 10);
+
+  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
+               NULL, info->uri);
+  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
+               NULL, cupsUser());
+  if (title)
+    ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "job-name", NULL,
+                 title);
+
+  cupsEncodeOptions2(request, num_options, options, IPP_TAG_OPERATION);
+  cupsEncodeOptions2(request, num_options, options, IPP_TAG_JOB);
+  cupsEncodeOptions2(request, num_options, options, IPP_TAG_SUBSCRIPTION);
+
+ /*
+  * Send the request and get the job-id...
+  */
+
+  response = cupsDoRequest(http, request, info->resource);
+
+  if ((attr = ippFindAttribute(response, "job-id", IPP_TAG_INTEGER)) != NULL)
+  {
+    *job_id = attr->values[0].integer;
+    DEBUG_printf(("1cupsCreateDestJob: job-id=%d", *job_id));
+  }
+
+  ippDelete(response);
+
+ /*
+  * Return the status code from the Create-Job request...
+  */
+
+  DEBUG_printf(("1cupsCreateDestJob: %s (%s)", ippErrorString(cupsLastError()),
+                cupsLastErrorString()));
+
+  return (cupsLastError());
 }
 
 
 /*
  * 'cupsFinishDestDocument()' - Finish the current document.
  *
- * Returns IPP_OK on success.
+ * Returns @code IPP_STATUS_OK@ or @code IPP_STATUS_OK_SUBST@ on success.
  *
- * @since CUPS 1.6@
+ * @since CUPS 1.6/macOS 10.8@
  */
 
-ipp_status_t
+ipp_status_t                           /* O - Status of document submission */
 cupsFinishDestDocument(
-    http_t      *http,                 /* I - Connection to destination */
-    cups_dest_t *dest)                 /* I - Destination */
+    http_t       *http,                        /* I - Connection to destination */
+    cups_dest_t  *dest,                        /* I - Destination */
+    cups_dinfo_t *info)                /* I - Destination information */
 {
-  return (IPP_NOT_FOUND);
+  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));
+
+ /*
+  * Get the default connection as needed...
+  */
+
+  if (!http)
+    http = _cupsConnect();
+
+ /*
+  * Range check input...
+  */
+
+  if (!http || !dest || !info)
+  {
+    _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(EINVAL), 0);
+    DEBUG_puts("1cupsFinishDestDocument: Bad arguments.");
+    return (IPP_STATUS_ERROR_INTERNAL);
+  }
+
+ /*
+  * Get the response at the end of the document and return it...
+  */
+
+  ippDelete(cupsGetResponse(http, info->resource));
+
+  DEBUG_printf(("1cupsFinishDestDocument: %s (%s)",
+                ippErrorString(cupsLastError()), cupsLastErrorString()));
+
+  return (cupsLastError());
 }
 
 
@@ -119,12 +299,12 @@ cupsFinishDestDocument(
  * document (see CUPS_FORMAT_xxx constants), and "num_options" and "options"
  * are the options do be applied to the document. "last_document" should be 1
  * if this is the last document to be submitted in the job.  Returns
- * HTTP_CONTINUE on success.
+ * @code HTTP_CONTINUE@ on success.
  *
- * @since CUPS 1.6@
+ * @since CUPS 1.6/macOS 10.8@
  */
 
-http_status_t
+http_status_t                          /* O - Status of document creation */
 cupsStartDestDocument(
     http_t        *http,               /* I - Connection to destination */
     cups_dest_t   *dest,               /* I - Destination */
@@ -136,10 +316,67 @@ cupsStartDestDocument(
     cups_option_t *options,            /* I - Document options */
     int           last_document)       /* I - 1 if this is the last document */
 {
-  return (HTTP_CONTINUE);
-}
+  ipp_t                *request;               /* Send-Document request */
+  http_status_t        status;                 /* HTTP status */
 
 
-/*
- * End of "$Id$".
- */
+  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));
+
+ /*
+  * Get the default connection as needed...
+  */
+
+  if (!http)
+    http = _cupsConnect();
+
+ /*
+  * Range check input...
+  */
+
+  if (!http || !dest || !info || job_id <= 0)
+  {
+    _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(EINVAL), 0);
+    DEBUG_puts("1cupsStartDestDocument: Bad arguments.");
+    return (HTTP_STATUS_ERROR);
+  }
+
+ /*
+  * Create a Send-Document request...
+  */
+
+  if ((request = ippNewRequest(IPP_OP_SEND_DOCUMENT)) == NULL)
+  {
+    _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(ENOMEM), 0);
+    DEBUG_puts("1cupsStartDestDocument: Unable to create Send-Document "
+               "request.");
+    return (HTTP_STATUS_ERROR);
+  }
+
+  ippSetVersion(request, info->version / 10, info->version % 10);
+
+  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
+               NULL, info->uri);
+  ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER, "job-id", job_id);
+  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
+               NULL, cupsUser());
+  if (docname)
+    ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "document-name",
+                 NULL, docname);
+  if (format)
+    ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_MIMETYPE,
+                 "document-format", NULL, format);
+  ippAddBoolean(request, IPP_TAG_OPERATION, "last-document", (char)last_document);
+
+  cupsEncodeOptions2(request, num_options, options, IPP_TAG_OPERATION);
+  cupsEncodeOptions2(request, num_options, options, IPP_TAG_DOCUMENT);
+
+ /*
+  * Send and delete the request, then return the status...
+  */
+
+  status = cupsSendRequest(http, request, info->resource, CUPS_LENGTH_VARIABLE);
+
+  ippDelete(request);
+
+  return (status);
+}