|
|
@ -54,19 +54,20 @@ struct http_request {
|
|
|
|
|
|
|
|
|
|
|
|
struct zet_search {
|
|
|
|
struct zet_search {
|
|
|
|
DIR *dir;
|
|
|
|
DIR *dir;
|
|
|
|
char *id;
|
|
|
|
const char *id;
|
|
|
|
char *query;
|
|
|
|
char *query;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
enum page {
|
|
|
|
enum page {
|
|
|
|
PAGE_NEW,
|
|
|
|
PAGE_NEW,
|
|
|
|
PAGE_ALL,
|
|
|
|
PAGE_ALL,
|
|
|
|
|
|
|
|
PAGE_HEADS,
|
|
|
|
PAGE_ZET,
|
|
|
|
PAGE_ZET,
|
|
|
|
PAGE_SEARCH,
|
|
|
|
PAGE_SEARCH,
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static int count_lines_in(const char *str) {
|
|
|
|
static int count_lines_in(const char *str) {
|
|
|
|
int count = 0;
|
|
|
|
int count = 1;
|
|
|
|
char c;
|
|
|
|
char c;
|
|
|
|
int col = 0;
|
|
|
|
int col = 0;
|
|
|
|
while ((c = *str++)) {
|
|
|
|
while ((c = *str++)) {
|
|
|
@ -79,7 +80,7 @@ static int count_lines_in(const char *str) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int count_lines(int fd) {
|
|
|
|
static int count_lines(int fd) {
|
|
|
|
int count = 0;
|
|
|
|
int count = 1;
|
|
|
|
do {
|
|
|
|
do {
|
|
|
|
unsigned char buf[4096];
|
|
|
|
unsigned char buf[4096];
|
|
|
|
size_t len = sizeof(buf)-1;
|
|
|
|
size_t len = sizeof(buf)-1;
|
|
|
@ -124,8 +125,13 @@ static int write_html(int fd, const char *buf, size_t len) {
|
|
|
|
static int write_topbar(int fd, enum page page, const char *id, const char *title) {
|
|
|
|
static int write_topbar(int fd, enum page page, const char *id, const char *title) {
|
|
|
|
int rc = write_buf(fd, "<form action=\"search\">");
|
|
|
|
int rc = write_buf(fd, "<form action=\"search\">");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (page == PAGE_HEADS) rc |= write_buf(fd, "<strong>");
|
|
|
|
|
|
|
|
rc |= write_buf(fd, "<a href=\".\">Heads</a>");
|
|
|
|
|
|
|
|
if (page == PAGE_HEADS) rc |= write_buf(fd, "</strong>");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
rc |= write_buf(fd, " ");
|
|
|
|
if (page == PAGE_ALL) rc |= write_buf(fd, "<strong>");
|
|
|
|
if (page == PAGE_ALL) rc |= write_buf(fd, "<strong>");
|
|
|
|
rc |= write_buf(fd, "<a href=\".\">All</a>");
|
|
|
|
rc |= write_buf(fd, "<a href=\"all\">All</a>");
|
|
|
|
if (page == PAGE_ALL) rc |= write_buf(fd, "</strong>");
|
|
|
|
if (page == PAGE_ALL) rc |= write_buf(fd, "</strong>");
|
|
|
|
|
|
|
|
|
|
|
|
rc |= write_buf(fd, " ");
|
|
|
|
rc |= write_buf(fd, " ");
|
|
|
@ -274,7 +280,7 @@ static int zet_matches_query(const char *id, const char *query) {
|
|
|
|
return found ? 1 : 0;
|
|
|
|
return found ? 1 : 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int zet_search_start(struct zet_search *zs, 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;
|
|
|
@ -286,8 +292,8 @@ 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;
|
|
|
|
char *const dest_id = zs->id;
|
|
|
|
const char *dest_id = zs->id;
|
|
|
|
char *const query = zs->query;
|
|
|
|
const char *query = zs->query;
|
|
|
|
while (1) {
|
|
|
|
while (1) {
|
|
|
|
errno = 0;
|
|
|
|
errno = 0;
|
|
|
|
ent = readdir(zs->dir);
|
|
|
|
ent = readdir(zs->dir);
|
|
|
@ -319,7 +325,7 @@ static int zet_search_close(struct zet_search *sz) {
|
|
|
|
return closedir(sz->dir);
|
|
|
|
return closedir(sz->dir);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int dpi_serve_zet_index(int fd) {
|
|
|
|
static int dpi_serve_zet_all(int fd) {
|
|
|
|
int rc;
|
|
|
|
int rc;
|
|
|
|
struct zet_search zs;
|
|
|
|
struct zet_search zs;
|
|
|
|
rc = zet_search_start(&zs, NULL, NULL);
|
|
|
|
rc = zet_search_start(&zs, NULL, NULL);
|
|
|
@ -328,7 +334,7 @@ static int dpi_serve_zet_index(int fd) {
|
|
|
|
if (rc < 0) { warn("dpi_send_header"); close(fd); return 0; }
|
|
|
|
if (rc < 0) { warn("dpi_send_header"); close(fd); return 0; }
|
|
|
|
rc = dprintf(fd,
|
|
|
|
rc = dprintf(fd,
|
|
|
|
"<!doctype html><html><head>"
|
|
|
|
"<!doctype html><html><head>"
|
|
|
|
"<title>Notes</title>"
|
|
|
|
"<title>Notes - All</title>"
|
|
|
|
"<meta charset=utf-8>"
|
|
|
|
"<meta charset=utf-8>"
|
|
|
|
"</head>"
|
|
|
|
"</head>"
|
|
|
|
"<body>");
|
|
|
|
"<body>");
|
|
|
@ -369,6 +375,72 @@ static int dpi_serve_zet_index(int fd) {
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int dpi_serve_zet_heads(int fd) {
|
|
|
|
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
struct zet_search zs;
|
|
|
|
|
|
|
|
rc = zet_search_start(&zs, NULL, NULL);
|
|
|
|
|
|
|
|
if (rc < 0) return dpi_respond_err(fd, "Unable to list");
|
|
|
|
|
|
|
|
rc = dpi_send_header(fd, "text/html");
|
|
|
|
|
|
|
|
if (rc < 0) { warn("dpi_send_header"); close(fd); return 0; }
|
|
|
|
|
|
|
|
rc = dprintf(fd,
|
|
|
|
|
|
|
|
"<!doctype html><html><head>"
|
|
|
|
|
|
|
|
"<title>Notes - Heads</title>"
|
|
|
|
|
|
|
|
"<meta charset=utf-8>"
|
|
|
|
|
|
|
|
"</head>"
|
|
|
|
|
|
|
|
"<body>");
|
|
|
|
|
|
|
|
rc |= write_topbar(fd, PAGE_HEADS, NULL, NULL);
|
|
|
|
|
|
|
|
rc |= write_buf(fd, "<ul>");
|
|
|
|
|
|
|
|
if (rc < 0) { warn("write"); close(fd); return 0; }
|
|
|
|
|
|
|
|
const char *id;
|
|
|
|
|
|
|
|
while (1) {
|
|
|
|
|
|
|
|
rc = zet_search_next(&zs, &id);
|
|
|
|
|
|
|
|
if (rc < 0) {
|
|
|
|
|
|
|
|
rc = dprintf(fd,
|
|
|
|
|
|
|
|
"\n<strong>Error</strong>: %s\n",
|
|
|
|
|
|
|
|
strerror(errno));
|
|
|
|
|
|
|
|
if (rc < 0) warnx("dprintf");
|
|
|
|
|
|
|
|
close(fd);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (id == NULL) break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool has_backlink = false;
|
|
|
|
|
|
|
|
struct zet_search backlink_zs;
|
|
|
|
|
|
|
|
rc = zet_search_start(&backlink_zs, id, NULL);
|
|
|
|
|
|
|
|
if (rc < 0) warn("zet_search_start");
|
|
|
|
|
|
|
|
while (1) {
|
|
|
|
|
|
|
|
const char *backlink_id;
|
|
|
|
|
|
|
|
rc = zet_search_next(&backlink_zs, &backlink_id);
|
|
|
|
|
|
|
|
if (rc < 0) warn("zet_search_next");
|
|
|
|
|
|
|
|
if (backlink_id == NULL) break;
|
|
|
|
|
|
|
|
has_backlink = true;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
(void)zet_search_close(&backlink_zs);
|
|
|
|
|
|
|
|
if (has_backlink) continue;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
char title_buf[128];
|
|
|
|
|
|
|
|
char *title = zet_get_title(id, title_buf, sizeof(title_buf));
|
|
|
|
|
|
|
|
if (title == NULL) {
|
|
|
|
|
|
|
|
warn("zet_get_title");
|
|
|
|
|
|
|
|
title = title_buf;
|
|
|
|
|
|
|
|
strncpy(title, id, sizeof(title)-1);
|
|
|
|
|
|
|
|
title[sizeof(title)-1] = '\0';
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
rc = dprintf(fd, "<li><a href=\"%s\">", id);
|
|
|
|
|
|
|
|
rc |= write_html(fd, title, strlen(title));
|
|
|
|
|
|
|
|
rc |= write_buf(fd, "</a></li>");
|
|
|
|
|
|
|
|
if (rc < 0) { warnx("write"); close(fd); return 0; }
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
rc = dprintf(fd, "</ul></body></html>");
|
|
|
|
|
|
|
|
if (rc < 0) { warn("dprintf"); close(fd); return 0; }
|
|
|
|
|
|
|
|
rc = zet_search_close(&zs);
|
|
|
|
|
|
|
|
if (rc < 0) warn("closedir");
|
|
|
|
|
|
|
|
close(fd);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void unescape(char *buf, size_t len, const char *str) {
|
|
|
|
static void unescape(char *buf, size_t len, const char *str) {
|
|
|
|
struct buf *ob = bufnew(1024);
|
|
|
|
struct buf *ob = bufnew(1024);
|
|
|
|
houdini_unescape_url(ob, str, strlen(str));
|
|
|
|
houdini_unescape_url(ob, str, strlen(str));
|
|
|
@ -620,7 +692,8 @@ static int dpi_serve_zet(int fd, char *path) {
|
|
|
|
char *hash, *query;
|
|
|
|
char *hash, *query;
|
|
|
|
parse_req_uri(path, &hash, &query);
|
|
|
|
parse_req_uri(path, &hash, &query);
|
|
|
|
|
|
|
|
|
|
|
|
if (!strcmp(path, "/")) return dpi_serve_zet_index(fd);
|
|
|
|
if (!strcmp(path, "/")) return dpi_serve_zet_heads(fd);
|
|
|
|
|
|
|
|
if (!strcmp(path, "/all")) return dpi_serve_zet_all(fd);
|
|
|
|
if (!strcmp(path, "/search")) return dpi_serve_zet_search(fd, query);
|
|
|
|
if (!strcmp(path, "/search")) return dpi_serve_zet_search(fd, query);
|
|
|
|
if (!strcmp(path, "/new")) return dpi_serve_zet_new(fd);
|
|
|
|
if (!strcmp(path, "/new")) return dpi_serve_zet_new(fd);
|
|
|
|
|
|
|
|
|
|
|
|