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($playerphp_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
?>