valenok 13 rokov pred
rodič
commit
01c5ee0973
2 zmenil súbory, kde vykonal 60 pridanie a 2 odobranie
  1. 47 2
      mongoose.c
  2. 13 0
      test/unit_test.c

+ 47 - 2
mongoose.c

@@ -405,7 +405,7 @@ enum {
   GLOBAL_PASSWORDS_FILE, INDEX_FILES,
   ENABLE_KEEP_ALIVE, ACCESS_CONTROL_LIST, MAX_REQUEST_SIZE,
   EXTRA_MIME_TYPES, LISTENING_PORTS,
-  DOCUMENT_ROOT, SSL_CERTIFICATE, NUM_THREADS, RUN_AS_USER,
+  DOCUMENT_ROOT, SSL_CERTIFICATE, NUM_THREADS, RUN_AS_USER, REWRITE,
   NUM_OPTIONS
 };
 
@@ -432,6 +432,7 @@ static const char *config_options[] = {
   "s", "ssl_certificate", NULL,
   "t", "num_threads", "10",
   "u", "run_as_user", NULL,
+  "w", "rewrite", NULL,
   NULL
 };
 #define ENTRIES_PER_CONFIG_OPTION 3
@@ -1544,15 +1545,59 @@ static int get_document_root(const struct mg_connection *conn,
   return len_of_matched_uri;
 }
 
+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 = memchr(pattern, '|', pattern_len)) != NULL) {
+    res = match_prefix(or_str + 1, (pattern + pattern_len) - (or_str + 1), str);
+    return res > 0 ? res : match_prefix(pattern, or_str - pattern, str);
+  }
+
+  i = j = res = 0;
+  for (; i < pattern_len; i++, j++) {
+    if (pattern[i] == '?' && str[j] != '\0') {
+      continue;
+    } else if (pattern[i] == '*') {
+      i++;
+      if (pattern[i] == '*') {
+        i++;
+        len = strlen(str + j);
+      } else {
+        len = strcspn(str + j, "/");
+      }
+      if (i == pattern_len) {
+        return j + len;
+      }
+      do {
+        res = match_prefix(pattern + i, pattern_len - i, str + j + len);
+      } while (res == 0 && len-- > 0);
+      return res == 0 ? 0 : j + res + len;
+    } else if (pattern[i] != str[j]) {
+      return 0;
+    }
+  }
+  return j;
+}
+
 static void convert_uri_to_file_name(struct mg_connection *conn,
                                      const char *uri, char *buf,
                                      size_t buf_len) {
-  struct vec vec;
+  struct vec vec, a, b;
+  const char *rewrite;
   int match_len;
 
   match_len = get_document_root(conn, &vec);
   mg_snprintf(conn, buf, buf_len, "%.*s%s", vec.len, vec.ptr, uri + match_len);
 
+  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, "%.*s%s", b.len, b.ptr, uri + match_len);
+      break;
+    }
+  }
+
 #if defined(_WIN32) && !defined(__SYMBIAN32__)
   change_slashes_to_backslashes(buf);
 #endif // _WIN32

+ 13 - 0
test/unit_test.c

@@ -0,0 +1,13 @@
+#include "mongoose.c"
+
+int main(void) {
+  assert(match_prefix("/a/", 3, "/a/b/c") == 3);
+  assert(match_prefix("/a/", 3, "/ab/c") == 0);
+  assert(match_prefix("/*/", 3, "/ab/c") == 4);
+  assert(match_prefix("**", 2, "/a/b/c") == 6);
+  assert(match_prefix("/*", 2, "/a/b/c") == 2);
+  assert(match_prefix("*/*", 3, "/a/b/c") == 2);
+  assert(match_prefix("**/", 3, "/a/b/c") == 5);
+
+  return 0;
+}