Hey Guys, I have a strange problem with my PHP code… perhaps someone here can help identify what’s going on. The purpose of my script is to stream an .mp3 while keeping the location hidden and download hard to get to for the average user.
The streaming part is/was working great. Part of my code deals with a token, everytime an .mp3 is streamed it must look through the database to see if n MD5 hash I post to the script has been used before… if so, then it will not stream the mp3… if not, then it approves the token and begins the stream, and it add’s that track ID and hash to the DB… so it cannot be run again through a forced download through Safari’s activity window for example.
Now, the token process works great… except, when it’s running in Safari or Flash, it simply shows the quicktime logo with a question mark over it. If i try it in Firefox, it streams perfectly. So again, the token process and conditional loop works great, it’s just that it won’t stream the file. Now, if I move my stream function outside the conditional statement, say to the line above, then it will stream through Safari and Flash. So it’s not that the conditional isn’t working, it’s just that it won’t stream it if it’s inside that conditional. Weird, hu?
I’ve tried several variations of the if/else on line 42 to try to get it to work… most recently I put the function in the condition with a return variable, and still no success. You would think there is something wrong with the conditional… I don’t think there is.
Here is the script online… every time you call the URL you must change the token( just add or change a letter). Runs in Firefox, not Safari/Flash. Perhaps it’s something easy I’m just missing.
if ( !preg_match("/^[a-z0-9_]+$/i", $_REQUEST['artistID']) || !preg_match("/^[a-z0-9_]+$/i", $_REQUEST['trackID']))
{
die('No illegal characters');
} else {
//connect to live DB, I omitted the credentials on Kirupa
$username = "...";
$password = "...";
$hostname = "...";
$database = "...";
$dbhandle = mysql_connect($hostname, $username, $password) or die("Unable to connect to MySQL");
mysql_select_db($database,$dbhandle) or die("Could not select $database");
//trackID is the guid for the track in DB, artistID is to matched with guid
$trackID = mysql_real_escape_string(stripslashes($_REQUEST['trackID']));
$artistID = mysql_real_escape_string(stripslashes($_REQUEST['artistID']));
$token = mysql_real_escape_string(stripslashes($_REQUEST['token']));
$tokenexists;
$tokenApproved = false;
//---- token code, select all token entries in token table that match the specific guid(track)
$tokenquery = "SELECT * FROM streamtoken WHERE guid='$trackID'";
$tokenresult = mysql_query($tokenquery) or die("Could not select tokens");
//if($tokenresult && strlen($token) > 5)
//checkToken();
//select matching row with guid in track DB, this is to get the source url
$result = mysql_query("SELECT url FROM eztracks WHERE guid='$trackID'") or die(mysql_error());
$row = mysql_fetch_array( $result ) or die("Invalid query: " . mysql_error());
//create full URL from row's url field, this is hidden from user
$direction = $row[0];
$path = 'http://www.eztun.es/'.$direction;
//if token has been approved from checkToken(), then stream file.
if(checkToken() && strlen($token) > 5)
{
streamfileworks($path);
} else {
header("Content-type: text/javascript");
echo "Stream failed. $tokenexists, $tokenApproved";
}
mysql_close($dbhandle);
}
function checkToken()
{
global $token, $tokenexists, $tokenApproved, $tokenresult, $trackID;
//loop through results, break loop if the current token value is matched with a value in the DB
while($row = mysql_fetch_assoc($tokenresult))
{
if($row['token'] == $token)
{
$tokenexists = "yes";
break;
} else {
$tokenexists = "no";
}
}
//if a matching token was not found, then this token has not been used before. set tokenApproved to true, so track can be streamed
if($tokenexists == "no")
{
$insertTokenQuery = "INSERT INTO streamtoken (guid, token) VALUES ('$trackID', '$token')" ;
$insertTokenResult = mysql_query($insertTokenQuery) or die("Could not insert token");
if($insertTokenResult)
{
$tokenApproved = true;
}
}
return $tokenApproved;
}
function ffilesize($file)
{
//gets the file size for the header length
$ch = curl_init($file);
curl_setopt($ch, CURLOPT_NOBODY, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, true);
$data = curl_exec($ch);
curl_close($ch);
if ($data === false)
return false;
if (preg_match('/Content-Length: (\d+)/', $data, $matches))
return (float)$matches[1];
}
function streamfileworks($path)
{
//get full file size so full track streams. I pulled this from an online example because the "filesize" function was not returning the full size.
$filesize = ffilesize($path);
//make expiration date for header
date_default_timezone_set('GMT');
$date = date(DATE_RFC822);
//header info to set streaming values
header("Content-type: audio/mpeg");
header("Content-Length: $filesize");
header("Expires: -1");
//header("Pragma: no-cache");
header('Content-Disposition: filename="eztunesaudio.mp3"');
header("Cache-Control: no-store, no-cache, must-revalidate");
header("Cache-Control: post-check=0, pre-check=0", false);
readfile($path);
}