~ubuntu-branches/ubuntu/saucy/argyll/saucy

« back to all changes in this revision

Viewing changes to spectro/mongoose.c

  • Committer: Package Import Robot
  • Author(s): Christian Marillat
  • Date: 2012-04-25 07:46:07 UTC
  • mfrom: (1.2.2) (13.1.15 sid)
  • Revision ID: package-import@ubuntu.com-20120425074607-yjqadetw8kum9skc
Tags: 1.4.0-4
Should Build-Depends on libusb-dev (Closes: #670329).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Copyright (c) 2004-2011 Sergey Lyubka
 
2
//
 
3
// Permission is hereby granted, free of charge, to any person obtaining a copy
 
4
// of this software and associated documentation files (the "Software"), to deal
 
5
// in the Software without restriction, including without limitation the rights
 
6
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 
7
// copies of the Software, and to permit persons to whom the Software is
 
8
// furnished to do so, subject to the following conditions:
 
9
//
 
10
// The above copyright notice and this permission notice shall be included in
 
11
// all copies or substantial portions of the Software.
 
12
//
 
13
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 
14
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 
15
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 
16
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 
17
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 
18
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 
19
// THE SOFTWARE.
 
20
 
 
21
#if defined(_WIN32)
 
22
#define _CRT_SECURE_NO_WARNINGS // Disable deprecation warning in VS2005
 
23
#else
 
24
#define _XOPEN_SOURCE 600     // For flockfile() on Linux
 
25
#define _LARGEFILE_SOURCE     // Enable 64-bit file offsets
 
26
#define __STDC_FORMAT_MACROS  // <inttypes.h> wants this for C++
 
27
#define __STDC_LIMIT_MACROS   // C++ wants that for INT64_MAX
 
28
#endif
 
29
 
 
30
#if defined(__SYMBIAN32__)
 
31
#define NO_SSL // SSL is not supported
 
32
#define NO_CGI // CGI is not supported
 
33
#define PATH_MAX FILENAME_MAX
 
34
#endif // __SYMBIAN32__
 
35
 
 
36
#ifndef _WIN32_WCE // Some ANSI #includes are not available on Windows CE
 
37
#include <sys/types.h>
 
38
#include <sys/stat.h>
 
39
#include <errno.h>
 
40
#include <signal.h>
 
41
#include <fcntl.h>
 
42
#endif // !_WIN32_WCE
 
43
 
 
44
#include <time.h>
 
45
#include <stdlib.h>
 
46
#include <stdarg.h>
 
47
#include <assert.h>
 
48
#include <string.h>
 
49
#include <ctype.h>
 
50
#include <limits.h>
 
51
#include <stddef.h>
 
52
#include <stdio.h>
 
53
 
 
54
#if defined(_WIN32) && !defined(__SYMBIAN32__) // Windows specific
 
55
#define _WIN32_WINNT 0x0400 // To make it link in VS2005
 
56
#include <windows.h>
 
57
 
 
58
#ifndef PATH_MAX
 
59
#define PATH_MAX MAX_PATH
 
60
#endif
 
61
 
 
62
#ifndef _WIN32_WCE
 
63
#include <process.h>
 
64
#include <direct.h>
 
65
#include <io.h>
 
66
#else // _WIN32_WCE
 
67
#include <winsock2.h>
 
68
#define NO_CGI // WinCE has no pipes
 
69
 
 
70
typedef long off_t;
 
71
#define BUFSIZ  4096
 
72
 
 
73
#define errno   GetLastError()
 
74
#define strerror(x)  _ultoa(x, (char *) _alloca(sizeof(x) *3 ), 10)
 
75
#endif // _WIN32_WCE
 
76
 
 
77
#define MAKEUQUAD(lo, hi) ((uint64_t)(((uint32_t)(lo)) | \
 
78
      ((uint64_t)((uint32_t)(hi))) << 32))
 
79
#define RATE_DIFF 10000000 // 100 nsecs
 
80
#define EPOCH_DIFF MAKEUQUAD(0xd53e8000, 0x019db1de)
 
81
#define SYS2UNIX_TIME(lo, hi) \
 
82
  (time_t) ((MAKEUQUAD((lo), (hi)) - EPOCH_DIFF) / RATE_DIFF)
 
83
 
 
84
// Visual Studio 6 does not know __func__ or __FUNCTION__
 
85
// The rest of MS compilers use __FUNCTION__, not C99 __func__
 
86
// Also use _strtoui64 on modern M$ compilers
 
87
#if defined(_MSC_VER) && _MSC_VER < 1300
 
88
#define STRX(x) #x
 
89
#define STR(x) STRX(x)
 
90
#define __func__ "line " STR(__LINE__)
 
91
#define strtoull(x, y, z) strtoul(x, y, z)
 
92
#define strtoll(x, y, z) strtol(x, y, z)
 
93
#else
 
94
#define __func__  __FUNCTION__
 
95
#define strtoull(x, y, z) _strtoui64(x, y, z)
 
96
#define strtoll(x, y, z) _strtoi64(x, y, z)
 
97
#endif // _MSC_VER
 
98
 
 
99
#define ERRNO   GetLastError()
 
100
#define NO_SOCKLEN_T
 
101
#define SSL_LIB   "ssleay32.dll"
 
102
#define CRYPTO_LIB  "libeay32.dll"
 
103
#define DIRSEP '\\'
 
104
#define IS_DIRSEP_CHAR(c) ((c) == '/' || (c) == '\\')
 
105
#define O_NONBLOCK  0
 
106
#if !defined(EWOULDBLOCK)
 
107
#define EWOULDBLOCK  WSAEWOULDBLOCK
 
108
#endif // !EWOULDBLOCK
 
109
#define _POSIX_
 
110
#define INT64_FMT  "I64d"
 
111
 
 
112
#define WINCDECL __cdecl
 
113
#define SHUT_WR 1
 
114
#define snprintf _snprintf
 
115
#define vsnprintf _vsnprintf
 
116
#define sleep(x) Sleep((x) * 1000)
 
117
 
 
118
#define pipe(x) _pipe(x, BUFSIZ, _O_BINARY)
 
119
#define popen(x, y) _popen(x, y)
 
120
#define pclose(x) _pclose(x)
 
121
#define close(x) _close(x)
 
122
#define dlsym(x,y) GetProcAddress((HINSTANCE) (x), (y))
 
123
#define RTLD_LAZY  0
 
124
#define fseeko(x, y, z) fseek((x), (y), (z))
 
125
#define fdopen(x, y) _fdopen((x), (y))
 
126
#define write(x, y, z) _write((x), (y), (unsigned) z)
 
127
#define read(x, y, z) _read((x), (y), (unsigned) z)
 
128
#define flockfile(x) EnterCriticalSection(&global_log_file_lock)
 
129
#define funlockfile(x) LeaveCriticalSection(&global_log_file_lock)
 
130
 
 
131
#if !defined(fileno)
 
132
#define fileno(x) _fileno(x)
 
133
#endif // !fileno MINGW #defines fileno
 
134
 
 
135
typedef HANDLE pthread_mutex_t;
 
136
typedef struct {HANDLE signal, broadcast;} pthread_cond_t;
 
137
typedef DWORD pthread_t;
 
138
#define pid_t HANDLE // MINGW typedefs pid_t to int. Using #define here.
 
139
 
 
140
struct timespec {
 
141
  long tv_nsec;
 
142
  long tv_sec;
 
143
};
 
144
 
 
145
static int pthread_mutex_lock(pthread_mutex_t *);
 
146
static int pthread_mutex_unlock(pthread_mutex_t *);
 
147
static FILE *mg_fopen(const char *path, const char *mode);
 
148
 
 
149
#if defined(HAVE_STDINT)
 
150
#include <stdint.h>
 
151
#else
 
152
typedef unsigned int  uint32_t;
 
153
typedef unsigned short  uint16_t;
 
154
typedef unsigned __int64 uint64_t;
 
155
typedef __int64   int64_t;
 
156
#define INT64_MAX  9223372036854775807
 
157
#endif // HAVE_STDINT
 
158
 
 
159
// POSIX dirent interface
 
160
struct dirent {
 
161
  char d_name[PATH_MAX];
 
162
};
 
163
 
 
164
typedef struct DIR {
 
165
  HANDLE   handle;
 
166
  WIN32_FIND_DATAW info;
 
167
  struct dirent  result;
 
168
} DIR;
 
169
 
 
170
#else    // UNIX  specific
 
171
#include <sys/wait.h>
 
172
#include <sys/socket.h>
 
173
#include <sys/select.h>
 
174
#include <netinet/in.h>
 
175
#include <arpa/inet.h>
 
176
#include <sys/time.h>
 
177
#include <stdint.h>
 
178
#include <inttypes.h>
 
179
#include <netdb.h>
 
180
 
 
181
#include <pwd.h>
 
182
#include <unistd.h>
 
183
#include <dirent.h>
 
184
#if !defined(NO_SSL_DL) && !defined(NO_SSL)
 
185
#include <dlfcn.h>
 
186
#endif
 
187
#include <pthread.h>
 
188
#if defined(__MACH__)
 
189
#define SSL_LIB   "libssl.dylib"
 
190
#define CRYPTO_LIB  "libcrypto.dylib"
 
191
#else
 
192
#if !defined(SSL_LIB)
 
193
#define SSL_LIB   "libssl.so"
 
194
#endif
 
195
#if !defined(CRYPTO_LIB)
 
196
#define CRYPTO_LIB  "libcrypto.so"
 
197
#endif
 
198
#endif
 
199
#define DIRSEP   '/'
 
200
#define IS_DIRSEP_CHAR(c) ((c) == '/')
 
201
#ifndef O_BINARY
 
202
#define O_BINARY  0
 
203
#endif // O_BINARY
 
204
#define closesocket(a) close(a)
 
205
#define mg_fopen(x, y) fopen(x, y)
 
206
#define mg_mkdir(x, y) mkdir(x, y)
 
207
#define mg_remove(x) remove(x)
 
208
#define mg_rename(x, y) rename(x, y)
 
209
#define ERRNO errno
 
210
#define INVALID_SOCKET (-1)
 
211
#define INT64_FMT PRId64
 
212
typedef int SOCKET;
 
213
#define WINCDECL
 
214
 
 
215
#endif // End of Windows and UNIX specific includes
 
216
 
 
217
#include "mongoose.h"
 
218
 
 
219
#define MONGOOSE_VERSION "3.1"
 
220
#define PASSWORDS_FILE_NAME ".htpasswd"
 
221
#define CGI_ENVIRONMENT_SIZE 4096
 
222
#define MAX_CGI_ENVIR_VARS 64
 
223
#define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0]))
 
224
 
 
225
#ifdef _WIN32
 
226
static CRITICAL_SECTION global_log_file_lock;
 
227
static pthread_t pthread_self(void) {
 
228
  return GetCurrentThreadId();
 
229
}
 
230
#endif // _WIN32
 
231
 
 
232
#if defined(DEBUG)
 
233
#define DEBUG_TRACE(x) do { \
 
234
  flockfile(stdout); \
 
235
  printf("*** %lu.%p.%s.%d: ", \
 
236
         (unsigned long) time(NULL), (void *) pthread_self(), \
 
237
         __func__, __LINE__); \
 
238
  printf x; \
 
239
  putchar('\n'); \
 
240
  fflush(stdout); \
 
241
  funlockfile(stdout); \
 
242
} while (0)
 
243
#else
 
244
#define DEBUG_TRACE(x)
 
245
#endif // DEBUG
 
246
 
 
247
// Darwin prior to 7.0 and Win32 do not have socklen_t
 
248
#ifdef NO_SOCKLEN_T
 
249
typedef int socklen_t;
 
250
#endif // NO_SOCKLEN_T
 
251
 
 
252
#if !defined(MSG_NOSIGNAL)
 
253
#define MSG_NOSIGNAL 0
 
254
#endif
 
255
 
 
256
typedef void * (*mg_thread_func_t)(void *);
 
257
 
 
258
static const char *http_500_error = "Internal Server Error";
 
259
 
 
260
// Snatched from OpenSSL includes. I put the prototypes here to be independent
 
261
// from the OpenSSL source installation. Having this, mongoose + SSL can be
 
262
// built on any system with binary SSL libraries installed.
 
263
typedef struct ssl_st SSL;
 
264
typedef struct ssl_method_st SSL_METHOD;
 
265
typedef struct ssl_ctx_st SSL_CTX;
 
266
 
 
267
#define SSL_ERROR_WANT_READ 2
 
268
#define SSL_ERROR_WANT_WRITE 3
 
269
#define SSL_FILETYPE_PEM 1
 
270
#define CRYPTO_LOCK  1
 
271
 
 
272
#if defined(NO_SSL_DL)
 
273
extern void SSL_free(SSL *);
 
274
extern int SSL_accept(SSL *);
 
275
extern int SSL_connect(SSL *);
 
276
extern int SSL_read(SSL *, void *, int);
 
277
extern int SSL_write(SSL *, const void *, int);
 
278
extern int SSL_get_error(const SSL *, int);
 
279
extern int SSL_set_fd(SSL *, int);
 
280
extern SSL *SSL_new(SSL_CTX *);
 
281
extern SSL_CTX *SSL_CTX_new(SSL_METHOD *);
 
282
extern SSL_METHOD *SSLv23_server_method(void);
 
283
extern int SSL_library_init(void);
 
284
extern void SSL_load_error_strings(void);
 
285
extern int SSL_CTX_use_PrivateKey_file(SSL_CTX *, const char *, int);
 
286
extern int SSL_CTX_use_certificate_file(SSL_CTX *, const char *, int);
 
287
extern int SSL_CTX_use_certificate_chain_file(SSL_CTX *, const char *);
 
288
extern void SSL_CTX_set_default_passwd_cb(SSL_CTX *, mg_callback_t);
 
289
extern void SSL_CTX_free(SSL_CTX *);
 
290
extern unsigned long ERR_get_error(void);
 
291
extern char *ERR_error_string(unsigned long, char *);
 
292
extern int CRYPTO_num_locks(void);
 
293
extern void CRYPTO_set_locking_callback(void (*)(int, int, const char *, int));
 
294
extern void CRYPTO_set_id_callback(unsigned long (*)(void));
 
295
#else
 
296
// Dynamically loaded SSL functionality
 
297
struct ssl_func {
 
298
  const char *name;   // SSL function name
 
299
  void  (*ptr)(void); // Function pointer
 
300
};
 
301
 
 
302
#define SSL_free (* (void (*)(SSL *)) ssl_sw[0].ptr)
 
303
#define SSL_accept (* (int (*)(SSL *)) ssl_sw[1].ptr)
 
304
#define SSL_connect (* (int (*)(SSL *)) ssl_sw[2].ptr)
 
305
#define SSL_read (* (int (*)(SSL *, void *, int)) ssl_sw[3].ptr)
 
306
#define SSL_write (* (int (*)(SSL *, const void *,int)) ssl_sw[4].ptr)
 
307
#define SSL_get_error (* (int (*)(SSL *, int)) ssl_sw[5].ptr)
 
308
#define SSL_set_fd (* (int (*)(SSL *, SOCKET)) ssl_sw[6].ptr)
 
309
#define SSL_new (* (SSL * (*)(SSL_CTX *)) ssl_sw[7].ptr)
 
310
#define SSL_CTX_new (* (SSL_CTX * (*)(SSL_METHOD *)) ssl_sw[8].ptr)
 
311
#define SSLv23_server_method (* (SSL_METHOD * (*)(void)) ssl_sw[9].ptr)
 
312
#define SSL_library_init (* (int (*)(void)) ssl_sw[10].ptr)
 
313
#define SSL_CTX_use_PrivateKey_file (* (int (*)(SSL_CTX *, \
 
314
        const char *, int)) ssl_sw[11].ptr)
 
315
#define SSL_CTX_use_certificate_file (* (int (*)(SSL_CTX *, \
 
316
        const char *, int)) ssl_sw[12].ptr)
 
317
#define SSL_CTX_set_default_passwd_cb \
 
318
  (* (void (*)(SSL_CTX *, mg_callback_t)) ssl_sw[13].ptr)
 
319
#define SSL_CTX_free (* (void (*)(SSL_CTX *)) ssl_sw[14].ptr)
 
320
#define SSL_load_error_strings (* (void (*)(void)) ssl_sw[15].ptr)
 
321
#define SSL_CTX_use_certificate_chain_file \
 
322
  (* (int (*)(SSL_CTX *, const char *)) ssl_sw[16].ptr)
 
323
 
 
324
#define CRYPTO_num_locks (* (int (*)(void)) crypto_sw[0].ptr)
 
325
#define CRYPTO_set_locking_callback \
 
326
  (* (void (*)(void (*)(int, int, const char *, int))) crypto_sw[1].ptr)
 
327
#define CRYPTO_set_id_callback \
 
328
  (* (void (*)(unsigned long (*)(void))) crypto_sw[2].ptr)
 
329
#define ERR_get_error (* (unsigned long (*)(void)) crypto_sw[3].ptr)
 
330
#define ERR_error_string (* (char * (*)(unsigned long,char *)) crypto_sw[4].ptr)
 
331
 
 
332
// set_ssl_option() function updates this array.
 
333
// It loads SSL library dynamically and changes NULLs to the actual addresses
 
334
// of respective functions. The macros above (like SSL_connect()) are really
 
335
// just calling these functions indirectly via the pointer.
 
336
static struct ssl_func ssl_sw[] = {
 
337
  {"SSL_free",   NULL},
 
338
  {"SSL_accept",   NULL},
 
339
  {"SSL_connect",   NULL},
 
340
  {"SSL_read",   NULL},
 
341
  {"SSL_write",   NULL},
 
342
  {"SSL_get_error",  NULL},
 
343
  {"SSL_set_fd",   NULL},
 
344
  {"SSL_new",   NULL},
 
345
  {"SSL_CTX_new",   NULL},
 
346
  {"SSLv23_server_method", NULL},
 
347
  {"SSL_library_init",  NULL},
 
348
  {"SSL_CTX_use_PrivateKey_file", NULL},
 
349
  {"SSL_CTX_use_certificate_file",NULL},
 
350
  {"SSL_CTX_set_default_passwd_cb",NULL},
 
351
  {"SSL_CTX_free",  NULL},
 
352
  {"SSL_load_error_strings", NULL},
 
353
  {"SSL_CTX_use_certificate_chain_file", NULL},
 
354
  {NULL,    NULL}
 
355
};
 
356
 
 
357
// Similar array as ssl_sw. These functions could be located in different lib.
 
358
static struct ssl_func crypto_sw[] = {
 
359
  {"CRYPTO_num_locks",  NULL},
 
360
  {"CRYPTO_set_locking_callback", NULL},
 
361
  {"CRYPTO_set_id_callback", NULL},
 
362
  {"ERR_get_error",  NULL},
 
363
  {"ERR_error_string", NULL},
 
364
  {NULL,    NULL}
 
365
};
 
366
#endif // NO_SSL_DL
 
367
 
 
368
static const char *month_names[] = {
 
369
  "Jan", "Feb", "Mar", "Apr", "May", "Jun",
 
370
  "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
 
371
};
 
372
 
 
373
// Unified socket address. For IPv6 support, add IPv6 address structure
 
374
// in the union u.
 
375
union usa {
 
376
  struct sockaddr sa;
 
377
  struct sockaddr_in sin;
 
378
#if defined(USE_IPV6)
 
379
  struct sockaddr_in6 sin6;
 
380
#endif
 
381
};
 
382
 
 
383
// Describes a string (chunk of memory).
 
384
struct vec {
 
385
  const char *ptr;
 
386
  size_t len;
 
387
};
 
388
 
 
389
// Structure used by mg_stat() function. Uses 64 bit file length.
 
390
struct mgstat {
 
391
  int is_directory;  // Directory marker
 
392
  int64_t size;      // File size
 
393
  time_t mtime;      // Modification time
 
394
};
 
395
 
 
396
// Describes listening socket, or socket which was accept()-ed by the master
 
397
// thread and queued for future handling by the worker thread.
 
398
struct socket {
 
399
  struct socket *next;  // Linkage
 
400
  SOCKET sock;          // Listening socket
 
401
  union usa lsa;        // Local socket address
 
402
  union usa rsa;        // Remote socket address
 
403
  int is_ssl;           // Is socket SSL-ed
 
404
};
 
405
 
 
406
enum {
 
407
  CGI_EXTENSIONS, CGI_ENVIRONMENT, PUT_DELETE_PASSWORDS_FILE, CGI_INTERPRETER,
 
408
  PROTECT_URI, AUTHENTICATION_DOMAIN, SSI_EXTENSIONS, ACCESS_LOG_FILE,
 
409
  SSL_CHAIN_FILE, ENABLE_DIRECTORY_LISTING, ERROR_LOG_FILE,
 
410
  GLOBAL_PASSWORDS_FILE, INDEX_FILES,
 
411
  ENABLE_KEEP_ALIVE, ACCESS_CONTROL_LIST, MAX_REQUEST_SIZE,
 
412
  EXTRA_MIME_TYPES, LISTENING_PORTS,
 
413
  DOCUMENT_ROOT, SSL_CERTIFICATE, NUM_THREADS, RUN_AS_USER, REWRITE,
 
414
  NUM_OPTIONS
 
415
};
 
416
 
 
417
static const char *config_options[] = {
 
418
  "C", "cgi_pattern", "**.cgi$|**.pl$|**.php$",
 
419
  "E", "cgi_environment", NULL,
 
420
  "G", "put_delete_passwords_file", NULL,
 
421
  "I", "cgi_interpreter", NULL,
 
422
  "P", "protect_uri", NULL,
 
423
  "R", "authentication_domain", "mydomain.com",
 
424
  "S", "ssi_pattern", "**.shtml$|**.shtm$",
 
425
  "a", "access_log_file", NULL,
 
426
  "c", "ssl_chain_file", NULL,
 
427
  "d", "enable_directory_listing", "yes",
 
428
  "e", "error_log_file", NULL,
 
429
  "g", "global_passwords_file", NULL,
 
430
  "i", "index_files", "index.html,index.htm,index.cgi",
 
431
  "k", "enable_keep_alive", "no",
 
432
  "l", "access_control_list", NULL,
 
433
  "M", "max_request_size", "16384",
 
434
  "m", "extra_mime_types", NULL,
 
435
  "p", "listening_ports", "8080",
 
436
  "r", "document_root",  ".",
 
437
  "s", "ssl_certificate", NULL,
 
438
  "t", "num_threads", "10",
 
439
  "u", "run_as_user", NULL,
 
440
  "w", "url_rewrite_patterns", NULL,
 
441
  NULL
 
442
};
 
443
#define ENTRIES_PER_CONFIG_OPTION 3
 
444
 
 
445
struct mg_context {
 
446
  volatile int stop_flag;       // Should we stop event loop
 
447
  SSL_CTX *ssl_ctx;             // SSL context
 
448
  char *config[NUM_OPTIONS];    // Mongoose configuration parameters
 
449
  mg_callback_t user_callback;  // User-defined callback function
 
450
  void *user_data;              // User-defined data
 
451
 
 
452
  struct socket *listening_sockets;
 
453
 
 
454
  volatile int num_threads;  // Number of threads
 
455
  pthread_mutex_t mutex;     // Protects (max|num)_threads
 
456
  pthread_cond_t  cond;      // Condvar for tracking workers terminations
 
457
 
 
458
  struct socket queue[20];   // Accepted sockets
 
459
  volatile int sq_head;      // Head of the socket queue
 
460
  volatile int sq_tail;      // Tail of the socket queue
 
461
  pthread_cond_t sq_full;    // Singaled when socket is produced
 
462
  pthread_cond_t sq_empty;   // Signaled when socket is consumed
 
463
};
 
464
 
 
465
struct mg_connection {
 
466
  struct mg_request_info request_info;
 
467
  struct mg_context *ctx;
 
468
  SSL *ssl;                   // SSL descriptor
 
469
  struct socket client;       // Connected client
 
470
  time_t birth_time;          // Time connection was accepted
 
471
  int64_t num_bytes_sent;     // Total bytes sent to client
 
472
  int64_t content_len;        // Content-Length header value
 
473
  int64_t consumed_content;   // How many bytes of content is already read
 
474
  char *buf;                  // Buffer for received data
 
475
  char *path_info;            // PATH_INFO part of the URL
 
476
  int must_close;             // 1 if connection must be closed
 
477
  int buf_size;               // Buffer size
 
478
  int request_len;            // Size of the request + headers in a buffer
 
479
  int data_len;               // Total size of data in a buffer
 
480
};
 
481
 
 
482
const char **mg_get_valid_option_names(void) {
 
483
  return config_options;
 
484
}
 
485
 
 
486
static void *call_user(struct mg_connection *conn, enum mg_event event) {
 
487
  conn->request_info.user_data = conn->ctx->user_data;
 
488
  return conn->ctx->user_callback == NULL ? NULL :
 
489
    conn->ctx->user_callback(event, conn, &conn->request_info);
 
490
}
 
491
 
 
492
static int get_option_index(const char *name) {
 
493
  int i;
 
494
 
 
495
  for (i = 0; config_options[i] != NULL; i += ENTRIES_PER_CONFIG_OPTION) {
 
496
    if (strcmp(config_options[i], name) == 0 ||
 
497
        strcmp(config_options[i + 1], name) == 0) {
 
498
      return i / ENTRIES_PER_CONFIG_OPTION;
 
499
    }
 
500
  }
 
501
  return -1;
 
502
}
 
