root/cgi/html.h
/*INCLUDED FROM
DEFINITIONS
This source file includes following definitions.- readable_time_static
- readable_time
- html_transcnt
- html_catsz
- html_conv_tab
- html_encode
- html_make_link
- vhtml
- html
- html_page_begin
- html_table_begin
- html_table_row
- html_table_end
- html_print_err
- html_page_end
1 #ifndef __cgi_html__ 2 #define __cgi_html__ 1 3 4 #include "cgi.h" 5 6 #include <stdio.h> 7 #include <stdlib.h> 8 #include <string.h> 9 #include <stdarg.h> 10 11 extern const char *extra_head; 12 extern const char *my_header; 13 extern const char *my_footer; 14 extern FILE *capture; 15 16 17 #ifndef MY_DATE_FMT 18 # define MY_DATE_FMT "%Y.%m.%d" 19 #endif 20 #ifndef MY_LONG_DATE_FMT 21 # define MY_LONG_DATE_FMT "%Y.%m.%d %H:%M %z" 22 #endif 23 24 25 static char * 26 readable_time_static(time_t t, const char *fmt) 27 { 28 char *ts = my_malloc(MINB); 29 30 if (!ts) return NULL; 31 32 strftime(ts, MINB, fmt, localtime(&t)); 33 34 return ts; 35 } 36 37 38 static char * 39 readable_time(time_t t) 40 { 41 #ifdef NO_DATE_AGO 42 return readable_time_static(t); 43 #else 44 char *ts = my_malloc(MINB); 45 time_t n = time(NULL) - t; 46 # ifndef NO_DATE_COLOR 47 # define SEC_RB "<span class=\"cgi-rdate-sec\">" 48 # define MIN_RB "<span class=\"cgi-rdate-min\">" 49 # define HRT_RB "<span class=\"cgi-rdate-hour\">" 50 # define DAY_RB "<span class=\"cgi-rdate-day\">" 51 # define TC_RE "</span>" 52 # else 53 # define SEC_RB "" 54 # define HRT_RB "" 55 # define MIN_RB "" 56 # define DAY_RB "" 57 # define TC_RE "" 58 # endif 59 60 if (!ts) return NULL; 61 62 if (n < 60) 63 snprintf(ts, MINB, SEC_RB "%ds ago" TC_RE, (int)n); 64 else if (n < 3600) 65 snprintf(ts, MINB, MIN_RB "%dm ago" TC_RE, (int)(n / 60)); 66 else if (n < 86400) 67 snprintf(ts, MINB, HRT_RB "%dh ago" TC_RE, (int)(n / 3600)); 68 else if (n < 2419200) 69 snprintf(ts, MINB, DAY_RB "%dd ago" TC_RE, (int)(n / 86400)); 70 else { 71 my_free(ts); 72 return readable_time_static(t, MY_DATE_FMT); 73 } 74 75 return ts; 76 #endif 77 } 78 79 80 static size_t 81 html_transcnt(const char *s, int a, ...) 82 { 83 va_list ap; 84 size_t c = 1; 85 int i, tc; 86 87 while (*s != '\0') { 88 va_start(ap, a); 89 for (tc = 1, i = 0; i < a; i++) 90 if (*s == va_arg(ap, int)) { 91 tc = va_arg(ap, int); 92 } else (void)va_arg(ap, int); 93 va_end(ap); 94 c += tc; s++; 95 } 96 97 return c; 98 } 99 100 101 static size_t 102 html_catsz(const char *s, ...) 103 { 104 va_list ap; 105 size_t t = 0; 106 int i; 107 108 va_start(ap, s); 109 for (i = 0; i < strlen(s); i++) { 110 switch (s[i]) { 111 case 's': t += va_arg(ap, size_t); break; 112 case 'r': t += strlen(va_arg(ap, const char *)) + 1; break; 113 default : break; 114 } 115 } 116 va_end(ap); 117 118 return t; 119 } 120 121 122 static char * 123 html_conv_tab(const char *line, size_t tw) 124 { 125 size_t i = 0, tsz = html_transcnt(line, 1, '\t', 8); 126 char *cp, *t = my_malloc(tsz); 127 char *lim = t + tsz; 128 129 if (!t) return NULL; 130 131 #define bputc(b, m, c) ((b) < (m) ? (*(b)++ = (c)) : (*(b) = '\0')) 132 cp = t; while (*line != '\0') { 133 int i2, ci = 1; 134 if (*line == '\t') { 135 ci = tw - (i % tw); 136 for (i2 = 0; i2 < ci; i2++) 137 bputc(cp, lim, ' '); 138 } else bputc(cp, lim, *line); 139 i += ci; line++; 140 } 141 bputc(cp, lim, '\0'); 142 143 return t; 144 } 145 146 147 #define html_encode_cnt(s) (html_transcnt((s), 3, '<', 4, '>', 4, '&', 5)) 148 static char * 149 html_encode(const char *s) 150 { 151 size_t i, a, bsz = html_encode_cnt(s); 152 int c; 153 char *cp, *cp2, *st = my_strdup(s), *t = my_malloc(bsz); 154 155 if (!(t && st)) return NULL; 156 *t = '\0'; 157 158 for (cp = st;;) { 159 /* cut up s into already-valid spans */ 160 a = strcspn(cp2 = cp, "<>&"); 161 c = *(cp += a); 162 *(cp++) = '\0'; 163 164 /* copy valid section directly */ 165 strncat(t, cp2, bsz); 166 167 /* process invalid character */ 168 switch (c) { 169 case '\0': goto exit_encode; 170 case '<' : strncat(t, "<" , bsz); break; 171 case '>' : strncat(t, ">" , bsz); break; 172 case '&' : strncat(t, "&", bsz); break; 173 } 174 } 175 exit_encode: 176 my_free(st); 177 return t; 178 } 179 180 181 static char * 182 html_make_link(const char *href, const char *title) 183 { 184 const char *fmt = "<a href=\"%s\">%s</a>"; 185 size_t bsz = html_catsz("srr", html_encode_cnt(href), title, fmt); 186 char *ht, *t = my_malloc(bsz); 187 188 if (!t) return NULL; 189 190 ht = html_encode(href); 191 192 snprintf(t, bsz, fmt, ht, title); 193 194 my_free(ht); 195 196 return t; 197 } 198 199 200 static void 201 vhtml(const char *fmt, va_list ap) 202 { 203 vfprintf(capture, fmt, ap); 204 } 205 206 207 static void 208 html(const char *fmt, ...) 209 { 210 va_list ap; 211 va_start(ap, fmt); 212 vhtml(fmt, ap); 213 va_end(ap); 214 } 215 216 217 static void 218 html_page_begin(char *title) 219 { 220 html("<!DOCTYPE html>\n\ 221 <html>\ 222 <head>\ 223 <meta charset=\"UTF-8\">\n\ 224 <title>%s</title>\n\ 225 %s</head>\n\ 226 <body>\n\ 227 %s", html_encode(title), extra_head, my_header); 228 } 229 230 231 static void 232 html_table_begin(int n, ...) 233 { 234 int i; 235 va_list ap; 236 237 va_start(ap, n); 238 html("<table>\n"); 239 if (n > 0) { 240 html(" <tr>\n"); 241 for (i = 0; i < n; i++) 242 html(" <th>%s</th>\n", va_arg(ap, char *)); 243 html(" </tr>\n"); 244 } 245 va_end(ap); 246 } 247 248 249 static void 250 html_table_row(int n, ...) 251 { 252 int i; 253 va_list ap; 254 255 va_start(ap, n); 256 html(" <tr>\n"); 257 for (i = 0; i < n; i++) 258 html(" <td>%s</td>\n", va_arg(ap, char *)); 259 html(" </tr>\n"); 260 va_end(ap); 261 } 262 263 264 static void 265 html_table_end(void) 266 { 267 html("</table>\n"); 268 } 269 270 271 static void 272 html_print_err(const char *fmt, ...) 273 { 274 va_list ap; 275 va_start(ap, fmt); 276 html("<div class=\"cgi-error\"><p>"); 277 vhtml(fmt, ap); 278 html("</p></div>\n"); 279 va_end(ap); 280 } 281 282 283 static void 284 html_page_end(void) 285 { 286 html("%s</body></html>\n", my_footer); 287 } 288 289 290 #endif
/*