commit - 83991185828f6429132ea6dc924774b2c73d7c27
commit + 18906bcc2b3035e3483bcff2371e771da0004cae
blob - 8ad3eb7e54a09f151c2bda965bdb7b3dd61b807b
blob + e8755e42ab9311cfc4b7fe0d1ab154408818523c
--- fcgi.c
+++ fcgi.c
#include "galileo.h"
#define MIN(a, b) ((a) < (b) ? (a) : (b))
+
+#define FCGI_MAX_CONTENT_SIZE 65535
struct fcgi_header {
unsigned char version;
break;
}
- clt->clt_tp = template(clt, clt_tp_puts, clt_tp_putc);
+ clt->clt_tp = template(clt, clt_write, clt->clt_buf,
+ sizeof(clt->clt_buf));
if (clt->clt_tp == NULL) {
free(clt);
log_warn("template");
int
clt_flush(struct client *clt)
+{
+ return (template_flush(clt->clt_tp));
+}
+
+static inline int
+dowrite(struct client *clt, const void *data, size_t len)
{
struct fcgi *fcgi = clt->clt_fcgi;
struct bufferevent *bev = fcgi->fcg_bev;
struct fcgi_header hdr;
- if (clt->clt_buflen == 0)
- return (0);
-
memset(&hdr, 0, sizeof(hdr));
hdr.version = FCGI_VERSION_1;
hdr.type = FCGI_STDOUT;
hdr.req_id0 = (clt->clt_id & 0xFF);
hdr.req_id1 = (clt->clt_id >> 8);
- hdr.content_len0 = (clt->clt_buflen & 0xFF);
- hdr.content_len1 = (clt->clt_buflen >> 8);
+ hdr.content_len0 = (len & 0xFF);
+ hdr.content_len1 = (len >> 8);
if (bufferevent_write(bev, &hdr, sizeof(hdr)) == -1 ||
- bufferevent_write(bev, clt->clt_buf, clt->clt_buflen) == -1) {
+ bufferevent_write(bev, clt->clt_buf, len) == -1) {
fcgi_error(bev, EV_WRITE, fcgi);
return (-1);
}
- clt->clt_buflen = 0;
-
return (0);
}
int
-clt_write(struct client *clt, const uint8_t *buf, size_t len)
+clt_write(void *arg, const void *d, size_t len)
{
- size_t left, copy;
+ struct client *clt = arg;
+ const char *data = d;
+ size_t avail;
while (len > 0) {
- left = sizeof(clt->clt_buf) - clt->clt_buflen;
- if (left == 0) {
- if (clt_flush(clt) == -1)
- return (-1);
- left = sizeof(clt->clt_buf);
- }
-
- copy = MIN(left, len);
-
- memcpy(&clt->clt_buf[clt->clt_buflen], buf, copy);
- clt->clt_buflen += copy;
- buf += copy;
- len -= copy;
+ avail = MIN(len, FCGI_MAX_CONTENT_SIZE);
+ if (dowrite(clt, data, avail) == -1)
+ return (-1);
+ data += avail;
+ len -= avail;
}
return (0);
}
int
-clt_putc(struct client *clt, char ch)
-{
- return (clt_write(clt, &ch, 1));
-}
-
-int
-clt_puts(struct client *clt, const char *str)
-{
- return (clt_write(clt, str, strlen(str)));
-}
-
-int
clt_write_bufferevent(struct client *clt, struct bufferevent *bev)
{
struct evbuffer *src = EVBUFFER_INPUT(bev);
- size_t len, left, copy;
+ size_t len;
+ int ret;
len = EVBUFFER_LENGTH(src);
- while (len > 0) {
- left = sizeof(clt->clt_buf) - clt->clt_buflen;
- if (left == 0) {
- if (clt_flush(clt) == -1)
- return (-1);
- left = sizeof(clt->clt_buf);
- }
-
- copy = bufferevent_read(bev, &clt->clt_buf[clt->clt_buflen],
- MIN(left, len));
- clt->clt_buflen += copy;
-
- len = EVBUFFER_LENGTH(src);
- }
-
- return (0);
+ ret = clt_write(clt, EVBUFFER_DATA(src), len);
+ evbuffer_drain(src, len);
+ return (ret);
}
int
-clt_printf(struct client *clt, const char *fmt, ...)
-{
- struct fcgi *fcgi = clt->clt_fcgi;
- struct bufferevent *bev = fcgi->fcg_bev;
- char *str;
- va_list ap;
- int r;
-
- va_start(ap, fmt);
- r = vasprintf(&str, fmt, ap);
- va_end(ap);
- if (r == -1) {
- fcgi_error(bev, EV_WRITE, fcgi);
- return (-1);
- }
-
- r = clt_write(clt, str, r);
- free(str);
- return (r);
-}
-
-int
-clt_tp_puts(struct template *tp, const char *str)
-{
- struct client *clt = tp->tp_arg;
-
- if (clt_puts(clt, str) == -1)
- return (-1);
-
- return (0);
-}
-
-int
-clt_tp_putc(struct template *tp, int c)
-{
- struct client *clt = tp->tp_arg;
-
- if (clt_putc(clt, c) == -1)
- return (-1);
-
- return (0);
-}
-
-int
fcgi_cmp(struct fcgi *a, struct fcgi *b)
{
return ((int)a->fcg_id - b->fcg_id);
blob - 05a8126ae966aec99082f671e6dc52680c168fd9
blob + 7c07219997055de3dd12bd37dfdead4e69fa894c
--- galileo.h
+++ galileo.h
int clt_translate;
char clt_buf[1024];
- size_t clt_buflen;
SPLAY_ENTRY(client) clt_nodes;
};
void fcgi_write(struct bufferevent *, void *);
void fcgi_error(struct bufferevent *, short error, void *);
void fcgi_free(struct fcgi *);
-int clt_putc(struct client *, char);
-int clt_puts(struct client *, const char *);
int clt_write_bufferevent(struct client *, struct bufferevent *);
int clt_flush(struct client *);
-int clt_write(struct client *, const uint8_t *, size_t);
-int clt_printf(struct client *, const char *, ...)
- __attribute__((__format__(printf, 2, 3)))
- __attribute__((__nonnull__(2)));
-int clt_tp_puts(struct template *, const char *);
-int clt_tp_putc(struct template *, int);
+int clt_write(void *, const void *, size_t);
int fcgi_cmp(struct fcgi *, struct fcgi *);
int fcgi_client_cmp(struct client *, struct client *);
blob - e68c29ebb94b7838ee92572d741ba5903e4c35fe
blob + 7b554d2017bcdfad1c15b6473a1b93f322ad9e4d
--- proxy.c
+++ proxy.c
static int
gemtext_translate_line(struct client *clt, char *line)
{
+ struct template *tp = clt->clt_tp;
char buf[1025];
char *url;
if (tp_htmlescape(clt->clt_tp, line) == -1)
return (-1);
- return (clt_putc(clt, '\n'));
+ return (tp_write(tp, "\n", 1));
}
/* bullet */
if (!strncmp(line, "* ", 2)) {
if (clt->clt_translate & TR_NAV) {
- if (clt_puts(clt, "</ul></nav>") == -1)
+ if (tp_writes(tp, "</ul></nav>") == -1)
return (-1);
clt->clt_translate &= ~TR_NAV;
}
if (!(clt->clt_translate & TR_LIST)) {
- if (clt_puts(clt, "<ul>") == -1)
+ if (tp_writes(tp, "<ul>") == -1)
return (-1);
clt->clt_translate |= TR_LIST;
}
- if (clt_puts(clt, "<li>") == -1 ||
+ if (tp_writes(tp, "<li>") == -1 ||
tp_htmlescape(clt->clt_tp, line + 2) == -1 ||
- clt_puts(clt, "</li>") == -1)
+ tp_writes(tp, "</li>") == -1)
return (-1);
return (0);
}
if (clt->clt_translate & TR_LIST) {
- if (clt_puts(clt, "</ul>") == -1)
+ if (tp_writes(tp, "</ul>") == -1)
return (-1);
clt->clt_translate &= ~TR_LIST;
}
if (!(clt->clt_pc->flags & PROXY_NO_IMGPRV) &&
match_image_heur(url)) {
if (clt->clt_translate & TR_NAV) {
- if (clt_puts(clt, "</ul></nav>") == -1)
+ if (tp_writes(tp, "</ul></nav>") == -1)
return (-1);
clt->clt_translate &= ~TR_NAV;
}
- if (tp_figure(clt->clt_tp, url, label) == -1)
+ if (tp_figure(tp, url, label) == -1)
return (-1);
return (0);
}
if (!(clt->clt_translate & TR_NAV)) {
- if (clt_puts(clt, "<nav><ul>") == -1)
+ if (tp_writes(tp, "<nav><ul>") == -1)
return (-1);
clt->clt_translate |= TR_NAV;
}
- if (clt_puts(clt, "<li><a href='") == -1)
+ if (tp_writes(tp, "<li><a href='") == -1)
return (-1);
if (tp_urlescape(clt->clt_tp, url) == -1 ||
- clt_puts(clt, "'>") == -1 ||
+ tp_writes(tp, "'>") == -1 ||
tp_htmlescape(clt->clt_tp, label) == -1 ||
- clt_puts(clt, "</a></li>") == -1)
+ tp_writes(tp, "</a></li>") == -1)
return (-1);
return (0);
}
if (clt->clt_translate & TR_NAV) {
- if (clt_puts(clt, "</ul></nav>") == -1)
+ if (tp_writes(tp, "</ul></nav>") == -1)
return (-1);
clt->clt_translate &= ~TR_NAV;
}
line += strspn(line, " \t");
clt->clt_translate |= TR_PRE;
- return (tp_pre_open(clt->clt_tp, line));
+ return (tp_pre_open(tp, line));
}
/* citation block */
if (*line == '>') {
- if (clt_puts(clt, "<blockquote>") == -1 ||
+ if (tp_writes(tp, "<blockquote>") == -1 ||
tp_htmlescape(clt->clt_tp, line + 1) == -1 ||
- clt_puts(clt, "</blockquote>") == -1)
+ tp_writes(tp, "</blockquote>") == -1)
return (-1);
return (0);
}
/* headings */
if (!strncmp(line, "###", 3)) {
- if (clt_puts(clt, "<h3>") == -1 ||
+ if (tp_writes(tp, "<h3>") == -1 ||
tp_htmlescape(clt->clt_tp, line + 3) == -1 ||
- clt_puts(clt, "</h3>") == -1)
+ tp_writes(tp, "</h3>") == -1)
return (-1);
return (0);
}
if (!strncmp(line, "##", 2)) {
- if (clt_puts(clt, "<h2>") == -1 ||
+ if (tp_writes(tp, "<h2>") == -1 ||
tp_htmlescape(clt->clt_tp, line + 2) == -1 ||
- clt_puts(clt, "</h2>") == -1)
+ tp_writes(tp, "</h2>") == -1)
return (-1);
return (0);
}
if (!strncmp(line, "#", 1)) {
- if (clt_puts(clt, "<h1>") == -1 ||
+ if (tp_writes(tp, "<h1>") == -1 ||
tp_htmlescape(clt->clt_tp, line + 1) == -1 ||
- clt_puts(clt, "</h1>") == -1)
+ tp_writes(tp, "</h1>") == -1)
return (-1);
return (0);
}
return (0);
/* paragraph */
- if (clt_puts(clt, "<p>") == -1 ||
+ if (tp_writes(tp, "<p>") == -1 ||
tp_htmlescape(clt->clt_tp, line) == -1 ||
- clt_puts(clt, "</p>") == -1)
+ tp_writes(tp, "</p>") == -1)
return (-1);
return (0);
int
proxy_start_reply(struct client *clt, int status, const char *ctype)
{
+ struct template *tp = clt->clt_tp;
const char *csp;
csp = "Content-Security-Policy: default-src 'self'; "
"script-src 'none'; object-src 'none';\r\n";
if (status != 200 &&
- clt_printf(clt, "Status: %d\r\n", status) == -1)
+ tp_writef(tp, "Status: %d\r\n", status) == -1)
return (-1);
- if (clt_puts(clt, csp) == -1)
+ if (tp_writes(tp, csp) == -1)
return (-1);
if (status == 302) {
/* use "ctype" as redirect target */
- if (clt_printf(clt, "Location: %s\r\n", ctype) == -1)
+ if (tp_writef(tp, "Location: %s\r\n", ctype) == -1)
return (-1);
- if (clt_puts(clt, "\r\n") == -1)
+ if (tp_writes(tp, "\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)
+ if (tp_writef(tp, "Content-Type: %s\r\n", ctype)
== -1)
return (-1);
}
- if (clt_puts(clt, "\r\n") == -1)
+ if (tp_writes(tp, "\r\n") == -1)
return (-1);
return (0);
else
ctype = mime;
- if (clt_printf(clt, "Content-Type: %s\r\n\r\n", ctype) == -1)
+ if (tp_writef(clt->clt_tp, "Content-Type: %s\r\n\r\n", ctype) == -1)
goto err;
clt->clt_headersdone = 1;
proxy_error(struct bufferevent *bev, short err, void *d)
{
struct client *clt = d;
+ struct template *tp = clt->clt_tp;
int status = !(err & EVBUFFER_EOF);
log_debug("proxy error, shutting down the connection (err: %x)",
}
if (clt->clt_translate & TR_LIST) {
- if (clt_puts(clt, "</ul>") == -1)
+ if (tp_writes(tp, "</ul>") == -1)
return;
clt->clt_translate &= ~TR_LIST;
}
if (clt->clt_translate & TR_NAV) {
- if (clt_puts(clt, "</ul></nav>") == -1)
+ if (tp_writes(tp, "</ul></nav>") == -1)
return;
clt->clt_translate &= ~TR_NAV;
}
blob - c97478128fa19c9cddcf687a802db929cfa6bd36
blob + 59cf6888097e2e08fde77614c4ea7f9517e3f4ac
--- template/parse.y
+++ template/parse.y
raw : nstring {
dbg();
- fprintf(fp, "if ((tp_ret = tp->tp_puts(tp, ");
+ fprintf(fp, "if ((tp_ret = tp_write(tp, ");
printq($1);
- fputs(")) == -1) goto err;\n", fp);
+ fprintf(fp, ", %zu)) == -1) goto err;\n",
+ strlen($1));
free($1);
}
| '{' string '|' UNSAFE '}' {
dbg();
fprintf(fp,
- "if ((tp_ret = tp->tp_puts(tp, %s)) == -1)\n",
+ "if ((tp_ret = tp_writes(tp, %s)) == -1)\n",
$2);
fputs("goto err;\n", fp);
free($2);
| '{' string '}' {
dbg();
fprintf(fp,
- "if ((tp_ret = tp->tp_escape(tp, %s)) == -1)\n",
+ "if ((tp_ret = tp_htmlescape(tp, %s)) == -1)\n",
$2);
fputs("goto err;\n", fp);
free($2);
} printfargs '}' {
fputs(") == -1)\n", fp);
fputs("goto err;\n", fp);
- fputs("if ((tp_ret = tp->tp_escape(tp, tp->tp_tmp)) "
+ fputs("if ((tp_ret = tp_htmlescape(tp, tp->tp_tmp)) "
"== -1)\n", fp);
fputs("goto err;\n", fp);
fputs("free(tp->tp_tmp);\n", fp);
blob - 0d5556832752616b4191a8cf21835e45f65b16b4
blob + a26f893929de81045bf85ad76631aa136e7d86b3
--- template/regress/runbase.c
+++ template/regress/runbase.c
#include "tmpl.h"
int base(struct template *, const char *title);
+int my_write(void *, const void *, size_t);
int
-my_putc(struct template *tp, int c)
+my_write(void *arg, const void *s, size_t len)
{
- FILE *fp = tp->tp_arg;
+ FILE *fp = arg;
- if (putc(c, fp) < 0)
+ if (fwrite(s, 1, len, fp) < 0)
return (-1);
return (0);
}
int
-my_puts(struct template *tp, const char *s)
-{
- FILE *fp = tp->tp_arg;
-
- if (fputs(s, fp) < 0)
- return (-1);
-
- return (0);
-}
-
-int
main(int argc, char **argv)
{
- struct template *tp;
+ struct template *tp;
+ char buf[3];
+ /* use a ridiculously small buffer in regress */
- if ((tp = template(stdout, my_puts, my_putc)) == NULL)
+ if ((tp = template(stdout, my_write, buf, sizeof(buf))) == NULL)
err(1, "template");
- if (base(tp, " *hello* ") == -1)
+ if (base(tp, " *hello* ") == -1 ||
+ template_flush(tp) == -1)
return (1);
puts("");
- if (base(tp, "<hello>") == -1)
+ if (base(tp, "<hello>") == -1 ||
+ template_flush(tp) == -1)
return (1);
puts("");
blob - 70491763b5ea06841ec7b67897202e9bfb3c3223
blob + 648bcc07fa18e09307682160f77408c3d644530c
--- template/regress/runlist.c
+++ template/regress/runlist.c
#include "lists.h"
int base(struct template *, struct tailhead *);
+int my_write(void *, const void *, size_t);
int
-my_putc(struct template *tp, int c)
+my_write(void *arg, const void *s, size_t len)
{
- FILE *fp = tp->tp_arg;
+ FILE *fp = arg;
- if (putc(c, fp) < 0)
+ if (fwrite(s, 1, len, fp) < 0)
return (-1);
return (0);
}
int
-my_puts(struct template *tp, const char *s)
-{
- FILE *fp = tp->tp_arg;
-
- if (fputs(s, fp) < 0)
- return (-1);
-
- return (0);
-}
-
-int
main(int argc, char **argv)
{
struct template *tp;
struct tailhead head;
struct entry *np;
int i;
+ char buf[3];
+ /* use a ridiculously small buffer in regress */
- if ((tp = template(stdout, my_puts, my_putc)) == NULL)
+ if ((tp = template(stdout, my_write, buf, sizeof(buf))) == NULL)
err(1, "template");
TAILQ_INIT(&head);
TAILQ_INSERT_TAIL(&head, np, entries);
}
- if (base(tp, &head) == -1)
+ if (base(tp, &head) == -1 ||
+ template_flush(tp) == -1)
return (1);
puts("");
free(np);
}
- if (base(tp, &head) == -1)
+ if (base(tp, &head) == -1 ||
+ template_flush(tp) == -1)
return (1);
puts("");
blob - 18ee428516dc3b90ef925c5ac135e90278c0d5f9
blob + 5f1093f5488dc59cedb4551421207df0fb7e025d
--- template/tmpl.c
+++ template/tmpl.c
*/
#include <ctype.h>
+#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include "tmpl.h"
int
+tp_write(struct template *tp, const char *str, size_t len)
+{
+ size_t avail;
+
+ while (len > 0) {
+ avail = tp->tp_cap - tp->tp_len;
+ if (avail == 0) {
+ if (template_flush(tp) == -1)
+ return (-1);
+ avail = tp->tp_cap;
+ }
+
+ if (len < avail)
+ avail = len;
+
+ memcpy(tp->tp_buf + tp->tp_len, str, avail);
+ tp->tp_len += avail;
+ str += avail;
+ len -= avail;
+ }
+
+ return (0);
+}
+
+int
+tp_writes(struct template *tp, const char *str)
+{
+ return (tp_write(tp, str, strlen(str)));
+}
+
+int
+tp_writef(struct template *tp, const char *fmt, ...)
+{
+ va_list ap;
+ char *str;
+ int r;
+
+ va_start(ap, fmt);
+ r = vasprintf(&str, fmt, ap);
+ va_end(ap);
+ if (r == -1)
+ return (-1);
+ r = tp_write(tp, str, r);
+ free(str);
+ return (r);
+}
+
+int
tp_urlescape(struct template *tp, const char *str)
{
int r;
r = snprintf(tmp, sizeof(tmp), "%%%2X", *str);
if (r < 0 || (size_t)r >= sizeof(tmp))
return (0);
- if (tp->tp_puts(tp, tmp) == -1)
+ if (tp_write(tp, tmp, r) == -1)
return (-1);
} else {
- if (tp->tp_putc(tp, *str) == -1)
+ if (tp_write(tp, str, 1) == -1)
return (-1);
}
}
for (; *str; ++str) {
switch (*str) {
case '<':
- r = tp->tp_puts(tp, "<");
+ r = tp_write(tp, "<", 4);
break;
case '>':
- r = tp->tp_puts(tp, ">");
+ r = tp_write(tp, ">", 4);
break;
case '&':
- r = tp->tp_puts(tp, "&");
+ r = tp_write(tp, "&", 5);
break;
case '"':
- r = tp->tp_puts(tp, """);
+ r = tp_write(tp, """, 6);
break;
case '\'':
- r = tp->tp_puts(tp, "'");
+ r = tp_write(tp, "'", 6);
break;
default:
- r = tp->tp_putc(tp, *str);
+ r = tp_write(tp, str, 1);
break;
}
}
struct template *
-template(void *arg, tmpl_puts putsfn, tmpl_putc putcfn)
+template(void *arg, tmpl_write writefn, char *buf, size_t siz)
{
struct template *tp;
return (NULL);
tp->tp_arg = arg;
- tp->tp_escape = tp_htmlescape;
- tp->tp_puts = putsfn;
- tp->tp_putc = putcfn;
+ tp->tp_write = writefn;
+ tp->tp_buf = buf;
+ tp->tp_cap = siz;
return (tp);
}
+int
+template_flush(struct template *tp)
+{
+ if (tp->tp_len == 0)
+ return (0);
+
+ if (tp->tp_write(tp->tp_arg, tp->tp_buf, tp->tp_len) == -1)
+ return (-1);
+ tp->tp_len = 0;
+ return (0);
+}
+
void
template_free(struct template *tp)
{
blob - 4c8de903c9b7957de3c6bc1ed2058fa9a5db553b
blob + df3b74c2696e16f2a591fb656220ac7957c59a56
--- template/tmpl.h
+++ template/tmpl.h
struct template;
-typedef int (*tmpl_puts)(struct template *, const char *);
-typedef int (*tmpl_putc)(struct template *, int);
+typedef int (*tmpl_write)(void *, const void *, size_t);
struct template {
void *tp_arg;
char *tp_tmp;
- tmpl_puts tp_escape;
- tmpl_puts tp_puts;
- tmpl_putc tp_putc;
+ tmpl_write tp_write;
+ char *tp_buf;
+ size_t tp_len;
+ size_t tp_cap;
};
-int tp_urlescape(struct template *, const char *);
-int tp_htmlescape(struct template *, const char *);
+int tp_write(struct template *, const char *, size_t);
+int tp_writes(struct template *, const char *);
+int tp_writef(struct template *, const char *, ...)
+ __attribute__((__format__ (printf, 2, 3)));
+int tp_urlescape(struct template *, const char *);
+int tp_htmlescape(struct template *, const char *);
-struct template *template(void *, tmpl_puts, tmpl_putc);
+struct template *template(void *, tmpl_write, char *, size_t);
+int template_flush(struct template *);
void template_free(struct template *);
#endif