r7072: moved the esp hooks calls to the ejs level, so we can call them from
[jra/samba/.git] / source / web_server / http.c
index 6687ab7d16af2461aa238e1c8f5015567c942157..4a82477160add635a33c2a9eea2057772e551dad 100644 (file)
 
 #define SWAT_SESSION_KEY "_swat_session_"
 
-/*
-  context for long term storage in the web server, to support session[]
-  and application[] data. Stored in task->private.
-*/
-struct esp_data {
-       struct session_data {
-               struct session_data *next, *prev;
-               struct esp_data *edata;
-               const char *id;
-               struct MprVar *data;
-               struct timed_event *te;
-               int lifetime;
-       } *sessions;
-       struct MprVar *application_data;
-};
-
 /* state of the esp subsystem for a specific request */
 struct esp_state {
        struct websrv_context *web;
@@ -76,6 +60,7 @@ static void http_output_headers(struct websrv_context *web)
        int i;
        char *s;
        DATA_BLOB b;
+       uint32_t content_length = 0;
        const char *response_string = "Unknown Code";
        const struct {
                unsigned code;
@@ -106,7 +91,15 @@ static void http_output_headers(struct websrv_context *web)
        for (i=0;web->output.headers[i];i++) {
                s = talloc_asprintf_append(s, "%s\r\n", web->output.headers[i]);
        }
-       s = talloc_asprintf_append(s, "\r\n");
+
+       /* work out the content length */
+       content_length = web->output.content.length;
+       if (web->output.fd != -1) {
+               struct stat st;
+               fstat(web->output.fd, &st);
+               content_length += st.st_size;
+       }
+       s = talloc_asprintf_append(s, "Content-Length: %u\r\n\r\n", content_length);
        if (s == NULL) return;
 
        b = web->output.content;
@@ -250,10 +243,13 @@ static void http_redirect(EspHandle handle, int code, char *url)
                if (url[0] != '/') {
                        char *p = strrchr(web->input.url, '/');
                        if (p == web->input.url) {
-                               url = talloc_asprintf(web, "http://%s/%s", host, url);
+                               url = talloc_asprintf(web, "http%s://%s/%s", 
+                                                     web->tls_session?"s":"",
+                                                     host, url);
                        } else {
                                int dirlen = p - web->input.url;
-                               url = talloc_asprintf(web, "http://%s%*.*s/%s",
+                               url = talloc_asprintf(web, "http%s://%s%*.*s/%s",
+                                                     web->tls_session?"s":"",
                                                      host, 
                                                      dirlen, dirlen, web->input.url,
                                                      url);
@@ -351,6 +347,7 @@ void http_error(struct websrv_context *web, int code, const char *info)
        http_output_headers(web);
        EVENT_FD_NOT_READABLE(web->conn->event.fde);
        EVENT_FD_WRITEABLE(web->conn->event.fde);
+       web->output.output_pending = True;
 }
 
 /*
@@ -399,6 +396,7 @@ static void http_simple_request(struct websrv_context *web)
 
        http_output_headers(web);
        EVENT_FD_WRITEABLE(web->conn->event.fde);
+       web->output.output_pending = True;
        return;
 
 invalid:
@@ -411,6 +409,7 @@ invalid:
 static void http_setup_arrays(struct esp_state *esp)
 {
        struct websrv_context *web = esp->web;
+       struct esp_data *edata = talloc_get_type(web->task->private, struct esp_data);
        struct EspRequest *req = esp->req;
        char *p;
 
@@ -426,6 +425,7 @@ static void http_setup_arrays(struct esp_state *esp)
        SETVAR(ESP_REQUEST_OBJ, "REQUEST_URI", web->input.url);
        p = strrchr(web->input.url, '/');
        SETVAR(ESP_REQUEST_OBJ, "SCRIPT_NAME", p+1);
+       SETVAR(ESP_REQUEST_OBJ, "SCRIPT_FILENAME", web->input.url);
        p = socket_get_peer_name(web->conn->socket, esp);
        SETVAR(ESP_REQUEST_OBJ, "REMOTE_HOST", p);
        SETVAR(ESP_REQUEST_OBJ, "REMOTE_ADDR", p);
@@ -449,10 +449,10 @@ static void http_setup_arrays(struct esp_state *esp)
        SETVAR(ESP_SERVER_OBJ, "DOCUMENT_ROOT", lp_swat_directory());
        SETVAR(ESP_SERVER_OBJ, "SERVER_PORT", 
               talloc_asprintf(esp, "%u", socket_get_my_port(web->conn->socket)));
-       SETVAR(ESP_SERVER_OBJ, "SERVER_PROTOCOL", "http");
+       SETVAR(ESP_SERVER_OBJ, "SERVER_PROTOCOL", web->tls_session?"https":"http");
        SETVAR(ESP_SERVER_OBJ, "SERVER_SOFTWARE", "SWAT");
        SETVAR(ESP_SERVER_OBJ, "GATEWAY_INTERFACE", "CGI/1.1");
-       SETVAR(ESP_REQUEST_OBJ, "SCRIPT_FILENAME", web->input.url);
+       SETVAR(ESP_SERVER_OBJ, "TLS_SUPPORT", edata->tls_data?"True":"False");
 }
 
 #if HAVE_SETJMP_H
@@ -461,17 +461,17 @@ static void http_setup_arrays(struct esp_state *esp)
    report a internal server error via http
 */
 #include <setjmp.h>
-static jmp_buf http_exception_buf;
+static jmp_buf ejs_exception_buf;
 static const char *exception_reason;
 
-void http_exception(const char *reason)
+void ejs_exception(const char *reason)
 {
        exception_reason = reason;
        DEBUG(0,("%s", reason));
-       longjmp(http_exception_buf, -1);
+       longjmp(ejs_exception_buf, -1);
 }
 #else
-void http_exception(const char *reason)
+void ejs_exception(const char *reason)
 {
        DEBUG(0,("%s", reason));
        smb_panic(reason);
@@ -497,7 +497,7 @@ static void esp_request(struct esp_state *esp)
        }
 
 #if HAVE_SETJMP_H
-       if (setjmp(http_exception_buf) != 0) {
+       if (setjmp(ejs_exception_buf) != 0) {
                http_error(web, 500, exception_reason);
                return;
        }
@@ -509,6 +509,7 @@ static void esp_request(struct esp_state *esp)
        talloc_free(buf);
        http_output_headers(web);
        EVENT_FD_WRITEABLE(web->conn->event.fde);
+       web->output.output_pending = True;
 }
 
 
@@ -663,7 +664,7 @@ static void http_setup_session(struct esp_state *esp)
                s->data = NULL;
                s->te = NULL;
                s->edata = edata;
-               s->lifetime = lp_parm_int(-1, "http", "sessiontimeout", 300);
+               s->lifetime = lp_parm_int(-1, "web", "sessiontimeout", 300);
                DLIST_ADD(edata->sessions, s);
                talloc_set_destructor(s, session_destructor);
        }
@@ -748,7 +749,7 @@ void http_process_input(struct websrv_context *web)
 
        talloc_set_destructor(esp, esp_destructor);
 
-       http_setup_ejs_functions();
+       smb_setup_ejs_functions();
 
        esp->req = espCreateRequest(web, web->input.url, esp->variables);
        if (esp->req == NULL) goto internal_error;
@@ -775,6 +776,9 @@ void http_process_input(struct websrv_context *web)
 
        /* work out the mime type */
        p = strrchr(web->input.url, '.');
+       if (p == NULL) {
+               esp_enable = True;
+       }
        for (i=0;p && i<ARRAY_SIZE(mime_types);i++) {
                if (strcmp(mime_types[i].extension, p+1) == 0) {
                        file_type = mime_types[i].mime_type;
@@ -880,12 +884,10 @@ NTSTATUS http_setup_esp(struct task_server *task)
 {
        struct esp_data *edata;
 
-       edata = talloc(task, struct esp_data);
+       edata = talloc_zero(task, struct esp_data);
        NT_STATUS_HAVE_NO_MEMORY(edata);
 
        task->private = edata;
-       edata->sessions = NULL;
-       edata->application_data = NULL;
 
        return NT_STATUS_OK;
 }