<?php1
// 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($shuffle) shuffle($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($recurse) array_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($recurse) array_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','','','&css=' . $css);
if($b != 0) {
echo '#' . $b[0];
$cb = $b[0];
} else {
$cb = '';
$opt = '&css=' . $css;
}
echo '">' . $title . '</a>: ';
for($i = 0 ; $i < $c-1 ; $i += 1) {
if($cp == '') $cp = $p[0];
else $cp = $cp . '/' . $p[$i];
if($cb != '') $opt = '&back=' . $cb
. '&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
. '&' . $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 > 0) array_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 == 0 || 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,'&back=' . $b
. '&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,'&recurse=1') . "\">Play</a>\n";
echo ' <a href="' . make_url('pls',$path,$file,'&recurse=1&queue=1') . "\">Enqueue</a>\n";
echo ' <a href="' . make_url('tar',$path,$file,'&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,'&recurse=1') ?>'>Play all songs</a>
</span>
<span class="enqueueAll" id="enqueueAllRecurse">
<a href='<?php echo make_url('pls','',$path,'&recurse=1&queue') ?>'>Enqueue all songs</a>
</span>
<span class="shuffleAll" id="shuffleAllRecurse">
<a href='<?php echo make_url('pls','',$path,'&recurse=1&shuffle=1') ?>'>Shuffle all songs</a>
</span>
<span class="enqueueShuffled" id="enqueueShuffledRecurse">
<a href='<?php echo make_url('pls','',$path,'&recurse=1&shuffle=1&queue') ?>'>Enqueue all shuffled songs</a>
</span>
<?php if($host == '') { ?>
<span class="tarAll" id="tarAllRecurse">
<a href='<?php echo make_url('tar','',$path,'&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,'&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,'&queue') ?>'>Enqueue all songs</a>
</span>
<span class="shuffleAll" id="shuffleAll">
<a href='<?php echo make_url('pls','',$path,'&shuffle=1') ?>'>Shuffle all songs</a>
</span>
<span class="enqueueShuffled" id="enqueueShuffled">
<a href='<?php echo make_url('pls','',$path,'&shuffle=1&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>