Want XSPF playlists from playlist.com ?

Recently I found that I could not use the playlists I had created on playlist.com in my media player. The quick and short of this is that they are not providing a standardized XSPF format in their RSS feed.
All I really had to do was determine how to decrypt their hash which was pretty easy thanks to OneWeirdKid90, rename a few fields, and export a correctly formatted XSPF file. Below is the resultant code. I am using the script to access all the playlists on this site via playlist.com.

function hexToChars($hex) {
	$a = array();
	$b = (substr($hex, 0, 2) == "0x") ? 2 : 0;
	while ($b < strlen($hex)) {
		array_push($a, intval(substr($hex, $b, 2), 16));
		$b += 2;
	}
	return $a;
}
 
function charsToStr($chars) {
	$a = "";
	$b = 0;
	while ($b < count($chars)) {
		$a .= chr($chars[$b]);
		++$b;
	}
	return $a;
}
 
function strToChars($str) {
	$a = array();
	$b = 0;
	while ($b < strlen($str)) {
		array_push($a, ord($str[$b]));
		++$b;
	}
	return $a;
}
 
function calculate($plaintxt, $psw) {
	$sbox = array();
	$mykey = array();
 
	$a = 0;
	$b;
	$c = count($psw);
	$d = 0;
	while ($d <= 255) {
		$mykey[$d] = $psw[$d % $c];
		$sbox[$d] = $d;
		++$d;
	}
	$d = 0;
	while ($d <= 255) {
		$a = ($a + $sbox[$d] + $mykey[$d]) % 256;
		$b = $sbox[$d];
		$sbox[$d] = $sbox[$a];
		$sbox[$a] = $b;
		++$d;
	}
 
	$a = 0;
	$b = 0;
	$c = array();
	$d;
	$e;
	$f;
	$g = 0;
	while ($g < count($plaintxt)) {
		$a = ($a + 1) % 256;
		$b = ($b + $sbox[$a]) % 256;
		$e = $sbox[$a];
 
		$sbox[$a] = $sbox[$b];
 
		$sbox[$b] = $e;
		$h = ($sbox[$a] + $sbox[$b]) % 256;
		$d = $sbox[$h];
		$f = $plaintxt[$g] ^ $d;
		array_push($c, $f);
		++$g;
	}
	return $c;
}
 
function decrypt($src, $key) {
	return charsToStr(calculate(hexToChars($src), strToChars($key)));
}
 
$hashKey = "sdf883jsdf22";
 
$playlist = $_GET["playlist"];
if (!$playlist) {
	exit;
}
$url = "http://pl.playlist.com/pl.php?playlist=".$playlist;
 
$dom = new DOMDocument("1.0", "UTF-8");
$dom->formatOutput = true;
 
$playlist = $dom->createElement("playlist");
$playlist->setAttribute("version", "0");
$playlist->setAttribute("xmlns", "http://xspf.org/ns/0/");
$dom->appendChild($playlist);
 
$metaCacheControl = $dom->createElement("meta");
$metaCacheControl->setAttribute("http-equiv", "Cache-Control");
$metaCacheControl->setAttribute("content", "no-cache");
$playlist->appendChild($metaCacheControl);
 
$metaPragma = $dom->createElement("meta");
$metaPragma->setAttribute("http-equiv", "Pragma");
$metaPragma->setAttribute("content", "no-cache");
$playlist->appendChild($metaPragma);
 
$info = $dom->createElement("info", $url);
$playlist->appendChild($info);
 