503
 
 
504
const char *mg_get_option(const struct mg_context *ctx, const char *name) {
 
505
  int i;
 
506
  if ((i = get_option_index(name)) == -1) {
 
507
    return NULL;
 
508
  } else if (ctx->config[i] == NULL) {
 
509
    return "";
 
510
  } else {
 
511
    return ctx->config[i];
 
512
  }
 
513
}
 
514
 
 
515
static void sockaddr_to_string(char *buf, size_t len,
 
516
                                     const union usa *usa) {
 
517
  buf[0] = '\0';
 
518
#if defined(USE_IPV6)
 
519
  inet_ntop(usa->sa.sa_family, usa->sa.sa_family == AF_INET ?
 
520
            (void *) &usa->sin.sin_addr :
 
521
            (void *) &usa->sin6.sin6_addr, buf, len);
 
522
#elif defined(_WIN32)
 
523
  // Only Windoze Vista (and newer) have inet_ntop()
 
524
  strncpy(buf, inet_ntoa(usa->sin.sin_addr), len);
 
525
#else
 
526
  inet_ntop(usa->sa.sa_family, (void *) &usa->sin.sin_addr, buf, len);
 
527
#endif
 
528
}
 
529
 
 
530
// Print error message to the opened error log stream.
 
531
static void cry(struct mg_connection *conn, const char *fmt, ...) {
 
532
  char buf[BUFSIZ], src_addr[20];
 
533
  va_list ap;
 
534
  FILE *fp;
 
535
  time_t timestamp;
 
536
 
 
537
  va_start(ap, fmt);
 
538
  (void) vsnprintf(buf, sizeof(buf), fmt, ap);
 
539
  va_end(ap);
 
540
 
 
541
  // Do not lock when getting the callback value, here and below.
 
542
  // I suppose this is fine, since function cannot disappear in the
 
543
  // same way string option can.
 
544
  conn->request_info.log_message = buf;
 
545
  if (call_user(conn, MG_EVENT_LOG) == NULL) {
 
546
    fp = conn->ctx->config[ERROR_LOG_FILE] == NULL ? NULL :
 
547
      mg_fopen(conn->ctx->config[ERROR_LOG_FILE], "a+");
 
548
 
 
549
    if (fp != NULL) {
 
550
      flockfile(fp);
 
551
      timestamp = time(NULL);
 
552
 
 
553
      sockaddr_to_string(src_addr, sizeof(src_addr), &conn->client.rsa);
 
554
      fprintf(fp, "[%010lu] [error] [client %s] ", (unsigned long) timestamp,
 
555
              src_addr);
 
556
 
 
557
      if (conn->request_info.request_method != NULL) {
 
558
        fprintf(fp, "%s %s: ", conn->request_info.request_method,
 
559
                conn->request_info.uri);
 
560
      }
 
561
 
 
562
      (void) fprintf(fp, "%s", buf);
 
563
      fputc('\n', fp);
 
564
      funlockfile(fp);
 
565
      if (fp != stderr) {
 
566
        fclose(fp);
 
567
      }
 
568
    }
 
569
  }
 
570
  conn->request_info.log_message = NULL;
 
571
}
 
572
 
 
573
// Return OpenSSL error message
 
574
static const char *ssl_error(void) {
 
575
  unsigned long err;
 
576
  err = ERR_get_error();
 
577
  return err == 0 ? "" : ERR_error_string(err, NULL);
 
578
}
 
579
 
 
580
// Return fake connection structure. Used for logging, if connection
 
581
// is not applicable at the moment of logging.
 
582
static struct mg_connection *fc(struct mg_context *ctx) {
 
583
  static struct mg_connection fake_connection;
 
584
  fake_connection.ctx = ctx;
 
585
  return &fake_connection;
 
586
}
 
587
 
 
588
const char *mg_version(void) {
 
589
  return MONGOOSE_VERSION;
 
590
}
 
591
 
 
592
static void mg_strlcpy(register char *dst, register const char *src, size_t n) {
 
593
  for (; *src != '\0' && n > 1; n--) {
 
594
    *dst++ = *src++;
 
595
  }
 
596
  *dst = '\0';
 
597
}
 
598
 
 
599
static int lowercase(const char *s) {
 
600
  return tolower(* (const unsigned char *) s);
 
601
}
 
602
 
 
603
static int mg_strncasecmp(const char *s1, const char *s2, size_t len) {
 
604
  int diff = 0;
 
605
 
 
606
  if (len > 0)
 
607
    do {
 
608
      diff = lowercase(s1++) - lowercase(s2++);
 
609
    } while (diff == 0 && s1[-1] != '\0' && --len > 0);
 
610
 
 
611
  return diff;
 
612
}
 
613
 
 
614
static int mg_strcasecmp(const char *s1, const char *s2) {
 
615
  int diff;
 
616
 
 
617
  do {
 
618
    diff = lowercase(s1++) - lowercase(s2++);
 
619
  } while (diff == 0 && s1[-1] != '\0');
 
620
 
 
621
  return diff;
 
622
}
 
623
 
 
624
static char * mg_strndup(const char *ptr, size_t len) {
 
625
  char *p;
 
626
 
 
627
  if ((p = (char *) malloc(len + 1)) != NULL) {
 
628
    mg_strlcpy(p, ptr, len + 1);
 
629
  }
 
630
 
 
631
  return p;
 
632
}
 
633
 
 
634
static char * mg_strdup(const char *str) {
 
635
  return mg_strndup(str, strlen(str));
 
636
}
 
637
 
 
638
// Like snprintf(), but never returns negative value, or the value
 
639
// that is larger than a supplied buffer.
 
640
// Thanks to Adam Zeldis to pointing snprintf()-caused vulnerability
 
641
// in his audit report.
 
642
static int mg_vsnprintf(struct mg_connection *conn, char *buf, size_t buflen,
 
643
                        const char *fmt, va_list ap) {
 
644
  int n;
 
645
 
 
646
  if (buflen == 0)
 
647
    return 0;
 
648
 
 
649
  n = vsnprintf(buf, buflen, fmt, ap);
 
650
 
 
651
  if (n < 0) {
 
652
    cry(conn, "vsnprintf error");
 
653
    n = 0;
 
654
  } else if (n >= (int) buflen) {
 
655
    cry(conn, "truncating vsnprintf buffer: [%.*s]",
 
656
        n > 200 ? 200 : n, buf);
 
657
    n = (int) buflen - 1;
 
658
  }
 
659
  buf[n] = '\0';
 
660
 
 
661
  return n;
 
662
}
 
663
 
 
664
static int mg_snprintf(struct mg_connection *conn, char *buf, size_t buflen,
 
665
                       const char *fmt, ...) {
 
666
  va_list ap;
 
667
  int n;
 
668
 
 
669
  va_start(ap, fmt);
 
670
  n = mg_vsnprintf(conn, buf, buflen, fmt, ap);
 
671
  va_end(ap);
 
672
 
 
673
  return n;
 
674
}
 
675
 
 
676
// Skip the characters until one of the delimiters characters found.
 
677
// 0-terminate resulting word. Skip the delimiter and following whitespaces if any.
 
678
// Advance pointer to buffer to the next word. Return found 0-terminated word.
 
679
// Delimiters can be quoted with quotechar.
 
680
static char *skip_quoted(char **buf, const char *delimiters, const char *whitespace, char quotechar) {
 
681
  char *p, *begin_word, *end_word, *end_whitespace;
 
682
 
 
683
  begin_word = *buf;
 
684
  end_word = begin_word + strcspn(begin_word, delimiters);
 
685
 
 
686
  // Check for quotechar
 
687
  if (end_word > begin_word) {
 
688
    p = end_word - 1;
 
689
    while (*p == quotechar) {
 
690
      // If there is anything beyond end_word, copy it
 
691
      if (*end_word == '\0') {
 
692
        *p = '\0';
 
693
        break;
 
694
      } else {
 
695
        size_t end_off = strcspn(end_word + 1, delimiters);
 
696
        memmove (p, end_word, end_off + 1);
 
697
        p += end_off; // p must correspond to end_word - 1
 
698
        end_word += end_off + 1;
 
699
      }
 
700
    }
 
701
    for (p++; p < end_word; p++) {
 
702
      *p = '\0';
 
703
    }
 
704
  }
 
705
 
 
706
  if (*end_word == '\0') {
 
707
    *buf = end_word;
 
708
  } else {
 
709
    end_whitespace = end_word + 1 + strspn(end_word + 1, whitespace);
 
710
 
 
711
    for (p = end_word; p < end_whitespace; p++) {
 
712
      *p = '\0';
 
713
    }
 
714
 
 
715
    *buf = end_whitespace;
 
716
  }
 
717
 
 
718
  return begin_word;
 
719
}
 
720
 
 
721
// Simplified version of skip_quoted without quote char
 
722
// and whitespace == delimiters
 
723
static char *skip(char **buf, const char *delimiters) {
 
724
  return skip_quoted(buf, delimiters, delimiters, 0);
 
725
}
 
726
 
 
727
 
 
728
// Return HTTP header value, or NULL if not found.
 
729
static const char *get_header(const struct mg_request_info *ri,
 
730
                              const char *name) {
 
731
  int i;
 
732
 
 
733
  for (i = 0; i < ri->num_headers; i++)
 
734
    if (!mg_strcasecmp(name, ri->http_headers[i].name))
 
735
      return ri->http_headers[i].value;
 
736
 
 
737
  return NULL;
 
738
}
 
739
 
 
740
const char *mg_get_header(const struct mg_connection *conn, const char *name) {
 
741
  return get_header(&conn->request_info, name);
 
742
}
 
743
 
 
744
// A helper function for traversing comma separated list of values.
 
745
// It returns a list pointer shifted to the next value, of NULL if the end
 
746
// of the list found.
 
747
// Value is stored in val vector. If value has form "x=y", then eq_val
 
748
// vector is initialized to point to the "y" part, and val vector length
 
749
// is adjusted to point only to "x".
 
750
static const char *next_option(const char *list, struct vec *val,
 
751
                               struct vec *eq_val) {
 
752
  if (list == NULL || *list == '\0') {
 
753
    // End of the list
 
754
    list = NULL;
 
755
  } else {
 
756
    val->ptr = list;
 
757
    if ((list = strchr(val->ptr, ',')) != NULL) {
 
758
      // Comma found. Store length and shift the list ptr
 
759
      val->len = list - val->ptr;
 
760
      list++;
 
761
    } else {
 
762
      // This value is the last one
 
763
      list = val->ptr + strlen(val->ptr);
 
764
      val->len = list - val->ptr;
 
765
    }
 
766
 
 
767
    if (eq_val != NULL) {
 
768
      // Value has form "x=y", adjust pointers and lengths
 
769
      // so that val points to "x", and eq_val points to "y".
 
770
      eq_val->len = 0;
 
771
      eq_val->ptr = (const char *) memchr(val->ptr, '=', val->len);
 
772
      if (eq_val->ptr != NULL) {
 
773
        eq_val->ptr++;  // Skip over '=' character
 
774
        eq_val->len = val->ptr + val->len - eq_val->ptr;
 
775
        val->len = (eq_val->ptr - val->ptr) - 1;
 
776
      }
 
777
    }
 
778
  }
 
779
 
 
780
  return list;
 
781
}
 
782
 
 
783
static int match_prefix(const char *pattern, int pattern_len, const char *str) {
 
784
  const char *or_str;
 
785
  int i, j, len, res;
 
786
 
 
787
  if ((or_str = (const char *) memchr(pattern, '|', pattern_len)) != NULL) {
 
788
    res = match_prefix(pattern, or_str - pattern, str);
 
789
    return res > 0 ? res :
 
790
        match_prefix(or_str + 1, (pattern + pattern_len) - (or_str + 1), str);
 
791
  }
 
792
 
 
793
  i = j = 0;
 
794
  res = -1;
 
795
  for (; i < pattern_len; i++, j++) {
 
796
    if (pattern[i] == '?' && str[j] != '\0') {
 
797
      continue;
 
798
    } else if (pattern[i] == '$') {
 
799
      return str[j] == '\0' ? j : -1;
 
800
    } else if (pattern[i] == '*') {
 
801
      i++;
 
802
      if (pattern[i] == '*') {
 
803
        i++;
 
804
        len = strlen(str + j);
 
805
      } else {
 
806
        len = strcspn(str + j, "/");
 
807
      }
 
808
      if (i == pattern_len) {
 
809
        return j + len;
 
810
      }
 
811
      do {
 
812
        res = match_prefix(pattern + i, pattern_len - i, str + j + len);
 
813
      } while (res == -1 && len-- > 0);
 
814
      return res == -1 ? -1 : j + res + len;
 
815
    } else if (pattern[i] != str[j]) {
 
816
      return -1;
 
817
    }
 
818
  }
 
819
  return j;
 
820
}
 
821
 
 
822
// HTTP 1.1 assumes keep alive if "Connection:" header is not set
 
823
// This function must tolerate situations when connection info is not
 
824
// set up, for example if request parsing failed.
 
825
static int should_keep_alive(const struct mg_connection *conn) {
 
826
  const char *http_version = conn->request_info.http_version;
 
827
  const char *header = mg_get_header(conn, "Connection");
 
828
  return (!conn->must_close &&
 
829
          !conn->request_info.status_code != 401 &&
 
830
          !mg_strcasecmp(conn->ctx->config[ENABLE_KEEP_ALIVE], "yes") &&
 
831
          (header == NULL && http_version && !strcmp(http_version, "1.1"))) ||
 
832
          (header != NULL && !mg_strcasecmp(header, "keep-alive"));
 
833
}
 
834
 
 
835
static const char *suggest_connection_header(const struct mg_connection *conn) {
 
836
  return should_keep_alive(conn) ? "keep-alive" : "close";
 
837
}
 
838
 
 
839
static void send_http_error(struct mg_connection *conn, int status,
 
840
                            const char *reason, const char *fmt, ...) {
 
841
  char buf[BUFSIZ];
 
842
  va_list ap;
 
843
  int len;
 
844
 
 
845
  conn->request_info.status_code = status;
 
846
 
 
847
  if (call_user(conn, MG_HTTP_ERROR) == NULL) {
 
848
    buf[0] = '\0';
 
849
    len = 0;
 
850
 
 
851
    // Errors 1xx, 204 and 304 MUST NOT send a body
 
852
    if (status > 199 && status != 204 && status != 304) {
 
853
      len = mg_snprintf(conn, buf, sizeof(buf), "Error %d: %s", status, reason);
 
854
      cry(conn, "%s", buf);
 
855
      buf[len++] = '\n';
 
856
 
 
857
      va_start(ap, fmt);
 
858
      len += mg_vsnprintf(conn, buf + len, sizeof(buf) - len, fmt, ap);
 
859
      va_end(ap);
 
860
    }
 
861
    DEBUG_TRACE(("[%s]", buf));
 
862
 
 
863
    mg_printf(conn, "HTTP/1.1 %d %s\r\n"
 
864
              "Content-Type: text/plain\r\n"
 
865
              "Content-Length: %d\r\n"
 
866
              "Connection: %s\r\n\r\n", status, reason, len,
 
867
              suggest_connection_header(conn));
 
868
    conn->num_bytes_sent += mg_printf(conn, "%s", buf);
 
869
  }
 
870
}
 
871
 
 
872
#if defined(_WIN32) && !defined(__SYMBIAN32__)
 
873
static int pthread_mutex_init(pthread_mutex_t *mutex, void *unused) {
 
874
  unused = NULL;
 
875
  *mutex = CreateMutex(NULL, FALSE, NULL);
 
876
  return *mutex == NULL ? -1 : 0;
 
877
}
 
878
 
 
879
static int pthread_mutex_destroy(pthread_mutex_t *mutex) {
 
880
  return CloseHandle(*mutex) == 0 ? -1 : 0;
 
881
}
 
882
 
 
883
static int pthread_mutex_lock(pthread_mutex_t *mutex) {
 
884
  return WaitForSingleObject(*mutex, INFINITE) == WAIT_OBJECT_0? 0 : -1;
 
885
}
 
886
 
 
887
static int pthread_mutex_unlock(pthread_mutex_t *mutex) {
 
888
  return ReleaseMutex(*mutex) == 0 ? -1 : 0;
 
889
}
 
890
 
 
891
static int pthread_cond_init(pthread_cond_t *cv, const void *unused) {
 
892
  unused = NULL;
 
893
  cv->signal = CreateEvent(NULL, FALSE, FALSE, NULL);
 
894
  cv->broadcast = CreateEvent(NULL, TRUE, FALSE, NULL);
 
895
  return cv->signal != NULL && cv->broadcast != NULL ? 0 : -1;
 
896
}
 
897
 
 
898
static int pthread_cond_wait(pthread_cond_t *cv, pthread_mutex_t *mutex) {
 
899
  HANDLE handles[] = {cv->signal, cv->broadcast};
 
900
  ReleaseMutex(*mutex);
 
901
  WaitForMultipleObjects(2, handles, FALSE, INFINITE);
 
902
  return WaitForSingleObject(*mutex, INFINITE) == WAIT_OBJECT_0? 0 : -1;
 
903
}
 
904
 
 
905
static int pthread_cond_signal(pthread_cond_t *cv) {
 
906
  return SetEvent(cv->signal) == 0 ? -1 : 0;
 
907
}
 
908
 
 
909
static int pthread_cond_broadcast(pthread_cond_t *cv) {
 
910
  // Implementation with PulseEvent() has race condition, see
 
911
  // http://www.cs.wustl.edu/~schmidt/win32-cv-1.html
 
912
  return PulseEvent(cv->broadcast) == 0 ? -1 : 0;
 
913
}
 
914
 
 
915
static int pthread_cond_destroy(pthread_cond_t *cv) {
 
916
  return CloseHandle(cv->signal) && CloseHandle(cv->broadcast) ? 0 : -1;
 
917
}
 
918
 
 
919
// For Windows, change all slashes to backslashes in path names.
 
920
static void change_slashes_to_backslashes(char *path) {
 
921
  int i;
 
922
 
 
923
  for (i = 0; path[i] != '\0'; i++) {
 
924
    if (path[i] == '/')
 
925
      path[i] = '\\';
 
926
    // i > 0 check is to preserve UNC paths, like \\server\file.txt
 
927
    if (path[i] == '\\' && i > 0)
 
928
      while (path[i + 1] == '\\' || path[i + 1] == '/')
 
929
        (void) memmove(path + i + 1,
 
930
            path + i + 2, strlen(path + i + 1));
 
931
  }
 
932
}
 
933
 
 
934
// Encode 'path' which is assumed UTF-8 string, into UNICODE string.
 
935
// wbuf and wbuf_len is a target buffer and its length.
 
936
static void to_unicode(const char *path, wchar_t *wbuf, size_t wbuf_len) {
 
937
  char buf[PATH_MAX], buf2[PATH_MAX], *p;
 
938
 
 
939
  mg_strlcpy(buf, path, sizeof(buf));
 
940
  change_slashes_to_backslashes(buf);
 
941
 
 
942
  // Point p to the end of the file name
 
943
  p = buf + strlen(buf) - 1;
 
944
 
 
945
  // Trim trailing backslash character
 
946
  while (p > buf && *p == '\\' && p[-1] != ':') {
 
947
    *p-- = '\0';
 
948
  }
 
949
 
 
950
   // Protect from CGI code disclosure.
 
951
   // This is very nasty hole. Windows happily opens files with
 
952
   // some garbage in the end of file name. So fopen("a.cgi    ", "r")
 
953
   // actually opens "a.cgi", and does not return an error!
 
954
  if (*p == 0x20 ||               // No space at the end
 
955
      (*p == 0x2e && p > buf) ||  // No '.' but allow '.' as full path
 
956
      *p == 0x2b ||               // No '+'
 
957
      (*p & ~0x7f)) {             // And generally no non-ascii chars
 
958
    (void) fprintf(stderr, "Rejecting suspicious path: [%s]", buf);
 
959
    wbuf[0] = L'\0';
 
960
  } else {
 
961
    // Convert to Unicode and back. If doubly-converted string does not
 
962
    // match the original, something is fishy, reject.
 
963
    memset(wbuf, 0, wbuf_len * sizeof(wchar_t));
 
964
    MultiByteToWideChar(CP_UTF8, 0, buf, -1, wbuf, (int) wbuf_len);
 
965
    WideCharToMultiByte(CP_UTF8, 0, wbuf, (int) wbuf_len, buf2, sizeof(buf2),
 
966
                        NULL, NULL);
 
967
    if (strcmp(buf, buf2) != 0) {
 
968
      wbuf[0] = L'\0';
 
969
    }
 
970
  }
 
971
}
 
972
 
 
973
#if defined(_WIN32_WCE)
 
974
static time_t time(time_t *ptime) {
 
975
  time_t t;
 
976
  SYSTEMTIME st;
 
977
  FILETIME ft;
 
978
 
 
979
  GetSystemTime(&st);
 
980
  SystemTimeToFileTime(&st, &ft);
 
981
  t = SYS2UNIX_TIME(ft.dwLowDateTime, ft.dwHighDateTime);
 
982
 
 
983
  if (ptime != NULL) {
 
984
    *ptime = t;
 
985
  }
 
986
 
 
987
  return t;
 
988
}
 
989
 
 
990
static struct tm *localtime(const time_t *ptime, struct tm *ptm) {
 
991
  int64_t t = ((int64_t) *ptime) * RATE_DIFF + EPOCH_DIFF;
 
992
  FILETIME ft, lft;
 
993
  SYSTEMTIME st;
 
994
  TIME_ZONE_INFORMATION tzinfo;
 
995
 
 
996
  if (ptm == NULL) {
 
997
    return NULL;
 
998
  }
 
999
 
 
1000
  * (int64_t *) &ft = t;
 
1001
  FileTimeToLocalFileTime(&ft, &lft);
 
1002
  FileTimeToSystemTime(&lft, &st);
 
1003
  ptm->tm_year = st.wYear - 1900;
 
1004
  ptm->tm_mon = st.wMonth - 1;
 
1005
  ptm->tm_wday = st.wDayOfWeek;
 
1006
  ptm->tm_mday = st.wDay;
 
1007
  ptm->tm_hour = st.wHour;
 
1008
  ptm->tm_min = st.wMinute;
 
1009
  ptm->tm_sec = st.wSecond;
 
1010
  ptm->tm_yday = 0; // hope nobody uses this
 
1011
  ptm->tm_isdst =
 
1012
    GetTimeZoneInformation(&tzinfo) == TIME_ZONE_ID_DAYLIGHT ? 1 : 0;
 
1013
 
 
1014
  return ptm;
 
1015
}
 
1016
 
 
1017
static struct tm *gmtime(const time_t *ptime, struct tm *ptm) {
 
1018
  // FIXME(lsm): fix this.
 
1019
  return localtime(ptime, ptm);
 
1020
}
 
1021
 
 
1022
static size_t strftime(char *dst, size_t dst_size, const char *fmt,
 
1023
                       const struct tm *tm) {
 
1024
  (void) snprintf(dst, dst_size, "implement strftime() for WinCE");
 
1025
  return 0;
 
1026
}
 
1027
#endif
 
1028
 
 
1029
static int mg_rename(const char* oldname, const char* newname) {
 
1030
  wchar_t woldbuf[PATH_MAX];
 
1031
  wchar_t wnewbuf[PATH_MAX];
 
1032
 
 
1033
  to_unicode(oldname, woldbuf, ARRAY_SIZE(woldbuf));
 
1034
  to_unicode(newname, wnewbuf, ARRAY_SIZE(wnewbuf));
 
1035
 
 
1036
  return MoveFileW(woldbuf, wnewbuf) ? 0 : -1;
 
1037
}
 
1038
 
 
1039
 
 
1040
static FILE *mg_fopen(const char *path, const char *mode) {
 
1041
  wchar_t wbuf[PATH_MAX], wmode[20];
 
1042
 
 
1043
  to_unicode(path, wbuf, ARRAY_SIZE(wbuf));
 
1044
  MultiByteToWideChar(CP_UTF8, 0, mode, -1, wmode, ARRAY_SIZE(wmode));
 
1045
 
 
1046
  return _wfopen(wbuf, wmode);
 
1047
}
 
1048
 
 
1049
static int mg_stat(const char *path, struct mgstat *stp) {
 
1050
  int ok = -1; // Error
 
1051
  wchar_t wbuf[PATH_MAX];
 
1052
  WIN32_FILE_ATTRIBUTE_DATA info;
 
1053
 
 
1054
  to_unicode(path, wbuf, ARRAY_SIZE(wbuf));
 
1055
 
 
1056
  if (GetFileAttributesExW(wbuf, GetFileExInfoStandard, &info) != 0) {
 
1057
    stp->size = MAKEUQUAD(info.nFileSizeLow, info.nFileSizeHigh);
 
1058
    stp->mtime = SYS2UNIX_TIME(info.ftLastWriteTime.dwLowDateTime,
 
1059
                               info.ftLastWriteTime.dwHighDateTime);
 
1060
    stp->is_directory =
 
1061
      info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
 
1062
    ok = 0;  // Success
 
1063
  }
 
1064
 
 
1065
  return ok;
 
1066
}
 
1067
 
 
1068
static int mg_remove(const char *path) {
 
1069
  wchar_t wbuf[PATH_MAX];
 
1070
  to_unicode(path, wbuf, ARRAY_SIZE(wbuf));
 
1071
  return DeleteFileW(wbuf) ? 0 : -1;
 
1072
}
 
