📄 client.c
字号:
con->http.state = HTTP_TRACE; else if (strcmp(operation, "OPTIONS") == 0) con->http.state = HTTP_OPTIONS; else if (strcmp(operation, "HEAD") == 0) con->http.state = HTTP_HEAD; else { LogMessage(L_ERROR, "Bad operation \"%s\"!", operation); SendError(con, HTTP_BAD_REQUEST); return (CloseClient(con)); } con->start = time(NULL); con->operation = con->http.state; LogMessage(L_DEBUG, "ReadClient: %d %s %s HTTP/%d.%d", con->http.fd, operation, con->uri, con->http.version / 100, con->http.version % 100); con->http.status = HTTP_OK; case HTTP_OPTIONS : case HTTP_DELETE : case HTTP_GET : case HTTP_HEAD : case HTTP_POST : case HTTP_PUT : case HTTP_TRACE : /* * Parse incoming parameters until the status changes... */ DEBUG_printf(("HTTP_POST Process:httUpdate()\n")); status = httpUpdate(HTTP(con)); if (status != HTTP_OK && status != HTTP_CONTINUE) { SendError(con, HTTP_BAD_REQUEST); return (CloseClient(con)); } break; default : break; /* Anti-compiler-warning-code */ } /* * Handle new transfers... */ if (status == HTTP_OK) { DEBUG_printf(("HTTP_OK Process\n")); if (con->http.fields[HTTP_FIELD_ACCEPT_LANGUAGE][0]) { /* * Figure out the locale from the Accept-Language and Content-Type * fields... */ if ((ptr = strchr(con->http.fields[HTTP_FIELD_ACCEPT_LANGUAGE], ',')) != NULL) *ptr = '\0'; if ((ptr = strchr(con->http.fields[HTTP_FIELD_ACCEPT_LANGUAGE], ';')) != NULL) *ptr = '\0'; if ((ptr = strstr(con->http.fields[HTTP_FIELD_CONTENT_TYPE], "charset=")) != NULL) { /* * Combine language and charset, and trim any extra params in the * content-type. */ snprintf(locale, sizeof(locale), "%s.%s", con->http.fields[HTTP_FIELD_ACCEPT_LANGUAGE], ptr + 8); if ((ptr = strchr(locale, ',')) != NULL) *ptr = '\0'; } else snprintf(locale, sizeof(locale), "%s.%s", con->http.fields[HTTP_FIELD_ACCEPT_LANGUAGE], DefaultCharset); con->language = cupsLangGet(locale); } else con->language = cupsLangGet(DefaultLocale);#if 0 decode_auth(con);#endif if (strncmp(con->http.fields[HTTP_FIELD_CONNECTION], "Keep-Alive", 10) == 0 && KeepAlive) con->http.keep_alive = HTTP_KEEPALIVE_ON; if (con->http.fields[HTTP_FIELD_HOST][0] == '\0' && con->http.version >= HTTP_1_1) { /* * HTTP/1.1 and higher require the "Host:" field... */ if (!SendError(con, HTTP_BAD_REQUEST)) return (CloseClient(con)); } #if 0 else if (con->operation == HTTP_OPTIONS) { /* * Do OPTIONS command... */ if ((best = FindBest(con->uri, con->http.state)) != NULL && best->type != AUTH_NONE) { if (!SendHeader(con, HTTP_UNAUTHORIZED, NULL)) return (CloseClient(con)); } if (strcasecmp(con->http.fields[HTTP_FIELD_CONNECTION], "Upgrade") == 0 && con->http.tls == NULL) {#ifdef HAVE_SSL /* * Do encryption stuff... */ if (!SendHeader(con, HTTP_SWITCHING_PROTOCOLS, NULL)) return (CloseClient(con)); httpPrintf(HTTP(con), "Connection: Upgrade\r\n"); httpPrintf(HTTP(con), "Upgrade: TLS/1.0,HTTP/1.1\r\n"); httpPrintf(HTTP(con), "Content-Length: 0\r\n"); httpPrintf(HTTP(con), "\r\n"); EncryptClient(con);#else if (!SendError(con, HTTP_NOT_IMPLEMENTED)) return (CloseClient(con));#endif /* HAVE_SSL */ } if (!SendHeader(con, HTTP_OK, NULL)) return (CloseClient(con)); httpPrintf(HTTP(con), "Allow: GET, HEAD, OPTIONS, POST, PUT\r\n"); httpPrintf(HTTP(con), "Content-Length: 0\r\n"); httpPrintf(HTTP(con), "\r\n"); } else if (!is_path_absolute(con->uri)) { /* * Protect against malicious users! */ if (!SendError(con, HTTP_FORBIDDEN)) return (CloseClient(con)); }#endif else { #if 0 if (strcasecmp(con->http.fields[HTTP_FIELD_CONNECTION], "Upgrade") == 0 && con->http.tls == NULL) {#ifdef HAVE_SSL /* * Do encryption stuff... */ if (!SendHeader(con, HTTP_SWITCHING_PROTOCOLS, NULL)) return (CloseClient(con)); httpPrintf(HTTP(con), "Connection: Upgrade\r\n"); httpPrintf(HTTP(con), "Upgrade: TLS/1.0,HTTP/1.1\r\n"); httpPrintf(HTTP(con), "Content-Length: 0\r\n"); httpPrintf(HTTP(con), "\r\n"); EncryptClient(con);#else if (!SendError(con, HTTP_NOT_IMPLEMENTED)) return (CloseClient(con));#endif /* HAVE_SSL */ } if ((status = IsAuthorized(con)) != HTTP_OK) { LogMessage(L_DEBUG2, "ReadClient: Unauthorized request for %s...\n", con->uri); SendError(con, status); return (CloseClient(con)); }#endif switch (con->http.state) {#if 0 case HTTP_GET_SEND : 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", 6) == 0 && strncmp(con->uri, "/admin/conf/", 12) != 0) || strncmp(con->uri, "/printers", 9) == 0 || strncmp(con->uri, "/classes", 8) == 0 || strncmp(con->uri, "/jobs", 5) == 0) { /* * Send CGI output... */ if (strncmp(con->uri, "/admin", 6) == 0) { SetStringf(&con->command, "%s/cgi-bin/admin.cgi", ServerBin); if ((ptr = strchr(con->uri + 6, '?')) != NULL) SetStringf(&con->options, "admin%s", ptr); else SetString(&con->options, "admin"); } else if (strncmp(con->uri, "/printers", 9) == 0) { SetStringf(&con->command, "%s/cgi-bin/printers.cgi", ServerBin); SetString(&con->options, con->uri + 9); } else if (strncmp(con->uri, "/classes", 8) == 0) { SetStringf(&con->command, "%s/cgi-bin/classes.cgi", ServerBin); SetString(&con->options, con->uri + 8); } else { SetStringf(&con->command, "%s/cgi-bin/jobs.cgi", ServerBin); SetString(&con->options, con->uri + 5); } if (con->options[0] == '/') cups_strcpy(con->options, con->options + 1); if (!SendCommand(con, con->command, con->options)) { if (!SendError(con, HTTP_NOT_FOUND)) return (CloseClient(con)); } else LogRequest(con, HTTP_OK); if (con->http.version <= HTTP_1_0) con->http.keep_alive = HTTP_KEEPALIVE_OFF; } else if (strncmp(con->uri, "/admin/conf/", 12) == 0 && (strchr(con->uri + 12, '/') != NULL || strlen(con->uri) == 12)) { /* * GET can only be done to configuration files under * /admin/conf... */ if (!SendError(con, HTTP_FORBIDDEN)) return (CloseClient(con)); break; } else { /* * Serve a file... */ if ((filename = get_file(con, &filestats, buf, sizeof(buf))) == NULL) { if (!SendError(con, HTTP_NOT_FOUND)) return (CloseClient(con)); break; } type = mimeFileType(MimeDatabase, filename, NULL); if (IsCGI(con, filename, &filestats, type)) { /* * Note: con->command and con->options were set by * IsCGI()... */ if (!SendCommand(con, con->command, con->options)) { if (!SendError(con, HTTP_NOT_FOUND)) return (CloseClient(con)); } else LogRequest(con, HTTP_OK); if (con->http.version <= HTTP_1_0) con->http.keep_alive = HTTP_KEEPALIVE_OFF; break; } if (!check_if_modified(con, &filestats)) { if (!SendError(con, HTTP_NOT_MODIFIED)) return (CloseClient(con)); } else { if (type == NULL) strcpy(line, "text/plain"); else snprintf(line, sizeof(line), "%s/%s", type->super, type->type); if (!SendFile(con, HTTP_OK, filename, line, &filestats)) return (CloseClient(con)); } } break;#endif case HTTP_POST_RECV : /* * See if the POST request includes a Content-Length field, and if * so check the length against any limits that are set... */ LogMessage(L_DEBUG2, "POST %s", con->uri); LogMessage(L_DEBUG2, "CONTENT_TYPE = %s", con->http.fields[HTTP_FIELD_CONTENT_TYPE]); if (con->http.fields[HTTP_FIELD_CONTENT_LENGTH][0] && atoi(con->http.fields[HTTP_FIELD_CONTENT_LENGTH]) > MaxRequestSize && MaxRequestSize > 0) { /* * Request too large... */ if (!SendError(con, HTTP_REQUEST_TOO_LARGE)) return (CloseClient(con)); break; } else if (atoi(con->http.fields[HTTP_FIELD_CONTENT_LENGTH]) < 0) { /* * Negative content lengths are invalid! */ if (!SendError(con, HTTP_BAD_REQUEST)) return (CloseClient(con)); break; } /* * See what kind of POST request this is; for IPP requests the * content-type field will be "application/ipp"... */ if (strcmp(con->http.fields[HTTP_FIELD_CONTENT_TYPE], "application/ipp") == 0) con->request = ippNew();#if 0 else if ((strncmp(con->uri, "/admin", 6) == 0 && strncmp(con->uri, "/admin/conf/", 12) != 0) || strncmp(con->uri, "/printers", 9) == 0 || strncmp(con->uri, "/classes", 8) == 0 || strncmp(con->uri, "/jobs", 5) == 0) { /* * CGI request... */ if (strncmp(con->uri, "/admin", 6) == 0) { SetStringf(&con->command, "%s/cgi-bin/admin.cgi", ServerBin); if ((ptr = strchr(con->uri + 6, '?')) != NULL) SetStringf(&con->options, "admin%s", ptr); else SetString(&con->options, "admin"); } else if (strncmp(con->uri, "/printers", 9) == 0) { SetStringf(&con->command, "%s/cgi-bin/printers.cgi", ServerBin); SetString(&con->options, con->uri + 9); } else if (strncmp(con->uri, "/classes", 8) == 0) { SetStringf(&con->command, "%s/cgi-bin/classes.cgi", ServerBin); SetString(&con->options, con->uri + 8); } else { SetStringf(&con->command, "%s/cgi-bin/jobs.cgi", ServerBin); SetString(&con->options, con->uri + 5); } if (con->options[0] == '/') cups_strcpy(con->options, con->options + 1); LogMessage(L_DEBUG2, "ReadClient: %d command=\"%s\", options = \"%s\"", con->http.fd, con->command, con->options); if (con->http.version <= HTTP_1_0) con->http.keep_alive = HTTP_KEEPALIVE_OFF; } else { /* * POST to a file... */ if ((filename = get_file(con, &filestats, buf, sizeof(buf))) == NULL) { if (!SendError(con, HTTP_NOT_FOUND)) return (CloseClient(con)); break; } type = mimeFileType(MimeDatabase, filename, NULL); if (!IsCGI(con, filename, &filestats, type)) { /* * Only POST to CGI's... */ if (!SendError(con, HTTP_UNAUTHORIZED)) return (CloseClient(con)); } }#endif break;#if 0 case HTTP_PUT_RECV : /* * Validate the resource name... */ if (strncmp(con->uri, "/admin/conf/", 12) != 0 || strchr(con->uri + 12, '/') != NULL || strlen(con->uri) == 12) { /* * PUT can only be done to configuration files under * /admin/conf... */ if (!SendError(con, HTTP_FORBIDDEN)) return (CloseClient(con)); break; } /* * See if the PUT request includes a Content-Length field, and if * so check the length against any limits that are set... */ LogMessage(L_DEBUG2, "PUT %s", con->uri); LogMessage(L_DEBUG2, "CONTENT_TYPE = %s", con->http.fields[HTTP_FIELD_CONTENT_TYPE]); if (con->http.fields[HTTP_FIELD_CONTENT_LENGTH][0] && atoi(con->http.fields[HTTP_FIELD_CONTENT_LENGTH]) > MaxRequestSize && MaxRequestSize > 0) { /* * Request too large... */ if (!SendError(con, HTTP_REQUEST_TOO_LARGE)) return (CloseClient(con)); break; } else if (atoi(con->http.fields[HTTP_FIELD_CONTENT_LENGTH]) < 0) { /* * Negative content lengths are invalid! */ if (!SendError(con, HTTP_BAD_REQUEST)) return (CloseClient(con)); break; } /* * Open a temporary file to hold the request... */ SetStringf(&con->filename, "%s/%08x", RequestRoot, request_id ++); con->file = open(con->filename, O_WRONLY | O_CREAT | O_TRUNC, 0640); 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); break; case HTTP_DELETE : case HTTP_TRACE :
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -