diff src/http/modules/ngx_http_ssi_filter.c @ 239:574bea0142be

nginx-0.0.1-2004-01-26-11:52:49 import
author Igor Sysoev <igor@sysoev.ru>
date Mon, 26 Jan 2004 08:52:49 +0000
parents 049e78b1f852
children 725129fdd524
line wrap: on
line diff
--- a/src/http/modules/ngx_http_ssi_filter.c
+++ b/src/http/modules/ngx_http_ssi_filter.c
@@ -7,7 +7,7 @@
 #define NGX_HTTP_SSI_COMMAND_LEN      31
 #define NGX_HTTP_SSI_PARAM_LEN        31
 
-#define NGX_HTTP_SSI_DONE             1
+#define NGX_HTTP_SSI_COPY             1
 #define NGX_HTTP_SSI_INVALID_COMMAND  2
 #define NGX_HTTP_SSI_INVALID_PARAM    3
 #define NGX_HTTP_SSI_INVALID_VALUE    4
@@ -15,175 +15,267 @@
 
 
 typedef struct {
-    ngx_hunk_t       *hunk;
-    ngx_table_elt_t  *param;
-    ngx_str_t         command;
-    ngx_array_t       params;
-    int               state;
-    int               looked;
-    char             *pos;
-    ngx_chain_t      *incoming;
-    int               new_hunk;
-    u_int             value_len;
+    int               enable;
+} ngx_http_ssi_conf_t;
+
+
+typedef struct {
+    ngx_hunk_t        *buf;
+
+    char              *start;
+    char              *last;
+    char              *pos;
+
+    ngx_table_elt_t   *param;
+    ngx_str_t          command;
+    ngx_array_t        params;
+    int                state;
+
+    ngx_chain_t       *in;
+    ngx_chain_t       *current;
+    ngx_chain_t       *out;
+    ngx_chain_t      **last_out;
+    ngx_chain_t       *busy;
+
+    size_t             prev;
+
+    u_int              value_len;
 } ngx_http_ssi_ctx_t;
 
 
+static ngx_int_t ngx_http_ssi_parse(ngx_http_request_t *r,
+                                    ngx_http_ssi_ctx_t *ctx);
+static void *ngx_http_ssi_create_conf(ngx_conf_t *cf);
+static char *ngx_http_ssi_merge_conf(ngx_conf_t *cf,
+                                     void *parent, void *child);
 static int ngx_http_ssi_filter_init(ngx_cycle_t *cycle);
 
