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