/*
- * "$Id: http-support.c 5138 2006-02-21 10:49:06Z mike $"
+ * "$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 1997-2006 by Easy Software Products, all rights reserved.
+ * 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
- * property of Easy Software Products and are protected by Federal
- * copyright law. Distribution and use rights are outlined in the file
- * "LICENSE.txt" which should have been included with this file. If this
- * file is missing or damaged please contact Easy Software Products
- * at:
- *
- * Attn: CUPS Licensing Information
- * Easy Software Products
- * 44141 Airport View Drive, Suite 204
- * Hollywood, Maryland 20636 USA
- *
- * Voice: (301) 373-9600
- * EMail: cups-info@cups.org
- * WWW: http://www.cups.org
+ * property of Apple Inc. and are protected by Federal copyright
+ * law. Distribution and use rights are outlined in the file "LICENSE.txt"
+ * which should have been included with this file. If this file is
+ * file is missing or damaged, see the license at "http://www.cups.org/".
*
* This file is subject to the Apple OS-Developed Software exception.
*
* 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.
* http_copy_encode() - Copy and encode a URI.
+ * resolve_callback() - Build a device URI for the given service name.
*/
/*
* Include necessary headers...
*/
-#include "debug.h"
-#include "globals.h"
-#include <stdlib.h>
+#include "cups-private.h"
+#ifdef HAVE_DNSSD
+# include <dns_sd.h>
+# ifdef WIN32
+# include <io.h>
+# elif defined(HAVE_POLL)
+# include <poll.h>
+# else
+# include <sys/select.h>
+# endif /* WIN32 */
+#endif /* HAVE_DNSSD */
+
+
+/*
+ * Local types...
+ */
+
+typedef struct _http_uribuf_s /* URI buffer */
+{
+ char *buffer; /* Pointer to buffer */
+ size_t bufsize; /* Size of buffer */
+} _http_uribuf_t;
/*
static const char * const http_days[7] =
{
- "Sun", "Mon",
+ "Sun",
+ "Mon",
"Tue",
"Wed",
"Thu",
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 DNSSD_API resolve_callback(DNSServiceRef sdRef,
+ DNSServiceFlags flags,
+ uint32_t interfaceIndex,
+ DNSServiceErrorType errorCode,
+ const char *fullName,
+ const char *hostTarget,
+ uint16_t port, uint16_t txtLen,
+ const unsigned char *txtRecord,
+ void *context);
+#endif /* HAVE_DNSSD */
/*
* place of traditional string functions whenever you need to create a
* URI string.
*
- * @since CUPS 1.2@
+ * @since CUPS 1.2/Mac OS X 10.5@
*/
http_uri_status_t /* O - URI status */
if (!ptr)
goto assemble_overflow;
- if (!strcmp(scheme, "mailto:"))
+ if (!strcmp(scheme, "mailto"))
{
/*
* mailto: only has :, no //...
/*
* Then add the hostname. Since IPv6 is a particular pain to deal
- * with, we have several special cases to deal with... If we get
+ * with, we have several special cases to deal with. If we get
* an IPv6 address with brackets around it, assume it is already in
- * URI format...
+ * URI format. Since DNS-SD service names can sometimes look like
+ * raw IPv6 addresses, we specifically look for "._tcp" in the name,
+ * too...
*/
- if (host[0] != '[' && strchr(host, ':'))
+ if (host[0] != '[' && strchr(host, ':') && !strstr(host, "._tcp"))
{
/*
- * We have an IPv6 address...
+ * We have a raw IPv6 address...
*/
if (strchr(host, '%'))
* Otherwise, just copy the host string...
*/
- ptr = http_copy_encode(ptr, host, end, NULL, NULL,
+ ptr = http_copy_encode(ptr, host, end, ":/?#[]@\\\"", NULL,
encoding & HTTP_URI_CODING_HOSTNAME);
if (!ptr)
* this function in place of traditional string functions whenever
* you need to create a URI string.
*
- * @since CUPS 1.2@
+ * @since CUPS 1.2/Mac OS X 10.5@
*/
http_uri_status_t /* O - URI status */
/*
* 'httpDecode64_2()' - Base64-decode a string.
*
- * @since CUPS 1.1.21@
+ * @since CUPS 1.1.21/Mac OS X 10.4@
*/
char * /* O - Decoded string */
httpEncode64(char *out, /* I - String to write to */
const char *in) /* I - String to read from */
{
- return (httpEncode64_2(out, 512, in, strlen(in)));
+ return (httpEncode64_2(out, 512, in, (int)strlen(in)));
}
/*
* 'httpEncode64_2()' - Base64-encode a string.
*
- * @since CUPS 1.1.21@
+ * @since CUPS 1.1.21/Mac OS X 10.4@
*/
char * /* O - Encoded string */
if (outptr < outend)
*outptr ++ = base64[(in[0] & 255) >> 2];
+
if (outptr < outend)
- *outptr ++ = base64[(((in[0] & 255) << 4) | ((in[1] & 255) >> 4)) & 63];
+ {
+ if (inlen > 1)
+ *outptr ++ = base64[(((in[0] & 255) << 4) | ((in[1] & 255) >> 4)) & 63];
+ else
+ *outptr ++ = base64[((in[0] & 255) << 4) & 63];
+ }
in ++;
inlen --;
}
if (outptr < outend)
- *outptr ++ = base64[(((in[0] & 255) << 2) | ((in[1] & 255) >> 6)) & 63];
+ {
+ if (inlen > 1)
+ *outptr ++ = base64[(((in[0] & 255) << 2) | ((in[1] & 255) >> 6)) & 63];
+ else
+ *outptr ++ = base64[((in[0] & 255) << 2) & 63];
+ }
in ++;
inlen --;
/*
* 'httpGetDateString2()' - Get a formatted date/time string from a time value.
*
- * @since CUPS 1.2@
+ * @since CUPS 1.2/Mac OS X 10.5@
*/
const char * /* O - Date/time string */
{ 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 };
- DEBUG_printf(("httpGetDateTime(s=\"%s\")\n", s));
+ DEBUG_printf(("2httpGetDateTime(s=\"%s\")", s));
/*
* Extract the date and time from the formatted string...
if (sscanf(s, "%*s%d%15s%d%d:%d:%d", &day, mon, &year, &hour, &min, &sec) < 6)
return (0);
- DEBUG_printf((" day=%d, mon=\"%s\", year=%d, hour=%d, min=%d, sec=%d\n",
- day, mon, year, hour, min, sec));
+ DEBUG_printf(("4httpGetDateTime: day=%d, mon=\"%s\", year=%d, hour=%d, "
+ "min=%d, sec=%d", day, mon, year, hour, min, sec));
/*
* Convert the month name to a number from 0 to 11.
if (i >= 12)
return (0);
- DEBUG_printf((" i=%d\n", i));
+ DEBUG_printf(("4httpGetDateTime: i=%d", i));
/*
* Now convert the date and time to a UNIX time value in seconds since
else
days = normal_days[i] + day - 1;
- DEBUG_printf((" days=%d\n", days));
+ DEBUG_printf(("4httpGetDateTime: days=%d", days));
days += (year - 1970) * 365 + /* 365 days per year (normally) */
((year - 1) / 4 - 492) - /* + leap days */
((year - 1) / 100 - 19) + /* - 100 year days */
((year - 1) / 400 - 4); /* + 400 year days */
- DEBUG_printf((" days=%d\n", days));
+ DEBUG_printf(("4httpGetDateTime: days=%d\n", days));
return (days * 86400 + hour * 3600 + min * 60 + sec);
}
*
* This function is deprecated; use the httpSeparateURI() function instead.
*
- * @since CUPS 1.1.21@
+ * @since CUPS 1.1.21/Mac OS X 10.4@
* @deprecated@
*/
* 'httpSeparateURI()' - Separate a Universal Resource Identifier into its
* components.
*
- * @since CUPS 1.2@
+ * @since CUPS 1.2/Mac OS X 10.5@
*/
http_uri_status_t /* O - Result of separation */
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;
*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;
else
{
/*
- * Grab hostname or IPv4 address...
+ * Validate the hostname or IPv4 address first...
+ */
+
+ for (ptr = (char *)uri; *ptr; ptr ++)
+ if (strchr(":?/", *ptr))
+ break;
+ else if (!strchr("abcdefghijklmnopqrstuvwxyz"
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "0123456789"
+ "-._~"
+ "%"
+ "!$&'()*+,;=\\", *ptr))
+ {
+ *host = '\0';
+ return (HTTP_URI_BAD_HOSTNAME);
+ }
+
+ /*
+ * Then copy the hostname or IPv4 address to the buffer...
*/
uri = http_copy_decode(host, uri, hostlen, ":?/",
*host = '\0';
return (HTTP_URI_BAD_HOSTNAME);
}
-
- /*
- * Validate value...
- */
-
- for (ptr = host; *ptr; ptr ++)
- if (!strchr("abcdefghijklmnopqrstuvwxyz"
- "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
- "0123456789"
- "-._~"
- "!$&'()*+,;=", *ptr))
- {
- *host = '\0';
- return (HTTP_URI_BAD_HOSTNAME);
- }
}
/*
* Yes, collect the port number...
*/
+ if (!isdigit(uri[1] & 255))
+ {
+ *port = 0;
+ return (HTTP_URI_BAD_PORT);
+ }
+
*port = strtol(uri + 1, (char **)&uri, 10);
- if (*uri != '/')
+ if (*uri != '/' && *uri)
{
*port = 0;
return (HTTP_URI_BAD_PORT);
char *resptr = resource + strlen(resource);
- uri = http_copy_decode(resptr, uri, resourcelen - (resptr - resource),
+ uri = http_copy_decode(resptr, uri, resourcelen - (int)(resptr - resource),
NULL, decoding & HTTP_URI_CODING_QUERY);
}
}
/*
* 'httpStatus()' - Return a short string describing a HTTP status code.
+ *
+ * The returned string is localized to the current POSIX locale and is based
+ * on the status strings defined in RFC 2616.
*/
-const char * /* O - String or NULL */
+const char * /* O - Localized status string */
httpStatus(http_status_t status) /* I - HTTP status code */
{
+ const char *s; /* Status string */
+ _cups_globals_t *cg = _cupsGlobals(); /* Global data */
+
+
+ if (!cg->lang_default)
+ cg->lang_default = cupsLangDefault();
+
switch (status)
{
case HTTP_CONTINUE :
- return ("Continue");
+ s = _("Continue");
+ break;
case HTTP_SWITCHING_PROTOCOLS :
- return ("Switching Protocols");
+ s = _("Switching Protocols");
+ break;
case HTTP_OK :
- return ("OK");
+ s = _("OK");
+ break;
case HTTP_CREATED :
- return ("Created");
+ s = _("Created");
+ break;
case HTTP_ACCEPTED :
- return ("Accepted");
+ s = _("Accepted");
+ break;
case HTTP_NO_CONTENT :
- return ("No Content");
+ s = _("No Content");
+ break;
+ case HTTP_MOVED_PERMANENTLY :
+ s = _("Moved Permanently");
+ break;
+ case HTTP_SEE_OTHER :
+ s = _("See Other");
+ break;
case HTTP_NOT_MODIFIED :
- return ("Not Modified");
+ s = _("Not Modified");
+ break;
case HTTP_BAD_REQUEST :
- return ("Bad Request");
+ s = _("Bad Request");
+ break;
case HTTP_UNAUTHORIZED :
- return ("Unauthorized");
+ case HTTP_AUTHORIZATION_CANCELED :
+ s = _("Unauthorized");
+ break;
case HTTP_FORBIDDEN :
- return ("Forbidden");
+ s = _("Forbidden");
+ break;
case HTTP_NOT_FOUND :
- return ("Not Found");
+ s = _("Not Found");
+ break;
case HTTP_REQUEST_TOO_LARGE :
- return ("Request Entity Too Large");
+ s = _("Request Entity Too Large");
+ break;
case HTTP_URI_TOO_LONG :
- return ("URI Too Long");
+ s = _("URI Too Long");
+ break;
case HTTP_UPGRADE_REQUIRED :
- return ("Upgrade Required");
+ s = _("Upgrade Required");
+ break;
case HTTP_NOT_IMPLEMENTED :
- return ("Not Implemented");
+ s = _("Not Implemented");
+ break;
case HTTP_NOT_SUPPORTED :
- return ("Not Supported");
+ s = _("Not Supported");
+ break;
+ case HTTP_EXPECTATION_FAILED :
+ s = _("Expectation Failed");
+ break;
+ case HTTP_SERVICE_UNAVAILABLE :
+ s = _("Service Unavailable");
+ break;
+ 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 :
- return ("Unknown");
+ s = _("Unknown");
+ break;
}
+
+ return (_cupsLangString(cg->lang_default, s));
}
#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.
+ */
+
+char * /* O - Encoded URI */
+_httpEncodeURI(char *dst, /* I - Destination buffer */
+ const char *src, /* I - Source URI */
+ size_t dstsize) /* I - Size of destination buffer */
+{
+ http_copy_encode(dst, src, dst + dstsize - 1, NULL, NULL, 1);
+ return (dst);
+}
+
+
+/*
+ * '_httpResolveURI()' - Resolve a DNS-SD URI.
+ */
+
+const char * /* O - Resolved URI */
+_httpResolveURI(
+ const char *uri, /* I - DNS-SD URI */
+ char *resolved_uri, /* I - Buffer for resolved URI */
+ size_t resolved_size, /* I - Size of URI buffer */
+ int logit) /* I - Log progress to stderr? */
+{
+ char scheme[32], /* URI components... */
+ userpass[256],
+ hostname[1024],
+ resource[1024];
+ int port;
+#ifdef DEBUG
+ http_uri_status_t status; /* URI decode status */
+#endif /* DEBUG */
+
+
+ DEBUG_printf(("4_httpResolveURI(uri=\"%s\", resolved_uri=%p, "
+ "resolved_size=" CUPS_LLFMT ")", uri, resolved_uri,
+ CUPS_LLCAST resolved_size));
+
+ /*
+ * Get the device URI...
+ */
+
+#ifdef DEBUG
+ if ((status = httpSeparateURI(HTTP_URI_CODING_ALL, uri, scheme,
+ sizeof(scheme), userpass, sizeof(userpass),
+ hostname, sizeof(hostname), &port, resource,
+ sizeof(resource))) < HTTP_URI_OK)
+#else
+ if (httpSeparateURI(HTTP_URI_CODING_ALL, uri, scheme,
+ sizeof(scheme), userpass, sizeof(userpass),
+ hostname, sizeof(hostname), &port, resource,
+ sizeof(resource)) < HTTP_URI_OK)
+#endif /* DEBUG */
+ {
+ if (logit)
+ _cupsLangPrintFilter(stderr, "ERROR", _("Bad device-uri \"%s\"."), uri);
+
+ DEBUG_printf(("6_httpResolveURI: httpSeparateURI returned %d!", status));
+ DEBUG_puts("5_httpResolveURI: Returning NULL");
+ return (NULL);
+ }
+
+ /*
+ * Resolve it as needed...
+ */
+
+ 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? */
+ 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);
+
+ /*
+ * Separate the hostname into service name, registration type, and domain...
+ */
+
+ for (regtype = strstr(hostname, "._tcp") - 2;
+ regtype > hostname;
+ regtype --)
+ if (regtype[0] == '.' && regtype[1] == '_')
+ {
+ /*
+ * Found ._servicetype in front of ._tcp...
+ */
+
+ *regtype++ = '\0';
+ break;
+ }
+
+ if (regtype <= hostname)
+ {
+ DEBUG_puts("5_httpResolveURI: Bad hostname, returning NULL");
+ return (NULL);
+ }
+
+ for (domain = strchr(regtype, '.');
+ domain;
+ domain = strchr(domain + 1, '.'))
+ if (domain[1] != '_')
+ break;
+
+ if (domain)
+ *domain++ = '\0';
+
+ uribuf.buffer = resolved_uri;
+ uribuf.bufsize = resolved_size;
+
+ resolved_uri[0] = '\0';
+
+ DEBUG_printf(("6_httpResolveURI: Resolving hostname=\"%s\", regtype=\"%s\", "
+ "domain=\"%s\"\n", hostname, regtype, domain));
+ if (logit)
+ {
+ fputs("STATE: +connecting-to-device\n", stderr);
+ fprintf(stderr, "DEBUG: Resolving \"%s\", regtype=\"%s\", "
+ "domain=\"local.\"...\n", hostname, regtype);
+ }
+
+ uri = NULL;
+
+ if (DNSServiceCreateConnection(&ref) == kDNSServiceErr_NoError)
+ {
+ localref = ref;
+ if (DNSServiceResolve(&localref, kDNSServiceFlagsShareConnection, 0,
+ hostname, regtype, "local.", resolve_callback,
+ &uribuf) == kDNSServiceErr_NoError)
+ {
+ 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."));
+
+ /*
+ * 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;
+
+ 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)
+ {
+ /*
+ * Wait 2 seconds for a response to the local resolve; if nothing
+ * comes in, do an additional domain resolution...
+ */
+
+ 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;
+ }
+
+ /*
+ * If it hasn't resolved within 5 seconds set the offline-report
+ * printer-state-reason...
+ */
+
+ 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);
+
+ DNSServiceRefDeallocate(localref);
+ }
+
+ DNSServiceRefDeallocate(ref);
+ }
+
+ if (logit)
+ {
+ if (uri)
+ fprintf(stderr, "DEBUG: Resolved as \"%s\"...\n", uri);
+ else
+ fputs("DEBUG: Unable to resolve URI\n", stderr);
+
+ fputs("STATE: -connecting-to-device,offline-report\n", stderr);
+ }
+
+#else
+ /*
+ * No DNS-SD support...
+ */
+
+ uri = NULL;
+#endif /* HAVE_DNSSD */
+
+ if (logit && !uri)
+ _cupsLangPrintFilter(stderr, "ERROR", _("Unable to find printer."));
+ }
+
+ DEBUG_printf(("5_httpResolveURI: Returning \"%s\"", uri));
+
+ return (uri);
+}
+
+
/*
* 'http_copy_decode()' - Copy and decode a URI.
*/
const char *term, /* I - Terminating characters */
int encode) /* I - %-encode reserved chars? */
{
- static const char *hex = "0123456789ABCDEF";
+ static const char hex[] = "0123456789ABCDEF";
while (*src && dst < dstend)
*dst++ = *src++;
}
+ *dst = '\0';
+
if (*src)
return (NULL);
else
}
+#ifdef HAVE_DNSSD
+/*
+ * 'resolve_callback()' - Build a device URI for the given service name.
+ */
+
+static void DNSSD_API
+resolve_callback(
+ DNSServiceRef sdRef, /* I - Service reference */
+ DNSServiceFlags flags, /* I - Results flags */
+ uint32_t interfaceIndex, /* I - Interface number */
+ DNSServiceErrorType errorCode, /* I - Error, if any */
+ const char *fullName, /* I - Full service name */
+ const char *hostTarget, /* I - Hostname */
+ uint16_t port, /* I - Port number */
+ uint16_t txtLen, /* I - Length of TXT record */
+ const unsigned char *txtRecord, /* I - TXT record data */
+ void *context) /* I - Pointer to URI buffer */
+{
+ const char *scheme; /* URI scheme */
+ char rp[257]; /* Remote printer */
+ const void *value; /* Value from TXT record */
+ uint8_t valueLen; /* Length of value */
+ _http_uribuf_t *uribuf; /* URI buffer */
+
+
+ DEBUG_printf(("7resolve_callback(sdRef=%p, flags=%x, interfaceIndex=%u, "
+ "errorCode=%d, fullName=\"%s\", hostTarget=\"%s\", port=%u, "
+ "txtLen=%u, txtRecord=%p, context=%p)", sdRef, flags,
+ interfaceIndex, errorCode, fullName, hostTarget, port, txtLen,
+ txtRecord, context));
+
+ /*
+ * Figure out the scheme from the full name...
+ */
+
+ if (strstr(fullName, "._ipp") || strstr(fullName, "._fax-ipp"))
+ scheme = "ipp";
+ else if (strstr(fullName, "._printer."))
+ scheme = "lpd";
+ else if (strstr(fullName, "._pdl-datastream."))
+ scheme = "socket";
+ else
+ scheme = "riousbprint";
+
+ /*
+ * Extract the "remote printer" key from the TXT record...
+ */
+
+ if ((value = TXTRecordGetValuePtr(txtLen, txtRecord, "rp",
+ &valueLen)) != NULL)
+ {
+ /*
+ * Convert to resource by concatenating with a leading "/"...
+ */
+
+ rp[0] = '/';
+ memcpy(rp + 1, value, valueLen);
+ rp[valueLen + 1] = '\0';
+ }
+ else
+ rp[0] = '\0';
+
+ /*
+ * Assemble the final device URI...
+ */
+
+ uribuf = (_http_uribuf_t *)context;
+
+ httpAssembleURI(HTTP_URI_CODING_ALL, uribuf->buffer, uribuf->bufsize, scheme,
+ NULL, hostTarget, ntohs(port), rp);
+
+ DEBUG_printf(("8resolve_callback: Resolved URI is \"%s\"...",
+ uribuf->buffer));
+}
+#endif /* HAVE_DNSSD */
+
+
/*
- * End of "$Id: http-support.c 5138 2006-02-21 10:49:06Z mike $".
+ * End of "$Id: http-support.c 7952 2008-09-17 00:56:20Z mike $".
*/