version 0.2.1
[fms.git] / libs / shttpd / io_ssi.c
index 84176e1..74993f2 100644 (file)
@@ -11,8 +11,6 @@
 
 #include "defs.h"
 
-#if !defined(NO_SSI)
-
 #define        CMDBUFSIZ       512             /* SSI command buffer size      */
 #define        NEST_MAX        6               /* Maximum nesting level        */
 
@@ -59,16 +57,12 @@ shttpd_register_ssi_func(struct shttpd_ctx *ctx, const char *name,
 }
 
 void
-free_ssi_funcs(struct shttpd_ctx *ctx)
+ssi_func_destructor(struct llhead *lp)
 {
-       struct llhead   *lp, *tmp;
-       struct ssi_func *e;
+       struct ssi_func *e = LL_ENTRY(lp, struct ssi_func, link);
 
-       LL_FOREACH_SAFE(&ctx->ssi_funcs, lp, tmp) {
-               e = LL_ENTRY(lp, struct ssi_func, link);
-               free(e->name);
-               free(e);
-       }
+       free(e->name);
+       free(e);
 }
 
 static const struct ssi_func *
@@ -94,6 +88,16 @@ call(struct ssi *ssi, const char *name,
 
        (void) memset(arg, 0, sizeof(*arg));
 
+       /*
+        * SSI function may be called with parameters. These parameters
+        * are passed as arg->in.buf, arg->in.len vector.
+        */
+       arg->in.buf = strchr(name, ' ');
+       if (arg->in.buf != NULL) {
+               *arg->in.buf++ = '\0';
+               arg->in.len = strlen(arg->in.buf);
+       }
+
        if ((ssi_func = find_ssi_func(ssi, name)) != NULL) {
                arg->priv = ssi->conn;
                arg->user_data = ssi_func->user_data;
@@ -135,7 +139,7 @@ get_path(struct conn *conn, const char *src,
                {NULL,          0},
        };
        struct vec      *vec;
-       const char      *p;
+       const char      *p, *root = conn->ctx->options[OPT_ROOT];
        int             len;
 
        for (vec = accepted; vec->len > 0; vec++)
@@ -146,14 +150,14 @@ get_path(struct conn *conn, const char *src,
                                break;
                        if (vec->len == 6) {
                                len = my_snprintf(dst, dst_len, "%s%c%s",
-                                   conn->ctx->document_root, DIRSEP, conn->uri);
+                                   root, DIRSEP, conn->uri);
                                while (len > 0 && dst[len] != '/')
                                        len--;
                                dst += len;
                                dst_len -= len;
                        } else if (vec->len == 9) {
                                len = my_snprintf(dst, dst_len, "%s%c",
-                                   conn->ctx->document_root, DIRSEP);
+                                   root, DIRSEP);
                                dst += len;
                                dst_len -= len;
                        }
@@ -196,16 +200,16 @@ do_include(struct ssi *ssi)
 static char *
 trim_spaces(struct ssi_inc *inc)
 {
-       unsigned char   *p = inc->buf + inc->nbuf - 2;
+       char    *p = inc->buf + inc->nbuf - 2;
 
        /* Trim spaces from the right */
        *p-- = '\0';
-       while (isspace(*p))
+       while (isspace(* (unsigned char *) p))
                *p-- = '\0';
 
        /* Shift pointer to the start of attributes */
-       for (p = inc->buf; !isspace(*p); p++);
-       while (*p && isspace(*p)) p++;
+       for (p = inc->buf; !isspace(* (unsigned char *) p); p++);
+       while (*p && isspace(* (unsigned char *) p)) p++;
 
        return (p);
 }
@@ -214,15 +218,16 @@ static void
 do_if(struct ssi *ssi)
 {
        struct ssi_inc  *inc = ssi->incs + ssi->nest;
-       unsigned char   *name = trim_spaces(inc);
+       char            *name = trim_spaces(inc);
 
        inc->cond = evaluate(ssi, name) ? SSI_GO : SSI_STOP;
 }
+
 static void
 do_elif(struct ssi *ssi)
 {
        struct ssi_inc  *inc = ssi->incs + ssi->nest;
-       unsigned char   *name = trim_spaces(inc);
+       char            *name = trim_spaces(inc);
 
        if (inc->cond == SSI_STOP && evaluate(ssi, name))
                inc->cond = SSI_GO;
@@ -258,8 +263,8 @@ do_call2(struct ssi *ssi, char *buf, int len, int *n)
 static void
 do_call(struct ssi *ssi, char *buf, int len, int *n)
 {
-       struct ssi_inc          *inc = ssi->incs + ssi->nest;
-       unsigned char           *name = trim_spaces(inc);
+       struct ssi_inc  *inc = ssi->incs + ssi->nest;
+       char            *name = trim_spaces(inc);
 
        if (inc->cond == SSI_GO) {
                (void) memmove(inc->buf, name, strlen(name) + 1);
@@ -290,8 +295,7 @@ static void
 do_exec(struct ssi *ssi, char *buf, int len, int *n)
 {
        struct ssi_inc  *inc = ssi->incs + ssi->nest;
-       unsigned char   *e, *p;
-       char            cmd[sizeof(inc->buf)];
+       char            cmd[sizeof(inc->buf)], *e, *p;
 
        p = trim_spaces(inc);
 
@@ -354,7 +358,6 @@ read_ssi(struct stream *stream, void *vbuf, size_t len)
        char            *buf = vbuf;
        int             ch = EOF, n = 0;
 
-
 again:
 
        if (inc->state == SSI_CALL)
@@ -376,6 +379,15 @@ again:
                        }
                        break;
 
+               /*
+                * We are buffering whole SSI command, until closing "-->".
+                * That means that when do_command() is called, we can rely
+                * on that full command with arguments is buffered in and
+                * there is no need for streaming.
+                * Restrictions:
+                *  1. The command must fit in CMDBUFSIZ
+                *  2. HTML comments inside the command ? Not sure about this.
+                */
                case SSI_BUF:
                        if (inc->nbuf >= sizeof(inc->buf) - 1) {
                                pass(inc, buf + n, &n);
@@ -393,7 +405,12 @@ again:
                        }
                        break;
 
+               case SSI_EXEC:
+               case SSI_CALL:
+                       break;
+
                default:
+                       /* Never happens */
                        abort();
                        break;
                }
@@ -463,5 +480,3 @@ const struct io_class       io_ssi =  {
        NULL,
        close_ssi
 };
-
-#endif /* NO_SSI */