From 096975db943e4422a9a0afd57d785d4f3ade97f0 Mon Sep 17 00:00:00 2001
From: Lars-Dominik Braun <PromyLOPh@lavabit.com>
Date: Sun, 3 May 2009 19:56:54 +0200
Subject: piano: Switch to libwaitress

---
 libpiano/src/CMakeLists.txt |   8 +-
 libpiano/src/http.c         |  91 ++++-------------
 libpiano/src/http.h         |   6 +-
 libpiano/src/main.c         | 232 +++++++++++++++++++++-----------------------
 libpiano/src/piano.h        |  11 +--
 5 files changed, 139 insertions(+), 209 deletions(-)

diff --git a/libpiano/src/CMakeLists.txt b/libpiano/src/CMakeLists.txt
index 9525101..432c5fd 100644
--- a/libpiano/src/CMakeLists.txt
+++ b/libpiano/src/CMakeLists.txt
@@ -1,11 +1,13 @@
 set (CMAKE_C_FLAGS -Wall)
 
 find_package (LibXml2 REQUIRED)
-find_package (CURL REQUIRED)
 
 configure_file (${CMAKE_CURRENT_SOURCE_DIR}/config.h.in
 	${CMAKE_CURRENT_BINARY_DIR}/config.h)
 
-include_directories (${LIBXML2_INCLUDE_DIR} ${CURL_INCLUDE_DIRS})
+include_directories (${LIBXML2_INCLUDE_DIR}
+	${CMAKE_CURRENT_SOURCE_DIR}/../../libwaitress/src)
+
 add_library (piano STATIC crypt.c http.c main.c xml.c)
-target_link_libraries (${CURL_LIBRARIES} ${LIBXML_LIBRARIES})
+target_link_libraries (piano ${LIBXML_LIBRARIES} waitress)
+
diff --git a/libpiano/src/http.c b/libpiano/src/http.c
index 6a73aa7..acae893 100644
--- a/libpiano/src/http.c
+++ b/libpiano/src/http.c
@@ -21,40 +21,13 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 THE SOFTWARE.
 */
 
-#include <curl/curl.h>
 #include <stdlib.h>
 #include <string.h>
+#include <stdio.h>
 
-#include "http.h"
-
-struct PianoHttpBuffer {
-	size_t size; /* size of string without NUL-byte */
-	char *buf; /* NUL-terminated string */
-};
-
-/*	callback for curl, writes data to buffer
- *	@param received data
- *	@param block size
- *	@param blocks received
- *	@param write data into this buffer
- *	@return written bytes
- */
-size_t PianoCurlRetToVar (void *ptr, size_t size, size_t nmemb,
-		void *stream) {
-	struct PianoHttpBuffer *curlRet = stream;
+#include <waitress.h>
 
-	if (curlRet->buf == NULL) {
-		curlRet->buf = malloc (nmemb + 1);
-		curlRet->size = 0;
-	} else {
-		curlRet->buf = realloc (curlRet->buf, curlRet->size + nmemb + 1);
-	}
-	memcpy (curlRet->buf + curlRet->size, ptr, size*nmemb);
-	curlRet->size += nmemb;
-	curlRet->buf[curlRet->size] = 0;
-
-	return size*nmemb;
-}
+#include "http.h"
 
 /* FIXME: we may use a callback given by the library client here. would be
  * more flexible... */