1073
 
 
1074
static int mg_mkdir(const char *path, int mode) {
 
1075
  char buf[PATH_MAX];
 
1076
  wchar_t wbuf[PATH_MAX];
 
1077
 
 
1078
  mode = 0; // Unused
 
1079
  mg_strlcpy(buf, path, sizeof(buf));
 
1080
  change_slashes_to_backslashes(buf);
 
1081
 
 
1082
  (void) MultiByteToWideChar(CP_UTF8, 0, buf, -1, wbuf, sizeof(wbuf));
 
1083
 
 
1084
  return CreateDirectoryW(wbuf, NULL) ? 0 : -1;
 
1085
}
 
1086
 
 
1087
// Implementation of POSIX opendir/closedir/readdir for Windows.
 
1088
static DIR * opendir(const char *name) {
 
1089
  DIR *dir = NULL;
 
1090
  wchar_t wpath[PATH_MAX];
 
1091
  DWORD attrs;
 
1092
 
 
1093
  if (name == NULL) {
 
1094
    SetLastError(ERROR_BAD_ARGUMENTS);
 
1095
  } else if ((dir = (DIR *) malloc(sizeof(*dir))) == NULL) {
 
1096
    SetLastError(ERROR_NOT_ENOUGH_MEMORY);
 
1097
  } else {
 
1098
    to_unicode(name, wpath, ARRAY_SIZE(wpath));
 
1099
    attrs = GetFileAttributesW(wpath);
 
1100
    if (attrs != 0xFFFFFFFF &&
 
1101
        ((attrs & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY)) {
 
1102
      (void) wcscat(wpath, L"\\*");
 
1103
      dir->handle = FindFirstFileW(wpath, &dir->info);
 
1104
      dir->result.d_name[0] = '\0';
 
1105
    } else {
 
1106
      free(dir);
 
1107
      dir = NULL;
 
1108
    }
 
1109
  }
 
1110
 
 
1111
  return dir;
 
1112
}
 
1113
 
 
1114
static int closedir(DIR *dir) {
 
1115
  int result = 0;
 
1116
 
 
1117
  if (dir != NULL) {
 
1118
    if (dir->handle != INVALID_HANDLE_VALUE)
 
1119
      result = FindClose(dir->handle) ? 0 : -1;
 
1120
 
 
1121
    free(dir);
 
1122
  } else {
 
1123
    result = -1;
 
1124
    SetLastError(ERROR_BAD_ARGUMENTS);
 
1125
  }
 
1126
 
 
1127
  return result;
 
1128
}
 
1129
 
 
1130
struct dirent * readdir(DIR *dir) {
 
1131
  struct dirent *result = 0;
 
1132
 
 
1133
  if (dir) {
 
1134
    if (dir->handle != INVALID_HANDLE_VALUE) {
 
1135
      result = &dir->result;
 
1136
      (void) WideCharToMultiByte(CP_UTF8, 0,
 
1137
          dir->info.cFileName, -1, result->d_name,
 
1138
          sizeof(result->d_name), NULL, NULL);
 
1139
 
 
1140
      if (!FindNextFileW(dir->handle, &dir->info)) {
 
1141
        (void) FindClose(dir->handle);
 
1142
        dir->handle = INVALID_HANDLE_VALUE;
 
1143
      }
 
1144
 
 
1145
    } else {
 
1146
      SetLastError(ERROR_FILE_NOT_FOUND);
 
1147
    }
 
1148
  } else {
 
1149
    SetLastError(ERROR_BAD_ARGUMENTS);
 
1150
  }
 
1151
 
 
1152
  return result;
 
1153
}
 
1154
 
 
1155
#define set_close_on_exec(fd) // No FD_CLOEXEC on Windows
 
1156
 
 
1157
static int start_thread(struct mg_context *ctx, mg_thread_func_t f, void *p) {
 
1158
  return _beginthread((void (__cdecl *)(void *)) f, 0, p) == -1L ? -1 : 0;
 
1159
}
 
1160
 
 
1161
static HANDLE dlopen(const char *dll_name, int flags) {
 
1162
  wchar_t wbuf[PATH_MAX];
 
1163
  flags = 0; // Unused
 
1164
  to_unicode(dll_name, wbuf, ARRAY_SIZE(wbuf));
 
1165
  return LoadLibraryW(wbuf);
 
1166
}
 
1167
 
 
1168
#if !defined(NO_CGI)
 
1169
#define SIGKILL 0
 
1170
static int kill(pid_t pid, int sig_num) {
 
1171
  (void) TerminateProcess(pid, sig_num);
 
1172
  (void) CloseHandle(pid);
 
1173
  return 0;
 
1174
}
 
1175
 
 
1176
static pid_t spawn_process(struct mg_connection *conn, const char *prog,
 
1177
                           char *envblk, char *envp[], int fd_stdin,
 
1178
                           int fd_stdout, const char *dir) {
 
1179
  HANDLE me;
 
1180
  char *p, *interp, cmdline[PATH_MAX], buf[PATH_MAX];
 
1181
  FILE *fp;
 
1182
  STARTUPINFOA si = { sizeof(si) };
 
1183
  PROCESS_INFORMATION pi = { 0 };
 
1184
 
 
1185
  envp = NULL; // Unused
 
1186
 
 
1187
  // TODO(lsm): redirect CGI errors to the error log file
 
1188
  si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
 
1189
  si.wShowWindow = SW_HIDE;
 
1190
 
 
1191
  me = GetCurrentProcess();
 
1192
  (void) DuplicateHandle(me, (HANDLE) _get_osfhandle(fd_stdin), me,
 
1193
      &si.hStdInput, 0, TRUE, DUPLICATE_SAME_ACCESS);
 
1194
  (void) DuplicateHandle(me, (HANDLE) _get_osfhandle(fd_stdout), me,
 
1195
      &si.hStdOutput, 0, TRUE, DUPLICATE_SAME_ACCESS);
 
1196
 
 
1197
  // If CGI file is a script, try to read the interpreter line
 
1198
  interp = conn->ctx->config[CGI_INTERPRETER];
 
1199
  if (interp == NULL) {
 
1200
    buf[2] = '\0';
 
1201
    mg_snprintf(conn, cmdline, sizeof(cmdline), "%s%c%s", dir, DIRSEP, prog);
 
1202
    if ((fp = fopen(cmdline, "r")) != NULL) {
 
1203
      (void) fgets(buf, sizeof(buf), fp);
 
1204
      if (buf[0] != '#' || buf[1] != '!') {
 
1205
        // First line does not start with "#!". Do not set interpreter.
 
1206
        buf[2] = '\0';
 
1207
      } else {
 
1208
        // Trim whitespaces in interpreter name
 
1209
        for (p = &buf[strlen(buf) - 1]; p > buf && isspace(*p); p--) {
 
1210
          *p = '\0';
 
1211
        }
 
1212
      }
 
1213
      (void) fclose(fp);
 
1214
    }
 
1215
    interp = buf + 2;
 
1216
  }
 
1217
 
 
1218
  (void) mg_snprintf(conn, cmdline, sizeof(cmdline), "%s%s%s%c%s",
 
1219
                     interp, interp[0] == '\0' ? "" : " ", dir, DIRSEP, prog);
 
1220
 
 
1221
  DEBUG_TRACE(("Running [%s]", cmdline));
 
1222
  if (CreateProcessA(NULL, cmdline, NULL, NULL, TRUE,
 
1223
        CREATE_NEW_PROCESS_GROUP, envblk, dir, &si, &pi) == 0) {
 
1224
    cry(conn, "%s: CreateProcess(%s): %d",
 
1225
        __func__, cmdline, ERRNO);
 
1226
    pi.hProcess = (pid_t) -1;
 
1227
  } else {
 
1228
    (void) close(fd_stdin);
 
1229
    (void) close(fd_stdout);
 
1230
  }
 
1231
 
 
1232
  (void) CloseHandle(si.hStdOutput);
 
1233
  (void) CloseHandle(si.hStdInput);
 
1234
  (void) CloseHandle(pi.hThread);
 
1235
 
 
1236
  return (pid_t) pi.hProcess;
 
1237
}
 
1238
#endif // !NO_CGI
 
1239
 
 
1240
static int set_non_blocking_mode(SOCKET sock) {
 
1241
  unsigned long on = 1;
 
1242
  return ioctlsocket(sock, FIONBIO, &on);
 
1243
}
 
1244
 
 
1245
#else
 
1246
static int mg_stat(const char *path, struct mgstat *stp) {
 
1247
  struct stat st;
 
1248
  int ok;
 
1249
 
 
1250
  if (stat(path, &st) == 0) {
 
1251
    ok = 0;
 
1252
    stp->size = st.st_size;
 
1253
    stp->mtime = st.st_mtime;
 
1254
    stp->is_directory = S_ISDIR(st.st_mode);
 
1255
  } else {
 
1256
    ok = -1;
 
1257
  }
 
1258
 
 
1259
  return ok;
 
1260
}
 
1261
 
 
1262
static void set_close_on_exec(int fd) {
 
1263
  (void) fcntl(fd, F_SETFD, FD_CLOEXEC);
 
1264
}
 
1265
 
 
1266
static int start_thread(struct mg_context *ctx, mg_thread_func_t func,
 
1267
                        void *param) {
 
1268
  pthread_t thread_id;
 
1269
  pthread_attr_t attr;
 
1270
  int retval;
 
1271
 
 
1272
  (void) pthread_attr_init(&attr);
 
1273
  (void) pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
 
1274
  // TODO(lsm): figure out why mongoose dies on Linux if next line is enabled
 
1275
  // (void) pthread_attr_setstacksize(&attr, sizeof(struct mg_connection) * 5);
 
1276
 
 
1277
  if ((retval = pthread_create(&thread_id, &attr, func, param)) != 0) {
 
1278
    cry(fc(ctx), "%s: %s", __func__, strerror(retval));
 
1279
  }
 
1280
 
 
1281
  return retval;
 
1282
}
 
1283
 
 
1284
#ifndef NO_CGI
 
1285
static pid_t spawn_process(struct mg_connection *conn, const char *prog,
 
1286
                           char *envblk, char *envp[], int fd_stdin,
 
1287
                           int fd_stdout, const char *dir) {
 
1288
  pid_t pid;
 
1289
  const char *interp;
 
1290
 
 
1291
  envblk = NULL; // Unused
 
1292
 
 
1293
  if ((pid = fork()) == -1) {
 
1294
    // Parent
 
1295
    send_http_error(conn, 500, http_500_error, "fork(): %s", strerror(ERRNO));
 
1296
  } else if (pid == 0) {
 
1297
    // Child
 
1298
    if (chdir(dir) != 0) {
 
1299
      cry(conn, "%s: chdir(%s): %s", __func__, dir, strerror(ERRNO));
 
1300
    } else if (dup2(fd_stdin, 0) == -1) {
 
1301
      cry(conn, "%s: dup2(%d, 0): %s", __func__, fd_stdin, strerror(ERRNO));
 
1302
    } else if (dup2(fd_stdout, 1) == -1) {
 
1303
      cry(conn, "%s: dup2(%d, 1): %s", __func__, fd_stdout, strerror(ERRNO));
 
1304
    } else {
 
1305
      (void) dup2(fd_stdout, 2);
 
1306
      (void) close(fd_stdin);
 
1307
      (void) close(fd_stdout);
 
1308
 
 
1309
      // Execute CGI program. No need to lock: new process
 
1310
      interp = conn->ctx->config[CGI_INTERPRETER];
 
1311
      if (interp == NULL) {
 
1312
        (void) execle(prog, prog, NULL, envp);
 
1313
        cry(conn, "%s: execle(%s): %s", __func__, prog, strerror(ERRNO));
 
1314
      } else {
 
1315
        (void) execle(interp, interp, prog, NULL, envp);
 
1316
        cry(conn, "%s: execle(%s %s): %s", __func__, interp, prog,
 
1317
            strerror(ERRNO));
 
1318
      }
 
1319
    }
 
1320
    exit(EXIT_FAILURE);
 
1321
  } else {
 
1322
    // Parent. Close stdio descriptors
 
1323
    (void) close(fd_stdin);
 
1324
    (void) close(fd_stdout);
 
1325
  }
 
1326
 
 
1327
  return pid;
 
1328
}
 
1329
#endif // !NO_CGI
 
1330
 
 
1331
static int set_non_blocking_mode(SOCKET sock) {
 
1332
  int flags;
 
1333
 
 
1334
  flags = fcntl(sock, F_GETFL, 0);
 
1335
  (void) fcntl(sock, F_SETFL, flags | O_NONBLOCK);
 
1336
 
 
1337
  return 0;
 
1338
}
 
1339
#endif // _WIN32
 
1340
 
 
1341
// Write data to the IO channel - opened file descriptor, socket or SSL
 
1342
// descriptor. Return number of bytes written.
 
1343
static int64_t push(FILE *fp, SOCKET sock, SSL *ssl, const char *buf,
 
1344
                    int64_t len) {
 
1345
  int64_t sent;
 
1346
  int n, k;
 
1347
 
 
1348
  sent = 0;
 
1349
  while (sent < len) {
 
1350
 
 
1351
    // How many bytes we send in this iteration
 
1352
    k = len - sent > INT_MAX ? INT_MAX : (int) (len - sent);
 
1353
 
 
1354
    if (ssl != NULL) {
 
1355
      n = SSL_write(ssl, buf + sent, k);
 
1356
    } else if (fp != NULL) {
 
1357
      n = fwrite(buf + sent, 1, (size_t) k, fp);
 
1358
      if (ferror(fp))
 
1359
        n = -1;
 
1360
    } else {
 
1361
      n = send(sock, buf + sent, (size_t) k, MSG_NOSIGNAL);
 
1362
    }
 
1363
 
 
1364
    if (n < 0)
 
1365
      break;
 
1366
 
 
1367
    sent += n;
 
1368
  }
 
1369
 
 
1370
  return sent;
 
1371
}
 
1372
 
 
1373
// Read from IO channel - opened file descriptor, socket, or SSL descriptor.
 
1374
// Return number of bytes read.
 
1375
static int pull(FILE *fp, SOCKET sock, SSL *ssl, char *buf, int len) {
 
1376
  int nread;
 
1377
 
 
1378
  if (ssl != NULL) {
 
1379
    nread = SSL_read(ssl, buf, len);
 
1380
  } else if (fp != NULL) {
 
1381
    // Use read() instead of fread(), because if we're reading from the CGI
 
1382
    // pipe, fread() may block until IO buffer is filled up. We cannot afford
 
1383
    // to block and must pass all read bytes immediately to the client.
 
1384
    nread = read(fileno(fp), buf, (size_t) len);
 
1385
    if (ferror(fp))
 
1386
      nread = -1;
 
1387
  } else {
 
1388
    nread = recv(sock, buf, (size_t) len, 0);
 
1389
  }
 
1390
 
 
1391
  return nread;
 
1392
}
 
1393
 
 
1394
int mg_read(struct mg_connection *conn, void *buf, size_t len) {
 
1395
  int n, buffered_len, nread;
 
1396
  const char *buffered;
 
1397
 
 
1398
  assert((conn->content_len == -1 && conn->consumed_content == 0) ||
 
1399
         conn->consumed_content <= conn->content_len);
 
1400
  DEBUG_TRACE(("%p %zu %lld %lld", buf, len,
 
1401
               conn->content_len, conn->consumed_content));
 
1402
  nread = 0;
 
1403
  if (conn->consumed_content < conn->content_len) {
 
1404
 
 
1405
    // Adjust number of bytes to read.
 
1406
    int64_t to_read = conn->content_len - conn->consumed_content;
 
1407
    if (to_read < (int64_t) len) {
 
1408
      len = (int) to_read;
 
1409
    }
 
1410
 
 
1411
    // How many bytes of data we have buffered in the request buffer?
 
1412
    buffered = conn->buf + conn->request_len + conn->consumed_content;
 
1413
    buffered_len = conn->data_len - conn->request_len;
 
1414
    assert(buffered_len >= 0);
 
1415
 
 
1416
    // Return buffered data back if we haven't done that yet.
 
1417
    if (conn->consumed_content < (int64_t) buffered_len) {
 
1418
      buffered_len -= (int) conn->consumed_content;
 
1419
      if (len < (size_t) buffered_len) {
 
1420
        buffered_len = len;
 
1421
      }
 
1422
      memcpy(buf, buffered, (size_t)buffered_len);
 
1423
      len -= buffered_len;
 
1424
      buf = (char *) buf + buffered_len;
 
1425
      conn->consumed_content += buffered_len;
 
1426
      nread = buffered_len;
 
1427
    }
 
1428
 
 
1429
    // We have returned all buffered data. Read new data from the remote socket.
 
1430
    while (len > 0) {
 
1431
      n = pull(NULL, conn->client.sock, conn->ssl, (char *) buf, (int) len);
 
1432
      if (n <= 0) {
 
1433
        break;
 
1434
      }
 
1435
      buf = (char *) buf + n;
 
1436
      conn->consumed_content += n;
 
1437
      nread += n;
 
1438
      len -= n;
 
1439
    }
 
1440
  }
 
1441
  return nread;
 
1442
}
 
1443
 
 
1444
int mg_write(struct mg_connection *conn, const void *buf, size_t len) {
 
1445
  return (int) push(NULL, conn->client.sock, conn->ssl, (const char *) buf,
 
1446
                    (int64_t) len);
 
1447
}
 
1448
 
 
1449
int mg_printf(struct mg_connection *conn, const char *fmt, ...) {
 
1450
  char buf[BUFSIZ];
 
1451
  int len;
 
1452
  va_list ap;
 
1453
 
 
1454
  va_start(ap, fmt);
 
1455
  len = mg_vsnprintf(conn, buf, sizeof(buf), fmt, ap);
 
1456
  va_end(ap);
 
1457
 
 
1458
  return mg_write(conn, buf, (size_t)len);
 
1459
}
 
1460
 
 
1461
// URL-decode input buffer into destination buffer.
 
1462
// 0-terminate the destination buffer. Return the length of decoded data.
 
1463
// form-url-encoded data differs from URI encoding in a way that it
 
1464
// uses '+' as character for space, see RFC 1866 section 8.2.1
 
1465
// http://ftp.ics.uci.edu/pub/ietf/html/rfc1866.txt
 
1466
static size_t url_decode(const char *src, size_t src_len, char *dst,
 
1467
                         size_t dst_len, int is_form_url_encoded) {
 
1468
  size_t i, j;
 
1469
  int a, b;
 
1470
#define HEXTOI(x) (isdigit(x) ? x - '0' : x - 'W')
 
1471
 
 
1472
  for (i = j = 0; i < src_len && j < dst_len - 1; i++, j++) {
 
1473
    if (src[i] == '%' &&
 
1474
        isxdigit(* (const unsigned char *) (src + i + 1)) &&
 
1475
        isxdigit(* (const unsigned char *) (src + i + 2))) {
 
1476
      a = tolower(* (const unsigned char *) (src + i + 1));
 
1477
      b = tolower(* (const unsigned char *) (src + i + 2));
 
1478
      dst[j] = (char) ((HEXTOI(a) << 4) | HEXTOI(b));
 
1479
      i += 2;
 
1480
    } else if (is_form_url_encoded && src[i] == '+') {
 
1481
      dst[j] = ' ';
 
1482
    } else {
 
1483
      dst[j] = src[i];
 
1484
    }
 
1485
  }
 
1486
 
 
1487
  dst[j] = '\0'; // Null-terminate the destination
 
1488
 
 
1489
  return j;
 
1490
}
 
1491
 
 
1492
// Scan given buffer and fetch the value of the given variable.
 
1493
// It can be specified in query string, or in the POST data.
 
1494
// Return NULL if the variable not found, or allocated 0-terminated value.
 
1495
// It is caller's responsibility to free the returned value.
 
1496
int mg_get_var(const char *buf, size_t buf_len, const char *name,
 
1497
               char *dst, size_t dst_len) {
 
1498
  const char *p, *e, *s;
 
1499
  size_t name_len, len;
 
1500
 
 
1501
  name_len = strlen(name);
 
1502
  e = buf + buf_len;
 
1503
  len = -1;
 
1504
  dst[0] = '\0';
 
1505
 
 
1506
  // buf is "var1=val1&var2=val2...". Find variable first
 
1507
  for (p = buf; p != NULL && p + name_len < e; p++) {
 
1508
    if ((p == buf || p[-1] == '&') && p[name_len] == '=' &&
 
1509
        !mg_strncasecmp(name, p, name_len)) {
 
1510
 
 
1511
      // Point p to variable value
 
1512
      p += name_len + 1;
 
1513
 
 
1514
      // Point s to the end of the value
 
1515
      s = (const char *) memchr(p, '&', (size_t)(e - p));
 
1516
      if (s == NULL) {
 
1517
        s = e;
 
1518
      }
 
1519
      assert(s >= p);
 
1520
 
 
1521
      // Decode variable into destination buffer
 
1522
      if ((size_t) (s - p) < dst_len) {
 
1523
        len = url_decode(p, (size_t)(s - p), dst, dst_len, 1);
 
1524
      }
 
1525
      break;
 
1526
    }
 
1527
  }
 
1528
 
 
1529
  return len;
 
1530
}
 
1531
 
 
1532
int mg_get_cookie(const struct mg_connection *conn, const char *cookie_name,
 
1533
                  char *dst, size_t dst_size) {
 
1534
  const char *s, *p, *end;
 
1535
  int name_len, len = -1;
 
1536
 
 
1537
  dst[0] = '\0';
 
1538
  if ((s = mg_get_header(conn, "Cookie")) == NULL) {
 
1539
    return 0;
 
1540
  }
 
1541
 
 
1542
  name_len = strlen(cookie_name);
 
1543
  end = s + strlen(s);
 
1544
 
 
1545
  for (; (s = strstr(s, cookie_name)) != NULL; s += name_len)
 
1546
    if (s[name_len] == '=') {
 
1547
      s += name_len + 1;
 
1548
      if ((p = strchr(s, ' ')) == NULL)
 
1549
        p = end;
 
1550
      if (p[-1] == ';')
 
1551
        p--;
 
1552
      if (*s == '"' && p[-1] == '"' && p > s + 1) {
 
1553
        s++;
 
1554
        p--;
 
1555
      }
 
1556
      if ((size_t) (p - s) < dst_size) {
 
1557
        len = (p - s) + 1;
 
1558
        mg_strlcpy(dst, s, (size_t)len);
 
1559
      }
 
1560
      break;
 
1561
    }
 
1562
 
 
1563
  return len;
 
1564
}
 
1565
 
 
1566
static int convert_uri_to_file_name(struct mg_connection *conn, char *buf,
 
1567
                                    size_t buf_len, struct mgstat *st) {
 
1568
  struct vec a, b;
 
1569
  const char *rewrite, *uri = conn->request_info.uri;
 
1570
  char *p;
 
1571
  int match_len, stat_result;
 
1572
 
 
1573
  buf_len--;  // This is because memmove() for PATH_INFO may shift part
 
1574
              // of the path one byte on the right.
 
1575
  mg_snprintf(conn, buf, buf_len, "%s%s", conn->ctx->config[DOCUMENT_ROOT],
 
1576
              uri);
 
1577
 
 
1578
  rewrite = conn->ctx->config[REWRITE];
 
1579
  while ((rewrite = next_option(rewrite, &a, &b)) != NULL) {
 
1580
    if ((match_len = match_prefix(a.ptr, a.len, uri)) > 0) {
 
1581
      mg_snprintf(conn, buf, buf_len, "%.*s%s", b.len, b.ptr, uri + match_len);
 
1582
      break;
 
1583
    }
 
1584
  }
 
1585
 
 
1586
#if defined(_WIN32) && !defined(__SYMBIAN32__)
 
1587
  //change_slashes_to_backslashes(buf);
 
1588
#endif // _WIN32
 
1589
 
 
1590
  if ((stat_result = mg_stat(buf, st)) != 0) {
 
1591
    // Support PATH_INFO for CGI scripts.
 
1592
    for (p = buf + strlen(buf); p > buf + 1; p--) {
 
1593
      if (*p == '/') {
 
1594
        *p = '\0';
 
1595
        if (match_prefix(conn->ctx->config[CGI_EXTENSIONS],
 
1596
                         strlen(conn->ctx->config[CGI_EXTENSIONS]), buf) > 0 &&
 
1597
            (stat_result = mg_stat(buf, st)) == 0) {
 
1598
          conn->path_info = p + 1;
 
1599
          memmove(p + 2, p + 1, strlen(p + 1));
 
1600
          p[1] = '/';
 
1601
          break;
 
1602
        } else {
 
1603
          *p = '/';
 
1604
          stat_result = -1;
 
1605
        }
 
1606
      }
 
1607
    }
 
1608
  }
 
1609
 
 
1610
  return stat_result;
 
1611
}
 
1612
 
 
1613
static int sslize(struct mg_connection *conn, int (*func)(SSL *)) {
 
1614
  return (conn->ssl = SSL_new(conn->ctx->ssl_ctx)) != NULL &&
 
1615
    SSL_set_fd(conn->ssl, conn->client.sock) == 1 &&
 
1616
    func(conn->ssl) == 1;
 
1617
}
 
1618
 
 
1619
// Check whether full request is buffered. Return:
 
1620
//   -1  if request is malformed
 
1621
//    0  if request is not yet fully buffered
 
1622
//   >0  actual request length, including last \r\n\r\n
 
1623
static int get_request_len(const char *buf, int buflen) {
 
1624
  const char *s, *e;
 
1625
  int len = 0;
 
1626
 
 
1627
  DEBUG_TRACE(("buf: %p, len: %d", buf, buflen));
 
1628
  for (s = buf, e = s + buflen - 1; len <= 0 && s < e; s++)
 
1629
    // Control characters are not allowed but >=128 is.
 
1630
    if (!isprint(* (const unsigned char *) s) && *s != '\r' &&
 
1631
        *s != '\n' && * (const unsigned char *) s < 128) {
 
1632
      len = -1;
 
1633
    } else if (s[0] == '\n' && s[1] == '\n') {
 
1634
      len = (int) (s - buf) + 2;
 
1635
    } else if (s[0] == '\n' && &s[1] < e &&
 
1636
        s[1] == '\r' && s[2] == '\n') {
 
1637
      len = (int) (s - buf) + 3;
 
1638
    }
 
1639
 
 
1640
  return len;
 
1641
}
 
1642
 
 
1643
// Convert month to the month number. Return -1 on error, or month number
 
1644
static int get_month_index(const char *s) {
 
1645
  size_t i;
 
1646
 
 
1647
  for (i = 0; i < ARRAY_SIZE(month_names); i++)
 
1648
    if (!strcmp(s, month_names[i]))
 
1649
      return (int) i;
 
1650
 
 
1651
  return -1;
 
1652
}
 
1653
 
 
1654
// Parse UTC date-time string, and return the corresponding time_t value.
 
1655
static time_t parse_date_string(const char *datetime) {
 
1656
  static const unsigned short days_before_month[] = {
 
1657
    0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
 
1658
  };
 
1659
  char month_str[32];
 
1660
  int second, minute, hour, day, month, year, leap_days, days;
 
1661
  time_t result = (time_t) 0;
 
1662
 
 
1663
  if (((sscanf(datetime, "%d/%3s/%d %d:%d:%d",
 
1664
               &day, month_str, &year, &hour, &minute, &second) == 6) ||
 
1665
       (sscanf(datetime, "%d %3s %d %d:%d:%d",
 
1666
               &day, month_str, &year, &hour, &minute, &second) == 6) ||
 
1667
       (sscanf(datetime, "%*3s, %d %3s %d %d:%d:%d",
 
1668
               &day, month_str, &year, &hour, &minute, &second) == 6) ||
 
1669
       (sscanf(datetime, "%d-%3s-%d %d:%d:%d",
 
1670
               &day, month_str, &year, &hour, &minute, &second) == 6)) &&
 
1671
      year > 1970 &&
 
1672
      (month = get_month_index(month_str)) != -1) {
 
1673
    year -= 1970;
 
1674
    leap_days = year / 4 - year / 100 + year / 400;
 
1675
    days = year * 365 + days_before_month[month] + (day - 1) + leap_days;
 
1676
    result = days * 24 * 3600 + hour * 3600 + minute * 60 + second;
 
1677
  }
 
1678
 
 
1679
  return result;
 
1680
}
 
1681
 
 
1682
// Protect against directory disclosure attack by removing '..',
 
1683
// excessive '/' and '\' characters
 
1684
static void remove_double_dots_and_double_slashes(char *s) {
 
1685
  char *p = s;
 
1686
 
 
1687
  while (*s != '\0') {
 
1688
    *p++ = *s++;
 
1689
    if (IS_DIRSEP_CHAR(s[-1])) {
 
1690
      // Skip all following slashes and backslashes
 
1691
      while (IS_DIRSEP_CHAR(s[0])) {
 
1692
        s++;
 
1693
      }
 
1694
 
 
1695
      // Skip all double-dots
 
1696
      while (*s == '.' && s[1] == '.') {
 
1697
        s += 2;
 
1698
      }
 
1699
    }
 
1700
  }
 
1701
  *p = '\0';
 
1702
}
 
1703
 
 
1704
static const struct {
 
1705
  const char *extension;
 
1706
  size_t ext_len;
 
1707
  const char *mime_type;
 
1708
  size_t mime_type_len;
 
1709
} builtin_mime_types[] = {
 
1710
  {".html", 5, "text/html",   9},
 
1711
  {".htm", 4, "text/html",   9},
 
1712
  {".shtm", 5, "text/html",   9},
 
1713
  {".shtml", 6, "text/html",   9},
 
1714
  {".css", 4, "text/css",   8},
 
1715
  {".js",  3, "application/x-javascript", 24},
 
1716
  {".ico", 4, "image/x-icon",   12},
 
1717
  {".gif", 4, "image/gif",   9},
 
1718
  {".jpg", 4, "image/jpeg",   10},
 
1719
  {".jpeg", 5, "image/jpeg",   10},
 
1720
  {".png", 4, "image/png",   9},
 
1721
  {".svg", 4, "image/svg+xml",  13},
 
1722
  {".torrent", 8, "application/x-bittorrent", 24},
 
1723
  {".wav", 4, "audio/x-wav",   11},
 
1724
  {".mp3", 4, "audio/x-mp3",   11},
 
1725
  {".mid", 4, "audio/mid",   9},
 
1726
  {".m3u", 4, "audio/x-mpegurl",  15},
 
1727
  {".ram", 4, "audio/x-pn-realaudio",  20},
 
1728
  {".xml", 4, "text/xml",   8},
 
1729
  {".xslt", 5, "application/xml",  15},
 
1730
  {".ra",  3, "audio/x-pn-realaudio",  20},
 
1731
  {".doc", 4, "application/msword",  19},
 
1732
  {".exe", 4, "application/octet-stream", 24},
 
1733
  {".zip", 4, "application/x-zip-compressed", 28},
 
1734
  {".xls", 4, "application/excel",  17},
 
1735
  {".tgz", 4, "application/x-tar-gz",  20},
 
1736
  {".tar", 4, "application/x-tar",  17},
 
1737
  {".gz",  3, "application/x-gunzip",  20},
 
1738
  {".arj", 4, "application/x-arj-compressed", 28},
 
1739
  {".rar", 4, "application/x-arj-compressed", 28},
 
1740
  {".rtf", 4, "application/rtf",  15},
 
1741
  {".pdf", 4, "application/pdf",  15},
 
1742
  {".swf", 4, "application/x-shockwave-flash",29},
 
1743
  {".mpg", 4, "video/mpeg",   10},
 
1744
  {".mpeg", 5, "video/mpeg",   10},
 
1745
  {".mp4", 4, "video/mp4", 9},
 
1746
  {".m4v", 4, "video/x-m4v", 11},
 
1747
  {".asf", 4, "video/x-ms-asf",  14},
 
1748
  {".avi", 4, "video/x-msvideo",  15},
 
1749
  {".bmp", 4, "image/bmp",   9},
 
1750
  {NULL,  0, NULL,    0}
 
1751
};
 
1752
 
 
1753
// Look at the "path" extension and figure what mime type it has.
 
1754
// Store mime type in the vector.
 
1755
static void get_mime_type(struct mg_context *ctx, const char *path,
 
1756
                          struct vec *vec) {
 
1757
  struct vec ext_vec, mime_vec;
 
1758
  const char *list, *ext;
 
1759
  size_t i, path_len;
 
1760
 
 
1761
  path_len = strlen(path);
 
1762
 
 
1763
  // Scan user-defined mime types first, in case user wants to
 
1764
  // override default mime types.
 
1765
  list = ctx->config[EXTRA_MIME_TYPES];
 
1766
  while ((list = next_option(list, &ext_vec, &mime_vec)) != NULL) {
 
1767
    // ext now points to the path suffix
 
1768
    ext = path + path_len - ext_vec.len;
 
1769
    if (mg_strncasecmp(ext, ext_vec.ptr, ext_vec.len) == 0) {
 
1770
      *vec = mime_vec;
 
1771
      return;
 
1772
    }
 
1773
  }
 
1774
 
 
1775
  // Now scan built-in mime types
 
1776
  for (i = 0; builtin_mime_types[i].extension != NULL; i++) {
 
1777
    ext = path + (path_len - builtin_mime_types[i].ext_len);
 
1778
    if (path_len > builtin_mime_types[i].ext_len &&
 
1779
        mg_strcasecmp(ext, builtin_mime_types[i].extension) == 0) {
 
1780
      vec->ptr = builtin_mime_types[i].mime_type;
 
1781
      vec->len = builtin_mime_types[i].mime_type_len;
 
1782
      return;
 
1783
    }
 
1784
  }
 
1785
 
 
1786
  // Nothing found. Fall back to "text/plain"
 
1787
  vec->ptr = "text/plain";
 
1788
  vec->len = 10;
 
1789
}
 
1790
 
 
1791
#ifndef HAVE_MD5
 
1792
typedef struct MD5Context {
 
1793
  uint32_t buf[4];
 
1794
  uint32_t bits[2];
 
1795
  unsigned char in[64];
 
1796
} MD5_CTX;
 
1797
 
 
1798
#if defined(__BYTE_ORDER) && (__BYTE_ORDER == 1234)
 
1799
#define byteReverse(buf, len) // Do nothing
 
1800
#else
 
1801
static void byteReverse(unsigned char *buf, unsigned longs) {
 
1802
  uint32_t t;
 
1803
  do {
 
1804
    t = (uint32_t) ((unsigned) buf[3] << 8 | buf[2]) << 16 |
 
1805
      ((unsigned) buf[1] << 8 | buf[0]);
 
1806
    *(uint32_t *) buf = t;
 
1807
    buf += 4;
 
1808
  } while (--longs);
 
1809
}
 
1810
#endif
 
1811
 
 
1812
#define F1(x, y, z) (z ^ (x & (y ^ z)))
 
1813
#define F2(x, y, z) F1(z, x, y)
 
1814
#define F3(x, y, z) (x ^ y ^ z)
 
1815
#define F4(x, y, z) (y ^ (x | ~z))
 
1816
 
 
1817
#define MD5STEP(f, w, x, y, z, data, s) \
 
1818
  ( w += f(x, y, z) + data,  w = w<<s | w>>(32-s),  w += x )
 
1819
 
 
1820
// Start MD5 accumulation.  Set bit count to 0 and buffer to mysterious
 
1821
// initialization constants.
 
1822
static void MD5Init(MD5_CTX *ctx) {
 
1823
  ctx->buf[0] = 0x67452301;
 
1824
  ctx->buf[1] = 0xefcdab89;
 
1825
  ctx->buf[2] = 0x98badcfe;
 
1826
  ctx->buf[3] = 0x10325476;
 
1827
 
 
1828
  ctx->bits[0] = 0;
 
1829
  ctx->bits[1] = 0;
 
1830
}
 
1831
 
 
1832
static void MD5Transform(uint32_t buf[4], uint32_t const in[16]) {
 
1833
  register uint32_t a, b, c, d;
 
1834
 
 
1835
  a = buf[0];
 
1836
  b = buf[1];
 
1837
  c = buf[2];
 
1838
  d = buf[3];
 
1839
 
 
1840
  MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
 
1841
  MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
 
1842
  MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
 
1843
  MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
 
1844
  MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
 
1845
  MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
 
1846
  MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
 
1847
  MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
 
1848
  MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
 
1849
  MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
 
1850
  MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
 
1851
  MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
 
1852
  MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
 
1853
  MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
 
1854
  MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
 
1855
  MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
 
1856
 
 
1857
  MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
 
1858
  MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
 
1859
  MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
 
1860
  MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
 
1861
  MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
 
1862
  MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
 
1863
  MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
 
1864
  MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
 
1865
  MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
 
1866
  MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
 
1867
  MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
 
1868
  MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
 
1869
  MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
 
1870
  MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
 
1871
  MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
 
1872
  MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
 
1873
 
 
1874
  MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
 
1875
  MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
 
1876
  MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
 
1877
  MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
 
1878
  MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
 
1879
  MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
 
1880
  MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
 
1881
  MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
 
1882
  MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
 
1883
  MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
 
1884
  MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
 
1885
  MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
 
1886
  MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
 
1887
  MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
 
1888
  MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
 
1889
  MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
 
1890
 
 
1891
  MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
 
1892
  MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
 
1893
  MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
 
1894
  MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
 
1895
  MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
 
1896
  MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
 
1897
  MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
 
1898
  MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
 
1899
  MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
 
1900
  MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
 
1901
  MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
 
1902
  MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
 
1903
  MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
 
1904
  MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
 
1905
  MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
 
1906
  MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
 
1907
 
 
1908
  buf[0] += a;
 
1909
  buf[1] += b;
 
1910
  buf[2] += c;
 
1911
  buf[3] += d;
 
1912
}
 
1913
 
 
1914
static void MD5Update(MD5_CTX *ctx, unsigned char const *buf, unsigned len) {
 
1915
  uint32_t t;
 
1916
 
 
1917
  t = ctx->bits[0];
 
1918
  if ((ctx->bits[0] = t + ((uint32_t) len << 3)) < t)
 
1919
    ctx->bits[1]++;
 
1920
  ctx->bits[1] += len >> 29;
 
1921
 
 
1922
  t = (t >> 3) & 0x3f;
 
1923
 
 
1924
  if (t) {
 
1925
    unsigned char *p = (unsigned char *) ctx->in + t;
 
1926
 
 
1927
    t = 64 - t;
 
1928
    if (len < t) {
 
1929
      memcpy(p, buf, len);
 
1930
      return;
 
1931
    }
 
1932
    memcpy(p, buf, t);
 
1933
    byteReverse(ctx->in, 16);
 
1934
    MD5Transform(ctx->buf, (uint32_t *) ctx->in);
 
1935
    buf += t;
 
1936
    len -= t;
 
1937
  }
 
1938
 
 
1939
  while (len >= 64) {
 
1940
    memcpy(ctx->in, buf, 64);
 
1941
    byteReverse(ctx->in, 16);
 
1942
    MD5Transform(ctx->buf, (uint32_t *) ctx->in);
 
1943
    buf += 64;
 
1944
    len -= 64;
 
1945
  }
 
1946
 
 
1947
  memcpy(ctx->in, buf, len);
 
1948
}
 
1949
 
 
1950
static void MD5Final(unsigned char digest[16], MD5_CTX *ctx) {
 
1951
  unsigned count;
 
1952
  unsigned char *p;
 
1953
 
 
1954
  count = (ctx->bits[0] >> 3) & 0x3F;
 
1955
 
 
1956
  p = ctx->in + count;
 
1957
  *p++ = 0x80;
 
1958
  count = 64 - 1 - count;
 
1959
  if (count < 8) {
 
1960
    memset(p, 0, count);
 
1961
    byteReverse(ctx->in, 16);
 
1962
    MD5Transform(ctx->buf, (uint32_t *) ctx->in);
 
1963
    memset(ctx->in, 0, 56);
 
1964
  } else {
 
1965
    memset(p, 0, count - 8);
 
1966
  }
 
1967
  byteReverse(ctx->in, 14);
 
1968
 
 
1969
  ((uint32_t *) ctx->in)[14] = ctx->bits[0];
 
1970
  ((uint32_t *) ctx->in)[15] = ctx->bits[1];
 
1971
 
 
1972
  MD5Transform(ctx->buf, (uint32_t *) ctx->in);
 
1973
  byteReverse((unsigned char *) ctx->buf, 4);
 
1974
  memcpy(digest, ctx->buf, 16);
 
1975
  memset((char *) ctx, 0, sizeof(*ctx));
 
1976
}
 
1977
#endif // !HAVE_MD5
 
1978
 
 
1979
// Stringify binary data. Output buffer must be twice as big as input,
 
1980
// because each byte takes 2 bytes in string representation
 
1981
static void bin2str(char *to, const unsigned char *p, size_t len) {
 
1982
  static const char *hex = "0123456789abcdef";
 
1983
 
 
1984
  for (; len--; p++) {
 
1985
    *to++ = hex[p[0] >> 4];
 
1986
    *to++ = hex[p[0] & 0x0f];
 
1987
  }
 
1988
  *to = '\0';
 
1989
}
 
1990
 
 
1991
// Return stringified MD5 hash for list of vectors. Buffer must be 33 bytes.
 
1992
void mg_md5(char *buf, ...) {
 
1993
  unsigned char hash[16];
 
1994
  const char *p;
 
1995
  va_list ap;
 
1996
  MD5_CTX ctx;
 
1997
 
 
1998
  MD5Init(&ctx);
 
1999
 
 
2000
  va_start(ap, buf);
 
2001
  while ((p = va_arg(ap, const char *)) != NULL) {
 
2002
    MD5Update(&ctx, (const unsigned char *) p, (unsigned) strlen(p));
 
2003
  }
 
2004
  va_end(ap);
 
2005
 
 
2006
  MD5Final(hash, &ctx);
 
2007
  bin2str(buf, hash, sizeof(hash));
 
2008
}
 
2009
 
 
2010
// Check the user's password, return 1 if OK
 
2011
static int check_password(const char *method, const char *ha1, const char *uri,
 
2012
                          const char *nonce, const char *nc, const char *cnonce,
 
2013
                          const char *qop, const char *response) {
 
2014
  char ha2[32 + 1], expected_response[32 + 1];
 
2015
 
 
2016
  // Some of the parameters may be NULL
 
2017
  if (method == NULL || nonce == NULL || nc == NULL || cnonce == NULL ||
 
2018
      qop == NULL || response == NULL) {
 
2019
    return 0;
 
2020
  }
 
2021
 
 
2022
  // NOTE(lsm): due to a bug in MSIE, we do not compare the URI
 
2023
  // TODO(lsm): check for authentication timeout
 
2024
  if (// strcmp(dig->uri, c->ouri) != 0 ||
 
2025
      strlen(response) != 32
 
2026
      // || now - strtoul(dig->nonce, NULL, 10) > 3600
 
2027
      ) {
 
2028
    return 0;
 
2029
  }
 
2030
 
 
2031
  mg_md5(ha2, method, ":", uri, NULL);
 
2032
  mg_md5(expected_response, ha1, ":", nonce, ":", nc,
 
2033
      ":", cnonce, ":", qop, ":", ha2, NULL);
 
2034
 
 
2035
  return mg_strcasecmp(response, expected_response) == 0;
 
2036
}
 
2037
 
 
2038
// Use the global passwords file, if specified by auth_gpass option,
 
2039
// or search for .htpasswd in the requested directory.
 
2040
static FILE *open_auth_file(struct mg_connection *conn, const char *path) {
 
2041
  struct mg_context *ctx = conn->ctx;
 
2042
  char name[PATH_MAX];
 
2043
  const char *p, *e;
 
2044
  struct mgstat st;
 
2045
  FILE *fp;
 
2046
 
 
2047
  if (ctx->config[GLOBAL_PASSWORDS_FILE] != NULL) {
 
2048
    // Use global passwords file
 
2049
    fp =  mg_fopen(ctx->config[GLOBAL_PASSWORDS_FILE], "r");
 
2050
    if (fp == NULL)
 
2051
      cry(fc(ctx), "fopen(%s): %s",
 
2052
          ctx->config[GLOBAL_PASSWORDS_FILE], strerror(ERRNO));
 
2053
  } else if (!mg_stat(path, &st) && st.is_directory) {
 
2054
    (void) mg_snprintf(conn, name, sizeof(name), "%s%c%s",
 
2055
        path, DIRSEP, PASSWORDS_FILE_NAME);
 
2056
    fp = mg_fopen(name, "r");
 
2057
  } else {
 
2058
     // Try to find .htpasswd in requested directory.
 
2059
    for (p = path, e = p + strlen(p) - 1; e > p; e--)
 
2060
      if (IS_DIRSEP_CHAR(*e))
 
2061
        break;
 
2062
    (void) mg_snprintf(conn, name, sizeof(name), "%.*s%c%s",
 
2063
        (int) (e - p), p, DIRSEP, PASSWORDS_FILE_NAME);
 
2064
    fp = mg_fopen(name, "r");
 
2065
  }
 
2066
 
 
2067
  return fp;
 
2068
}
 
2069
 
 
2070
// Parsed Authorization header
 
2071
struct ah {
 
2072
  char *user, *uri, *cnonce, *response, *qop, *nc, *nonce;
 
2073
};
 
2074
 
 
2075
static int parse_auth_header(struct mg_connection *conn, char *buf,
 
2076
                             size_t buf_size, struct ah *ah) {
 
2077
  char *name, *value, *s;
 
2078
  const char *auth_header;
 
2079
 
 
2080
  if ((auth_header = mg_get_header(conn, "Authorization")) == NULL ||
 
2081
      mg_strncasecmp(auth_header, "Digest ", 7) != 0) {
 
2082
    return 0;
 
2083
  }
 
2084
 
 
2085
  // Make modifiable copy of the auth header
 
2086
  (void) mg_strlcpy(buf, auth_header + 7, buf_size);
 
2087
 
 
2088
  s = buf;
 
2089
  (void) memset(ah, 0, sizeof(*ah));
 
2090
 
 
2091
  // Parse authorization header
 
2092
  for (;;) {
 
2093
    // Gobble initial spaces
 
2094
    while (isspace(* (unsigned char *) s)) {
 
2095
      s++;
 
2096
    }
 
2097
    name = skip_quoted(&s, "=", " ", 0);
 
2098
    // Value is either quote-delimited, or ends at first comma or space.
 
2099
    if (s[0] == '\"') {
 
2100
      s++;
 
2101
      value = skip_quoted(&s, "\"", " ", '\\');
 
2102
      if (s[0] == ',') {
 
2103
        s++;
 
2104
      }
 
2105
    } else {
 
2106
      value = skip_quoted(&s, ", ", " ", 0);  // IE uses commas, FF uses spaces
 
2107
    }
 
2108
    if (*name == '\0') {
 
2109
      break;
 
2110
    }
 
2111
 
 
2112
    if (!strcmp(name, "username")) {
 
2113
      ah->user = value;
 
2114
    } else if (!strcmp(name, "cnonce")) {
 
2115
      ah->cnonce = value;
 
2116
    } else if (!strcmp(name, "response")) {
 
2117
      ah->response = value;
 
2118
    } else if (!strcmp(name, "uri")) {
 
2119
      ah->uri = value;
 
2120
    } else if (!strcmp(name, "qop")) {
 
2121
      ah->qop = value;
 
2122
    } else if (!strcmp(name, "nc")) {
 
2123
      ah->nc = value;
 
2124
    } else if (!strcmp(name, "nonce")) {
 
2125
      ah->nonce = value;
 
2126
    }
 
2127
  }
 
2128
 
 
2129
  // CGI needs it as REMOTE_USER
 
2130
  if (ah->user != NULL) {
 
2131
    conn->request_info.remote_user = mg_strdup(ah->user);
 
2132
  } else {
 
2133
    return 0;
 
2134
  }
 
2135
 
 
2136
  return 1;
 
2137
}
 
2138
 
 
2139
// Authorize against the opened passwords file. Return 1 if authorized.
 
2140
static int authorize(struct mg_connection *conn, FILE *fp) {
 
2141
  struct ah ah;
 
2142
  char line[256], f_user[256], ha1[256], f_domain[256], buf[BUFSIZ];
 
2143
 
 
2144
  if (!parse_auth_header(conn, buf, sizeof(buf), &ah)) {
 
2145
    return 0;
 
2146
  }
 
2147
 
 
2148
  // Loop over passwords file
 
2149
  while (fgets(line, sizeof(line), fp) != NULL) {
 
2150
    if (sscanf(line, "%[^:]:%[^:]:%s", f_user, f_domain, ha1) != 3) {
 
2151
      continue;
 
2152
    }
 
2153
 
 
2154
    if (!strcmp(ah.user, f_user) &&
 
2155
        !strcmp(conn->ctx->config[AUTHENTICATION_DOMAIN], f_domain))
 
2156
      return check_password(
 
2157
            conn->request_info.request_method,
 
2158
            ha1, ah.uri, ah.nonce, ah.nc, ah.cnonce, ah.qop,
 
2159
            ah.response);
 
2160
  }
 
2161
 
 
2162
  return 0;
 
2163
}
 
2164
 
 
2165
// Return 1 if request is authorised, 0 otherwise.
 
2166
static int check_authorization(struct mg_connection *conn, const char *path) {
 
2167
  FILE *fp;
 
2168
  char fname[PATH_MAX];
 
2169
  struct vec uri_vec, filename_vec;
 
2170
  const char *list;
 
2171
  int authorized;
 
2172
 
 
2173
  fp = NULL;
 
2174
  authorized = 1;
 
2175
 
 
2176
  list = conn->ctx->config[PROTECT_URI];
 
2177
  while ((list = next_option(list, &uri_vec, &filename_vec)) != NULL) {
 
2178
    if (!memcmp(conn->request_info.uri, uri_vec.ptr, uri_vec.len)) {
 
2179
      (void) mg_snprintf(conn, fname, sizeof(fname), "%.*s",
 
2180
          filename_vec.len, filename_vec.ptr);
 
2181
      if ((fp = mg_fopen(fname, "r")) == NULL) {
 
2182
        cry(conn, "%s: cannot open %s: %s", __func__, fname, strerror(errno));
 
2183
      }
 
2184
      break;
 
2185
    }
 
2186
  }
 
2187
 
 
2188
  if (fp == NULL) {
 
2189
    fp = open_auth_file(conn, path);
 
2190
  }
 
2191
 
 
2192
  if (fp != NULL) {
 
2193
    authorized = authorize(conn, fp);
 
2194
    (void) fclose(fp);
 
2195
  }
 
2196
 
 
2197
  return authorized;
 
2198
}
 
2199
 
 
2200
static void send_authorization_request(struct mg_connection *conn) {
 
2201
  conn->request_info.status_code = 401;
 
2202
  (void) mg_printf(conn,
 
2203
      "HTTP/1.1 401 Unauthorized\r\n"
 
2204
      "Content-Length: 0\r\n"
 
2205
      "WWW-Authenticate: Digest qop=\"auth\", "
 
2206
      "realm=\"%s\", nonce=\"%lu\"\r\n\r\n",
 
2207
      conn->ctx->config[AUTHENTICATION_DOMAIN],
 
2208
      (unsigned long) time(NULL));
 
2209
}
 
2210
 
 
2211
static int is_authorized_for_put(struct mg_connection *conn) {
 
2212
  FILE *fp;
 
2213
  int ret = 0;
 
2214
 
 
2215
  fp = conn->ctx->config[PUT_DELETE_PASSWORDS_FILE] == NULL ? NULL :
 
2216
    mg_fopen(conn->ctx->config[PUT_DELETE_PASSWORDS_FILE], "r");
 
2217
 
 
2218
  if (fp != NULL) {
 
2219
    ret = authorize(conn, fp);
 
2220
    (void) fclose(fp);
 
2221
  }
 
2222
 
 
2223
  return ret;
 
2224
}
 
2225
 
 
2226
int mg_modify_passwords_file(const char *fname, const char *domain,
 
2227
                             const char *user, const char *pass) {
 
2228
  int found;
 
2229
  char line[512], u[512], d[512], ha1[33], tmp[PATH_MAX];
 
2230
  FILE *fp, *fp2;
 
2231
 
 
2232
  found = 0;
 
2233
  fp = fp2 = NULL;
 
2234
 
 
2235
  // Regard empty password as no password - remove user record.
 
2236
  if (pass != NULL && pass[0] == '\0') {
 
2237
    pass = NULL;
 
2238
  }
 
2239
 
 
2240
  (void) snprintf(tmp, sizeof(tmp), "%s.tmp", fname);
 
2241
 
 
2242
  // Create the file if does not exist
 
2243
  if ((fp = mg_fopen(fname, "a+")) != NULL) {
 
2244
    (void) fclose(fp);
 
2245
  }
 
2246
 
 
2247
  // Open the given file and temporary file
 
2248
  if ((fp = mg_fopen(fname, "r")) == NULL) {
 
2249
    return 0;
 
2250
  } else if ((fp2 = mg_fopen(tmp, "w+")) == NULL) {
 
2251
    fclose(fp);
 
2252
    return 0;
 
2253
  }
 
2254
 
 
2255
  // Copy the stuff to temporary file
 
2256
  while (fgets(line, sizeof(line), fp) != NULL) {
 
2257
    if (sscanf(line, "%[^:]:%[^:]:%*s", u, d) != 2) {
 
2258
      continue;
 
2259
    }
 
2260
 
 
2261
    if (!strcmp(u, user) && !strcmp(d, domain)) {
 
2262
      found++;
 
2263
      if (pass != NULL) {
 
2264
        mg_md5(ha1, user, ":", domain, ":", pass, NULL);
 
2265
        fprintf(fp2, "%s:%s:%s\n", user, domain, ha1);
 
2266
      }
 
2267
    } else {
 
2268
      (void) fprintf(fp2, "%s", line);
 
2269
    }
 
2270
  }
 
2271
 
 
2272
  // If new user, just add it
 
2273
  if (!found && pass != NULL) {
 
2274
    mg_md5(ha1, user, ":", domain, ":", pass, NULL);
 
2275
    (void) fprintf(fp2, "%s:%s:%s\n", user, domain, ha1);
 
2276
  }
 
2277
 
 
2278
  // Close files
 
2279
  (void) fclose(fp);
 
2280
  (void) fclose(fp2);
 
2281
 
 
2282
  // Put the temp file in place of real file
 
2283
  (void) mg_remove(fname);
 
2284
  (void) mg_rename(tmp, fname);
 
2285
 
 
2286
  return 1;
 
2287
}
 
2288
 
 
2289
struct de {
 
2290
  struct mg_connection *conn;
 
2291
  char *file_name;
 
2292
  struct mgstat st;
 
2293
};
 
2294
 
 
2295
static void url_encode(const char *src, char *dst, size_t dst_len) {
 
2296
  static const char *dont_escape = "._-$,;~()";
 
2297
  static const char *hex = "0123456789abcdef";
 
2298
  const char *end = dst + dst_len - 1;
 
2299
 
 
2300
  for (; *src != '\0' && dst < end; src++, dst++) {
 
2301
    if (isalnum(*(const unsigned char *) src) ||
 
2302
        strchr(dont_escape, * (const unsigned char *) src) != NULL) {
 
2303
      *dst = *src;
 
2304
    } else if (dst + 2 < end) {
 
2305
      dst[0] = '%';
 
2306
      dst[1] = hex[(* (const unsigned char *) src) >> 4];
 
2307
      dst[2] = hex[(* (const unsigned char *) src) & 0xf];
 
2308
      dst += 2;
 
2309
    }
 
2310
  }
 
2311
 
 
2312
  *dst = '\0';
 
2313
}
 
2314
 
 
2315
static void print_dir_entry(struct de *de) {
 
2316
  char size[64], mod[64], href[PATH_MAX];
 
2317
 
 
2318
  if (de->st.is_directory) {
 
2319
    (void) mg_snprintf(de->conn, size, sizeof(size), "%s", "[DIRECTORY]");
 
2320
  } else {
 
2321
     // We use (signed) cast below because MSVC 6 compiler cannot
 
2322
     // convert unsigned __int64 to double. Sigh.
 
2323
    if (de->st.size < 1024) {
 
2324
      (void) mg_snprintf(de->conn, size, sizeof(size),
 
2325
          "%lu", (unsigned long) de->st.size);
 
2326
    } else if (de->st.size < 1024 * 1024) {
 
2327
      (void) mg_snprintf(de->conn, size, sizeof(size),
 
2328
          "%.1fk", (double) de->st.size / 1024.0);
 
2329
    } else if (de->st.size < 1024 * 1024 * 1024) {
 
2330
      (void) mg_snprintf(de->conn, size, sizeof(size),
 
2331
          "%.1fM", (double) de->st.size / 1048576);
 
2332
    } else {
 
2333
      (void) mg_snprintf(de->conn, size, sizeof(size),
 
2334
          "%.1fG", (double) de->st.size / 1073741824);
 
2335
    }
 
2336
  }
 
2337
  (void) strftime(mod, sizeof(mod), "%d-%b-%Y %H:%M", localtime(&de->st.mtime));
 
2338
  url_encode(de->file_name, href, sizeof(href));
 
2339
  de->conn->num_bytes_sent += mg_printf(de->conn,
 
2340
      "<tr><td><a href=\"%s%s%s\">%s%s</a></td>"
 
2341
      "<td>&nbsp;%s</td><td>&nbsp;&nbsp;%s</td></tr>\n",
 
2342
      de->conn->request_info.uri, href, de->st.is_directory ? "/" : "",
 
2343
      de->file_name, de->st.is_directory ? "/" : "", mod, size);
 
2344
}
 
2345
 
 
2346
// This function is called from send_directory() and used for
 
2347
// sorting directory entries by size, or name, or modification time.
 
2348
// On windows, __cdecl specification is needed in case if project is built
 
2349
// with __stdcall convention. qsort always requires __cdels callback.
 
2350
static int WINCDECL compare_dir_entries(const void *p1, const void *p2) {
 
2351
  const struct de *a = (const struct de *) p1, *b = (const struct de *) p2;
 
2352
  const char *query_string = a->conn->request_info.query_string;
 
2353
  int cmp_result = 0;
 
2354
 
 
2355
  if (query_string == NULL) {
 
2356
    query_string = "na";
 
2357
  }
 
2358
 
 
2359
  if (a->st.is_directory && !b->st.is_directory) {
 
2360
    return -1;  // Always put directories on top
 
2361
  } else if (!a->st.is_directory && b->st.is_directory) {
 
2362
    return 1;   // Always put directories on top
 
2363
  } else if (*query_string == 'n') {
 
2364
    cmp_result = strcmp(a->file_name, b->file_name);
 
2365
  } else if (*query_string == 's') {
 
2366
    cmp_result = a->st.size == b->st.size ? 0 :
 
2367
      a->st.size > b->st.size ? 1 : -1;
 
2368
  } else if (*query_string == 'd') {
 
2369
    cmp_result = a->st.mtime == b->st.mtime ? 0 :
 
2370
      a->st.mtime > b->st.mtime ? 1 : -1;
 
2371
  }
 
2372
 
 
2373
  return query_string[1] == 'd' ? -cmp_result : cmp_result;
 
2374
}
 
2375
 
 
2376
static int scan_directory(struct mg_connection *conn, const char *dir,
 
2377
                          void *data, void (*cb)(struct de *, void *)) {
 
2378
  char path[PATH_MAX];
 
2379
  struct dirent *dp;
 
2380
  DIR *dirp;
 
2381
  struct de de;
 
2382
 
 
2383
  if ((dirp = opendir(dir)) == NULL) {
 
2384
    return 0;
 
2385
  } else {
 
2386
    de.conn = conn;
 
2387
 
 
2388
    while ((dp = readdir(dirp)) != NULL) {
 
2389
      // Do not show current dir and passwords file
 
2390
      if (!strcmp(dp->d_name, ".") ||
 
2391
          !strcmp(dp->d_name, "..") ||
 
2392
          !strcmp(dp->d_name, PASSWORDS_FILE_NAME))
 
2393
        continue;
 
2394
 
 
2395
      mg_snprintf(conn, path, sizeof(path), "%s%c%s", dir, DIRSEP, dp->d_name);
 
2396
 
 
2397
      // If we don't memset stat structure to zero, mtime will have
 
2398
      // garbage and strftime() will segfault later on in
 
2399
      // print_dir_entry(). memset is required only if mg_stat()
 
2400
      // fails. For more details, see
 
2401
      // http://code.google.com/p/mongoose/issues/detail?id=79
 
2402
      if (mg_stat(path, &de.st) != 0) {
 
2403
        memset(&de.st, 0, sizeof(de.st));
 
2404
      }
 
2405
      de.file_name = dp->d_name;
 
2406
 
 
2407
      cb(&de, data);
 
2408
    }
 
2409
    (void) closedir(dirp);
 
2410
  }
 
2411
  return 1;
 
2412
}
 
2413
 
 
2414
struct dir_scan_data {
 
2415
  struct de *entries;
 
2416
  int num_entries;
 
2417
  int arr_size;
 
2418
};
 
2419
 
 
2420
static void dir_scan_callback(struct de *de, void *data) {
 
2421
  struct dir_scan_data *dsd = (struct dir_scan_data *) data;
 
2422
 
 
2423
  if (dsd->entries == NULL || dsd->num_entries >= dsd->arr_size) {
 
2424
    dsd->arr_size *= 2;
 
2425
    dsd->entries = (struct de *) realloc(dsd->entries, dsd->arr_size *
 
2426
                                         sizeof(dsd->entries[0]));
 
2427
  }
 
2428
  if (dsd->entries == NULL) {
 
2429
    // TODO(lsm): propagate an error to the caller
 
2430
    dsd->num_entries = 0;
 
2431
  } else {
 
2432
    dsd->entries[dsd->num_entries].file_name = mg_strdup(de->file_name);
 
2433
    dsd->entries[dsd->num_entries].st = de->st;
 
2434
    dsd->entries[dsd->num_entries].conn = de->conn;
 
2435
    dsd->num_entries++;
 
2436
  }
 
2437
}
 
2438
 
 
2439
static void handle_directory_request(struct mg_connection *conn,
 
2440
                                     const char *dir) {
 
2441
  int i, sort_direction;
 
2442
  struct dir_scan_data data = { NULL, 0, 128 };
 
2443
 
 
2444
  if (!scan_directory(conn, dir, &data, dir_scan_callback)) {
 
2445
    send_http_error(conn, 500, "Cannot open directory",
 
2446
                    "Error: opendir(%s): %s", dir, strerror(ERRNO));
 
2447
    return;
 
2448
  }
 
2449
 
 
2450
  sort_direction = conn->request_info.query_string != NULL &&
 
2451
    conn->request_info.query_string[1] == 'd' ? 'a' : 'd';
 
2452
 
 
2453
  conn->must_close = 1;
 
2454
  mg_printf(conn, "%s",
 
2455
            "HTTP/1.1 200 OK\r\n"
 
2456
            "Connection: close\r\n"
 
2457
            "Content-Type: text/html; charset=utf-8\r\n\r\n");
 
2458
 
 
2459
  conn->num_bytes_sent += mg_printf(conn,
 
2460
      "<html><head><title>Index of %s</title>"
 
2461
      "<style>th {text-align: left;}</style></head>"
 
2462
      "<body><h1>Index of %s</h1><pre><table cellpadding=\"0\">"
 
2463
      "<tr><th><a href=\"?n%c\">Name</a></th>"
 
2464
      "<th><a href=\"?d%c\">Modified</a></th>"
 
2465
      "<th><a href=\"?s%c\">Size</a></th></tr>"
 
2466
      "<tr><td colspan=\"3\"><hr></td></tr>",
 
2467
      conn->request_info.uri, conn->request_info.uri,
 
2468
      sort_direction, sort_direction, sort_direction);
 
2469
 
 
2470
  // Print first entry - link to a parent directory
 
2471
  conn->num_bytes_sent += mg_printf(conn,
 
2472
      "<tr><td><a href=\"%s%s\">%s</a></td>"
 
2473
      "<td>&nbsp;%s</td><td>&nbsp;&nbsp;%s</td></tr>\n",
 
2474
      conn->request_info.uri, "..", "Parent directory", "-", "-");
 
2475
 
 
2476
  // Sort and print directory entries
 
2477
  qsort(data.entries, (size_t) data.num_entries, sizeof(data.entries[0]),
 
2478
        compare_dir_entries);
 
2479
  for (i = 0; i < data.num_entries; i++) {
 
2480
    print_dir_entry(&data.entries[i]);
 
2481
    free(data.entries[i].file_name);
 
2482
  }
 
2483
  free(data.entries);
 
2484
 
 
2485
  conn->num_bytes_sent += mg_printf(conn, "%s", "</table></body></html>");
 
2486
  conn->request_info.status_code = 200;
 
2487
}
 
2488
 
 
2489
// Send len bytes from the opened file to the client.
 
2490
static void send_file_data(struct mg_connection *conn, FILE *fp, int64_t len) {
 
2491
  char buf[BUFSIZ];
 
2492
  int to_read, num_read, num_written;
 
2493
 
 
2494
  while (len > 0) {
 
2495
    // Calculate how much to read from the file in the buffer
 
2496
    to_read = sizeof(buf);
 
2497
    if ((int64_t) to_read > len)
 
2498
      to_read = (int) len;
 
2499
 
 
2500
    // Read from file, exit the loop on error
 
2501
    if ((num_read = fread(buf, 1, (size_t)to_read, fp)) == 0)
 
2502
      break;
 
2503
 
 
2504
    // Send read bytes to the client, exit the loop on error
 
2505
    if ((num_written = mg_write(conn, buf, (size_t)num_read)) != num_read)
 
2506
      break;
 
2507
 
 
2508
    // Both read and were successful, adjust counters
 
2509
    conn->num_bytes_sent += num_written;
 
2510
    len -= num_written;
 
2511
  }
 
2512
}
 
2513
 
 
2514
static int parse_range_header(const char *header, int64_t *a, int64_t *b) {
 
2515
  return sscanf(header, "bytes=%" INT64_FMT "-%" INT64_FMT, a, b);
 
2516
}
 
2517
 
 
2518
static void gmt_time_string(char *buf, size_t buf_len, time_t *t) {
 
2519
  strftime(buf, buf_len, "%a, %d %b %Y %H:%M:%S GMT", gmtime(t));
 
2520
}
 
2521
 
 
2522
static void handle_file_request(struct mg_connection *conn, const char *path,
 
2523
                                struct mgstat *stp) {
 
2524
  char date[64], lm[64], etag[64], range[64];
 
2525
  const char *msg = "OK", *hdr;
 
2526
  time_t curtime = time(NULL);
 
2527
  int64_t cl, r1, r2;
 
2528
  struct vec mime_vec;
 
2529
  FILE *fp;
 
2530
  int n;
 
2531
 
 
2532
  get_mime_type(conn->ctx, path, &mime_vec);
 
2533
  cl = stp->size;
 
2534
  conn->request_info.status_code = 200;
 
2535
  range[0] = '\0';
 
2536
 
 
2537
  if ((fp = mg_fopen(path, "rb")) == NULL) {
 
2538
    send_http_error(conn, 500, http_500_error,
 
2539
        "fopen(%s): %s", path, strerror(ERRNO));
 
2540
    return;
 
2541
  }
 
2542
  set_close_on_exec(fileno(fp));
 
2543
 
 
2544
  // If Range: header specified, act accordingly
 
2545
  r1 = r2 = 0;
 
2546
  hdr = mg_get_header(conn, "Range");
 
2547
  if (hdr != NULL && (n = parse_range_header(hdr, &r1, &r2)) > 0) {
 
2548
    conn->request_info.status_code = 206;
 
2549
    (void) fseeko(fp, (off_t) r1, SEEK_SET);
 
2550
    cl = n == 2 ? r2 - r1 + 1: cl - r1;
 
2551
    (void) mg_snprintf(conn, range, sizeof(range),
 
2552
        "Content-Range: bytes "
 
2553
        "%" INT64_FMT "-%"
 
2554
        INT64_FMT "/%" INT64_FMT "\r\n",
 
2555
        r1, r1 + cl - 1, stp->size);
 
2556
    msg = "Partial Content";
 
2557
  }
 
2558
 
 
2559
  // Prepare Etag, Date, Last-Modified headers. Must be in UTC, according to
 
2560
  // http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3
 
2561
  gmt_time_string(date, sizeof(date), &curtime);
 
2562
  gmt_time_string(lm, sizeof(lm), &stp->mtime);
 
2563
  (void) mg_snprintf(conn, etag, sizeof(etag), "%lx.%lx",
 
2564
      (unsigned long) stp->mtime, (unsigned long) stp->size);
 
2565
 
 
2566
  (void) mg_printf(conn,
 
2567
      "HTTP/1.1 %d %s\r\n"
 
2568
      "Date: %s\r\n"
 
2569
      "Last-Modified: %s\r\n"
 
2570
      "Etag: \"%s\"\r\n"
 
2571
      "Content-Type: %.*s\r\n"
 
2572
      "Content-Length: %" INT64_FMT "\r\n"
 
2573
      "Connection: %s\r\n"
 
2574
      "Accept-Ranges: bytes\r\n"
 
2575
      "%s\r\n",
 
2576
      conn->request_info.status_code, msg, date, lm, etag, (int) mime_vec.len,
 
2577
      mime_vec.ptr, cl, suggest_connection_header(conn), range);
 
2578
 
 
2579
  if (strcmp(conn->request_info.request_method, "HEAD") != 0) {
 
2580
    send_file_data(conn, fp, cl);
 
2581
  }
 
2582
  (void) fclose(fp);
 
2583
}
 
2584
 
 
2585
void mg_send_file(struct mg_connection *conn, const char *path) {
 
2586
  struct mgstat st;
 
2587
  if (mg_stat(path, &st) == 0) {
 
2588
    handle_file_request(conn, path, &st);
 
2589
  } else {
 
2590
    send_http_error(conn, 404, "Not Found", "%s", "File not found");
 
2591
  }
 
2592
}
 
2593
 
 
2594
 
 
2595
// Parse HTTP headers from the given buffer, advance buffer to the point
 
2596
// where parsing stopped.
 
2597
static void parse_http_headers(char **buf, struct mg_request_info *ri) {
 
2598
  int i;
 
2599
 
 
2600
  for (i = 0; i < (int) ARRAY_SIZE(ri->http_headers); i++) {
 
2601
    ri->http_headers[i].name = skip_quoted(buf, ":", " ", 0);
 
2602
    ri->http_headers[i].value = skip(buf, "\r\n");
 
2603
    if (ri->http_headers[i].name[0] == '\0')
 
2604
      break;
 
2605
    ri->num_headers = i + 1;
 
2606
  }
 
2607
}
 
2608
 
 
2609
static int is_valid_http_method(const char *method) {
 
2610
  return !strcmp(method, "GET") || !strcmp(method, "POST") ||
 
2611
    !strcmp(method, "HEAD") || !strcmp(method, "CONNECT") ||
 
2612
    !strcmp(method, "PUT") || !strcmp(method, "DELETE") ||
 
2613
    !strcmp(method, "OPTIONS") || !strcmp(method, "PROPFIND");
 
2614
}
 
2615
 
 
2616
// Parse HTTP request, fill in mg_request_info structure.
 
2617
static int parse_http_request(char *buf, struct mg_request_info *ri) {
 
2618
  int status = 0;
 
2619
 
 
2620
  // RFC says that all initial whitespaces should be ingored
 
2621
  while (*buf != '\0' && isspace(* (unsigned char *) buf)) {
 
2622
    buf++;
 
2623
  }
 
2624
 
 
2625
  ri->request_method = skip(&buf, " ");
 
2626
  ri->uri = skip(&buf, " ");
 
2627
  ri->http_version = skip(&buf, "\r\n");
 
2628
 
 
2629
  if (is_valid_http_method(ri->request_method) &&
 
2630
      strncmp(ri->http_version, "HTTP/", 5) == 0) {
 
2631
    ri->http_version += 5;   // Skip "HTTP/"
 
2632
    parse_http_headers(&buf, ri);
 
2633
    status = 1;
 
2634
  }
 
2635
 
 
2636
  return status;
 
2637
}
 
2638
 
 
2639
// Keep reading the input (either opened file descriptor fd, or socket sock,
 
2640
// or SSL descriptor ssl) into buffer buf, until \r\n\r\n appears in the
 
2641
// buffer (which marks the end of HTTP request). Buffer buf may already
 
2642
// have some data. The length of the data is stored in nread.
 
2643
// Upon every read operation, increase nread by the number of bytes read.
 
2644
static int read_request(FILE *fp, SOCKET sock, SSL *ssl, char *buf, int bufsiz,
 
2645
                        int *nread) {
 
2646
  int n, request_len;
 
2647
 
 
2648
  request_len = 0;
 
2649
  while (*nread < bufsiz && request_len == 0) {
 
2650
    n = pull(fp, sock, ssl, buf + *nread, bufsiz - *nread);
 
2651
    if (n <= 0) {
 
2652
      break;
 
2653
    } else {
 
2654
      *nread += n;
 
2655
      request_len = get_request_len(buf, *nread);
 
2656
    }
 
2657
  }
 
2658
 
 
2659
  return request_len;
 
2660
}
 
2661
 
 
2662
// For given directory path, substitute it to valid index file.
 
2663
// Return 0 if index file has been found, -1 if not found.
 
2664
// If the file is found, it's stats is returned in stp.
 
2665
static int substitute_index_file(struct mg_connection *conn, char *path,
 
2666
                                 size_t path_len, struct mgstat *stp) {
 
2667
  const char *list = conn->ctx->config[INDEX_FILES];
 
2668
  struct mgstat st;
 
2669
  struct vec filename_vec;
 
2670
  size_t n = strlen(path);
 
2671
  int found = 0;
 
2672
 
 
2673
  // The 'path' given to us points to the directory. Remove all trailing
 
2674
  // directory separator characters from the end of the path, and
 
2675
  // then append single directory separator character.
 
2676
  while (n > 0 && IS_DIRSEP_CHAR(path[n - 1])) {
 
2677
    n--;
 
2678
  }
 
2679
  path[n] = DIRSEP;
 
2680
 
 
2681
  // Traverse index files list. For each entry, append it to the given
 
2682
  // path and see if the file exists. If it exists, break the loop
 
2683
  while ((list = next_option(list, &filename_vec, NULL)) != NULL) {
 
2684
 
 
2685
    // Ignore too long entries that may overflow path buffer
 
2686
    if (filename_vec.len > path_len - (n + 2))
 
2687
      continue;
 
2688
 
 
2689
    // Prepare full path to the index file
 
2690
    (void) mg_strlcpy(path + n + 1, filename_vec.ptr, filename_vec.len + 1);
 
2691
 
 
2692
    // Does it exist?
 
2693
    if (mg_stat(path, &st) == 0) {
 
2694
      // Yes it does, break the loop
 
2695
      *stp = st;
 
2696
      found = 1;
 
2697
      break;
 
2698
    }
 
2699
  }
 
2700
 
 
2701
  // If no index file exists, restore directory path
 
2702
  if (!found) {
 
2703
    path[n] = '\0';
 
2704
  }
 
2705
 
 
2706
  return found;
 
2707
}
 
2708
 
 
2709
// Return True if we should reply 304 Not Modified.
 
2710
static int is_not_modified(const struct mg_connection *conn,
 
2711
                           const struct mgstat *stp) {
 
2712
  const char *ims = mg_get_header(conn, "If-Modified-Since");
 
2713
  return ims != NULL && stp->mtime <= parse_date_string(ims);
 
2714
}
 
2715
 
 
2716
static int forward_body_data(struct mg_connection *conn, FILE *fp,
 
2717
                             SOCKET sock, SSL *ssl) {
 
2718
  const char *expect, *buffered;
 
2719
  char buf[BUFSIZ];
 
2720
  int to_read, nread, buffered_len, success = 0;
 
2721
 
 
2722
  expect = mg_get_header(conn, "Expect");
 
2723
  assert(fp != NULL);
 
2724
 
 
2725
  if (conn->content_len == -1) {
 
2726
    send_http_error(conn, 411, "Length Required", "");
 
2727
  } else if (expect != NULL && mg_strcasecmp(expect, "100-continue")) {
 
2728
    send_http_error(conn, 417, "Expectation Failed", "");
 
2729
  } else {
 
2730
    if (expect != NULL) {
 
2731
      (void) mg_printf(conn, "%s", "HTTP/1.1 100 Continue\r\n\r\n");
 
2732
    }
 
2733
 
 
2734
    buffered = conn->buf + conn->request_len;
 
2735
    buffered_len = conn->data_len - conn->request_len;
 
2736
    assert(buffered_len >= 0);
 
2737
    assert(conn->consumed_content == 0);
 
2738
 
 
2739
    if (buffered_len > 0) {
 
2740
      if ((int64_t) buffered_len > conn->content_len) {
 
2741
        buffered_len = (int) conn->content_len;
 
2742
      }
 
2743
      push(fp, sock, ssl, buffered, (int64_t) buffered_len);
 
2744
      conn->consumed_content += buffered_len;
 
2745
    }
 
2746
 
 
2747
    while (conn->consumed_content < conn->content_len) {
 
2748
      to_read = sizeof(buf);
 
2749
      if ((int64_t) to_read > conn->content_len - conn->consumed_content) {
 
2750
        to_read = (int) (conn->content_len - conn->consumed_content);
 
2751
      }
 
2752
      nread = pull(NULL, conn->client.sock, conn->ssl, buf, to_read);
 
2753
      if (nread <= 0 || push(fp, sock, ssl, buf, nread) != nread) {
 
2754
        break;
 
2755
      }
 
2756
      conn->consumed_content += nread;
 
2757
    }
 
2758
 
 
2759
    if (conn->consumed_content == conn->content_len) {
 
2760
      success = 1;
 
2761
    }
 
2762
 
 
2763
    // Each error code path in this function must send an error
 
2764
    if (!success) {
 
2765
      send_http_error(conn, 577, http_500_error, "");
 
2766
    }
 
2767
  }
 
2768
 
 
2769
  return success;
 
2770
}
 
2771
 
 
2772
#if !defined(NO_CGI)
 
2773
// This structure helps to create an environment for the spawned CGI program.
 
2774
// Environment is an array of "VARIABLE=VALUE\0" ASCIIZ strings,
 
2775
// last element must be NULL.
 
2776
// However, on Windows there is a requirement that all these VARIABLE=VALUE\0
 
2777
// strings must reside in a contiguous buffer. The end of the buffer is
 
2778
// marked by two '\0' characters.
 
2779
// We satisfy both worlds: we create an envp array (which is vars), all
 
2780
// entries are actually pointers inside buf.
 
2781
struct cgi_env_block {
 
2782
  struct mg_connection *conn;
 
2783
  char buf[CGI_ENVIRONMENT_SIZE]; // Environment buffer
 
2784
  int len; // Space taken
 
2785
  char *vars[MAX_CGI_ENVIR_VARS]; // char **envp
 
2786
  int nvars; // Number of variables
 
2787
};
 
2788
 
 
2789
// Append VARIABLE=VALUE\0 string to the buffer, and add a respective
 
2790
// pointer into the vars array.
 
2791
static char *addenv(struct cgi_env_block *block, const char *fmt, ...) {
 
2792
  int n, space;
 
2793
  char *added;
 
2794
  va_list ap;
 
2795
 
 
2796
  // Calculate how much space is left in the buffer
 
2797
  space = sizeof(block->buf) - block->len - 2;
 
2798
  assert(space >= 0);
 
2799
 
 
2800
  // Make a pointer to the free space int the buffer
 
2801
  added = block->buf + block->len;
 
2802
 
 
2803
  // Copy VARIABLE=VALUE\0 string into the free space
 
2804
  va_start(ap, fmt);
 
2805
  n = mg_vsnprintf(block->conn, added, (size_t) space, fmt, ap);
 
2806
  va_end(ap);
 
2807
 
 
2808
  // Make sure we do not overflow buffer and the envp array
 
2809
  if (n > 0 && n < space &&
 
2810
      block->nvars < (int) ARRAY_SIZE(block->vars) - 2) {
 
2811
    // Append a pointer to the added string into the envp array
 
2812
    block->vars[block->nvars++] = block->buf + block->len;
 
2813
    // Bump up used length counter. Include \0 terminator
 
2814
    block->len += n + 1;
 
2815
  }
 
2816
 
 
2817
  return added;
 
2818
}
 
2819
 
 
2820
static void prepare_cgi_environment(struct mg_connection *conn,
 
2821
                                    const char *prog,
 
2822
                                    struct cgi_env_block *blk) {
 
2823
  const char *s, *slash;
 
2824
  struct vec var_vec;
 
2825
  char *p, src_addr[20];
 
2826
  int  i;
 
2827
 
 
2828
  blk->len = blk->nvars = 0;
 
2829
  blk->conn = conn;
 
2830
  sockaddr_to_string(src_addr, sizeof(src_addr), &conn->client.rsa);
 
2831
 
 
2832
  addenv(blk, "SERVER_NAME=%s", conn->ctx->config[AUTHENTICATION_DOMAIN]);
 
2833
  addenv(blk, "SERVER_ROOT=%s", conn->ctx->config[DOCUMENT_ROOT]);
 
2834
  addenv(blk, "DOCUMENT_ROOT=%s", conn->ctx->config[DOCUMENT_ROOT]);
 
2835
 
 
2836
  // Prepare the environment block
 
2837
  addenv(blk, "%s", "GATEWAY_INTERFACE=CGI/1.1");
 
2838
  addenv(blk, "%s", "SERVER_PROTOCOL=HTTP/1.1");
 
2839
  addenv(blk, "%s", "REDIRECT_STATUS=200"); // For PHP
 
2840
 
 
2841
  // TODO(lsm): fix this for IPv6 case
 
2842
  addenv(blk, "SERVER_PORT=%d", ntohs(conn->client.lsa.sin.sin_port));
 
2843
 
 
2844
  addenv(blk, "REQUEST_METHOD=%s", conn->request_info.request_method);
 
2845
  addenv(blk, "REMOTE_ADDR=%s", src_addr);
 
2846
  addenv(blk, "REMOTE_PORT=%d", conn->request_info.remote_port);
 
2847
  addenv(blk, "REQUEST_URI=%s", conn->request_info.uri);
 
2848
 
 
2849
  // SCRIPT_NAME
 
2850
  assert(conn->request_info.uri[0] == '/');
 
2851
  slash = strrchr(conn->request_info.uri, '/');
 
2852
  if ((s = strrchr(prog, '/')) == NULL)
 
2853
    s = prog;
 
2854
  addenv(blk, "SCRIPT_NAME=%.*s%s", slash - conn->request_info.uri,
 
2855
         conn->request_info.uri, s);
 
2856
 
 
2857
  addenv(blk, "SCRIPT_FILENAME=%s", prog);
 
2858
  addenv(blk, "PATH_TRANSLATED=%s", prog);
 
2859
  addenv(blk, "HTTPS=%s", conn->ssl == NULL ? "off" : "on");
 
2860
 
 
2861
  if ((s = mg_get_header(conn, "Content-Type")) != NULL)
 
2862
    addenv(blk, "CONTENT_TYPE=%s", s);
 
2863
 
 
2864
  if (conn->request_info.query_string != NULL)
 
2865
    addenv(blk, "QUERY_STRING=%s", conn->request_info.query_string);
 
2866
 
 
2867
  if ((s = mg_get_header(conn, "Content-Length")) != NULL)
 
2868
    addenv(blk, "CONTENT_LENGTH=%s", s);
 
2869
 
 
2870
  if ((s = getenv("PATH")) != NULL)
 
2871
    addenv(blk, "PATH=%s", s);
 
2872
 
 
2873
  if (conn->path_info != NULL) {
 
2874
    addenv(blk, "PATH_INFO=%s", conn->path_info);
 
2875
  }
 
2876
 
 
2877
#if defined(_WIN32)
 
2878
  if ((s = getenv("COMSPEC")) != NULL) {
 
2879
    addenv(blk, "COMSPEC=%s", s);
 
2880
  }
 
2881
  if ((s = getenv("SYSTEMROOT")) != NULL) {
 
2882
    addenv(blk, "SYSTEMROOT=%s", s);
 
2883
  }
 
2884
  if ((s = getenv("SystemDrive")) != NULL) {
 
2885
    addenv(blk, "SystemDrive=%s", s);
 
2886
  }
 
2887
#else
 
2888
  if ((s = getenv("LD_LIBRARY_PATH")) != NULL)
 
2889
    addenv(blk, "LD_LIBRARY_PATH=%s", s);
 
2890
#endif // _WIN32
 
2891
 
 
2892
  if ((s = getenv("PERLLIB")) != NULL)
 
2893
    addenv(blk, "PERLLIB=%s", s);
 
2894
 
 
2895
  if (conn->request_info.remote_user != NULL) {
 
2896
    addenv(blk, "REMOTE_USER=%s", conn->request_info.remote_user);
 
2897
    addenv(blk, "%s", "AUTH_TYPE=Digest");
 
2898
  }
 
2899
 
 
2900
  // Add all headers as HTTP_* variables
 
2901
  for (i = 0; i < conn->request_info.num_headers; i++) {
 
2902
    p = addenv(blk, "HTTP_%s=%s",
 
2903
        conn->request_info.http_headers[i].name,
 
2904
        conn->request_info.http_headers[i].value);
 
2905
 
 
2906
    // Convert variable name into uppercase, and change - to _
 
2907
    for (; *p != '=' && *p != '\0'; p++) {
 
2908
      if (*p == '-')
 
2909
        *p = '_';
 
2910
      *p = (char) toupper(* (unsigned char *) p);
 
2911
    }
 
2912
  }
 
2913
 
 
2914
  // Add user-specified variables
 
2915
  s = conn->ctx->config[CGI_ENVIRONMENT];
 
2916
  while ((s = next_option(s, &var_vec, NULL)) != NULL) {
 
2917
    addenv(blk, "%.*s", var_vec.len, var_vec.ptr);
 
2918
  }
 
2919
 
 
2920
  blk->vars[blk->nvars++] = NULL;
 
2921
  blk->buf[blk->len++] = '\0';
 
2922
 
 
2923
  assert(blk->nvars < (int) ARRAY_SIZE(blk->vars));
 
2924
  assert(blk->len > 0);
 
2925
  assert(blk->len < (int) sizeof(blk->buf));
 
2926
}
 
2927
 
 
2928
static void handle_cgi_request(struct mg_connection *conn, const char *prog) {
 
2929
  int headers_len, data_len, i, fd_stdin[2], fd_stdout[2];
 
2930
  const char *status, *status_text;
 
2931
  char buf[BUFSIZ], *pbuf, dir[PATH_MAX], *p;
 
2932
  struct mg_request_info ri;
 
2933
  struct cgi_env_block blk;
 
2934
  FILE *in, *out;
 
2935
  pid_t pid;
 
2936
 
 
2937
  prepare_cgi_environment(conn, prog, &blk);
 
2938
 
 
2939
  // CGI must be executed in its own directory. 'dir' must point to the
 
2940
  // directory containing executable program, 'p' must point to the
 
2941
  // executable program name relative to 'dir'.
 
2942
  (void) mg_snprintf(conn, dir, sizeof(dir), "%s", prog);
 
2943
  if ((p = strrchr(dir, DIRSEP)) != NULL) {
 
2944
    *p++ = '\0';
 
2945
  } else {
 
2946
    dir[0] = '.', dir[1] = '\0';
 
2947
    p = (char *) prog;
 
2948
  }
 
2949
 
 
2950
  pid = (pid_t) -1;
 
2951
  fd_stdin[0] = fd_stdin[1] = fd_stdout[0] = fd_stdout[1] = -1;
 
2952
  in = out = NULL;
 
2953
 
 
2954
  if (pipe(fd_stdin) != 0 || pipe(fd_stdout) != 0) {
 
2955
    send_http_error(conn, 500, http_500_error,
 
2956
        "Cannot create CGI pipe: %s", strerror(ERRNO));
 
2957
    goto done;
 
2958
  } else if ((pid = spawn_process(conn, p, blk.buf, blk.vars,
 
2959
          fd_stdin[0], fd_stdout[1], dir)) == (pid_t) -1) {
 
2960
    goto done;
 
2961
  } else if ((in = fdopen(fd_stdin[1], "wb")) == NULL ||
 
2962
      (out = fdopen(fd_stdout[0], "rb")) == NULL) {
 
2963
    send_http_error(conn, 500, http_500_error,
 
2964
        "fopen: %s", strerror(ERRNO));
 
2965
    goto done;
 
2966
  }
 
2967
 
 
2968
  setbuf(in, NULL);
 
2969
  setbuf(out, NULL);
 
2970
 
 
2971
  // spawn_process() must close those!
 
2972
  // If we don't mark them as closed, close() attempt before
 
2973
  // return from this function throws an exception on Windows.
 
2974
  // Windows does not like when closed descriptor is closed again.
 
2975
  fd_stdin[0] = fd_stdout[1] = -1;
 
2976
 
 
2977
  // Send POST data to the CGI process if needed
 
2978
  if (!strcmp(conn->request_info.request_method, "POST") &&
 
2979
      !forward_body_data(conn, in, INVALID_SOCKET, NULL)) {
 
2980
    goto done;
 
2981
  }
 
2982
 
 
2983
  // Now read CGI reply into a buffer. We need to set correct
 
2984
  // status code, thus we need to see all HTTP headers first.
 
2985
  // Do not send anything back to client, until we buffer in all
 
2986
  // HTTP headers.
 
2987
  data_len = 0;
 
2988
  headers_len = read_request(out, INVALID_SOCKET, NULL,
 
2989
      buf, sizeof(buf), &data_len);
 
2990
  if (headers_len <= 0) {
 
2991
    send_http_error(conn, 500, http_500_error,
 
2992
                    "CGI program sent malformed HTTP headers: [%.*s]",
 
2993
                    data_len, buf);
 
2994
    goto done;
 
2995
  }
 
2996
  pbuf = buf;
 
2997
  buf[headers_len - 1] = '\0';
 
2998
  parse_http_headers(&pbuf, &ri);
 
2999
 
 
3000
  // Make up and send the status line
 
3001
  status_text = "OK";
 
3002
  if ((status = get_header(&ri, "Status")) != NULL) {
 
3003
    conn->request_info.status_code = atoi(status);
 
3004
    status_text = status;
 
3005
    while (isdigit(* (unsigned char *) status_text) || *status_text == ' ') {
 
3006
      status_text++;
 
3007
    }
 
3008
  } else if (get_header(&ri, "Location") != NULL) {
 
3009
    conn->request_info.status_code = 302;
 
3010
  } else {
 
3011
    conn->request_info.status_code = 200;
 
3012
  }
 
3013
  if (get_header(&ri, "Connection") != NULL &&
 
3014
      !mg_strcasecmp(get_header(&ri, "Connection"), "keep-alive")) {
 
3015
    conn->must_close = 1;
 
3016
  }
 
3017
  (void) mg_printf(conn, "HTTP/1.1 %d %s\r\n", conn->request_info.status_code,
 
3018
                   status_text);
 
3019
 
 
3020
  // Send headers
 
3021
  for (i = 0; i < ri.num_headers; i++) {
 
3022
    mg_printf(conn, "%s: %s\r\n",
 
3023
              ri.http_headers[i].name, ri.http_headers[i].value);
 
3024
  }
 
3025
  (void) mg_write(conn, "\r\n", 2);
 
3026
 
 
3027
  // Send chunk of data that may be read after the headers
 
3028
  conn->num_bytes_sent += mg_write(conn, buf + headers_len,
 
3029
                                   (size_t)(data_len - headers_len));
 
3030
 
 
3031
  // Read the rest of CGI output and send to the client
 
3032
  send_file_data(conn, out, INT64_MAX);
 
3033
 
 
3034
done:
 
3035
  if (pid != (pid_t) -1) {
 
3036
    kill(pid, SIGKILL);
 
3037
  }
 
3038
  if (fd_stdin[0] != -1) {
 
3039
    (void) close(fd_stdin[0]);
 
3040
  }
 
3041
  if (fd_stdout[1] != -1) {
 
3042
    (void) close(fd_stdout[1]);
 
3043
  }
 
3044
 
 
3045
  if (in != NULL) {
 
3046
    (void) fclose(in);
 
3047
  } else if (fd_stdin[1] != -1) {
 
3048
    (void) close(fd_stdin[1]);
 
3049
  }
 
3050
 
 
3051
  if (out != NULL) {
 
3052
    (void) fclose(out);
 
3053
  } else if (fd_stdout[0] != -1) {
 
3054
    (void) close(fd_stdout[0]);
 
3055
  }
 
3056
}
 
3057
#endif // !NO_CGI
 
3058
 
 
3059
// For a given PUT path, create all intermediate subdirectories
 
3060
// for given path. Return 0 if the path itself is a directory,
 
3061
// or -1 on error, 1 if OK.
 
3062
static int put_dir(const char *path) {
 
3063
  char buf[PATH_MAX];
 
3064
  const char *s, *p;
 
3065
  struct mgstat st;
 
3066
  int len, res = 1;
 
3067
 
 
3068
  for (s = p = path + 2; (p = strchr(s, DIRSEP)) != NULL; s = ++p) {
 
3069
    len = p - path;
 
3070
    if (len >= (int) sizeof(buf)) {
 
3071
      res = -1;
 
3072
      break;
 
3073
    }
 
3074
    memcpy(buf, path, len);
 
3075
    buf[len] = '\0';
 
3076
 
 
3077
    // Try to create intermediate directory
 
3078
    DEBUG_TRACE(("mkdir(%s)", buf));
 
3079
    if (mg_stat(buf, &st) == -1 && mg_mkdir(buf, 0755) != 0) {
 
3080
      res = -1;
 
3081
      break;
 
3082
    }
 
3083
 
 
3084
    // Is path itself a directory?
 
3085
    if (p[1] == '\0') {
 
3086
      res = 0;
 
3087
    }
 
3088
  }
 
3089
 
 
3090
  return res;
 
3091
}
 
3092
 
 
3093
static void put_file(struct mg_connection *conn, const char *path) {
 
3094
  struct mgstat st;
 
3095
  const char *range;
 
3096
  int64_t r1, r2;
 
3097
  FILE *fp;
 
3098
  int rc;
 
3099
 
 
3100
  conn->request_info.status_code = mg_stat(path, &st) == 0 ? 200 : 201;
 
3101
 
 
3102
  if ((rc = put_dir(path)) == 0) {
 
3103
    mg_printf(conn, "HTTP/1.1 %d OK\r\n\r\n", conn->request_info.status_code);
 
3104
  } else if (rc == -1) {
 
3105
    send_http_error(conn, 500, http_500_error,
 
3106
        "put_dir(%s): %s", path, strerror(ERRNO));
 
3107
  } else if ((fp = mg_fopen(path, "wb+")) == NULL) {
 
3108
    send_http_error(conn, 500, http_500_error,
 
3109
        "fopen(%s): %s", path, strerror(ERRNO));
 
3110
  } else {
 
3111
    set_close_on_exec(fileno(fp));
 
3112
    range = mg_get_header(conn, "Content-Range");
 
3113
    r1 = r2 = 0;
 
3114
    if (range != NULL && parse_range_header(range, &r1, &r2) > 0) {
 
3115
      conn->request_info.status_code = 206;
 
3116
      // TODO(lsm): handle seek error
 
3117
      (void) fseeko(fp, (off_t) r1, SEEK_SET);
 
3118
    }
 
3119
    if (forward_body_data(conn, fp, INVALID_SOCKET, NULL))
 
3120
      (void) mg_printf(conn, "HTTP/1.1 %d OK\r\n\r\n",
 
3121
          conn->request_info.status_code);
 
3122
    (void) fclose(fp);
 
3123
  }
 
3124
}
 
3125
 
 
3126
static void send_ssi_file(struct mg_connection *, const char *, FILE *, int);
 
3127
 
 
3128
static void do_ssi_include(struct mg_connection *conn, const char *ssi,
 
3129
                           char *tag, int include_level) {
 
3130
  char file_name[BUFSIZ], path[PATH_MAX], *p;
 
3131
  FILE *fp;
 
3132
 
 
3133
  // sscanf() is safe here, since send_ssi_file() also uses buffer
 
3134
  // of size BUFSIZ to get the tag. So strlen(tag) is always < BUFSIZ.
 
3135
  if (sscanf(tag, " virtual=\"%[^\"]\"", file_name) == 1) {
 
3136
    // File name is relative to the webserver root
 
3137
    (void) mg_snprintf(conn, path, sizeof(path), "%s%c%s",
 
3138
        conn->ctx->config[DOCUMENT_ROOT], DIRSEP, file_name);
 
3139
  } else if (sscanf(tag, " file=\"%[^\"]\"", file_name) == 1) {
 
3140
    // File name is relative to the webserver working directory
 
3141
    // or it is absolute system path
 
3142
    (void) mg_snprintf(conn, path, sizeof(path), "%s", file_name);
 
3143
  } else if (sscanf(tag, " \"%[^\"]\"", file_name) == 1) {
 
3144
    // File name is relative to the currect document
 
3145
    (void) mg_snprintf(conn, path, sizeof(path), "%s", ssi);
 
3146
    if ((p = strrchr(path, DIRSEP)) != NULL) {
 
3147
      p[1] = '\0';
 
3148
    }
 
3149
    (void) mg_snprintf(conn, path + strlen(path),
 
3150
        sizeof(path) - strlen(path), "%s", file_name);
 
3151
  } else {
 
3152
    cry(conn, "Bad SSI #include: [%s]", tag);
 
3153
    return;
 
3154
  }
 
3155
 
 
3156
  if ((fp = mg_fopen(path, "rb")) == NULL) {
 
3157
    cry(conn, "Cannot open SSI #include: [%s]: fopen(%s): %s",
 
3158
        tag, path, strerror(ERRNO));
 
3159
  } else {
 
3160
    set_close_on_exec(fileno(fp));
 
3161
    if (match_prefix(conn->ctx->config[SSI_EXTENSIONS],
 
3162
                     strlen(conn->ctx->config[SSI_EXTENSIONS]), path) > 0) {
 
3163
      send_ssi_file(conn, path, fp, include_level + 1);
 
3164
    } else {
 
3165
      send_file_data(conn, fp, INT64_MAX);
 
3166
    }
 
3167
    (void) fclose(fp);
 
3168
  }
 
3169
}
 
3170
 
 
3171
#if !defined(NO_POPEN)
 
3172
static void do_ssi_exec(struct mg_connection *conn, char *tag) {
 
3173
  char cmd[BUFSIZ];
 
3174
  FILE *fp;
 
3175
 
 
3176
  if (sscanf(tag, " \"%[^\"]\"", cmd) != 1) {
 
3177
    cry(conn, "Bad SSI #exec: [%s]", tag);
 
3178
  } else if ((fp = popen(cmd, "r")) == NULL) {
 
3179
    cry(conn, "Cannot SSI #exec: [%s]: %s", cmd, strerror(ERRNO));
 
3180
  } else {
 
3181
    send_file_data(conn, fp, INT64_MAX);
 
3182
    (void) pclose(fp);
 
3183
  }
 
3184
}
 
3185
#endif // !NO_POPEN
 
3186
 
 
3187
static void send_ssi_file(struct mg_connection *conn, const char *path,
 
3188
                          FILE *fp, int include_level) {
 
3189
  char buf[BUFSIZ];
 
3190
  int ch, len, in_ssi_tag;
 
3191
 
 
3192
  if (include_level > 10) {
 
3193
    cry(conn, "SSI #include level is too deep (%s)", path);
 
3194
    return;
 
3195
  }
 
3196
 
 
3197
  in_ssi_tag = 0;
 
3198
  len = 0;
 
3199
 
 
3200
  while ((ch = fgetc(fp)) != EOF) {
 
3201
    if (in_ssi_tag && ch == '>') {
 
3202
      in_ssi_tag = 0;
 
3203
      buf[len++] = (char) ch;
 
3204
      buf[len] = '\0';
 
3205
      assert(len <= (int) sizeof(buf));
 
3206
      if (len < 6 || memcmp(buf, "<!--#", 5) != 0) {
 
3207
        // Not an SSI tag, pass it
 
3208
        (void) mg_write(conn, buf, (size_t)len);
 
3209
      } else {
 
3210
        if (!memcmp(buf + 5, "include", 7)) {
 
3211
          do_ssi_include(conn, path, buf + 12, include_level);
 
3212
#if !defined(NO_POPEN)
 
3213
        } else if (!memcmp(buf + 5, "exec", 4)) {
 
3214
          do_ssi_exec(conn, buf + 9);
 
3215
#endif // !NO_POPEN
 
3216
        } else {
 
3217
          cry(conn, "%s: unknown SSI " "command: \"%s\"", path, buf);
 
3218
        }
 
3219
      }
 
3220
      len = 0;
 
3221
    } else if (in_ssi_tag) {
 
3222
      if (len == 5 && memcmp(buf, "<!--#", 5) != 0) {
 
3223
        // Not an SSI tag
 
3224
        in_ssi_tag = 0;
 
3225
      } else if (len == (int) sizeof(buf) - 2) {
 
3226
        cry(conn, "%s: SSI tag is too large", path);
 
3227
        len = 0;
 
3228
      }
 
3229
      buf[len++] = ch & 0xff;
 
3230
    } else if (ch == '<') {
 
3231
      in_ssi_tag = 1;
 
3232
      if (len > 0) {
 
3233
        (void) mg_write(conn, buf, (size_t)len);
 
3234
      }
 
3235
      len = 0;
 
3236
      buf[len++] = ch & 0xff;
 
3237
    } else {
 
3238
      buf[len++] = ch & 0xff;
 
3239
      if (len == (int) sizeof(buf)) {
 
3240
        (void) mg_write(conn, buf, (size_t)len);
 
3241
        len = 0;
 
3242
      }
 
3243
    }
 
3244
  }
 
3245
 
 
3246
  // Send the rest of buffered data
 
3247
  if (len > 0) {
 
3248
    (void) mg_write(conn, buf, (size_t)len);
 
3249
  }
 
3250
}
 
3251
 
 
3252
static void handle_ssi_file_request(struct mg_connection *conn,
 
3253
                                    const char *path) {
 
3254
  FILE *fp;
 
3255
 
 
3256
  if ((fp = mg_fopen(path, "rb")) == NULL) {
 
3257
    send_http_error(conn, 500, http_500_error, "fopen(%s): %s", path,
 
3258
                    strerror(ERRNO));
 
3259
  } else {
 
3260
    conn->must_close = 1;
 
3261
    set_close_on_exec(fileno(fp));
 
3262
    mg_printf(conn, "HTTP/1.1 200 OK\r\n"
 
3263
              "Content-Type: text/html\r\nConnection: %s\r\n\r\n",
 
3264
              suggest_connection_header(conn));
 
3265
    send_ssi_file(conn, path, fp, 0);
 
3266
    (void) fclose(fp);
 
3267
  }
 
3268
}
 
3269
 
 
3270
static void send_options(struct mg_connection *conn) {
 
3271
  conn->request_info.status_code = 200;
 
3272
 
 
3273
  (void) mg_printf(conn,
 
3274
      "HTTP/1.1 200 OK\r\n"
 
3275
      "Allow: GET, POST, HEAD, CONNECT, PUT, DELETE, OPTIONS\r\n"
 
3276
      "DAV: 1\r\n\r\n");
 
3277
}
 
3278
 
 
3279
// Writes PROPFIND properties for a collection element
 
3280
static void print_props(struct mg_connection *conn, const char* uri,
 
3281
                        struct mgstat* st) {
 
3282
  char mtime[64];
 
3283
  gmt_time_string(mtime, sizeof(mtime), &st->mtime);
 
3284
  conn->num_bytes_sent += mg_printf(conn,
 
3285
      "<d:response>"
 
3286
       "<d:href>%s</d:href>"
 
3287
       "<d:propstat>"
 
3288
        "<d:prop>"
 
3289
         "<d:resourcetype>%s</d:resourcetype>"
 
3290
         "<d:getcontentlength>%" INT64_FMT "</d:getcontentlength>"
 
3291
         "<d:getlastmodified>%s</d:getlastmodified>"
 
3292
        "</d:prop>"
 
3293
        "<d:status>HTTP/1.1 200 OK</d:status>"
 
3294
       "</d:propstat>"
 
3295
      "</d:response>\n",
 
3296
      uri,
 
3297
      st->is_directory ? "<d:collection/>" : "",
 
3298
      st->size,
 
3299
      mtime);
 
3300
}
 
3301
 
 
3302
static void print_dav_dir_entry(struct de *de, void *data) {
 
3303
  char href[PATH_MAX];
 
3304
  struct mg_connection *conn = (struct mg_connection *) data;
 
3305
  mg_snprintf(conn, href, sizeof(href), "%s%s",
 
3306
              conn->request_info.uri, de->file_name);
 
3307
  print_props(conn, href, &de->st);
 
3308
}
 
3309
 
 
3310
static void handle_propfind(struct mg_connection *conn, const char* path,
 
3311
                            struct mgstat* st) {
 
3312
  const char *depth = mg_get_header(conn, "Depth");
 
3313
 
 
3314
  conn->must_close = 1;
 
3315
  conn->request_info.status_code = 207;
 
3316
  mg_printf(conn, "HTTP/1.1 207 Multi-Status\r\n"
 
3317
            "Connection: close\r\n"
 
3318
            "Content-Type: text/xml; charset=utf-8\r\n\r\n");
 
3319
 
 
3320
  conn->num_bytes_sent += mg_printf(conn,
 
3321
      "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
 
3322
      "<d:multistatus xmlns:d='DAV:'>\n");
 
3323
 
 
3324
  // Print properties for the requested resource itself
 
3325
  print_props(conn, conn->request_info.uri, st);
 
3326
 
 
3327
  // If it is a directory, print directory entries too if Depth is not 0
 
3328
  if (st->is_directory &&
 
3329
      !mg_strcasecmp(conn->ctx->config[ENABLE_DIRECTORY_LISTING], "yes") &&
 
3330
      (depth == NULL || strcmp(depth, "0") != 0)) {
 
3331
    scan_directory(conn, path, conn, &print_dav_dir_entry);
 
3332
  }
 
3333
 
 
3334
  conn->num_bytes_sent += mg_printf(conn, "%s\n", "</d:multistatus>");
 
3335
}
 
3336
 
 
3337
// This is the heart of the Mongoose's logic.
 
3338
// This function is called when the request is read, parsed and validated,
 
3339
// and Mongoose must decide what action to take: serve a file, or
 
3340
// a directory, or call embedded function, etcetera.
 
3341
static void handle_request(struct mg_connection *conn) {
 
3342
  struct mg_request_info *ri = &conn->request_info;
 
3343
  char path[PATH_MAX];
 
3344
  int stat_result, uri_len;
 
3345
  struct mgstat st;
 
3346
 
 
3347
  if ((conn->request_info.query_string = strchr(ri->uri, '?')) != NULL) {
 
3348
    * conn->request_info.query_string++ = '\0';
 
3349
  }
 
3350
  uri_len = strlen(ri->uri);
 
3351
  url_decode(ri->uri, (size_t)uri_len, ri->uri, (size_t)(uri_len + 1), 0);
 
3352
  remove_double_dots_and_double_slashes(ri->uri);
 
3353
  stat_result = convert_uri_to_file_name(conn, path, sizeof(path), &st);
 
3354
 
 
3355
  DEBUG_TRACE(("%s", ri->uri));
 
3356
  if (!check_authorization(conn, path)) {
 
3357
    send_authorization_request(conn);
 
3358
  } else if (call_user(conn, MG_NEW_REQUEST) != NULL) {
 
3359
    // Do nothing, callback has served the request
 
3360
  } else if (!strcmp(ri->request_method, "OPTIONS")) {
 
3361
    send_options(conn);
 
3362
  } else if (strstr(path, PASSWORDS_FILE_NAME)) {
 
3363
    // Do not allow to view passwords files
 
3364
    send_http_error(conn, 403, "Forbidden", "Access Forbidden");
 
3365
  } else if (conn->ctx->config[DOCUMENT_ROOT] == NULL) {
 
3366
    send_http_error(conn, 404, "Not Found", "Not Found");
 
3367
  } else if ((!strcmp(ri->request_method, "PUT") ||
 
3368
        !strcmp(ri->request_method, "DELETE")) &&
 
3369
      (conn->ctx->config[PUT_DELETE_PASSWORDS_FILE] == NULL ||
 
3370
       !is_authorized_for_put(conn))) {
 
3371
    send_authorization_request(conn);
 
3372
  } else if (!strcmp(ri->request_method, "PUT")) {
 
3373
    put_file(conn, path);
 
3374
  } else if (!strcmp(ri->request_method, "DELETE")) {
 
3375
    if (mg_remove(path) == 0) {
 
3376
      send_http_error(conn, 200, "OK", "");
 
3377
    } else {
 
3378
      send_http_error(conn, 500, http_500_error, "remove(%s): %s", path,
 
3379
                      strerror(ERRNO));
 
3380
    }
 
3381
  } else if (stat_result != 0) {
 
3382
    send_http_error(conn, 404, "Not Found", "%s", "File not found");
 
3383
  } else if (st.is_directory && ri->uri[uri_len - 1] != '/') {
 
3384
    (void) mg_printf(conn,
 
3385
        "HTTP/1.1 301 Moved Permanently\r\n"
 
3386
        "Location: %s/\r\n\r\n", ri->uri);
 
3387
  } else if (!strcmp(ri->request_method, "PROPFIND")) {
 
3388
    handle_propfind(conn, path, &st);
 
3389
  } else if (st.is_directory &&
 
3390
             !substitute_index_file(conn, path, sizeof(path), &st)) {
 
3391
    if (!mg_strcasecmp(conn->ctx->config[ENABLE_DIRECTORY_LISTING], "yes")) {
 
3392
      handle_directory_request(conn, path);
 
3393
    } else {
 
3394
      send_http_error(conn, 403, "Directory Listing Denied",
 
3395
          "Directory listing denied");
 
3396
    }
 
3397
#if !defined(NO_CGI)
 
3398
  } else if (match_prefix(conn->ctx->config[CGI_EXTENSIONS],
 
3399
                          strlen(conn->ctx->config[CGI_EXTENSIONS]),
 
3400
                          path) > 0) {
 
3401
    if (strcmp(ri->request_method, "POST") &&
 
3402
        strcmp(ri->request_method, "GET")) {
 
3403
      send_http_error(conn, 501, "Not Implemented",
 
3404
                      "Method %s is not implemented", ri->request_method);
 
3405
    } else {
 
3406
      handle_cgi_request(conn, path);
 
3407
    }
 
3408
#endif // !NO_CGI
 
3409
  } else if (match_prefix(conn->ctx->config[SSI_EXTENSIONS],
 
3410
                          strlen(conn->ctx->config[SSI_EXTENSIONS]),
 
3411
                          path) > 0) {
 
3412
    handle_ssi_file_request(conn, path);
 
3413
  } else if (is_not_modified(conn, &st)) {
 
3414
    send_http_error(conn, 304, "Not Modified", "");
 
3415
  } else {
 
3416
    handle_file_request(conn, path, &st);
 
3417
  }
 
3418
}
 
3419
 
 
3420
static void close_all_listening_sockets(struct mg_context *ctx) {
 
3421
  struct socket *sp, *tmp;
 
3422
  for (sp = ctx->listening_sockets; sp != NULL; sp = tmp) {
 
3423
    tmp = sp->next;
 
3424
    (void) closesocket(sp->sock);
 
3425
    free(sp);
 
3426
  }
 
3427
}
 
3428
 
 
3429
// Valid listening port specification is: [ip_address:]port[s]
 
3430
// Examples: 80, 443s, 127.0.0.1:3128,1.2.3.4:8080s
 
3431
// TODO(lsm): add parsing of the IPv6 address
 
3432
static int parse_port_string(const struct vec *vec, struct socket *so) {
 
3433
  int a, b, c, d, port, len;
 
3434
 
 
3435
  // MacOS needs that. If we do not zero it, subsequent bind() will fail.
 
3436
  // Also, all-zeroes in the socket address means binding to all addresses
 
3437
  // for both IPv4 and IPv6 (INADDR_ANY and IN6ADDR_ANY_INIT).
 
3438
  memset(so, 0, sizeof(*so));
 
3439
 
 
3440
  if (sscanf(vec->ptr, "%d.%d.%d.%d:%d%n", &a, &b, &c, &d, &port, &len) == 5) {
 
3441
    // Bind to a specific IPv4 address
 
3442
    so->lsa.sin.sin_addr.s_addr = htonl((a << 24) | (b << 16) | (c << 8) | d);
 
3443
  } else if (sscanf(vec->ptr, "%d%n", &port, &len) != 1 ||
 
3444
             len <= 0 ||
 
3445
             len > (int) vec->len ||
 
3446
             (vec->ptr[len] && vec->ptr[len] != 's' && vec->ptr[len] != ',')) {
 
3447
    return 0;
 
3448
  }
 
3449
 
 
3450
  so->is_ssl = vec->ptr[len] == 's';
 
3451
#if defined(USE_IPV6)
 
3452
  so->lsa.sin6.sin6_family = AF_INET6;
 
3453
  so->lsa.sin6.sin6_port = htons((uint16_t) port);
 
3454
#else
 
3455
  so->lsa.sin.sin_family = AF_INET;
 
3456
  so->lsa.sin.sin_port = htons((uint16_t) port);
 
3457
#endif
 
3458
 
 
3459
  return 1;
 
3460
}
 
3461
 
 
3462
static int set_ports_option(struct mg_context *ctx) {
 
3463
  const char *list = ctx->config[LISTENING_PORTS];
 
3464
  int on = 1, success = 1;
 
3465
  SOCKET sock;
 
3466
  struct vec vec;
 
3467
  struct socket so, *listener;
 
3468
 
 
3469
  while (success && (list = next_option(list, &vec, NULL)) != NULL) {
 
3470
    if (!parse_port_string(&vec, &so)) {
 
3471
      cry(fc(ctx), "%s: %.*s: invalid port spec. Expecting list of: %s",
 
3472
          __func__, vec.len, vec.ptr, "[IP_ADDRESS:]PORT[s|p]");
 
3473
      success = 0;
 
3474
    } else if (so.is_ssl && ctx->ssl_ctx == NULL) {
 
3475
      cry(fc(ctx), "Cannot add SSL socket, is -ssl_certificate option set?");
 
3476
      success = 0;
 
3477
    } else if ((sock = socket(so.lsa.sa.sa_family, SOCK_STREAM, 6)) ==
 
3478
               INVALID_SOCKET ||
 
3479
#if !defined(_WIN32)
 
3480
               // On Windows, SO_REUSEADDR is recommended only for
 
3481
               // broadcast UDP sockets
 
3482
               setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on,
 
3483
                          sizeof(on)) != 0 ||
 
3484
#endif // !_WIN32
 
3485
               // Set TCP keep-alive. This is needed because if HTTP-level
 
3486
               // keep-alive is enabled, and client resets the connection,
 
3487
               // server won't get TCP FIN or RST and will keep the connection
 
3488
               // open forever. With TCP keep-alive, next keep-alive
 
3489
               // handshake will figure out that the client is down and
 
3490
               // will close the server end.
 
3491
               // Thanks to Igor Klopov who suggested the patch.
 
3492
               setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (void *) &on,
 
3493
                          sizeof(on)) != 0 ||
 
3494
               bind(sock, &so.lsa.sa, sizeof(so.lsa)) != 0 ||
 
3495
               listen(sock, 100) != 0) {
 
3496
      closesocket(sock);
 
3497
      cry(fc(ctx), "%s: cannot bind to %.*s: %s", __func__,
 
3498
          vec.len, vec.ptr, strerror(ERRNO));
 
3499
      success = 0;
 
3500
    } else if ((listener = (struct socket *)
 
3501
                calloc(1, sizeof(*listener))) == NULL) {
 
3502
      closesocket(sock);
 
3503
      cry(fc(ctx), "%s: %s", __func__, strerror(ERRNO));
 
3504
      success = 0;
 
3505
    } else {
 
3506
      *listener = so;
 
3507
      listener->sock = sock;
 
3508
      set_close_on_exec(listener->sock);
 
3509
      listener->next = ctx->listening_sockets;
 
3510
      ctx->listening_sockets = listener;
 
3511
    }
 
3512
  }
 
