Sync usage with man page.
[netbsd-mini2440.git] / dist / ipf / lib / load_http.c
bloba514be1b5b2d5891882fbeec159c6b1236ed35db
1 /* $NetBSD$ */
3 /*
4 * Copyright (C) 2006 by Darren Reed.
6 * See the IPFILTER.LICENCE file for details on licencing.
8 * Id: load_http.c,v 1.1.2.2 2009/07/23 20:01:12 darrenr Exp
9 */
11 #include "ipf.h"
14 * Because the URL can be included twice into the buffer, once as the
15 * full path for the "GET" and once as the "Host:", the buffer it is
16 * put in needs to be larger than 512*2 to make room for the supporting
17 * text. Why not just use snprintf and truncate? The warning about the
18 * URL being too long tells you something is wrong and does not fetch
19 * any data - just truncating the URL (with snprintf, etc) and sending
20 * that to the server is allowing an unknown and unintentioned action
21 * to happen.
23 #define MAX_URL_LEN 512
24 #define LOAD_BUFSIZE (MAX_URL_LEN * 2 + 128)
27 * Format expected is one addres per line, at the start of each line.
29 alist_t *
30 load_http(char *url)
32 char *s, *t, *u, buffer[LOAD_BUFSIZE], *myurl;
33 int fd, len, left, port, endhdr, removed;
34 alist_t *a, *rtop, *rbot;
35 struct sockaddr_in sin;
36 struct hostent *host;
37 size_t rem;
40 * More than this would just be absurd.
42 if (strlen(url) > MAX_URL_LEN) {
43 fprintf(stderr, "load_http has a URL > %d bytes?!\n",
44 MAX_URL_LEN);
45 return NULL;
48 fd = -1;
49 rtop = NULL;
50 rbot = NULL;
52 myurl = strdup(url);
53 if (myurl == NULL)
54 goto done;
56 rem = sizeof(buffer);
57 left = snprintf(buffer, rem, "GET %s HTTP/1.0\r\n", url);
58 if (left < 0 || left > rem)
59 goto done;
60 rem -= left;
62 s = myurl + 7; /* http:// */
63 t = strchr(s, '/');
64 if (t == NULL) {
65 fprintf(stderr, "load_http has a malformed URL '%s'\n", url);
66 goto done;
68 *t++ = '\0';
71 * 10 is the length of 'Host: \r\n\r\n' below.
73 if (strlen(s) + strlen(buffer) + 10 > sizeof(buffer)) {
74 fprintf(stderr, "load_http has a malformed URL '%s'\n", url);
75 free(myurl);
76 return NULL;
79 u = strchr(s, '@');
80 if (u != NULL)
81 s = u + 1; /* AUTH */
83 left = snprintf(buffer + left, rem, "Host: %s\r\n\r\n", s);
84 if (left < 0 || left > rem)
85 goto done;
86 rem -= left;
88 u = strchr(s, ':');
89 if (u != NULL) {
90 *u++ = '\0';
91 port = atoi(u);
92 if (port < 0 || port > 65535)
93 goto done;
94 } else {
95 port = 80;
98 memset(&sin, 0, sizeof(sin));
99 sin.sin_family = AF_INET;
100 sin.sin_port = htons(port);
102 if (isdigit((unsigned char)*s)) {
103 if (inet_aton(s, &sin.sin_addr) == -1) {
104 goto done;
106 } else {
107 host = gethostbyname(s);
108 if (host == NULL)
109 goto done;
110 memcpy(&sin.sin_addr, host->h_addr_list[0],
111 sizeof(sin.sin_addr));
114 fd = socket(AF_INET, SOCK_STREAM, 0);
115 if (fd == -1)
116 goto done;
118 if (connect(fd, (struct sockaddr *)&sin, sizeof(sin)) == -1)
119 goto done;
121 len = strlen(buffer);
122 if (write(fd, buffer, len) != len)
123 goto done;
125 s = buffer;
126 endhdr = 0;
127 left = sizeof(buffer) - 1;
129 while ((len = read(fd, s, left)) > 0) {
130 s[len] = '\0';
131 left -= len;
132 s += len;
134 if (endhdr >= 0) {
135 if (endhdr == 0) {
136 t = strchr(buffer, ' ');
137 if (t == NULL)
138 continue;
139 t++;
140 if (*t != '2')
141 break;
144 u = buffer;
145 while ((t = strchr(u, '\r')) != NULL) {
146 if (t == u) {
147 if (*(t + 1) == '\n') {
148 u = t + 2;
149 endhdr = -1;
150 break;
151 } else
152 t++;
153 } else if (*(t + 1) == '\n') {
154 endhdr++;
155 u = t + 2;
156 } else
157 u = t + 1;
159 if (endhdr >= 0)
160 continue;
161 removed = (u - buffer) + 1;
162 memmove(buffer, u, (sizeof(buffer) - left) - removed);
163 s -= removed;
164 left += removed;
167 do {
168 t = strchr(buffer, '\n');
169 if (t == NULL)
170 break;
172 *t++ = '\0';
173 for (u = buffer; isdigit((unsigned char)*u) ||
174 (*u == '.'); u++)
175 continue;
176 if (*u == '/') {
177 char *slash;
179 slash = u;
180 u++;
181 while (isdigit((unsigned char)*u))
182 u++;
183 if (!isspace((unsigned char)*u) && *u)
184 u = slash;
186 *u = '\0';
188 a = alist_new(4, buffer);
189 if (a != NULL) {
190 if (rbot != NULL)
191 rbot->al_next = a;
192 else
193 rtop = a;
194 rbot = a;
197 removed = t - buffer;
198 memmove(buffer, t, sizeof(buffer) - left - removed);
199 s -= removed;
200 left += removed;
202 } while (1);
205 done:
206 if (myurl != NULL)
207 free(myurl);
208 if (fd != -1)
209 close(fd);
210 return rtop;