]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - contrib/ipfilter/lib/load_http.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / contrib / ipfilter / lib / load_http.c
1 /*
2  * Copyright (C) 2006 by Darren Reed.
3  *
4  * See the IPFILTER.LICENCE file for details on licencing.
5  *
6  * $Id: load_http.c,v 1.1.2.1 2006/08/25 21:13:04 darrenr Exp $
7  */
8
9 #include "ipf.h"
10
11 /*
12  * Format expected is one addres per line, at the start of each line.
13  */
14 alist_t *
15 load_http(char *url)
16 {
17         char *s, *t, *u, buffer[1044], *myurl;
18         alist_t *a, *rtop, *rbot;
19         struct sockaddr_in sin;
20         struct hostent *host;
21         size_t avail;
22         int fd, len, left, port, endhdr, removed;
23         int error;
24
25         /*
26          * More than this would just be absurd.
27          */
28         if (strlen(url) > 512) {
29                 fprintf(stderr, "load_http has a URL > 512 bytes?!\n");
30                 return NULL;
31         }
32
33         fd = -1;
34         rtop = NULL;
35         rbot = NULL;
36
37         avail = sizeof(buffer);
38         error = snprintf(buffer, avail, "GET %s HTTP/1.0\r\n", url);
39
40         /*
41          * error is always less then avail due to the constraint on
42          * the url length above.
43          */
44         avail -= error;
45
46         myurl = strdup(url);
47         if (myurl == NULL)
48                 goto done;
49
50         s = myurl + 7;                  /* http:// */
51         t = strchr(s, '/');
52         if (t == NULL) {
53                 fprintf(stderr, "load_http has a malformed URL '%s'\n", url);
54                 free(myurl);
55                 return NULL;
56         }
57         *t++ = '\0';
58
59         u = strchr(s, '@');
60         if (u != NULL)
61                 s = u + 1;              /* AUTH */
62
63         error = snprintf(buffer + strlen(buffer), avail, "Host: %s\r\n\r\n", s);
64         if (error >= avail) {
65                 fprintf(stderr, "URL is too large: %s\n", url);
66                 goto done;
67         }
68
69         u = strchr(s, ':');
70         if (u != NULL) {
71                 *u++ = '\0';
72                 port = atoi(u);
73                 if (port < 0 || port > 65535)
74                         goto done;
75         } else {
76                 port = 80;
77         }
78
79         memset(&sin, 0, sizeof(sin));
80         sin.sin_family = AF_INET;
81         sin.sin_port = htons(port);
82
83         if (isdigit(*s)) {
84                 if (inet_aton(s, &sin.sin_addr) == -1) {
85                         goto done;
86                 }
87         } else {
88                 host = gethostbyname(s);
89                 if (host == NULL)
90                         goto done;
91                 memcpy(&sin.sin_addr, host->h_addr_list[0],
92                        sizeof(sin.sin_addr));
93         }
94
95         fd = socket(AF_INET, SOCK_STREAM, 0);
96         if (fd == -1)
97                 goto done;
98
99         if (connect(fd, (struct sockaddr *)&sin, sizeof(sin)) == -1)
100                 goto done;
101
102         len = strlen(buffer);
103         if (write(fd, buffer, len) != len)
104                 goto done;
105
106         s = buffer;
107         endhdr = 0;
108         left = sizeof(buffer) - 1;
109
110         while ((len = read(fd, s, left)) > 0) {
111                 s[len] = '\0';
112                 left -= len;
113                 s += len;
114
115                 if (endhdr >= 0) {
116                         if (endhdr == 0) {
117                                 t = strchr(buffer, ' ');
118                                 if (t == NULL)
119                                         continue;
120                                 t++;
121                                 if (*t != '2')
122                                         break;
123                         }
124
125                         u = buffer;
126                         while ((t = strchr(u, '\r')) != NULL) {
127                                 if (t == u) {
128                                         if (*(t + 1) == '\n') {
129                                                 u = t + 2;
130                                                 endhdr = -1;
131                                                 break;
132                                         } else
133                                                 t++;
134                                 } else if (*(t + 1) == '\n') {
135                                         endhdr++;
136                                         u = t + 2;
137                                 } else
138                                         u = t + 1;
139                         }
140                         if (endhdr >= 0)
141                                 continue;
142                         removed = (u - buffer) + 1;
143                         memmove(buffer, u, (sizeof(buffer) - left) - removed);
144                         s -= removed;
145                         left += removed;
146                 }
147
148                 do {
149                         t = strchr(buffer, '\n');
150                         if (t == NULL)
151                                 break;
152
153                         *t++ = '\0';
154                         for (u = buffer; isdigit(*u) || (*u == '.'); u++)
155                                 ;
156                         if (*u == '/') {
157                                 char *slash;
158
159                                 slash = u;
160                                 u++;
161                                 while (isdigit(*u))
162                                         u++;
163                                 if (!isspace(*u) && *u)
164                                         u = slash;
165                         }
166                         *u = '\0';
167
168                         a = alist_new(4, buffer);
169                         if (a != NULL) {
170                                 if (rbot != NULL)
171                                         rbot->al_next = a;
172                                 else
173                                         rtop = a;
174                                 rbot = a;
175                         }
176
177                         removed = t - buffer;
178                         memmove(buffer, t, sizeof(buffer) - left - removed);
179                         s -= removed;
180                         left += removed;
181
182                 } while (1);
183         }
184
185 done:
186         if (myurl != NULL)
187                 free(myurl);
188         if (fd != -1)
189                 close(fd);
190         return rtop;
191 }