X-Git-Url: https://git.pterodactylus.net/?a=blobdiff_plain;f=libs%2Fshttpd%2Fcompat_win32.c;fp=libs%2Fshttpd%2Fcompat_win32.c;h=0000000000000000000000000000000000000000;hb=dec33c63afafabf83c3039e916725cac6faef9b3;hp=05f6036553f137ae12854ed0febdb3305e456624;hpb=9b22dd53fe62e312c1647310b7ec43aa127090af;p=fms.git diff --git a/libs/shttpd/compat_win32.c b/libs/shttpd/compat_win32.c deleted file mode 100644 index 05f6036..0000000 --- a/libs/shttpd/compat_win32.c +++ /dev/null @@ -1,442 +0,0 @@ -/* - * Copyright (c) 2004-2005 Sergey Lyubka - * All rights reserved - * - * "THE BEER-WARE LICENSE" (Revision 42): - * Sergey Lyubka wrote this file. As long as you retain this notice you - * can do whatever you want with this stuff. If we meet some day, and you think - * this stuff is worth it, you can buy me a beer in return. - */ - -#include "defs.h" - -static void -fix_directory_separators(char *path) -{ - for (; *path != '\0'; path++) { - if (*path == '/') - *path = '\\'; - if (*path == '\\') - while (path[1] == '\\' || path[1] == '/') - (void) memmove(path + 1, - path + 2, strlen(path + 2) + 1); - } -} - -static int -protect_against_code_disclosure(const char *path) -{ - WIN32_FIND_DATA data; - HANDLE handle; - const char *p; - - /* - * Protect against CGI code disclosure under Windows. - * This is very nasty hole. Windows happily opens files with - * some garbage in the end of file name. So fopen("a.cgi ", "r") - * actually opens "a.cgi", and does not return an error! And since - * "a.cgi " does not have valid CGI extension, this leads to - * the CGI code disclosure. - * To protect, here we delete all fishy characters from the - * end of file name. - */ - - if ((handle = FindFirstFile(path, &data)) == INVALID_HANDLE_VALUE) - return (FALSE); - - FindClose(handle); - - for (p = path + strlen(path); p > path && p[-1] != '\\';) - p--; - - if (!(data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && - strcmp(data.cFileName, p) != 0) - return (FALSE); - - return (TRUE); -} - -int -my_open(const char *path, int flags, int mode) -{ - char buf[FILENAME_MAX]; - wchar_t wbuf[FILENAME_MAX]; - - my_strlcpy(buf, path, sizeof(buf)); - fix_directory_separators(buf); - MultiByteToWideChar(CP_UTF8, 0, buf, -1, wbuf, sizeof(wbuf)); - - if (protect_against_code_disclosure(buf) == FALSE) - return (-1); - - return (_wopen(wbuf, flags)); -} - -int -my_stat(const char *path, struct stat *stp) -{ - char buf[FILENAME_MAX], *p; - wchar_t wbuf[FILENAME_MAX]; - - my_strlcpy(buf, path, sizeof(buf)); - fix_directory_separators(buf); - - p = buf + strlen(buf) - 1; - while (p > buf && *p == '\\' && p[-1] != ':') - *p-- = '\0'; - - MultiByteToWideChar(CP_UTF8, 0, buf, -1, wbuf, sizeof(wbuf)); - - return (_wstat(wbuf, (struct _stat *) stp)); -} - -int -my_remove(const char *path) -{ - char buf[FILENAME_MAX]; - wchar_t wbuf[FILENAME_MAX]; - - my_strlcpy(buf, path, sizeof(buf)); - fix_directory_separators(buf); - - MultiByteToWideChar(CP_UTF8, 0, buf, -1, wbuf, sizeof(wbuf)); - - return (_wremove(wbuf)); -} - -int -my_rename(const char *path1, const char *path2) -{ - char buf1[FILENAME_MAX]; - char buf2[FILENAME_MAX]; - wchar_t wbuf1[FILENAME_MAX]; - wchar_t wbuf2[FILENAME_MAX]; - - my_strlcpy(buf1, path1, sizeof(buf1)); - my_strlcpy(buf2, path2, sizeof(buf2)); - fix_directory_separators(buf1); - fix_directory_separators(buf2); - - MultiByteToWideChar(CP_UTF8, 0, buf1, -1, wbuf1, sizeof(wbuf1)); - MultiByteToWideChar(CP_UTF8, 0, buf2, -1, wbuf2, sizeof(wbuf2)); - - return (_wrename(wbuf1, wbuf2)); -} - -int -my_mkdir(const char *path, int mode) -{ - char buf[FILENAME_MAX]; - wchar_t wbuf[FILENAME_MAX]; - - my_strlcpy(buf, path, sizeof(buf)); - fix_directory_separators(buf); - - MultiByteToWideChar(CP_UTF8, 0, buf, -1, wbuf, sizeof(wbuf)); - - return (_wmkdir(wbuf)); -} - -static char * -wide_to_utf8(const wchar_t *str) -{ - char *buf = NULL; - if (str) { - int nchar = WideCharToMultiByte(CP_UTF8, 0, str, -1, NULL, 0, NULL, NULL); - if (nchar > 0) { - buf = malloc(nchar); - if (!buf) - errno = ENOMEM; - else if (!WideCharToMultiByte(CP_UTF8, 0, str, -1, buf, nchar, NULL, NULL)) { - free(buf); - buf = NULL; - errno = EINVAL; - } - } else - errno = EINVAL; - } else - errno = EINVAL; - return buf; -} - -char * -my_getcwd(char *buffer, int maxlen) -{ - char *result = NULL; - wchar_t *wbuffer, *wresult; - - if (buffer) { - /* User-supplied buffer */ - wbuffer = malloc(maxlen * sizeof(wchar_t)); - if (wbuffer == NULL) - return NULL; - } else - /* Dynamically allocated buffer */ - wbuffer = NULL; - wresult = _wgetcwd(wbuffer, maxlen); - if (wresult) { - int err = errno; - if (buffer) { - /* User-supplied buffer */ - int n = WideCharToMultiByte(CP_UTF8, 0, wresult, -1, buffer, maxlen, NULL, NULL); - if (n == 0) - err = ERANGE; - free(wbuffer); - result = buffer; - } else { - /* Buffer allocated by _wgetcwd() */ - result = wide_to_utf8(wresult); - err = errno; - free(wresult); - } - errno = err; - } - return result; -} - -DIR * -opendir(const char *name) -{ - DIR *dir = NULL; - char path[FILENAME_MAX]; - wchar_t wpath[FILENAME_MAX]; - - if (name == NULL || name[0] == '\0') { - errno = EINVAL; - } else if ((dir = malloc(sizeof(*dir))) == NULL) { - errno = ENOMEM; - } else { - my_snprintf(path, sizeof(path), "%s/*", name); - fix_directory_separators(path); - MultiByteToWideChar(CP_UTF8, 0, path, -1, wpath, sizeof(wpath)); - dir->handle = FindFirstFileW(wpath, &dir->info); - - if (dir->handle != INVALID_HANDLE_VALUE) { - dir->result.d_name[0] = '\0'; - } else { - free(dir); - dir = NULL; - } - } - - return (dir); -} - -int -closedir(DIR *dir) -{ - int result = -1; - - if (dir != NULL) { - if (dir->handle != INVALID_HANDLE_VALUE) - result = FindClose(dir->handle) ? 0 : -1; - - free(dir); - } - - if (result == -1) - errno = EBADF; - - return (result); -} - -struct dirent * -readdir(DIR *dir) -{ - struct dirent *result = 0; - - if (dir && dir->handle != INVALID_HANDLE_VALUE) { - if(!dir->result.d_name || - FindNextFileW(dir->handle, &dir->info)) { - result = &dir->result; - - WideCharToMultiByte(CP_UTF8, 0, dir->info.cFileName, - -1, result->d_name, - sizeof(result->d_name), NULL, NULL); - } - } else { - errno = EBADF; - } - - return (result); -} - -int -set_non_blocking_mode(int fd) -{ - unsigned long on = 1; - - return (ioctlsocket(fd, FIONBIO, &on)); -} - -void -set_close_on_exec(int fd) -{ - fd = 0; /* Do nothing. There is no FD_CLOEXEC on Windows */ -} - -#if !defined(NO_CGI) - -struct threadparam { - SOCKET s; - HANDLE hPipe; - big_int_t content_len; -}; - -/* - * Thread function that reads POST data from the socket pair - * and writes it to the CGI process. - */ -static void//DWORD WINAPI -stdoutput(void *arg) -{ - struct threadparam *tp = arg; - int n, sent, stop = 0; - big_int_t total = 0; - DWORD k; - char buf[BUFSIZ]; - size_t max_recv; - - max_recv = min(sizeof(buf), tp->content_len - total); - while (!stop && max_recv > 0 && (n = recv(tp->s, buf, max_recv, 0)) > 0) { - for (sent = 0; !stop && sent < n; sent += k) - if (!WriteFile(tp->hPipe, buf + sent, n - sent, &k, 0)) - stop++; - total += n; - max_recv = min(sizeof(buf), tp->content_len - total); - } - - CloseHandle(tp->hPipe); /* Suppose we have POSTed everything */ - free(tp); -} - -/* - * Thread function that reads CGI output and pushes it to the socket pair. - */ -static void -stdinput(void *arg) -{ - struct threadparam *tp = arg; - static int ntotal; - int k, stop = 0; - DWORD n, sent; - char buf[BUFSIZ]; - - while (!stop && ReadFile(tp->hPipe, buf, sizeof(buf), &n, NULL)) { - ntotal += n; - for (sent = 0; !stop && sent < n; sent += k) - if ((k = send(tp->s, buf + sent, n - sent, 0)) <= 0) - stop++; - } - CloseHandle(tp->hPipe); - - /* - * Windows is a piece of crap. When this thread closes its end - * of the socket pair, the other end (get_cgi() function) may loose - * some data. I presume, this happens if get_cgi() is not fast enough, - * and the data written by this end does not "push-ed" to the other - * end socket buffer. So after closesocket() the remaining data is - * gone. If I put shutdown() before closesocket(), that seems to - * fix the problem, but I am not sure this is the right fix. - * XXX (submitted by James Marshall) we do not do shutdown() on UNIX. - * If fork() is called from user callback, shutdown() messes up things. - */ - shutdown(tp->s, 2); - - closesocket(tp->s); - free(tp); - - _endthread(); -} - -static void -spawn_stdio_thread(int sock, HANDLE hPipe, void (*func)(void *), - big_int_t content_len) -{ - struct threadparam *tp; - DWORD tid; - - tp = malloc(sizeof(*tp)); - assert(tp != NULL); - - tp->s = sock; - tp->hPipe = hPipe; - tp->content_len = content_len; - _beginthread(func, 0, tp); -} - -int -spawn_process(struct conn *c, const char *prog, char *envblk, - char *envp[], int sock, const char *dir) -{ - HANDLE a[2], b[2], h[2], me; - DWORD flags; - char *p, cmdline[FILENAME_MAX], line[FILENAME_MAX]; - FILE *fp; - STARTUPINFOA si; - PROCESS_INFORMATION pi; - - me = GetCurrentProcess(); - flags = DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS; - - /* FIXME add error checking code here */ - CreatePipe(&a[0], &a[1], NULL, 0); - CreatePipe(&b[0], &b[1], NULL, 0); - DuplicateHandle(me, a[0], me, &h[0], 0, TRUE, flags); - DuplicateHandle(me, b[1], me, &h[1], 0, TRUE, flags); - - (void) memset(&si, 0, sizeof(si)); - (void) memset(&pi, 0, sizeof(pi)); - - /* XXX redirect CGI errors to the error log file */ - si.cb = sizeof(si); - si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; - si.wShowWindow = SW_HIDE; - si.hStdOutput = si.hStdError = h[1]; - si.hStdInput = h[0]; - - /* If CGI file is a script, try to read the interpreter line */ - if (c->ctx->options[OPT_CGI_INTERPRETER] == NULL) { - if ((fp = fopen(prog, "r")) != NULL) { - (void) fgets(line, sizeof(line), fp); - if (memcmp(line, "#!", 2) != 0) - line[2] = '\0'; - /* Trim whitespaces from interpreter name */ - for (p = &line[strlen(line) - 1]; p > line && - isspace(*p); p--) - *p = '\0'; - (void) fclose(fp); - } - (void) my_snprintf(cmdline, sizeof(cmdline), "%s%s%s", - line + 2, line[2] == '\0' ? "" : " ", prog); - } else { - (void) my_snprintf(cmdline, sizeof(cmdline), "%s %s", - c->ctx->options[OPT_CGI_INTERPRETER], prog); - } - - (void) my_snprintf(line, sizeof(line), "%s", dir); - fix_directory_separators(line); - fix_directory_separators(cmdline); - - /* - * Spawn reader & writer threads before we create CGI process. - * Otherwise CGI process may die too quickly, loosing the data - */ - spawn_stdio_thread(sock, b[0], stdinput, 0); - spawn_stdio_thread(sock, a[1], stdoutput, c->rem.content_len); - - if (CreateProcessA(NULL, cmdline, NULL, NULL, TRUE, - CREATE_NEW_PROCESS_GROUP, envblk, line, &si, &pi) == 0) { - elog(E_LOG, c,"redirect: CreateProcess(%s): %d",cmdline,ERRNO); - return (-1); - } else { - CloseHandle(h[0]); - CloseHandle(h[1]); - CloseHandle(pi.hThread); - CloseHandle(pi.hProcess); - } - - return (0); -} - -#endif /* !NO_CGI */