]> git.ipfire.org Git - thirdparty/cups.git/blobdiff - backend/ipp.c
Fix printing to some IPP Everywhere printers (Issue #5238)
[thirdparty/cups.git] / backend / ipp.c
index a338577f9dc20de788a658b7fb902cf9444f9524..dbbb029f189020d5dfff2878ae4694d46246a3b2 100644 (file)
@@ -1,16 +1,11 @@
 /*
  * IPP backend for CUPS.
  *
- * Copyright 2007-2016 by Apple Inc.
- * Copyright 1997-2007 by Easy Software Products, all rights reserved.
+ * Copyright © 2007-2018 by Apple Inc.
+ * Copyright © 1997-2007 by Easy Software Products, all rights reserved.
  *
- * 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"
- * "LICENSE" which should have been included with this file.  If this
- * file is missing or damaged, see the license at "http://www.cups.org/".
- *
- * This file is subject to the Apple OS-Developed Software exception.
+ * Licensed under Apache License v2.0.  See the file "LICENSE" for more
+ * information.
  */
 
 /*
@@ -47,6 +42,8 @@ extern void   xpc_connection_set_target_uid(xpc_connection_t connection,
 #define _CUPS_JSR_ACCOUNT_LIMIT_REACHED                0x08
 #define _CUPS_JSR_JOB_PASSWORD_WAIT            0x10
 #define _CUPS_JSR_JOB_RELEASE_WAIT             0x20
+#define _CUPS_JSR_DOCUMENT_FORMAT_ERROR                0x40
+#define _CUPS_JSR_DOCUMENT_UNPRINTABLE         0x80
 
 
 /*
@@ -69,6 +66,7 @@ typedef struct _cups_monitor_s                /**** Monitoring data ****/
   http_encryption_t    encryption;     /* Use encryption? */
   ipp_jstate_t         job_state;      /* Current job state */
   ipp_pstate_t         printer_state;  /* Current printer state */
+  int                  retryable;      /* Is this a job that should be retried? */
 } _cups_monitor_t;
 
 