3513
 
 
3514
  if (!success) {
 
3515
    close_all_listening_sockets(ctx);
 
3516
  }
 
3517
  return success;
 
3518
}
 
3519
 
 
3520
static void log_header(const struct mg_connection *conn, const char *header,
 
3521
                       FILE *fp) {
 
3522
  const char *header_value;
 
3523
 
 
3524
  if ((header_value = mg_get_header(conn, header)) == NULL) {
 
3525
    (void) fprintf(fp, "%s", " -");
 
3526
  } else {
 
3527
    (void) fprintf(fp, " \"%s\"", header_value);
 
3528
  }
 
3529
}
 
3530
 
 
3531
static void log_access(const struct mg_connection *conn) {
 
3532
  const struct mg_request_info *ri;
 
3533
  FILE *fp;
 
3534
  char date[64], src_addr[20];
 
3535
 
 
3536
  fp = conn->ctx->config[ACCESS_LOG_FILE] == NULL ?  NULL :
 
3537
    mg_fopen(conn->ctx->config[ACCESS_LOG_FILE], "a+");
 
3538
 
 
3539
  if (fp == NULL)
 
3540
    return;
 
3541
 
 
3542
  strftime(date, sizeof(date), "%d/%b/%Y:%H:%M:%S %z",
 
3543
           localtime(&conn->birth_time));
 
3544
 
 
3545
  ri = &conn->request_info;
 
3546
  flockfile(fp);
 
3547
 
 
3548
  sockaddr_to_string(src_addr, sizeof(src_addr), &conn->client.rsa);
 
3549
  fprintf(fp, "%s - %s [%s] \"%s %s HTTP/%s\" %d %" INT64_FMT,
 
3550
          src_addr, ri->remote_user == NULL ? "-" : ri->remote_user, date,
 
3551
          ri->request_method ? ri->request_method : "-",
 
3552
          ri->uri ? ri->uri : "-", ri->http_version,
 
3553
          conn->request_info.status_code, conn->num_bytes_sent);
 
3554
  log_header(conn, "Referer", fp);
 
3555
  log_header(conn, "User-Agent", fp);
 
3556
  fputc('\n', fp);
 
3557
  fflush(fp);
 
3558
 
 
3559
  funlockfile(fp);
 
3560
  fclose(fp);
 
3561
}
 
