diff options
| -rw-r--r-- | INSTALL | 2 | ||||
| -rw-r--r-- | Makefile | 46 | ||||
| -rw-r--r-- | src/libpiano/request.c | 17 | ||||
| -rw-r--r-- | src/libwaitress/config.h | 1 | ||||
| -rw-r--r-- | src/libwaitress/waitress-test.c | 143 | ||||
| -rw-r--r-- | src/libwaitress/waitress.c | 1240 | ||||
| -rw-r--r-- | src/libwaitress/waitress.h | 136 | ||||
| -rw-r--r-- | src/main.c | 46 | ||||
| -rw-r--r-- | src/main.h | 5 | ||||
| -rw-r--r-- | src/player.h | 1 | ||||
| -rw-r--r-- | src/settings.h | 1 | ||||
| -rw-r--r-- | src/ui.c | 122 | ||||
| -rw-r--r-- | src/ui.h | 5 | ||||
| -rw-r--r-- | src/ui_act.c | 30 | 
14 files changed, 150 insertions, 1645 deletions
| @@ -7,7 +7,7 @@ Dependencies  - gmake  - pthreads  - libao -- gnutls +- libcurl  - gcrypt[1]  - json-c  - libav/ffmpeg[2] @@ -61,21 +61,12 @@ LIBPIANO_OBJ:=${LIBPIANO_SRC:.c=.o}  LIBPIANO_RELOBJ:=${LIBPIANO_SRC:.c=.lo}  LIBPIANO_INCLUDE:=${LIBPIANO_DIR} -LIBWAITRESS_DIR:=src/libwaitress -LIBWAITRESS_SRC:=${LIBWAITRESS_DIR}/waitress.c -LIBWAITRESS_HDR:=\ -		${LIBWAITRESS_DIR}/config.h \ -		${LIBWAITRESS_DIR}/waitress.h -LIBWAITRESS_OBJ:=${LIBWAITRESS_SRC:.c=.o} -LIBWAITRESS_RELOBJ:=${LIBWAITRESS_SRC:.c=.lo} -LIBWAITRESS_INCLUDE:=${LIBWAITRESS_DIR} - -LIBWAITRESS_TEST_SRC=${LIBWAITRESS_DIR}/waitress-test.c -LIBWAITRESS_TEST_OBJ:=${LIBWAITRESS_TEST_SRC:.c=.o} -  LIBAV_CFLAGS=$(shell pkg-config --cflags libavcodec libavformat libavutil libavfilter)  LIBAV_LDFLAGS=$(shell pkg-config --libs libavcodec libavformat libavutil libavfilter) +LIBCURL_CFLAGS=$(shell pkg-config --cflags libcurl) +LIBCURL_LDFLAGS=$(shell pkg-config --libs libcurl) +  LIBGNUTLS_CFLAGS:=$(shell pkg-config --cflags gnutls)  LIBGNUTLS_LDFLAGS:=$(shell pkg-config --libs gnutls) @@ -86,12 +77,12 @@ LIBJSONC_CFLAGS:=$(shell pkg-config --cflags json-c 2>/dev/null || pkg-config --  LIBJSONC_LDFLAGS:=$(shell pkg-config --libs json-c 2>/dev/null || pkg-config --libs json)  # combine all flags -ALL_CFLAGS:=${CFLAGS} -I ${LIBPIANO_INCLUDE} -I ${LIBWAITRESS_INCLUDE} \ +ALL_CFLAGS:=${CFLAGS} -I ${LIBPIANO_INCLUDE} \  			${LIBAV_CFLAGS} ${LIBGNUTLS_CFLAGS} \  			${LIBGCRYPT_CFLAGS} ${LIBJSONC_CFLAGS}  ALL_LDFLAGS:=${LDFLAGS} -lao -lpthread -lm \  			${LIBAV_LDFLAGS} ${LIBGNUTLS_LDFLAGS} \ -			${LIBGCRYPT_LDFLAGS} ${LIBJSONC_LDFLAGS} +			${LIBGCRYPT_LDFLAGS} ${LIBJSONC_LDFLAGS} ${LIBCURL_LDFLAGS}  # build pianobar  ifeq (${DYNLINK},1) @@ -99,28 +90,24 @@ pianobar: ${PIANOBAR_OBJ} ${PIANOBAR_HDR} libpiano.so.0  	@echo "  LINK  $@"  	@${CC} -o $@ ${PIANOBAR_OBJ} -L. -lpiano ${ALL_LDFLAGS}  else -pianobar: ${PIANOBAR_OBJ} ${PIANOBAR_HDR} ${LIBPIANO_OBJ} ${LIBWAITRESS_OBJ} \ -		${LIBWAITRESS_HDR} +pianobar: ${PIANOBAR_OBJ} ${PIANOBAR_HDR} ${LIBPIANO_OBJ}  	@echo "  LINK  $@" -	@${CC} -o $@ ${PIANOBAR_OBJ} ${LIBPIANO_OBJ} ${LIBWAITRESS_OBJ} \ -			${ALL_LDFLAGS} +	@${CC} -o $@ ${PIANOBAR_OBJ} ${LIBPIANO_OBJ} ${ALL_LDFLAGS}  endif  # build shared and static libpiano -libpiano.so.0: ${LIBPIANO_RELOBJ} ${LIBPIANO_HDR} ${LIBWAITRESS_RELOBJ} \ -		${LIBWAITRESS_HDR} ${LIBPIANO_OBJ} ${LIBWAITRESS_OBJ} +libpiano.so.0: ${LIBPIANO_RELOBJ} ${LIBPIANO_HDR} ${LIBPIANO_OBJ}  	@echo "  LINK  $@"  	@${CC} -shared -Wl,-soname,libpiano.so.0 -o libpiano.so.0.0.0 \ -			${LIBPIANO_RELOBJ} ${LIBWAITRESS_RELOBJ} ${ALL_LDFLAGS} +			${LIBPIANO_RELOBJ} ${ALL_LDFLAGS}  	@ln -s libpiano.so.0.0.0 libpiano.so.0  	@ln -s libpiano.so.0 libpiano.so  	@echo "    AR  libpiano.a" -	@${AR} rcs libpiano.a ${LIBPIANO_OBJ} ${LIBWAITRESS_OBJ} +	@${AR} rcs libpiano.a ${LIBPIANO_OBJ}  -include $(PIANOBAR_SRC:.c=.d)  -include $(LIBPIANO_SRC:.c=.d) --include $(LIBWAITRESS_SRC:.c=.d)  # build standard object files  %.o: %.c @@ -134,19 +121,12 @@ libpiano.so.0: ${LIBPIANO_RELOBJ} ${LIBPIANO_HDR} ${LIBWAITRESS_RELOBJ} \  clean:  	@echo " CLEAN" -	@${RM} ${PIANOBAR_OBJ} ${LIBPIANO_OBJ} ${LIBWAITRESS_OBJ} ${LIBWAITRESS_OBJ}/test.o \ -			${LIBPIANO_RELOBJ} ${LIBWAITRESS_RELOBJ} pianobar libpiano.so* \ -			libpiano.a waitress-test $(PIANOBAR_SRC:.c=.d) $(LIBPIANO_SRC:.c=.d) \ -			$(LIBWAITRESS_SRC:.c=.d) +	@${RM} ${PIANOBAR_OBJ} ${LIBPIANO_OBJ} \ +			${LIBPIANO_RELOBJ} pianobar libpiano.so* \ +			libpiano.a $(PIANOBAR_SRC:.c=.d) $(LIBPIANO_SRC:.c=.d)  all: pianobar -waitress-test: ${LIBWAITRESS_TEST_OBJ} -	${CC} ${LDFLAGS} ${LIBWAITRESS_TEST_OBJ} ${LIBGNUTLS_LDFLAGS} -o waitress-test - -test: waitress-test -	./waitress-test -  ifeq (${DYNLINK},1)  install: pianobar install-libpiano  else diff --git a/src/libpiano/request.c b/src/libpiano/request.c index 6d0c8e5..cad0907 100644 --- a/src/libpiano/request.c +++ b/src/libpiano/request.c @@ -26,12 +26,11 @@ THE SOFTWARE.  #define _DARWIN_C_SOURCE /* strdup() on OS X */  #endif +#include <curl/curl.h>  #include <json.h>  #include <assert.h>  #include <stdio.h>  #include <string.h> -/* needed for urlencode */ -#include <waitress.h>  #include "piano.h"  #include "crypt.h" @@ -100,13 +99,16 @@ PianoReturn_t PianoRequest (PianoHandle_t *ph, PianoRequest_t *req,  					json_object_object_add (j, "syncTime",  							json_object_new_int (timestamp)); -					urlencAuthToken = WaitressUrlEncode (ph->partner.authToken); +					CURL * const curl = curl_easy_init (); +					urlencAuthToken = curl_easy_escape (curl, +							ph->partner.authToken, 0);  					assert (urlencAuthToken != NULL);  					snprintf (req->urlPath, sizeof (req->urlPath),  							PIANO_RPC_PATH "method=auth.userLogin&"  							"auth_token=%s&partner_id=%i", urlencAuthToken,  							ph->partner.id); -					free (urlencAuthToken); +					curl_free (urlencAuthToken); +					curl_easy_cleanup (curl);  					break;  				} @@ -432,14 +434,17 @@ PianoReturn_t PianoRequest (PianoHandle_t *ph, PianoRequest_t *req,  		assert (ph->user.authToken != NULL); -		urlencAuthToken = WaitressUrlEncode (ph->user.authToken); +		CURL * const curl = curl_easy_init (); +		urlencAuthToken = curl_easy_escape (curl, +				ph->user.authToken, 0);  		assert (urlencAuthToken != NULL);  		snprintf (req->urlPath, sizeof (req->urlPath), PIANO_RPC_PATH  				"method=%s&auth_token=%s&partner_id=%i&user_id=%s", method,  				urlencAuthToken, ph->partner.id, ph->user.listenerId); -		free (urlencAuthToken); +		curl_free (urlencAuthToken); +		curl_easy_cleanup (curl);  		json_object_object_add (j, "userAuthToken",  				json_object_new_string (ph->user.authToken)); diff --git a/src/libwaitress/config.h b/src/libwaitress/config.h deleted file mode 100644 index e13fe40..0000000 --- a/src/libwaitress/config.h +++ /dev/null @@ -1 +0,0 @@ -#define PACKAGE "libwaitress" diff --git a/src/libwaitress/waitress-test.c b/src/libwaitress/waitress-test.c deleted file mode 100644 index 8cc3e3a..0000000 --- a/src/libwaitress/waitress-test.c +++ /dev/null @@ -1,143 +0,0 @@ -/* -Copyright (c) 2009-2013 -	Lars-Dominik Braun <lars@6xq.net> - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -*/ - -/* test cases for libwaitress */ - -/* we are testing static methods and therefore have to include the .c */ -#include "waitress.c" - -#include <stdio.h> -#include <stdbool.h> -#include <string.h> - -#define streq(a,b) (strcmp(a,b) == 0) - -/*	string equality test (memory location or content) - */ -static bool streqtest (const char *x, const char *y) { -	return (x == y) || (x != NULL && y != NULL && streq (x, y)); -} - -/*	test WaitressSplitUrl - *	@param tested url - *	@param expected user - *	@param expected password - *	@param expected host - *	@param expected port - *	@param expected path - */ -static void compareUrl (const char *url, const char *user, -		const char *password, const char *host, const char *port, -		const char *path) { -	WaitressUrl_t splitUrl; - -	memset (&splitUrl, 0, sizeof (splitUrl)); - -	WaitressSplitUrl (url, &splitUrl); - -	bool userTest, passwordTest, hostTest, portTest, pathTest, overallTest; - -	userTest = streqtest (splitUrl.user, user); -	passwordTest = streqtest (splitUrl.password, password); -	hostTest = streqtest (splitUrl.host, host); -	portTest = streqtest (splitUrl.port, port); -	pathTest = streqtest (splitUrl.path, path); - -	overallTest = userTest && passwordTest && hostTest && portTest && pathTest; - -	if (!overallTest) { -		printf ("FAILED test(s) for %s\n", url); -		if (!userTest) { -			printf ("user: %s vs %s\n", splitUrl.user, user); -		} -		if (!passwordTest) { -			printf ("password: %s vs %s\n", splitUrl.password, password); -		} -		if (!hostTest) { -			printf ("host: %s vs %s\n", splitUrl.host, host); -		} -		if (!portTest) { -			printf ("port: %s vs %s\n", splitUrl.port, port); -		} -		if (!pathTest) { -			printf ("path: %s vs %s\n", splitUrl.path, path); -		} -	} else { -		printf ("OK for %s\n", url); -	} -} - -/*	compare two strings - */ -void compareStr (const char *result, const char *expected) { -	if (!streq (result, expected)) { -		printf ("FAIL for %s, result was %s\n", expected, result); -	} else { -		printf ("OK for %s\n", expected); -	} -} - -/*	test entry point - */ -int main () { -	/* WaitressSplitUrl tests */ -	compareUrl ("http://www.example.com/", NULL, NULL, "www.example.com", NULL, -			""); -	compareUrl ("http://www.example.com", NULL, NULL, "www.example.com", NULL, -			NULL); -	compareUrl ("http://www.example.com:80/", NULL, NULL, "www.example.com", -			"80", ""); -	compareUrl ("http://www.example.com:/", NULL, NULL, "www.example.com", "", -			""); -	compareUrl ("http://:80/", NULL, NULL, "", "80", ""); -	compareUrl ("http://www.example.com/foobar/barbaz", NULL, NULL, -			"www.example.com", NULL, "foobar/barbaz"); -	compareUrl ("http://www.example.com:80/foobar/barbaz", NULL, NULL, -			"www.example.com", "80", "foobar/barbaz"); -	compareUrl ("http://foo:bar@www.example.com:80/foobar/barbaz", "foo", "bar", -			"www.example.com", "80", "foobar/barbaz"); -	compareUrl ("http://foo:@www.example.com:80/foobar/barbaz", "foo", "", -			"www.example.com", "80", "foobar/barbaz"); -	compareUrl ("http://foo@www.example.com:80/foobar/barbaz", "foo", NULL, -			"www.example.com", "80", "foobar/barbaz"); -	compareUrl ("http://:foo@www.example.com:80/foobar/barbaz", "", "foo", -			"www.example.com", "80", "foobar/barbaz"); -	compareUrl ("http://:@:80", "", "", "", "80", NULL); -	compareUrl ("http://", NULL, NULL, NULL, NULL, NULL); -	compareUrl ("http:///", NULL, NULL, "", NULL, ""); -	compareUrl ("http://foo:bar@", "foo", "bar", "", NULL, NULL); - -	/* WaitressBase64Encode tests */ -	compareStr (WaitressBase64Encode ("M"), "TQ=="); -	compareStr (WaitressBase64Encode ("Ma"), "TWE="); -	compareStr (WaitressBase64Encode ("Man"), "TWFu"); -	compareStr (WaitressBase64Encode ("The quick brown fox jumped over the lazy dog."), -			"VGhlIHF1aWNrIGJyb3duIGZveCBqdW1wZWQgb3ZlciB0aGUgbGF6eSBkb2cu"); -	compareStr (WaitressBase64Encode ("The quick brown fox jumped over the lazy dog"), -			"VGhlIHF1aWNrIGJyb3duIGZveCBqdW1wZWQgb3ZlciB0aGUgbGF6eSBkb2c="); -	compareStr (WaitressBase64Encode ("The quick brown fox jumped over the lazy do"), -			"VGhlIHF1aWNrIGJyb3duIGZveCBqdW1wZWQgb3ZlciB0aGUgbGF6eSBkbw=="); - -	return EXIT_SUCCESS; -} - diff --git a/src/libwaitress/waitress.c b/src/libwaitress/waitress.c deleted file mode 100644 index 62e06a0..0000000 --- a/src/libwaitress/waitress.c +++ /dev/null @@ -1,1240 +0,0 @@ -/* -Copyright (c) 2009-2013 -	Lars-Dominik Braun <lars@6xq.net> - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -*/ - -#ifndef __FreeBSD__ -#define _POSIX_C_SOURCE 1 /* required by getaddrinfo() */ -#define _BSD_SOURCE /* snprintf() */ -#define _DARWIN_C_SOURCE /* snprintf() on OS X */ -#endif - -#include <sys/types.h> -#include <sys/socket.h> -#include <netdb.h> -#include <string.h> -#include <unistd.h> -#include <stdio.h> -#include <stdlib.h> -#include <ctype.h> -#include <fcntl.h> -#include <poll.h> -#include <errno.h> -#include <assert.h> -#include <stdint.h> - -#include <gnutls/x509.h> - -#include "config.h" -#include "waitress.h" - -#define strcaseeq(a,b) (strcasecmp(a,b) == 0) -#define WAITRESS_HTTP_VERSION "1.1" - -typedef struct { -	char *data; -	size_t pos; -} WaitressFetchBufCbBuffer_t; - -static WaitressReturn_t WaitressReceiveHeaders (WaitressHandle_t *, size_t *); - -#define READ_RET(buf, count, size) \ -		if ((wRet = waith->request.read (waith, buf, count, size)) != \ -				WAITRESS_RET_OK) { \ -			return wRet; \ -		} - -#define WRITE_RET(buf, count) \ -		if ((wRet = waith->request.write (waith, buf, count)) != WAITRESS_RET_OK) { \ -			return wRet; \ -		} - -void WaitressInit (WaitressHandle_t *waith) { -	assert (waith != NULL); - -	memset (waith, 0, sizeof (*waith)); -	waith->timeout = 30000; -} - -void WaitressFree (WaitressHandle_t *waith) { -	assert (waith != NULL); - -	free (waith->url.url); -	free (waith->proxy.url); -	memset (waith, 0, sizeof (*waith)); -} - -/*	Proxy set up? - *	@param Waitress handle - *	@return true|false - */ -static bool WaitressProxyEnabled (const WaitressHandle_t *waith) { -	assert (waith != NULL); - -	return waith->proxy.host != NULL; -} - -/*	urlencode post-data - *	@param encode this - *	@return malloc'ed encoded string, don't forget to free it - */ -char *WaitressUrlEncode (const char *in) { -	assert (in != NULL); - -	size_t inLen = strlen (in); -	/* worst case: encode all characters */ -	char *out = calloc (inLen * 3 + 1, sizeof (*in)); -	const char *inPos = in; -	char *outPos = out; - -	while (inPos - in < inLen) { -		if (!isalnum (*inPos) && *inPos != '_' && *inPos != '-' && *inPos != '.') { -			*outPos++ = '%'; -			snprintf (outPos, 3, "%02x", *inPos & 0xff); -			outPos += 2; -		} else { -			/* copy character */ -			*outPos++ = *inPos; -		} -		++inPos; -	} - -	return out; -} - -/*	base64 encode data - *	@param encode this - *	@return malloc'ed string - */ -static char *WaitressBase64Encode (const char *in) { -	assert (in != NULL); - -	size_t inLen = strlen (in); -	char *out, *outPos; -	const char *inPos; -	static const char *alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" -			"abcdefghijklmnopqrstuvwxyz0123456789+/"; -	const size_t alphabetLen = strlen (alphabet); - -	/* worst case is 1.333 */ -	out = malloc ((inLen * 2 + 1) * sizeof (*out)); -	if (out == NULL) { -		return NULL; -	} -	outPos = out; -	inPos = in; - -	while (inLen >= 3) { -		uint8_t idx; - -		idx = ((*inPos) >> 2) & 0x3f; -		assert (idx < alphabetLen); -		*outPos = alphabet[idx]; -		++outPos; - -		idx = ((*inPos) & 0x3) << 4; -		++inPos; -		idx |= ((*inPos) >> 4) & 0xf; -		assert (idx < alphabetLen); -		*outPos = alphabet[idx]; -		++outPos; - -		idx = ((*inPos) & 0xf) << 2; -		++inPos; -		idx |= ((*inPos) >> 6) & 0x3; -		assert (idx < alphabetLen); -		*outPos = alphabet[idx]; -		++outPos; - -		idx = (*inPos) & 0x3f; -		++inPos; -		assert (idx < alphabetLen); -		*outPos = alphabet[idx]; -		++outPos; - -		inLen -= 3; -	} - -	switch (inLen) { -		case 2: { -			uint8_t idx; - -			idx = ((*inPos) >> 2) & 0x3f; -			assert (idx < alphabetLen); -			*outPos = alphabet[idx]; -			++outPos; - -			idx = ((*inPos) & 0x3) << 4; -			++inPos; -			idx |= ((*inPos) >> 4) & 0xf; -			assert (idx < alphabetLen); -			*outPos = alphabet[idx]; -			++outPos; - -			idx = ((*inPos) & 0xf) << 2; -			assert (idx < alphabetLen); -			*outPos = alphabet[idx]; -			++outPos; - -			*outPos = '='; -			++outPos; -			break; -		} - -		case 1: { -			uint8_t idx; - -			idx = ((*inPos) >> 2) & 0x3f; -			assert (idx < alphabetLen); -			*outPos = alphabet[idx]; -			++outPos; - -			idx = ((*inPos) & 0x3) << 4; -			assert (idx < alphabetLen); -			*outPos = alphabet[idx]; -			++outPos; - -			*outPos = '='; -			++outPos; - -			*outPos = '='; -			++outPos; -			break; -		} -	} -	*outPos = '\0'; - -	return out; -} - -/*	Split http url into host, port and path - *	@param url - *	@param returned url struct - *	@return url is a http url? does not say anything about its validity! - */ -static bool WaitressSplitUrl (const char *inurl, WaitressUrl_t *retUrl) { -	assert (inurl != NULL); -	assert (retUrl != NULL); - -	static const char *httpPrefix = "http://"; -	 -	/* is http url? */ -	if (strncmp (httpPrefix, inurl, strlen (httpPrefix)) == 0) { -		enum {FIND_USER, FIND_PASS, FIND_HOST, FIND_PORT, FIND_PATH, DONE} -				state = FIND_USER, newState = FIND_USER; -		char *url, *urlPos, *assignStart; -		const char **assign = NULL; - -		url = strdup (inurl); -		retUrl->url = url; - -		urlPos = url + strlen (httpPrefix); -		assignStart = urlPos; - -		if (*urlPos == '\0') { -			state = DONE; -		} - -		while (state != DONE) { -			const char c = *urlPos; - -			switch (state) { -				case FIND_USER: { -					if (c == ':') { -						assign = &retUrl->user; -						newState = FIND_PASS; -					} else if (c == '@') { -						assign = &retUrl->user; -						newState = FIND_HOST; -					} else if (c == '/') { -						/* not a user */ -						assign = &retUrl->host; -						newState = FIND_PATH; -					} else if (c == '\0') { -						assign = &retUrl->host; -						newState = DONE; -					} -					break; -				} - -				case FIND_PASS: { -					if (c == '@') { -						assign = &retUrl->password; -						newState = FIND_HOST; -					} else if (c == '/') { -						/* not a password */ -						assign = &retUrl->port; -						newState = FIND_PATH; -					} else if (c == '\0') { -						assign = &retUrl->port; -						newState = DONE; -					} -					break; -				} - -				case FIND_HOST: { -					if (c == ':') { -						assign = &retUrl->host; -						newState = FIND_PORT; -					} else if (c == '/') { -						assign = &retUrl->host; -						newState = FIND_PATH; -					} else if (c == '\0') { -						assign = &retUrl->host; -						newState = DONE; -					} -					break; -				} - -				case FIND_PORT: { -					if (c == '/') { -						assign = &retUrl->port; -						newState = FIND_PATH; -					} else if (c == '\0') { -						assign = &retUrl->port; -						newState = DONE; -					} -					break; -				} - -				case FIND_PATH: { -					if (c == '\0') { -						assign = &retUrl->path; -						newState = DONE; -					} -					break; -				} - -				case DONE: -					break; -			} /* end switch */ - -			if (assign != NULL) { -				*assign = assignStart; -				*urlPos = '\0'; -				assignStart = urlPos+1; - -				state = newState; -				assign = NULL; -			} - -			++urlPos; -		} /* end while */ - -		/* fixes for our state machine logic */ -		if (retUrl->user != NULL && retUrl->host == NULL && retUrl->port != NULL) { -			retUrl->host = retUrl->user; -			retUrl->user = NULL; -		} -		return true; -	} /* end if strncmp */ - -	return false; -} - -/*	Parse url and set host, port, path - *	@param Waitress handle - *	@param url: protocol://host:port/path - */ -bool WaitressSetUrl (WaitressHandle_t *waith, const char *url) { -	return WaitressSplitUrl (url, &waith->url); -} - -/*	Set http proxy - *	@param waitress handle - *  @param url, e.g. http://proxy:80/ - */ -bool WaitressSetProxy (WaitressHandle_t *waith, const char *url) { -	return WaitressSplitUrl (url, &waith->proxy); -} - -/*	Callback for WaitressFetchBuf, appends received data to \0-terminated - *	buffer - *	@param received data - *	@param data size - *	@param buffer structure - */ -static WaitressCbReturn_t WaitressFetchBufCb (void *recvData, size_t recvDataSize, -		void *extraData) { -	char *recvBytes = recvData; -	WaitressFetchBufCbBuffer_t *buffer = extraData; - -	if (buffer->data == NULL) { -		if ((buffer->data = malloc (sizeof (*buffer->data) * -				(recvDataSize + 1))) == NULL) { -			return WAITRESS_CB_RET_ERR; -		} -	} else { -		char *newbuf; -		if ((newbuf = realloc (buffer->data, -				sizeof (*buffer->data) * -				(buffer->pos + recvDataSize + 1))) == NULL) { -			free (buffer->data); -			return WAITRESS_CB_RET_ERR; -		} -		buffer->data = newbuf; -	} -	memcpy (buffer->data + buffer->pos, recvBytes, recvDataSize); -	buffer->pos += recvDataSize; -	buffer->data[buffer->pos] = '\0'; - -	return WAITRESS_CB_RET_OK; -} - -/*	Fetch string. Beware! This overwrites your waith->data pointer - *	@param waitress handle - *	@param \0-terminated result buffer, malloced (don't forget to free it - *			yourself) - */ -WaitressReturn_t WaitressFetchBuf (WaitressHandle_t *waith, char **retBuffer) { -	WaitressFetchBufCbBuffer_t buffer; -	WaitressReturn_t wRet; - -	assert (waith != NULL); -	assert (retBuffer != NULL); - -	memset (&buffer, 0, sizeof (buffer)); - -	waith->data = &buffer; -	waith->callback = WaitressFetchBufCb; - -	wRet = WaitressFetchCall (waith); -	*retBuffer = buffer.data; -	return wRet; -} - -/*	poll wrapper that retries after signal interrupts, required for socksify - *	wrapper - */ -static int WaitressPollLoop (int fd, short events, int timeout) { -	int pollres = -1; -	struct pollfd sockpoll = {fd, events, 0}; - -	assert (fd != -1); - -	do { -		errno = 0; -		pollres = poll (&sockpoll, 1, timeout); -	} while (errno == EINTR || errno == EINPROGRESS || errno == EAGAIN); - -	return pollres; -} - -/*	write () wrapper with poll () timeout - *	@param waitress handle - *	@param write buffer - *	@param write count bytes - *	@return number of written bytes or -1 on error - */ -static ssize_t WaitressPollWrite (void *data, const void *buf, size_t count) { -	int pollres = -1; -	ssize_t retSize; -	WaitressHandle_t *waith = data; - -	assert (waith != NULL); -	assert (buf != NULL); - -	/* FIXME: simplify logic */ -	pollres = WaitressPollLoop (waith->request.sockfd, POLLOUT, -			waith->timeout); -	if (pollres == 0) { -		waith->request.readWriteRet = WAITRESS_RET_TIMEOUT; -		return -1; -	} else if (pollres == -1) { -		waith->request.readWriteRet = WAITRESS_RET_ERR; -		return -1; -	} -	if ((retSize = write (waith->request.sockfd, buf, count)) == -1) { -		waith->request.readWriteRet = WAITRESS_RET_ERR; -		return -1; -	} -	waith->request.readWriteRet = WAITRESS_RET_OK; -	return retSize; -} - -static WaitressReturn_t WaitressOrdinaryWrite (void *data, const char *buf, -		const size_t size) { -	WaitressHandle_t *waith = data; - -	WaitressPollWrite (waith, buf, size); -	return waith->request.readWriteRet; -} - -static WaitressReturn_t WaitressGnutlsWrite (void *data, const char *buf, -		const size_t size) { -	WaitressHandle_t *waith = data; - -	if (gnutls_record_send (waith->request.tlsSession, buf, size) < 0) { -		return WAITRESS_RET_TLS_WRITE_ERR; -	} -	return waith->request.readWriteRet; -} - -/*	read () wrapper with poll () timeout - *	@param waitress handle - *	@param write to this buf, not NULL terminated - *	@param buffer size - *	@return number of read bytes or -1 on error - */ -static ssize_t WaitressPollRead (void *data, void *buf, size_t count) { -	int pollres = -1; -	ssize_t retSize; -	WaitressHandle_t *waith = data; - -	assert (waith != NULL); -	assert (buf != NULL); - -	/* FIXME: simplify logic */ -	pollres = WaitressPollLoop (waith->request.sockfd, POLLIN, waith->timeout); -	if (pollres == 0) { -		waith->request.readWriteRet = WAITRESS_RET_TIMEOUT; -		return -1; -	} else if (pollres == -1) { -		waith->request.readWriteRet = WAITRESS_RET_ERR; -		return -1; -	} -	if ((retSize = read (waith->request.sockfd, buf, count)) == -1) { -		waith->request.readWriteRet = WAITRESS_RET_READ_ERR; -		return -1; -	} -	waith->request.readWriteRet = WAITRESS_RET_OK; -	return retSize; -} - -static WaitressReturn_t WaitressOrdinaryRead (void *data, char *buf, -		const size_t size, size_t *retSize) { -	WaitressHandle_t *waith = data; - -	const ssize_t ret = WaitressPollRead (waith, buf, size); -	if (ret != -1) { -		assert (ret >= 0); -		*retSize = (size_t) ret; -	} -	return waith->request.readWriteRet; -} - -static WaitressReturn_t WaitressGnutlsRead (void *data, char *buf, -		const size_t size, size_t *retSize) { -	WaitressHandle_t *waith = data; - -	ssize_t ret = gnutls_record_recv (waith->request.tlsSession, buf, size); -	if (ret < 0) { -		return WAITRESS_RET_TLS_READ_ERR; -	} else { -		*retSize = ret; -	} -	return waith->request.readWriteRet; -} - -/*	send basic http authorization - *	@param waitress handle - *	@param url containing user/password - *	@param header name prefix - */ -static bool WaitressFormatAuthorization (WaitressHandle_t *waith, -		WaitressUrl_t *url, const char *prefix, char *writeBuf, -		const size_t writeBufSize) { -	assert (waith != NULL); -	assert (url != NULL); -	assert (prefix != NULL); -	assert (writeBuf != NULL); -	assert (writeBufSize > 0); - -	if (url->user != NULL) { -		char userPass[1024], *encodedUserPass; -		snprintf (userPass, sizeof (userPass), "%s:%s", url->user, -				(url->password != NULL) ? url->password : ""); -		encodedUserPass = WaitressBase64Encode (userPass); -		assert (encodedUserPass != NULL); -		snprintf (writeBuf, writeBufSize, "%sAuthorization: Basic %s\r\n", -				prefix, encodedUserPass); -		free (encodedUserPass); -		return true; -	} -	return false; -} - -/*	get default http port if none was given - */ -static const char *WaitressDefaultPort (const WaitressUrl_t * const url) { -	assert (url != NULL); - -	if (url->tls) { -		return url->tlsPort == NULL ? "443" : url->tlsPort; -	} else { -		return url->port == NULL ? "80" : url->port; -	} -} - -/*	get line from string - *	@param string beginning/return value of last call - *	@return start of _next_ line or NULL if there is no next line - */ -static char *WaitressGetline (char * const str) { -	char *eol; - -	assert (str != NULL); - -	eol = strchr (str, '\n'); -	if (eol == NULL) { -		return NULL; -	} - -	/* make lines parseable by string routines */ -	*eol = '\0'; -	if (eol-1 >= str && *(eol-1) == '\r') { -		*(eol-1) = '\0'; -	} -	/* skip \0 */ -	++eol; - -	assert (eol >= str); - -	return eol; -} - -/*	identity encoding handler - */ -static WaitressHandlerReturn_t WaitressHandleIdentity (void *data, char *buf, -		const size_t size) { -	assert (data != NULL); -	assert (buf != NULL); - -	WaitressHandle_t *waith = data; - -	waith->request.contentReceived += size; -	if (waith->callback (buf, size, waith->data) == WAITRESS_CB_RET_ERR) { -		return WAITRESS_HANDLER_ABORTED; -	} else { -		return WAITRESS_HANDLER_CONTINUE; -	} -} - -/*	chunked encoding handler - */ -static WaitressHandlerReturn_t WaitressHandleChunked (void *data, char *buf, -		const size_t size) { -	assert (data != NULL); -	assert (buf != NULL); - -	WaitressHandle_t * const waith = data; -	size_t pos = 0; - -	while (pos < size) { -		switch (waith->request.chunkedState) { -			case CHUNKSIZE: -				/* Poor man’s hex to integer. This avoids another buffer that -				 * fills until the terminating \r\n is received. */ -				if (buf[pos] >= '0' && buf[pos] <= '9') { -					waith->request.chunkSize <<= 4; -					waith->request.chunkSize |= buf[pos] & 0xf; -				} else if (buf[pos] >= 'a' && buf[pos] <= 'f') { -					waith->request.chunkSize <<= 4; -					waith->request.chunkSize |= (buf[pos]+9) & 0xf; -				} else if (buf[pos] == '\r') { -					/* ignore */ -				} else if (buf[pos] == '\n') { -					waith->request.chunkedState = DATA; -					/* last chunk has size 0 */ -					if (waith->request.chunkSize == 0) { -						return WAITRESS_HANDLER_DONE; -					} -				} else { -					/* everything else is a protocol violation */ -					return WAITRESS_HANDLER_ERR; -				} -				++pos; -				break; - -			case DATA: -				if (waith->request.chunkSize > 0) { -					assert (size >= pos); -					size_t payloadSize = size - pos; - -					if (payloadSize > waith->request.chunkSize) { -						payloadSize = waith->request.chunkSize; -					} -					if (WaitressHandleIdentity (waith, &buf[pos], -							payloadSize) == WAITRESS_HANDLER_ABORTED) { -						return WAITRESS_HANDLER_ABORTED; -					} -					pos += payloadSize; -					assert (waith->request.chunkSize >= payloadSize); -					waith->request.chunkSize -= payloadSize; -				} else { -					/* next chunk size starts in the next line */ -					if (buf[pos] == '\n') { -						waith->request.chunkedState = CHUNKSIZE; -					} -					++pos; -				} -				break; -		} -	} - -	return WAITRESS_HANDLER_CONTINUE; -} - -/*	handle http header - */ -static void WaitressHandleHeader (WaitressHandle_t *waith, const char * const key, -		const char * const value) { -	assert (waith != NULL); -	assert (key != NULL); -	assert (value != NULL); - -	if (strcaseeq (key, "Content-Length")) { -		waith->request.contentLength = atol (value); -		waith->request.contentLengthKnown = true; -	} else if (strcaseeq (key, "Transfer-Encoding")) { -		if (strcaseeq (value, "chunked")) { -			waith->request.dataHandler = WaitressHandleChunked; -		} -	} -} - -/*	parse http status line and return status code - */ -static int WaitressParseStatusline (const char * const line) { -	char status[4] = "000"; - -	assert (line != NULL); - -	if (sscanf (line, "HTTP/1.%*1[0-9] %3[0-9] ", status) == 1) { -		return atoi (status); -	} -	return -1; -} - -/*	verify server certificate - */ -static WaitressReturn_t WaitressTlsVerify (const WaitressHandle_t *waith) { -	gnutls_session_t session = waith->request.tlsSession; -	unsigned int certListSize; -	const gnutls_datum_t *certList; -	gnutls_x509_crt_t cert; - -	if (gnutls_certificate_type_get (session) != GNUTLS_CRT_X509) { -		return WAITRESS_RET_TLS_HANDSHAKE_ERR; -	} - -	if ((certList = gnutls_certificate_get_peers (session, -			&certListSize)) == NULL) { -		return WAITRESS_RET_TLS_HANDSHAKE_ERR; -	} - -	if (gnutls_x509_crt_init (&cert) != GNUTLS_E_SUCCESS) { -		return WAITRESS_RET_TLS_HANDSHAKE_ERR; -	} - -	if (gnutls_x509_crt_import (cert, &certList[0], -			GNUTLS_X509_FMT_DER) != GNUTLS_E_SUCCESS) { -		return WAITRESS_RET_TLS_HANDSHAKE_ERR; -	} - -	char fingerprint[20]; -	size_t fingerprintSize = sizeof (fingerprint); -	if (gnutls_x509_crt_get_fingerprint (cert, GNUTLS_DIG_SHA1, fingerprint, -			&fingerprintSize) != 0) { -		return WAITRESS_RET_TLS_HANDSHAKE_ERR; -	} - -	assert (waith->tlsFingerprint != NULL); -	if (memcmp (fingerprint, waith->tlsFingerprint, sizeof (fingerprint)) != 0) { -		return WAITRESS_RET_TLS_FINGERPRINT_MISMATCH; -	} - -	gnutls_x509_crt_deinit (cert); - -	return WAITRESS_RET_OK; -} - -/*	Connect to server - */ -static WaitressReturn_t WaitressConnect (WaitressHandle_t *waith) { -	WaitressReturn_t ret; -	struct addrinfo hints, *gares; - -	memset (&hints, 0, sizeof hints); - -	hints.ai_family = AF_UNSPEC; -	hints.ai_socktype = SOCK_STREAM; - -	/* Use proxy? */ -	if (WaitressProxyEnabled (waith)) { -		if (getaddrinfo (waith->proxy.host, -				WaitressDefaultPort (&waith->proxy), &hints, &gares) != 0) { -			return WAITRESS_RET_GETADDR_ERR; -		} -	} else { -		if (getaddrinfo (waith->url.host, -				WaitressDefaultPort (&waith->url), &hints, &gares) != 0) { -			return WAITRESS_RET_GETADDR_ERR; -		} -	} - -	/* try all addresses */ -	for (struct addrinfo *gacurr = gares; gacurr != NULL; -			gacurr = gacurr->ai_next) { -		int sock = -1; - -		ret = WAITRESS_RET_OK; - -		if ((sock = socket (gacurr->ai_family, gacurr->ai_socktype, -				gacurr->ai_protocol)) == -1) { -			ret = WAITRESS_RET_SOCK_ERR; -		} else { -			int pollres; - -			/* we need shorter timeouts for connect() */ -			fcntl (sock, F_SETFL, O_NONBLOCK); - -			/* non-blocking connect will return immediately */ -			connect (sock, gacurr->ai_addr, gacurr->ai_addrlen); - -			pollres = WaitressPollLoop (sock, POLLOUT, waith->timeout); -			if (pollres == 0) { -				ret = WAITRESS_RET_TIMEOUT; -			} else if (pollres == -1) { -				ret = WAITRESS_RET_ERR; -			} else { -				/* check connect () return value */ -				socklen_t pollresSize = sizeof (pollres); -				getsockopt (sock, SOL_SOCKET, SO_ERROR, &pollres, -						&pollresSize); -				if (pollres != 0) { -					ret = WAITRESS_RET_CONNECT_REFUSED; -				} else { -					/* this one is working */ -					waith->request.sockfd = sock; -					break; -				} -			} -			close (sock); -		} -	} - -	freeaddrinfo (gares); -	/* could not connect to any of the addresses */ -	if (ret != WAITRESS_RET_OK) { -		return ret; -	} - -	if (waith->url.tls) { -		WaitressReturn_t wRet; - -		/* set up proxy tunnel */ -		if (WaitressProxyEnabled (waith)) { -			char buf[256]; -			size_t size; - -			snprintf (buf, sizeof (buf), "CONNECT %s:%s HTTP/" -					WAITRESS_HTTP_VERSION "\r\n" -					"Host: %s:%s\r\n" -					"Proxy-Connection: close\r\n", -					waith->url.host, WaitressDefaultPort (&waith->url), -					waith->url.host, WaitressDefaultPort (&waith->url)); -			WRITE_RET (buf, strlen (buf)); - -			/* write authorization headers */ -			if (WaitressFormatAuthorization (waith, &waith->proxy, "Proxy-", -					buf, WAITRESS_BUFFER_SIZE)) { -				WRITE_RET (buf, strlen (buf)); -			} - -			WRITE_RET ("\r\n", 2); - -			if ((wRet = WaitressReceiveHeaders (waith, &size)) != -					WAITRESS_RET_OK) { -				return wRet; -			} -		} - -		/* Ignore return code as connection will likely still succeed */ -		gnutls_server_name_set (waith->request.tlsSession, GNUTLS_NAME_DNS, -				waith->url.host, strlen (waith->url.host)); - -		if (gnutls_handshake (waith->request.tlsSession) != GNUTLS_E_SUCCESS) { -			return WAITRESS_RET_TLS_HANDSHAKE_ERR; -		} - -		if ((wRet = WaitressTlsVerify (waith)) != WAITRESS_RET_OK) { -			return wRet; -		} - -		/* now we can talk encrypted */ -		waith->request.read = WaitressGnutlsRead; -		waith->request.write = WaitressGnutlsWrite; -	} - -	return WAITRESS_RET_OK; -} - -/*	Write http header/post data to socket - */ -static WaitressReturn_t WaitressSendRequest (WaitressHandle_t *waith) { -	assert (waith != NULL); -	assert (waith->request.buf != NULL); - -	const char *path = waith->url.path; -	char * const buf = waith->request.buf; -	WaitressReturn_t wRet = WAITRESS_RET_OK; - -	if (waith->url.path == NULL) { -		/* avoid NULL pointer deref */ -		path = ""; -	} else if (waith->url.path[0] == '/') { -		/* most servers don't like "//" */ -		++path; -	} - -	/* send request */ -	if (WaitressProxyEnabled (waith) && !waith->url.tls) { -		snprintf (buf, WAITRESS_BUFFER_SIZE, -			"%s http://%s:%s/%s HTTP/" WAITRESS_HTTP_VERSION "\r\n" -			"Host: %s\r\nUser-Agent: " PACKAGE "\r\nConnection: Close\r\n", -			(waith->method == WAITRESS_METHOD_GET ? "GET" : "POST"), -			waith->url.host, -			WaitressDefaultPort (&waith->url), path, waith->url.host); -	} else { -		snprintf (buf, WAITRESS_BUFFER_SIZE, -			"%s /%s HTTP/" WAITRESS_HTTP_VERSION "\r\n" -			"Host: %s\r\nUser-Agent: " PACKAGE "\r\nConnection: Close\r\n", -			(waith->method == WAITRESS_METHOD_GET ? "GET" : "POST"), -			path, waith->url.host); -	} -	WRITE_RET (buf, strlen (buf)); - -	if (waith->method == WAITRESS_METHOD_POST && waith->postData != NULL) { -		snprintf (buf, WAITRESS_BUFFER_SIZE, "Content-Length: %zu\r\n", -				strlen (waith->postData)); -		WRITE_RET (buf, strlen (buf)); -	} - -	/* write authorization headers */ -	if (WaitressFormatAuthorization (waith, &waith->url, "", buf, -			WAITRESS_BUFFER_SIZE)) { -		WRITE_RET (buf, strlen (buf)); -	} -	/* don't leak proxy credentials to destination server if tls is used */ -	if (!waith->url.tls && -			WaitressFormatAuthorization (waith, &waith->proxy, "Proxy-", -			buf, WAITRESS_BUFFER_SIZE)) { -		WRITE_RET (buf, strlen (buf)); -	} -	 -	if (waith->extraHeaders != NULL) { -		WRITE_RET (waith->extraHeaders, strlen (waith->extraHeaders)); -	} -	 -	WRITE_RET ("\r\n", 2); - -	if (waith->method == WAITRESS_METHOD_POST && waith->postData != NULL) { -		WRITE_RET (waith->postData, strlen (waith->postData)); -	} - -	return WAITRESS_RET_OK; -} - -/*	receive response headers - *	@param Waitress handle - *	@param return unhandled bytes count in buf - */ -static WaitressReturn_t WaitressReceiveHeaders (WaitressHandle_t *waith, -		size_t *retRemaining) { -	char * const buf = waith->request.buf; -	size_t bufFilled = 0, recvSize = 0; -	char *nextLine = NULL, *thisLine = NULL; -	enum {HDRM_HEAD, HDRM_LINES, HDRM_FINISHED} hdrParseMode = HDRM_HEAD; -	WaitressReturn_t wRet = WAITRESS_RET_OK; - -	/* receive answer */ -	nextLine = buf; -	while (hdrParseMode != HDRM_FINISHED) { -		READ_RET (buf+bufFilled, WAITRESS_BUFFER_SIZE-1 - bufFilled, &recvSize); -		if (recvSize == 0) { -			/* connection closed too early */ -			return WAITRESS_RET_CONNECTION_CLOSED; -		} -		bufFilled += recvSize; -		buf[bufFilled] = '\0'; -		thisLine = buf; - -		/* split */ -		while (hdrParseMode != HDRM_FINISHED && -				(nextLine = WaitressGetline (thisLine)) != NULL) { -			switch (hdrParseMode) { -				/* Status code */ -				case HDRM_HEAD: -					switch (WaitressParseStatusline (thisLine)) { -						case 200: -						case 206: -							hdrParseMode = HDRM_LINES; -							break; - -						case 400: -							return WAITRESS_RET_BAD_REQUEST; -							break; - -						case 403: -							return WAITRESS_RET_FORBIDDEN; -							break; - -						case 404: -							return WAITRESS_RET_NOTFOUND; -							break; - -						case -1: -							/* ignore invalid line */ -							break; - -						default: -							return WAITRESS_RET_STATUS_UNKNOWN; -							break; -					} -					break; - -				/* Everything else, except status code */ -				case HDRM_LINES: -					/* empty line => content starts here */ -					if (*thisLine == '\0') { -						hdrParseMode = HDRM_FINISHED; -					} else { -						/* parse header: "key: value", ignore invalid lines */ -						char *key = thisLine, *val; - -						val = strchr (thisLine, ':'); -						if (val != NULL) { -							*val++ = '\0'; -							while (*val != '\0' && isspace ((unsigned char) *val)) { -								++val; -							} -							WaitressHandleHeader (waith, key, val); -						} -					} -					break; - -				default: -					break; -			} /* end switch */ -			thisLine = nextLine; -		} /* end while strchr */ -		memmove (buf, thisLine, bufFilled-(thisLine-buf)); -		bufFilled -= (thisLine-buf); -	} /* end while hdrParseMode */ - -	*retRemaining = bufFilled; - -	return wRet; -} - -/*	read response header and data - */ -static WaitressReturn_t WaitressReceiveResponse (WaitressHandle_t *waith) { -	assert (waith != NULL); -	assert (waith->request.buf != NULL); - -	char * const buf = waith->request.buf; -	size_t recvSize = 0; -	WaitressReturn_t wRet = WAITRESS_RET_OK; - -	if ((wRet = WaitressReceiveHeaders (waith, &recvSize)) != WAITRESS_RET_OK) { -		return wRet; -	} - -	do { -		/* data must be \0-terminated for chunked handler */ -		buf[recvSize] = '\0'; -		switch (waith->request.dataHandler (waith, buf, recvSize)) { -			case WAITRESS_HANDLER_DONE: -				return WAITRESS_RET_OK; -				break; - -			case WAITRESS_HANDLER_ERR: -				return WAITRESS_RET_DECODING_ERR; -				break; - -			case WAITRESS_HANDLER_ABORTED: -				return WAITRESS_RET_CB_ABORT; -				break; - -			case WAITRESS_HANDLER_CONTINUE: -				/* go on */ -				break; -		} -		if (waith->request.contentLengthKnown && -				waith->request.contentReceived >= waith->request.contentLength) { -			/* don’t call read() again if we know the body’s size and have all -			 * of it already */ -			break; -		} -		READ_RET (buf, WAITRESS_BUFFER_SIZE-1, &recvSize); -	} while (recvSize > 0); - -	return WAITRESS_RET_OK; -} - -/*	Receive data from host and call *callback () - *	@param waitress handle - *	@return WaitressReturn_t - */ -WaitressReturn_t WaitressFetchCall (WaitressHandle_t *waith) { -	WaitressReturn_t wRet = WAITRESS_RET_OK; - -	/* initialize */ -	memset (&waith->request, 0, sizeof (waith->request)); -	waith->request.sockfd = -1; -	waith->request.dataHandler = WaitressHandleIdentity; -	waith->request.read = WaitressOrdinaryRead; -	waith->request.write = WaitressOrdinaryWrite; -	waith->request.contentLengthKnown = false; - -	if (waith->url.tls) { -		gnutls_init (&waith->request.tlsSession, GNUTLS_CLIENT); -		gnutls_set_default_priority (waith->request.tlsSession); - -		gnutls_certificate_allocate_credentials (&waith->tlsCred); -		if (gnutls_credentials_set (waith->request.tlsSession, -				GNUTLS_CRD_CERTIFICATE, -				waith->tlsCred) != GNUTLS_E_SUCCESS) { -			return WAITRESS_RET_ERR; -		} - -		/* set up custom read/write functions */ -		gnutls_transport_set_ptr (waith->request.tlsSession, -				(gnutls_transport_ptr_t) waith); -		gnutls_transport_set_pull_function (waith->request.tlsSession, -				WaitressPollRead); -		gnutls_transport_set_push_function (waith->request.tlsSession, -				WaitressPollWrite); -	} - -	/* buffer is required for connect already */ -	waith->request.buf = malloc (WAITRESS_BUFFER_SIZE * -			sizeof (*waith->request.buf)); - -	/* request */ -	if ((wRet = WaitressConnect (waith)) == WAITRESS_RET_OK) { -		if ((wRet = WaitressSendRequest (waith)) == WAITRESS_RET_OK) { -			wRet = WaitressReceiveResponse (waith); -		} -		if (waith->url.tls) { -			gnutls_bye (waith->request.tlsSession, GNUTLS_SHUT_RDWR); -		} -	} - -	/* cleanup */ -	if (waith->url.tls) { -		gnutls_deinit (waith->request.tlsSession); -		gnutls_certificate_free_credentials (waith->tlsCred); -	} -	if (waith->request.sockfd != -1) { -		close (waith->request.sockfd); -	} -	free (waith->request.buf); - -	if (wRet == WAITRESS_RET_OK && -			waith->request.contentReceived < waith->request.contentLength) { -		return WAITRESS_RET_PARTIAL_FILE; -	} -	return wRet; -} - -const char *WaitressErrorToStr (WaitressReturn_t wRet) { -	switch (wRet) { -		case WAITRESS_RET_OK: -			return "Everything's fine :)"; -			break; - -		case WAITRESS_RET_ERR: -			return "Unknown."; -			break; - -		case WAITRESS_RET_STATUS_UNKNOWN: -			return "Unknown HTTP status code."; -			break; - -		case WAITRESS_RET_NOTFOUND: -			return "File not found."; -			break; -		 -		case WAITRESS_RET_FORBIDDEN: -			return "Forbidden."; -			break; - -		case WAITRESS_RET_CONNECT_REFUSED: -			return "Connection refused."; -			break; - -		case WAITRESS_RET_SOCK_ERR: -			return "Socket error."; -			break; - -		case WAITRESS_RET_GETADDR_ERR: -			return "DNS lookup failed."; -			break; - -		case WAITRESS_RET_CB_ABORT: -			return "Callback aborted request."; -			break; - -		case WAITRESS_RET_PARTIAL_FILE: -			return "Partial file."; -			break; -	 -		case WAITRESS_RET_TIMEOUT: -			return "Timeout."; -			break; - -		case WAITRESS_RET_READ_ERR: -			return "Read error."; -			break; - -		case WAITRESS_RET_CONNECTION_CLOSED: -			return "Connection closed by remote host."; -			break; - -		case WAITRESS_RET_DECODING_ERR: -			return "Invalid encoded data."; -			break; - -		case WAITRESS_RET_TLS_WRITE_ERR: -			return "TLS write failed."; -			break; - -		case WAITRESS_RET_TLS_READ_ERR: -			return "TLS read failed."; -			break; - -		case WAITRESS_RET_TLS_HANDSHAKE_ERR: -			return "TLS handshake failed."; -			break; - -		case WAITRESS_RET_TLS_FINGERPRINT_MISMATCH: -			return "TLS fingerprint mismatch."; -			break; - -		default: -			return "No error message available."; -			break; -	} -} - diff --git a/src/libwaitress/waitress.h b/src/libwaitress/waitress.h deleted file mode 100644 index b17d3c1..0000000 --- a/src/libwaitress/waitress.h +++ /dev/null @@ -1,136 +0,0 @@ -/* -Copyright (c) 2009-2013 -	Lars-Dominik Braun <lars@6xq.net> - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -*/ - -#ifndef SRC_LIBWAITRESS_WAITRESS_H_ZE5NT8JI -#define SRC_LIBWAITRESS_WAITRESS_H_ZE5NT8JI - -#include <stdlib.h> -#include <unistd.h> -#include <stdbool.h> -#include <gnutls/gnutls.h> - -#define WAITRESS_BUFFER_SIZE 10*1024 - -typedef enum { -	WAITRESS_METHOD_GET = 0, -	WAITRESS_METHOD_POST, -} WaitressMethod_t; - -typedef enum { -	WAITRESS_CB_RET_ERR, -	WAITRESS_CB_RET_OK, -} WaitressCbReturn_t; - -typedef enum { -	WAITRESS_HANDLER_CONTINUE, -	WAITRESS_HANDLER_DONE, -	WAITRESS_HANDLER_ERR, -	WAITRESS_HANDLER_ABORTED, -} WaitressHandlerReturn_t; - -typedef struct { -	char *url; /* splitted url, unusable */ -	bool tls; -	const char *user; -	const char *password; -	const char *host; -	const char *port; -	const char *tlsPort; -	const char *path; /* without leading '/' */ -} WaitressUrl_t; - -typedef enum { -	WAITRESS_RET_ERR = 0, -	WAITRESS_RET_OK, -	WAITRESS_RET_CB_ABORT, -	/* http error codes */ -	WAITRESS_RET_STATUS_UNKNOWN, -	WAITRESS_RET_NOTFOUND, -	WAITRESS_RET_FORBIDDEN, -	WAITRESS_RET_BAD_REQUEST, -	/* socket errors */ -	WAITRESS_RET_CONNECT_REFUSED, -	WAITRESS_RET_SOCK_ERR, -	WAITRESS_RET_GETADDR_ERR, -	WAITRESS_RET_TIMEOUT, -	WAITRESS_RET_READ_ERR, -	WAITRESS_RET_CONNECTION_CLOSED, -	WAITRESS_RET_TLS_WRITE_ERR, -	WAITRESS_RET_TLS_READ_ERR, -	/* protocol errors */ -	WAITRESS_RET_PARTIAL_FILE, -	WAITRESS_RET_DECODING_ERR, -	WAITRESS_RET_TLS_HANDSHAKE_ERR, -	WAITRESS_RET_TLS_FINGERPRINT_MISMATCH, -} WaitressReturn_t; - -/*	reusable handle - */ -typedef struct { -	int timeout; -	WaitressMethod_t method; - -	const char *extraHeaders; -	const char *postData; -	/* extra data handed over to callback function */ -	void *data; -	WaitressCbReturn_t (*callback) (void *, size_t, void *); -	const char *tlsFingerprint; - -	WaitressUrl_t url; -	WaitressUrl_t proxy; - -	gnutls_certificate_credentials_t tlsCred; - -	/* per-request data */ -	struct { -		int sockfd; - -		/* temporary return value storage */ -		WaitressReturn_t readWriteRet; - -		size_t contentLength, contentReceived, chunkSize; -		bool contentLengthKnown; -		enum {CHUNKSIZE = 0, DATA = 1} chunkedState; - -		char *buf; -		/* first argument is WaitressHandle_t, but that's not defined yet */ -		WaitressHandlerReturn_t (*dataHandler) (void *, char *, const size_t); -		WaitressReturn_t (*read) (void *, char *, const size_t, size_t *); -		WaitressReturn_t (*write) (void *, const char *, const size_t); - -		gnutls_session_t tlsSession; -	} request; -} WaitressHandle_t; - -void WaitressInit (WaitressHandle_t *); -void WaitressFree (WaitressHandle_t *); -bool WaitressSetProxy (WaitressHandle_t *, const char *); -char *WaitressUrlEncode (const char *); -bool WaitressSetUrl (WaitressHandle_t *, const char *); -WaitressReturn_t WaitressFetchBuf (WaitressHandle_t *, char **); -WaitressReturn_t WaitressFetchCall (WaitressHandle_t *); -const char *WaitressErrorToStr (WaitressReturn_t); - -#endif /* SRC_LIBWAITRESS_WAITRESS_H_ZE5NT8JI */ - @@ -61,33 +61,11 @@ THE SOFTWARE.  #include "ui_dispatch.h"  #include "ui_readline.h" -/*	copy proxy settings to waitress handle - */ -static void BarMainLoadProxy (const BarSettings_t *settings, -		WaitressHandle_t *waith) { -	/* set up proxy (control proxy for non-us citizen or global proxy for poor -	 * firewalled fellows) */ -	if (settings->controlProxy != NULL) { -		/* control proxy overrides global proxy */ -		if (!WaitressSetProxy (waith, settings->controlProxy)) { -			/* if setting proxy fails, url is invalid */ -			BarUiMsg (settings, MSG_ERR, "Control proxy (%s) is invalid!\n", -					 settings->controlProxy); -		} -	} else if (settings->proxy != NULL && strlen (settings->proxy) > 0) { -		if (!WaitressSetProxy (waith, settings->proxy)) { -			/* if setting proxy fails, url is invalid */ -			BarUiMsg (settings, MSG_ERR, "Proxy (%s) is invalid!\n", -					 settings->proxy); -		} -	} -} -  /*	authenticate user   */  static bool BarMainLoginUser (BarApp_t *app) {  	PianoReturn_t pRet; -	WaitressReturn_t wRet; +	CURLcode wRet;  	PianoRequestDataLogin_t reqData;  	bool ret; @@ -188,7 +166,7 @@ static bool BarMainGetLoginCredentials (BarSettings_t *settings,   */  static bool BarMainGetStations (BarApp_t *app) {  	PianoReturn_t pRet; -	WaitressReturn_t wRet; +	CURLcode wRet;  	bool ret;  	BarUiMsg (&app->settings, MSG_INFO, "Get stations... "); @@ -235,7 +213,7 @@ static void BarMainHandleUserInput (BarApp_t *app) {   */  static void BarMainGetPlaylist (BarApp_t *app) {  	PianoReturn_t pRet; -	WaitressReturn_t wRet; +	CURLcode wRet;  	PianoRequestDataGetPlaylist_t reqData;  	reqData.station = app->curStation;  	reqData.quality = app->settings.audioQuality; @@ -288,7 +266,7 @@ static void BarMainStartPlayback (BarApp_t *app, pthread_t *playerThread) {  		/* throw event */  		BarUiStartEventCmd (&app->settings, "songstart",  				app->curStation, curSong, &app->player, app->ph.stations, -				PIANO_RET_OK, WAITRESS_RET_OK); +				PIANO_RET_OK, CURLE_OK);  		/* prevent race condition, mode must _not_ be DEAD if  		 * thread has been started */ @@ -306,7 +284,7 @@ static void BarMainPlayerCleanup (BarApp_t *app, pthread_t *playerThread) {  	BarUiStartEventCmd (&app->settings, "songfinish", app->curStation,  			app->playlist, &app->player, app->ph.stations, PIANO_RET_OK, -			WAITRESS_RET_OK); +			CURLE_OK);  	/* FIXME: pthread_join blocks everything if network connection  	 * is hung up e.g. */ @@ -358,8 +336,6 @@ static void BarMainLoop (BarApp_t *app) {  		return;  	} -	BarMainLoadProxy (&app->settings, &app->waith); -  	if (!BarMainLoginUser (app)) {  		return;  	} @@ -427,7 +403,6 @@ int main (int argc, char **argv) {  	gcry_check_version (NULL);  	gcry_control (GCRYCTL_DISABLE_SECMEM, 0);  	gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0); -	gnutls_global_init ();  	BarPlayerInit ();  	BarSettingsInit (&app.settings); @@ -452,10 +427,9 @@ int main (int argc, char **argv) {  				app.settings.keys[BAR_KS_HELP]);  	} -	WaitressInit (&app.waith); -	app.waith.url.host = app.settings.rpcHost; -	app.waith.url.tlsPort = app.settings.rpcTlsPort; -	app.waith.tlsFingerprint = app.settings.tlsFingerprint; +	curl_global_init (CURL_GLOBAL_DEFAULT); +	app.http = curl_easy_init (); +	assert (app.http != NULL);  	/* init fds */  	FD_ZERO(&app.input.set); @@ -496,9 +470,9 @@ int main (int argc, char **argv) {  	PianoDestroy (&app.ph);  	PianoDestroyPlaylist (app.songHistory);  	PianoDestroyPlaylist (app.playlist); -	WaitressFree (&app.waith); +	curl_easy_cleanup (app.http); +	curl_global_cleanup ();  	BarPlayerDestroy (); -	gnutls_global_deinit ();  	BarSettingsDestroy (&app.settings);  	/* restore terminal attributes, zsh doesn't need this, bash does... */ @@ -24,8 +24,9 @@ THE SOFTWARE.  #ifndef SRC_MAIN_H_4ZGSCG6X  #define SRC_MAIN_H_4ZGSCG6X +#include <curl/curl.h> +  #include <piano.h> -#include <waitress.h>  #include "player.h"  #include "settings.h" @@ -33,7 +34,7 @@ THE SOFTWARE.  typedef struct {  	PianoHandle_t ph; -	WaitressHandle_t waith; +	CURL *http;  	player_t player;  	BarSettings_t settings;  	/* first item is current song */ diff --git a/src/player.h b/src/player.h index 5c60e59..b97f5b2 100644 --- a/src/player.h +++ b/src/player.h @@ -36,7 +36,6 @@ THE SOFTWARE.  #include <libavfilter/avfilter.h>  #include <libavfilter/avfiltergraph.h>  #include <piano.h> -#include <waitress.h>  #include "settings.h"  #include "config.h" diff --git a/src/settings.h b/src/settings.h index b56351e..ae22111 100644 --- a/src/settings.h +++ b/src/settings.h @@ -27,7 +27,6 @@ THE SOFTWARE.  #include <stdbool.h>  #include <piano.h> -#include <waitress.h>  /* update structure in ui_dispatch.h if you add shortcuts here */  typedef enum { @@ -131,32 +131,100 @@ void BarUiMsg (const BarSettings_t *settings, const BarUiMsg_t type,  	fflush (stdout);  } -/*	fetch http resource (post request) - *	@param waitress handle - *	@param piano request (initialized by PianoRequest()) - */ -static WaitressReturn_t BarPianoHttpRequest (WaitressHandle_t *waith, -		PianoRequest_t *req) { -	waith->extraHeaders = "Content-Type: text/plain\r\n"; -	waith->postData = req->postData; -	waith->method = WAITRESS_METHOD_POST; -	waith->url.path = req->urlPath; -	waith->url.tls = req->secure; - -	return WaitressFetchBuf (waith, &req->responseData); +typedef struct { +	char *data; +	size_t pos; +} buffer; + +static size_t httpFetchCb (char *ptr, size_t size, size_t nmemb, +		void *userdata) { +	buffer * const buffer = userdata; +	size_t recvSize = size * nmemb; + +	if (buffer->data == NULL) { +		if ((buffer->data = malloc (sizeof (*buffer->data) * +				(recvSize + 1))) == NULL) { +			return 0; +		} +	} else { +		char *newbuf; +		if ((newbuf = realloc (buffer->data, sizeof (*buffer->data) * +				(buffer->pos + recvSize + 1))) == NULL) { +			free (buffer->data); +			return 0; +		} +		buffer->data = newbuf; +	} +	memcpy (buffer->data + buffer->pos, ptr, recvSize); +	buffer->pos += recvSize; +	buffer->data[buffer->pos] = '\0'; + +	return recvSize; +} + +#define setAndCheck(k,v) \ +	httpret = curl_easy_setopt (http, k, v); \ +	assert (httpret == CURLE_OK); + +static CURLcode BarPianoHttpRequest (CURL * const http, +		const BarSettings_t * const settings, PianoRequest_t * const req) { +	buffer buffer = {NULL, 0}; +	char url[2048]; +	int ret = snprintf (url, sizeof (url), "%s://%s:%s%s", +		req->secure ? "https" : "http", +		settings->rpcHost, +		req->secure ? settings->rpcTlsPort : "80", +		req->urlPath); +	assert (ret >= 0 && ret <= (int) sizeof (url)); + +	curl_easy_reset (http); +	CURLcode httpret; +	setAndCheck (CURLOPT_URL, url); +	setAndCheck (CURLOPT_USERAGENT, PACKAGE "-" VERSION); +	setAndCheck (CURLOPT_POSTFIELDS, req->postData); +	setAndCheck (CURLOPT_WRITEFUNCTION, httpFetchCb); +	setAndCheck (CURLOPT_WRITEDATA, &buffer); +	setAndCheck (CURLOPT_POST, 1); +	setAndCheck (CURLOPT_TIMEOUT, 30); + +	/* set up proxy (control proxy for non-us citizen or global proxy for poor +	 * firewalled fellows) */ +	if (settings->controlProxy != NULL) { +		/* control proxy overrides global proxy */ +		if (curl_easy_setopt (http, CURLOPT_PROXY, +				settings->controlProxy) != CURLE_OK) { +			/* if setting proxy fails, url is invalid */ +			BarUiMsg (settings, MSG_ERR, "Control proxy (%s) is invalid!\n", +					 settings->controlProxy); +		} +	} else if (settings->proxy != NULL && strlen (settings->proxy) > 0) { +		if (curl_easy_setopt (http, CURLOPT_PROXY, +				settings->proxy) != CURLE_OK) { +			/* if setting proxy fails, url is invalid */ +			BarUiMsg (settings, MSG_ERR, "Proxy (%s) is invalid!\n", +					 settings->proxy); +		} +	} + +	struct curl_slist *list = NULL; +	list = curl_slist_append (list, "Content-Type: text/plain"); +	setAndCheck (CURLOPT_HTTPHEADER, list); + +	httpret = curl_easy_perform (http); + +	curl_slist_free_all (list); + +	req->responseData = buffer.data; + +	return httpret;  }  /*	piano wrapper: prepare/execute http request and pass result back to   *	libpiano (updates data structures) - *	@param app handle - *	@param request type - *	@param request data - *	@param stores piano return code - *	@param stores waitress return code   *	@return 1 on success, 0 otherwise   */  int BarUiPianoCall (BarApp_t * const app, PianoRequestType_t type, -		void *data, PianoReturn_t *pRet, WaitressReturn_t *wRet) { +		void *data, PianoReturn_t *pRet, CURLcode *wRet) {  	PianoRequest_t req;  	memset (&req, 0, sizeof (req)); @@ -172,9 +240,10 @@ int BarUiPianoCall (BarApp_t * const app, PianoRequestType_t type,  			return 0;  		} -		*wRet = BarPianoHttpRequest (&app->waith, &req); -		if (*wRet != WAITRESS_RET_OK) { -			BarUiMsg (&app->settings, MSG_NONE, "Network error: %s\n", WaitressErrorToStr (*wRet)); +		*wRet = BarPianoHttpRequest (app->http, &app->settings, &req); +		if (*wRet != CURLE_OK) { +			BarUiMsg (&app->settings, MSG_NONE, "Network error: %s\n", +					curl_easy_strerror (*wRet));  			if (req.responseData != NULL) {  				free (req.responseData);  			} @@ -189,7 +258,7 @@ int BarUiPianoCall (BarApp_t * const app, PianoRequestType_t type,  					type != PIANO_REQUEST_LOGIN) {  				/* reauthenticate */  				PianoReturn_t authpRet; -				WaitressReturn_t authwRet; +				CURLcode authwRet;  				PianoRequestDataLogin_t reqData;  				reqData.user = app->settings.username;  				reqData.password = app->settings.password; @@ -481,7 +550,7 @@ char *BarUiSelectMusicId (BarApp_t *app, PianoStation_t *station,  	if (BarReadlineStr (lineBuf, sizeof (lineBuf), &app->input,  			BAR_RL_DEFAULT) > 0) {  		PianoReturn_t pRet; -		WaitressReturn_t wRet; +		CURLcode wRet;  		PianoRequestDataSearch_t reqData;  		reqData.searchStr = lineBuf; @@ -680,12 +749,11 @@ size_t BarUiListSongs (const BarSettings_t *settings,   *	@param current station   *	@param current song   *	@param piano error-code (PIANO_RET_OK if not applicable) - *	@param waitress error-code (WAITRESS_RET_OK if not applicable)   */  void BarUiStartEventCmd (const BarSettings_t *settings, const char *type,  		const PianoStation_t *curStation, const PianoSong_t *curSong,  		const player_t * const player, PianoStation_t *stations, -                PianoReturn_t pRet, WaitressReturn_t wRet) { +		PianoReturn_t pRet, CURLcode wRet) {  	pid_t chld;  	int pipeFd[2]; @@ -748,7 +816,7 @@ void BarUiStartEventCmd (const BarSettings_t *settings, const char *type,  				pRet,  				PianoErrorToStr (pRet),  				wRet, -				WaitressErrorToStr (wRet), +				curl_easy_strerror (wRet),  				player->songDuration,  				player->songPlayed,  				curSong == NULL ? PIANO_RATE_NONE : curSong->rating, @@ -27,7 +27,6 @@ THE SOFTWARE.  #include <stdbool.h>  #include <piano.h> -#include <waitress.h>  #include "settings.h"  #include "player.h" @@ -50,9 +49,9 @@ void BarUiPrintSong (const BarSettings_t *, const PianoSong_t *,  size_t BarUiListSongs (const BarSettings_t *, const PianoSong_t *, const char *);  void BarUiStartEventCmd (const BarSettings_t *, const char *,  		const PianoStation_t *, const PianoSong_t *, const player_t *, -		PianoStation_t *, PianoReturn_t, WaitressReturn_t); +		PianoStation_t *, PianoReturn_t, CURLcode);  int BarUiPianoCall (BarApp_t * const, PianoRequestType_t, -		void *, PianoReturn_t *, WaitressReturn_t *); +		void *, PianoReturn_t *, CURLcode *);  void BarUiHistoryPrepend (BarApp_t *app, PianoSong_t *song);  #endif /* SRC_UI_H_46P20TS0 */ diff --git a/src/ui_act.c b/src/ui_act.c index c39f98b..adb2f87 100644 --- a/src/ui_act.c +++ b/src/ui_act.c @@ -63,7 +63,7 @@ static inline void BarUiDoSkipSong (player_t * const player) {   */  static int BarTransformIfShared (BarApp_t *app, PianoStation_t *station) {  	PianoReturn_t pRet; -	WaitressReturn_t wRet; +	CURLcode wRet;  	assert (station != NULL); @@ -96,7 +96,7 @@ BarUiActCallback(BarUiActHelp) {   */  BarUiActCallback(BarUiActAddMusic) {  	PianoReturn_t pRet; -	WaitressReturn_t wRet; +	CURLcode wRet;  	PianoRequestDataAddSeed_t reqData;  	assert (selStation != NULL); @@ -122,7 +122,7 @@ BarUiActCallback(BarUiActAddMusic) {   */  BarUiActCallback(BarUiActBanSong) {  	PianoReturn_t pRet; -	WaitressReturn_t wRet; +	CURLcode wRet;  	PianoStation_t *realStation;  	assert (selStation != NULL); @@ -154,7 +154,7 @@ BarUiActCallback(BarUiActBanSong) {   */  BarUiActCallback(BarUiActCreateStation) {  	PianoReturn_t pRet; -	WaitressReturn_t wRet; +	CURLcode wRet;  	PianoRequestDataCreateStation_t reqData;  	reqData.type = PIANO_MUSICTYPE_INVALID; @@ -172,7 +172,7 @@ BarUiActCallback(BarUiActCreateStation) {   */  BarUiActCallback(BarUiActCreateStationFromSong) {  	PianoReturn_t pRet; -	WaitressReturn_t wRet; +	CURLcode wRet;  	PianoRequestDataCreateStation_t reqData;  	char selectBuf[2]; @@ -202,7 +202,7 @@ BarUiActCallback(BarUiActCreateStationFromSong) {   */  BarUiActCallback(BarUiActAddSharedStation) {  	PianoReturn_t pRet; -	WaitressReturn_t wRet; +	CURLcode wRet;  	char stationId[50];  	PianoRequestDataCreateStation_t reqData; @@ -222,7 +222,7 @@ BarUiActCallback(BarUiActAddSharedStation) {   */  BarUiActCallback(BarUiActDeleteStation) {  	PianoReturn_t pRet; -	WaitressReturn_t wRet; +	CURLcode wRet;  	assert (selStation != NULL); @@ -247,7 +247,7 @@ BarUiActCallback(BarUiActDeleteStation) {   */  BarUiActCallback(BarUiActExplain) {  	PianoReturn_t pRet; -	WaitressReturn_t wRet; +	CURLcode wRet;  	PianoRequestDataExplain_t reqData;  	assert (selSong != NULL); @@ -266,7 +266,7 @@ BarUiActCallback(BarUiActExplain) {   */  BarUiActCallback(BarUiActStationFromGenre) {  	PianoReturn_t pRet; -	WaitressReturn_t wRet; +	CURLcode wRet;  	const PianoGenreCategory_t *curCat;  	const PianoGenre_t *curGenre;  	int i; @@ -376,7 +376,7 @@ BarUiActCallback(BarUiActDebug) {   */  BarUiActCallback(BarUiActLoveSong) {  	PianoReturn_t pRet; -	WaitressReturn_t wRet; +	CURLcode wRet;  	PianoStation_t *realStation;  	assert (selStation != NULL); @@ -438,7 +438,7 @@ BarUiActCallback(BarUiActTogglePause) {   */  BarUiActCallback(BarUiActRenameStation) {  	PianoReturn_t pRet; -	WaitressReturn_t wRet; +	CURLcode wRet;  	char lineBuf[100];  	assert (selStation != NULL); @@ -481,7 +481,7 @@ BarUiActCallback(BarUiActSelectStation) {   */  BarUiActCallback(BarUiActTempBanSong) {  	PianoReturn_t pRet; -	WaitressReturn_t wRet; +	CURLcode wRet;  	assert (selSong != NULL); @@ -547,7 +547,7 @@ static void BarUiActQuickmixCallback (BarApp_t *app, char *buf) {   */  BarUiActCallback(BarUiActSelectQuickMix) {  	PianoReturn_t pRet; -	WaitressReturn_t wRet; +	CURLcode wRet;  	assert (selStation != NULL); @@ -616,7 +616,7 @@ BarUiActCallback(BarUiActHistory) {   */  BarUiActCallback(BarUiActBookmark) {  	PianoReturn_t pRet; -	WaitressReturn_t wRet; +	CURLcode wRet;  	char selectBuf[2];  	assert (selSong != NULL); @@ -660,7 +660,7 @@ BarUiActCallback(BarUiActVolReset) {   */  BarUiActCallback(BarUiActManageStation) {  	PianoReturn_t pRet; -	WaitressReturn_t wRet; +	CURLcode wRet;  	PianoRequestDataGetStationInfo_t reqData;  	char selectBuf[2], allowedActions[6], *allowedPos = allowedActions;  	char question[64]; | 
