int mg_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 = mg_match_prefix(pattern, or_str - pattern, str); return res > 0 ? res : mg_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 = mg_match_prefix(pattern + i, pattern_len - i, str + j + len); } while (res == -1 && len-- > 0); return res == -1 ? -1 : j + res + len; } else if (pattern[i] != str[j]) { return -1; } } return j; }
int sj_conf_check_access(const char *key, const char *acl) { int key_len; struct mg_str entry; if (acl == NULL) return 0; key_len = strlen(key); while ((acl = mg_next_comma_list_entry(acl, &entry, NULL)) != NULL) { int result; if (entry.len == 0) continue; result = (entry.p[0] != '-'); if (entry.p[0] == '-' || entry.p[0] == '+') { entry.p++; entry.len--; } if (mg_match_prefix(entry.p, entry.len, key) == key_len) { return result; } } return 0; }
static const char *test_match_prefix(void) { ASSERT(mg_match_prefix("/api", 4, "/api") == 4); ASSERT(mg_match_prefix("/a/", 3, "/a/b/c") == 3); ASSERT(mg_match_prefix("/a/", 3, "/ab/c") == -1); ASSERT(mg_match_prefix("/*/", 3, "/ab/c") == 4); ASSERT(mg_match_prefix("**", 2, "/a/b/c") == 6); ASSERT(mg_match_prefix("/*", 2, "/a/b/c") == 2); ASSERT(mg_match_prefix("*/*", 3, "/a/b/c") == 2); ASSERT(mg_match_prefix("**/", 3, "/a/b/c") == 5); ASSERT(mg_match_prefix("**.foo|**.bar", 13, "a.bar") == 5); ASSERT(mg_match_prefix("a|b|cd", 6, "cdef") == 2); ASSERT(mg_match_prefix("a|b|c?", 6, "cdef") == 2); ASSERT(mg_match_prefix("a|?|cd", 6, "cdef") == 1); ASSERT(mg_match_prefix("/a/**.cgi", 9, "/foo/bar/x.cgi") == -1); ASSERT(mg_match_prefix("/a/**.cgi", 9, "/a/bar/x.cgi") == 12); ASSERT(mg_match_prefix("**/", 3, "/a/b/c") == 5); ASSERT(mg_match_prefix("**/$", 4, "/a/b/c") == -1); ASSERT(mg_match_prefix("**/$", 4, "/a/b/") == 5); ASSERT(mg_match_prefix("$", 1, "") == 0); ASSERT(mg_match_prefix("$", 1, "x") == -1); ASSERT(mg_match_prefix("*$", 2, "x") == 1); ASSERT(mg_match_prefix("/$", 2, "/") == 1); ASSERT(mg_match_prefix("**/$", 4, "/a/b/c") == -1); ASSERT(mg_match_prefix("**/$", 4, "/a/b/") == 5); ASSERT(mg_match_prefix("*", 1, "/hello/") == 0); ASSERT(mg_match_prefix("**.a$|**.b$", 11, "/a/b.b/") == -1); ASSERT(mg_match_prefix("**.a$|**.b$", 11, "/a/b.b") == 6); ASSERT(mg_match_prefix("**.a$|**.b$", 11, "/a/B.A") == 6); ASSERT(mg_match_prefix("**o$", 4, "HELLO") == 5); return NULL; }