iconv: Bail out of the loop when an illegal sequence of bytes occurs.
[elinks/elinks-j605.git] / src / document / html / parse-meta-refresh.c
blob2991e0fe41aee7427fdfd4590cafe67a0d07e692
1 /* Parse <meta http-equiv="refresh" content="..."> */
3 #ifdef HAVE_CONFIG_H
4 #include "config.h"
5 #endif
7 #include <errno.h>
8 #include <stdlib.h>
10 #include "elinks.h"
12 #include "document/html/parse-meta-refresh.h"
13 #include "osdep/ascii.h"
14 #include "util/string.h"
16 #define LWS(c) ((c) == ' ' || (c) == ASCII_TAB)
18 int
19 html_parse_meta_refresh(const unsigned char *content,
20 unsigned long *delay_out,
21 unsigned char **url_out)
23 const unsigned char *scan = content;
24 char *delay_end;
25 int saw_delay = 0;
26 const unsigned char *url_begin;
27 const unsigned char *url_end;
29 *url_out = NULL;
30 *delay_out = 0;
32 while (LWS(*scan))
33 ++scan;
35 /* TODO: Do we need to switch to the "C" locale and back? */
36 *delay_out = strtoul(scan, &delay_end, 10);
37 saw_delay = (scan != (const unsigned char *) delay_end);
38 scan = (const unsigned char *) delay_end;
40 if (saw_delay) {
41 /* Omit any fractional part. */
42 if (*scan == '.') {
43 ++scan;
44 while (!(*scan == '\0' || LWS(*scan)
45 || *scan == ';' || *scan == ','))
46 ++scan;
49 if (!(*scan == '\0' || LWS(*scan)
50 || *scan == ';' || *scan == ',')) {
51 /* The delay is followed by garbage. Give up. */
52 return -1;
55 /* Between the delay and the URL, there must be at
56 * least one LWS, semicolon, or comma; optionally with
57 * more LWS around it. */
58 while (LWS(*scan))
59 ++scan;
60 if (*scan == ';' || *scan == ',')
61 ++scan;
62 } else {
63 /* The delay was not specified. The delimiter must be
64 * a semicolon or a comma, optionally with LWS. LWS
65 * alone does not suffice. */
66 while (*scan != '\0' && *scan != ';' && *scan != ',')
67 ++scan;
68 if (*scan == ';' || *scan == ',')
69 ++scan;
72 while (LWS(*scan))
73 ++scan;
75 /* Presume the URL begins here... */
76 url_begin = scan;
78 /* ..unless there is "URL=" with at least one equals sign,
79 * and optional spaces. */
80 if ((scan[0] == 'U' || scan[0] == 'u')
81 && (scan[1] == 'R' || scan[1] == 'r')
82 && (scan[2] == 'L' || scan[2] == 'l')) {
83 scan += 3;
84 while (LWS(*scan))
85 ++scan;
86 if (*scan == '=') {
87 ++scan;
88 while (LWS(*scan))
89 ++scan;
90 url_begin = scan;
94 if (*url_begin == '"' || *url_begin == '\'') {
95 unsigned char quote = *url_begin++;
97 url_end = strchr(url_begin, quote);
98 if (url_end == NULL)
99 url_end = strchr(url_begin, '\0');
100 } else {
101 url_end = strchr(url_begin, '\0');
104 /* In any case, trim all spaces from the end of the URL. */
105 while (url_begin < url_end && LWS(url_end[-1]))
106 --url_end;
108 if (url_begin != url_end) {
109 *url_out = memacpy(url_begin, url_end - url_begin);
110 if (!*url_out)
111 return -1;
112 } else if (!saw_delay) {
113 /* There is no delay and no URL. */
114 return -1;
117 return 0;