From 43e70f351f013f3d8b38513fd0cc8af194fcefe2 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Fri, 23 Feb 2018 00:57:03 +0100 Subject: [PATCH] gluon-web: handle translation and escaping in generated Lua code By emitting Lua code to call translate() and pcdata(), we are more flexible than when doing this internally in the parser. The performance penalty should be negligible. --- package/gluon-web/src/template_parser.c | 57 +++++++++++++++---------- package/gluon-web/src/template_utils.c | 52 +--------------------- package/gluon-web/src/template_utils.h | 4 +- 3 files changed, 37 insertions(+), 76 deletions(-) diff --git a/package/gluon-web/src/template_parser.c b/package/gluon-web/src/template_parser.c index b69a99b3..3ba45488 100644 --- a/package/gluon-web/src/template_parser.c +++ b/package/gluon-web/src/template_parser.c @@ -72,15 +72,15 @@ struct template_parser { /* leading and trailing code for different types */ static const char *const gen_code[][2] = { - [T_TYPE_INIT] = {NULL, NULL}, - [T_TYPE_TEXT] = {"write('", "')"}, - [T_TYPE_COMMENT] = {NULL, NULL}, - [T_TYPE_EXPR] = {"write(tostring(", " or ''))"}, - [T_TYPE_INCLUDE] = {"include('", "')"}, - [T_TYPE_I18N] = {"write('", "')"}, - [T_TYPE_I18N_RAW] = {"write('", "')"}, - [T_TYPE_CODE] = {NULL, " "}, - [T_TYPE_EOF] = {NULL, NULL}, + [T_TYPE_INIT] = {NULL, NULL}, + [T_TYPE_TEXT] = {"write('", "')"}, + [T_TYPE_COMMENT] = {NULL, NULL}, + [T_TYPE_EXPR] = {"write(tostring(", " or ''))"}, + [T_TYPE_INCLUDE] = {"include('", "')"}, + [T_TYPE_I18N] = {"write(pcdata(translate('", "')))"}, + [T_TYPE_I18N_RAW] = {"write(translate('", "'))"}, + [T_TYPE_CODE] = {NULL, " "}, + [T_TYPE_EOF] = {NULL, NULL}, }; static struct template_parser * template_init(struct template_parser *parser) @@ -241,6 +241,28 @@ static void template_code(struct template_parser *parser, const char *e) parser->cur_chunk.e = e; } +static void luastr_escape(struct template_buffer *out, const char *s, const char *e) +{ + for (const char *ptr = s; ptr < e; ptr++) { + switch (*ptr) { + case '\\': + buf_append(out, "\\\\", 2); + break; + + case '\'': + buf_append(out, "\\\'", 2); + break; + + case '\n': + buf_append(out, "\\n", 2); + break; + + default: + buf_putchar(out, *ptr); + } + } +} + static struct template_buffer * template_format_chunk(struct template_parser *parser) { const char *p; @@ -266,7 +288,10 @@ static struct template_buffer * template_format_chunk(struct template_parser *pa switch (c->type) { case T_TYPE_TEXT: - luastr_escape(buf, c->s, c->e - c->s, false); + case T_TYPE_INCLUDE: + case T_TYPE_I18N: + case T_TYPE_I18N_RAW: + luastr_escape(buf, c->s, c->e); break; case T_TYPE_EXPR: @@ -275,18 +300,6 @@ static struct template_buffer * template_format_chunk(struct template_parser *pa parser->line += (*p == '\n'); break; - case T_TYPE_INCLUDE: - luastr_escape(buf, c->s, c->e - c->s, false); - break; - - case T_TYPE_I18N: - luastr_translate(buf, c->s, c->e - c->s, true); - break; - - case T_TYPE_I18N_RAW: - luastr_translate(buf, c->s, c->e - c->s, false); - break; - case T_TYPE_CODE: buf_append(buf, c->s, c->e - c->s); for (p = c->s; p < c->e; p++) diff --git a/package/gluon-web/src/template_utils.c b/package/gluon-web/src/template_utils.c index 7bd0f709..8a4cecfe 100644 --- a/package/gluon-web/src/template_utils.c +++ b/package/gluon-web/src/template_utils.c @@ -66,7 +66,7 @@ static bool buf_grow(struct template_buffer *buf, size_t len) } /* put one char into buffer object */ -static bool buf_putchar(struct template_buffer *buf, char c) +bool buf_putchar(struct template_buffer *buf, char c) { if (!buf_grow(buf, 1)) return false; @@ -311,53 +311,3 @@ char * pcdata(const char *s, size_t l, size_t *outl) *outl = buf_length(buf); return buf_destroy(buf); } - -void luastr_escape(struct template_buffer *out, const char *s, size_t l, bool escape_xml) -{ - int esl; - char esq[8]; - const char *ptr; - - for (ptr = s; ptr < (s + l); ptr++) { - switch (*ptr) { - case '\\': - buf_append(out, "\\\\", 2); - break; - - case '\'': - if (escape_xml) - buf_append(out, "'", 5); - else - buf_append(out, "\\\'", 2); - break; - - case '\n': - buf_append(out, "\\n", 2); - break; - - case '"': - case '&': - case '<': - case '>': - if (escape_xml) { - esl = snprintf(esq, sizeof(esq), "&#%i;", *ptr); - buf_append(out, esq, esl); - break; - } - - default: - buf_putchar(out, *ptr); - } - } -} - -void luastr_translate(struct template_buffer *out, const char *s, size_t l, bool escape_xml) -{ - char *tr; - size_t trlen; - - if (lmo_translate(s, l, &tr, &trlen)) - luastr_escape(out, tr, trlen, escape_xml); - else - luastr_escape(out, s, l, escape_xml); -} diff --git a/package/gluon-web/src/template_utils.h b/package/gluon-web/src/template_utils.h index a094d344..5708bfd3 100644 --- a/package/gluon-web/src/template_utils.h +++ b/package/gluon-web/src/template_utils.h @@ -32,6 +32,7 @@ struct template_buffer { }; struct template_buffer * buf_init(size_t size); +bool buf_putchar(struct template_buffer *buf, char c); bool buf_append(struct template_buffer *buf, const char *s, size_t len); char * buf_destroy(struct template_buffer *buf); @@ -44,7 +45,4 @@ static inline size_t buf_length(struct template_buffer *buf) char * pcdata(const char *s, size_t l, size_t *outl); -void luastr_escape(struct template_buffer *out, const char *s, size_t l, bool escape_xml); -void luastr_translate(struct template_buffer *out, const char *s, size_t l, bool escape_xml); - #endif