Add recent page, with error handling

main
cel 5 years ago
parent 44ea48cfc6
commit e662f26ba0
Signed by: cel
GPG Key ID: C28D95BB012367EA

@ -59,9 +59,15 @@ struct zet_search {
char *query;
};
struct zet_mtime {
char *id;
int mtime;
};
enum page {
PAGE_NEW,
PAGE_ALL,
PAGE_RECENT,
PAGE_HEADS,
PAGE_TAILS,
PAGE_ZET,
@ -107,6 +113,14 @@ static int write_html_char(int fd, char c) {
return write_char(fd, c);
}
static void write_err(int fd, const char *subject) {
int rc = dprintf(fd,
"\n<strong>Error</strong>: %s: %s\n",
subject,
strerror(errno));
if (rc < 0) warnx("dprintf");
}
static int write_html(int fd, const char *buf, size_t len) {
while (len > 0) {
// note: buf must null-terminated
@ -141,6 +155,11 @@ static int write_topbar(int fd, enum page page, const char *id, const char *titl
rc |= write_buf(fd, "<a href=\"all\">All</a>");
if (page == PAGE_ALL) rc |= write_buf(fd, "</strong>");
rc |= write_buf(fd, " ");
if (page == PAGE_RECENT) rc |= write_buf(fd, "<strong>");
rc |= write_buf(fd, "<a href=\"recent\">Recent</a>");
if (page == PAGE_RECENT) rc |= write_buf(fd, "</strong>");
rc |= write_buf(fd, " ");
if (page == PAGE_NEW) rc |= write_buf(fd, "<strong>");
rc |= write_buf(fd, "<a href=\"new\">New</a>");
@ -221,6 +240,13 @@ static char *zet_get_title(const char *id, char *buf, size_t len) {
return buf;
}
static int zet_stat(const char *id, struct stat *st) {
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;
return stat(path_buf, st);
}
static int zet_has_links(const char *id) {
char path_buf[_POSIX_PATH_MAX];
ssize_t sz = snprintf(path_buf, sizeof(path_buf), "%s/%s", zet_dir, id);
@ -426,6 +452,87 @@ static int dpi_serve_zet_all(int fd) {
return 0;
}
static int cmp_zet_mtimes(const void *ptr1, const void *ptr2) {
const struct zet_mtime *zet_mtime1 = ptr1;
const struct zet_mtime *zet_mtime2 = ptr2;
return zet_mtime2->mtime - zet_mtime1->mtime;
}
static int dpi_serve_zet_recent(int fd) {
int rc, i;
struct zet_search zs;
int capacity = 0;
int count = 0;
struct zet_mtime *zets = NULL;
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"); goto cleanup; }
rc = dprintf(fd,
"<!doctype html><html><head>"
"<title>Notes - Recent</title>"
"<meta charset=utf-8>"
"</head>"
"<body>");
rc |= write_topbar(fd, PAGE_RECENT, NULL, NULL);
rc |= write_buf(fd, "<ul>");
if (rc < 0) { warn("write"); goto cleanup; }
const char *id;
for (i = 0;; i++) {
struct stat st;
rc = zet_search_next(&zs, &id);
if (rc == 0 && id == NULL) break;
if (rc == 0) rc = zet_stat(id, &st);
if (rc == 0 && i >= capacity) {
if (capacity == 0) capacity = 256;
else capacity *= 2;
void *new_zets = reallocarray(zets, capacity, sizeof *zets);
if (new_zets == NULL) rc = -1;
else zets = new_zets;
}
if (rc < 0) {
write_err(fd, "list");
goto cleanup;
}
zets[i].mtime = st.st_mtime;
zets[i].id = strdup(id);
count++;
}
qsort(zets, count, sizeof(*zets), cmp_zet_mtimes);
static int limit = 50;
if (limit > count) limit = count;
for (i = 0; i < limit; i++) {
id = zets[i].id;
char title_buf[128];
char *title = zet_get_title(id, title_buf, sizeof(title_buf));
if (title == NULL) {
write_err(fd, "get_title");
goto cleanup;
}
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"); goto cleanup; }
}
rc = dprintf(fd, "</ul></body></html>");
if (rc < 0) warn("dprintf");
cleanup:
for (i = 0; i < count; i++) {
free(zets[i].id);
}
free(zets);
rc = zet_search_close(&zs);
if (rc < 0) warn("closedir");
close(fd);
return 0;
}
static int dpi_serve_zet_heads(int fd) {
int rc;
struct zet_search zs;
@ -800,6 +907,7 @@ static int dpi_serve_zet(int fd, char *path) {
if (!strcmp(path, "/")) return dpi_serve_zet_heads(fd);
if (!strcmp(path, "/tails")) return dpi_serve_zet_tails(fd);
if (!strcmp(path, "/all")) return dpi_serve_zet_all(fd);
if (!strcmp(path, "/recent")) return dpi_serve_zet_recent(fd);
if (!strcmp(path, "/search")) return dpi_serve_zet_search(fd, query);
if (!strcmp(path, "/new")) return dpi_serve_zet_new(fd);

Loading…
Cancel
Save