46 #include "EST_socket.h"
48 #include <sys/types.h>
50 #include "EST_String.h"
56 EST_Regex RxURL(
"\\([a-z]+\\)://?\\([^/:]+\\)\\(:\\([0-9]+\\)\\)?\\(.*\\)");
58 static EST_Regex ipnum(
"[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+");
60 const int default_http_port = 80;
63 #define MAX_LINE_LENGTH (256)
65 static int port_to_int(
const char *port)
69 if (!port || *port ==
'\0')
72 if ((serv=getservbyname(port,
"tcp")))
85 int start_of_bracket[EST_Regex_max_subexpressions];
86 int end_of_bracket[EST_Regex_max_subexpressions];
88 if (url.
matches(RxFILEURL,0,start_of_bracket, end_of_bracket))
93 path = url.
after(
"file:");
96 else if (!url.
matches(RxURL, 0, start_of_bracket, end_of_bracket))
99 protocol = url.
at(start_of_bracket[1], end_of_bracket[1]-start_of_bracket[1]);
100 host = url.
at(start_of_bracket[2], end_of_bracket[2]-start_of_bracket[2]);
101 port = url.
at(start_of_bracket[4], end_of_bracket[4]-start_of_bracket[4]);
102 bitpath = url.
at(start_of_bracket[5], end_of_bracket[5]-start_of_bracket[5]);
104 if (protocol ==
"http")
105 path = protocol +
"://" + host + bitpath;
112 static int connect_to_server(
const char *host,
int port)
114 struct sockaddr_in address;
115 struct hostent *hostentp;
119 memset(&address, 0,
sizeof(address));
123 address.sin_addr.s_addr = inet_addr(host);
124 address.sin_family = AF_INET;
126 else if ((hostentp=gethostbyname(host))==NULL)
127 err(
"can't find host", host);
130 memset(&(address.sin_addr),0,
sizeof(
struct in_addr));
131 address.sin_family=hostentp->h_addrtype;
132 memmove(&address.sin_addr,
133 (hostentp->h_addr_list)[0],
136 address.sin_port=htons(port);
138 if ((s=socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
139 err(
"can't create socket", NIL);
141 if (connect(s, (
struct sockaddr *)&address,
sizeof(address)) < 0)
144 err(
"can't connect to host",
145 inet_ntoa(address.sin_addr));
151 static void server_send(
int s,
const char *text)
153 size_t n=strlen(text);
157 if ((sent = write(s, text, n))<0)
158 err(
"error talking to server", NIL);
163 static const char *server_get_line(
int s)
165 static char buffer[MAX_LINE_LENGTH+1];
172 if ((n=read(s, p, 1)) == 0)
175 err(
"error while reading from server", NIL);
176 else if (*(p++) ==
'\n')
189 int fd_open_stdinout(
const char *r_or_w)
193 if (r_or_w[0] ==
'r')
195 else if (r_or_w[0] ==
'w')
198 err(
"mode not understood for -", r_or_w);
207 int fd_open_file(
const char *name,
const char *r_or_w)
213 if (strcmp(name,
"-")==0)
214 return fd_open_stdinout(r_or_w);
216 if (r_or_w[0] ==
'r')
217 if (r_or_w[1] ==
'+' || r_or_w[1] ==
'w')
218 mode = O_RDWR|O_CREAT;
221 else if (r_or_w[0] ==
'w')
222 if (r_or_w[1] ==
'+')
223 mode = O_RDWR|O_CREAT|O_TRUNC;
225 mode = O_WRONLY|O_CREAT|O_TRUNC;
226 else if (r_or_w[0] ==
'a')
227 if (r_or_w[1] ==
'+')
228 go_to_end = mode = O_RDWR;
230 go_to_end = mode = O_WRONLY|O_CREAT;
232 err(
"mode not understood", r_or_w);
237 fd= open(name, mode, 0666);
239 if (fd >=0 && go_to_end)
240 lseek(fd, 0, SEEK_END);
245 int fd_open_http(
const char *host,
253 port=default_http_port;
255 if ((s=connect_to_server(host, port)) < 0)
263 char location[1024] =
"";
265 server_send(s,
"GET ");
266 server_send(s, path);
267 server_send(s,
" HTTP/1.0\n\n");
270 line= server_get_line(s);
272 if (sscanf(line,
"HTTP/%f %d", &http_version, &code) != 2)
275 err(
"HTTP error", line);
279 while((line = server_get_line(s)))
281 if (*line==
'\r' || *line ==
'\n' || *line ==
'\0')
283 else if (sscanf(line,
"Location: %s", location) == 1)
285 cout <<
"redirect to '" << location <<
"'\n";
289 if (code == 301 || code == 302)
293 if (*location ==
'\0')
294 err(
"Redirection to no loction", NIL);
299 if (!parse_url(location, sprotocol, shost, sport, spath))
300 err(
"redirection to bad URL", location);
302 s = fd_open_url(sprotocol, shost, sport, spath,
"rb");
306 else if (*r_or_w ==
'w')
307 err(
"Write to HTTP url not yet implemented", NIL);
312 int fd_open_ftp(
const char *host,
325 int fd_open_tcp(
const char *host,
335 if ((s=connect_to_server(host, port)) < 0)
338 server_send(s, text);
342 else if (*r_or_w ==
'w')
352 int fd_open_url(
const char *protocol,
359 if (strcmp(protocol,
"file") == 0
360 && (!host || *host ==
'\0')
361 && (!port || *port ==
'\0'))
362 return fd_open_file(path, r_or_w);
363 else if (strcmp(protocol,
"file") == 0 || strcmp(protocol,
"ftp") == 0)
364 return fd_open_ftp(host, port_to_int(port), path, r_or_w);
365 else if (strcmp(protocol,
"http") == 0)
366 return fd_open_http(host, port_to_int(port), path, r_or_w);
367 else if (strcmp(protocol,
"tcp") == 0)
368 return fd_open_tcp(host, port_to_int(port), path, r_or_w);