1#include <stdio.h>
2#include <unistd.h>
3#include <stdlib.h>
4#include <string.h>
5#include <ctype.h>
6#include <limits.h>
7#include <sys/socket.h>
8#include <netinet/in.h>
9#include <netinet/ip.h>
10#include <netinet/ip_icmp.h>
11#include <arpa/inet.h>
12#include <netdb.h>
13#include "shutils.h"
14
15int waitsock(int fd, int sec, int usec){
16	struct timeval tv;
17	fd_set fdvar;
18	int res;
19
20	FD_ZERO(&fdvar);
21	FD_SET(fd, &fdvar);
22	tv.tv_sec = sec;
23	tv.tv_usec = usec;
24	res = select(fd+1, &fdvar, NULL, NULL, &tv);
25
26	return res;
27}
28
29char *base64enc(const char *p, char *buf, int len){
30	char al[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
31	char *s = buf;
32
33	while(*p){
34		if(s >= buf+len-4)
35			break;
36
37		*(s++) = al[(*p>>2)&0x3F];
38		*(s++) = al[((*p<<4)&0x30)|((*(p+1)>>4)&0x0F)];
39		*s = *(s+1) = '=';
40		*(s+2) = 0;
41		if(!*(++p))
42			break;
43		*(s++) = al[((*p<<2)&0x3C)|((*(p+1)>>6)&0x03)];
44		if(!*(++p))
45			break;
46		*(s++) = al[*(p++)&0x3F];
47	}
48
49	return buf;
50}
51
52int wgetToFile(const char *const server, const char *const filename){
53	char url[PATH_MAX], *s;
54	char *host = url, *path = "", auth[128], line[PATH_MAX];
55	unsigned short port = 80;
56	int fd, len = 0;
57	FILE *np, *fp;
58	struct sockaddr_in sin;
59	struct hostent *hostaddr;
60	unsigned long ul_hostip;
61	int i;
62
63	memset(url, 0, PATH_MAX);
64	strncpy(url, server, PATH_MAX);
65
66	// Parse URL
67	if(!strncmp(url, "http://", 7)){
68		port = 80;
69		host = url+7;
70	}
71	if((s = strchr(host, '/'))){
72		*s++ = '\0';
73		path = s;
74	}
75	if((s = strchr(host, '@'))){
76		*s++ = '\0';
77		base64enc(host, auth, sizeof(auth));
78		host = s;
79	}
80	if((s = strchr(host, ':'))){
81		*s++ = '\0';
82		port = atoi(s);
83	}
84	printf("host: %s!\n", host);
85	// Open socket
86	if((ul_hostip = inet_addr(host)) != INADDR_NONE){
87		//printf("1.\n");
88		sin.sin_addr.s_addr = ul_hostip;
89	}
90	else if((hostaddr = gethostbyname(host)) != NULL){
91		//printf("2.\n");
92		memcpy(&sin.sin_addr, hostaddr->h_addr, sizeof(sin.sin_addr));
93	}
94	else{
95		printf("Failed to get host, %s!\n", host);
96		return -1;
97	}
98
99	sin.sin_family = AF_INET;
100	sin.sin_port = htons(port);
101
102	printf("\nConnecting to %s:%u...\n", host, port);
103	if((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0
104			|| connect(fd, (struct sockaddr *)&sin, sizeof(sin)) < 0
105			|| !(np = fdopen(fd, "r"))
106			){
107		perror(host);
108		if(fd >= 0)
109			close(fd);
110		return -1;
111	}
112	printf("connected!\n\n");
113
114	// Send HTTP request
115	memset(line, 0, PATH_MAX);
116	sprintf(line, "GET /%s HTTP/1.0\r\n", path);
117	sprintf(line, "%sUser-Agent: wget\r\n", line);
118	sprintf(line, "%sHost: %s\r\n", line, host);
119	sprintf(line, "%sAccept: */*\r\n", line);
120	if(strlen(auth) > 0)
121		sprintf(line, "%sAuthorization: Basic %s\r\n", line, auth);
122	sprintf(line, "%sConnection: close\r\n\r\n", line);
123	//sprintf(line, "%sConnection: Keep-Alive\r\n\r\n", line);
124
125	// Check HTTP response
126	printf("wrote the request:\n");
127	printf("******************************\n");
128	printf("%s", line);
129	printf("******************************\n");//*/
130	write(fd, line, strlen(line));
131
132	//printf("Got header:\n");
133	//printf("******************************\n");
134	if(waitsock(fd, 2, 0) && fgets(line, sizeof(line), np)){
135		//printf("%s", line);
136		for(s = line; *s && !isspace((int)*s); s++)
137			;
138
139		for(; isspace((int)*s); s++)
140			;
141
142		switch(atoi(s)){
143			case 200:
144				break;
145			case 206:
146				printf("Failed to get the page!\n");
147				goto done;
148			default:
149				printf("Exceptionable error!\n");
150				goto done;
151		}
152	}
153	else{
154		printf("Failed to get the page!\n");
155		close(fd);
156		return -1;
157	}
158
159	while(fgets(line, sizeof(line), np))
160		if(strlen(line) == 2)
161			break;
162	//printf("******************************\n\n");
163	if(line == NULL || strlen(line) <= 0){
164		printf("Failed to get the page!\n");
165		goto done;
166	}
167
168	printf("Got content:\n");
169	//printf("******************************\n");
170	if((fp = fopen(filename, "w+")) != NULL){
171		//printf("Wrote the file, %s...\n", filename);
172		i = 0;
173		while(fgets(line, sizeof(line), np)){
174			//printf("%s", line);
175			//printf("wrote %d rows: ", ++i);
176			fputs(line, fp);
177			//printf("ok!\n");
178		}
179		//printf("Finished!\n");//*/
180		fclose(fp);
181	}
182	//printf("******************************\n\n");
183	printf("Ok!\n");
184
185done:
186	// Close socket
187	fflush(np);
188	fclose(np);
189	return len;
190}
191
192int main(int argc, char *argv[]){
193	if(argc != 3){
194		fprintf(stderr, "usage: wget [url] [outpur file]\n");
195		return -1;
196	}
197
198	wgetToFile(argv[1], argv[2]);
199
200	return 0;
201}
202