diff --git a/build/Makefile b/build/Makefile
index 92c7e82a53bd55ede4fc8f557e7651171ac583d9..618896db17713af885062a526d81e53d2dfd5c8f 100644
--- a/build/Makefile
+++ b/build/Makefile
@@ -24,7 +24,7 @@ EXE_SUFFIX =
 CFLAGS = -std=c99 -O2 -W -Wall -pedantic -pthread -pipe -I.. $(CFLAGS_EXTRA)
 VERSION = $(shell perl -lne \
             'print $$1 if /define\s+MONGOOSE_VERSION\s+"(\S+)"/' ../mongoose.c)
-SOURCES = src/mongoose.c
+SOURCES = src/internal.h src/string.c src/mongoose.c
 
 TINY_SOURCES = ../mongoose.c main.c
 LUA_SOURCES = $(TINY_SOURCES) sqlite3.c lsqlite3.c lua_5.2.1.c
@@ -57,8 +57,8 @@ endif
 all:
 	@echo "make (unix|windows|macos)"
 
-../mongoose.c: mod_lua.c ../mongoose.h Makefile src/internal.h $(SOURCES)
-	cat src/internal.h src/mongoose.c | sed '/#include "internal.h"/d' > $@
+../mongoose.c: mod_lua.c ../mongoose.h Makefile $(SOURCES)
+	cat $(SOURCES) | sed '/#include "internal.h"/d' > $@
 
 unix_unit_test: $(LUA_SOURCES) Makefile ../test/unit_test.c
 	$(CC) ../test/unit_test.c lua_5.2.1.c $(CFLAGS) -g -O0 -o t && ./t
diff --git a/build/src/mongoose.c b/build/src/mongoose.c
index 7f73e6649de1a30963609013ea5625f20a412000..3b26a277e8280fe857c765a55863438bf314b0d0 100644
--- a/build/src/mongoose.c
+++ b/build/src/mongoose.c
@@ -159,254 +159,6 @@ const char *mg_version(void) {
   return MONGOOSE_VERSION;
 }
 
-static void mg_strlcpy(register char *dst, register const char *src, size_t n) {
-  for (; *src != '\0' && n > 1; n--) {
-    *dst++ = *src++;
-  }
-  *dst = '\0';
-}
-
-static int lowercase(const char *s) {
-  return tolower(* (const unsigned char *) s);
-}
-
-static int mg_strncasecmp(const char *s1, const char *s2, size_t len) {
-  int diff = 0;
-
-  if (len > 0)
-    do {
-      diff = lowercase(s1++) - lowercase(s2++);
-    } while (diff == 0 && s1[-1] != '\0' && --len > 0);
-
-  return diff;
-}
-
-static int mg_strcasecmp(const char *s1, const char *s2) {
-  int diff;
-
-  do {
-    diff = lowercase(s1++) - lowercase(s2++);
-  } while (diff == 0 && s1[-1] != '\0');
-
-  return diff;
-}
-
-static char * mg_strndup(const char *ptr, size_t len) {
-  char *p;
-
-  if ((p = (char *) malloc(len + 1)) != NULL) {
-    mg_strlcpy(p, ptr, len + 1);
-  }
-
-  return p;
-}
-
-static char * mg_strdup(const char *str) {
-  return mg_strndup(str, strlen(str));
-}
-
-static const char *mg_strcasestr(const char *big_str, const char *small_str) {
-  int i, big_len = strlen(big_str), small_len = strlen(small_str);
-
-  for (i = 0; i <= big_len - small_len; i++) {
-    if (mg_strncasecmp(big_str + i, small_str, small_len) == 0) {
-      return big_str + i;
-    }
-  }
-
-  return NULL;
-}
-
-// Like snprintf(), but never returns negative value, or a value
-// that is larger than a supplied buffer.
-// Thanks to Adam Zeldis to pointing snprintf()-caused vulnerability
-// in his audit report.
-static int mg_vsnprintf(struct mg_connection *conn, char *buf, size_t buflen,
-                        const char *fmt, va_list ap) {
-  int n;
-
-  if (buflen == 0)
-    return 0;
-
-  n = vsnprintf(buf, buflen, fmt, ap);
-
-  if (n < 0) {
-    cry(conn, "vsnprintf error");
-    n = 0;
-  } else if (n >= (int) buflen) {
-    cry(conn, "truncating vsnprintf buffer: [%.*s]",
-        n > 200 ? 200 : n, buf);
-    n = (int) buflen - 1;
-  }
-  buf[n] = '\0';
-
-  return n;
-}
-
-static int mg_snprintf(struct mg_connection *conn, char *buf, size_t buflen,
-                       PRINTF_FORMAT_STRING(const char *fmt), ...)
-  PRINTF_ARGS(4, 5);
-
-static int mg_snprintf(struct mg_connection *conn, char *buf, size_t buflen,
-                       const char *fmt, ...) {
-  va_list ap;
-  int n;
-
-  va_start(ap, fmt);
-  n = mg_vsnprintf(conn, buf, buflen, fmt, ap);
-  va_end(ap);
-
-  return n;
-}
-
-// Skip the characters until one of the delimiters characters found.
-// 0-terminate resulting word. Skip the delimiter and following whitespaces.
-// Advance pointer to buffer to the next word. Return found 0-terminated word.
-// Delimiters can be quoted with quotechar.
-static char *skip_quoted(char **buf, const char *delimiters,
-                         const char *whitespace, char quotechar) {
-  char *p, *begin_word, *end_word, *end_whitespace;
-
-  begin_word = *buf;
-  end_word = begin_word + strcspn(begin_word, delimiters);
-
-  // Check for quotechar
-  if (end_word > begin_word) {
-    p = end_word - 1;
-    while (*p == quotechar) {
-      // If there is anything beyond end_word, copy it
-      if (*end_word == '\0') {
-        *p = '\0';
-        break;
-      } else {
-        size_t end_off = strcspn(end_word + 1, delimiters);
-        memmove (p, end_word, end_off + 1);
-        p += end_off; // p must correspond to end_word - 1
-        end_word += end_off + 1;
-      }
-    }
-    for (p++; p < end_word; p++) {
-      *p = '\0';
-    }
-  }
-
-  if (*end_word == '\0') {
-    *buf = end_word;
-  } else {
-    end_whitespace = end_word + 1 + strspn(end_word + 1, whitespace);
-
-    for (p = end_word; p < end_whitespace; p++) {
-      *p = '\0';
-    }
-
-    *buf = end_whitespace;
-  }
-
-  return begin_word;
-}
-
-// Simplified version of skip_quoted without quote char
-// and whitespace == delimiters
-static char *skip(char **buf, const char *delimiters) {
-  return skip_quoted(buf, delimiters, delimiters, 0);
-}
-
-
-// Return HTTP header value, or NULL if not found.
-static const char *get_header(const struct mg_request_info *ri,
-                              const char *name) {
-  int i;
-
-  for (i = 0; i < ri->num_headers; i++)
-    if (!mg_strcasecmp(name, ri->http_headers[i].name))
-      return ri->http_headers[i].value;
-
-  return NULL;
-}
-
-const char *mg_get_header(const struct mg_connection *conn, const char *name) {
-  return get_header(&conn->request_info, name);
-}
-
-// A helper function for traversing a comma separated list of values.
-// It returns a list pointer shifted to the next value, or NULL if the end
-// of the list found.
-// Value is stored in val vector. If value has form "x=y", then eq_val
-// vector is initialized to point to the "y" part, and val vector length
-// is adjusted to point only to "x".
-static const char *next_option(const char *list, struct vec *val,
-                               struct vec *eq_val) {
-  if (list == NULL || *list == '\0') {
-    // End of the list
-    list = NULL;
-  } else {
-    val->ptr = list;
-    if ((list = strchr(val->ptr, ',')) != NULL) {
-      // Comma found. Store length and shift the list ptr
-      val->len = list - val->ptr;
-      list++;
-    } else {
-      // This value is the last one
-      list = val->ptr + strlen(val->ptr);
-      val->len = list - val->ptr;
-    }
-
-    if (eq_val != NULL) {
-      // Value has form "x=y", adjust pointers and lengths
-      // so that val points to "x", and eq_val points to "y".
-      eq_val->len = 0;
-      eq_val->ptr = (const char *) memchr(val->ptr, '=', val->len);
-      if (eq_val->ptr != NULL) {
-        eq_val->ptr++;  // Skip over '=' character
-        eq_val->len = val->ptr + val->len - eq_val->ptr;
-        val->len = (eq_val->ptr - val->ptr) - 1;
-      }
-    }
-  }
-
-  return list;
-}
-
-// Perform case-insensitive match of string against pattern
-static int match_prefix(const char *pattern, int pattern_len, const char *str) {
-  const char *or_str;
-  int i, j, len, res;
-
-  if ((or_str = (const char *) memchr(pattern, '|', pattern_len)) != NULL) {
-    res = match_prefix(pattern, or_str - pattern, str);
-    return res > 0 ? res :
-        match_prefix(or_str + 1, (pattern + pattern_len) - (or_str + 1), str);
-  }
-
-  i = j = 0;
-  res = -1;
-  for (; i < pattern_len; i++, j++) {
-    if (pattern[i] == '?' && str[j] != '\0') {
-      continue;
-    } else if (pattern[i] == '$') {
-      return str[j] == '\0' ? j : -1;
-    } else if (pattern[i] == '*') {
-      i++;
-      if (pattern[i] == '*') {
-        i++;
-        len = (int) strlen(str + j);
-      } else {
-        len = (int) strcspn(str + j, "/");
-      }
-      if (i == pattern_len) {
-        return j + len;
-      }
-      do {
-        res = match_prefix(pattern + i, pattern_len - i, str + j + len);
-      } while (res == -1 && len-- > 0);
-      return res == -1 ? -1 : j + res + len;
-    } else if (lowercase(&pattern[i]) != lowercase(&str[j])) {
-      return -1;
-    }
-  }
-  return j;
-}
-
 // HTTP 1.1 assumes keep alive if "Connection:" header is not set
 // This function must tolerate situations when connection info is not
 // set up, for example if request parsing failed.
