summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libpiano/src/crypt.c41
-rw-r--r--libpiano/src/http.c4
-rw-r--r--libpiano/src/main.c16
-rw-r--r--libpiano/src/piano.h2
-rw-r--r--libpiano/src/xml.c143
5 files changed, 147 insertions, 59 deletions
diff --git a/libpiano/src/crypt.c b/libpiano/src/crypt.c
index 67e2467..9b21516 100644
--- a/libpiano/src/crypt.c
+++ b/libpiano/src/crypt.c
@@ -38,20 +38,24 @@ THE SOFTWARE.
/* decrypt hex-encoded, blowfish-crypted string: decode 2 hex-encoded blocks,
* decrypt, byteswap
* @param hex string
- * @return decrypted string
+ * @return decrypted string or NULL
*/
#define INITIAL_SHIFT 28
#define SHIFT_DEC 4
unsigned char *PianoDecryptString (const unsigned char *strInput) {
/* hex-decode => strlen/2 + null-byte */
- uint32_t *iDecrypt = calloc (strlen ((char *) strInput)/2/sizeof (*iDecrypt)+1, sizeof (*iDecrypt));
- unsigned char *strDecrypted = (unsigned char *) iDecrypt;
- unsigned char shift = INITIAL_SHIFT;
- unsigned char intsDecoded = 0;
- unsigned char j;
+ uint32_t *iDecrypt;
+ unsigned char *strDecrypted;
+ unsigned char shift = INITIAL_SHIFT, intsDecoded = 0, j;
/* blowfish blocks, 32-bit */
uint32_t f, l, r, lrExchange;
+ if ((iDecrypt = calloc (strlen ((char *) strInput)/2/sizeof (*iDecrypt)+1,
+ sizeof (*iDecrypt))) == NULL) {
+ return NULL;
+ }
+ strDecrypted = (unsigned char *) iDecrypt;
+
while (*strInput != '\0') {
/* hex-decode string */
if (*strInput >= '0' && *strInput <= '9') {
@@ -115,20 +119,29 @@ unsigned char *PianoEncryptString (const unsigned char *strInput) {
const size_t strInputN = strlen ((char *) strInput);
/* num of 64-bit blocks, rounded to next block */
size_t blockN = strInputN / 8 + 1;
- uint32_t *blockInput = calloc (blockN*2, sizeof (*blockInput));
- uint32_t *blockPtr = blockInput;
- /* encryption blocks */
- uint32_t f, lrExchange;
- register uint32_t l, r;
+ uint32_t *blockInput, *blockPtr;
/* output string */
- unsigned char *strHex = calloc (blockN*8*2 + 1, sizeof (*strHex));
- unsigned char *hexPtr = strHex;
+ unsigned char *strHex, *hexPtr;
const char *hexmap = "0123456789abcdef";
- size_t i;
+
+ if ((blockInput = calloc (blockN*2, sizeof (*blockInput))) == NULL) {
+ return NULL;
+ }
+ blockPtr = blockInput;
+
+ if ((strHex = calloc (blockN*8*2 + 1, sizeof (*strHex))) == NULL) {
+ return NULL;
+ }
+ hexPtr = strHex;
memcpy (blockInput, strInput, strInputN);
while (blockN > 0) {
+ /* encryption blocks */
+ uint32_t f, lrExchange;
+ register uint32_t l, r;
+ int i;
+
l = byteswap32 (*blockPtr);
r = byteswap32 (*(blockPtr+1));
diff --git a/libpiano/src/http.c b/libpiano/src/http.c
index d33a4e5..f21b839 100644
--- a/libpiano/src/http.c
+++ b/libpiano/src/http.c
@@ -43,6 +43,10 @@ PianoReturn_t PianoHttpPost (WaitressHandle_t *waith, const char *postData,
PianoReturn_t pRet = PIANO_RET_NET_ERROR;
char *reqPostData = PianoEncryptString (postData);
+ if (reqPostData == NULL) {
+ return PIANO_RET_OUT_OF_MEMORY;
+ }
+
waith->extraHeaders = "Content-Type: text/xml\r\n";
waith->postData = reqPostData;
waith->method = WAITRESS_METHOD_POST;
diff --git a/libpiano/src/main.c b/libpiano/src/main.c
index 01e055b..b3bcab8 100644
--- a/libpiano/src/main.c
+++ b/libpiano/src/main.c
@@ -390,7 +390,10 @@ PianoReturn_t PianoRenameStation (PianoHandle_t *ph, PianoStation_t *station,
char *urlencodedNewName, *xmlencodedNewName;
PianoReturn_t ret = PIANO_RET_ERR;
- xmlencodedNewName = PianoXmlEncodeString (newName);
+ if ((xmlencodedNewName = PianoXmlEncodeString (newName)) == NULL) {
+ return PIANO_RET_OUT_OF_MEMORY;
+ }
+
snprintf (xmlSendBuf, sizeof (xmlSendBuf), "<?xml version=\"1.0\"?>"
"<methodCall><methodName>station.setStationName</methodName>"
"<params><param><value><int>%li</int></value></param>"
@@ -479,7 +482,10 @@ PianoReturn_t PianoSearchMusic (PianoHandle_t *ph,
char *xmlencodedSearchStr, *urlencodedSearchStr;
PianoReturn_t ret;
- xmlencodedSearchStr = PianoXmlEncodeString (searchStr);
+ if ((xmlencodedSearchStr = PianoXmlEncodeString (searchStr)) == NULL) {
+ return PIANO_RET_OUT_OF_MEMORY;
+ }
+
snprintf (xmlSendBuf, sizeof (xmlSendBuf), "<?xml version=\"1.0\"?>"
"<methodCall><methodName>music.search</methodName>"
"<params><param><value><int>%li</int></value></param>"
@@ -810,7 +816,11 @@ const char *PianoErrorToStr (PianoReturn_t ret) {
break;
case PIANO_RET_STATION_NONEXISTENT:
- return "Station does not exist";
+ return "Station does not exist.";
+ break;
+
+ case PIANO_RET_OUT_OF_MEMORY:
+ return "Out of memory.";
break;
default:
diff --git a/libpiano/src/piano.h b/libpiano/src/piano.h
index caee1b7..2910e99 100644
--- a/libpiano/src/piano.h
+++ b/libpiano/src/piano.h
@@ -104,7 +104,7 @@ typedef enum {PIANO_RET_OK, PIANO_RET_ERR, PIANO_RET_XML_INVALID,
PIANO_RET_NET_ERROR, PIANO_RET_NOT_AUTHORIZED,
PIANO_RET_PROTOCOL_INCOMPATIBLE, PIANO_RET_READONLY_MODE,
PIANO_RET_STATION_CODE_INVALID, PIANO_RET_IP_REJECTED,
- PIANO_RET_STATION_NONEXISTENT} PianoReturn_t;
+ PIANO_RET_STATION_NONEXISTENT, PIANO_RET_OUT_OF_MEMORY} PianoReturn_t;
void PianoInit (PianoHandle_t *);
void PianoDestroy (PianoHandle_t *);
diff --git a/libpiano/src/xml.c b/libpiano/src/xml.c
index 463caa7..2cc519f 100644
--- a/libpiano/src/xml.c
+++ b/libpiano/src/xml.c
@@ -45,7 +45,7 @@ static void PianoXmlIsFaultCb (const char *key, const ezxml_t value,
void *data) {
PianoReturn_t *ret = data;
char *valueStr = PianoXmlGetNodeText (value);
- char *matchStart, *matchEnd, *matchStr;
+ char *matchStart, *matchEnd;
if (strcmp ("faultString", key) == 0) {
*ret = PIANO_RET_ERR;
@@ -56,36 +56,34 @@ static void PianoXmlIsFaultCb (const char *key, const ezxml_t value,
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));
+ /* changes text in xml node, but we don't care... */
+ *matchEnd = '\0';
+ ++matchStart;
/* translate to our error message system */
- if (strcmp ("AUTH_INVALID_TOKEN", matchStr) == 0) {
+ if (strcmp ("AUTH_INVALID_TOKEN", matchStart) == 0) {
*ret = PIANO_RET_AUTH_TOKEN_INVALID;
} else if (strcmp ("AUTH_INVALID_USERNAME_PASSWORD",
- matchStr) == 0) {
+ matchStart) == 0) {
*ret = PIANO_RET_AUTH_USER_PASSWORD_INVALID;
} else if (strcmp ("LISTENER_NOT_AUTHORIZED",
- matchStr) == 0) {
+ matchStart) == 0) {
*ret = PIANO_RET_NOT_AUTHORIZED;
} else if (strcmp ("INCOMPATIBLE_VERSION",
- matchStr) == 0) {
+ matchStart) == 0) {
*ret = PIANO_RET_PROTOCOL_INCOMPATIBLE;
- } else if (strcmp ("READONLY_MODE", matchStr) == 0) {
+ } else if (strcmp ("READONLY_MODE", matchStart) == 0) {
*ret = PIANO_RET_READONLY_MODE;
} else if (strcmp ("STATION_CODE_INVALID",
- matchStr) == 0) {
+ matchStart) == 0) {
*ret = PIANO_RET_STATION_CODE_INVALID;
} else if (strcmp ("STATION_DOES_NOT_EXIST",
- matchStr) == 0) {
+ matchStart) == 0) {
*ret = PIANO_RET_STATION_NONEXISTENT;
} else {
*ret = PIANO_RET_ERR;
printf (PACKAGE ": Unknown error %s in %s\n",
- matchStr, valueStr);
+ matchStart, valueStr);
}
- PianoFree (matchStr, 0);
}
}
}
@@ -232,18 +230,24 @@ static void PianoXmlParsePlaylistCb (const char *key, const ezxml_t value,
if (strcmp ("audioURL", key) == 0) {
/* last 48 chars of audioUrl are encrypted, but they put the key
- * into the door's lock; dumb pandora... */
+ * into the door's lock... */
const char urlTailN = 48;
const size_t valueStrN = strlen (valueStr);
char *urlTail = NULL,
*urlTailCrypted = &valueStr[valueStrN - urlTailN];
- urlTail = PianoDecryptString (urlTailCrypted);
- song->audioUrl = calloc (valueStrN + 1, sizeof (*song->audioUrl));
- 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);
- PianoFree (urlTail, urlTailN/2);
+
+ if ((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);
+ }
+ PianoFree (urlTail, urlTailN/2);
+ }
} else if (strcmp ("artistSummary", key) == 0) {
song->artist = strdup (valueStr);
} else if (strcmp ("musicId", key) == 0) {
@@ -315,18 +319,32 @@ static void PianoXmlParseQuickMixStationsCb (const char *key, const ezxml_t valu
curNode; curNode = curNode->next) {
idsN++;
if (ids == NULL) {
- ids = calloc (idsN, sizeof (*ids));
+ if ((ids = calloc (idsN, sizeof (*ids))) == NULL) {
+ *retIds = NULL;
+ return;
+ }
} else {
- ids = realloc (ids, idsN * sizeof (*ids));
+ /* 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) {
- ids = calloc (idsN, sizeof (*ids));
+ if ((ids = calloc (idsN, sizeof (*ids))) == NULL) {
+ *retIds = NULL;
+ return;
+ }
} else {
- ids = realloc (ids, idsN * sizeof (*ids));
+ if ((ids = realloc (ids, idsN * sizeof (*ids))) == NULL) {
+ *retIds = NULL;
+ return;
+ }
}
ids[idsN-1] = NULL;
}
@@ -352,9 +370,16 @@ PianoReturn_t PianoXmlParseStations (PianoHandle_t *ph, char *xml) {
for (dataNode = ezxml_child (dataNode, "value"); dataNode;
dataNode = dataNode->next) {
- PianoStation_t *tmpStation = calloc (1, sizeof (*tmpStation));
+ PianoStation_t *tmpStation;
+
+ if ((tmpStation = calloc (1, sizeof (*tmpStation))) == NULL) {
+ ezxml_free (xmlDoc);
+ return PIANO_RET_OUT_OF_MEMORY;
+ }
+
PianoXmlStructParser (ezxml_child (dataNode, "struct"),
PianoXmlParseStationsCb, tmpStation);
+
/* get stations selected for quickmix */
if (tmpStation->isQuickMix) {
PianoXmlStructParser (ezxml_child (dataNode, "struct"),
@@ -406,7 +431,11 @@ PianoReturn_t PianoXmlParseCreateStation (PianoHandle_t *ph, char *xml) {
}
dataNode = ezxml_get (xmlDoc, "params", 0, "param", 0, "value", 0, "struct", -1);
- tmpStation = calloc (1, sizeof (*tmpStation));
+
+ if ((tmpStation = calloc (1, sizeof (*tmpStation))) == NULL) {
+ ezxml_free (xmlDoc);
+ return PIANO_RET_OUT_OF_MEMORY;
+ }
PianoXmlStructParser (dataNode, PianoXmlParseStationsCb, tmpStation);
/* FIXME: copy & waste */
/* start new linked list or append */
@@ -465,7 +494,13 @@ PianoReturn_t PianoXmlParsePlaylist (PianoHandle_t *ph, char *xml) {
for (dataNode = ezxml_child (dataNode, "value"); dataNode;
dataNode = dataNode->next) {
- PianoSong_t *tmpSong = calloc (1, sizeof (*tmpSong));
+ PianoSong_t *tmpSong;
+
+ if ((tmpSong = calloc (1, sizeof (*tmpSong))) == NULL) {
+ ezxml_free (xmlDoc);
+ return PIANO_RET_OUT_OF_MEMORY;
+ }
+
PianoXmlStructParser (ezxml_child (dataNode, "struct"),
PianoXmlParsePlaylistCb, tmpSong);
/* begin linked list or append */
@@ -538,7 +573,13 @@ static void PianoXmlParseSearchCb (const char *key, const ezxml_t value,
/* skip <value><array><data> */
for (curNode = ezxml_child (ezxml_get (value, "array", 0, "data", -1), "value");
curNode; curNode = curNode->next) {
- PianoArtist_t *artist = calloc (1, sizeof (*artist));
+ PianoArtist_t *artist;
+
+ if ((artist = calloc (1, sizeof (*artist))) == NULL) {
+ /* fail silently */
+ break;
+ }
+
memset (artist, 0, sizeof (*artist));
PianoXmlStructParser (ezxml_child (curNode, "struct"),
@@ -559,7 +600,13 @@ static void PianoXmlParseSearchCb (const char *key, const ezxml_t value,
for (curNode = ezxml_child (ezxml_get (value, "array", 0, "data", -1), "value");
curNode; curNode = curNode->next) {
/* FIXME: copy & waste */
- PianoSong_t *tmpSong = calloc (1, sizeof (*tmpSong));
+ PianoSong_t *tmpSong;
+
+ if ((tmpSong = calloc (1, sizeof (*tmpSong))) == NULL) {
+ /* fail silently */
+ break;
+ }
+
PianoXmlStructParser (ezxml_child (curNode, "struct"),
PianoXmlParsePlaylistCb, tmpSong);
/* begin linked list or append */
@@ -603,15 +650,18 @@ PianoReturn_t PianoXmlParseSearch (char *xml,
/* encode reserved xml chars
* TODO: remove and use ezxml_ampencode
* @param encode this
- * @return encoded string
+ * @return encoded string or NULL
*/
char *PianoXmlEncodeString (const char *s) {
char *replacements[] = {"&&amp;", "'&apos;", "\"&quot;", "<&lt;",
">&gt;", NULL};
- char **r;
- char *sOut = calloc (strlen (s) * 5 + 1, sizeof (*sOut)),
- *sOutCurr = sOut;
- char found;
+ char **r, *sOut, *sOutCurr, found;
+
+ if ((sOut = calloc (strlen (s) * 5 + 1, sizeof (*sOut))) == NULL) {
+ return NULL;
+ }
+
+ sOutCurr = sOut;
while (*s != '\0') {
r = replacements;
@@ -635,10 +685,8 @@ char *PianoXmlEncodeString (const char *s) {
}
PianoReturn_t PianoXmlParseGenreExplorer (PianoHandle_t *ph, char *xml) {
- ezxml_t xmlDoc, catNode, genreNode;
+ ezxml_t xmlDoc, catNode;
PianoReturn_t ret;
- PianoGenreCategory_t *tmpGenreCategory;
- PianoStation_t *tmpStation;
if ((ret = PianoXmlInitDoc (xml, &xmlDoc)) != PIANO_RET_OK) {
return ret;
@@ -647,13 +695,26 @@ PianoReturn_t PianoXmlParseGenreExplorer (PianoHandle_t *ph, char *xml) {
/* get all <member> nodes */
for (catNode = ezxml_child (xmlDoc, "category"); catNode;
catNode = catNode->next) {
- tmpGenreCategory = calloc (1, sizeof (*tmpGenreCategory));
+ PianoGenreCategory_t *tmpGenreCategory;
+ ezxml_t genreNode;
+
+ if ((tmpGenreCategory = calloc (1, sizeof (*tmpGenreCategory))) == NULL) {
+ ezxml_free (xmlDoc);
+ return PIANO_RET_OUT_OF_MEMORY;
+ }
+
tmpGenreCategory->name = strdup (ezxml_attr (catNode, "categoryName"));
/* get genre subnodes */
for (genreNode = ezxml_child (catNode, "genre"); genreNode;
genreNode = genreNode->next) {
- tmpStation = calloc (1, sizeof (*tmpStation));
+ PianoStation_t *tmpStation;
+
+ if ((tmpStation = calloc (1, sizeof (*tmpStation))) == NULL) {
+ ezxml_free (xmlDoc);
+ return PIANO_RET_OUT_OF_MEMORY;
+ }
+
/* get genre attributes */
tmpStation->name = strdup (ezxml_attr (genreNode, "name"));
tmpStation->id = strdup (ezxml_attr (genreNode, "stationId"));