download this file: play.php view text/plain: play.php file encoding: UTF-8 [goback]
<?php
##
## [PHP/MP3] APACHE/PHP4 base very simple mp3 streaming modules(?)
##
## - san2(at)linuxchannel.net
##
## - 2003.04.29(Ver 0.6.7)
## fixed '+' string for user agent guly parsing
## - 2003.01.05(Ver 0.6.6)
## small bug fixed
## - 2002.08.20(Ver 0.6.5)
## support vorbis OGG file
## support RMA(ReadMedia-Player)
## support Zinf(FreeAmp)
## support XMPlay(win)
## - 2002.05.15(Ver 0.5)
## support access logging
## security
## support direct access(such as xmms, winamp ...), then random playing
## - 2002.05.14(Ver 0.3)
## support PHP/4.0.x
## - 2002.05.13(Ver 0.2)
##
## [download]
## - http://ftp.linuxchannel.net/devel/php_stream/
##
## There is no need to use together.
## (such as icecast, apache-mp3, mod_mp3 streaming server)
##
## [reference]
## 0. if mime type isn't registered by IANA(->ICANN),
## adding a "x-" before the subtype
## 1. /usr/local/apache/conf/mime.types.default
## 2. http://sander.vanzoest.com/talks/apachecon/2001/notes/notes_apachecon.txt
## 3. http://www.mp3dev.org/ support mp3 bitrate(use lame)
## 4. RFC 1806, The Content-Disposition Header
## 5. RFC 3003, The audio/mpeg Media Type
## 6. vorbis OGG : http://www.xiph.org/ and http://www.vorbis.com/faq.psp
##
## [test]
## 1. Linux/2.4 (redhat 7.x)
## 2. Apache/1.3.x
## 3. PHP/4.2.x PHP/4.1.x, PHP/4.0.x
## 4. useragent :
## - MSIE5/6
## - netscape/4,6 (linux,win)
## - mozilla/0.9.x(linux)
## - xmms/1.2.x(linux) : ok
## - winamp(win) : ok
## - winmap3(win) : ok
## - Zinf(FreeAMP) : ok
## - XMPlay(win) : ok
## - RMA, RealMedia-Player(win) : ok
## - Window-Media-Player(win) : fail
## - NSPlayer(win) : fail
## 5. test only *.mp3(korean file name success)
## 6. support lame(only *.mp3 bitrate)
## 7. support access log write(options)
## 8. support direct access(such as xmms, winamp ...)
## 9. support vorbis OGG file
##
## [TODO] - I just think.
## 1. user auth(option)
## 2. check more useragent
## 3. more useragent support
## 4. ID3tag support
## 5. mp3 list view and select playing(unit readdir()).
## 6. etc, .... T.T
##
## enjoy !!!
##
#####################################################
##
//session_start();
/***
function session_mp3list($MP3LIST) {
session_register('MP3LIST');
}
***/
## do not set to $GLOBALS in $array
## $GLOBALS dump : _var_dump(get_defined_vars())
##
function _var_dump($array, $name='', $constants=0)
{
foreach($array AS $k=>$v) {
$var = $name ? "${name}[\"$k\"]" : $k;
if(!$constants) $var = '$'.$var;
echo "$var = $v<BR>\n";
if(is_array($v) && sizeof($v)>0) {
echo "<UL>\n";
_var_dump($v,$var,1);
echo "</UL>\n";
}
}
}
## if you using the PHP/4.0.x
## http://www.php.net/ChangeLog-4.php
##
function _globals()
{
global $_SERVER; // add user vars for 4.0.x
if(preg_match('/^4\.0/',PHP_VERSION)) {
$GLOBALS[_SERVER] = array_merge($GLOBALS[HTTP_SERVER_VARS],$_SERVER);
$GLOBALS[_GET] = $GLOBALS[HTTP_GET_VARS];
$GLOBALS[_POST] = $GLOBALS[HTTP_POST_VARS];
$GLOBALS[_COOKIE] = $GLOBALS[HTTP_COOKIE_VARS];
$GLOBALS[_SESSION] = $GLOBALS[HTTP_SESSION_VARS];
$GLOBALS[_ENV] = $GLOBALS[HTTP_ENV_VARS];
$GLOBALS[_FILES] = $GLOBALS[HTTP_POST_FILES]; // ???
$GLOBALS[_REQUEST] = array_merge($_GET,$_COOKIE);
}
}
function check_useragent()
{
global $_SERVER;
$player = 'xmms|Winamp|RMA|Zinf|XMPlay|FreeAMP|RealMedia|Player';
if(preg_match("/$player/i",$_SERVER[HTTP_USER_AGENT]))
{ return 1; }
}
## check for vorbis OGG file
##
function get_ftype($file)
{
if(preg_match('/\.ogg$/i',$file)) {
$ftype[subtype] = 'application/x-ogg';
$ftype[ext] = '&.ogg'; // good idea ???
}
else $ftype[subtype] = 'audio/mpeg';
return $ftype;
}
## mp3 stream core module
##
function php_mp3stream($mp3file, $lame='', $ftype='')
{
$file[name] = basename($mp3file);
$file[size] = filesize($mp3file);
clearstatcache(); // flush buffer
if(is_executable($lame) && !$ftype[ext]) {
clearstatcache(); // flush buffer
$mp3file = "$lame -q 3 -b 64 -m m -S --quiet --silent ".
"--tt '$file[name]' '$mp3file' - 2>/dev/null";
$open = 'popen';
} else $open = 'fopen';
if(!$ftype[subtype]) $ftype[subtype] = 'audio/mpeg';
if($fp = @$open($mp3file,r)) {
header("Content-Type: $ftype[subtype]");
header("Content-Disposition: filename=$file[name]");
header('Content-Transfer-Encoding: binary');
header("Content-Length: $file[size]"); // check(do not win32 agent)
fpassthru($fp);
}
}
## mp3 playlist core module
## 2002.05.15 patch random play(for direct access BAD user)
##
function php_mp3plist($mp3_dir, $mp3list='', $player='') // $mp3list = array();
{
global $_SERVER;
if(is_array($mp3list)) {
if($player) { // for BAD user
$randkey = array_rand($mp3list);
if(is_readable("$mp3_dir/".agent_decode($randfile=$mp3list[$randkey]))) {
$ftype = get_ftype($randfile);
header("Location: http://$_SERVER[HTTP_HOST]$_SERVER[_PHP_SELF]".
"?stream=$randfile$ftype[ext]");
}
exit;
}
header('Content-Disposition: inline; filename=playlist_lcn.m3u');
header('Content-Type: audio/x-mpegurl');
foreach($mp3list AS $k=>$v) {
if(is_readable($mp3file="$mp3_dir/".agent_decode($v))) {
$ftype = get_ftype($mp3file);
echo "http://$_SERVER[HTTP_HOST]$_SERVER[_PHP_SELF]".
"?stream=$v$ftype[ext]\n";
}
}
} else exit; // stop
}
## check and go stream module
## request file(from xmms/winamp)
##
function php_stream($mp3_dir, $mp3list, $mp3file, $lame='')
{
$player = check_useragent();
if($mp3file) {
if(is_readable($mp3file = "$mp3_dir/".agent_decode($mp3file))) {
clearstatcache(); // flush buffer
if($player) php_mp3stream($mp3file,$lame,get_ftype($mp3file));
sleep(1);
}
exit; // force to go next stream
} else php_mp3plist($mp3_dir,$mp3list,$player);
}
function write_log($log_dir)
{
global $_SERVER;
if(!$log_dir) return 0;
$time = date('Y.m.d H:i:s');
$logfile = 'php_stream_access.' . preg_replace('/ .+$/i','',$time) . '.log';
$logformat = sprintf("%-16s%25s \"%s\"\t%s\n",
$_SERVER['REMOTE_ADDR'],"[$time]",$_SERVER['REQUEST_URI'],
$_SERVER['HTTP_USER_AGENT']);
if(file_exists($file="$log_dir/$logfile")) {
if($fp = @fopen($file,r)) {
$content = @fread($fp,filesize($file));
fclose($fp);
}
}
if($fp = @fopen($file,'w+')) {
fputs($fp,$content.$logformat);
fclose($fp);
}
}
## for xmms/winapm
##
function agent_encode($str)
{
$str = base64_encode($str);
return str_replace('+','__PLUS__',$str);
}
function agent_decode($str)
{
$str = str_replace('__PLUS__','+',$str);
return base64_decode($str);
}
## inital var(security) ########################
## do not delete unset() functions
##
unset($mp3_dir);
unset($lame);
unset($file_name);
unset($MP3LIST);
unset($log_dir);
##
#################################################
## configuration ################################
##
$not = 1; // don't print check microtime result
$mp3_dir = '/home/linuxchannel/mp3'; // do not set ducumentroot inside
//$lame = '/usr/local/bin/lame'; // require lame(http://www.mp3dev.org/)
$log_dir = '/home/linuxchannel/mp3/log'; // logging directory(nobody access and writable)
##
## end configuration #############################
## example
##
if($hdle = @opendir($mp3_dir)) {
while($file = readdir($hdle)) { // only 1 depth
if(is_file("$mp3_dir/$file") && is_readable("$mp3_dir/$file") &&
preg_match('/\.(mp3|ogg)$/i',$file))
{ $file_name[] = $file; }
clearstatcache(); // flush buffer
}
closedir($hdle);
}
## must session var or cookie var($MP3LIST)
##
foreach($file_name AS $k=>$v) $MP3LIST[$k] = agent_encode($v);
_globals();
## are you use the 'Action' directive?
##
$_SERVER['_PHP_SELF'] = preg_replace('/\?.*$/','',$_SERVER[REQUEST_URI]);
@write_log($log_dir);
php_stream($mp3_dir,$MP3LIST,$_GET['stream'],$lame);
exit; // don't print any messages
?>