version 0.3.0
[fms.git] / libs / shttpd / compat_win32.c
diff --git a/libs/shttpd/compat_win32.c b/libs/shttpd/compat_win32.c
deleted file mode 100644 (file)
index 05f6036..0000000
+++ /dev/null
@@ -1,442 +0,0 @@
-/*
- * Copyright (c) 2004-2005 Sergey Lyubka <valenok@gmail.com>
- * 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 */