]> git.ipfire.org Git - thirdparty/cups.git/blobdiff - backend/ipp.c
Remove support for AIX, HP-UX, and OSF/1.
[thirdparty/cups.git] / backend / ipp.c
index 180586e0548ba79283e58b2a729a2b0f672031aa..1bbd73c3f9e7c89fa88f45981c8ce5fc31697e5e 100644 (file)
@@ -1,9 +1,9 @@
 /*
- * "$Id: ipp.c 9759 2011-05-11 03:24:33Z mike $"
+ * "$Id$"
  *
  *   IPP backend for CUPS.
  *
- *   Copyright 2007-2012 by Apple Inc.
+ *   Copyright 2007-2013 by Apple Inc.
  *   Copyright 1997-2007 by Easy Software Products, all rights reserved.
  *
  *   These coded instructions, statements, and computer programs are the
@@ -115,8 +115,6 @@ static char         username[256] = "",
                                        /* Username for device URI */
                        *password = NULL;
                                        /* Password for device URI */
-static int             password_tries = 0;
-                                       /* Password tries */
 static const char * const pattrs[] =   /* Printer attributes we want */
 {
 #ifdef HAVE_LIBZ
@@ -185,7 +183,7 @@ static ipp_t                *new_request(ipp_op_t op, int version, const char *uri,
                                     int print_color_mode);
 static const char      *password_cb(const char *prompt, http_t *http,
                                     const char *method, const char *resource,
-                                    void *user_data);
+                                    int *user_data);
 static const char      *quote_string(const char *s, char *q, size_t qsize);
 static void            report_attr(ipp_attribute_t *attr);
 static void            report_printer_state(ipp_t *ipp);
