Logo ROOT   6.14/05
Reference Guide
civetweb.c
Go to the documentation of this file.
1 /* Copyright (c) 2013-2017 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 #if defined(_WIN32)
24 #if !defined(_CRT_SECURE_NO_WARNINGS)
25 #define _CRT_SECURE_NO_WARNINGS /* Disable deprecation warning in VS2005 */
26 #endif
27 #ifndef _WIN32_WINNT /* defined for tdm-gcc so we can use getnameinfo */
28 #define _WIN32_WINNT 0x0501
29 #endif
30 #else
31 #if !defined(_GNU_SOURCE)
32 #define _GNU_SOURCE /* for setgroups(), pthread_setname_np() */
33 #endif
34 #if defined(__linux__) && !defined(_XOPEN_SOURCE)
35 #define _XOPEN_SOURCE 600 /* For flockfile() on Linux */
36 #endif
37 #ifndef _LARGEFILE_SOURCE
38 #define _LARGEFILE_SOURCE /* For fseeko(), ftello() */
39 #endif
40 #ifndef _FILE_OFFSET_BITS
41 #define _FILE_OFFSET_BITS 64 /* Use 64-bit file offsets by default */
42 #endif
43 #ifndef __STDC_FORMAT_MACROS
44 #define __STDC_FORMAT_MACROS /* <inttypes.h> wants this for C++ */
45 #endif
46 #ifndef __STDC_LIMIT_MACROS
47 #define __STDC_LIMIT_MACROS /* C++ wants that for INT64_MAX */
48 #endif
49 #ifdef __sun
50 #define __EXTENSIONS__ /* to expose flockfile and friends in stdio.h */
51 #define __inline inline /* not recognized on older compiler versions */
52 #endif
53 #endif
54 
55 #if defined(USE_LUA)
56 #define USE_TIMERS
57 #endif
58 
59 #if defined(_MSC_VER)
60 /* 'type cast' : conversion from 'int' to 'HANDLE' of greater size */
61 #pragma warning(disable : 4306)
62 /* conditional expression is constant: introduced by FD_SET(..) */
63 #pragma warning(disable : 4127)
64 /* non-constant aggregate initializer: issued due to missing C99 support */
65 #pragma warning(disable : 4204)
66 /* padding added after data member */
67 #pragma warning(disable : 4820)
68 /* not defined as a preprocessor macro, replacing with '0' for '#if/#elif' */
69 #pragma warning(disable : 4668)
70 /* no function prototype given: converting '()' to '(void)' */
71 #pragma warning(disable : 4255)
72 /* function has been selected for automatic inline expansion */
73 #pragma warning(disable : 4711)
74 #endif
75 
76 
77 /* This code uses static_assert to check some conditions.
78  * Unfortunately some compilers still do not support it, so we have a
79  * replacement function here. */
80 #if defined(_MSC_VER) && (_MSC_VER >= 1600)
81 #define mg_static_assert static_assert
82 #elif defined(__cplusplus) && (__cplusplus >= 201103L)
83 #define mg_static_assert static_assert
84 #elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)
85 #define mg_static_assert _Static_assert
86 #else
88 #define mg_static_assert(cond, txt) \
89  extern char static_assert_replacement[(cond) ? 1 : -1]
90 #endif
91 
92 mg_static_assert(sizeof(int) == 4 || sizeof(int) == 8,
93  "int data type size check");
94 mg_static_assert(sizeof(void *) == 4 || sizeof(void *) == 8,
95  "pointer data type size check");
96 mg_static_assert(sizeof(void *) >= sizeof(int), "data type size check");
97 
98 
99 /* Alternative queue is well tested and should be the new default */
100 #ifdef NO_ALTERNATIVE_QUEUE
101 #ifdef ALTERNATIVE_QUEUE
102 #error "Define ALTERNATIVE_QUEUE or NO_ALTERNATIVE_QUEUE or none, but not both"
103 #endif
104 #else
105 #define ALTERNATIVE_QUEUE
106 #endif
107 
108 
109 /* DTL -- including winsock2.h works better if lean and mean */
110 #ifndef WIN32_LEAN_AND_MEAN
111 #define WIN32_LEAN_AND_MEAN
112 #endif
113 
114 #if defined(__SYMBIAN32__)
115 /* According to https://en.wikipedia.org/wiki/Symbian#History,
116  * Symbian is no longer maintained since 2014-01-01.
117  * Recent versions of CivetWeb are no longer tested for Symbian.
118  * It makes no sense, to support an abandoned operating system.
119  * All remaining "#ifdef __SYMBIAN__" cases will be droped from
120  * the code sooner or later.
121  */
122 #pragma message \
123  "Symbian is no longer maintained. CivetWeb will drop Symbian support."
124 #define NO_SSL /* SSL is not supported */
125 #define NO_CGI /* CGI is not supported */
126 #define PATH_MAX FILENAME_MAX
127 #endif /* __SYMBIAN32__ */
128 
129 
130 #ifndef CIVETWEB_HEADER_INCLUDED
131 /* Include the header file here, so the CivetWeb interface is defined for the
132  * entire implementation, including the following forward definitions. */
133 #include "civetweb.h"
134 #endif
135 
136 
137 #ifndef IGNORE_UNUSED_RESULT
138 #define IGNORE_UNUSED_RESULT(a) ((void)((a) && 1))
139 #endif
140 
141 
142 #if defined(__GNUC__) || defined(__MINGW32__)
143 
144 /* GCC unused function attribute seems fundamentally broken.
145  * Several attempts to tell the compiler "THIS FUNCTION MAY BE USED
146  * OR UNUSED" for individual functions failed.
147  * Either the compiler creates an "unused-function" warning if a
148  * function is not marked with __attribute__((unused)).
149  * On the other hand, if the function is marked with this attribute,
150  * but is used, the compiler raises a completely idiotic
151  * "used-but-marked-unused" warning - and
152  * #pragma GCC diagnostic ignored "-Wused-but-marked-unused"
153  * raises error: unknown option after ‘#pragma GCC diagnostic’.
154  * Disable this warning completely, until the GCC guys sober up
155  * again.
156  */
157 
158 #pragma GCC diagnostic ignored "-Wunused-function"
159 
160 #define FUNCTION_MAY_BE_UNUSED /* __attribute__((unused)) */
161 
162 #else
163 #define FUNCTION_MAY_BE_UNUSED
164 #endif
165 
166 
167 #ifndef _WIN32_WCE /* Some ANSI #includes are not available on Windows CE */
168 #include <sys/types.h>
169 #include <sys/stat.h>
170 #include <errno.h>
171 #include <signal.h>
172 #include <fcntl.h>
173 #endif /* !_WIN32_WCE */
174 
175 
176 #ifdef __clang__
177 /* When using -Weverything, clang does not accept it's own headers
178  * in a release build configuration. Disable what is too much in
179  * -Weverything. */
180 #pragma clang diagnostic ignored "-Wdisabled-macro-expansion"
181 #endif
182 
183 #if defined(__GNUC__) || defined(__MINGW32__)
184 /* Who on earth came to the conclusion, using __DATE__ should rise
185  * an "expansion of date or time macro is not reproducible"
186  * warning. That's exactly what was intended by using this macro.
187  * Just disable this nonsense warning. */
188 
189 /* And disabling them does not work either:
190  * #pragma clang diagnostic ignored "-Wno-error=date-time"
191  * #pragma clang diagnostic ignored "-Wdate-time"
192  * So we just have to disable ALL warnings for some lines
193  * of code.
194  */
195 #endif
196 
197 
198 #ifdef __MACH__ /* Apple OSX section */
199 
200 #ifdef __clang__
201 #if (__clang_major__ == 3) && ((__clang_minor__ == 7) || (__clang_minor__ == 8))
202 /* Avoid warnings for Xcode 7. It seems it does no longer exist in Xcode 8 */
203 #pragma clang diagnostic ignored "-Wno-reserved-id-macro"
204 #pragma clang diagnostic ignored "-Wno-keyword-macro"
205 #endif
206 #endif
207 
208 #define CLOCK_MONOTONIC (1)
209 #define CLOCK_REALTIME (2)
210 
211 #include <sys/errno.h>
212 #include <sys/time.h>
213 #include <mach/clock.h>
214 #include <mach/mach.h>
215 #include <mach/mach_time.h>
216 #include <assert.h>
217 
218 /* clock_gettime is not implemented on OSX prior to 10.12 */
219 static int
220 _civet_clock_gettime(int clk_id, struct timespec *t)
221 {
222  memset(t, 0, sizeof(*t));
223  if (clk_id == CLOCK_REALTIME) {
224  struct timeval now;
225  int rv = gettimeofday(&now, NULL);
226  if (rv) {
227  return rv;
228  }
229  t->tv_sec = now.tv_sec;
230  t->tv_nsec = now.tv_usec * 1000;
231  return 0;
232 
233  } else if (clk_id == CLOCK_MONOTONIC) {
234  static uint64_t clock_start_time = 0;
235  static mach_timebase_info_data_t timebase_ifo = {0, 0};
236 
237  uint64_t now = mach_absolute_time();
238 
239  if (clock_start_time == 0) {
240  kern_return_t mach_status = mach_timebase_info(&timebase_ifo);
241 #if defined(DEBUG)
242  assert(mach_status == KERN_SUCCESS);
243 #else
244  /* appease "unused variable" warning for release builds */
245  (void)mach_status;
246 #endif
247  clock_start_time = now;
248  }
249 
250  now = (uint64_t)((double)(now - clock_start_time)
251  * (double)timebase_ifo.numer
252  / (double)timebase_ifo.denom);
253 
254  t->tv_sec = now / 1000000000;
255  t->tv_nsec = now % 1000000000;
256  return 0;
257  }
258  return -1; /* EINVAL - Clock ID is unknown */
259 }
260 
261 /* if clock_gettime is declared, then __CLOCK_AVAILABILITY will be defined */
262 #ifdef __CLOCK_AVAILABILITY
263 /* If we compiled with Mac OSX 10.12 or later, then clock_gettime will be
264  * declared but it may be NULL at runtime. So we need to check before using
265  * it. */
266 static int
267 _civet_safe_clock_gettime(int clk_id, struct timespec *t)
268 {
269  if (clock_gettime) {
270  return clock_gettime(clk_id, t);
271  }
272  return _civet_clock_gettime(clk_id, t);
273 }
274 #define clock_gettime _civet_safe_clock_gettime
275 #else
276 #define clock_gettime _civet_clock_gettime
277 #endif
278 
279 #endif
280 
281 
282 #include <time.h>
283 #include <stdlib.h>
284 #include <stdarg.h>
285 #include <assert.h>
286 #include <string.h>
287 #include <ctype.h>
288 #include <limits.h>
289 #include <stddef.h>
290 #include <stdio.h>
291 #include <stdint.h>
292 
293 #ifndef INT64_MAX
294 #define INT64_MAX (9223372036854775807)
295 #endif
296 
297 
298 #ifndef MAX_WORKER_THREADS
299 #define MAX_WORKER_THREADS (1024 * 64)
300 #endif
301 
302 #ifndef SOCKET_TIMEOUT_QUANTUM /* in ms */
303 #define SOCKET_TIMEOUT_QUANTUM (2000)
304 #endif
305 
306 #define SHUTDOWN_RD (0)
307 #define SHUTDOWN_WR (1)
308 #define SHUTDOWN_BOTH (2)
309 
311  "worker threads must be a positive number");
312 
313 mg_static_assert(sizeof(size_t) == 4 || sizeof(size_t) == 8,
314  "size_t data type size check");
315 
316 #if defined(_WIN32) \
317  && !defined(__SYMBIAN32__) /* WINDOWS / UNIX include block */
318 #include <windows.h>
319 #include <winsock2.h> /* DTL add for SO_EXCLUSIVE */
320 #include <ws2tcpip.h>
321 
322 typedef const char *SOCK_OPT_TYPE;
323 
324 #if !defined(PATH_MAX)
325 #define PATH_MAX (MAX_PATH)
326 #endif
327 
328 #if !defined(PATH_MAX)
329 #define PATH_MAX (4096)
330 #endif
331 
332 mg_static_assert(PATH_MAX >= 1, "path length must be a positive number");
333 
334 #ifndef _IN_PORT_T
335 #ifndef in_port_t
336 #define in_port_t u_short
337 #endif
338 #endif
339 
340 #ifndef _WIN32_WCE
341 #include <process.h>
342 #include <direct.h>
343 #include <io.h>
344 #else /* _WIN32_WCE */
345 #define NO_CGI /* WinCE has no pipes */
346 #define NO_POPEN /* WinCE has no popen */
347 
348 typedef long off_t;
349 
350 #define errno ((int)(GetLastError()))
351 #define strerror(x) (_ultoa(x, (char *)_alloca(sizeof(x) * 3), 10))
352 #endif /* _WIN32_WCE */
353 
354 #define MAKEUQUAD(lo, hi) \
355  ((uint64_t)(((uint32_t)(lo)) | ((uint64_t)((uint32_t)(hi))) << 32))
356 #define RATE_DIFF (10000000) /* 100 nsecs */
357 #define EPOCH_DIFF (MAKEUQUAD(0xd53e8000, 0x019db1de))
358 #define SYS2UNIX_TIME(lo, hi) \
359  ((time_t)((MAKEUQUAD((lo), (hi)) - EPOCH_DIFF) / RATE_DIFF))
360 
361 /* Visual Studio 6 does not know __func__ or __FUNCTION__
362  * The rest of MS compilers use __FUNCTION__, not C99 __func__
363  * Also use _strtoui64 on modern M$ compilers */
364 #if defined(_MSC_VER)
365 #if (_MSC_VER < 1300)
366 #define STRX(x) #x
367 #define STR(x) STRX(x)
368 #define __func__ __FILE__ ":" STR(__LINE__)
369 #define strtoull(x, y, z) ((unsigned __int64)_atoi64(x))
370 #define strtoll(x, y, z) (_atoi64(x))
371 #else
372 #define __func__ __FUNCTION__
373 #define strtoull(x, y, z) (_strtoui64(x, y, z))
374 #define strtoll(x, y, z) (_strtoi64(x, y, z))
375 #endif
376 #endif /* _MSC_VER */
377 
378 #define ERRNO ((int)(GetLastError()))
379 #define NO_SOCKLEN_T
380 
381 #if defined(_WIN64) || defined(__MINGW64__)
382 #define SSL_LIB "ssleay64.dll"
383 #define CRYPTO_LIB "libeay64.dll"
384 #else
385 #define SSL_LIB "ssleay32.dll"
386 #define CRYPTO_LIB "libeay32.dll"
387 #endif
388 
389 #define O_NONBLOCK (0)
390 #ifndef W_OK
391 #define W_OK (2) /* http://msdn.microsoft.com/en-us/library/1w06ktdy.aspx */
392 #endif
393 #if !defined(EWOULDBLOCK)
394 #define EWOULDBLOCK WSAEWOULDBLOCK
395 #endif /* !EWOULDBLOCK */
396 #define _POSIX_
397 #define INT64_FMT "I64d"
398 #define UINT64_FMT "I64u"
399 
400 #define WINCDECL __cdecl
401 #define vsnprintf_impl _vsnprintf
402 #define access _access
403 #define mg_sleep(x) (Sleep(x))
404 
405 #define pipe(x) _pipe(x, MG_BUF_LEN, _O_BINARY)
406 #ifndef popen
407 #define popen(x, y) (_popen(x, y))
408 #endif
409 #ifndef pclose
410 #define pclose(x) (_pclose(x))
411 #endif
412 #define close(x) (_close(x))
413 #define dlsym(x, y) (GetProcAddress((HINSTANCE)(x), (y)))
414 #define RTLD_LAZY (0)
415 #define fseeko(x, y, z) ((_lseeki64(_fileno(x), (y), (z)) == -1) ? -1 : 0)
416 #define fdopen(x, y) (_fdopen((x), (y)))
417 #define write(x, y, z) (_write((x), (y), (unsigned)z))
418 #define read(x, y, z) (_read((x), (y), (unsigned)z))
419 #define flockfile(x) (EnterCriticalSection(&global_log_file_lock))
420 #define funlockfile(x) (LeaveCriticalSection(&global_log_file_lock))
421 #define sleep(x) (Sleep((x)*1000))
422 #define rmdir(x) (_rmdir(x))
423 #define timegm(x) (_mkgmtime(x))
424 
425 #if !defined(fileno)
426 #define fileno(x) (_fileno(x))
427 #endif /* !fileno MINGW #defines fileno */
428 
429 typedef HANDLE pthread_mutex_t;
430 typedef DWORD pthread_key_t;
431 typedef HANDLE pthread_t;
432 typedef struct {
433  CRITICAL_SECTION threadIdSec;
434  struct mg_workerTLS *waiting_thread; /* The chain of threads */
436 
437 #ifndef __clockid_t_defined
438 typedef DWORD clockid_t;
439 #endif
440 #ifndef CLOCK_MONOTONIC
441 #define CLOCK_MONOTONIC (1)
442 #endif
443 #ifndef CLOCK_REALTIME
444 #define CLOCK_REALTIME (2)
445 #endif
446 #ifndef CLOCK_THREAD
447 #define CLOCK_THREAD (3)
448 #endif
449 #ifndef CLOCK_PROCESS
450 #define CLOCK_PROCESS (4)
451 #endif
452 
453 
454 #if defined(_MSC_VER) && (_MSC_VER >= 1900)
455 #define _TIMESPEC_DEFINED
456 #endif
457 #ifndef _TIMESPEC_DEFINED
458 struct timespec {
459  time_t tv_sec; /* seconds */
460  long tv_nsec; /* nanoseconds */
461 };
462 #endif
463 
464 #if !defined(WIN_PTHREADS_TIME_H)
465 #define MUST_IMPLEMENT_CLOCK_GETTIME
466 #endif
467 
468 #ifdef MUST_IMPLEMENT_CLOCK_GETTIME
469 #define clock_gettime mg_clock_gettime
470 static int
471 clock_gettime(clockid_t clk_id, struct timespec *tp)
472 {
473  FILETIME ft;
474  ULARGE_INTEGER li, li2;
475  BOOL ok = FALSE;
476  double d;
477  static double perfcnt_per_sec = 0.0;
478 
479  if (tp) {
480  memset(tp, 0, sizeof(*tp));
481 
482  if (clk_id == CLOCK_REALTIME) {
483 
484  /* BEGIN: CLOCK_REALTIME = wall clock (date and time) */
485  GetSystemTimeAsFileTime(&ft);
486  li.LowPart = ft.dwLowDateTime;
487  li.HighPart = ft.dwHighDateTime;
488  li.QuadPart -= 116444736000000000; /* 1.1.1970 in filedate */
489  tp->tv_sec = (time_t)(li.QuadPart / 10000000);
490  tp->tv_nsec = (long)(li.QuadPart % 10000000) * 100;
491  ok = TRUE;
492  /* END: CLOCK_REALTIME */
493 
494  } else if (clk_id == CLOCK_MONOTONIC) {
495 
496  /* BEGIN: CLOCK_MONOTONIC = stopwatch (time differences) */
497  if (perfcnt_per_sec == 0.0) {
498  QueryPerformanceFrequency((LARGE_INTEGER *)&li);
499  perfcnt_per_sec = 1.0 / li.QuadPart;
500  }
501  if (perfcnt_per_sec != 0.0) {
502  QueryPerformanceCounter((LARGE_INTEGER *)&li);
503  d = li.QuadPart * perfcnt_per_sec;
504  tp->tv_sec = (time_t)d;
505  d -= tp->tv_sec;
506  tp->tv_nsec = (long)(d * 1.0E9);
507  ok = TRUE;
508  }
509  /* END: CLOCK_MONOTONIC */
510 
511  } else if (clk_id == CLOCK_THREAD) {
512 
513  /* BEGIN: CLOCK_THREAD = CPU usage of thread */
514  FILETIME t_create, t_exit, t_kernel, t_user;
515  if (GetThreadTimes(GetCurrentThread(),
516  &t_create,
517  &t_exit,
518  &t_kernel,
519  &t_user)) {
520  li.LowPart = t_user.dwLowDateTime;
521  li.HighPart = t_user.dwHighDateTime;
522  li2.LowPart = t_kernel.dwLowDateTime;
523  li2.HighPart = t_kernel.dwHighDateTime;
524  li.QuadPart += li2.QuadPart;
525  tp->tv_sec = (time_t)(li.QuadPart / 10000000);
526  tp->tv_nsec = (long)(li.QuadPart % 10000000) * 100;
527  ok = TRUE;
528  }
529  /* END: CLOCK_THREAD */
530 
531  } else if (clk_id == CLOCK_PROCESS) {
532 
533  /* BEGIN: CLOCK_PROCESS = CPU usage of process */
534  FILETIME t_create, t_exit, t_kernel, t_user;
535  if (GetProcessTimes(GetCurrentProcess(),
536  &t_create,
537  &t_exit,
538  &t_kernel,
539  &t_user)) {
540  li.LowPart = t_user.dwLowDateTime;
541  li.HighPart = t_user.dwHighDateTime;
542  li2.LowPart = t_kernel.dwLowDateTime;
543  li2.HighPart = t_kernel.dwHighDateTime;
544  li.QuadPart += li2.QuadPart;
545  tp->tv_sec = (time_t)(li.QuadPart / 10000000);
546  tp->tv_nsec = (long)(li.QuadPart % 10000000) * 100;
547  ok = TRUE;
548  }
549  /* END: CLOCK_PROCESS */
550 
551  } else {
552 
553  /* BEGIN: unknown clock */
554  /* ok = FALSE; already set by init */
555  /* END: unknown clock */
556  }
557  }
558 
559  return ok ? 0 : -1;
560 }
561 #endif
562 
563 
564 #define pid_t HANDLE /* MINGW typedefs pid_t to int. Using #define here. */
565 
566 static int pthread_mutex_lock(pthread_mutex_t *);
567 static int pthread_mutex_unlock(pthread_mutex_t *);
568 static void path_to_unicode(const struct mg_connection *conn,
569  const char *path,
570  wchar_t *wbuf,
571  size_t wbuf_len);
572 
573 /* All file operations need to be rewritten to solve #246. */
574 
575 #include "file_ops.inl"
576 
577 struct mg_file;
578 
579 static const char *
580 mg_fgets(char *buf, size_t size, struct mg_file *filep, char **p);
581 
582 
583 /* POSIX dirent interface */
584 struct dirent {
585  char d_name[PATH_MAX];
586 };
587 
588 typedef struct DIR {
589  HANDLE handle;
590  WIN32_FIND_DATAW info;
591  struct dirent result;
592 } DIR;
593 
594 #if defined(_WIN32) && !defined(POLLIN)
595 #ifndef HAVE_POLL
596 struct pollfd {
597  SOCKET fd;
598  short events;
599  short revents;
600 };
601 #define POLLIN (0x0300)
602 #endif
603 #endif
604 
605 /* Mark required libraries */
606 #if defined(_MSC_VER)
607 #pragma comment(lib, "Ws2_32.lib")
608 #endif
609 
610 #else /* defined(_WIN32) && !defined(__SYMBIAN32__) - \
611  WINDOWS / UNIX include block */
612 
613 #include <sys/wait.h>
614 #include <sys/socket.h>
615 #include <sys/poll.h>
616 #include <netinet/in.h>
617 #include <arpa/inet.h>
618 #include <sys/time.h>
619 #include <sys/utsname.h>
620 #include <stdint.h>
621 #include <inttypes.h>
622 #include <netdb.h>
623 #include <netinet/tcp.h>
624 typedef const void *SOCK_OPT_TYPE;
625 
626 #if defined(ANDROID)
627 typedef unsigned short int in_port_t;
628 #endif
629 
630 #include <pwd.h>
631 #include <unistd.h>
632 #include <grp.h>
633 #include <dirent.h>
634 #define vsnprintf_impl vsnprintf
635 
636 #if !defined(NO_SSL_DL) && !defined(NO_SSL)
637 #include <dlfcn.h>
638 #endif
639 #include <pthread.h>
640 #if defined(__MACH__)
641 #define SSL_LIB "libssl.dylib"
642 #define CRYPTO_LIB "libcrypto.dylib"
643 #else
644 #if !defined(SSL_LIB)
645 #define SSL_LIB "libssl.so"
646 #endif
647 #if !defined(CRYPTO_LIB)
648 #define CRYPTO_LIB "libcrypto.so"
649 #endif
650 #endif
651 #ifndef O_BINARY
652 #define O_BINARY (0)
653 #endif /* O_BINARY */
654 #define closesocket(a) (close(a))
655 #define mg_mkdir(conn, path, mode) (mkdir(path, mode))
656 #define mg_remove(conn, x) (remove(x))
657 #define mg_sleep(x) (usleep((x)*1000))
658 #define mg_opendir(conn, x) (opendir(x))
659 #define mg_closedir(x) (closedir(x))
660 #define mg_readdir(x) (readdir(x))
661 #define ERRNO (errno)
662 #define INVALID_SOCKET (-1)
663 #define INT64_FMT PRId64
664 #define UINT64_FMT PRIu64
665 typedef int SOCKET;
666 #define WINCDECL
667 
668 #if defined(__hpux)
669 /* HPUX 11 does not have monotonic, fall back to realtime */
670 #ifndef CLOCK_MONOTONIC
671 #define CLOCK_MONOTONIC CLOCK_REALTIME
672 #endif
673 
674 /* HPUX defines socklen_t incorrectly as size_t which is 64bit on
675  * Itanium. Without defining _XOPEN_SOURCE or _XOPEN_SOURCE_EXTENDED
676  * the prototypes use int* rather than socklen_t* which matches the
677  * actual library expectation. When called with the wrong size arg
678  * accept() returns a zero client inet addr and check_acl() always
679  * fails. Since socklen_t is widely used below, just force replace
680  * their typedef with int. - DTL
681  */
682 #define socklen_t int
683 #endif /* hpux */
684 
685 #endif /* defined(_WIN32) && !defined(__SYMBIAN32__) - \
686  WINDOWS / UNIX include block */
687 
688 /* va_copy should always be a macro, C99 and C++11 - DTL */
689 #ifndef va_copy
690 #define va_copy(x, y) ((x) = (y))
691 #endif
692 
693 #ifdef _WIN32
694 /* Create substitutes for POSIX functions in Win32. */
695 
696 #if defined(__MINGW32__)
697 /* Show no warning in case system functions are not used. */
698 #pragma GCC diagnostic push
699 #pragma GCC diagnostic ignored "-Wunused-function"
700 #endif
701 
702 
703 static CRITICAL_SECTION global_log_file_lock;
704 
706 static DWORD
707 pthread_self(void)
708 {
709  return GetCurrentThreadId();
710 }
711 
712 
714 static int
715 pthread_key_create(
716  pthread_key_t *key,
717  void (*_ignored)(void *) /* destructor not supported for Windows */
718  )
719 {
720  (void)_ignored;
721 
722  if ((key != 0)) {
723  *key = TlsAlloc();
724  return (*key != TLS_OUT_OF_INDEXES) ? 0 : -1;
725  }
726  return -2;
727 }
728 
729 
731 static int
732 pthread_key_delete(pthread_key_t key)
733 {
734  return TlsFree(key) ? 0 : 1;
735 }
736 
737 
739 static int
740 pthread_setspecific(pthread_key_t key, void *value)
741 {
742  return TlsSetValue(key, value) ? 0 : 1;
743 }
744 
745 
747 static void *
748 pthread_getspecific(pthread_key_t key)
749 {
750  return TlsGetValue(key);
751 }
752 
753 #if defined(__MINGW32__)
754 /* Enable unused function warning again */
755 #pragma GCC diagnostic pop
756 #endif
757 
758 static struct pthread_mutex_undefined_struct *pthread_mutex_attr = NULL;
759 #else
760 static pthread_mutexattr_t pthread_mutex_attr;
761 #endif /* _WIN32 */
762 
763 
764 #define PASSWORDS_FILE_NAME ".htpasswd"
765 #define CGI_ENVIRONMENT_SIZE (4096)
766 #define MAX_CGI_ENVIR_VARS (256)
767 #define MG_BUF_LEN (8192)
768 
769 #define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0]))
770 
771 
772 #if defined(_WIN32_WCE)
773 /* Create substitutes for POSIX functions in Win32. */
774 
775 #if defined(__MINGW32__)
776 /* Show no warning in case system functions are not used. */
777 #pragma GCC diagnostic push
778 #pragma GCC diagnostic ignored "-Wunused-function"
779 #endif
780 
781 
783 static time_t
784 time(time_t *ptime)
785 {
786  time_t t;
787  SYSTEMTIME st;
788  FILETIME ft;
789 
790  GetSystemTime(&st);
791  SystemTimeToFileTime(&st, &ft);
792  t = SYS2UNIX_TIME(ft.dwLowDateTime, ft.dwHighDateTime);
793 
794  if (ptime != NULL) {
795  *ptime = t;
796  }
797 
798  return t;
799 }
800 
801 
803 static struct tm *
804 localtime_s(const time_t *ptime, struct tm *ptm)
805 {
806  int64_t t = ((int64_t)*ptime) * RATE_DIFF + EPOCH_DIFF;
807  FILETIME ft, lft;
808  SYSTEMTIME st;
809  TIME_ZONE_INFORMATION tzinfo;
810 
811  if (ptm == NULL) {
812  return NULL;
813  }
814 
815  *(int64_t *)&ft = t;
816  FileTimeToLocalFileTime(&ft, &lft);
817  FileTimeToSystemTime(&lft, &st);
818  ptm->tm_year = st.wYear - 1900;
819  ptm->tm_mon = st.wMonth - 1;
820  ptm->tm_wday = st.wDayOfWeek;
821  ptm->tm_mday = st.wDay;
822  ptm->tm_hour = st.wHour;
823  ptm->tm_min = st.wMinute;
824  ptm->tm_sec = st.wSecond;
825  ptm->tm_yday = 0; /* hope nobody uses this */
826  ptm->tm_isdst =
827  (GetTimeZoneInformation(&tzinfo) == TIME_ZONE_ID_DAYLIGHT) ? 1 : 0;
828 
829  return ptm;
830 }
831 
832 
834 static struct tm *
835 gmtime_s(const time_t *ptime, struct tm *ptm)
836 {
837  /* FIXME(lsm): fix this. */
838  return localtime_s(ptime, ptm);
839 }
840 
841 
842 static int mg_atomic_inc(volatile int *addr);
843 static struct tm tm_array[MAX_WORKER_THREADS];
844 static int tm_index = 0;
845 
846 
848 static struct tm *
849 localtime(const time_t *ptime)
850 {
851  int i = mg_atomic_inc(&tm_index) % (sizeof(tm_array) / sizeof(tm_array[0]));
852  return localtime_s(ptime, tm_array + i);
853 }
854 
855 
857 static struct tm *
858 gmtime(const time_t *ptime)
859 {
860  int i = mg_atomic_inc(&tm_index) % ARRAY_SIZE(tm_array);
861  return gmtime_s(ptime, tm_array + i);
862 }
863 
864 
866 static size_t
867 strftime(char *dst, size_t dst_size, const char *fmt, const struct tm *tm)
868 {
869  /* TODO: (void)mg_snprintf(NULL, dst, dst_size, "implement strftime()
870  * for WinCE"); */
871  return 0;
872 }
873 
874 #define _beginthreadex(psec, stack, func, prm, flags, ptid) \
875  (uintptr_t) CreateThread(psec, stack, func, prm, flags, ptid)
876 
877 #define remove(f) mg_remove(NULL, f)
878 
879 
881 static int
882 rename(const char *a, const char *b)
883 {
884  wchar_t wa[PATH_MAX];
885  wchar_t wb[PATH_MAX];
886  path_to_unicode(NULL, a, wa, ARRAY_SIZE(wa));
887  path_to_unicode(NULL, b, wb, ARRAY_SIZE(wb));
888 
889  return MoveFileW(wa, wb) ? 0 : -1;
890 }
891 
892 
893 struct stat {
894  int64_t st_size;
895  time_t st_mtime;
896 };
897 
898 
900 static int
901 stat(const char *name, struct stat *st)
902 {
903  wchar_t wbuf[PATH_MAX];
904  WIN32_FILE_ATTRIBUTE_DATA attr;
905  time_t creation_time, write_time;
906 
907  path_to_unicode(NULL, name, wbuf, ARRAY_SIZE(wbuf));
908  memset(&attr, 0, sizeof(attr));
909 
910  GetFileAttributesExW(wbuf, GetFileExInfoStandard, &attr);
911  st->st_size =
912  (((int64_t)attr.nFileSizeHigh) << 32) + (int64_t)attr.nFileSizeLow;
913 
914  write_time = SYS2UNIX_TIME(attr.ftLastWriteTime.dwLowDateTime,
915  attr.ftLastWriteTime.dwHighDateTime);
916  creation_time = SYS2UNIX_TIME(attr.ftCreationTime.dwLowDateTime,
917  attr.ftCreationTime.dwHighDateTime);
918 
919  if (creation_time > write_time) {
920  st->st_mtime = creation_time;
921  } else {
922  st->st_mtime = write_time;
923  }
924  return 0;
925 }
926 
927 #define access(x, a) 1 /* not required anyway */
928 
929 /* WinCE-TODO: define stat, remove, rename, _rmdir, _lseeki64 */
930 /* Values from errno.h in Windows SDK (Visual Studio). */
931 #define EEXIST 17
932 #define EACCES 13
933 #define ENOENT 2
934 
935 #if defined(__MINGW32__)
936 /* Enable unused function warning again */
937 #pragma GCC diagnostic pop
938 #endif
939 
940 #endif /* defined(_WIN32_WCE) */
941 
942 
943 #if defined(__GNUC__) || defined(__MINGW32__)
944 /* Show no warning in case system functions are not used. */
945 #define GCC_VERSION \
946  (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
947 #if GCC_VERSION >= 40500
948 #pragma GCC diagnostic push
949 #pragma GCC diagnostic ignored "-Wunused-function"
950 #endif /* GCC_VERSION >= 40500 */
951 #endif /* defined(__GNUC__) || defined(__MINGW32__) */
952 #if defined(__clang__)
953 /* Show no warning in case system functions are not used. */
954 #pragma clang diagnostic push
955 #pragma clang diagnostic ignored "-Wunused-function"
956 #endif
957 
958 static pthread_mutex_t global_lock_mutex;
959 
960 
961 #if defined(_WIN32) && !defined(__SYMBIAN32__)
962 /* Forward declaration for Windows */
964 static int pthread_mutex_lock(pthread_mutex_t *mutex);
965 
967 static int pthread_mutex_unlock(pthread_mutex_t *mutex);
968 #endif
969 
970 
972 static void
974 {
975  (void)pthread_mutex_lock(&global_lock_mutex);
976 }
977 
978 
980 static void
982 {
983  (void)pthread_mutex_unlock(&global_lock_mutex);
984 }
985 
986 
988 static int
989 mg_atomic_inc(volatile int *addr)
990 {
991  int ret;
992 #if defined(_WIN32) && !defined(__SYMBIAN32__) && !defined(NO_ATOMICS)
993  /* Depending on the SDK, this function uses either
994  * (volatile unsigned int *) or (volatile LONG *),
995  * so whatever you use, the other SDK is likely to raise a warning. */
996  ret = InterlockedIncrement((volatile long *)addr);
997 #elif defined(__GNUC__) \
998  && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 0))) \
999  && !defined(NO_ATOMICS)
1000  ret = __sync_add_and_fetch(addr, 1);
1001 #else
1002  mg_global_lock();
1003  ret = (++(*addr));
1004  mg_global_unlock();
1005 #endif
1006  return ret;
1007 }
1008 
1009 
1011 static int
1012 mg_atomic_dec(volatile int *addr)
1013 {
1014  int ret;
1015 #if defined(_WIN32) && !defined(__SYMBIAN32__) && !defined(NO_ATOMICS)
1016  /* Depending on the SDK, this function uses either
1017  * (volatile unsigned int *) or (volatile LONG *),
1018  * so whatever you use, the other SDK is likely to raise a warning. */
1019  ret = InterlockedDecrement((volatile long *)addr);
1020 #elif defined(__GNUC__) \
1021  && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 0))) \
1022  && !defined(NO_ATOMICS)
1023  ret = __sync_sub_and_fetch(addr, 1);
1024 #else
1025  mg_global_lock();
1026  ret = (--(*addr));
1027  mg_global_unlock();
1028 #endif
1029  return ret;
1030 }
1031 
1032 
1033 #if defined(USE_SERVER_STATS)
1034 static int64_t
1035 mg_atomic_add(volatile int64_t *addr, int64_t value)
1036 {
1037  int64_t ret;
1038 #if defined(_WIN64) && !defined(__SYMBIAN32__) && !defined(NO_ATOMICS)
1039  ret = InterlockedAdd64(addr, value);
1040 #elif defined(__GNUC__) \
1041  && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 0))) \
1042  && !defined(NO_ATOMICS)
1043  ret = __sync_add_and_fetch(addr, value);
1044 #else
1045  mg_global_lock();
1046  *addr += value;
1047  ret = (*addr);
1048  mg_global_unlock();
1049 #endif
1050  return ret;
1051 }
1052 #endif
1053 
1054 
1055 #if defined(__GNUC__)
1056 /* Show no warning in case system functions are not used. */
1057 #if GCC_VERSION >= 40500
1058 #pragma GCC diagnostic pop
1059 #endif /* GCC_VERSION >= 40500 */
1060 #endif /* defined(__GNUC__) */
1061 #if defined(__clang__)
1062 /* Show no warning in case system functions are not used. */
1063 #pragma clang diagnostic pop
1064 #endif
1065 
1066 
1067 #if defined(USE_SERVER_STATS)
1068 
1069 struct mg_memory_stat {
1070  volatile int64_t totalMemUsed;
1071  volatile int64_t maxMemUsed;
1072  volatile int blockCount;
1073 };
1074 
1075 
1076 static struct mg_memory_stat *get_memory_stat(struct mg_context *ctx);
1077 
1078 
1079 static void *
1080 mg_malloc_ex(size_t size,
1081  struct mg_context *ctx,
1082  const char *file,
1083  unsigned line)
1084 {
1085  void *data = malloc(size + 2 * sizeof(uintptr_t));
1086  void *memory = 0;
1087  struct mg_memory_stat *mstat = get_memory_stat(ctx);
1088 
1089 #if defined(MEMORY_DEBUGGING)
1090  char mallocStr[256];
1091 #else
1092  (void)file;
1093  (void)line;
1094 #endif
1095 
1096  if (data) {
1097  int64_t mmem = mg_atomic_add(&mstat->totalMemUsed, (int64_t)size);
1098  if (mmem > mstat->maxMemUsed) {
1099  /* could use atomic compare exchange, but this
1100  * seems overkill for statistics data */
1101  mstat->maxMemUsed = mmem;
1102  }
1103 
1104  mg_atomic_inc(&mstat->blockCount);
1105  ((uintptr_t *)data)[0] = size;
1106  ((uintptr_t *)data)[1] = (uintptr_t)mstat;
1107  memory = (void *)(((char *)data) + 2 * sizeof(uintptr_t));
1108  }
1109 
1110 #if defined(MEMORY_DEBUGGING)
1111  sprintf(mallocStr,
1112  "MEM: %p %5lu alloc %7lu %4lu --- %s:%u\n",
1113  memory,
1114  (unsigned long)size,
1115  (unsigned long)mstat->totalMemUsed,
1116  (unsigned long)mstat->blockCount,
1117  file,
1118  line);
1119 #if defined(_WIN32)
1120  OutputDebugStringA(mallocStr);
1121 #else
1122  DEBUG_TRACE("%s", mallocStr);
1123 #endif
1124 #endif
1125 
1126  return memory;
1127 }
1128 
1129 
1130 static void *
1131 mg_calloc_ex(size_t count,
1132  size_t size,
1133  struct mg_context *ctx,
1134  const char *file,
1135  unsigned line)
1136 {
1137  void *data = mg_malloc_ex(size * count, ctx, file, line);
1138 
1139  if (data) {
1140  memset(data, 0, size * count);
1141  }
1142  return data;
1143 }
1144 
1145 
1146 static void
1147 mg_free_ex(void *memory, const char *file, unsigned line)
1148 {
1149  void *data = (void *)(((char *)memory) - 2 * sizeof(uintptr_t));
1150 
1151 
1152 #if defined(MEMORY_DEBUGGING)
1153  char mallocStr[256];
1154 #else
1155  (void)file;
1156  (void)line;
1157 #endif
1158 
1159  if (memory) {
1160  uintptr_t size = ((uintptr_t *)data)[0];
1161  struct mg_memory_stat *mstat =
1162  (struct mg_memory_stat *)(((uintptr_t *)data)[1]);
1163  mg_atomic_add(&mstat->totalMemUsed, -(int64_t)size);
1164  mg_atomic_dec(&mstat->blockCount);
1165 #if defined(MEMORY_DEBUGGING)
1166  sprintf(mallocStr,
1167  "MEM: %p %5lu free %7lu %4lu --- %s:%u\n",
1168  memory,
1169  (unsigned long)size,
1170  (unsigned long)mstat->totalMemUsed,
1171  (unsigned long)mstat->blockCount,
1172  file,
1173  line);
1174 #if defined(_WIN32)
1175  OutputDebugStringA(mallocStr);
1176 #else
1177  DEBUG_TRACE("%s", mallocStr);
1178 #endif
1179 #endif
1180  free(data);
1181  }
1182 }
1183 
1184 
1185 static void *
1186 mg_realloc_ex(void *memory,
1187  size_t newsize,
1188  struct mg_context *ctx,
1189  const char *file,
1190  unsigned line)
1191 {
1192  void *data;
1193  void *_realloc;
1194  uintptr_t oldsize;
1195 
1196 #if defined(MEMORY_DEBUGGING)
1197  char mallocStr[256];
1198 #else
1199  (void)file;
1200  (void)line;
1201 #endif
1202 
1203  if (newsize) {
1204  if (memory) {
1205  /* Reallocate existing block */
1206  struct mg_memory_stat *mstat;
1207  data = (void *)(((char *)memory) - 2 * sizeof(uintptr_t));
1208  oldsize = ((uintptr_t *)data)[0];
1209  mstat = (struct mg_memory_stat *)((uintptr_t *)data)[1];
1210  _realloc = realloc(data, newsize + 2 * sizeof(uintptr_t));
1211  if (_realloc) {
1212  data = _realloc;
1213  mg_atomic_add(&mstat->totalMemUsed, -(int64_t)oldsize);
1214 #if defined(MEMORY_DEBUGGING)
1215  sprintf(mallocStr,
1216  "MEM: %p %5lu r-free %7lu %4lu --- %s:%u\n",
1217  memory,
1218  (unsigned long)oldsize,
1219  (unsigned long)mstat->totalMemUsed,
1220  (unsigned long)mstat->blockCount,
1221  file,
1222  line);
1223 #if defined(_WIN32)
1224  OutputDebugStringA(mallocStr);
1225 #else
1226  DEBUG_TRACE("%s", mallocStr);
1227 #endif
1228 #endif
1229  mg_atomic_add(&mstat->totalMemUsed, (int64_t)newsize);
1230 #if defined(MEMORY_DEBUGGING)
1231  sprintf(mallocStr,
1232  "MEM: %p %5lu r-alloc %7lu %4lu --- %s:%u\n",
1233  memory,
1234  (unsigned long)newsize,
1235  (unsigned long)mstat->totalMemUsed,
1236  (unsigned long)mstat->blockCount,
1237  file,
1238  line);
1239 #if defined(_WIN32)
1240  OutputDebugStringA(mallocStr);
1241 #else
1242  DEBUG_TRACE("%s", mallocStr);
1243 #endif
1244 #endif
1245  *(uintptr_t *)data = newsize;
1246  data = (void *)(((char *)data) + 2 * sizeof(uintptr_t));
1247  } else {
1248 #if defined(MEMORY_DEBUGGING)
1249 #if defined(_WIN32)
1250  OutputDebugStringA("MEM: realloc failed\n");
1251 #else
1252  DEBUG_TRACE("%s", "MEM: realloc failed\n");
1253 #endif
1254 #endif
1255  return _realloc;
1256  }
1257  } else {
1258  /* Allocate new block */
1259  data = mg_malloc_ex(newsize, ctx, file, line);
1260  }
1261  } else {
1262  /* Free existing block */
1263  data = 0;
1264  mg_free_ex(memory, file, line);
1265  }
1266 
1267  return data;
1268 }
1269 
1270 #define mg_malloc(a) mg_malloc_ex(a, NULL, __FILE__, __LINE__)
1271 #define mg_calloc(a, b) mg_calloc_ex(a, b, NULL, __FILE__, __LINE__)
1272 #define mg_realloc(a, b) mg_realloc_ex(a, b, NULL, __FILE__, __LINE__)
1273 #define mg_free(a) mg_free_ex(a, __FILE__, __LINE__)
1274 
1275 #define mg_malloc_ctx(a, c) mg_malloc_ex(a, c, __FILE__, __LINE__)
1276 #define mg_calloc_ctx(a, b, c) mg_calloc_ex(a, b, c, __FILE__, __LINE__)
1277 #define mg_realloc_ctx(a, b, c) mg_realloc_ex(a, b, c, __FILE__, __LINE__)
1278 
1279 #else /* USE_SERVER_STATS */
1280 
1281 static __inline void *
1282 mg_malloc(size_t a)
1283 {
1284  return malloc(a);
1285 }
1286 
1287 static __inline void *
1288 mg_calloc(size_t a, size_t b)
1289 {
1290  return calloc(a, b);
1291 }
1292 
1293 static __inline void *
1294 mg_realloc(void *a, size_t b)
1295 {
1296  return realloc(a, b);
1297 }
1298 
1299 static __inline void
1300 mg_free(void *a)
1301 {
1302  free(a);
1303 }
1304 
1305 #define mg_malloc_ctx(a, c) mg_malloc(a)
1306 #define mg_calloc_ctx(a, b, c) mg_calloc(a, b)
1307 #define mg_realloc_ctx(a, b, c) mg_realloc(a, b)
1308 #define mg_free_ctx(a, c) mg_free(a)
1309 
1310 #endif /* USE_SERVER_STATS */
1311 
1312 
1313 static void mg_vsnprintf(const struct mg_connection *conn,
1314  int *truncated,
1315  char *buf,
1316  size_t buflen,
1317  const char *fmt,
1318  va_list ap);
1319 
1320 static void mg_snprintf(const struct mg_connection *conn,
1321  int *truncated,
1322  char *buf,
1323  size_t buflen,
1324  PRINTF_FORMAT_STRING(const char *fmt),
1325  ...) PRINTF_ARGS(5, 6);
1326 
1327 /* This following lines are just meant as a reminder to use the mg-functions
1328  * for memory management */
1329 #ifdef malloc
1330 #undef malloc
1331 #endif
1332 #ifdef calloc
1333 #undef calloc
1334 #endif
1335 #ifdef realloc
1336 #undef realloc
1337 #endif
1338 #ifdef free
1339 #undef free
1340 #endif
1341 #ifdef snprintf
1342 #undef snprintf
1343 #endif
1344 #ifdef vsnprintf
1345 #undef vsnprintf
1346 #endif
1347 #define malloc DO_NOT_USE_THIS_FUNCTION__USE_mg_malloc
1348 #define calloc DO_NOT_USE_THIS_FUNCTION__USE_mg_calloc
1349 #define realloc DO_NOT_USE_THIS_FUNCTION__USE_mg_realloc
1350 #define free DO_NOT_USE_THIS_FUNCTION__USE_mg_free
1351 #define snprintf DO_NOT_USE_THIS_FUNCTION__USE_mg_snprintf
1352 #ifdef _WIN32 /* vsnprintf must not be used in any system, * \ \ \ \
1353  * but this define only works well for Windows. */
1354 #define vsnprintf DO_NOT_USE_THIS_FUNCTION__USE_mg_vsnprintf
1355 #endif
1356 
1357 
1358 /* mg_init_library counter */
1359 static int mg_init_library_called = 0;
1360 
1361 #if !defined(NO_SSL)
1362 static int mg_ssl_initialized = 0;
1363 #endif
1364 
1365 static pthread_key_t sTlsKey; /* Thread local storage index */
1366 static int thread_idx_max = 0;
1367 
1368 
1369 struct mg_workerTLS {
1370  int is_master;
1371  unsigned long thread_idx;
1372 #if defined(_WIN32) && !defined(__SYMBIAN32__)
1373  HANDLE pthread_cond_helper_mutex;
1374  struct mg_workerTLS *next_waiting_thread;
1375 #endif
1376 };
1377 
1378 
1379 #if defined(__GNUC__) || defined(__MINGW32__)
1380 /* Show no warning in case system functions are not used. */
1381 #if GCC_VERSION >= 40500
1382 #pragma GCC diagnostic push
1383 #pragma GCC diagnostic ignored "-Wunused-function"
1384 #endif /* GCC_VERSION >= 40500 */
1385 #endif /* defined(__GNUC__) || defined(__MINGW32__) */
1386 #if defined(__clang__)
1387 /* Show no warning in case system functions are not used. */
1388 #pragma clang diagnostic push
1389 #pragma clang diagnostic ignored "-Wunused-function"
1390 #endif
1391 
1392 
1393 /* Get a unique thread ID as unsigned long, independent from the data type
1394  * of thread IDs defined by the operating system API.
1395  * If two calls to mg_current_thread_id return the same value, they calls
1396  * are done from the same thread. If they return different values, they are
1397  * done from different threads. (Provided this function is used in the same
1398  * process context and threads are not repeatedly created and deleted, but
1399  * CivetWeb does not do that).
1400  * This function must match the signature required for SSL id callbacks:
1401  * CRYPTO_set_id_callback
1402  */
1404 static unsigned long
1406 {
1407 #ifdef _WIN32
1408  return GetCurrentThreadId();
1409 #else
1410 
1411 #ifdef __clang__
1412 #pragma clang diagnostic push
1413 #pragma clang diagnostic ignored "-Wunreachable-code"
1414 /* For every compiler, either "sizeof(pthread_t) > sizeof(unsigned long)"
1415  * or not, so one of the two conditions will be unreachable by construction.
1416  * Unfortunately the C standard does not define a way to check this at
1417  * compile time, since the #if preprocessor conditions can not use the sizeof
1418  * operator as an argument. */
1419 #endif
1420 
1421  if (sizeof(pthread_t) > sizeof(unsigned long)) {
1422  /* This is the problematic case for CRYPTO_set_id_callback:
1423  * The OS pthread_t can not be cast to unsigned long. */
1424  struct mg_workerTLS *tls =
1425  (struct mg_workerTLS *)pthread_getspecific(sTlsKey);
1426  if (tls == NULL) {
1427  /* SSL called from an unknown thread: Create some thread index.
1428  */
1429  tls = (struct mg_workerTLS *)mg_malloc(sizeof(struct mg_workerTLS));
1430  tls->is_master = -2; /* -2 means "3rd party thread" */
1431  tls->thread_idx = (unsigned)mg_atomic_inc(&thread_idx_max);
1432  pthread_setspecific(sTlsKey, tls);
1433  }
1434  return tls->thread_idx;
1435  } else {
1436  /* pthread_t may be any data type, so a simple cast to unsigned long
1437  * can rise a warning/error, depending on the platform.
1438  * Here memcpy is used as an anything-to-anything cast. */
1439  unsigned long ret = 0;
1440  pthread_t t = pthread_self();
1441  memcpy(&ret, &t, sizeof(pthread_t));
1442  return ret;
1443  }
1444 
1445 #ifdef __clang__
1446 #pragma clang diagnostic pop
1447 #endif
1448 
1449 #endif
1450 }
1451 
1452 
1454 static uint64_t
1456 {
1457  struct timespec tsnow;
1458  clock_gettime(CLOCK_REALTIME, &tsnow);
1459  return (((uint64_t)tsnow.tv_sec) * 1000000000) + (uint64_t)tsnow.tv_nsec;
1460 }
1461 
1462 
1463 #if defined(__GNUC__)
1464 /* Show no warning in case system functions are not used. */
1465 #if GCC_VERSION >= 40500
1466 #pragma GCC diagnostic pop
1467 #endif /* GCC_VERSION >= 40500 */
1468 #endif /* defined(__GNUC__) */
1469 #if defined(__clang__)
1470 /* Show no warning in case system functions are not used. */
1471 #pragma clang diagnostic pop
1472 #endif
1473 
1474 
1475 #if !defined(DEBUG_TRACE)
1476 #if defined(DEBUG)
1477 static void DEBUG_TRACE_FUNC(const char *func,
1478  unsigned line,
1479  PRINTF_FORMAT_STRING(const char *fmt),
1480  ...) PRINTF_ARGS(3, 4);
1481 
1482 static void
1483 DEBUG_TRACE_FUNC(const char *func, unsigned line, const char *fmt, ...)
1484 {
1485  va_list args;
1486  uint64_t nsnow;
1487  static uint64_t nslast;
1488  struct timespec tsnow;
1489 
1490  /* Get some operating system independent thread id */
1491  unsigned long thread_id = mg_current_thread_id();
1492 
1493  clock_gettime(CLOCK_REALTIME, &tsnow);
1494  nsnow = ((uint64_t)tsnow.tv_sec) * ((uint64_t)1000000000)
1495  + ((uint64_t)tsnow.tv_nsec);
1496 
1497  if (!nslast) {
1498  nslast = nsnow;
1499  }
1500 
1501  flockfile(stdout);
1502  printf("*** %lu.%09lu %12" INT64_FMT " %lu %s:%u: ",
1503  (unsigned long)tsnow.tv_sec,
1504  (unsigned long)tsnow.tv_nsec,
1505  nsnow - nslast,
1506  thread_id,
1507  func,
1508  line);
1509  va_start(args, fmt);
1510  vprintf(fmt, args);
1511  va_end(args);
1512  putchar('\n');
1513  fflush(stdout);
1514  funlockfile(stdout);
1515  nslast = nsnow;
1516 }
1517 
1518 #define DEBUG_TRACE(fmt, ...) \
1519  DEBUG_TRACE_FUNC(__func__, __LINE__, fmt, __VA_ARGS__)
1520 
1521 #else
1522 #define DEBUG_TRACE(fmt, ...) \
1523  do { \
1524  } while (0)
1525 #endif /* DEBUG */
1526 #endif /* DEBUG_TRACE */
1527 
1528 
1529 #define MD5_STATIC static
1530 #include "md5.inl"
1531 
1532 /* Darwin prior to 7.0 and Win32 do not have socklen_t */
1533 #ifdef NO_SOCKLEN_T
1534 typedef int socklen_t;
1535 #endif /* NO_SOCKLEN_T */
1536 #define _DARWIN_UNLIMITED_SELECT
1537 
1538 #define IP_ADDR_STR_LEN (50) /* IPv6 hex string is 46 chars */
1539 
1540 #if !defined(MSG_NOSIGNAL)
1541 #define MSG_NOSIGNAL (0)
1542 #endif
1543 
1544 #if !defined(SOMAXCONN)
1545 #define SOMAXCONN (100)
1546 #endif
1547 
1548 /* Size of the accepted socket queue */
1549 #if !defined(MGSQLEN)
1550 #define MGSQLEN (20)
1551 #endif
1552 
1553 
1554 #if defined(NO_SSL)
1555 typedef struct SSL SSL; /* dummy for SSL argument to push/pull */
1556 typedef struct SSL_CTX SSL_CTX;
1557 #else
1558 #if defined(NO_SSL_DL)
1559 #include <openssl/ssl.h>
1560 #include <openssl/err.h>
1561 #include <openssl/crypto.h>
1562 #include <openssl/x509.h>
1563 #include <openssl/pem.h>
1564 #include <openssl/engine.h>
1565 #include <openssl/conf.h>
1566 #include <openssl/dh.h>
1567 #include <openssl/bn.h>
1568 #include <openssl/opensslv.h>
1569 #else
1570 
1571 /* SSL loaded dynamically from DLL.
1572  * I put the prototypes here to be independent from OpenSSL source
1573  * installation. */
1574 
1575 typedef struct ssl_st SSL;
1576 typedef struct ssl_method_st SSL_METHOD;
1577 typedef struct ssl_ctx_st SSL_CTX;
1578 typedef struct x509_store_ctx_st X509_STORE_CTX;
1579 typedef struct x509_name X509_NAME;
1580 typedef struct asn1_integer ASN1_INTEGER;
1581 typedef struct bignum BIGNUM;
1582 typedef struct ossl_init_settings_st OPENSSL_INIT_SETTINGS;
1583 typedef struct evp_md EVP_MD;
1584 typedef struct x509 X509;
1585 
1586 
1587 #define SSL_CTRL_OPTIONS (32)
1588 #define SSL_CTRL_CLEAR_OPTIONS (77)
1589 #define SSL_CTRL_SET_ECDH_AUTO (94)
1590 
1591 #define OPENSSL_INIT_NO_LOAD_SSL_STRINGS 0x00100000L
1592 #define OPENSSL_INIT_LOAD_SSL_STRINGS 0x00200000L
1593 #define OPENSSL_INIT_LOAD_CRYPTO_STRINGS 0x00000002L
1594 
1595 #define SSL_VERIFY_NONE (0)
1596 #define SSL_VERIFY_PEER (1)
1597 #define SSL_VERIFY_FAIL_IF_NO_PEER_CERT (2)
1598 #define SSL_VERIFY_CLIENT_ONCE (4)
1599 #define SSL_OP_ALL ((long)(0x80000BFFUL))
1600 #define SSL_OP_NO_SSLv2 (0x01000000L)
1601 #define SSL_OP_NO_SSLv3 (0x02000000L)
1602 #define SSL_OP_NO_TLSv1 (0x04000000L)
1603 #define SSL_OP_NO_TLSv1_2 (0x08000000L)
1604 #define SSL_OP_NO_TLSv1_1 (0x10000000L)
1605 #define SSL_OP_SINGLE_DH_USE (0x00100000L)
1606 #define SSL_OP_CIPHER_SERVER_PREFERENCE (0x00400000L)
1607 #define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION (0x00010000L)
1608 #define SSL_OP_NO_COMPRESSION (0x00020000L)
1609 
1610 #define SSL_CB_HANDSHAKE_START (0x10)
1611 #define SSL_CB_HANDSHAKE_DONE (0x20)
1612 
1613 #define SSL_ERROR_NONE (0)
1614 #define SSL_ERROR_SSL (1)
1615 #define SSL_ERROR_WANT_READ (2)
1616 #define SSL_ERROR_WANT_WRITE (3)
1617 #define SSL_ERROR_WANT_X509_LOOKUP (4)
1618 #define SSL_ERROR_SYSCALL (5) /* see errno */
1619 #define SSL_ERROR_ZERO_RETURN (6)
1620 #define SSL_ERROR_WANT_CONNECT (7)
1621 #define SSL_ERROR_WANT_ACCEPT (8)
1622 
1623 
1624 struct ssl_func {
1625  const char *name; /* SSL function name */
1626  void (*ptr)(void); /* Function pointer */
1627 };
1628 
1629 
1630 #ifdef OPENSSL_API_1_1
1631 
1632 #define SSL_free (*(void (*)(SSL *))ssl_sw[0].ptr)
1633 #define SSL_accept (*(int (*)(SSL *))ssl_sw[1].ptr)
1634 #define SSL_connect (*(int (*)(SSL *))ssl_sw[2].ptr)
1635 #define SSL_read (*(int (*)(SSL *, void *, int))ssl_sw[3].ptr)
1636 #define SSL_write (*(int (*)(SSL *, const void *, int))ssl_sw[4].ptr)
1637 #define SSL_get_error (*(int (*)(SSL *, int))ssl_sw[5].ptr)
1638 #define SSL_set_fd (*(int (*)(SSL *, SOCKET))ssl_sw[6].ptr)
1639 #define SSL_new (*(SSL * (*)(SSL_CTX *))ssl_sw[7].ptr)
1640 #define SSL_CTX_new (*(SSL_CTX * (*)(SSL_METHOD *))ssl_sw[8].ptr)
1641 #define TLS_server_method (*(SSL_METHOD * (*)(void))ssl_sw[9].ptr)
1642 #define OPENSSL_init_ssl \
1643  (*(int (*)(uint64_t opts, \
1644  const OPENSSL_INIT_SETTINGS *settings))ssl_sw[10].ptr)
1645 #define SSL_CTX_use_PrivateKey_file \
1646  (*(int (*)(SSL_CTX *, const char *, int))ssl_sw[11].ptr)
1647 #define SSL_CTX_use_certificate_file \
1648  (*(int (*)(SSL_CTX *, const char *, int))ssl_sw[12].ptr)
1649 #define SSL_CTX_set_default_passwd_cb \
1650  (*(void (*)(SSL_CTX *, mg_callback_t))ssl_sw[13].ptr)
1651 #define SSL_CTX_free (*(void (*)(SSL_CTX *))ssl_sw[14].ptr)
1652 #define SSL_CTX_use_certificate_chain_file \
1653  (*(int (*)(SSL_CTX *, const char *))ssl_sw[15].ptr)
1654 #define TLS_client_method (*(SSL_METHOD * (*)(void))ssl_sw[16].ptr)
1655 #define SSL_pending (*(int (*)(SSL *))ssl_sw[17].ptr)
1656 #define SSL_CTX_set_verify \
1657  (*(void (*)(SSL_CTX *, \
1658  int, \
1659  int (*verify_callback)(int, X509_STORE_CTX *)))ssl_sw[18].ptr)
1660 #define SSL_shutdown (*(int (*)(SSL *))ssl_sw[19].ptr)
1661 #define SSL_CTX_load_verify_locations \
1662  (*(int (*)(SSL_CTX *, const char *, const char *))ssl_sw[20].ptr)
1663 #define SSL_CTX_set_default_verify_paths (*(int (*)(SSL_CTX *))ssl_sw[21].ptr)
1664 #define SSL_CTX_set_verify_depth (*(void (*)(SSL_CTX *, int))ssl_sw[22].ptr)
1665 #define SSL_get_peer_certificate (*(X509 * (*)(SSL *))ssl_sw[23].ptr)
1666 #define SSL_get_version (*(const char *(*)(SSL *))ssl_sw[24].ptr)
1667 #define SSL_get_current_cipher (*(SSL_CIPHER * (*)(SSL *))ssl_sw[25].ptr)
1668 #define SSL_CIPHER_get_name \
1669  (*(const char *(*)(const SSL_CIPHER *))ssl_sw[26].ptr)
1670 #define SSL_CTX_check_private_key (*(int (*)(SSL_CTX *))ssl_sw[27].ptr)
1671 #define SSL_CTX_set_session_id_context \
1672  (*(int (*)(SSL_CTX *, const unsigned char *, unsigned int))ssl_sw[28].ptr)
1673 #define SSL_CTX_ctrl (*(long (*)(SSL_CTX *, int, long, void *))ssl_sw[29].ptr)
1674 #define SSL_CTX_set_cipher_list \
1675  (*(int (*)(SSL_CTX *, const char *))ssl_sw[30].ptr)
1676 #define SSL_CTX_set_options \
1677  (*(unsigned long (*)(SSL_CTX *, unsigned long))ssl_sw[31].ptr)
1678 #define SSL_CTX_set_info_callback \
1679  (*(void (*)(SSL_CTX * ctx, \
1680  void (*callback)(const SSL * s, int, int)))ssl_sw[32].ptr)
1681 #define SSL_get_ex_data (*(char *(*)(SSL *, int))ssl_sw[33].ptr)
1682 #define SSL_set_ex_data (*(void (*)(SSL *, int, char *))ssl_sw[34].ptr)
1683 
1684 #define SSL_CTX_clear_options(ctx, op) \
1685  SSL_CTX_ctrl((ctx), SSL_CTRL_CLEAR_OPTIONS, (op), NULL)
1686 #define SSL_CTX_set_ecdh_auto(ctx, onoff) \
1687  SSL_CTX_ctrl(ctx, SSL_CTRL_SET_ECDH_AUTO, onoff, NULL)
1688 
1689 #define X509_get_notBefore(x) ((x)->cert_info->validity->notBefore)
1690 #define X509_get_notAfter(x) ((x)->cert_info->validity->notAfter)
1691 
1692 #define SSL_set_app_data(s, arg) (SSL_set_ex_data(s, 0, (char *)arg))
1693 #define SSL_get_app_data(s) (SSL_get_ex_data(s, 0))
1694 
1695 #define ERR_get_error (*(unsigned long (*)(void))crypto_sw[0].ptr)
1696 #define ERR_error_string (*(char *(*)(unsigned long, char *))crypto_sw[1].ptr)
1697 #define ERR_remove_state (*(void (*)(unsigned long))crypto_sw[2].ptr)
1698 #define CONF_modules_unload (*(void (*)(int))crypto_sw[3].ptr)
1699 #define X509_free (*(void (*)(X509 *))crypto_sw[4].ptr)
1700 #define X509_get_subject_name (*(X509_NAME * (*)(X509 *))crypto_sw[5].ptr)
1701 #define X509_get_issuer_name (*(X509_NAME * (*)(X509 *))crypto_sw[6].ptr)
1702 #define X509_NAME_oneline \
1703  (*(char *(*)(X509_NAME *, char *, int))crypto_sw[7].ptr)
1704 #define X509_get_serialNumber (*(ASN1_INTEGER * (*)(X509 *))crypto_sw[8].ptr)
1705 #define EVP_get_digestbyname \
1706  (*(const EVP_MD *(*)(const char *))crypto_sw[9].ptr)
1707 #define EVP_Digest \
1708  (*(int (*)( \
1709  const void *, size_t, void *, unsigned int *, const EVP_MD *, void *)) \
1710  crypto_sw[10].ptr)
1711 #define i2d_X509 (*(int (*)(X509 *, unsigned char **))crypto_sw[11].ptr)
1712 #define BN_bn2hex (*(char *(*)(const BIGNUM *a))crypto_sw[12].ptr)
1713 #define ASN1_INTEGER_to_BN \
1714  (*(BIGNUM * (*)(const ASN1_INTEGER *ai, BIGNUM *bn))crypto_sw[13].ptr)
1715 #define BN_free (*(void (*)(const BIGNUM *a))crypto_sw[14].ptr)
1716 #define CRYPTO_free (*(void (*)(void *addr))crypto_sw[15].ptr)
1717 
1718 #define OPENSSL_free(a) CRYPTO_free(a)
1719 
1720 
1721 /* set_ssl_option() function updates this array.
1722  * It loads SSL library dynamically and changes NULLs to the actual addresses
1723  * of respective functions. The macros above (like SSL_connect()) are really
1724  * just calling these functions indirectly via the pointer. */
1725 static struct ssl_func ssl_sw[] = {{"SSL_free", NULL},
1726  {"SSL_accept", NULL},
1727  {"SSL_connect", NULL},
1728  {"SSL_read", NULL},
1729  {"SSL_write", NULL},
1730  {"SSL_get_error", NULL},
1731  {"SSL_set_fd", NULL},
1732  {"SSL_new", NULL},
1733  {"SSL_CTX_new", NULL},
1734  {"TLS_server_method", NULL},
1735  {"OPENSSL_init_ssl", NULL},
1736  {"SSL_CTX_use_PrivateKey_file", NULL},
1737  {"SSL_CTX_use_certificate_file", NULL},
1738  {"SSL_CTX_set_default_passwd_cb", NULL},
1739  {"SSL_CTX_free", NULL},
1740  {"SSL_CTX_use_certificate_chain_file", NULL},
1741  {"TLS_client_method", NULL},
1742  {"SSL_pending", NULL},
1743  {"SSL_CTX_set_verify", NULL},
1744  {"SSL_shutdown", NULL},
1745  {"SSL_CTX_load_verify_locations", NULL},
1746  {"SSL_CTX_set_default_verify_paths", NULL},
1747  {"SSL_CTX_set_verify_depth", NULL},
1748  {"SSL_get_peer_certificate", NULL},
1749  {"SSL_get_version", NULL},
1750  {"SSL_get_current_cipher", NULL},
1751  {"SSL_CIPHER_get_name", NULL},
1752  {"SSL_CTX_check_private_key", NULL},
1753  {"SSL_CTX_set_session_id_context", NULL},
1754  {"SSL_CTX_ctrl", NULL},
1755  {"SSL_CTX_set_cipher_list", NULL},
1756  {"SSL_CTX_set_options", NULL},
1757  {"SSL_CTX_set_info_callback", NULL},
1758  {"SSL_get_ex_data", NULL},
1759  {"SSL_set_ex_data", NULL},
1760  {NULL, NULL}};
1761 
1762 
1763 /* Similar array as ssl_sw. These functions could be located in different
1764  * lib. */
1765 static struct ssl_func crypto_sw[] = {{"ERR_get_error", NULL},
1766  {"ERR_error_string", NULL},
1767  {"ERR_remove_state", NULL},
1768  {"CONF_modules_unload", NULL},
1769  {"X509_free", NULL},
1770  {"X509_get_subject_name", NULL},
1771  {"X509_get_issuer_name", NULL},
1772  {"X509_NAME_oneline", NULL},
1773  {"X509_get_serialNumber", NULL},
1774  {"EVP_get_digestbyname", NULL},
1775  {"EVP_Digest", NULL},
1776  {"i2d_X509", NULL},
1777  {"BN_bn2hex", NULL},
1778  {"ASN1_INTEGER_to_BN", NULL},
1779  {"BN_free", NULL},
1780  {"CRYPTO_free", NULL},
1781  {NULL, NULL}};
1782 #else
1783 
1784 #define SSL_free (*(void (*)(SSL *))ssl_sw[0].ptr)
1785 #define SSL_accept (*(int (*)(SSL *))ssl_sw[1].ptr)
1786 #define SSL_connect (*(int (*)(SSL *))ssl_sw[2].ptr)
1787 #define SSL_read (*(int (*)(SSL *, void *, int))ssl_sw[3].ptr)
1788 #define SSL_write (*(int (*)(SSL *, const void *, int))ssl_sw[4].ptr)
1789 #define SSL_get_error (*(int (*)(SSL *, int))ssl_sw[5].ptr)
1790 #define SSL_set_fd (*(int (*)(SSL *, SOCKET))ssl_sw[6].ptr)
1791 #define SSL_new (*(SSL * (*)(SSL_CTX *))ssl_sw[7].ptr)
1792 #define SSL_CTX_new (*(SSL_CTX * (*)(SSL_METHOD *))ssl_sw[8].ptr)
1793 #define SSLv23_server_method (*(SSL_METHOD * (*)(void))ssl_sw[9].ptr)
1794 #define SSL_library_init (*(int (*)(void))ssl_sw[10].ptr)
1795 #define SSL_CTX_use_PrivateKey_file \
1796  (*(int (*)(SSL_CTX *, const char *, int))ssl_sw[11].ptr)
1797 #define SSL_CTX_use_certificate_file \
1798  (*(int (*)(SSL_CTX *, const char *, int))ssl_sw[12].ptr)
1799 #define SSL_CTX_set_default_passwd_cb \
1800  (*(void (*)(SSL_CTX *, mg_callback_t))ssl_sw[13].ptr)
1801 #define SSL_CTX_free (*(void (*)(SSL_CTX *))ssl_sw[14].ptr)
1802 #define SSL_load_error_strings (*(void (*)(void))ssl_sw[15].ptr)
1803 #define SSL_CTX_use_certificate_chain_file \
1804  (*(int (*)(SSL_CTX *, const char *))ssl_sw[16].ptr)
1805 #define SSLv23_client_method (*(SSL_METHOD * (*)(void))ssl_sw[17].ptr)
1806 #define SSL_pending (*(int (*)(SSL *))ssl_sw[18].ptr)
1807 #define SSL_CTX_set_verify \
1808  (*(void (*)(SSL_CTX *, \
1809  int, \
1810  int (*verify_callback)(int, X509_STORE_CTX *)))ssl_sw[19].ptr)
1811 #define SSL_shutdown (*(int (*)(SSL *))ssl_sw[20].ptr)
1812 #define SSL_CTX_load_verify_locations \
1813  (*(int (*)(SSL_CTX *, const char *, const char *))ssl_sw[21].ptr)
1814 #define SSL_CTX_set_default_verify_paths (*(int (*)(SSL_CTX *))ssl_sw[22].ptr)
1815 #define SSL_CTX_set_verify_depth (*(void (*)(SSL_CTX *, int))ssl_sw[23].ptr)
1816 #define SSL_get_peer_certificate (*(X509 * (*)(SSL *))ssl_sw[24].ptr)
1817 #define SSL_get_version (*(const char *(*)(SSL *))ssl_sw[25].ptr)
1818 #define SSL_get_current_cipher (*(SSL_CIPHER * (*)(SSL *))ssl_sw[26].ptr)
1819 #define SSL_CIPHER_get_name \
1820  (*(const char *(*)(const SSL_CIPHER *))ssl_sw[27].ptr)
1821 #define SSL_CTX_check_private_key (*(int (*)(SSL_CTX *))ssl_sw[28].ptr)
1822 #define SSL_CTX_set_session_id_context \
1823  (*(int (*)(SSL_CTX *, const unsigned char *, unsigned int))ssl_sw[29].ptr)
1824 #define SSL_CTX_ctrl (*(long (*)(SSL_CTX *, int, long, void *))ssl_sw[30].ptr)
1825 #define SSL_CTX_set_cipher_list \
1826  (*(int (*)(SSL_CTX *, const char *))ssl_sw[31].ptr)
1827 #define SSL_CTX_set_info_callback \
1828  (*(void (*)(SSL_CTX * ctx, \
1829  void (*callback)(const SSL * s, int, int)))ssl_sw[32].ptr)
1830 #define SSL_get_ex_data (*(char *(*)(SSL *, int))ssl_sw[33].ptr)
1831 #define SSL_set_ex_data (*(void (*)(SSL *, int, char *))ssl_sw[34].ptr)
1832 
1833 #define SSL_CTX_set_options(ctx, op) \
1834  SSL_CTX_ctrl((ctx), SSL_CTRL_OPTIONS, (op), NULL)
1835 #define SSL_CTX_clear_options(ctx, op) \
1836  SSL_CTX_ctrl((ctx), SSL_CTRL_CLEAR_OPTIONS, (op), NULL)
1837 #define SSL_CTX_set_ecdh_auto(ctx, onoff) \
1838  SSL_CTX_ctrl(ctx, SSL_CTRL_SET_ECDH_AUTO, onoff, NULL)
1839 
1840 
1841 #define X509_get_notBefore(x) ((x)->cert_info->validity->notBefore)
1842 #define X509_get_notAfter(x) ((x)->cert_info->validity->notAfter)
1843 
1844 #define SSL_set_app_data(s, arg) (SSL_set_ex_data(s, 0, (char *)arg))
1845 #define SSL_get_app_data(s) (SSL_get_ex_data(s, 0))
1846 
1847 #define CRYPTO_num_locks (*(int (*)(void))crypto_sw[0].ptr)
1848 #define CRYPTO_set_locking_callback \
1849  (*(void (*)(void (*)(int, int, const char *, int)))crypto_sw[1].ptr)
1850 #define CRYPTO_set_id_callback \
1851  (*(void (*)(unsigned long (*)(void)))crypto_sw[2].ptr)
1852 #define ERR_get_error (*(unsigned long (*)(void))crypto_sw[3].ptr)
1853 #define ERR_error_string (*(char *(*)(unsigned long, char *))crypto_sw[4].ptr)
1854 #define ERR_remove_state (*(void (*)(unsigned long))crypto_sw[5].ptr)
1855 #define ERR_free_strings (*(void (*)(void))crypto_sw[6].ptr)
1856 #define ENGINE_cleanup (*(void (*)(void))crypto_sw[7].ptr)
1857 #define CONF_modules_unload (*(void (*)(int))crypto_sw[8].ptr)
1858 #define CRYPTO_cleanup_all_ex_data (*(void (*)(void))crypto_sw[9].ptr)
1859 #define EVP_cleanup (*(void (*)(void))crypto_sw[10].ptr)
1860 #define X509_free (*(void (*)(X509 *))crypto_sw[11].ptr)
1861 #define X509_get_subject_name (*(X509_NAME * (*)(X509 *))crypto_sw[12].ptr)
1862 #define X509_get_issuer_name (*(X509_NAME * (*)(X509 *))crypto_sw[13].ptr)
1863 #define X509_NAME_oneline \
1864  (*(char *(*)(X509_NAME *, char *, int))crypto_sw[14].ptr)
1865 #define X509_get_serialNumber (*(ASN1_INTEGER * (*)(X509 *))crypto_sw[15].ptr)
1866 #define i2c_ASN1_INTEGER \
1867  (*(int (*)(ASN1_INTEGER *, unsigned char **))crypto_sw[16].ptr)
1868 #define EVP_get_digestbyname \
1869  (*(const EVP_MD *(*)(const char *))crypto_sw[17].ptr)
1870 #define EVP_Digest \
1871  (*(int (*)( \
1872  const void *, size_t, void *, unsigned int *, const EVP_MD *, void *)) \
1873  crypto_sw[18].ptr)
1874 #define i2d_X509 (*(int (*)(X509 *, unsigned char **))crypto_sw[19].ptr)
1875 #define BN_bn2hex (*(char *(*)(const BIGNUM *a))crypto_sw[20].ptr)
1876 #define ASN1_INTEGER_to_BN \
1877  (*(BIGNUM * (*)(const ASN1_INTEGER *ai, BIGNUM *bn))crypto_sw[21].ptr)
1878 #define BN_free (*(void (*)(const BIGNUM *a))crypto_sw[22].ptr)
1879 #define CRYPTO_free (*(void (*)(void *addr))crypto_sw[23].ptr)
1880 
1881 #define OPENSSL_free(a) CRYPTO_free(a)
1882 
1883 /* set_ssl_option() function updates this array.
1884  * It loads SSL library dynamically and changes NULLs to the actual addresses
1885  * of respective functions. The macros above (like SSL_connect()) are really
1886  * just calling these functions indirectly via the pointer. */
1887 static struct ssl_func ssl_sw[] = {{"SSL_free", NULL},
1888  {"SSL_accept", NULL},
1889  {"SSL_connect", NULL},
1890  {"SSL_read", NULL},
1891  {"SSL_write", NULL},
1892  {"SSL_get_error", NULL},
1893  {"SSL_set_fd", NULL},
1894  {"SSL_new", NULL},
1895  {"SSL_CTX_new", NULL},
1896  {"SSLv23_server_method", NULL},
1897  {"SSL_library_init", NULL},
1898  {"SSL_CTX_use_PrivateKey_file", NULL},
1899  {"SSL_CTX_use_certificate_file", NULL},
1900  {"SSL_CTX_set_default_passwd_cb", NULL},
1901  {"SSL_CTX_free", NULL},
1902  {"SSL_load_error_strings", NULL},
1903  {"SSL_CTX_use_certificate_chain_file", NULL},
1904  {"SSLv23_client_method", NULL},
1905  {"SSL_pending", NULL},
1906  {"SSL_CTX_set_verify", NULL},
1907  {"SSL_shutdown", NULL},
1908  {"SSL_CTX_load_verify_locations", NULL},
1909  {"SSL_CTX_set_default_verify_paths", NULL},
1910  {"SSL_CTX_set_verify_depth", NULL},
1911  {"SSL_get_peer_certificate", NULL},
1912  {"SSL_get_version", NULL},
1913  {"SSL_get_current_cipher", NULL},
1914  {"SSL_CIPHER_get_name", NULL},
1915  {"SSL_CTX_check_private_key", NULL},
1916  {"SSL_CTX_set_session_id_context", NULL},
1917  {"SSL_CTX_ctrl", NULL},
1918  {"SSL_CTX_set_cipher_list", NULL},
1919  {"SSL_CTX_set_info_callback", NULL},
1920  {"SSL_get_ex_data", NULL},
1921  {"SSL_set_ex_data", NULL},
1922  {NULL, NULL}};
1923 
1924 
1925 /* Similar array as ssl_sw. These functions could be located in different
1926  * lib. */
1927 static struct ssl_func crypto_sw[] = {{"CRYPTO_num_locks", NULL},
1928  {"CRYPTO_set_locking_callback", NULL},
1929  {"CRYPTO_set_id_callback", NULL},
1930  {"ERR_get_error", NULL},
1931  {"ERR_error_string", NULL},
1932  {"ERR_remove_state", NULL},
1933  {"ERR_free_strings", NULL},
1934  {"ENGINE_cleanup", NULL},
1935  {"CONF_modules_unload", NULL},
1936  {"CRYPTO_cleanup_all_ex_data", NULL},
1937  {"EVP_cleanup", NULL},
1938  {"X509_free", NULL},
1939  {"X509_get_subject_name", NULL},
1940  {"X509_get_issuer_name", NULL},
1941  {"X509_NAME_oneline", NULL},
1942  {"X509_get_serialNumber", NULL},
1943  {"i2c_ASN1_INTEGER", NULL},
1944  {"EVP_get_digestbyname", NULL},
1945  {"EVP_Digest", NULL},
1946  {"i2d_X509", NULL},
1947  {"BN_bn2hex", NULL},
1948  {"ASN1_INTEGER_to_BN", NULL},
1949  {"BN_free", NULL},
1950  {"CRYPTO_free", NULL},
1951  {NULL, NULL}};
1952 #endif /* OPENSSL_API_1_1 */
1953 #endif /* NO_SSL_DL */
1954 #endif /* NO_SSL */
1955 
1956 
1957 #if !defined(NO_CACHING)
1958 static const char *month_names[] = {"Jan",
1959  "Feb",
1960  "Mar",
1961  "Apr",
1962  "May",
1963  "Jun",
1964  "Jul",
1965  "Aug",
1966  "Sep",
1967  "Oct",
1968  "Nov",
1969  "Dec"};
1970 #endif /* !NO_CACHING */
1971 
1972 /* Unified socket address. For IPv6 support, add IPv6 address structure in
1973  * the
1974  * union u. */
1975 union usa {
1976  struct sockaddr sa;
1977  struct sockaddr_in sin;
1978 #if defined(USE_IPV6)
1979  struct sockaddr_in6 sin6;
1980 #endif
1981 };
1982 
1983 /* Describes a string (chunk of memory). */
1984 struct vec {
1985  const char *ptr;
1986  size_t len;
1987 };
1988 
1989 struct mg_file_stat {
1990  /* File properties filled by mg_stat: */
1991  uint64_t size;
1992  time_t last_modified;
1993  int is_directory; /* Set to 1 if mg_stat is called for a directory */
1994  int is_gzipped; /* Set to 1 if the content is gzipped, in which
1995  * case we need a "Content-Eencoding: gzip" header */
1996  int location; /* 0 = nowhere, 1 = on disk, 2 = in memory */
1997 };
1998 
1999 struct mg_file_in_memory {
2000  char *p;
2001  uint32_t pos;
2002  char mode;
2003 };
2004 
2005 struct mg_file_access {
2006  /* File properties filled by mg_fopen: */
2007  FILE *fp;
2008  /* TODO (low): Replace "membuf" implementation by a "file in memory"
2009  * support library. Use some struct mg_file_in_memory *mf; instead of
2010  * membuf char pointer. */
2011  const char *membuf;
2012 };
2013 
2014 struct mg_file {
2015  struct mg_file_stat stat;
2016  struct mg_file_access access;
2017 };
2018 
2019 #define STRUCT_FILE_INITIALIZER \
2020  { \
2021  { \
2022  (uint64_t)0, (time_t)0, 0, 0, 0 \
2023  } \
2024  , \
2025  { \
2026  (FILE *) NULL, (const char *)NULL \
2027  } \
2028  }
2029 
2030 /* Describes listening socket, or socket which was accept()-ed by the master
2031  * thread and queued for future handling by the worker thread. */
2032 struct socket {
2033  SOCKET sock; /* Listening socket */
2034  union usa lsa; /* Local socket address */
2035  union usa rsa; /* Remote socket address */
2036  unsigned char is_ssl; /* Is port SSL-ed */
2037  unsigned char ssl_redir; /* Is port supposed to redirect everything to SSL
2038  * port */
2039  unsigned char in_use; /* Is valid */
2040 };
2041 
2042 /* NOTE(lsm): this enum shoulds be in sync with the config_options below. */
2043 enum {
2080 
2081 #if defined(USE_WEBSOCKET)
2082  WEBSOCKET_TIMEOUT,
2083 #endif
2084 
2086 
2087 #if defined(USE_LUA)
2088  LUA_PRELOAD_FILE,
2089  LUA_SCRIPT_EXTENSIONS,
2090  LUA_SERVER_PAGE_EXTENSIONS,
2091 #endif
2092 #if defined(USE_DUKTAPE)
2093  DUKTAPE_SCRIPT_EXTENSIONS,
2094 #endif
2095 
2096 #if defined(USE_WEBSOCKET)
2097  WEBSOCKET_ROOT,
2098 #endif
2099 #if defined(USE_LUA) && defined(USE_WEBSOCKET)
2100  LUA_WEBSOCKET_EXTENSIONS,
2101 #endif
2102 
2107  CONFIG_TCP_NODELAY, /* Prepended CONFIG_ to avoid conflict with the
2108  * socket option typedef TCP_NODELAY. */
2109 #if !defined(NO_CACHING)
2111 #endif
2112 #if !defined(NO_SSL)
2114 #endif
2115 #if defined(__linux__)
2116  ALLOW_SENDFILE_CALL,
2117 #endif
2118 #if defined(_WIN32)
2119  CASE_SENSITIVE_FILES,
2120 #endif
2121 #if defined(USE_LUA)
2122  LUA_BACKGROUND_SCRIPT,
2123  LUA_BACKGROUND_SCRIPT_PARAMS,
2124 #endif
2128 
2130 };
2131 
2132 
2133 /* Config option name, config types, default value */
2134 static struct mg_option config_options[] = {
2135  {"cgi_pattern", CONFIG_TYPE_EXT_PATTERN, "**.cgi$|**.pl$|**.php$"},
2136  {"cgi_environment", CONFIG_TYPE_STRING_LIST, NULL},
2137  {"put_delete_auth_file", CONFIG_TYPE_FILE, NULL},
2138  {"cgi_interpreter", CONFIG_TYPE_FILE, NULL},
2139  {"protect_uri", CONFIG_TYPE_STRING_LIST, NULL},
2140  {"authentication_domain", CONFIG_TYPE_STRING, "mydomain.com"},
2141  {"enable_auth_domain_check", CONFIG_TYPE_BOOLEAN, "yes"},
2142  {"ssi_pattern", CONFIG_TYPE_EXT_PATTERN, "**.shtml$|**.shtm$"},
2143  {"throttle", CONFIG_TYPE_STRING_LIST, NULL},
2144  {"access_log_file", CONFIG_TYPE_FILE, NULL},
2145  {"enable_directory_listing", CONFIG_TYPE_BOOLEAN, "yes"},
2146  {"error_log_file", CONFIG_TYPE_FILE, NULL},
2147  {"global_auth_file", CONFIG_TYPE_FILE, NULL},
2148  {"index_files",
2150 #ifdef USE_LUA
2151  "index.xhtml,index.html,index.htm,"
2152  "index.lp,index.lsp,index.lua,index.cgi,"
2153  "index.shtml,index.php"},
2154 #else
2155  "index.xhtml,index.html,index.htm,index.cgi,index.shtml,index.php"},
2156 #endif
2157  {"enable_keep_alive", CONFIG_TYPE_BOOLEAN, "no"},
2158  {"access_control_list", CONFIG_TYPE_STRING_LIST, NULL},
2159  {"extra_mime_types", CONFIG_TYPE_STRING_LIST, NULL},
2160  {"listening_ports", CONFIG_TYPE_STRING_LIST, "8080"},
2161  {"document_root", CONFIG_TYPE_DIRECTORY, NULL},
2162  {"ssl_certificate", CONFIG_TYPE_FILE, NULL},
2163  {"ssl_certificate_chain", CONFIG_TYPE_FILE, NULL},
2164  {"num_threads", CONFIG_TYPE_NUMBER, "50"},
2165  {"run_as_user", CONFIG_TYPE_STRING, NULL},
2166  {"url_rewrite_patterns", CONFIG_TYPE_STRING_LIST, NULL},
2167  {"hide_files_patterns", CONFIG_TYPE_EXT_PATTERN, NULL},
2168  {"request_timeout_ms", CONFIG_TYPE_NUMBER, "30000"},
2169  {"keep_alive_timeout_ms", CONFIG_TYPE_NUMBER, "500"},
2170  {"linger_timeout_ms", CONFIG_TYPE_NUMBER, NULL},
2171 
2172  /* TODO(Feature): this is no longer a boolean, but yes/no/optional */
2173  {"ssl_verify_peer", CONFIG_TYPE_BOOLEAN, "no"},
2174 
2175  {"ssl_ca_path", CONFIG_TYPE_DIRECTORY, NULL},
2176  {"ssl_ca_file", CONFIG_TYPE_FILE, NULL},
2177  {"ssl_verify_depth", CONFIG_TYPE_NUMBER, "9"},
2178  {"ssl_default_verify_paths", CONFIG_TYPE_BOOLEAN, "yes"},
2179  {"ssl_cipher_list", CONFIG_TYPE_STRING, NULL},
2180  {"ssl_protocol_version", CONFIG_TYPE_NUMBER, "0"},
2181  {"ssl_short_trust", CONFIG_TYPE_BOOLEAN, "no"},
2182 #if defined(USE_WEBSOCKET)
2183  {"websocket_timeout_ms", CONFIG_TYPE_NUMBER, "30000"},
2184 #endif
2185  {"decode_url", CONFIG_TYPE_BOOLEAN, "yes"},
2186 
2187 #if defined(USE_LUA)
2188  {"lua_preload_file", CONFIG_TYPE_FILE, NULL},
2189  {"lua_script_pattern", CONFIG_TYPE_EXT_PATTERN, "**.lua$"},
2190  {"lua_server_page_pattern", CONFIG_TYPE_EXT_PATTERN, "**.lp$|**.lsp$"},
2191 #endif
2192 #if defined(USE_DUKTAPE)
2193  /* The support for duktape is still in alpha version state.
2194  * The name of this config option might change. */
2195  {"duktape_script_pattern", CONFIG_TYPE_EXT_PATTERN, "**.ssjs$"},
2196 #endif
2197 
2198 #if defined(USE_WEBSOCKET)
2199  {"websocket_root", CONFIG_TYPE_DIRECTORY, NULL},
2200 #endif
2201 #if defined(USE_LUA) && defined(USE_WEBSOCKET)
2202  {"lua_websocket_pattern", CONFIG_TYPE_EXT_PATTERN, "**.lua$"},
2203 #endif
2204  {"access_control_allow_origin", CONFIG_TYPE_STRING, "*"},
2205  {"access_control_allow_methods", CONFIG_TYPE_STRING, "*"},
2206  {"access_control_allow_headers", CONFIG_TYPE_STRING, "*"},
2207  {"error_pages", CONFIG_TYPE_DIRECTORY, NULL},
2208  {"tcp_nodelay", CONFIG_TYPE_NUMBER, "0"},
2209 #if !defined(NO_CACHING)
2210  {"static_file_max_age", CONFIG_TYPE_NUMBER, "3600"},
2211 #endif
2212 #if !defined(NO_SSL)
2213  {"strict_transport_security_max_age", CONFIG_TYPE_NUMBER, NULL},
2214 #endif
2215 #if defined(__linux__)
2216  {"allow_sendfile_call", CONFIG_TYPE_BOOLEAN, "yes"},
2217 #endif
2218 #if defined(_WIN32)
2219  {"case_sensitive", CONFIG_TYPE_BOOLEAN, "no"},
2220 #endif
2221 #if defined(USE_LUA)
2222  {"lua_background_script", CONFIG_TYPE_FILE, NULL},
2223  {"lua_background_script_params", CONFIG_TYPE_STRING_LIST, NULL},
2224 #endif
2225  {"additional_header", CONFIG_TYPE_STRING_MULTILINE, NULL},
2226  {"max_request_size", CONFIG_TYPE_NUMBER, "16384"},
2227  {"allow_index_script_resource", CONFIG_TYPE_BOOLEAN, "no"},
2228 
2229  {NULL, CONFIG_TYPE_UNKNOWN, NULL}};
2230 
2231 
2232 /* Check if the config_options and the corresponding enum have compatible
2233  * sizes. */
2234 mg_static_assert((sizeof(config_options) / sizeof(config_options[0]))
2235  == (NUM_OPTIONS + 1),
2236  "config_options and enum not sync");
2237 
2238 
2240 
2241 
2242 struct mg_handler_info {
2243  /* Name/Pattern of the URI. */
2244  char *uri;
2245  size_t uri_len;
2246 
2247  /* handler type */
2248  int handler_type;
2249 
2250  /* Handler for http/https or authorization requests. */
2251  mg_request_handler handler;
2252 
2253  /* Handler for ws/wss (websocket) requests. */
2254  mg_websocket_connect_handler connect_handler;
2255  mg_websocket_ready_handler ready_handler;
2256  mg_websocket_data_handler data_handler;
2257  mg_websocket_close_handler close_handler;
2258 
2259  /* accepted subprotocols for ws/wss requests. */
2261 
2262  /* Handler for authorization requests */
2263  mg_authorization_handler auth_handler;
2264 
2265  /* User supplied argument for the handler function. */
2266  void *cbdata;
2267 
2268  /* next handler in a linked list */
2269  struct mg_handler_info *next;
2270 };
2271 
2272 
2273 enum {
2278 };
2279 
2280 
2281 struct mg_context {
2282  volatile int stop_flag; /* Should we stop event loop */
2283  SSL_CTX *ssl_ctx; /* SSL context */
2284  char *config[NUM_OPTIONS]; /* Civetweb configuration parameters */
2285  struct mg_callbacks callbacks; /* User-defined callback function */
2286  void *user_data; /* User-defined data */
2287  int context_type; /* See CONTEXT_* above */
2288 
2289  struct socket *listening_sockets;
2290  struct pollfd *listening_socket_fds;
2291  unsigned int num_listening_sockets;
2292 
2293  pthread_mutex_t thread_mutex; /* Protects (max|num)_threads */
2294 
2295 #ifdef ALTERNATIVE_QUEUE
2296  struct socket *client_socks;
2297  void **client_wait_events;
2298 #else
2299  struct socket queue[MGSQLEN]; /* Accepted sockets */
2300  volatile int sq_head; /* Head of the socket queue */
2301  volatile int sq_tail; /* Tail of the socket queue */
2302  pthread_cond_t sq_full; /* Signaled when socket is produced */
2303  pthread_cond_t sq_empty; /* Signaled when socket is consumed */
2304 #endif
2305 
2306  unsigned int max_request_size; /* The max request size */
2307 
2308  pthread_t masterthreadid; /* The master thread ID */
2309  unsigned int
2310  cfg_worker_threads; /* The number of configured worker threads. */
2311  pthread_t *worker_threadids; /* The worker thread IDs */
2312  struct mg_connection *worker_connections; /* The connection struct, pre-
2313  * allocated for each worker */
2314 
2315  time_t start_time; /* Server start time, used for authentication
2316  * and for diagnstics. */
2317 
2318  uint64_t auth_nonce_mask; /* Mask for all nonce values */
2319  pthread_mutex_t nonce_mutex; /* Protects nonce_count */
2320  unsigned long nonce_count; /* Used nonces, used for authentication */
2321 
2322  char *systemName; /* What operating system is running */
2323 
2324  /* linked list of uri handlers */
2325  struct mg_handler_info *handlers;
2326 
2327 #if defined(USE_LUA) && defined(USE_WEBSOCKET)
2328  /* linked list of shared lua websockets */
2329  struct mg_shared_lua_websocket_list *shared_lua_websockets;
2330 #endif
2331 
2332 #if defined(USE_TIMERS)
2333  struct ttimers *timers;
2334 #endif
2335 
2336 #if defined(USE_LUA)
2337  void *lua_background_state;
2338 #endif
2339 
2340 #if defined(USE_SERVER_STATS)
2341  int active_connections;
2342  int max_connections;
2343  int64_t total_connections;
2344  int64_t total_requests;
2345  struct mg_memory_stat ctx_memory;
2346  int64_t total_data_read;
2347  int64_t total_data_written;
2348 #endif
2349 };
2350 
2351 
2352 #if defined(USE_SERVER_STATS)
2353 static struct mg_memory_stat mg_common_memory = {0, 0, 0};
2354 
2355 static struct mg_memory_stat *
2356 get_memory_stat(struct mg_context *ctx)
2357 {
2358  if (ctx) {
2359  return &(ctx->ctx_memory);
2360  }
2361  return &mg_common_memory;
2362 }
2363 #endif
2364 
2365 enum {
2369 };
2370 
2371 struct mg_connection {
2372  int connection_type; /* see CONNECTION_TYPE_* above */
2373 
2374  struct mg_request_info request_info;
2375  struct mg_response_info response_info;
2376 
2377  struct mg_context *ctx;
2378 
2379 #if defined(USE_SERVER_STATS)
2380  int conn_state; /* 0 = undef, numerical value may change in different
2381  * versions. For the current definition, see
2382  * mg_get_connection_info_impl */
2383 #endif
2384 
2385  SSL *ssl; /* SSL descriptor */
2386  SSL_CTX *client_ssl_ctx; /* SSL context for client connections */
2387  struct socket client; /* Connected client */
2388  time_t conn_birth_time; /* Time (wall clock) when connection was
2389  * established */
2390  struct timespec req_time; /* Time (since system start) when the request
2391  * was received */
2392  int64_t num_bytes_sent; /* Total bytes sent to client */
2393  int64_t content_len; /* Content-Length header value */
2394  int64_t consumed_content; /* How many bytes of content have been read */
2395  int is_chunked; /* Transfer-Encoding is chunked:
2396  * 0 = not chunked,
2397  * 1 = chunked, do data read yet,
2398  * 2 = chunked, some data read,
2399  * 3 = chunked, all data read
2400  */
2401  size_t chunk_remainder; /* Unread data from the last chunk */
2402  char *buf; /* Buffer for received data */
2403  char *path_info; /* PATH_INFO part of the URL */
2404 
2405  int must_close; /* 1 if connection must be closed */
2406  int accept_gzip; /* 1 if gzip encoding is accepted */
2407  int in_error_handler; /* 1 if in handler for user defined error
2408  * pages */
2409 #if defined(USE_WEBSOCKET)
2410  int in_websocket_handling; /* 1 if in read_websocket */
2411 #endif
2412  int handled_requests; /* Number of requests handled by this connection
2413  */
2414  int buf_size; /* Buffer size */
2415  int request_len; /* Size of the request + headers in a buffer */
2416  int data_len; /* Total size of data in a buffer */
2417  int status_code; /* HTTP reply status code, e.g. 200 */
2418  int throttle; /* Throttling, bytes/sec. <= 0 means no
2419  * throttle */
2420 
2421  time_t last_throttle_time; /* Last time throttled data was sent */
2422  int64_t last_throttle_bytes; /* Bytes sent this second */
2423  pthread_mutex_t mutex; /* Used by mg_(un)lock_connection to ensure
2424  * atomic transmissions for websockets */
2425 #if defined(USE_LUA) && defined(USE_WEBSOCKET)
2426  void *lua_websocket_state; /* Lua_State for a websocket connection */
2427 #endif
2428 
2429  int thread_index; /* Thread index within ctx */
2430 };
2431 
2432 
2433 /* Directory entry */
2434 struct de {
2435  struct mg_connection *conn;
2436  char *file_name;
2437  struct mg_file_stat file;
2438 };
2439 
2440 
2441 #if defined(USE_WEBSOCKET)
2442 static int is_websocket_protocol(const struct mg_connection *conn);
2443 #else
2444 #define is_websocket_protocol(conn) (0)
2445 #endif
2446 
2447 
2448 #if !defined(NO_THREAD_NAME)
2449 #if defined(_WIN32) && defined(_MSC_VER)
2450 /* Set the thread name for debugging purposes in Visual Studio
2451  * http://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx
2452  */
2453 #pragma pack(push, 8)
2454 typedef struct tagTHREADNAME_INFO {
2455  DWORD dwType; /* Must be 0x1000. */
2456  LPCSTR szName; /* Pointer to name (in user addr space). */
2457  DWORD dwThreadID; /* Thread ID (-1=caller thread). */
2458  DWORD dwFlags; /* Reserved for future use, must be zero. */
2459 } THREADNAME_INFO;
2460 #pragma pack(pop)
2461 
2462 #elif defined(__linux__)
2463 
2464 #include <sys/prctl.h>
2465 #include <sys/sendfile.h>
2466 #ifdef ALTERNATIVE_QUEUE
2467 #include <sys/eventfd.h>
2468 #endif /* ALTERNATIVE_QUEUE */
2469 
2470 
2471 #if defined(ALTERNATIVE_QUEUE)
2472 
2473 
2474 #ifdef __clang__
2475 #pragma clang diagnostic push
2476 #pragma clang diagnostic ignored "-Wunreachable-code"
2477 /* For every system, "(sizeof(int) == sizeof(void *))" is either always
2478  * true or always false. One of the two branches is unreachable in any case.
2479  * Unfortunately the C standard does not define a way to check this at
2480  * compile time, since the #if preprocessor conditions can not use the sizeof
2481  * operator as an argument. */
2482 #endif
2483 
2484 #if defined(__GNUC__) || defined(__MINGW32__)
2485 /* GCC does not realize one branch is unreachable, so it raises some
2486  * pointer cast warning within the unreachable branch.
2487  */
2488 #pragma GCC diagnostic push
2489 #pragma GCC diagnostic ignored "-Wint-to-pointer-cast"
2490 #pragma GCC diagnostic ignored "-Wpointer-to-int-cast"
2491 #endif
2492 
2493 
2494 static void *
2495 event_create(void)
2496 {
2497  int evhdl = eventfd(0, EFD_CLOEXEC);
2498  int *ret;
2499 
2500  if (evhdl == -1) {
2501  /* Linux uses -1 on error, Windows NULL. */
2502  /* However, Linux does not return 0 on success either. */
2503  return 0;
2504  }
2505  if (sizeof(int) == sizeof(void *)) {
2506  ret = (void *)evhdl;
2507  } else {
2508  ret = (int *)mg_malloc(sizeof(int));
2509  if (ret) {
2510  *ret = evhdl;
2511  } else {
2512  (void)close(evhdl);
2513  }
2514  }
2515 
2516  return (void *)ret;
2517 }
2518 
2519 
2520 static int
2521 event_wait(void *eventhdl)
2522 {
2523  uint64_t u;
2524  int evhdl, s;
2525 
2526  if (sizeof(int) == sizeof(void *)) {
2527  evhdl = (int)eventhdl;
2528  } else {
2529  if (!eventhdl) {
2530  /* error */
2531  return 0;
2532  }
2533  evhdl = *(int *)eventhdl;
2534  }
2535 
2536  s = (int)read(evhdl, &u, sizeof(u));
2537  if (s != sizeof(uint64_t)) {
2538  /* error */
2539  return 0;
2540  }
2541  (void)u; /* the value is not required */
2542  return 1;
2543 }
2544 
2545 
2546 static int
2547 event_signal(void *eventhdl)
2548 {
2549  uint64_t u = 1;
2550  int evhdl, s;
2551 
2552  if (sizeof(int) == sizeof(void *)) {
2553  evhdl = (int)eventhdl;
2554  } else {
2555  if (!eventhdl) {
2556  /* error */
2557  return 0;
2558  }
2559  evhdl = *(int *)eventhdl;
2560  }
2561 
2562  s = (int)write(evhdl, &u, sizeof(u));
2563  if (s != sizeof(uint64_t)) {
2564  /* error */
2565  return 0;
2566  }
2567  return 1;
2568 }
2569 
2570 
2571 static void
2572 event_destroy(void *eventhdl)
2573 {
2574  int evhdl;
2575 
2576  if (sizeof(int) == sizeof(void *)) {
2577  evhdl = (int)eventhdl;
2578  close(evhdl);
2579  } else {
2580  if (!eventhdl) {
2581  /* error */
2582  return;
2583  }
2584  evhdl = *(int *)eventhdl;
2585  close(evhdl);
2586  mg_free(eventhdl);
2587  }
2588 }
2589 
2590 
2591 #if defined(__GNUC__) || defined(__MINGW32__)
2592 #pragma GCC diagnostic pop
2593 #endif
2594 
2595 #ifdef __clang__
2596 #pragma clang diagnostic pop
2597 #endif
2598 
2599 #endif
2600 
2601 #endif
2602 
2603 
2604 #if !defined(__linux__) && !defined(_WIN32) && defined(ALTERNATIVE_QUEUE)
2605 
2606 struct posix_event {
2607  pthread_mutex_t mutex;
2608  pthread_cond_t cond;
2609 };
2610 
2611 
2612 static void *
2614 {
2615  struct posix_event *ret = mg_malloc(sizeof(struct posix_event));
2616  if (ret == 0) {
2617  /* out of memory */
2618  return 0;
2619  }
2620  if (0 != pthread_mutex_init(&(ret->mutex), NULL)) {
2621  /* pthread mutex not available */
2622  mg_free(ret);
2623  return 0;
2624  }
2625  if (0 != pthread_cond_init(&(ret->cond), NULL)) {
2626  /* pthread cond not available */
2627  pthread_mutex_destroy(&(ret->mutex));
2628  mg_free(ret);
2629  return 0;
2630  }
2631  return (void *)ret;
2632 }
2633 
2634 
2635 static int
2636 event_wait(void *eventhdl)
2637 {
2638  struct posix_event *ev = (struct posix_event *)eventhdl;
2639  pthread_mutex_lock(&(ev->mutex));
2640  pthread_cond_wait(&(ev->cond), &(ev->mutex));
2641  pthread_mutex_unlock(&(ev->mutex));
2642  return 1;
2643 }
2644 
2645 
2646 static int
2647 event_signal(void *eventhdl)
2648 {
2649  struct posix_event *ev = (struct posix_event *)eventhdl;
2650  pthread_mutex_lock(&(ev->mutex));
2651  pthread_cond_signal(&(ev->cond));
2652  pthread_mutex_unlock(&(ev->mutex));
2653  return 1;
2654 }
2655 
2656 
2657 static void
2658 event_destroy(void *eventhdl)
2659 {
2660  struct posix_event *ev = (struct posix_event *)eventhdl;
2661  pthread_cond_destroy(&(ev->cond));
2662  pthread_mutex_destroy(&(ev->mutex));
2663  mg_free(ev);
2664 }
2665 #endif
2666 
2667 
2668 static void
2669 mg_set_thread_name(const char *name)
2670 {
2671  char threadName[16 + 1]; /* 16 = Max. thread length in Linux/OSX/.. */
2672 
2673  mg_snprintf(
2674  NULL, NULL, threadName, sizeof(threadName), "civetweb-%s", name);
2675 
2676 #if defined(_WIN32)
2677 #if defined(_MSC_VER)
2678  /* Windows and Visual Studio Compiler */
2679  __try
2680  {
2681  THREADNAME_INFO info;
2682  info.dwType = 0x1000;
2683  info.szName = threadName;
2684  info.dwThreadID = ~0U;
2685  info.dwFlags = 0;
2686 
2687  RaiseException(0x406D1388,
2688  0,
2689  sizeof(info) / sizeof(ULONG_PTR),
2690  (ULONG_PTR *)&info);
2691  }
2692  __except(EXCEPTION_EXECUTE_HANDLER)
2693  {
2694  }
2695 #elif defined(__MINGW32__)
2696 /* No option known to set thread name for MinGW */
2697 #endif
2698 #elif defined(_GNU_SOURCE) && defined(__GLIBC__) \
2699  && ((__GLIBC__ > 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 12)))
2700  /* pthread_setname_np first appeared in glibc in version 2.12*/
2701  (void)pthread_setname_np(pthread_self(), threadName);
2702 #elif defined(__linux__)
2703  /* on linux we can use the old prctl function */
2704  (void)prctl(PR_SET_NAME, threadName, 0, 0, 0);
2705 #endif
2706 }
2707 #else /* !defined(NO_THREAD_NAME) */
2708 void
2709 mg_set_thread_name(const char *threadName)
2710 {
2711 }
2712 #endif
2713 
2714 
2715 #if defined(MG_LEGACY_INTERFACE)
2716 const char **
2717 mg_get_valid_option_names(void)
2718 {
2719  /* This function is deprecated. Use mg_get_valid_options instead. */
2720  static const char *
2721  data[2 * sizeof(config_options) / sizeof(config_options[0])] = {0};
2722  int i;
2723 
2724  for (i = 0; config_options[i].name != NULL; i++) {
2725  data[i * 2] = config_options[i].name;
2726  data[i * 2 + 1] = config_options[i].default_value;
2727  }
2728 
2729  return data;
2730 }
2731 #endif
2732 
2733 
2734 const struct mg_option *
2736 {
2737  return config_options;
2738 }
2739 
2740 
2741 /* Do not open file (used in is_file_in_memory) */
2742 #define MG_FOPEN_MODE_NONE (0)
2743 
2744 /* Open file for read only access */
2745 #define MG_FOPEN_MODE_READ (1)
2746 
2747 /* Open file for writing, create and overwrite */
2748 #define MG_FOPEN_MODE_WRITE (2)
2749 
2750 /* Open file for writing, create and append */
2751 #define MG_FOPEN_MODE_APPEND (4)
2752 
2753 
2754 /* If a file is in memory, set all "stat" members and the membuf pointer of
2755  * output filep and return 1, otherwise return 0 and don't modify anything.
2756  */
2757 static int
2758 open_file_in_memory(const struct mg_connection *conn,
2759  const char *path,
2760  struct mg_file *filep,
2761  int mode)
2762 {
2763 #if defined(MG_USE_OPEN_FILE)
2764 
2765  size_t size = 0;
2766  const char *buf = NULL;
2767  if (!conn) {
2768  return 0;
2769  }
2770 
2771  if ((mode != MG_FOPEN_MODE_NONE) && (mode != MG_FOPEN_MODE_READ)) {
2772  return 0;
2773  }
2774 
2775  if (conn->ctx->callbacks.open_file) {
2776  buf = conn->ctx->callbacks.open_file(conn, path, &size);
2777  if (buf != NULL) {
2778  if (filep == NULL) {
2779  /* This is a file in memory, but we cannot store the
2780  * properties
2781  * now.
2782  * Called from "is_file_in_memory" function. */
2783  return 1;
2784  }
2785 
2786  /* NOTE: override filep->size only on success. Otherwise, it
2787  * might
2788  * break constructs like if (!mg_stat() || !mg_fopen()) ... */
2789  filep->access.membuf = buf;
2790  filep->access.fp = NULL;
2791 
2792  /* Size was set by the callback */
2793  filep->stat.size = size;
2794 
2795  /* Assume the data may change during runtime by setting
2796  * last_modified = now */
2797  filep->stat.last_modified = time(NULL);
2798 
2799  filep->stat.is_directory = 0;
2800  filep->stat.is_gzipped = 0;
2801  }
2802  }
2803 
2804  return (buf != NULL);
2805 
2806 #else
2807  (void)conn;
2808  (void)path;
2809  (void)filep;
2810  (void)mode;
2811 
2812  return 0;
2813 
2814 #endif
2815 }
2816 
2817 
2818 static int
2819 is_file_in_memory(const struct mg_connection *conn, const char *path)
2820 {
2821  return open_file_in_memory(conn, path, NULL, MG_FOPEN_MODE_NONE);
2822 }
2823 
2824 
2825 static int
2826 is_file_opened(const struct mg_file_access *fileacc)
2827 {
2828  if (!fileacc) {
2829  return 0;
2830  }
2831  return (fileacc->membuf != NULL) || (fileacc->fp != NULL);
2832 }
2833 
2834 
2835 static int mg_stat(const struct mg_connection *conn,
2836  const char *path,
2837  struct mg_file_stat *filep);
2838 
2839 
2840 /* mg_fopen will open a file either in memory or on the disk.
2841  * The input parameter path is a string in UTF-8 encoding.
2842  * The input parameter mode is MG_FOPEN_MODE_*
2843  * On success, either fp or membuf will be set in the output
2844  * struct file. All status members will also be set.
2845  * The function returns 1 on success, 0 on error. */
2846 static int
2847 mg_fopen(const struct mg_connection *conn,
2848  const char *path,
2849  int mode,
2850  struct mg_file *filep)
2851 {
2852  int found;
2853 
2854  if (!filep) {
2855  return 0;
2856  }
2857  filep->access.fp = NULL;
2858  filep->access.membuf = NULL;
2859 
2860  if (!is_file_in_memory(conn, path)) {
2861 
2862  /* filep is initialized in mg_stat: all fields with memset to,
2863  * some fields like size and modification date with values */
2864  found = mg_stat(conn, path, &(filep->stat));
2865 
2866  if ((mode == MG_FOPEN_MODE_READ) && (!found)) {
2867  /* file does not exist and will not be created */
2868  return 0;
2869  }
2870 
2871 #ifdef _WIN32
2872  {
2873  wchar_t wbuf[PATH_MAX];
2874  path_to_unicode(conn, path, wbuf, ARRAY_SIZE(wbuf));
2875  switch (mode) {
2876  case MG_FOPEN_MODE_READ:
2877  filep->access.fp = _wfopen(wbuf, L"rb");
2878  break;
2879  case MG_FOPEN_MODE_WRITE:
2880  filep->access.fp = _wfopen(wbuf, L"wb");
2881  break;
2882  case MG_FOPEN_MODE_APPEND:
2883  filep->access.fp = _wfopen(wbuf, L"ab");
2884  break;
2885  }
2886  }
2887 #else
2888  /* Linux et al already use unicode. No need to convert. */
2889  switch (mode) {
2890  case MG_FOPEN_MODE_READ:
2891  filep->access.fp = fopen(path, "r");
2892  break;
2893  case MG_FOPEN_MODE_WRITE:
2894  filep->access.fp = fopen(path, "w");
2895  break;
2896  case MG_FOPEN_MODE_APPEND:
2897  filep->access.fp = fopen(path, "a");
2898  break;
2899  }
2900 
2901 #endif
2902  if (!found) {
2903  /* File did not exist before fopen was called.
2904  * Maybe it has been created now. Get stat info
2905  * like creation time now. */
2906  found = mg_stat(conn, path, &(filep->stat));
2907  (void)found;
2908  }
2909 
2910  /* file is on disk */
2911  return (filep->access.fp != NULL);
2912 
2913  } else {
2914  /* is_file_in_memory returned true */
2915  if (open_file_in_memory(conn, path, filep, mode)) {
2916  /* file is in memory */
2917  return (filep->access.membuf != NULL);
2918  }
2919  }
2920 
2921  /* Open failed */
2922  return 0;
2923 }
2924 
2925 
2926 /* return 0 on success, just like fclose */
2927 static int
2928 mg_fclose(struct mg_file_access *fileacc)
2929 {
2930  int ret = -1;
2931  if (fileacc != NULL) {
2932  if (fileacc->fp != NULL) {
2933  ret = fclose(fileacc->fp);
2934  } else if (fileacc->membuf != NULL) {
2935  ret = 0;
2936  }
2937  /* reset all members of fileacc */
2938  memset(fileacc, 0, sizeof(*fileacc));
2939  }
2940  return ret;
2941 }
2942 
2943 
2944 static void
2945 mg_strlcpy(register char *dst, register const char *src, size_t n)
2946 {
2947  for (; *src != '\0' && n > 1; n--) {
2948  *dst++ = *src++;
2949  }
2950  *dst = '\0';
2951 }
2952 
2953 
2954 static int
2955 lowercase(const char *s)
2956 {
2957  return tolower(*(const unsigned char *)s);
2958 }
2959 
2960 
2961 int
2962 mg_strncasecmp(const char *s1, const char *s2, size_t len)
2963 {
2964  int diff = 0;
2965 
2966  if (len > 0) {
2967  do {
2968  diff = lowercase(s1++) - lowercase(s2++);
2969  } while (diff == 0 && s1[-1] != '\0' && --len > 0);
2970  }
2971 
2972  return diff;
2973 }
2974 
2975 
2976 int
2977 mg_strcasecmp(const char *s1, const char *s2)
2978 {
2979  int diff;
2980 
2981  do {
2982  diff = lowercase(s1++) - lowercase(s2++);
2983  } while (diff == 0 && s1[-1] != '\0');
2984 
2985  return diff;
2986 }
2987 
2988 
2989 static char *
2990 mg_strndup(const char *ptr, size_t len)
2991 {
2992  char *p;
2993 
2994  if ((p = (char *)mg_malloc(len + 1)) != NULL) {
2995  mg_strlcpy(p, ptr, len + 1);
2996  }
2997 
2998  return p;
2999 }
3000 
3001 
3002 static char *
3003 mg_strdup(const char *str)
3004 {
3005  return mg_strndup(str, strlen(str));
3006 }
3007 
3008 
3009 static const char *
3010 mg_strcasestr(const char *big_str, const char *small_str)
3011 {
3012  size_t i, big_len = strlen(big_str), small_len = strlen(small_str);
3013 
3014  if (big_len >= small_len) {
3015  for (i = 0; i <= (big_len - small_len); i++) {
3016  if (mg_strncasecmp(big_str + i, small_str, small_len) == 0) {
3017  return big_str + i;
3018  }
3019  }
3020  }
3021 
3022  return NULL;
3023 }
3024 
3025 
3026 /* Return null terminated string of given maximum length.
3027  * Report errors if length is exceeded. */
3028 static void
3029 mg_vsnprintf(const struct mg_connection *conn,
3030  int *truncated,
3031  char *buf,
3032  size_t buflen,
3033  const char *fmt,
3034  va_list ap)
3035 {
3036  int n, ok;
3037 
3038  if (buflen == 0) {
3039  if (truncated) {
3040  *truncated = 1;
3041  }
3042  return;
3043  }
3044 
3045 #ifdef __clang__
3046 #pragma clang diagnostic push
3047 #pragma clang diagnostic ignored "-Wformat-nonliteral"
3048 /* Using fmt as a non-literal is intended here, since it is mostly called
3049  * indirectly by mg_snprintf */
3050 #endif
3051 
3052  n = (int)vsnprintf_impl(buf, buflen, fmt, ap);
3053  ok = (n >= 0) && ((size_t)n < buflen);
3054 
3055 #ifdef __clang__
3056 #pragma clang diagnostic pop
3057 #endif
3058 
3059  if (ok) {
3060  if (truncated) {
3061  *truncated = 0;
3062  }
3063  } else {
3064  if (truncated) {
3065  *truncated = 1;
3066  }
3067  mg_cry(conn,
3068  "truncating vsnprintf buffer: [%.*s]",
3069  (int)((buflen > 200) ? 200 : (buflen - 1)),
3070  buf);
3071  n = (int)buflen - 1;
3072  }
3073  buf[n] = '\0';
3074 }
3075 
3076 
3077 static void
3078 mg_snprintf(const struct mg_connection *conn,
3079  int *truncated,
3080  char *buf,
3081  size_t buflen,
3082  const char *fmt,
3083  ...)
3084 {
3085  va_list ap;
3086 
3087  va_start(ap, fmt);
3088  mg_vsnprintf(conn, truncated, buf, buflen, fmt, ap);
3089  va_end(ap);
3090 }
3091 
3092 
3093 static int
3094 get_option_index(const char *name)
3095 {
3096  int i;
3097 
3098  for (i = 0; config_options[i].name != NULL; i++) {
3099  if (strcmp(config_options[i].name, name) == 0) {
3100  return i;
3101  }
3102  }
3103  return -1;
3104 }
3105 
3106 
3107 const char *
3108 mg_get_option(const struct mg_context *ctx, const char *name)
3109 {
3110  int i;
3111  if ((i = get_option_index(name)) == -1) {
3112  return NULL;
3113  } else if (!ctx || ctx->config[i] == NULL) {
3114  return "";
3115  } else {
3116  return ctx->config[i];
3117  }
3118 }
3119 
3120 
3121 struct mg_context *
3122 mg_get_context(const struct mg_connection *conn)
3123 {
3124  return (conn == NULL) ? (struct mg_context *)NULL : (conn->ctx);
3125 }
3126 
3127 
3128 void *
3129 mg_get_user_data(const struct mg_context *ctx)
3130 {
3131  return (ctx == NULL) ? NULL : ctx->user_data;
3132 }
3133 
3134 
3135 void
3136 mg_set_user_connection_data(struct mg_connection *conn, void *data)
3137 {
3138  if (conn != NULL) {
3139  conn->request_info.conn_data = data;
3140  }
3141 }
3142 
3143 
3144 void *
3145 mg_get_user_connection_data(const struct mg_connection *conn)
3146 {
3147  if (conn != NULL) {
3148  return conn->request_info.conn_data;
3149  }
3150  return NULL;
3151 }
3152 
3153 
3154 #if defined(MG_LEGACY_INTERFACE)
3155 /* Deprecated: Use mg_get_server_ports instead. */
3156 size_t
3157 mg_get_ports(const struct mg_context *ctx, size_t size, int *ports, int *ssl)
3158 {
3159  size_t i;
3160  if (!ctx) {
3161  return 0;
3162  }
3163  for (i = 0; i < size && i < ctx->num_listening_sockets; i++) {
3164  ssl[i] = ctx->listening_sockets[i].is_ssl;
3165  ports[i] =
3166 #if defined(USE_IPV6)
3167  (ctx->listening_sockets[i].lsa.sa.sa_family == AF_INET6)
3168  ? ntohs(ctx->listening_sockets[i].lsa.sin6.sin6_port)
3169  :
3170 #endif
3171  ntohs(ctx->listening_sockets[i].lsa.sin.sin_port);
3172  }
3173  return i;
3174 }
3175 #endif
3176 
3177 
3178 int
3179 mg_get_server_ports(const struct mg_context *ctx,
3180  int size,
3181  struct mg_server_ports *ports)
3182 {
3183  int i, cnt = 0;
3184 
3185  if (size <= 0) {
3186  return -1;
3187  }
3188  memset(ports, 0, sizeof(*ports) * (size_t)size);
3189  if (!ctx) {
3190  return -1;
3191  }
3192  if (!ctx->listening_sockets) {
3193  return -1;
3194  }
3195 
3196  for (i = 0; (i < size) && (i < (int)ctx->num_listening_sockets); i++) {
3197 
3198  ports[cnt].port =
3199 #if defined(USE_IPV6)
3200  (ctx->listening_sockets[i].lsa.sa.sa_family == AF_INET6)
3201  ? ntohs(ctx->listening_sockets[i].lsa.sin6.sin6_port)
3202  :
3203 #endif
3204  ntohs(ctx->listening_sockets[i].lsa.sin.sin_port);
3205  ports[cnt].is_ssl = ctx->listening_sockets[i].is_ssl;
3206  ports[cnt].is_redirect = ctx->listening_sockets[i].ssl_redir;
3207 
3208  if (ctx->listening_sockets[i].lsa.sa.sa_family == AF_INET) {
3209  /* IPv4 */
3210  ports[cnt].protocol = 1;
3211  cnt++;
3212  } else if (ctx->listening_sockets[i].lsa.sa.sa_family == AF_INET6) {
3213  /* IPv6 */
3214  ports[cnt].protocol = 3;
3215  cnt++;
3216  }
3217  }
3218 
3219  return cnt;
3220 }
3221 
3222 
3223 static void
3224 sockaddr_to_string(char *buf, size_t len, const union usa *usa)
3225 {
3226  buf[0] = '\0';
3227 
3228  if (!usa) {
3229  return;
3230  }
3231 
3232  if (usa->sa.sa_family == AF_INET) {
3233  getnameinfo(&usa->sa,
3234  sizeof(usa->sin),
3235  buf,
3236  (unsigned)len,
3237  NULL,
3238  0,
3239  NI_NUMERICHOST);
3240  }
3241 #if defined(USE_IPV6)
3242  else if (usa->sa.sa_family == AF_INET6) {
3243  getnameinfo(&usa->sa,
3244  sizeof(usa->sin6),
3245  buf,
3246  (unsigned)len,
3247  NULL,
3248  0,
3249  NI_NUMERICHOST);
3250  }
3251 #endif
3252 }
3253 
3254 
3255 /* Convert time_t to a string. According to RFC2616, Sec 14.18, this must be
3256  * included in all responses other than 100, 101, 5xx. */
3257 static void
3258 gmt_time_string(char *buf, size_t buf_len, time_t *t)
3259 {
3260  struct tm *tm;
3261 
3262  tm = ((t != NULL) ? gmtime(t) : NULL);
3263  if (tm != NULL) {
3264  strftime(buf, buf_len, "%a, %d %b %Y %H:%M:%S GMT", tm);
3265  } else {
3266  mg_strlcpy(buf, "Thu, 01 Jan 1970 00:00:00 GMT", buf_len);
3267  buf[buf_len - 1] = '\0';
3268  }
3269 }
3270 
3271 
3272 /* difftime for struct timespec. Return value is in seconds. */
3273 static double
3274 mg_difftimespec(const struct timespec *ts_now, const struct timespec *ts_before)
3275 {
3276  return (double)(ts_now->tv_nsec - ts_before->tv_nsec) * 1.0E-9
3277  + (double)(ts_now->tv_sec - ts_before->tv_sec);
3278 }
3279 
3280 
3281 /* Print error message to the opened error log stream. */
3282 void
3283 mg_cry(const struct mg_connection *conn, const char *fmt, ...)
3284 {
3285  char buf[MG_BUF_LEN], src_addr[IP_ADDR_STR_LEN];
3286  va_list ap;
3287  struct mg_file fi;
3288  time_t timestamp;
3289 
3290  va_start(ap, fmt);
3291  IGNORE_UNUSED_RESULT(vsnprintf_impl(buf, sizeof(buf), fmt, ap));
3292  va_end(ap);
3293  buf[sizeof(buf) - 1] = 0;
3294 
3295  DEBUG_TRACE("mg_cry: %s", buf);
3296 
3297  if (!conn) {
3298  puts(buf);
3299  return;
3300  }
3301 
3302  /* Do not lock when getting the callback value, here and below.
3303  * I suppose this is fine, since function cannot disappear in the
3304  * same way string option can. */
3305  if ((conn->ctx->callbacks.log_message == NULL)
3306  || (conn->ctx->callbacks.log_message(conn, buf) == 0)) {
3307 
3308  if (conn->ctx->config[ERROR_LOG_FILE] != NULL) {
3309  if (mg_fopen(conn,
3310  conn->ctx->config[ERROR_LOG_FILE],
3312  &fi) == 0) {
3313  fi.access.fp = NULL;
3314  }
3315  } else {
3316  fi.access.fp = NULL;
3317  }
3318 
3319  if (fi.access.fp != NULL) {
3320  flockfile(fi.access.fp);
3321  timestamp = time(NULL);
3322 
3323  sockaddr_to_string(src_addr, sizeof(src_addr), &conn->client.rsa);
3324  fprintf(fi.access.fp,
3325  "[%010lu] [error] [client %s] ",
3326  (unsigned long)timestamp,
3327  src_addr);
3328 
3329  if (conn->request_info.request_method != NULL) {
3330  fprintf(fi.access.fp,
3331  "%s %s: ",
3332  conn->request_info.request_method,
3333  conn->request_info.request_uri
3334  ? conn->request_info.request_uri
3335  : "");
3336  }
3337 
3338  fprintf(fi.access.fp, "%s", buf);
3339  fputc('\n', fi.access.fp);
3340  fflush(fi.access.fp);
3341  funlockfile(fi.access.fp);
3342  (void)mg_fclose(&fi.access); /* Ignore errors. We can't call
3343  * mg_cry here anyway ;-) */
3344  }
3345  }
3346 }
3347 
3348 
3349 /* Return fake connection structure. Used for logging, if connection
3350  * is not applicable at the moment of logging. */
3351 static struct mg_connection *
3352 fc(struct mg_context *ctx)
3353 {
3354  static struct mg_connection fake_connection;
3355  fake_connection.ctx = ctx;
3356  return &fake_connection;
3357 }
3358 
3359 
3360 const char *
3362 {
3363  return CIVETWEB_VERSION;
3364 }
3365 
3366 
3367 const struct mg_request_info *
3368 mg_get_request_info(const struct mg_connection *conn)
3369 {
3370  if (!conn) {
3371  return NULL;
3372  }
3373 #if 1 /* TODO: deal with legacy */
3374  if (conn->connection_type == CONNECTION_TYPE_RESPONSE) {
3375  static char txt[16];
3376  sprintf(txt, "%03i", conn->response_info.status_code);
3377 
3378  ((struct mg_connection *)conn)->request_info.local_uri =
3379  ((struct mg_connection *)conn)->request_info.request_uri =
3380  txt; /* TODO: not thread safe */
3381 
3382  ((struct mg_connection *)conn)->request_info.num_headers =
3383  conn->response_info.num_headers;
3384  memcpy(((struct mg_connection *)conn)->request_info.http_headers,
3385  conn->response_info.http_headers,
3386  sizeof(conn->response_info.http_headers));
3387  } else
3388 #endif
3389  if (conn->connection_type != CONNECTION_TYPE_REQUEST) {
3390  return NULL;
3391  }
3392  return &conn->request_info;
3393 }
3394 
3395 
3396 const struct mg_response_info *
3397 mg_get_response_info(const struct mg_connection *conn)
3398 {
3399  if (!conn) {
3400  return NULL;
3401  }
3402  if (conn->connection_type != CONNECTION_TYPE_RESPONSE) {
3403  return NULL;
3404  }
3405  return &conn->response_info;
3406 }
3407 
3408 
3409 static const char *
3410 get_proto_name(const struct mg_connection *conn)
3411 {
3412 #ifdef __clang__
3413 #pragma clang diagnostic push
3414 #pragma clang diagnostic ignored "-Wunreachable-code"
3415 /* Depending on USE_WEBSOCKET and NO_SSL, some oft the protocols might be
3416  * not supported. Clang raises an "unreachable code" warning for parts of ?:
3417  * unreachable, but splitting into four different #ifdef clauses here is more
3418  * complicated.
3419  */
3420 #endif
3421 
3422  const struct mg_request_info *ri = &conn->request_info;
3423 
3424  const char *proto =
3425  (is_websocket_protocol(conn) ? (ri->is_ssl ? "wss" : "ws")
3426  : (ri->is_ssl ? "https" : "http"));
3427 
3428  return proto;
3429 
3430 #ifdef __clang__
3431 #pragma clang diagnostic pop
3432 #endif
3433 }
3434 
3435 
3436 int
3437 mg_get_request_link(const struct mg_connection *conn, char *buf, size_t buflen)
3438 {
3439  if ((buflen < 1) || (buf == 0) || (conn == 0)) {
3440  return -1;
3441  } else {
3442 
3443  int truncated = 0;
3444  const struct mg_request_info *ri = &conn->request_info;
3445 
3446  const char *proto = get_proto_name(conn);
3447 
3448  if (ri->local_uri == NULL) {
3449  return -1;
3450  }
3451 
3452  if ((ri->request_uri != NULL)
3453  && strcmp(ri->local_uri, ri->request_uri)) {
3454  mg_snprintf(conn,
3455  &truncated,
3456  buf,
3457  buflen,
3458  "%s://%s",
3459  proto,
3460  ri->request_uri);
3461  if (truncated) {
3462  return -1;
3463  }
3464  return 0;
3465  } else {
3466 
3467 #if defined(USE_IPV6)
3468  int is_ipv6 = (conn->client.lsa.sa.sa_family == AF_INET6);
3469  int port = is_ipv6 ? htons(conn->client.lsa.sin6.sin6_port)
3470  : htons(conn->client.lsa.sin.sin_port);
3471 #else
3472  int port = htons(conn->client.lsa.sin.sin_port);
3473 #endif
3474  int def_port = ri->is_ssl ? 443 : 80;
3475  int auth_domain_check_enabled =
3476  conn->ctx->config[ENABLE_AUTH_DOMAIN_CHECK]
3477  && (!mg_strcasecmp(conn->ctx->config[ENABLE_AUTH_DOMAIN_CHECK],
3478  "yes"));
3479  const char *server_domain =
3480  conn->ctx->config[AUTHENTICATION_DOMAIN];
3481 
3482  char portstr[16];
3483  char server_ip[48];
3484 
3485  if (port != def_port) {
3486  sprintf(portstr, ":%u", (unsigned)port);
3487  } else {
3488  portstr[0] = 0;
3489  }
3490 
3491  if (!auth_domain_check_enabled || !server_domain) {
3492 
3493  sockaddr_to_string(server_ip,
3494  sizeof(server_ip),
3495  &conn->client.lsa);
3496 
3497  server_domain = server_ip;
3498  }
3499 
3500  mg_snprintf(conn,
3501  &truncated,
3502  buf,
3503  buflen,
3504  "%s://%s%s%s",
3505  proto,
3506  server_domain,
3507  portstr,
3508  ri->local_uri);
3509  if (truncated) {
3510  return -1;
3511  }
3512  return 0;
3513  }
3514  }
3515 }
3516 
3517 /* Skip the characters until one of the delimiters characters found.
3518  * 0-terminate resulting word. Skip the delimiter and following whitespaces.
3519  * Advance pointer to buffer to the next word. Return found 0-terminated
3520  * word.
3521  * Delimiters can be quoted with quotechar. */
3522 static char *
3523 skip_quoted(char **buf,
3524  const char *delimiters,
3525  const char *whitespace,
3526  char quotechar)
3527 {
3528  char *p, *begin_word, *end_word, *end_whitespace;
3529 
3530  begin_word = *buf;
3531  end_word = begin_word + strcspn(begin_word, delimiters);
3532 
3533  /* Check for quotechar */
3534  if (end_word > begin_word) {
3535  p = end_word - 1;
3536  while (*p == quotechar) {
3537  /* While the delimiter is quoted, look for the next delimiter.
3538  */
3539  /* This happens, e.g., in calls from parse_auth_header,
3540  * if the user name contains a " character. */
3541 
3542  /* If there is anything beyond end_word, copy it. */
3543  if (*end_word != '\0') {
3544  size_t end_off = strcspn(end_word + 1, delimiters);
3545  memmove(p, end_word, end_off + 1);
3546  p += end_off; /* p must correspond to end_word - 1 */
3547  end_word += end_off + 1;
3548  } else {
3549  *p = '\0';
3550  break;
3551  }
3552  }
3553  for (p++; p < end_word; p++) {
3554  *p = '\0';
3555  }
3556  }
3557 
3558  if (*end_word == '\0') {
3559  *buf = end_word;
3560  } else {
3561 
3562 #if defined(__GNUC__) || defined(__MINGW32__)
3563 /* Disable spurious conversion warning for GCC */
3564 #if GCC_VERSION >= 40500
3565 #pragma GCC diagnostic push
3566 #pragma GCC diagnostic ignored "-Wsign-conversion"
3567 #endif /* GCC_VERSION >= 40500 */
3568 #endif /* defined(__GNUC__) || defined(__MINGW32__) */
3569 
3570  end_whitespace = end_word + strspn(&end_word[1], whitespace) + 1;
3571 
3572 #if defined(__GNUC__) || defined(__MINGW32__)
3573 #if GCC_VERSION >= 40500
3574 #pragma GCC diagnostic pop
3575 #endif /* GCC_VERSION >= 40500 */
3576 #endif /* defined(__GNUC__) || defined(__MINGW32__) */
3577 
3578  for (p = end_word; p < end_whitespace; p++) {
3579  *p = '\0';
3580  }
3581 
3582  *buf = end_whitespace;
3583  }
3584 
3585  return begin_word;
3586 }
3587 
3588 
3589 /* Return HTTP header value, or NULL if not found. */
3590 static const char *
3591 get_header(const struct mg_header *hdr, int num_hdr, const char *name)
3592 {
3593  int i;
3594  for (i = 0; i < num_hdr; i++) {
3595  if (!mg_strcasecmp(name, hdr[i].name)) {
3596  return hdr[i].value;
3597  }
3598  }
3599 
3600  return NULL;
3601 }
3602 
3603 
3604 #if defined(USE_WEBSOCKET)
3605 /* Retrieve requested HTTP header multiple values, and return the number of
3606  * found occurences */
3607 static int
3608 get_req_headers(const struct mg_request_info *ri,
3609  const char *name,
3610  const char **output,
3611  int output_max_size)
3612 {
3613  int i;
3614  int cnt = 0;
3615  if (ri) {
3616  for (i = 0; i < ri->num_headers && cnt < output_max_size; i++) {
3617  if (!mg_strcasecmp(name, ri->http_headers[i].name)) {
3618  output[cnt++] = ri->http_headers[i].value;
3619  }
3620  }
3621  }
3622  return cnt;
3623 }
3624 #endif
3625 
3626 
3627 const char *
3628 mg_get_header(const struct mg_connection *conn, const char *name)
3629 {
3630  if (!conn) {
3631  return NULL;
3632  }
3633 
3634  if (conn->connection_type == CONNECTION_TYPE_REQUEST) {
3635  return get_header(conn->request_info.http_headers,
3636  conn->request_info.num_headers,
3637  name);
3638  }
3639  if (conn->connection_type == CONNECTION_TYPE_RESPONSE) {
3640  return get_header(conn->response_info.http_headers,
3641  conn->request_info.num_headers,
3642  name);
3643  }
3644  return NULL;
3645 }
3646 
3647 
3648 static const char *
3649 get_http_version(const struct mg_connection *conn)
3650 {
3651  if (!conn) {
3652  return NULL;
3653  }
3654 
3655  if (conn->connection_type == CONNECTION_TYPE_REQUEST) {
3656  return conn->request_info.http_version;
3657  }
3658  if (conn->connection_type == CONNECTION_TYPE_RESPONSE) {
3659  return conn->response_info.http_version;
3660  }
3661  return NULL;
3662 }
3663 
3664 
3665 /* A helper function for traversing a comma separated list of values.
3666  * It returns a list pointer shifted to the next value, or NULL if the end
3667  * of the list found.
3668  * Value is stored in val vector. If value has form "x=y", then eq_val
3669  * vector is initialized to point to the "y" part, and val vector length
3670  * is adjusted to point only to "x". */
3671 static const char *
3672 next_option(const char *list, struct vec *val, struct vec *eq_val)
3673 {
3674  int end;
3675 
3676 reparse:
3677  if (val == NULL || list == NULL || *list == '\0') {
3678  /* End of the list */
3679  return NULL;
3680  }
3681 
3682  /* Skip over leading LWS */
3683  while (*list == ' ' || *list == '\t')
3684  list++;
3685 
3686  val->ptr = list;
3687  if ((list = strchr(val->ptr, ',')) != NULL) {
3688  /* Comma found. Store length and shift the list ptr */
3689  val->len = ((size_t)(list - val->ptr));
3690  list++;
3691  } else {
3692  /* This value is the last one */
3693  list = val->ptr + strlen(val->ptr);
3694  val->len = ((size_t)(list - val->ptr));
3695  }
3696 
3697  /* Adjust length for trailing LWS */
3698  end = (int)val->len - 1;
3699  while (end >= 0 && ((val->ptr[end] == ' ') || (val->ptr[end] == '\t')))
3700  end--;
3701  val->len = (size_t)(end + 1);
3702 
3703  if (val->len == 0) {
3704  /* Ignore any empty entries. */
3705  goto reparse;
3706  }
3707 
3708  if (eq_val != NULL) {
3709  /* Value has form "x=y", adjust pointers and lengths
3710  * so that val points to "x", and eq_val points to "y". */
3711  eq_val->len = 0;
3712  eq_val->ptr = (const char *)memchr(val->ptr, '=', val->len);
3713  if (eq_val->ptr != NULL) {
3714  eq_val->ptr++; /* Skip over '=' character */
3715  eq_val->len = ((size_t)(val->ptr - eq_val->ptr)) + val->len;
3716  val->len = ((size_t)(eq_val->ptr - val->ptr)) - 1;
3717  }
3718  }
3719 
3720  return list;
3721 }
3722 
3723 
3724 /* A helper function for checking if a comma separated list of values
3725  * contains
3726  * the given option (case insensitvely).
3727  * 'header' can be NULL, in which case false is returned. */
3728 static int
3729 header_has_option(const char *header, const char *option)
3730 {
3731  struct vec opt_vec;
3732  struct vec eq_vec;
3733 
3734  /*
3735  assert(option != NULL);
3736  assert(option[0] != '\0');
3737  */
3738 
3739  while ((header = next_option(header, &opt_vec, &eq_vec)) != NULL) {
3740  if (mg_strncasecmp(option, opt_vec.ptr, opt_vec.len) == 0)
3741  return 1;
3742  }
3743 
3744  return 0;
3745 }
3746 
3747 
3748 /* Perform case-insensitive match of string against pattern */
3749 static int
3750 match_prefix(const char *pattern, size_t pattern_len, const char *str)
3751 {
3752  const char *or_str;
3753  size_t i;
3754  int j, len, res;
3755 
3756  if ((or_str = (const char *)memchr(pattern, '|', pattern_len)) != NULL) {
3757  res = match_prefix(pattern, (size_t)(or_str - pattern), str);
3758  return (res > 0) ? res : match_prefix(or_str + 1,
3759  (size_t)((pattern + pattern_len)
3760  - (or_str + 1)),
3761  str);
3762  }
3763 
3764  for (i = 0, j = 0; (i < pattern_len); i++, j++) {
3765  if ((pattern[i] == '?') && (str[j] != '\0')) {
3766  continue;
3767  } else if (pattern[i] == '$') {
3768  return (str[j] == '\0') ? j : -1;
3769  } else if (pattern[i] == '*') {
3770  i++;
3771  if (pattern[i] == '*') {
3772  i++;
3773  len = (int)strlen(str + j);
3774  } else {
3775  len = (int)strcspn(str + j, "/");
3776  }
3777  if (i == pattern_len) {
3778  return j + len;
3779  }
3780  do {
3781  res = match_prefix(pattern + i, pattern_len - i, str + j + len);
3782  } while (res == -1 && len-- > 0);
3783  return (res == -1) ? -1 : j + res + len;
3784  } else if (lowercase(&pattern[i]) != lowercase(&str[j])) {
3785  return -1;
3786  }
3787  }
3788  return j;
3789 }
3790 
3791 
3792 /* HTTP 1.1 assumes keep alive if "Connection:" header is not set
3793  * This function must tolerate situations when connection info is not
3794  * set up, for example if request parsing failed. */
3795 static int
3796 should_keep_alive(const struct mg_connection *conn)
3797 {
3798  const char *http_version;
3799  const char *header;
3800 
3801  /* First satisfy needs of the server */
3802  if ((conn == NULL) || conn->must_close) {
3803  /* Close, if civetweb framework needs to close */
3804  return 0;
3805  }
3806 
3807  if (mg_strcasecmp(conn->ctx->config[ENABLE_KEEP_ALIVE], "yes") != 0) {
3808  /* Close, if keep alive is not enabled */
3809  return 0;
3810  }
3811 
3812  /* Check explicit wish of the client */
3813  header = mg_get_header(conn, "Connection");
3814  if (header) {
3815  /* If there is a connection header from the client, obey */
3816  if (header_has_option(header, "keep-alive")) {
3817  return 1;
3818  }
3819  return 0;
3820  }
3821 
3822  /* Use default of the standard */
3823  http_version = get_http_version(conn);
3824  if (http_version && (0 == strcmp(http_version, "1.1"))) {
3825  /* HTTP 1.1 default is keep alive */
3826  return 1;
3827  }
3828 
3829  /* HTTP 1.0 (and earlier) default is to close the connection */
3830  return 0;
3831 }
3832 
3833 
3834 static int
3835 should_decode_url(const struct mg_connection *conn)
3836 {
3837  if (!conn || !conn->ctx) {
3838  return 0;
3839  }
3840 
3841  return (mg_strcasecmp(conn->ctx->config[DECODE_URL], "yes") == 0);
3842 }
3843 
3844 
3845 static const char *
3846 suggest_connection_header(const struct mg_connection *conn)
3847 {
3848  return should_keep_alive(conn) ? "keep-alive" : "close";
3849 }
3850 
3851 
3852 static int
3853 send_no_cache_header(struct mg_connection *conn)
3854 {
3855  /* Send all current and obsolete cache opt-out directives. */
3856  return mg_printf(conn,
3857  "Cache-Control: no-cache, no-store, "
3858  "must-revalidate, private, max-age=0\r\n"
3859  "Pragma: no-cache\r\n"
3860  "Expires: 0\r\n");
3861 }
3862 
3863 
3864 static int
3865 send_static_cache_header(struct mg_connection *conn)
3866 {
3867 #if !defined(NO_CACHING)
3868  /* Read the server config to check how long a file may be cached.
3869  * The configuration is in seconds. */
3870  int max_age = atoi(conn->ctx->config[STATIC_FILE_MAX_AGE]);
3871  if (max_age <= 0) {
3872  /* 0 means "do not cache". All values <0 are reserved
3873  * and may be used differently in the future. */
3874  /* If a file should not be cached, do not only send
3875  * max-age=0, but also pragmas and Expires headers. */
3876  return send_no_cache_header(conn);
3877  }
3878 
3879  /* Use "Cache-Control: max-age" instead of "Expires" header.
3880  * Reason: see https://www.mnot.net/blog/2007/05/15/expires_max-age */
3881  /* See also https://www.mnot.net/cache_docs/ */
3882  /* According to RFC 2616, Section 14.21, caching times should not exceed
3883  * one year. A year with 365 days corresponds to 31536000 seconds, a
3884  * leap
3885  * year to 31622400 seconds. For the moment, we just send whatever has
3886  * been configured, still the behavior for >1 year should be considered
3887  * as undefined. */
3888  return mg_printf(conn, "Cache-Control: max-age=%u\r\n", (unsigned)max_age);
3889 #else /* NO_CACHING */
3890  return send_no_cache_header(conn);
3891 #endif /* !NO_CACHING */
3892 }
3893 
3894 
3895 static int
3896 send_additional_header(struct mg_connection *conn)
3897 {
3898  int i = 0;
3899  const char *header = conn->ctx->config[ADDITIONAL_HEADER];
3900 
3901 #if !defined(NO_SSL)
3902  if (conn->ctx->config[STRICT_HTTPS_MAX_AGE]) {
3903  int max_age = atoi(conn->ctx->config[STRICT_HTTPS_MAX_AGE]);
3904  if (max_age >= 0) {
3905  i += mg_printf(conn,
3906  "Strict-Transport-Security: max-age=%u\r\n",
3907  (unsigned)max_age);
3908  }
3909  }
3910 #endif
3911 
3912  if (header && header[0]) {
3913  i += mg_printf(conn, "%s\r\n", header);
3914  }
3915 
3916  return i;
3917 }
3918 
3919 
3920 static void handle_file_based_request(struct mg_connection *conn,
3921  const char *path,
3922  struct mg_file *filep);
3923 
3924 
3925 const char *
3926 mg_get_response_code_text(const struct mg_connection *conn, int response_code)
3927 {
3928  /* See IANA HTTP status code assignment:
3929  * http://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml
3930  */
3931 
3932  switch (response_code) {
3933  /* RFC2616 Section 10.1 - Informational 1xx */
3934  case 100:
3935  return "Continue"; /* RFC2616 Section 10.1.1 */
3936  case 101:
3937  return "Switching Protocols"; /* RFC2616 Section 10.1.2 */
3938  case 102:
3939  return "Processing"; /* RFC2518 Section 10.1 */
3940 
3941  /* RFC2616 Section 10.2 - Successful 2xx */
3942  case 200:
3943  return "OK"; /* RFC2616 Section 10.2.1 */
3944  case 201:
3945  return "Created"; /* RFC2616 Section 10.2.2 */
3946  case 202:
3947  return "Accepted"; /* RFC2616 Section 10.2.3 */
3948  case 203:
3949  return "Non-Authoritative Information"; /* RFC2616 Section 10.2.4 */
3950  case 204:
3951  return "No Content"; /* RFC2616 Section 10.2.5 */
3952  case 205:
3953  return "Reset Content"; /* RFC2616 Section 10.2.6 */
3954  case 206:
3955  return "Partial Content"; /* RFC2616 Section 10.2.7 */
3956  case 207:
3957  return "Multi-Status"; /* RFC2518 Section 10.2, RFC4918 Section 11.1
3958  */
3959  case 208:
3960  return "Already Reported"; /* RFC5842 Section 7.1 */
3961 
3962  case 226:
3963  return "IM used"; /* RFC3229 Section 10.4.1 */
3964 
3965  /* RFC2616 Section 10.3 - Redirection 3xx */
3966  case 300:
3967  return "Multiple Choices"; /* RFC2616 Section 10.3.1 */
3968  case 301:
3969  return "Moved Permanently"; /* RFC2616 Section 10.3.2 */
3970  case 302:
3971  return "Found"; /* RFC2616 Section 10.3.3 */
3972  case 303:
3973  return "See Other"; /* RFC2616 Section 10.3.4 */
3974  case 304:
3975  return "Not Modified"; /* RFC2616 Section 10.3.5 */
3976  case 305:
3977  return "Use Proxy"; /* RFC2616 Section 10.3.6 */
3978  case 307:
3979  return "Temporary Redirect"; /* RFC2616 Section 10.3.8 */
3980  case 308:
3981  return "Permanent Redirect"; /* RFC7238 Section 3 */
3982 
3983  /* RFC2616 Section 10.4 - Client Error 4xx */
3984  case 400:
3985  return "Bad Request"; /* RFC2616 Section 10.4.1 */
3986  case 401:
3987  return "Unauthorized"; /* RFC2616 Section 10.4.2 */
3988  case 402:
3989  return "Payment Required"; /* RFC2616 Section 10.4.3 */
3990  case 403:
3991  return "Forbidden"; /* RFC2616 Section 10.4.4 */
3992  case 404:
3993  return "Not Found"; /* RFC2616 Section 10.4.5 */
3994  case 405:
3995  return "Method Not Allowed"; /* RFC2616 Section 10.4.6 */
3996  case 406:
3997  return "Not Acceptable"; /* RFC2616 Section 10.4.7 */
3998  case 407:
3999  return "Proxy Authentication Required"; /* RFC2616 Section 10.4.8 */
4000  case 408:
4001  return "Request Time-out"; /* RFC2616 Section 10.4.9 */
4002  case 409:
4003  return "Conflict"; /* RFC2616 Section 10.4.10 */
4004  case 410:
4005  return "Gone"; /* RFC2616 Section 10.4.11 */
4006  case 411:
4007  return "Length Required"; /* RFC2616 Section 10.4.12 */
4008  case 412:
4009  return "Precondition Failed"; /* RFC2616 Section 10.4.13 */
4010  case 413:
4011  return "Request Entity Too Large"; /* RFC2616 Section 10.4.14 */
4012  case 414:
4013  return "Request-URI Too Large"; /* RFC2616 Section 10.4.15 */
4014  case 415:
4015  return "Unsupported Media Type"; /* RFC2616 Section 10.4.16 */
4016  case 416:
4017  return "Requested range not satisfiable"; /* RFC2616 Section 10.4.17
4018  */
4019  case 417:
4020  return "Expectation Failed"; /* RFC2616 Section 10.4.18 */
4021 
4022  case 421:
4023  return "Misdirected Request"; /* RFC7540 Section 9.1.2 */
4024  case 422:
4025  return "Unproccessable entity"; /* RFC2518 Section 10.3, RFC4918
4026  * Section 11.2 */
4027  case 423:
4028  return "Locked"; /* RFC2518 Section 10.4, RFC4918 Section 11.3 */
4029  case 424:
4030  return "Failed Dependency"; /* RFC2518 Section 10.5, RFC4918
4031  * Section 11.4 */
4032 
4033  case 426:
4034  return "Upgrade Required"; /* RFC 2817 Section 4 */
4035 
4036  case 428:
4037  return "Precondition Required"; /* RFC 6585, Section 3 */
4038  case 429:
4039  return "Too Many Requests"; /* RFC 6585, Section 4 */
4040 
4041  case 431:
4042  return "Request Header Fields Too Large"; /* RFC 6585, Section 5 */
4043 
4044  case 451:
4045  return "Unavailable For Legal Reasons"; /* draft-tbray-http-legally-restricted-status-05,
4046  * Section 3 */
4047 
4048  /* RFC2616 Section 10.5 - Server Error 5xx */
4049  case 500:
4050  return "Internal Server Error"; /* RFC2616 Section 10.5.1 */
4051  case 501:
4052  return "Not Implemented"; /* RFC2616 Section 10.5.2 */
4053  case 502:
4054  return "Bad Gateway"; /* RFC2616 Section 10.5.3 */
4055  case 503:
4056  return "Service Unavailable"; /* RFC2616 Section 10.5.4 */
4057  case 504:
4058  return "Gateway Time-out"; /* RFC2616 Section 10.5.5 */
4059  case 505:
4060  return "HTTP Version not supported"; /* RFC2616 Section 10.5.6 */
4061  case 506:
4062  return "Variant Also Negotiates"; /* RFC 2295, Section 8.1 */
4063  case 507:
4064  return "Insufficient Storage"; /* RFC2518 Section 10.6, RFC4918
4065  * Section 11.5 */
4066  case 508:
4067  return "Loop Detected"; /* RFC5842 Section 7.1 */
4068 
4069  case 510:
4070  return "Not Extended"; /* RFC 2774, Section 7 */
4071  case 511:
4072  return "Network Authentication Required"; /* RFC 6585, Section 6 */
4073 
4074  /* Other status codes, not shown in the IANA HTTP status code
4075  * assignment.
4076  * E.g., "de facto" standards due to common use, ... */
4077  case 418:
4078  return "I am a teapot"; /* RFC2324 Section 2.3.2 */
4079  case 419:
4080  return "Authentication Timeout"; /* common use */
4081  case 420:
4082  return "Enhance Your Calm"; /* common use */
4083  case 440:
4084  return "Login Timeout"; /* common use */
4085  case 509:
4086  return "Bandwidth Limit Exceeded"; /* common use */
4087 
4088  default:
4089  /* This error code is unknown. This should not happen. */
4090  if (conn) {
4091  mg_cry(conn, "Unknown HTTP response code: %u", response_code);
4092  }
4093 
4094  /* Return at least a category according to RFC 2616 Section 10. */
4095  if (response_code >= 100 && response_code < 200) {
4096  /* Unknown informational status code */
4097  return "Information";
4098  }
4099  if (response_code >= 200 && response_code < 300) {
4100  /* Unknown success code */
4101  return "Success";
4102  }
4103  if (response_code >= 300 && response_code < 400) {
4104  /* Unknown redirection code */
4105  return "Redirection";
4106  }
4107  if (response_code >= 400 && response_code < 500) {
4108  /* Unknown request error code */
4109  return "Client Error";
4110  }
4111  if (response_code >= 500 && response_code < 600) {
4112  /* Unknown server error code */
4113  return "Server Error";
4114  }
4115 
4116  /* Response code not even within reasonable range */
4117  return "";
4118  }
4119 }
4120 
4121 
4122 void
4123 mg_send_http_error(struct mg_connection *conn, int status, const char *fmt, ...)
4124 {
4125  char buf[MG_BUF_LEN];
4126  va_list ap;
4127  int len, i, page_handler_found, scope, truncated, has_body;
4128  char date[64];
4129  time_t curtime = time(NULL);
4130  const char *error_handler = NULL;
4131  struct mg_file error_page_file = STRUCT_FILE_INITIALIZER;
4132  const char *error_page_file_ext, *tstr;
4133 
4134  const char *status_text = mg_get_response_code_text(conn, status);
4135 
4136  if (conn == NULL) {
4137  return;
4138  }
4139 
4140  conn->status_code = status;
4141  if (conn->in_error_handler || (conn->ctx->callbacks.http_error == NULL)
4142  || conn->ctx->callbacks.http_error(conn, status)) {
4143 
4144  /* Check for recursion */
4145  if (conn->in_error_handler) {
4146  DEBUG_TRACE(
4147  "Recursion when handling error %u - fall back to default",
4148  status);
4149  } else {
4150  /* Send user defined error pages, if defined */
4151  error_handler = conn->ctx->config[ERROR_PAGES];
4152  error_page_file_ext = conn->ctx->config[INDEX_FILES];
4153  page_handler_found = 0;
4154 
4155  if (error_handler != NULL) {
4156  for (scope = 1; (scope <= 3) && !page_handler_found; scope++) {
4157  switch (scope) {
4158  case 1: /* Handler for specific error, e.g. 404 error */
4159  mg_snprintf(conn,
4160  &truncated,
4161  buf,
4162  sizeof(buf) - 32,
4163  "%serror%03u.",
4164  error_handler,
4165  status);
4166  break;
4167  case 2: /* Handler for error group, e.g., 5xx error
4168  * handler
4169  * for all server errors (500-599) */
4170  mg_snprintf(conn,
4171  &truncated,
4172  buf,
4173  sizeof(buf) - 32,
4174  "%serror%01uxx.",
4175  error_handler,
4176  status / 100);
4177  break;
4178  default: /* Handler for all errors */
4179  mg_snprintf(conn,
4180  &truncated,
4181  buf,
4182  sizeof(buf) - 32,
4183  "%serror.",
4184  error_handler);
4185  break;
4186  }
4187 
4188  /* String truncation in buf may only occur if
4189  * error_handler is too long. This string is
4190  * from the config, not from a client. */
4191  (void)truncated;
4192 
4193  len = (int)strlen(buf);
4194 
4195  tstr = strchr(error_page_file_ext, '.');
4196 
4197  while (tstr) {
4198  for (i = 1;
4199  (i < 32) && (tstr[i] != 0) && (tstr[i] != ',');
4200  i++)
4201  buf[len + i - 1] = tstr[i];
4202  buf[len + i - 1] = 0;
4203 
4204  if (mg_stat(conn, buf, &error_page_file.stat)) {
4205  DEBUG_TRACE("Check error page %s - found", buf);
4206  page_handler_found = 1;
4207  break;
4208  }
4209  DEBUG_TRACE("Check error page %s - not found", buf);
4210 
4211  tstr = strchr(tstr + i, '.');
4212  }
4213  }
4214  }
4215 
4216  if (page_handler_found) {
4217  conn->in_error_handler = 1;
4218  handle_file_based_request(conn, buf, &error_page_file);
4219  conn->in_error_handler = 0;
4220  return;
4221  }
4222  }
4223 
4224  /* No custom error page. Send default error page. */
4225  gmt_time_string(date, sizeof(date), &curtime);
4226 
4227  /* Errors 1xx, 204 and 304 MUST NOT send a body */
4228  has_body = ((status > 199) && (status != 204) && (status != 304));
4229 
4230  conn->must_close = 1;
4231  mg_printf(conn, "HTTP/1.1 %d %s\r\n", status, status_text);
4232  send_no_cache_header(conn);
4233  send_additional_header(conn);
4234  if (has_body) {
4235  mg_printf(conn,
4236  "%s",
4237  "Content-Type: text/plain; charset=utf-8\r\n");
4238  }
4239  mg_printf(conn,
4240  "Date: %s\r\n"
4241  "Connection: close\r\n\r\n",
4242  date);
4243 
4244  /* Errors 1xx, 204 and 304 MUST NOT send a body */
4245  if (has_body) {
4246  mg_printf(conn, "Error %d: %s\n", status, status_text);
4247 
4248  if (fmt != NULL) {
4249  va_start(ap, fmt);
4250  mg_vsnprintf(conn, NULL, buf, sizeof(buf), fmt, ap);
4251  va_end(ap);
4252  mg_write(conn, buf, strlen(buf));
4253  DEBUG_TRACE("Error %i - [%s]", status, buf);
4254  }
4255 
4256  } else {
4257  /* No body allowed. Close the connection. */
4258  DEBUG_TRACE("Error %i", status);
4259  }
4260  }
4261 }
4262 
4263 #if defined(_WIN32) && !defined(__SYMBIAN32__)
4264 /* Create substitutes for POSIX functions in Win32. */
4265 
4266 #if defined(__MINGW32__)
4267 /* Show no warning in case system functions are not used. */
4268 #pragma GCC diagnostic push
4269 #pragma GCC diagnostic ignored "-Wunused-function"
4270 #endif
4271 
4272 
4274 static int
4275 pthread_mutex_init(pthread_mutex_t *mutex, void *unused)
4276 {
4277  (void)unused;
4278  *mutex = CreateMutex(NULL, FALSE, NULL);
4279  return (*mutex == NULL) ? -1 : 0;
4280 }
4281 
4283 static int
4284 pthread_mutex_destroy(pthread_mutex_t *mutex)
4285 {
4286  return (CloseHandle(*mutex) == 0) ? -1 : 0;
4287 }
4288 
4289 
4291 static int
4292 pthread_mutex_lock(pthread_mutex_t *mutex)
4293 {
4294  return (WaitForSingleObject(*mutex, (DWORD)INFINITE) == WAIT_OBJECT_0) ? 0
4295  : -1;
4296 }
4297 
4298 
4299 #ifdef ENABLE_UNUSED_PTHREAD_FUNCTIONS
4301 static int
4302 pthread_mutex_trylock(pthread_mutex_t *mutex)
4303 {
4304  switch (WaitForSingleObject(*mutex, 0)) {
4305  case WAIT_OBJECT_0:
4306  return 0;
4307  case WAIT_TIMEOUT:
4308  return -2; /* EBUSY */
4309  }
4310  return -1;
4311 }
4312 #endif
4313 
4314 
4316 static int
4317 pthread_mutex_unlock(pthread_mutex_t *mutex)
4318 {
4319  return (ReleaseMutex(*mutex) == 0) ? -1 : 0;
4320 }
4321 
4322 
4324 static int
4325 pthread_cond_init(pthread_cond_t *cv, const void *unused)
4326 {
4327  (void)unused;
4328  InitializeCriticalSection(&cv->threadIdSec);
4329  cv->waiting_thread = NULL;
4330  return 0;
4331 }
4332 
4333 
4335 static int
4336 pthread_cond_timedwait(pthread_cond_t *cv,
4337  pthread_mutex_t *mutex,
4338  const struct timespec *abstime)
4339 {
4340  struct mg_workerTLS **ptls,
4341  *tls = (struct mg_workerTLS *)pthread_getspecific(sTlsKey);
4342  int ok;
4343  int64_t nsnow, nswaitabs, nswaitrel;
4344  DWORD mswaitrel;
4345 
4346  EnterCriticalSection(&cv->threadIdSec);
4347  /* Add this thread to cv's waiting list */
4348  ptls = &cv->waiting_thread;
4349  for (; *ptls != NULL; ptls = &(*ptls)->next_waiting_thread)
4350  ;
4351  tls->next_waiting_thread = NULL;
4352  *ptls = tls;
4353  LeaveCriticalSection(&cv->threadIdSec);
4354 
4355  if (abstime) {
4356  nsnow = mg_get_current_time_ns();
4357  nswaitabs =
4358  (((int64_t)abstime->tv_sec) * 1000000000) + abstime->tv_nsec;
4359  nswaitrel = nswaitabs - nsnow;
4360  if (nswaitrel < 0) {
4361  nswaitrel = 0;
4362  }
4363  mswaitrel = (DWORD)(nswaitrel / 1000000);
4364  } else {
4365  mswaitrel = (DWORD)INFINITE;
4366  }
4367 
4368  pthread_mutex_unlock(mutex);
4369  ok = (WAIT_OBJECT_0
4370  == WaitForSingleObject(tls->pthread_cond_helper_mutex, mswaitrel));
4371  if (!ok) {
4372  ok = 1;
4373  EnterCriticalSection(&cv->threadIdSec);
4374  ptls = &cv->waiting_thread;
4375  for (; *ptls != NULL; ptls = &(*ptls)->next_waiting_thread) {
4376  if (*ptls == tls) {
4377  *ptls = tls->next_waiting_thread;
4378  ok = 0;
4379  break;
4380  }
4381  }
4382  LeaveCriticalSection(&cv->threadIdSec);
4383  if (ok) {
4384  WaitForSingleObject(tls->pthread_cond_helper_mutex,
4385  (DWORD)INFINITE);
4386  }
4387  }
4388  /* This thread has been removed from cv's waiting list */
4389  pthread_mutex_lock(mutex);
4390 
4391  return ok ? 0 : -1;
4392 }
4393 
4394 
4396 static int
4397 pthread_cond_wait(pthread_cond_t *cv, pthread_mutex_t *mutex)
4398 {
4399  return pthread_cond_timedwait(cv, mutex, NULL);
4400 }
4401 
4402 
4404 static int
4405 pthread_cond_signal(pthread_cond_t *cv)
4406 {
4407  HANDLE wkup = NULL;
4408  BOOL ok = FALSE;
4409 
4410  EnterCriticalSection(&cv->threadIdSec);
4411  if (cv->waiting_thread) {
4412  wkup = cv->waiting_thread->pthread_cond_helper_mutex;
4413  cv->waiting_thread = cv->waiting_thread->next_waiting_thread;
4414 
4415  ok = SetEvent(wkup);
4416  assert(ok);
4417  }
4418  LeaveCriticalSection(&cv->threadIdSec);
4419 
4420  return ok ? 0 : 1;
4421 }
4422 
4423 
4425 static int
4426 pthread_cond_broadcast(pthread_cond_t *cv)
4427 {
4428  EnterCriticalSection(&cv->threadIdSec);
4429  while (cv->waiting_thread) {
4430  pthread_cond_signal(cv);
4431  }
4432  LeaveCriticalSection(&cv->threadIdSec);
4433 
4434  return 0;
4435 }
4436 
4437 
4439 static int
4440 pthread_cond_destroy(pthread_cond_t *cv)
4441 {
4442  EnterCriticalSection(&cv->threadIdSec);
4443  assert(cv->waiting_thread == NULL);
4444  LeaveCriticalSection(&cv->threadIdSec);
4445  DeleteCriticalSection(&cv->threadIdSec);
4446 
4447  return 0;
4448 }
4449 
4450 
4451 #ifdef ALTERNATIVE_QUEUE
4453 static void *
4454 event_create(void)
4455 {
4456  return (void *)CreateEvent(NULL, FALSE, FALSE, NULL);
4457 }
4458 
4459 
4461 static int
4462 event_wait(void *eventhdl)
4463 {
4464  int res = WaitForSingleObject((HANDLE)eventhdl, (DWORD)INFINITE);
4465  return (res == WAIT_OBJECT_0);
4466 }
4467 
4468 
4470 static int
4471 event_signal(void *eventhdl)
4472 {
4473  return (int)SetEvent((HANDLE)eventhdl);
4474 }
4475 
4476 
4478 static void
4479 event_destroy(void *eventhdl)
4480 {
4481  CloseHandle((HANDLE)eventhdl);
4482 }
4483 #endif
4484 
4485 
4486 #if defined(__MINGW32__)
4487 /* Enable unused function warning again */
4488 #pragma GCC diagnostic pop
4489 #endif
4490 
4491 
4492 /* For Windows, change all slashes to backslashes in path names. */
4493 static void
4494 change_slashes_to_backslashes(char *path)
4495 {
4496  int i;
4497 
4498  for (i = 0; path[i] != '\0'; i++) {
4499  if (path[i] == '/') {
4500  path[i] = '\\';
4501  }
4502 
4503  /* remove double backslash (check i > 0 to preserve UNC paths,
4504  * like \\server\file.txt) */
4505  if ((path[i] == '\\') && (i > 0)) {
4506  while ((path[i + 1] == '\\') || (path[i + 1] == '/')) {
4507  (void)memmove(path + i + 1, path + i + 2, strlen(path + i + 1));
4508  }
4509  }
4510  }
4511 }
4512 
4513 
4514 static int
4515 mg_wcscasecmp(const wchar_t *s1, const wchar_t *s2)
4516 {
4517  int diff;
4518 
4519  do {
4520  diff = tolower(*s1) - tolower(*s2);
4521  s1++;
4522  s2++;
4523  } while ((diff == 0) && (s1[-1] != '\0'));
4524 
4525  return diff;
4526 }
4527 
4528 
4529 /* Encode 'path' which is assumed UTF-8 string, into UNICODE string.
4530  * wbuf and wbuf_len is a target buffer and its length. */
4531 static void
4532 path_to_unicode(const struct mg_connection *conn,
4533  const char *path,
4534  wchar_t *wbuf,
4535  size_t wbuf_len)
4536 {
4537  char buf[PATH_MAX], buf2[PATH_MAX];
4538  wchar_t wbuf2[MAX_PATH + 1];
4539  DWORD long_len, err;
4540  int (*fcompare)(const wchar_t *, const wchar_t *) = mg_wcscasecmp;
4541 
4542  mg_strlcpy(buf, path, sizeof(buf));
4543  change_slashes_to_backslashes(buf);
4544 
4545  /* Convert to Unicode and back. If doubly-converted string does not
4546  * match the original, something is fishy, reject. */
4547  memset(wbuf, 0, wbuf_len * sizeof(wchar_t));
4548  MultiByteToWideChar(CP_UTF8, 0, buf, -1, wbuf, (int)wbuf_len);
4549  WideCharToMultiByte(
4550  CP_UTF8, 0, wbuf, (int)wbuf_len, buf2, sizeof(buf2), NULL, NULL);
4551  if (strcmp(buf, buf2) != 0) {
4552  wbuf[0] = L'\0';
4553  }
4554 
4555  /* Windows file systems are not case sensitive, but you can still use
4556  * uppercase and lowercase letters (on all modern file systems).
4557  * The server can check if the URI uses the same upper/lowercase
4558  * letters an the file system, effectively making Windows servers
4559  * case sensitive (like Linux servers are). It is still not possible
4560  * to use two files with the same name in different cases on Windows
4561  * (like /a and /A) - this would be possible in Linux.
4562  * As a default, Windows is not case sensitive, but the case sensitive
4563  * file name check can be activated by an additional configuration. */
4564  if (conn) {
4565  if (conn->ctx->config[CASE_SENSITIVE_FILES]
4566  && !mg_strcasecmp(conn->ctx->config[CASE_SENSITIVE_FILES], "yes")) {
4567  /* Use case sensitive compare function */
4568  fcompare = wcscmp;
4569  }
4570  }
4571  (void)conn; /* conn is currently unused */
4572 
4573 #if !defined(_WIN32_WCE)
4574  /* Only accept a full file path, not a Windows short (8.3) path. */
4575  memset(wbuf2, 0, ARRAY_SIZE(wbuf2) * sizeof(wchar_t));
4576  long_len = GetLongPathNameW(wbuf, wbuf2, ARRAY_SIZE(wbuf2) - 1);
4577  if (long_len == 0) {
4578  err = GetLastError();
4579  if (err == ERROR_FILE_NOT_FOUND) {
4580  /* File does not exist. This is not always a problem here. */
4581  return;
4582  }
4583  }
4584  if ((long_len >= ARRAY_SIZE(wbuf2)) || (fcompare(wbuf, wbuf2) != 0)) {
4585  /* Short name is used. */
4586  wbuf[0] = L'\0';
4587  }
4588 #else
4589  (void)long_len;
4590  (void)wbuf2;
4591  (void)err;
4592 
4593  if (strchr(path, '~')) {
4594  wbuf[0] = L'\0';
4595  }
4596 #endif
4597 }
4598 
4599 
4600 /* Windows happily opens files with some garbage at the end of file name.
4601  * For example, fopen("a.cgi ", "r") on Windows successfully opens
4602  * "a.cgi", despite one would expect an error back.
4603  * This function returns non-0 if path ends with some garbage. */
4604 static int
4605 path_cannot_disclose_cgi(const char *path)
4606 {
4607  static const char *allowed_last_characters = "_-";
4608  int last = path[strlen(path) - 1];
4609  return isalnum(last) || strchr(allowed_last_characters, last) != NULL;
4610 }
4611 
4612 
4613 static int
4614 mg_stat(const struct mg_connection *conn,
4615  const char *path,
4616  struct mg_file_stat *filep)
4617 {
4618  wchar_t wbuf[PATH_MAX];
4619  WIN32_FILE_ATTRIBUTE_DATA info;
4620  time_t creation_time;
4621 
4622  if (!filep) {
4623  return 0;
4624  }
4625  memset(filep, 0, sizeof(*filep));
4626 
4627  if (conn && is_file_in_memory(conn, path)) {
4628  /* filep->is_directory = 0; filep->gzipped = 0; .. already done by
4629  * memset */
4630 
4631  /* Quick fix (for 1.9.x): */
4632  /* mg_stat must fill all fields, also for files in memory */
4633  struct mg_file tmp_file = STRUCT_FILE_INITIALIZER;
4634  open_file_in_memory(conn, path, &tmp_file, MG_FOPEN_MODE_NONE);
4635  filep->size = tmp_file.stat.size;
4636  filep->location = 2;
4637  /* TODO: for 1.10: restructure how files in memory are handled */
4638 
4639  /* The "file in memory" feature is a candidate for deletion.
4640  * Please join the discussion at
4641  * https://groups.google.com/forum/#!topic/civetweb/h9HT4CmeYqI
4642  */
4643 
4644  filep->last_modified = time(NULL); /* TODO */
4645  /* last_modified = now ... assumes the file may change during
4646  * runtime,
4647  * so every mg_fopen call may return different data */
4648  /* last_modified = conn->ctx.start_time;
4649  * May be used it the data does not change during runtime. This
4650  * allows
4651  * browser caching. Since we do not know, we have to assume the file
4652  * in memory may change. */
4653  return 1;
4654  }
4655 
4656  path_to_unicode(conn, path, wbuf, ARRAY_SIZE(wbuf));
4657  if (GetFileAttributesExW(wbuf, GetFileExInfoStandard, &info) != 0) {
4658  filep->size = MAKEUQUAD(info.nFileSizeLow, info.nFileSizeHigh);
4659  filep->last_modified =
4660  SYS2UNIX_TIME(info.ftLastWriteTime.dwLowDateTime,
4661  info.ftLastWriteTime.dwHighDateTime);
4662 
4663  /* On Windows, the file creation time can be higher than the
4664  * modification time, e.g. when a file is copied.
4665  * Since the Last-Modified timestamp is used for caching
4666  * it should be based on the most recent timestamp. */
4667  creation_time = SYS2UNIX_TIME(info.ftCreationTime.dwLowDateTime,
4668  info.ftCreationTime.dwHighDateTime);
4669  if (creation_time > filep->last_modified) {
4670  filep->last_modified = creation_time;
4671  }
4672 
4673  filep->is_directory = info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
4674  /* If file name is fishy, reset the file structure and return
4675  * error.
4676  * Note it is important to reset, not just return the error, cause
4677  * functions like is_file_opened() check the struct. */
4678  if (!filep->is_directory && !path_cannot_disclose_cgi(path)) {
4679  memset(filep, 0, sizeof(*filep));
4680  return 0;
4681  }
4682 
4683  return 1;
4684  }
4685 
4686  return 0;
4687 }
4688 
4689 
4690 static int
4691 mg_remove(const struct mg_connection *conn, const char *path)
4692 {
4693  wchar_t wbuf[PATH_MAX];
4694  path_to_unicode(conn, path, wbuf, ARRAY_SIZE(wbuf));
4695  return DeleteFileW(wbuf) ? 0 : -1;
4696 }
4697 
4698 
4699 static int
4700 mg_mkdir(const struct mg_connection *conn, const char *path, int mode)
4701 {
4702  wchar_t wbuf[PATH_MAX];
4703  (void)mode;
4704  path_to_unicode(conn, path, wbuf, ARRAY_SIZE(wbuf));
4705  return CreateDirectoryW(wbuf, NULL) ? 0 : -1;
4706 }
4707 
4708 
4709 /* Create substitutes for POSIX functions in Win32. */
4710 
4711 #if defined(__MINGW32__)
4712 /* Show no warning in case system functions are not used. */
4713 #pragma GCC diagnostic push
4714 #pragma GCC diagnostic ignored "-Wunused-function"
4715 #endif
4716 
4717 
4718 /* Implementation of POSIX opendir/closedir/readdir for Windows. */
4720 static DIR *
4721 mg_opendir(const struct mg_connection *conn, const char *name)
4722 {
4723  DIR *dir = NULL;
4724  wchar_t wpath[PATH_MAX];
4725  DWORD attrs;
4726 
4727  if (name == NULL) {
4728  SetLastError(ERROR_BAD_ARGUMENTS);
4729  } else if ((dir = (DIR *)mg_malloc(sizeof(*dir))) == NULL) {
4730  SetLastError(ERROR_NOT_ENOUGH_MEMORY);
4731  } else {
4732  path_to_unicode(conn, name, wpath, ARRAY_SIZE(wpath));
4733  attrs = GetFileAttributesW(wpath);
4734  if (attrs != 0xFFFFFFFF && ((attrs & FILE_ATTRIBUTE_DIRECTORY)
4735  == FILE_ATTRIBUTE_DIRECTORY)) {
4736  (void)wcscat(wpath, L"\\*");
4737  dir->handle = FindFirstFileW(wpath, &dir->info);
4738  dir->result.d_name[0] = '\0';
4739  } else {
4740  mg_free(dir);
4741  dir = NULL;
4742  }
4743  }
4744 
4745  return dir;
4746 }
4747 
4748 
4750 static int
4751 mg_closedir(DIR *dir)
4752 {
4753  int result = 0;
4754 
4755  if (dir != NULL) {
4756  if (dir->handle != INVALID_HANDLE_VALUE)
4757  result = FindClose(dir->handle) ? 0 : -1;
4758 
4759  mg_free(dir);
4760  } else {
4761  result = -1;
4762  SetLastError(ERROR_BAD_ARGUMENTS);
4763  }
4764 
4765  return result;
4766 }
4767 
4768 
4770 static struct dirent *
4771 mg_readdir(DIR *dir)
4772 {
4773  struct dirent *result = 0;
4774 
4775  if (dir) {
4776  if (dir->handle != INVALID_HANDLE_VALUE) {
4777  result = &dir->result;
4778  (void)WideCharToMultiByte(CP_UTF8,
4779  0,
4780  dir->info.cFileName,
4781  -1,
4782  result->d_name,
4783  sizeof(result->d_name),
4784  NULL,
4785  NULL);
4786 
4787  if (!FindNextFileW(dir->handle, &dir->info)) {
4788  (void)FindClose(dir->handle);
4789  dir->handle = INVALID_HANDLE_VALUE;
4790  }
4791 
4792  } else {
4793  SetLastError(ERROR_FILE_NOT_FOUND);
4794  }
4795  } else {
4796  SetLastError(ERROR_BAD_ARGUMENTS);
4797  }
4798 
4799  return result;
4800 }
4801 
4802 
4803 #ifndef HAVE_POLL
4805 static int
4806 poll(struct pollfd *pfd, unsigned int n, int milliseconds)
4807 {
4808  struct timeval tv;
4809  fd_set set;
4810  unsigned int i;
4811  int result;
4812  SOCKET maxfd = 0;
4813 
4814  memset(&tv, 0, sizeof(tv));
4815  tv.tv_sec = milliseconds / 1000;
4816  tv.tv_usec = (milliseconds % 1000) * 1000;
4817  FD_ZERO(&set);
4818 
4819  for (i = 0; i < n; i++) {
4820  FD_SET((SOCKET)pfd[i].fd, &set);
4821  pfd[i].revents = 0;
4822 
4823  if (pfd[i].fd > maxfd) {
4824  maxfd = pfd[i].fd;
4825  }
4826  }
4827 
4828  if ((result = select((int)maxfd + 1, &set, NULL, NULL, &tv)) > 0) {
4829  for (i = 0; i < n; i++) {
4830  if (FD_ISSET(pfd[i].fd, &set)) {
4831  pfd[i].revents = POLLIN;
4832  }
4833  }
4834  }
4835 
4836  /* We should subtract the time used in select from remaining
4837  * "milliseconds", in particular if called from mg_poll with a
4838  * timeout quantum.
4839  * Unfortunately, the remaining time is not stored in "tv" in all
4840  * implementations, so the result in "tv" must be considered undefined.
4841  * See http://man7.org/linux/man-pages/man2/select.2.html */
4842 
4843  return result;
4844 }
4845 #endif /* HAVE_POLL */
4846 
4847 
4848 #if defined(__MINGW32__)
4849 /* Enable unused function warning again */
4850 #pragma GCC diagnostic pop
4851 #endif
4852 
4853 
4854 static void
4855 set_close_on_exec(SOCKET sock, struct mg_connection *conn /* may be null */)
4856 {
4857  (void)conn; /* Unused. */
4858 #if defined(_WIN32_WCE)
4859  (void)sock;
4860 #else
4861  (void)SetHandleInformation((HANDLE)(intptr_t)sock, HANDLE_FLAG_INHERIT, 0);
4862 #endif
4863 }
4864 
4865 
4866 int
4868 {
4869 #if defined(USE_STACK_SIZE) && (USE_STACK_SIZE > 1)
4870  /* Compile-time option to control stack size, e.g.
4871  * -DUSE_STACK_SIZE=16384
4872  */
4873  return ((_beginthread((void(__cdecl *)(void *))f, USE_STACK_SIZE, p)
4874  == ((uintptr_t)(-1L)))
4875  ? -1
4876  : 0);
4877 #else
4878  return (
4879  (_beginthread((void(__cdecl *)(void *))f, 0, p) == ((uintptr_t)(-1L)))
4880  ? -1
4881  : 0);
4882 #endif /* defined(USE_STACK_SIZE) && (USE_STACK_SIZE > 1) */
4883 }
4884 
4885 
4886 /* Start a thread storing the thread context. */
4887 static int
4888 mg_start_thread_with_id(unsigned(__stdcall *f)(void *),
4889  void *p,
4890  pthread_t *threadidptr)
4891 {
4892  uintptr_t uip;
4893  HANDLE threadhandle;
4894  int result = -1;
4895 
4896  uip = _beginthreadex(NULL, 0, (unsigned(__stdcall *)(void *))f, p, 0, NULL);
4897  threadhandle = (HANDLE)uip;
4898  if ((uip != (uintptr_t)(-1L)) && (threadidptr != NULL)) {
4899  *threadidptr = threadhandle;
4900  result = 0;
4901  }
4902 
4903  return result;
4904 }
4905 
4906 
4907 /* Wait for a thread to finish. */
4908 static int
4909 mg_join_thread(pthread_t threadid)
4910 {
4911  int result;
4912  DWORD dwevent;
4913 
4914  result = -1;
4915  dwevent = WaitForSingleObject(threadid, (DWORD)INFINITE);
4916  if (dwevent == WAIT_FAILED) {
4917  DEBUG_TRACE("WaitForSingleObject() failed, error %d", ERRNO);
4918  } else {
4919  if (dwevent == WAIT_OBJECT_0) {
4920  CloseHandle(threadid);
4921  result = 0;
4922  }
4923  }
4924 
4925  return result;
4926 }
4927 
4928 #if !defined(NO_SSL_DL) && !defined(NO_SSL)
4929 /* If SSL is loaded dynamically, dlopen/dlclose is required. */
4930 /* Create substitutes for POSIX functions in Win32. */
4931 
4932 #if defined(__MINGW32__)
4933 /* Show no warning in case system functions are not used. */
4934 #pragma GCC diagnostic push
4935 #pragma GCC diagnostic ignored "-Wunused-function"
4936 #endif
4937 
4938 
4940 static HANDLE
4941 dlopen(const char *dll_name, int flags)
4942 {
4943  wchar_t wbuf[PATH_MAX];
4944  (void)flags;
4945  path_to_unicode(NULL, dll_name, wbuf, ARRAY_SIZE(wbuf));
4946  return LoadLibraryW(wbuf);
4947 }
4948 
4949 
4951 static int
4952 dlclose(void *handle)
4953 {
4954  int result;
4955 
4956  if (FreeLibrary((HMODULE)handle) != 0) {
4957  result = 0;
4958  } else {
4959  result = -1;
4960  }
4961 
4962  return result;
4963 }
4964 
4965 
4966 #if defined(__MINGW32__)
4967 /* Enable unused function warning again */
4968 #pragma GCC diagnostic pop
4969 #endif
4970 
4971 #endif
4972 
4973 
4974 #if !defined(NO_CGI)
4975 #define SIGKILL (0)
4976 
4977 static int
4978 kill(pid_t pid, int sig_num)
4979 {
4980  (void)TerminateProcess((HANDLE)pid, (UINT)sig_num);
4981  (void)CloseHandle((HANDLE)pid);
4982  return 0;
4983 }
4984 
4985 
4986 static void
4987 trim_trailing_whitespaces(char *s)
4988 {
4989  char *e = s + strlen(s) - 1;
4990  while ((e > s) && isspace(*(unsigned char *)e)) {
4991  *e-- = '\0';
4992  }
4993 }
4994 
4995 
4996 static pid_t
4997 spawn_process(struct mg_connection *conn,
4998  const char *prog,
4999  char *envblk,
5000  char *envp[],
5001  int fdin[2],
5002  int fdout[2],
5003  int fderr[2],
5004  const char *dir)
5005 {
5006  HANDLE me;
5007  char *p, *interp, full_interp[PATH_MAX], full_dir[PATH_MAX],
5008  cmdline[PATH_MAX], buf[PATH_MAX];
5009  int truncated;
5010  struct mg_file file = STRUCT_FILE_INITIALIZER;
5011  STARTUPINFOA si;
5012  PROCESS_INFORMATION pi = {0};
5013 
5014  (void)envp;
5015 
5016  memset(&si, 0, sizeof(si));
5017  si.cb = sizeof(si);
5018 
5019  si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
5020  si.wShowWindow = SW_HIDE;
5021 
5022  me = GetCurrentProcess();
5023  DuplicateHandle(me,
5024  (HANDLE)_get_osfhandle(fdin[0]),
5025  me,
5026  &si.hStdInput,
5027  0,
5028  TRUE,
5029  DUPLICATE_SAME_ACCESS);
5030  DuplicateHandle(me,
5031  (HANDLE)_get_osfhandle(fdout[1]),
5032  me,
5033  &si.hStdOutput,
5034  0,
5035  TRUE,
5036  DUPLICATE_SAME_ACCESS);
5037  DuplicateHandle(me,
5038  (HANDLE)_get_osfhandle(fderr[1]),
5039  me,
5040  &si.hStdError,
5041  0,
5042  TRUE,
5043  DUPLICATE_SAME_ACCESS);
5044 
5045  /* Mark handles that should not be inherited. See
5046  * https://msdn.microsoft.com/en-us/library/windows/desktop/ms682499%28v=vs.85%29.aspx
5047  */
5048  SetHandleInformation((HANDLE)_get_osfhandle(fdin[1]),
5049  HANDLE_FLAG_INHERIT,
5050  0);
5051  SetHandleInformation((HANDLE)_get_osfhandle(fdout[0]),
5052  HANDLE_FLAG_INHERIT,
5053  0);
5054  SetHandleInformation((HANDLE)_get_osfhandle(fderr[0]),
5055  HANDLE_FLAG_INHERIT,
5056  0);
5057 
5058  /* If CGI file is a script, try to read the interpreter line */
5059  interp = conn->ctx->config[CGI_INTERPRETER];
5060  if (interp == NULL) {
5061  buf[0] = buf[1] = '\0';
5062 
5063  /* Read the first line of the script into the buffer */
5064  mg_snprintf(
5065  conn, &truncated, cmdline, sizeof(cmdline), "%s/%s", dir, prog);
5066 
5067  if (truncated) {
5068  pi.hProcess = (pid_t)-1;
5069  goto spawn_cleanup;
5070  }
5071 
5072  if (mg_fopen(conn, cmdline, MG_FOPEN_MODE_READ, &file)) {
5073  p = (char *)file.access.membuf;
5074  mg_fgets(buf, sizeof(buf), &file, &p);
5075  (void)mg_fclose(&file.access); /* ignore error on read only file */
5076  buf[sizeof(buf) - 1] = '\0';
5077  }
5078 
5079  if ((buf[0] == '#') && (buf[1] == '!')) {
5080  trim_trailing_whitespaces(buf + 2);
5081  } else {
5082  buf[2] = '\0';
5083  }
5084  interp = buf + 2;
5085  }
5086 
5087  if (interp[0] != '\0') {
5088  GetFullPathNameA(interp, sizeof(full_interp), full_interp, NULL);
5089  interp = full_interp;
5090  }
5091  GetFullPathNameA(dir, sizeof(full_dir), full_dir, NULL);
5092 
5093  if (interp[0] != '\0') {
5094  mg_snprintf(conn,
5095  &truncated,
5096  cmdline,
5097  sizeof(cmdline),
5098  "\"%s\" \"%s\\%s\"",
5099  interp,
5100  full_dir,
5101  prog);
5102  } else {
5103  mg_snprintf(conn,
5104  &truncated,
5105  cmdline,
5106  sizeof(cmdline),
5107  "\"%s\\%s\"",
5108  full_dir,
5109  prog);
5110  }
5111 
5112  if (truncated) {
5113  pi.hProcess = (pid_t)-1;
5114  goto spawn_cleanup;
5115  }
5116 
5117  DEBUG_TRACE("Running [%s]", cmdline);
5118  if (CreateProcessA(NULL,
5119  cmdline,
5120  NULL,
5121  NULL,
5122  TRUE,
5123  CREATE_NEW_PROCESS_GROUP,
5124  envblk,
5125  NULL,
5126  &si,
5127  &pi) == 0) {
5128  mg_cry(
5129  conn, "%s: CreateProcess(%s): %ld", __func__, cmdline, (long)ERRNO);
5130  pi.hProcess = (pid_t)-1;
5131  /* goto spawn_cleanup; */
5132  }
5133 
5134 spawn_cleanup:
5135  (void)CloseHandle(si.hStdOutput);
5136  (void)CloseHandle(si.hStdError);
5137  (void)CloseHandle(si.hStdInput);
5138  if (pi.hThread != NULL) {
5139  (void)CloseHandle(pi.hThread);
5140  }
5141 
5142  return (pid_t)pi.hProcess;
5143 }
5144 #endif /* !NO_CGI */
5145 
5146 
5147 static int
5148 set_blocking_mode(SOCKET sock)
5149 {
5150  unsigned long non_blocking = 0;
5151  return ioctlsocket(sock, (long)FIONBIO, &non_blocking);
5152 }
5153 
5154 static int
5155 set_non_blocking_mode(SOCKET sock)
5156 {
5157  unsigned long non_blocking = 1;
5158  return ioctlsocket(sock, (long)FIONBIO, &non_blocking);
5159 }
5160 #else
5161 
5162 static int
5163 mg_stat(const struct mg_connection *conn,
5164  const char *path,
5165  struct mg_file_stat *filep)
5166 {
5167  struct stat st;
5168  if (!filep) {
5169  return 0;
5170  }
5171  memset(filep, 0, sizeof(*filep));
5172 
5173  if (conn && is_file_in_memory(conn, path)) {
5174 
5175  /* Quick fix (for 1.9.x): */
5176  /* mg_stat must fill all fields, also for files in memory */
5177  struct mg_file tmp_file = STRUCT_FILE_INITIALIZER;
5178  open_file_in_memory(conn, path, &tmp_file, MG_FOPEN_MODE_NONE);
5179  filep->size = tmp_file.stat.size;
5180  filep->last_modified = time(NULL);
5181  filep->location = 2;
5182  /* TODO: for 1.10: restructure how files in memory are handled */
5183 
5184  return 1;
5185  }
5186 
5187  if (0 == stat(path, &st)) {
5188  filep->size = (uint64_t)(st.st_size);
5189  filep->last_modified = st.st_mtime;
5190  filep->is_directory = S_ISDIR(st.st_mode);
5191  return 1;
5192  }
5193 
5194  return 0;
5195 }
5196 
5197 
5198 static void
5199 set_close_on_exec(SOCKET fd, struct mg_connection *conn /* may be null */)
5200 {
5201  if (fcntl(fd, F_SETFD, FD_CLOEXEC) != 0) {
5202  if (conn) {
5203  mg_cry(conn,
5204  "%s: fcntl(F_SETFD FD_CLOEXEC) failed: %s",
5205  __func__,
5206  strerror(ERRNO));
5207  }
5208  }
5209 }
5210 
5211 
5212 int
5214 {
5215  pthread_t thread_id;
5216  pthread_attr_t attr;
5217  int result;
5218 
5219  (void)pthread_attr_init(&attr);
5220  (void)pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
5221 
5222 #if defined(USE_STACK_SIZE) && (USE_STACK_SIZE > 1)
5223  /* Compile-time option to control stack size,
5224  * e.g. -DUSE_STACK_SIZE=16384 */
5225  (void)pthread_attr_setstacksize(&attr, USE_STACK_SIZE);
5226 #endif /* defined(USE_STACK_SIZE) && (USE_STACK_SIZE > 1) */
5227 
5228  result = pthread_create(&thread_id, &attr, func, param);
5229  pthread_attr_destroy(&attr);
5230 
5231  return result;
5232 }
5233 
5234 
5235 /* Start a thread storing the thread context. */
5236 static int
5238  void *param,
5239  pthread_t *threadidptr)
5240 {
5241  pthread_t thread_id;
5242  pthread_attr_t attr;
5243  int result;
5244 
5245  (void)pthread_attr_init(&attr);
5246 
5247 #if defined(USE_STACK_SIZE) && (USE_STACK_SIZE > 1)
5248  /* Compile-time option to control stack size,
5249  * e.g. -DUSE_STACK_SIZE=16384 */
5250  (void)pthread_attr_setstacksize(&attr, USE_STACK_SIZE);
5251 #endif /* defined(USE_STACK_SIZE) && USE_STACK_SIZE > 1 */
5252 
5253  result = pthread_create(&thread_id, &attr, func, param);
5254  pthread_attr_destroy(&attr);
5255  if ((result == 0) && (threadidptr != NULL)) {
5256  *threadidptr = thread_id;
5257  }
5258  return result;
5259 }
5260 
5261 
5262 /* Wait for a thread to finish. */
5263 static int
5264 mg_join_thread(pthread_t threadid)
5265 {
5266  int result;
5267 
5268  result = pthread_join(threadid, NULL);
5269  return result;
5270 }
5271 
5272 
5273 #ifndef NO_CGI
5274 static pid_t
5275 spawn_process(struct mg_connection *conn,
5276  const char *prog,
5277  char *envblk,
5278  char *envp[],
5279  int fdin[2],
5280  int fdout[2],
5281  int fderr[2],
5282  const char *dir)
5283 {
5284  pid_t pid;
5285  const char *interp;
5286 
5287  (void)envblk;
5288 
5289  if (conn == NULL) {
5290  return 0;
5291  }
5292 
5293  if ((pid = fork()) == -1) {
5294  /* Parent */
5295  mg_send_http_error(conn,
5296  500,
5297  "Error: Creating CGI process\nfork(): %s",
5298  strerror(ERRNO));
5299  } else if (pid == 0) {
5300  /* Child */
5301  if (chdir(dir) != 0) {
5302  mg_cry(conn, "%s: chdir(%s): %s", __func__, dir, strerror(ERRNO));
5303  } else if (dup2(fdin[0], 0) == -1) {
5304  mg_cry(conn,
5305  "%s: dup2(%d, 0): %s",
5306  __func__,
5307  fdin[0],
5308  strerror(ERRNO));
5309  } else if (dup2(fdout[1], 1) == -1) {
5310  mg_cry(conn,
5311  "%s: dup2(%d, 1): %s",
5312  __func__,
5313  fdout[1],
5314  strerror(ERRNO));
5315  } else if (dup2(fderr[1], 2) == -1) {
5316  mg_cry(conn,
5317  "%s: dup2(%d, 2): %s",
5318  __func__,
5319  fderr[1],
5320  strerror(ERRNO));
5321  } else {
5322  /* Keep stderr and stdout in two different pipes.
5323  * Stdout will be sent back to the client,
5324  * stderr should go into a server error log. */
5325  (void)close(fdin[0]);
5326  (void)close(fdout[1]);
5327  (void)close(fderr[1]);
5328 
5329  /* Close write end fdin and read end fdout and fderr */
5330  (void)close(fdin[1]);
5331  (void)close(fdout[0]);
5332  (void)close(fderr[0]);
5333 
5334  /* After exec, all signal handlers are restored to their default
5335  * values, with one exception of SIGCHLD. According to
5336  * POSIX.1-2001 and Linux's implementation, SIGCHLD's handler will
5337  * leave unchanged after exec if it was set to be ignored. Restore
5338  * it to default action. */
5339  signal(SIGCHLD, SIG_DFL);
5340 
5341  interp = conn->ctx->config[CGI_INTERPRETER];
5342  if (interp == NULL) {
5343  (void)execle(prog, prog, NULL, envp);
5344  mg_cry(conn,
5345  "%s: execle(%s): %s",
5346  __func__,
5347  prog,
5348  strerror(ERRNO));
5349  } else {
5350  (void)execle(interp, interp, prog, NULL, envp);
5351  mg_cry(conn,
5352  "%s: execle(%s %s): %s",
5353  __func__,
5354  interp,
5355  prog,
5356  strerror(ERRNO));
5357  }
5358  }
5359  exit(EXIT_FAILURE);
5360  }
5361 
5362  return pid;
5363 }
5364 #endif /* !NO_CGI */
5365 
5366 
5367 static int
5369 {
5370  int flags = fcntl(sock, F_GETFL, 0);
5371  if (flags < 0) {
5372  return -1;
5373  }
5374 
5375  if (fcntl(sock, F_SETFL, (flags | O_NONBLOCK)) < 0) {
5376  return -1;
5377  }
5378  return 0;
5379 }
5380 
5381 static int
5382 set_blocking_mode(SOCKET sock)
5383 {
5384  int flags = fcntl(sock, F_GETFL, 0);
5385  if (flags < 0) {
5386  return -1;
5387  }
5388 
5389  if (fcntl(sock, F_SETFL, flags & (~(int)(O_NONBLOCK))) < 0) {
5390  return -1;
5391  }
5392  return 0;
5393 }
5394 #endif /* _WIN32 / else */
5395 
5396 /* End of initial operating system specific define block. */
5397 
5398 
5399 /* Get a random number (independent of C rand function) */
5400 static uint64_t
5402 {
5403  static uint64_t lfsr = 0; /* Linear feedback shift register */
5404  static uint64_t lcg = 0; /* Linear congruential generator */
5405  uint64_t now = mg_get_current_time_ns();
5406 
5407  if (lfsr == 0) {
5408  /* lfsr will be only 0 if has not been initialized,
5409  * so this code is called only once. */
5410  lfsr = mg_get_current_time_ns();
5411  lcg = mg_get_current_time_ns();
5412  } else {
5413  /* Get the next step of both random number generators. */
5414  lfsr = (lfsr >> 1)
5415  | ((((lfsr >> 0) ^ (lfsr >> 1) ^ (lfsr >> 3) ^ (lfsr >> 4)) & 1)
5416  << 63);
5417  lcg = lcg * 6364136223846793005LL + 1442695040888963407LL;
5418  }
5419 
5420  /* Combining two pseudo-random number generators and a high resolution
5421  * part
5422  * of the current server time will make it hard (impossible?) to guess
5423  * the
5424  * next number. */
5425  return (lfsr ^ lcg ^ now);
5426 }
5427 
5428 
5429 static int
5430 mg_poll(struct pollfd *pfd,
5431  unsigned int n,
5432  int milliseconds,
5433  volatile int *stop_server)
5434 {
5435  /* Call poll, but only for a maximum time of a few seconds.
5436  * This will allow to stop the server after some seconds, instead
5437  * of having to wait for a long socket timeout. */
5438  int ms_now = SOCKET_TIMEOUT_QUANTUM; /* Sleep quantum in ms */
5439 
5440  do {
5441  int result;
5442 
5443  if (*stop_server) {
5444  /* Shut down signal */
5445  return -2;
5446  }
5447 
5448  if ((milliseconds >= 0) && (milliseconds < ms_now)) {
5449  ms_now = milliseconds;
5450  }
5451 
5452  result = poll(pfd, n, ms_now);
5453  if (result != 0) {
5454  /* Poll returned either success (1) or error (-1).
5455  * Forward both to the caller. */
5456  return result;
5457  }
5458 
5459  /* Poll returned timeout (0). */
5460  if (milliseconds > 0) {
5461  milliseconds -= ms_now;
5462  }
5463 
5464  } while (milliseconds != 0);
5465 
5466  /* timeout: return 0 */
5467  return 0;
5468 }
5469 
5470 
5471 /* Write data to the IO channel - opened file descriptor, socket or SSL
5472  * descriptor.
5473  * Return value:
5474  * >=0 .. number of bytes successfully written
5475  * -1 .. timeout
5476  * -2 .. error
5477  */
5478 static int
5479 push_inner(struct mg_context *ctx,
5480  FILE *fp,
5481  SOCKET sock,
5482  SSL *ssl,
5483  const char *buf,
5484  int len,
5485  double timeout)
5486 {
5487  uint64_t start = 0, now = 0, timeout_ns = 0;
5488  int n, err;
5489  unsigned ms_wait = SOCKET_TIMEOUT_QUANTUM; /* Sleep quantum in ms */
5490 
5491 #ifdef _WIN32
5492  typedef int len_t;
5493 #else
5494  typedef size_t len_t;
5495 #endif
5496 
5497  if (timeout > 0) {
5498  now = mg_get_current_time_ns();
5499  start = now;
5500  timeout_ns = (uint64_t)(timeout * 1.0E9);
5501  }
5502 
5503  if (ctx == NULL) {
5504  return -2;
5505  }
5506 
5507 #ifdef NO_SSL
5508  if (ssl) {
5509  return -2;
5510  }
5511 #endif
5512 
5513  /* Try to read until it succeeds, fails, times out, or the server
5514  * shuts down. */
5515  for (;;) {
5516 
5517 #ifndef NO_SSL
5518  if (ssl != NULL) {
5519  n = SSL_write(ssl, buf, len);
5520  if (n <= 0) {
5521  err = SSL_get_error(ssl, n);
5522  if ((err == SSL_ERROR_SYSCALL) && (n == -1)) {
5523  err = ERRNO;
5524  } else if ((err == SSL_ERROR_WANT_READ)
5525  || (err == SSL_ERROR_WANT_WRITE)) {
5526  n = 0;
5527  } else {
5528  DEBUG_TRACE("SSL_write() failed, error %d", err);
5529  return -2;
5530  }
5531  } else {
5532  err = 0;
5533  }
5534  } else
5535 #endif
5536  if (fp != NULL) {
5537  n = (int)fwrite(buf, 1, (size_t)len, fp);
5538  if (ferror(fp)) {
5539  n = -1;
5540  err = ERRNO;
5541  } else {
5542  err = 0;
5543  }
5544  } else {
5545  n = (int)send(sock, buf, (len_t)len, MSG_NOSIGNAL);
5546  err = (n < 0) ? ERRNO : 0;
5547 #ifdef _WIN32
5548  if (err == WSAEWOULDBLOCK) {
5549  err = 0;
5550  n = 0;
5551  }
5552 #else
5553  if (err == EWOULDBLOCK) {
5554  err = 0;
5555  n = 0;
5556  }
5557 #endif
5558  if (n < 0) {
5559  /* shutdown of the socket at client side */
5560  return -2;
5561  }
5562  }
5563 
5564  if (ctx->stop_flag) {
5565  return -2;
5566  }
5567 
5568  if ((n > 0) || ((n == 0) && (len == 0))) {
5569  /* some data has been read, or no data was requested */
5570  return n;
5571  }
5572  if (n < 0) {
5573  /* socket error - check errno */
5574  DEBUG_TRACE("send() failed, error %d", err);
5575 
5576  /* TODO (mid): error handling depending on the error code.
5577  * These codes are different between Windows and Linux.
5578  * Currently there is no problem with failing send calls,
5579  * if there is a reproducible situation, it should be
5580  * investigated in detail.
5581  */
5582  return -2;
5583  }
5584 
5585  /* Only in case n=0 (timeout), repeat calling the write function */
5586 
5587  /* If send failed, wait before retry */
5588  if (fp != NULL) {
5589  /* For files, just wait a fixed time,
5590  * maybe an average disk seek time. */
5591  mg_sleep(ms_wait > 10 ? 10 : ms_wait);
5592  } else {
5593  /* For sockets, wait for the socket using select */
5594  fd_set wfds;
5595  struct timeval tv;
5596  int sret;
5597 
5598 #if defined(__GNUC__) || defined(__MINGW32__)
5599 /* GCC seems to have a flaw with it's own socket macros:
5600  * http://www.linuxquestions.org/questions/programming-9/impossible-to-use-gcc-with-wconversion-and-standard-socket-macros-841935/
5601  */
5602 #pragma GCC diagnostic push
5603 #pragma GCC diagnostic ignored "-Wsign-conversion"
5604 #endif
5605 
5606  FD_ZERO(&wfds);
5607  FD_SET(sock, &wfds);
5608  tv.tv_sec = (time_t)(ms_wait / 1000);
5609  tv.tv_usec = (long)((ms_wait % 1000) * 1000);
5610 
5611  sret = select((int)sock + 1, NULL, &wfds, NULL, &tv);
5612 
5613 #if defined(__GNUC__) || defined(__MINGW32__)
5614 #pragma GCC diagnostic pop
5615 #endif
5616 
5617  if (sret > 0) {
5618  /* We got ready to write. Don't check the timeout
5619  * but directly go back to write again. */
5620  continue;
5621  }
5622  }
5623 
5624  if (timeout > 0) {
5625  now = mg_get_current_time_ns();
5626  if ((now - start) > timeout_ns) {
5627  /* Timeout */
5628  break;
5629  }
5630  }
5631  }
5632 
5633  (void)err; /* Avoid unused warning if NO_SSL is set and DEBUG_TRACE is not
5634  used */
5635 
5636  return -1;
5637 }
5638 
5639 
5640 static int64_t
5641 push_all(struct mg_context *ctx,
5642  FILE *fp,
5643  SOCKET sock,
5644  SSL *ssl,
5645  const char *buf,
5646  int64_t len)
5647 {
5648  double timeout = -1.0;
5649  int64_t n, nwritten = 0;
5650 
5651  if (ctx == NULL) {
5652  return -1;
5653  }
5654 
5655  if (ctx->config[REQUEST_TIMEOUT]) {
5656  timeout = atoi(ctx->config[REQUEST_TIMEOUT]) / 1000.0;
5657  }
5658 
5659  while ((len > 0) && (ctx->stop_flag == 0)) {
5660  n = push_inner(ctx, fp, sock, ssl, buf + nwritten, (int)len, timeout);
5661  if (n < 0) {
5662  if (nwritten == 0) {
5663  nwritten = n; /* Propagate the error */
5664  }
5665  break;
5666  } else if (n == 0) {
5667  break; /* No more data to write */
5668  } else {
5669  nwritten += n;
5670  len -= n;
5671  }
5672  }
5673 
5674  return nwritten;
5675 }
5676 
5677 
5678 /* Read from IO channel - opened file descriptor, socket, or SSL descriptor.
5679  * Return value:
5680  * >=0 .. number of bytes successfully read
5681  * -1 .. timeout
5682  * -2 .. error
5683  */
5684 static int
5685 pull_inner(FILE *fp,
5686  struct mg_connection *conn,
5687  char *buf,
5688  int len,
5689  double timeout)
5690 {
5691  int nread, err = 0;
5692 
5693 #ifdef _WIN32
5694  typedef int len_t;
5695 #else
5696  typedef size_t len_t;
5697 #endif
5698 #ifndef NO_SSL
5699  int ssl_pending;
5700 #endif
5701 
5702  /* We need an additional wait loop around this, because in some cases
5703  * with TLSwe may get data from the socket but not from SSL_read.
5704  * In this case we need to repeat at least once.
5705  */
5706 
5707  if (fp != NULL) {
5708 #if !defined(_WIN32_WCE)
5709  /* Use read() instead of fread(), because if we're reading from the
5710  * CGI pipe, fread() may block until IO buffer is filled up. We
5711  * cannot afford to block and must pass all read bytes immediately
5712  * to the client. */
5713  nread = (int)read(fileno(fp), buf, (size_t)len);
5714 #else
5715  /* WinCE does not support CGI pipes */
5716  nread = (int)fread(buf, 1, (size_t)len, fp);
5717 #endif
5718  err = (nread < 0) ? ERRNO : 0;
5719  if ((nread == 0) && (len > 0)) {
5720  /* Should get data, but got EOL */
5721  return -2;
5722  }
5723 
5724 #ifndef NO_SSL
5725  } else if ((conn->ssl != NULL)
5726  && ((ssl_pending = SSL_pending(conn->ssl)) > 0)) {
5727  /* We already know there is no more data buffered in conn->buf
5728  * but there is more available in the SSL layer. So don't poll
5729  * conn->client.sock yet. */
5730  if (ssl_pending > len) {
5731  ssl_pending = len;
5732  }
5733  nread = SSL_read(conn->ssl, buf, ssl_pending);
5734  if (nread <= 0) {
5735  err = SSL_get_error(conn->ssl, nread);
5736  if ((err == SSL_ERROR_SYSCALL) && (nread == -1)) {
5737  err = ERRNO;
5738  } else if ((err == SSL_ERROR_WANT_READ)
5739  || (err == SSL_ERROR_WANT_WRITE)) {
5740  nread = 0;
5741  } else {
5742  DEBUG_TRACE("SSL_read() failed, error %d", err);
5743  return -1;
5744  }
5745  } else {
5746  err = 0;
5747  }
5748 
5749  } else if (conn->ssl != NULL) {
5750 
5751  struct pollfd pfd[1];
5752  int pollres;
5753 
5754  pfd[0].fd = conn->client.sock;
5755  pfd[0].events = POLLIN;
5756  pollres =
5757  mg_poll(pfd, 1, (int)(timeout * 1000.0), &(conn->ctx->stop_flag));
5758  if (conn->ctx->stop_flag) {
5759  return -2;
5760  }
5761  if (pollres > 0) {
5762  nread = SSL_read(conn->ssl, buf, len);
5763  if (nread <= 0) {
5764  err = SSL_get_error(conn->ssl, nread);
5765  if ((err == SSL_ERROR_SYSCALL) && (nread == -1)) {
5766  err = ERRNO;
5767  } else if ((err == SSL_ERROR_WANT_READ)
5768  || (err == SSL_ERROR_WANT_WRITE)) {
5769  nread = 0;
5770  } else {
5771  DEBUG_TRACE("SSL_read() failed, error %d", err);
5772  return -2;
5773  }
5774  } else {
5775  err = 0;
5776  }
5777 
5778  } else if (pollres < 0) {
5779  /* Error */
5780  return -2;
5781  } else {
5782  /* pollres = 0 means timeout */
5783  nread = 0;
5784  }
5785 #endif
5786 
5787  } else {
5788  struct pollfd pfd[1];
5789  int pollres;
5790 
5791  pfd[0].fd = conn->client.sock;
5792  pfd[0].events = POLLIN;
5793  pollres =
5794  mg_poll(pfd, 1, (int)(timeout * 1000.0), &(conn->ctx->stop_flag));
5795  if (conn->ctx->stop_flag) {
5796  return -2;
5797  }
5798  if (pollres > 0) {
5799  nread = (int)recv(conn->client.sock, buf, (len_t)len, 0);
5800  err = (nread < 0) ? ERRNO : 0;
5801  if (nread <= 0) {
5802  /* shutdown of the socket at client side */
5803  return -2;
5804  }
5805  } else if (pollres < 0) {
5806  /* error callint poll */
5807  return -2;
5808  } else {
5809  /* pollres = 0 means timeout */
5810  nread = 0;
5811  }
5812  }
5813 
5814  if (conn->ctx->stop_flag) {
5815  return -2;
5816  }
5817 
5818  if ((nread > 0) || ((nread == 0) && (len == 0))) {
5819  /* some data has been read, or no data was requested */
5820  return nread;
5821  }
5822 
5823  if (nread < 0) {
5824 /* socket error - check errno */
5825 #ifdef _WIN32
5826  if (err == WSAEWOULDBLOCK) {
5827  /* TODO (low): check if this is still required */
5828  /* standard case if called from close_socket_gracefully */
5829  return -2;
5830  } else if (err == WSAETIMEDOUT) {
5831  /* TODO (low): check if this is still required */
5832  /* timeout is handled by the while loop */
5833  return 0;
5834  } else if (err == WSAECONNABORTED) {
5835  /* See https://www.chilkatsoft.com/p/p_299.asp */
5836  return -2;
5837  } else {
5838  DEBUG_TRACE("recv() failed, error %d", err);
5839  return -2;
5840  }
5841 #else
5842  /* TODO: POSIX returns either EAGAIN or EWOULDBLOCK in both cases,
5843  * if the timeout is reached and if the socket was set to non-
5844  * blocking in close_socket_gracefully, so we can not distinguish
5845  * here. We have to wait for the timeout in both cases for now.
5846  */
5847  if ((err == EAGAIN) || (err == EWOULDBLOCK) || (err == EINTR)) {
5848  /* TODO (low): check if this is still required */
5849  /* EAGAIN/EWOULDBLOCK:
5850  * standard case if called from close_socket_gracefully
5851  * => should return -1 */
5852  /* or timeout occured
5853  * => the code must stay in the while loop */
5854 
5855  /* EINTR can be generated on a socket with a timeout set even
5856  * when SA_RESTART is effective for all relevant signals
5857  * (see signal(7)).
5858  * => stay in the while loop */
5859  } else {
5860  DEBUG_TRACE("recv() failed, error %d", err);
5861  return -2;
5862  }
5863 #endif
5864  }
5865 
5866  /* Timeout occured, but no data available. */
5867  return -1;
5868 }
5869 
5870 
5871 static int
5872 pull_all(FILE *fp, struct mg_connection *conn, char *buf, int len)
5873 {
5874  int n, nread = 0;
5875  double timeout = -1.0;
5876  uint64_t start_time = 0, now = 0, timeout_ns = 0;
5877 
5878  if (conn->ctx->config[REQUEST_TIMEOUT]) {
5879  timeout = atoi(conn->ctx->config[REQUEST_TIMEOUT]) / 1000.0;
5880  }
5881  if (timeout >= 0.0) {
5882  start_time = mg_get_current_time_ns();
5883  timeout_ns = (uint64_t)(timeout * 1.0E9);
5884  }
5885 
5886  while ((len > 0) && (conn->ctx->stop_flag == 0)) {
5887  n = pull_inner(fp, conn, buf + nread, len, timeout);
5888  if (n == -2) {
5889  if (nread == 0) {
5890  nread = -1; /* Propagate the error */
5891  }
5892  break;
5893  } else if (n == -1) {
5894  /* timeout */
5895  if (timeout >= 0.0) {
5896  now = mg_get_current_time_ns();
5897  if ((now - start_time) <= timeout_ns) {
5898  continue;
5899  }
5900  }
5901  break;
5902  } else if (n == 0) {
5903  break; /* No more data to read */
5904  } else {
5905  conn->consumed_content += n;
5906  nread += n;
5907  len -= n;
5908  }
5909  }
5910 
5911  return nread;
5912 }
5913 
5914 
5915 static void
5916 discard_unread_request_data(struct mg_connection *conn)
5917 {
5918  char buf[MG_BUF_LEN];
5919  size_t to_read;
5920  int nread;
5921 
5922  if (conn == NULL) {
5923  return;
5924  }
5925 
5926  to_read = sizeof(buf);
5927 
5928  if (conn->is_chunked) {
5929  /* Chunked encoding: 3=chunk read completely
5930  * completely */
5931  while (conn->is_chunked != 3) {
5932  nread = mg_read(conn, buf, to_read);
5933  if (nread <= 0) {
5934  break;
5935  }
5936  }
5937 
5938  } else {
5939  /* Not chunked: content length is known */
5940  while (conn->consumed_content < conn->content_len) {
5941  if (to_read
5942  > (size_t)(conn->content_len - conn->consumed_content)) {
5943  to_read = (size_t)(conn->content_len - conn->consumed_content);
5944  }
5945 
5946  nread = mg_read(conn, buf, to_read);
5947  if (nread <= 0) {
5948  break;
5949  }
5950  }
5951  }
5952 }
5953 
5954 
5955 static int
5956 mg_read_inner(struct mg_connection *conn, void *buf, size_t len)
5957 {
5958  int64_t n, buffered_len, nread;
5959  int64_t len64 =
5960  (int64_t)((len > INT_MAX) ? INT_MAX : len); /* since the return value is
5961  * int, we may not read more
5962  * bytes */
5963  const char *body;
5964 
5965  if (conn == NULL) {
5966  return 0;
5967  }
5968 
5969  /* If Content-Length is not set for a request with body data
5970  * (e.g., a PUT or POST request), we do not know in advance
5971  * how much data should be read. */
5972  if (conn->consumed_content == 0) {
5973  if (conn->is_chunked == 1) {
5974  conn->content_len = len64;
5975  conn->is_chunked = 2;
5976  } else if (conn->content_len == -1) {
5977  /* The body data is completed when the connection
5978  * is closed. */
5979  conn->content_len = INT64_MAX;
5980  conn->must_close = 1;
5981  }
5982  }
5983 
5984  nread = 0;
5985  if (conn->consumed_content < conn->content_len) {
5986  /* Adjust number of bytes to read. */
5987  int64_t left_to_read = conn->content_len - conn->consumed_content;
5988  if (left_to_read < len64) {
5989  /* Do not read more than the total content length of the
5990  * request.
5991  */
5992  len64 = left_to_read;
5993  }
5994 
5995  /* Return buffered data */
5996  buffered_len = (int64_t)(conn->data_len) - (int64_t)conn->request_len
5997  - conn->consumed_content;
5998  if (buffered_len > 0) {
5999  if (len64 < buffered_len) {
6000  buffered_len = len64;
6001  }
6002  body = conn->buf + conn->request_len + conn->consumed_content;
6003  memcpy(buf, body, (size_t)buffered_len);
6004  len64 -= buffered_len;
6005  conn->consumed_content += buffered_len;
6006  nread += buffered_len;
6007  buf = (char *)buf + buffered_len;
6008  }
6009 
6010  /* We have returned all buffered data. Read new data from the remote
6011  * socket.
6012  */
6013  if ((n = pull_all(NULL, conn, (char *)buf, (int)len64)) >= 0) {
6014  nread += n;
6015  } else {
6016  nread = ((nread > 0) ? nread : n);
6017  }
6018  }
6019  return (int)nread;
6020 }
6021 
6022 
6023 static char
6024 mg_getc(struct mg_connection *conn)
6025 {
6026  char c;
6027  if (conn == NULL) {
6028  return 0;
6029  }
6030  if (mg_read_inner(conn, &c, 1) <= 0) {
6031  return (char)0;
6032  }
6033  return c;
6034 }
6035 
6036 
6037 int
6038 mg_read(struct mg_connection *conn, void *buf, size_t len)
6039 {
6040  if (len > INT_MAX) {
6041  len = INT_MAX;
6042  }
6043 
6044  if (conn == NULL) {
6045  return 0;
6046  }
6047 
6048  if (conn->is_chunked) {
6049  size_t all_read = 0;
6050 
6051  while (len > 0) {
6052  if (conn->is_chunked == 3) {
6053  /* No more data left to read */
6054  return 0;
6055  }
6056 
6057  if (conn->chunk_remainder) {
6058  /* copy from the remainder of the last received chunk */
6059  long read_ret;
6060  size_t read_now =
6061  ((conn->chunk_remainder > len) ? (len)
6062  : (conn->chunk_remainder));
6063 
6064  conn->content_len += (int)read_now;
6065  read_ret =
6066  mg_read_inner(conn, (char *)buf + all_read, read_now);
6067 
6068  if (read_ret < 1) {
6069  /* read error */
6070  return -1;
6071  }
6072 
6073  all_read += (size_t)read_ret;
6074  conn->chunk_remainder -= (size_t)read_ret;
6075  len -= (size_t)read_ret;
6076 
6077  if (conn->chunk_remainder == 0) {
6078  /* Add data bytes in the current chunk have been read,
6079  * so we are expecting \r\n now. */
6080  char x1, x2;
6081  conn->content_len += 2;
6082  x1 = mg_getc(conn);
6083  x2 = mg_getc(conn);
6084  if ((x1 != '\r') || (x2 != '\n')) {
6085  /* Protocol violation */
6086  return -1;
6087  }
6088  }
6089 
6090  } else {
6091  /* fetch a new chunk */
6092  int i = 0;
6093  char lenbuf[64];
6094  char *end = 0;
6095  unsigned long chunkSize = 0;
6096 
6097  for (i = 0; i < ((int)sizeof(lenbuf) - 1); i++) {
6098  conn->content_len++;
6099  lenbuf[i] = mg_getc(conn);
6100  if ((i > 0) && (lenbuf[i] == '\r')
6101  && (lenbuf[i - 1] != '\r')) {
6102  continue;
6103  }
6104  if ((i > 1) && (lenbuf[i] == '\n')
6105  && (lenbuf[i - 1] == '\r')) {
6106  lenbuf[i + 1] = 0;
6107  chunkSize = strtoul(lenbuf, &end, 16);
6108  if (chunkSize == 0) {
6109  /* regular end of content */
6110  conn->is_chunked = 3;
6111  }
6112  break;
6113  }
6114  if (!isxdigit(lenbuf[i])) {
6115  /* illegal character for chunk length */
6116  return -1;
6117  }
6118  }
6119  if ((end == NULL) || (*end != '\r')) {
6120  /* chunksize not set correctly */
6121  return -1;
6122  }
6123  if (chunkSize == 0) {
6124  break;
6125  }
6126 
6127  conn->chunk_remainder = chunkSize;
6128  }
6129  }
6130 
6131  return (int)all_read;
6132  }
6133  return mg_read_inner(conn, buf, len);
6134 }
6135 
6136 
6137 int
6138 mg_write(struct mg_connection *conn, const void *buf, size_t len)
6139 {
6140  time_t now;
6141  int64_t n, total, allowed;
6142 
6143  if (conn == NULL) {
6144  return 0;
6145  }
6146 
6147  if (conn->throttle > 0) {
6148  if ((now = time(NULL)) != conn->last_throttle_time) {
6149  conn->last_throttle_time = now;
6150  conn->last_throttle_bytes = 0;
6151  }
6152  allowed = conn->throttle - conn->last_throttle_bytes;
6153  if (allowed > (int64_t)len) {
6154  allowed = (int64_t)len;
6155  }
6156  if ((total = push_all(conn->ctx,
6157  NULL,
6158  conn->client.sock,
6159  conn->ssl,
6160  (const char *)buf,
6161  (int64_t)allowed)) == allowed) {
6162  buf = (const char *)buf + total;
6163  conn->last_throttle_bytes += total;
6164  while ((total < (int64_t)len) && (conn->ctx->stop_flag == 0)) {
6165  allowed = (conn->throttle > ((int64_t)len - total))
6166  ? (int64_t)len - total
6167  : conn->throttle;
6168  if ((n = push_all(conn->ctx,
6169  NULL,
6170  conn->client.sock,
6171  conn->ssl,
6172  (const char *)buf,
6173  (int64_t)allowed)) != allowed) {
6174  break;
6175  }
6176  sleep(1);
6177  conn->last_throttle_bytes = allowed;
6178  conn->last_throttle_time = time(NULL);
6179  buf = (const char *)buf + n;
6180  total += n;
6181  }
6182  }
6183  } else {
6184  total = push_all(conn->ctx,
6185  NULL,
6186  conn->client.sock,
6187  conn->ssl,
6188  (const char *)buf,
6189  (int64_t)len);
6190  }
6191  if (total > 0) {
6192  conn->num_bytes_sent += total;
6193  }
6194  return (int)total;
6195 }
6196 
6197 
6198 /* Send a chunk, if "Transfer-Encoding: chunked" is used */
6199 int
6200 mg_send_chunk(struct mg_connection *conn,
6201  const char *chunk,
6202  unsigned int chunk_len)
6203 {
6204  char lenbuf[16];
6205  size_t lenbuf_len;
6206  int ret;
6207  int t;
6208 
6209  /* First store the length information in a text buffer. */
6210  sprintf(lenbuf, "%x\r\n", chunk_len);
6211  lenbuf_len = strlen(lenbuf);
6212 
6213  /* Then send length information, chunk and terminating \r\n. */
6214  ret = mg_write(conn, lenbuf, lenbuf_len);
6215  if (ret != (int)lenbuf_len) {
6216  return -1;
6217  }
6218  t = ret;
6219 
6220  ret = mg_write(conn, chunk, chunk_len);
6221  if (ret != (int)chunk_len) {
6222  return -1;
6223  }
6224  t += ret;
6225 
6226  ret = mg_write(conn, "\r\n", 2);
6227  if (ret != 2) {
6228  return -1;
6229  }
6230  t += ret;
6231 
6232  return t;
6233 }
6234 
6235 
6236 /* Alternative alloc_vprintf() for non-compliant C runtimes */
6237 static int
6238 alloc_vprintf2(char **buf, const char *fmt, va_list ap)
6239 {
6240  va_list ap_copy;
6241  size_t size = MG_BUF_LEN / 4;
6242  int len = -1;
6243 
6244  *buf = NULL;
6245  while (len < 0) {
6246  if (*buf) {
6247  mg_free(*buf);
6248  }
6249 
6250  size *= 4;
6251  *buf = (char *)mg_malloc(size);
6252  if (!*buf) {
6253  break;
6254  }
6255 
6256  va_copy(ap_copy, ap);
6257  len = vsnprintf_impl(*buf, size - 1, fmt, ap_copy);
6258  va_end(ap_copy);
6259  (*buf)[size - 1] = 0;
6260  }
6261 
6262  return len;
6263 }
6264 
6265 
6266 /* Print message to buffer. If buffer is large enough to hold the message,
6267  * return buffer. If buffer is to small, allocate large enough buffer on
6268  * heap,
6269  * and return allocated buffer. */
6270 static int
6271 alloc_vprintf(char **out_buf,
6272  char *prealloc_buf,
6273  size_t prealloc_size,
6274  const char *fmt,
6275  va_list ap)
6276 {
6277  va_list ap_copy;
6278  int len;
6279 
6280  /* Windows is not standard-compliant, and vsnprintf() returns -1 if
6281  * buffer is too small. Also, older versions of msvcrt.dll do not have
6282  * _vscprintf(). However, if size is 0, vsnprintf() behaves correctly.
6283  * Therefore, we make two passes: on first pass, get required message
6284  * length.
6285  * On second pass, actually print the message. */
6286  va_copy(ap_copy, ap);
6287  len = vsnprintf_impl(NULL, 0, fmt, ap_copy);
6288  va_end(ap_copy);
6289 
6290  if (len < 0) {
6291  /* C runtime is not standard compliant, vsnprintf() returned -1.
6292  * Switch to alternative code path that uses incremental
6293  * allocations.
6294  */
6295  va_copy(ap_copy, ap);
6296  len = alloc_vprintf2(out_buf, fmt, ap_copy);
6297  va_end(ap_copy);
6298 
6299  } else if ((size_t)(len) >= prealloc_size) {
6300  /* The pre-allocated buffer not large enough. */
6301  /* Allocate a new buffer. */
6302  *out_buf = (char *)mg_malloc((size_t)(len) + 1);
6303  if (!*out_buf) {
6304  /* Allocation failed. Return -1 as "out of memory" error. */
6305  return -1;
6306  }
6307  /* Buffer allocation successful. Store the string there. */
6308  va_copy(ap_copy, ap);
6310  vsnprintf_impl(*out_buf, (size_t)(len) + 1, fmt, ap_copy));
6311  va_end(ap_copy);
6312 
6313  } else {
6314  /* The pre-allocated buffer is large enough.
6315  * Use it to store the string and return the address. */
6316  va_copy(ap_copy, ap);
6318  vsnprintf_impl(prealloc_buf, prealloc_size, fmt, ap_copy));
6319  va_end(ap_copy);
6320  *out_buf = prealloc_buf;
6321  }
6322 
6323  return len;
6324 }
6325 
6326 
6327 static int
6328 mg_vprintf(struct mg_connection *conn, const char *fmt, va_list ap)
6329 {
6330  char mem[MG_BUF_LEN];
6331  char *buf = NULL;
6332  int len;
6333 
6334  if ((len = alloc_vprintf(&buf, mem, sizeof(mem), fmt, ap)) > 0) {
6335  len = mg_write(conn, buf, (size_t)len);
6336  }
6337  if ((buf != mem) && (buf != NULL)) {
6338  mg_free(buf);
6339  }
6340 
6341  return len;
6342 }
6343 
6344 
6345 int
6346 mg_printf(struct mg_connection *conn, const char *fmt, ...)
6347 {
6348  va_list ap;
6349  int result;
6350 
6351  va_start(ap, fmt);
6352  result = mg_vprintf(conn, fmt, ap);
6353  va_end(ap);
6354 
6355  return result;
6356 }
6357 
6358 
6359 int
6360 mg_url_decode(const char *src,
6361  int src_len,
6362  char *dst,
6363  int dst_len,
6364  int is_form_url_encoded)
6365 {
6366  int i, j, a, b;
6367 #define HEXTOI(x) (isdigit(x) ? (x - '0') : (x - 'W'))
6368 
6369  for (i = j = 0; (i < src_len) && (j < (dst_len - 1)); i++, j++) {
6370  if ((i < src_len - 2) && (src[i] == '%')
6371  && isxdigit(*(const unsigned char *)(src + i + 1))
6372  && isxdigit(*(const unsigned char *)(src + i + 2))) {
6373  a = tolower(*(const unsigned char *)(src + i + 1));
6374  b = tolower(*(const unsigned char *)(src + i + 2));
6375  dst[j] = (char)((HEXTOI(a) << 4) | HEXTOI(b));
6376  i += 2;
6377  } else if (is_form_url_encoded && (src[i] == '+')) {
6378  dst[j] = ' ';
6379  } else {
6380  dst[j] = src[i];
6381  }
6382  }
6383 
6384  dst[j] = '\0'; /* Null-terminate the destination */
6385 
6386  return (i >= src_len) ? j : -1;
6387 }
6388 
6389 
6390 int
6391 mg_get_var(const char *data,
6392  size_t data_len,
6393  const char *name,
6394  char *dst,
6395  size_t dst_len)
6396 {
6397  return mg_get_var2(data, data_len, name, dst, dst_len, 0);
6398 }
6399 
6400 
6401 int
6402 mg_get_var2(const char *data,
6403  size_t data_len,
6404  const char *name,
6405  char *dst,
6406  size_t dst_len,
6407  size_t occurrence)
6408 {
6409  const char *p, *e, *s;
6410  size_t name_len;
6411  int len;
6412 
6413  if ((dst == NULL) || (dst_len == 0)) {
6414  len = -2;
6415  } else if ((data == NULL) || (name == NULL) || (data_len == 0)) {
6416  len = -1;
6417  dst[0] = '\0';
6418  } else {
6419  name_len = strlen(name);
6420  e = data + data_len;
6421  len = -1;
6422  dst[0] = '\0';
6423 
6424  /* data is "var1=val1&var2=val2...". Find variable first */
6425  for (p = data; p + name_len < e; p++) {
6426  if (((p == data) || (p[-1] == '&')) && (p[name_len] == '=')
6427  && !mg_strncasecmp(name, p, name_len) && 0 == occurrence--) {
6428  /* Point p to variable value */
6429  p += name_len + 1;
6430 
6431  /* Point s to the end of the value */
6432  s = (const char *)memchr(p, '&', (size_t)(e - p));
6433  if (s == NULL) {
6434  s = e;
6435  }
6436  /* assert(s >= p); */
6437  if (s < p) {
6438  return -3;
6439  }
6440 
6441  /* Decode variable into destination buffer */
6442  len = mg_url_decode(p, (int)(s - p), dst, (int)dst_len, 1);
6443 
6444  /* Redirect error code from -1 to -2 (destination buffer too
6445  * small). */
6446  if (len == -1) {
6447  len = -2;
6448  }
6449  break;
6450  }
6451  }
6452  }
6453 
6454  return len;
6455 }
6456 
6457 
6458 /* HCP24: some changes to compare hole var_name */
6459 int
6460 mg_get_cookie(const char *cookie_header,
6461  const char *var_name,
6462  char *dst,
6463  size_t dst_size)
6464 {
6465  const char *s, *p, *end;
6466  int name_len, len = -1;
6467 
6468  if ((dst == NULL) || (dst_size == 0)) {
6469  return -2;
6470  }
6471 
6472  dst[0] = '\0';
6473  if ((var_name == NULL) || ((s = cookie_header) == NULL)) {
6474  return -1;
6475  }
6476 
6477  name_len = (int)strlen(var_name);
6478  end = s + strlen(s);
6479  for (; (s = mg_strcasestr(s, var_name)) != NULL; s += name_len) {
6480  if (s[name_len] == '=') {
6481  /* HCP24: now check is it a substring or a full cookie name */
6482  if ((s == cookie_header) || (s[-1] == ' ')) {
6483  s += name_len + 1;
6484  if ((p = strchr(s, ' ')) == NULL) {
6485  p = end;
6486  }
6487  if (p[-1] == ';') {
6488  p--;
6489  }
6490  if ((*s == '"') && (p[-1] == '"') && (p > s + 1)) {
6491  s++;
6492  p--;
6493  }
6494  if ((size_t)(p - s) < dst_size) {
6495  len = (int)(p - s);
6496  mg_strlcpy(dst, s, (size_t)len + 1);
6497  } else {
6498  len = -3;
6499  }
6500  break;
6501  }
6502  }
6503  }
6504  return len;
6505 }
6506 
6507 
6508 #if defined(USE_WEBSOCKET) || defined(USE_LUA)
6509 static void
6510 base64_encode(const unsigned char *src, int src_len, char *dst)
6511 {
6512  static const char *b64 =
6513  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
6514  int i, j, a, b, c;
6515 
6516  for (i = j = 0; i < src_len; i += 3) {
6517  a = src[i];
6518  b = ((i + 1) >= src_len) ? 0 : src[i + 1];
6519  c = ((i + 2) >= src_len) ? 0 : src[i + 2];
6520 
6521  dst[j++] = b64[a >> 2];
6522  dst[j++] = b64[((a & 3) << 4) | (b >> 4)];
6523  if (i + 1 < src_len) {
6524  dst[j++] = b64[(b & 15) << 2 | (c >> 6)];
6525  }
6526  if (i + 2 < src_len) {
6527  dst[j++] = b64[c & 63];
6528  }
6529  }
6530  while (j % 4 != 0) {
6531  dst[j++] = '=';
6532  }
6533  dst[j++] = '\0';
6534 }
6535 #endif
6536 
6537 
6538 #if defined(USE_LUA)
6539 static unsigned char
6540 b64reverse(char letter)
6541 {
6542  if ((letter >= 'A') && (letter <= 'Z')) {
6543  return letter - 'A';
6544  }
6545  if ((letter >= 'a') && (letter <= 'z')) {
6546  return letter - 'a' + 26;
6547  }
6548  if ((letter >= '0') && (letter <= '9')) {
6549  return letter - '0' + 52;
6550  }
6551  if (letter == '+') {
6552  return 62;
6553  }
6554  if (letter == '/') {
6555  return 63;
6556  }
6557  if (letter == '=') {
6558  return 255; /* normal end */
6559  }
6560  return 254; /* error */
6561 }
6562 
6563 
6564 static int
6565 base64_decode(const unsigned char *src, int src_len, char *dst, size_t *dst_len)
6566 {
6567  int i;
6568  unsigned char a, b, c, d;
6569 
6570  *dst_len = 0;
6571 
6572  for (i = 0; i < src_len; i += 4) {
6573  a = b64reverse(src[i]);
6574  if (a >= 254) {
6575  return i;
6576  }
6577 
6578  b = b64reverse(((i + 1) >= src_len) ? 0 : src[i + 1]);
6579  if (b >= 254) {
6580  return i + 1;
6581  }
6582 
6583  c = b64reverse(((i + 2) >= src_len) ? 0 : src[i + 2]);
6584  if (c == 254) {
6585  return i + 2;
6586  }
6587 
6588  d = b64reverse(((i + 3) >= src_len) ? 0 : src[i + 3]);
6589  if (d == 254) {
6590  return i + 3;
6591  }
6592 
6593  dst[(*dst_len)++] = (a << 2) + (b >> 4);
6594  if (c != 255) {
6595  dst[(*dst_len)++] = (b << 4) + (c >> 2);
6596  if (d != 255) {
6597  dst[(*dst_len)++] = (c << 6) + d;
6598  }
6599  }
6600  }
6601  return -1;
6602 }
6603 #endif
6604 
6605 
6606 static int
6607 is_put_or_delete_method(const struct mg_connection *conn)
6608 {
6609  if (conn) {
6610  const char *s = conn->request_info.request_method;
6611  return (s != NULL) && (!strcmp(s, "PUT") || !strcmp(s, "DELETE")
6612  || !strcmp(s, "MKCOL") || !strcmp(s, "PATCH"));
6613  }
6614  return 0;
6615 }
6616 
6617 
6618 #if !defined(NO_FILES)
6619 static int
6621  struct mg_connection *conn, /* in: request (must be valid) */
6622  const char *filename /* in: filename (must be valid) */
6623  )
6624 {
6625 #if !defined(NO_CGI)
6626  if (match_prefix(conn->ctx->config[CGI_EXTENSIONS],
6627  strlen(conn->ctx->config[CGI_EXTENSIONS]),
6628  filename) > 0) {
6629  return 1;
6630  }
6631 #endif
6632 #if defined(USE_LUA)
6633  if (match_prefix(conn->ctx->config[LUA_SCRIPT_EXTENSIONS],
6634  strlen(conn->ctx->config[LUA_SCRIPT_EXTENSIONS]),
6635  filename) > 0) {
6636  return 1;
6637  }
6638 #endif
6639 #if defined(USE_DUKTAPE)
6640  if (match_prefix(conn->ctx->config[DUKTAPE_SCRIPT_EXTENSIONS],
6641  strlen(conn->ctx->config[DUKTAPE_SCRIPT_EXTENSIONS]),
6642  filename) > 0) {
6643  return 1;
6644  }
6645 #endif
6646  /* filename and conn could be unused, if all preocessor conditions
6647  * are false (no script language supported). */
6648  (void)filename;
6649  (void)conn;
6650 
6651  return 0;
6652 }
6653 
6654 
6655 /* For given directory path, substitute it to valid index file.
6656  * Return 1 if index file has been found, 0 if not found.
6657  * If the file is found, it's stats is returned in stp. */
6658 static int
6659 substitute_index_file(struct mg_connection *conn,
6660  char *path,
6661  size_t path_len,
6662  struct mg_file_stat *filestat)
6663 {
6664  const char *list = conn->ctx->config[INDEX_FILES];
6665  struct vec filename_vec;
6666  size_t n = strlen(path);
6667  int found = 0;
6668 
6669  /* The 'path' given to us points to the directory. Remove all trailing
6670  * directory separator characters from the end of the path, and
6671  * then append single directory separator character. */
6672  while ((n > 0) && (path[n - 1] == '/')) {
6673  n--;
6674  }
6675  path[n] = '/';
6676 
6677  /* Traverse index files list. For each entry, append it to the given
6678  * path and see if the file exists. If it exists, break the loop */
6679  while ((list = next_option(list, &filename_vec, NULL)) != NULL) {
6680  /* Ignore too long entries that may overflow path buffer */
6681  if (filename_vec.len > (path_len - (n + 2))) {
6682  continue;
6683  }
6684 
6685  /* Prepare full path to the index file */
6686  mg_strlcpy(path + n + 1, filename_vec.ptr, filename_vec.len + 1);
6687 
6688  /* Does it exist? */
6689  if (mg_stat(conn, path, filestat)) {
6690  /* Yes it does, break the loop */
6691  found = 1;
6692  break;
6693  }
6694  }
6695 
6696  /* If no index file exists, restore directory path */
6697  if (!found) {
6698  path[n] = '\0';
6699  }
6700 
6701  return found;
6702 }
6703 #endif
6704 
6705 
6706 static void
6707 interpret_uri(struct mg_connection *conn, /* in/out: request (must be valid) */
6708  char *filename, /* out: filename */
6709  size_t filename_buf_len, /* in: size of filename buffer */
6710  struct mg_file_stat *filestat, /* out: file status structure */
6711  int *is_found, /* out: file found (directly) */
6712  int *is_script_resource, /* out: handled by a script? */
6713  int *is_websocket_request, /* out: websocket connetion? */
6714  int *is_put_or_delete_request /* out: put/delete a file? */
6715  )
6716 {
6717  char const *accept_encoding;
6718 
6719 #if !defined(NO_FILES)
6720  const char *uri = conn->request_info.local_uri;
6721  const char *root = conn->ctx->config[DOCUMENT_ROOT];
6722  const char *rewrite;
6723  struct vec a, b;
6724  int match_len;
6725  char gz_path[PATH_MAX];
6726  int truncated;
6727 #if !defined(NO_CGI) || defined(USE_LUA) || defined(USE_DUKTAPE)
6728  char *tmp_str;
6729  size_t tmp_str_len, sep_pos;
6730  int allow_substitute_script_subresources;
6731 #endif
6732 #else
6733  (void)filename_buf_len; /* unused if NO_FILES is defined */
6734 #endif
6735 
6736  /* Step 1: Set all initially unknown outputs to zero */
6737  memset(filestat, 0, sizeof(*filestat));
6738  *filename = 0;
6739  *is_found = 0;
6740  *is_script_resource = 0;
6741 
6742  /* Step 2: Check if the request attempts to modify the file system */
6743  *is_put_or_delete_request = is_put_or_delete_method(conn);
6744 
6745 /* Step 3: Check if it is a websocket request, and modify the document
6746  * root if required */
6747 #if defined(USE_WEBSOCKET)
6748  *is_websocket_request = is_websocket_protocol(conn);
6749 #if !defined(NO_FILES)
6750  if (*is_websocket_request && conn->ctx->config[WEBSOCKET_ROOT]) {
6751  root = conn->ctx->config[WEBSOCKET_ROOT];
6752  }
6753 #endif /* !NO_FILES */
6754 #else /* USE_WEBSOCKET */
6755  *is_websocket_request = 0;
6756 #endif /* USE_WEBSOCKET */
6757 
6758  /* Step 4: Check if gzip encoded response is allowed */
6759  conn->accept_gzip = 0;
6760  if ((accept_encoding = mg_get_header(conn, "Accept-Encoding")) != NULL) {
6761  if (strstr(accept_encoding, "gzip") != NULL) {
6762  conn->accept_gzip = 1;
6763  }
6764  }
6765 
6766 #if !defined(NO_FILES)
6767  /* Step 5: If there is no root directory, don't look for files. */
6768  /* Note that root == NULL is a regular use case here. This occurs,
6769  * if all requests are handled by callbacks, so the WEBSOCKET_ROOT
6770  * config is not required. */
6771  if (root == NULL) {
6772  /* all file related outputs have already been set to 0, just return
6773  */
6774  return;
6775  }
6776 
6777  /* Step 6: Determine the local file path from the root path and the
6778  * request uri. */
6779  /* Using filename_buf_len - 1 because memmove() for PATH_INFO may shift
6780  * part of the path one byte on the right. */
6781  mg_snprintf(
6782  conn, &truncated, filename, filename_buf_len - 1, "%s%s", root, uri);
6783 
6784  if (truncated) {
6785  goto interpret_cleanup;
6786  }
6787 
6788  /* Step 7: URI rewriting */
6789  rewrite = conn->ctx->config[URL_REWRITE_PATTERN];
6790  while ((rewrite = next_option(rewrite, &a, &b)) != NULL) {
6791  if ((match_len = match_prefix(a.ptr, a.len, uri)) > 0) {
6792  mg_snprintf(conn,
6793  &truncated,
6794  filename,
6795  filename_buf_len - 1,
6796  "%.*s%s",
6797  (int)b.len,
6798  b.ptr,
6799  uri + match_len);
6800  break;
6801  }
6802  }
6803 
6804  if (truncated) {
6805  goto interpret_cleanup;
6806  }
6807 
6808  /* Step 8: Check if the file exists at the server */
6809  /* Local file path and name, corresponding to requested URI
6810  * is now stored in "filename" variable. */
6811  if (mg_stat(conn, filename, filestat)) {
6812  /* 8.1: File exists. */
6813  *is_found = 1;
6814 
6815  /* 8.2: Check if it is a script type. */
6816  if (extention_matches_script(conn, filename)) {
6817  /* The request addresses a CGI resource, Lua script or
6818  * server-side javascript.
6819  * The URI corresponds to the script itself (like
6820  * /path/script.cgi), and there is no additional resource
6821  * path (like /path/script.cgi/something).
6822  * Requests that modify (replace or delete) a resource, like
6823  * PUT and DELETE requests, should replace/delete the script
6824  * file.
6825  * Requests that read or write from/to a resource, like GET and
6826  * POST requests, should call the script and return the
6827  * generated response. */
6828  *is_script_resource = (!*is_put_or_delete_request);
6829  }
6830 
6831  /* 8.3: If the request target is a directory, there could be
6832  * a substitute file (index.html, index.cgi, ...). */
6833  if (filestat->is_directory) {
6834  /* Use a local copy here, since substitute_index_file will
6835  * change the content of the file status */
6836  struct mg_file_stat tmp_filestat;
6837  memset(&tmp_filestat, 0, sizeof(tmp_filestat));
6838 
6840  conn, filename, filename_buf_len, &tmp_filestat)) {
6841 
6842  /* Substitute file found. Copy stat to the output, then
6843  * check if the file is a script file */
6844  *filestat = tmp_filestat;
6845 
6846  if (extention_matches_script(conn, filename)) {
6847  /* Substitute file is a script file */
6848  *is_script_resource = 1;
6849  } else {
6850  /* Substitute file is a regular file */
6851  *is_script_resource = 0;
6852  *is_found = (mg_stat(conn, filename, filestat) ? 1 : 0);
6853  }
6854  }
6855  /* If there is no substitute file, the server could return
6856  * a directory listing in a later step */
6857  }
6858  return;
6859  }
6860 
6861  /* Step 9: Check for zipped files: */
6862  /* If we can't find the actual file, look for the file
6863  * with the same name but a .gz extension. If we find it,
6864  * use that and set the gzipped flag in the file struct
6865  * to indicate that the response need to have the content-
6866  * encoding: gzip header.
6867  * We can only do this if the browser declares support. */
6868  if (conn->accept_gzip) {
6869  mg_snprintf(
6870  conn, &truncated, gz_path, sizeof(gz_path), "%s.gz", filename);
6871 
6872  if (truncated) {
6873  goto interpret_cleanup;
6874  }
6875 
6876  if (mg_stat(conn, gz_path, filestat)) {
6877  if (filestat) {
6878  filestat->is_gzipped = 1;
6879  *is_found = 1;
6880  }
6881  /* Currently gz files can not be scripts. */
6882  return;
6883  }
6884  }
6885 
6886 #if !defined(NO_CGI) || defined(USE_LUA) || defined(USE_DUKTAPE)
6887  /* Step 10: Script resources may handle sub-resources */
6888  /* Support PATH_INFO for CGI scripts. */
6889  tmp_str_len = strlen(filename);
6890  tmp_str = (char *)mg_malloc_ctx(tmp_str_len + PATH_MAX + 1, conn->ctx);
6891  if (!tmp_str) {
6892  /* Out of memory */
6893  goto interpret_cleanup;
6894  }
6895  memcpy(tmp_str, filename, tmp_str_len + 1);
6896 
6897  /* Check config, if index scripts may have sub-resources */
6898  allow_substitute_script_subresources =
6899  !mg_strcasecmp(conn->ctx->config[ALLOW_INDEX_SCRIPT_SUB_RES], "yes");
6900 
6901  sep_pos = tmp_str_len;
6902  while (sep_pos > 0) {
6903  sep_pos--;
6904  if (tmp_str[sep_pos] == '/') {
6905  int is_script = 0, does_exist = 0;
6906 
6907  tmp_str[sep_pos] = 0;
6908  if (tmp_str[0]) {
6909  is_script = extention_matches_script(conn, tmp_str);
6910  does_exist = mg_stat(conn, tmp_str, filestat);
6911  }
6912 
6913  if (does_exist && is_script) {
6914  filename[sep_pos] = 0;
6915  memmove(filename + sep_pos + 2,
6916  filename + sep_pos + 1,
6917  strlen(filename + sep_pos + 1) + 1);
6918  conn->path_info = filename + sep_pos + 1;
6919  filename[sep_pos + 1] = '/';
6920  *is_script_resource = 1;
6921  *is_found = 1;
6922  break;
6923  }
6924 
6925  if (allow_substitute_script_subresources) {
6927  conn, tmp_str, tmp_str_len + PATH_MAX, filestat)) {
6928 
6929  /* some intermediate directory has an index file */
6930  if (extention_matches_script(conn, tmp_str)) {
6931 
6932  char *tmp_str2;
6933 
6934  DEBUG_TRACE("Substitute script %s serving path %s",
6935  tmp_str,
6936  filename);
6937 
6938  /* this index file is a script */
6939  tmp_str2 = mg_strdup(filename + sep_pos + 1);
6940  mg_snprintf(conn,
6941  &truncated,
6942  filename,
6943  filename_buf_len,
6944  "%s//%s",
6945  tmp_str,
6946  tmp_str2);
6947  mg_free(tmp_str2);
6948 
6949  if (truncated) {
6950  mg_free(tmp_str);
6951  goto interpret_cleanup;
6952  }
6953  sep_pos = strlen(tmp_str);
6954  filename[sep_pos] = 0;
6955  conn->path_info = filename + sep_pos + 1;
6956  *is_script_resource = 1;
6957  *is_found = 1;
6958  break;
6959 
6960  } else {
6961 
6962  DEBUG_TRACE("Substitute file %s serving path %s",
6963  tmp_str,
6964  filename);
6965 
6966  /* non-script files will not have sub-resources */
6967  filename[sep_pos] = 0;
6968  conn->path_info = 0;
6969  *is_script_resource = 0;
6970  *is_found = 0;
6971  break;
6972  }
6973  }
6974  }
6975 
6976  tmp_str[sep_pos] = '/';
6977  }
6978  }
6979 
6980  mg_free(tmp_str);
6981 
6982 #endif /* !defined(NO_CGI) || defined(USE_LUA) || defined(USE_DUKTAPE) */
6983 #endif /* !defined(NO_FILES) */
6984  return;
6985 
6986 #if !defined(NO_FILES)
6987 /* Reset all outputs */
6988 interpret_cleanup:
6989  memset(filestat, 0, sizeof(*filestat));
6990  *filename = 0;
6991  *is_found = 0;
6992  *is_script_resource = 0;
6993  *is_websocket_request = 0;
6994  *is_put_or_delete_request = 0;
6995 #endif /* !defined(NO_FILES) */
6996 }
6997 
6998 
6999 /* Check whether full request is buffered. Return:
7000  * -1 if request or response is malformed
7001  * 0 if request or response is not yet fully buffered
7002  * >0 actual request length, including last \r\n\r\n */
7003 static int
7004 get_http_header_len(const char *buf, int buflen)
7005 {
7006  int i;
7007  for (i = 0; i < buflen; i++) {
7008  /* Do an unsigned comparison in some conditions below */
7009  const unsigned char c = ((const unsigned char *)buf)[i];
7010 
7011  if ((c < 128) && ((char)c != '\r') && ((char)c != '\n')
7012  && !isprint(c)) {
7013  /* abort scan as soon as one malformed character is found */
7014  return -1;
7015  }
7016 
7017  if (i < buflen - 1) {
7018  if ((buf[i] == '\n') && (buf[i + 1] == '\n')) {
7019  /* Two newline, no carriage return - not standard compliant,
7020  * but
7021  * it
7022  * should be accepted */
7023  return i + 2;
7024  }
7025  }
7026 
7027  if (i < buflen - 3) {
7028  if ((buf[i] == '\r') && (buf[i + 1] == '\n') && (buf[i + 2] == '\r')
7029  && (buf[i + 3] == '\n')) {
7030  /* Two \r\n - standard compliant */
7031  return i + 4;
7032  }
7033  }
7034  }
7035 
7036  return 0;
7037 }
7038 
7039 
7040 #if !defined(NO_CACHING)
7041 /* Convert month to the month number. Return -1 on error, or month number */
7042 static int
7043 get_month_index(const char *s)
7044 {
7045  size_t i;
7046 
7047  for (i = 0; i < ARRAY_SIZE(month_names); i++) {
7048  if (!strcmp(s, month_names[i])) {
7049  return (int)i;
7050  }
7051  }
7052 
7053  return -1;
7054 }
7055 
7056 
7057 /* Parse UTC date-time string, and return the corresponding time_t value. */
7058 static time_t
7059 parse_date_string(const char *datetime)
7060 {
7061  char month_str[32] = {0};
7062  int second, minute, hour, day, month, year;
7063  time_t result = (time_t)0;
7064  struct tm tm;
7065 
7066  if ((sscanf(datetime,
7067  "%d/%3s/%d %d:%d:%d",
7068  &day,
7069  month_str,
7070  &year,
7071  &hour,
7072  &minute,
7073  &second) == 6) || (sscanf(datetime,
7074  "%d %3s %d %d:%d:%d",
7075  &day,
7076  month_str,
7077  &year,
7078  &hour,
7079  &minute,
7080  &second) == 6)
7081  || (sscanf(datetime,
7082  "%*3s, %d %3s %d %d:%d:%d",
7083  &day,
7084  month_str,
7085  &year,
7086  &hour,
7087  &minute,
7088  &second) == 6) || (sscanf(datetime,
7089  "%d-%3s-%d %d:%d:%d",
7090  &day,
7091  month_str,
7092  &year,
7093  &hour,
7094  &minute,
7095  &second) == 6)) {
7096  month = get_month_index(month_str);
7097  if ((month >= 0) && (year >= 1970)) {
7098  memset(&tm, 0, sizeof(tm));
7099  tm.tm_year = year - 1900;
7100  tm.tm_mon = month;
7101  tm.tm_mday = day;
7102  tm.tm_hour = hour;
7103  tm.tm_min = minute;
7104  tm.tm_sec = second;
7105  result = timegm(&tm);
7106  }
7107  }
7108 
7109  return result;
7110 }
7111 #endif /* !NO_CACHING */
7112 
7113 
7114 /* Protect against directory disclosure attack by removing '..',
7115  * excessive '/' and '\' characters */
7116 static void
7118 {
7119  char *p = s;
7120 
7121  while ((s[0] == '.') && (s[1] == '.')) {
7122  s++;
7123  }
7124 
7125  while (*s != '\0') {
7126  *p++ = *s++;
7127  if ((s[-1] == '/') || (s[-1] == '\\')) {
7128  /* Skip all following slashes, backslashes and double-dots */
7129  while (s[0] != '\0') {
7130  if ((s[0] == '/') || (s[0] == '\\')) {
7131  s++;
7132  } else if ((s[0] == '.') && (s[1] == '.')) {
7133  s += 2;
7134  } else {
7135  break;
7136  }
7137  }
7138  }
7139  }
7140  *p = '\0';
7141 }
7142 
7143 
7144 static const struct {
7145  const char *extension;
7146  size_t ext_len;
7147  const char *mime_type;
7148 } builtin_mime_types[] = {
7149  /* IANA registered MIME types
7150  * (http://www.iana.org/assignments/media-types)
7151  * application types */
7152  {".doc", 4, "application/msword"},
7153  {".eps", 4, "application/postscript"},
7154  {".exe", 4, "application/octet-stream"},
7155  {".js", 3, "application/javascript"},
7156  {".json", 5, "application/json"},
7157  {".pdf", 4, "application/pdf"},
7158  {".ps", 3, "application/postscript"},
7159  {".rtf", 4, "application/rtf"},
7160  {".xhtml", 6, "application/xhtml+xml"},
7161  {".xsl", 4, "application/xml"},
7162  {".xslt", 5, "application/xml"},
7163 
7164  /* fonts */
7165  {".ttf", 4, "application/font-sfnt"},
7166  {".cff", 4, "application/font-sfnt"},
7167  {".otf", 4, "application/font-sfnt"},
7168  {".aat", 4, "application/font-sfnt"},
7169  {".sil", 4, "application/font-sfnt"},
7170  {".pfr", 4, "application/font-tdpfr"},
7171  {".woff", 5, "application/font-woff"},
7172 
7173  /* audio */
7174  {".mp3", 4, "audio/mpeg"},
7175  {".oga", 4, "audio/ogg"},
7176  {".ogg", 4, "audio/ogg"},
7177 
7178  /* image */
7179  {".gif", 4, "image/gif"},
7180  {".ief", 4, "image/ief"},
7181  {".jpeg", 5, "image/jpeg"},
7182  {".jpg", 4, "image/jpeg"},
7183  {".jpm", 4, "image/jpm"},
7184  {".jpx", 4, "image/jpx"},
7185  {".png", 4, "image/png"},
7186  {".svg", 4, "image/svg+xml"},
7187  {".tif", 4, "image/tiff"},
7188  {".tiff", 5, "image/tiff"},
7189 
7190  /* model */
7191  {".wrl", 4, "model/vrml"},
7192 
7193  /* text */
7194  {".css", 4, "text/css"},
7195  {".csv", 4, "text/csv"},
7196  {".htm", 4, "text/html"},
7197  {".html", 5, "text/html"},
7198  {".sgm", 4, "text/sgml"},
7199  {".shtm", 5, "text/html"},
7200  {".shtml", 6, "text/html"},
7201  {".txt", 4, "text/plain"},
7202  {".xml", 4, "text/xml"},
7203 
7204  /* video */
7205  {".mov", 4, "video/quicktime"},
7206  {".mp4", 4, "video/mp4"},
7207  {".mpeg", 5, "video/mpeg"},
7208  {".mpg", 4, "video/mpeg"},
7209  {".ogv", 4, "video/ogg"},
7210  {".qt", 3, "video/quicktime"},
7211 
7212  /* not registered types
7213  * (http://reference.sitepoint.com/html/mime-types-full,
7214  * http://www.hansenb.pdx.edu/DMKB/dict/tutorials/mime_typ.php, ..) */
7215  {".arj", 4, "application/x-arj-compressed"},
7216  {".gz", 3, "application/x-gunzip"},
7217  {".rar", 4, "application/x-arj-compressed"},
7218  {".swf", 4, "application/x-shockwave-flash"},
7219  {".tar", 4, "application/x-tar"},
7220  {".tgz", 4, "application/x-tar-gz"},
7221  {".torrent", 8, "application/x-bittorrent"},
7222  {".ppt", 4, "application/x-mspowerpoint"},
7223  {".xls", 4, "application/x-msexcel"},
7224  {".zip", 4, "application/x-zip-compressed"},
7225  {".aac",
7226  4,
7227  "audio/aac"}, /* http://en.wikipedia.org/wiki/Advanced_Audio_Coding */
7228  {".aif", 4, "audio/x-aif"},
7229  {".m3u", 4, "audio/x-mpegurl"},
7230  {".mid", 4, "audio/x-midi"},
7231  {".ra", 3, "audio/x-pn-realaudio"},
7232  {".ram", 4, "audio/x-pn-realaudio"},
7233  {".wav", 4, "audio/x-wav"},
7234  {".bmp", 4, "image/bmp"},
7235  {".ico", 4, "image/x-icon"},
7236  {".pct", 4, "image/x-pct"},
7237  {".pict", 5, "image/pict"},
7238  {".rgb", 4, "image/x-rgb"},
7239  {".webm", 5, "video/webm"}, /* http://en.wikipedia.org/wiki/WebM */
7240  {".asf", 4, "video/x-ms-asf"},
7241  {".avi", 4, "video/x-msvideo"},
7242  {".m4v", 4, "video/x-m4v"},
7243  {NULL, 0, NULL}};
7244 
7245 
7246 const char *
7247 mg_get_builtin_mime_type(const char *path)
7248 {
7249  const char *ext;
7250  size_t i, path_len;
7251 
7252  path_len = strlen(path);
7253 
7254  for (i = 0; builtin_mime_types[i].extension != NULL; i++) {
7255  ext = path + (path_len - builtin_mime_types[i].ext_len);
7256  if ((path_len > builtin_mime_types[i].ext_len)
7257  && (mg_strcasecmp(ext, builtin_mime_types[i].extension) == 0)) {
7258  return builtin_mime_types[i].mime_type;
7259  }
7260  }
7261 
7262  return "text/plain";
7263 }
7264 
7265 
7266 /* Look at the "path" extension and figure what mime type it has.
7267  * Store mime type in the vector. */
7268 static void
7269 get_mime_type(struct mg_context *ctx, const char *path, struct vec *vec)
7270 {
7271  struct vec ext_vec, mime_vec;
7272  const char *list, *ext;
7273  size_t path_len;
7274 
7275  path_len = strlen(path);
7276 
7277  if ((ctx == NULL) || (vec == NULL)) {
7278  if (vec != NULL) {
7279  memset(vec, '\0', sizeof(struct vec));
7280  }
7281  return;
7282  }
7283 
7284  /* Scan user-defined mime types first, in case user wants to
7285  * override default mime types. */
7286  list = ctx->config[EXTRA_MIME_TYPES];
7287  while ((list = next_option(list, &ext_vec, &mime_vec)) != NULL) {
7288  /* ext now points to the path suffix */
7289  ext = path + path_len - ext_vec.len;
7290  if (mg_strncasecmp(ext, ext_vec.ptr, ext_vec.len) == 0) {
7291  *vec = mime_vec;
7292  return;
7293  }
7294  }
7295 
7296  vec->ptr = mg_get_builtin_mime_type(path);
7297  vec->len = strlen(vec->ptr);
7298 }
7299 
7300 
7301 /* Stringify binary data. Output buffer must be twice as big as input,
7302  * because each byte takes 2 bytes in string representation */
7303 static void
7304 bin2str(char *to, const unsigned char *p, size_t len)
7305 {
7306  static const char *hex = "0123456789abcdef";
7307 
7308  for (; len--; p++) {
7309  *to++ = hex[p[0] >> 4];
7310  *to++ = hex[p[0] & 0x0f];
7311  }
7312  *to = '\0';
7313 }
7314 
7315 
7316 /* Return stringified MD5 hash for list of strings. Buffer must be 33 bytes.
7317  */
7318 char *
7319 mg_md5(char buf[33], ...)
7320 {
7321  md5_byte_t hash[16];
7322  const char *p;
7323  va_list ap;
7324  md5_state_t ctx;
7325 
7326  md5_init(&ctx);
7327 
7328  va_start(ap, buf);
7329  while ((p = va_arg(ap, const char *)) != NULL) {
7330  md5_append(&ctx, (const md5_byte_t *)p, strlen(p));
7331  }
7332  va_end(ap);
7333 
7334  md5_finish(&ctx, hash);
7335  bin2str(buf, hash, sizeof(hash));
7336  return buf;
7337 }
7338 
7339 
7340 /* Check the user's password, return 1 if OK */
7341 static int
7342 check_password(const char *method,
7343  const char *ha1,
7344  const char *uri,
7345  const char *nonce,
7346  const char *nc,
7347  const char *cnonce,
7348  const char *qop,
7349  const char *response)
7350 {
7351  char ha2[32 + 1], expected_response[32 + 1];
7352 
7353  /* Some of the parameters may be NULL */
7354  if ((method == NULL) || (nonce == NULL) || (nc == NULL) || (cnonce == NULL)
7355  || (qop == NULL) || (response == NULL)) {
7356  return 0;
7357  }
7358 
7359  /* NOTE(lsm): due to a bug in MSIE, we do not compare the URI */
7360  if (strlen(response) != 32) {
7361  return 0;
7362  }
7363 
7364  mg_md5(ha2, method, ":", uri, NULL);
7365  mg_md5(expected_response,
7366  ha1,
7367  ":",
7368  nonce,
7369  ":",
7370  nc,
7371  ":",
7372  cnonce,
7373  ":",
7374  qop,
7375  ":",
7376  ha2,
7377  NULL);
7378 
7379  return mg_strcasecmp(response, expected_response) == 0;
7380 }
7381 
7382 
7383 /* Use the global passwords file, if specified by auth_gpass option,
7384  * or search for .htpasswd in the requested directory. */
7385 static void
7386 open_auth_file(struct mg_connection *conn,
7387  const char *path,
7388  struct mg_file *filep)
7389 {
7390  if ((conn != NULL) && (conn->ctx != NULL)) {
7391  char name[PATH_MAX];
7392  const char *p, *e, *gpass = conn->ctx->config[GLOBAL_PASSWORDS_FILE];
7393  int truncated;
7394 
7395  if (gpass != NULL) {
7396  /* Use global passwords file */
7397  if (!mg_fopen(conn, gpass, MG_FOPEN_MODE_READ, filep)) {
7398 #ifdef DEBUG
7399  /* Use mg_cry here, since gpass has been configured. */
7400  mg_cry(conn, "fopen(%s): %s", gpass, strerror(ERRNO));
7401 #endif
7402  }
7403  /* Important: using local struct mg_file to test path for
7404  * is_directory flag. If filep is used, mg_stat() makes it
7405  * appear as if auth file was opened.
7406  * TODO(mid): Check if this is still required after rewriting
7407  * mg_stat */
7408  } else if (mg_stat(conn, path, &filep->stat)
7409  && filep->stat.is_directory) {
7410  mg_snprintf(conn,
7411  &truncated,
7412  name,
7413  sizeof(name),
7414  "%s/%s",
7415  path,
7417 
7418  if (truncated || !mg_fopen(conn, name, MG_FOPEN_MODE_READ, filep)) {
7419 #ifdef DEBUG
7420  /* Don't use mg_cry here, but only a trace, since this is
7421  * a typical case. It will occur for every directory
7422  * without a password file. */
7423  DEBUG_TRACE("fopen(%s): %s", name, strerror(ERRNO));
7424 #endif
7425  }
7426  } else {
7427  /* Try to find .htpasswd in requested directory. */
7428  for (p = path, e = p + strlen(p) - 1; e > p; e--) {
7429  if (e[0] == '/') {
7430  break;
7431  }
7432  }
7433  mg_snprintf(conn,
7434  &truncated,
7435  name,
7436  sizeof(name),
7437  "%.*s/%s",
7438  (int)(e - p),
7439  p,
7441 
7442  if (truncated || !mg_fopen(conn, name, MG_FOPEN_MODE_READ, filep)) {
7443 #ifdef DEBUG
7444  /* Don't use mg_cry here, but only a trace, since this is
7445  * a typical case. It will occur for every directory
7446  * without a password file. */
7447  DEBUG_TRACE("fopen(%s): %s", name, strerror(ERRNO));
7448 #endif
7449  }
7450  }
7451  }
7452 }
7453 
7454 
7455 /* Parsed Authorization header */
7456 struct ah {
7457  char *user, *uri, *cnonce, *response, *qop, *nc, *nonce;
7458 };
7459 
7460 
7461 /* Return 1 on success. Always initializes the ah structure. */
7462 static int
7463 parse_auth_header(struct mg_connection *conn,
7464  char *buf,
7465  size_t buf_size,
7466  struct ah *ah)
7467 {
7468  char *name, *value, *s;
7469  const char *auth_header;
7470  uint64_t nonce;
7471 
7472  if (!ah || !conn) {
7473  return 0;
7474  }
7475 
7476  (void)memset(ah, 0, sizeof(*ah));
7477  if (((auth_header = mg_get_header(conn, "Authorization")) == NULL)
7478  || mg_strncasecmp(auth_header, "Digest ", 7) != 0) {
7479  return 0;
7480  }
7481 
7482  /* Make modifiable copy of the auth header */
7483  (void)mg_strlcpy(buf, auth_header + 7, buf_size);
7484  s = buf;
7485 
7486  /* Parse authorization header */
7487  for (;;) {
7488  /* Gobble initial spaces */
7489  while (isspace(*(unsigned char *)s)) {
7490  s++;
7491  }
7492  name = skip_quoted(&s, "=", " ", 0);
7493  /* Value is either quote-delimited, or ends at first comma or space.
7494  */
7495  if (s[0] == '\"') {
7496  s++;
7497  value = skip_quoted(&s, "\"", " ", '\\');
7498  if (s[0] == ',') {
7499  s++;
7500  }
7501  } else {
7502  value = skip_quoted(&s, ", ", " ", 0); /* IE uses commas, FF uses
7503  * spaces */
7504  }
7505  if (*name == '\0') {
7506  break;
7507  }
7508 
7509  if (!strcmp(name, "username")) {
7510  ah->user = value;
7511  } else if (!strcmp(name, "cnonce")) {
7512  ah->cnonce = value;
7513  } else if (!strcmp(name, "response")) {
7514  ah->response = value;
7515  } else if (!strcmp(name, "uri")) {
7516  ah->uri = value;
7517  } else if (!strcmp(name, "qop")) {
7518  ah->qop = value;
7519  } else if (!strcmp(name, "nc")) {
7520  ah->nc = value;
7521  } else if (!strcmp(name, "nonce")) {
7522  ah->nonce = value;
7523  }
7524  }
7525 
7526 #ifndef NO_NONCE_CHECK
7527  /* Read the nonce from the response. */
7528  if (ah->nonce == NULL) {
7529  return 0;
7530  }
7531  s = NULL;
7532  nonce = strtoull(ah->nonce, &s, 10);
7533  if ((s == NULL) || (*s != 0)) {
7534  return 0;
7535  }
7536 
7537  /* Convert the nonce from the client to a number. */
7538  nonce ^= conn->ctx->auth_nonce_mask;
7539 
7540  /* The converted number corresponds to the time the nounce has been
7541  * created. This should not be earlier than the server start. */
7542  /* Server side nonce check is valuable in all situations but one:
7543  * if the server restarts frequently, but the client should not see
7544  * that, so the server should accept nonces from previous starts. */
7545  /* However, the reasonable default is to not accept a nonce from a
7546  * previous start, so if anyone changed the access rights between
7547  * two restarts, a new login is required. */
7548  if (nonce < (uint64_t)conn->ctx->start_time) {
7549  /* nonce is from a previous start of the server and no longer valid
7550  * (replay attack?) */
7551  return 0;
7552  }
7553  /* Check if the nonce is too high, so it has not (yet) been used by the
7554  * server. */
7555  if (nonce >= ((uint64_t)conn->ctx->start_time + conn->ctx->nonce_count)) {
7556  return 0;
7557  }
7558 #else
7559  (void)nonce;
7560 #endif
7561 
7562  /* CGI needs it as REMOTE_USER */
7563  if (ah->user != NULL) {
7564  conn->request_info.remote_user = mg_strdup(ah->user);
7565  } else {
7566  return 0;
7567  }
7568 
7569  return 1;
7570 }
7571 
7572 
7573 static const char *
7574 mg_fgets(char *buf, size_t size, struct mg_file *filep, char **p)
7575 {
7576  const char *eof;
7577  size_t len;
7578  const char *memend;
7579 
7580  if (!filep) {
7581  return NULL;
7582  }
7583 
7584  if ((filep->access.membuf != NULL) && (*p != NULL)) {
7585  memend = (const char *)&filep->access.membuf[filep->stat.size];
7586  /* Search for \n from p till the end of stream */
7587  eof = (char *)memchr(*p, '\n', (size_t)(memend - *p));
7588  if (eof != NULL) {
7589  eof += 1; /* Include \n */
7590  } else {
7591  eof = memend; /* Copy remaining data */
7592  }
7593  len =
7594  ((size_t)(eof - *p) > (size - 1)) ? (size - 1) : (size_t)(eof - *p);
7595  memcpy(buf, *p, len);
7596  buf[len] = '\0';
7597  *p += len;
7598  return len ? eof : NULL;
7599  } else if (filep->access.fp != NULL) {
7600  return fgets(buf, (int)size, filep->access.fp);
7601  } else {
7602  return NULL;
7603  }
7604 }
7605 
7606 /* Define the initial recursion depth for procesesing htpasswd files that
7607  * include other htpasswd
7608  * (or even the same) files. It is not difficult to provide a file or files
7609  * s.t. they force civetweb
7610  * to infinitely recurse and then crash.
7611  */
7612 #define INITIAL_DEPTH 9
7613 #if INITIAL_DEPTH <= 0
7614 #error Bad INITIAL_DEPTH for recursion, set to at least 1
7615 #endif
7616 
7617 struct read_auth_file_struct {
7618  struct mg_connection *conn;
7619  struct ah ah;
7620  const char *domain;
7621  char buf[256 + 256 + 40];
7622  const char *f_user;
7623  const char *f_domain;
7624  const char *f_ha1;
7625 };
7626 
7627 
7628 static int
7629 read_auth_file(struct mg_file *filep,
7630  struct read_auth_file_struct *workdata,
7631  int depth)
7632 {
7633  char *p;
7634  int is_authorized = 0;
7635  struct mg_file fp;
7636  size_t l;
7637 
7638  if (!filep || !workdata || (0 == depth)) {
7639  return 0;
7640  }
7641 
7642  /* Loop over passwords file */
7643  p = (char *)filep->access.membuf;
7644  while (mg_fgets(workdata->buf, sizeof(workdata->buf), filep, &p) != NULL) {
7645  l = strlen(workdata->buf);
7646  while (l > 0) {
7647  if (isspace(workdata->buf[l - 1])
7648  || iscntrl(workdata->buf[l - 1])) {
7649  l--;
7650  workdata->buf[l] = 0;
7651  } else
7652  break;
7653  }
7654  if (l < 1) {
7655  continue;
7656  }
7657 
7658  workdata->f_user = workdata->buf;
7659 
7660  if (workdata->f_user[0] == ':') {
7661  /* user names may not contain a ':' and may not be empty,
7662  * so lines starting with ':' may be used for a special purpose
7663  */
7664  if (workdata->f_user[1] == '#') {
7665  /* :# is a comment */
7666  continue;
7667  } else if (!strncmp(workdata->f_user + 1, "include=", 8)) {
7668  if (mg_fopen(workdata->conn,
7669  workdata->f_user + 9,
7671  &fp)) {
7672  is_authorized = read_auth_file(&fp, workdata, depth - 1);
7673  (void)mg_fclose(
7674  &fp.access); /* ignore error on read only file */
7675 
7676  /* No need to continue processing files once we have a
7677  * match, since nothing will reset it back
7678  * to 0.
7679  */
7680  if (is_authorized) {
7681  return is_authorized;
7682  }
7683  } else {
7684  mg_cry(workdata->conn,
7685  "%s: cannot open authorization file: %s",
7686  __func__,
7687  workdata->buf);
7688  }
7689  continue;
7690  }
7691  /* everything is invalid for the moment (might change in the
7692  * future) */
7693  mg_cry(workdata->conn,
7694  "%s: syntax error in authorization file: %s",
7695  __func__,
7696  workdata->buf);
7697  continue;
7698  }
7699 
7700  workdata->f_domain = strchr(workdata->f_user, ':');
7701  if (workdata->f_domain == NULL) {
7702  mg_cry(workdata->conn,
7703  "%s: syntax error in authorization file: %s",
7704  __func__,
7705  workdata->buf);
7706  continue;
7707  }
7708  *(char *)(workdata->f_domain) = 0;
7709  (workdata->f_domain)++;
7710 
7711  workdata->f_ha1 = strchr(workdata->f_domain, ':');
7712  if (workdata->f_ha1 == NULL) {
7713  mg_cry(workdata->conn,
7714  "%s: syntax error in authorization file: %s",
7715  __func__,
7716  workdata->buf);
7717  continue;
7718  }
7719  *(char *)(workdata->f_ha1) = 0;
7720  (workdata->f_ha1)++;
7721 
7722  if (!strcmp(workdata->ah.user, workdata->f_user)
7723  && !strcmp(workdata->domain, workdata->f_domain)) {
7724  return check_password(workdata->conn->request_info.request_method,
7725  workdata->f_ha1,
7726  workdata->ah.uri,
7727  workdata->ah.nonce,
7728  workdata->ah.nc,
7729  workdata->ah.cnonce,
7730  workdata->ah.qop,
7731  workdata->ah.response);
7732  }
7733  }
7734 
7735  return is_authorized;
7736 }
7737 
7738 
7739 /* Authorize against the opened passwords file. Return 1 if authorized. */
7740 static int
7741 authorize(struct mg_connection *conn, struct mg_file *filep, const char *realm)
7742 {
7743  struct read_auth_file_struct workdata;
7744  char buf[MG_BUF_LEN];
7745 
7746  if (!conn || !conn->ctx) {
7747  return 0;
7748  }
7749 
7750  memset(&workdata, 0, sizeof(workdata));
7751  workdata.conn = conn;
7752 
7753  if (!parse_auth_header(conn, buf, sizeof(buf), &workdata.ah)) {
7754  return 0;
7755  }
7756 
7757  if (realm) {
7758  workdata.domain = realm;
7759  } else {
7760  workdata.domain = conn->ctx->config[AUTHENTICATION_DOMAIN];
7761  }
7762 
7763  return read_auth_file(filep, &workdata, INITIAL_DEPTH);
7764 }
7765 
7766 
7767 /* Public function to check http digest authentication header */
7768 int
7769 mg_check_digest_access_authentication(struct mg_connection *conn,
7770  const char *realm,
7771  const char *filename)
7772 {
7773  struct mg_file file = STRUCT_FILE_INITIALIZER;
7774  int auth;
7775 
7776  if (!conn || !filename) {
7777  return -1;
7778  }
7779  if (!mg_fopen(conn, filename, MG_FOPEN_MODE_READ, &file)) {
7780  return -2;
7781  }
7782 
7783  auth = authorize(conn, &file, realm);
7784 
7785  mg_fclose(&file.access);
7786 
7787  return auth;
7788 }
7789 
7790 
7791 /* Return 1 if request is authorised, 0 otherwise. */
7792 static int
7793 check_authorization(struct mg_connection *conn, const char *path)
7794 {
7795  char fname[PATH_MAX];
7796  struct vec uri_vec, filename_vec;
7797  const char *list;
7798  struct mg_file file = STRUCT_FILE_INITIALIZER;
7799  int authorized = 1, truncated;
7800 
7801  if (!conn || !conn->ctx) {
7802  return 0;
7803  }
7804 
7805  list = conn->ctx->config[PROTECT_URI];
7806  while ((list = next_option(list, &uri_vec, &filename_vec)) != NULL) {
7807  if (!memcmp(conn->request_info.local_uri, uri_vec.ptr, uri_vec.len)) {
7808  mg_snprintf(conn,
7809  &truncated,
7810  fname,
7811  sizeof(fname),
7812  "%.*s",
7813  (int)filename_vec.len,
7814  filename_vec.ptr);
7815 
7816  if (truncated
7817  || !mg_fopen(conn, fname, MG_FOPEN_MODE_READ, &file)) {
7818  mg_cry(conn,
7819  "%s: cannot open %s: %s",
7820  __func__,
7821  fname,
7822  strerror(errno));
7823  }
7824  break;
7825  }
7826  }
7827 
7828  if (!is_file_opened(&file.access)) {
7829  open_auth_file(conn, path, &file);
7830  }
7831 
7832  if (is_file_opened(&file.access)) {
7833  authorized = authorize(conn, &file, NULL);
7834  (void)mg_fclose(&file.access); /* ignore error on read only file */
7835  }
7836 
7837  return authorized;
7838 }
7839 
7840 
7841 /* Internal function. Assumes conn is valid */
7842 static void
7843 send_authorization_request(struct mg_connection *conn, const char *realm)
7844 {
7845  char date[64];
7846  time_t curtime = time(NULL);
7847  uint64_t nonce = (uint64_t)(conn->ctx->start_time);
7848 
7849  if (!realm) {
7850  realm = conn->ctx->config[AUTHENTICATION_DOMAIN];
7851  }
7852 
7853  (void)pthread_mutex_lock(&conn->ctx->nonce_mutex);
7854  nonce += conn->ctx->nonce_count;
7855  ++conn->ctx->nonce_count;
7856  (void)pthread_mutex_unlock(&conn->ctx->nonce_mutex);
7857 
7858  nonce ^= conn->ctx->auth_nonce_mask;
7859  conn->status_code = 401;
7860  conn->must_close = 1;
7861 
7862  gmt_time_string(date, sizeof(date), &curtime);
7863 
7864  mg_printf(conn, "HTTP/1.1 401 Unauthorized\r\n");
7865  send_no_cache_header(conn);
7866  send_additional_header(conn);
7867  mg_printf(conn,
7868  "Date: %s\r\n"
7869  "Connection: %s\r\n"
7870  "Content-Length: 0\r\n"
7871  "WWW-Authenticate: Digest qop=\"auth\", realm=\"%s\", "
7872  "nonce=\"%" UINT64_FMT "\"\r\n\r\n",
7873  date,
7875  realm,
7876  nonce);
7877 }
7878 
7879 
7880 /* Interface function. Parameters are provided by the user, so do
7881  * at least some basic checks.
7882  */
7883 int
7885  const char *realm)
7886 {
7887  if (conn && conn->ctx) {
7888  send_authorization_request(conn, realm);
7889  return 0;
7890  }
7891  return -1;
7892 }
7893 
7894 
7895 #if !defined(NO_FILES)
7896 static int
7897 is_authorized_for_put(struct mg_connection *conn)
7898 {
7899  if (conn) {
7900  struct mg_file file = STRUCT_FILE_INITIALIZER;
7901  const char *passfile = conn->ctx->config[PUT_DELETE_PASSWORDS_FILE];
7902  int ret = 0;
7903 
7904  if (passfile != NULL
7905  && mg_fopen(conn, passfile, MG_FOPEN_MODE_READ, &file)) {
7906  ret = authorize(conn, &file, NULL);
7907  (void)mg_fclose(&file.access); /* ignore error on read only file */
7908  }
7909 
7910  return ret;
7911  }
7912  return 0;
7913 }
7914 #endif
7915 
7916 
7917 int
7918 mg_modify_passwords_file(const char *fname,
7919  const char *domain,
7920  const char *user,
7921  const char *pass)
7922 {
7923  int found, i;
7924  char line[512], u[512] = "", d[512] = "", ha1[33], tmp[PATH_MAX + 8];
7925  FILE *fp, *fp2;
7926 
7927  found = 0;
7928  fp = fp2 = NULL;
7929 
7930  /* Regard empty password as no password - remove user record. */
7931  if ((pass != NULL) && (pass[0] == '\0')) {
7932  pass = NULL;
7933  }
7934 
7935  /* Other arguments must not be empty */
7936  if ((fname == NULL) || (domain == NULL) || (user == NULL)) {
7937  return 0;
7938  }
7939 
7940  /* Using the given file format, user name and domain must not contain
7941  * ':'
7942  */
7943  if (strchr(user, ':') != NULL) {
7944  return 0;
7945  }
7946  if (strchr(domain, ':') != NULL) {
7947  return 0;
7948  }
7949 
7950  /* Do not allow control characters like newline in user name and domain.
7951  * Do not allow excessively long names either. */
7952  for (i = 0; ((i < 255) && (user[i] != 0)); i++) {
7953  if (iscntrl(user[i])) {
7954  return 0;
7955  }
7956  }
7957  if (user[i]) {
7958  return 0;
7959  }
7960  for (i = 0; ((i < 255) && (domain[i] != 0)); i++) {
7961  if (iscntrl(domain[i])) {
7962  return 0;
7963  }
7964  }
7965  if (domain[i]) {
7966  return 0;
7967  }
7968 
7969  /* The maximum length of the path to the password file is limited */
7970  if ((strlen(fname) + 4) >= PATH_MAX) {
7971  return 0;
7972  }
7973 
7974  /* Create a temporary file name. Length has been checked before. */
7975  strcpy(tmp, fname);
7976  strcat(tmp, ".tmp");
7977 
7978  /* Create the file if does not exist */
7979  /* Use of fopen here is OK, since fname is only ASCII */
7980  if ((fp = fopen(fname, "a+")) != NULL) {
7981  (void)fclose(fp);
7982  }
7983 
7984  /* Open the given file and temporary file */
7985  if ((fp = fopen(fname, "r")) == NULL) {
7986  return 0;
7987  } else if ((fp2 = fopen(tmp, "w+")) == NULL) {
7988  fclose(fp);
7989  return 0;
7990  }
7991 
7992  /* Copy the stuff to temporary file */
7993  while (fgets(line, sizeof(line), fp) != NULL) {
7994  if (sscanf(line, "%255[^:]:%255[^:]:%*s", u, d) != 2) {
7995  continue;
7996  }
7997  u[255] = 0;
7998  d[255] = 0;
7999 
8000  if (!strcmp(u, user) && !strcmp(d, domain)) {
8001  found++;
8002  if (pass != NULL) {
8003  mg_md5(ha1, user, ":", domain, ":", pass, NULL);
8004  fprintf(fp2, "%s:%s:%s\n", user, domain, ha1);
8005  }
8006  } else {
8007  fprintf(fp2, "%s", line);
8008  }
8009  }
8010 
8011  /* If new user, just add it */
8012  if (!found && (pass != NULL)) {
8013  mg_md5(ha1, user, ":", domain, ":", pass, NULL);
8014  fprintf(fp2, "%s:%s:%s\n", user, domain, ha1);
8015  }
8016 
8017  /* Close files */
8018  fclose(fp);
8019  fclose(fp2);
8020 
8021  /* Put the temp file in place of real file */
8022  IGNORE_UNUSED_RESULT(remove(fname));
8023  IGNORE_UNUSED_RESULT(rename(tmp, fname));
8024 
8025  return 1;
8026 }
8027 
8028 
8029 static int
8030 is_valid_port(unsigned long port)
8031 {
8032  return (port <= 0xffff);
8033 }
8034 
8035 
8036 static int
8037 mg_inet_pton(int af, const char *src, void *dst, size_t dstlen)
8038 {
8039  struct addrinfo hints, *res, *ressave;
8040  int func_ret = 0;
8041  int gai_ret;
8042 
8043  memset(&hints, 0, sizeof(struct addrinfo));
8044  hints.ai_family = af;
8045 
8046  gai_ret = getaddrinfo(src, NULL, &hints, &res);
8047  if (gai_ret != 0) {
8048  /* gai_strerror could be used to convert gai_ret to a string */
8049  /* POSIX return values: see
8050  * http://pubs.opengroup.org/onlinepubs/9699919799/functions/freeaddrinfo.html
8051  */
8052  /* Windows return values: see
8053  * https://msdn.microsoft.com/en-us/library/windows/desktop/ms738520%28v=vs.85%29.aspx
8054  */
8055  return 0;
8056  }
8057 
8058  ressave = res;
8059 
8060  while (res) {
8061  if (dstlen >= (size_t)res->ai_addrlen) {
8062  memcpy(dst, res->ai_addr, res->ai_addrlen);
8063  func_ret = 1;
8064  }
8065  res = res->ai_next;
8066  }
8067 
8068  freeaddrinfo(ressave);
8069  return func_ret;
8070 }
8071 
8072 
8073 static int
8074 connect_socket(struct mg_context *ctx /* may be NULL */,
8075  const char *host,
8076  int port,
8077  int use_ssl,
8078  char *ebuf,
8079  size_t ebuf_len,
8080  SOCKET *sock /* output: socket, must not be NULL */,
8081  union usa *sa /* output: socket address, must not be NULL */
8082  )
8083 {
8084  int ip_ver = 0;
8085  *sock = INVALID_SOCKET;
8086  memset(sa, 0, sizeof(*sa));
8087 
8088  if (ebuf_len > 0) {
8089  *ebuf = 0;
8090  }
8091 
8092  if (host == NULL) {
8093  mg_snprintf(NULL,
8094  NULL, /* No truncation check for ebuf */
8095  ebuf,
8096  ebuf_len,
8097  "%s",
8098  "NULL host");
8099  return 0;
8100  }
8101 
8102  if ((port <= 0) || !is_valid_port((unsigned)port)) {
8103  mg_snprintf(NULL,
8104  NULL, /* No truncation check for ebuf */
8105  ebuf,
8106  ebuf_len,
8107  "%s",
8108  "invalid port");
8109  return 0;
8110  }
8111 
8112 #if !defined(NO_SSL)
8113 #if !defined(NO_SSL_DL)
8114 #ifdef OPENSSL_API_1_1
8115  if (use_ssl && (TLS_client_method == NULL)) {
8116  mg_snprintf(NULL,
8117  NULL, /* No truncation check for ebuf */
8118  ebuf,
8119  ebuf_len,
8120  "%s",
8121  "SSL is not initialized");
8122  return 0;
8123  }
8124 #else
8125  if (use_ssl && (SSLv23_client_method == NULL)) {
8126  mg_snprintf(NULL,
8127  NULL, /* No truncation check for ebuf */
8128  ebuf,
8129  ebuf_len,
8130  "%s",
8131  "SSL is not initialized");
8132  return 0;
8133  }
8134 
8135 #endif /* OPENSSL_API_1_1 */
8136 #else
8137  (void)use_ssl;
8138 #endif /* NO_SSL_DL */
8139 #else
8140  (void)use_ssl;
8141 #endif /* !defined(NO_SSL) */
8142 
8143  if (mg_inet_pton(AF_INET, host, &sa->sin, sizeof(sa->sin))) {
8144  sa->sin.sin_family = AF_INET;
8145  sa->sin.sin_port = htons((uint16_t)port);
8146  ip_ver = 4;
8147 #ifdef USE_IPV6
8148  } else if (mg_inet_pton(AF_INET6, host, &sa->sin6, sizeof(sa->sin6))) {
8149  sa->sin6.sin6_family = AF_INET6;
8150  sa->sin6.sin6_port = htons((uint16_t)port);
8151  ip_ver = 6;
8152  } else if (host[0] == '[') {
8153  /* While getaddrinfo on Windows will work with [::1],
8154  * getaddrinfo on Linux only works with ::1 (without []). */
8155  size_t l = strlen(host + 1);
8156  char *h = (l > 1) ? mg_strdup(host + 1) : NULL;
8157  if (h) {
8158  h[l - 1] = 0;
8159  if (mg_inet_pton(AF_INET6, h, &sa->sin6, sizeof(sa->sin6))) {
8160  sa->sin6.sin6_family = AF_INET6;
8161  sa->sin6.sin6_port = htons((uint16_t)port);
8162  ip_ver = 6;
8163  }
8164  mg_free(h);
8165  }
8166 #endif
8167  }
8168 
8169  if (ip_ver == 0) {
8170  mg_snprintf(NULL,
8171  NULL, /* No truncation check for ebuf */
8172  ebuf,
8173  ebuf_len,
8174  "%s",
8175  "host not found");
8176  return 0;
8177  }
8178 
8179  if (ip_ver == 4) {
8180  *sock = socket(PF_INET, SOCK_STREAM, 0);
8181  }
8182 #ifdef USE_IPV6
8183  else if (ip_ver == 6) {
8184  *sock = socket(PF_INET6, SOCK_STREAM, 0);
8185  }
8186 #endif
8187 
8188  if (*sock == INVALID_SOCKET) {
8189  mg_snprintf(NULL,
8190  NULL, /* No truncation check for ebuf */
8191  ebuf,
8192  ebuf_len,
8193  "socket(): %s",
8194  strerror(ERRNO));
8195  return 0;
8196  }
8197 
8198  set_close_on_exec(*sock, fc(ctx));
8199 
8200  if ((ip_ver == 4)
8201  && (connect(*sock, (struct sockaddr *)&sa->sin, sizeof(sa->sin))
8202  == 0)) {
8203  /* connected with IPv4 */
8204  if (0 == set_non_blocking_mode(*sock)) {
8205  /* Ok */
8206  return 1;
8207  }
8208  /* failed */
8209  /* TODO: specific error message */
8210  }
8211 
8212 #ifdef USE_IPV6
8213  if ((ip_ver == 6)
8214  && (connect(*sock, (struct sockaddr *)&sa->sin6, sizeof(sa->sin6))
8215  == 0)) {
8216  /* connected with IPv6 */
8217  if (0 == set_non_blocking_mode(*sock)) {
8218  /* Ok */
8219  return 1;
8220  }
8221  /* failed */
8222  /* TODO: specific error message */
8223  }
8224 #endif
8225 
8226  /* Not connected */
8227  mg_snprintf(NULL,
8228  NULL, /* No truncation check for ebuf */
8229  ebuf,
8230  ebuf_len,
8231  "connect(%s:%d): %s",
8232  host,
8233  port,
8234  strerror(ERRNO));
8235  closesocket(*sock);
8236  *sock = INVALID_SOCKET;
8237 
8238  return 0;
8239 }
8240 
8241 
8242 int
8243 mg_url_encode(const char *src, char *dst, size_t dst_len)
8244 {
8245  static const char *dont_escape = "._-$,;~()";
8246  static const char *hex = "0123456789abcdef";
8247  char *pos = dst;
8248  const char *end = dst + dst_len - 1;
8249 
8250  for (; ((*src != '\0') && (pos < end)); src++, pos++) {
8251  if (isalnum(*(const unsigned char *)src)
8252  || (strchr(dont_escape, *(const unsigned char *)src) != NULL)) {
8253  *pos = *src;
8254  } else if (pos + 2 < end) {
8255  pos[0] = '%';
8256  pos[1] = hex[(*(const unsigned char *)src) >> 4];
8257  pos[2] = hex[(*(const unsigned char *)src) & 0xf];
8258  pos += 2;
8259  } else {
8260  break;
8261  }
8262  }
8263 
8264  *pos = '\0';
8265  return (*src == '\0') ? (int)(pos - dst) : -1;
8266 }
8267 
8268 /* Return 0 on success, non-zero if an error occurs. */
8269 
8270 static int
8271 print_dir_entry(struct de *de)
8272 {
8273  size_t hrefsize;
8274  char *href;
8275  char size[64], mod[64];
8276  struct tm *tm;
8277 
8278  hrefsize = PATH_MAX * 3; /* worst case */
8279  href = (char *)mg_malloc(hrefsize);
8280  if (href == NULL) {
8281  return -1;
8282  }
8283  if (de->file.is_directory) {
8284  mg_snprintf(de->conn,
8285  NULL, /* Buffer is big enough */
8286  size,
8287  sizeof(size),
8288  "%s",
8289  "[DIRECTORY]");
8290  } else {
8291  /* We use (signed) cast below because MSVC 6 compiler cannot
8292  * convert unsigned __int64 to double. Sigh. */
8293  if (de->file.size < 1024) {
8294  mg_snprintf(de->conn,
8295  NULL, /* Buffer is big enough */
8296  size,
8297  sizeof(size),
8298  "%d",
8299  (int)de->file.size);
8300  } else if (de->file.size < 0x100000) {
8301  mg_snprintf(de->conn,
8302  NULL, /* Buffer is big enough */
8303  size,
8304  sizeof(size),
8305  "%.1fk",
8306  (double)de->file.size / 1024.0);
8307  } else if (de->file.size < 0x40000000) {
8308  mg_snprintf(de->conn,
8309  NULL, /* Buffer is big enough */
8310  size,
8311  sizeof(size),
8312  "%.1fM",
8313  (double)de->file.size / 1048576);
8314  } else {
8315  mg_snprintf(de->conn,
8316  NULL, /* Buffer is big enough */
8317  size,
8318  sizeof(size),
8319  "%.1fG",
8320  (double)de->file.size / 1073741824);
8321  }
8322  }
8323 
8324  /* Note: mg_snprintf will not cause a buffer overflow above.
8325  * So, string truncation checks are not required here. */
8326 
8327  tm = localtime(&de->file.last_modified);
8328  if (tm != NULL) {
8329  strftime(mod, sizeof(mod), "%d-%b-%Y %H:%M", tm);
8330  } else {
8331  mg_strlcpy(mod, "01-Jan-1970 00:00", sizeof(mod));
8332  mod[sizeof(mod) - 1] = '\0';
8333  }
8334  mg_url_encode(de->file_name, href, hrefsize);
8335  mg_printf(de->conn,
8336  "<tr><td><a href=\"%s%s%s\">%s%s</a></td>"
8337  "<td>&nbsp;%s</td><td>&nbsp;&nbsp;%s</td></tr>\n",
8338  de->conn->request_info.local_uri,
8339  href,
8340  de->file.is_directory ? "/" : "",
8341  de->file_name,
8342  de->file.is_directory ? "/" : "",
8343  mod,
8344  size);
8345  mg_free(href);
8346  return 0;
8347 }
8348 
8349 
8350 /* This function is called from send_directory() and used for
8351  * sorting directory entries by size, or name, or modification time.
8352  * On windows, __cdecl specification is needed in case if project is built
8353  * with __stdcall convention. qsort always requires __cdels callback. */
8354 static int WINCDECL
8355 compare_dir_entries(const void *p1, const void *p2)
8356 {
8357  if (p1 && p2) {
8358  const struct de *a = (const struct de *)p1, *b = (const struct de *)p2;
8359  const char *query_string = a->conn->request_info.query_string;
8360  int cmp_result = 0;
8361 
8362  if (query_string == NULL) {
8363  query_string = "na";
8364  }
8365 
8366  if (a->file.is_directory && !b->file.is_directory) {
8367  return -1; /* Always put directories on top */
8368  } else if (!a->file.is_directory && b->file.is_directory) {
8369  return 1; /* Always put directories on top */
8370  } else if (*query_string == 'n') {
8371  cmp_result = strcmp(a->file_name, b->file_name);
8372  } else if (*query_string == 's') {
8373  cmp_result = (a->file.size == b->file.size)
8374  ? 0
8375  : ((a->file.size > b->file.size) ? 1 : -1);
8376  } else if (*query_string == 'd') {
8377  cmp_result =
8378  (a->file.last_modified == b->file.last_modified)
8379  ? 0
8380  : ((a->file.last_modified > b->file.last_modified) ? 1
8381  : -1);
8382  }
8383 
8384  return (query_string[1] == 'd') ? -cmp_result : cmp_result;
8385  }
8386  return 0;
8387 }
8388 
8389 
8390 static int
8391 must_hide_file(struct mg_connection *conn, const char *path)
8392 {
8393  if (conn && conn->ctx) {
8394  const char *pw_pattern = "**" PASSWORDS_FILE_NAME "$";
8395  const char *pattern = conn->ctx->config[HIDE_FILES];
8396  return (match_prefix(pw_pattern, strlen(pw_pattern), path) > 0)
8397  || ((pattern != NULL)
8398  && (match_prefix(pattern, strlen(pattern), path) > 0));
8399  }
8400  return 0;
8401 }
8402 
8403 
8404 static int
8405 scan_directory(struct mg_connection *conn,
8406  const char *dir,
8407  void *data,
8408  int (*cb)(struct de *, void *))
8409 {
8410  char path[PATH_MAX];
8411  struct dirent *dp;
8412  DIR *dirp;
8413  struct de de;
8414  int truncated;
8415 
8416  if ((dirp = mg_opendir(conn, dir)) == NULL) {
8417  return 0;
8418  } else {
8419  de.conn = conn;
8420 
8421  while ((dp = mg_readdir(dirp)) != NULL) {
8422  /* Do not show current dir and hidden files */
8423  if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..")
8424  || must_hide_file(conn, dp->d_name)) {
8425  continue;
8426  }
8427 
8428  mg_snprintf(
8429  conn, &truncated, path, sizeof(path), "%s/%s", dir, dp->d_name);
8430 
8431  /* If we don't memset stat structure to zero, mtime will have
8432  * garbage and strftime() will segfault later on in
8433  * print_dir_entry(). memset is required only if mg_stat()
8434  * fails. For more details, see
8435  * http://code.google.com/p/mongoose/issues/detail?id=79 */
8436  memset(&de.file, 0, sizeof(de.file));
8437 
8438  if (truncated) {
8439  /* If the path is not complete, skip processing. */
8440  continue;
8441  }
8442 
8443  if (!mg_stat(conn, path, &de.file)) {
8444  mg_cry(conn,
8445  "%s: mg_stat(%s) failed: %s",
8446  __func__,
8447  path,
8448  strerror(ERRNO));
8449  }
8450  de.file_name = dp->d_name;
8451  cb(&de, data);
8452  }
8453  (void)mg_closedir(dirp);
8454  }
8455  return 1;
8456 }
8457 
8458 
8459 #if !defined(NO_FILES)
8460 static int
8461 remove_directory(struct mg_connection *conn, const char *dir)
8462 {
8463  char path[PATH_MAX];
8464  struct dirent *dp;
8465  DIR *dirp;
8466  struct de de;
8467  int truncated;
8468  int ok = 1;
8469 
8470  if ((dirp = mg_opendir(conn, dir)) == NULL) {
8471  return 0;
8472  } else {
8473  de.conn = conn;
8474 
8475  while ((dp = mg_readdir(dirp)) != NULL) {
8476  /* Do not show current dir (but show hidden files as they will
8477  * also be removed) */
8478  if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..")) {
8479  continue;
8480  }
8481 
8482  mg_snprintf(
8483  conn, &truncated, path, sizeof(path), "%s/%s", dir, dp->d_name);
8484 
8485  /* If we don't memset stat structure to zero, mtime will have
8486  * garbage and strftime() will segfault later on in
8487  * print_dir_entry(). memset is required only if mg_stat()
8488  * fails. For more details, see
8489  * http://code.google.com/p/mongoose/issues/detail?id=79 */
8490  memset(&de.file, 0, sizeof(de.file));
8491 
8492  if (truncated) {
8493  /* Do not delete anything shorter */
8494  ok = 0;
8495  continue;
8496  }
8497 
8498  if (!mg_stat(conn, path, &de.file)) {
8499  mg_cry(conn,
8500  "%s: mg_stat(%s) failed: %s",
8501  __func__,
8502  path,
8503  strerror(ERRNO));
8504  ok = 0;
8505  }
8506 
8507  if (de.file.is_directory) {
8508  if (remove_directory(conn, path) == 0) {
8509  ok = 0;
8510  }
8511  } else {
8512  /* This will fail file is the file is in memory */
8513  if (mg_remove(conn, path) == 0) {
8514  ok = 0;
8515  }
8516  }
8517  }
8518  (void)mg_closedir(dirp);
8519 
8520  IGNORE_UNUSED_RESULT(rmdir(dir));
8521  }
8522 
8523  return ok;
8524 }
8525 #endif
8526 
8527 
8528 struct dir_scan_data {
8529  struct de *entries;
8530  unsigned int num_entries;
8531  unsigned int arr_size;
8532 };
8533 
8534 
8535 /* Behaves like realloc(), but frees original pointer on failure */
8536 static void *
8537 realloc2(void *ptr, size_t size)
8538 {
8539  void *new_ptr = mg_realloc(ptr, size);
8540  if (new_ptr == NULL) {
8541  mg_free(ptr);
8542  }
8543  return new_ptr;
8544 }
8545 
8546 
8547 static int
8548 dir_scan_callback(struct de *de, void *data)
8549 {
8550  struct dir_scan_data *dsd = (struct dir_scan_data *)data;
8551 
8552  if ((dsd->entries == NULL) || (dsd->num_entries >= dsd->arr_size)) {
8553  dsd->arr_size *= 2;
8554  dsd->entries =
8555  (struct de *)realloc2(dsd->entries,
8556  dsd->arr_size * sizeof(dsd->entries[0]));
8557  }
8558  if (dsd->entries == NULL) {
8559  /* TODO(lsm, low): propagate an error to the caller */
8560  dsd->num_entries = 0;
8561  } else {
8562  dsd->entries[dsd->num_entries].file_name = mg_strdup(de->file_name);
8563  dsd->entries[dsd->num_entries].file = de->file;
8564  dsd->entries[dsd->num_entries].conn = de->conn;
8565  dsd->num_entries++;
8566  }
8567 
8568  return 0;
8569 }
8570 
8571 
8572 static void
8573 handle_directory_request(struct mg_connection *conn, const char *dir)
8574 {
8575  unsigned int i;
8576  int sort_direction;
8577  struct dir_scan_data data = {NULL, 0, 128};
8578  char date[64];
8579  time_t curtime = time(NULL);
8580 
8581  if (!scan_directory(conn, dir, &data, dir_scan_callback)) {
8582  mg_send_http_error(conn,
8583  500,
8584  "Error: Cannot open directory\nopendir(%s): %s",
8585  dir,
8586  strerror(ERRNO));
8587  return;
8588  }
8589 
8590  gmt_time_string(date, sizeof(date), &curtime);
8591 
8592  if (!conn) {
8593  return;
8594  }
8595 
8596  sort_direction = ((conn->request_info.query_string != NULL)
8597  && (conn->request_info.query_string[1] == 'd'))
8598  ? 'a'
8599  : 'd';
8600 
8601  conn->must_close = 1;
8602  mg_printf(conn, "HTTP/1.1 200 OK\r\n");
8604  send_additional_header(conn);
8605  mg_printf(conn,
8606  "Date: %s\r\n"
8607  "Connection: close\r\n"
8608  "Content-Type: text/html; charset=utf-8\r\n\r\n",
8609  date);
8610  mg_printf(conn,
8611  "<html><head><title>Index of %s</title>"
8612  "<style>th {text-align: left;}</style></head>"
8613  "<body><h1>Index of %s</h1><pre><table cellpadding=\"0\">"
8614  "<tr><th><a href=\"?n%c\">Name</a></th>"
8615  "<th><a href=\"?d%c\">Modified</a></th>"
8616  "<th><a href=\"?s%c\">Size</a></th></tr>"
8617  "<tr><td colspan=\"3\"><hr></td></tr>",
8618  conn->request_info.local_uri,
8619  conn->request_info.local_uri,
8620  sort_direction,
8621  sort_direction,
8622  sort_direction);
8623 
8624  /* Print first entry - link to a parent directory */
8625  mg_printf(conn,
8626  "<tr><td><a href=\"%s%s\">%s</a></td>"
8627  "<td>&nbsp;%s</td><td>&nbsp;&nbsp;%s</td></tr>\n",
8628  conn->request_info.local_uri,
8629  "..",
8630  "Parent directory",
8631  "-",
8632  "-");
8633 
8634  /* Sort and print directory entries */
8635  if (data.entries != NULL) {
8636  qsort(data.entries,
8637  (size_t)data.num_entries,
8638  sizeof(data.entries[0]),
8640  for (i = 0; i < data.num_entries; i++) {
8641  print_dir_entry(&data.entries[i]);
8642  mg_free(data.entries[i].file_name);
8643  }
8644  mg_free(data.entries);
8645  }
8646 
8647  mg_printf(conn, "%s", "</table></body></html>");
8648  conn->status_code = 200;
8649 }
8650 
8651 
8652 /* Send len bytes from the opened file to the client. */
8653 static void
8654 send_file_data(struct mg_connection *conn,
8655  struct mg_file *filep,
8656  int64_t offset,
8657  int64_t len)
8658 {
8659  char buf[MG_BUF_LEN];
8660  int to_read, num_read, num_written;
8661  int64_t size;
8662 
8663  if (!filep || !conn) {
8664  return;
8665  }
8666 
8667  /* Sanity check the offset */
8668  size = (filep->stat.size > INT64_MAX) ? INT64_MAX
8669  : (int64_t)(filep->stat.size);
8670  offset = (offset < 0) ? 0 : ((offset > size) ? size : offset);
8671 
8672  if ((len > 0) && (filep->access.membuf != NULL) && (size > 0)) {
8673  /* file stored in memory */
8674  if (len > size - offset) {
8675  len = size - offset;
8676  }
8677  mg_write(conn, filep->access.membuf + offset, (size_t)len);
8678  } else if (len > 0 && filep->access.fp != NULL) {
8679 /* file stored on disk */
8680 #if defined(__linux__)
8681  /* sendfile is only available for Linux */
8682  if ((conn->ssl == 0) && (conn->throttle == 0)
8683  && (!mg_strcasecmp(conn->ctx->config[ALLOW_SENDFILE_CALL],
8684  "yes"))) {
8685  off_t sf_offs = (off_t)offset;
8686  ssize_t sf_sent;
8687  int sf_file = fileno(filep->access.fp);
8688  int loop_cnt = 0;
8689 
8690  do {
8691  /* 2147479552 (0x7FFFF000) is a limit found by experiment on
8692  * 64 bit Linux (2^31 minus one memory page of 4k?). */
8693  size_t sf_tosend =
8694  (size_t)((len < 0x7FFFF000) ? len : 0x7FFFF000);
8695  sf_sent =
8696  sendfile(conn->client.sock, sf_file, &sf_offs, sf_tosend);
8697  if (sf_sent > 0) {
8698  len -= sf_sent;
8699  offset += sf_sent;
8700  } else if (loop_cnt == 0) {
8701  /* This file can not be sent using sendfile.
8702  * This might be the case for pseudo-files in the
8703  * /sys/ and /proc/ file system.
8704  * Use the regular user mode copy code instead. */
8705  break;
8706  } else if (sf_sent == 0) {
8707  /* No error, but 0 bytes sent. May be EOF? */
8708  return;
8709  }
8710  loop_cnt++;
8711 
8712  } while ((len > 0) && (sf_sent >= 0));
8713 
8714  if (sf_sent > 0) {
8715  return; /* OK */
8716  }
8717 
8718  /* sf_sent<0 means error, thus fall back to the classic way */
8719  /* This is always the case, if sf_file is not a "normal" file,
8720  * e.g., for sending data from the output of a CGI process. */
8721  offset = (int64_t)sf_offs;
8722  }
8723 #endif
8724  if ((offset > 0) && (fseeko(filep->access.fp, offset, SEEK_SET) != 0)) {
8725  mg_cry(conn, "%s: fseeko() failed: %s", __func__, strerror(ERRNO));
8727  conn,
8728  500,
8729  "%s",
8730  "Error: Unable to access file at requested position.");
8731  } else {
8732  while (len > 0) {
8733  /* Calculate how much to read from the file in the buffer */
8734  to_read = sizeof(buf);
8735  if ((int64_t)to_read > len) {
8736  to_read = (int)len;
8737  }
8738 
8739  /* Read from file, exit the loop on error */
8740  if ((num_read =
8741  (int)fread(buf, 1, (size_t)to_read, filep->access.fp))
8742  <= 0) {
8743  break;
8744  }
8745 
8746  /* Send read bytes to the client, exit the loop on error */
8747  if ((num_written = mg_write(conn, buf, (size_t)num_read))
8748  != num_read) {
8749  break;
8750  }
8751 
8752  /* Both read and were successful, adjust counters */
8753  len -= num_written;
8754  }
8755  }
8756  }
8757 }
8758 
8759 
8760 static int
8761 parse_range_header(const char *header, int64_t *a, int64_t *b)
8762 {
8763  return sscanf(header, "bytes=%" INT64_FMT "-%" INT64_FMT, a, b);
8764 }
8765 
8766 
8767 static void
8768 construct_etag(char *buf, size_t buf_len, const struct mg_file_stat *filestat)
8769 {
8770  if ((filestat != NULL) && (buf != NULL)) {
8771  mg_snprintf(NULL,
8772  NULL, /* All calls to construct_etag use 64 byte buffer */
8773  buf,
8774  buf_len,
8775  "\"%lx.%" INT64_FMT "\"",
8776  (unsigned long)filestat->last_modified,
8777  filestat->size);
8778  }
8779 }
8780 
8781 
8782 static void
8783 fclose_on_exec(struct mg_file_access *filep, struct mg_connection *conn)
8784 {
8785  if (filep != NULL && filep->fp != NULL) {
8786 #ifdef _WIN32
8787  (void)conn; /* Unused. */
8788 #else
8789  if (fcntl(fileno(filep->fp), F_SETFD, FD_CLOEXEC) != 0) {
8790  mg_cry(conn,
8791  "%s: fcntl(F_SETFD FD_CLOEXEC) failed: %s",
8792  __func__,
8793  strerror(ERRNO));
8794  }
8795 #endif
8796  }
8797 }
8798 
8799 
8800 static void
8801 handle_static_file_request(struct mg_connection *conn,
8802  const char *path,
8803  struct mg_file *filep,
8804  const char *mime_type,
8805  const char *additional_headers)
8806 {
8807  char date[64], lm[64], etag[64];
8808  char range[128]; /* large enough, so there will be no overflow */
8809  const char *msg = "OK", *hdr;
8810  time_t curtime = time(NULL);
8811  int64_t cl, r1, r2;
8812  struct vec mime_vec;
8813  int n, truncated;
8814  char gz_path[PATH_MAX];
8815  const char *encoding = "";
8816  const char *cors1, *cors2, *cors3;
8817  int allow_on_the_fly_compression;
8818 
8819  if ((conn == NULL) || (conn->ctx == NULL) || (filep == NULL)) {
8820  return;
8821  }
8822 
8823  if (mime_type == NULL) {
8824  get_mime_type(conn->ctx, path, &mime_vec);
8825  } else {
8826  mime_vec.ptr = mime_type;
8827  mime_vec.len = strlen(mime_type);
8828  }
8829  if (filep->stat.size > INT64_MAX) {
8830  mg_send_http_error(conn,
8831  500,
8832  "Error: File size is too large to send\n%" INT64_FMT,
8833  filep->stat.size);
8834  return;
8835  }
8836  cl = (int64_t)filep->stat.size;
8837  conn->status_code = 200;
8838  range[0] = '\0';
8839 
8840  /* if this file is in fact a pre-gzipped file, rewrite its filename
8841  * it's important to rewrite the filename after resolving
8842  * the mime type from it, to preserve the actual file's type */
8843  allow_on_the_fly_compression = conn->accept_gzip;
8844 
8845  if (filep->stat.is_gzipped) {
8846  mg_snprintf(conn, &truncated, gz_path, sizeof(gz_path), "%s.gz", path);
8847 
8848  if (truncated) {
8849  mg_send_http_error(conn,
8850  500,
8851  "Error: Path of zipped file too long (%s)",
8852  path);
8853  return;
8854  }
8855 
8856  path = gz_path;
8857  encoding = "Content-Encoding: gzip\r\n";
8858 
8859  /* File is already compressed. No "on the fly" compression. */
8860  allow_on_the_fly_compression = 0;
8861  }
8862 
8863  if (!mg_fopen(conn, path, MG_FOPEN_MODE_READ, filep)) {
8864  mg_send_http_error(conn,
8865  500,
8866  "Error: Cannot open file\nfopen(%s): %s",
8867  path,
8868  strerror(ERRNO));
8869  return;
8870  }
8871 
8872  fclose_on_exec(&filep->access, conn);
8873 
8874  /* If Range: header specified, act accordingly */
8875  r1 = r2 = 0;
8876  hdr = mg_get_header(conn, "Range");
8877  if ((hdr != NULL) && ((n = parse_range_header(hdr, &r1, &r2)) > 0)
8878  && (r1 >= 0) && (r2 >= 0)) {
8879  /* actually, range requests don't play well with a pre-gzipped
8880  * file (since the range is specified in the uncompressed space) */
8881  if (filep->stat.is_gzipped) {
8883  conn,
8884  416, /* 416 = Range Not Satisfiable */
8885  "%s",
8886  "Error: Range requests in gzipped files are not supported");
8887  (void)mg_fclose(
8888  &filep->access); /* ignore error on read only file */
8889  return;
8890  }
8891  conn->status_code = 206;
8892  cl = (n == 2) ? (((r2 > cl) ? cl : r2) - r1 + 1) : (cl - r1);
8893  mg_snprintf(conn,
8894  NULL, /* range buffer is big enough */
8895  range,
8896  sizeof(range),
8897  "Content-Range: bytes "
8898  "%" INT64_FMT "-%" INT64_FMT "/%" INT64_FMT "\r\n",
8899  r1,
8900  r1 + cl - 1,
8901  filep->stat.size);
8902  msg = "Partial Content";
8903 
8904  /* Do not compress ranges. */
8905  allow_on_the_fly_compression = 0;
8906  }
8907 
8908  hdr = mg_get_header(conn, "Origin");
8909  if (hdr) {
8910  /* Cross-origin resource sharing (CORS), see
8911  * http://www.html5rocks.com/en/tutorials/cors/,
8912  * http://www.html5rocks.com/static/images/cors_server_flowchart.png
8913  * -
8914  * preflight is not supported for files. */
8915  cors1 = "Access-Control-Allow-Origin: ";
8916  cors2 = conn->ctx->config[ACCESS_CONTROL_ALLOW_ORIGIN];
8917  cors3 = "\r\n";
8918  } else {
8919  cors1 = cors2 = cors3 = "";
8920  }
8921 
8922  /* Prepare Etag, Date, Last-Modified headers. Must be in UTC,
8923  * according to
8924  * http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3 */
8925  gmt_time_string(date, sizeof(date), &curtime);
8926  gmt_time_string(lm, sizeof(lm), &filep->stat.last_modified);
8927  construct_etag(etag, sizeof(etag), &filep->stat);
8928 
8929  /* On the fly compression allowed */
8930  if (allow_on_the_fly_compression) {
8931  ;
8932  /* TODO: add interface to compression module */
8933  /* e.g., def from https://zlib.net/zlib_how.html */
8934  /* Check license (zlib has a permissive license, but */
8935  /* is still not MIT) and use dynamic binding like */
8936  /* done with OpenSSL */
8937  /* See #199 (https://github.com/civetweb/civetweb/issues/199) */
8938  }
8939 
8940  /* Send header */
8941  (void)mg_printf(conn,
8942  "HTTP/1.1 %d %s\r\n"
8943  "%s%s%s"
8944  "Date: %s\r\n",
8945  conn->status_code,
8946  msg,
8947  cors1,
8948  cors2,
8949  cors3,
8950  date);
8952  send_additional_header(conn);
8953 
8954  (void)mg_printf(conn,
8955  "Last-Modified: %s\r\n"
8956  "Etag: %s\r\n"
8957  "Content-Type: %.*s\r\n"
8958  "Content-Length: %" INT64_FMT "\r\n"
8959  "Connection: %s\r\n"
8960  "Accept-Ranges: bytes\r\n"
8961  "%s%s",
8962  lm,
8963  etag,
8964  (int)mime_vec.len,
8965  mime_vec.ptr,
8966  cl,
8968  range,
8969  encoding);
8970 
8971  /* The previous code must not add any header starting with X- to make
8972  * sure no one of the additional_headers is included twice */
8973 
8974  if (additional_headers != NULL) {
8975  (void)mg_printf(conn,
8976  "%.*s\r\n\r\n",
8977  (int)strlen(additional_headers),
8978  additional_headers);
8979  } else {
8980  (void)mg_printf(conn, "\r\n");
8981  }
8982 
8983  if (strcmp(conn->request_info.request_method, "HEAD") != 0) {
8984  send_file_data(conn, filep, r1, cl);
8985  }
8986  (void)mg_fclose(&filep->access); /* ignore error on read only file */
8987 }
8988 
8989 
8990 #if !defined(NO_CACHING)
8991 static void
8992 handle_not_modified_static_file_request(struct mg_connection *conn,
8993  struct mg_file *filep)
8994 {
8995  char date[64], lm[64], etag[64];
8996  time_t curtime = time(NULL);
8997 
8998  if ((conn == NULL) || (filep == NULL)) {
8999  return;
9000  }
9001  conn->status_code = 304;
9002  gmt_time_string(date, sizeof(date), &curtime);
9003  gmt_time_string(lm, sizeof(lm), &filep->stat.last_modified);
9004  construct_etag(etag, sizeof(etag), &filep->stat);
9005 
9006  (void)mg_printf(conn,
9007  "HTTP/1.1 %d %s\r\n"
9008  "Date: %s\r\n",
9009  conn->status_code,
9010  mg_get_response_code_text(conn, conn->status_code),
9011  date);
9013  send_additional_header(conn);
9014  (void)mg_printf(conn,
9015  "Last-Modified: %s\r\n"
9016  "Etag: %s\r\n"
9017  "Connection: %s\r\n"
9018  "\r\n",
9019  lm,
9020  etag,
9022 }
9023 #endif
9024 
9025 
9026 void
9027 mg_send_file(struct mg_connection *conn, const char *path)
9028 {
9029  mg_send_mime_file(conn, path, NULL);
9030 }
9031 
9032 
9033 void
9034 mg_send_mime_file(struct mg_connection *conn,
9035  const char *path,
9036  const char *mime_type)
9037 {
9038  mg_send_mime_file2(conn, path, mime_type, NULL);
9039 }
9040 
9041 
9042 void
9043 mg_send_mime_file2(struct mg_connection *conn,
9044  const char *path,
9045  const char *mime_type,
9046  const char *additional_headers)
9047 {
9048  struct mg_file file = STRUCT_FILE_INITIALIZER;
9049 
9050  if (!conn) {
9051  /* No conn */
9052  return;
9053  }
9054 
9055  if (mg_stat(conn, path, &file.stat)) {
9056  if (file.stat.is_directory) {
9057  if (!mg_strcasecmp(conn->ctx->config[ENABLE_DIRECTORY_LISTING],
9058  "yes")) {
9059  handle_directory_request(conn, path);
9060  } else {
9061  mg_send_http_error(conn,
9062  403,
9063  "%s",
9064  "Error: Directory listing denied");
9065  }
9066  } else {
9068  conn, path, &file, mime_type, additional_headers);
9069  }
9070  } else {
9071  mg_send_http_error(conn, 404, "%s", "Error: File not found");
9072  }
9073 }
9074 
9075 
9076 /* For a given PUT path, create all intermediate subdirectories.
9077  * Return 0 if the path itself is a directory.
9078  * Return 1 if the path leads to a file.
9079  * Return -1 for if the path is too long.
9080  * Return -2 if path can not be created.
9081 */
9082 static int
9083 put_dir(struct mg_connection *conn, const char *path)
9084 {
9085  char buf[PATH_MAX];
9086  const char *s, *p;
9087  struct mg_file file = STRUCT_FILE_INITIALIZER;
9088  size_t len;
9089  int res = 1;
9090 
9091  for (s = p = path + 2; (p = strchr(s, '/')) != NULL; s = ++p) {
9092  len = (size_t)(p - path);
9093  if (len >= sizeof(buf)) {
9094  /* path too long */
9095  res = -1;
9096  break;
9097  }
9098  memcpy(buf, path, len);
9099  buf[len] = '\0';
9100 
9101  /* Try to create intermediate directory */
9102  DEBUG_TRACE("mkdir(%s)", buf);
9103  if (!mg_stat(conn, buf, &file.stat) && mg_mkdir(conn, buf, 0755) != 0) {
9104  /* path does not exixt and can not be created */
9105  res = -2;
9106  break;
9107  }
9108 
9109  /* Is path itself a directory? */
9110  if (p[1] == '\0') {
9111  res = 0;
9112  }
9113  }
9114 
9115  return res;
9116 }
9117 
9118 
9119 static void
9120 remove_bad_file(const struct mg_connection *conn, const char *path)
9121 {
9122  int r = mg_remove(conn, path);
9123  if (r != 0) {
9124  mg_cry(conn, "%s: Cannot remove invalid file %s", __func__, path);
9125  }
9126 }
9127 
9128 
9129 long long
9130 mg_store_body(struct mg_connection *conn, const char *path)
9131 {
9132  char buf[MG_BUF_LEN];
9133  long long len = 0;
9134  int ret, n;
9135  struct mg_file fi;
9136 
9137  if (conn->consumed_content != 0) {
9138  mg_cry(conn, "%s: Contents already consumed", __func__);
9139  return -11;
9140  }
9141 
9142  ret = put_dir(conn, path);
9143  if (ret < 0) {
9144  /* -1 for path too long,
9145  * -2 for path can not be created. */
9146  return ret;
9147  }
9148  if (ret != 1) {
9149  /* Return 0 means, path itself is a directory. */
9150  return 0;
9151  }
9152 
9153  if (mg_fopen(conn, path, MG_FOPEN_MODE_WRITE, &fi) == 0) {
9154  return -12;
9155  }
9156 
9157  ret = mg_read(conn, buf, sizeof(buf));
9158  while (ret > 0) {
9159  n = (int)fwrite(buf, 1, (size_t)ret, fi.access.fp);
9160  if (n != ret) {
9161  (void)mg_fclose(
9162  &fi.access); /* File is bad and will be removed anyway. */
9163  remove_bad_file(conn, path);
9164  return -13;
9165  }
9166  len += ret;
9167  ret = mg_read(conn, buf, sizeof(buf));
9168  }
9169 
9170  /* File is open for writing. If fclose fails, there was probably an
9171  * error flushing the buffer to disk, so the file on disk might be
9172  * broken. Delete it and return an error to the caller. */
9173  if (mg_fclose(&fi.access) != 0) {
9174  remove_bad_file(conn, path);
9175  return -14;
9176  }
9177 
9178  return len;
9179 }
9180 
9181 
9182 /* Parse a buffer:
9183  * Forward the string pointer till the end of a word, then
9184  * terminate it and forward till the begin of the next word.
9185  */
9186 static int
9188 {
9189  /* Forward until a space is found - use isgraph here */
9190  /* See http://www.cplusplus.com/reference/cctype/ */
9191  while (isgraph(**ppw)) {
9192  (*ppw)++;
9193  }
9194 
9195  /* Check end of word */
9196  if (eol) {
9197  /* must be a end of line */
9198  if ((**ppw != '\r') && (**ppw != '\n')) {
9199  return -1;
9200  }
9201  } else {
9202  /* must be a end of a word, but not a line */
9203  if (**ppw != ' ') {
9204  return -1;
9205  }
9206  }
9207 
9208  /* Terminate and forward to the next word */
9209  do {
9210  **ppw = 0;
9211  (*ppw)++;
9212  } while ((**ppw) && isspace(**ppw));
9213 
9214  /* Check after term */
9215  if (!eol) {
9216  /* if it's not the end of line, there must be a next word */
9217  if (!isgraph(**ppw)) {
9218  return -1;
9219  }
9220  }
9221 
9222  /* ok */
9223  return 1;
9224 }
9225 
9226 
9227 /* Parse HTTP headers from the given buffer, advance buf pointer
9228  * to the point where parsing stopped.
9229  * All parameters must be valid pointers (not NULL).
9230  * Return <0 on error. */
9231 static int
9233 {
9234  int i;
9235  int num_headers = 0;
9236 
9237  for (i = 0; i < (int)MG_MAX_HEADERS; i++) {
9238  char *dp = *buf;
9239  while ((*dp != ':') && (*dp >= 33) && (*dp <= 126)) {
9240  dp++;
9241  }
9242  if (dp == *buf) {
9243  /* End of headers reached. */
9244  break;
9245  }
9246  if (*dp != ':') {
9247  /* This is not a valid field. */
9248  return -1;
9249  }
9250 
9251  /* End of header key (*dp == ':') */
9252  /* Truncate here and set the key name */
9253  *dp = 0;
9254  hdr[i].name = *buf;
9255  do {
9256  dp++;
9257  } while (*dp == ' ');
9258 
9259  /* The rest of the line is the value */
9260  hdr[i].value = dp;
9261  *buf = dp + strcspn(dp, "\r\n");
9262  if (((*buf)[0] != '\r') || ((*buf)[1] != '\n')) {
9263  *buf = NULL;
9264  }
9265 
9266  num_headers = i + 1;
9267  if (*buf) {
9268  (*buf)[0] = 0;
9269  (*buf)[1] = 0;
9270  *buf += 2;
9271  } else {
9272  *buf = dp;
9273  break;
9274  }
9275 
9276  if ((*buf)[0] == '\r') {
9277  /* This is the end of the header */
9278  break;
9279  }
9280  }
9281  return num_headers;
9282 }
9283 
9284 
9285 struct mg_http_method_info {
9286  const char *name;
9287  int request_has_body;
9288  int response_has_body;
9289  int is_safe;
9290  int is_idempotent;
9291  int is_cacheable;
9292 };
9293 
9294 
9295 /* https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods */
9296 static struct mg_http_method_info http_methods[] = {
9297  /* HTTP (RFC 2616) */
9298  {"GET", 0, 1, 1, 1, 1},
9299  {"POST", 1, 1, 0, 0, 0},
9300  {"PUT", 1, 0, 0, 1, 0},
9301  {"DELETE", 0, 0, 0, 1, 0},
9302  {"HEAD", 0, 0, 1, 1, 1},
9303  {"OPTIONS", 0, 0, 1, 1, 0},
9304  {"CONNECT", 1, 1, 0, 0, 0},
9305  /* TRACE method (RFC 2616) is not supported for security reasons */
9306 
9307  /* PATCH method (RFC 5789) */
9308  {"PATCH", 1, 0, 0, 0, 0},
9309  /* PATCH method only allowed for CGI/Lua/LSP and callbacks. */
9310 
9311  /* WEBDAV (RFC 2518) */
9312  {"PROPFIND", 0, 1, 1, 1, 0},
9313  /* http://www.webdav.org/specs/rfc4918.html, 9.1:
9314  * Some PROPFIND results MAY be cached, with care,
9315  * as there is no cache validation mechanism for
9316  * most properties. This method is both safe and
9317  * idempotent (see Section 9.1 of [RFC2616]). */
9318  {"MKCOL", 0, 0, 0, 1, 0},
9319  /* http://www.webdav.org/specs/rfc4918.html, 9.1:
9320  * When MKCOL is invoked without a request body,
9321  * the newly created collection SHOULD have no
9322  * members. A MKCOL request message may contain
9323  * a message body. The precise behavior of a MKCOL
9324  * request when the body is present is undefined,
9325  * ... ==> We do not support MKCOL with body data.
9326  * This method is idempotent, but not safe (see
9327  * Section 9.1 of [RFC2616]). Responses to this
9328  * method MUST NOT be cached. */
9329 
9330  /* Unsupported WEBDAV Methods: */
9331  /* PROPPATCH, COPY, MOVE, LOCK, UNLOCK (RFC 2518) */
9332  /* + 11 methods from RFC 3253 */
9333  /* ORDERPATCH (RFC 3648) */
9334  /* ACL (RFC 3744) */
9335  /* SEARCH (RFC 5323) */
9336  /* + MicroSoft extensions
9337  * https://msdn.microsoft.com/en-us/library/aa142917.aspx */
9338 
9339  /* REPORT method (RFC 3253) */
9340  {"REPORT", 1, 1, 1, 1, 1},
9341  /* REPORT method only allowed for CGI/Lua/LSP and callbacks. */
9342  /* It was defined for WEBDAV in RFC 3253, Sec. 3.6
9343  * (https://tools.ietf.org/html/rfc3253#section-3.6), but seems
9344  * to be useful for REST in case a "GET request with body" is
9345  * required. */
9346 
9347  {NULL, 0, 0, 0, 0, 0}
9348  /* end of list */
9349 };
9350 
9351 
9352 static const struct mg_http_method_info *
9353 get_http_method_info(const char *method)
9354 {
9355  /* Check if the method is known to the server. The list of all known
9356  * HTTP methods can be found here at
9357  * http://www.iana.org/assignments/http-methods/http-methods.xhtml
9358  */
9359  const struct mg_http_method_info *m = http_methods;
9360 
9361  while (m->name) {
9362  if (!strcmp(m->name, method)) {
9363  return m;
9364  }
9365  m++;
9366  }
9367  return NULL;
9368 }
9369 
9370 
9371 static int
9372 is_valid_http_method(const char *method)
9373 {
9374  return (get_http_method_info(method) != NULL);
9375 }
9376 
9377 
9378 /* Parse HTTP request, fill in mg_request_info structure.
9379  * This function modifies the buffer by NUL-terminating
9380  * HTTP request components, header names and header values.
9381  * Parameters:
9382  * buf (in/out): pointer to the HTTP header to parse and split
9383  * len (in): length of HTTP header buffer
9384  * re (out): parsed header as mg_request_info
9385  * buf and ri must be valid pointers (not NULL), len>0.
9386  * Returns <0 on error. */
9387 static int
9388 parse_http_request(char *buf, int len, struct mg_request_info *ri)
9389 {
9390  int request_length;
9391  int init_skip = 0;
9392 
9393  /* Reset attributes. DO NOT TOUCH is_ssl, remote_ip, remote_addr,
9394  * remote_port */
9395  ri->remote_user = ri->request_method = ri->request_uri = ri->http_version =
9396  NULL;
9397  ri->num_headers = 0;
9398 
9399  /* RFC says that all initial whitespaces should be ingored */
9400  /* This included all leading \r and \n (isspace) */
9401  /* See table: http://www.cplusplus.com/reference/cctype/ */
9402  while ((len > 0) && isspace(*(unsigned char *)buf)) {
9403  buf++;
9404  len--;
9405  init_skip++;
9406  }
9407 
9408  if (len == 0) {
9409  /* Incomplete request */
9410  return 0;
9411  }
9412 
9413  /* Control characters are not allowed, including zero */
9414  if (iscntrl(*(unsigned char *)buf)) {
9415  return -1;
9416  }
9417 
9418  /* Find end of HTTP header */
9419  request_length = get_http_header_len(buf, len);
9420  if (request_length <= 0) {
9421  return request_length;
9422  }
9423  buf[request_length - 1] = '\0';
9424 
9425  if ((*buf == 0) || (*buf == '\r') || (*buf == '\n')) {
9426  return -1;
9427  }
9428 
9429  /* The first word has to be the HTTP method */
9430  ri->request_method = buf;
9431 
9432  if (skip_to_end_of_word_and_terminate(&buf, 0) <= 0) {
9433  return -1;
9434  }
9435 
9436  /* Check for a valid http method */
9438  return -1;
9439  }
9440 
9441  /* The second word is the URI */
9442  ri->request_uri = buf;
9443 
9444  if (skip_to_end_of_word_and_terminate(&buf, 0) <= 0) {
9445  return -1;
9446  }
9447 
9448  /* Next would be the HTTP version */
9449  ri->http_version = buf;
9450 
9451  if (skip_to_end_of_word_and_terminate(&buf, 1) <= 0) {
9452  return -1;
9453  }
9454 
9455  /* Check for a valid HTTP version key */
9456  if (strncmp(ri->http_version, "HTTP/", 5) != 0) {
9457  /* Invalid request */
9458  return -1;
9459  }
9460  ri->http_version += 5;
9461 
9462 
9463  /* Parse all HTTP headers */
9464  ri->num_headers = parse_http_headers(&buf, ri->http_headers);
9465  if (ri->num_headers < 0) {
9466  /* Error while parsing headers */
9467  return -1;
9468  }
9469 
9470  return request_length + init_skip;
9471 }
9472 
9473 
9474 static int
9475 parse_http_response(char *buf, int len, struct mg_response_info *ri)
9476 {
9477  int response_length;
9478  int init_skip = 0;
9479  char *tmp, *tmp2;
9480  long l;
9481 
9482  /* Initialize elements. */
9483  ri->http_version = ri->status_text = NULL;
9484  ri->num_headers = ri->status_code = 0;
9485 
9486  /* RFC says that all initial whitespaces should be ingored */
9487  /* This included all leading \r and \n (isspace) */
9488  /* See table: http://www.cplusplus.com/reference/cctype/ */
9489  while ((len > 0) && isspace(*(unsigned char *)buf)) {
9490  buf++;
9491  len--;
9492  init_skip++;
9493  }
9494 
9495  if (len == 0) {
9496  /* Incomplete request */
9497  return 0;
9498  }
9499 
9500  /* Control characters are not allowed, including zero */
9501  if (iscntrl(*(unsigned char *)buf)) {
9502  return -1;
9503  }
9504 
9505  /* Find end of HTTP header */
9506  response_length = get_http_header_len(buf, len);
9507  if (response_length <= 0) {
9508  return response_length;
9509  }
9510  buf[response_length - 1] = '\0';
9511 
9512 
9513  /* TODO: Define mg_response_info and implement parsing */
9514  (void)buf;
9515  (void)len;
9516  (void)ri;
9517 
9518  /* RFC says that all initial whitespaces should be ingored */
9519  while ((*buf != '\0') && isspace(*(unsigned char *)buf)) {
9520  buf++;
9521  }
9522  if ((*buf == 0) || (*buf == '\r') || (*buf == '\n')) {
9523  return -1;
9524  }
9525 
9526  /* The first word is the HTTP version */
9527  /* Check for a valid HTTP version key */
9528  if (strncmp(buf, "HTTP/", 5) != 0) {
9529  /* Invalid request */
9530  return -1;
9531  }
9532  buf += 5;
9533  if (!isgraph(buf[0])) {
9534  /* Invalid request */
9535  return -1;
9536  }
9537  ri->http_version = buf;
9538 
9539  if (skip_to_end_of_word_and_terminate(&buf, 0) <= 0) {
9540  return -1;
9541  }
9542 
9543  /* The second word is the status as a number */
9544  tmp = buf;
9545 
9546  if (skip_to_end_of_word_and_terminate(&buf, 0) <= 0) {
9547  return -1;
9548  }
9549 
9550  l = strtol(tmp, &tmp2, 10);
9551  if ((l < 100) || (l >= 1000) || ((tmp2 - tmp) != 3) || (*tmp2 != 0)) {
9552  /* Everything else but a 3 digit code is invalid */
9553  return -1;
9554  }
9555  ri->status_code = (int)l;
9556 
9557  /* The rest of the line is the status text */
9558  ri->status_text = buf;
9559 
9560  /* Find end of status text */
9561  /* isgraph or isspace = isprint */
9562  while (isprint(*buf)) {
9563  buf++;
9564  }
9565  if ((*buf != '\r') && (*buf != '\n')) {
9566  return -1;
9567  }
9568  /* Terminate string and forward buf to next line */
9569  do {
9570  *buf = 0;
9571  buf++;
9572  } while ((*buf) && isspace(*buf));
9573 
9574 
9575  /* Parse all HTTP headers */
9576  ri->num_headers = parse_http_headers(&buf, ri->http_headers);
9577  if (ri->num_headers < 0) {
9578  /* Error while parsing headers */
9579  return -1;
9580  }
9581 
9582  return response_length + init_skip;
9583 }
9584 
9585 
9586 /* Keep reading the input (either opened file descriptor fd, or socket sock,
9587  * or SSL descriptor ssl) into buffer buf, until \r\n\r\n appears in the
9588  * buffer (which marks the end of HTTP request). Buffer buf may already
9589  * have some data. The length of the data is stored in nread.
9590  * Upon every read operation, increase nread by the number of bytes read. */
9591 static int
9592 read_message(FILE *fp,
9593  struct mg_connection *conn,
9594  char *buf,
9595  int bufsiz,
9596  int *nread)
9597 {
9598  int request_len, n = 0;
9599  struct timespec last_action_time;
9600  double request_timeout;
9601 
9602  if (!conn) {
9603  return 0;
9604  }
9605 
9606  memset(&last_action_time, 0, sizeof(last_action_time));
9607 
9608  if (conn->ctx->config[REQUEST_TIMEOUT]) {
9609  /* value of request_timeout is in seconds, config in milliseconds */
9610  request_timeout = atof(conn->ctx->config[REQUEST_TIMEOUT]) / 1000.0;
9611  } else {
9612  request_timeout = -1.0;
9613  }
9614  if (conn->handled_requests > 0) {
9615  if (conn->ctx->config[KEEP_ALIVE_TIMEOUT]) {
9616  request_timeout =
9617  atof(conn->ctx->config[KEEP_ALIVE_TIMEOUT]) / 1000.0;
9618  }
9619  }
9620 
9621  request_len = get_http_header_len(buf, *nread);
9622 
9623  /* first time reading from this connection */
9624  clock_gettime(CLOCK_MONOTONIC, &last_action_time);
9625 
9626  while (request_len == 0) {
9627  /* Full request not yet received */
9628  if (conn->ctx->stop_flag != 0) {
9629  /* Server is to be stopped. */
9630  return -1;
9631  }
9632 
9633  if (*nread >= bufsiz) {
9634  /* Request too long */
9635  return -2;
9636  }
9637 
9638  n = pull_inner(
9639  fp, conn, buf + *nread, bufsiz - *nread, request_timeout);
9640  if (n == -2) {
9641  /* Receive error */
9642  return -1;
9643  }
9644  if (n > 0) {
9645  *nread += n;
9646  request_len = get_http_header_len(buf, *nread);
9647  } else {
9648  request_len = 0;
9649  }
9650 
9651  if ((request_len == 0) && (request_timeout >= 0)) {
9652  if (mg_difftimespec(&last_action_time, &(conn->req_time))
9653  > request_timeout) {
9654  /* Timeout */
9655  return -1;
9656  }
9657  clock_gettime(CLOCK_MONOTONIC, &last_action_time);
9658  }
9659  }
9660 
9661  return request_len;
9662 }
9663 
9664 
9665 #if !defined(NO_CACHING)
9666 /* Return True if we should reply 304 Not Modified. */
9667 static int
9668 is_not_modified(const struct mg_connection *conn,
9669  const struct mg_file_stat *filestat)
9670 {
9671  char etag[64];
9672  const char *ims = mg_get_header(conn, "If-Modified-Since");
9673  const char *inm = mg_get_header(conn, "If-None-Match");
9674  construct_etag(etag, sizeof(etag), filestat);
9675 
9676  return ((inm != NULL) && !mg_strcasecmp(etag, inm))
9677  || ((ims != NULL)
9678  && (filestat->last_modified <= parse_date_string(ims)));
9679 }
9680 #endif /* !NO_CACHING */
9681 
9682 
9683 #if !defined(NO_CGI) || !defined(NO_FILES)
9684 static int
9685 forward_body_data(struct mg_connection *conn, FILE *fp, SOCKET sock, SSL *ssl)
9686 {
9687  const char *expect, *body;
9688  char buf[MG_BUF_LEN];
9689  int to_read, nread, success = 0;
9690  int64_t buffered_len;
9691  double timeout = -1.0;
9692 
9693  if (!conn) {
9694  return 0;
9695  }
9696  if (conn->ctx->config[REQUEST_TIMEOUT]) {
9697  timeout = atoi(conn->ctx->config[REQUEST_TIMEOUT]) / 1000.0;
9698  }
9699 
9700  expect = mg_get_header(conn, "Expect");
9701  /* assert(fp != NULL); */
9702  if (!fp) {
9703  mg_send_http_error(conn, 500, "%s", "Error: NULL File");
9704  return 0;
9705  }
9706 
9707  if ((conn->content_len == -1) && (!conn->is_chunked)) {
9708  /* Content length is not specified by the client. */
9709  mg_send_http_error(conn,
9710  411,
9711  "%s",
9712  "Error: Client did not specify content length");
9713  } else if ((expect != NULL)
9714  && (mg_strcasecmp(expect, "100-continue") != 0)) {
9715  /* Client sent an "Expect: xyz" header and xyz is not 100-continue.
9716  */
9717  mg_send_http_error(conn,
9718  417,
9719  "Error: Can not fulfill expectation %s",
9720  expect);
9721  } else {
9722  if (expect != NULL) {
9723  (void)mg_printf(conn, "%s", "HTTP/1.1 100 Continue\r\n\r\n");
9724  conn->status_code = 100;
9725  } else {
9726  conn->status_code = 200;
9727  }
9728 
9729  buffered_len = (int64_t)(conn->data_len) - (int64_t)conn->request_len
9730  - conn->consumed_content;
9731 
9732  /* assert(buffered_len >= 0); */
9733  /* assert(conn->consumed_content == 0); */
9734 
9735  if ((buffered_len < 0) || (conn->consumed_content != 0)) {
9736  mg_send_http_error(conn, 500, "%s", "Error: Size mismatch");
9737  return 0;
9738  }
9739 
9740  if (buffered_len > 0) {
9741  if ((int64_t)buffered_len > conn->content_len) {
9742  buffered_len = (int)conn->content_len;
9743  }
9744  body = conn->buf + conn->request_len + conn->consumed_content;
9745  push_all(conn->ctx, fp, sock, ssl, body, (int64_t)buffered_len);
9746  conn->consumed_content += buffered_len;
9747  }
9748 
9749  nread = 0;
9750  while (conn->consumed_content < conn->content_len) {
9751  to_read = sizeof(buf);
9752  if ((int64_t)to_read > conn->content_len - conn->consumed_content) {
9753  to_read = (int)(conn->content_len - conn->consumed_content);
9754  }
9755  nread = pull_inner(NULL, conn, buf, to_read, timeout);
9756  if (nread == -2) {
9757  /* error */
9758  break;
9759  }
9760  if (nread > 0) {
9761  if (push_all(conn->ctx, fp, sock, ssl, buf, nread) != nread) {
9762  break;
9763  }
9764  }
9765  conn->consumed_content += nread;
9766  }
9767 
9768  if (conn->consumed_content == conn->content_len) {
9769  success = (nread >= 0);
9770  }
9771 
9772  /* Each error code path in this function must send an error */
9773  if (!success) {
9774  /* NOTE: Maybe some data has already been sent. */
9775  /* TODO (low): If some data has been sent, a correct error
9776  * reply can no longer be sent, so just close the connection */
9777  mg_send_http_error(conn, 500, "%s", "");
9778  }
9779  }
9780 
9781  return success;
9782 }
9783 #endif
9784 
9785 #if !defined(NO_CGI)
9786 /* This structure helps to create an environment for the spawned CGI
9787  * program.
9788  * Environment is an array of "VARIABLE=VALUE\0" ASCIIZ strings,
9789  * last element must be NULL.
9790  * However, on Windows there is a requirement that all these
9791  * VARIABLE=VALUE\0
9792  * strings must reside in a contiguous buffer. The end of the buffer is
9793  * marked by two '\0' characters.
9794  * We satisfy both worlds: we create an envp array (which is vars), all
9795  * entries are actually pointers inside buf. */
9796 struct cgi_environment {
9797  struct mg_connection *conn;
9798  /* Data block */
9799  char *buf; /* Environment buffer */
9800  size_t buflen; /* Space available in buf */
9801  size_t bufused; /* Space taken in buf */
9802  /* Index block */
9803  char **var; /* char **envp */
9804  size_t varlen; /* Number of variables available in var */
9805  size_t varused; /* Number of variables stored in var */
9806 };
9807 
9808 
9809 static void addenv(struct cgi_environment *env,
9810  PRINTF_FORMAT_STRING(const char *fmt),
9811  ...) PRINTF_ARGS(2, 3);
9812 
9813 /* Append VARIABLE=VALUE\0 string to the buffer, and add a respective
9814  * pointer into the vars array. Assumes env != NULL and fmt != NULL. */
9815 static void
9816 addenv(struct cgi_environment *env, const char *fmt, ...)
9817 {
9818  size_t n, space;
9819  int truncated = 0;
9820  char *added;
9821  va_list ap;
9822 
9823  /* Calculate how much space is left in the buffer */
9824  space = (env->buflen - env->bufused);
9825 
9826  /* Calculate an estimate for the required space */
9827  n = strlen(fmt) + 2 + 128;
9828 
9829  do {
9830  if (space <= n) {
9831  /* Allocate new buffer */
9832  n = env->buflen + CGI_ENVIRONMENT_SIZE;
9833  added = (char *)mg_realloc_ctx(env->buf, n, env->conn->ctx);
9834  if (!added) {
9835  /* Out of memory */
9836  mg_cry(env->conn,
9837  "%s: Cannot allocate memory for CGI variable [%s]",
9838  __func__,
9839  fmt);
9840  return;
9841  }
9842  env->buf = added;
9843  env->buflen = n;
9844  space = (env->buflen - env->bufused);
9845  }
9846 
9847  /* Make a pointer to the free space int the buffer */
9848  added = env->buf + env->bufused;
9849 
9850  /* Copy VARIABLE=VALUE\0 string into the free space */
9851  va_start(ap, fmt);
9852  mg_vsnprintf(env->conn, &truncated, added, (size_t)space, fmt, ap);
9853  va_end(ap);
9854 
9855  /* Do not add truncated strings to the environment */
9856  if (truncated) {
9857  /* Reallocate the buffer */
9858  space = 0;
9859  n = 1;
9860  }
9861  } while (truncated);
9862 
9863  /* Calculate number of bytes added to the environment */
9864  n = strlen(added) + 1;
9865  env->bufused += n;
9866 
9867  /* Now update the variable index */
9868  space = (env->varlen - env->varused);
9869  if (space < 2) {
9870  mg_cry(env->conn,
9871  "%s: Cannot register CGI variable [%s]",
9872  __func__,
9873  fmt);
9874  return;
9875  }
9876 
9877  /* Append a pointer to the added string into the envp array */
9878  env->var[env->varused] = added;
9879  env->varused++;
9880 }
9881 
9882 /* Return 0 on success, non-zero if an error occurs. */
9883 
9884 static int
9885 prepare_cgi_environment(struct mg_connection *conn,
9886  const char *prog,
9887  struct cgi_environment *env)
9888 {
9889  const char *s;
9890  struct vec var_vec;
9891  char *p, src_addr[IP_ADDR_STR_LEN], http_var_name[128];
9892  int i, truncated, uri_len;
9893 
9894  if ((conn == NULL) || (prog == NULL) || (env == NULL)) {
9895  return -1;
9896  }
9897 
9898  env->conn = conn;
9899  env->buflen = CGI_ENVIRONMENT_SIZE;
9900  env->bufused = 0;
9901  env->buf = (char *)mg_malloc_ctx(env->buflen, conn->ctx);
9902  if (env->buf == NULL) {
9903  mg_cry(conn,
9904  "%s: Not enough memory for environmental buffer",
9905  __func__);
9906  return -1;
9907  }
9908  env->varlen = MAX_CGI_ENVIR_VARS;
9909  env->varused = 0;
9910  env->var = (char **)mg_malloc_ctx(env->buflen * sizeof(char *), conn->ctx);
9911  if (env->var == NULL) {
9912  mg_cry(conn,
9913  "%s: Not enough memory for environmental variables",
9914  __func__);
9915  mg_free(env->buf);
9916  return -1;
9917  }
9918 
9919  addenv(env, "SERVER_NAME=%s", conn->ctx->config[AUTHENTICATION_DOMAIN]);
9920  addenv(env, "SERVER_ROOT=%s", conn->ctx->config[DOCUMENT_ROOT]);
9921  addenv(env, "DOCUMENT_ROOT=%s", conn->ctx->config[DOCUMENT_ROOT]);
9922  addenv(env, "SERVER_SOFTWARE=%s/%s", "Civetweb", mg_version());
9923 
9924  /* Prepare the environment block */
9925  addenv(env, "%s", "GATEWAY_INTERFACE=CGI/1.1");
9926  addenv(env, "%s", "SERVER_PROTOCOL=HTTP/1.1");
9927  addenv(env, "%s", "REDIRECT_STATUS=200"); /* For PHP */
9928 
9929 #if defined(USE_IPV6)
9930  if (conn->client.lsa.sa.sa_family == AF_INET6) {
9931  addenv(env, "SERVER_PORT=%d", ntohs(conn->client.lsa.sin6.sin6_port));
9932  } else
9933 #endif
9934  {
9935  addenv(env, "SERVER_PORT=%d", ntohs(conn->client.lsa.sin.sin_port));
9936  }
9937 
9938  sockaddr_to_string(src_addr, sizeof(src_addr), &conn->client.rsa);
9939  addenv(env, "REMOTE_ADDR=%s", src_addr);
9940 
9941  addenv(env, "REQUEST_METHOD=%s", conn->request_info.request_method);
9942  addenv(env, "REMOTE_PORT=%d", conn->request_info.remote_port);
9943 
9944  addenv(env, "REQUEST_URI=%s", conn->request_info.request_uri);
9945  addenv(env, "LOCAL_URI=%s", conn->request_info.local_uri);
9946 
9947  /* SCRIPT_NAME */
9948  uri_len = (int)strlen(conn->request_info.local_uri);
9949  if (conn->path_info == NULL) {
9950  if (conn->request_info.local_uri[uri_len - 1] != '/') {
9951  /* URI: /path_to_script/script.cgi */
9952  addenv(env, "SCRIPT_NAME=%s", conn->request_info.local_uri);
9953  } else {
9954  /* URI: /path_to_script/ ... using index.cgi */
9955  const char *index_file = strrchr(prog, '/');
9956  if (index_file) {
9957  addenv(env,
9958  "SCRIPT_NAME=%s%s",
9959  conn->request_info.local_uri,
9960  index_file + 1);
9961  }
9962  }
9963  } else {
9964  /* URI: /path_to_script/script.cgi/path_info */
9965  addenv(env,
9966  "SCRIPT_NAME=%.*s",
9967  uri_len - (int)strlen(conn->path_info),
9968  conn->request_info.local_uri);
9969  }
9970 
9971  addenv(env, "SCRIPT_FILENAME=%s", prog);
9972  if (conn->path_info == NULL) {
9973  addenv(env, "PATH_TRANSLATED=%s", conn->ctx->config[DOCUMENT_ROOT]);
9974  } else {
9975  addenv(env,
9976  "PATH_TRANSLATED=%s%s",
9977  conn->ctx->config[DOCUMENT_ROOT],
9978  conn->path_info);
9979  }
9980 
9981  addenv(env, "HTTPS=%s", (conn->ssl == NULL) ? "off" : "on");
9982 
9983  if ((s = mg_get_header(conn, "Content-Type")) != NULL) {
9984  addenv(env, "CONTENT_TYPE=%s", s);
9985  }
9986  if (conn->request_info.query_string != NULL) {
9987  addenv(env, "QUERY_STRING=%s", conn->request_info.query_string);
9988  }
9989  if ((s = mg_get_header(conn, "Content-Length")) != NULL) {
9990  addenv(env, "CONTENT_LENGTH=%s", s);
9991  }
9992  if ((s = getenv("PATH")) != NULL) {
9993  addenv(env, "PATH=%s", s);
9994  }
9995  if (conn->path_info != NULL) {
9996  addenv(env, "PATH_INFO=%s", conn->path_info);
9997  }
9998 
9999  if (conn->status_code > 0) {
10000  /* CGI error handler should show the status code */
10001  addenv(env, "STATUS=%d", conn->status_code);
10002  }
10003 
10004 #if defined(_WIN32)
10005  if ((s = getenv("COMSPEC")) != NULL) {
10006  addenv(env, "COMSPEC=%s", s);
10007  }
10008  if ((s = getenv("SYSTEMROOT")) != NULL) {
10009  addenv(env, "SYSTEMROOT=%s", s);
10010  }
10011  if ((s = getenv("SystemDrive")) != NULL) {
10012  addenv(env, "SystemDrive=%s", s);
10013  }
10014  if ((s = getenv("ProgramFiles")) != NULL) {
10015  addenv(env, "ProgramFiles=%s", s);
10016  }
10017  if ((s = getenv("ProgramFiles(x86)")) != NULL) {
10018  addenv(env, "ProgramFiles(x86)=%s", s);
10019  }
10020 #else
10021  if ((s = getenv("LD_LIBRARY_PATH")) != NULL) {
10022  addenv(env, "LD_LIBRARY_PATH=%s", s);
10023  }
10024 #endif /* _WIN32 */
10025 
10026  if ((s = getenv("PERLLIB")) != NULL) {
10027  addenv(env, "PERLLIB=%s", s);
10028  }
10029 
10030  if (conn->request_info.remote_user != NULL) {
10031  addenv(env, "REMOTE_USER=%s", conn->request_info.remote_user);
10032  addenv(env, "%s", "AUTH_TYPE=Digest");
10033  }
10034 
10035  /* Add all headers as HTTP_* variables */
10036  for (i = 0; i < conn->request_info.num_headers; i++) {
10037 
10038  (void)mg_snprintf(conn,
10039  &truncated,
10040  http_var_name,
10041  sizeof(http_var_name),
10042  "HTTP_%s",
10043  conn->request_info.http_headers[i].name);
10044 
10045  if (truncated) {
10046  mg_cry(conn,
10047  "%s: HTTP header variable too long [%s]",
10048  __func__,
10049  conn->request_info.http_headers[i].name);
10050  continue;
10051  }
10052 
10053  /* Convert variable name into uppercase, and change - to _ */
10054  for (p = http_var_name; *p != '\0'; p++) {
10055  if (*p == '-') {
10056  *p = '_';
10057  }
10058  *p = (char)toupper(*(unsigned char *)p);
10059  }
10060 
10061  addenv(env,
10062  "%s=%s",
10063  http_var_name,
10064  conn->request_info.http_headers[i].value);
10065  }
10066 
10067  /* Add user-specified variables */
10068  s = conn->ctx->config[CGI_ENVIRONMENT];
10069  while ((s = next_option(s, &var_vec, NULL)) != NULL) {
10070  addenv(env, "%.*s", (int)var_vec.len, var_vec.ptr);
10071  }
10072 
10073  env->var[env->varused] = NULL;
10074  env->buf[env->bufused] = '\0';
10075 
10076  return 0;
10077 }
10078 
10079 
10080 static void
10081 handle_cgi_request(struct mg_connection *conn, const char *prog)
10082 {
10083  char *buf;
10084  size_t buflen;
10085  int headers_len, data_len, i, truncated;
10086  int fdin[2] = {-1, -1}, fdout[2] = {-1, -1}, fderr[2] = {-1, -1};
10087  const char *status, *status_text, *connection_state;
10088  char *pbuf, dir[PATH_MAX], *p;
10089  struct mg_request_info ri;
10090  struct cgi_environment blk;
10091  FILE *in = NULL, *out = NULL, *err = NULL;
10092  struct mg_file fout = STRUCT_FILE_INITIALIZER;
10093  pid_t pid = (pid_t)-1;
10094 
10095  if (conn == NULL) {
10096  return;
10097  }
10098 
10099  buf = NULL;
10100  buflen = 16384;
10101  i = prepare_cgi_environment(conn, prog, &blk);
10102  if (i != 0) {
10103  blk.buf = NULL;
10104  blk.var = NULL;
10105  goto done;
10106  }
10107 
10108  /* CGI must be executed in its own directory. 'dir' must point to the
10109  * directory containing executable program, 'p' must point to the
10110  * executable program name relative to 'dir'. */
10111  (void)mg_snprintf(conn, &truncated, dir, sizeof(dir), "%s", prog);
10112 
10113  if (truncated) {
10114  mg_cry(conn, "Error: CGI program \"%s\": Path too long", prog);
10115  mg_send_http_error(conn, 500, "Error: %s", "CGI path too long");
10116  goto done;
10117  }
10118 
10119  if ((p = strrchr(dir, '/')) != NULL) {
10120  *p++ = '\0';
10121  } else {
10122  dir[0] = '.';
10123  dir[1] = '\0';
10124  p = (char *)prog;
10125  }
10126 
10127  if ((pipe(fdin) != 0) || (pipe(fdout) != 0) || (pipe(fderr) != 0)) {
10128  status = strerror(ERRNO);
10129  mg_cry(conn,
10130  "Error: CGI program \"%s\": Can not create CGI pipes: %s",
10131  prog,
10132  status);
10133  mg_send_http_error(conn,
10134  500,
10135  "Error: Cannot create CGI pipe: %s",
10136  status);
10137  goto done;
10138  }
10139 
10140  DEBUG_TRACE("CGI: spawn %s %s\n", dir, p);
10141  pid = spawn_process(conn, p, blk.buf, blk.var, fdin, fdout, fderr, dir);
10142 
10143  if (pid == (pid_t)-1) {
10144  status = strerror(ERRNO);
10145  mg_cry(conn,
10146  "Error: CGI program \"%s\": Can not spawn CGI process: %s",
10147  prog,
10148  status);
10149  mg_send_http_error(conn,
10150  500,
10151  "Error: Cannot spawn CGI process [%s]: %s",
10152  prog,
10153  status);
10154  goto done;
10155  }
10156 
10157  /* Make sure child closes all pipe descriptors. It must dup them to 0,1
10158  */
10159  set_close_on_exec((SOCKET)fdin[0], conn); /* stdin read */
10160  set_close_on_exec((SOCKET)fdout[1], conn); /* stdout write */
10161  set_close_on_exec((SOCKET)fderr[1], conn); /* stderr write */
10162  set_close_on_exec((SOCKET)fdin[1], conn); /* stdin write */
10163  set_close_on_exec((SOCKET)fdout[0], conn); /* stdout read */
10164  set_close_on_exec((SOCKET)fderr[0], conn); /* stderr read */
10165 
10166  /* Parent closes only one side of the pipes.
10167  * If we don't mark them as closed, close() attempt before
10168  * return from this function throws an exception on Windows.
10169  * Windows does not like when closed descriptor is closed again. */
10170  (void)close(fdin[0]);
10171  (void)close(fdout[1]);
10172  (void)close(fderr[1]);
10173  fdin[0] = fdout[1] = fderr[1] = -1;
10174 
10175  if ((in = fdopen(fdin[1], "wb")) == NULL) {
10176  status = strerror(ERRNO);
10177  mg_cry(conn,
10178  "Error: CGI program \"%s\": Can not open stdin: %s",
10179  prog,
10180  status);
10181  mg_send_http_error(conn,
10182  500,
10183  "Error: CGI can not open fdin\nfopen: %s",
10184  status);
10185  goto done;
10186  }
10187 
10188  if ((out = fdopen(fdout[0], "rb")) == NULL) {
10189  status = strerror(ERRNO);
10190  mg_cry(conn,
10191  "Error: CGI program \"%s\": Can not open stdout: %s",
10192  prog,
10193  status);
10194  mg_send_http_error(conn,
10195  500,
10196  "Error: CGI can not open fdout\nfopen: %s",
10197  status);
10198  goto done;
10199  }
10200 
10201  if ((err = fdopen(fderr[0], "rb")) == NULL) {
10202  status = strerror(ERRNO);
10203  mg_cry(conn,
10204  "Error: CGI program \"%s\": Can not open stderr: %s",
10205  prog,
10206  status);
10207  mg_send_http_error(conn,
10208  500,
10209  "Error: CGI can not open fdout\nfopen: %s",
10210  status);
10211  goto done;
10212  }
10213 
10214  setbuf(in, NULL);
10215  setbuf(out, NULL);
10216  setbuf(err, NULL);
10217  fout.access.fp = out;
10218 
10219  if ((conn->request_info.content_length != 0) || (conn->is_chunked)) {
10220  DEBUG_TRACE("CGI: send body data (%lli)\n",
10221  (signed long long)conn->request_info.content_length);
10222 
10223  /* This is a POST/PUT request, or another request with body data. */
10224  if (!forward_body_data(conn, in, INVALID_SOCKET, NULL)) {
10225  /* Error sending the body data */
10226  mg_cry(conn,
10227  "Error: CGI program \"%s\": Forward body data failed",
10228  prog);
10229  goto done;
10230  }
10231  }
10232 
10233  /* Close so child gets an EOF. */
10234  fclose(in);
10235  in = NULL;
10236  fdin[1] = -1;
10237 
10238  /* Now read CGI reply into a buffer. We need to set correct
10239  * status code, thus we need to see all HTTP headers first.
10240  * Do not send anything back to client, until we buffer in all
10241  * HTTP headers. */
10242  data_len = 0;
10243  buf = (char *)mg_malloc_ctx(buflen, conn->ctx);
10244  if (buf == NULL) {
10245  mg_send_http_error(conn,
10246  500,
10247  "Error: Not enough memory for CGI buffer (%u bytes)",
10248  (unsigned int)buflen);
10249  mg_cry(conn,
10250  "Error: CGI program \"%s\": Not enough memory for buffer (%u "
10251  "bytes)",
10252  prog,
10253  (unsigned int)buflen);
10254  goto done;
10255  }
10256 
10257  DEBUG_TRACE("CGI: %s", "wait for response");
10258  headers_len = read_message(out, conn, buf, (int)buflen, &data_len);
10259  DEBUG_TRACE("CGI: response: %li", (signed long)headers_len);
10260 
10261  if (headers_len <= 0) {
10262 
10263  /* Could not parse the CGI response. Check if some error message on
10264  * stderr. */
10265  i = pull_all(err, conn, buf, (int)buflen);
10266  if (i > 0) {
10267  mg_cry(conn,
10268  "Error: CGI program \"%s\" sent error "
10269  "message: [%.*s]",
10270  prog,
10271  i,
10272  buf);
10273  mg_send_http_error(conn,
10274  500,
10275  "Error: CGI program \"%s\" sent error "
10276  "message: [%.*s]",
10277  prog,
10278  i,
10279  buf);
10280  } else {
10281  mg_cry(conn,
10282  "Error: CGI program sent malformed or too big "
10283  "(>%u bytes) HTTP headers: [%.*s]",
10284  (unsigned)buflen,
10285  data_len,
10286  buf);
10287 
10288  mg_send_http_error(conn,
10289  500,
10290  "Error: CGI program sent malformed or too big "
10291  "(>%u bytes) HTTP headers: [%.*s]",
10292  (unsigned)buflen,
10293  data_len,
10294  buf);
10295  }
10296 
10297  goto done;
10298  }
10299 
10300  pbuf = buf;
10301  buf[headers_len - 1] = '\0';
10303 
10304  /* Make up and send the status line */
10305  status_text = "OK";
10306  if ((status = get_header(ri.http_headers, ri.num_headers, "Status"))
10307  != NULL) {
10308  conn->status_code = atoi(status);
10309  status_text = status;
10310  while (isdigit(*(const unsigned char *)status_text)
10311  || *status_text == ' ') {
10312  status_text++;
10313  }
10314  } else if (get_header(ri.http_headers, ri.num_headers, "Location")
10315  != NULL) {
10316  conn->status_code = 302;
10317  } else {
10318  conn->status_code = 200;
10319  }
10320  connection_state =
10321  get_header(ri.http_headers, ri.num_headers, "Connection");
10322  if (!header_has_option(connection_state, "keep-alive")) {
10323  conn->must_close = 1;
10324  }
10325 
10326  DEBUG_TRACE("CGI: response %u %s", conn->status_code, status_text);
10327 
10328  (void)mg_printf(conn, "HTTP/1.1 %d %s\r\n", conn->status_code, status_text);
10329 
10330  /* Send headers */
10331  for (i = 0; i < ri.num_headers; i++) {
10332  mg_printf(conn,
10333  "%s: %s\r\n",
10334  ri.http_headers[i].name,
10335  ri.http_headers[i].value);
10336  }
10337  mg_write(conn, "\r\n", 2);
10338 
10339  /* Send chunk of data that may have been read after the headers */
10340  mg_write(conn, buf + headers_len, (size_t)(data_len - headers_len));
10341 
10342  /* Read the rest of CGI output and send to the client */
10343  send_file_data(conn, &fout, 0, INT64_MAX);
10344 
10345  DEBUG_TRACE("CGI: %s", "all data sent");
10346 
10347 done:
10348  mg_free(blk.var);
10349  mg_free(blk.buf);
10350 
10351  if (pid != (pid_t)-1) {
10352  kill(pid, SIGKILL);
10353 #if !defined(_WIN32)
10354  {
10355  int st;
10356  while (waitpid(pid, &st, 0) != -1)
10357  ; /* clean zombies */
10358  }
10359 #endif
10360  }
10361  if (fdin[0] != -1) {
10362  close(fdin[0]);
10363  }
10364  if (fdout[1] != -1) {
10365  close(fdout[1]);
10366  }
10367 
10368  if (in != NULL) {
10369  fclose(in);
10370  } else if (fdin[1] != -1) {
10371  close(fdin[1]);
10372  }
10373 
10374  if (out != NULL) {
10375  fclose(out);
10376  } else if (fdout[0] != -1) {
10377  close(fdout[0]);
10378  }
10379 
10380  if (err != NULL) {
10381  fclose(err);
10382  } else if (fderr[0] != -1) {
10383  close(fderr[0]);
10384  }
10385 
10386  if (buf != NULL) {
10387  mg_free(buf);
10388  }
10389 }
10390 #endif /* !NO_CGI */
10391 
10392 
10393 #if !defined(NO_FILES)
10394 static void
10395 mkcol(struct mg_connection *conn, const char *path)
10396 {
10397  int rc, body_len;
10398  struct de de;
10399  char date[64];
10400  time_t curtime = time(NULL);
10401 
10402  if (conn == NULL) {
10403  return;
10404  }
10405 
10406  /* TODO (mid): Check the mg_send_http_error situations in this function
10407  */
10408 
10409  memset(&de.file, 0, sizeof(de.file));
10410  if (!mg_stat(conn, path, &de.file)) {
10411  mg_cry(conn,
10412  "%s: mg_stat(%s) failed: %s",
10413  __func__,
10414  path,
10415  strerror(ERRNO));
10416  }
10417 
10418  if (de.file.last_modified) {
10419  /* TODO (mid): This check does not seem to make any sense ! */
10420  /* TODO (mid): Add a webdav unit test first, before changing
10421  * anything here. */
10423  conn, 405, "Error: mkcol(%s): %s", path, strerror(ERRNO));
10424  return;
10425  }
10426 
10427  body_len = conn->data_len - conn->request_len;
10428  if (body_len > 0) {
10430  conn, 415, "Error: mkcol(%s): %s", path, strerror(ERRNO));
10431  return;
10432  }
10433 
10434  rc = mg_mkdir(conn, path, 0755);
10435 
10436  if (rc == 0) {
10437  conn->status_code = 201;
10438  gmt_time_string(date, sizeof(date), &curtime);
10439  mg_printf(conn,
10440  "HTTP/1.1 %d Created\r\n"
10441  "Date: %s\r\n",
10442  conn->status_code,
10443  date);
10445  send_additional_header(conn);
10446  mg_printf(conn,
10447  "Content-Length: 0\r\n"
10448  "Connection: %s\r\n\r\n",
10450  } else if (rc == -1) {
10451  if (errno == EEXIST) {
10453  conn, 405, "Error: mkcol(%s): %s", path, strerror(ERRNO));
10454  } else if (errno == EACCES) {
10456  conn, 403, "Error: mkcol(%s): %s", path, strerror(ERRNO));
10457  } else if (errno == ENOENT) {
10459  conn, 409, "Error: mkcol(%s): %s", path, strerror(ERRNO));
10460  } else {
10462  conn, 500, "fopen(%s): %s", path, strerror(ERRNO));
10463  }
10464  }
10465 }
10466 
10467 
10468 static void
10469 put_file(struct mg_connection *conn, const char *path)
10470 {
10471  struct mg_file file = STRUCT_FILE_INITIALIZER;
10472  const char *range;
10473  int64_t r1, r2;
10474  int rc;
10475  char date[64];
10476  time_t curtime = time(NULL);
10477 
10478  if (conn == NULL) {
10479  return;
10480  }
10481 
10482  if (mg_stat(conn, path, &file.stat)) {
10483  /* File already exists */
10484  conn->status_code = 200;
10485 
10486  if (file.stat.is_directory) {
10487  /* This is an already existing directory,
10488  * so there is nothing to do for the server. */
10489  rc = 0;
10490 
10491  } else {
10492  /* File exists and is not a directory. */
10493  /* Can it be replaced? */
10494 
10495  if (file.access.membuf != NULL) {
10496  /* This is an "in-memory" file, that can not be replaced */
10497  mg_send_http_error(conn,
10498  405,
10499  "Error: Put not possible\nReplacing %s "
10500  "is not supported",
10501  path);
10502  return;
10503  }
10504 
10505  /* Check if the server may write this file */
10506  if (access(path, W_OK) == 0) {
10507  /* Access granted */
10508  conn->status_code = 200;
10509  rc = 1;
10510  } else {
10512  conn,
10513  403,
10514  "Error: Put not possible\nReplacing %s is not allowed",
10515  path);
10516  return;
10517  }
10518  }
10519  } else {
10520  /* File should be created */
10521  conn->status_code = 201;
10522  rc = put_dir(conn, path);
10523  }
10524 
10525  if (rc == 0) {
10526  /* put_dir returns 0 if path is a directory */
10527  gmt_time_string(date, sizeof(date), &curtime);
10528  mg_printf(conn,
10529  "HTTP/1.1 %d %s\r\n",
10530  conn->status_code,
10531  mg_get_response_code_text(NULL, conn->status_code));
10532  send_no_cache_header(conn);
10533  send_additional_header(conn);
10534  mg_printf(conn,
10535  "Date: %s\r\n"
10536  "Content-Length: 0\r\n"
10537  "Connection: %s\r\n\r\n",
10538  date,
10540 
10541  /* Request to create a directory has been fulfilled successfully.
10542  * No need to put a file. */
10543  return;
10544  }
10545 
10546  if (rc == -1) {
10547  /* put_dir returns -1 if the path is too long */
10548  mg_send_http_error(conn,
10549  414,
10550  "Error: Path too long\nput_dir(%s): %s",
10551  path,
10552  strerror(ERRNO));
10553  return;
10554  }
10555 
10556  if (rc == -2) {
10557  /* put_dir returns -2 if the directory can not be created */
10558  mg_send_http_error(conn,
10559  500,
10560  "Error: Can not create directory\nput_dir(%s): %s",
10561  path,
10562  strerror(ERRNO));
10563  return;
10564  }
10565 
10566  /* A file should be created or overwritten. */
10567  /* Currently CivetWeb does not nead read+write access. */
10568  if (!mg_fopen(conn, path, MG_FOPEN_MODE_WRITE, &file)
10569  || file.access.fp == NULL) {
10570  (void)mg_fclose(&file.access);
10571  mg_send_http_error(conn,
10572  500,
10573  "Error: Can not create file\nfopen(%s): %s",
10574  path,
10575  strerror(ERRNO));
10576  return;
10577  }
10578 
10579  fclose_on_exec(&file.access, conn);
10580  range = mg_get_header(conn, "Content-Range");
10581  r1 = r2 = 0;
10582  if ((range != NULL) && parse_range_header(range, &r1, &r2) > 0) {
10583  conn->status_code = 206; /* Partial content */
10584  fseeko(file.access.fp, r1, SEEK_SET);
10585  }
10586 
10587  if (!forward_body_data(conn, file.access.fp, INVALID_SOCKET, NULL)) {
10588  /* forward_body_data failed.
10589  * The error code has already been sent to the client,
10590  * and conn->status_code is already set. */
10591  (void)mg_fclose(&file.access);
10592  return;
10593  }
10594 
10595  if (mg_fclose(&file.access) != 0) {
10596  /* fclose failed. This might have different reasons, but a likely
10597  * one is "no space on disk", http 507. */
10598  conn->status_code = 507;
10599  }
10600 
10601  gmt_time_string(date, sizeof(date), &curtime);
10602  mg_printf(conn,
10603  "HTTP/1.1 %d %s\r\n",
10604  conn->status_code,
10605  mg_get_response_code_text(NULL, conn->status_code));
10606  send_no_cache_header(conn);
10607  send_additional_header(conn);
10608  mg_printf(conn,
10609  "Date: %s\r\n"
10610  "Content-Length: 0\r\n"
10611  "Connection: %s\r\n\r\n",
10612  date,
10614 }
10615 
10616 
10617 static void
10618 delete_file(struct mg_connection *conn, const char *path)
10619 {
10620  struct de de;
10621  memset(&de.file, 0, sizeof(de.file));
10622  if (!mg_stat(conn, path, &de.file)) {
10623  /* mg_stat returns 0 if the file does not exist */
10624  mg_send_http_error(conn,
10625  404,
10626  "Error: Cannot delete file\nFile %s not found",
10627  path);
10628  return;
10629  }
10630 
10631 #if 0 /* Ignore if a file in memory is inside a folder */
10632  if (de.access.membuf != NULL) {
10633  /* the file is cached in memory */
10635  conn,
10636  405,
10637  "Error: Delete not possible\nDeleting %s is not supported",
10638  path);
10639  return;
10640  }
10641 #endif
10642 
10643  if (de.file.is_directory) {
10644  if (remove_directory(conn, path)) {
10645  /* Delete is successful: Return 204 without content. */
10646  mg_send_http_error(conn, 204, "%s", "");
10647  } else {
10648  /* Delete is not successful: Return 500 (Server error). */
10649  mg_send_http_error(conn, 500, "Error: Could not delete %s", path);
10650  }
10651  return;
10652  }
10653 
10654  /* This is an existing file (not a directory).
10655  * Check if write permission is granted. */
10656  if (access(path, W_OK) != 0) {
10657  /* File is read only */
10659  conn,
10660  403,
10661  "Error: Delete not possible\nDeleting %s is not allowed",
10662  path);
10663  return;
10664  }
10665 
10666  /* Try to delete it. */
10667  if (mg_remove(conn, path) == 0) {
10668  /* Delete was successful: Return 204 without content. */
10669  mg_send_http_error(conn, 204, "%s", "");
10670  } else {
10671  /* Delete not successful (file locked). */
10672  mg_send_http_error(conn,
10673  423,
10674  "Error: Cannot delete file\nremove(%s): %s",
10675  path,
10676  strerror(ERRNO));
10677  }
10678 }
10679 #endif /* !NO_FILES */
10680 
10681 
10682 static void
10683 send_ssi_file(struct mg_connection *, const char *, struct mg_file *, int);
10684 
10685 
10686 static void
10687 do_ssi_include(struct mg_connection *conn,
10688  const char *ssi,
10689  char *tag,
10690  int include_level)
10691 {
10692  char file_name[MG_BUF_LEN], path[512], *p;
10693  struct mg_file file = STRUCT_FILE_INITIALIZER;
10694  size_t len;
10695  int truncated = 0;
10696 
10697  if (conn == NULL) {
10698  return;
10699  }
10700 
10701  /* sscanf() is safe here, since send_ssi_file() also uses buffer
10702  * of size MG_BUF_LEN to get the tag. So strlen(tag) is
10703  * always < MG_BUF_LEN. */
10704  if (sscanf(tag, " virtual=\"%511[^\"]\"", file_name) == 1) {
10705  /* File name is relative to the webserver root */
10706  file_name[511] = 0;
10707  (void)mg_snprintf(conn,
10708  &truncated,
10709  path,
10710  sizeof(path),
10711  "%s/%s",
10712  conn->ctx->config[DOCUMENT_ROOT],
10713  file_name);
10714 
10715  } else if (sscanf(tag, " abspath=\"%511[^\"]\"", file_name) == 1) {
10716  /* File name is relative to the webserver working directory
10717  * or it is absolute system path */
10718  file_name[511] = 0;
10719  (void)
10720  mg_snprintf(conn, &truncated, path, sizeof(path), "%s", file_name);
10721 
10722  } else if ((sscanf(tag, " file=\"%511[^\"]\"", file_name) == 1)
10723  || (sscanf(tag, " \"%511[^\"]\"", file_name) == 1)) {
10724  /* File name is relative to the currect document */
10725  file_name[511] = 0;
10726  (void)mg_snprintf(conn, &truncated, path, sizeof(path), "%s", ssi);
10727 
10728  if (!truncated) {
10729  if ((p = strrchr(path, '/')) != NULL) {
10730  p[1] = '\0';
10731  }
10732  len = strlen(path);
10733  (void)mg_snprintf(conn,
10734  &truncated,
10735  path + len,
10736  sizeof(path) - len,
10737  "%s",
10738  file_name);
10739  }
10740 
10741  } else {
10742  mg_cry(conn, "Bad SSI #include: [%s]", tag);
10743  return;
10744  }
10745 
10746  if (truncated) {
10747  mg_cry(conn, "SSI #include path length overflow: [%s]", tag);
10748  return;
10749  }
10750 
10751  if (!mg_fopen(conn, path, MG_FOPEN_MODE_READ, &file)) {
10752  mg_cry(conn,
10753  "Cannot open SSI #include: [%s]: fopen(%s): %s",
10754  tag,
10755  path,
10756  strerror(ERRNO));
10757  } else {
10758  fclose_on_exec(&file.access, conn);
10759  if (match_prefix(conn->ctx->config[SSI_EXTENSIONS],
10760  strlen(conn->ctx->config[SSI_EXTENSIONS]),
10761  path) > 0) {
10762  send_ssi_file(conn, path, &file, include_level + 1);
10763  } else {
10764  send_file_data(conn, &file, 0, INT64_MAX);
10765  }
10766  (void)mg_fclose(&file.access); /* Ignore errors for readonly files */
10767  }
10768 }
10769 
10770 
10771 #if !defined(NO_POPEN)
10772 static void
10773 do_ssi_exec(struct mg_connection *conn, char *tag)
10774 {
10775  char cmd[1024] = "";
10776  struct mg_file file = STRUCT_FILE_INITIALIZER;
10777 
10778  if (sscanf(tag, " \"%1023[^\"]\"", cmd) != 1) {
10779  mg_cry(conn, "Bad SSI #exec: [%s]", tag);
10780  } else {
10781  cmd[1023] = 0;
10782  if ((file.access.fp = popen(cmd, "r")) == NULL) {
10783  mg_cry(conn, "Cannot SSI #exec: [%s]: %s", cmd, strerror(ERRNO));
10784  } else {
10785  send_file_data(conn, &file, 0, INT64_MAX);
10786  pclose(file.access.fp);
10787  }
10788  }
10789 }
10790 #endif /* !NO_POPEN */
10791 
10792 
10793 static int
10794 mg_fgetc(struct mg_file *filep, int offset)
10795 {
10796  if (filep == NULL) {
10797  return EOF;
10798  }
10799  if ((filep->access.membuf != NULL) && (offset >= 0)
10800  && (((unsigned int)(offset)) < filep->stat.size)) {
10801  return ((const unsigned char *)filep->access.membuf)[offset];
10802  } else if (filep->access.fp != NULL) {
10803  return fgetc(filep->access.fp);
10804  } else {
10805  return EOF;
10806  }
10807 }
10808 
10809 
10810 static void
10811 send_ssi_file(struct mg_connection *conn,
10812  const char *path,
10813  struct mg_file *filep,
10814  int include_level)
10815 {
10816  char buf[MG_BUF_LEN];
10817  int ch, offset, len, in_tag, in_ssi_tag;
10818 
10819  if (include_level > 10) {
10820  mg_cry(conn, "SSI #include level is too deep (%s)", path);
10821  return;
10822  }
10823 
10824  in_tag = in_ssi_tag = len = offset = 0;
10825 
10826  /* Read file, byte by byte, and look for SSI include tags */
10827  while ((ch = mg_fgetc(filep, offset++)) != EOF) {
10828 
10829  if (in_tag) {
10830  /* We are in a tag, either SSI tag or html tag */
10831 
10832  if (ch == '>') {
10833  /* Tag is closing */
10834  buf[len++] = '>';
10835 
10836  if (in_ssi_tag) {
10837  /* Handle SSI tag */
10838  buf[len] = 0;
10839 
10840  if (!memcmp(buf + 5, "include", 7)) {
10841  do_ssi_include(conn, path, buf + 12, include_level + 1);
10842 #if !defined(NO_POPEN)
10843  } else if (!memcmp(buf + 5, "exec", 4)) {
10844  do_ssi_exec(conn, buf + 9);
10845 #endif /* !NO_POPEN */
10846  } else {
10847  mg_cry(conn,
10848  "%s: unknown SSI "
10849  "command: \"%s\"",
10850  path,
10851  buf);
10852  }
10853  len = 0;
10854  in_ssi_tag = in_tag = 0;
10855 
10856  } else {
10857  /* Not an SSI tag */
10858  /* Flush buffer */
10859  (void)mg_write(conn, buf, (size_t)len);
10860  len = 0;
10861  in_tag = 0;
10862  }
10863 
10864  } else {
10865  /* Tag is still open */
10866  buf[len++] = (char)(ch & 0xff);
10867 
10868  if ((len == 5) && !memcmp(buf, "<!--#", 5)) {
10869  /* All SSI tags start with <!--# */
10870  in_ssi_tag = 1;
10871  }
10872 
10873  if ((len + 2) > (int)sizeof(buf)) {
10874  /* Tag to long for buffer */
10875  mg_cry(conn, "%s: tag is too large", path);
10876  return;
10877  }
10878  }
10879 
10880  } else {
10881  /* We are not in a tag yet. */
10882 
10883  if (ch == '<') {
10884  /* Tag is opening */
10885  in_tag = 1;
10886  /* Flush current buffer */
10887  (void)mg_write(conn, buf, (size_t)len);
10888  /* Store the < */
10889  len = 1;
10890  buf[0] = '<';
10891 
10892  } else {
10893  /* No Tag */
10894  /* Add data to buffer */
10895  buf[len++] = (char)(ch & 0xff);
10896  /* Flush if buffer is full */
10897  if (len == (int)sizeof(buf)) {
10898  mg_write(conn, buf, (size_t)len);
10899  len = 0;
10900  }
10901  }
10902  }
10903  }
10904 
10905  /* Send the rest of buffered data */
10906  if (len > 0) {
10907  mg_write(conn, buf, (size_t)len);
10908  }
10909 }
10910 
10911 
10912 static void
10913 handle_ssi_file_request(struct mg_connection *conn,
10914  const char *path,
10915  struct mg_file *filep)
10916 {
10917  char date[64];
10918  time_t curtime = time(NULL);
10919  const char *cors1, *cors2, *cors3;
10920 
10921  if ((conn == NULL) || (path == NULL) || (filep == NULL)) {
10922  return;
10923  }
10924 
10925  if (mg_get_header(conn, "Origin")) {
10926  /* Cross-origin resource sharing (CORS). */
10927  cors1 = "Access-Control-Allow-Origin: ";
10928  cors2 = conn->ctx->config[ACCESS_CONTROL_ALLOW_ORIGIN];
10929  cors3 = "\r\n";
10930  } else {
10931  cors1 = cors2 = cors3 = "";
10932  }
10933 
10934  if (!mg_fopen(conn, path, MG_FOPEN_MODE_READ, filep)) {
10935  /* File exists (precondition for calling this function),
10936  * but can not be opened by the server. */
10937  mg_send_http_error(conn,
10938  500,
10939  "Error: Cannot read file\nfopen(%s): %s",
10940  path,
10941  strerror(ERRNO));
10942  } else {
10943  conn->must_close = 1;
10944  gmt_time_string(date, sizeof(date), &curtime);
10945  fclose_on_exec(&filep->access, conn);
10946  mg_printf(conn, "HTTP/1.1 200 OK\r\n");
10947  send_no_cache_header(conn);
10948  send_additional_header(conn);
10949  mg_printf(conn,
10950  "%s%s%s"
10951  "Date: %s\r\n"
10952  "Content-Type: text/html\r\n"
10953  "Connection: %s\r\n\r\n",
10954  cors1,
10955  cors2,
10956  cors3,
10957  date,
10959  send_ssi_file(conn, path, filep, 0);
10960  (void)mg_fclose(&filep->access); /* Ignore errors for readonly files */
10961  }
10962 }
10963 
10964 
10965 #if !defined(NO_FILES)
10966 static void
10967 send_options(struct mg_connection *conn)
10968 {
10969  char date[64];
10970  time_t curtime = time(NULL);
10971 
10972  if (!conn) {
10973  return;
10974  }
10975 
10976  conn->status_code = 200;
10977  conn->must_close = 1;
10978  gmt_time_string(date, sizeof(date), &curtime);
10979 
10980  /* We do not set a "Cache-Control" header here, but leave the default.
10981  * Since browsers do not send an OPTIONS request, we can not test the
10982  * effect anyway. */
10983  mg_printf(conn,
10984  "HTTP/1.1 200 OK\r\n"
10985  "Date: %s\r\n"
10986  "Connection: %s\r\n"
10987  "Allow: GET, POST, HEAD, CONNECT, PUT, DELETE, OPTIONS, "
10988  "PROPFIND, MKCOL\r\n"
10989  "DAV: 1\r\n",
10990  date,
10992  send_additional_header(conn);
10993  mg_printf(conn, "\r\n");
10994 }
10995 
10996 
10997 /* Writes PROPFIND properties for a collection element */
10998 static void
10999 print_props(struct mg_connection *conn,
11000  const char *uri,
11001  struct mg_file_stat *filep)
11002 {
11003  char mtime[64];
11004 
11005  if ((conn == NULL) || (uri == NULL) || (filep == NULL)) {
11006  return;
11007  }
11008 
11009  gmt_time_string(mtime, sizeof(mtime), &filep->last_modified);
11010  mg_printf(conn,
11011  "<d:response>"
11012  "<d:href>%s</d:href>"
11013  "<d:propstat>"
11014  "<d:prop>"
11015  "<d:resourcetype>%s</d:resourcetype>"
11016  "<d:getcontentlength>%" INT64_FMT "</d:getcontentlength>"
11017  "<d:getlastmodified>%s</d:getlastmodified>"
11018  "</d:prop>"
11019  "<d:status>HTTP/1.1 200 OK</d:status>"
11020  "</d:propstat>"
11021  "</d:response>\n",
11022  uri,
11023  filep->is_directory ? "<d:collection/>" : "",
11024  filep->size,
11025  mtime);
11026 }
11027 
11028 
11029 static int
11030 print_dav_dir_entry(struct de *de, void *data)
11031 {
11032  char href[PATH_MAX];
11033  int truncated;
11034 
11035  struct mg_connection *conn = (struct mg_connection *)data;
11036  if (!de || !conn) {
11037  return -1;
11038  }
11039  mg_snprintf(conn,
11040  &truncated,
11041  href,
11042  sizeof(href),
11043  "%s%s",
11044  conn->request_info.local_uri,
11045  de->file_name);
11046 
11047  if (!truncated) {
11048  size_t href_encoded_size;
11049  char *href_encoded;
11050 
11051  href_encoded_size = PATH_MAX * 3; /* worst case */
11052  href_encoded = (char *)mg_malloc(href_encoded_size);
11053  if (href_encoded == NULL) {
11054  return -1;
11055  }
11056  mg_url_encode(href, href_encoded, href_encoded_size);
11057  print_props(conn, href_encoded, &de->file);
11058  mg_free(href_encoded);
11059  }
11060 
11061  return 0;
11062 }
11063 
11064 
11065 static void
11066 handle_propfind(struct mg_connection *conn,
11067  const char *path,
11068  struct mg_file_stat *filep)
11069 {
11070  const char *depth = mg_get_header(conn, "Depth");
11071  char date[64];
11072  time_t curtime = time(NULL);
11073 
11074  gmt_time_string(date, sizeof(date), &curtime);
11075 
11076  if (!conn || !path || !filep || !conn->ctx) {
11077  return;
11078  }
11079 
11080  conn->must_close = 1;
11081  conn->status_code = 207;
11082  mg_printf(conn,
11083  "HTTP/1.1 207 Multi-Status\r\n"
11084  "Date: %s\r\n",
11085  date);
11087  send_additional_header(conn);
11088  mg_printf(conn,
11089  "Connection: %s\r\n"
11090  "Content-Type: text/xml; charset=utf-8\r\n\r\n",
11092 
11093  mg_printf(conn,
11094  "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
11095  "<d:multistatus xmlns:d='DAV:'>\n");
11096 
11097  /* Print properties for the requested resource itself */
11098  print_props(conn, conn->request_info.local_uri, filep);
11099 
11100  /* If it is a directory, print directory entries too if Depth is not 0
11101  */
11102  if (filep && filep->is_directory
11103  && !mg_strcasecmp(conn->ctx->config[ENABLE_DIRECTORY_LISTING], "yes")
11104  && ((depth == NULL) || (strcmp(depth, "0") != 0))) {
11105  scan_directory(conn, path, conn, &print_dav_dir_entry);
11106  }
11107 
11108  mg_printf(conn, "%s\n", "</d:multistatus>");
11109 }
11110 #endif
11111 
11112 void
11113 mg_lock_connection(struct mg_connection *conn)
11114 {
11115  if (conn) {
11116  (void)pthread_mutex_lock(&conn->mutex);
11117  }
11118 }
11119 
11120 void
11121 mg_unlock_connection(struct mg_connection *conn)
11122 {
11123  if (conn) {
11124  (void)pthread_mutex_unlock(&conn->mutex);
11125  }
11126 }
11127 
11128 void
11129 mg_lock_context(struct mg_context *ctx)
11130 {
11131  if (ctx) {
11132  (void)pthread_mutex_lock(&ctx->nonce_mutex);
11133  }
11134 }
11135 
11136 void
11137 mg_unlock_context(struct mg_context *ctx)
11138 {
11139  if (ctx) {
11140  (void)pthread_mutex_unlock(&ctx->nonce_mutex);
11141  }
11142 }
11143 
11144 #if defined(USE_TIMERS)
11145 #define TIMER_API static
11146 #include "timer.inl"
11147 #endif /* USE_TIMERS */
11148 
11149 #ifdef USE_LUA
11150 #include "mod_lua.inl"
11151 #endif /* USE_LUA */
11152 
11153 #ifdef USE_DUKTAPE
11154 #include "mod_duktape.inl"
11155 #endif /* USE_DUKTAPE */
11156 
11157 #if defined(USE_WEBSOCKET)
11158 
11159 #if !defined(NO_SSL_DL)
11160 #define SHA_API static
11161 #include "sha1.inl"
11162 #endif
11163 
11164 static int
11165 send_websocket_handshake(struct mg_connection *conn, const char *websock_key)
11166 {
11167  static const char *magic = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
11168  char buf[100], sha[20], b64_sha[sizeof(sha) * 2];
11169  SHA_CTX sha_ctx;
11170  int truncated;
11171 
11172  /* Calculate Sec-WebSocket-Accept reply from Sec-WebSocket-Key. */
11173  mg_snprintf(conn, &truncated, buf, sizeof(buf), "%s%s", websock_key, magic);
11174  if (truncated) {
11175  conn->must_close = 1;
11176  return 0;
11177  }
11178 
11179  SHA1_Init(&sha_ctx);
11180  SHA1_Update(&sha_ctx, (unsigned char *)buf, (uint32_t)strlen(buf));
11181  SHA1_Final((unsigned char *)sha, &sha_ctx);
11182  base64_encode((unsigned char *)sha, sizeof(sha), b64_sha);
11183  mg_printf(conn,
11184  "HTTP/1.1 101 Switching Protocols\r\n"
11185  "Upgrade: websocket\r\n"
11186  "Connection: Upgrade\r\n"
11187  "Sec-WebSocket-Accept: %s\r\n",
11188  b64_sha);
11189  if (conn->request_info.acceptedWebSocketSubprotocol) {
11190  mg_printf(conn,
11191  "Sec-WebSocket-Protocol: %s\r\n\r\n",
11192  conn->request_info.acceptedWebSocketSubprotocol);
11193  } else {
11194  mg_printf(conn, "%s", "\r\n");
11195  }
11196 
11197  return 1;
11198 }
11199 
11200 
11201 static void
11202 read_websocket(struct mg_connection *conn,
11203  mg_websocket_data_handler ws_data_handler,
11204  void *callback_data)
11205 {
11206  /* Pointer to the beginning of the portion of the incoming websocket
11207  * message queue.
11208  * The original websocket upgrade request is never removed, so the queue
11209  * begins after it. */
11210  unsigned char *buf = (unsigned char *)conn->buf + conn->request_len;
11211  int n, error, exit_by_callback;
11212 
11213  /* body_len is the length of the entire queue in bytes
11214  * len is the length of the current message
11215  * data_len is the length of the current message's data payload
11216  * header_len is the length of the current message's header */
11217  size_t i, len, mask_len = 0, header_len, body_len;
11218  uint64_t data_len = 0;
11219 
11220  /* "The masking key is a 32-bit value chosen at random by the client."
11221  * http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-17#section-5
11222  */
11223  unsigned char mask[4];
11224 
11225  /* data points to the place where the message is stored when passed to
11226  * the
11227  * websocket_data callback. This is either mem on the stack, or a
11228  * dynamically allocated buffer if it is too large. */
11229  unsigned char mem[4096];
11230  unsigned char mop; /* mask flag and opcode */
11231  double timeout = -1.0;
11232 
11233  if (conn->ctx->config[WEBSOCKET_TIMEOUT]) {
11234  timeout = atoi(conn->ctx->config[WEBSOCKET_TIMEOUT]) / 1000.0;
11235  }
11236  if ((timeout <= 0.0) && (conn->ctx->config[REQUEST_TIMEOUT])) {
11237  timeout = atoi(conn->ctx->config[REQUEST_TIMEOUT]) / 1000.0;
11238  }
11239 
11240  conn->in_websocket_handling = 1;
11241  mg_set_thread_name("wsock");
11242 
11243  /* Loop continuously, reading messages from the socket, invoking the
11244  * callback, and waiting repeatedly until an error occurs. */
11245  while (!conn->ctx->stop_flag && !conn->must_close) {
11246  header_len = 0;
11247  assert(conn->data_len >= conn->request_len);
11248  if ((body_len = (size_t)(conn->data_len - conn->request_len)) >= 2) {
11249  len = buf[1] & 127;
11250  mask_len = (buf[1] & 128) ? 4 : 0;
11251  if ((len < 126) && (body_len >= mask_len)) {
11252  /* inline 7-bit length field */
11253  data_len = len;
11254  header_len = 2 + mask_len;
11255  } else if ((len == 126) && (body_len >= (4 + mask_len))) {
11256  /* 16-bit length field */
11257  header_len = 4 + mask_len;
11258  data_len = ((((size_t)buf[2]) << 8) + buf[3]);
11259  } else if (body_len >= (10 + mask_len)) {
11260  /* 64-bit length field */
11261  uint32_t l1, l2;
11262  memcpy(&l1, &buf[2], 4); /* Use memcpy for alignment */
11263  memcpy(&l2, &buf[6], 4);
11264  header_len = 10 + mask_len;
11265  data_len = (((uint64_t)ntohl(l1)) << 32) + ntohl(l2);
11266 
11267  if (data_len > (uint64_t)0x7FFF0000ul) {
11268  /* no can do */
11269  mg_cry(conn, "websocket out of memory; closing connection");
11270  break;
11271  }
11272  }
11273  }
11274 
11275  if ((header_len > 0) && (body_len >= header_len)) {
11276  /* Allocate space to hold websocket payload */
11277  unsigned char *data = mem;
11278 
11279  if ((size_t)data_len > (size_t)sizeof(mem)) {
11280  data =
11281  (unsigned char *)mg_malloc_ctx((size_t)data_len, conn->ctx);
11282  if (data == NULL) {
11283  /* Allocation failed, exit the loop and then close the
11284  * connection */
11285  mg_cry(conn, "websocket out of memory; closing connection");
11286  break;
11287  }
11288  }
11289 
11290  /* Copy the mask before we shift the queue and destroy it */
11291  if (mask_len > 0) {
11292  memcpy(mask, buf + header_len - mask_len, sizeof(mask));
11293  } else {
11294  memset(mask, 0, sizeof(mask));
11295  }
11296 
11297  /* Read frame payload from the first message in the queue into
11298  * data and advance the queue by moving the memory in place. */
11299  assert(body_len >= header_len);
11300  if (data_len + (uint64_t)header_len > (uint64_t)body_len) {
11301  mop = buf[0]; /* current mask and opcode */
11302  /* Overflow case */
11303  len = body_len - header_len;
11304  memcpy(data, buf + header_len, len);
11305  error = 0;
11306  while ((uint64_t)len < data_len) {
11307  n = pull_inner(NULL,
11308  conn,
11309  (char *)(data + len),
11310  (int)(data_len - len),
11311  timeout);
11312  if (n <= -2) {
11313  error = 1;
11314  break;
11315  } else if (n > 0) {
11316  len += (size_t)n;
11317  } else {
11318  /* Timeout: should retry */
11319  /* TODO: retry condition */
11320  }
11321  }
11322  if (error) {
11323  mg_cry(conn, "Websocket pull failed; closing connection");
11324  if (data != mem) {
11325  mg_free(data);
11326  }
11327  break;
11328  }
11329 
11330  conn->data_len = conn->request_len;
11331 
11332  } else {
11333 
11334  mop = buf[0]; /* current mask and opcode, overwritten by
11335  * memmove() */
11336 
11337  /* Length of the message being read at the front of the
11338  * queue. Cast to 31 bit is OK, since we limited
11339  * data_len before. */
11340  len = (size_t)data_len + header_len;
11341 
11342  /* Copy the data payload into the data pointer for the
11343  * callback. Cast to 31 bit is OK, since we
11344  * limited data_len */
11345  memcpy(data, buf + header_len, (size_t)data_len);
11346 
11347  /* Move the queue forward len bytes */
11348  memmove(buf, buf + len, body_len - len);
11349 
11350  /* Mark the queue as advanced */
11351  conn->data_len -= (int)len;
11352  }
11353 
11354  /* Apply mask if necessary */
11355  if (mask_len > 0) {
11356  for (i = 0; i < (size_t)data_len; i++) {
11357  data[i] ^= mask[i & 3];
11358  }
11359  }
11360 
11361  /* Exit the loop if callback signals to exit (server side),
11362  * or "connection close" opcode received (client side). */
11363  exit_by_callback = 0;
11364  if ((ws_data_handler != NULL)
11365  && !ws_data_handler(conn,
11366  mop,
11367  (char *)data,
11368  (size_t)data_len,
11369  callback_data)) {
11370  exit_by_callback = 1;
11371  }
11372 
11373  if (data != mem) {
11374  mg_free(data);
11375  }
11376 
11377  if (exit_by_callback
11378  || ((mop & 0xf) == WEBSOCKET_OPCODE_CONNECTION_CLOSE)) {
11379  /* Opcode == 8, connection close */
11380  break;
11381  }
11382 
11383  /* Not breaking the loop, process next websocket frame. */
11384  } else {
11385  /* Read from the socket into the next available location in the
11386  * message queue. */
11387  n = pull_inner(NULL,
11388  conn,
11389  conn->buf + conn->data_len,
11390  conn->buf_size - conn->data_len,
11391  timeout);
11392  if (n <= -2) {
11393  /* Error, no bytes read */
11394  break;
11395  }
11396  if (n > 0) {
11397  conn->data_len += n;
11398  } else {
11399  /* Timeout: should retry */
11400  /* TODO: get timeout def */
11401  }
11402  }
11403  }
11404 
11405  mg_set_thread_name("worker");
11406  conn->in_websocket_handling = 0;
11407 }
11408 
11409 
11410 static int
11411 mg_websocket_write_exec(struct mg_connection *conn,
11412  int opcode,
11413  const char *data,
11414  size_t dataLen,
11415  uint32_t masking_key)
11416 {
11417  unsigned char header[14];
11418  size_t headerLen = 1;
11419 
11420  int retval = -1;
11421 
11422 #if defined(__GNUC__) || defined(__MINGW32__)
11423 /* Disable spurious conversion warning for GCC */
11424 #pragma GCC diagnostic push
11425 #pragma GCC diagnostic ignored "-Wconversion"
11426 #endif
11427 
11428  header[0] = 0x80u | (unsigned char)((unsigned)opcode & 0xf);
11429 
11430 #if defined(__GNUC__) || defined(__MINGW32__)
11431 #pragma GCC diagnostic pop
11432 #endif
11433 
11434  /* Frame format: http://tools.ietf.org/html/rfc6455#section-5.2 */
11435  if (dataLen < 126) {
11436  /* inline 7-bit length field */
11437  header[1] = (unsigned char)dataLen;
11438  headerLen = 2;
11439  } else if (dataLen <= 0xFFFF) {
11440  /* 16-bit length field */
11441  uint16_t len = htons((uint16_t)dataLen);
11442  header[1] = 126;
11443  memcpy(header + 2, &len, 2);
11444  headerLen = 4;
11445  } else {
11446  /* 64-bit length field */
11447  uint32_t len1 = htonl((uint32_t)((uint64_t)dataLen >> 32));
11448  uint32_t len2 = htonl((uint32_t)(dataLen & 0xFFFFFFFFu));
11449  header[1] = 127;
11450  memcpy(header + 2, &len1, 4);
11451  memcpy(header + 6, &len2, 4);
11452  headerLen = 10;
11453  }
11454 
11455  if (masking_key) {
11456  /* add mask */
11457  header[1] |= 0x80;
11458  memcpy(header + headerLen, &masking_key, 4);
11459  headerLen += 4;
11460  }
11461 
11462 
11463  /* Note that POSIX/Winsock's send() is threadsafe
11464  * http://stackoverflow.com/questions/1981372/are-parallel-calls-to-send-recv-on-the-same-socket-valid
11465  * but mongoose's mg_printf/mg_write is not (because of the loop in
11466  * push(), although that is only a problem if the packet is large or
11467  * outgoing buffer is full). */
11468 
11469  /* TODO: Check if this lock should be moved to user land.
11470  * Currently the server sets this lock for websockets, but
11471  * not for any other connection. It must be set for every
11472  * conn read/written by more than one thread, no matter if
11473  * it is a websocket or regular connection. */
11474  (void)mg_lock_connection(conn);
11475 
11476  retval = mg_write(conn, header, headerLen);
11477  if (dataLen > 0) {
11478  retval = mg_write(conn, data, dataLen);
11479  }
11480 
11481  /* TODO: Remove this unlock as well, when lock is moved. */
11482  mg_unlock_connection(conn);
11483 
11484  return retval;
11485 }
11486 
11487 int
11488 mg_websocket_write(struct mg_connection *conn,
11489  int opcode,
11490  const char *data,
11491  size_t dataLen)
11492 {
11493  return mg_websocket_write_exec(conn, opcode, data, dataLen, 0);
11494 }
11495 
11496 
11497 static void
11498 mask_data(const char *in, size_t in_len, uint32_t masking_key, char *out)
11499 {
11500  size_t i = 0;
11501 
11502  i = 0;
11503  if ((in_len > 3) && ((ptrdiff_t)in % 4) == 0) {
11504  /* Convert in 32 bit words, if data is 4 byte aligned */
11505  while (i < (in_len - 3)) {
11506  *(uint32_t *)(void *)(out + i) =
11507  *(uint32_t *)(void *)(in + i) ^ masking_key;
11508  i += 4;
11509  }
11510  }
11511  if (i != in_len) {
11512  /* convert 1-3 remaining bytes if ((dataLen % 4) != 0)*/
11513  while (i < in_len) {
11514  *(uint8_t *)(void *)(out + i) =
11515  *(uint8_t *)(void *)(in + i)
11516  ^ *(((uint8_t *)&masking_key) + (i % 4));
11517  i++;
11518  }
11519  }
11520 }
11521 
11522 
11523 int
11524 mg_websocket_client_write(struct mg_connection *conn,
11525  int opcode,
11526  const char *data,
11527  size_t dataLen)
11528 {
11529  int retval = -1;
11530  char *masked_data =
11531  (char *)mg_malloc_ctx(((dataLen + 7) / 4) * 4, conn->ctx);
11532  uint32_t masking_key = (uint32_t)get_random();
11533 
11534  if (masked_data == NULL) {
11535  /* Return -1 in an error case */
11536  mg_cry(conn,
11537  "Cannot allocate buffer for masked websocket response: "
11538  "Out of memory");
11539  return -1;
11540  }
11541 
11542  mask_data(data, dataLen, masking_key, masked_data);
11543 
11544  retval = mg_websocket_write_exec(
11545  conn, opcode, masked_data, dataLen, masking_key);
11546  mg_free(masked_data);
11547 
11548  return retval;
11549 }
11550 
11551 
11552 static void
11553 handle_websocket_request(struct mg_connection *conn,
11554  const char *path,
11555  int is_callback_resource,
11556  struct mg_websocket_subprotocols *subprotocols,
11557  mg_websocket_connect_handler ws_connect_handler,
11558  mg_websocket_ready_handler ws_ready_handler,
11559  mg_websocket_data_handler ws_data_handler,
11560  mg_websocket_close_handler ws_close_handler,
11561  void *cbData)
11562 {
11563  const char *websock_key = mg_get_header(conn, "Sec-WebSocket-Key");
11564  const char *version = mg_get_header(conn, "Sec-WebSocket-Version");
11565  int lua_websock = 0;
11566 
11567 #if !defined(USE_LUA)
11568  (void)path;
11569 #endif
11570 
11571  /* Step 1: Check websocket protocol version. */
11572  /* Step 1.1: Check Sec-WebSocket-Key. */
11573  if (!websock_key) {
11574  /* The RFC standard version (https://tools.ietf.org/html/rfc6455)
11575  * requires a Sec-WebSocket-Key header.
11576  */
11577  /* It could be the hixie draft version
11578  * (http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol-76).
11579  */
11580  const char *key1 = mg_get_header(conn, "Sec-WebSocket-Key1");
11581  const char *key2 = mg_get_header(conn, "Sec-WebSocket-Key2");
11582  char key3[8];
11583 
11584  if ((key1 != NULL) && (key2 != NULL)) {
11585  /* This version uses 8 byte body data in a GET request */
11586  conn->content_len = 8;
11587  if (8 == mg_read(conn, key3, 8)) {
11588  /* This is the hixie version */
11589  mg_send_http_error(conn,
11590  426,
11591  "%s",
11592  "Protocol upgrade to RFC 6455 required");
11593  return;
11594  }
11595  }
11596  /* This is an unknown version */
11597  mg_send_http_error(conn, 400, "%s", "Malformed websocket request");
11598  return;
11599  }
11600 
11601  /* Step 1.2: Check websocket protocol version. */
11602  /* The RFC version (https://tools.ietf.org/html/rfc6455) is 13. */
11603  if ((version == NULL) || (strcmp(version, "13") != 0)) {
11604  /* Reject wrong versions */
11605  mg_send_http_error(conn, 426, "%s", "Protocol upgrade required");
11606  return;
11607  }
11608 
11609  /* Step 1.3: Could check for "Host", but we do not really nead this
11610  * value for anything, so just ignore it. */
11611 
11612  /* Step 2: If a callback is responsible, call it. */
11613  if (is_callback_resource) {
11614  /* Step 2.1 check and select subprotocol */
11615  const char *protocols[64]; // max 64 headers
11616  int nbSubprotocolHeader = get_req_headers(&conn->request_info,
11617  "Sec-WebSocket-Protocol",
11618  protocols,
11619  64);
11620  if ((nbSubprotocolHeader > 0) && subprotocols) {
11621  int cnt = 0;
11622  int idx;
11623  unsigned long len;
11624  const char *sep, *curSubProtocol,
11625  *acceptedWebSocketSubprotocol = NULL;
11626 
11627 
11628  /* look for matching subprotocol */
11629  do {
11630  const char *protocol = protocols[cnt];
11631 
11632  do {
11633  sep = strchr(protocol, ',');
11634  curSubProtocol = protocol;
11635  len = sep ? (unsigned long)(sep - protocol)
11636  : (unsigned long)strlen(protocol);
11637  while (sep && isspace(*++sep))
11638  ; // ignore leading whitespaces
11639  protocol = sep;
11640 
11641 
11642  for (idx = 0; idx < subprotocols->nb_subprotocols; idx++) {
11643  if ((strlen(subprotocols->subprotocols[idx]) == len)
11644  && (strncmp(curSubProtocol,
11645  subprotocols->subprotocols[idx],
11646  len) == 0)) {
11647  acceptedWebSocketSubprotocol =
11648  subprotocols->subprotocols[idx];
11649  break;
11650  }
11651  }
11652  } while (sep && !acceptedWebSocketSubprotocol);
11653  } while (++cnt < nbSubprotocolHeader
11654  && !acceptedWebSocketSubprotocol);
11655 
11656  conn->request_info.acceptedWebSocketSubprotocol =
11657  acceptedWebSocketSubprotocol;
11658  } else if (nbSubprotocolHeader > 0) {
11659  /* keep legacy behavior */
11660  const char *protocol = protocols[0];
11661 
11662  /* The protocol is a comma separated list of names. */
11663  /* The server must only return one value from this list. */
11664  /* First check if it is a list or just a single value. */
11665  const char *sep = strrchr(protocol, ',');
11666  if (sep == NULL) {
11667  /* Just a single protocol -> accept it. */
11668  conn->request_info.acceptedWebSocketSubprotocol = protocol;
11669  } else {
11670  /* Multiple protocols -> accept the last one. */
11671  /* This is just a quick fix if the client offers multiple
11672  * protocols. The handler should have a list of accepted
11673  * protocols on his own
11674  * and use it to select one protocol among those the client
11675  * has
11676  * offered.
11677  */
11678  while (isspace(*++sep)) {
11679  ; /* ignore leading whitespaces */
11680  }
11681  conn->request_info.acceptedWebSocketSubprotocol = sep;
11682  }
11683  }
11684 
11685  if ((ws_connect_handler != NULL)
11686  && (ws_connect_handler(conn, cbData) != 0)) {
11687  /* C callback has returned non-zero, do not proceed with
11688  * handshake.
11689  */
11690  /* Note that C callbacks are no longer called when Lua is
11691  * responsible, so C can no longer filter callbacks for Lua. */
11692  return;
11693  }
11694  }
11695 #if defined(USE_LUA)
11696  /* Step 3: No callback. Check if Lua is responsible. */
11697  else {
11698  /* Step 3.1: Check if Lua is responsible. */
11699  if (conn->ctx->config[LUA_WEBSOCKET_EXTENSIONS]) {
11700  lua_websock =
11701  match_prefix(conn->ctx->config[LUA_WEBSOCKET_EXTENSIONS],
11702  strlen(
11703  conn->ctx->config[LUA_WEBSOCKET_EXTENSIONS]),
11704  path);
11705  }
11706 
11707  if (lua_websock) {
11708  /* Step 3.2: Lua is responsible: call it. */
11709  conn->lua_websocket_state = lua_websocket_new(path, conn);
11710  if (!conn->lua_websocket_state) {
11711  /* Lua rejected the new client */
11712  return;
11713  }
11714  }
11715  }
11716 #endif
11717 
11718  /* Step 4: Check if there is a responsible websocket handler. */
11719  if (!is_callback_resource && !lua_websock) {
11720  /* There is no callback, and Lua is not responsible either. */
11721  /* Reply with a 404 Not Found. We are still at a standard
11722  * HTTP request here, before the websocket handshake, so
11723  * we can still send standard HTTP error replies. */
11724  mg_send_http_error(conn, 404, "%s", "Not found");
11725  return;
11726  }
11727 
11728  /* Step 5: The websocket connection has been accepted */
11729  if (!send_websocket_handshake(conn, websock_key)) {
11730  mg_send_http_error(conn, 500, "%s", "Websocket handshake failed");
11731  return;
11732  }
11733 
11734  /* Step 6: Call the ready handler */
11735  if (is_callback_resource) {
11736  if (ws_ready_handler != NULL) {
11737  ws_ready_handler(conn, cbData);
11738  }
11739 #if defined(USE_LUA)
11740  } else if (lua_websock) {
11741  if (!lua_websocket_ready(conn, conn->lua_websocket_state)) {
11742  /* the ready handler returned false */
11743  return;
11744  }
11745 #endif
11746  }
11747 
11748  /* Step 7: Enter the read loop */
11749  if (is_callback_resource) {
11750  read_websocket(conn, ws_data_handler, cbData);
11751 #if defined(USE_LUA)
11752  } else if (lua_websock) {
11753  read_websocket(conn, lua_websocket_data, conn->lua_websocket_state);
11754 #endif
11755  }
11756 
11757  /* Step 8: Call the close handler */
11758  if (ws_close_handler) {
11759  ws_close_handler(conn, cbData);
11760  }
11761 }
11762 
11763 
11764 static int
11765 is_websocket_protocol(const struct mg_connection *conn)
11766 {
11767  const char *upgrade, *connection;
11768 
11769  /* A websocket protocoll has the following HTTP headers:
11770  *
11771  * Connection: Upgrade
11772  * Upgrade: Websocket
11773  */
11774 
11775  upgrade = mg_get_header(conn, "Upgrade");
11776  if (upgrade == NULL) {
11777  return 0; /* fail early, don't waste time checking other header
11778  * fields
11779  */
11780  }
11781  if (!mg_strcasestr(upgrade, "websocket")) {
11782  return 0;
11783  }
11784 
11785  connection = mg_get_header(conn, "Connection");
11786  if (connection == NULL) {
11787  return 0;
11788  }
11789  if (!mg_strcasestr(connection, "upgrade")) {
11790  return 0;
11791  }
11792 
11793  /* The headers "Host", "Sec-WebSocket-Key", "Sec-WebSocket-Protocol" and
11794  * "Sec-WebSocket-Version" are also required.
11795  * Don't check them here, since even an unsupported websocket protocol
11796  * request still IS a websocket request (in contrast to a standard HTTP
11797  * request). It will fail later in handle_websocket_request.
11798  */
11799 
11800  return 1;
11801 }
11802 #endif /* !USE_WEBSOCKET */
11803 
11804 
11805 static int
11806 isbyte(int n)
11807 {
11808  return (n >= 0) && (n <= 255);
11809 }
11810 
11811 
11812 static int
11813 parse_net(const char *spec, uint32_t *net, uint32_t *mask)
11814 {
11815  int n, a, b, c, d, slash = 32, len = 0;
11816 
11817  if (((sscanf(spec, "%d.%d.%d.%d/%d%n", &a, &b, &c, &d, &slash, &n) == 5)
11818  || (sscanf(spec, "%d.%d.%d.%d%n", &a, &b, &c, &d, &n) == 4))
11819  && isbyte(a) && isbyte(b) && isbyte(c) && isbyte(d) && (slash >= 0)
11820  && (slash < 33)) {
11821  len = n;
11822  *net = ((uint32_t)a << 24) | ((uint32_t)b << 16) | ((uint32_t)c << 8)
11823  | (uint32_t)d;
11824  *mask = slash ? (0xffffffffU << (32 - slash)) : 0;
11825  }
11826 
11827  return len;
11828 }
11829 
11830 
11831 static int
11832 set_throttle(const char *spec, uint32_t remote_ip, const char *uri)
11833 {
11834  int throttle = 0;
11835  struct vec vec, val;
11836  uint32_t net, mask;
11837  char mult;
11838  double v;
11839 
11840  while ((spec = next_option(spec, &vec, &val)) != NULL) {
11841  mult = ',';
11842  if ((val.ptr == NULL) || (sscanf(val.ptr, "%lf%c", &v, &mult) < 1)
11843  || (v < 0) || ((lowercase(&mult) != 'k')
11844  && (lowercase(&mult) != 'm') && (mult != ','))) {
11845  continue;
11846  }
11847  v *= (lowercase(&mult) == 'k')
11848  ? 1024
11849  : ((lowercase(&mult) == 'm') ? 1048576 : 1);
11850  if (vec.len == 1 && vec.ptr[0] == '*') {
11851  throttle = (int)v;
11852  } else if (parse_net(vec.ptr, &net, &mask) > 0) {
11853  if ((remote_ip & mask) == net) {
11854  throttle = (int)v;
11855  }
11856  } else if (match_prefix(vec.ptr, vec.len, uri) > 0) {
11857  throttle = (int)v;
11858  }
11859  }
11860 
11861  return throttle;
11862 }
11863 
11864 
11865 static uint32_t
11866 get_remote_ip(const struct mg_connection *conn)
11867 {
11868  if (!conn) {
11869  return 0;
11870  }
11871  return ntohl(*(const uint32_t *)&conn->client.rsa.sin.sin_addr);
11872 }
11873 
11874 
11875 /* The mg_upload function is superseeded by mg_handle_form_request. */
11876 #include "handle_form.inl"
11877 
11878 
11879 #if defined(MG_LEGACY_INTERFACE)
11880 /* Implement the deprecated mg_upload function by calling the new
11881  * mg_handle_form_request function. While mg_upload could only handle
11882  * HTML forms sent as POST request in multipart/form-data format
11883  * containing only file input elements, mg_handle_form_request can
11884  * handle all form input elements and all standard request methods. */
11885 struct mg_upload_user_data {
11886  struct mg_connection *conn;
11887  const char *destination_dir;
11888  int num_uploaded_files;
11889 };
11890 
11891 
11892 /* Helper function for deprecated mg_upload. */
11893 static int
11894 mg_upload_field_found(const char *key,
11895  const char *filename,
11896  char *path,
11897  size_t pathlen,
11898  void *user_data)
11899 {
11900  int truncated = 0;
11901  struct mg_upload_user_data *fud = (struct mg_upload_user_data *)user_data;
11902  (void)key;
11903 
11904  if (!filename) {
11905  mg_cry(fud->conn, "%s: No filename set", __func__);
11906  return FORM_FIELD_STORAGE_ABORT;
11907  }
11908  mg_snprintf(fud->conn,
11909  &truncated,
11910  path,
11911  pathlen - 1,
11912  "%s/%s",
11913  fud->destination_dir,
11914  filename);
11915  if (!truncated) {
11916  mg_cry(fud->conn, "%s: File path too long", __func__);
11917  return FORM_FIELD_STORAGE_ABORT;
11918  }
11919  return FORM_FIELD_STORAGE_STORE;
11920 }
11921 
11922 
11923 /* Helper function for deprecated mg_upload. */
11924 static int
11925 mg_upload_field_get(const char *key,
11926  const char *value,
11927  size_t value_size,
11928  void *user_data)
11929 {
11930  /* Function should never be called */
11931  (void)key;
11932  (void)value;
11933  (void)value_size;
11934  (void)user_data;
11935 
11936  return 0;
11937 }
11938 
11939 
11940 /* Helper function for deprecated mg_upload. */
11941 static int
11942 mg_upload_field_stored(const char *path, long long file_size, void *user_data)
11943 {
11944  struct mg_upload_user_data *fud = (struct mg_upload_user_data *)user_data;
11945  (void)file_size;
11946 
11947  fud->num_uploaded_files++;
11948  fud->conn->ctx->callbacks.upload(fud->conn, path);
11949 
11950  return 0;
11951 }
11952 
11953 
11954 /* Deprecated function mg_upload - use mg_handle_form_request instead. */
11955 int
11956 mg_upload(struct mg_connection *conn, const char *destination_dir)
11957 {
11958  struct mg_upload_user_data fud = {conn, destination_dir, 0};
11959  struct mg_form_data_handler fdh = {mg_upload_field_found,
11960  mg_upload_field_get,
11961  mg_upload_field_stored,
11962  0};
11963  int ret;
11964 
11965  fdh.user_data = (void *)&fud;
11966  ret = mg_handle_form_request(conn, &fdh);
11967 
11968  if (ret < 0) {
11969  mg_cry(conn, "%s: Error while parsing the request", __func__);
11970  }
11971 
11972  return fud.num_uploaded_files;
11973 }
11974 #endif
11975 
11976 
11977 static int
11978 get_first_ssl_listener_index(const struct mg_context *ctx)
11979 {
11980  unsigned int i;
11981  int idx = -1;
11982  if (ctx) {
11983  for (i = 0; ((idx == -1) && (i < ctx->num_listening_sockets)); i++) {
11984  idx = ctx->listening_sockets[i].is_ssl ? ((int)(i)) : -1;
11985  }
11986  }
11987  return idx;
11988 }
11989 
11990 
11991 static void
11992 redirect_to_https_port(struct mg_connection *conn, int ssl_index)
11993 {
11994  char host[1025];
11995  const char *host_header;
11996  size_t hostlen;
11997 
11998  host_header = mg_get_header(conn, "Host");
11999  hostlen = sizeof(host);
12000  if (host_header != NULL) {
12001  char *pos;
12002 
12003  mg_strlcpy(host, host_header, hostlen);
12004  host[hostlen - 1] = '\0';
12005  pos = strchr(host, ':');
12006  if (pos != NULL) {
12007  *pos = '\0';
12008  }
12009  } else {
12010  /* Cannot get host from the Host: header.
12011  * Fallback to our IP address. */
12012  if (conn) {
12013  sockaddr_to_string(host, hostlen, &conn->client.lsa);
12014  }
12015  }
12016 
12017  /* Send host, port, uri and (if it exists) ?query_string */
12018  if (conn) {
12019  mg_printf(conn,
12020  "HTTP/1.1 302 Found\r\nLocation: https://%s:%d%s%s%s\r\n\r\n",
12021  host,
12022 #if defined(USE_IPV6)
12023  (conn->ctx->listening_sockets[ssl_index].lsa.sa.sa_family
12024  == AF_INET6)
12025  ? (int)ntohs(conn->ctx->listening_sockets[ssl_index]
12026  .lsa.sin6.sin6_port)
12027  :
12028 #endif
12029  (int)ntohs(conn->ctx->listening_sockets[ssl_index]
12030  .lsa.sin.sin_port),
12031  conn->request_info.local_uri,
12032  (conn->request_info.query_string == NULL) ? "" : "?",
12033  (conn->request_info.query_string == NULL)
12034  ? ""
12035  : conn->request_info.query_string);
12036  }
12037 }
12038 
12039 
12040 static void
12041 mg_set_handler_type(struct mg_context *ctx,
12042  const char *uri,
12043  int handler_type,
12044  int is_delete_request,
12045  mg_request_handler handler,
12046  struct mg_websocket_subprotocols *subprotocols,
12047  mg_websocket_connect_handler connect_handler,
12048  mg_websocket_ready_handler ready_handler,
12049  mg_websocket_data_handler data_handler,
12050  mg_websocket_close_handler close_handler,
12051  mg_authorization_handler auth_handler,
12052  void *cbdata)
12053 {
12054  struct mg_handler_info *tmp_rh, **lastref;
12055  size_t urilen = strlen(uri);
12056 
12057  if (handler_type == WEBSOCKET_HANDLER) {
12058  /* assert(handler == NULL); */
12059  /* assert(is_delete_request || connect_handler!=NULL ||
12060  * ready_handler!=NULL || data_handler!=NULL ||
12061  * close_handler!=NULL);
12062  */
12063  /* assert(auth_handler == NULL); */
12064  if (handler != NULL) {
12065  return;
12066  }
12067  if (!is_delete_request && (connect_handler == NULL)
12068  && (ready_handler == NULL) && (data_handler == NULL)
12069  && (close_handler == NULL)) {
12070  return;
12071  }
12072  if (auth_handler != NULL) {
12073  return;
12074  }
12075  } else if (handler_type == REQUEST_HANDLER) {
12076  /* assert(connect_handler==NULL && ready_handler==NULL &&
12077  * data_handler==NULL && close_handler==NULL); */
12078  /* assert(is_delete_request || (handler!=NULL));
12079  */
12080  /* assert(auth_handler == NULL); */
12081  if ((connect_handler != NULL) || (ready_handler != NULL)
12082  || (data_handler != NULL) || (close_handler != NULL)) {
12083  return;
12084  }
12085  if (!is_delete_request && (handler == NULL)) {
12086  return;
12087  }
12088  if (auth_handler != NULL) {
12089  return;
12090  }
12091  } else { /* AUTH_HANDLER */
12092  /* assert(handler == NULL); */
12093  /* assert(connect_handler==NULL && ready_handler==NULL &&
12094  * data_handler==NULL && close_handler==NULL); */
12095  /* assert(auth_handler != NULL); */
12096  if (handler != NULL) {
12097  return;
12098  }
12099  if ((connect_handler != NULL) || (ready_handler != NULL)
12100  || (data_handler != NULL) || (close_handler != NULL)) {
12101  return;
12102  }
12103  if (!is_delete_request && (auth_handler == NULL)) {
12104  return;
12105  }
12106  }
12107 
12108  if (!ctx) {
12109  return;
12110  }
12111 
12112  mg_lock_context(ctx);
12113 
12114  /* first try to find an existing handler */
12115  lastref = &(ctx->handlers);
12116  for (tmp_rh = ctx->handlers; tmp_rh != NULL; tmp_rh = tmp_rh->next) {
12117  if (tmp_rh->handler_type == handler_type) {
12118  if ((urilen == tmp_rh->uri_len) && !strcmp(tmp_rh->uri, uri)) {
12119  if (!is_delete_request) {
12120  /* update existing handler */
12121  if (handler_type == REQUEST_HANDLER) {
12122  tmp_rh->handler = handler;
12123  } else if (handler_type == WEBSOCKET_HANDLER) {
12124  tmp_rh->subprotocols = subprotocols;
12125  tmp_rh->connect_handler = connect_handler;
12126  tmp_rh->ready_handler = ready_handler;
12127  tmp_rh->data_handler = data_handler;
12128  tmp_rh->close_handler = close_handler;
12129  } else { /* AUTH_HANDLER */
12130  tmp_rh->auth_handler = auth_handler;
12131  }
12132  tmp_rh->cbdata = cbdata;
12133  } else {
12134  /* remove existing handler */
12135  *lastref = tmp_rh->next;
12136  mg_free(tmp_rh->uri);
12137  mg_free(tmp_rh);
12138  }
12139  mg_unlock_context(ctx);
12140  return;
12141  }
12142  }
12143  lastref = &(tmp_rh->next);
12144  }
12145 
12146  if (is_delete_request) {
12147  /* no handler to set, this was a remove request to a non-existing
12148  * handler */
12149  mg_unlock_context(ctx);
12150  return;
12151  }
12152 
12153  tmp_rh =
12154  (struct mg_handler_info *)mg_calloc_ctx(sizeof(struct mg_handler_info),
12155  1,
12156  ctx);
12157  if (tmp_rh == NULL) {
12158  mg_unlock_context(ctx);
12159  mg_cry(fc(ctx), "%s", "Cannot create new request handler struct, OOM");
12160  return;
12161  }
12162  tmp_rh->uri = mg_strdup(uri);
12163  if (!tmp_rh->uri) {
12164  mg_unlock_context(ctx);
12165  mg_free(tmp_rh);
12166  mg_cry(fc(ctx), "%s", "Cannot create new request handler struct, OOM");
12167  return;
12168  }
12169  tmp_rh->uri_len = urilen;
12170  if (handler_type == REQUEST_HANDLER) {
12171  tmp_rh->handler = handler;
12172  } else if (handler_type == WEBSOCKET_HANDLER) {
12173  tmp_rh->subprotocols = subprotocols;
12174  tmp_rh->connect_handler = connect_handler;
12175  tmp_rh->ready_handler = ready_handler;
12176  tmp_rh->data_handler = data_handler;
12177  tmp_rh->close_handler = close_handler;
12178  } else { /* AUTH_HANDLER */
12179  tmp_rh->auth_handler = auth_handler;
12180  }
12181  tmp_rh->cbdata = cbdata;
12182  tmp_rh->handler_type = handler_type;
12183  tmp_rh->next = NULL;
12184 
12185  *lastref = tmp_rh;
12186  mg_unlock_context(ctx);
12187 }
12188 
12189 
12190 void
12191 mg_set_request_handler(struct mg_context *ctx,
12192  const char *uri,
12193  mg_request_handler handler,
12194  void *cbdata)
12195 {
12196  mg_set_handler_type(ctx,
12197  uri,
12199  handler == NULL,
12200  handler,
12201  NULL,
12202  NULL,
12203  NULL,
12204  NULL,
12205  NULL,
12206  NULL,
12207  cbdata);
12208 }
12209 
12210 
12211 void
12212 mg_set_websocket_handler(struct mg_context *ctx,
12213  const char *uri,
12214  mg_websocket_connect_handler connect_handler,
12215  mg_websocket_ready_handler ready_handler,
12216  mg_websocket_data_handler data_handler,
12217  mg_websocket_close_handler close_handler,
12218  void *cbdata)
12219 {
12221  uri,
12222  NULL,
12223  connect_handler,
12224  ready_handler,
12225  data_handler,
12226  close_handler,
12227  cbdata);
12228 }
12229 
12230 
12231 void
12233  struct mg_context *ctx,
12234  const char *uri,
12235  struct mg_websocket_subprotocols *subprotocols,
12236  mg_websocket_connect_handler connect_handler,
12237  mg_websocket_ready_handler ready_handler,
12238  mg_websocket_data_handler data_handler,
12239  mg_websocket_close_handler close_handler,
12240  void *cbdata)
12241 {
12242  int is_delete_request = (connect_handler == NULL) && (ready_handler == NULL)
12243  && (data_handler == NULL)
12244  && (close_handler == NULL);
12245  mg_set_handler_type(ctx,
12246  uri,
12248  is_delete_request,
12249  NULL,
12250  subprotocols,
12251  connect_handler,
12252  ready_handler,
12253  data_handler,
12254  close_handler,
12255  NULL,
12256  cbdata);
12257 }
12258 
12259 
12260 void
12261 mg_set_auth_handler(struct mg_context *ctx,
12262  const char *uri,
12263  mg_request_handler handler,
12264  void *cbdata)
12265 {
12266  mg_set_handler_type(ctx,
12267  uri,
12268  AUTH_HANDLER,
12269  handler == NULL,
12270  NULL,
12271  NULL,
12272  NULL,
12273  NULL,
12274  NULL,
12275  NULL,
12276  handler,
12277  cbdata);
12278 }
12279 
12280 
12281 static int
12282 get_request_handler(struct mg_connection *conn,
12283  int handler_type,
12284  mg_request_handler *handler,
12285  struct mg_websocket_subprotocols **subprotocols,
12286  mg_websocket_connect_handler *connect_handler,
12287  mg_websocket_ready_handler *ready_handler,
12288  mg_websocket_data_handler *data_handler,
12289  mg_websocket_close_handler *close_handler,
12290  mg_authorization_handler *auth_handler,
12291  void **cbdata)
12292 {
12293  const struct mg_request_info *request_info = mg_get_request_info(conn);
12294  if (request_info) {
12295  const char *uri = request_info->local_uri;
12296  size_t urilen = strlen(uri);
12297  struct mg_handler_info *tmp_rh;
12298 
12299  if (!conn || !conn->ctx) {
12300  return 0;
12301  }
12302 
12303  mg_lock_context(conn->ctx);
12304 
12305  /* first try for an exact match */
12306  for (tmp_rh = conn->ctx->handlers; tmp_rh != NULL;
12307  tmp_rh = tmp_rh->next) {
12308  if (tmp_rh->handler_type == handler_type) {
12309  if ((urilen == tmp_rh->uri_len) && !strcmp(tmp_rh->uri, uri)) {
12310  if (handler_type == WEBSOCKET_HANDLER) {
12311  *subprotocols = tmp_rh->subprotocols;
12312  *connect_handler = tmp_rh->connect_handler;
12313  *ready_handler = tmp_rh->ready_handler;
12314  *data_handler = tmp_rh->data_handler;
12315  *close_handler = tmp_rh->close_handler;
12316  } else if (handler_type == REQUEST_HANDLER) {
12317  *handler = tmp_rh->handler;
12318  } else { /* AUTH_HANDLER */
12319  *auth_handler = tmp_rh->auth_handler;
12320  }
12321  *cbdata = tmp_rh->cbdata;
12322  mg_unlock_context(conn->ctx);
12323  return 1;
12324  }
12325  }
12326  }
12327 
12328  /* next try for a partial match, we will accept uri/something */
12329  for (tmp_rh = conn->ctx->handlers; tmp_rh != NULL;
12330  tmp_rh = tmp_rh->next) {
12331  if (tmp_rh->handler_type == handler_type) {
12332  if ((tmp_rh->uri_len < urilen) && (uri[tmp_rh->uri_len] == '/')
12333  && (memcmp(tmp_rh->uri, uri, tmp_rh->uri_len) == 0)) {
12334  if (handler_type == WEBSOCKET_HANDLER) {
12335  *subprotocols = tmp_rh->subprotocols;
12336  *connect_handler = tmp_rh->connect_handler;
12337  *ready_handler = tmp_rh->ready_handler;
12338  *data_handler = tmp_rh->data_handler;
12339  *close_handler = tmp_rh->close_handler;
12340  } else if (handler_type == REQUEST_HANDLER) {
12341  *handler = tmp_rh->handler;
12342  } else { /* AUTH_HANDLER */
12343  *auth_handler = tmp_rh->auth_handler;
12344  }
12345  *cbdata = tmp_rh->cbdata;
12346  mg_unlock_context(conn->ctx);
12347  return 1;
12348  }
12349  }
12350  }
12351 
12352  /* finally try for pattern match */
12353  for (tmp_rh = conn->ctx->handlers; tmp_rh != NULL;
12354  tmp_rh = tmp_rh->next) {
12355  if (tmp_rh->handler_type == handler_type) {
12356  if (match_prefix(tmp_rh->uri, tmp_rh->uri_len, uri) > 0) {
12357  if (handler_type == WEBSOCKET_HANDLER) {
12358  *subprotocols = tmp_rh->subprotocols;
12359  *connect_handler = tmp_rh->connect_handler;
12360  *ready_handler = tmp_rh->ready_handler;
12361  *data_handler = tmp_rh->data_handler;
12362  *close_handler = tmp_rh->close_handler;
12363  } else if (handler_type == REQUEST_HANDLER) {
12364  *handler = tmp_rh->handler;
12365  } else { /* AUTH_HANDLER */
12366  *auth_handler = tmp_rh->auth_handler;
12367  }
12368  *cbdata = tmp_rh->cbdata;
12369  mg_unlock_context(conn->ctx);
12370  return 1;
12371  }
12372  }
12373  }
12374 
12375  mg_unlock_context(conn->ctx);
12376  }
12377  return 0; /* none found */
12378 }
12379 
12380 
12381 /* Check if the script file is in a path, allowed for script files.
12382  * This can be used if uploading files is possible not only for the server
12383  * admin, and the upload mechanism does not check the file extension.
12384  */
12385 static int
12386 is_in_script_path(const struct mg_connection *conn, const char *path)
12387 {
12388  /* TODO (Feature): Add config value for allowed script path.
12389  * Default: All allowed. */
12390  (void)conn;
12391  (void)path;
12392  return 1;
12393 }
12394 
12395 
12396 #if defined(USE_WEBSOCKET) && defined(MG_LEGACY_INTERFACE)
12397 static int
12398 deprecated_websocket_connect_wrapper(const struct mg_connection *conn,
12399  void *cbdata)
12400 {
12401  struct mg_callbacks *pcallbacks = (struct mg_callbacks *)cbdata;
12402  if (pcallbacks->websocket_connect) {
12403  return pcallbacks->websocket_connect(conn);
12404  }
12405  /* No handler set - assume "OK" */
12406  return 0;
12407 }
12408 
12409 
12410 static void
12411 deprecated_websocket_ready_wrapper(struct mg_connection *conn, void *cbdata)
12412 {
12413  struct mg_callbacks *pcallbacks = (struct mg_callbacks *)cbdata;
12414  if (pcallbacks->websocket_ready) {
12415  pcallbacks->websocket_ready(conn);
12416  }
12417 }
12418 
12419 
12420 static int
12421 deprecated_websocket_data_wrapper(struct mg_connection *conn,
12422  int bits,
12423  char *data,
12424  size_t len,
12425  void *cbdata)
12426 {
12427  struct mg_callbacks *pcallbacks = (struct mg_callbacks *)cbdata;
12428  if (pcallbacks->websocket_data) {
12429  return pcallbacks->websocket_data(conn, bits, data, len);
12430  }
12431  /* No handler set - assume "OK" */
12432  return 1;
12433 }
12434 #endif
12435 
12436 
12437 /* This is the heart of the Civetweb's logic.
12438  * This function is called when the request is read, parsed and validated,
12439  * and Civetweb must decide what action to take: serve a file, or
12440  * a directory, or call embedded function, etcetera. */
12441 static void
12442 handle_request(struct mg_connection *conn)
12443 {
12444  struct mg_request_info *ri = &conn->request_info;
12445  char path[PATH_MAX];
12446  int uri_len, ssl_index;
12447  int is_found = 0, is_script_resource = 0, is_websocket_request = 0,
12448  is_put_or_delete_request = 0, is_callback_resource = 0;
12449  int i;
12450  struct mg_file file = STRUCT_FILE_INITIALIZER;
12451  mg_request_handler callback_handler = NULL;
12453  mg_websocket_connect_handler ws_connect_handler = NULL;
12454  mg_websocket_ready_handler ws_ready_handler = NULL;
12455  mg_websocket_data_handler ws_data_handler = NULL;
12456  mg_websocket_close_handler ws_close_handler = NULL;
12457  void *callback_data = NULL;
12458  mg_authorization_handler auth_handler = NULL;
12459  void *auth_callback_data = NULL;
12460  int handler_type;
12461  time_t curtime = time(NULL);
12462  char date[64];
12463 
12464  path[0] = 0;
12465 
12466  /* 1. get the request url */
12467  /* 1.1. split into url and query string */
12468  if ((conn->request_info.query_string = strchr(ri->request_uri, '?'))
12469  != NULL) {
12470  *((char *)conn->request_info.query_string++) = '\0';
12471  }
12472 
12473  /* 1.2. do a https redirect, if required. Do not decode URIs yet. */
12474  if (!conn->client.is_ssl && conn->client.ssl_redir) {
12475  ssl_index = get_first_ssl_listener_index(conn->ctx);
12476  if (ssl_index >= 0) {
12477  redirect_to_https_port(conn, ssl_index);
12478  } else {
12479  /* A http to https forward port has been specified,
12480  * but no https port to forward to. */
12481  mg_send_http_error(conn,
12482  503,
12483  "%s",
12484  "Error: SSL forward not configured properly");
12485  mg_cry(conn, "Can not redirect to SSL, no SSL port available");
12486  }
12487  return;
12488  }
12489  uri_len = (int)strlen(ri->local_uri);
12490 
12491  /* 1.3. decode url (if config says so) */
12492  if (should_decode_url(conn)) {
12493  mg_url_decode(
12494  ri->local_uri, uri_len, (char *)ri->local_uri, uri_len + 1, 0);
12495  }
12496 
12497  /* 1.4. clean URIs, so a path like allowed_dir/../forbidden_file is
12498  * not possible */
12500 
12501  /* step 1. completed, the url is known now */
12502  uri_len = (int)strlen(ri->local_uri);
12503  DEBUG_TRACE("URL: %s", ri->local_uri);
12504 
12505  /* 2. if this ip has limited speed, set it for this connection */
12506  conn->throttle = set_throttle(conn->ctx->config[THROTTLE],
12507  get_remote_ip(conn),
12508  ri->local_uri);
12509 
12510  /* 3. call a "handle everything" callback, if registered */
12511  if (conn->ctx->callbacks.begin_request != NULL) {
12512  /* Note that since V1.7 the "begin_request" function is called
12513  * before an authorization check. If an authorization check is
12514  * required, use a request_handler instead. */
12515  i = conn->ctx->callbacks.begin_request(conn);
12516  if (i > 0) {
12517  /* callback already processed the request. Store the
12518  return value as a status code for the access log. */
12519  conn->status_code = i;
12521  return;
12522  } else if (i == 0) {
12523  /* civetweb should process the request */
12524  } else {
12525  /* unspecified - may change with the next version */
12526  return;
12527  }
12528  }
12529 
12530  /* request not yet handled by a handler or redirect, so the request
12531  * is processed here */
12532 
12533  /* 4. Check for CORS preflight requests and handle them (if configured).
12534  * https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS
12535  */
12536  if (!strcmp(ri->request_method, "OPTIONS")) {
12537  /* Send a response to CORS preflights only if
12538  * access_control_allow_methods is not NULL and not an empty string.
12539  * In this case, scripts can still handle CORS. */
12540  const char *cors_meth_cfg =
12541  conn->ctx->config[ACCESS_CONTROL_ALLOW_METHODS];
12542  const char *cors_orig_cfg =
12543  conn->ctx->config[ACCESS_CONTROL_ALLOW_ORIGIN];
12544  const char *cors_origin =
12545  get_header(ri->http_headers, ri->num_headers, "Origin");
12546  const char *cors_acrm = get_header(ri->http_headers,
12547  ri->num_headers,
12548  "Access-Control-Request-Method");
12549 
12550  /* Todo: check if cors_origin is in cors_orig_cfg.
12551  * Or, let the client check this. */
12552 
12553  if ((cors_meth_cfg != NULL) && (*cors_meth_cfg != 0)
12554  && (cors_orig_cfg != NULL) && (*cors_orig_cfg != 0)
12555  && (cors_origin != NULL) && (cors_acrm != NULL)) {
12556  /* This is a valid CORS preflight, and the server is configured
12557  * to
12558  * handle it automatically. */
12559  const char *cors_acrh =
12561  ri->num_headers,
12562  "Access-Control-Request-Headers");
12563 
12564  gmt_time_string(date, sizeof(date), &curtime);
12565  mg_printf(conn,
12566  "HTTP/1.1 200 OK\r\n"
12567  "Date: %s\r\n"
12568  "Access-Control-Allow-Origin: %s\r\n"
12569  "Access-Control-Allow-Methods: %s\r\n"
12570  "Content-Length: 0\r\n"
12571  "Connection: %s\r\n",
12572  date,
12573  cors_orig_cfg,
12574  ((cors_meth_cfg[0] == '*') ? cors_acrm : cors_meth_cfg),
12576 
12577  if (cors_acrh != NULL) {
12578  /* CORS request is asking for additional headers */
12579  const char *cors_hdr_cfg =
12580  conn->ctx->config[ACCESS_CONTROL_ALLOW_HEADERS];
12581 
12582  if ((cors_hdr_cfg != NULL) && (*cors_hdr_cfg != 0)) {
12583  /* Allow only if access_control_allow_headers is
12584  * not NULL and not an empty string. If this
12585  * configuration is set to *, allow everything.
12586  * Otherwise this configuration must be a list
12587  * of allowed HTTP header names. */
12588  mg_printf(conn,
12589  "Access-Control-Allow-Headers: %s\r\n",
12590  ((cors_hdr_cfg[0] == '*') ? cors_acrh
12591  : cors_hdr_cfg));
12592  }
12593  }
12594  mg_printf(conn, "Access-Control-Max-Age: 60\r\n");
12595 
12596  mg_printf(conn, "\r\n");
12597  return;
12598  }
12599  }
12600 
12601  /* 5. interpret the url to find out how the request must be handled
12602  */
12603  /* 5.1. first test, if the request targets the regular http(s)://
12604  * protocol namespace or the websocket ws(s):// protocol namespace.
12605  */
12606  is_websocket_request = is_websocket_protocol(conn);
12607 #if defined(USE_WEBSOCKET)
12608  handler_type = is_websocket_request ? WEBSOCKET_HANDLER : REQUEST_HANDLER;
12609 #else
12610  handler_type = REQUEST_HANDLER;
12611 #endif /* defined(USE_WEBSOCKET) */
12612  /* 5.2. check if the request will be handled by a callback */
12613  if (get_request_handler(conn,
12614  handler_type,
12615  &callback_handler,
12616  &subprotocols,
12617  &ws_connect_handler,
12618  &ws_ready_handler,
12619  &ws_data_handler,
12620  &ws_close_handler,
12621  NULL,
12622  &callback_data)) {
12623  /* 5.2.1. A callback will handle this request. All requests
12624  * handled
12625  * by a callback have to be considered as requests to a script
12626  * resource. */
12627  is_callback_resource = 1;
12628  is_script_resource = 1;
12629  is_put_or_delete_request = is_put_or_delete_method(conn);
12630  } else {
12631  no_callback_resource:
12632  /* 5.2.2. No callback is responsible for this request. The URI
12633  * addresses a file based resource (static content or Lua/cgi
12634  * scripts in the file system). */
12635  is_callback_resource = 0;
12636  interpret_uri(conn,
12637  path,
12638  sizeof(path),
12639  &file.stat,
12640  &is_found,
12641  &is_script_resource,
12642  &is_websocket_request,
12643  &is_put_or_delete_request);
12644  }
12645 
12646  /* 6. authorization check */
12647  /* 6.1. a custom authorization handler is installed */
12648  if (get_request_handler(conn,
12649  AUTH_HANDLER,
12650  NULL,
12651  NULL,
12652  NULL,
12653  NULL,
12654  NULL,
12655  NULL,
12656  &auth_handler,
12657  &auth_callback_data)) {
12658  if (!auth_handler(conn, auth_callback_data)) {
12659  return;
12660  }
12661  } else if (is_put_or_delete_request && !is_script_resource
12662  && !is_callback_resource) {
12663 /* 6.2. this request is a PUT/DELETE to a real file */
12664 /* 6.2.1. thus, the server must have real files */
12665 #if defined(NO_FILES)
12666  if (1) {
12667 #else
12668  if (conn->ctx->config[DOCUMENT_ROOT] == NULL) {
12669 #endif
12670  /* This server does not have any real files, thus the
12671  * PUT/DELETE methods are not valid. */
12672  mg_send_http_error(conn,
12673  405,
12674  "%s method not allowed",
12675  conn->request_info.request_method);
12676  return;
12677  }
12678 
12679 #if !defined(NO_FILES)
12680  /* 6.2.2. Check if put authorization for static files is
12681  * available.
12682  */
12683  if (!is_authorized_for_put(conn)) {
12684  send_authorization_request(conn, NULL);
12685  return;
12686  }
12687 #endif
12688 
12689  } else {
12690  /* 6.3. This is either a OPTIONS, GET, HEAD or POST request,
12691  * or it is a PUT or DELETE request to a resource that does not
12692  * correspond to a file. Check authorization. */
12693  if (!check_authorization(conn, path)) {
12694  send_authorization_request(conn, NULL);
12695  return;
12696  }
12697  }
12698 
12699  /* request is authorized or does not need authorization */
12700 
12701  /* 7. check if there are request handlers for this uri */
12702  if (is_callback_resource) {
12703  if (!is_websocket_request) {
12704  i = callback_handler(conn, callback_data);
12705  if (i > 0) {
12706  /* Do nothing, callback has served the request. Store
12707  * then return value as status code for the log and discard
12708  * all data from the client not used by the callback. */
12709  conn->status_code = i;
12711  } else {
12712  /* The handler did NOT handle the request. */
12713  /* Some proper reactions would be:
12714  * a) close the connections without sending anything
12715  * b) send a 404 not found
12716  * c) try if there is a file matching the URI
12717  * It would be possible to do a, b or c in the callback
12718  * implementation, and return 1 - we cannot do anything
12719  * here, that is not possible in the callback.
12720  *
12721  * TODO: What would be the best reaction here?
12722  * (Note: The reaction may change, if there is a better
12723  *idea.)
12724  */
12725 
12726  /* For the moment, use option c: We look for a proper file,
12727  * but since a file request is not always a script resource,
12728  * the authorization check might be different. */
12729  interpret_uri(conn,
12730  path,
12731  sizeof(path),
12732  &file.stat,
12733  &is_found,
12734  &is_script_resource,
12735  &is_websocket_request,
12736  &is_put_or_delete_request);
12737  callback_handler = NULL;
12738 
12739  /* Here we are at a dead end:
12740  * According to URI matching, a callback should be
12741  * responsible for handling the request,
12742  * we called it, but the callback declared itself
12743  * not responsible.
12744  * We use a goto here, to get out of this dead end,
12745  * and continue with the default handling.
12746  * A goto here is simpler and better to understand
12747  * than some curious loop. */
12748  goto no_callback_resource;
12749  }
12750  } else {
12751 #if defined(USE_WEBSOCKET)
12752  handle_websocket_request(conn,
12753  path,
12754  is_callback_resource,
12755  subprotocols,
12756  ws_connect_handler,
12757  ws_ready_handler,
12758  ws_data_handler,
12759  ws_close_handler,
12760  callback_data);
12761 #endif
12762  }
12763  return;
12764  }
12765 
12766 /* 8. handle websocket requests */
12767 #if defined(USE_WEBSOCKET)
12768  if (is_websocket_request) {
12769  if (is_script_resource) {
12770 
12771  if (is_in_script_path(conn, path)) {
12772  /* Websocket Lua script */
12773  handle_websocket_request(conn,
12774  path,
12775  0 /* Lua Script */,
12776  NULL,
12777  NULL,
12778  NULL,
12779  NULL,
12780  NULL,
12781  &conn->ctx->callbacks);
12782  } else {
12783  /* Script was in an illegal path */
12784  mg_send_http_error(conn, 403, "%s", "Forbidden");
12785  }
12786  } else {
12787 #if defined(MG_LEGACY_INTERFACE)
12788  handle_websocket_request(
12789  conn,
12790  path,
12791  !is_script_resource /* could be deprecated global callback */,
12792  NULL,
12793  deprecated_websocket_connect_wrapper,
12794  deprecated_websocket_ready_wrapper,
12795  deprecated_websocket_data_wrapper,
12796  NULL,
12797  &conn->ctx->callbacks);
12798 #else
12799  mg_send_http_error(conn, 404, "%s", "Not found");
12800 #endif
12801  }
12802  return;
12803  } else
12804 #endif
12805 
12806 #if defined(NO_FILES)
12807  /* 9a. In case the server uses only callbacks, this uri is
12808  * unknown.
12809  * Then, all request handling ends here. */
12810  mg_send_http_error(conn, 404, "%s", "Not Found");
12811 
12812 #else
12813  /* 9b. This request is either for a static file or resource handled
12814  * by a script file. Thus, a DOCUMENT_ROOT must exist. */
12815  if (conn->ctx->config[DOCUMENT_ROOT] == NULL) {
12816  mg_send_http_error(conn, 404, "%s", "Not Found");
12817  return;
12818  }
12819 
12820  /* 10. Request is handled by a script */
12821  if (is_script_resource) {
12822  handle_file_based_request(conn, path, &file);
12823  return;
12824  }
12825 
12826  /* 11. Handle put/delete/mkcol requests */
12827  if (is_put_or_delete_request) {
12828  /* 11.1. PUT method */
12829  if (!strcmp(ri->request_method, "PUT")) {
12830  put_file(conn, path);
12831  return;
12832  }
12833  /* 11.2. DELETE method */
12834  if (!strcmp(ri->request_method, "DELETE")) {
12835  delete_file(conn, path);
12836  return;
12837  }
12838  /* 11.3. MKCOL method */
12839  if (!strcmp(ri->request_method, "MKCOL")) {
12840  mkcol(conn, path);
12841  return;
12842  }
12843  /* 11.4. PATCH method
12844  * This method is not supported for static resources,
12845  * only for scripts (Lua, CGI) and callbacks. */
12846  mg_send_http_error(conn,
12847  405,
12848  "%s method not allowed",
12849  conn->request_info.request_method);
12850  return;
12851  }
12852 
12853  /* 11. File does not exist, or it was configured that it should be
12854  * hidden */
12855  if (!is_found || (must_hide_file(conn, path))) {
12856  mg_send_http_error(conn, 404, "%s", "Not found");
12857  return;
12858  }
12859 
12860  /* 12. Directory uris should end with a slash */
12861  if (file.stat.is_directory && (uri_len > 0)
12862  && (ri->local_uri[uri_len - 1] != '/')) {
12863  gmt_time_string(date, sizeof(date), &curtime);
12864  mg_printf(conn,
12865  "HTTP/1.1 301 Moved Permanently\r\n"
12866  "Location: %s/\r\n"
12867  "Date: %s\r\n"
12868  /* "Cache-Control: private\r\n" (= default) */
12869  "Content-Length: 0\r\n"
12870  "Connection: %s\r\n",
12871  ri->request_uri,
12872  date,
12874  send_additional_header(conn);
12875  mg_printf(conn, "\r\n");
12876  return;
12877  }
12878 
12879  /* 13. Handle other methods than GET/HEAD */
12880  /* 13.1. Handle PROPFIND */
12881  if (!strcmp(ri->request_method, "PROPFIND")) {
12882  handle_propfind(conn, path, &file.stat);
12883  return;
12884  }
12885  /* 13.2. Handle OPTIONS for files */
12886  if (!strcmp(ri->request_method, "OPTIONS")) {
12887  /* This standard handler is only used for real files.
12888  * Scripts should support the OPTIONS method themselves, to allow a
12889  * maximum flexibility.
12890  * Lua and CGI scripts may fully support CORS this way (including
12891  * preflights). */
12892  send_options(conn);
12893  return;
12894  }
12895  /* 13.3. everything but GET and HEAD (e.g. POST) */
12896  if ((0 != strcmp(ri->request_method, "GET"))
12897  && (0 != strcmp(ri->request_method, "HEAD"))) {
12898  mg_send_http_error(conn,
12899  405,
12900  "%s method not allowed",
12901  conn->request_info.request_method);
12902  return;
12903  }
12904 
12905  /* 14. directories */
12906  if (file.stat.is_directory) {
12907  /* Substitute files have already been handled above. */
12908  /* Here we can either generate and send a directory listing,
12909  * or send an "access denied" error. */
12910  if (!mg_strcasecmp(conn->ctx->config[ENABLE_DIRECTORY_LISTING],
12911  "yes")) {
12912  handle_directory_request(conn, path);
12913  } else {
12914  mg_send_http_error(conn,
12915  403,
12916  "%s",
12917  "Error: Directory listing denied");
12918  }
12919  return;
12920  }
12921 
12922  handle_file_based_request(conn, path, &file);
12923 #endif /* !defined(NO_FILES) */
12924 
12925 #if 0
12926  /* Perform redirect and auth checks before calling begin_request()
12927  * handler.
12928  * Otherwise, begin_request() would need to perform auth checks and
12929  * redirects. */
12930 #endif
12931 }
12932 
12933 
12934 static void
12935 handle_file_based_request(struct mg_connection *conn,
12936  const char *path,
12937  struct mg_file *file)
12938 {
12939  if (!conn || !conn->ctx) {
12940  return;
12941  }
12942 
12943  if (0) {
12944 #ifdef USE_LUA
12945  } else if (match_prefix(conn->ctx->config[LUA_SERVER_PAGE_EXTENSIONS],
12946  strlen(
12947  conn->ctx->config[LUA_SERVER_PAGE_EXTENSIONS]),
12948  path) > 0) {
12949  if (is_in_script_path(conn, path)) {
12950  /* Lua server page: an SSI like page containing mostly plain
12951  * html
12952  * code
12953  * plus some tags with server generated contents. */
12954  handle_lsp_request(conn, path, file, NULL);
12955  } else {
12956  /* Script was in an illegal path */
12957  mg_send_http_error(conn, 403, "%s", "Forbidden");
12958  }
12959 
12960  } else if (match_prefix(conn->ctx->config[LUA_SCRIPT_EXTENSIONS],
12961  strlen(conn->ctx->config[LUA_SCRIPT_EXTENSIONS]),
12962  path) > 0) {
12963  if (is_in_script_path(conn, path)) {
12964  /* Lua in-server module script: a CGI like script used to
12965  * generate
12966  * the
12967  * entire reply. */
12968  mg_exec_lua_script(conn, path, NULL);
12969  } else {
12970  /* Script was in an illegal path */
12971  mg_send_http_error(conn, 403, "%s", "Forbidden");
12972  }
12973 #endif
12974 #if defined(USE_DUKTAPE)
12975  } else if (match_prefix(conn->ctx->config[DUKTAPE_SCRIPT_EXTENSIONS],
12976  strlen(
12977  conn->ctx->config[DUKTAPE_SCRIPT_EXTENSIONS]),
12978  path) > 0) {
12979  if (is_in_script_path(conn, path)) {
12980  /* Call duktape to generate the page */
12981  mg_exec_duktape_script(conn, path);
12982  } else {
12983  /* Script was in an illegal path */
12984  mg_send_http_error(conn, 403, "%s", "Forbidden");
12985  }
12986 #endif
12987 #if !defined(NO_CGI)
12988  } else if (match_prefix(conn->ctx->config[CGI_EXTENSIONS],
12989  strlen(conn->ctx->config[CGI_EXTENSIONS]),
12990  path) > 0) {
12991  if (is_in_script_path(conn, path)) {
12992  /* CGI scripts may support all HTTP methods */
12993  handle_cgi_request(conn, path);
12994  } else {
12995  /* Script was in an illegal path */
12996  mg_send_http_error(conn, 403, "%s", "Forbidden");
12997  }
12998 #endif /* !NO_CGI */
12999  } else if (match_prefix(conn->ctx->config[SSI_EXTENSIONS],
13000  strlen(conn->ctx->config[SSI_EXTENSIONS]),
13001  path) > 0) {
13002  if (is_in_script_path(conn, path)) {
13003  handle_ssi_file_request(conn, path, file);
13004  } else {
13005  /* Script was in an illegal path */
13006  mg_send_http_error(conn, 403, "%s", "Forbidden");
13007  }
13008 #if !defined(NO_CACHING)
13009  } else if ((!conn->in_error_handler)
13010  && is_not_modified(conn, &file->stat)) {
13011  /* Send 304 "Not Modified" - this must not send any body data */
13013 #endif /* !NO_CACHING */
13014  } else {
13015  handle_static_file_request(conn, path, file, NULL, NULL);
13016  }
13017 }
13018 
13019 
13020 static void
13021 close_all_listening_sockets(struct mg_context *ctx)
13022 {
13023  unsigned int i;
13024  if (!ctx) {
13025  return;
13026  }
13027 
13028  for (i = 0; i < ctx->num_listening_sockets; i++) {
13029  closesocket(ctx->listening_sockets[i].sock);
13030  ctx->listening_sockets[i].sock = INVALID_SOCKET;
13031  }
13032  mg_free(ctx->listening_sockets);
13033  ctx->listening_sockets = NULL;
13034  mg_free(ctx->listening_socket_fds);
13035  ctx->listening_socket_fds = NULL;
13036 }
13037 
13038 
13039 /* Valid listening port specification is: [ip_address:]port[s]
13040  * Examples for IPv4: 80, 443s, 127.0.0.1:3128, 192.0.2.3:8080s
13041  * Examples for IPv6: [::]:80, [::1]:80,
13042  * [2001:0db8:7654:3210:FEDC:BA98:7654:3210]:443s
13043  * see https://tools.ietf.org/html/rfc3513#section-2.2
13044  * In order to bind to both, IPv4 and IPv6, you can either add
13045  * both ports using 8080,[::]:8080, or the short form +8080.
13046  * Both forms differ in detail: 8080,[::]:8080 create two sockets,
13047  * one only accepting IPv4 the other only IPv6. +8080 creates
13048  * one socket accepting IPv4 and IPv6. Depending on the IPv6
13049  * environment, they might work differently, or might not work
13050  * at all - it must be tested what options work best in the
13051  * relevant network environment.
13052  */
13053 static int
13054 parse_port_string(const struct vec *vec, struct socket *so, int *ip_version)
13055 {
13056  unsigned int a, b, c, d, port;
13057  int ch, len;
13058  const char *cb;
13059 #if defined(USE_IPV6)
13060  char buf[100] = {0};
13061 #endif
13062 
13063  /* MacOS needs that. If we do not zero it, subsequent bind() will fail.
13064  * Also, all-zeroes in the socket address means binding to all addresses
13065  * for both IPv4 and IPv6 (INADDR_ANY and IN6ADDR_ANY_INIT). */
13066  memset(so, 0, sizeof(*so));
13067  so->lsa.sin.sin_family = AF_INET;
13068  *ip_version = 0;
13069 
13070  /* Initialize port and len as invalid. */
13071  port = 0;
13072  len = 0;
13073 
13074  /* Test for different ways to format this string */
13075  if (sscanf(vec->ptr, "%u.%u.%u.%u:%u%n", &a, &b, &c, &d, &port, &len)
13076  == 5) {
13077  /* Bind to a specific IPv4 address, e.g. 192.168.1.5:8080 */
13078  so->lsa.sin.sin_addr.s_addr =
13079  htonl((a << 24) | (b << 16) | (c << 8) | d);
13080  so->lsa.sin.sin_port = htons((uint16_t)port);
13081  *ip_version = 4;
13082 
13083 #if defined(USE_IPV6)
13084  } else if (sscanf(vec->ptr, "[%49[^]]]:%u%n", buf, &port, &len) == 2
13085  && mg_inet_pton(
13086  AF_INET6, buf, &so->lsa.sin6, sizeof(so->lsa.sin6))) {
13087  /* IPv6 address, examples: see above */
13088  /* so->lsa.sin6.sin6_family = AF_INET6; already set by mg_inet_pton
13089  */
13090  so->lsa.sin6.sin6_port = htons((uint16_t)port);
13091  *ip_version = 6;
13092 #endif
13093 
13094  } else if ((vec->ptr[0] == '+')
13095  && (sscanf(vec->ptr + 1, "%u%n", &port, &len) == 1)) {
13096 
13097  /* Port is specified with a +, bind to IPv6 and IPv4, INADDR_ANY */
13098  /* Add 1 to len for the + character we skipped before */
13099  len++;
13100 
13101 #if defined(USE_IPV6)
13102  /* Set socket family to IPv6, do not use IPV6_V6ONLY */
13103  so->lsa.sin6.sin6_family = AF_INET6;
13104  so->lsa.sin6.sin6_port = htons((uint16_t)port);
13105  *ip_version = 4 + 6;
13106 #else
13107  /* Bind to IPv4 only, since IPv6 is not built in. */
13108  so->lsa.sin.sin_port = htons((uint16_t)port);
13109  *ip_version = 4;
13110 #endif
13111 
13112  } else if (sscanf(vec->ptr, "%u%n", &port, &len) == 1) {
13113  /* If only port is specified, bind to IPv4, INADDR_ANY */
13114  so->lsa.sin.sin_port = htons((uint16_t)port);
13115  *ip_version = 4;
13116 
13117  } else if ((cb = strchr(vec->ptr, ':')) != NULL) {
13118  /* Could be a hostname */
13119  /* Will only work for RFC 952 compliant hostnames,
13120  * starting with a letter, containing only letters,
13121  * digits and hyphen ('-'). Newer specs may allow
13122  * more, but this is not guaranteed here, since it
13123  * may interfere with rules for port option lists. */
13124 
13125  *(char *)cb = 0; /* Use a const cast here and modify the string.
13126  * We are going to restore the string later. */
13127 
13128  if (mg_inet_pton(
13129  AF_INET, vec->ptr, &so->lsa.sin, sizeof(so->lsa.sin))) {
13130  if (sscanf(cb + 1, "%u%n", &port, &len) == 1) {
13131  *ip_version = 4;
13132  so->lsa.sin.sin_family = AF_INET;
13133  so->lsa.sin.sin_port = htons((uint16_t)port);
13134  len += (int)(cb - vec->ptr) + 1;
13135  } else {
13136  port = 0;
13137  len = 0;
13138  }
13139 #if defined(USE_IPV6)
13140  } else if (mg_inet_pton(AF_INET6,
13141  vec->ptr,
13142  &so->lsa.sin6,
13143  sizeof(so->lsa.sin6))) {
13144  if (sscanf(cb + 1, "%u%n", &port, &len) == 1) {
13145  *ip_version = 6;
13146  so->lsa.sin6.sin6_family = AF_INET6;
13147  so->lsa.sin.sin_port = htons((uint16_t)port);
13148  len += (int)(cb - vec->ptr) + 1;
13149  } else {
13150  port = 0;
13151  len = 0;
13152  }
13153 #endif
13154  }
13155 
13156  *(char *)cb = ':'; /* restore the string */
13157 
13158  } else {
13159  /* Parsing failure. */
13160  }
13161 
13162  /* sscanf and the option splitting code ensure the following condition
13163  */
13164  if ((len < 0) && ((unsigned)len > (unsigned)vec->len)) {
13165  *ip_version = 0;
13166  return 0;
13167  }
13168  ch = vec->ptr[len]; /* Next character after the port number */
13169  so->is_ssl = (ch == 's');
13170  so->ssl_redir = (ch == 'r');
13171 
13172  /* Make sure the port is valid and vector ends with 's', 'r' or ',' */
13173  if (is_valid_port(port)
13174  && ((ch == '\0') || (ch == 's') || (ch == 'r') || (ch == ','))) {
13175  return 1;
13176  }
13177 
13178  /* Reset ip_version to 0 of there is an error */
13179  *ip_version = 0;
13180  return 0;
13181 }
13182 
13183 
13184 static int
13185 set_ports_option(struct mg_context *ctx)
13186 {
13187  const char *list;
13188  int on = 1;
13189 #if defined(USE_IPV6)
13190  int off = 0;
13191 #endif
13192  struct vec vec;
13193  struct socket so, *ptr;
13194 
13195  struct pollfd *pfd;
13196  union usa usa;
13197  socklen_t len;
13198  int ip_version;
13199 
13200  int portsTotal = 0;
13201  int portsOk = 0;
13202 
13203  if (!ctx) {
13204  return 0;
13205  }
13206 
13207  memset(&so, 0, sizeof(so));
13208  memset(&usa, 0, sizeof(usa));
13209  len = sizeof(usa);
13210  list = ctx->config[LISTENING_PORTS];
13211 
13212  while ((list = next_option(list, &vec, NULL)) != NULL) {
13213 
13214  portsTotal++;
13215 
13216  if (!parse_port_string(&vec, &so, &ip_version)) {
13217  mg_cry(fc(ctx),
13218  "%.*s: invalid port spec (entry %i). Expecting list of: %s",
13219  (int)vec.len,
13220  vec.ptr,
13221  portsTotal,
13222  "[IP_ADDRESS:]PORT[s|r]");
13223  continue;
13224  }
13225 
13226 #if !defined(NO_SSL)
13227  if (so.is_ssl && ctx->ssl_ctx == NULL) {
13228 
13229  mg_cry(fc(ctx),
13230  "Cannot add SSL socket (entry %i). Is -ssl_certificate "
13231  "option set?",
13232  portsTotal);
13233  continue;
13234  }
13235 #endif
13236 
13237  if ((so.sock = socket(so.lsa.sa.sa_family, SOCK_STREAM, 6))
13238  == INVALID_SOCKET) {
13239 
13240  mg_cry(fc(ctx), "cannot create socket (entry %i)", portsTotal);
13241  continue;
13242  }
13243 
13244 #ifdef _WIN32
13245  /* Windows SO_REUSEADDR lets many procs binds to a
13246  * socket, SO_EXCLUSIVEADDRUSE makes the bind fail
13247  * if someone already has the socket -- DTL */
13248  /* NOTE: If SO_EXCLUSIVEADDRUSE is used,
13249  * Windows might need a few seconds before
13250  * the same port can be used again in the
13251  * same process, so a short Sleep may be
13252  * required between mg_stop and mg_start.
13253  */
13254  if (setsockopt(so.sock,
13255  SOL_SOCKET,
13256  SO_EXCLUSIVEADDRUSE,
13257  (SOCK_OPT_TYPE)&on,
13258  sizeof(on)) != 0) {
13259 
13260  /* Set reuse option, but don't abort on errors. */
13261  mg_cry(fc(ctx),
13262  "cannot set socket option SO_EXCLUSIVEADDRUSE (entry %i)",
13263  portsTotal);
13264  }
13265 #else
13266  if (setsockopt(so.sock,
13267  SOL_SOCKET,
13268  SO_REUSEADDR,
13269  (SOCK_OPT_TYPE)&on,
13270  sizeof(on)) != 0) {
13271 
13272  /* Set reuse option, but don't abort on errors. */
13273  mg_cry(fc(ctx),
13274  "cannot set socket option SO_REUSEADDR (entry %i)",
13275  portsTotal);
13276  }
13277 #endif
13278 
13279  if (ip_version > 4) {
13280 #if defined(USE_IPV6)
13281  if (ip_version == 6) {
13282  if (so.lsa.sa.sa_family == AF_INET6
13283  && setsockopt(so.sock,
13284  IPPROTO_IPV6,
13285  IPV6_V6ONLY,
13286  (void *)&off,
13287  sizeof(off)) != 0) {
13288 
13289  /* Set IPv6 only option, but don't abort on errors. */
13290  mg_cry(fc(ctx),
13291  "cannot set socket option IPV6_V6ONLY (entry %i)",
13292  portsTotal);
13293  }
13294  }
13295 #else
13296  mg_cry(fc(ctx), "IPv6 not available");
13297  closesocket(so.sock);
13298  so.sock = INVALID_SOCKET;
13299  continue;
13300 #endif
13301  }
13302 
13303  if (so.lsa.sa.sa_family == AF_INET) {
13304 
13305  len = sizeof(so.lsa.sin);
13306  if (bind(so.sock, &so.lsa.sa, len) != 0) {
13307  mg_cry(fc(ctx),
13308  "cannot bind to %.*s: %d (%s)",
13309  (int)vec.len,
13310  vec.ptr,
13311  (int)ERRNO,
13312  strerror(errno));
13313  closesocket(so.sock);
13314  so.sock = INVALID_SOCKET;
13315  continue;
13316  }
13317  }
13318 #if defined(USE_IPV6)
13319  else if (so.lsa.sa.sa_family == AF_INET6) {
13320 
13321  len = sizeof(so.lsa.sin6);
13322  if (bind(so.sock, &so.lsa.sa, len) != 0) {
13323  mg_cry(fc(ctx),
13324  "cannot bind to IPv6 %.*s: %d (%s)",
13325  (int)vec.len,
13326  vec.ptr,
13327  (int)ERRNO,
13328  strerror(errno));
13329  closesocket(so.sock);
13330  so.sock = INVALID_SOCKET;
13331  continue;
13332  }
13333  }
13334 #endif
13335  else {
13336  mg_cry(fc(ctx),
13337  "cannot bind: address family not supported (entry %i)",
13338  portsTotal);
13339  closesocket(so.sock);
13340  so.sock = INVALID_SOCKET;
13341  continue;
13342  }
13343 
13344  if (listen(so.sock, SOMAXCONN) != 0) {
13345 
13346  mg_cry(fc(ctx),
13347  "cannot listen to %.*s: %d (%s)",
13348  (int)vec.len,
13349  vec.ptr,
13350  (int)ERRNO,
13351  strerror(errno));
13352  closesocket(so.sock);
13353  so.sock = INVALID_SOCKET;
13354  continue;
13355  }
13356 
13357  if ((getsockname(so.sock, &(usa.sa), &len) != 0)
13358  || (usa.sa.sa_family != so.lsa.sa.sa_family)) {
13359 
13360  int err = (int)ERRNO;
13361  mg_cry(fc(ctx),
13362  "call to getsockname failed %.*s: %d (%s)",
13363  (int)vec.len,
13364  vec.ptr,
13365  err,
13366  strerror(errno));
13367  closesocket(so.sock);
13368  so.sock = INVALID_SOCKET;
13369  continue;
13370  }
13371 
13372 /* Update lsa port in case of random free ports */
13373 #if defined(USE_IPV6)
13374  if (so.lsa.sa.sa_family == AF_INET6) {
13375  so.lsa.sin6.sin6_port = usa.sin6.sin6_port;
13376  } else
13377 #endif
13378  {
13379  so.lsa.sin.sin_port = usa.sin.sin_port;
13380  }
13381 
13382  if ((ptr = (struct socket *)
13383  mg_realloc_ctx(ctx->listening_sockets,
13384  (ctx->num_listening_sockets + 1)
13385  * sizeof(ctx->listening_sockets[0]),
13386  ctx)) == NULL) {
13387 
13388  mg_cry(fc(ctx), "%s", "Out of memory");
13389  closesocket(so.sock);
13390  so.sock = INVALID_SOCKET;
13391  continue;
13392  }
13393 
13394  if ((pfd = (struct pollfd *)
13395  mg_realloc_ctx(ctx->listening_socket_fds,
13396  (ctx->num_listening_sockets + 1)
13397  * sizeof(ctx->listening_socket_fds[0]),
13398  ctx)) == NULL) {
13399 
13400  mg_cry(fc(ctx), "%s", "Out of memory");
13401  closesocket(so.sock);
13402  so.sock = INVALID_SOCKET;
13403  mg_free(ptr);
13404  continue;
13405  }
13406 
13407  set_close_on_exec(so.sock, fc(ctx));
13408  ctx->listening_sockets = ptr;
13409  ctx->listening_sockets[ctx->num_listening_sockets] = so;
13410  ctx->listening_socket_fds = pfd;
13411  ctx->num_listening_sockets++;
13412  portsOk++;
13413  }
13414 
13415  if (portsOk != portsTotal) {
13417  portsOk = 0;
13418  }
13419 
13420  return portsOk;
13421 }
13422 
13423 
13424 static const char *
13425 header_val(const struct mg_connection *conn, const char *header)
13426 {
13427  const char *header_value;
13428 
13429  if ((header_value = mg_get_header(conn, header)) == NULL) {
13430  return "-";
13431  } else {
13432  return header_value;
13433  }
13434 }
13435 
13436 
13437 static void
13438 log_access(const struct mg_connection *conn)
13439 {
13440  const struct mg_request_info *ri;
13441  struct mg_file fi;
13442  char date[64], src_addr[IP_ADDR_STR_LEN];
13443  struct tm *tm;
13444 
13445  const char *referer;
13446  const char *user_agent;
13447 
13448  char buf[4096];
13449 
13450  if (!conn || !conn->ctx) {
13451  return;
13452  }
13453 
13454  if (conn->ctx->config[ACCESS_LOG_FILE] != NULL) {
13455  if (mg_fopen(conn,
13456  conn->ctx->config[ACCESS_LOG_FILE],
13458  &fi) == 0) {
13459  fi.access.fp = NULL;
13460  }
13461  } else {
13462  fi.access.fp = NULL;
13463  }
13464 
13465  /* Log is written to a file and/or a callback. If both are not set,
13466  * executing the rest of the function is pointless. */
13467  if ((fi.access.fp == NULL) && (conn->ctx->callbacks.log_access == NULL)) {
13468  return;
13469  }
13470 
13471  tm = localtime(&conn->conn_birth_time);
13472  if (tm != NULL) {
13473  strftime(date, sizeof(date), "%d/%b/%Y:%H:%M:%S %z", tm);
13474  } else {
13475  mg_strlcpy(date, "01/Jan/1970:00:00:00 +0000", sizeof(date));
13476  date[sizeof(date) - 1] = '\0';
13477  }
13478 
13479  ri = &conn->request_info;
13480 
13481  sockaddr_to_string(src_addr, sizeof(src_addr), &conn->client.rsa);
13482  referer = header_val(conn, "Referer");
13483  user_agent = header_val(conn, "User-Agent");
13484 
13485  mg_snprintf(conn,
13486  NULL, /* Ignore truncation in access log */
13487  buf,
13488  sizeof(buf),
13489  "%s - %s [%s] \"%s %s%s%s HTTP/%s\" %d %" INT64_FMT " %s %s",
13490  src_addr,
13491  (ri->remote_user == NULL) ? "-" : ri->remote_user,
13492  date,
13493  ri->request_method ? ri->request_method : "-",
13494  ri->request_uri ? ri->request_uri : "-",
13495  ri->query_string ? "?" : "",
13496  ri->query_string ? ri->query_string : "",
13497  ri->http_version,
13498  conn->status_code,
13499  conn->num_bytes_sent,
13500  referer,
13501  user_agent);
13502 
13503  if (conn->ctx->callbacks.log_access) {
13504  conn->ctx->callbacks.log_access(conn, buf);
13505  }
13506 
13507  if (fi.access.fp) {
13508  int ok = 1;
13509  flockfile(fi.access.fp);
13510  if (fprintf(fi.access.fp, "%s\n", buf) < 1) {
13511  ok = 0;
13512  }
13513  if (fflush(fi.access.fp) != 0) {
13514  ok = 0;
13515  }
13516  funlockfile(fi.access.fp);
13517  if (mg_fclose(&fi.access) != 0) {
13518  ok = 0;
13519  }
13520  if (!ok) {
13521  mg_cry(conn,
13522  "Error writing log file %s",
13523  conn->ctx->config[ACCESS_LOG_FILE]);
13524  }
13525  }
13526 }
13527 
13528 
13529 /* Verify given socket address against the ACL.
13530  * Return -1 if ACL is malformed, 0 if address is disallowed, 1 if allowed.
13531  */
13532 static int
13533 check_acl(struct mg_context *ctx, uint32_t remote_ip)
13534 {
13535  int allowed, flag;
13536  uint32_t net, mask;
13537  struct vec vec;
13538 
13539  if (ctx) {
13540  const char *list = ctx->config[ACCESS_CONTROL_LIST];
13541 
13542  /* If any ACL is set, deny by default */
13543  allowed = (list == NULL) ? '+' : '-';
13544 
13545  while ((list = next_option(list, &vec, NULL)) != NULL) {
13546  flag = vec.ptr[0];
13547  if ((flag != '+' && flag != '-')
13548  || (parse_net(&vec.ptr[1], &net, &mask) == 0)) {
13549  mg_cry(fc(ctx),
13550  "%s: subnet must be [+|-]x.x.x.x[/x]",
13551  __func__);
13552  return -1;
13553  }
13554 
13555  if (net == (remote_ip & mask)) {
13556  allowed = flag;
13557  }
13558  }
13559 
13560  return allowed == '+';
13561  }
13562  return -1;
13563 }
13564 
13565 
13566 #if !defined(_WIN32)
13567 static int
13568 set_uid_option(struct mg_context *ctx)
13569 {
13570  struct passwd *pw;
13571  if (ctx) {
13572  const char *uid = ctx->config[RUN_AS_USER];
13573  int success = 0;
13574 
13575  if (uid == NULL) {
13576  success = 1;
13577  } else {
13578  if ((pw = getpwnam(uid)) == NULL) {
13579  mg_cry(fc(ctx), "%s: unknown user [%s]", __func__, uid);
13580  } else if (setgid(pw->pw_gid) == -1) {
13581  mg_cry(fc(ctx),
13582  "%s: setgid(%s): %s",
13583  __func__,
13584  uid,
13585  strerror(errno));
13586  } else if (setgroups(0, NULL)) {
13587  mg_cry(fc(ctx),
13588  "%s: setgroups(): %s",
13589  __func__,
13590  strerror(errno));
13591  } else if (setuid(pw->pw_uid) == -1) {
13592  mg_cry(fc(ctx),
13593  "%s: setuid(%s): %s",
13594  __func__,
13595  uid,
13596  strerror(errno));
13597  } else {
13598  success = 1;
13599  }
13600  }
13601 
13602  return success;
13603  }
13604  return 0;
13605 }
13606 #endif /* !_WIN32 */
13607 
13608 
13609 static void
13610 tls_dtor(void *key)
13611 {
13612  struct mg_workerTLS *tls = (struct mg_workerTLS *)key;
13613  /* key == pthread_getspecific(sTlsKey); */
13614 
13615  if (tls) {
13616  if (tls->is_master == 2) {
13617  tls->is_master = -3; /* Mark memory as dead */
13618  mg_free(tls);
13619  }
13620  }
13621  pthread_setspecific(sTlsKey, NULL);
13622 }
13623 
13624 
13625 #if !defined(NO_SSL)
13626 
13627 static int
13628 ssl_use_pem_file(struct mg_context *ctx, const char *pem, const char *chain);
13629 static const char *ssl_error(void);
13630 
13631 
13632 static int
13633 refresh_trust(struct mg_connection *conn)
13634 {
13635  static int reload_lock = 0;
13636  static long int data_check = 0;
13637  volatile int *p_reload_lock = (volatile int *)&reload_lock;
13638 
13639  struct stat cert_buf;
13640  long int t;
13641  const char *pem;
13642  const char *chain;
13643  int should_verify_peer;
13644 
13645  if ((pem = conn->ctx->config[SSL_CERTIFICATE]) == NULL) {
13646  /* If peem is NULL and conn->ctx->callbacks.init_ssl is not,
13647  * refresh_trust still can not work. */
13648  return 0;
13649  }
13650  chain = conn->ctx->config[SSL_CERTIFICATE_CHAIN];
13651  if (chain == NULL) {
13652  /* pem is not NULL here */
13653  chain = pem;
13654  }
13655  if (*chain == 0) {
13656  chain = NULL;
13657  }
13658 
13659  t = data_check;
13660  if (stat(pem, &cert_buf) != -1) {
13661  t = (long int)cert_buf.st_mtime;
13662  }
13663 
13664  if (data_check != t) {
13665  data_check = t;
13666 
13667  should_verify_peer = 0;
13668  if (conn->ctx->config[SSL_DO_VERIFY_PEER] != NULL) {
13669  if (mg_strcasecmp(conn->ctx->config[SSL_DO_VERIFY_PEER], "yes")
13670  == 0) {
13671  should_verify_peer = 1;
13672  } else if (mg_strcasecmp(conn->ctx->config[SSL_DO_VERIFY_PEER],
13673  "optional") == 0) {
13674  should_verify_peer = 1;
13675  }
13676  }
13677 
13678  if (should_verify_peer) {
13679  char *ca_path = conn->ctx->config[SSL_CA_PATH];
13680  char *ca_file = conn->ctx->config[SSL_CA_FILE];
13681  if (SSL_CTX_load_verify_locations(conn->ctx->ssl_ctx,
13682  ca_file,
13683  ca_path) != 1) {
13684  mg_cry(fc(conn->ctx),
13685  "SSL_CTX_load_verify_locations error: %s "
13686  "ssl_verify_peer requires setting "
13687  "either ssl_ca_path or ssl_ca_file. Is any of them "
13688  "present in "
13689  "the .conf file?",
13690  ssl_error());
13691  return 0;
13692  }
13693  }
13694 
13695  if (1 == mg_atomic_inc(p_reload_lock)) {
13696  if (ssl_use_pem_file(conn->ctx, pem, chain) == 0) {
13697  return 0;
13698  }
13699  *p_reload_lock = 0;
13700  }
13701  }
13702  /* lock while cert is reloading */
13703  while (*p_reload_lock) {
13704  sleep(1);
13705  }
13706 
13707  return 1;
13708 }
13709 
13710 #ifdef OPENSSL_API_1_1
13711 #else
13712 static pthread_mutex_t *ssl_mutexes;
13713 #endif /* OPENSSL_API_1_1 */
13714 
13715 static int
13716 sslize(struct mg_connection *conn,
13717  SSL_CTX *s,
13718  int (*func)(SSL *),
13719  volatile int *stop_server)
13720 {
13721  int ret, err;
13722  int short_trust;
13723  unsigned i;
13724 
13725  if (!conn) {
13726  return 0;
13727  }
13728 
13729  short_trust =
13730  (conn->ctx->config[SSL_SHORT_TRUST] != NULL)
13731  && (mg_strcasecmp(conn->ctx->config[SSL_SHORT_TRUST], "yes") == 0);
13732 
13733  if (short_trust) {
13734  int trust_ret = refresh_trust(conn);
13735  if (!trust_ret) {
13736  return trust_ret;
13737  }
13738  }
13739 
13740  conn->ssl = SSL_new(s);
13741  if (conn->ssl == NULL) {
13742  return 0;
13743  }
13744  SSL_set_app_data(conn->ssl, (char *)conn);
13745 
13746  ret = SSL_set_fd(conn->ssl, conn->client.sock);
13747  if (ret != 1) {
13748  err = SSL_get_error(conn->ssl, ret);
13749  (void)err; /* TODO: set some error message */
13750  SSL_free(conn->ssl);
13751  conn->ssl = NULL;
13752 /* Avoid CRYPTO_cleanup_all_ex_data(); See discussion:
13753  * https://wiki.openssl.org/index.php/Talk:Library_Initialization */
13754 #ifndef OPENSSL_API_1_1
13755  ERR_remove_state(0);
13756 #endif
13757  return 0;
13758  }
13759 
13760  /* SSL functions may fail and require to be called again:
13761  * see https://www.openssl.org/docs/manmaster/ssl/SSL_get_error.html
13762  * Here "func" could be SSL_connect or SSL_accept. */
13763  for (i = 16; i <= 1024; i *= 2) {
13764  ret = func(conn->ssl);
13765  if (ret != 1) {
13766  err = SSL_get_error(conn->ssl, ret);
13767  if ((err == SSL_ERROR_WANT_CONNECT)
13768  || (err == SSL_ERROR_WANT_ACCEPT)
13769  || (err == SSL_ERROR_WANT_READ)
13770  || (err == SSL_ERROR_WANT_WRITE)) {
13771  /* Need to retry the function call "later".
13772  * See https://linux.die.net/man/3/ssl_get_error
13773  * This is typical for non-blocking sockets. */
13774  if (*stop_server) {
13775  /* Don't wait if the server is going to be stopped. */
13776  break;
13777  }
13778  mg_sleep(i);
13779 
13780  } else if (err == SSL_ERROR_SYSCALL) {
13781  /* This is an IO error. Look at errno. */
13782  err = errno;
13783  /* TODO: set some error message */
13784  (void)err;
13785  break;
13786  } else {
13787  /* This is an SSL specific error */
13788  /* TODO: set some error message */
13789  break;
13790  }
13791 
13792  } else {
13793  /* success */
13794  break;
13795  }
13796  }
13797 
13798  if (ret != 1) {
13799  SSL_free(conn->ssl);
13800  conn->ssl = NULL;
13801 /* Avoid CRYPTO_cleanup_all_ex_data(); See discussion:
13802  * https://wiki.openssl.org/index.php/Talk:Library_Initialization */
13803 #ifndef OPENSSL_API_1_1
13804  ERR_remove_state(0);
13805 #endif
13806  return 0;
13807  }
13808 
13809  return 1;
13810 }
13811 
13812 
13813 /* Return OpenSSL error message (from CRYPTO lib) */
13814 static const char *
13816 {
13817  unsigned long err;
13818  err = ERR_get_error();
13819  return ((err == 0) ? "" : ERR_error_string(err, NULL));
13820 }
13821 
13822 
13823 static int
13824 hexdump2string(void *mem, int memlen, char *buf, int buflen)
13825 {
13826  int i;
13827  const char hexdigit[] = "0123456789abcdef";
13828 
13829  if ((memlen <= 0) || (buflen <= 0)) {
13830  return 0;
13831  }
13832  if (buflen < (3 * memlen)) {
13833  return 0;
13834  }
13835 
13836  for (i = 0; i < memlen; i++) {
13837  if (i > 0) {
13838  buf[3 * i - 1] = ' ';
13839  }
13840  buf[3 * i] = hexdigit[(((uint8_t *)mem)[i] >> 4) & 0xF];
13841  buf[3 * i + 1] = hexdigit[((uint8_t *)mem)[i] & 0xF];
13842  }
13843  buf[3 * memlen - 1] = 0;
13844 
13845  return 1;
13846 }
13847 
13848 
13849 static void
13850 ssl_get_client_cert_info(struct mg_connection *conn)
13851 {
13852  X509 *cert = SSL_get_peer_certificate(conn->ssl);
13853  if (cert) {
13854  char str_subject[1024];
13855  char str_issuer[1024];
13856  char str_finger[1024];
13857  unsigned char buf[256];
13858  char *str_serial = NULL;
13859  unsigned int ulen;
13860  int ilen;
13861  unsigned char *tmp_buf;
13862  unsigned char *tmp_p;
13863 
13864  /* Handle to algorithm used for fingerprint */
13865  const EVP_MD *digest = EVP_get_digestbyname("sha1");
13866 
13867  /* Get Subject and issuer */
13868  X509_NAME *subj = X509_get_subject_name(cert);
13869  X509_NAME *iss = X509_get_issuer_name(cert);
13870 
13871  /* Get serial number */
13872  ASN1_INTEGER *serial = X509_get_serialNumber(cert);
13873 
13874  /* Translate serial number to a hex string */
13875  BIGNUM *serial_bn = ASN1_INTEGER_to_BN(serial, NULL);
13876  str_serial = BN_bn2hex(serial_bn);
13877  BN_free(serial_bn);
13878 
13879  /* Translate subject and issuer to a string */
13880  (void)X509_NAME_oneline(subj, str_subject, (int)sizeof(str_subject));
13881  (void)X509_NAME_oneline(iss, str_issuer, (int)sizeof(str_issuer));
13882 
13883  /* Calculate SHA1 fingerprint and store as a hex string */
13884  ulen = 0;
13885 
13886  /* ASN1_digest is deprecated. Do the calculation manually,
13887  * using EVP_Digest. */
13888  ilen = i2d_X509(cert, NULL);
13889  tmp_buf =
13890  (ilen > 0)
13891  ? (unsigned char *)mg_malloc_ctx((unsigned)ilen + 1, conn->ctx)
13892  : NULL;
13893  if (tmp_buf) {
13894  tmp_p = tmp_buf;
13895  (void)i2d_X509(cert, &tmp_p);
13896  if (!EVP_Digest(
13897  tmp_buf, (unsigned)ilen, buf, &ulen, digest, NULL)) {
13898  ulen = 0;
13899  }
13900  mg_free(tmp_buf);
13901  }
13902 
13903  if (!hexdump2string(
13904  buf, (int)ulen, str_finger, (int)sizeof(str_finger))) {
13905  *str_finger = 0;
13906  }
13907 
13908  conn->request_info.client_cert = (struct mg_client_cert *)
13909  mg_malloc_ctx(sizeof(struct mg_client_cert), conn->ctx);
13910  if (conn->request_info.client_cert) {
13911  conn->request_info.client_cert->subject = mg_strdup(str_subject);
13912  conn->request_info.client_cert->issuer = mg_strdup(str_issuer);
13913  conn->request_info.client_cert->serial = mg_strdup(str_serial);
13914  conn->request_info.client_cert->finger = mg_strdup(str_finger);
13915  } else {
13916  mg_cry(conn,
13917  "Out of memory: Cannot allocate memory for client "
13918  "certificate");
13919  }
13920 
13921  /* Strings returned from bn_bn2hex must be freed using OPENSSL_free,
13922  * see https://linux.die.net/man/3/bn_bn2hex */
13923  OPENSSL_free(str_serial);
13924 
13925  /* Free certificate memory */
13926  X509_free(cert);
13927  }
13928 }
13929 
13930 
13931 #ifdef OPENSSL_API_1_1
13932 #else
13933 static void
13934 ssl_locking_callback(int mode, int mutex_num, const char *file, int line)
13935 {
13936  (void)line;
13937  (void)file;
13938 
13939  if (mode & 1) {
13940  /* 1 is CRYPTO_LOCK */
13941  (void)pthread_mutex_lock(&ssl_mutexes[mutex_num]);
13942  } else {
13943  (void)pthread_mutex_unlock(&ssl_mutexes[mutex_num]);
13944  }
13945 }
13946 #endif /* OPENSSL_API_1_1 */
13947 
13948 
13949 #if !defined(NO_SSL_DL)
13950 static void *
13951 load_dll(char *ebuf, size_t ebuf_len, const char *dll_name, struct ssl_func *sw)
13952 {
13953  union {
13954  void *p;
13955  void (*fp)(void);
13956  } u;
13957  void *dll_handle;
13958  struct ssl_func *fp;
13959  int ok;
13960  int truncated = 0;
13961 
13962  if ((dll_handle = dlopen(dll_name, RTLD_LAZY)) == NULL) {
13963  mg_snprintf(NULL,
13964  NULL, /* No truncation check for ebuf */
13965  ebuf,
13966  ebuf_len,
13967  "%s: cannot load %s",
13968  __func__,
13969  dll_name);
13970  return NULL;
13971  }
13972 
13973  ok = 1;
13974  for (fp = sw; fp->name != NULL; fp++) {
13975 #ifdef _WIN32
13976  /* GetProcAddress() returns pointer to function */
13977  u.fp = (void (*)(void))dlsym(dll_handle, fp->name);
13978 #else
13979  /* dlsym() on UNIX returns void *. ISO C forbids casts of data
13980  * pointers to function pointers. We need to use a union to make a
13981  * cast. */
13982  u.p = dlsym(dll_handle, fp->name);
13983 #endif /* _WIN32 */
13984  if (u.fp == NULL) {
13985  if (ok) {
13986  mg_snprintf(NULL,
13987  &truncated,
13988  ebuf,
13989  ebuf_len,
13990  "%s: %s: cannot find %s",
13991  __func__,
13992  dll_name,
13993  fp->name);
13994  ok = 0;
13995  } else {
13996  size_t cur_len = strlen(ebuf);
13997  if (!truncated) {
13998  mg_snprintf(NULL,
13999  &truncated,
14000  ebuf + cur_len,
14001  ebuf_len - cur_len - 3,
14002  ", %s",
14003  fp->name);
14004  if (truncated) {
14005  /* If truncated, add "..." */
14006  strcat(ebuf, "...");
14007  }
14008  }
14009  }
14010  /* Debug:
14011  * printf("Missing function: %s\n", fp->name); */
14012  } else {
14013  fp->ptr = u.fp;
14014  }
14015  }
14016 
14017  if (!ok) {
14018  (void)dlclose(dll_handle);
14019  return NULL;
14020  }
14021 
14022  return dll_handle;
14023 }
14024 
14025 
14026 static void *ssllib_dll_handle; /* Store the ssl library handle. */
14027 static void *cryptolib_dll_handle; /* Store the crypto library handle. */
14028 
14029 #endif /* NO_SSL_DL */
14030 
14031 
14032 #if defined(SSL_ALREADY_INITIALIZED)
14033 static int cryptolib_users = 1; /* Reference counter for crypto library. */
14034 #else
14035 static int cryptolib_users = 0; /* Reference counter for crypto library. */
14036 #endif
14037 
14038 
14039 static int
14040 initialize_ssl(char *ebuf, size_t ebuf_len)
14041 {
14042 #ifdef OPENSSL_API_1_1
14043  if (ebuf_len > 0) {
14044  ebuf[0] = 0;
14045  }
14046 
14047 #if !defined(NO_SSL_DL)
14048  if (!cryptolib_dll_handle) {
14049  cryptolib_dll_handle = load_dll(ebuf, ebuf_len, CRYPTO_LIB, crypto_sw);
14050  if (!cryptolib_dll_handle) {
14051  return 0;
14052  }
14053  }
14054 #endif /* NO_SSL_DL */
14055 
14056  if (mg_atomic_inc(&cryptolib_users) > 1) {
14057  return 1;
14058  }
14059 
14060 #else /* not OPENSSL_API_1_1 */
14061  int i;
14062  size_t size;
14063 
14064  if (ebuf_len > 0) {
14065  ebuf[0] = 0;
14066  }
14067 
14068 #if !defined(NO_SSL_DL)
14069  if (!cryptolib_dll_handle) {
14070  cryptolib_dll_handle = load_dll(ebuf, ebuf_len, CRYPTO_LIB, crypto_sw);
14071  if (!cryptolib_dll_handle) {
14072  return 0;
14073  }
14074  }
14075 #endif /* NO_SSL_DL */
14076 
14077  if (mg_atomic_inc(&cryptolib_users) > 1) {
14078  return 1;
14079  }
14080 
14081  /* Initialize locking callbacks, needed for thread safety.
14082  * http://www.openssl.org/support/faq.html#PROG1
14083  */
14084  i = CRYPTO_num_locks();
14085  if (i < 0) {
14086  i = 0;
14087  }
14088  size = sizeof(pthread_mutex_t) * ((size_t)(i));
14089 
14090  if (size == 0) {
14091  ssl_mutexes = NULL;
14092  } else if ((ssl_mutexes = (pthread_mutex_t *)mg_malloc(size)) == NULL) {
14093  mg_snprintf(NULL,
14094  NULL, /* No truncation check for ebuf */
14095  ebuf,
14096  ebuf_len,
14097  "%s: cannot allocate mutexes: %s",
14098  __func__,
14099  ssl_error());
14100 
14101  return 0;
14102  }
14103 
14104  for (i = 0; i < CRYPTO_num_locks(); i++) {
14105  pthread_mutex_init(&ssl_mutexes[i], &pthread_mutex_attr);
14106  }
14107 
14110 #endif /* OPENSSL_API_1_1 */
14111 
14112  return 1;
14113 }
14114 
14115 
14116 static int
14117 ssl_use_pem_file(struct mg_context *ctx, const char *pem, const char *chain)
14118 {
14119  if (SSL_CTX_use_certificate_file(ctx->ssl_ctx, pem, 1) == 0) {
14120  mg_cry(fc(ctx),
14121  "%s: cannot open certificate file %s: %s",
14122  __func__,
14123  pem,
14124  ssl_error());
14125  return 0;
14126  }
14127 
14128  /* could use SSL_CTX_set_default_passwd_cb_userdata */
14129  if (SSL_CTX_use_PrivateKey_file(ctx->ssl_ctx, pem, 1) == 0) {
14130  mg_cry(fc(ctx),
14131  "%s: cannot open private key file %s: %s",
14132  __func__,
14133  pem,
14134  ssl_error());
14135  return 0;
14136  }
14137 
14138  if (SSL_CTX_check_private_key(ctx->ssl_ctx) == 0) {
14139  mg_cry(fc(ctx),
14140  "%s: certificate and private key do not match: %s",
14141  __func__,
14142  pem);
14143  return 0;
14144  }
14145 
14146  /* In contrast to OpenSSL, wolfSSL does not support certificate
14147  * chain files that contain private keys and certificates in
14148  * SSL_CTX_use_certificate_chain_file.
14149  * The CivetWeb-Server used pem-Files that contained both information.
14150  * In order to make wolfSSL work, it is split in two files.
14151  * One file that contains key and certificate used by the server and
14152  * an optional chain file for the ssl stack.
14153  */
14154  if (chain) {
14155  if (SSL_CTX_use_certificate_chain_file(ctx->ssl_ctx, chain) == 0) {
14156  mg_cry(fc(ctx),
14157  "%s: cannot use certificate chain file %s: %s",
14158  __func__,
14159  pem,
14160  ssl_error());
14161  return 0;
14162  }
14163  }
14164  return 1;
14165 }
14166 
14167 
14168 #ifdef OPENSSL_API_1_1
14169 static unsigned long
14170 ssl_get_protocol(int version_id)
14171 {
14172  long unsigned ret = SSL_OP_ALL;
14173  if (version_id > 0)
14174  ret |= SSL_OP_NO_SSLv2;
14175  if (version_id > 1)
14176  ret |= SSL_OP_NO_SSLv3;
14177  if (version_id > 2)
14178  ret |= SSL_OP_NO_TLSv1;
14179  if (version_id > 3)
14180  ret |= SSL_OP_NO_TLSv1_1;
14181  return ret;
14182 }
14183 #else
14184 static long
14185 ssl_get_protocol(int version_id)
14186 {
14187  long ret = SSL_OP_ALL;
14188  if (version_id > 0)
14189  ret |= SSL_OP_NO_SSLv2;
14190  if (version_id > 1)
14191  ret |= SSL_OP_NO_SSLv3;
14192  if (version_id > 2)
14193  ret |= SSL_OP_NO_TLSv1;
14194  if (version_id > 3)
14195  ret |= SSL_OP_NO_TLSv1_1;
14196  return ret;
14197 }
14198 #endif /* OPENSSL_API_1_1 */
14199 
14200 
14201 /* SSL callback documentation:
14202  * https://www.openssl.org/docs/man1.1.0/ssl/SSL_set_info_callback.html
14203  * https://linux.die.net/man/3/ssl_set_info_callback */
14204 static void
14205 ssl_info_callback(const SSL *ssl, int what, int ret)
14206 {
14207  (void)ret;
14208 
14209  if (what & SSL_CB_HANDSHAKE_START) {
14210  SSL_get_app_data((SSL *)ssl);
14211  }
14212  if (what & SSL_CB_HANDSHAKE_DONE) {
14213  /* TODO: check for openSSL 1.1 */
14214  //#define SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS 0x0001
14215  // ssl->s3->flags |= SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS;
14216  }
14217 }
14218 
14219 
14220 /* Dynamically load SSL library. Set up ctx->ssl_ctx pointer. */
14221 static int
14222 set_ssl_option(struct mg_context *ctx)
14223 {
14224  const char *pem;
14225  const char *chain;
14226  int callback_ret;
14227  int should_verify_peer;
14228  int peer_certificate_optional;
14229  const char *ca_path;
14230  const char *ca_file;
14231  int use_default_verify_paths;
14232  int verify_depth;
14233  time_t now_rt = time(NULL);
14234  struct timespec now_mt;
14235  md5_byte_t ssl_context_id[16];
14236  md5_state_t md5state;
14237  int protocol_ver;
14238  char ebuf[128];
14239 
14240  /* If PEM file is not specified and the init_ssl callback
14241  * is not specified, skip SSL initialization. */
14242  if (!ctx) {
14243  return 0;
14244  }
14245  if ((pem = ctx->config[SSL_CERTIFICATE]) == NULL
14246  && ctx->callbacks.init_ssl == NULL) {
14247  return 1;
14248  }
14249  chain = ctx->config[SSL_CERTIFICATE_CHAIN];
14250  if (chain == NULL) {
14251  chain = pem;
14252  }
14253  if ((chain != NULL) && (*chain == 0)) {
14254  chain = NULL;
14255  }
14256 
14257  if (!initialize_ssl(ebuf, sizeof(ebuf))) {
14258  mg_cry(fc(ctx), "%s", ebuf);
14259  return 0;
14260  }
14261 
14262 #if !defined(NO_SSL_DL)
14263  if (!ssllib_dll_handle) {
14264  ssllib_dll_handle = load_dll(ebuf, sizeof(ebuf), SSL_LIB, ssl_sw);
14265  if (!ssllib_dll_handle) {
14266  mg_cry(fc(ctx), "%s", ebuf);
14267  return 0;
14268  }
14269  }
14270 #endif /* NO_SSL_DL */
14271 
14272 #ifdef OPENSSL_API_1_1
14273  /* Initialize SSL library */
14274  OPENSSL_init_ssl(0, NULL);
14275  OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS
14277  NULL);
14278 
14279  if ((ctx->ssl_ctx = SSL_CTX_new(TLS_server_method())) == NULL) {
14280  mg_cry(fc(ctx), "SSL_CTX_new (server) error: %s", ssl_error());
14281  return 0;
14282  }
14283 #else
14284  /* Initialize SSL library */
14285  SSL_library_init();
14287 
14288  if ((ctx->ssl_ctx = SSL_CTX_new(SSLv23_server_method())) == NULL) {
14289  mg_cry(fc(ctx), "SSL_CTX_new (server) error: %s", ssl_error());
14290  return 0;
14291  }
14292 #endif /* OPENSSL_API_1_1 */
14293 
14294  SSL_CTX_clear_options(ctx->ssl_ctx,
14296  | SSL_OP_NO_TLSv1_1);
14297  protocol_ver = atoi(ctx->config[SSL_PROTOCOL_VERSION]);
14298  SSL_CTX_set_options(ctx->ssl_ctx, ssl_get_protocol(protocol_ver));
14301  SSL_CTX_set_options(ctx->ssl_ctx,
14304 #if !defined(NO_SSL_DL)
14305  SSL_CTX_set_ecdh_auto(ctx->ssl_ctx, 1);
14306 #endif /* NO_SSL_DL */
14307 
14308  /* Depending on the OpenSSL version, the callback may be
14309  * 'void (*)(SSL *, int, int)' or 'void (*)(const SSL *, int, int)'
14310  * yielding in an "incompatible-pointer-type" warning for the other
14311  * version. It seems to be "unclear" what is correct:
14312  * https://bugs.launchpad.net/ubuntu/+source/openssl/+bug/1147526
14313  * https://www.openssl.org/docs/man1.0.2/ssl/ssl.html
14314  * https://www.openssl.org/docs/man1.1.0/ssl/ssl.html
14315  * https://github.com/openssl/openssl/blob/1d97c8435171a7af575f73c526d79e1ef0ee5960/ssl/ssl.h#L1173
14316  * Disable this warning here.
14317  * Alternative would be a version dependent ssl_info_callback and
14318  * a const-cast to call 'char *SSL_get_app_data(SSL *ssl)' there.
14319  */
14321 
14322  /* If a callback has been specified, call it. */
14323  callback_ret =
14324  (ctx->callbacks.init_ssl == NULL)
14325  ? 0
14326  : (ctx->callbacks.init_ssl(ctx->ssl_ctx, ctx->user_data));
14327 
14328  /* If callback returns 0, civetweb sets up the SSL certificate.
14329  * If it returns 1, civetweb assumes the calback already did this.
14330  * If it returns -1, initializing ssl fails. */
14331  if (callback_ret < 0) {
14332  mg_cry(fc(ctx), "SSL callback returned error: %i", callback_ret);
14333  return 0;
14334  }
14335  if (callback_ret > 0) {
14336  if (pem != NULL) {
14337  (void)SSL_CTX_use_certificate_chain_file(ctx->ssl_ctx, pem);
14338  }
14339  return 1;
14340  }
14341 
14342  /* Use some UID as session context ID. */
14343  md5_init(&md5state);
14344  md5_append(&md5state, (const md5_byte_t *)&now_rt, sizeof(now_rt));
14345  clock_gettime(CLOCK_MONOTONIC, &now_mt);
14346  md5_append(&md5state, (const md5_byte_t *)&now_mt, sizeof(now_mt));
14347  md5_append(&md5state,
14348  (const md5_byte_t *)ctx->config[LISTENING_PORTS],
14349  strlen(ctx->config[LISTENING_PORTS]));
14350  md5_append(&md5state, (const md5_byte_t *)ctx, sizeof(*ctx));
14351  md5_finish(&md5state, ssl_context_id);
14352 
14353  SSL_CTX_set_session_id_context(ctx->ssl_ctx,
14354  (const unsigned char *)&ssl_context_id,
14355  sizeof(ssl_context_id));
14356 
14357  if (pem != NULL) {
14358  if (!ssl_use_pem_file(ctx, pem, chain)) {
14359  return 0;
14360  }
14361  }
14362 
14363  /* Should we support client certificates? */
14364  /* Default is "no". */
14365  should_verify_peer = 0;
14366  peer_certificate_optional = 0;
14367  if (ctx->config[SSL_DO_VERIFY_PEER] != NULL) {
14368  if (mg_strcasecmp(ctx->config[SSL_DO_VERIFY_PEER], "yes") == 0) {
14369  /* Yes, they are mandatory */
14370  should_verify_peer = 1;
14371  peer_certificate_optional = 0;
14372  } else if (mg_strcasecmp(ctx->config[SSL_DO_VERIFY_PEER], "optional")
14373  == 0) {
14374  /* Yes, they are optional */
14375  should_verify_peer = 1;
14376  peer_certificate_optional = 1;
14377  }
14378  }
14379 
14380  use_default_verify_paths =
14381  (ctx->config[SSL_DEFAULT_VERIFY_PATHS] != NULL)
14382  && (mg_strcasecmp(ctx->config[SSL_DEFAULT_VERIFY_PATHS], "yes") == 0);
14383 
14384  if (should_verify_peer) {
14385  ca_path = ctx->config[SSL_CA_PATH];
14386  ca_file = ctx->config[SSL_CA_FILE];
14387  if (SSL_CTX_load_verify_locations(ctx->ssl_ctx, ca_file, ca_path)
14388  != 1) {
14389  mg_cry(fc(ctx),
14390  "SSL_CTX_load_verify_locations error: %s "
14391  "ssl_verify_peer requires setting "
14392  "either ssl_ca_path or ssl_ca_file. Is any of them "
14393  "present in "
14394  "the .conf file?",
14395  ssl_error());
14396  return 0;
14397  }
14398 
14399  if (peer_certificate_optional) {
14400  SSL_CTX_set_verify(ctx->ssl_ctx, SSL_VERIFY_PEER, NULL);
14401  } else {
14402  SSL_CTX_set_verify(ctx->ssl_ctx,
14405  NULL);
14406  }
14407 
14408  if (use_default_verify_paths
14409  && (SSL_CTX_set_default_verify_paths(ctx->ssl_ctx) != 1)) {
14410  mg_cry(fc(ctx),
14411  "SSL_CTX_set_default_verify_paths error: %s",
14412  ssl_error());
14413  return 0;
14414  }
14415 
14416  if (ctx->config[SSL_VERIFY_DEPTH]) {
14417  verify_depth = atoi(ctx->config[SSL_VERIFY_DEPTH]);
14418  SSL_CTX_set_verify_depth(ctx->ssl_ctx, verify_depth);
14419  }
14420  }
14421 
14422  if (ctx->config[SSL_CIPHER_LIST] != NULL) {
14423  if (SSL_CTX_set_cipher_list(ctx->ssl_ctx, ctx->config[SSL_CIPHER_LIST])
14424  != 1) {
14425  mg_cry(fc(ctx), "SSL_CTX_set_cipher_list error: %s", ssl_error());
14426  }
14427  }
14428 
14429  return 1;
14430 }
14431 
14432 
14433 static void
14435 {
14436 #ifdef OPENSSL_API_1_1
14437 
14438  if (mg_atomic_dec(&cryptolib_users) == 0) {
14439 
14440  /* Shutdown according to
14441  * https://wiki.openssl.org/index.php/Library_Initialization#Cleanup
14442  * http://stackoverflow.com/questions/29845527/how-to-properly-uninitialize-openssl
14443  */
14445 #else
14446  int i;
14447 
14448  if (mg_atomic_dec(&cryptolib_users) == 0) {
14449 
14450  /* Shutdown according to
14451  * https://wiki.openssl.org/index.php/Library_Initialization#Cleanup
14452  * http://stackoverflow.com/questions/29845527/how-to-properly-uninitialize-openssl
14453  */
14455  CRYPTO_set_id_callback(NULL);
14456  ENGINE_cleanup();
14458  ERR_free_strings();
14459  EVP_cleanup();
14461  ERR_remove_state(0);
14462 
14463  for (i = 0; i < CRYPTO_num_locks(); i++) {
14464  pthread_mutex_destroy(&ssl_mutexes[i]);
14465  }
14466  mg_free(ssl_mutexes);
14467  ssl_mutexes = NULL;
14468 #endif /* OPENSSL_API_1_1 */
14469  }
14470 }
14471 #endif /* !NO_SSL */
14472 
14473 
14474 static int
14475 set_gpass_option(struct mg_context *ctx)
14476 {
14477  if (ctx) {
14478  struct mg_file file = STRUCT_FILE_INITIALIZER;
14479  const char *path = ctx->config[GLOBAL_PASSWORDS_FILE];
14480  if ((path != NULL) && !mg_stat(fc(ctx), path, &file.stat)) {
14481  mg_cry(fc(ctx), "Cannot open %s: %s", path, strerror(ERRNO));
14482  return 0;
14483  }
14484  return 1;
14485  }
14486  return 0;
14487 }
14488 
14489 
14490 static int
14491 set_acl_option(struct mg_context *ctx)
14492 {
14493  return check_acl(ctx, (uint32_t)0x7f000001UL) != -1;
14494 }
14495 
14496 
14497 static void
14498 reset_per_request_attributes(struct mg_connection *conn)
14499 {
14500  if (!conn) {
14501  return;
14502  }
14503  conn->connection_type =
14504  CONNECTION_TYPE_INVALID; /* Not yet a valid request/response */
14505 
14506  conn->num_bytes_sent = conn->consumed_content = 0;
14507 
14508  conn->path_info = NULL;
14509  conn->status_code = -1;
14510  conn->content_len = -1;
14511  conn->is_chunked = 0;
14512  conn->must_close = 0;
14513  conn->request_len = 0;
14514  conn->throttle = 0;
14515  conn->data_len = 0;
14516  conn->chunk_remainder = 0;
14517  conn->accept_gzip = 0;
14518 
14519  conn->response_info.content_length = conn->request_info.content_length = -1;
14520  conn->response_info.http_version = conn->request_info.http_version = NULL;
14521  conn->response_info.num_headers = conn->request_info.num_headers = 0;
14522  conn->response_info.status_text = NULL;
14523  conn->response_info.status_code = 0;
14524 
14525  conn->request_info.remote_user = NULL;
14526  conn->request_info.request_method = NULL;
14527  conn->request_info.request_uri = NULL;
14528  conn->request_info.local_uri = NULL;
14529 
14530 #if defined(MG_LEGACY_INTERFACE)
14531  /* Legacy before split into local_uri and request_uri */
14532  conn->request_info.uri = NULL;
14533 #endif
14534 }
14535 
14536 
14537 #if 0
14538 /* Note: set_sock_timeout is not required for non-blocking sockets.
14539  * Leave this function here (commented out) for reference until
14540  * CivetWeb 1.9 is tested, and the tests confirme this function is
14541  * no longer required.
14542 */
14543 static int
14544 set_sock_timeout(SOCKET sock, int milliseconds)
14545 {
14546  int r0 = 0, r1, r2;
14547 
14548 #ifdef _WIN32
14549  /* Windows specific */
14550 
14551  DWORD tv = (DWORD)milliseconds;
14552 
14553 #else
14554  /* Linux, ... (not Windows) */
14555 
14556  struct timeval tv;
14557 
14558 /* TCP_USER_TIMEOUT/RFC5482 (http://tools.ietf.org/html/rfc5482):
14559  * max. time waiting for the acknowledged of TCP data before the connection
14560  * will be forcefully closed and ETIMEDOUT is returned to the application.
14561  * If this option is not set, the default timeout of 20-30 minutes is used.
14562 */
14563 /* #define TCP_USER_TIMEOUT (18) */
14564 
14565 #if defined(TCP_USER_TIMEOUT)
14566  unsigned int uto = (unsigned int)milliseconds;
14567  r0 = setsockopt(sock, 6, TCP_USER_TIMEOUT, (const void *)&uto, sizeof(uto));
14568 #endif
14569 
14570  memset(&tv, 0, sizeof(tv));
14571  tv.tv_sec = milliseconds / 1000;
14572  tv.tv_usec = (milliseconds * 1000) % 1000000;
14573 
14574 #endif /* _WIN32 */
14575 
14576  r1 = setsockopt(
14577  sock, SOL_SOCKET, SO_RCVTIMEO, (SOCK_OPT_TYPE)&tv, sizeof(tv));
14578  r2 = setsockopt(
14579  sock, SOL_SOCKET, SO_SNDTIMEO, (SOCK_OPT_TYPE)&tv, sizeof(tv));
14580 
14581  return r0 || r1 || r2;
14582 }
14583 #endif
14584 
14585 
14586 static int
14587 set_tcp_nodelay(SOCKET sock, int nodelay_on)
14588 {
14589  if (setsockopt(sock,
14590  IPPROTO_TCP,
14591  TCP_NODELAY,
14592  (SOCK_OPT_TYPE)&nodelay_on,
14593  sizeof(nodelay_on)) != 0) {
14594  /* Error */
14595  return 1;
14596  }
14597  /* OK */
14598  return 0;
14599 }
14600 
14601 
14602 static void
14603 close_socket_gracefully(struct mg_connection *conn)
14604 {
14605 #if defined(_WIN32)
14606  char buf[MG_BUF_LEN];
14607  int n;
14608 #endif
14609  struct linger linger;
14610  int error_code = 0;
14611  int linger_timeout = -2;
14612  socklen_t opt_len = sizeof(error_code);
14613 
14614  if (!conn) {
14615  return;
14616  }
14617 
14618  /* http://msdn.microsoft.com/en-us/library/ms739165(v=vs.85).aspx:
14619  * "Note that enabling a nonzero timeout on a nonblocking socket
14620  * is not recommended.", so set it to blocking now */
14621  set_blocking_mode(conn->client.sock);
14622 
14623  /* Send FIN to the client */
14624  shutdown(conn->client.sock, SHUTDOWN_WR);
14625 
14626 
14627 #if defined(_WIN32)
14628  /* Read and discard pending incoming data. If we do not do that and
14629  * close
14630  * the socket, the data in the send buffer may be discarded. This
14631  * behaviour is seen on Windows, when client keeps sending data
14632  * when server decides to close the connection; then when client
14633  * does recv() it gets no data back. */
14634  do {
14635  n = pull_inner(NULL, conn, buf, sizeof(buf), /* Timeout in s: */ 1.0);
14636  } while (n > 0);
14637 #endif
14638 
14639  if (conn->ctx->config[LINGER_TIMEOUT]) {
14640  linger_timeout = atoi(conn->ctx->config[LINGER_TIMEOUT]);
14641  }
14642 
14643  /* Set linger option according to configuration */
14644  if (linger_timeout >= 0) {
14645  /* Set linger option to avoid socket hanging out after close. This
14646  * prevent ephemeral port exhaust problem under high QPS. */
14647  linger.l_onoff = 1;
14648 
14649 #if defined(_MSC_VER)
14650 #pragma warning(push)
14651 #pragma warning(disable : 4244)
14652 #endif
14653 #if defined(__GNUC__) || defined(__MINGW32__)
14654 #pragma GCC diagnostic push
14655 #pragma GCC diagnostic ignored "-Wconversion"
14656 #endif
14657  /* Data type of linger structure elements may differ,
14658  * so we don't know what cast we need here.
14659  * Disable type conversion warnings. */
14660 
14661  linger.l_linger = (linger_timeout + 999) / 1000;
14662 
14663 #if defined(__GNUC__) || defined(__MINGW32__)
14664 #pragma GCC diagnostic pop
14665 #endif
14666 #if defined(_MSC_VER)
14667 #pragma warning(pop)
14668 #endif
14669 
14670  } else {
14671  linger.l_onoff = 0;
14672  linger.l_linger = 0;
14673  }
14674 
14675  if (linger_timeout < -1) {
14676  /* Default: don't configure any linger */
14677  } else if (getsockopt(conn->client.sock,
14678  SOL_SOCKET,
14679  SO_ERROR,
14680  (char *)&error_code,
14681  &opt_len) != 0) {
14682  /* Cannot determine if socket is already closed. This should
14683  * not occur and never did in a test. Log an error message
14684  * and continue. */
14685  mg_cry(conn,
14686  "%s: getsockopt(SOL_SOCKET SO_ERROR) failed: %s",
14687  __func__,
14688  strerror(ERRNO));
14689  } else if (error_code == ECONNRESET) {
14690  /* Socket already closed by client/peer, close socket without linger
14691  */
14692  } else {
14693 
14694  /* Set linger timeout */
14695  if (setsockopt(conn->client.sock,
14696  SOL_SOCKET,
14697  SO_LINGER,
14698  (char *)&linger,
14699  sizeof(linger)) != 0) {
14700  mg_cry(conn,
14701  "%s: setsockopt(SOL_SOCKET SO_LINGER(%i,%i)) failed: %s",
14702  __func__,
14703  linger.l_onoff,
14704  linger.l_linger,
14705  strerror(ERRNO));
14706  }
14707  }
14708 
14709  /* Now we know that our FIN is ACK-ed, safe to close */
14710  closesocket(conn->client.sock);
14711  conn->client.sock = INVALID_SOCKET;
14712 }
14713 
14714 
14715 static void
14716 close_connection(struct mg_connection *conn)
14717 {
14718 #if defined(USE_SERVER_STATS)
14719  conn->conn_state = 6; /* to close */
14720 #endif
14721 
14722 #if defined(USE_LUA) && defined(USE_WEBSOCKET)
14723  if (conn->lua_websocket_state) {
14724  lua_websocket_close(conn, conn->lua_websocket_state);
14725  conn->lua_websocket_state = NULL;
14726  }
14727 #endif
14728 
14729  mg_lock_connection(conn);
14730 
14731  /* Set close flag, so keep-alive loops will stop */
14732  conn->must_close = 1;
14733 
14734  /* call the connection_close callback if assigned */
14735  if (conn->ctx->callbacks.connection_close != NULL) {
14736  if (conn->ctx->context_type == CONTEXT_SERVER) {
14737  conn->ctx->callbacks.connection_close(conn);
14738  }
14739  }
14740 
14741  /* Reset user data, after close callback is called.
14742  * Do not reuse it. If the user needs a destructor,
14743  * it must be done in the connection_close callback. */
14744  mg_set_user_connection_data(conn, NULL);
14745 
14746 
14747 #if defined(USE_SERVER_STATS)
14748  conn->conn_state = 7; /* closing */
14749 #endif
14750 
14751 #ifndef NO_SSL
14752  if (conn->ssl != NULL) {
14753  /* Run SSL_shutdown twice to ensure completly close SSL connection
14754  */
14755  SSL_shutdown(conn->ssl);
14756  SSL_free(conn->ssl);
14757 /* Avoid CRYPTO_cleanup_all_ex_data(); See discussion:
14758  * https://wiki.openssl.org/index.php/Talk:Library_Initialization */
14759 #ifndef OPENSSL_API_1_1
14760  ERR_remove_state(0);
14761 #endif
14762  conn->ssl = NULL;
14763  }
14764 #endif
14765  if (conn->client.sock != INVALID_SOCKET) {
14767  conn->client.sock = INVALID_SOCKET;
14768  }
14769 
14770  mg_unlock_connection(conn);
14771 
14772 #if defined(USE_SERVER_STATS)
14773  conn->conn_state = 8; /* closed */
14774 #endif
14775 }
14776 
14777 
14778 void
14779 mg_close_connection(struct mg_connection *conn)
14780 {
14781 #if defined(USE_WEBSOCKET)
14782  struct mg_context *client_ctx = NULL;
14783 #endif /* defined(USE_WEBSOCKET) */
14784 
14785  if ((conn == NULL) || (conn->ctx == NULL)) {
14786  return;
14787  }
14788 
14789 #if defined(USE_WEBSOCKET)
14790  if (conn->ctx->context_type == CONTEXT_SERVER) {
14791  if (conn->in_websocket_handling) {
14792  /* Set close flag, so the server thread can exit. */
14793  conn->must_close = 1;
14794  return;
14795  }
14796  }
14797  if (conn->ctx->context_type == CONTEXT_WS_CLIENT) {
14798 
14799  unsigned int i;
14800 
14801  /* ws/wss client */
14802  client_ctx = conn->ctx;
14803 
14804  /* client context: loops must end */
14805  conn->ctx->stop_flag = 1;
14806  conn->must_close = 1;
14807 
14808  /* We need to get the client thread out of the select/recv call
14809  * here. */
14810  /* Since we use a sleep quantum of some seconds to check for recv
14811  * timeouts, we will just wait a few seconds in mg_join_thread. */
14812 
14813  /* join worker thread */
14814  for (i = 0; i < client_ctx->cfg_worker_threads; i++) {
14815  if (client_ctx->worker_threadids[i] != 0) {
14816  mg_join_thread(client_ctx->worker_threadids[i]);
14817  }
14818  }
14819  }
14820 #endif /* defined(USE_WEBSOCKET) */
14821 
14822  close_connection(conn);
14823 
14824 #ifndef NO_SSL
14825  if (conn->client_ssl_ctx != NULL) {
14826  SSL_CTX_free((SSL_CTX *)conn->client_ssl_ctx);
14827  }
14828 #endif
14829 
14830 #if defined(USE_WEBSOCKET)
14831  if (client_ctx != NULL) {
14832  /* free context */
14833  mg_free(client_ctx->worker_threadids);
14834  mg_free(client_ctx);
14835  (void)pthread_mutex_destroy(&conn->mutex);
14836  mg_free(conn);
14837  } else if (conn->ctx->context_type == CONTEXT_HTTP_CLIENT) {
14838  mg_free(conn);
14839  }
14840 #else
14841  if (conn->ctx->context_type == CONTEXT_HTTP_CLIENT) { /* Client */
14842  mg_free(conn);
14843  }
14844 #endif /* defined(USE_WEBSOCKET) */
14845 }
14846 
14847 
14848 /* Only for memory statistics */
14849 static struct mg_context common_client_context;
14850 
14851 
14852 static struct mg_connection *
14853 mg_connect_client_impl(const struct mg_client_options *client_options,
14854  int use_ssl,
14855  char *ebuf,
14856  size_t ebuf_len)
14857 {
14858  struct mg_connection *conn = NULL;
14859  SOCKET sock;
14860  union usa sa;
14861  struct sockaddr *psa;
14862  socklen_t len;
14863 
14864  unsigned max_req_size =
14865  (unsigned)atoi(config_options[MAX_REQUEST_SIZE].default_value);
14866 
14867  /* Size of structures, aligned to 8 bytes */
14868  size_t conn_size = ((sizeof(struct mg_connection) + 7) >> 3) << 3;
14869  size_t ctx_size = ((sizeof(struct mg_context) + 7) >> 3) << 3;
14870 
14871  conn = (struct mg_connection *)mg_calloc_ctx(1,
14872  conn_size + ctx_size
14873  + max_req_size,
14875 
14876  if (conn == NULL) {
14877  mg_snprintf(NULL,
14878  NULL, /* No truncation check for ebuf */
14879  ebuf,
14880  ebuf_len,
14881  "calloc(): %s",
14882  strerror(ERRNO));
14883  return NULL;
14884  }
14885 
14886  conn->ctx = (struct mg_context *)(((char *)conn) + conn_size);
14887  conn->buf = (((char *)conn) + conn_size + ctx_size);
14888  conn->buf_size = (int)max_req_size;
14889  conn->ctx->context_type = CONTEXT_HTTP_CLIENT;
14890 
14892  client_options->host,
14893  client_options->port,
14894  use_ssl,
14895  ebuf,
14896  ebuf_len,
14897  &sock,
14898  &sa)) {
14899  /* ebuf is set by connect_socket,
14900  * free all memory and return NULL; */
14901  mg_free(conn);
14902  return NULL;
14903  }
14904 
14905 #ifndef NO_SSL
14906 #ifdef OPENSSL_API_1_1
14907  if (use_ssl
14908  && (conn->client_ssl_ctx = SSL_CTX_new(TLS_client_method())) == NULL) {
14909  mg_snprintf(NULL,
14910  NULL, /* No truncation check for ebuf */
14911  ebuf,
14912  ebuf_len,
14913  "SSL_CTX_new error");
14914  closesocket(sock);
14915  mg_free(conn);
14916  return NULL;
14917  }
14918 #else
14919  if (use_ssl
14920  && (conn->client_ssl_ctx = SSL_CTX_new(SSLv23_client_method()))
14921  == NULL) {
14922  mg_snprintf(NULL,
14923  NULL, /* No truncation check for ebuf */
14924  ebuf,
14925  ebuf_len,
14926  "SSL_CTX_new error");
14927  closesocket(sock);
14928  mg_free(conn);
14929  return NULL;
14930  }
14931 #endif /* OPENSSL_API_1_1 */
14932 #endif /* NO_SSL */
14933 
14934 
14935 #ifdef USE_IPV6
14936  len = (sa.sa.sa_family == AF_INET) ? sizeof(conn->client.rsa.sin)
14937  : sizeof(conn->client.rsa.sin6);
14938  psa = (sa.sa.sa_family == AF_INET)
14939  ? (struct sockaddr *)&(conn->client.rsa.sin)
14940  : (struct sockaddr *)&(conn->client.rsa.sin6);
14941 #else
14942  len = sizeof(conn->client.rsa.sin);
14943  psa = (struct sockaddr *)&(conn->client.rsa.sin);
14944 #endif
14945 
14946  conn->client.sock = sock;
14947  conn->client.lsa = sa;
14948 
14949  if (getsockname(sock, psa, &len) != 0) {
14950  mg_cry(conn, "%s: getsockname() failed: %s", __func__, strerror(ERRNO));
14951  }
14952 
14953  conn->client.is_ssl = use_ssl ? 1 : 0;
14954  (void)pthread_mutex_init(&conn->mutex, &pthread_mutex_attr);
14955 
14956 #ifndef NO_SSL
14957  if (use_ssl) {
14958  common_client_context.ssl_ctx = conn->client_ssl_ctx;
14959 
14960  /* TODO: Check ssl_verify_peer and ssl_ca_path here.
14961  * SSL_CTX_set_verify call is needed to switch off server
14962  * certificate checking, which is off by default in OpenSSL and
14963  * on in yaSSL. */
14964  /* TODO: SSL_CTX_set_verify(conn->client_ssl_ctx,
14965  * SSL_VERIFY_PEER, verify_ssl_server); */
14966 
14967  if (client_options->client_cert) {
14969  client_options->client_cert,
14970  NULL)) {
14971  mg_snprintf(NULL,
14972  NULL, /* No truncation check for ebuf */
14973  ebuf,
14974  ebuf_len,
14975  "Can not use SSL client certificate");
14976  SSL_CTX_free(conn->client_ssl_ctx);
14977  closesocket(sock);
14978  mg_free(conn);
14979  return NULL;
14980  }
14981  }
14982 
14983  if (client_options->server_cert) {
14984  SSL_CTX_load_verify_locations(conn->client_ssl_ctx,
14985  client_options->server_cert,
14986  NULL);
14987  SSL_CTX_set_verify(conn->client_ssl_ctx, SSL_VERIFY_PEER, NULL);
14988  } else {
14989  SSL_CTX_set_verify(conn->client_ssl_ctx, SSL_VERIFY_NONE, NULL);
14990  }
14991 
14992  if (!sslize(conn,
14993  conn->client_ssl_ctx,
14994  SSL_connect,
14995  &(conn->ctx->stop_flag))) {
14996  mg_snprintf(NULL,
14997  NULL, /* No truncation check for ebuf */
14998  ebuf,
14999  ebuf_len,
15000  "SSL connection error");
15001  SSL_CTX_free(conn->client_ssl_ctx);
15002  closesocket(sock);
15003  mg_free(conn);
15004  return NULL;
15005  }
15006  }
15007 #endif
15008 
15009  if (0 != set_non_blocking_mode(sock)) {
15010  /* TODO: handle error */
15011  ;
15012  }
15013 
15014  return conn;
15015 }
15016 
15017 
15018 CIVETWEB_API struct mg_connection *
15019 mg_connect_client_secure(const struct mg_client_options *client_options,
15020  char *error_buffer,
15021  size_t error_buffer_size)
15022 {
15023  return mg_connect_client_impl(client_options,
15024  1,
15025  error_buffer,
15026  error_buffer_size);
15027 }
15028 
15029 
15030 struct mg_connection *
15031 mg_connect_client(const char *host,
15032  int port,
15033  int use_ssl,
15034  char *error_buffer,
15035  size_t error_buffer_size)
15036 {
15037  struct mg_client_options opts;
15038  memset(&opts, 0, sizeof(opts));
15039  opts.host = host;
15040  opts.port = port;
15041  return mg_connect_client_impl(&opts,
15042  use_ssl,
15043  error_buffer,
15044  error_buffer_size);
15045 }
15046 
15047 
15048 static const struct {
15049  const char *proto;
15050  size_t proto_len;
15051  unsigned default_port;
15052 } abs_uri_protocols[] = {{"http://", 7, 80},
15053  {"https://", 8, 443},
15054  {"ws://", 5, 80},
15055  {"wss://", 6, 443},
15056  {NULL, 0, 0}};
15057 
15058 
15059 /* Check if the uri is valid.
15060  * return 0 for invalid uri,
15061  * return 1 for *,
15062  * return 2 for relative uri,
15063  * return 3 for absolute uri without port,
15064  * return 4 for absolute uri with port */
15065 static int
15066 get_uri_type(const char *uri)
15067 {
15068  int i;
15069  const char *hostend, *portbegin;
15070  char *portend;
15071  unsigned long port;
15072 
15073  /* According to the HTTP standard
15074  * http://www.w3.org/Protocols/rfc2616/rfc2616-sec5.html#sec5.1.2
15075  * URI can be an asterisk (*) or should start with slash (relative uri),
15076  * or it should start with the protocol (absolute uri). */
15077  if ((uri[0] == '*') && (uri[1] == '\0')) {
15078  /* asterisk */
15079  return 1;
15080  }
15081 
15082  /* Valid URIs according to RFC 3986
15083  * (https://www.ietf.org/rfc/rfc3986.txt)
15084  * must only contain reserved characters :/?#[]@!$&'()*+,;=
15085  * and unreserved characters A-Z a-z 0-9 and -._~
15086  * and % encoded symbols.
15087  */
15088  for (i = 0; uri[i] != 0; i++) {
15089  if (uri[i] < 33) {
15090  /* control characters and spaces are invalid */
15091  return 0;
15092  }
15093  if (uri[i] > 126) {
15094  /* non-ascii characters must be % encoded */
15095  return 0;
15096  } else {
15097  switch (uri[i]) {
15098  case '"': /* 34 */
15099  case '<': /* 60 */
15100  case '>': /* 62 */
15101  case '\\': /* 92 */
15102  case '^': /* 94 */
15103  case '`': /* 96 */
15104  case '{': /* 123 */
15105  case '|': /* 124 */
15106  case '}': /* 125 */
15107  return 0;
15108  default:
15109  /* character is ok */
15110  break;
15111  }
15112  }
15113  }
15114 
15115  /* A relative uri starts with a / character */
15116  if (uri[0] == '/') {
15117  /* relative uri */
15118  return 2;
15119  }
15120 
15121  /* It could be an absolute uri: */
15122  /* This function only checks if the uri is valid, not if it is
15123  * addressing the current server. So civetweb can also be used
15124  * as a proxy server. */
15125  for (i = 0; abs_uri_protocols[i].proto != NULL; i++) {
15126  if (mg_strncasecmp(uri,
15128  abs_uri_protocols[i].proto_len) == 0) {
15129 
15130  hostend = strchr(uri + abs_uri_protocols[i].proto_len, '/');
15131  if (!hostend) {
15132  return 0;
15133  }
15134  portbegin = strchr(uri + abs_uri_protocols[i].proto_len, ':');
15135  if (!portbegin) {
15136  return 3;
15137  }
15138 
15139  port = strtoul(portbegin + 1, &portend, 10);
15140  if ((portend != hostend) || (port <= 0) || !is_valid_port(port)) {
15141  return 0;
15142  }
15143 
15144  return 4;
15145  }
15146  }
15147 
15148  return 0;
15149 }
15150 
15151 
15152 /* Return NULL or the relative uri at the current server */
15153 static const char *
15154 get_rel_url_at_current_server(const char *uri, const struct mg_connection *conn)
15155 {
15156  const char *server_domain;
15157  size_t server_domain_len;
15158  size_t request_domain_len = 0;
15159  unsigned long port = 0;
15160  int i, auth_domain_check_enabled;
15161  const char *hostbegin = NULL;
15162  const char *hostend = NULL;
15163  const char *portbegin;
15164  char *portend;
15165 
15166  auth_domain_check_enabled =
15167  !mg_strcasecmp(conn->ctx->config[ENABLE_AUTH_DOMAIN_CHECK], "yes");
15168 
15169  if (!auth_domain_check_enabled) {
15170  return 0;
15171  }
15172 
15173  server_domain = conn->ctx->config[AUTHENTICATION_DOMAIN];
15174  if (!server_domain) {
15175  return 0;
15176  }
15177  server_domain_len = strlen(server_domain);
15178  if (!server_domain_len) {
15179  return 0;
15180  }
15181 
15182  /* DNS is case insensitive, so use case insensitive string compare here
15183  */
15184  for (i = 0; abs_uri_protocols[i].proto != NULL; i++) {
15185  if (mg_strncasecmp(uri,
15187  abs_uri_protocols[i].proto_len) == 0) {
15188 
15189  hostbegin = uri + abs_uri_protocols[i].proto_len;
15190  hostend = strchr(hostbegin, '/');
15191  if (!hostend) {
15192  return 0;
15193  }
15194  portbegin = strchr(hostbegin, ':');
15195  if ((!portbegin) || (portbegin > hostend)) {
15196  port = abs_uri_protocols[i].default_port;
15197  request_domain_len = (size_t)(hostend - hostbegin);
15198  } else {
15199  port = strtoul(portbegin + 1, &portend, 10);
15200  if ((portend != hostend) || (port <= 0)
15201  || !is_valid_port(port)) {
15202  return 0;
15203  }
15204  request_domain_len = (size_t)(portbegin - hostbegin);
15205  }
15206  /* protocol found, port set */
15207  break;
15208  }
15209  }
15210 
15211  if (!port) {
15212  /* port remains 0 if the protocol is not found */
15213  return 0;
15214  }
15215 
15216 /* Check if the request is directed to a different server. */
15217 /* First check if the port is the same (IPv4 and IPv6). */
15218 #if defined(USE_IPV6)
15219  if (conn->client.lsa.sa.sa_family == AF_INET6) {
15220  if (ntohs(conn->client.lsa.sin6.sin6_port) != port) {
15221  /* Request is directed to a different port */
15222  return 0;
15223  }
15224  } else
15225 #endif
15226  {
15227  if (ntohs(conn->client.lsa.sin.sin_port) != port) {
15228  /* Request is directed to a different port */
15229  return 0;
15230  }
15231  }
15232 
15233  /* Finally check if the server corresponds to the authentication
15234  * domain of the server (the server domain).
15235  * Allow full matches (like http://mydomain.com/path/file.ext), and
15236  * allow subdomain matches (like http://www.mydomain.com/path/file.ext),
15237  * but do not allow substrings (like
15238  * http://notmydomain.com/path/file.ext
15239  * or http://mydomain.com.fake/path/file.ext).
15240  */
15241  if (auth_domain_check_enabled) {
15242  if ((request_domain_len == server_domain_len)
15243  && (!memcmp(server_domain, hostbegin, server_domain_len))) {
15244  /* Request is directed to this server - full name match. */
15245  } else {
15246  if (request_domain_len < (server_domain_len + 2)) {
15247  /* Request is directed to another server: The server name is
15248  * longer
15249  * than
15250  * the request name. Drop this case here to avoid overflows
15251  * in
15252  * the
15253  * following checks. */
15254  return 0;
15255  }
15256  if (hostbegin[request_domain_len - server_domain_len - 1] != '.') {
15257  /* Request is directed to another server: It could be a
15258  * substring
15259  * like notmyserver.com */
15260  return 0;
15261  }
15262  if (0 != memcmp(server_domain,
15263  hostbegin + request_domain_len - server_domain_len,
15264  server_domain_len)) {
15265  /* Request is directed to another server:
15266  * The server name is different. */
15267  return 0;
15268  }
15269  }
15270  }
15271 
15272  return hostend;
15273 }
15274 
15275 
15276 static int
15277 get_message(struct mg_connection *conn, char *ebuf, size_t ebuf_len, int *err)
15278 {
15279  if (ebuf_len > 0) {
15280  ebuf[0] = '\0';
15281  }
15282  *err = 0;
15283 
15285 
15286  if (!conn) {
15287  mg_snprintf(conn,
15288  NULL, /* No truncation check for ebuf */
15289  ebuf,
15290  ebuf_len,
15291  "%s",
15292  "Internal error");
15293  *err = 500;
15294  return 0;
15295  }
15296  /* Set the time the request was received. This value should be used for
15297  * timeouts. */
15298  clock_gettime(CLOCK_MONOTONIC, &(conn->req_time));
15299 
15300  conn->request_len =
15301  read_message(NULL, conn, conn->buf, conn->buf_size, &conn->data_len);
15302  /* assert(conn->request_len < 0 || conn->data_len >= conn->request_len);
15303  */
15304  if ((conn->request_len >= 0) && (conn->data_len < conn->request_len)) {
15305  mg_snprintf(conn,
15306  NULL, /* No truncation check for ebuf */
15307  ebuf,
15308  ebuf_len,
15309  "%s",
15310  "Invalid message size");
15311  *err = 500;
15312  return 0;
15313  }
15314 
15315  if ((conn->request_len == 0) && (conn->data_len == conn->buf_size)) {
15316  mg_snprintf(conn,
15317  NULL, /* No truncation check for ebuf */
15318  ebuf,
15319  ebuf_len,
15320  "%s",
15321  "Message too large");
15322  *err = 413;
15323  return 0;
15324  }
15325 
15326  if (conn->request_len <= 0) {
15327  if (conn->data_len > 0) {
15328  mg_snprintf(conn,
15329  NULL, /* No truncation check for ebuf */
15330  ebuf,
15331  ebuf_len,
15332  "%s",
15333  "Malformed message");
15334  *err = 400;
15335  } else {
15336  /* Server did not recv anything -> just close the connection */
15337  conn->must_close = 1;
15338  mg_snprintf(conn,
15339  NULL, /* No truncation check for ebuf */
15340  ebuf,
15341  ebuf_len,
15342  "%s",
15343  "No data received");
15344  *err = 0;
15345  }
15346  return 0;
15347  }
15348  return 1;
15349 }
15350 
15351 
15352 static int
15353 get_request(struct mg_connection *conn, char *ebuf, size_t ebuf_len, int *err)
15354 {
15355  const char *cl;
15356  if (!get_message(conn, ebuf, ebuf_len, err)) {
15357  return 0;
15358  }
15359 
15360  if (parse_http_request(conn->buf, conn->buf_size, &conn->request_info)
15361  <= 0) {
15362  mg_snprintf(conn,
15363  NULL, /* No truncation check for ebuf */
15364  ebuf,
15365  ebuf_len,
15366  "%s",
15367  "Bad request");
15368  *err = 400;
15369  return 0;
15370  }
15371 
15372  /* Message is a valid request */
15373  if ((cl = get_header(conn->request_info.http_headers,
15374  conn->request_info.num_headers,
15375  "Content-Length")) != NULL) {
15376  /* Request/response has content length set */
15377  char *endptr = NULL;
15378  conn->content_len = strtoll(cl, &endptr, 10);
15379  if (endptr == cl) {
15380  mg_snprintf(conn,
15381  NULL, /* No truncation check for ebuf */
15382  ebuf,
15383  ebuf_len,
15384  "%s",
15385  "Bad request");
15386  *err = 411;
15387  return 0;
15388  }
15389  /* Publish the content length back to the request info. */
15390  conn->request_info.content_length = conn->content_len;
15391  } else if ((cl = get_header(conn->request_info.http_headers,
15392  conn->request_info.num_headers,
15393  "Transfer-Encoding")) != NULL
15394  && !mg_strcasecmp(cl, "chunked")) {
15395  conn->is_chunked = 1;
15396  conn->content_len = -1; /* unknown content length */
15397  } else if (get_http_method_info(conn->request_info.request_method)
15398  ->request_has_body) {
15399  /* POST or PUT request without content length set */
15400  conn->content_len = -1; /* unknown content length */
15401  } else {
15402  /* Other request */
15403  conn->content_len = 0; /* No content */
15404  }
15405 
15406  conn->connection_type = CONNECTION_TYPE_REQUEST; /* Valid request */
15407  return 1;
15408 }
15409 
15410 
15411 /* conn is assumed to be valid in this internal function */
15412 static int
15413 get_response(struct mg_connection *conn, char *ebuf, size_t ebuf_len, int *err)
15414 {
15415  const char *cl;
15416  if (!get_message(conn, ebuf, ebuf_len, err)) {
15417  return 0;
15418  }
15419 
15420  if (parse_http_response(conn->buf, conn->buf_size, &conn->response_info)
15421  <= 0) {
15422  mg_snprintf(conn,
15423  NULL, /* No truncation check for ebuf */
15424  ebuf,
15425  ebuf_len,
15426  "%s",
15427  "Bad response");
15428  *err = 400;
15429  return 0;
15430  }
15431 
15432  /* Message is a valid response */
15433  if ((cl = get_header(conn->response_info.http_headers,
15434  conn->response_info.num_headers,
15435  "Content-Length")) != NULL) {
15436  /* Request/response has content length set */
15437  char *endptr = NULL;
15438  conn->content_len = strtoll(cl, &endptr, 10);
15439  if (endptr == cl) {
15440  mg_snprintf(conn,
15441  NULL, /* No truncation check for ebuf */
15442  ebuf,
15443  ebuf_len,
15444  "%s",
15445  "Bad request");
15446  *err = 411;
15447  return 0;
15448  }
15449  /* Publish the content length back to the response info. */
15450  conn->response_info.content_length = conn->content_len;
15451 
15452  /* TODO: check if it is still used in response_info */
15453  conn->request_info.content_length = conn->content_len;
15454 
15455  } else if ((cl = get_header(conn->response_info.http_headers,
15456  conn->response_info.num_headers,
15457  "Transfer-Encoding")) != NULL
15458  && !mg_strcasecmp(cl, "chunked")) {
15459  conn->is_chunked = 1;
15460  conn->content_len = -1; /* unknown content length */
15461  } else {
15462  conn->content_len = -1; /* unknown content length */
15463  }
15464 
15465  conn->connection_type = CONNECTION_TYPE_RESPONSE; /* Valid response */
15466  return 1;
15467 }
15468 
15469 
15470 int
15471 mg_get_response(struct mg_connection *conn,
15472  char *ebuf,
15473  size_t ebuf_len,
15474  int timeout)
15475 {
15476  int err, ret;
15477  char txt[32]; /* will not overflow */
15478  struct mg_context *octx;
15479  struct mg_context rctx;
15480 
15481  if (ebuf_len > 0) {
15482  ebuf[0] = '\0';
15483  }
15484 
15485  if (!conn) {
15486  mg_snprintf(conn,
15487  NULL, /* No truncation check for ebuf */
15488  ebuf,
15489  ebuf_len,
15490  "%s",
15491  "Parameter error");
15492  return -1;
15493  }
15494 
15495  /* Implementation of API function for HTTP clients */
15496  octx = conn->ctx;
15497  rctx = *(conn->ctx);
15498 
15499  if (timeout >= 0) {
15500  mg_snprintf(conn, NULL, txt, sizeof(txt), "%i", timeout);
15501  rctx.config[REQUEST_TIMEOUT] = txt;
15502  /* Not required for non-blocking sockets.
15503  set_sock_timeout(conn->client.sock, timeout);
15504  */
15505  } else {
15506  rctx.config[REQUEST_TIMEOUT] = NULL;
15507  }
15508 
15509  conn->ctx = &rctx;
15510  ret = get_response(conn, ebuf, ebuf_len, &err);
15511  conn->ctx = octx;
15512 
15513 #if defined(MG_LEGACY_INTERFACE)
15514  /* TODO: 1) uri is deprecated;
15515  * 2) here, ri.uri is the http response code */
15516  conn->request_info.uri = conn->request_info.request_uri;
15517 #endif
15518  conn->request_info.local_uri = conn->request_info.request_uri;
15519 
15520  /* TODO (mid): Define proper return values - maybe return length?
15521  * For the first test use <0 for error and >0 for OK */
15522  return (ret == 0) ? -1 : +1;
15523 }
15524 
15525 
15526 struct mg_connection *
15527 mg_download(const char *host,
15528  int port,
15529  int use_ssl,
15530  char *ebuf,
15531  size_t ebuf_len,
15532  const char *fmt,
15533  ...)
15534 {
15535  struct mg_connection *conn;
15536  va_list ap;
15537  int i;
15538  int reqerr;
15539 
15540  if (ebuf_len > 0) {
15541  ebuf[0] = '\0';
15542  }
15543 
15544  va_start(ap, fmt);
15545 
15546  /* open a connection */
15547  conn = mg_connect_client(host, port, use_ssl, ebuf, ebuf_len);
15548 
15549  if (conn != NULL) {
15550  i = mg_vprintf(conn, fmt, ap);
15551  if (i <= 0) {
15552  mg_snprintf(conn,
15553  NULL, /* No truncation check for ebuf */
15554  ebuf,
15555  ebuf_len,
15556  "%s",
15557  "Error sending request");
15558  } else {
15559  get_response(conn, ebuf, ebuf_len, &reqerr);
15560 
15561 #if defined(MG_LEGACY_INTERFACE)
15562  /* TODO: 1) uri is deprecated;
15563  * 2) here, ri.uri is the http response code */
15564  conn->request_info.uri = conn->request_info.request_uri;
15565 #endif
15566  conn->request_info.local_uri = conn->request_info.request_uri;
15567  }
15568  }
15569 
15570  /* if an error occured, close the connection */
15571  if ((ebuf[0] != '\0') && (conn != NULL)) {
15572  mg_close_connection(conn);
15573  conn = NULL;
15574  }
15575 
15576  va_end(ap);
15577  return conn;
15578 }
15579 
15580 
15581 struct websocket_client_thread_data {
15582  struct mg_connection *conn;
15583  mg_websocket_data_handler data_handler;
15584  mg_websocket_close_handler close_handler;
15585  void *callback_data;
15586 };
15587 
15588 
15589 #if defined(USE_WEBSOCKET)
15590 #ifdef _WIN32
15591 static unsigned __stdcall websocket_client_thread(void *data)
15592 #else
15593 static void *
15594 websocket_client_thread(void *data)
15595 #endif
15596 {
15597  struct websocket_client_thread_data *cdata =
15598  (struct websocket_client_thread_data *)data;
15599 
15600  mg_set_thread_name("ws-clnt");
15601 
15602  if (cdata->conn->ctx) {
15603  if (cdata->conn->ctx->callbacks.init_thread) {
15604  /* 3 indicates a websocket client thread */
15605  /* TODO: check if conn->ctx can be set */
15606  cdata->conn->ctx->callbacks.init_thread(cdata->conn->ctx, 3);
15607  }
15608  }
15609 
15610  read_websocket(cdata->conn, cdata->data_handler, cdata->callback_data);
15611 
15612  DEBUG_TRACE("%s", "Websocket client thread exited\n");
15613 
15614  if (cdata->close_handler != NULL) {
15615  cdata->close_handler(cdata->conn, cdata->callback_data);
15616  }
15617 
15618  /* The websocket_client context has only this thread. If it runs out,
15619  set the stop_flag to 2 (= "stopped"). */
15620  cdata->conn->ctx->stop_flag = 2;
15621 
15622  mg_free((void *)cdata);
15623 
15624 #ifdef _WIN32
15625  return 0;
15626 #else
15627  return NULL;
15628 #endif
15629 }
15630 #endif
15631 
15632 
15633 struct mg_connection *
15635  int port,
15636  int use_ssl,
15637  char *error_buffer,
15638  size_t error_buffer_size,
15639  const char *path,
15640  const char *origin,
15641  mg_websocket_data_handler data_func,
15642  mg_websocket_close_handler close_func,
15643  void *user_data)
15644 {
15645  struct mg_connection *conn = NULL;
15646 
15647 #if defined(USE_WEBSOCKET)
15648  struct mg_context *newctx = NULL;
15649  struct websocket_client_thread_data *thread_data;
15650  static const char *magic = "x3JJHMbDL1EzLkh9GBhXDw==";
15651  static const char *handshake_req;
15652 
15653  if (origin != NULL) {
15654  handshake_req = "GET %s HTTP/1.1\r\n"
15655  "Host: %s\r\n"
15656  "Upgrade: websocket\r\n"
15657  "Connection: Upgrade\r\n"
15658  "Sec-WebSocket-Key: %s\r\n"
15659  "Sec-WebSocket-Version: 13\r\n"
15660  "Origin: %s\r\n"
15661  "\r\n";
15662  } else {
15663  handshake_req = "GET %s HTTP/1.1\r\n"
15664  "Host: %s\r\n"
15665  "Upgrade: websocket\r\n"
15666  "Connection: Upgrade\r\n"
15667  "Sec-WebSocket-Key: %s\r\n"
15668  "Sec-WebSocket-Version: 13\r\n"
15669  "\r\n";
15670  }
15671 
15672  /* Establish the client connection and request upgrade */
15673  conn = mg_download(host,
15674  port,
15675  use_ssl,
15676  error_buffer,
15677  error_buffer_size,
15678  handshake_req,
15679  path,
15680  host,
15681  magic,
15682  origin);
15683 
15684  /* Connection object will be null if something goes wrong */
15685  if (conn == NULL) {
15686  if (!*error_buffer) {
15687  /* There should be already an error message */
15688  mg_snprintf(conn,
15689  NULL, /* No truncation check for ebuf */
15690  error_buffer,
15691  error_buffer_size,
15692  "Unexpected error");
15693  }
15694  return NULL;
15695  }
15696 
15697  if (conn->response_info.status_code != 101) {
15698  /* We sent an "upgrade" request. For a correct websocket
15699  * protocol handshake, we expect a "101 Continue" response.
15700  * Otherwise it is a protocol violation. Maybe the HTTP
15701  * Server does not know websockets. */
15702  if (!*error_buffer) {
15703  /* set an error, if not yet set */
15704  mg_snprintf(conn,
15705  NULL, /* No truncation check for ebuf */
15706  error_buffer,
15707  error_buffer_size,
15708  "Unexpected server reply");
15709  }
15710 
15711  DEBUG_TRACE("Websocket client connect error: %s\r\n", error_buffer);
15712  mg_free(conn);
15713  return NULL;
15714  }
15715 
15716  /* For client connections, mg_context is fake. Since we need to set a
15717  * callback function, we need to create a copy and modify it. */
15718  newctx = (struct mg_context *)mg_malloc(sizeof(struct mg_context));
15719  memcpy(newctx, conn->ctx, sizeof(struct mg_context));
15720  newctx->user_data = user_data;
15721  newctx->context_type = CONTEXT_WS_CLIENT; /* ws/wss client context */
15722  newctx->cfg_worker_threads = 1; /* one worker thread will be created */
15723  newctx->worker_threadids =
15724  (pthread_t *)mg_calloc_ctx(newctx->cfg_worker_threads,
15725  sizeof(pthread_t),
15726  newctx);
15727  conn->ctx = newctx;
15728  thread_data = (struct websocket_client_thread_data *)
15729  mg_calloc_ctx(sizeof(struct websocket_client_thread_data), 1, newctx);
15730  thread_data->conn = conn;
15731  thread_data->data_handler = data_func;
15732  thread_data->close_handler = close_func;
15733  thread_data->callback_data = user_data;
15734 
15735  /* Start a thread to read the websocket client connection
15736  * This thread will automatically stop when mg_disconnect is
15737  * called on the client connection */
15738  if (mg_start_thread_with_id(websocket_client_thread,
15739  (void *)thread_data,
15740  newctx->worker_threadids) != 0) {
15741  mg_free((void *)thread_data);
15742  mg_free((void *)newctx->worker_threadids);
15743  mg_free((void *)newctx);
15744  mg_free((void *)conn);
15745  conn = NULL;
15746  DEBUG_TRACE("%s",
15747  "Websocket client connect thread could not be started\r\n");
15748  }
15749 
15750 #else
15751  /* Appease "unused parameter" warnings */
15752  (void)host;
15753  (void)port;
15754  (void)use_ssl;
15755  (void)error_buffer;
15756  (void)error_buffer_size;
15757  (void)path;
15758  (void)origin;
15759  (void)user_data;
15760  (void)data_func;
15761  (void)close_func;
15762 #endif
15763 
15764  return conn;
15765 }
15766 
15767 
15768 /* Prepare connection data structure */
15769 static void
15770 init_connection(struct mg_connection *conn)
15771 {
15772  /* Is keep alive allowed by the server */
15773  int keep_alive_enabled =
15774  !mg_strcasecmp(conn->ctx->config[ENABLE_KEEP_ALIVE], "yes");
15775 
15776  if (!keep_alive_enabled) {
15777  conn->must_close = 1;
15778  }
15779 
15780  /* Important: on new connection, reset the receiving buffer. Credit
15781  * goes to crule42. */
15782  conn->data_len = 0;
15783  conn->handled_requests = 0;
15784  mg_set_user_connection_data(conn, NULL);
15785 
15786 #if defined(USE_SERVER_STATS)
15787  conn->conn_state = 2; /* init */
15788 #endif
15789 
15790  /* call the init_connection callback if assigned */
15791  if (conn->ctx->callbacks.init_connection != NULL) {
15792  if (conn->ctx->context_type == CONTEXT_SERVER) {
15793  void *conn_data = NULL;
15794  conn->ctx->callbacks.init_connection(conn, &conn_data);
15795  mg_set_user_connection_data(conn, conn_data);
15796  }
15797  }
15798 }
15799 
15800 
15801 /* Process a connection - may handle multiple requests
15802  * using the same connection.
15803  * Must be called with a valid connection (conn and
15804  * conn->ctx must be valid).
15805  */
15806 static void
15807 process_new_connection(struct mg_connection *conn)
15808 {
15809  struct mg_request_info *ri = &conn->request_info;
15810  int keep_alive, discard_len;
15811  char ebuf[100];
15812  const char *hostend;
15813  int reqerr, uri_type;
15814 
15815 #if defined(USE_SERVER_STATS)
15816  int mcon = mg_atomic_inc(&(conn->ctx->active_connections));
15817  mg_atomic_add(&(conn->ctx->total_connections), 1);
15818  if (mcon > (conn->ctx->max_connections)) {
15819  /* could use atomic compare exchange, but this
15820  * seems overkill for statistics data */
15821  conn->ctx->max_connections = mcon;
15822  }
15823 #endif
15824 
15825  init_connection(conn);
15826 
15827  DEBUG_TRACE("Start processing connection from %s",
15828  conn->request_info.remote_addr);
15829 
15830  /* Loop over multiple requests sent using the same connection
15831  * (while "keep alive"). */
15832  do {
15833 
15834  DEBUG_TRACE("calling get_request (%i times for this connection)",
15835  conn->handled_requests + 1);
15836 
15837 #if defined(USE_SERVER_STATS)
15838  conn->conn_state = 3; /* ready */
15839 #endif
15840 
15841  if (!get_request(conn, ebuf, sizeof(ebuf), &reqerr)) {
15842  /* The request sent by the client could not be understood by
15843  * the server, or it was incomplete or a timeout. Send an
15844  * error message and close the connection. */
15845  if (reqerr > 0) {
15846  /*assert(ebuf[0] != '\0');*/
15847  mg_send_http_error(conn, reqerr, "%s", ebuf);
15848  }
15849  } else if (strcmp(ri->http_version, "1.0")
15850  && strcmp(ri->http_version, "1.1")) {
15851  mg_snprintf(conn,
15852  NULL, /* No truncation check for ebuf */
15853  ebuf,
15854  sizeof(ebuf),
15855  "Bad HTTP version: [%s]",
15856  ri->http_version);
15857  mg_send_http_error(conn, 505, "%s", ebuf);
15858  }
15859 
15860  if (ebuf[0] == '\0') {
15861  uri_type = get_uri_type(conn->request_info.request_uri);
15862  switch (uri_type) {
15863  case 1:
15864  /* Asterisk */
15865  conn->request_info.local_uri = NULL;
15866  break;
15867  case 2:
15868  /* relative uri */
15869  conn->request_info.local_uri = conn->request_info.request_uri;
15870  break;
15871  case 3:
15872  case 4:
15873  /* absolute uri (with/without port) */
15875  conn->request_info.request_uri, conn);
15876  if (hostend) {
15877  conn->request_info.local_uri = hostend;
15878  } else {
15879  conn->request_info.local_uri = NULL;
15880  }
15881  break;
15882  default:
15883  mg_snprintf(conn,
15884  NULL, /* No truncation check for ebuf */
15885  ebuf,
15886  sizeof(ebuf),
15887  "Invalid URI");
15888  mg_send_http_error(conn, 400, "%s", ebuf);
15889  conn->request_info.local_uri = NULL;
15890  break;
15891  }
15892 
15893 #if defined(MG_LEGACY_INTERFACE)
15894  /* Legacy before split into local_uri and request_uri */
15895  conn->request_info.uri = conn->request_info.local_uri;
15896 #endif
15897  }
15898 
15899  DEBUG_TRACE("http: %s, error: %s",
15900  (ri->http_version ? ri->http_version : "none"),
15901  (ebuf[0] ? ebuf : "none"));
15902 
15903  if (ebuf[0] == '\0') {
15904  if (conn->request_info.local_uri) {
15905 
15906 /* handle request to local server */
15907 #if defined(USE_SERVER_STATS)
15908  conn->conn_state = 4; /* processing */
15909 #endif
15910  handle_request(conn);
15911 
15912 #if defined(USE_SERVER_STATS)
15913  conn->conn_state = 5; /* processed */
15914 
15915  mg_atomic_add(&(conn->ctx->total_data_read),
15916  conn->consumed_content);
15917  mg_atomic_add(&(conn->ctx->total_data_written),
15918  conn->num_bytes_sent);
15919 #endif
15920 
15921  DEBUG_TRACE("%s", "handle_request done");
15922 
15923  if (conn->ctx->callbacks.end_request != NULL) {
15924  conn->ctx->callbacks.end_request(conn, conn->status_code);
15925  DEBUG_TRACE("%s", "end_request callback done");
15926  }
15927  log_access(conn);
15928  } else {
15929  /* TODO: handle non-local request (PROXY) */
15930  conn->must_close = 1;
15931  }
15932  } else {
15933  conn->must_close = 1;
15934  }
15935 
15936  if (ri->remote_user != NULL) {
15937  mg_free((void *)ri->remote_user);
15938  /* Important! When having connections with and without auth
15939  * would cause double free and then crash */
15940  ri->remote_user = NULL;
15941  }
15942 
15943  /* NOTE(lsm): order is important here. should_keep_alive() call
15944  * is using parsed request, which will be invalid after
15945  * memmove's below.
15946  * Therefore, memorize should_keep_alive() result now for later
15947  * use in loop exit condition. */
15948  keep_alive = (conn->ctx->stop_flag == 0) && should_keep_alive(conn)
15949  && (conn->content_len >= 0);
15950 
15951 
15952  /* Discard all buffered data for this request */
15953  discard_len = ((conn->content_len >= 0) && (conn->request_len > 0)
15954  && ((conn->request_len + conn->content_len)
15955  < (int64_t)conn->data_len))
15956  ? (int)(conn->request_len + conn->content_len)
15957  : conn->data_len;
15958  /*assert(discard_len >= 0);*/
15959  if (discard_len < 0) {
15960  DEBUG_TRACE("internal error: discard_len = %li",
15961  (long int)discard_len);
15962  break;
15963  }
15964  conn->data_len -= discard_len;
15965  if (conn->data_len > 0) {
15966  DEBUG_TRACE("discard_len = %lu", (long unsigned)discard_len);
15967  memmove(conn->buf, conn->buf + discard_len, (size_t)conn->data_len);
15968  }
15969 
15970  /* assert(conn->data_len >= 0); */
15971  /* assert(conn->data_len <= conn->buf_size); */
15972 
15973  if ((conn->data_len < 0) || (conn->data_len > conn->buf_size)) {
15974  DEBUG_TRACE("internal error: data_len = %li, buf_size = %li",
15975  (long int)conn->data_len,
15976  (long int)conn->buf_size);
15977  break;
15978  }
15979 
15980  conn->handled_requests++;
15981 
15982  } while (keep_alive);
15983 
15984  DEBUG_TRACE("Done processing connection from %s (%f sec)",
15985  conn->request_info.remote_addr,
15986  difftime(time(NULL), conn->conn_birth_time));
15987 
15988  close_connection(conn);
15989 
15990 #if defined(USE_SERVER_STATS)
15991  mg_atomic_add(&(conn->ctx->total_requests), conn->handled_requests);
15992  mg_atomic_dec(&(conn->ctx->active_connections));
15993 #endif
15994 }
15995 
15996 
15997 #if defined(ALTERNATIVE_QUEUE)
15998 
15999 static void
16000 produce_socket(struct mg_context *ctx, const struct socket *sp)
16001 {
16002  unsigned int i;
16003 
16004  for (;;) {
16005  for (i = 0; i < ctx->cfg_worker_threads; i++) {
16006  /* find a free worker slot and signal it */
16007  if (ctx->client_socks[i].in_use == 0) {
16008  ctx->client_socks[i] = *sp;
16009  ctx->client_socks[i].in_use = 1;
16010  event_signal(ctx->client_wait_events[i]);
16011  return;
16012  }
16013  }
16014  /* queue is full */
16015  mg_sleep(1);
16016  }
16017 }
16018 
16019 
16020 static int
16021 consume_socket(struct mg_context *ctx, struct socket *sp, int thread_index)
16022 {
16023  DEBUG_TRACE("%s", "going idle");
16024  ctx->client_socks[thread_index].in_use = 0;
16025  event_wait(ctx->client_wait_events[thread_index]);
16026  *sp = ctx->client_socks[thread_index];
16027  DEBUG_TRACE("grabbed socket %d, going busy", sp ? sp->sock : -1);
16028 
16029  return !ctx->stop_flag;
16030 }
16031 
16032 #else /* ALTERNATIVE_QUEUE */
16033 
16034 /* Worker threads take accepted socket from the queue */
16035 static int
16036 consume_socket(struct mg_context *ctx, struct socket *sp, int thread_index)
16037 {
16038 #define QUEUE_SIZE(ctx) ((int)(ARRAY_SIZE(ctx->queue)))
16039 
16040  (void)thread_index;
16041 
16042  (void)pthread_mutex_lock(&ctx->thread_mutex);
16043  DEBUG_TRACE("%s", "going idle");
16044 
16045  /* If the queue is empty, wait. We're idle at this point. */
16046  while ((ctx->sq_head == ctx->sq_tail) && (ctx->stop_flag == 0)) {
16047  pthread_cond_wait(&ctx->sq_full, &ctx->thread_mutex);
16048  }
16049 
16050  /* If we're stopping, sq_head may be equal to sq_tail. */
16051  if (ctx->sq_head > ctx->sq_tail) {
16052  /* Copy socket from the queue and increment tail */
16053  *sp = ctx->queue[ctx->sq_tail % QUEUE_SIZE(ctx)];
16054  ctx->sq_tail++;
16055 
16056  DEBUG_TRACE("grabbed socket %d, going busy", sp ? sp->sock : -1);
16057 
16058  /* Wrap pointers if needed */
16059  while (ctx->sq_tail > QUEUE_SIZE(ctx)) {
16060  ctx->sq_tail -= QUEUE_SIZE(ctx);
16061  ctx->sq_head -= QUEUE_SIZE(ctx);
16062  }
16063  }
16064 
16065  (void)pthread_cond_signal(&ctx->sq_empty);
16066  (void)pthread_mutex_unlock(&ctx->thread_mutex);
16067 
16068  return !ctx->stop_flag;
16069 #undef QUEUE_SIZE
16070 }
16071 
16072 
16073 /* Master thread adds accepted socket to a queue */
16074 static void
16075 produce_socket(struct mg_context *ctx, const struct socket *sp)
16076 {
16077 #define QUEUE_SIZE(ctx) ((int)(ARRAY_SIZE(ctx->queue)))
16078  if (!ctx) {
16079  return;
16080  }
16081  (void)pthread_mutex_lock(&ctx->thread_mutex);
16082 
16083  /* If the queue is full, wait */
16084  while ((ctx->stop_flag == 0)
16085  && (ctx->sq_head - ctx->sq_tail >= QUEUE_SIZE(ctx))) {
16086  (void)pthread_cond_wait(&ctx->sq_empty, &ctx->thread_mutex);
16087  }
16088 
16089  if (ctx->sq_head - ctx->sq_tail < QUEUE_SIZE(ctx)) {
16090  /* Copy socket to the queue and increment head */
16091  ctx->queue[ctx->sq_head % QUEUE_SIZE(ctx)] = *sp;
16092  ctx->sq_head++;
16093  DEBUG_TRACE("queued socket %d", sp ? sp->sock : -1);
16094  }
16095 
16096  (void)pthread_cond_signal(&ctx->sq_full);
16097  (void)pthread_mutex_unlock(&ctx->thread_mutex);
16098 #undef QUEUE_SIZE
16099 }
16100 #endif /* ALTERNATIVE_QUEUE */
16101 
16102 
16103 struct worker_thread_args {
16104  struct mg_context *ctx;
16105  int index;
16106 };
16107 
16108 
16109 static void *
16110 worker_thread_run(struct worker_thread_args *thread_args)
16111 {
16112  struct mg_context *ctx = thread_args->ctx;
16113  struct mg_connection *conn;
16114  struct mg_workerTLS tls;
16115 #if defined(MG_LEGACY_INTERFACE)
16116  uint32_t addr;
16117 #endif
16118 
16119  mg_set_thread_name("worker");
16120 
16121  tls.is_master = 0;
16122  tls.thread_idx = (unsigned)mg_atomic_inc(&thread_idx_max);
16123 #if defined(_WIN32) && !defined(__SYMBIAN32__)
16124  tls.pthread_cond_helper_mutex = CreateEvent(NULL, FALSE, FALSE, NULL);
16125 #endif
16126 
16127  /* Initialize thread local storage before calling any callback */
16128  pthread_setspecific(sTlsKey, &tls);
16129 
16130  if (ctx->callbacks.init_thread) {
16131  /* call init_thread for a worker thread (type 1) */
16132  ctx->callbacks.init_thread(ctx, 1);
16133  }
16134 
16135  /* Connection structure has been pre-allocated */
16136  if (((int)thread_args->index < 0)
16137  || ((unsigned)thread_args->index
16138  >= (unsigned)ctx->cfg_worker_threads)) {
16139  mg_cry(fc(ctx),
16140  "Internal error: Invalid worker index %i",
16141  (int)thread_args->index);
16142  return NULL;
16143  }
16144  conn = ctx->worker_connections + thread_args->index;
16145 
16146  /* Request buffers are not pre-allocated. They are private to the
16147  * request and do not contain any state information that might be
16148  * of interest to anyone observing a server status. */
16149  conn->buf = (char *)mg_malloc_ctx(ctx->max_request_size, conn->ctx);
16150  if (conn->buf == NULL) {
16151  mg_cry(fc(ctx),
16152  "Out of memory: Cannot allocate buffer for worker %i",
16153  (int)thread_args->index);
16154  return NULL;
16155  }
16156  conn->buf_size = (int)ctx->max_request_size;
16157 
16158  conn->ctx = ctx;
16159  conn->thread_index = thread_args->index;
16160  conn->request_info.user_data = ctx->user_data;
16161  /* Allocate a mutex for this connection to allow communication both
16162  * within the request handler and from elsewhere in the application
16163  */
16164  (void)pthread_mutex_init(&conn->mutex, &pthread_mutex_attr);
16165 
16166 #if defined(USE_SERVER_STATS)
16167  conn->conn_state = 1; /* not consumed */
16168 #endif
16169 
16170  /* Call consume_socket() even when ctx->stop_flag > 0, to let it
16171  * signal sq_empty condvar to wake up the master waiting in
16172  * produce_socket() */
16173  while (consume_socket(ctx, &conn->client, conn->thread_index)) {
16174  conn->conn_birth_time = time(NULL);
16175 
16176 /* Fill in IP, port info early so even if SSL setup below fails,
16177  * error handler would have the corresponding info.
16178  * Thanks to Johannes Winkelmann for the patch.
16179  */
16180 #if defined(USE_IPV6)
16181  if (conn->client.rsa.sa.sa_family == AF_INET6) {
16182  conn->request_info.remote_port =
16183  ntohs(conn->client.rsa.sin6.sin6_port);
16184  } else
16185 #endif
16186  {
16187  conn->request_info.remote_port =
16188  ntohs(conn->client.rsa.sin.sin_port);
16189  }
16190 
16191  sockaddr_to_string(conn->request_info.remote_addr,
16192  sizeof(conn->request_info.remote_addr),
16193  &conn->client.rsa);
16194 
16195  DEBUG_TRACE("Start processing connection from %s",
16196  conn->request_info.remote_addr);
16197 
16198 #if defined(MG_LEGACY_INTERFACE)
16199  /* This legacy interface only works for the IPv4 case */
16200  addr = ntohl(conn->client.rsa.sin.sin_addr.s_addr);
16201  memcpy(&conn->request_info.remote_ip, &addr, 4);
16202 #endif
16203 
16204  conn->request_info.is_ssl = conn->client.is_ssl;
16205 
16206  if (conn->client.is_ssl) {
16207 #ifndef NO_SSL
16208  /* HTTPS connection */
16209  if (sslize(conn,
16210  conn->ctx->ssl_ctx,
16211  SSL_accept,
16212  &(conn->ctx->stop_flag))) {
16213  /* Get SSL client certificate information (if set) */
16215 
16216  /* process HTTPS connection */
16217  process_new_connection(conn);
16218 
16219  /* Free client certificate info */
16220  if (conn->request_info.client_cert) {
16221  mg_free((void *)(conn->request_info.client_cert->subject));
16222  mg_free((void *)(conn->request_info.client_cert->issuer));
16223  mg_free((void *)(conn->request_info.client_cert->serial));
16224  mg_free((void *)(conn->request_info.client_cert->finger));
16225  conn->request_info.client_cert->subject = 0;
16226  conn->request_info.client_cert->issuer = 0;
16227  conn->request_info.client_cert->serial = 0;
16228  conn->request_info.client_cert->finger = 0;
16229  mg_free(conn->request_info.client_cert);
16230  conn->request_info.client_cert = 0;
16231  }
16232  }
16233 #endif
16234  } else {
16235  /* process HTTP connection */
16236  process_new_connection(conn);
16237  }
16238 
16239  DEBUG_TRACE("%s", "Connection closed");
16240  }
16241 
16242 
16243  pthread_setspecific(sTlsKey, NULL);
16244 #if defined(_WIN32) && !defined(__SYMBIAN32__)
16245  CloseHandle(tls.pthread_cond_helper_mutex);
16246 #endif
16247  pthread_mutex_destroy(&conn->mutex);
16248 
16249  /* Free the request buffer. */
16250  conn->buf_size = 0;
16251  mg_free(conn->buf);
16252  conn->buf = NULL;
16253 
16254 #if defined(USE_SERVER_STATS)
16255  conn->conn_state = 9; /* done */
16256 #endif
16257 
16258  DEBUG_TRACE("%s", "exiting");
16259  return NULL;
16260 }
16261 
16262 
16263 /* Threads have different return types on Windows and Unix. */
16264 #ifdef _WIN32
16265 static unsigned __stdcall worker_thread(void *thread_func_param)
16266 {
16267  struct worker_thread_args *pwta =
16268  (struct worker_thread_args *)thread_func_param;
16269  worker_thread_run(pwta);
16270  mg_free(thread_func_param);
16271  return 0;
16272 }
16273 #else
16274 static void *
16275 worker_thread(void *thread_func_param)
16276 {
16277  struct worker_thread_args *pwta =
16278  (struct worker_thread_args *)thread_func_param;
16279  worker_thread_run(pwta);
16280  mg_free(thread_func_param);
16281  return NULL;
16282 }
16283 #endif /* _WIN32 */
16284 
16285 
16286 static void
16287 accept_new_connection(const struct socket *listener, struct mg_context *ctx)
16288 {
16289  struct socket so;
16290  char src_addr[IP_ADDR_STR_LEN];
16291  socklen_t len = sizeof(so.rsa);
16292  int on = 1;
16293 
16294  if (!listener) {
16295  return;
16296  }
16297 
16298  if ((so.sock = accept(listener->sock, &so.rsa.sa, &len))
16299  == INVALID_SOCKET) {
16300  } else if (!check_acl(ctx, ntohl(*(uint32_t *)&so.rsa.sin.sin_addr))) {
16301  sockaddr_to_string(src_addr, sizeof(src_addr), &so.rsa);
16302  mg_cry(fc(ctx), "%s: %s is not allowed to connect", __func__, src_addr);
16303  closesocket(so.sock);
16304  } else {
16305  /* Put so socket structure into the queue */
16306  DEBUG_TRACE("Accepted socket %d", (int)so.sock);
16307  set_close_on_exec(so.sock, fc(ctx));
16308  so.is_ssl = listener->is_ssl;
16309  so.ssl_redir = listener->ssl_redir;
16310  if (getsockname(so.sock, &so.lsa.sa, &len) != 0) {
16311  mg_cry(fc(ctx),
16312  "%s: getsockname() failed: %s",
16313  __func__,
16314  strerror(ERRNO));
16315  }
16316 
16317  /* Set TCP keep-alive. This is needed because if HTTP-level
16318  * keep-alive
16319  * is enabled, and client resets the connection, server won't get
16320  * TCP FIN or RST and will keep the connection open forever. With
16321  * TCP keep-alive, next keep-alive handshake will figure out that
16322  * the client is down and will close the server end.
16323  * Thanks to Igor Klopov who suggested the patch. */
16324  if (setsockopt(so.sock,
16325  SOL_SOCKET,
16326  SO_KEEPALIVE,
16327  (SOCK_OPT_TYPE)&on,
16328  sizeof(on)) != 0) {
16329  mg_cry(fc(ctx),
16330  "%s: setsockopt(SOL_SOCKET SO_KEEPALIVE) failed: %s",
16331  __func__,
16332  strerror(ERRNO));
16333  }
16334 
16335  /* Disable TCP Nagle's algorithm. Normally TCP packets are coalesced
16336  * to effectively fill up the underlying IP packet payload and
16337  * reduce the overhead of sending lots of small buffers. However
16338  * this hurts the server's throughput (ie. operations per second)
16339  * when HTTP 1.1 persistent connections are used and the responses
16340  * are relatively small (eg. less than 1400 bytes).
16341  */
16342  if ((ctx != NULL) && (ctx->config[CONFIG_TCP_NODELAY] != NULL)
16343  && (!strcmp(ctx->config[CONFIG_TCP_NODELAY], "1"))) {
16344  if (set_tcp_nodelay(so.sock, 1) != 0) {
16345  mg_cry(fc(ctx),
16346  "%s: setsockopt(IPPROTO_TCP TCP_NODELAY) failed: %s",
16347  __func__,
16348  strerror(ERRNO));
16349  }
16350  }
16351 
16352  /* We are using non-blocking sockets. Thus, the
16353  * set_sock_timeout(so.sock, timeout);
16354  * call is no longer required. */
16355 
16356  /* The "non blocking" property should already be
16357  * inherited from the parent socket. Set it for
16358  * non-compliant socket implementations. */
16359  set_non_blocking_mode(so.sock);
16360 
16361  so.in_use = 0;
16362  produce_socket(ctx, &so);
16363  }
16364 }
16365 
16366 
16367 static void
16368 master_thread_run(void *thread_func_param)
16369 {
16370  struct mg_context *ctx = (struct mg_context *)thread_func_param;
16371  struct mg_workerTLS tls;
16372  struct pollfd *pfd;
16373  unsigned int i;
16374  unsigned int workerthreadcount;
16375 
16376  if (!ctx) {
16377  return;
16378  }
16379 
16380  mg_set_thread_name("master");
16381 
16382 /* Increase priority of the master thread */
16383 #if defined(_WIN32)
16384  SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL);
16385 #elif defined(USE_MASTER_THREAD_PRIORITY)
16386  int min_prio = sched_get_priority_min(SCHED_RR);
16387  int max_prio = sched_get_priority_max(SCHED_RR);
16388  if ((min_prio >= 0) && (max_prio >= 0)
16389  && ((USE_MASTER_THREAD_PRIORITY) <= max_prio)
16390  && ((USE_MASTER_THREAD_PRIORITY) >= min_prio)) {
16391  struct sched_param sched_param = {0};
16392  sched_param.sched_priority = (USE_MASTER_THREAD_PRIORITY);
16393  pthread_setschedparam(pthread_self(), SCHED_RR, &sched_param);
16394  }
16395 #endif
16396 
16397 /* Initialize thread local storage */
16398 #if defined(_WIN32) && !defined(__SYMBIAN32__)
16399  tls.pthread_cond_helper_mutex = CreateEvent(NULL, FALSE, FALSE, NULL);
16400 #endif
16401  tls.is_master = 1;
16402  pthread_setspecific(sTlsKey, &tls);
16403 
16404  if (ctx->callbacks.init_thread) {
16405  /* Callback for the master thread (type 0) */
16406  ctx->callbacks.init_thread(ctx, 0);
16407  }
16408 
16409  /* Server starts *now* */
16410  ctx->start_time = time(NULL);
16411 
16412  /* Start the server */
16413  pfd = ctx->listening_socket_fds;
16414  while (ctx->stop_flag == 0) {
16415  for (i = 0; i < ctx->num_listening_sockets; i++) {
16416  pfd[i].fd = ctx->listening_sockets[i].sock;
16417  pfd[i].events = POLLIN;
16418  }
16419 
16420  if (poll(pfd, ctx->num_listening_sockets, 200) > 0) {
16421  for (i = 0; i < ctx->num_listening_sockets; i++) {
16422  /* NOTE(lsm): on QNX, poll() returns POLLRDNORM after the
16423  * successful poll, and POLLIN is defined as
16424  * (POLLRDNORM | POLLRDBAND)
16425  * Therefore, we're checking pfd[i].revents & POLLIN, not
16426  * pfd[i].revents == POLLIN. */
16427  if ((ctx->stop_flag == 0) && (pfd[i].revents & POLLIN)) {
16428  accept_new_connection(&ctx->listening_sockets[i], ctx);
16429  }
16430  }
16431  }
16432  }
16433 
16434  /* Here stop_flag is 1 - Initiate shutdown. */
16435  DEBUG_TRACE("%s", "stopping workers");
16436 
16437  /* Stop signal received: somebody called mg_stop. Quit. */
16439 
16440  /* Wakeup workers that are waiting for connections to handle. */
16441  (void)pthread_mutex_lock(&ctx->thread_mutex);
16442 #if defined(ALTERNATIVE_QUEUE)
16443  for (i = 0; i < ctx->cfg_worker_threads; i++) {
16444  event_signal(ctx->client_wait_events[i]);
16445 
16446  /* Since we know all sockets, we can shutdown the connections. */
16447  if (ctx->client_socks[i].in_use) {
16448  shutdown(ctx->client_socks[i].sock, SHUTDOWN_BOTH);
16449  }
16450  }
16451 #else
16452  pthread_cond_broadcast(&ctx->sq_full);
16453 #endif
16454  (void)pthread_mutex_unlock(&ctx->thread_mutex);
16455 
16456  /* Join all worker threads to avoid leaking threads. */
16457  workerthreadcount = ctx->cfg_worker_threads;
16458  for (i = 0; i < workerthreadcount; i++) {
16459  if (ctx->worker_threadids[i] != 0) {
16460  mg_join_thread(ctx->worker_threadids[i]);
16461  }
16462  }
16463 
16464 #if defined(USE_LUA)
16465  /* Free Lua state of lua background task */
16466  if (ctx->lua_background_state) {
16467  lua_State *lstate = (lua_State *)ctx->lua_background_state;
16468  lua_getglobal(lstate, LUABACKGROUNDPARAMS);
16469  if (lua_istable(lstate, -1)) {
16470  reg_boolean(lstate, "shutdown", 1);
16471  lua_pop(lstate, 1);
16472  mg_sleep(2);
16473  }
16474  lua_close(lstate);
16475  ctx->lua_background_state = 0;
16476  }
16477 #endif
16478 
16479  DEBUG_TRACE("%s", "exiting");
16480 
16481 #if defined(_WIN32) && !defined(__SYMBIAN32__)
16482  CloseHandle(tls.pthread_cond_helper_mutex);
16483 #endif
16484  pthread_setspecific(sTlsKey, NULL);
16485 
16486  /* Signal mg_stop() that we're done.
16487  * WARNING: This must be the very last thing this
16488  * thread does, as ctx becomes invalid after this line. */
16489  ctx->stop_flag = 2;
16490 }
16491 
16492 
16493 /* Threads have different return types on Windows and Unix. */
16494 #ifdef _WIN32
16495 static unsigned __stdcall master_thread(void *thread_func_param)
16496 {
16497  master_thread_run(thread_func_param);
16498  return 0;
16499 }
16500 #else
16501 static void *
16502 master_thread(void *thread_func_param)
16503 {
16504  master_thread_run(thread_func_param);
16505  return NULL;
16506 }
16507 #endif /* _WIN32 */
16508 
16509 
16510 static void
16511 free_context(struct mg_context *ctx)
16512 {
16513  int i;
16514  struct mg_handler_info *tmp_rh;
16515 
16516  if (ctx == NULL) {
16517  return;
16518  }
16519 
16520  if (ctx->callbacks.exit_context) {
16521  ctx->callbacks.exit_context(ctx);
16522  }
16523 
16524  /* All threads exited, no sync is needed. Destroy thread mutex and
16525  * condvars
16526  */
16527  (void)pthread_mutex_destroy(&ctx->thread_mutex);
16528 #if defined(ALTERNATIVE_QUEUE)
16529  mg_free(ctx->client_socks);
16530  for (i = 0; (unsigned)i < ctx->cfg_worker_threads; i++) {
16531  event_destroy(ctx->client_wait_events[i]);
16532  }
16533  mg_free(ctx->client_wait_events);
16534 #else
16535  (void)pthread_cond_destroy(&ctx->sq_empty);
16536  (void)pthread_cond_destroy(&ctx->sq_full);
16537 #endif
16538 
16539  /* Destroy other context global data structures mutex */
16540  (void)pthread_mutex_destroy(&ctx->nonce_mutex);
16541 
16542 #if defined(USE_TIMERS)
16543  timers_exit(ctx);
16544 #endif
16545 
16546  /* Deallocate config parameters */
16547  for (i = 0; i < NUM_OPTIONS; i++) {
16548  if (ctx->config[i] != NULL) {
16549 #if defined(_MSC_VER)
16550 #pragma warning(suppress : 6001)
16551 #endif
16552  mg_free(ctx->config[i]);
16553  }
16554  }
16555 
16556  /* Deallocate request handlers */
16557  while (ctx->handlers) {
16558  tmp_rh = ctx->handlers;
16559  ctx->handlers = tmp_rh->next;
16560  mg_free(tmp_rh->uri);
16561  mg_free(tmp_rh);
16562  }
16563 
16564 #ifndef NO_SSL
16565  /* Deallocate SSL context */
16566  if (ctx->ssl_ctx != NULL) {
16567  SSL_CTX_free(ctx->ssl_ctx);
16568  }
16569 #endif /* !NO_SSL */
16570 
16571  /* Deallocate worker thread ID array */
16572  if (ctx->worker_threadids != NULL) {
16573  mg_free(ctx->worker_threadids);
16574  }
16575 
16576  /* Deallocate worker thread ID array */
16577  if (ctx->worker_connections != NULL) {
16578  mg_free(ctx->worker_connections);
16579  }
16580 
16581  /* deallocate system name string */
16582  mg_free(ctx->systemName);
16583 
16584  /* Deallocate context itself */
16585  mg_free(ctx);
16586 }
16587 
16588 
16589 void
16590 mg_stop(struct mg_context *ctx)
16591 {
16592  pthread_t mt;
16593  if (!ctx) {
16594  return;
16595  }
16596 
16597  /* We don't use a lock here. Calling mg_stop with the same ctx from
16598  * two threads is not allowed. */
16599  mt = ctx->masterthreadid;
16600  if (mt == 0) {
16601  return;
16602  }
16603 
16604  ctx->masterthreadid = 0;
16605 
16606  /* Set stop flag, so all threads know they have to exit. */
16607  ctx->stop_flag = 1;
16608 
16609  /* Wait until everything has stopped. */
16610  while (ctx->stop_flag != 2) {
16611  (void)mg_sleep(10);
16612  }
16613 
16614  mg_join_thread(mt);
16615  free_context(ctx);
16616 
16617 #if defined(_WIN32) && !defined(__SYMBIAN32__)
16618  (void)WSACleanup();
16619 #endif /* _WIN32 && !__SYMBIAN32__ */
16620 }
16621 
16622 
16623 static void
16624 get_system_name(char **sysName)
16625 {
16626 #if defined(_WIN32)
16627 #if !defined(__SYMBIAN32__)
16628 #if defined(_WIN32_WCE)
16629  *sysName = mg_strdup("WinCE");
16630 #else
16631  char name[128];
16632  DWORD dwVersion = 0;
16633  DWORD dwMajorVersion = 0;
16634  DWORD dwMinorVersion = 0;
16635  DWORD dwBuild = 0;
16636  BOOL wowRet, isWoW = FALSE;
16637 
16638 #ifdef _MSC_VER
16639 #pragma warning(push)
16640 /* GetVersion was declared deprecated */
16641 #pragma warning(disable : 4996)
16642 #endif
16643  dwVersion = GetVersion();
16644 #ifdef _MSC_VER
16645 #pragma warning(pop)
16646 #endif
16647 
16648  dwMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion)));
16649  dwMinorVersion = (DWORD)(HIBYTE(LOWORD(dwVersion)));
16650  dwBuild = ((dwVersion < 0x80000000) ? (DWORD)(HIWORD(dwVersion)) : 0);
16651  (void)dwBuild;
16652 
16653  wowRet = IsWow64Process(GetCurrentProcess(), &isWoW);
16654 
16655  sprintf(name,
16656  "Windows %u.%u%s",
16657  (unsigned)dwMajorVersion,
16658  (unsigned)dwMinorVersion,
16659  (wowRet ? (isWoW ? " (WoW64)" : "") : " (?)"));
16660 
16661  *sysName = mg_strdup(name);
16662 #endif
16663 #else
16664  *sysName = mg_strdup("Symbian");
16665 #endif
16666 #else
16667  struct utsname name;
16668  memset(&name, 0, sizeof(name));
16669  uname(&name);
16670  *sysName = mg_strdup(name.sysname);
16671 #endif
16672 }
16673 
16674 
16675 struct mg_context *
16676 mg_start(const struct mg_callbacks *callbacks,
16677  void *user_data,
16678  const char **options)
16679 {
16680  struct mg_context *ctx;
16681  const char *name, *value, *default_value;
16682  int idx, ok, workerthreadcount;
16683  unsigned int i;
16684  int itmp;
16685  void (*exit_callback)(const struct mg_context *ctx) = 0;
16686 
16687  struct mg_workerTLS tls;
16688 
16689 #if defined(_WIN32) && !defined(__SYMBIAN32__)
16690  WSADATA data;
16691  WSAStartup(MAKEWORD(2, 2), &data);
16692 #endif /* _WIN32 && !__SYMBIAN32__ */
16693 
16694  /* Allocate context and initialize reasonable general case defaults. */
16695  if ((ctx = (struct mg_context *)mg_calloc(1, sizeof(*ctx))) == NULL) {
16696  return NULL;
16697  }
16698 
16699  /* Random number generator will initialize at the first call */
16700  ctx->auth_nonce_mask =
16701  (uint64_t)get_random() ^ (uint64_t)(ptrdiff_t)(options);
16702 
16703  if (mg_init_library_called == 0) {
16704  /* Legacy INIT, if mg_start is called without mg_init_library.
16705  * Note: This may cause a memory leak */
16706  mg_init_library(0);
16707  }
16708 
16709  tls.is_master = -1;
16710  tls.thread_idx = (unsigned)mg_atomic_inc(&thread_idx_max);
16711 #if defined(_WIN32) && !defined(__SYMBIAN32__)
16712  tls.pthread_cond_helper_mutex = NULL;
16713 #endif
16714  pthread_setspecific(sTlsKey, &tls);
16715 
16716  ok = 0 == pthread_mutex_init(&ctx->thread_mutex, &pthread_mutex_attr);
16717 #if !defined(ALTERNATIVE_QUEUE)
16718  ok &= 0 == pthread_cond_init(&ctx->sq_empty, NULL);
16719  ok &= 0 == pthread_cond_init(&ctx->sq_full, NULL);
16720 #endif
16721  ok &= 0 == pthread_mutex_init(&ctx->nonce_mutex, &pthread_mutex_attr);
16722  if (!ok) {
16723  /* Fatal error - abort start. However, this situation should never
16724  * occur in practice. */
16725  mg_cry(fc(ctx), "Cannot initialize thread synchronization objects");
16726  mg_free(ctx);
16727  pthread_setspecific(sTlsKey, NULL);
16728  return NULL;
16729  }
16730 
16731  if (callbacks) {
16732  ctx->callbacks = *callbacks;
16733  exit_callback = callbacks->exit_context;
16734  ctx->callbacks.exit_context = 0;
16735  }
16736  ctx->user_data = user_data;
16737  ctx->handlers = NULL;
16738 
16739 #if defined(USE_LUA) && defined(USE_WEBSOCKET)
16740  ctx->shared_lua_websockets = 0;
16741 #endif
16742 
16743  while (options && (name = *options++) != NULL) {
16744  if ((idx = get_option_index(name)) == -1) {
16745  mg_cry(fc(ctx), "Invalid option: %s", name);
16746  free_context(ctx);
16747  pthread_setspecific(sTlsKey, NULL);
16748  return NULL;
16749  } else if ((value = *options++) == NULL) {
16750  mg_cry(fc(ctx), "%s: option value cannot be NULL", name);
16751  free_context(ctx);
16752  pthread_setspecific(sTlsKey, NULL);
16753  return NULL;
16754  }
16755  if (ctx->config[idx] != NULL) {
16756  mg_cry(fc(ctx), "warning: %s: duplicate option", name);
16757  mg_free(ctx->config[idx]);
16758  }
16759  ctx->config[idx] = mg_strdup(value);
16760  DEBUG_TRACE("[%s] -> [%s]", name, value);
16761  }
16762 
16763  /* Set default value if needed */
16764  for (i = 0; config_options[i].name != NULL; i++) {
16765  default_value = config_options[i].default_value;
16766  if ((ctx->config[i] == NULL) && (default_value != NULL)) {
16767  ctx->config[i] = mg_strdup(default_value);
16768  }
16769  }
16770 
16771  itmp = atoi(ctx->config[MAX_REQUEST_SIZE]);
16772 
16773  if (itmp < 1024) {
16774  mg_cry(fc(ctx), "max_request_size too small");
16775  free_context(ctx);
16776  pthread_setspecific(sTlsKey, NULL);
16777  return NULL;
16778  }
16779  ctx->max_request_size = (unsigned)itmp;
16780 
16781  workerthreadcount = atoi(ctx->config[NUM_THREADS]);
16782 
16783  if (workerthreadcount > MAX_WORKER_THREADS) {
16784  mg_cry(fc(ctx), "Too many worker threads");
16785  free_context(ctx);
16786  pthread_setspecific(sTlsKey, NULL);
16787  return NULL;
16788  }
16789 
16790  if (workerthreadcount <= 0) {
16791  mg_cry(fc(ctx), "Invalid number of worker threads");
16792  free_context(ctx);
16793  pthread_setspecific(sTlsKey, NULL);
16794  return NULL;
16795  }
16796 
16797 #if defined(NO_FILES)
16798  if (ctx->config[DOCUMENT_ROOT] != NULL) {
16799  mg_cry(fc(ctx), "%s", "Document root must not be set");
16800  free_context(ctx);
16801  pthread_setspecific(sTlsKey, NULL);
16802  return NULL;
16803  }
16804 #endif
16805 
16806  get_system_name(&ctx->systemName);
16807 
16808 #if defined(USE_LUA)
16809  /* If a Lua background script has been configured, start it. */
16810  if (ctx->config[LUA_BACKGROUND_SCRIPT] != NULL) {
16811  char ebuf[256];
16812  lua_State *state = (void *)mg_prepare_lua_context_script(
16813  ctx->config[LUA_BACKGROUND_SCRIPT], ctx, ebuf, sizeof(ebuf));
16814  if (!state) {
16815  mg_cry(fc(ctx), "lua_background_script error: %s", ebuf);
16816  free_context(ctx);
16817  pthread_setspecific(sTlsKey, NULL);
16818  return NULL;
16819  }
16820  ctx->lua_background_state = (void *)state;
16821 
16822  lua_newtable(state);
16823  reg_boolean(state, "shutdown", 0);
16824 
16825  struct vec opt_vec;
16826  struct vec eq_vec;
16827  const char *sparams = ctx->config[LUA_BACKGROUND_SCRIPT_PARAMS];
16828 
16829  while ((sparams = next_option(sparams, &opt_vec, &eq_vec)) != NULL) {
16830  reg_llstring(
16831  state, opt_vec.ptr, opt_vec.len, eq_vec.ptr, eq_vec.len);
16832  if (mg_strncasecmp(sparams, opt_vec.ptr, opt_vec.len) == 0)
16833  break;
16834  }
16835  lua_setglobal(state, LUABACKGROUNDPARAMS);
16836 
16837  } else {
16838  ctx->lua_background_state = 0;
16839  }
16840 #endif
16841 
16842  /* NOTE(lsm): order is important here. SSL certificates must
16843  * be initialized before listening ports. UID must be set last. */
16844  if (!set_gpass_option(ctx) ||
16845 #if !defined(NO_SSL)
16846  !set_ssl_option(ctx) ||
16847 #endif
16848  !set_ports_option(ctx) ||
16849 #if !defined(_WIN32)
16850  !set_uid_option(ctx) ||
16851 #endif
16852  !set_acl_option(ctx)) {
16853  free_context(ctx);
16854  pthread_setspecific(sTlsKey, NULL);
16855  return NULL;
16856  }
16857 
16858 #if !defined(_WIN32) && !defined(__SYMBIAN32__)
16859  /* Ignore SIGPIPE signal, so if browser cancels the request, it
16860  * won't kill the whole process. */
16861  (void)signal(SIGPIPE, SIG_IGN);
16862 #endif /* !_WIN32 && !__SYMBIAN32__ */
16863 
16864  ctx->cfg_worker_threads = ((unsigned int)(workerthreadcount));
16865  ctx->worker_threadids = (pthread_t *)mg_calloc_ctx(ctx->cfg_worker_threads,
16866  sizeof(pthread_t),
16867  ctx);
16868  if (ctx->worker_threadids == NULL) {
16869  mg_cry(fc(ctx), "Not enough memory for worker thread ID array");
16870  free_context(ctx);
16871  pthread_setspecific(sTlsKey, NULL);
16872  return NULL;
16873  }
16874  ctx->worker_connections =
16875  (struct mg_connection *)mg_calloc_ctx(ctx->cfg_worker_threads,
16876  sizeof(struct mg_connection),
16877  ctx);
16878  if (ctx->worker_connections == NULL) {
16879  mg_cry(fc(ctx), "Not enough memory for worker thread connection array");
16880  free_context(ctx);
16881  pthread_setspecific(sTlsKey, NULL);
16882  return NULL;
16883  }
16884 
16885 
16886 #if defined(ALTERNATIVE_QUEUE)
16887  ctx->client_wait_events =
16888  (void **)mg_calloc_ctx(sizeof(ctx->client_wait_events[0]),
16889  ctx->cfg_worker_threads,
16890  ctx);
16891  if (ctx->client_wait_events == NULL) {
16892  mg_cry(fc(ctx), "Not enough memory for worker event array");
16893  mg_free(ctx->worker_threadids);
16894  free_context(ctx);
16895  pthread_setspecific(sTlsKey, NULL);
16896  return NULL;
16897  }
16898 
16899  ctx->client_socks =
16900  (struct socket *)mg_calloc_ctx(sizeof(ctx->client_socks[0]),
16901  ctx->cfg_worker_threads,
16902  ctx);
16903  if (ctx->client_wait_events == NULL) {
16904  mg_cry(fc(ctx), "Not enough memory for worker socket array");
16905  mg_free(ctx->client_socks);
16906  mg_free(ctx->worker_threadids);
16907  free_context(ctx);
16908  pthread_setspecific(sTlsKey, NULL);
16909  return NULL;
16910  }
16911 
16912  for (i = 0; (unsigned)i < ctx->cfg_worker_threads; i++) {
16913  ctx->client_wait_events[i] = event_create();
16914  if (ctx->client_wait_events[i] == 0) {
16915  mg_cry(fc(ctx), "Error creating worker event %i", i);
16916  while (i > 0) {
16917  i--;
16918  event_destroy(ctx->client_wait_events[i]);
16919  }
16920  mg_free(ctx->client_socks);
16921  mg_free(ctx->worker_threadids);
16922  free_context(ctx);
16923  pthread_setspecific(sTlsKey, NULL);
16924  return NULL;
16925  }
16926  }
16927 #endif
16928 
16929 
16930 #if defined(USE_TIMERS)
16931  if (timers_init(ctx) != 0) {
16932  mg_cry(fc(ctx), "Error creating timers");
16933  free_context(ctx);
16934  pthread_setspecific(sTlsKey, NULL);
16935  return NULL;
16936  }
16937 #endif
16938 
16939  /* Context has been created - init user libraries */
16940  if (ctx->callbacks.init_context) {
16941  ctx->callbacks.init_context(ctx);
16942  }
16943  ctx->callbacks.exit_context = exit_callback;
16944  ctx->context_type = CONTEXT_SERVER; /* server context */
16945 
16946  /* Start master (listening) thread */
16947  mg_start_thread_with_id(master_thread, ctx, &ctx->masterthreadid);
16948 
16949  /* Start worker threads */
16950  for (i = 0; i < ctx->cfg_worker_threads; i++) {
16951  struct worker_thread_args *wta = (struct worker_thread_args *)
16952  mg_malloc_ctx(sizeof(struct worker_thread_args), ctx);
16953  if (wta) {
16954  wta->ctx = ctx;
16955  wta->index = (int)i;
16956  }
16957 
16958  if ((wta == NULL)
16960  wta,
16961  &ctx->worker_threadids[i]) != 0)) {
16962 
16963  /* thread was not created */
16964  if (wta != NULL) {
16965  mg_free(wta);
16966  }
16967 
16968  if (i > 0) {
16969  mg_cry(fc(ctx),
16970  "Cannot start worker thread %i: error %ld",
16971  i + 1,
16972  (long)ERRNO);
16973  } else {
16974  mg_cry(fc(ctx),
16975  "Cannot create threads: error %ld",
16976  (long)ERRNO);
16977  free_context(ctx);
16978  pthread_setspecific(sTlsKey, NULL);
16979  return NULL;
16980  }
16981  break;
16982  }
16983  }
16984 
16985  pthread_setspecific(sTlsKey, NULL);
16986  return ctx;
16987 }
16988 
16989 
16990 /* Feature check API function */
16991 unsigned
16992 mg_check_feature(unsigned feature)
16993 {
16994  static const unsigned feature_set = 0
16995 /* Set bits for available features according to API documentation.
16996  * This bit mask is created at compile time, according to the active
16997  * preprocessor defines. It is a single const value at runtime. */
16998 #if !defined(NO_FILES)
16999  | 0x0001u
17000 #endif
17001 #if !defined(NO_SSL)
17002  | 0x0002u
17003 #endif
17004 #if !defined(NO_CGI)
17005  | 0x0004u
17006 #endif
17007 #if defined(USE_IPV6)
17008  | 0x0008u
17009 #endif
17010 #if defined(USE_WEBSOCKET)
17011  | 0x0010u
17012 #endif
17013 #if defined(USE_LUA)
17014  | 0x0020u
17015 #endif
17016 #if defined(USE_DUKTAPE)
17017  | 0x0040u
17018 #endif
17019 #if !defined(NO_CACHING)
17020  | 0x0080u
17021 #endif
17022 #if defined(USE_SERVER_STATS)
17023  | 0x0100u
17024 #endif
17025 
17026 /* Set some extra bits not defined in the API documentation.
17027  * These bits may change without further notice. */
17028 #if defined(MG_LEGACY_INTERFACE)
17029  | 0x8000u
17030 #endif
17031 #if defined(MEMORY_DEBUGGING)
17032  | 0x0100u
17033 #endif
17034 #if defined(USE_TIMERS)
17035  | 0x0200u
17036 #endif
17037 #if !defined(NO_NONCE_CHECK)
17038  | 0x0400u
17039 #endif
17040 #if !defined(NO_POPEN)
17041  | 0x0800u
17042 #endif
17043  ;
17044  return (feature & feature_set);
17045 }
17046 
17047 
17048 /* strcat with additional NULL check to avoid clang scan-build warning. */
17049 #define strcat0(a, b) \
17050  { \
17051  if ((a != NULL) && (b != NULL)) { \
17052  strcat(a, b); \
17053  } \
17054  }
17055 
17056 
17057 /* Get system information. It can be printed or stored by the caller.
17058  * Return the size of available information. */
17059 static int
17060 mg_get_system_info_impl(char *buffer, int buflen)
17061 {
17062  char block[256];
17063  int system_info_length = 0;
17064 
17065 #if defined(_WIN32)
17066  const char *eol = "\r\n";
17067 #else
17068  const char *eol = "\n";
17069 #endif
17070 
17071  const char *eoobj = "}";
17072  int reserved_len = (int)strlen(eoobj) + (int)strlen(eol);
17073 
17074  if ((buffer == NULL) || (buflen < 1)) {
17075  buflen = 0;
17076  } else {
17077  *buffer = 0;
17078  }
17079 
17080  mg_snprintf(NULL, NULL, block, sizeof(block), "{%s", eol);
17081  system_info_length += (int)strlen(block);
17082  if (system_info_length < buflen) {
17083  strcat0(buffer, block);
17084  }
17085 
17086  /* Server version */
17087  {
17088  const char *version = mg_version();
17089  mg_snprintf(NULL,
17090  NULL,
17091  block,
17092  sizeof(block),
17093  "\"version\" : \"%s\",%s",
17094  version,
17095  eol);
17096  system_info_length += (int)strlen(block);
17097  if (system_info_length < buflen) {
17098  strcat0(buffer, block);
17099  }
17100  }
17101 
17102  /* System info */
17103  {
17104 #if defined(_WIN32)
17105 #if !defined(__SYMBIAN32__)
17106  DWORD dwVersion = 0;
17107  DWORD dwMajorVersion = 0;
17108  DWORD dwMinorVersion = 0;
17109  SYSTEM_INFO si;
17110 
17111  GetSystemInfo(&si);
17112 
17113 #ifdef _MSC_VER
17114 #pragma warning(push)
17115 /* GetVersion was declared deprecated */
17116 #pragma warning(disable : 4996)
17117 #endif
17118  dwVersion = GetVersion();
17119 #ifdef _MSC_VER
17120 #pragma warning(pop)
17121 #endif
17122 
17123  dwMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion)));
17124  dwMinorVersion = (DWORD)(HIBYTE(LOWORD(dwVersion)));
17125 
17126  mg_snprintf(NULL,
17127  NULL,
17128  block,
17129  sizeof(block),
17130  "\"os\" : \"Windows %u.%u\",%s",
17131  (unsigned)dwMajorVersion,
17132  (unsigned)dwMinorVersion,
17133  eol);
17134  system_info_length += (int)strlen(block);
17135  if (system_info_length < buflen) {
17136  strcat0(buffer, block);
17137  }
17138 
17139  mg_snprintf(NULL,
17140  NULL,
17141  block,
17142  sizeof(block),
17143  "\"cpu\" : \"type %u, cores %u, mask %x\",%s",
17144  (unsigned)si.wProcessorArchitecture,
17145  (unsigned)si.dwNumberOfProcessors,
17146  (unsigned)si.dwActiveProcessorMask,
17147  eol);
17148  system_info_length += (int)strlen(block);
17149  if (system_info_length < buflen) {
17150  strcat0(buffer, block);
17151  }
17152 
17153 #else
17154  mg_snprintf(NULL, NULL, block, sizeof(block), "%s - Symbian%s", eol);
17155  system_info_length += (int)strlen(block);
17156  if (system_info_length < buflen) {
17157  strcat0(buffer, block);
17158  }
17159 #endif
17160 #else
17161  struct utsname name;
17162  memset(&name, 0, sizeof(name));
17163  uname(&name);
17164 
17165  mg_snprintf(NULL,
17166  NULL,
17167  block,
17168  sizeof(block),
17169  "\"os\" : \"%s %s (%s) - %s\",%s",
17170  name.sysname,
17171  name.version,
17172  name.release,
17173  name.machine,
17174  eol);
17175  system_info_length += (int)strlen(block);
17176  if (system_info_length < buflen) {
17177  strcat0(buffer, block);
17178  }
17179 #endif
17180  }
17181 
17182  /* Features */
17183  {
17184  mg_snprintf(NULL,
17185  NULL,
17186  block,
17187  sizeof(block),
17188  "\"features\" : %lu,%s"
17189  "\"feature_list\" : \"Server:%s%s%s%s%s%s%s%s%s\",%s",
17190  (unsigned long)mg_check_feature(0xFFFFFFFFu),
17191  eol,
17192  mg_check_feature(1) ? " Files" : "",
17193  mg_check_feature(2) ? " HTTPS" : "",
17194  mg_check_feature(4) ? " CGI" : "",
17195  mg_check_feature(8) ? " IPv6" : "",
17196  mg_check_feature(16) ? " WebSockets" : "",
17197  mg_check_feature(32) ? " Lua" : "",
17198  mg_check_feature(64) ? " JavaScript" : "",
17199  mg_check_feature(128) ? " Cache" : "",
17200  mg_check_feature(256) ? " Stats" : "",
17201  eol);
17202  system_info_length += (int)strlen(block);
17203  if (system_info_length < buflen) {
17204  strcat0(buffer, block);
17205  }
17206 
17207 #ifdef USE_LUA
17208  mg_snprintf(NULL,
17209  NULL,
17210  block,
17211  sizeof(block),
17212  "\"lua_version\" : \"%u (%s)\",%s",
17213  (unsigned)LUA_VERSION_NUM,
17214  LUA_RELEASE,
17215  eol);
17216  system_info_length += (int)strlen(block);
17217  if (system_info_length < buflen) {
17218  strcat0(buffer, block);
17219  }
17220 #endif
17221 #if defined(USE_DUKTAPE)
17222  mg_snprintf(NULL,
17223  NULL,
17224  block,
17225  sizeof(block),
17226  "\"javascript\" : \"Duktape %u.%u.%u\",%s",
17227  (unsigned)DUK_VERSION / 10000,
17228  ((unsigned)DUK_VERSION / 100) % 100,
17229  (unsigned)DUK_VERSION % 100,
17230  eol);
17231  system_info_length += (int)strlen(block);
17232  if (system_info_length < buflen) {
17233  strcat0(buffer, block);
17234  }
17235 #endif
17236  }
17237 
17238  /* Build date */
17239  {
17240 
17241 // Sergey Linev: remove this kind of warning suppression, most probably for old GCC
17242 //#if defined(__GNUC__)
17243 //#pragma GCC diagnostic push
17244 /* Disable bogus compiler warning -Wdate-time */
17245 // #pragma GCC diagnostic ignored "-Wall"
17246 // #pragma GCC diagnostic ignored "-Werror"
17247 //#endif
17248  mg_snprintf(NULL,
17249  NULL,
17250  block,
17251  sizeof(block),
17252  "\"build\" : \"%s\",%s",
17253  __DATE__,
17254  eol);
17255 
17256 //#if defined(__GNUC__)
17257 //#pragma GCC diagnostic pop
17258 //#endif
17259 
17260  system_info_length += (int)strlen(block);
17261  if (system_info_length < buflen) {
17262  strcat0(buffer, block);
17263  }
17264  }
17265 
17266 
17267  /* Compiler information */
17268  /* http://sourceforge.net/p/predef/wiki/Compilers/ */
17269  {
17270 #if defined(_MSC_VER)
17271  mg_snprintf(NULL,
17272  NULL,
17273  block,
17274  sizeof(block),
17275  "\"compiler\" : \"MSC: %u (%u)\",%s",
17276  (unsigned)_MSC_VER,
17277  (unsigned)_MSC_FULL_VER,
17278  eol);
17279  system_info_length += (int)strlen(block);
17280  if (system_info_length < buflen) {
17281  strcat0(buffer, block);
17282  }
17283 #elif defined(__MINGW64__)
17284  mg_snprintf(NULL,
17285  NULL,
17286  block,
17287  sizeof(block),
17288  "\"compiler\" : \"MinGW64: %u.%u\",%s",
17289  (unsigned)__MINGW64_VERSION_MAJOR,
17290  (unsigned)__MINGW64_VERSION_MINOR,
17291  eol);
17292  system_info_length += (int)strlen(block);
17293  if (system_info_length < buflen) {
17294  strcat0(buffer, block);
17295  }
17296  mg_snprintf(NULL,
17297  NULL,
17298  block,
17299  sizeof(block),
17300  "\"compiler\" : \"MinGW32: %u.%u\",%s",
17301  (unsigned)__MINGW32_MAJOR_VERSION,
17302  (unsigned)__MINGW32_MINOR_VERSION,
17303  eol);
17304  system_info_length += (int)strlen(block);
17305  if (system_info_length < buflen) {
17306  strcat0(buffer, block);
17307  }
17308 #elif defined(__MINGW32__)
17309  mg_snprintf(NULL,
17310  NULL,
17311  block,
17312  sizeof(block),
17313  "\"compiler\" : \"MinGW32: %u.%u\",%s",
17314  (unsigned)__MINGW32_MAJOR_VERSION,
17315  (unsigned)__MINGW32_MINOR_VERSION,
17316  eol);
17317  system_info_length += (int)strlen(block);
17318  if (system_info_length < buflen) {
17319  strcat0(buffer, block);
17320  }
17321 #elif defined(__clang__)
17322  mg_snprintf(NULL,
17323  NULL,
17324  block,
17325  sizeof(block),
17326  "\"compiler\" : \"clang: %u.%u.%u (%s)\",%s",
17327  __clang_major__,
17328  __clang_minor__,
17329  __clang_patchlevel__,
17330  __clang_version__,
17331  eol);
17332  system_info_length += (int)strlen(block);
17333  if (system_info_length < buflen) {
17334  strcat0(buffer, block);
17335  }
17336 #elif defined(__GNUC__)
17337  mg_snprintf(NULL,
17338  NULL,
17339  block,
17340  sizeof(block),
17341  "\"compiler\" : \"gcc: %u.%u.%u\",%s",
17342  (unsigned)__GNUC__,
17343  (unsigned)__GNUC_MINOR__,
17344  (unsigned)__GNUC_PATCHLEVEL__,
17345  eol);
17346  system_info_length += (int)strlen(block);
17347  if (system_info_length < buflen) {
17348  strcat0(buffer, block);
17349  }
17350 #elif defined(__INTEL_COMPILER)
17351  mg_snprintf(NULL,
17352  NULL,
17353  block,
17354  sizeof(block),
17355  "\"compiler\" : \"Intel C/C++: %u\",%s",
17356  (unsigned)__INTEL_COMPILER,
17357  eol);
17358  system_info_length += (int)strlen(block);
17359  if (system_info_length < buflen) {
17360  strcat0(buffer, block);
17361  }
17362 #elif defined(__BORLANDC__)
17363  mg_snprintf(NULL,
17364  NULL,
17365  block,
17366  sizeof(block),
17367  "\"compiler\" : \"Borland C: 0x%x\",%s",
17368  (unsigned)__BORLANDC__,
17369  eol);
17370  system_info_length += (int)strlen(block);
17371  if (system_info_length < buflen) {
17372  strcat0(buffer, block);
17373  }
17374 #elif defined(__SUNPRO_C)
17375  mg_snprintf(NULL,
17376  NULL,
17377  block,
17378  sizeof(block),
17379  "\"compiler\" : \"Solaris: 0x%x\",%s",
17380  (unsigned)__SUNPRO_C,
17381  eol);
17382  system_info_length += (int)strlen(block);
17383  if (system_info_length < buflen) {
17384  strcat0(buffer, block);
17385  }
17386 #else
17387  mg_snprintf(NULL,
17388  NULL,
17389  block,
17390  sizeof(block),
17391  "\"compiler\" : \"other\",%s",
17392  eol);
17393  system_info_length += (int)strlen(block);
17394  if (system_info_length < buflen) {
17395  strcat0(buffer, block);
17396  }
17397 #endif
17398  }
17399 
17400  /* Determine 32/64 bit data mode.
17401  * see https://en.wikipedia.org/wiki/64-bit_computing */
17402  {
17403  mg_snprintf(
17404  NULL,
17405  NULL,
17406  block,
17407  sizeof(block),
17408  "\"data_model\" : \"int:%u/%u/%u/%u, float:%u/%u/%u, char:%u/%u, "
17409  "ptr:%u, size:%u, time:%u\"%s",
17410  (unsigned)sizeof(short),
17411  (unsigned)sizeof(int),
17412  (unsigned)sizeof(long),
17413  (unsigned)sizeof(long long),
17414  (unsigned)sizeof(float),
17415  (unsigned)sizeof(double),
17416  (unsigned)sizeof(long double),
17417  (unsigned)sizeof(char),
17418  (unsigned)sizeof(wchar_t),
17419  (unsigned)sizeof(void *),
17420  (unsigned)sizeof(size_t),
17421  (unsigned)sizeof(time_t),
17422  eol);
17423  system_info_length += (int)strlen(block);
17424  if (system_info_length < buflen) {
17425  strcat0(buffer, block);
17426  }
17427  }
17428 
17429  /* Terminate string */
17430  if ((buflen > 0) && buffer && buffer[0]) {
17431  if (system_info_length < buflen) {
17432  strcat0(buffer, eoobj);
17433  strcat0(buffer, eol);
17434  }
17435  }
17436  system_info_length += reserved_len;
17437 
17438  return system_info_length;
17439 }
17440 
17441 
17442 #if defined(USE_SERVER_STATS)
17443 /* Get context information. It can be printed or stored by the caller.
17444  * Return the size of available information. */
17445 static int
17446 mg_get_context_info_impl(const struct mg_context *ctx, char *buffer, int buflen)
17447 
17448 {
17449  char block[256];
17450  int context_info_length = 0;
17451 
17452 #if defined(_WIN32)
17453  const char *eol = "\r\n";
17454 #else
17455  const char *eol = "\n";
17456 #endif
17457  struct mg_memory_stat *ms = get_memory_stat((struct mg_context *)ctx);
17458 
17459  const char *eoobj = "}";
17460  int reserved_len = (int)strlen(eoobj) + (int)strlen(eol);
17461 
17462  if ((buffer == NULL) || (buflen < 1)) {
17463  buflen = 0;
17464  } else {
17465  *buffer = 0;
17466  }
17467 
17468  mg_snprintf(NULL, NULL, block, sizeof(block), "{%s", eol);
17469  context_info_length += (int)strlen(block);
17470  if (context_info_length < buflen) {
17471  strcat0(buffer, block);
17472  }
17473 
17474  /* Memory information */
17475  if (ms) {
17476  mg_snprintf(NULL,
17477  NULL,
17478  block,
17479  sizeof(block),
17480  "\"memory\" : {%s"
17481  "\"blocks\" : %i,%s"
17482  "\"used\" : %" INT64_FMT ",%s"
17483  "\"maxUsed\" : %" INT64_FMT "%s"
17484  "}%s%s",
17485  eol,
17486  ms->blockCount,
17487  eol,
17488  ms->totalMemUsed,
17489  eol,
17490  ms->maxMemUsed,
17491  eol,
17492  (ctx ? "," : ""),
17493  eol);
17494 
17495  context_info_length += (int)strlen(block);
17496  if (context_info_length + reserved_len < buflen) {
17497  strcat0(buffer, block);
17498  }
17499  }
17500 
17501 
17502  /* Connections information */
17503  if (ctx) {
17504  mg_snprintf(NULL,
17505  NULL,
17506  block,
17507  sizeof(block),
17508  "\"connections\" : {%s"
17509  "\"active\" : %i,%s"
17510  "\"maxActive\" : %i,%s"
17511  "\"total\" : %" INT64_FMT "%s"
17512  "},%s",
17513  eol,
17514  ctx->active_connections,
17515  eol,
17516  ctx->max_connections,
17517  eol,
17518  ctx->total_connections,
17519  eol,
17520  eol);
17521 
17522  context_info_length += (int)strlen(block);
17523  if (context_info_length + reserved_len < buflen) {
17524  strcat0(buffer, block);
17525  }
17526  }
17527 
17528  /* Requests information */
17529  if (ctx) {
17530  mg_snprintf(NULL,
17531  NULL,
17532  block,
17533  sizeof(block),
17534  "\"requests\" : {%s"
17535  "\"total\" : %" INT64_FMT "%s"
17536  "},%s",
17537  eol,
17538  ctx->total_requests,
17539  eol,
17540  eol);
17541 
17542  context_info_length += (int)strlen(block);
17543  if (context_info_length + reserved_len < buflen) {
17544  strcat0(buffer, block);
17545  }
17546  }
17547 
17548  /* Data information */
17549  if (ctx) {
17550  mg_snprintf(NULL,
17551  NULL,
17552  block,
17553  sizeof(block),
17554  "\"data\" : {%s"
17555  "\"read\" : %" INT64_FMT "%s,"
17556  "\"written\" : %" INT64_FMT "%s"
17557  "},%s",
17558  eol,
17559  ctx->total_data_read,
17560  eol,
17561  ctx->total_data_written,
17562  eol,
17563  eol);
17564 
17565  context_info_length += (int)strlen(block);
17566  if (context_info_length + reserved_len < buflen) {
17567  strcat0(buffer, block);
17568  }
17569  }
17570 
17571  /* Execution time information */
17572  if (ctx) {
17573  char start_time_str[64] = {0};
17574  char now_str[64] = {0};
17575  time_t start_time = ctx->start_time;
17576  time_t now = time(NULL);
17577 
17578  gmt_time_string(start_time_str,
17579  sizeof(start_time_str) - 1,
17580  &start_time);
17581  gmt_time_string(now_str, sizeof(now_str) - 1, &now);
17582 
17583  mg_snprintf(NULL,
17584  NULL,
17585  block,
17586  sizeof(block),
17587  "\"time\" : {%s"
17588  "\"uptime\" : %.0f,%s"
17589  "\"start\" : \"%s\",%s"
17590  "\"now\" : \"%s\"%s"
17591  "}%s",
17592  eol,
17593  difftime(now, start_time),
17594  eol,
17595  start_time_str,
17596  eol,
17597  now_str,
17598  eol,
17599  eol);
17600 
17601  context_info_length += (int)strlen(block);
17602  if (context_info_length + reserved_len < buflen) {
17603  strcat0(buffer, block);
17604  }
17605  }
17606 
17607  /* Terminate string */
17608  if ((buflen > 0) && buffer && buffer[0]) {
17609  if (context_info_length < buflen) {
17610  strcat0(buffer, eoobj);
17611  strcat0(buffer, eol);
17612  }
17613  }
17614  context_info_length += reserved_len;
17615 
17616  return context_info_length;
17617 }
17618 #endif
17619 
17620 
17621 #ifdef MG_EXPERIMENTAL_INTERFACES
17622 /* Get connection information. It can be printed or stored by the caller.
17623  * Return the size of available information. */
17624 static int
17625 mg_get_connection_info_impl(const struct mg_context *ctx,
17626  int idx,
17627  char *buffer,
17628  int buflen)
17629 {
17630  const struct mg_connection *conn;
17631  const struct mg_request_info *ri;
17632  char block[256];
17633  int connection_info_length = 0;
17634  int state = 0;
17635  const char *state_str = "unknown";
17636 
17637 #if defined(_WIN32)
17638  const char *eol = "\r\n";
17639 #else
17640  const char *eol = "\n";
17641 #endif
17642 
17643  const char *eoobj = "}";
17644  int reserved_len = (int)strlen(eoobj) + (int)strlen(eol);
17645 
17646  if ((buffer == NULL) || (buflen < 1)) {
17647  buflen = 0;
17648  } else {
17649  *buffer = 0;
17650  }
17651 
17652  if ((ctx == NULL) || (idx < 0)) {
17653  /* Parameter error */
17654  return 0;
17655  }
17656 
17657  if ((unsigned)idx >= ctx->cfg_worker_threads) {
17658  /* Out of range */
17659  return 0;
17660  }
17661 
17662  /* Take connection [idx]. This connection is not locked in
17663  * any way, so some other thread might use it. */
17664  conn = (ctx->worker_connections) + idx;
17665 
17666  /* Initialize output string */
17667  mg_snprintf(NULL, NULL, block, sizeof(block), "{%s", eol);
17668  connection_info_length += (int)strlen(block);
17669  if (connection_info_length < buflen) {
17670  strcat0(buffer, block);
17671  }
17672 
17673  /* Init variables */
17674  ri = &(conn->request_info);
17675 
17676 #if defined(USE_SERVER_STATS)
17677  state = conn->conn_state;
17678 
17679  /* State as string */
17680  switch (state) {
17681  case 0:
17682  state_str = "undefined";
17683  break;
17684  case 1:
17685  state_str = "not used";
17686  break;
17687  case 2:
17688  state_str = "init";
17689  break;
17690  case 3:
17691  state_str = "ready";
17692  break;
17693  case 4:
17694  state_str = "processing";
17695  break;
17696  case 5:
17697  state_str = "processed";
17698  break;
17699  case 6:
17700  state_str = "to close";
17701  break;
17702  case 7:
17703  state_str = "closing";
17704  break;
17705  case 8:
17706  state_str = "closed";
17707  break;
17708  case 9:
17709  state_str = "done";
17710  break;
17711  }
17712 #endif
17713 
17714  /* Connection info */
17715  if ((state >= 3) && (state < 9)) {
17716  mg_snprintf(NULL,
17717  NULL,
17718  block,
17719  sizeof(block),
17720  "\"connection\" : {%s"
17721  "\"remote\" : {%s"
17722  "\"protocol\" : \"%s\",%s"
17723  "\"addr\" : \"%s\",%s"
17724  "\"port\" : %u%s"
17725  "},%s"
17726  "\"handled_requests\" : %u%s"
17727  "},%s",
17728  eol,
17729  eol,
17730  get_proto_name(conn),
17731  eol,
17732  ri->remote_addr,
17733  eol,
17734  ri->remote_port,
17735  eol,
17736  eol,
17737  conn->handled_requests,
17738  eol,
17739  eol);
17740 
17741  connection_info_length += (int)strlen(block);
17742  if (connection_info_length + reserved_len < buflen) {
17743  strcat0(buffer, block);
17744  }
17745  }
17746 
17747  /* Request info */
17748  if ((state >= 4) && (state < 6)) {
17749  mg_snprintf(NULL,
17750  NULL,
17751  block,
17752  sizeof(block),
17753  "\"request_info\" : {%s"
17754  "\"method\" : \"%s\",%s"
17755  "\"uri\" : \"%s\",%s"
17756  "\"query\" : %s%s%s%s"
17757  "},%s",
17758  eol,
17759  ri->request_method,
17760  eol,
17761  ri->request_uri,
17762  eol,
17763  ri->query_string ? "\"" : "",
17764  ri->query_string ? ri->query_string : "null",
17765  ri->query_string ? "\"" : "",
17766  eol,
17767  eol);
17768 
17769  connection_info_length += (int)strlen(block);
17770  if (connection_info_length + reserved_len < buflen) {
17771  strcat0(buffer, block);
17772  }
17773  }
17774 
17775  /* Execution time information */
17776  if ((state >= 2) && (state < 9)) {
17777  char start_time_str[64] = {0};
17778  char now_str[64] = {0};
17779  time_t start_time = conn->conn_birth_time;
17780  time_t now = time(NULL);
17781 
17782  gmt_time_string(start_time_str,
17783  sizeof(start_time_str) - 1,
17784  &start_time);
17785  gmt_time_string(now_str, sizeof(now_str) - 1, &now);
17786 
17787  mg_snprintf(NULL,
17788  NULL,
17789  block,
17790  sizeof(block),
17791  "\"time\" : {%s"
17792  "\"uptime\" : %.0f,%s"
17793  "\"start\" : \"%s\",%s"
17794  "\"now\" : \"%s\"%s"
17795  "},%s",
17796  eol,
17797  difftime(now, start_time),
17798  eol,
17799  start_time_str,
17800  eol,
17801  now_str,
17802  eol,
17803  eol);
17804 
17805  connection_info_length += (int)strlen(block);
17806  if (connection_info_length + reserved_len < buflen) {
17807  strcat0(buffer, block);
17808  }
17809  }
17810 
17811  /* Remote user name */
17812  if ((ri->remote_user) && (state < 9)) {
17813  mg_snprintf(NULL,
17814  NULL,
17815  block,
17816  sizeof(block),
17817  "\"user\" : {%s"
17818  "\"name\" : \"%s\",%s"
17819  "},%s",
17820  eol,
17821  ri->remote_user,
17822  eol,
17823  eol);
17824 
17825  connection_info_length += (int)strlen(block);
17826  if (connection_info_length + reserved_len < buflen) {
17827  strcat0(buffer, block);
17828  }
17829  }
17830 
17831  /* Data block */
17832  if (state >= 3) {
17833  mg_snprintf(NULL,
17834  NULL,
17835  block,
17836  sizeof(block),
17837  "\"data\" : {%s"
17838  "\"read\" : %" INT64_FMT ",%s"
17839  "\"written\" : %" INT64_FMT "%s"
17840  "},%s",
17841  eol,
17842  conn->consumed_content,
17843  eol,
17844  conn->num_bytes_sent,
17845  eol,
17846  eol);
17847 
17848  connection_info_length += (int)strlen(block);
17849  if (connection_info_length + reserved_len < buflen) {
17850  strcat0(buffer, block);
17851  }
17852  }
17853 
17854  /* State */
17855  mg_snprintf(NULL,
17856  NULL,
17857  block,
17858  sizeof(block),
17859  "\"state\" : \"%s\"%s",
17860  state_str,
17861  eol);
17862 
17863  connection_info_length += (int)strlen(block);
17864  if (connection_info_length + reserved_len < buflen) {
17865  strcat0(buffer, block);
17866  }
17867 
17868  /* Terminate string */
17869  if ((buflen > 0) && buffer && buffer[0]) {
17870  if (connection_info_length < buflen) {
17871  strcat0(buffer, eoobj);
17872  strcat0(buffer, eol);
17873  }
17874  }
17875  connection_info_length += reserved_len;
17876 
17877  return connection_info_length;
17878 }
17879 #endif
17880 
17881 
17882 /* Get system information. It can be printed or stored by the caller.
17883  * Return the size of available information. */
17884 int
17885 mg_get_system_info(char *buffer, int buflen)
17886 {
17887  if ((buffer == NULL) || (buflen < 1)) {
17888  return mg_get_system_info_impl(NULL, 0);
17889  } else {
17890  /* Reset buffer, so we can always use strcat. */
17891  buffer[0] = 0;
17892  return mg_get_system_info_impl(buffer, buflen);
17893  }
17894 }
17895 
17896 
17897 /* Get context information. It can be printed or stored by the caller.
17898  * Return the size of available information. */
17899 int
17900 mg_get_context_info(const struct mg_context *ctx, char *buffer, int buflen)
17901 {
17902 #if defined(USE_SERVER_STATS)
17903  if ((buffer == NULL) || (buflen < 1)) {
17904  return mg_get_context_info_impl(ctx, NULL, 0);
17905  } else {
17906  /* Reset buffer, so we can always use strcat. */
17907  buffer[0] = 0;
17908  return mg_get_context_info_impl(ctx, buffer, buflen);
17909  }
17910 #else
17911  (void)ctx;
17912  if ((buffer != NULL) && (buflen > 0)) {
17913  buffer[0] = 0;
17914  }
17915  return 0;
17916 #endif
17917 }
17918 
17919 
17920 #ifdef MG_EXPERIMENTAL_INTERFACES
17921 int
17922 mg_get_connection_info(const struct mg_context *ctx,
17923  int idx,
17924  char *buffer,
17925  int buflen)
17926 {
17927  if ((buffer == NULL) || (buflen < 1)) {
17928  return mg_get_connection_info_impl(ctx, idx, NULL, 0);
17929  } else {
17930  /* Reset buffer, so we can always use strcat. */
17931  buffer[0] = 0;
17932  return mg_get_connection_info_impl(ctx, idx, buffer, buflen);
17933  }
17934 }
17935 #endif
17936 
17937 
17938 /* Initialize this library. This function does not need to be thread safe.
17939  */
17940 unsigned
17941 mg_init_library(unsigned features)
17942 {
17943 #if !defined(NO_SSL)
17944  char ebuf[128];
17945 #endif
17946 
17947  unsigned features_to_init = mg_check_feature(features & 0xFFu);
17948  unsigned features_inited = features_to_init;
17949 
17950  if (mg_init_library_called <= 0) {
17951  /* Not initialized yet */
17952  if (0 != pthread_mutex_init(&global_lock_mutex, NULL)) {
17953  return 0;
17954  }
17955  }
17956 
17957  mg_global_lock();
17958 
17959  if (mg_init_library_called <= 0) {
17960  if (0 != pthread_key_create(&sTlsKey, tls_dtor)) {
17961  /* Fatal error - abort start. However, this situation should
17962  * never occur in practice. */
17963  return 0;
17964  }
17965 
17966 #if defined(_WIN32) && !defined(__SYMBIAN32__)
17967  InitializeCriticalSection(&global_log_file_lock);
17968 #endif /* _WIN32 && !__SYMBIAN32__ */
17969 #if !defined(_WIN32)
17970  pthread_mutexattr_init(&pthread_mutex_attr);
17971  pthread_mutexattr_settype(&pthread_mutex_attr, PTHREAD_MUTEX_RECURSIVE);
17972 #endif
17973 
17974 #if defined(USE_LUA)
17975  lua_init_optional_libraries();
17976 #endif
17977  }
17978 
17979 
17980 #if !defined(NO_SSL)
17981  if (features_to_init & 2) {
17982  if (!mg_ssl_initialized) {
17983  if (initialize_ssl(ebuf, sizeof(ebuf))) {
17984  mg_ssl_initialized = 1;
17985  } else {
17986  (void)ebuf;
17987  /* TODO: print error */
17988  features_inited &= ~(2u);
17989  }
17990  } else {
17991  /* ssl already initialized */
17992  }
17993  }
17994 #endif
17995 
17996  /* Start WinSock for Windows */
17997  if (mg_init_library_called <= 0) {
17998 #if defined(_WIN32) && !defined(__SYMBIAN32__)
17999  WSADATA data;
18000  WSAStartup(MAKEWORD(2, 2), &data);
18001 #endif /* _WIN32 && !__SYMBIAN32__ */
18002  mg_init_library_called = 1;
18003  } else {
18004  mg_init_library_called++;
18005  }
18006 
18007  mg_global_unlock();
18008 
18009  return features_inited;
18010 }
18011 
18012 
18013 /* Un-initialize this library. */
18014 unsigned
18016 {
18017  if (mg_init_library_called <= 0) {
18018  return 0;
18019  }
18020 
18021  mg_global_lock();
18022 
18023  mg_init_library_called--;
18024  if (mg_init_library_called == 0) {
18025 #if defined(_WIN32) && !defined(__SYMBIAN32__)
18026  (void)WSACleanup();
18027 #endif /* _WIN32 && !__SYMBIAN32__ */
18028 #if !defined(NO_SSL)
18029  if (mg_ssl_initialized) {
18030  uninitialize_ssl();
18031  mg_ssl_initialized = 0;
18032  }
18033 #endif
18034 
18035 #if defined(_WIN32) && !defined(__SYMBIAN32__)
18036  (void)DeleteCriticalSection(&global_log_file_lock);
18037 #endif /* _WIN32 && !__SYMBIAN32__ */
18038 #if !defined(_WIN32)
18039  (void)pthread_mutexattr_destroy(&pthread_mutex_attr);
18040 #endif
18041 
18042  (void)pthread_key_delete(sTlsKey);
18043 
18044 #if defined(USE_LUA)
18045  lua_exit_optional_libraries();
18046 #endif
18047 
18048  mg_global_unlock();
18049  (void)pthread_mutex_destroy(&global_lock_mutex);
18050  return 1;
18051  }
18052 
18053  mg_global_unlock();
18054  return 1;
18055 }
18056 
18057 
18058 /* End of civetweb.c */
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:6402
#define mg_remove(conn, x)
Definition: civetweb.c:656
#define MAX_CGI_ENVIR_VARS
Definition: civetweb.c:766
static int set_ports_option(struct mg_context *ctx)
Definition: civetweb.c:13185
#define SSL_OP_ALL
Definition: civetweb.c:1599
int mg_get_response(struct mg_connection *conn, char *ebuf, size_t ebuf_len, int timeout)
Definition: civetweb.c:15471
#define SSL_set_app_data(s, arg)
Definition: civetweb.c:1844
const char * remote_user
Definition: civetweb.h:102
static const char * next_option(const char *list, struct vec *val, struct vec *eq_val)
Definition: civetweb.c:3672
int mg_url_decode(const char *src, int src_len, char *dst, int dst_len, int is_form_url_encoded)
Definition: civetweb.c:6360
static void close_all_listening_sockets(struct mg_context *ctx)
Definition: civetweb.c:13021
struct md5_state_s md5_state_t
#define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION
Definition: civetweb.c:1607
static int hexdump2string(void *mem, int memlen, char *buf, int buflen)
Definition: civetweb.c:13824
static const char * mg_fgets(char *buf, size_t size, struct mg_file *filep, char **p)
Definition: civetweb.c:7574
#define ERRNO
Definition: civetweb.c:661
#define SSL_CTX_set_ecdh_auto(ctx, onoff)
Definition: civetweb.c:1837
static int print_dir_entry(struct de *de)
Definition: civetweb.c:8271
struct x509 X509
Definition: civetweb.c:1584
static int parse_http_headers(char **buf, struct mg_header hdr[MG_MAX_HEADERS])
Definition: civetweb.c:9232
int pw_uid
Definition: TWinNTSystem.h:50
const char * local_uri
Definition: civetweb.h:93
#define SSL_CB_HANDSHAKE_DONE
Definition: civetweb.c:1611
static int cryptolib_users
Definition: civetweb.c:14035
#define BN_bn2hex
Definition: civetweb.c:1875
#define CRYPTO_set_id_callback
Definition: civetweb.c:1850
#define SSL_OP_NO_SSLv3
Definition: civetweb.c:1601
#define vsnprintf_impl
Definition: civetweb.c:634
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:5275
static constexpr double pi
#define ERR_get_error
Definition: civetweb.c:1852
auto * m
Definition: textangle.C:8
static char * mg_strndup(const char *ptr, size_t len)
Definition: civetweb.c:2990
#define mg_closedir(x)
Definition: civetweb.c:659
int mg_modify_passwords_file(const char *fname, const char *domain, const char *user, const char *pass)
Definition: civetweb.c:7918
int mg_get_server_ports(const struct mg_context *ctx, int size, struct mg_server_ports *ports)
Definition: civetweb.c:3179
#define SSL_CTX_use_certificate_chain_file
Definition: civetweb.c:1803
void mg_set_user_connection_data(struct mg_connection *conn, void *data)
Definition: civetweb.c:3136
int mg_start_thread(mg_thread_func_t func, void *param)
Definition: civetweb.c:5213
static int send_no_cache_header(struct mg_connection *conn)
Definition: civetweb.c:3853
#define X509_get_subject_name
Definition: civetweb.c:1861
static void gmt_time_string(char *buf, size_t buf_len, time_t *t)
Definition: civetweb.c:3258
#define mg_readdir(x)
Definition: civetweb.c:660
#define SSL_pending
Definition: civetweb.c:1806
static void do_ssi_include(struct mg_connection *conn, const char *ssi, char *tag, int include_level)
Definition: civetweb.c:10687
const char * mime_type
Definition: civetweb.c:7147
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:13533
static void ssl_get_client_cert_info(struct mg_connection *conn)
Definition: civetweb.c:13850
#define PRINTF_ARGS(x, y)
Definition: civetweb.h:778
#define mg_mkdir(conn, path, mode)
Definition: civetweb.c:655
struct evp_md EVP_MD
Definition: civetweb.c:1583
static int mg_poll(struct pollfd *pfd, unsigned int n, int milliseconds, volatile int *stop_server)
Definition: civetweb.c:5430
static struct ssl_func crypto_sw[]
Definition: civetweb.c:1927
size_t proto_len
Definition: civetweb.c:15050
static int set_uid_option(struct mg_context *ctx)
Definition: civetweb.c:13568
void mg_set_websocket_handler_with_subprotocols(struct mg_context *ctx, const char *uri, struct mg_websocket_subprotocols *subprotocols, 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:12232
const char * host
Definition: civetweb.h:1240
int mg_check_digest_access_authentication(struct mg_connection *conn, const char *realm, const char *filename)
Definition: civetweb.c:7769
static int mg_fopen(const struct mg_connection *conn, const char *path, int mode, struct mg_file *filep)
Definition: civetweb.c:2847
static const char * get_header(const struct mg_header *hdr, int num_hdr, const char *name)
Definition: civetweb.c:3591
const char * server_cert
Definition: civetweb.h:1243
#define SSL_ERROR_WANT_READ
Definition: civetweb.c:1615
static void uninitialize_ssl(void)
Definition: civetweb.c:14434
static int set_acl_option(struct mg_context *ctx)
Definition: civetweb.c:14491
#define ERR_free_strings
Definition: civetweb.c:1855
#define SSL_library_init
Definition: civetweb.c:1794
#define SSL_VERIFY_FAIL_IF_NO_PEER_CERT
Definition: civetweb.c:1597
#define is_websocket_protocol(conn)
Definition: civetweb.c:2444
static void handle_static_file_request(struct mg_connection *conn, const char *path, struct mg_file *filep, const char *mime_type, const char *additional_headers)
Definition: civetweb.c:8801
#define closesocket(a)
Definition: civetweb.c:654
static int isbyte(int n)
Definition: civetweb.c:11806
void mg_unlock_context(struct mg_context *ctx)
Definition: civetweb.c:11137
int mg_read(struct mg_connection *conn, void *buf, size_t len)
Definition: civetweb.c:6038
static void ssl_info_callback(const SSL *ssl, int what, int ret)
Definition: civetweb.c:14205
#define EVP_cleanup
Definition: civetweb.c:1859
static void bin2str(char *to, const unsigned char *p, size_t len)
Definition: civetweb.c:7304
static void produce_socket(struct mg_context *ctx, const struct socket *sp)
Definition: civetweb.c:16000
const char * mg_version(void)
Definition: civetweb.c:3361
static void handle_cgi_request(struct mg_connection *conn, const char *prog)
Definition: civetweb.c:10081
static void handle_file_based_request(struct mg_connection *conn, const char *path, struct mg_file *filep)
Definition: civetweb.c:12935
#define SSL_set_fd
Definition: civetweb.c:1790
#define va_copy(x, y)
Definition: civetweb.c:690
static void handle_request(struct mg_connection *conn)
Definition: civetweb.c:12442
static int is_in_script_path(const struct mg_connection *conn, const char *path)
Definition: civetweb.c:12386
const struct mg_option * mg_get_valid_options(void)
Definition: civetweb.c:2735
static int parse_http_response(char *buf, int len, struct mg_response_info *ri)
Definition: civetweb.c:9475
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:3029
static int prepare_cgi_environment(struct mg_connection *conn, const char *prog, struct cgi_environment *env)
Definition: civetweb.c:9885
static int refresh_trust(struct mg_connection *conn)
Definition: civetweb.c:13633
#define DEBUG_TRACE(fmt,...)
Definition: civetweb.c:1522
static void reset_per_request_attributes(struct mg_connection *conn)
Definition: civetweb.c:14498
#define OPENSSL_INIT_LOAD_CRYPTO_STRINGS
Definition: civetweb.c:1593
static void * event_create(void)
Definition: civetweb.c:2613
void mg_stop(struct mg_context *ctx)
Definition: civetweb.c:16590
void(* exit_context)(const struct mg_context *ctx)
Definition: civetweb.h:318
static void remove_double_dots_and_double_slashes(char *s)
Definition: civetweb.c:7117
#define SSL_write
Definition: civetweb.c:1788
#define ARRAY_SIZE(array)
Definition: civetweb.c:769
static int get_uri_type(const char *uri)
Definition: civetweb.c:15066
void mg_cry(const struct mg_connection *conn, const char *fmt,...)
Definition: civetweb.c:3283
static int get_option_index(const char *name)
Definition: civetweb.c:3094
static int open_file_in_memory(const struct mg_connection *conn, const char *path, struct mg_file *filep, int mode)
Definition: civetweb.c:2758
#define MAX_WORKER_THREADS
Definition: civetweb.c:299
static int ssl_use_pem_file(struct mg_context *ctx, const char *pem, const char *chain)
Definition: civetweb.c:14117
int mg_get_cookie(const char *cookie_header, const char *var_name, char *dst, size_t dst_size)
Definition: civetweb.c:6460
static FUNCTION_MAY_BE_UNUSED int mg_atomic_inc(volatile int *addr)
Definition: civetweb.c:989
#define f(i)
Definition: RSha256.hxx:104
const struct mg_response_info * mg_get_response_info(const struct mg_connection *conn)
Definition: civetweb.c:3397
static const char * get_proto_name(const struct mg_connection *conn)
Definition: civetweb.c:3410
static void * master_thread(void *thread_func_param)
Definition: civetweb.c:16502
unsigned mg_exit_library(void)
Definition: civetweb.c:18015
static int parse_range_header(const char *header, int64_t *a, int64_t *b)
Definition: civetweb.c:8761
#define CGI_ENVIRONMENT_SIZE
Definition: civetweb.c:765
#define ERR_remove_state
Definition: civetweb.c:1854
void mg_unlock_connection(struct mg_connection *conn)
Definition: civetweb.c:11121
char remote_addr[48]
Definition: civetweb.h:104
static pthread_mutex_t * ssl_mutexes
Definition: civetweb.c:13712
static void remove_bad_file(const struct mg_connection *conn, const char *path)
Definition: civetweb.c:9120
static double mg_difftimespec(const struct timespec *ts_now, const struct timespec *ts_before)
Definition: civetweb.c:3274
static int match_prefix(const char *pattern, size_t pattern_len, const char *str)
Definition: civetweb.c:3750
static void handle_propfind(struct mg_connection *conn, const char *path, struct mg_file_stat *filep)
Definition: civetweb.c:11066
int(* mg_authorization_handler)(struct mg_connection *conn, void *cbdata)
Definition: civetweb.h:500
static void close_connection(struct mg_connection *conn)
Definition: civetweb.c:14716
#define CIVETWEB_VERSION
Definition: civetweb.h:26
#define X509_get_issuer_name
Definition: civetweb.c:1862
#define malloc
Definition: civetweb.c:1347
#define ASN1_INTEGER_to_BN
Definition: civetweb.c:1876
#define CRYPTO_num_locks
Definition: civetweb.c:1847
#define SSL_get_peer_certificate
Definition: civetweb.c:1816
#define UINT64_FMT
Definition: civetweb.c:664
static void close_socket_gracefully(struct mg_connection *conn)
Definition: civetweb.c:14603
static int pull_all(FILE *fp, struct mg_connection *conn, char *buf, int len)
Definition: civetweb.c:5872
#define SSL_CTX_set_info_callback
Definition: civetweb.c:1827
static void handle_ssi_file_request(struct mg_connection *conn, const char *path, struct mg_file *filep)
Definition: civetweb.c:10913
static FUNCTION_MAY_BE_UNUSED uint64_t mg_get_current_time_ns(void)
Definition: civetweb.c:1455
static int check_authorization(struct mg_connection *conn, const char *path)
Definition: civetweb.c:7793
static int extention_matches_script(struct mg_connection *conn, const char *filename)
Definition: civetweb.c:6620
#define strcat0(a, b)
Definition: civetweb.c:17049
#define ENGINE_cleanup
Definition: civetweb.c:1856
static void interpret_uri(struct mg_connection *conn, char *filename, size_t filename_buf_len, struct mg_file_stat *filestat, int *is_found, int *is_script_resource, int *is_websocket_request, int *is_put_or_delete_request)
Definition: civetweb.c:6707
const char * default_value
Definition: civetweb.h:569
int SOCKET
Definition: civetweb.c:665
const char * mg_get_option(const struct mg_context *ctx, const char *name)
Definition: civetweb.c:3108
static int read_auth_file(struct mg_file *filep, struct read_auth_file_struct *workdata, int depth)
Definition: civetweb.c:7629
static void handle_not_modified_static_file_request(struct mg_connection *conn, struct mg_file *filep)
Definition: civetweb.c:8992
unsigned default_port
Definition: civetweb.c:15051
void mg_send_mime_file(struct mg_connection *conn, const char *path, const char *mime_type)
Definition: civetweb.c:9034
static int header_has_option(const char *header, const char *option)
Definition: civetweb.c:3729
static int should_decode_url(const struct mg_connection *conn)
Definition: civetweb.c:3835
#define SSL_OP_SINGLE_DH_USE
Definition: civetweb.c:1605
#define SSL_CTX_free
Definition: civetweb.c:1801
#define PRINTF_FORMAT_STRING(s)
Definition: civetweb.h:772
static int skip_to_end_of_word_and_terminate(char **ppw, int eol)
Definition: civetweb.c:9187
#define ERR_error_string
Definition: civetweb.c:1853
static int is_not_modified(const struct mg_connection *conn, const struct mg_file_stat *filestat)
Definition: civetweb.c:9668
static int mg_ssl_initialized
Definition: civetweb.c:1362
static struct mg_connection * fc(struct mg_context *ctx)
Definition: civetweb.c:3352
static int mg_start_thread_with_id(mg_thread_func_t func, void *param, pthread_t *threadidptr)
Definition: civetweb.c:5237
unsigned char md5_byte_t
Definition: md5.inl:50
static void open_auth_file(struct mg_connection *conn, const char *path, struct mg_file *filep)
Definition: civetweb.c:7386
#define SSL_VERIFY_PEER
Definition: civetweb.c:1596
static const double x2[5]
const char * request_method
Definition: civetweb.h:90
static const char * mg_strcasestr(const char *big_str, const char *small_str)
Definition: civetweb.c:3010
static int initialize_ssl(char *ebuf, size_t ebuf_len)
Definition: civetweb.c:14040
#define WINCDECL
Definition: civetweb.c:666
static struct mg_http_method_info http_methods[]
Definition: civetweb.c:9296
static struct ssl_func ssl_sw[]
Definition: civetweb.c:1887
#define SSL_OP_NO_TLSv1_1
Definition: civetweb.c:1604
#define SSL_CTX_clear_options(ctx, op)
Definition: civetweb.c:1835
#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:15634
void mg_set_auth_handler(struct mg_context *ctx, const char *uri, mg_request_handler handler, void *cbdata)
Definition: civetweb.c:12261
#define mg_static_assert(cond, txt)
Definition: civetweb.c:88
static int is_authorized_for_put(struct mg_connection *conn)
Definition: civetweb.c:7897
int mg_send_digest_access_authentication_request(struct mg_connection *conn, const char *realm)
Definition: civetweb.c:7884
static void * cryptolib_dll_handle
Definition: civetweb.c:14027
static int thread_idx_max
Definition: civetweb.c:1366
void mg_set_request_handler(struct mg_context *ctx, const char *uri, mg_request_handler handler, void *cbdata)
Definition: civetweb.c:12191
#define SSL_CTX_set_session_id_context
Definition: civetweb.c:1822
static char * skip_quoted(char **buf, const char *delimiters, const char *whitespace, char quotechar)
Definition: civetweb.c:3523
static double p2(double t, double a, double b, double c)
static int read_message(FILE *fp, struct mg_connection *conn, char *buf, int bufsiz, int *nread)
Definition: civetweb.c:9592
static int is_valid_port(unsigned long port)
Definition: civetweb.c:8030
static int parse_net(const char *spec, uint32_t *net, uint32_t *mask)
Definition: civetweb.c:11813
#define SSL_CTX_use_PrivateKey_file
Definition: civetweb.c:1795
static int alloc_vprintf2(char **buf, const char *fmt, va_list ap)
Definition: civetweb.c:6238
static int get_message(struct mg_connection *conn, char *ebuf, size_t ebuf_len, int *err)
Definition: civetweb.c:15277
struct x509_name X509_NAME
Definition: civetweb.c:1579
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:15031
static void master_thread_run(void *thread_func_param)
Definition: civetweb.c:16368
SHA_API void SHA1_Init(SHA_CTX *context)
Definition: sha1.inl:257
static constexpr double L
static int set_blocking_mode(SOCKET sock)
Definition: civetweb.c:5382
static int set_tcp_nodelay(SOCKET sock, int nodelay_on)
Definition: civetweb.c:14587
#define SSL_get_error
Definition: civetweb.c:1789
static void * ssllib_dll_handle
Definition: civetweb.c:14026
static void init_connection(struct mg_connection *conn)
Definition: civetweb.c:15770
static const char * suggest_connection_header(const struct mg_connection *conn)
Definition: civetweb.c:3846
static void mg_set_thread_name(const char *name)
Definition: civetweb.c:2669
#define SSL_shutdown
Definition: civetweb.c:1811
static struct mg_option config_options[]
Definition: civetweb.c:2134
long long mg_store_body(struct mg_connection *conn, const char *path)
Definition: civetweb.c:9130
static int sslize(struct mg_connection *conn, SSL_CTX *s, int(*func)(SSL *), volatile int *stop_server)
Definition: civetweb.c:13716
static int parse_port_string(const struct vec *vec, struct socket *so, int *ip_version)
Definition: civetweb.c:13054
void mg_send_file(struct mg_connection *conn, const char *path)
Definition: civetweb.c:9027
static int set_non_blocking_mode(SOCKET sock)
Definition: civetweb.c:5368
#define SSLv23_client_method
Definition: civetweb.c:1805
const char * mg_get_response_code_text(const struct mg_connection *conn, int response_code)
Definition: civetweb.c:3926
#define realloc
Definition: civetweb.c:1349
#define SSL_CTX_set_verify_depth
Definition: civetweb.c:1815
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:14853
static __inline void * mg_calloc(size_t a, size_t b)
Definition: civetweb.c:1288
#define SSL_OP_NO_SSLv2
Definition: civetweb.c:1600
#define SOMAXCONN
Definition: civetweb.c:1545
#define INITIAL_DEPTH
Definition: civetweb.c:7612
static int get_first_ssl_listener_index(const struct mg_context *ctx)
Definition: civetweb.c:11978
int(* mg_websocket_data_handler)(struct mg_connection *, int, char *, size_t, void *)
Definition: civetweb.h:444
static constexpr double second
#define SSL_CTX_use_certificate_file
Definition: civetweb.c:1797
static void get_system_name(char **sysName)
Definition: civetweb.c:16624
static int mg_join_thread(pthread_t threadid)
Definition: civetweb.c:5264
int mg_printf(struct mg_connection *conn, const char *fmt,...)
Definition: civetweb.c:6346
#define INT64_MAX
Definition: civetweb.c:294
#define BN_free
Definition: civetweb.c:1878
struct asn1_integer ASN1_INTEGER
Definition: civetweb.c:1580
static pthread_mutexattr_t pthread_mutex_attr
Definition: civetweb.c:760
static FUNCTION_MAY_BE_UNUSED void mg_global_unlock(void)
Definition: civetweb.c:981
static int dir_scan_callback(struct de *de, void *data)
Definition: civetweb.c:8548
char * mg_md5(char buf[33],...)
Definition: civetweb.c:7319
static int set_ssl_option(struct mg_context *ctx)
Definition: civetweb.c:14222
#define SSL_CTX_check_private_key
Definition: civetweb.c:1821
#define MG_MAX_HEADERS
Definition: civetweb.h:80
static const struct mg_http_method_info * get_http_method_info(const char *method)
Definition: civetweb.c:9353
void(* mg_websocket_close_handler)(const struct mg_connection *, void *)
Definition: civetweb.h:449
static time_t parse_date_string(const char *datetime)
Definition: civetweb.c:7059
#define EVP_get_digestbyname
Definition: civetweb.c:1868
#define SSL_ERROR_WANT_CONNECT
Definition: civetweb.c:1620
#define SHUTDOWN_BOTH
Definition: civetweb.c:308
struct ssl_st SSL
Definition: civetweb.c:1575
static const char * ssl_error(void)
Definition: civetweb.c:13815
static void mkcol(struct mg_connection *conn, const char *path)
Definition: civetweb.c:10395
static int mg_inet_pton(int af, const char *src, void *dst, size_t dstlen)
Definition: civetweb.c:8037
static const char * get_rel_url_at_current_server(const char *uri, const struct mg_connection *conn)
Definition: civetweb.c:15154
static int WINCDECL compare_dir_entries(const void *p1, const void *p2)
Definition: civetweb.c:8355
const void * SOCK_OPT_TYPE
Definition: civetweb.c:624
size_t ext_len
Definition: civetweb.c:7146
static int mg_vprintf(struct mg_connection *conn, const char *fmt, va_list ap)
Definition: civetweb.c:6328
ROOT::R::TRInterface & r
Definition: Object.C:4
struct ssl_method_st SSL_METHOD
Definition: civetweb.c:1576
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 int mg_fgetc(struct mg_file *filep, int offset)
Definition: civetweb.c:10794
static int64_t push_all(struct mg_context *ctx, FILE *fp, SOCKET sock, SSL *ssl, const char *buf, int64_t len)
Definition: civetweb.c:5641
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:7342
static void event_destroy(void *eventhdl)
Definition: civetweb.c:2658
auto * a
Definition: textangle.C:12
static int push_inner(struct mg_context *ctx, FILE *fp, SOCKET sock, SSL *ssl, const char *buf, int len, double timeout)
Definition: civetweb.c:5479
static struct mg_context common_client_context
Definition: civetweb.c:14849
static int substitute_index_file(struct mg_connection *conn, char *path, size_t path_len, struct mg_file_stat *filestat)
Definition: civetweb.c:6659
#define INT64_FMT
Definition: civetweb.c:663
static void print_props(struct mg_connection *conn, const char *uri, struct mg_file_stat *filep)
Definition: civetweb.c:10999
int mg_url_encode(const char *src, char *dst, size_t dst_len)
Definition: civetweb.c:8243
#define OPENSSL_INIT_LOAD_SSL_STRINGS
Definition: civetweb.c:1592
static int mg_read_inner(struct mg_connection *conn, void *buf, size_t len)
Definition: civetweb.c:5956
#define SSL_new
Definition: civetweb.c:1791
#define SSL_CTX_set_default_verify_paths
Definition: civetweb.c:1814
static int consume_socket(struct mg_context *ctx, struct socket *sp, int thread_index)
Definition: civetweb.c:16021
static int get_response(struct mg_connection *conn, char *ebuf, size_t ebuf_len, int *err)
Definition: civetweb.c:15413
#define calloc
Definition: civetweb.c:1348
void mg_send_mime_file2(struct mg_connection *conn, const char *path, const char *mime_type, const char *additional_headers)
Definition: civetweb.c:9043
#define s1(x)
Definition: RSha256.hxx:91
static int is_put_or_delete_method(const struct mg_connection *conn)
Definition: civetweb.c:6607
#define mg_malloc_ctx(a, c)
Definition: civetweb.c:1305
static __inline void mg_free(void *a)
Definition: civetweb.c:1300
unsigned mg_check_feature(unsigned feature)
Definition: civetweb.c:16992
static void ssl_locking_callback(int mode, int mutex_num, const char *file, int line)
Definition: civetweb.c:13934
static double p1(double t, double a, double b)
static int put_dir(struct mg_connection *conn, const char *path)
Definition: civetweb.c:9083
static int must_hide_file(struct mg_connection *conn, const char *path)
Definition: civetweb.c:8391
struct mg_header http_headers[MG_MAX_HEADERS]
Definition: civetweb.h:119
static char mg_getc(struct mg_connection *conn)
Definition: civetweb.c:6024
const char * http_version
Definition: civetweb.h:99
#define X509_free
Definition: civetweb.c:1860
void mg_lock_connection(struct mg_connection *conn)
Definition: civetweb.c:11113
static __inline void * mg_realloc(void *a, size_t b)
Definition: civetweb.c:1294
static void put_file(struct mg_connection *conn, const char *path)
Definition: civetweb.c:10469
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:15019
#define SSL_CTX_new
Definition: civetweb.c:1792
#define mg_calloc_ctx(a, b, c)
Definition: civetweb.c:1306
struct mg_context * mg_start(const struct mg_callbacks *callbacks, void *user_data, const char **options)
Definition: civetweb.c:16676
int mg_send_chunk(struct mg_connection *conn, const char *chunk, unsigned int chunk_len)
Definition: civetweb.c:6200
int mg_write(struct mg_connection *conn, const void *buf, size_t len)
Definition: civetweb.c:6138
static int scan_directory(struct mg_connection *conn, const char *dir, void *data, int(*cb)(struct de *, void *))
Definition: civetweb.c:8405
static const char * header_val(const struct mg_connection *conn, const char *header)
Definition: civetweb.c:13425
static constexpr double ms
static int remove_directory(struct mg_connection *conn, const char *dir)
Definition: civetweb.c:8461
const char * name
Definition: civetweb.h:567
constexpr Double_t E()
Base of natural log: .
Definition: TMath.h:97
int mg_get_context_info(const struct mg_context *ctx, char *buffer, int buflen)
Definition: civetweb.c:17900
#define h(i)
Definition: RSha256.hxx:106
int mg_get_request_link(const struct mg_connection *conn, char *buf, size_t buflen)
Definition: civetweb.c:3437
static int should_keep_alive(const struct mg_connection *conn)
Definition: civetweb.c:3796
void mg_close_connection(struct mg_connection *conn)
Definition: civetweb.c:14779
static void handle_directory_request(struct mg_connection *conn, const char *dir)
Definition: civetweb.c:8573
int(* mg_request_handler)(struct mg_connection *conn, void *cbdata)
Definition: civetweb.h:387
static void send_file_data(struct mg_connection *conn, struct mg_file *filep, int64_t offset, int64_t len)
Definition: civetweb.c:8654
const char * extension
Definition: civetweb.c:7145
int mg_strcasecmp(const char *s1, const char *s2)
Definition: civetweb.c:2977
#define X509_NAME_oneline
Definition: civetweb.c:1863
static void tls_dtor(void *key)
Definition: civetweb.c:13610
static int lowercase(const char *s)
Definition: civetweb.c:2955
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:15527
static int mg_stat(const struct mg_connection *conn, const char *path, struct mg_file_stat *filep)
Definition: civetweb.c:5163
#define SSL_OP_NO_TLSv1
Definition: civetweb.c:1602
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 SSL_OP_CIPHER_SERVER_PREFERENCE
Definition: civetweb.c:1606
static void get_mime_type(struct mg_context *ctx, const char *path, struct vec *vec)
Definition: civetweb.c:7269
#define d(i)
Definition: RSha256.hxx:102
struct bignum BIGNUM
Definition: civetweb.c:1581
static int set_throttle(const char *spec, uint32_t remote_ip, const char *uri)
Definition: civetweb.c:11832
static const double x1[5]
const char * mg_get_header(const struct mg_connection *conn, const char *name)
Definition: civetweb.c:3628
static int mg_fclose(struct mg_file_access *fileacc)
Definition: civetweb.c:2928
#define SSL_ERROR_WANT_WRITE
Definition: civetweb.c:1616
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:1578
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:3865
#define INVALID_SOCKET
Definition: civetweb.c:662
void * mg_get_user_data(const struct mg_context *ctx)
Definition: civetweb.c:3129
#define CRYPTO_LIB
Definition: civetweb.c:648
static void discard_unread_request_data(struct mg_connection *conn)
Definition: civetweb.c:5916
const char * status_text
Definition: civetweb.h:133
char static_assert_replacement[1]
Definition: civetweb.c:87
#define SSL_CB_HANDSHAKE_START
Definition: civetweb.c:1610
#define CRYPTO_cleanup_all_ex_data
Definition: civetweb.c:1858
#define MG_FOPEN_MODE_WRITE
Definition: civetweb.c:2748
static void fclose_on_exec(struct mg_file_access *filep, struct mg_connection *conn)
Definition: civetweb.c:8783
#define CRYPTO_set_locking_callback
Definition: civetweb.c:1848
#define TRUE
struct ossl_init_settings_st OPENSSL_INIT_SETTINGS
Definition: civetweb.c:1582
static uint32_t get_remote_ip(const struct mg_connection *conn)
Definition: civetweb.c:11866
#define free
Definition: civetweb.c:1350
#define i2d_X509
Definition: civetweb.c:1874
static int get_request_handler(struct mg_connection *conn, int handler_type, mg_request_handler *handler, struct mg_websocket_subprotocols **subprotocols, 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:12282
#define EVP_Digest
Definition: civetweb.c:1870
static FUNCTION_MAY_BE_UNUSED unsigned long mg_current_thread_id(void)
Definition: civetweb.c:1405
#define MG_FOPEN_MODE_READ
Definition: civetweb.c:2745
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
struct mg_header http_headers[MG_MAX_HEADERS]
Definition: civetweb.h:140
static int is_file_in_memory(const struct mg_connection *conn, const char *path)
Definition: civetweb.c:2819
int(* mg_websocket_connect_handler)(const struct mg_connection *, void *)
Definition: civetweb.h:441
#define SSL_load_error_strings
Definition: civetweb.c:1802
static void send_ssi_file(struct mg_connection *, const char *, struct mg_file *, int)
Definition: civetweb.c:10811
#define X509_get_serialNumber
Definition: civetweb.c:1865
#define SSL_get_app_data(s)
Definition: civetweb.c:1845
static void process_new_connection(struct mg_connection *conn)
Definition: civetweb.c:15807
TCanvas * slash()
Definition: slash.C:1
static void * worker_thread_run(struct worker_thread_args *thread_args)
Definition: civetweb.c:16110
#define PASSWORDS_FILE_NAME
Definition: civetweb.c:764
#define IP_ADDR_STR_LEN
Definition: civetweb.c:1538
static const char * get_http_version(const struct mg_connection *conn)
Definition: civetweb.c:3649
#define SSL_OP_NO_COMPRESSION
Definition: civetweb.c:1608
static void * worker_thread(void *thread_func_param)
Definition: civetweb.c:16275
static int mg_get_system_info_impl(char *buffer, int buflen)
Definition: civetweb.c:17060
R__EXTERN C unsigned int sleep(unsigned int seconds)
#define mg_opendir(conn, x)
Definition: civetweb.c:658
static int alloc_vprintf(char **out_buf, char *prealloc_buf, size_t prealloc_size, const char *fmt, va_list ap)
Definition: civetweb.c:6271
int pw_gid
Definition: TWinNTSystem.h:51
static int pull_inner(FILE *fp, struct mg_connection *conn, char *buf, int len, double timeout)
Definition: civetweb.c:5685
#define SSL_CTX_set_verify
Definition: civetweb.c:1807
#define SSL_free
Definition: civetweb.c:1784
static FUNCTION_MAY_BE_UNUSED void mg_global_lock(void)
Definition: civetweb.c:973
const struct mg_request_info * mg_get_request_info(const struct mg_connection *conn)
Definition: civetweb.c:3368
static int is_valid_http_method(const char *method)
Definition: civetweb.c:9372
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:8074
static void delete_file(struct mg_connection *conn, const char *path)
Definition: civetweb.c:10618
typedef void((*Func_t)())
#define FALSE
#define SSL_CTX_set_cipher_list
Definition: civetweb.c:1825
#define SSL_CTX_set_options(ctx, op)
Definition: civetweb.c:1833
#define SSLv23_server_method
Definition: civetweb.c:1793
#define STRUCT_FILE_INITIALIZER
Definition: civetweb.c:2019
#define mg_realloc_ctx(a, b, c)
Definition: civetweb.c:1307
void(* mg_websocket_ready_handler)(struct mg_connection *, void *)
Definition: civetweb.h:443
static int authorize(struct mg_connection *conn, struct mg_file *filep, const char *realm)
Definition: civetweb.c:7741
static void set_close_on_exec(SOCKET fd, struct mg_connection *conn)
Definition: civetweb.c:5199
static void do_ssi_exec(struct mg_connection *conn, char *tag)
Definition: civetweb.c:10773
static int get_http_header_len(const char *buf, int buflen)
Definition: civetweb.c:7004
static int event_wait(void *eventhdl)
Definition: civetweb.c:2636
auto * l
Definition: textangle.C:4
static int print_dav_dir_entry(struct de *de, void *data)
Definition: civetweb.c:11030
Definition: file.py:1
#define SSL_LIB
Definition: civetweb.c:645
#define SSL_connect
Definition: civetweb.c:1786
#define IGNORE_UNUSED_RESULT(a)
Definition: civetweb.c:138
static void mg_strlcpy(register char *dst, register const char *src, size_t n)
Definition: civetweb.c:2945
#define SHUTDOWN_WR
Definition: civetweb.c:307
static int send_additional_header(struct mg_connection *conn)
Definition: civetweb.c:3896
static __inline void * mg_malloc(size_t a)
Definition: civetweb.c:1282
const char * mg_get_builtin_mime_type(const char *path)
Definition: civetweb.c:7247
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:1577
const char * name
Definition: civetweb.h:83
void * mg_get_user_connection_data(const struct mg_connection *conn)
Definition: civetweb.c:3145
static uint64_t get_random(void)
Definition: civetweb.c:5401
static void send_options(struct mg_connection *conn)
Definition: civetweb.c:10967
static int event_signal(void *eventhdl)
Definition: civetweb.c:2647
SHA_API void SHA1_Update(SHA_CTX *context, const uint8_t *data, const uint32_t len)
Definition: sha1.inl:270
const char * proto
Definition: civetweb.c:15049
void mg_lock_context(struct mg_context *ctx)
Definition: civetweb.c:11129
void *(* mg_thread_func_t)(void *)
Definition: civetweb.h:1126
#define c(i)
Definition: RSha256.hxx:101
#define SOCKET_TIMEOUT_QUANTUM
Definition: civetweb.c:303
static const struct @133 abs_uri_protocols[]
unsigned mg_init_library(unsigned features)
Definition: civetweb.c:17941
static void mg_set_handler_type(struct mg_context *ctx, const char *uri, int handler_type, int is_delete_request, mg_request_handler handler, struct mg_websocket_subprotocols *subprotocols, 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:12041
#define MG_FOPEN_MODE_APPEND
Definition: civetweb.c:2751
#define SSL_CTX_load_verify_locations
Definition: civetweb.c:1812
static int is_file_opened(const struct mg_file_access *fileacc)
Definition: civetweb.c:2826
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:1365
static int set_gpass_option(struct mg_context *ctx)
Definition: civetweb.c:14475
static const char * month_names[]
Definition: civetweb.c:1958
SHA_API void SHA1_Final(unsigned char *digest, SHA_CTX *context)
Definition: sha1.inl:297
static void redirect_to_https_port(struct mg_connection *conn, int ssl_index)
Definition: civetweb.c:11992
#define MG_BUF_LEN
Definition: civetweb.c:767
#define MSG_NOSIGNAL
Definition: civetweb.c:1541
static int mg_init_library_called
Definition: civetweb.c:1359
#define SSL_accept
Definition: civetweb.c:1785
CIVETWEB_API int mg_websocket_client_write(struct mg_connection *conn, int opcode, const char *data, size_t data_len)
const char * query_string
Definition: civetweb.h:100
#define FUNCTION_MAY_BE_UNUSED
Definition: civetweb.c:163
static char * mg_strdup(const char *str)
Definition: civetweb.c:3003
static pthread_mutex_t global_lock_mutex
Definition: civetweb.c:958
MD5_STATIC void md5_init(md5_state_t *pms)
Definition: md5.inl:401
#define SSL_VERIFY_NONE
Definition: civetweb.c:1595
static void accept_new_connection(const struct socket *listener, struct mg_context *ctx)
Definition: civetweb.c:16287
static void sockaddr_to_string(char *buf, size_t len, const union usa *usa)
Definition: civetweb.c:3224
#define CONF_modules_unload
Definition: civetweb.c:1857
const char * client_cert
Definition: civetweb.h:1242
static void free_context(struct mg_context *ctx)
Definition: civetweb.c:16511
int mg_get_var(const char *data, size_t data_len, const char *name, char *dst, size_t dst_len)
Definition: civetweb.c:6391
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:12212
static int parse_auth_header(struct mg_connection *conn, char *buf, size_t buf_size, struct ah *ah)
Definition: civetweb.c:7463
static const struct @132 builtin_mime_types[]
static int parse_http_request(char *buf, int len, struct mg_request_info *ri)
Definition: civetweb.c:9388
void mg_send_http_error(struct mg_connection *conn, int status, const char *fmt,...)
Definition: civetweb.c:4123
const Int_t n
Definition: legend1.C:16
const char * value
Definition: civetweb.h:84
#define SSL_ERROR_WANT_ACCEPT
Definition: civetweb.c:1621
static int get_month_index(const char *s)
Definition: civetweb.c:7043
static FUNCTION_MAY_BE_UNUSED int mg_atomic_dec(volatile int *addr)
Definition: civetweb.c:1012
const char * http_version
Definition: civetweb.h:134
#define MG_FOPEN_MODE_NONE
Definition: civetweb.c:2742
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:9685
static void * load_dll(char *ebuf, size_t ebuf_len, const char *dll_name, struct ssl_func *sw)
Definition: civetweb.c:13951
struct mg_context * mg_get_context(const struct mg_connection *conn)
Definition: civetweb.c:3122
const char * cnt
Definition: TXMLSetup.cxx:74
static void construct_etag(char *buf, size_t buf_len, const struct mg_file_stat *filestat)
Definition: civetweb.c:8768
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:13438
#define mg_sleep(x)
Definition: civetweb.c:657
int mg_get_system_info(char *buffer, int buflen)
Definition: civetweb.c:17885
const char * request_uri
Definition: civetweb.h:91
#define SSL_ERROR_SYSCALL
Definition: civetweb.c:1618
int mg_strncasecmp(const char *s1, const char *s2, size_t len)
Definition: civetweb.c:2962
#define CIVETWEB_API
Definition: civetweb.h:44
static int get_request(struct mg_connection *conn, char *ebuf, size_t ebuf_len, int *err)
Definition: civetweb.c:15353
static void send_authorization_request(struct mg_connection *conn, const char *realm)
Definition: civetweb.c:7843
#define OPENSSL_free(a)
Definition: civetweb.c:1881
#define SSL_read
Definition: civetweb.c:1787
static long ssl_get_protocol(int version_id)
Definition: civetweb.c:14185
static void * realloc2(void *ptr, size_t size)
Definition: civetweb.c:8537