]> git.cameronkatri.com Git - mandoc.git/blob - html.c
Character-set validation fixes.
[mandoc.git] / html.c
1 /* $Id: html.c,v 1.5 2008/12/04 16:19:52 kristaps Exp $ */
2 /*
3 * Copyright (c) 2008 Kristaps Dzonsons <kristaps@kth.se>
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the
7 * above copyright notice and this permission notice appear in all
8 * copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
18 */
19 #include <sys/param.h>
20 #include <sys/stat.h>
21
22 #include <assert.h>
23 #include <err.h>
24 #include <fcntl.h>
25 #include <stdlib.h>
26 #include <stdio.h>
27 #include <string.h>
28 #include <unistd.h>
29
30 #include "libmdocml.h"
31 #include "private.h"
32 #include "ml.h"
33
34
35 static int html_loadcss(struct md_mbuf *, const char *);
36
37 static ssize_t html_endtag(struct md_mbuf *,
38 const struct md_args *,
39 enum md_ns, int);
40 static ssize_t html_begintag(struct md_mbuf *,
41 const struct md_args *,
42 enum md_ns, int,
43 const int *, const char **);
44 static int html_begin(struct md_mbuf *,
45 const struct md_args *,
46 const struct tm *,
47 const char *, const char *,
48 const char *, const char *);
49 static int html_end(struct md_mbuf *,
50 const struct md_args *);
51 static ssize_t html_blocktagname(struct md_mbuf *,
52 const struct md_args *, int);
53 static ssize_t html_blocktagargs(struct md_mbuf *,
54 const struct md_args *, int,
55 const int *, const char **);
56 static ssize_t html_blockheadtagname(struct md_mbuf *,
57 const struct md_args *, int);
58 static ssize_t html_blockheadtagargs(struct md_mbuf *,
59 const struct md_args *, int,
60 const int *, const char **);
61 static ssize_t html_blockbodytagname(struct md_mbuf *,
62 const struct md_args *, int);
63 static ssize_t html_blockbodytagargs(struct md_mbuf *,
64 const struct md_args *, int,
65 const int *, const char **);
66 static ssize_t html_inlinetagname(struct md_mbuf *,
67 const struct md_args *, int);
68 static ssize_t html_inlinetagargs(struct md_mbuf *,
69 const struct md_args *, int,
70 const int *, const char **);
71
72
73 static int
74 html_loadcss(struct md_mbuf *mbuf, const char *css)
75 {
76 size_t res, bufsz;
77 char *buf;
78 struct stat st;
79 int fd, c;
80 ssize_t ssz;
81
82 c = 0;
83 res = 0;
84 buf = NULL;
85
86 if (-1 == (fd = open(css, O_RDONLY, 0))) {
87 warn("%s", css);
88 return(0);
89 }
90
91 if (-1 == fstat(fd, &st)) {
92 warn("%s", css);
93 goto out;
94 }
95
96 bufsz = MAX(st.st_blksize, BUFSIZ);
97 if (NULL == (buf = malloc(bufsz))) {
98 warn("malloc");
99 goto out;
100 }
101
102 for (;;) {
103 if (-1 == (ssz = read(fd, buf, bufsz))) {
104 warn("%s", css);
105 goto out;
106 } else if (0 == ssz)
107 break;
108 if ( ! ml_nputs(mbuf, buf, (size_t)ssz, &res))
109 goto out;
110 }
111
112 c = 1;
113
114 out:
115 if (-1 == close(fd)) {
116 warn("%s", css);
117 c = 0;
118 }
119
120 if (buf)
121 free(buf);
122
123 return(c);
124 }
125
126
127 /* ARGSUSED */
128 static int
129 html_begin(struct md_mbuf *mbuf, const struct md_args *args,
130 const struct tm *tm, const char *os,
131 const char *title, const char *section,
132 const char *vol)
133 {
134 const char *preamble, *css, *trail;
135 char buf[512];
136 size_t res;
137
138 preamble =
139 "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\"\n"
140 " \"http://www.w3.org/TR/html4/strict.dtd\">\n"
141 "<html>\n"
142 "<head>\n"
143 " <meta http-equiv=\"Content-Type\"\n"
144 " content=\"text/html;charset=utf-8\">\n"
145 " <meta name=\"resource-type\" content=\"document\">\n"
146 " <title>Manual Page for %s(%s)</title>\n";
147
148 css =
149 " <link rel=\"stylesheet\" type=\"text/css\"\n"
150 " href=\"%s\">\n";
151 trail =
152 "</head>\n"
153 "<body>\n"
154 "<div class=\"mdoc\">\n";
155
156 res = 0;
157
158 (void)snprintf(buf, sizeof(buf) - 1,
159 preamble, title, section);
160
161 if ( ! ml_puts(mbuf, buf, &res))
162 return(0);
163
164 assert(args->params.html.css);
165 if (HTML_CSS_EMBED & args->params.html.flags) {
166 if ( ! ml_puts(mbuf, " <style type=\"text/css\"><!--\n", &res))
167 return(0);
168 if ( ! html_loadcss(mbuf, args->params.html.css))
169 return(0);
170 if ( ! ml_puts(mbuf, " --!></style>\n", &res))
171 return(0);
172 } else {
173 (void)snprintf(buf, sizeof(buf) - 1, css,
174 args->params.html.css);
175 if ( ! ml_puts(mbuf, buf, &res))
176 return(0);
177 }
178
179 if ( ! ml_puts(mbuf, trail, &res))
180 return(0);
181
182 return(1);
183 }
184
185
186 /* ARGSUSED */
187 static int
188 html_end(struct md_mbuf *mbuf, const struct md_args *args)
189 {
190 size_t res;
191
192 res = 0;
193 if ( ! ml_puts(mbuf, "</div></body>\n</html>", &res))
194 return(0);
195
196 return(1);
197 }
198
199
200 /* ARGSUSED */
201 static ssize_t
202 html_blockbodytagname(struct md_mbuf *mbuf,
203 const struct md_args *args, int tok)
204 {
205 size_t res;
206
207 res = 0;
208 if ( ! ml_puts(mbuf, "div", &res))
209 return(-1);
210
211 return((ssize_t)res);
212 }
213
214
215
216
217 /* ARGSUSED */
218 static ssize_t
219 html_blockheadtagname(struct md_mbuf *mbuf,
220 const struct md_args *args, int tok)
221 {
222 size_t res;
223
224 res = 0;
225 if ( ! ml_puts(mbuf, "div", &res))
226 return(-1);
227
228 return((ssize_t)res);
229 }
230
231
232 /* ARGSUSED */
233 static ssize_t
234 html_blocktagname(struct md_mbuf *mbuf,
235 const struct md_args *args, int tok)
236 {
237 size_t res;
238
239 res = 0;
240 if ( ! ml_puts(mbuf, "div", &res))
241 return(-1);
242
243 return((ssize_t)res);
244 }
245
246
247 /* ARGSUSED */
248 static ssize_t
249 html_blockheadtagargs(struct md_mbuf *mbuf, const struct md_args *args,
250 int tok, const int *argc, const char **argv)
251 {
252 size_t res;
253
254 res = 0;
255
256 if ( ! ml_puts(mbuf, " class=\"head-", &res))
257 return(0);
258 if ( ! ml_puts(mbuf, toknames[tok], &res))
259 return(0);
260 if ( ! ml_puts(mbuf, "\"", &res))
261 return(0);
262
263 switch (tok) {
264 default:
265 break;
266 }
267
268 return(0);
269 }
270
271
272 /* ARGSUSED */
273 static ssize_t
274 html_blockbodytagargs(struct md_mbuf *mbuf, const struct md_args *args,
275 int tok, const int *argc, const char **argv)
276 {
277 size_t res;
278
279 res = 0;
280
281 if ( ! ml_puts(mbuf, " class=\"body-", &res))
282 return(0);
283 if ( ! ml_puts(mbuf, toknames[tok], &res))
284 return(0);
285 if ( ! ml_puts(mbuf, "\"", &res))
286 return(0);
287
288 switch (tok) {
289 default:
290 break;
291 }
292
293 return(res);
294 }
295
296
297 /* ARGSUSED */
298 static ssize_t
299 html_blocktagargs(struct md_mbuf *mbuf, const struct md_args *args,
300 int tok, const int *argc, const char **argv)
301 {
302 size_t res;
303
304 res = 0;
305
306 if ( ! ml_puts(mbuf, " class=\"block-", &res))
307 return(0);
308 if ( ! ml_puts(mbuf, toknames[tok], &res))
309 return(0);
310 if ( ! ml_puts(mbuf, "\"", &res))
311 return(0);
312
313 switch (tok) {
314 default:
315 break;
316 }
317
318 return(0);
319 }
320
321
322 /* ARGSUSED */
323 static ssize_t
324 html_inlinetagargs(struct md_mbuf *mbuf, const struct md_args *args,
325 int tok, const int *argc, const char **argv)
326 {
327 size_t res;
328
329 res = 0;
330
331 if ( ! ml_puts(mbuf, " class=\"inline-", &res))
332 return(0);
333 if ( ! ml_puts(mbuf, toknames[tok], &res))
334 return(0);
335 if ( ! ml_puts(mbuf, "\"", &res))
336 return(0);
337
338
339 switch (tok) {
340 default:
341 break;
342 }
343
344 return(0);
345 }
346
347
348 /* ARGSUSED */
349 static ssize_t
350 html_inlinetagname(struct md_mbuf *mbuf,
351 const struct md_args *args, int tok)
352 {
353 size_t res;
354
355 res = 0;
356
357 switch (tok) {
358 case (ROFF_Pp):
359 if ( ! ml_puts(mbuf, "div", &res))
360 return(-1);
361 break;
362 default:
363 if ( ! ml_puts(mbuf, "span", &res))
364 return(-1);
365 break;
366 }
367
368 return((ssize_t)res);
369 }
370
371
372 static ssize_t
373 html_begintag(struct md_mbuf *mbuf, const struct md_args *args,
374 enum md_ns ns, int tok,
375 const int *argc, const char **argv)
376 {
377
378 assert(ns != MD_NS_DEFAULT);
379 switch (ns) {
380 case (MD_NS_BLOCK):
381 if ( ! html_blocktagname(mbuf, args, tok))
382 return(0);
383 return(html_blocktagargs(mbuf, args,
384 tok, argc, argv));
385 case (MD_NS_BODY):
386 if ( ! html_blockbodytagname(mbuf, args, tok))
387 return(0);
388 return(html_blockbodytagargs(mbuf, args,
389 tok, argc, argv));
390 case (MD_NS_HEAD):
391 if ( ! html_blockheadtagname(mbuf, args, tok))
392 return(0);
393 return(html_blockheadtagargs(mbuf, args,
394 tok, argc, argv));
395 default:
396 break;
397 }
398
399 if ( ! html_inlinetagname(mbuf, args, tok))
400 return(0);
401 return(html_inlinetagargs(mbuf, args, tok, argc, argv));
402 }
403
404
405 static ssize_t
406 html_endtag(struct md_mbuf *mbuf, const struct md_args *args,
407 enum md_ns ns, int tok)
408 {
409
410 assert(ns != MD_NS_DEFAULT);
411 switch (ns) {
412 case (MD_NS_BLOCK):
413 return(html_blocktagname(mbuf, args, tok));
414 case (MD_NS_BODY):
415 return(html_blockbodytagname(mbuf, args, tok));
416 case (MD_NS_HEAD):
417 return(html_blockheadtagname(mbuf, args, tok));
418 default:
419 break;
420 }
421
422 return(html_inlinetagname(mbuf, args, tok));
423 }
424
425
426 int
427 md_line_html(void *data, char *buf)
428 {
429
430 return(mlg_line((struct md_mlg *)data, buf));
431 }
432
433
434 int
435 md_exit_html(void *data, int flush)
436 {
437
438 return(mlg_exit((struct md_mlg *)data, flush));
439 }
440
441
442 void *
443 md_init_html(const struct md_args *args,
444 struct md_mbuf *mbuf, const struct md_rbuf *rbuf)
445 {
446
447 return(mlg_alloc(args, rbuf, mbuf, html_begintag,
448 html_endtag, html_begin, html_end));
449 }
450