summaryrefslogtreecommitdiff
path: root/libpiano
diff options
context:
space:
mode:
authorLars-Dominik Braun <PromyLOPh@gmail.com>2008-06-17 12:13:56 +0200
committerLars-Dominik Braun <PromyLOPh@gmail.com>2008-06-17 12:13:56 +0200
commit56432d661e34de9aa0d1727fb7b06f19aa18723e (patch)
tree11cd9f4272afae4867496dc942f35866718d2a7c /libpiano
parentdddcf192c7c9d3a4cb19e7523d81ed2b11d560ad (diff)
downloadpianobar-56432d661e34de9aa0d1727fb7b06f19aa18723e.tar.gz
pianobar-56432d661e34de9aa0d1727fb7b06f19aa18723e.tar.bz2
pianobar-56432d661e34de9aa0d1727fb7b06f19aa18723e.zip
More error handling.
Now we can parse and handle pandora's <fault> messages and abort the parsing process. Some more fault type should be added, as well as more client support for those errors.
Diffstat (limited to 'libpiano')
-rw-r--r--libpiano/main.c14
-rw-r--r--libpiano/piano.h7
-rw-r--r--libpiano/xml.c130
-rw-r--r--libpiano/xml.h6
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);