ssize_t /* O - Bytes read, 0 on EOF, -1 on error */ cupsReadResponseData( http_t *http, /* I - Connection to server or @code CUPS_HTTP_DEFAULT@ */ char *buffer, /* I - Buffer to use */ size_t length) /* I - Number of bytes to read */ { /* * Get the default connection as needed... */ DEBUG_printf(("cupsReadResponseData(http=%p, buffer=%p, " "length=" CUPS_LLFMT ")", http, buffer, CUPS_LLCAST length)); if (!http) { _cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */ if ((http = cg->http) == NULL) { _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("No active connection"), 1); return (-1); } } /* * Then read from the HTTP connection... */ return (httpRead2(http, buffer, length)); }
static void _get_read_data (GtkCupsRequest *request) { char buffer[_GTK_CUPS_MAX_CHUNK_SIZE]; gsize bytes; gsize bytes_written; GIOStatus io_status; GError *error; GTK_NOTE (PRINTING, g_print ("CUPS Backend: %s\n", G_STRFUNC)); error = NULL; request->poll_state = GTK_CUPS_HTTP_READ; #if HAVE_CUPS_API_1_2 bytes = httpRead2 (request->http, buffer, sizeof (buffer)); #else bytes = httpRead (request->http, buffer, sizeof (buffer)); #endif /* HAVE_CUPS_API_1_2 */ request->bytes_received += bytes; GTK_NOTE (PRINTING, g_print ("CUPS Backend: %" G_GSIZE_FORMAT " bytes read\n", bytes)); io_status = g_io_channel_write_chars (request->data_io, buffer, bytes, &bytes_written, &error); if (io_status == G_IO_STATUS_ERROR) { request->state = GTK_CUPS_GET_DONE; request->poll_state = GTK_CUPS_HTTP_IDLE; gtk_cups_result_set_error (request->result, GTK_CUPS_ERROR_IO, io_status, error->code, error->message); g_error_free (error); } /* Stop if we do not expect any more data or EOF was received. */ #if HAVE_CUPS_API_1_2 if (httpGetLength2 (request->http) <= request->bytes_received || bytes == 0) #else if (httpGetLength (request->http) <= request->bytes_received || bytes == 0) #endif /* HAVE_CUPS_API_1_2 */ { request->state = GTK_CUPS_GET_DONE; request->poll_state = GTK_CUPS_HTTP_IDLE; return; } }
static void _get_read_data (GtkCupsRequest *request) { char buffer[_GTK_CUPS_MAX_CHUNK_SIZE]; gsize bytes; gsize bytes_written; GIOStatus io_status; GError *error; GTK_NOTE (PRINTING, g_print ("CUPS Backend: %s\n", G_STRFUNC)); error = NULL; request->poll_state = GTK_CUPS_HTTP_READ; #if HAVE_CUPS_API_1_2 bytes = httpRead2 (request->http, buffer, sizeof (buffer)); #else bytes = httpRead (request->http, buffer, sizeof (buffer)); #endif /* HAVE_CUPS_API_1_2 */ GTK_NOTE (PRINTING, g_print ("CUPS Backend: %i bytes read\n", bytes)); if (bytes == 0) { request->state = GTK_CUPS_GET_DONE; request->poll_state = GTK_CUPS_HTTP_IDLE; return; } io_status = g_io_channel_write_chars (request->data_io, buffer, bytes, &bytes_written, &error); if (io_status == G_IO_STATUS_ERROR) { request->state = GTK_CUPS_GET_DONE; request->poll_state = GTK_CUPS_HTTP_IDLE; gtk_cups_result_set_error (request->result, GTK_CUPS_ERROR_IO, io_status, error->code, error->message); g_error_free (error); } }
void httpFlush(http_t *http) { char buffer[8192]; /* Junk buffer */ int blocking; /* To block or not to block */ http_state_t oldstate; /* Old state */ blocking = http->blocking; http->blocking = 0; oldstate = http->state; while (httpRead2(http, buffer, sizeof(buffer)) > 0); http->blocking = blocking; if (http->state == oldstate && http->state != HTTP_WAITING && http->fd >= 0) { http->state = HTTP_WAITING; closesocket(http->fd); http->fd = -1; } }
ipp_t * /* O - Response data */ cupsDoIORequest(http_t *http, /* I - Connection to server or @code CUPS_HTTP_DEFAULT@ */ ipp_t *request, /* I - IPP request */ const char *resource, /* I - HTTP resource for POST */ int infile, /* I - File to read from or -1 for none */ int outfile) /* I - File to write to or -1 for none */ { ipp_t *response = NULL; /* IPP response data */ size_t length = 0; /* Content-Length value */ http_status_t status; /* Status of HTTP request */ struct stat fileinfo; /* File information */ int bytes; /* Number of bytes read/written */ char buffer[32768]; /* Output buffer */ DEBUG_printf(("cupsDoIORequest(http=%p, request=%p(%s), resource=\"%s\", " "infile=%d, outfile=%d)", http, request, request ? ippOpString(request->request.op.operation_id) : "?", resource, infile, outfile)); /* * Range check input... */ if (!request || !resource) { ippDelete(request); _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(EINVAL), 0); return (NULL); } /* * Get the default connection as needed... */ if (!http) if ((http = _cupsConnect()) == NULL) { ippDelete(request); return (NULL); } /* * See if we have a file to send... */ if (infile >= 0) { if (fstat(infile, &fileinfo)) { /* * Can't get file information! */ _cupsSetError(errno == EBADF ? IPP_STATUS_ERROR_NOT_FOUND : IPP_STATUS_ERROR_NOT_AUTHORIZED, NULL, 0); ippDelete(request); return (NULL); } #ifdef WIN32 if (fileinfo.st_mode & _S_IFDIR) #else if (S_ISDIR(fileinfo.st_mode)) #endif /* WIN32 */ { /* * Can't send a directory... */ ippDelete(request); _cupsSetError(IPP_STATUS_ERROR_NOT_POSSIBLE, strerror(EISDIR), 0); return (NULL); } #ifndef WIN32 if (!S_ISREG(fileinfo.st_mode)) length = 0; /* Chunk when piping */ else #endif /* !WIN32 */ length = ippLength(request) + fileinfo.st_size; } else length = ippLength(request); DEBUG_printf(("2cupsDoIORequest: Request length=%ld, total length=%ld", (long)ippLength(request), (long)length)); /* * Clear any "Local" authentication data since it is probably stale... */ if (http->authstring && !strncmp(http->authstring, "Local ", 6)) httpSetAuthString(http, NULL, NULL); /* * Loop until we can send the request without authorization problems. */ while (response == NULL) { DEBUG_puts("2cupsDoIORequest: setup..."); /* * Send the request... */ status = cupsSendRequest(http, request, resource, length); DEBUG_printf(("2cupsDoIORequest: status=%d", status)); if (status == HTTP_STATUS_CONTINUE && request->state == IPP_STATE_DATA && infile >= 0) { DEBUG_puts("2cupsDoIORequest: file write..."); /* * Send the file with the request... */ #ifndef WIN32 if (S_ISREG(fileinfo.st_mode)) #endif /* WIN32 */ lseek(infile, 0, SEEK_SET); while ((bytes = (int)read(infile, buffer, sizeof(buffer))) > 0) { if ((status = cupsWriteRequestData(http, buffer, bytes)) != HTTP_STATUS_CONTINUE) break; } } /* * Get the server's response... */ if (status != HTTP_STATUS_ERROR) { response = cupsGetResponse(http, resource); status = httpGetStatus(http); } DEBUG_printf(("2cupsDoIORequest: status=%d", status)); if (status == HTTP_STATUS_ERROR || (status >= HTTP_STATUS_BAD_REQUEST && status != HTTP_STATUS_UNAUTHORIZED && status != HTTP_STATUS_UPGRADE_REQUIRED)) { _cupsSetHTTPError(status); break; } if (response && outfile >= 0) { /* * Write trailing data to file... */ while ((bytes = (int)httpRead2(http, buffer, sizeof(buffer))) > 0) if (write(outfile, buffer, bytes) < bytes) break; } if (http->state != HTTP_STATE_WAITING) { /* * Flush any remaining data... */ httpFlush(http); } } /* * Delete the original request and return the response... */ ippDelete(request); return (response); }
int /* O - 1 on success, 0 on error */ translate_messages(cups_array_t *cat, /* I - Message catalog */ const char *lang) /* I - Output language... */ { /* * Google provides a simple translation/language tool for translating * from one language to another. It is far from perfect, however it * can be used to get a basic translation done or update an existing * translation when no other resources are available. * * Translation requests are sent as HTTP POSTs to * "http://translate.google.com/translate_t" with the following form * variables: * * Name Description Value * -------- ---------------------------------- ---------------- * hl Help language? "en" * ie Input encoding "UTF8" * langpair Language pair "en|" + language * oe Output encoding "UTF8" * text Text to translate translation string */ int ret; /* Return value */ _cups_message_t *m; /* Current message */ int tries; /* Number of tries... */ http_t *http; /* HTTP connection */ http_status_t status; /* Status of POST request */ char *idptr, /* Pointer into msgid */ buffer[65536], /* Input/output buffer */ *bufptr, /* Pointer into buffer */ *bufend, /* Pointer to end of buffer */ length[16]; /* Content length */ int bytes; /* Number of bytes read */ /* * Connect to translate.google.com... */ puts("Connecting to translate.google.com..."); if ((http = httpConnect("translate.google.com", 80)) == NULL) { perror("Unable to connect to translate.google.com"); return (0); } /* * Scan the current messages, requesting a translation of any untranslated * messages... */ for (m = (_cups_message_t *)cupsArrayFirst(cat), ret = 1; m; m = (_cups_message_t *)cupsArrayNext(cat)) { /* * Skip messages that are already translated... */ if (m->str && m->str[0]) continue; /* * Encode the form data into the buffer... */ snprintf(buffer, sizeof(buffer), "hl=en&ie=UTF8&langpair=en|%s&oe=UTF8&text=", lang); bufptr = buffer + strlen(buffer); bufend = buffer + sizeof(buffer) - 5; for (idptr = m->id; *idptr && bufptr < bufend; idptr ++) if (*idptr == ' ') *bufptr++ = '+'; else if (*idptr < ' ' || *idptr == '%') { sprintf(bufptr, "%%%02X", *idptr & 255); bufptr += 3; } else if (*idptr != '&') *bufptr++ = *idptr; *bufptr++ = '&'; *bufptr = '\0'; sprintf(length, "%d", (int)(bufptr - buffer)); /* * Send the request... */ printf("\"%s\" = ", m->id); fflush(stdout); tries = 0; do { httpClearFields(http); httpSetField(http, HTTP_FIELD_CONTENT_TYPE, "application/x-www-form-urlencoded"); httpSetField(http, HTTP_FIELD_CONTENT_LENGTH, length); if (httpPost(http, "/translate_t")) { httpReconnect(http); httpPost(http, "/translate_t"); } httpWrite2(http, buffer, bufptr - buffer); while ((status = httpUpdate(http)) == HTTP_CONTINUE); if (status != HTTP_OK && status != HTTP_ERROR) httpFlush(http); tries ++; } while (status == HTTP_ERROR && tries < 10); if (status == HTTP_OK) { /* * OK, read the translation back... */ bufptr = buffer; bufend = buffer + sizeof(buffer) - 1; while ((bytes = httpRead2(http, bufptr, bufend - bufptr)) > 0) bufptr += bytes; if (bytes < 0) { /* * Read error, abort! */ puts("READ ERROR!"); ret = 0; break; } *bufptr = '\0'; /* * Find the div containing translation */ if ((bufptr = strstr(buffer, "<div id=result_box")) == NULL) { /* * No textarea, abort! */ puts("NO div id=result_box!"); ret = 0; break; } if ((bufptr = strchr(bufptr, '>')) == NULL) { /* * textarea doesn't end, abort! */ puts("DIV SHORT DATA!"); ret = 0; break; } bufptr ++; if ((bufend = strstr(bufptr, "</div>")) == NULL) { /* * textarea doesn't close, abort! */ puts("/DIV SHORT DATA!"); ret = 0; break; } *bufend = '\0'; /* * Copy the translation... */ m->str = strdup(bufptr); /* * Convert character entities to regular chars... */ for (bufptr = strchr(m->str, '&'); bufptr; bufptr = strchr(bufptr + 1, '&')) { if (!strncmp(bufptr, "<", 4)) { *bufptr = '<'; _cups_strcpy(bufptr + 1, bufptr + 4); } else if (!strncmp(bufptr, ">", 4)) { *bufptr = '>'; _cups_strcpy(bufptr + 1, bufptr + 4); } else if (!strncmp(bufptr, "&", 5)) _cups_strcpy(bufptr + 1, bufptr + 5); } printf("\"%s\"\n", m->str); } else if (status == HTTP_ERROR) { printf("NETWORK ERROR (%s)!\n", strerror(httpError(http))); ret = 0; break; } else { printf("HTTP ERROR %d!\n", status); ret = 0; break; } } httpClose(http); return (ret); }
int /* O - Exit status */ main(int argc, /* I - Number of command-line arguments */ char *argv[]) /* I - Command-line arguments */ { int i, j, k; /* Looping vars */ http_t *http; /* HTTP connection */ http_encryption_t encryption; /* Encryption type */ http_status_t status; /* Status of GET command */ int failures; /* Number of test failures */ char buffer[8192]; /* Input buffer */ long bytes; /* Number of bytes read */ FILE *out; /* Output file */ char encode[256], /* Base64-encoded string */ decode[256]; /* Base64-decoded string */ int decodelen; /* Length of decoded string */ char scheme[HTTP_MAX_URI], /* Scheme from URI */ hostname[HTTP_MAX_URI], /* Hostname from URI */ username[HTTP_MAX_URI], /* Username:password from URI */ resource[HTTP_MAX_URI]; /* Resource from URI */ int port; /* Port number from URI */ http_uri_status_t uri_status; /* Status of URI separation */ http_addrlist_t *addrlist, /* Address list */ *addr; /* Current address */ off_t length, total; /* Length and total bytes */ time_t start, current; /* Start and end time */ const char *encoding; /* Negotiated Content-Encoding */ static const char * const uri_status_strings[] = { "HTTP_URI_STATUS_OVERFLOW", "HTTP_URI_STATUS_BAD_ARGUMENTS", "HTTP_URI_STATUS_BAD_RESOURCE", "HTTP_URI_STATUS_BAD_PORT", "HTTP_URI_STATUS_BAD_HOSTNAME", "HTTP_URI_STATUS_BAD_USERNAME", "HTTP_URI_STATUS_BAD_SCHEME", "HTTP_URI_STATUS_BAD_URI", "HTTP_URI_STATUS_OK", "HTTP_URI_STATUS_MISSING_SCHEME", "HTTP_URI_STATUS_UNKNOWN_SCHEME", "HTTP_URI_STATUS_MISSING_RESOURCE" }; /* * Do API tests if we don't have a URL on the command-line... */ if (argc == 1) { failures = 0; /* * httpGetDateString()/httpGetDateTime() */ fputs("httpGetDateString()/httpGetDateTime(): ", stdout); start = time(NULL); strlcpy(buffer, httpGetDateString(start), sizeof(buffer)); current = httpGetDateTime(buffer); i = (int)(current - start); if (i < 0) i = -i; if (!i) puts("PASS"); else { failures ++; puts("FAIL"); printf(" Difference is %d seconds, %02d:%02d:%02d...\n", i, i / 3600, (i / 60) % 60, i % 60); printf(" httpGetDateString(%d) returned \"%s\"\n", (int)start, buffer); printf(" httpGetDateTime(\"%s\") returned %d\n", buffer, (int)current); printf(" httpGetDateString(%d) returned \"%s\"\n", (int)current, httpGetDateString(current)); } /* * httpDecode64_2()/httpEncode64_2() */ fputs("httpDecode64_2()/httpEncode64_2(): ", stdout); for (i = 0, j = 0; i < (int)(sizeof(base64_tests) / sizeof(base64_tests[0])); i ++) { httpEncode64_2(encode, sizeof(encode), base64_tests[i][0], (int)strlen(base64_tests[i][0])); decodelen = (int)sizeof(decode); httpDecode64_2(decode, &decodelen, base64_tests[i][1]); if (strcmp(decode, base64_tests[i][0])) { failures ++; if (j) { puts("FAIL"); j = 1; } printf(" httpDecode64_2() returned \"%s\", expected \"%s\"...\n", decode, base64_tests[i][0]); } if (strcmp(encode, base64_tests[i][1])) { failures ++; if (j) { puts("FAIL"); j = 1; } printf(" httpEncode64_2() returned \"%s\", expected \"%s\"...\n", encode, base64_tests[i][1]); } } if (!j) puts("PASS"); /* * httpGetHostname() */ fputs("httpGetHostname(): ", stdout); if (httpGetHostname(NULL, hostname, sizeof(hostname))) printf("PASS (%s)\n", hostname); else { failures ++; puts("FAIL"); } /* * httpAddrGetList() */ printf("httpAddrGetList(%s): ", hostname); addrlist = httpAddrGetList(hostname, AF_UNSPEC, NULL); if (addrlist) { for (i = 0, addr = addrlist; addr; i ++, addr = addr->next) { char numeric[1024]; /* Numeric IP address */ httpAddrString(&(addr->addr), numeric, sizeof(numeric)); if (!strcmp(numeric, "UNKNOWN")) break; } if (addr) printf("FAIL (bad address for %s)\n", hostname); else printf("PASS (%d address(es) for %s)\n", i, hostname); httpAddrFreeList(addrlist); } else if (isdigit(hostname[0] & 255)) { puts("FAIL (ignored because hostname is numeric)"); } else { failures ++; puts("FAIL"); } /* * Test httpSeparateURI()... */ fputs("httpSeparateURI(): ", stdout); for (i = 0, j = 0; i < (int)(sizeof(uri_tests) / sizeof(uri_tests[0])); i ++) { uri_status = httpSeparateURI(HTTP_URI_CODING_MOST, uri_tests[i].uri, scheme, sizeof(scheme), username, sizeof(username), hostname, sizeof(hostname), &port, resource, sizeof(resource)); if (uri_status != uri_tests[i].result || strcmp(scheme, uri_tests[i].scheme) || strcmp(username, uri_tests[i].username) || strcmp(hostname, uri_tests[i].hostname) || port != uri_tests[i].port || strcmp(resource, uri_tests[i].resource)) { failures ++; if (!j) { puts("FAIL"); j = 1; } printf(" \"%s\":\n", uri_tests[i].uri); if (uri_status != uri_tests[i].result) printf(" Returned %s instead of %s\n", uri_status_strings[uri_status + 8], uri_status_strings[uri_tests[i].result + 8]); if (strcmp(scheme, uri_tests[i].scheme)) printf(" Scheme \"%s\" instead of \"%s\"\n", scheme, uri_tests[i].scheme); if (strcmp(username, uri_tests[i].username)) printf(" Username \"%s\" instead of \"%s\"\n", username, uri_tests[i].username); if (strcmp(hostname, uri_tests[i].hostname)) printf(" Hostname \"%s\" instead of \"%s\"\n", hostname, uri_tests[i].hostname); if (port != uri_tests[i].port) printf(" Port %d instead of %d\n", port, uri_tests[i].port); if (strcmp(resource, uri_tests[i].resource)) printf(" Resource \"%s\" instead of \"%s\"\n", resource, uri_tests[i].resource); } } if (!j) printf("PASS (%d URIs tested)\n", (int)(sizeof(uri_tests) / sizeof(uri_tests[0]))); /* * Test httpAssembleURI()... */ fputs("httpAssembleURI(): ", stdout); for (i = 0, j = 0, k = 0; i < (int)(sizeof(uri_tests) / sizeof(uri_tests[0])); i ++) if (uri_tests[i].result == HTTP_URI_STATUS_OK && !strstr(uri_tests[i].uri, "%64") && strstr(uri_tests[i].uri, "//")) { k ++; uri_status = httpAssembleURI(uri_tests[i].assemble_coding, buffer, sizeof(buffer), uri_tests[i].scheme, uri_tests[i].username, uri_tests[i].hostname, uri_tests[i].assemble_port, uri_tests[i].resource); if (uri_status != HTTP_URI_STATUS_OK) { failures ++; if (!j) { puts("FAIL"); j = 1; } printf(" \"%s\": %s\n", uri_tests[i].uri, uri_status_strings[uri_status + 8]); } else if (strcmp(buffer, uri_tests[i].uri)) { failures ++; if (!j) { puts("FAIL"); j = 1; } printf(" \"%s\": assembled = \"%s\"\n", uri_tests[i].uri, buffer); } } if (!j) printf("PASS (%d URIs tested)\n", k); /* * httpAssembleUUID */ fputs("httpAssembleUUID: ", stdout); httpAssembleUUID("hostname.example.com", 631, "printer", 12345, buffer, sizeof(buffer)); if (strncmp(buffer, "urn:uuid:", 9)) { printf("FAIL (%s)\n", buffer); failures ++; } else printf("PASS (%s)\n", buffer); /* * Show a summary and return... */ if (failures) printf("\n%d TESTS FAILED!\n", failures); else puts("\nALL TESTS PASSED!"); return (failures); } else if (strstr(argv[1], "._tcp")) { /* * Test resolving an mDNS name. */ char resolved[1024]; /* Resolved URI */ printf("_httpResolveURI(%s, _HTTP_RESOLVE_DEFAULT): ", argv[1]); fflush(stdout); if (!_httpResolveURI(argv[1], resolved, sizeof(resolved), _HTTP_RESOLVE_DEFAULT, NULL, NULL)) { puts("FAIL"); return (1); } else printf("PASS (%s)\n", resolved); printf("_httpResolveURI(%s, _HTTP_RESOLVE_FQDN): ", argv[1]); fflush(stdout); if (!_httpResolveURI(argv[1], resolved, sizeof(resolved), _HTTP_RESOLVE_FQDN, NULL, NULL)) { puts("FAIL"); return (1); } else if (strstr(resolved, ".local:")) { printf("FAIL (%s)\n", resolved); return (1); } else { printf("PASS (%s)\n", resolved); return (0); } } else if (!strcmp(argv[1], "-u") && argc == 3) { /* * Test URI separation... */ uri_status = httpSeparateURI(HTTP_URI_CODING_ALL, argv[2], scheme, sizeof(scheme), username, sizeof(username), hostname, sizeof(hostname), &port, resource, sizeof(resource)); printf("uri_status = %s\n", uri_status_strings[uri_status + 8]); printf("scheme = \"%s\"\n", scheme); printf("username = \"%s\"\n", username); printf("hostname = \"%s\"\n", hostname); printf("port = %d\n", port); printf("resource = \"%s\"\n", resource); return (0); } /* * Test HTTP GET requests... */ http = NULL; out = stdout; for (i = 1; i < argc; i ++) { if (!strcmp(argv[i], "-o")) { i ++; if (i >= argc) break; out = fopen(argv[i], "wb"); continue; } httpSeparateURI(HTTP_URI_CODING_MOST, argv[i], scheme, sizeof(scheme), username, sizeof(username), hostname, sizeof(hostname), &port, resource, sizeof(resource)); if (!_cups_strcasecmp(scheme, "https") || !_cups_strcasecmp(scheme, "ipps") || port == 443) encryption = HTTP_ENCRYPTION_ALWAYS; else encryption = HTTP_ENCRYPTION_IF_REQUESTED; http = httpConnect2(hostname, port, NULL, AF_UNSPEC, encryption, 1, 30000, NULL); if (http == NULL) { perror(hostname); continue; } printf("Checking file \"%s\"...\n", resource); do { if (!_cups_strcasecmp(httpGetField(http, HTTP_FIELD_CONNECTION), "close")) { httpClearFields(http); if (httpReconnect2(http, 30000, NULL)) { status = HTTP_STATUS_ERROR; break; } } httpClearFields(http); httpSetField(http, HTTP_FIELD_AUTHORIZATION, httpGetAuthString(http)); httpSetField(http, HTTP_FIELD_ACCEPT_LANGUAGE, "en"); if (httpHead(http, resource)) { if (httpReconnect2(http, 30000, NULL)) { status = HTTP_STATUS_ERROR; break; } else { status = HTTP_STATUS_UNAUTHORIZED; continue; } } while ((status = httpUpdate(http)) == HTTP_STATUS_CONTINUE); if (status == HTTP_STATUS_UNAUTHORIZED) { /* * Flush any error message... */ httpFlush(http); /* * See if we can do authentication... */ if (cupsDoAuthentication(http, "GET", resource)) { status = HTTP_STATUS_CUPS_AUTHORIZATION_CANCELED; break; } if (httpReconnect2(http, 30000, NULL)) { status = HTTP_STATUS_ERROR; break; } continue; } #ifdef HAVE_SSL else if (status == HTTP_STATUS_UPGRADE_REQUIRED) { /* Flush any error message... */ httpFlush(http); /* Reconnect... */ if (httpReconnect2(http, 30000, NULL)) { status = HTTP_STATUS_ERROR; break; } /* Upgrade with encryption... */ httpEncryption(http, HTTP_ENCRYPTION_REQUIRED); /* Try again, this time with encryption enabled... */ continue; } #endif /* HAVE_SSL */ } while (status == HTTP_STATUS_UNAUTHORIZED || status == HTTP_STATUS_UPGRADE_REQUIRED); if (status == HTTP_STATUS_OK) puts("HEAD OK:"); else printf("HEAD failed with status %d...\n", status); encoding = httpGetContentEncoding(http); printf("Requesting file \"%s\" (Accept-Encoding: %s)...\n", resource, encoding ? encoding : "identity"); do { if (!_cups_strcasecmp(httpGetField(http, HTTP_FIELD_CONNECTION), "close")) { httpClearFields(http); if (httpReconnect2(http, 30000, NULL)) { status = HTTP_STATUS_ERROR; break; } } httpClearFields(http); httpSetField(http, HTTP_FIELD_AUTHORIZATION, httpGetAuthString(http)); httpSetField(http, HTTP_FIELD_ACCEPT_LANGUAGE, "en"); httpSetField(http, HTTP_FIELD_ACCEPT_ENCODING, encoding); if (httpGet(http, resource)) { if (httpReconnect2(http, 30000, NULL)) { status = HTTP_STATUS_ERROR; break; } else { status = HTTP_STATUS_UNAUTHORIZED; continue; } } while ((status = httpUpdate(http)) == HTTP_STATUS_CONTINUE); if (status == HTTP_STATUS_UNAUTHORIZED) { /* * Flush any error message... */ httpFlush(http); /* * See if we can do authentication... */ if (cupsDoAuthentication(http, "GET", resource)) { status = HTTP_STATUS_CUPS_AUTHORIZATION_CANCELED; break; } if (httpReconnect2(http, 30000, NULL)) { status = HTTP_STATUS_ERROR; break; } continue; } #ifdef HAVE_SSL else if (status == HTTP_STATUS_UPGRADE_REQUIRED) { /* Flush any error message... */ httpFlush(http); /* Reconnect... */ if (httpReconnect2(http, 30000, NULL)) { status = HTTP_STATUS_ERROR; break; } /* Upgrade with encryption... */ httpEncryption(http, HTTP_ENCRYPTION_REQUIRED); /* Try again, this time with encryption enabled... */ continue; } #endif /* HAVE_SSL */ } while (status == HTTP_STATUS_UNAUTHORIZED || status == HTTP_STATUS_UPGRADE_REQUIRED); if (status == HTTP_STATUS_OK) puts("GET OK:"); else printf("GET failed with status %d...\n", status); start = time(NULL); length = httpGetLength2(http); total = 0; while ((bytes = httpRead2(http, buffer, sizeof(buffer))) > 0) { total += bytes; fwrite(buffer, bytes, 1, out); if (out != stdout) { current = time(NULL); if (current == start) current ++; printf("\r" CUPS_LLFMT "/" CUPS_LLFMT " bytes (" CUPS_LLFMT " bytes/sec) ", CUPS_LLCAST total, CUPS_LLCAST length, CUPS_LLCAST (total / (current - start))); fflush(stdout); } } } puts("Closing connection to server..."); httpClose(http); if (out != stdout) fclose(out); return (0); }
http_status_t /* O - HTTP status */ cupsGetFd(http_t *http, /* I - Connection to server or @code CUPS_HTTP_DEFAULT@ */ const char *resource, /* I - Resource name */ int fd) /* I - File descriptor */ { ssize_t bytes; /* Number of bytes read */ char buffer[8192]; /* Buffer for file */ http_status_t status; /* HTTP status from server */ char if_modified_since[HTTP_MAX_VALUE]; /* If-Modified-Since header */ int new_auth = 0; /* Using new auth information? */ int digest; /* Are we using Digest authentication? */ /* * Range check input... */ DEBUG_printf(("cupsGetFd(http=%p, resource=\"%s\", fd=%d)", (void *)http, resource, fd)); if (!resource || fd < 0) { if (http) http->error = EINVAL; return (HTTP_STATUS_ERROR); } if (!http) if ((http = _cupsConnect()) == NULL) return (HTTP_STATUS_SERVICE_UNAVAILABLE); /* * Then send GET requests to the HTTP server... */ strlcpy(if_modified_since, httpGetField(http, HTTP_FIELD_IF_MODIFIED_SINCE), sizeof(if_modified_since)); do { if (!_cups_strcasecmp(httpGetField(http, HTTP_FIELD_CONNECTION), "close")) { httpClearFields(http); if (httpReconnect2(http, 30000, NULL)) { status = HTTP_STATUS_ERROR; break; } } httpClearFields(http); httpSetField(http, HTTP_FIELD_IF_MODIFIED_SINCE, if_modified_since); digest = http->authstring && !strncmp(http->authstring, "Digest ", 7); if (digest && !new_auth) { /* * Update the Digest authentication string... */ _httpSetDigestAuthString(http, http->nextnonce, "GET", resource); } #ifdef HAVE_GSSAPI if (http->authstring && !strncmp(http->authstring, "Negotiate", 9) && !new_auth) { /* * Do not use cached Kerberos credentials since they will look like a * "replay" attack... */ _cupsSetNegotiateAuthString(http, "GET", resource); } #endif /* HAVE_GSSAPI */ httpSetField(http, HTTP_FIELD_AUTHORIZATION, http->authstring); if (httpGet(http, resource)) { if (httpReconnect2(http, 30000, NULL)) { status = HTTP_STATUS_ERROR; break; } else { status = HTTP_STATUS_UNAUTHORIZED; continue; } } new_auth = 0; while ((status = httpUpdate(http)) == HTTP_STATUS_CONTINUE); if (status == HTTP_STATUS_UNAUTHORIZED) { /* * Flush any error message... */ httpFlush(http); /* * See if we can do authentication... */ new_auth = 1; if (cupsDoAuthentication(http, "GET", resource)) { status = HTTP_STATUS_CUPS_AUTHORIZATION_CANCELED; break; } if (httpReconnect2(http, 30000, NULL)) { status = HTTP_STATUS_ERROR; break; } continue; } #ifdef HAVE_SSL else if (status == HTTP_STATUS_UPGRADE_REQUIRED) { /* Flush any error message... */ httpFlush(http); /* Reconnect... */ if (httpReconnect2(http, 30000, NULL)) { status = HTTP_STATUS_ERROR; break; } /* Upgrade with encryption... */ httpEncryption(http, HTTP_ENCRYPTION_REQUIRED); /* Try again, this time with encryption enabled... */ continue; } #endif /* HAVE_SSL */ } while (status == HTTP_STATUS_UNAUTHORIZED || status == HTTP_STATUS_UPGRADE_REQUIRED); /* * See if we actually got the file or an error... */ if (status == HTTP_STATUS_OK) { /* * Yes, copy the file... */ while ((bytes = httpRead2(http, buffer, sizeof(buffer))) > 0) write(fd, buffer, (size_t)bytes); } else { _cupsSetHTTPError(status); httpFlush(http); } /* * Return the request status... */ DEBUG_printf(("1cupsGetFd: Returning %d...", status)); return (status); }
http_status_t /* O - HTTP status */ cupsGetFd(http_t *http, /* I - HTTP connection to server */ const char *resource, /* I - Resource name */ int fd) /* I - File descriptor */ { int bytes; /* Number of bytes read */ char buffer[8192]; /* Buffer for file */ http_status_t status; /* HTTP status from server */ char if_modified_since[HTTP_MAX_VALUE]; /* If-Modified-Since header */ /* * Range check input... */ DEBUG_printf(("cupsGetFd(http=%p, resource=\"%s\", fd=%d)\n", http, resource, fd)); if (!http || !resource || fd < 0) { if (http) http->error = EINVAL; return (HTTP_ERROR); } /* * Then send GET requests to the HTTP server... */ strlcpy(if_modified_since, httpGetField(http, HTTP_FIELD_IF_MODIFIED_SINCE), sizeof(if_modified_since)); do { httpClearFields(http); httpSetField(http, HTTP_FIELD_AUTHORIZATION, http->authstring); httpSetField(http, HTTP_FIELD_IF_MODIFIED_SINCE, if_modified_since); if (httpGet(http, resource)) { if (httpReconnect(http)) { status = HTTP_ERROR; break; } else { status = HTTP_UNAUTHORIZED; continue; } } while ((status = httpUpdate(http)) == HTTP_CONTINUE); if (status == HTTP_UNAUTHORIZED) { /* * Flush any error message... */ httpFlush(http); /* * See if we can do authentication... */ if (cupsDoAuthentication(http, "GET", resource)) break; if (httpReconnect(http)) { status = HTTP_ERROR; break; } continue; } #ifdef HAVE_SSL else if (status == HTTP_UPGRADE_REQUIRED) { /* Flush any error message... */ httpFlush(http); /* Reconnect... */ if (httpReconnect(http)) { status = HTTP_ERROR; break; } /* Upgrade with encryption... */ httpEncryption(http, HTTP_ENCRYPT_REQUIRED); /* Try again, this time with encryption enabled... */ continue; } #endif /* HAVE_SSL */ } while (status == HTTP_UNAUTHORIZED || status == HTTP_UPGRADE_REQUIRED); /* * See if we actually got the file or an error... */ if (status == HTTP_OK) { /* * Yes, copy the file... */ while ((bytes = httpRead2(http, buffer, sizeof(buffer))) > 0) write(fd, buffer, bytes); } else { _cupsSetHTTPError(status); httpFlush(http); } /* * Return the request status... */ return (status); }
int /* O - Exit status */ main(int argc, /* I - Number of command-line arguments */ char *argv[]) /* I - Command-line arguments */ { int i, j, k; /* Looping vars */ http_t *http; /* HTTP connection */ http_status_t status; /* Status of GET command */ int failures; /* Number of test failures */ char buffer[8192]; /* Input buffer */ long bytes; /* Number of bytes read */ FILE *out; /* Output file */ char encode[256], /* Base64-encoded string */ decode[256]; /* Base64-decoded string */ int decodelen; /* Length of decoded string */ char scheme[HTTP_MAX_URI], /* Scheme from URI */ hostname[HTTP_MAX_URI], /* Hostname from URI */ username[HTTP_MAX_URI], /* Username:password from URI */ resource[HTTP_MAX_URI]; /* Resource from URI */ int port; /* Port number from URI */ http_uri_status_t uri_status; /* Status of URI separation */ http_addrlist_t *addrlist, /* Address list */ *addr; /* Current address */ off_t length, total; /* Length and total bytes */ time_t start, current; /* Start and end time */ static const char * const uri_status_strings[] = { "HTTP_URI_OVERFLOW", "HTTP_URI_BAD_ARGUMENTS", "HTTP_URI_BAD_RESOURCE", "HTTP_URI_BAD_PORT", "HTTP_URI_BAD_HOSTNAME", "HTTP_URI_BAD_USERNAME", "HTTP_URI_BAD_SCHEME", "HTTP_URI_BAD_URI", "HTTP_URI_OK", "HTTP_URI_MISSING_SCHEME", "HTTP_URI_UNKNOWN_SCHEME", "HTTP_URI_MISSING_RESOURCE" }; /* * Do API tests if we don't have a URL on the command-line... */ if (argc == 1) { failures = 0; /* * httpGetDateString()/httpGetDateTime() */ fputs("httpGetDateString()/httpGetDateTime(): ", stdout); start = time(NULL); strcpy(buffer, httpGetDateString(start)); current = httpGetDateTime(buffer); i = (int)(current - start); if (i < 0) i = -i; if (!i) puts("PASS"); else { failures ++; puts("FAIL"); printf(" Difference is %d seconds, %02d:%02d:%02d...\n", i, i / 3600, (i / 60) % 60, i % 60); printf(" httpGetDateString(%d) returned \"%s\"\n", (int)start, buffer); printf(" httpGetDateTime(\"%s\") returned %d\n", buffer, (int)current); printf(" httpGetDateString(%d) returned \"%s\"\n", (int)current, httpGetDateString(current)); } /* * httpDecode64_2()/httpEncode64_2() */ fputs("httpDecode64_2()/httpEncode64_2(): ", stdout); for (i = 0, j = 0; i < (int)(sizeof(base64_tests) / sizeof(base64_tests[0])); i ++) { httpEncode64_2(encode, sizeof(encode), base64_tests[i][0], strlen(base64_tests[i][0])); decodelen = (int)sizeof(decode); httpDecode64_2(decode, &decodelen, base64_tests[i][1]); if (strcmp(decode, base64_tests[i][0])) { failures ++; if (j) { puts("FAIL"); j = 1; } printf(" httpDecode64_2() returned \"%s\", expected \"%s\"...\n", decode, base64_tests[i][0]); } if (strcmp(encode, base64_tests[i][1])) { failures ++; if (j) { puts("FAIL"); j = 1; } printf(" httpEncode64_2() returned \"%s\", expected \"%s\"...\n", encode, base64_tests[i][1]); } } if (!j) puts("PASS"); /* * httpGetHostname() */ fputs("httpGetHostname(): ", stdout); if (httpGetHostname(NULL, hostname, sizeof(hostname))) printf("PASS (%s)\n", hostname); else { failures ++; puts("FAIL"); } /* * httpAddrGetList() */ printf("httpAddrGetList(%s): ", hostname); addrlist = httpAddrGetList(hostname, AF_UNSPEC, NULL); if (addrlist) { for (i = 0, addr = addrlist; addr; i ++, addr = addr->next) { char numeric[1024]; /* Numeric IP address */ httpAddrString(&(addr->addr), numeric, sizeof(numeric)); if (!strcmp(numeric, "UNKNOWN")) break; } if (addr) printf("FAIL (bad address for %s)\n", hostname); else printf("PASS (%d address(es) for %s)\n", i, hostname); httpAddrFreeList(addrlist); } else { failures ++; puts("FAIL"); } /* * Test httpSeparateURI()... */ fputs("httpSeparateURI(): ", stdout); for (i = 0, j = 0; i < (int)(sizeof(uri_tests) / sizeof(uri_tests[0])); i ++) { uri_status = httpSeparateURI(HTTP_URI_CODING_MOST, uri_tests[i].uri, scheme, sizeof(scheme), username, sizeof(username), hostname, sizeof(hostname), &port, resource, sizeof(resource)); if (uri_status != uri_tests[i].result || strcmp(scheme, uri_tests[i].scheme) || strcmp(username, uri_tests[i].username) || strcmp(hostname, uri_tests[i].hostname) || port != uri_tests[i].port || strcmp(resource, uri_tests[i].resource)) { failures ++; if (!j) { puts("FAIL"); j = 1; } printf(" \"%s\":\n", uri_tests[i].uri); if (uri_status != uri_tests[i].result) printf(" Returned %s instead of %s\n", uri_status_strings[uri_status + 8], uri_status_strings[uri_tests[i].result + 8]); if (strcmp(scheme, uri_tests[i].scheme)) printf(" Scheme \"%s\" instead of \"%s\"\n", scheme, uri_tests[i].scheme); if (strcmp(username, uri_tests[i].username)) printf(" Username \"%s\" instead of \"%s\"\n", username, uri_tests[i].username); if (strcmp(hostname, uri_tests[i].hostname)) printf(" Hostname \"%s\" instead of \"%s\"\n", hostname, uri_tests[i].hostname); if (port != uri_tests[i].port) printf(" Port %d instead of %d\n", port, uri_tests[i].port); if (strcmp(resource, uri_tests[i].resource)) printf(" Resource \"%s\" instead of \"%s\"\n", resource, uri_tests[i].resource); } } if (!j) printf("PASS (%d URIs tested)\n", (int)(sizeof(uri_tests) / sizeof(uri_tests[0]))); /* * Test httpAssembleURI()... */ fputs("httpAssembleURI(): ", stdout); for (i = 0, j = 0, k = 0; i < (int)(sizeof(uri_tests) / sizeof(uri_tests[0])); i ++) if (uri_tests[i].result == HTTP_URI_OK && !strstr(uri_tests[i].uri, "%64") && strstr(uri_tests[i].uri, "//")) { k ++; uri_status = httpAssembleURI(HTTP_URI_CODING_MOST, buffer, sizeof(buffer), uri_tests[i].scheme, uri_tests[i].username, uri_tests[i].hostname, uri_tests[i].assemble_port, uri_tests[i].resource); if (uri_status != HTTP_URI_OK) { failures ++; if (!j) { puts("FAIL"); j = 1; } printf(" \"%s\": %s\n", uri_tests[i].uri, uri_status_strings[uri_status + 8]); } else if (strcmp(buffer, uri_tests[i].uri)) { failures ++; if (!j) { puts("FAIL"); j = 1; } printf(" \"%s\": assembled = \"%s\"\n", uri_tests[i].uri, buffer); } } if (!j) printf("PASS (%d URIs tested)\n", k); /* * Show a summary and return... */ if (failures) printf("\n%d TESTS FAILED!\n", failures); else puts("\nALL TESTS PASSED!"); return (failures); } /* * Test HTTP GET requests... */ http = NULL; out = stdout; for (i = 1; i < argc; i ++) { if (!strcmp(argv[i], "-o")) { i ++; if (i >= argc) break; out = fopen(argv[i], "wb"); continue; } httpSeparateURI(HTTP_URI_CODING_MOST, argv[i], scheme, sizeof(scheme), username, sizeof(username), hostname, sizeof(hostname), &port, resource, sizeof(resource)); http = httpConnectEncrypt(hostname, port, HTTP_ENCRYPT_IF_REQUESTED); if (http == NULL) { perror(hostname); continue; } printf("Requesting file \"%s\"...\n", resource); httpClearFields(http); httpSetField(http, HTTP_FIELD_ACCEPT_LANGUAGE, "en"); httpGet(http, resource); while ((status = httpUpdate(http)) == HTTP_CONTINUE); if (status == HTTP_OK) puts("GET OK:"); else printf("GET failed with status %d...\n", status); start = time(NULL); length = httpGetLength2(http); total = 0; while ((bytes = httpRead2(http, buffer, sizeof(buffer))) > 0) { total += bytes; fwrite(buffer, bytes, 1, out); if (out != stdout) { current = time(NULL); if (current == start) current ++; printf("\r" CUPS_LLFMT "/" CUPS_LLFMT " bytes (" CUPS_LLFMT " bytes/sec) ", CUPS_LLCAST total, CUPS_LLCAST length, CUPS_LLCAST (total / (current - start))); fflush(stdout); } } } puts("Closing connection to server..."); httpClose(http); if (out != stdout) fclose(out); return (0); }