commit - 28239bac769c9db0bcc8f48bdd16db80886f84e9
commit + 8857131d3f62c08a0b3d450582560322c36ea219
blob - ca72d81c7c2c00b392c169b96e90353c7d5d1e0c
blob + 4bb8cbe2e0de72bbbc39546d4541198f274d12d1
--- fcgi.c
+++ fcgi.c
char server[HOST_NAME_MAX + 1];
char path[PATH_MAX];
char query[GEMINI_MAXLEN];
+ char method[8];
int nlen, vlen;
while (fcgi->fcg_toread > 0) {
vlen > 0) {
fcgi->fcg_toread -= vlen;
evbuffer_remove(src, &query, vlen);
+ query[vlen] = '\0';
free(clt->clt_query);
if ((clt->clt_query = strdup(query)) == NULL)
log_debug("clt %d: query: %s", clt->clt_id,
clt->clt_query);
+ continue;
+ }
+
+ if (!strcmp(pname, "REQUEST_METHOD") &&
+ (size_t)vlen < sizeof(method)) {
+ fcgi->fcg_toread -= vlen;
+ evbuffer_remove(src, &method, vlen);
+ method[vlen] = '\0';
+
+ if (!strcasecmp(method, "GET"))
+ clt->clt_method = METHOD_GET;
+ if (!strcasecmp(method, "POST"))
+ clt->clt_method = METHOD_POST;
+
continue;
}
return (0);
}
+
+static int
+fcgi_parse_form(struct fcgi *fcgi, struct client *clt, struct evbuffer *src)
+{
+ char *a, *s;
+ char tmp[2048];
+ size_t len;
+
+ if (fcgi->fcg_toread == 0) {
+ clt->clt_bodydone = 1;
+ return (proxy_start_request(fcgi->fcg_env, clt));
+ }
+ len = sizeof(tmp) - 1;
+ if (len > (size_t)fcgi->fcg_toread)
+ len = fcgi->fcg_toread;
+
+ fcgi->fcg_toread -= len;
+ evbuffer_remove(src, &tmp, len);
+ tmp[len] = '\0';
+
+ if (clt->clt_bodydone)
+ return (0);
+
+ if (clt->clt_bodylen > GEMINI_MAXLEN) {
+ free(clt->clt_body);
+ clt->clt_body = NULL;
+ return (0);
+ }
+
+ if (clt->clt_body != NULL) {
+ if ((a = strchr(tmp, '&')) != NULL ||
+ (a = strchr(tmp, '\r')) != NULL) {
+ *a = '\0';
+ clt->clt_bodydone = 1;
+ }
+
+ a = clt->clt_body;
+ if (asprintf(&clt->clt_body, "%s%s", a, tmp) == -1) {
+ free(a);
+ clt->clt_body = NULL;
+ return (0);
+ }
+ clt->clt_bodylen += strlen(tmp);
+ return (0);
+ }
+
+ if (clt->clt_bodylen != 0)
+ return (0); /* EOM situation */
+
+ if ((s = strstr(tmp, "q=")) == NULL)
+ return (0);
+ s += 2;
+
+ if ((a = strchr(s, '&')) != NULL ||
+ (a = strchr(s, '\r')) != NULL) {
+ *a = '\0';
+ clt->clt_bodydone = 1;
+ }
+
+ clt->clt_bodylen = strlen(s);
+ if ((clt->clt_body = strdup(s)) == NULL)
+ return (0);
+
+ return (0);
+}
+
void
fcgi_read(struct bufferevent *bev, void *d)
{
}
if (fcgi->fcg_toread == 0) {
evbuffer_drain(src, fcgi->fcg_toread);
- proxy_start_request(env, clt);
+ if (clt->clt_method == METHOD_GET) {
+ if (proxy_start_request(env, clt)
+ == -1)
+ return;
+ }
break;
}
if (fcgi_parse_params(fcgi, src, clt) == -1) {
}
break;
case FCGI_STDIN:
- /* ignore */
- evbuffer_drain(src, fcgi->fcg_toread);
+ if (clt == NULL ||
+ clt->clt_method != METHOD_POST) {
+ evbuffer_drain(src, fcgi->fcg_toread);
+ break;
+ }
+ if (fcgi_parse_form(fcgi, clt, src) == -1)
+ return;
break;
case FCGI_ABORT_REQUEST:
if (clt == NULL) {
blob - f91b4726219ad3b6279cf6434b4eb645b13cc38c
blob + 01048822f1936c48ec0afb7515c540f592595f66
--- fragments.tmpl
+++ fragments.tmpl
</main>
{{ render tp_foot(tp) }}
{{ end }}
+
+{{ define tp_inputpage(struct template *tp, const char *prompt) }}
+ {{ render tp_head(tp, "en", "input request") }}
+ <p>The server ask for input: {{ prompt }}</p>
+ <form method="post" enctype="{{ FORM_URLENCODED }}">
+ <label for="reply">
+ <span>response </span>
+ </label>
+ <input type="text" value="" id="reply" name="q" />
+ </form>
+{{ render tp_foot(tp) }}
+{{ end }}
blob - 45fe5a76745182c85ebc18cb5f8bbbac17c3045e
blob + 37590580ae2b38c294c24ffe438fa1b2384859d5
--- galileo.h
+++ galileo.h
#define PROXY_NUMPROC 3
#define PROC_PARENT_SOCK_FILENO 3
#define GEMINI_MAXLEN (1024 + 1) /* NULL */
+#define FORM_URLENCODED "application/x-www-form-urlencoded"
enum {
+ METHOD_UNKNOWN,
+ METHOD_GET,
+ METHOD_POST,
+};
+
+enum {
IMSG_NONE,
IMSG_CFG_START,
IMSG_CFG_SRV,
char *clt_script_name;
char *clt_path_info;
char *clt_query;
+ int clt_method;
+ int clt_bodydone;
+ char *clt_body;
+ int clt_bodylen;
struct proxy_config *clt_pc;
struct event_asr *clt_evasr;
struct addrinfo *clt_addrinfo;
int tp_foot(struct template *);
int tp_figure(struct template *, const char *, const char *);
int tp_error(struct template *, int, const char *);
+int tp_inputpage(struct template *, const char *);
/* galileo.c */
int accept_reserve(int, struct sockaddr *, socklen_t *, int,
void proxy(struct privsep *, struct privsep_proc *);
void proxy_purge(struct server *);
-void proxy_start_request(struct galileo *, struct client *);
+int proxy_start_request(struct galileo *, struct client *);
void proxy_client_free(struct client *);
SPLAY_PROTOTYPE(fcgi_tree, fcgi, fcg_nodes, fcgi_cmp);
blob - a8313a7a6bcf16c034dd7cfc8ad9e088e2f833be
blob + 107898868bf05ee176299f6fba32f140e52e0ab9
--- proxy.c
+++ proxy.c
return NULL;
}
-void
+int
proxy_start_request(struct galileo *env, struct client *clt)
{
struct addrinfo hints;
struct asr_query *query;
- char port[32];
+ int r;
+ char *url, port[32];
if ((clt->clt_pc = proxy_server_match(env, clt)) == NULL) {
if (proxy_start_reply(clt, 501, "text/html") == -1)
- return;
+ return (-1);
if (tp_error(clt->clt_tp, -1, "unknown server") == -1)
- return;
- fcgi_end_request(clt, 1);
- return;
+ return (-1);
+ return (fcgi_end_request(clt, 1));
+ }
+
+ if (clt->clt_bodylen != 0 && clt->clt_body == NULL) {
+ if (proxy_start_reply(clt, 400, "text/html") == -1)
+ return (-1);
+ if (tp_error(clt->clt_tp, -1, "bad request") == -1)
+ return (-1);
+ return (fcgi_end_request(clt, 1));
}
+ if (clt->clt_body) {
+ r = asprintf(&url, "%s%s?%s", clt->clt_script_name,
+ clt->clt_path_info + 1, clt->clt_body);
+ if (r == -1)
+ return (fcgi_end_request(clt, 1));
+
+ if (proxy_start_reply(clt, 302, url) == -1 ||
+ fcgi_end_request(clt, 1) == -1) {
+ free(url);
+ return (-1);
+ }
+ free(url);
+ return (0);
+ }
+
(void)snprintf(port, sizeof(port), "%d", clt->clt_pc->proxy_port);
memset(&hints, 0, sizeof(hints));
query = getaddrinfo_async(clt->clt_pc->proxy_addr, port, &hints, NULL);
if (query == NULL) {
log_warn("getaddrinfo_async");
- fcgi_abort_request(clt);
- return;
+ return (fcgi_abort_request(clt));
}
clt->clt_evasr = event_asr_run(query, proxy_resolved, clt);
if (clt->clt_evasr == NULL) {
log_warn("event_asr_run");
asr_abort(query);
- fcgi_abort_request(clt);
- return;
+ return (fcgi_abort_request(clt));
}
+
+ return (0);
}
void
csp = "Content-Security-Policy: default-src 'self'; "
"script-src 'none'; object-src 'none';\r\n";
- if (ctype != NULL && !strcmp(ctype, "text/html"))
- ctype = "text/html;charset=utf-8";
-
if (status != 200 &&
clt_printf(clt, "Status: %d\r\n", status) == -1)
return (-1);
- if (ctype != NULL &&
- clt_printf(clt, "Content-Type: %s\r\n", ctype) == -1)
- return (-1);
-
if (clt_puts(clt, csp) == -1)
return (-1);
+
+ if (status == 302) {
+ /* use "ctype" as redirect target */
+ if (clt_printf(clt, "Location: %s\r\n", ctype) == -1)
+ return (-1);
+ if (clt_puts(clt, "\r\n") == -1)
+ return (-1);
+ return (0);
+ }
+ if (ctype != NULL) {
+ if (!strcmp(ctype, "text/html"))
+ ctype = "text/html;charset=utf-8";
+ if (clt_printf(clt, "Content-Type: %s\r\n", ctype)
+ == -1)
+ return (-1);
+ }
+
if (clt_puts(clt, "\r\n") == -1)
return (-1);
code = (hdr[0] - '0') * 10 + (hdr[1] - '0');
switch (hdr[0]) {
+ case '1':
+ if (proxy_start_reply(clt, 200, "text/html") == -1)
+ goto err;
+ if (tp_inputpage(clt->clt_tp, &hdr[3]) == -1)
+ goto err;
+ fcgi_end_request(clt, 0);
+ goto err;
case '2':
/* handled below */
break;
if (clt->clt_bev)
bufferevent_free(clt->clt_bev);
+ free(clt->clt_body);
free(clt->clt_tp);
free(clt->clt_server_name);
free(clt->clt_script_name);