about summary refs log tree commit diff
diff options
context:
space:
mode:
authorLaurent Bercot <ska-skaware@skarnet.org>2023-09-21 10:06:09 +0000
committerLaurent Bercot <ska@appnovation.com>2023-09-21 10:06:09 +0000
commit3730ea387e3e358b7767de59f8afd602d49b17fd (patch)
tree347585d17fb2525527c90219699e3c77e1ca8607
parent877e5ffe23a5ee2fea63d01d74c81dfdf0974e53 (diff)
downloadtipidee-3730ea387e3e358b7767de59f8afd602d49b17fd.tar.gz
tipidee-3730ea387e3e358b7767de59f8afd602d49b17fd.tar.xz
tipidee-3730ea387e3e358b7767de59f8afd602d49b17fd.zip
Force redirect for incomplete directories
Signed-off-by: Laurent Bercot <ska@appnovation.com>
-rw-r--r--src/tipideed/tipideed-internal.h4
-rw-r--r--src/tipideed/tipideed.c23
2 files changed, 24 insertions, 3 deletions
diff --git a/src/tipideed/tipideed-internal.h b/src/tipideed/tipideed-internal.h
index 3eb0644..a53fc0c 100644
--- a/src/tipideed/tipideed-internal.h
+++ b/src/tipideed/tipideed-internal.h
@@ -51,6 +51,7 @@ struct global_s
   uint16_t indexn : 4 ;
   uint16_t verbosity : 3 ;
   uint16_t cont : 2 ;
+  uint16_t ssl : 1 ;
 } ;
 #define GLOBAL_ZERO \
 { \
@@ -75,7 +76,8 @@ struct global_s
   .maxcgibody = 0, \
   .indexn = 0, \
   .verbosity = 1, \
-  .cont = 1 \
+  .cont = 1, \
+  .ssl = 0 \
 }
 
 extern struct global_s g ;
diff --git a/src/tipideed/tipideed.c b/src/tipideed/tipideed.c
index 6f453f6..7202bde 100644
--- a/src/tipideed/tipideed.c
+++ b/src/tipideed/tipideed.c
@@ -55,6 +55,7 @@ static inline void prep_env (void)
   if (g.cwdlen && !stralloc_0(&g.sa)) dienomem() ;
   if (!stralloc_catb(&g.sa, basevars, sizeof(basevars))) dienomem() ;
   if (x && !stralloc_catb(&g.sa, sslvars, sizeof(sslvars))) dienomem() ;
+  g.ssl = !!x ;
   x = getenv(basevars) ;
   if (!x) strerr_dienotset(100, "PROTO") ;
   {
@@ -141,9 +142,14 @@ static uint32_t get_uint32 (char const *key)
 
 static inline unsigned int indexify (tipidee_rql const *rql, char *s, struct stat *st)
 {
+  unsigned int e = 0 ;
   size_t len = strlen(s) ;
   unsigned int i = 0 ;
-  if (s[len - 1] != '/') s[len++] = '/' ;
+  if (s[len - 1] != '/')
+  {
+    s[len++] = '/' ;
+    e = 308 ;
+  }
   for (; i < g.indexn ; i++)
   {
     strcpy(s + len, g.indexnames[i]) ;
@@ -159,7 +165,8 @@ static inline unsigned int indexify (tipidee_rql const *rql, char *s, struct sta
   }
   if (i >= g.indexn) return 404 ;
   if (S_ISDIR(st->st_mode)) die500x(rql, 103, "bad document hierarchy: ", s, " is a directory") ;
-  return 0 ;
+  if (e == 308) s[len] = 0 ;
+  return e ;
 }
 
 static inline void get_resattr (tipidee_rql const *rql, char const *res, tipidee_resattr *ra)
@@ -216,6 +223,17 @@ static inline void get_resattr (tipidee_rql const *rql, char const *res, tipidee
   }
 }
 
+static inline void force_redirect (tipidee_rql const *rql, char const *fn)
+{
+  tipidee_redirection rd = { .sub = 0, .type = 1 } ;
+  size_t len = strlen(fn) ;
+  char location[len + 8 + g.ssl] ;
+  memcpy(location, g.ssl ? "https://" : "http://", 7 + g.ssl) ;
+  memcpy(location + 7 + g.ssl, fn, len + 1) ;
+  rd.location = location ;
+  respond_30x(rql, &rd) ;
+}
+
 static inline int serve (tipidee_rql *rql, char const *docroot, size_t docrootlen, char *uribuf, tipidee_headers const *hdr, char const *body, size_t bodylen)
 {
   tipidee_resattr ra = TIPIDEE_RESATTR_ZERO ;
@@ -271,6 +289,7 @@ static inline int serve (tipidee_rql *rql, char const *docroot, size_t docrootle
       case 403 : respond_403(rql) ; return 0 ;
       case 404 : respond_404(rql) ; return 0 ;
       case 414 : respond_414(rql) ; return 0 ;
+      case 308 : force_redirect(rql, fn) ; return 0 ;
       case 0 : break ;
     }
   }