static void updateCurrentDate() { Http *http; MprTicks diff; http = HTTP; http->now = mprGetTicks(); diff = http->now - http->currentTime; if (diff <= TPS || diff >= TPS) { /* Optimize and only update the string date representation once per second */ http->currentTime = http->now; http->currentDate = httpGetDateString(NULL); } }
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); }
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); }
static http_status_t /* O - Status of request */ get_cupsd_conf( http_t *http, /* I - Connection to server */ _cups_globals_t *cg, /* I - Global data */ time_t last_update, /* I - Last update time for file */ char *name, /* I - Filename buffer */ size_t namesize, /* I - Size of filename buffer */ int *remote) /* O - Remote file? */ { int fd; /* Temporary file descriptor */ #ifndef _WIN32 struct stat info; /* cupsd.conf file information */ #endif /* _WIN32 */ http_status_t status; /* Status of getting cupsd.conf */ char host[HTTP_MAX_HOST]; /* Hostname for connection */ /* * See if we already have the data we need... */ httpGetHostname(http, host, sizeof(host)); if (_cups_strcasecmp(cg->cupsd_hostname, host)) invalidate_cupsd_cache(cg); snprintf(name, namesize, "%s/cupsd.conf", cg->cups_serverroot); *remote = 0; #ifndef _WIN32 if (!_cups_strcasecmp(host, "localhost") && !access(name, R_OK)) { /* * Read the local file rather than using HTTP... */ if (stat(name, &info)) { char message[1024]; /* Message string */ snprintf(message, sizeof(message), _cupsLangString(cupsLangDefault(), _("stat of %s failed: %s")), name, strerror(errno)); _cupsSetError(IPP_STATUS_ERROR_INTERNAL, message, 0); *name = '\0'; return (HTTP_STATUS_SERVER_ERROR); } else if (last_update && info.st_mtime <= last_update) status = HTTP_STATUS_NOT_MODIFIED; else status = HTTP_STATUS_OK; } else #endif /* !_WIN32 */ { /* * Read cupsd.conf via a HTTP GET request... */ if ((fd = cupsTempFd(name, (int)namesize)) < 0) { *name = '\0'; _cupsSetError(IPP_STATUS_ERROR_INTERNAL, NULL, 0); invalidate_cupsd_cache(cg); return (HTTP_STATUS_SERVER_ERROR); } *remote = 1; httpClearFields(http); if (last_update) httpSetField(http, HTTP_FIELD_IF_MODIFIED_SINCE, httpGetDateString(last_update)); status = cupsGetFd(http, "/admin/conf/cupsd.conf", fd); close(fd); if (status != HTTP_STATUS_OK) { unlink(name); *name = '\0'; } } return (status); }
static void openFileHandler(HttpQueue *q) { HttpRx *rx; HttpTx *tx; HttpRoute *route; HttpConn *conn; MprPath *info; char *date; conn = q->conn; tx = conn->tx; rx = conn->rx; route = rx->route; info = &tx->fileInfo; if (rx->flags & (HTTP_PUT | HTTP_DELETE)) { if (!(route->flags & HTTP_ROUTE_PUT_DELETE_METHODS)) { httpError(q->conn, HTTP_CODE_BAD_METHOD, "The \"%s\" method is not supported by file handler", rx->method); } } else { if (rx->flags & (HTTP_GET | HTTP_HEAD | HTTP_POST)) { if (!(info->valid || info->isDir)) { if (rx->referrer) { mprLog(2, "fileHandler: Cannot find filename %s from referrer %s", tx->filename, rx->referrer); } else { mprLog(2, "fileHandler: Cannot find filename %s", tx->filename); } httpError(conn, HTTP_CODE_NOT_FOUND, "Cannot find %s", rx->uri); } else if (info->valid) { if (!tx->etag) { /* Set the etag for caching in the client */ tx->etag = sfmt("\"%Lx-%Lx-%Lx\"", (int64) info->inode, (int64) info->size, (int64) info->mtime); } } } if (rx->flags & (HTTP_GET | HTTP_HEAD | HTTP_POST) && !conn->error) { if (tx->fileInfo.valid && tx->fileInfo.mtime) { // TODO - OPT could cache this date = httpGetDateString(&tx->fileInfo); httpSetHeader(conn, "Last-Modified", date); } if (httpContentNotModified(conn)) { httpSetStatus(conn, HTTP_CODE_NOT_MODIFIED); httpOmitBody(conn); tx->length = -1; } if (!tx->fileInfo.isReg && !tx->fileInfo.isLink) { httpError(conn, HTTP_CODE_NOT_FOUND, "Cannot locate document: %s", rx->uri); } else if (tx->fileInfo.size > conn->limits->transmissionBodySize) { httpError(conn, HTTP_ABORT | HTTP_CODE_REQUEST_TOO_LARGE, "Http transmission aborted. File size exceeds max body of %,Ld bytes", conn->limits->transmissionBodySize); } else if (!(tx->connector == conn->http->sendConnector)) { /* If using the net connector, open the file if a body must be sent with the response. The file will be automatically closed when the request completes. */ if (!(tx->flags & HTTP_TX_NO_BODY)) { tx->file = mprOpenFile(tx->filename, O_RDONLY | O_BINARY, 0); if (tx->file == 0) { if (rx->referrer) { httpError(conn, HTTP_CODE_NOT_FOUND, "Cannot open document: %s from %s", tx->filename, rx->referrer); } else { httpError(conn, HTTP_CODE_NOT_FOUND, "Cannot open document: %s from %s", tx->filename); } } } } } else if (rx->flags & (HTTP_OPTIONS | HTTP_TRACE)) { if (route->flags & HTTP_ROUTE_PUT_DELETE_METHODS) { httpHandleOptionsTrace(q->conn, "DELETE,GET,HEAD,POST,PUT"); } else { httpHandleOptionsTrace(q->conn, "GET,HEAD,POST"); } } } }
size_t /* O - Total size of credentials string */ httpCredentialsString( cups_array_t *credentials, /* I - Credentials */ char *buffer, /* I - Buffer or @code NULL@ */ size_t bufsize) /* I - Size of buffer */ { http_credential_t *first; /* First certificate */ gnutls_x509_crt_t cert; /* Certificate */ DEBUG_printf(("httpCredentialsString(credentials=%p, buffer=%p, bufsize=" CUPS_LLFMT ")", credentials, buffer, CUPS_LLCAST bufsize)); if (!buffer) return (0); if (buffer && bufsize > 0) *buffer = '\0'; if ((first = (http_credential_t *)cupsArrayFirst(credentials)) != NULL && (cert = http_gnutls_create_credential(first)) != NULL) { char name[256]; /* Common name associated with cert */ size_t namelen; /* Length of name */ time_t expiration; /* Expiration date of cert */ _cups_md5_state_t md5_state; /* MD5 state */ unsigned char md5_digest[16]; /* MD5 result */ namelen = sizeof(name) - 1; if (gnutls_x509_crt_get_dn_by_oid(cert, GNUTLS_OID_X520_COMMON_NAME, 0, 0, name, &namelen) >= 0) name[namelen] = '\0'; else strlcpy(name, "unknown", sizeof(name)); expiration = gnutls_x509_crt_get_expiration_time(cert); _cupsMD5Init(&md5_state); _cupsMD5Append(&md5_state, first->data, (int)first->datalen); _cupsMD5Finish(&md5_state, md5_digest); snprintf(buffer, bufsize, "%s / %s / %02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X", name, httpGetDateString(expiration), md5_digest[0], md5_digest[1], md5_digest[2], md5_digest[3], md5_digest[4], md5_digest[5], md5_digest[6], md5_digest[7], md5_digest[8], md5_digest[9], md5_digest[10], md5_digest[11], md5_digest[12], md5_digest[13], md5_digest[14], md5_digest[15]); gnutls_x509_crt_deinit(cert); } DEBUG_printf(("1httpCredentialsString: Returning \"%s\".", buffer)); return (strlen(buffer)); }
void email_message(const char *to, /* I - Recipient of message */ const char *subject, /* I - Subject of message */ const char *text) /* I - Text of message */ { cups_file_t *fp; /* Pipe/socket to mail server */ const char *nl; /* Newline to use */ char response[1024]; /* SMTP response buffer */ /* * Connect to the mail server... */ if (mailtoSendmail[0]) { /* * Use the sendmail command... */ fp = pipe_sendmail(to); if (!fp) return; nl = "\n"; } else { /* * Use an SMTP server... */ char hostbuf[1024]; /* Local hostname */ if (strchr(mailtoSMTPServer, ':')) fp = cupsFileOpen(mailtoSMTPServer, "s"); else { char spec[1024]; /* Host:service spec */ snprintf(spec, sizeof(spec), "%s:smtp", mailtoSMTPServer); fp = cupsFileOpen(spec, "s"); } if (!fp) { fprintf(stderr, "ERROR: Unable to connect to SMTP server \"%s\"!\n", mailtoSMTPServer); return; } fprintf(stderr, "DEBUG: Connected to \"%s\"...\n", mailtoSMTPServer); cupsFilePrintf(fp, "HELO %s\r\n", httpGetHostname(NULL, hostbuf, sizeof(hostbuf))); fprintf(stderr, "DEBUG: >>> HELO %s\n", hostbuf); if (!cupsFileGets(fp, response, sizeof(response)) || atoi(response) >= 500) goto smtp_error; fprintf(stderr, "DEBUG: <<< %s\n", response); cupsFilePrintf(fp, "MAIL FROM:%s\r\n", mailtoFrom); fprintf(stderr, "DEBUG: >>> MAIL FROM:%s\n", mailtoFrom); if (!cupsFileGets(fp, response, sizeof(response)) || atoi(response) >= 500) goto smtp_error; fprintf(stderr, "DEBUG: <<< %s\n", response); cupsFilePrintf(fp, "RCPT TO:%s\r\n", to); fprintf(stderr, "DEBUG: >>> RCPT TO:%s\n", to); if (!cupsFileGets(fp, response, sizeof(response)) || atoi(response) >= 500) goto smtp_error; fprintf(stderr, "DEBUG: <<< %s\n", response); cupsFilePuts(fp, "DATA\r\n"); fputs("DEBUG: DATA\n", stderr); if (!cupsFileGets(fp, response, sizeof(response)) || atoi(response) >= 500) goto smtp_error; fprintf(stderr, "DEBUG: <<< %s\n", response); nl = "\r\n"; } /* * Send the message... */ cupsFilePrintf(fp, "Date: %s%s", httpGetDateString(time(NULL)), nl); cupsFilePrintf(fp, "From: %s%s", mailtoFrom, nl); cupsFilePrintf(fp, "Subject: %s %s%s", mailtoSubject, subject, nl); if (mailtoReplyTo[0]) { cupsFilePrintf(fp, "Sender: %s%s", mailtoReplyTo, nl); cupsFilePrintf(fp, "Reply-To: %s%s", mailtoReplyTo, nl); } cupsFilePrintf(fp, "To: %s%s", to, nl); if (mailtoCc[0]) cupsFilePrintf(fp, "Cc: %s%s", mailtoCc, nl); cupsFilePrintf(fp, "Content-Type: text/plain%s", nl); cupsFilePuts(fp, nl); cupsFilePrintf(fp, "%s%s", text, nl); cupsFilePrintf(fp, ".\n", nl); /* * Close the connection to the mail server... */ if (mailtoSendmail[0]) { /* * Close the pipe and wait for the sendmail command to finish... */ int status; /* Exit status */ cupsFileClose(fp); if (wait(&status)) status = errno << 8; /* * Report any non-zero status... */ if (status) { if (WIFEXITED(status)) fprintf(stderr, "ERROR: Sendmail command returned status %d!\n", WEXITSTATUS(status)); else fprintf(stderr, "ERROR: Sendmail command crashed on signal %d!\n", WTERMSIG(status)); } } else { /* * Finish up the SMTP submission and close the connection... */ if (!cupsFileGets(fp, response, sizeof(response)) || atoi(response) >= 500) goto smtp_error; fprintf(stderr, "DEBUG: <<< %s\n", response); /* * Process SMTP errors here... */ smtp_error: cupsFilePuts(fp, "QUIT\r\n"); fputs("DEBUG: QUIT\n", stderr); if (!cupsFileGets(fp, response, sizeof(response)) || atoi(response) >= 500) goto smtp_error; fprintf(stderr, "DEBUG: <<< %s\n", response); cupsFileClose(fp); fprintf(stderr, "DEBUG: Closed connection to \"%s\"...\n", mailtoSMTPServer); } }
http_status_t /* O - HTTP status */ cupsGetPPD3(http_t *http, /* I - HTTP connection or @code CUPS_HTTP_DEFAULT@ */ const char *name, /* I - Destination name */ time_t *modtime, /* IO - Modification time */ char *buffer, /* I - Filename buffer */ size_t bufsize) /* I - Size of filename buffer */ { int http_port; /* Port number */ char http_hostname[HTTP_MAX_HOST]; /* Hostname associated with connection */ http_t *http2; /* Alternate HTTP connection */ int fd; /* PPD file */ char localhost[HTTP_MAX_URI],/* Local hostname */ hostname[HTTP_MAX_URI], /* Hostname */ resource[HTTP_MAX_URI]; /* Resource name */ int port; /* Port number */ http_status_t status; /* HTTP status from server */ char tempfile[1024] = ""; /* Temporary filename */ _cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */ /* * Range check input... */ DEBUG_printf(("cupsGetPPD3(http=%p, name=\"%s\", modtime=%p(%d), buffer=%p, " "bufsize=%d)", http, name, modtime, modtime ? (int)*modtime : 0, buffer, (int)bufsize)); if (!name) { _cupsSetError(IPP_INTERNAL_ERROR, _("No printer name"), 1); return (HTTP_NOT_ACCEPTABLE); } if (!modtime) { _cupsSetError(IPP_INTERNAL_ERROR, _("No modification time"), 1); return (HTTP_NOT_ACCEPTABLE); } if (!buffer || bufsize <= 1) { _cupsSetError(IPP_INTERNAL_ERROR, _("Bad filename buffer"), 1); return (HTTP_NOT_ACCEPTABLE); } #ifndef WIN32 /* * See if the PPD file is available locally... */ if (!cg->servername[0]) cupsServer(); if (!_cups_strcasecmp(cg->servername, "localhost")) { char ppdname[1024]; /* PPD filename */ struct stat ppdinfo; /* PPD file information */ snprintf(ppdname, sizeof(ppdname), "%s/ppd/%s.ppd", cg->cups_serverroot, name); if (!stat(ppdname, &ppdinfo)) { /* * OK, the file exists, use it! */ if (buffer[0]) { unlink(buffer); if (symlink(ppdname, buffer) && errno != EEXIST) { _cupsSetError(IPP_INTERNAL_ERROR, NULL, 0); return (HTTP_SERVER_ERROR); } } else { int tries; /* Number of tries */ const char *tmpdir; /* TMPDIR environment variable */ struct timeval curtime; /* Current time */ /* * Previously we put root temporary files in the default CUPS temporary * directory under /var/spool/cups. However, since the scheduler cleans * out temporary files there and runs independently of the user apps, we * don't want to use it unless specifically told to by cupsd. */ if ((tmpdir = getenv("TMPDIR")) == NULL) # ifdef __APPLE__ tmpdir = "/private/tmp"; /* /tmp is a symlink to /private/tmp */ # else tmpdir = "/tmp"; # endif /* __APPLE__ */ /* * Make the temporary name using the specified directory... */ tries = 0; do { /* * Get the current time of day... */ gettimeofday(&curtime, NULL); /* * Format a string using the hex time values... */ snprintf(buffer, bufsize, "%s/%08lx%05lx", tmpdir, (unsigned long)curtime.tv_sec, (unsigned long)curtime.tv_usec); /* * Try to make a symlink... */ if (!symlink(ppdname, buffer)) break; tries ++; } while (tries < 1000); if (tries >= 1000) { _cupsSetError(IPP_INTERNAL_ERROR, NULL, 0); return (HTTP_SERVER_ERROR); } } if (*modtime >= ppdinfo.st_mtime) return (HTTP_NOT_MODIFIED); else { *modtime = ppdinfo.st_mtime; return (HTTP_OK); } } } #endif /* !WIN32 */ /* * Try finding a printer URI for this printer... */ if (!http) if ((http = _cupsConnect()) == NULL) return (HTTP_SERVICE_UNAVAILABLE); if (!cups_get_printer_uri(http, name, hostname, sizeof(hostname), &port, resource, sizeof(resource), 0)) return (HTTP_NOT_FOUND); DEBUG_printf(("2cupsGetPPD3: Printer hostname=\"%s\", port=%d", hostname, port)); /* * Remap local hostname to localhost... */ httpGetHostname(NULL, localhost, sizeof(localhost)); DEBUG_printf(("2cupsGetPPD3: Local hostname=\"%s\"", localhost)); if (!_cups_strcasecmp(localhost, hostname)) strcpy(hostname, "localhost"); /* * Get the hostname and port number we are connected to... */ httpGetHostname(http, http_hostname, sizeof(http_hostname)); http_port = _httpAddrPort(http->hostaddr); DEBUG_printf(("2cupsGetPPD3: Connection hostname=\"%s\", port=%d", http_hostname, http_port)); /* * Reconnect to the correct server as needed... */ if (!_cups_strcasecmp(http_hostname, hostname) && port == http_port) http2 = http; else if ((http2 = httpConnectEncrypt(hostname, port, cupsEncryption())) == NULL) { DEBUG_puts("1cupsGetPPD3: Unable to connect to server"); return (HTTP_SERVICE_UNAVAILABLE); } /* * Get a temp file... */ if (buffer[0]) fd = open(buffer, O_CREAT | O_TRUNC | O_WRONLY, 0600); else fd = cupsTempFd(tempfile, sizeof(tempfile)); if (fd < 0) { /* * Can't open file; close the server connection and return NULL... */ _cupsSetError(IPP_INTERNAL_ERROR, NULL, 0); if (http2 != http) httpClose(http2); return (HTTP_SERVER_ERROR); } /* * And send a request to the HTTP server... */ strlcat(resource, ".ppd", sizeof(resource)); if (*modtime > 0) httpSetField(http2, HTTP_FIELD_IF_MODIFIED_SINCE, httpGetDateString(*modtime)); status = cupsGetFd(http2, resource, fd); close(fd); /* * See if we actually got the file or an error... */ if (status == HTTP_OK) { *modtime = httpGetDateTime(httpGetField(http2, HTTP_FIELD_DATE)); if (tempfile[0]) strlcpy(buffer, tempfile, bufsize); } else if (status != HTTP_NOT_MODIFIED) { _cupsSetHTTPError(status); if (buffer[0]) unlink(buffer); else if (tempfile[0]) unlink(tempfile); } else if (tempfile[0]) unlink(tempfile); if (http2 != http) httpClose(http2); /* * Return the PPD file... */ DEBUG_printf(("1cupsGetPPD3: Returning status %d", status)); return (status); }
static int openFileHandler(HttpQueue *q) { HttpRx *rx; HttpTx *tx; HttpConn *conn; MprPath *info; char *date, dbuf[16]; MprHash *dateCache; conn = q->conn; tx = conn->tx; rx = conn->rx; info = &tx->fileInfo; if (conn->error) { return MPR_ERR_CANT_OPEN; } if (rx->flags & (HTTP_GET | HTTP_HEAD | HTTP_POST)) { if (!(info->valid || info->isDir)) { httpError(conn, HTTP_CODE_NOT_FOUND, "Cannot find document"); return 0; } if (!tx->etag) { /* Set the etag for caching in the client */ tx->etag = sfmt("\"%llx-%llx-%llx\"", (int64) info->inode, (int64) info->size, (int64) info->mtime); } if (info->mtime) { dateCache = conn->http->dateCache; if ((date = mprLookupKey(dateCache, itosbuf(dbuf, sizeof(dbuf), (int64) info->mtime, 10))) == 0) { if (!dateCache || mprGetHashLength(dateCache) > 128) { conn->http->dateCache = dateCache = mprCreateHash(0, 0); } date = httpGetDateString(&tx->fileInfo); mprAddKey(dateCache, itosbuf(dbuf, sizeof(dbuf), (int64) info->mtime, 10), date); } httpSetHeaderString(conn, "Last-Modified", date); } if (httpContentNotModified(conn)) { httpSetStatus(conn, HTTP_CODE_NOT_MODIFIED); httpOmitBody(conn); tx->length = -1; } if (!tx->fileInfo.isReg && !tx->fileInfo.isLink) { httpTrace(conn, "request.document.error", "error", "msg: 'Document is not a regular file', filename: '%s'", tx->filename); httpError(conn, HTTP_CODE_NOT_FOUND, "Cannot serve document"); } else if (tx->fileInfo.size > conn->limits->transmissionBodySize) { httpError(conn, HTTP_ABORT | HTTP_CODE_REQUEST_TOO_LARGE, "Http transmission aborted. File size exceeds max body of %'lld bytes", conn->limits->transmissionBodySize); } else if (!(tx->connector == conn->http->sendConnector)) { /* If using the net connector, open the file if a body must be sent with the response. The file will be automatically closed when the request completes. */ if (!(tx->flags & HTTP_TX_NO_BODY)) { tx->file = mprOpenFile(tx->filename, O_RDONLY | O_BINARY, 0); if (tx->file == 0) { if (rx->referrer && *rx->referrer) { httpTrace(conn, "request.document.error", "error", "msg: 'Cannot open document', filename: '%s', referrer: '%s'", tx->filename, rx->referrer); } else { httpTrace(conn, "request.document.error", "error", "msg: 'Cannot open document', filename: '%s'", tx->filename); } httpError(conn, HTTP_CODE_NOT_FOUND, "Cannot open document"); } } } } else if (rx->flags & (HTTP_DELETE | HTTP_OPTIONS | HTTP_PUT)) { ; } else { httpError(conn, HTTP_CODE_BAD_METHOD, "Unsupported method"); } return 0; }