]> git.ipfire.org Git - thirdparty/cups.git/blobdiff - cups/http-support.c
Merge changes from CUPS 1.5svn-r9641
[thirdparty/cups.git] / cups / http-support.c
index cd78c628b67277d5bbf996e4449a22823bbe66f9..1d73f7d4887e8767cbfbb71ff56508a103a682aa 100644 (file)
@@ -1,9 +1,9 @@
 /*
  * "$Id: http-support.c 7952 2008-09-17 00:56:20Z mike $"
  *
- *   HTTP support routines for the Common UNIX Printing System (CUPS) scheduler.
+ *   HTTP support routines for CUPS.
  *
- *   Copyright 2007-2009 by Apple Inc.
+ *   Copyright 2007-2011 by Apple Inc.
  *   Copyright 1997-2007 by Easy Software Products, all rights reserved.
  *
  *   These coded instructions, statements, and computer programs are the
@@ -36,6 +36,7 @@
  *   httpStatus()         - Return a short string describing a HTTP status code.
  *   _cups_hstrerror()    - hstrerror() emulation function for Solaris and
  *                          others...
+ *   _httpDecodeURI()     - Percent-decode a HTTP request URI.
  *   _httpEncodeURI()     - Percent-encode a HTTP request URI.
  *   _httpResolveURI()    - Resolve a DNS-SD URI.
  *   http_copy_decode()   - Copy and decode a URI.
  * Include necessary headers...
  */
 
-#include "debug.h"
-#include "globals.h"
-#include <stdlib.h>
+#include "cups-private.h"
 #ifdef HAVE_DNSSD
 #  include <dns_sd.h>
-#  include <poll.h>
+#  ifdef WIN32
+#    include <io.h>
+#  elif defined(HAVE_POLL)
+#    include <poll.h>
+#  else
+#    include <sys/select.h>
+#  endif /* WIN32 */
 #endif /* HAVE_DNSSD */
 
 
@@ -109,7 +114,7 @@ static char         *http_copy_encode(char *dst, const char *src,
                                          char *dstend, const char *reserved,
                                          const char *term, int encode);
 #ifdef HAVE_DNSSD
