From 1345f8bebb2b77a334fa3e8ae5899740a327058d Mon Sep 17 00:00:00 2001 From: Lammert Bies Date: Sat, 10 Dec 2016 22:59:06 +0100 Subject: [PATCH] Moved prepare_cgi_environment to own file --- Makefile | 1 + src/httplib_prepare_cgi_environment.c | 159 ++++++++++++++++++++++++++ src/libhttp-private.h | 1 + src/libhttp.c | 123 +------------------- 4 files changed, 162 insertions(+), 122 deletions(-) create mode 100644 src/httplib_prepare_cgi_environment.c diff --git a/Makefile b/Makefile index 799688ce..4f7a96d2 100644 --- a/Makefile +++ b/Makefile @@ -78,6 +78,7 @@ LIB_SOURCES = src/libhttp.c \ src/httplib_master_thread.c \ src/httplib_mkcol.c \ src/httplib_parse_net.c \ + src/httplib_prepare_cgi_environment.c \ src/httplib_process_new_connection.c \ src/httplib_produce_socket.c \ src/httplib_put_file.c \ diff --git a/src/httplib_prepare_cgi_environment.c b/src/httplib_prepare_cgi_environment.c new file mode 100644 index 00000000..c7d909cc --- /dev/null +++ b/src/httplib_prepare_cgi_environment.c @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2016 Lammert Bies + * Copyright (c) 2013-2016 the Civetweb developers + * Copyright (c) 2004-2013 Sergey Lyubka + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + + + +#include "libhttp-private.h" + + + +/* + * void XX_httplib_prepare_cgi_environment( struct mg_connection *conn, const char *prog, struct cgi_environment *env ); + * + * The function XX_httplib_prepare_cgi_environment() is used to prepare all + * environment variables before a CGI script is called. + */ + +#if !defined(NO_CGI) + +void XX_httplib_prepare_cgi_environment( struct mg_connection *conn, const char *prog, struct cgi_environment *env ) { + + const char *s; + struct vec var_vec; + char *p; + char src_addr[IP_ADDR_STR_LEN]; + char http_var_name[128]; + int i; + int truncated; + + if ( conn == NULL || prog == NULL || env == NULL ) return; + + env->conn = conn; + env->buflen = CGI_ENVIRONMENT_SIZE; + env->bufused = 0; + env->buf = (char *)XX_httplib_malloc(env->buflen); + env->varlen = MAX_CGI_ENVIR_VARS; + env->varused = 0; + env->var = (char **)XX_httplib_malloc(env->buflen * sizeof(char *)); + + XX_httplib_addenv( env, "SERVER_NAME=%s", conn->ctx->config[AUTHENTICATION_DOMAIN] ); + XX_httplib_addenv( env, "SERVER_ROOT=%s", conn->ctx->config[DOCUMENT_ROOT] ); + XX_httplib_addenv( env, "DOCUMENT_ROOT=%s", conn->ctx->config[DOCUMENT_ROOT] ); + XX_httplib_addenv( env, "SERVER_SOFTWARE=%s/%s", "LibHTTP", mg_version() ); + + /* Prepare the environment block */ + XX_httplib_addenv( env, "%s", "GATEWAY_INTERFACE=CGI/1.1" ); + XX_httplib_addenv( env, "%s", "SERVER_PROTOCOL=HTTP/1.1" ); + XX_httplib_addenv( env, "%s", "REDIRECT_STATUS=200" ); /* For PHP */ + +#if defined(USE_IPV6) + if (conn->client.lsa.sa.sa_family == AF_INET6) { + XX_httplib_addenv(env, "SERVER_PORT=%d", ntohs(conn->client.lsa.sin6.sin6_port)); + } else +#endif + { + XX_httplib_addenv(env, "SERVER_PORT=%d", ntohs(conn->client.lsa.sin.sin_port)); + } + + XX_httplib_sockaddr_to_string(src_addr, sizeof(src_addr), &conn->client.rsa); + + XX_httplib_addenv( env, "REMOTE_ADDR=%s", src_addr ); + XX_httplib_addenv( env, "REQUEST_METHOD=%s", conn->request_info.request_method ); + XX_httplib_addenv( env, "REMOTE_PORT=%d", conn->request_info.remote_port ); + XX_httplib_addenv( env, "REQUEST_URI=%s", conn->request_info.request_uri ); + XX_httplib_addenv( env, "LOCAL_URI=%s", conn->request_info.local_uri ); + + /* SCRIPT_NAME */ + XX_httplib_addenv(env, + "SCRIPT_NAME=%.*s", + (int)strlen(conn->request_info.local_uri) + - ((conn->path_info == NULL) ? 0 : (int)strlen(conn->path_info)), + conn->request_info.local_uri); + + XX_httplib_addenv(env, "SCRIPT_FILENAME=%s", prog); + + if ( conn->path_info == NULL ) XX_httplib_addenv( env, "PATH_TRANSLATED=%s", conn->ctx->config[DOCUMENT_ROOT] ); + else XX_httplib_addenv( env, "PATH_TRANSLATED=%s%s", conn->ctx->config[DOCUMENT_ROOT], conn->path_info ); + + XX_httplib_addenv(env, "HTTPS=%s", (conn->ssl == NULL) ? "off" : "on"); + + if ( (s = mg_get_header( conn, "Content-Type" ) ) != NULL ) XX_httplib_addenv( env, "CONTENT_TYPE=%s", s ); + if ( conn->request_info.query_string != NULL ) XX_httplib_addenv( env, "QUERY_STRING=%s", conn->request_info.query_string ); + if ( (s = mg_get_header( conn, "Content-Length" ) ) != NULL ) XX_httplib_addenv( env, "CONTENT_LENGTH=%s", s ); + if ( (s = getenv( "PATH" )) != NULL ) XX_httplib_addenv( env, "PATH=%s", s ); + if ( conn->path_info != NULL ) XX_httplib_addenv( env, "PATH_INFO=%s", conn->path_info ); + + if (conn->status_code > 0) { + /* CGI error handler should show the status code */ + XX_httplib_addenv(env, "STATUS=%d", conn->status_code); + } + +#if defined(_WIN32) + if ( (s = getenv( "COMSPEC" )) != NULL ) XX_httplib_addenv( env, "COMSPEC=%s", s ); + if ( (s = getenv( "SYSTEMROOT" )) != NULL ) XX_httplib_addenv( env, "SYSTEMROOT=%s", s ); + if ( (s = getenv( "SystemDrive" )) != NULL ) XX_httplib_addenv( env, "SystemDrive=%s", s ); + if ( (s = getenv( "ProgramFiles" )) != NULL ) XX_httplib_addenv( env, "ProgramFiles=%s", s ); + if ( (s = getenv( "ProgramFiles(x86)" )) != NULL ) XX_httplib_addenv( env, "ProgramFiles(x86)=%s", s ); +#else + if ( (s = getenv("LD_LIBRARY_PATH" )) != NULL ) XX_httplib_addenv( env, "LD_LIBRARY_PATH=%s", s ); +#endif /* _WIN32 */ + + if ( (s = getenv("PERLLIB" )) != NULL ) XX_httplib_addenv( env, "PERLLIB=%s", s ); + + if (conn->request_info.remote_user != NULL) { + XX_httplib_addenv(env, "REMOTE_USER=%s", conn->request_info.remote_user); + XX_httplib_addenv(env, "%s", "AUTH_TYPE=Digest"); + } + + /* Add all headers as HTTP_* variables */ + for (i = 0; i < conn->request_info.num_headers; i++) { + + XX_httplib_snprintf(conn, &truncated, http_var_name, sizeof(http_var_name), "HTTP_%s", conn->request_info.http_headers[i].name); + + if (truncated) { + mg_cry(conn, "%s: HTTP header variable too long [%s]", __func__, conn->request_info.http_headers[i].name); + continue; + } + + /* Convert variable name into uppercase, and change - to _ */ + for (p = http_var_name; *p != '\0'; p++) { + if (*p == '-') *p = '_'; + *p = (char)toupper(*(unsigned char *)p); + } + + XX_httplib_addenv(env, "%s=%s", http_var_name, conn->request_info.http_headers[i].value); + } + + /* Add user-specified variables */ + s = conn->ctx->config[CGI_ENVIRONMENT]; + while ((s = XX_httplib_next_option(s, &var_vec, NULL)) != NULL) { + XX_httplib_addenv(env, "%.*s", (int)var_vec.len, var_vec.ptr); + } + + env->var[env->varused] = NULL; + env->buf[env->bufused] = '\0'; + +} /* XX_httplib_prepare_cgi_environment */ + +#endif /* !NO_CGI */ diff --git a/src/libhttp-private.h b/src/libhttp-private.h index 54d41716..4dacdac0 100644 --- a/src/libhttp-private.h +++ b/src/libhttp-private.h @@ -878,6 +878,7 @@ void SHA1Init( SHA1_CTX *context ); void SHA1Update( SHA1_CTX *context, const unsigned char *data, uint32_t len ); void XX_httplib_accept_new_connection( const struct socket *listener, struct mg_context *ctx ); +void XX_httplib_addenv( struct cgi_environment *env, PRINTF_FORMAT_STRING(const char *fmt), ... ) PRINTF_ARGS(2, 3); int XX_httplib_atomic_dec( volatile int *addr ); int XX_httplib_atomic_inc( volatile int *addr ); void XX_httplib_base64_encode( const unsigned char *src, int src_len, char *dst ); diff --git a/src/libhttp.c b/src/libhttp.c index 14e3d761..5ac1fc62 100644 --- a/src/libhttp.c +++ b/src/libhttp.c @@ -5528,11 +5528,10 @@ int XX_httplib_forward_body_data( struct mg_connection *conn, FILE *fp, SOCKET s #if !defined(NO_CGI) -static void addenv(struct cgi_environment *env, PRINTF_FORMAT_STRING(const char *fmt), ...) PRINTF_ARGS(2, 3); /* Append VARIABLE=VALUE\0 string to the buffer, and add a respective * pointer into the vars array. Assumes env != NULL and fmt != NULL. */ -static void addenv(struct cgi_environment *env, const char *fmt, ...) { +void XX_httplib_addenv( struct cgi_environment *env, const char *fmt, ... ) { size_t n; size_t space; @@ -5593,124 +5592,4 @@ static void addenv(struct cgi_environment *env, const char *fmt, ...) { env->varused++; } - -void XX_httplib_prepare_cgi_environment( struct mg_connection *conn, const char *prog, struct cgi_environment *env ) { - - const char *s; - struct vec var_vec; - char *p; - char src_addr[IP_ADDR_STR_LEN]; - char http_var_name[128]; - int i; - int truncated; - - if ( conn == NULL || prog == NULL || env == NULL ) return; - - env->conn = conn; - env->buflen = CGI_ENVIRONMENT_SIZE; - env->bufused = 0; - env->buf = (char *)XX_httplib_malloc(env->buflen); - env->varlen = MAX_CGI_ENVIR_VARS; - env->varused = 0; - env->var = (char **)XX_httplib_malloc(env->buflen * sizeof(char *)); - - addenv( env, "SERVER_NAME=%s", conn->ctx->config[AUTHENTICATION_DOMAIN] ); - addenv( env, "SERVER_ROOT=%s", conn->ctx->config[DOCUMENT_ROOT] ); - addenv( env, "DOCUMENT_ROOT=%s", conn->ctx->config[DOCUMENT_ROOT] ); - addenv( env, "SERVER_SOFTWARE=%s/%s", "LibHTTP", mg_version() ); - - /* Prepare the environment block */ - addenv( env, "%s", "GATEWAY_INTERFACE=CGI/1.1" ); - addenv( env, "%s", "SERVER_PROTOCOL=HTTP/1.1" ); - addenv( env, "%s", "REDIRECT_STATUS=200" ); /* For PHP */ - -#if defined(USE_IPV6) - if (conn->client.lsa.sa.sa_family == AF_INET6) { - addenv(env, "SERVER_PORT=%d", ntohs(conn->client.lsa.sin6.sin6_port)); - } else -#endif - { - addenv(env, "SERVER_PORT=%d", ntohs(conn->client.lsa.sin.sin_port)); - } - - XX_httplib_sockaddr_to_string(src_addr, sizeof(src_addr), &conn->client.rsa); - - addenv( env, "REMOTE_ADDR=%s", src_addr ); - addenv( env, "REQUEST_METHOD=%s", conn->request_info.request_method ); - addenv( env, "REMOTE_PORT=%d", conn->request_info.remote_port ); - addenv( env, "REQUEST_URI=%s", conn->request_info.request_uri ); - addenv( env, "LOCAL_URI=%s", conn->request_info.local_uri ); - - /* SCRIPT_NAME */ - addenv(env, - "SCRIPT_NAME=%.*s", - (int)strlen(conn->request_info.local_uri) - - ((conn->path_info == NULL) ? 0 : (int)strlen(conn->path_info)), - conn->request_info.local_uri); - - addenv(env, "SCRIPT_FILENAME=%s", prog); - - if ( conn->path_info == NULL ) addenv( env, "PATH_TRANSLATED=%s", conn->ctx->config[DOCUMENT_ROOT] ); - else addenv( env, "PATH_TRANSLATED=%s%s", conn->ctx->config[DOCUMENT_ROOT], conn->path_info ); - - addenv(env, "HTTPS=%s", (conn->ssl == NULL) ? "off" : "on"); - - if ( (s = mg_get_header( conn, "Content-Type" ) ) != NULL ) addenv( env, "CONTENT_TYPE=%s", s ); - if ( conn->request_info.query_string != NULL ) addenv( env, "QUERY_STRING=%s", conn->request_info.query_string ); - if ( (s = mg_get_header( conn, "Content-Length" ) ) != NULL ) addenv( env, "CONTENT_LENGTH=%s", s ); - if ( (s = getenv( "PATH" )) != NULL ) addenv( env, "PATH=%s", s ); - if ( conn->path_info != NULL ) addenv( env, "PATH_INFO=%s", conn->path_info ); - - if (conn->status_code > 0) { - /* CGI error handler should show the status code */ - addenv(env, "STATUS=%d", conn->status_code); - } - -#if defined(_WIN32) - if ( (s = getenv( "COMSPEC" )) != NULL ) addenv( env, "COMSPEC=%s", s ); - if ( (s = getenv( "SYSTEMROOT" )) != NULL ) addenv( env, "SYSTEMROOT=%s", s ); - if ( (s = getenv( "SystemDrive" )) != NULL ) addenv( env, "SystemDrive=%s", s ); - if ( (s = getenv( "ProgramFiles" )) != NULL ) addenv( env, "ProgramFiles=%s", s ); - if ( (s = getenv( "ProgramFiles(x86)" )) != NULL ) addenv( env, "ProgramFiles(x86)=%s", s ); -#else - if ( (s = getenv("LD_LIBRARY_PATH" )) != NULL ) addenv( env, "LD_LIBRARY_PATH=%s", s ); -#endif /* _WIN32 */ - - if ( (s = getenv("PERLLIB" )) != NULL ) addenv( env, "PERLLIB=%s", s ); - - if (conn->request_info.remote_user != NULL) { - addenv(env, "REMOTE_USER=%s", conn->request_info.remote_user); - addenv(env, "%s", "AUTH_TYPE=Digest"); - } - - /* Add all headers as HTTP_* variables */ - for (i = 0; i < conn->request_info.num_headers; i++) { - - XX_httplib_snprintf(conn, &truncated, http_var_name, sizeof(http_var_name), "HTTP_%s", conn->request_info.http_headers[i].name); - - if (truncated) { - mg_cry(conn, "%s: HTTP header variable too long [%s]", __func__, conn->request_info.http_headers[i].name); - continue; - } - - /* Convert variable name into uppercase, and change - to _ */ - for (p = http_var_name; *p != '\0'; p++) { - if (*p == '-') *p = '_'; - *p = (char)toupper(*(unsigned char *)p); - } - - addenv(env, "%s=%s", http_var_name, conn->request_info.http_headers[i].value); - } - - /* Add user-specified variables */ - s = conn->ctx->config[CGI_ENVIRONMENT]; - while ((s = XX_httplib_next_option(s, &var_vec, NULL)) != NULL) { - addenv(env, "%.*s", (int)var_vec.len, var_vec.ptr); - } - - env->var[env->varused] = NULL; - env->buf[env->bufused] = '\0'; - -} /* XX_httplib_prepare_cgi_environment */ - #endif /* !NO_CGI */