3562
 
 
3563
static int isbyte(int n) {
 
3564
  return n >= 0 && n <= 255;
 
3565
}
 
3566
 
 
3567
// Verify given socket address against the ACL.
 
3568
// Return -1 if ACL is malformed, 0 if address is disallowed, 1 if allowed.
 
3569
static int check_acl(struct mg_context *ctx, const union usa *usa) {
 
3570
  int a, b, c, d, n, mask, allowed;
 
3571
  char flag;
 
3572
  uint32_t acl_subnet, acl_mask, remote_ip;
 
3573
  struct vec vec;
 
3574
  const char *list = ctx->config[ACCESS_CONTROL_LIST];
 
3575
 
 
3576
  if (list == NULL) {
 
3577
    return 1;
 
3578
  }
 
3579
 
 
3580
  (void) memcpy(&remote_ip, &usa->sin.sin_addr, sizeof(remote_ip));
 
3581
 
 
3582
  // If any ACL is set, deny by default
 
3583
  allowed = '-';
 
3584
 
 
3585
  while ((list = next_option(list, &vec, NULL)) != NULL) {
 
3586
    mask = 32;
 
3587
 
 
3588
    if (sscanf(vec.ptr, "%c%d.%d.%d.%d%n", &flag, &a, &b, &c, &d, &n) != 5) {
 
3589
      cry(fc(ctx), "%s: subnet must be [+|-]x.x.x.x[/x]", __func__);
 
3590
      return -1;
 
3591
    } else if (flag != '+' && flag != '-') {
 
3592
      cry(fc(ctx), "%s: flag must be + or -: [%s]", __func__, vec.ptr);
 
3593
      return -1;
 
3594
    } else if (!isbyte(a)||!isbyte(b)||!isbyte(c)||!isbyte(d)) {
 
3595
      cry(fc(ctx), "%s: bad ip address: [%s]", __func__, vec.ptr);
 
3596
      return -1;
 
3597
    } else if (sscanf(vec.ptr + n, "/%d", &mask) == 0) {
 
3598
      // Do nothing, no mask specified
 
3599
    } else if (mask < 0 || mask > 32) {
 
3600
      cry(fc(ctx), "%s: bad subnet mask: %d [%s]", __func__, n, vec.ptr);
 
3601
      return -1;
 
3602
    }
 
3603
 
 
3604
    acl_subnet = (a << 24) | (b << 16) | (c << 8) | d;
 
3605
    acl_mask = mask ? 0xffffffffU << (32 - mask) : 0;
 
3606
 
 
3607
    if (acl_subnet == (ntohl(remote_ip) & acl_mask)) {
 
3608
      allowed = flag;
 
3609
    }
 
3610
  }
 
3611
 
 
3612
  return allowed == '+';
 
3613
}
 
