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 int
102 tp_htmlescape(struct template *tp, const char *str)
104 int r;
106 if (str == NULL)
107 return (0);
109 for (; *str; ++str) {
110 switch (*str) {
111 case '<':
112 r = tp_write(tp, "&lt;", 4);
113 break;
114 case '>':
115 r = tp_write(tp, "&gt;", 4);
116 break;
117 case '&':
118 r = tp_write(tp, "&amp;", 5);
119 break;
120 case '"':
121 r = tp_write(tp, "&quot;", 6);
122 break;
123 case '\'':
124 r = tp_write(tp, "&apos;", 6);
125 break;
126 default:
127 r = tp_write(tp, str, 1);
128 break;
131 if (r == -1)
132 return (-1);
135 return (0);
138 struct template *
139 template(void *arg, tmpl_write writefn, char *buf, size_t siz)
141 struct template *tp;
143 if ((tp = calloc(1, sizeof(*tp))) == NULL)
144 return (NULL);
146 tp->tp_arg = arg;
147 tp->tp_write = writefn;
148 tp->tp_buf = buf;
149 tp->tp_cap = siz;
151 return (tp);
154 int
155 template_flush(struct template *tp)
157 if (tp->tp_len == 0)
158 return (0);
160 if (tp->tp_write(tp->tp_arg, tp->tp_buf, tp->tp_len) == -1)
161 return (-1);
162 tp->tp_len = 0;
163 return (0);
166 void
167 template_free(struct template *tp)
169 free(tp->tp_tmp);
170 free(tp);