Example #1
0
static size_t readstring (mpg123_string *string, size_t maxlen, int fd)
{
	int err;
	debug2("Attempting readstring on %d for %"SIZE_P" bytes", fd, (size_p)maxlen);
	string->fill = 0;
	while(maxlen == 0 || string->fill < maxlen)
	{
		if(string->size-string->fill < 1)
		if(!mpg123_grow_string(string, string->fill+4096))
		{
			error("Cannot allocate memory for reading.");
			string->fill = 0;
			return 0;
		}
		err = read(fd,string->p+string->fill,1);
		/* Whoa... reading one byte at a time... one could ensure the line break in another way, but more work. */
		if( err == 1)
		{
			string->fill++;
			if(string->p[string->fill-1] == '\n') break;
		}
		else if(errno != EINTR)
		{
			error("Error reading from socket or unexpected EOF.");
			string->fill = 0;
			/* bail out to prevent endless loop */
			return 0;
		}
	}

	if(!mpg123_grow_string(string, string->fill+1))
	{
		string->fill=0;
	}
	else
	{
		string->p[string->fill] = 0;
		string->fill++;
	}
	return string->fill;
}
Example #2
0
size_t readstring (mpg123_string *string, size_t maxlen, FILE *f)
{
	string->fill = 0;
	while(maxlen == 0 || string->fill < maxlen)
	{
		if(string->size-string->fill < 1)
		if(!mpg123_grow_string(string, string->fill+4096))
		{
			error("Cannot allocate memory for reading.");
			string->fill = 0;
			return 0;
		}
		/* Whoa... reading one byte at a time... one could ensure the line break in another way, but more work. */
		if( read(fileno(f),string->p+string->fill,1) == 1)
		{
			string->fill++;
			if(string->p[string->fill-1] == '\n') break;
		}
		else if(errno != EINTR)
		{
			error("Error reading from socket or unexpected EOF.");
			string->fill = 0;
			/* bail out to prevent endless loop */
			return 0;
		}
	}

	if(!mpg123_grow_string(string, string->fill+1))
	{
		string->fill=0;
	}
	else
	{
		string->p[string->fill] = 0;
		string->fill++;
	}
	return string->fill;
}
Example #3
0
int win32_net_http_open(char* url, struct httpdata *hd)
{
	mpg123_string purl, host, port, path;
	mpg123_string request, response, request_url;
	mpg123_string httpauth1;
	ws.local_socket = SOCKET_ERROR;
	int oom  = 0;
	int relocate, numrelocs = 0;
	int got_location = FALSE;
	/*
		workaround for http://www.global24music.com/rautemusik/files/extreme/isdn.pls
		this site's apache gives me a relocation to the same place when I give the port in Host request field
		for the record: Apache/2.0.51 (Fedora)
	*/
	int try_without_port = 0;
	mpg123_init_string(&purl);
	mpg123_init_string(&host);
	mpg123_init_string(&port);
	mpg123_init_string(&path);
	mpg123_init_string(&request);
	mpg123_init_string(&response);
	mpg123_init_string(&request_url);
	mpg123_init_string(&httpauth1);

	/* Get initial info for proxy server. Once. */
	if(hd->proxystate == PROXY_UNKNOWN && !proxy_init(hd)) goto exit;

	if(!translate_url(url, &purl)){ oom=1; goto exit; }

	/* Don't confuse the different auth strings... */
	if(!split_url(&purl, &httpauth1, NULL, NULL, NULL) ){ oom=1; goto exit; }

	/* "GET http://"		11
	 * " HTTP/1.0\r\nUser-Agent: <PACKAGE_NAME>/<PACKAGE_VERSION>\r\n"
	 * 				26 + PACKAGE_NAME + PACKAGE_VERSION
	 * accept header            + accept_length()
	 * "Authorization: Basic \r\n"	23
	 * "\r\n"			 2
	 * ... plus the other predefined header lines
	 */
	/* Just use this estimate as first guess to reduce malloc calls in string library. */
	{
		size_t length_estimate = 62 + strlen(PACKAGE_NAME) + strlen(PACKAGE_VERSION) 
		                       + accept_length() + strlen(CONN_HEAD) + strlen(icy_yes) + purl.fill;
		if(    !mpg123_grow_string(&request, length_estimate)
		    || !mpg123_grow_string(&response,4096) )
		{
			oom=1; goto exit;
		}
	}

	do
	{
		/* Storing the request url, with http:// prepended if needed. */
		/* used to be url here... seemed wrong to me (when loop advanced...) */
		if(strncasecmp(purl.p, "http://", 7) != 0) mpg123_set_string(&request_url, "http://");
		else mpg123_set_string(&request_url, "");

		mpg123_add_string(&request_url, purl.p);

		if (hd->proxystate >= PROXY_HOST)
		{
			/* We will connect to proxy, full URL goes into the request. */
			if(    !mpg123_copy_string(&hd->proxyhost, &host)
			    || !mpg123_copy_string(&hd->proxyport, &port)
			    || !mpg123_set_string(&request, "GET ")
			    || !mpg123_add_string(&request, request_url.p) )
			{
				oom=1; goto exit;
			}
		}
		else
		{
			/* We will connect to the host from the URL and only the path goes into the request. */
			if(!split_url(&purl, NULL, &host, &port, &path)){ oom=1; goto exit; }
			if(    !mpg123_set_string(&request, "GET ")
			    || !mpg123_add_string(&request, path.p) )
			{
				oom=1; goto exit;
			}
		}

		if(!fill_request(&request, &host, &port, &httpauth1, &try_without_port)){ oom=1; goto exit; }

		httpauth1.fill = 0; /* We use the auth data from the URL only once. */
		debug2("attempting to open_connection to %s:%s", host.p, port.p);
		win32_net_open_connection(&host, &port);
		if(ws.local_socket == SOCKET_ERROR)
		{
			error1("Unable to establish connection to %s", host.fill ? host.p : "");
			goto exit;
		}
		debug("win32_net_open_connection succeed");
#define http_failure win32_net_close(ws.local_socket); ws.local_socket=SOCKET_ERROR; goto exit;
		
		if(param.verbose > 2) fprintf(stderr, "HTTP request:\n%s\n",request.p);
		if(!win32_net_writestring(ws.local_socket, &request)){ http_failure; }
		debug("Skipping fdopen for WSA sockets");
		relocate = FALSE;
		/* Arbitrary length limit here... */
#define safe_readstring \
		win32_net_readstring(&response, SIZE_MAX/16, NULL); \
		if(response.fill > SIZE_MAX/16) /* > because of appended zero. */ \
		{ \
			error("HTTP response line exceeds max. length"); \
			http_failure; \
		} \
		else if(response.fill == 0) \
		{ \
			error("readstring failed"); \
			http_failure; \
		} \
		if(param.verbose > 2) fprintf(stderr, "HTTP in: %s", response.p);
		safe_readstring;

		{
			char *sptr;
			if((sptr = strchr(response.p, ' ')))
			{
				if(response.fill > sptr-response.p+2)
				switch (sptr[1])
				{
					case '3':
						relocate = TRUE;
					case '2':
						break;
					default:
						fprintf (stderr, "HTTP request failed: %s", sptr+1); /* '\n' is included */
						http_failure;
				}
				else{ error("Too short response,"); http_failure; }
			}
		}

		/* If we are relocated, we need to look out for a Location header. */
		got_location = FALSE;

		do
		{
			safe_readstring; /* Think about that: Should we really error out when we get nothing? Could be that the server forgot the trailing empty line... */
			if (!strncasecmp(response.p, "Location: ", 10))
			{ /* It is a redirection! */
				if(!win32_net_resolve_redirect(&response, &request_url, &purl)){ oom=1, http_failure; }

				if(!strcmp(purl.p, request_url.p))
				{
					warning("relocated to very same place! trying request again without host port");
					try_without_port = 1;
				}
				got_location = TRUE;
			}
			else
			{ /* We got a header line (or the closing empty line). */
				char *tmp;
				debug1("searching for header values... %s", response.p);
				/* Not sure if I want to bail out on error here. */
				/* Also: What text encoding are these strings in? Doesn't need to be plain ASCII... */
				get_header_string(&response, "content-type", &hd->content_type);
				get_header_string(&response, "icy-name",     &hd->icy_name);
				get_header_string(&response, "icy-url",      &hd->icy_url);

				/* watch out for icy-metaint */
				if((tmp = get_header_val("icy-metaint", &response)))
				{
					hd->icy_interval = (off_t) atol(tmp); /* atoll ? */
					debug1("got icy-metaint %li", (long int)hd->icy_interval);
				}
			}
		} while(response.p[0] != '\r' && response.p[0] != '\n');
	} while(relocate && got_location && purl.fill && numrelocs++ < HTTP_MAX_RELOCATIONS);
	if(relocate)
	{
		if(!got_location)
		error("Server meant to redirect but failed to provide a location!");
		else
		error1("Too many HTTP relocations (%i).", numrelocs);

		http_failure;
	}

exit: /* The end as well as the exception handling point... */
	if(oom) error("Apparently, I ran out of memory or had some bad input data...");

	mpg123_free_string(&purl);
	mpg123_free_string(&host);
	mpg123_free_string(&port);
	mpg123_free_string(&path);
	mpg123_free_string(&request);
	mpg123_free_string(&response);
	mpg123_free_string(&request_url);
	mpg123_free_string(&httpauth1);
	if (ws.local_socket == SOCKET_ERROR || oom)
	return -1;
	else
	return 1;
}