]> git.ipfire.org Git - thirdparty/cups.git/blobdiff - backend/ipp.c
Import all of the bug fixes from the OpenPrinting CUPS repository.
[thirdparty/cups.git] / backend / ipp.c
index 0b2edeb7ef7bc6344b43744c2d67cba40b6fa40e..8b1976990dbb148027b9a5ce62eda72af2a73ff5 100644 (file)
@@ -233,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 */
@@ -1450,6 +1449,8 @@ main(int  argc,                           /* I - Number of command-line args */
   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)
   {
     monitor.job_name = argv[3];
@@ -1504,7 +1505,7 @@ main(int  argc,                           /* I - Number of command-line args */
 
         const char *sides = cupsGetOption("sides", num_options, options);
 
-        if (!strncmp(sides, "two-sided-", 10))
+        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);
@@ -1867,21 +1868,29 @@ main(int  argc,                         /* I - Number of command-line args */
        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_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)
@@ -1898,7 +1907,7 @@ main(int  argc,                           /* I - Number of command-line args */
       fprintf(stderr, "PAGE: 1 %d\n", copies_sup ? atoi(argv[4]) : 1);
       copies_remaining --;
     }
-    else if ((ipp_status == IPP_STATUS_ERROR_DOCUMENT_FORMAT_NOT_SUPPORTED || 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"))
     {
@@ -1999,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...
@@ -2114,11 +2123,10 @@ 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;
@@ -2232,7 +2240,8 @@ 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 (job_canceled)
+  // job_canceled can be -1 which should not be treated as CUPS_BACKEND_OK
+  if (job_canceled > 0)
     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);
@@ -2576,8 +2585,7 @@ 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_JSTATE_CANCELED ||
@@ -2658,8 +2666,7 @@ 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_JSTATE_CANCELED ||
@@ -2819,7 +2826,21 @@ new_request(
         */
 
         _httpDecodeURI(phone, keyword, sizeof(phone));
-        for (ptr = phone; *ptr;)
+        ptr = phone;
+
+        /*
+         * Weed out "Custom." in the beginning, this allows to put the
+         * "phone" option as custom string option into the PPD so that
+         * print dialogs not supporting fax display the option and
+         * allow entering the phone number. Print dialogs also send "None"
+         * if no phone number got entered, filter this, too.
+         */
+        if (!_cups_strcasecmp(phone, "None"))
+          *ptr = '\0';
+        if (!_cups_strncasecmp(phone, "Custom.", 7))
+          _cups_strcpy(ptr, ptr + 7);
+
+        for (; *ptr;)
        {
          if (*ptr == ',')
            *ptr = 'p';
@@ -2829,20 +2850,36 @@ new_request(
            ptr ++;
         }
 
-        httpAssembleURI(HTTP_URI_CODING_ALL, tel_uri, sizeof(tel_uri), "tel", NULL, NULL, 0, phone);
-        ippAddString(destination, IPP_TAG_JOB, IPP_TAG_URI, "destination-uri", NULL, tel_uri);
-
-       if ((keyword = cupsGetOption("faxPrefix", num_options,
-                                    options)) != NULL && *keyword)
+        if (strlen(phone) > 0)
         {
-         char  predial[1024];          /* Pre-dial string */
+          httpAssembleURI(HTTP_URI_CODING_ALL, tel_uri, sizeof(tel_uri), "tel", NULL, NULL, 0, phone);
+          ippAddString(destination, IPP_TAG_JOB, IPP_TAG_URI, "destination-uri", NULL, tel_uri);
+          fprintf(stderr, "DEBUG: Faxing to phone %s; destination-uri: %s\n", phone, tel_uri);
 
-         _httpDecodeURI(predial, keyword, sizeof(predial));
-         ippAddString(destination, IPP_TAG_JOB, IPP_TAG_TEXT, "pre-dial-string", NULL, predial);
-       }
+          if ((keyword = cupsGetOption("faxPrefix", num_options, options)) != NULL && *keyword)
+          {
+            char       predial[1024];          /* Pre-dial string */
+
+            _httpDecodeURI(predial, keyword, sizeof(predial));
+            ptr = predial;
+            if (!_cups_strcasecmp(ptr, "None"))
+              *ptr = '\0';
+            if (!_cups_strncasecmp(ptr, "Custom.", 7))
+              ptr += 7;
+            if (strlen(ptr) > 0)
+            {
+              ippAddString(destination, IPP_TAG_JOB, IPP_TAG_TEXT, "pre-dial-string", NULL, ptr);
+              fprintf(stderr, "DEBUG: Pre-dialing %s; pre-dial-string: %s\n", ptr, ptr);
+            }
+            else
+              fprintf(stderr, "WARNING: Pre-dial number for fax not valid! Sending fax without pre-dial number.\n");
+          }
 
-        ippAddCollection(request, IPP_TAG_JOB, "destination-uris", destination);
-        ippDelete(destination);
+          ippAddCollection(request, IPP_TAG_JOB, "destination-uris", destination);
+          ippDelete(destination);
+        }
+        else
+          fprintf(stderr, "ERROR: Phone number for fax not valid! Fax cannot be sent.\n");
       }
     }
     else
@@ -3069,7 +3106,7 @@ report_printer_state(ipp_t *ipp)  /* I - IPP response */
   * Report alerts and messages...
   */
 
-  if ((pa = ippFindAttribute(ipp, "printer-alert", IPP_TAG_TEXT)) != NULL)
+  if ((pa = ippFindAttribute(ipp, "printer-alert", IPP_TAG_STRING)) != NULL)
     report_attr(pa);
 
   if ((pam = ippFindAttribute(ipp, "printer-alert-message",
@@ -3110,11 +3147,10 @@ report_printer_state(ipp_t *ipp)        /* I - IPP response */
       if (*ptr < ' ' && *ptr > 0 && *ptr != '\t')
       {
        /*
-        * Substitute "<XX>" for the control character; sprintf is safe because
-       * we always leave 6 chars free at the end...
+        * Substitute "<XX>" for the control character...
        */
 
-        sprintf(valptr, "<%02X>", *ptr);
+        snprintf(valptr, sizeof(value) - (size_t)(valptr - value), "<%02X>", *ptr);
        valptr += 4;
       }
       else