Blame


1 6509b181 2022-12-30 thomas /*
2 96b8c570 2022-12-30 thomas * Copyright (c) 2022 Omar Polo <op@openbsd.org>
3 6509b181 2022-12-30 thomas *
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.
7 6509b181 2022-12-30 thomas *
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.
15 6509b181 2022-12-30 thomas */
16 6509b181 2022-12-30 thomas
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>
22 6509b181 2022-12-30 thomas
23 efc1d990 2023-11-25 thomas #include "got_compat.h"
24 6509b181 2022-12-30 thomas #include "tmpl.h"
25 6509b181 2022-12-30 thomas
26 6509b181 2022-12-30 thomas int
27 d8bf4f25 2023-09-14 thomas tp_write(struct template *tp, const char *str, size_t len)
28 d8bf4f25 2023-09-14 thomas {
29 d8bf4f25 2023-09-14 thomas size_t avail;
30 d8bf4f25 2023-09-14 thomas
31 d8bf4f25 2023-09-14 thomas while (len > 0) {
32 d8bf4f25 2023-09-14 thomas avail = tp->tp_cap - tp->tp_len;
33 d8bf4f25 2023-09-14 thomas if (avail == 0) {
34 d8bf4f25 2023-09-14 thomas if (template_flush(tp) == -1)
35 d8bf4f25 2023-09-14 thomas return (-1);
36 d8bf4f25 2023-09-14 thomas avail = tp->tp_cap;
37 d8bf4f25 2023-09-14 thomas }
38 d8bf4f25 2023-09-14 thomas
39 d8bf4f25 2023-09-14 thomas if (len < avail)
40 d8bf4f25 2023-09-14 thomas avail = len;
41 d8bf4f25 2023-09-14 thomas
42 d8bf4f25 2023-09-14 thomas memcpy(tp->tp_buf + tp->tp_len, str, avail);
43 d8bf4f25 2023-09-14 thomas tp->tp_len += avail;
44 d8bf4f25 2023-09-14 thomas str += avail;
45 d8bf4f25 2023-09-14 thomas len -= avail;
46 d8bf4f25 2023-09-14 thomas }
47 d8bf4f25 2023-09-14 thomas
48 d8bf4f25 2023-09-14 thomas return (0);
49 d8bf4f25 2023-09-14 thomas }
50 d8bf4f25 2023-09-14 thomas
51 d8bf4f25 2023-09-14 thomas int
52 d8bf4f25 2023-09-14 thomas tp_writes(struct template *tp, const char *str)
53 d8bf4f25 2023-09-14 thomas {
54 d8bf4f25 2023-09-14 thomas return (tp_write(tp, str, strlen(str)));
55 d8bf4f25 2023-09-14 thomas }
56 d8bf4f25 2023-09-14 thomas
57 d8bf4f25 2023-09-14 thomas int
58 d8bf4f25 2023-09-14 thomas tp_writef(struct template *tp, const char *fmt, ...)
59 d8bf4f25 2023-09-14 thomas {
60 d8bf4f25 2023-09-14 thomas va_list ap;
61 d8bf4f25 2023-09-14 thomas char *str;
62 d8bf4f25 2023-09-14 thomas int r;
63 d8bf4f25 2023-09-14 thomas
64 d8bf4f25 2023-09-14 thomas va_start(ap, fmt);
65 d8bf4f25 2023-09-14 thomas r = vasprintf(&str, fmt, ap);
66 d8bf4f25 2023-09-14 thomas va_end(ap);
67 d8bf4f25 2023-09-14 thomas if (r == -1)
68 d8bf4f25 2023-09-14 thomas return (-1);
69 d8bf4f25 2023-09-14 thomas r = tp_write(tp, str, r);
70 d8bf4f25 2023-09-14 thomas free(str);
71 d8bf4f25 2023-09-14 thomas return (r);
72 d8bf4f25 2023-09-14 thomas }
73 d8bf4f25 2023-09-14 thomas
74 d8bf4f25 2023-09-14 thomas int
75 6509b181 2022-12-30 thomas tp_urlescape(struct template *tp, const char *str)
76 6509b181 2022-12-30 thomas {
77 6509b181 2022-12-30 thomas int r;
78 6509b181 2022-12-30 thomas char tmp[4];
79 6509b181 2022-12-30 thomas
80 6509b181 2022-12-30 thomas if (str == NULL)
81 6509b181 2022-12-30 thomas return (0);
82 6509b181 2022-12-30 thomas
83 6509b181 2022-12-30 thomas for (; *str; ++str) {
84 6509b181 2022-12-30 thomas if (iscntrl((unsigned char)*str) ||
85 6509b181 2022-12-30 thomas isspace((unsigned char)*str) ||
86 6509b181 2022-12-30 thomas *str == '\'' || *str == '"' || *str == '\\') {
87 6509b181 2022-12-30 thomas r = snprintf(tmp, sizeof(tmp), "%%%2X", *str);
88 6509b181 2022-12-30 thomas if (r < 0 || (size_t)r >= sizeof(tmp))
89 6509b181 2022-12-30 thomas return (0);
90 d8bf4f25 2023-09-14 thomas if (tp_write(tp, tmp, r) == -1)
91 6509b181 2022-12-30 thomas return (-1);
92 6509b181 2022-12-30 thomas } else {
93 d8bf4f25 2023-09-14 thomas if (tp_write(tp, str, 1) == -1)
94 6509b181 2022-12-30 thomas return (-1);
95 6509b181 2022-12-30 thomas }
96 6509b181 2022-12-30 thomas }
97 6509b181 2022-12-30 thomas
98 6509b181 2022-12-30 thomas return (0);
99 6509b181 2022-12-30 thomas }
100 6509b181 2022-12-30 thomas
101 e6c0de4d 2023-12-08 thomas static inline int
102 e6c0de4d 2023-12-08 thomas htmlescape(struct template *tp, char c)
103 e6c0de4d 2023-12-08 thomas {
104 e6c0de4d 2023-12-08 thomas switch (c) {
105 e6c0de4d 2023-12-08 thomas case '<':
106 e6c0de4d 2023-12-08 thomas return tp_write(tp, "&lt;", 4);
107 e6c0de4d 2023-12-08 thomas case '>':
108 e6c0de4d 2023-12-08 thomas return tp_write(tp, "&gt;", 4);
109 e6c0de4d 2023-12-08 thomas case '&':
110 e6c0de4d 2023-12-08 thomas return tp_write(tp, "&amp;", 5);
111 e6c0de4d 2023-12-08 thomas case '"':
112 e6c0de4d 2023-12-08 thomas return tp_write(tp, "&quot;", 6);
113 e6c0de4d 2023-12-08 thomas case '\'':
114 e6c0de4d 2023-12-08 thomas return tp_write(tp, "&apos;", 6);
115 e6c0de4d 2023-12-08 thomas default:
116 e6c0de4d 2023-12-08 thomas return tp_write(tp, &c, 1);
117 e6c0de4d 2023-12-08 thomas }
118 e6c0de4d 2023-12-08 thomas }
119 e6c0de4d 2023-12-08 thomas
120 6509b181 2022-12-30 thomas int
121 6509b181 2022-12-30 thomas tp_htmlescape(struct template *tp, const char *str)
122 6509b181 2022-12-30 thomas {
123 6509b181 2022-12-30 thomas if (str == NULL)
124 6509b181 2022-12-30 thomas return (0);
125 6509b181 2022-12-30 thomas
126 6509b181 2022-12-30 thomas for (; *str; ++str) {
127 e6c0de4d 2023-12-08 thomas if (htmlescape(tp, *str) == -1)
128 e6c0de4d 2023-12-08 thomas return (-1);
129 e6c0de4d 2023-12-08 thomas }
130 6509b181 2022-12-30 thomas
131 e6c0de4d 2023-12-08 thomas return (0);
132 e6c0de4d 2023-12-08 thomas }
133 e6c0de4d 2023-12-08 thomas
134 e6c0de4d 2023-12-08 thomas int
135 e6c0de4d 2023-12-08 thomas tp_write_htmlescape(struct template *tp, const char *str, size_t len)
136 e6c0de4d 2023-12-08 thomas {
137 e6c0de4d 2023-12-08 thomas size_t i;
138 e6c0de4d 2023-12-08 thomas
139 e6c0de4d 2023-12-08 thomas for (i = 0; i < len; ++i) {
140 e6c0de4d 2023-12-08 thomas if (htmlescape(tp, str[i]) == -1)
141 6509b181 2022-12-30 thomas return (-1);
142 6509b181 2022-12-30 thomas }
143 6509b181 2022-12-30 thomas
144 6509b181 2022-12-30 thomas return (0);
145 6509b181 2022-12-30 thomas }
146 6509b181 2022-12-30 thomas
147 6509b181 2022-12-30 thomas struct template *
148 d8bf4f25 2023-09-14 thomas template(void *arg, tmpl_write writefn, char *buf, size_t siz)
149 6509b181 2022-12-30 thomas {
150 6509b181 2022-12-30 thomas struct template *tp;
151 6509b181 2022-12-30 thomas
152 6509b181 2022-12-30 thomas if ((tp = calloc(1, sizeof(*tp))) == NULL)
153 6509b181 2022-12-30 thomas return (NULL);
154 6509b181 2022-12-30 thomas
155 6509b181 2022-12-30 thomas tp->tp_arg = arg;
156 d8bf4f25 2023-09-14 thomas tp->tp_write = writefn;
157 d8bf4f25 2023-09-14 thomas tp->tp_buf = buf;
158 d8bf4f25 2023-09-14 thomas tp->tp_cap = siz;
159 6509b181 2022-12-30 thomas
160 6509b181 2022-12-30 thomas return (tp);
161 6509b181 2022-12-30 thomas }
162 6509b181 2022-12-30 thomas
163 d8bf4f25 2023-09-14 thomas int
164 d8bf4f25 2023-09-14 thomas template_flush(struct template *tp)
165 d8bf4f25 2023-09-14 thomas {
166 d8bf4f25 2023-09-14 thomas if (tp->tp_len == 0)
167 d8bf4f25 2023-09-14 thomas return (0);
168 d8bf4f25 2023-09-14 thomas
169 d8bf4f25 2023-09-14 thomas if (tp->tp_write(tp->tp_arg, tp->tp_buf, tp->tp_len) == -1)
170 d8bf4f25 2023-09-14 thomas return (-1);
171 d8bf4f25 2023-09-14 thomas tp->tp_len = 0;
172 d8bf4f25 2023-09-14 thomas return (0);
173 d8bf4f25 2023-09-14 thomas }
174 d8bf4f25 2023-09-14 thomas
175 6509b181 2022-12-30 thomas void
176 6509b181 2022-12-30 thomas template_free(struct template *tp)
177 6509b181 2022-12-30 thomas {
178 6509b181 2022-12-30 thomas free(tp->tp_tmp);
179 6509b181 2022-12-30 thomas free(tp);
180 6509b181 2022-12-30 thomas }