]> git.ipfire.org Git - thirdparty/cups.git/blobdiff - cups/util.c
Merge changes from CUPS 1.5svn-r9641
[thirdparty/cups.git] / cups / util.c
index fe2a55bb05e1ea947e305c326e5aea6239f4003d..80f36d153a047cc5c9189233ac879d0a584b91aa 100644 (file)
@@ -1,9 +1,9 @@
 /*
  * "$Id: util.c 7850 2008-08-20 00:07:25Z mike $"
  *
- *   Printing utilities for the Common UNIX Printing System (CUPS).
+ *   Printing utilities for CUPS.
  *
- *   Copyright 2007-2008 by Apple Inc.
+ *   Copyright 2007-2010 by Apple Inc.
  *   Copyright 1997-2006 by Easy Software Products.
  *
  *   These coded instructions, statements, and computer programs are the
@@ -18,7 +18,7 @@
  *
  *   cupsCancelJob()        - Cancel a print job on the default server.
  *   cupsCancelJob2()       - Cancel or purge a print job.
- *   cupsCreateJob()        - Create an empty job.
+ *   cupsCreateJob()        - Create an empty job for streaming.
  *   cupsFinishDocument()   - Finish sending a document.
  *   cupsFreeJobs()         - Free memory used by job data.
  *   cupsGetClasses()       - Get a list of printer classes from the default
@@ -37,8 +37,6 @@
  *                            server if it has changed.
  *   cupsGetPrinters()      - Get a list of printers from the default server.
  *   cupsGetServerPPD()     - Get an available PPD file from the server.
- *   cupsLastError()        - Return the last IPP status code.
- *   cupsLastErrorString()  - Return the last IPP status-message.
  *   cupsPrintFile()        - Print a file to a printer or class on the default
  *                            server.
  *   cupsPrintFile2()       - Print a file to a printer or class on the
@@ -49,7 +47,6 @@
  *                            the specified server.
  *   cupsStartDocument()    - Add a document to a job created with
  *                            cupsCreateJob().
- *   _cupsConnect()         - Get the default server connection...
  *   cups_get_printer_uri() - Get the printer-uri-supported attribute for the
  *                            first printer in a class.
  */
  * Include necessary headers...
  */
 
-#include "globals.h"
-#include "debug.h"
-#include <stdlib.h>
-#include <errno.h>
+#include "cups-private.h"
 #include <fcntl.h>
 #include <sys/stat.h>
 #if defined(WIN32) || defined(__EMX__)
