commit - 882ee74dcf6c73130b57c0db7b8013d02d26a95a
commit + d8bf4f258cbea84e319b0ed044224aaac37a085c
blob - fc9087208b069caaf128a3857cdb21b5a13fc4cf
blob + 3b66f82ce8ca320dfbef2bfe19db158e464eeb8c
--- gotwebd/fcgi.c
+++ gotwebd/fcgi.c
break;
case FCGI_STDIN:
case FCGI_ABORT_REQUEST:
- if (c->sock->client_status != CLIENT_DISCONNECT &&
- c->outbuf_len != 0) {
- fcgi_send_response(c, FCGI_STDOUT, c->outbuf,
- c->outbuf_len);
- }
-
fcgi_create_end_record(c);
fcgi_cleanup_request(c);
return 0;
if (n == 0) {
gotweb_process_request(c);
+ template_flush(c->tp);
return;
}
fcgi_timeout(int fd, short events, void *arg)
{
fcgi_cleanup_request((struct request*) arg);
-}
-
-int
-fcgi_puts(struct template *tp, const char *str)
-{
- if (str == NULL)
- return 0;
- return fcgi_gen_binary_response(tp->tp_arg, str, strlen(str));
}
-int
-fcgi_putc(struct template *tp, int ch)
-{
- uint8_t c = ch;
- return fcgi_gen_binary_response(tp->tp_arg, &c, 1);
-}
-
-int
-fcgi_vprintf(struct request *c, const char *fmt, va_list ap)
-{
- char *str;
- int r;
-
- r = vasprintf(&str, fmt, ap);
- if (r == -1) {
- log_warn("%s: asprintf", __func__);
- return -1;
- }
-
- r = fcgi_gen_binary_response(c, str, r);
- free(str);
- return r;
-}
-
-int
-fcgi_printf(struct request *c, const char *fmt, ...)
-{
- va_list ap;
- int r;
-
- va_start(ap, fmt);
- r = fcgi_vprintf(c, fmt, ap);
- va_end(ap);
-
- return r;
-}
-
-int
-fcgi_gen_binary_response(struct request *c, const uint8_t *data, int len)
-{
- int r;
-
- if (c->sock->client_status == CLIENT_DISCONNECT)
- return -1;
-
- if (data == NULL || len == 0)
- return 0;
-
- /*
- * special case: send big replies -like blobs- directly
- * without copying.
- */
- if (len > sizeof(c->outbuf)) {
- if (c->outbuf_len > 0) {
- fcgi_send_response(c, FCGI_STDOUT,
- c->outbuf, c->outbuf_len);
- c->outbuf_len = 0;
- }
- return fcgi_send_response(c, FCGI_STDOUT, data, len);
- }
-
- if (len < sizeof(c->outbuf) - c->outbuf_len) {
- memcpy(c->outbuf + c->outbuf_len, data, len);
- c->outbuf_len += len;
- return 0;
- }
-
- r = fcgi_send_response(c, FCGI_STDOUT, c->outbuf, c->outbuf_len);
- if (r == -1)
- return -1;
-
- memcpy(c->outbuf, data, len);
- c->outbuf_len = len;
- return 0;
-}
-
static int
send_response(struct request *c, int type, const uint8_t *data,
size_t len)
return send_response(c, type, data, len);
}
+int
+fcgi_write(void *arg, const void *buf, size_t len)
+{
+ struct request *c = arg;
+
+ return fcgi_send_response(c, FCGI_STDOUT, buf, len);
+}
+
void
fcgi_create_end_record(struct request *c)
{
blob - 96f09e96a245ef57f71cf92d5933096ef5eb9f32
blob + 17ccc57c2c33ce3bdbf92fe4b70615c83efa04e6
--- gotwebd/gotweb.c
+++ gotwebd/gotweb.c
{
const char *csp;
- if (status != 200 && fcgi_printf(c, "Status: %d\r\n", status) == -1)
+ if (status != 200 && tp_writef(c->tp, "Status: %d\r\n", status) == -1)
return -1;
if (location) {
- if (fcgi_puts(c->tp, "Location: ") == -1 ||
+ if (tp_writes(c->tp, "Location: ") == -1 ||
gotweb_render_url(c, location) == -1 ||
- fcgi_puts(c->tp, "\r\n") == -1)
+ tp_writes(c->tp, "\r\n") == -1)
return -1;
}
csp = "Content-Security-Policy: default-src 'self'; "
"script-src 'none'; object-src 'none';\r\n";
- if (fcgi_puts(c->tp, csp) == -1)
+ if (tp_writes(c->tp, csp) == -1)
return -1;
- if (ctype && fcgi_printf(c, "Content-Type: %s\r\n", ctype) == -1)
+ if (ctype && tp_writef(c->tp, "Content-Type: %s\r\n", ctype) == -1)
return -1;
- return fcgi_puts(c->tp, "\r\n");
+ return tp_writes(c->tp, "\r\n");
}
static int
{
int r;
- r = fcgi_printf(c, "Content-Disposition: attachment; "
+ r = tp_writef(c->tp, "Content-Disposition: attachment; "
"filename=%s%s\r\n", file, suffix ? suffix : "");
if (r == -1)
return -1;
else
r = gotweb_reply(c, 200, "text/plain", NULL);
if (r == -1)
+ return;
+ if (template_flush(c->tp) == -1)
return;
for (;;) {
if (len == 0)
break;
buf = got_object_blob_get_read_buf(c->t->blob);
- if (fcgi_gen_binary_response(c, buf, len) == -1)
+ if (fcgi_write(c, buf, len) == -1)
break;
}
return;
action = gotweb_action_name(url->action);
if (action != NULL) {
- if (fcgi_printf(c, "?action=%s", action) == -1)
+ if (tp_writef(c->tp, "?action=%s", action) == -1)
return -1;
sep = "&";
}
if (url->commit) {
- if (fcgi_printf(c, "%scommit=%s", sep, url->commit) == -1)
+ if (tp_writef(c->tp, "%scommit=%s", sep, url->commit) == -1)
return -1;
sep = "&";
}
if (url->previd) {
- if (fcgi_printf(c, "%sprevid=%s", sep, url->previd) == -1)
+ if (tp_writef(c->tp, "%sprevid=%s", sep, url->previd) == -1)
return -1;
sep = "&";
}
if (url->prevset) {
- if (fcgi_printf(c, "%sprevset=%s", sep, url->prevset) == -1)
+ if (tp_writef(c->tp, "%sprevset=%s", sep, url->prevset) == -1)
return -1;
sep = "&";
}
tmp = gotweb_urlencode(url->file);
if (tmp == NULL)
return -1;
- r = fcgi_printf(c, "%sfile=%s", sep, tmp);
+ r = tp_writef(c->tp, "%sfile=%s", sep, tmp);
free(tmp);
if (r == -1)
return -1;
tmp = gotweb_urlencode(url->folder);
if (tmp == NULL)
return -1;
- r = fcgi_printf(c, "%sfolder=%s", sep, tmp);
+ r = tp_writef(c->tp, "%sfolder=%s", sep, tmp);
free(tmp);
if (r == -1)
return -1;
tmp = gotweb_urlencode(url->headref);
if (tmp == NULL)
return -1;
- r = fcgi_printf(c, "%sheadref=%s", sep, url->headref);
+ r = tp_writef(c->tp, "%sheadref=%s", sep, url->headref);
free(tmp);
if (r == -1)
return -1;
}
if (url->index_page != -1) {
- if (fcgi_printf(c, "%sindex_page=%d", sep,
+ if (tp_writef(c->tp, "%sindex_page=%d", sep,
url->index_page) == -1)
return -1;
sep = "&";
tmp = gotweb_urlencode(url->path);
if (tmp == NULL)
return -1;
- r = fcgi_printf(c, "%spath=%s", sep, tmp);
+ r = tp_writef(c->tp, "%spath=%s", sep, tmp);
free(tmp);
if (r == -1)
return -1;
}
if (url->page != -1) {
- if (fcgi_printf(c, "%spage=%d", sep, url->page) == -1)
+ if (tp_writef(c->tp, "%spage=%d", sep, url->page) == -1)
return -1;
sep = "&";
}
struct template *tp = c->tp;
const char *proto = c->https ? "https" : "http";
- if (fcgi_puts(tp, proto) == -1 ||
- fcgi_puts(tp, "://") == -1 ||
+ if (tp_writes(tp, proto) == -1 ||
+ tp_writes(tp, "://") == -1 ||
tp_htmlescape(tp, c->server_name) == -1 ||
tp_htmlescape(tp, c->document_uri) == -1)
return -1;
case TM_DIFF:
diff_time = time(NULL) - committer_time;
if (diff_time > 60 * 60 * 24 * 365 * 2) {
- if (fcgi_printf(c, "%lld %s",
+ if (tp_writef(c->tp, "%lld %s",
(diff_time / 60 / 60 / 24 / 365), years) == -1)
return -1;
} else if (diff_time > 60 * 60 * 24 * (365 / 12) * 2) {
- if (fcgi_printf(c, "%lld %s",
+ if (tp_writef(c->tp, "%lld %s",
(diff_time / 60 / 60 / 24 / (365 / 12)),
months) == -1)
return -1;
} else if (diff_time > 60 * 60 * 24 * 7 * 2) {
- if (fcgi_printf(c, "%lld %s",
+ if (tp_writef(c->tp, "%lld %s",
(diff_time / 60 / 60 / 24 / 7), weeks) == -1)
return -1;
} else if (diff_time > 60 * 60 * 24 * 2) {
- if (fcgi_printf(c, "%lld %s",
+ if (tp_writef(c->tp, "%lld %s",
(diff_time / 60 / 60 / 24), days) == -1)
return -1;
} else if (diff_time > 60 * 60 * 2) {
- if (fcgi_printf(c, "%lld %s",
+ if (tp_writef(c->tp, "%lld %s",
(diff_time / 60 / 60), hours) == -1)
return -1;
} else if (diff_time > 60 * 2) {
- if (fcgi_printf(c, "%lld %s", (diff_time / 60),
+ if (tp_writef(c->tp, "%lld %s", (diff_time / 60),
minutes) == -1)
return -1;
} else if (diff_time > 2) {
- if (fcgi_printf(c, "%lld %s", diff_time,
+ if (tp_writef(c->tp, "%lld %s", diff_time,
seconds) == -1)
return -1;
} else {
- if (fcgi_puts(tp, now) == -1)
+ if (tp_writes(tp, now) == -1)
return -1;
}
break;
if (s == NULL)
return -1;
- if (fcgi_puts(tp, datebuf) == -1 ||
- fcgi_puts(tp, " UTC") == -1)
+ if (tp_writes(tp, datebuf) == -1 ||
+ tp_writes(tp, " UTC") == -1)
return -1;
break;
case TM_RFC822:
if (r == 0)
return -1;
- if (fcgi_puts(tp, datebuf) == -1)
+ if (tp_writes(tp, datebuf) == -1)
return -1;
break;
}
blob - b57b5c257cd8c89e9488fadc04f55c798b3a2c03
blob + 8e18e98aad26908b7294403e5baed1ce637e1368
--- gotwebd/gotwebd.h
+++ gotwebd/gotwebd.h
size_t buf_len;
uint8_t outbuf[GOTWEBD_CACHESIZE];
- size_t outbuf_len;
char querystring[MAX_QUERYSTRING];
char document_uri[MAX_DOCUMENT_URI];
void fcgi_cleanup_request(struct request *);
void fcgi_create_end_record(struct request *);
void dump_fcgi_record(const char *, struct fcgi_record_header *);
-int fcgi_puts(struct template *, const char *);
-int fcgi_putc(struct template *, int);
-int fcgi_vprintf(struct request *, const char *, va_list);
-int fcgi_printf(struct request *, const char *, ...)
- __attribute__((__format__(printf, 2, 3)))
- __attribute__((__nonnull__(2)));
-int fcgi_gen_binary_response(struct request *, const uint8_t *, int);
+int fcgi_write(void *, const void *, size_t);
/* got_operations.c */
const struct got_error *got_gotweb_closefile(FILE *);
blob - 1b80500f53fe828051e897701a7d5eef582c9b91
blob + 542f9d911ce6be7a94b6c10c2b004417ebaeaeea
--- gotwebd/sockets.c
+++ gotwebd/sockets.c
return;
}
- c->tp = template(c, fcgi_puts, fcgi_putc);
+ c->tp = template(c, &fcgi_write, c->outbuf, sizeof(c->outbuf));
if (c->tp == NULL) {
log_warn("%s", __func__);
close(s);
blob - 602717bcefc2fd65c0cb426c4d1fe263cdbaee7f
blob + a26f893929de81045bf85ad76631aa136e7d86b3
--- regress/template/runbase.c
+++ regress/template/runbase.c
#include "tmpl.h"
int base(struct template *, const char *title);
-int my_putc(struct template *, int);
-int my_puts(struct template *, const char *);
+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 - f6a415f000a087d0b1d41be0343b51916bebe9dd
blob + 648bcc07fa18e09307682160f77408c3d644530c
--- regress/template/runlist.c
+++ regress/template/runlist.c
#include "lists.h"
int base(struct template *, struct tailhead *);
-int my_putc(struct template *, int);
-int my_puts(struct template *, const char *);
+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 - 4aee74ee52af6f9230f3ed9bf0e1446d58e75dd8
blob + 50ecf8a1b74fb9d9826806c63507c927372c7c21
--- 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 - 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