diff options
Diffstat (limited to 'cups')
-rw-r--r-- | cups/cups.h | 2 | ||||
-rw-r--r-- | cups/debug.h | 12 | ||||
-rw-r--r-- | cups/dest.c | 263 | ||||
-rw-r--r-- | cups/globals.h | 1 | ||||
-rw-r--r-- | cups/http-private.h | 1 | ||||
-rw-r--r-- | cups/http-support.c | 80 | ||||
-rw-r--r-- | cups/http.c | 211 | ||||
-rw-r--r-- | cups/libcups.exp | 2 | ||||
-rw-r--r-- | cups/request.c | 22 | ||||
-rw-r--r-- | cups/testhttp.c | 2 | ||||
-rw-r--r-- | cups/util.c | 12 |
11 files changed, 347 insertions, 261 deletions
diff --git a/cups/cups.h b/cups/cups.h index 8742cf29d..8836aab94 100644 --- a/cups/cups.h +++ b/cups/cups.h @@ -288,8 +288,8 @@ extern int cupsGetConflicts(ppd_file_t *ppd, const char *option, cups_option_t **options) _CUPS_API_1_4; extern ipp_status_t cupsGetDevices(http_t *http, int timeout, - const char *exclude_schemes, const char *include_schemes, + const char *exclude_schemes, cups_device_cb_t callback, void *user_data) _CUPS_API_1_4; extern cups_dest_t *cupsGetNamedDest(http_t *http, const char *name, diff --git a/cups/debug.h b/cups/debug.h index 4efd1619c..0d81b46cb 100644 --- a/cups/debug.h +++ b/cups/debug.h @@ -19,6 +19,15 @@ # define _CUPS_DEBUG_H_ /* + * C++ magic... + */ + +# ifdef __cplusplus +extern "C" { +# endif /* __cplusplus */ + + +/* * The debug macros are used if you compile with DEBUG defined. * * Usage: @@ -50,6 +59,9 @@ __attribute__ ((__format__ (__printf__, 1, 2))) ; extern void _cups_debug_puts(const char *s); +# ifdef __cplusplus +} +# endif /* __cplusplus */ #endif /* !_CUPS_DEBUG_H_ */ diff --git a/cups/dest.c b/cups/dest.c index 9417bddc1..2886a0478 100644 --- a/cups/dest.c +++ b/cups/dest.c @@ -83,7 +83,6 @@ #ifdef __APPLE__ static CFArrayRef appleCopyLocations(void); static CFStringRef appleCopyNetwork(void); -static char *appleGetDefault(char *name, int namesize); static char *appleGetPaperSize(char *name, int namesize); static CFStringRef appleGetPrinter(CFArrayRef locations, CFStringRef network, CFIndex *locindex); @@ -99,8 +98,8 @@ static int cups_find_dest(const char *name, const char *instance, static char *cups_get_default(const char *filename, char *namebuf, size_t namesize, const char **instance); static int cups_get_dests(const char *filename, const char *match_name, - const char *match_inst, int num_dests, - cups_dest_t **dests); + const char *match_inst, int user_default_set, + int num_dests, cups_dest_t **dests); static int cups_get_sdests(http_t *http, ipp_op_t op, const char *name, int num_dests, cups_dest_t **dests); static char *cups_make_string(ipp_attribute_t *attr, char *buffer, @@ -302,7 +301,8 @@ cupsGetDests2(http_t *http, /* I - Connection to server or @code CUPS_HTTP_ char filename[1024]; /* Local ~/.cups/lpoptions file */ const char *defprinter; /* Default printer */ char name[1024], /* Copy of printer name */ - *instance; /* Pointer to instance name */ + *instance, /* Pointer to instance name */ + *user_default; /* User default printer */ int num_reals; /* Number of real queues */ cups_dest_t *reals; /* Real queues */ _cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */ @@ -362,22 +362,20 @@ cupsGetDests2(http_t *http, /* I - Connection to server or @code CUPS_HTTP_ * Grab the default destination... */ -#ifdef __APPLE__ - if ((defprinter = appleGetDefault(name, sizeof(name))) == NULL) -#endif /* __APPLE__ */ - defprinter = cupsGetDefault2(http); + if ((user_default = _cupsUserDefault(name, sizeof(name))) != NULL) + defprinter = name; + else if ((defprinter = cupsGetDefault2(http)) != NULL) + { + strlcpy(name, defprinter, sizeof(name)); + defprinter = name; + } if (defprinter) { /* - * Grab printer and instance name... + * Separate printer and instance name... */ -#ifdef __APPLE__ - if (name != defprinter) -#endif /* __APPLE__ */ - strlcpy(name, defprinter, sizeof(name)); - if ((instance = strchr(name, '/')) != NULL) *instance++ = '\0'; @@ -389,21 +387,15 @@ cupsGetDests2(http_t *http, /* I - Connection to server or @code CUPS_HTTP_ dest->is_default = 1; } else - { - /* - * This initialization of "instance" is unnecessary, but avoids a - * compiler warning... - */ - instance = NULL; - } /* * Load the /etc/cups/lpoptions and ~/.cups/lpoptions files... */ snprintf(filename, sizeof(filename), "%s/lpoptions", cg->cups_serverroot); - num_dests = cups_get_dests(filename, NULL, NULL, num_dests, dests); + num_dests = cups_get_dests(filename, NULL, NULL, user_default != NULL, + num_dests, dests); if ((home = getenv("HOME")) != NULL) { @@ -411,7 +403,8 @@ cupsGetDests2(http_t *http, /* I - Connection to server or @code CUPS_HTTP_ if (access(filename, 0)) snprintf(filename, sizeof(filename), "%s/.lpoptions", home); - num_dests = cups_get_dests(filename, NULL, NULL, num_dests, dests); + num_dests = cups_get_dests(filename, NULL, NULL, user_default != NULL, + num_dests, dests); } /* @@ -497,6 +490,7 @@ cupsGetNamedDest(http_t *http, /* I - Connection to server or @code CUPS_HTT char filename[1024], /* Path to lpoptions */ defname[256]; /* Default printer name */ const char *home = getenv("HOME"); /* Home directory */ + int set_as_default = 0; /* Set returned destination as default */ ipp_op_t op = IPP_GET_PRINTER_ATTRIBUTES; /* IPP operation to get server ops */ _cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */ @@ -508,9 +502,8 @@ cupsGetNamedDest(http_t *http, /* I - Connection to server or @code CUPS_HTT if (!name) { - if ((name = getenv("LPDEST")) == NULL) - if ((name = getenv("PRINTER")) != NULL && !strcmp(name, "lp")) - name = NULL; + set_as_default = 1; + name = _cupsUserDefault(defname, sizeof(defname)); if (!name && home) { @@ -571,12 +564,15 @@ cupsGetNamedDest(http_t *http, /* I - Connection to server or @code CUPS_HTT if (instance) dest->instance = _cupsStrAlloc(instance); + if (set_as_default) + dest->is_default = 1; + /* * Then add local options... */ snprintf(filename, sizeof(filename), "%s/lpoptions", cg->cups_serverroot); - cups_get_dests(filename, name, instance, 1, &dest); + cups_get_dests(filename, name, instance, 1, 1, &dest); if (home) { @@ -585,7 +581,7 @@ cupsGetNamedDest(http_t *http, /* I - Connection to server or @code CUPS_HTT if (access(filename, 0)) snprintf(filename, sizeof(filename), "%s/.lpoptions", home); - cups_get_dests(filename, name, instance, 1, &dest); + cups_get_dests(filename, name, instance, 1, 1, &dest); } /* @@ -762,7 +758,7 @@ cupsSetDests2(http_t *http, /* I - Connection to server or @code CUPS_HTTP_ * Merge in server defaults... */ - num_temps = cups_get_dests(filename, NULL, NULL, num_temps, &temps); + num_temps = cups_get_dests(filename, NULL, NULL, 0, num_temps, &temps); /* * Point to user defaults... @@ -938,6 +934,106 @@ cupsSetDests2(http_t *http, /* I - Connection to server or @code CUPS_HTTP_ } +/* + * '_cupsUserDefault()' - Get the user default printer from environment + * variables and location information. + */ + +char * /* O - Default printer or NULL */ +_cupsUserDefault(char *name, /* I - Name buffer */ + size_t namesize) /* I - Size of name buffer */ +{ + const char *env; /* LPDEST or PRINTER env variable */ +#ifdef __APPLE__ + CFStringRef network; /* Network location */ + CFArrayRef locations; /* Location array */ + CFStringRef locprinter; /* Current printer */ +#endif /* __APPLE__ */ + + + if ((env = getenv("LPDEST")) == NULL) + if ((env = getenv("PRINTER")) != NULL && !strcmp(env, "lp")) + env = NULL; + + if (env) + { + strlcpy(name, env, namesize); + return (name); + } + +#ifdef __APPLE__ + /* + * Use location-based defaults if "use last printer" is selected in the + * system preferences... + */ + + if (!appleUseLastPrinter()) + { + DEBUG_puts("_cupsUserDefault: Not using last printer as default..."); + name[0] = '\0'; + return (NULL); + } + + /* + * Get the current location... + */ + + if ((network = appleCopyNetwork()) == NULL) + { + DEBUG_puts("_cupsUserDefault: Unable to get current network..."); + name[0] = '\0'; + return (NULL); + } + +# ifdef DEBUG + CFStringGetCString(network, name, namesize, kCFStringEncodingUTF8); + DEBUG_printf(("_cupsUserDefault: network=\"%s\"\n", name)); +# endif /* DEBUG */ + + /* + * Lookup the network in the preferences... + */ + + if ((locations = appleCopyLocations()) == NULL) + { + /* + * Missing or bad location array, so no location-based default... + */ + + DEBUG_puts("_cupsUserDefault: Missing or bad location history array..."); + + CFRelease(network); + + name[0] = '\0'; + return (NULL); + } + + DEBUG_printf(("_cupsUserDefault: Got location, %d entries...\n", + (int)CFArrayGetCount(locations))); + + if ((locprinter = appleGetPrinter(locations, network, NULL)) != NULL) + CFStringGetCString(locprinter, name, namesize, kCFStringEncodingUTF8); + else + name[0] = '\0'; + + CFRelease(network); + CFRelease(locations); + + DEBUG_printf(("_cupsUserDefault: Returning \"%s\"...\n", name)); + + return (*name ? name : NULL); + +#else + /* + * No location-based defaults on this platform... + */ + + name[0] = '\0'; + return (NULL); +#endif /* __APPLE__ */ +} + + #ifdef __APPLE__ /* * 'appleCopyLocations()' - Copy the location history array. @@ -1006,79 +1102,6 @@ appleCopyNetwork(void) /* - * 'appleGetDefault()' - Get the default printer for this location. - */ - -static char * /* O - Name or NULL if no default */ -appleGetDefault(char *name, /* I - Name buffer */ - int namesize) /* I - Size of name buffer */ -{ - CFStringRef network; /* Network location */ - CFArrayRef locations; /* Location array */ - CFStringRef locprinter; /* Current printer */ - - - /* - * Use location-based defaults if "use last printer" is selected in the - * system preferences... - */ - - if (!appleUseLastPrinter()) - { - DEBUG_puts("appleGetDefault: Not using last printer as default..."); - return (NULL); - } - - /* - * Get the current location... - */ - - if ((network = appleCopyNetwork()) == NULL) - { - DEBUG_puts("appleGetDefault: Unable to get current network..."); - return (NULL); - } - -#ifdef DEBUG - CFStringGetCString(network, name, namesize, kCFStringEncodingUTF8); - DEBUG_printf(("appleGetDefault: network=\"%s\"\n", name)); -#endif /* DEBUG */ - - /* - * Lookup the network in the preferences... - */ - - if ((locations = appleCopyLocations()) == NULL) - { - /* - * Missing or bad location array, so no location-based default... - */ - - DEBUG_puts("appleGetDefault: Missing or bad location history array..."); - - CFRelease(network); - - return (NULL); - } - - DEBUG_printf(("appleGetDefault: Got location, %d entries...\n", - (int)CFArrayGetCount(locations))); - - if ((locprinter = appleGetPrinter(locations, network, NULL)) != NULL) - CFStringGetCString(locprinter, name, namesize, kCFStringEncodingUTF8); - else - name[0] = '\0'; - - CFRelease(network); - CFRelease(locations); - - DEBUG_printf(("appleGetDefault: Returning \"%s\"...\n", name)); - - return (*name ? name : NULL); -} - - -/* * 'appleGetPaperSize()' - Get the default paper size. */ @@ -1237,6 +1260,7 @@ appleSetDefault(const char *name) /* I - Default printer/class name */ CFPreferencesSetAppValue(kLocationHistoryArrayKey, newlocations, kPMPrintingPreferences); CFPreferencesAppSynchronize(kPMPrintingPreferences); + notify_post("com.apple.printerPrefsChange"); } if (newlocations) @@ -1526,11 +1550,13 @@ cups_get_default(const char *filename, /* I - File to read */ */ static int /* O - Number of destinations */ -cups_get_dests(const char *filename, /* I - File to read from */ - const char *match_name, /* I - Destination name we want */ - const char *match_inst, /* I - Instance name we want */ - int num_dests, /* I - Number of destinations */ - cups_dest_t **dests) /* IO - Destinations */ +cups_get_dests( + const char *filename, /* I - File to read from */ + const char *match_name, /* I - Destination name we want */ + const char *match_inst, /* I - Instance name we want */ + int user_default_set, /* I - User default printer set? */ + int num_dests, /* I - Number of destinations */ + cups_dest_t **dests) /* IO - Destinations */ { int i; /* Looping var */ cups_dest_t *dest; /* Current destination */ @@ -1540,13 +1566,12 @@ cups_get_dests(const char *filename, /* I - File to read from */ *name, /* Name of destination/option */ *instance; /* Instance of destination */ int linenum; /* Current line number */ - const char *printer; /* PRINTER or LPDEST */ DEBUG_printf(("cups_get_dests(filename=\"%s\", match_name=\"%s\", " - "match_inst=\"%s\", num_dests=%d, dests=%p)\n", filename, - match_name ? match_name : "(null)", - match_inst ? match_inst : "(null)", num_dests, dests)); + "match_inst=\"%s\", user_default_set=%d, num_dests=%d, " + "dests=%p)\n", filename, match_name, match_inst, + user_default_set, num_dests, dests)); /* * Try to open the file... @@ -1556,18 +1581,6 @@ cups_get_dests(const char *filename, /* I - File to read from */ return (num_dests); /* - * Check environment variables... - */ - - if ((printer = getenv("LPDEST")) == NULL) - if ((printer = getenv("PRINTER")) != NULL) - if (strcmp(printer, "lp") == 0) - printer = NULL; - - DEBUG_printf(("cups_get_dests: printer=\"%s\"\n", - printer ? printer : "(null)")); - - /* * Read each printer; each line looks like: * * Dest name[/instance] options @@ -1583,7 +1596,7 @@ cups_get_dests(const char *filename, /* I - File to read from */ */ DEBUG_printf(("cups_get_dests: linenum=%d line=\"%s\" lineptr=\"%s\"\n", - linenum, line, lineptr ? lineptr : "(null)")); + linenum, line, lineptr)); if ((strcasecmp(line, "dest") && strcasecmp(line, "default")) || !lineptr) { @@ -1682,7 +1695,7 @@ cups_get_dests(const char *filename, /* I - File to read from */ * Set this as default if needed... */ - if (!printer && !strcasecmp(line, "default")) + if (!user_default_set && !strcasecmp(line, "default")) { DEBUG_puts("cups_get_dests: Setting as default..."); diff --git a/cups/globals.h b/cups/globals.h index 9a0a99842..cdf4d1fec 100644 --- a/cups/globals.h +++ b/cups/globals.h @@ -145,6 +145,7 @@ extern _cups_globals_t *_cupsGlobals(void); extern void _cupsSetError(ipp_status_t status, const char *message, int localize); extern void _cupsSetHTTPError(http_status_t status); +extern char *_cupsUserDefault(char *name, size_t namesize); /* diff --git a/cups/http-private.h b/cups/http-private.h index 8ffe5a281..9362e36d7 100644 --- a/cups/http-private.h +++ b/cups/http-private.h @@ -268,6 +268,7 @@ extern char *_httpEncodeURI(char *dst, const char *src, size_t dstsize); extern const char *_httpResolveURI(const char *uri, char *resolved_uri, size_t resolved_size, int log); +extern int _httpWait(http_t *http, int msec, int usessl); #endif /* !_CUPS_HTTP_PRIVATE_H_ */ /* diff --git a/cups/http-support.c b/cups/http-support.c index 342c383b2..c59ecfb50 100644 --- a/cups/http-support.c +++ b/cups/http-support.c @@ -52,6 +52,7 @@ #include <stdlib.h> #ifdef HAVE_DNSSD # include <dns_sd.h> +# include <poll.h> #endif /* HAVE_DNSSD */ @@ -1347,10 +1348,18 @@ _httpResolveURI( if (strstr(hostname, "._tcp")) { #ifdef HAVE_DNSSD - DNSServiceRef ref; /* DNS-SD service reference */ + 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? */ char *regtype, /* Pointer to type in hostname */ *domain; /* Pointer to domain in hostname */ _http_uribuf_t uribuf; /* URI buffer */ + struct pollfd polldata; /* Polling data */ + + + if (logit) + fprintf(stderr, "DEBUG: Resolving \"%s\"...\n", hostname); /* * Separate the hostname into service name, registration type, and domain... @@ -1375,10 +1384,6 @@ _httpResolveURI( return (NULL); } - domain = regtype + strlen(regtype) - 1; - if (domain > regtype && *domain == '.') - *domain = '\0'; - for (domain = strchr(regtype, '.'); domain; domain = strchr(domain + 1, '.')) @@ -1398,28 +1403,69 @@ _httpResolveURI( if (logit) { fputs("STATE: +connecting-to-device\n", stderr); - fprintf(stderr, "DEBUG: Resolving %s, regtype=%s, domain=%s...\n", - hostname, regtype, domain); + fprintf(stderr, "DEBUG: Resolving \"%s\", regtype=\"%s\", " + "domain=\"local.\"...\n", hostname, regtype); _cupsLangPuts(stderr, _("INFO: Looking for printer...\n")); } - if (DNSServiceResolve(&ref, 0, 0, hostname, regtype, domain, - resolve_callback, - &uribuf) == kDNSServiceErr_NoError) + uri = NULL; + + if (DNSServiceCreateConnection(&ref) == kDNSServiceErr_NoError) { - if (DNSServiceProcessResult(ref) != kDNSServiceErr_NoError && - resolved_uri[0]) - uri = NULL; - else - uri = resolved_uri; + localref = ref; + if (DNSServiceResolve(&localref, kDNSServiceFlagsShareConnection, 0, + hostname, regtype, "local.", resolve_callback, + &uribuf) == kDNSServiceErr_NoError) + { + if (strcasecmp(domain, "local.")) + { + /* + * Wait 2 seconds for a response to the local resolve; if nothing comes + * in, do an additional domain resolution... + */ + + polldata.fd = DNSServiceRefSockFD(ref); + polldata.events = POLLIN; + + if (poll(&polldata, 1, 2000) != 1) + { + /* + * OK, send the domain name resolve... + */ + + 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 (DNSServiceProcessResult(ref) == kDNSServiceErr_NoError) + uri = resolved_uri; + + if (domainsent) + DNSServiceRefDeallocate(domainref); + + DNSServiceRefDeallocate(localref); + } DNSServiceRefDeallocate(ref); } - else - uri = NULL; if (logit) + { + if (uri) + fputs("DEBUG: Unable to resolve URI!\n", stderr); + else + fprintf(stderr, "DEBUG: Resolved as \"%s\"...\n", uri); + fputs("STATE: -connecting-to-device\n", stderr); + } #else /* diff --git a/cups/http.c b/cups/http.c index 4d4ef2a7a..eef9973b8 100644 --- a/cups/http.c +++ b/cups/http.c @@ -3,7 +3,7 @@ * * HTTP routines for the Common UNIX Printing System (CUPS). * - * Copyright 2007-2008 by Apple Inc. + * Copyright 2007-2009 by Apple Inc. * Copyright 1997-2007 by Easy Software Products, all rights reserved. * * This file contains Kerberos support code, copyright 2006 by @@ -21,13 +21,14 @@ * * _httpBIOMethods() - Get the OpenSSL BIO methods for HTTP connections. * httpBlocking() - Set blocking/non-blocking behavior on a connection. - * httpCheck() - Check to see if there is a pending response from - * the server. + * httpCheck() - Check to see if there is a pending response from the + * server. * httpClearCookie() - Clear the cookie value(s). * httpClearFields() - Clear HTTP request fields. * httpClose() - Close an HTTP connection... * httpConnect() - Connect to a HTTP server. * httpConnectEncrypt() - Connect to a HTTP server using encryption. + * _httpCreate() - Create an unconnected HTTP connection. * httpDelete() - Send a DELETE request to the server. * httpEncryption() - Set the required encryption on the link. * httpError() - Get the last error on a connection. @@ -46,6 +47,7 @@ * content-length or transfer-encoding fields. * httpGetStatus() - Get the status of the last HTTP request. * httpGetSubField() - Get a sub-field value. + * httpGetSubField2() - Get a sub-field value. * httpGets() - Get a line of text from a HTTP connection. * httpHead() - Send a HEAD request to the server. * httpInitialize() - Initialize the HTTP interface library and set the @@ -58,14 +60,15 @@ * httpRead2() - Read data from a HTTP connection. * _httpReadCDSA() - Read function for the CDSA library. * _httpReadGNUTLS() - Read function for the GNU TLS library. - * httpReconnect() - Reconnect to a HTTP server... + * httpReconnect() - Reconnect to a HTTP server. * httpSetAuthString() - Set the current authorization string. * httpSetCookie() - Set the cookie value(s)... * httpSetExpect() - Set the Expect: header in a request. * httpSetField() - Set the value of an HTTP header. - * httpSetLength() - Set the content-length and transfer-encoding. + * httpSetLength() - Set the content-length and content-encoding. * httpTrace() - Send an TRACE request to the server. * httpUpdate() - Update the current HTTP state for incoming data. + * _httpWait() - Wait for data available on a connection (no flush). * httpWait() - Wait for data available on a connection. * httpWrite() - Write data to a HTTP connection. * httpWrite2() - Write data to a HTTP connection. @@ -82,11 +85,11 @@ * http_read_ssl() - Read from a SSL/TLS connection. * http_send() - Send a request with all fields and the trailing * blank line. - * http_setup_ssl() - Set up SSL/TLS on a connection. + * http_setup_ssl() - Set up SSL/TLS support on a connection. * http_shutdown_ssl() - Shut down SSL/TLS on a connection. * http_upgrade() - Force upgrade to TLS encryption. - * http_wait() - Wait for data available on a connection. - * http_write() - Write data to a connection. + * http_write() - Write a buffer to a HTTP connection. + * http_write_chunk() - Write a chunked buffer. * http_write_ssl() - Write to a SSL/TLS connection. */ @@ -131,7 +134,6 @@ static void http_debug_hex(const char *prefix, const char *buffer, static http_field_t http_field(const char *name); static int http_send(http_t *http, http_state_t request, const char *uri); -static int http_wait(http_t *http, int msec, int usessl); static int http_write(http_t *http, const char *buffer, int length); static int http_write_chunk(http_t *http, const char *buffer, @@ -1012,7 +1014,7 @@ httpGets(char *line, /* I - Line to read into */ * No newline; see if there is more data to be read... */ - if (!http->blocking && !http_wait(http, 10000, 1)) + if (!http->blocking && !_httpWait(http, 10000, 1)) { DEBUG_puts("httpGets: Timed out!"); #ifdef WIN32 @@ -1539,7 +1541,7 @@ _httpReadCDSA( * Make sure we have data before we read... */ - if (!http_wait(http, 10000, 0)) + if (!_httpWait(http, 10000, 0)) { http->error = ETIMEDOUT; return (-1); @@ -1600,7 +1602,7 @@ _httpReadGNUTLS( * Make sure we have data before we read... */ - if (!http_wait(http, 10000, 0)) + if (!_httpWait(http, 10000, 0)) { http->error = ETIMEDOUT; return (-1); @@ -2075,6 +2077,95 @@ httpUpdate(http_t *http) /* I - Connection to server */ /* + * '_httpWait()' - Wait for data available on a connection (no flush). + */ + +int /* O - 1 if data is available, 0 otherwise */ +_httpWait(http_t *http, /* I - Connection to server */ + int msec, /* I - Milliseconds to wait */ + int usessl) /* I - Use SSL context? */ +{ +#ifdef HAVE_POLL + struct pollfd pfd; /* Polled file descriptor */ +#else + fd_set input_set; /* select() input set */ + struct timeval timeout; /* Timeout */ +#endif /* HAVE_POLL */ + int nfds; /* Result from select()/poll() */ + + + DEBUG_printf(("_httpWait(http=%p, msec=%d, usessl=%d)\n", http, msec, usessl)); + + if (http->fd < 0) + return (0); + + /* + * Check the SSL/TLS buffers for data first... + */ + +#ifdef HAVE_SSL + if (http->tls && usessl) + { +# ifdef HAVE_LIBSSL + if (SSL_pending((SSL *)(http->tls))) + return (1); +# elif defined(HAVE_GNUTLS) + if (gnutls_record_check_pending(((http_tls_t *)(http->tls))->session)) + return (1); +# elif defined(HAVE_CDSASSL) + size_t bytes; /* Bytes that are available */ + + if (!SSLGetBufferedReadSize(((http_tls_t *)(http->tls))->session, &bytes) && + bytes > 0) + return (1); +# endif /* HAVE_LIBSSL */ + } +#endif /* HAVE_SSL */ + + /* + * Then try doing a select() or poll() to poll the socket... + */ + +#ifdef HAVE_POLL + pfd.fd = http->fd; + pfd.events = POLLIN; + + while ((nfds = poll(&pfd, 1, msec)) < 0 && errno == EINTR); + +#else + do + { + FD_ZERO(&input_set); + FD_SET(http->fd, &input_set); + + DEBUG_printf(("_httpWait: msec=%d, http->fd=%d\n", msec, http->fd)); + + if (msec >= 0) + { + timeout.tv_sec = msec / 1000; + timeout.tv_usec = (msec % 1000) * 1000; + + nfds = select(http->fd + 1, &input_set, NULL, NULL, &timeout); + } + else + nfds = select(http->fd + 1, &input_set, NULL, NULL, NULL); + + DEBUG_printf(("_httpWait: select() returned %d...\n", nfds)); + } +# ifdef WIN32 + while (nfds < 0 && WSAGetLastError() == WSAEINTR); +# else + while (nfds < 0 && errno == EINTR); +# endif /* WIN32 */ +#endif /* HAVE_POLL */ + + DEBUG_printf(("_httpWait: returning with nfds=%d...\n", nfds)); + + return (nfds > 0); +} + + +/* * 'httpWait()' - Wait for data available on a connection. * * @since CUPS 1.1.19/Mac OS X 10.3@ @@ -2108,7 +2199,7 @@ httpWait(http_t *http, /* I - Connection to server */ * If not, check the SSL/TLS buffers and do a select() on the connection... */ - return (http_wait(http, msec, 1)); + return (_httpWait(http, msec, 1)); } @@ -2174,7 +2265,8 @@ httpWrite2(http_t *http, /* I - Connection to server */ httpFlushWrite(http); } - if ((length + http->wused) <= sizeof(http->wbuffer)) + if ((length + http->wused) <= sizeof(http->wbuffer) && + length < sizeof(http->wbuffer)) { /* * Write to buffer... @@ -2436,7 +2528,7 @@ http_bio_read(BIO *h, /* I - BIO data */ * Make sure we have data before we read... */ - if (!http_wait(http, 10000, 0)) + if (!_httpWait(http, 10000, 0)) { #ifdef WIN32 http->error = WSAETIMEDOUT; @@ -3038,95 +3130,6 @@ http_upgrade(http_t *http) /* I - Connection to server */ /* - * 'http_wait()' - Wait for data available on a connection. - */ - -static int /* O - 1 if data is available, 0 otherwise */ -http_wait(http_t *http, /* I - Connection to server */ - int msec, /* I - Milliseconds to wait */ - int usessl) /* I - Use SSL context? */ -{ -#ifdef HAVE_POLL - struct pollfd pfd; /* Polled file descriptor */ -#else - fd_set input_set; /* select() input set */ - struct timeval timeout; /* Timeout */ -#endif /* HAVE_POLL */ - int nfds; /* Result from select()/poll() */ - - - DEBUG_printf(("http_wait(http=%p, msec=%d)\n", http, msec)); - - if (http->fd < 0) - return (0); - - /* - * Check the SSL/TLS buffers for data first... - */ - -#ifdef HAVE_SSL - if (http->tls && usessl) - { -# ifdef HAVE_LIBSSL - if (SSL_pending((SSL *)(http->tls))) - return (1); -# elif defined(HAVE_GNUTLS) - if (gnutls_record_check_pending(((http_tls_t *)(http->tls))->session)) - return (1); -# elif defined(HAVE_CDSASSL) - size_t bytes; /* Bytes that are available */ - - if (!SSLGetBufferedReadSize(((http_tls_t *)(http->tls))->session, &bytes) && - bytes > 0) - return (1); -# endif /* HAVE_LIBSSL */ - } -#endif /* HAVE_SSL */ - - /* - * Then try doing a select() or poll() to poll the socket... - */ - -#ifdef HAVE_POLL - pfd.fd = http->fd; - pfd.events = POLLIN; - - while ((nfds = poll(&pfd, 1, msec)) < 0 && errno == EINTR); - -#else - do - { - FD_ZERO(&input_set); - FD_SET(http->fd, &input_set); - - DEBUG_printf(("http_wait: msec=%d, http->fd=%d\n", msec, http->fd)); - - if (msec >= 0) - { - timeout.tv_sec = msec / 1000; - timeout.tv_usec = (msec % 1000) * 1000; - - nfds = select(http->fd + 1, &input_set, NULL, NULL, &timeout); - } - else - nfds = select(http->fd + 1, &input_set, NULL, NULL, NULL); - - DEBUG_printf(("http_wait: select() returned %d...\n", nfds)); - } -# ifdef WIN32 - while (nfds < 0 && WSAGetLastError() == WSAEINTR); -# else - while (nfds < 0 && errno == EINTR); -# endif /* WIN32 */ -#endif /* HAVE_POLL */ - - DEBUG_printf(("http_wait: returning with nfds=%d...\n", nfds)); - - return (nfds > 0); -} - - -/* * 'http_write()' - Write a buffer to a HTTP connection. */ diff --git a/cups/libcups.exp b/cups/libcups.exp index 74914ae44..4bb5cd67a 100644 --- a/cups/libcups.exp +++ b/cups/libcups.exp @@ -306,6 +306,8 @@ _ippRead _ippReadFile _ippReadIO _ippSetPort +_ippTagString +_ippTagValue _ippTimeToDate _ippWrite _ippWriteFile diff --git a/cups/request.c b/cups/request.c index bf291eabf..8179e51cb 100644 --- a/cups/request.c +++ b/cups/request.c @@ -753,6 +753,9 @@ cupsWriteRequestData( const char *buffer, /* I - Bytes to write */ size_t length) /* I - Number of bytes to write */ { + int wused; /* Previous bytes in buffer */ + + /* * Get the default connection as needed... */ @@ -776,6 +779,8 @@ cupsWriteRequestData( * Then write to the HTTP connection... */ + wused = http->wused; + if (httpWrite2(http, buffer, length) < 0) return (HTTP_ERROR); @@ -783,10 +788,19 @@ cupsWriteRequestData( * Finally, check if we have any pending data from the server... */ - if (httpCheck(http)) - return (httpUpdate(http)); - else - return (HTTP_CONTINUE); + if (length > HTTP_MAX_BUFFER || + http->wused < wused || + (wused > 0 && http->wused == length)) + { + /* + * We've written something to the server, so check for response data... + */ + + if (_httpWait(http, 0, 1)) + return (httpUpdate(http)); + } + + return (HTTP_CONTINUE); } diff --git a/cups/testhttp.c b/cups/testhttp.c index fda2147b2..3e10a7634 100644 --- a/cups/testhttp.c +++ b/cups/testhttp.c @@ -468,7 +468,7 @@ main(int argc, /* I - Number of command-line arguments */ printf("_httpResolveURI(%s): ", argv[1]); fflush(stdout); - if (!_httpResolveURI(argv[1], resolved, sizeof(resolved), 0)) + if (!_httpResolveURI(argv[1], resolved, sizeof(resolved), 1)) { puts("FAIL"); return (1); diff --git a/cups/util.c b/cups/util.c index 1a6dd50a3..ee1cdf372 100644 --- a/cups/util.c +++ b/cups/util.c @@ -458,21 +458,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... |