From 36f6fb197fd719ca58736d745e9106d2698e1593 Mon Sep 17 00:00:00 2001 From: Lammert Bies Date: Sun, 11 Dec 2016 13:37:30 +0100 Subject: [PATCH] Moved httplib_stat to own file --- Makefile | 1 + src/httplib_stat.c | 111 ++++++++++++++++++++++++++++++++++++++++++ src/libhttp-private.h | 1 + src/libhttp.c | 98 +++---------------------------------- 4 files changed, 121 insertions(+), 90 deletions(-) create mode 100644 src/httplib_stat.c diff --git a/Makefile b/Makefile index bb7d551a..aa578785 100644 --- a/Makefile +++ b/Makefile @@ -170,6 +170,7 @@ LIB_SOURCES = src/libhttp.c \ src/httplib_start.c \ src/httplib_start_thread.c \ src/httplib_start_thread_with_id.c \ + src/httplib_stat.c \ src/httplib_stop.c \ src/httplib_store_body.c \ src/httplib_substitute_index_file.c \ diff --git a/src/httplib_stat.c b/src/httplib_stat.c new file mode 100644 index 00000000..c0f2f2d3 --- /dev/null +++ b/src/httplib_stat.c @@ -0,0 +1,111 @@ +/* + * 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" + + +#if defined(_WIN32) + +int XX_httplib_stat( struct mg_connection *conn, const char *path, struct file *filep ) { + + wchar_t wbuf[PATH_MAX]; + WIN32_FILE_ATTRIBUTE_DATA info; + time_t creation_time; + + if ( filep == NULL ) return 0; + + memset(filep, 0, sizeof(*filep)); + + if (conn && XX_httplib_is_file_in_memory(conn, path, filep)) { + /* filep->is_directory = 0; filep->gzipped = 0; .. already done by + * memset */ + filep->last_modified = time(NULL); + /* last_modified = now ... assumes the file may change during runtime, + * so every XX_httplib_fopen call may return different data */ + /* last_modified = conn->ctx.start_time; + * May be used it the data does not change during runtime. This allows + * browser caching. Since we do not know, we have to assume the file + * in memory may change. */ + return 1; + } + + path_to_unicode(conn, path, wbuf, ARRAY_SIZE(wbuf)); + if (GetFileAttributesExW(wbuf, GetFileExInfoStandard, &info) != 0) { + filep->size = MAKEUQUAD(info.nFileSizeLow, info.nFileSizeHigh); + filep->last_modified = + SYS2UNIX_TIME(info.ftLastWriteTime.dwLowDateTime, + info.ftLastWriteTime.dwHighDateTime); + + /* On Windows, the file creation time can be higher than the + * modification time, e.g. when a file is copied. + * Since the Last-Modified timestamp is used for caching + * it should be based on the most recent timestamp. */ + creation_time = SYS2UNIX_TIME(info.ftCreationTime.dwLowDateTime, + info.ftCreationTime.dwHighDateTime); + if (creation_time > filep->last_modified) { + filep->last_modified = creation_time; + } + + filep->is_directory = info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY; + /* If file name is fishy, reset the file structure and return + * error. + * Note it is important to reset, not just return the error, cause + * functions like XX_httplib_is_file_opened() check the struct. */ + if (!filep->is_directory && !path_cannot_disclose_cgi(path)) { + memset(filep, 0, sizeof(*filep)); + return 0; + } + + return 1; + } + + return 0; + +} /* XX_httplib_stat */ + +#else + +int XX_httplib_stat( struct mg_connection *conn, const char *path, struct file *filep ) { + + struct stat st; + if (!filep) return 0; + + memset(filep, 0, sizeof(*filep)); + + if (conn && XX_httplib_is_file_in_memory(conn, path, filep)) return 1; + + if (0 == stat(path, &st)) { + filep->size = (uint64_t)(st.st_size); + filep->last_modified = st.st_mtime; + filep->is_directory = S_ISDIR(st.st_mode); + return 1; + } + + return 0; + +} /* XX_httplib_stat */ + +#endif /* _WIN32 */ diff --git a/src/libhttp-private.h b/src/libhttp-private.h index 159cef66..8f706b24 100644 --- a/src/libhttp-private.h +++ b/src/libhttp-private.h @@ -958,6 +958,7 @@ int XX_httplib_inet_pton( int af, const char *src, void *dst, size_t dstlen ); int XX_httplib_initialize_ssl( struct mg_context *ctx ); void XX_httplib_interpret_uri( struct mg_connection *conn, char *filename, size_t filename_buf_len, struct file *filep, int *is_found, int *is_script_resource, int *is_websocket_request, int *is_put_or_delete_request ); int XX_httplib_is_authorized_for_put( struct mg_connection *conn ); +int XX_httplib_is_file_in_memory( const struct mg_connection *conn, const char *path, struct file *filep ); bool XX_httplib_is_file_opened( const struct file *filep ); int XX_httplib_is_not_modified( const struct mg_connection *conn, const struct file *filep ); int XX_httplib_is_put_or_delete_method( const struct mg_connection *conn ); diff --git a/src/libhttp.c b/src/libhttp.c index 53138686..1c8b9722 100644 --- a/src/libhttp.c +++ b/src/libhttp.c @@ -834,7 +834,7 @@ const struct mg_option * mg_get_valid_options(void) { } /* mg_get_valid_options */ -static int is_file_in_memory(const struct mg_connection *conn, const char *path, struct file *filep) { +int XX_httplib_is_file_in_memory( const struct mg_connection *conn, const char *path, struct file *filep ) { size_t size = 0; @@ -851,7 +851,7 @@ static int is_file_in_memory(const struct mg_connection *conn, const char *path, return filep->membuf != NULL; -} /* is_file_in_memory */ +} /* XX_httplib_is_file_in_memory */ bool XX_httplib_is_file_opened( const struct file *filep ) { @@ -881,7 +881,7 @@ int XX_httplib_fopen( const struct mg_connection *conn, const char *path, const if (stat(path, &st) == 0) filep->size = (uint64_t)(st.st_size); - if (!is_file_in_memory(conn, path, filep)) { + if (!XX_httplib_is_file_in_memory(conn, path, filep)) { #ifdef _WIN32 wchar_t wbuf[PATH_MAX], wmode[20]; path_to_unicode(conn, path, wbuf, ARRAY_SIZE(wbuf)); @@ -1963,64 +1963,6 @@ static int path_cannot_disclose_cgi(const char *path) { } -int XX_httplib_stat( struct mg_connection *conn, const char *path, struct file *filep ) { - - wchar_t wbuf[PATH_MAX]; - WIN32_FILE_ATTRIBUTE_DATA info; - time_t creation_time; - - if ( filep == NULL ) return 0; - - memset(filep, 0, sizeof(*filep)); - - if (conn && is_file_in_memory(conn, path, filep)) { - /* filep->is_directory = 0; filep->gzipped = 0; .. already done by - * memset */ - filep->last_modified = time(NULL); - /* last_modified = now ... assumes the file may change during runtime, - * so every XX_httplib_fopen call may return different data */ - /* last_modified = conn->ctx.start_time; - * May be used it the data does not change during runtime. This allows - * browser caching. Since we do not know, we have to assume the file - * in memory may change. */ - return 1; - } - - path_to_unicode(conn, path, wbuf, ARRAY_SIZE(wbuf)); - if (GetFileAttributesExW(wbuf, GetFileExInfoStandard, &info) != 0) { - filep->size = MAKEUQUAD(info.nFileSizeLow, info.nFileSizeHigh); - filep->last_modified = - SYS2UNIX_TIME(info.ftLastWriteTime.dwLowDateTime, - info.ftLastWriteTime.dwHighDateTime); - - /* On Windows, the file creation time can be higher than the - * modification time, e.g. when a file is copied. - * Since the Last-Modified timestamp is used for caching - * it should be based on the most recent timestamp. */ - creation_time = SYS2UNIX_TIME(info.ftCreationTime.dwLowDateTime, - info.ftCreationTime.dwHighDateTime); - if (creation_time > filep->last_modified) { - filep->last_modified = creation_time; - } - - filep->is_directory = info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY; - /* If file name is fishy, reset the file structure and return - * error. - * Note it is important to reset, not just return the error, cause - * functions like XX_httplib_is_file_opened() check the struct. */ - if (!filep->is_directory && !path_cannot_disclose_cgi(path)) { - memset(filep, 0, sizeof(*filep)); - return 0; - } - - return 1; - } - - return 0; - -} /* XX_httplib_stat */ - - static int mg_remove(const struct mg_connection *conn, const char *path) { wchar_t wbuf[PATH_MAX]; @@ -2121,7 +2063,8 @@ static struct dirent * mg_readdir(DIR *dir) { #ifndef HAVE_POLL -static int poll(struct pollfd *pfd, unsigned int n, int milliseconds) { + +static int poll( struct pollfd *pfd, unsigned int n, int milliseconds ) { struct timeval tv; fd_set set; @@ -2148,34 +2091,9 @@ static int poll(struct pollfd *pfd, unsigned int n, int milliseconds) { } return result; -} + +} /* poll */ + #endif /* HAVE_POLL */ -#if defined(__MINGW32__) -/* Enable unused function warning again */ -#pragma GCC diagnostic pop -#endif - -#else - -int XX_httplib_stat( struct mg_connection *conn, const char *path, struct file *filep ) { - - struct stat st; - if (!filep) return 0; - - memset(filep, 0, sizeof(*filep)); - - if (conn && is_file_in_memory(conn, path, filep)) return 1; - - if (0 == stat(path, &st)) { - filep->size = (uint64_t)(st.st_size); - filep->last_modified = st.st_mtime; - filep->is_directory = S_ISDIR(st.st_mode); - return 1; - } - - return 0; - -} /* XX_httplib_stat */ - #endif /* _WIN32 */