@@ -357,8 +355,7 @@ main(int  argc,                             /* I - Number of command-line args */
   * that way.
   */
 
-  if (!getuid() && (value = getenv("AUTH_UID")) != NULL &&
-      !getenv("AUTH_PASSWORD"))
+  if (!getuid() && (value = getenv("AUTH_UID")) != NULL)
   {
     uid_t      uid = (uid_t)atoi(value);
                                        /* User ID */
@@ -743,8 +740,7 @@ main(int  argc,                             /* I - Number of command-line args */
 
       fprintf(stderr, "DEBUG: Connection error: %s\n", strerror(errno));
 
-      if (errno == ECONNREFUSED || errno == EHOSTDOWN ||
-          errno == EHOSTUNREACH)
+      if (errno == ECONNREFUSED || errno == EHOSTDOWN || errno == EHOSTUNREACH || errno == ETIMEDOUT || errno == ENOTCONN)
       {
         if (contimeout && (time(NULL) - start_time) > contimeout)
        {
@@ -763,13 +759,13 @@ main(int  argc,                           /* I - Number of command-line args */
              break;
 
          case EHOSTUNREACH :
+         default :
              _cupsLangPrintFilter(stderr, "WARNING",
                                   _("The printer is unreachable at this "
                                     "time."));
              break;
 
          case ECONNREFUSED :
-         default :
              _cupsLangPrintFilter(stderr, "WARNING",
                                   _("The printer is in use."));
              break;
@@ -1449,6 +1445,7 @@ main(int  argc,                           /* I - Number of command-line args */
   monitor.encryption    = cupsEncryption();
   monitor.job_state     = IPP_JOB_PENDING;
   monitor.printer_state = IPP_PRINTER_IDLE;
+  monitor.retryable     = argc == 6 && document_format && strcmp(document_format, "image/pwg-raster") && strcmp(document_format, "image/urf");
 
   if (create_job)
   {
@@ -1469,7 +1466,7 @@ main(int  argc,                           /* I - Number of command-line args */
 
   while (!job_canceled && validate_job)
   {
-    request = new_request(IPP_VALIDATE_JOB, version, uri, argv[2],
+    request = new_request(IPP_OP_VALIDATE_JOB, version, uri, argv[2],
                           monitor.job_name, num_options, options, compression,
                          copies_sup ? copies : 1, document_format, pc, ppd,
                          media_col_sup, doc_handling_sup, print_color_mode_sup);
@@ -1533,6 +1530,8 @@ main(int  argc,                           /* I - Number of command-line args */
     else if (ipp_status < IPP_REDIRECTION_OTHER_SITE ||
              ipp_status == IPP_BAD_REQUEST)
       break;
+    else if (job_auth == NULL && ipp_status > IPP_BAD_REQUEST)
+      goto cleanup;
   }
 
  /*
@@ -2216,7 +2215,7 @@ main(int  argc,                           /* I - Number of command-line args */
     return (CUPS_BACKEND_HOLD);
   else if (ipp_status == IPP_INTERNAL_ERROR)
     return (CUPS_BACKEND_STOP);
-  else if (ipp_status == IPP_CONFLICT)
+  else if (ipp_status == IPP_CONFLICT || ipp_status == IPP_STATUS_ERROR_REQUEST_ENTITY || ipp_status == IPP_STATUS_ERROR_REQUEST_VALUE)
     return (CUPS_BACKEND_FAILED);
   else if (ipp_status == IPP_REQUEST_VALUE ||
           ipp_status == IPP_STATUS_ERROR_ATTRIBUTES_OR_VALUES ||
@@ -2430,10 +2429,13 @@ monitor_printer(
   while (monitor->job_state < IPP_JOB_CANCELED && !job_canceled)
   {
    /*
-    * Reconnect to the printer...
+    * Reconnect to the printer as needed...
     */
 
-    if (!httpReconnect(http))
+    if (httpGetFd(http) < 0)
+      httpReconnect(http);
+
+    if (httpGetFd(http) >= 0)
     {
      /*
       * Connected, so check on the printer state...
@@ -2452,7 +2454,7 @@ monitor_printer(
         * No job-id yet, so continue...
        */
 
-        goto monitor_disconnect;
+        goto monitor_sleep;
       }
 
      /*
@@ -2564,22 +2566,24 @@ monitor_printer(
 
         for (i = 0; i < attr->num_values; i ++)
         {
-          if (!strcmp(attr->values[i].string.text,
-                      "account-authorization-failed"))
+          if (!strcmp(attr->values[i].string.text, "account-authorization-failed"))
             new_reasons |= _CUPS_JSR_ACCOUNT_AUTHORIZATION_FAILED;
           else if (!strcmp(attr->values[i].string.text, "account-closed"))
             new_reasons |= _CUPS_JSR_ACCOUNT_CLOSED;
           else if (!strcmp(attr->values[i].string.text, "account-info-needed"))
             new_reasons |= _CUPS_JSR_ACCOUNT_INFO_NEEDED;
-          else if (!strcmp(attr->values[i].string.text,
-                           "account-limit-reached"))
+          else if (!strcmp(attr->values[i].string.text, "account-limit-reached"))
             new_reasons |= _CUPS_JSR_ACCOUNT_LIMIT_REACHED;
           else if (!strcmp(attr->values[i].string.text, "job-password-wait"))
             new_reasons |= _CUPS_JSR_JOB_PASSWORD_WAIT;
           else if (!strcmp(attr->values[i].string.text, "job-release-wait"))
             new_reasons |= _CUPS_JSR_JOB_RELEASE_WAIT;
-         if (!job_canceled &&
-             (!strncmp(attr->values[i].string.text, "job-canceled-", 13) || !strcmp(attr->values[i].string.text, "aborted-by-system")))
+          else if (!strcmp(attr->values[i].string.text, "document-format-error"))
+            new_reasons |= _CUPS_JSR_DOCUMENT_FORMAT_ERROR;
+          else if (!strcmp(attr->values[i].string.text, "document-unprintable"))
+            new_reasons |= _CUPS_JSR_DOCUMENT_UNPRINTABLE;
+
+         if (!job_canceled && (!strncmp(attr->values[i].string.text, "job-canceled-", 13) || !strcmp(attr->values[i].string.text, "aborted-by-system")))
             job_canceled = 1;
         }
 
@@ -2597,6 +2601,26 @@ monitor_printer(
            fputs("JOBSTATE: job-password-wait\n", stderr);
          else if (new_reasons & _CUPS_JSR_JOB_RELEASE_WAIT)
            fputs("JOBSTATE: job-release-wait\n", stderr);
+          else if (new_reasons & (_CUPS_JSR_DOCUMENT_FORMAT_ERROR | _CUPS_JSR_DOCUMENT_UNPRINTABLE))
+          {
+            if (monitor->retryable)
+            {
+             /*
+              * Can't print this, so retry as raster...
+              */
+
+              job_canceled = 1;
+              fputs("JOBSTATE: cups-retry-as-raster\n", stderr);
+           }
+           else if (new_reasons & _CUPS_JSR_DOCUMENT_FORMAT_ERROR)
+           {
+             fputs("JOBSTATE: document-format-error\n", stderr);
+           }
+           else
+           {
+             fputs("JOBSTATE: document-unprintable\n", stderr);
+           }
+          }
          else
            fputs("JOBSTATE: job-printing\n", stderr);
 
@@ -2613,20 +2637,14 @@ monitor_printer(
           (monitor->job_state == IPP_JOB_CANCELED ||
           monitor->job_state == IPP_JOB_ABORTED))
        job_canceled = -1;
-
-     /*
-      * Disconnect from the printer - we'll reconnect on the next poll...
-      */
-
-      monitor_disconnect:
-
-      _httpDisconnect(http);
     }
 
    /*
     * Sleep for N seconds...
     */
 
+    monitor_sleep:
+
     sleep((unsigned)delay);
 
     delay = _cupsNextDelay(delay, &prev_delay);
@@ -2638,7 +2656,10 @@ monitor_printer(
 
   if (job_canceled > 0 && monitor->job_id > 0)
   {
-    if (!httpReconnect(http))
+    if (httpGetFd(http) < 0)
+      httpReconnect(http);
+
+    if (httpGetFd(http) >= 0)
     {
       cancel_job(http, monitor->uri, monitor->job_id, monitor->resource,
                  monitor->user, monitor->version);