Jamoma API  0.6.0.a19
civetweb.cpp
1 /* Copyright (c) 2004-2013 Sergey Lyubka
2  *
3  * Permission is hereby granted, free of charge, to any person obtaining a copy
4  * of this software and associated documentation files (the "Software"), to deal
5  * in the Software without restriction, including without limitation the rights
6  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7  * copies of the Software, and to permit persons to whom the Software is
8  * furnished to do so, subject to the following conditions:
9  *
10  * The above copyright notice and this permission notice shall be included in
11  * all copies or substantial portions of the Software.
12  *
13  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19  * THE SOFTWARE.
20  */
21 
22 #if defined(_WIN32)
23 #if !defined(_CRT_SECURE_NO_WARNINGS)
24 #define _CRT_SECURE_NO_WARNINGS /* Disable deprecation warning in VS2005 */
25 #endif
26 #else
27 #ifdef __linux__
28 #define _XOPEN_SOURCE 600 /* For flockfile() on Linux */
29 #endif
30 #define _LARGEFILE_SOURCE /* Enable 64-bit file offsets */
31 #define __STDC_FORMAT_MACROS /* <inttypes.h> wants this for C++ */
32 #define __STDC_LIMIT_MACROS /* C++ wants that for INT64_MAX */
33 #endif
34 
35 #if defined (_MSC_VER)
36 /* 'type cast' : conversion from 'int' to 'HANDLE' of greater size */
37 #pragma warning (disable : 4306 )
38 /* conditional expression is constant: introduced by FD_SET(..) */
39 #pragma warning (disable : 4127)
40 /* non-constant aggregate initializer: issued due to missing C99 support */
41 #pragma warning (disable : 4204)
42 #endif
43 
44 /* Disable WIN32_LEAN_AND_MEAN.
45  This makes windows.h always include winsock2.h */
46 #if defined(WIN32_LEAN_AND_MEAN) && (_MSC_VER <= 1400)
47 #undef WIN32_LEAN_AND_MEAN
48 #endif
49 
50 #if defined USE_IPV6 && defined(_WIN32)
51 #include <ws2tcpip.h>
52 #endif
53 
54 #if defined(__SYMBIAN32__)
55 #define NO_SSL /* SSL is not supported */
56 #define NO_CGI /* CGI is not supported */
57 #define PATH_MAX FILENAME_MAX
58 #endif /* __SYMBIAN32__ */
59 
60 #ifndef IGNORE_UNUSED_RESULT
61 #define IGNORE_UNUSED_RESULT(a) (void)((a) && 1)
62 #endif
63 
64 #ifndef _WIN32_WCE /* Some ANSI #includes are not available on Windows CE */
65 #include <sys/types.h>
66 #include <sys/stat.h>
67 #include <errno.h>
68 #include <signal.h>
69 #include <fcntl.h>
70 #endif /* !_WIN32_WCE */
71 
72 #include <time.h>
73 #include <stdlib.h>
74 #include <stdarg.h>
75 #include <assert.h>
76 #include <string.h>
77 #include <ctype.h>
78 #include <limits.h>
79 #include <stddef.h>
80 #include <stdio.h>
81 
82 #define MAX_WORKER_THREADS 1024
83 
84 #if defined(_WIN32) && !defined(__SYMBIAN32__) /* Windows specific */
85 #if defined(_MSC_VER) && _MSC_VER <= 1400
86 #undef _WIN32_WINNT
87 #define _WIN32_WINNT 0x0400 /* To make it link in VS2005 */
88 #endif
89 #include <windows.h>
90 
91 #ifndef PATH_MAX
92 #define PATH_MAX MAX_PATH
93 #endif
94 
95 #ifndef _IN_PORT_T
96 #ifndef in_port_t
97 #define in_port_t u_short
98 #endif
99 #endif
100 
101 #ifndef _WIN32_WCE
102 #include <process.h>
103 #include <direct.h>
104 #include <io.h>
105 #else /* _WIN32_WCE */
106 #define NO_CGI /* WinCE has no pipes */
107 
108 typedef long off_t;
109 
110 #define errno GetLastError()
111 #define strerror(x) _ultoa(x, (char *) _alloca(sizeof(x) *3 ), 10)
112 #endif /* _WIN32_WCE */
113 
114 #define MAKEUQUAD(lo, hi) ((uint64_t)(((uint32_t)(lo)) | \
115  ((uint64_t)((uint32_t)(hi))) << 32))
116 #define RATE_DIFF 10000000 /* 100 nsecs */
117 #define EPOCH_DIFF MAKEUQUAD(0xd53e8000, 0x019db1de)
118 #define SYS2UNIX_TIME(lo, hi) \
119  (time_t) ((MAKEUQUAD((lo), (hi)) - EPOCH_DIFF) / RATE_DIFF)
120 
121 /* Visual Studio 6 does not know __func__ or __FUNCTION__
122  The rest of MS compilers use __FUNCTION__, not C99 __func__
123  Also use _strtoui64 on modern M$ compilers */
124 #if defined(_MSC_VER) && _MSC_VER < 1300
125 #define STRX(x) #x
126 #define STR(x) STRX(x)
127 #define __func__ __FILE__ ":" STR(__LINE__)
128 #define strtoull(x, y, z) (unsigned __int64) _atoi64(x)
129 #define strtoll(x, y, z) _atoi64(x)
130 #else
131 #define __func__ __FUNCTION__
132 #define strtoull(x, y, z) _strtoui64(x, y, z)
133 #define strtoll(x, y, z) _strtoi64(x, y, z)
134 #endif /* _MSC_VER */
135 
136 #define ERRNO GetLastError()
137 #define NO_SOCKLEN_T
138 #define SSL_LIB "ssleay32.dll"
139 #define CRYPTO_LIB "libeay32.dll"
140 #define O_NONBLOCK 0
141 #if !defined(EWOULDBLOCK)
142 #define EWOULDBLOCK WSAEWOULDBLOCK
143 #endif /* !EWOULDBLOCK */
144 #define _POSIX_
145 #define INT64_FMT "I64d"
146 
147 #define WINCDECL __cdecl
148 #define SHUT_WR 1
149 #define snprintf _snprintf
150 #define vsnprintf _vsnprintf
151 #define mg_sleep(x) Sleep(x)
152 
153 #define pipe(x) _pipe(x, MG_BUF_LEN, _O_BINARY)
154 #ifndef popen
155 #define popen(x, y) _popen(x, y)
156 #endif
157 #ifndef pclose
158 #define pclose(x) _pclose(x)
159 #endif
160 #define close(x) _close(x)
161 #define dlsym(x,y) GetProcAddress((HINSTANCE) (x), (y))
162 #define RTLD_LAZY 0
163 #define fseeko(x, y, z) _lseeki64(_fileno(x), (y), (z))
164 #define fdopen(x, y) _fdopen((x), (y))
165 #define write(x, y, z) _write((x), (y), (unsigned) z)
166 #define read(x, y, z) _read((x), (y), (unsigned) z)
167 #define flockfile(x) EnterCriticalSection(&global_log_file_lock)
168 #define funlockfile(x) LeaveCriticalSection(&global_log_file_lock)
169 #define sleep(x) Sleep((x) * 1000)
170 #define rmdir(x) _rmdir(x)
171 
172 #if !defined(va_copy)
173 #define va_copy(x, y) x = y
174 #endif /* !va_copy MINGW #defines va_copy */
175 
176 #if !defined(fileno)
177 #define fileno(x) _fileno(x)
178 #endif /* !fileno MINGW #defines fileno */
179 
180 typedef HANDLE pthread_mutex_t;
181 typedef DWORD pthread_key_t;
182 typedef HANDLE pthread_t;
183 typedef struct {
184  CRITICAL_SECTION threadIdSec;
185  int waitingthreadcount; /* The number of threads queued. */
186  pthread_t *waitingthreadhdls; /* The thread handles. */
187 } pthread_cond_t;
188 
189 typedef DWORD clockid_t;
190 #define CLOCK_MONOTONIC (1)
191 #define CLOCK_REALTIME (2)
192 
193 struct timespec {
194  time_t tv_sec; /* seconds */
195  long tv_nsec; /* nanoseconds */
196 };
197 
198 #define pid_t HANDLE /* MINGW typedefs pid_t to int. Using #define here. */
199 
200 static int pthread_mutex_lock(pthread_mutex_t *);
201 static int pthread_mutex_unlock(pthread_mutex_t *);
202 static void to_unicode(const char *path, wchar_t *wbuf, size_t wbuf_len);
203 struct file;
204 static char *mg_fgets(char *buf, size_t size, struct file *filep, char **p);
205 
206 #if defined(HAVE_STDINT)
207 #include <stdint.h>
208 #else
209 typedef unsigned int uint32_t;
210 typedef unsigned short uint16_t;
211 typedef unsigned __int64 uint64_t;
212 typedef __int64 int64_t;
213 #define INT64_MAX 9223372036854775807
214 #endif /* HAVE_STDINT */
215 
216 /* POSIX dirent interface */
217 struct dirent {
218  char d_name[PATH_MAX];
219 };
220 
221 typedef struct DIR {
222  HANDLE handle;
223  WIN32_FIND_DATAW info;
224  struct dirent result;
225 } DIR;
226 
227 #if !defined(USE_IPV6) && defined(_WIN32)
228 #ifndef HAVE_POLL
229 struct pollfd {
230  SOCKET fd;
231  short events;
232  short revents;
233 };
234 #define POLLIN 1
235 #endif
236 #endif
237 
238 /* Mark required libraries */
239 #ifdef _MSC_VER
240 #pragma comment(lib, "Ws2_32.lib")
241 #endif
242 
243 #else /* UNIX specific */
244 #include <sys/wait.h>
245 #include <sys/socket.h>
246 #include <sys/poll.h>
247 #include <netinet/in.h>
248 #include <arpa/inet.h>
249 #include <sys/time.h>
250 #include <stdint.h>
251 #include <inttypes.h>
252 #include <netdb.h>
253 
254 #include <pwd.h>
255 #include <unistd.h>
256 #include <dirent.h>
257 #if !defined(NO_SSL_DL) && !defined(NO_SSL)
258 #include <dlfcn.h>
259 #endif
260 #include <pthread.h>
261 #if defined(__MACH__)
262 #define SSL_LIB "libssl.dylib"
263 #define CRYPTO_LIB "libcrypto.dylib"
264 #else
265 #if !defined(SSL_LIB)
266 #define SSL_LIB "libssl.so"
267 #endif
268 #if !defined(CRYPTO_LIB)
269 #define CRYPTO_LIB "libcrypto.so"
270 #endif
271 #endif
272 #ifndef O_BINARY
273 #define O_BINARY 0
274 #endif /* O_BINARY */
275 #define closesocket(a) close(a)
276 #define mg_mkdir(x, y) mkdir(x, y)
277 #define mg_remove(x) remove(x)
278 #define mg_sleep(x) usleep((x) * 1000)
279 #define ERRNO errno
280 #define INVALID_SOCKET (-1)
281 #define INT64_FMT PRId64
282 typedef int SOCKET;
283 #define WINCDECL
284 
285 #endif /* End of Windows and UNIX specific includes */
286 
287 #include "civetweb.h"
288 
289 #define PASSWORDS_FILE_NAME ".htpasswd"
290 #define CGI_ENVIRONMENT_SIZE 4096
291 #define MAX_CGI_ENVIR_VARS 64
292 #define MG_BUF_LEN 8192
293 #ifndef MAX_REQUEST_SIZE
294 #define MAX_REQUEST_SIZE 16384
295 #endif
296 #define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0]))
297 
298 #ifdef _WIN32
299 static CRITICAL_SECTION global_log_file_lock;
300 static DWORD pthread_self(void)
301 {
302  return GetCurrentThreadId();
303 }
304 
305 int pthread_key_create(pthread_key_t *key, void (*_must_be_zero)(void*) /* destructor function not supported for windows */)
306 {
307  assert(_must_be_zero == NULL);
308  if ((key!=0) && (_must_be_zero == NULL)) {
309  *key = TlsAlloc();
310  return (*key != TLS_OUT_OF_INDEXES) ? 0 : -1;
311  }
312  return -2;
313 }
314 
315 int pthread_key_delete(pthread_key_t key)
316 {
317  return TlsFree(key) ? 0 : 1;
318 }
319 
320 int pthread_setspecific(pthread_key_t key, void * value)
321 {
322  return TlsSetValue(key, value) ? 0 : 1;
323 }
324 
325 void *pthread_getspecific(pthread_key_t key)
326 {
327  return TlsGetValue(key);
328 }
329 #endif /* _WIN32 */
330 
331 #define MD5_STATIC static
332 #include "md5.inl"
333 
334 #ifdef DEBUG_TRACE
335 #undef DEBUG_TRACE
336 #define DEBUG_TRACE(x)
337 #else
338 #if defined(DEBUG)
339 #define DEBUG_TRACE(x) do { \
340  flockfile(stdout); \
341  printf("*** %lu.%p.%s.%d: ", \
342  (unsigned long) time(NULL), (void *) pthread_self(), \
343  __func__, __LINE__); \
344  printf x; \
345  putchar('\n'); \
346  fflush(stdout); \
347  funlockfile(stdout); \
348 } while (0)
349 #else
350 #define DEBUG_TRACE(x)
351 #endif /* DEBUG */
352 #endif /* DEBUG_TRACE */
353 
354 /* Darwin prior to 7.0 and Win32 do not have socklen_t */
355 #ifdef NO_SOCKLEN_T
356 typedef int socklen_t;
357 #endif /* NO_SOCKLEN_T */
358 #define _DARWIN_UNLIMITED_SELECT
359 
360 #define IP_ADDR_STR_LEN 50 /* IPv6 hex string is 46 chars */
361 
362 #if !defined(MSG_NOSIGNAL)
363 #define MSG_NOSIGNAL 0
364 #endif
365 
366 #if !defined(SOMAXCONN)
367 #define SOMAXCONN 100
368 #endif
369 
370 #if !defined(PATH_MAX)
371 #define PATH_MAX 4096
372 #endif
373 
374 /* Size of the accepted socket queue */
375 #if !defined(MGSQLEN)
376 #define MGSQLEN 20
377 #endif
378 
379 static const char *http_500_error = "Internal Server Error";
380 
381 #if defined(NO_SSL_DL)
382 #include <openssl/ssl.h>
383 #include <openssl/err.h>
384 #else
385 /* SSL loaded dynamically from DLL.
386  I put the prototypes here to be independent from OpenSSL source
387  installation. */
388 
389 typedef struct ssl_st SSL;
390 typedef struct ssl_method_st SSL_METHOD;
391 typedef struct ssl_ctx_st SSL_CTX;
392 
393 struct ssl_func {
394  const char *name; /* SSL function name */
395  void (*ptr)(void); /* Function pointer */
396 };
397 
398 #define SSL_free (* (void (*)(SSL *)) ssl_sw[0].ptr)
399 #define SSL_accept (* (int (*)(SSL *)) ssl_sw[1].ptr)
400 #define SSL_connect (* (int (*)(SSL *)) ssl_sw[2].ptr)
401 #define SSL_read (* (int (*)(SSL *, void *, int)) ssl_sw[3].ptr)
402 #define SSL_write (* (int (*)(SSL *, const void *,int)) ssl_sw[4].ptr)
403 #define SSL_get_error (* (int (*)(SSL *, int)) ssl_sw[5].ptr)
404 #define SSL_set_fd (* (int (*)(SSL *, SOCKET)) ssl_sw[6].ptr)
405 #define SSL_new (* (SSL * (*)(SSL_CTX *)) ssl_sw[7].ptr)
406 #define SSL_CTX_new (* (SSL_CTX * (*)(SSL_METHOD *)) ssl_sw[8].ptr)
407 #define SSLv23_server_method (* (SSL_METHOD * (*)(void)) ssl_sw[9].ptr)
408 #define SSL_library_init (* (int (*)(void)) ssl_sw[10].ptr)
409 #define SSL_CTX_use_PrivateKey_file (* (int (*)(SSL_CTX *, \
410  const char *, int)) ssl_sw[11].ptr)
411 #define SSL_CTX_use_certificate_file (* (int (*)(SSL_CTX *, \
412  const char *, int)) ssl_sw[12].ptr)
413 #define SSL_CTX_set_default_passwd_cb \
414  (* (void (*)(SSL_CTX *, mg_callback_t)) ssl_sw[13].ptr)
415 #define SSL_CTX_free (* (void (*)(SSL_CTX *)) ssl_sw[14].ptr)
416 #define SSL_load_error_strings (* (void (*)(void)) ssl_sw[15].ptr)
417 #define SSL_CTX_use_certificate_chain_file \
418  (* (int (*)(SSL_CTX *, const char *)) ssl_sw[16].ptr)
419 #define SSLv23_client_method (* (SSL_METHOD * (*)(void)) ssl_sw[17].ptr)
420 #define SSL_pending (* (int (*)(SSL *)) ssl_sw[18].ptr)
421 #define SSL_CTX_set_verify (* (void (*)(SSL_CTX *, int, int)) ssl_sw[19].ptr)
422 #define SSL_shutdown (* (int (*)(SSL *)) ssl_sw[20].ptr)
423 
424 #define CRYPTO_num_locks (* (int (*)(void)) crypto_sw[0].ptr)
425 #define CRYPTO_set_locking_callback \
426  (* (void (*)(void (*)(int, int, const char *, int))) crypto_sw[1].ptr)
427 #define CRYPTO_set_id_callback \
428  (* (void (*)(unsigned long (*)(void))) crypto_sw[2].ptr)
429 #define ERR_get_error (* (unsigned long (*)(void)) crypto_sw[3].ptr)
430 #define ERR_error_string (* (char * (*)(unsigned long,char *)) crypto_sw[4].ptr)
431 
432 /* set_ssl_option() function updates this array.
433  It loads SSL library dynamically and changes NULLs to the actual addresses
434  of respective functions. The macros above (like SSL_connect()) are really
435  just calling these functions indirectly via the pointer. */
436 static struct ssl_func ssl_sw[] = {
437  {"SSL_free", NULL},
438  {"SSL_accept", NULL},
439  {"SSL_connect", NULL},
440  {"SSL_read", NULL},
441  {"SSL_write", NULL},
442  {"SSL_get_error", NULL},
443  {"SSL_set_fd", NULL},
444  {"SSL_new", NULL},
445  {"SSL_CTX_new", NULL},
446  {"SSLv23_server_method", NULL},
447  {"SSL_library_init", NULL},
448  {"SSL_CTX_use_PrivateKey_file", NULL},
449  {"SSL_CTX_use_certificate_file",NULL},
450  {"SSL_CTX_set_default_passwd_cb",NULL},
451  {"SSL_CTX_free", NULL},
452  {"SSL_load_error_strings", NULL},
453  {"SSL_CTX_use_certificate_chain_file", NULL},
454  {"SSLv23_client_method", NULL},
455  {"SSL_pending", NULL},
456  {"SSL_CTX_set_verify", NULL},
457  {"SSL_shutdown", NULL},
458  {NULL, NULL}
459 };
460 
461 /* Similar array as ssl_sw. These functions could be located in different
462  lib. */
463 #if !defined(NO_SSL)
464 static struct ssl_func crypto_sw[] = {
465  {"CRYPTO_num_locks", NULL},
466  {"CRYPTO_set_locking_callback", NULL},
467  {"CRYPTO_set_id_callback", NULL},
468  {"ERR_get_error", NULL},
469  {"ERR_error_string", NULL},
470  {NULL, NULL}
471 };
472 #endif /* NO_SSL */
473 #endif /* NO_SSL_DL */
474 
475 static const char *month_names[] = {
476  "Jan", "Feb", "Mar", "Apr", "May", "Jun",
477  "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
478 };
479 
480 /* Unified socket address. For IPv6 support, add IPv6 address structure
481  in the union u. */
482 union usa {
483  struct sockaddr sa;
484  struct sockaddr_in sin;
485 #if defined(USE_IPV6)
486  struct sockaddr_in6 sin6;
487 #endif
488 };
489 
490 /* Describes a string (chunk of memory). */
491 struct vec {
492  const char *ptr;
493  size_t len;
494 };
495 
496 struct file {
497  int is_directory;
498  time_t modification_time;
499  int64_t size;
500  FILE *fp;
501  const char *membuf; /* Non-NULL if file data is in memory */
502  /* set to 1 if the content is gzipped
503  in which case we need a content-encoding: gzip header */
504  int gzipped;
505 };
506 #define STRUCT_FILE_INITIALIZER {0, 0, 0, NULL, NULL, 0}
507 
508 /* Describes listening socket, or socket which was accept()-ed by the master
509  thread and queued for future handling by the worker thread. */
510 struct socket {
511  SOCKET sock; /* Listening socket */
512  union usa lsa; /* Local socket address */
513  union usa rsa; /* Remote socket address */
514  unsigned is_ssl:1; /* Is port SSL-ed */
515  unsigned ssl_redir:1; /* Is port supposed to redirect everything to SSL
516  port */
517 };
518 
519 /* NOTE(lsm): this enum shoulds be in sync with the config_options below. */
520 enum {
521  CGI_EXTENSIONS, CGI_ENVIRONMENT, PUT_DELETE_PASSWORDS_FILE, CGI_INTERPRETER,
522  PROTECT_URI, AUTHENTICATION_DOMAIN, SSI_EXTENSIONS, THROTTLE,
523  ACCESS_LOG_FILE, ENABLE_DIRECTORY_LISTING, ERROR_LOG_FILE,
524  GLOBAL_PASSWORDS_FILE, INDEX_FILES, ENABLE_KEEP_ALIVE, ACCESS_CONTROL_LIST,
525  EXTRA_MIME_TYPES, LISTENING_PORTS, DOCUMENT_ROOT, SSL_CERTIFICATE,
526  NUM_THREADS, RUN_AS_USER, REWRITE, HIDE_FILES, REQUEST_TIMEOUT,
527 
528 #if defined(USE_LUA)
529  LUA_SCRIPT_EXTENSIONS, LUA_SERVER_PAGE_EXTENSIONS,
530 #endif
531 #if defined(USE_WEBSOCKET)
532  WEBSOCKET_ROOT,
533 #endif
534 #if defined(USE_LUA) && defined(USE_WEBSOCKET)
535  LUA_WEBSOCKET_EXTENSIONS,
536 #endif
537 
538  NUM_OPTIONS
539 };
540 
541 static const char *config_options[] = {
542  "cgi_pattern", "**.cgi$|**.pl$|**.php$",
543  "cgi_environment", NULL,
544  "put_delete_auth_file", NULL,
545  "cgi_interpreter", NULL,
546  "protect_uri", NULL,
547  "authentication_domain", "mydomain.com",
548  "ssi_pattern", "**.shtml$|**.shtm$",
549  "throttle", NULL,
550  "access_log_file", NULL,
551  "enable_directory_listing", "yes",
552  "error_log_file", NULL,
553  "global_auth_file", NULL,
554  "index_files",
555 #ifdef USE_LUA
556  "index.html,index.htm,index.lp,index.lsp,index.lua,index.cgi,index.shtml,index.php",
557 #else
558  "index.html,index.htm,index.cgi,index.shtml,index.php",
559 #endif
560  "enable_keep_alive", "no",
561  "access_control_list", NULL,
562  "extra_mime_types", NULL,
563  "listening_ports", "8080",
564  "document_root", NULL,
565  "ssl_certificate", NULL,
566  "num_threads", "50",
567  "run_as_user", NULL,
568  "url_rewrite_patterns", NULL,
569  "hide_files_patterns", NULL,
570  "request_timeout_ms", "30000",
571 
572 #if defined(USE_LUA)
573  "lua_script_pattern", "**.lua$",
574  "lua_server_page_pattern", "**.lp$|**.lsp$",
575 #endif
576 #if defined(USE_WEBSOCKET)
577  "websocket_root", NULL,
578 #endif
579 #if defined(USE_LUA) && defined(USE_WEBSOCKET)
580  "lua_websocket_pattern", "**.lua$",
581 #endif
582 
583  NULL
584 };
585 
586 struct mg_request_handler_info {
587  char *uri;
588  size_t uri_len;
589  mg_request_handler handler;
590  void *cbdata;
591  struct mg_request_handler_info *next;
592 };
593 
594 struct mg_context {
595  volatile int stop_flag; /* Should we stop event loop */
596  void *ssllib_dll_handle; /* Store the ssl library handle. */
597  void *cryptolib_dll_handle; /* Store the crypto library handle. */
598  SSL_CTX *ssl_ctx; /* SSL context */
599  char *config[NUM_OPTIONS]; /* Civetweb configuration parameters */
600  struct mg_callbacks callbacks; /* User-defined callback function */
601  void *user_data; /* User-defined data */
602 
603  struct socket *listening_sockets;
604  in_port_t *listening_ports;
605  int num_listening_sockets;
606 
607  volatile int num_threads; /* Number of threads */
608  pthread_mutex_t mutex; /* Protects (max|num)_threads */
609  pthread_cond_t cond; /* Condvar for tracking workers terminations */
610 
611  struct socket queue[MGSQLEN]; /* Accepted sockets */
612  volatile int sq_head; /* Head of the socket queue */
613  volatile int sq_tail; /* Tail of the socket queue */
614  pthread_cond_t sq_full; /* Signaled when socket is produced */
615  pthread_cond_t sq_empty; /* Signaled when socket is consumed */
616  pthread_t masterthreadid; /* The master thread ID. */
617  int workerthreadcount; /* The amount of worker threads. */
618  pthread_t *workerthreadids;/* The worker thread IDs. */
619 
620  /* linked list of uri handlers */
621  struct mg_request_handler_info *request_handlers;
622 };
623 
624 struct mg_connection {
625  struct mg_request_info request_info;
626  struct mg_context *ctx;
627  SSL *ssl; /* SSL descriptor */
628  SSL_CTX *client_ssl_ctx; /* SSL context for client connections */
629  struct socket client; /* Connected client */
630  time_t birth_time; /* Time when request was received */
631  int64_t num_bytes_sent; /* Total bytes sent to client */
632  int64_t content_len; /* Content-Length header value */
633  int64_t consumed_content; /* How many bytes of content have been read */
634  char *buf; /* Buffer for received data */
635  char *path_info; /* PATH_INFO part of the URL */
636  int must_close; /* 1 if connection must be closed */
637  int buf_size; /* Buffer size */
638  int request_len; /* Size of the request + headers in a buffer */
639  int data_len; /* Total size of data in a buffer */
640  int status_code; /* HTTP reply status code, e.g. 200 */
641  int throttle; /* Throttling, bytes/sec. <= 0 means no
642  throttle */
643  time_t last_throttle_time; /* Last time throttled data was sent */
644  int64_t last_throttle_bytes;/* Bytes sent this second */
645  pthread_mutex_t mutex; /* Used by mg_lock/mg_unlock to ensure atomic
646  transmissions for websockets */
647 #if defined(USE_LUA) && defined(USE_WEBSOCKET)
648  void * lua_websocket_state; /* Lua_State for a websocket connection */
649 #endif
650 };
651 
652 static pthread_key_t sTlsKey; /* Thread local storage index */
653 static int sTlsInit = 0;
654 
655 struct mg_workerTLS {
656  int is_master;
657 #if defined(_WIN32) && !defined(__SYMBIAN32__)
658  HANDLE pthread_cond_helper_mutex;
659 #endif
660 };
661 
662 /* Directory entry */
663 struct de {
664  struct mg_connection *conn;
665  char *file_name;
666  struct file file;
667 };
668 
669 #if defined(USE_WEBSOCKET)
670 static int is_websocket_request(const struct mg_connection *conn);
671 #endif
672 
673 const char **mg_get_valid_option_names(void)
674 {
675  return config_options;
676 }
677 
678 static int is_file_in_memory(struct mg_connection *conn, const char *path,
679  struct file *filep)
680 {
681  size_t size = 0;
682  if ((filep->membuf = conn->ctx->callbacks.open_file == NULL ? NULL :
683  conn->ctx->callbacks.open_file(conn, path, &size)) != NULL) {
684  /* NOTE: override filep->size only on success. Otherwise, it might
685  break constructs like if (!mg_stat() || !mg_fopen()) ... */
686  filep->size = size;
687  }
688  return filep->membuf != NULL;
689 }
690 
691 static int is_file_opened(const struct file *filep)
692 {
693  return filep->membuf != NULL || filep->fp != NULL;
694 }
695 
696 static int mg_fopen(struct mg_connection *conn, const char *path,
697  const char *mode, struct file *filep)
698 {
699  if (!is_file_in_memory(conn, path, filep)) {
700 #ifdef _WIN32
701  wchar_t wbuf[PATH_MAX], wmode[20];
702  to_unicode(path, wbuf, ARRAY_SIZE(wbuf));
703  MultiByteToWideChar(CP_UTF8, 0, mode, -1, wmode, ARRAY_SIZE(wmode));
704  filep->fp = _wfopen(wbuf, wmode);
705 #else
706  filep->fp = fopen(path, mode);
707 #endif
708  }
709 
710  return is_file_opened(filep);
711 }
712 
713 static void mg_fclose(struct file *filep)
714 {
715  if (filep != NULL && filep->fp != NULL) {
716  fclose(filep->fp);
717  }
718 }
719 
720 static int get_option_index(const char *name)
721 {
722  int i;
723 
724  for (i = 0; config_options[i * 2] != NULL; i++) {
725  if (strcmp(config_options[i * 2], name) == 0) {
726  return i;
727  }
728  }
729  return -1;
730 }
731 
732 const char *mg_get_option(const struct mg_context *ctx, const char *name)
733 {
734  int i;
735  if ((i = get_option_index(name)) == -1) {
736  return NULL;
737  } else if (ctx->config[i] == NULL) {
738  return "";
739  } else {
740  return ctx->config[i];
741  }
742 }
743 
744 size_t mg_get_ports(const struct mg_context *ctx, size_t size, int* ports, int* ssl)
745 {
746  size_t i;
747  for (i = 0; i < size && i < (size_t)ctx->num_listening_sockets; i++)
748  {
749  ssl[i] = ctx->listening_sockets[i].is_ssl;
750  ports[i] = ctx->listening_ports[i];
751  }
752  return i;
753 }
754 
755 static void sockaddr_to_string(char *buf, size_t len,
756  const union usa *usa)
757 {
758  buf[0] = '\0';
759 #if defined(USE_IPV6)
760  inet_ntop(usa->sa.sa_family, usa->sa.sa_family == AF_INET ?
761  (void *) &usa->sin.sin_addr :
762  (void *) &usa->sin6.sin6_addr, buf, len);
763 #elif defined(_WIN32)
764  /* Only Windows Vista (and newer) have inet_ntop() */
765  strncpy(buf, inet_ntoa(usa->sin.sin_addr), len);
766 #else
767  inet_ntop(usa->sa.sa_family, (void *) &usa->sin.sin_addr, buf, len);
768 #endif
769 }
770 
771 /* Convert time_t to a string. According to RFC2616, Sec 14.18, this must be included in all responses other than 100, 101, 5xx. */
772 static void gmt_time_string(char *buf, size_t buf_len, time_t *t)
773 {
774  struct tm *tm;
775 
776  tm = gmtime(t);
777  if (tm != NULL) {
778  strftime(buf, buf_len, "%a, %d %b %Y %H:%M:%S GMT", tm);
779  } else {
780  strncpy(buf, "Thu, 01 Jan 1970 00:00:00 GMT", buf_len);
781  buf[buf_len - 1] = '\0';
782  }
783 }
784 
785 /* Print error message to the opened error log stream. */
786 void mg_cry(struct mg_connection *conn, const char *fmt, ...)
787 {
788  char buf[MG_BUF_LEN], src_addr[IP_ADDR_STR_LEN];
789  va_list ap;
790  FILE *fp;
791  time_t timestamp;
792 
793  va_start(ap, fmt);
794  IGNORE_UNUSED_RESULT(vsnprintf(buf, sizeof(buf), fmt, ap));
795  va_end(ap);
796 
797  /* Do not lock when getting the callback value, here and below.
798  I suppose this is fine, since function cannot disappear in the
799  same way string option can. */
800  if (conn->ctx->callbacks.log_message == NULL ||
801  conn->ctx->callbacks.log_message(conn, buf) == 0) {
802  fp = conn->ctx->config[ERROR_LOG_FILE] == NULL ? NULL :
803  fopen(conn->ctx->config[ERROR_LOG_FILE], "a+");
804 
805  if (fp != NULL) {
806  flockfile(fp);
807  timestamp = time(NULL);
808 
809  sockaddr_to_string(src_addr, sizeof(src_addr), &conn->client.rsa);
810  fprintf(fp, "[%010lu] [error] [client %s] ", (unsigned long) timestamp,
811  src_addr);
812 
813  if (conn->request_info.request_method != NULL) {
814  fprintf(fp, "%s %s: ", conn->request_info.request_method,
815  conn->request_info.uri);
816  }
817 
818  fprintf(fp, "%s", buf);
819  fputc('\n', fp);
820  funlockfile(fp);
821  fclose(fp);
822  }
823  }
824 }
825 
826 /* Return fake connection structure. Used for logging, if connection
827  is not applicable at the moment of logging. */
828 static struct mg_connection *fc(struct mg_context *ctx)
829 {
830  static struct mg_connection fake_connection;
831  fake_connection.ctx = ctx;
832  return &fake_connection;
833 }
834 
835 const char *mg_version(void)
836 {
837  return CIVETWEB_VERSION;
838 }
839 
840 struct mg_request_info *mg_get_request_info(struct mg_connection *conn)
841 {
842  return &conn->request_info;
843 }
844 
845 static void mg_strlcpy(register char *dst, register const char *src, size_t n)
846 {
847  for (; *src != '\0' && n > 1; n--) {
848  *dst++ = *src++;
849  }
850  *dst = '\0';
851 }
852 
853 static int lowercase(const char *s)
854 {
855  return tolower(* (const unsigned char *) s);
856 }
857 
858 int mg_strncasecmp(const char *s1, const char *s2, size_t len)
859 {
860  int diff = 0;
861 
862  if (len > 0)
863  do {
864  diff = lowercase(s1++) - lowercase(s2++);
865  } while (diff == 0 && s1[-1] != '\0' && --len > 0);
866 
867  return diff;
868 }
869 
870 static int mg_strcasecmp(const char *s1, const char *s2)
871 {
872  int diff;
873 
874  do {
875  diff = lowercase(s1++) - lowercase(s2++);
876  } while (diff == 0 && s1[-1] != '\0');
877 
878  return diff;
879 }
880 
881 static char * mg_strndup(const char *ptr, size_t len)
882 {
883  char *p;
884 
885  if ((p = (char *) malloc(len + 1)) != NULL) {
886  mg_strlcpy(p, ptr, len + 1);
887  }
888 
889  return p;
890 }
891 
892 static char * mg_strdup(const char *str)
893 {
894  return mg_strndup(str, strlen(str));
895 }
896 
897 static const char *mg_strcasestr(const char *big_str, const char *small_str)
898 {
899  int i, big_len = (int)strlen(big_str), small_len = (int)strlen(small_str);
900 
901  for (i = 0; i <= big_len - small_len; i++) {
902  if (mg_strncasecmp(big_str + i, small_str, small_len) == 0) {
903  return big_str + i;
904  }
905  }
906 
907  return NULL;
908 }
909 
910 /* Like snprintf(), but never returns negative value, or a value
911  that is larger than a supplied buffer.
912  Thanks to Adam Zeldis to pointing snprintf()-caused vulnerability
913  in his audit report. */
914 static int mg_vsnprintf(struct mg_connection *conn, char *buf, size_t buflen,
915  const char *fmt, va_list ap)
916 {
917  int n;
918 
919  if (buflen == 0)
920  return 0;
921 
922  n = vsnprintf(buf, buflen, fmt, ap);
923 
924  if (n < 0) {
925  mg_cry(conn, "vsnprintf error");
926  n = 0;
927  } else if (n >= (int) buflen) {
928  mg_cry(conn, "truncating vsnprintf buffer: [%.*s]",
929  n > 200 ? 200 : n, buf);
930  n = (int) buflen - 1;
931  }
932  buf[n] = '\0';
933 
934  return n;
935 }
936 
937 static int mg_snprintf(struct mg_connection *conn, char *buf, size_t buflen,
938  PRINTF_FORMAT_STRING(const char *fmt), ...)
939 PRINTF_ARGS(4, 5);
940 
941 static int mg_snprintf(struct mg_connection *conn, char *buf, size_t buflen,
942  const char *fmt, ...)
943 {
944  va_list ap;
945  int n;
946 
947  va_start(ap, fmt);
948  n = mg_vsnprintf(conn, buf, buflen, fmt, ap);
949  va_end(ap);
950 
951  return n;
952 }
953 
954 /* Skip the characters until one of the delimiters characters found.
955  0-terminate resulting word. Skip the delimiter and following whitespaces.
956  Advance pointer to buffer to the next word. Return found 0-terminated word.
957  Delimiters can be quoted with quotechar. */
958 static char *skip_quoted(char **buf, const char *delimiters,
959  const char *whitespace, char quotechar)
960 {
961  char *p, *begin_word, *end_word, *end_whitespace;
962 
963  begin_word = *buf;
964  end_word = begin_word + strcspn(begin_word, delimiters);
965 
966  /* Check for quotechar */
967  if (end_word > begin_word) {
968  p = end_word - 1;
969  while (*p == quotechar) {
970  /* If there is anything beyond end_word, copy it */
971  if (*end_word == '\0') {
972  *p = '\0';
973  break;
974  } else {
975  size_t end_off = strcspn(end_word + 1, delimiters);
976  memmove (p, end_word, end_off + 1);
977  p += end_off; /* p must correspond to end_word - 1 */
978  end_word += end_off + 1;
979  }
980  }
981  for (p++; p < end_word; p++) {
982  *p = '\0';
983  }
984  }
985 
986  if (*end_word == '\0') {
987  *buf = end_word;
988  } else {
989  end_whitespace = end_word + 1 + strspn(end_word + 1, whitespace);
990 
991  for (p = end_word; p < end_whitespace; p++) {
992  *p = '\0';
993  }
994 
995  *buf = end_whitespace;
996  }
997 
998  return begin_word;
999 }
1000 
1001 /* Simplified version of skip_quoted without quote char
1002  and whitespace == delimiters */
1003 static char *skip(char **buf, const char *delimiters)
1004 {
1005  return skip_quoted(buf, delimiters, delimiters, 0);
1006 }
1007 
1008 
1009 /* Return HTTP header value, or NULL if not found. */
1010 static const char *get_header(const struct mg_request_info *ri,
1011  const char *name)
1012 {
1013  int i;
1014 
1015  for (i = 0; i < ri->num_headers; i++)
1016  if (!mg_strcasecmp(name, ri->http_headers[i].name))
1017  return ri->http_headers[i].value;
1018 
1019  return NULL;
1020 }
1021 
1022 const char *mg_get_header(const struct mg_connection *conn, const char *name)
1023 {
1024  return get_header(&conn->request_info, name);
1025 }
1026 
1027 /* A helper function for traversing a comma separated list of values.
1028  It returns a list pointer shifted to the next value, or NULL if the end
1029  of the list found.
1030  Value is stored in val vector. If value has form "x=y", then eq_val
1031  vector is initialized to point to the "y" part, and val vector length
1032  is adjusted to point only to "x". */
1033 static const char *next_option(const char *list, struct vec *val,
1034  struct vec *eq_val)
1035 {
1036  if (list == NULL || *list == '\0') {
1037  /* End of the list */
1038  list = NULL;
1039  } else {
1040  val->ptr = list;
1041  if ((list = strchr(val->ptr, ',')) != NULL) {
1042  /* Comma found. Store length and shift the list ptr */
1043  val->len = list - val->ptr;
1044  list++;
1045  } else {
1046  /* This value is the last one */
1047  list = val->ptr + strlen(val->ptr);
1048  val->len = list - val->ptr;
1049  }
1050 
1051  if (eq_val != NULL) {
1052  /* Value has form "x=y", adjust pointers and lengths
1053  so that val points to "x", and eq_val points to "y". */
1054  eq_val->len = 0;
1055  eq_val->ptr = (const char *) memchr(val->ptr, '=', val->len);
1056  if (eq_val->ptr != NULL) {
1057  eq_val->ptr++; /* Skip over '=' character */
1058  eq_val->len = val->ptr + val->len - eq_val->ptr;
1059  val->len = (eq_val->ptr - val->ptr) - 1;
1060  }
1061  }
1062  }
1063 
1064  return list;
1065 }
1066 
1067 /* Perform case-insensitive match of string against pattern */
1068 static int match_prefix(const char *pattern, int pattern_len, const char *str)
1069 {
1070  const char *or_str;
1071  int i, j, len, res;
1072 
1073  if ((or_str = (const char *) memchr(pattern, '|', pattern_len)) != NULL) {
1074  res = match_prefix(pattern, (int)(or_str - pattern), str);
1075  return res > 0 ? res :
1076  match_prefix(or_str + 1, (int)((pattern + pattern_len) - (or_str + 1)), str);
1077  }
1078 
1079  i = j = 0;
1080  res = -1;
1081  for (; i < pattern_len; i++, j++) {
1082  if (pattern[i] == '?' && str[j] != '\0') {
1083  continue;
1084  } else if (pattern[i] == '$') {
1085  return str[j] == '\0' ? j : -1;
1086  } else if (pattern[i] == '*') {
1087  i++;
1088  if (pattern[i] == '*') {
1089  i++;
1090  len = (int) strlen(str + j);
1091  } else {
1092  len = (int) strcspn(str + j, "/");
1093  }
1094  if (i == pattern_len) {
1095  return j + len;
1096  }
1097  do {
1098  res = match_prefix(pattern + i, pattern_len - i, str + j + len);
1099  } while (res == -1 && len-- > 0);
1100  return res == -1 ? -1 : j + res + len;
1101  } else if (lowercase(&pattern[i]) != lowercase(&str[j])) {
1102  return -1;
1103  }
1104  }
1105  return j;
1106 }
1107 
1108 /* HTTP 1.1 assumes keep alive if "Connection:" header is not set
1109  This function must tolerate situations when connection info is not
1110  set up, for example if request parsing failed. */
1111 static int should_keep_alive(const struct mg_connection *conn)
1112 {
1113  const char *http_version = conn->request_info.http_version;
1114  const char *header = mg_get_header(conn, "Connection");
1115  if (conn->must_close ||
1116  conn->status_code == 401 ||
1117  mg_strcasecmp(conn->ctx->config[ENABLE_KEEP_ALIVE], "yes") != 0 ||
1118  (header != NULL && mg_strcasecmp(header, "keep-alive") != 0) ||
1119  (header == NULL && http_version && strcmp(http_version, "1.1"))) {
1120  return 0;
1121  }
1122  return 1;
1123 }
1124 
1125 static const char *suggest_connection_header(const struct mg_connection *conn)
1126 {
1127  return should_keep_alive(conn) ? "keep-alive" : "close";
1128 }
1129 
1130 static void send_http_error(struct mg_connection *, int, const char *,
1131  PRINTF_FORMAT_STRING(const char *fmt), ...)
1132 PRINTF_ARGS(4, 5);
1133 
1134 
1135 static void send_http_error(struct mg_connection *conn, int status,
1136  const char *reason, const char *fmt, ...)
1137 {
1138  char buf[MG_BUF_LEN];
1139  va_list ap;
1140  int len = 0;
1141  char date[64];
1142  time_t curtime = time(NULL);
1143 
1144  conn->status_code = status;
1145  if (conn->ctx->callbacks.http_error == NULL ||
1146  conn->ctx->callbacks.http_error(conn, status)) {
1147  buf[0] = '\0';
1148 
1149  gmt_time_string(date, sizeof(date), &curtime);
1150 
1151  /* Errors 1xx, 204 and 304 MUST NOT send a body */
1152  if (status > 199 && status != 204 && status != 304) {
1153  len = mg_snprintf(conn, buf, sizeof(buf), "Error %d: %s", status, reason);
1154  buf[len++] = '\n';
1155 
1156  va_start(ap, fmt);
1157  len += mg_vsnprintf(conn, buf + len, sizeof(buf) - len, fmt, ap);
1158  va_end(ap);
1159  }
1160  DEBUG_TRACE(("[%s]", buf));
1161 
1162  mg_printf(conn, "HTTP/1.1 %d %s\r\n"
1163  "Content-Length: %d\r\n"
1164  "Date: %s\r\n"
1165  "Connection: %s\r\n\r\n",
1166  status, reason, len, date,
1167  suggest_connection_header(conn));
1168  conn->num_bytes_sent += mg_printf(conn, "%s", buf);
1169  }
1170 }
1171 
1172 #if defined(_WIN32) && !defined(__SYMBIAN32__)
1173 static int pthread_mutex_init(pthread_mutex_t *mutex, void *unused)
1174 {
1175  (void) unused;
1176  *mutex = CreateMutex(NULL, FALSE, NULL);
1177  return *mutex == NULL ? -1 : 0;
1178 }
1179 
1180 static int pthread_mutex_destroy(pthread_mutex_t *mutex)
1181 {
1182  return CloseHandle(*mutex) == 0 ? -1 : 0;
1183 }
1184 
1185 static int pthread_mutex_lock(pthread_mutex_t *mutex)
1186 {
1187  return WaitForSingleObject(*mutex, INFINITE) == WAIT_OBJECT_0? 0 : -1;
1188 }
1189 
1190 static int pthread_mutex_unlock(pthread_mutex_t *mutex)
1191 {
1192  return ReleaseMutex(*mutex) == 0 ? -1 : 0;
1193 }
1194 
1195 static int clock_gettime(clockid_t clk_id, struct timespec *tp)
1196 {
1197  FILETIME ft;
1198  ULARGE_INTEGER li;
1199  BOOL ok = FALSE;
1200  double d;
1201  static double perfcnt_per_sec = 0.0;
1202 
1203  if (tp) {
1204  if (clk_id == CLOCK_REALTIME) {
1205  GetSystemTimeAsFileTime(&ft);
1206  li.LowPart = ft.dwLowDateTime;
1207  li.HighPart = ft.dwHighDateTime;
1208  li.QuadPart -= 116444736000000000; /* 1.1.1970 in filedate */
1209  tp->tv_sec = (time_t)(li.QuadPart / 10000000);
1210  tp->tv_nsec = (long)(li.QuadPart % 10000000) * 100;
1211  ok = TRUE;
1212  } else if (clk_id == CLOCK_MONOTONIC) {
1213  if (perfcnt_per_sec==0) {
1214  QueryPerformanceFrequency((LARGE_INTEGER *) &li);
1215  perfcnt_per_sec = 1.0 / li.QuadPart;
1216  }
1217  if (perfcnt_per_sec!=0) {
1218  QueryPerformanceCounter((LARGE_INTEGER *) &li);
1219  d = li.QuadPart * perfcnt_per_sec;
1220  tp->tv_sec = (time_t)d;
1221  d -= tp->tv_sec;
1222  tp->tv_nsec = (long)(d*1.0E9);
1223  ok = TRUE;
1224  }
1225  }
1226  }
1227 
1228  return ok ? 0 : -1;
1229 }
1230 
1231 static int pthread_cond_init(pthread_cond_t *cv, const void *unused)
1232 {
1233  (void) unused;
1234  InitializeCriticalSection(&cv->threadIdSec);
1235  cv->waitingthreadcount = 0;
1236  cv->waitingthreadhdls = (pthread_t*) calloc(MAX_WORKER_THREADS, sizeof(pthread_t));
1237  return (cv->waitingthreadhdls!=NULL) ? 0 : -1;
1238 }
1239 
1240 static int pthread_cond_timedwait(pthread_cond_t *cv, pthread_mutex_t *mutex, const struct timespec * abstime)
1241 {
1242  struct mg_workerTLS * tls = (struct mg_workerTLS *)TlsGetValue(sTlsKey);
1243  int ok;
1244  struct timespec tsnow;
1245  int64_t nsnow, nswaitabs, nswaitrel;
1246  DWORD mswaitrel;
1247 
1248  EnterCriticalSection(&cv->threadIdSec);
1249  assert(cv->waitingthreadcount < MAX_WORKER_THREADS);
1250  cv->waitingthreadhdls[cv->waitingthreadcount] = tls->pthread_cond_helper_mutex;
1251  cv->waitingthreadcount++;
1252  LeaveCriticalSection(&cv->threadIdSec);
1253 
1254  if (abstime) {
1255  clock_gettime(CLOCK_REALTIME, &tsnow);
1256  nsnow = (((uint64_t)tsnow.tv_sec)<<32) + tsnow.tv_nsec;
1257  nswaitabs = (((uint64_t)abstime->tv_sec)<<32) + abstime->tv_nsec;
1258  nswaitrel = nswaitabs - nsnow;
1259  if (nswaitrel<0) nswaitrel=0;
1260  mswaitrel = (DWORD)(nswaitrel / 1000000);
1261  } else {
1262  mswaitrel = INFINITE;
1263  }
1264 
1265  pthread_mutex_unlock(mutex);
1266  ok = (WAIT_OBJECT_0 == WaitForSingleObject(tls->pthread_cond_helper_mutex, mswaitrel));
1267  pthread_mutex_lock(mutex);
1268 
1269  return ok ? 0 : -1;
1270 }
1271 
1272 static int pthread_cond_wait(pthread_cond_t *cv, pthread_mutex_t *mutex)
1273 {
1274  return pthread_cond_timedwait(cv, mutex, NULL);
1275 }
1276 
1277 static int pthread_cond_signal(pthread_cond_t *cv)
1278 {
1279  int i;
1280  HANDLE wkup = NULL;
1281  BOOL ok = FALSE;
1282 
1283  EnterCriticalSection(&cv->threadIdSec);
1284  if (cv->waitingthreadcount) {
1285  wkup = cv->waitingthreadhdls[0];
1286  ok = SetEvent(wkup);
1287 
1288  for (i=1; i<cv->waitingthreadcount; i++) {
1289  cv->waitingthreadhdls[i-1] = cv->waitingthreadhdls[i];
1290  }
1291  cv->waitingthreadcount--;
1292 
1293  assert(ok);
1294  }
1295  LeaveCriticalSection(&cv->threadIdSec);
1296 
1297  return ok ? 0 : 1;
1298 }
1299 
1300 static int pthread_cond_broadcast(pthread_cond_t *cv)
1301 {
1302  EnterCriticalSection(&cv->threadIdSec);
1303  while (cv->waitingthreadcount) {
1304  pthread_cond_signal(cv);
1305  }
1306  LeaveCriticalSection(&cv->threadIdSec);
1307 
1308  return 0;
1309 }
1310 
1311 static int pthread_cond_destroy(pthread_cond_t *cv)
1312 {
1313  EnterCriticalSection(&cv->threadIdSec);
1314  assert(cv->waitingthreadcount==0);
1315  cv->waitingthreadhdls = 0;
1316  free(cv->waitingthreadhdls);
1317  LeaveCriticalSection(&cv->threadIdSec);
1318  DeleteCriticalSection(&cv->threadIdSec);
1319 
1320  return 0;
1321 }
1322 
1323 /* For Windows, change all slashes to backslashes in path names. */
1324 static void change_slashes_to_backslashes(char *path)
1325 {
1326  int i;
1327 
1328  for (i = 0; path[i] != '\0'; i++) {
1329  if (path[i] == '/')
1330  path[i] = '\\';
1331  /* i > 0 check is to preserve UNC paths, like \\server\file.txt */
1332  if (path[i] == '\\' && i > 0)
1333  while (path[i + 1] == '\\' || path[i + 1] == '/')
1334  (void) memmove(path + i + 1,
1335  path + i + 2, strlen(path + i + 1));
1336  }
1337 }
1338 
1339 /* Encode 'path' which is assumed UTF-8 string, into UNICODE string.
1340  wbuf and wbuf_len is a target buffer and its length. */
1341 static void to_unicode(const char *path, wchar_t *wbuf, size_t wbuf_len)
1342 {
1343  char buf[PATH_MAX], buf2[PATH_MAX];
1344 
1345  mg_strlcpy(buf, path, sizeof(buf));
1346  change_slashes_to_backslashes(buf);
1347 
1348  /* Convert to Unicode and back. If doubly-converted string does not
1349  match the original, something is fishy, reject. */
1350  memset(wbuf, 0, wbuf_len * sizeof(wchar_t));
1351  MultiByteToWideChar(CP_UTF8, 0, buf, -1, wbuf, (int) wbuf_len);
1352  WideCharToMultiByte(CP_UTF8, 0, wbuf, (int) wbuf_len, buf2, sizeof(buf2),
1353  NULL, NULL);
1354  if (strcmp(buf, buf2) != 0) {
1355  wbuf[0] = L'\0';
1356  }
1357 }
1358 
1359 #if defined(_WIN32_WCE)
1360 static time_t time(time_t *ptime)
1361 {
1362  time_t t;
1363  SYSTEMTIME st;
1364  FILETIME ft;
1365 
1366  GetSystemTime(&st);
1367  SystemTimeToFileTime(&st, &ft);
1368  t = SYS2UNIX_TIME(ft.dwLowDateTime, ft.dwHighDateTime);
1369 
1370  if (ptime != NULL) {
1371  *ptime = t;
1372  }
1373 
1374  return t;
1375 }
1376 
1377 static struct tm *localtime(const time_t *ptime, struct tm *ptm)
1378 {
1379  int64_t t = ((int64_t) *ptime) * RATE_DIFF + EPOCH_DIFF;
1380  FILETIME ft, lft;
1381  SYSTEMTIME st;
1382  TIME_ZONE_INFORMATION tzinfo;
1383 
1384  if (ptm == NULL) {
1385  return NULL;
1386  }
1387 
1388  * (int64_t *) &ft = t;
1389  FileTimeToLocalFileTime(&ft, &lft);
1390  FileTimeToSystemTime(&lft, &st);
1391  ptm->tm_year = st.wYear - 1900;
1392  ptm->tm_mon = st.wMonth - 1;
1393  ptm->tm_wday = st.wDayOfWeek;
1394  ptm->tm_mday = st.wDay;
1395  ptm->tm_hour = st.wHour;
1396  ptm->tm_min = st.wMinute;
1397  ptm->tm_sec = st.wSecond;
1398  ptm->tm_yday = 0; /* hope nobody uses this */
1399  ptm->tm_isdst =
1400  GetTimeZoneInformation(&tzinfo) == TIME_ZONE_ID_DAYLIGHT ? 1 : 0;
1401 
1402  return ptm;
1403 }
1404 
1405 static struct tm *gmtime(const time_t *ptime, struct tm *ptm)
1406 {
1407  /* FIXME(lsm): fix this. */
1408  return localtime(ptime, ptm);
1409 }
1410 
1411 static size_t strftime(char *dst, size_t dst_size, const char *fmt,
1412  const struct tm *tm)
1413 {
1414  (void) snprintf(dst, dst_size, "implement strftime() for WinCE");
1415  return 0;
1416 }
1417 #endif
1418 
1419 /* Windows happily opens files with some garbage at the end of file name.
1420  For example, fopen("a.cgi ", "r") on Windows successfully opens
1421  "a.cgi", despite one would expect an error back.
1422  This function returns non-0 if path ends with some garbage. */
1423 static int path_cannot_disclose_cgi(const char *path)
1424 {
1425  static const char *allowed_last_characters = "_-";
1426  int last = path[strlen(path) - 1];
1427  return isalnum(last) || strchr(allowed_last_characters, last) != NULL;
1428 }
1429 
1430 static int mg_stat(struct mg_connection *conn, const char *path,
1431  struct file *filep)
1432 {
1433  wchar_t wbuf[PATH_MAX];
1434  WIN32_FILE_ATTRIBUTE_DATA info;
1435 
1436  if (!is_file_in_memory(conn, path, filep)) {
1437  to_unicode(path, wbuf, ARRAY_SIZE(wbuf));
1438  if (GetFileAttributesExW(wbuf, GetFileExInfoStandard, &info) != 0) {
1439  filep->size = MAKEUQUAD(info.nFileSizeLow, info.nFileSizeHigh);
1440  filep->modification_time = SYS2UNIX_TIME(
1441  info.ftLastWriteTime.dwLowDateTime,
1442  info.ftLastWriteTime.dwHighDateTime);
1443  filep->is_directory = info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
1444  /* If file name is fishy, reset the file structure and return
1445  error.
1446  Note it is important to reset, not just return the error, cause
1447  functions like is_file_opened() check the struct. */
1448  if (!filep->is_directory && !path_cannot_disclose_cgi(path)) {
1449  memset(filep, 0, sizeof(*filep));
1450  }
1451  }
1452  }
1453 
1454  return filep->membuf != NULL || filep->modification_time != 0;
1455 }
1456 
1457 static int mg_remove(const char *path)
1458 {
1459  wchar_t wbuf[PATH_MAX];
1460  to_unicode(path, wbuf, ARRAY_SIZE(wbuf));
1461  return DeleteFileW(wbuf) ? 0 : -1;
1462 }
1463 
1464 static int mg_mkdir(const char *path, int mode)
1465 {
1466  char buf[PATH_MAX];
1467  wchar_t wbuf[PATH_MAX];
1468 
1469  (void) mode;
1470  mg_strlcpy(buf, path, sizeof(buf));
1471  change_slashes_to_backslashes(buf);
1472 
1473  (void) MultiByteToWideChar(CP_UTF8, 0, buf, -1, wbuf, ARRAY_SIZE(wbuf));
1474 
1475  return CreateDirectoryW(wbuf, NULL) ? 0 : -1;
1476 }
1477 
1478 /* Implementation of POSIX opendir/closedir/readdir for Windows. */
1479 static DIR * opendir(const char *name)
1480 {
1481  DIR *dir = NULL;
1482  wchar_t wpath[PATH_MAX];
1483  DWORD attrs;
1484 
1485  if (name == NULL) {
1486  SetLastError(ERROR_BAD_ARGUMENTS);
1487  } else if ((dir = (DIR *) malloc(sizeof(*dir))) == NULL) {
1488  SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1489  } else {
1490  to_unicode(name, wpath, ARRAY_SIZE(wpath));
1491  attrs = GetFileAttributesW(wpath);
1492  if (attrs != 0xFFFFFFFF &&
1493  ((attrs & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY)) {
1494  (void) wcscat(wpath, L"\\*");
1495  dir->handle = FindFirstFileW(wpath, &dir->info);
1496  dir->result.d_name[0] = '\0';
1497  } else {
1498  free(dir);
1499  dir = NULL;
1500  }
1501  }
1502 
1503  return dir;
1504 }
1505 
1506 static int closedir(DIR *dir)
1507 {
1508  int result = 0;
1509 
1510  if (dir != NULL) {
1511  if (dir->handle != INVALID_HANDLE_VALUE)
1512  result = FindClose(dir->handle) ? 0 : -1;
1513 
1514  free(dir);
1515  } else {
1516  result = -1;
1517  SetLastError(ERROR_BAD_ARGUMENTS);
1518  }
1519 
1520  return result;
1521 }
1522 
1523 static struct dirent *readdir(DIR *dir)
1524 {
1525  struct dirent *result = 0;
1526 
1527  if (dir) {
1528  if (dir->handle != INVALID_HANDLE_VALUE) {
1529  result = &dir->result;
1530  (void) WideCharToMultiByte(CP_UTF8, 0,
1531  dir->info.cFileName, -1, result->d_name,
1532  sizeof(result->d_name), NULL, NULL);
1533 
1534  if (!FindNextFileW(dir->handle, &dir->info)) {
1535  (void) FindClose(dir->handle);
1536  dir->handle = INVALID_HANDLE_VALUE;
1537  }
1538 
1539  } else {
1540  SetLastError(ERROR_FILE_NOT_FOUND);
1541  }
1542  } else {
1543  SetLastError(ERROR_BAD_ARGUMENTS);
1544  }
1545 
1546  return result;
1547 }
1548 
1549 #ifndef HAVE_POLL
1550 static int poll(struct pollfd *pfd, int n, int milliseconds)
1551 {
1552  struct timeval tv;
1553  fd_set set;
1554  int i, result;
1555  SOCKET maxfd = 0;
1556 
1557  tv.tv_sec = milliseconds / 1000;
1558  tv.tv_usec = (milliseconds % 1000) * 1000;
1559  FD_ZERO(&set);
1560 
1561  for (i = 0; i < n; i++) {
1562  FD_SET((SOCKET) pfd[i].fd, &set);
1563  pfd[i].revents = 0;
1564 
1565  if (pfd[i].fd > maxfd) {
1566  maxfd = pfd[i].fd;
1567  }
1568  }
1569 
1570  if ((result = select((int)maxfd + 1, &set, NULL, NULL, &tv)) > 0) {
1571  for (i = 0; i < n; i++) {
1572  if (FD_ISSET(pfd[i].fd, &set)) {
1573  pfd[i].revents = POLLIN;
1574  }
1575  }
1576  }
1577 
1578  return result;
1579 }
1580 #endif /* HAVE_POLL */
1581 
1582 static void set_close_on_exec(SOCKET sock, struct mg_connection *conn /* may be null */)
1583 {
1584  (void) conn; /* Unused. */
1585  (void) SetHandleInformation((HANDLE) sock, HANDLE_FLAG_INHERIT, 0);
1586 }
1587 
1588 int mg_start_thread(mg_thread_func_t f, void *p)
1589 {
1590 #if defined(USE_STACK_SIZE) && (USE_STACK_SIZE > 1)
1591  /* Compile-time option to control stack size, e.g. -DUSE_STACK_SIZE=16384 */
1592  return (long)_beginthread((void (__cdecl *)(void *)) f, USE_STACK_SIZE, p) == -1L ? -1 : 0;
1593 #else
1594  return (long)_beginthread((void (__cdecl *)(void *)) f, 0, p) == -1L ? -1 : 0;
1595 #endif /* defined(USE_STACK_SIZE) && (USE_STACK_SIZE > 1) */
1596 }
1597 
1598 /* Start a thread storing the thread context. */
1599 
1600 static int mg_start_thread_with_id(unsigned (__stdcall *f)(void *), void *p,
1601  pthread_t *threadidptr)
1602 {
1603  uintptr_t uip;
1604  HANDLE threadhandle;
1605  int result;
1606 
1607  uip = _beginthreadex(NULL, 0, (unsigned (__stdcall *)(void *)) f, p, 0,
1608  NULL);
1609  threadhandle = (HANDLE) uip;
1610  if (threadidptr != NULL) {
1611  *threadidptr = threadhandle;
1612  }
1613  result = (threadhandle == NULL) ? -1 : 0;
1614 
1615  return result;
1616 }
1617 
1618 /* Wait for a thread to finish. */
1619 
1620 static int mg_join_thread(pthread_t threadid)
1621 {
1622  int result;
1623  DWORD dwevent;
1624 
1625  result = -1;
1626  dwevent = WaitForSingleObject(threadid, INFINITE);
1627  if (dwevent == WAIT_FAILED) {
1628  int err;
1629 
1630  err = GetLastError();
1631  DEBUG_TRACE(("WaitForSingleObject() failed, error %d", err));
1632  } else {
1633  if (dwevent == WAIT_OBJECT_0) {
1634  CloseHandle(threadid);
1635  result = 0;
1636  }
1637  }
1638 
1639  return result;
1640 }
1641 
1642 static HANDLE dlopen(const char *dll_name, int flags)
1643 {
1644  wchar_t wbuf[PATH_MAX];
1645  (void) flags;
1646  to_unicode(dll_name, wbuf, ARRAY_SIZE(wbuf));
1647  return LoadLibraryW(wbuf);
1648 }
1649 
1650 static int dlclose(void *handle)
1651 {
1652  int result;
1653 
1654  if (FreeLibrary((HMODULE) handle) != 0) {
1655  result = 0;
1656  } else {
1657  result = -1;
1658  }
1659 
1660  return result;
1661 }
1662 
1663 #if !defined(NO_CGI)
1664 #define SIGKILL 0
1665 static int kill(pid_t pid, int sig_num)
1666 {
1667  (void) TerminateProcess(pid, sig_num);
1668  (void) CloseHandle(pid);
1669  return 0;
1670 }
1671 
1672 static void trim_trailing_whitespaces(char *s)
1673 {
1674  char *e = s + strlen(s) - 1;
1675  while (e > s && isspace(* (unsigned char *) e)) {
1676  *e-- = '\0';
1677  }
1678 }
1679 
1680 static pid_t spawn_process(struct mg_connection *conn, const char *prog,
1681  char *envblk, char *envp[], int fdin,
1682  int fdout, const char *dir)
1683 {
1684  HANDLE me;
1685  char *p, *interp, full_interp[PATH_MAX], full_dir[PATH_MAX],
1686  cmdline[PATH_MAX], buf[PATH_MAX];
1687  struct file file = STRUCT_FILE_INITIALIZER;
1688  STARTUPINFOA si;
1689  PROCESS_INFORMATION pi = { 0 };
1690 
1691  (void) envp;
1692 
1693  memset(&si, 0, sizeof(si));
1694  si.cb = sizeof(si);
1695 
1696  /* TODO(lsm): redirect CGI errors to the error log file */
1697  si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
1698  si.wShowWindow = SW_HIDE;
1699 
1700  me = GetCurrentProcess();
1701  DuplicateHandle(me, (HANDLE) _get_osfhandle(fdin), me,
1702  &si.hStdInput, 0, TRUE, DUPLICATE_SAME_ACCESS);
1703  DuplicateHandle(me, (HANDLE) _get_osfhandle(fdout), me,
1704  &si.hStdOutput, 0, TRUE, DUPLICATE_SAME_ACCESS);
1705 
1706  /* If CGI file is a script, try to read the interpreter line */
1707  interp = conn->ctx->config[CGI_INTERPRETER];
1708  if (interp == NULL) {
1709  buf[0] = buf[1] = '\0';
1710 
1711  /* Read the first line of the script into the buffer */
1712  snprintf(cmdline, sizeof(cmdline), "%s%c%s", dir, '/', prog);
1713  if (mg_fopen(conn, cmdline, "r", &file)) {
1714  p = (char *) file.membuf;
1715  mg_fgets(buf, sizeof(buf), &file, &p);
1716  mg_fclose(&file);
1717  buf[sizeof(buf) - 1] = '\0';
1718  }
1719 
1720  if (buf[0] == '#' && buf[1] == '!') {
1721  trim_trailing_whitespaces(buf + 2);
1722  } else {
1723  buf[2] = '\0';
1724  }
1725  interp = buf + 2;
1726  }
1727 
1728  if (interp[0] != '\0') {
1729  GetFullPathNameA(interp, sizeof(full_interp), full_interp, NULL);
1730  interp = full_interp;
1731  }
1732  GetFullPathNameA(dir, sizeof(full_dir), full_dir, NULL);
1733 
1734  mg_snprintf(conn, cmdline, sizeof(cmdline), "%s%s\"%s\\%s\"",
1735  interp, interp[0] == '\0' ? "" : " ", full_dir, prog);
1736 
1737  DEBUG_TRACE(("Running [%s]", cmdline));
1738  if (CreateProcessA(NULL, cmdline, NULL, NULL, TRUE,
1739  CREATE_NEW_PROCESS_GROUP, envblk, NULL, &si, &pi) == 0) {
1740  mg_cry(conn, "%s: CreateProcess(%s): %ld",
1741  __func__, cmdline, ERRNO);
1742  pi.hProcess = (pid_t) -1;
1743  }
1744 
1745  (void) CloseHandle(si.hStdOutput);
1746  (void) CloseHandle(si.hStdInput);
1747  if (pi.hThread != NULL)
1748  (void) CloseHandle(pi.hThread);
1749 
1750  return (pid_t) pi.hProcess;
1751 }
1752 #endif /* !NO_CGI */
1753 
1754 static int set_non_blocking_mode(SOCKET sock)
1755 {
1756  unsigned long on = 1;
1757  return ioctlsocket(sock, FIONBIO, &on);
1758 }
1759 
1760 #else
1761 static int mg_stat(struct mg_connection *conn, const char *path,
1762  struct file *filep)
1763 {
1764  struct stat st;
1765 
1766  if (!is_file_in_memory(conn, path, filep) && !stat(path, &st)) {
1767  filep->size = st.st_size;
1768  filep->modification_time = st.st_mtime;
1769  filep->is_directory = S_ISDIR(st.st_mode);
1770  } else {
1771  filep->modification_time = (time_t) 0;
1772  }
1773 
1774  return filep->membuf != NULL || filep->modification_time != (time_t) 0;
1775 }
1776 
1777 static void set_close_on_exec(int fd, struct mg_connection *conn /* may be null */)
1778 {
1779  if (fcntl(fd, F_SETFD, FD_CLOEXEC) != 0) {
1780  if (conn)
1781  mg_cry(conn, "%s: fcntl(F_SETFD FD_CLOEXEC) failed: %s",
1782  __func__, strerror(ERRNO));
1783  }
1784 }
1785 
1786 int mg_start_thread(mg_thread_func_t func, void *param)
1787 {
1788  pthread_t thread_id;
1789  pthread_attr_t attr;
1790  int result;
1791 
1792  (void) pthread_attr_init(&attr);
1793  (void) pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
1794 
1795 #if defined(USE_STACK_SIZE) && (USE_STACK_SIZE > 1)
1796  /* Compile-time option to control stack size,
1797  e.g. -DUSE_STACK_SIZE=16384 */
1798  (void) pthread_attr_setstacksize(&attr, USE_STACK_SIZE);
1799 #endif /* defined(USE_STACK_SIZE) && (USE_STACK_SIZE > 1) */
1800 
1801  result = pthread_create(&thread_id, &attr, func, param);
1802  pthread_attr_destroy(&attr);
1803 
1804  return result;
1805 }
1806 
1807 /* Start a thread storing the thread context. */
1808 
1809 static int mg_start_thread_with_id(mg_thread_func_t func, void *param,
1810  pthread_t *threadidptr)
1811 {
1812  pthread_t thread_id;
1813  pthread_attr_t attr;
1814  int result;
1815 
1816  (void) pthread_attr_init(&attr);
1817 
1818 #if defined(USE_STACK_SIZE) && (USE_STACK_SIZE > 1)
1819  /* Compile-time option to control stack size,
1820  e.g. -DUSE_STACK_SIZE=16384 */
1821  (void) pthread_attr_setstacksize(&attr, USE_STACK_SIZE);
1822 #endif /* defined(USE_STACK_SIZE) && USE_STACK_SIZE > 1 */
1823 
1824  result = pthread_create(&thread_id, &attr, func, param);
1825  pthread_attr_destroy(&attr);
1826  if (threadidptr != NULL) {
1827  *threadidptr = thread_id;
1828  }
1829  return result;
1830 }
1831 
1832 /* Wait for a thread to finish. */
1833 
1834 static int mg_join_thread(pthread_t threadid)
1835 {
1836  int result;
1837 
1838  result = pthread_join(threadid, NULL);
1839  return result;
1840 }
1841 
1842 #ifndef NO_CGI
1843 static pid_t spawn_process(struct mg_connection *conn, const char *prog,
1844  char *envblk, char *envp[], int fdin,
1845  int fdout, const char *dir)
1846 {
1847  pid_t pid;
1848  const char *interp;
1849 
1850  (void) envblk;
1851 
1852  if ((pid = fork()) == -1) {
1853  /* Parent */
1854  send_http_error(conn, 500, http_500_error, "fork(): %s", strerror(ERRNO));
1855  } else if (pid == 0) {
1856  /* Child */
1857  if (chdir(dir) != 0) {
1858  mg_cry(conn, "%s: chdir(%s): %s", __func__, dir, strerror(ERRNO));
1859  } else if (dup2(fdin, 0) == -1) {
1860  mg_cry(conn, "%s: dup2(%d, 0): %s", __func__, fdin, strerror(ERRNO));
1861  } else if (dup2(fdout, 1) == -1) {
1862  mg_cry(conn, "%s: dup2(%d, 1): %s", __func__, fdout, strerror(ERRNO));
1863  } else {
1864  /* Not redirecting stderr to stdout, to avoid output being littered
1865  with the error messages. */
1866  (void) close(fdin);
1867  (void) close(fdout);
1868 
1869  /* After exec, all signal handlers are restored to their default
1870  values, with one exception of SIGCHLD. According to
1871  POSIX.1-2001 and Linux's implementation, SIGCHLD's handler will
1872  leave unchanged after exec if it was set to be ignored. Restore
1873  it to default action. */
1874  signal(SIGCHLD, SIG_DFL);
1875 
1876  interp = conn->ctx->config[CGI_INTERPRETER];
1877  if (interp == NULL) {
1878  (void) execle(prog, prog, NULL, envp);
1879  mg_cry(conn, "%s: execle(%s): %s", __func__, prog, strerror(ERRNO));
1880  } else {
1881  (void) execle(interp, interp, prog, NULL, envp);
1882  mg_cry(conn, "%s: execle(%s %s): %s", __func__, interp, prog,
1883  strerror(ERRNO));
1884  }
1885  }
1886  exit(EXIT_FAILURE);
1887  }
1888 
1889  return pid;
1890 }
1891 #endif /* !NO_CGI */
1892 
1893 static int set_non_blocking_mode(SOCKET sock)
1894 {
1895  int flags;
1896 
1897  flags = fcntl(sock, F_GETFL, 0);
1898  (void) fcntl(sock, F_SETFL, flags | O_NONBLOCK);
1899 
1900  return 0;
1901 }
1902 #endif /* _WIN32 */
1903 
1904 /* Write data to the IO channel - opened file descriptor, socket or SSL
1905  descriptor. Return number of bytes written. */
1906 static int64_t push(FILE *fp, SOCKET sock, SSL *ssl, const char *buf,
1907  int64_t len)
1908 {
1909  int64_t sent;
1910  int n, k;
1911 
1912  (void) ssl; /* Get rid of warning */
1913  sent = 0;
1914  while (sent < len) {
1915 
1916  /* How many bytes we send in this iteration */
1917  k = len - sent > INT_MAX ? INT_MAX : (int) (len - sent);
1918 
1919 #ifndef NO_SSL
1920  if (ssl != NULL) {
1921  n = SSL_write(ssl, buf + sent, k);
1922  } else
1923 #endif
1924  if (fp != NULL) {
1925  n = (int) fwrite(buf + sent, 1, (size_t) k, fp);
1926  if (ferror(fp))
1927  n = -1;
1928  } else {
1929  n = send(sock, buf + sent, (size_t) k, MSG_NOSIGNAL);
1930  }
1931 
1932  if (n <= 0)
1933  break;
1934 
1935  sent += n;
1936  }
1937 
1938  return sent;
1939 }
1940 
1941 /* Read from IO channel - opened file descriptor, socket, or SSL descriptor.
1942  Return negative value on error, or number of bytes read on success. */
1943 static int pull(FILE *fp, struct mg_connection *conn, char *buf, int len)
1944 {
1945  int nread;
1946 
1947  if (fp != NULL) {
1948  /* Use read() instead of fread(), because if we're reading from the
1949  CGI pipe, fread() may block until IO buffer is filled up. We cannot
1950  afford to block and must pass all read bytes immediately to the
1951  client. */
1952  nread = read(fileno(fp), buf, (size_t) len);
1953 #ifndef NO_SSL
1954  } else if (conn->ssl != NULL) {
1955  nread = SSL_read(conn->ssl, buf, len);
1956 #endif
1957  } else {
1958  nread = recv(conn->client.sock, buf, (size_t) len, 0);
1959  }
1960 
1961  return conn->ctx->stop_flag ? -1 : nread;
1962 }
1963 
1964 static int pull_all(FILE *fp, struct mg_connection *conn, char *buf, int len)
1965 {
1966  int n, nread = 0;
1967 
1968  while (len > 0 && conn->ctx->stop_flag == 0) {
1969  n = pull(fp, conn, buf + nread, len);
1970  if (n < 0) {
1971  nread = n; /* Propagate the error */
1972  break;
1973  } else if (n == 0) {
1974  break; /* No more data to read */
1975  } else {
1976  conn->consumed_content += n;
1977  nread += n;
1978  len -= n;
1979  }
1980  }
1981 
1982  return nread;
1983 }
1984 
1985 int mg_read(struct mg_connection *conn, void *buf, size_t len)
1986 {
1987  int n, buffered_len, nread;
1988  const char *body;
1989 
1990  /* If Content-Length is not set, read until socket is closed */
1991  if (conn->consumed_content == 0 && conn->content_len == 0) {
1992  conn->content_len = INT64_MAX;
1993  conn->must_close = 1;
1994  }
1995 
1996  nread = 0;
1997  if (conn->consumed_content < conn->content_len) {
1998  /* Adjust number of bytes to read. */
1999  int64_t to_read = conn->content_len - conn->consumed_content;
2000  if (to_read < (int64_t) len) {
2001  len = (size_t) to_read;
2002  }
2003 
2004  /* Return buffered data */
2005  body = conn->buf + conn->request_len + conn->consumed_content;
2006  buffered_len = (int)(&conn->buf[conn->data_len] - body);
2007  if (buffered_len > 0) {
2008  if (len < (size_t) buffered_len) {
2009  buffered_len = (int) len;
2010  }
2011  memcpy(buf, body, (size_t) buffered_len);
2012  len -= buffered_len;
2013  conn->consumed_content += buffered_len;
2014  nread += buffered_len;
2015  buf = (char *) buf + buffered_len;
2016  }
2017 
2018  /* We have returned all buffered data. Read new data from the remote
2019  socket. */
2020  n = pull_all(NULL, conn, (char *) buf, (int) len);
2021  nread = n >= 0 ? nread + n : n;
2022  }
2023  return nread;
2024 }
2025 
2026 int mg_write(struct mg_connection *conn, const void *buf, size_t len)
2027 {
2028  time_t now;
2029  int64_t n, total, allowed;
2030 
2031  if (conn->throttle > 0) {
2032  if ((now = time(NULL)) != conn->last_throttle_time) {
2033  conn->last_throttle_time = now;
2034  conn->last_throttle_bytes = 0;
2035  }
2036  allowed = conn->throttle - conn->last_throttle_bytes;
2037  if (allowed > (int64_t) len) {
2038  allowed = len;
2039  }
2040  if ((total = push(NULL, conn->client.sock, conn->ssl, (const char *) buf,
2041  (int64_t) allowed)) == allowed) {
2042  buf = (char *) buf + total;
2043  conn->last_throttle_bytes += total;
2044  while (total < (int64_t) len && conn->ctx->stop_flag == 0) {
2045  allowed = conn->throttle > (int64_t) len - total ?
2046  (int64_t) len - total : conn->throttle;
2047  if ((n = push(NULL, conn->client.sock, conn->ssl, (const char *) buf,
2048  (int64_t) allowed)) != allowed) {
2049  break;
2050  }
2051  sleep(1);
2052  conn->last_throttle_bytes = allowed;
2053  conn->last_throttle_time = time(NULL);
2054  buf = (char *) buf + n;
2055  total += n;
2056  }
2057  }
2058  } else {
2059  total = push(NULL, conn->client.sock, conn->ssl, (const char *) buf,
2060  (int64_t) len);
2061  }
2062  return (int) total;
2063 }
2064 
2065 /* Alternative alloc_vprintf() for non-compliant C runtimes */
2066 static int alloc_vprintf2(char **buf, const char *fmt, va_list ap)
2067 {
2068  va_list ap_copy;
2069  int size = MG_BUF_LEN;
2070  int len = -1;
2071 
2072  *buf = NULL;
2073  while (len == -1) {
2074  if (*buf) free(*buf);
2075  *buf = (char *)malloc(size *= 4);
2076  if (!*buf) break;
2077  va_copy(ap_copy, ap);
2078  len = vsnprintf(*buf, size, fmt, ap_copy);
2079  va_end(ap_copy);
2080  }
2081 
2082  return len;
2083 }
2084 
2085 /* Print message to buffer. If buffer is large enough to hold the message,
2086  return buffer. If buffer is to small, allocate large enough buffer on heap,
2087  and return allocated buffer. */
2088 static int alloc_vprintf(char **buf, size_t size, const char *fmt, va_list ap)
2089 {
2090  va_list ap_copy;
2091  int len;
2092 
2093  /* Windows is not standard-compliant, and vsnprintf() returns -1 if
2094  buffer is too small. Also, older versions of msvcrt.dll do not have
2095  _vscprintf(). However, if size is 0, vsnprintf() behaves correctly.
2096  Therefore, we make two passes: on first pass, get required message
2097  length.
2098  On second pass, actually print the message. */
2099  va_copy(ap_copy, ap);
2100  len = vsnprintf(NULL, 0, fmt, ap_copy);
2101  va_end(ap_copy);
2102 
2103  if (len < 0) {
2104  /* C runtime is not standard compliant, vsnprintf() returned -1.
2105  Switch to alternative code path that uses incremental allocations.
2106  */
2107  va_copy(ap_copy, ap);
2108  len = alloc_vprintf2(buf, fmt, ap);
2109  va_end(ap_copy);
2110  } else if (len > (int) size &&
2111  (size = len + 1) > 0 &&
2112  (*buf = (char *) malloc(size)) == NULL) {
2113  len = -1; /* Allocation failed, mark failure */
2114  } else {
2115  va_copy(ap_copy, ap);
2116  IGNORE_UNUSED_RESULT(vsnprintf(*buf, size, fmt, ap_copy));
2117  va_end(ap_copy);
2118  }
2119 
2120  return len;
2121 }
2122 
2123 int mg_vprintf(struct mg_connection *conn, const char *fmt, va_list ap);
2124 
2125 int mg_vprintf(struct mg_connection *conn, const char *fmt, va_list ap)
2126 {
2127  char mem[MG_BUF_LEN], *buf = mem;
2128  int len;
2129 
2130  if ((len = alloc_vprintf(&buf, sizeof(mem), fmt, ap)) > 0) {
2131  len = mg_write(conn, buf, (size_t) len);
2132  }
2133  if (buf != mem && buf != NULL) {
2134  free(buf);
2135  }
2136 
2137  return len;
2138 }
2139 
2140 int mg_printf(struct mg_connection *conn, const char *fmt, ...)
2141 {
2142  va_list ap;
2143  int result;
2144 
2145  va_start(ap, fmt);
2146  result = mg_vprintf(conn, fmt, ap);
2147  va_end(ap);
2148 
2149  return result;
2150 }
2151 
2152 int mg_url_decode(const char *src, int src_len, char *dst,
2153  int dst_len, int is_form_url_encoded)
2154 {
2155  int i, j, a, b;
2156 #define HEXTOI(x) (isdigit(x) ? x - '0' : x - 'W')
2157 
2158  for (i = j = 0; i < src_len && j < dst_len - 1; i++, j++) {
2159  if (src[i] == '%' && i < src_len - 2 &&
2160  isxdigit(* (const unsigned char *) (src + i + 1)) &&
2161  isxdigit(* (const unsigned char *) (src + i + 2))) {
2162  a = tolower(* (const unsigned char *) (src + i + 1));
2163  b = tolower(* (const unsigned char *) (src + i + 2));
2164  dst[j] = (char) ((HEXTOI(a) << 4) | HEXTOI(b));
2165  i += 2;
2166  } else if (is_form_url_encoded && src[i] == '+') {
2167  dst[j] = ' ';
2168  } else {
2169  dst[j] = src[i];
2170  }
2171  }
2172 
2173  dst[j] = '\0'; /* Null-terminate the destination */
2174 
2175  return i >= src_len ? j : -1;
2176 }
2177 
2178 int mg_get_var(const char *data, size_t data_len, const char *name,
2179  char *dst, size_t dst_len)
2180 {
2181  return mg_get_var2(data,data_len,name,dst,dst_len,0);
2182 }
2183 
2184 int mg_get_var2(const char *data, size_t data_len, const char *name,
2185  char *dst, size_t dst_len, size_t occurrence)
2186 {
2187  const char *p, *e, *s;
2188  size_t name_len;
2189  int len;
2190 
2191  if (dst == NULL || dst_len == 0) {
2192  len = -2;
2193  } else if (data == NULL || name == NULL || data_len == 0) {
2194  len = -1;
2195  dst[0] = '\0';
2196  } else {
2197  name_len = strlen(name);
2198  e = data + data_len;
2199  len = -1;
2200  dst[0] = '\0';
2201 
2202  /* data is "var1=val1&var2=val2...". Find variable first */
2203  for (p = data; p + name_len < e; p++) {
2204  if ((p == data || p[-1] == '&') && p[name_len] == '=' &&
2205  !mg_strncasecmp(name, p, name_len) && 0 == occurrence--) {
2206 
2207  /* Point p to variable value */
2208  p += name_len + 1;
2209 
2210  /* Point s to the end of the value */
2211  s = (const char *) memchr(p, '&', (size_t)(e - p));
2212  if (s == NULL) {
2213  s = e;
2214  }
2215  assert(s >= p);
2216 
2217  /* Decode variable into destination buffer */
2218  len = mg_url_decode(p, (int)(s - p), dst, (int)dst_len, 1);
2219 
2220  /* Redirect error code from -1 to -2 (destination buffer too
2221  small). */
2222  if (len == -1) {
2223  len = -2;
2224  }
2225  break;
2226  }
2227  }
2228  }
2229 
2230  return len;
2231 }
2232 
2233 int mg_get_cookie(const char *cookie_header, const char *var_name,
2234  char *dst, size_t dst_size)
2235 {
2236  const char *s, *p, *end;
2237  int name_len, len = -1;
2238 
2239  if (dst == NULL || dst_size == 0) {
2240  len = -2;
2241  } else if (var_name == NULL || (s = cookie_header) == NULL) {
2242  len = -1;
2243  dst[0] = '\0';
2244  } else {
2245  name_len = (int) strlen(var_name);
2246  end = s + strlen(s);
2247  dst[0] = '\0';
2248 
2249  for (; (s = mg_strcasestr(s, var_name)) != NULL; s += name_len) {
2250  if (s[name_len] == '=') {
2251  s += name_len + 1;
2252  if ((p = strchr(s, ' ')) == NULL)
2253  p = end;
2254  if (p[-1] == ';')
2255  p--;
2256  if (*s == '"' && p[-1] == '"' && p > s + 1) {
2257  s++;
2258  p--;
2259  }
2260  if ((size_t) (p - s) < dst_size) {
2261  len = (int)(p - s);
2262  mg_strlcpy(dst, s, (size_t) len + 1);
2263  } else {
2264  len = -3;
2265  }
2266  break;
2267  }
2268  }
2269  }
2270  return len;
2271 }
2272 
2273 static void convert_uri_to_file_name(struct mg_connection *conn, char *buf,
2274  size_t buf_len, struct file *filep,
2275  int * is_script_ressource)
2276 {
2277  struct vec a, b;
2278  const char *rewrite, *uri = conn->request_info.uri,
2279  *root = conn->ctx->config[DOCUMENT_ROOT];
2280  char *p;
2281  int match_len;
2282  char gz_path[PATH_MAX];
2283  char const* accept_encoding;
2284 
2285  *is_script_ressource = 0;
2286 
2287 #if defined(USE_WEBSOCKET)
2288  if (is_websocket_request(conn) && conn->ctx->config[WEBSOCKET_ROOT]) {
2289  root = conn->ctx->config[WEBSOCKET_ROOT];
2290  }
2291 #endif
2292 
2293  /* Using buf_len - 1 because memmove() for PATH_INFO may shift part
2294  of the path one byte on the right.
2295  If document_root is NULL, leave the file empty. */
2296  mg_snprintf(conn, buf, buf_len - 1, "%s%s",
2297  root == NULL ? "" : root,
2298  root == NULL ? "" : uri);
2299 
2300  rewrite = conn->ctx->config[REWRITE];
2301  while ((rewrite = next_option(rewrite, &a, &b)) != NULL) {
2302  if ((match_len = match_prefix(a.ptr, (int) a.len, uri)) > 0) {
2303  mg_snprintf(conn, buf, buf_len - 1, "%.*s%s", (int) b.len, b.ptr,
2304  uri + match_len);
2305  break;
2306  }
2307  }
2308 
2309  if (mg_stat(conn, buf, filep)) return;
2310 
2311  /* if we can't find the actual file, look for the file
2312  with the same name but a .gz extension. If we find it,
2313  use that and set the gzipped flag in the file struct
2314  to indicate that the response need to have the content-
2315  encoding: gzip header
2316  we can only do this if the browser declares support */
2317  if ((accept_encoding = mg_get_header(conn, "Accept-Encoding")) != NULL) {
2318  if (strstr(accept_encoding,"gzip") != NULL) {
2319  snprintf(gz_path, sizeof(gz_path), "%s.gz", buf);
2320  if (mg_stat(conn, gz_path, filep)) {
2321  filep->gzipped = 1;
2322  return;
2323  }
2324  }
2325  }
2326 
2327  /* Support PATH_INFO for CGI scripts. */
2328  for (p = buf + strlen(buf); p > buf + 1; p--) {
2329  if (*p == '/') {
2330  *p = '\0';
2331  if ((match_prefix(conn->ctx->config[CGI_EXTENSIONS],
2332  (int)strlen(conn->ctx->config[CGI_EXTENSIONS]), buf) > 0
2333 #ifdef USE_LUA
2334  ||
2335  match_prefix(conn->ctx->config[LUA_SCRIPT_EXTENSIONS],
2336  (int)strlen(conn->ctx->config[LUA_SCRIPT_EXTENSIONS]), buf) > 0
2337 #endif
2338  ) && mg_stat(conn, buf, filep)) {
2339  /* Shift PATH_INFO block one character right, e.g.
2340  "/x.cgi/foo/bar\x00" => "/x.cgi\x00/foo/bar\x00"
2341  conn->path_info is pointing to the local variable "path"
2342  declared in handle_request(), so PATH_INFO is not valid
2343  after handle_request returns. */
2344  conn->path_info = p + 1;
2345  memmove(p + 2, p + 1, strlen(p + 1) + 1); /* +1 is for
2346  trailing \0 */
2347  p[1] = '/';
2348  *is_script_ressource = 1;
2349  break;
2350  } else {
2351  *p = '/';
2352  }
2353  }
2354  }
2355 }
2356 
2357 /* Check whether full request is buffered. Return:
2358  -1 if request is malformed
2359  0 if request is not yet fully buffered
2360  >0 actual request length, including last \r\n\r\n */
2361 static int get_request_len(const char *buf, int buflen)
2362 {
2363  const char *s, *e;
2364  int len = 0;
2365 
2366  for (s = buf, e = s + buflen - 1; len <= 0 && s < e; s++)
2367  /* Control characters are not allowed but >=128 is. */
2368  if (!isprint(* (const unsigned char *) s) && *s != '\r' &&
2369  *s != '\n' && * (const unsigned char *) s < 128) {
2370  len = -1;
2371  break; /* [i_a] abort scan as soon as one malformed character is
2372  found; */
2373  /* don't let subsequent \r\n\r\n win us over anyhow */
2374  } else if (s[0] == '\n' && s[1] == '\n') {
2375  len = (int) (s - buf) + 2;
2376  } else if (s[0] == '\n' && &s[1] < e &&
2377  s[1] == '\r' && s[2] == '\n') {
2378  len = (int) (s - buf) + 3;
2379  }
2380 
2381  return len;
2382 }
2383 
2384 /* Convert month to the month number. Return -1 on error, or month number */
2385 static int get_month_index(const char *s)
2386 {
2387  size_t i;
2388 
2389  for (i = 0; i < ARRAY_SIZE(month_names); i++)
2390  if (!strcmp(s, month_names[i]))
2391  return (int) i;
2392 
2393  return -1;
2394 }
2395 
2396 static int num_leap_years(int year)
2397 {
2398  return year / 4 - year / 100 + year / 400;
2399 }
2400 
2401 /* Parse UTC date-time string, and return the corresponding time_t value. */
2402 static time_t parse_date_string(const char *datetime)
2403 {
2404  static const unsigned short days_before_month[] = {
2405  0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
2406  };
2407  char month_str[32];
2408  int second, minute, hour, day, month, year, leap_days, days;
2409  time_t result = (time_t) 0;
2410 
2411  if (((sscanf(datetime, "%d/%3s/%d %d:%d:%d",
2412  &day, month_str, &year, &hour, &minute, &second) == 6) ||
2413  (sscanf(datetime, "%d %3s %d %d:%d:%d",
2414  &day, month_str, &year, &hour, &minute, &second) == 6) ||
2415  (sscanf(datetime, "%*3s, %d %3s %d %d:%d:%d",
2416  &day, month_str, &year, &hour, &minute, &second) == 6) ||
2417  (sscanf(datetime, "%d-%3s-%d %d:%d:%d",
2418  &day, month_str, &year, &hour, &minute, &second) == 6)) &&
2419  year > 1970 &&
2420  (month = get_month_index(month_str)) != -1) {
2421  leap_days = num_leap_years(year) - num_leap_years(1970);
2422  year -= 1970;
2423  days = year * 365 + days_before_month[month] + (day - 1) + leap_days;
2424  result = (time_t) days * 24 * 3600 + (time_t) hour * 3600 +
2425  minute * 60 + second;
2426  }
2427 
2428  return result;
2429 }
2430 
2431 /* Protect against directory disclosure attack by removing '..',
2432  excessive '/' and '\' characters */
2433 static void remove_double_dots_and_double_slashes(char *s)
2434 {
2435  char *p = s;
2436 
2437  while (*s != '\0') {
2438  *p++ = *s++;
2439  if (s[-1] == '/' || s[-1] == '\\') {
2440  /* Skip all following slashes, backslashes and double-dots */
2441  while (s[0] != '\0') {
2442  if (s[0] == '/' || s[0] == '\\') {
2443  s++;
2444  } else if (s[0] == '.' && s[1] == '.') {
2445  s += 2;
2446  } else {
2447  break;
2448  }
2449  }
2450  }
2451  }
2452  *p = '\0';
2453 }
2454 
2455 static const struct {
2456  const char *extension;
2457  size_t ext_len;
2458  const char *mime_type;
2459 } builtin_mime_types[] = {
2460  /* IANA registered MIME types (http://www.iana.org/assignments/media-types)
2461  application types */
2462  {".doc", 4, "application/msword"},
2463  {".eps", 4, "application/postscript"},
2464  {".exe", 4, "application/octet-stream"},
2465  {".js", 3, "application/javascript"},
2466  {".json", 5, "application/json"},
2467  {".pdf", 4, "application/pdf"},
2468  {".ps", 3, "application/postscript"},
2469  {".rtf", 4, "application/rtf"},
2470  {".xhtml", 6, "application/xhtml+xml"},
2471  {".xsl", 4, "application/xml"},
2472  {".xslt", 5, "application/xml"},
2473 
2474  /* audio */
2475  {".mp3", 4, "audio/mpeg"},
2476  {".oga", 4, "audio/ogg"},
2477  {".ogg", 4, "audio/ogg"},
2478 
2479  /* image */
2480  {".gif", 4, "image/gif"},
2481  {".ief", 4, "image/ief"},
2482  {".jpeg", 5, "image/jpeg"},
2483  {".jpg", 4, "image/jpeg"},
2484  {".jpm", 4, "image/jpm"},
2485  {".jpx", 4, "image/jpx"},
2486  {".png", 4, "image/png"},
2487  {".svg", 4, "image/svg+xml"},
2488  {".tif", 4, "image/tiff"},
2489  {".tiff", 5, "image/tiff"},
2490 
2491  /* model */
2492  {".wrl", 4, "model/vrml"},
2493 
2494  /* text */
2495  {".css", 4, "text/css"},
2496  {".csv", 4, "text/csv"},
2497  {".htm", 4, "text/html"},
2498  {".html", 5, "text/html"},
2499  {".sgm", 4, "text/sgml"},
2500  {".shtm", 5, "text/html"},
2501  {".shtml", 6, "text/html"},
2502  {".txt", 4, "text/plain"},
2503  {".xml", 4, "text/xml"},
2504 
2505  /* video */
2506  {".mov", 4, "video/quicktime"},
2507  {".mp4", 4, "video/mp4"},
2508  {".mpeg", 5, "video/mpeg"},
2509  {".mpg", 4, "video/mpeg"},
2510  {".ogv", 4, "video/ogg"},
2511  {".qt", 3, "video/quicktime"},
2512 
2513  /* not registered types
2514  (http://reference.sitepoint.com/html/mime-types-full,
2515  http://www.hansenb.pdx.edu/DMKB/dict/tutorials/mime_typ.php, ..) */
2516  {".arj", 4, "application/x-arj-compressed"},
2517  {".gz", 3, "application/x-gunzip"},
2518  {".rar", 4, "application/x-arj-compressed"},
2519  {".swf", 4, "application/x-shockwave-flash"},
2520  {".tar", 4, "application/x-tar"},
2521  {".tgz", 4, "application/x-tar-gz"},
2522  {".torrent", 8, "application/x-bittorrent"},
2523  {".ppt", 4, "application/x-mspowerpoint"},
2524  {".xls", 4, "application/x-msexcel"},
2525  {".zip", 4, "application/x-zip-compressed"},
2526  {".aac", 4, "audio/aac"}, /* http://en.wikipedia.org/wiki/Advanced_Audio_Coding */
2527  {".aif", 4, "audio/x-aif"},
2528  {".m3u", 4, "audio/x-mpegurl"},
2529  {".mid", 4, "audio/x-midi"},
2530  {".ra", 3, "audio/x-pn-realaudio"},
2531  {".ram", 4, "audio/x-pn-realaudio"},
2532  {".wav", 4, "audio/x-wav"},
2533  {".bmp", 4, "image/bmp"},
2534  {".ico", 4, "image/x-icon"},
2535  {".pct", 4, "image/x-pct"},
2536  {".pict", 5, "image/pict"},
2537  {".rgb", 4, "image/x-rgb"},
2538  {".webm", 5, "video/webm"}, /* http://en.wikipedia.org/wiki/WebM */
2539  {".asf", 4, "video/x-ms-asf"},
2540  {".avi", 4, "video/x-msvideo"},
2541  {".m4v", 4, "video/x-m4v"},
2542  {NULL, 0, NULL}
2543 };
2544 
2545 const char *mg_get_builtin_mime_type(const char *path)
2546 {
2547  const char *ext;
2548  size_t i, path_len;
2549 
2550  path_len = strlen(path);
2551 
2552  for (i = 0; builtin_mime_types[i].extension != NULL; i++) {
2553  ext = path + (path_len - builtin_mime_types[i].ext_len);
2554  if (path_len > builtin_mime_types[i].ext_len &&
2555  mg_strcasecmp(ext, builtin_mime_types[i].extension) == 0) {
2556  return builtin_mime_types[i].mime_type;
2557  }
2558  }
2559 
2560  return "text/plain";
2561 }
2562 
2563 /* Look at the "path" extension and figure what mime type it has.
2564  Store mime type in the vector. */
2565 static void get_mime_type(struct mg_context *ctx, const char *path,
2566  struct vec *vec)
2567 {
2568  struct vec ext_vec, mime_vec;
2569  const char *list, *ext;
2570  size_t path_len;
2571 
2572  path_len = strlen(path);
2573 
2574  /* Scan user-defined mime types first, in case user wants to
2575  override default mime types. */
2576  list = ctx->config[EXTRA_MIME_TYPES];
2577  while ((list = next_option(list, &ext_vec, &mime_vec)) != NULL) {
2578  /* ext now points to the path suffix */
2579  ext = path + path_len - ext_vec.len;
2580  if (mg_strncasecmp(ext, ext_vec.ptr, ext_vec.len) == 0) {
2581  *vec = mime_vec;
2582  return;
2583  }
2584  }
2585 
2586  vec->ptr = mg_get_builtin_mime_type(path);
2587  vec->len = strlen(vec->ptr);
2588 }
2589 
2590 /* Stringify binary data. Output buffer must be twice as big as input,
2591  because each byte takes 2 bytes in string representation */
2592 static void bin2str(char *to, const unsigned char *p, size_t len)
2593 {
2594  static const char *hex = "0123456789abcdef";
2595 
2596  for (; len--; p++) {
2597  *to++ = hex[p[0] >> 4];
2598  *to++ = hex[p[0] & 0x0f];
2599  }
2600  *to = '\0';
2601 }
2602 
2603 /* Return stringified MD5 hash for list of strings. Buffer must be 33 bytes. */
2604 char *mg_md5(char buf[33], ...)
2605 {
2606  md5_byte_t hash[16];
2607  const char *p;
2608  va_list ap;
2609  md5_state_t ctx;
2610 
2611  md5_init(&ctx);
2612 
2613  va_start(ap, buf);
2614  while ((p = va_arg(ap, const char *)) != NULL) {
2615  md5_append(&ctx, (const md5_byte_t *) p, (int) strlen(p));
2616  }
2617  va_end(ap);
2618 
2619  md5_finish(&ctx, hash);
2620  bin2str(buf, hash, sizeof(hash));
2621  return buf;
2622 }
2623 
2624 /* Check the user's password, return 1 if OK */
2625 static int check_password(const char *method, const char *ha1, const char *uri,
2626  const char *nonce, const char *nc, const char *cnonce,
2627  const char *qop, const char *response)
2628 {
2629  char ha2[32 + 1], expected_response[32 + 1];
2630 
2631  /* Some of the parameters may be NULL */
2632  if (method == NULL || nonce == NULL || nc == NULL || cnonce == NULL ||
2633  qop == NULL || response == NULL) {
2634  return 0;
2635  }
2636 
2637  /* NOTE(lsm): due to a bug in MSIE, we do not compare the URI */
2638  /* TODO(lsm): check for authentication timeout */
2639  if (/* strcmp(dig->uri, c->ouri) != 0 || */
2640  strlen(response) != 32
2641  /* || now - strtoul(dig->nonce, NULL, 10) > 3600 */
2642  ) {
2643  return 0;
2644  }
2645 
2646  mg_md5(ha2, method, ":", uri, NULL);
2647  mg_md5(expected_response, ha1, ":", nonce, ":", nc,
2648  ":", cnonce, ":", qop, ":", ha2, NULL);
2649 
2650  return mg_strcasecmp(response, expected_response) == 0;
2651 }
2652 
2653 /* Use the global passwords file, if specified by auth_gpass option,
2654  or search for .htpasswd in the requested directory. */
2655 static void open_auth_file(struct mg_connection *conn, const char *path,
2656  struct file *filep)
2657 {
2658  char name[PATH_MAX];
2659  const char *p, *e, *gpass = conn->ctx->config[GLOBAL_PASSWORDS_FILE];
2660  struct file file = STRUCT_FILE_INITIALIZER;
2661 
2662  if (gpass != NULL) {
2663  /* Use global passwords file */
2664  if (!mg_fopen(conn, gpass, "r", filep)) {
2665 #ifdef DEBUG
2666  mg_cry(conn, "fopen(%s): %s", gpass, strerror(ERRNO));
2667 #endif
2668  }
2669  /* Important: using local struct file to test path for is_directory
2670  flag.
2671  If filep is used, mg_stat() makes it appear as if auth file was
2672  opened. */
2673  } else if (mg_stat(conn, path, &file) && file.is_directory) {
2674  mg_snprintf(conn, name, sizeof(name), "%s%c%s",
2675  path, '/', PASSWORDS_FILE_NAME);
2676  if (!mg_fopen(conn, name, "r", filep)) {
2677 #ifdef DEBUG
2678  mg_cry(conn, "fopen(%s): %s", name, strerror(ERRNO));
2679 #endif
2680  }
2681  } else {
2682  /* Try to find .htpasswd in requested directory. */
2683  for (p = path, e = p + strlen(p) - 1; e > p; e--)
2684  if (e[0] == '/')
2685  break;
2686  mg_snprintf(conn, name, sizeof(name), "%.*s%c%s",
2687  (int) (e - p), p, '/', PASSWORDS_FILE_NAME);
2688  if (!mg_fopen(conn, name, "r", filep)) {
2689 #ifdef DEBUG
2690  mg_cry(conn, "fopen(%s): %s", name, strerror(ERRNO));
2691 #endif
2692  }
2693  }
2694 }
2695 
2696 /* Parsed Authorization header */
2697 struct ah {
2698  char *user, *uri, *cnonce, *response, *qop, *nc, *nonce;
2699 };
2700 
2701 /* Return 1 on success. Always initializes the ah structure. */
2702 static int parse_auth_header(struct mg_connection *conn, char *buf,
2703  size_t buf_size, struct ah *ah)
2704 {
2705  char *name, *value, *s;
2706  const char *auth_header;
2707 
2708  (void) memset(ah, 0, sizeof(*ah));
2709  if ((auth_header = mg_get_header(conn, "Authorization")) == NULL ||
2710  mg_strncasecmp(auth_header, "Digest ", 7) != 0) {
2711  return 0;
2712  }
2713 
2714  /* Make modifiable copy of the auth header */
2715  (void) mg_strlcpy(buf, auth_header + 7, buf_size);
2716  s = buf;
2717 
2718  /* Parse authorization header */
2719  for (;;) {
2720  /* Gobble initial spaces */
2721  while (isspace(* (unsigned char *) s)) {
2722  s++;
2723  }
2724  name = skip_quoted(&s, "=", " ", 0);
2725  /* Value is either quote-delimited, or ends at first comma or space. */
2726  if (s[0] == '\"') {
2727  s++;
2728  value = skip_quoted(&s, "\"", " ", '\\');
2729  if (s[0] == ',') {
2730  s++;
2731  }
2732  } else {
2733  value = skip_quoted(&s, ", ", " ", 0); /* IE uses commas, FF uses
2734  spaces */
2735  }
2736  if (*name == '\0') {
2737  break;
2738  }
2739 
2740  if (!strcmp(name, "username")) {
2741  ah->user = value;
2742  } else if (!strcmp(name, "cnonce")) {
2743  ah->cnonce = value;
2744  } else if (!strcmp(name, "response")) {
2745  ah->response = value;
2746  } else if (!strcmp(name, "uri")) {
2747  ah->uri = value;
2748  } else if (!strcmp(name, "qop")) {
2749  ah->qop = value;
2750  } else if (!strcmp(name, "nc")) {
2751  ah->nc = value;
2752  } else if (!strcmp(name, "nonce")) {
2753  ah->nonce = value;
2754  }
2755  }
2756 
2757  /* CGI needs it as REMOTE_USER */
2758  if (ah->user != NULL) {
2759  conn->request_info.remote_user = mg_strdup(ah->user);
2760  } else {
2761  return 0;
2762  }
2763 
2764  return 1;
2765 }
2766 
2767 static char *mg_fgets(char *buf, size_t size, struct file *filep, char **p)
2768 {
2769  char *eof;
2770  size_t len;
2771  char *memend;
2772 
2773  if (filep->membuf != NULL && *p != NULL) {
2774  memend = (char *) &filep->membuf[filep->size];
2775  eof = (char *) memchr(*p, '\n', memend - *p); /* Search for \n from p
2776  till the end of
2777  stream */
2778  if (eof != NULL) {
2779  eof += 1; /* Include \n */
2780  } else {
2781  eof = memend; /* Copy remaining data */
2782  }
2783  len = (size_t) (eof - *p) > size - 1 ? size - 1 : (size_t) (eof - *p);
2784  memcpy(buf, *p, len);
2785  buf[len] = '\0';
2786  *p += len;
2787  return len ? eof : NULL;
2788  } else if (filep->fp != NULL) {
2789  return fgets(buf, (int)size, filep->fp);
2790  } else {
2791  return NULL;
2792  }
2793 }
2794 
2795 /* Authorize against the opened passwords file. Return 1 if authorized. */
2796 static int authorize(struct mg_connection *conn, struct file *filep)
2797 {
2798  struct ah ah;
2799  char line[256], f_user[256] = "", ha1[256] = "", f_domain[256] = "", buf[MG_BUF_LEN], *p;
2800 
2801  if (!parse_auth_header(conn, buf, sizeof(buf), &ah)) {
2802  return 0;
2803  }
2804 
2805  /* Loop over passwords file */
2806  p = (char *) filep->membuf;
2807  while (mg_fgets(line, sizeof(line), filep, &p) != NULL) {
2808  if (sscanf(line, "%[^:]:%[^:]:%s", f_user, f_domain, ha1) != 3) {
2809  continue;
2810  }
2811 
2812  if (!strcmp(ah.user, f_user) &&
2813  !strcmp(conn->ctx->config[AUTHENTICATION_DOMAIN], f_domain))
2814  return check_password(conn->request_info.request_method, ha1, ah.uri,
2815  ah.nonce, ah.nc, ah.cnonce, ah.qop, ah.response);
2816  }
2817 
2818  return 0;
2819 }
2820 
2821 /* Return 1 if request is authorised, 0 otherwise. */
2822 static int check_authorization(struct mg_connection *conn, const char *path)
2823 {
2824  char fname[PATH_MAX];
2825  struct vec uri_vec, filename_vec;
2826  const char *list;
2827  struct file file = STRUCT_FILE_INITIALIZER;
2828  int authorized = 1;
2829 
2830  list = conn->ctx->config[PROTECT_URI];
2831  while ((list = next_option(list, &uri_vec, &filename_vec)) != NULL) {
2832  if (!memcmp(conn->request_info.uri, uri_vec.ptr, uri_vec.len)) {
2833  mg_snprintf(conn, fname, sizeof(fname), "%.*s",
2834  (int) filename_vec.len, filename_vec.ptr);
2835  if (!mg_fopen(conn, fname, "r", &file)) {
2836  mg_cry(conn, "%s: cannot open %s: %s", __func__, fname, strerror(errno));
2837  }
2838  break;
2839  }
2840  }
2841 
2842  if (!is_file_opened(&file)) {
2843  open_auth_file(conn, path, &file);
2844  }
2845 
2846  if (is_file_opened(&file)) {
2847  authorized = authorize(conn, &file);
2848  mg_fclose(&file);
2849  }
2850 
2851  return authorized;
2852 }
2853 
2854 static void send_authorization_request(struct mg_connection *conn)
2855 {
2856  char date[64];
2857  time_t curtime = time(NULL);
2858 
2859  conn->status_code = 401;
2860  conn->must_close = 1;
2861 
2862  gmt_time_string(date, sizeof(date), &curtime);
2863 
2864  mg_printf(conn,
2865  "HTTP/1.1 401 Unauthorized\r\n"
2866  "Date: %s\r\n"
2867  "Connection: %s\r\n"
2868  "Content-Length: 0\r\n"
2869  "WWW-Authenticate: Digest qop=\"auth\", realm=\"%s\", nonce=\"%lu\"\r\n\r\n",
2870  date, suggest_connection_header(conn),
2871  conn->ctx->config[AUTHENTICATION_DOMAIN],
2872  (unsigned long) time(NULL));
2873 }
2874 
2875 static int is_authorized_for_put(struct mg_connection *conn)
2876 {
2877  struct file file = STRUCT_FILE_INITIALIZER;
2878  const char *passfile = conn->ctx->config[PUT_DELETE_PASSWORDS_FILE];
2879  int ret = 0;
2880 
2881  if (passfile != NULL && mg_fopen(conn, passfile, "r", &file)) {
2882  ret = authorize(conn, &file);
2883  mg_fclose(&file);
2884  }
2885 
2886  return ret;
2887 }
2888 
2889 int mg_modify_passwords_file(const char *fname, const char *domain,
2890  const char *user, const char *pass)
2891 {
2892  int found;
2893  char line[512], u[512] = "", d[512] ="", ha1[33], tmp[PATH_MAX+1];
2894  FILE *fp, *fp2;
2895 
2896  found = 0;
2897  fp = fp2 = NULL;
2898 
2899  /* Regard empty password as no password - remove user record. */
2900  if (pass != NULL && pass[0] == '\0') {
2901  pass = NULL;
2902  }
2903 
2904  (void) snprintf(tmp, sizeof(tmp) - 1, "%s.tmp", fname);
2905  tmp[sizeof(tmp) - 1] = 0;
2906 
2907  /* Create the file if does not exist */
2908  if ((fp = fopen(fname, "a+")) != NULL) {
2909  (void) fclose(fp);
2910  }
2911 
2912  /* Open the given file and temporary file */
2913  if ((fp = fopen(fname, "r")) == NULL) {
2914  return 0;
2915  } else if ((fp2 = fopen(tmp, "w+")) == NULL) {
2916  fclose(fp);
2917  return 0;
2918  }
2919 
2920  /* Copy the stuff to temporary file */
2921  while (fgets(line, sizeof(line), fp) != NULL) {
2922  if (sscanf(line, "%[^:]:%[^:]:%*s", u, d) != 2) {
2923  continue;
2924  }
2925 
2926  if (!strcmp(u, user) && !strcmp(d, domain)) {
2927  found++;
2928  if (pass != NULL) {
2929  mg_md5(ha1, user, ":", domain, ":", pass, NULL);
2930  fprintf(fp2, "%s:%s:%s\n", user, domain, ha1);
2931  }
2932  } else {
2933  fprintf(fp2, "%s", line);
2934  }
2935  }
2936 
2937  /* If new user, just add it */
2938  if (!found && pass != NULL) {
2939  mg_md5(ha1, user, ":", domain, ":", pass, NULL);
2940  fprintf(fp2, "%s:%s:%s\n", user, domain, ha1);
2941  }
2942 
2943  /* Close files */
2944  fclose(fp);
2945  fclose(fp2);
2946 
2947  /* Put the temp file in place of real file */
2948  IGNORE_UNUSED_RESULT(remove(fname));
2949  IGNORE_UNUSED_RESULT(rename(tmp, fname));
2950 
2951  return 1;
2952 }
2953 
2954 static SOCKET conn2(struct mg_context *ctx /* may be null */, const char *host, int port,
2955  int use_ssl, char *ebuf, size_t ebuf_len)
2956 {
2957  struct sockaddr_in sain;
2958  struct hostent *he;
2959  SOCKET sock = INVALID_SOCKET;
2960 
2961  if (host == NULL) {
2962  snprintf(ebuf, ebuf_len, "%s", "NULL host");
2963  } else if (use_ssl && SSLv23_client_method == NULL) {
2964  snprintf(ebuf, ebuf_len, "%s", "SSL is not initialized");
2965  /* TODO(lsm): use something threadsafe instead of gethostbyname() */
2966  } else if ((he = gethostbyname(host)) == NULL) {
2967  snprintf(ebuf, ebuf_len, "gethostbyname(%s): %s", host, strerror(ERRNO));
2968  } else if ((sock = socket(PF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) {
2969  snprintf(ebuf, ebuf_len, "socket(): %s", strerror(ERRNO));
2970  } else {
2971  set_close_on_exec(sock, fc(ctx));
2972  memset(&sain, '\0', sizeof(sain));
2973  sain.sin_family = AF_INET;
2974  sain.sin_port = htons((uint16_t) port);
2975  sain.sin_addr = * (struct in_addr *) he->h_addr_list[0];
2976  if (connect(sock, (struct sockaddr *) &sain, sizeof(sain)) != 0) {
2977  snprintf(ebuf, ebuf_len, "connect(%s:%d): %s",
2978  host, port, strerror(ERRNO));
2979  closesocket(sock);
2980  sock = INVALID_SOCKET;
2981  }
2982  }
2983  return sock;
2984 }
2985 
2986 int mg_url_encode(const char *src, char *dst, size_t dst_len)
2987 {
2988  static const char *dont_escape = "._-$,;~()";
2989  static const char *hex = "0123456789abcdef";
2990  char *pos = dst;
2991  const char *end = dst + dst_len - 1;
2992 
2993  for (; *src != '\0' && pos < end; src++, pos++) {
2994  if (isalnum(*(const unsigned char *) src) ||
2995  strchr(dont_escape, * (const unsigned char *) src) != NULL) {
2996  *pos = *src;
2997  } else if (pos + 2 < end) {
2998  pos[0] = '%';
2999  pos[1] = hex[(* (const unsigned char *) src) >> 4];
3000  pos[2] = hex[(* (const unsigned char *) src) & 0xf];
3001  pos += 2;
3002  } else {
3003  return -1;
3004  }
3005  }
3006 
3007  *pos = '\0';
3008  return (*src == '\0') ? (int)(pos - dst) : -1;
3009 }
3010 
3011 static void print_dir_entry(struct de *de)
3012 {
3013  char size[64], mod[64], href[PATH_MAX];
3014  struct tm *tm;
3015 
3016  if (de->file.is_directory) {
3017  mg_snprintf(de->conn, size, sizeof(size), "%s", "[DIRECTORY]");
3018  } else {
3019  /* We use (signed) cast below because MSVC 6 compiler cannot
3020  convert unsigned __int64 to double. Sigh. */
3021  if (de->file.size < 1024) {
3022  mg_snprintf(de->conn, size, sizeof(size), "%d", (int) de->file.size);
3023  } else if (de->file.size < 0x100000) {
3024  mg_snprintf(de->conn, size, sizeof(size),
3025  "%.1fk", (double) de->file.size / 1024.0);
3026  } else if (de->file.size < 0x40000000) {
3027  mg_snprintf(de->conn, size, sizeof(size),
3028  "%.1fM", (double) de->file.size / 1048576);
3029  } else {
3030  mg_snprintf(de->conn, size, sizeof(size),
3031  "%.1fG", (double) de->file.size / 1073741824);
3032  }
3033  }
3034  tm = localtime(&de->file.modification_time);
3035  if (tm != NULL) {
3036  strftime(mod, sizeof(mod), "%d-%b-%Y %H:%M", tm);
3037  } else {
3038  strncpy(mod, "01-Jan-1970 00:00", sizeof(mod));
3039  mod[sizeof(mod) - 1] = '\0';
3040  }
3041  mg_url_encode(de->file_name, href, sizeof(href));
3042  de->conn->num_bytes_sent += mg_printf(de->conn,
3043  "<tr><td><a href=\"%s%s%s\">%s%s</a></td>"
3044  "<td>&nbsp;%s</td><td>&nbsp;&nbsp;%s</td></tr>\n",
3045  de->conn->request_info.uri, href, de->file.is_directory ? "/" : "",
3046  de->file_name, de->file.is_directory ? "/" : "", mod, size);
3047 }
3048 
3049 /* This function is called from send_directory() and used for
3050  sorting directory entries by size, or name, or modification time.
3051  On windows, __cdecl specification is needed in case if project is built
3052  with __stdcall convention. qsort always requires __cdels callback. */
3053 static int WINCDECL compare_dir_entries(const void *p1, const void *p2)
3054 {
3055  const struct de *a = (const struct de *) p1, *b = (const struct de *) p2;
3056  const char *query_string = a->conn->request_info.query_string;
3057  int cmp_result = 0;
3058 
3059  if (query_string == NULL) {
3060  query_string = "na";
3061  }
3062 
3063  if (a->file.is_directory && !b->file.is_directory) {
3064  return -1; /* Always put directories on top */
3065  } else if (!a->file.is_directory && b->file.is_directory) {
3066  return 1; /* Always put directories on top */
3067  } else if (*query_string == 'n') {
3068  cmp_result = strcmp(a->file_name, b->file_name);
3069  } else if (*query_string == 's') {
3070  cmp_result = a->file.size == b->file.size ? 0 :
3071  a->file.size > b->file.size ? 1 : -1;
3072  } else if (*query_string == 'd') {
3073  cmp_result = a->file.modification_time == b->file.modification_time ? 0 :
3074  a->file.modification_time > b->file.modification_time ? 1 : -1;
3075  }
3076 
3077  return query_string[1] == 'd' ? -cmp_result : cmp_result;
3078 }
3079 
3080 static int must_hide_file(struct mg_connection *conn, const char *path)
3081 {
3082  const char *pw_pattern = "**" PASSWORDS_FILE_NAME "$";
3083  const char *pattern = conn->ctx->config[HIDE_FILES];
3084  return match_prefix(pw_pattern, (int)strlen(pw_pattern), path) > 0 ||
3085  (pattern != NULL && match_prefix(pattern, (int)strlen(pattern), path) > 0);
3086 }
3087 
3088 static int scan_directory(struct mg_connection *conn, const char *dir,
3089  void *data, void (*cb)(struct de *, void *))
3090 {
3091  char path[PATH_MAX];
3092  struct dirent *dp;
3093  DIR *dirp;
3094  struct de de;
3095 
3096  if ((dirp = opendir(dir)) == NULL) {
3097  return 0;
3098  } else {
3099  de.conn = conn;
3100 
3101  while ((dp = readdir(dirp)) != NULL) {
3102  /* Do not show current dir and hidden files */
3103  if (!strcmp(dp->d_name, ".") ||
3104  !strcmp(dp->d_name, "..") ||
3105  must_hide_file(conn, dp->d_name)) {
3106  continue;
3107  }
3108 
3109  mg_snprintf(conn, path, sizeof(path), "%s%c%s", dir, '/', dp->d_name);
3110 
3111  /* If we don't memset stat structure to zero, mtime will have
3112  garbage and strftime() will segfault later on in
3113  print_dir_entry(). memset is required only if mg_stat()
3114  fails. For more details, see
3115  http://code.google.com/p/mongoose/issues/detail?id=79 */
3116  memset(&de.file, 0, sizeof(de.file));
3117  if (!mg_stat(conn, path, &de.file)) {
3118  mg_cry(conn, "%s: mg_stat(%s) failed: %s",
3119  __func__, path, strerror(ERRNO));
3120  }
3121 
3122  de.file_name = dp->d_name;
3123  cb(&de, data);
3124  }
3125  (void) closedir(dirp);
3126  }
3127  return 1;
3128 }
3129 
3130 static int remove_directory(struct mg_connection *conn, const char *dir)
3131 {
3132  char path[PATH_MAX];
3133  struct dirent *dp;
3134  DIR *dirp;
3135  struct de de;
3136 
3137  if ((dirp = opendir(dir)) == NULL) {
3138  return 0;
3139  } else {
3140  de.conn = conn;
3141 
3142  while ((dp = readdir(dirp)) != NULL) {
3143  /* Do not show current dir (but show hidden files as they will
3144  also be removed) */
3145  if (!strcmp(dp->d_name, ".") ||
3146  !strcmp(dp->d_name, "..")) {
3147  continue;
3148  }
3149 
3150  mg_snprintf(conn, path, sizeof(path), "%s%c%s", dir, '/', dp->d_name);
3151 
3152  /* If we don't memset stat structure to zero, mtime will have
3153  garbage and strftime() will segfault later on in
3154  print_dir_entry(). memset is required only if mg_stat()
3155  fails. For more details, see
3156  http://code.google.com/p/mongoose/issues/detail?id=79 */
3157  memset(&de.file, 0, sizeof(de.file));
3158  if (!mg_stat(conn, path, &de.file)) {
3159  mg_cry(conn, "%s: mg_stat(%s) failed: %s",
3160  __func__, path, strerror(ERRNO));
3161  }
3162  if(de.file.modification_time) {
3163  if(de.file.is_directory) {
3164  remove_directory(conn, path);
3165  } else {
3166  mg_remove(path);
3167  }
3168  }
3169 
3170  }
3171  (void) closedir(dirp);
3172 
3173  IGNORE_UNUSED_RESULT(rmdir(dir));
3174  }
3175 
3176  return 1;
3177 }
3178 
3179 struct dir_scan_data {
3180  struct de *entries;
3181  int num_entries;
3182  int arr_size;
3183 };
3184 
3185 /* Behaves like realloc(), but frees original pointer on failure */
3186 static void *realloc2(void *ptr, size_t size)
3187 {
3188  void *new_ptr = realloc(ptr, size);
3189  if (new_ptr == NULL) {
3190  free(ptr);
3191  }
3192  return new_ptr;
3193 }
3194 
3195 static void dir_scan_callback(struct de *de, void *data)
3196 {
3197  struct dir_scan_data *dsd = (struct dir_scan_data *) data;
3198 
3199  if (dsd->entries == NULL || dsd->num_entries >= dsd->arr_size) {
3200  dsd->arr_size *= 2;
3201  dsd->entries = (struct de *) realloc2(dsd->entries, dsd->arr_size *
3202  sizeof(dsd->entries[0]));
3203  }
3204  if (dsd->entries == NULL) {
3205  /* TODO(lsm): propagate an error to the caller */
3206  dsd->num_entries = 0;
3207  } else {
3208  dsd->entries[dsd->num_entries].file_name = mg_strdup(de->file_name);
3209  dsd->entries[dsd->num_entries].file = de->file;
3210  dsd->entries[dsd->num_entries].conn = de->conn;
3211  dsd->num_entries++;
3212  }
3213 }
3214 
3215 static void handle_directory_request(struct mg_connection *conn,
3216  const char *dir)
3217 {
3218  int i, sort_direction;
3219  struct dir_scan_data data = { NULL, 0, 128 };
3220  char date[64];
3221  time_t curtime = time(NULL);
3222 
3223  if (!scan_directory(conn, dir, &data, dir_scan_callback)) {
3224  send_http_error(conn, 500, "Cannot open directory",
3225  "Error: opendir(%s): %s", dir, strerror(ERRNO));
3226  return;
3227  }
3228 
3229  gmt_time_string(date, sizeof(date), &curtime);
3230 
3231  sort_direction = conn->request_info.query_string != NULL &&
3232  conn->request_info.query_string[1] == 'd' ? 'a' : 'd';
3233 
3234  conn->must_close = 1;
3235  mg_printf(conn, "HTTP/1.1 200 OK\r\n"
3236  "Date: %s\r\n"
3237  "Connection: close\r\n"
3238  "Content-Type: text/html; charset=utf-8\r\n\r\n",
3239  date);
3240 
3241  conn->num_bytes_sent += mg_printf(conn,
3242  "<html><head><title>Index of %s</title>"
3243  "<style>th {text-align: left;}</style></head>"
3244  "<body><h1>Index of %s</h1><pre><table cellpadding=\"0\">"
3245  "<tr><th><a href=\"?n%c\">Name</a></th>"
3246  "<th><a href=\"?d%c\">Modified</a></th>"
3247  "<th><a href=\"?s%c\">Size</a></th></tr>"
3248  "<tr><td colspan=\"3\"><hr></td></tr>",
3249  conn->request_info.uri, conn->request_info.uri,
3250  sort_direction, sort_direction, sort_direction);
3251 
3252  /* Print first entry - link to a parent directory */
3253  conn->num_bytes_sent += mg_printf(conn,
3254  "<tr><td><a href=\"%s%s\">%s</a></td>"
3255  "<td>&nbsp;%s</td><td>&nbsp;&nbsp;%s</td></tr>\n",
3256  conn->request_info.uri, "..", "Parent directory", "-", "-");
3257 
3258  /* Sort and print directory entries */
3259  if (data.entries != NULL) {
3260  qsort(data.entries, (size_t) data.num_entries,
3261  sizeof(data.entries[0]), compare_dir_entries);
3262  for (i = 0; i < data.num_entries; i++) {
3263  print_dir_entry(&data.entries[i]);
3264  free(data.entries[i].file_name);
3265  }
3266  free(data.entries);
3267  }
3268 
3269  conn->num_bytes_sent += mg_printf(conn, "%s", "</table></body></html>");
3270  conn->status_code = 200;
3271 }
3272 
3273 /* Send len bytes from the opened file to the client. */
3274 static void send_file_data(struct mg_connection *conn, struct file *filep,
3275  int64_t offset, int64_t len)
3276 {
3277  char buf[MG_BUF_LEN];
3278  int to_read, num_read, num_written;
3279 
3280  /* Sanity check the offset */
3281  offset = offset < 0 ? 0 : offset > filep->size ? filep->size : offset;
3282 
3283  if (len > 0 && filep->membuf != NULL && filep->size > 0) {
3284  if (len > filep->size - offset) {
3285  len = filep->size - offset;
3286  }
3287  mg_write(conn, filep->membuf + offset, (size_t) len);
3288  } else if (len > 0 && filep->fp != NULL) {
3289  if (offset > 0 && fseeko(filep->fp, offset, SEEK_SET) != 0) {
3290  mg_cry(conn, "%s: fseeko() failed: %s",
3291  __func__, strerror(ERRNO));
3292  }
3293  while (len > 0) {
3294  /* Calculate how much to read from the file in the buffer */
3295  to_read = sizeof(buf);
3296  if ((int64_t) to_read > len) {
3297  to_read = (int) len;
3298  }
3299 
3300  /* Read from file, exit the loop on error */
3301  if ((num_read = (int) fread(buf, 1, (size_t) to_read, filep->fp)) <= 0) {
3302  break;
3303  }
3304 
3305  /* Send read bytes to the client, exit the loop on error */
3306  if ((num_written = mg_write(conn, buf, (size_t) num_read)) != num_read) {
3307  break;
3308  }
3309 
3310  /* Both read and were successful, adjust counters */
3311  conn->num_bytes_sent += num_written;
3312  len -= num_written;
3313  }
3314  }
3315 }
3316 
3317 static int parse_range_header(const char *header, int64_t *a, int64_t *b)
3318 {
3319  return sscanf(header, "bytes=%" INT64_FMT "-%" INT64_FMT, a, b);
3320 }
3321 
3322 static void construct_etag(char *buf, size_t buf_len,
3323  const struct file *filep)
3324 {
3325  snprintf(buf, buf_len, "\"%lx.%" INT64_FMT "\"",
3326  (unsigned long) filep->modification_time, filep->size);
3327 }
3328 
3329 static void fclose_on_exec(struct file *filep, struct mg_connection *conn)
3330 {
3331  if (filep != NULL && filep->fp != NULL) {
3332 #ifdef _WIN32
3333  (void) conn; /* Unused. */
3334 #else
3335  if (fcntl(fileno(filep->fp), F_SETFD, FD_CLOEXEC) != 0) {
3336  mg_cry(conn, "%s: fcntl(F_SETFD FD_CLOEXEC) failed: %s",
3337  __func__, strerror(ERRNO));
3338  }
3339 #endif
3340  }
3341 }
3342 
3343 static void handle_file_request(struct mg_connection *conn, const char *path,
3344  struct file *filep)
3345 {
3346  char date[64], lm[64], etag[64], range[64];
3347  const char *msg = "OK", *hdr;
3348  time_t curtime = time(NULL);
3349  int64_t cl, r1, r2;
3350  struct vec mime_vec;
3351  int n;
3352  char gz_path[PATH_MAX];
3353  char const* encoding = "";
3354 
3355  get_mime_type(conn->ctx, path, &mime_vec);
3356  cl = filep->size;
3357  conn->status_code = 200;
3358  range[0] = '\0';
3359 
3360  /* if this file is in fact a pre-gzipped file, rewrite its filename
3361  it's important to rewrite the filename after resolving
3362  the mime type from it, to preserve the actual file's type */
3363  if (filep->gzipped) {
3364  snprintf(gz_path, sizeof(gz_path), "%s.gz", path);
3365  path = gz_path;
3366  encoding = "Content-Encoding: gzip\r\n";
3367  }
3368 
3369  if (!mg_fopen(conn, path, "rb", filep)) {
3370  send_http_error(conn, 500, http_500_error,
3371  "fopen(%s): %s", path, strerror(ERRNO));
3372  return;
3373  }
3374 
3375  fclose_on_exec(filep, conn);
3376 
3377  /* If Range: header specified, act accordingly */
3378  r1 = r2 = 0;
3379  hdr = mg_get_header(conn, "Range");
3380  if (hdr != NULL && (n = parse_range_header(hdr, &r1, &r2)) > 0 &&
3381  r1 >= 0 && r2 >= 0) {
3382  /* actually, range requests don't play well with a pre-gzipped
3383  file (since the range is specified in the uncompressed space) */
3384  if (filep->gzipped) {
3385  send_http_error(conn, 501, "Not Implemented", "range requests in gzipped files are not supported");
3386  mg_fclose(filep);
3387  return;
3388  }
3389  conn->status_code = 206;
3390 cl = n == 2 ? (r2 > cl ? cl : r2) - r1 + 1: cl - r1;
3391  mg_snprintf(conn, range, sizeof(range),
3392  "Content-Range: bytes "
3393  "%" INT64_FMT "-%"
3394  INT64_FMT "/%" INT64_FMT "\r\n",
3395  r1, r1 + cl - 1, filep->size);
3396  msg = "Partial Content";
3397  }
3398 
3399  /* Prepare Etag, Date, Last-Modified headers. Must be in UTC, according to
3400  http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3 */
3401  gmt_time_string(date, sizeof(date), &curtime);
3402  gmt_time_string(lm, sizeof(lm), &filep->modification_time);
3403  construct_etag(etag, sizeof(etag), filep);
3404 
3405  (void) mg_printf(conn,
3406  "HTTP/1.1 %d %s\r\n"
3407  "Date: %s\r\n"
3408  "Last-Modified: %s\r\n"
3409  "Etag: %s\r\n"
3410  "Content-Type: %.*s\r\n"
3411  "Content-Length: %" INT64_FMT "\r\n"
3412  "Connection: %s\r\n"
3413  "Accept-Ranges: bytes\r\n"
3414  "%s%s\r\n",
3415  conn->status_code, msg, date, lm, etag, (int) mime_vec.len,
3416  mime_vec.ptr, cl, suggest_connection_header(conn), range, encoding);
3417 
3418  if (strcmp(conn->request_info.request_method, "HEAD") != 0) {
3419  send_file_data(conn, filep, r1, cl);
3420  }
3421  mg_fclose(filep);
3422 }
3423 
3424 void mg_send_file(struct mg_connection *conn, const char *path)
3425 {
3426  struct file file = STRUCT_FILE_INITIALIZER;
3427  if (mg_stat(conn, path, &file)) {
3428  handle_file_request(conn, path, &file);
3429  } else {
3430  send_http_error(conn, 404, "Not Found", "%s", "File not found");
3431  }
3432 }
3433 
3434 
3435 /* Parse HTTP headers from the given buffer, advance buffer to the point
3436  where parsing stopped. */
3437 static void parse_http_headers(char **buf, struct mg_request_info *ri)
3438 {
3439  int i;
3440 
3441  for (i = 0; i < (int) ARRAY_SIZE(ri->http_headers); i++) {
3442  ri->http_headers[i].name = skip_quoted(buf, ":", " ", 0);
3443  ri->http_headers[i].value = skip(buf, "\r\n");
3444  if (ri->http_headers[i].name[0] == '\0')
3445  break;
3446  ri->num_headers = i + 1;
3447  }
3448 }
3449 
3450 static int is_valid_http_method(const char *method)
3451 {
3452  return !strcmp(method, "GET") || !strcmp(method, "POST") ||
3453  !strcmp(method, "HEAD") || !strcmp(method, "CONNECT") ||
3454  !strcmp(method, "PUT") || !strcmp(method, "DELETE") ||
3455  !strcmp(method, "OPTIONS") || !strcmp(method, "PROPFIND")
3456  || !strcmp(method, "MKCOL")
3457  ;
3458 }
3459 
3460 /* Parse HTTP request, fill in mg_request_info structure.
3461  This function modifies the buffer by NUL-terminating
3462  HTTP request components, header names and header values. */
3463 static int parse_http_message(char *buf, int len, struct mg_request_info *ri)
3464 {
3465  int is_request, request_length = get_request_len(buf, len);
3466  if (request_length > 0) {
3467  /* Reset attributes. DO NOT TOUCH is_ssl, remote_ip, remote_port */
3468  ri->remote_user = ri->request_method = ri->uri = ri->http_version = NULL;
3469  ri->num_headers = 0;
3470 
3471  buf[request_length - 1] = '\0';
3472 
3473  /* RFC says that all initial whitespaces should be ingored */
3474  while (*buf != '\0' && isspace(* (unsigned char *) buf)) {
3475  buf++;
3476  }
3477  ri->request_method = skip(&buf, " ");
3478  ri->uri = skip(&buf, " ");
3479  ri->http_version = skip(&buf, "\r\n");
3480 
3481  /* HTTP message could be either HTTP request or HTTP response, e.g.
3482  "GET / HTTP/1.0 ...." or "HTTP/1.0 200 OK ..." */
3483  is_request = is_valid_http_method(ri->request_method);
3484  if ((is_request && memcmp(ri->http_version, "HTTP/", 5) != 0) ||
3485  (!is_request && memcmp(ri->request_method, "HTTP/", 5) != 0)) {
3486  request_length = -1;
3487  } else {
3488  if (is_request) {
3489  ri->http_version += 5;
3490  }
3491  parse_http_headers(&buf, ri);
3492  }
3493  }
3494  return request_length;
3495 }
3496 
3497 /* Keep reading the input (either opened file descriptor fd, or socket sock,
3498  or SSL descriptor ssl) into buffer buf, until \r\n\r\n appears in the
3499  buffer (which marks the end of HTTP request). Buffer buf may already
3500  have some data. The length of the data is stored in nread.
3501  Upon every read operation, increase nread by the number of bytes read. */
3502 static int read_request(FILE *fp, struct mg_connection *conn,
3503  char *buf, int bufsiz, int *nread)
3504 {
3505  int request_len, n = 0;
3506 
3507  request_len = get_request_len(buf, *nread);
3508  while (conn->ctx->stop_flag == 0 &&
3509  *nread < bufsiz && request_len == 0 &&
3510  (n = pull(fp, conn, buf + *nread, bufsiz - *nread)) > 0) {
3511  *nread += n;
3512  assert(*nread <= bufsiz);
3513  request_len = get_request_len(buf, *nread);
3514  }
3515 
3516  return request_len <= 0 && n <= 0 ? -1 : request_len;
3517 }
3518 
3519 /* For given directory path, substitute it to valid index file.
3520  Return 1 if index file has been found, 0 if not found.
3521  If the file is found, it's stats is returned in stp. */
3522 static int substitute_index_file(struct mg_connection *conn, char *path,
3523  size_t path_len, struct file *filep)
3524 {
3525  const char *list = conn->ctx->config[INDEX_FILES];
3526  struct file file = STRUCT_FILE_INITIALIZER;
3527  struct vec filename_vec;
3528  size_t n = strlen(path);
3529  int found = 0;
3530 
3531  /* The 'path' given to us points to the directory. Remove all trailing
3532  directory separator characters from the end of the path, and
3533  then append single directory separator character. */
3534  while (n > 0 && path[n - 1] == '/') {
3535  n--;
3536  }
3537  path[n] = '/';
3538 
3539  /* Traverse index files list. For each entry, append it to the given
3540  path and see if the file exists. If it exists, break the loop */
3541  while ((list = next_option(list, &filename_vec, NULL)) != NULL) {
3542 
3543  /* Ignore too long entries that may overflow path buffer */
3544  if (filename_vec.len > path_len - (n + 2))
3545  continue;
3546 
3547  /* Prepare full path to the index file */
3548  mg_strlcpy(path + n + 1, filename_vec.ptr, filename_vec.len + 1);
3549 
3550  /* Does it exist? */
3551  if (mg_stat(conn, path, &file)) {
3552  /* Yes it does, break the loop */
3553  *filep = file;
3554  found = 1;
3555  break;
3556  }
3557  }
3558 
3559  /* If no index file exists, restore directory path */
3560  if (!found) {
3561  path[n] = '\0';
3562  }
3563 
3564  return found;
3565 }
3566 
3567 /* Return True if we should reply 304 Not Modified. */
3568 static int is_not_modified(const struct mg_connection *conn,
3569  const struct file *filep)
3570 {
3571  char etag[64];
3572  const char *ims = mg_get_header(conn, "If-Modified-Since");
3573  const char *inm = mg_get_header(conn, "If-None-Match");
3574  construct_etag(etag, sizeof(etag), filep);
3575  return (inm != NULL && !mg_strcasecmp(etag, inm)) ||
3576  (ims != NULL && filep->modification_time <= parse_date_string(ims));
3577 }
3578 
3579 static int forward_body_data(struct mg_connection *conn, FILE *fp,
3580  SOCKET sock, SSL *ssl)
3581 {
3582  const char *expect, *body;
3583  char buf[MG_BUF_LEN];
3584  int to_read, nread, buffered_len, success = 0;
3585 
3586  expect = mg_get_header(conn, "Expect");
3587  assert(fp != NULL);
3588 
3589  if (conn->content_len == -1) {
3590  send_http_error(conn, 411, "Length Required", "%s", "");
3591  } else if (expect != NULL && mg_strcasecmp(expect, "100-continue")) {
3592  send_http_error(conn, 417, "Expectation Failed", "%s", "");
3593  } else {
3594  if (expect != NULL) {
3595  (void) mg_printf(conn, "%s", "HTTP/1.1 100 Continue\r\n\r\n");
3596  }
3597 
3598  body = conn->buf + conn->request_len + conn->consumed_content;
3599  buffered_len = (int)(&conn->buf[conn->data_len] - body);
3600  assert(buffered_len >= 0);
3601  assert(conn->consumed_content == 0);
3602 
3603  if (buffered_len > 0) {
3604  if ((int64_t) buffered_len > conn->content_len) {
3605  buffered_len = (int) conn->content_len;
3606  }
3607  push(fp, sock, ssl, body, (int64_t) buffered_len);
3608  conn->consumed_content += buffered_len;
3609  }
3610 
3611  nread = 0;
3612  while (conn->consumed_content < conn->content_len) {
3613  to_read = sizeof(buf);
3614  if ((int64_t) to_read > conn->content_len - conn->consumed_content) {
3615  to_read = (int) (conn->content_len - conn->consumed_content);
3616  }
3617  nread = pull(NULL, conn, buf, to_read);
3618  if (nread <= 0 || push(fp, sock, ssl, buf, nread) != nread) {
3619  break;
3620  }
3621  conn->consumed_content += nread;
3622  }
3623 
3624  if (conn->consumed_content == conn->content_len) {
3625  success = nread >= 0;
3626  }
3627 
3628  /* Each error code path in this function must send an error */
3629  if (!success) {
3630  send_http_error(conn, 577, http_500_error, "%s", "");
3631  }
3632  }
3633 
3634  return success;
3635 }
3636 
3637 #if !defined(NO_CGI)
3638 /* This structure helps to create an environment for the spawned CGI program.
3639  Environment is an array of "VARIABLE=VALUE\0" ASCIIZ strings,
3640  last element must be NULL.
3641  However, on Windows there is a requirement that all these VARIABLE=VALUE\0
3642  strings must reside in a contiguous buffer. The end of the buffer is
3643  marked by two '\0' characters.
3644  We satisfy both worlds: we create an envp array (which is vars), all
3645  entries are actually pointers inside buf. */
3646 struct cgi_env_block {
3647  struct mg_connection *conn;
3648  char buf[CGI_ENVIRONMENT_SIZE]; /* Environment buffer */
3649  int len; /* Space taken */
3650  char *vars[MAX_CGI_ENVIR_VARS]; /* char **envp */
3651  int nvars; /* Number of variables */
3652 };
3653 
3654 static char *addenv(struct cgi_env_block *block,
3655  PRINTF_FORMAT_STRING(const char *fmt), ...)
3656 PRINTF_ARGS(2, 3);
3657 
3658 /* Append VARIABLE=VALUE\0 string to the buffer, and add a respective
3659  pointer into the vars array. */
3660 static char *addenv(struct cgi_env_block *block, const char *fmt, ...)
3661 {
3662  int n, space;
3663  char *added;
3664  va_list ap;
3665 
3666  /* Calculate how much space is left in the buffer */
3667  space = sizeof(block->buf) - block->len - 2;
3668  assert(space >= 0);
3669 
3670  /* Make a pointer to the free space int the buffer */
3671  added = block->buf + block->len;
3672 
3673  /* Copy VARIABLE=VALUE\0 string into the free space */
3674  va_start(ap, fmt);
3675  n = mg_vsnprintf(block->conn, added, (size_t) space, fmt, ap);
3676  va_end(ap);
3677 
3678  /* Make sure we do not overflow buffer and the envp array */
3679  if (n > 0 && n + 1 < space &&
3680  block->nvars < (int) ARRAY_SIZE(block->vars) - 2) {
3681  /* Append a pointer to the added string into the envp array */
3682  block->vars[block->nvars++] = added;
3683  /* Bump up used length counter. Include \0 terminator */
3684  block->len += n + 1;
3685  } else {
3686  mg_cry(block->conn, "%s: CGI env buffer truncated for [%s]", __func__, fmt);
3687  }
3688 
3689  return added;
3690 }
3691 
3692 static void prepare_cgi_environment(struct mg_connection *conn,
3693  const char *prog,
3694  struct cgi_env_block *blk)
3695 {
3696  const char *s, *slash;
3697  struct vec var_vec;
3698  char *p, src_addr[IP_ADDR_STR_LEN];
3699  int i;
3700 
3701  blk->len = blk->nvars = 0;
3702  blk->conn = conn;
3703  sockaddr_to_string(src_addr, sizeof(src_addr), &conn->client.rsa);
3704 
3705  addenv(blk, "SERVER_NAME=%s", conn->ctx->config[AUTHENTICATION_DOMAIN]);
3706  addenv(blk, "SERVER_ROOT=%s", conn->ctx->config[DOCUMENT_ROOT]);
3707  addenv(blk, "DOCUMENT_ROOT=%s", conn->ctx->config[DOCUMENT_ROOT]);
3708  addenv(blk, "SERVER_SOFTWARE=%s/%s", "Civetweb", mg_version());
3709 
3710  /* Prepare the environment block */
3711  addenv(blk, "%s", "GATEWAY_INTERFACE=CGI/1.1");
3712  addenv(blk, "%s", "SERVER_PROTOCOL=HTTP/1.1");
3713  addenv(blk, "%s", "REDIRECT_STATUS=200"); /* For PHP */
3714 
3715  /* TODO(lsm): fix this for IPv6 case */
3716  addenv(blk, "SERVER_PORT=%d", ntohs(conn->client.lsa.sin.sin_port));
3717 
3718  addenv(blk, "REQUEST_METHOD=%s", conn->request_info.request_method);
3719  addenv(blk, "REMOTE_ADDR=%s", src_addr);
3720  addenv(blk, "REMOTE_PORT=%d", conn->request_info.remote_port);
3721  addenv(blk, "REQUEST_URI=%s", conn->request_info.uri);
3722 
3723  /* SCRIPT_NAME */
3724  assert(conn->request_info.uri[0] == '/');
3725  slash = strrchr(conn->request_info.uri, '/');
3726  if ((s = strrchr(prog, '/')) == NULL)
3727  s = prog;
3728  addenv(blk, "SCRIPT_NAME=%.*s%s", (int) (slash - conn->request_info.uri),
3729  conn->request_info.uri, s);
3730 
3731  addenv(blk, "SCRIPT_FILENAME=%s", prog);
3732  addenv(blk, "PATH_TRANSLATED=%s", prog);
3733  addenv(blk, "HTTPS=%s", conn->ssl == NULL ? "off" : "on");
3734 
3735  if ((s = mg_get_header(conn, "Content-Type")) != NULL)
3736  addenv(blk, "CONTENT_TYPE=%s", s);
3737 
3738  if (conn->request_info.query_string != NULL)
3739  addenv(blk, "QUERY_STRING=%s", conn->request_info.query_string);
3740 
3741  if ((s = mg_get_header(conn, "Content-Length")) != NULL)
3742  addenv(blk, "CONTENT_LENGTH=%s", s);
3743 
3744  if ((s = getenv("PATH")) != NULL)
3745  addenv(blk, "PATH=%s", s);
3746 
3747  if (conn->path_info != NULL) {
3748  addenv(blk, "PATH_INFO=%s", conn->path_info);
3749  }
3750 
3751 #if defined(_WIN32)
3752  if ((s = getenv("COMSPEC")) != NULL) {
3753  addenv(blk, "COMSPEC=%s", s);
3754  }
3755  if ((s = getenv("SYSTEMROOT")) != NULL) {
3756  addenv(blk, "SYSTEMROOT=%s", s);
3757  }
3758  if ((s = getenv("SystemDrive")) != NULL) {
3759  addenv(blk, "SystemDrive=%s", s);
3760  }
3761  if ((s = getenv("ProgramFiles")) != NULL) {
3762  addenv(blk, "ProgramFiles=%s", s);
3763  }
3764  if ((s = getenv("ProgramFiles(x86)")) != NULL) {
3765  addenv(blk, "ProgramFiles(x86)=%s", s);
3766  }
3767 #else
3768  if ((s = getenv("LD_LIBRARY_PATH")) != NULL)
3769  addenv(blk, "LD_LIBRARY_PATH=%s", s);
3770 #endif /* _WIN32 */
3771 
3772  if ((s = getenv("PERLLIB")) != NULL)
3773  addenv(blk, "PERLLIB=%s", s);
3774 
3775  if (conn->request_info.remote_user != NULL) {
3776  addenv(blk, "REMOTE_USER=%s", conn->request_info.remote_user);
3777  addenv(blk, "%s", "AUTH_TYPE=Digest");
3778  }
3779 
3780  /* Add all headers as HTTP_* variables */
3781  for (i = 0; i < conn->request_info.num_headers; i++) {
3782  p = addenv(blk, "HTTP_%s=%s",
3783  conn->request_info.http_headers[i].name,
3784  conn->request_info.http_headers[i].value);
3785 
3786  /* Convert variable name into uppercase, and change - to _ */
3787  for (; *p != '=' && *p != '\0'; p++) {
3788  if (*p == '-')
3789  *p = '_';
3790  *p = (char) toupper(* (unsigned char *) p);
3791  }
3792  }
3793 
3794  /* Add user-specified variables */
3795  s = conn->ctx->config[CGI_ENVIRONMENT];
3796  while ((s = next_option(s, &var_vec, NULL)) != NULL) {
3797  addenv(blk, "%.*s", (int) var_vec.len, var_vec.ptr);
3798  }
3799 
3800  blk->vars[blk->nvars++] = NULL;
3801  blk->buf[blk->len++] = '\0';
3802 
3803  assert(blk->nvars < (int) ARRAY_SIZE(blk->vars));
3804  assert(blk->len > 0);
3805  assert(blk->len < (int) sizeof(blk->buf));
3806 }
3807 
3808 static void handle_cgi_request(struct mg_connection *conn, const char *prog)
3809 {
3810  char *buf;
3811  size_t buflen;
3812  int headers_len, data_len, i, fdin[2] = { 0, 0 }, fdout[2] = { 0, 0 };
3813  const char *status, *status_text, *connection_state;
3814  char *pbuf, dir[PATH_MAX], *p;
3815  struct mg_request_info ri;
3816  struct cgi_env_block blk;
3817  FILE *in = NULL, *out = NULL;
3818  struct file fout = STRUCT_FILE_INITIALIZER;
3819  pid_t pid = (pid_t) -1;
3820 
3821  buf = NULL;
3822  buflen = 16384;
3823  prepare_cgi_environment(conn, prog, &blk);
3824 
3825  /* CGI must be executed in its own directory. 'dir' must point to the
3826  directory containing executable program, 'p' must point to the
3827  executable program name relative to 'dir'. */
3828  (void) mg_snprintf(conn, dir, sizeof(dir), "%s", prog);
3829  if ((p = strrchr(dir, '/')) != NULL) {
3830  *p++ = '\0';
3831  } else {
3832  dir[0] = '.', dir[1] = '\0';
3833  p = (char *) prog;
3834  }
3835 
3836  if (pipe(fdin) != 0 || pipe(fdout) != 0) {
3837  send_http_error(conn, 500, http_500_error,
3838  "Cannot create CGI pipe: %s", strerror(ERRNO));
3839  goto done;
3840  }
3841 
3842  pid = spawn_process(conn, p, blk.buf, blk.vars, fdin[0], fdout[1], dir);
3843  if (pid == (pid_t) -1) {
3844  send_http_error(conn, 500, http_500_error,
3845  "Cannot spawn CGI process [%s]: %s", prog, strerror(ERRNO));
3846  goto done;
3847  }
3848 
3849  /* Make sure child closes all pipe descriptors. It must dup them to 0,1 */
3850  set_close_on_exec(fdin[0], conn);
3851  set_close_on_exec(fdin[1], conn);
3852  set_close_on_exec(fdout[0], conn);
3853  set_close_on_exec(fdout[1], conn);
3854 
3855  /* Parent closes only one side of the pipes.
3856  If we don't mark them as closed, close() attempt before
3857  return from this function throws an exception on Windows.
3858  Windows does not like when closed descriptor is closed again. */
3859  (void) close(fdin[0]);
3860  (void) close(fdout[1]);
3861  fdin[0] = fdout[1] = -1;
3862 
3863 
3864  if ((in = fdopen(fdin[1], "wb")) == NULL ||
3865  (out = fdopen(fdout[0], "rb")) == NULL) {
3866  send_http_error(conn, 500, http_500_error,
3867  "fopen: %s", strerror(ERRNO));
3868  goto done;
3869  }
3870 
3871  setbuf(in, NULL);
3872  setbuf(out, NULL);
3873  fout.fp = out;
3874 
3875  /* Send POST data to the CGI process if needed */
3876  if (!strcmp(conn->request_info.request_method, "POST") &&
3877  !forward_body_data(conn, in, INVALID_SOCKET, NULL)) {
3878  goto done;
3879  }
3880 
3881  /* Close so child gets an EOF. */
3882  fclose(in);
3883  in = NULL;
3884  fdin[1] = -1;
3885 
3886  /* Now read CGI reply into a buffer. We need to set correct
3887  status code, thus we need to see all HTTP headers first.
3888  Do not send anything back to client, until we buffer in all
3889  HTTP headers. */
3890  data_len = 0;
3891  buf = (char*)malloc(buflen);
3892  if (buf == NULL) {
3893  send_http_error(conn, 500, http_500_error,
3894  "Not enough memory for buffer (%u bytes)",
3895  (unsigned int) buflen);
3896  goto done;
3897  }
3898  headers_len = read_request(out, conn, buf, (int) buflen, &data_len);
3899  if (headers_len <= 0) {
3900  send_http_error(conn, 500, http_500_error,
3901  "CGI program sent malformed or too big (>%u bytes) "
3902  "HTTP headers: [%.*s]",
3903  (unsigned) buflen, data_len, buf);
3904  goto done;
3905  }
3906  pbuf = buf;
3907  buf[headers_len - 1] = '\0';
3908  parse_http_headers(&pbuf, &ri);
3909 
3910  /* Make up and send the status line */
3911  status_text = "OK";
3912  if ((status = get_header(&ri, "Status")) != NULL) {
3913  conn->status_code = atoi(status);
3914  status_text = status;
3915  while (isdigit(* (unsigned char *) status_text) || *status_text == ' ') {
3916  status_text++;
3917  }
3918  } else if (get_header(&ri, "Location") != NULL) {
3919  conn->status_code = 302;
3920  } else {
3921  conn->status_code = 200;
3922  }
3923  connection_state = get_header(&ri, "Connection");
3924  if (connection_state == NULL ||
3925  mg_strcasecmp(connection_state, "keep-alive")) {
3926  conn->must_close = 1;
3927  }
3928  (void) mg_printf(conn, "HTTP/1.1 %d %s\r\n", conn->status_code,
3929  status_text);
3930 
3931  /* Send headers */
3932  for (i = 0; i < ri.num_headers; i++) {
3933  mg_printf(conn, "%s: %s\r\n",
3934  ri.http_headers[i].name, ri.http_headers[i].value);
3935  }
3936  mg_write(conn, "\r\n", 2);
3937 
3938  /* Send chunk of data that may have been read after the headers */
3939  conn->num_bytes_sent += mg_write(conn, buf + headers_len,
3940  (size_t)(data_len - headers_len));
3941 
3942  /* Read the rest of CGI output and send to the client */
3943  send_file_data(conn, &fout, 0, INT64_MAX);
3944 
3945 done:
3946  if (pid != (pid_t) -1) {
3947  kill(pid, SIGKILL);
3948 #if !defined(_WIN32)
3949  {
3950  int st;
3951  while (waitpid(pid, &st, 0) != -1); /* clean zombies */
3952  }
3953 #endif
3954  }
3955  if (fdin[0] != -1) {
3956  close(fdin[0]);
3957  }
3958  if (fdout[1] != -1) {
3959  close(fdout[1]);
3960  }
3961 
3962  if (in != NULL) {
3963  fclose(in);
3964  } else if (fdin[1] != -1) {
3965  close(fdin[1]);
3966  }
3967 
3968  if (out != NULL) {
3969  fclose(out);
3970  } else if (fdout[0] != -1) {
3971  close(fdout[0]);
3972  }
3973  if (buf != NULL) {
3974  free(buf);
3975  }
3976 }
3977 #endif /* !NO_CGI */
3978 
3979 /* For a given PUT path, create all intermediate subdirectories
3980  for given path. Return 0 if the path itself is a directory,
3981  or -1 on error, 1 if OK. */
3982 static int put_dir(struct mg_connection *conn, const char *path)
3983 {
3984  char buf[PATH_MAX];
3985  const char *s, *p;
3986  struct file file = STRUCT_FILE_INITIALIZER;
3987  int len, res = 1;
3988 
3989  for (s = p = path + 2; (p = strchr(s, '/')) != NULL; s = ++p) {
3990  len = (int)(p - path);
3991  if (len >= (int) sizeof(buf)) {
3992  res = -1;
3993  break;
3994  }
3995  memcpy(buf, path, len);
3996  buf[len] = '\0';
3997 
3998  /* Try to create intermediate directory */
3999  DEBUG_TRACE(("mkdir(%s)", buf));
4000  if (!mg_stat(conn, buf, &file) && mg_mkdir(buf, 0755) != 0) {
4001  res = -1;
4002  break;
4003  }
4004 
4005  /* Is path itself a directory? */
4006  if (p[1] == '\0') {
4007  res = 0;
4008  }
4009  }
4010 
4011  return res;
4012 }
4013 
4014 static void mkcol(struct mg_connection *conn, const char *path)
4015 {
4016  int rc, body_len;
4017  struct de de;
4018  char date[64];
4019  time_t curtime = time(NULL);
4020 
4021  memset(&de.file, 0, sizeof(de.file));
4022  if (!mg_stat(conn, path, &de.file)) {
4023  mg_cry(conn, "%s: mg_stat(%s) failed: %s",
4024  __func__, path, strerror(ERRNO));
4025  }
4026 
4027  if(de.file.modification_time) {
4028  send_http_error(conn, 405, "Method Not Allowed",
4029  "mkcol(%s): %s", path, strerror(ERRNO));
4030  return;
4031  }
4032 
4033  body_len = conn->data_len - conn->request_len;
4034  if(body_len > 0) {
4035  send_http_error(conn, 415, "Unsupported media type",
4036  "mkcol(%s): %s", path, strerror(ERRNO));
4037  return;
4038  }
4039 
4040  rc = mg_mkdir(path, 0755);
4041 
4042  if (rc == 0) {
4043  conn->status_code = 201;
4044  gmt_time_string(date, sizeof(date), &curtime);
4045  mg_printf(conn, "HTTP/1.1 %d Created\r\nDate: %s\r\nContent-Length: 0\r\nConnection: %s\r\n\r\n",
4046  conn->status_code, date, suggest_connection_header(conn));
4047  } else if (rc == -1) {
4048  if(errno == EEXIST)
4049  send_http_error(conn, 405, "Method Not Allowed",
4050  "mkcol(%s): %s", path, strerror(ERRNO));
4051  else if(errno == EACCES)
4052  send_http_error(conn, 403, "Forbidden",
4053  "mkcol(%s): %s", path, strerror(ERRNO));
4054  else if(errno == ENOENT)
4055  send_http_error(conn, 409, "Conflict",
4056  "mkcol(%s): %s", path, strerror(ERRNO));
4057  else
4058  send_http_error(conn, 500, http_500_error,
4059  "fopen(%s): %s", path, strerror(ERRNO));
4060  }
4061 }
4062 
4063 static void put_file(struct mg_connection *conn, const char *path)
4064 {
4065  struct file file = STRUCT_FILE_INITIALIZER;
4066  const char *range;
4067  int64_t r1, r2;
4068  int rc;
4069  char date[64];
4070  time_t curtime = time(NULL);
4071 
4072  conn->status_code = mg_stat(conn, path, &file) ? 200 : 201;
4073 
4074  if ((rc = put_dir(conn, path)) == 0) {
4075  gmt_time_string(date, sizeof(date), &curtime);
4076  mg_printf(conn, "HTTP/1.1 %d OK\r\nDate: %s\r\nContent-Length: 0\r\nConnection: %s\r\n\r\n",
4077  conn->status_code, date, suggest_connection_header(conn));
4078  } else if (rc == -1) {
4079  send_http_error(conn, 500, http_500_error,
4080  "put_dir(%s): %s", path, strerror(ERRNO));
4081  } else if (!mg_fopen(conn, path, "wb+", &file) || file.fp == NULL) {
4082  mg_fclose(&file);
4083  send_http_error(conn, 500, http_500_error,
4084  "fopen(%s): %s", path, strerror(ERRNO));
4085  } else {
4086  fclose_on_exec(&file, conn);
4087  range = mg_get_header(conn, "Content-Range");
4088  r1 = r2 = 0;
4089  if (range != NULL && parse_range_header(range, &r1, &r2) > 0) {
4090  conn->status_code = 206;
4091  fseeko(file.fp, r1, SEEK_SET);
4092  }
4093  if (!forward_body_data(conn, file.fp, INVALID_SOCKET, NULL)) {
4094  conn->status_code = 500;
4095  }
4096  gmt_time_string(date, sizeof(date), &curtime);
4097  mg_printf(conn, "HTTP/1.1 %d OK\r\nDate: %s\r\nContent-Length: 0\r\nConnection: %s\r\n\r\n",
4098  conn->status_code, date, suggest_connection_header(conn));
4099  mg_fclose(&file);
4100  }
4101 }
4102 
4103 static void send_ssi_file(struct mg_connection *, const char *,
4104  struct file *, int);
4105 
4106 static void do_ssi_include(struct mg_connection *conn, const char *ssi,
4107  char *tag, int include_level)
4108 {
4109  char file_name[MG_BUF_LEN], path[PATH_MAX], *p;
4110  struct file file = STRUCT_FILE_INITIALIZER;
4111 
4112  /* sscanf() is safe here, since send_ssi_file() also uses buffer
4113  of size MG_BUF_LEN to get the tag. So strlen(tag) is
4114  always < MG_BUF_LEN. */
4115  if (sscanf(tag, " virtual=\"%[^\"]\"", file_name) == 1) {
4116  /* File name is relative to the webserver root */
4117  (void) mg_snprintf(conn, path, sizeof(path), "%s%c%s",
4118  conn->ctx->config[DOCUMENT_ROOT], '/', file_name);
4119  } else if (sscanf(tag, " abspath=\"%[^\"]\"", file_name) == 1) {
4120  /* File name is relative to the webserver working directory
4121  or it is absolute system path */
4122  (void) mg_snprintf(conn, path, sizeof(path), "%s", file_name);
4123  } else if (sscanf(tag, " file=\"%[^\"]\"", file_name) == 1 ||
4124  sscanf(tag, " \"%[^\"]\"", file_name) == 1) {
4125  /* File name is relative to the currect document */
4126  (void) mg_snprintf(conn, path, sizeof(path), "%s", ssi);
4127  if ((p = strrchr(path, '/')) != NULL) {
4128  p[1] = '\0';
4129  }
4130  (void) mg_snprintf(conn, path + strlen(path),
4131  sizeof(path) - strlen(path), "%s", file_name);
4132  } else {
4133  mg_cry(conn, "Bad SSI #include: [%s]", tag);
4134  return;
4135  }
4136 
4137  if (!mg_fopen(conn, path, "rb", &file)) {
4138  mg_cry(conn, "Cannot open SSI #include: [%s]: fopen(%s): %s",
4139  tag, path, strerror(ERRNO));
4140  } else {
4141  fclose_on_exec(&file, conn);
4142  if (match_prefix(conn->ctx->config[SSI_EXTENSIONS],
4143  (int)strlen(conn->ctx->config[SSI_EXTENSIONS]), path) > 0) {
4144  send_ssi_file(conn, path, &file, include_level + 1);
4145  } else {
4146  send_file_data(conn, &file, 0, INT64_MAX);
4147  }
4148  mg_fclose(&file);
4149  }
4150 }
4151 
4152 #if !defined(NO_POPEN)
4153 static void do_ssi_exec(struct mg_connection *conn, char *tag)
4154 {
4155  char cmd[MG_BUF_LEN] = "";
4156  struct file file = STRUCT_FILE_INITIALIZER;
4157 
4158  if (sscanf(tag, " \"%[^\"]\"", cmd) != 1) {
4159  mg_cry(conn, "Bad SSI #exec: [%s]", tag);
4160  } else if ((file.fp = popen(cmd, "r")) == NULL) {
4161  mg_cry(conn, "Cannot SSI #exec: [%s]: %s", cmd, strerror(ERRNO));
4162  } else {
4163  send_file_data(conn, &file, 0, INT64_MAX);
4164  pclose(file.fp);
4165  }
4166 }
4167 #endif /* !NO_POPEN */
4168 
4169 static int mg_fgetc(struct file *filep, int offset)
4170 {
4171  if (filep->membuf != NULL && offset >=0 && offset < filep->size) {
4172  return ((unsigned char *) filep->membuf)[offset];
4173  } else if (filep->fp != NULL) {
4174  return fgetc(filep->fp);
4175  } else {
4176  return EOF;
4177  }
4178 }
4179 
4180 static void send_ssi_file(struct mg_connection *conn, const char *path,
4181  struct file *filep, int include_level)
4182 {
4183  char buf[MG_BUF_LEN];
4184  int ch, offset, len, in_ssi_tag;
4185 
4186  if (include_level > 10) {
4187  mg_cry(conn, "SSI #include level is too deep (%s)", path);
4188  return;
4189  }
4190 
4191  in_ssi_tag = len = offset = 0;
4192  while ((ch = mg_fgetc(filep, offset)) != EOF) {
4193  if (in_ssi_tag && ch == '>') {
4194  in_ssi_tag = 0;
4195  buf[len++] = (char) ch;
4196  buf[len] = '\0';
4197  assert(len <= (int) sizeof(buf));
4198  if (len < 6 || memcmp(buf, "<!--#", 5) != 0) {
4199  /* Not an SSI tag, pass it */
4200  (void) mg_write(conn, buf, (size_t) len);
4201  } else {
4202  if (!memcmp(buf + 5, "include", 7)) {
4203  do_ssi_include(conn, path, buf + 12, include_level);
4204 #if !defined(NO_POPEN)
4205  } else if (!memcmp(buf + 5, "exec", 4)) {
4206  do_ssi_exec(conn, buf + 9);
4207 #endif /* !NO_POPEN */
4208  } else {
4209  mg_cry(conn, "%s: unknown SSI " "command: \"%s\"", path, buf);
4210  }
4211  }
4212  len = 0;
4213  } else if (in_ssi_tag) {
4214  if (len == 5 && memcmp(buf, "<!--#", 5) != 0) {
4215  /* Not an SSI tag */
4216  in_ssi_tag = 0;
4217  } else if (len == (int) sizeof(buf) - 2) {
4218  mg_cry(conn, "%s: SSI tag is too large", path);
4219  len = 0;
4220  }
4221  buf[len++] = ch & 0xff;
4222  } else if (ch == '<') {
4223  in_ssi_tag = 1;
4224  if (len > 0) {
4225  mg_write(conn, buf, (size_t) len);
4226  }
4227  len = 0;
4228  buf[len++] = ch & 0xff;
4229  } else {
4230  buf[len++] = ch & 0xff;
4231  if (len == (int) sizeof(buf)) {
4232  mg_write(conn, buf, (size_t) len);
4233  len = 0;
4234  }
4235  }
4236  }
4237 
4238  /* Send the rest of buffered data */
4239  if (len > 0) {
4240  mg_write(conn, buf, (size_t) len);
4241  }
4242 }
4243 
4244 static void handle_ssi_file_request(struct mg_connection *conn,
4245  const char *path)
4246 {
4247  struct file file = STRUCT_FILE_INITIALIZER;
4248  char date[64];
4249  time_t curtime = time(NULL);
4250 
4251  if (!mg_fopen(conn, path, "rb", &file)) {
4252  send_http_error(conn, 500, http_500_error, "fopen(%s): %s", path,
4253  strerror(ERRNO));
4254  } else {
4255  conn->must_close = 1;
4256  gmt_time_string(date, sizeof(date), &curtime);
4257  fclose_on_exec(&file, conn);
4258  mg_printf(conn, "HTTP/1.1 200 OK\r\n"
4259  "Date: %s\r\n"
4260  "Content-Type: text/html\r\n"
4261  "Connection: %s\r\n\r\n",
4262  date, suggest_connection_header(conn));
4263  send_ssi_file(conn, path, &file, 0);
4264  mg_fclose(&file);
4265  }
4266 }
4267 
4268 static void send_options(struct mg_connection *conn)
4269 {
4270  char date[64];
4271  time_t curtime = time(NULL);
4272 
4273  conn->status_code = 200;
4274  conn->must_close = 1;
4275  gmt_time_string(date, sizeof(date), &curtime);
4276 
4277  mg_printf(conn, "HTTP/1.1 200 OK\r\n"
4278  "Date: %s\r\n"
4279  "Connection: %s\r\n"
4280  "Allow: GET, POST, HEAD, CONNECT, PUT, DELETE, OPTIONS, PROPFIND, MKCOL\r\n"
4281  "DAV: 1\r\n\r\n",
4282  date, suggest_connection_header(conn));
4283 }
4284 
4285 /* Writes PROPFIND properties for a collection element */
4286 static void print_props(struct mg_connection *conn, const char* uri,
4287  struct file *filep)
4288 {
4289  char mtime[64];
4290  gmt_time_string(mtime, sizeof(mtime), &filep->modification_time);
4291  conn->num_bytes_sent += mg_printf(conn,
4292  "<d:response>"
4293  "<d:href>%s</d:href>"
4294  "<d:propstat>"
4295  "<d:prop>"
4296  "<d:resourcetype>%s</d:resourcetype>"
4297  "<d:getcontentlength>%" INT64_FMT "</d:getcontentlength>"
4298  "<d:getlastmodified>%s</d:getlastmodified>"
4299  "</d:prop>"
4300  "<d:status>HTTP/1.1 200 OK</d:status>"
4301  "</d:propstat>"
4302  "</d:response>\n",
4303  uri,
4304  filep->is_directory ? "<d:collection/>" : "",
4305  filep->size,
4306  mtime);
4307 }
4308 
4309 static void print_dav_dir_entry(struct de *de, void *data)
4310 {
4311  char href[PATH_MAX];
4312  char href_encoded[PATH_MAX];
4313  struct mg_connection *conn = (struct mg_connection *) data;
4314  mg_snprintf(conn, href, sizeof(href), "%s%s",
4315  conn->request_info.uri, de->file_name);
4316  mg_url_encode(href, href_encoded, PATH_MAX-1);
4317  print_props(conn, href_encoded, &de->file);
4318 }
4319 
4320 static void handle_propfind(struct mg_connection *conn, const char *path,
4321  struct file *filep)
4322 {
4323  const char *depth = mg_get_header(conn, "Depth");
4324  char date[64];
4325  time_t curtime = time(NULL);
4326 
4327  gmt_time_string(date, sizeof(date), &curtime);
4328 
4329  conn->must_close = 1;
4330  conn->status_code = 207;
4331  mg_printf(conn, "HTTP/1.1 207 Multi-Status\r\n"
4332  "Date: %s\r\n"
4333  "Connection: %s\r\n"
4334  "Content-Type: text/xml; charset=utf-8\r\n\r\n",
4335  date, suggest_connection_header(conn));
4336 
4337  conn->num_bytes_sent += mg_printf(conn,
4338  "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
4339  "<d:multistatus xmlns:d='DAV:'>\n");
4340 
4341  /* Print properties for the requested resource itself */
4342  print_props(conn, conn->request_info.uri, filep);
4343 
4344  /* If it is a directory, print directory entries too if Depth is not 0 */
4345  if (filep->is_directory &&
4346  !mg_strcasecmp(conn->ctx->config[ENABLE_DIRECTORY_LISTING], "yes") &&
4347  (depth == NULL || strcmp(depth, "0") != 0)) {
4348  scan_directory(conn, path, conn, &print_dav_dir_entry);
4349  }
4350 
4351  conn->num_bytes_sent += mg_printf(conn, "%s\n", "</d:multistatus>");
4352 }
4353 
4354 void mg_lock(struct mg_connection* conn)
4355 {
4356  (void) pthread_mutex_lock(&conn->mutex);
4357 }
4358 
4359 void mg_unlock(struct mg_connection* conn)
4360 {
4361  (void) pthread_mutex_unlock(&conn->mutex);
4362 }
4363 
4364 #ifdef USE_LUA
4365 #include "mod_lua.inl"
4366 #endif /* USE_LUA */
4367 
4368 #if defined(USE_WEBSOCKET)
4369 
4370 /* START OF SHA-1 code
4371  Copyright(c) By Steve Reid <steve@edmweb.com> */
4372 #define SHA1HANDSOFF
4373 #if defined(__sun)
4374 #include "solarisfixes.h"
4375 #endif
4376 
4377 static int is_big_endian(void)
4378 {
4379  static const int n = 1;
4380  return ((char *) &n)[0] == 0;
4381 }
4382 
4383 union char64long16 {
4384  unsigned char c[64];
4385  uint32_t l[16];
4386 };
4387 
4388 #define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
4389 
4390 static uint32_t blk0(union char64long16 *block, int i)
4391 {
4392  /* Forrest: SHA expect BIG_ENDIAN, swap if LITTLE_ENDIAN */
4393  if (!is_big_endian()) {
4394  block->l[i] = (rol(block->l[i], 24) & 0xFF00FF00) |
4395  (rol(block->l[i], 8) & 0x00FF00FF);
4396  }
4397  return block->l[i];
4398 }
4399 
4400 #define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \
4401  ^block->l[(i+2)&15]^block->l[i&15],1))
4402 #define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(block, i)+0x5A827999+rol(v,5);w=rol(w,30);
4403 #define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
4404 #define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
4405 #define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
4406 #define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
4407 
4408 typedef struct {
4409  uint32_t state[5];
4410  uint32_t count[2];
4411  unsigned char buffer[64];
4412 } SHA1_CTX;
4413 
4414 static void SHA1Transform(uint32_t state[5], const unsigned char buffer[64])
4415 {
4416  uint32_t a, b, c, d, e;
4417  union char64long16 block[1];
4418 
4419  memcpy(block, buffer, 64);
4420  a = state[0];
4421  b = state[1];
4422  c = state[2];
4423  d = state[3];
4424  e = state[4];
4425  R0(a,b,c,d,e, 0);
4426  R0(e,a,b,c,d, 1);
4427  R0(d,e,a,b,c, 2);
4428  R0(c,d,e,a,b, 3);
4429  R0(b,c,d,e,a, 4);
4430  R0(a,b,c,d,e, 5);
4431  R0(e,a,b,c,d, 6);
4432  R0(d,e,a,b,c, 7);
4433  R0(c,d,e,a,b, 8);
4434  R0(b,c,d,e,a, 9);
4435  R0(a,b,c,d,e,10);
4436  R0(e,a,b,c,d,11);
4437  R0(d,e,a,b,c,12);
4438  R0(c,d,e,a,b,13);
4439  R0(b,c,d,e,a,14);
4440  R0(a,b,c,d,e,15);
4441  R1(e,a,b,c,d,16);
4442  R1(d,e,a,b,c,17);
4443  R1(c,d,e,a,b,18);
4444  R1(b,c,d,e,a,19);
4445  R2(a,b,c,d,e,20);
4446  R2(e,a,b,c,d,21);
4447  R2(d,e,a,b,c,22);
4448  R2(c,d,e,a,b,23);
4449  R2(b,c,d,e,a,24);
4450  R2(a,b,c,d,e,25);
4451  R2(e,a,b,c,d,26);
4452  R2(d,e,a,b,c,27);
4453  R2(c,d,e,a,b,28);
4454  R2(b,c,d,e,a,29);
4455  R2(a,b,c,d,e,30);
4456  R2(e,a,b,c,d,31);
4457  R2(d,e,a,b,c,32);
4458  R2(c,d,e,a,b,33);
4459  R2(b,c,d,e,a,34);
4460  R2(a,b,c,d,e,35);
4461  R2(e,a,b,c,d,36);
4462  R2(d,e,a,b,c,37);
4463  R2(c,d,e,a,b,38);
4464  R2(b,c,d,e,a,39);
4465  R3(a,b,c,d,e,40);
4466  R3(e,a,b,c,d,41);
4467  R3(d,e,a,b,c,42);
4468  R3(c,d,e,a,b,43);
4469  R3(b,c,d,e,a,44);
4470  R3(a,b,c,d,e,45);
4471  R3(e,a,b,c,d,46);
4472  R3(d,e,a,b,c,47);
4473  R3(c,d,e,a,b,48);
4474  R3(b,c,d,e,a,49);
4475  R3(a,b,c,d,e,50);
4476  R3(e,a,b,c,d,51);
4477  R3(d,e,a,b,c,52);
4478  R3(c,d,e,a,b,53);
4479  R3(b,c,d,e,a,54);
4480  R3(a,b,c,d,e,55);
4481  R3(e,a,b,c,d,56);
4482  R3(d,e,a,b,c,57);
4483  R3(c,d,e,a,b,58);
4484  R3(b,c,d,e,a,59);
4485  R4(a,b,c,d,e,60);
4486  R4(e,a,b,c,d,61);
4487  R4(d,e,a,b,c,62);
4488  R4(c,d,e,a,b,63);
4489  R4(b,c,d,e,a,64);
4490  R4(a,b,c,d,e,65);
4491  R4(e,a,b,c,d,66);
4492  R4(d,e,a,b,c,67);
4493  R4(c,d,e,a,b,68);
4494  R4(b,c,d,e,a,69);
4495  R4(a,b,c,d,e,70);
4496  R4(e,a,b,c,d,71);
4497  R4(d,e,a,b,c,72);
4498  R4(c,d,e,a,b,73);
4499  R4(b,c,d,e,a,74);
4500  R4(a,b,c,d,e,75);
4501  R4(e,a,b,c,d,76);
4502  R4(d,e,a,b,c,77);
4503  R4(c,d,e,a,b,78);
4504  R4(b,c,d,e,a,79);
4505  state[0] += a;
4506  state[1] += b;
4507  state[2] += c;
4508  state[3] += d;
4509  state[4] += e;
4510  a = b = c = d = e = 0;
4511  memset(block, '\0', sizeof(block));
4512 }
4513 
4514 static void SHA1Init(SHA1_CTX* context)
4515 {
4516  context->state[0] = 0x67452301;
4517  context->state[1] = 0xEFCDAB89;
4518  context->state[2] = 0x98BADCFE;
4519  context->state[3] = 0x10325476;
4520  context->state[4] = 0xC3D2E1F0;
4521  context->count[0] = context->count[1] = 0;
4522 }
4523 
4524 static void SHA1Update(SHA1_CTX* context, const unsigned char* data,
4525  uint32_t len)
4526 {
4527  uint32_t i, j;
4528 
4529  j = context->count[0];
4530  if ((context->count[0] += len << 3) < j)
4531  context->count[1]++;
4532  context->count[1] += (len>>29);
4533  j = (j >> 3) & 63;
4534  if ((j + len) > 63) {
4535  memcpy(&context->buffer[j], data, (i = 64-j));
4536  SHA1Transform(context->state, context->buffer);
4537  for ( ; i + 63 < len; i += 64) {
4538  SHA1Transform(context->state, &data[i]);
4539  }
4540  j = 0;
4541  } else i = 0;
4542  memcpy(&context->buffer[j], &data[i], len - i);
4543 }
4544 
4545 static void SHA1Final(unsigned char digest[20], SHA1_CTX* context)
4546 {
4547  unsigned i;
4548  unsigned char finalcount[8], c;
4549 
4550  for (i = 0; i < 8; i++) {
4551  finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)]
4552  >> ((3-(i & 3)) * 8) ) & 255);
4553  }
4554  c = 0200;
4555  SHA1Update(context, &c, 1);
4556  while ((context->count[0] & 504) != 448) {
4557  c = 0000;
4558  SHA1Update(context, &c, 1);
4559  }
4560  SHA1Update(context, finalcount, 8);
4561  for (i = 0; i < 20; i++) {
4562  digest[i] = (unsigned char)
4563  ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
4564  }
4565  memset(context, '\0', sizeof(*context));
4566  memset(&finalcount, '\0', sizeof(finalcount));
4567 }
4568 /* END OF SHA1 CODE */
4569 
4570 static void base64_encode(const unsigned char *src, int src_len, char *dst)
4571 {
4572  static const char *b64 =
4573  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
4574  int i, j, a, b, c;
4575 
4576  for (i = j = 0; i < src_len; i += 3) {
4577  a = src[i];
4578  b = i + 1 >= src_len ? 0 : src[i + 1];
4579  c = i + 2 >= src_len ? 0 : src[i + 2];
4580 
4581  dst[j++] = b64[a >> 2];
4582  dst[j++] = b64[((a & 3) << 4) | (b >> 4)];
4583  if (i + 1 < src_len) {
4584  dst[j++] = b64[(b & 15) << 2 | (c >> 6)];
4585  }
4586  if (i + 2 < src_len) {
4587  dst[j++] = b64[c & 63];
4588  }
4589  }
4590  while (j % 4 != 0) {
4591  dst[j++] = '=';
4592  }
4593  dst[j++] = '\0';
4594 }
4595 
4596 static void send_websocket_handshake(struct mg_connection *conn)
4597 {
4598  static const char *magic = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
4599  char buf[100], sha[20], b64_sha[sizeof(sha) * 2];
4600  SHA1_CTX sha_ctx;
4601 
4602  mg_snprintf(conn, buf, sizeof(buf), "%s%s",
4603  mg_get_header(conn, "Sec-WebSocket-Key"), magic);
4604  SHA1Init(&sha_ctx);
4605  SHA1Update(&sha_ctx, (unsigned char *) buf, (uint32_t)strlen(buf));
4606  SHA1Final((unsigned char *) sha, &sha_ctx);
4607  base64_encode((unsigned char *) sha, sizeof(sha), b64_sha);
4608  mg_printf(conn, "%s%s%s",
4609  "HTTP/1.1 101 Switching Protocols\r\n"
4610  "Upgrade: websocket\r\n"
4611  "Connection: Upgrade\r\n"
4612  "Sec-WebSocket-Accept: ", b64_sha, "\r\n\r\n");
4613 }
4614 
4615 static void read_websocket(struct mg_connection *conn)
4616 {
4617  /* Pointer to the beginning of the portion of the incoming websocket
4618  message queue.
4619  The original websocket upgrade request is never removed, so the queue
4620  begins after it. */
4621  unsigned char *buf = (unsigned char *) conn->buf + conn->request_len;
4622  int n, error;
4623 
4624  /* body_len is the length of the entire queue in bytes
4625  len is the length of the current message
4626  data_len is the length of the current message's data payload
4627  header_len is the length of the current message's header */
4628  size_t i, len, mask_len, data_len, header_len, body_len;
4629 
4630  /* "The masking key is a 32-bit value chosen at random by the client."
4631  http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-17#section-5 */
4632  unsigned char mask[4];
4633 
4634  /* data points to the place where the message is stored when passed to the
4635  websocket_data callback. This is either mem on the stack, or a
4636  dynamically allocated buffer if it is too large. */
4637  char mem[4096];
4638  char *data = mem;
4639  unsigned char mop; /* mask flag and opcode */
4640 
4641  /* Loop continuously, reading messages from the socket, invoking the
4642  callback, and waiting repeatedly until an error occurs. */
4643  assert(conn->content_len == 0);
4644  for (;;) {
4645  header_len = 0;
4646  assert(conn->data_len >= conn->request_len);
4647  if ((body_len = conn->data_len - conn->request_len) >= 2) {
4648  len = buf[1] & 127;
4649  mask_len = buf[1] & 128 ? 4 : 0;
4650  if (len < 126 && body_len >= mask_len) {
4651  data_len = len;
4652  header_len = 2 + mask_len;
4653  } else if (len == 126 && body_len >= 4 + mask_len) {
4654  header_len = 4 + mask_len;
4655  data_len = ((((int) buf[2]) << 8) + buf[3]);
4656  } else if (body_len >= 10 + mask_len) {
4657  header_len = 10 + mask_len;
4658  data_len = (((uint64_t) ntohl(* (uint32_t *) &buf[2])) << 32) +
4659  ntohl(* (uint32_t *) &buf[6]);
4660  }
4661  }
4662 
4663  if (header_len > 0) {
4664  /* Allocate space to hold websocket payload */
4665  data = mem;
4666  if (data_len > sizeof(mem)) {
4667  data = (char *)malloc(data_len);
4668  if (data == NULL) {
4669  /* Allocation failed, exit the loop and then close the
4670  connection */
4671  mg_cry(conn, "websocket malloc() failed; closing connection");
4672  break;
4673  }
4674  }
4675 
4676  /* Copy the mask before we shift the queue and destroy it */
4677  if (mask_len > 0) {
4678  *(uint32_t*)mask = *(uint32_t*)(buf + header_len - mask_len);
4679  } else {
4680  *(uint32_t*)mask = 0;
4681  }
4682 
4683  /* Read frame payload from the first message in the queue into
4684  data and advance the queue by moving the memory in place. */
4685  assert(body_len >= header_len);
4686  if (data_len + header_len > body_len) {
4687  mop = buf[0]; /* current mask and opcode */
4688  /* Overflow case */
4689  len = body_len - header_len;
4690  memcpy(data, buf + header_len, len);
4691  error = 0;
4692  while (len < data_len) {
4693  int n = pull(NULL, conn, data + len, (int)(data_len - len));
4694  if (n < 0) {
4695  error = 1;
4696  break;
4697  }
4698  len += n;
4699  }
4700  if (error) {
4701  mg_cry(conn, "Websocket pull failed; closing connection");
4702  break;
4703  }
4704  conn->data_len = conn->request_len;
4705  } else {
4706  mop = buf[0]; /* current mask and opcode, overwritten by memmove() */
4707  /* Length of the message being read at the front of the
4708  queue */
4709  len = data_len + header_len;
4710 
4711  /* Copy the data payload into the data pointer for the
4712  callback */
4713  memcpy(data, buf + header_len, data_len);
4714 
4715  /* Move the queue forward len bytes */
4716  memmove(buf, buf + len, body_len - len);
4717 
4718  /* Mark the queue as advanced */
4719  conn->data_len -= (int)len;
4720  }
4721 
4722  /* Apply mask if necessary */
4723  if (mask_len > 0) {
4724  for (i = 0; i < data_len; ++i) {
4725  data[i] ^= mask[i & 3];
4726  }
4727  }
4728 
4729  /* Exit the loop if callback signalled to exit,
4730  or "connection close" opcode received. */
4731  if ((conn->ctx->callbacks.websocket_data != NULL &&
4732 #ifdef USE_LUA
4733  (conn->lua_websocket_state == NULL) &&
4734 #endif
4735  !conn->ctx->callbacks.websocket_data(conn, mop, data, data_len)) ||
4736 #ifdef USE_LUA
4737  (conn->lua_websocket_state &&
4738  !lua_websocket_data(conn, mop, data, data_len)) ||
4739 #endif
4740  (buf[0] & 0xf) == WEBSOCKET_OPCODE_CONNECTION_CLOSE) { /* Opcode == 8, connection close */
4741  break;
4742  }
4743 
4744  if (data != mem) {
4745  free(data);
4746  }
4747  /* Not breaking the loop, process next websocket frame. */
4748  } else {
4749  /* Read from the socket into the next available location in the
4750  message queue. */
4751  if ((n = pull(NULL, conn, conn->buf + conn->data_len,
4752  conn->buf_size - conn->data_len)) <= 0) {
4753  /* Error, no bytes read */
4754  break;
4755  }
4756  conn->data_len += n;
4757  }
4758  }
4759 }
4760 
4761 int mg_websocket_write(struct mg_connection* conn, int opcode, const char* data, size_t dataLen)
4762 {
4763  unsigned char header[10];
4764  size_t headerLen = 1;
4765 
4766  int retval = -1;
4767 
4768  header[0] = 0x80 + (opcode & 0xF);
4769 
4770  /* Frame format: http://tools.ietf.org/html/rfc6455#section-5.2 */
4771  if (dataLen < 126) {
4772  /* inline 7-bit length field */
4773  header[1] = (unsigned char)dataLen;
4774  headerLen = 2;
4775  } else if (dataLen <= 0xFFFF) {
4776  /* 16-bit length field */
4777  header[1] = 126;
4778  *(uint16_t*)(header + 2) = htons((uint16_t)dataLen);
4779  headerLen = 4;
4780  } else {
4781  /* 64-bit length field */
4782  header[1] = 127;
4783  *(uint32_t*)(header + 2) = htonl((uint64_t)dataLen >> 32);
4784  *(uint32_t*)(header + 6) = htonl(dataLen & 0xFFFFFFFF);
4785  headerLen = 10;
4786  }
4787 
4788  /* Note that POSIX/Winsock's send() is threadsafe
4789  http://stackoverflow.com/questions/1981372/are-parallel-calls-to-send-recv-on-the-same-socket-valid
4790  but mongoose's mg_printf/mg_write is not (because of the loop in
4791  push(), although that is only a problem if the packet is large or
4792  outgoing buffer is full). */
4793  (void) mg_lock(conn);
4794  retval = mg_write(conn, header, headerLen);
4795  retval = mg_write(conn, data, dataLen);
4796  mg_unlock(conn);
4797 
4798  return retval;
4799 }
4800 
4801 static void handle_websocket_request(struct mg_connection *conn, const char *path, int is_script_resource)
4802 {
4803  const char *version = mg_get_header(conn, "Sec-WebSocket-Version");
4804 #ifdef USE_LUA
4805  int lua_websock, shared_lua_websock = 0;
4806  /* TODO: A websocket script may be shared between several clients, allowing them to communicate
4807  directly instead of writing to a data base and polling the data base. */
4808 #endif
4809 
4810  if (version == NULL || strcmp(version, "13") != 0) {
4811  send_http_error(conn, 426, "Upgrade Required", "%s", "Upgrade Required");
4812  } else if (conn->ctx->callbacks.websocket_connect != NULL &&
4813  conn->ctx->callbacks.websocket_connect(conn) != 0) {
4814  /* C callback has returned non-zero, do not proceed with handshake. */
4815  /* The C callback is called before Lua and may prevent Lua from handling the websocket. */
4816  } else {
4817 #ifdef USE_LUA
4818  lua_websock = conn->ctx->config[LUA_WEBSOCKET_EXTENSIONS] ?
4819  match_prefix(conn->ctx->config[LUA_WEBSOCKET_EXTENSIONS],
4820  (int)strlen(conn->ctx->config[LUA_WEBSOCKET_EXTENSIONS]),
4821  path) : 0;
4822 
4823  if (lua_websock || shared_lua_websock) {
4824  conn->lua_websocket_state = lua_websocket_new(path, conn, !!shared_lua_websock);
4825  if (conn->lua_websocket_state) {
4826  send_websocket_handshake(conn);
4827  if (lua_websocket_ready(conn)) {
4828  read_websocket(conn);
4829  }
4830  }
4831  } else
4832 #endif
4833  {
4834  /* No Lua websock script specified. */
4835  send_websocket_handshake(conn);
4836  if (conn->ctx->callbacks.websocket_ready != NULL) {
4837  conn->ctx->callbacks.websocket_ready(conn);
4838  }
4839  read_websocket(conn);
4840  }
4841  }
4842 }
4843 
4844 static int is_websocket_request(const struct mg_connection *conn)
4845 {
4846  const char *host, *upgrade, *connection, *version, *key;
4847 
4848  host = mg_get_header(conn, "Host");
4849  upgrade = mg_get_header(conn, "Upgrade");
4850  connection = mg_get_header(conn, "Connection");
4851  key = mg_get_header(conn, "Sec-WebSocket-Key");
4852  version = mg_get_header(conn, "Sec-WebSocket-Version");
4853 
4854  return host != NULL && upgrade != NULL && connection != NULL &&
4855  key != NULL && version != NULL &&
4856  mg_strcasestr(upgrade, "websocket") != NULL &&
4857  mg_strcasestr(connection, "Upgrade") != NULL;
4858 }
4859 #endif /* !USE_WEBSOCKET */
4860 
4861 static int isbyte(int n)
4862 {
4863  return n >= 0 && n <= 255;
4864 }
4865 
4866 static int parse_net(const char *spec, uint32_t *net, uint32_t *mask)
4867 {
4868  int n, a, b, c, d, slash = 32, len = 0;
4869 
4870  if ((sscanf(spec, "%d.%d.%d.%d/%d%n", &a, &b, &c, &d, &slash, &n) == 5 ||
4871  sscanf(spec, "%d.%d.%d.%d%n", &a, &b, &c, &d, &n) == 4) &&
4872  isbyte(a) && isbyte(b) && isbyte(c) && isbyte(d) &&
4873  slash >= 0 && slash < 33) {
4874  len = n;
4875  *net = ((uint32_t)a << 24) | ((uint32_t)b << 16) | ((uint32_t)c << 8) | d;
4876  *mask = slash ? 0xffffffffU << (32 - slash) : 0;
4877  }
4878 
4879  return len;
4880 }
4881 
4882 static int set_throttle(const char *spec, uint32_t remote_ip, const char *uri)
4883 {
4884  int throttle = 0;
4885  struct vec vec, val;
4886  uint32_t net, mask;
4887  char mult;
4888  double v;
4889 
4890  while ((spec = next_option(spec, &vec, &val)) != NULL) {
4891  mult = ',';
4892  if (sscanf(val.ptr, "%lf%c", &v, &mult) < 1 || v < 0 ||
4893  (lowercase(&mult) != 'k' && lowercase(&mult) != 'm' && mult != ',')) {
4894  continue;
4895  }
4896  v *= lowercase(&mult) == 'k' ? 1024 : lowercase(&mult) == 'm' ? 1048576 : 1;
4897  if (vec.len == 1 && vec.ptr[0] == '*') {
4898  throttle = (int) v;
4899  } else if (parse_net(vec.ptr, &net, &mask) > 0) {
4900  if ((remote_ip & mask) == net) {
4901  throttle = (int) v;
4902  }
4903  } else if (match_prefix(vec.ptr, (int)vec.len, uri) > 0) {
4904  throttle = (int) v;
4905  }
4906  }
4907 
4908  return throttle;
4909 }
4910 
4911 static uint32_t get_remote_ip(const struct mg_connection *conn)
4912 {
4913  return ntohl(* (uint32_t *) &conn->client.rsa.sin.sin_addr);
4914 }
4915 
4916 int mg_upload(struct mg_connection *conn, const char *destination_dir)
4917 {
4918  const char *content_type_header, *boundary_start;
4919  char buf[MG_BUF_LEN], path[PATH_MAX], fname[1024], boundary[100], *s;
4920  FILE *fp;
4921  int bl, n, i, j, headers_len, boundary_len, eof,
4922  len = 0, num_uploaded_files = 0;
4923 
4924  /* Request looks like this:
4925 
4926  POST /upload HTTP/1.1
4927  Host: 127.0.0.1:8080
4928  Content-Length: 244894
4929  Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryRVr
4930 
4931  ------WebKitFormBoundaryRVr
4932  Content-Disposition: form-data; name="file"; filename="accum.png"
4933  Content-Type: image/png
4934 
4935  <89>PNG
4936  <PNG DATA>
4937  ------WebKitFormBoundaryRVr */
4938 
4939  /* Extract boundary string from the Content-Type header */
4940  if ((content_type_header = mg_get_header(conn, "Content-Type")) == NULL ||
4941  (boundary_start = mg_strcasestr(content_type_header,
4942  "boundary=")) == NULL ||
4943  (sscanf(boundary_start, "boundary=\"%99[^\"]\"", boundary) == 0 &&
4944  sscanf(boundary_start, "boundary=%99s", boundary) == 0) ||
4945  boundary[0] == '\0') {
4946  return num_uploaded_files;
4947  }
4948 
4949  boundary_len = (int)strlen(boundary);
4950  bl = boundary_len + 4; /* \r\n--<boundary> */
4951  for (;;) {
4952  /* Pull in headers */
4953  assert(len >= 0 && len <= (int) sizeof(buf));
4954  while ((n = mg_read(conn, buf + len, sizeof(buf) - len)) > 0) {
4955  len += n;
4956  }
4957  if ((headers_len = get_request_len(buf, len)) <= 0) {
4958  break;
4959  }
4960 
4961  /* Fetch file name. */
4962  fname[0] = '\0';
4963  for (i = j = 0; i < headers_len; i++) {
4964  if (buf[i] == '\r' && buf[i + 1] == '\n') {
4965  buf[i] = buf[i + 1] = '\0';
4966  /* TODO(lsm): don't expect filename to be the 3rd field,
4967  parse the header properly instead. */
4968  IGNORE_UNUSED_RESULT(sscanf(&buf[j], "Content-Disposition: %*s %*s filename=\"%1023[^\"]",
4969  fname));
4970  j = i + 2;
4971  }
4972  }
4973 
4974  /* Give up if the headers are not what we expect */
4975  if (fname[0] == '\0') {
4976  break;
4977  }
4978 
4979  /* Move data to the beginning of the buffer */
4980  assert(len >= headers_len);
4981  memmove(buf, &buf[headers_len], len - headers_len);
4982  len -= headers_len;
4983 
4984  /* We open the file with exclusive lock held. This guarantee us
4985  there is no other thread can save into the same file
4986  simultaneously. */
4987  fp = NULL;
4988  /* Construct destination file name. Do not allow paths to have
4989  slashes. */
4990  if ((s = strrchr(fname, '/')) == NULL &&
4991  (s = strrchr(fname, '\\')) == NULL) {
4992  s = fname;
4993  }
4994 
4995  /* Open file in binary mode. TODO: set an exclusive lock. */
4996  snprintf(path, sizeof(path), "%s/%s", destination_dir, s);
4997  if ((fp = fopen(path, "wb")) == NULL) {
4998  break;
4999  }
5000 
5001  /* Read POST data, write into file until boundary is found. */
5002  eof = n = 0;
5003  do {
5004  len += n;
5005  for (i = 0; i < len - bl; i++) {
5006  if (!memcmp(&buf[i], "\r\n--", 4) &&
5007  !memcmp(&buf[i + 4], boundary, boundary_len)) {
5008  /* Found boundary, that's the end of file data. */
5009  fwrite(buf, 1, i, fp);
5010  eof = 1;
5011  memmove(buf, &buf[i + bl], len - (i + bl));
5012  len -= i + bl;
5013  break;
5014  }
5015  }
5016  if (!eof && len > bl) {
5017  fwrite(buf, 1, len - bl, fp);
5018  memmove(buf, &buf[len - bl], bl);
5019  len = bl;
5020  }
5021  } while (!eof && (n = mg_read(conn, buf + len, sizeof(buf) - len)) > 0);
5022  fclose(fp);
5023  if (eof) {
5024  num_uploaded_files++;
5025  if (conn->ctx->callbacks.upload != NULL) {
5026  conn->ctx->callbacks.upload(conn, path);
5027  }
5028  }
5029  }
5030 
5031  return num_uploaded_files;
5032 }
5033 
5034 static int is_put_or_delete_request(const struct mg_connection *conn)
5035 {
5036  const char *s = conn->request_info.request_method;
5037  return s != NULL && (!strcmp(s, "PUT") ||
5038  !strcmp(s, "DELETE") ||
5039  !strcmp(s, "MKCOL"));
5040 }
5041 
5042 static int get_first_ssl_listener_index(const struct mg_context *ctx)
5043 {
5044  int i, idx = -1;
5045  for (i = 0; idx == -1 && i < ctx->num_listening_sockets; i++) {
5046  idx = ctx->listening_sockets[i].is_ssl ? i : -1;
5047  }
5048  return idx;
5049 }
5050 
5051 static void redirect_to_https_port(struct mg_connection *conn, int ssl_index)
5052 {
5053  char host[1025];
5054  const char *host_header;
5055  size_t hostlen;
5056 
5057  host_header = mg_get_header(conn, "Host");
5058  hostlen = sizeof(host);
5059  if (host_header != NULL) {
5060  char *pos;
5061 
5062  strncpy(host, host_header, hostlen);
5063  host[hostlen - 1] = '\0';
5064  pos = strchr(host, ':');
5065  if (pos != NULL) {
5066  *pos = '\0';
5067  }
5068  } else {
5069  /* Cannot get host from the Host: header.
5070  Fallback to our IP address. */
5071  sockaddr_to_string(host, hostlen, &conn->client.lsa);
5072  }
5073 
5074  mg_printf(conn, "HTTP/1.1 302 Found\r\nLocation: https://%s:%d%s\r\n\r\n",
5075  host, (int) ntohs(conn->ctx->listening_sockets[ssl_index].
5076  lsa.sin.sin_port), conn->request_info.uri);
5077 }
5078 
5079 
5080 void mg_set_request_handler(struct mg_context *ctx, const char *uri, mg_request_handler handler, void *cbdata)
5081 {
5082  struct mg_request_handler_info *tmp_rh, *lastref = 0;
5083  size_t urilen = strlen(uri);
5084 
5085  /* first see it the uri exists */
5086  for (tmp_rh = ctx->request_handlers;
5087  tmp_rh != NULL && strcmp(uri, tmp_rh->uri);
5088  lastref = tmp_rh, tmp_rh = tmp_rh->next) {
5089  /* first try for an exact match */
5090  if (urilen == tmp_rh->uri_len && !strcmp(tmp_rh->uri,uri)) {
5091  /* already there... */
5092 
5093  if (handler != NULL) {
5094  /* change this entry */
5095  tmp_rh->handler = handler;
5096  tmp_rh->cbdata = cbdata;
5097  } else {
5098  /* remove this entry */
5099  if (lastref != NULL)
5100  lastref->next = tmp_rh->next;
5101  else
5102  ctx->request_handlers = tmp_rh->next;
5103  free(tmp_rh->uri);
5104  free(tmp_rh);
5105  }
5106  return;
5107  }
5108 
5109  /* next try for a partial match, we will accept uri/something */
5110  if (tmp_rh->uri_len < urilen
5111  && uri[tmp_rh->uri_len] == '/'
5112  && memcmp(tmp_rh->uri, uri, tmp_rh->uri_len) == 0) {
5113  /* if there is a partical match this new entry MUST go BEFORE
5114  the current position otherwise it will never be matched. */
5115  break;
5116  }
5117 
5118  }
5119 
5120  if (handler == NULL) {
5121  /* no handler to set, this was a remove request */
5122  return;
5123  }
5124 
5125  tmp_rh = (struct mg_request_handler_info *)malloc(sizeof(struct mg_request_handler_info));
5126  if (tmp_rh == NULL) {
5127  mg_cry(fc(ctx), "%s", "Cannot create new request handler struct, OOM");
5128  return;
5129  }
5130  tmp_rh->uri = mg_strdup(uri);
5131  tmp_rh->uri_len = strlen(uri);
5132  tmp_rh->handler = handler;
5133  tmp_rh->cbdata = cbdata;
5134 
5135  if (lastref == NULL) {
5136  tmp_rh->next = ctx->request_handlers;
5137  ctx->request_handlers = tmp_rh;
5138  } else {
5139  tmp_rh->next = lastref->next;
5140  lastref->next = tmp_rh;
5141  }
5142 
5143 }
5144 
5145 static int use_request_handler(struct mg_connection *conn)
5146 {
5147  struct mg_request_info *request_info = mg_get_request_info(conn);
5148  const char *uri = request_info->uri;
5149  size_t urilen = strlen(uri);
5150  struct mg_request_handler_info *tmp_rh = conn->ctx->request_handlers;
5151 
5152  for (; tmp_rh != NULL; tmp_rh = tmp_rh->next) {
5153 
5154  /* first try for an exact match */
5155  if (urilen == tmp_rh->uri_len && !strcmp(tmp_rh->uri,uri)) {
5156  return tmp_rh->handler(conn, tmp_rh->cbdata);
5157  }
5158 
5159  /* next try for a partial match */
5160  /* we will accept uri/something */
5161  if (tmp_rh->uri_len < urilen
5162  && uri[tmp_rh->uri_len] == '/'
5163  && memcmp(tmp_rh->uri, uri, tmp_rh->uri_len) == 0) {
5164 
5165  return tmp_rh->handler(conn, tmp_rh->cbdata);
5166  }
5167 
5168  /* try for pattern match */
5169  if (match_prefix(tmp_rh->uri, tmp_rh->uri_len, uri) > 0) {
5170  return tmp_rh->handler(conn, tmp_rh->cbdata);
5171  }
5172 
5173  }
5174 
5175  return 0; /* none found */
5176 }
5177 
5178 /* This is the heart of the Civetweb's logic.
5179  This function is called when the request is read, parsed and validated,
5180  and Civetweb must decide what action to take: serve a file, or
5181  a directory, or call embedded function, etcetera. */
5182 static void handle_request(struct mg_connection *conn)
5183 {
5184  struct mg_request_info *ri = &conn->request_info;
5185  char path[PATH_MAX];
5186  int uri_len, ssl_index, is_script_resource;
5187  struct file file = STRUCT_FILE_INITIALIZER;
5188  char date[64];
5189  time_t curtime = time(NULL);
5190 
5191  if ((conn->request_info.query_string = strchr(ri->uri, '?')) != NULL) {
5192  * ((char *) conn->request_info.query_string++) = '\0';
5193  }
5194  uri_len = (int) strlen(ri->uri);
5195  mg_url_decode(ri->uri, uri_len, (char *) ri->uri, uri_len + 1, 0);
5196  remove_double_dots_and_double_slashes((char *) ri->uri);
5197  path[0] = '\0';
5198  convert_uri_to_file_name(conn, path, sizeof(path), &file, &is_script_resource);
5199  conn->throttle = set_throttle(conn->ctx->config[THROTTLE],
5200  get_remote_ip(conn), ri->uri);
5201 
5202  DEBUG_TRACE(("%s", ri->uri));
5203  /* Perform redirect and auth checks before calling begin_request() handler.
5204  Otherwise, begin_request() would need to perform auth checks and
5205  redirects. */
5206  if (!conn->client.is_ssl && conn->client.ssl_redir &&
5207  (ssl_index = get_first_ssl_listener_index(conn->ctx)) > -1) {
5208  redirect_to_https_port(conn, ssl_index);
5209  } else if (!is_script_resource && !is_put_or_delete_request(conn) &&
5210  !check_authorization(conn, path)) {
5211  send_authorization_request(conn);
5212  } else if (conn->ctx->callbacks.begin_request != NULL &&
5213  conn->ctx->callbacks.begin_request(conn)) {
5214  /* Do nothing, callback has served the request */
5215 #if defined(USE_WEBSOCKET)
5216  } else if (is_websocket_request(conn)) {
5217  handle_websocket_request(conn, path, is_script_resource);
5218 #endif
5219  } else if (conn->ctx->request_handlers != NULL &&
5220  use_request_handler(conn)) {
5221  /* Do nothing, callback has served the request */
5222  } else if (!is_script_resource && !strcmp(ri->request_method, "OPTIONS")) {
5223  send_options(conn);
5224  } else if (conn->ctx->config[DOCUMENT_ROOT] == NULL) {
5225  send_http_error(conn, 404, "Not Found", "Not Found");
5226  } else if (!is_script_resource && is_put_or_delete_request(conn) &&
5227  (is_authorized_for_put(conn) != 1)) {
5228  send_authorization_request(conn);
5229  } else if (!is_script_resource && !strcmp(ri->request_method, "PUT")) {
5230  put_file(conn, path);
5231  } else if (!is_script_resource && !strcmp(ri->request_method, "MKCOL")) {
5232  mkcol(conn, path);
5233  } else if (!is_script_resource && !strcmp(ri->request_method, "DELETE")) {
5234  struct de de;
5235  memset(&de.file, 0, sizeof(de.file));
5236  if(!mg_stat(conn, path, &de.file)) {
5237  send_http_error(conn, 404, "Not Found", "%s", "File not found");
5238  } else {
5239  if(de.file.modification_time) {
5240  if(de.file.is_directory) {
5241  remove_directory(conn, path);
5242  send_http_error(conn, 204, "No Content", "%s", "");
5243  } else if (mg_remove(path) == 0) {
5244  send_http_error(conn, 204, "No Content", "%s", "");
5245  } else {
5246  send_http_error(conn, 423, "Locked", "remove(%s): %s", path,
5247  strerror(ERRNO));
5248  }
5249  } else {
5250  send_http_error(conn, 500, http_500_error, "remove(%s): %s", path,
5251  strerror(ERRNO));
5252  }
5253  }
5254  } else if ((file.membuf == NULL && file.modification_time == (time_t) 0) ||
5255  must_hide_file(conn, path)) {
5256  send_http_error(conn, 404, "Not Found", "%s", "File not found");
5257  } else if (file.is_directory && ri->uri[uri_len - 1] != '/') {
5258  gmt_time_string(date, sizeof(date), &curtime);
5259  mg_printf(conn, "HTTP/1.1 301 Moved Permanently\r\n"
5260  "Location: %s/\r\n"
5261  "Date: %s\r\n"
5262  "Content-Length: 0\r\n"
5263  "Connection: %s\r\n\r\n",
5264  ri->uri, date, suggest_connection_header(conn));
5265  } else if (!is_script_resource && !strcmp(ri->request_method, "PROPFIND")) {
5266  handle_propfind(conn, path, &file);
5267  } else if (file.is_directory &&
5268  !substitute_index_file(conn, path, sizeof(path), &file)) {
5269  if (!mg_strcasecmp(conn->ctx->config[ENABLE_DIRECTORY_LISTING], "yes")) {
5270  handle_directory_request(conn, path);
5271  } else {
5272  send_http_error(conn, 403, "Directory Listing Denied",
5273  "Directory listing denied");
5274  }
5275 #ifdef USE_LUA
5276  } else if (match_prefix(conn->ctx->config[LUA_SERVER_PAGE_EXTENSIONS],
5277  (int)strlen(conn->ctx->config[LUA_SERVER_PAGE_EXTENSIONS]),
5278  path) > 0) {
5279  /* Lua server page: an SSI like page containing mostly plain html code plus some tags with server generated contents. */
5280  handle_lsp_request(conn, path, &file, NULL);
5281  } else if (match_prefix(conn->ctx->config[LUA_SCRIPT_EXTENSIONS],
5282  (int)strlen(conn->ctx->config[LUA_SCRIPT_EXTENSIONS]),
5283  path) > 0) {
5284  /* Lua in-server module script: a CGI like script used to generate the entire reply. */
5285  mg_exec_lua_script(conn, path, NULL);
5286 #endif
5287 #if !defined(NO_CGI)
5288  } else if (match_prefix(conn->ctx->config[CGI_EXTENSIONS],
5289  (int)strlen(conn->ctx->config[CGI_EXTENSIONS]),
5290  path) > 0) {
5291  /* TODO: check unsupported methods -> 501
5292  if (strcmp(ri->request_method, "POST") &&
5293  strcmp(ri->request_method, "HEAD") &&
5294  strcmp(ri->request_method, "GET")) {
5295  send_http_error(conn, 501, "Not Implemented",
5296  "Method %s is not implemented", ri->request_method);
5297  } else {
5298  handle_cgi_request(conn, path);
5299  } */
5300  handle_cgi_request(conn, path);
5301 #endif /* !NO_CGI */
5302  } else if (match_prefix(conn->ctx->config[SSI_EXTENSIONS],
5303  (int)strlen(conn->ctx->config[SSI_EXTENSIONS]),
5304  path) > 0) {
5305  handle_ssi_file_request(conn, path);
5306  } else if (is_not_modified(conn, &file)) {
5307  send_http_error(conn, 304, "Not Modified", "%s", "");
5308  } else {
5309  handle_file_request(conn, path, &file);
5310  }
5311 }
5312 
5313 static void close_all_listening_sockets(struct mg_context *ctx)
5314 {
5315  int i;
5316  for (i = 0; i < ctx->num_listening_sockets; i++) {
5317  closesocket(ctx->listening_sockets[i].sock);
5318  }
5319  free(ctx->listening_sockets);
5320 }
5321 
5322 static int is_valid_port(unsigned int port)
5323 {
5324  return port < 0xffff;
5325 }
5326 
5327 /* Valid listening port specification is: [ip_address:]port[s]
5328  Examples: 80, 443s, 127.0.0.1:3128, 1.2.3.4:8080s
5329  TODO(lsm): add parsing of the IPv6 address */
5330 static int parse_port_string(const struct vec *vec, struct socket *so)
5331 {
5332  unsigned int a, b, c, d, ch, len, port;
5333 #if defined(USE_IPV6)
5334  char buf[100];
5335 #endif
5336 
5337  /* MacOS needs that. If we do not zero it, subsequent bind() will fail.
5338  Also, all-zeroes in the socket address means binding to all addresses
5339  for both IPv4 and IPv6 (INADDR_ANY and IN6ADDR_ANY_INIT). */
5340  memset(so, 0, sizeof(*so));
5341  so->lsa.sin.sin_family = AF_INET;
5342 
5343  if (sscanf(vec->ptr, "%u.%u.%u.%u:%u%n", &a, &b, &c, &d, &port, &len) == 5) {
5344  /* Bind to a specific IPv4 address, e.g. 192.168.1.5:8080 */
5345  so->lsa.sin.sin_addr.s_addr = htonl((a << 24) | (b << 16) | (c << 8) | d);
5346  so->lsa.sin.sin_port = htons((uint16_t) port);
5347 #if defined(USE_IPV6)
5348 
5349  } else if (sscanf(vec->ptr, "[%49[^]]]:%d%n", buf, &port, &len) == 2 &&
5350  inet_pton(AF_INET6, buf, &so->lsa.sin6.sin6_addr)) {
5351  /* IPv6 address, e.g. [3ffe:2a00:100:7031::1]:8080 */
5352  so->lsa.sin6.sin6_family = AF_INET6;
5353  so->lsa.sin6.sin6_port = htons((uint16_t) port);
5354 #endif
5355  } else if (sscanf(vec->ptr, "%u%n", &port, &len) == 1) {
5356  /* If only port is specified, bind to IPv4, INADDR_ANY */
5357  so->lsa.sin.sin_port = htons((uint16_t) port);
5358  } else {
5359  port = len = 0; /* Parsing failure. Make port invalid. */
5360  }
5361 
5362  ch = vec->ptr[len]; /* Next character after the port number */
5363  so->is_ssl = ch == 's';
5364  so->ssl_redir = ch == 'r';
5365 
5366  /* Make sure the port is valid and vector ends with 's', 'r' or ',' */
5367  return is_valid_port(port) &&
5368  (ch == '\0' || ch == 's' || ch == 'r' || ch == ',');
5369 }
5370 
5371 static int set_ports_option(struct mg_context *ctx)
5372 {
5373  const char *list = ctx->config[LISTENING_PORTS];
5374  int on = 1, success = 1;
5375 #if defined(USE_IPV6)
5376  int off = 0;
5377 #endif
5378  struct vec vec;
5379  struct socket so, *ptr;
5380 
5381  in_port_t *portPtr;
5382  struct sockaddr_in sin;
5383  socklen_t len;
5384 
5385  memset(&sin, 0, sizeof(sin));
5386  len = sizeof(sin);
5387 
5388  while (success && (list = next_option(list, &vec, NULL)) != NULL) {
5389  if (!parse_port_string(&vec, &so)) {
5390  mg_cry(fc(ctx), "%s: %.*s: invalid port spec. Expecting list of: %s",
5391  __func__, (int) vec.len, vec.ptr, "[IP_ADDRESS:]PORT[s|r]");
5392  success = 0;
5393  } else if (so.is_ssl && ctx->ssl_ctx == NULL) {
5394  mg_cry(fc(ctx), "Cannot add SSL socket, is -ssl_certificate option set?");
5395  success = 0;
5396  } else if ((so.sock = socket(so.lsa.sa.sa_family, SOCK_STREAM, 6)) ==
5397  INVALID_SOCKET ||
5398  /* On Windows, SO_REUSEADDR is recommended only for
5399  broadcast UDP sockets */
5400  setsockopt(so.sock, SOL_SOCKET, SO_REUSEADDR,
5401  (const char *) &on, sizeof(on)) != 0 ||
5402 #if defined(USE_IPV6)
5403  (so.lsa.sa.sa_family == AF_INET6 &&
5404  setsockopt(so.sock, IPPROTO_IPV6, IPV6_V6ONLY, (void *) &off,
5405  sizeof(off)) != 0) ||
5406 #endif
5407  bind(so.sock, &so.lsa.sa, so.lsa.sa.sa_family == AF_INET ?
5408  sizeof(so.lsa.sin) : sizeof(so.lsa)) != 0 ||
5409  listen(so.sock, SOMAXCONN) != 0 ||
5410  getsockname(so.sock, (struct sockaddr *)&sin, &len) != 0) {
5411  mg_cry(fc(ctx), "%s: cannot bind to %.*s: %d (%s)", __func__,
5412  (int) vec.len, vec.ptr, ERRNO, strerror(errno));
5413  if (so.sock != INVALID_SOCKET) {
5414  closesocket(so.sock);
5415  }
5416  success = 0;
5417  } else if ((ptr = (struct socket *) realloc(ctx->listening_sockets,
5418  (ctx->num_listening_sockets + 1) *
5419  sizeof(ctx->listening_sockets[0]))) == NULL) {
5420  closesocket(so.sock);
5421  success = 0;
5422  } else if ((portPtr = (in_port_t*) realloc(ctx->listening_ports,
5423  (ctx->num_listening_sockets + 1) *
5424  sizeof(ctx->listening_ports[0]))) == NULL) {
5425  closesocket(so.sock);
5426  success = 0;
5427  }
5428  else {
5429  set_close_on_exec(so.sock, fc(ctx));
5430  ctx->listening_sockets = ptr;
5431  ctx->listening_sockets[ctx->num_listening_sockets] = so;
5432  ctx->listening_ports = portPtr;
5433  ctx->listening_ports[ctx->num_listening_sockets] = ntohs(sin.sin_port);
5434  ctx->num_listening_sockets++;
5435  }
5436  }
5437 
5438  if (!success) {
5439  close_all_listening_sockets(ctx);
5440  }
5441 
5442  return success;
5443 }
5444 
5445 static void log_header(const struct mg_connection *conn, const char *header,
5446  FILE *fp)
5447 {
5448  const char *header_value;
5449 
5450  if ((header_value = mg_get_header(conn, header)) == NULL) {
5451  (void) fprintf(fp, "%s", " -");
5452  } else {
5453  (void) fprintf(fp, " \"%s\"", header_value);
5454  }
5455 }
5456 
5457 static void log_access(const struct mg_connection *conn)
5458 {
5459  const struct mg_request_info *ri;
5460  FILE *fp;
5461  char date[64], src_addr[IP_ADDR_STR_LEN];
5462  struct tm *tm;
5463 
5464  fp = conn->ctx->config[ACCESS_LOG_FILE] == NULL ? NULL :
5465  fopen(conn->ctx->config[ACCESS_LOG_FILE], "a+");
5466 
5467  if (fp == NULL)
5468  return;
5469 
5470  tm = localtime(&conn->birth_time);
5471  if (tm != NULL) {
5472  strftime(date, sizeof(date), "%d/%b/%Y:%H:%M:%S %z", tm);
5473  } else {
5474  strncpy(date, "01/Jan/1970:00:00:00 +0000", sizeof(date));
5475  date[sizeof(date) - 1] = '\0';
5476  }
5477 
5478  ri = &conn->request_info;
5479  flockfile(fp);
5480 
5481  sockaddr_to_string(src_addr, sizeof(src_addr), &conn->client.rsa);
5482  fprintf(fp, "%s - %s [%s] \"%s %s HTTP/%s\" %d %" INT64_FMT,
5483  src_addr, ri->remote_user == NULL ? "-" : ri->remote_user, date,
5484  ri->request_method ? ri->request_method : "-",
5485  ri->uri ? ri->uri : "-", ri->http_version,
5486  conn->status_code, conn->num_bytes_sent);
5487  log_header(conn, "Referer", fp);
5488  log_header(conn, "User-Agent", fp);
5489  fputc('\n', fp);
5490  fflush(fp);
5491 
5492  funlockfile(fp);
5493  fclose(fp);
5494 }
5495 
5496 /* Verify given socket address against the ACL.
5497  Return -1 if ACL is malformed, 0 if address is disallowed, 1 if allowed. */
5498 static int check_acl(struct mg_context *ctx, uint32_t remote_ip)
5499 {
5500  int allowed, flag;
5501  uint32_t net, mask;
5502  struct vec vec;
5503  const char *list = ctx->config[ACCESS_CONTROL_LIST];
5504 
5505  /* If any ACL is set, deny by default */
5506  allowed = list == NULL ? '+' : '-';
5507 
5508  while ((list = next_option(list, &vec, NULL)) != NULL) {
5509  flag = vec.ptr[0];
5510  if ((flag != '+' && flag != '-') ||
5511  parse_net(&vec.ptr[1], &net, &mask) == 0) {
5512  mg_cry(fc(ctx), "%s: subnet must be [+|-]x.x.x.x[/x]", __func__);
5513  return -1;
5514  }
5515 
5516  if (net == (remote_ip & mask)) {
5517  allowed = flag;
5518  }
5519  }
5520 
5521  return allowed == '+';
5522 }
5523 
5524 #if !defined(_WIN32)
5525 static int set_uid_option(struct mg_context *ctx)
5526 {
5527  struct passwd *pw;
5528  const char *uid = ctx->config[RUN_AS_USER];
5529  int success = 0;
5530 
5531  if (uid == NULL) {
5532  success = 1;
5533  } else {
5534  if ((pw = getpwnam(uid)) == NULL) {
5535  mg_cry(fc(ctx), "%s: unknown user [%s]", __func__, uid);
5536  } else if (setgid(pw->pw_gid) == -1) {
5537  mg_cry(fc(ctx), "%s: setgid(%s): %s", __func__, uid, strerror(errno));
5538  } else if (setuid(pw->pw_uid) == -1) {
5539  mg_cry(fc(ctx), "%s: setuid(%s): %s", __func__, uid, strerror(errno));
5540  } else {
5541  success = 1;
5542  }
5543  }
5544 
5545  return success;
5546 }
5547 #endif /* !_WIN32 */
5548 
5549 #if !defined(NO_SSL)
5550 static pthread_mutex_t *ssl_mutexes;
5551 
5552 static int sslize(struct mg_connection *conn, SSL_CTX *s, int (*func)(SSL *))
5553 {
5554  return (conn->ssl = SSL_new(s)) != NULL &&
5555  SSL_set_fd(conn->ssl, conn->client.sock) == 1 &&
5556  func(conn->ssl) == 1;
5557 }
5558 
5559 /* Return OpenSSL error message */
5560 static const char *ssl_error(void)
5561 {
5562  unsigned long err;
5563  err = ERR_get_error();
5564  return err == 0 ? "" : ERR_error_string(err, NULL);
5565 }
5566 
5567 static void ssl_locking_callback(int mode, int mutex_num, const char *file,
5568  int line)
5569 {
5570  (void) line;
5571  (void) file;
5572 
5573  if (mode & 1) { /* 1 is CRYPTO_LOCK */
5574  (void) pthread_mutex_lock(&ssl_mutexes[mutex_num]);
5575  } else {
5576  (void) pthread_mutex_unlock(&ssl_mutexes[mutex_num]);
5577  }
5578 }
5579 
5580 static unsigned long ssl_id_callback(void)
5581 {
5582  return (unsigned long) pthread_self();
5583 }
5584 
5585 #if !defined(NO_SSL_DL)
5586 static void *load_dll(struct mg_context *ctx, const char *dll_name,
5587  struct ssl_func *sw)
5588 {
5589  union {
5590  void *p;
5591  void (*fp)(void);
5592  } u;
5593  void *dll_handle;
5594  struct ssl_func *fp;
5595 
5596  if ((dll_handle = dlopen(dll_name, RTLD_LAZY)) == NULL) {
5597  mg_cry(fc(ctx), "%s: cannot load %s", __func__, dll_name);
5598  return NULL;
5599  }
5600 
5601  for (fp = sw; fp->name != NULL; fp++) {
5602 #ifdef _WIN32
5603  /* GetProcAddress() returns pointer to function */
5604  u.fp = (void (*)(void)) dlsym(dll_handle, fp->name);
5605 #else
5606  /* dlsym() on UNIX returns void *. ISO C forbids casts of data
5607  pointers to function pointers. We need to use a union to make a
5608  cast. */
5609  u.p = dlsym(dll_handle, fp->name);
5610 #endif /* _WIN32 */
5611  if (u.fp == NULL) {
5612  mg_cry(fc(ctx), "%s: %s: cannot find %s", __func__, dll_name, fp->name);
5613  dlclose(dll_handle);
5614  return NULL;
5615  } else {
5616  fp->ptr = u.fp;
5617  }
5618  }
5619 
5620  return dll_handle;
5621 }
5622 #endif /* NO_SSL_DL */
5623 
5624 /* Dynamically load SSL library. Set up ctx->ssl_ctx pointer. */
5625 static int set_ssl_option(struct mg_context *ctx)
5626 {
5627  int i, size;
5628  const char *pem;
5629 
5630  /* If PEM file is not specified and the init_ssl callback
5631  is not specified, skip SSL initialization. */
5632  if ((pem = ctx->config[SSL_CERTIFICATE]) == NULL &&
5633  ctx->callbacks.init_ssl == NULL) {
5634  return 1;
5635  }
5636 
5637 #if !defined(NO_SSL_DL)
5638  ctx->ssllib_dll_handle = load_dll(ctx, SSL_LIB, ssl_sw);
5639  ctx->cryptolib_dll_handle = load_dll(ctx, CRYPTO_LIB, crypto_sw);
5640  if (!ctx->ssllib_dll_handle || !ctx->cryptolib_dll_handle) {
5641  return 0;
5642  }
5643 #endif /* NO_SSL_DL */
5644 
5645  /* Initialize SSL library */
5646  SSL_library_init();
5647  SSL_load_error_strings();
5648 
5649  if ((ctx->ssl_ctx = SSL_CTX_new(SSLv23_server_method())) == NULL) {
5650  mg_cry(fc(ctx), "SSL_CTX_new (server) error: %s", ssl_error());
5651  return 0;
5652  }
5653 
5654  /* If user callback returned non-NULL, that means that user callback has
5655  set up certificate itself. In this case, skip sertificate setting. */
5656  if ((ctx->callbacks.init_ssl == NULL ||
5657  !ctx->callbacks.init_ssl(ctx->ssl_ctx, ctx->user_data)) &&
5658  (SSL_CTX_use_certificate_file(ctx->ssl_ctx, pem, 1) == 0 ||
5659  SSL_CTX_use_PrivateKey_file(ctx->ssl_ctx, pem, 1) == 0)) {
5660  mg_cry(fc(ctx), "%s: cannot open %s: %s", __func__, pem, ssl_error());
5661  return 0;
5662  }
5663 
5664  if (pem != NULL) {
5665  (void) SSL_CTX_use_certificate_chain_file(ctx->ssl_ctx, pem);
5666  }
5667 
5668  /* Initialize locking callbacks, needed for thread safety.
5669  http://www.openssl.org/support/faq.html#PROG1 */
5670  size = sizeof(pthread_mutex_t) * CRYPTO_num_locks();
5671  if ((ssl_mutexes = (pthread_mutex_t *) malloc((size_t)size)) == NULL) {
5672  mg_cry(fc(ctx), "%s: cannot allocate mutexes: %s", __func__, ssl_error());
5673  return 0;
5674  }
5675 
5676  for (i = 0; i < CRYPTO_num_locks(); i++) {
5677  pthread_mutex_init(&ssl_mutexes[i], NULL);
5678  }
5679 
5680  CRYPTO_set_locking_callback(&ssl_locking_callback);
5681  CRYPTO_set_id_callback(&ssl_id_callback);
5682 
5683  return 1;
5684 }
5685 
5686 static void uninitialize_ssl(struct mg_context *ctx)
5687 {
5688  int i;
5689  if (ctx->ssl_ctx != NULL) {
5690  CRYPTO_set_locking_callback(NULL);
5691  for (i = 0; i < CRYPTO_num_locks(); i++) {
5692  pthread_mutex_destroy(&ssl_mutexes[i]);
5693  }
5694  CRYPTO_set_locking_callback(NULL);
5695  CRYPTO_set_id_callback(NULL);
5696  }
5697 }
5698 #endif /* !NO_SSL */
5699 
5700 static int set_gpass_option(struct mg_context *ctx)
5701 {
5702  struct file file = STRUCT_FILE_INITIALIZER;
5703  const char *path = ctx->config[GLOBAL_PASSWORDS_FILE];
5704  if (path != NULL && !mg_stat(fc(ctx), path, &file)) {
5705  mg_cry(fc(ctx), "Cannot open %s: %s", path, strerror(ERRNO));
5706  return 0;
5707  }
5708  return 1;
5709 }
5710 
5711 static int set_acl_option(struct mg_context *ctx)
5712 {
5713  return check_acl(ctx, (uint32_t) 0x7f000001UL) != -1;
5714 }
5715 
5716 static void reset_per_request_attributes(struct mg_connection *conn)
5717 {
5718  conn->path_info = NULL;
5719  conn->num_bytes_sent = conn->consumed_content = 0;
5720  conn->status_code = -1;
5721  conn->must_close = conn->request_len = conn->throttle = 0;
5722 }
5723 
5724 static void close_socket_gracefully(struct mg_connection *conn)
5725 {
5726 #if defined(_WIN32)
5727  char buf[MG_BUF_LEN];
5728  int n;
5729 #endif
5730  struct linger linger;
5731 
5732  /* Set linger option to avoid socket hanging out after close. This prevent
5733  ephemeral port exhaust problem under high QPS. */
5734  linger.l_onoff = 1;
5735  linger.l_linger = 1;
5736  if (setsockopt(conn->client.sock, SOL_SOCKET, SO_LINGER,
5737  (char *) &linger, sizeof(linger)) != 0) {
5738  mg_cry(conn, "%s: setsockopt(SOL_SOCKET SO_LINGER) failed: %s",
5739  __func__, strerror(ERRNO));
5740  }
5741 
5742  /* Send FIN to the client */
5743  shutdown(conn->client.sock, SHUT_WR);
5744  set_non_blocking_mode(conn->client.sock);
5745 
5746 #if defined(_WIN32)
5747  /* Read and discard pending incoming data. If we do not do that and close
5748  the socket, the data in the send buffer may be discarded. This
5749  behaviour is seen on Windows, when client keeps sending data
5750  when server decides to close the connection; then when client
5751  does recv() it gets no data back. */
5752  do {
5753  n = pull(NULL, conn, buf, sizeof(buf));
5754  } while (n > 0);
5755 #endif
5756 
5757  /* Now we know that our FIN is ACK-ed, safe to close */
5758  closesocket(conn->client.sock);
5759 }
5760 
5761 static void close_connection(struct mg_connection *conn)
5762 {
5763 #if defined(USE_LUA) && defined(USE_WEBSOCKET)
5764  if (conn->lua_websocket_state) {
5765  lua_websocket_close(conn);
5766  }
5767 #endif
5768 
5769  /* call the connection_close callback if assigned */
5770  if (conn->ctx->callbacks.connection_close != NULL)
5771  conn->ctx->callbacks.connection_close(conn);
5772 
5773  mg_lock(conn);
5774 
5775  conn->must_close = 1;
5776 
5777 #ifndef NO_SSL
5778  if (conn->ssl != NULL) {
5779  /* Run SSL_shutdown twice to ensure completly close SSL connection */
5780  SSL_shutdown(conn->ssl);
5781  SSL_free(conn->ssl);
5782  conn->ssl = NULL;
5783  }
5784 #endif
5785  if (conn->client.sock != INVALID_SOCKET) {
5786  close_socket_gracefully(conn);
5787  conn->client.sock = INVALID_SOCKET;
5788  }
5789 
5790  mg_unlock(conn);
5791 }
5792 
5793 void mg_close_connection(struct mg_connection *conn)
5794 {
5795 #ifndef NO_SSL
5796  if (conn->client_ssl_ctx != NULL) {
5797  SSL_CTX_free((SSL_CTX *) conn->client_ssl_ctx);
5798  }
5799 #endif
5800  close_connection(conn);
5801  (void) pthread_mutex_destroy(&conn->mutex);
5802  free(conn);
5803 }
5804 
5805 struct mg_connection *mg_connect(const char *host, int port, int use_ssl,
5806  char *ebuf, size_t ebuf_len);
5807 
5808 struct mg_connection *mg_connect(const char *host, int port, int use_ssl,
5809  char *ebuf, size_t ebuf_len)
5810 {
5811  static struct mg_context fake_ctx;
5812  struct mg_connection *conn = NULL;
5813  SOCKET sock;
5814 
5815  if ((sock = conn2(&fake_ctx, host, port, use_ssl, ebuf,
5816  ebuf_len)) == INVALID_SOCKET) {
5817  } else if ((conn = (struct mg_connection *)
5818  calloc(1, sizeof(*conn) + MAX_REQUEST_SIZE)) == NULL) {
5819  snprintf(ebuf, ebuf_len, "calloc(): %s", strerror(ERRNO));
5820  closesocket(sock);
5821 #ifndef NO_SSL
5822  } else if (use_ssl && (conn->client_ssl_ctx =
5823  SSL_CTX_new(SSLv23_client_method())) == NULL) {
5824  snprintf(ebuf, ebuf_len, "SSL_CTX_new error");
5825  closesocket(sock);
5826  free(conn);
5827  conn = NULL;
5828 #endif /* NO_SSL */
5829  } else {
5830  socklen_t len = sizeof(struct sockaddr);
5831  conn->buf_size = MAX_REQUEST_SIZE;
5832  conn->buf = (char *) (conn + 1);
5833  conn->ctx = &fake_ctx;
5834  conn->client.sock = sock;
5835  if (getsockname(sock, &conn->client.rsa.sa, &len) != 0) {
5836  mg_cry(conn, "%s: getsockname() failed: %s",
5837  __func__, strerror(ERRNO));
5838  }
5839  conn->client.is_ssl = use_ssl;
5840  (void) pthread_mutex_init(&conn->mutex, NULL);
5841 #ifndef NO_SSL
5842  if (use_ssl) {
5843  /* SSL_CTX_set_verify call is needed to switch off server
5844  certificate checking, which is off by default in OpenSSL and on
5845  in yaSSL. */
5846  SSL_CTX_set_verify(conn->client_ssl_ctx, 0, 0);
5847  sslize(conn, conn->client_ssl_ctx, SSL_connect);
5848  }
5849 #endif
5850  }
5851 
5852  return conn;
5853 }
5854 
5855 static int is_valid_uri(const char *uri)
5856 {
5857  /* Conform to
5858  http://www.w3.org/Protocols/rfc2616/rfc2616-sec5.html#sec5.1.2
5859  URI can be an asterisk (*) or should start with slash. */
5860  return uri[0] == '/' || (uri[0] == '*' && uri[1] == '\0');
5861 }
5862 
5863 static int getreq(struct mg_connection *conn, char *ebuf, size_t ebuf_len)
5864 {
5865  const char *cl;
5866 
5867  ebuf[0] = '\0';
5868  reset_per_request_attributes(conn);
5869  conn->request_len = read_request(NULL, conn, conn->buf, conn->buf_size,
5870  &conn->data_len);
5871  assert(conn->request_len < 0 || conn->data_len >= conn->request_len);
5872 
5873  if (conn->request_len == 0 && conn->data_len == conn->buf_size) {
5874  snprintf(ebuf, ebuf_len, "%s", "Request Too Large");
5875  } else if (conn->request_len <= 0) {
5876  snprintf(ebuf, ebuf_len, "%s", "Client closed connection");
5877  } else if (parse_http_message(conn->buf, conn->buf_size,
5878  &conn->request_info) <= 0) {
5879  snprintf(ebuf, ebuf_len, "Bad request: [%.*s]", conn->data_len, conn->buf);
5880  } else {
5881  /* Request is valid */
5882  if ((cl = get_header(&conn->request_info, "Content-Length")) != NULL) {
5883  conn->content_len = strtoll(cl, NULL, 10);
5884  } else if (!mg_strcasecmp(conn->request_info.request_method, "POST") ||
5885  !mg_strcasecmp(conn->request_info.request_method, "PUT")) {
5886  conn->content_len = -1;
5887  } else {
5888  conn->content_len = 0;
5889  }
5890  conn->birth_time = time(NULL);
5891  }
5892  return ebuf[0] == '\0';
5893 }
5894 
5895 struct mg_connection *mg_download(const char *host, int port, int use_ssl,
5896  char *ebuf, size_t ebuf_len,
5897  const char *fmt, ...)
5898 {
5899  struct mg_connection *conn;
5900  va_list ap;
5901 
5902  va_start(ap, fmt);
5903  ebuf[0] = '\0';
5904  if ((conn = mg_connect(host, port, use_ssl, ebuf, ebuf_len)) == NULL) {
5905  } else if (mg_vprintf(conn, fmt, ap) <= 0) {
5906  snprintf(ebuf, ebuf_len, "%s", "Error sending request");
5907  } else {
5908  getreq(conn, ebuf, ebuf_len);
5909  }
5910  if (ebuf[0] != '\0' && conn != NULL) {
5911  mg_close_connection(conn);
5912  conn = NULL;
5913  }
5914  va_end(ap);
5915 
5916  return conn;
5917 }
5918 
5919 static void process_new_connection(struct mg_connection *conn)
5920 {
5921  struct mg_request_info *ri = &conn->request_info;
5922  int keep_alive_enabled, keep_alive, discard_len;
5923  char ebuf[100];
5924 
5925  keep_alive_enabled = !strcmp(conn->ctx->config[ENABLE_KEEP_ALIVE], "yes");
5926  keep_alive = 0;
5927 
5928  /* Important: on new connection, reset the receiving buffer. Credit goes
5929  to crule42. */
5930  conn->data_len = 0;
5931  do {
5932  if (!getreq(conn, ebuf, sizeof(ebuf))) {
5933  send_http_error(conn, 500, "Server Error", "%s", ebuf);
5934  conn->must_close = 1;
5935  } else if (!is_valid_uri(conn->request_info.uri)) {
5936  snprintf(ebuf, sizeof(ebuf), "Invalid URI: [%s]", ri->uri);
5937  send_http_error(conn, 400, "Bad Request", "%s", ebuf);
5938  } else if (strcmp(ri->http_version, "1.0") &&
5939  strcmp(ri->http_version, "1.1")) {
5940  snprintf(ebuf, sizeof(ebuf), "Bad HTTP version: [%s]", ri->http_version);
5941  send_http_error(conn, 505, "Bad HTTP version", "%s", ebuf);
5942  }
5943 
5944  if (ebuf[0] == '\0') {
5945  handle_request(conn);
5946  if (conn->ctx->callbacks.end_request != NULL) {
5947  conn->ctx->callbacks.end_request(conn, conn->status_code);
5948  }
5949  log_access(conn);
5950  }
5951  if (ri->remote_user != NULL) {
5952  free((void *) ri->remote_user);
5953  /* Important! When having connections with and without auth
5954  would cause double free and then crash */
5955  ri->remote_user = NULL;
5956  }
5957 
5958  /* NOTE(lsm): order is important here. should_keep_alive() call is
5959  using parsed request, which will be invalid after memmove's below.
5960  Therefore, memorize should_keep_alive() result now for later use
5961  in loop exit condition. */
5962  keep_alive = conn->ctx->stop_flag == 0 && keep_alive_enabled &&
5963  conn->content_len >= 0 && should_keep_alive(conn);
5964 
5965  /* Discard all buffered data for this request */
5966  discard_len = conn->content_len >= 0 && conn->request_len > 0 &&
5967  conn->request_len + conn->content_len < (int64_t) conn->data_len ?
5968  (int) (conn->request_len + conn->content_len) : conn->data_len;
5969  assert(discard_len >= 0);
5970  memmove(conn->buf, conn->buf + discard_len, conn->data_len - discard_len);
5971  conn->data_len -= discard_len;
5972  assert(conn->data_len >= 0);
5973  assert(conn->data_len <= conn->buf_size);
5974  } while (keep_alive);
5975 }
5976 
5977 /* Worker threads take accepted socket from the queue */
5978 static int consume_socket(struct mg_context *ctx, struct socket *sp)
5979 {
5980  (void) pthread_mutex_lock(&ctx->mutex);
5981  DEBUG_TRACE(("going idle"));
5982 
5983  /* If the queue is empty, wait. We're idle at this point. */
5984  while (ctx->sq_head == ctx->sq_tail && ctx->stop_flag == 0) {
5985  pthread_cond_wait(&ctx->sq_full, &ctx->mutex);
5986  }
5987 
5988  /* If we're stopping, sq_head may be equal to sq_tail. */
5989  if (ctx->sq_head > ctx->sq_tail) {
5990  /* Copy socket from the queue and increment tail */
5991  *sp = ctx->queue[ctx->sq_tail % ARRAY_SIZE(ctx->queue)];
5992  ctx->sq_tail++;
5993  DEBUG_TRACE(("grabbed socket %d, going busy", sp->sock));
5994 
5995  /* Wrap pointers if needed */
5996  while (ctx->sq_tail > (int) ARRAY_SIZE(ctx->queue)) {
5997  ctx->sq_tail -= ARRAY_SIZE(ctx->queue);
5998  ctx->sq_head -= ARRAY_SIZE(ctx->queue);
5999  }
6000  }
6001 
6002  (void) pthread_cond_signal(&ctx->sq_empty);
6003  (void) pthread_mutex_unlock(&ctx->mutex);
6004 
6005  return !ctx->stop_flag;
6006 }
6007 
6008 static void *worker_thread_run(void *thread_func_param)
6009 {
6010  struct mg_context *ctx = (struct mg_context *) thread_func_param;
6011  struct mg_connection *conn;
6012  struct mg_workerTLS tls;
6013 
6014  tls.is_master = 0;
6015 #if defined(_WIN32) && !defined(__SYMBIAN32__)
6016  tls.pthread_cond_helper_mutex = CreateEvent(NULL, FALSE, FALSE, NULL);
6017 #endif
6018 
6019  conn = (struct mg_connection *) calloc(1, sizeof(*conn) + MAX_REQUEST_SIZE);
6020  if (conn == NULL) {
6021  mg_cry(fc(ctx), "%s", "Cannot create new connection struct, OOM");
6022  } else {
6023  pthread_setspecific(sTlsKey, &tls);
6024  conn->buf_size = MAX_REQUEST_SIZE;
6025  conn->buf = (char *) (conn + 1);
6026  conn->ctx = ctx;
6027  conn->request_info.user_data = ctx->user_data;
6028  /* Allocate a mutex for this connection to allow communication both
6029  within the request handler and from elsewhere in the application */
6030  (void) pthread_mutex_init(&conn->mutex, NULL);
6031 
6032  /* Call consume_socket() even when ctx->stop_flag > 0, to let it
6033  signal sq_empty condvar to wake up the master waiting in
6034  produce_socket() */
6035  while (consume_socket(ctx, &conn->client)) {
6036  conn->birth_time = time(NULL);
6037 
6038  /* Fill in IP, port info early so even if SSL setup below fails,
6039  error handler would have the corresponding info.
6040  Thanks to Johannes Winkelmann for the patch.
6041  TODO(lsm): Fix IPv6 case */
6042  conn->request_info.remote_port = ntohs(conn->client.rsa.sin.sin_port);
6043  memcpy(&conn->request_info.remote_ip,
6044  &conn->client.rsa.sin.sin_addr.s_addr, 4);
6045  conn->request_info.remote_ip = ntohl(conn->request_info.remote_ip);
6046  conn->request_info.is_ssl = conn->client.is_ssl;
6047 
6048  if (!conn->client.is_ssl
6049 #ifndef NO_SSL
6050  || sslize(conn, conn->ctx->ssl_ctx, SSL_accept)
6051 #endif
6052  ) {
6053  process_new_connection(conn);
6054  }
6055 
6056  close_connection(conn);
6057  }
6058  }
6059 
6060  /* Signal master that we're done with connection and exiting */
6061  (void) pthread_mutex_lock(&ctx->mutex);
6062  ctx->num_threads--;
6063  (void) pthread_cond_signal(&ctx->cond);
6064  assert(ctx->num_threads >= 0);
6065  (void) pthread_mutex_unlock(&ctx->mutex);
6066 
6067  pthread_setspecific(sTlsKey, 0);
6068 #if defined(_WIN32) && !defined(__SYMBIAN32__)
6069  CloseHandle(tls.pthread_cond_helper_mutex);
6070 #endif
6071  free(conn);
6072 
6073  DEBUG_TRACE(("exiting"));
6074  return NULL;
6075 }
6076 
6077 /* Threads have different return types on Windows and Unix. */
6078 
6079 #ifdef _WIN32
6080 static unsigned __stdcall worker_thread(void *thread_func_param)
6081 {
6082  worker_thread_run(thread_func_param);
6083  return 0;
6084 }
6085 #else
6086 static void *worker_thread(void *thread_func_param)
6087 {
6088  worker_thread_run(thread_func_param);
6089  return NULL;
6090 }
6091 #endif /* _WIN32 */
6092 
6093 /* Master thread adds accepted socket to a queue */
6094 static void produce_socket(struct mg_context *ctx, const struct socket *sp)
6095 {
6096  (void) pthread_mutex_lock(&ctx->mutex);
6097 
6098  /* If the queue is full, wait */
6099  while (ctx->stop_flag == 0 &&
6100  ctx->sq_head - ctx->sq_tail >= (int) ARRAY_SIZE(ctx->queue)) {
6101  (void) pthread_cond_wait(&ctx->sq_empty, &ctx->mutex);
6102  }
6103 
6104  if (ctx->sq_head - ctx->sq_tail < (int) ARRAY_SIZE(ctx->queue)) {
6105  /* Copy socket to the queue and increment head */
6106  ctx->queue[ctx->sq_head % ARRAY_SIZE(ctx->queue)] = *sp;
6107  ctx->sq_head++;
6108  DEBUG_TRACE(("queued socket %d", sp->sock));
6109  }
6110 
6111  (void) pthread_cond_signal(&ctx->sq_full);
6112  (void) pthread_mutex_unlock(&ctx->mutex);
6113 }
6114 
6115 static int set_sock_timeout(SOCKET sock, int milliseconds)
6116 {
6117 #ifdef _WIN32
6118  DWORD t = milliseconds;
6119 #else
6120  struct timeval t;
6121  t.tv_sec = milliseconds / 1000;
6122  t.tv_usec = (milliseconds * 1000) % 1000000;
6123 #endif
6124  return setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (const char *) &t, sizeof(t)) ||
6125  setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (const char *) &t, sizeof(t));
6126 }
6127 
6128 static void accept_new_connection(const struct socket *listener,
6129  struct mg_context *ctx)
6130 {
6131  struct socket so;
6132  char src_addr[IP_ADDR_STR_LEN];
6133  socklen_t len = sizeof(so.rsa);
6134  int on = 1;
6135 
6136  if ((so.sock = accept(listener->sock, &so.rsa.sa, &len)) == INVALID_SOCKET) {
6137  } else if (!check_acl(ctx, ntohl(* (uint32_t *) &so.rsa.sin.sin_addr))) {
6138  sockaddr_to_string(src_addr, sizeof(src_addr), &so.rsa);
6139  mg_cry(fc(ctx), "%s: %s is not allowed to connect", __func__, src_addr);
6140  closesocket(so.sock);
6141  } else {
6142  /* Put so socket structure into the queue */
6143  DEBUG_TRACE(("Accepted socket %d", (int) so.sock));
6144  set_close_on_exec(so.sock, fc(ctx));
6145  so.is_ssl = listener->is_ssl;
6146  so.ssl_redir = listener->ssl_redir;
6147  if (getsockname(so.sock, &so.lsa.sa, &len) != 0) {
6148  mg_cry(fc(ctx), "%s: getsockname() failed: %s",
6149  __func__, strerror(ERRNO));
6150  }
6151  /* Set TCP keep-alive. This is needed because if HTTP-level keep-alive
6152  is enabled, and client resets the connection, server won't get
6153  TCP FIN or RST and will keep the connection open forever. With TCP
6154  keep-alive, next keep-alive handshake will figure out that the
6155  client is down and will close the server end.
6156  Thanks to Igor Klopov who suggested the patch. */
6157  if (setsockopt(so.sock, SOL_SOCKET, SO_KEEPALIVE, (const char *) &on,
6158  sizeof(on)) != 0) {
6159  mg_cry(fc(ctx),
6160  "%s: setsockopt(SOL_SOCKET SO_KEEPALIVE) failed: %s",
6161  __func__, strerror(ERRNO));
6162  }
6163  set_sock_timeout(so.sock, atoi(ctx->config[REQUEST_TIMEOUT]));
6164  produce_socket(ctx, &so);
6165  }
6166 }
6167 
6168 static void master_thread_run(void *thread_func_param)
6169 {
6170  struct mg_context *ctx = (struct mg_context *) thread_func_param;
6171  struct mg_workerTLS tls;
6172  struct pollfd *pfd;
6173  int i;
6174  int workerthreadcount;
6175 
6176  /* Increase priority of the master thread */
6177 #if defined(_WIN32)
6178  SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL);
6179 #elif defined(USE_MASTER_THREAD_PRIORITY)
6180  int min_prio = sched_get_priority_min(SCHED_RR);
6181  int max_prio = sched_get_priority_max(SCHED_RR);
6182  if ((min_prio >=0) && (max_prio >= 0) &&
6183  ((USE_MASTER_THREAD_PRIORITY) <= max_prio) &&
6184  ((USE_MASTER_THREAD_PRIORITY) >= min_prio)
6185  ) {
6186  struct sched_param sched_param = {0};
6187  sched_param.sched_priority = (USE_MASTER_THREAD_PRIORITY);
6188  pthread_setschedparam(pthread_self(), SCHED_RR, &sched_param);
6189  }
6190 #endif
6191 
6192 #if defined(_WIN32) && !defined(__SYMBIAN32__)
6193  tls.pthread_cond_helper_mutex = CreateEvent(NULL, FALSE, FALSE, NULL);
6194 #endif
6195  tls.is_master = 1;
6196  pthread_setspecific(sTlsKey, &tls);
6197 
6198  pfd = (struct pollfd *) calloc(ctx->num_listening_sockets, sizeof(pfd[0]));
6199  while (pfd != NULL && ctx->stop_flag == 0) {
6200  for (i = 0; i < ctx->num_listening_sockets; i++) {
6201  pfd[i].fd = ctx->listening_sockets[i].sock;
6202  pfd[i].events = POLLIN;
6203  }
6204 
6205  if (poll(pfd, ctx->num_listening_sockets, 200) > 0) {
6206  for (i = 0; i < ctx->num_listening_sockets; i++) {
6207  /* NOTE(lsm): on QNX, poll() returns POLLRDNORM after the
6208  successful poll, and POLLIN is defined as
6209  (POLLRDNORM | POLLRDBAND)
6210  Therefore, we're checking pfd[i].revents & POLLIN, not
6211  pfd[i].revents == POLLIN. */
6212  if (ctx->stop_flag == 0 && (pfd[i].revents & POLLIN)) {
6213  accept_new_connection(&ctx->listening_sockets[i], ctx);
6214  }
6215  }
6216  }
6217  }
6218  free(pfd);
6219  DEBUG_TRACE(("stopping workers"));
6220 
6221  /* Stop signal received: somebody called mg_stop. Quit. */
6222  close_all_listening_sockets(ctx);
6223 
6224  /* Wakeup workers that are waiting for connections to handle. */
6225  pthread_cond_broadcast(&ctx->sq_full);
6226 
6227  /* Wait until all threads finish */
6228  (void) pthread_mutex_lock(&ctx->mutex);
6229  while (ctx->num_threads > 0) {
6230  (void) pthread_cond_wait(&ctx->cond, &ctx->mutex);
6231  }
6232  (void) pthread_mutex_unlock(&ctx->mutex);
6233 
6234  /* Join all worker threads to avoid leaking threads. */
6235  workerthreadcount = ctx->workerthreadcount;
6236  for (i = 0; i < workerthreadcount; i++) {
6237  mg_join_thread(ctx->workerthreadids[i]);
6238  }
6239 
6240  /* All threads exited, no sync is needed. Destroy mutex and condvars */
6241  (void) pthread_mutex_destroy(&ctx->mutex);
6242  (void) pthread_cond_destroy(&ctx->cond);
6243  (void) pthread_cond_destroy(&ctx->sq_empty);
6244  (void) pthread_cond_destroy(&ctx->sq_full);
6245 
6246 #if !defined(NO_SSL)
6247  uninitialize_ssl(ctx);
6248 #endif
6249  DEBUG_TRACE(("exiting"));
6250 
6251 #if defined(_WIN32) && !defined(__SYMBIAN32__)
6252  CloseHandle(tls.pthread_cond_helper_mutex);
6253 #endif
6254  pthread_setspecific(sTlsKey, 0);
6255 
6256  /* Signal mg_stop() that we're done.
6257  WARNING: This must be the very last thing this
6258  thread does, as ctx becomes invalid after this line. */
6259  ctx->stop_flag = 2;
6260 }
6261 
6262 /* Threads have different return types on Windows and Unix. */
6263 
6264 #ifdef _WIN32
6265 static unsigned __stdcall master_thread(void *thread_func_param)
6266 {
6267  master_thread_run(thread_func_param);
6268  return 0;
6269 }
6270 #else
6271 static void *master_thread(void *thread_func_param)
6272 {
6273  master_thread_run(thread_func_param);
6274  return NULL;
6275 }
6276 #endif /* _WIN32 */
6277 
6278 static void free_context(struct mg_context *ctx)
6279 {
6280  int i;
6281  struct mg_request_handler_info *tmp_rh;
6282 
6283  if (ctx == NULL)
6284  return;
6285 
6286  /* Deallocate config parameters */
6287  for (i = 0; i < NUM_OPTIONS; i++) {
6288  if (ctx->config[i] != NULL)
6289 #ifdef WIN32
6290 #pragma warning(suppress: 6001)
6291 #endif
6292  free(ctx->config[i]);
6293  }
6294 
6295  /* Deallocate request handlers */
6296  while (ctx->request_handlers) {
6297  tmp_rh = ctx->request_handlers;
6298  ctx->request_handlers = tmp_rh->next;
6299  free(tmp_rh->uri);
6300  free(tmp_rh);
6301  }
6302 
6303 #ifndef NO_SSL
6304  /* Deallocate SSL context */
6305  if (ctx->ssl_ctx != NULL) {
6306  SSL_CTX_free(ctx->ssl_ctx);
6307  }
6308  if (ssl_mutexes != NULL) {
6309  free(ssl_mutexes);
6310  ssl_mutexes = NULL;
6311  }
6312 #endif /* !NO_SSL */
6313 
6314  /* Deallocate worker thread ID array */
6315  if (ctx->workerthreadids != NULL) {
6316  free(ctx->workerthreadids);
6317  }
6318 
6319  /* Deallocate the tls variable */
6320  sTlsInit--;
6321  if (sTlsInit==0) {
6322  pthread_key_delete(sTlsKey);
6323  }
6324 
6325  /* Deallocate context itself */
6326  free(ctx);
6327 }
6328 
6329 void mg_stop(struct mg_context *ctx)
6330 {
6331  ctx->stop_flag = 1;
6332 
6333  /* Wait until mg_fini() stops */
6334  while (ctx->stop_flag != 2) {
6335  (void) mg_sleep(10);
6336  }
6337  mg_join_thread(ctx->masterthreadid);
6338  free_context(ctx);
6339 
6340 #if defined(_WIN32) && !defined(__SYMBIAN32__)
6341  (void) WSACleanup();
6342 #endif /* _WIN32 && !__SYMBIAN32__ */
6343 }
6344 
6345 struct mg_context *mg_start(const struct mg_callbacks *callbacks,
6346  void *user_data,
6347  const char **options)
6348 {
6349  struct mg_context *ctx;
6350  const char *name, *value, *default_value;
6351  int i;
6352  int workerthreadcount;
6353 
6354 #if defined(_WIN32) && !defined(__SYMBIAN32__)
6355  WSADATA data;
6356  WSAStartup(MAKEWORD(2,2), &data);
6357 #pragma warning(suppress: 28125)
6358  InitializeCriticalSection(&global_log_file_lock);
6359 #endif /* _WIN32 && !__SYMBIAN32__ */
6360 
6361  /* Check if the config_options and the corresponding enum have compatible sizes. */
6362  /* Could use static_assert, once it is verified that all compilers support this. */
6363  assert(sizeof(config_options)/sizeof(config_options[0]) == NUM_OPTIONS*2+1);
6364 
6365  /* Allocate context and initialize reasonable general case defaults.
6366  TODO(lsm): do proper error handling here. */
6367  if ((ctx = (struct mg_context *) calloc(1, sizeof(*ctx))) == NULL) {
6368  return NULL;
6369  }
6370 
6371  if (sTlsInit==0) {
6372  if (0 != pthread_key_create(&sTlsKey, NULL)) {
6373  mg_cry(fc(ctx), "Cannot initialize thread local storage");
6374  free(ctx);
6375  return NULL;
6376  }
6377  sTlsInit++;
6378  }
6379 
6380  ctx->callbacks = *callbacks;
6381  ctx->user_data = user_data;
6382  ctx->request_handlers = 0;
6383 
6384  while (options && (name = *options++) != NULL) {
6385  if ((i = get_option_index(name)) == -1) {
6386  mg_cry(fc(ctx), "Invalid option: %s", name);
6387  free_context(ctx);
6388  return NULL;
6389  } else if ((value = *options++) == NULL) {
6390  mg_cry(fc(ctx), "%s: option value cannot be NULL", name);
6391  free_context(ctx);
6392  return NULL;
6393  }
6394  if (ctx->config[i] != NULL) {
6395  mg_cry(fc(ctx), "warning: %s: duplicate option", name);
6396  free(ctx->config[i]);
6397  }
6398  ctx->config[i] = mg_strdup(value);
6399  DEBUG_TRACE(("[%s] -> [%s]", name, value));
6400  }
6401 
6402  /* Set default value if needed */
6403  for (i = 0; config_options[i * 2] != NULL; i++) {
6404  default_value = config_options[i * 2 + 1];
6405  if (ctx->config[i] == NULL && default_value != NULL) {
6406  ctx->config[i] = mg_strdup(default_value);
6407  }
6408  }
6409 
6410  /* NOTE(lsm): order is important here. SSL certificates must
6411  be initialized before listening ports. UID must be set last. */
6412  if (!set_gpass_option(ctx) ||
6413 #if !defined(NO_SSL)
6414  !set_ssl_option(ctx) ||
6415 #endif
6416  !set_ports_option(ctx) ||
6417 #if !defined(_WIN32)
6418  !set_uid_option(ctx) ||
6419 #endif
6420  !set_acl_option(ctx)) {
6421  free_context(ctx);
6422  return NULL;
6423  }
6424 
6425 #if !defined(_WIN32) && !defined(__SYMBIAN32__)
6426  /* Ignore SIGPIPE signal, so if browser cancels the request, it
6427  won't kill the whole process. */
6428  (void) signal(SIGPIPE, SIG_IGN);
6429 #endif /* !_WIN32 && !__SYMBIAN32__ */
6430 
6431  (void) pthread_mutex_init(&ctx->mutex, NULL);
6432  (void) pthread_cond_init(&ctx->cond, NULL);
6433  (void) pthread_cond_init(&ctx->sq_empty, NULL);
6434  (void) pthread_cond_init(&ctx->sq_full, NULL);
6435 
6436  workerthreadcount = atoi(ctx->config[NUM_THREADS]);
6437 
6438  if (workerthreadcount > MAX_WORKER_THREADS) {
6439  mg_cry(fc(ctx), "Too many worker threads");
6440  free_context(ctx);
6441  return NULL;
6442  }
6443 
6444  if (workerthreadcount > 0) {
6445  ctx->workerthreadcount = workerthreadcount;
6446  ctx->workerthreadids = (pthread_t*)calloc(workerthreadcount, sizeof(pthread_t));
6447  if (ctx->workerthreadids == NULL) {
6448  mg_cry(fc(ctx), "Not enough memory for worker thread ID array");
6449  free_context(ctx);
6450  return NULL;
6451  }
6452  }
6453 
6454  /* Start master (listening) thread */
6455  mg_start_thread_with_id(master_thread, ctx, &ctx->masterthreadid);
6456 
6457  /* Start worker threads */
6458  for (i = 0; i < workerthreadcount; i++) {
6459  (void) pthread_mutex_lock(&ctx->mutex);
6460  ctx->num_threads++;
6461  (void) pthread_mutex_unlock(&ctx->mutex);
6462  if (mg_start_thread_with_id(worker_thread, ctx,
6463  &ctx->workerthreadids[i]) != 0) {
6464  (void) pthread_mutex_lock(&ctx->mutex);
6465  ctx->num_threads--;
6466  (void) pthread_mutex_unlock(&ctx->mutex);
6467  mg_cry(fc(ctx), "Cannot start worker thread: %ld", (long) ERRNO);
6468  }
6469  }
6470 
6471  return ctx;
6472 }