2020-08-25 19:08:23 +00:00
|
|
|
/* See LICENSE file for copyright and license details. */
|
|
|
|
#include <dirent.h>
|
2020-08-29 18:36:10 +00:00
|
|
|
#include <errno.h>
|
2020-08-25 19:08:23 +00:00
|
|
|
#include <fcntl.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <sys/sendfile.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
|
2020-08-27 22:40:04 +00:00
|
|
|
#include "config.h"
|
2020-08-25 19:08:23 +00:00
|
|
|
#include "dirl.h"
|
|
|
|
#include "http.h"
|
|
|
|
#include "util.h"
|
|
|
|
|
2020-08-27 22:40:04 +00:00
|
|
|
static char*
|
|
|
|
suffix(int t)
|
|
|
|
{
|
2020-08-25 19:08:23 +00:00
|
|
|
switch (t) {
|
2020-08-27 22:40:04 +00:00
|
|
|
case DT_FIFO:
|
|
|
|
return "|";
|
|
|
|
case DT_DIR:
|
|
|
|
return "/";
|
|
|
|
case DT_LNK:
|
|
|
|
return "@";
|
|
|
|
case DT_SOCK:
|
|
|
|
return "=";
|
2020-08-25 19:08:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
|
2020-08-27 22:40:04 +00:00
|
|
|
static char*
|
2020-08-29 18:36:10 +00:00
|
|
|
dirl_read(char* tpl)
|
2020-08-27 22:40:04 +00:00
|
|
|
{
|
|
|
|
FILE* tpl_fp;
|
|
|
|
|
2020-08-29 18:36:10 +00:00
|
|
|
if (!(tpl_fp = fopen(tpl, "r"))) {
|
2020-08-27 22:40:04 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Get size of template */
|
|
|
|
if (fseek(tpl_fp, 0L, SEEK_END) < 0) {
|
|
|
|
fclose(tpl_fp);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
long tpl_size;
|
|
|
|
if ((tpl_size = ftell(tpl_fp)) < 0) {
|
|
|
|
fclose(tpl_fp);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
rewind(tpl_fp);
|
|
|
|
|
|
|
|
/* Read template into tpl_buf */
|
2020-08-29 18:36:10 +00:00
|
|
|
char* tpl_buf = (char*)calloc(sizeof(char), tpl_size);
|
2020-08-27 22:40:04 +00:00
|
|
|
|
|
|
|
if (tpl_buf == NULL) {
|
|
|
|
fclose(tpl_fp);
|
|
|
|
free(tpl_buf);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fread(tpl_buf, 1, tpl_size, tpl_fp) < tpl_size) {
|
|
|
|
if (feof(tpl_fp)) {
|
|
|
|
warn("Reached end of template %s prematurely", tpl);
|
|
|
|
} else if (ferror(tpl_fp)) {
|
|
|
|
warn("Error while reading template %s", tpl);
|
|
|
|
}
|
|
|
|
|
|
|
|
fclose(tpl_fp);
|
|
|
|
free(tpl_buf);
|
|
|
|
clearerr(tpl_fp);
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return tpl_buf;
|
|
|
|
}
|
|
|
|
|
2020-08-29 18:36:10 +00:00
|
|
|
/* Try to find templates up until root
|
|
|
|
*
|
|
|
|
* Iterates the directory hierarchy upwards. Returns the closest path containing
|
|
|
|
* a template file or NULL if none could be found.
|
|
|
|
*
|
|
|
|
* Note that we are chrooted.
|
|
|
|
*/
|
|
|
|
static char*
|
|
|
|
dirl_find_templ_dir(const char* start_path)
|
2020-08-27 22:40:04 +00:00
|
|
|
{
|
2020-08-29 18:36:10 +00:00
|
|
|
char* path_buf = calloc(sizeof(char), strlen(start_path));
|
|
|
|
strcat(path_buf, start_path);
|
|
|
|
|
|
|
|
while (strlen(path_buf) != 0) {
|
|
|
|
DIR* cur = opendir(path_buf);
|
|
|
|
struct dirent* de;
|
|
|
|
errno = 0;
|
|
|
|
while ((de = readdir(cur))) {
|
|
|
|
if (de->d_type == DT_REG) {
|
|
|
|
if (strcmp(DIRL_HEADER, de->d_name) || strcmp(DIRL_ENTRY, de->d_name) ||
|
|
|
|
strcmp(DIRL_FOOTER, de->d_name)) {
|
|
|
|
closedir(cur);
|
|
|
|
return path_buf;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
char* parent = strrchr(path_buf, '/');
|
|
|
|
(*parent) = '\0'; // strip tail from path_buf
|
2020-08-25 19:08:23 +00:00
|
|
|
}
|
|
|
|
|
2020-08-29 18:36:10 +00:00
|
|
|
free(path_buf);
|
|
|
|
return NULL;
|
2020-08-25 19:08:23 +00:00
|
|
|
}
|
|
|
|
|
2020-08-29 18:36:10 +00:00
|
|
|
struct dirl_templ
|
|
|
|
dirl_read_templ(const char* path)
|
2020-08-25 19:08:23 +00:00
|
|
|
{
|
2020-08-29 18:36:10 +00:00
|
|
|
struct dirl_templ templates = { .header = DIRL_HEADER_DEFAULT,
|
|
|
|
.entry = DIRL_ENTRY_DEFAULT,
|
|
|
|
.footer = DIRL_FOOTER_DEFAULT };
|
|
|
|
|
|
|
|
char* templ_dir = dirl_find_templ_dir(path);
|
|
|
|
|
|
|
|
char* header_file =
|
|
|
|
calloc(sizeof(char), strlen(templ_dir) + strlen(DIRL_HEADER));
|
|
|
|
strcpy(header_file, templ_dir);
|
|
|
|
strcat(header_file, DIRL_HEADER);
|
|
|
|
char* header = dirl_read(header_file);
|
|
|
|
if (header)
|
|
|
|
templates.header = header;
|
|
|
|
free(header_file);
|
|
|
|
|
|
|
|
char* entry_file =
|
|
|
|
calloc(sizeof(char), strlen(templ_dir) + strlen(DIRL_ENTRY));
|
|
|
|
strcpy(entry_file, templ_dir);
|
|
|
|
strcat(entry_file, DIRL_ENTRY);
|
|
|
|
char* entry = dirl_read(entry_file);
|
|
|
|
if (entry)
|
|
|
|
templates.entry = entry;
|
|
|
|
free(entry_file);
|
|
|
|
|
|
|
|
char* footer_file =
|
|
|
|
calloc(sizeof(char), strlen(templ_dir) + strlen(DIRL_FOOTER));
|
|
|
|
strcpy(footer_file, templ_dir);
|
|
|
|
strcat(footer_file, DIRL_FOOTER);
|
|
|
|
char* footer = dirl_read(footer_file);
|
|
|
|
if (footer)
|
|
|
|
templates.footer = footer;
|
|
|
|
free(footer_file);
|
|
|
|
|
|
|
|
free(templ_dir);
|
|
|
|
|
|
|
|
return templates;
|
|
|
|
}
|
2020-08-25 19:08:23 +00:00
|
|
|
|
2020-08-29 18:36:10 +00:00
|
|
|
enum status
|
|
|
|
dirl_header(int fd, const struct response* res, const struct dirl_templ* templ)
|
|
|
|
{
|
2020-08-25 19:08:23 +00:00
|
|
|
/* Replace placeholder */
|
2020-08-29 18:36:10 +00:00
|
|
|
char* nhead = replace(templ->header, "{curdir}", "something");
|
2020-08-25 19:08:23 +00:00
|
|
|
|
|
|
|
/* Write header */
|
|
|
|
write(fd, nhead, strlen(nhead));
|
|
|
|
|
|
|
|
free(nhead);
|
|
|
|
|
|
|
|
/* listing header */
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
enum status
|
2020-08-29 18:36:10 +00:00
|
|
|
dirl_entry(int fd, const struct dirent* entry, const struct dirl_templ* templ)
|
2020-08-27 22:40:04 +00:00
|
|
|
{
|
|
|
|
/* Replace placeholder */
|
2020-08-29 18:36:10 +00:00
|
|
|
char* nentry = replace(templ->entry, "{entry}", entry->d_name);
|
2020-08-27 22:40:04 +00:00
|
|
|
|
2020-08-25 19:08:23 +00:00
|
|
|
/* Write entry */
|
2020-08-27 22:40:04 +00:00
|
|
|
write(fd, nentry, strlen(nentry));
|
|
|
|
|
|
|
|
free(nentry);
|
2020-08-25 19:08:23 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
enum status
|
2020-08-29 18:36:10 +00:00
|
|
|
dirl_footer(int fd, const struct dirl_templ* templ)
|
2020-08-27 22:40:04 +00:00
|
|
|
{
|
|
|
|
/* Replace placeholder */
|
2020-08-29 18:36:10 +00:00
|
|
|
char* nfoot = replace(templ->footer, "{idx}", "something");
|
2020-08-27 22:40:04 +00:00
|
|
|
|
2020-08-25 19:08:23 +00:00
|
|
|
/* Write footer */
|
2020-08-27 22:40:04 +00:00
|
|
|
write(fd, nfoot, strlen(nfoot));
|
2020-08-25 19:08:23 +00:00
|
|
|
|
2020-08-27 22:40:04 +00:00
|
|
|
free(nfoot);
|
|
|
|
return 0;
|
2020-08-25 19:08:23 +00:00
|
|
|
}
|
|
|
|
|
2020-08-27 22:40:04 +00:00
|
|
|
int
|
|
|
|
dirl_skip(const char* name)
|
|
|
|
{
|
2020-08-29 18:36:10 +00:00
|
|
|
return name[0] == '.' //
|
|
|
|
|| !strcmp(name, DIRL_HEADER) //
|
2020-08-27 22:40:04 +00:00
|
|
|
|| !strcmp(name, DIRL_ENTRY) //
|
|
|
|
|| !strcmp(name, DIRL_FOOTER) //
|
2020-08-29 18:36:10 +00:00
|
|
|
|| !strcmp(name, DIRL_STYLE); //
|
2020-08-25 19:08:23 +00:00
|
|
|
}
|