summaryrefslogtreecommitdiffabout
authorSergey Poznyakoff <gray@gnu.org>2018-02-15 08:18:59 (GMT)
committer Sergey Poznyakoff <gray@gnu.org>2018-02-15 08:18:59 (GMT)
commit39691861000586efaf0f6fdead742f73c7c734a3 (patch) (side-by-side diff)
treeded257ec06d64b35e1f3e1200a76dc95f7f56621
parent353e3210fefe141bbde7d117dbf07752261e37a8 (diff)
downloadfileserv-39691861000586efaf0f6fdead742f73c7c734a3.tar.gz
fileserv-39691861000586efaf0f6fdead742f73c7c734a3.tar.bz2
Support for configurable icons in fancy listing mode
* src/icon.c: New file. * src/Makefile.am: Add new sources. * src/catfile.c (catfile_n): Compress trailing slashes in dir, and remove such in file. This makes sure that the returned value never ends in slash, which is necessary in particular for lstat to work correctly. * src/config.c: New global keywords: name-icon, type-icon and mime-icon. * src/defidx.html: Update. * src/fileserv.h: Update. * src/idx.c: New expansion command: iconlookup. Rename icon to iconsrc, and alt to iconalt.
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--src/Makefile.am2
-rw-r--r--src/catfile.c31
-rw-r--r--src/config.c100
-rw-r--r--src/defidx.html12
-rw-r--r--src/fileserv.h15
-rw-r--r--src/icon.c109
-rw-r--r--src/idx.c60
7 files changed, 291 insertions, 38 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 657e47b..b793023 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,7 +1,7 @@
bin_PROGRAMS=fileserv
fileserv_SOURCES=fileserv.c runas.c fileserv.h logger.c pidfile.c\
wordsplit.c wordsplit.h catfile.c config.c idx.c defidx.h\
- mem.c remoteip.c
+ mem.c remoteip.c icon.c
BUILT_SOURCES=defidx.h
if FSRV_WRAP
fileserv_SOURCES += wrapacl.c
diff --git a/src/catfile.c b/src/catfile.c
index 56ee0a9..929e15e 100644
--- a/src/catfile.c
+++ b/src/catfile.c
@@ -5,21 +5,26 @@
char *
catfile_n(char const *dir, size_t len, char const *file)
{
- size_t sz;
- char *p;
+ size_t flen;
+ char *res, *p;
- sz = len;
- if (sz > 0 && dir[sz-1] != '/')
- sz++;
- if (*file == '/')
+ while (len > 0 && dir[len-1] == '/')
+ len--;
+ while (*file == '/')
file++;
- sz += strlen(file);
- p = xmalloc(sz + 1);
- memcpy(p, dir, len);
- if (p[len-1] != '/')
- p[len++] = '/';
- strcpy(p + len, file);
- return p;
+ flen = strlen(file);
+ while (flen && file[flen-1] == '/')
+ --flen;
+ res = xmalloc(len + flen + 2);
+ memcpy(res, dir, len);
+ p = res + len;
+ if (flen) {
+ *p++ = '/';
+ memcpy(p, file, flen);
+ p += flen;
+ }
+ *p = 0;
+ return res;
}
char *
diff --git a/src/config.c b/src/config.c
index 1cb591d..a7561e7 100644
--- a/src/config.c
+++ b/src/config.c
@@ -438,6 +438,103 @@ set_mapping(size_t argc, char **argv, CONFIG *conf,
return 0;
}
+/* set-mime-icon icon [ALT=X] mime-type ...
+ */
+static int
+set_mime_icon(size_t argc, char **argv, CONFIG *conf,
+ char const *file, int line)
+{
+ size_t i;
+ char const *icon;
+ char const *alt = NULL;
+
+ if (argc < 3) {
+ error("%s:%d: expected two or more arguments", file, line);
+ return 1;
+ }
+
+ icon = argv[1];
+
+ i = 2;
+ if (strncasecmp(argv[i], "alt=", 4) == 0) {
+ alt = argv[i] + 4;
+ i++;
+ }
+
+ if (i == argc) {
+ error("%s:%d: expected one or more mime types", file, line);
+ return 1;
+ }
+
+
+ for (; i < argc; i++)
+ add_icon_by_mime(argv[i], icon, alt);
+
+ return 0;
+}
+
+static int
+set_name_icon(size_t argc, char **argv, CONFIG *conf,
+ char const *file, int line)
+{
+ size_t i;
+ char const *icon;
+ char const *alt = NULL;
+
+ if (argc < 3) {
+ error("%s:%d: expected two or more arguments", file, line);
+ return 1;
+ }
+
+ icon = argv[1];
+
+ i = 2;
+ if (strncasecmp(argv[i], "alt=", 4) == 0) {
+ alt = argv[i] + 4;
+ i++;
+ }
+
+ if (i == argc) {
+ error("%s:%d: expected one or more mime types", file, line);
+ return 1;
+ }
+
+
+ for (; i < argc; i++)
+ add_icon_by_name(argv[i], icon, alt);
+
+ return 0;
+}
+
+static int
+set_type_icon(size_t argc, char **argv, CONFIG *conf,
+ char const *file, int line)
+{
+ size_t i;
+ char const *icon;
+ char const *alt = NULL;
+
+ if (argc < 3) {
+ error("%s:%d: expected two or three arguments", file, line);
+ return 1;
+ }
+
+ icon = argv[1];
+
+ i = 2;
+ if (strncasecmp(argv[i], "alt=", 4) == 0) {
+ alt = argv[i] + 4;
+ i++;
+ }
+
+ if (i == argc) {
+ error("%s:%d: expected file type", file, line);
+ return 1;
+ }
+
+ add_icon_by_type(argv[i], icon, alt);
+ return 0;
+}
struct config_keyword {
@@ -453,6 +550,9 @@ static struct config_keyword keywords[] = {
{ CTXGLOB, "listen", set_listen },
{ CTXGLOB, "index-template", set_index_template },
{ CTXGLOB, "index-css", set_index_css },
+ { CTXGLOB, "mime-icon", set_mime_icon },
+ { CTXGLOB, "name-icon", set_name_icon },
+ { CTXGLOB, "type-icon", set_type_icon },
{ CTXGLOB, "access-file-name", set_dotfile },
{ CTXGLOB, "forwarded-header", set_forwarded_header },
{ CTXGLOB, "trusted-proxy", set_trusted_proxy },
diff --git a/src/defidx.html b/src/defidx.html
index 12bea9f..385eeec 100644
--- a/src/defidx.html
+++ b/src/defidx.html
@@ -11,8 +11,8 @@
<table id="indexlist">
<tr class="indexhead">
<th class="indexcolicon">
- {% if $(icon blank) %}
- <img src="{% $(icon blank) %}" alt="[ICO]">
+ {% if $(iconlookup BLANK) %}
+ <img src="{% $(iconsrc) %}" alt="[{% $(iconalt) %}]">
{% else %}
[ICO]
{% endif %}
@@ -36,8 +36,8 @@
{% if $(updir $URI) %}
<tr class="odd">
<td class="indexcolicon">
- {% if $(icon back) %}
- <img src="{% $(icon 'back') %}" alt="[PARENTDIR]">
+ {% if $(iconlookup "..") %}
+ <img src="{% $(iconsrc) %}" alt=" {% $(iconalt) %}]">
{% else %}
[PARENTDIR]
{% endif %}
@@ -53,8 +53,8 @@
{% loop %}
<tr class="{% $ROWCLASS %}">
<td class="indexcolicon">
- {% if $(icon $MIMETYPE) %}
- <img src="{% $(icon $MIMETYPE) %}" alt="[{% $(alt $MIMETYPE) %}]">
+ {% if $(iconlookup "$FILENAME" "$MIMETYPE" "$FILETYPE") %}
+ <img src="{% $(iconsrc) %}" alt="[{% $(iconalt) %}]">
{% else %}
[{% $FILETYPE %}]
{% endif %}
diff --git a/src/fileserv.h b/src/fileserv.h
index 1eda56b..d22d927 100644
--- a/src/fileserv.h
+++ b/src/fileserv.h
@@ -18,6 +18,7 @@
#include <stdlib.h>
#include <stdarg.h>
#include <regex.h>
+#include <sys/queue.h>
#ifndef SIZE_T_MAX
# define SIZE_T_MAX ((size_t)-1)
@@ -127,3 +128,17 @@ void parse_template_file(char const *file_name);
void trusted_ip_add(char const *s);
struct MHD_Connection;
char *get_remote_ip(struct MHD_Connection *conn);
+
+typedef struct icon {
+ char *name;
+ char *src;
+ char *alt;
+ TAILQ_ENTRY(icon) link;
+} ICON;
+
+ICON const *icon_by_mime(char const *type);
+void add_icon_by_mime(char const *type, char const *src, char const *alt);
+ICON const *icon_by_name(char const *name);
+void add_icon_by_name(char const *name, char const *src, char const *alt);
+ICON const *icon_by_type(char const *type);
+void add_icon_by_type(char const *name, char const *src, char const *alt);
diff --git a/src/icon.c b/src/icon.c
new file mode 100644
index 0000000..cd77968
--- a/dev/null
+++ b/src/icon.c
@@ -0,0 +1,109 @@
+#include <stdlib.h>
+#include <fnmatch.h>
+#include <string.h>
+#include "fileserv.h"
+
+typedef TAILQ_HEAD(icon_list,icon) ICON_LIST;
+
+static void
+add_icon(ICON_LIST *lst, char const *type, char const *src, char const *alt)
+{
+ ICON *icon;
+
+ icon = xcalloc(1, sizeof(icon[0]));
+ icon->name = xstrdup(type);
+ icon->src = xstrdup(src);
+ icon->alt = alt ? xstrdup(alt) : NULL;
+
+ TAILQ_INSERT_TAIL(lst, icon, link);
+}
+
+static ICON_LIST mime_icon_list = TAILQ_HEAD_INITIALIZER(mime_icon_list);
+
+ICON const *
+icon_by_mime(char const *type)
+{
+ ICON *icon;
+
+ TAILQ_FOREACH(icon, &mime_icon_list, link) {
+ if (fnmatch(icon->name, type, 0) == 0)
+ return icon;
+ }
+ return NULL;
+}
+
+void
+add_icon_by_mime(char const *type, char const *src, char const *alt)
+{
+ return add_icon(&mime_icon_list, type, src, alt);
+}
+
+static ICON_LIST suf_icon_list = TAILQ_HEAD_INITIALIZER(suf_icon_list);
+
+void
+add_icon_by_name(char const *name, char const *src, char const *alt)
+{
+ ICON *icon, *cur;
+ size_t len, i;
+
+ icon = xcalloc(1, sizeof(icon[0]));
+ len = strlen(name);
+ icon->name = xmalloc(len + 1);
+ for (i = 0; i < len; i++)
+ icon->name[i] = name[len-i-1];
+ icon->name[i] = 0;
+ icon->src = xstrdup(src);
+ icon->alt = alt ? xstrdup(alt) : NULL;
+
+ TAILQ_FOREACH(cur, &suf_icon_list, link) {
+ if (strlen(cur->name) < len) {
+ TAILQ_INSERT_BEFORE(cur, icon, link);
+ return;
+ }
+ }
+ TAILQ_INSERT_TAIL(&suf_icon_list, icon, link);
+}
+
+static int
+sufcmp(char const *suf, char const *end, char const *beg)
+{
+ while (*suf) {
+ if (end == beg || *suf++ != *--end)
+ return 1;
+ }
+ return 0;
+}
+
+ICON const *
+icon_by_name(char const *name)
+{
+ ICON *icon;
+ char const *end = name + strlen(name);
+
+ TAILQ_FOREACH(icon, &suf_icon_list, link) {
+ if (sufcmp(icon->name, end, name) == 0)
+ return icon;
+ }
+ return NULL;
+}
+
+static ICON_LIST type_icon_list = TAILQ_HEAD_INITIALIZER(type_icon_list);
+
+ICON const *
+icon_by_type(char const *type)
+{
+ ICON *icon;
+
+ TAILQ_FOREACH(icon, &type_icon_list, link) {
+ if (strcmp(icon->name, type) == 0)
+ return icon;
+ }
+ return NULL;
+}
+
+void
+add_icon_by_type(char const *name, char const *src, char const *alt)
+{
+ return add_icon(&type_icon_list, name, src, alt);
+}
+
diff --git a/src/idx.c b/src/idx.c
index 8a74754..bd1286f 100644
--- a/src/idx.c
+++ b/src/idx.c
@@ -436,6 +436,7 @@ typedef struct {
int wsflags;
INDEX_SORT_COL col;
INDEX_SORT_ORD ord;
+ ICON const *icon;
#define expansion ws.ws_wordv[0]
} EVAL_ENV;
@@ -602,7 +603,7 @@ exp_filetype(char **ret, EVAL_ENV *env)
{
char const *s = " ";
if (env->ent)
- s = S_ISDIR(env->ent->st.st_mode) ? "DIR" : "FILE";
+ s = S_ISDIR(env->ent->st.st_mode) ? "DIRECTORY" : "FILE";
*ret = xstrdup(s);
return WRDSE_OK;
}
@@ -636,24 +637,43 @@ template_getvar(char **ret, const char *var, size_t len, void *clos)
}
static int
-cmd_alt(char **ret, char **argv, EVAL_ENV *env)
-{
- char *s = strdup(argv[1] ? argv[1] : "");
- if (!s)
- return WRDSE_NOSPACE;
- *ret = s;
- for (; *s; s++)
- *s = toupper(*s);
- return WRDSE_OK;
+cmd_iconlookup(char **ret, char **argv, EVAL_ENV *env)
+{
+ ICON const *icon = NULL;
+ if (argv[1]) {
+ icon = icon_by_name(argv[1]);
+ if (!icon && argv[2]) {
+ icon = icon_by_mime(argv[2]);
+ if (!icon && argv[3])
+ icon = icon_by_type(argv[3]);
+ }
+ }
+ env->icon = icon;
+ *ret = strdup(icon ? icon->src : "");
+ return *ret ? WRDSE_OK : WRDSE_NOSPACE;
}
static int
-cmd_icon(char **ret, char **argv, EVAL_ENV *env)
+cmd_iconsrc(char **ret, char **argv, EVAL_ENV *env)
{
- /* FIXME */
- *ret = strdup("");
+ char const *s = "";
+ if (env->icon)
+ s = env->icon->src;
+
+ *ret = strdup(s);
return *ret ? WRDSE_OK : WRDSE_NOSPACE;
-}
+}
+
+static int
+cmd_iconalt(char **ret, char **argv, EVAL_ENV *env)
+{
+ char const *s = "";
+ if (env->icon && env->icon->alt)
+ s = env->icon->alt;
+
+ *ret = strdup(s);
+ return *ret ? WRDSE_OK : WRDSE_NOSPACE;
+}
static int
cmd_updir(char **ret, char **argv, EVAL_ENV *env)
@@ -695,12 +715,16 @@ static int
template_command(char **ret, const char *cmd, size_t len, char **argv,
void *clos)
{
- if (strcmp(argv[0], "icon") == 0) {
- return cmd_icon(ret, argv, clos);
+ if (strcmp(argv[0], "iconlookup") == 0) {
+ return cmd_iconlookup(ret, argv, clos);
+ }
+
+ if (strcmp(argv[0], "iconsrc") == 0) {
+ return cmd_iconsrc(ret, argv, clos);
}
- if (strcmp(argv[0], "alt") == 0) {
- return cmd_alt(ret, argv, clos);
+ if (strcmp(argv[0], "iconalt") == 0) {
+ return cmd_iconalt(ret, argv, clos);
}
if (strcmp(argv[0], "updir") == 0) {

Return to:

Send suggestions and report system problems to the System administrator.