diff options
| -rw-r--r-- | libpiano/src/crypt.c | 41 | ||||
| -rw-r--r-- | libpiano/src/http.c | 4 | ||||
| -rw-r--r-- | libpiano/src/main.c | 16 | ||||
| -rw-r--r-- | libpiano/src/piano.h | 2 | ||||
| -rw-r--r-- | libpiano/src/xml.c | 117 | 
5 files changed, 135 insertions, 45 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 c8497be..2cc519f 100644 --- a/libpiano/src/xml.c +++ b/libpiano/src/xml.c @@ -230,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) { @@ -313,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;  	} @@ -350,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"), @@ -404,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 */ @@ -463,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 */ @@ -536,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"), @@ -557,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 */ @@ -601,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[] = {"&&", "''", "\""", "<<",  			">>", 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; @@ -633,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; @@ -645,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")); | 