@@ -112,7 +106,7 @@ cupsCancelJob(const char *name,             /* I - Name of printer or class */
  * Use the @link cupsLastError@ and @link cupsLastErrorString@ functions to get
  * the cause of any failure.
  *
- * @since CUPS 1.4@
+ * @since CUPS 1.4/Mac OS X 10.6@
  */
 
 ipp_status_t                           /* O - IPP status */
@@ -200,7 +194,7 @@ cupsCancelJob2(http_t     *http,    /* I - Connection to server or @code CUPS_HTTP_
  * print, use the @link cupsPrintFile2@ or @link cupsPrintFiles2@ function
  * instead.
  *
- * @since CUPS 1.4@
+ * @since CUPS 1.4/Mac OS X 10.6@
  */
 
 int                                    /* O - Job ID or 0 on error */
@@ -220,7 +214,7 @@ cupsCreateJob(
 
 
   DEBUG_printf(("cupsCreateJob(http=%p, name=\"%s\", title=\"%s\", "
-                "num_options=%d, options=%p)\n",
+                "num_options=%d, options=%p)",
                 http, name, title, num_options, options));
 
  /*
@@ -280,7 +274,7 @@ cupsCreateJob(
  *
  * The document must have been started using @link cupsStartDocument@.
  *
- * @since CUPS 1.4@
+ * @since CUPS 1.4/Mac OS X 10.6@
  */
 
 ipp_status_t                           /* O - Status of document submission */
@@ -449,7 +443,7 @@ cupsGetDefault(void)
  * functions to get the user-defined default printer, as this function does
  * not support the lpoptions-defined default printer.
  *
- * @since CUPS 1.1.21@
+ * @since CUPS 1.1.21/Mac OS X 10.4@
  */
 
 const char *                           /* O - Default printer or @code NULL@ */
@@ -458,21 +452,15 @@ cupsGetDefault2(http_t *http)             /* I - Connection to server or @code CUPS_HTTP_DE
   ipp_t                *request,               /* IPP Request */
                *response;              /* IPP Response */
   ipp_attribute_t *attr;               /* Current attribute */
-  const char   *var;                   /* Environment variable */
   _cups_globals_t *cg = _cupsGlobals();        /* Pointer to library globals */
 
 
  /*
-  * First see if the LPDEST or PRINTER environment variables are
-  * set...  However, if PRINTER is set to "lp", ignore it to work
-  * around a "feature" in most Linux distributions - the default
-  * user login scripts set PRINTER to "lp"...
+  * See if we have a user default printer set...
   */
 
-  if ((var = getenv("LPDEST")) != NULL)
-    return (var);
-  else if ((var = getenv("PRINTER")) != NULL && strcmp(var, "lp") != 0)
-    return (var);
+  if (_cupsUserDefault(cg->def_printer, sizeof(cg->def_printer)))
+    return (cg->def_printer);
 
  /*
   * Connect to the server as needed...
@@ -546,7 +534,7 @@ cupsGetJobs(cups_job_t **jobs,              /* O - Job data */
  * pending, processing, or held and @code CUPS_WHICHJOBS_COMPLETED@ returns
  * jobs that are stopped, canceled, aborted, or completed.
  *
- * @since CUPS 1.1.21@
+ * @since CUPS 1.1.21/Mac OS X 10.4@
  */
 
 int                                    /* O - Number of jobs */
@@ -576,17 +564,17 @@ cupsGetJobs2(http_t     *http,            /* I - Connection to server or @code CUPS_HTTP_D
   _cups_globals_t *cg = _cupsGlobals();        /* Pointer to library globals */
   static const char * const attrs[] =  /* Requested attributes */
                {
+                 "document-format",
                  "job-id",
-                 "job-priority",
                  "job-k-octets",
+                 "job-name",
+                 "job-originating-user-name",
+                 "job-printer-uri",
+                 "job-priority",
                  "job-state",
                  "time-at-completed",
                  "time-at-creation",
-                 "time-at-processing",
-                 "job-printer-uri",
-                 "document-format",
-                 "job-name",
-                 "job-originating-user-name"
+                 "time-at-processing"
                };
 
 
@@ -610,13 +598,13 @@ cupsGetJobs2(http_t     *http,            /* I - Connection to server or @code CUPS_HTTP_D
     if (httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
                          "localhost", 0, "/printers/%s", name) != HTTP_URI_OK)
     {
-      _cupsSetError(IPP_INTERNAL_ERROR, _("Unable to create printer-uri!"), 1);
+      _cupsSetError(IPP_INTERNAL_ERROR, _("Unable to create printer-uri"), 1);
 
       return (-1);
     }
   }
   else
-    strcpy(uri, "ipp://localhost/jobs");
+    strcpy(uri, "ipp://localhost/");
 
   if (!http)
     if ((http = _cupsConnect()) == NULL)
@@ -815,7 +803,8 @@ cupsGetJobs2(http_t     *http,              /* I - Connection to server or @code CUPS_HTTP_D
  * in the class.
  *
  * The returned filename is stored in a static buffer and is overwritten with
- * each call to @code cupsGetPPD@ or @link cupsGetPPD2@.
+ * each call to @code cupsGetPPD@ or @link cupsGetPPD2@.  The caller "owns" the
+ * file that is created and must @code unlink@ the returned filename.
  */
 
 const char *                           /* O - Filename for PPD file */
@@ -846,9 +835,10 @@ cupsGetPPD(const char *name)               /* I - Destination name */
  * in the class.
  *
  * The returned filename is stored in a static buffer and is overwritten with
- * each call to @link cupsGetPPD@ or @code cupsGetPPD2@.
+ * each call to @link cupsGetPPD@ or @code cupsGetPPD2@.  The caller "owns" the
+ * file that is created and must @code unlink@ the returned filename.
  *
- * @since CUPS 1.1.21@
+ * @since CUPS 1.1.21/Mac OS X 10.4@
  */
 
 const char *                           /* O - Filename for PPD file */
@@ -879,7 +869,8 @@ cupsGetPPD2(http_t     *http,               /* I - Connection to server or @code CUPS_HTTP_DE
  *
  * The "buffer" parameter contains the local PPD filename.  If it contains
  * the empty string, a new temporary file is created, otherwise the existing
- * file will be overwritten as needed.
+ * file will be overwritten as needed.  The caller "owns" the file that is
+ * created and must @code unlink@ the returned filename.
  *
  * On success, @code HTTP_OK@ is returned for a new PPD file and
  * @code HTTP_NOT_MODIFIED@ if the existing PPD file is up-to-date.  Any other
@@ -888,7 +879,7 @@ cupsGetPPD2(http_t     *http,               /* I - Connection to server or @code CUPS_HTTP_DE
  * For classes, @code cupsGetPPD3@ returns the PPD file for the first printer
  * in the class.
  *
- * @since CUPS 1.4@
+ * @since CUPS 1.4/Mac OS X 10.6@
  */
 
 http_status_t                          /* O  - HTTP status */
@@ -916,27 +907,132 @@ cupsGetPPD3(http_t     *http,            /* I  - HTTP connection or @code CUPS_HTTP_DEFAUL
   */
 
   DEBUG_printf(("cupsGetPPD3(http=%p, name=\"%s\", modtime=%p(%d), buffer=%p, "
-                "bufsize=%d)\n", http, name ? name : "(null)", modtime,
+                "bufsize=%d)", http, name, modtime,
                modtime ? (int)*modtime : 0, buffer, (int)bufsize));
 
   if (!name)
   {
-    _cupsSetError(IPP_INTERNAL_ERROR, _("No printer name!"), 1);
+    _cupsSetError(IPP_INTERNAL_ERROR, _("No printer name"), 1);
     return (HTTP_NOT_ACCEPTABLE);
   }
 
   if (!modtime)
   {
-    _cupsSetError(IPP_INTERNAL_ERROR, _("No modification time!"), 1);
+    _cupsSetError(IPP_INTERNAL_ERROR, _("No modification time"), 1);
     return (HTTP_NOT_ACCEPTABLE);
   }
 
   if (!buffer || bufsize <= 1)
   {
-    _cupsSetError(IPP_INTERNAL_ERROR, _("Bad filename buffer!"), 1);
+    _cupsSetError(IPP_INTERNAL_ERROR, _("Bad filename buffer"), 1);
     return (HTTP_NOT_ACCEPTABLE);
   }
 
+#ifndef WIN32
+ /*
+  * See if the PPD file is available locally...
+  */
+
+  if (!cg->servername[0])
+    cupsServer();
+
+  if (!strcasecmp(cg->servername, "localhost"))
+  {
+    char       ppdname[1024];          /* PPD filename */
+    struct stat        ppdinfo;                /* PPD file information */
+
+
+    snprintf(ppdname, sizeof(ppdname), "%s/ppd/%s.ppd", cg->cups_serverroot,
+             name);
+    if (!stat(ppdname, &ppdinfo))
+    {
+     /*
+      * OK, the file exists, use it!
+      */
+
+      if (buffer[0])
+      {
+        unlink(buffer);
+
+       if (symlink(ppdname, buffer) && errno != EEXIST)
+        {
+          _cupsSetError(IPP_INTERNAL_ERROR, NULL, 0);
+
+         return (HTTP_SERVER_ERROR);
+       }
+      }
+      else
+      {
+        int            tries;          /* Number of tries */
+        const char     *tmpdir;        /* TMPDIR environment variable */
+       struct timeval  curtime;        /* Current time */
+
+       /*
+       * Previously we put root temporary files in the default CUPS temporary
+       * directory under /var/spool/cups.  However, since the scheduler cleans
+       * out temporary files there and runs independently of the user apps, we
+       * don't want to use it unless specifically told to by cupsd.
+       */
+
+       if ((tmpdir = getenv("TMPDIR")) == NULL)
+#  ifdef __APPLE__
+         tmpdir = "/private/tmp";      /* /tmp is a symlink to /private/tmp */
+#  else
+          tmpdir = "/tmp";
+#  endif /* __APPLE__ */
+
+       /*
+       * Make the temporary name using the specified directory...
+       */
+
+       tries = 0;
+
+       do
+       {
+        /*
+         * Get the current time of day...
+         */
+
+         gettimeofday(&curtime, NULL);
+
+        /*
+         * Format a string using the hex time values...
+         */
+
+         snprintf(buffer, bufsize, "%s/%08lx%05lx", tmpdir,
+                  (unsigned long)curtime.tv_sec,
+                  (unsigned long)curtime.tv_usec);
+
+        /*
+         * Try to make a symlink...
+         */
+
+         if (!symlink(ppdname, buffer))
+           break;
+
+         tries ++;
+       }
+       while (tries < 1000);
+
+        if (tries >= 1000)
+       {
+          _cupsSetError(IPP_INTERNAL_ERROR, NULL, 0);
+
+         return (HTTP_SERVER_ERROR);
+       }
+      }
+
+      if (*modtime >= ppdinfo.st_mtime)
+        return (HTTP_NOT_MODIFIED);
+      else
+      {
+        *modtime = ppdinfo.st_mtime;
+       return (HTTP_OK);
+      }
+    }
+  }
+#endif /* !WIN32 */
+
  /*
   * Try finding a printer URI for this printer...
   */
@@ -949,7 +1045,7 @@ cupsGetPPD3(http_t     *http,              /* I  - HTTP connection or @code CUPS_HTTP_DEFAUL
                             resource, sizeof(resource), 0))
     return (HTTP_NOT_FOUND);
 
-  DEBUG_printf(("cupsGetPPD3: Printer hostname=\"%s\", port=%d\n", hostname,
+  DEBUG_printf(("2cupsGetPPD3: Printer hostname=\"%s\", port=%d", hostname,
                 port));
 
  /*
@@ -958,7 +1054,7 @@ cupsGetPPD3(http_t     *http,              /* I  - HTTP connection or @code CUPS_HTTP_DEFAUL
 
   httpGetHostname(NULL, localhost, sizeof(localhost));
 
-  DEBUG_printf(("cupsGetPPD3: Local hostname=\"%s\"\n", localhost));
+  DEBUG_printf(("2cupsGetPPD3: Local hostname=\"%s\"", localhost));
 
   if (!strcasecmp(localhost, hostname))
     strcpy(hostname, "localhost");
@@ -970,7 +1066,7 @@ cupsGetPPD3(http_t     *http,              /* I  - HTTP connection or @code CUPS_HTTP_DEFAUL
   httpGetHostname(http, http_hostname, sizeof(http_hostname));
   http_port = _httpAddrPort(http->hostaddr);
 
-  DEBUG_printf(("cupsGetPPD3: Connection hostname=\"%s\", port=%d\n",
+  DEBUG_printf(("2cupsGetPPD3: Connection hostname=\"%s\", port=%d",
                 http_hostname, http_port));
 
  /*
@@ -982,7 +1078,7 @@ cupsGetPPD3(http_t     *http,              /* I  - HTTP connection or @code CUPS_HTTP_DEFAUL
   else if ((http2 = httpConnectEncrypt(hostname, port,
                                        cupsEncryption())) == NULL)
   {
-    DEBUG_puts("cupsGetPPD3: Unable to connect to server!");
+    DEBUG_puts("1cupsGetPPD3: Unable to connect to server");
 
     return (HTTP_SERVICE_UNAVAILABLE);
   }
@@ -1032,22 +1128,7 @@ cupsGetPPD3(http_t     *http,            /* I  - HTTP connection or @code CUPS_HTTP_DEFAUL
     *modtime = httpGetDateTime(httpGetField(http2, HTTP_FIELD_DATE));
   else if (status != HTTP_NOT_MODIFIED)
   {
-    switch (status)
-    {
-      case HTTP_NOT_FOUND :
-          _cupsSetError(IPP_NOT_FOUND, httpStatus(status), 0);
-         break;
-
-      case HTTP_UNAUTHORIZED :
-          _cupsSetError(IPP_NOT_AUTHORIZED, httpStatus(status), 0);
-         break;
-
-      default :
-         DEBUG_printf(("cupsGetPPD3: HTTP error %d mapped to "
-                       "IPP_SERVICE_UNAVAILABLE!\n", status));
-         _cupsSetError(IPP_SERVICE_UNAVAILABLE, httpStatus(status), 0);
-         break;
-    }
+    _cupsSetHTTPError(status);
 
     unlink(cg->ppd_filename);
   }
@@ -1059,6 +1140,8 @@ cupsGetPPD3(http_t     *http,             /* I  - HTTP connection or @code CUPS_HTTP_DEFAUL
   * Return the PPD file...
   */
 
+  DEBUG_printf(("1cupsGetPPD3: Returning status %d", status));
+
   return (status);
 }
 
@@ -1181,7 +1264,7 @@ cupsGetPrinters(char ***printers) /* O - Printers */
  * overwritten on the next call to @link cupsGetPPD@, @link cupsGetPPD2@,
  * or @link cupsGetServerPPD@.
  *
- * @since CUPS 1.3@
+ * @since CUPS 1.3/Mac OS X 10.5@
  */
 
 char *                                 /* O - Name of PPD file or @code NULL@ on error */
@@ -1200,7 +1283,7 @@ cupsGetServerPPD(http_t     *http,        /* I - Connection to server or @code CUPS_HTT
 
   if (!name)
   {
-    _cupsSetError(IPP_INTERNAL_ERROR, _("No PPD name!"), 1);
+    _cupsSetError(IPP_INTERNAL_ERROR, _("No PPD name"), 1);
 
     return (NULL);
   }
@@ -1246,30 +1329,6 @@ cupsGetServerPPD(http_t     *http,       /* I - Connection to server or @code CUPS_HTT
 }
 
 
-/*
- * 'cupsLastError()' - Return the last IPP status code.
- */
-
-ipp_status_t                           /* O - IPP status code from last request */
-cupsLastError(void)
-{
-  return (_cupsGlobals()->last_error);
-}
-
-
-/*
- * 'cupsLastErrorString()' - Return the last IPP status-message.
- *
- * @since CUPS 1.2@
- */
-
-const char *                           /* O - status-message text from last request */
-cupsLastErrorString(void)
-{
-  return (_cupsGlobals()->last_status_message);
-}
-
-
 /*
  * 'cupsPrintFile()' - Print a file to a printer or class on the default server.
  */
@@ -1282,7 +1341,7 @@ cupsPrintFile(const char    *name,        /* I - Destination name */
              cups_option_t *options)   /* I - Options */
 {
   DEBUG_printf(("cupsPrintFile(name=\"%s\", filename=\"%s\", "
-                "title=\"%s\", num_options=%d, options=%p)\n",
+                "title=\"%s\", num_options=%d, options=%p)",
                 name, filename, title, num_options, options));
 
   return (cupsPrintFiles2(CUPS_HTTP_DEFAULT, name, 1, &filename, title,
@@ -1294,7 +1353,7 @@ cupsPrintFile(const char    *name,        /* I - Destination name */
  * 'cupsPrintFile2()' - Print a file to a printer or class on the specified
  *                      server.
  *
- * @since CUPS 1.1.21@
+ * @since CUPS 1.1.21/Mac OS X 10.4@
  */
 
 int                                    /* O - Job ID or 0 on error */
@@ -1307,7 +1366,7 @@ cupsPrintFile2(
     cups_option_t *options)            /* I - Options */
 {
   DEBUG_printf(("cupsPrintFile2(http=%p, name=\"%s\", filename=\"%s\", "
-                "title=\"%s\", num_options=%d, options=%p)\n",
+                "title=\"%s\", num_options=%d, options=%p)",
                 http, name, filename, title, num_options, options));
 
   return (cupsPrintFiles2(http, name, 1, &filename, title, num_options,
@@ -1330,10 +1389,9 @@ cupsPrintFiles(
     cups_option_t *options)            /* I - Options */
 {
   DEBUG_printf(("cupsPrintFiles(name=\"%s\", num_files=%d, "
-                "files=%p, title=\"%s\", num_options=%d, options=%p)\n",
+                "files=%p, title=\"%s\", num_options=%d, options=%p)",
                 name, num_files, files, title, num_options, options));
 
-
  /*
   * Print the file(s)...
   */
@@ -1347,7 +1405,7 @@ cupsPrintFiles(
  * 'cupsPrintFiles2()' - Print one or more files to a printer or class on the
  *                       specified server.
  *
- * @since CUPS 1.1.21@
+ * @since CUPS 1.1.21/Mac OS X 10.4@
  */
 
 int                                    /* O - Job ID or 0 on error */
@@ -1368,10 +1426,13 @@ cupsPrintFiles2(
   char         buffer[8192];           /* Copy buffer */
   ssize_t      bytes;                  /* Bytes in buffer */
   http_status_t        status;                 /* Status of write */
+  _cups_globals_t *cg = _cupsGlobals();        /* Global data */
+  ipp_status_t cancel_status;          /* Status code to preserve */
+  char         *cancel_message;        /* Error message to preserve */
 
 
   DEBUG_printf(("cupsPrintFiles2(http=%p, name=\"%s\", num_files=%d, "
-                "files=%p, title=\"%s\", num_options=%d, options=%p)\n",
+                "files=%p, title=\"%s\", num_options=%d, options=%p)",
                 http, name, num_files, files, title, num_options, options));
 
  /*
@@ -1419,15 +1480,15 @@ cupsPrintFiles2(
       * Unable to open print file, cancel the job and return...
       */
 
-      cupsCancelJob2(http, name, job_id, 0);
-      return (0);
+      _cupsSetError(IPP_DOCUMENT_ACCESS_ERROR, NULL, 0);
+      goto cancel_job;
     }
 
     status = cupsStartDocument(http, name, job_id, docname, format,
-                               i == (num_files - 1));
+                              i == (num_files - 1));
 
     while (status == HTTP_CONTINUE &&
-           (bytes = cupsFileRead(fp, buffer, sizeof(buffer))) > 0)
+          (bytes = cupsFileRead(fp, buffer, sizeof(buffer))) > 0)
       status = cupsWriteRequestData(http, buffer, bytes);
 
     cupsFileClose(fp);
@@ -1438,12 +1499,30 @@ cupsPrintFiles2(
       * Unable to queue, cancel the job and return...
       */
 
-      cupsCancelJob2(http, name, job_id, 0);
-      return (0);
+      goto cancel_job;
     }
   }
 
   return (job_id);
+
+ /*
+  * If we get here, something happened while sending the print job so we need
+  * to cancel the job without setting the last error (since we need to preserve
+  * the current error...
+  */
+
+  cancel_job:
+
+  cancel_status  = cg->last_error;
+  cancel_message = cg->last_status_message ?
+                       _cupsStrRetain(cg->last_status_message) : NULL;
+
+  cupsCancelJob2(http, name, job_id, 0);
+
+  cg->last_error          = cancel_status;
+  cg->last_status_message = cancel_message;
+
+  return (0);
 }
 
 
@@ -1458,7 +1537,7 @@ cupsPrintFiles2(
  * @code CUPS_FORMAT_TEXT@ are provided for the "format" argument, although
  * any supported MIME type string can be supplied.
  *
- * @since CUPS 1.4@
+ * @since CUPS 1.4/Mac OS X 10.6@
  */
 
 http_status_t                          /* O - HTTP status of request */
@@ -1516,68 +1595,8 @@ cupsStartDocument(
 
 
 /*
- * '_cupsConnect()' - Get the default server connection...
- */
-
-http_t *                               /* O - HTTP connection */
-_cupsConnect(void)
-{
-  _cups_globals_t *cg = _cupsGlobals();        /* Pointer to library globals */
-
-
- /*
-  * See if we are connected to the same server...
-  */
-
-  if (cg->http)
-  {
-   /*
-    * Compare the connection hostname, port, and encryption settings to
-    * the cached defaults; these were initialized the first time we
-    * connected...
-    */
-
-    if (strcmp(cg->http->hostname, cg->server) ||
-        cg->ipp_port != _httpAddrPort(cg->http->hostaddr) ||
-        (cg->http->encryption != cg->encryption &&
-        cg->http->encryption == HTTP_ENCRYPT_NEVER))
-    {
-     /*
-      * Need to close the current connection because something has changed...
-      */
-
-      httpClose(cg->http);
-      cg->http = NULL;
-    }
-  }
-
- /*
-  * (Re)connect as needed...
-  */
-
-  if (!cg->http)
-  {
-    if ((cg->http = httpConnectEncrypt(cupsServer(), ippPort(),
-                                       cupsEncryption())) == NULL)
-    {
-      if (errno)
-        _cupsSetError(IPP_SERVICE_UNAVAILABLE, NULL, 0);
-      else
-        _cupsSetError(IPP_SERVICE_UNAVAILABLE,
-                     _("Unable to connect to host."), 1);
-    }
-  }
-
- /*
-  * Return the cached connection...
-  */
-
-  return (cg->http);
-}
-
-
-/*
- * 'cups_get_printer_uri()' - Get the printer-uri-supported attribute for the first printer in a class.
+ * 'cups_get_printer_uri()' - Get the printer-uri-supported attribute for the
+ *                            first printer in a class.
  */
 
 static int                             /* O - 1 on success, 0 on failure */
@@ -1605,16 +1624,15 @@ cups_get_printer_uri(
                                        /* Hostname associated with connection */
   static const char * const requested_attrs[] =
                {                       /* Requested attributes */
+                 "member-uris",
                  "printer-uri-supported",
-                 "printer-type",
-                 "member-uris"
+                 "printer-type"
                };
 
 
-  DEBUG_printf(("cups_get_printer_uri(http=%p, name=\"%s\", host=%p, "
-                "hostsize=%d, resource=%p, resourcesize=%d, depth=%d)\n",
-               http, name ? name : "(null)", host, hostsize,
-               resource, resourcesize, depth));
+  DEBUG_printf(("7cups_get_printer_uri(http=%p, name=\"%s\", host=%p, "
+                "hostsize=%d, resource=%p, resourcesize=%d, depth=%d)",
+               http, name, host, hostsize, resource, resourcesize, depth));
 
  /*
   * Setup the printer URI...
@@ -1623,7 +1641,7 @@ cups_get_printer_uri(
   if (httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
                        "localhost", 0, "/printers/%s", name) != HTTP_URI_OK)
   {
-    _cupsSetError(IPP_INTERNAL_ERROR, _("Unable to create printer-uri!"), 1);
+    _cupsSetError(IPP_INTERNAL_ERROR, _("Unable to create printer-uri"), 1);
 
     *host     = '\0';
     *resource = '\0';
@@ -1631,7 +1649,7 @@ cups_get_printer_uri(
     return (0);
   }
 
-  DEBUG_printf(("cups_get_printer_uri: printer-uri=\"%s\"\n", uri));
+  DEBUG_printf(("9cups_get_printer_uri: printer-uri=\"%s\"", uri));
 
  /*
   * Get the hostname and port number we are connected to...
@@ -1712,7 +1730,7 @@ cups_get_printer_uri(
            else if ((http2 = httpConnectEncrypt(host, *port,
                                                 cupsEncryption())) == NULL)
            {
-             DEBUG_puts("Unable to connect to server!");
+             DEBUG_puts("8cups_get_printer_uri: Unable to connect to server");
 
              continue;
            }
@@ -1742,7 +1760,9 @@ cups_get_printer_uri(
     else if ((attr = ippFindAttribute(response, "printer-uri-supported",
                                       IPP_TAG_URI)) != NULL)
     {
-      httpSeparateURI(HTTP_URI_CODING_ALL, attr->values[0].string.text,
+      httpSeparateURI(HTTP_URI_CODING_ALL,
+                      _httpResolveURI(attr->values[0].string.text, uri,
+                                     sizeof(uri), 0),
                       scheme, sizeof(scheme), username, sizeof(username),
                      host, hostsize, port, resource, resourcesize);
       ippDelete(response);
@@ -1750,7 +1770,7 @@ cups_get_printer_uri(
       if (!strncmp(resource, "/classes/", 9))
       {
         _cupsSetError(IPP_INTERNAL_ERROR,
-                     _("No printer-uri found for class!"), 1);
+                     _("No printer-uri found for class"), 1);
 
        *host     = '\0';
        *resource = '\0';
@@ -1765,7 +1785,7 @@ cups_get_printer_uri(
   }
 
   if (cupsLastError() != IPP_NOT_FOUND)
-    _cupsSetError(IPP_INTERNAL_ERROR, _("No printer-uri found!"), 1);
+    _cupsSetError(IPP_INTERNAL_ERROR, _("No printer-uri found"), 1);
 
   *host     = '\0';
   *resource = '\0';