]> git.ipfire.org Git - thirdparty/cups.git/blobdiff - backend/ipp.c
Fix some new compiler warnings (Issue #5700)
[thirdparty/cups.git] / backend / ipp.c
index 2a2921db645006c540961d46391045bd3bb3f9a1..3f3e1867d3efb0b631b743a28b5a62e701386e31 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * IPP backend for CUPS.
  *
- * Copyright © 2007-2018 by Apple Inc.
+ * Copyright © 2007-2019 by Apple Inc.
  * Copyright © 1997-2007 by Easy Software Products, all rights reserved.
  *
  * Licensed under Apache License v2.0.  See the file "LICENSE" for more
 #  define kPMPrintUIToolAgent  "com.apple.printuitool.agent"
 #  define kPMStartJob          100
 #  define kPMWaitForJob                101
-#  ifdef HAVE_XPC_PRIVATE_H
-#    include <xpc/private.h>
-#  else
 extern void    xpc_connection_set_target_uid(xpc_connection_t connection,
                                              uid_t uid);
-#  endif /* HAVE_XPC_PRIVATE_H */
 #endif /* HAVE_GSSAPI && HAVE_XPC */
 
 
@@ -42,6 +38,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
 
 
 /*
@@ -64,6 +62,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;
 
 
@@ -234,7 +233,6 @@ main(int  argc,                             /* I - Number of command-line args */
   int          waitjob,                        /* Wait for job complete? */
                waitjob_tries = 0,      /* Number of times we've waited */
                waitprinter;            /* Wait for printer ready? */
-  time_t       waittime;               /* Wait time for held jobs */
   _cups_monitor_t monitor;             /* Monitoring data */
   ipp_attribute_t *job_id_attr;                /* job-id attribute */
   int          job_id;                 /* job-id value */
@@ -352,8 +350,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 */
@@ -387,7 +384,7 @@ main(int  argc,                             /* I - Number of command-line args */
 
 #  else /* No XPC, just try to run as the user ID */
     if (uid > 0)
-      seteuid(uid);
+      setuid(uid);
 #  endif /* HAVE_XPC */
   }
 #endif /* HAVE_GSSAPI */
@@ -419,9 +416,9 @@ main(int  argc,                             /* I - Number of command-line args */
     port = IPP_PORT;                   /* Default to port 631 */
 
   if (!strcmp(scheme, "https") || !strcmp(scheme, "ipps"))
-    cupsSetEncryption(HTTP_ENCRYPT_ALWAYS);
+    cupsSetEncryption(HTTP_ENCRYPTION_ALWAYS);
   else
-    cupsSetEncryption(HTTP_ENCRYPT_IF_REQUESTED);
+    cupsSetEncryption(HTTP_ENCRYPTION_IF_REQUESTED);
 
  /*
   * See if there are any options...
@@ -508,13 +505,13 @@ main(int  argc,                           /* I - Number of command-line args */
        */
 
         if (!_cups_strcasecmp(value, "always"))
-         cupsSetEncryption(HTTP_ENCRYPT_ALWAYS);
+         cupsSetEncryption(HTTP_ENCRYPTION_ALWAYS);
         else if (!_cups_strcasecmp(value, "required"))
-         cupsSetEncryption(HTTP_ENCRYPT_REQUIRED);
+         cupsSetEncryption(HTTP_ENCRYPTION_REQUIRED);
         else if (!_cups_strcasecmp(value, "never"))
-         cupsSetEncryption(HTTP_ENCRYPT_NEVER);
+         cupsSetEncryption(HTTP_ENCRYPTION_NEVER);
         else if (!_cups_strcasecmp(value, "ifrequested"))
-         cupsSetEncryption(HTTP_ENCRYPT_IF_REQUESTED);
+         cupsSetEncryption(HTTP_ENCRYPTION_IF_REQUESTED);
        else
        {
          _cupsLangPrintFilter(stderr, "ERROR",
@@ -702,11 +699,11 @@ main(int  argc,                           /* I - Number of command-line args */
     fprintf(stderr, "DEBUG: Connecting to %s:%d\n", hostname, port);
     _cupsLangPrintFilter(stderr, "INFO", _("Connecting to printer."));
 
-    if (httpReconnect(http))
+    if (httpReconnect2(http, 30000, NULL))
     {
       int error = errno;               /* Connection error */
 
-      if (http->status == HTTP_PKI_ERROR)
+      if (http->status == HTTP_STATUS_CUPS_PKI_ERROR)
        update_reasons(NULL, "+cups-certificate-error");
 
       if (job_canceled)
@@ -909,7 +906,7 @@ main(int  argc,                             /* I - Number of command-line args */
     * Build the IPP request...
     */
 
-    request = ippNewRequest(IPP_GET_PRINTER_ATTRIBUTES);
+    request = ippNewRequest(IPP_OP_GET_PRINTER_ATTRIBUTES);
     ippSetVersion(request, version / 10, version % 10);
     ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
                 NULL, uri);
@@ -924,7 +921,7 @@ main(int  argc,                             /* I - Number of command-line args */
 
     fputs("DEBUG: Getting supported attributes...\n", stderr);
 
-    if (http->version < HTTP_1_1)
+    if (http->version < HTTP_VERSION_1_1)
     {
       fprintf(stderr, "DEBUG: Printer responded with HTTP version %d.%d.\n",
               http->version / 100, http->version % 100);
@@ -938,15 +935,15 @@ main(int  argc,                           /* I - Number of command-line args */
     fprintf(stderr, "DEBUG: Get-Printer-Attributes: %s (%s)\n",
             ippErrorString(ipp_status), cupsLastErrorString());
 
-    if (ipp_status <= IPP_OK_CONFLICT)
+    if (ipp_status <= IPP_STATUS_OK_CONFLICTING)
       password_tries = 0;
     else
     {
       fprintf(stderr, "DEBUG: Get-Printer-Attributes returned %s.\n",
               ippErrorString(ipp_status));
 
-      if (ipp_status == IPP_PRINTER_BUSY ||
-         ipp_status == IPP_SERVICE_UNAVAILABLE)
+      if (ipp_status == IPP_STATUS_ERROR_BUSY ||
+         ipp_status == IPP_STATUS_ERROR_SERVICE_UNAVAILABLE)
       {
         if (contimeout && (time(NULL) - start_time) > contimeout)
        {
@@ -963,8 +960,8 @@ main(int  argc,                             /* I - Number of command-line args */
 
         delay = _cupsNextDelay(delay, &prev_delay);
       }
-      else if ((ipp_status == IPP_BAD_REQUEST ||
-               ipp_status == IPP_VERSION_NOT_SUPPORTED) && version > 10)
+      else if ((ipp_status == IPP_STATUS_ERROR_BAD_REQUEST ||
+               ipp_status == IPP_STATUS_ERROR_VERSION_NOT_SUPPORTED) && version > 10)
       {
        /*
        * Switch to IPP/1.1 or IPP/1.0...
@@ -987,9 +984,9 @@ main(int  argc,                             /* I - Number of command-line args */
          version = 10;
         }
 
-       httpReconnect(http);
+       httpReconnect2(http, 30000, NULL);
       }
-      else if (ipp_status == IPP_NOT_FOUND)
+      else if (ipp_status == IPP_STATUS_ERROR_NOT_FOUND)
       {
         _cupsLangPrintFilter(stderr, "ERROR",
                             _("The printer configuration is incorrect or the "
@@ -999,8 +996,8 @@ main(int  argc,                             /* I - Number of command-line args */
 
        return (CUPS_BACKEND_STOP);
       }
-      else if (ipp_status == IPP_FORBIDDEN ||
-               ipp_status == IPP_AUTHENTICATION_CANCELED)
+      else if (ipp_status == IPP_STATUS_ERROR_FORBIDDEN ||
+               ipp_status == IPP_STATUS_ERROR_CUPS_AUTHENTICATION_CANCELED)
       {
         const char *www_auth = httpGetField(http, HTTP_FIELD_WWW_AUTHENTICATE);
                                        /* WWW-Authenticate field value */
@@ -1013,13 +1010,13 @@ main(int  argc,                         /* I - Number of command-line args */
        fprintf(stderr, "ATTR: auth-info-required=%s\n", auth_info_required);
        return (CUPS_BACKEND_AUTH_REQUIRED);
       }
-      else if (ipp_status != IPP_NOT_AUTHORIZED)
+      else if (ipp_status != IPP_STATUS_ERROR_NOT_AUTHORIZED)
       {
        _cupsLangPrintFilter(stderr, "ERROR",
                             _("Unable to get printer status."));
         sleep(10);
 
-       httpReconnect(http);
+       httpReconnect2(http, 30000, NULL);
       }
 
       ippDelete(supported);
@@ -1133,7 +1130,14 @@ main(int  argc,                          /* I - Number of command-line args */
        copies_sup = NULL; /* No */
     }
 
-    cups_version = ippFindAttribute(supported, "cups-version", IPP_TAG_TEXT);
+    if ((cups_version = ippFindAttribute(supported, "cups-version", IPP_TAG_TEXT)) != NULL)
+    {
+      const char *val = ippGetString(cups_version, 0, NULL);
+
+      fprintf(stderr, "DEBUG: cups-version = \"%s\"\n", val);
+      if (!strcmp(val, "cups-version"))
+        cups_version = NULL;           /* Bogus cups-version value returned by buggy printers! */
+    }
 
     encryption_sup = ippFindAttribute(supported, "job-password-encryption-supported", IPP_TAG_KEYWORD);
 
@@ -1169,7 +1173,7 @@ main(int  argc,                           /* I - Number of command-line args */
                 ippOpString(operations_sup->values[i].integer));
 
       for (i = 0; i < operations_sup->num_values; i ++)
-        if (operations_sup->values[i].integer == IPP_PRINT_JOB)
+        if (operations_sup->values[i].integer == IPP_OP_PRINT_JOB)
          break;
 
       if (i >= operations_sup->num_values)
@@ -1177,7 +1181,7 @@ main(int  argc,                           /* I - Number of command-line args */
                             "cups-ipp-missing-print-job");
 
       for (i = 0; i < operations_sup->num_values; i ++)
-        if (operations_sup->values[i].integer == IPP_CANCEL_JOB)
+        if (operations_sup->values[i].integer == IPP_OP_CANCEL_JOB)
          break;
 
       if (i >= operations_sup->num_values)
@@ -1185,7 +1189,7 @@ main(int  argc,                           /* I - Number of command-line args */
                             "cups-ipp-missing-cancel-job");
 
       for (i = 0; i < operations_sup->num_values; i ++)
-        if (operations_sup->values[i].integer == IPP_GET_JOB_ATTRIBUTES)
+        if (operations_sup->values[i].integer == IPP_OP_GET_JOB_ATTRIBUTES)
          break;
 
       if (i >= operations_sup->num_values)
@@ -1193,7 +1197,7 @@ main(int  argc,                           /* I - Number of command-line args */
                              "cups-ipp-missing-get-job-attributes");
 
       for (i = 0; i < operations_sup->num_values; i ++)
-        if (operations_sup->values[i].integer == IPP_GET_PRINTER_ATTRIBUTES)
+        if (operations_sup->values[i].integer == IPP_OP_GET_PRINTER_ATTRIBUTES)
          break;
 
       if (i >= operations_sup->num_values)
@@ -1202,13 +1206,13 @@ main(int  argc,                         /* I - Number of command-line args */
 
       for (i = 0; i < operations_sup->num_values; i ++)
       {
-        if (operations_sup->values[i].integer == IPP_VALIDATE_JOB)
+        if (operations_sup->values[i].integer == IPP_OP_VALIDATE_JOB)
          validate_job = 1;
-        else if (operations_sup->values[i].integer == IPP_CREATE_JOB)
+        else if (operations_sup->values[i].integer == IPP_OP_CREATE_JOB)
          create_job = 1;
-        else if (operations_sup->values[i].integer == IPP_SEND_DOCUMENT)
+        else if (operations_sup->values[i].integer == IPP_OP_SEND_DOCUMENT)
          send_document = 1;
-        else if (operations_sup->values[i].integer == IPP_GET_JOB_ATTRIBUTES)
+        else if (operations_sup->values[i].integer == IPP_OP_GET_JOB_ATTRIBUTES)
          get_job_attrs = 1;
       }
 
@@ -1236,7 +1240,7 @@ main(int  argc,                           /* I - Number of command-line args */
 
     report_printer_state(supported);
   }
-  while (!job_canceled && ipp_status > IPP_OK_CONFLICT);
+  while (!job_canceled && ipp_status > IPP_STATUS_OK_CONFLICTING);
 
   if (job_canceled)
     return (CUPS_BACKEND_OK);
@@ -1254,7 +1258,7 @@ main(int  argc,                           /* I - Number of command-line args */
                                         IPP_TAG_BOOLEAN);
 
     if (printer_state == NULL ||
-       (printer_state->values[0].integer > IPP_PRINTER_PROCESSING &&
+       (printer_state->values[0].integer > IPP_PSTATE_PROCESSING &&
         waitprinter) ||
        printer_accepting == NULL ||
        !printer_accepting->values[0].boolean)
@@ -1380,7 +1384,7 @@ main(int  argc,                           /* I - Number of command-line args */
   * (I hate compatibility hacks!)
   */
 
-  if (http->version < HTTP_1_1 && num_files == 0)
+  if (http->version < HTTP_VERSION_1_1 && num_files == 0)
   {
     if ((fd = cupsTempFd(tmpfilename, sizeof(tmpfilename))) < 0)
     {
@@ -1408,7 +1412,7 @@ main(int  argc,                           /* I - Number of command-line args */
     files      = &compatfile;
     num_files  = 1;
   }
-  else if (http->version < HTTP_1_1 && num_files == 1)
+  else if (http->version < HTTP_VERSION_1_1 && num_files == 1)
   {
     struct stat        fileinfo;               /* File information */
 
@@ -1441,8 +1445,11 @@ main(int  argc,                          /* I - Number of command-line args */
   monitor.create_job    = create_job;
   monitor.get_job_attrs = get_job_attrs;
   monitor.encryption    = cupsEncryption();
-  monitor.job_state     = IPP_JOB_PENDING;
-  monitor.printer_state = IPP_PRINTER_IDLE;
+  monitor.job_state     = IPP_JSTATE_PENDING;
+  monitor.printer_state = IPP_PSTATE_IDLE;
+  monitor.retryable     = argc == 6 && document_format && strcmp(document_format, "image/pwg-raster") && strcmp(document_format, "image/urf");
+
+  fprintf(stderr, "DEBUG: retryable=%d\n", monitor.retryable);
 
   if (create_job)
   {
@@ -1482,6 +1489,30 @@ main(int  argc,                          /* I - Number of command-line args */
                                   ippGetString(job_auth, 0, NULL), num_options,
                                   &options);
 
+    if (ipp_status == IPP_STATUS_OK_IGNORED_OR_SUBSTITUTED || ipp_status == IPP_STATUS_OK_CONFLICTING)
+    {
+     /*
+      * One or more options are not supported...
+      */
+
+      ipp_attribute_t  *attr;          /* Unsupported attribute */
+
+      if ((attr = ippFindAttribute(response, "sides", IPP_TAG_ZERO)) != NULL)
+      {
+       /*
+        * The sides value is not supported, revert to one-sided as needed...
+        */
+
+        const char *sides = cupsGetOption("sides", num_options, options);
+
+        if (!sides || !strncmp(sides, "two-sided-", 10))
+        {
+          fputs("DEBUG: Unable to do two-sided printing, setting sides to 'one-sided'.\n", stderr);
+          num_options = cupsAddOption("sides", "one-sided", num_options, &options);
+        }
+      }
+    }
+
     ippDelete(response);
 
     if (job_canceled)
@@ -1524,10 +1555,10 @@ main(int  argc,                         /* I - Number of command-line args */
                           "cups-ipp-missing-validate-job");
       break;
     }
-    else if (ipp_status < IPP_REDIRECTION_OTHER_SITE ||
-             ipp_status == IPP_BAD_REQUEST)
+    else if (ipp_status < IPP_STATUS_REDIRECTION_OTHER_SITE ||
+             ipp_status == IPP_STATUS_ERROR_BAD_REQUEST)
       break;
-    else if (job_auth == NULL && ipp_status > IPP_BAD_REQUEST)
+    else if (job_auth == NULL && ipp_status > IPP_STATUS_ERROR_BAD_REQUEST)
       goto cleanup;
   }
 
@@ -1552,8 +1583,8 @@ main(int  argc,                           /* I - Number of command-line args */
     if (job_canceled)
       break;
 
-    request = new_request((num_files > 1 || create_job) ? IPP_CREATE_JOB :
-                                                          IPP_PRINT_JOB,
+    request = new_request((num_files > 1 || create_job) ? IPP_OP_CREATE_JOB :
+                                                          IPP_OP_PRINT_JOB,
                          version, uri, argv[2], monitor.job_name, num_options,
                          options, compression, copies_sup ? copies : 1,
                          document_format, pc, ppd, media_col_sup,
@@ -1578,7 +1609,7 @@ main(int  argc,                           /* I - Number of command-line args */
         fputs("DEBUG: Sending file using HTTP/1.1 chunking...\n", stderr);
 
       http_status = cupsSendRequest(http, request, resource, length);
-      if (http_status == HTTP_CONTINUE && request->state == IPP_DATA)
+      if (http_status == HTTP_STATUS_CONTINUE && request->state == IPP_STATE_DATA)
       {
        if (compression && strcmp(compression, "none"))
          httpSetField(http, HTTP_FIELD_CONTENT_ENCODING, compression);
@@ -1597,7 +1628,7 @@ main(int  argc,                           /* I - Number of command-line args */
          http_status = cupsWriteRequestData(http, buffer, (size_t)bytes);
         }
 
-        while (http_status == HTTP_CONTINUE &&
+        while (http_status == HTTP_STATUS_CONTINUE &&
                (!job_canceled || compatsize > 0))
        {
         /*
@@ -1622,7 +1653,7 @@ main(int  argc,                           /* I - Number of command-line args */
              fprintf(stderr, "DEBUG: Read %d bytes...\n", (int)bytes);
 
              if ((http_status = cupsWriteRequestData(http, buffer, (size_t)bytes))
-                     != HTTP_CONTINUE)
+                     != HTTP_STATUS_CONTINUE)
                break;
            }
            else if (bytes == 0 || (errno != EINTR && errno != EAGAIN))
@@ -1630,7 +1661,7 @@ main(int  argc,                           /* I - Number of command-line args */
          }
        }
 
-       if (http_status == HTTP_ERROR)
+       if (http_status == HTTP_STATUS_ERROR)
          fprintf(stderr, "DEBUG: Error writing document data for "
                          "Print-Job: %s\n", strerror(httpError(http)));
 
@@ -1649,7 +1680,7 @@ main(int  argc,                           /* I - Number of command-line args */
             ippErrorString(ipp_status), cupsLastErrorString());
     debug_attributes(response);
 
-    if (ipp_status > IPP_OK_CONFLICT)
+    if (ipp_status > IPP_STATUS_OK_CONFLICTING)
     {
       job_id = 0;
 
@@ -1701,7 +1732,7 @@ main(int  argc,                           /* I - Number of command-line args */
          else if (www_auth[0])
            auth_info_required = "username,password";
        }
-       else if (ipp_status == IPP_REQUEST_VALUE)
+       else if (ipp_status == IPP_STATUS_ERROR_REQUEST_VALUE)
        {
         /*
          * Print file is too large, abort this job...
@@ -1757,7 +1788,7 @@ main(int  argc,                           /* I - Number of command-line args */
         * Send the next file in the job...
        */
 
-       request = ippNewRequest(IPP_SEND_DOCUMENT);
+       request = ippNewRequest(IPP_OP_SEND_DOCUMENT);
        ippSetVersion(request, version / 10, version % 10);
 
        ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
@@ -1786,7 +1817,7 @@ main(int  argc,                           /* I - Number of command-line args */
        debug_attributes(request);
 
        http_status = cupsSendRequest(http, request, resource, 0);
-       if (http_status == HTTP_CONTINUE && request->state == IPP_DATA)
+       if (http_status == HTTP_STATUS_CONTINUE && request->state == IPP_STATE_DATA)
        {
          if (compression && strcmp(compression, "none"))
            httpSetField(http, HTTP_FIELD_CONTENT_ENCODING, compression);
@@ -1810,11 +1841,11 @@ main(int  argc,                         /* I - Number of command-line args */
 
        if (fd >= 0)
        {
-         while (!job_canceled && http_status == HTTP_CONTINUE &&
+         while (!job_canceled && http_status == HTTP_STATUS_CONTINUE &&
                 (bytes = read(fd, buffer, sizeof(buffer))) > 0)
          {
            if ((http_status = cupsWriteRequestData(http, buffer, (size_t)bytes))
-                   != HTTP_CONTINUE)
+                   != HTTP_STATUS_CONTINUE)
              break;
            else
            {
@@ -1830,28 +1861,36 @@ main(int  argc,                         /* I - Number of command-line args */
            close(fd);
        }
 
-        if (http_status == HTTP_ERROR)
+        if (http_status == HTTP_STATUS_ERROR)
           fprintf(stderr, "DEBUG: Error writing document data for "
                           "Send-Document: %s\n", strerror(httpError(http)));
 
        response = cupsGetResponse(http, resource);
        ippDelete(request);
 
-       fprintf(stderr, "DEBUG: Send-Document: %s (%s)\n",
-               ippErrorString(cupsLastError()), cupsLastErrorString());
+       fprintf(stderr, "DEBUG: Send-Document: %s (%s)\n", ippErrorString(cupsLastError()), cupsLastErrorString());
         debug_attributes(response);
-        ippDelete(response);
 
-       if (cupsLastError() > IPP_OK_CONFLICT && !job_canceled)
+       if (cupsLastError() > IPP_STATUS_OK_CONFLICTING && !job_canceled)
        {
+         ipp_attribute_t *reasons = ippFindAttribute(response, "job-state-reasons", IPP_TAG_KEYWORD);
+                                       /* job-state-reasons values */
+
          ipp_status = cupsLastError();
 
-         _cupsLangPrintFilter(stderr, "ERROR",
-                              _("Unable to add document to print job."));
+          if (ippContainsString(reasons, "document-format-error"))
+            ipp_status = IPP_STATUS_ERROR_DOCUMENT_FORMAT_ERROR;
+          else if (ippContainsString(reasons, "document-unprintable"))
+            ipp_status = IPP_STATUS_ERROR_DOCUMENT_UNPRINTABLE;
+
+         ippDelete(response);
+         _cupsLangPrintFilter(stderr, "ERROR", _("Unable to add document to print job."));
          break;
        }
        else
        {
+         ippDelete(response);
+
          password_tries = 0;
 
          if (num_files == 0 || fd < 0)
@@ -1863,12 +1902,12 @@ main(int  argc,                         /* I - Number of command-line args */
     if (job_canceled)
       break;
 
-    if (ipp_status <= IPP_OK_CONFLICT && argc > 6)
+    if (ipp_status <= IPP_STATUS_OK_CONFLICTING && argc > 6)
     {
       fprintf(stderr, "PAGE: 1 %d\n", copies_sup ? atoi(argv[4]) : 1);
       copies_remaining --;
     }
-    else if ((ipp_status == IPP_STATUS_ERROR_DOCUMENT_FORMAT_ERROR || ipp_status == IPP_STATUS_ERROR_DOCUMENT_UNPRINTABLE) &&
+    else if ((ipp_status == IPP_STATUS_ERROR_DOCUMENT_FORMAT_NOT_SUPPORTED || ipp_status == IPP_STATUS_ERROR_DOCUMENT_FORMAT_ERROR || ipp_status == IPP_STATUS_ERROR_DOCUMENT_UNPRINTABLE) &&
              argc == 6 &&
              document_format && strcmp(document_format, "image/pwg-raster") && strcmp(document_format, "image/urf"))
     {
@@ -1882,9 +1921,9 @@ main(int  argc,                           /* I - Number of command-line args */
 
       goto cleanup;
     }
-    else if (ipp_status == IPP_SERVICE_UNAVAILABLE ||
-             ipp_status == IPP_NOT_POSSIBLE ||
-            ipp_status == IPP_PRINTER_BUSY)
+    else if (ipp_status == IPP_STATUS_ERROR_SERVICE_UNAVAILABLE ||
+             ipp_status == IPP_STATUS_ERROR_NOT_POSSIBLE ||
+            ipp_status == IPP_STATUS_ERROR_BUSY)
     {
       if (argc == 6)
       {
@@ -1900,14 +1939,14 @@ main(int  argc,                         /* I - Number of command-line args */
       }
       continue;
     }
-    else if (ipp_status == IPP_REQUEST_VALUE ||
-             ipp_status == IPP_ERROR_JOB_CANCELED ||
-             ipp_status == IPP_NOT_AUTHORIZED ||
+    else if (ipp_status == IPP_STATUS_ERROR_REQUEST_VALUE ||
+             ipp_status == IPP_STATUS_ERROR_JOB_CANCELED ||
+             ipp_status == IPP_STATUS_ERROR_NOT_AUTHORIZED ||
              ipp_status == IPP_STATUS_ERROR_CUPS_ACCOUNT_INFO_NEEDED ||
              ipp_status == IPP_STATUS_ERROR_CUPS_ACCOUNT_CLOSED ||
              ipp_status == IPP_STATUS_ERROR_CUPS_ACCOUNT_LIMIT_REACHED ||
              ipp_status == IPP_STATUS_ERROR_CUPS_ACCOUNT_AUTHORIZATION_FAILED ||
-             ipp_status == IPP_INTERNAL_ERROR)
+             ipp_status == IPP_STATUS_ERROR_INTERNAL)
     {
      /*
       * Print file is too large, job was canceled, we need new
@@ -1937,7 +1976,7 @@ main(int  argc,                           /* I - Number of command-line args */
 
       goto cleanup;
     }
-    else if (ipp_status == IPP_NOT_FOUND)
+    else if (ipp_status == IPP_STATUS_ERROR_NOT_FOUND)
     {
      /*
       * Printer does not actually implement support for Create-Job/
@@ -1951,7 +1990,7 @@ main(int  argc,                           /* I - Number of command-line args */
       update_reasons(NULL, "+cups-ipp-conformance-failure-report,"
                           "cups-ipp-missing-send-document");
 
-      ipp_status = IPP_INTERNAL_ERROR; /* Force queue to stop */
+      ipp_status = IPP_STATUS_ERROR_INTERNAL;  /* Force queue to stop */
 
       goto cleanup;
     }
@@ -1969,7 +2008,7 @@ main(int  argc,                           /* I - Number of command-line args */
 
     _cupsLangPrintFilter(stderr, "INFO", _("Waiting for job to complete."));
 
-    for (delay = _cupsNextDelay(0, &prev_delay), waittime = time(NULL) + 30; !job_canceled;)
+    for (delay = _cupsNextDelay(0, &prev_delay); !job_canceled;)
     {
      /*
       * Check for side-channel requests...
@@ -1983,14 +2022,14 @@ main(int  argc,                         /* I - Number of command-line args */
 
       check_printer_state(http, uri, resource, argv[2], version);
 
-      if (cupsLastError() <= IPP_OK_CONFLICT)
+      if (cupsLastError() <= IPP_STATUS_OK_CONFLICTING)
         password_tries = 0;
 
      /*
-      * Build an IPP_GET_JOB_ATTRIBUTES request...
+      * Build an IPP_OP_GET_JOB_ATTRIBUTES request...
       */
 
-      request = ippNewRequest(IPP_GET_JOB_ATTRIBUTES);
+      request = ippNewRequest(IPP_OP_GET_JOB_ATTRIBUTES);
       ippSetVersion(request, version / 10, version % 10);
 
       ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
@@ -2014,11 +2053,11 @@ main(int  argc,                         /* I - Number of command-line args */
       * Do the request...
       */
 
-      httpReconnect(http);
+      httpReconnect2(http, 30000, NULL);
       response   = cupsDoRequest(http, request, resource);
       ipp_status = cupsLastError();
 
-      if (ipp_status == IPP_NOT_FOUND || ipp_status == IPP_NOT_POSSIBLE)
+      if (ipp_status == IPP_STATUS_ERROR_NOT_FOUND || ipp_status == IPP_STATUS_ERROR_NOT_POSSIBLE)
       {
        /*
         * Job has gone away and/or the server has no job history...
@@ -2028,7 +2067,7 @@ main(int  argc,                           /* I - Number of command-line args */
                             "cups-ipp-missing-job-history");
         ippDelete(response);
 
-       ipp_status = IPP_OK;
+       ipp_status = IPP_STATUS_OK;
         break;
       }
 
@@ -2036,25 +2075,25 @@ main(int  argc,                         /* I - Number of command-line args */
              ippErrorString(ipp_status), cupsLastErrorString());
       debug_attributes(response);
 
-      if (ipp_status <= IPP_OK_CONFLICT)
+      if (ipp_status <= IPP_STATUS_OK_CONFLICTING)
        password_tries = 0;
       else
       {
-       if (ipp_status != IPP_SERVICE_UNAVAILABLE &&
-           ipp_status != IPP_PRINTER_BUSY)
+       if (ipp_status != IPP_STATUS_ERROR_SERVICE_UNAVAILABLE &&
+           ipp_status != IPP_STATUS_ERROR_BUSY)
        {
          ippDelete(response);
-          ipp_status = IPP_OK;
+          ipp_status = IPP_STATUS_OK;
           break;
        }
-       else if (ipp_status == IPP_INTERNAL_ERROR)
+       else if (ipp_status == IPP_STATUS_ERROR_INTERNAL)
        {
          waitjob_tries ++;
 
          if (waitjob_tries > 4)
          {
            ippDelete(response);
-           ipp_status = IPP_OK;
+           ipp_status = IPP_STATUS_OK;
            break;
          }
        }
@@ -2070,11 +2109,11 @@ main(int  argc,                         /* I - Number of command-line args */
          */
 
          if (cups_version &&
-             job_state->values[0].integer >= IPP_JOB_PENDING &&
-             job_state->values[0].integer <= IPP_JOB_COMPLETED)
+             job_state->values[0].integer >= IPP_JSTATE_PENDING &&
+             job_state->values[0].integer <= IPP_JSTATE_COMPLETED)
            update_reasons(NULL,
                           remote_job_states[job_state->values[0].integer -
-                                            IPP_JOB_PENDING]);
+                                            IPP_JSTATE_PENDING]);
 
          if ((job_sheets = ippFindAttribute(response, "job-impressions-completed", IPP_TAG_INTEGER)) == NULL)
            job_sheets = ippFindAttribute(response, "job-media-sheets-completed", IPP_TAG_INTEGER);
@@ -2084,19 +2123,18 @@ main(int  argc,                         /* I - Number of command-line args */
                    job_sheets->values[0].integer);
 
         /*
-          * Stop polling if the job is finished or pending-held for 30 seconds...
+          * Stop polling if the job is finished or pending-held...
          */
 
-          if (job_state->values[0].integer > IPP_JSTATE_STOPPED ||
-             (job_state->values[0].integer == IPP_JSTATE_HELD && time(NULL) > waittime))
+          if (job_state->values[0].integer > IPP_JSTATE_STOPPED || job_state->values[0].integer == IPP_JSTATE_HELD)
          {
            ippDelete(response);
            break;
          }
        }
-       else if (ipp_status != IPP_SERVICE_UNAVAILABLE &&
-                ipp_status != IPP_NOT_POSSIBLE &&
-                ipp_status != IPP_PRINTER_BUSY)
+       else if (ipp_status != IPP_STATUS_ERROR_SERVICE_UNAVAILABLE &&
+                ipp_status != IPP_STATUS_ERROR_NOT_POSSIBLE &&
+                ipp_status != IPP_STATUS_ERROR_BUSY)
        {
         /*
          * If the printer does not return a job-state attribute, it does not
@@ -2106,7 +2144,7 @@ main(int  argc,                           /* I - Number of command-line args */
 
          update_reasons(NULL, "+cups-ipp-conformance-failure-report,"
                               "cups-ipp-missing-job-state");
-         ipp_status = IPP_INTERNAL_ERROR;
+         ipp_status = IPP_STATUS_ERROR_INTERNAL;
          break;
        }
       }
@@ -2131,7 +2169,7 @@ main(int  argc,                           /* I - Number of command-line args */
   {
     cancel_job(http, uri, job_id, resource, argv[2], version);
 
-    if (cupsLastError() > IPP_OK_CONFLICT)
+    if (cupsLastError() > IPP_STATUS_OK_CONFLICTING)
       _cupsLangPrintFilter(stderr, "ERROR", _("Unable to cancel print job."));
   }
 
@@ -2141,7 +2179,7 @@ main(int  argc,                           /* I - Number of command-line args */
 
   check_printer_state(http, uri, resource, argv[2], version);
 
-  if (cupsLastError() <= IPP_OK_CONFLICT)
+  if (cupsLastError() <= IPP_STATUS_OK_CONFLICTING)
     password_tries = 0;
 
  /*
@@ -2188,9 +2226,9 @@ main(int  argc,                           /* I - Number of command-line args */
   * Return the queue status...
   */
 
-  if (ipp_status == IPP_NOT_AUTHORIZED || ipp_status == IPP_FORBIDDEN ||
-      ipp_status == IPP_AUTHENTICATION_CANCELED ||
-      ipp_status <= IPP_OK_CONFLICT)
+  if (ipp_status == IPP_STATUS_ERROR_NOT_AUTHORIZED || ipp_status == IPP_STATUS_ERROR_FORBIDDEN ||
+      ipp_status == IPP_STATUS_ERROR_CUPS_AUTHENTICATION_CANCELED ||
+      ipp_status <= IPP_STATUS_OK_CONFLICTING)
     fprintf(stderr, "ATTR: auth-info-required=%s\n", auth_info_required);
 
   if (ipp_status == IPP_STATUS_ERROR_CUPS_ACCOUNT_INFO_NEEDED)
@@ -2202,25 +2240,26 @@ main(int  argc,                         /* I - Number of command-line args */
   else if (ipp_status == IPP_STATUS_ERROR_CUPS_ACCOUNT_AUTHORIZATION_FAILED)
     fputs("JOBSTATE: account-authorization-failed\n", stderr);
 
-  if (ipp_status == IPP_NOT_AUTHORIZED || ipp_status == IPP_FORBIDDEN ||
-      ipp_status == IPP_AUTHENTICATION_CANCELED)
+  if (job_canceled)
+    return (CUPS_BACKEND_OK);
+  else if (ipp_status == IPP_STATUS_ERROR_NOT_AUTHORIZED || ipp_status == IPP_STATUS_ERROR_FORBIDDEN || ipp_status == IPP_STATUS_ERROR_CUPS_AUTHENTICATION_CANCELED)
     return (CUPS_BACKEND_AUTH_REQUIRED);
   else if (ipp_status == IPP_STATUS_ERROR_CUPS_ACCOUNT_LIMIT_REACHED ||
           ipp_status == IPP_STATUS_ERROR_CUPS_ACCOUNT_INFO_NEEDED ||
           ipp_status == IPP_STATUS_ERROR_CUPS_ACCOUNT_CLOSED ||
           ipp_status == IPP_STATUS_ERROR_CUPS_ACCOUNT_AUTHORIZATION_FAILED)
     return (CUPS_BACKEND_HOLD);
-  else if (ipp_status == IPP_INTERNAL_ERROR)
+  else if (ipp_status == IPP_STATUS_ERROR_INTERNAL)
     return (CUPS_BACKEND_STOP);
-  else if (ipp_status == IPP_CONFLICT || ipp_status == IPP_STATUS_ERROR_REQUEST_ENTITY || ipp_status == IPP_STATUS_ERROR_REQUEST_VALUE)
+  else if (ipp_status == IPP_STATUS_ERROR_CONFLICTING || 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 ||
+  else if (ipp_status == IPP_STATUS_ERROR_REQUEST_VALUE ||
           ipp_status == IPP_STATUS_ERROR_ATTRIBUTES_OR_VALUES ||
-           ipp_status == IPP_DOCUMENT_FORMAT || job_canceled < 0)
+           ipp_status == IPP_STATUS_ERROR_DOCUMENT_FORMAT_NOT_SUPPORTED || job_canceled < 0)
   {
-    if (ipp_status == IPP_REQUEST_VALUE)
+    if (ipp_status == IPP_STATUS_ERROR_REQUEST_VALUE)
       _cupsLangPrintFilter(stderr, "ERROR", _("Print job too large."));
-    else if (ipp_status == IPP_DOCUMENT_FORMAT)
+    else if (ipp_status == IPP_STATUS_ERROR_DOCUMENT_FORMAT_NOT_SUPPORTED)
       _cupsLangPrintFilter(stderr, "ERROR",
                            _("Printer cannot print supplied content."));
     else if (ipp_status == IPP_STATUS_ERROR_ATTRIBUTES_OR_VALUES)
@@ -2231,7 +2270,7 @@ main(int  argc,                           /* I - Number of command-line args */
 
     return (CUPS_BACKEND_CANCEL);
   }
-  else if (ipp_status > IPP_OK_CONFLICT && ipp_status != IPP_ERROR_JOB_CANCELED)
+  else if (ipp_status > IPP_STATUS_OK_CONFLICTING && ipp_status != IPP_STATUS_ERROR_JOB_CANCELED)
     return (CUPS_BACKEND_RETRY_CURRENT);
   else
     return (CUPS_BACKEND_OK);
@@ -2255,7 +2294,7 @@ cancel_job(http_t     *http,              /* I - HTTP connection */
 
   _cupsLangPrintFilter(stderr, "INFO", _("Canceling print job."));
 
-  request = ippNewRequest(IPP_CANCEL_JOB);
+  request = ippNewRequest(IPP_OP_CANCEL_JOB);
   ippSetVersion(request, version / 10, version % 10);
 
   ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
@@ -2289,7 +2328,7 @@ check_printer_state(
   ipp_t                *request,               /* IPP request */
                *response;              /* IPP response */
   ipp_attribute_t *attr;               /* Attribute in response */
-  ipp_pstate_t printer_state = IPP_PRINTER_STOPPED;
+  ipp_pstate_t printer_state = IPP_PSTATE_STOPPED;
                                        /* Current printer-state */
 
 
@@ -2297,7 +2336,7 @@ check_printer_state(
   * Send a Get-Printer-Attributes request and log the results...
   */
 
-  request = ippNewRequest(IPP_GET_PRINTER_ATTRIBUTES);
+  request = ippNewRequest(IPP_OP_GET_PRINTER_ATTRIBUTES);
   ippSetVersion(request, version / 10, version % 10);
 
   ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
@@ -2423,14 +2462,14 @@ monitor_printer(
 
   monitor->job_reasons = 0;
 
-  while (monitor->job_state < IPP_JOB_CANCELED && !job_canceled)
+  while (monitor->job_state < IPP_JSTATE_CANCELED && !job_canceled)
   {
    /*
     * Reconnect to the printer as needed...
     */
 
     if (httpGetFd(http) < 0)
-      httpReconnect(http);
+      httpReconnect2(http, 30000, NULL);
 
     if (httpGetFd(http) >= 0)
     {
@@ -2442,7 +2481,7 @@ monitor_printer(
                                                    monitor->resource,
                                                   monitor->user,
                                                   monitor->version);
-      if (cupsLastError() <= IPP_OK_CONFLICT)
+      if (cupsLastError() <= IPP_STATUS_OK_CONFLICTING)
         password_tries = 0;
 
       if (monitor->job_id == 0 && monitor->create_job)
@@ -2459,13 +2498,13 @@ monitor_printer(
       */
 
       job_op  = (monitor->job_id > 0 && monitor->get_job_attrs) ?
-                    IPP_GET_JOB_ATTRIBUTES : IPP_GET_JOBS;
+                    IPP_OP_GET_JOB_ATTRIBUTES : IPP_OP_GET_JOBS;
       request = ippNewRequest(job_op);
       ippSetVersion(request, monitor->version / 10, monitor->version % 10);
 
       ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
                   NULL, monitor->uri);
-      if (job_op == IPP_GET_JOB_ATTRIBUTES)
+      if (job_op == IPP_OP_GET_JOB_ATTRIBUTES)
        ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER, "job-id",
                      monitor->job_id);
 
@@ -2486,16 +2525,16 @@ monitor_printer(
       fprintf(stderr, "DEBUG: (monitor) %s: %s (%s)\n", ippOpString(job_op),
              ippErrorString(cupsLastError()), cupsLastErrorString());
 
-      if (cupsLastError() <= IPP_OK_CONFLICT)
+      if (cupsLastError() <= IPP_STATUS_OK_CONFLICTING)
         password_tries = 0;
 
-      if (job_op == IPP_GET_JOB_ATTRIBUTES)
+      if (job_op == IPP_OP_GET_JOB_ATTRIBUTES)
       {
        if ((attr = ippFindAttribute(response, "job-state",
                                     IPP_TAG_ENUM)) != NULL)
          monitor->job_state = (ipp_jstate_t)attr->values[0].integer;
        else
-         monitor->job_state = IPP_JOB_COMPLETED;
+         monitor->job_state = IPP_JSTATE_COMPLETED;
       }
       else if (response)
       {
@@ -2503,7 +2542,7 @@ monitor_printer(
         {
           job_id    = 0;
           job_name  = NULL;
-          job_state = IPP_JOB_PENDING;
+          job_state = IPP_JSTATE_PENDING;
           job_user  = NULL;
 
           while (attr && attr->group_tag != IPP_TAG_JOB)
@@ -2545,12 +2584,11 @@ monitor_printer(
         }
       }
 
-      fprintf(stderr, "DEBUG: (monitor) job-state = %s\n",
-              ippEnumString("job-state", monitor->job_state));
+      fprintf(stderr, "DEBUG: (monitor) job-state = %s\n", ippEnumString("job-state", (int)monitor->job_state));
 
       if (!job_canceled &&
-          (monitor->job_state == IPP_JOB_CANCELED ||
-          monitor->job_state == IPP_JOB_ABORTED))
+          (monitor->job_state == IPP_JSTATE_CANCELED ||
+          monitor->job_state == IPP_JSTATE_ABORTED))
       {
        job_canceled = -1;
        fprintf(stderr, "DEBUG: (monitor) job_canceled = -1\n");
@@ -2563,22 +2601,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;
         }
 
@@ -2596,6 +2636,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);
 
@@ -2605,12 +2665,11 @@ monitor_printer(
 
       ippDelete(response);
 
-      fprintf(stderr, "DEBUG: (monitor) job-state = %s\n",
-              ippEnumString("job-state", monitor->job_state));
+      fprintf(stderr, "DEBUG: (monitor) job-state = %s\n", ippEnumString("job-state", (int)monitor->job_state));
 
       if (!job_canceled &&
-          (monitor->job_state == IPP_JOB_CANCELED ||
-          monitor->job_state == IPP_JOB_ABORTED))
+          (monitor->job_state == IPP_JSTATE_CANCELED ||
+          monitor->job_state == IPP_JSTATE_ABORTED))
        job_canceled = -1;
     }
 
@@ -2632,14 +2691,14 @@ monitor_printer(
   if (job_canceled > 0 && monitor->job_id > 0)
   {
     if (httpGetFd(http) < 0)
-      httpReconnect(http);
+      httpReconnect2(http, 30000, NULL);
 
     if (httpGetFd(http) >= 0)
     {
       cancel_job(http, monitor->uri, monitor->job_id, monitor->resource,
                  monitor->user, monitor->version);
 
-      if (cupsLastError() > IPP_OK_CONFLICT)
+      if (cupsLastError() > IPP_STATUS_OK_CONFLICTING)
       {
        fprintf(stderr, "DEBUG: (monitor) cancel_job() = %s\n", cupsLastErrorString());
        _cupsLangPrintFilter(stderr, "ERROR", _("Unable to cancel print job."));
@@ -2715,7 +2774,7 @@ new_request(
     fprintf(stderr, "DEBUG: job-name=\"%s\"\n", title);
   }
 
-  if (format && op != IPP_CREATE_JOB)
+  if (format && op != IPP_OP_CREATE_JOB)
   {
     ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_MIMETYPE, "document-format", NULL, format);
     fprintf(stderr, "DEBUG: document-format=\"%s\"\n", format);
@@ -2755,7 +2814,7 @@ new_request(
        char    phone[1024],            /* Phone number string */
                *ptr,                   /* Pointer into string */
                tel_uri[1024];          /* tel: URI */
-        static const char * const allowed = "0123456789#*-+.()";
+        static const char * const allowed = "0123456789#*-+.()pw";
                                        /* Allowed characters */
 
         destination = ippNew();
@@ -2768,7 +2827,9 @@ new_request(
         _httpDecodeURI(phone, keyword, sizeof(phone));
         for (ptr = phone; *ptr;)
        {
-         if (!strchr(allowed, *ptr))
+         if (*ptr == ',')
+           *ptr = 'p';
+         else if (!strchr(allowed, *ptr))
            _cups_strcpy(ptr, ptr + 1);
          else
            ptr ++;
@@ -3554,6 +3615,8 @@ update_reasons(ipp_attribute_t *attr,     /* I - printer-state-reasons or NULL */
     }
   }
 
+  cupsArrayDelete(new_reasons);
+
   _cupsMutexUnlock(&report_mutex);
 
  /*