Logo ROOT   6.12/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 buffer to the point
6813  * where parsing stopped. */
6814 static void
6815 parse_http_headers(char **buf, struct mg_request_info *ri)
6816 {
6817  int i;
6818 
6819  if (!ri) {
6820  return;
6821  }
6822 
6823  ri->num_headers = 0;
6824 
6825  for (i = 0; i < (int)ARRAY_SIZE(ri->http_headers); i++) {
6826  char *dp = *buf;
6827  while ((*dp != ':') && (*dp != '\r') && (*dp != 0)) {
6828  dp++;
6829  }
6830  if (!*dp) {
6831  /* neither : nor \r\n. This is not a valid field. */
6832  break;
6833  }
6834  if (*dp == '\r') {
6835  if (dp[1] == '\n') {
6836  /* \r\n */
6837  ri->http_headers[i].name = *buf;
6838  ri->http_headers[i].value = 0;
6839  *buf = dp;
6840  } else {
6841  /* stray \r. This is not valid. */
6842  break;
6843  }
6844  } else {
6845  /* (*dp == ':') */
6846  *dp = 0;
6847  ri->http_headers[i].name = *buf;
6848  do {
6849  dp++;
6850  } while (*dp == ' ');
6851 
6852  ri->http_headers[i].value = dp;
6853  *buf = strstr(dp, "\r\n");
6854  }
6855 
6856  ri->num_headers = i + 1;
6857  if (*buf) {
6858  (*buf)[0] = 0;
6859  (*buf)[1] = 0;
6860  *buf += 2;
6861  } else {
6862  *buf = dp;
6863  break;
6864  }
6865 
6866  if (*buf[0] == '\r') {
6867  /* This is the end of the header */
6868  break;
6869  }
6870  }
6871 }
6872 
6873 
6874 static int
6875 is_valid_http_method(const char *method)
6876 {
6877  return !strcmp(method, "GET") /* HTTP (RFC 2616) */
6878  || !strcmp(method, "POST") /* HTTP (RFC 2616) */
6879  || !strcmp(method, "HEAD") /* HTTP (RFC 2616) */
6880  || !strcmp(method, "PUT") /* HTTP (RFC 2616) */
6881  || !strcmp(method, "DELETE") /* HTTP (RFC 2616) */
6882  || !strcmp(method, "OPTIONS") /* HTTP (RFC 2616) */
6883  /* TRACE method (RFC 2616) is not supported for security reasons */
6884  || !strcmp(method, "CONNECT") /* HTTP (RFC 2616) */
6885 
6886  || !strcmp(method, "PROPFIND") /* WEBDAV (RFC 2518) */
6887  || !strcmp(method, "MKCOL") /* WEBDAV (RFC 2518) */
6888 
6889  /* Unsupported WEBDAV Methods: */
6890  /* PROPPATCH, COPY, MOVE, LOCK, UNLOCK (RFC 2518) */
6891  /* + 11 methods from RFC 3253 */
6892  /* ORDERPATCH (RFC 3648) */
6893  /* ACL (RFC 3744) */
6894  /* SEARCH (RFC 5323) */
6895  /* + MicroSoft extensions
6896  * https://msdn.microsoft.com/en-us/library/aa142917.aspx */
6897 
6898  /* PATCH method only allowed for CGI/Lua/LSP and callbacks. */
6899  || !strcmp(method, "PATCH"); /* PATCH method (RFC 5789) */
6900 }
6901 
6902 
6903 /* Parse HTTP request, fill in mg_request_info structure.
6904  * This function modifies the buffer by NUL-terminating
6905  * HTTP request components, header names and header values. */
6906 static int
6907 parse_http_message(char *buf, int len, struct mg_request_info *ri)
6908 {
6909  int is_request, request_length;
6910 
6911  if (!ri) {
6912  return 0;
6913  }
6914 
6915  request_length = get_request_len(buf, len);
6916 
6917  if (request_length > 0) {
6918  /* Reset attributes. DO NOT TOUCH is_ssl, remote_ip, remote_addr,
6919  * remote_port */
6920  ri->remote_user = ri->request_method = ri->request_uri =
6921  ri->http_version = NULL;
6922  ri->num_headers = 0;
6923 
6924  buf[request_length - 1] = '\0';
6925 
6926  /* RFC says that all initial whitespaces should be ingored */
6927  while (*buf != '\0' && isspace(*(unsigned char *)buf)) {
6928  buf++;
6929  }
6930  ri->request_method = skip(&buf, " ");
6931  ri->request_uri = skip(&buf, " ");
6932  ri->http_version = skip(&buf, "\r\n");
6933 
6934  /* HTTP message could be either HTTP request or HTTP response, e.g.
6935  * "GET / HTTP/1.0 ...." or "HTTP/1.0 200 OK ..." */
6936  is_request = is_valid_http_method(ri->request_method);
6937  if ((is_request && memcmp(ri->http_version, "HTTP/", 5) != 0)
6938  || (!is_request && memcmp(ri->request_method, "HTTP/", 5) != 0)) {
6939  request_length = -1;
6940  } else {
6941  if (is_request) {
6942  ri->http_version += 5;
6943  }
6944  parse_http_headers(&buf, ri);
6945  }
6946  }
6947  return request_length;
6948 }
6949 
6950 
6951 /* Keep reading the input (either opened file descriptor fd, or socket sock,
6952  * or SSL descriptor ssl) into buffer buf, until \r\n\r\n appears in the
6953  * buffer (which marks the end of HTTP request). Buffer buf may already
6954  * have some data. The length of the data is stored in nread.
6955  * Upon every read operation, increase nread by the number of bytes read. */
6956 static int
6957 read_request(FILE *fp,
6958  struct mg_connection *conn,
6959  char *buf,
6960  int bufsiz,
6961  int *nread)
6962 {
6963  int request_len, n = 0;
6964  struct timespec last_action_time;
6965  double request_timeout;
6966 
6967  if (!conn) {
6968  return 0;
6969  }
6970 
6971  memset(&last_action_time, 0, sizeof(last_action_time));
6972 
6973  if (conn->ctx->config[REQUEST_TIMEOUT]) {
6974  /* value of request_timeout is in seconds, config in milliseconds */
6975  request_timeout = atof(conn->ctx->config[REQUEST_TIMEOUT]) / 1000.0;
6976  } else {
6977  request_timeout = -1.0;
6978  }
6979 
6980  request_len = get_request_len(buf, *nread);
6981 
6982  /* first time reading from this connection */
6983  clock_gettime(CLOCK_MONOTONIC, &last_action_time);
6984 
6985  while (
6986  (conn->ctx->stop_flag == 0) && (*nread < bufsiz) && (request_len == 0)
6987  && ((mg_difftimespec(&last_action_time, &(conn->req_time))
6988  <= request_timeout) || (request_timeout < 0))
6989  && ((n = pull(fp, conn, buf + *nread, bufsiz - *nread, request_timeout))
6990  > 0)) {
6991  *nread += n;
6992  /* assert(*nread <= bufsiz); */
6993  if (*nread > bufsiz) {
6994  return -2;
6995  }
6996  request_len = get_request_len(buf, *nread);
6997  if (request_timeout > 0.0) {
6998  clock_gettime(CLOCK_MONOTONIC, &last_action_time);
6999  }
7000  }
7001 
7002  return (request_len <= 0 && n <= 0) ? -1 : request_len;
7003 }
7004 
7005 #if !defined(NO_FILES)
7006 /* For given directory path, substitute it to valid index file.
7007  * Return 1 if index file has been found, 0 if not found.
7008  * If the file is found, it's stats is returned in stp. */
7009 static int
7010 substitute_index_file(struct mg_connection *conn,
7011  char *path,
7012  size_t path_len,
7013  struct file *filep)
7014 {
7015  if (conn && conn->ctx) {
7016  const char *list = conn->ctx->config[INDEX_FILES];
7017  struct file file = STRUCT_FILE_INITIALIZER;
7018  struct vec filename_vec;
7019  size_t n = strlen(path);
7020  int found = 0;
7021 
7022  /* The 'path' given to us points to the directory. Remove all trailing
7023  * directory separator characters from the end of the path, and
7024  * then append single directory separator character. */
7025  while (n > 0 && path[n - 1] == '/') {
7026  n--;
7027  }
7028  path[n] = '/';
7029 
7030  /* Traverse index files list. For each entry, append it to the given
7031  * path and see if the file exists. If it exists, break the loop */
7032  while ((list = next_option(list, &filename_vec, NULL)) != NULL) {
7033  /* Ignore too long entries that may overflow path buffer */
7034  if (filename_vec.len > path_len - (n + 2)) {
7035  continue;
7036  }
7037 
7038  /* Prepare full path to the index file */
7039  mg_strlcpy(path + n + 1, filename_vec.ptr, filename_vec.len + 1);
7040 
7041  /* Does it exist? */
7042  if (mg_stat(conn, path, &file)) {
7043  /* Yes it does, break the loop */
7044  *filep = file;
7045  found = 1;
7046  break;
7047  }
7048  }
7049 
7050  /* If no index file exists, restore directory path */
7051  if (!found) {
7052  path[n] = '\0';
7053  }
7054 
7055  return found;
7056  }
7057  return 0;
7058 }
7059 #endif
7060 
7061 
7062 #if !defined(NO_CACHING)
7063 /* Return True if we should reply 304 Not Modified. */
7064 static int
7065 is_not_modified(const struct mg_connection *conn, const struct file *filep)
7066 {
7067  char etag[64];
7068  const char *ims = mg_get_header(conn, "If-Modified-Since");
7069  const char *inm = mg_get_header(conn, "If-None-Match");
7070  construct_etag(etag, sizeof(etag), filep);
7071  if (!filep) {
7072  return 0;
7073  }
7074  return (inm != NULL && !mg_strcasecmp(etag, inm))
7075  || (ims != NULL && (filep->last_modified <= parse_date_string(ims)));
7076 }
7077 #endif /* !NO_CACHING */
7078 
7079 
7080 #if !defined(NO_CGI) || !defined(NO_FILES)
7081 static int
7082 forward_body_data(struct mg_connection *conn, FILE *fp, SOCKET sock, SSL *ssl)
7083 {
7084  const char *expect, *body;
7085  char buf[MG_BUF_LEN];
7086  int to_read, nread, success = 0;
7087  int64_t buffered_len;
7088  double timeout = -1.0;
7089 
7090  if (!conn) {
7091  return 0;
7092  }
7093  if (conn->ctx->config[REQUEST_TIMEOUT]) {
7094  timeout = atoi(conn->ctx->config[REQUEST_TIMEOUT]) / 1000.0;
7095  }
7096 
7097  expect = mg_get_header(conn, "Expect");
7098  /* assert(fp != NULL); */
7099  if (!fp) {
7100  send_http_error(conn, 500, "%s", "Error: NULL File");
7101  return 0;
7102  }
7103 
7104  if (conn->content_len == -1 && !conn->is_chunked) {
7105  /* Content length is not specified by the client. */
7106  send_http_error(conn,
7107  411,
7108  "%s",
7109  "Error: Client did not specify content length");
7110  } else if ((expect != NULL)
7111  && (mg_strcasecmp(expect, "100-continue") != 0)) {
7112  /* Client sent an "Expect: xyz" header and xyz is not 100-continue. */
7113  send_http_error(conn,
7114  417,
7115  "Error: Can not fulfill expectation %s",
7116  expect);
7117  } else {
7118  if (expect != NULL) {
7119  (void)mg_printf(conn, "%s", "HTTP/1.1 100 Continue\r\n\r\n");
7120  conn->status_code = 100;
7121  } else {
7122  conn->status_code = 200;
7123  }
7124 
7125  buffered_len = (int64_t)(conn->data_len) - (int64_t)conn->request_len
7126  - conn->consumed_content;
7127 
7128  /* assert(buffered_len >= 0); */
7129  /* assert(conn->consumed_content == 0); */
7130 
7131  if ((buffered_len < 0) || (conn->consumed_content != 0)) {
7132  send_http_error(conn, 500, "%s", "Error: Size mismatch");
7133  return 0;
7134  }
7135 
7136  if (buffered_len > 0) {
7137  if ((int64_t)buffered_len > conn->content_len) {
7138  buffered_len = (int)conn->content_len;
7139  }
7140  body = conn->buf + conn->request_len + conn->consumed_content;
7141  push_all(conn->ctx, fp, sock, ssl, body, (int64_t)buffered_len);
7142  conn->consumed_content += buffered_len;
7143  }
7144 
7145  nread = 0;
7146  while (conn->consumed_content < conn->content_len) {
7147  to_read = sizeof(buf);
7148  if ((int64_t)to_read > conn->content_len - conn->consumed_content) {
7149  to_read = (int)(conn->content_len - conn->consumed_content);
7150  }
7151  nread = pull(NULL, conn, buf, to_read, timeout);
7152  if (nread <= 0
7153  || push_all(conn->ctx, fp, sock, ssl, buf, nread) != nread) {
7154  break;
7155  }
7156  conn->consumed_content += nread;
7157  }
7158 
7159  if (conn->consumed_content == conn->content_len) {
7160  success = (nread >= 0);
7161  }
7162 
7163  /* Each error code path in this function must send an error */
7164  if (!success) {
7165  /* NOTE: Maybe some data has already been sent. */
7166  /* TODO (low): If some data has been sent, a correct error
7167  * reply can no longer be sent, so just close the connection */
7168  send_http_error(conn, 500, "%s", "");
7169  }
7170  }
7171 
7172  return success;
7173 }
7174 #endif
7175 
7176 #if !defined(NO_CGI)
7177 /* This structure helps to create an environment for the spawned CGI program.
7178  * Environment is an array of "VARIABLE=VALUE\0" ASCIIZ strings,
7179  * last element must be NULL.
7180  * However, on Windows there is a requirement that all these VARIABLE=VALUE\0
7181  * strings must reside in a contiguous buffer. The end of the buffer is
7182  * marked by two '\0' characters.
7183  * We satisfy both worlds: we create an envp array (which is vars), all
7184  * entries are actually pointers inside buf. */
7185 struct cgi_environment {
7186  struct mg_connection *conn;
7187  /* Data block */
7188  char *buf; /* Environment buffer */
7189  size_t buflen; /* Space available in buf */
7190  size_t bufused; /* Space taken in buf */
7191  /* Index block */
7192  char **var; /* char **envp */
7193  size_t varlen; /* Number of variables available in var */
7194  size_t varused; /* Number of variables stored in var */
7195 };
7196 
7197 
7198 static void addenv(struct cgi_environment *env,
7199  PRINTF_FORMAT_STRING(const char *fmt),
7200  ...) PRINTF_ARGS(2, 3);
7201 
7202 /* Append VARIABLE=VALUE\0 string to the buffer, and add a respective
7203  * pointer into the vars array. Assumes env != NULL and fmt != NULL. */
7204 static void
7205 addenv(struct cgi_environment *env, const char *fmt, ...)
7206 {
7207  size_t n, space;
7208  int truncated = 0;
7209  char *added;
7210  va_list ap;
7211 
7212  /* Calculate how much space is left in the buffer */
7213  space = (env->buflen - env->bufused);
7214 
7215  /* Calculate an estimate for the required space */
7216  n = strlen(fmt) + 2 + 128;
7217 
7218  do {
7219  if (space <= n) {
7220  /* Allocate new buffer */
7221  n = env->buflen + CGI_ENVIRONMENT_SIZE;
7222  added = (char *)mg_realloc(env->buf, n);
7223  if (!added) {
7224  /* Out of memory */
7225  mg_cry(env->conn,
7226  "%s: Cannot allocate memory for CGI variable [%s]",
7227  __func__,
7228  fmt);
7229  return;
7230  }
7231  env->buf = added;
7232  env->buflen = n;
7233  space = (env->buflen - env->bufused);
7234  }
7235 
7236  /* Make a pointer to the free space int the buffer */
7237  added = env->buf + env->bufused;
7238 
7239  /* Copy VARIABLE=VALUE\0 string into the free space */
7240  va_start(ap, fmt);
7241  mg_vsnprintf(env->conn, &truncated, added, (size_t)space, fmt, ap);
7242  va_end(ap);
7243 
7244  /* Do not add truncated strings to the environment */
7245  if (truncated) {
7246  /* Reallocate the buffer */
7247  space = 0;
7248  n = 1;
7249  }
7250  } while (truncated);
7251 
7252  /* Calculate number of bytes added to the environment */
7253  n = strlen(added) + 1;
7254  env->bufused += n;
7255 
7256  /* Now update the variable index */
7257  space = (env->varlen - env->varused);
7258  if (space < 2) {
7259  mg_cry(env->conn,
7260  "%s: Cannot register CGI variable [%s]",
7261  __func__,
7262  fmt);
7263  return;
7264  }
7265 
7266  /* Append a pointer to the added string into the envp array */
7267  env->var[env->varused] = added;
7268  env->varused++;
7269 }
7270 
7271 
7272 static void
7273 prepare_cgi_environment(struct mg_connection *conn,
7274  const char *prog,
7275  struct cgi_environment *env)
7276 {
7277  const char *s;
7278  struct vec var_vec;
7279  char *p, src_addr[IP_ADDR_STR_LEN], http_var_name[128];
7280  int i, truncated;
7281 
7282  if (conn == NULL || prog == NULL || env == NULL) {
7283  return;
7284  }
7285 
7286  env->conn = conn;
7287  env->buflen = CGI_ENVIRONMENT_SIZE;
7288  env->bufused = 0;
7289  env->buf = (char *)mg_malloc(env->buflen);
7290  env->varlen = MAX_CGI_ENVIR_VARS;
7291  env->varused = 0;
7292  env->var = (char **)mg_malloc(env->buflen * sizeof(char *));
7293 
7294  addenv(env, "SERVER_NAME=%s", conn->ctx->config[AUTHENTICATION_DOMAIN]);
7295  addenv(env, "SERVER_ROOT=%s", conn->ctx->config[DOCUMENT_ROOT]);
7296  addenv(env, "DOCUMENT_ROOT=%s", conn->ctx->config[DOCUMENT_ROOT]);
7297  addenv(env, "SERVER_SOFTWARE=%s/%s", "Civetweb", mg_version());
7298 
7299  /* Prepare the environment block */
7300  addenv(env, "%s", "GATEWAY_INTERFACE=CGI/1.1");
7301  addenv(env, "%s", "SERVER_PROTOCOL=HTTP/1.1");
7302  addenv(env, "%s", "REDIRECT_STATUS=200"); /* For PHP */
7303 
7304 #if defined(USE_IPV6)
7305  if (conn->client.lsa.sa.sa_family == AF_INET6) {
7306  addenv(env, "SERVER_PORT=%d", ntohs(conn->client.lsa.sin6.sin6_port));
7307  } else
7308 #endif
7309  {
7310  addenv(env, "SERVER_PORT=%d", ntohs(conn->client.lsa.sin.sin_port));
7311  }
7312 
7313  sockaddr_to_string(src_addr, sizeof(src_addr), &conn->client.rsa);
7314  addenv(env, "REMOTE_ADDR=%s", src_addr);
7315 
7316  addenv(env, "REQUEST_METHOD=%s", conn->request_info.request_method);
7317  addenv(env, "REMOTE_PORT=%d", conn->request_info.remote_port);
7318 
7319  addenv(env, "REQUEST_URI=%s", conn->request_info.request_uri);
7320  addenv(env, "LOCAL_URI=%s", conn->request_info.local_uri);
7321 
7322  /* SCRIPT_NAME */
7323  addenv(env,
7324  "SCRIPT_NAME=%.*s",
7325  (int)strlen(conn->request_info.local_uri)
7326  - ((conn->path_info == NULL) ? 0 : (int)strlen(conn->path_info)),
7327  conn->request_info.local_uri);
7328 
7329  addenv(env, "SCRIPT_FILENAME=%s", prog);
7330  if (conn->path_info == NULL) {
7331  addenv(env, "PATH_TRANSLATED=%s", conn->ctx->config[DOCUMENT_ROOT]);
7332  } else {
7333  addenv(env,
7334  "PATH_TRANSLATED=%s%s",
7335  conn->ctx->config[DOCUMENT_ROOT],
7336  conn->path_info);
7337  }
7338 
7339  addenv(env, "HTTPS=%s", conn->ssl == NULL ? "off" : "on");
7340 
7341  if ((s = mg_get_header(conn, "Content-Type")) != NULL) {
7342  addenv(env, "CONTENT_TYPE=%s", s);
7343  }
7344  if (conn->request_info.query_string != NULL) {
7345  addenv(env, "QUERY_STRING=%s", conn->request_info.query_string);
7346  }
7347  if ((s = mg_get_header(conn, "Content-Length")) != NULL) {
7348  addenv(env, "CONTENT_LENGTH=%s", s);
7349  }
7350  if ((s = getenv("PATH")) != NULL) {
7351  addenv(env, "PATH=%s", s);
7352  }
7353  if (conn->path_info != NULL) {
7354  addenv(env, "PATH_INFO=%s", conn->path_info);
7355  }
7356 
7357  if (conn->status_code > 0) {
7358  /* CGI error handler should show the status code */
7359  addenv(env, "STATUS=%d", conn->status_code);
7360  }
7361 
7362 #if defined(_WIN32)
7363  if ((s = getenv("COMSPEC")) != NULL) {
7364  addenv(env, "COMSPEC=%s", s);
7365  }
7366  if ((s = getenv("SYSTEMROOT")) != NULL) {
7367  addenv(env, "SYSTEMROOT=%s", s);
7368  }
7369  if ((s = getenv("SystemDrive")) != NULL) {
7370  addenv(env, "SystemDrive=%s", s);
7371  }
7372  if ((s = getenv("ProgramFiles")) != NULL) {
7373  addenv(env, "ProgramFiles=%s", s);
7374  }
7375  if ((s = getenv("ProgramFiles(x86)")) != NULL) {
7376  addenv(env, "ProgramFiles(x86)=%s", s);
7377  }
7378 #else
7379  if ((s = getenv("LD_LIBRARY_PATH")) != NULL) {
7380  addenv(env, "LD_LIBRARY_PATH=%s", s);
7381  }
7382 #endif /* _WIN32 */
7383 
7384  if ((s = getenv("PERLLIB")) != NULL) {
7385  addenv(env, "PERLLIB=%s", s);
7386  }
7387 
7388  if (conn->request_info.remote_user != NULL) {
7389  addenv(env, "REMOTE_USER=%s", conn->request_info.remote_user);
7390  addenv(env, "%s", "AUTH_TYPE=Digest");
7391  }
7392 
7393  /* Add all headers as HTTP_* variables */
7394  for (i = 0; i < conn->request_info.num_headers; i++) {
7395 
7396  (void)mg_snprintf(conn,
7397  &truncated,
7398  http_var_name,
7399  sizeof(http_var_name),
7400  "HTTP_%s",
7401  conn->request_info.http_headers[i].name);
7402 
7403  if (truncated) {
7404  mg_cry(conn,
7405  "%s: HTTP header variable too long [%s]",
7406  __func__,
7407  conn->request_info.http_headers[i].name);
7408  continue;
7409  }
7410 
7411  /* Convert variable name into uppercase, and change - to _ */
7412  for (p = http_var_name; *p != '\0'; p++) {
7413  if (*p == '-') {
7414  *p = '_';
7415  }
7416  *p = (char)toupper(*(unsigned char *)p);
7417  }
7418 
7419  addenv(env,
7420  "%s=%s",
7421  http_var_name,
7422  conn->request_info.http_headers[i].value);
7423  }
7424 
7425  /* Add user-specified variables */
7426  s = conn->ctx->config[CGI_ENVIRONMENT];
7427  while ((s = next_option(s, &var_vec, NULL)) != NULL) {
7428  addenv(env, "%.*s", (int)var_vec.len, var_vec.ptr);
7429  }
7430 
7431  env->var[env->varused] = NULL;
7432  env->buf[env->bufused] = '\0';
7433 }
7434 
7435 
7436 static void
7437 handle_cgi_request(struct mg_connection *conn, const char *prog)
7438 {
7439  char *buf;
7440  size_t buflen;
7441  int headers_len, data_len, i, truncated;
7442  int fdin[2] = {-1, -1}, fdout[2] = {-1, -1}, fderr[2] = {-1, -1};
7443  const char *status, *status_text, *connection_state;
7444  char *pbuf, dir[PATH_MAX], *p;
7445  struct mg_request_info ri;
7446  struct cgi_environment blk;
7447  FILE *in = NULL, *out = NULL, *err = NULL;
7448  struct file fout = STRUCT_FILE_INITIALIZER;
7449  pid_t pid = (pid_t)-1;
7450 
7451  if (conn == NULL) {
7452  return;
7453  }
7454 
7455  buf = NULL;
7456  buflen = 16384;
7457  prepare_cgi_environment(conn, prog, &blk);
7458 
7459  /* CGI must be executed in its own directory. 'dir' must point to the
7460  * directory containing executable program, 'p' must point to the
7461  * executable program name relative to 'dir'. */
7462  (void)mg_snprintf(conn, &truncated, dir, sizeof(dir), "%s", prog);
7463 
7464  if (truncated) {
7465  mg_cry(conn, "Error: CGI program \"%s\": Path too long", prog);
7466  send_http_error(conn, 500, "Error: %s", "CGI path too long");
7467  goto done;
7468  }
7469 
7470  if ((p = strrchr(dir, '/')) != NULL) {
7471  *p++ = '\0';
7472  } else {
7473  dir[0] = '.', dir[1] = '\0';
7474  p = (char *)prog;
7475  }
7476 
7477  if (pipe(fdin) != 0 || pipe(fdout) != 0 || pipe(fderr) != 0) {
7478  status = strerror(ERRNO);
7479  mg_cry(conn,
7480  "Error: CGI program \"%s\": Can not create CGI pipes: %s",
7481  prog,
7482  status);
7483  send_http_error(conn, 500, "Error: Cannot create CGI pipe: %s", status);
7484  goto done;
7485  }
7486 
7487  pid = spawn_process(conn, p, blk.buf, blk.var, fdin, fdout, fderr, dir);
7488 
7489  if (pid == (pid_t)-1) {
7490  status = strerror(ERRNO);
7491  mg_cry(conn,
7492  "Error: CGI program \"%s\": Can not spawn CGI process: %s",
7493  prog,
7494  status);
7495  send_http_error(conn,
7496  500,
7497  "Error: Cannot spawn CGI process [%s]: %s",
7498  prog,
7499  status);
7500  goto done;
7501  }
7502 
7503  /* Make sure child closes all pipe descriptors. It must dup them to 0,1 */
7504  set_close_on_exec((SOCKET)fdin[0], conn); /* stdin read */
7505  set_close_on_exec((SOCKET)fdout[1], conn); /* stdout write */
7506  set_close_on_exec((SOCKET)fderr[1], conn); /* stderr write */
7507  set_close_on_exec((SOCKET)fdin[1], conn); /* stdin write */
7508  set_close_on_exec((SOCKET)fdout[0], conn); /* stdout read */
7509  set_close_on_exec((SOCKET)fderr[0], conn); /* stderr read */
7510 
7511  /* Parent closes only one side of the pipes.
7512  * If we don't mark them as closed, close() attempt before
7513  * return from this function throws an exception on Windows.
7514  * Windows does not like when closed descriptor is closed again. */
7515  (void)close(fdin[0]);
7516  (void)close(fdout[1]);
7517  (void)close(fderr[1]);
7518  fdin[0] = fdout[1] = fderr[1] = -1;
7519 
7520  if ((in = fdopen(fdin[1], "wb")) == NULL) {
7521  status = strerror(ERRNO);
7522  mg_cry(conn,
7523  "Error: CGI program \"%s\": Can not open stdin: %s",
7524  prog,
7525  status);
7526  send_http_error(conn,
7527  500,
7528  "Error: CGI can not open fdin\nfopen: %s",
7529  status);
7530  goto done;
7531  }
7532 
7533  if ((out = fdopen(fdout[0], "rb")) == NULL) {
7534  status = strerror(ERRNO);
7535  mg_cry(conn,
7536  "Error: CGI program \"%s\": Can not open stdout: %s",
7537  prog,
7538  status);
7539  send_http_error(conn,
7540  500,
7541  "Error: CGI can not open fdout\nfopen: %s",
7542  status);
7543  goto done;
7544  }
7545 
7546  if ((err = fdopen(fderr[0], "rb")) == NULL) {
7547  status = strerror(ERRNO);
7548  mg_cry(conn,
7549  "Error: CGI program \"%s\": Can not open stderr: %s",
7550  prog,
7551  status);
7552  send_http_error(conn,
7553  500,
7554  "Error: CGI can not open fdout\nfopen: %s",
7555  status);
7556  goto done;
7557  }
7558 
7559  setbuf(in, NULL);
7560  setbuf(out, NULL);
7561  setbuf(err, NULL);
7562  fout.fp = out;
7563 
7564  if ((conn->request_info.content_length > 0) || conn->is_chunked) {
7565  /* This is a POST/PUT request, or another request with body data. */
7566  if (!forward_body_data(conn, in, INVALID_SOCKET, NULL)) {
7567  /* Error sending the body data */
7568  mg_cry(conn,
7569  "Error: CGI program \"%s\": Forward body data failed",
7570  prog);
7571  goto done;
7572  }
7573  }
7574 
7575  /* Close so child gets an EOF. */
7576  fclose(in);
7577  in = NULL;
7578  fdin[1] = -1;
7579 
7580  /* Now read CGI reply into a buffer. We need to set correct
7581  * status code, thus we need to see all HTTP headers first.
7582  * Do not send anything back to client, until we buffer in all
7583  * HTTP headers. */
7584  data_len = 0;
7585  buf = (char *)mg_malloc(buflen);
7586  if (buf == NULL) {
7587  send_http_error(conn,
7588  500,
7589  "Error: Not enough memory for CGI buffer (%u bytes)",
7590  (unsigned int)buflen);
7591  mg_cry(conn,
7592  "Error: CGI program \"%s\": Not enough memory for buffer (%u "
7593  "bytes)",
7594  prog,
7595  (unsigned int)buflen);
7596  goto done;
7597  }
7598  headers_len = read_request(out, conn, buf, (int)buflen, &data_len);
7599  if (headers_len <= 0) {
7600 
7601  /* Could not parse the CGI response. Check if some error message on
7602  * stderr. */
7603  i = pull_all(err, conn, buf, (int)buflen);
7604  if (i > 0) {
7605  mg_cry(conn,
7606  "Error: CGI program \"%s\" sent error "
7607  "message: [%.*s]",
7608  prog,
7609  i,
7610  buf);
7611  send_http_error(conn,
7612  500,
7613  "Error: CGI program \"%s\" sent error "
7614  "message: [%.*s]",
7615  prog,
7616  i,
7617  buf);
7618  } else {
7619  mg_cry(conn,
7620  "Error: CGI program sent malformed or too big "
7621  "(>%u bytes) HTTP headers: [%.*s]",
7622  (unsigned)buflen,
7623  data_len,
7624  buf);
7625 
7626  send_http_error(conn,
7627  500,
7628  "Error: CGI program sent malformed or too big "
7629  "(>%u bytes) HTTP headers: [%.*s]",
7630  (unsigned)buflen,
7631  data_len,
7632  buf);
7633  }
7634 
7635  goto done;
7636  }
7637  pbuf = buf;
7638  buf[headers_len - 1] = '\0';
7639  parse_http_headers(&pbuf, &ri);
7640 
7641  /* Make up and send the status line */
7642  status_text = "OK";
7643  if ((status = get_header(&ri, "Status")) != NULL) {
7644  conn->status_code = atoi(status);
7645  status_text = status;
7646  while (isdigit(*(const unsigned char *)status_text)
7647  || *status_text == ' ') {
7648  status_text++;
7649  }
7650  } else if (get_header(&ri, "Location") != NULL) {
7651  conn->status_code = 302;
7652  } else {
7653  conn->status_code = 200;
7654  }
7655  connection_state = get_header(&ri, "Connection");
7656  if (!header_has_option(connection_state, "keep-alive")) {
7657  conn->must_close = 1;
7658  }
7659  (void)mg_printf(conn, "HTTP/1.1 %d %s\r\n", conn->status_code, status_text);
7660 
7661  /* Send headers */
7662  for (i = 0; i < ri.num_headers; i++) {
7663  mg_printf(conn,
7664  "%s: %s\r\n",
7665  ri.http_headers[i].name,
7666  ri.http_headers[i].value);
7667  }
7668  mg_write(conn, "\r\n", 2);
7669 
7670  /* Send chunk of data that may have been read after the headers */
7671  conn->num_bytes_sent +=
7672  mg_write(conn, buf + headers_len, (size_t)(data_len - headers_len));
7673 
7674  /* Read the rest of CGI output and send to the client */
7675  send_file_data(conn, &fout, 0, INT64_MAX);
7676 
7677 done:
7678  mg_free(blk.var);
7679  mg_free(blk.buf);
7680 
7681  if (pid != (pid_t)-1) {
7682  kill(pid, SIGKILL);
7683 #if !defined(_WIN32)
7684  {
7685  int st;
7686  while (waitpid(pid, &st, 0) != -1)
7687  ; /* clean zombies */
7688  }
7689 #endif
7690  }
7691  if (fdin[0] != -1) {
7692  close(fdin[0]);
7693  }
7694  if (fdout[1] != -1) {
7695  close(fdout[1]);
7696  }
7697 
7698  if (in != NULL) {
7699  fclose(in);
7700  } else if (fdin[1] != -1) {
7701  close(fdin[1]);
7702  }
7703 
7704  if (out != NULL) {
7705  fclose(out);
7706  } else if (fdout[0] != -1) {
7707  close(fdout[0]);
7708  }
7709 
7710  if (err != NULL) {
7711  fclose(err);
7712  } else if (fderr[0] != -1) {
7713  close(fderr[0]);
7714  }
7715 
7716  if (buf != NULL) {
7717  mg_free(buf);
7718  }
7719 }
7720 #endif /* !NO_CGI */
7721 
7722 
7723 #if !defined(NO_FILES)
7724 static void
7725 mkcol(struct mg_connection *conn, const char *path)
7726 {
7727  int rc, body_len;
7728  struct de de;
7729  char date[64];
7730  time_t curtime = time(NULL);
7731 
7732  if (conn == NULL) {
7733  return;
7734  }
7735 
7736  /* TODO (mid): Check the send_http_error situations in this function */
7737 
7738  memset(&de.file, 0, sizeof(de.file));
7739  if (!mg_stat(conn, path, &de.file)) {
7740  mg_cry(conn,
7741  "%s: mg_stat(%s) failed: %s",
7742  __func__,
7743  path,
7744  strerror(ERRNO));
7745  }
7746 
7747  if (de.file.last_modified) {
7748  /* TODO (high): This check does not seem to make any sense ! */
7750  conn, 405, "Error: mkcol(%s): %s", path, strerror(ERRNO));
7751  return;
7752  }
7753 
7754  body_len = conn->data_len - conn->request_len;
7755  if (body_len > 0) {
7757  conn, 415, "Error: mkcol(%s): %s", path, strerror(ERRNO));
7758  return;
7759  }
7760 
7761  rc = mg_mkdir(conn, path, 0755);
7762 
7763  if (rc == 0) {
7764  conn->status_code = 201;
7765  gmt_time_string(date, sizeof(date), &curtime);
7766  mg_printf(conn,
7767  "HTTP/1.1 %d Created\r\n"
7768  "Date: %s\r\n",
7769  conn->status_code,
7770  date);
7772  mg_printf(conn,
7773  "Content-Length: 0\r\n"
7774  "Connection: %s\r\n\r\n",
7776  } else if (rc == -1) {
7777  if (errno == EEXIST) {
7779  conn, 405, "Error: mkcol(%s): %s", path, strerror(ERRNO));
7780  } else if (errno == EACCES) {
7782  conn, 403, "Error: mkcol(%s): %s", path, strerror(ERRNO));
7783  } else if (errno == ENOENT) {
7785  conn, 409, "Error: mkcol(%s): %s", path, strerror(ERRNO));
7786  } else {
7787  send_http_error(conn, 500, "fopen(%s): %s", path, strerror(ERRNO));
7788  }
7789  }
7790 }
7791 
7792 
7793 static void
7794 put_file(struct mg_connection *conn, const char *path)
7795 {
7796  struct file file = STRUCT_FILE_INITIALIZER;
7797  const char *range;
7798  int64_t r1, r2;
7799  int rc;
7800  char date[64];
7801  time_t curtime = time(NULL);
7802 
7803  if (conn == NULL) {
7804  return;
7805  }
7806 
7807  if (mg_stat(conn, path, &file)) {
7808  /* File already exists */
7809  conn->status_code = 200;
7810 
7811  if (file.is_directory) {
7812  /* This is an already existing directory,
7813  * so there is nothing to do for the server. */
7814  rc = 0;
7815 
7816  } else {
7817  /* File exists and is not a directory. */
7818  /* Can it be replaced? */
7819 
7820  if (file.membuf != NULL) {
7821  /* This is an "in-memory" file, that can not be replaced */
7823  conn,
7824  405,
7825  "Error: Put not possible\nReplacing %s is not supported",
7826  path);
7827  return;
7828  }
7829 
7830  /* Check if the server may write this file */
7831  if (access(path, W_OK) == 0) {
7832  /* Access granted */
7833  conn->status_code = 200;
7834  rc = 1;
7835  } else {
7837  conn,
7838  403,
7839  "Error: Put not possible\nReplacing %s is not allowed",
7840  path);
7841  return;
7842  }
7843  }
7844  } else {
7845  /* File should be created */
7846  conn->status_code = 201;
7847  rc = put_dir(conn, path);
7848  }
7849 
7850  if (rc == 0) {
7851  /* put_dir returns 0 if path is a directory */
7852  gmt_time_string(date, sizeof(date), &curtime);
7853  mg_printf(conn,
7854  "HTTP/1.1 %d %s\r\n",
7855  conn->status_code,
7856  mg_get_response_code_text(NULL, conn->status_code));
7857  send_no_cache_header(conn);
7858  mg_printf(conn,
7859  "Date: %s\r\n"
7860  "Content-Length: 0\r\n"
7861  "Connection: %s\r\n\r\n",
7862  date,
7864 
7865  /* Request to create a directory has been fulfilled successfully.
7866  * No need to put a file. */
7867  return;
7868  }
7869 
7870  if (rc == -1) {
7871  /* put_dir returns -1 if the path is too long */
7872  send_http_error(conn,
7873  414,
7874  "Error: Path too long\nput_dir(%s): %s",
7875  path,
7876  strerror(ERRNO));
7877  return;
7878  }
7879 
7880  if (rc == -2) {
7881  /* put_dir returns -2 if the directory can not be created */
7882  send_http_error(conn,
7883  500,
7884  "Error: Can not create directory\nput_dir(%s): %s",
7885  path,
7886  strerror(ERRNO));
7887  return;
7888  }
7889 
7890  /* A file should be created or overwritten. */
7891  if (!mg_fopen(conn, path, "wb+", &file) || file.fp == NULL) {
7892  mg_fclose(&file);
7893  send_http_error(conn,
7894  500,
7895  "Error: Can not create file\nfopen(%s): %s",
7896  path,
7897  strerror(ERRNO));
7898  return;
7899  }
7900 
7901  fclose_on_exec(&file, conn);
7902  range = mg_get_header(conn, "Content-Range");
7903  r1 = r2 = 0;
7904  if (range != NULL && parse_range_header(range, &r1, &r2) > 0) {
7905  conn->status_code = 206; /* Partial content */
7906  fseeko(file.fp, r1, SEEK_SET);
7907  }
7908 
7909  if (!forward_body_data(conn, file.fp, INVALID_SOCKET, NULL)) {
7910  /* forward_body_data failed.
7911  * The error code has already been sent to the client,
7912  * and conn->status_code is already set. */
7913  mg_fclose(&file);
7914  return;
7915  }
7916 
7917  gmt_time_string(date, sizeof(date), &curtime);
7918  mg_printf(conn,
7919  "HTTP/1.1 %d %s\r\n",
7920  conn->status_code,
7921  mg_get_response_code_text(NULL, conn->status_code));
7922  send_no_cache_header(conn);
7923  mg_printf(conn,
7924  "Date: %s\r\n"
7925  "Content-Length: 0\r\n"
7926  "Connection: %s\r\n\r\n",
7927  date,
7929 
7930  mg_fclose(&file);
7931 }
7932 
7933 
7934 static void
7935 delete_file(struct mg_connection *conn, const char *path)
7936 {
7937  struct de de;
7938  memset(&de.file, 0, sizeof(de.file));
7939  if (!mg_stat(conn, path, &de.file)) {
7940  /* mg_stat returns 0 if the file does not exist */
7941  send_http_error(conn,
7942  404,
7943  "Error: Cannot delete file\nFile %s not found",
7944  path);
7945  return;
7946  }
7947 
7948  if (de.file.membuf != NULL) {
7949  /* the file is cached in memory */
7951  conn,
7952  405,
7953  "Error: Delete not possible\nDeleting %s is not supported",
7954  path);
7955  return;
7956  }
7957 
7958  if (de.file.is_directory) {
7959  if (remove_directory(conn, path)) {
7960  /* Delete is successful: Return 204 without content. */
7961  send_http_error(conn, 204, "%s", "");
7962  } else {
7963  /* Delete is not successful: Return 500 (Server error). */
7964  send_http_error(conn, 500, "Error: Could not delete %s", path);
7965  }
7966  return;
7967  }
7968 
7969  /* This is an existing file (not a directory).
7970  * Check if write permission is granted. */
7971  if (access(path, W_OK) != 0) {
7972  /* File is read only */
7974  conn,
7975  403,
7976  "Error: Delete not possible\nDeleting %s is not allowed",
7977  path);
7978  return;
7979  }
7980 
7981  /* Try to delete it. */
7982  if (mg_remove(conn, path) == 0) {
7983  /* Delete was successful: Return 204 without content. */
7984  send_http_error(conn, 204, "%s", "");
7985  } else {
7986  /* Delete not successful (file locked). */
7987  send_http_error(conn,
7988  423,
7989  "Error: Cannot delete file\nremove(%s): %s",
7990  path,
7991  strerror(ERRNO));
7992  }
7993 }
7994 #endif /* !NO_FILES */
7995 
7996 
7997 static void
7998 send_ssi_file(struct mg_connection *, const char *, struct file *, int);
7999 
8000 
8001 static void
8002 do_ssi_include(struct mg_connection *conn,
8003  const char *ssi,
8004  char *tag,
8005  int include_level)
8006 {
8007  char file_name[MG_BUF_LEN], path[512], *p;
8008  struct file file = STRUCT_FILE_INITIALIZER;
8009  size_t len;
8010  int truncated = 0;
8011 
8012  if (conn == NULL) {
8013  return;
8014  }
8015 
8016  /* sscanf() is safe here, since send_ssi_file() also uses buffer
8017  * of size MG_BUF_LEN to get the tag. So strlen(tag) is
8018  * always < MG_BUF_LEN. */
8019  if (sscanf(tag, " virtual=\"%511[^\"]\"", file_name) == 1) {
8020  /* File name is relative to the webserver root */
8021  file_name[511] = 0;
8022  (void)mg_snprintf(conn,
8023  &truncated,
8024  path,
8025  sizeof(path),
8026  "%s/%s",
8027  conn->ctx->config[DOCUMENT_ROOT],
8028  file_name);
8029 
8030  } else if (sscanf(tag, " abspath=\"%511[^\"]\"", file_name) == 1) {
8031  /* File name is relative to the webserver working directory
8032  * or it is absolute system path */
8033  file_name[511] = 0;
8034  (void)
8035  mg_snprintf(conn, &truncated, path, sizeof(path), "%s", file_name);
8036 
8037  } else if (sscanf(tag, " file=\"%511[^\"]\"", file_name) == 1
8038  || sscanf(tag, " \"%511[^\"]\"", file_name) == 1) {
8039  /* File name is relative to the currect document */
8040  file_name[511] = 0;
8041  (void)mg_snprintf(conn, &truncated, path, sizeof(path), "%s", ssi);
8042 
8043  if (!truncated) {
8044  if ((p = strrchr(path, '/')) != NULL) {
8045  p[1] = '\0';
8046  }
8047  len = strlen(path);
8048  (void)mg_snprintf(conn,
8049  &truncated,
8050  path + len,
8051  sizeof(path) - len,
8052  "%s",
8053  file_name);
8054  }
8055 
8056  } else {
8057  mg_cry(conn, "Bad SSI #include: [%s]", tag);
8058  return;
8059  }
8060 
8061  if (truncated) {
8062  mg_cry(conn, "SSI #include path length overflow: [%s]", tag);
8063  return;
8064  }
8065 
8066  if (!mg_fopen(conn, path, "rb", &file)) {
8067  mg_cry(conn,
8068  "Cannot open SSI #include: [%s]: fopen(%s): %s",
8069  tag,
8070  path,
8071  strerror(ERRNO));
8072  } else {
8073  fclose_on_exec(&file, conn);
8074  if (match_prefix(conn->ctx->config[SSI_EXTENSIONS],
8075  strlen(conn->ctx->config[SSI_EXTENSIONS]),
8076  path) > 0) {
8077  send_ssi_file(conn, path, &file, include_level + 1);
8078  } else {
8079  send_file_data(conn, &file, 0, INT64_MAX);
8080  }
8081  mg_fclose(&file);
8082  }
8083 }
8084 
8085 
8086 #if !defined(NO_POPEN)
8087 static void
8088 do_ssi_exec(struct mg_connection *conn, char *tag)
8089 {
8090  char cmd[1024] = "";
8091  struct file file = STRUCT_FILE_INITIALIZER;
8092 
8093  if (sscanf(tag, " \"%1023[^\"]\"", cmd) != 1) {
8094  mg_cry(conn, "Bad SSI #exec: [%s]", tag);
8095  } else {
8096  cmd[1023] = 0;
8097  if ((file.fp = popen(cmd, "r")) == NULL) {
8098  mg_cry(conn, "Cannot SSI #exec: [%s]: %s", cmd, strerror(ERRNO));
8099  } else {
8100  send_file_data(conn, &file, 0, INT64_MAX);
8101  pclose(file.fp);
8102  }
8103  }
8104 }
8105 #endif /* !NO_POPEN */
8106 
8107 
8108 static int
8109 mg_fgetc(struct file *filep, int offset)
8110 {
8111  if (filep == NULL) {
8112  return EOF;
8113  }
8114  if (filep->membuf != NULL && offset >= 0
8115  && ((unsigned int)(offset)) < filep->size) {
8116  return ((const unsigned char *)filep->membuf)[offset];
8117  } else if (filep->fp != NULL) {
8118  return fgetc(filep->fp);
8119  } else {
8120  return EOF;
8121  }
8122 }
8123 
8124 
8125 static void
8126 send_ssi_file(struct mg_connection *conn,
8127  const char *path,
8128  struct file *filep,
8129  int include_level)
8130 {
8131  char buf[MG_BUF_LEN];
8132  int ch, offset, len, in_ssi_tag;
8133 
8134  if (include_level > 10) {
8135  mg_cry(conn, "SSI #include level is too deep (%s)", path);
8136  return;
8137  }
8138 
8139  in_ssi_tag = len = offset = 0;
8140  while ((ch = mg_fgetc(filep, offset)) != EOF) {
8141  if (in_ssi_tag && ch == '>') {
8142  in_ssi_tag = 0;
8143  buf[len++] = (char)ch;
8144  buf[len] = '\0';
8145  /* assert(len <= (int) sizeof(buf)); */
8146  if (len > (int)sizeof(buf)) {
8147  break;
8148  }
8149  if (len < 6 || memcmp(buf, "<!--#", 5) != 0) {
8150  /* Not an SSI tag, pass it */
8151  (void)mg_write(conn, buf, (size_t)len);
8152  } else {
8153  if (!memcmp(buf + 5, "include", 7)) {
8154  do_ssi_include(conn, path, buf + 12, include_level);
8155 #if !defined(NO_POPEN)
8156  } else if (!memcmp(buf + 5, "exec", 4)) {
8157  do_ssi_exec(conn, buf + 9);
8158 #endif /* !NO_POPEN */
8159  } else {
8160  mg_cry(conn,
8161  "%s: unknown SSI "
8162  "command: \"%s\"",
8163  path,
8164  buf);
8165  }
8166  }
8167  len = 0;
8168  } else if (in_ssi_tag) {
8169  if (len == 5 && memcmp(buf, "<!--#", 5) != 0) {
8170  /* Not an SSI tag */
8171  in_ssi_tag = 0;
8172  } else if (len == (int)sizeof(buf) - 2) {
8173  mg_cry(conn, "%s: SSI tag is too large", path);
8174  len = 0;
8175  }
8176  buf[len++] = (char)(ch & 0xff);
8177  } else if (ch == '<') {
8178  in_ssi_tag = 1;
8179  if (len > 0) {
8180  mg_write(conn, buf, (size_t)len);
8181  }
8182  len = 0;
8183  buf[len++] = (char)(ch & 0xff);
8184  } else {
8185  buf[len++] = (char)(ch & 0xff);
8186  if (len == (int)sizeof(buf)) {
8187  mg_write(conn, buf, (size_t)len);
8188  len = 0;
8189  }
8190  }
8191  }
8192 
8193  /* Send the rest of buffered data */
8194  if (len > 0) {
8195  mg_write(conn, buf, (size_t)len);
8196  }
8197 }
8198 
8199 
8200 static void
8201 handle_ssi_file_request(struct mg_connection *conn,
8202  const char *path,
8203  struct file *filep)
8204 {
8205  char date[64];
8206  time_t curtime = time(NULL);
8207  const char *cors1, *cors2, *cors3;
8208 
8209  if (conn == NULL || path == NULL || filep == NULL) {
8210  return;
8211  }
8212 
8213  if (mg_get_header(conn, "Origin")) {
8214  /* Cross-origin resource sharing (CORS). */
8215  cors1 = "Access-Control-Allow-Origin: ";
8216  cors2 = conn->ctx->config[ACCESS_CONTROL_ALLOW_ORIGIN];
8217  cors3 = "\r\n";
8218  } else {
8219  cors1 = cors2 = cors3 = "";
8220  }
8221 
8222  if (!mg_fopen(conn, path, "rb", filep)) {
8223  /* File exists (precondition for calling this function),
8224  * but can not be opened by the server. */
8225  send_http_error(conn,
8226  500,
8227  "Error: Cannot read file\nfopen(%s): %s",
8228  path,
8229  strerror(ERRNO));
8230  } else {
8231  conn->must_close = 1;
8232  gmt_time_string(date, sizeof(date), &curtime);
8233  fclose_on_exec(filep, conn);
8234  mg_printf(conn, "HTTP/1.1 200 OK\r\n");
8235  send_no_cache_header(conn);
8236  mg_printf(conn,
8237  "%s%s%s"
8238  "Date: %s\r\n"
8239  "Content-Type: text/html\r\n"
8240  "Connection: %s\r\n\r\n",
8241  cors1,
8242  cors2,
8243  cors3,
8244  date,
8246  send_ssi_file(conn, path, filep, 0);
8247  mg_fclose(filep);
8248  }
8249 }
8250 
8251 
8252 #if !defined(NO_FILES)
8253 static void
8254 send_options(struct mg_connection *conn)
8255 {
8256  char date[64];
8257  time_t curtime = time(NULL);
8258 
8259  if (!conn) {
8260  return;
8261  }
8262 
8263  conn->status_code = 200;
8264  conn->must_close = 1;
8265  gmt_time_string(date, sizeof(date), &curtime);
8266 
8267  mg_printf(conn,
8268  "HTTP/1.1 200 OK\r\n"
8269  "Date: %s\r\n"
8270  /* TODO: "Cache-Control" (?) */
8271  "Connection: %s\r\n"
8272  "Allow: GET, POST, HEAD, CONNECT, PUT, DELETE, OPTIONS, "
8273  "PROPFIND, MKCOL\r\n"
8274  "DAV: 1\r\n\r\n",
8275  date,
8277 }
8278 
8279 
8280 /* Writes PROPFIND properties for a collection element */
8281 static void
8282 print_props(struct mg_connection *conn, const char *uri, struct file *filep)
8283 {
8284  char mtime[64];
8285 
8286  if (conn == NULL || uri == NULL || filep == NULL) {
8287  return;
8288  }
8289 
8290  gmt_time_string(mtime, sizeof(mtime), &filep->last_modified);
8291  conn->num_bytes_sent +=
8292  mg_printf(conn,
8293  "<d:response>"
8294  "<d:href>%s</d:href>"
8295  "<d:propstat>"
8296  "<d:prop>"
8297  "<d:resourcetype>%s</d:resourcetype>"
8298  "<d:getcontentlength>%" INT64_FMT "</d:getcontentlength>"
8299  "<d:getlastmodified>%s</d:getlastmodified>"
8300  "</d:prop>"
8301  "<d:status>HTTP/1.1 200 OK</d:status>"
8302  "</d:propstat>"
8303  "</d:response>\n",
8304  uri,
8305  filep->is_directory ? "<d:collection/>" : "",
8306  filep->size,
8307  mtime);
8308 }
8309 
8310 
8311 static void
8312 print_dav_dir_entry(struct de *de, void *data)
8313 {
8314  char href[PATH_MAX];
8315  char href_encoded[PATH_MAX];
8316  int truncated;
8317 
8318  struct mg_connection *conn = (struct mg_connection *)data;
8319  if (!de || !conn) {
8320  return;
8321  }
8322  mg_snprintf(conn,
8323  &truncated,
8324  href,
8325  sizeof(href),
8326  "%s%s",
8327  conn->request_info.local_uri,
8328  de->file_name);
8329 
8330  if (!truncated) {
8331  mg_url_encode(href, href_encoded, PATH_MAX - 1);
8332  print_props(conn, href_encoded, &de->file);
8333  }
8334 }
8335 
8336 
8337 static void
8338 handle_propfind(struct mg_connection *conn,
8339  const char *path,
8340  struct file *filep)
8341 {
8342  const char *depth = mg_get_header(conn, "Depth");
8343  char date[64];
8344  time_t curtime = time(NULL);
8345 
8346  gmt_time_string(date, sizeof(date), &curtime);
8347 
8348  if (!conn || !path || !filep || !conn->ctx) {
8349  return;
8350  }
8351 
8352  conn->must_close = 1;
8353  conn->status_code = 207;
8354  mg_printf(conn,
8355  "HTTP/1.1 207 Multi-Status\r\n"
8356  "Date: %s\r\n",
8357  date);
8359  mg_printf(conn,
8360  "Connection: %s\r\n"
8361  "Content-Type: text/xml; charset=utf-8\r\n\r\n",
8363 
8364  conn->num_bytes_sent +=
8365  mg_printf(conn,
8366  "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
8367  "<d:multistatus xmlns:d='DAV:'>\n");
8368 
8369  /* Print properties for the requested resource itself */
8370  print_props(conn, conn->request_info.local_uri, filep);
8371 
8372  /* If it is a directory, print directory entries too if Depth is not 0 */
8373  if (filep && filep->is_directory
8374  && !mg_strcasecmp(conn->ctx->config[ENABLE_DIRECTORY_LISTING], "yes")
8375  && (depth == NULL || strcmp(depth, "0") != 0)) {
8376  scan_directory(conn, path, conn, &print_dav_dir_entry);
8377  }
8378 
8379  conn->num_bytes_sent += mg_printf(conn, "%s\n", "</d:multistatus>");
8380 }
8381 #endif
8382 
8383 void
8384 mg_lock_connection(struct mg_connection *conn)
8385 {
8386  if (conn) {
8387  (void)pthread_mutex_lock(&conn->mutex);
8388  }
8389 }
8390 
8391 void
8392 mg_unlock_connection(struct mg_connection *conn)
8393 {
8394  if (conn) {
8395  (void)pthread_mutex_unlock(&conn->mutex);
8396  }
8397 }
8398 
8399 void
8400 mg_lock_context(struct mg_context *ctx)
8401 {
8402  if (ctx) {
8403  (void)pthread_mutex_lock(&ctx->nonce_mutex);
8404  }
8405 }
8406 
8407 void
8408 mg_unlock_context(struct mg_context *ctx)
8409 {
8410  if (ctx) {
8411  (void)pthread_mutex_unlock(&ctx->nonce_mutex);
8412  }
8413 }
8414 
8415 #if defined(USE_TIMERS)
8416 #include "timer.inl"
8417 #endif /* USE_TIMERS */
8418 
8419 #ifdef USE_LUA
8420 #include "mod_lua.inl"
8421 #endif /* USE_LUA */
8422 
8423 #ifdef USE_DUKTAPE
8424 #include "mod_duktape.inl"
8425 #endif /* USE_DUKTAPE */
8426 
8427 #if defined(USE_WEBSOCKET)
8428 
8429 /* START OF SHA-1 code
8430  * Copyright(c) By Steve Reid <steve@edmweb.com> */
8431 #define SHA1HANDSOFF
8432 
8433 /* According to current tests (May 2015), the <solarisfixes.h> is not required.
8434  *
8435  * #if defined(__sun)
8436  * #include "solarisfixes.h"
8437  * #endif
8438  */
8439 
8440 
8441 static int
8442 is_big_endian(void)
8443 {
8444  static const int n = 1;
8445  return ((char *)&n)[0] == 0;
8446 }
8447 
8448 
8449 union char64long16 {
8450  unsigned char c[64];
8451  uint32_t l[16];
8452 };
8453 
8454 #define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
8455 
8456 
8457 static uint32_t
8458 blk0(union char64long16 *block, int i)
8459 {
8460  /* Forrest: SHA expect BIG_ENDIAN, swap if LITTLE_ENDIAN */
8461  if (!is_big_endian()) {
8462  block->l[i] = (rol(block->l[i], 24) & 0xFF00FF00)
8463  | (rol(block->l[i], 8) & 0x00FF00FF);
8464  }
8465  return block->l[i];
8466 }
8467 
8468 #define blk(i) \
8469  (block->l[i & 15] = rol(block->l[(i + 13) & 15] ^ block->l[(i + 8) & 15] \
8470  ^ block->l[(i + 2) & 15] ^ block->l[i & 15], \
8471  1))
8472 #define R0(v, w, x, y, z, i) \
8473  z += ((w & (x ^ y)) ^ y) + blk0(block, i) + 0x5A827999 + rol(v, 5); \
8474  w = rol(w, 30);
8475 #define R1(v, w, x, y, z, i) \
8476  z += ((w & (x ^ y)) ^ y) + blk(i) + 0x5A827999 + rol(v, 5); \
8477  w = rol(w, 30);
8478 #define R2(v, w, x, y, z, i) \
8479  z += (w ^ x ^ y) + blk(i) + 0x6ED9EBA1 + rol(v, 5); \
8480  w = rol(w, 30);
8481 #define R3(v, w, x, y, z, i) \
8482  z += (((w | x) & y) | (w & x)) + blk(i) + 0x8F1BBCDC + rol(v, 5); \
8483  w = rol(w, 30);
8484 #define R4(v, w, x, y, z, i) \
8485  z += (w ^ x ^ y) + blk(i) + 0xCA62C1D6 + rol(v, 5); \
8486  w = rol(w, 30);
8487 
8488 
8489 typedef struct {
8490  uint32_t state[5];
8491  uint32_t count[2];
8492  unsigned char buffer[64];
8493 } SHA1_CTX;
8494 
8495 
8496 static void
8497 SHA1Transform(uint32_t state[5], const unsigned char buffer[64])
8498 {
8499  uint32_t a, b, c, d, e;
8500  union char64long16 block[1];
8501 
8502  memcpy(block, buffer, 64);
8503  a = state[0];
8504  b = state[1];
8505  c = state[2];
8506  d = state[3];
8507  e = state[4];
8508  R0(a, b, c, d, e, 0);
8509  R0(e, a, b, c, d, 1);
8510  R0(d, e, a, b, c, 2);
8511  R0(c, d, e, a, b, 3);
8512  R0(b, c, d, e, a, 4);
8513  R0(a, b, c, d, e, 5);
8514  R0(e, a, b, c, d, 6);
8515  R0(d, e, a, b, c, 7);
8516  R0(c, d, e, a, b, 8);
8517  R0(b, c, d, e, a, 9);
8518  R0(a, b, c, d, e, 10);
8519  R0(e, a, b, c, d, 11);
8520  R0(d, e, a, b, c, 12);
8521  R0(c, d, e, a, b, 13);
8522  R0(b, c, d, e, a, 14);
8523  R0(a, b, c, d, e, 15);
8524  R1(e, a, b, c, d, 16);
8525  R1(d, e, a, b, c, 17);
8526  R1(c, d, e, a, b, 18);
8527  R1(b, c, d, e, a, 19);
8528  R2(a, b, c, d, e, 20);
8529  R2(e, a, b, c, d, 21);
8530  R2(d, e, a, b, c, 22);
8531  R2(c, d, e, a, b, 23);
8532  R2(b, c, d, e, a, 24);
8533  R2(a, b, c, d, e, 25);
8534  R2(e, a, b, c, d, 26);
8535  R2(d, e, a, b, c, 27);
8536  R2(c, d, e, a, b, 28);
8537  R2(b, c, d, e, a, 29);
8538  R2(a, b, c, d, e, 30);
8539  R2(e, a, b, c, d, 31);
8540  R2(d, e, a, b, c, 32);
8541  R2(c, d, e, a, b, 33);
8542  R2(b, c, d, e, a, 34);
8543  R2(a, b, c, d, e, 35);
8544  R2(e, a, b, c, d, 36);
8545  R2(d, e, a, b, c, 37);
8546  R2(c, d, e, a, b, 38);
8547  R2(b, c, d, e, a, 39);
8548  R3(a, b, c, d, e, 40);
8549  R3(e, a, b, c, d, 41);
8550  R3(d, e, a, b, c, 42);
8551  R3(c, d, e, a, b, 43);
8552  R3(b, c, d, e, a, 44);
8553  R3(a, b, c, d, e, 45);
8554  R3(e, a, b, c, d, 46);
8555  R3(d, e, a, b, c, 47);
8556  R3(c, d, e, a, b, 48);
8557  R3(b, c, d, e, a, 49);
8558  R3(a, b, c, d, e, 50);
8559  R3(e, a, b, c, d, 51);
8560  R3(d, e, a, b, c, 52);
8561  R3(c, d, e, a, b, 53);
8562  R3(b, c, d, e, a, 54);
8563  R3(a, b, c, d, e, 55);
8564  R3(e, a, b, c, d, 56);
8565  R3(d, e, a, b, c, 57);
8566  R3(c, d, e, a, b, 58);
8567  R3(b, c, d, e, a, 59);
8568  R4(a, b, c, d, e, 60);
8569  R4(e, a, b, c, d, 61);
8570  R4(d, e, a, b, c, 62);
8571  R4(c, d, e, a, b, 63);
8572  R4(b, c, d, e, a, 64);
8573  R4(a, b, c, d, e, 65);
8574  R4(e, a, b, c, d, 66);
8575  R4(d, e, a, b, c, 67);
8576  R4(c, d, e, a, b, 68);
8577  R4(b, c, d, e, a, 69);
8578  R4(a, b, c, d, e, 70);
8579  R4(e, a, b, c, d, 71);
8580  R4(d, e, a, b, c, 72);
8581  R4(c, d, e, a, b, 73);
8582  R4(b, c, d, e, a, 74);
8583  R4(a, b, c, d, e, 75);
8584  R4(e, a, b, c, d, 76);
8585  R4(d, e, a, b, c, 77);
8586  R4(c, d, e, a, b, 78);
8587  R4(b, c, d, e, a, 79);
8588  state[0] += a;
8589  state[1] += b;
8590  state[2] += c;
8591  state[3] += d;
8592  state[4] += e;
8593  a = b = c = d = e = 0;
8594  memset(block, '\0', sizeof(block));
8595 }
8596 
8597 
8598 static void
8599 SHA1Init(SHA1_CTX *context)
8600 {
8601  context->state[0] = 0x67452301;
8602  context->state[1] = 0xEFCDAB89;
8603  context->state[2] = 0x98BADCFE;
8604  context->state[3] = 0x10325476;
8605  context->state[4] = 0xC3D2E1F0;
8606  context->count[0] = context->count[1] = 0;
8607 }
8608 
8609 
8610 static void
8611 SHA1Update(SHA1_CTX *context, const unsigned char *data, uint32_t len)
8612 {
8613  uint32_t i, j;
8614 
8615  j = context->count[0];
8616  if ((context->count[0] += len << 3) < j) {
8617  context->count[1]++;
8618  }
8619  context->count[1] += (len >> 29);
8620  j = (j >> 3) & 63;
8621  if ((j + len) > 63) {
8622  memcpy(&context->buffer[j], data, (i = 64 - j));
8623  SHA1Transform(context->state, context->buffer);
8624  for (; i + 63 < len; i += 64) {
8625  SHA1Transform(context->state, &data[i]);
8626  }
8627  j = 0;
8628  } else
8629  i = 0;
8630  memcpy(&context->buffer[j], &data[i], len - i);
8631 }
8632 
8633 
8634 static void
8635 SHA1Final(unsigned char digest[20], SHA1_CTX *context)
8636 {
8637  unsigned i;
8638  unsigned char finalcount[8], c;
8639 
8640  for (i = 0; i < 8; i++) {
8641  finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)]
8642  >> ((3 - (i & 3)) * 8)) & 255);
8643  }
8644  c = 0200;
8645  SHA1Update(context, &c, 1);
8646  while ((context->count[0] & 504) != 448) {
8647  c = 0000;
8648  SHA1Update(context, &c, 1);
8649  }
8650  SHA1Update(context, finalcount, 8);
8651  for (i = 0; i < 20; i++) {
8652  digest[i] = (unsigned char)((context->state[i >> 2]
8653  >> ((3 - (i & 3)) * 8)) & 255);
8654  }
8655  memset(context, '\0', sizeof(*context));
8656  memset(&finalcount, '\0', sizeof(finalcount));
8657 }
8658 /* END OF SHA1 CODE */
8659 
8660 
8661 static int
8662 send_websocket_handshake(struct mg_connection *conn, const char *websock_key)
8663 {
8664  static const char *magic = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
8665  const char *protocol = NULL;
8666  char buf[100], sha[20], b64_sha[sizeof(sha) * 2];
8667  SHA1_CTX sha_ctx;
8668  int truncated;
8669 
8670  /* Calculate Sec-WebSocket-Accept reply from Sec-WebSocket-Key. */
8671  mg_snprintf(conn, &truncated, buf, sizeof(buf), "%s%s", websock_key, magic);
8672  if (truncated) {
8673  conn->must_close = 1;
8674  return 0;
8675  }
8676 
8677  SHA1Init(&sha_ctx);
8678  SHA1Update(&sha_ctx, (unsigned char *)buf, (uint32_t)strlen(buf));
8679  SHA1Final((unsigned char *)sha, &sha_ctx);
8680  base64_encode((unsigned char *)sha, sizeof(sha), b64_sha);
8681  mg_printf(conn,
8682  "HTTP/1.1 101 Switching Protocols\r\n"
8683  "Upgrade: websocket\r\n"
8684  "Connection: Upgrade\r\n"
8685  "Sec-WebSocket-Accept: %s\r\n",
8686  b64_sha);
8687  protocol = mg_get_header(conn, "Sec-WebSocket-Protocol");
8688  if (protocol) {
8689  /* The protocol is a comma seperated list of names. */
8690  /* The server must only return one value from this list. */
8691  /* First check if it is a list or just a single value. */
8692  const char *sep = strchr(protocol, ',');
8693  if (sep == NULL) {
8694  /* Just a single protocol -> accept it. */
8695  mg_printf(conn, "Sec-WebSocket-Protocol: %s\r\n\r\n", protocol);
8696  } else {
8697  /* Multiple protocols -> accept the first one. */
8698  /* This is just a quick fix if the client offers multiple
8699  * protocols. In order to get the behavior intended by
8700  * RFC 6455 (https://tools.ietf.org/rfc/rfc6455.txt), it is
8701  * required to have a list of websocket subprotocols accepted
8702  * by the server. Then the server must either select a subprotocol
8703  * supported by client and server, or the server has to abort the
8704  * handshake by not returning a Sec-Websocket-Protocol header if
8705  * no subprotocol is acceptable.
8706  */
8707  mg_printf(conn,
8708  "Sec-WebSocket-Protocol: %.*s\r\n\r\n",
8709  (int)(sep - protocol),
8710  protocol);
8711  }
8712  /* TODO: Real subprotocol negotiation instead of just taking the first
8713  * websocket subprotocol suggested by the client. */
8714  } else {
8715  mg_printf(conn, "%s", "\r\n");
8716  }
8717 
8718  return 1;
8719 }
8720 
8721 
8722 static void
8723 read_websocket(struct mg_connection *conn,
8724  mg_websocket_data_handler ws_data_handler,
8725  void *callback_data)
8726 {
8727  /* Pointer to the beginning of the portion of the incoming websocket
8728  * message queue.
8729  * The original websocket upgrade request is never removed, so the queue
8730  * begins after it. */
8731  unsigned char *buf = (unsigned char *)conn->buf + conn->request_len;
8732  int n, error, exit_by_callback;
8733 
8734  /* body_len is the length of the entire queue in bytes
8735  * len is the length of the current message
8736  * data_len is the length of the current message's data payload
8737  * header_len is the length of the current message's header */
8738  size_t i, len, mask_len = 0, data_len = 0, header_len, body_len;
8739 
8740  /* "The masking key is a 32-bit value chosen at random by the client."
8741  * http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-17#section-5
8742  */
8743  unsigned char mask[4];
8744 
8745  /* data points to the place where the message is stored when passed to
8746  * the
8747  * websocket_data callback. This is either mem on the stack, or a
8748  * dynamically allocated buffer if it is too large. */
8749  char mem[4096];
8750  char *data = mem;
8751  unsigned char mop; /* mask flag and opcode */
8752  double timeout = -1.0;
8753 
8754  if (conn->ctx->config[WEBSOCKET_TIMEOUT]) {
8755  timeout = atoi(conn->ctx->config[WEBSOCKET_TIMEOUT]) / 1000.0;
8756  }
8757  if ((timeout <= 0.0) && (conn->ctx->config[REQUEST_TIMEOUT])) {
8758  timeout = atoi(conn->ctx->config[REQUEST_TIMEOUT]) / 1000.0;
8759  }
8760 
8761  mg_set_thread_name("wsock");
8762 
8763  /* Loop continuously, reading messages from the socket, invoking the
8764  * callback, and waiting repeatedly until an error occurs. */
8765  while (!conn->ctx->stop_flag) {
8766  header_len = 0;
8767  assert(conn->data_len >= conn->request_len);
8768  if ((body_len = (size_t)(conn->data_len - conn->request_len)) >= 2) {
8769  len = buf[1] & 127;
8770  mask_len = buf[1] & 128 ? 4 : 0;
8771  if (len < 126 && body_len >= mask_len) {
8772  data_len = len;
8773  header_len = 2 + mask_len;
8774  } else if (len == 126 && body_len >= 4 + mask_len) {
8775  header_len = 4 + mask_len;
8776  data_len = ((((size_t)buf[2]) << 8) + buf[3]);
8777  } else if (body_len >= 10 + mask_len) {
8778  header_len = 10 + mask_len;
8779  data_len = (((uint64_t)ntohl(*(uint32_t *)(void *)&buf[2]))
8780  << 32) + ntohl(*(uint32_t *)(void *)&buf[6]);
8781  }
8782  }
8783 
8784  if (header_len > 0 && body_len >= header_len) {
8785  /* Allocate space to hold websocket payload */
8786  data = mem;
8787  if (data_len > sizeof(mem)) {
8788  data = (char *)mg_malloc(data_len);
8789  if (data == NULL) {
8790  /* Allocation failed, exit the loop and then close the
8791  * connection */
8792  mg_cry(conn, "websocket out of memory; closing connection");
8793  break;
8794  }
8795  }
8796 
8797  /* Copy the mask before we shift the queue and destroy it */
8798  if (mask_len > 0) {
8799  memcpy(mask, buf + header_len - mask_len, sizeof(mask));
8800  } else {
8801  memset(mask, 0, sizeof(mask));
8802  }
8803 
8804  /* Read frame payload from the first message in the queue into
8805  * data and advance the queue by moving the memory in place. */
8806  assert(body_len >= header_len);
8807  if (data_len + header_len > body_len) {
8808  mop = buf[0]; /* current mask and opcode */
8809  /* Overflow case */
8810  len = body_len - header_len;
8811  memcpy(data, buf + header_len, len);
8812  error = 0;
8813  while (len < data_len) {
8814  n = pull(
8815  NULL, conn, data + len, (int)(data_len - len), timeout);
8816  if (n <= 0) {
8817  error = 1;
8818  break;
8819  }
8820  len += (size_t)n;
8821  }
8822  if (error) {
8823  mg_cry(conn, "Websocket pull failed; closing connection");
8824  break;
8825  }
8826  conn->data_len = conn->request_len;
8827  } else {
8828  mop = buf[0]; /* current mask and opcode, overwritten by
8829  * memmove() */
8830  /* Length of the message being read at the front of the
8831  * queue */
8832  len = data_len + header_len;
8833 
8834  /* Copy the data payload into the data pointer for the
8835  * callback */
8836  memcpy(data, buf + header_len, data_len);
8837 
8838  /* Move the queue forward len bytes */
8839  memmove(buf, buf + len, body_len - len);
8840 
8841  /* Mark the queue as advanced */
8842  conn->data_len -= (int)len;
8843  }
8844 
8845  /* Apply mask if necessary */
8846  if (mask_len > 0) {
8847  for (i = 0; i < data_len; ++i) {
8848  data[i] ^= mask[i & 3];
8849  }
8850  }
8851 
8852  /* Exit the loop if callback signals to exit (server side),
8853  * or "connection close" opcode received (client side). */
8854  exit_by_callback = 0;
8855  if ((ws_data_handler != NULL)
8856  && !ws_data_handler(conn, mop, data, data_len, callback_data)) {
8857  exit_by_callback = 1;
8858  }
8859 
8860  if (data != mem) {
8861  mg_free(data);
8862  }
8863 
8864  if (exit_by_callback
8865  || ((mop & 0xf) == WEBSOCKET_OPCODE_CONNECTION_CLOSE)) {
8866  /* Opcode == 8, connection close */
8867  break;
8868  }
8869 
8870  /* Not breaking the loop, process next websocket frame. */
8871  } else {
8872  /* Read from the socket into the next available location in the
8873  * message queue. */
8874  if ((n = pull(NULL,
8875  conn,
8876  conn->buf + conn->data_len,
8877  conn->buf_size - conn->data_len,
8878  timeout)) <= 0) {
8879  /* Error, no bytes read */
8880  break;
8881  }
8882  conn->data_len += n;
8883  }
8884  }
8885 
8886  mg_set_thread_name("worker");
8887 }
8888 
8889 
8890 static int
8891 mg_websocket_write_exec(struct mg_connection *conn,
8892  int opcode,
8893  const char *data,
8894  size_t dataLen,
8895  uint32_t masking_key)
8896 {
8897  unsigned char header[14];
8898  size_t headerLen = 1;
8899 
8900  int retval = -1;
8901 
8902  header[0] = 0x80 + (opcode & 0xF);
8903 
8904  /* Frame format: http://tools.ietf.org/html/rfc6455#section-5.2 */
8905  if (dataLen < 126) {
8906  /* inline 7-bit length field */
8907  header[1] = (unsigned char)dataLen;
8908  headerLen = 2;
8909  } else if (dataLen <= 0xFFFF) {
8910  /* 16-bit length field */
8911  header[1] = 126;
8912  *(uint16_t *)(void *)(header + 2) = htons((uint16_t)dataLen);
8913  headerLen = 4;
8914  } else {
8915  /* 64-bit length field */
8916  header[1] = 127;
8917  *(uint32_t *)(void *)(header + 2) = htonl((uint64_t)dataLen >> 32);
8918  *(uint32_t *)(void *)(header + 6) = htonl(dataLen & 0xFFFFFFFF);
8919  headerLen = 10;
8920  }
8921 
8922  if (masking_key) {
8923  /* add mask */
8924  header[1] |= 0x80;
8925  *(uint32_t *)(void *)(header + headerLen) = masking_key;
8926  headerLen += 4;
8927  }
8928 
8929 
8930  /* Note that POSIX/Winsock's send() is threadsafe
8931  * http://stackoverflow.com/questions/1981372/are-parallel-calls-to-send-recv-on-the-same-socket-valid
8932  * but mongoose's mg_printf/mg_write is not (because of the loop in
8933  * push(), although that is only a problem if the packet is large or
8934  * outgoing buffer is full). */
8935  (void)mg_lock_connection(conn);
8936  retval = mg_write(conn, header, headerLen);
8937  if (dataLen > 0) {
8938  retval = mg_write(conn, data, dataLen);
8939  }
8940  mg_unlock_connection(conn);
8941 
8942  return retval;
8943 }
8944 
8945 int
8946 mg_websocket_write(struct mg_connection *conn,
8947  int opcode,
8948  const char *data,
8949  size_t dataLen)
8950 {
8951  return mg_websocket_write_exec(conn, opcode, data, dataLen, 0);
8952 }
8953 
8954 
8955 static void
8956 mask_data(const char *in, size_t in_len, uint32_t masking_key, char *out)
8957 {
8958  size_t i = 0;
8959 
8960  i = 0;
8961  if ((in_len > 3) && ((ptrdiff_t)in % 4) == 0) {
8962  /* Convert in 32 bit words, if data is 4 byte aligned */
8963  while (i < (in_len - 3)) {
8964  *(uint32_t *)(void *)(out + i) =
8965  *(uint32_t *)(void *)(in + i) ^ masking_key;
8966  i += 4;
8967  }
8968  }
8969  if (i != in_len) {
8970  /* convert 1-3 remaining bytes if ((dataLen % 4) != 0)*/
8971  while (i < in_len) {
8972  *(uint8_t *)(void *)(out + i) =
8973  *(uint8_t *)(void *)(in + i)
8974  ^ *(((uint8_t *)&masking_key) + (i % 4));
8975  i++;
8976  }
8977  }
8978 }
8979 
8980 
8981 int
8982 mg_websocket_client_write(struct mg_connection *conn,
8983  int opcode,
8984  const char *data,
8985  size_t dataLen)
8986 {
8987  int retval = -1;
8988  char *masked_data = (char *)mg_malloc(((dataLen + 7) / 4) * 4);
8989  uint32_t masking_key = (uint32_t)get_random();
8990 
8991  if (masked_data == NULL) {
8992  /* Return -1 in an error case */
8993  mg_cry(conn,
8994  "Cannot allocate buffer for masked websocket response: "
8995  "Out of memory");
8996  return -1;
8997  }
8998 
8999  mask_data(data, dataLen, masking_key, masked_data);
9000 
9001  retval = mg_websocket_write_exec(
9002  conn, opcode, masked_data, dataLen, masking_key);
9003  mg_free(masked_data);
9004 
9005  return retval;
9006 }
9007 
9008 
9009 static void
9010 handle_websocket_request(struct mg_connection *conn,
9011  const char *path,
9012  int is_callback_resource,
9013  mg_websocket_connect_handler ws_connect_handler,
9014  mg_websocket_ready_handler ws_ready_handler,
9015  mg_websocket_data_handler ws_data_handler,
9016  mg_websocket_close_handler ws_close_handler,
9017  void *cbData)
9018 {
9019  const char *websock_key = mg_get_header(conn, "Sec-WebSocket-Key");
9020  const char *version = mg_get_header(conn, "Sec-WebSocket-Version");
9021  int lua_websock = 0;
9022 
9023 #if !defined(USE_LUA)
9024  (void)path;
9025 #endif
9026 
9027  /* Step 1: Check websocket protocol version. */
9028  /* Step 1.1: Check Sec-WebSocket-Key. */
9029  if (!websock_key) {
9030  /* The RFC standard version (https://tools.ietf.org/html/rfc6455)
9031  * requires a Sec-WebSocket-Key header.
9032  */
9033  /* It could be the hixie draft version
9034  * (http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol-76).
9035  */
9036  const char *key1 = mg_get_header(conn, "Sec-WebSocket-Key1");
9037  const char *key2 = mg_get_header(conn, "Sec-WebSocket-Key2");
9038  char key3[8];
9039 
9040  if ((key1 != NULL) && (key2 != NULL)) {
9041  /* This version uses 8 byte body data in a GET request */
9042  conn->content_len = 8;
9043  if (8 == mg_read(conn, key3, 8)) {
9044  /* This is the hixie version */
9045  send_http_error(conn,
9046  426,
9047  "%s",
9048  "Protocol upgrade to RFC 6455 required");
9049  return;
9050  }
9051  }
9052  /* This is an unknown version */
9053  send_http_error(conn, 400, "%s", "Malformed websocket request");
9054  return;
9055  }
9056 
9057  /* Step 1.2: Check websocket protocol version. */
9058  /* The RFC version (https://tools.ietf.org/html/rfc6455) is 13. */
9059  if (version == NULL || strcmp(version, "13") != 0) {
9060  /* Reject wrong versions */
9061  send_http_error(conn, 426, "%s", "Protocol upgrade required");
9062  return;
9063  }
9064 
9065  /* Step 1.3: Could check for "Host", but we do not really nead this
9066  * value for anything, so just ignore it. */
9067 
9068  /* Step 2: If a callback is responsible, call it. */
9069  if (is_callback_resource) {
9070  if (ws_connect_handler != NULL
9071  && ws_connect_handler(conn, cbData) != 0) {
9072  /* C callback has returned non-zero, do not proceed with
9073  * handshake.
9074  */
9075  /* Note that C callbacks are no longer called when Lua is
9076  * responsible, so C can no longer filter callbacks for Lua. */
9077  return;
9078  }
9079  }
9080 #if defined(USE_LUA)
9081  /* Step 3: No callback. Check if Lua is responsible. */
9082  else {
9083  /* Step 3.1: Check if Lua is responsible. */
9084  if (conn->ctx->config[LUA_WEBSOCKET_EXTENSIONS]) {
9085  lua_websock =
9086  match_prefix(conn->ctx->config[LUA_WEBSOCKET_EXTENSIONS],
9087  strlen(
9088  conn->ctx->config[LUA_WEBSOCKET_EXTENSIONS]),
9089  path);
9090  }
9091 
9092  if (lua_websock) {
9093  /* Step 3.2: Lua is responsible: call it. */
9094  conn->lua_websocket_state = lua_websocket_new(path, conn);
9095  if (!conn->lua_websocket_state) {
9096  /* Lua rejected the new client */
9097  return;
9098  }
9099  }
9100  }
9101 #endif
9102 
9103  /* Step 4: Check if there is a responsible websocket handler. */
9104  if (!is_callback_resource && !lua_websock) {
9105  /* There is no callback, an Lua is not responsible either. */
9106  /* Reply with a 404 Not Found or with nothing at all?
9107  * TODO (mid): check the websocket standards, how to reply to
9108  * requests to invalid websocket addresses. */
9109  send_http_error(conn, 404, "%s", "Not found");
9110  return;
9111  }
9112 
9113  /* Step 5: The websocket connection has been accepted */
9114  if (!send_websocket_handshake(conn, websock_key)) {
9115  send_http_error(conn, 500, "%s", "Websocket handshake failed");
9116  return;
9117  }
9118 
9119  /* Step 6: Call the ready handler */
9120  if (is_callback_resource) {
9121  if (ws_ready_handler != NULL) {
9122  ws_ready_handler(conn, cbData);
9123  }
9124 #if defined(USE_LUA)
9125  } else if (lua_websock) {
9126  if (!lua_websocket_ready(conn, conn->lua_websocket_state)) {
9127  /* the ready handler returned false */
9128  return;
9129  }
9130 #endif
9131  }
9132 
9133  /* Step 7: Enter the read loop */
9134  if (is_callback_resource) {
9135  read_websocket(conn, ws_data_handler, cbData);
9136 #if defined(USE_LUA)
9137  } else if (lua_websock) {
9138  read_websocket(conn, lua_websocket_data, conn->lua_websocket_state);
9139 #endif
9140  }
9141 
9142  /* Step 8: Call the close handler */
9143  if (ws_close_handler) {
9144  ws_close_handler(conn, cbData);
9145  }
9146 }
9147 
9148 
9149 static int
9150 is_websocket_protocol(const struct mg_connection *conn)
9151 {
9152  const char *upgrade, *connection;
9153 
9154  /* A websocket protocoll has the following HTTP headers:
9155  *
9156  * Connection: Upgrade
9157  * Upgrade: Websocket
9158  */
9159 
9160  upgrade = mg_get_header(conn, "Upgrade");
9161  if (upgrade == NULL) {
9162  return 0; /* fail early, don't waste time checking other header
9163  * fields
9164  */
9165  }
9166  if (!mg_strcasestr(upgrade, "websocket")) {
9167  return 0;
9168  }
9169 
9170  connection = mg_get_header(conn, "Connection");
9171  if (connection == NULL) {
9172  return 0;
9173  }
9174  if (!mg_strcasestr(connection, "upgrade")) {
9175  return 0;
9176  }
9177 
9178  /* The headers "Host", "Sec-WebSocket-Key", "Sec-WebSocket-Protocol" and
9179  * "Sec-WebSocket-Version" are also required.
9180  * Don't check them here, since even an unsupported websocket protocol
9181  * request still IS a websocket request (in contrast to a standard HTTP
9182  * request). It will fail later in handle_websocket_request.
9183  */
9184 
9185  return 1;
9186 }
9187 #endif /* !USE_WEBSOCKET */
9188 
9189 
9190 static int
9191 isbyte(int n)
9192 {
9193  return n >= 0 && n <= 255;
9194 }
9195 
9196 
9197 static int
9198 parse_net(const char *spec, uint32_t *net, uint32_t *mask)
9199 {
9200  int n, a, b, c, d, slash = 32, len = 0;
9201 
9202  if ((sscanf(spec, "%d.%d.%d.%d/%d%n", &a, &b, &c, &d, &slash, &n) == 5
9203  || sscanf(spec, "%d.%d.%d.%d%n", &a, &b, &c, &d, &n) == 4) && isbyte(a)
9204  && isbyte(b) && isbyte(c) && isbyte(d) && slash >= 0
9205  && slash < 33) {
9206  len = n;
9207  *net = ((uint32_t)a << 24) | ((uint32_t)b << 16) | ((uint32_t)c << 8)
9208  | (uint32_t)d;
9209  *mask = slash ? 0xffffffffU << (32 - slash) : 0;
9210  }
9211 
9212  return len;
9213 }
9214 
9215 
9216 static int
9217 set_throttle(const char *spec, uint32_t remote_ip, const char *uri)
9218 {
9219  int throttle = 0;
9220  struct vec vec, val;
9221  uint32_t net, mask;
9222  char mult;
9223  double v;
9224 
9225  while ((spec = next_option(spec, &vec, &val)) != NULL) {
9226  mult = ',';
9227  if (sscanf(val.ptr, "%lf%c", &v, &mult) < 1 || v < 0
9228  || (lowercase(&mult) != 'k' && lowercase(&mult) != 'm'
9229  && mult != ',')) {
9230  continue;
9231  }
9232  v *= lowercase(&mult) == 'k' ? 1024 : lowercase(&mult) == 'm' ? 1048576
9233  : 1;
9234  if (vec.len == 1 && vec.ptr[0] == '*') {
9235  throttle = (int)v;
9236  } else if (parse_net(vec.ptr, &net, &mask) > 0) {
9237  if ((remote_ip & mask) == net) {
9238  throttle = (int)v;
9239  }
9240  } else if (match_prefix(vec.ptr, vec.len, uri) > 0) {
9241  throttle = (int)v;
9242  }
9243  }
9244 
9245  return throttle;
9246 }
9247 
9248 
9249 static uint32_t
9250 get_remote_ip(const struct mg_connection *conn)
9251 {
9252  if (!conn) {
9253  return 0;
9254  }
9255  return ntohl(*(const uint32_t *)&conn->client.rsa.sin.sin_addr);
9256 }
9257 
9258 
9259 /* The mg_upload function is superseeded by mg_handle_form_request. */
9260 #include "handle_form.inl"
9261 
9262 
9263 #if defined(MG_LEGACY_INTERFACE)
9264 /* Implement the deprecated mg_upload function by calling the new
9265  * mg_handle_form_request function. While mg_upload could only handle
9266  * HTML forms sent as POST request in multipart/form-data format
9267  * containing only file input elements, mg_handle_form_request can
9268  * handle all form input elements and all standard request methods. */
9269 struct mg_upload_user_data {
9270  struct mg_connection *conn;
9271  const char *destination_dir;
9272  int num_uploaded_files;
9273 };
9274 
9275 
9276 /* Helper function for deprecated mg_upload. */
9277 static int
9278 mg_upload_field_found(const char *key,
9279  const char *filename,
9280  char *path,
9281  size_t pathlen,
9282  void *user_data)
9283 {
9284  int truncated = 0;
9285  struct mg_upload_user_data *fud = (struct mg_upload_user_data *)user_data;
9286  (void)key;
9287 
9288  if (!filename) {
9289  mg_cry(fud->conn, "%s: No filename set", __func__);
9290  return FORM_FIELD_STORAGE_ABORT;
9291  }
9292  mg_snprintf(fud->conn,
9293  &truncated,
9294  path,
9295  pathlen - 1,
9296  "%s/%s",
9297  fud->destination_dir,
9298  filename);
9299  if (!truncated) {
9300  mg_cry(fud->conn, "%s: File path too long", __func__);
9301  return FORM_FIELD_STORAGE_ABORT;
9302  }
9303  return FORM_FIELD_STORAGE_STORE;
9304 }
9305 
9306 
9307 /* Helper function for deprecated mg_upload. */
9308 static int
9309 mg_upload_field_get(const char *key,
9310  const char *value,
9311  size_t value_size,
9312  void *user_data)
9313 {
9314  /* Function should never be called */
9315  (void)key;
9316  (void)value;
9317  (void)value_size;
9318  (void)user_data;
9319 
9320  return 0;
9321 }
9322 
9323 
9324 /* Helper function for deprecated mg_upload. */
9325 static int
9326 mg_upload_field_stored(const char *path, long long file_size, void *user_data)
9327 {
9328  struct mg_upload_user_data *fud = (struct mg_upload_user_data *)user_data;
9329  (void)file_size;
9330 
9331  fud->num_uploaded_files++;
9332  fud->conn->ctx->callbacks.upload(fud->conn, path);
9333 
9334  return 0;
9335 }
9336 
9337 
9338 /* Deprecated function mg_upload - use mg_handle_form_request instead. */
9339 int
9340 mg_upload(struct mg_connection *conn, const char *destination_dir)
9341 {
9342  struct mg_upload_user_data fud = {conn, destination_dir, 0};
9343  struct mg_form_data_handler fdh = {mg_upload_field_found,
9344  mg_upload_field_get,
9345  mg_upload_field_stored,
9346  0};
9347  int ret;
9348 
9349  fdh.user_data = (void *)&fud;
9350  ret = mg_handle_form_request(conn, &fdh);
9351 
9352  if (ret < 0) {
9353  mg_cry(conn, "%s: Error while parsing the request", __func__);
9354  }
9355 
9356  return fud.num_uploaded_files;
9357 }
9358 #endif
9359 
9360 
9361 static int
9362 get_first_ssl_listener_index(const struct mg_context *ctx)
9363 {
9364  unsigned int i;
9365  int idx = -1;
9366  if (ctx) {
9367  for (i = 0; idx == -1 && i < ctx->num_listening_sockets; i++) {
9368  idx = ctx->listening_sockets[i].is_ssl ? ((int)(i)) : -1;
9369  }
9370  }
9371  return idx;
9372 }
9373 
9374 
9375 static void
9376 redirect_to_https_port(struct mg_connection *conn, int ssl_index)
9377 {
9378  char host[1025];
9379  const char *host_header;
9380  size_t hostlen;
9381 
9382  host_header = mg_get_header(conn, "Host");
9383  hostlen = sizeof(host);
9384  if (host_header != NULL) {
9385  char *pos;
9386 
9387  mg_strlcpy(host, host_header, hostlen);
9388  host[hostlen - 1] = '\0';
9389  pos = strchr(host, ':');
9390  if (pos != NULL) {
9391  *pos = '\0';
9392  }
9393  } else {
9394  /* Cannot get host from the Host: header.
9395  * Fallback to our IP address. */
9396  if (conn) {
9397  sockaddr_to_string(host, hostlen, &conn->client.lsa);
9398  }
9399  }
9400 
9401  /* Send host, port, uri and (if it exists) ?query_string */
9402  if (conn) {
9403  mg_printf(conn,
9404  "HTTP/1.1 302 Found\r\nLocation: https://%s:%d%s%s%s\r\n\r\n",
9405  host,
9406  (int)ntohs(
9407  conn->ctx->listening_sockets[ssl_index].lsa.sin.sin_port),
9408  conn->request_info.local_uri,
9409  (conn->request_info.query_string == NULL) ? "" : "?",
9410  (conn->request_info.query_string == NULL)
9411  ? ""
9412  : conn->request_info.query_string);
9413  }
9414 }
9415 
9416 
9417 static void
9418 mg_set_handler_type(struct mg_context *ctx,
9419  const char *uri,
9420  int handler_type,
9421  int is_delete_request,
9422  mg_request_handler handler,
9423  mg_websocket_connect_handler connect_handler,
9424  mg_websocket_ready_handler ready_handler,
9425  mg_websocket_data_handler data_handler,
9426  mg_websocket_close_handler close_handler,
9427  mg_authorization_handler auth_handler,
9428  void *cbdata)
9429 {
9430  struct mg_handler_info *tmp_rh, **lastref;
9431  size_t urilen = strlen(uri);
9432 
9433  if (handler_type == WEBSOCKET_HANDLER) {
9434  /* assert(handler == NULL); */
9435  /* assert(is_delete_request || connect_handler!=NULL ||
9436  * ready_handler!=NULL || data_handler!=NULL ||
9437  * close_handler!=NULL);
9438  */
9439  /* assert(auth_handler == NULL); */
9440  if (handler != NULL) {
9441  return;
9442  }
9443  if (!is_delete_request && connect_handler == NULL
9444  && ready_handler == NULL
9445  && data_handler == NULL
9446  && close_handler == NULL) {
9447  return;
9448  }
9449  if (auth_handler != NULL) {
9450  return;
9451  }
9452  } else if (handler_type == REQUEST_HANDLER) {
9453  /* assert(connect_handler==NULL && ready_handler==NULL &&
9454  * data_handler==NULL && close_handler==NULL); */
9455  /* assert(is_delete_request || (handler!=NULL));
9456  */
9457  /* assert(auth_handler == NULL); */
9458  if (connect_handler != NULL || ready_handler != NULL
9459  || data_handler != NULL
9460  || close_handler != NULL) {
9461  return;
9462  }
9463  if (!is_delete_request && (handler == NULL)) {
9464  return;
9465  }
9466  if (auth_handler != NULL) {
9467  return;
9468  }
9469  } else { /* AUTH_HANDLER */
9470  /* assert(handler == NULL); */
9471  /* assert(connect_handler==NULL && ready_handler==NULL &&
9472  * data_handler==NULL && close_handler==NULL); */
9473  /* assert(auth_handler != NULL); */
9474  if (handler != NULL) {
9475  return;
9476  }
9477  if (connect_handler != NULL || ready_handler != NULL
9478  || data_handler != NULL
9479  || close_handler != NULL) {
9480  return;
9481  }
9482  if (!is_delete_request && (auth_handler == NULL)) {
9483  return;
9484  }
9485  }
9486 
9487  if (!ctx) {
9488  return;
9489  }
9490 
9491  mg_lock_context(ctx);
9492 
9493  /* first try to find an existing handler */
9494  lastref = &(ctx->handlers);
9495  for (tmp_rh = ctx->handlers; tmp_rh != NULL; tmp_rh = tmp_rh->next) {
9496  if (tmp_rh->handler_type == handler_type) {
9497  if (urilen == tmp_rh->uri_len && !strcmp(tmp_rh->uri, uri)) {
9498  if (!is_delete_request) {
9499  /* update existing handler */
9500  if (handler_type == REQUEST_HANDLER) {
9501  tmp_rh->handler = handler;
9502  } else if (handler_type == WEBSOCKET_HANDLER) {
9503  tmp_rh->connect_handler = connect_handler;
9504  tmp_rh->ready_handler = ready_handler;
9505  tmp_rh->data_handler = data_handler;
9506  tmp_rh->close_handler = close_handler;
9507  } else { /* AUTH_HANDLER */
9508  tmp_rh->auth_handler = auth_handler;
9509  }
9510  tmp_rh->cbdata = cbdata;
9511  } else {
9512  /* remove existing handler */
9513  *lastref = tmp_rh->next;
9514  mg_free(tmp_rh->uri);
9515  mg_free(tmp_rh);
9516  }
9517  mg_unlock_context(ctx);
9518  return;
9519  }
9520  }
9521  lastref = &(tmp_rh->next);
9522  }
9523 
9524  if (is_delete_request) {
9525  /* no handler to set, this was a remove request to a non-existing
9526  * handler */
9527  mg_unlock_context(ctx);
9528  return;
9529  }
9530 
9531  tmp_rh =
9532  (struct mg_handler_info *)mg_calloc(sizeof(struct mg_handler_info), 1);
9533  if (tmp_rh == NULL) {
9534  mg_unlock_context(ctx);
9535  mg_cry(fc(ctx), "%s", "Cannot create new request handler struct, OOM");
9536  return;
9537  }
9538  tmp_rh->uri = mg_strdup(uri);
9539  if (!tmp_rh->uri) {
9540  mg_unlock_context(ctx);
9541  mg_free(tmp_rh);
9542  mg_cry(fc(ctx), "%s", "Cannot create new request handler struct, OOM");
9543  return;
9544  }
9545  tmp_rh->uri_len = urilen;
9546  if (handler_type == REQUEST_HANDLER) {
9547  tmp_rh->handler = handler;
9548  } else if (handler_type == WEBSOCKET_HANDLER) {
9549  tmp_rh->connect_handler = connect_handler;
9550  tmp_rh->ready_handler = ready_handler;
9551  tmp_rh->data_handler = data_handler;
9552  tmp_rh->close_handler = close_handler;
9553  } else { /* AUTH_HANDLER */
9554  tmp_rh->auth_handler = auth_handler;
9555  }
9556  tmp_rh->cbdata = cbdata;
9557  tmp_rh->handler_type = handler_type;
9558  tmp_rh->next = NULL;
9559 
9560  *lastref = tmp_rh;
9561  mg_unlock_context(ctx);
9562 }
9563 
9564 
9565 void
9566 mg_set_request_handler(struct mg_context *ctx,
9567  const char *uri,
9568  mg_request_handler handler,
9569  void *cbdata)
9570 {
9571  mg_set_handler_type(ctx,
9572  uri,
9574  handler == NULL,
9575  handler,
9576  NULL,
9577  NULL,
9578  NULL,
9579  NULL,
9580  NULL,
9581  cbdata);
9582 }
9583 
9584 
9585 void
9586 mg_set_websocket_handler(struct mg_context *ctx,
9587  const char *uri,
9588  mg_websocket_connect_handler connect_handler,
9589  mg_websocket_ready_handler ready_handler,
9590  mg_websocket_data_handler data_handler,
9591  mg_websocket_close_handler close_handler,
9592  void *cbdata)
9593 {
9594  int is_delete_request = (connect_handler == NULL) && (ready_handler == NULL)
9595  && (data_handler == NULL)
9596  && (close_handler == NULL);
9597  mg_set_handler_type(ctx,
9598  uri,
9600  is_delete_request,
9601  NULL,
9602  connect_handler,
9603  ready_handler,
9604  data_handler,
9605  close_handler,
9606  NULL,
9607  cbdata);
9608 }
9609 
9610 
9611 void
9612 mg_set_auth_handler(struct mg_context *ctx,
9613  const char *uri,
9614  mg_request_handler handler,
9615  void *cbdata)
9616 {
9617  mg_set_handler_type(ctx,
9618  uri,
9619  AUTH_HANDLER,
9620  handler == NULL,
9621  NULL,
9622  NULL,
9623  NULL,
9624  NULL,
9625  NULL,
9626  handler,
9627  cbdata);
9628 }
9629 
9630 
9631 static int
9632 get_request_handler(struct mg_connection *conn,
9633  int handler_type,
9634  mg_request_handler *handler,
9635  mg_websocket_connect_handler *connect_handler,
9636  mg_websocket_ready_handler *ready_handler,
9637  mg_websocket_data_handler *data_handler,
9638  mg_websocket_close_handler *close_handler,
9639  mg_authorization_handler *auth_handler,
9640  void **cbdata)
9641 {
9642  const struct mg_request_info *request_info = mg_get_request_info(conn);
9643  if (request_info) {
9644  const char *uri = request_info->local_uri;
9645  size_t urilen = strlen(uri);
9646  struct mg_handler_info *tmp_rh;
9647 
9648  if (!conn || !conn->ctx) {
9649  return 0;
9650  }
9651 
9652  mg_lock_context(conn->ctx);
9653 
9654  /* first try for an exact match */
9655  for (tmp_rh = conn->ctx->handlers; tmp_rh != NULL;
9656  tmp_rh = tmp_rh->next) {
9657  if (tmp_rh->handler_type == handler_type) {
9658  if (urilen == tmp_rh->uri_len && !strcmp(tmp_rh->uri, uri)) {
9659  if (handler_type == WEBSOCKET_HANDLER) {
9660  *connect_handler = tmp_rh->connect_handler;
9661  *ready_handler = tmp_rh->ready_handler;
9662  *data_handler = tmp_rh->data_handler;
9663  *close_handler = tmp_rh->close_handler;
9664  } else if (handler_type == REQUEST_HANDLER) {
9665  *handler = tmp_rh->handler;
9666  } else { /* AUTH_HANDLER */
9667  *auth_handler = tmp_rh->auth_handler;
9668  }
9669  *cbdata = tmp_rh->cbdata;
9670  mg_unlock_context(conn->ctx);
9671  return 1;
9672  }
9673  }
9674  }
9675 
9676  /* next try for a partial match, we will accept uri/something */
9677  for (tmp_rh = conn->ctx->handlers; tmp_rh != NULL;
9678  tmp_rh = tmp_rh->next) {
9679  if (tmp_rh->handler_type == handler_type) {
9680  if (tmp_rh->uri_len < urilen && uri[tmp_rh->uri_len] == '/'
9681  && memcmp(tmp_rh->uri, uri, tmp_rh->uri_len) == 0) {
9682  if (handler_type == WEBSOCKET_HANDLER) {
9683  *connect_handler = tmp_rh->connect_handler;
9684  *ready_handler = tmp_rh->ready_handler;
9685  *data_handler = tmp_rh->data_handler;
9686  *close_handler = tmp_rh->close_handler;
9687  } else if (handler_type == REQUEST_HANDLER) {
9688  *handler = tmp_rh->handler;
9689  } else { /* AUTH_HANDLER */
9690  *auth_handler = tmp_rh->auth_handler;
9691  }
9692  *cbdata = tmp_rh->cbdata;
9693  mg_unlock_context(conn->ctx);
9694  return 1;
9695  }
9696  }
9697  }
9698 
9699  /* finally try for pattern match */
9700  for (tmp_rh = conn->ctx->handlers; tmp_rh != NULL;
9701  tmp_rh = tmp_rh->next) {
9702  if (tmp_rh->handler_type == handler_type) {
9703  if (match_prefix(tmp_rh->uri, tmp_rh->uri_len, uri) > 0) {
9704  if (handler_type == WEBSOCKET_HANDLER) {
9705  *connect_handler = tmp_rh->connect_handler;
9706  *ready_handler = tmp_rh->ready_handler;
9707  *data_handler = tmp_rh->data_handler;
9708  *close_handler = tmp_rh->close_handler;
9709  } else if (handler_type == REQUEST_HANDLER) {
9710  *handler = tmp_rh->handler;
9711  } else { /* AUTH_HANDLER */
9712  *auth_handler = tmp_rh->auth_handler;
9713  }
9714  *cbdata = tmp_rh->cbdata;
9715  mg_unlock_context(conn->ctx);
9716  return 1;
9717  }
9718  }
9719  }
9720 
9721  mg_unlock_context(conn->ctx);
9722  }
9723  return 0; /* none found */
9724 }
9725 
9726 
9727 #if defined(USE_WEBSOCKET) && defined(MG_LEGACY_INTERFACE)
9728 static int
9729 deprecated_websocket_connect_wrapper(const struct mg_connection *conn,
9730  void *cbdata)
9731 {
9732  struct mg_callbacks *pcallbacks = (struct mg_callbacks *)cbdata;
9733  if (pcallbacks->websocket_connect) {
9734  return pcallbacks->websocket_connect(conn);
9735  }
9736  /* No handler set - assume "OK" */
9737  return 0;
9738 }
9739 
9740 
9741 static void
9742 deprecated_websocket_ready_wrapper(struct mg_connection *conn, void *cbdata)
9743 {
9744  struct mg_callbacks *pcallbacks = (struct mg_callbacks *)cbdata;
9745  if (pcallbacks->websocket_ready) {
9746  pcallbacks->websocket_ready(conn);
9747  }
9748 }
9749 
9750 
9751 static int
9752 deprecated_websocket_data_wrapper(struct mg_connection *conn,
9753  int bits,
9754  char *data,
9755  size_t len,
9756  void *cbdata)
9757 {
9758  struct mg_callbacks *pcallbacks = (struct mg_callbacks *)cbdata;
9759  if (pcallbacks->websocket_data) {
9760  return pcallbacks->websocket_data(conn, bits, data, len);
9761  }
9762  /* No handler set - assume "OK" */
9763  return 1;
9764 }
9765 #endif
9766 
9767 
9768 /* This is the heart of the Civetweb's logic.
9769  * This function is called when the request is read, parsed and validated,
9770  * and Civetweb must decide what action to take: serve a file, or
9771  * a directory, or call embedded function, etcetera. */
9772 static void
9773 handle_request(struct mg_connection *conn)
9774 {
9775  if (conn) {
9776  struct mg_request_info *ri = &conn->request_info;
9777  char path[PATH_MAX];
9778  int uri_len, ssl_index;
9779  int is_found = 0, is_script_resource = 0, is_websocket_request = 0,
9780  is_put_or_delete_request = 0, is_callback_resource = 0;
9781  int i;
9782  struct file file = STRUCT_FILE_INITIALIZER;
9783  mg_request_handler callback_handler = NULL;
9784  mg_websocket_connect_handler ws_connect_handler = NULL;
9785  mg_websocket_ready_handler ws_ready_handler = NULL;
9786  mg_websocket_data_handler ws_data_handler = NULL;
9787  mg_websocket_close_handler ws_close_handler = NULL;
9788  void *callback_data = NULL;
9789  mg_authorization_handler auth_handler = NULL;
9790  void *auth_callback_data = NULL;
9791 #if !defined(NO_FILES)
9792  time_t curtime = time(NULL);
9793  char date[64];
9794 #endif
9795 
9796  path[0] = 0;
9797 
9798  if (!ri) {
9799  return;
9800  }
9801 
9802  /* 1. get the request url */
9803  /* 1.1. split into url and query string */
9804  if ((conn->request_info.query_string = strchr(ri->request_uri, '?'))
9805  != NULL) {
9806  *((char *)conn->request_info.query_string++) = '\0';
9807  }
9808  uri_len = (int)strlen(ri->local_uri);
9809 
9810  /* 1.2. decode url (if config says so) */
9811  if (should_decode_url(conn)) {
9812  mg_url_decode(
9813  ri->local_uri, uri_len, (char *)ri->local_uri, uri_len + 1, 0);
9814  }
9815 
9816  /* 1.3. clean URIs, so a path like allowed_dir/../forbidden_file is
9817  * not possible */
9819 
9820  /* step 1. completed, the url is known now */
9821  DEBUG_TRACE("URL: %s", ri->local_uri);
9822 
9823  /* 2. do a https redirect, if required */
9824  if (!conn->client.is_ssl && conn->client.ssl_redir) {
9825  ssl_index = get_first_ssl_listener_index(conn->ctx);
9826  if (ssl_index >= 0) {
9827  redirect_to_https_port(conn, ssl_index);
9828  } else {
9829  /* A http to https forward port has been specified,
9830  * but no https port to forward to. */
9831  send_http_error(conn,
9832  503,
9833  "%s",
9834  "Error: SSL forward not configured properly");
9835  mg_cry(conn, "Can not redirect to SSL, no SSL port available");
9836  }
9837  return;
9838  }
9839 
9840  /* 3. if this ip has limited speed, set it for this connection */
9841  conn->throttle = set_throttle(conn->ctx->config[THROTTLE],
9842  get_remote_ip(conn),
9843  ri->local_uri);
9844 
9845  /* 4. call a "handle everything" callback, if registered */
9846  if (conn->ctx->callbacks.begin_request != NULL) {
9847  /* Note that since V1.7 the "begin_request" function is called
9848  * before an authorization check. If an authorization check is
9849  * required, use a request_handler instead. */
9850  i = conn->ctx->callbacks.begin_request(conn);
9851  if (i > 0) {
9852  /* callback already processed the request. Store the
9853  return value as a status code for the access log. */
9854  conn->status_code = i;
9855  return;
9856  } else if (i == 0) {
9857  /* civetweb should process the request */
9858  } else {
9859  /* unspecified - may change with the next version */
9860  return;
9861  }
9862  }
9863 
9864  /* request not yet handled by a handler or redirect, so the request
9865  * is processed here */
9866 
9867  /* 5. interpret the url to find out how the request must be handled
9868  */
9869  /* 5.1. first test, if the request targets the regular http(s)://
9870  * protocol namespace or the websocket ws(s):// protocol namespace.
9871  */
9872  is_websocket_request = is_websocket_protocol(conn);
9873 
9874  /* 5.2. check if the request will be handled by a callback */
9875  if (get_request_handler(conn,
9876  is_websocket_request ? WEBSOCKET_HANDLER
9877  : REQUEST_HANDLER,
9878  &callback_handler,
9879  &ws_connect_handler,
9880  &ws_ready_handler,
9881  &ws_data_handler,
9882  &ws_close_handler,
9883  NULL,
9884  &callback_data)) {
9885  /* 5.2.1. A callback will handle this request. All requests
9886  * handled
9887  * by a callback have to be considered as requests to a script
9888  * resource. */
9889  is_callback_resource = 1;
9890  is_script_resource = 1;
9891  is_put_or_delete_request = is_put_or_delete_method(conn);
9892  } else {
9893  no_callback_resource:
9894  /* 5.2.2. No callback is responsible for this request. The URI
9895  * addresses a file based resource (static content or Lua/cgi
9896  * scripts in the file system). */
9897  is_callback_resource = 0;
9898  interpret_uri(conn,
9899  path,
9900  sizeof(path),
9901  &file,
9902  &is_found,
9903  &is_script_resource,
9904  &is_websocket_request,
9905  &is_put_or_delete_request);
9906  }
9907 
9908  /* 6. authorization check */
9909  /* 6.1. a custom authorization handler is installed */
9910  if (get_request_handler(conn,
9911  AUTH_HANDLER,
9912  NULL,
9913  NULL,
9914  NULL,
9915  NULL,
9916  NULL,
9917  &auth_handler,
9918  &auth_callback_data)) {
9919  if (!auth_handler(conn, auth_callback_data)) {
9920  return;
9921  }
9922  } else if (is_put_or_delete_request && !is_script_resource
9923  && !is_callback_resource) {
9924 /* 6.2. this request is a PUT/DELETE to a real file */
9925 /* 6.2.1. thus, the server must have real files */
9926 #if defined(NO_FILES)
9927  if (1) {
9928 #else
9929  if (conn->ctx->config[DOCUMENT_ROOT] == NULL) {
9930 #endif
9931  /* This server does not have any real files, thus the
9932  * PUT/DELETE methods are not valid. */
9933  send_http_error(conn,
9934  405,
9935  "%s method not allowed",
9936  conn->request_info.request_method);
9937  return;
9938  }
9939 
9940 #if !defined(NO_FILES)
9941  /* 6.2.2. Check if put authorization for static files is
9942  * available.
9943  */
9944  if (!is_authorized_for_put(conn)) {
9946  return;
9947  }
9948 #endif
9949 
9950  } else {
9951  /* 6.3. This is either a OPTIONS, GET, HEAD or POST request,
9952  * or it is a PUT or DELETE request to a resource that does not
9953  * correspond to a file. Check authorization. */
9954  if (!check_authorization(conn, path)) {
9956  return;
9957  }
9958  }
9959 
9960  /* request is authorized or does not need authorization */
9961 
9962  /* 7. check if there are request handlers for this uri */
9963  if (is_callback_resource) {
9964  if (!is_websocket_request) {
9965  i = callback_handler(conn, callback_data);
9966  if (i > 0) {
9967  /* Do nothing, callback has served the request. Store
9968  * the
9969  * return value as status code for the log and discard
9970  * all
9971  * data from the client not used by the callback. */
9972  conn->status_code = i;
9974  } else {
9975  /* TODO (high): what if the handler did NOT handle the
9976  * request */
9977  /* The last version did handle this as a file request,
9978  * but
9979  * since a file request is not always a script resource,
9980  * the authorization check might be different */
9981  interpret_uri(conn,
9982  path,
9983  sizeof(path),
9984  &file,
9985  &is_found,
9986  &is_script_resource,
9987  &is_websocket_request,
9988  &is_put_or_delete_request);
9989  callback_handler = NULL;
9990 
9991  /* TODO (very low): goto is deprecated but for the
9992  * moment,
9993  * a goto is simpler than some curious loop. */
9994  /* The situation "callback does not handle the request"
9995  * needs to be reconsidered anyway. */
9996  goto no_callback_resource;
9997  }
9998  } else {
9999 #if defined(USE_WEBSOCKET)
10000  handle_websocket_request(conn,
10001  path,
10002  is_callback_resource,
10003  ws_connect_handler,
10004  ws_ready_handler,
10005  ws_data_handler,
10006  ws_close_handler,
10007  callback_data);
10008 #endif
10009  }
10010  return;
10011  }
10012 
10013 /* 8. handle websocket requests */
10014 #if defined(USE_WEBSOCKET)
10015  if (is_websocket_request) {
10016  if (is_script_resource) {
10017  /* Websocket Lua script */
10018  handle_websocket_request(conn,
10019  path,
10020  0 /* Lua Script */,
10021  NULL,
10022  NULL,
10023  NULL,
10024  NULL,
10025  &conn->ctx->callbacks);
10026  } else {
10027 #if defined(MG_LEGACY_INTERFACE)
10028  handle_websocket_request(
10029  conn,
10030  path,
10031  !is_script_resource /* could be deprecated global callback */,
10032  deprecated_websocket_connect_wrapper,
10033  deprecated_websocket_ready_wrapper,
10034  deprecated_websocket_data_wrapper,
10035  NULL,
10036  &conn->ctx->callbacks);
10037 #else
10038  send_http_error(conn, 404, "%s", "Not found");
10039 #endif
10040  }
10041  return;
10042  } else
10043 #endif
10044 
10045 #if defined(NO_FILES)
10046  /* 9a. In case the server uses only callbacks, this uri is
10047  * unknown.
10048  * Then, all request handling ends here. */
10049  send_http_error(conn, 404, "%s", "Not Found");
10050 
10051 #else
10052  /* 9b. This request is either for a static file or resource handled
10053  * by a script file. Thus, a DOCUMENT_ROOT must exist. */
10054  if (conn->ctx->config[DOCUMENT_ROOT] == NULL) {
10055  send_http_error(conn, 404, "%s", "Not Found");
10056  return;
10057  }
10058 
10059  /* 10. File is handled by a script. */
10060  if (is_script_resource) {
10061  handle_file_based_request(conn, path, &file);
10062  return;
10063  }
10064 
10065  /* 11. Handle put/delete/mkcol requests */
10066  if (is_put_or_delete_request) {
10067  /* 11.1. PUT method */
10068  if (!strcmp(ri->request_method, "PUT")) {
10069  put_file(conn, path);
10070  return;
10071  }
10072  /* 11.2. DELETE method */
10073  if (!strcmp(ri->request_method, "DELETE")) {
10074  delete_file(conn, path);
10075  return;
10076  }
10077  /* 11.3. MKCOL method */
10078  if (!strcmp(ri->request_method, "MKCOL")) {
10079  mkcol(conn, path);
10080  return;
10081  }
10082  /* 11.4. PATCH method
10083  * This method is not supported for static resources,
10084  * only for scripts (Lua, CGI) and callbacks. */
10085  send_http_error(conn,
10086  405,
10087  "%s method not allowed",
10088  conn->request_info.request_method);
10089  return;
10090  }
10091 
10092  /* 11. File does not exist, or it was configured that it should be
10093  * hidden */
10094  if (!is_found || (must_hide_file(conn, path))) {
10095  send_http_error(conn, 404, "%s", "Not found");
10096  return;
10097  }
10098 
10099  /* 12. Directory uris should end with a slash */
10100  if (file.is_directory && ri->local_uri[uri_len - 1] != '/') {
10101  gmt_time_string(date, sizeof(date), &curtime);
10102  mg_printf(conn,
10103  "HTTP/1.1 301 Moved Permanently\r\n"
10104  "Location: %s/\r\n"
10105  "Date: %s\r\n"
10106  /* "Cache-Control: private\r\n" (= default) */
10107  "Content-Length: 0\r\n"
10108  "Connection: %s\r\n\r\n",
10109  ri->request_uri,
10110  date,
10112  return;
10113  }
10114 
10115  /* 13. Handle other methods than GET/HEAD */
10116  /* 13.1. Handle PROPFIND */
10117  if (!strcmp(ri->request_method, "PROPFIND")) {
10118  handle_propfind(conn, path, &file);
10119  return;
10120  }
10121  /* 13.2. Handle OPTIONS for files */
10122  if (!strcmp(ri->request_method, "OPTIONS")) {
10123  /* This standard handler is only used for real files.
10124  * Scripts should support the OPTIONS method themselves, to allow a
10125  * maximum flexibility.
10126  * Lua and CGI scripts may fully support CORS this way (including
10127  * preflights). */
10128  send_options(conn);
10129  return;
10130  }
10131  /* 13.3. everything but GET and HEAD (e.g. POST) */
10132  if (0 != strcmp(ri->request_method, "GET")
10133  && 0 != strcmp(ri->request_method, "HEAD")) {
10134  send_http_error(conn,
10135  405,
10136  "%s method not allowed",
10137  conn->request_info.request_method);
10138  return;
10139  }
10140 
10141  /* 14. directories */
10142  if (file.is_directory) {
10143  if (substitute_index_file(conn, path, sizeof(path), &file)) {
10144  /* 14.1. use a substitute file */
10145  /* TODO (high): substitute index may be a script resource.
10146  * define what should be possible in this case. */
10147  } else {
10148  /* 14.2. no substitute file */
10149  if (!mg_strcasecmp(conn->ctx->config[ENABLE_DIRECTORY_LISTING],
10150  "yes")) {
10151  handle_directory_request(conn, path);
10152  } else {
10153  send_http_error(conn,
10154  403,
10155  "%s",
10156  "Error: Directory listing denied");
10157  }
10158  return;
10159  }
10160  }
10161 
10162  handle_file_based_request(conn, path, &file);
10163 #endif /* !defined(NO_FILES) */
10164 
10165 #if 0
10166  /* Perform redirect and auth checks before calling begin_request()
10167  * handler.
10168  * Otherwise, begin_request() would need to perform auth checks and
10169  * redirects. */
10170 #endif
10171  }
10172  return;
10173 }
10174 
10175 
10176 static void
10177 handle_file_based_request(struct mg_connection *conn,
10178  const char *path,
10179  struct file *file)
10180 {
10181  if (!conn || !conn->ctx) {
10182  return;
10183  }
10184 
10185  if (0) {
10186 #ifdef USE_LUA
10187  } else if (match_prefix(conn->ctx->config[LUA_SERVER_PAGE_EXTENSIONS],
10188  strlen(
10189  conn->ctx->config[LUA_SERVER_PAGE_EXTENSIONS]),
10190  path) > 0) {
10191  /* Lua server page: an SSI like page containing mostly plain html
10192  * code
10193  * plus some tags with server generated contents. */
10194  handle_lsp_request(conn, path, file, NULL);
10195  } else if (match_prefix(conn->ctx->config[LUA_SCRIPT_EXTENSIONS],
10196  strlen(conn->ctx->config[LUA_SCRIPT_EXTENSIONS]),
10197  path) > 0) {
10198  /* Lua in-server module script: a CGI like script used to generate
10199  * the
10200  * entire reply. */
10201  mg_exec_lua_script(conn, path, NULL);
10202 #endif
10203 #if defined(USE_DUKTAPE)
10204  } else if (match_prefix(conn->ctx->config[DUKTAPE_SCRIPT_EXTENSIONS],
10205  strlen(
10206  conn->ctx->config[DUKTAPE_SCRIPT_EXTENSIONS]),
10207  path) > 0) {
10208  /* Call duktape to generate the page */
10209  mg_exec_duktape_script(conn, path);
10210 #endif
10211 #if !defined(NO_CGI)
10212  } else if (match_prefix(conn->ctx->config[CGI_EXTENSIONS],
10213  strlen(conn->ctx->config[CGI_EXTENSIONS]),
10214  path) > 0) {
10215  /* CGI scripts may support all HTTP methods */
10216  handle_cgi_request(conn, path);
10217 #endif /* !NO_CGI */
10218  } else if (match_prefix(conn->ctx->config[SSI_EXTENSIONS],
10219  strlen(conn->ctx->config[SSI_EXTENSIONS]),
10220  path) > 0) {
10221  handle_ssi_file_request(conn, path, file);
10222 #if !defined(NO_CACHING)
10223  } else if ((!conn->in_error_handler) && is_not_modified(conn, file)) {
10224  /* Send 304 "Not Modified" - this must not send any body data */
10225  send_http_error(conn, 304, "%s", "");
10226 #endif /* !NO_CACHING */
10227  } else {
10228  handle_static_file_request(conn, path, file, NULL);
10229  }
10230 }
10231 
10232 
10233 static void
10234 close_all_listening_sockets(struct mg_context *ctx)
10235 {
10236  unsigned int i;
10237  if (!ctx) {
10238  return;
10239  }
10240 
10241  for (i = 0; i < ctx->num_listening_sockets; i++) {
10242  closesocket(ctx->listening_sockets[i].sock);
10243  ctx->listening_sockets[i].sock = INVALID_SOCKET;
10244  }
10245  mg_free(ctx->listening_sockets);
10246  ctx->listening_sockets = NULL;
10247  mg_free(ctx->listening_ports);
10248  ctx->listening_ports = NULL;
10249 }
10250 
10251 
10252 /* Valid listening port specification is: [ip_address:]port[s]
10253  * Examples for IPv4: 80, 443s, 127.0.0.1:3128, 1.2.3.4:8080s
10254  * Examples for IPv6: [::]:80, [::1]:80,
10255  * [FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:443s
10256  * see https://tools.ietf.org/html/rfc3513#section-2.2 */
10257 static int
10258 parse_port_string(const struct vec *vec, struct socket *so)
10259 {
10260  unsigned int a, b, c, d, port;
10261  int ch, len;
10262 #if defined(USE_IPV6)
10263  char buf[100] = {0};
10264 #endif
10265 
10266  /* MacOS needs that. If we do not zero it, subsequent bind() will fail.
10267  * Also, all-zeroes in the socket address means binding to all addresses
10268  * for both IPv4 and IPv6 (INADDR_ANY and IN6ADDR_ANY_INIT). */
10269  memset(so, 0, sizeof(*so));
10270  so->lsa.sin.sin_family = AF_INET;
10271 
10272  if (sscanf(vec->ptr, "%u.%u.%u.%u:%u%n", &a, &b, &c, &d, &port, &len)
10273  == 5) {
10274  /* Bind to a specific IPv4 address, e.g. 192.168.1.5:8080 */
10275  so->lsa.sin.sin_addr.s_addr =
10276  htonl((a << 24) | (b << 16) | (c << 8) | d);
10277  so->lsa.sin.sin_port = htons((uint16_t)port);
10278 #if defined(USE_IPV6)
10279  } else if (sscanf(vec->ptr, "[%49[^]]]:%u%n", buf, &port, &len) == 2
10280  && mg_inet_pton(
10281  AF_INET6, buf, &so->lsa.sin6, sizeof(so->lsa.sin6))) {
10282  /* IPv6 address, examples: see above */
10283  /* so->lsa.sin6.sin6_family = AF_INET6; already set by mg_inet_pton
10284  */
10285  so->lsa.sin6.sin6_port = htons((uint16_t)port);
10286 #endif
10287  } else if (sscanf(vec->ptr, "%u%n", &port, &len) == 1) {
10288  /* If only port is specified, bind to IPv4, INADDR_ANY */
10289  so->lsa.sin.sin_port = htons((uint16_t)port);
10290  } else {
10291  /* Parsing failure. Make port invalid. */
10292  port = 0;
10293  len = 0;
10294  }
10295 
10296  /* sscanf and the option splitting code ensure the following condition
10297  */
10298  if ((len < 0) && ((unsigned)len > (unsigned)vec->len)) {
10299  return 0;
10300  }
10301  ch = vec->ptr[len]; /* Next character after the port number */
10302  so->is_ssl = (ch == 's');
10303  so->ssl_redir = (ch == 'r');
10304 
10305  /* Make sure the port is valid and vector ends with 's', 'r' or ',' */
10306  return is_valid_port(port)
10307  && (ch == '\0' || ch == 's' || ch == 'r' || ch == ',');
10308 }
10309 
10310 
10311 static int
10312 set_ports_option(struct mg_context *ctx)
10313 {
10314  const char *list;
10315  int on = 1;
10316 #if defined(USE_IPV6)
10317  int off = 0;
10318 #endif
10319  struct vec vec;
10320  struct socket so, *ptr;
10321 
10322  in_port_t *portPtr;
10323  union usa usa;
10324  socklen_t len;
10325 
10326  int portsTotal = 0;
10327  int portsOk = 0;
10328 
10329  if (!ctx) {
10330  return 0;
10331  }
10332 
10333  memset(&so, 0, sizeof(so));
10334  memset(&usa, 0, sizeof(usa));
10335  len = sizeof(usa);
10336  list = ctx->config[LISTENING_PORTS];
10337  while ((list = next_option(list, &vec, NULL)) != NULL) {
10338 
10339  portsTotal++;
10340 
10341  if (!parse_port_string(&vec, &so)) {
10342  mg_cry(fc(ctx),
10343  "%.*s: invalid port spec (entry %i). Expecting list of: %s",
10344  (int)vec.len,
10345  vec.ptr,
10346  portsTotal,
10347  "[IP_ADDRESS:]PORT[s|r]");
10348  continue;
10349  }
10350 
10351  if (so.is_ssl && ctx->ssl_ctx == NULL) {
10352 
10353  mg_cry(fc(ctx),
10354  "Cannot add SSL socket (entry %i). Is -ssl_certificate "
10355  "option set?",
10356  portsTotal);
10357  continue;
10358  }
10359 
10360  if ((so.sock = socket(so.lsa.sa.sa_family, SOCK_STREAM, 6))
10361  == INVALID_SOCKET) {
10362 
10363  mg_cry(fc(ctx), "cannot create socket (entry %i)", portsTotal);
10364  continue;
10365  }
10366 
10367 #ifdef _WIN32
10368  /* Windows SO_REUSEADDR lets many procs binds to a
10369  * socket, SO_EXCLUSIVEADDRUSE makes the bind fail
10370  * if someone already has the socket -- DTL */
10371  /* NOTE: If SO_EXCLUSIVEADDRUSE is used,
10372  * Windows might need a few seconds before
10373  * the same port can be used again in the
10374  * same process, so a short Sleep may be
10375  * required between mg_stop and mg_start.
10376  */
10377  if (setsockopt(so.sock,
10378  SOL_SOCKET,
10379  SO_EXCLUSIVEADDRUSE,
10380  (SOCK_OPT_TYPE)&on,
10381  sizeof(on)) != 0) {
10382 
10383  mg_cry(fc(ctx),
10384  "cannot set socket option SO_EXCLUSIVEADDRUSE (entry %i)",
10385  portsTotal);
10386  }
10387 #else
10388  if (setsockopt(so.sock,
10389  SOL_SOCKET,
10390  SO_REUSEADDR,
10391  (SOCK_OPT_TYPE)&on,
10392  sizeof(on)) != 0) {
10393 
10394  mg_cry(fc(ctx),
10395  "cannot set socket option SO_REUSEADDR (entry %i)",
10396  portsTotal);
10397  }
10398 #endif
10399 
10400 #if defined(USE_IPV6)
10401  if (so.lsa.sa.sa_family == AF_INET6
10402  && setsockopt(so.sock,
10403  IPPROTO_IPV6,
10404  IPV6_V6ONLY,
10405  (void *)&off,
10406  sizeof(off)) != 0) {
10407 
10408  mg_cry(fc(ctx),
10409  "cannot set socket option IPV6_V6ONLY (entry %i)",
10410  portsTotal);
10411  }
10412 #endif
10413 
10414  if (so.lsa.sa.sa_family == AF_INET) {
10415 
10416  len = sizeof(so.lsa.sin);
10417  if (bind(so.sock, &so.lsa.sa, len) != 0) {
10418  mg_cry(fc(ctx),
10419  "cannot bind to %.*s: %d (%s)",
10420  (int)vec.len,
10421  vec.ptr,
10422  (int)ERRNO,
10423  strerror(errno));
10424  closesocket(so.sock);
10425  so.sock = INVALID_SOCKET;
10426  continue;
10427  }
10428  }
10429 #if defined(USE_IPV6)
10430  else if (so.lsa.sa.sa_family == AF_INET6) {
10431 
10432  len = sizeof(so.lsa.sin6);
10433  if (bind(so.sock, &so.lsa.sa, len) != 0) {
10434  mg_cry(fc(ctx),
10435  "cannot bind to IPv6 %.*s: %d (%s)",
10436  (int)vec.len,
10437  vec.ptr,
10438  (int)ERRNO,
10439  strerror(errno));
10440  closesocket(so.sock);
10441  so.sock = INVALID_SOCKET;
10442  continue;
10443  }
10444  }
10445 #endif
10446  else {
10447  mg_cry(fc(ctx),
10448  "cannot bind: address family not supported (entry %i)",
10449  portsTotal);
10450  continue;
10451  }
10452 
10453  if (listen(so.sock, SOMAXCONN) != 0) {
10454 
10455  mg_cry(fc(ctx),
10456  "cannot listen to %.*s: %d (%s)",
10457  (int)vec.len,
10458  vec.ptr,
10459  (int)ERRNO,
10460  strerror(errno));
10461  closesocket(so.sock);
10462  so.sock = INVALID_SOCKET;
10463  continue;
10464  }
10465 
10466  if (getsockname(so.sock, &(usa.sa), &len) != 0) {
10467 
10468  int err = (int)ERRNO;
10469  mg_cry(fc(ctx),
10470  "call to getsockname failed %.*s: %d (%s)",
10471  (int)vec.len,
10472  vec.ptr,
10473  err,
10474  strerror(errno));
10475  closesocket(so.sock);
10476  so.sock = INVALID_SOCKET;
10477  continue;
10478  }
10479 
10480  if ((ptr = (struct socket *)
10481  mg_realloc(ctx->listening_sockets,
10482  (ctx->num_listening_sockets + 1)
10483  * sizeof(ctx->listening_sockets[0]))) == NULL) {
10484 
10485  mg_cry(fc(ctx), "%s", "Out of memory");
10486  closesocket(so.sock);
10487  so.sock = INVALID_SOCKET;
10488  continue;
10489  }
10490 
10491  if ((portPtr =
10492  (in_port_t *)mg_realloc(ctx->listening_ports,
10493  (ctx->num_listening_sockets + 1)
10494  * sizeof(ctx->listening_ports[0])))
10495  == NULL) {
10496 
10497  mg_cry(fc(ctx), "%s", "Out of memory");
10498  closesocket(so.sock);
10499  so.sock = INVALID_SOCKET;
10500  mg_free(ptr);
10501  continue;
10502  }
10503 
10504  set_close_on_exec(so.sock, fc(ctx));
10505  ctx->listening_sockets = ptr;
10506  ctx->listening_sockets[ctx->num_listening_sockets] = so;
10507  ctx->listening_ports = portPtr;
10508  ctx->listening_ports[ctx->num_listening_sockets] =
10509  ntohs(usa.sin.sin_port);
10510  ctx->num_listening_sockets++;
10511  portsOk++;
10512  }
10513 
10514  if (portsOk != portsTotal) {
10516  portsOk = 0;
10517  }
10518 
10519  return portsOk;
10520 }
10521 
10522 
10523 static const char *
10524 header_val(const struct mg_connection *conn, const char *header)
10525 {
10526  const char *header_value;
10527 
10528  if ((header_value = mg_get_header(conn, header)) == NULL) {
10529  return "-";
10530  } else {
10531  return header_value;
10532  }
10533 }
10534 
10535 
10536 static void
10537 log_access(const struct mg_connection *conn)
10538 {
10539  const struct mg_request_info *ri;
10540  struct file fi;
10541  char date[64], src_addr[IP_ADDR_STR_LEN];
10542  struct tm *tm;
10543 
10544  const char *referer;
10545  const char *user_agent;
10546 
10547  char buf[4096];
10548 
10549  if (!conn || !conn->ctx) {
10550  return;
10551  }
10552 
10553  if (conn->ctx->config[ACCESS_LOG_FILE] != NULL) {
10554  if (mg_fopen(conn, conn->ctx->config[ACCESS_LOG_FILE], "a+", &fi)
10555  == 0) {
10556  fi.fp = NULL;
10557  }
10558  } else {
10559  fi.fp = NULL;
10560  }
10561 
10562  if (fi.fp == NULL && conn->ctx->callbacks.log_message == NULL) {
10563  return;
10564  }
10565 
10566  tm = localtime(&conn->conn_birth_time);
10567  if (tm != NULL) {
10568  strftime(date, sizeof(date), "%d/%b/%Y:%H:%M:%S %z", tm);
10569  } else {
10570  mg_strlcpy(date, "01/Jan/1970:00:00:00 +0000", sizeof(date));
10571  date[sizeof(date) - 1] = '\0';
10572  }
10573 
10574  ri = &conn->request_info;
10575 
10576  sockaddr_to_string(src_addr, sizeof(src_addr), &conn->client.rsa);
10577  referer = header_val(conn, "Referer");
10578  user_agent = header_val(conn, "User-Agent");
10579 
10580  mg_snprintf(conn,
10581  NULL, /* Ignore truncation in access log */
10582  buf,
10583  sizeof(buf),
10584  "%s - %s [%s] \"%s %s%s%s HTTP/%s\" %d %" INT64_FMT " %s %s",
10585  src_addr,
10586  ri->remote_user == NULL ? "-" : ri->remote_user,
10587  date,
10588  ri->request_method ? ri->request_method : "-",
10589  ri->request_uri ? ri->request_uri : "-",
10590  ri->query_string ? "?" : "",
10591  ri->query_string ? ri->query_string : "",
10592  ri->http_version,
10593  conn->status_code,
10594  conn->num_bytes_sent,
10595  referer,
10596  user_agent);
10597 
10598  if (conn->ctx->callbacks.log_access) {
10599  conn->ctx->callbacks.log_access(conn, buf);
10600  }
10601 
10602  if (fi.fp) {
10603  flockfile(fi.fp);
10604  fprintf(fi.fp, "%s\n", buf);
10605  fflush(fi.fp);
10606  funlockfile(fi.fp);
10607  mg_fclose(&fi);
10608  }
10609 }
10610 
10611 
10612 /* Verify given socket address against the ACL.
10613  * Return -1 if ACL is malformed, 0 if address is disallowed, 1 if allowed.
10614  */
10615 static int
10616 check_acl(struct mg_context *ctx, uint32_t remote_ip)
10617 {
10618  int allowed, flag;
10619  uint32_t net, mask;
10620  struct vec vec;
10621 
10622  if (ctx) {
10623  const char *list = ctx->config[ACCESS_CONTROL_LIST];
10624 
10625  /* If any ACL is set, deny by default */
10626  allowed = list == NULL ? '+' : '-';
10627 
10628  while ((list = next_option(list, &vec, NULL)) != NULL) {
10629  flag = vec.ptr[0];
10630  if ((flag != '+' && flag != '-')
10631  || parse_net(&vec.ptr[1], &net, &mask) == 0) {
10632  mg_cry(fc(ctx),
10633  "%s: subnet must be [+|-]x.x.x.x[/x]",
10634  __func__);
10635  return -1;
10636  }
10637 
10638  if (net == (remote_ip & mask)) {
10639  allowed = flag;
10640  }
10641  }
10642 
10643  return allowed == '+';
10644  }
10645  return -1;
10646 }
10647 
10648 
10649 #if !defined(_WIN32)
10650 static int
10651 set_uid_option(struct mg_context *ctx)
10652 {
10653  struct passwd *pw;
10654  if (ctx) {
10655  const char *uid = ctx->config[RUN_AS_USER];
10656  int success = 0;
10657 
10658  if (uid == NULL) {
10659  success = 1;
10660  } else {
10661  if ((pw = getpwnam(uid)) == NULL) {
10662  mg_cry(fc(ctx), "%s: unknown user [%s]", __func__, uid);
10663  } else if (setgid(pw->pw_gid) == -1) {
10664  mg_cry(fc(ctx),
10665  "%s: setgid(%s): %s",
10666  __func__,
10667  uid,
10668  strerror(errno));
10669  } else if (setgroups(0, NULL)) {
10670  mg_cry(fc(ctx),
10671  "%s: setgroups(): %s",
10672  __func__,
10673  strerror(errno));
10674  } else if (setuid(pw->pw_uid) == -1) {
10675  mg_cry(fc(ctx),
10676  "%s: setuid(%s): %s",
10677  __func__,
10678  uid,
10679  strerror(errno));
10680  } else {
10681  success = 1;
10682  }
10683  }
10684 
10685  return success;
10686  }
10687  return 0;
10688 }
10689 #endif /* !_WIN32 */
10690 
10691 
10692 static void
10693 tls_dtor(void *key)
10694 {
10695  struct mg_workerTLS *tls = (struct mg_workerTLS *)key;
10696  /* key == pthread_getspecific(sTlsKey); */
10697 
10698  if (tls) {
10699  if (tls->is_master == 2) {
10700  tls->is_master = -3; /* Mark memory as dead */
10701  mg_free(tls);
10702  }
10703  }
10704  pthread_setspecific(sTlsKey, NULL);
10705 }
10706 
10707 
10708 #if !defined(NO_SSL)
10709 
10710 /* Must be set if sizeof(pthread_t) > sizeof(unsigned long) */
10711 static unsigned long
10713 {
10714 #ifdef _WIN32
10715  return GetCurrentThreadId();
10716 #else
10717 
10718 #ifdef __clang__
10719 #pragma clang diagnostic push
10720 #pragma clang diagnostic ignored "-Wunreachable-code"
10721 /* For every compiler, either "sizeof(pthread_t) > sizeof(unsigned long)"
10722  * or not, so one of the two conditions will be unreachable by construction.
10723  * Unfortunately the C standard does not define a way to check this at
10724  * compile time, since the #if preprocessor conditions can not use the sizeof
10725  * operator as an argument. */
10726 #endif
10727 
10728  if (sizeof(pthread_t) > sizeof(unsigned long)) {
10729  /* This is the problematic case for CRYPTO_set_id_callback:
10730  * The OS pthread_t can not be cast to unsigned long. */
10731  struct mg_workerTLS *tls =
10732  (struct mg_workerTLS *)pthread_getspecific(sTlsKey);
10733  if (tls == NULL) {
10734  /* SSL called from an unknown thread: Create some thread index.
10735  */
10736  tls = (struct mg_workerTLS *)mg_malloc(sizeof(struct mg_workerTLS));
10737  tls->is_master = -2; /* -2 means "3rd party thread" */
10738  tls->thread_idx = (unsigned)mg_atomic_inc(&thread_idx_max);
10739  pthread_setspecific(sTlsKey, tls);
10740  }
10741  return tls->thread_idx;
10742  } else {
10743  /* pthread_t may be any data type, so a simple cast to unsigned long
10744  * can rise a warning/error, depending on the platform.
10745  * Here memcpy is used as an anything-to-anything cast. */
10746  unsigned long ret = 0;
10747  pthread_t t = pthread_self();
10748  memcpy(&ret, &t, sizeof(pthread_t));
10749  return ret;
10750  }
10751 
10752 #ifdef __clang__
10753 #pragma clang diagnostic pop
10754 #endif
10755 
10756 #endif
10757 }
10758 
10759 
10760 static int ssl_use_pem_file(struct mg_context *ctx, const char *pem);
10761 static const char *ssl_error(void);
10762 
10763 
10764 static int
10765 refresh_trust(struct mg_connection *conn)
10766 {
10767  static int reload_lock = 0;
10768  static long int data_check = 0;
10769 
10770  struct stat cert_buf;
10771  long int t;
10772  char *pem;
10773  int should_verify_peer;
10774 
10775  if ((pem = conn->ctx->config[SSL_CERTIFICATE]) == NULL
10776  && conn->ctx->callbacks.init_ssl == NULL) {
10777  return 0;
10778  }
10779 
10780  t = data_check;
10781  if (stat(pem, &cert_buf) != -1) {
10782  t = (long int)cert_buf.st_mtime;
10783  }
10784 
10785  if (data_check != t) {
10786  data_check = t;
10787 
10788  should_verify_peer =
10789  (conn->ctx->config[SSL_DO_VERIFY_PEER] != NULL)
10790  && (mg_strcasecmp(conn->ctx->config[SSL_DO_VERIFY_PEER], "yes")
10791  == 0);
10792 
10793  if (should_verify_peer) {
10794  char *ca_path = conn->ctx->config[SSL_CA_PATH];
10795  char *ca_file = conn->ctx->config[SSL_CA_FILE];
10796  if (SSL_CTX_load_verify_locations(conn->ctx->ssl_ctx,
10797  ca_file,
10798  ca_path) != 1) {
10799  mg_cry(fc(conn->ctx),
10800  "SSL_CTX_load_verify_locations error: %s "
10801  "ssl_verify_peer requires setting "
10802  "either ssl_ca_path or ssl_ca_file. Is any of them "
10803  "present in "
10804  "the .conf file?",
10805  ssl_error());
10806  return 0;
10807  }
10808  }
10809 
10810  if (!reload_lock) {
10811  reload_lock = 1;
10812  if (ssl_use_pem_file(conn->ctx, pem) == 0) {
10813  return 0;
10814  }
10815  reload_lock = 0;
10816  }
10817  }
10818  /* lock while cert is reloading */
10819  while (reload_lock) {
10820  sleep(1);
10821  }
10822 
10823  return 1;
10824 }
10825 
10826 
10827 static pthread_mutex_t *ssl_mutexes;
10828 
10829 
10830 static int
10831 sslize(struct mg_connection *conn, SSL_CTX *s, int (*func)(SSL *))
10832 {
10833  int ret, err;
10834  int short_trust;
10835 
10836  if (!conn) {
10837  return 0;
10838  }
10839 
10840  short_trust =
10841  (conn->ctx->config[SSL_SHORT_TRUST] != NULL)
10842  && (mg_strcasecmp(conn->ctx->config[SSL_SHORT_TRUST], "yes") == 0);
10843 
10844  if (short_trust) {
10845  int trust_ret = refresh_trust(conn);
10846  if (!trust_ret) {
10847  return trust_ret;
10848  }
10849  }
10850 
10851  conn->ssl = SSL_new(s);
10852  if (conn->ssl == NULL) {
10853  return 0;
10854  }
10855 
10856  ret = SSL_set_fd(conn->ssl, conn->client.sock);
10857  if (ret != 1) {
10858  err = SSL_get_error(conn->ssl, ret);
10859  (void)err; /* TODO: set some error message */
10860  SSL_free(conn->ssl);
10861  conn->ssl = NULL;
10862  /* maybe not? CRYPTO_cleanup_all_ex_data(); */
10863  /* see
10864  * https://wiki.openssl.org/index.php/Talk:Library_Initialization */
10865  ERR_remove_state(0);
10866  return 0;
10867  }
10868 
10869  ret = func(conn->ssl);
10870  if (ret != 1) {
10871  err = SSL_get_error(conn->ssl, ret);
10872  (void)err; /* TODO: set some error message */
10873  SSL_free(conn->ssl);
10874  conn->ssl = NULL;
10875  /* maybe not? CRYPTO_cleanup_all_ex_data(); */
10876  /* see
10877  * https://wiki.openssl.org/index.php/Talk:Library_Initialization */
10878  ERR_remove_state(0);
10879  return 0;
10880  }
10881 
10882  return 1;
10883 }
10884 
10885 
10886 /* Return OpenSSL error message (from CRYPTO lib) */
10887 static const char *
10889 {
10890  unsigned long err;
10891  err = ERR_get_error();
10892  return err == 0 ? "" : ERR_error_string(err, NULL);
10893 }
10894 
10895 
10896 static void
10897 ssl_locking_callback(int mode, int mutex_num, const char *file, int line)
10898 {
10899  (void)line;
10900  (void)file;
10901 
10902  if (mode & 1) {
10903  /* 1 is CRYPTO_LOCK */
10904  (void)pthread_mutex_lock(&ssl_mutexes[mutex_num]);
10905  } else {
10906  (void)pthread_mutex_unlock(&ssl_mutexes[mutex_num]);
10907  }
10908 }
10909 
10910 
10911 #if !defined(NO_SSL_DL)
10912 static void *
10913 load_dll(struct mg_context *ctx, const char *dll_name, struct ssl_func *sw)
10914 {
10915  union {
10916  void *p;
10917  void (*fp)(void);
10918  } u;
10919  void *dll_handle;
10920  struct ssl_func *fp;
10921 
10922  if ((dll_handle = dlopen(dll_name, RTLD_LAZY)) == NULL) {
10923  mg_cry(fc(ctx), "%s: cannot load %s", __func__, dll_name);
10924  return NULL;
10925  }
10926 
10927  for (fp = sw; fp->name != NULL; fp++) {
10928 #ifdef _WIN32
10929  /* GetProcAddress() returns pointer to function */
10930  u.fp = (void (*)(void))dlsym(dll_handle, fp->name);
10931 #else
10932  /* dlsym() on UNIX returns void *. ISO C forbids casts of data
10933  * pointers to function pointers. We need to use a union to make a
10934  * cast. */
10935  u.p = dlsym(dll_handle, fp->name);
10936 #endif /* _WIN32 */
10937  if (u.fp == NULL) {
10938  mg_cry(fc(ctx),
10939  "%s: %s: cannot find %s",
10940  __func__,
10941  dll_name,
10942  fp->name);
10943  dlclose(dll_handle);
10944  return NULL;
10945  } else {
10946  fp->ptr = u.fp;
10947  }
10948  }
10949 
10950  return dll_handle;
10951 }
10952 
10953 
10954 static void *ssllib_dll_handle; /* Store the ssl library handle. */
10955 static void *cryptolib_dll_handle; /* Store the crypto library handle. */
10956 
10957 #endif /* NO_SSL_DL */
10958 
10959 
10960 #if defined(SSL_ALREADY_INITIALIZED)
10961 static int cryptolib_users = 1; /* Reference counter for crypto library. */
10962 #else
10963 static int cryptolib_users = 0; /* Reference counter for crypto library. */
10964 #endif
10965 
10966 
10967 static int
10968 initialize_ssl(struct mg_context *ctx)
10969 {
10970  int i;
10971  size_t size;
10972 
10973 #if !defined(NO_SSL_DL)
10974  if (!cryptolib_dll_handle) {
10975  cryptolib_dll_handle = load_dll(ctx, CRYPTO_LIB, crypto_sw);
10976  if (!cryptolib_dll_handle) {
10977  return 0;
10978  }
10979  }
10980 #endif /* NO_SSL_DL */
10981 
10982  if (mg_atomic_inc(&cryptolib_users) > 1) {
10983  return 1;
10984  }
10985 
10986  /* Initialize locking callbacks, needed for thread safety.
10987  * http://www.openssl.org/support/faq.html#PROG1
10988  */
10989  i = CRYPTO_num_locks();
10990  if (i < 0) {
10991  i = 0;
10992  }
10993  size = sizeof(pthread_mutex_t) * ((size_t)(i));
10994  if ((ssl_mutexes = (pthread_mutex_t *)mg_malloc(size)) == NULL) {
10995  mg_cry(fc(ctx),
10996  "%s: cannot allocate mutexes: %s",
10997  __func__,
10998  ssl_error());
10999  return 0;
11000  }
11001 
11002  for (i = 0; i < CRYPTO_num_locks(); i++) {
11003  pthread_mutex_init(&ssl_mutexes[i], &pthread_mutex_attr);
11004  }
11005 
11008 
11009  return 1;
11010 }
11011 
11012 
11013 static int
11014 ssl_use_pem_file(struct mg_context *ctx, const char *pem)
11015 {
11016  if (SSL_CTX_use_certificate_file(ctx->ssl_ctx, pem, 1) == 0) {
11017  mg_cry(fc(ctx),
11018  "%s: cannot open certificate file %s: %s",
11019  __func__,
11020  pem,
11021  ssl_error());
11022  return 0;
11023  }
11024 
11025  /* could use SSL_CTX_set_default_passwd_cb_userdata */
11026  if (SSL_CTX_use_PrivateKey_file(ctx->ssl_ctx, pem, 1) == 0) {
11027  mg_cry(fc(ctx),
11028  "%s: cannot open private key file %s: %s",
11029  __func__,
11030  pem,
11031  ssl_error());
11032  return 0;
11033  }
11034 
11035  if (SSL_CTX_check_private_key(ctx->ssl_ctx) == 0) {
11036  mg_cry(fc(ctx),
11037  "%s: certificate and private key do not match: %s",
11038  __func__,
11039  pem);
11040  return 0;
11041  }
11042 
11043  if (SSL_CTX_use_certificate_chain_file(ctx->ssl_ctx, pem) == 0) {
11044  mg_cry(fc(ctx),
11045  "%s: cannot use certificate chain file %s: %s",
11046  __func__,
11047  pem,
11048  ssl_error());
11049  return 0;
11050  }
11051  return 1;
11052 }
11053 
11054 
11055 static long
11056 ssl_get_protocol(int version_id)
11057 {
11058  long ret = SSL_OP_ALL;
11059  if (version_id > 0)
11060  ret |= SSL_OP_NO_SSLv2;
11061  if (version_id > 1)
11062  ret |= SSL_OP_NO_SSLv3;
11063  if (version_id > 2)
11064  ret |= SSL_OP_NO_TLSv1;
11065  if (version_id > 3)
11066  ret |= SSL_OP_NO_TLSv1_1;
11067  return ret;
11068 }
11069 
11070 
11071 /* Dynamically load SSL library. Set up ctx->ssl_ctx pointer. */
11072 static int
11073 set_ssl_option(struct mg_context *ctx)
11074 {
11075  const char *pem;
11076  int callback_ret;
11077  int should_verify_peer;
11078  const char *ca_path;
11079  const char *ca_file;
11080  int use_default_verify_paths;
11081  int verify_depth;
11082  time_t now_rt = time(NULL);
11083  struct timespec now_mt;
11084  md5_byte_t ssl_context_id[16];
11085  md5_state_t md5state;
11086  int protocol_ver;
11087 
11088  /* If PEM file is not specified and the init_ssl callback
11089  * is not specified, skip SSL initialization. */
11090  if (!ctx) {
11091  return 0;
11092  }
11093  if ((pem = ctx->config[SSL_CERTIFICATE]) == NULL
11094  && ctx->callbacks.init_ssl == NULL) {
11095  return 1;
11096  }
11097 
11098  if (!initialize_ssl(ctx)) {
11099  return 0;
11100  }
11101 
11102 #if !defined(NO_SSL_DL)
11103  if (!ssllib_dll_handle) {
11104  ssllib_dll_handle = load_dll(ctx, SSL_LIB, ssl_sw);
11105  if (!ssllib_dll_handle) {
11106  return 0;
11107  }
11108  }
11109 #endif /* NO_SSL_DL */
11110 
11111  /* Initialize SSL library */
11112  SSL_library_init();
11114 
11115  if ((ctx->ssl_ctx = SSL_CTX_new(SSLv23_server_method())) == NULL) {
11116  mg_cry(fc(ctx), "SSL_CTX_new (server) error: %s", ssl_error());
11117  return 0;
11118  }
11119 
11120  SSL_CTX_clear_options(ctx->ssl_ctx,
11122  | SSL_OP_NO_TLSv1_1);
11123  protocol_ver = atoi(ctx->config[SSL_PROTOCOL_VERSION]);
11124  SSL_CTX_set_options(ctx->ssl_ctx, ssl_get_protocol(protocol_ver));
11126  SSL_CTX_set_ecdh_auto(ctx->ssl_ctx, 1);
11127 
11128  /* If a callback has been specified, call it. */
11129  callback_ret =
11130  (ctx->callbacks.init_ssl == NULL)
11131  ? 0
11132  : (ctx->callbacks.init_ssl(ctx->ssl_ctx, ctx->user_data));
11133 
11134  /* If callback returns 0, civetweb sets up the SSL certificate.
11135  * If it returns 1, civetweb assumes the calback already did this.
11136  * If it returns -1, initializing ssl fails. */
11137  if (callback_ret < 0) {
11138  mg_cry(fc(ctx), "SSL callback returned error: %i", callback_ret);
11139  return 0;
11140  }
11141  if (callback_ret > 0) {
11142  if (pem != NULL) {
11143  (void)SSL_CTX_use_certificate_chain_file(ctx->ssl_ctx, pem);
11144  }
11145  return 1;
11146  }
11147 
11148  /* Use some UID as session context ID. */
11149  md5_init(&md5state);
11150  md5_append(&md5state, (const md5_byte_t *)&now_rt, sizeof(now_rt));
11151  clock_gettime(CLOCK_MONOTONIC, &now_mt);
11152  md5_append(&md5state, (const md5_byte_t *)&now_mt, sizeof(now_mt));
11153  md5_append(&md5state,
11154  (const md5_byte_t *)ctx->config[LISTENING_PORTS],
11155  strlen(ctx->config[LISTENING_PORTS]));
11156  md5_append(&md5state, (const md5_byte_t *)ctx, sizeof(*ctx));
11157  md5_finish(&md5state, ssl_context_id);
11158 
11159  SSL_CTX_set_session_id_context(ctx->ssl_ctx,
11160  (const unsigned char *)&ssl_context_id,
11161  sizeof(ssl_context_id));
11162 
11163  if (pem != NULL) {
11164  if (!ssl_use_pem_file(ctx, pem)) {
11165  return 0;
11166  }
11167  }
11168 
11169  should_verify_peer =
11170  (ctx->config[SSL_DO_VERIFY_PEER] != NULL)
11171  && (mg_strcasecmp(ctx->config[SSL_DO_VERIFY_PEER], "yes") == 0);
11172 
11173  use_default_verify_paths =
11174  (ctx->config[SSL_DEFAULT_VERIFY_PATHS] != NULL)
11175  && (mg_strcasecmp(ctx->config[SSL_DEFAULT_VERIFY_PATHS], "yes") == 0);
11176 
11177  if (should_verify_peer) {
11178  ca_path = ctx->config[SSL_CA_PATH];
11179  ca_file = ctx->config[SSL_CA_FILE];
11180  if (SSL_CTX_load_verify_locations(ctx->ssl_ctx, ca_file, ca_path)
11181  != 1) {
11182  mg_cry(fc(ctx),
11183  "SSL_CTX_load_verify_locations error: %s "
11184  "ssl_verify_peer requires setting "
11185  "either ssl_ca_path or ssl_ca_file. Is any of them "
11186  "present in "
11187  "the .conf file?",
11188  ssl_error());
11189  return 0;
11190  }
11191 
11192  SSL_CTX_set_verify(ctx->ssl_ctx,
11194  NULL);
11195 
11196  if (use_default_verify_paths
11197  && SSL_CTX_set_default_verify_paths(ctx->ssl_ctx) != 1) {
11198  mg_cry(fc(ctx),
11199  "SSL_CTX_set_default_verify_paths error: %s",
11200  ssl_error());
11201  return 0;
11202  }
11203 
11204  if (ctx->config[SSL_VERIFY_DEPTH]) {
11205  verify_depth = atoi(ctx->config[SSL_VERIFY_DEPTH]);
11206  SSL_CTX_set_verify_depth(ctx->ssl_ctx, verify_depth);
11207  }
11208  }
11209 
11210  if (ctx->config[SSL_CIPHER_LIST] != NULL) {
11211  if (SSL_CTX_set_cipher_list(ctx->ssl_ctx, ctx->config[SSL_CIPHER_LIST])
11212  != 1) {
11213  mg_cry(fc(ctx), "SSL_CTX_set_cipher_list error: %s", ssl_error());
11214  }
11215  }
11216 
11217  return 1;
11218 }
11219 
11220 
11221 static void
11222 uninitialize_ssl(struct mg_context *ctx)
11223 {
11224  int i;
11225  (void)ctx;
11226 
11227  if (mg_atomic_dec(&cryptolib_users) == 0) {
11228 
11229  /* Shutdown according to
11230  * https://wiki.openssl.org/index.php/Library_Initialization#Cleanup
11231  * http://stackoverflow.com/questions/29845527/how-to-properly-uninitialize-openssl
11232  */
11234  CRYPTO_set_id_callback(NULL);
11235  ENGINE_cleanup();
11237  ERR_free_strings();
11238  EVP_cleanup();
11240  ERR_remove_state(0);
11241 
11242  for (i = 0; i < CRYPTO_num_locks(); i++) {
11243  pthread_mutex_destroy(&ssl_mutexes[i]);
11244  }
11245  mg_free(ssl_mutexes);
11246  ssl_mutexes = NULL;
11247  }
11248 }
11249 #endif /* !NO_SSL */
11250 
11251 
11252 static int
11253 set_gpass_option(struct mg_context *ctx)
11254 {
11255  if (ctx) {
11256  struct file file = STRUCT_FILE_INITIALIZER;
11257  const char *path = ctx->config[GLOBAL_PASSWORDS_FILE];
11258  if (path != NULL && !mg_stat(fc(ctx), path, &file)) {
11259  mg_cry(fc(ctx), "Cannot open %s: %s", path, strerror(ERRNO));
11260  return 0;
11261  }
11262  return 1;
11263  }
11264  return 0;
11265 }
11266 
11267 
11268 static int
11269 set_acl_option(struct mg_context *ctx)
11270 {
11271  return check_acl(ctx, (uint32_t)0x7f000001UL) != -1;
11272 }
11273 
11274 
11275 static void
11276 reset_per_request_attributes(struct mg_connection *conn)
11277 {
11278  if (!conn) {
11279  return;
11280  }
11281  conn->path_info = NULL;
11282  conn->num_bytes_sent = conn->consumed_content = 0;
11283  conn->status_code = -1;
11284  conn->is_chunked = 0;
11285  conn->must_close = conn->request_len = conn->throttle = 0;
11286  conn->request_info.content_length = -1;
11287  conn->request_info.remote_user = NULL;
11288  conn->request_info.request_method = NULL;
11289  conn->request_info.request_uri = NULL;
11290  conn->request_info.local_uri = NULL;
11291  conn->request_info.uri = NULL; /* TODO: cleanup uri,
11292  * local_uri and request_uri */
11293  conn->request_info.http_version = NULL;
11294  conn->request_info.num_headers = 0;
11295  conn->data_len = 0;
11296  conn->chunk_remainder = 0;
11297  conn->internal_error = 0;
11298 }
11299 
11300 
11301 static int
11302 set_sock_timeout(SOCKET sock, int milliseconds)
11303 {
11304  int r0 = 0, r1, r2;
11305 
11306 #ifdef _WIN32
11307  /* Windows specific */
11308 
11309  DWORD tv = (DWORD)milliseconds;
11310 
11311 #else
11312  /* Linux, ... (not Windows) */
11313 
11314  struct timeval tv;
11315 
11316 /* TCP_USER_TIMEOUT/RFC5482 (http://tools.ietf.org/html/rfc5482):
11317  * max. time waiting for the acknowledged of TCP data before the connection
11318  * will be forcefully closed and ETIMEDOUT is returned to the application.
11319  * If this option is not set, the default timeout of 20-30 minutes is used.
11320 */
11321 /* #define TCP_USER_TIMEOUT (18) */
11322 
11323 #if defined(TCP_USER_TIMEOUT)
11324  unsigned int uto = (unsigned int)milliseconds;
11325  r0 = setsockopt(sock, 6, TCP_USER_TIMEOUT, (const void *)&uto, sizeof(uto));
11326 #endif
11327 
11328  memset(&tv, 0, sizeof(tv));
11329  tv.tv_sec = milliseconds / 1000;
11330  tv.tv_usec = (milliseconds * 1000) % 1000000;
11331 
11332 #endif /* _WIN32 */
11333 
11334  r1 = setsockopt(
11335  sock, SOL_SOCKET, SO_RCVTIMEO, (SOCK_OPT_TYPE)&tv, sizeof(tv));
11336  r2 = setsockopt(
11337  sock, SOL_SOCKET, SO_SNDTIMEO, (SOCK_OPT_TYPE)&tv, sizeof(tv));
11338 
11339  return r0 || r1 || r2;
11340 }
11341 
11342 
11343 static int
11344 set_tcp_nodelay(SOCKET sock, int nodelay_on)
11345 {
11346  if (setsockopt(sock,
11347  IPPROTO_TCP,
11348  TCP_NODELAY,
11349  (SOCK_OPT_TYPE)&nodelay_on,
11350  sizeof(nodelay_on)) != 0) {
11351  /* Error */
11352  return 1;
11353  }
11354  /* OK */
11355  return 0;
11356 }
11357 
11358 
11359 static void
11360 close_socket_gracefully(struct mg_connection *conn)
11361 {
11362 #if defined(_WIN32)
11363  char buf[MG_BUF_LEN];
11364  int n;
11365 #endif
11366  struct linger linger;
11367 
11368  if (!conn) {
11369  return;
11370  }
11371 
11372  /* Set linger option to avoid socket hanging out after close. This
11373  * prevent
11374  * ephemeral port exhaust problem under high QPS. */
11375  linger.l_onoff = 1;
11376  linger.l_linger = 1;
11377 
11378  if (setsockopt(conn->client.sock,
11379  SOL_SOCKET,
11380  SO_LINGER,
11381  (char *)&linger,
11382  sizeof(linger)) != 0) {
11383  mg_cry(conn,
11384  "%s: setsockopt(SOL_SOCKET SO_LINGER) failed: %s",
11385  __func__,
11386  strerror(ERRNO));
11387  }
11388 
11389  /* Send FIN to the client */
11390  shutdown(conn->client.sock, SHUT_WR);
11391  set_non_blocking_mode(conn->client.sock);
11392 
11393 #if defined(_WIN32)
11394  /* Read and discard pending incoming data. If we do not do that and
11395  * close
11396  * the socket, the data in the send buffer may be discarded. This
11397  * behaviour is seen on Windows, when client keeps sending data
11398  * when server decides to close the connection; then when client
11399  * does recv() it gets no data back. */
11400  do {
11401  n = pull(
11402  NULL, conn, buf, sizeof(buf), 1E-10 /* TODO: allow 0 as timeout */);
11403  } while (n > 0);
11404 #endif
11405 
11406  /* Now we know that our FIN is ACK-ed, safe to close */
11407  closesocket(conn->client.sock);
11408  conn->client.sock = INVALID_SOCKET;
11409 }
11410 
11411 
11412 static void
11413 close_connection(struct mg_connection *conn)
11414 {
11415  if (!conn || !conn->ctx) {
11416  return;
11417  }
11418 
11419 #if defined(USE_LUA) && defined(USE_WEBSOCKET)
11420  if (conn->lua_websocket_state) {
11421  lua_websocket_close(conn, conn->lua_websocket_state);
11422  conn->lua_websocket_state = NULL;
11423  }
11424 #endif
11425 
11426  /* call the connection_close callback if assigned */
11427  if ((conn->ctx->callbacks.connection_close != NULL)
11428  && (conn->ctx->context_type == 1)) {
11429  conn->ctx->callbacks.connection_close(conn);
11430  }
11431 
11432  mg_lock_connection(conn);
11433 
11434  conn->must_close = 1;
11435 
11436 #ifndef NO_SSL
11437  if (conn->ssl != NULL) {
11438  /* Run SSL_shutdown twice to ensure completly close SSL connection
11439  */
11440  SSL_shutdown(conn->ssl);
11441  SSL_free(conn->ssl);
11442  /* maybe not? CRYPTO_cleanup_all_ex_data(); */
11443  /* see
11444  * https://wiki.openssl.org/index.php/Talk:Library_Initialization */
11445  ERR_remove_state(0);
11446  conn->ssl = NULL;
11447  }
11448 #endif
11449  if (conn->client.sock != INVALID_SOCKET) {
11451  conn->client.sock = INVALID_SOCKET;
11452  }
11453 
11454  mg_unlock_connection(conn);
11455 }
11456 
11457 void
11458 mg_close_connection(struct mg_connection *conn)
11459 {
11460  struct mg_context *client_ctx = NULL;
11461  unsigned int i;
11462 
11463  if (conn == NULL) {
11464  return;
11465  }
11466 
11467  if (conn->ctx->context_type == 2) {
11468  client_ctx = conn->ctx;
11469  /* client context: loops must end */
11470  conn->ctx->stop_flag = 1;
11471  }
11472 
11473 #ifndef NO_SSL
11474  if (conn->client_ssl_ctx != NULL) {
11475  SSL_CTX_free((SSL_CTX *)conn->client_ssl_ctx);
11476  }
11477 #endif
11478  close_connection(conn);
11479  if (client_ctx != NULL) {
11480  /* join worker thread and free context */
11481  for (i = 0; i < client_ctx->cfg_worker_threads; i++) {
11482  if (client_ctx->workerthreadids[i] != 0) {
11483  mg_join_thread(client_ctx->workerthreadids[i]);
11484  }
11485  }
11486  mg_free(client_ctx->workerthreadids);
11487  mg_free(client_ctx);
11488  (void)pthread_mutex_destroy(&conn->mutex);
11489  mg_free(conn);
11490  }
11491 }
11492 
11493 
11494 static struct mg_connection *
11495 mg_connect_client_impl(const struct mg_client_options *client_options,
11496  int use_ssl,
11497  char *ebuf,
11498  size_t ebuf_len)
11499 {
11500  static struct mg_context fake_ctx;
11501  struct mg_connection *conn = NULL;
11502  SOCKET sock;
11503  union usa sa;
11504 
11505  if (!connect_socket(&fake_ctx,
11506  client_options->host,
11507  client_options->port,
11508  use_ssl,
11509  ebuf,
11510  ebuf_len,
11511  &sock,
11512  &sa)) {
11513  ;
11514  } else if ((conn = (struct mg_connection *)
11515  mg_calloc(1, sizeof(*conn) + MAX_REQUEST_SIZE)) == NULL) {
11516  mg_snprintf(NULL,
11517  NULL, /* No truncation check for ebuf */
11518  ebuf,
11519  ebuf_len,
11520  "calloc(): %s",
11521  strerror(ERRNO));
11522  closesocket(sock);
11523 #ifndef NO_SSL
11524  } else if (use_ssl
11525  && (conn->client_ssl_ctx = SSL_CTX_new(SSLv23_client_method()))
11526  == NULL) {
11527  mg_snprintf(NULL,
11528  NULL, /* No truncation check for ebuf */
11529  ebuf,
11530  ebuf_len,
11531  "SSL_CTX_new error");
11532  closesocket(sock);
11533  mg_free(conn);
11534  conn = NULL;
11535 #endif /* NO_SSL */
11536 
11537  } else {
11538 
11539 #ifdef USE_IPV6
11540  socklen_t len = (sa.sa.sa_family == AF_INET)
11541  ? sizeof(conn->client.rsa.sin)
11542  : sizeof(conn->client.rsa.sin6);
11543  struct sockaddr *psa =
11544  (sa.sa.sa_family == AF_INET)
11545  ? (struct sockaddr *)&(conn->client.rsa.sin)
11546  : (struct sockaddr *)&(conn->client.rsa.sin6);
11547 #else
11548  socklen_t len = sizeof(conn->client.rsa.sin);
11549  struct sockaddr *psa = (struct sockaddr *)&(conn->client.rsa.sin);
11550 #endif
11551 
11552  conn->buf_size = MAX_REQUEST_SIZE;
11553  conn->buf = (char *)(conn + 1);
11554  conn->ctx = &fake_ctx;
11555  conn->client.sock = sock;
11556  conn->client.lsa = sa;
11557 
11558  if (getsockname(sock, psa, &len) != 0) {
11559  mg_cry(conn,
11560  "%s: getsockname() failed: %s",
11561  __func__,
11562  strerror(ERRNO));
11563  }
11564 
11565  conn->client.is_ssl = use_ssl ? 1 : 0;
11566  (void)pthread_mutex_init(&conn->mutex, &pthread_mutex_attr);
11567 
11568 #ifndef NO_SSL
11569  if (use_ssl) {
11570  fake_ctx.ssl_ctx = conn->client_ssl_ctx;
11571 
11572  /* TODO: Check ssl_verify_peer and ssl_ca_path here.
11573  * SSL_CTX_set_verify call is needed to switch off server
11574  * certificate checking, which is off by default in OpenSSL and
11575  * on in yaSSL. */
11576  /* TODO: SSL_CTX_set_verify(conn->client_ssl_ctx,
11577  * SSL_VERIFY_PEER, verify_ssl_server); */
11578 
11579  if (client_options->client_cert) {
11580  if (!ssl_use_pem_file(&fake_ctx, client_options->client_cert)) {
11581  mg_snprintf(NULL,
11582  NULL, /* No truncation check for ebuf */
11583  ebuf,
11584  ebuf_len,
11585  "Can not use SSL client certificate");
11586  SSL_CTX_free(conn->client_ssl_ctx);
11587  closesocket(sock);
11588  mg_free(conn);
11589  conn = NULL;
11590  }
11591  }
11592 
11593  if (client_options->server_cert) {
11594  SSL_CTX_load_verify_locations(conn->client_ssl_ctx,
11595  client_options->server_cert,
11596  NULL);
11597  SSL_CTX_set_verify(conn->client_ssl_ctx, SSL_VERIFY_PEER, NULL);
11598  } else {
11599  SSL_CTX_set_verify(conn->client_ssl_ctx, SSL_VERIFY_NONE, NULL);
11600  }
11601 
11602  if (!sslize(conn, conn->client_ssl_ctx, SSL_connect)) {
11603  mg_snprintf(NULL,
11604  NULL, /* No truncation check for ebuf */
11605  ebuf,
11606  ebuf_len,
11607  "SSL connection error");
11608  SSL_CTX_free(conn->client_ssl_ctx);
11609  closesocket(sock);
11610  mg_free(conn);
11611  conn = NULL;
11612  }
11613  }
11614 #endif
11615  }
11616 
11617  return conn;
11618 }
11619 
11620 
11621 CIVETWEB_API struct mg_connection *
11622 mg_connect_client_secure(const struct mg_client_options *client_options,
11623  char *error_buffer,
11624  size_t error_buffer_size)
11625 {
11626  return mg_connect_client_impl(client_options,
11627  1,
11628  error_buffer,
11629  error_buffer_size);
11630 }
11631 
11632 
11633 struct mg_connection *
11634 mg_connect_client(const char *host,
11635  int port,
11636  int use_ssl,
11637  char *error_buffer,
11638  size_t error_buffer_size)
11639 {
11640  struct mg_client_options opts;
11641  memset(&opts, 0, sizeof(opts));
11642  opts.host = host;
11643  opts.port = port;
11644  return mg_connect_client_impl(&opts,
11645  use_ssl,
11646  error_buffer,
11647  error_buffer_size);
11648 }
11649 
11650 
11651 static const struct {
11652  const char *proto;
11653  size_t proto_len;
11654  unsigned default_port;
11655 } abs_uri_protocols[] = {{"http://", 7, 80},
11656  {"https://", 8, 443},
11657  {"ws://", 5, 80},
11658  {"wss://", 6, 443},
11659  {NULL, 0, 0}};
11660 
11661 
11662 /* Check if the uri is valid.
11663  * return 0 for invalid uri,
11664  * return 1 for *,
11665  * return 2 for relative uri,
11666  * return 3 for absolute uri without port,
11667  * return 4 for absolute uri with port */
11668 static int
11669 get_uri_type(const char *uri)
11670 {
11671  int i;
11672  char *hostend, *portbegin, *portend;
11673  unsigned long port;
11674 
11675  /* According to the HTTP standard
11676  * http://www.w3.org/Protocols/rfc2616/rfc2616-sec5.html#sec5.1.2
11677  * URI can be an asterisk (*) or should start with slash (relative uri),
11678  * or it should start with the protocol (absolute uri). */
11679  if (uri[0] == '*' && uri[1] == '\0') {
11680  /* asterisk */
11681  return 1;
11682  }
11683  if (uri[0] == '/') {
11684  /* relative uri */
11685  return 2;
11686  }
11687 
11688  /* It could be an absolute uri: */
11689  /* This function only checks if the uri is valid, not if it is
11690  * addressing the current server. So civetweb can also be used
11691  * as a proxy server. */
11692  for (i = 0; abs_uri_protocols[i].proto != NULL; i++) {
11693  if (mg_strncasecmp(uri,
11695  abs_uri_protocols[i].proto_len) == 0) {
11696 
11697  hostend = strchr(uri + abs_uri_protocols[i].proto_len, '/');
11698  if (!hostend) {
11699  return 0;
11700  }
11701  portbegin = strchr(uri + abs_uri_protocols[i].proto_len, ':');
11702  if (!portbegin) {
11703  return 3;
11704  }
11705 
11706  port = strtoul(portbegin + 1, &portend, 10);
11707  if ((portend != hostend) || !port || !is_valid_port(port)) {
11708  return 0;
11709  }
11710 
11711  return 4;
11712  }
11713  }
11714 
11715  return 0;
11716 }
11717 
11718 
11719 /* Return NULL or the relative uri at the current server */
11720 static const char *
11721 get_rel_url_at_current_server(const char *uri, const struct mg_connection *conn)
11722 {
11723  const char *server_domain;
11724  size_t server_domain_len;
11725  size_t request_domain_len = 0;
11726  unsigned long port = 0;
11727  int i;
11728  const char *hostbegin = NULL;
11729  const char *hostend = NULL;
11730  const char *portbegin;
11731  char *portend;
11732 
11733  /* DNS is case insensitive, so use case insensitive string compare here
11734  */
11735  server_domain = conn->ctx->config[AUTHENTICATION_DOMAIN];
11736  if (!server_domain) {
11737  return 0;
11738  }
11739  server_domain_len = strlen(server_domain);
11740  if (!server_domain_len) {
11741  return 0;
11742  }
11743 
11744  for (i = 0; abs_uri_protocols[i].proto != NULL; i++) {
11745  if (mg_strncasecmp(uri,
11747  abs_uri_protocols[i].proto_len) == 0) {
11748 
11749  hostbegin = uri + abs_uri_protocols[i].proto_len;
11750  hostend = strchr(hostbegin, '/');
11751  if (!hostend) {
11752  return 0;
11753  }
11754  portbegin = strchr(hostbegin, ':');
11755  if ((!portbegin) || (portbegin > hostend)) {
11756  port = abs_uri_protocols[i].default_port;
11757  request_domain_len = (size_t)(hostend - hostbegin);
11758  } else {
11759  port = strtoul(portbegin + 1, &portend, 10);
11760  if ((portend != hostend) || !port || !is_valid_port(port)) {
11761  return 0;
11762  }
11763  request_domain_len = (size_t)(portbegin - hostbegin);
11764  }
11765  /* protocol found, port set */
11766  break;
11767  }
11768  }
11769 
11770  if (!port) {
11771  /* port remains 0 if the protocol is not found */
11772  return 0;
11773  }
11774 
11775 #if defined(USE_IPV6)
11776  if (conn->client.lsa.sa.sa_family == AF_INET6) {
11777  if (ntohs(conn->client.lsa.sin6.sin6_port) != port) {
11778  /* Request is directed to a different port */
11779  return 0;
11780  }
11781  } else
11782 #endif
11783  {
11784  if (ntohs(conn->client.lsa.sin.sin_port) != port) {
11785  /* Request is directed to a different port */
11786  return 0;
11787  }
11788  }
11789 
11790  if ((request_domain_len != server_domain_len)
11791  || (0 != memcmp(server_domain, hostbegin, server_domain_len))) {
11792  /* Request is directed to another server */
11793  return 0;
11794  }
11795 
11796  return hostend;
11797 }
11798 
11799 
11800 static int
11801 getreq(struct mg_connection *conn, char *ebuf, size_t ebuf_len, int *err)
11802 {
11803  const char *cl;
11804 
11805  if (ebuf_len > 0) {
11806  ebuf[0] = '\0';
11807  }
11808  *err = 0;
11809 
11811 
11812  if (!conn) {
11813  mg_snprintf(conn,
11814  NULL, /* No truncation check for ebuf */
11815  ebuf,
11816  ebuf_len,
11817  "%s",
11818  "Internal error");
11819  *err = 500;
11820  return 0;
11821  }
11822  /* Set the time the request was received. This value should be used for
11823  * timeouts. */
11824  clock_gettime(CLOCK_MONOTONIC, &(conn->req_time));
11825 
11826  conn->request_len =
11827  read_request(NULL, conn, conn->buf, conn->buf_size, &conn->data_len);
11828  /* assert(conn->request_len < 0 || conn->data_len >= conn->request_len);
11829  */
11830  if (conn->request_len >= 0 && conn->data_len < conn->request_len) {
11831  mg_snprintf(conn,
11832  NULL, /* No truncation check for ebuf */
11833  ebuf,
11834  ebuf_len,
11835  "%s",
11836  "Invalid request size");
11837  *err = 500;
11838  return 0;
11839  }
11840 
11841  if (conn->request_len == 0 && conn->data_len == conn->buf_size) {
11842  mg_snprintf(conn,
11843  NULL, /* No truncation check for ebuf */
11844  ebuf,
11845  ebuf_len,
11846  "%s",
11847  "Request Too Large");
11848  *err = 413;
11849  return 0;
11850  } else if (conn->request_len <= 0) {
11851  if (conn->data_len > 0) {
11852  mg_snprintf(conn,
11853  NULL, /* No truncation check for ebuf */
11854  ebuf,
11855  ebuf_len,
11856  "%s",
11857  "Client sent malformed request");
11858  *err = 400;
11859  } else {
11860  /* Server did not send anything -> just close the connection */
11861  conn->must_close = 1;
11862  mg_snprintf(conn,
11863  NULL, /* No truncation check for ebuf */
11864  ebuf,
11865  ebuf_len,
11866  "%s",
11867  "Client did not send a request");
11868  *err = 0;
11869  }
11870  return 0;
11871  } else if (parse_http_message(conn->buf,
11872  conn->buf_size,
11873  &conn->request_info) <= 0) {
11874  mg_snprintf(conn,
11875  NULL, /* No truncation check for ebuf */
11876  ebuf,
11877  ebuf_len,
11878  "%s",
11879  "Bad Request");
11880  *err = 400;
11881  return 0;
11882  } else {
11883  /* Message is a valid request or response */
11884  if ((cl = get_header(&conn->request_info, "Content-Length")) != NULL) {
11885  /* Request/response has content length set */
11886  char *endptr = NULL;
11887  conn->content_len = strtoll(cl, &endptr, 10);
11888  if (endptr == cl) {
11889  mg_snprintf(conn,
11890  NULL, /* No truncation check for ebuf */
11891  ebuf,
11892  ebuf_len,
11893  "%s",
11894  "Bad Request");
11895  *err = 411;
11896  return 0;
11897  }
11898  /* Publish the content length back to the request info. */
11899  conn->request_info.content_length = conn->content_len;
11900  } else if ((cl = get_header(&conn->request_info, "Transfer-Encoding"))
11901  != NULL
11902  && !mg_strcasecmp(cl, "chunked")) {
11903  conn->is_chunked = 1;
11904  } else if (!mg_strcasecmp(conn->request_info.request_method, "POST")
11905  || !mg_strcasecmp(conn->request_info.request_method,
11906  "PUT")) {
11907  /* POST or PUT request without content length set */
11908  conn->content_len = -1;
11909  } else if (!mg_strncasecmp(conn->request_info.request_method,
11910  "HTTP/",
11911  5)) {
11912  /* Response without content length set */
11913  conn->content_len = -1;
11914  } else {
11915  /* Other request */
11916  conn->content_len = 0;
11917  }
11918  }
11919  return 1;
11920 }
11921 
11922 
11923 int
11924 mg_get_response(struct mg_connection *conn,
11925  char *ebuf,
11926  size_t ebuf_len,
11927  int timeout)
11928 {
11929  if (conn) {
11930  /* Implementation of API function for HTTP clients */
11931  int err, ret;
11932  struct mg_context *octx = conn->ctx;
11933  struct mg_context rctx = *(conn->ctx);
11934  char txt[32]; /* will not overflow */
11935 
11936  if (timeout >= 0) {
11937  mg_snprintf(conn, NULL, txt, sizeof(txt), "%i", timeout);
11938  rctx.config[REQUEST_TIMEOUT] = txt;
11939  set_sock_timeout(conn->client.sock, timeout);
11940  } else {
11941  rctx.config[REQUEST_TIMEOUT] = NULL;
11942  }
11943 
11944  conn->ctx = &rctx;
11945  ret = getreq(conn, ebuf, ebuf_len, &err);
11946  conn->ctx = octx;
11947 
11948  /* TODO: 1) uri is deprecated;
11949  * 2) here, ri.uri is the http response code */
11950  conn->request_info.uri = conn->request_info.request_uri;
11951 
11952  /* TODO (mid): Define proper return values - maybe return length?
11953  * For the first test use <0 for error and >0 for OK */
11954  return (ret == 0) ? -1 : +1;
11955  }
11956  return -1;
11957 }
11958 
11959 
11960 struct mg_connection *
11961 mg_download(const char *host,
11962  int port,
11963  int use_ssl,
11964  char *ebuf,
11965  size_t ebuf_len,
11966  const char *fmt,
11967  ...)
11968 {
11969  struct mg_connection *conn;
11970  va_list ap;
11971  int i;
11972  int reqerr;
11973 
11974  va_start(ap, fmt);
11975  ebuf[0] = '\0';
11976 
11977  /* open a connection */
11978  conn = mg_connect_client(host, port, use_ssl, ebuf, ebuf_len);
11979 
11980  if (conn != NULL) {
11981  i = mg_vprintf(conn, fmt, ap);
11982  if (i <= 0) {
11983  mg_snprintf(conn,
11984  NULL, /* No truncation check for ebuf */
11985  ebuf,
11986  ebuf_len,
11987  "%s",
11988  "Error sending request");
11989  } else {
11990  getreq(conn, ebuf, ebuf_len, &reqerr);
11991 
11992  /* TODO: 1) uri is deprecated;
11993  * 2) here, ri.uri is the http response code */
11994  conn->request_info.uri = conn->request_info.request_uri;
11995  }
11996  }
11997 
11998  /* if an error occured, close the connection */
11999  if (ebuf[0] != '\0' && conn != NULL) {
12000  mg_close_connection(conn);
12001  conn = NULL;
12002  }
12003 
12004  va_end(ap);
12005  return conn;
12006 }
12007 
12008 
12009 struct websocket_client_thread_data {
12010  struct mg_connection *conn;
12011  mg_websocket_data_handler data_handler;
12012  mg_websocket_close_handler close_handler;
12013  void *callback_data;
12014 };
12015 
12016 
12017 #if defined(USE_WEBSOCKET)
12018 #ifdef _WIN32
12019 static unsigned __stdcall websocket_client_thread(void *data)
12020 #else
12021 static void *
12022 websocket_client_thread(void *data)
12023 #endif
12024 {
12025  struct websocket_client_thread_data *cdata =
12026  (struct websocket_client_thread_data *)data;
12027 
12028  mg_set_thread_name("ws-client");
12029 
12030  if (cdata->conn->ctx) {
12031  if (cdata->conn->ctx->callbacks.init_thread) {
12032  /* 3 indicates a websocket client thread */
12033  /* TODO: check if conn->ctx can be set */
12034  cdata->conn->ctx->callbacks.init_thread(cdata->conn->ctx, 3);
12035  }
12036  }
12037 
12038  read_websocket(cdata->conn, cdata->data_handler, cdata->callback_data);
12039 
12040  DEBUG_TRACE("%s", "Websocket client thread exited\n");
12041 
12042  if (cdata->close_handler != NULL) {
12043  cdata->close_handler(cdata->conn, cdata->callback_data);
12044  }
12045 
12046  mg_free((void *)cdata);
12047 
12048 #ifdef _WIN32
12049  return 0;
12050 #else
12051  return NULL;
12052 #endif
12053 }
12054 #endif
12055 
12056 
12057 struct mg_connection *
12059  int port,
12060  int use_ssl,
12061  char *error_buffer,
12062  size_t error_buffer_size,
12063  const char *path,
12064  const char *origin,
12065  mg_websocket_data_handler data_func,
12066  mg_websocket_close_handler close_func,
12067  void *user_data)
12068 {
12069  struct mg_connection *conn = NULL;
12070 
12071 #if defined(USE_WEBSOCKET)
12072  struct mg_context *newctx = NULL;
12073  struct websocket_client_thread_data *thread_data;
12074  static const char *magic = "x3JJHMbDL1EzLkh9GBhXDw==";
12075  static const char *handshake_req;
12076 
12077  if (origin != NULL) {
12078  handshake_req = "GET %s HTTP/1.1\r\n"
12079  "Host: %s\r\n"
12080  "Upgrade: websocket\r\n"
12081  "Connection: Upgrade\r\n"
12082  "Sec-WebSocket-Key: %s\r\n"
12083  "Sec-WebSocket-Version: 13\r\n"
12084  "Origin: %s\r\n"
12085  "\r\n";
12086  } else {
12087  handshake_req = "GET %s HTTP/1.1\r\n"
12088  "Host: %s\r\n"
12089  "Upgrade: websocket\r\n"
12090  "Connection: Upgrade\r\n"
12091  "Sec-WebSocket-Key: %s\r\n"
12092  "Sec-WebSocket-Version: 13\r\n"
12093  "\r\n";
12094  }
12095 
12096  /* Establish the client connection and request upgrade */
12097  conn = mg_download(host,
12098  port,
12099  use_ssl,
12100  error_buffer,
12101  error_buffer_size,
12102  handshake_req,
12103  path,
12104  host,
12105  magic,
12106  origin);
12107 
12108  /* Connection object will be null if something goes wrong */
12109  if (conn == NULL || (strcmp(conn->request_info.request_uri, "101") != 0)) {
12110  if (!*error_buffer) {
12111  /* if there is a connection, but it did not return 101,
12112  * error_buffer is not yet set */
12113  mg_snprintf(conn,
12114  NULL, /* No truncation check for ebuf */
12115  error_buffer,
12116  error_buffer_size,
12117  "Unexpected server reply");
12118  }
12119  DEBUG_TRACE("Websocket client connect error: %s\r\n", error_buffer);
12120  if (conn != NULL) {
12121  mg_free(conn);
12122  conn = NULL;
12123  }
12124  return conn;
12125  }
12126 
12127  /* For client connections, mg_context is fake. Since we need to set a
12128  * callback function, we need to create a copy and modify it. */
12129  newctx = (struct mg_context *)mg_malloc(sizeof(struct mg_context));
12130  memcpy(newctx, conn->ctx, sizeof(struct mg_context));
12131  newctx->user_data = user_data;
12132  newctx->context_type = 2; /* client context type */
12133  newctx->cfg_worker_threads = 1; /* one worker thread will be created */
12134  newctx->workerthreadids =
12135  (pthread_t *)mg_calloc(newctx->cfg_worker_threads, sizeof(pthread_t));
12136  conn->ctx = newctx;
12137  thread_data = (struct websocket_client_thread_data *)
12138  mg_calloc(sizeof(struct websocket_client_thread_data), 1);
12139  thread_data->conn = conn;
12140  thread_data->data_handler = data_func;
12141  thread_data->close_handler = close_func;
12142  thread_data->callback_data = NULL;
12143 
12144  /* Start a thread to read the websocket client connection
12145  * This thread will automatically stop when mg_disconnect is
12146  * called on the client connection */
12147  if (mg_start_thread_with_id(websocket_client_thread,
12148  (void *)thread_data,
12149  newctx->workerthreadids) != 0) {
12150  mg_free((void *)thread_data);
12151  mg_free((void *)newctx->workerthreadids);
12152  mg_free((void *)newctx);
12153  mg_free((void *)conn);
12154  conn = NULL;
12155  DEBUG_TRACE("%s",
12156  "Websocket client connect thread could not be started\r\n");
12157  }
12158 #else
12159  /* Appease "unused parameter" warnings */
12160  (void)host;
12161  (void)port;
12162  (void)use_ssl;
12163  (void)error_buffer;
12164  (void)error_buffer_size;
12165  (void)path;
12166  (void)origin;
12167  (void)user_data;
12168  (void)data_func;
12169  (void)close_func;
12170 #endif
12171 
12172  return conn;
12173 }
12174 
12175 
12176 static void
12177 process_new_connection(struct mg_connection *conn)
12178 {
12179  if (conn && conn->ctx) {
12180  struct mg_request_info *ri = &conn->request_info;
12181  int keep_alive_enabled, keep_alive, discard_len;
12182  char ebuf[100];
12183  const char *hostend;
12184  int reqerr, uri_type;
12185 
12186  keep_alive_enabled =
12187  !strcmp(conn->ctx->config[ENABLE_KEEP_ALIVE], "yes");
12188 
12189  /* Important: on new connection, reset the receiving buffer. Credit
12190  * goes to crule42. */
12191  conn->data_len = 0;
12192  do {
12193  if (!getreq(conn, ebuf, sizeof(ebuf), &reqerr)) {
12194  /* The request sent by the client could not be understood by
12195  * the server, or it was incomplete or a timeout. Send an
12196  * error message and close the connection. */
12197  if (reqerr > 0) {
12198  /*assert(ebuf[0] != '\0');*/
12199  send_http_error(conn, reqerr, "%s", ebuf);
12200  }
12201  } else if (strcmp(ri->http_version, "1.0")
12202  && strcmp(ri->http_version, "1.1")) {
12203  mg_snprintf(conn,
12204  NULL, /* No truncation check for ebuf */
12205  ebuf,
12206  sizeof(ebuf),
12207  "Bad HTTP version: [%s]",
12208  ri->http_version);
12209  send_http_error(conn, 505, "%s", ebuf);
12210  }
12211 
12212  if (ebuf[0] == '\0') {
12213  uri_type = get_uri_type(conn->request_info.request_uri);
12214  switch (uri_type) {
12215  case 1:
12216  /* Asterisk */
12217  conn->request_info.local_uri = NULL;
12218  break;
12219  case 2:
12220  /* relative uri */
12221  conn->request_info.local_uri =
12222  conn->request_info.request_uri;
12223  break;
12224  case 3:
12225  case 4:
12226  /* absolute uri (with/without port) */
12228  conn->request_info.request_uri, conn);
12229  if (hostend) {
12230  conn->request_info.local_uri = hostend;
12231  } else {
12232  conn->request_info.local_uri = NULL;
12233  }
12234  break;
12235  default:
12236  mg_snprintf(conn,
12237  NULL, /* No truncation check for ebuf */
12238  ebuf,
12239  sizeof(ebuf),
12240  "Invalid URI: [%s]",
12241  ri->request_uri);
12242  send_http_error(conn, 400, "%s", ebuf);
12243  break;
12244  }
12245 
12246  /* TODO: cleanup uri, local_uri and request_uri */
12247  conn->request_info.uri = conn->request_info.local_uri;
12248  }
12249 
12250  if (ebuf[0] == '\0') {
12251  if (conn->request_info.local_uri) {
12252  /* handle request to local server */
12253  handle_request(conn);
12254  if (conn->ctx->callbacks.end_request != NULL) {
12255  conn->ctx->callbacks.end_request(conn,
12256  conn->status_code);
12257  }
12258  log_access(conn);
12259  } else {
12260  /* TODO: handle non-local request (PROXY) */
12261  conn->must_close = 1;
12262  }
12263  } else {
12264  conn->must_close = 1;
12265  }
12266 
12267  if (ri->remote_user != NULL) {
12268  mg_free((void *)ri->remote_user);
12269  /* Important! When having connections with and without auth
12270  * would cause double free and then crash */
12271  ri->remote_user = NULL;
12272  }
12273 
12274  /* NOTE(lsm): order is important here. should_keep_alive() call
12275  * is
12276  * using parsed request, which will be invalid after memmove's
12277  * below.
12278  * Therefore, memorize should_keep_alive() result now for later
12279  * use
12280  * in loop exit condition. */
12281  keep_alive = conn->ctx->stop_flag == 0 && keep_alive_enabled
12282  && conn->content_len >= 0 && should_keep_alive(conn);
12283 
12284  /* Discard all buffered data for this request */
12285  discard_len = conn->content_len >= 0 && conn->request_len > 0
12286  && conn->request_len + conn->content_len
12287  < (int64_t)conn->data_len
12288  ? (int)(conn->request_len + conn->content_len)
12289  : conn->data_len;
12290  /*assert(discard_len >= 0);*/
12291  if (discard_len < 0)
12292  break;
12293  conn->data_len -= discard_len;
12294  if (conn->data_len > 0) {
12295  memmove(conn->buf,
12296  conn->buf + discard_len,
12297  (size_t)conn->data_len);
12298  }
12299 
12300  /* assert(conn->data_len >= 0); */
12301  /* assert(conn->data_len <= conn->buf_size); */
12302 
12303  if ((conn->data_len < 0) || (conn->data_len > conn->buf_size)) {
12304  break;
12305  }
12306 
12307  } while (keep_alive);
12308  }
12309 }
12310 
12311 
12312 /* Worker threads take accepted socket from the queue */
12313 static int
12314 consume_socket(struct mg_context *ctx, struct socket *sp)
12315 {
12316 #define QUEUE_SIZE(ctx) ((int)(ARRAY_SIZE(ctx->queue)))
12317  if (!ctx) {
12318  return 0;
12319  }
12320 
12321  (void)pthread_mutex_lock(&ctx->thread_mutex);
12322  DEBUG_TRACE("%s", "going idle");
12323 
12324  /* If the queue is empty, wait. We're idle at this point. */
12325  while (ctx->sq_head == ctx->sq_tail && ctx->stop_flag == 0) {
12326  pthread_cond_wait(&ctx->sq_full, &ctx->thread_mutex);
12327  }
12328 
12329  /* If we're stopping, sq_head may be equal to sq_tail. */
12330  if (ctx->sq_head > ctx->sq_tail) {
12331  /* Copy socket from the queue and increment tail */
12332  *sp = ctx->queue[ctx->sq_tail % QUEUE_SIZE(ctx)];
12333  ctx->sq_tail++;
12334 
12335  DEBUG_TRACE("grabbed socket %d, going busy", sp ? sp->sock : -1);
12336 
12337  /* Wrap pointers if needed */
12338  while (ctx->sq_tail > QUEUE_SIZE(ctx)) {
12339  ctx->sq_tail -= QUEUE_SIZE(ctx);
12340  ctx->sq_head -= QUEUE_SIZE(ctx);
12341  }
12342  }
12343 
12344  (void)pthread_cond_signal(&ctx->sq_empty);
12345  (void)pthread_mutex_unlock(&ctx->thread_mutex);
12346 
12347  return !ctx->stop_flag;
12348 #undef QUEUE_SIZE
12349 }
12350 
12351 
12352 static void *
12353 worker_thread_run(void *thread_func_param)
12354 {
12355  struct mg_context *ctx = (struct mg_context *)thread_func_param;
12356  struct mg_connection *conn;
12357  struct mg_workerTLS tls;
12358 #if defined(MG_LEGACY_INTERFACE)
12359  uint32_t addr;
12360 #endif
12361 
12362  mg_set_thread_name("worker");
12363 
12364  tls.is_master = 0;
12365  tls.thread_idx = (unsigned)mg_atomic_inc(&thread_idx_max);
12366 #if defined(_WIN32) && !defined(__SYMBIAN32__)
12367  tls.pthread_cond_helper_mutex = CreateEvent(NULL, FALSE, FALSE, NULL);
12368 #endif
12369 
12370  if (ctx->callbacks.init_thread) {
12371  /* call init_thread for a worker thread (type 1) */
12372  ctx->callbacks.init_thread(ctx, 1);
12373  }
12374 
12375  conn =
12376  (struct mg_connection *)mg_calloc(1, sizeof(*conn) + MAX_REQUEST_SIZE);
12377  if (conn == NULL) {
12378  mg_cry(fc(ctx), "%s", "Cannot create new connection struct, OOM");
12379  } else {
12380  pthread_setspecific(sTlsKey, &tls);
12381  conn->buf_size = MAX_REQUEST_SIZE;
12382  conn->buf = (char *)(conn + 1);
12383  conn->ctx = ctx;
12384  conn->request_info.user_data = ctx->user_data;
12385  /* Allocate a mutex for this connection to allow communication both
12386  * within the request handler and from elsewhere in the application
12387  */
12388  (void)pthread_mutex_init(&conn->mutex, &pthread_mutex_attr);
12389 
12390  /* Call consume_socket() even when ctx->stop_flag > 0, to let it
12391  * signal sq_empty condvar to wake up the master waiting in
12392  * produce_socket() */
12393  while (consume_socket(ctx, &conn->client)) {
12394  conn->conn_birth_time = time(NULL);
12395 
12396 /* Fill in IP, port info early so even if SSL setup below fails,
12397  * error handler would have the corresponding info.
12398  * Thanks to Johannes Winkelmann for the patch.
12399  */
12400 #if defined(USE_IPV6)
12401  if (conn->client.rsa.sa.sa_family == AF_INET6) {
12402  conn->request_info.remote_port =
12403  ntohs(conn->client.rsa.sin6.sin6_port);
12404  } else
12405 #endif
12406  {
12407  conn->request_info.remote_port =
12408  ntohs(conn->client.rsa.sin.sin_port);
12409  }
12410 
12411  sockaddr_to_string(conn->request_info.remote_addr,
12412  sizeof(conn->request_info.remote_addr),
12413  &conn->client.rsa);
12414 
12415 #if defined(MG_LEGACY_INTERFACE)
12416  /* This legacy interface only works for the IPv4 case */
12417  addr = ntohl(conn->client.rsa.sin.sin_addr.s_addr);
12418  memcpy(&conn->request_info.remote_ip, &addr, 4);
12419 #endif
12420 
12421  conn->request_info.is_ssl = conn->client.is_ssl;
12422 
12423  if (!conn->client.is_ssl
12424 #ifndef NO_SSL
12425  || sslize(conn, conn->ctx->ssl_ctx, SSL_accept)
12426 #endif
12427  ) {
12428 
12429 
12430  process_new_connection(conn);
12431  }
12432 
12433  close_connection(conn);
12434  }
12435  }
12436 
12437  /* Signal master that we're done with connection and exiting */
12438  (void)pthread_mutex_lock(&ctx->thread_mutex);
12439  ctx->running_worker_threads--;
12440  (void)pthread_cond_signal(&ctx->thread_cond);
12441  /* assert(ctx->running_worker_threads >= 0); */
12442  (void)pthread_mutex_unlock(&ctx->thread_mutex);
12443 
12444  pthread_setspecific(sTlsKey, NULL);
12445 #if defined(_WIN32) && !defined(__SYMBIAN32__)
12446  CloseHandle(tls.pthread_cond_helper_mutex);
12447 #endif
12448  pthread_mutex_destroy(&conn->mutex);
12449  mg_free(conn);
12450 
12451  DEBUG_TRACE("%s", "exiting");
12452  return NULL;
12453 }
12454 
12455 
12456 /* Threads have different return types on Windows and Unix. */
12457 #ifdef _WIN32
12458 static unsigned __stdcall worker_thread(void *thread_func_param)
12459 {
12460  worker_thread_run(thread_func_param);
12461  return 0;
12462 }
12463 #else
12464 static void *
12465 worker_thread(void *thread_func_param)
12466 {
12467  worker_thread_run(thread_func_param);
12468  return NULL;
12469 }
12470 #endif /* _WIN32 */
12471 
12472 
12473 /* Master thread adds accepted socket to a queue */
12474 static void
12475 produce_socket(struct mg_context *ctx, const struct socket *sp)
12476 {
12477 #define QUEUE_SIZE(ctx) ((int)(ARRAY_SIZE(ctx->queue)))
12478  if (!ctx) {
12479  return;
12480  }
12481  (void)pthread_mutex_lock(&ctx->thread_mutex);
12482 
12483  /* If the queue is full, wait */
12484  while (ctx->stop_flag == 0
12485  && ctx->sq_head - ctx->sq_tail >= QUEUE_SIZE(ctx)) {
12486  (void)pthread_cond_wait(&ctx->sq_empty, &ctx->thread_mutex);
12487  }
12488 
12489  if (ctx->sq_head - ctx->sq_tail < QUEUE_SIZE(ctx)) {
12490  /* Copy socket to the queue and increment head */
12491  ctx->queue[ctx->sq_head % QUEUE_SIZE(ctx)] = *sp;
12492  ctx->sq_head++;
12493  DEBUG_TRACE("queued socket %d", sp ? sp->sock : -1);
12494  }
12495 
12496  (void)pthread_cond_signal(&ctx->sq_full);
12497  (void)pthread_mutex_unlock(&ctx->thread_mutex);
12498 #undef QUEUE_SIZE
12499 }
12500 
12501 
12502 static void
12503 accept_new_connection(const struct socket *listener, struct mg_context *ctx)
12504 {
12505  struct socket so;
12506  char src_addr[IP_ADDR_STR_LEN];
12507  socklen_t len = sizeof(so.rsa);
12508  int on = 1;
12509  int timeout;
12510 
12511  if (!listener) {
12512  return;
12513  }
12514 
12515  if ((so.sock = accept(listener->sock, &so.rsa.sa, &len))
12516  == INVALID_SOCKET) {
12517  } else if (!check_acl(ctx, ntohl(*(uint32_t *)&so.rsa.sin.sin_addr))) {
12518  sockaddr_to_string(src_addr, sizeof(src_addr), &so.rsa);
12519  mg_cry(fc(ctx), "%s: %s is not allowed to connect", __func__, src_addr);
12520  closesocket(so.sock);
12521  so.sock = INVALID_SOCKET;
12522  } else {
12523  /* Put so socket structure into the queue */
12524  DEBUG_TRACE("Accepted socket %d", (int)so.sock);
12525  set_close_on_exec(so.sock, fc(ctx));
12526  so.is_ssl = listener->is_ssl;
12527  so.ssl_redir = listener->ssl_redir;
12528  if (getsockname(so.sock, &so.lsa.sa, &len) != 0) {
12529  mg_cry(fc(ctx),
12530  "%s: getsockname() failed: %s",
12531  __func__,
12532  strerror(ERRNO));
12533  }
12534 
12535  /* Set TCP keep-alive. This is needed because if HTTP-level
12536  * keep-alive
12537  * is enabled, and client resets the connection, server won't get
12538  * TCP FIN or RST and will keep the connection open forever. With
12539  * TCP keep-alive, next keep-alive handshake will figure out that
12540  * the client is down and will close the server end.
12541  * Thanks to Igor Klopov who suggested the patch. */
12542  if (setsockopt(so.sock,
12543  SOL_SOCKET,
12544  SO_KEEPALIVE,
12545  (SOCK_OPT_TYPE)&on,
12546  sizeof(on)) != 0) {
12547  mg_cry(fc(ctx),
12548  "%s: setsockopt(SOL_SOCKET SO_KEEPALIVE) failed: %s",
12549  __func__,
12550  strerror(ERRNO));
12551  }
12552 
12553 
12554  /* Disable TCP Nagle's algorithm. Normally TCP packets are
12555  * coalesced
12556  * to effectively fill up the underlying IP packet payload and
12557  * reduce
12558  * the overhead of sending lots of small buffers. However this hurts
12559  * the server's throughput (ie. operations per second) when HTTP 1.1
12560  * persistent connections are used and the responses are relatively
12561  * small (eg. less than 1400 bytes).
12562  */
12563  if ((ctx != NULL) && (ctx->config[CONFIG_TCP_NODELAY] != NULL)
12564  && (!strcmp(ctx->config[CONFIG_TCP_NODELAY], "1"))) {
12565  if (set_tcp_nodelay(so.sock, 1) != 0) {
12566  mg_cry(fc(ctx),
12567  "%s: setsockopt(IPPROTO_TCP TCP_NODELAY) failed: %s",
12568  __func__,
12569  strerror(ERRNO));
12570  }
12571  }
12572 
12573  if (ctx && ctx->config[REQUEST_TIMEOUT]) {
12574  timeout = atoi(ctx->config[REQUEST_TIMEOUT]);
12575  } else {
12576  timeout = -1;
12577  }
12578 
12579  /* Set socket timeout to the given value, but not more than a
12580  * a certain limit (SOCKET_TIMEOUT_QUANTUM, default 10 seconds),
12581  * so the server can exit after that time if requested. */
12582  if ((timeout > 0) && (timeout < SOCKET_TIMEOUT_QUANTUM)) {
12583  set_sock_timeout(so.sock, timeout);
12584  } else {
12586  }
12587 
12588  produce_socket(ctx, &so);
12589  }
12590 }
12591 
12592 
12593 static void
12594 master_thread_run(void *thread_func_param)
12595 {
12596  struct mg_context *ctx = (struct mg_context *)thread_func_param;
12597  struct mg_workerTLS tls;
12598  struct pollfd *pfd;
12599  unsigned int i;
12600  unsigned int workerthreadcount;
12601 
12602  if (!ctx) {
12603  return;
12604  }
12605 
12606  mg_set_thread_name("master");
12607 
12608 /* Increase priority of the master thread */
12609 #if defined(_WIN32)
12610  SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL);
12611 #elif defined(USE_MASTER_THREAD_PRIORITY)
12612  int min_prio = sched_get_priority_min(SCHED_RR);
12613  int max_prio = sched_get_priority_max(SCHED_RR);
12614  if ((min_prio >= 0) && (max_prio >= 0)
12615  && ((USE_MASTER_THREAD_PRIORITY) <= max_prio)
12616  && ((USE_MASTER_THREAD_PRIORITY) >= min_prio)) {
12617  struct sched_param sched_param = {0};
12618  sched_param.sched_priority = (USE_MASTER_THREAD_PRIORITY);
12619  pthread_setschedparam(pthread_self(), SCHED_RR, &sched_param);
12620  }
12621 #endif
12622 
12623 /* Initialize thread local storage */
12624 #if defined(_WIN32) && !defined(__SYMBIAN32__)
12625  tls.pthread_cond_helper_mutex = CreateEvent(NULL, FALSE, FALSE, NULL);
12626 #endif
12627  tls.is_master = 1;
12628  pthread_setspecific(sTlsKey, &tls);
12629 
12630  if (ctx->callbacks.init_thread) {
12631  /* Callback for the master thread (type 0) */
12632  ctx->callbacks.init_thread(ctx, 0);
12633  }
12634 
12635  /* Server starts *now* */
12636  ctx->start_time = time(NULL);
12637 
12638  /* Allocate memory for the listening sockets, and start the server */
12639  pfd =
12640  (struct pollfd *)mg_calloc(ctx->num_listening_sockets, sizeof(pfd[0]));
12641  while (pfd != NULL && ctx->stop_flag == 0) {
12642  for (i = 0; i < ctx->num_listening_sockets; i++) {
12643  pfd[i].fd = ctx->listening_sockets[i].sock;
12644  pfd[i].events = POLLIN;
12645  }
12646 
12647  if (poll(pfd, ctx->num_listening_sockets, 200) > 0) {
12648  for (i = 0; i < ctx->num_listening_sockets; i++) {
12649  /* NOTE(lsm): on QNX, poll() returns POLLRDNORM after the
12650  * successful poll, and POLLIN is defined as
12651  * (POLLRDNORM | POLLRDBAND)
12652  * Therefore, we're checking pfd[i].revents & POLLIN, not
12653  * pfd[i].revents == POLLIN. */
12654  if (ctx->stop_flag == 0 && (pfd[i].revents & POLLIN)) {
12655  accept_new_connection(&ctx->listening_sockets[i], ctx);
12656  }
12657  }
12658  }
12659  }
12660  mg_free(pfd);
12661  DEBUG_TRACE("%s", "stopping workers");
12662 
12663  /* Stop signal received: somebody called mg_stop. Quit. */
12665 
12666  /* Wakeup workers that are waiting for connections to handle. */
12667  pthread_cond_broadcast(&ctx->sq_full);
12668 
12669  /* Wait until all threads finish */
12670  (void)pthread_mutex_lock(&ctx->thread_mutex);
12671  while (ctx->running_worker_threads > 0) {
12672  (void)pthread_cond_wait(&ctx->thread_cond, &ctx->thread_mutex);
12673  }
12674  (void)pthread_mutex_unlock(&ctx->thread_mutex);
12675 
12676  /* Join all worker threads to avoid leaking threads. */
12677  workerthreadcount = ctx->cfg_worker_threads;
12678  for (i = 0; i < workerthreadcount; i++) {
12679  if (ctx->workerthreadids[i] != 0) {
12680  mg_join_thread(ctx->workerthreadids[i]);
12681  }
12682  }
12683 
12684 #if !defined(NO_SSL)
12685  if (ctx->ssl_ctx != NULL) {
12686  uninitialize_ssl(ctx);
12687  }
12688 #endif
12689  DEBUG_TRACE("%s", "exiting");
12690 
12691 #if defined(_WIN32) && !defined(__SYMBIAN32__)
12692  CloseHandle(tls.pthread_cond_helper_mutex);
12693 #endif
12694  pthread_setspecific(sTlsKey, NULL);
12695 
12696  /* Signal mg_stop() that we're done.
12697  * WARNING: This must be the very last thing this
12698  * thread does, as ctx becomes invalid after this line. */
12699  ctx->stop_flag = 2;
12700 }
12701 
12702 
12703 /* Threads have different return types on Windows and Unix. */
12704 #ifdef _WIN32
12705 static unsigned __stdcall master_thread(void *thread_func_param)
12706 {
12707  master_thread_run(thread_func_param);
12708  return 0;
12709 }
12710 #else
12711 static void *
12712 master_thread(void *thread_func_param)
12713 {
12714  master_thread_run(thread_func_param);
12715  return NULL;
12716 }
12717 #endif /* _WIN32 */
12718 
12719 
12720 static void
12721 free_context(struct mg_context *ctx)
12722 {
12723  int i;
12724  struct mg_handler_info *tmp_rh;
12725 
12726  if (ctx == NULL) {
12727  return;
12728  }
12729 
12730  if (ctx->callbacks.exit_context) {
12731  ctx->callbacks.exit_context(ctx);
12732  }
12733 
12734  /* All threads exited, no sync is needed. Destroy thread mutex and
12735  * condvars
12736  */
12737  (void)pthread_mutex_destroy(&ctx->thread_mutex);
12738  (void)pthread_cond_destroy(&ctx->thread_cond);
12739  (void)pthread_cond_destroy(&ctx->sq_empty);
12740  (void)pthread_cond_destroy(&ctx->sq_full);
12741 
12742  /* Destroy other context global data structures mutex */
12743  (void)pthread_mutex_destroy(&ctx->nonce_mutex);
12744 
12745 #if defined(USE_TIMERS)
12746  timers_exit(ctx);
12747 #endif
12748 
12749  /* Deallocate config parameters */
12750  for (i = 0; i < NUM_OPTIONS; i++) {
12751  if (ctx->config[i] != NULL) {
12752 #if defined(_MSC_VER)
12753 #pragma warning(suppress : 6001)
12754 #endif
12755  mg_free(ctx->config[i]);
12756  }
12757  }
12758 
12759  /* Deallocate request handlers */
12760  while (ctx->handlers) {
12761  tmp_rh = ctx->handlers;
12762  ctx->handlers = tmp_rh->next;
12763  mg_free(tmp_rh->uri);
12764  mg_free(tmp_rh);
12765  }
12766 
12767 #ifndef NO_SSL
12768  /* Deallocate SSL context */
12769  if (ctx->ssl_ctx != NULL) {
12770  SSL_CTX_free(ctx->ssl_ctx);
12771  }
12772 #endif /* !NO_SSL */
12773 
12774  /* Deallocate worker thread ID array */
12775  if (ctx->workerthreadids != NULL) {
12776  mg_free(ctx->workerthreadids);
12777  }
12778 
12779  /* Deallocate the tls variable */
12780  if (mg_atomic_dec(&sTlsInit) == 0) {
12781 #if defined(_WIN32) && !defined(__SYMBIAN32__)
12782  DeleteCriticalSection(&global_log_file_lock);
12783 #endif /* _WIN32 && !__SYMBIAN32__ */
12784 #if !defined(_WIN32)
12785  pthread_mutexattr_destroy(&pthread_mutex_attr);
12786 #endif
12787 
12788  pthread_key_delete(sTlsKey);
12789  }
12790 
12791  /* deallocate system name string */
12792  mg_free(ctx->systemName);
12793 
12794  /* Deallocate context itself */
12795  mg_free(ctx);
12796 }
12797 
12798 
12799 void
12800 mg_stop(struct mg_context *ctx)
12801 {
12802  pthread_t mt;
12803  if (!ctx) {
12804  return;
12805  }
12806 
12807  /* We don't use a lock here. Calling mg_stop with the same ctx from
12808  * two threads is not allowed. */
12809  mt = ctx->masterthreadid;
12810  if (mt == 0) {
12811  return;
12812  }
12813 
12814  ctx->masterthreadid = 0;
12815  ctx->stop_flag = 1;
12816 
12817  /* Wait until mg_fini() stops */
12818  while (ctx->stop_flag != 2) {
12819  (void)mg_sleep(10);
12820  }
12821 
12822  mg_join_thread(mt);
12823  free_context(ctx);
12824 
12825 #if defined(_WIN32) && !defined(__SYMBIAN32__)
12826  (void)WSACleanup();
12827 #endif /* _WIN32 && !__SYMBIAN32__ */
12828 }
12829 
12830 
12831 static void
12832 get_system_name(char **sysName)
12833 {
12834 #if defined(_WIN32)
12835 #if !defined(__SYMBIAN32__)
12836  char name[128];
12837  DWORD dwVersion = 0;
12838  DWORD dwMajorVersion = 0;
12839  DWORD dwMinorVersion = 0;
12840  DWORD dwBuild = 0;
12841 
12842 #ifdef _MSC_VER
12843 #pragma warning(push)
12844 // GetVersion was declared deprecated
12845 #pragma warning(disable : 4996)
12846 #endif
12847  dwVersion = GetVersion();
12848 #ifdef _MSC_VER
12849 #pragma warning(pop)
12850 #endif
12851 
12852  dwMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion)));
12853  dwMinorVersion = (DWORD)(HIBYTE(LOWORD(dwVersion)));
12854  dwBuild = ((dwVersion < 0x80000000) ? (DWORD)(HIWORD(dwVersion)) : 0);
12855  (void)dwBuild;
12856 
12857  sprintf(name,
12858  "Windows %u.%u",
12859  (unsigned)dwMajorVersion,
12860  (unsigned)dwMinorVersion);
12861  *sysName = mg_strdup(name);
12862 #else
12863  *sysName = mg_strdup("Symbian");
12864 #endif
12865 #else
12866  struct utsname name;
12867  memset(&name, 0, sizeof(name));
12868  uname(&name);
12869  *sysName = mg_strdup(name.sysname);
12870 #endif
12871 }
12872 
12873 
12874 struct mg_context *
12875 mg_start(const struct mg_callbacks *callbacks,
12876  void *user_data,
12877  const char **options)
12878 {
12879  struct mg_context *ctx;
12880  const char *name, *value, *default_value;
12881  int idx, ok, workerthreadcount;
12882  unsigned int i;
12883  void (*exit_callback)(const struct mg_context *ctx) = 0;
12884 
12885  struct mg_workerTLS tls;
12886 
12887 #if defined(_WIN32) && !defined(__SYMBIAN32__)
12888  WSADATA data;
12889  WSAStartup(MAKEWORD(2, 2), &data);
12890 #endif /* _WIN32 && !__SYMBIAN32__ */
12891 
12892  /* Allocate context and initialize reasonable general case defaults. */
12893  if ((ctx = (struct mg_context *)mg_calloc(1, sizeof(*ctx))) == NULL) {
12894  return NULL;
12895  }
12896 
12897  /* Random number generator will initialize at the first call */
12898  ctx->auth_nonce_mask =
12899  (uint64_t)get_random() ^ (uint64_t)(ptrdiff_t)(options);
12900 
12901  if (mg_atomic_inc(&sTlsInit) == 1) {
12902 
12903 #if defined(_WIN32) && !defined(__SYMBIAN32__)
12904  InitializeCriticalSection(&global_log_file_lock);
12905 #endif /* _WIN32 && !__SYMBIAN32__ */
12906 #if !defined(_WIN32)
12907  pthread_mutexattr_init(&pthread_mutex_attr);
12908  pthread_mutexattr_settype(&pthread_mutex_attr, PTHREAD_MUTEX_RECURSIVE);
12909 #endif
12910 
12911  if (0 != pthread_key_create(&sTlsKey, tls_dtor)) {
12912  /* Fatal error - abort start. However, this situation should
12913  * never
12914  * occur in practice. */
12915  mg_atomic_dec(&sTlsInit);
12916  mg_cry(fc(ctx), "Cannot initialize thread local storage");
12917  mg_free(ctx);
12918  return NULL;
12919  }
12920  } else {
12921  /* TODO (low): istead of sleeping, check if sTlsKey is already
12922  * initialized. */
12923  mg_sleep(1);
12924  }
12925 
12926  tls.is_master = -1;
12927  tls.thread_idx = (unsigned)mg_atomic_inc(&thread_idx_max);
12928 #if defined(_WIN32) && !defined(__SYMBIAN32__)
12929  tls.pthread_cond_helper_mutex = NULL;
12930 #endif
12931  pthread_setspecific(sTlsKey, &tls);
12932 
12933 #if defined(USE_LUA)
12934  lua_init_optional_libraries();
12935 #endif
12936 
12937  ok = 0 == pthread_mutex_init(&ctx->thread_mutex, &pthread_mutex_attr);
12938  ok &= 0 == pthread_cond_init(&ctx->thread_cond, NULL);
12939  ok &= 0 == pthread_cond_init(&ctx->sq_empty, NULL);
12940  ok &= 0 == pthread_cond_init(&ctx->sq_full, NULL);
12941  ok &= 0 == pthread_mutex_init(&ctx->nonce_mutex, &pthread_mutex_attr);
12942  if (!ok) {
12943  /* Fatal error - abort start. However, this situation should never
12944  * occur in practice. */
12945  mg_cry(fc(ctx), "Cannot initialize thread synchronization objects");
12946  mg_free(ctx);
12947  pthread_setspecific(sTlsKey, NULL);
12948  return NULL;
12949  }
12950 
12951  if (callbacks) {
12952  ctx->callbacks = *callbacks;
12953  exit_callback = callbacks->exit_context;
12954  ctx->callbacks.exit_context = 0;
12955  }
12956  ctx->user_data = user_data;
12957  ctx->handlers = NULL;
12958 
12959 #if defined(USE_LUA) && defined(USE_WEBSOCKET)
12960  ctx->shared_lua_websockets = 0;
12961 #endif
12962 
12963  while (options && (name = *options++) != NULL) {
12964  if ((idx = get_option_index(name)) == -1) {
12965  mg_cry(fc(ctx), "Invalid option: %s", name);
12966  free_context(ctx);
12967  pthread_setspecific(sTlsKey, NULL);
12968  return NULL;
12969  } else if ((value = *options++) == NULL) {
12970  mg_cry(fc(ctx), "%s: option value cannot be NULL", name);
12971  free_context(ctx);
12972  pthread_setspecific(sTlsKey, NULL);
12973  return NULL;
12974  }
12975  if (ctx->config[idx] != NULL) {
12976  mg_cry(fc(ctx), "warning: %s: duplicate option", name);
12977  mg_free(ctx->config[idx]);
12978  }
12979  ctx->config[idx] = mg_strdup(value);
12980  DEBUG_TRACE("[%s] -> [%s]", name, value);
12981  }
12982 
12983  /* Set default value if needed */
12984  for (i = 0; config_options[i].name != NULL; i++) {
12985  default_value = config_options[i].default_value;
12986  if (ctx->config[i] == NULL && default_value != NULL) {
12987  ctx->config[i] = mg_strdup(default_value);
12988  }
12989  }
12990 
12991 #if defined(NO_FILES)
12992  if (ctx->config[DOCUMENT_ROOT] != NULL) {
12993  mg_cry(fc(ctx), "%s", "Document root must not be set");
12994  free_context(ctx);
12995  pthread_setspecific(sTlsKey, NULL);
12996  return NULL;
12997  }
12998 #endif
12999 
13000  get_system_name(&ctx->systemName);
13001 
13002  /* NOTE(lsm): order is important here. SSL certificates must
13003  * be initialized before listening ports. UID must be set last. */
13004  if (!set_gpass_option(ctx) ||
13005 #if !defined(NO_SSL)
13006  !set_ssl_option(ctx) ||
13007 #endif
13008  !set_ports_option(ctx) ||
13009 #if !defined(_WIN32)
13010  !set_uid_option(ctx) ||
13011 #endif
13012  !set_acl_option(ctx)) {
13013  free_context(ctx);
13014  pthread_setspecific(sTlsKey, NULL);
13015  return NULL;
13016  }
13017 
13018 #if !defined(_WIN32) && !defined(__SYMBIAN32__)
13019  /* Ignore SIGPIPE signal, so if browser cancels the request, it
13020  * won't kill the whole process. */
13021  (void)signal(SIGPIPE, SIG_IGN);
13022 #endif /* !_WIN32 && !__SYMBIAN32__ */
13023 
13024  workerthreadcount = atoi(ctx->config[NUM_THREADS]);
13025 
13026  if (workerthreadcount > MAX_WORKER_THREADS) {
13027  mg_cry(fc(ctx), "Too many worker threads");
13028  free_context(ctx);
13029  pthread_setspecific(sTlsKey, NULL);
13030  return NULL;
13031  }
13032 
13033  if (workerthreadcount > 0) {
13034  ctx->cfg_worker_threads = ((unsigned int)(workerthreadcount));
13035  ctx->workerthreadids =
13036  (pthread_t *)mg_calloc(ctx->cfg_worker_threads, sizeof(pthread_t));
13037  if (ctx->workerthreadids == NULL) {
13038  mg_cry(fc(ctx), "Not enough memory for worker thread ID array");
13039  free_context(ctx);
13040  pthread_setspecific(sTlsKey, NULL);
13041  return NULL;
13042  }
13043  }
13044 
13045 #if defined(USE_TIMERS)
13046  if (timers_init(ctx) != 0) {
13047  mg_cry(fc(ctx), "Error creating timers");
13048  free_context(ctx);
13049  pthread_setspecific(sTlsKey, NULL);
13050  return NULL;
13051  }
13052 #endif
13053 
13054  /* Context has been created - init user libraries */
13055  if (ctx->callbacks.init_context) {
13056  ctx->callbacks.init_context(ctx);
13057  }
13058  ctx->callbacks.exit_context = exit_callback;
13059  ctx->context_type = 1; /* server context */
13060 
13061  /* Start master (listening) thread */
13062  mg_start_thread_with_id(master_thread, ctx, &ctx->masterthreadid);
13063 
13064  /* Start worker threads */
13065  for (i = 0; i < ctx->cfg_worker_threads; i++) {
13066  (void)pthread_mutex_lock(&ctx->thread_mutex);
13067  ctx->running_worker_threads++;
13068  (void)pthread_mutex_unlock(&ctx->thread_mutex);
13070  ctx,
13071  &ctx->workerthreadids[i]) != 0) {
13072  (void)pthread_mutex_lock(&ctx->thread_mutex);
13073  ctx->running_worker_threads--;
13074  (void)pthread_mutex_unlock(&ctx->thread_mutex);
13075  if (i > 0) {
13076  mg_cry(fc(ctx),
13077  "Cannot start worker thread %i: error %ld",
13078  i + 1,
13079  (long)ERRNO);
13080  } else {
13081  mg_cry(fc(ctx),
13082  "Cannot create threads: error %ld",
13083  (long)ERRNO);
13084  free_context(ctx);
13085  pthread_setspecific(sTlsKey, NULL);
13086  return NULL;
13087  }
13088  break;
13089  }
13090  }
13091 
13092  pthread_setspecific(sTlsKey, NULL);
13093  return ctx;
13094 }
13095 
13096 
13097 /* Feature check API function */
13098 unsigned
13099 mg_check_feature(unsigned feature)
13100 {
13101  static const unsigned feature_set = 0
13102 /* Set bits for available features according to API documentation.
13103  * This bit mask is created at compile time, according to the active
13104  * preprocessor defines. It is a single const value at runtime. */
13105 #if !defined(NO_FILES)
13106  | 0x0001u
13107 #endif
13108 #if !defined(NO_SSL)
13109  | 0x0002u
13110 #endif
13111 #if !defined(NO_CGI)
13112  | 0x0004u
13113 #endif
13114 #if defined(USE_IPV6)
13115  | 0x0008u
13116 #endif
13117 #if defined(USE_WEBSOCKET)
13118  | 0x0010u
13119 #endif
13120 #if defined(USE_LUA)
13121  | 0x0020u
13122 #endif
13123 #if defined(USE_DUKTAPE)
13124  | 0x0040u
13125 #endif
13126 #if !defined(NO_CACHING)
13127  | 0x0080u
13128 #endif
13129 
13130 /* Set some extra bits not defined in the API documentation.
13131  * These bits may change without further notice. */
13132 #if defined(MG_LEGACY_INTERFACE)
13133  | 0x8000u
13134 #endif
13135 #if defined(MEMORY_DEBUGGING)
13136  | 0x0100u
13137 #endif
13138 #if defined(USE_TIMERS)
13139  | 0x0200u
13140 #endif
13141 #if !defined(NO_NONCE_CHECK)
13142  | 0x0400u
13143 #endif
13144 #if !defined(NO_POPEN)
13145  | 0x0800u
13146 #endif
13147  ;
13148  return (feature & feature_set);
13149 }
int mg_get_var2(const char *data, size_t data_len, const char *name, char *dst, size_t dst_len, size_t occurrence)
Definition: civetweb.c:4456
#define mg_remove(conn, x)
Definition: civetweb.c:455
#define MAX_CGI_ENVIR_VARS
Definition: civetweb.c:559
static int set_ports_option(struct mg_context *ctx)
Definition: civetweb.c:10312
#define SSL_OP_ALL
Definition: civetweb.c:876
int mg_get_response(struct mg_connection *conn, char *ebuf, size_t ebuf_len, int timeout)
Definition: civetweb.c:11924
const char * remote_user
Definition: civetweb.h:68
static const char * next_option(const char *list, struct vec *val, struct vec *eq_val)
Definition: civetweb.c:2080
static void mg_fclose(struct file *filep)
Definition: civetweb.c:1565
int mg_url_decode(const char *src, int src_len, char *dst, int dst_len, int is_form_url_encoded)
Definition: civetweb.c:4414
static void close_all_listening_sockets(struct mg_context *ctx)
Definition: civetweb.c:10234
struct md5_state_s md5_state_t
size_t mg_get_ports(const struct mg_context *ctx, size_t size, int *ports, int *ssl)
Definition: civetweb.c:1781
#define ERRNO
Definition: civetweb.c:460
#define SSL_CTX_set_ecdh_auto(ctx, onoff)
Definition: civetweb.c:936
int pw_uid
Definition: TWinNTSystem.h:50
const char * local_uri
Definition: civetweb.h:61
static int authorize(struct mg_connection *conn, struct file *filep)
Definition: civetweb.c:5556
static int cryptolib_users
Definition: civetweb.c:10963
#define CRYPTO_set_id_callback
Definition: civetweb.c:942
#define SSL_OP_NO_SSLv3
Definition: civetweb.c:878
#define vsnprintf_impl
Definition: civetweb.c:433
static pid_t spawn_process(struct mg_connection *conn, const char *prog, char *envblk, char *envp[], int fdin[2], int fdout[2], int fderr[2], const char *dir)
Definition: civetweb.c:3612
#define MAX_REQUEST_SIZE
Definition: civetweb.c:563
static constexpr double pi
#define ERR_get_error
Definition: civetweb.c:944
const char * uri
Definition: civetweb.h:64
static char * mg_strndup(const char *ptr, size_t len)
Definition: civetweb.c:1619
#define mg_closedir(x)
Definition: civetweb.c:458
int mg_modify_passwords_file(const char *fname, const char *domain, const char *user, const char *pass)
Definition: civetweb.c:5684
int mg_get_server_ports(const struct mg_context *ctx, int size, struct mg_server_ports *ports)
Definition: civetweb.c:1796
#define SSL_CTX_use_certificate_chain_file
Definition: civetweb.c:908
void mg_set_user_connection_data(struct mg_connection *conn, void *data)
Definition: civetweb.c:1762
int mg_start_thread(mg_thread_func_t func, void *param)
Definition: civetweb.c:3550
static int send_no_cache_header(struct mg_connection *conn)
Definition: civetweb.c:2236
static void gmt_time_string(char *buf, size_t buf_len, time_t *t)
Definition: civetweb.c:1869
#define mg_readdir(x)
Definition: civetweb.c:459
static void do_ssi_include(struct mg_connection *conn, const char *ssi, char *tag, int include_level)
Definition: civetweb.c:8002
const char * mime_type
Definition: civetweb.c:5007
TLine * line
#define INVALID_HANDLE_VALUE
Definition: TMapFile.cxx:84
static int check_acl(struct mg_context *ctx, uint32_t remote_ip)
Definition: civetweb.c:10616
#define PRINTF_ARGS(x, y)
Definition: civetweb.h:590
#define mg_mkdir(conn, path, mode)
Definition: civetweb.c:454
static struct ssl_func crypto_sw[]
Definition: civetweb.c:996
size_t proto_len
Definition: civetweb.c:11653
static int set_uid_option(struct mg_context *ctx)
Definition: civetweb.c:10651
const char * host
Definition: civetweb.h:966
const char * server_cert
Definition: civetweb.h:969
static const struct @129 abs_uri_protocols[]
static int set_acl_option(struct mg_context *ctx)
Definition: civetweb.c:11269
#define ERR_free_strings
Definition: civetweb.c:947
#define SSL_library_init
Definition: civetweb.c:899
#define SSL_VERIFY_FAIL_IF_NO_PEER_CERT
Definition: civetweb.c:874
#define is_websocket_protocol(conn)
Definition: civetweb.c:1355
#define closesocket(a)
Definition: civetweb.c:453
static int isbyte(int n)
Definition: civetweb.c:9191
static int consume_socket(struct mg_context *ctx, struct socket *sp)
Definition: civetweb.c:12314
void mg_unlock_context(struct mg_context *ctx)
Definition: civetweb.c:8408
TH1 * h
Definition: legend2.C:5
int mg_read(struct mg_connection *conn, void *buf, size_t len)
Definition: civetweb.c:4146
#define EVP_cleanup
Definition: civetweb.c:951
static void bin2str(char *to, const unsigned char *p, size_t len)
Definition: civetweb.c:5160
static void print_props(struct mg_connection *conn, const char *uri, struct file *filep)
Definition: civetweb.c:8282
static void produce_socket(struct mg_context *ctx, const struct socket *sp)
Definition: civetweb.c:12475
const char * mg_version(void)
Definition: civetweb.c:1965
static void handle_cgi_request(struct mg_connection *conn, const char *prog)
Definition: civetweb.c:7437
#define SSL_set_fd
Definition: civetweb.c:895
#define va_copy(x, y)
Definition: civetweb.c:489
static void handle_request(struct mg_connection *conn)
Definition: civetweb.c:9773
const struct mg_option * mg_get_valid_options(void)
Definition: civetweb.c:1482
static void mg_vsnprintf(const struct mg_connection *conn, int *truncated, char *buf, size_t buflen, const char *fmt, va_list ap)
Definition: civetweb.c:1658
static int refresh_trust(struct mg_connection *conn)
Definition: civetweb.c:10765
#define DEBUG_TRACE(fmt,...)
Definition: civetweb.c:602
static void reset_per_request_attributes(struct mg_connection *conn)
Definition: civetweb.c:11276
void mg_stop(struct mg_context *ctx)
Definition: civetweb.c:12800
void(* exit_context)(const struct mg_context *ctx)
Definition: civetweb.h:225
static void remove_double_dots_and_double_slashes(char *s)
Definition: civetweb.c:4981
#define SSL_write
Definition: civetweb.c:893
#define ARRAY_SIZE(array)
Definition: civetweb.c:569
static int get_uri_type(const char *uri)
Definition: civetweb.c:11669
void mg_cry(const struct mg_connection *conn, const char *fmt,...)
Definition: civetweb.c:1894
static int get_option_index(const char *name)
Definition: civetweb.c:1720
static const char * get_header(const struct mg_request_info *ri, const char *name)
Definition: civetweb.c:2047
#define MAX_WORKER_THREADS
Definition: civetweb.c:205
int mg_get_cookie(const char *cookie_header, const char *var_name, char *dst, size_t dst_size)
Definition: civetweb.c:4513
struct mg_request_info::mg_header http_headers[64]
static void * master_thread(void *thread_func_param)
Definition: civetweb.c:12712
static int parse_range_header(const char *header, int64_t *a, int64_t *b)
Definition: civetweb.c:6484
#define CGI_ENVIRONMENT_SIZE
Definition: civetweb.c:558
#define ERR_remove_state
Definition: civetweb.c:946
static const struct @128 builtin_mime_types[]
static void handle_static_file_request(struct mg_connection *conn, const char *path, struct file *filep, const char *mime_type)
Definition: civetweb.c:6524
void mg_unlock_connection(struct mg_connection *conn)
Definition: civetweb.c:8392
static pthread_mutex_t * ssl_mutexes
Definition: civetweb.c:10827
static void remove_bad_file(const struct mg_connection *conn, const char *path)
Definition: civetweb.c:6753
static int ssl_use_pem_file(struct mg_context *ctx, const char *pem)
Definition: civetweb.c:11014
static void prepare_cgi_environment(struct mg_connection *conn, const char *prog, struct cgi_environment *env)
Definition: civetweb.c:7273
static double mg_difftimespec(const struct timespec *ts_now, const struct timespec *ts_before)
Definition: civetweb.c:1885
static int match_prefix(const char *pattern, size_t pattern_len, const char *str)
Definition: civetweb.c:2153
static void * load_dll(struct mg_context *ctx, const char *dll_name, struct ssl_func *sw)
Definition: civetweb.c:10913
int(* mg_authorization_handler)(struct mg_connection *conn, void *cbdata)
Definition: civetweb.h:371
static void close_connection(struct mg_connection *conn)
Definition: civetweb.c:11413
#define CIVETWEB_VERSION
Definition: civetweb.h:26
#define malloc
Definition: civetweb.c:818
#define CRYPTO_num_locks
Definition: civetweb.c:939
#define UINT64_FMT
Definition: civetweb.c:463
static void close_socket_gracefully(struct mg_connection *conn)
Definition: civetweb.c:11360
static int pull_all(FILE *fp, struct mg_connection *conn, char *buf, int len)
Definition: civetweb.c:4002
static int check_authorization(struct mg_connection *conn, const char *path)
Definition: civetweb.c:5579
#define ENGINE_cleanup
Definition: civetweb.c:948
const char * default_value
Definition: civetweb.h:427
int SOCKET
Definition: civetweb.c:464
const char * mg_get_option(const struct mg_context *ctx, const char *name)
Definition: civetweb.c:1734
unsigned default_port
Definition: civetweb.c:11654
void mg_send_mime_file(struct mg_connection *conn, const char *path, const char *mime_type)
Definition: civetweb.c:6681
static int header_has_option(const char *header, const char *option)
Definition: civetweb.c:2135
static int should_decode_url(const struct mg_connection *conn)
Definition: civetweb.c:2218
#define SSL_OP_SINGLE_DH_USE
Definition: civetweb.c:882
#define SSL_CTX_free
Definition: civetweb.c:906
#define PRINTF_FORMAT_STRING(s)
Definition: civetweb.h:584
static void parse_http_headers(char **buf, struct mg_request_info *ri)
Definition: civetweb.c:6815
#define ERR_error_string
Definition: civetweb.c:945
static struct mg_connection * fc(struct mg_context *ctx)
Definition: civetweb.c:1956
static int read_request(FILE *fp, struct mg_connection *conn, char *buf, int bufsiz, int *nread)
Definition: civetweb.c:6957
static int mg_start_thread_with_id(mg_thread_func_t func, void *param, pthread_t *threadidptr)
Definition: civetweb.c:3574
static void dir_scan_callback(struct de *de, void *data)
Definition: civetweb.c:6273
unsigned char md5_byte_t
Definition: md5.inl:50
#define SSL_VERIFY_PEER
Definition: civetweb.c:873
const char * request_method
Definition: civetweb.h:58
static const char * mg_strcasestr(const char *big_str, const char *small_str)
Definition: civetweb.c:1639
#define WINCDECL
Definition: civetweb.c:465
static struct ssl_func ssl_sw[]
Definition: civetweb.c:958
static int mg_atomic_dec(volatile int *addr)
Definition: civetweb.c:1379
#define SSL_OP_NO_TLSv1_1
Definition: civetweb.c:881
#define SSL_CTX_clear_options(ctx, op)
Definition: civetweb.c:934
#define HEXTOI(x)
struct mg_connection * mg_connect_websocket_client(const char *host, int port, int use_ssl, char *error_buffer, size_t error_buffer_size, const char *path, const char *origin, mg_websocket_data_handler data_func, mg_websocket_close_handler close_func, void *user_data)
Definition: civetweb.c:12058
void mg_set_auth_handler(struct mg_context *ctx, const char *uri, mg_request_handler handler, void *cbdata)
Definition: civetweb.c:9612
#define mg_static_assert(cond, txt)
Definition: civetweb.c:89
static void handle_propfind(struct mg_connection *conn, const char *path, struct file *filep)
Definition: civetweb.c:8338
static int is_authorized_for_put(struct mg_connection *conn)
Definition: civetweb.c:5664
static void * cryptolib_dll_handle
Definition: civetweb.c:10955
static int getreq(struct mg_connection *conn, char *ebuf, size_t ebuf_len, int *err)
Definition: civetweb.c:11801
static int thread_idx_max
Definition: civetweb.c:1333
void mg_set_request_handler(struct mg_context *ctx, const char *uri, mg_request_handler handler, void *cbdata)
Definition: civetweb.c:9566
#define SSL_CTX_set_session_id_context
Definition: civetweb.c:927
static char * skip_quoted(char **buf, const char *delimiters, const char *whitespace, char quotechar)
Definition: civetweb.c:1986
static double p2(double t, double a, double b, double c)
static void send_authorization_request(struct mg_connection *conn)
Definition: civetweb.c:5627
static int is_valid_port(unsigned long port)
Definition: civetweb.c:5795
static int is_not_modified(const struct mg_connection *conn, const struct file *filep)
Definition: civetweb.c:7065
static int parse_net(const char *spec, uint32_t *net, uint32_t *mask)
Definition: civetweb.c:9198
#define SSL_CTX_use_PrivateKey_file
Definition: civetweb.c:900
static int alloc_vprintf2(char **buf, const char *fmt, va_list ap)
Definition: civetweb.c:4294
struct mg_connection * mg_connect_client(const char *host, int port, int use_ssl, char *error_buffer, size_t error_buffer_size)
Definition: civetweb.c:11634
static void master_thread_run(void *thread_func_param)
Definition: civetweb.c:12594
static const char * mg_fgets(char *buf, size_t size, struct file *filep, char **p)
Definition: civetweb.c:5416
static constexpr double L
static int set_tcp_nodelay(SOCKET sock, int nodelay_on)
Definition: civetweb.c:11344
#define SSL_get_error
Definition: civetweb.c:894
static void * ssllib_dll_handle
Definition: civetweb.c:10954
static void send_http_error(struct mg_connection *, int, PRINTF_FORMAT_STRING(const char *fmt),...)
Definition: civetweb.c:2479
static const char * suggest_connection_header(const struct mg_connection *conn)
Definition: civetweb.c:2229
static int get_request_len(const char *buf, int buflen)
Definition: civetweb.c:4881
static void mg_set_thread_name(const char *name)
Definition: civetweb.c:1416
#define SSL_shutdown
Definition: civetweb.c:916
static struct mg_option config_options[]
Definition: civetweb.c:1136
long long mg_store_body(struct mg_connection *conn, const char *path)
Definition: civetweb.c:6763
static int mg_fgetc(struct file *filep, int offset)
Definition: civetweb.c:8109
void mg_send_file(struct mg_connection *conn, const char *path)
Definition: civetweb.c:6674
static int set_non_blocking_mode(SOCKET sock)
Definition: civetweb.c:3705
#define SSLv23_client_method
Definition: civetweb.c:910
#define realloc
Definition: civetweb.c:820
#define SSL_CTX_set_verify_depth
Definition: civetweb.c:920
static struct mg_connection * mg_connect_client_impl(const struct mg_client_options *client_options, int use_ssl, char *ebuf, size_t ebuf_len)
Definition: civetweb.c:11495
static __inline void * mg_calloc(size_t a, size_t b)
Definition: civetweb.c:764
#define SSL_OP_NO_SSLv2
Definition: civetweb.c:877
#define SOMAXCONN
Definition: civetweb.c:844
static void print_dav_dir_entry(struct de *de, void *data)
Definition: civetweb.c:8312
static int get_first_ssl_listener_index(const struct mg_context *ctx)
Definition: civetweb.c:9362
int(* mg_websocket_data_handler)(struct mg_connection *, int, char *, size_t, void *)
Definition: civetweb.h:337
static constexpr double second
#define SSL_CTX_use_certificate_file
Definition: civetweb.c:902
static void get_system_name(char **sysName)
Definition: civetweb.c:12832
static void handle_file_based_request(struct mg_connection *conn, const char *path, struct file *filep)
Definition: civetweb.c:10177
static int mg_join_thread(pthread_t threadid)
Definition: civetweb.c:3601
static int scan_directory(struct mg_connection *conn, const char *dir, void *data, void(*cb)(struct de *, void *))
Definition: civetweb.c:6126
int mg_printf(struct mg_connection *conn, const char *fmt,...)
Definition: civetweb.c:4400
static pthread_mutexattr_t pthread_mutex_attr
Definition: civetweb.c:553
char * mg_md5(char buf[33],...)
Definition: civetweb.c:5174
static int set_ssl_option(struct mg_context *ctx)
Definition: civetweb.c:11073
#define SSL_CTX_check_private_key
Definition: civetweb.c:926
void(* mg_websocket_close_handler)(const struct mg_connection *, void *)
Definition: civetweb.h:342
static time_t parse_date_string(const char *datetime)
Definition: civetweb.c:4923
static int is_file_opened(const struct file *filep)
Definition: civetweb.c:1512
struct ssl_st SSL
Definition: civetweb.c:863
static const char * ssl_error(void)
Definition: civetweb.c:10888
static void mkcol(struct mg_connection *conn, const char *path)
Definition: civetweb.c:7725
static int mg_inet_pton(int af, const char *src, void *dst, size_t dstlen)
Definition: civetweb.c:5802
static const char * get_rel_url_at_current_server(const char *uri, const struct mg_connection *conn)
Definition: civetweb.c:11721
static int WINCDECL compare_dir_entries(const void *p1, const void *p2)
Definition: civetweb.c:6076
static int sTlsInit
Definition: civetweb.c:1332
static void uninitialize_ssl(struct mg_context *ctx)
Definition: civetweb.c:11222
const void * SOCK_OPT_TYPE
Definition: civetweb.c:423
static void * worker_thread_run(void *thread_func_param)
Definition: civetweb.c:12353
size_t ext_len
Definition: civetweb.c:5006
static int mg_vprintf(struct mg_connection *conn, const char *fmt, va_list ap)
Definition: civetweb.c:4382
ROOT::R::TRInterface & r
Definition: Object.C:4
static int substitute_index_file(struct mg_connection *conn, char *path, size_t path_len, struct file *filep)
Definition: civetweb.c:7010
struct ssl_method_st SSL_METHOD
Definition: civetweb.c:864
static void addenv(struct cgi_environment *env, PRINTF_FORMAT_STRING(const char *fmt),...) PRINTF_ARGS(2
SVector< double, 2 > v
Definition: Dict.h:5
static int64_t push_all(struct mg_context *ctx, FILE *fp, SOCKET sock, SSL *ssl, const char *buf, int64_t len)
Definition: civetweb.c:3857
static int check_password(const char *method, const char *ha1, const char *uri, const char *nonce, const char *nc, const char *cnonce, const char *qop, const char *response)
Definition: civetweb.c:5197
auto * a
Definition: textangle.C:12
static int initialize_ssl(struct mg_context *ctx)
Definition: civetweb.c:10968
#define INT64_FMT
Definition: civetweb.c:462
int mg_url_encode(const char *src, char *dst, size_t dst_len)
Definition: civetweb.c:5973
static int push(struct mg_context *ctx, FILE *fp, SOCKET sock, SSL *ssl, const char *buf, int len, double timeout)
Definition: civetweb.c:3754
static int mg_read_inner(struct mg_connection *conn, void *buf, size_t len)
Definition: civetweb.c:4072
#define SSL_new
Definition: civetweb.c:896
#define SSL_CTX_set_default_verify_paths
Definition: civetweb.c:919
#define calloc
Definition: civetweb.c:819
static int is_put_or_delete_method(const struct mg_connection *conn)
Definition: civetweb.c:4657
static __inline void mg_free(void *a)
Definition: civetweb.c:776
unsigned mg_check_feature(unsigned feature)
Definition: civetweb.c:13099
static void ssl_locking_callback(int mode, int mutex_num, const char *file, int line)
Definition: civetweb.c:10897
static double p1(double t, double a, double b)
static int put_dir(struct mg_connection *conn, const char *path)
Definition: civetweb.c:6716
static int must_hide_file(struct mg_connection *conn, const char *path)
Definition: civetweb.c:6112
static char mg_getc(struct mg_connection *conn)
Definition: civetweb.c:4131
static int mg_stat(struct mg_connection *conn, const char *path, struct file *filep)
Definition: civetweb.c:3512
const char * http_version
Definition: civetweb.h:65
void mg_lock_connection(struct mg_connection *conn)
Definition: civetweb.c:8384
static __inline void * mg_realloc(void *a, size_t b)
Definition: civetweb.c:770
static void put_file(struct mg_connection *conn, const char *path)
Definition: civetweb.c:7794
const char * mg_get_response_code_text(struct mg_connection *conn, int response_code)
Definition: civetweb.c:2286
static int mg_fopen(const struct mg_connection *conn, const char *path, const char *mode, struct file *filep)
Definition: civetweb.c:1528
CIVETWEB_API struct mg_connection * mg_connect_client_secure(const struct mg_client_options *client_options, char *error_buffer, size_t error_buffer_size)
Definition: civetweb.c:11622
#define SSL_CTX_new
Definition: civetweb.c:897
struct mg_context * mg_start(const struct mg_callbacks *callbacks, void *user_data, const char **options)
Definition: civetweb.c:12875
int mg_write(struct mg_connection *conn, const void *buf, size_t len)
Definition: civetweb.c:4235
static const char * header_val(const struct mg_connection *conn, const char *header)
Definition: civetweb.c:10524
static int remove_directory(struct mg_connection *conn, const char *dir)
Definition: civetweb.c:6182
const char * name
Definition: civetweb.h:425
constexpr Double_t E()
Definition: TMath.h:74
static void send_ssi_file(struct mg_connection *, const char *, struct file *, int)
Definition: civetweb.c:8126
static int should_keep_alive(const struct mg_connection *conn)
Definition: civetweb.c:2199
void mg_close_connection(struct mg_connection *conn)
Definition: civetweb.c:11458
static void handle_directory_request(struct mg_connection *conn, const char *dir)
Definition: civetweb.c:6296
int(* mg_request_handler)(struct mg_connection *conn, void *cbdata)
Definition: civetweb.h:279
const char * extension
Definition: civetweb.c:5005
int mg_strcasecmp(const char *s1, const char *s2)
Definition: civetweb.c:1606
static void tls_dtor(void *key)
Definition: civetweb.c:10693
static int lowercase(const char *s)
Definition: civetweb.c:1584
struct mg_connection * mg_download(const char *host, int port, int use_ssl, char *ebuf, size_t ebuf_len, const char *fmt,...)
Definition: civetweb.c:11961
#define SSL_OP_NO_TLSv1
Definition: civetweb.c:879
static void mg_snprintf(const struct mg_connection *conn, int *truncated, char *buf, size_t buflen, PRINTF_FORMAT_STRING(const char *fmt),...) PRINTF_ARGS(5
static unsigned int total
#define QUEUE_SIZE(ctx)
static void get_mime_type(struct mg_context *ctx, const char *path, struct vec *vec)
Definition: civetweb.c:5128
static int set_throttle(const char *spec, uint32_t remote_ip, const char *uri)
Definition: civetweb.c:9217
const char * mg_get_header(const struct mg_connection *conn, const char *name)
Definition: civetweb.c:2063
MD5_STATIC void md5_finish(md5_state_t *pms, md5_byte_t digest[16])
Definition: md5.inl:449
struct x509_store_ctx_st X509_STORE_CTX
Definition: civetweb.c:866
CIVETWEB_API int mg_websocket_write(struct mg_connection *conn, int opcode, const char *data, size_t data_len)
static int send_static_cache_header(struct mg_connection *conn)
Definition: civetweb.c:2248
#define INVALID_SOCKET
Definition: civetweb.c:461
void * mg_get_user_data(const struct mg_context *ctx)
Definition: civetweb.c:1755
#define CRYPTO_LIB
Definition: civetweb.c:447
static void discard_unread_request_data(struct mg_connection *conn)
Definition: civetweb.c:4032
char static_assert_replacement[1]
Definition: civetweb.c:88
#define CRYPTO_cleanup_all_ex_data
Definition: civetweb.c:950
static int mg_atomic_inc(volatile int *addr)
Definition: civetweb.c:1360
#define CRYPTO_set_locking_callback
Definition: civetweb.c:940
#define TRUE
static uint32_t get_remote_ip(const struct mg_connection *conn)
Definition: civetweb.c:9250
#define free
Definition: civetweb.c:821
static void fclose_on_exec(struct file *filep, struct mg_connection *conn)
Definition: civetweb.c:6506
static constexpr double s
you should not use this method at all Int_t Int_t Double_t Double_t Double_t e
Definition: TRolke.cxx:630
int(* mg_websocket_connect_handler)(const struct mg_connection *, void *)
Definition: civetweb.h:334
#define SSL_load_error_strings
Definition: civetweb.c:907
static void process_new_connection(struct mg_connection *conn)
Definition: civetweb.c:12177
TCanvas * slash()
Definition: slash.C:1
#define PASSWORDS_FILE_NAME
Definition: civetweb.c:557
#define IP_ADDR_STR_LEN
Definition: civetweb.c:837
static void * worker_thread(void *thread_func_param)
Definition: civetweb.c:12465
static void interpret_uri(struct mg_connection *conn, char *filename, size_t filename_buf_len, struct file *filep, int *is_found, int *is_script_resource, int *is_websocket_request, int *is_put_or_delete_request)
Definition: civetweb.c:4669
R__EXTERN C unsigned int sleep(unsigned int seconds)
#define mg_opendir(conn, x)
Definition: civetweb.c:457
static int alloc_vprintf(char **out_buf, char *prealloc_buf, size_t prealloc_size, const char *fmt, va_list ap)
Definition: civetweb.c:4326
static void construct_etag(char *buf, size_t buf_len, const struct file *filep)
Definition: civetweb.c:6491
int pw_gid
Definition: TWinNTSystem.h:51
#define SSL_CTX_set_verify
Definition: civetweb.c:912
#define SSL_free
Definition: civetweb.c:889
const struct mg_request_info * mg_get_request_info(const struct mg_connection *conn)
Definition: civetweb.c:1972
static int is_valid_http_method(const char *method)
Definition: civetweb.c:6875
static int connect_socket(struct mg_context *ctx, const char *host, int port, int use_ssl, char *ebuf, size_t ebuf_len, SOCKET *sock, union usa *sa)
Definition: civetweb.c:5839
static void delete_file(struct mg_connection *conn, const char *path)
Definition: civetweb.c:7935
typedef void((*Func_t)())
#define FALSE
#define SSL_CTX_set_cipher_list
Definition: civetweb.c:930
#define SSL_CTX_set_options(ctx, op)
Definition: civetweb.c:932
#define SSLv23_server_method
Definition: civetweb.c:898
static void mg_set_handler_type(struct mg_context *ctx, const char *uri, int handler_type, int is_delete_request, mg_request_handler handler, mg_websocket_connect_handler connect_handler, mg_websocket_ready_handler ready_handler, mg_websocket_data_handler data_handler, mg_websocket_close_handler close_handler, mg_authorization_handler auth_handler, void *cbdata)
Definition: civetweb.c:9418
#define STRUCT_FILE_INITIALIZER
Definition: civetweb.c:1053
void(* mg_websocket_ready_handler)(struct mg_connection *, void *)
Definition: civetweb.h:336
static void set_close_on_exec(SOCKET fd, struct mg_connection *conn)
Definition: civetweb.c:3536
static void do_ssi_exec(struct mg_connection *conn, char *tag)
Definition: civetweb.c:8088
auto * l
Definition: textangle.C:4
static int read_auth_file(struct file *filep, struct read_auth_file_struct *workdata)
Definition: civetweb.c:5459
Definition: file.py:1
#define SSL_LIB
Definition: civetweb.c:444
#define SSL_connect
Definition: civetweb.c:891
#define IGNORE_UNUSED_RESULT(a)
Definition: civetweb.c:119
static void mg_strlcpy(register char *dst, register const char *src, size_t n)
Definition: civetweb.c:1574
static int parse_http_message(char *buf, int len, struct mg_request_info *ri)
Definition: civetweb.c:6907
static int sslize(struct mg_connection *conn, SSL_CTX *s, int(*func)(SSL *))
Definition: civetweb.c:10831
static void send_file_data(struct mg_connection *conn, struct file *filep, int64_t offset, int64_t len)
Definition: civetweb.c:6379
static void print_dir_entry(struct de *de)
Definition: civetweb.c:6000
static __inline void * mg_malloc(size_t a)
Definition: civetweb.c:758
const char * mg_get_builtin_mime_type(const char *path)
Definition: civetweb.c:5106
static int set_sock_timeout(SOCKET sock, int milliseconds)
Definition: civetweb.c:11302
you should not use this method at all Int_t Int_t Double_t Double_t Double_t Int_t Double_t Double_t Double_t Double_t b
Definition: TRolke.cxx:630
struct ssl_ctx_st SSL_CTX
Definition: civetweb.c:865
void * mg_get_user_connection_data(const struct mg_connection *conn)
Definition: civetweb.c:1771
static uint64_t get_random(void)
Definition: civetweb.c:3720
static void send_options(struct mg_connection *conn)
Definition: civetweb.c:8254
static void open_auth_file(struct mg_connection *conn, const char *path, struct file *filep)
Definition: civetweb.c:5242
static int get_request_handler(struct mg_connection *conn, int handler_type, mg_request_handler *handler, mg_websocket_connect_handler *connect_handler, mg_websocket_ready_handler *ready_handler, mg_websocket_data_handler *data_handler, mg_websocket_close_handler *close_handler, mg_authorization_handler *auth_handler, void **cbdata)
Definition: civetweb.c:9632
const char * proto
Definition: civetweb.c:11652
void mg_lock_context(struct mg_context *ctx)
Definition: civetweb.c:8400
void *(* mg_thread_func_t)(void *)
Definition: civetweb.h:852
#define SOCKET_TIMEOUT_QUANTUM
Definition: civetweb.c:208
#define SSL_CTX_load_verify_locations
Definition: civetweb.c:917
CIVETWEB_API int mg_handle_form_request(struct mg_connection *conn, struct mg_form_data_handler *fdh)
static pthread_key_t sTlsKey
Definition: civetweb.c:1331
static int set_gpass_option(struct mg_context *ctx)
Definition: civetweb.c:11253
static const char * month_names[]
Definition: civetweb.c:1013
static void redirect_to_https_port(struct mg_connection *conn, int ssl_index)
Definition: civetweb.c:9376
#define MG_BUF_LEN
Definition: civetweb.c:560
#define MSG_NOSIGNAL
Definition: civetweb.c:840
#define SSL_accept
Definition: civetweb.c:890
CIVETWEB_API int mg_websocket_client_write(struct mg_connection *conn, int opcode, const char *data, size_t data_len)
static unsigned long ssl_id_callback(void)
Definition: civetweb.c:10712
static char * mg_strdup(const char *str)
Definition: civetweb.c:1632
MD5_STATIC void md5_init(md5_state_t *pms)
Definition: md5.inl:401
#define SSL_VERIFY_NONE
Definition: civetweb.c:872
static void accept_new_connection(const struct socket *listener, struct mg_context *ctx)
Definition: civetweb.c:12503
static void sockaddr_to_string(char *buf, size_t len, const union usa *usa)
Definition: civetweb.c:1835
#define CONF_modules_unload
Definition: civetweb.c:949
const char * client_cert
Definition: civetweb.h:968
static void free_context(struct mg_context *ctx)
Definition: civetweb.c:12721
int mg_get_var(const char *data, size_t data_len, const char *name, char *dst, size_t dst_len)
Definition: civetweb.c:4445
void mg_set_websocket_handler(struct mg_context *ctx, const char *uri, mg_websocket_connect_handler connect_handler, mg_websocket_ready_handler ready_handler, mg_websocket_data_handler data_handler, mg_websocket_close_handler close_handler, void *cbdata)
Definition: civetweb.c:9586
static int parse_auth_header(struct mg_connection *conn, char *buf, size_t buf_size, struct ah *ah)
Definition: civetweb.c:5308
static char * skip(char **buf, const char *delimiters)
Definition: civetweb.c:2039
const Int_t n
Definition: legend1.C:16
static int parse_port_string(const struct vec *vec, struct socket *so)
Definition: civetweb.c:10258
static int get_month_index(const char *s)
Definition: civetweb.c:4907
char name[80]
Definition: TGX11.cxx:109
static int forward_body_data(struct mg_connection *conn, FILE *fp, SOCKET sock, SSL *ssl)
Definition: civetweb.c:7082
struct mg_context * mg_get_context(const struct mg_connection *conn)
Definition: civetweb.c:1748
const char * cnt
Definition: TXMLSetup.cxx:74
static int is_file_in_memory(const struct mg_connection *conn, const char *path, struct file *filep)
Definition: civetweb.c:1489
MD5_STATIC void md5_append(md5_state_t *pms, const md5_byte_t *data, size_t nbytes)
Definition: md5.inl:411
static void log_access(const struct mg_connection *conn)
Definition: civetweb.c:10537
#define mg_sleep(x)
Definition: civetweb.c:456
static void handle_ssi_file_request(struct mg_connection *conn, const char *path, struct file *filep)
Definition: civetweb.c:8201
const char * request_uri
Definition: civetweb.h:59
int mg_strncasecmp(const char *s1, const char *s2, size_t len)
Definition: civetweb.c:1591
#define CIVETWEB_API
Definition: civetweb.h:40
static int pull(FILE *fp, struct mg_connection *conn, char *buf, int len, double timeout)
Definition: civetweb.c:3897
#define SSL_read
Definition: civetweb.c:892
static long ssl_get_protocol(int version_id)
Definition: civetweb.c:11056
static void * realloc2(void *ptr, size_t size)
Definition: civetweb.c:6262