📄 client.c
字号:
SendError(con, HTTP_NOT_IMPLEMENTED); return (CloseClient(con)); case HTTP_HEAD : if (strncmp(con->uri, "/printers/", 10) == 0 && strcmp(con->uri + strlen(con->uri) - 4, ".ppd") == 0) { /* * Send PPD file - get the real printer name since printer * names are not case sensitive but filenames can be... */ con->uri[strlen(con->uri) - 4] = '\0'; /* Drop ".ppd" */ if ((p = FindPrinter(con->uri + 10)) != NULL) snprintf(con->uri, sizeof(con->uri), "/ppd/%s.ppd", p->name); else { if (!SendError(con, HTTP_NOT_FOUND)) return (CloseClient(con)); break; } } if ((strncmp(con->uri, "/admin/", 7) == 0 && strncmp(con->uri, "/admin/conf/", 12) != 0) || strncmp(con->uri, "/printers/", 10) == 0 || strncmp(con->uri, "/classes/", 9) == 0 || strncmp(con->uri, "/jobs/", 6) == 0) { /* * CGI output... */ if (!SendHeader(con, HTTP_OK, "text/html")) return (CloseClient(con)); if (httpPrintf(HTTP(con), "\r\n") < 0) return (CloseClient(con)); LogRequest(con, HTTP_OK); } else if (strncmp(con->uri, "/admin/conf/", 12) == 0 && (strchr(con->uri + 12, '/') != NULL || strlen(con->uri) == 12)) { /* * HEAD can only be done to configuration files under * /admin/conf... */ if (!SendError(con, HTTP_FORBIDDEN)) return (CloseClient(con)); break; } else if ((filename = get_file(con, &filestats, buf, sizeof(buf))) == NULL) { if (!SendHeader(con, HTTP_NOT_FOUND, "text/html")) return (CloseClient(con)); LogRequest(con, HTTP_NOT_FOUND); } else if (!check_if_modified(con, &filestats)) { if (!SendError(con, HTTP_NOT_MODIFIED)) return (CloseClient(con)); LogRequest(con, HTTP_NOT_MODIFIED); } else { /* * Serve a file... */ type = mimeFileType(MimeDatabase, filename, NULL); if (type == NULL) strcpy(line, "text/plain"); else snprintf(line, sizeof(line), "%s/%s", type->super, type->type); if (!SendHeader(con, HTTP_OK, line)) return (CloseClient(con)); if (httpPrintf(HTTP(con), "Last-Modified: %s\r\n", httpGetDateString(filestats.st_mtime)) < 0) return (CloseClient(con)); if (httpPrintf(HTTP(con), "Content-Length: %lu\r\n", (unsigned long)filestats.st_size) < 0) return (CloseClient(con)); LogRequest(con, HTTP_OK); } if (httpPrintf(HTTP(con), "\r\n") < 0) return (CloseClient(con)); con->http.state = HTTP_WAITING; break;#endif default : break; /* Anti-compiler-warning-code */ } } } /* * Handle any incoming data... */ switch (con->http.state) {#if 0 case HTTP_PUT_RECV : LogMessage(L_DEBUG2, "ReadClient: %d con->data_encoding = %s, con->data_remaining = %d, con->file = %d", con->http.fd, con->http.data_encoding == HTTP_ENCODE_CHUNKED ? "chunked" : "length", con->http.data_remaining, con->file); if ((bytes = httpRead(HTTP(con), line, sizeof(line))) < 0) return (CloseClient(con)); else if (bytes > 0) { con->bytes += bytes; LogMessage(L_DEBUG2, "ReadClient: %d writing %d bytes to %d", con->http.fd, bytes, con->file); if (write(con->file, line, bytes) < bytes) { LogMessage(L_ERROR, "ReadClient: Unable to write %d bytes to %s: %s", bytes, con->filename, strerror(errno)); close(con->file); con->file = -1; unlink(con->filename); ClearString(&con->filename); if (!SendError(con, HTTP_REQUEST_TOO_LARGE)) return (CloseClient(con)); } } if (con->http.state == HTTP_WAITING) { /* * End of file, see how big it is... */ fstat(con->file, &filestats); LogMessage(L_DEBUG2, "ReadClient: %d Closing data file %d, size = %d.", con->http.fd, con->file, (int)filestats.st_size); close(con->file); con->file = -1; if (filestats.st_size > MaxRequestSize && MaxRequestSize > 0) { /* * Request is too big; remove it and send an error... */ LogMessage(L_DEBUG2, "ReadClient: %d Removing temp file %s", con->http.fd, con->filename); unlink(con->filename); ClearString(&con->filename); if (!SendError(con, HTTP_REQUEST_TOO_LARGE)) return (CloseClient(con)); } /* * Install the configuration file... */ status = install_conf_file(con); /* * Return the status to the client... */ if (!SendError(con, status)) return (CloseClient(con)); } break;#endif case HTTP_POST_RECV : LogMessage(L_DEBUG2, "ReadClient: %d con->data_encoding = %s, con->data_remaining = %d, con->file = %d", con->http.fd, con->http.data_encoding == HTTP_ENCODE_CHUNKED ? "chunked" : "length", con->http.data_remaining, con->file); if (con->request != NULL) { /* * Grab any request data from the connection... */ if ((ipp_state = ippRead(&(con->http), con->request)) == IPP_ERROR) { LogMessage(L_ERROR, "ReadClient: %d IPP Read Error!", con->http.fd); SendError(con, HTTP_BAD_REQUEST); return (CloseClient(con)); } else if (ipp_state != IPP_DATA) break; else con->bytes += ippLength(con->request); } if (con->file < 0 && con->http.state != HTTP_POST_SEND) { /* * Create a file as needed for the request data... */ SetStringf(&con->filename, "%s/lp0", CUPS_DATADIR);#if 0 con->file = open(con->filename, O_WRONLY | O_CREAT | O_TRUNC, 0640);#else DEBUG_printf(("printer_get [0]")); SFD = printer_get(con, con->filename); con->file = SFD; if(-1 == SFD) con->http.state = HTTP_POST_SEND; else { DEBUG_printf(("printer_get [1]")); ftruncate(con->file, 0); DEBUG_printf(("printer_get [2]"));#endif LogMessage(L_DEBUG2, "ReadClient: %d REQUEST %s=%d", con->http.fd, con->filename, con->file); if (con->file < 0) { if (!SendError(con, HTTP_REQUEST_TOO_LARGE)) return (CloseClient(con)); } fchmod(con->file, 0640); fchown(con->file, RunUser, Group); fcntl(con->file, F_SETFD, fcntl(con->file, F_GETFD) | FD_CLOEXEC); } } if (con->http.state != HTTP_POST_SEND) { if ((bytes = httpRead(HTTP(con), line, sizeof(line))) < 0) return (CloseClient(con)); else if (bytes > 0) {#if 1 static int cur = 0; cur += bytes; if(cur > (cur%(1<<15))) { cur %= (1<<15); sleep(1); DEBUG_printf(("sleep: 1 sec\t")); } DEBUG_printf(("cur size: %d \n"));#endif con->bytes += bytes; LogMessage(L_DEBUG2, "ReadClient: %d writing %d bytes to %d", con->http.fd, bytes, con->file); if (write(con->file, line, bytes) < bytes) { LogMessage(L_ERROR, "ReadClient: Unable to write %d bytes to %s: %s", bytes, con->filename, strerror(errno)); close(con->file); con->file = -1;#if 0 unlink(con->filename);#endif ClearString(&con->filename); if (!SendError(con, HTTP_REQUEST_TOO_LARGE)) return (CloseClient(con)); } } else if (con->http.state == HTTP_POST_RECV) return (1); /* ??? */ else if (con->http.state != HTTP_POST_SEND) return (CloseClient(con)); } if (con->http.state == HTTP_POST_SEND) {#if 0 if (con->file >= 0) { fstat(con->file, &filestats); LogMessage(L_DEBUG2, "ReadClient: %d Closing data file %d, size = %d.", con->http.fd, con->file, (int)filestats.st_size); close(con->file); con->file = -1; if (filestats.st_size > MaxRequestSize && MaxRequestSize > 0) { /* * Request is too big; remove it and send an error... */ LogMessage(L_DEBUG2, "ReadClient: %d Removing temp file %s", con->http.fd, con->filename); unlink(con->filename); ClearString(&con->filename); if (con->request) { /* * Delete any IPP request data... */ ippDelete(con->request); con->request = NULL; } if (!SendError(con, HTTP_REQUEST_TOO_LARGE)) return (CloseClient(con)); } if (con->command) { if (!SendCommand(con, con->command, con->options)) { if (!SendError(con, HTTP_NOT_FOUND)) return (CloseClient(con)); } else LogRequest(con, HTTP_OK); } }#endif if (con->request) return (ProcessIPPRequest(con)); } break; default : break; /* Anti-compiler-warning-code */ } if (!con->http.keep_alive && con->http.state == HTTP_WAITING) return (CloseClient(con)); else return (1); DEBUG_printf(("Function ReadClient()\n\n")); }#if 0/* * 'SendCommand()' - Send output from a command via HTTP. */intSendCommand(client_t *con, char *command, char *options){ int fd; if (con->filename) fd = open(con->filename, O_RDONLY); else fd = open("/dev/null", O_RDONLY); if (fd < 0) { LogMessage(L_ERROR, "SendCommand: %d Unable to open \"%s\" for reading: %s", con->http.fd, con->filename ? con->filename : "/dev/null", strerror(errno)); return (0); } fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC); con->pipe_pid = pipe_command(con, fd, &(con->file), command, options); close(fd); LogMessage(L_INFO, "Started \"%s\" (pid=%d)", command, con->pipe_pid); LogMessage(L_DEBUG, "SendCommand: %d file=%d", con->http.fd, con->file); if (con->pipe_pid == 0) return (0); fcntl(con->file, F_SETFD, fcntl(con->file, F_GETFD) | FD_CLOEXEC); LogMessage(L_DEBUG2, "SendCommand: Adding fd %d to InputSet...", con->file); LogMessage(L_DEBUG2, "SendCommand: Adding fd %d to OutputSet...", con->http.fd); FD_SET(con->file, InputSet); FD_SET(con->http.fd, OutputSet); if (!SendHeader(con, HTTP_OK, NULL)) return (0); if (con->http.version == HTTP_1_1) { con->http.data_encoding = HTTP_ENCODE_CHUNKED; if (httpPrintf(HTTP(con), "Transfer-Encoding: chunked\r\n") < 0) return (0); } con->file_ready = 0; con->got_fields = 0; con->field_col = 0; return (1);}#endif/* * 'SendError()' - Send an error message via HTTP. */int /* O - 1 if successful, 0 otherwise */SendError(client_t *con, /* I - Connection */ http_status_t code) /* I - Error code */{ char message[1024]; /* Message for user */ /* * Put the request in the access_log file... */ LogRequest(con, code); LogMessage(L_DEBUG, "SendError: %d code=%d (%s)", con->http.fd, code, httpStatus(code)); /* * To work around bugs in some proxies, don't use Keep-Alive for some * error messages... */ if (code >= HTTP_BAD_REQUEST) con->http.keep_alive = HTTP_KEEPALIVE_OFF; /* * Send an error message back to the client. If the error code is a * 400 or 500 series, make sure the message contains some text, too! */ if (!SendHeader(con, code, NULL)) return (0);#ifdef HAVE_SSL if (code == HTTP_UPGRADE_REQUIRED) if (httpPrintf(HTTP(con), "Connection: Upgrade\r\n") < 0) return (0); if (httpPrintf(HTTP(con), "Upgrade: TLS/1.0,HTTP/1.1\r\n") < 0) return (0);#endif /* HAVE_SSL */ if ((con->http.version >= HTTP_1_1 && !con->http.keep_alive) || (code >= HTTP_BAD_REQUEST && code != HTTP_UPGRADE_REQUIRED)) { if (httpPrintf(HTTP(con), "Connection: close\r\n") < 0) return (0); } if (code >= HTTP_BAD_REQUEST) { /* * Send a human-readable error message. */ snprintf(message, sizeof(message), "<HTML><HEAD><TITLE>%d %s</TITLE></HEAD>" "<BODY><H1>%s</H1>%s</BODY></HTML>\n", code, httpStatus(code), httpStatus(code), con->language ? con->language->messages[code] : httpStatus(code)); if (httpPrintf(HTTP(con), "Content-Type: text/html\r\n") < 0) return (0); if (httpPrintf(HTTP(con), "Content-Length: %d\r\n", (int)strlen(message)) < 0) return (0); if (httpPrintf(HTTP(con), "\r\n") < 0) return (0); if (httpPrintf(HTTP(con), "%s", message) < 0) return (0); } else if (httpPrintf(HTTP(con), "\r\n") < 0) return (0); con->http.state = HTTP_WAITING; return (1);}/* * 'SendFile()' - Send a file via HTTP. */intSendFile(client_t *con, http_status_t code, char *filename, char *type, struct stat *filestats)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -