html.c (view raw)
1/* html.c: helper functions for html output
2 *
3 * Copyright (C) 2006 Lars Hjemli
4 *
5 * Licensed under GNU General Public License v2
6 * (see COPYING for full license text)
7 */
8
9#include <unistd.h>
10#include <stdio.h>
11#include <stdlib.h>
12#include <stdarg.h>
13#include <string.h>
14#include <errno.h>
15
16int htmlfd = STDOUT_FILENO;
17
18char *fmt(const char *format, ...)
19{
20 static char buf[8][1024];
21 static int bufidx;
22 int len;
23 va_list args;
24
25 bufidx++;
26 bufidx &= 7;
27
28 va_start(args, format);
29 len = vsnprintf(buf[bufidx], sizeof(buf[bufidx]), format, args);
30 va_end(args);
31 if (len>sizeof(buf[bufidx])) {
32 fprintf(stderr, "[html.c] string truncated: %s\n", format);
33 exit(1);
34 }
35 return buf[bufidx];
36}
37
38void html(const char *txt)
39{
40 write(htmlfd, txt, strlen(txt));
41}
42
43void htmlf(const char *format, ...)
44{
45 static char buf[65536];
46 va_list args;
47
48 va_start(args, format);
49 vsnprintf(buf, sizeof(buf), format, args);
50 va_end(args);
51 html(buf);
52}
53
54void html_status(int code, int more_headers)
55{
56 htmlf("Status: %d\n", code);
57 if (!more_headers)
58 html("\n");
59}
60
61void html_txt(char *txt)
62{
63 char *t = txt;
64 while(t && *t){
65 int c = *t;
66 if (c=='<' || c=='>' || c=='&') {
67 write(htmlfd, txt, t - txt);
68 if (c=='>')
69 html(">");
70 else if (c=='<')
71 html("<");
72 else if (c=='&')
73 html("&");
74 txt = t+1;
75 }
76 t++;
77 }
78 if (t!=txt)
79 html(txt);
80}
81
82void html_ntxt(int len, char *txt)
83{
84 char *t = txt;
85 while(t && *t && len--){
86 int c = *t;
87 if (c=='<' || c=='>' || c=='&') {
88 write(htmlfd, txt, t - txt);
89 if (c=='>')
90 html(">");
91 else if (c=='<')
92 html("<");
93 else if (c=='&')
94 html("&");
95 txt = t+1;
96 }
97 t++;
98 }
99 if (t!=txt)
100 write(htmlfd, txt, t - txt);
101 if (len<0)
102 html("...");
103}
104
105void html_attr(char *txt)
106{
107 char *t = txt;
108 while(t && *t){
109 int c = *t;
110 if (c=='<' || c=='>' || c=='\'') {
111 write(htmlfd, txt, t - txt);
112 if (c=='>')
113 html(">");
114 else if (c=='<')
115 html("<");
116 else if (c=='\'')
117 html(""e;");
118 txt = t+1;
119 }
120 t++;
121 }
122 if (t!=txt)
123 html(txt);
124}
125
126void html_hidden(char *name, char *value)
127{
128 html("<input type='hidden' name='");
129 html_attr(name);
130 html("' value='");
131 html_attr(value);
132 html("'/>");
133}
134
135void html_option(char *value, char *text, char *selected_value)
136{
137 html("<option value='");
138 html_attr(value);
139 html("'");
140 if (selected_value && !strcmp(selected_value, value))
141 html(" selected='selected'");
142 html(">");
143 html_txt(text);
144 html("</option>\n");
145}
146
147void html_link_open(char *url, char *title, char *class)
148{
149 html("<a href='");
150 html_attr(url);
151 if (title) {
152 html("' title='");
153 html_attr(title);
154 }
155 if (class) {
156 html("' class='");
157 html_attr(class);
158 }
159 html("'>");
160}
161
162void html_link_close(void)
163{
164 html("</a>");
165}
166
167void html_fileperm(unsigned short mode)
168{
169 htmlf("%c%c%c", (mode & 4 ? 'r' : '-'),
170 (mode & 2 ? 'w' : '-'), (mode & 1 ? 'x' : '-'));
171}
172
173int html_include(const char *filename)
174{
175 FILE *f;
176 char buf[4096];
177 size_t len;
178
179 if (!(f = fopen(filename, "r"))) {
180 fprintf(stderr, "[cgit] Failed to include file %s: %s (%d).\n",
181 filename, strerror(errno), errno);
182 return -1;
183 }
184 while((len = fread(buf, 1, 4096, f)) > 0)
185 write(htmlfd, buf, len);
186 fclose(f);
187 return 0;
188}
189
190int hextoint(char c)
191{
192 if (c >= 'a' && c <= 'f')
193 return 10 + c - 'a';
194 else if (c >= 'A' && c <= 'F')
195 return 10 + c - 'A';
196 else if (c >= '0' && c <= '9')
197 return c - '0';
198 else
199 return -1;
200}
201
202char *convert_query_hexchar(char *txt)
203{
204 int d1, d2;
205 if (strlen(txt) < 3) {
206 *txt = '\0';
207 return txt-1;
208 }
209 d1 = hextoint(*(txt+1));
210 d2 = hextoint(*(txt+2));
211 if (d1<0 || d2<0) {
212 strcpy(txt, txt+3);
213 return txt-1;
214 } else {
215 *txt = d1 * 16 + d2;
216 strcpy(txt+1, txt+3);
217 return txt;
218 }
219}
220
221int http_parse_querystring(char *txt, void (*fn)(const char *name, const char *value))
222{
223 char *t, *value = NULL, c;
224
225 if (!txt)
226 return 0;
227
228 t = txt = strdup(txt);
229 if (t == NULL) {
230 printf("Out of memory\n");
231 exit(1);
232 }
233 while((c=*t) != '\0') {
234 if (c=='=') {
235 *t = '\0';
236 value = t+1;
237 } else if (c=='+') {
238 *t = ' ';
239 } else if (c=='%') {
240 t = convert_query_hexchar(t);
241 } else if (c=='&') {
242 *t = '\0';
243 (*fn)(txt, value);
244 txt = t+1;
245 value = NULL;
246 }
247 t++;
248 }
249 if (t!=txt)
250 (*fn)(txt, value);
251 return 0;
252}