<?php

// Set the page title
$title 'php edna';
// script url, should work most of the times.
// If not give the path or url to this script.
$scripturl basename(getenv('SCRIPT_FILENAME'));
// url to the base dir containing your mp3s
$baseurl 'http://alban.dotsec.net/php-edna-demo';
// local path to the base dir
$basepath '/home/alban/public_html/php-edna-demo';

// base path to where the css are stored
$cssurl 'http://alban.dotsec.net/php-edna-css';
// Not used currently
$csspath '/home/alban/public_html/php-edna-css';

// Remote host list
// One can browse content from a server that use the standard
// apache directory listing.
// This is beta and not implemented in the UI, to use it you have
// to manualy add a "host=friend" parameter to your URL.
$host_list = array(
//    'friend' => 'http://friend.lan/music'
);

// max age to be new, in seconds.
$newage 30*24*60*60;

// filters to pick out the zik and pictures
$zikfilter '/\.([Mm][Pp]3|[oO][gG][gG]|[wW][aA][vV])$/';
$picfilter '/\.([j][pP][eE]?[gG]|[pP][nN][gG]|[gG][iI][fF])$/';
$cssfilter '/\.([cC][sS][sS]$/';

// filter for the remote host listing
$httplistfilter '/<a href="(.*?)">(.*?)(\/?)<\/a>/';

function 
var_get($n,$d) {
    if(
array_key_exists($n,$_GET)) return $_GET[$n];
    else return 
$d;
}

function 
clean_path($path) {
    
// kill starting /
    // /../
    // ./
    // starting .
    // trailling /
    
return preg_replace(array('/^\//',  '/\/\.\./''/\.\//','/^\.+/','/\/$/'),'',$path);
}

function 
make_title($name) {
    return 
preg_replace('/\.[a-zA-Z0-9]*$/','',$name);
}

function 
encodepath($p) {
    
$l explode('/',$p);
    
$e = array();
    foreach(
$l as $i)
    
array_push($e,rawurlencode($i));
    return 
implode('/',$e);
}