3614
 
 
3615
static void add_to_set(SOCKET fd, fd_set *set, int *max_fd) {
 
3616
  FD_SET(fd, set);
 
3617
  if (fd > (SOCKET) *max_fd) {
 
3618
    *max_fd = (int) fd;
 
3619
  }
 
3620
}
 
3621
 
 
3622
#if !defined(_WIN32)
 
3623
static int set_uid_option(struct mg_context *ctx) {
 
3624
  struct passwd *pw;
 
3625
  const char *uid = ctx->config[RUN_AS_USER];
 
3626
  int success = 0;
 
3627
 
 
3628
  if (uid == NULL) {
 
3629
    success = 1;
 
3630
  } else {
 
3631
    if ((pw = getpwnam(uid)) == NULL) {
 
3632
      cry(fc(ctx), "%s: unknown user [%s]", __func__, uid);
 
3633
    } else if (setgid(pw->pw_gid) == -1) {
 
3634
      cry(fc(ctx), "%s: setgid(%s): %s", __func__, uid, strerror(errno));
 
3635
    } else if (setuid(pw->pw_uid) == -1) {
 
3636
      cry(fc(ctx), "%s: setuid(%s): %s", __func__, uid, strerror(errno));
 
3637
    } else {
 
3638
      success = 1;
 
3639
    }
 
3640
  }
 
3641
 
 
3642
  return success;
 
3643
}
 