$contents = file_get_contents($url, "r");
if (!empty($contents)) {
	$xml = new SimpleXMLElement($contents);
	if (!empty($xml)) {
		$title = $dom->createElement("title", $xml->title);
		$playlist->appendChild($title);
 
		$trackList = $dom->createElement("trackList");
		$playlist->appendChild($trackList);
 
		if ($xml->trackList && (count($xml->trackList) > 0)) {
			foreach ($xml->trackList->track as $item) {
				$track = $dom->createElement("track");
				$trackList->appendChild($track);
 
				$location = $dom->createElement("location");
				$usableLocation = empty($item->location) ? $item->originallocation : decrypt($item->location, $hashKey);
				$location->appendChild($dom->createTextNode($usableLocation));
				$track->appendChild($location);
 
				$title = $dom->createElement("title");
				$title->appendChild($dom->createTextNode($item->tracktitle));
				$track->appendChild($title);
 
				$creator = $dom->createElement("creator");
				$creator->appendChild($dom->createTextNode($item->artist));
				$track->appendChild($creator);
 
				/*
				$duration = $dom->createElement("duration");
				$creator->appendChild($dom->createTextNode($item->duration));
				$track->appendChild($duration);
				*/
 
				/*
				$album = $dom->createElement("album");
				$creator->appendChild($dom->createTextNode($item->album));
				$track->appendChild($album);
				*/
 
				/*
				$image = $dom->createElement("image");
				$creator->appendChild($dom->createTextNode($item->image));
				$track->appendChild($image);
				*/
			}
		}
	}
}
 
header("Content-Type: application/xspf+xml");
 
echo $dom->saveXML();

the 4th 2009

Yesterday was awesome. We all went to Dairy Queen for lunch and let Keenan eat his own ice cream which went well, hardly any mess. On the way back we found another shortcut and stopped to pick up Julies’ new bike. She was pretty excited as there has been some jealousy when Keenan and I take off for a ride. So after Keenans nap we all hopped on our bikes and took off down the Guadalupe River Trail.

We had already decided that Keenan would be up with us for fireworks and we managed to keep him awake long enough for him to head up to the rooftop with us to see some sparks( actually he calls them spots ). He was a wreck by the time they were all finished. I was able to see at least a half dozen different shows in progress. Nothing was close enough to be overhead but it was still cool to see a bunch of different displays. We finally got him down around 10:15 which I think is the latest he has been up to date, shy of being sick.

Andrea came over to hang with us and see some spots as well. After the show we ordered some pizza and had a few drinks on the porch and talked. Eventually we realized it was after midnight and called it a day. Time flies…

No more crib

Last night was Keenan’s first night out of his crib. It was also the first night in over 2 weeks that he hasn’t been up several times during the night crying. We decided to take down the walls after noticing several markers like telling us he was ready to go ‘night night’ and laying down on his own. Added benefit… he slept in an hour later and didn’t cry this morning. We are also going to let him determine if he wants to take a day nap by leaving him gated in his room during his normal naptime. We’ll see how that goes today.

Happy 7th to us

Today is our 7th wedding anniversary. I still remember the day like it was yesterday. One of the happiest days of my life thus far. And after 7 years I love her more than I did then.

Here’s to the perfect wife and the best Mom in the world!

Past SJC Airport

Well we made it past the airport today heading north on the Guadalupe River Trail. It was such a trek we ended up having to take the rail back home. We stopped off at IHOP on the way back and got some crepes. Mmmm Keenan’s favorite.

Guadalupe bike trail

Well the first run at the trail with Keenan went great. We recently got a bike from some friends of ours. Keenan then quickly decided that he needed to go on some bike rides so we went out and bought a trailer for him so he could tag along. He LOVES it.

The Guadalupe River Trail is within 2 blocks of our place and provides almost 15 miles of trails for us to ride on. Couldn’t be a more perfect setup.

photo

photo

photo

RIP T Roy

Troy Lane Ernest, 34, of Olney, died at 10:32 a.m. Sunday, May 10, 2009, at his residence.

After switching to a mac at wo…

After switching to a mac at work, what’s up with proprietary key mapping… seriously

Looks like GV Mobile may get a…

Looks like GV Mobile may get approved this weekend, according to my sources.

Finally out of jail :) well my…

Finally out of jail :) well my iPhone is anyway. Report to follow on the “nothing works like the instructions” approach that I took.