diff --git a/zet.dpi.c b/zet.dpi.c index af16b35..8e3449e 100644 --- a/zet.dpi.c +++ b/zet.dpi.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -66,7 +67,8 @@ struct http_request { struct zet_search { DIR *dir; const char *id; - char *query; + regex_t regex; + bool has_regex; }; struct zet_mtime { @@ -335,7 +337,7 @@ static int zet_links_to(const char *id_from, const char *id_to) { return rc; } -static int zet_matches_query(const char *id, const char *query) { +static int zet_matches_regex(const char *id, regex_t *regex) { char path_buf[_POSIX_PATH_MAX]; ssize_t sz = snprintf(path_buf, sizeof(path_buf), "%s/%s", zet_dir, id); if (sz < 0 || (size_t)sz >= sizeof(path_buf)) return -1; @@ -344,17 +346,38 @@ static int zet_matches_query(const char *id, const char *query) { if (note_fd < 0) return -1; char *text = read_full(note_fd); - bool found = strcasestr(text, query) != NULL; + bool found = regexec(regex, text, 0, NULL, 0) == 0; free(text); return found ? 1 : 0; } +static int zet_search_init_query(struct zet_search *zs, const char *query) { + int rc = regcomp(&zs->regex, query, REG_NOSUB | REG_EXTENDED | REG_ICASE); + if (rc != 0) { + char errbuf[LINE_MAX]; + size_t sz = regerror(rc, &zs->regex, errbuf, sizeof(errbuf)); + if (sz > sizeof(errbuf)-1) { + errbuf[sizeof(errbuf)-2] = '.'; + errbuf[sizeof(errbuf)-3] = '.'; + errbuf[sizeof(errbuf)-4] = '.'; + } + warnx("regex: %s", errbuf); + return -1; + } + return 0; +} + static int zet_search_start(struct zet_search *zs, const char *id, char *query) { zs->dir = opendir(zet_dir); if (zs->dir == NULL) return -1; zs->id = id; - zs->query = query; - return 0; + if (query != NULL) { + zs->has_regex = true; + return zet_search_init_query(zs, query); + } else { + zs->has_regex = false; + return 0; + } } static int zet_search_next(struct zet_search *zs, const char **idp) { @@ -362,7 +385,6 @@ static int zet_search_next(struct zet_search *zs, const char **idp) { struct dirent *ent; const char *id; const char *dest_id = zs->id; - const char *query = zs->query; while (1) { errno = 0; ent = readdir(zs->dir); @@ -379,8 +401,8 @@ static int zet_search_next(struct zet_search *zs, const char **idp) { if (rc < 0) return -1; if (rc != 1) continue; } - if (query != NULL) { - rc = zet_matches_query(id, query); + if (zs->has_regex) { + rc = zet_matches_regex(id, &zs->regex); if (rc < 0) return -1; if (rc != 1) continue; } @@ -391,6 +413,7 @@ static int zet_search_next(struct zet_search *zs, const char **idp) { } static int zet_search_close(struct zet_search *sz) { + regfree(&sz->regex); return closedir(sz->dir); }