+
+static ngx_command_t  ngx_http_ssi_filter_commands[] = {
+
+    { ngx_string("ssi"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
+      ngx_conf_set_flag_slot,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      offsetof(ngx_http_ssi_conf_t, enable),
+      NULL },
+
+     ngx_null_command
+};
+
+
     
 static ngx_http_module_t  ngx_http_ssi_filter_module_ctx = {
+    NULL,                                  /* pre conf */
+
     NULL,                                  /* create main configuration */
     NULL,                                  /* init main configuration */
 
     NULL,                                  /* create server configuration */
     NULL,                                  /* merge server configuration */
 
-    NULL,                                  /* create location configuration */
-    NULL,                                  /* merge location configuration */
+    ngx_http_ssi_create_conf,              /* create location configuration */
+    ngx_http_ssi_merge_conf                /* merge location configuration */
 };  
 
 
 ngx_module_t  ngx_http_ssi_filter_module = {
     NGX_MODULE,
     &ngx_http_ssi_filter_module_ctx,       /* module context */
-    NULL,                                  /* module directives */
+    ngx_http_ssi_filter_commands,          /* module directives */
     NGX_HTTP_MODULE,                       /* module type */
     ngx_http_ssi_filter_init,              /* init module */
     NULL                                   /* init child */
 };
 
 
-static int (*next_header_filter) (ngx_http_request_t *r);
-static int (*next_body_filter) (ngx_http_request_t *r, ngx_chain_t *ch);
+static int (*ngx_http_next_header_filter) (ngx_http_request_t *r);
+static int (*ngx_http_next_body_filter) (ngx_http_request_t *r, ngx_chain_t *in);
 
 
 
 static char comment_string[] = "<!--";
+static char error_string[] = "[an error occurred while processing "
+                             "the directive]";
 
 
 static int ngx_http_ssi_header_filter(ngx_http_request_t *r)
 {
-    ngx_http_ssi_ctx_t  *ctx;
+    ngx_http_ssi_ctx_t   *ctx;
+    ngx_http_ssi_conf_t  *conf;
 
-    /* if () */ {
-        ngx_http_create_ctx(r, ctx, ngx_http_ssi_filter_module,
-                            sizeof(ngx_http_ssi_ctx_t), NGX_ERROR);
+    conf = ngx_http_get_module_loc_conf(r, ngx_http_ssi_filter_module);
+
+    if (!conf->enable) {
+        return ngx_http_next_header_filter(r);
     }
 
-    return NGX_OK;
+    ngx_http_create_ctx(r, ctx, ngx_http_ssi_filter_module,
+                        sizeof(ngx_http_ssi_ctx_t), NGX_ERROR);
+
+    ctx->last_out = &ctx->out;
+    /* STUB: conf */ ctx->value_len = 200;
+
+    r->headers_out.content_length_n = -1;
+    if (r->headers_out.content_length) {
+        r->headers_out.content_length->key.len = 0;
+        r->headers_out.content_length = NULL;
+    }
+
+    r->headers_out.last_modified_time = -1;
+    if (r->headers_out.last_modified) {
+        r->headers_out.last_modified->key.len = 0;
+        r->headers_out.last_modified = NULL;
+    }
+
+    r->filter |= NGX_HTTP_FILTER_NEED_IN_MEMORY;
+
+    return ngx_http_next_header_filter(r);
 }
 
 
 static int ngx_http_ssi_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
 {
-    int                  rc;
-    ngx_chain_t          chain;
+    ngx_int_t            rc;
+    ngx_hunk_t          *hunk;
+    ngx_chain_t         *cl, *tl;
     ngx_http_ssi_ctx_t  *ctx;
 
     ctx = ngx_http_get_module_ctx(r, ngx_http_ssi_filter_module);
 
-    if ((ctx == NULL) || (in == NULL && ctx->incoming == NULL)) {
-        return next_body_filter(r, NULL);
+    if (ctx == NULL || (in == NULL && ctx->in == NULL)) {
+        return ngx_http_next_body_filter(r, NULL);
     }
 
-    if (ctx->hunk &&
-        (((ctx->hunk->type & NGX_HUNK_FILE)
-           && (ctx->hunk->file_pos < ctx->hunk->file_last))
-        || ((ctx->hunk->type & NGX_HUNK_IN_MEMORY)
-             && (ctx->hunk->pos < ctx->hunk->last))))
-    {
-        rc = next_body_filter(r, NULL);
+    /* add the incoming hunk to the chain ctx->in */
 
-        if (rc == NGX_ERROR) {
+    if (in) {
+        if (ngx_chain_add_copy(r->pool, &ctx->in, in) == NGX_ERROR) {
             return NGX_ERROR;
         }
 
-        if (ctx->hunk->shadow) {
-            if (ctx->hunk->type & NGX_HUNK_FILE) {
-                ctx->hunk->shadow->file_pos = ctx->hunk->file_pos;
-            }
+        if (ctx->current == NULL) {
+            ctx->current = ctx->in;
+        }
+    }
 
-            if (ctx->hunk->type & NGX_HUNK_IN_MEMORY) {
-                ctx->hunk->shadow->pos = ctx->hunk->pos;
-            }
-        }
+    while (ctx->current) {
+        if (ctx->buf == NULL) {
+            ctx->buf = ctx->current->hunk;
+            ctx->current = ctx->current->next;
 
-        if (rc == NGX_AGAIN) {
-            return NGX_AGAIN;
+            ctx->start = ctx->buf->pos;
+            ctx->pos = ctx->buf->pos;
+            ctx->last = ctx->buf->pos;
         }
 
+        while (ctx->pos < ctx->buf->last) {
+            rc = ngx_http_ssi_parse(r, ctx);
 
-    }
+            if (rc == NGX_ERROR) {
+                return rc;
+
+            } else if (rc == NGX_HTTP_SSI_COPY) {
+                if (ctx->prev) {
+
+                    if (!(hunk = ngx_calloc_hunk(r->pool))) {
+                        return NGX_ERROR;
+                    }
+
+                    hunk->type = NGX_HUNK_IN_MEMORY|NGX_HUNK_TEMP;
+                    hunk->pos = comment_string;
+                    hunk->last = comment_string + ctx->prev;
+
+                    ngx_alloc_link_and_set_hunk(cl, hunk, r->pool, NGX_ERROR);
+
+                    *ctx->last_out = cl;
+                    ctx->last_out = &cl->next;
+
+                    ctx->prev = 0;
+                }
+
+                if (ctx->pos == ctx->buf->last) {
+                    ctx->prev = ctx->buf->last - ctx->last;
+                }
+
+                if (!(hunk = ngx_calloc_hunk(r->pool))) {
+                    return NGX_ERROR;
+                }
+
+                hunk->type = NGX_HUNK_IN_MEMORY|NGX_HUNK_TEMP|NGX_HUNK_RECYCLED;
+                hunk->pos = ctx->start;
+                hunk->last = ctx->last;
+                hunk->shadow = ctx->buf;
+
+                ngx_alloc_link_and_set_hunk(cl, hunk, r->pool, NGX_ERROR);
+
+                *ctx->last_out = cl;
+                ctx->last_out = &cl->next;
+
+                continue;
 
 #if 0
+            } else if (rc == NGX_HTTP_SSI_INVALID_COMMAND) {
+            } else if (rc == NGX_HTTP_SSI_INVALID_PARAM) {
+            } else if (rc == NGX_HTTP_SSI_INVALID_VALUE) {
+            } else if (rc == NGX_HTTP_SSI_LONG_VALUE) {
+#endif
 
-    add in to ctx->incoming chain
+            } else {
+                if (!(hunk = ngx_calloc_hunk(r->pool))) {
+                    return NGX_ERROR;
+                }
 
-    while (ctx->incoming) {
-        rc == ngx_http_ssi_exec(r, ctx);
+                hunk->type = NGX_HUNK_IN_MEMORY|NGX_HUNK_TEMP;
+                hunk->pos = error_string;
+                hunk->last = error_string + sizeof(error_string) - 1;
+
+                ngx_alloc_link_and_set_hunk(cl, hunk, r->pool, NGX_ERROR);
 
-        if (rc != NGX_ERROR) {
-            return rc;
+                *ctx->last_out = cl;
+                ctx->last_out = &cl->next;
+            }
+        }
+    }
+
+    if (ctx->out) {
+        if (ngx_http_next_body_filter(r, ctx->out) == NGX_ERROR) {
+            return NGX_ERROR;
         }
 
-        ctx->incoming = ctx->incoming->next;
+        if (ctx->busy == NULL) {
+            ctx->busy = ctx->out;
+
+        } else {
+            for (tl = ctx->busy; /* void */ ; tl = tl->next) {
+                if (tl->next == NULL) { 
+                    tl->next = ctx->out;
+                    break;
+                }
+            }
+        }
+    
+        ctx->out = NULL;
+
+        while (ctx->busy) {
+            if (ngx_hunk_size(ctx->busy->hunk) != 0) {
+                break;
+            }
+
+            if (ctx->busy->hunk->shadow) {
+                ctx->busy->hunk->shadow->pos = ctx->busy->hunk->pos;
+            }
+
+            ctx->busy = ctx->busy->next;
+        }
     }
 
-#endif
-
     return NGX_OK;
 }
 
 
 #if 0
 
-
-    while (ctx->incoming) {
-        rc = ngx_http_ssi_parse(r, ctx, ctx->incoming->hunk);
-
-        if (rc == NGX_ERROR) {
-            return rc;
-        }
-
-        if (rc == NGX_OK) {
-            ngx_test_null(temp, ngx_calloc_hunk(r->pool), NGX_ERROR);
-            temp->type = NGX_HUNK_IN_MEMORY|NGX_HUNK_TEMP;
-            temp->pos = comment_string;
-            temp->last = comment_string + looked;
-        }
-
-        if (rc == NGX_HTTP_SSI_DONE) {
-
-
-            - looked
-
-            chain.hunk = ctx->incoming->hunk;
-            chain.next = NULL;
-
-            rc = next_body_filter(r, &chain);
-
-            if (rc != NGX_OK) {
-                ctx->incoming = ctx->incoming->next;
-                return rc;
-            }
-
-        } else if (rc == NGX_HTTP_SSI_INVALID_COMMAND) {
-        } else if (rc == NGX_HTTP_SSI_INVALID_PARAM) {
-        } else if (rc == NGX_HTTP_SSI_INVALID_VALUE) {
-        } else if (rc == NGX_HTTP_SSI_LONG_VALUE) {
-        }
-
-        ctx->incoming = ctx->incoming->next;
-    }
-
-#endif
-
-
-
-
-
-#if 0
-
 static int ngx_http_ssi_copy_opcode(ngx_http_request_t *r,
                                     ngx_http_ssi_ctx_t *ctx, void *data)
 {
@@ -245,14 +337,10 @@ static int ngx_http_ssi_copy_opcode(ngx_
 #endif
 
 
-
-static int ngx_http_ssi_parse(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx,
-                              ngx_hunk_t *h)
+static ngx_int_t ngx_http_ssi_parse(ngx_http_request_t *r,
+                                    ngx_http_ssi_ctx_t *ctx)
 {
-    int           looked;
-    char         *p, ch;
-    ngx_hunk_t   *temp;
-    ngx_chain_t   chain;
+    char  *p, *last, *end, ch;
 
     enum {
         ssi_start_state = 0,
@@ -275,50 +363,35 @@ static int ngx_http_ssi_parse(ngx_http_r
     } state;
 
 
-    looked = ctx->looked;
     state = ctx->state;
+    last = ctx->last;
     p = ctx->pos;
+    end = ctx->buf->last;
 
-    while (p < h->last) {
+    while (p < end) {
         ch = *p++;
 
         switch (state) {
 
         case ssi_start_state:
 
-            if (ctx->new_hunk) {
-
-                if (looked) {
-                    ngx_test_null(temp, ngx_calloc_hunk(r->pool), NGX_ERROR);
-                    temp->type = NGX_HUNK_IN_MEMORY|NGX_HUNK_TEMP;
-                    temp->pos = comment_string;
-                    temp->last = comment_string + looked;
+            last = NULL;
 
-                    chain.hunk = temp;
-                    chain.next = NULL;
-
-                    if (next_body_filter(r, &chain) == NGX_ERROR) {
-                        return NGX_ERROR;
-                    }
-                }
-
-                ctx->new_hunk = 0;
-            }
-
-            /* tight loop */
+            /* a tight loop */
             for ( ;; ) {
 
                 if (ch == '<') {
                     state = ssi_tag_state;
-                    looked = 1;
+                    last = p - 1;
                     break;
                 }
 
-                if (p < h->last) {
+                if (p == end) {
                     ctx->state = ssi_start_state;
-                    ctx->looked = 0;
+                    ctx->last = p;
                     ctx->pos = p;
-                    return NGX_HTTP_SSI_DONE;
+
+                    return NGX_HTTP_SSI_COPY;
                 }
 
                 ch = *p++;
@@ -330,15 +403,14 @@ static int ngx_http_ssi_parse(ngx_http_r
             switch (ch) {
             case '!':
                 state = ssi_comment0_state;
-                looked = 2;
                 break;
 
             case '<':
+                last = p - 1;
                 break;
 
             default:
                 state = ssi_start_state;
-                looked = 0;
                 break;
             }
 
@@ -348,17 +420,15 @@ static int ngx_http_ssi_parse(ngx_http_r
             switch (ch) {
             case '-':
                 state = ssi_comment1_state;
-                looked = 3;
                 break;
 
             case '<':
+                last = p - 1;
                 state = ssi_tag_state;
-                looked = 1;
                 break;
 
             default:
                 state = ssi_start_state;
-                looked = 0;
                 break;
             }
 
@@ -368,17 +438,15 @@ static int ngx_http_ssi_parse(ngx_http_r
             switch (ch) {
             case '-':
                 state = ssi_sharp_state;
-                looked = 4;
                 break;
 
             case '<':
+                last = p - 1;
                 state = ssi_tag_state;
-                looked = 1;
                 break;
 
             default:
                 state = ssi_start_state;
-                looked = 0;
                 break;
             }
 
@@ -387,18 +455,19 @@ static int ngx_http_ssi_parse(ngx_http_r
         case ssi_sharp_state:
             switch (ch) {
             case '#':
-                state = ssi_precommand_state;
-                looked = 0;
-                break;
+                ctx->state = ssi_precommand_state;
+                ctx->last = last;
+                ctx->pos = p;
+
+                return NGX_HTTP_SSI_COPY;
 
             case '<':
+                last = p - 1;
                 state = ssi_tag_state;
-                looked = 1;
                 break;
 
             default:
                 state = ssi_start_state;
-                looked = 0;
                 break;
             }
 
@@ -413,9 +482,12 @@ static int ngx_http_ssi_parse(ngx_http_r
                 break;
 
             default:
-                ngx_test_null(ctx->command.data,
-                              ngx_palloc(r->pool, NGX_HTTP_SSI_COMMAND_LEN + 1),
-                              NGX_ERROR);
+                ctx->command.data = 
+                             ngx_palloc(r->pool, NGX_HTTP_SSI_COMMAND_LEN + 1);
+                if (ctx->command.data == NULL) {
+                    return NGX_ERROR;
+                }
+
                 ctx->command.data[0] = ch;
                 ctx->command.len = 1;
                 state = ssi_command_state;
@@ -462,18 +534,23 @@ static int ngx_http_ssi_parse(ngx_http_r
                 break;
 
             default:
-                ngx_test_null(ctx->param, ngx_push_array(&ctx->params),
-                              NGX_ERROR);
+                if (!(ctx->param = ngx_push_array(&ctx->params))) {
+                    return NGX_ERROR;
+                }
 
-                ngx_test_null(ctx->param->key.data,
-                              ngx_palloc(r->pool, NGX_HTTP_SSI_PARAM_LEN + 1),
-                              NGX_ERROR);
+                ctx->param->key.data =
+                               ngx_palloc(r->pool, NGX_HTTP_SSI_PARAM_LEN + 1);
+                if (ctx->param->key.data == NULL) {
+                    return NGX_ERROR;
+                }
                 ctx->param->key.data[0] = ch;
                 ctx->param->key.len = 1;
 
-                ngx_test_null(ctx->param->value.data,
-                              ngx_palloc(r->pool, ctx->value_len + 1),
-                              NGX_ERROR);
+                ctx->param->value.data =
+                                       ngx_palloc(r->pool, ctx->value_len + 1);
+                if (ctx->param->value.data == NULL) {
+                    return NGX_ERROR;
+                }
                 ctx->param->value.len = 0;
 
                 state = ssi_param_state;
@@ -623,6 +700,7 @@ static int ngx_http_ssi_parse(ngx_http_r
             switch (ch) {
             case '>':
                 ctx->state = ssi_start_state;
+                ctx->start = p;
                 ctx->pos = p;
                 return NGX_OK;
 
@@ -635,19 +713,45 @@ static int ngx_http_ssi_parse(ngx_http_r
     }
 
     ctx->state = state;
-    ctx->looked = looked;
+    ctx->last = last;
     ctx->pos = p;
 
-    return NGX_HTTP_SSI_DONE;
+    return NGX_HTTP_SSI_COPY;
+}
+
+
+static void *ngx_http_ssi_create_conf(ngx_conf_t *cf)
+{
+    ngx_http_ssi_conf_t  *conf;
+
+    if (!(conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_ssi_conf_t)))) {
+        return NGX_CONF_ERROR;
+    }
+
+    conf->enable = NGX_CONF_UNSET;
+
+    return conf;
+}
+
+
+static char *ngx_http_ssi_merge_conf(ngx_conf_t *cf,
+                                     void *parent, void *child)
+{
+    ngx_http_ssi_conf_t *prev = parent;
+    ngx_http_ssi_conf_t *conf = child;
+
+    ngx_conf_merge_value(conf->enable, prev->enable, 0);
+
+    return NGX_CONF_OK;
 }
 
 
 static int ngx_http_ssi_filter_init(ngx_cycle_t *cycle)
 {
-    next_header_filter = ngx_http_top_header_filter;
+    ngx_http_next_header_filter = ngx_http_top_header_filter;
     ngx_http_top_header_filter = ngx_http_ssi_header_filter;
 
-    next_body_filter = ngx_http_top_body_filter;
+    ngx_http_next_body_filter = ngx_http_top_body_filter;
     ngx_http_top_body_filter = ngx_http_ssi_body_filter;
 
     return NGX_OK;