static char * /* I - Printer name or NULL */ cups_connect(const char *name, /* I - Destination (printer[@host]) */ char *printer, /* O - Printer name [HTTP_MAX_URI] */ char *hostname) /* O - Hostname [HTTP_MAX_URI] */ { char hostbuf[HTTP_MAX_URI], /* Name of host */ http_hostname[HTTP_MAX_HOST]; /* Hostname associated with connection */ _cups_globals_t *cg = _cupsGlobals();/* Pointer to library globals */ DEBUG_printf(("cups_connect(\"%s\", %p, %p)\n", name, printer, hostname)); if (name == NULL) { _cupsSetError(IPP_BAD_REQUEST, NULL); return (NULL); } /* * All jobs are now queued to cupsServer() to avoid hostname * resolution problems and to ensure that the user sees all * locally queued jobs locally. */ strlcpy(hostbuf, cupsServer(), sizeof(hostbuf)); httpGetHostname(cg->http, http_hostname, sizeof(http_hostname)); if (hostname != NULL) strlcpy(hostname, hostbuf, HTTP_MAX_URI); else hostname = hostbuf; if (printer != NULL) strlcpy(printer, name, HTTP_MAX_URI); else printer = (char *)name; if (cg->http != NULL) { if (!strcasecmp(http_hostname, hostname)) return (printer); httpClose(cg->http); } DEBUG_printf(("connecting to %s on port %d...\n", hostname, ippPort())); if ((cg->http = httpConnectEncrypt(hostname, ippPort(), cupsEncryption())) == NULL) { DEBUG_puts("Unable to connect to server!"); _cupsSetError(IPP_SERVICE_UNAVAILABLE, strerror(errno)); return (NULL); } else return (printer); }
static int /* O - 1 on success, 0 on failure */ cups_get_printer_uri( http_t *http, /* I - HTTP connection */ const char *name, /* I - Name of printer or class */ char *host, /* I - Hostname buffer */ int hostsize, /* I - Size of hostname buffer */ int *port, /* O - Port number */ char *resource, /* I - Resource buffer */ int resourcesize, /* I - Size of resource buffer */ int depth) /* I - Depth of query */ { int i; /* Looping var */ int http_port; /* Port number */ http_t *http2; /* Alternate HTTP connection */ ipp_t *request, /* IPP request */ *response; /* IPP response */ ipp_attribute_t *attr; /* Current attribute */ char uri[HTTP_MAX_URI], /* printer-uri attribute */ scheme[HTTP_MAX_URI], /* Scheme name */ username[HTTP_MAX_URI], /* Username:password */ classname[255], /* Temporary class name */ http_hostname[HTTP_MAX_HOST]; /* Hostname associated with connection */ static const char * const requested_attrs[] = { /* Requested attributes */ "printer-uri-supported", "printer-type", "member-uris" }; DEBUG_printf(("cups_get_printer_uri(http=%p, name=\"%s\", host=%p, " "hostsize=%d, resource=%p, resourcesize=%d, depth=%d)\n", http, name ? name : "(null)", host, hostsize, resource, resourcesize, depth)); /* * Setup the printer URI... */ if (httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL, "localhost", 0, "/printers/%s", name) != HTTP_URI_OK) { _cupsSetError(IPP_INTERNAL_ERROR, "Unable to create printer-uri!"); *host = '\0'; *resource = '\0'; return (0); } DEBUG_printf(("cups_get_printer_uri: printer-uri=\"%s\"\n", uri)); /* * Get the hostname and port number we are connected to... */ httpGetHostname(http, http_hostname, sizeof(http_hostname)); #ifdef AF_INET6 if (http->hostaddr->addr.sa_family == AF_INET6) http_port = ntohs(http->hostaddr->ipv6.sin6_port); else #endif /* AF_INET6 */ if (http->hostaddr->addr.sa_family == AF_INET) http_port = ntohs(http->hostaddr->ipv4.sin_port); else http_port = ippPort(); /* * Build an IPP_GET_PRINTER_ATTRIBUTES request, which requires the following * attributes: * * attributes-charset * attributes-natural-language * printer-uri * requested-attributes */ request = ippNewRequest(IPP_GET_PRINTER_ATTRIBUTES); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, uri); ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requested-attributes", sizeof(requested_attrs) / sizeof(requested_attrs[0]), NULL, requested_attrs); /* * Do the request and get back a response... */ if ((response = cupsDoRequest(http, request, "/")) != NULL) { if ((attr = ippFindAttribute(response, "member-uris", IPP_TAG_URI)) != NULL) { /* * Get the first actual printer name in the class... */ for (i = 0; i < attr->num_values; i ++) { httpSeparateURI(HTTP_URI_CODING_ALL, attr->values[i].string.text, scheme, sizeof(scheme), username, sizeof(username), host, hostsize, port, resource, resourcesize); if (!strncmp(resource, "/printers/", 10)) { /* * Found a printer! */ ippDelete(response); return (1); } } /* * No printers in this class - try recursively looking for a printer, * but not more than 3 levels deep... */ if (depth < 3) { for (i = 0; i < attr->num_values; i ++) { httpSeparateURI(HTTP_URI_CODING_ALL, attr->values[i].string.text, scheme, sizeof(scheme), username, sizeof(username), host, hostsize, port, resource, resourcesize); if (!strncmp(resource, "/classes/", 9)) { /* * Found a class! Connect to the right server... */ if (!strcasecmp(http_hostname, host) && *port == http_port) http2 = http; else if ((http2 = httpConnectEncrypt(host, *port, cupsEncryption())) == NULL) { DEBUG_puts("Unable to connect to server!"); continue; } /* * Look up printers on that server... */ strlcpy(classname, resource + 9, sizeof(classname)); cups_get_printer_uri(http2, classname, host, hostsize, port, resource, resourcesize, depth + 1); /* * Close the connection as needed... */ if (http2 != http) httpClose(http2); if (*host) return (1); } } } } else if ((attr = ippFindAttribute(response, "printer-uri-supported", IPP_TAG_URI)) != NULL) { httpSeparateURI(HTTP_URI_CODING_ALL, attr->values[0].string.text, scheme, sizeof(scheme), username, sizeof(username), host, hostsize, port, resource, resourcesize); ippDelete(response); if (!strncmp(resource, "/classes/", 9)) { _cupsSetError(IPP_INTERNAL_ERROR, _("No printer-uri found for class!")); *host = '\0'; *resource = '\0'; return (0); } return (1); } ippDelete(response); } if (cupsLastError() != IPP_NOT_FOUND) _cupsSetError(IPP_INTERNAL_ERROR, _("No printer-uri found!")); *host = '\0'; *resource = '\0'; return (0); }
static void cups_create_localizations( http_t *http, /* I - Connection to destination */ cups_dinfo_t *dinfo) /* I - Destination informations */ { http_t *http2; /* Connection for strings file */ http_status_t status; /* Request status */ ipp_attribute_t *attr; /* "printer-strings-uri" attribute */ char scheme[32], /* URI scheme */ userpass[256], /* Username/password info */ hostname[256], /* Hostname */ resource[1024], /* Resource */ http_hostname[256], /* Hostname of connection */ tempfile[1024]; /* Temporary filename */ int port; /* Port number */ http_encryption_t encryption; /* Encryption to use */ cups_file_t *temp; /* Temporary file */ /* * Create an empty message catalog... */ dinfo->localizations = _cupsMessageNew(NULL); /* * See if there are any localizations... */ if ((attr = ippFindAttribute(dinfo->attrs, "printer-strings-uri", IPP_TAG_URI)) == NULL) { /* * Nope... */ DEBUG_puts("4cups_create_localizations: No printer-strings-uri (uri) " "value."); return; /* Nope */ } /* * Pull apart the URI and determine whether we need to try a different * server... */ if (httpSeparateURI(HTTP_URI_CODING_ALL, attr->values[0].string.text, scheme, sizeof(scheme), userpass, sizeof(userpass), hostname, sizeof(hostname), &port, resource, sizeof(resource)) < HTTP_URI_OK) { DEBUG_printf(("4cups_create_localizations: Bad printer-strings-uri value " "\"%s\".", attr->values[0].string.text)); return; } httpGetHostname(http, http_hostname, sizeof(http_hostname)); if (!_cups_strcasecmp(http_hostname, hostname) && port == _httpAddrPort(http->hostaddr)) { /* * Use the same connection... */ http2 = http; } else { /* * Connect to the alternate host... */ if (!strcmp(scheme, "https")) encryption = HTTP_ENCRYPT_ALWAYS; else encryption = HTTP_ENCRYPT_IF_REQUESTED; if ((http2 = httpConnectEncrypt(hostname, port, encryption)) == NULL) { DEBUG_printf(("4cups_create_localizations: Unable to connect to " "%s:%d: %s", hostname, port, cupsLastErrorString())); return; } } /* * Get a temporary file... */ if ((temp = cupsTempFile2(tempfile, sizeof(tempfile))) == NULL) { DEBUG_printf(("4cups_create_localizations: Unable to create temporary " "file: %s", cupsLastErrorString())); if (http2 != http) httpClose(http2); return; } status = cupsGetFd(http2, resource, cupsFileNumber(temp)); DEBUG_printf(("4cups_create_localizations: GET %s = %s", resource, httpStatus(status))); if (status == HTTP_OK) { /* * Got the file, read it... */ char buffer[8192], /* Message buffer */ *id, /* ID string */ *str; /* Translated message */ _cups_message_t *m; /* Current message */ lseek(cupsFileNumber(temp), 0, SEEK_SET); while (cups_read_strings(temp, buffer, sizeof(buffer), &id, &str)) { if ((m = malloc(sizeof(_cups_message_t))) == NULL) break; m->id = strdup(id); m->str = strdup(str); if (m->id && m->str) cupsArrayAdd(dinfo->localizations, m); else { if (m->id) free(m->id); if (m->str) free(m->str); free(m); break; } } } DEBUG_printf(("4cups_create_localizations: %d messages loaded.", cupsArrayCount(dinfo->localizations))); /* * Cleanup... */ unlink(tempfile); cupsFileClose(temp); if (http2 != http) httpClose(http2); }
static int /* O - Zero on success, non-zero on failure */ lpd_queue(const char *hostname, /* I - Host to connect to */ http_addrlist_t *addrlist, /* I - List of host addresses */ const char *printer, /* I - Printer/queue name */ int print_fd, /* I - File to print */ int snmp_fd, /* I - SNMP socket */ int mode, /* I - Print mode */ const char *user, /* I - Requesting user */ const char *title, /* I - Job title */ int copies, /* I - Number of copies */ int banner, /* I - Print LPD banner? */ int format, /* I - Format specifier */ int order, /* I - Order of data/control files */ int reserve, /* I - Reserve ports? */ int manual_copies,/* I - Do copies by hand... */ int timeout, /* I - Timeout... */ int contimeout, /* I - Connection timeout */ const char *orighost) /* I - job-originating-host-name */ { char localhost[255]; /* Local host name */ int error; /* Error number */ struct stat filestats; /* File statistics */ int lport; /* LPD connection local port */ int fd; /* LPD socket */ char control[10240], /* LPD control 'file' */ *cptr; /* Pointer into control file string */ char status; /* Status byte from command */ int delay; /* Delay for retries... */ char addrname[256]; /* Address name */ http_addrlist_t *addr; /* Socket address */ int have_supplies; /* Printer supports supply levels? */ int copy; /* Copies written */ time_t start_time; /* Time of first connect */ size_t nbytes; /* Number of bytes written */ off_t tbytes; /* Total bytes written */ char buffer[32768]; /* Output buffer */ #ifdef WIN32 DWORD tv; /* Timeout in milliseconds */ #else struct timeval tv; /* Timeout in secs and usecs */ #endif /* WIN32 */ /* * Remember when we started trying to connect to the printer... */ start_time = time(NULL); /* * Loop forever trying to print the file... */ while (!abort_job) { /* * First try to reserve a port for this connection... */ fprintf(stderr, "DEBUG: Connecting to %s:%d for printer %s\n", hostname, httpAddrPort(&(addrlist->addr)), printer); _cupsLangPrintFilter(stderr, "INFO", _("Connecting to printer.")); for (lport = reserve == RESERVE_RFC1179 ? 732 : 1024, addr = addrlist, delay = 5;; addr = addr->next) { /* * Stop if this job has been canceled... */ if (abort_job) return (CUPS_BACKEND_FAILED); /* * Choose the next priviledged port... */ if (!addr) addr = addrlist; lport --; if (lport < 721 && reserve == RESERVE_RFC1179) lport = 731; else if (lport < 1) lport = 1023; #ifdef HAVE_GETEUID if (geteuid() || !reserve) #else if (getuid() || !reserve) #endif /* HAVE_GETEUID */ { /* * Just create a regular socket... */ if ((fd = socket(addr->addr.addr.sa_family, SOCK_STREAM, 0)) < 0) { perror("DEBUG: Unable to create socket"); sleep(1); continue; } lport = 0; } else { /* * We're running as root and want to comply with RFC 1179. Reserve a * priviledged lport between 721 and 731... */ if ((fd = rresvport_af(&lport, addr->addr.addr.sa_family)) < 0) { perror("DEBUG: Unable to reserve port"); sleep(1); continue; } } /* * Connect to the printer or server... */ if (abort_job) { close(fd); return (CUPS_BACKEND_FAILED); } if (!connect(fd, &(addr->addr.addr), httpAddrLength(&(addr->addr)))) break; error = errno; close(fd); if (addr->next) continue; if (getenv("CLASS") != NULL) { /* * If the CLASS environment variable is set, the job was submitted * to a class and not to a specific queue. In this case, we want * to abort immediately so that the job can be requeued on the next * available printer in the class. */ _cupsLangPrintFilter(stderr, "INFO", _("Unable to contact printer, queuing on next " "printer in class.")); /* * Sleep 5 seconds to keep the job from requeuing too rapidly... */ sleep(5); return (CUPS_BACKEND_FAILED); } fprintf(stderr, "DEBUG: Connection error: %s\n", strerror(error)); if (error == ECONNREFUSED || error == EHOSTDOWN || error == EHOSTUNREACH) { if (contimeout && (time(NULL) - start_time) > contimeout) { _cupsLangPrintFilter(stderr, "ERROR", _("The printer is not responding.")); return (CUPS_BACKEND_FAILED); } switch (error) { case EHOSTDOWN : _cupsLangPrintFilter(stderr, "WARNING", _("The printer may not exist or " "is unavailable at this time.")); break; case EHOSTUNREACH : _cupsLangPrintFilter(stderr, "WARNING", _("The printer is unreachable at " "this time.")); break; case ECONNREFUSED : default : _cupsLangPrintFilter(stderr, "WARNING", _("The printer is in use.")); break; } sleep(delay); if (delay < 30) delay += 5; } else if (error == EADDRINUSE) { /* * Try on another port... */ sleep(1); } else { _cupsLangPrintFilter(stderr, "ERROR", _("The printer is not responding.")); sleep(30); } } /* * Set the timeout... */ #ifdef WIN32 tv = (DWORD)(timeout * 1000); setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(tv)); setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, (char *)&tv, sizeof(tv)); #else tv.tv_sec = timeout; tv.tv_usec = 0; setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)); #endif /* WIN32 */ fputs("STATE: -connecting-to-device\n", stderr); _cupsLangPrintFilter(stderr, "INFO", _("Connected to printer.")); fprintf(stderr, "DEBUG: Connected to %s:%d (local port %d)...\n", httpAddrString(&(addr->addr), addrname, sizeof(addrname)), httpAddrPort(&(addr->addr)), lport); /* * See if the printer supports SNMP... */ if (snmp_fd >= 0) have_supplies = !backendSNMPSupplies(snmp_fd, &(addrlist->addr), NULL, NULL); else have_supplies = 0; /* * Check for side-channel requests... */ backendCheckSideChannel(snmp_fd, &(addrlist->addr)); /* * Next, open the print file and figure out its size... */ if (print_fd) { /* * Use the size from the print file... */ if (fstat(print_fd, &filestats)) { close(fd); perror("DEBUG: unable to stat print file"); return (CUPS_BACKEND_FAILED); } filestats.st_size *= manual_copies; } else { /* * Use a "very large value" for the size so that the printer will * keep printing until we close the connection... */ #ifdef _LARGEFILE_SOURCE filestats.st_size = (size_t)(999999999999.0); #else filestats.st_size = 2147483647; #endif /* _LARGEFILE_SOURCE */ } /* * Send a job header to the printer, specifying no banner page and * literal output... */ if (lpd_command(fd, "\002%s\n", printer)) /* Receive print job(s) */ { close(fd); return (CUPS_BACKEND_FAILED); } if (orighost && _cups_strcasecmp(orighost, "localhost")) strlcpy(localhost, orighost, sizeof(localhost)); else httpGetHostname(NULL, localhost, sizeof(localhost)); snprintf(control, sizeof(control), "H%.31s\n" /* RFC 1179, Section 7.2 - host name <= 31 chars */ "P%.31s\n" /* RFC 1179, Section 7.2 - user name <= 31 chars */ "J%.99s\n", /* RFC 1179, Section 7.2 - job name <= 99 chars */ localhost, user, title); cptr = control + strlen(control); if (banner) { snprintf(cptr, sizeof(control) - (cptr - control), "C%.31s\n" /* RFC 1179, Section 7.2 - class name <= 31 chars */ "L%s\n", localhost, user); cptr += strlen(cptr); } while (copies > 0) { snprintf(cptr, sizeof(control) - (cptr - control), "%cdfA%03d%.15s\n", format, (int)getpid() % 1000, localhost); cptr += strlen(cptr); copies --; } snprintf(cptr, sizeof(control) - (cptr - control), "UdfA%03d%.15s\n" "N%.131s\n", /* RFC 1179, Section 7.2 - sourcefile name <= 131 chars */ (int)getpid() % 1000, localhost, title); fprintf(stderr, "DEBUG: Control file is:\n%s", control); if (order == ORDER_CONTROL_DATA) { /* * Check for side-channel requests... */ backendCheckSideChannel(snmp_fd, &(addr->addr)); /* * Send the control file... */ if (lpd_command(fd, "\002%d cfA%03.3d%.15s\n", strlen(control), (int)getpid() % 1000, localhost)) { close(fd); return (CUPS_BACKEND_FAILED); } fprintf(stderr, "DEBUG: Sending control file (%u bytes)\n", (unsigned)strlen(control)); if (lpd_write(fd, control, strlen(control) + 1) < (strlen(control) + 1)) { status = errno; perror("DEBUG: Unable to write control file"); } else { if (read(fd, &status, 1) < 1) { _cupsLangPrintFilter(stderr, "WARNING", _("The printer did not respond.")); status = errno; } } if (status != 0) _cupsLangPrintFilter(stderr, "ERROR", _("Remote host did not accept control file (%d)."), status); else _cupsLangPrintFilter(stderr, "INFO", _("Control file sent successfully.")); } else status = 0; if (status == 0) { /* * Check for side-channel requests... */ backendCheckSideChannel(snmp_fd, &(addr->addr)); /* * Send the print file... */ if (lpd_command(fd, "\003" CUPS_LLFMT " dfA%03.3d%.15s\n", CUPS_LLCAST filestats.st_size, (int)getpid() % 1000, localhost)) { close(fd); return (CUPS_BACKEND_FAILED); } fprintf(stderr, "DEBUG: Sending data file (" CUPS_LLFMT " bytes)\n", CUPS_LLCAST filestats.st_size); tbytes = 0; for (copy = 0; copy < manual_copies; copy ++) { lseek(print_fd, 0, SEEK_SET); while ((nbytes = read(print_fd, buffer, sizeof(buffer))) > 0) { _cupsLangPrintFilter(stderr, "INFO", _("Spooling job, %.0f%% complete."), 100.0 * tbytes / filestats.st_size); if (lpd_write(fd, buffer, nbytes) < nbytes) { perror("DEBUG: Unable to send print file to printer"); break; } else tbytes += nbytes; } } if (mode == MODE_STANDARD) { if (tbytes < filestats.st_size) status = errno; else if (lpd_write(fd, "", 1) < 1) { perror("DEBUG: Unable to send trailing nul to printer"); status = errno; } else { /* * Read the status byte from the printer; if we can't read the byte * back now, we should set status to "errno", however at this point * we know the printer got the whole file and we don't necessarily * want to requeue it over and over... */ if (recv(fd, &status, 1, 0) < 1) { _cupsLangPrintFilter(stderr, "WARNING", _("The printer did not respond.")); status = 0; } } } else status = 0; if (status != 0) _cupsLangPrintFilter(stderr, "ERROR", _("Remote host did not accept data file (%d)."), status); else _cupsLangPrintFilter(stderr, "INFO", _("Data file sent successfully.")); } if (status == 0 && order == ORDER_DATA_CONTROL) { /* * Check for side-channel requests... */ backendCheckSideChannel(snmp_fd, &(addr->addr)); /* * Send control file... */ if (lpd_command(fd, "\002%d cfA%03.3d%.15s\n", strlen(control), (int)getpid() % 1000, localhost)) { close(fd); return (CUPS_BACKEND_FAILED); } fprintf(stderr, "DEBUG: Sending control file (%lu bytes)\n", (unsigned long)strlen(control)); if (lpd_write(fd, control, strlen(control) + 1) < (strlen(control) + 1)) { status = errno; perror("DEBUG: Unable to write control file"); } else { if (read(fd, &status, 1) < 1) { _cupsLangPrintFilter(stderr, "WARNING", _("The printer did not respond.")); status = errno; } } if (status != 0) _cupsLangPrintFilter(stderr, "ERROR", _("Remote host did not accept control file (%d)."), status); else _cupsLangPrintFilter(stderr, "INFO", _("Control file sent successfully.")); } /* * Collect the final supply levels as needed... */ if (have_supplies) backendSNMPSupplies(snmp_fd, &(addr->addr), NULL, NULL); /* * Close the socket connection and input file... */ close(fd); if (status == 0) return (CUPS_BACKEND_OK); /* * Waiting for a retry... */ sleep(30); } /* * If we get here, then the job has been canceled... */ return (CUPS_BACKEND_FAILED); }
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); }
char * /* O - New URL */ cgiRewriteURL(const char *uri, /* I - Current URI */ char *url, /* O - New URL */ int urlsize, /* I - Size of URL buffer */ const char *newresource) /* I - Replacement resource */ { char method[HTTP_MAX_URI], userpass[HTTP_MAX_URI], hostname[HTTP_MAX_URI], rawresource[HTTP_MAX_URI], resource[HTTP_MAX_URI], /* URI components... */ *rawptr, /* Pointer into rawresource */ *resptr; /* Pointer into resource */ int port; /* Port number */ static int ishttps = -1; /* Using encryption? */ static const char *server; /* Name of server */ static char servername[1024]; /* Local server name */ static const char hexchars[] = "0123456789ABCDEF"; /* Hexadecimal conversion characters */ /* * Check if we have been called before... */ if (ishttps < 0) { /* * No, initialize static vars for the conversion... * * First get the server name associated with the client interface as * well as the locally configured hostname. We'll check *both* of * these to see if the printer URL is local... */ if ((server = getenv("SERVER_NAME")) == NULL) server = ""; httpGetHostname(NULL, servername, sizeof(servername)); /* * Then flag whether we are using SSL on this connection... */ ishttps = getenv("HTTPS") != NULL; } /* * Convert the URI to a URL... */ httpSeparateURI(HTTP_URI_CODING_ALL, uri, method, sizeof(method), userpass, sizeof(userpass), hostname, sizeof(hostname), &port, rawresource, sizeof(rawresource)); if (!strcmp(method, "ipp") || !strcmp(method, "http") || !strcmp(method, "https")) { if (newresource) { /* * Force the specified resource name instead of the one in the URL... */ strlcpy(resource, newresource, sizeof(resource)); } else { /* * Rewrite the resource string so it doesn't contain any * illegal chars... */ for (rawptr = rawresource, resptr = resource; *rawptr; rawptr ++) if ((*rawptr & 128) || *rawptr == '%' || *rawptr == ' ' || *rawptr == '#' || *rawptr == '?' || *rawptr == '.') /* For MSIE */ { if (resptr < (resource + sizeof(resource) - 3)) { *resptr++ = '%'; *resptr++ = hexchars[(*rawptr >> 4) & 15]; *resptr++ = hexchars[*rawptr & 15]; } } else if (resptr < (resource + sizeof(resource) - 1)) *resptr++ = *rawptr; *resptr = '\0'; }
int /* O - 1 on success, 0 on failure */ cupsAdminSetServerSettings( http_t *http, /* I - Connection to server or @code CUPS_HTTP_DEFAULT@ */ int num_settings, /* I - Number of settings */ cups_option_t *settings) /* I - Settings */ { int i; /* Looping var */ http_status_t status; /* GET/PUT status */ const char *server_port_env; /* SERVER_PORT env var */ int server_port; /* IPP port for server */ cups_file_t *cupsd; /* cupsd.conf file */ char cupsdconf[1024]; /* cupsd.conf filename */ int remote; /* Remote cupsd.conf file? */ char tempfile[1024]; /* Temporary new cupsd.conf */ cups_file_t *temp; /* Temporary file */ char line[1024], /* Line from cupsd.conf file */ *value; /* Value on line */ int linenum, /* Line number in file */ in_location, /* In a location section? */ in_policy, /* In a policy section? */ in_default_policy, /* In the default policy section? */ in_cancel_job, /* In a cancel-job section? */ in_admin_location, /* In the /admin location? */ in_conf_location, /* In the /admin/conf location? */ in_log_location, /* In the /admin/log location? */ in_root_location; /* In the / location? */ const char *val; /* Setting value */ int share_printers, /* Share local printers */ remote_admin, /* Remote administration allowed? */ remote_any, /* Remote access from anywhere? */ user_cancel_any, /* Cancel-job policy set? */ debug_logging; /* LogLevel debug set? */ int wrote_port_listen, /* Wrote the port/listen lines? */ wrote_browsing, /* Wrote the browsing lines? */ wrote_policy, /* Wrote the policy? */ wrote_loglevel, /* Wrote the LogLevel line? */ wrote_admin_location, /* Wrote the /admin location? */ wrote_conf_location, /* Wrote the /admin/conf location? */ wrote_log_location, /* Wrote the /admin/log location? */ wrote_root_location; /* Wrote the / location? */ int indent; /* Indentation */ int cupsd_num_settings; /* New number of settings */ int old_share_printers, /* Share local printers */ old_remote_admin, /* Remote administration allowed? */ old_remote_any, /* Remote access from anywhere? */ old_user_cancel_any, /* Cancel-job policy set? */ old_debug_logging; /* LogLevel debug set? */ cups_option_t *cupsd_settings, /* New settings */ *setting; /* Current setting */ _cups_globals_t *cg = _cupsGlobals(); /* Global data */ /* * Range check input... */ if (!http) http = _cupsConnect(); if (!http || !num_settings || !settings) { _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(EINVAL), 0); return (0); } /* * Get the cupsd.conf file... */ if (get_cupsd_conf(http, cg, 0, cupsdconf, sizeof(cupsdconf), &remote) == HTTP_STATUS_OK) { if ((cupsd = cupsFileOpen(cupsdconf, "r")) == NULL) { _cupsSetError(IPP_STATUS_ERROR_INTERNAL, NULL, 0); return (0); } } else return (0); /* * Get current settings... */ if (!cupsAdminGetServerSettings(http, &cupsd_num_settings, &cupsd_settings)) return (0); if ((val = cupsGetOption(CUPS_SERVER_DEBUG_LOGGING, cupsd_num_settings, cupsd_settings)) != NULL) old_debug_logging = atoi(val); else old_debug_logging = 0; DEBUG_printf(("1cupsAdminSetServerSettings: old debug_logging=%d", old_debug_logging)); if ((val = cupsGetOption(CUPS_SERVER_REMOTE_ADMIN, cupsd_num_settings, cupsd_settings)) != NULL) old_remote_admin = atoi(val); else old_remote_admin = 0; DEBUG_printf(("1cupsAdminSetServerSettings: old remote_admin=%d", old_remote_admin)); if ((val = cupsGetOption(CUPS_SERVER_REMOTE_ANY, cupsd_num_settings, cupsd_settings)) != NULL) old_remote_any = atoi(val); else old_remote_any = 0; DEBUG_printf(("1cupsAdminSetServerSettings: old remote_any=%d", old_remote_any)); if ((val = cupsGetOption(CUPS_SERVER_SHARE_PRINTERS, cupsd_num_settings, cupsd_settings)) != NULL) old_share_printers = atoi(val); else old_share_printers = 0; DEBUG_printf(("1cupsAdminSetServerSettings: old share_printers=%d", old_share_printers)); if ((val = cupsGetOption(CUPS_SERVER_USER_CANCEL_ANY, cupsd_num_settings, cupsd_settings)) != NULL) old_user_cancel_any = atoi(val); else old_user_cancel_any = 0; DEBUG_printf(("1cupsAdminSetServerSettings: old user_cancel_any=%d", old_user_cancel_any)); cupsFreeOptions(cupsd_num_settings, cupsd_settings); /* * Get basic settings... */ if ((val = cupsGetOption(CUPS_SERVER_DEBUG_LOGGING, num_settings, settings)) != NULL) { debug_logging = atoi(val); if (debug_logging == old_debug_logging) { /* * No change to this setting... */ debug_logging = -1; } } else debug_logging = -1; DEBUG_printf(("1cupsAdminSetServerSettings: debug_logging=%d", debug_logging)); if ((val = cupsGetOption(CUPS_SERVER_REMOTE_ANY, num_settings, settings)) != NULL) { remote_any = atoi(val); if (remote_any == old_remote_any) { /* * No change to this setting... */ remote_any = -1; } } else remote_any = -1; DEBUG_printf(("1cupsAdminSetServerSettings: remote_any=%d", remote_any)); if ((val = cupsGetOption(CUPS_SERVER_REMOTE_ADMIN, num_settings, settings)) != NULL) { remote_admin = atoi(val); if (remote_admin == old_remote_admin) { /* * No change to this setting... */ remote_admin = -1; } } else remote_admin = -1; DEBUG_printf(("1cupsAdminSetServerSettings: remote_admin=%d", remote_admin)); if ((val = cupsGetOption(CUPS_SERVER_SHARE_PRINTERS, num_settings, settings)) != NULL) { share_printers = atoi(val); if (share_printers == old_share_printers) { /* * No change to this setting... */ share_printers = -1; } } else share_printers = -1; DEBUG_printf(("1cupsAdminSetServerSettings: share_printers=%d", share_printers)); if ((val = cupsGetOption(CUPS_SERVER_USER_CANCEL_ANY, num_settings, settings)) != NULL) { user_cancel_any = atoi(val); if (user_cancel_any == old_user_cancel_any) { /* * No change to this setting... */ user_cancel_any = -1; } } else user_cancel_any = -1; DEBUG_printf(("1cupsAdminSetServerSettings: user_cancel_any=%d", user_cancel_any)); /* * Create a temporary file for the new cupsd.conf file... */ if ((temp = cupsTempFile2(tempfile, sizeof(tempfile))) == NULL) { cupsFileClose(cupsd); if (remote) unlink(cupsdconf); _cupsSetError(IPP_STATUS_ERROR_INTERNAL, NULL, 0); return (0); } /* * Copy the old file to the new, making changes along the way... */ cupsd_num_settings = 0; in_admin_location = 0; in_cancel_job = 0; in_conf_location = 0; in_default_policy = 0; in_location = 0; in_log_location = 0; in_policy = 0; in_root_location = 0; linenum = 0; wrote_admin_location = 0; wrote_browsing = 0; wrote_conf_location = 0; wrote_log_location = 0; wrote_loglevel = 0; wrote_policy = 0; wrote_port_listen = 0; wrote_root_location = 0; indent = 0; if ((server_port_env = getenv("SERVER_PORT")) != NULL) { if ((server_port = atoi(server_port_env)) <= 0) server_port = ippPort(); } else server_port = ippPort(); if (server_port <= 0) server_port = IPP_PORT; while (cupsFileGetConf(cupsd, line, sizeof(line), &value, &linenum)) { if ((!_cups_strcasecmp(line, "Port") || !_cups_strcasecmp(line, "Listen")) && (remote_admin >= 0 || remote_any >= 0 || share_printers >= 0)) { if (!wrote_port_listen) { wrote_port_listen = 1; if (remote_admin > 0 || remote_any > 0 || share_printers > 0) { cupsFilePuts(temp, "# Allow remote access\n"); cupsFilePrintf(temp, "Port %d\n", server_port); } else { cupsFilePuts(temp, "# Only listen for connections from the local " "machine.\n"); cupsFilePrintf(temp, "Listen localhost:%d\n", server_port); } #ifdef CUPS_DEFAULT_DOMAINSOCKET if ((!value || strcmp(CUPS_DEFAULT_DOMAINSOCKET, value)) && !access(CUPS_DEFAULT_DOMAINSOCKET, 0)) cupsFilePuts(temp, "Listen " CUPS_DEFAULT_DOMAINSOCKET "\n"); #endif /* CUPS_DEFAULT_DOMAINSOCKET */ } else if (value && value[0] == '/' #ifdef CUPS_DEFAULT_DOMAINSOCKET && strcmp(CUPS_DEFAULT_DOMAINSOCKET, value) #endif /* CUPS_DEFAULT_DOMAINSOCKET */ ) cupsFilePrintf(temp, "Listen %s\n", value); } else if ((!_cups_strcasecmp(line, "Browsing") || !_cups_strcasecmp(line, "BrowseLocalProtocols")) && share_printers >= 0) { if (!wrote_browsing) { int new_share_printers = (share_printers > 0 || (share_printers == -1 && old_share_printers > 0)); wrote_browsing = 1; if (new_share_printers) { const char *localp = cupsGetOption("BrowseLocalProtocols", num_settings, settings); if (!localp || !localp[0]) localp = cupsGetOption("BrowseLocalProtocols", cupsd_num_settings, cupsd_settings); cupsFilePuts(temp, "# Share local printers on the local network.\n"); cupsFilePuts(temp, "Browsing On\n"); if (!localp) localp = CUPS_DEFAULT_BROWSE_LOCAL_PROTOCOLS; cupsFilePrintf(temp, "BrowseLocalProtocols %s\n", localp); cupsd_num_settings = cupsAddOption("BrowseLocalProtocols", localp, cupsd_num_settings, &cupsd_settings); } else { cupsFilePuts(temp, "# Disable printer sharing.\n"); cupsFilePuts(temp, "Browsing Off\n"); } } } else if (!_cups_strcasecmp(line, "LogLevel") && debug_logging >= 0) { wrote_loglevel = 1; if (debug_logging) { cupsFilePuts(temp, "# Show troubleshooting information in error_log.\n"); cupsFilePuts(temp, "LogLevel debug\n"); } else { cupsFilePuts(temp, "# Show general information in error_log.\n"); cupsFilePuts(temp, "LogLevel " CUPS_DEFAULT_LOG_LEVEL "\n"); } } else if (!_cups_strcasecmp(line, "<Policy")) { in_default_policy = !_cups_strcasecmp(value, "default"); in_policy = 1; cupsFilePrintf(temp, "%s %s>\n", line, value); indent += 2; } else if (!_cups_strcasecmp(line, "</Policy>")) { indent -= 2; if (!wrote_policy && in_default_policy) { wrote_policy = 1; if (!user_cancel_any) cupsFilePuts(temp, " # Only the owner or an administrator can " "cancel a job...\n" " <Limit Cancel-Job>\n" " Order deny,allow\n" " Require user @OWNER " CUPS_DEFAULT_PRINTOPERATOR_AUTH "\n" " </Limit>\n"); } in_policy = 0; in_default_policy = 0; cupsFilePuts(temp, "</Policy>\n"); } else if (!_cups_strcasecmp(line, "<Location")) { in_location = 1; indent += 2; if (!strcmp(value, "/admin")) in_admin_location = 1; else if (!strcmp(value, "/admin/conf")) in_conf_location = 1; else if (!strcmp(value, "/admin/log")) in_log_location = 1; else if (!strcmp(value, "/")) in_root_location = 1; cupsFilePrintf(temp, "%s %s>\n", line, value); } else if (!_cups_strcasecmp(line, "</Location>")) { in_location = 0; indent -= 2; if (in_admin_location && remote_admin >= 0) { wrote_admin_location = 1; if (remote_admin) cupsFilePuts(temp, " # Allow remote administration...\n"); else if (remote_admin == 0) cupsFilePuts(temp, " # Restrict access to the admin pages...\n"); cupsFilePuts(temp, " Order allow,deny\n"); if (remote_admin) cupsFilePrintf(temp, " Allow %s\n", remote_any > 0 ? "all" : "@LOCAL"); } else if (in_conf_location && remote_admin >= 0) { wrote_conf_location = 1; if (remote_admin) cupsFilePuts(temp, " # Allow remote access to the configuration " "files...\n"); else cupsFilePuts(temp, " # Restrict access to the configuration " "files...\n"); cupsFilePuts(temp, " Order allow,deny\n"); if (remote_admin) cupsFilePrintf(temp, " Allow %s\n", remote_any > 0 ? "all" : "@LOCAL"); } else if (in_log_location && remote_admin >= 0) { wrote_log_location = 1; if (remote_admin) cupsFilePuts(temp, " # Allow remote access to the log " "files...\n"); else cupsFilePuts(temp, " # Restrict access to the log " "files...\n"); cupsFilePuts(temp, " Order allow,deny\n"); if (remote_admin) cupsFilePrintf(temp, " Allow %s\n", remote_any > 0 ? "all" : "@LOCAL"); } else if (in_root_location && (remote_admin >= 0 || remote_any >= 0 || share_printers >= 0)) { wrote_root_location = 1; if (remote_admin > 0 && share_printers > 0) cupsFilePuts(temp, " # Allow shared printing and remote " "administration...\n"); else if (remote_admin > 0) cupsFilePuts(temp, " # Allow remote administration...\n"); else if (share_printers > 0) cupsFilePuts(temp, " # Allow shared printing...\n"); else if (remote_any > 0) cupsFilePuts(temp, " # Allow remote access...\n"); else cupsFilePuts(temp, " # Restrict access to the server...\n"); cupsFilePuts(temp, " Order allow,deny\n"); if (remote_admin > 0 || remote_any > 0 || share_printers > 0) cupsFilePrintf(temp, " Allow %s\n", remote_any > 0 ? "all" : "@LOCAL"); } in_admin_location = 0; in_conf_location = 0; in_log_location = 0; in_root_location = 0; cupsFilePuts(temp, "</Location>\n"); } else if (!_cups_strcasecmp(line, "<Limit")) { if (in_default_policy) { /* * See if the policy limit is for the Cancel-Job operation... */ char *valptr; /* Pointer into value */ if (!_cups_strcasecmp(value, "cancel-job") && user_cancel_any >= 0) { /* * Don't write anything for this limit section... */ in_cancel_job = 2; } else { cupsFilePrintf(temp, "%*s%s", indent, "", line); while (*value) { for (valptr = value; *valptr && !_cups_isspace(*valptr); valptr ++); if (*valptr) *valptr++ = '\0'; if (!_cups_strcasecmp(value, "cancel-job") && user_cancel_any >= 0) { /* * Write everything except for this definition... */ in_cancel_job = 1; } else cupsFilePrintf(temp, " %s", value); for (value = valptr; _cups_isspace(*value); value ++); } cupsFilePuts(temp, ">\n"); } } else cupsFilePrintf(temp, "%*s%s %s>\n", indent, "", line, value); indent += 2; } else if (!_cups_strcasecmp(line, "</Limit>") && in_cancel_job) { indent -= 2; if (in_cancel_job == 1) cupsFilePuts(temp, " </Limit>\n"); wrote_policy = 1; if (!user_cancel_any) cupsFilePuts(temp, " # Only the owner or an administrator can cancel " "a job...\n" " <Limit Cancel-Job>\n" " Order deny,allow\n" " Require user @OWNER " CUPS_DEFAULT_PRINTOPERATOR_AUTH "\n" " </Limit>\n"); in_cancel_job = 0; } else if ((((in_admin_location || in_conf_location || in_root_location) && (remote_admin >= 0 || remote_any >= 0)) || (in_root_location && share_printers >= 0)) && (!_cups_strcasecmp(line, "Allow") || !_cups_strcasecmp(line, "Deny") || !_cups_strcasecmp(line, "Order"))) continue; else if (in_cancel_job == 2) continue; else if (line[0] == '<') { if (value) { cupsFilePrintf(temp, "%*s%s %s>\n", indent, "", line, value); indent += 2; } else { if (line[1] == '/') indent -= 2; cupsFilePrintf(temp, "%*s%s\n", indent, "", line); } } else if (!in_policy && !in_location && (val = cupsGetOption(line, num_settings, settings)) != NULL) { /* * Replace this directive's value with the new one... */ cupsd_num_settings = cupsAddOption(line, val, cupsd_num_settings, &cupsd_settings); /* * Write the new value in its place, without indentation since we * only support setting root directives, not in sections... */ cupsFilePrintf(temp, "%s %s\n", line, val); } else if (value) { if (!in_policy && !in_location) { /* * Record the non-policy, non-location directives that we find * in the server settings, since we cache this info and record it * in cupsAdminGetServerSettings()... */ cupsd_num_settings = cupsAddOption(line, value, cupsd_num_settings, &cupsd_settings); } cupsFilePrintf(temp, "%*s%s %s\n", indent, "", line, value); } else cupsFilePrintf(temp, "%*s%s\n", indent, "", line); } /* * Write any missing info... */ if (!wrote_browsing && share_printers >= 0) { if (share_printers > 0) { cupsFilePuts(temp, "# Share local printers on the local network.\n"); cupsFilePuts(temp, "Browsing On\n"); } else { cupsFilePuts(temp, "# Disable printer sharing and shared printers.\n"); cupsFilePuts(temp, "Browsing Off\n"); } } if (!wrote_loglevel && debug_logging >= 0) { if (debug_logging) { cupsFilePuts(temp, "# Show troubleshooting information in error_log.\n"); cupsFilePuts(temp, "LogLevel debug\n"); } else { cupsFilePuts(temp, "# Show general information in error_log.\n"); cupsFilePuts(temp, "LogLevel " CUPS_DEFAULT_LOG_LEVEL "\n"); } } if (!wrote_port_listen && (remote_admin >= 0 || remote_any >= 0 || share_printers >= 0)) { if (remote_admin > 0 || remote_any > 0 || share_printers > 0) { cupsFilePuts(temp, "# Allow remote access\n"); cupsFilePrintf(temp, "Port %d\n", ippPort()); } else { cupsFilePuts(temp, "# Only listen for connections from the local machine.\n"); cupsFilePrintf(temp, "Listen localhost:%d\n", ippPort()); } #ifdef CUPS_DEFAULT_DOMAINSOCKET if (!access(CUPS_DEFAULT_DOMAINSOCKET, 0)) cupsFilePuts(temp, "Listen " CUPS_DEFAULT_DOMAINSOCKET "\n"); #endif /* CUPS_DEFAULT_DOMAINSOCKET */ } if (!wrote_root_location && (remote_admin >= 0 || remote_any >= 0 || share_printers >= 0)) { if (remote_admin > 0 && share_printers > 0) cupsFilePuts(temp, "# Allow shared printing and remote administration...\n"); else if (remote_admin > 0) cupsFilePuts(temp, "# Allow remote administration...\n"); else if (share_printers > 0) cupsFilePuts(temp, "# Allow shared printing...\n"); else if (remote_any > 0) cupsFilePuts(temp, "# Allow remote access...\n"); else cupsFilePuts(temp, "# Restrict access to the server...\n"); cupsFilePuts(temp, "<Location />\n" " Order allow,deny\n"); if (remote_admin > 0 || remote_any > 0 || share_printers > 0) cupsFilePrintf(temp, " Allow %s\n", remote_any > 0 ? "all" : "@LOCAL"); cupsFilePuts(temp, "</Location>\n"); } if (!wrote_admin_location && remote_admin >= 0) { if (remote_admin) cupsFilePuts(temp, "# Allow remote administration...\n"); else cupsFilePuts(temp, "# Restrict access to the admin pages...\n"); cupsFilePuts(temp, "<Location /admin>\n" " Order allow,deny\n"); if (remote_admin) cupsFilePrintf(temp, " Allow %s\n", remote_any > 0 ? "all" : "@LOCAL"); cupsFilePuts(temp, "</Location>\n"); } if (!wrote_conf_location && remote_admin >= 0) { if (remote_admin) cupsFilePuts(temp, "# Allow remote access to the configuration files...\n"); else cupsFilePuts(temp, "# Restrict access to the configuration files...\n"); cupsFilePuts(temp, "<Location /admin/conf>\n" " AuthType Default\n" " Require user @SYSTEM\n" " Order allow,deny\n"); if (remote_admin) cupsFilePrintf(temp, " Allow %s\n", remote_any > 0 ? "all" : "@LOCAL"); cupsFilePuts(temp, "</Location>\n"); } if (!wrote_log_location && remote_admin >= 0) { if (remote_admin) cupsFilePuts(temp, "# Allow remote access to the log files...\n"); else cupsFilePuts(temp, "# Restrict access to the log files...\n"); cupsFilePuts(temp, "<Location /admin/log>\n" " AuthType Default\n" " Require user @SYSTEM\n" " Order allow,deny\n"); if (remote_admin) cupsFilePrintf(temp, " Allow %s\n", remote_any > 0 ? "all" : "@LOCAL"); cupsFilePuts(temp, "</Location>\n"); } if (!wrote_policy && user_cancel_any >= 0) { cupsFilePuts(temp, "<Policy default>\n" " # Job-related operations must be done by the owner " "or an administrator...\n" " <Limit Send-Document Send-URI Hold-Job Release-Job " "Restart-Job Purge-Jobs Set-Job-Attributes " "Create-Job-Subscription Renew-Subscription " "Cancel-Subscription Get-Notifications Reprocess-Job " "Cancel-Current-Job Suspend-Current-Job Resume-Job " "CUPS-Move-Job>\n" " Require user @OWNER @SYSTEM\n" " Order deny,allow\n" " </Limit>\n" " # All administration operations require an " "administrator to authenticate...\n" " <Limit Pause-Printer Resume-Printer " "Set-Printer-Attributes Enable-Printer " "Disable-Printer Pause-Printer-After-Current-Job " "Hold-New-Jobs Release-Held-New-Jobs Deactivate-Printer " "Activate-Printer Restart-Printer Shutdown-Printer " "Startup-Printer Promote-Job Schedule-Job-After " "CUPS-Add-Printer CUPS-Delete-Printer " "CUPS-Add-Class CUPS-Delete-Class " "CUPS-Accept-Jobs CUPS-Reject-Jobs " "CUPS-Set-Default CUPS-Add-Device CUPS-Delete-Device>\n" " AuthType Default\n" " Require user @SYSTEM\n" " Order deny,allow\n" "</Limit>\n"); if (!user_cancel_any) cupsFilePuts(temp, " # Only the owner or an administrator can cancel " "a job...\n" " <Limit Cancel-Job>\n" " Order deny,allow\n" " Require user @OWNER " CUPS_DEFAULT_PRINTOPERATOR_AUTH "\n" " </Limit>\n"); cupsFilePuts(temp, " <Limit All>\n" " Order deny,allow\n" " </Limit>\n" "</Policy>\n"); } for (i = num_settings, setting = settings; i > 0; i --, setting ++) if (setting->name[0] != '_' && _cups_strcasecmp(setting->name, "Listen") && _cups_strcasecmp(setting->name, "Port") && !cupsGetOption(setting->name, cupsd_num_settings, cupsd_settings)) { /* * Add this directive to the list of directives we have written... */ cupsd_num_settings = cupsAddOption(setting->name, setting->value, cupsd_num_settings, &cupsd_settings); /* * Write the new value, without indentation since we only support * setting root directives, not in sections... */ cupsFilePrintf(temp, "%s %s\n", setting->name, setting->value); } cupsFileClose(cupsd); cupsFileClose(temp); /* * Upload the configuration file to the server... */ status = cupsPutFile(http, "/admin/conf/cupsd.conf", tempfile); if (status == HTTP_STATUS_CREATED) { /* * Updated OK, add the basic settings... */ if (debug_logging >= 0) cupsd_num_settings = cupsAddOption(CUPS_SERVER_DEBUG_LOGGING, debug_logging ? "1" : "0", cupsd_num_settings, &cupsd_settings); else cupsd_num_settings = cupsAddOption(CUPS_SERVER_DEBUG_LOGGING, old_debug_logging ? "1" : "0", cupsd_num_settings, &cupsd_settings); if (remote_admin >= 0) cupsd_num_settings = cupsAddOption(CUPS_SERVER_REMOTE_ADMIN, remote_admin ? "1" : "0", cupsd_num_settings, &cupsd_settings); else cupsd_num_settings = cupsAddOption(CUPS_SERVER_REMOTE_ADMIN, old_remote_admin ? "1" : "0", cupsd_num_settings, &cupsd_settings); if (remote_any >= 0) cupsd_num_settings = cupsAddOption(CUPS_SERVER_REMOTE_ANY, remote_any ? "1" : "0", cupsd_num_settings, &cupsd_settings); else cupsd_num_settings = cupsAddOption(CUPS_SERVER_REMOTE_ANY, old_remote_any ? "1" : "0", cupsd_num_settings, &cupsd_settings); if (share_printers >= 0) cupsd_num_settings = cupsAddOption(CUPS_SERVER_SHARE_PRINTERS, share_printers ? "1" : "0", cupsd_num_settings, &cupsd_settings); else cupsd_num_settings = cupsAddOption(CUPS_SERVER_SHARE_PRINTERS, old_share_printers ? "1" : "0", cupsd_num_settings, &cupsd_settings); if (user_cancel_any >= 0) cupsd_num_settings = cupsAddOption(CUPS_SERVER_USER_CANCEL_ANY, user_cancel_any ? "1" : "0", cupsd_num_settings, &cupsd_settings); else cupsd_num_settings = cupsAddOption(CUPS_SERVER_USER_CANCEL_ANY, old_user_cancel_any ? "1" : "0", cupsd_num_settings, &cupsd_settings); /* * Save the new values... */ invalidate_cupsd_cache(cg); cg->cupsd_num_settings = cupsd_num_settings; cg->cupsd_settings = cupsd_settings; cg->cupsd_update = time(NULL); httpGetHostname(http, cg->cupsd_hostname, sizeof(cg->cupsd_hostname)); } else cupsFreeOptions(cupsd_num_settings, cupsd_settings); /* * Remote our temp files and return... */ if (remote) unlink(cupsdconf); unlink(tempfile); return (status == HTTP_STATUS_CREATED); }
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); } }
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); }
int /* O - 1 on success, 0 on failure */ serverFinalizeConfiguration(void) { char local[1024]; /* Local hostname */ /* * Default hostname... */ if (!ServerName && httpGetHostname(NULL, local, sizeof(local))) ServerName = strdup(local); if (!ServerName) ServerName = strdup("localhost"); #ifdef HAVE_SSL /* * Setup TLS certificate for server... */ cupsSetServerCredentials(KeychainPath, ServerName, 1); #endif /* HAVE_SSL */ /* * Default directories... */ if (!DataDirectory) { char directory[1024]; /* New directory */ const char *tmpdir; /* Temporary directory */ #ifdef WIN32 if ((tmpdir = getenv("TEMP")) == NULL) tmpdir = "C:/TEMP"; #elif defined(__APPLE__) if ((tmpdir = getenv("TMPDIR")) == NULL) tmpdir = "/private/tmp"; #else if ((tmpdir = getenv("TMPDIR")) == NULL) tmpdir = "/tmp"; #endif /* WIN32 */ snprintf(directory, sizeof(directory), "%s/ippserver.%d", tmpdir, (int)getpid()); if (mkdir(directory, 0755) && errno != EEXIST) { serverLog(SERVER_LOGLEVEL_ERROR, "Unable to create default data directory \"%s\": %s", directory, strerror(errno)); return (0); } serverLog(SERVER_LOGLEVEL_INFO, "Using default data directory \"%s\".", directory); DataDirectory = strdup(directory); } if (!SpoolDirectory) { SpoolDirectory = strdup(DataDirectory); serverLog(SERVER_LOGLEVEL_INFO, "Using default spool directory \"%s\".", DataDirectory); } /* * Initialize Bonjour... */ serverDNSSDInit(); /* * Apply default listeners if none are specified... */ if (!Listeners) { #ifdef WIN32 /* * Windows is almost always used as a single user system, so use a default port * number of 8631. */ if (!DefaultPort) DefaultPort = 8631; #else /* * Use 8000 + UID mod 1000 for the default port number... */ if (!DefaultPort) DefaultPort = 8000 + ((int)getuid() % 1000); #endif /* WIN32 */ serverLog(SERVER_LOGLEVEL_INFO, "Using default listeners for %s:%d.", ServerName, DefaultPort); if (!serverCreateListeners(strcmp(ServerName, "localhost") ? NULL : "localhost", DefaultPort)) return (0); } return (1); }
int main(int argc, /* I - Number of command-line arguments */ char *argv[]) /* I - Command-line arguments */ { int i, j; /* Looping var */ int job_id; /* Job ID */ char ch; /* Option character */ char *printer, /* Destination printer or class */ *instance; /* Instance */ const char *title, /* Job title */ *val; /* Environment variable name */ int num_copies; /* Number of copies per file */ int num_files; /* Number of files to print */ const char *files[1000]; /* Files to print */ cups_dest_t *dest; /* Selected destination */ int num_options; /* Number of options */ cups_option_t *options; /* Options */ int deletefile; /* Delete file after print? */ char buffer[8192]; /* Copy buffer */ _cupsSetLocale(argv); deletefile = 0; printer = NULL; dest = NULL; num_options = 0; options = NULL; num_files = 0; title = NULL; for (i = 1; i < argc; i ++) if (argv[i][0] == '-') switch (ch = argv[i][1]) { case 'E' : /* Encrypt */ #ifdef HAVE_SSL cupsSetEncryption(HTTP_ENCRYPT_REQUIRED); #else _cupsLangPrintf(stderr, _("%s: Sorry, no encryption support."), argv[0]); #endif /* HAVE_SSL */ break; case 'U' : /* Username */ if (argv[i][2] != '\0') cupsSetUser(argv[i] + 2); else { i ++; if (i >= argc) { _cupsLangPrintf(stderr, _("%s: Error - expected username after " "\"-U\" option."), argv[0]); return (1); } cupsSetUser(argv[i]); } break; case 'H' : /* Connect to host */ if (argv[i][2] != '\0') cupsSetServer(argv[i] + 2); else { i ++; if (i >= argc) { _cupsLangPrintf(stderr, _("%s: Error - expected hostname after " "\"-H\" option."), argv[0]); return (1); } else cupsSetServer(argv[i]); } break; case '1' : /* TROFF font set 1 */ case '2' : /* TROFF font set 2 */ case '3' : /* TROFF font set 3 */ case '4' : /* TROFF font set 4 */ case 'i' : /* indent */ case 'w' : /* width */ if (argv[i][2] == '\0') { i ++; if (i >= argc) { _cupsLangPrintf(stderr, _("%s: Error - expected value after \"-%c\" " "option."), argv[0], ch); return (1); } } case 'c' : /* CIFPLOT */ case 'd' : /* DVI */ case 'f' : /* FORTRAN */ case 'g' : /* plot */ case 'n' : /* Ditroff */ case 't' : /* Troff */ case 'v' : /* Raster image */ _cupsLangPrintf(stderr, _("%s: Warning - \"%c\" format modifier not " "supported - output may not be correct."), argv[0], ch); break; case 'o' : /* Option */ if (argv[i][2] != '\0') num_options = cupsParseOptions(argv[i] + 2, num_options, &options); else { i ++; if (i >= argc) { _cupsLangPrintf(stderr, _("%s: Error - expected option=value after " "\"-o\" option."), argv[0]); return (1); } num_options = cupsParseOptions(argv[i], num_options, &options); } break; case 'l' : /* Literal/raw */ num_options = cupsAddOption("raw", "true", num_options, &options); break; case 'p' : /* Prettyprint */ num_options = cupsAddOption("prettyprint", "true", num_options, &options); break; case 'h' : /* Suppress burst page */ num_options = cupsAddOption("job-sheets", "none", num_options, &options); break; case 's' : /* Don't use symlinks */ break; case 'm' : /* Mail on completion */ { char email[1024]; /* EMail address */ snprintf(email, sizeof(email), "mailto:%s@%s", cupsUser(), httpGetHostname(NULL, buffer, sizeof(buffer))); num_options = cupsAddOption("notify-recipient-uri", email, num_options, &options); } break; case 'q' : /* Queue file but don't print */ num_options = cupsAddOption("job-hold-until", "indefinite", num_options, &options); break; case 'r' : /* Remove file after printing */ deletefile = 1; break; case 'P' : /* Destination printer or class */ if (argv[i][2] != '\0') printer = argv[i] + 2; else { i ++; if (i >= argc) { _cupsLangPrintf(stderr, _("%s: Error - expected destination after " "\"-P\" option."), argv[0]); return (1); } printer = argv[i]; } if ((instance = strrchr(printer, '/')) != NULL) *instance++ = '\0'; if ((dest = cupsGetNamedDest(NULL, printer, instance)) != NULL) { for (j = 0; j < dest->num_options; j ++) if (cupsGetOption(dest->options[j].name, num_options, options) == NULL) num_options = cupsAddOption(dest->options[j].name, dest->options[j].value, num_options, &options); } break; case '#' : /* Number of copies */ if (argv[i][2] != '\0') num_copies = atoi(argv[i] + 2); else { i ++; if (i >= argc) { _cupsLangPrintf(stderr, _("%s: Error - expected copies after " "\"-#\" option."), argv[0]); return (1); } num_copies = atoi(argv[i]); } sprintf(buffer, "%d", num_copies); num_options = cupsAddOption("copies", buffer, num_options, &options); break; case 'C' : /* Class */ case 'J' : /* Job name */ case 'T' : /* Title */ if (argv[i][2] != '\0') title = argv[i] + 2; else { i ++; if (i >= argc) { _cupsLangPrintf(stderr, _("%s: Error - expected name after \"-%c\" " "option."), argv[0], ch); return (1); } title = argv[i]; } break; default : _cupsLangPrintf(stderr, _("%s: Error - unknown option \"%c\"."), argv[0], argv[i][1]); return (1); } else if (num_files < 1000) { /* * Print a file... */ if (access(argv[i], R_OK) != 0) { _cupsLangPrintf(stderr, _("%s: Error - unable to access \"%s\" - %s"), argv[0], argv[i], strerror(errno)); return (1); } files[num_files] = argv[i]; num_files ++; if (title == NULL) { if ((title = strrchr(argv[i], '/')) != NULL) title ++; else title = argv[i]; } } else _cupsLangPrintf(stderr, _("%s: Error - too many files - \"%s\"."), argv[0], argv[i]); /* * See if we have any files to print; if not, print from stdin... */ if (printer == NULL) { if ((dest = cupsGetNamedDest(NULL, NULL, NULL)) != NULL) { printer = dest->name; for (j = 0; j < dest->num_options; j ++) if (cupsGetOption(dest->options[j].name, num_options, options) == NULL) num_options = cupsAddOption(dest->options[j].name, dest->options[j].value, num_options, &options); } } if (printer == NULL) { val = NULL; if ((printer = getenv("LPDEST")) == NULL) { if ((printer = getenv("PRINTER")) != NULL) { if (!strcmp(printer, "lp")) printer = NULL; else val = "PRINTER"; } } else val = "LPDEST"; if (printer && !cupsGetNamedDest(NULL, printer, NULL)) _cupsLangPrintf(stderr, _("%s: Error - %s environment variable names " "non-existent destination \"%s\"."), argv[0], val, printer); else if (cupsLastError() == IPP_NOT_FOUND) _cupsLangPrintf(stderr, _("%s: Error - no default destination available."), argv[0]); else _cupsLangPrintf(stderr, _("%s: Error - scheduler not responding."), argv[0]); return (1); } if (num_files > 0) { job_id = cupsPrintFiles(printer, num_files, files, title, num_options, options); if (deletefile && job_id > 0) { /* * Delete print files after printing... */ for (i = 0; i < num_files; i ++) unlink(files[i]); } } else if ((job_id = cupsCreateJob(CUPS_HTTP_DEFAULT, printer, title ? title : "(stdin)", num_options, options)) > 0) { http_status_t status; /* Write status */ const char *format; /* Document format */ ssize_t bytes; /* Bytes read */ if (cupsGetOption("raw", num_options, options)) format = CUPS_FORMAT_RAW; else if ((format = cupsGetOption("document-format", num_options, options)) == NULL) format = CUPS_FORMAT_AUTO; status = cupsStartDocument(CUPS_HTTP_DEFAULT, printer, job_id, NULL, format, 1); while (status == HTTP_CONTINUE && (bytes = read(0, buffer, sizeof(buffer))) > 0) status = cupsWriteRequestData(CUPS_HTTP_DEFAULT, buffer, bytes); if (status != HTTP_CONTINUE) { _cupsLangPrintf(stderr, _("%s: Error - unable to queue from stdin - %s."), argv[0], httpStatus(status)); cupsFinishDocument(CUPS_HTTP_DEFAULT, printer); cupsCancelJob2(CUPS_HTTP_DEFAULT, printer, job_id, 0); return (1); } if (cupsFinishDocument(CUPS_HTTP_DEFAULT, printer) != IPP_OK) { _cupsLangPrintf(stderr, "%s: %s", argv[0], cupsLastErrorString()); cupsCancelJob2(CUPS_HTTP_DEFAULT, printer, job_id, 0); return (1); } } if (job_id < 1) { _cupsLangPrintf(stderr, "%s: %s", argv[0], cupsLastErrorString()); return (1); } return (0); }
int /* I - 1 on success, 0 on failure */ load_configuration(void) { cups_file_t *fp; /* mailto.conf file */ const char *server_root, /* CUPS_SERVERROOT environment variable */ *server_admin; /* SERVER_ADMIN environment variable */ char line[1024], /* Line from file */ *value; /* Value for directive */ int linenum; /* Line number in file */ /* * Initialize defaults... */ mailtoCc[0] = '\0'; if ((server_admin = getenv("SERVER_ADMIN")) != NULL) strlcpy(mailtoFrom, server_admin, sizeof(mailtoFrom)); else snprintf(mailtoFrom, sizeof(mailtoFrom), "root@%s", httpGetHostname(NULL, line, sizeof(line))); strlcpy(mailtoSendmail, "/usr/sbin/sendmail", sizeof(mailtoSendmail)); mailtoSMTPServer[0] = '\0'; mailtoSubject[0] = '\0'; /* * Try loading the config file... */ if ((server_root = getenv("CUPS_SERVERROOT")) == NULL) server_root = CUPS_SERVERROOT; snprintf(line, sizeof(line), "%s/mailto.conf", server_root); if ((fp = cupsFileOpen(line, "r")) == NULL) { fprintf(stderr, "ERROR: Unable to open \"%s\" - %s\n", line, strerror(errno)); return (1); } linenum = 0; while (cupsFileGetConf(fp, line, sizeof(line), &value, &linenum)) { if (!value) { fprintf(stderr, "ERROR: No value found for %s directive on line %d!\n", line, linenum); cupsFileClose(fp); return (0); } if (!strcasecmp(line, "Cc")) strlcpy(mailtoCc, value, sizeof(mailtoCc)); else if (!strcasecmp(line, "From")) strlcpy(mailtoFrom, value, sizeof(mailtoFrom)); else if (!strcasecmp(line, "Sendmail")) { strlcpy(mailtoSendmail, value, sizeof(mailtoSendmail)); mailtoSMTPServer[0] = '\0'; } else if (!strcasecmp(line, "SMTPServer")) { mailtoSendmail[0] = '\0'; strlcpy(mailtoSMTPServer, value, sizeof(mailtoSMTPServer)); } else if (!strcasecmp(line, "Subject")) strlcpy(mailtoSubject, value, sizeof(mailtoSubject)); else { fprintf(stderr, "ERROR: Unknown configuration directive \"%s\" on line %d!\n", line, linenum); } } /* * Close file and return... */ cupsFileClose(fp); return (1); }
const char * /* O - Filename for PPD file */ cupsGetPPD2(http_t *http, /* I - HTTP connection */ const char *name) /* I - Printer name */ { 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 */ _cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */ /* * Range check input... */ DEBUG_printf(("cupsGetPPD2(http=%p, name=\"%s\")\n", http, name ? name : "(null)")); if (!http || !name) { if (!http) _cupsSetError(IPP_INTERNAL_ERROR, "No HTTP connection!"); else _cupsSetError(IPP_INTERNAL_ERROR, "No printer name!"); return (NULL); } /* * Try finding a printer URI for this printer... */ if (!cups_get_printer_uri(http, name, hostname, sizeof(hostname), &port, resource, sizeof(resource), 0)) return (NULL); DEBUG_printf(("cupsGetPPD3: Printer hostname=\"%s\", port=%d\n", hostname, port)); /* * Remap local hostname to localhost... */ httpGetHostname(NULL, localhost, sizeof(localhost)); DEBUG_printf(("Local hostname=\"%s\"\n", localhost)); if (!strcasecmp(localhost, hostname)) strcpy(hostname, "localhost"); /* * Get the hostname and port number we are connected to... */ httpGetHostname(http, http_hostname, sizeof(http_hostname)); #ifdef AF_INET6 if (http->hostaddr->addr.sa_family == AF_INET6) http_port = ntohs(http->hostaddr->ipv6.sin6_port); else #endif /* AF_INET6 */ if (http->hostaddr->addr.sa_family == AF_INET) http_port = ntohs(http->hostaddr->ipv4.sin_port); else http_port = ippPort(); DEBUG_printf(("Connection hostname=\"%s\", port=%d\n", http_hostname, http_port)); /* * Reconnect to the correct server as needed... */ if (!strcasecmp(http_hostname, hostname) && port == http_port) http2 = http; else if ((http2 = httpConnectEncrypt(hostname, port, cupsEncryption())) == NULL) { DEBUG_puts("Unable to connect to server!"); return (NULL); } /* * Get a temp file... */ if ((fd = cupsTempFd(cg->ppd_filename, sizeof(cg->ppd_filename))) < 0) { /* * Can't open file; close the server connection and return NULL... */ _cupsSetError(IPP_INTERNAL_ERROR, strerror(errno)); if (http2 != http) httpClose(http2); return (NULL); } /* * And send a request to the HTTP server... */ strlcat(resource, ".ppd", sizeof(resource)); status = cupsGetFd(http2, resource, fd); close(fd); /* * See if we actually got the file or an error... */ if (status != HTTP_OK) { switch (status) { case HTTP_NOT_FOUND : _cupsSetError(IPP_NOT_FOUND, httpStatus(status)); break; case HTTP_UNAUTHORIZED : _cupsSetError(IPP_NOT_AUTHORIZED, httpStatus(status)); break; default : DEBUG_printf(("HTTP error %d mapped to IPP_SERVICE_UNAVAILABLE!\n", status)); _cupsSetError(IPP_SERVICE_UNAVAILABLE, httpStatus(status)); break; } unlink(cg->ppd_filename); return (NULL); } if (http2 != http) httpClose(http2); /* * Return the PPD file... */ return (cg->ppd_filename); }
int /* O - 1 on success, 0 on failure */ cupsAdminGetServerSettings( http_t *http, /* I - Connection to server or @code CUPS_HTTP_DEFAULT@ */ int *num_settings, /* O - Number of settings */ cups_option_t **settings) /* O - Settings */ { int i; /* Looping var */ cups_file_t *cupsd; /* cupsd.conf file */ char cupsdconf[1024]; /* cupsd.conf filename */ int remote; /* Remote cupsd.conf file? */ http_status_t status; /* Status of getting cupsd.conf */ char line[1024], /* Line from cupsd.conf file */ *value; /* Value on line */ cups_option_t *setting; /* Current setting */ _cups_globals_t *cg = _cupsGlobals(); /* Global data */ /* * Range check input... */ if (!http) { /* * See if we are connected to the same server... */ if (cg->http) { /* * Compare the connection hostname, port, and encryption settings to * the cached defaults; these were initialized the first time we * connected... */ if (strcmp(cg->http->hostname, cg->server) || cg->ipp_port != httpAddrPort(cg->http->hostaddr) || (cg->http->encryption != cg->encryption && cg->http->encryption == HTTP_ENCRYPTION_NEVER)) { /* * Need to close the current connection because something has changed... */ httpClose(cg->http); cg->http = NULL; } } /* * (Re)connect as needed... */ if (!cg->http) { if ((cg->http = httpConnect2(cupsServer(), ippPort(), NULL, AF_UNSPEC, cupsEncryption(), 1, 0, NULL)) == NULL) { if (errno) _cupsSetError(IPP_STATUS_ERROR_SERVICE_UNAVAILABLE, NULL, 0); else _cupsSetError(IPP_STATUS_ERROR_SERVICE_UNAVAILABLE, _("Unable to connect to host."), 1); if (num_settings) *num_settings = 0; if (settings) *settings = NULL; return (0); } } http = cg->http; } if (!http || !num_settings || !settings) { _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(EINVAL), 0); if (num_settings) *num_settings = 0; if (settings) *settings = NULL; return (0); } *num_settings = 0; *settings = NULL; /* * Get the cupsd.conf file... */ if ((status = get_cupsd_conf(http, cg, cg->cupsd_update, cupsdconf, sizeof(cupsdconf), &remote)) == HTTP_STATUS_OK) { if ((cupsd = cupsFileOpen(cupsdconf, "r")) == NULL) { char message[1024]; /* Message string */ snprintf(message, sizeof(message), _cupsLangString(cupsLangDefault(), _("Open of %s failed: %s")), cupsdconf, strerror(errno)); _cupsSetError(IPP_STATUS_ERROR_INTERNAL, message, 0); } } else cupsd = NULL; if (cupsd) { /* * Read the file, keeping track of what settings are enabled... */ int remote_access = 0, /* Remote access allowed? */ remote_admin = 0, /* Remote administration allowed? */ remote_any = 0, /* Remote access from anywhere allowed? */ browsing = 1, /* Browsing enabled? */ cancel_policy = 1, /* Cancel-job policy set? */ debug_logging = 0; /* LogLevel debug set? */ int linenum = 0, /* Line number in file */ in_location = 0, /* In a location section? */ in_policy = 0, /* In a policy section? */ in_cancel_job = 0, /* In a cancel-job section? */ in_admin_location = 0; /* In the /admin location? */ invalidate_cupsd_cache(cg); cg->cupsd_update = time(NULL); httpGetHostname(http, cg->cupsd_hostname, sizeof(cg->cupsd_hostname)); while (cupsFileGetConf(cupsd, line, sizeof(line), &value, &linenum)) { if (!value && strncmp(line, "</", 2)) value = line + strlen(line); if ((!_cups_strcasecmp(line, "Port") || !_cups_strcasecmp(line, "Listen")) && value) { char *port; /* Pointer to port number, if any */ if ((port = strrchr(value, ':')) != NULL) *port = '\0'; else if (isdigit(*value & 255)) { /* * Listen on a port number implies remote access... */ remote_access = 1; continue; } if (_cups_strcasecmp(value, "localhost") && strcmp(value, "127.0.0.1") #ifdef AF_LOCAL && *value != '/' #endif /* AF_LOCAL */ #ifdef AF_INET6 && strcmp(value, "[::1]") #endif /* AF_INET6 */ ) remote_access = 1; } else if (!_cups_strcasecmp(line, "Browsing")) { browsing = !_cups_strcasecmp(value, "yes") || !_cups_strcasecmp(value, "on") || !_cups_strcasecmp(value, "true"); } else if (!_cups_strcasecmp(line, "LogLevel")) { debug_logging = !_cups_strncasecmp(value, "debug", 5); } else if (!_cups_strcasecmp(line, "<Policy") && !_cups_strcasecmp(value, "default")) { in_policy = 1; } else if (!_cups_strcasecmp(line, "</Policy>")) { in_policy = 0; } else if (!_cups_strcasecmp(line, "<Limit") && in_policy && value) { /* * See if the policy limit is for the Cancel-Job operation... */ char *valptr; /* Pointer into value */ while (*value) { for (valptr = value; *valptr && !_cups_isspace(*valptr); valptr ++); if (*valptr) *valptr++ = '\0'; if (!_cups_strcasecmp(value, "cancel-job") || !_cups_strcasecmp(value, "all")) { in_cancel_job = 1; break; } for (value = valptr; _cups_isspace(*value); value ++); } } else if (!_cups_strcasecmp(line, "</Limit>")) { in_cancel_job = 0; } else if (!_cups_strcasecmp(line, "Require") && in_cancel_job) { cancel_policy = 0; } else if (!_cups_strcasecmp(line, "<Location") && value) { in_admin_location = !_cups_strcasecmp(value, "/admin"); in_location = 1; } else if (!_cups_strcasecmp(line, "</Location>")) { in_admin_location = 0; in_location = 0; } else if (!_cups_strcasecmp(line, "Allow") && value && _cups_strcasecmp(value, "localhost") && _cups_strcasecmp(value, "127.0.0.1") #ifdef AF_LOCAL && *value != '/' #endif /* AF_LOCAL */ #ifdef AF_INET6 && strcmp(value, "::1") #endif /* AF_INET6 */ ) { if (in_admin_location) remote_admin = 1; else if (!_cups_strcasecmp(value, "all")) remote_any = 1; } else if (line[0] != '<' && !in_location && !in_policy && _cups_strcasecmp(line, "Allow") && _cups_strcasecmp(line, "AuthType") && _cups_strcasecmp(line, "Deny") && _cups_strcasecmp(line, "Order") && _cups_strcasecmp(line, "Require") && _cups_strcasecmp(line, "Satisfy")) cg->cupsd_num_settings = cupsAddOption(line, value, cg->cupsd_num_settings, &(cg->cupsd_settings)); } cupsFileClose(cupsd); cg->cupsd_num_settings = cupsAddOption(CUPS_SERVER_DEBUG_LOGGING, debug_logging ? "1" : "0", cg->cupsd_num_settings, &(cg->cupsd_settings)); cg->cupsd_num_settings = cupsAddOption(CUPS_SERVER_REMOTE_ADMIN, (remote_access && remote_admin) ? "1" : "0", cg->cupsd_num_settings, &(cg->cupsd_settings)); cg->cupsd_num_settings = cupsAddOption(CUPS_SERVER_REMOTE_ANY, remote_any ? "1" : "0", cg->cupsd_num_settings, &(cg->cupsd_settings)); cg->cupsd_num_settings = cupsAddOption(CUPS_SERVER_SHARE_PRINTERS, (remote_access && browsing) ? "1" : "0", cg->cupsd_num_settings, &(cg->cupsd_settings)); cg->cupsd_num_settings = cupsAddOption(CUPS_SERVER_USER_CANCEL_ANY, cancel_policy ? "1" : "0", cg->cupsd_num_settings, &(cg->cupsd_settings)); } else if (status != HTTP_STATUS_NOT_MODIFIED) invalidate_cupsd_cache(cg); /* * Remove any temporary files and copy the settings array... */ if (remote) unlink(cupsdconf); for (i = cg->cupsd_num_settings, setting = cg->cupsd_settings; i > 0; i --, setting ++) *num_settings = cupsAddOption(setting->name, setting->value, *num_settings, settings); return (cg->cupsd_num_settings > 0); }
static gss_name_t /* O - Server name */ cups_gss_getname( http_t *http, /* I - Connection to server */ const char *service_name) /* I - Service name */ { gss_buffer_desc token = GSS_C_EMPTY_BUFFER; /* Service token */ OM_uint32 major_status, /* Major status code */ minor_status; /* Minor status code */ gss_name_t server_name; /* Server name */ char buf[1024]; /* Name buffer */ DEBUG_printf(("7cups_gss_getname(http=%p, service_name=\"%s\")", http, service_name)); /* * Get the hostname... */ if (!http->gsshost[0]) { httpGetHostname(http, http->gsshost, sizeof(http->gsshost)); if (!strcmp(http->gsshost, "localhost")) { if (gethostname(http->gsshost, sizeof(http->gsshost)) < 0) { DEBUG_printf(("1cups_gss_getname: gethostname() failed: %s", strerror(errno))); http->gsshost[0] = '\0'; return (NULL); } if (!strchr(http->gsshost, '.')) { /* * The hostname is not a FQDN, so look it up... */ struct hostent *host; /* Host entry to get FQDN */ if ((host = gethostbyname(http->gsshost)) != NULL && host->h_name) { /* * Use the resolved hostname... */ strlcpy(http->gsshost, host->h_name, sizeof(http->gsshost)); } else { DEBUG_printf(("1cups_gss_getname: gethostbyname(\"%s\") failed.", http->gsshost)); http->gsshost[0] = '\0'; return (NULL); } } } } /* * Get a service name we can use for authentication purposes... */ snprintf(buf, sizeof(buf), "%s@%s", service_name, http->gsshost); DEBUG_printf(("8cups_gss_getname: Looking up \"%s\".", buf)); token.value = buf; token.length = strlen(buf); server_name = GSS_C_NO_NAME; major_status = gss_import_name(&minor_status, &token, GSS_C_NT_HOSTBASED_SERVICE, &server_name); if (GSS_ERROR(major_status)) { cups_gss_printf(major_status, minor_status, "cups_gss_getname: gss_import_name() failed"); return (NULL); } return (server_name); }
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); }