suckless-quark/dirl.c
Armin Friedl 329dedc33b
Some checks failed
continuous-integration/drone/push Build is failing
Read dirlist from templates
Reads header, footer and entry templates from files defined in config.h.
Defaults to original output if not found.
2020-08-25 21:08:23 +02:00

185 lines
3.8 KiB
C

/* See LICENSE file for copyright and license details. */
#include <dirent.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/sendfile.h>
#include <sys/stat.h>
#include <unistd.h>
#include "dirl.h"
#include "http.h"
#include "util.h"
#include "config.h"
static char *suffix(int t) {
switch (t) {
case DT_FIFO:
return "|";
case DT_DIR:
return "/";
case DT_LNK:
return "@";
case DT_SOCK:
return "=";
}
return "";
}
enum status
dirl_header_default(int fd, const struct response *res) {
char esc[PATH_MAX];
html_escape(res->uri, esc, sizeof(esc));
if (dprintf(fd,
"<!DOCTYPE html>\n<html>\n\t<head>"
"<title>Index of %s</title></head>\n"
"\t<body>\n"
"\t\t<h1>Index of %s</h1>\n"
"\t\t\t<a href=\"..\">..</a>",
esc, esc) < 0) {
return S_REQUEST_TIMEOUT;
}
return 0;
}
enum status
dirl_header(int fd, const struct response *res)
{
/* No header file defined, default */
#ifndef DIRL_HEADER
return dirl_header_default(fd, res);
#endif
/* Try find header in root (note that we are chroot'ed) */
int header_fd;
if ( (header_fd = open(("/" DIRL_HEADER), O_RDONLY)) < 0 ) {
return dirl_header_default(fd, res);
}
/* Get size of header */
struct stat header_stat;
if (fstat(header_fd, &header_stat) < 0) {
return dirl_header_default(fd, res);
}
/* Allocate space for file */
char *header = (char *) malloc(sizeof(char) * header_stat.st_size);
if (header == NULL) {
return dirl_header_default(fd, res);
}
/* Read header into string for template replacement */
if ( (read(header_fd, header, header_stat.st_size)) < 0) {
free(header);
return dirl_header_default(fd, res);
}
/* Replace placeholder */
char *nhead = replace(header, "{idx}", "something");
/* Write header */
write(fd, nhead, strlen(nhead));
free(header);
free(nhead);
/* listing header */
return 0;
}
static enum status
dirl_entry_default(int fd, const struct dirent* entry) {
char esc[PATH_MAX];
html_escape(entry->d_name, esc, sizeof(esc));
if (dprintf(fd, "<br />\n\t\t<a href=\"%s%s\">%s%s</a>", esc,
(entry->d_type == DT_DIR) ? "/" : "", esc,
suffix(entry->d_type)) < 0) {
return S_REQUEST_TIMEOUT;
}
return 0;
}
enum status
dirl_entry(int fd, const struct dirent* entry) {
/* Try find entry in root (note that we are chroot'ed) */
int entry_fd;
if ((entry_fd = open(("/" DIRL_ENTRY), O_RDONLY)) < 0) {
return dirl_entry_default(fd, entry);
}
/* Get size of entry*/
struct stat entry_stat;
if (fstat(entry_fd, &entry_stat) < 0) {
return dirl_entry_default(fd, entry);
}
/* Write entry */
if (sendfile(fd, entry_fd, NULL, entry_stat.st_size) < 0) {
return dirl_entry_default(fd, entry);
}
return 0;
}
static enum status
dirl_footer_default(int fd) {
if (dprintf(fd, "\n\t</body>\n</html>\n") < 0) {
return S_REQUEST_TIMEOUT;
}
return 0;
}
enum status
dirl_footer(int fd) {
/* Try find footer in root (note that we are chroot'ed) */
int footer_fd;
if ((footer_fd = open(("/" DIRL_FOOTER), O_RDONLY)) < 0) {
return dirl_footer_default(fd);
}
/* Get size of footer */
struct stat footer_stat;
if (fstat(footer_fd, &footer_stat) < 0) {
return dirl_footer_default(fd);
}
/* Write footer */
if (sendfile(fd, footer_fd, NULL, footer_stat.st_size) < 0) {
return dirl_footer_default(fd);
}
return 0;
}
int dirl_skip(const char *name) {
(void) name;
#ifdef DIRL_HEADER
if(!strcmp(name, DIRL_HEADER)) {
return 1;
}
#endif
#ifdef DIRL_ENTRY
if (!strcmp(name, DIRL_ENTRY)) {
return 1;
}
#endif
#ifdef DIRL_FOOTER
if (!strcmp(name, DIRL_FOOTER)) {
return 1;
}
#endif
#ifdef DIRL_STYLE
if (!strcmp(name, DIRL_STYLE)) {
return 1;
}
#endif
return 0;
}