1 <?php
require_once('./http_auth.php'); /*Delete this line to disable password protection*/ ?
>
2 <?php
$exec_time = round(microtime(true), 3); /*
3 Harvie's JuKe!Box (2oo7-2o1o)
4 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6 * 0.3.6 - Now sorting also directories and have icon link support in css
7 * 0.3.5 - Fixed security bug - directory traversal in filelisting (upgrade recommended)
8 * 0.3.4 - Generating playlist for flashplayer, searching for bugs, cleaning code and preparing for new version release
9 * 0.3.3 - Shorter URLs for flashplayer (due to discussion at #skola ;o), nicer national characters handling
10 * 0.3.2 - Better support for national charsets, few small bugfixes, css improvements, modular search engines
11 * 0.3.1 - Buckfickses in m3u generation, better navigation, magic_quotes_gpc handled, css improvements
12 * 0.3 - Migrated to standalone WPAudioPlayer (better, nicer, with more functions)
13 * 0.2 - Few new functions (search playlist, random,...)
14 * 0.1.1 - Few little fixups, written help.html in Czech language ;o)
15 * 0.1 - All functions are working - TODO: bugfix & replace ugly code
16 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
20 $title = 'Harvie\'s JuKe!Box'; //Title of jukebox
21 $music_dir = './music'; //Local path to directory with music
22 $music_dir_url = 'http://your-server.net/jukebox/music'; //URL path to the same directory
23 $cache_passwd = 'renew123'; //You need this passwd to refresh search cache
24 $sort = 3; //Sort? 0 = none, 1 = playlists, 2 = 1+listings; 3 = 2+search-EXPERIMENTAL! (sorting could eat lot of memory)
25 $access_limit = 40; //How many files could be accessed without using cache (while searching)
28 $charset = 'UTF-8'; //Charset for page
29 $national_characters = 1; //Support searching in filenames with national characters? 0 = no; 1 = yes; (may slowdown search a little)
32 $playlist_name = 'playlist.m3u'; //Name of downloaded pl
33 $m3u_exts = 'ogg|mp[0-9]|wma|wmv|wav'; //Allow only these files
34 $default_random_count = 30; //How many random songs by defaul?
37 $indexlist = array('index.html', 'index.txt'); //Search for this file in each directory
38 $bonus_dir = './jbx'; //Misc. files directory
40 $search_cache = $bonus_dir.'/cache.db'; //Database for searching music (php +rw) - .htaccess: Deny from all!!!
41 $css_file = $bonus_dir.'/themes/default/jukebox.css'; //CSS (Design)
42 $favicon_file = './favicon.png'; //favicon
43 $header_file = $bonus_dir.'/header.html'; //header file
44 $footer_file = $bonus_dir.'/footer.html'; //footer file
46 //Search engines extend search experience
47 $search_engines = array(
48 'Google.com' => 'http://google.com/search?q=',
49 'Images' => 'http://google.com/images?q=',
50 'Karaoke-Lyrics.net' => 'http://www.karaoke-lyrics.net/index.php?page=find&q=',
51 'Jyxo.cz multimedia' => 'http://jyxo.cz/s?d=mm&q=',
52 'Centrum.cz mp3' => 'http://search.centrum.cz/index.php?sec=mp3&q=',
53 'YOUTube.com' => 'http://youtube.com/results?search_query='
56 //Flash MusicPlayer (info about settings: http://wpaudioplayer.com/standalone)
57 $flash_player_swf = $bonus_dir.'/player.swf'; //path to musicplayer
58 $flash_player_frame = 'playframe-show'; //FlashPlayer Target (playframe-show|playframe-hide) - usefull for compatibility with old music player
59 $flash_player_options = '?bg=000099&loader=000000&tracker=AAAAFF&skip=FFFFFF' //.'&leftbg=000077&rightbg=000077&righticon=999999'
60 .'&autostart=yes&initialvolume=100&soundFile='; //& arguments (urlencoded song url will be added)
63 error_reporting(0); //This will disable error reporting, wich can pass sensitive data to users
65 //External configuration file (overrides index.php configuration)
66 @include
('./_config.php');
68 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
72 @ini_set
('magic_quotes_gpc' , 'off');
73 if(get_magic_quotes_gpc()) die("Error: magic_quotes_gpc needs to be disabled!\n");
76 $useflash = is_file($flash_player_swf);
78 //Little magic with directories ;o)
79 if($_SERVER['PATH_INFO']!='') $_GET['dir']=$_SERVER['PATH_INFO'];
80 $current_dir = ereg_replace('/+', '/', '/'.$_GET['dir'].'/');
81 if(eregi('(/|\\\\)\\.\\.(/|\\\\)', $current_dir)) { //check for directory traversal ;)
82 header('Location: ?');
83 die('Error - directory not found!');
85 $dir = $music_dir.$current_dir;
86 $url = $music_dir_url.$current_dir;
87 $parent_dir = dirname($current_dir);
90 function serve_download($filename) {
91 header('Cache-Control: no-cache, no-store, max-age=0, must-revalidate');
92 header('Expires: Mon, 26 Jul 1997 05:00:00 GMT'); // Date in the past
93 header('Pragma: no-cache');
95 //header('Content-Type: application/force-download');
96 header('Content-Type: audio/x-mpegurl');
97 header("Content-Disposition: attachment; filename={$filename}");
98 header('Content-Transfer-Encoding: binary');
100 header('X-PHP-Application: Harvie\'s JuKe!Box');
103 $nchars_f = array('Á','Ä','Č','Ç','Ď','É','Ě','Ë','Í','Ň','Ó','Ö','Ř','Š','Ť','Ú','Ů','Ü','Ý','Ž','á','ä','č','ç','ď','é','ě','ë','í','ň','ó','ö','ř','š','ť','ú','ů','ü','ý','ž');
104 $nchars_t = array('A','A','C','C','D','E','E','E','I','N','O','O','R','S','T','U','U','U','Y','Z','a','a','c','c','d','e','e','e','i','n','o','o','r','s','t','u','u','u','y','z');
106 function unational($text) {
107 if(!$GLOBALS['national_characters']) return $text;
108 return(str_replace($GLOBALS['nchars_f'], $GLOBALS['nchars_t'], $text));
111 function generate_m3u($dir, $prefix='', $recursive=0, $nl="\r\n", $doubleenc=0) {
113 if(isset($_GET['newline'])) $nl = $_GET['newline'];
114 if(!isset($_GET['search'])) {
116 while(($item = readdir($dd)) != false) {
117 if($item == '.' ||
$item == '..') continue;
118 if( is_file($dir.$item) && eregi(('\.('.$GLOBALS['m3u_exts'].')$'), $item) ) {
119 if($GLOBALS['sort'] > 0) {
122 $item=($prefix.'/'.str_replace('%2F', '/', (rawurlencode($dir.$item))).$nl);
123 if($doubleenc) $item = rawurlencode($item);
127 if($recursive && is_dir($dir.$item)) {
128 generate_m3u($dir.$item, $prefix, $recursive, $nl, $doubleenc);
132 if(!($searchfp = fopen($GLOBALS['search_cache'], 'r')))
133 die("Cannot read cache from $outfile<br />Refresh cache or set permissions properly!<br />\n");
134 while(!feof($searchfp)) {
135 $line = trim(fgets($searchfp));
136 if(@eregi
(str_replace(' ', '(.*)', unational($_GET['search'])), unational($line))) {
137 $line=(dirname($GLOBALS['music_dir_url']).'/'.str_replace('%2F', '/', (rawurlencode($line))).$nl);
138 if($doubleenc) $line = rawurlencode($line);
144 if($GLOBALS['sort'] > 0) {
146 foreach($temp as $item) {
147 $temp=($prefix.'/'.str_replace('%2F', '/', (rawurlencode($dir.$item))).$nl);
148 if($doubleenc) $temp = rawurlencode($temp);
154 function write_search_cache($dir, $outfp) {
157 while($item = readdir($dd)) {
158 if($item == '.' ||
$item == '..') continue;
159 if( is_file($dir.$item) && eregi(('\.('.$GLOBALS['m3u_exts'].')$'), $item) ) {
160 fwrite($outfp, $dir.$item."\n");
162 if(is_dir($dir.$item)) {
163 write_search_cache($dir.$item, $outfp);
168 function generate_search_cache($dir, $outfile) {
169 echo("Generating search cache. Please wait...<br />\n"); flush();
170 @chmod
($outfile, 0755); //At least i tryed ;D
171 if(!($outfp = fopen($outfile, 'w')))
172 die("Cannot write cache to $outfile<br />You probably haven't set the permissions properly!<br />\n");
173 write_search_cache($dir, $outfp);
175 $osize = filesize($outfile); clearstatcache();
176 if($GLOBALS['sort'] > 2) {
177 echo("Sorting search cache. Please wait...<br />\n"); flush();
179 $items = file($outfile); @sort
($items);
180 $total = ' ('.sizeof($items).' files)';
181 file_put_contents($outfile, @implode
('', $items));
183 if(abs(filesize($outfile)-$osize) > 2)
184 die('ERROR! Please disable sorting of search cache ($sort < 3)<br />'."\nSorted only ".
185 filesize($outfile).' of '.$osize.' bytes!!!\n');
187 echo('Total: '.filesize($outfile).' of '.$osize.' bytes'.$total.' <a href="?">DONE!</a>'.'<br /><META http-equiv="refresh" content="2;URL=?">'."\n");
190 function render_file_line($dir, $item, $dir_url, $index, $filesize, $parent = false) {
191 $parclass=($index%2?
'even':'odd'); $parcolor=($index%2?
'lightblue':'white');
192 $temp=str_replace('&', '%26', dirname($dir_url)).'/'.str_replace('%2F', '/', (rawurlencode($dir.$item)));
193 if(is_numeric($filesize)) $filesize = round($filesize/(1024*1024), 2);
194 echo("<tr class=\"$parclass\" bgcolor=\"$parcolor\">".'<td><a href="#up">'.$index.'</a></td><td class="btntd">');
195 echo('<a href="?download&song='.rawurlencode($temp).'" class="icon iplay">P</a>');
197 echo('/<a href="?dir='.
198 substr(str_replace(array('&','%2F'), array('%26','/'), (rawurlencode(dirname($dir.$item)))), strlen($GLOBALS['music_dir'])).
199 '" class="icon ifolder">D</a>');
201 if($GLOBALS['useflash'] && eregi(('\.('.$GLOBALS['m3u_exts'].')$'), $item)) {
202 echo('/<a href="?f&song='.rawurlencode($temp).
203 '" target="'.$GLOBALS['flash_player_frame'].'" class="icon ifplay">F</a>/'.
204 '<a href="?blank" target="'.$GLOBALS['flash_player_frame'].'" class="icon ifstop">S</a>');
206 echo(' </td><td class="maximize-width"><a href="'.$temp.'">'.unxss(str_replace('-',' - ',str_replace('_', ' ',
207 $item))).'</a></td><td>'.$filesize." MiB </td></tr>\n");
210 function render_dir_line($current_dir, $item, $i) {
211 $parclass=($i%2?
'even':'odd'); $parcolor=($i%2?
'lightblue':'white');
212 $temp=str_replace('%2F', '/', rawurlencode($current_dir)).rawurlencode($item);
213 echo("<tr class=\"$parclass directory\" bgcolor=\"$parcolor\">".
214 '<td><a href="#up">'.$i.'</a></td><td class="btntd"><a href="?download&playlist&dir='.$temp.'" class="icon iplay">P</a>/'.
215 '<a href="?download&recursive&playlist&dir='.$temp.'" class="icon irplay">R</a>');
216 if($GLOBALS['useflash']) echo('/<a href="?f&playlist&dir='.$temp.'" target="'.$GLOBALS['flash_player_frame'].'" class="icon ifplay">F</a>');
217 echo('</td><td colspan="100%" class="maximize-width"><span class="icon ifolder">[DIR] </span><a href="?dir='.$temp.'">'.unxss(str_replace('_', ' ', $item)).
221 function render_tr_playframe_show() {
222 if($GLOBALS['flash_player_frame'] == 'playframe-show' && $GLOBALS['useflash']) { ?
>
223 <tr id
="playframe-tr">
224 <td
><a href
="?blank" target
="playframe-show" title
="Stop playback" class="icon ifstop">S
</a
></td
>
228 name
="playframe-show"
232 transparentpagebg
="yes"
237 function render_footer() {
239 'This is NOT advertisments. This is just good text to think about... Remove it if you want!',
240 'Downloading without sharing and other forms of leeching equals STEALING! ;P',
241 'Do NOT support Microsoft!!! Use Linux! ;D',
242 'Don\'t steal! Steal and share!!! ;P',
243 'Linux is not matter of price, it\'s matter of freedom!',
244 'This software brought to you by <a href="http://blog.Harvie.cz">Harvie</a> free of charge! Of course...',
245 'Don\'t be looser, use GNU/Linux! ;P',
246 'Make love and not war!',
247 'Take your chance! Prove yourself!',
248 'This software is free of charge. If you wan\'t to donate, please send some money to children in Africa/etc...',
249 'Fork <a href="http://github.com/harvie/jukebox">'.$GLOBALS['title'].'</a> on GIThub :-)<a href="http://github.com/harvie/jukebox"><img style="position: absolute; top: 0; left: 0; border: 0; height:120px; background-color:transparent;" src="http://s3.amazonaws.com/github/ribbons/forkme_left_red_aa0000.png" alt="Fork me on GitHub" /></a>'
252 echo('<span id="quote" style="float: left;"><i><small>'.$quotes[rand(0,sizeof($quotes)-1)]."</small></i></span>\n");
253 echo('<span id="exectime" style="float: right;"><small>Page was generated in '.(round(microtime(true), 3) - $GLOBALS['exec_time']).'
254 seconds</small></span>');
255 @readfile
($GLOBALS['footer_file']);
256 echo('</body></html>');
259 function unxss($string) {
260 return htmlspecialchars($string);
263 function explode_path($dir) {
264 $dir = substr($dir, strlen($GLOBALS['music_dir'])+
1);
265 $temp = split('/', ereg_replace('/+', '/', $dir));
267 for($j=sizeof($temp)-1;$j>0;$j--) {
269 for($i=0;$i<(sizeof($temp)-$j);$i++
) {
272 $out.='<a href="?dir='.rawurlencode($dir).'">'.unxss($temp[$i-1]).'</a>/';
274 return('<a href="?">.</a>/'.$out);
277 function flash_mp3_player() {
279 <html
><head
><title
><?
=$GLOBALS['title']?
>: Flash Music Player Plugin
</title
>
280 <style
> * { margin
: 0; padding
: 0; border
: 0; } </style
></head
><body
>
281 <object width
="100%" height
="344">
283 echo($GLOBALS['flash_player_swf'].$GLOBALS['flash_player_options']);
284 if(isset($_GET['song'])) echo(rawurlencode($_GET['song']));
285 if(isset($_GET['playlist'])) generate_m3u($GLOBALS['dir'], dirname($GLOBALS['music_dir_url']), isset($_GET['recursive']), ',', true);
287 type
="application/x-shockwave-flash"
288 allowscriptaccess
="never"
289 allowfullscreen
="true"
290 transparentpagebg
="yes"
292 width
="100%" height
="24px"
293 >You need Adobe Flash enabled browser to play records directly in website
.</embed
>
294 </object></body
></html
>
299 if(isset($_GET['dj'])) { ?
><title
><?php
echo "DJ MODE @ $title"; ?
></title
><frameset cols
="*,*"><frame name
="dj-left" src
="./"><frame name
="dj-right" src
="./"></frameset
><?php
die(); }
300 if(isset($_GET['download'])) serve_download($playlist_name);
301 if(isset($_GET['f'])) flash_mp3_player();
302 if(isset($_GET['song'])) {
303 die($_GET['song']."\r\n");
308 if($_POST['cache-refresh'] == $cache_passwd) {
309 generate_search_cache($music_dir, $search_cache);
313 if(isset($_GET['playlist'])) {
314 generate_m3u($dir, dirname($music_dir_url), isset($_GET['recursive']));
318 if(isset($_GET['random'])) {
320 if(!($searchfp = fopen($search_cache, 'r')))
321 die("Cannot read cache from $outfile<br />Refresh cache or set permissions properly!<br />\n");
322 while(!feof($searchfp)) { fgets($searchfp); $flen++
; }
323 for($i=0; $i<$_GET['random']; $i++
) {
325 for($j=0; $j<rand(0, $flen-1); $j++
) fgets($searchfp);
326 echo(dirname($music_dir_url).'/'.str_replace('%2F', '/', (rawurlencode(trim(fgets($searchfp)))))."\r\n");
331 if(isset($_GET['blank'])) {
333 <link rel
="stylesheet" type
="text/css" href
="<?=$css_file?>" />
334 <body
class="blank"><div
class="blank"><b
>Music player
</b
> <small
><i
>(click
'F' link next to the song name to start
, 'S' to stop
...)</i
></small
></div
></body
>
340 <meta http
-equiv
="Content-Type" content
="text/html; charset=<?=$charset?>" />
343 <meta charset
="<?=$charset?>" />
344 <link rel
="stylesheet" type
="text/css" href
="<?=$css_file?>" />
345 <link rel
="shortcut icon" href
="<?=$favicon_file?>" />
346 <link href
="<?=$favicon_file?>" rel
="icon" type
="image/gif" />
350 <div align
="right" style
="position: absolute; top: 5px; right: 5px;">
352 <iframe src
="about:blank" name
="playframe-hide" width
="0" height
="0" style
="border: none;" class="hide"></iframe
><!-- -----------???
--------------- -->
353 <span
class="icon"><
;</span
> <a href
="javascript: history.go(-1)" class="icon iback">BACK
</a
>
354 |
<a href
="?" target
="_parent" class="icon ihome">HOME
 
;(<?
=$music_dir?
>)</a
>
355 |
<a href
="?dj" class="icon idjmode">DJ
</a
>
356 |
<a href
="?help" class="icon ihelp">ABOUT
/HELP
</a
>
357 |
<a href
="?logout" class="icon ilogout">LOGOUT
</a
>
361 if(isset($_GET['help'])) {
362 ?
><h1
>About
/Help
</h1
><?php
363 readfile($bonus_dir.'/help.html');
368 if(!isset($_GET['search'])) {
369 echo('<title>'.$title.': '.unxss($dir).'</title>');
370 echo('<a href="?" style="color: black;"><h1 style="float: left;">'.$title.'</h1></a><h2 style="clear: left; display: inline; float: left;">Index of: '.explode_path($dir).'</h2>');
372 echo('<title>'.$title.': '.unxss($_GET['search']).'</title>');
373 echo('<a href="?" style="color: black;"><h1 style="float: left;">'.$title.'</h1></a><h2 style="clear: left; display: inline; float: left;">Searching for: '.unxss($_GET['search']).'</h2>');
381 <span style
="float: right;">
382 <form action
="?" method
="GET" align
="right" style
="display: inline;">
383 <input type
="hidden" name
="download" value
="" />
384 <input type
="number" min
="1" name
="random" value
="<?=$default_random_count?>" style
="width:4em;" title
="how many randomly selected tracks should be in
387 <input type
="submit" value
="random" title
="Generate random music playlist..." />
389 <form action
="?" method
="GET" align
="right" style
="display: inline;">
390 <span
class="icon isearch"></span
><input type
="search" name
="search" autofocus placeholder
="search regexp..."
391 title
="Search in music/google/lyrics/mp3/youtube; Hint: You can use regular expressions in search query..."
392 value
="<?=unxss($_GET['search'])?>"
394 <input type
="submit" value
="search" title
="Search in this JuKe!Box..." />
398 if(!isset($_GET['search'])) {
399 echo('<br style="clear: both;" />');
403 <span style
="float: right;">
404 <form action
="?" method
="POST" align
="right">
405 <input type
="password" name
="cache-refresh" value
="" style
="width:5em;" title
="Password for refreshing - good for avoiding DoS Attacks!!!" />
406 <input type
="submit" value
="refresh cache" title
="You should refresh cache each time when you add new music or upgrade to newer version of JuKe!Box !!!" />
410 <div align
="right" style
="clear: right;" title
="Aditional search engines...">
414 foreach($search_engines as $search_desc => $search_link) {
415 if(!$search_prefix) {
416 echo(unxss($_GET['search'])." @\n");
419 echo('<a href="'.$search_link.rawurlencode($_GET['search']).'">'.$search_desc."</a>;\n");
422 </div
><br style
="clear: both;" />
424 echo('<small>Search DB size: '.(filesize($search_cache)/1024)." kB<br /></small>\n");
426 if(!($searchfp = fopen($search_cache, 'r')))
427 die("Cannot read cache from $outfile<br />Refresh cache or set permissions properly!<br />\n");
430 echo('<table border="1" width="100%">');
431 render_tr_playframe_show();
432 echo('<tr class="directory"><td>S</td><td><a href="?download&playlist&search='.unxss($_GET['search']).'" class="icon iplay">P</a>');
433 if($GLOBALS['useflash']) echo('/<a href="?f&playlist&search='.unxss($_GET['search']).'" target="'.$GLOBALS['flash_player_frame'].'" class="icon ifplay">F</a>');
434 echo('</td><td colspan="100%">Search: '.unxss($_GET['search']).'</td></tr>');
436 while(!feof($searchfp)) {
437 $line = trim(fgets($searchfp));
438 $parclass=($i%2?
'even':'odd'); $parcolor=($i%2?
'lightblue':'white');
439 if(@eregi
(str_replace(' ', '(.*)', unational($_GET['search'])), unational($line))) {
441 $filesize = 0; if($i <= $access_limit) $filesize = filesize($line); else $filesize = 'n/a';
442 render_file_line('', $line, $music_dir_url, $i, $filesize, true);
445 echo('<tr><td colspan="100%">Total: '.$i.' results...</td></tr></table>');
446 render_footer(); die();
449 @readfile
($header_file);
450 foreach($indexlist as $index) @readfile
($dir.$index);
453 <table border
="1" width
="100%">
454 <?php
render_tr_playframe_show(); ?
>
456 <tr
class="directory"><td
>>
;</td
>
457 <td
><a href
="?download&playlist&dir=<?=str_replace('%2F', '/', rawurlencode($current_dir))?>" class="icon iplay">P
</a
>/<a
458 href
="?download&recursive&playlist&dir=<?=str_replace('%2F', '/', rawurlencode($current_dir))?>" class="icon irplay">R
</a
><?php
459 if($GLOBALS['useflash']) echo('/<a href="?f&playlist&dir='.str_replace('%2F', '/', rawurlencode($current_dir)).'" target="'.$GLOBALS['flash_player_frame'].'"
460 class="icon ifplay">F</a>'); ?
>
462 <td colspan
="100%"><?
=unxss($dir)?
></td
></tr
>
463 <tr
><td
>^
</td
><td
> 
;</td
><td colspan
="100%" class="directory"><span
class="icon ifolder">[DIR
] </span
><a href
="?dir=<?=rawurlencode($parent_dir)?>">..
464 (<?
=$parent_dir?
>)</a
></td
></tr
>
469 for($s=2;$s;$s--) { while(($item = readdir($dd)) != false) {
470 if($item == '.' ||
$item == '..') continue;
471 if(($s==2 && is_file($dir.$item)) ||
($s!=2 && is_dir($dir.$item))) continue;
473 //$parclass=($i%2?'even':'odd'); $parcolor=($i%2?'lightblue':'white');
475 if(is_file($dir.$item)) {
479 if(is_dir($dir.$item)) {
484 if(is_file($dir.$item)) {
485 render_file_line($dir, $item, $music_dir_url, $i, filesize($dir.$item));
487 if(is_dir($dir.$item)) {
488 render_dir_line($current_dir, $item, $i);
496 foreach($itemsd as $item) {
498 render_dir_line($current_dir, $item, $i);
500 foreach($itemsf as $item) {
502 render_file_line($dir, $item, $music_dir_url, $i, filesize($dir.$item));