From: Andy Green Date: Wed, 13 Apr 2016 03:49:07 +0000 (+0800) Subject: lwsws cgi integration X-Git-Tag: upstream/2.0.3~125 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=a5e73a1a4bd61bd5c513573ff0f2da7d903d4a92;p=platform%2Fupstream%2Flibwebsockets.git lwsws cgi integration Signed-off-by: Andy Green --- diff --git a/README.lwsws.md b/README.lwsws.md index 4692a77..a49ee01 100644 --- a/README.lwsws.md +++ b/README.lwsws.md @@ -140,8 +140,56 @@ Mounts Where mounts are given in the vhost definition, then directory contents may be auto-served if it matches the mountpoint. -Currently only file:// mount protocol and a fixed set of mimetypes are -supported. +Mount protocols are used to control what kind of translation happens + + - file:// serve the uri using the remainder of the url past the mountpoint based on the origin directory. + + Eg, with this mountpoint + +``` + { + "mountpoint": "/", + "origin": "file:///var/www/mysite.com", + "default": "/" + } +``` + + The uri /file.jpg would serve /var/www/mysite.com/file.jpg, since / matched. + + - ^http:// or ^https:// these cause any url matching the mountpoint to issue a redirect to the origin url + + - cgi:// this causes any matching url to be given to the named cgi, eg + +``` + { + "mountpoint": "/git", + "origin": "cgi:///var/www/cgi-bin/cgit", + "default": "/" + }, { + "mountpoint": "/cgit-data", + "origin": "file:///usr/share/cgit", + "default": "/" + }, +``` + + would cause the url /git/myrepo to pass "myrepo" to the cgi /var/www/cgi-bin/cgit and send the results to the client. + + When using a cgi:// protcol origin at a mountpoint, you may also give cgi environment variables specific to the mountpoint like this + +``` + { + "mountpoint": "/git", + "origin": "cgi:///var/www/cgi-bin/cgit", + "default": "/", + "cgi-env": [{ + "CGIT_CONFIG": "/etc/cgitrc/libwebsockets.org" + }] + } +``` + + This allows you to customize one cgi depending on the mountpoint (and / or vhost). + +Currently only a fixed set of mimetypes are supported. Plugins diff --git a/lib/context.c b/lib/context.c index fb9aabf..d8a04a8 100644 --- a/lib/context.c +++ b/lib/context.c @@ -52,7 +52,7 @@ static const char * const mount_protocols[] = { LWS_VISIBLE LWS_EXTERN int lws_write_http_mount(struct lws_http_mount *next, struct lws_http_mount **res, void *store, const char *mountpoint, const char *origin, - const char *def) + const char *def, struct lws_protocol_vhost_options *cgienv) { struct lws_http_mount *m; void *orig = store; @@ -70,6 +70,7 @@ lws_write_http_mount(struct lws_http_mount *next, struct lws_http_mount **res, m->mountpoint = mountpoint; m->mountpoint_len = (unsigned char)strlen(mountpoint); m->mount_next = NULL; + m->cgienv = cgienv; if (next) next->mount_next = m; diff --git a/lib/libuv.c b/lib/libuv.c index 89ee690..6013e09 100644 --- a/lib/libuv.c +++ b/lib/libuv.c @@ -51,11 +51,14 @@ lws_uv_idle(uv_idle_t *handle /* still somebody left who wants forced service? */ if (!lws_service_adjust_timeout(pt->context, 1, pt->tid)) /* yes... come back again later */ + lwsl_debug("%s: done again\n", __func__); return; } /* there is nobody who needs service forcing, shut down idle */ uv_idle_stop(handle); + + lwsl_debug("%s: done stop\n", __func__); } static void @@ -272,7 +275,7 @@ lws_libuv_io(struct lws *wsi, int flags) if (!LWS_LIBUV_ENABLED(context)) return; - lwsl_debug("%s: wsi: %p, flags:%d\n", __func__, wsi, flags); + lwsl_debug("%s: wsi: %p, flags:0x%x\n", __func__, wsi, flags); if (!pt->io_loop_uv) { lwsl_info("%s: no io loop yet\n", __func__); diff --git a/lib/libwebsockets.c b/lib/libwebsockets.c index c537c1b..b85e6e9 100644 --- a/lib/libwebsockets.c +++ b/lib/libwebsockets.c @@ -176,10 +176,11 @@ lws_close_free_wsi(struct lws *wsi, enum lws_close_status reason) if (wsi->mode == LWSCM_CGI) { /* we are not a network connection, but a handler for CGI io */ if (wsi->parent && wsi->parent->cgi) - /* end the binding between us and master */ - wsi->parent->cgi->stdwsi[(int)wsi->cgi_channel] = NULL; + /* end the binding between us and master */ + wsi->parent->cgi->stdwsi[(int)wsi->cgi_channel] = NULL; wsi->socket_is_permanently_unusable = 1; + lwsl_debug("------ %s: detected cgi fdhandler wsi %p\n", __func__, wsi); goto just_kill_connection; } @@ -496,6 +497,7 @@ just_kill_connection: #ifdef LWS_USE_LIBUV if (LWS_LIBUV_ENABLED(context)) { + lwsl_debug("%s: lws_libuv_closehandle: wsi %p\n", __func__, wsi); /* libuv has to do his own close handle processing asynchronously */ lws_libuv_closehandle(wsi); @@ -1534,7 +1536,7 @@ lws_urlencode(const char *in, int inlen, char *out, int outlen) const char *hex = "0123456789ABCDEF"; char *start = out, *end = out + outlen; - while (inlen-- && out > end - 4) { + while (inlen-- && out < end - 4) { if ((*in >= 'A' && *in <= 'Z') || (*in >= 'a' && *in <= 'z') || (*in >= '0' && *in <= '9') || @@ -1635,12 +1637,12 @@ lws_create_basic_wsi(struct lws_context *context, int tsi) */ LWS_VISIBLE LWS_EXTERN int -lws_cgi(struct lws *wsi, char * const *exec_array, int script_uri_path_len, - int timeout_secs) +lws_cgi(struct lws *wsi, const char * const *exec_array, int script_uri_path_len, + int timeout_secs, struct lws_protocol_vhost_options *mp_cgienv) { struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi]; char *env_array[30], cgi_path[400], e[1024], *p = e, - *end = p + sizeof(e) - 1, tok[256]; + *end = p + sizeof(e) - 1, tok[256], *t; struct lws_cgi *cgi; int n, m, i; @@ -1670,12 +1672,15 @@ lws_cgi(struct lws *wsi, char * const *exec_array, int script_uri_path_len, if (!cgi->stdwsi[n]) goto bail2; cgi->stdwsi[n]->cgi_channel = n; + cgi->stdwsi[n]->vhost = wsi->vhost; + /* read side is 0, stdin we want the write side, others read */ cgi->stdwsi[n]->sock = cgi->pipe_fds[n][!!(n == 0)]; fcntl(cgi->pipe_fds[n][!!(n == 0)], F_SETFL, O_NONBLOCK); } for (n = 0; n < 3; n++) { + lws_libuv_accept(cgi->stdwsi[n], cgi->stdwsi[n]->sock); if (insert_wsi_socket_into_fds(wsi->context, cgi->stdwsi[n])) goto bail3; cgi->stdwsi[n]->parent = wsi; @@ -1725,9 +1730,16 @@ lws_cgi(struct lws *wsi, char * const *exec_array, int script_uri_path_len, WSI_TOKEN_HTTP_URI_ARGS, m); if (i < 0) break; - i = lws_urlencode(tok, i, p, end - p); - p += i; - *p++ = '&'; + t = tok; + while (*t && *t != '=' && p < end - 4) + *p++ = *t++; + if (*t == '=') + *p++ = *t++; + i = lws_urlencode(t, i- (t - tok), p, end - p); + if (i > 0) { + p += i; + *p++ = '&'; + } m++; } if (m) @@ -1759,13 +1771,23 @@ lws_cgi(struct lws *wsi, char * const *exec_array, int script_uri_path_len, p++; } env_array[n++] = p; - p += snprintf(p, end - p, "SCRIPT_PATH=%s", exec_array[2]) + 1; + p += snprintf(p, end - p, "SCRIPT_PATH=%s", exec_array[0]) + 1; + + while (mp_cgienv) { + env_array[n++] = p; + p += snprintf(p, end - p, "%s=%s", mp_cgienv->name, + mp_cgienv->value); + lwsl_notice(" Applying mount-specific cgi env '%s'\n", + env_array[n - 1]); + p++; + mp_cgienv = mp_cgienv->next; + } env_array[n++] = "SERVER_SOFTWARE=libwebsockets"; env_array[n++] = "PATH=/bin:/usr/bin:/usr/local/bin:/var/www/cgi-bin"; env_array[n] = NULL; -#if 0 +#if 1 for (m = 0; m < n; m++) lwsl_err(" %s\n", env_array[m]); #endif @@ -1785,6 +1807,10 @@ lws_cgi(struct lws *wsi, char * const *exec_array, int script_uri_path_len, /* we are the parent process */ return 0; + /* somewhere we can at least read things and enter it */ + if (chdir("/")) + lwsl_notice("%s: Failed to chdir\n", __func__); + /* We are the forked process, redirect and kill inherited things. * * Because of vfork(), we cannot do anything that changes pages in @@ -1806,9 +1832,9 @@ lws_cgi(struct lws *wsi, char * const *exec_array, int script_uri_path_len, *p++ = '\0'; setenv(env_array[m], p, 1); } - execvp(exec_array[0], &exec_array[0]); + execvp(exec_array[0], (char * const *)&exec_array[0]); #else - execvpe(exec_array[0], &exec_array[0], &env_array[0]); + execvpe(exec_array[0], (char * const *)&exec_array[0], &env_array[0]); #endif exit(1); @@ -1948,6 +1974,8 @@ lws_cgi_kill(struct lws *wsi) struct lws_cgi_args args; int n, status, do_close = 0; + lwsl_debug("!!!!! %s: %p\n", __func__, wsi); + if (!wsi->cgi) return 0; @@ -1986,17 +2014,20 @@ lws_cgi_kill(struct lws *wsi) pcgi = &(*pcgi)->cgi_list; } - for (n = 0 ; n < 3; n++) { - if (wsi->cgi->pipe_fds[n][!!(n == 0)] >= 0) { - close(wsi->cgi->pipe_fds[n][!!(n == 0)]); - wsi->cgi->pipe_fds[n][!!(n == 0)] = -1; + if (!do_close) + for (n = 0 ; n < 3; n++) { + if (wsi->cgi->pipe_fds[n][!!(n == 0)] >= 0) { + close(wsi->cgi->pipe_fds[n][!!(n == 0)]); + wsi->cgi->pipe_fds[n][!!(n == 0)] = -1; + } } - } lws_free_set_NULL(wsi->cgi); - if (do_close) + if (do_close) { + lwsl_debug("!!!!! %s: do_close\n", __func__); lws_close_free_wsi(wsi, 0); + } return 0; } diff --git a/lib/libwebsockets.h b/lib/libwebsockets.h index 13d8bcc..9996cf2 100644 --- a/lib/libwebsockets.h +++ b/lib/libwebsockets.h @@ -1538,10 +1538,20 @@ struct lws_client_connect_info { struct lws_http_mount; +enum { + LWSMPRO_HTTP, + LWSMPRO_HTTPS, + LWSMPRO_FILE, + LWSMPRO_CGI, + LWSMPRO_REDIR_HTTP, + LWSMPRO_REDIR_HTTPS, +}; + LWS_VISIBLE LWS_EXTERN int lws_write_http_mount(struct lws_http_mount *next, struct lws_http_mount **res, void *store, const char *mountpoint, const char *origin, - const char *def); + const char *def, + struct lws_protocol_vhost_options *cgienv); LWS_VISIBLE LWS_EXTERN void lws_set_log_level(int level, @@ -2012,8 +2022,9 @@ struct lws_cgi_args { }; LWS_VISIBLE LWS_EXTERN int -lws_cgi(struct lws *wsi, char * const *exec_array, int script_uri_path_len, - int timeout_secs); +lws_cgi(struct lws *wsi, const char * const *exec_array, + int script_uri_path_len, int timeout_secs, + struct lws_protocol_vhost_options *mp_cgienv); LWS_VISIBLE LWS_EXTERN int lws_cgi_write_split_stdout_headers(struct lws *wsi); diff --git a/lib/lws-plat-unix.c b/lib/lws-plat-unix.c index eb2f762..880ad85 100644 --- a/lib/lws-plat-unix.c +++ b/lib/lws-plat-unix.c @@ -441,8 +441,10 @@ next: static void -sigpipe_handler(int x) +sigabrt_handler(int x) { + printf("%s\n", __func__); + //*(char *)0 = 0; } LWS_VISIBLE int @@ -456,7 +458,9 @@ lws_plat_context_early_init(void) sigprocmask(SIG_BLOCK, &mask, NULL); - signal(SIGPIPE, sigpipe_handler); + signal(SIGPIPE, SIG_IGN); + + signal(SIGABRT, sigabrt_handler); return 0; } diff --git a/lib/private-libwebsockets.h b/lib/private-libwebsockets.h index 35f3ed6..0684326 100644 --- a/lib/private-libwebsockets.h +++ b/lib/private-libwebsockets.h @@ -621,6 +621,8 @@ struct lws_http_mount { const char *origin; /* path to be mounted, eg, "/var/www/warmcat.com" */ const char *def; /* default target, eg, "index.html" */ + struct lws_protocol_vhost_options *cgienv; + unsigned char origin_protocol; unsigned char mountpoint_len; }; diff --git a/lib/server.c b/lib/server.c index f1ca7ac..b28c9bb 100644 --- a/lib/server.c +++ b/lib/server.c @@ -218,17 +218,48 @@ static const char * get_mimetype(const char *file) int lws_http_serve(struct lws *wsi, char *uri, const char *origin) { const char *mimetype; - char path[256]; - int n; + struct stat st; + char path[256], sym[256]; + int n, spin = 0; lwsl_notice("%s: %s %s\n", __func__, uri, origin); snprintf(path, sizeof(path) - 1, "%s/%s", origin, uri); + do { + spin++; + + if (stat(path, &st)) { + lwsl_err("unable to stat %s\n", path); + goto bail; + } + + lwsl_debug(" %s mode %d\n", path, S_IFMT & st.st_mode); + + if ((S_IFMT & st.st_mode) == S_IFLNK) { + if (readlink(path, sym, sizeof(sym))) { + lwsl_err("Failed to read link %s\n", path); + goto bail; + } + lwsl_debug("symlink %s -> %s\n", path, sym); + snprintf(path, sizeof(path) - 1, "%s", sym); + } + + if ((S_IFMT & st.st_mode) == S_IFDIR) { + lwsl_debug("default filename append to dir\n"); + snprintf(path, sizeof(path) - 1, "%s/%s/index.html", + origin, uri); + } + + } while ((S_IFMT & st.st_mode) != S_IFREG && spin < 5); + + if (spin == 5) { + lwsl_err("symlink loop %s \n", path); + } + mimetype = get_mimetype(path); if (!mimetype) { lwsl_err("unknown mimetype for %s", path); - lws_return_http_status(wsi, HTTP_STATUS_NOT_FOUND, NULL); - return -1; + goto bail; } n = lws_serve_http_file(wsi, path, mimetype, NULL, 0); @@ -237,6 +268,10 @@ int lws_http_serve(struct lws *wsi, char *uri, const char *origin) return -1; /* error or can't reuse connection: close the socket */ return 0; +bail: + lws_return_http_status(wsi, HTTP_STATUS_NOT_FOUND, NULL); + + return -1; } int @@ -403,7 +438,11 @@ lws_http_action(struct lws *wsi) hm = wsi->vhost->mount_list; while (hm) { if (uri_len >= hm->mountpoint_len && - !strncmp(uri_ptr, hm->mountpoint, hm->mountpoint_len)) { + !strncmp(uri_ptr, hm->mountpoint, hm->mountpoint_len) && + (uri_ptr[hm->mountpoint_len] == '\0' || + uri_ptr[hm->mountpoint_len] == '/' || + hm->mountpoint_len == 1) + ) { if (hm->mountpoint_len > best) { best = hm->mountpoint_len; hit = hm; @@ -414,7 +453,8 @@ lws_http_action(struct lws *wsi) if (hit) { char *s = uri_ptr + hit->mountpoint_len; - lwsl_err("*** hit %d %d %s\n", hit->mountpoint_len, hit->origin_protocol , hit->origin); + lwsl_debug("*** hit %d %d %s\n", hit->mountpoint_len, + hit->origin_protocol , hit->origin); /* * if we have a mountpoint like https://xxx.com/yyy @@ -431,50 +471,87 @@ lws_http_action(struct lws *wsi) * / at the end, we must redirect to add it so the browser * understands he is one "directory level" down. */ - if (hit->mountpoint_len > 1 || (hit->origin_protocol & 4)) - if (*s != '/' || (hit->origin_protocol & 4)) { - unsigned char *start = pt->serv_buf + LWS_PRE, + if ((hit->mountpoint_len > 1 || (hit->origin_protocol & 4)) && + (*s != '/' || (hit->origin_protocol & 4))) { + unsigned char *start = pt->serv_buf + LWS_PRE, *p = start, *end = p + 512; - static const char *oprot[] = { - "http://", "https://" - }; - - if (!lws_hdr_total_length(wsi, WSI_TOKEN_HOST)) - goto bail_nuke_ah; - if (lws_add_http_header_status(wsi, 301, &p, end)) - goto bail_nuke_ah; - - lwsl_err("**** %s", hit->origin); - - /* > at start indicates deal with by redirect */ - if (hit->origin_protocol & 4) - n = snprintf((char *)end, 256, "%s%s", - oprot[hit->origin_protocol & 1], - hit->origin); - else - n = snprintf((char *)end, 256, - "https://%s/%s/", - lws_hdr_simple_ptr(wsi, WSI_TOKEN_HOST), - uri_ptr); - if (lws_add_http_header_by_token(wsi, - WSI_TOKEN_HTTP_LOCATION, - end, n, &p, end)) - goto bail_nuke_ah; - if (lws_finalize_http_header(wsi, &p, end)) - goto bail_nuke_ah; - n = lws_write(wsi, start, p - start, - LWS_WRITE_HTTP_HEADERS); - if ((int)n < 0) - goto bail_nuke_ah; - - return lws_http_transaction_completed(wsi); + static const char *oprot[] = { + "http://", "https://" + }; + + if (!lws_hdr_total_length(wsi, WSI_TOKEN_HOST)) + goto bail_nuke_ah; + if (lws_add_http_header_status(wsi, 301, &p, end)) + goto bail_nuke_ah; + + lwsl_debug("**** %s", hit->origin); + + /* > at start indicates deal with by redirect */ + if (hit->origin_protocol & 4) + n = snprintf((char *)end, 256, "%s%s", + oprot[hit->origin_protocol & 1], + hit->origin); + else + n = snprintf((char *)end, 256, + "https://%s/%s/", + lws_hdr_simple_ptr(wsi, WSI_TOKEN_HOST), + uri_ptr); + if (lws_add_http_header_by_token(wsi, + WSI_TOKEN_HTTP_LOCATION, + end, n, &p, end)) + goto bail_nuke_ah; + if (lws_finalize_http_header(wsi, &p, end)) + goto bail_nuke_ah; + n = lws_write(wsi, start, p - start, + LWS_WRITE_HTTP_HEADERS); + if ((int)n < 0) + goto bail_nuke_ah; + + return lws_http_transaction_completed(wsi); + } + +#ifdef LWS_WITH_CGI + /* did we hit something with a cgi:// origin? */ + if (hit->origin_protocol == LWSMPRO_CGI) { + const char *cmd[] = { + NULL, /* replace with cgi path */ + NULL + }; + unsigned char *p, *end, buffer[256]; + + lwsl_debug("%s: cgi\n", __func__); + cmd[0] = hit->origin; + n = lws_cgi(wsi, cmd, hit->mountpoint_len, 5, + hit->cgienv); + if (n) { + lwsl_err("%s: cgi failed\n"); + return -1; } + p = buffer + LWS_PRE; + end = p + sizeof(buffer) - LWS_PRE; + + if (lws_add_http_header_status(wsi, 200, &p, end)) + return 1; + if (lws_add_http_header_by_token(wsi, WSI_TOKEN_CONNECTION, + (unsigned char *)"close", 5, &p, end)) + return 1; + n = lws_write(wsi, buffer + LWS_PRE, + p - (buffer + LWS_PRE), + LWS_WRITE_HTTP_HEADERS); + + return 0; + } +#endif - if (s[0] == '\0' || (s[0] == '/' && s[1] == '\0')) + n = strlen(s); + if (s[0] == '\0' || (n == 1 && s[n - 1] == '/')) s = (char *)hit->def; if (!s) s = "index.html"; + + + n = lws_http_serve(wsi, s, hit->origin); } else n = wsi->protocol->callback(wsi, LWS_CALLBACK_HTTP, @@ -992,18 +1069,21 @@ lws_adopt_socket_vhost(struct lws_vhost *vh, lws_sockfd_type accept_fd) lws_libuv_accept(new_wsi, new_wsi->sock); if (!LWS_SSL_ENABLED(new_wsi->vhost)) { - if (insert_wsi_socket_into_fds(context, new_wsi)) + if (insert_wsi_socket_into_fds(context, new_wsi)) { + lwsl_err("%s: fail inserting socket\n", __func__); goto fail; + } } else { new_wsi->mode = LWSCM_SSL_INIT; - if (lws_server_socket_service_ssl(new_wsi, accept_fd)) + if (lws_server_socket_service_ssl(new_wsi, accept_fd)) { + lwsl_err("%s: fail ssl negotiation\n", __func__); goto fail; + } } return new_wsi; fail: - lwsl_err("%s: fail\n", __func__); lws_close_free_wsi(new_wsi, LWS_CLOSE_STATUS_NOSTATUS); return NULL; diff --git a/lib/ssl-server.c b/lib/ssl-server.c index 9bd2af9..55ff61b 100644 --- a/lib/ssl-server.c +++ b/lib/ssl-server.c @@ -178,7 +178,8 @@ lws_ssl_server_name_cb(SSL *ssl, int *ad, void *arg) if (servername) { vhost = lws_select_vhost(context, port, servername); if (vhost) { - lwsl_notice("SNI: Found: %s (port %d)\n", servername, port); + lwsl_debug("SNI: Found: %s (port %d)\n", + servername, port); SSL_set_SSL_CTX(ssl, vhost->ssl_ctx); return SSL_TLSEXT_ERR_OK; } diff --git a/lwsws/conf.c b/lwsws/conf.c index ff4029d..1cbc5ed 100644 --- a/lwsws/conf.c +++ b/lwsws/conf.c @@ -48,6 +48,7 @@ static const char * const paths_vhosts[] = { "vhosts[].mounts[].mountpoint", "vhosts[].mounts[].origin", "vhosts[].mounts[].default", + "vhosts[].mounts[].cgi-env[].*", "vhosts[].ws-protocols[].*.*", "vhosts[].ws-protocols[].*", "vhosts[].ws-protocols[]", @@ -64,6 +65,7 @@ enum lejp_vhost_paths { LEJPVP_MOUNTPOINT, LEJPVP_ORIGIN, LEJPVP_DEFAULT, + LEJPVP_CGI_ENV, LEJPVP_PROTOCOL_NAME_OPT, LEJPVP_PROTOCOL_NAME, LEJPVP_PROTOCOL, @@ -78,6 +80,7 @@ struct jpargs { struct lws_http_mount *head, *last; char *mountpoint, *origin, *def; struct lws_protocol_vhost_options *pvo; + struct lws_protocol_vhost_options *mp_cgienv; }; static void * @@ -144,13 +147,15 @@ static char lejp_vhosts_cb(struct lejp_ctx *ctx, char reason) { struct jpargs *a = (struct jpargs *)ctx->user; - struct lws_protocol_vhost_options *pvo; + struct lws_protocol_vhost_options *pvo, *mp_cgienv; struct lws_http_mount *m; int n; -// lwsl_notice(" %d: %s (%d)\n", reason, ctx->path, ctx->path_match); -// for (n = 0; n < ctx->wildcount; n++) -// lwsl_notice(" %d\n", ctx->wild[n]); +#if 0 + lwsl_notice(" %d: %s (%d)\n", reason, ctx->path, ctx->path_match); + for (n = 0; n < ctx->wildcount; n++) + lwsl_notice(" %d\n", ctx->wild[n]); +#endif if (reason == LEJPCB_OBJECT_START && ctx->path_match == LEJPVP + 1) { /* set the defaults for this vhost */ @@ -186,6 +191,7 @@ lejp_vhosts_cb(struct lejp_ctx *ctx, char reason) a->mountpoint = NULL; a->origin = NULL; a->def = NULL; + a->mp_cgienv = NULL; } /* this catches, eg, vhosts[].ws-protocols[].xxx-protocol */ @@ -235,7 +241,7 @@ lejp_vhosts_cb(struct lejp_ctx *ctx, char reason) } n = lws_write_http_mount(a->last, &m, a->p, a->mountpoint, - a->origin, a->def); + a->origin, a->def, a->mp_cgienv); if (!n) return 1; a->p += n; @@ -274,7 +280,25 @@ lejp_vhosts_cb(struct lejp_ctx *ctx, char reason) case LEJPVP_DEFAULT: a->def = a->p; break; + case LEJPVP_CGI_ENV: + mp_cgienv = lwsws_align(a); + a->p += sizeof(*a->mp_cgienv); + + mp_cgienv->next = a->mp_cgienv; + a->mp_cgienv = mp_cgienv; + n = lejp_get_wildcard(ctx, 0, a->p, a->end - a->p); + mp_cgienv->name = a->p; + a->p += n; + mp_cgienv->value = a->p; + mp_cgienv->options = NULL; + a->p += snprintf(a->p, a->end - a->p, "%s", ctx->buf); + *(a->p)++ = '\0'; + + lwsl_notice(" adding cgi-env '%s' = '%s'\n", mp_cgienv->name, + mp_cgienv->value); + + break; case LEJPVP_PROTOCOL_NAME_OPT: /* this catches, eg, * vhosts[].ws-protocols[].xxx-protocol.yyy-option @@ -435,7 +459,7 @@ lwsws_get_config_globals(struct lws_context_creation_info *info, const char *d, a.info = info; a.p = *cs; - a.end = a.p + *len; + a.end = (a.p + *len) - 1; a.valid = 0; if (lwsws_get_config(&a, "/etc/lwsws/conf", paths_global, diff --git a/lwsws/http.c b/lwsws/http.c index 66f398f..ff4ca98 100644 --- a/lwsws/http.c +++ b/lwsws/http.c @@ -152,42 +152,6 @@ int callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user, } #endif -#ifdef LWS_WITH_CGI - if (!strncmp(in, "/cgitest", 8)) { - static char *cmd[] = { - "/bin/sh", - "-c", - INSTALL_DATADIR"/libwebsockets-test-server/lws-cgi-test.sh", -// "/var/www/cgi-bin/cgit", - NULL - }; - - lwsl_notice("%s: cgitest\n", __func__); - n = lws_cgi(wsi, cmd, 8, 5); - if (n) { - lwsl_err("%s: cgi failed\n"); - return -1; - } - p = buffer + LWS_PRE; - end = p + sizeof(buffer) - LWS_PRE; - - if (lws_add_http_header_status(wsi, 200, &p, end)) - return 1; - if (lws_add_http_header_by_token(wsi, WSI_TOKEN_CONNECTION, - (unsigned char *)"close", 5, &p, end)) - return 1; - n = lws_write(wsi, buffer + LWS_PRE, - p - (buffer + LWS_PRE), - LWS_WRITE_HTTP_HEADERS); - - /* the cgi starts by outputting headers, we can't - * finalize the headers until we see the end of that - */ - - break; - } -#endif - /* if a legal POST URL, let it continue and accept data */ if (lws_hdr_total_length(wsi, WSI_TOKEN_POST_URI)) return 0; diff --git a/test-server/test-server-http.c b/test-server/test-server-http.c index 902e945..af40609 100644 --- a/test-server/test-server-http.c +++ b/test-server/test-server-http.c @@ -215,42 +215,6 @@ int callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user, } #endif -#ifdef LWS_WITH_CGI - if (!strncmp(in, "/cgitest", 8)) { - static char *cmd[] = { - "/bin/sh", - "-c", - INSTALL_DATADIR"/libwebsockets-test-server/lws-cgi-test.sh", -// "/var/www/cgi-bin/cgit", - NULL - }; - - lwsl_notice("%s: cgitest\n", __func__); - n = lws_cgi(wsi, cmd, 8, 5); - if (n) { - lwsl_err("%s: cgi failed\n"); - return -1; - } - p = buffer + LWS_PRE; - end = p + sizeof(buffer) - LWS_PRE; - - if (lws_add_http_header_status(wsi, 200, &p, end)) - return 1; - if (lws_add_http_header_by_token(wsi, WSI_TOKEN_CONNECTION, - (unsigned char *)"close", 5, &p, end)) - return 1; - n = lws_write(wsi, buffer + LWS_PRE, - p - (buffer + LWS_PRE), - LWS_WRITE_HTTP_HEADERS); - - /* the cgi starts by outputting headers, we can't - * finalize the headers until we see the end of that - */ - - break; - } -#endif - /* if a legal POST URL, let it continue and accept data */ if (lws_hdr_total_length(wsi, WSI_TOKEN_POST_URI)) return 0; @@ -423,15 +387,7 @@ int callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user, if (pss->fd == LWS_INVALID_FILE) goto try_to_reuse; -#ifdef LWS_WITH_CGI - if (pss->reason_bf & 1) { - if (lws_cgi_write_split_stdout_headers(wsi) < 0) - goto bail; - pss->reason_bf &= ~1; - break; - } -#endif #ifndef LWS_NO_CLIENT if (pss->reason_bf & 2) { char *px = buf + LWS_PRE; @@ -601,56 +557,6 @@ bail: break; #endif -#ifdef LWS_WITH_CGI - /* CGI IO events (POLLIN/OUT) appear here our demo user code policy is - * - * - POST data goes on subprocess stdin - * - subprocess stdout goes on http via writeable callback - * - subprocess stderr goes to the logs - */ - case LWS_CALLBACK_CGI: - pss->args = *((struct lws_cgi_args *)in); - //lwsl_notice("LWS_CALLBACK_CGI: ch %d\n", pss->args.ch); - switch (pss->args.ch) { /* which of stdin/out/err ? */ - case LWS_STDIN: - /* TBD stdin rx flow control */ - break; - case LWS_STDOUT: - pss->reason_bf |= 1; - /* when writing to MASTER would not block */ - lws_callback_on_writable(wsi); - break; - case LWS_STDERR: - n = read(lws_get_socket_fd(pss->args.stdwsi[LWS_STDERR]), - buf, 127); - //lwsl_notice("stderr reads %d\n", n); - if (n > 0) { - if (buf[n - 1] != '\n') - buf[n++] = '\n'; - buf[n] = '\0'; - lwsl_notice("CGI-stderr: %s\n", buf); - } - break; - } - break; - - case LWS_CALLBACK_CGI_TERMINATED: - //lwsl_notice("LWS_CALLBACK_CGI_TERMINATED\n"); - /* because we sent on openended http, close the connection */ - return -1; - - case LWS_CALLBACK_CGI_STDIN_DATA: /* POST body for stdin */ - //lwsl_notice("LWS_CALLBACK_CGI_STDIN_DATA\n"); - pss->args = *((struct lws_cgi_args *)in); - n = write(lws_get_socket_fd(pss->args.stdwsi[LWS_STDIN]), - pss->args.data, pss->args.len); - //lwsl_notice("LWS_CALLBACK_CGI_STDIN_DATA: write says %d", n); - if (n < pss->args.len) - lwsl_notice("LWS_CALLBACK_CGI_STDIN_DATA: sent %d only %d went", - n, pss->args.len); - return n; -#endif - /* * callbacks for managing the external poll() array appear in * protocol 0 callback