2 96b8c570 2022-12-30 thomas * Copyright (c) 2022 Omar Polo <op@openbsd.org>
4 6509b181 2022-12-30 thomas * Permission to use, copy, modify, and distribute this software for any
5 6509b181 2022-12-30 thomas * purpose with or without fee is hereby granted, provided that the above
6 6509b181 2022-12-30 thomas * copyright notice and this permission notice appear in all copies.
8 6509b181 2022-12-30 thomas * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 6509b181 2022-12-30 thomas * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 6509b181 2022-12-30 thomas * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 6509b181 2022-12-30 thomas * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 6509b181 2022-12-30 thomas * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 6509b181 2022-12-30 thomas * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 6509b181 2022-12-30 thomas * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 6509b181 2022-12-30 thomas #include <ctype.h>
18 d8bf4f25 2023-09-14 thomas #include <stdarg.h>
19 6509b181 2022-12-30 thomas #include <stdio.h>
20 6509b181 2022-12-30 thomas #include <stdlib.h>
21 d8bf4f25 2023-09-14 thomas #include <string.h>
23 6509b181 2022-12-30 thomas #include "tmpl.h"
26 d8bf4f25 2023-09-14 thomas tp_write(struct template *tp, const char *str, size_t len)
28 d8bf4f25 2023-09-14 thomas size_t avail;
30 d8bf4f25 2023-09-14 thomas while (len > 0) {
31 d8bf4f25 2023-09-14 thomas avail = tp->tp_cap - tp->tp_len;
32 d8bf4f25 2023-09-14 thomas if (avail == 0) {
33 d8bf4f25 2023-09-14 thomas if (template_flush(tp) == -1)
34 d8bf4f25 2023-09-14 thomas return (-1);
35 d8bf4f25 2023-09-14 thomas avail = tp->tp_cap;
38 d8bf4f25 2023-09-14 thomas if (len < avail)
39 d8bf4f25 2023-09-14 thomas avail = len;
41 d8bf4f25 2023-09-14 thomas memcpy(tp->tp_buf + tp->tp_len, str, avail);
42 d8bf4f25 2023-09-14 thomas tp->tp_len += avail;
43 d8bf4f25 2023-09-14 thomas str += avail;
44 d8bf4f25 2023-09-14 thomas len -= avail;
47 d8bf4f25 2023-09-14 thomas return (0);
51 d8bf4f25 2023-09-14 thomas tp_writes(struct template *tp, const char *str)
53 d8bf4f25 2023-09-14 thomas return (tp_write(tp, str, strlen(str)));
57 d8bf4f25 2023-09-14 thomas tp_writef(struct template *tp, const char *fmt, ...)
59 d8bf4f25 2023-09-14 thomas va_list ap;
60 d8bf4f25 2023-09-14 thomas char *str;
63 d8bf4f25 2023-09-14 thomas va_start(ap, fmt);
64 d8bf4f25 2023-09-14 thomas r = vasprintf(&str, fmt, ap);
65 d8bf4f25 2023-09-14 thomas va_end(ap);
66 d8bf4f25 2023-09-14 thomas if (r == -1)
67 d8bf4f25 2023-09-14 thomas return (-1);
68 d8bf4f25 2023-09-14 thomas r = tp_write(tp, str, r);
69 d8bf4f25 2023-09-14 thomas free(str);
70 d8bf4f25 2023-09-14 thomas return (r);
74 6509b181 2022-12-30 thomas tp_urlescape(struct template *tp, const char *str)
77 6509b181 2022-12-30 thomas char tmp[4];
79 6509b181 2022-12-30 thomas if (str == NULL)
80 6509b181 2022-12-30 thomas return (0);
82 6509b181 2022-12-30 thomas for (; *str; ++str) {
83 6509b181 2022-12-30 thomas if (iscntrl((unsigned char)*str) ||
84 6509b181 2022-12-30 thomas isspace((unsigned char)*str) ||
85 6509b181 2022-12-30 thomas *str == '\'' || *str == '"' || *str == '\\') {
86 6509b181 2022-12-30 thomas r = snprintf(tmp, sizeof(tmp), "%%%2X", *str);
87 6509b181 2022-12-30 thomas if (r < 0 || (size_t)r >= sizeof(tmp))
88 6509b181 2022-12-30 thomas return (0);
89 d8bf4f25 2023-09-14 thomas if (tp_write(tp, tmp, r) == -1)
90 6509b181 2022-12-30 thomas return (-1);
92 d8bf4f25 2023-09-14 thomas if (tp_write(tp, str, 1) == -1)
93 6509b181 2022-12-30 thomas return (-1);
97 6509b181 2022-12-30 thomas return (0);
101 6509b181 2022-12-30 thomas tp_htmlescape(struct template *tp, const char *str)
105 6509b181 2022-12-30 thomas if (str == NULL)
106 6509b181 2022-12-30 thomas return (0);
108 6509b181 2022-12-30 thomas for (; *str; ++str) {
109 6509b181 2022-12-30 thomas switch (*str) {
110 6509b181 2022-12-30 thomas case '<':
111 d8bf4f25 2023-09-14 thomas r = tp_write(tp, "<", 4);
113 6509b181 2022-12-30 thomas case '>':
114 d8bf4f25 2023-09-14 thomas r = tp_write(tp, ">", 4);
116 6509b181 2022-12-30 thomas case '&':
117 d8bf4f25 2023-09-14 thomas r = tp_write(tp, "&", 5);
119 6509b181 2022-12-30 thomas case '"':
120 d8bf4f25 2023-09-14 thomas r = tp_write(tp, """, 6);
122 6509b181 2022-12-30 thomas case '\'':
123 d8bf4f25 2023-09-14 thomas r = tp_write(tp, "'", 6);
126 d8bf4f25 2023-09-14 thomas r = tp_write(tp, str, 1);
130 6509b181 2022-12-30 thomas if (r == -1)
131 6509b181 2022-12-30 thomas return (-1);
134 6509b181 2022-12-30 thomas return (0);
137 6509b181 2022-12-30 thomas struct template *
138 d8bf4f25 2023-09-14 thomas template(void *arg, tmpl_write writefn, char *buf, size_t siz)
140 6509b181 2022-12-30 thomas struct template *tp;
142 6509b181 2022-12-30 thomas if ((tp = calloc(1, sizeof(*tp))) == NULL)
143 6509b181 2022-12-30 thomas return (NULL);
145 6509b181 2022-12-30 thomas tp->tp_arg = arg;
146 d8bf4f25 2023-09-14 thomas tp->tp_write = writefn;
147 d8bf4f25 2023-09-14 thomas tp->tp_buf = buf;
148 d8bf4f25 2023-09-14 thomas tp->tp_cap = siz;
150 6509b181 2022-12-30 thomas return (tp);
154 d8bf4f25 2023-09-14 thomas template_flush(struct template *tp)
156 d8bf4f25 2023-09-14 thomas if (tp->tp_len == 0)
157 d8bf4f25 2023-09-14 thomas return (0);
159 d8bf4f25 2023-09-14 thomas if (tp->tp_write(tp->tp_arg, tp->tp_buf, tp->tp_len) == -1)
160 d8bf4f25 2023-09-14 thomas return (-1);
161 d8bf4f25 2023-09-14 thomas tp->tp_len = 0;
162 d8bf4f25 2023-09-14 thomas return (0);
166 6509b181 2022-12-30 thomas template_free(struct template *tp)
168 6509b181 2022-12-30 thomas free(tp->tp_tmp);
169 6509b181 2022-12-30 thomas free(tp);