1/*
2 * Copyright 2004, ASUSTek Inc.
3 * All Rights Reserved.
4 *
5 * THIS SOFTWARE IS OFFERED "AS IS", AND ASUS GRANTS NO WARRANTIES OF ANY
6 * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
7 * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
8 * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
9 *
10 * $Id: http_ex.c,v 1.2 2008/10/24 03:32:30 james26_jang Exp $
11 */
12
13#include <stdio.h>
14#include <stdlib.h>
15#include <limits.h>
16#include <ctype.h>
17#include <string.h>
18#include <signal.h>
19#include <time.h>
20#include <unistd.h>
21#include <errno.h>
22#include <sys/socket.h>
23#include <netinet/in.h>
24#include <arpa/inet.h>
25#include <sys/types.h>
26#include <sys/stat.h>
27#include <fcntl.h>	// 2008.04 for open().
28#include <unistd.h>	// 2008.04 for open().
29
30#include <shutils.h>
31
32#ifdef ASUS
33#define PATH_MAX 256
34#endif
35
36/*#define dprintf printf*/
37
38static char *
39base64enc(const char *p, char *buf, int len)
40{
41        char al[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
42		"0123456789+/";
43	char *s = buf;
44
45        while(*p) {
46		if (s >= buf+len-4)
47			break;
48                *(s++) = al[(*p >> 2) & 0x3F];
49                *(s++) = al[((*p << 4) & 0x30) | ((*(p+1) >> 4) & 0x0F)];
50                *s = *(s+1) = '=';
51                *(s+2) = 0;
52                if (! *(++p)) break;
53                *(s++) = al[((*p << 2) & 0x3C) | ((*(p+1) >> 6) & 0x03)];
54                if (! *(++p)) break;
55                *(s++) = al[*(p++) & 0x3F];
56        }
57
58	return buf;
59}
60
61enum {
62	METHOD_GET,
63	METHOD_POST
64};
65
66static int
67waitsock(int fd, int sec, int usec)
68{
69	struct timeval tv;
70	fd_set fdvar;
71	int res;
72
73	FD_ZERO(&fdvar);
74	FD_SET(fd, &fdvar);
75	tv.tv_sec = sec;
76	tv.tv_usec = usec;
77	res = select(fd+1, &fdvar, NULL, NULL, &tv);
78
79	return res;
80}
81
82static int
83wget(int method, const char *server, char *buf, size_t count, off_t offset)
84{
85	char url[PATH_MAX] = { 0 }, *s;
86	char *host = url, *path = "", auth[128] = { 0 }, line[1024];
87	unsigned short port = 80;
88	int fd;
89	FILE *fp;
90	struct sockaddr_in sin;
91	struct stat fstatus;
92
93	int chunked = 0, len = 0;
94
95	if(server == NULL || !strcmp(server, "")){
96		dprintf("wget: null server input\n");
97		return (0);
98	}
99
100	strncpy(url, server, sizeof(url));
101
102	/* Parse URL */
103	if(!strncmp(url, "http://", 7)){
104		port = 80;
105		host = url+7;
106	}
107	if((s = strchr(host, '/'))){
108		*s++ = '\0';
109		path = s;
110	}
111	if((s = strchr(host, '@'))){
112		*s++ = '\0';
113		base64enc(host, auth, sizeof(auth));
114		host = s;
115	}
116	if((s = strchr(host, ':'))){
117		*s++ = '\0';
118		port = atoi(s);
119	}
120
121	/* Open socket */
122	if(!inet_aton(host, &sin.sin_addr))
123		return 0;
124	sin.sin_family = AF_INET;
125	sin.sin_port = htons(port);
126
127	dprintf("Connecting to %s:%u...\n", host, port);
128	if((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0
129			|| connect(fd, (struct sockaddr *)&sin, sizeof(sin)) < 0
130//#ifdef REMOVE
131			|| !(fp = fdopen(fd, "r+"))
132//#endif
133			){
134		perror(host);
135		if(fd >= 0)
136			close(fd);
137		return 0;
138	}
139	dprintf("connected!\n");
140
141	/* Send HTTP request */
142	sprintf(line, "%s /%s HTTP/1.1\r\n", method == METHOD_POST?"POST":"GET", path);
143	sprintf(line, "%sHost: %s\r\n", line, host);
144	sprintf(line, "%sUser-Agent: wget\r\n", line);
145	if(strlen(auth))
146		sprintf(line, "%sAuthorization: Basic %s\r\n", line, auth);
147	if(offset)
148		sprintf(line, "%sRange: bytes=%ld-\r\n", line, offset);
149
150	if(method == METHOD_POST){
151		sprintf(line, "%sContent-Type: application/x-www-form-urlencoded\r\n", line);
152		sprintf(line, "%sContent-Length: %d\r\n\r\n", line, (int)strlen(buf));
153		sprintf(line, "%s%s", line, buf);
154	}
155	else
156		sprintf(line,"%sConnection: close\r\n\r\n", line);
157
158	/* Check HTTP response */
159	dprintf("HTTP request sent, awaiting response..\n");
160	write(fd, line, strlen(line));
161
162	if(waitsock(fd, 2, 0) && read(fd, line, sizeof(line)))
163	{
164		dprintf("%s", line);
165		// get message anyway
166		/*close(fd);
167		return 1;//*/
168//#ifdef REMOVE
169		for(s = line; *s && !isspace((int)*s); s++) ;
170		for(; isspace((int)*s); s++) ;
171		switch(atoi(s)){
172			case 200:
173				if(offset)
174					goto done;
175				else
176					break;
177			case 206:
178				if(offset)
179					break;
180				else
181					goto done;
182			default:
183				goto done;
184		}
185//#endif
186	}
187	else
188	{
189		close(fd);
190		return 0;
191	}
192
193//#ifdef REMOVE
194	/* Parse headers */
195	while(fgets(line, sizeof(line), fp)){
196		dprintf("%s", line);
197		for(s = line; *s == '\r'; s++) ;
198		if(*s == '\n')
199			break;
200		if(!strncasecmp(s, "Content-Length:", 15)){
201			for(s += 15; isblank(*s); s++) ;
202			chomp(s);
203			len = atoi(s);
204		}
205		else if (!strncasecmp(s, "Transfer-Encoding:", 18)) {
206			for(s += 18; isblank(*s); s++) ;
207				chomp(s);
208			if(!strncasecmp(s, "chunked", 7))
209				chunked = 1;
210		}
211	}
212
213	if(chunked && fgets(line, sizeof(line), fp))
214		len = strtol(line, NULL, 16);
215
216	len = (len > count) ? count : len;
217	len = fread(buf, 1, len, fp);
218
219done:
220	/* Close socket */
221	fflush(fp);
222	fclose(fp);
223	return len;
224//#endif
225}
226
227int
228http_check(const char *server, char *buf, size_t count, off_t offset)
229{
230// 2008.04 James. {
231	//return wget(METHOD_GET, server, buf, count, offset);
232
233	char *pid_file = "/var/run/httpd.pid";
234	char pid_buf[10], proc_path[32];
235	int fd, pid;
236	struct stat f_st;
237
238	if((fd = open(pid_file, O_RDONLY)) <= 0)
239		return 0;
240	memset(pid_buf, 0, sizeof(pid_buf));
241	read(fd, pid_buf, sizeof(pid_buf));
242	close(fd);
243	if((pid = atoi(pid_buf)) <= 0)
244		return 0;
245
246	memset(proc_path, 0, sizeof(proc_path));
247	sprintf(proc_path, "/proc/%d", pid);
248
249	lstat(proc_path, &f_st);
250	if(!S_ISDIR(f_st.st_mode))
251		return 0;
252
253	return 1;
254// 2008.04 James. }
255}
256