function 
print_pls($list,$shuffle) {
    global 
$baseurl;

    if(
$shuffleshuffle($list);

    echo 
"[playlist]\n";
    echo 
'numberofentries=' count($list) . "\n";
    
    
$n 1;
    foreach(
$list as $f) {
    echo 
'File' $n '=' $baseurl '/' encodepath($f) . "\n";
    echo 
'Title' $n '=' make_title(basename($f)) . "\n";
    echo 
'Length' $n "=-1\n";
    
$n += 1;
    }

    echo 
"Version=2\n\n";
}

function 
make_file_list($path,$matches,$recurse) {
    global 
$basepath;

    if(!
is_dir($basepath '/' $path)) return array($path);

    
$dd opendir($basepath '/' $path);
    if(
$dd == false) {
    return 
0;
    }

    if(
$recurse$dir = array();
    
$zik = array();

    while((
$file readdir($dd)) == true) {
    if(
$file[0] == ".") continue;
    if(
is_dir($basepath '/' $path '/' $file)) {
        if(
$recursearray_push($dir$path '/' $file);
        continue;
    }
    foreach(
$matches as $m) {
        if(
preg_match($m,$file)) {
        
array_push($zik$path '/' $file);
        break;
        }
    }
    }
    
    
asort($zik);

    if(
$recurse) {
    
asort($dir);
    foreach(
$dir as $d)
        
$zik array_merge($zik,make_file_list($d,$matches,1));
    }

    return 
$zik;
}


function 
make_lists($path) {
    global 
$basepath,$zikfilter,$picfilter;
    
    
$dd opendir($basepath '/' $path);
    if(
$dd == false) return 0;

    
$dir = array();
    
$pic = array();
    
$zik = array();

    while((
$file readdir($dd)) == true) {
    if(
$file[0] == ".") continue;
    if(
is_dir($basepath '/' $path '/' $file))
        
array_push($dir,$file);
    elseif(
preg_match($zikfilter,$file))
        
array_push($zik,$file);
    elseif(
preg_match($picfilter,$file))
        
array_push($pic,$file);
    }
    
closedir($dd);
    return array(
'dir' => $dir'pic' => $pic'zik' => $zik);
}

function 
make_http_list($url) {
    global 
$zikfilter,$picfilter,$httplistfilter;

    
$lines file($url);
    
    
$dir = array();
    
$pic = array();
    
$zik = array();

#    print "Got from" . utf8_encode(htmlentities($url))  . ":<br>\n<pre>" . utf8_encode(htmlentities(implode("",$lines))) . "\n</pre>\n";

     
foreach($lines as $l) {
    if(!
preg_match($httplistfilter,$l,$matches)) continue;

    
$f rawurldecode($matches[1]);

    if(
$matches[3] != '')
        
array_push($dir,$matches[2]);
    else if(
preg_match($zikfilter,$f))
        
array_push($zik,$matches[1]);
    elseif(
preg_match($picfilter,$f))
        
array_push($pic,$f);
    }
    return array(
'dir' => $dir'pic' => $pic'zik' => $zik);
}

function 
make_http_file_list($url,$path,$matches,$recurse) {
    global 
$httplistfilter;

    foreach(
$matches as $m) {
    if(
preg_match($m,$path))
        return array(
$path);
    }

    
// Otherwise estimate it's a dir listing
    
$lines file($url '/' encodepath($path) . '/');

    if(
$recurse$dir = array();
    
$zik = array();

    foreach(
$lines as $l) {
    if(!
preg_match($httplistfilter,$l,$res)) continue;

    
$f rawurldecode($res[1]);

    if(
$res[3] != '') {
        if(
$recursearray_push($dir$path '/' $f);
        continue;
    }
    foreach(
$matches as $m) {
        if(
preg_match($m,$f)) {
        
array_push($zik$path '/' $f);
        break;
        }
    }
    }
    
    
asort($zik);

    if(
$recurse) {
    
asort($dir);
    foreach(
$dir as $d)
        
$zik array_merge($zik,make_http_file_list($url,$d,$matches,1));
    }

    return 
$zik;
}


function 
make_links($path,$href,$back,$css) {
    global 
$title;

    if(
$path == "") {
    echo 
$title;
    return;
    }

    if(
$href) {

    
$p explode('/',$path);
    
$c count($p);
    
$cp ''$cb '';
    if(
$back != '') {
        
$b explode('/',$back);
        if(
count($b) != $c$b 0;
    } else 
$b 0;
        

    echo 
'<a href="' make_url('path','','','&amp;css=' $css);
    if(
$b != 0) {
        echo 
'#' $b[0];
        
$cb $b[0];
    } else {
        
$cb '';
        
$opt '&amp;css=' $css;
    }
    echo 
'">' $title '</a>: ';

    for(
$i $i $c-$i += 1) {
        if(
$cp == ''$cp $p[0];
        else 
$cp $cp '/' $p[$i];
        if(
$cb != ''$opt '&amp;back=' $cb
                  
'&amp;css=' $css
                  
'#' $b[$i+1];
        echo 
'<a href="' make_url('path','',$cp,$opt) . '">'
        
utf8_encode(htmlentities($p[$i])) . '</a> / ';
        if(
$cb != ''$cb $cb '/' $b[$i+1];
    }
    echo 
utf8_encode(htmlentities($p[$i]));
    } else
    echo 
$title ': ' utf8_encode(htmlentities($path));
}


function 
make_url($cmd,$base,$path,$opt) {
    global 
$scripturl,$host;

    if(
$base != ""$p $base '/' $path;
    else 
$p $path;

    if(
$host != '')
    return 
$scripturl '?host=' $host
        
'&amp;' $cmd '='encodepath($p) . $opt;

    return 
$scripturl '?' $cmd '='encodepath($p) . $opt;
}

function 
make_data_url($base,$path) {
    global 
$baseurl;

    if(
$base != ""$p $base '/' $path;
    else 
$p $path;
    return 
$baseurl '/' encodepath($p);
}

function 
get_dir_age($dir) {
    
$dd opendir($dir);
    if(
$dd == false) {
    echo 
"Failed to open directory $path\n";
    return 
0;
    }

    
$ages = array();

    while((
$file readdir($dd)) == true) {
    if(
$file[0] == ".") continue;
    if(
is_dir($dir '/' $file)) {
        
$a get_dir_age($dir '/' $file);
        if(
$a 0array_push($ages,$a);
    } else
        
array_push($ages,filemtime($dir '/' $file));
    }

    if(!
count($ages)) return 0;

    
sort($ages);
    return 
$ages[0];
}

function 
make_new($base,$path) {
    global 
$basepath,$newage;

    if(
$base != ""$p $base '/' $path;
    else 
$p $path;

    
$p $basepath '/' $p;

    if(
is_dir($p)) {
    
$a get_dir_age($p);
    if(
$a == || time() - $a $newage) return '';
    return 
'          <span class="isnew">new since ' date("F d",$a) . "</span>\n";
    }
    

    if(!
file_exists($p)) return '';

    
$mtime filemtime($p);
    
$d time() - $mtime;
    if(
$d $newage) return '';
    
    return 
'          <span class="isnew">new since ' date("F d",$mtime) . "</span>\n";
}
    

function 
print_pics($path,$list) {
    
    if(
count($list) == 0) return;

    
asort($list);
    
reset($list);


    
?>
    <div id="pictureBlock">
<?php 
    $n 
0;
    foreach(
$list as $file) {
    echo 
'      <a class="pictureLink" id="picture' $n  .'" href="' make_data_url($path,$file) . "\">\n";
    echo 
'        <img class="picture" alt="' utf8_encode(htmlentities($file)) . '" src="' make_data_url($path,$file) . "\"/>\n";
    echo 
"      </a>\n";
    
$n++;
    }

 
?>
    </div>
<?php

// print_pics

function print_dirs($path,$list,$back,$css) {
    global 
$host;
    
    if(
count($list) == 0) return;

 
?>

    <div class="listBlock" id="dirListBlock">
      <h2 class="listHeader" id="dirHeader">Subdirectories</h2>
      <ul class="list" id="dirList">
<?php 

    asort
($list);
    
reset($list);
    
$n 0;
    foreach(
$list as $file) {
    if(
$back == '')
        
$b 'dir' $n;
    else
        
$b $back '/dir' $n;
    echo 
'        <li class="dirBlock"  id="dir' $n "\">\n";
        echo 
"          <span class='dirname'>\n";
    echo 
'            <a href="'
        
make_url('path',$path,$file,'&amp;back=' $b 
               
'&amp;css=' $css) . '">' 
        
utf8_encode(htmlentities($file)) . "</a>\n";
    echo 
make_new($path,$file);
    echo 
"          </span>\n";
    echo 
"          <span class='dirAction'>\n";
    echo 
'            <a href="' make_url('pls',$path,$file,'&amp;recurse=1') . "\">Play</a>\n";
    echo 
'            <a href="' make_url('pls',$path,$file,'&amp;recurse=1&amp;queue=1') . "\">Enqueue</a>\n";
    echo 
'            <a href="' make_url('tar',$path,$file,'&amp;recurse=1'). "\">Download</a>\n";
    echo 
"          </span>\n";
    echo 
"        </li>\n";
    
$n++;
    }
    
?>
      </ul>

      <div class="linksBlock" id="dirLinks">
        <h3>Recursively</h3>
        <span class="playAll" id="playAllRecurse">
          <a href='<?php echo make_url('pls','',$path,'&amp;recurse=1'?>'>Play all songs</a>
        </span>
        <span class="enqueueAll" id="enqueueAllRecurse">
      <a href='<?php echo make_url('pls','',$path,'&amp;recurse=1&amp;queue'?>'>Enqueue all songs</a>
    </span>
    <span class="shuffleAll" id="shuffleAllRecurse">
          <a href='<?php echo make_url('pls','',$path,'&amp;recurse=1&amp;shuffle=1'?>'>Shuffle all songs</a>
        </span>
    <span class="enqueueShuffled" id="enqueueShuffledRecurse">
      <a href='<?php echo make_url('pls','',$path,'&amp;recurse=1&amp;shuffle=1&amp;queue'?>'>Enqueue all shuffled songs</a>
    </span>
<?php if($host == '') { ?>
    <span class="tarAll" id="tarAllRecurse">
          <a href='<?php echo make_url('tar','',$path,'&amp;recurse=1'?>'>Download tarball</a>
    </span>
<?php }  ?>
      </div>
    </div>
    
<?php  

// print_dirs



function print_zik($path,$list) {
    global 
$host;

    if(
count($list) == 0) return;

 
?>

    <div class="listBlock" id="fileListBlock">
      <h2 class="listHeader" id="fileHeader">Songs</h2>
      <ul class="list" id="fileList">
<?php
    asort
($list);
    
reset($list);
    
$n 0;
    foreach(
$list as $file) {
    echo 
'        <li class="fileBlock" id="file' $n .  "\">\n";
    echo 
"          <span class='filename'>\n";
    echo 
'            <a href="' make_url('pls',$path,$file,'') . '">'
        
utf8_encode(htmlentities(make_title($file))) . "</a>\n";
    echo 
make_new($path,$file);
    echo 
"          </span>\n";
    echo 
"          <span class='fileAction'>\n";
    echo 
'            <a href="' make_url('pls',$path,$file,'&amp;queue') . '">'
        
'Enqueue</a> <a href="' make_data_url($path,$file). "\">Download</a>\n";
    echo 
"          </span>\n";
    echo 
"        </li>\n";
    
$n++;
    }
    
 
?>
      </ul>

      <div class="linksBlock" id="fileLinks">
        <span class="playAll" id="playAll">
          <a href='<?php echo make_url('pls','',$path,''?>'>Play all songs</a>
    </span>
    <span class="enqueueAll" id="enqueueAll">
      <a href='<?php echo make_url('pls','',$path,'&amp;queue'?>'>Enqueue all songs</a>
        </span>
        <span class="shuffleAll" id="shuffleAll">
          <a href='<?php echo make_url('pls','',$path,'&amp;shuffle=1'?>'>Shuffle all songs</a>
    </span>
        <span class="enqueueShuffled" id="enqueueShuffled">
          <a href='<?php echo make_url('pls','',$path,'&amp;shuffle=1&amp;queue'?>'>Enqueue all shuffled songs</a>
        </span>
<?php if($host == '') { ?>
    <span class="tarAll" id="tarAll">
          <a href='<?php echo make_url('tar','',$path,''?>'>Download tarball</a>
    </span>
<?php }  ?>
      </div>

    </div>

<?php 

// print_zik


// Ouputs



// Our source
if(array_key_exists('hsource',$_GET)) {


 
?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
   "http://www.w3.org/TR/html4/loose.dtd">
<html>
  <head>
    <META http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
    <title>php edna source</title>
  </head>
  <body>
    <p><?php echo highlight_file(getenv('SCRIPT_FILENAME')) ?></p>
  </body>
</html>
<?php
    
return;
}

if(
array_key_exists('source',$_GET)) {
    
header('Content-type: text/plain');

    echo 
readfile(getenv('SCRIPT_FILENAME'));
    return;
}

// A playlist
if(array_key_exists('pls',$_GET)) {
    
$path clean_path($_GET['pls']);

    
$recurse var_get('recurse',0);
    
$shuffle var_get('shuffle',0);
    
$host var_get('host','');
    if(
$host != '') {
    if(
array_key_exists($host,$host_list)) {
        
$baseurl $host_list[$host];
        
$list make_http_file_list($baseurl,$path,array($zikfilter),$recurse);
    } else {
        
$host '';
        
$list = array();
    }
    } else
    
$list make_file_list($path,array($zikfilter),$recurse);
    

    
// This is needed to get the browser to use a .pls filename,
    // Otherwise some app, like xmms, won't open the pls correctly.
    // inline make the download action automatic.
    
header('Content-Disposition: inline;filename=edna.pls');
    if(
array_key_exists('queue'$_GET))
    
header('Content-type: audio/x-scpls-queue');
    else
    
header('Content-type: audio/x-scpls');

    
print_pls($list,$shuffle);

    return;
}

// A tarball
if(array_key_exists('tar',$_GET)) {
    
    
$path clean_path($_GET['tar']);

    
$list make_file_list($path,array($zikfilter,$picfilter),var_get('recurse',0));

    if(
count($list) == 0) {
    
header('Content-type: text/plain');
    
    echo 
"Nothing to tar ????.\n";
    return;
    }

    if(
$path == '')
    
header('Content-Disposition: inline;filename=edna.tar');
    else {
    
$name preg_replace(array('/ /','/\//'),array('_','_'),$path);
    
header('Content-Disposition: inline;filename=' $name '.tar.gz');
    }
    
header('Content-type: application/x-tar');

    
// commented out for the demo
    //passthru('tar c -C "' . $basepath . '" "' . implode('" "',$list) . "\"\n");
    
return;
}


// Normal html output
header('Content-type: text/html; charset=UTF-8');

$host var_get('host','');
if(
array_key_exists($host,$host_list))
    
$baseurl $host_list[$host];
else 
    
$host '';

$path clean_path(var_get('path',''));

$css clean_path(var_get('css','default.css'));

$back var_get('back','');

 
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" 
   "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">

<html>

  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>

    <title><?php make_links($path,0,'',''); ?></title>

    <link media="screen" rel="stylesheet" type="text/css" href='<?php echo $cssurl '/' $css  ?>'/>

  </head>

  <body>
    <h1 id="title"><?php make_links($path,1,$back,$css); ?></h1>

 <?php 

if($host != '') {
    
$l make_http_list($baseurl '/' encodepath($path) . '/');
} else
    
$l make_lists($path);


if(
$l) {
    if(
$l['pic'] || $l['dir'] || $l['zik']) {
    
print_pics($path,$l['pic']);
    
print_dirs($path,$l['dir'],$back,$css);
    
print_zik($path,$l['zik']);
    } else echo 
"    <div id='emptyDir'>Empty directory</div>\n";
} else echo 
"    <div id='failedDir'>Failed to open directory.</div>\n";


?>

    <div id="footer">
      <span id="poweredBy">
        Powered by a php port of <a href="http://edna.sourceforge.net/">edna</a>.
      </span>
      <span id="sourceLinks">
        View the source in <a href="<?php echo $scripturl '?hsource' ?>">highlighted HTML</a> or <a href="<?php echo $scripturl '?source' ?>">plain text</a>.
      </span>
    </div>

  </body>
</html>
1