@@ -65,33 +38,16 @@ size_t PianoCurlRetToVar (void *ptr, size_t size, size_t nmemb,
  *	@param put received data here, memory is allocated by this function
  *	@return nothing yet
  */
-PianoReturn_t PianoHttpPost (CURL *ch, const char *url, const char *postData,
-		char **retData) {
-	struct curl_slist *headers = NULL;
-	struct PianoHttpBuffer curlRet = {0, NULL};
-	PianoReturn_t ret;
-
-	headers = curl_slist_append (headers, "Content-Type: text/xml");
-
-	curl_easy_setopt (ch, CURLOPT_URL, url);
-	curl_easy_setopt (ch, CURLOPT_POSTFIELDS, postData);
-	curl_easy_setopt (ch, CURLOPT_HTTPHEADER, headers);
-	curl_easy_setopt (ch, CURLOPT_WRITEFUNCTION, PianoCurlRetToVar);
-	/* don't verify certificate for now, it's easier ;) */
-	curl_easy_setopt (ch, CURLOPT_SSL_VERIFYPEER, 0);
-	curl_easy_setopt (ch, CURLOPT_WRITEDATA, (void *) &curlRet);
-
-	if (curl_easy_perform (ch) == CURLE_OK) {
-		ret = PIANO_RET_OK;
-		*retData = curlRet.buf;
-	} else {
-		ret = PIANO_RET_NET_ERROR;
-		*retData = NULL;
+PianoReturn_t PianoHttpPost (WaitressHandle_t *waith, const char *postData,
+		char *retData, size_t retDataSize) {
+	waith->extraHeaders = "Content-Type: text/xml\r\n";
+	waith->postData = postData;
+	waith->method = WAITRESS_METHOD_POST;
+
+	if (WaitressFetchBuf (waith, retData, retDataSize) == WAITRESS_RET_OK) {
+		return PIANO_RET_OK;
 	}
-
-	curl_slist_free_all (headers);
-
-	return ret;
+	return PIANO_RET_NET_ERROR;
 }
 
 /*	get data
@@ -100,23 +56,12 @@ PianoReturn_t PianoHttpPost (CURL *ch, const char *url, const char *postData,
  *	@param put received data here, memory is allocated by this function
  *	@return nothing yet
  */
-PianoReturn_t PianoHttpGet (CURL *ch, const char *url, char **retData) {
-	struct PianoHttpBuffer curlRet = {0, NULL};
-	PianoReturn_t ret;
-
-	curl_easy_setopt (ch, CURLOPT_URL, url);
-	curl_easy_setopt (ch, CURLOPT_HTTPGET, 1L);
-	curl_easy_setopt (ch, CURLOPT_HTTPHEADER, NULL);
-	curl_easy_setopt (ch, CURLOPT_WRITEFUNCTION, PianoCurlRetToVar);
-	curl_easy_setopt (ch, CURLOPT_WRITEDATA, (void *) &curlRet);
+PianoReturn_t PianoHttpGet (WaitressHandle_t *waith, char *retData,
+		size_t retDataSize) {
+	waith->method = WAITRESS_METHOD_GET;
 
-	if (curl_easy_perform (ch) == CURLE_OK) {
-		ret = PIANO_RET_OK;
-		*retData = curlRet.buf;
-	} else {
-		ret = PIANO_RET_NET_ERROR;
-		*retData = NULL;
+	if (WaitressFetchBuf (waith, retData, retDataSize) == WAITRESS_RET_OK) {
+		return PIANO_RET_OK;
 	}
-
-	return ret;
+	return PIANO_RET_NET_ERROR;
 }
diff --git a/libpiano/src/http.h b/libpiano/src/http.h
index fa525dd..c56ef8b 100644
--- a/libpiano/src/http.h
+++ b/libpiano/src/http.h
@@ -24,10 +24,10 @@ THE SOFTWARE.
 #ifndef _HTTP_H
 #define _HTTP_H
 
+#include <waitress.h>
 #include "piano.h"
 
-PianoReturn_t PianoHttpPost (CURL *ch, const char *url, const char *postData,
-		char **retData);
-PianoReturn_t PianoHttpGet (CURL *ch, const char *url, char **retData);
+PianoReturn_t PianoHttpPost (WaitressHandle_t *, const char *, char *, size_t);
+PianoReturn_t PianoHttpGet (WaitressHandle_t *, char *, size_t);
 
 #endif /* _HTTP_H */
diff --git a/libpiano/src/main.c b/libpiano/src/main.c
index 7e7b989..e662c14 100644
--- a/libpiano/src/main.c
+++ b/libpiano/src/main.c
@@ -34,21 +34,19 @@ THE SOFTWARE.
 #include "config.h"
 
 #define PIANO_PROTOCOL_VERSION "23"
-#define PIANO_RPC_URL "http://www.pandora.com/radio/xmlrpc/v" \
-		PIANO_PROTOCOL_VERSION "?"
-#define PIANO_SECURE_RPC_URL "https://www.pandora.com/radio/xmlrpc/v" \
-		PIANO_PROTOCOL_VERSION "?"
-#define PIANO_URL_BUFFER_SIZE 1024
+#define PIANO_RPC_HOST "www.pandora.com"
+#define PIANO_RPC_PORT "80"
+#define PIANO_RPC_PATH "/radio/xmlrpc/v" PIANO_PROTOCOL_VERSION "?"
 #define PIANO_SEND_BUFFER_SIZE 10000
+/* station responses are _huge_... */
+#define PIANO_RECV_BUFFER 100*1024
 
 /* prototypes */
 PianoReturn_t PianoAddFeedback (PianoHandle_t *, const char *, const char *,
 		const char *, const char *, const char *, PianoSongRating_t);
 const char *PianoAudioFormatToString (PianoAudioFormat_t);
 
-/*	more "secure" free version; only use this function, not original free ()
- *	in this library
- *	@public no!!!
+/*	more "secure" free version
  *	@param free this pointer
  *	@param zero n bytes; 0 disables zeroing (for strings with unknown size,
  *			e.g.)
@@ -71,11 +69,13 @@ void PianoFree (void *ptr, size_t size) {
  */
 void PianoInit (PianoHandle_t *ph) {
 	memset (ph, 0, sizeof (*ph));
-	ph->curlHandle = curl_easy_init ();
+
+	WaitressInit (&ph->waith);
+	strncpy (ph->waith.host, PIANO_RPC_HOST, sizeof (ph->waith.host)-1);
+	strncpy (ph->waith.port, PIANO_RPC_PORT, sizeof (ph->waith.port)-1);
+
+	/* route-id seems to be random. we're using time anyway... */
 	snprintf (ph->routeId, sizeof (ph->routeId), "%07liP", time (NULL) % 10000000);
-	curl_easy_setopt (ph->curlHandle, CURLOPT_USERAGENT, PACKAGE);
-	curl_easy_setopt (ph->curlHandle, CURLOPT_CONNECTTIMEOUT, 60);
-	curl_easy_setopt (ph->curlHandle, CURLOPT_TIMEOUT, 60);
 }
 
 /*	free complete search result
@@ -164,7 +164,8 @@ void PianoDestroyPlaylist (PianoHandle_t *ph) {
  *	@return nothing
  */
 void PianoDestroy (PianoHandle_t *ph) {
-	curl_easy_cleanup (ph->curlHandle);
+	WaitressFree (&ph->waith);
+
 	PianoFree (ph->user.webAuthToken, 0);
 	PianoFree (ph->user.authToken, 0);
 	PianoFree (ph->user.listenerId, 0);
@@ -191,12 +192,11 @@ void PianoDestroy (PianoHandle_t *ph) {
  *			is not hashed and will be sent as plain-text!
  */
 PianoReturn_t PianoConnect (PianoHandle_t *ph, const char *user,
-		const char *password, char secureLogin) {
-	char url[PIANO_URL_BUFFER_SIZE];
+		const char *password) {
+	char retStr[PIANO_RECV_BUFFER], requestStrPlain[PIANO_SEND_BUFFER_SIZE];
 	char *requestStr = PianoEncryptString ("<?xml version=\"1.0\"?>"
 			"<methodCall><methodName>misc.sync</methodName>"
 			"<params></params></methodCall>");
-	char *retStr, requestStrPlain[PIANO_SEND_BUFFER_SIZE];
 	PianoReturn_t ret;
 
 #if 0
@@ -205,11 +205,10 @@ PianoReturn_t PianoConnect (PianoHandle_t *ph, const char *user,
 			"==========\n");
 #endif
 	/* sync (is the return value used by pandora? for now: ignore result) */
-	snprintf (url, sizeof (url), PIANO_RPC_URL "rid=%s&method=sync",
-			ph->routeId);
-	ret = PianoHttpPost (ph->curlHandle, url, requestStr, &retStr);
+	snprintf (ph->waith.path, sizeof (ph->waith.path), PIANO_RPC_PATH
+			"rid=%s&method=sync", ph->routeId);
+	ret = PianoHttpPost (&ph->waith, requestStr, retStr, sizeof (retStr));
 	PianoFree (requestStr, 0);
-	PianoFree (retStr, 0);
 
 	if (ret != PIANO_RET_OK) {
 		return ret;
@@ -224,13 +223,12 @@ PianoReturn_t PianoConnect (PianoHandle_t *ph, const char *user,
 			"<param><value><string>%s</string></value></param>"
 			"</params></methodCall>", time (NULL), user, password);
 	requestStr = PianoEncryptString (requestStrPlain);
-	snprintf (url, sizeof (url), "%srid=%s&method=authenticateListener",
-			secureLogin ? PIANO_SECURE_RPC_URL : PIANO_RPC_URL, ph->routeId);
+	snprintf (ph->waith.path, sizeof (ph->waith.path), PIANO_RPC_PATH
+			"rid=%s&method=authenticateListener", ph->routeId);
 
-	if ((ret = PianoHttpPost (ph->curlHandle, url, requestStr, &retStr)) ==
-			PIANO_RET_OK) {
+	if ((ret = PianoHttpPost (&ph->waith, requestStr, retStr,
+			sizeof (retStr))) == PIANO_RET_OK) {
 		ret = PianoXmlParseUserinfo (ph, retStr);
-		PianoFree (retStr, 0);
 	}
 
 	PianoFree (requestStr, 0);
@@ -243,8 +241,8 @@ PianoReturn_t PianoConnect (PianoHandle_t *ph, const char *user,
  *	@param piano handle filled with some authentication data by PianoConnect
  */
 PianoReturn_t PianoGetStations (PianoHandle_t *ph) {
-	char xmlSendBuf[PIANO_SEND_BUFFER_SIZE], url[PIANO_URL_BUFFER_SIZE];
-	char *requestStr, *retStr;
+	char xmlSendBuf[PIANO_SEND_BUFFER_SIZE], retStr[PIANO_RECV_BUFFER];
+	char *requestStr;
 	PianoReturn_t ret;
 
 	snprintf (xmlSendBuf, sizeof (xmlSendBuf), "<?xml version=\"1.0\"?>"
@@ -253,14 +251,13 @@ PianoReturn_t PianoGetStations (PianoHandle_t *ph) {
 			"<param><value><string>%s</string></value></param>"
 			"</params></methodCall>", time (NULL), ph->user.authToken);
 	requestStr = PianoEncryptString (xmlSendBuf);
-	snprintf (url, sizeof (url), PIANO_RPC_URL
+	snprintf (ph->waith.path, sizeof (ph->waith.path), PIANO_RPC_PATH
 			"rid=%s&lid=%s&method=getStations", ph->routeId,
 			ph->user.listenerId);
 
-	if ((ret = PianoHttpPost (ph->curlHandle, url, requestStr, &retStr)) ==
-			PIANO_RET_OK) {
+	if ((ret = PianoHttpPost (&ph->waith, requestStr, retStr,
+			sizeof (retStr))) == PIANO_RET_OK) {
 		ret = PianoXmlParseStations (ph, retStr);
-		PianoFree (retStr, 0);
 	}
 
 	PianoFree (requestStr, 0);
@@ -274,8 +271,8 @@ PianoReturn_t PianoGetStations (PianoHandle_t *ph) {
  */
 PianoReturn_t PianoGetPlaylist (PianoHandle_t *ph, const char *stationId,
 		PianoAudioFormat_t format) {
-	char xmlSendBuf[PIANO_SEND_BUFFER_SIZE], url[PIANO_URL_BUFFER_SIZE];
-	char *requestStr, *retStr;
+	char xmlSendBuf[PIANO_SEND_BUFFER_SIZE], retStr[PIANO_RECV_BUFFER];
+	char *requestStr;
 	PianoReturn_t ret;
 
 	/* FIXME: remove static numbers */
@@ -291,16 +288,15 @@ PianoReturn_t PianoGetPlaylist (PianoHandle_t *ph, const char *stationId,
 			"</params></methodCall>", time (NULL), ph->user.authToken,
 			stationId, PianoAudioFormatToString (format));
 	requestStr = PianoEncryptString (xmlSendBuf);
-	snprintf (url, sizeof (url), PIANO_RPC_URL
+	snprintf (ph->waith.path, sizeof (ph->waith.path), PIANO_RPC_PATH
 			"rid=%s&lid=%s&method=getFragment&arg1=%s&arg2=0"
 			"&arg3=&arg4=&arg5=%s", ph->routeId,
 			ph->user.listenerId, stationId,
 			PianoAudioFormatToString (format));
 
-	if ((ret = PianoHttpPost (ph->curlHandle, url, requestStr, &retStr)) ==
-			PIANO_RET_OK) {
+	if ((ret = PianoHttpPost (&ph->waith, requestStr, retStr,
+			sizeof (retStr))) == PIANO_RET_OK) {
 		ret = PianoXmlParsePlaylist (ph, retStr);
-		PianoFree (retStr, 0);
 	}
 
 	PianoFree (requestStr, 0);
@@ -363,8 +359,8 @@ PianoReturn_t PianoAddFeedback (PianoHandle_t *ph, const char *stationId,
 		const char *songMusicId, const char *songMatchingSeed,
 		const char *songUserSeed, const char *songFocusTraitId,
 		PianoSongRating_t rating) {
-	char xmlSendBuf[PIANO_SEND_BUFFER_SIZE], url[PIANO_URL_BUFFER_SIZE];
-	char *requestStr, *retStr;
+	char xmlSendBuf[PIANO_SEND_BUFFER_SIZE], retStr[PIANO_RECV_BUFFER];
+	char *requestStr;
 	PianoReturn_t ret = PIANO_RET_ERR;
 
 	snprintf (xmlSendBuf, sizeof (xmlSendBuf), "<?xml version=\"1.0\"?>"
@@ -386,7 +382,7 @@ PianoReturn_t PianoAddFeedback (PianoHandle_t *ph, const char *stationId,
 			(songFocusTraitId == NULL) ? "" : songFocusTraitId,
 			(rating == PIANO_RATE_LOVE) ? 1 : 0);
 	requestStr = PianoEncryptString (xmlSendBuf);
-	snprintf (url, sizeof (url), PIANO_RPC_URL
+	snprintf (ph->waith.path, sizeof (ph->waith.path), PIANO_RPC_PATH
 			"rid=%s&lid=%s&method=addFeedback&arg1=%s&arg2=%s"
 			"&arg3=%s&arg4=%s&arg5=%s&arg6=&arg7=%s&arg8=false", ph->routeId,
 			ph->user.listenerId, stationId, songMusicId,
@@ -395,10 +391,9 @@ PianoReturn_t PianoAddFeedback (PianoHandle_t *ph, const char *stationId,
 			(songFocusTraitId == NULL) ? "" : songFocusTraitId,
 			(rating == PIANO_RATE_LOVE) ? "true" : "false");
 
-	if ((ret = PianoHttpPost (ph->curlHandle, url, requestStr, &retStr)) ==
-			PIANO_RET_OK) {
+	if ((ret = PianoHttpPost (&ph->waith, requestStr, retStr,
+			sizeof (retStr))) == PIANO_RET_OK) {
 		ret = PianoXmlParseSimple (retStr);
-		PianoFree (retStr, 0);
 	}
 
 	PianoFree (requestStr, 0);
@@ -415,8 +410,8 @@ PianoReturn_t PianoAddFeedback (PianoHandle_t *ph, const char *stationId,
  */
 PianoReturn_t PianoRenameStation (PianoHandle_t *ph, PianoStation_t *station,
 		const char *newName) {
-	char xmlSendBuf[PIANO_SEND_BUFFER_SIZE], url[PIANO_URL_BUFFER_SIZE];
-	char *requestStr, *retStr, *urlencodedNewName, *xmlencodedNewName;
+	char xmlSendBuf[PIANO_SEND_BUFFER_SIZE], retStr[PIANO_RECV_BUFFER];
+	char *requestStr, *urlencodedNewName, *xmlencodedNewName;
 	PianoReturn_t ret = PIANO_RET_ERR;
 
 	xmlencodedNewName = PianoXmlEncodeString (newName);
@@ -430,21 +425,20 @@ PianoReturn_t PianoRenameStation (PianoHandle_t *ph, PianoStation_t *station,
 			station->id, xmlencodedNewName);
 	requestStr = PianoEncryptString (xmlSendBuf);
 
-	urlencodedNewName = curl_easy_escape (ph->curlHandle, newName, 0);
-	snprintf (url, sizeof (url), PIANO_RPC_URL "rid=%s&lid=%s"
-			"&method=setStationName&arg1=%s&arg2=%s", ph->routeId,
-			ph->user.listenerId, station->id, urlencodedNewName);
+	urlencodedNewName = WaitressUrlEncode (newName);
+	snprintf (ph->waith.path, sizeof (ph->waith.path), PIANO_RPC_PATH
+			"rid=%s&lid=%s&method=setStationName&arg1=%s&arg2=%s",
+			ph->routeId, ph->user.listenerId, station->id, urlencodedNewName);
 
-	if ((ret = PianoHttpPost (ph->curlHandle, url, requestStr, &retStr)) ==
-			PIANO_RET_OK) {
+	if ((ret = PianoHttpPost (&ph->waith, requestStr, retStr,
+			sizeof (retStr))) == PIANO_RET_OK) {
 		if ((ret = PianoXmlParseSimple (retStr)) == PIANO_RET_OK) {
 			PianoFree (station->name, 0);
 			station->name = strdup (newName);
 		}
-		PianoFree (retStr, 0);
 	}
 
-	curl_free (urlencodedNewName);
+	PianoFree (urlencodedNewName, 0);
 	PianoFree (xmlencodedNewName, 0);
 	PianoFree (requestStr, 0);
 
@@ -457,8 +451,8 @@ PianoReturn_t PianoRenameStation (PianoHandle_t *ph, PianoStation_t *station,
  *	@param station you want to delete
  */
 PianoReturn_t PianoDeleteStation (PianoHandle_t *ph, PianoStation_t *station) {
-	char xmlSendBuf[PIANO_SEND_BUFFER_SIZE], url[PIANO_URL_BUFFER_SIZE];
-	char *requestStr, *retStr;
+	char xmlSendBuf[PIANO_SEND_BUFFER_SIZE], retStr[PIANO_RECV_BUFFER];
+	char *requestStr;
 	PianoReturn_t ret = PIANO_RET_ERR;
 
 	snprintf (xmlSendBuf, sizeof (xmlSendBuf), "<?xml version=\"1.0\"?>"
@@ -470,11 +464,11 @@ PianoReturn_t PianoDeleteStation (PianoHandle_t *ph, PianoStation_t *station) {
 			station->id);
 	requestStr = PianoEncryptString (xmlSendBuf);
 
-	snprintf (url, sizeof (url), PIANO_RPC_URL "rid=%s&lid=%s"
-			"&method=removeStation&arg1=%s", ph->routeId, ph->user.listenerId,
-			station->id);
-	if ((ret = PianoHttpPost (ph->curlHandle, url, requestStr, &retStr)) ==
-			PIANO_RET_OK) {
+	snprintf (ph->waith.path, sizeof (ph->waith.path), PIANO_RPC_PATH
+			"rid=%s&lid=%s&method=removeStation&arg1=%s", ph->routeId,
+			ph->user.listenerId, station->id);
+	if ((ret = PianoHttpPost (&ph->waith, requestStr, retStr,
+			sizeof (retStr))) == PIANO_RET_OK) {
 		if ((ret = PianoXmlParseSimple (retStr)) == PIANO_RET_OK) {
 			/* delete station from local station list */
 			PianoStation_t *curStation = ph->stations, *lastStation = NULL;
@@ -494,7 +488,6 @@ PianoReturn_t PianoDeleteStation (PianoHandle_t *ph, PianoStation_t *station) {
 				curStation = curStation->next;
 			}
 		}
-		PianoFree (retStr, 0);
 	}
 
 	PianoFree (requestStr, 0);
@@ -510,10 +503,10 @@ PianoReturn_t PianoDeleteStation (PianoHandle_t *ph, PianoStation_t *station) {
  *	@param utf-8 search string
  *	@param return search result
  */
-PianoReturn_t PianoSearchMusic (const PianoHandle_t *ph,
+PianoReturn_t PianoSearchMusic (PianoHandle_t *ph,
 		const char *searchStr, PianoSearchResult_t *searchResult) {
-	char xmlSendBuf[PIANO_SEND_BUFFER_SIZE], url[PIANO_URL_BUFFER_SIZE];
-	char *requestStr, *retStr, *xmlencodedSearchStr, *urlencodedSearchStr;
+	char xmlSendBuf[PIANO_SEND_BUFFER_SIZE], retStr[PIANO_RECV_BUFFER];
+	char *requestStr, *xmlencodedSearchStr, *urlencodedSearchStr;
 	PianoReturn_t ret;
 
 	xmlencodedSearchStr = PianoXmlEncodeString (searchStr);
@@ -526,18 +519,17 @@ PianoReturn_t PianoSearchMusic (const PianoHandle_t *ph,
 			xmlencodedSearchStr);
 	requestStr = PianoEncryptString (xmlSendBuf);
 
-	urlencodedSearchStr = curl_easy_escape (ph->curlHandle, searchStr, 0);
-	snprintf (url, sizeof (url), PIANO_RPC_URL "rid=%s&lid=%s&"
-			"method=search&arg1=%s", ph->routeId, ph->user.listenerId,
-			urlencodedSearchStr);
+	urlencodedSearchStr = WaitressUrlEncode (searchStr);
+	snprintf (ph->waith.path, sizeof (ph->waith.path), PIANO_RPC_PATH
+			"rid=%s&lid=%s&method=search&arg1=%s", ph->routeId,
+			ph->user.listenerId, urlencodedSearchStr);
 	
-	if ((ret = PianoHttpPost (ph->curlHandle, url, requestStr, &retStr)) ==
-			PIANO_RET_OK) {
+	if ((ret = PianoHttpPost (&ph->waith, requestStr, retStr,
+			sizeof (retStr))) == PIANO_RET_OK) {
 		ret = PianoXmlParseSearch (retStr, searchResult);
-		PianoFree (retStr, 0);
 	}
 
-	curl_free (urlencodedSearchStr);
+	PianoFree (urlencodedSearchStr, 0);
 	PianoFree (xmlencodedSearchStr, 0);
 	PianoFree (requestStr, 0);
 
@@ -553,8 +545,8 @@ PianoReturn_t PianoSearchMusic (const PianoHandle_t *ph,
  */
 PianoReturn_t PianoCreateStation (PianoHandle_t *ph, const char *type,
 		const char *id) {
-	char xmlSendBuf[PIANO_SEND_BUFFER_SIZE], url[PIANO_URL_BUFFER_SIZE];
-	char *requestStr, *retStr;
+	char xmlSendBuf[PIANO_SEND_BUFFER_SIZE], retStr[PIANO_RECV_BUFFER];
+	char *requestStr;
 	PianoReturn_t ret;
 
 	snprintf (xmlSendBuf, sizeof (xmlSendBuf), "<?xml version=\"1.0\"?>"
@@ -566,14 +558,13 @@ PianoReturn_t PianoCreateStation (PianoHandle_t *ph, const char *type,
 			type, id);
 	requestStr = PianoEncryptString (xmlSendBuf);
 
-	snprintf (url, sizeof (url), PIANO_RPC_URL "rid=%s&lid=%s"
-			"&method=createStation&arg1=%s%s", ph->routeId,
+	snprintf (ph->waith.path, sizeof (ph->waith.path), PIANO_RPC_PATH
+			"rid=%s&lid=%s&method=createStation&arg1=%s%s", ph->routeId,
 			ph->user.listenerId, type, id);
 	
-	if ((ret = PianoHttpPost (ph->curlHandle, url, requestStr, &retStr)) ==
-			PIANO_RET_OK) {
+	if ((ret = PianoHttpPost (&ph->waith, requestStr, retStr,
+			sizeof (retStr))) == PIANO_RET_OK) {
 		ret = PianoXmlParseCreateStation (ph, retStr);
-		PianoFree (retStr, 0);
 	}
 
 	PianoFree (requestStr, 0);
@@ -592,8 +583,8 @@ PianoReturn_t PianoCreateStation (PianoHandle_t *ph, const char *type,
  */
 PianoReturn_t PianoStationAddMusic (PianoHandle_t *ph,
 		PianoStation_t *station, const char *musicId) {
-	char xmlSendBuf[PIANO_SEND_BUFFER_SIZE], url[PIANO_URL_BUFFER_SIZE];
-	char *requestStr, *retStr;
+	char xmlSendBuf[PIANO_SEND_BUFFER_SIZE], retStr[PIANO_RECV_BUFFER];
+	char *requestStr;
 	PianoReturn_t ret;
 
 	snprintf (xmlSendBuf, sizeof (xmlSendBuf), "<?xml version=\"1.0\"?>"
@@ -606,14 +597,13 @@ PianoReturn_t PianoStationAddMusic (PianoHandle_t *ph,
 			station->id, musicId);
 	requestStr = PianoEncryptString (xmlSendBuf);
 
-	snprintf (url, sizeof (url), PIANO_RPC_URL "rid=%s&lid=%s"
-			"&method=addSeed&arg1=%s&arg2=%s", ph->routeId,
+	snprintf (ph->waith.path, sizeof (ph->waith.path), PIANO_RPC_PATH
+			"rid=%s&lid=%s&method=addSeed&arg1=%s&arg2=%s", ph->routeId,
 			ph->user.listenerId, station->id, musicId);
 	
-	if ((ret = PianoHttpPost (ph->curlHandle, url, requestStr, &retStr)) ==
-			PIANO_RET_OK) {
+	if ((ret = PianoHttpPost (&ph->waith, requestStr, retStr,
+			sizeof (retStr))) == PIANO_RET_OK) {
 		ret = PianoXmlParseAddSeed (ph, retStr, station);
-		PianoFree (retStr, 0);
 	}
 
 	PianoFree (requestStr, 0);
@@ -627,8 +617,8 @@ PianoReturn_t PianoStationAddMusic (PianoHandle_t *ph,
  *	@return _OK or error
  */
 PianoReturn_t PianoSongTired (PianoHandle_t *ph, const PianoSong_t *song) {
-	char xmlSendBuf[PIANO_SEND_BUFFER_SIZE], url[PIANO_URL_BUFFER_SIZE];
-	char *requestStr, *retStr;
+	char xmlSendBuf[PIANO_SEND_BUFFER_SIZE], retStr[PIANO_RECV_BUFFER];
+	char *requestStr;
 	PianoReturn_t ret;
 
 	snprintf (xmlSendBuf, sizeof (xmlSendBuf), "<?xml version=\"1.0\"?>"
@@ -640,14 +630,13 @@ PianoReturn_t PianoSongTired (PianoHandle_t *ph, const PianoSong_t *song) {
 			song->identity);
 	requestStr = PianoEncryptString (xmlSendBuf);
 
-	snprintf (url, sizeof (url), PIANO_RPC_URL "rid=%s&lid=%s&"
-			"method=addTiredSong&arg1=%s", ph->routeId, ph->user.listenerId,
-			song->identity);
+	snprintf (ph->waith.path, sizeof (ph->waith.path), PIANO_RPC_PATH
+			"rid=%s&lid=%s&method=addTiredSong&arg1=%s", ph->routeId,
+			ph->user.listenerId, song->identity);
 
-	if ((ret = PianoHttpPost (ph->curlHandle, url, requestStr, &retStr)) ==
-			PIANO_RET_OK) {
+	if ((ret = PianoHttpPost (&ph->waith, requestStr, retStr,
+			sizeof (retStr))) == PIANO_RET_OK) {
 		ret = PianoXmlParseSimple (retStr);
-		PianoFree (retStr, 0);
 	}
 
 	PianoFree (requestStr, 0);
@@ -661,8 +650,8 @@ PianoReturn_t PianoSongTired (PianoHandle_t *ph, const PianoSong_t *song) {
  */
 PianoReturn_t PianoSetQuickmix (PianoHandle_t *ph) {
 	char xmlSendBuf[PIANO_SEND_BUFFER_SIZE], valueBuf[1000], urlArgBuf[1000],
-			url[PIANO_URL_BUFFER_SIZE];
-	char *requestStr, *retStr;
+			retStr[PIANO_RECV_BUFFER];
+	char *requestStr;
 	PianoReturn_t ret;
 	PianoStation_t *curStation = ph->stations;
 
@@ -699,14 +688,13 @@ PianoReturn_t PianoSetQuickmix (PianoHandle_t *ph) {
 			sizeof (xmlSendBuf) - strlen (xmlSendBuf) - 1);
 	requestStr = PianoEncryptString (xmlSendBuf);
 
-	snprintf (url, sizeof (url), PIANO_RPC_URL "rid=%s&lid=%s&"
-			"method=setQuickMix&arg1=RANDOM&arg2=%s", ph->routeId,
-			ph->user.listenerId, urlArgBuf);
+	snprintf (ph->waith.path, sizeof (ph->waith.path), PIANO_RPC_PATH
+			"rid=%s&lid=%s&method=setQuickMix&arg1=RANDOM&arg2=%s",
+			ph->routeId, ph->user.listenerId, urlArgBuf);
 	
-	if ((ret = PianoHttpPost (ph->curlHandle, url, requestStr, &retStr)) ==
-			PIANO_RET_OK) {
+	if ((ret = PianoHttpPost (&ph->waith, requestStr, retStr,
+			sizeof (retStr))) == PIANO_RET_OK) {
 		ret = PianoXmlParseSimple (retStr);
-		PianoFree (retStr, 0);
 	}
 
 	PianoFree (requestStr, 0);
@@ -735,17 +723,15 @@ PianoStation_t *PianoFindStationById (PianoStation_t *stations,
  *	@return _OK or error
  */
 PianoReturn_t PianoGetGenreStations (PianoHandle_t *ph) {
-	char url[PIANO_URL_BUFFER_SIZE];
-	char *retStr;
+	char retStr[PIANO_RECV_BUFFER];
 	PianoReturn_t ret;
 
-	snprintf (url, sizeof (url), "http://www.pandora.com/xml/genre?r=%li",
+	snprintf (ph->waith.path, sizeof (ph->waith.path), "/xml/genre?r=%li",
 			time (NULL));
 	
-	if ((ret = PianoHttpGet (ph->curlHandle, url, &retStr)) ==
+	if ((ret = PianoHttpGet (&ph->waith, retStr, sizeof (retStr))) ==
 			PIANO_RET_OK) {
 		ret = PianoXmlParseGenreExplorer (ph, retStr);
-		PianoFree (retStr, 0);
 	}
 
 	return ret;
@@ -759,8 +745,8 @@ PianoReturn_t PianoGetGenreStations (PianoHandle_t *ph) {
  */
 PianoReturn_t PianoTransformShared (PianoHandle_t *ph,
 		PianoStation_t *station) {
-	char xmlSendBuf[PIANO_SEND_BUFFER_SIZE], url[PIANO_URL_BUFFER_SIZE];
-	char *requestStr, *retStr;
+	char xmlSendBuf[PIANO_SEND_BUFFER_SIZE], retStr[PIANO_RECV_BUFFER];
+	char *requestStr;
 	PianoReturn_t ret;
 
 	snprintf (xmlSendBuf, sizeof (xmlSendBuf), "<?xml version=\"1.0\"?>"
@@ -772,19 +758,18 @@ PianoReturn_t PianoTransformShared (PianoHandle_t *ph,
 			station->id);
 	requestStr = PianoEncryptString (xmlSendBuf);
 
-	snprintf (url, sizeof (url), PIANO_RPC_URL "rid=%s&lid=%s&"
-			"method=transformShared&arg1=%s", ph->routeId, ph->user.listenerId,
-			station->id);
+	snprintf (ph->waith.path, sizeof (ph->waith.path), PIANO_RPC_PATH
+			"rid=%s&lid=%s&method=transformShared&arg1=%s", ph->routeId,
+			ph->user.listenerId, station->id);
 	
-	if ((ret = PianoHttpPost (ph->curlHandle, url, requestStr, &retStr)) ==
-			PIANO_RET_OK) {
+	if ((ret = PianoHttpPost (&ph->waith, requestStr, retStr,
+			sizeof (retStr))) == PIANO_RET_OK) {
 		ret = PianoXmlParseTranformStation (retStr);
 		/* though this call returns a bunch of "new" data only this one is
 		 * changed and important (at the moment) */
 		if (ret == PIANO_RET_OK) {
 			station->isCreator = 1;
 		}
-		PianoFree (retStr, 0);
 	}
 
 	PianoFree (requestStr, 0);
@@ -798,10 +783,10 @@ PianoReturn_t PianoTransformShared (PianoHandle_t *ph,
  *	@param return allocated string; you have to free it yourself
  *	@return _OK or error
  */
-PianoReturn_t PianoExplain (const PianoHandle_t *ph, const PianoSong_t *song,
+PianoReturn_t PianoExplain (PianoHandle_t *ph, const PianoSong_t *song,
 		char **retExplain) {
-	char xmlSendBuf[PIANO_SEND_BUFFER_SIZE], url[PIANO_URL_BUFFER_SIZE];
-	char *requestStr, *retStr;
+	char xmlSendBuf[PIANO_SEND_BUFFER_SIZE], retStr[PIANO_RECV_BUFFER];
+	char *requestStr;
 	PianoReturn_t ret;
 
 	snprintf (xmlSendBuf, sizeof (xmlSendBuf), "<?xml version=\"1.0\"?>"
@@ -814,14 +799,13 @@ PianoReturn_t PianoExplain (const PianoHandle_t *ph, const PianoSong_t *song,
 			song->stationId, song->musicId);
 	requestStr = PianoEncryptString (xmlSendBuf);
 	
-	snprintf (url, sizeof (url), PIANO_RPC_URL "rid=%s&lid=%s&"
-			"method=method=narrative&arg1=%s&arg2=%s", ph->routeId,
-			ph->user.listenerId, song->stationId, song->musicId);
+	snprintf (ph->waith.path, sizeof (ph->waith.path), PIANO_RPC_PATH
+			"rid=%s&lid=%s&method=method=narrative&arg1=%s&arg2=%s",
+			ph->routeId, ph->user.listenerId, song->stationId, song->musicId);
 	
-	if ((ret = PianoHttpPost (ph->curlHandle, url, requestStr, &retStr)) ==
-			PIANO_RET_OK) {
+	if ((ret = PianoHttpPost (&ph->waith, requestStr, retStr,
+			sizeof (retStr))) == PIANO_RET_OK) {
 		ret = PianoXmlParseNarrative (retStr, retExplain);
-		PianoFree (retStr, 0);
 	}
 
 	PianoFree (requestStr, 0);
diff --git a/libpiano/src/piano.h b/libpiano/src/piano.h
index db85108..7ed5394 100644
--- a/libpiano/src/piano.h
+++ b/libpiano/src/piano.h
@@ -29,7 +29,7 @@ THE SOFTWARE.
  * all strings _must_ be utf-8 encoded. i won't care, but pandora does. so
  * be nice and check the encoding of your strings. thanks :) */
 
-#include <curl/curl.h>
+#include <waitress.h>
 
 typedef struct PianoUserInfo {
 	char *webAuthToken;
@@ -85,7 +85,7 @@ typedef struct PianoGenreCategory {
 } PianoGenreCategory_t;
 
 typedef struct PianoHandle {
-	CURL *curlHandle;
+	WaitressHandle_t waith;
 	char routeId[9];
 	PianoUserInfo_t user;
 	/* linked lists */
@@ -110,7 +110,7 @@ void PianoInit (PianoHandle_t *);
 void PianoDestroy (PianoHandle_t *);
 void PianoDestroyPlaylist (PianoHandle_t *);
 void PianoDestroySearchResult (PianoSearchResult_t *);
-PianoReturn_t PianoConnect (PianoHandle_t *, const char *, const char *, char);
+PianoReturn_t PianoConnect (PianoHandle_t *, const char *, const char *);
 
 PianoReturn_t PianoGetStations (PianoHandle_t *);
 PianoReturn_t PianoGetPlaylist (PianoHandle_t *, const char *,
@@ -123,7 +123,7 @@ PianoReturn_t PianoMoveSong (PianoHandle_t *, const PianoStation_t *,
 PianoReturn_t PianoRenameStation (PianoHandle_t *, PianoStation_t *,
 		const char *);
 PianoReturn_t PianoDeleteStation (PianoHandle_t *, PianoStation_t *);
-PianoReturn_t PianoSearchMusic (const PianoHandle_t *, const char *,
+PianoReturn_t PianoSearchMusic (PianoHandle_t *, const char *,
 		PianoSearchResult_t *);
 PianoReturn_t PianoCreateStation (PianoHandle_t *, const char *,
 		const char *);
@@ -134,8 +134,7 @@ PianoReturn_t PianoSetQuickmix (PianoHandle_t *);
 PianoStation_t *PianoFindStationById (PianoStation_t *, const char *);
 PianoReturn_t PianoGetGenreStations (PianoHandle_t *);
 PianoReturn_t PianoTransformShared (PianoHandle_t *, PianoStation_t *);
-PianoReturn_t PianoExplain (const PianoHandle_t *, const PianoSong_t *,
-		char **);
+PianoReturn_t PianoExplain (PianoHandle_t *, const PianoSong_t *, char **);
 const char *PianoErrorToStr (PianoReturn_t);
 
 #endif /* _PIANO_H */
-- 
cgit v1.2.3