diff options
Diffstat (limited to 'libpiano')
| -rw-r--r-- | libpiano/main.c | 14 | ||||
| -rw-r--r-- | libpiano/piano.h | 7 | ||||
| -rw-r--r-- | libpiano/xml.c | 130 | ||||
| -rw-r--r-- | libpiano/xml.h | 6 | 
4 files changed, 126 insertions, 31 deletions
| diff --git a/libpiano/main.c b/libpiano/main.c index faf5317..be97737 100644 --- a/libpiano/main.c +++ b/libpiano/main.c @@ -166,12 +166,13 @@ void PianoDestroy (PianoHandle_t *ph) {   *	@param password (plaintext, utf-8 encoded)   *	@return nothing   */ -void PianoConnect (PianoHandle_t *ph, char *user, char *password) { +PianoReturn_t PianoConnect (PianoHandle_t *ph, char *user, char *password) {  	char url[PIANO_URL_BUFFER_SIZE];  	char *requestStr = PianoEncryptString ("<?xml version=\"1.0\"?>"  			"<methodCall><methodName>misc.sync</methodName>"  			"<params></params></methodCall>");  	char *retStr, requestStrPlain[10000]; +	PianoReturn_t ret;  	/* sync (is the return value used by pandora? for now: ignore result) */  	snprintf (url, sizeof (url), PIANO_RPC_URL "rid=%s&method=sync", @@ -192,10 +193,12 @@ void PianoConnect (PianoHandle_t *ph, char *user, char *password) {  	snprintf (url, sizeof (url), PIANO_SECURE_RPC_URL "rid=%s"  			"&method=authenticateListener", ph->routeId);  	PianoHttpPost (ph->curlHandle, url, requestStr, &retStr); -	PianoXmlParseUserinfo (ph, retStr); +	ret = PianoXmlParseUserinfo (ph, retStr);  	free (requestStr);  	free (retStr); + +	return ret;  }  /*	get all stations for authenticated user (so: PianoConnect needs to @@ -205,9 +208,10 @@ void PianoConnect (PianoHandle_t *ph, char *user, char *password) {   *	@param piano handle filled with some authentication data by PianoConnect   *	@return nothing   */ -void PianoGetStations (PianoHandle_t *ph) { +PianoReturn_t PianoGetStations (PianoHandle_t *ph) {  	char xmlSendBuf[10000], url[PIANO_URL_BUFFER_SIZE];  	char *requestStr, *retStr; +	PianoReturn_t ret;  	snprintf (xmlSendBuf, sizeof (xmlSendBuf), "<?xml version=\"1.0\"?>"  			"<methodCall><methodName>station.getStations</methodName>" @@ -219,9 +223,11 @@ void PianoGetStations (PianoHandle_t *ph) {  			"rid=%s&lid=%s&method=getStations", ph->routeId,  			ph->user.listenerId);  	PianoHttpPost (ph->curlHandle, url, requestStr, &retStr); -	PianoXmlParseStations (ph, retStr); +	ret = PianoXmlParseStations (ph, retStr);  	free (retStr);  	free (requestStr); + +	return ret;  }  /*	get next songs for station (usually four tracks) diff --git a/libpiano/piano.h b/libpiano/piano.h index bad8401..b832b69 100644 --- a/libpiano/piano.h +++ b/libpiano/piano.h @@ -139,7 +139,8 @@ struct PianoSearchResult {  typedef struct PianoSearchResult PianoSearchResult_t;  /* FIXME: more error types (http failed, e.g.) later */ -enum PianoReturn {PIANO_RET_OK, PIANO_RET_ERR}; +enum PianoReturn {PIANO_RET_OK, PIANO_RET_ERR, PIANO_RET_XML_INVALID, +		PIANO_RET_AUTH_TOKEN_INVALID, PIANO_RET_AUTH_USER_PASSWORD_INVALID};  typedef enum PianoReturn PianoReturn_t;  void PianoInit (PianoHandle_t *); @@ -148,9 +149,9 @@ void PianoDestroyPlaylist (PianoHandle_t *ph);  void PianoDestroySearchResult (PianoSearchResult_t *searchResult);  void PianoDestroyStation (PianoStation_t *station);  void PianoDestroyStations (PianoHandle_t *ph); -void PianoConnect (PianoHandle_t *, char *, char *); +PianoReturn_t PianoConnect (PianoHandle_t *, char *, char *); -void PianoGetStations (PianoHandle_t *ph); +PianoReturn_t PianoGetStations (PianoHandle_t *ph);  void PianoGetPlaylist (PianoHandle_t *ph, char *stationId);  PianoReturn_t PianoRateTrack (PianoHandle_t *ph, PianoStation_t *station, diff --git a/libpiano/xml.c b/libpiano/xml.c index 4d4b4b1..f6e21f8 100644 --- a/libpiano/xml.c +++ b/libpiano/xml.c @@ -29,6 +29,71 @@ THE SOFTWARE.  #include "piano.h"  #include "crypt.h" +void PianoXmlStructParser (xmlNode *structRoot, +		void (*callback) (char *, xmlNode *, void *), void *data); +char *PianoXmlGetNodeText (xmlNode *node); + +/*	parse fault and get fault type + */ +void PianoXmlIsFaultCb (char *key, xmlNode *value, void *data) { +	PianoReturn_t *ret = data; +	char *valueStr = PianoXmlGetNodeText (value); +	char *matchStart, *matchEnd, *matchStr; + +	if (strcmp ("faultString", key) == 0) { +		*ret = PIANO_RET_ERR; +		/* find fault identifier in a string like this: +		 * com.savagebeast.radio.api.protocol.xmlrpc.RadioXmlRpcException: +		 * 192.168.160.78|1213101717317|AUTH_INVALID_TOKEN| +		 * Invalid auth token */ +		if ((matchStart = strchr (valueStr, '|')) != NULL) { +			if ((matchStart = strchr (matchStart+1, '|')) != NULL) { +				if ((matchEnd = strchr (matchStart+1, '|')) != NULL) { +					matchStr = calloc (matchEnd - (matchStart+1)+1, +							sizeof (*matchStr)); +					memcpy (matchStr, matchStart+1, matchEnd - +							(matchStart+1)); +					/* translate to our error message system */ +					if (strcmp ("AUTH_INVALID_TOKEN", matchStr) == 0) { +						*ret = PIANO_RET_AUTH_TOKEN_INVALID; +					} else if (strcmp ("AUTH_INVALID_USERNAME_PASSWORD", +							matchStr) == 0) { +						*ret = PIANO_RET_AUTH_USER_PASSWORD_INVALID; +					} else { +						*ret = PIANO_RET_ERR; +						printf (PACKAGE ": Unknown error %s in %s\n", +								matchStr, valueStr); +					} +					free (matchStr); +				} +			} +		} +	} +} + +/*	check whether pandora returned an error or not + *	@author PromyLOPh + *	@added 2008-06-16 + *	@param document root of xml doc + *	@return _RET_OK or fault code (_RET_*) + */ +PianoReturn_t PianoXmlIsFault (xmlNode *docRoot) { +	xmlNode *faultStruct; +	PianoReturn_t ret; + +	/* FIXME: we could get into troubles when fault is not the first child +	 * (pandora yould add whitespace e.g.) */ +	if (docRoot->children != NULL && +			docRoot->children->type == XML_ELEMENT_NODE && +			xmlStrEqual (docRoot->children->name, (xmlChar *) "fault")) { +		/* FIXME: detect fault type */ +		faultStruct = docRoot->children->children->children; +		PianoXmlStructParser (faultStruct, PianoXmlIsFaultCb, &ret); +		return ret; +	} +	return PIANO_RET_OK; +} +  /*	parses things like this:   *	<struct>   *		<member> @@ -89,14 +154,19 @@ void PianoXmlStructParser (xmlNode *structRoot,   */  PianoReturn_t PianoXmlInitDoc (char *xml, xmlDocPtr *doc, xmlNode **docRoot) {  	*doc = xmlReadDoc ((xmlChar *) xml, NULL, NULL, 0); +	PianoReturn_t ret;  	if (*doc == NULL) {  		printf (PACKAGE ": error while parsing this xml document\n%s\n", xml); -		return PIANO_RET_ERR; +		return PIANO_RET_XML_INVALID;  	}  	*docRoot = xmlDocGetRootElement (*doc); +	if ((ret = PianoXmlIsFault (*docRoot)) != PIANO_RET_OK) { +		return ret; +	} +  	return PIANO_RET_OK;  } @@ -190,19 +260,20 @@ void PianoXmlParsePlaylistCb (char *key, xmlNode *value, void *data) {  	}  } -/*	parses server response and updates handle +/*	parses userinfos sent by pandora as login response   *	@author PromyLOPh   *	@added 2008-06-03   *	@param piano handle   *	@param utf-8 string - *	@return nothing + *	@return _RET_OK or error   */ -void PianoXmlParseUserinfo (PianoHandle_t *ph, char *xml) { +PianoReturn_t PianoXmlParseUserinfo (PianoHandle_t *ph, char *xml) {  	xmlNode *docRoot;  	xmlDocPtr doc; +	PianoReturn_t ret; -	if (PianoXmlInitDoc (xml, &doc, &docRoot) != PIANO_RET_OK) { -		return; +	if ((ret = PianoXmlInitDoc (xml, &doc, &docRoot)) != PIANO_RET_OK) { +		return ret;  	}  	/* <methodResponse> <params> <param> <value> <struct> */ @@ -210,6 +281,7 @@ void PianoXmlParseUserinfo (PianoHandle_t *ph, char *xml) {  	PianoXmlStructParser (structRoot, PianoXmlParseUserinfoCb, &ph->user);  	xmlFreeDoc (doc); +	return PIANO_RET_OK;  }  /*	parse stations returned by pandora @@ -217,14 +289,15 @@ void PianoXmlParseUserinfo (PianoHandle_t *ph, char *xml) {   *	@added 2008-06-04   *	@param piano handle   *	@param xml returned by pandora - *	@return nothing + *	@return _RET_OK or error   */ -void PianoXmlParseStations (PianoHandle_t *ph, char *xml) { +PianoReturn_t PianoXmlParseStations (PianoHandle_t *ph, char *xml) {  	xmlNode *docRoot, *curNode;  	xmlDocPtr doc; +	PianoReturn_t ret; -	if (PianoXmlInitDoc (xml, &doc, &docRoot) != PIANO_RET_OK) { -		return; +	if ((ret = PianoXmlInitDoc (xml, &doc, &docRoot)) != PIANO_RET_OK) { +		return ret;  	}  	/* <methodResponse> <params> <param> <value> <array> <data> */ @@ -249,6 +322,7 @@ void PianoXmlParseStations (PianoHandle_t *ph, char *xml) {  	}  	xmlFreeDoc (doc); +	return PIANO_RET_OK;  }  /*	parse "create station" answer (it returns a new station structure) @@ -258,13 +332,14 @@ void PianoXmlParseStations (PianoHandle_t *ph, char *xml) {   *	@param xml document   *	@return nothing yet   */ -void PianoXmlParseCreateStation (PianoHandle_t *ph, char *xml) { +PianoReturn_t PianoXmlParseCreateStation (PianoHandle_t *ph, char *xml) {  	xmlNode *docRoot;  	xmlDocPtr doc;  	PianoStation_t *tmpStation; +	PianoReturn_t ret; -	if (PianoXmlInitDoc (xml, &doc, &docRoot) != PIANO_RET_OK) { -		return; +	if ((ret = PianoXmlInitDoc (xml, &doc, &docRoot)) != PIANO_RET_OK) { +		return ret;  	}  	/* get <struct> node */ @@ -284,6 +359,8 @@ void PianoXmlParseCreateStation (PianoHandle_t *ph, char *xml) {  	}  	xmlFreeDoc (doc); + +	return PIANO_RET_OK;  }  /*	parses playlist; used when searching too @@ -292,12 +369,13 @@ void PianoXmlParseCreateStation (PianoHandle_t *ph, char *xml) {   *	@param piano handle   *	@param xml document   */ -void PianoXmlParsePlaylist (PianoHandle_t *ph, char *xml) { +PianoReturn_t PianoXmlParsePlaylist (PianoHandle_t *ph, char *xml) {  	xmlNode *docRoot, *curNode;  	xmlDocPtr doc; +	PianoReturn_t ret; -	if (PianoXmlInitDoc (xml, &doc, &docRoot) != PIANO_RET_OK) { -		return; +	if ((ret = PianoXmlInitDoc (xml, &doc, &docRoot)) != PIANO_RET_OK) { +		return ret;  	}  	/* <methodResponse> <params> <param> <value> <array> <data> */ @@ -322,6 +400,8 @@ void PianoXmlParsePlaylist (PianoHandle_t *ph, char *xml) {  	}  	xmlFreeDoc (doc); + +	return PIANO_RET_OK;  }  /*	parse simple answers like this: <?xml version="1.0" encoding="UTF-8"?> @@ -335,15 +415,17 @@ void PianoXmlParsePlaylist (PianoHandle_t *ph, char *xml) {  PianoReturn_t PianoXmlParseSimple (char *xml) {  	xmlNode *docRoot;  	xmlDocPtr doc; -	PianoReturn_t ret = PIANO_RET_ERR; +	PianoReturn_t ret; -	if (PianoXmlInitDoc (xml, &doc, &docRoot) != PIANO_RET_OK) { -		return PIANO_RET_ERR; +	if ((ret = PianoXmlInitDoc (xml, &doc, &docRoot)) != PIANO_RET_OK) { +		return ret;  	}  	xmlNode *val = docRoot->children->children->children->children;  	if (xmlStrEqual (val->content, (xmlChar *) "1")) {  		ret = PIANO_RET_OK; +	} else { +		ret = PIANO_RET_ERR;  	}  	xmlFreeDoc (doc); @@ -434,12 +516,14 @@ void PianoXmlParseSearchCb (char *key, xmlNode *value, void *data) {   *	@param returns search result   *	@return nothing yet   */ -void PianoXmlParseSearch (char *searchXml, PianoSearchResult_t *searchResult) { +PianoReturn_t PianoXmlParseSearch (char *searchXml, +		PianoSearchResult_t *searchResult) {  	xmlNode *docRoot, *curNode;  	xmlDocPtr doc; +	PianoReturn_t ret; -	if (PianoXmlInitDoc (searchXml, &doc, &docRoot) != PIANO_RET_OK) { -		return; +	if ((ret = PianoXmlInitDoc (searchXml, &doc, &docRoot)) != PIANO_RET_OK) { +		return ret;  	}  	xmlNode *structRoot = docRoot->children->children->children->children; @@ -448,6 +532,8 @@ void PianoXmlParseSearch (char *searchXml, PianoSearchResult_t *searchResult) {  	PianoXmlStructParser (structRoot, PianoXmlParseSearchCb, searchResult);  	xmlFreeDoc (doc); + +	return PIANO_RET_OK;  }  /*	encode reserved xml chars diff --git a/libpiano/xml.h b/libpiano/xml.h index f8c9106..54deb6e 100644 --- a/libpiano/xml.h +++ b/libpiano/xml.h @@ -23,8 +23,10 @@ THE SOFTWARE.  #ifndef _XML_H  #define _XML_H -void PianoXmlParseUserinfo (PianoHandle_t *ph, char *xml); -void PianoXmlParseStations (PianoHandle_t *ph, char *xml); +#include "piano.h" + +PianoReturn_t PianoXmlParseUserinfo (PianoHandle_t *ph, char *xml); +PianoReturn_t PianoXmlParseStations (PianoHandle_t *ph, char *xml);  void PianoXmlParsePlaylist (PianoHandle_t *ph, char *xml);  void PianoXmlParseSearch (char *searchXml,  		PianoSearchResult_t *searchResult); | 
