|
|
@ -7,6 +7,7 @@
|
|
|
|
#include <dirent.h>
|
|
|
|
#include <dirent.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <limits.h>
|
|
|
|
#include <limits.h>
|
|
|
|
|
|
|
|
#include <regex.h>
|
|
|
|
#include <stdarg.h>
|
|
|
|
#include <stdarg.h>
|
|
|
|
#include <stdbool.h>
|
|
|
|
#include <stdbool.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdio.h>
|
|
|
@ -66,7 +67,8 @@ struct http_request {
|
|
|
|
struct zet_search {
|
|
|
|
struct zet_search {
|
|
|
|
DIR *dir;
|
|
|
|
DIR *dir;
|
|
|
|
const char *id;
|
|
|
|
const char *id;
|
|
|
|
char *query;
|
|
|
|
regex_t regex;
|
|
|
|
|
|
|
|
bool has_regex;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
struct zet_mtime {
|
|
|
|
struct zet_mtime {
|
|
|
@ -335,7 +337,7 @@ static int zet_links_to(const char *id_from, const char *id_to) {
|
|
|
|
return rc;
|
|
|
|
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];
|
|
|
|
char path_buf[_POSIX_PATH_MAX];
|
|
|
|
ssize_t sz = snprintf(path_buf, sizeof(path_buf), "%s/%s", zet_dir, id);
|
|
|
|
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;
|
|
|
|
if (sz < 0 || (size_t)sz >= sizeof(path_buf)) return -1;
|
|
|
@ -344,25 +346,45 @@ static int zet_matches_query(const char *id, const char *query) {
|
|
|
|
if (note_fd < 0) return -1;
|
|
|
|
if (note_fd < 0) return -1;
|
|
|
|
|
|
|
|
|
|
|
|
char *text = read_full(note_fd);
|
|
|
|
char *text = read_full(note_fd);
|
|
|
|
bool found = strcasestr(text, query) != NULL;
|
|
|
|
bool found = regexec(regex, text, 0, NULL, 0) == 0;
|
|
|
|
free(text);
|
|
|
|
free(text);
|
|
|
|
return found ? 1 : 0;
|
|
|
|
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) {
|
|
|
|
static int zet_search_start(struct zet_search *zs, const char *id, char *query) {
|
|
|
|
zs->dir = opendir(zet_dir);
|
|
|
|
zs->dir = opendir(zet_dir);
|
|
|
|
if (zs->dir == NULL) return -1;
|
|
|
|
if (zs->dir == NULL) return -1;
|
|
|
|
zs->id = id;
|
|
|
|
zs->id = id;
|
|
|
|
zs->query = query;
|
|
|
|
if (query != NULL) {
|
|
|
|
|
|
|
|
zs->has_regex = true;
|
|
|
|
|
|
|
|
return zet_search_init_query(zs, query);
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
zs->has_regex = false;
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int zet_search_next(struct zet_search *zs, const char **idp) {
|
|
|
|
static int zet_search_next(struct zet_search *zs, const char **idp) {
|
|
|
|
int rc;
|
|
|
|
int rc;
|
|
|
|
struct dirent *ent;
|
|
|
|
struct dirent *ent;
|
|
|
|
const char *id;
|
|
|
|
const char *id;
|
|
|
|
const char *dest_id = zs->id;
|
|
|
|
const char *dest_id = zs->id;
|
|
|
|
const char *query = zs->query;
|
|
|
|
|
|
|
|
while (1) {
|
|
|
|
while (1) {
|
|
|
|
errno = 0;
|
|
|
|
errno = 0;
|
|
|
|
ent = readdir(zs->dir);
|
|
|
|
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 < 0) return -1;
|
|
|
|
if (rc != 1) continue;
|
|
|
|
if (rc != 1) continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (query != NULL) {
|
|
|
|
if (zs->has_regex) {
|
|
|
|
rc = zet_matches_query(id, query);
|
|
|
|
rc = zet_matches_regex(id, &zs->regex);
|
|
|
|
if (rc < 0) return -1;
|
|
|
|
if (rc < 0) return -1;
|
|
|
|
if (rc != 1) continue;
|
|
|
|
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) {
|
|
|
|
static int zet_search_close(struct zet_search *sz) {
|
|
|
|
|
|
|
|
regfree(&sz->regex);
|
|
|
|
return closedir(sz->dir);
|
|
|
|
return closedir(sz->dir);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|