all repos — cgit @ 02a545e63454530c1639014d3239c14ced2022c6

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_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("&gt;");
 70			else if (c=='<')
 71				html("&lt;");
 72			else if (c=='&')
 73				html("&amp;");
 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("&gt;");
 91			else if (c=='<')
 92				html("&lt;");
 93			else if (c=='&')
 94				html("&amp;");
 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("&gt;");
114			else if (c=='<')
115				html("&lt;");
116			else if (c=='\'')
117				html("&quote;");
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}