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 6509b181 2022-12-30 thomas #include "tmpl.h"
24 6509b181 2022-12-30 thomas
25 6509b181 2022-12-30 thomas int
26 d8bf4f25 2023-09-14 thomas tp_write(struct template *tp, const char *str, size_t len)
27 d8bf4f25 2023-09-14 thomas {
28 d8bf4f25 2023-09-14 thomas size_t avail;
29 d8bf4f25 2023-09-14 thomas
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;
36 d8bf4f25 2023-09-14 thomas }
37 d8bf4f25 2023-09-14 thomas
38 d8bf4f25 2023-09-14 thomas if (len < avail)
39 d8bf4f25 2023-09-14 thomas avail = len;
40 d8bf4f25 2023-09-14 thomas
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;
45 d8bf4f25 2023-09-14 thomas }
46 d8bf4f25 2023-09-14 thomas
47 d8bf4f25 2023-09-14 thomas return (0);
48 d8bf4f25 2023-09-14 thomas }
49 d8bf4f25 2023-09-14 thomas
50 d8bf4f25 2023-09-14 thomas int
51 d8bf4f25 2023-09-14 thomas tp_writes(struct template *tp, const char *str)
52 d8bf4f25 2023-09-14 thomas {
53 d8bf4f25 2023-09-14 thomas return (tp_write(tp, str, strlen(str)));
54 d8bf4f25 2023-09-14 thomas }
55 d8bf4f25 2023-09-14 thomas
56 d8bf4f25 2023-09-14 thomas int
57 d8bf4f25 2023-09-14 thomas tp_writef(struct template *tp, const char *fmt, ...)
58 d8bf4f25 2023-09-14 thomas {
59 d8bf4f25 2023-09-14 thomas va_list ap;
60 d8bf4f25 2023-09-14 thomas char *str;
61 d8bf4f25 2023-09-14 thomas int r;
62 d8bf4f25 2023-09-14 thomas
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);
71 d8bf4f25 2023-09-14 thomas }
72 d8bf4f25 2023-09-14 thomas
73 d8bf4f25 2023-09-14 thomas int
74 6509b181 2022-12-30 thomas tp_urlescape(struct template *tp, const char *str)
75 6509b181 2022-12-30 thomas {
76 6509b181 2022-12-30 thomas int r;
77 6509b181 2022-12-30 thomas char tmp[4];
78 6509b181 2022-12-30 thomas
79 6509b181 2022-12-30 thomas if (str == NULL)
80 6509b181 2022-12-30 thomas return (0);
81 6509b181 2022-12-30 thomas
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);
91 6509b181 2022-12-30 thomas } else {
92 d8bf4f25 2023-09-14 thomas if (tp_write(tp, str, 1) == -1)
93 6509b181 2022-12-30 thomas return (-1);
94 6509b181 2022-12-30 thomas }
95 6509b181 2022-12-30 thomas }
96 6509b181 2022-12-30 thomas
97 6509b181 2022-12-30 thomas return (0);
98 6509b181 2022-12-30 thomas }
99 6509b181 2022-12-30 thomas
100 6509b181 2022-12-30 thomas int
101 6509b181 2022-12-30 thomas tp_htmlescape(struct template *tp, const char *str)
102 6509b181 2022-12-30 thomas {
103 6509b181 2022-12-30 thomas int r;
104 6509b181 2022-12-30 thomas
105 6509b181 2022-12-30 thomas if (str == NULL)
106 6509b181 2022-12-30 thomas return (0);
107 6509b181 2022-12-30 thomas
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, "&lt;", 4);
112 6509b181 2022-12-30 thomas break;
113 6509b181 2022-12-30 thomas case '>':
114 d8bf4f25 2023-09-14 thomas r = tp_write(tp, "&gt;", 4);
115 6509b181 2022-12-30 thomas break;
116 6509b181 2022-12-30 thomas case '&':
117 d8bf4f25 2023-09-14 thomas r = tp_write(tp, "&amp;", 5);
118 6509b181 2022-12-30 thomas break;
119 6509b181 2022-12-30 thomas case '"':
120 d8bf4f25 2023-09-14 thomas r = tp_write(tp, "&quot;", 6);
121 6509b181 2022-12-30 thomas break;
122 6509b181 2022-12-30 thomas case '\'':
123 d8bf4f25 2023-09-14 thomas r = tp_write(tp, "&apos;", 6);
124 6509b181 2022-12-30 thomas break;
125 6509b181 2022-12-30 thomas default:
126 d8bf4f25 2023-09-14 thomas r = tp_write(tp, str, 1);
127 6509b181 2022-12-30 thomas break;
128 6509b181 2022-12-30 thomas }
129 6509b181 2022-12-30 thomas
130 6509b181 2022-12-30 thomas if (r == -1)
131 6509b181 2022-12-30 thomas return (-1);
132 6509b181 2022-12-30 thomas }
133 6509b181 2022-12-30 thomas
134 6509b181 2022-12-30 thomas return (0);
135 6509b181 2022-12-30 thomas }
136 6509b181 2022-12-30 thomas
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)
139 6509b181 2022-12-30 thomas {
140 6509b181 2022-12-30 thomas struct template *tp;
141 6509b181 2022-12-30 thomas
142 6509b181 2022-12-30 thomas if ((tp = calloc(1, sizeof(*tp))) == NULL)
143 6509b181 2022-12-30 thomas return (NULL);
144 6509b181 2022-12-30 thomas
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;
149 6509b181 2022-12-30 thomas
150 6509b181 2022-12-30 thomas return (tp);
151 6509b181 2022-12-30 thomas }
152 6509b181 2022-12-30 thomas
153 d8bf4f25 2023-09-14 thomas int
154 d8bf4f25 2023-09-14 thomas template_flush(struct template *tp)
155 d8bf4f25 2023-09-14 thomas {
156 d8bf4f25 2023-09-14 thomas if (tp->tp_len == 0)
157 d8bf4f25 2023-09-14 thomas return (0);
158 d8bf4f25 2023-09-14 thomas
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);
163 d8bf4f25 2023-09-14 thomas }
164 d8bf4f25 2023-09-14 thomas
165 6509b181 2022-12-30 thomas void
166 6509b181 2022-12-30 thomas template_free(struct template *tp)
167 6509b181 2022-12-30 thomas {
168 6509b181 2022-12-30 thomas free(tp->tp_tmp);
169 6509b181 2022-12-30 thomas free(tp);
170 6509b181 2022-12-30 thomas }