summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/config/PROTOCOL.txt42
-rw-r--r--src/config/conftree.c5
-rw-r--r--src/config/headers.c13
-rw-r--r--src/config/lexparse.c41
-rw-r--r--src/config/resattr.c56
-rw-r--r--src/include/tipidee/conf.h5
-rw-r--r--src/include/tipidee/log.h10
-rw-r--r--src/include/tipidee/resattr.h23
-rw-r--r--src/include/tipidee/tipidee.h1
-rw-r--r--src/libtipidee/deps-lib/tipidee2
-rw-r--r--src/libtipidee/tipidee_conf_get_resattr.c62
-rw-r--r--src/libtipidee/tipidee_conf_get_resattr1.c36
-rw-r--r--src/libtipidee/tipidee_log_resource.c5
-rw-r--r--src/tipideed/cgi.c5
-rw-r--r--src/tipideed/tipideed.c52
15 files changed, 228 insertions, 130 deletions
diff --git a/src/config/PROTOCOL.txt b/src/config/PROTOCOL.txt
deleted file mode 100644
index f6cc304..0000000
--- a/src/config/PROTOCOL.txt
+++ /dev/null
@@ -1,42 +0,0 @@
-* Globals
-
-G:read_timeout -> 4 bytes exit if waiting on client input for read_timeout ms
-G:write_timeout -> 4 bytes die if waiting on flush to client for write_timeout ms
-G:cgi_timeout -> 4 bytes 504 if CGI hasn't finished answering / die if NPH hasn't finished reading
-G:max_request_body_length -> 4 bytes
-G:max_cgi_body_length -> 4 bytes
-G:index_file -> file1\0file2\0file3\0 list of files to attempt when URL is a directory
-
-They all need to exist, tipidee-config creates defaults.
-
-
-* Content-Type
-
-T:extension -> string T:pdf -> application/pdf
-or individual Content-Types in resource attributes
-
-tipidee-config hardcodes a number of default content-types, they
-can be overridden.
-
-
-* Individual redirection
-
-R:vres -> Xurl R:skarnet.org/rickroll.html -> Xhttps://www.youtube.com/watch?v=dQw4w9WgXcQ
- X = '@' | redir_type (307=0, 308=1, 302=2, 301=3)
-
-
-* Prefix redirection
-
-r:prefix -> Xurlprefix r:s6.org -> Xhttps://skarnet.org/software/s6
- X = '@' | redir_type (307=0, 308=1, 302=2, 301=3)
-
-* Resource attributes
-
-A:file -> Xstring X = '@' | 1 (iscgi)
- if string nonempty: it's the content-type for the resource. If empty, default ctype
-
-a:prefix -> Xstring same, but for prefixes
-
-* NPH prefixes
-
-N:domain -> nphprefix N:skarnet.org -> nph- any CGI under skarnet.org starting with nph
diff --git a/src/config/conftree.c b/src/config/conftree.c
index d4b01ef..a146188 100644
--- a/src/config/conftree.c
+++ b/src/config/conftree.c
@@ -42,11 +42,6 @@ static int confnode_write (uint32_t d, unsigned int h, void *data)
{
node *nod = genalloc_s(node, &conftree.ga) + d ;
(void)h ;
- if ((conftree.storage->s[nod->key] & ~0x20) == 'A')
- {
- conftree.storage->s[++nod->data] |= '@' ;
- nod->datalen-- ;
- }
return cdbmake_add((cdbmaker *)data, conftree.storage->s + nod->key, nod->keylen, conftree.storage->s + nod->data, nod->datalen) ;
}
diff --git a/src/config/headers.c b/src/config/headers.c
index 31d3e69..4fcdf7d 100644
--- a/src/config/headers.c
+++ b/src/config/headers.c
@@ -25,11 +25,8 @@ static struct builtinheaders_s const builtinheaders[] =
{ .key = "Allow", .value = 0, .overridable = 0 },
{ .key = "Cache-Control", .value = "private", .overridable = 1 },
{ .key = "Connection", .value = 0, .overridable = 0 },
- { .key = "Content-Length", .value = 0, .overridable = 0 },
{ .key = "Content-Security-Policy", .value = "default-src 'self'; style-src 'self' 'unsafe-inline';", .overridable = 1 },
- { .key = "Content-Type", .value = 0, .overridable = 0 },
{ .key = "Date", .value = 0, .overridable = 0 },
- { .key = "Location", .value = 0, .overridable = 0 },
{ .key = "Referrer-Policy", .value = "no-referrer-when-downgrade", .overridable = 1 },
{ .key = "Server", .value = "tipidee/" TIPIDEE_VERSION, .overridable = 0 },
{ .key = "Status", .value = 0, .overridable = 0 },
@@ -49,7 +46,15 @@ static repo headers = \
int header_allowed (char const *key)
{
- struct builtinheaders_s const *p = BSEARCH(struct builtinheaders_s, key, builtinheaders) ;
+ static char const *const nope[] =
+ {
+ "Content-Length",
+ "Content-Type",
+ "Location"
+ } ;
+ struct builtinheaders_s const *p ;
+ if (BSEARCH(char const *, key, nope)) return 0 ;
+ p = BSEARCH(struct builtinheaders_s, key, builtinheaders) ;
return !p || p->overridable ;
}
diff --git a/src/config/lexparse.c b/src/config/lexparse.c
index b72182e..afd22a5 100644
--- a/src/config/lexparse.c
+++ b/src/config/lexparse.c
@@ -273,12 +273,11 @@ static inline void parse_redirect (char const *s, size_t const *word, size_t n,
}
}
-static void parse_bitattr (char const *s, size_t const *word, size_t n, char const *domain, size_t domainlen, mdt const *md, unsigned int bit, int set)
+static void parse_bitattr (char const *s, size_t const *word, size_t n, char const *domain, size_t domainlen, mdt const *md, uint8_t bit, int h)
{
static char const *const attr[3][2] = { { "noncgi", "cgi" }, { "nonnph", "nph", }, { "noauth", "basic-auth" } } ;
- uint8_t mask = (uint8_t)0x01 << bit ;
if (n != 1)
- strerr_dief8x(1, "too ", n > 1 ? "many" : "few", " arguments to directive ", attr[bit][set], " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ;
+ strerr_dief8x(1, "too ", n > 1 ? "many" : "few", " arguments to directive ", attr[bit][h], " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ;
if (!domain)
strerr_dief7x(1, "resource attribute ", "definition", " without a domain directive", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ;
if (s[*word] != '/')
@@ -294,24 +293,31 @@ static void parse_bitattr (char const *s, size_t const *word, size_t n, char con
key[2 + domainlen + arglen] = 0 ;
oldnode = conftree_search(key) ;
if (oldnode)
- if (g.storage.s[oldnode->data] & mask)
+ {
+ uint32_t flags, mask ;
+ uint32_unpack_big(g.storage.s + oldnode->data, &flags) ;
+ uint32_unpack_big(g.storage.s + oldnode->data + 4, &mask) ;
+ if (mask & 1 << bit)
{
char fmt[UINT32_FMT] ;
fmt[uint32_fmt(fmt, oldnode->line)] = 0 ;
- strerr_diefn(1, 13, "resource attribute ", attr[bit][set], " redefinition", " in file ", g.storage.s + md->filepos, " line ", md->linefmt, "; previous definition", " in file ", g.storage.s + oldnode->filepos, " line ", fmt, " or later") ;
- }
- else
- {
- g.storage.s[oldnode->data] |= mask ;
- if (set) g.storage.s[oldnode->data + 1] |= mask ;
- else g.storage.s[oldnode->data + 1] &= ~mask ;
+ strerr_diefn(1, 13, "resource attribute ", attr[bit][h], " redefinition", " in file ", g.storage.s + md->filepos, " line ", md->linefmt, "; previous definition", " in file ", g.storage.s + oldnode->filepos, " line ", fmt, " or later") ;
}
+ mask |= 1 << bit ;
+ if (h) flags |= 1 << bit ; else flags &= ~(1 << bit) ;
+ uint32_pack_big(g.storage.s + oldnode->data, flags) ;
+ uint32_pack_big(g.storage.s + oldnode->data + 4, mask) ;
+ }
else
{
node node ;
- char val[3] = { mask, set ? mask : 0, 0 } ;
+ uint32_t flags = h ? 1 << bit : 0 ;
+ uint32_t mask = 1 << bit ;
+ char val[9] = "\0\0\0\0\0\0\0\0" ;
+ uint32_pack_big(val, flags) ;
+ uint32_pack_big(val + 4, mask) ;
confnode_start(&node, key, md->filepos, md->line) ;
- confnode_add(&node, val, 3) ;
+ confnode_add(&node, val, 9) ;
conftree_add(&node) ;
}
}
@@ -337,19 +343,17 @@ static inline void parse_filetype (char const *s, size_t const *word, size_t n,
oldnode = conftree_search(key) ;
if (oldnode)
{
- if (g.storage.s[oldnode->data] & 0x80)
+ if (g.storage.s[oldnode->data + 8])
{
char fmt[UINT32_FMT] ;
fmt[uint32_fmt(fmt, oldnode->line)] = 0 ;
strerr_diefn(1, 12, "file-type", " redefinition", " in file ", g.storage.s + md->filepos, " line ", md->linefmt, "; previous definition", " in file ", g.storage.s + oldnode->filepos, " line ", fmt, " or later") ;
}
-
else
{
node node ;
- char val[2] = { g.storage.s[oldnode->data] | 0x80, g.storage.s[oldnode->data + 1] } ;
confnode_start(&node, key, md->filepos, md->line) ;
- confnode_add(&node, val, 2) ;
+ confnode_add(&node, g.storage.s + oldnode->data, 8) ;
confnode_add(&node, s + word[1], strlen(s + word[1]) + 1) ;
conftree_update(&node) ;
}
@@ -357,9 +361,8 @@ static inline void parse_filetype (char const *s, size_t const *word, size_t n,
else
{
node node ;
- char val[2] = { 0x80, 0x00 } ;
confnode_start(&node, key, md->filepos, md->line) ;
- confnode_add(&node, val, 2) ;
+ confnode_add(&node, "\0\0\0\0\0\0\0", 8) ;
confnode_add(&node, s + word[1], strlen(s + word[1]) + 1) ;
conftree_add(&node) ;
}
diff --git a/src/config/resattr.c b/src/config/resattr.c
new file mode 100644
index 0000000..80bd0e0
--- /dev/null
+++ b/src/config/resattr.c
@@ -0,0 +1,56 @@
+/* ISC license. */
+
+#include <skalibs/genalloc.h>
+#include <skalibs/avltree.h>
+#include <skalibs/cdbmake.h>
+
+#include "tipidee-config-internal.h"
+
+static repo resattr = \
+{ \
+ .ga = GENALLOC_ZERO, \
+ .tree = AVLTREE_INIT(8, 3, 8, &node_dtok, &node_cmp, &resattr.ga), \
+ .storage = &g.storage \
+} ;
+
+void confnode_start (node *node, char const *key, size_t filepos, uint32_t line)
+{
+ return node_start(&g.storage, node, key, filepos, line) ;
+}
+
+void confnode_add (node *node, char const *s, size_t len)
+{
+ return node_add(&g.storage, node, s, len) ;
+}
+
+node const *conftree_search (char const *key)
+{
+ return repo_search(&conftree, key) ;
+}
+
+void conftree_add (node const *node)
+{
+ return repo_add(&conftree, node) ;
+}
+
+void conftree_update (node const *node)
+{
+ return repo_update(&conftree, node) ;
+}
+
+static int confnode_write (uint32_t d, unsigned int h, void *data)
+{
+ node *nod = genalloc_s(node, &conftree.ga) + d ;
+ (void)h ;
+ if ((conftree.storage->s[nod->key] & ~0x20) == 'A')
+ {
+ conftree.storage->s[++nod->data] |= '@' ;
+ nod->datalen-- ;
+ }
+ return cdbmake_add((cdbmaker *)data, conftree.storage->s + nod->key, nod->keylen, conftree.storage->s + nod->data, nod->datalen) ;
+}
+
+int conftree_write (cdbmaker *cm)
+{
+ return avltree_iter(&conftree.tree, &confnode_write, cm) ;
+}
diff --git a/src/include/tipidee/conf.h b/src/include/tipidee/conf.h
index 5f3b697..aa8cb45 100644
--- a/src/include/tipidee/conf.h
+++ b/src/include/tipidee/conf.h
@@ -7,8 +7,10 @@
#include <stdint.h>
#include <skalibs/uint16.h>
+#include <skalibs/uint32.h>
#include <skalibs/cdb.h>
+#include <tipidee/resattr.h>
#include <tipidee/uri.h>
#define TIPIDEE_CONF_KEY_MAXLEN 0x1000U
@@ -44,4 +46,7 @@ extern int tipidee_conf_get_redirection (tipidee_conf const *, char const *, siz
extern char const *tipidee_conf_get_content_type (tipidee_conf const *, char const *) ;
extern char const *tipidee_conf_get_errorfile (tipidee_conf const *, char const *, unsigned int) ;
+extern int tipidee_conf_get_resattr1 (tipidee_conf const *, char const *, tipidee_resattr *) ; /* direct key lookup */
+extern int tipidee_conf_get_resattr (tipidee_conf const *, char const *, tipidee_resattr *) ; /* high-level */
+
#endif
diff --git a/src/include/tipidee/log.h b/src/include/tipidee/log.h
index 0904ca4..93ee386 100644
--- a/src/include/tipidee/log.h
+++ b/src/include/tipidee/log.h
@@ -11,6 +11,7 @@
#include <tipidee/rql.h>
#include <tipidee/headers.h>
+#include <tipidee/resattr.h>
#define TIPIDEE_LOG_REQUEST 0x0001
#define TIPIDEE_LOG_REFERRER 0x0002
@@ -26,15 +27,6 @@
#define TIPIDEE_LOG_DEFAULT (TIPIDEE_LOG_REQUEST | TIPIDEE_LOG_ANSWER | TIPIDEE_LOG_SIZE)
-typedef struct tipidee_resattr_s tipidee_resattr, *tipidee_resattr_ref ;
-struct tipidee_resattr_s
-{
- char const *content_type ;
- uint32_t iscgi : 1 ;
- uint32_t isnph : 1 ;
-} ;
-#define TIPIDEE_RESATTR_ZERO { .content_type = 0, .iscgi = 0, .isnph = 0 }
-
extern void tipidee_log_start (uint32_t, char const *, char const *) ;
extern void tipidee_log_exit (uint32_t, unsigned int) ;
diff --git a/src/include/tipidee/resattr.h b/src/include/tipidee/resattr.h
new file mode 100644
index 0000000..edd0a41
--- /dev/null
+++ b/src/include/tipidee/resattr.h
@@ -0,0 +1,23 @@
+/* ISC license. */
+
+#ifndef TIPIDEE_RESATTR_H
+#define TIPIDEE_RESATTR_H
+
+#include <stdint.h>
+
+#define TIPIDEE_RA_FLAG_CGI 0x0001
+#define TIPIDEE_RA_FLAG_NPH 0x0002
+#define TIPIDEE_RA_FLAG_BA 0x0004
+
+#define TIPIDEE_RA_BITS 3
+
+typedef struct tipidee_resattr_s tipidee_resattr, *tipidee_resattr_ref ;
+struct tipidee_resattr_s
+{
+ uint32_t flags ;
+ uint32_t mask ;
+ char const *content_type ;
+} ;
+#define TIPIDEE_RESATTR_ZERO { .flags = 0, .mask = 0, .content_type = 0 }
+
+#endif
diff --git a/src/include/tipidee/tipidee.h b/src/include/tipidee/tipidee.h
index 7153b7d..7c5154c 100644
--- a/src/include/tipidee/tipidee.h
+++ b/src/include/tipidee/tipidee.h
@@ -8,6 +8,7 @@
#include <tipidee/headers.h>
#include <tipidee/log.h>
#include <tipidee/method.h>
+#include <tipidee/resattr.h>
#include <tipidee/response.h>
#include <tipidee/rql.h>
#include <tipidee/uri.h>
diff --git a/src/libtipidee/deps-lib/tipidee b/src/libtipidee/deps-lib/tipidee
index b20898b..d71ef89 100644
--- a/src/libtipidee/deps-lib/tipidee
+++ b/src/libtipidee/deps-lib/tipidee
@@ -4,6 +4,8 @@ tipidee_conf_get_argv.o
tipidee_conf_get_content_type.o
tipidee_conf_get_errorfile.o
tipidee_conf_get_redirection.o
+tipidee_conf_get_resattr.o
+tipidee_conf_get_resattr1.o
tipidee_conf_get_responseheaders.o
tipidee_conf_get_string.o
tipidee_conf_get_uint32.o
diff --git a/src/libtipidee/tipidee_conf_get_resattr.c b/src/libtipidee/tipidee_conf_get_resattr.c
new file mode 100644
index 0000000..9b33208
--- /dev/null
+++ b/src/libtipidee/tipidee_conf_get_resattr.c
@@ -0,0 +1,62 @@
+/* ISC license. */
+
+#include <string.h>
+
+#include <skalibs/bytestr.h>
+
+#include <tipidee/conf.h>
+#include <tipidee/resattr.h>
+
+#define FULLMASK ((1 << TIPIDEE_RA_BITS) - 1)
+
+int tipidee_conf_get_resattr (tipidee_conf const *conf, char const *res, tipidee_resattr *ra)
+{
+ tipidee_resattr rra = TIPIDEE_RESATTR_ZERO ;
+ size_t len = strlen(res) + 2 ;
+ char key[len + 1] ;
+ key[0] = 'A' ; key[1] = ':' ;
+ memcpy(key + 2, res, len - 2) ;
+ key[len] = '/' ;
+ while (len > 2 && (rra.mask & FULLMASK) != FULLMASK)
+ {
+ tipidee_resattr atom ;
+ int r ;
+ while (len > 2 && key[len] != '/') len-- ;
+ if (len <= 2) break ;
+ key[len--] = 0 ;
+ r = tipidee_conf_get_resattr1(conf, key, &atom) ;
+ if (r == -1) return 0 ;
+ if (r)
+ {
+ rra.flags = (~rra.mask & atom.mask & atom.flags) | ((rra.mask | ~atom.mask) & rra.flags) ; /* yup */
+ rra.mask |= atom.mask ;
+ if (!rra.content_type) rra.content_type = atom.content_type ;
+ }
+ key[0] = 'a' ;
+ }
+
+ if (!(rra.mask & TIPIDEE_RA_FLAG_NPH))
+ {
+ char const *nphprefix ;
+ char *p = strchr(key+2, '/') ;
+ if (p) *p = 0 ;
+ key[0] = 'N' ;
+ nphprefix = tipidee_conf_get_string(conf, key) ;
+ if (nphprefix)
+ {
+ char const *base = strrchr(res, '/') ;
+ if (base && str_start(base + 1, nphprefix)) rra.flags |= 1 << TIPIDEE_RA_FLAG_NPH ;
+ else rra.flags &= ~(1 << TIPIDEE_RA_FLAG_NPH) ;
+ rra.mask |= 1 << TIPIDEE_RA_FLAG_NPH ;
+ }
+ }
+
+ if (!(rra.flags & TIPIDEE_RA_FLAG_CGI) && !rra.content_type)
+ {
+ rra.content_type = tipidee_conf_get_content_type(conf, res) ;
+ if (!rra.content_type) return 0 ;
+ }
+
+ *ra = rra ;
+ return 1 ;
+}
diff --git a/src/libtipidee/tipidee_conf_get_resattr1.c b/src/libtipidee/tipidee_conf_get_resattr1.c
new file mode 100644
index 0000000..182a7ba
--- /dev/null
+++ b/src/libtipidee/tipidee_conf_get_resattr1.c
@@ -0,0 +1,36 @@
+/* ISC license. */
+
+#include <stdint.h>
+#include <errno.h>
+#include <string.h>
+
+#include <skalibs/uint32.h>
+#include <skalibs/cdb.h>
+
+#include <tipidee/resattr.h>
+#include <tipidee/conf.h>
+
+#include <skalibs/posixishard.h>
+
+int tipidee_conf_get_resattr1 (tipidee_conf const *conf, char const *key, tipidee_resattr *ra)
+{
+ tipidee_resattr atom = TIPIDEE_RESATTR_ZERO ;
+ cdb_data data ;
+ if (!tipidee_conf_get(conf, key, &data)) return errno == ENOENT ? 0 : -1 ;
+ if (data.len < 9 || data.s[data.len - 1]) return (errno = EPROTO, -1) ;
+ uint32_unpack_big(data.s, &atom.flags) ;
+ uint32_unpack_big(data.s + 4, &atom.mask) ;
+ data.s += 8 ; data.len -= 8 ;
+ if (*data.s)
+ {
+ size_t len = strlen(data.s) + 1 ;
+ if (len > data.len) return (errno = EPROTO, -1) ;
+ atom.content_type = data.s ;
+ data.s += len ;
+ data.len -= len ;
+ }
+ else data.len-- ;
+ if (data.len) return (errno = EPROTO, -1) ;
+ *ra = atom ;
+ return 1 ;
+}
diff --git a/src/libtipidee/tipidee_log_resource.c b/src/libtipidee/tipidee_log_resource.c
index 75196b0..efdea69 100644
--- a/src/libtipidee/tipidee_log_resource.c
+++ b/src/libtipidee/tipidee_log_resource.c
@@ -4,6 +4,7 @@
#include <skalibs/strerr.h>
+#include <tipidee/resattr.h>
#include <tipidee/log.h>
void tipidee_log_resource (uint32_t v, tipidee_rql const *rql, char const *file, tipidee_resattr const *ra, char const *infopath)
@@ -19,8 +20,8 @@ void tipidee_log_resource (uint32_t v, tipidee_rql const *rql, char const *file,
a[m++] = " resource " ;
a[m++] = file ;
a[m++] = " type " ;
- a[m++] = ra->iscgi ? ra->isnph ? "nph" : "cgi" : ra->content_type ;
- if (ra->iscgi && infopath)
+ a[m++] = ra->flags & TIPIDEE_RA_FLAG_CGI ? ra->flags & TIPIDEE_RA_FLAG_NPH ? "nph" : "cgi" : ra->content_type ;
+ if (ra->flags & TIPIDEE_RA_FLAG_CGI && infopath)
{
a[m++] = " path_info /" ;
a[m++] = infopath ;
diff --git a/src/tipideed/cgi.c b/src/tipideed/cgi.c
index 9751911..43fb98d 100644
--- a/src/tipideed/cgi.c
+++ b/src/tipideed/cgi.c
@@ -364,6 +364,7 @@ int respond_cgi (tipidee_rql *rql, char const *docroot, char const *fn, size_t d
modify_env(rql, docroot, hdr, bodylen, fn + docrootlen, infopath) ;
env_merge(envp, envmax, (char const *const *)environ, g.envlen, g.sa.s + g.cwdlen + 1, g.sa.len - (g.cwdlen+1)) ;
g.sa.len = sabase ;
- return ra->isnph ? do_nph(rql, docroot, argv, envp, body, bodylen) :
- do_cgi(rql, docroot, argv, envp, body, bodylen, uribuf) ;
+ return ra->flags & TIPIDEE_RA_FLAG_NPH ?
+ do_nph(rql, docroot, argv, envp, body, bodylen) :
+ do_cgi(rql, docroot, argv, envp, body, bodylen, uribuf) ;
}
diff --git a/src/tipideed/tipideed.c b/src/tipideed/tipideed.c
index da4724b..4df6e8f 100644
--- a/src/tipideed/tipideed.c
+++ b/src/tipideed/tipideed.c
@@ -199,50 +199,8 @@ static inline void get_resattr (tipidee_rql const *rql, char const *docroot, cha
if (sarealpath(&g.sa, res) == -1 || !stralloc_0(&g.sa)) die500sys(rql, 111, docroot, "realpath ", res) ;
if (strncmp(g.sa.s + pos, g.sa.s, g.cwdlen) || g.sa.s[pos + g.cwdlen] != '/')
die500x(rql, 102, docroot, "resource ", res, " points outside of the server's root") ;
-
- {
- char const *attr = 0 ;
- size_t len = g.sa.len - pos - g.cwdlen + 1 ;
- char key[len + 1] ;
- key[0] = 'A' ; key[1] = ':' ;
- memcpy(key + 2, g.sa.s + pos + 1 + g.cwdlen, len - 2) ;
- key[len] = '/' ;
- errno = ENOENT ;
- while (!attr)
- {
- if (errno != ENOENT) die500x(rql, 102, docroot, "invalid configuration data for ", key) ;
- while (len > 2 && key[len] != '/') len-- ;
- if (len <= 2) break ;
- key[len--] = 0 ;
- attr = tipidee_conf_get_string(&g.conf, key) ;
- key[0] = 'a' ;
- }
- if (attr)
- {
- if (*attr < '@' || *attr > 'G') die500x(rql, 102, docroot, "invalid configuration data for ", key) ;
- ra->iscgi = *attr & ~'@' & 1 ;
- if (attr[1]) ra->content_type = attr + 1 ;
- if (ra->iscgi)
- {
- char const *nphprefix ;
- char *p ;
- key[0] = 'N' ;
- p = strchr(key+2, '/') ;
- if (p) *p = 0 ;
- nphprefix = tipidee_conf_get_string(&g.conf, key) ;
- if (nphprefix)
- {
- char const *base = strrchr(g.sa.s + pos + g.cwdlen, '/') ;
- if (str_start(base + 1, nphprefix)) ra->isnph = 1 ;
- }
- }
- }
- }
- if (!ra->iscgi && !ra->content_type)
- {
- ra->content_type = tipidee_conf_get_content_type(&g.conf, g.sa.s + pos + g.cwdlen) ;
- if (!ra->content_type) die500sys(rql, 111, docroot, "get content type for ", g.sa.s + pos + g.cwdlen) ;
- }
+ if (!tipidee_conf_get_resattr(&g.conf, g.sa.s + pos + g.cwdlen + 1, ra))
+ die500sys(rql, 102, docroot, "look up resource attributes for ", g.sa.s + pos + g.cwdlen + 1) ;
g.sa.len = pos ;
}
@@ -321,18 +279,18 @@ static inline int serve (tipidee_rql *rql, char const *docroot, char *uribuf, ti
get_resattr(rql, docroot, fn, &ra) ;
- if (!ra.iscgi)
+ if (!ra.flags & TIPIDEE_RA_FLAG_CGI)
{
if (infopath) { respond_404(rql, docroot) ; return 0 ; }
if (rql->m == TIPIDEE_METHOD_POST) exit_405(rql) ;
}
if (rql->m == TIPIDEE_METHOD_OPTIONS)
- return respond_options(rql, 2 | ra.iscgi) ;
+ return respond_options(rql, 2 | !!(ra.flags & TIPIDEE_RA_FLAG_CGI)) ;
tipidee_log_resource(g.logv, rql, fn, &ra, infopath) ;
- if (ra.iscgi)
+ if (ra.flags & TIPIDEE_RA_FLAG_CGI)
return respond_cgi(rql, docroot, fn, docrootlen, infopath, uribuf, hdr, &ra, body, bodylen) ;
infopath = tipidee_headers_search(hdr, "If-Modified-Since") ;