libmicrohttpd2

HTTP server C library (MHD 2.x, alpha)
Log | Files | Refs | README | LICENSE

commit bdfc7e4abaca7fb8583f858d12435d98169e5a74
parent 8efda46ed9f5507e91712ea977e3ea79697349a4
Author: Evgeny Grin <k2k@drgrin.dev>
Date:   Fri,  2 May 2025 19:56:09 +0300

demo.c: fully ported to MSVC

Diffstat:
Msrc/examples2/demo.c | 207++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------
1 file changed, 179 insertions(+), 28 deletions(-)

diff --git a/src/examples2/demo.c b/src/examples2/demo.c @@ -30,24 +30,56 @@ * @author Karlson2k (Evgeny Grin) */ #include <microhttpd2.h> -#include <unistd.h> +#include <sys/types.h> +#include <stdbool.h> +#if ! defined(_WIN32) || defined(__CYGWIN__) +# include <unistd.h> +#else +# include <direct.h> +#endif #include <stdio.h> #include <stdlib.h> -#include <stdbool.h> #include <signal.h> #include <fcntl.h> #include <sys/stat.h> -#include <pthread.h> #include <string.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <dirent.h> +#if ! defined(_WIN32) || defined(__CYGWIN__) +# include <dirent.h> +#else +# include <io.h> +#endif #ifdef MHD_HAVE_LIBMAGIC -#include <magic.h> +# include <magic.h> #endif /* MHD_HAVE_LIBMAGIC */ #include <limits.h> #include <ctype.h> #include <errno.h> +#if defined(_WIN32) && ! defined(__CYGWIN__) +# include <locale.h> +#endif + +#if ! defined(_WIN32) || defined(__CYGWIN__) +# include <pthread.h> +typedef pthread_mutex_t my_mutex_t; +# define my_mutex_init(pmtx) ((void) pthread_mutex_init ((pmtx), NULL)) +# define my_mutex_destroy(pmtx) ((void) pthread_mutex_destroy ((pmtx))) +# define my_mutex_lock(pmtx) ((void) pthread_mutex_lock ((pmtx))) +# define my_mutex_unlock(pmtx) ((void) pthread_mutex_unlock ((pmtx))) +#else +# define WIN32_LEAN_AND_MEAN 1 +# include <windows.h> +typedef CRITICAL_SECTION my_mutex_t; +# define my_mutex_init(pmtx) ((void) InitializeCriticalSection ((pmtx))) +# define my_mutex_destroy(pmtx) DeleteCriticalSection ((pmtx)) +# define my_mutex_lock(pmtx) EnterCriticalSection ((pmtx)) +# define my_mutex_unlock(pmtx) LeaveCriticalSection ((pmtx)) +#endif + +#ifdef S_ISREG +# define my_S_ISREG(arg) S_ISREG (arg) +#else +# define my_S_ISREG(arg) (_S_IFREG == ((arg)&_S_IFMT)) +#endif #if defined(MHD_CPU_COUNT) && (MHD_CPU_COUNT + 0) < 2 #undef MHD_CPU_COUNT @@ -81,6 +113,56 @@ #define MAGIC_HEADER_SIZE (16 * 1024) #endif /* MHD_HAVE_LIBMAGIC */ +#if defined(_MSC_VER) && _MSC_VER < 1900 /* Before VS 2015 */ +/* _snprintf works differently, but the code handles it correctly */ +# define snprintf _snprintf +#endif + +#if ! defined(_WIN32) || defined(__CYGWIN__) +# define my_mkstemp(tmpl) mkstemp ((tmpl)) +#else +static int +my_mkstemp (char *template) +{ + int i; + + for (i = 0; i < 32; ++i) + { + char tmp_file_name[PATH_MAX + 1]; + HANDLE hndl; + if (0 == GetTempFileNameA (".", + template, + 0, + tmp_file_name)) + return -1; + hndl = CreateFileA (tmp_file_name, + GENERIC_READ | GENERIC_WRITE, + 0, + NULL, + CREATE_ALWAYS, + FILE_FLAG_SEQUENTIAL_SCAN, + NULL); + if (INVALID_HANDLE_VALUE != hndl) + { + int fd; + fd = _open_osfhandle ((intptr_t) hndl, + _O_RDWR | _O_BINARY); + if (-1 != fd) + { + strcpy (template, tmp_file_name); + return fd; /* Success */ + } + + /* Failure */ + CloseHandle (hndl); + } + (void) DeleteFileA (tmp_file_name); + } + return -1; +} + + +#endif #ifdef HAVE_STRDUP # define my_strdup(str) strdup ((str)) @@ -225,7 +307,7 @@ static struct MHD_Response *request_refused_response; /** * Mutex used when we update the cached directory response object. */ -static pthread_mutex_t mutex; +static my_mutex_t mutex; #ifdef MHD_HAVE_LIBMAGIC /** @@ -268,11 +350,11 @@ update_cached_response (struct MHD_Response *response) MHD_YES))) exit (1); } - (void) pthread_mutex_lock (&mutex); + my_mutex_lock (&mutex); if (NULL != cached_directory_response) MHD_response_destroy (cached_directory_response); cached_directory_response = response; - (void) pthread_mutex_unlock (&mutex); + my_mutex_unlock (&mutex); } @@ -310,6 +392,7 @@ static bool list_directory (struct ResponseDataContext *rdc, const char *dirname) { +#if ! defined(_WIN32) || defined(__CYGWIN__) char fullname[PATH_MAX + 1]; struct stat sbuf; DIR *dir; @@ -335,7 +418,8 @@ list_directory (struct ResponseDataContext *rdc, { void *r; - if ( (2 * rdc->buf_size + 1024) < rdc->buf_size) + if ((2 * rdc->buf_size < rdc->buf_size) || + (2 * rdc->buf_size + 1024) < rdc->buf_size) break; /* more than SIZE_T _index_ size? Too big for us */ rdc->buf_size = 2 * rdc->buf_size + 1024; if (NULL == (r = realloc (rdc->buf, rdc->buf_size))) @@ -354,6 +438,53 @@ list_directory (struct ResponseDataContext *rdc, rdc->off += (size_t) res; } (void) closedir (dir); +#else + char search_patt[PATH_MAX + 1]; + struct _finddatai64_t finfo; + intptr_t dir; + if (sizeof(search_patt) <= + (size_t) snprintf (search_patt, + sizeof(search_patt), + "%s\\*", + dirname)) + return false; + if (-1 == (dir = _findfirsti64 (search_patt, + &finfo))) + return false; + do + { + int res; + + if (0 != (finfo.attrib & (_A_HIDDEN | _A_SUBDIR | _A_SYSTEM))) + continue; /* Not a regular file, skip */ + if (rdc->off + 1024 > rdc->buf_size) + { + void *r; + + if ((2 * rdc->buf_size < rdc->buf_size) || + (2 * rdc->buf_size + 1024) < rdc->buf_size) + break; /* more than SIZE_T _index_ size? Too big for us */ + rdc->buf_size = 2 * rdc->buf_size + 1024; + if (NULL == (r = realloc (rdc->buf, rdc->buf_size))) + break; /* out of memory */ + rdc->buf = (char *) r; + } + res = snprintf (rdc->buf + rdc->off, + rdc->buf_size - rdc->off, + "<li><a href=\"/%s/%s\">%s</a></li>\n", + dirname, + finfo.name, + finfo.name); + if (0 >= res) + continue; /* snprintf() error */ + if (rdc->buf_size - rdc->off <= (size_t) res) + continue; /* buffer too small?? */ + rdc->off += (size_t) res; + + } while (0 == _findnexti64 (dir, + &finfo)); + (void) _findclose (dir); +#endif return true; } @@ -619,7 +750,7 @@ stream_reader (struct MHD_Request *req, if (! isprint ((unsigned char) uc->filename[i])) uc->filename[i] = '_'; } - uc->fd = mkstemp (uc->tmpname); + uc->fd = my_mkstemp (uc->tmpname); if (-1 == uc->fd) { fprintf (stderr, @@ -703,7 +834,7 @@ handle_full_upload (void *cls, return MHD_NO; } uc->filename = my_strdup (data->filename.cstr); - fd = mkstemp (uc->tmpname); + fd = my_mkstemp (uc->tmpname); if (-1 == fd) { fprintf (stderr, @@ -873,18 +1004,20 @@ done_cb (struct MHD_Request *req, request_refused_response); goto cleanup; } +#if ! defined(_WIN32) || defined(__CYGWIN__) chmod (uc->filename, S_IRUSR | S_IWUSR); +#endif update_directory (); - (void) pthread_mutex_lock (&mutex); + my_mutex_lock (&mutex); if (NULL == cached_directory_response) ret = MHD_upload_action_from_response (req, internal_error_response); else ret = MHD_upload_action_from_response (req, cached_directory_response); - (void) pthread_mutex_unlock (&mutex); + my_mutex_unlock (&mutex); cleanup: if (NULL != uc->filename) free (uc->filename); @@ -911,8 +1044,8 @@ cleanup: * socket closure). */ static const struct MHD_Action * generate_page (void *cls, - struct MHD_Request *request, - const struct MHD_String *path, + struct MHD_Request *MHD_RESTRICT request, + const struct MHD_String *MHD_RESTRICT path, enum MHD_HTTP_Method method, uint_fast64_t upload_size) { @@ -951,14 +1084,18 @@ generate_page (void *cls, "..")) && (0 != url[0]) && (0 != url[1]) && - ('/' != url[1]) ) - { - fd = open (&url[1], +#ifdef _WIN32 + ('\\' != url[1]) && + ((3 > path->len) || ':' != url[2]) && +#endif + ('/' != url[1]) ) + fd = open (url + 1, O_RDONLY); - if ( (-1 != fd) && - ( (0 != fstat (fd, - &buf)) || - (! S_ISREG (buf.st_mode)) ) ) + if (-1 != fd) + { + if ((0 != fstat (fd, + &buf)) + || ! my_S_ISREG (buf.st_mode)) { (void) close (fd); fd = -1; @@ -1059,14 +1196,14 @@ generate_page (void *cls, { const struct MHD_Action *ret; - (void) pthread_mutex_lock (&mutex); + my_mutex_lock (&mutex); if (NULL == cached_directory_response) ret = MHD_action_from_response (request, internal_error_response); else ret = MHD_action_from_response (request, cached_directory_response); - (void) pthread_mutex_unlock (&mutex); + my_mutex_unlock (&mutex); return ret; } /* unexpected request, refuse */ @@ -1115,6 +1252,17 @@ ignore_sigpipe (void) #endif +#if defined(_WIN32) && ! defined(__CYGWIN__) +static void +set_utf8_locale (void) +{ + if (NULL != setlocale (LC_CTYPE, ".UTF8")) + return; /* Success */ + (void) setlocale (LC_CTYPE, "C"); /* A fallback, not really helpful */ +} + + +#endif /** * Entry point to demo. Note: this HTTP server will make all @@ -1146,12 +1294,15 @@ main (int argc, #if ! defined(_WIN32) || defined(__CYGWIN__) ignore_sigpipe (); #endif +#if defined(_WIN32) && ! defined(__CYGWIN__) + set_utf8_locale (); +#endif #ifdef MHD_HAVE_LIBMAGIC magic = magic_open (MAGIC_MIME_TYPE); (void) magic_load (magic, NULL); #endif /* MHD_HAVE_LIBMAGIC */ - (void) pthread_mutex_init (&mutex, NULL); + my_mutex_init (&mutex); file_not_found_response = MHD_response_from_buffer_static ( MHD_HTTP_STATUS_NOT_FOUND, @@ -1219,7 +1370,7 @@ main (int argc, MHD_response_destroy (request_refused_response); MHD_response_destroy (internal_error_response); update_cached_response (NULL); - (void) pthread_mutex_destroy (&mutex); + my_mutex_destroy (&mutex); #ifdef MHD_HAVE_LIBMAGIC magic_close (magic); #endif /* MHD_HAVE_LIBMAGIC */