-static void            resolve_callback(DNSServiceRef sdRef,
+static void DNSSD_API  resolve_callback(DNSServiceRef sdRef,
                                         DNSServiceFlags flags,
                                         uint32_t interfaceIndex,
                                         DNSServiceErrorType errorCode,
@@ -293,7 +298,7 @@ httpAssembleURI(
       * Otherwise, just copy the host string...
       */
 
-      ptr = http_copy_encode(ptr, host, end, ":/?#[]@\\", NULL,
+      ptr = http_copy_encode(ptr, host, end, ":/?#[]@\\\"", NULL,
                              encoding & HTTP_URI_CODING_HOSTNAME);
 
       if (!ptr)
@@ -916,7 +921,9 @@ httpSeparateURI(
 
     for (ptr = scheme, end = scheme + schemelen - 1;
          *uri && *uri != ':' && ptr < end;)
-      if (isalnum(*uri & 255) || *uri == '-' || *uri == '+' || *uri == '.')
+      if (strchr("ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+                 "abcdefghijklmnopqrstuvwxyz"
+                "0123456789-+.", *uri) != NULL)
         *ptr++ = *uri++;
       else
         break;
@@ -940,7 +947,7 @@ httpSeparateURI(
     *port = 80;
   else if (!strcmp(scheme, "https"))
     *port = 443;
-  else if (!strcmp(scheme, "ipp"))
+  else if (!strcmp(scheme, "ipp") || !strcmp(scheme, "ipps"))
     *port = 631;
   else if (!strcasecmp(scheme, "lpd"))
     *port = 515;
@@ -1243,6 +1250,12 @@ httpStatus(http_status_t status) /* I - HTTP status code */
     case HTTP_SERVER_ERROR :
         s = _("Internal Server Error");
        break;
+    case HTTP_PKI_ERROR :
+        s = _("SSL/TLS Negotiation Error");
+       break;
+    case HTTP_WEBIF_DISABLED :
+        s = _("Web Interface is Disabled");
+       break;
 
     default :
         s = _("Unknown");
@@ -1279,6 +1292,22 @@ _cups_hstrerror(int error)               /* I - Error number */
 #endif /* !HAVE_HSTRERROR */
 
 
+/*
+ * '_httpDecodeURI()' - Percent-decode a HTTP request URI.
+ */
+
+char *                                 /* O - Decoded URI or NULL on error */
+_httpDecodeURI(char       *dst,                /* I - Destination buffer */
+               const char *src,                /* I - Source URI */
+              size_t     dstsize)      /* I - Size of destination buffer */
+{
+  if (http_copy_decode(dst, src, (int)dstsize, NULL, 1))
+    return (dst);
+  else
+    return (NULL);
+}
+
+
 /*
  * '_httpEncodeURI()' - Percent-encode a HTTP request URI.
  */
@@ -1335,7 +1364,7 @@ _httpResolveURI(
 #endif /* DEBUG */
   {
     if (logit)
-      _cupsLangPrintf(stderr, _("Bad device URI \"%s\"!\n"), uri);
+      _cupsLangPrintFilter(stderr, "ERROR", _("Bad device-uri \"%s\"."), uri);
 
     DEBUG_printf(("6_httpResolveURI: httpSeparateURI returned %d!", status));
     DEBUG_puts("5_httpResolveURI: Returning NULL");
@@ -1349,15 +1378,23 @@ _httpResolveURI(
   if (strstr(hostname, "._tcp"))
   {
 #ifdef HAVE_DNSSD
+#  ifdef WIN32
+#    pragma comment(lib, "dnssd.lib")
+#  endif /* WIN32 */
     DNSServiceRef      ref,            /* DNS-SD master service reference */
                        domainref,      /* DNS-SD service reference for domain */
                        localref;       /* DNS-SD service reference for .local */
-    int                        domainsent = 0; /* Send the domain resolve? */
+    int                        domainsent = 0, /* Send the domain resolve? */
+                       offline = 0;    /* offline-report state set? */
     char               *regtype,       /* Pointer to type in hostname */
                        *domain;        /* Pointer to domain in hostname */
     _http_uribuf_t     uribuf;         /* URI buffer */
+#ifdef HAVE_POLL
     struct pollfd      polldata;       /* Polling data */
-
+#else /* select() */
+    fd_set             input_set;      /* Input set for select() */
+    struct timeval     stimeout;       /* Timeout value for select() */
+#endif /* HAVE_POLL */
 
     if (logit)
       fprintf(stderr, "DEBUG: Resolving \"%s\"...\n", hostname);
@@ -1406,7 +1443,6 @@ _httpResolveURI(
       fputs("STATE: +connecting-to-device\n", stderr);
       fprintf(stderr, "DEBUG: Resolving \"%s\", regtype=\"%s\", "
                       "domain=\"local.\"...\n", hostname, regtype);
-      _cupsLangPuts(stderr, _("INFO: Looking for printer...\n"));
     }
 
     uri = NULL;
@@ -1418,36 +1454,88 @@ _httpResolveURI(
                            hostname, regtype, "local.", resolve_callback,
                            &uribuf) == kDNSServiceErr_NoError)
       {
-        if (strcasecmp(domain, "local."))
+       int     fds;                    /* Number of ready descriptors */
+       time_t  timeout,                /* Poll timeout */
+               start_time = time(NULL);/* Start time */
+
+       for (;;)
        {
+         if (logit)
+           _cupsLangPrintFilter(stderr, "INFO", _("Looking for printer."));
+
         /*
-         * Wait 2 seconds for a response to the local resolve; if nothing comes
-         * in, do an additional domain resolution...
+         * For the first minute, wakeup every 2 seconds to emit a
+         * "looking for printer" message...
          */
 
+         timeout = (time(NULL) < (start_time + 60)) ? 2000 : -1;
+
+#ifdef HAVE_POLL
          polldata.fd     = DNSServiceRefSockFD(ref);
          polldata.events = POLLIN;
 
-         if (poll(&polldata, 1, 2000) != 1)
+         fds = poll(&polldata, 1, timeout);
+
+#else /* select() */
+         FD_ZERO(&input_set);
+         FD_SET(DNSServiceRefSockFD(ref), &input_set);
+
+         stimeout.tv_sec  = ((int)timeout) / 1000;
+         stimeout.tv_usec = ((int)(timeout) * 1000) % 1000000;
+
+         fds = select(DNSServiceRefSockFD(ref)+1, &input_set, NULL, NULL, 
+                      timeout < 0.0 ? NULL : &stimeout); 
+#endif /* HAVE_POLL */
+
+         if (fds < 0)
+         {
+           if (errno != EINTR && errno != EAGAIN)
+           {
+             DEBUG_printf(("5_httpResolveURI: poll error: %s", strerror(errno)));
+             break;
+           }
+         }
+         else if (fds == 0)
          {
           /*
-           * OK, send the domain name resolve...
+           * Wait 2 seconds for a response to the local resolve; if nothing
+           * comes in, do an additional domain resolution...
            */
 
-           if (logit)
-             fprintf(stderr, "DEBUG: Resolving \"%s\", regtype=\"%s\", "
-                             "domain=\"%s\"...\n", hostname, regtype, domain);
+           if (domainsent == 0 && strcasecmp(domain, "local."))
+           {
+             if (logit)
+               fprintf(stderr,
+                       "DEBUG: Resolving \"%s\", regtype=\"%s\", "
+                       "domain=\"%s\"...\n", hostname, regtype, domain);
+  
+             domainref = ref;
+             if (DNSServiceResolve(&domainref, kDNSServiceFlagsShareConnection, 0,
+                                   hostname, regtype, domain, resolve_callback,
+                                   &uribuf) == kDNSServiceErr_NoError)
+               domainsent = 1;
+           }
 
-           domainref = ref;
-           if (DNSServiceResolve(&domainref, kDNSServiceFlagsShareConnection, 0,
-                                 hostname, regtype, domain, resolve_callback,
-                                 &uribuf) == kDNSServiceErr_NoError)
-             domainsent = 1;
-         }
-        }
+          /*
+           * If it hasn't resolved within 5 seconds set the offline-report
+           * printer-state-reason...
+           */
 
-       if (DNSServiceProcessResult(ref) == kDNSServiceErr_NoError)
-         uri = resolved_uri;
+           if (logit && offline == 0 && time(NULL) > (start_time + 5))
+           {
+             fputs("STATE: +offline-report\n", stderr);
+             offline = 1;
+           }
+         }
+         else
+         {
+           if (DNSServiceProcessResult(ref) == kDNSServiceErr_NoError)
+           {
+             uri = resolved_uri;
+             break;
+           }
+         }
+       }
 
        if (domainsent)
          DNSServiceRefDeallocate(domainref);
@@ -1463,9 +1551,9 @@ _httpResolveURI(
       if (uri)
         fprintf(stderr, "DEBUG: Resolved as \"%s\"...\n", uri);
       else
-        fputs("DEBUG: Unable to resolve URI!\n", stderr);
+        fputs("DEBUG: Unable to resolve URI\n", stderr);
 
-      fputs("STATE: -connecting-to-device\n", stderr);
+      fputs("STATE: -connecting-to-device,offline-report\n", stderr);
     }
 
 #else
@@ -1477,7 +1565,7 @@ _httpResolveURI(
 #endif /* HAVE_DNSSD */
 
     if (logit && !uri)
-      _cupsLangPuts(stderr, _("Unable to find printer!\n"));
+      _cupsLangPrintFilter(stderr, "ERROR", _("Unable to find printer."));
   }
 
   DEBUG_printf(("5_httpResolveURI: Returning \"%s\"", uri));
@@ -1608,7 +1696,7 @@ http_copy_encode(char       *dst, /* O - Destination buffer */
  * 'resolve_callback()' - Build a device URI for the given service name.
  */
 
-static void
+static void DNSSD_API
 resolve_callback(
     DNSServiceRef       sdRef,         /* I - Service reference */
     DNSServiceFlags     flags,         /* I - Results flags */