all repos — cgit @ 17890d0058c1555133c8767ceb123e809e6971ab

a hyperfast web frontend for git written in c

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_txt(char *txt)
 55{
 56	char *t = txt;
 57	while(t && *t){
 58		int c = *t;
 59		if (c=='<' || c=='>' || c=='&') {
 60			write(htmlfd, txt, t - txt);
 61			if (c=='>')
 62				html("&gt;");
 63			else if (c=='<')
 64				html("&lt;");
 65			else if (c=='&')
 66				html("&amp;");
 67			txt = t+1;
 68		}
 69		t++;
 70	}
 71	if (t!=txt)
 72		html(txt);
 73}
 74
 75void html_ntxt(int len, char *txt)
 76{
 77	char *t = txt;
 78	while(t && *t && len--){
 79		int c = *t;
 80		if (c=='<' || c=='>' || c=='&') {
 81			write(htmlfd, txt, t - txt);
 82			if (c=='>')
 83				html("&gt;");
 84			else if (c=='<')
 85				html("&lt;");
 86			else if (c=='&')
 87				html("&amp;");
 88			txt = t+1;
 89		}
 90		t++;
 91	}
 92	if (t!=txt)
 93		write(htmlfd, txt, t - txt);
 94	if (len<0)
 95		html("...");
 96}
 97
 98void html_attr(char *txt)
 99{
100	char *t = txt;
101	while(t && *t){
102		int c = *t;
103		if (c=='<' || c=='>' || c=='\'') {
104			write(htmlfd, txt, t - txt);
105			if (c=='>')
106				html("&gt;");
107			else if (c=='<')
108				html("&lt;");
109			else if (c=='\'')
110				html("&quote;");
111			txt = t+1;
112		}
113		t++;
114	}
115	if (t!=txt)
116		html(txt);
117}
118
119void html_hidden(char *name, char *value)
120{
121	html("<input type='hidden' name='");
122	html_attr(name);
123	html("' value='");
124	html_attr(value);
125	html("'/>");
126}
127
128void html_option(char *value, char *text, char *selected_value)
129{
130	html("<option value='");
131	html_attr(value);
132	html("'");
133	if (selected_value && !strcmp(selected_value, value))
134		html(" selected='selected'");
135	html(">");
136	html_txt(text);
137	html("</option>\n");
138}
139
140void html_link_open(char *url, char *title, char *class)
141{
142	html("<a href='");
143	html_attr(url);
144	if (title) {
145		html("' title='");
146		html_attr(title);
147	}
148	if (class) {
149		html("' class='");
150		html_attr(class);
151	}
152	html("'>");
153}
154
155void html_link_close(void)
156{
157	html("</a>");
158}
159
160void html_fileperm(unsigned short mode)
161{
162	htmlf("%c%c%c", (mode & 4 ? 'r' : '-'),
163	      (mode & 2 ? 'w' : '-'), (mode & 1 ? 'x' : '-'));
164}
165
166int html_include(const char *filename)
167{
168	FILE *f;
169	char buf[4096];
170	size_t len;
171
172	if (!(f = fopen(filename, "r"))) {
173		fprintf(stderr, "[cgit] Failed to include file %s: %s (%d).\n",
174			filename, strerror(errno), errno);
175		return -1;
176	}
177	while((len = fread(buf, 1, 4096, f)) > 0)
178		write(htmlfd, buf, len);
179	fclose(f);
180	return 0;
181}
182
183int hextoint(char c)
184{
185	if (c >= 'a' && c <= 'f')
186		return 10 + c - 'a';
187	else if (c >= 'A' && c <= 'F')
188		return 10 + c - 'A';
189	else if (c >= '0' && c <= '9')
190		return c - '0';
191	else
192		return -1;
193}
194
195char *convert_query_hexchar(char *txt)
196{
197	int d1, d2;
198	if (strlen(txt) < 3) {
199		*txt = '\0';
200		return txt-1;
201	}
202	d1 = hextoint(*(txt+1));
203	d2 = hextoint(*(txt+2));
204	if (d1<0 || d2<0) {
205		strcpy(txt, txt+3);
206		return txt-1;
207	} else {
208		*txt = d1 * 16 + d2;
209		strcpy(txt+1, txt+3);
210		return txt;
211	}
212}
213
214int http_parse_querystring(char *txt, void (*fn)(const char *name, const char *value))
215{
216	char *t, *value = NULL, c;
217
218	if (!txt)
219		return 0;
220
221	t = txt = strdup(txt);
222	if (t == NULL) {
223		printf("Out of memory\n");
224		exit(1);
225	}
226	while((c=*t) != '\0') {
227		if (c=='=') {
228			*t = '\0';
229			value = t+1;
230		} else if (c=='+') {
231			*t = ' ';
232		} else if (c=='%') {
233			t = convert_query_hexchar(t);
234		} else if (c=='&') {
235			*t = '\0';
236			(*fn)(txt, value);
237			txt = t+1;
238			value = NULL;
239		}
240		t++;
241	}
242	if (t!=txt)
243		(*fn)(txt, value);
244	return 0;
245}