diff options
Diffstat (limited to 'protocols/yahoo/yahoo_httplib.c')
| -rw-r--r-- | protocols/yahoo/yahoo_httplib.c | 339 | 
1 files changed, 155 insertions, 184 deletions
| diff --git a/protocols/yahoo/yahoo_httplib.c b/protocols/yahoo/yahoo_httplib.c index dbbe2a84..6bb8923d 100644 --- a/protocols/yahoo/yahoo_httplib.c +++ b/protocols/yahoo/yahoo_httplib.c @@ -29,14 +29,13 @@  #  define strchr index  #  define strrchr rindex  # endif -char *strchr (), *strrchr (); +char *strchr(), *strrchr();  # if !HAVE_MEMCPY  #  define memcpy(d, s, n) bcopy ((s), (d), (n))  #  define memmove(d, s, n) bcopy ((s), (d), (n))  # endif  #endif -  #include <errno.h>  #ifndef _WIN32  #include <unistd.h> @@ -50,8 +49,6 @@ char *strchr (), *strrchr ();  #include "yahoo_debug.h"  #ifdef __MINGW32__  # include <winsock2.h> -# define write(a,b,c) send(a,b,c,0) -# define read(a,b,c)  recv(a,b,c,0)  # define snprintf _snprintf  #endif @@ -64,7 +61,7 @@ extern struct yahoo_callbacks *yc;  extern enum yahoo_log_level log_level; -int yahoo_tcp_readline(char *ptr, int maxlen, int fd) +int yahoo_tcp_readline(char *ptr, int maxlen, void *fd)  {  	int n, rc;  	char c; @@ -72,11 +69,11 @@ int yahoo_tcp_readline(char *ptr, int maxlen, int fd)  	for (n = 1; n < maxlen; n++) {  		do { -			rc = read(fd, &c, 1); -		} while(rc == -1 && (errno == EINTR || errno == EAGAIN)); /* this is bad - it should be done asynchronously */ +			rc = YAHOO_CALLBACK(ext_yahoo_read) (fd, &c, 1); +		} while (rc == -1 && (errno == EINTR || errno == EAGAIN));	/* this is bad - it should be done asynchronously */  		if (rc == 1) { -			if(c == '\r')			/* get rid of \r */ +			if (c == '\r')	/* get rid of \r */  				continue;  			*ptr = c;  			if (c == '\n') @@ -84,9 +81,9 @@ int yahoo_tcp_readline(char *ptr, int maxlen, int fd)  			ptr++;  		} else if (rc == 0) {  			if (n == 1) -				return (0);		/* EOF, no data */ +				return (0);	/* EOF, no data */  			else -				break;			/* EOF, w/ data */ +				break;	/* EOF, w/ data */  		} else {  			return -1;  		} @@ -97,12 +94,12 @@ int yahoo_tcp_readline(char *ptr, int maxlen, int fd)  }  static int url_to_host_port_path(const char *url, -		char *host, int *port, char *path) +	char *host, int *port, char *path, int *ssl)  { -	char *urlcopy=NULL; -	char *slash=NULL; -	char *colon=NULL; -	 +	char *urlcopy = NULL; +	char *slash = NULL; +	char *colon = NULL; +  	/*  	 * http://hostname  	 * http://hostname/ @@ -112,10 +109,14 @@ static int url_to_host_port_path(const char *url,  	 * http://hostname:port/  	 * http://hostname:port/path  	 * http://hostname:port/path:foo +	 * and https:// variants of the above  	 */ -	if(strstr(url, "http://") == url) { -		urlcopy = strdup(url+7); +	if (strstr(url, "http://") == url) { +		urlcopy = strdup(url + 7); +	} else if (strstr(url, "https://") == url) { +		urlcopy = strdup(url + 8); +		*ssl = 1;  	} else {  		WARNING(("Weird url - unknown protocol: %s", url));  		return 0; @@ -124,14 +125,17 @@ static int url_to_host_port_path(const char *url,  	slash = strchr(urlcopy, '/');  	colon = strchr(urlcopy, ':'); -	if(!colon || (slash && slash < colon)) { -		*port = 80; +	if (!colon || (slash && slash < colon)) { +		if (*ssl) +			*port = 443; +		else +			*port = 80;  	} else {  		*colon = 0; -		*port = atoi(colon+1); +		*port = atoi(colon + 1);  	} -	if(!slash) { +	if (!slash) {  		strcpy(path, "/");  	} else {  		strcpy(path, slash); @@ -139,7 +143,7 @@ static int url_to_host_port_path(const char *url,  	}  	strcpy(host, urlcopy); -	 +  	FREE(urlcopy);  	return 1; @@ -147,135 +151,135 @@ static int url_to_host_port_path(const char *url,  static int isurlchar(unsigned char c)  { -	return (isalnum(c) || '-' == c || '_' == c); +	return (isalnum(c));  }  char *yahoo_urlencode(const char *instr)  { -	int ipos=0, bpos=0; +	int ipos = 0, bpos = 0;  	char *str = NULL;  	int len = strlen(instr); -	if(!(str = y_new(char, 3*len + 1) )) -		return ""; +	if (!(str = y_new(char, 3 *len + 1))) +		 return ""; -	while(instr[ipos]) { -		while(isurlchar(instr[ipos])) +	while (instr[ipos]) { +		while (isurlchar(instr[ipos]))  			str[bpos++] = instr[ipos++]; -		if(!instr[ipos]) +		if (!instr[ipos])  			break; -		 -		snprintf(&str[bpos], 4, "%%%.2x", instr[ipos]); -		bpos+=3; + +		snprintf(&str[bpos], 4, "%%%02x", instr[ipos] & 0xff); +		bpos += 3;  		ipos++;  	} -	str[bpos]='\0'; +	str[bpos] = '\0';  	/* free extra alloc'ed mem. */  	len = strlen(str); -	str = y_renew(char, str, len+1); +	str = y_renew(char, str, len + 1);  	return (str);  }  char *yahoo_urldecode(const char *instr)  { -	int ipos=0, bpos=0; +	int ipos = 0, bpos = 0;  	char *str = NULL; -	char entity[3]={0,0,0}; +	char entity[3] = { 0, 0, 0 };  	unsigned dec;  	int len = strlen(instr); -	if(!(str = y_new(char, len+1) )) -		return ""; +	if (!(str = y_new(char, len + 1))) +		 return ""; -	while(instr[ipos]) { -		while(instr[ipos] && instr[ipos]!='%') -			if(instr[ipos]=='+') { -				str[bpos++]=' '; +	while (instr[ipos]) { +		while (instr[ipos] && instr[ipos] != '%') +			if (instr[ipos] == '+') { +				str[bpos++] = ' ';  				ipos++;  			} else  				str[bpos++] = instr[ipos++]; -		if(!instr[ipos]) +		if (!instr[ipos])  			break; -		 -		if(instr[ipos+1] && instr[ipos+2]) { + +		if (instr[ipos + 1] && instr[ipos + 2]) {  			ipos++; -			entity[0]=instr[ipos++]; -			entity[1]=instr[ipos++]; +			entity[0] = instr[ipos++]; +			entity[1] = instr[ipos++];  			sscanf(entity, "%2x", &dec);  			str[bpos++] = (char)dec;  		} else {  			str[bpos++] = instr[ipos++];  		}  	} -	str[bpos]='\0'; +	str[bpos] = '\0';  	/* free extra alloc'ed mem. */  	len = strlen(str); -	str = y_renew(char, str, len+1); +	str = y_renew(char, str, len + 1);  	return (str);  }  char *yahoo_xmldecode(const char *instr)  { -	int ipos=0, bpos=0, epos=0; +	int ipos = 0, bpos = 0, epos = 0;  	char *str = NULL; -	char entity[4]={0,0,0,0}; -	char *entitymap[5][2]={ -		{"amp;",  "&"},  +	char entity[4] = { 0, 0, 0, 0 }; +	char *entitymap[5][2] = { +		{"amp;", "&"},  		{"quot;", "\""}, -		{"lt;",   "<"},  -		{"gt;",   "<"},  +		{"lt;", "<"}, +		{"gt;", "<"},  		{"nbsp;", " "}  	};  	unsigned dec;  	int len = strlen(instr); -	if(!(str = y_new(char, len+1) )) -		return ""; +	if (!(str = y_new(char, len + 1))) +		 return ""; -	while(instr[ipos]) { -		while(instr[ipos] && instr[ipos]!='&') -			if(instr[ipos]=='+') { -				str[bpos++]=' '; +	while (instr[ipos]) { +		while (instr[ipos] && instr[ipos] != '&') +			if (instr[ipos] == '+') { +				str[bpos++] = ' ';  				ipos++;  			} else  				str[bpos++] = instr[ipos++]; -		if(!instr[ipos] || !instr[ipos+1]) +		if (!instr[ipos] || !instr[ipos + 1])  			break;  		ipos++; -		if(instr[ipos] == '#') { +		if (instr[ipos] == '#') {  			ipos++; -			epos=0; -			while(instr[ipos] != ';') -				entity[epos++]=instr[ipos++]; +			epos = 0; +			while (instr[ipos] != ';') +				entity[epos++] = instr[ipos++];  			sscanf(entity, "%u", &dec);  			str[bpos++] = (char)dec;  			ipos++;  		} else {  			int i; -			for (i=0; i<5; i++)  -				if(!strncmp(instr+ipos, entitymap[i][0],  -					       strlen(entitymap[i][0]))) { -				       	str[bpos++] = entitymap[i][1][0]; +			for (i = 0; i < 5; i++) +				if (!strncmp(instr + ipos, entitymap[i][0], +						strlen(entitymap[i][0]))) { +					str[bpos++] = entitymap[i][1][0];  					ipos += strlen(entitymap[i][0]);  					break;  				}  		}  	} -	str[bpos]='\0'; +	str[bpos] = '\0';  	/* free extra alloc'ed mem. */  	len = strlen(str); -	str = y_renew(char, str, len+1); +	str = y_renew(char, str, len + 1);  	return (str);  } -typedef void (*http_connected)(int id, int fd, int error); +typedef void (*http_connected) (int id, void *fd, int error);  struct callback_data {  	int id; @@ -284,150 +288,117 @@ struct callback_data {  	void *user_data;  }; -static void connect_complete(int fd, int error, void *data) +static void connect_complete(void *fd, int error, void *data)  {  	struct callback_data *ccd = data; -	if(error == 0 && fd > 0) -		write(fd, ccd->request, strlen(ccd->request)); -	FREE(ccd->request); +	if (error == 0) +		YAHOO_CALLBACK(ext_yahoo_write) (fd, ccd->request, +			strlen(ccd->request)); +	free(ccd->request);  	ccd->callback(ccd->id, fd, error, ccd->user_data);  	FREE(ccd);  } -static void yahoo_send_http_request(int id, char *host, int port, char *request,  -		yahoo_get_fd_callback callback, void *data) +static void yahoo_send_http_request(int id, char *host, int port, char *request, +	yahoo_get_fd_callback callback, void *data, int use_ssl)  { -	struct callback_data *ccd=y_new0(struct callback_data, 1); +	struct callback_data *ccd = y_new0(struct callback_data, 1);  	ccd->callback = callback;  	ccd->id = id;  	ccd->request = strdup(request);  	ccd->user_data = data; -	 -	YAHOO_CALLBACK(ext_yahoo_connect_async)(id, host, port, connect_complete, ccd); + +	YAHOO_CALLBACK(ext_yahoo_connect_async) (id, host, port, +		connect_complete, ccd, use_ssl);  } -void yahoo_http_post(int id, const char *url, const char *cookies, long content_length, -		yahoo_get_fd_callback callback, void *data) +void yahoo_http_post(int id, const char *url, const char *cookies, +	long content_length, yahoo_get_fd_callback callback, void *data)  {  	char host[255];  	int port = 80;  	char path[255];  	char buff[1024]; -	 -	if(!url_to_host_port_path(url, host, &port, path)) -		return; +	int ssl = 0; -	snprintf(buff, sizeof(buff),  -			"POST %s HTTP/1.0\r\n" -			"Content-length: %ld\r\n" -			"User-Agent: Mozilla/4.5 [en] (" PACKAGE "/" VERSION ")\r\n" -			"Host: %s:%d\r\n" -			"Cookie: %s\r\n" -			"\r\n", -			path, content_length,  -			host, port, -			cookies); +	if (!url_to_host_port_path(url, host, &port, path, &ssl)) +		return; -	yahoo_send_http_request(id, host, port, buff, callback, data); +	/* thanks to kopete dumpcap */ +	snprintf(buff, sizeof(buff), +		"POST %s HTTP/1.1\r\n" +		"Cookie: %s\r\n" +		"User-Agent: Mozilla/5.0\r\n" +		"Host: %s\r\n" +		"Content-Length: %ld\r\n" +		"Cache-Control: no-cache\r\n" +		"\r\n", path, cookies, host, content_length); + +	yahoo_send_http_request(id, host, port, buff, callback, data, ssl);  } -void yahoo_http_get(int id, const char *url, const char *cookies, -		yahoo_get_fd_callback callback, void *data) +void yahoo_http_get(int id, const char *url, const char *cookies, int http11, +	int keepalive, yahoo_get_fd_callback callback, void *data)  {  	char host[255];  	int port = 80;  	char path[255]; -	char buff[1024]; -	 -	if(!url_to_host_port_path(url, host, &port, path)) -		return; +	char buff[2048]; +	char cookiebuff[1024]; +	int ssl = 0; -	snprintf(buff, sizeof(buff),  -			"GET %s HTTP/1.0\r\n" -			"Host: %s:%d\r\n" -			"User-Agent: Mozilla/4.5 [en] (" PACKAGE "/" VERSION ")\r\n" -			"Cookie: %s\r\n" -			"\r\n", -			path, host, port, cookies); +	if (!url_to_host_port_path(url, host, &port, path, &ssl)) +		return; -	yahoo_send_http_request(id, host, port, buff, callback, data); +	/* Allow cases when we don't need to send a cookie */ +	if (cookies) +		snprintf(cookiebuff, sizeof(cookiebuff), "Cookie: %s\r\n", +			cookies); +	else +		cookiebuff[0] = '\0'; + +	snprintf(buff, sizeof(buff), +		"GET %s HTTP/1.%s\r\n" +		"%sHost: %s\r\n" +		"User-Agent: Mozilla/4.5 [en] (" PACKAGE "/" VERSION ")\r\n" +		"Accept: */*\r\n" +		"%s" "\r\n", path, http11?"1":"0", cookiebuff, host, +		keepalive? "Connection: Keep-Alive\r\n":"Connection: close\r\n"); + +	yahoo_send_http_request(id, host, port, buff, callback, data, ssl);  } -struct url_data { -	yahoo_get_url_handle_callback callback; -	void *user_data; -}; - -static void yahoo_got_url_fd(int id, int fd, int error, void *data) +void yahoo_http_head(int id, const char *url, const char *cookies, int len, +	char *payload, yahoo_get_fd_callback callback, void *data)  { -	char *tmp=NULL; -	char buff[1024]; -	unsigned long filesize=0; -	char *filename=NULL; -	int n; - -	struct url_data *ud = data; +	char host[255]; +	int port = 80; +	char path[255]; +	char buff[2048]; +	char cookiebuff[1024]; +	int ssl = 0; -	if(error || fd < 0) { -		ud->callback(id, fd, error, filename, filesize, ud->user_data); -		FREE(ud); +	if (!url_to_host_port_path(url, host, &port, path, &ssl))  		return; -	} - -	while((n=yahoo_tcp_readline(buff, sizeof(buff), fd)) > 0) { -		LOG(("Read:%s:\n", buff)); -		if(!strcmp(buff, "")) -			break; - -		if( !strncasecmp(buff, "Content-length:",  -				strlen("Content-length:")) ) { -			tmp = strrchr(buff, ' '); -			if(tmp) -				filesize = atol(tmp); -		} - -		if( !strncasecmp(buff, "Content-disposition:",  -				strlen("Content-disposition:")) ) { -			tmp = strstr(buff, "name="); -			if(tmp) { -				tmp+=strlen("name="); -				if(tmp[0] == '"') { -					char *tmp2; -					tmp++; -					tmp2 = strchr(tmp, '"'); -					if(tmp2) -						*tmp2 = '\0'; -				} else { -					char *tmp2; -					tmp2 = strchr(tmp, ';'); -					if(!tmp2) -						tmp2 = strchr(tmp, '\r'); -					if(!tmp2) -						tmp2 = strchr(tmp, '\n'); -					if(tmp2) -						*tmp2 = '\0'; -				} -				filename = strdup(tmp); -			} -		} -	} - -	LOG(("n == %d\n", n)); -	LOG(("Calling callback, filename:%s, size: %ld\n", filename, filesize)); -	ud->callback(id, fd, error, filename, filesize, ud->user_data); -	FREE(ud); -	FREE(filename); -} - -void yahoo_get_url_fd(int id, const char *url, const struct yahoo_data *yd, -		yahoo_get_url_handle_callback callback, void *data) -{ -	char buff[1024]; -	struct url_data *ud = y_new0(struct url_data, 1); -	snprintf(buff, sizeof(buff), "Y=%s; T=%s", yd->cookie_y, yd->cookie_t); -	ud->callback = callback; -	ud->user_data = data; -	yahoo_http_get(id, url, buff, yahoo_got_url_fd, ud); +	/* Allow cases when we don't need to send a cookie */ +	if (cookies) +		snprintf(cookiebuff, sizeof(cookiebuff), "Cookie: %s\r\n", +			cookies); +	else +		cookiebuff[0] = '\0'; + +	snprintf(buff, sizeof(buff), +		"HEAD %s HTTP/1.0\r\n" +		"Accept: */*\r\n" +		"Host: %s:%d\r\n" +		"User-Agent: Mozilla/4.5 [en] (" PACKAGE "/" VERSION ")\r\n" +		"%s" +		"Content-Length: %d\r\n" +		"Cache-Control: no-cache\r\n" +		"\r\n%s", path, host, port, cookiebuff, len, +		payload?payload:""); + +	yahoo_send_http_request(id, host, port, buff, callback, data, ssl);  } | 
