/* parse fault and get fault type * @param xml <name> content * @param xml <value> node * @param return error string * @return nothing */ static void PianoXmlIsFaultCb (const char *key, const ezxml_t value, void *data) { PianoReturn_t *ret = data; char *valueStr = PianoXmlGetNodeText (value); char *matchStart, *matchEnd; 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) { /* changes text in xml node, but we don't care... */ *matchEnd = '\0'; ++matchStart; /* translate to our error message system */ if (strcmp ("AUTH_INVALID_TOKEN", matchStart) == 0) { *ret = PIANO_RET_AUTH_TOKEN_INVALID; } else if (strcmp ("AUTH_INVALID_USERNAME_PASSWORD", matchStart) == 0) { *ret = PIANO_RET_AUTH_USER_PASSWORD_INVALID; } else if (strcmp ("LISTENER_NOT_AUTHORIZED", matchStart) == 0) { *ret = PIANO_RET_NOT_AUTHORIZED; } else if (strcmp ("INCOMPATIBLE_VERSION", matchStart) == 0) { *ret = PIANO_RET_PROTOCOL_INCOMPATIBLE; } else if (strcmp ("READONLY_MODE", matchStart) == 0) { *ret = PIANO_RET_READONLY_MODE; } else if (strcmp ("STATION_CODE_INVALID", matchStart) == 0) { *ret = PIANO_RET_STATION_CODE_INVALID; } else if (strcmp ("STATION_DOES_NOT_EXIST", matchStart) == 0) { *ret = PIANO_RET_STATION_NONEXISTENT; } else if (strcmp ("OUT_OF_SYNC", matchStart) == 0) { *ret = PIANO_RET_OUT_OF_SYNC; } else if (strcmp ("PLAYLIST_END", matchStart) == 0) { *ret = PIANO_RET_PLAYLIST_END; } else if (strcmp ("QUICKMIX_NOT_PLAYABLE", matchStart) == 0) { *ret = PIANO_RET_QUICKMIX_NOT_PLAYABLE; } else { *ret = PIANO_RET_ERR; printf (PACKAGE ": Unknown error %s in %s\n", matchStart, valueStr); } } } } } else if (strcmp ("faultCode", key) == 0) { /* some errors can only be identified by looking at their id */ /* detect pandora's ip restriction */ if (strcmp ("12", valueStr) == 0) { *ret = PIANO_RET_IP_REJECTED; } } }
/* xml struct parser callback, used in PianoXmlParseSearchCb */ static void PianoXmlParseSearchArtistCb (const char *key, const ezxml_t value, void *data) { PianoArtist_t *artist = data; char *valueStr = PianoXmlGetNodeText (value); if (strcmp ("artistName", key) == 0) { artist->name = strdup (valueStr); } else if (strcmp ("musicId", key) == 0) { artist->musicId = strdup (valueStr); } }
/* structParser callback; writes userinfo to PianoUserInfo structure * @param value identifier * @param value node * @param pointer to userinfo structure * @return nothing */ static void PianoXmlParseUserinfoCb (const char *key, const ezxml_t value, void *data) { PianoUserInfo_t *user = data; char *valueStr = PianoXmlGetNodeText (value); if (strcmp ("webAuthToken", key) == 0) { user->webAuthToken = strdup (valueStr); } else if (strcmp ("authToken", key) == 0) { user->authToken = strdup (valueStr); } else if (strcmp ("listenerId", key) == 0) { user->listenerId = strdup (valueStr); } }
static void PianoXmlParseStationsCb (const char *key, const ezxml_t value, void *data) { PianoStation_t *station = data; char *valueStr = PianoXmlGetNodeText (value); if (strcmp ("stationName", key) == 0) { station->name = strdup (valueStr); } else if (strcmp ("stationId", key) == 0) { station->id = strdup (valueStr); } else if (strcmp ("isQuickMix", key) == 0) { station->isQuickMix = (strcmp (valueStr, "1") == 0); } else if (strcmp ("isCreator", key) == 0) { station->isCreator = (strcmp (valueStr, "1") == 0); } }
static void PianoXmlParseQuickMixStationsCb (const char *key, const ezxml_t value, void *data) { char ***retIds = data; char **ids = NULL; size_t idsN = 0; ezxml_t curNode; if (strcmp ("quickMixStationIds", key) == 0) { for (curNode = ezxml_child (ezxml_get (value, "array", 0, "data", -1), "value"); curNode; curNode = curNode->next) { idsN++; if (ids == NULL) { if ((ids = calloc (idsN, sizeof (*ids))) == NULL) { *retIds = NULL; return; } } else { /* FIXME: memory leak (on failure) */ if ((ids = realloc (ids, idsN * sizeof (*ids))) == NULL) { *retIds = NULL; return; } } ids[idsN-1] = strdup (PianoXmlGetNodeText (curNode)); } /* append NULL: list ends here */ idsN++; /* FIXME: copy&waste */ if (ids == NULL) { if ((ids = calloc (idsN, sizeof (*ids))) == NULL) { *retIds = NULL; return; } } else { if ((ids = realloc (ids, idsN * sizeof (*ids))) == NULL) { *retIds = NULL; return; } } ids[idsN-1] = NULL; *retIds = ids; } }
/* parse seed struct */ static void PianoXmlParseSeedCb (const char *key, const ezxml_t value, void *data) { struct PianoXmlParseSeedBag *bag = data; assert (bag != NULL); if (strcmp ("song", key) == 0) { assert (bag->song == NULL); if ((bag->song = calloc (1, sizeof (*bag->song))) == NULL) { return; } PianoXmlStructParser (ezxml_child (value, "struct"), PianoXmlParsePlaylistCb, bag->song); } else if (strcmp ("artist", key) == 0) { assert (bag->artist == NULL); if ((bag->artist = calloc (1, sizeof (*bag->artist))) == NULL) { return; } PianoXmlStructParser (ezxml_child (value, "struct"), PianoXmlParseSearchArtistCb, bag->artist); } else if (strcmp ("nonGenomeStation", key) == 0) { /* genre stations are "non genome" station seeds */ assert (bag->station == NULL); if ((bag->station = calloc (1, sizeof (*bag->station))) == NULL) { return; } PianoXmlStructParser (ezxml_child (value, "struct"), PianoXmlParseStationsCb, bag->station); } else if (strcmp ("seedId", key) == 0) { char *valueStr = PianoXmlGetNodeText (value); bag->seedId = strdup (valueStr); } }
static void PianoXmlParsePlaylistCb (const char *key, const ezxml_t value, void *data) { PianoSong_t *song = data; char *valueStr = PianoXmlGetNodeText (value); if (strcmp ("audioURL", key) == 0) { /* last 48 chars of audioUrl are encrypted, but they put the key * into the door's lock... */ const char urlTailN = 48; const size_t valueStrN = strlen (valueStr); char *urlTail = NULL, *urlTailCrypted = &valueStr[valueStrN - urlTailN]; /* don't try to decrypt if string is too short (=> invalid memory * reads/writes) */ if (valueStrN > urlTailN && (urlTail = PianoDecryptString (urlTailCrypted)) != NULL) { if ((song->audioUrl = calloc (valueStrN + 1, sizeof (*song->audioUrl))) != NULL) { memcpy (song->audioUrl, valueStr, valueStrN - urlTailN); /* FIXME: the key seems to be broken... so ignore 8 x 0x08 * postfix; urlTailN/2 because the encrypted hex string is now * decoded */ memcpy (&song->audioUrl[valueStrN - urlTailN], urlTail, urlTailN/2 - 8); } free (urlTail); } } else if (strcmp ("artRadio", key) == 0) { song->coverArt = strdup (valueStr); } else if (strcmp ("artistSummary", key) == 0) { song->artist = strdup (valueStr); } else if (strcmp ("musicId", key) == 0) { song->musicId = strdup (valueStr); } else if (strcmp ("userSeed", key) == 0) { song->userSeed = strdup (valueStr); } else if (strcmp ("songTitle", key) == 0) { song->title = strdup (valueStr); } else if (strcmp ("rating", key) == 0) { if (strcmp (valueStr, "1") == 0) { song->rating = PIANO_RATE_LOVE; } else { song->rating = PIANO_RATE_NONE; } } else if (strcmp ("stationId", key) == 0) { song->stationId = strdup (valueStr); } else if (strcmp ("albumTitle", key) == 0) { song->album = strdup (valueStr); } else if (strcmp ("fileGain", key) == 0) { song->fileGain = atof (valueStr); } else if (strcmp ("audioEncoding", key) == 0) { if (strcmp (valueStr, "aacplus") == 0) { song->audioFormat = PIANO_AF_AACPLUS; } else if (strcmp (valueStr, "mp3") == 0) { song->audioFormat = PIANO_AF_MP3; } else if (strcmp (valueStr, "mp3-hifi") == 0) { song->audioFormat = PIANO_AF_MP3_HI; } } else if (strcmp ("artistMusicId", key) == 0) { song->artistMusicId = strdup (valueStr); } else if (strcmp ("testStrategy", key) == 0) { song->testStrategy = atoi (valueStr); } else if (strcmp ("songType", key) == 0) { song->songType = atoi (valueStr); } }