File: http.c

package info (click to toggle)
echoping 6.0.2-2
  • links: PTS
  • area: main
  • in suites: lenny
  • size: 7,596 kB
  • ctags: 380
  • sloc: sh: 8,966; ansic: 3,350; makefile: 162
file content (159 lines) | stat: -rw-r--r-- 4,317 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
/* $Id: http.c 394 2007-03-29 20:27:50Z bortz $ */

#include "echoping.h"

#ifdef HTTP
#include "HTParse.h"


char            big_recvline[MAXTOREAD];

char           *
make_http_sendline(char *url, char *host, int port, int nocache)
{
	short           sport = (short) port;
	int             size = 350;	/* Enough? RFC 2616, section 3.2.1 says 255
					 * should be enough, although there is no
					 * hard limit. We reserve more because there 
					 * * are the protocol elements, the HTTP
					 * headers, etc */
	char           *sendline = (char *) malloc(size);
	char           *hostname = (char *) malloc(size);
	char           *cache_directive = "";
	int             result;
#ifdef HTTP10
	if (nocache)
		cache_directive = "Pragma: no-cache\r\n";	/* RFC 1945,
								 * "Hypertext
								 * Transfer Protocol 
								 * * -- HTTP/1.0" */
	result = snprintf(sendline, size,
			  "GET %s HTTP/1.0\r\nUser-Agent: Echoping/%s\r\n%s\r\n",
			  url, VERSION, cache_directive);
#else
	if (nocache) {
		if (nocache == 1)
			cache_directive = "Cache-control: max-age=0\r\n";	/* Simply 
										 * force 
										 * a
										 * recheck 
										 * with 
										 * the
										 * server 
										 */
		else
			cache_directive = "Cache-control: no-cache\r\n";	/* RFC 
										 * 2616 
										 * "Hypertext
										 * Transfer
										 * Protocol --
										 * HTTP/1.1" */
	}
	strncpy(hostname, HTParse(url, "", PARSE_HOST), size);	/* See bug #1688940
								 * to see why we use 
								 * * strNcpy. */
	hostname[size] = '\0';	/* Not added automatically */
	if (!strcmp(hostname, ""))
		snprintf(hostname, size, "%s:%d", host, sport);
	result = snprintf(sendline, size,
			  "GET %s HTTP/1.1\r\nUser-Agent: Echoping/%s\r\nHost: %s\r\nConnection: close\r\n%s\r\n",
			  url, VERSION, hostname, cache_directive);
	free(hostname);
#endif
	if (result >= size)
		err_quit("URL and/or hostname too long(s)");
	return sendline;
}

int
read_from_server(CHANNEL fs, short ssl, boolean accept_redirects)
{
	int             nr = 0;
	int             total = 0;
	char            reply_code;
	int             first_line = TRUE;
	short           body = FALSE;
#ifdef OPENSSL
	int             sslcode;
#endif
	while (!body && !timeout_flag) {
		if (!ssl)
			nr = readline(fs.fs, big_recvline, MAXTOREAD, TRUE);
#ifdef OPENSSL
		else {
			nr = SSL_readline(fs.ssl, big_recvline, MAXTOREAD, TRUE);
			if (nr == -1) {
				sslcode = ERR_get_error();
				err_ret("SSL_readline error: %s",
					ERR_error_string(sslcode, NULL));
			}
		}
#endif
#ifdef GNUTLS
		else
		{
			nr = TLS_readline(fs.tls, big_recvline, MAXTOREAD, TRUE);
			if (nr == -1) {
				err_ret("TLS_readline error: %s",
					gnutls_strerror(nr));
			}
		}
#endif
		/* 
		 * printf ("DEBUG: reading \"%s\"\n (%d chars)\n",
		 * big_recvline, nr);
		 */
		/* 
		 * HTTP replies should be separated by CR-LF. Unfortunately,
		 * some servers send only CR :-(
		 */
		body = ((nr == 2) || (nr == 1));	/* Empty line CR-LF seen */
		if ((nr < 1) && (timeout_flag))	/* Probably a timeout */
			return -1;
		if (nr < 1)
			/* SourceForge bug #109385 */
			/* err_sys ("Error reading HTTP header"); */
			return -1;
		/* 
		 * if ((int) big_recvline[nr-1] == 10) nr--;
		 */
		if (first_line) {
			reply_code = big_recvline[9];	/* 9 because "HTTP/1.x
							 * 200..." */
			if (reply_code != '2'
			    && !(reply_code == '3' && accept_redirects))
				/* 
				 * Status codes beginning with 3 are not
				 * errors See bug #850674 and RFC 2616,
				 * section 10.3
				 */
				err_quit("HTTP error \"%s\"", big_recvline);
		}
		total = total + nr;
		first_line = FALSE;
	}
	/* Read the body */
	if (!ssl)
		nr = readline(fs.fs, big_recvline, MAXTOREAD, FALSE);
#ifdef OPENSSL
	else
		nr = SSL_readline(fs.ssl, big_recvline, MAXTOREAD, FALSE);
#endif
#ifdef GNUTLS
	else
	nr = TLS_readline(fs.tls, big_recvline, MAXTOREAD, FALSE);
#endif
	/* 
	 * printf ("DEBUG: reading body \"%s\"\n (%d chars)\n", big_recvline,
	 * nr);
	 */
	if ((nr < 2) && (timeout_flag))	/* Probably a timeout */
		return -1;
	if (nr < 2)		/* Hmm, if the body is empty, we'll get a * * * * *
				 * * meaningless error message */
		err_sys("Error reading HTTP body");
	total = total + nr;
	return total;		/* How to do if we want only the body's size? */
}

#endif				/* HTTP */