summaryrefslogtreecommitdiffstats
path: root/fluent-bit/lib/monkey/plugins/dirlisting
diff options
context:
space:
mode:
Diffstat (limited to 'fluent-bit/lib/monkey/plugins/dirlisting')
-rw-r--r--fluent-bit/lib/monkey/plugins/dirlisting/ABOUT4
-rw-r--r--fluent-bit/lib/monkey/plugins/dirlisting/CMakeLists.txt7
-rw-r--r--fluent-bit/lib/monkey/plugins/dirlisting/OPTIONAL0
-rw-r--r--fluent-bit/lib/monkey/plugins/dirlisting/conf/CMakeLists.txt11
-rw-r--r--fluent-bit/lib/monkey/plugins/dirlisting/conf/dirhtml.conf2
-rw-r--r--fluent-bit/lib/monkey/plugins/dirlisting/conf/themes/bootstrap/entry.theme5
-rw-r--r--fluent-bit/lib/monkey/plugins/dirlisting/conf/themes/bootstrap/footer.theme8
-rw-r--r--fluent-bit/lib/monkey/plugins/dirlisting/conf/themes/bootstrap/header.theme27
-rw-r--r--fluent-bit/lib/monkey/plugins/dirlisting/conf/themes/guineo/entry.theme14
-rw-r--r--fluent-bit/lib/monkey/plugins/dirlisting/conf/themes/guineo/footer.theme7
-rw-r--r--fluent-bit/lib/monkey/plugins/dirlisting/conf/themes/guineo/header.theme58
-rw-r--r--fluent-bit/lib/monkey/plugins/dirlisting/dirlisting.c949
-rw-r--r--fluent-bit/lib/monkey/plugins/dirlisting/dirlisting.h181
13 files changed, 1273 insertions, 0 deletions
diff --git a/fluent-bit/lib/monkey/plugins/dirlisting/ABOUT b/fluent-bit/lib/monkey/plugins/dirlisting/ABOUT
new file mode 100644
index 000000000..2d71cb77e
--- /dev/null
+++ b/fluent-bit/lib/monkey/plugins/dirlisting/ABOUT
@@ -0,0 +1,4 @@
+Directory Listing Plugin
+========================
+When a directory is requested, this plugin will show
+an HTML list of the available content to the client.
diff --git a/fluent-bit/lib/monkey/plugins/dirlisting/CMakeLists.txt b/fluent-bit/lib/monkey/plugins/dirlisting/CMakeLists.txt
new file mode 100644
index 000000000..7432e1091
--- /dev/null
+++ b/fluent-bit/lib/monkey/plugins/dirlisting/CMakeLists.txt
@@ -0,0 +1,7 @@
+set(src
+ dirlisting.c
+ )
+
+MONKEY_PLUGIN(dirlisting "${src}")
+
+add_subdirectory(conf) \ No newline at end of file
diff --git a/fluent-bit/lib/monkey/plugins/dirlisting/OPTIONAL b/fluent-bit/lib/monkey/plugins/dirlisting/OPTIONAL
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/fluent-bit/lib/monkey/plugins/dirlisting/OPTIONAL
diff --git a/fluent-bit/lib/monkey/plugins/dirlisting/conf/CMakeLists.txt b/fluent-bit/lib/monkey/plugins/dirlisting/conf/CMakeLists.txt
new file mode 100644
index 000000000..4faf80a4d
--- /dev/null
+++ b/fluent-bit/lib/monkey/plugins/dirlisting/conf/CMakeLists.txt
@@ -0,0 +1,11 @@
+set(conf_dir "${MK_PATH_CONF}/plugins/dirlisting/")
+
+install(DIRECTORY DESTINATION ${conf_dir})
+
+if(BUILD_LOCAL)
+ file(COPY dirhtml.conf DESTINATION ${conf_dir})
+ file(COPY themes DESTINATION ${conf_dir})
+else()
+ install(FILES dirhtml.conf DESTINATION ${conf_dir})
+ install(DIRECTORY themes DESTINATION ${conf_dir})
+endif() \ No newline at end of file
diff --git a/fluent-bit/lib/monkey/plugins/dirlisting/conf/dirhtml.conf b/fluent-bit/lib/monkey/plugins/dirlisting/conf/dirhtml.conf
new file mode 100644
index 000000000..c73188df2
--- /dev/null
+++ b/fluent-bit/lib/monkey/plugins/dirlisting/conf/dirhtml.conf
@@ -0,0 +1,2 @@
+[DIRLISTING]
+ Theme bootstrap
diff --git a/fluent-bit/lib/monkey/plugins/dirlisting/conf/themes/bootstrap/entry.theme b/fluent-bit/lib/monkey/plugins/dirlisting/conf/themes/bootstrap/entry.theme
new file mode 100644
index 000000000..8c1ef026d
--- /dev/null
+++ b/fluent-bit/lib/monkey/plugins/dirlisting/conf/themes/bootstrap/entry.theme
@@ -0,0 +1,5 @@
+<tr>
+ <td><a title='%_target_title_%' href='%_target_url_%'>%_target_name_%</a></td>
+ <td>%_target_time_%</td>
+ <td>%_target_size_%</td>
+</tr>
diff --git a/fluent-bit/lib/monkey/plugins/dirlisting/conf/themes/bootstrap/footer.theme b/fluent-bit/lib/monkey/plugins/dirlisting/conf/themes/bootstrap/footer.theme
new file mode 100644
index 000000000..88290ac8b
--- /dev/null
+++ b/fluent-bit/lib/monkey/plugins/dirlisting/conf/themes/bootstrap/footer.theme
@@ -0,0 +1,8 @@
+ <tbody>
+</table>
+</div>
+</div>
+<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
+<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>
+</body>
+</HTML>
diff --git a/fluent-bit/lib/monkey/plugins/dirlisting/conf/themes/bootstrap/header.theme b/fluent-bit/lib/monkey/plugins/dirlisting/conf/themes/bootstrap/header.theme
new file mode 100644
index 000000000..f7f6cfcfd
--- /dev/null
+++ b/fluent-bit/lib/monkey/plugins/dirlisting/conf/themes/bootstrap/header.theme
@@ -0,0 +1,27 @@
+<html>
+ <head>
+ <meta http-equiv="content-type" content="text/html; charset=UTF-8">
+ <title>Index of %_html_title_%</title>
+ <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
+ <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap-theme.min.css">
+ <link href="http://maxcdn.bootstrapcdn.com/font-awesome/4.1.0/css/font-awesome.min.css" rel="stylesheet">
+ </head>
+ <body>
+ <div class="container">
+ <h1>Index of %_html_title_%</h1>
+ <div class="table-responsive">
+ <table class="table table-hover table-bordered">
+ <thead>
+ <tr>
+ <th>
+ Name
+ </th>
+ <th>
+ Last time modified
+ </th>
+ <th>
+ Size
+ </th>
+ </tr>
+ </thead>
+ <tbody>
diff --git a/fluent-bit/lib/monkey/plugins/dirlisting/conf/themes/guineo/entry.theme b/fluent-bit/lib/monkey/plugins/dirlisting/conf/themes/guineo/entry.theme
new file mode 100644
index 000000000..af00e250c
--- /dev/null
+++ b/fluent-bit/lib/monkey/plugins/dirlisting/conf/themes/guineo/entry.theme
@@ -0,0 +1,14 @@
+<TR>
+<TD class="row">
+ <A title='%_target_title_%' href='%_target_url_%'>
+ %_target_name_%
+ </A>
+</TD>
+<TD class="row">
+ %_target_time_%
+</TD>
+<TD class="row">
+ %_target_size_%
+ %_theme_path_%
+</TD>
+</TR>
diff --git a/fluent-bit/lib/monkey/plugins/dirlisting/conf/themes/guineo/footer.theme b/fluent-bit/lib/monkey/plugins/dirlisting/conf/themes/guineo/footer.theme
new file mode 100644
index 000000000..c785ba97f
--- /dev/null
+++ b/fluent-bit/lib/monkey/plugins/dirlisting/conf/themes/guineo/footer.theme
@@ -0,0 +1,7 @@
+</TABLE>
+
+</TD>
+</TR>
+</TABLE>
+</BODY></HTML>
+
diff --git a/fluent-bit/lib/monkey/plugins/dirlisting/conf/themes/guineo/header.theme b/fluent-bit/lib/monkey/plugins/dirlisting/conf/themes/guineo/header.theme
new file mode 100644
index 000000000..6a11a458f
--- /dev/null
+++ b/fluent-bit/lib/monkey/plugins/dirlisting/conf/themes/guineo/header.theme
@@ -0,0 +1,58 @@
+<HTML>
+ <HEAD>
+ <META http-equiv="content-type" content="text/html; charset=UTF-8">
+ <STYLE type="text/css">
+ H1.header {
+ text-align: center;
+ color: #4a77a0;
+ font-size: 12pt;
+ font-weight: bold;
+ }
+ .row {
+ color: #6c95bc;
+ font-size: 10pt;
+ background-color: #ffffff;
+ padding-left: 0.4em;
+ }
+ .title {color: #617691; font-size: 10pt; font-weight: bold;}
+
+ a:link {
+ color: #475f7e;
+ }
+ a:visited {
+ color: #ac7a2a;
+ }
+ a:hover {
+ color: #475f7e;
+ background-color: #dbdbdb;
+ text-decoration: none;
+ }
+ a:active {
+ color: #333333;
+ }
+ </STYLE>
+
+ <TITLE>Index of %_html_title_%</TITLE>
+ </HEAD>
+<BODY>
+
+<CENTER>
+<IMG src="/imgs/monkey_logo.png">
+<BR>
+<h1 class="header">Index of %_html_title_%</h1>
+<TABLE cellpadding="0" cellspacing="0" border="0" bgcolor="#000000" width="50%">
+<TR>
+<TD>
+
+<TABLE cellpadding="2" cellspacing="1" border="0" bgcolor="#e7e7e7" width="100%">
+<TR bgcolor="#ececec">
+ <TD class="title">
+ Name
+ </TD>
+ <TD class="title">
+ Last time modified
+ </TD>
+ <TD class="title">
+ Size
+ </TD>
+</TR>
diff --git a/fluent-bit/lib/monkey/plugins/dirlisting/dirlisting.c b/fluent-bit/lib/monkey/plugins/dirlisting/dirlisting.c
new file mode 100644
index 000000000..1ffd3fac4
--- /dev/null
+++ b/fluent-bit/lib/monkey/plugins/dirlisting/dirlisting.c
@@ -0,0 +1,949 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+
+/* Monkey HTTP Server
+ * ==================
+ * Copyright 2001-2017 Eduardo Silva <eduardo@monkey.io>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Some history about this plugin
+ * ------------------------------
+ * 2008 - Rewrite module, suport dynamic themes by Eduardo Silva
+ * 2008 - Felipe Astroza (max) provided the mk_dirhtml_human_readable_size_func()
+ * 2007 - Add struct client_request support by Eduardo
+ * 2002 - Original version written by Daniel R. Ome
+ */
+
+#include <monkey/mk_api.h>
+#include <monkey/mk_stream.h>
+#include "dirlisting.h"
+
+#include <time.h>
+#include <dirent.h>
+#include <sys/stat.h>
+
+const mk_ptr_t mk_dirhtml_default_mime = mk_ptr_init(MK_DIRHTML_DEFAULT_MIME);
+const mk_ptr_t mk_dir_iov_dash = mk_ptr_init("-");
+const mk_ptr_t mk_dir_iov_none = mk_ptr_init("");
+const mk_ptr_t mk_dir_iov_slash = mk_ptr_init("/");
+
+void mk_dirhtml_cb_body_rows(struct mk_stream_input *in);
+
+/* Function wrote by Max (Felipe Astroza), thanks! */
+static char *mk_dirhtml_human_readable_size(char *buf, size_t size, int len)
+{
+ unsigned long u = 1024, i;
+ static const char *__units[] = {
+ "b", "K", "M", "G",
+ "T", "P", "E", "Z", "Y", NULL
+ };
+
+ for (i = 0; __units[i] != NULL; i++) {
+ if ((size / u) == 0) {
+ break;
+ }
+ u *= 1024;
+ }
+ if (!i) {
+ snprintf(buf, size, "%lu%s", (long unsigned int) len, __units[0]);
+ }
+ else {
+ float fsize = (float) ((double) len / (u / 1024));
+ snprintf(buf, size, "%.1f%s", fsize, __units[i]);
+ }
+
+ return buf;
+}
+
+static struct mk_f_list *mk_dirhtml_create_element(char *file,
+ unsigned char type,
+ char *full_path,
+ unsigned long *list_len)
+{
+ int n;
+ struct tm *st_time;
+ struct mk_f_list *entry;
+
+ entry = mk_api->mem_alloc_z(sizeof(struct mk_f_list));
+
+ if (mk_api->file_get_info(full_path, &entry->info, MK_FILE_READ) != 0) {
+ mk_api->mem_free(entry);
+ return NULL;
+ }
+
+ strcpy(entry->name, file);
+ entry->type = type;
+
+ st_time = localtime((time_t *) & entry->info.last_modification);
+ n = strftime(entry->ft_modif, MK_DIRHTML_FMOD_LEN, "%d-%b-%G %H:%M", st_time);
+ if (n == 0) {
+ mk_mem_free(entry);
+ return NULL;
+ }
+
+ if (type != DT_DIR) {
+ mk_dirhtml_human_readable_size(entry->size,
+ sizeof(entry->size),
+ entry->info.size);
+ }
+ else {
+ entry->size[0] = '-';
+ entry->size[1] = '\0';
+ }
+
+ *list_len = *list_len + 1;
+
+ return entry;
+}
+
+static struct mk_list *mk_dirhtml_create_list(DIR * dir, char *path,
+ unsigned long *list_len)
+{
+ char full_path[PATH_MAX];
+ struct mk_list *list;
+ struct dirent *ent;
+ struct mk_f_list *entry = 0;
+
+ list = mk_api->mem_alloc(sizeof(struct mk_list));
+ mk_list_init(list);
+
+ while ((ent = readdir(dir)) != NULL) {
+ if ((ent->d_name[0] == '.') && (strcmp(ent->d_name, "..") != 0))
+ continue;
+
+ /* Look just for files and dirs */
+ if (ent->d_type != DT_REG && ent->d_type != DT_DIR
+ && ent->d_type != DT_LNK && ent->d_type != DT_UNKNOWN) {
+ continue;
+ }
+
+ snprintf(full_path, PATH_MAX, "%s%s", path, ent->d_name);
+ entry = mk_dirhtml_create_element(ent->d_name,
+ ent->d_type, full_path, list_len);
+ if (!entry) {
+ continue;
+ }
+
+ mk_list_add(&entry->_head, list);
+ }
+
+ return list;
+}
+
+/* Read dirhtml config and themes */
+int mk_dirhtml_conf(char *confdir)
+{
+ int ret = 0;
+ unsigned long len;
+ char *conf_file = NULL;
+
+ mk_api->str_build(&conf_file, &len, "%s", confdir);
+
+ /* Read configuration */
+ ret = mk_dirhtml_read_config(conf_file);
+ if (ret < 0) {
+ mk_mem_free(conf_file);
+ return -1;
+ }
+
+ /*
+ * This function will load the default theme setted in dirhtml_conf struct
+ */
+ mk_mem_free(conf_file);
+ return mk_dirhtml_theme_load();
+}
+
+/*
+ * Read the main configuration file for dirhtml: dirhtml.conf,
+ * it will alloc the dirhtml_conf struct
+*/
+int mk_dirhtml_read_config(char *path)
+{
+ unsigned long len;
+ char *default_file = NULL;
+ struct mk_rconf *conf;
+ struct mk_rconf_section *section;
+ struct file_info finfo;
+
+ mk_api->str_build(&default_file, &len, "%sdirhtml.conf", path);
+ conf = mk_api->config_open(default_file);
+ if (!conf) {
+ return -1;
+ }
+
+ section = mk_api->config_section_get(conf, "DIRLISTING");
+ if (!section) {
+ mk_err_ex(mk_api, "Could not find DIRLISTING tag in configuration file");
+ exit(EXIT_FAILURE);
+ }
+
+ /* alloc dirhtml config struct */
+ dirhtml_conf = mk_api->mem_alloc(sizeof(struct dirhtml_config));
+ dirhtml_conf->theme = mk_api->config_section_get_key(section, "Theme",
+ MK_RCONF_STR);
+ dirhtml_conf->theme_path = NULL;
+
+ mk_api->str_build(&dirhtml_conf->theme_path, &len,
+ "%sthemes/%s/", path, dirhtml_conf->theme);
+ mk_api->mem_free(default_file);
+
+ if (mk_api->file_get_info(dirhtml_conf->theme_path,
+ &finfo, MK_FILE_READ) != 0) {
+ mk_warn_ex(mk_api, "Dirlisting: cannot load theme from '%s'", dirhtml_conf->theme_path);
+ mk_warn_ex(mk_api, "Dirlisting: unloading plugin");
+ return -1;
+ }
+
+ mk_api->config_free(conf);
+ return 0;
+}
+
+int mk_dirhtml_theme_load()
+{
+ /* Data */
+ char *header, *entry, *footer;
+
+ /* Load theme files */
+ header = mk_dirhtml_load_file(MK_DIRHTML_FILE_HEADER);
+ entry = mk_dirhtml_load_file(MK_DIRHTML_FILE_ENTRY);
+ footer = mk_dirhtml_load_file(MK_DIRHTML_FILE_FOOTER);
+
+ if (!header || !entry || !footer) {
+ mk_api->mem_free(header);
+ mk_api->mem_free(entry);
+ mk_api->mem_free(footer);
+ return -1;
+ }
+
+ /* Parse themes */
+ mk_dirhtml_tpl_header = mk_dirhtml_template_create(header);
+ mk_dirhtml_tpl_entry = mk_dirhtml_template_create(entry);
+ mk_dirhtml_tpl_footer = mk_dirhtml_template_create(footer);
+
+#ifdef DEBUG_THEME
+ /* Debug data */
+ mk_dirhtml_theme_debug(&mk_dirhtml_tpl_header);
+ mk_dirhtml_theme_debug(&mk_dirhtml_tpl_entry);
+ mk_dirhtml_theme_debug(&mk_dirhtml_tpl_footer);
+
+#endif
+ mk_api->mem_free(header);
+ mk_api->mem_free(entry);
+ mk_api->mem_free(footer);
+
+ return 0;
+}
+
+#ifdef DEBUG_THEME
+int mk_dirhtml_theme_debug(struct dirhtml_template **st_tpl)
+{
+ int i = 0;
+ struct dirhtml_template *aux;
+
+ aux = *st_tpl;
+
+ printf("\n** DEBUG_THEME **");
+ fflush(stdout);
+
+ while (aux) {
+ printf("\n%i) len=%i, tag_id=%i", i, aux->len, aux->tag_id);
+ if (aux->tag_id >= 0) {
+ printf(" (%s) ", aux->tags[aux->tag_id]);
+ }
+ fflush(stdout);
+ aux = aux->next;
+ i++;
+ }
+ return 0;
+}
+#endif
+
+/* Search which tag exists first in content :
+ * ex: %_html_title_%
+ */
+static int mk_dirhtml_theme_match_tag(char *content, char *tpl[])
+{
+ int i, len, match;
+
+ for (i = 0; tpl[i]; i++) {
+ len = strlen(tpl[i]);
+ match = (int) mk_api->str_search_n(content, tpl[i], MK_STR_INSENSITIVE, len);
+ if (match >= 0) {
+ return i;
+ }
+ }
+
+ return -1;
+}
+
+struct dirhtml_template *mk_dirhtml_template_create(char *content)
+{
+ int i = 0, cont_len;
+ int pos, last = 0; /* 0=search init, 1=search end */
+ int n_tags = 0, tpl_idx = 0;
+
+ char *_buf;
+ int _len;
+
+ /* Global keys */
+ char **_tpl = 0;
+
+ /* Template to return */
+ struct dirhtml_template *st_tpl = 0;
+
+ cont_len = strlen(content);
+ if (cont_len <= 0) {
+ return NULL;
+ }
+
+ /* Parsing content */
+ while (i < cont_len) {
+ pos = (int) mk_api->str_search(content + i,
+ MK_DIRHTML_TAG_INIT, MK_STR_INSENSITIVE);
+
+ if (pos < 0) {
+ break;
+ }
+
+ /* Checking global tag, if it's not found, proceed with
+ * 'entry tags'
+ */
+ _tpl = (char **) _tags_global;
+ tpl_idx = mk_dirhtml_theme_match_tag(content + i + pos, _tpl);
+
+ /* if global template do not match, use the entry tags */
+ if (tpl_idx < 0) {
+ _tpl = (char **) _tags_entry;
+ tpl_idx = mk_dirhtml_theme_match_tag(content + i + pos, _tpl);
+ }
+
+ /* if tag found is known, we add them to our list */
+ if (tpl_idx >= 0) {
+
+ _buf = mk_api->str_copy_substr(content, i, i + pos);
+ _len = strlen(_buf);
+
+ /* Dummy if/else to create or pass a created st_tpl */
+ if (!st_tpl) {
+ st_tpl = mk_dirhtml_template_list_add(NULL,
+ _buf, _len, _tpl, -1);
+ }
+ else {
+ mk_dirhtml_template_list_add(&st_tpl, _buf, _len, _tpl, -1);
+ }
+ i += (pos + strlen(_tpl[tpl_idx]));
+
+ /* This means that a value need to be replaced */
+ mk_dirhtml_template_list_add(&st_tpl, NULL, -1, _tpl, tpl_idx);
+ n_tags++;
+ }
+ else {
+ i++;
+ }
+ }
+
+ if (last < cont_len) {
+ _buf = mk_api->str_copy_substr(content, i, cont_len);
+ _len = strlen(_buf);
+
+ if (n_tags <= 0) {
+ st_tpl = mk_dirhtml_template_list_add(NULL, _buf, _len, _tpl, -1);
+ }
+ else {
+ mk_dirhtml_template_list_add(&st_tpl, _buf, _len, _tpl, -1);
+ }
+ }
+
+ return st_tpl;
+}
+
+struct dirhtml_template *mk_dirhtml_template_list_add(struct dirhtml_template **header,
+ char *buf, int len, char **tpl,
+ int tag_id)
+{
+ struct dirhtml_template *node, *aux;
+
+ node = mk_api->mem_alloc_z(sizeof(struct dirhtml_template));
+ if (!node) {
+ return NULL;
+ }
+
+ node->buf = buf;
+ node->len = len;
+ node->tag_id = tag_id;
+ node->tags = tpl;
+ node->next = NULL;
+
+ if (!header || !(*header)) {
+ return (struct dirhtml_template *) node;
+ }
+
+ aux = *header;
+ while ((*aux).next != NULL) {
+ aux = (*aux).next;
+ }
+
+ (*aux).next = node;
+ return (struct dirhtml_template *) node;
+}
+
+static int mk_dirhtml_template_len(struct dirhtml_template *tpl)
+{
+ int len = 0;
+ struct dirhtml_template *aux;
+
+ aux = tpl;
+ while (aux) {
+ len++;
+ aux = aux->next;
+ }
+
+ return len;
+}
+
+static struct mk_iov *mk_dirhtml_theme_compose(struct dirhtml_template *template,
+ struct mk_list *list)
+{
+ /*
+ * template = struct { char buf ; int len, int tag }
+ * values = struct {int tag, char *value, struct *next}
+ */
+ struct mk_iov *iov;
+ struct dirhtml_template *tpl = template;
+ struct dirhtml_value *val;
+ struct mk_list *head;
+
+ int tpl_len;
+
+ tpl_len = mk_dirhtml_template_len(template);
+
+ /* we duplicate the lenght in case we get separators */
+ iov = mk_api->iov_create(1 + tpl_len * 2, 1);
+ tpl = template;
+
+ while (tpl) {
+ /* check for dynamic value */
+ if (!tpl->buf && tpl->tag_id >= 0) {
+ mk_list_foreach(head, list) {
+ val = mk_list_entry(head, struct dirhtml_value, _head);
+ if (val->tags == tpl->tags && val->tag_id == tpl->tag_id) {
+ mk_api->iov_add(iov,
+ val->value, val->len,
+ MK_FALSE);
+ mk_api->iov_add(iov,
+ val->sep.data, val->sep.len,
+ MK_FALSE);
+ break;
+ }
+ }
+ }
+ /* static */
+ else {
+ mk_api->iov_add(iov,
+ tpl->buf, tpl->len,
+ MK_FALSE);
+ }
+ tpl = tpl->next;
+ }
+
+ return iov;
+}
+
+struct dirhtml_value *mk_dirhtml_tag_assign(struct mk_list *list,
+ int tag_id, mk_ptr_t sep,
+ char *value, char **tags)
+{
+ struct dirhtml_value *aux = NULL;
+
+ aux = mk_api->mem_alloc(sizeof(struct dirhtml_value));
+ if (!aux) {
+ return NULL;
+ }
+
+ aux->tag_id = tag_id;
+ aux->value = value;
+ aux->sep = sep;
+ aux->tags = tags;
+
+ if (value) {
+ aux->len = strlen(value);
+ }
+ else {
+ aux->len = -1;
+ }
+
+ mk_list_add(&aux->_head, list);
+ return (struct dirhtml_value *) aux;
+}
+
+static void mk_dirhtml_tag_free_list(struct mk_list *list)
+{
+ struct mk_list *head;
+ struct mk_list *tmp;
+ struct dirhtml_value *target;
+
+ mk_list_foreach_safe(head, tmp, list) {
+ target = mk_list_entry(head, struct dirhtml_value, _head);
+ mk_list_del(&target->_head);
+ mk_api->mem_free(target);
+ }
+}
+
+char *mk_dirhtml_load_file(char *filename)
+{
+ char *tmp = 0, *data = 0;
+ unsigned long len;
+
+ mk_api->str_build(&tmp, &len, "%s%s", dirhtml_conf->theme_path, filename);
+
+ if (!tmp) {
+ return NULL;
+ }
+
+ data = mk_api->file_to_buffer(tmp);
+ mk_api->mem_free(tmp);
+
+ if (!data) {
+ return NULL;
+ }
+
+ return (char *) data;
+}
+
+static int mk_dirhtml_entry_cmp(const void *a, const void *b)
+{
+ struct mk_f_list *const *f_a = a;
+ struct mk_f_list *const *f_b = b;
+
+ return strcasecmp((*f_a)->name, (*f_b)->name);
+}
+
+static void mk_dirhtml_free_list(struct mk_dirhtml_request *request)
+{
+ struct mk_list *tmp;
+ struct mk_list *head;
+ struct mk_f_list *entry;
+
+ mk_list_foreach_safe(head, tmp, request->file_list) {
+ entry = mk_list_entry(head, struct mk_f_list, _head);
+ mk_list_del(&entry->_head);
+ mk_api->mem_free(entry);
+ }
+
+ mk_api->mem_free(request->file_list);
+ mk_api->mem_free(request->toc);
+}
+
+static inline struct mk_iov *enqueue_row(int i, struct mk_dirhtml_request *request)
+{
+ mk_ptr_t sep;
+ struct mk_list list;
+ struct mk_iov *iov_entry;
+
+ /* %_target_title_% */
+ if (request->toc[i]->type == DT_DIR) {
+ sep = mk_dir_iov_slash;
+ }
+ else {
+ sep = mk_dir_iov_none;
+ }
+
+ mk_list_init(&list);
+
+ /* target title */
+ mk_dirhtml_tag_assign(&list, 0, sep,
+ request->toc[i]->name,
+ (char **) _tags_entry);
+
+ /* target url */
+ mk_dirhtml_tag_assign(&list, 1, sep,
+ request->toc[i]->name, (char **) _tags_entry);
+
+ /* target name */
+ mk_dirhtml_tag_assign(&list, 2, sep,
+ request->toc[i]->name, (char **) _tags_entry);
+
+ /* target modification time */
+ mk_dirhtml_tag_assign(&list, 3, mk_dir_iov_none,
+ request->toc[i]->ft_modif, (char **) _tags_entry);
+
+ /* target size */
+ mk_dirhtml_tag_assign(&list, 4, mk_dir_iov_none,
+ request->toc[i]->size, (char **) _tags_entry);
+
+ iov_entry = mk_dirhtml_theme_compose(mk_dirhtml_tpl_entry, &list);
+
+ /* free entry list */
+ mk_dirhtml_tag_free_list(&list);
+ return iov_entry;
+}
+
+/* Release all resources for a given Request context */
+void mk_dirhtml_cleanup(struct mk_dirhtml_request *req)
+{
+ PLUGIN_TRACE("release resources");
+
+ if (req->iov_header) {
+ mk_api->iov_free(req->iov_header);
+ req->iov_header = NULL;
+ }
+ if (req->iov_entry) {
+ mk_api->iov_free(req->iov_entry);
+ req->iov_entry = NULL;
+ }
+ if (req->iov_footer) {
+ mk_api->iov_free(req->iov_footer);
+ req->iov_footer = NULL;
+ }
+ mk_dirhtml_free_list(req);
+ closedir(req->dir);
+
+ req->sr->handler_data = NULL;
+ mk_api->mem_free(req);
+ req = NULL;
+}
+
+void mk_dirhtml_cb_complete(struct mk_stream_input *in)
+{
+ struct mk_stream *stream;
+ struct mk_dirhtml_request *req;
+
+ stream = in->stream;
+ req = stream->context;
+ if (req) {
+ mk_dirhtml_cleanup(req);
+ }
+}
+
+void mk_dirhtml_cb_error(struct mk_stream *stream, int status)
+{
+#ifndef TRACE
+ (void) status;
+#endif
+ struct mk_dirhtml_request *req = stream->context;
+
+ PLUGIN_TRACE("exception: %i", status);
+
+ if (req) {
+ mk_dirhtml_cleanup(req);
+ }
+}
+
+void mk_dirhtml_cb_chunk_body_rows(struct mk_stream_input *in, long bytes)
+{
+ (void) bytes;
+
+ mk_dirhtml_cb_body_rows(in);
+}
+
+void mk_dirhtml_cb_body_rows(struct mk_stream_input *in)
+{
+ int len;
+ char tmp[16];
+ struct mk_stream *stream = in->stream;
+ struct mk_dirhtml_request *req = stream->context;
+ void (*cb_ok)(struct mk_stream_input *) = NULL;
+
+ if (req->iov_entry) {
+ mk_api->iov_free(req->iov_entry);
+ req->iov_entry = NULL;
+ }
+
+ if (req->toc_idx >= req->toc_len) {
+ if (req->chunked) {
+ len = snprintf(tmp, sizeof(tmp), "%x\r\n",
+ (int) req->iov_footer->total_len);
+ mk_stream_in_raw(req->stream,
+ NULL,
+ tmp, len,
+ NULL, NULL);
+ cb_ok = NULL;
+ }
+ else {
+ cb_ok = mk_dirhtml_cb_complete;
+ }
+
+ mk_stream_in_iov(req->stream,
+ NULL,
+ req->iov_footer,
+ NULL, NULL);
+ if (req->chunked) {
+ mk_stream_in_raw(req->stream,
+ NULL,
+ "\r\n0\r\n\r\n", 7,
+ NULL, mk_dirhtml_cb_complete);
+ }
+
+ return;
+ }
+
+ req->iov_entry = enqueue_row(req->toc_idx, req);
+ if (req->chunked) {
+ len = snprintf(tmp, sizeof(tmp), "%x\r\n",
+ (int) req->iov_entry->total_len);
+ mk_stream_in_raw(req->stream,
+ NULL,
+ tmp, len,
+ NULL, NULL);
+ cb_ok = NULL;
+ }
+ else {
+ cb_ok = mk_dirhtml_cb_body_rows;
+ }
+
+ mk_stream_in_iov(req->stream,
+ NULL,
+ req->iov_entry,
+ NULL, cb_ok);
+
+ if (req->chunked) {
+ mk_stream_in_raw(req->stream,
+ NULL,
+ "\r\n", 2,
+ mk_dirhtml_cb_chunk_body_rows, NULL);
+ }
+ req->toc_idx++;
+}
+
+/*
+ * The HTTP Headers were sent, now start registering the
+ * rows for each directory entry.
+ */
+void cb_header_finish(struct mk_stream_input *in)
+{
+ struct mk_stream *stream = in->stream;
+ struct mk_dirhtml_request *req;
+
+ req = stream->context;
+ if (req->iov_header) {
+ mk_api->iov_free(req->iov_header);
+ req->iov_header = NULL;
+ }
+ mk_dirhtml_cb_body_rows(in);
+}
+
+static int mk_dirhtml_init(struct mk_plugin *plugin,
+ struct mk_http_session *cs, struct mk_http_request *sr)
+{
+ DIR *dir;
+ int len;
+ char tmp[16];
+ unsigned int i = 0;
+ struct mk_list *head;
+ struct mk_list list;
+ struct mk_f_list *entry;
+ struct mk_dirhtml_request *request;
+ struct mk_stream *stream;
+
+ if (!(dir = opendir(sr->real_path.data))) {
+ return -1;
+ }
+
+ /* Create the main context */
+ request = mk_api->mem_alloc(sizeof(struct mk_dirhtml_request));
+ if (!request) {
+ closedir(dir);
+ return -1;
+ }
+
+ stream = mk_stream_set(NULL, cs->channel, request,
+ NULL, NULL, mk_dirhtml_cb_error);
+ if (!stream) {
+ closedir(dir);
+ free(request);
+ return -1;
+ }
+
+ request->stream = stream;
+ request->state = MK_DIRHTML_STATE_HTTP_HEADER;
+ request->dir = dir;
+ request->toc_idx = 0;
+ request->cs = cs;
+ request->sr = sr;
+ request->toc_len = 0;
+ request->chunked = MK_FALSE;
+ request->iov_header = NULL;
+ request->iov_entry = NULL;
+ request->iov_footer = NULL;
+
+ sr->handler_data = request;
+
+ request->file_list = mk_dirhtml_create_list(dir, sr->real_path.data,
+ &request->toc_len);
+
+ /* Building headers */
+ mk_api->header_set_http_status(sr, MK_HTTP_OK);
+ sr->headers.cgi = SH_CGI;
+ sr->headers.breakline = MK_HEADER_BREAKLINE;
+ sr->headers.content_type = mk_dirhtml_default_mime;
+ sr->headers.content_length = -1;
+
+ if (sr->protocol >= MK_HTTP_PROTOCOL_11) {
+ sr->headers.transfer_encoding = MK_HEADER_TE_TYPE_CHUNKED;
+ request->chunked = MK_TRUE;
+ }
+
+ /*
+ * Creating response template
+ */
+
+ mk_list_init(&list);
+
+ /* Set %_html_title_% */
+ mk_dirhtml_tag_assign(&list, 0, mk_dir_iov_none,
+ sr->uri_processed.data,
+ (char **) _tags_global);
+
+ /* Set %_theme_path_% */
+ mk_dirhtml_tag_assign(&list, 1, mk_dir_iov_none,
+ dirhtml_conf->theme_path, (char **) _tags_global);
+
+ /* HTML Header */
+ request->iov_header = mk_dirhtml_theme_compose(mk_dirhtml_tpl_header,
+ &list);
+
+ /* HTML Footer */
+ request->iov_footer = mk_dirhtml_theme_compose(mk_dirhtml_tpl_footer,
+ &list);
+ mk_dirhtml_tag_free_list(&list);
+
+ /* Creating table of contents and sorting */
+ request->toc = mk_api->mem_alloc(sizeof(struct mk_f_list *) * request->toc_len);
+
+ i = 0;
+ mk_list_foreach(head, request->file_list) {
+ entry = mk_list_entry(head, struct mk_f_list, _head);
+ request->toc[i] = entry;
+ i++;
+ }
+
+ qsort(request->toc,
+ request->toc_len,
+ sizeof(*request->toc),
+ mk_dirhtml_entry_cmp);
+
+ /* Prepare HTTP response headers */
+ mk_api->header_prepare(plugin, cs, sr);
+
+ if (request->chunked) {
+ len = snprintf(tmp, sizeof(tmp), "%x\r\n",
+ (int) request->iov_header->total_len);
+ mk_stream_in_raw(request->stream,
+ NULL,
+ tmp, len,
+ NULL, mk_dirhtml_cb_complete);
+ }
+
+ mk_stream_in_iov(request->stream,
+ NULL,
+ request->iov_header,
+ NULL, cb_header_finish);
+
+ if (request->chunked) {
+ mk_stream_in_raw(request->stream,
+ NULL,
+ "\r\n", 2,
+ NULL, NULL);
+ }
+ return 0;
+}
+
+int mk_dirlisting_plugin_init(struct mk_plugin *plugin, char *confdir)
+{
+ mk_api = plugin->api;
+
+ return mk_dirhtml_conf(confdir);
+}
+
+int mk_dirlisting_plugin_exit(struct mk_plugin *plugin)
+{
+ (void) plugin;
+
+ mk_api->mem_free(dirhtml_conf->theme);
+ mk_api->mem_free(dirhtml_conf->theme_path);
+ mk_api->mem_free(dirhtml_conf);
+
+ return 0;
+}
+
+int mk_dirlisting_stage30(struct mk_plugin *plugin,
+ struct mk_http_session *cs,
+ struct mk_http_request *sr,
+ int n_param,
+ struct mk_list *params)
+{
+ (void) plugin;
+ (void) n_param;
+ (void) params;
+
+ /* validate file_info */
+ if (sr->file_info.size == 0) {
+ return MK_PLUGIN_RET_NOT_ME;
+ }
+
+ /* This plugin just handle directories */
+ if (sr->file_info.is_directory == MK_FALSE) {
+ return MK_PLUGIN_RET_NOT_ME;
+ }
+
+ PLUGIN_TRACE("Dirlisting attending socket %i", cs->socket);
+ if (mk_dirhtml_init(plugin, cs, sr)) {
+ /*
+ * If we failed here, we cannot return RET_END - that causes a mk_bug.
+ * dirhtml_init only fails if opendir fails. Usually we're at full
+ * capacity then and can't open new files.
+ */
+ return MK_PLUGIN_RET_CLOSE_CONX;
+ }
+
+ return MK_PLUGIN_RET_END;
+}
+
+int mk_dirlisting_stage30_hangup(struct mk_plugin *plugin,
+ struct mk_http_session *cs,
+ struct mk_http_request *sr)
+{
+ (void) cs;
+ (void) plugin;
+
+ if (sr->handler_data) {
+ mk_dirhtml_cleanup(sr->handler_data);
+ }
+ return 0;
+}
+
+struct mk_plugin_stage mk_plugin_stage_dirlisting = {
+ .stage30 = &mk_dirlisting_stage30,
+ .stage30_hangup = &mk_dirlisting_stage30_hangup
+};
+
+struct mk_plugin mk_plugin_dirlisting = {
+ /* Identification */
+ .shortname = "dirlisting",
+ .name = "Directory Listing",
+ .version = MK_VERSION_STR,
+ .hooks = MK_PLUGIN_STAGE,
+
+ /* Init / Exit */
+ .init_plugin = mk_dirlisting_plugin_init,
+ .exit_plugin = mk_dirlisting_plugin_exit,
+
+ /* Init Levels */
+ .master_init = NULL,
+ .worker_init = NULL,
+
+ /* Type */
+ .stage = &mk_plugin_stage_dirlisting
+};
diff --git a/fluent-bit/lib/monkey/plugins/dirlisting/dirlisting.h b/fluent-bit/lib/monkey/plugins/dirlisting/dirlisting.h
new file mode 100644
index 000000000..678a4887b
--- /dev/null
+++ b/fluent-bit/lib/monkey/plugins/dirlisting/dirlisting.h
@@ -0,0 +1,181 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+
+/* Monkey HTTP Server
+ * ==================
+ * Copyright 2001-2017 Eduardo Silva <eduardo@monkey.io>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* dir_html.c */
+#ifndef MK_DIRHTML_H
+#define MK_DIRHTML_H
+
+#include <dirent.h>
+#include <limits.h>
+
+#define MK_DIRHTML_URL "/_mktheme"
+#define MK_DIRHTML_DEFAULT_MIME "Content-Type: text/html\r\n"
+
+/* For every directory requested, don't send more than
+ * this limit of entries.
+ */
+#define MK_DIRHTML_BUFFER_LIMIT 30
+#define MK_DIRHTML_BUFFER_GROW 5
+
+#define MK_HEADER_CHUNKED "Transfer-Encoding: Chunked\r\n\r\n"
+#define MK_DIRHTML_FMOD_LEN 24
+
+/* Theme files */
+#define MK_DIRHTML_FILE_HEADER "header.theme"
+#define MK_DIRHTML_FILE_ENTRY "entry.theme"
+#define MK_DIRHTML_FILE_FOOTER "footer.theme"
+
+#define MK_DIRHTML_TAG_INIT "%_"
+#define MK_DIRHTML_TAG_END "_%"
+#define MK_DIRHTML_SIZE_DIR "-"
+
+/* Stream state */
+#define MK_DIRHTML_STATE_HTTP_HEADER 0
+#define MK_DIRHTML_STATE_TPL_HEADER 1
+#define MK_DIRHTML_STATE_BODY 2
+#define MK_DIRHTML_STATE_FOOTER 3
+
+char *_tags_global[] = { "%_html_title_%",
+ "%_theme_path_%",
+ NULL
+};
+
+char *_tags_entry[] = { "%_target_title_%",
+ "%_target_url_%",
+ "%_target_name_%",
+ "%_target_time_%",
+ "%_target_size_%",
+ NULL
+};
+
+struct plugin_api *mk_api;
+
+struct mk_f_list
+{
+ char ft_modif[MK_DIRHTML_FMOD_LEN];
+ struct file_info info;
+ char name[NAME_MAX + 1]; /* The name can be up to NAME_MAX long; include NULL. */
+ char size[16];
+ unsigned char type;
+
+ struct mk_list _head;
+};
+
+/* Main configuration of dirhtml module */
+struct dirhtml_config
+{
+ char *theme;
+ char *theme_path;
+};
+
+/* Represent a request context */
+struct mk_dirhtml_request
+{
+ /* State */
+ int state;
+ int chunked;
+
+ /* Target directory */
+ DIR *dir;
+
+ /* Table of Content */
+ unsigned int toc_idx;
+ unsigned long toc_len;
+ struct mk_f_list **toc;
+ struct mk_list *file_list;
+
+ /* Stream handler */
+ struct mk_stream *stream;
+
+ /* Reference IOV stuff */
+ struct mk_iov *iov_header;
+ struct mk_iov *iov_entry;
+ struct mk_iov *iov_footer;
+
+ /* Session data */
+ struct mk_http_session *cs;
+ struct mk_http_request *sr;
+};
+
+
+extern const mk_ptr_t mk_dirhtml_default_mime;
+extern const mk_ptr_t mk_iov_dash;
+
+/* Global config */
+struct dirhtml_config *dirhtml_conf;
+
+/* Used to keep splitted content of every template */
+struct dirhtml_template
+{
+ char *buf;
+ int tag_id;
+ int len;
+ struct dirhtml_template *next;
+ char **tags; /* array of theme tags: [%_xaa__%, %_xyz_%] */
+};
+
+/* Templates for header, entries and footer */
+struct dirhtml_template *mk_dirhtml_tpl_header;
+struct dirhtml_template *mk_dirhtml_tpl_entry;
+struct dirhtml_template *mk_dirhtml_tpl_footer;
+
+struct dirhtml_value
+{
+ int tag_id;
+ mk_ptr_t sep; /* separator code after value */
+
+ /* string data */
+ int len;
+ char *value;
+
+ /* next node */
+ struct mk_list _head;
+
+ char **tags; /* array of tags which values correspond */
+};
+
+struct dirhtml_value *mk_dirhtml_value_global;
+
+/* Configuration struct */
+struct mk_config *conf;
+
+char *check_string(char *str);
+char *read_header_footer_file(char *file_path);
+
+int mk_dirhtml_conf();
+char *mk_dirhtml_load_file(char *filename);
+
+struct dirhtml_template *mk_dirhtml_template_create(char *content);
+
+struct dirhtml_template
+ *mk_dirhtml_template_list_add(struct dirhtml_template **header,
+ char *buf, int len, char **tpl, int tag);
+
+int mk_dirhtml_read_config(char *path);
+int mk_dirhtml_theme_load();
+int mk_dirhtml_theme_debug(struct dirhtml_template **st_tpl);
+
+struct dirhtml_value *mk_dirhtml_tag_assign(struct mk_list *list,
+ int tag_id, mk_ptr_t sep,
+ char *value, char **tags);
+
+struct f_list *get_dir_content(struct mk_http_request *sr, char *path);
+
+
+#endif