]> gitweb.ps.run Git - ps-cgit/blob - html.c
Merge branch 'lh/cache'
[ps-cgit] / html.c
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
16 int htmlfd = STDOUT_FILENO;
17
18 char *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
38 void html(const char *txt)
39 {
40         write(htmlfd, txt, strlen(txt));
41 }
42
43 void 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
54 void 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
75 void 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
98 void 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
119 void 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
128 void 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
140 void 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
155 void html_link_close(void)
156 {
157         html("</a>");
158 }
159
160 void html_fileperm(unsigned short mode)
161 {
162         htmlf("%c%c%c", (mode & 4 ? 'r' : '-'),
163               (mode & 2 ? 'w' : '-'), (mode & 1 ? 'x' : '-'));
164 }
165
166 int 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
183 int 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
195 char *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
214 int 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 }