Blob


1 /*
2 * Copyright (c) 2022 Omar Polo <op@openbsd.org>
3 *
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
17 #include <ctype.h>
18 #include <stdarg.h>
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
23 #include "got_compat.h"
24 #include "tmpl.h"
26 int
27 tp_write(struct template *tp, const char *str, size_t len)
28 {
29 size_t avail;
31 while (len > 0) {
32 avail = tp->tp_cap - tp->tp_len;
33 if (avail == 0) {
34 if (template_flush(tp) == -1)
35 return (-1);
36 avail = tp->tp_cap;
37 }
39 if (len < avail)
40 avail = len;
42 memcpy(tp->tp_buf + tp->tp_len, str, avail);
43 tp->tp_len += avail;
44 str += avail;
45 len -= avail;
46 }
48 return (0);
49 }
51 int
52 tp_writes(struct template *tp, const char *str)
53 {
54 return (tp_write(tp, str, strlen(str)));
55 }
57 int
58 tp_writef(struct template *tp, const char *fmt, ...)
59 {
60 va_list ap;
61 char *str;
62 int r;
64 va_start(ap, fmt);
65 r = vasprintf(&str, fmt, ap);
66 va_end(ap);
67 if (r == -1)
68 return (-1);
69 r = tp_write(tp, str, r);
70 free(str);
71 return (r);
72 }
74 int
75 tp_urlescape(struct template *tp, const char *str)
76 {
77 int r;
78 char tmp[4];
80 if (str == NULL)
81 return (0);
83 for (; *str; ++str) {
84 if (iscntrl((unsigned char)*str) ||
85 isspace((unsigned char)*str) ||
86 *str == '\'' || *str == '"' || *str == '\\') {
87 r = snprintf(tmp, sizeof(tmp), "%%%2X", *str);
88 if (r < 0 || (size_t)r >= sizeof(tmp))
89 return (0);
90 if (tp_write(tp, tmp, r) == -1)
91 return (-1);
92 } else {
93 if (tp_write(tp, str, 1) == -1)
94 return (-1);
95 }
96 }
98 return (0);
99 }
101 static inline int
102 htmlescape(struct template *tp, char c)
104 switch (c) {
105 case '<':
106 return tp_write(tp, "&lt;", 4);
107 case '>':
108 return tp_write(tp, "&gt;", 4);
109 case '&':
110 return tp_write(tp, "&amp;", 5);
111 case '"':
112 return tp_write(tp, "&quot;", 6);
113 case '\'':
114 return tp_write(tp, "&apos;", 6);
115 default:
116 return tp_write(tp, &c, 1);
120 int
121 tp_htmlescape(struct template *tp, const char *str)
123 if (str == NULL)
124 return (0);
126 for (; *str; ++str) {
127 if (htmlescape(tp, *str) == -1)
128 return (-1);
131 return (0);
134 int
135 tp_write_htmlescape(struct template *tp, const char *str, size_t len)
137 size_t i;
139 for (i = 0; i < len; ++i) {
140 if (htmlescape(tp, str[i]) == -1)
141 return (-1);
144 return (0);
147 struct template *
148 template(void *arg, tmpl_write writefn, char *buf, size_t siz)
150 struct template *tp;
152 if ((tp = calloc(1, sizeof(*tp))) == NULL)
153 return (NULL);
155 tp->tp_arg = arg;
156 tp->tp_write = writefn;
157 tp->tp_buf = buf;
158 tp->tp_cap = siz;
160 return (tp);
163 int
164 template_flush(struct template *tp)
166 if (tp->tp_len == 0)
167 return (0);
169 if (tp->tp_write(tp->tp_arg, tp->tp_buf, tp->tp_len) == -1)
170 return (-1);
171 tp->tp_len = 0;
172 return (0);
175 void
176 template_free(struct template *tp)
178 free(tp->tp_tmp);
179 free(tp);