]> git.mxchange.org Git - flightgear.git/blob - 3rdparty/mongoose/mongoose.c
Initial commit for mongoose httpd
[flightgear.git] / 3rdparty / mongoose / mongoose.c
1 // Copyright (c) 2004-2013 Sergey Lyubka <valenok@gmail.com>
2 // Copyright (c) 2013-2014 Cesanta Software Limited
3 // All rights reserved
4 //
5 // This library is dual-licensed: you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License version 2 as
7 // published by the Free Software Foundation. For the terms of this
8 // license, see <http://www.gnu.org/licenses/>.
9 //
10 // You are free to use this library under the terms of the GNU General
11 // Public License, but WITHOUT ANY WARRANTY; without even the implied
12 // warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 // See the GNU General Public License for more details.
14 //
15 // Alternatively, you can license this library under a commercial
16 // license, as set out in <http://cesanta.com/>.
17
18 #undef UNICODE                  // Use ANSI WinAPI functions
19 #undef _UNICODE                 // Use multibyte encoding on Windows
20 #define _MBCS                   // Use multibyte encoding on Windows
21 #define _INTEGRAL_MAX_BITS 64   // Enable _stati64() on Windows
22 #define _CRT_SECURE_NO_WARNINGS // Disable deprecation warning in VS2005+
23 #undef WIN32_LEAN_AND_MEAN      // Let windows.h always include winsock2.h
24 #define _XOPEN_SOURCE 600       // For flockfile() on Linux
25 #define __STDC_FORMAT_MACROS    // <inttypes.h> wants this for C++
26 #define __STDC_LIMIT_MACROS     // C++ wants that for INT64_MAX
27 #define _LARGEFILE_SOURCE       // Enable fseeko() and ftello() functions
28 #define _FILE_OFFSET_BITS 64    // Enable 64-bit file offsets
29
30 #ifdef _MSC_VER
31 #pragma warning (disable : 4127)  // FD_SET() emits warning, disable it
32 #pragma warning (disable : 4204)  // missing c99 support
33 #endif
34
35 #include <sys/types.h>
36 #include <sys/stat.h>
37 #include <stddef.h>
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <string.h>
41 #include <fcntl.h>
42 #include <assert.h>
43 #include <errno.h>
44 #include <time.h>
45 #include <ctype.h>
46 #include <stdarg.h>
47
48 #ifdef _WIN32
49 #include <windows.h>
50 #include <process.h>    // For _beginthread
51 #include <io.h>         // For _lseeki64
52 #include <direct.h>     // For _mkdir
53 typedef int socklen_t;
54 #if !defined(__MINGW32__) || !defined(_PID_T_) || defined(_NO_OLDNAMES)
55 typedef HANDLE pid_t;
56 #endif
57 typedef SOCKET sock_t;
58 typedef unsigned char uint8_t;
59 typedef unsigned int uint32_t;
60 typedef unsigned short uint16_t;
61 typedef unsigned __int64 uint64_t;
62 typedef __int64   int64_t;
63 typedef CRITICAL_SECTION mutex_t;
64 typedef struct _stati64 file_stat_t;
65 #pragma comment(lib, "ws2_32.lib")
66 #define snprintf _snprintf
67 #define vsnprintf _vsnprintf
68 #define INT64_FMT  "I64d"
69 #ifndef EINPROGRESS
70 #define EINPROGRESS WSAEINPROGRESS
71 #endif
72 #ifndef EWOULDBLOCK
73 #define EWOULDBLOCK WSAEWOULDBLOCK
74 #endif
75 #define mutex_init(x) InitializeCriticalSection(x)
76 #define mutex_destroy(x) DeleteCriticalSection(x)
77 #define mutex_lock(x) EnterCriticalSection(x)
78 #define mutex_unlock(x) LeaveCriticalSection(x)
79 #define get_thread_id() ((unsigned long) GetCurrentThreadId())
80 #ifndef S_ISDIR
81 #define S_ISDIR(x) ((x) & _S_IFDIR)
82 #endif
83 #define sleep(x) Sleep((x) * 1000)
84 #define stat(x, y) mg_stat((x), (y))
85 #define fopen(x, y) mg_fopen((x), (y))
86 #define open(x, y) mg_open((x), (y))
87 #define lseek(x, y, z) _lseeki64((x), (y), (z))
88 #define mkdir(x, y) _mkdir(x)
89 #define to64(x) _atoi64(x)
90 #define flockfile(x)
91 #define funlockfile(x)
92 #ifndef va_copy
93 #define va_copy(x,y) x = y
94 #endif // MINGW #defines va_copy
95 #ifndef __func__
96 #define STRX(x) #x
97 #define STR(x) STRX(x)
98 #define __func__ __FILE__ ":" STR(__LINE__)
99 #endif
100 #else
101 #include <dirent.h>
102 #include <inttypes.h>
103 #include <pthread.h>
104 #include <pwd.h>
105 #include <signal.h>
106 #include <unistd.h>
107 #include <netdb.h>
108 #include <arpa/inet.h>  // For inet_pton() when MONGOOSE_USE_IPV6 is defined
109 #include <netinet/in.h>
110 #include <sys/socket.h>
111 #include <sys/select.h>
112 #define closesocket(x) close(x)
113 typedef int sock_t;
114 typedef pthread_mutex_t mutex_t;
115 typedef struct stat file_stat_t;
116 #define mutex_init(x) pthread_mutex_init(x, NULL)
117 #define mutex_destroy(x) pthread_mutex_destroy(x)
118 #define mutex_lock(x) pthread_mutex_lock(x)
119 #define mutex_unlock(x) pthread_mutex_unlock(x)
120 #define get_thread_id() ((unsigned long) pthread_self())
121 #define INVALID_SOCKET ((sock_t) -1)
122 #define INT64_FMT PRId64
123 #define to64(x) strtoll(x, NULL, 10)
124 #define __cdecl
125 #define O_BINARY 0
126 #endif
127
128 #ifdef MONGOOSE_USE_SSL
129 #ifdef __APPLE__
130 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
131 #endif
132 #include <openssl/ssl.h>
133 #endif
134
135 #include "mongoose.h"
136
137 struct ll { struct ll *prev, *next; };
138 #define LINKED_LIST_INIT(N)  ((N)->next = (N)->prev = (N))
139 #define LINKED_LIST_DECLARE_AND_INIT(H)  struct ll H = { &H, &H }
140 #define LINKED_LIST_ENTRY(P,T,N)  ((T *)((char *)(P) - offsetof(T, N)))
141 #define LINKED_LIST_IS_EMPTY(N)  ((N)->next == (N))
142 #define LINKED_LIST_FOREACH(H,N,T) \
143   for (N = (H)->next, T = (N)->next; N != (H); N = (T), T = (N)->next)
144 #define LINKED_LIST_ADD_TO_FRONT(H,N) do { ((H)->next)->prev = (N); \
145   (N)->next = ((H)->next);  (N)->prev = (H); (H)->next = (N); } while (0)
146 #define LINKED_LIST_ADD_TO_TAIL(H,N) do { ((H)->prev)->next = (N); \
147   (N)->prev = ((H)->prev); (N)->next = (H); (H)->prev = (N); } while (0)
148 #define LINKED_LIST_REMOVE(N) do { ((N)->next)->prev = ((N)->prev); \
149   ((N)->prev)->next = ((N)->next); LINKED_LIST_INIT(N); } while (0)
150
151 #define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0]))
152 #define MAX_REQUEST_SIZE 16384
153 #define IOBUF_SIZE 8192
154 #define MAX_PATH_SIZE 8192
155 #define LUA_SCRIPT_PATTERN "**.lp$"
156 #define DEFAULT_CGI_PATTERN "**.cgi$|**.pl$|**.php$"
157 #define CGI_ENVIRONMENT_SIZE 4096
158 #define MAX_CGI_ENVIR_VARS 64
159 #define ENV_EXPORT_TO_CGI "MONGOOSE_CGI"
160 #define PASSWORDS_FILE_NAME ".htpasswd"
161
162 #ifndef MONGOOSE_USE_WEBSOCKET_PING_INTERVAL
163 #define MONGOOSE_USE_WEBSOCKET_PING_INTERVAL 5
164 #endif
165
166 // Extra HTTP headers to send in every static file reply
167 #if !defined(MONGOOSE_USE_EXTRA_HTTP_HEADERS)
168 #define MONGOOSE_USE_EXTRA_HTTP_HEADERS ""
169 #endif
170
171 #ifndef MONGOOSE_USE_POST_SIZE_LIMIT
172 #define MONGOOSE_USE_POST_SIZE_LIMIT 0
173 #endif
174
175 #ifndef MONGOOSE_USE_IDLE_TIMEOUT_SECONDS
176 #define MONGOOSE_USE_IDLE_TIMEOUT_SECONDS 30
177 #endif
178
179 #ifdef MONGOOSE_ENABLE_DEBUG
180 #define DBG(x) do { printf("%-20s ", __func__); printf x; putchar('\n'); \
181   fflush(stdout); } while(0)
182 #else
183 #define DBG(x)
184 #endif
185
186 #ifdef MONGOOSE_NO_FILESYSTEM
187 #define MONGOOSE_NO_AUTH
188 #define MONGOOSE_NO_CGI
189 #define MONGOOSE_NO_DAV
190 #define MONGOOSE_NO_DIRECTORY_LISTING
191 #define MONGOOSE_NO_LOGGING
192 #endif
193
194 union socket_address {
195   struct sockaddr sa;
196   struct sockaddr_in sin;
197 #ifdef MONGOOSE_USE_IPV6
198   struct sockaddr_in6 sin6;
199 #endif
200 };
201
202 struct vec {
203   const char *ptr;
204   int len;
205 };
206
207 // For directory listing and WevDAV support
208 struct dir_entry {
209   struct connection *conn;
210   char *file_name;
211   file_stat_t st;
212 };
213
214 // NOTE(lsm): this enum shoulds be in sync with the config_options.
215 enum {
216   ACCESS_CONTROL_LIST,
217 #ifndef MONGOOSE_NO_FILESYSTEM
218   ACCESS_LOG_FILE,
219 #ifndef MONGOOSE_NO_AUTH
220   AUTH_DOMAIN,
221 #endif
222 #ifndef MONGOOSE_NO_CGI
223   CGI_INTERPRETER,
224   CGI_PATTERN,
225 #endif
226 #ifndef MONGOOSE_NO_DAV
227   DAV_AUTH_FILE,
228 #endif
229   DOCUMENT_ROOT,
230 #ifndef MONGOOSE_NO_DIRECTORY_LISTING
231   ENABLE_DIRECTORY_LISTING,
232 #endif
233 #endif
234   EXTRA_MIME_TYPES,
235 #if !defined(MONGOOSE_NO_FILESYSTEM) && !defined(MONGOOSE_NO_AUTH)
236   GLOBAL_AUTH_FILE,
237 #endif
238   HIDE_FILES_PATTERN,
239 #ifndef MONGOOSE_NO_FILESYSTEM
240   INDEX_FILES,
241 #endif
242   LISTENING_PORT,
243 #ifndef _WIN32
244   RUN_AS_USER,
245 #endif
246 #ifdef MONGOOSE_USE_SSL
247   SSL_CERTIFICATE,
248 #endif
249   URL_REWRITES,
250   NUM_OPTIONS
251 };
252
253 static const char *static_config_options[] = {
254   "access_control_list", NULL,
255 #ifndef MONGOOSE_NO_FILESYSTEM
256   "access_log_file", NULL,
257 #ifndef MONGOOSE_NO_AUTH
258   "auth_domain", "mydomain.com",
259 #endif
260 #ifndef MONGOOSE_NO_CGI
261   "cgi_interpreter", NULL,
262   "cgi_pattern", DEFAULT_CGI_PATTERN,
263 #endif
264 #ifndef MONGOOSE_NO_DAV
265   "dav_auth_file", NULL,
266 #endif
267   "document_root",  NULL,
268 #ifndef MONGOOSE_NO_DIRECTORY_LISTING
269   "enable_directory_listing", "yes",
270 #endif
271 #endif
272   "extra_mime_types", NULL,
273 #if !defined(MONGOOSE_NO_FILESYSTEM) && !defined(MONGOOSE_NO_AUTH)
274   "global_auth_file", NULL,
275 #endif
276   "hide_files_patterns", NULL,
277 #ifndef MONGOOSE_NO_FILESYSTEM
278   "index_files","index.html,index.htm,index.cgi,index.php,index.lp",
279 #endif
280   "listening_port", NULL,
281 #ifndef _WIN32
282   "run_as_user", NULL,
283 #endif
284 #ifdef MONGOOSE_USE_SSL
285   "ssl_certificate", NULL,
286 #endif
287   "url_rewrites", NULL,
288   NULL
289 };
290
291 struct mg_server {
292   sock_t listening_sock;
293   union socket_address lsa;   // Listening socket address
294   struct ll active_connections;
295   mg_handler_t request_handler;
296   mg_handler_t error_handler;
297   mg_handler_t auth_handler;
298   char *config_options[NUM_OPTIONS];
299   char local_ip[48];
300   void *server_data;
301 #ifdef MONGOOSE_USE_SSL
302   SSL_CTX *ssl_ctx;            // Server SSL context
303   SSL_CTX *client_ssl_ctx;     // Client SSL context
304 #endif
305   sock_t ctl[2];    // Control socketpair. Used to wake up from select() call
306 };
307
308 // Expandable IO buffer
309 struct iobuf {
310   char *buf;    // Buffer that holds the data
311   int size;     // Buffer size
312   int len;      // Number of bytes currently in a buffer
313 };
314
315 // Local endpoint representation
316 union endpoint {
317   int fd;                   // Opened regular local file
318   sock_t cgi_sock;          // CGI socket
319   void *ssl;                // SSL descriptor
320 };
321
322 enum endpoint_type { EP_NONE, EP_FILE, EP_CGI, EP_USER, EP_PUT, EP_CLIENT };
323 enum connection_flags {
324   CONN_CLOSE = 1,           // Connection must be closed at the end of the poll
325   CONN_SPOOL_DONE = 2,        // All data has been buffered for sending
326   CONN_SSL_HANDS_SHAKEN = 4,  // SSL handshake has completed. Only for SSL
327   CONN_HEADERS_SENT = 8,      // User callback has sent HTTP headers
328   CONN_BUFFER = 16,           // CGI only. Holds data send until CGI prints
329                               // all HTTP headers
330   CONN_CONNECTING = 32,       // HTTP client is doing non-blocking connect()
331   CONN_LONG_RUNNING = 64      // Long-running URI handlers
332 };
333
334 struct connection {
335   struct mg_connection mg_conn;   // XXX: Must be first
336   struct ll link;                 // Linkage to server->active_connections
337   struct mg_server *server;
338   sock_t client_sock;             // Connected client
339   struct iobuf local_iobuf;
340   struct iobuf remote_iobuf;
341   union endpoint endpoint;
342   enum endpoint_type endpoint_type;
343   time_t birth_time;
344   time_t last_activity_time;
345   char *path_info;
346   char *request;
347   int64_t num_bytes_sent; // Total number of bytes sent
348   int64_t cl;             // Reply content length, for Range support
349   int request_len;  // Request length, including last \r\n after last header
350   int flags;        // CONN_* flags: CONN_CLOSE, CONN_SPOOL_DONE, etc
351   mg_handler_t handler;  // Callback for HTTP client
352 #ifdef MONGOOSE_USE_SSL
353   SSL *ssl;        // SSL descriptor
354 #endif
355 };
356
357 static void open_local_endpoint(struct connection *conn, int skip_user);
358 static void close_local_endpoint(struct connection *conn);
359
360 static const struct {
361   const char *extension;
362   size_t ext_len;
363   const char *mime_type;
364 } static_builtin_mime_types[] = {
365   {".html", 5, "text/html"},
366   {".htm", 4, "text/html"},
367   {".shtm", 5, "text/html"},
368   {".shtml", 6, "text/html"},
369   {".css", 4, "text/css"},
370   {".js",  3, "application/x-javascript"},
371   {".ico", 4, "image/x-icon"},
372   {".gif", 4, "image/gif"},
373   {".jpg", 4, "image/jpeg"},
374   {".jpeg", 5, "image/jpeg"},
375   {".png", 4, "image/png"},
376   {".svg", 4, "image/svg+xml"},
377   {".txt", 4, "text/plain"},
378   {".torrent", 8, "application/x-bittorrent"},
379   {".wav", 4, "audio/x-wav"},
380   {".mp3", 4, "audio/x-mp3"},
381   {".mid", 4, "audio/mid"},
382   {".m3u", 4, "audio/x-mpegurl"},
383   {".ogg", 4, "application/ogg"},
384   {".ram", 4, "audio/x-pn-realaudio"},
385   {".xml", 4, "text/xml"},
386   {".json",  5, "text/json"},
387   {".xslt", 5, "application/xml"},
388   {".xsl", 4, "application/xml"},
389   {".ra",  3, "audio/x-pn-realaudio"},
390   {".doc", 4, "application/msword"},
391   {".exe", 4, "application/octet-stream"},
392   {".zip", 4, "application/x-zip-compressed"},
393   {".xls", 4, "application/excel"},
394   {".tgz", 4, "application/x-tar-gz"},
395   {".tar", 4, "application/x-tar"},
396   {".gz",  3, "application/x-gunzip"},
397   {".arj", 4, "application/x-arj-compressed"},
398   {".rar", 4, "application/x-arj-compressed"},
399   {".rtf", 4, "application/rtf"},
400   {".pdf", 4, "application/pdf"},
401   {".swf", 4, "application/x-shockwave-flash"},
402   {".mpg", 4, "video/mpeg"},
403   {".webm", 5, "video/webm"},
404   {".mpeg", 5, "video/mpeg"},
405   {".mov", 4, "video/quicktime"},
406   {".mp4", 4, "video/mp4"},
407   {".m4v", 4, "video/x-m4v"},
408   {".asf", 4, "video/x-ms-asf"},
409   {".avi", 4, "video/x-msvideo"},
410   {".bmp", 4, "image/bmp"},
411   {".ttf", 4, "application/x-font-ttf"},
412   {NULL,  0, NULL}
413 };
414
415 #ifndef MONGOOSE_NO_THREADS
416 void *mg_start_thread(void *(*f)(void *), void *p) {
417 #ifdef _WIN32
418   return (void *) _beginthread((void (__cdecl *)(void *)) f, 0, p);
419 #else
420   pthread_t thread_id = (pthread_t) 0;
421   pthread_attr_t attr;
422
423   (void) pthread_attr_init(&attr);
424   (void) pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
425
426 #if MONGOOSE_USE_STACK_SIZE > 1
427   (void) pthread_attr_setstacksize(&attr, MONGOOSE_USE_STACK_SIZE);
428 #endif
429
430   pthread_create(&thread_id, &attr, f, p);
431   pthread_attr_destroy(&attr);
432
433   return (void *) thread_id;
434 #endif
435 }
436 #endif  // MONGOOSE_NO_THREADS
437
438 #ifdef _WIN32
439 // Encode 'path' which is assumed UTF-8 string, into UNICODE string.
440 // wbuf and wbuf_len is a target buffer and its length.
441 static void to_wchar(const char *path, wchar_t *wbuf, size_t wbuf_len) {
442   char buf[MAX_PATH_SIZE * 2], buf2[MAX_PATH_SIZE * 2], *p;
443
444   strncpy(buf, path, sizeof(buf));
445   buf[sizeof(buf) - 1] = '\0';
446
447   // Trim trailing slashes
448   p = buf + strlen(buf) - 1;
449   while (p > buf && p[0] == '\\' || p[0] == '/') *p-- = '\0';
450   //change_slashes_to_backslashes(buf);
451
452   // Convert to Unicode and back. If doubly-converted string does not
453   // match the original, something is fishy, reject.
454   memset(wbuf, 0, wbuf_len * sizeof(wchar_t));
455   MultiByteToWideChar(CP_UTF8, 0, buf, -1, wbuf, (int) wbuf_len);
456   WideCharToMultiByte(CP_UTF8, 0, wbuf, (int) wbuf_len, buf2, sizeof(buf2),
457                       NULL, NULL);
458   if (strcmp(buf, buf2) != 0) {
459     wbuf[0] = L'\0';
460   }
461 }
462
463 static int mg_stat(const char *path, file_stat_t *st) {
464   wchar_t wpath[MAX_PATH_SIZE];
465   to_wchar(path, wpath, ARRAY_SIZE(wpath));
466   DBG(("[%ls] -> %d", wpath, _wstati64(wpath, st)));
467   return _wstati64(wpath, st);
468 }
469
470 static FILE *mg_fopen(const char *path, const char *mode) {
471   wchar_t wpath[MAX_PATH_SIZE], wmode[10];
472   to_wchar(path, wpath, ARRAY_SIZE(wpath));
473   to_wchar(mode, wmode, ARRAY_SIZE(wmode));
474   return _wfopen(wpath, wmode);
475 }
476
477 static int mg_open(const char *path, int flag) {
478   wchar_t wpath[MAX_PATH_SIZE];
479   to_wchar(path, wpath, ARRAY_SIZE(wpath));
480   return _wopen(wpath, flag);
481 }
482 #endif
483
484 static void set_close_on_exec(int fd) {
485 #ifdef _WIN32
486   (void) SetHandleInformation((HANDLE) fd, HANDLE_FLAG_INHERIT, 0);
487 #else
488   fcntl(fd, F_SETFD, FD_CLOEXEC);
489 #endif
490 }
491
492 static void set_non_blocking_mode(sock_t sock) {
493 #ifdef _WIN32
494   unsigned long on = 1;
495   ioctlsocket(sock, FIONBIO, &on);
496 #else
497   int flags = fcntl(sock, F_GETFL, 0);
498   fcntl(sock, F_SETFL, flags | O_NONBLOCK);
499 #endif
500 }
501
502 // A helper function for traversing a comma separated list of values.
503 // It returns a list pointer shifted to the next value, or NULL if the end
504 // of the list found.
505 // Value is stored in val vector. If value has form "x=y", then eq_val
506 // vector is initialized to point to the "y" part, and val vector length
507 // is adjusted to point only to "x".
508 static const char *next_option(const char *list, struct vec *val,
509                                struct vec *eq_val) {
510   if (list == NULL || *list == '\0') {
511     // End of the list
512     list = NULL;
513   } else {
514     val->ptr = list;
515     if ((list = strchr(val->ptr, ',')) != NULL) {
516       // Comma found. Store length and shift the list ptr
517       val->len = list - val->ptr;
518       list++;
519     } else {
520       // This value is the last one
521       list = val->ptr + strlen(val->ptr);
522       val->len = list - val->ptr;
523     }
524
525     if (eq_val != NULL) {
526       // Value has form "x=y", adjust pointers and lengths
527       // so that val points to "x", and eq_val points to "y".
528       eq_val->len = 0;
529       eq_val->ptr = (const char *) memchr(val->ptr, '=', val->len);
530       if (eq_val->ptr != NULL) {
531         eq_val->ptr++;  // Skip over '=' character
532         eq_val->len = val->ptr + val->len - eq_val->ptr;
533         val->len = (eq_val->ptr - val->ptr) - 1;
534       }
535     }
536   }
537
538   return list;
539 }
540
541 static int spool(struct iobuf *io, const void *buf, int len) {
542   static const double mult = 1.2;
543   char *p = NULL;
544   int new_len = 0;
545
546   assert(io->len >= 0);
547   assert(io->len <= io->size);
548
549   //DBG(("1. %d %d %d", len, io->len, io->size));
550   if (len <= 0) {
551   } else if ((new_len = io->len + len) < io->size) {
552     memcpy(io->buf + io->len, buf, len);
553     io->len = new_len;
554   } else if ((p = (char *) realloc(io->buf, (int) (new_len * mult))) != NULL) {
555     io->buf = p;
556     memcpy(io->buf + io->len, buf, len);
557     io->len = new_len;
558     io->size = (int) (new_len * mult);
559   } else {
560     len = 0;
561   }
562   //DBG(("%d %d %d", len, io->len, io->size));
563
564   return len;
565 }
566
567 // Like snprintf(), but never returns negative value, or a value
568 // that is larger than a supplied buffer.
569 static int mg_vsnprintf(char *buf, size_t buflen, const char *fmt, va_list ap) {
570   int n;
571   if (buflen < 1) return 0;
572   n = vsnprintf(buf, buflen, fmt, ap);
573   if (n < 0) {
574     n = 0;
575   } else if (n >= (int) buflen) {
576     n = (int) buflen - 1;
577   }
578   buf[n] = '\0';
579   return n;
580 }
581
582 static int mg_snprintf(char *buf, size_t buflen, const char *fmt, ...) {
583   va_list ap;
584   int n;
585   va_start(ap, fmt);
586   n = mg_vsnprintf(buf, buflen, fmt, ap);
587   va_end(ap);
588   return n;
589 }
590
591 // Check whether full request is buffered. Return:
592 //   -1  if request is malformed
593 //    0  if request is not yet fully buffered
594 //   >0  actual request length, including last \r\n\r\n
595 static int get_request_len(const char *s, int buf_len) {
596   const unsigned char *buf = (unsigned char *) s;
597   int i;
598
599   for (i = 0; i < buf_len; i++) {
600     // Control characters are not allowed but >=128 are.
601     // Abort scan as soon as one malformed character is found.
602     if (!isprint(buf[i]) && buf[i] != '\r' && buf[i] != '\n' && buf[i] < 128) {
603       return -1;
604     } else if (buf[i] == '\n' && i + 1 < buf_len && buf[i + 1] == '\n') {
605       return i + 2;
606     } else if (buf[i] == '\n' && i + 2 < buf_len && buf[i + 1] == '\r' &&
607                buf[i + 2] == '\n') {
608       return i + 3;
609     }
610   }
611
612   return 0;
613 }
614
615 // Skip the characters until one of the delimiters characters found.
616 // 0-terminate resulting word. Skip the rest of the delimiters if any.
617 // Advance pointer to buffer to the next word. Return found 0-terminated word.
618 static char *skip(char **buf, const char *delimiters) {
619   char *p, *begin_word, *end_word, *end_delimiters;
620
621   begin_word = *buf;
622   end_word = begin_word + strcspn(begin_word, delimiters);
623   end_delimiters = end_word + strspn(end_word, delimiters);
624
625   for (p = end_word; p < end_delimiters; p++) {
626     *p = '\0';
627   }
628
629   *buf = end_delimiters;
630
631   return begin_word;
632 }
633
634 // Parse HTTP headers from the given buffer, advance buffer to the point
635 // where parsing stopped.
636 static void parse_http_headers(char **buf, struct mg_connection *ri) {
637   size_t i;
638
639   for (i = 0; i < ARRAY_SIZE(ri->http_headers); i++) {
640     ri->http_headers[i].name = skip(buf, ": ");
641     ri->http_headers[i].value = skip(buf, "\r\n");
642     if (ri->http_headers[i].name[0] == '\0')
643       break;
644     ri->num_headers = i + 1;
645   }
646 }
647
648 static const char *status_code_to_str(int status_code) {
649   switch (status_code) {
650     case 200: return "OK";
651     case 201: return "Created";
652     case 204: return "No Content";
653     case 301: return "Moved Permanently";
654     case 302: return "Found";
655     case 304: return "Not Modified";
656     case 400: return "Bad Request";
657     case 403: return "Forbidden";
658     case 404: return "Not Found";
659     case 405: return "Method Not Allowed";
660     case 409: return "Conflict";
661     case 411: return "Length Required";
662     case 413: return "Request Entity Too Large";
663     case 415: return "Unsupported Media Type";
664     case 423: return "Locked";
665     case 500: return "Server Error";
666     case 501: return "Not Implemented";
667     default:  return "Server Error";
668   }
669 }
670
671 static void send_http_error(struct connection *conn, int code,
672                             const char *fmt, ...) {
673   const char *message = status_code_to_str(code);
674   const char *rewrites = conn->server->config_options[URL_REWRITES];
675   char headers[200], body[200];
676   struct vec a, b;
677   va_list ap;
678   int body_len, headers_len, match_code;
679
680   conn->mg_conn.status_code = code;
681
682   // Invoke error handler if it is set
683   if (conn->server->error_handler != NULL &&
684       conn->server->error_handler(&conn->mg_conn) == MG_ERROR_PROCESSED) {
685     close_local_endpoint(conn);
686     return;
687   }
688
689   // Handle error code rewrites
690   while ((rewrites = next_option(rewrites, &a, &b)) != NULL) {
691     if ((match_code = atoi(a.ptr)) > 0 && match_code == code) {
692       conn->mg_conn.status_code = 302;
693       mg_printf(&conn->mg_conn, "HTTP/1.1 %d Moved\r\n"
694                 "Location: %.*s?code=%d&orig_uri=%s\r\n\r\n",
695                 conn->mg_conn.status_code, b.len, b.ptr, code,
696                 conn->mg_conn.uri);
697       close_local_endpoint(conn);
698       return;
699     }
700   }
701
702   body_len = mg_snprintf(body, sizeof(body), "%d %s\n", code, message);
703   if (fmt != NULL) {
704     va_start(ap, fmt);
705     body_len += mg_vsnprintf(body + body_len, sizeof(body) - body_len, fmt, ap);
706     va_end(ap);
707   }
708   if (code >= 300 && code <= 399) {
709     // 3xx errors do not have body
710     body_len = 0;
711   }
712   headers_len = mg_snprintf(headers, sizeof(headers),
713                             "HTTP/1.1 %d %s\r\nContent-Length: %d\r\n"
714                             "Content-Type: text/plain\r\n\r\n",
715                             code, message, body_len);
716   spool(&conn->remote_iobuf, headers, headers_len);
717   spool(&conn->remote_iobuf, body, body_len);
718   close_local_endpoint(conn);  // This will write to the log file
719 }
720
721 // Print message to buffer. If buffer is large enough to hold the message,
722 // return buffer. If buffer is to small, allocate large enough buffer on heap,
723 // and return allocated buffer.
724 static int alloc_vprintf(char **buf, size_t size, const char *fmt, va_list ap) {
725   va_list ap_copy;
726   int len;
727
728   // Windows is not standard-compliant, and vsnprintf() returns -1 if
729   // buffer is too small. Also, older versions of msvcrt.dll do not have
730   // _vscprintf().  However, if size is 0, vsnprintf() behaves correctly.
731   // Therefore, we make two passes: on first pass, get required message length.
732   // On second pass, actually print the message.
733   va_copy(ap_copy, ap);
734   len = vsnprintf(NULL, 0, fmt, ap_copy);
735
736   if (len > (int) size &&
737       (size = len + 1) > 0 &&
738       (*buf = (char *) malloc(size)) == NULL) {
739     len = -1;  // Allocation failed, mark failure
740   } else {
741     va_copy(ap_copy, ap);
742     vsnprintf(*buf, size, fmt, ap_copy);
743   }
744
745   return len;
746 }
747
748 static void write_chunk(struct connection *conn, const char *buf, int len) {
749   char chunk_size[50];
750   int n = mg_snprintf(chunk_size, sizeof(chunk_size), "%X\r\n", len);
751   spool(&conn->remote_iobuf, chunk_size, n);
752   spool(&conn->remote_iobuf, buf, len);
753   spool(&conn->remote_iobuf, "\r\n", 2);
754 }
755
756 int mg_vprintf(struct mg_connection *conn, const char *fmt, va_list ap,
757                int chunked) {
758   char mem[IOBUF_SIZE], *buf = mem;
759   int len;
760
761   if ((len = alloc_vprintf(&buf, sizeof(mem), fmt, ap)) > 0) {
762     if (chunked) {
763       write_chunk((struct connection *) conn, buf, len);
764     } else {
765       len = mg_write(conn, buf, (size_t) len);
766     }
767   }
768   if (buf != mem && buf != NULL) {
769     free(buf);
770   }
771
772   return len;
773 }
774
775 int mg_printf(struct mg_connection *conn, const char *fmt, ...) {
776   int len;
777   va_list ap;
778   va_start(ap, fmt);
779   len = mg_vprintf(conn, fmt, ap, 0);
780   va_end(ap);
781   return len;
782 }
783
784 static int mg_socketpair(sock_t sp[2]) {
785   struct sockaddr_in sa;
786   sock_t sock, ret = -1;
787   socklen_t len = sizeof(sa);
788
789   sp[0] = sp[1] = INVALID_SOCKET;
790
791   (void) memset(&sa, 0, sizeof(sa));
792   sa.sin_family = AF_INET;
793   sa.sin_port = htons(0);
794   sa.sin_addr.s_addr = htonl(0x7f000001);
795
796   if ((sock = socket(AF_INET, SOCK_STREAM, 0)) != INVALID_SOCKET &&
797       !bind(sock, (struct sockaddr *) &sa, len) &&
798       !listen(sock, 1) &&
799       !getsockname(sock, (struct sockaddr *) &sa, &len) &&
800       (sp[0] = socket(AF_INET, SOCK_STREAM, 6)) != -1 &&
801       !connect(sp[0], (struct sockaddr *) &sa, len) &&
802       (sp[1] = accept(sock,(struct sockaddr *) &sa, &len)) != INVALID_SOCKET) {
803     set_close_on_exec(sp[0]);
804     set_close_on_exec(sp[1]);
805     ret = 0;
806   } else {
807     if (sp[0] != INVALID_SOCKET) closesocket(sp[0]);
808     if (sp[1] != INVALID_SOCKET) closesocket(sp[1]);
809     sp[0] = sp[1] = INVALID_SOCKET;
810   }
811   closesocket(sock);
812
813   return ret;
814 }
815
816 static int is_error(int n) {
817   return n == 0 ||
818     (n < 0 && errno != EINTR && errno != EINPROGRESS &&
819      errno != EAGAIN && errno != EWOULDBLOCK
820 #ifdef _WIN32
821      && WSAGetLastError() != WSAEINTR && WSAGetLastError() != WSAEWOULDBLOCK
822 #endif
823     );
824 }
825
826 static void discard_leading_iobuf_bytes(struct iobuf *io, int n) {
827   if (n >= 0 && n <= io->len) {
828     memmove(io->buf, io->buf + n, io->len - n);
829     io->len -= n;
830   }
831 }
832
833 #ifndef MONGOOSE_NO_CGI
834 #ifdef _WIN32
835 struct threadparam {
836   sock_t s;
837   HANDLE hPipe;
838 };
839
840 static int wait_until_ready(sock_t sock, int for_read) {
841   fd_set set;
842   FD_ZERO(&set);
843   FD_SET(sock, &set);
844   select(sock + 1, for_read ? &set : 0, for_read ? 0 : &set, 0, 0);
845   return 1;
846 }
847
848 static void *push_to_stdin(void *arg) {
849   struct threadparam *tp = arg;
850   int n, sent, stop = 0;
851   DWORD k;
852   char buf[IOBUF_SIZE];
853
854   while (!stop && wait_until_ready(tp->s, 1) &&
855          (n = recv(tp->s, buf, sizeof(buf), 0)) > 0) {
856     if (n == -1 && GetLastError() == WSAEWOULDBLOCK) continue;
857     for (sent = 0; !stop && sent < n; sent += k) {
858       if (!WriteFile(tp->hPipe, buf + sent, n - sent, &k, 0)) stop = 1;
859     }
860   }
861   DBG(("%s", "FORWARED EVERYTHING TO CGI"));
862   CloseHandle(tp->hPipe);
863   free(tp);
864   _endthread();
865   return NULL;
866 }
867
868 static void *pull_from_stdout(void *arg) {
869   struct threadparam *tp = arg;
870   int k, stop = 0;
871   DWORD n, sent;
872   char buf[IOBUF_SIZE];
873
874   while (!stop && ReadFile(tp->hPipe, buf, sizeof(buf), &n, NULL)) {
875     for (sent = 0; !stop && sent < n; sent += k) {
876       if (wait_until_ready(tp->s, 0) &&
877           (k = send(tp->s, buf + sent, n - sent, 0)) <= 0) stop = 1;
878     }
879   }
880   DBG(("%s", "EOF FROM CGI"));
881   CloseHandle(tp->hPipe);
882   shutdown(tp->s, 2);  // Without this, IO thread may get truncated data
883   closesocket(tp->s);
884   free(tp);
885   _endthread();
886   return NULL;
887 }
888
889 static void spawn_stdio_thread(sock_t sock, HANDLE hPipe,
890                                void *(*func)(void *)) {
891   struct threadparam *tp = malloc(sizeof(*tp));
892   if (tp != NULL) {
893     tp->s = sock;
894     tp->hPipe = hPipe;
895     mg_start_thread(func, tp);
896   }
897 }
898
899 static void abs_path(const char *utf8_path, char *abs_path, size_t len) {
900   wchar_t buf[MAX_PATH_SIZE], buf2[MAX_PATH_SIZE];
901   to_wchar(utf8_path, buf, ARRAY_SIZE(buf));
902   GetFullPathNameW(buf, ARRAY_SIZE(buf2), buf2, NULL);
903   WideCharToMultiByte(CP_UTF8, 0, buf2, wcslen(buf2) + 1, abs_path, len, 0, 0);
904 }
905
906 static pid_t start_process(char *interp, const char *cmd, const char *env,
907                            const char *envp[], const char *dir, sock_t sock) {
908   STARTUPINFOW si = {0};
909   PROCESS_INFORMATION pi = {0};
910   HANDLE a[2], b[2], me = GetCurrentProcess();
911   wchar_t wcmd[MAX_PATH_SIZE], full_dir[MAX_PATH_SIZE];
912   char buf[MAX_PATH_SIZE], buf4[MAX_PATH_SIZE], buf5[MAX_PATH_SIZE],
913        cmdline[MAX_PATH_SIZE], *p;
914   DWORD flags = DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS;
915   FILE *fp;
916
917   si.cb = sizeof(si);
918   si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
919   si.wShowWindow = SW_HIDE;
920   si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
921
922   CreatePipe(&a[0], &a[1], NULL, 0);
923   CreatePipe(&b[0], &b[1], NULL, 0);
924   DuplicateHandle(me, a[0], me, &si.hStdInput, 0, TRUE, flags);
925   DuplicateHandle(me, b[1], me, &si.hStdOutput, 0, TRUE, flags);
926
927   if (interp == NULL && (fp = fopen(cmd, "r")) != NULL) {
928     buf[0] = buf[1] = '\0';
929     fgets(buf, sizeof(buf), fp);
930     buf[sizeof(buf) - 1] = '\0';
931     if (buf[0] == '#' && buf[1] == '!') {
932       interp = buf + 2;
933       for (p = interp + strlen(interp);
934            isspace(* (uint8_t *) p) && p > interp; p--) *p = '\0';
935     }
936     fclose(fp);
937   }
938
939   if (interp != NULL) {
940     abs_path(interp, buf4, ARRAY_SIZE(buf4));
941     interp = buf4;
942   }
943   abs_path(dir, buf5, ARRAY_SIZE(buf5));
944   to_wchar(dir, full_dir, ARRAY_SIZE(full_dir));
945   mg_snprintf(cmdline, sizeof(cmdline), "%s%s\"%s\"",
946               interp ? interp : "", interp ? " " : "", cmd);
947   to_wchar(cmdline, wcmd, ARRAY_SIZE(wcmd));
948
949   if (CreateProcessW(NULL, wcmd, NULL, NULL, TRUE, CREATE_NEW_PROCESS_GROUP,
950                      (void *) env, full_dir, &si, &pi) != 0) {
951     spawn_stdio_thread(sock, a[1], push_to_stdin);
952     spawn_stdio_thread(sock, b[0], pull_from_stdout);
953   } else {
954     CloseHandle(a[1]);
955     CloseHandle(b[0]);
956     closesocket(sock);
957   }
958   DBG(("CGI command: [%ls] -> %p", wcmd, pi.hProcess));
959
960   CloseHandle(si.hStdOutput);
961   CloseHandle(si.hStdInput);
962   CloseHandle(a[0]);
963   CloseHandle(b[1]);
964   CloseHandle(pi.hThread);
965   CloseHandle(pi.hProcess);
966
967   return pi.hProcess;
968 }
969 #else
970 static pid_t start_process(const char *interp, const char *cmd, const char *env,
971                            const char *envp[], const char *dir, sock_t sock) {
972   char buf[500];
973   pid_t pid = fork();
974   (void) env;
975
976   if (pid == 0) {
977     (void) chdir(dir);
978     (void) dup2(sock, 0);
979     (void) dup2(sock, 1);
980     closesocket(sock);
981
982     // After exec, all signal handlers are restored to their default values,
983     // with one exception of SIGCHLD. According to POSIX.1-2001 and Linux's
984     // implementation, SIGCHLD's handler will leave unchanged after exec
985     // if it was set to be ignored. Restore it to default action.
986     signal(SIGCHLD, SIG_DFL);
987
988     if (interp == NULL) {
989       execle(cmd, cmd, NULL, envp);
990     } else {
991       execle(interp, interp, cmd, NULL, envp);
992     }
993     snprintf(buf, sizeof(buf), "Status: 500\r\n\r\n"
994              "500 Server Error: %s%s%s: %s", interp == NULL ? "" : interp,
995              interp == NULL ? "" : " ", cmd, strerror(errno));
996     send(1, buf, strlen(buf), 0);
997     exit(EXIT_FAILURE);  // exec call failed
998   }
999
1000   return pid;
1001 }
1002 #endif  // _WIN32
1003
1004 // This structure helps to create an environment for the spawned CGI program.
1005 // Environment is an array of "VARIABLE=VALUE\0" ASCIIZ strings,
1006 // last element must be NULL.
1007 // However, on Windows there is a requirement that all these VARIABLE=VALUE\0
1008 // strings must reside in a contiguous buffer. The end of the buffer is
1009 // marked by two '\0' characters.
1010 // We satisfy both worlds: we create an envp array (which is vars), all
1011 // entries are actually pointers inside buf.
1012 struct cgi_env_block {
1013   struct mg_connection *conn;
1014   char buf[CGI_ENVIRONMENT_SIZE];       // Environment buffer
1015   const char *vars[MAX_CGI_ENVIR_VARS]; // char *envp[]
1016   int len;                              // Space taken
1017   int nvars;                            // Number of variables in envp[]
1018 };
1019
1020 // Append VARIABLE=VALUE\0 string to the buffer, and add a respective
1021 // pointer into the vars array.
1022 static char *addenv(struct cgi_env_block *block, const char *fmt, ...) {
1023   int n, space;
1024   char *added;
1025   va_list ap;
1026
1027   // Calculate how much space is left in the buffer
1028   space = sizeof(block->buf) - block->len - 2;
1029   assert(space >= 0);
1030
1031   // Make a pointer to the free space int the buffer
1032   added = block->buf + block->len;
1033
1034   // Copy VARIABLE=VALUE\0 string into the free space
1035   va_start(ap, fmt);
1036   n = mg_vsnprintf(added, (size_t) space, fmt, ap);
1037   va_end(ap);
1038
1039   // Make sure we do not overflow buffer and the envp array
1040   if (n > 0 && n + 1 < space &&
1041       block->nvars < (int) ARRAY_SIZE(block->vars) - 2) {
1042     // Append a pointer to the added string into the envp array
1043     block->vars[block->nvars++] = added;
1044     // Bump up used length counter. Include \0 terminator
1045     block->len += n + 1;
1046   }
1047
1048   return added;
1049 }
1050
1051 static void addenv2(struct cgi_env_block *blk, const char *name) {
1052   const char *s;
1053   if ((s = getenv(name)) != NULL) addenv(blk, "%s=%s", name, s);
1054 }
1055
1056 static void prepare_cgi_environment(struct connection *conn,
1057                                     const char *prog,
1058                                     struct cgi_env_block *blk) {
1059   struct mg_connection *ri = &conn->mg_conn;
1060   const char *s, *slash;
1061   char *p, **opts = conn->server->config_options;
1062   int  i;
1063
1064   blk->len = blk->nvars = 0;
1065   blk->conn = ri;
1066
1067   addenv(blk, "SERVER_NAME=%s", opts[AUTH_DOMAIN]);
1068   addenv(blk, "SERVER_ROOT=%s", opts[DOCUMENT_ROOT]);
1069   addenv(blk, "DOCUMENT_ROOT=%s", opts[DOCUMENT_ROOT]);
1070   addenv(blk, "SERVER_SOFTWARE=%s/%s", "Mongoose", MONGOOSE_VERSION);
1071
1072   // Prepare the environment block
1073   addenv(blk, "%s", "GATEWAY_INTERFACE=CGI/1.1");
1074   addenv(blk, "%s", "SERVER_PROTOCOL=HTTP/1.1");
1075   addenv(blk, "%s", "REDIRECT_STATUS=200"); // For PHP
1076
1077   // TODO(lsm): fix this for IPv6 case
1078   //addenv(blk, "SERVER_PORT=%d", ri->remote_port);
1079
1080   addenv(blk, "REQUEST_METHOD=%s", ri->request_method);
1081   addenv(blk, "REMOTE_ADDR=%s", ri->remote_ip);
1082   addenv(blk, "REMOTE_PORT=%d", ri->remote_port);
1083   addenv(blk, "REQUEST_URI=%s%s%s", ri->uri,
1084          ri->query_string == NULL ? "" : "?",
1085          ri->query_string == NULL ? "" : ri->query_string);
1086
1087   // SCRIPT_NAME
1088   if (conn->path_info != NULL) {
1089     addenv(blk, "SCRIPT_NAME=%.*s",
1090            (int) (strlen(ri->uri) - strlen(conn->path_info)), ri->uri);
1091     addenv(blk, "PATH_INFO=%s", conn->path_info);
1092   } else {
1093     s = strrchr(prog, '/');
1094     slash = strrchr(ri->uri, '/');
1095     addenv(blk, "SCRIPT_NAME=%.*s%s",
1096            slash == NULL ? 0 : (int) (slash - ri->uri), ri->uri,
1097            s == NULL ? prog : s);
1098   }
1099
1100   addenv(blk, "SCRIPT_FILENAME=%s", prog);
1101   addenv(blk, "PATH_TRANSLATED=%s", prog);
1102 #ifdef MONGOOSE_USE_SSL
1103   addenv(blk, "HTTPS=%s", conn->ssl != NULL ? "on" : "off");
1104 #else
1105   addenv(blk, "HTTPS=%s", "off");
1106 #endif
1107
1108   if ((s = mg_get_header(ri, "Content-Type")) != NULL)
1109     addenv(blk, "CONTENT_TYPE=%s", s);
1110
1111   if (ri->query_string != NULL)
1112     addenv(blk, "QUERY_STRING=%s", ri->query_string);
1113
1114   if ((s = mg_get_header(ri, "Content-Length")) != NULL)
1115     addenv(blk, "CONTENT_LENGTH=%s", s);
1116
1117   addenv2(blk, "PATH");
1118   addenv2(blk, "PERLLIB");
1119   addenv2(blk, ENV_EXPORT_TO_CGI);
1120
1121 #if defined(_WIN32)
1122   addenv2(blk, "COMSPEC");
1123   addenv2(blk, "SYSTEMROOT");
1124   addenv2(blk, "SystemDrive");
1125   addenv2(blk, "ProgramFiles");
1126   addenv2(blk, "ProgramFiles(x86)");
1127   addenv2(blk, "CommonProgramFiles(x86)");
1128 #else
1129   addenv2(blk, "LD_LIBRARY_PATH");
1130 #endif // _WIN32
1131
1132   // Add all headers as HTTP_* variables
1133   for (i = 0; i < ri->num_headers; i++) {
1134     p = addenv(blk, "HTTP_%s=%s",
1135         ri->http_headers[i].name, ri->http_headers[i].value);
1136
1137     // Convert variable name into uppercase, and change - to _
1138     for (; *p != '=' && *p != '\0'; p++) {
1139       if (*p == '-')
1140         *p = '_';
1141       *p = (char) toupper(* (unsigned char *) p);
1142     }
1143   }
1144
1145   blk->vars[blk->nvars++] = NULL;
1146   blk->buf[blk->len++] = '\0';
1147
1148   assert(blk->nvars < (int) ARRAY_SIZE(blk->vars));
1149   assert(blk->len > 0);
1150   assert(blk->len < (int) sizeof(blk->buf));
1151 }
1152
1153 static const char cgi_status[] = "HTTP/1.1 200 OK\r\n";
1154
1155 static void open_cgi_endpoint(struct connection *conn, const char *prog) {
1156   struct cgi_env_block blk;
1157   char dir[MAX_PATH_SIZE], *p;
1158   sock_t fds[2];
1159
1160   prepare_cgi_environment(conn, prog, &blk);
1161   // CGI must be executed in its own directory. 'dir' must point to the
1162   // directory containing executable program, 'p' must point to the
1163   // executable program name relative to 'dir'.
1164   if ((p = strrchr(prog, '/')) == NULL) {
1165     mg_snprintf(dir, sizeof(dir), "%s", ".");
1166   } else {
1167     mg_snprintf(dir, sizeof(dir), "%.*s", (int) (p - prog), prog);
1168   }
1169
1170   // Try to create socketpair in a loop until success. mg_socketpair()
1171   // can be interrupted by a signal and fail.
1172   // TODO(lsm): use sigaction to restart interrupted syscall
1173   do {
1174     mg_socketpair(fds);
1175   } while (fds[0] == INVALID_SOCKET);
1176
1177   if (start_process(conn->server->config_options[CGI_INTERPRETER],
1178                     prog, blk.buf, blk.vars, dir, fds[1]) > 0) {
1179     conn->endpoint_type = EP_CGI;
1180     conn->endpoint.cgi_sock = fds[0];
1181     spool(&conn->remote_iobuf, cgi_status, sizeof(cgi_status) - 1);
1182     conn->mg_conn.status_code = 200;
1183     conn->flags |= CONN_BUFFER;
1184   } else {
1185     closesocket(fds[0]);
1186     send_http_error(conn, 500, "start_process(%s) failed", prog);
1187   }
1188
1189 #ifndef _WIN32
1190   closesocket(fds[1]);  // On Windows, CGI stdio thread closes that socket
1191 #endif
1192 }
1193
1194 static void read_from_cgi(struct connection *conn) {
1195   struct iobuf *io = &conn->remote_iobuf;
1196   char buf[IOBUF_SIZE], buf2[sizeof(buf)], *s = buf2;
1197   const char *status = "500";
1198   struct mg_connection c;
1199   int len, s_len = sizeof(cgi_status) - 1,
1200       n = recv(conn->endpoint.cgi_sock, buf, sizeof(buf), 0);
1201
1202   DBG(("%p %d", conn, n));
1203   if (is_error(n)) {
1204     close_local_endpoint(conn);
1205   } else if (n > 0) {
1206     spool(&conn->remote_iobuf, buf, n);
1207     if (conn->flags & CONN_BUFFER) {
1208       len = get_request_len(io->buf + s_len, io->len - s_len);
1209       if (len == 0) return;
1210       if (len > 0) {
1211         memset(&c, 0, sizeof(c));
1212         memcpy(buf2, io->buf + s_len, len);
1213         buf2[len - 1] = '\0';
1214         parse_http_headers(&s, &c);
1215         if (mg_get_header(&c, "Location") != NULL) {
1216           status = "302";
1217         } else if ((status = (char *) mg_get_header(&c, "Status")) == NULL) {
1218           status = "200";
1219         }
1220       }
1221       memcpy(io->buf + 9, status, 3);
1222       conn->mg_conn.status_code = atoi(status);
1223       conn->flags &= ~CONN_BUFFER;
1224     }
1225   }
1226 }
1227
1228 static void forward_post_data(struct connection *conn) {
1229   struct iobuf *io = &conn->local_iobuf;
1230   int n = send(conn->endpoint.cgi_sock, io->buf, io->len, 0);
1231   discard_leading_iobuf_bytes(io, n);
1232 }
1233 #endif  // !MONGOOSE_NO_CGI
1234
1235 // 'sa' must be an initialized address to bind to
1236 static sock_t open_listening_socket(union socket_address *sa) {
1237   socklen_t len = sizeof(*sa);
1238   sock_t on = 1, sock = INVALID_SOCKET;
1239
1240   if ((sock = socket(sa->sa.sa_family, SOCK_STREAM, 6)) != INVALID_SOCKET &&
1241       !setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *) &on, sizeof(on)) &&
1242       !bind(sock, &sa->sa, sa->sa.sa_family == AF_INET ?
1243             sizeof(sa->sin) : sizeof(sa->sa)) &&
1244       !listen(sock, SOMAXCONN)) {
1245     set_non_blocking_mode(sock);
1246     // In case port was set to 0, get the real port number
1247     (void) getsockname(sock, &sa->sa, &len);
1248   } else if (sock != INVALID_SOCKET) {
1249     closesocket(sock);
1250     sock = INVALID_SOCKET;
1251   }
1252
1253   return sock;
1254 }
1255
1256 static char *mg_strdup(const char *str) {
1257   char *copy = (char *) malloc(strlen(str) + 1);
1258   if (copy != NULL) {
1259     strcpy(copy, str);
1260   }
1261   return copy;
1262 }
1263
1264 static int isbyte(int n) {
1265   return n >= 0 && n <= 255;
1266 }
1267
1268 static int parse_net(const char *spec, uint32_t *net, uint32_t *mask) {
1269   int n, a, b, c, d, slash = 32, len = 0;
1270
1271   if ((sscanf(spec, "%d.%d.%d.%d/%d%n", &a, &b, &c, &d, &slash, &n) == 5 ||
1272       sscanf(spec, "%d.%d.%d.%d%n", &a, &b, &c, &d, &n) == 4) &&
1273       isbyte(a) && isbyte(b) && isbyte(c) && isbyte(d) &&
1274       slash >= 0 && slash < 33) {
1275     len = n;
1276     *net = ((uint32_t)a << 24) | ((uint32_t)b << 16) | ((uint32_t)c << 8) | d;
1277     *mask = slash ? 0xffffffffU << (32 - slash) : 0;
1278   }
1279
1280   return len;
1281 }
1282
1283 // Verify given socket address against the ACL.
1284 // Return -1 if ACL is malformed, 0 if address is disallowed, 1 if allowed.
1285 static int check_acl(const char *acl, uint32_t remote_ip) {
1286   int allowed, flag;
1287   uint32_t net, mask;
1288   struct vec vec;
1289
1290   // If any ACL is set, deny by default
1291   allowed = acl == NULL ? '+' : '-';
1292
1293   while ((acl = next_option(acl, &vec, NULL)) != NULL) {
1294     flag = vec.ptr[0];
1295     if ((flag != '+' && flag != '-') ||
1296         parse_net(&vec.ptr[1], &net, &mask) == 0) {
1297       return -1;
1298     }
1299
1300     if (net == (remote_ip & mask)) {
1301       allowed = flag;
1302     }
1303   }
1304
1305   return allowed == '+';
1306 }
1307
1308 static void sockaddr_to_string(char *buf, size_t len,
1309                                const union socket_address *usa) {
1310   buf[0] = '\0';
1311 #if defined(MONGOOSE_USE_IPV6)
1312   inet_ntop(usa->sa.sa_family, usa->sa.sa_family == AF_INET ?
1313             (void *) &usa->sin.sin_addr :
1314             (void *) &usa->sin6.sin6_addr, buf, len);
1315 #elif defined(_WIN32)
1316   // Only Windoze Vista (and newer) have inet_ntop()
1317   strncpy(buf, inet_ntoa(usa->sin.sin_addr), len);
1318 #else
1319   inet_ntop(usa->sa.sa_family, (void *) &usa->sin.sin_addr, buf, len);
1320 #endif
1321 }
1322
1323 static struct connection *accept_new_connection(struct mg_server *server) {
1324   union socket_address sa;
1325   socklen_t len = sizeof(sa);
1326   sock_t sock = INVALID_SOCKET;
1327   struct connection *conn = NULL;
1328
1329   // NOTE(lsm): on Windows, sock is always > FD_SETSIZE
1330   if ((sock = accept(server->listening_sock, &sa.sa, &len)) == INVALID_SOCKET) {
1331   } else if (!check_acl(server->config_options[ACCESS_CONTROL_LIST],
1332                         ntohl(* (uint32_t *) &sa.sin.sin_addr))) {
1333     // NOTE(lsm): check_acl doesn't work for IPv6
1334     closesocket(sock);
1335   } else if ((conn = (struct connection *) calloc(1, sizeof(*conn))) == NULL) {
1336     closesocket(sock);
1337 #ifdef MONGOOSE_USE_SSL
1338   } else if (server->ssl_ctx != NULL &&
1339              ((conn->ssl = SSL_new(server->ssl_ctx)) == NULL ||
1340               SSL_set_fd(conn->ssl, sock) != 1)) {
1341     DBG(("SSL error"));
1342     closesocket(sock);
1343     free(conn);
1344     conn = NULL;
1345 #endif
1346   } else {
1347     set_close_on_exec(sock);
1348     set_non_blocking_mode(sock);
1349     conn->server = server;
1350     conn->client_sock = sock;
1351     sockaddr_to_string(conn->mg_conn.remote_ip,
1352                        sizeof(conn->mg_conn.remote_ip), &sa);
1353     conn->mg_conn.remote_port = ntohs(sa.sin.sin_port);
1354     conn->mg_conn.server_param = server->server_data;
1355     conn->mg_conn.local_ip = server->local_ip;
1356     conn->mg_conn.local_port = ntohs(server->lsa.sin.sin_port);
1357     LINKED_LIST_ADD_TO_FRONT(&server->active_connections, &conn->link);
1358     DBG(("added conn %p", conn));
1359   }
1360
1361   return conn;
1362 }
1363
1364 static void close_conn(struct connection *conn) {
1365   LINKED_LIST_REMOVE(&conn->link);
1366   closesocket(conn->client_sock);
1367   close_local_endpoint(conn);
1368   DBG(("%p %d %d", conn, conn->flags, conn->endpoint_type));
1369   free(conn->request);            // It's OK to free(NULL), ditto below
1370   free(conn->path_info);
1371   free(conn->remote_iobuf.buf);
1372   free(conn->local_iobuf.buf);
1373 #ifdef MONGOOSE_USE_SSL
1374   if (conn->ssl != NULL) SSL_free(conn->ssl);
1375 #endif
1376   free(conn);
1377 }
1378
1379 // Protect against directory disclosure attack by removing '..',
1380 // excessive '/' and '\' characters
1381 static void remove_double_dots_and_double_slashes(char *s) {
1382   char *p = s;
1383
1384   while (*s != '\0') {
1385     *p++ = *s++;
1386     if (s[-1] == '/' || s[-1] == '\\') {
1387       // Skip all following slashes, backslashes and double-dots
1388       while (s[0] != '\0') {
1389         if (s[0] == '/' || s[0] == '\\') { s++; }
1390         else if (s[0] == '.' && s[1] == '.') { s += 2; }
1391         else { break; }
1392       }
1393     }
1394   }
1395   *p = '\0';
1396 }
1397
1398 int mg_url_decode(const char *src, int src_len, char *dst,
1399                   int dst_len, int is_form_url_encoded) {
1400   int i, j, a, b;
1401 #define HEXTOI(x) (isdigit(x) ? x - '0' : x - 'W')
1402
1403   for (i = j = 0; i < src_len && j < dst_len - 1; i++, j++) {
1404     if (src[i] == '%' && i < src_len - 2 &&
1405         isxdigit(* (const unsigned char *) (src + i + 1)) &&
1406         isxdigit(* (const unsigned char *) (src + i + 2))) {
1407       a = tolower(* (const unsigned char *) (src + i + 1));
1408       b = tolower(* (const unsigned char *) (src + i + 2));
1409       dst[j] = (char) ((HEXTOI(a) << 4) | HEXTOI(b));
1410       i += 2;
1411     } else if (is_form_url_encoded && src[i] == '+') {
1412       dst[j] = ' ';
1413     } else {
1414       dst[j] = src[i];
1415     }
1416   }
1417
1418   dst[j] = '\0'; // Null-terminate the destination
1419
1420   return i >= src_len ? j : -1;
1421 }
1422
1423 static int is_valid_http_method(const char *method) {
1424   return !strcmp(method, "GET") || !strcmp(method, "POST") ||
1425     !strcmp(method, "HEAD") || !strcmp(method, "CONNECT") ||
1426     !strcmp(method, "PUT") || !strcmp(method, "DELETE") ||
1427     !strcmp(method, "OPTIONS") || !strcmp(method, "PROPFIND")
1428     || !strcmp(method, "MKCOL");
1429 }
1430
1431 // Parse HTTP request, fill in mg_request structure.
1432 // This function modifies the buffer by NUL-terminating
1433 // HTTP request components, header names and header values.
1434 // Note that len must point to the last \n of HTTP headers.
1435 static int parse_http_message(char *buf, int len, struct mg_connection *ri) {
1436   int is_request, n;
1437
1438   // Reset the connection. Make sure that we don't touch fields that are
1439   // set elsewhere: remote_ip, remote_port, server_param
1440   ri->request_method = ri->uri = ri->http_version = ri->query_string = NULL;
1441   ri->num_headers = ri->status_code = ri->is_websocket = ri->content_len = 0;
1442
1443   buf[len - 1] = '\0';
1444
1445   // RFC says that all initial whitespaces should be ingored
1446   while (*buf != '\0' && isspace(* (unsigned char *) buf)) {
1447     buf++;
1448   }
1449   ri->request_method = skip(&buf, " ");
1450   ri->uri = skip(&buf, " ");
1451   ri->http_version = skip(&buf, "\r\n");
1452
1453   // HTTP message could be either HTTP request or HTTP response, e.g.
1454   // "GET / HTTP/1.0 ...." or  "HTTP/1.0 200 OK ..."
1455   is_request = is_valid_http_method(ri->request_method);
1456   if ((is_request && memcmp(ri->http_version, "HTTP/", 5) != 0) ||
1457       (!is_request && memcmp(ri->request_method, "HTTP/", 5) != 0)) {
1458     len = -1;
1459   } else {
1460     if (is_request) {
1461       ri->http_version += 5;
1462     }
1463     parse_http_headers(&buf, ri);
1464
1465     if ((ri->query_string = strchr(ri->uri, '?')) != NULL) {
1466       *(char *) ri->query_string++ = '\0';
1467     }
1468     n = (int) strlen(ri->uri);
1469     mg_url_decode(ri->uri, n, (char *) ri->uri, n + 1, 0);
1470     remove_double_dots_and_double_slashes((char *) ri->uri);
1471   }
1472
1473   return len;
1474 }
1475
1476 static int lowercase(const char *s) {
1477   return tolower(* (const unsigned char *) s);
1478 }
1479
1480 static int mg_strcasecmp(const char *s1, const char *s2) {
1481   int diff;
1482
1483   do {
1484     diff = lowercase(s1++) - lowercase(s2++);
1485   } while (diff == 0 && s1[-1] != '\0');
1486
1487   return diff;
1488 }
1489
1490 static int mg_strncasecmp(const char *s1, const char *s2, size_t len) {
1491   int diff = 0;
1492
1493   if (len > 0)
1494     do {
1495       diff = lowercase(s1++) - lowercase(s2++);
1496     } while (diff == 0 && s1[-1] != '\0' && --len > 0);
1497
1498   return diff;
1499 }
1500
1501 // Return HTTP header value, or NULL if not found.
1502 const char *mg_get_header(const struct mg_connection *ri, const char *s) {
1503   int i;
1504
1505   for (i = 0; i < ri->num_headers; i++)
1506     if (!mg_strcasecmp(s, ri->http_headers[i].name))
1507       return ri->http_headers[i].value;
1508
1509   return NULL;
1510 }
1511
1512 #ifndef MONGOOSE_NO_FILESYSTEM
1513 // Perform case-insensitive match of string against pattern
1514 static int match_prefix(const char *pattern, int pattern_len, const char *str) {
1515   const char *or_str;
1516   int len, res, i = 0, j = 0;
1517
1518   if ((or_str = (const char *) memchr(pattern, '|', pattern_len)) != NULL) {
1519     res = match_prefix(pattern, or_str - pattern, str);
1520     return res > 0 ? res :
1521         match_prefix(or_str + 1, (pattern + pattern_len) - (or_str + 1), str);
1522   }
1523
1524   for (; i < pattern_len; i++, j++) {
1525     if (pattern[i] == '?' && str[j] != '\0') {
1526       continue;
1527     } else if (pattern[i] == '$') {
1528       return str[j] == '\0' ? j : -1;
1529     } else if (pattern[i] == '*') {
1530       i++;
1531       if (pattern[i] == '*') {
1532         i++;
1533         len = (int) strlen(str + j);
1534       } else {
1535         len = (int) strcspn(str + j, "/");
1536       }
1537       if (i == pattern_len) {
1538         return j + len;
1539       }
1540       do {
1541         res = match_prefix(pattern + i, pattern_len - i, str + j + len);
1542       } while (res == -1 && len-- > 0);
1543       return res == -1 ? -1 : j + res + len;
1544     } else if (lowercase(&pattern[i]) != lowercase(&str[j])) {
1545       return -1;
1546     }
1547   }
1548   return j;
1549 }
1550
1551 static int must_hide_file(struct connection *conn, const char *path) {
1552   const char *pw_pattern = "**" PASSWORDS_FILE_NAME "$";
1553   const char *pattern = conn->server->config_options[HIDE_FILES_PATTERN];
1554   return match_prefix(pw_pattern, strlen(pw_pattern), path) > 0 ||
1555     (pattern != NULL && match_prefix(pattern, strlen(pattern), path) > 0);
1556 }
1557
1558 // Return 1 if real file has been found, 0 otherwise
1559 static int convert_uri_to_file_name(struct connection *conn, char *buf,
1560                                     size_t buf_len, file_stat_t *st) {
1561   struct vec a, b;
1562   const char *rewrites = conn->server->config_options[URL_REWRITES];
1563   const char *root = conn->server->config_options[DOCUMENT_ROOT];
1564 #ifndef MONGOOSE_NO_CGI
1565   const char *cgi_pat = conn->server->config_options[CGI_PATTERN];
1566   char *p;
1567 #endif
1568   const char *uri = conn->mg_conn.uri;
1569   int match_len;
1570
1571   // No filesystem access
1572   if (root == NULL) return 0;
1573
1574   // Handle URL rewrites
1575   mg_snprintf(buf, buf_len, "%s%s", root, uri);
1576   while ((rewrites = next_option(rewrites, &a, &b)) != NULL) {
1577     if ((match_len = match_prefix(a.ptr, a.len, uri)) > 0) {
1578       mg_snprintf(buf, buf_len, "%.*s%s", (int) b.len, b.ptr, uri + match_len);
1579       break;
1580     }
1581   }
1582
1583   if (stat(buf, st) == 0) return 1;
1584
1585 #ifndef MONGOOSE_NO_CGI
1586   // Support PATH_INFO for CGI scripts.
1587   for (p = buf + strlen(root) + 2; *p != '\0'; p++) {
1588     if (*p == '/') {
1589       *p = '\0';
1590       if (match_prefix(cgi_pat, strlen(cgi_pat), buf) > 0 && !stat(buf, st)) {
1591       DBG(("!!!! [%s]", buf));
1592         *p = '/';
1593         conn->path_info = mg_strdup(p);
1594         *p = '\0';
1595         return 1;
1596       }
1597       *p = '/';
1598     }
1599   }
1600 #endif
1601
1602   return 0;
1603 }
1604 #endif  // MONGOOSE_NO_FILESYSTEM
1605
1606 static int should_keep_alive(const struct mg_connection *conn) {
1607   const char *method = conn->request_method;
1608   const char *http_version = conn->http_version;
1609   const char *header = mg_get_header(conn, "Connection");
1610   return method != NULL && (!strcmp(method, "GET") ||
1611         ((struct connection *) conn)->endpoint_type == EP_USER) &&
1612     ((header != NULL && !mg_strcasecmp(header, "keep-alive")) ||
1613      (header == NULL && http_version && !strcmp(http_version, "1.1")));
1614 }
1615
1616 int mg_write(struct mg_connection *c, const void *buf, int len) {
1617   return spool(&((struct connection *) c)->remote_iobuf, buf, len);
1618 }
1619
1620 void mg_send_status(struct mg_connection *c, int status) {
1621   if (c->status_code == 0) {
1622     c->status_code = status;
1623     mg_printf(c, "HTTP/1.1 %d %s\r\n", status, status_code_to_str(status));
1624   }
1625 }
1626
1627 void mg_send_header(struct mg_connection *c, const char *name, const char *v) {
1628   if (c->status_code == 0) {
1629     c->status_code = 200;
1630     mg_printf(c, "HTTP/1.1 %d %s\r\n", 200, status_code_to_str(200));
1631   }
1632   mg_printf(c, "%s: %s\r\n", name, v);
1633 }
1634
1635 static void terminate_headers(struct mg_connection *c) {
1636   struct connection *conn = (struct connection *) c;
1637   if (!(conn->flags & CONN_HEADERS_SENT)) {
1638     mg_send_header(c, "Transfer-Encoding", "chunked");
1639     mg_write(c, "\r\n", 2);
1640     conn->flags |= CONN_HEADERS_SENT;
1641   }
1642 }
1643
1644 void mg_send_data(struct mg_connection *c, const void *data, int data_len) {
1645   terminate_headers(c);
1646   write_chunk((struct connection *) c, (const char *) data, data_len);
1647 }
1648
1649 void mg_printf_data(struct mg_connection *c, const char *fmt, ...) {
1650   va_list ap;
1651
1652   terminate_headers(c);
1653
1654   va_start(ap, fmt);
1655   mg_vprintf(c, fmt, ap, 1);
1656   va_end(ap);
1657 }
1658
1659 #if !defined(NO_WEBSOCKET) || !defined(MONGOOSE_NO_AUTH)
1660 static int is_big_endian(void) {
1661   static const int n = 1;
1662   return ((char *) &n)[0] == 0;
1663 }
1664 #endif
1665
1666 #ifndef MONGOOSE_NO_WEBSOCKET
1667 // START OF SHA-1 code
1668 // Copyright(c) By Steve Reid <steve@edmweb.com>
1669 #define SHA1HANDSOFF
1670 #if defined(__sun)
1671 #include "solarisfixes.h"
1672 #endif
1673
1674 union char64long16 { unsigned char c[64]; uint32_t l[16]; };
1675
1676 #define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
1677
1678 static uint32_t blk0(union char64long16 *block, int i) {
1679   // Forrest: SHA expect BIG_ENDIAN, swap if LITTLE_ENDIAN
1680   if (!is_big_endian()) {
1681     block->l[i] = (rol(block->l[i], 24) & 0xFF00FF00) |
1682       (rol(block->l[i], 8) & 0x00FF00FF);
1683   }
1684   return block->l[i];
1685 }
1686
1687 #define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \
1688     ^block->l[(i+2)&15]^block->l[i&15],1))
1689 #define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(block, i)+0x5A827999+rol(v,5);w=rol(w,30);
1690 #define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
1691 #define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
1692 #define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
1693 #define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
1694
1695 typedef struct {
1696     uint32_t state[5];
1697     uint32_t count[2];
1698     unsigned char buffer[64];
1699 } SHA1_CTX;
1700
1701 static void SHA1Transform(uint32_t state[5], const unsigned char buffer[64]) {
1702   uint32_t a, b, c, d, e;
1703   union char64long16 block[1];
1704
1705   memcpy(block, buffer, 64);
1706   a = state[0];
1707   b = state[1];
1708   c = state[2];
1709   d = state[3];
1710   e = state[4];
1711   R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
1712   R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
1713   R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
1714   R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
1715   R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
1716   R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
1717   R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
1718   R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
1719   R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
1720   R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
1721   R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
1722   R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
1723   R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
1724   R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
1725   R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
1726   R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
1727   R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
1728   R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
1729   R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
1730   R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
1731   state[0] += a;
1732   state[1] += b;
1733   state[2] += c;
1734   state[3] += d;
1735   state[4] += e;
1736   // Erase working structures. The order of operations is important,
1737   // used to ensure that compiler doesn't optimize those out.
1738   memset(block, 0, sizeof(block));
1739   a = b = c = d = e = 0;
1740   (void) a; (void) b; (void) c; (void) d; (void) e;
1741 }
1742
1743 static void SHA1Init(SHA1_CTX* context) {
1744   context->state[0] = 0x67452301;
1745   context->state[1] = 0xEFCDAB89;
1746   context->state[2] = 0x98BADCFE;
1747   context->state[3] = 0x10325476;
1748   context->state[4] = 0xC3D2E1F0;
1749   context->count[0] = context->count[1] = 0;
1750 }
1751
1752 static void SHA1Update(SHA1_CTX* context, const unsigned char* data,
1753                        uint32_t len) {
1754   uint32_t i, j;
1755
1756   j = context->count[0];
1757   if ((context->count[0] += len << 3) < j)
1758     context->count[1]++;
1759   context->count[1] += (len>>29);
1760   j = (j >> 3) & 63;
1761   if ((j + len) > 63) {
1762     memcpy(&context->buffer[j], data, (i = 64-j));
1763     SHA1Transform(context->state, context->buffer);
1764     for ( ; i + 63 < len; i += 64) {
1765       SHA1Transform(context->state, &data[i]);
1766     }
1767     j = 0;
1768   }
1769   else i = 0;
1770   memcpy(&context->buffer[j], &data[i], len - i);
1771 }
1772
1773 static void SHA1Final(unsigned char digest[20], SHA1_CTX* context) {
1774   unsigned i;
1775   unsigned char finalcount[8], c;
1776
1777   for (i = 0; i < 8; i++) {
1778     finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)]
1779                                      >> ((3-(i & 3)) * 8) ) & 255);
1780   }
1781   c = 0200;
1782   SHA1Update(context, &c, 1);
1783   while ((context->count[0] & 504) != 448) {
1784     c = 0000;
1785     SHA1Update(context, &c, 1);
1786   }
1787   SHA1Update(context, finalcount, 8);
1788   for (i = 0; i < 20; i++) {
1789     digest[i] = (unsigned char)
1790       ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
1791   }
1792   memset(context, '\0', sizeof(*context));
1793   memset(&finalcount, '\0', sizeof(finalcount));
1794 }
1795 // END OF SHA1 CODE
1796
1797 static void base64_encode(const unsigned char *src, int src_len, char *dst) {
1798   static const char *b64 =
1799     "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
1800   int i, j, a, b, c;
1801
1802   for (i = j = 0; i < src_len; i += 3) {
1803     a = src[i];
1804     b = i + 1 >= src_len ? 0 : src[i + 1];
1805     c = i + 2 >= src_len ? 0 : src[i + 2];
1806
1807     dst[j++] = b64[a >> 2];
1808     dst[j++] = b64[((a & 3) << 4) | (b >> 4)];
1809     if (i + 1 < src_len) {
1810       dst[j++] = b64[(b & 15) << 2 | (c >> 6)];
1811     }
1812     if (i + 2 < src_len) {
1813       dst[j++] = b64[c & 63];
1814     }
1815   }
1816   while (j % 4 != 0) {
1817     dst[j++] = '=';
1818   }
1819   dst[j++] = '\0';
1820 }
1821
1822 static void send_websocket_handshake(struct mg_connection *conn,
1823                                      const char *key) {
1824   static const char *magic = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
1825   char buf[500], sha[20], b64_sha[sizeof(sha) * 2];
1826   SHA1_CTX sha_ctx;
1827
1828   mg_snprintf(buf, sizeof(buf), "%s%s", key, magic);
1829   SHA1Init(&sha_ctx);
1830   SHA1Update(&sha_ctx, (unsigned char *) buf, strlen(buf));
1831   SHA1Final((unsigned char *) sha, &sha_ctx);
1832   base64_encode((unsigned char *) sha, sizeof(sha), b64_sha);
1833   mg_snprintf(buf, sizeof(buf), "%s%s%s",
1834               "HTTP/1.1 101 Switching Protocols\r\n"
1835               "Upgrade: websocket\r\n"
1836               "Connection: Upgrade\r\n"
1837               "Sec-WebSocket-Accept: ", b64_sha, "\r\n\r\n");
1838
1839   mg_write(conn, buf, strlen(buf));
1840 }
1841
1842 static int deliver_websocket_frame(struct connection *conn) {
1843   // Having buf unsigned char * is important, as it is used below in arithmetic
1844   unsigned char *buf = (unsigned char *) conn->local_iobuf.buf;
1845   int i, len, buf_len = conn->local_iobuf.len, frame_len = 0,
1846       mask_len = 0, header_len = 0, data_len = 0, buffered = 0;
1847
1848   if (buf_len >= 2) {
1849     len = buf[1] & 127;
1850     mask_len = buf[1] & 128 ? 4 : 0;
1851     if (len < 126 && buf_len >= mask_len) {
1852       data_len = len;
1853       header_len = 2 + mask_len;
1854     } else if (len == 126 && buf_len >= 4 + mask_len) {
1855       header_len = 4 + mask_len;
1856       data_len = ((((int) buf[2]) << 8) + buf[3]);
1857     } else if (buf_len >= 10 + mask_len) {
1858       header_len = 10 + mask_len;
1859       data_len = (int) (((uint64_t) htonl(* (uint32_t *) &buf[2])) << 32) +
1860         htonl(* (uint32_t *) &buf[6]);
1861     }
1862   }
1863
1864   frame_len = header_len + data_len;
1865   buffered = frame_len > 0 && frame_len <= buf_len;
1866
1867   if (buffered) {
1868     conn->mg_conn.content_len = data_len;
1869     conn->mg_conn.content = (char *) buf + header_len;
1870     conn->mg_conn.wsbits = buf[0];
1871
1872     // Apply mask if necessary
1873     if (mask_len > 0) {
1874       for (i = 0; i < data_len; i++) {
1875         buf[i + header_len] ^= (buf + header_len - mask_len)[i % 4];
1876       }
1877     }
1878
1879     // Call the handler and remove frame from the iobuf
1880     if (conn->server->request_handler(&conn->mg_conn) == MG_CLIENT_CLOSE) {
1881       conn->flags |= CONN_SPOOL_DONE;
1882     }
1883     discard_leading_iobuf_bytes(&conn->local_iobuf, frame_len);
1884   }
1885
1886   return buffered;
1887 }
1888
1889 int mg_websocket_write(struct mg_connection* conn, int opcode,
1890                        const char *data, size_t data_len) {
1891     unsigned char *copy;
1892     size_t copy_len = 0;
1893     int retval = -1;
1894
1895     if ((copy = (unsigned char *) malloc(data_len + 10)) == NULL) {
1896       return -1;
1897     }
1898
1899     copy[0] = 0x80 + (opcode & 0x0f);
1900
1901     // Frame format: http://tools.ietf.org/html/rfc6455#section-5.2
1902     if (data_len < 126) {
1903       // Inline 7-bit length field
1904       copy[1] = data_len;
1905       memcpy(copy + 2, data, data_len);
1906       copy_len = 2 + data_len;
1907     } else if (data_len <= 0xFFFF) {
1908       // 16-bit length field
1909       copy[1] = 126;
1910       * (uint16_t *) (copy + 2) = (uint16_t) htons((uint16_t) data_len);
1911       memcpy(copy + 4, data, data_len);
1912       copy_len = 4 + data_len;
1913     } else {
1914       // 64-bit length field
1915       copy[1] = 127;
1916       * (uint32_t *) (copy + 2) = (uint32_t)
1917         htonl((uint32_t) ((uint64_t) data_len >> 32));
1918       * (uint32_t *) (copy + 6) = (uint32_t) htonl(data_len & 0xffffffff);
1919       memcpy(copy + 10, data, data_len);
1920       copy_len = 10 + data_len;
1921     }
1922
1923     if (copy_len > 0) {
1924       retval = mg_write(conn, copy, copy_len);
1925     }
1926     free(copy);
1927
1928     return retval;
1929 }
1930
1931 static void send_websocket_handshake_if_requested(struct mg_connection *conn) {
1932   const char *ver = mg_get_header(conn, "Sec-WebSocket-Version"),
1933         *key = mg_get_header(conn, "Sec-WebSocket-Key");
1934   if (ver != NULL && key != NULL) {
1935     conn->is_websocket = 1;
1936     send_websocket_handshake(conn, key);
1937   }
1938 }
1939
1940 static void ping_idle_websocket_connection(struct connection *conn, time_t t) {
1941   if (t - conn->last_activity_time > MONGOOSE_USE_WEBSOCKET_PING_INTERVAL) {
1942     mg_websocket_write(&conn->mg_conn, 0x9, "", 0);
1943   }
1944 }
1945 #else
1946 #define ping_idle_websocket_connection(conn, t)
1947 #endif // !MONGOOSE_NO_WEBSOCKET
1948
1949 static void write_terminating_chunk(struct connection *conn) {
1950   mg_write(&conn->mg_conn, "0\r\n\r\n", 5);
1951 }
1952
1953 static int call_request_handler(struct connection *conn) {
1954   int result;
1955   conn->mg_conn.content = conn->local_iobuf.buf;
1956   switch ((result = conn->server->request_handler(&conn->mg_conn))) {
1957     case MG_REQUEST_CALL_AGAIN: conn->flags |= CONN_LONG_RUNNING; break;
1958     case MG_REQUEST_NOT_PROCESSED: break;
1959     default:
1960       if (conn->flags & CONN_HEADERS_SENT) {
1961         write_terminating_chunk(conn);
1962       }
1963       close_local_endpoint(conn);
1964       break;
1965   }
1966   return result;
1967 }
1968
1969 static void callback_http_client_on_connect(struct connection *conn) {
1970   int ok = 1, ret;
1971   socklen_t len = sizeof(ok);
1972
1973   conn->flags &= ~CONN_CONNECTING;
1974   ret = getsockopt(conn->client_sock, SOL_SOCKET, SO_ERROR, (char *) &ok, &len);
1975 #ifdef MONGOOSE_USE_SSL
1976   if (ret == 0 && ok == 0 && conn->ssl != NULL) {
1977     int res = SSL_connect(conn->ssl), ssl_err = SSL_get_error(conn->ssl, res);
1978     //DBG(("%p res %d %d", conn, res, ssl_err));
1979     if (res == 1) {
1980       conn->flags = CONN_SSL_HANDS_SHAKEN;
1981     } else if (res == 0 || ssl_err == 2 || ssl_err == 3) {
1982       conn->flags |= CONN_CONNECTING;
1983       return; // Call us again
1984     } else {
1985       ok = 1;
1986     }
1987   }
1988 #endif
1989   conn->mg_conn.status_code =
1990     (ret == 0 && ok == 0) ? MG_CONNECT_SUCCESS : MG_CONNECT_FAILURE;
1991   if (conn->handler(&conn->mg_conn) || ok != 0) {
1992     conn->flags |= CONN_CLOSE;
1993   }
1994 }
1995
1996 static void write_to_socket(struct connection *conn) {
1997   struct iobuf *io = &conn->remote_iobuf;
1998   int n = 0;
1999
2000   if (conn->endpoint_type == EP_CLIENT && conn->flags & CONN_CONNECTING) {
2001     callback_http_client_on_connect(conn);
2002     return;
2003   }
2004
2005 #ifdef MONGOOSE_USE_SSL
2006   if (conn->ssl != NULL) {
2007     n = SSL_write(conn->ssl, io->buf, io->len);
2008   } else
2009 #endif
2010   { n = send(conn->client_sock, io->buf, io->len, 0); }
2011
2012   DBG(("%p Written %d of %d(%d): [%.*s ...]",
2013        conn, n, io->len, io->size, io->len < 40 ? io->len : 40, io->buf));
2014
2015   if (is_error(n)) {
2016     conn->flags |= CONN_CLOSE;
2017   } else if (n > 0) {
2018     discard_leading_iobuf_bytes(io, n);
2019     conn->num_bytes_sent += n;
2020   }
2021
2022   if (io->len == 0 && conn->flags & CONN_SPOOL_DONE) {
2023     conn->flags |= CONN_CLOSE;
2024   }
2025 }
2026
2027 const char *mg_get_mime_type(const char *path, const char *default_mime_type) {
2028   const char *ext;
2029   size_t i, path_len;
2030
2031   path_len = strlen(path);
2032
2033   for (i = 0; static_builtin_mime_types[i].extension != NULL; i++) {
2034     ext = path + (path_len - static_builtin_mime_types[i].ext_len);
2035     if (path_len > static_builtin_mime_types[i].ext_len &&
2036         mg_strcasecmp(ext, static_builtin_mime_types[i].extension) == 0) {
2037       return static_builtin_mime_types[i].mime_type;
2038     }
2039   }
2040
2041   return default_mime_type;
2042 }
2043
2044 #ifndef MONGOOSE_NO_FILESYSTEM
2045 // Convert month to the month number. Return -1 on error, or month number
2046 static int get_month_index(const char *s) {
2047   static const char *month_names[] = {
2048     "Jan", "Feb", "Mar", "Apr", "May", "Jun",
2049     "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
2050   };
2051   int i;
2052
2053   for (i = 0; i < (int) ARRAY_SIZE(month_names); i++)
2054     if (!strcmp(s, month_names[i]))
2055       return i;
2056
2057   return -1;
2058 }
2059
2060 static int num_leap_years(int year) {
2061   return year / 4 - year / 100 + year / 400;
2062 }
2063
2064 // Parse UTC date-time string, and return the corresponding time_t value.
2065 static time_t parse_date_string(const char *datetime) {
2066   static const unsigned short days_before_month[] = {
2067     0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
2068   };
2069   char month_str[32];
2070   int second, minute, hour, day, month, year, leap_days, days;
2071   time_t result = (time_t) 0;
2072
2073   if (((sscanf(datetime, "%d/%3s/%d %d:%d:%d",
2074                &day, month_str, &year, &hour, &minute, &second) == 6) ||
2075        (sscanf(datetime, "%d %3s %d %d:%d:%d",
2076                &day, month_str, &year, &hour, &minute, &second) == 6) ||
2077        (sscanf(datetime, "%*3s, %d %3s %d %d:%d:%d",
2078                &day, month_str, &year, &hour, &minute, &second) == 6) ||
2079        (sscanf(datetime, "%d-%3s-%d %d:%d:%d",
2080                &day, month_str, &year, &hour, &minute, &second) == 6)) &&
2081       year > 1970 &&
2082       (month = get_month_index(month_str)) != -1) {
2083     leap_days = num_leap_years(year) - num_leap_years(1970);
2084     year -= 1970;
2085     days = year * 365 + days_before_month[month] + (day - 1) + leap_days;
2086     result = days * 24 * 3600 + hour * 3600 + minute * 60 + second;
2087   }
2088
2089   return result;
2090 }
2091
2092 // Look at the "path" extension and figure what mime type it has.
2093 // Store mime type in the vector.
2094 static void get_mime_type(const struct mg_server *server, const char *path,
2095                           struct vec *vec) {
2096   struct vec ext_vec, mime_vec;
2097   const char *list, *ext;
2098   size_t path_len;
2099
2100   path_len = strlen(path);
2101
2102   // Scan user-defined mime types first, in case user wants to
2103   // override default mime types.
2104   list = server->config_options[EXTRA_MIME_TYPES];
2105   while ((list = next_option(list, &ext_vec, &mime_vec)) != NULL) {
2106     // ext now points to the path suffix
2107     ext = path + path_len - ext_vec.len;
2108     if (mg_strncasecmp(ext, ext_vec.ptr, ext_vec.len) == 0) {
2109       *vec = mime_vec;
2110       return;
2111     }
2112   }
2113
2114   vec->ptr = mg_get_mime_type(path, "text/plain");
2115   vec->len = strlen(vec->ptr);
2116 }
2117
2118 static const char *suggest_connection_header(const struct mg_connection *conn) {
2119   return should_keep_alive(conn) ? "keep-alive" : "close";
2120 }
2121
2122 static void construct_etag(char *buf, size_t buf_len, const file_stat_t *st) {
2123   mg_snprintf(buf, buf_len, "\"%lx.%" INT64_FMT "\"",
2124               (unsigned long) st->st_mtime, (int64_t) st->st_size);
2125 }
2126
2127 // Return True if we should reply 304 Not Modified.
2128 static int is_not_modified(const struct connection *conn,
2129                            const file_stat_t *stp) {
2130   char etag[64];
2131   const char *ims = mg_get_header(&conn->mg_conn, "If-Modified-Since");
2132   const char *inm = mg_get_header(&conn->mg_conn, "If-None-Match");
2133   construct_etag(etag, sizeof(etag), stp);
2134   return (inm != NULL && !mg_strcasecmp(etag, inm)) ||
2135     (ims != NULL && stp->st_mtime <= parse_date_string(ims));
2136 }
2137
2138 // For given directory path, substitute it to valid index file.
2139 // Return 0 if index file has been found, -1 if not found.
2140 // If the file is found, it's stats is returned in stp.
2141 static int find_index_file(struct connection *conn, char *path,
2142                            size_t path_len, file_stat_t *stp) {
2143   const char *list = conn->server->config_options[INDEX_FILES];
2144   file_stat_t st;
2145   struct vec filename_vec;
2146   size_t n = strlen(path), found = 0;
2147
2148   // The 'path' given to us points to the directory. Remove all trailing
2149   // directory separator characters from the end of the path, and
2150   // then append single directory separator character.
2151   while (n > 0 && path[n - 1] == '/') {
2152     n--;
2153   }
2154   path[n] = '/';
2155
2156   // Traverse index files list. For each entry, append it to the given
2157   // path and see if the file exists. If it exists, break the loop
2158   while ((list = next_option(list, &filename_vec, NULL)) != NULL) {
2159
2160     // Ignore too long entries that may overflow path buffer
2161     if (filename_vec.len > (int) (path_len - (n + 2)))
2162       continue;
2163
2164     // Prepare full path to the index file
2165     strncpy(path + n + 1, filename_vec.ptr, filename_vec.len);
2166     path[n + 1 + filename_vec.len] = '\0';
2167
2168     //DBG(("[%s]", path));
2169
2170     // Does it exist?
2171     if (!stat(path, &st)) {
2172       // Yes it does, break the loop
2173       *stp = st;
2174       found = 1;
2175       break;
2176     }
2177   }
2178
2179   // If no index file exists, restore directory path
2180   if (!found) {
2181     path[n] = '\0';
2182   }
2183
2184   return found;
2185 }
2186
2187 static int parse_range_header(const char *header, int64_t *a, int64_t *b) {
2188   return sscanf(header, "bytes=%" INT64_FMT "-%" INT64_FMT, a, b);
2189 }
2190
2191 static void gmt_time_string(char *buf, size_t buf_len, time_t *t) {
2192   strftime(buf, buf_len, "%a, %d %b %Y %H:%M:%S GMT", gmtime(t));
2193 }
2194
2195 static void open_file_endpoint(struct connection *conn, const char *path,
2196                                file_stat_t *st) {
2197   char date[64], lm[64], etag[64], range[64], headers[500];
2198   const char *msg = "OK", *hdr;
2199   time_t curtime = time(NULL);
2200   int64_t r1, r2;
2201   struct vec mime_vec;
2202   int n;
2203
2204   conn->endpoint_type = EP_FILE;
2205   set_close_on_exec(conn->endpoint.fd);
2206   conn->mg_conn.status_code = 200;
2207
2208   get_mime_type(conn->server, path, &mime_vec);
2209   conn->cl = st->st_size;
2210   range[0] = '\0';
2211
2212   // If Range: header specified, act accordingly
2213   r1 = r2 = 0;
2214   hdr = mg_get_header(&conn->mg_conn, "Range");
2215   if (hdr != NULL && (n = parse_range_header(hdr, &r1, &r2)) > 0 &&
2216       r1 >= 0 && r2 >= 0) {
2217     conn->mg_conn.status_code = 206;
2218     conn->cl = n == 2 ? (r2 > conn->cl ? conn->cl : r2) - r1 + 1: conn->cl - r1;
2219     mg_snprintf(range, sizeof(range), "Content-Range: bytes "
2220                 "%" INT64_FMT "-%" INT64_FMT "/%" INT64_FMT "\r\n",
2221                 r1, r1 + conn->cl - 1, (int64_t) st->st_size);
2222     msg = "Partial Content";
2223     lseek(conn->endpoint.fd, r1, SEEK_SET);
2224   }
2225
2226   // Prepare Etag, Date, Last-Modified headers. Must be in UTC, according to
2227   // http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3
2228   gmt_time_string(date, sizeof(date), &curtime);
2229   gmt_time_string(lm, sizeof(lm), &st->st_mtime);
2230   construct_etag(etag, sizeof(etag), st);
2231
2232   n = mg_snprintf(headers, sizeof(headers),
2233                   "HTTP/1.1 %d %s\r\n"
2234                   "Date: %s\r\n"
2235                   "Last-Modified: %s\r\n"
2236                   "Etag: %s\r\n"
2237                   "Content-Type: %.*s\r\n"
2238                   "Content-Length: %" INT64_FMT "\r\n"
2239                   "Connection: %s\r\n"
2240                   "Accept-Ranges: bytes\r\n"
2241                   "%s%s\r\n",
2242                   conn->mg_conn.status_code, msg, date, lm, etag,
2243                   (int) mime_vec.len, mime_vec.ptr, conn->cl,
2244                   suggest_connection_header(&conn->mg_conn),
2245                   range, MONGOOSE_USE_EXTRA_HTTP_HEADERS);
2246   spool(&conn->remote_iobuf, headers, n);
2247
2248   if (!strcmp(conn->mg_conn.request_method, "HEAD")) {
2249     conn->flags |= CONN_SPOOL_DONE;
2250     close(conn->endpoint.fd);
2251     conn->endpoint_type = EP_NONE;
2252   }
2253 }
2254
2255 #endif  // MONGOOSE_NO_FILESYSTEM
2256
2257 static void call_request_handler_if_data_is_buffered(struct connection *conn) {
2258   struct iobuf *loc = &conn->local_iobuf;
2259   struct mg_connection *c = &conn->mg_conn;
2260
2261 #ifndef MONGOOSE_NO_WEBSOCKET
2262   if (conn->mg_conn.is_websocket) {
2263     do { } while (deliver_websocket_frame(conn));
2264   } else
2265 #endif
2266   if ((size_t) loc->len >= c->content_len &&
2267       call_request_handler(conn) == MG_REQUEST_NOT_PROCESSED) {
2268     open_local_endpoint(conn, 1);
2269   }
2270 }
2271
2272 #if !defined(MONGOOSE_NO_DIRECTORY_LISTING) || !defined(MONGOOSE_NO_DAV)
2273
2274 #ifdef _WIN32
2275 struct dirent {
2276   char d_name[MAX_PATH_SIZE];
2277 };
2278
2279 typedef struct DIR {
2280   HANDLE   handle;
2281   WIN32_FIND_DATAW info;
2282   struct dirent result;
2283 } DIR;
2284
2285 // Implementation of POSIX opendir/closedir/readdir for Windows.
2286 static DIR *opendir(const char *name) {
2287   DIR *dir = NULL;
2288   wchar_t wpath[MAX_PATH_SIZE];
2289   DWORD attrs;
2290
2291   if (name == NULL) {
2292     SetLastError(ERROR_BAD_ARGUMENTS);
2293   } else if ((dir = (DIR *) malloc(sizeof(*dir))) == NULL) {
2294     SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2295   } else {
2296     to_wchar(name, wpath, ARRAY_SIZE(wpath));
2297     attrs = GetFileAttributesW(wpath);
2298     if (attrs != 0xFFFFFFFF &&
2299         ((attrs & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY)) {
2300       (void) wcscat(wpath, L"\\*");
2301       dir->handle = FindFirstFileW(wpath, &dir->info);
2302       dir->result.d_name[0] = '\0';
2303     } else {
2304       free(dir);
2305       dir = NULL;
2306     }
2307   }
2308
2309   return dir;
2310 }
2311
2312 static int closedir(DIR *dir) {
2313   int result = 0;
2314
2315   if (dir != NULL) {
2316     if (dir->handle != INVALID_HANDLE_VALUE)
2317       result = FindClose(dir->handle) ? 0 : -1;
2318
2319     free(dir);
2320   } else {
2321     result = -1;
2322     SetLastError(ERROR_BAD_ARGUMENTS);
2323   }
2324
2325   return result;
2326 }
2327
2328 static struct dirent *readdir(DIR *dir) {
2329   struct dirent *result = 0;
2330
2331   if (dir) {
2332     if (dir->handle != INVALID_HANDLE_VALUE) {
2333       result = &dir->result;
2334       (void) WideCharToMultiByte(CP_UTF8, 0,
2335           dir->info.cFileName, -1, result->d_name,
2336           sizeof(result->d_name), NULL, NULL);
2337
2338       if (!FindNextFileW(dir->handle, &dir->info)) {
2339         (void) FindClose(dir->handle);
2340         dir->handle = INVALID_HANDLE_VALUE;
2341       }
2342
2343     } else {
2344       SetLastError(ERROR_FILE_NOT_FOUND);
2345     }
2346   } else {
2347     SetLastError(ERROR_BAD_ARGUMENTS);
2348   }
2349
2350   return result;
2351 }
2352 #endif // _WIN32  POSIX opendir/closedir/readdir implementation
2353
2354 static int scan_directory(struct connection *conn, const char *dir,
2355                           struct dir_entry **arr) {
2356   char path[MAX_PATH_SIZE];
2357   struct dir_entry *p;
2358   struct dirent *dp;
2359   int arr_size = 0, arr_ind = 0, inc = 100;
2360   DIR *dirp;
2361
2362   *arr = NULL;
2363   if ((dirp = (opendir(dir))) == NULL) return 0;
2364
2365   while ((dp = readdir(dirp)) != NULL) {
2366     // Do not show current dir and hidden files
2367     if (!strcmp(dp->d_name, ".") ||
2368         !strcmp(dp->d_name, "..") ||
2369         must_hide_file(conn, dp->d_name)) {
2370       continue;
2371     }
2372     mg_snprintf(path, sizeof(path), "%s%c%s", dir, '/', dp->d_name);
2373
2374     // Resize the array if nesessary
2375     if (arr_ind >= arr_size) {
2376       if ((p = (struct dir_entry *)
2377            realloc(*arr, (inc + arr_size) * sizeof(**arr))) != NULL) {
2378         // Memset new chunk to zero, otherwize st_mtime will have garbage which
2379         // can make strftime() segfault, see
2380         // http://code.google.com/p/mongoose/issues/detail?id=79
2381         memset(p + arr_size, 0, sizeof(**arr) * inc);
2382
2383         *arr = p;
2384         arr_size += inc;
2385       }
2386     }
2387
2388     if (arr_ind < arr_size) {
2389       (*arr)[arr_ind].conn = conn;
2390       (*arr)[arr_ind].file_name = strdup(dp->d_name);
2391       stat(path, &(*arr)[arr_ind].st);
2392       arr_ind++;
2393     }
2394   }
2395   closedir(dirp);
2396
2397   return arr_ind;
2398 }
2399
2400 static void mg_url_encode(const char *src, char *dst, size_t dst_len) {
2401   static const char *dont_escape = "._-$,;~()";
2402   static const char *hex = "0123456789abcdef";
2403   const char *end = dst + dst_len - 1;
2404
2405   for (; *src != '\0' && dst < end; src++, dst++) {
2406     if (isalnum(*(const unsigned char *) src) ||
2407         strchr(dont_escape, * (const unsigned char *) src) != NULL) {
2408       *dst = *src;
2409     } else if (dst + 2 < end) {
2410       dst[0] = '%';
2411       dst[1] = hex[(* (const unsigned char *) src) >> 4];
2412       dst[2] = hex[(* (const unsigned char *) src) & 0xf];
2413       dst += 2;
2414     }
2415   }
2416
2417   *dst = '\0';
2418 }
2419 #endif  // !NO_DIRECTORY_LISTING || !MONGOOSE_NO_DAV
2420
2421 #ifndef MONGOOSE_NO_DIRECTORY_LISTING
2422
2423 static void print_dir_entry(const struct dir_entry *de) {
2424   char size[64], mod[64], href[MAX_PATH_SIZE * 3], chunk[MAX_PATH_SIZE * 4];
2425   int64_t fsize = de->st.st_size;
2426   int is_dir = S_ISDIR(de->st.st_mode), n;
2427   const char *slash = is_dir ? "/" : "";
2428
2429   if (is_dir) {
2430     mg_snprintf(size, sizeof(size), "%s", "[DIRECTORY]");
2431   } else {
2432      // We use (signed) cast below because MSVC 6 compiler cannot
2433      // convert unsigned __int64 to double.
2434     if (fsize < 1024) {
2435       mg_snprintf(size, sizeof(size), "%d", (int) fsize);
2436     } else if (fsize < 0x100000) {
2437       mg_snprintf(size, sizeof(size), "%.1fk", (double) fsize / 1024.0);
2438     } else if (fsize < 0x40000000) {
2439       mg_snprintf(size, sizeof(size), "%.1fM", (double) fsize / 1048576);
2440     } else {
2441       mg_snprintf(size, sizeof(size), "%.1fG", (double) fsize / 1073741824);
2442     }
2443   }
2444   strftime(mod, sizeof(mod), "%d-%b-%Y %H:%M", localtime(&de->st.st_mtime));
2445   mg_url_encode(de->file_name, href, sizeof(href));
2446   n = mg_snprintf(chunk, sizeof(chunk),
2447                   "<tr><td><a href=\"%s%s%s\">%s%s</a></td>"
2448                   "<td>&nbsp;%s</td><td>&nbsp;&nbsp;%s</td></tr>\n",
2449                   de->conn->mg_conn.uri, href, slash, de->file_name, slash,
2450                   mod, size);
2451   write_chunk((struct connection *) de->conn, chunk, n);
2452 }
2453
2454 // Sort directory entries by size, or name, or modification time.
2455 // On windows, __cdecl specification is needed in case if project is built
2456 // with __stdcall convention. qsort always requires __cdels callback.
2457 static int __cdecl compare_dir_entries(const void *p1, const void *p2) {
2458   const struct dir_entry *a = (const struct dir_entry *) p1,
2459         *b = (const struct dir_entry *) p2;
2460   const char *qs = a->conn->mg_conn.query_string ?
2461     a->conn->mg_conn.query_string : "na";
2462   int cmp_result = 0;
2463
2464   if (S_ISDIR(a->st.st_mode) && !S_ISDIR(b->st.st_mode)) {
2465     return -1;  // Always put directories on top
2466   } else if (!S_ISDIR(a->st.st_mode) && S_ISDIR(b->st.st_mode)) {
2467     return 1;   // Always put directories on top
2468   } else if (*qs == 'n') {
2469     cmp_result = strcmp(a->file_name, b->file_name);
2470   } else if (*qs == 's') {
2471     cmp_result = a->st.st_size == b->st.st_size ? 0 :
2472       a->st.st_size > b->st.st_size ? 1 : -1;
2473   } else if (*qs == 'd') {
2474     cmp_result = a->st.st_mtime == b->st.st_mtime ? 0 :
2475       a->st.st_mtime > b->st.st_mtime ? 1 : -1;
2476   }
2477
2478   return qs[1] == 'd' ? -cmp_result : cmp_result;
2479 }
2480
2481 static void send_directory_listing(struct connection *conn, const char *dir) {
2482   char buf[2000];
2483   struct dir_entry *arr = NULL;
2484   int i, num_entries, sort_direction = conn->mg_conn.query_string != NULL &&
2485     conn->mg_conn.query_string[1] == 'd' ? 'a' : 'd';
2486
2487   conn->mg_conn.status_code = 200;
2488   mg_snprintf(buf, sizeof(buf), "%s",
2489               "HTTP/1.1 200 OK\r\n"
2490               "Transfer-Encoding: Chunked\r\n"
2491               "Content-Type: text/html; charset=utf-8\r\n\r\n");
2492   spool(&conn->remote_iobuf, buf, strlen(buf));
2493
2494   mg_snprintf(buf, sizeof(buf),
2495               "<html><head><title>Index of %s</title>"
2496               "<style>th {text-align: left;}</style></head>"
2497               "<body><h1>Index of %s</h1><pre><table cellpadding=\"0\">"
2498               "<tr><th><a href=\"?n%c\">Name</a></th>"
2499               "<th><a href=\"?d%c\">Modified</a></th>"
2500               "<th><a href=\"?s%c\">Size</a></th></tr>"
2501               "<tr><td colspan=\"3\"><hr></td></tr>",
2502               conn->mg_conn.uri, conn->mg_conn.uri,
2503               sort_direction, sort_direction, sort_direction);
2504   write_chunk(conn, buf, strlen(buf));
2505
2506   num_entries = scan_directory(conn, dir, &arr);
2507   qsort(arr, num_entries, sizeof(arr[0]), compare_dir_entries);
2508   for (i = 0; i < num_entries; i++) {
2509     print_dir_entry(&arr[i]);
2510     free(arr[i].file_name);
2511   }
2512   free(arr);
2513
2514   write_terminating_chunk(conn);
2515   close_local_endpoint(conn);
2516 }
2517 #endif  // MONGOOSE_NO_DIRECTORY_LISTING
2518
2519 #ifndef MONGOOSE_NO_DAV
2520 static void print_props(struct connection *conn, const char *uri,
2521                         file_stat_t *stp) {
2522   char mtime[64], buf[MAX_PATH_SIZE + 200];
2523
2524   gmt_time_string(mtime, sizeof(mtime), &stp->st_mtime);
2525   mg_snprintf(buf, sizeof(buf),
2526       "<d:response>"
2527        "<d:href>%s</d:href>"
2528        "<d:propstat>"
2529         "<d:prop>"
2530          "<d:resourcetype>%s</d:resourcetype>"
2531          "<d:getcontentlength>%" INT64_FMT "</d:getcontentlength>"
2532          "<d:getlastmodified>%s</d:getlastmodified>"
2533         "</d:prop>"
2534         "<d:status>HTTP/1.1 200 OK</d:status>"
2535        "</d:propstat>"
2536       "</d:response>\n",
2537       uri, S_ISDIR(stp->st_mode) ? "<d:collection/>" : "",
2538       (int64_t) stp->st_size, mtime);
2539   spool(&conn->remote_iobuf, buf, strlen(buf));
2540 }
2541
2542 static void handle_propfind(struct connection *conn, const char *path,
2543                             file_stat_t *stp) {
2544   static const char header[] = "HTTP/1.1 207 Multi-Status\r\n"
2545     "Connection: close\r\n"
2546     "Content-Type: text/xml; charset=utf-8\r\n\r\n"
2547     "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
2548     "<d:multistatus xmlns:d='DAV:'>\n";
2549   static const char footer[] = "</d:multistatus>";
2550   const char *depth = mg_get_header(&conn->mg_conn, "Depth"),
2551         *list_dir = conn->server->config_options[ENABLE_DIRECTORY_LISTING];
2552
2553   conn->mg_conn.status_code = 207;
2554   spool(&conn->remote_iobuf, header, sizeof(header) - 1);
2555
2556   // Print properties for the requested resource itself
2557   print_props(conn, conn->mg_conn.uri, stp);
2558
2559   // If it is a directory, print directory entries too if Depth is not 0
2560   if (S_ISDIR(stp->st_mode) && !mg_strcasecmp(list_dir, "yes") &&
2561       (depth == NULL || strcmp(depth, "0") != 0)) {
2562     struct dir_entry *arr = NULL;
2563     int i, num_entries = scan_directory(conn, path, &arr);
2564
2565     for (i = 0; i < num_entries; i++) {
2566       char buf[MAX_PATH_SIZE], buf2[sizeof(buf) * 3];
2567       struct dir_entry *de = &arr[i];
2568
2569       mg_snprintf(buf, sizeof(buf), "%s%s", de->conn->mg_conn.uri,
2570                   de->file_name);
2571       mg_url_encode(buf, buf2, sizeof(buf2) - 1);
2572       print_props(conn, buf, &de->st);
2573     }
2574   }
2575
2576   spool(&conn->remote_iobuf, footer, sizeof(footer) - 1);
2577   close_local_endpoint(conn);
2578 }
2579
2580 static void handle_mkcol(struct connection *conn, const char *path) {
2581   int status_code = 500;
2582
2583   if (conn->mg_conn.content_len > 0) {
2584     status_code = 415;
2585   } else if (!mkdir(path, 0755)) {
2586     status_code = 201;
2587   } else if (errno == EEXIST) {
2588     status_code = 405;
2589   } else if (errno == EACCES) {
2590     status_code = 403;
2591   } else if (errno == ENOENT) {
2592     status_code = 409;
2593   }
2594   send_http_error(conn, status_code, NULL);
2595 }
2596
2597 static int remove_directory(const char *dir) {
2598   char path[MAX_PATH_SIZE];
2599   struct dirent *dp;
2600   file_stat_t st;
2601   DIR *dirp;
2602
2603   if ((dirp = opendir(dir)) == NULL) return 0;
2604
2605   while ((dp = readdir(dirp)) != NULL) {
2606     if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..")) continue;
2607     mg_snprintf(path, sizeof(path), "%s%c%s", dir, '/', dp->d_name);
2608     stat(path, &st);
2609     if (S_ISDIR(st.st_mode)) {
2610       remove_directory(path);
2611     } else {
2612       remove(path);
2613     }
2614   }
2615   closedir(dirp);
2616   rmdir(dir);
2617
2618   return 1;
2619 }
2620
2621 static void handle_delete(struct connection *conn, const char *path) {
2622   file_stat_t st;
2623
2624   if (stat(path, &st) != 0) {
2625     send_http_error(conn, 404, NULL);
2626   } else if (S_ISDIR(st.st_mode)) {
2627     remove_directory(path);
2628     send_http_error(conn, 204, NULL);
2629   } else if (!remove(path) == 0) {
2630     send_http_error(conn, 204, NULL);
2631   } else {
2632     send_http_error(conn, 423, NULL);
2633   }
2634 }
2635
2636 // For a given PUT path, create all intermediate subdirectories
2637 // for given path. Return 0 if the path itself is a directory,
2638 // or -1 on error, 1 if OK.
2639 static int put_dir(const char *path) {
2640   char buf[MAX_PATH_SIZE];
2641   const char *s, *p;
2642   file_stat_t st;
2643
2644   // Create intermediate directories if they do not exist
2645   for (s = p = path + 1; (p = strchr(s, '/')) != NULL; s = ++p) {
2646     if (p - path >= (int) sizeof(buf)) return -1; // Buffer overflow
2647     memcpy(buf, path, p - path);
2648     buf[p - path] = '\0';
2649     if (stat(buf, &st) != 0 && mkdir(buf, 0755) != 0) return -1;
2650     if (p[1] == '\0') return 0;  // Path is a directory itself
2651   }
2652
2653   return 1;
2654 }
2655
2656 static void handle_put(struct connection *conn, const char *path) {
2657   file_stat_t st;
2658   const char *range, *cl_hdr = mg_get_header(&conn->mg_conn, "Content-Length");
2659   int64_t r1, r2;
2660   int rc;
2661
2662   conn->mg_conn.status_code = !stat(path, &st) ? 200 : 201;
2663   if ((rc = put_dir(path)) == 0) {
2664     mg_printf(&conn->mg_conn, "HTTP/1.1 %d OK\r\n\r\n",
2665               conn->mg_conn.status_code);
2666     close_local_endpoint(conn);
2667   } else if (rc == -1) {
2668     send_http_error(conn, 500, "put_dir: %s", strerror(errno));
2669   } else if (cl_hdr == NULL) {
2670     send_http_error(conn, 411, NULL);
2671 #ifdef _WIN32
2672     //On Windows, open() is a macro with 2 params
2673   } else if ((conn->endpoint.fd =
2674               open(path, O_RDWR | O_CREAT | O_TRUNC)) < 0) {
2675 #else
2676   } else if ((conn->endpoint.fd =
2677               open(path, O_RDWR | O_CREAT | O_TRUNC, 0644)) < 0) {
2678 #endif
2679     send_http_error(conn, 500, "open(%s): %s", path, strerror(errno));
2680   } else {
2681     DBG(("PUT [%s] %d", path, conn->local_iobuf.len));
2682     conn->endpoint_type = EP_PUT;
2683     set_close_on_exec(conn->endpoint.fd);
2684     range = mg_get_header(&conn->mg_conn, "Content-Range");
2685     conn->cl = to64(cl_hdr);
2686     r1 = r2 = 0;
2687     if (range != NULL && parse_range_header(range, &r1, &r2) > 0) {
2688       conn->mg_conn.status_code = 206;
2689       lseek(conn->endpoint.fd, r1, SEEK_SET);
2690       conn->cl = r2 > r1 ? r2 - r1 + 1: conn->cl - r1;
2691     }
2692     mg_printf(&conn->mg_conn, "HTTP/1.1 %d OK\r\nContent-Length: 0\r\n\r\n",
2693               conn->mg_conn.status_code);
2694   }
2695 }
2696
2697 static void forward_put_data(struct connection *conn) {
2698   struct iobuf *io = &conn->local_iobuf;
2699   int n = write(conn->endpoint.fd, io->buf, io->len);
2700   if (n > 0) {
2701     discard_leading_iobuf_bytes(io, n);
2702     conn->cl -= n;
2703     if (conn->cl <= 0) {
2704       close_local_endpoint(conn);
2705     }
2706   }
2707 }
2708 #endif //  MONGOOSE_NO_DAV
2709
2710 static void send_options(struct connection *conn) {
2711   static const char reply[] = "HTTP/1.1 200 OK\r\nAllow: GET, POST, HEAD, "
2712     "CONNECT, PUT, DELETE, OPTIONS, PROPFIND, MKCOL\r\nDAV: 1\r\n\r\n";
2713   spool(&conn->remote_iobuf, reply, sizeof(reply) - 1);
2714   conn->flags |= CONN_SPOOL_DONE;
2715 }
2716
2717 #ifndef MONGOOSE_NO_AUTH
2718 void mg_send_digest_auth_request(struct mg_connection *c) {
2719   struct connection *conn = (struct connection *) c;
2720   c->status_code = 401;
2721   mg_printf(c,
2722             "HTTP/1.1 401 Unauthorized\r\n"
2723             "WWW-Authenticate: Digest qop=\"auth\", "
2724             "realm=\"%s\", nonce=\"%lu\"\r\n\r\n",
2725             conn->server->config_options[AUTH_DOMAIN],
2726             (unsigned long) time(NULL));
2727   close_local_endpoint(conn);
2728 }
2729
2730 // Use the global passwords file, if specified by auth_gpass option,
2731 // or search for .htpasswd in the requested directory.
2732 static FILE *open_auth_file(struct connection *conn, const char *path) {
2733   char name[MAX_PATH_SIZE];
2734   const char *p, *gpass = conn->server->config_options[GLOBAL_AUTH_FILE];
2735   file_stat_t st;
2736   FILE *fp = NULL;
2737
2738   if (gpass != NULL) {
2739     // Use global passwords file
2740     fp = fopen(gpass, "r");
2741   } else if (!stat(path, &st) && S_ISDIR(st.st_mode)) {
2742     mg_snprintf(name, sizeof(name), "%s%c%s", path, '/', PASSWORDS_FILE_NAME);
2743     fp = fopen(name, "r");
2744   } else {
2745     // Try to find .htpasswd in requested directory.
2746     if ((p = strrchr(path, '/')) == NULL) p = path;
2747     mg_snprintf(name, sizeof(name), "%.*s%c%s",
2748                 (int) (p - path), path, '/', PASSWORDS_FILE_NAME);
2749     fp = fopen(name, "r");
2750   }
2751
2752   return fp;
2753 }
2754
2755 #if !defined(HAVE_MD5) && !defined(MONGOOSE_NO_AUTH)
2756 typedef struct MD5Context {
2757   uint32_t buf[4];
2758   uint32_t bits[2];
2759   unsigned char in[64];
2760 } MD5_CTX;
2761
2762 static void byteReverse(unsigned char *buf, unsigned longs) {
2763   uint32_t t;
2764
2765   // Forrest: MD5 expect LITTLE_ENDIAN, swap if BIG_ENDIAN
2766   if (is_big_endian()) {
2767     do {
2768       t = (uint32_t) ((unsigned) buf[3] << 8 | buf[2]) << 16 |
2769         ((unsigned) buf[1] << 8 | buf[0]);
2770       * (uint32_t *) buf = t;
2771       buf += 4;
2772     } while (--longs);
2773   }
2774 }
2775
2776 #define F1(x, y, z) (z ^ (x & (y ^ z)))
2777 #define F2(x, y, z) F1(z, x, y)
2778 #define F3(x, y, z) (x ^ y ^ z)
2779 #define F4(x, y, z) (y ^ (x | ~z))
2780
2781 #define MD5STEP(f, w, x, y, z, data, s) \
2782   ( w += f(x, y, z) + data,  w = w<<s | w>>(32-s),  w += x )
2783
2784 // Start MD5 accumulation.  Set bit count to 0 and buffer to mysterious
2785 // initialization constants.
2786 static void MD5Init(MD5_CTX *ctx) {
2787   ctx->buf[0] = 0x67452301;
2788   ctx->buf[1] = 0xefcdab89;
2789   ctx->buf[2] = 0x98badcfe;
2790   ctx->buf[3] = 0x10325476;
2791
2792   ctx->bits[0] = 0;
2793   ctx->bits[1] = 0;
2794 }
2795
2796 static void MD5Transform(uint32_t buf[4], uint32_t const in[16]) {
2797   register uint32_t a, b, c, d;
2798
2799   a = buf[0];
2800   b = buf[1];
2801   c = buf[2];
2802   d = buf[3];
2803
2804   MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
2805   MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
2806   MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
2807   MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
2808   MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
2809   MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
2810   MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
2811   MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
2812   MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
2813   MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
2814   MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
2815   MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
2816   MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
2817   MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
2818   MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
2819   MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
2820
2821   MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
2822   MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
2823   MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
2824   MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
2825   MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
2826   MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
2827   MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
2828   MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
2829   MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
2830   MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
2831   MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
2832   MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
2833   MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
2834   MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
2835   MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
2836   MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
2837
2838   MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
2839   MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
2840   MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
2841   MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
2842   MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
2843   MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
2844   MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
2845   MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
2846   MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
2847   MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
2848   MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
2849   MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
2850   MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
2851   MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
2852   MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
2853   MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
2854
2855   MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
2856   MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
2857   MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
2858   MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
2859   MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
2860   MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
2861   MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
2862   MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
2863   MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
2864   MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
2865   MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
2866   MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
2867   MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
2868   MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
2869   MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
2870   MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
2871
2872   buf[0] += a;
2873   buf[1] += b;
2874   buf[2] += c;
2875   buf[3] += d;
2876 }
2877
2878 static void MD5Update(MD5_CTX *ctx, unsigned char const *buf, unsigned len) {
2879   uint32_t t;
2880
2881   t = ctx->bits[0];
2882   if ((ctx->bits[0] = t + ((uint32_t) len << 3)) < t)
2883     ctx->bits[1]++;
2884   ctx->bits[1] += len >> 29;
2885
2886   t = (t >> 3) & 0x3f;
2887
2888   if (t) {
2889     unsigned char *p = (unsigned char *) ctx->in + t;
2890
2891     t = 64 - t;
2892     if (len < t) {
2893       memcpy(p, buf, len);
2894       return;
2895     }
2896     memcpy(p, buf, t);
2897     byteReverse(ctx->in, 16);
2898     MD5Transform(ctx->buf, (uint32_t *) ctx->in);
2899     buf += t;
2900     len -= t;
2901   }
2902
2903   while (len >= 64) {
2904     memcpy(ctx->in, buf, 64);
2905     byteReverse(ctx->in, 16);
2906     MD5Transform(ctx->buf, (uint32_t *) ctx->in);
2907     buf += 64;
2908     len -= 64;
2909   }
2910
2911   memcpy(ctx->in, buf, len);
2912 }
2913
2914 static void MD5Final(unsigned char digest[16], MD5_CTX *ctx) {
2915   unsigned count;
2916   unsigned char *p;
2917   uint32_t *a;
2918
2919   count = (ctx->bits[0] >> 3) & 0x3F;
2920
2921   p = ctx->in + count;
2922   *p++ = 0x80;
2923   count = 64 - 1 - count;
2924   if (count < 8) {
2925     memset(p, 0, count);
2926     byteReverse(ctx->in, 16);
2927     MD5Transform(ctx->buf, (uint32_t *) ctx->in);
2928     memset(ctx->in, 0, 56);
2929   } else {
2930     memset(p, 0, count - 8);
2931   }
2932   byteReverse(ctx->in, 14);
2933
2934   a = (uint32_t *)ctx->in;
2935   a[14] = ctx->bits[0];
2936   a[15] = ctx->bits[1];
2937
2938   MD5Transform(ctx->buf, (uint32_t *) ctx->in);
2939   byteReverse((unsigned char *) ctx->buf, 4);
2940   memcpy(digest, ctx->buf, 16);
2941   memset((char *) ctx, 0, sizeof(*ctx));
2942 }
2943 #endif // !HAVE_MD5
2944
2945
2946
2947 // Stringify binary data. Output buffer must be twice as big as input,
2948 // because each byte takes 2 bytes in string representation
2949 static void bin2str(char *to, const unsigned char *p, size_t len) {
2950   static const char *hex = "0123456789abcdef";
2951
2952   for (; len--; p++) {
2953     *to++ = hex[p[0] >> 4];
2954     *to++ = hex[p[0] & 0x0f];
2955   }
2956   *to = '\0';
2957 }
2958
2959 // Return stringified MD5 hash for list of strings. Buffer must be 33 bytes.
2960 char *mg_md5(char buf[33], ...) {
2961   unsigned char hash[16];
2962   const char *p;
2963   va_list ap;
2964   MD5_CTX ctx;
2965
2966   MD5Init(&ctx);
2967
2968   va_start(ap, buf);
2969   while ((p = va_arg(ap, const char *)) != NULL) {
2970     MD5Update(&ctx, (const unsigned char *) p, (unsigned) strlen(p));
2971   }
2972   va_end(ap);
2973
2974   MD5Final(hash, &ctx);
2975   bin2str(buf, hash, sizeof(hash));
2976   return buf;
2977 }
2978
2979 // Check the user's password, return 1 if OK
2980 static int check_password(const char *method, const char *ha1, const char *uri,
2981                           const char *nonce, const char *nc, const char *cnonce,
2982                           const char *qop, const char *response) {
2983   char ha2[32 + 1], expected_response[32 + 1];
2984
2985 #if 0
2986   // Check for authentication timeout
2987   if ((unsigned long) time(NULL) - (unsigned long) to64(nonce) > 3600) {
2988     return 0;
2989   }
2990 #endif
2991
2992   mg_md5(ha2, method, ":", uri, NULL);
2993   mg_md5(expected_response, ha1, ":", nonce, ":", nc,
2994       ":", cnonce, ":", qop, ":", ha2, NULL);
2995
2996   return mg_strcasecmp(response, expected_response) == 0 ?
2997     MG_AUTH_OK : MG_AUTH_FAIL;
2998 }
2999
3000
3001 // Authorize against the opened passwords file. Return 1 if authorized.
3002 int mg_authorize_digest(struct mg_connection *c, FILE *fp) {
3003   struct connection *conn = (struct connection *) c;
3004   const char *hdr;
3005   char line[256], f_user[256], ha1[256], f_domain[256], user[100], nonce[100],
3006        uri[MAX_REQUEST_SIZE], cnonce[100], resp[100], qop[100], nc[100];
3007
3008   if (c == NULL || fp == NULL) return 0;
3009   if ((hdr = mg_get_header(c, "Authorization")) == NULL ||
3010       mg_strncasecmp(hdr, "Digest ", 7) != 0) return 0;
3011   if (!mg_parse_header(hdr, "username", user, sizeof(user))) return 0;
3012   if (!mg_parse_header(hdr, "cnonce", cnonce, sizeof(cnonce))) return 0;
3013   if (!mg_parse_header(hdr, "response", resp, sizeof(resp))) return 0;
3014   if (!mg_parse_header(hdr, "uri", uri, sizeof(uri))) return 0;
3015   if (!mg_parse_header(hdr, "qop", qop, sizeof(qop))) return 0;
3016   if (!mg_parse_header(hdr, "nc", nc, sizeof(nc))) return 0;
3017   if (!mg_parse_header(hdr, "nonce", nonce, sizeof(nonce))) return 0;
3018
3019   while (fgets(line, sizeof(line), fp) != NULL) {
3020     if (sscanf(line, "%[^:]:%[^:]:%s", f_user, f_domain, ha1) == 3 &&
3021         !strcmp(user, f_user) &&
3022         // NOTE(lsm): due to a bug in MSIE, we do not compare URIs
3023         !strcmp(conn->server->config_options[AUTH_DOMAIN], f_domain))
3024       return check_password(c->request_method, ha1, uri,
3025                             nonce, nc, cnonce, qop, resp);
3026   }
3027   return MG_AUTH_FAIL;
3028 }
3029
3030
3031 // Return 1 if request is authorised, 0 otherwise.
3032 static int is_authorized(struct connection *conn, const char *path) {
3033   FILE *fp;
3034   int authorized = MG_AUTH_OK;
3035
3036   if ((fp = open_auth_file(conn, path)) != NULL) {
3037     authorized = mg_authorize_digest(&conn->mg_conn, fp);
3038     fclose(fp);
3039   }
3040
3041   return authorized;
3042 }
3043
3044 static int is_authorized_for_dav(struct connection *conn) {
3045   const char *auth_file = conn->server->config_options[DAV_AUTH_FILE];
3046   FILE *fp;
3047   int authorized = MG_AUTH_FAIL;
3048
3049   if (auth_file != NULL && (fp = fopen(auth_file, "r")) != NULL) {
3050     authorized = mg_authorize_digest(&conn->mg_conn, fp);
3051     fclose(fp);
3052   }
3053
3054   return authorized;
3055 }
3056
3057 static int is_dav_mutation(const struct connection *conn) {
3058   const char *s = conn->mg_conn.request_method;
3059   return s && (!strcmp(s, "PUT") || !strcmp(s, "DELETE") ||
3060                !strcmp(s, "MKCOL"));
3061 }
3062 #endif // MONGOOSE_NO_AUTH
3063
3064 int parse_header(const char *str, int str_len, const char *var_name, char *buf,
3065                  size_t buf_size) {
3066   int ch = ' ', len = 0, n = strlen(var_name);
3067   const char *p, *end = str + str_len, *s = NULL;
3068
3069   if (buf != NULL && buf_size > 0) buf[0] = '\0';
3070
3071   // Find where variable starts
3072   for (s = str; s != NULL && s + n < end; s++) {
3073     if ((s == str || s[-1] == ' ' || s[-1] == ',') && s[n] == '=' &&
3074         !memcmp(s, var_name, n)) break;
3075   }
3076
3077   if (s != NULL && &s[n + 1] < end) {
3078     s += n + 1;
3079     if (*s == '"' || *s == '\'') ch = *s++;
3080     p = s;
3081     while (p < end && p[0] != ch && p[0] != ',' && len < (int) buf_size) {
3082       if (p[0] == '\\' && p[1] == ch) p++;
3083       buf[len++] = *p++;
3084     }
3085     if (len >= (int) buf_size || (ch != ' ' && *p != ch)) {
3086       len = 0;
3087     } else {
3088       if (len > 0 && s[len - 1] == ',') len--;
3089       if (len > 0 && s[len - 1] == ';') len--;
3090       buf[len] = '\0';
3091     }
3092   }
3093
3094   return len;
3095 }
3096
3097 int mg_parse_header(const char *s, const char *var_name, char *buf,
3098                     size_t buf_size) {
3099   return parse_header(s, s == NULL ? 0 : strlen(s), var_name, buf, buf_size);
3100 }
3101
3102 #ifdef MONGOOSE_USE_LUA
3103 #include "lua_5.2.1.h"
3104
3105 #ifdef _WIN32
3106 static void *mmap(void *addr, int64_t len, int prot, int flags, int fd,
3107                   int offset) {
3108   HANDLE fh = (HANDLE) _get_osfhandle(fd);
3109   HANDLE mh = CreateFileMapping(fh, 0, PAGE_READONLY, 0, 0, 0);
3110   void *p = MapViewOfFile(mh, FILE_MAP_READ, 0, 0, (size_t) len);
3111   CloseHandle(mh);
3112   return p;
3113 }
3114 #define munmap(x, y)  UnmapViewOfFile(x)
3115 #define MAP_FAILED NULL
3116 #define MAP_PRIVATE 0
3117 #define PROT_READ 0
3118 #else
3119 #include <sys/mman.h>
3120 #endif
3121
3122 static void reg_string(struct lua_State *L, const char *name, const char *val) {
3123   lua_pushstring(L, name);
3124   lua_pushstring(L, val);
3125   lua_rawset(L, -3);
3126 }
3127
3128 static void reg_int(struct lua_State *L, const char *name, int val) {
3129   lua_pushstring(L, name);
3130   lua_pushinteger(L, val);
3131   lua_rawset(L, -3);
3132 }
3133
3134 static void reg_function(struct lua_State *L, const char *name,
3135                          lua_CFunction func, struct mg_connection *conn) {
3136   lua_pushstring(L, name);
3137   lua_pushlightuserdata(L, conn);
3138   lua_pushcclosure(L, func, 1);
3139   lua_rawset(L, -3);
3140 }
3141
3142 static int lua_write(lua_State *L) {
3143   int i, num_args;
3144   const char *str;
3145   size_t size;
3146   struct mg_connection *conn = (struct mg_connection *)
3147     lua_touserdata(L, lua_upvalueindex(1));
3148
3149   num_args = lua_gettop(L);
3150   for (i = 1; i <= num_args; i++) {
3151     if (lua_isstring(L, i)) {
3152       str = lua_tolstring(L, i, &size);
3153       mg_write(conn, str, size);
3154     }
3155   }
3156
3157   return 0;
3158 }
3159
3160 static int lsp_sock_close(lua_State *L) {
3161   if (lua_gettop(L) > 0 && lua_istable(L, -1)) {
3162     lua_getfield(L, -1, "sock");
3163     closesocket((sock_t) lua_tonumber(L, -1));
3164   } else {
3165     return luaL_error(L, "invalid :close() call");
3166   }
3167   return 1;
3168 }
3169
3170 static int lsp_sock_recv(lua_State *L) {
3171   char buf[2000];
3172   int n;
3173
3174   if (lua_gettop(L) > 0 && lua_istable(L, -1)) {
3175     lua_getfield(L, -1, "sock");
3176     n = recv((sock_t) lua_tonumber(L, -1), buf, sizeof(buf), 0);
3177     if (n <= 0) {
3178       lua_pushnil(L);
3179     } else {
3180       lua_pushlstring(L, buf, n);
3181     }
3182   } else {
3183     return luaL_error(L, "invalid :close() call");
3184   }
3185   return 1;
3186 }
3187
3188 static int lsp_sock_send(lua_State *L) {
3189   const char *buf;
3190   size_t len, sent = 0;
3191   int n, sock;
3192
3193   if (lua_gettop(L) > 1 && lua_istable(L, -2) && lua_isstring(L, -1)) {
3194     buf = lua_tolstring(L, -1, &len);
3195     lua_getfield(L, -2, "sock");
3196     sock = (int) lua_tonumber(L, -1);
3197     while (sent < len) {
3198       if ((n = send(sock, buf + sent, len - sent, 0)) <= 0) break;
3199       sent += n;
3200     }
3201     lua_pushnumber(L, sent);
3202   } else {
3203     return luaL_error(L, "invalid :close() call");
3204   }
3205   return 1;
3206 }
3207
3208 static const struct luaL_Reg luasocket_methods[] = {
3209   {"close", lsp_sock_close},
3210   {"send", lsp_sock_send},
3211   {"recv", lsp_sock_recv},
3212   {NULL, NULL}
3213 };
3214
3215 static sock_t conn2(const char *host, int port) {
3216   struct sockaddr_in sin;
3217   struct hostent *he = NULL;
3218   sock_t sock = INVALID_SOCKET;
3219
3220   if (host != NULL &&
3221       (he = gethostbyname(host)) != NULL &&
3222     (sock = socket(PF_INET, SOCK_STREAM, 0)) != INVALID_SOCKET) {
3223     set_close_on_exec(sock);
3224     sin.sin_family = AF_INET;
3225     sin.sin_port = htons((uint16_t) port);
3226     sin.sin_addr = * (struct in_addr *) he->h_addr_list[0];
3227     if (connect(sock, (struct sockaddr *) &sin, sizeof(sin)) != 0) {
3228       closesocket(sock);
3229       sock = INVALID_SOCKET;
3230     }
3231   }
3232   return sock;
3233 }
3234
3235 static int lsp_connect(lua_State *L) {
3236   sock_t sock;
3237
3238   if (lua_isstring(L, -2) && lua_isnumber(L, -1)) {
3239     sock = conn2(lua_tostring(L, -2), (int) lua_tonumber(L, -1));
3240     if (sock == INVALID_SOCKET) {
3241       lua_pushnil(L);
3242     } else {
3243       lua_newtable(L);
3244       reg_int(L, "sock", sock);
3245       reg_string(L, "host", lua_tostring(L, -4));
3246       luaL_getmetatable(L, "luasocket");
3247       lua_setmetatable(L, -2);
3248     }
3249   } else {
3250     return luaL_error(L, "connect(host,port): invalid parameter given.");
3251   }
3252   return 1;
3253 }
3254
3255 static void prepare_lua_environment(struct mg_connection *ri, lua_State *L) {
3256   extern void luaL_openlibs(lua_State *);
3257   int i;
3258
3259   luaL_openlibs(L);
3260 #ifdef MONGOOSE_USE_LUA_SQLITE3
3261   { extern int luaopen_lsqlite3(lua_State *); luaopen_lsqlite3(L); }
3262 #endif
3263
3264   luaL_newmetatable(L, "luasocket");
3265   lua_pushliteral(L, "__index");
3266   luaL_newlib(L, luasocket_methods);
3267   lua_rawset(L, -3);
3268   lua_pop(L, 1);
3269   lua_register(L, "connect", lsp_connect);
3270
3271   if (ri == NULL) return;
3272
3273   // Register mg module
3274   lua_newtable(L);
3275   reg_function(L, "write", lua_write, ri);
3276
3277   // Export request_info
3278   lua_pushstring(L, "request_info");
3279   lua_newtable(L);
3280   reg_string(L, "request_method", ri->request_method);
3281   reg_string(L, "uri", ri->uri);
3282   reg_string(L, "http_version", ri->http_version);
3283   reg_string(L, "query_string", ri->query_string);
3284   reg_string(L, "remote_ip", ri->remote_ip);
3285   reg_int(L, "remote_port", ri->remote_port);
3286   lua_pushstring(L, "content");
3287   lua_pushlstring(L, ri->content == NULL ? "" : ri->content, 0);
3288   lua_rawset(L, -3);
3289   reg_int(L, "content_len", ri->content_len);
3290   reg_int(L, "num_headers", ri->num_headers);
3291   lua_pushstring(L, "http_headers");
3292   lua_newtable(L);
3293   for (i = 0; i < ri->num_headers; i++) {
3294     reg_string(L, ri->http_headers[i].name, ri->http_headers[i].value);
3295   }
3296   lua_rawset(L, -3);
3297   lua_rawset(L, -3);
3298
3299   lua_setglobal(L, "mg");
3300
3301   // Register default mg.onerror function
3302   (void) luaL_dostring(L, "mg.onerror = function(e) mg.write('\\nLua "
3303                        "error:\\n', debug.traceback(e, 1)) end");
3304 }
3305
3306 static int lua_error_handler(lua_State *L) {
3307   const char *error_msg =  lua_isstring(L, -1) ?  lua_tostring(L, -1) : "?\n";
3308
3309   lua_getglobal(L, "mg");
3310   if (!lua_isnil(L, -1)) {
3311     lua_getfield(L, -1, "write");   // call mg.write()
3312     lua_pushstring(L, error_msg);
3313     lua_pushliteral(L, "\n");
3314     lua_call(L, 2, 0);
3315     (void) luaL_dostring(L, "mg.write(debug.traceback(), '\\n')");
3316   } else {
3317     printf("Lua error: [%s]\n", error_msg);
3318     (void) luaL_dostring(L, "print(debug.traceback(), '\\n')");
3319   }
3320   // TODO(lsm): leave the stack balanced
3321
3322   return 0;
3323 }
3324
3325 static void lsp(struct connection *conn, const char *p, int len, lua_State *L) {
3326   int i, j, pos = 0;
3327
3328   for (i = 0; i < len; i++) {
3329     if (p[i] == '<' && p[i + 1] == '?') {
3330       for (j = i + 1; j < len ; j++) {
3331         if (p[j] == '?' && p[j + 1] == '>') {
3332           mg_write(&conn->mg_conn, p + pos, i - pos);
3333           if (luaL_loadbuffer(L, p + (i + 2), j - (i + 2), "") == LUA_OK) {
3334             lua_pcall(L, 0, LUA_MULTRET, 0);
3335           }
3336           pos = j + 2;
3337           i = pos - 1;
3338           break;
3339         }
3340       }
3341     }
3342   }
3343   if (i > pos) mg_write(&conn->mg_conn, p + pos, i - pos);
3344 }
3345
3346 static void handle_lsp_request(struct connection *conn, const char *path,
3347                                file_stat_t *st) {
3348   void *p = NULL;
3349   lua_State *L = NULL;
3350   FILE *fp = NULL;
3351
3352   if ((fp = fopen(path, "r")) == NULL ||
3353       (p = mmap(NULL, st->st_size, PROT_READ, MAP_PRIVATE,
3354                 fileno(fp), 0)) == MAP_FAILED ||
3355       (L = luaL_newstate()) == NULL) {
3356     send_http_error(conn, 500, "mmap(%s): %s", path, strerror(errno));
3357   } else {
3358     // We're not sending HTTP headers here, Lua page must do it.
3359     prepare_lua_environment(&conn->mg_conn, L);
3360     lua_pushcclosure(L, &lua_error_handler, 0);
3361     lua_pushglobaltable(L);
3362     lsp(conn, p, (int) st->st_size, L);
3363     close_local_endpoint(conn);
3364   }
3365
3366   if (L != NULL) lua_close(L);
3367   if (p != NULL) munmap(p, st->st_size);
3368   if (fp != NULL) fclose(fp);
3369 }
3370 #endif // MONGOOSE_USE_LUA
3371
3372 static void open_local_endpoint(struct connection *conn, int skip_user) {
3373 #ifndef MONGOOSE_NO_FILESYSTEM
3374   static const char lua_pat[] = LUA_SCRIPT_PATTERN;
3375   file_stat_t st;
3376   char path[MAX_PATH_SIZE];
3377   int exists = 0, is_directory = 0;
3378 #ifndef MONGOOSE_NO_CGI
3379   const char *cgi_pat = conn->server->config_options[CGI_PATTERN];
3380 #else
3381   const char *cgi_pat = DEFAULT_CGI_PATTERN;
3382 #endif
3383 #ifndef MONGOOSE_NO_DIRECTORY_LISTING
3384   const char *dir_lst = conn->server->config_options[ENABLE_DIRECTORY_LISTING];
3385 #else
3386   const char *dir_lst = "yes";
3387 #endif
3388 #endif
3389
3390 #ifndef MONGOOSE_NO_AUTH
3391   // Call auth handler
3392   if (conn->server->auth_handler != NULL &&
3393       conn->server->auth_handler(&conn->mg_conn) == MG_AUTH_FAIL) {
3394     mg_send_digest_auth_request(&conn->mg_conn);
3395     return;
3396   }
3397 #endif
3398
3399   // Call URI handler if one is registered for this URI
3400   if (skip_user == 0 && conn->server->request_handler != NULL) {
3401     conn->endpoint_type = EP_USER;
3402 #if MONGOOSE_USE_POST_SIZE_LIMIT > 1
3403     {
3404       const char *cl = mg_get_header(&conn->mg_conn, "Content-Length");
3405       if (!strcmp(conn->mg_conn.request_method, "POST") &&
3406           (cl == NULL || to64(cl) > MONGOOSE_USE_POST_SIZE_LIMIT)) {
3407         send_http_error(conn, 500, "POST size > %zu",
3408                         (size_t) MONGOOSE_USE_POST_SIZE_LIMIT);
3409       }
3410     }
3411 #endif
3412     return;
3413   }
3414
3415 #ifdef MONGOOSE_NO_FILESYSTEM
3416   if (!strcmp(conn->mg_conn.request_method, "OPTIONS")) {
3417     send_options(conn);
3418   } else {
3419     send_http_error(conn, 404, NULL);
3420   }
3421 #else
3422   exists = convert_uri_to_file_name(conn, path, sizeof(path), &st);
3423   is_directory = S_ISDIR(st.st_mode);
3424
3425   if (!strcmp(conn->mg_conn.request_method, "OPTIONS")) {
3426     send_options(conn);
3427   } else if (conn->server->config_options[DOCUMENT_ROOT] == NULL) {
3428     send_http_error(conn, 404, NULL);
3429 #ifndef MONGOOSE_NO_AUTH
3430   } else if ((!is_dav_mutation(conn) && !is_authorized(conn, path)) ||
3431              (is_dav_mutation(conn) && !is_authorized_for_dav(conn))) {
3432     mg_send_digest_auth_request(&conn->mg_conn);
3433     close_local_endpoint(conn);
3434 #endif
3435 #ifndef MONGOOSE_NO_DAV
3436   } else if (!strcmp(conn->mg_conn.request_method, "PROPFIND")) {
3437     handle_propfind(conn, path, &st);
3438   } else if (!strcmp(conn->mg_conn.request_method, "MKCOL")) {
3439     handle_mkcol(conn, path);
3440   } else if (!strcmp(conn->mg_conn.request_method, "DELETE")) {
3441     handle_delete(conn, path);
3442   } else if (!strcmp(conn->mg_conn.request_method, "PUT")) {
3443     handle_put(conn, path);
3444 #endif
3445   } else if (!exists || must_hide_file(conn, path)) {
3446     send_http_error(conn, 404, NULL);
3447   } else if (is_directory &&
3448              conn->mg_conn.uri[strlen(conn->mg_conn.uri) - 1] != '/') {
3449     conn->mg_conn.status_code = 301;
3450     mg_printf(&conn->mg_conn, "HTTP/1.1 301 Moved Permanently\r\n"
3451               "Location: %s/\r\n\r\n", conn->mg_conn.uri);
3452     close_local_endpoint(conn);
3453   } else if (is_directory && !find_index_file(conn, path, sizeof(path), &st)) {
3454     if (!mg_strcasecmp(dir_lst, "yes")) {
3455 #ifndef MONGOOSE_NO_DIRECTORY_LISTING
3456       send_directory_listing(conn, path);
3457 #else
3458       send_http_error(conn, 501, NULL);
3459 #endif
3460     } else {
3461       send_http_error(conn, 403, NULL);
3462     }
3463   } else if (match_prefix(lua_pat, sizeof(lua_pat) - 1, path) > 0) {
3464 #ifdef MONGOOSE_USE_LUA
3465     handle_lsp_request(conn, path, &st);
3466 #else
3467     send_http_error(conn, 501, NULL);
3468 #endif
3469   } else if (match_prefix(cgi_pat, strlen(cgi_pat), path) > 0) {
3470 #if !defined(MONGOOSE_NO_CGI)
3471     open_cgi_endpoint(conn, path);
3472 #else
3473     send_http_error(conn, 501, NULL);
3474 #endif // !MONGOOSE_NO_CGI
3475   } else if (is_not_modified(conn, &st)) {
3476     send_http_error(conn, 304, NULL);
3477   } else if ((conn->endpoint.fd = open(path, O_RDONLY | O_BINARY)) != -1) {
3478     // O_BINARY is required for Windows, otherwise in default text mode
3479     // two bytes \r\n will be read as one.
3480     open_file_endpoint(conn, path, &st);
3481   } else {
3482     send_http_error(conn, 404, NULL);
3483   }
3484 #endif  // MONGOOSE_NO_FILESYSTEM
3485 }
3486
3487 static void send_continue_if_expected(struct connection *conn) {
3488   static const char expect_response[] = "HTTP/1.1 100 Continue\r\n\r\n";
3489   const char *expect_hdr = mg_get_header(&conn->mg_conn, "Expect");
3490
3491   if (expect_hdr != NULL && !mg_strcasecmp(expect_hdr, "100-continue")) {
3492     spool(&conn->remote_iobuf, expect_response, sizeof(expect_response) - 1);
3493   }
3494 }
3495
3496 static int is_valid_uri(const char *uri) {
3497   // Conform to http://www.w3.org/Protocols/rfc2616/rfc2616-sec5.html#sec5.1.2
3498   // URI can be an asterisk (*) or should start with slash.
3499   return uri[0] == '/' || (uri[0] == '*' && uri[1] == '\0');
3500 }
3501
3502 static void try_http_parse_and_set_content_length(struct connection *conn) {
3503   struct iobuf *io = &conn->local_iobuf;
3504
3505   if (conn->request_len == 0 &&
3506       (conn->request_len = get_request_len(io->buf, io->len)) > 0) {
3507     // If request is buffered in, remove it from the iobuf. This is because
3508     // iobuf could be reallocated, and pointers in parsed request could
3509     // become invalid.
3510     conn->request = (char *) malloc(conn->request_len);
3511     memcpy(conn->request, io->buf, conn->request_len);
3512     DBG(("%p [%.*s]", conn, conn->request_len, conn->request));
3513     discard_leading_iobuf_bytes(io, conn->request_len);
3514     conn->request_len = parse_http_message(conn->request, conn->request_len,
3515                                            &conn->mg_conn);
3516     if (conn->request_len > 0) {
3517       const char *cl_hdr = mg_get_header(&conn->mg_conn, "Content-Length");
3518       conn->cl = cl_hdr == NULL ? 0 : to64(cl_hdr);
3519       conn->mg_conn.content_len = (long int) conn->cl;
3520     }
3521   }
3522 }
3523
3524 static void process_request(struct connection *conn) {
3525   struct iobuf *io = &conn->local_iobuf;
3526
3527   try_http_parse_and_set_content_length(conn);
3528   DBG(("%p %d %d %d [%.*s]", conn, conn->request_len, io->len, conn->flags,
3529        io->len, io->buf));
3530   if (conn->request_len < 0 ||
3531       (conn->request_len > 0 && !is_valid_uri(conn->mg_conn.uri))) {
3532     send_http_error(conn, 400, NULL);
3533   } else if (conn->request_len == 0 && io->len > MAX_REQUEST_SIZE) {
3534     send_http_error(conn, 413, NULL);
3535   } else if (conn->request_len > 0 &&
3536              strcmp(conn->mg_conn.http_version, "1.0") != 0 &&
3537              strcmp(conn->mg_conn.http_version, "1.1") != 0) {
3538     send_http_error(conn, 505, NULL);
3539   } else if (conn->request_len > 0 && conn->endpoint_type == EP_NONE) {
3540 #ifndef MONGOOSE_NO_WEBSOCKET
3541     send_websocket_handshake_if_requested(&conn->mg_conn);
3542 #endif
3543     send_continue_if_expected(conn);
3544     open_local_endpoint(conn, 0);
3545   }
3546
3547 #ifndef MONGOOSE_NO_CGI
3548   if (conn->endpoint_type == EP_CGI && io->len > 0) {
3549     forward_post_data(conn);
3550   }
3551 #endif
3552   if (conn->endpoint_type == EP_USER) {
3553     call_request_handler_if_data_is_buffered(conn);
3554   }
3555 #ifndef MONGOOSE_NO_DAV
3556   if (conn->endpoint_type == EP_PUT && io->len > 0) {
3557     forward_put_data(conn);
3558   }
3559 #endif
3560 }
3561
3562 static void call_http_client_handler(struct connection *conn, int code) {
3563   conn->mg_conn.status_code = code;
3564   // For responses without Content-Lengh, use the whole buffer
3565   if (conn->cl == 0 && code == MG_DOWNLOAD_SUCCESS) {
3566     conn->mg_conn.content_len = conn->local_iobuf.len;
3567   }
3568   conn->mg_conn.content = conn->local_iobuf.buf;
3569   if (conn->handler(&conn->mg_conn) || code == MG_CONNECT_FAILURE ||
3570       code == MG_DOWNLOAD_FAILURE) {
3571     conn->flags |= CONN_CLOSE;
3572   }
3573   discard_leading_iobuf_bytes(&conn->local_iobuf, conn->mg_conn.content_len);
3574   conn->flags = conn->mg_conn.status_code = 0;
3575   conn->cl = conn->num_bytes_sent = conn->request_len = 0;
3576   free(conn->request);
3577   conn->request = NULL;
3578 }
3579
3580 static void process_response(struct connection *conn) {
3581   struct iobuf *io = &conn->local_iobuf;
3582
3583   try_http_parse_and_set_content_length(conn);
3584   DBG(("%p %d %d [%.*s]", conn, conn->request_len, io->len,
3585        io->len > 40 ? 40 : io->len, io->buf));
3586   if (conn->request_len < 0 ||
3587       (conn->request_len == 0 && io->len > MAX_REQUEST_SIZE)) {
3588     call_http_client_handler(conn, MG_DOWNLOAD_FAILURE);
3589   }
3590   if (io->len >= conn->cl) {
3591     call_http_client_handler(conn, MG_DOWNLOAD_SUCCESS);
3592   }
3593 }
3594
3595 static void read_from_socket(struct connection *conn) {
3596   char buf[IOBUF_SIZE];
3597   int n = 0;
3598
3599   if (conn->endpoint_type == EP_CLIENT && conn->flags & CONN_CONNECTING) {
3600     callback_http_client_on_connect(conn);
3601     return;
3602   }
3603
3604 #ifdef MONGOOSE_USE_SSL
3605   if (conn->ssl != NULL) {
3606     if (conn->flags & CONN_SSL_HANDS_SHAKEN) {
3607       n = SSL_read(conn->ssl, buf, sizeof(buf));
3608     } else {
3609       if (SSL_accept(conn->ssl) == 1) {
3610         conn->flags |= CONN_SSL_HANDS_SHAKEN;
3611       }
3612       return;
3613     }
3614   } else
3615 #endif
3616   {
3617     n = recv(conn->client_sock, buf, sizeof(buf), 0);
3618   }
3619
3620   DBG(("%p %d %d (1)", conn, n, conn->flags));
3621   if (is_error(n)) {
3622     if (conn->endpoint_type == EP_CLIENT && conn->local_iobuf.len > 0) {
3623       call_http_client_handler(conn, MG_DOWNLOAD_SUCCESS);
3624     }
3625     conn->flags |= CONN_CLOSE;
3626   } else if (n > 0) {
3627     spool(&conn->local_iobuf, buf, n);
3628     if (conn->endpoint_type == EP_CLIENT) {
3629       process_response(conn);
3630     } else {
3631       process_request(conn);
3632     }
3633   }
3634   DBG(("%p %d %d (2)", conn, n, conn->flags));
3635 }
3636
3637 int mg_connect(struct mg_server *server, const char *host, int port,
3638                int use_ssl, mg_handler_t handler, void *param) {
3639   sock_t sock = INVALID_SOCKET;
3640   struct sockaddr_in sin;
3641   struct hostent *he = NULL;
3642   struct connection *conn = NULL;
3643   int connect_ret_val;
3644
3645   if (host == NULL || (he = gethostbyname(host)) == NULL ||
3646       (sock = socket(PF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) return 0;
3647 #ifndef MONGOOSE_USE_SSL
3648   if (use_ssl) return 0;
3649 #endif
3650
3651   sin.sin_family = AF_INET;
3652   sin.sin_port = htons((uint16_t) port);
3653   sin.sin_addr = * (struct in_addr *) he->h_addr_list[0];
3654   set_non_blocking_mode(sock);
3655
3656   connect_ret_val = connect(sock, (struct sockaddr *) &sin, sizeof(sin));
3657   if (is_error(connect_ret_val)) {
3658     return 0;
3659   } else if ((conn = (struct connection *) calloc(1, sizeof(*conn))) == NULL) {
3660     closesocket(sock);
3661     return 0;
3662   }
3663
3664   conn->server = server;
3665   conn->client_sock = sock;
3666   conn->endpoint_type = EP_CLIENT;
3667   conn->handler = handler;
3668   conn->mg_conn.server_param = server->server_data;
3669   conn->mg_conn.connection_param = param;
3670   conn->birth_time = conn->last_activity_time = time(NULL);
3671   conn->flags = CONN_CONNECTING;
3672   conn->mg_conn.status_code = MG_CONNECT_FAILURE;
3673 #ifdef MONGOOSE_USE_SSL
3674   if (use_ssl && (conn->ssl = SSL_new(server->client_ssl_ctx)) != NULL) {
3675     SSL_set_fd(conn->ssl, sock);
3676   }
3677 #endif
3678   LINKED_LIST_ADD_TO_FRONT(&server->active_connections, &conn->link);
3679   DBG(("%p %s:%d", conn, host, port));
3680
3681   return 1;
3682 }
3683
3684 #ifndef MONGOOSE_NO_LOGGING
3685 static void log_header(const struct mg_connection *conn, const char *header,
3686                        FILE *fp) {
3687   const char *header_value;
3688
3689   if ((header_value = mg_get_header(conn, header)) == NULL) {
3690     (void) fprintf(fp, "%s", " -");
3691   } else {
3692     (void) fprintf(fp, " \"%s\"", header_value);
3693   }
3694 }
3695
3696 static void log_access(const struct connection *conn, const char *path) {
3697   const struct mg_connection *c = &conn->mg_conn;
3698   FILE *fp = (path == NULL) ?  NULL : fopen(path, "a+");
3699   char date[64], user[100];
3700
3701   if (fp == NULL) return;
3702   strftime(date, sizeof(date), "%d/%b/%Y:%H:%M:%S %z",
3703            localtime(&conn->birth_time));
3704
3705   flockfile(fp);
3706   mg_parse_header(mg_get_header(&conn->mg_conn, "Authorization"), "username",
3707                   user, sizeof(user));
3708   fprintf(fp, "%s - %s [%s] \"%s %s HTTP/%s\" %d %" INT64_FMT,
3709           c->remote_ip, user[0] == '\0' ? "-" : user, date,
3710           c->request_method ? c->request_method : "-",
3711           c->uri ? c->uri : "-", c->http_version,
3712           c->status_code, conn->num_bytes_sent);
3713   log_header(c, "Referer", fp);
3714   log_header(c, "User-Agent", fp);
3715   fputc('\n', fp);
3716   fflush(fp);
3717
3718   funlockfile(fp);
3719   fclose(fp);
3720 }
3721 #endif
3722
3723 static void close_local_endpoint(struct connection *conn) {
3724   struct mg_connection *c = &conn->mg_conn;
3725   // Must be done before free()
3726   int keep_alive = should_keep_alive(&conn->mg_conn) &&
3727     (conn->endpoint_type == EP_FILE || conn->endpoint_type == EP_USER);
3728   DBG(("%p %d %d %d", conn, conn->endpoint_type, keep_alive, conn->flags));
3729
3730   switch (conn->endpoint_type) {
3731     case EP_PUT: close(conn->endpoint.fd); break;
3732     case EP_FILE: close(conn->endpoint.fd); break;
3733     case EP_CGI: closesocket(conn->endpoint.cgi_sock); break;
3734     default: break;
3735   }
3736
3737 #ifndef MONGOOSE_NO_LOGGING
3738   if (c->status_code > 0 && conn->endpoint_type != EP_CLIENT &&
3739       c->status_code != 400) {
3740     log_access(conn, conn->server->config_options[ACCESS_LOG_FILE]);
3741   }
3742 #endif
3743
3744   // Gobble possible POST data sent to the URI handler
3745   discard_leading_iobuf_bytes(&conn->local_iobuf, conn->mg_conn.content_len);
3746   conn->endpoint_type = EP_NONE;
3747   conn->cl = conn->num_bytes_sent = conn->request_len = conn->flags = 0;
3748   c->request_method = c->uri = c->http_version = c->query_string = NULL;
3749   c->num_headers = c->status_code = c->is_websocket = c->content_len = 0;
3750   free(conn->request);
3751   conn->request = NULL;
3752
3753   if (keep_alive) {
3754     process_request(conn);  // Can call us recursively if pipelining is used
3755   } else {
3756     conn->flags |= conn->remote_iobuf.len == 0 ? CONN_CLOSE : CONN_SPOOL_DONE;
3757   }
3758 }
3759
3760 static void transfer_file_data(struct connection *conn) {
3761   char buf[IOBUF_SIZE];
3762   int n = read(conn->endpoint.fd, buf, conn->cl < (int64_t) sizeof(buf) ?
3763                (int) conn->cl : (int) sizeof(buf));
3764
3765   if (is_error(n)) {
3766     close_local_endpoint(conn);
3767   } else if (n > 0) {
3768     conn->cl -= n;
3769     spool(&conn->remote_iobuf, buf, n);
3770     if (conn->cl <= 0) {
3771       close_local_endpoint(conn);
3772     }
3773   }
3774 }
3775
3776 static void execute_iteration(struct mg_server *server) {
3777   struct ll *lp, *tmp;
3778   struct connection *conn;
3779   union { mg_handler_t f; void *p; } msg[2];
3780
3781   recv(server->ctl[1], (void *) msg, sizeof(msg), 0);
3782   LINKED_LIST_FOREACH(&server->active_connections, lp, tmp) {
3783     conn = LINKED_LIST_ENTRY(lp, struct connection, link);
3784     conn->mg_conn.connection_param = msg[1].p;
3785     msg[0].f(&conn->mg_conn);
3786   }
3787 }
3788
3789 void add_to_set(sock_t sock, fd_set *set, sock_t *max_fd) {
3790   FD_SET(sock, set);
3791   if (sock > *max_fd) {
3792     *max_fd = sock;
3793   }
3794 }
3795
3796 unsigned int mg_poll_server(struct mg_server *server, int milliseconds) {
3797   struct ll *lp, *tmp;
3798   struct connection *conn;
3799   struct timeval tv;
3800   fd_set read_set, write_set;
3801   sock_t max_fd = -1;
3802   time_t current_time = time(NULL), expire_time = current_time -
3803     MONGOOSE_USE_IDLE_TIMEOUT_SECONDS;
3804
3805   if (server->listening_sock == INVALID_SOCKET) return 0;
3806
3807   FD_ZERO(&read_set);
3808   FD_ZERO(&write_set);
3809   add_to_set(server->listening_sock, &read_set, &max_fd);
3810   add_to_set(server->ctl[1], &read_set, &max_fd);
3811
3812   LINKED_LIST_FOREACH(&server->active_connections, lp, tmp) {
3813     conn = LINKED_LIST_ENTRY(lp, struct connection, link);
3814     add_to_set(conn->client_sock, &read_set, &max_fd);
3815     if (conn->endpoint_type == EP_CLIENT && (conn->flags & CONN_CONNECTING)) {
3816       add_to_set(conn->client_sock, &write_set, &max_fd);
3817     }
3818     if (conn->endpoint_type == EP_FILE) {
3819       transfer_file_data(conn);
3820     } else if (conn->endpoint_type == EP_CGI) {
3821       add_to_set(conn->endpoint.cgi_sock, &read_set, &max_fd);
3822     }
3823     if (conn->remote_iobuf.len > 0 && !(conn->flags & CONN_BUFFER)) {
3824       add_to_set(conn->client_sock, &write_set, &max_fd);
3825     } else if (conn->flags & CONN_CLOSE) {
3826       close_conn(conn);
3827     }
3828   }
3829
3830   tv.tv_sec = milliseconds / 1000;
3831   tv.tv_usec = (milliseconds % 1000) * 1000;
3832
3833   if (select(max_fd + 1, &read_set, &write_set, NULL, &tv) > 0) {
3834     if (FD_ISSET(server->ctl[1], &read_set)) {
3835       execute_iteration(server);
3836     }
3837
3838     // Accept new connections
3839     if (FD_ISSET(server->listening_sock, &read_set)) {
3840       while ((conn = accept_new_connection(server)) != NULL) {
3841         conn->birth_time = conn->last_activity_time = current_time;
3842       }
3843     }
3844
3845     // Read/write from clients
3846     LINKED_LIST_FOREACH(&server->active_connections, lp, tmp) {
3847       conn = LINKED_LIST_ENTRY(lp, struct connection, link);
3848       if (FD_ISSET(conn->client_sock, &read_set)) {
3849         conn->last_activity_time = current_time;
3850         read_from_socket(conn);
3851       }
3852 #ifndef MONGOOSE_NO_CGI
3853       if (conn->endpoint_type == EP_CGI &&
3854           FD_ISSET(conn->endpoint.cgi_sock, &read_set)) {
3855         read_from_cgi(conn);
3856       }
3857 #endif
3858       if (FD_ISSET(conn->client_sock, &write_set)) {
3859         if (conn->endpoint_type == EP_CLIENT &&
3860             (conn->flags & CONN_CONNECTING)) {
3861           read_from_socket(conn);
3862         } else if (!(conn->flags & CONN_BUFFER)) {
3863           conn->last_activity_time = current_time;
3864           write_to_socket(conn);
3865         }
3866       }
3867     }
3868   }
3869
3870   // Close expired connections and those that need to be closed
3871   LINKED_LIST_FOREACH(&server->active_connections, lp, tmp) {
3872     conn = LINKED_LIST_ENTRY(lp, struct connection, link);
3873     if (conn->mg_conn.is_websocket) {
3874       ping_idle_websocket_connection(conn, current_time);
3875     }
3876     if (conn->flags & CONN_LONG_RUNNING) {
3877       conn->mg_conn.wsbits = conn->flags & CONN_CLOSE ? 1 : 0;
3878       if (call_request_handler(conn) == MG_REQUEST_PROCESSED) {
3879         conn->flags |= CONN_CLOSE;
3880       }
3881     }
3882     if (conn->flags & CONN_CLOSE || conn->last_activity_time < expire_time) {
3883       close_conn(conn);
3884     }
3885   }
3886
3887   return (unsigned int) current_time;
3888 }
3889
3890 void mg_destroy_server(struct mg_server **server) {
3891   int i;
3892   struct ll *lp, *tmp;
3893
3894   if (server != NULL && *server != NULL) {
3895     struct mg_server *s = *server;
3896     // Do one last poll, see https://github.com/cesanta/mongoose/issues/286
3897     mg_poll_server(s, 0);
3898     closesocket(s->listening_sock);
3899     closesocket(s->ctl[0]);
3900     closesocket(s->ctl[1]);
3901     LINKED_LIST_FOREACH(&s->active_connections, lp, tmp) {
3902       close_conn(LINKED_LIST_ENTRY(lp, struct connection, link));
3903     }
3904     for (i = 0; i < (int) ARRAY_SIZE(s->config_options); i++) {
3905       free(s->config_options[i]);  // It is OK to free(NULL)
3906     }
3907 #ifdef MONGOOSE_USE_SSL
3908     if (s->ssl_ctx != NULL) SSL_CTX_free((*server)->ssl_ctx);
3909     if (s->client_ssl_ctx != NULL) SSL_CTX_free(s->client_ssl_ctx);
3910 #endif
3911     free(s);
3912     *server = NULL;
3913   }
3914 }
3915
3916 // Apply function to all active connections.
3917 void mg_iterate_over_connections(struct mg_server *server, mg_handler_t handler,
3918                                  void *param) {
3919   // Send closure (function + parameter) to the IO thread to execute
3920   union { mg_handler_t f; void *p; } msg[2];
3921   msg[0].f = handler;
3922   msg[1].p = param;
3923   send(server->ctl[0], (void *) msg, sizeof(msg), 0);
3924 }
3925
3926 static int get_var(const char *data, size_t data_len, const char *name,
3927                    char *dst, size_t dst_len) {
3928   const char *p, *e, *s;
3929   size_t name_len;
3930   int len;
3931
3932   if (dst == NULL || dst_len == 0) {
3933     len = -2;
3934   } else if (data == NULL || name == NULL || data_len == 0) {
3935     len = -1;
3936     dst[0] = '\0';
3937   } else {
3938     name_len = strlen(name);
3939     e = data + data_len;
3940     len = -1;
3941     dst[0] = '\0';
3942
3943     // data is "var1=val1&var2=val2...". Find variable first
3944     for (p = data; p + name_len < e; p++) {
3945       if ((p == data || p[-1] == '&') && p[name_len] == '=' &&
3946           !mg_strncasecmp(name, p, name_len)) {
3947
3948         // Point p to variable value
3949         p += name_len + 1;
3950
3951         // Point s to the end of the value
3952         s = (const char *) memchr(p, '&', (size_t)(e - p));
3953         if (s == NULL) {
3954           s = e;
3955         }
3956         assert(s >= p);
3957
3958         // Decode variable into destination buffer
3959         len = mg_url_decode(p, (size_t)(s - p), dst, dst_len, 1);
3960
3961         // Redirect error code from -1 to -2 (destination buffer too small).
3962         if (len == -1) {
3963           len = -2;
3964         }
3965         break;
3966       }
3967     }
3968   }
3969
3970   return len;
3971 }
3972
3973 int mg_get_var(const struct mg_connection *conn, const char *name,
3974                char *dst, size_t dst_len) {
3975   int len = get_var(conn->query_string, conn->query_string == NULL ? 0 :
3976                     strlen(conn->query_string), name, dst, dst_len);
3977   if (len < 0) {
3978     len = get_var(conn->content, conn->content_len, name, dst, dst_len);
3979   }
3980   return len;
3981 }
3982
3983 static int get_line_len(const char *buf, int buf_len) {
3984   int len = 0;
3985   while (len < buf_len && buf[len] != '\n') len++;
3986   return buf[len] == '\n' ? len + 1: -1;
3987 }
3988
3989 int mg_parse_multipart(const char *buf, int buf_len,
3990                        char *var_name, int var_name_len,
3991                        char *file_name, int file_name_len,
3992                        const char **data, int *data_len) {
3993   static const char cd[] = "Content-Disposition: ";
3994   //struct mg_connection c;
3995   int hl, bl, n, ll, pos, cdl = sizeof(cd) - 1;
3996   //char *p;
3997
3998   if (buf == NULL || buf_len <= 0) return 0;
3999   if ((hl = get_request_len(buf, buf_len)) <= 0) return 0;
4000   if (buf[0] != '-' || buf[1] != '-' || buf[2] == '\n') return 0;
4001
4002   // Get boundary length
4003   bl = get_line_len(buf, buf_len);
4004
4005   // Loop through headers, fetch variable name and file name
4006   var_name[0] = file_name[0] = '\0';
4007   for (n = bl; (ll = get_line_len(buf + n, hl - n)) > 0; n += ll) {
4008     if (mg_strncasecmp(cd, buf + n, cdl) == 0) {
4009       parse_header(buf + n + cdl, ll - (cdl + 2), "name",
4010                    var_name, var_name_len);
4011       parse_header(buf + n + cdl, ll - (cdl + 2), "filename",
4012                    file_name, file_name_len);
4013     }
4014   }
4015
4016   // Scan body, search for terminating boundary
4017   for (pos = hl; pos + (bl - 2) < buf_len; pos++) {
4018     if (buf[pos] == '-' && !memcmp(buf, &buf[pos], bl - 2)) {
4019       if (data_len != NULL) *data_len = (pos - 2) - hl;
4020       if (data != NULL) *data = buf + hl;
4021       return pos;
4022     }
4023   }
4024
4025   return 0;
4026 }
4027
4028 const char **mg_get_valid_option_names(void) {
4029   return static_config_options;
4030 }
4031
4032 static int get_option_index(const char *name) {
4033   int i;
4034
4035   for (i = 0; static_config_options[i * 2] != NULL; i++) {
4036     if (strcmp(static_config_options[i * 2], name) == 0) {
4037       return i;
4038     }
4039   }
4040   return -1;
4041 }
4042
4043 static void set_default_option_values(char **opts) {
4044   const char *value, **all_opts = mg_get_valid_option_names();
4045   int i;
4046
4047   for (i = 0; all_opts[i * 2] != NULL; i++) {
4048     value = all_opts[i * 2 + 1];
4049     if (opts[i] == NULL && value != NULL) {
4050       opts[i] = mg_strdup(value);
4051     }
4052   }
4053 }
4054
4055 // Valid listening port spec is: [ip_address:]port, e.g. "80", "127.0.0.1:3128"
4056 static int parse_port_string(const char *str, union socket_address *sa) {
4057   unsigned int a, b, c, d, port;
4058   int len = 0;
4059 #ifdef MONGOOSE_USE_IPV6
4060   char buf[100];
4061 #endif
4062
4063   // MacOS needs that. If we do not zero it, subsequent bind() will fail.
4064   // Also, all-zeroes in the socket address means binding to all addresses
4065   // for both IPv4 and IPv6 (INADDR_ANY and IN6ADDR_ANY_INIT).
4066   memset(sa, 0, sizeof(*sa));
4067   sa->sin.sin_family = AF_INET;
4068
4069   if (sscanf(str, "%u.%u.%u.%u:%u%n", &a, &b, &c, &d, &port, &len) == 5) {
4070     // Bind to a specific IPv4 address, e.g. 192.168.1.5:8080
4071     sa->sin.sin_addr.s_addr = htonl((a << 24) | (b << 16) | (c << 8) | d);
4072     sa->sin.sin_port = htons((uint16_t) port);
4073 #if defined(MONGOOSE_USE_IPV6)
4074   } else if (sscanf(str, "[%49[^]]]:%u%n", buf, &port, &len) == 2 &&
4075              inet_pton(AF_INET6, buf, &sa->sin6.sin6_addr)) {
4076     // IPv6 address, e.g. [3ffe:2a00:100:7031::1]:8080
4077     sa->sin6.sin6_family = AF_INET6;
4078     sa->sin6.sin6_port = htons((uint16_t) port);
4079 #endif
4080   } else if (sscanf(str, "%u%n", &port, &len) == 1) {
4081     // If only port is specified, bind to IPv4, INADDR_ANY
4082     sa->sin.sin_port = htons((uint16_t) port);
4083   } else {
4084     port = 0;   // Parsing failure. Make port invalid.
4085   }
4086
4087   return port <= 0xffff && str[len] == '\0';
4088 }
4089
4090 const char *mg_set_option(struct mg_server *server, const char *name,
4091                           const char *value) {
4092   int ind = get_option_index(name);
4093   const char *error_msg = NULL;
4094
4095   if (ind < 0) {
4096     error_msg = "No such option";
4097   } else {
4098     if (server->config_options[ind] != NULL) {
4099       free(server->config_options[ind]);
4100     }
4101     server->config_options[ind] = mg_strdup(value);
4102     DBG(("%s [%s]", name, value));
4103
4104     if (ind == LISTENING_PORT) {
4105       if (server->listening_sock != INVALID_SOCKET) {
4106         closesocket(server->listening_sock);
4107       }
4108       parse_port_string(server->config_options[LISTENING_PORT], &server->lsa);
4109       server->listening_sock = open_listening_socket(&server->lsa);
4110       if (server->listening_sock == INVALID_SOCKET) {
4111         error_msg = "Cannot bind to port";
4112       } else {
4113         sockaddr_to_string(server->local_ip, sizeof(server->local_ip),
4114                            &server->lsa);
4115         if (!strcmp(value, "0")) {
4116           char buf[10];
4117           mg_snprintf(buf, sizeof(buf), "%d",
4118                       (int) ntohs(server->lsa.sin.sin_port));
4119           free(server->config_options[ind]);
4120           server->config_options[ind] = mg_strdup(buf);
4121         }
4122       }
4123 #ifndef _WIN32
4124     } else if (ind == RUN_AS_USER) {
4125       struct passwd *pw;
4126       if ((pw = getpwnam(value)) == NULL) {
4127         error_msg = "Unknown user";
4128       } else if (setgid(pw->pw_gid) != 0) {
4129         error_msg = "setgid() failed";
4130       } else if (setuid(pw->pw_uid) != 0) {
4131         error_msg = "setuid() failed";
4132       }
4133 #endif
4134 #ifdef MONGOOSE_USE_SSL
4135     } else if (ind == SSL_CERTIFICATE) {
4136       //SSL_library_init();
4137       if ((server->ssl_ctx = SSL_CTX_new(SSLv23_server_method())) == NULL) {
4138         error_msg = "SSL_CTX_new() failed";
4139       } else if (SSL_CTX_use_certificate_file(server->ssl_ctx, value, 1) == 0 ||
4140                  SSL_CTX_use_PrivateKey_file(server->ssl_ctx, value, 1) == 0) {
4141         error_msg = "Cannot load PEM file";
4142       } else {
4143         SSL_CTX_use_certificate_chain_file(server->ssl_ctx, value);
4144       }
4145 #endif
4146     }
4147   }
4148
4149   return error_msg;
4150 }
4151
4152 void mg_set_request_handler(struct mg_server *server, mg_handler_t handler) {
4153   server->request_handler = handler;
4154 }
4155
4156 void mg_set_http_error_handler(struct mg_server *server, mg_handler_t handler) {
4157   server->error_handler = handler;
4158 }
4159
4160 void mg_set_auth_handler(struct mg_server *server, mg_handler_t handler) {
4161   server->auth_handler = handler;
4162 }
4163
4164 void mg_set_listening_socket(struct mg_server *server, int sock) {
4165   if (server->listening_sock != INVALID_SOCKET) {
4166     closesocket(server->listening_sock);
4167   }
4168   server->listening_sock = (sock_t) sock;
4169 }
4170
4171 int mg_get_listening_socket(struct mg_server *server) {
4172   return server->listening_sock;
4173 }
4174
4175 const char *mg_get_option(const struct mg_server *server, const char *name) {
4176   const char **opts = (const char **) server->config_options;
4177   int i = get_option_index(name);
4178   return i == -1 ? NULL : opts[i] == NULL ? "" : opts[i];
4179 }
4180
4181 struct mg_server *mg_create_server(void *server_data) {
4182   struct mg_server *server = (struct mg_server *) calloc(1, sizeof(*server));
4183
4184 #ifdef _WIN32
4185   WSADATA data;
4186   WSAStartup(MAKEWORD(2, 2), &data);
4187 #else
4188   // Ignore SIGPIPE signal, so if browser cancels the request, it
4189   // won't kill the whole process.
4190   signal(SIGPIPE, SIG_IGN);
4191 #endif
4192
4193   LINKED_LIST_INIT(&server->active_connections);
4194
4195   // Create control socket pair. Do it in a loop to protect from
4196   // interrupted syscalls in mg_socketpair().
4197   do {
4198     mg_socketpair(server->ctl);
4199   } while (server->ctl[0] == INVALID_SOCKET);
4200
4201 #ifdef MONGOOSE_USE_SSL
4202   SSL_library_init();
4203   server->client_ssl_ctx = SSL_CTX_new(SSLv23_client_method());
4204 #endif
4205
4206   server->server_data = server_data;
4207   server->listening_sock = INVALID_SOCKET;
4208   set_default_option_values(server->config_options);
4209
4210   return server;
4211 }