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