@@ -443,11 +195,11 @@ static void send_http_error(struct mg_connection *conn, int status,
 
   // Errors 1xx, 204 and 304 MUST NOT send a body
   if (status > 199 && status != 204 && status != 304) {
-    len = mg_snprintf(conn, buf, sizeof(buf), "Error %d: %s", status, reason);
+    len = mg_snprintf(buf, sizeof(buf), "Error %d: %s", status, reason);
     buf[len++] = '\n';
 
     va_start(ap, fmt);
-    len += mg_vsnprintf(conn, buf + len, sizeof(buf) - len, fmt, ap);
+    len += mg_vsnprintf(buf + len, sizeof(buf) - len, fmt, ap);
     va_end(ap);
   }
   DEBUG_TRACE(("[%s]", buf));
@@ -834,7 +586,7 @@ static pid_t spawn_process(struct mg_connection *conn, const char *prog,
   }
   GetFullPathNameA(dir, sizeof(full_dir), full_dir, NULL);
 
-  mg_snprintf(conn, cmdline, sizeof(cmdline), "%s%s\"%s\\%s\"",
+  mg_snprintf(cmdline, sizeof(cmdline), "%s%s\"%s\\%s\"",
               interp, interp[0] == '\0' ? "" : " ", full_dir, prog);
 
   DEBUG_TRACE(("Running [%s]", cmdline));
@@ -1311,12 +1063,12 @@ static int convert_uri_to_file_name(struct mg_connection *conn, char *buf,
   // Using buf_len - 1 because memmove() for PATH_INFO may shift part
   // of the path one byte on the right.
   // If document_root is NULL, leave the file empty.
-  mg_snprintf(conn, buf, buf_len - 1, "%s%s", root, uri);
+  mg_snprintf(buf, buf_len - 1, "%s%s", root, uri);
 
   rewrite = conn->ctx->config[REWRITE];
   while ((rewrite = next_option(rewrite, &a, &b)) != NULL) {
     if ((match_len = match_prefix(a.ptr, a.len, uri)) > 0) {
-      mg_snprintf(conn, buf, buf_len - 1, "%.*s%s", (int) b.len, b.ptr,
+      mg_snprintf(buf, buf_len - 1, "%.*s%s", (int) b.len, b.ptr,
                   uri + match_len);
       break;
     }
@@ -1827,7 +1579,7 @@ static FILE *open_auth_file(struct mg_connection *conn, const char *path) {
     // Important: using local struct file to test path for is_directory flag.
     // If filep is used, mg_stat() makes it appear as if auth file was opened.
   } else if (mg_stat(path, &file) && file.is_directory) {
-    mg_snprintf(conn, name, sizeof(name), "%s%c%s",
+    mg_snprintf(name, sizeof(name), "%s%c%s",
                 path, '/', PASSWORDS_FILE_NAME);
     fp = mg_fopen(name, "r");
   } else {
@@ -1835,7 +1587,7 @@ static FILE *open_auth_file(struct mg_connection *conn, const char *path) {
     for (p = path, e = p + strlen(p) - 1; e > p; e--)
       if (e[0] == '/')
         break;
-    mg_snprintf(conn, name, sizeof(name), "%.*s%c%s",
+    mg_snprintf(name, sizeof(name), "%.*s%c%s",
                 (int) (e - p), p, '/', PASSWORDS_FILE_NAME);
     fp = mg_fopen(name, "r");
   }
@@ -1947,7 +1699,7 @@ static int check_authorization(struct mg_connection *conn, const char *path) {
   list = conn->ctx->config[PROTECT_URI];
   while ((list = next_option(list, &uri_vec, &filename_vec)) != NULL) {
     if (!memcmp(conn->request_info.uri, uri_vec.ptr, uri_vec.len)) {
-      mg_snprintf(conn, fname, sizeof(fname), "%.*s",
+      mg_snprintf(fname, sizeof(fname), "%.*s",
                   (int) filename_vec.len, filename_vec.ptr);
       if ((fp = mg_fopen(fname, "r")) == NULL) {
         cry(conn, "%s: cannot open %s: %s", __func__, fname, strerror(errno));
@@ -2112,20 +1864,20 @@ static void print_dir_entry(const struct de *de) {
   const char *slash = de->file.is_directory ? "/" : "";
 
   if (de->file.is_directory) {
-    mg_snprintf(de->conn, size, sizeof(size), "%s", "[DIRECTORY]");
+    mg_snprintf(size, sizeof(size), "%s", "[DIRECTORY]");
   } else {
      // We use (signed) cast below because MSVC 6 compiler cannot
      // convert unsigned __int64 to double. Sigh.
     if (de->file.size < 1024) {
-      mg_snprintf(de->conn, size, sizeof(size), "%d", (int) de->file.size);
+      mg_snprintf(size, sizeof(size), "%d", (int) de->file.size);
     } else if (de->file.size < 0x100000) {
-      mg_snprintf(de->conn, size, sizeof(size),
+      mg_snprintf(size, sizeof(size),
                   "%.1fk", (double) de->file.size / 1024.0);
     } else if (de->file.size < 0x40000000) {
-      mg_snprintf(de->conn, size, sizeof(size),
+      mg_snprintf(size, sizeof(size),
                   "%.1fM", (double) de->file.size / 1048576);
     } else {
-      mg_snprintf(de->conn, size, sizeof(size),
+      mg_snprintf(size, sizeof(size),
                   "%.1fG", (double) de->file.size / 1073741824);
     }
   }
@@ -2195,7 +1947,7 @@ static int scan_directory(struct mg_connection *conn, const char *dir,
         continue;
       }
 
-      mg_snprintf(conn, path, sizeof(path), "%s%c%s", dir, '/', dp->d_name);
+      mg_snprintf(path, sizeof(path), "%s%c%s", dir, '/', dp->d_name);
 
       // If we don't memset stat structure to zero, mtime will have
       // garbage and strftime() will segfault later on in
@@ -2231,7 +1983,7 @@ static int remove_directory(struct mg_connection *conn, const char *dir) {
         continue;
       }
 
-      mg_snprintf(conn, path, sizeof(path), "%s%c%s", dir, '/', dp->d_name);
+      mg_snprintf(path, sizeof(path), "%s%c%s", dir, '/', dp->d_name);
 
       // If we don't memset stat structure to zero, mtime will have
       // garbage and strftime() will segfault later on in
@@ -2447,7 +2199,7 @@ static void handle_file_request(struct mg_connection *conn, const char *path,
     }
     conn->status_code = 206;
     cl = n == 2 ? (r2 > cl ? cl : r2) - r1 + 1: cl - r1;
-    mg_snprintf(conn, range, sizeof(range),
+    mg_snprintf(range, sizeof(range),
                 "Content-Range: bytes "
                 "%" INT64_FMT "-%"
                 INT64_FMT "/%" INT64_FMT "\r\n",
@@ -2724,7 +2476,7 @@ static char *addenv(struct cgi_env_block *block, const char *fmt, ...) {
 
   // Copy VARIABLE=VALUE\0 string into the free space
   va_start(ap, fmt);
-  n = mg_vsnprintf(block->conn, added, (size_t) space, fmt, ap);
+  n = mg_vsnprintf(added, (size_t) space, fmt, ap);
   va_end(ap);
 
   // Make sure we do not overflow buffer and the envp array
@@ -2877,7 +2629,7 @@ static void handle_cgi_request(struct mg_connection *conn, const char *prog) {
   // CGI must be executed in its own directory. 'dir' must point to the
   // directory containing executable program, 'p' must point to the
   // executable program name relative to 'dir'.
-  (void) mg_snprintf(conn, dir, sizeof(dir), "%s", prog);
+  (void) mg_snprintf(dir, sizeof(dir), "%s", prog);
   if ((p = strrchr(dir, '/')) != NULL) {
     *p++ = '\0';
   } else {
@@ -3130,20 +2882,20 @@ static void do_ssi_include(struct mg_connection *conn, const char *ssi,
   // of size MG_BUF_LEN to get the tag. So strlen(tag) is always < MG_BUF_LEN.
   if (sscanf(tag, " virtual=\"%[^\"]\"", file_name) == 1) {
     // File name is relative to the webserver root
-    (void) mg_snprintf(conn, path, sizeof(path), "%s%c%s",
+    (void) mg_snprintf(path, sizeof(path), "%s%c%s",
         conn->ctx->config[DOCUMENT_ROOT], '/', file_name);
   } else if (sscanf(tag, " abspath=\"%[^\"]\"", file_name) == 1) {
     // File name is relative to the webserver working directory
     // or it is absolute system path
-    (void) mg_snprintf(conn, path, sizeof(path), "%s", file_name);
+    (void) mg_snprintf(path, sizeof(path), "%s", file_name);
   } else if (sscanf(tag, " file=\"%[^\"]\"", file_name) == 1 ||
              sscanf(tag, " \"%[^\"]\"", file_name) == 1) {
     // File name is relative to the currect document
-    (void) mg_snprintf(conn, path, sizeof(path), "%s", ssi);
+    (void) mg_snprintf(path, sizeof(path), "%s", ssi);
     if ((p = strrchr(path, '/')) != NULL) {
       p[1] = '\0';
     }
-    (void) mg_snprintf(conn, path + strlen(path),
+    (void) mg_snprintf(path + strlen(path),
         sizeof(path) - strlen(path), "%s", file_name);
   } else {
     cry(conn, "Bad SSI #include: [%s]", tag);
@@ -3301,7 +3053,7 @@ static void print_dav_dir_entry(struct de *de, void *data) {
   char href[PATH_MAX];
   char href_encoded[PATH_MAX];
   struct mg_connection *conn = (struct mg_connection *) data;
-  mg_snprintf(conn, href, sizeof(href), "%s%s",
+  mg_snprintf(href, sizeof(href), "%s%s",
               conn->request_info.uri, de->file_name);
   mg_url_encode(href, href_encoded, PATH_MAX-1);
   print_props(conn, href_encoded, &de->file);
@@ -3493,7 +3245,7 @@ void mg_websocket_handshake(struct mg_connection *conn) {
   char buf[100], sha[20], b64_sha[sizeof(sha) * 2];
   SHA1_CTX sha_ctx;
 
-  mg_snprintf(conn, buf, sizeof(buf), "%s%s",
+  mg_snprintf(buf, sizeof(buf), "%s%s",
               mg_get_header(conn, "Sec-WebSocket-Key"), magic);
   SHA1Init(&sha_ctx);
   SHA1Update(&sha_ctx, (unsigned char *) buf, strlen(buf));
diff --git a/build/src/string.c b/build/src/string.c
new file mode 100644
index 0000000000000000000000000000000000000000..226d8f3631fc855915b6c9642d2f2583b010f529
--- /dev/null
+++ b/build/src/string.c
@@ -0,0 +1,245 @@
+#include "internal.h"
+
+static void mg_strlcpy(register char *dst, register const char *src, size_t n) {
+  for (; *src != '\0' && n > 1; n--) {
+    *dst++ = *src++;
+  }
+  *dst = '\0';
+}
+
+static int lowercase(const char *s) {
+  return tolower(* (const unsigned char *) s);
+}
+
+static int mg_strncasecmp(const char *s1, const char *s2, size_t len) {
+  int diff = 0;
+
+  if (len > 0)
+    do {
+      diff = lowercase(s1++) - lowercase(s2++);
+    } while (diff == 0 && s1[-1] != '\0' && --len > 0);
+
+  return diff;
+}
+
+static int mg_strcasecmp(const char *s1, const char *s2) {
+  int diff;
+
+  do {
+    diff = lowercase(s1++) - lowercase(s2++);
+  } while (diff == 0 && s1[-1] != '\0');
+
+  return diff;
+}
+
+static char * mg_strndup(const char *ptr, size_t len) {
+  char *p;
+
+  if ((p = (char *) malloc(len + 1)) != NULL) {
+    mg_strlcpy(p, ptr, len + 1);
+  }
+
+  return p;
+}
+
+static char * mg_strdup(const char *str) {
+  return mg_strndup(str, strlen(str));
+}
+
+static const char *mg_strcasestr(const char *big_str, const char *small_str) {
+  int i, big_len = strlen(big_str), small_len = strlen(small_str);
+
+  for (i = 0; i <= big_len - small_len; i++) {
+    if (mg_strncasecmp(big_str + i, small_str, small_len) == 0) {
+      return big_str + i;
+    }
+  }
+
+  return NULL;
+}
+
+// Like snprintf(), but never returns negative value, or a value
+// that is larger than a supplied buffer.
+// Thanks to Adam Zeldis to pointing snprintf()-caused vulnerability
+// in his audit report.
+static int mg_vsnprintf(char *buf, size_t buflen, const char *fmt, va_list ap) {
+  int n;
+
+  if (buflen == 0) {
+    return 0;
+  }
+
+  n = vsnprintf(buf, buflen, fmt, ap);
+
+  if (n < 0) {
+    n = 0;
+  } else if (n >= (int) buflen) {
+    n = (int) buflen - 1;
+  }
+  buf[n] = '\0';
+
+  return n;
+}
+
+static int mg_snprintf(char *buf, size_t buflen,
+    PRINTF_FORMAT_STRING(const char *fmt), ...) PRINTF_ARGS(3, 4);
+
+static int mg_snprintf(char *buf, size_t buflen, const char *fmt, ...) {
+  va_list ap;
+  int n;
+
+  va_start(ap, fmt);
+  n = mg_vsnprintf(buf, buflen, fmt, ap);
+  va_end(ap);
+
+  return n;
+}
+
+// Skip the characters until one of the delimiters characters found.
+// 0-terminate resulting word. Skip the delimiter and following whitespaces.
+// Advance pointer to buffer to the next word. Return found 0-terminated word.
+// Delimiters can be quoted with quotechar.
+static char *skip_quoted(char **buf, const char *delimiters,
+                         const char *whitespace, char quotechar) {
+  char *p, *begin_word, *end_word, *end_whitespace;
+
+  begin_word = *buf;
+  end_word = begin_word + strcspn(begin_word, delimiters);
+
+  // Check for quotechar
+  if (end_word > begin_word) {
+    p = end_word - 1;
+    while (*p == quotechar) {
+      // If there is anything beyond end_word, copy it
+      if (*end_word == '\0') {
+        *p = '\0';
+        break;
+      } else {
+        size_t end_off = strcspn(end_word + 1, delimiters);
+        memmove (p, end_word, end_off + 1);
+        p += end_off; // p must correspond to end_word - 1
+        end_word += end_off + 1;
+      }
+    }
+    for (p++; p < end_word; p++) {
+      *p = '\0';
+    }
+  }
+
+  if (*end_word == '\0') {
+    *buf = end_word;
+  } else {
+    end_whitespace = end_word + 1 + strspn(end_word + 1, whitespace);
+
+    for (p = end_word; p < end_whitespace; p++) {
+      *p = '\0';
+    }
+
+    *buf = end_whitespace;
+  }
+
+  return begin_word;
+}
+
+// Simplified version of skip_quoted without quote char
+// and whitespace == delimiters
+static char *skip(char **buf, const char *delimiters) {
+  return skip_quoted(buf, delimiters, delimiters, 0);
+}
+
+
+// Return HTTP header value, or NULL if not found.
+static const char *get_header(const struct mg_request_info *ri,
+                              const char *name) {
+  int i;
+
+  for (i = 0; i < ri->num_headers; i++)
+    if (!mg_strcasecmp(name, ri->http_headers[i].name))
+      return ri->http_headers[i].value;
+
+  return NULL;
+}
+
+const char *mg_get_header(const struct mg_connection *conn, const char *name) {
+  return get_header(&conn->request_info, name);
+}
+
+// A helper function for traversing a comma separated list of values.
+// It returns a list pointer shifted to the next value, or NULL if the end
+// of the list found.
+// Value is stored in val vector. If value has form "x=y", then eq_val
+// vector is initialized to point to the "y" part, and val vector length
+// is adjusted to point only to "x".
+static const char *next_option(const char *list, struct vec *val,
+                               struct vec *eq_val) {
+  if (list == NULL || *list == '\0') {
+    // End of the list
+    list = NULL;
+  } else {
+    val->ptr = list;
+    if ((list = strchr(val->ptr, ',')) != NULL) {
+      // Comma found. Store length and shift the list ptr
+      val->len = list - val->ptr;
+      list++;
+    } else {
+      // This value is the last one
+      list = val->ptr + strlen(val->ptr);
+      val->len = list - val->ptr;
+    }
+
+    if (eq_val != NULL) {
+      // Value has form "x=y", adjust pointers and lengths
+      // so that val points to "x", and eq_val points to "y".
+      eq_val->len = 0;
+      eq_val->ptr = (const char *) memchr(val->ptr, '=', val->len);
+      if (eq_val->ptr != NULL) {
+        eq_val->ptr++;  // Skip over '=' character
+        eq_val->len = val->ptr + val->len - eq_val->ptr;
+        val->len = (eq_val->ptr - val->ptr) - 1;
+      }
+    }
+  }
+
+  return list;
+}
+
+// Perform case-insensitive match of string against pattern
+static int match_prefix(const char *pattern, int pattern_len, const char *str) {
+  const char *or_str;
+  int i, j, len, res;
+
+  if ((or_str = (const char *) memchr(pattern, '|', pattern_len)) != NULL) {
+    res = match_prefix(pattern, or_str - pattern, str);
+    return res > 0 ? res :
+        match_prefix(or_str + 1, (pattern + pattern_len) - (or_str + 1), str);
+  }
+
+  i = j = 0;
+  res = -1;
+  for (; i < pattern_len; i++, j++) {
+    if (pattern[i] == '?' && str[j] != '\0') {
+      continue;
+    } else if (pattern[i] == '$') {
+      return str[j] == '\0' ? j : -1;
+    } else if (pattern[i] == '*') {
+      i++;
+      if (pattern[i] == '*') {
+        i++;
+        len = (int) strlen(str + j);
+      } else {
+        len = (int) strcspn(str + j, "/");
+      }
+      if (i == pattern_len) {
+        return j + len;
+      }
+      do {
+        res = match_prefix(pattern + i, pattern_len - i, str + j + len);
+      } while (res == -1 && len-- > 0);
+      return res == -1 ? -1 : j + res + len;
+    } else if (lowercase(&pattern[i]) != lowercase(&str[j])) {
+      return -1;
+    }
+  }
+  return j;
+}
+
diff --git a/mongoose.c b/mongoose.c
index d2be1a2062f2caa0676184b5809fc0a96aaa8170..9cc8604149bdf7718d6f57444ff2f9c20deea9b2 100644
--- a/mongoose.c
+++ b/mongoose.c
@@ -458,6 +458,250 @@ struct de {
   struct file file;
 };
 
+
+static void mg_strlcpy(register char *dst, register const char *src, size_t n) {
+  for (; *src != '\0' && n > 1; n--) {
+    *dst++ = *src++;
+  }
+  *dst = '\0';
+}
+
+static int lowercase(const char *s) {
+  return tolower(* (const unsigned char *) s);
+}
+
+static int mg_strncasecmp(const char *s1, const char *s2, size_t len) {
+  int diff = 0;
+
+  if (len > 0)
+    do {
+      diff = lowercase(s1++) - lowercase(s2++);
+    } while (diff == 0 && s1[-1] != '\0' && --len > 0);
+
+  return diff;
+}
+
+static int mg_strcasecmp(const char *s1, const char *s2) {
+  int diff;
+
+  do {
+    diff = lowercase(s1++) - lowercase(s2++);
+  } while (diff == 0 && s1[-1] != '\0');
+
+  return diff;
+}
+
+static char * mg_strndup(const char *ptr, size_t len) {
+  char *p;
+
+  if ((p = (char *) malloc(len + 1)) != NULL) {
+    mg_strlcpy(p, ptr, len + 1);
+  }
+
+  return p;
+}
+
+static char * mg_strdup(const char *str) {
+  return mg_strndup(str, strlen(str));
+}
+
+static const char *mg_strcasestr(const char *big_str, const char *small_str) {
+  int i, big_len = strlen(big_str), small_len = strlen(small_str);
+
+  for (i = 0; i <= big_len - small_len; i++) {
+    if (mg_strncasecmp(big_str + i, small_str, small_len) == 0) {
+      return big_str + i;
+    }
+  }
+
+  return NULL;
+}
+
+// Like snprintf(), but never returns negative value, or a value
+// that is larger than a supplied buffer.
+// Thanks to Adam Zeldis to pointing snprintf()-caused vulnerability
+// in his audit report.
+static int mg_vsnprintf(char *buf, size_t buflen, const char *fmt, va_list ap) {
+  int n;
+
+  if (buflen == 0) {
+    return 0;
+  }
+
+  n = vsnprintf(buf, buflen, fmt, ap);
+
+  if (n < 0) {
+    n = 0;
+  } else if (n >= (int) buflen) {
+    n = (int) buflen - 1;
+  }
+  buf[n] = '\0';
+
+  return n;
+}
+
+static int mg_snprintf(char *buf, size_t buflen,
+    PRINTF_FORMAT_STRING(const char *fmt), ...) PRINTF_ARGS(3, 4);
+
+static int mg_snprintf(char *buf, size_t buflen, const char *fmt, ...) {
+  va_list ap;
+  int n;
+
+  va_start(ap, fmt);
+  n = mg_vsnprintf(buf, buflen, fmt, ap);
+  va_end(ap);
+
+  return n;
+}
+
+// Skip the characters until one of the delimiters characters found.
+// 0-terminate resulting word. Skip the delimiter and following whitespaces.
+// Advance pointer to buffer to the next word. Return found 0-terminated word.
+// Delimiters can be quoted with quotechar.
+static char *skip_quoted(char **buf, const char *delimiters,
+                         const char *whitespace, char quotechar) {
+  char *p, *begin_word, *end_word, *end_whitespace;
+
+  begin_word = *buf;
+  end_word = begin_word + strcspn(begin_word, delimiters);
+
+  // Check for quotechar
+  if (end_word > begin_word) {
+    p = end_word - 1;
+    while (*p == quotechar) {
+      // If there is anything beyond end_word, copy it
+      if (*end_word == '\0') {
+        *p = '\0';
+        break;
+      } else {
+        size_t end_off = strcspn(end_word + 1, delimiters);
+        memmove (p, end_word, end_off + 1);
+        p += end_off; // p must correspond to end_word - 1
+        end_word += end_off + 1;
+      }
+    }
+    for (p++; p < end_word; p++) {
+      *p = '\0';
+    }
+  }
+
+  if (*end_word == '\0') {
+    *buf = end_word;
+  } else {
+    end_whitespace = end_word + 1 + strspn(end_word + 1, whitespace);
+
+    for (p = end_word; p < end_whitespace; p++) {
+      *p = '\0';
+    }
+
+    *buf = end_whitespace;
+  }
+
+  return begin_word;
+}
+
+// Simplified version of skip_quoted without quote char
+// and whitespace == delimiters
+static char *skip(char **buf, const char *delimiters) {
+  return skip_quoted(buf, delimiters, delimiters, 0);
+}
+
+
+// Return HTTP header value, or NULL if not found.
+static const char *get_header(const struct mg_request_info *ri,
+                              const char *name) {
+  int i;
+
+  for (i = 0; i < ri->num_headers; i++)
+    if (!mg_strcasecmp(name, ri->http_headers[i].name))
+      return ri->http_headers[i].value;
+
+  return NULL;
+}
+
+const char *mg_get_header(const struct mg_connection *conn, const char *name) {
+  return get_header(&conn->request_info, name);
+}
+
+// A helper function for traversing a comma separated list of values.
+// It returns a list pointer shifted to the next value, or NULL if the end
+// of the list found.
+// Value is stored in val vector. If value has form "x=y", then eq_val
+// vector is initialized to point to the "y" part, and val vector length
+// is adjusted to point only to "x".
+static const char *next_option(const char *list, struct vec *val,
+                               struct vec *eq_val) {
+  if (list == NULL || *list == '\0') {
+    // End of the list
+    list = NULL;
+  } else {
+    val->ptr = list;
+    if ((list = strchr(val->ptr, ',')) != NULL) {
+      // Comma found. Store length and shift the list ptr
+      val->len = list - val->ptr;
+      list++;
+    } else {
+      // This value is the last one
+      list = val->ptr + strlen(val->ptr);
+      val->len = list - val->ptr;
+    }
+
+    if (eq_val != NULL) {
+      // Value has form "x=y", adjust pointers and lengths
+      // so that val points to "x", and eq_val points to "y".
+      eq_val->len = 0;
+      eq_val->ptr = (const char *) memchr(val->ptr, '=', val->len);
+      if (eq_val->ptr != NULL) {
+        eq_val->ptr++;  // Skip over '=' character
+        eq_val->len = val->ptr + val->len - eq_val->ptr;
+        val->len = (eq_val->ptr - val->ptr) - 1;
+      }
+    }
+  }
+
+  return list;
+}
+
+// Perform case-insensitive match of string against pattern
+static int match_prefix(const char *pattern, int pattern_len, const char *str) {
+  const char *or_str;
+  int i, j, len, res;
+
+  if ((or_str = (const char *) memchr(pattern, '|', pattern_len)) != NULL) {
+    res = match_prefix(pattern, or_str - pattern, str);
+    return res > 0 ? res :
+        match_prefix(or_str + 1, (pattern + pattern_len) - (or_str + 1), str);
+  }
+
+  i = j = 0;
+  res = -1;
+  for (; i < pattern_len; i++, j++) {
+    if (pattern[i] == '?' && str[j] != '\0') {
+      continue;
+    } else if (pattern[i] == '$') {
+      return str[j] == '\0' ? j : -1;
+    } else if (pattern[i] == '*') {
+      i++;
+      if (pattern[i] == '*') {
+        i++;
+        len = (int) strlen(str + j);
+      } else {
+        len = (int) strcspn(str + j, "/");
+      }
+      if (i == pattern_len) {
+        return j + len;
+      }
+      do {
+        res = match_prefix(pattern + i, pattern_len - i, str + j + len);
+      } while (res == -1 && len-- > 0);
+      return res == -1 ? -1 : j + res + len;
+    } else if (lowercase(&pattern[i]) != lowercase(&str[j])) {
+      return -1;
+    }
+  }
+  return j;
+}
+
 
 static const char *month_names[] = {
   "Jan", "Feb", "Mar", "Apr", "May", "Jun",
@@ -618,254 +862,6 @@ const char *mg_version(void) {
   return MONGOOSE_VERSION;
 }
 
-static void mg_strlcpy(register char *dst, register const char *src, size_t n) {
-  for (; *src != '\0' && n > 1; n--) {
-    *dst++ = *src++;
-  }
-  *dst = '\0';
-}
-
-static int lowercase(const char *s) {
-  return tolower(* (const unsigned char *) s);
-}
-
-static int mg_strncasecmp(const char *s1, const char *s2, size_t len) {
-  int diff = 0;
-
-  if (len > 0)
-    do {
-      diff = lowercase(s1++) - lowercase(s2++);
-    } while (diff == 0 && s1[-1] != '\0' && --len > 0);
-
-  return diff;
-}
-
-static int mg_strcasecmp(const char *s1, const char *s2) {
-  int diff;
-
-  do {
-    diff = lowercase(s1++) - lowercase(s2++);
-  } while (diff == 0 && s1[-1] != '\0');
-
-  return diff;
-}
-
-static char * mg_strndup(const char *ptr, size_t len) {
-  char *p;
-
-  if ((p = (char *) malloc(len + 1)) != NULL) {
-    mg_strlcpy(p, ptr, len + 1);
-  }
-
-  return p;
-}
-
-static char * mg_strdup(const char *str) {
-  return mg_strndup(str, strlen(str));
-}
-
-static const char *mg_strcasestr(const char *big_str, const char *small_str) {
-  int i, big_len = strlen(big_str), small_len = strlen(small_str);
-
-  for (i = 0; i <= big_len - small_len; i++) {
-    if (mg_strncasecmp(big_str + i, small_str, small_len) == 0) {
-      return big_str + i;
-    }
-  }
-
-  return NULL;
-}
-
-// Like snprintf(), but never returns negative value, or a value
-// that is larger than a supplied buffer.
-// Thanks to Adam Zeldis to pointing snprintf()-caused vulnerability
-// in his audit report.
-static int mg_vsnprintf(struct mg_connection *conn, char *buf, size_t buflen,
-                        const char *fmt, va_list ap) {
-  int n;
-
-  if (buflen == 0)
-    return 0;
-
-  n = vsnprintf(buf, buflen, fmt, ap);
-
-  if (n < 0) {
-    cry(conn, "vsnprintf error");
-    n = 0;
-  } else if (n >= (int) buflen) {
-    cry(conn, "truncating vsnprintf buffer: [%.*s]",
-        n > 200 ? 200 : n, buf);
-    n = (int) buflen - 1;
-  }
-  buf[n] = '\0';
-
-  return n;
-}
-
-static int mg_snprintf(struct mg_connection *conn, char *buf, size_t buflen,
-                       PRINTF_FORMAT_STRING(const char *fmt), ...)
-  PRINTF_ARGS(4, 5);
-
-static int mg_snprintf(struct mg_connection *conn, char *buf, size_t buflen,
-                       const char *fmt, ...) {
-  va_list ap;
-  int n;
-
-  va_start(ap, fmt);
-  n = mg_vsnprintf(conn, buf, buflen, fmt, ap);
-  va_end(ap);
-
-  return n;
-}
-
-// Skip the characters until one of the delimiters characters found.
-// 0-terminate resulting word. Skip the delimiter and following whitespaces.
-// Advance pointer to buffer to the next word. Return found 0-terminated word.
-// Delimiters can be quoted with quotechar.
-static char *skip_quoted(char **buf, const char *delimiters,
-                         const char *whitespace, char quotechar) {
-  char *p, *begin_word, *end_word, *end_whitespace;
-
-  begin_word = *buf;
-  end_word = begin_word + strcspn(begin_word, delimiters);
-
-  // Check for quotechar
-  if (end_word > begin_word) {
-    p = end_word - 1;
-    while (*p == quotechar) {
-      // If there is anything beyond end_word, copy it
-      if (*end_word == '\0') {
-        *p = '\0';
-        break;
-      } else {
-        size_t end_off = strcspn(end_word + 1, delimiters);
-        memmove (p, end_word, end_off + 1);
-        p += end_off; // p must correspond to end_word - 1
-        end_word += end_off + 1;
-      }
-    }
-    for (p++; p < end_word; p++) {
-      *p = '\0';
-    }
-  }
-
-  if (*end_word == '\0') {
-    *buf = end_word;
-  } else {
-    end_whitespace = end_word + 1 + strspn(end_word + 1, whitespace);
-
-    for (p = end_word; p < end_whitespace; p++) {
-      *p = '\0';
-    }
-
-    *buf = end_whitespace;
-  }
-
-  return begin_word;
-}
-
-// Simplified version of skip_quoted without quote char
-// and whitespace == delimiters
-static char *skip(char **buf, const char *delimiters) {
-  return skip_quoted(buf, delimiters, delimiters, 0);
-}
-
-
-// Return HTTP header value, or NULL if not found.
-static const char *get_header(const struct mg_request_info *ri,
-                              const char *name) {
-  int i;
-
-  for (i = 0; i < ri->num_headers; i++)
-    if (!mg_strcasecmp(name, ri->http_headers[i].name))
-      return ri->http_headers[i].value;
-
-  return NULL;
-}
-
-const char *mg_get_header(const struct mg_connection *conn, const char *name) {
-  return get_header(&conn->request_info, name);
-}
-
-// A helper function for traversing a comma separated list of values.
-// It returns a list pointer shifted to the next value, or NULL if the end
-// of the list found.
-// Value is stored in val vector. If value has form "x=y", then eq_val
-// vector is initialized to point to the "y" part, and val vector length
-// is adjusted to point only to "x".
-static const char *next_option(const char *list, struct vec *val,
-                               struct vec *eq_val) {
-  if (list == NULL || *list == '\0') {
-    // End of the list
-    list = NULL;
-  } else {
-    val->ptr = list;
-    if ((list = strchr(val->ptr, ',')) != NULL) {
-      // Comma found. Store length and shift the list ptr
-      val->len = list - val->ptr;
-      list++;
-    } else {
-      // This value is the last one
-      list = val->ptr + strlen(val->ptr);
-      val->len = list - val->ptr;
-    }
-
-    if (eq_val != NULL) {
-      // Value has form "x=y", adjust pointers and lengths
-      // so that val points to "x", and eq_val points to "y".
-      eq_val->len = 0;
-      eq_val->ptr = (const char *) memchr(val->ptr, '=', val->len);
-      if (eq_val->ptr != NULL) {
-        eq_val->ptr++;  // Skip over '=' character
-        eq_val->len = val->ptr + val->len - eq_val->ptr;
-        val->len = (eq_val->ptr - val->ptr) - 1;
-      }
-    }
-  }
-
-  return list;
-}
-
-// Perform case-insensitive match of string against pattern
-static int match_prefix(const char *pattern, int pattern_len, const char *str) {
-  const char *or_str;
-  int i, j, len, res;
-
-  if ((or_str = (const char *) memchr(pattern, '|', pattern_len)) != NULL) {
-    res = match_prefix(pattern, or_str - pattern, str);
-    return res > 0 ? res :
-        match_prefix(or_str + 1, (pattern + pattern_len) - (or_str + 1), str);
-  }
-
-  i = j = 0;
-  res = -1;
-  for (; i < pattern_len; i++, j++) {
-    if (pattern[i] == '?' && str[j] != '\0') {
-      continue;
-    } else if (pattern[i] == '$') {
-      return str[j] == '\0' ? j : -1;
-    } else if (pattern[i] == '*') {
-      i++;
-      if (pattern[i] == '*') {
-        i++;
-        len = (int) strlen(str + j);
-      } else {
-        len = (int) strcspn(str + j, "/");
-      }
-      if (i == pattern_len) {
-        return j + len;
-      }
-      do {
-        res = match_prefix(pattern + i, pattern_len - i, str + j + len);
-      } while (res == -1 && len-- > 0);
-      return res == -1 ? -1 : j + res + len;
-    } else if (lowercase(&pattern[i]) != lowercase(&str[j])) {
-      return -1;
-    }
-  }
-  return j;
-}
-
 // HTTP 1.1 assumes keep alive if "Connection:" header is not set
 // This function must tolerate situations when connection info is not
 // set up, for example if request parsing failed.
@@ -902,11 +898,11 @@ static void send_http_error(struct mg_connection *conn, int status,
 
   // Errors 1xx, 204 and 304 MUST NOT send a body
   if (status > 199 && status != 204 && status != 304) {
-    len = mg_snprintf(conn, buf, sizeof(buf), "Error %d: %s", status, reason);
+    len = mg_snprintf(buf, sizeof(buf), "Error %d: %s", status, reason);
     buf[len++] = '\n';
 
     va_start(ap, fmt);
-    len += mg_vsnprintf(conn, buf + len, sizeof(buf) - len, fmt, ap);
+    len += mg_vsnprintf(buf + len, sizeof(buf) - len, fmt, ap);
     va_end(ap);
   }
   DEBUG_TRACE(("[%s]", buf));
@@ -1293,7 +1289,7 @@ static pid_t spawn_process(struct mg_connection *conn, const char *prog,
   }
   GetFullPathNameA(dir, sizeof(full_dir), full_dir, NULL);
 
-  mg_snprintf(conn, cmdline, sizeof(cmdline), "%s%s\"%s\\%s\"",
+  mg_snprintf(cmdline, sizeof(cmdline), "%s%s\"%s\\%s\"",
               interp, interp[0] == '\0' ? "" : " ", full_dir, prog);
 
   DEBUG_TRACE(("Running [%s]", cmdline));
@@ -1770,12 +1766,12 @@ static int convert_uri_to_file_name(struct mg_connection *conn, char *buf,
   // Using buf_len - 1 because memmove() for PATH_INFO may shift part
   // of the path one byte on the right.
   // If document_root is NULL, leave the file empty.
-  mg_snprintf(conn, buf, buf_len - 1, "%s%s", root, uri);
+  mg_snprintf(buf, buf_len - 1, "%s%s", root, uri);
 
   rewrite = conn->ctx->config[REWRITE];
   while ((rewrite = next_option(rewrite, &a, &b)) != NULL) {
     if ((match_len = match_prefix(a.ptr, a.len, uri)) > 0) {
-      mg_snprintf(conn, buf, buf_len - 1, "%.*s%s", (int) b.len, b.ptr,
+      mg_snprintf(buf, buf_len - 1, "%.*s%s", (int) b.len, b.ptr,
                   uri + match_len);
       break;
     }
@@ -2286,7 +2282,7 @@ static FILE *open_auth_file(struct mg_connection *conn, const char *path) {
     // Important: using local struct file to test path for is_directory flag.
     // If filep is used, mg_stat() makes it appear as if auth file was opened.
   } else if (mg_stat(path, &file) && file.is_directory) {
-    mg_snprintf(conn, name, sizeof(name), "%s%c%s",
+    mg_snprintf(name, sizeof(name), "%s%c%s",
                 path, '/', PASSWORDS_FILE_NAME);
     fp = mg_fopen(name, "r");
   } else {
@@ -2294,7 +2290,7 @@ static FILE *open_auth_file(struct mg_connection *conn, const char *path) {
     for (p = path, e = p + strlen(p) - 1; e > p; e--)
       if (e[0] == '/')
         break;
-    mg_snprintf(conn, name, sizeof(name), "%.*s%c%s",
+    mg_snprintf(name, sizeof(name), "%.*s%c%s",
                 (int) (e - p), p, '/', PASSWORDS_FILE_NAME);
     fp = mg_fopen(name, "r");
   }
@@ -2406,7 +2402,7 @@ static int check_authorization(struct mg_connection *conn, const char *path) {
   list = conn->ctx->config[PROTECT_URI];
   while ((list = next_option(list, &uri_vec, &filename_vec)) != NULL) {
     if (!memcmp(conn->request_info.uri, uri_vec.ptr, uri_vec.len)) {
-      mg_snprintf(conn, fname, sizeof(fname), "%.*s",
+      mg_snprintf(fname, sizeof(fname), "%.*s",
                   (int) filename_vec.len, filename_vec.ptr);
       if ((fp = mg_fopen(fname, "r")) == NULL) {
         cry(conn, "%s: cannot open %s: %s", __func__, fname, strerror(errno));
@@ -2571,20 +2567,20 @@ static void print_dir_entry(const struct de *de) {
   const char *slash = de->file.is_directory ? "/" : "";
 
   if (de->file.is_directory) {
-    mg_snprintf(de->conn, size, sizeof(size), "%s", "[DIRECTORY]");
+    mg_snprintf(size, sizeof(size), "%s", "[DIRECTORY]");
   } else {
      // We use (signed) cast below because MSVC 6 compiler cannot
      // convert unsigned __int64 to double. Sigh.
     if (de->file.size < 1024) {
-      mg_snprintf(de->conn, size, sizeof(size), "%d", (int) de->file.size);
+      mg_snprintf(size, sizeof(size), "%d", (int) de->file.size);
     } else if (de->file.size < 0x100000) {
-      mg_snprintf(de->conn, size, sizeof(size),
+      mg_snprintf(size, sizeof(size),
                   "%.1fk", (double) de->file.size / 1024.0);
     } else if (de->file.size < 0x40000000) {
-      mg_snprintf(de->conn, size, sizeof(size),
+      mg_snprintf(size, sizeof(size),
                   "%.1fM", (double) de->file.size / 1048576);
     } else {
-      mg_snprintf(de->conn, size, sizeof(size),
+      mg_snprintf(size, sizeof(size),
                   "%.1fG", (double) de->file.size / 1073741824);
     }
   }
@@ -2654,7 +2650,7 @@ static int scan_directory(struct mg_connection *conn, const char *dir,
         continue;
       }
 
-      mg_snprintf(conn, path, sizeof(path), "%s%c%s", dir, '/', dp->d_name);
+      mg_snprintf(path, sizeof(path), "%s%c%s", dir, '/', dp->d_name);
 
       // If we don't memset stat structure to zero, mtime will have
       // garbage and strftime() will segfault later on in
@@ -2690,7 +2686,7 @@ static int remove_directory(struct mg_connection *conn, const char *dir) {
         continue;
       }
 
-      mg_snprintf(conn, path, sizeof(path), "%s%c%s", dir, '/', dp->d_name);
+      mg_snprintf(path, sizeof(path), "%s%c%s", dir, '/', dp->d_name);
 
       // If we don't memset stat structure to zero, mtime will have
       // garbage and strftime() will segfault later on in
@@ -2906,7 +2902,7 @@ static void handle_file_request(struct mg_connection *conn, const char *path,
     }
     conn->status_code = 206;
     cl = n == 2 ? (r2 > cl ? cl : r2) - r1 + 1: cl - r1;
-    mg_snprintf(conn, range, sizeof(range),
+    mg_snprintf(range, sizeof(range),
                 "Content-Range: bytes "
                 "%" INT64_FMT "-%"
                 INT64_FMT "/%" INT64_FMT "\r\n",
@@ -3183,7 +3179,7 @@ static char *addenv(struct cgi_env_block *block, const char *fmt, ...) {
 
   // Copy VARIABLE=VALUE\0 string into the free space
   va_start(ap, fmt);
-  n = mg_vsnprintf(block->conn, added, (size_t) space, fmt, ap);
+  n = mg_vsnprintf(added, (size_t) space, fmt, ap);
   va_end(ap);
 
   // Make sure we do not overflow buffer and the envp array
@@ -3336,7 +3332,7 @@ static void handle_cgi_request(struct mg_connection *conn, const char *prog) {
   // CGI must be executed in its own directory. 'dir' must point to the
   // directory containing executable program, 'p' must point to the
   // executable program name relative to 'dir'.
-  (void) mg_snprintf(conn, dir, sizeof(dir), "%s", prog);
+  (void) mg_snprintf(dir, sizeof(dir), "%s", prog);
   if ((p = strrchr(dir, '/')) != NULL) {
     *p++ = '\0';
   } else {
@@ -3589,20 +3585,20 @@ static void do_ssi_include(struct mg_connection *conn, const char *ssi,
   // of size MG_BUF_LEN to get the tag. So strlen(tag) is always < MG_BUF_LEN.
   if (sscanf(tag, " virtual=\"%[^\"]\"", file_name) == 1) {
     // File name is relative to the webserver root
-    (void) mg_snprintf(conn, path, sizeof(path), "%s%c%s",
+    (void) mg_snprintf(path, sizeof(path), "%s%c%s",
         conn->ctx->config[DOCUMENT_ROOT], '/', file_name);
   } else if (sscanf(tag, " abspath=\"%[^\"]\"", file_name) == 1) {
     // File name is relative to the webserver working directory
     // or it is absolute system path
-    (void) mg_snprintf(conn, path, sizeof(path), "%s", file_name);
+    (void) mg_snprintf(path, sizeof(path), "%s", file_name);
   } else if (sscanf(tag, " file=\"%[^\"]\"", file_name) == 1 ||
              sscanf(tag, " \"%[^\"]\"", file_name) == 1) {
     // File name is relative to the currect document
-    (void) mg_snprintf(conn, path, sizeof(path), "%s", ssi);
+    (void) mg_snprintf(path, sizeof(path), "%s", ssi);
     if ((p = strrchr(path, '/')) != NULL) {
       p[1] = '\0';
     }
-    (void) mg_snprintf(conn, path + strlen(path),
+    (void) mg_snprintf(path + strlen(path),
         sizeof(path) - strlen(path), "%s", file_name);
   } else {
     cry(conn, "Bad SSI #include: [%s]", tag);
@@ -3760,7 +3756,7 @@ static void print_dav_dir_entry(struct de *de, void *data) {
   char href[PATH_MAX];
   char href_encoded[PATH_MAX];
   struct mg_connection *conn = (struct mg_connection *) data;
-  mg_snprintf(conn, href, sizeof(href), "%s%s",
+  mg_snprintf(href, sizeof(href), "%s%s",
               conn->request_info.uri, de->file_name);
   mg_url_encode(href, href_encoded, PATH_MAX-1);
   print_props(conn, href_encoded, &de->file);
@@ -3952,7 +3948,7 @@ void mg_websocket_handshake(struct mg_connection *conn) {
   char buf[100], sha[20], b64_sha[sizeof(sha) * 2];
   SHA1_CTX sha_ctx;
 
-  mg_snprintf(conn, buf, sizeof(buf), "%s%s",
+  mg_snprintf(buf, sizeof(buf), "%s%s",
               mg_get_header(conn, "Sec-WebSocket-Key"), magic);
   SHA1Init(&sha_ctx);
   SHA1Update(&sha_ctx, (unsigned char *) buf, strlen(buf));