@@ -223,6 +221,7 @@ main(int  argc,                             /* I - Number of command-line args */
                *name,                  /* Name of option */
                *value,                 /* Value of option */
                sep;                    /* Separator character */
+  int          password_tries = 0;     /* Password tries */
   http_addrlist_t *addrlist;           /* Address of printer */
   int          snmp_enabled = 1;       /* Is SNMP enabled? */
   int          snmp_fd,                /* SNMP socket */
@@ -262,6 +261,7 @@ main(int  argc,                             /* I - Number of command-line args */
   ipp_attribute_t *copies_sup;         /* copies-supported */
   ipp_attribute_t *cups_version;       /* cups-version */
   ipp_attribute_t *format_sup;         /* document-format-supported */
+  ipp_attribute_t *job_auth;           /* job-authorization-uri */
   ipp_attribute_t *media_col_sup;      /* media-col-supported */
   ipp_attribute_t *operations_sup;     /* operations-supported */
   ipp_attribute_t *doc_handling_sup;   /* multiple-document-handling-supported */
@@ -366,7 +366,8 @@ main(int  argc,                             /* I - Number of command-line args */
   * that way.
   */
 
-  if (!getuid() && (value = getenv("AUTH_UID")) != NULL)
+  if (!getuid() && (value = getenv("AUTH_UID")) != NULL &&
+      !getenv("AUTH_PASSWORD"))
   {
     uid_t      uid = (uid_t)atoi(value);
                                        /* User ID */
@@ -431,7 +432,7 @@ main(int  argc,                             /* I - Number of command-line args */
   if (!port)
     port = IPP_PORT;                   /* Default to port 631 */
 
-  if (!strcmp(scheme, "https"))
+  if (!strcmp(scheme, "https") || !strcmp(scheme, "ipps"))
     cupsSetEncryption(HTTP_ENCRYPT_ALWAYS);
   else
     cupsSetEncryption(HTTP_ENCRYPT_IF_REQUESTED);
@@ -634,7 +635,7 @@ main(int  argc,                             /* I - Number of command-line args */
   * Set the authentication info, if any...
   */
 
-  cupsSetPasswordCB2(password_cb, NULL);
+  cupsSetPasswordCB2((cups_password_cb2_t)password_cb, &password_tries);
 
   if (username[0])
   {
@@ -691,8 +692,8 @@ main(int  argc,                             /* I - Number of command-line args */
       return (CUPS_BACKEND_OK);
   }
 
-  http = _httpCreate(hostname, port, addrlist, AF_UNSPEC, cupsEncryption(), 1,
-                     _HTTP_MODE_CLIENT);
+  http = httpConnect2(hostname, port, addrlist, AF_UNSPEC, cupsEncryption(), 1,
+                      0, NULL);
   httpSetTimeout(http, 30.0, timeout_cb, NULL);
 
  /*
@@ -1066,10 +1067,10 @@ main(int  argc,                         /* I - Number of command-line args */
       }
       else if (!compression)
       {
-        if (ippContainsString(compression_sup, "deflate"))
-          compression = "deflate";
-        else if (ippContainsString(compression_sup, "gzip"))
+        if (ippContainsString(compression_sup, "gzip"))
           compression = "gzip";
+        else if (ippContainsString(compression_sup, "deflate"))
+          compression = "deflate";
 
         if (compression)
           fprintf(stderr, "DEBUG: Automatically using \"%s\" compression.\n",
@@ -1354,8 +1355,9 @@ main(int  argc,                           /* I - Number of command-line args */
  /*
   * If the printer only claims to support IPP/1.0, or if the user specifically
   * included version=1.0 in the URI, then do not try to use Create-Job or
-  * Send-Document.  This is another dreaded compatibility hack, but unfortunately
-  * there are enough broken printers out there that we need this for now...
+  * Send-Document.  This is another dreaded compatibility hack, but
+  * unfortunately there are enough broken printers out there that we need
+  * this for now...
   */
 
   if (version == 10)
@@ -1401,13 +1403,21 @@ main(int  argc,                         /* I - Number of command-line args */
                          copies_sup ? copies : 1, document_format, pc, ppd,
                          media_col_sup, doc_handling_sup, print_color_mode);
 
-    ippDelete(cupsDoRequest(http, request, resource));
+    response = cupsDoRequest(http, request, resource);
 
     ipp_status = cupsLastError();
 
     fprintf(stderr, "DEBUG: Validate-Job: %s (%s)\n",
             ippErrorString(ipp_status), cupsLastErrorString());
 
+    if ((job_auth = ippFindAttribute(response, "job-authorization-uri",
+                                    IPP_TAG_URI)) != NULL)
+      num_options = cupsAddOption("job-authorization-uri",
+                                  ippGetString(job_auth, 0, NULL), num_options,
+                                  &options);
+
+    ippDelete(response);
+
     if (job_canceled)
       break;
 
@@ -1500,6 +1510,9 @@ main(int  argc,                           /* I - Number of command-line args */
       http_status = cupsSendRequest(http, request, resource, length);
       if (http_status == HTTP_CONTINUE && request->state == IPP_DATA)
       {
+       if (compression && strcmp(compression, "none"))
+         httpSetField(http, HTTP_FIELD_CONTENT_ENCODING, compression);
+
         if (num_files == 1)
         {
          if ((fd = open(files[0], O_RDONLY)) < 0)
@@ -1537,7 +1550,8 @@ main(int  argc,                           /* I - Number of command-line args */
             {
              fprintf(stderr, "DEBUG: Read %d bytes...\n", (int)bytes);
 
-             if (cupsWriteRequestData(http, buffer, bytes) != HTTP_CONTINUE)
+             if ((http_status = cupsWriteRequestData(http, buffer, bytes))
+                     != HTTP_CONTINUE)
                break;
            }
            else if (bytes == 0 || (errno != EINTR && errno != EAGAIN))
@@ -1545,6 +1559,10 @@ main(int  argc,                          /* I - Number of command-line args */
          }
        }
 
+       if (http_status == HTTP_ERROR)
+         fprintf(stderr, "DEBUG: Error writing document data for "
+                         "Print-Job: %s\n", strerror(httpError(http)));
+
         if (num_files == 1)
          close(fd);
       }
@@ -1585,6 +1603,7 @@ main(int  argc,                           /* I - Number of command-line args */
       }
       else if (ipp_status == IPP_STATUS_ERROR_JOB_CANCELED ||
                ipp_status == IPP_STATUS_ERROR_NOT_AUTHORIZED ||
+               ipp_status == IPP_STATUS_ERROR_ATTRIBUTES_OR_VALUES ||
               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 ||
@@ -1680,8 +1699,8 @@ main(int  argc,                           /* I - Number of command-line args */
          ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
                        "requesting-user-name", NULL, argv[2]);
 
-        if ((i + 1) >= num_files)
-         ippAddBoolean(request, IPP_TAG_OPERATION, "last-document", 1);
+       ippAddBoolean(request, IPP_TAG_OPERATION, "last-document",
+                     (i + 1) >= num_files);
 
        if (document_format)
          ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_MIMETYPE,
@@ -1737,6 +1756,10 @@ main(int  argc,                          /* I - Number of command-line args */
            close(fd);
        }
 
+        if (http_status == HTTP_ERROR)
+          fprintf(stderr, "DEBUG: Error writing document data for "
+                          "Send-Document: %s\n", strerror(httpError(http)));
+
        ippDelete(cupsGetResponse(http, resource));
        ippDelete(request);
 
@@ -1800,6 +1823,27 @@ main(int  argc,                          /* I - Number of command-line args */
 
       goto cleanup;
     }
+    else if (ipp_status == IPP_STATUS_ERROR_CUPS_UPGRADE_REQUIRED)
+    {
+     /*
+      * Server is configured incorrectly; the policy for Create-Job and
+      * Send-Document has to be the same (auth or no auth, encryption or
+      * no encryption).  Force the queue to stop since printing will never
+      * work.
+      */
+
+      fputs("DEBUG: The server or printer is configured incorrectly.\n",
+            stderr);
+      fputs("DEBUG: The policy for Create-Job and Send-Document must have the "
+            "same authentication and encryption requirements.\n", stderr);
+
+      ipp_status = IPP_STATUS_ERROR_INTERNAL;
+
+      if (job_id > 0)
+       cancel_job(http, uri, job_id, resource, argv[2], version);
+
+      goto cleanup;
+    }
     else if (ipp_status == IPP_NOT_FOUND)
     {
      /*
@@ -1838,6 +1882,15 @@ main(int  argc,                          /* I - Number of command-line args */
 
       backendCheckSideChannel(snmp_fd, http->hostaddr);
 
+     /*
+      * Check printer state...
+      */
+
+      check_printer_state(http, uri, resource, argv[2], version);
+
+      if (cupsLastError() <= IPP_OK_CONFLICT)
+        password_tries = 0;
+
      /*
       * Build an IPP_GET_JOB_ATTRIBUTES request...
       */
@@ -1988,12 +2041,16 @@ main(int  argc,                         /* I - Number of command-line args */
 
   check_printer_state(http, uri, resource, argv[2], version);
 
+  if (cupsLastError() <= IPP_OK_CONFLICT)
+    password_tries = 0;
+
  /*
   * Collect the final page count as needed...
   */
 
   if (have_supplies &&
-      !backendSNMPSupplies(snmp_fd, http->hostaddr, &page_count, NULL) &&
+      !backendSNMPSupplies(snmp_fd, &(http->addrlist->addr), &page_count,
+                           NULL) &&
       page_count > start_count)
     fprintf(stderr, "PAGE: total %d\n", page_count - start_count);
 
@@ -2046,17 +2103,19 @@ main(int  argc,                         /* I - Number of command-line args */
     fputs("JOBSTATE: account-authorization-failed\n", stderr);
 
   if (ipp_status == IPP_NOT_AUTHORIZED || ipp_status == IPP_FORBIDDEN ||
-      ipp_status == IPP_AUTHENTICATION_CANCELED ||
-      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_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)
     return (CUPS_BACKEND_STOP);
   else if (ipp_status == IPP_CONFLICT)
     return (CUPS_BACKEND_FAILED);
   else if (ipp_status == IPP_REQUEST_VALUE ||
+          ipp_status == IPP_STATUS_ERROR_ATTRIBUTES_OR_VALUES ||
            ipp_status == IPP_DOCUMENT_FORMAT || job_canceled < 0)
   {
     if (ipp_status == IPP_REQUEST_VALUE)
@@ -2064,6 +2123,9 @@ main(int  argc,                           /* I - Number of command-line args */
     else if (ipp_status == IPP_DOCUMENT_FORMAT)
       _cupsLangPrintFilter(stderr, "ERROR",
                            _("Printer cannot print supplied content."));
+    else if (ipp_status == IPP_STATUS_ERROR_ATTRIBUTES_OR_VALUES)
+      _cupsLangPrintFilter(stderr, "ERROR",
+                           _("Printer cannot print with supplied options."));
     else
       _cupsLangPrintFilter(stderr, "ERROR", _("Print job canceled at printer."));
 
@@ -2168,9 +2230,6 @@ check_printer_state(
   fprintf(stderr, "DEBUG: Get-Printer-Attributes: %s (%s)\n",
          ippErrorString(cupsLastError()), cupsLastErrorString());
 
-  if (cupsLastError() <= IPP_OK_CONFLICT)
-    password_tries = 0;
-
  /*
   * Return the printer-state value...
   */
@@ -2198,18 +2257,20 @@ monitor_printer(
   const char   *job_name;              /* Job name */
   ipp_jstate_t job_state;              /* Job state */
   const char   *job_user;              /* Job originating user name */
+  int          password_tries = 0;     /* Password tries */
 
 
  /*
   * Make a copy of the printer connection...
   */
 
-  http = _httpCreate(monitor->hostname, monitor->port, NULL, AF_UNSPEC,
-                     monitor->encryption, 1, _HTTP_MODE_CLIENT);
+  http = httpConnect2(monitor->hostname, monitor->port, NULL, AF_UNSPEC,
+                      monitor->encryption, 1, 0, NULL);
   httpSetTimeout(http, 30.0, timeout_cb, NULL);
   if (username[0])
     cupsSetUser(username);
-  cupsSetPasswordCB2(password_cb, NULL);
+
+  cupsSetPasswordCB2((cups_password_cb2_t)password_cb, &password_tries);
 
  /*
   * Loop until the job is canceled, aborted, or completed.
@@ -2235,6 +2296,8 @@ monitor_printer(
                                                    monitor->resource,
                                                   monitor->user,
                                                   monitor->version);
+      if (cupsLastError() <= IPP_OK_CONFLICT)
+        password_tries = 0;
 
      /*
       * Check the status of the job itself...
@@ -2539,17 +2602,27 @@ new_request(
                      "job-password-encryption", NULL, keyword);
       }
 
-      if (pc->account_id &&
-          (keyword = cupsGetOption("job-account-id", num_options,
-                                   options)) != NULL)
-        ippAddString(request, IPP_TAG_JOB, IPP_TAG_NAME, "job-account-id",
-                     NULL, keyword);
+      if (pc->account_id)
+      {
+        if ((keyword = cupsGetOption("job-account-id", num_options,
+                                    options)) == NULL)
+         keyword = cupsGetOption("job-billing", num_options, options);
 
-      if (pc->account_id &&
-          (keyword = cupsGetOption("job-accounting-user-id", num_options,
-                                   options)) != NULL)
-        ippAddString(request, IPP_TAG_JOB, IPP_TAG_NAME,
-                     "job-accounting-user-id", NULL, keyword);
+        if (keyword)
+         ippAddString(request, IPP_TAG_JOB, IPP_TAG_NAME, "job-account-id",
+                      NULL, keyword);
+      }
+
+      if (pc->accounting_user_id)
+      {
+        if ((keyword = cupsGetOption("job-accounting-user-id", num_options,
+                                    options)) == NULL)
+         keyword = user;
+
+        if (keyword)
+         ippAddString(request, IPP_TAG_JOB, IPP_TAG_NAME,
+                      "job-accounting-user-id", NULL, keyword);
+      }
 
       for (mandatory = (char *)cupsArrayFirst(pc->mandatory);
            mandatory;
@@ -2877,18 +2950,19 @@ password_cb(const char *prompt,         /* I - Prompt (not used) */
             http_t     *http,          /* I - Connection */
             const char *method,                /* I - Request method (not used) */
             const char *resource,      /* I - Resource path (not used) */
-            void       *user_data)     /* I - User data (not used) */
+            int        *password_tries)        /* I - Password tries */
 {
   char def_username[HTTP_MAX_VALUE];   /* Default username */
 
 
-  fprintf(stderr, "DEBUG: password_cb(prompt=\"%s\"), password=%p, "
-          "password_tries=%d\n", prompt, password, password_tries);
+  fprintf(stderr, "DEBUG: password_cb(prompt=\"%s\", http=%p, method=\"%s\", "
+                  "resource=\"%s\", password_tries=%p(%d)), password=%p\n",
+          prompt, http, method, resource, password_tries, *password_tries,
+          password);
 
   (void)prompt;
   (void)method;
   (void)resource;
-  (void)user_data;
 
  /*
   * Remember that we need to authenticate...
@@ -2906,9 +2980,9 @@ password_cb(const char *prompt,           /* I - Prompt (not used) */
             quote_string(def_username, quoted, sizeof(quoted)));
   }
 
-  if (password && *password && password_tries < 3)
+  if (password && *password && *password_tries < 3)
   {
-    password_tries ++;
+    (*password_tries) ++;
 
     return (password);
   }
@@ -3340,7 +3414,6 @@ run_as_user(char       *argv[],           /* I - Command-line arguments */
 
   if (conn)
   {
-    xpc_connection_suspend(conn);
     xpc_connection_cancel(conn);
     xpc_release(conn);
   }
@@ -3606,5 +3679,5 @@ update_reasons(ipp_attribute_t *attr,     /* I - printer-state-reasons or NULL */
 }
 
 /*
- * End of "$Id: ipp.c 9759 2011-05-11 03:24:33Z mike $".
+ * End of "$Id$".
  */