3644
#endif // !_WIN32
 
3645
 
 
3646
#if !defined(NO_SSL)
 
3647
static pthread_mutex_t *ssl_mutexes;
 
3648
 
 
3649
static void ssl_locking_callback(int mode, int mutex_num, const char *file,
 
3650
                                 int line) {
 
3651
  line = 0;    // Unused
 
3652
  file = NULL; // Unused
 
3653
 
 
3654
  if (mode & CRYPTO_LOCK) {
 
3655
    (void) pthread_mutex_lock(&ssl_mutexes[mutex_num]);
 
3656
  } else {
 
3657
    (void) pthread_mutex_unlock(&ssl_mutexes[mutex_num]);
 
3658
  }
 
3659
}
 
3660
 
 
3661
static unsigned long ssl_id_callback(void) {
 
3662
  return (unsigned long) pthread_self();
 
3663
}
 
3664
 
 
3665
#if !defined(NO_SSL_DL)
 
3666
static int load_dll(struct mg_context *ctx, const char *dll_name,
 
3667
                    struct ssl_func *sw) {
 
3668
  union {void *p; void (*fp)(void);} u;
 
3669
  void  *dll_handle;
 
3670
  struct ssl_func *fp;
 
3671
 
 
3672
  if ((dll_handle = dlopen(dll_name, RTLD_LAZY)) == NULL) {
 
3673
    cry(fc(ctx), "%s: cannot load %s", __func__, dll_name);
 
3674
    return 0;
 
3675
  }
 
3676
 
 
3677
  for (fp = sw; fp->name != NULL; fp++) {
 
3678
#ifdef _WIN32
 
3679
    // GetProcAddress() returns pointer to function
 
3680
    u.fp = (void (*)(void)) dlsym(dll_handle, fp->name);
 
3681
#else
 
3682
    // dlsym() on UNIX returns void *. ISO C forbids casts of data pointers to
 
3683
    // function pointers. We need to use a union to make a cast.
 
3684
    u.p = dlsym(dll_handle, fp->name);
 
3685
#endif // _WIN32
 
3686
    if (u.fp == NULL) {
 
3687
      cry(fc(ctx), "%s: %s: cannot find %s", __func__, dll_name, fp->name);
 
3688
      return 0;
 
3689
    } else {
 
3690
      fp->ptr = u.fp;
 
3691
    }
 
3692
  }
 
3693
 
 
3694
  return 1;
 
3695
}
 
3696
#endif // NO_SSL_DL
 
3697
 
 
3698
// Dynamically load SSL library. Set up ctx->ssl_ctx pointer.
 
3699
static int set_ssl_option(struct mg_context *ctx) {
 
3700
  struct mg_request_info request_info;
 
3701
  SSL_CTX *CTX;
 
3702
  int i, size;
 
3703
  const char *pem = ctx->config[SSL_CERTIFICATE];
 
3704
  const char *chain = ctx->config[SSL_CHAIN_FILE];
 
3705
 
 
3706
  if (pem == NULL) {
 
3707
    return 1;
 
3708
  }
 
3709
 
 
3710
#if !defined(NO_SSL_DL)
 
3711
  if (!load_dll(ctx, SSL_LIB, ssl_sw) ||
 
3712
      !load_dll(ctx, CRYPTO_LIB, crypto_sw)) {
 
3713
    return 0;
 
3714
  }
 
3715
#endif // NO_SSL_DL
 
3716
 
 
3717
  // Initialize SSL crap
 
3718
  SSL_library_init();
 
3719
  SSL_load_error_strings();
 
3720
 
 
3721
  if ((CTX = SSL_CTX_new(SSLv23_server_method())) == NULL) {
 
3722
    cry(fc(ctx), "SSL_CTX_new error: %s", ssl_error());
 
3723
  } else if (ctx->user_callback != NULL) {
 
3724
    memset(&request_info, 0, sizeof(request_info));
 
3725
    request_info.user_data = ctx->user_data;
 
3726
    ctx->user_callback(MG_INIT_SSL, (struct mg_connection *) CTX,
 
3727
                       &request_info);
 
3728
  }
 
3729
 
 
3730
  if (CTX != NULL && SSL_CTX_use_certificate_file(CTX, pem,
 
3731
        SSL_FILETYPE_PEM) == 0) {
 
3732
    cry(fc(ctx), "%s: cannot open %s: %s", __func__, pem, ssl_error());
 
3733
    return 0;
 
3734
  } else if (CTX != NULL && SSL_CTX_use_PrivateKey_file(CTX, pem,
 
3735
        SSL_FILETYPE_PEM) == 0) {
 
3736
    cry(fc(ctx), "%s: cannot open %s: %s", NULL, pem, ssl_error());
 
3737
    return 0;
 
3738
  }
 
3739
 
 
3740
  if (CTX != NULL && chain != NULL &&
 
3741
      SSL_CTX_use_certificate_chain_file(CTX, chain) == 0) {
 
3742
    cry(fc(ctx), "%s: cannot open %s: %s", NULL, chain, ssl_error());
 
3743
    return 0;
 
3744
  }
 
3745
 
 
3746
  // Initialize locking callbacks, needed for thread safety.
 
3747
  // http://www.openssl.org/support/faq.html#PROG1
 
3748
  size = sizeof(pthread_mutex_t) * CRYPTO_num_locks();
 
3749
  if ((ssl_mutexes = (pthread_mutex_t *) malloc((size_t)size)) == NULL) {
 
3750
    cry(fc(ctx), "%s: cannot allocate mutexes: %s", __func__, ssl_error());
 
3751
    return 0;
 
3752
  }
 
3753
 
 
3754
  for (i = 0; i < CRYPTO_num_locks(); i++) {
 
3755
    pthread_mutex_init(&ssl_mutexes[i], NULL);
 
3756
  }
 
3757
 
 
3758
  CRYPTO_set_locking_callback(&ssl_locking_callback);
 
3759
  CRYPTO_set_id_callback(&ssl_id_callback);
 
3760
 
 
3761
  // Done with everything. Save the context.
 
3762
  ctx->ssl_ctx = CTX;
 
3763
 
 
3764
  return 1;
 
3765
}
 
3766
 
 
3767
static void uninitialize_ssl(struct mg_context *ctx) {
 
3768
  int i;
 
3769
  if (ctx->ssl_ctx != NULL) {
 
3770
    CRYPTO_set_locking_callback(NULL);
 
3771
    for (i = 0; i < CRYPTO_num_locks(); i++) {
 
3772
      pthread_mutex_destroy(&ssl_mutexes[i]);
 
3773
    }
 
3774
    CRYPTO_set_locking_callback(NULL);
 
3775
    CRYPTO_set_id_callback(NULL);
 
3776
  }
 
3777
}
 
3778
#endif // !NO_SSL
 
3779
 
 
3780
static int set_gpass_option(struct mg_context *ctx) {
 
3781
  struct mgstat mgstat;
 
3782
  const char *path = ctx->config[GLOBAL_PASSWORDS_FILE];
 
3783
  return path == NULL || mg_stat(path, &mgstat) == 0;
 
3784
}
 
3785
 
 
3786
static int set_acl_option(struct mg_context *ctx) {
 
3787
  union usa fake;
 
3788
  return check_acl(ctx, &fake) != -1;
 
3789
}
 
3790
 
 
3791
static void reset_per_request_attributes(struct mg_connection *conn) {
 
3792
  struct mg_request_info *ri = &conn->request_info;
 
3793
 
 
3794
  // Reset request info attributes. DO NOT TOUCH is_ssl, remote_ip, remote_port
 
3795
  ri->remote_user = ri->request_method = ri->uri = ri->http_version =
 
3796
    conn->path_info = NULL;
 
3797
  ri->num_headers = 0;
 
3798
  ri->status_code = -1;
 
3799
 
 
3800
  conn->num_bytes_sent = conn->consumed_content = 0;
 
3801
  conn->content_len = -1;
 
3802
  conn->request_len = conn->data_len = 0;
 
3803
  conn->must_close = 0;
 
3804
}
 
3805
 
 
3806
static void close_socket_gracefully(SOCKET sock) {
 
3807
  char buf[BUFSIZ];
 
3808
  struct linger linger;
 
3809
  int n;
 
3810
 
 
3811
  // Set linger option to avoid socket hanging out after close. This prevent
 
3812
  // ephemeral port exhaust problem under high QPS.
 
3813
  linger.l_onoff = 1;
 
3814
  linger.l_linger = 1;
 
3815
  setsockopt(sock, SOL_SOCKET, SO_LINGER, (void *) &linger, sizeof(linger));
 
3816
 
 
3817
  // Send FIN to the client
 
3818
  (void) shutdown(sock, SHUT_WR);
 
3819
  set_non_blocking_mode(sock);
 
3820
 
 
3821
  // Read and discard pending data. If we do not do that and close the
 
3822
  // socket, the data in the send buffer may be discarded. This
 
3823
  // behaviour is seen on Windows, when client keeps sending data
 
3824
  // when server decide to close the connection; then when client
 
3825
  // does recv() it gets no data back.
 
3826
  do {
 
3827
    n = pull(NULL, sock, NULL, buf, sizeof(buf));
 
3828
  } while (n > 0);
 
3829
 
 
3830
  // Now we know that our FIN is ACK-ed, safe to close
 
3831
  (void) closesocket(sock);
 
3832
}
 
3833
 
 
3834
static void close_connection(struct mg_connection *conn) {
 
3835
  if (conn->ssl) {
 
3836
    SSL_free(conn->ssl);
 
3837
    conn->ssl = NULL;
 
3838
  }
 
3839
 
 
3840
  if (conn->client.sock != INVALID_SOCKET) {
 
3841
    close_socket_gracefully(conn->client.sock);
 
3842
  }
 
3843
}
 
3844
 
 
3845
static void discard_current_request_from_buffer(struct mg_connection *conn) {
 
3846
  char *buffered;
 
3847
  int buffered_len, body_len;
 
3848
 
 
3849
  buffered = conn->buf + conn->request_len;
 
3850
  buffered_len = conn->data_len - conn->request_len;
 
3851
  assert(buffered_len >= 0);
 
3852
 
 
3853
  if (conn->content_len == -1) {
 
3854
    body_len = 0;
 
3855
  } else if (conn->content_len < (int64_t) buffered_len) {
 
3856
    body_len = (int) conn->content_len;
 
3857
  } else {
 
3858
    body_len = buffered_len;
 
3859
  }
 
3860
 
 
3861
  conn->data_len -= conn->request_len + body_len;
 
3862
  memmove(conn->buf, conn->buf + conn->request_len + body_len,
 
3863
          (size_t) conn->data_len);
 
3864
}
 
3865
 
 
3866
static int is_valid_uri(const char *uri) {
 
3867
  // Conform to http://www.w3.org/Protocols/rfc2616/rfc2616-sec5.html#sec5.1.2
 
3868
  // URI can be an asterisk (*) or should start with slash.
 
3869
  return uri[0] == '/' || (uri[0] == '*' && uri[1] == '\0');
 
3870
}
 
3871
 
 
3872
static void process_new_connection(struct mg_connection *conn) {
 
3873
  struct mg_request_info *ri = &conn->request_info;
 
3874
  int keep_alive_enabled;
 
3875
  const char *cl;
 
3876
 
 
3877
  keep_alive_enabled = !strcmp(conn->ctx->config[ENABLE_KEEP_ALIVE], "yes");
 
3878
 
 
3879
  do {
 
3880
    reset_per_request_attributes(conn);
 
3881
 
 
3882
    // If next request is not pipelined, read it in
 
3883
    if ((conn->request_len = get_request_len(conn->buf, conn->data_len)) == 0) {
 
3884
      conn->request_len = read_request(NULL, conn->client.sock, conn->ssl,
 
3885
          conn->buf, conn->buf_size, &conn->data_len);
 
3886
    }
 
3887
    assert(conn->data_len >= conn->request_len);
 
3888
    if (conn->request_len == 0 && conn->data_len == conn->buf_size) {
 
3889
      send_http_error(conn, 413, "Request Too Large", "");
 
3890
      return;
 
3891
    } if (conn->request_len <= 0) {
 
3892
      return;  // Remote end closed the connection
 
3893
    }
 
3894
 
 
3895
    // Nul-terminate the request cause parse_http_request() uses sscanf
 
3896
    conn->buf[conn->request_len - 1] = '\0';
 
3897
    if (!parse_http_request(conn->buf, ri) || !is_valid_uri(ri->uri)) {
 
3898
      // Do not put garbage in the access log, just send it back to the client
 
3899
      send_http_error(conn, 400, "Bad Request",
 
3900
          "Cannot parse HTTP request: [%.*s]", conn->data_len, conn->buf);
 
3901
    } else if (strcmp(ri->http_version, "1.0") &&
 
3902
               strcmp(ri->http_version, "1.1")) {
 
3903
      // Request seems valid, but HTTP version is strange
 
3904
      send_http_error(conn, 505, "HTTP version not supported", "");
 
3905
      log_access(conn);
 
3906
    } else {
 
3907
      // Request is valid, handle it
 
3908
      cl = get_header(ri, "Content-Length");
 
3909
      conn->content_len = cl == NULL ? -1 : strtoll(cl, NULL, 10);
 
3910
      conn->birth_time = time(NULL);
 
3911
      handle_request(conn);
 
3912
      call_user(conn, MG_REQUEST_COMPLETE);
 
3913
      log_access(conn);
 
3914
      discard_current_request_from_buffer(conn);
 
3915
    }
 
3916
    if (ri->remote_user != NULL) {
 
3917
      free((void *) ri->remote_user);
 
3918
    }
 
3919
  } while (conn->ctx->stop_flag == 0 &&
 
3920
           keep_alive_enabled &&
 
3921
           should_keep_alive(conn));
 
3922
}
 
3923
 
 
3924
// Worker threads take accepted socket from the queue
 
3925
static int consume_socket(struct mg_context *ctx, struct socket *sp) {
 
3926
  (void) pthread_mutex_lock(&ctx->mutex);
 
3927
  DEBUG_TRACE(("going idle"));
 
3928
 
 
3929
  // If the queue is empty, wait. We're idle at this point.
 
3930
  while (ctx->sq_head == ctx->sq_tail && ctx->stop_flag == 0) {
 
3931
    pthread_cond_wait(&ctx->sq_full, &ctx->mutex);
 
3932
  }
 
3933
 
 
3934
  // If we're stopping, sq_head may be equal to sq_tail.
 
3935
  if (ctx->sq_head > ctx->sq_tail) {
 
3936
    // Copy socket from the queue and increment tail
 
3937
    *sp = ctx->queue[ctx->sq_tail % ARRAY_SIZE(ctx->queue)];
 
3938
    ctx->sq_tail++;
 
3939
    DEBUG_TRACE(("grabbed socket %d, going busy", sp->sock));
 
3940
 
 
3941
    // Wrap pointers if needed
 
3942
    while (ctx->sq_tail > (int) ARRAY_SIZE(ctx->queue)) {
 
3943
      ctx->sq_tail -= ARRAY_SIZE(ctx->queue);
 
3944
      ctx->sq_head -= ARRAY_SIZE(ctx->queue);
 
3945
    }
 
3946
  }
 
3947
 
 
3948
  (void) pthread_cond_signal(&ctx->sq_empty);
 
3949
  (void) pthread_mutex_unlock(&ctx->mutex);
 
3950
 
 
3951
  return !ctx->stop_flag;
 
3952
}
 
3953
 
 
3954
static void worker_thread(struct mg_context *ctx) {
 
3955
  struct mg_connection *conn;
 
3956
  int buf_size = atoi(ctx->config[MAX_REQUEST_SIZE]);
 
3957
 
 
3958
  conn = (struct mg_connection *) calloc(1, sizeof(*conn) + buf_size);
 
3959
  if (conn == NULL) {
 
3960
    cry(fc(ctx), "%s", "Cannot create new connection struct, OOM");
 
3961
    return;
 
3962
  }
 
3963
  conn->buf_size = buf_size;
 
3964
  conn->buf = (char *) (conn + 1);
 
3965
 
 
3966
  // Call consume_socket() even when ctx->stop_flag > 0, to let it signal
 
3967
  // sq_empty condvar to wake up the master waiting in produce_socket()
 
3968
  while (consume_socket(ctx, &conn->client)) {
 
3969
    conn->birth_time = time(NULL);
 
3970
    conn->ctx = ctx;
 
3971
 
 
3972
    // Fill in IP, port info early so even if SSL setup below fails,
 
3973
    // error handler would have the corresponding info.
 
3974
    // Thanks to Johannes Winkelmann for the patch.
 
3975
    // TODO(lsm): Fix IPv6 case
 
3976
    conn->request_info.remote_port = ntohs(conn->client.rsa.sin.sin_port);
 
3977
    memcpy(&conn->request_info.remote_ip,
 
3978
           &conn->client.rsa.sin.sin_addr.s_addr, 4);
 
3979
    conn->request_info.remote_ip = ntohl(conn->request_info.remote_ip);
 
3980
    conn->request_info.is_ssl = conn->client.is_ssl;
 
3981
 
 
3982
    if (!conn->client.is_ssl ||
 
3983
        (conn->client.is_ssl && sslize(conn, SSL_accept))) {
 
3984
      process_new_connection(conn);
 
3985
    }
 
3986
 
 
3987
    close_connection(conn);
 
3988
  }
 
3989
  free(conn);
 
3990
 
 
3991
  // Signal master that we're done with connection and exiting
 
3992
  (void) pthread_mutex_lock(&ctx->mutex);
 
3993
  ctx->num_threads--;
 
3994
  (void) pthread_cond_signal(&ctx->cond);
 
3995
  assert(ctx->num_threads >= 0);
 
3996
  (void) pthread_mutex_unlock(&ctx->mutex);
 
3997
 
 
3998
  DEBUG_TRACE(("exiting"));
 
3999
}
 
4000
 
 
4001
// Master thread adds accepted socket to a queue
 
4002
static void produce_socket(struct mg_context *ctx, const struct socket *sp) {
 
4003
  (void) pthread_mutex_lock(&ctx->mutex);
 
4004
 
 
4005
  // If the queue is full, wait
 
4006
  while (ctx->stop_flag == 0 &&
 
4007
         ctx->sq_head - ctx->sq_tail >= (int) ARRAY_SIZE(ctx->queue)) {
 
4008
    (void) pthread_cond_wait(&ctx->sq_empty, &ctx->mutex);
 
4009
  }
 
4010
 
 
4011
  if (ctx->sq_head - ctx->sq_tail < (int) ARRAY_SIZE(ctx->queue)) {
 
4012
    // Copy socket to the queue and increment head
 
4013
    ctx->queue[ctx->sq_head % ARRAY_SIZE(ctx->queue)] = *sp;
 
4014
    ctx->sq_head++;
 
4015
    DEBUG_TRACE(("queued socket %d", sp->sock));
 
4016
  }
 
4017
 
 
4018
  (void) pthread_cond_signal(&ctx->sq_full);
 
4019
  (void) pthread_mutex_unlock(&ctx->mutex);
 
4020
}
 
4021
 
 
4022
static void accept_new_connection(const struct socket *listener,
 
4023
                                  struct mg_context *ctx) {
 
4024
  struct socket accepted;
 
4025
  char src_addr[20];
 
4026
  socklen_t len;
 
4027
  int allowed;
 
4028
 
 
4029
  len = sizeof(accepted.rsa);
 
4030
  accepted.lsa = listener->lsa;
 
4031
  accepted.sock = accept(listener->sock, &accepted.rsa.sa, &len);
 
4032
  if (accepted.sock != INVALID_SOCKET) {
 
4033
    allowed = check_acl(ctx, &accepted.rsa);
 
4034
    if (allowed) {
 
4035
      // Put accepted socket structure into the queue
 
4036
      DEBUG_TRACE(("accepted socket %d", accepted.sock));
 
4037
      accepted.is_ssl = listener->is_ssl;
 
4038
      produce_socket(ctx, &accepted);
 
4039
    } else {
 
4040
      sockaddr_to_string(src_addr, sizeof(src_addr), &accepted.rsa);
 
4041
      cry(fc(ctx), "%s: %s is not allowed to connect", __func__, src_addr);
 
4042
      (void) closesocket(accepted.sock);
 
4043
    }
 
4044
  }
 
4045
}
 
4046
 
 
4047
static void master_thread(struct mg_context *ctx) {
 
4048
  fd_set read_set;
 
4049
  struct timeval tv;
 
4050
  struct socket *sp;
 
4051
  int max_fd;
 
4052
 
 
4053
  // Increase priority of the master thread
 
4054
#if defined(_WIN32)
 
4055
  SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL);
 
4056
#endif
 
4057
  
 
4058
#if defined(ISSUE_317)
 
4059
  struct sched_param sched_param;
 
4060
  sched_param.sched_priority = sched_get_priority_max(SCHED_RR);
 
4061
  pthread_setschedparam(pthread_self(), SCHED_RR, &sched_param);
 
4062
#endif
 
4063
 
 
4064
  while (ctx->stop_flag == 0) {
 
4065
    FD_ZERO(&read_set);
 
4066
    max_fd = -1;
 
4067
 
 
4068
    // Add listening sockets to the read set
 
4069
    for (sp = ctx->listening_sockets; sp != NULL; sp = sp->next) {
 
4070
      add_to_set(sp->sock, &read_set, &max_fd);
 
4071
    }
 
4072
 
 
4073
    tv.tv_sec = 0;
 
4074
    tv.tv_usec = 200 * 1000;
 
4075
 
 
4076
    if (select(max_fd + 1, &read_set, NULL, NULL, &tv) < 0) {
 
4077
#ifdef _WIN32
 
4078
      // On windows, if read_set and write_set are empty,
 
4079
      // select() returns "Invalid parameter" error
 
4080
      // (at least on my Windows XP Pro). So in this case, we sleep here.
 
4081
      sleep(1);
 
4082
#endif // _WIN32
 
4083
    } else {
 
4084
      for (sp = ctx->listening_sockets; sp != NULL; sp = sp->next) {
 
4085
        if (ctx->stop_flag == 0 && FD_ISSET(sp->sock, &read_set)) {
 
4086
          accept_new_connection(sp, ctx);
 
4087
        }
 
4088
      }
 
4089
    }
 
4090
  }
 
4091
  DEBUG_TRACE(("stopping workers"));
 
4092
 
 
4093
  // Stop signal received: somebody called mg_stop. Quit.
 
4094
  close_all_listening_sockets(ctx);
 
4095
 
 
4096
  // Wakeup workers that are waiting for connections to handle.
 
4097
  pthread_cond_broadcast(&ctx->sq_full);
 
4098
 
 
4099
  // Wait until all threads finish
 
4100
  (void) pthread_mutex_lock(&ctx->mutex);
 
4101
  while (ctx->num_threads > 0) {
 
4102
    (void) pthread_cond_wait(&ctx->cond, &ctx->mutex);
 
4103
  }
 
4104
  (void) pthread_mutex_unlock(&ctx->mutex);
 
4105
 
 
4106
  // All threads exited, no sync is needed. Destroy mutex and condvars
 
4107
  (void) pthread_mutex_destroy(&ctx->mutex);
 
4108
  (void) pthread_cond_destroy(&ctx->cond);
 
4109
  (void) pthread_cond_destroy(&ctx->sq_empty);
 
4110
  (void) pthread_cond_destroy(&ctx->sq_full);
 
4111
 
 
4112
#if !defined(NO_SSL)
 
4113
  uninitialize_ssl(ctx);
 
4114
#endif
 
4115
 
 
4116
  // Signal mg_stop() that we're done
 
4117
  ctx->stop_flag = 2;
 
4118
 
 
4119
  DEBUG_TRACE(("exiting"));
 
4120
}
 
4121
 
 
4122
static void free_context(struct mg_context *ctx) {
 
4123
  int i;
 
4124
 
 
4125
  // Deallocate config parameters
 
4126
  for (i = 0; i < NUM_OPTIONS; i++) {
 
4127
    if (ctx->config[i] != NULL)
 
4128
      free(ctx->config[i]);
 
4129
  }
 
4130
 
 
4131
  // Deallocate SSL context
 
4132
  if (ctx->ssl_ctx != NULL) {
 
4133
    SSL_CTX_free(ctx->ssl_ctx);
 
4134
  }
 
4135
#ifndef NO_SSL
 
4136
  if (ssl_mutexes != NULL) {
 
4137
    free(ssl_mutexes);
 
4138
  }
 
4139
#endif // !NO_SSL
 
4140
 
 
4141
  // Deallocate context itself
 
4142
  free(ctx);
 
4143
}
 
4144
 
 
4145
void mg_stop(struct mg_context *ctx) {
 
4146
  ctx->stop_flag = 1;
 
4147
 
 
4148
  // Wait until mg_fini() stops
 
4149
  while (ctx->stop_flag != 2) {
 
4150
    (void) sleep(0);
 
4151
  }
 
4152
  free_context(ctx);
 
4153
 
 
4154
#if defined(_WIN32) && !defined(__SYMBIAN32__)
 
4155
  (void) WSACleanup();
 
4156
#endif // _WIN32
 
4157
}
 
4158
 
 
4159
struct mg_context *mg_start(mg_callback_t user_callback, void *user_data,
 
4160
                            const char **options) {
 
4161
  struct mg_context *ctx;
 
4162
  const char *name, *value, *default_value;
 
4163
  int i;
 
4164
 
 
4165
#if defined(_WIN32) && !defined(__SYMBIAN32__)
 
4166
  WSADATA data;
 
4167
  WSAStartup(MAKEWORD(2,2), &data);
 
4168
  InitializeCriticalSection(&global_log_file_lock);
 
4169
#endif // _WIN32
 
4170
 
 
4171
  // Allocate context and initialize reasonable general case defaults.
 
4172
  // TODO(lsm): do proper error handling here.
 
4173
  ctx = (struct mg_context *) calloc(1, sizeof(*ctx));
 
4174
  ctx->user_callback = user_callback;
 
4175
  ctx->user_data = user_data;
 
4176
 
 
4177
  while (options && (name = *options++) != NULL) {
 
4178
    if ((i = get_option_index(name)) == -1) {
 
4179
      cry(fc(ctx), "Invalid option: %s", name);
 
4180
      free_context(ctx);
 
4181
      return NULL;
 
4182
    } else if ((value = *options++) == NULL) {
 
4183
      cry(fc(ctx), "%s: option value cannot be NULL", name);
 
4184
      free_context(ctx);
 
4185
      return NULL;
 
4186
    }
 
4187
    if (ctx->config[i] != NULL) {
 
4188
      cry(fc(ctx), "%s: duplicate option", name);
 
4189
    }
 
4190
    ctx->config[i] = mg_strdup(value);
 
4191
    DEBUG_TRACE(("[%s] -> [%s]", name, value));
 
4192
  }
 
4193
 
 
4194
  // Set default value if needed
 
4195
  for (i = 0; config_options[i * ENTRIES_PER_CONFIG_OPTION] != NULL; i++) {
 
4196
    default_value = config_options[i * ENTRIES_PER_CONFIG_OPTION + 2];
 
4197
    if (ctx->config[i] == NULL && default_value != NULL) {
 
4198
      ctx->config[i] = mg_strdup(default_value);
 
4199
      DEBUG_TRACE(("Setting default: [%s] -> [%s]",
 
4200
                   config_options[i * ENTRIES_PER_CONFIG_OPTION + 1],
 
4201
                   default_value));
 
4202
    }
 
4203
  }
 
4204
 
 
4205
  // NOTE(lsm): order is important here. SSL certificates must
 
4206
  // be initialized before listening ports. UID must be set last.
 
4207
  if (!set_gpass_option(ctx) ||
 
4208
#if !defined(NO_SSL)
 
4209
      !set_ssl_option(ctx) ||
 
4210
#endif
 
4211
      !set_ports_option(ctx) ||
 
4212
#if !defined(_WIN32)
 
4213
      !set_uid_option(ctx) ||
 
4214
#endif
 
4215
      !set_acl_option(ctx)) {
 
4216
    free_context(ctx);
 
4217
    return NULL;
 
4218
  }
 
4219
 
 
4220
#if !defined(_WIN32) && !defined(__SYMBIAN32__)
 
4221
  // Ignore SIGPIPE signal, so if browser cancels the request, it
 
4222
  // won't kill the whole process.
 
4223
  (void) signal(SIGPIPE, SIG_IGN);
 
4224
  // Also ignoring SIGCHLD to let the OS to reap zombies properly.
 
4225
  (void) signal(SIGCHLD, SIG_IGN);
 
4226
#endif // !_WIN32
 
4227
 
 
4228
  (void) pthread_mutex_init(&ctx->mutex, NULL);
 
4229
  (void) pthread_cond_init(&ctx->cond, NULL);
 
4230
  (void) pthread_cond_init(&ctx->sq_empty, NULL);
 
4231
  (void) pthread_cond_init(&ctx->sq_full, NULL);
 
4232
 
 
4233
  // Start master (listening) thread
 
4234
  start_thread(ctx, (mg_thread_func_t) master_thread, ctx);
 
4235
 
 
4236
  // Start worker threads
 
4237
  for (i = 0; i < atoi(ctx->config[NUM_THREADS]); i++) {
 
4238
    if (start_thread(ctx, (mg_thread_func_t) worker_thread, ctx) != 0) {
 
4239
      cry(fc(ctx), "Cannot start worker thread: %d", ERRNO);
 
4240
    } else {
 
4241
      ctx->num_threads++;
 
4242
    }
 
4243
  }
 
4244
 
 
4245
  return ctx;
 
4246
}