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 $base_url = preg_replace('/[^\/]*$/', '', $_SERVER['SCRIPT_NAME']); //URL of this directory (always ends with slash)
23 $music_dir_url = 'http://your-server.net/jukebox/music'; //URL path to the same directory
24 $cache_passwd = 'renew123'; //You need this passwd to refresh search cache
25 $sort = 3; //Sort? 0 = none, 1 = playlists, 2 = 1+listings; 3 = 2+search-EXPERIMENTAL! (sorting could eat lot of memory)
26 $access_limit = 40; //How many files could be accessed without using cache (while searching)
29 $charset = 'UTF-8'; //Charset for page
30 $national_characters = 1; //Support searching in filenames with national characters? 0 = no; 1 = yes; (may slowdown search a little)
33 $playlist_name = 'playlist.m3u'; //Name of downloaded pl
34 $m3u_exts = 'ogg|mp[0-9]|wma|wmv|wav'; //Allow only these files
35 $default_random_count = 30; //How many random songs by defaul?
38 $indexlist = array('index.html', 'index.txt'); //Search for this file in each directory
39 $bonus_dir = 'jbx'; //Misc. files directory
41 $search_cache = $bonus_dir.'/cache.db'; //Database for searching music (php +rw) - .htaccess: Deny from all!!!
42 $css_file = $base_url.$bonus_dir.'/themes/default/jukebox.css'; //CSS (Design)
43 $favicon_file = $base_url.'favicon.png'; //favicon
44 $header_file = $bonus_dir.'/header.html'; //header file
45 $footer_file = $bonus_dir.'/footer.html'; //footer file
47 //Search engines extend search experience
48 $search_engines = array(
49 'Google.com' => 'http://google.com/search?q=',
50 'Images' => 'http://google.com/images?q=',
51 'Karaoke-Lyrics.net' => 'http://www.karaoke-lyrics.net/index.php?page=find&q=',
52 'Jyxo.cz multimedia' => 'http://jyxo.cz/s?d=mm&q=',
53 'Centrum.cz mp3' => 'http://search.centrum.cz/index.php?sec=mp3&q=',
54 'YOUTube.com' => 'http://youtube.com/results?search_query='
57 //Flash MusicPlayer (info about settings: http://wpaudioplayer.com/standalone)
58 $flash_player_swf = $bonus_dir.'/player.swf'; //path to musicplayer
59 $flash_player_frame = 'playframe-show'; //FlashPlayer Target (playframe-show|playframe-hide) - usefull for compatibility with old music player
60 $flash_player_options = '?bg=000099&loader=000000&tracker=AAAAFF&skip=FFFFFF' //.'&leftbg=000077&rightbg=000077&righticon=999999'
61 .'&autostart=yes&initialvolume=100&soundFile='; //& arguments (urlencoded song url will be added)
64 error_reporting(0); //This will disable error reporting, wich can pass sensitive data to users
66 //External configuration file (overrides index.php configuration)
67 @include
('./_config.php');
69 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
73 @ini_set
('magic_quotes_gpc' , 'off');
74 if(get_magic_quotes_gpc()) die("Error: magic_quotes_gpc needs to be disabled!\n");
77 $useflash = is_file($flash_player_swf);
79 //Little magic with directories ;o)
80 if($_SERVER['PATH_INFO']!='') $_GET['dir']=$_SERVER['PATH_INFO'];
81 $current_dir = ereg_replace('/+', '/', '/'.$_GET['dir'].'/');
82 if(eregi('(/|\\\\)\\.\\.(/|\\\\)', $current_dir)) { //check for directory traversal ;)
83 header('Location: ?');
84 die('Error - directory not found!');
86 $dir = $music_dir.$current_dir;
87 $url = $music_dir_url.$current_dir;
88 $parent_dir = dirname($current_dir);
91 function serve_download($filename) {
92 header('Cache-Control: no-cache, no-store, max-age=0, must-revalidate');
93 header('Expires: Mon, 26 Jul 1997 05:00:00 GMT'); // Date in the past
94 header('Pragma: no-cache');
96 //header('Content-Type: application/force-download');
97 header('Content-Type: audio/x-mpegurl');
98 header("Content-Disposition: attachment; filename={$filename}");
99 header('Content-Transfer-Encoding: binary');
101 header('X-PHP-Application: Harvie\'s JuKe!Box');
104 $nchars_f = array('Á','Ä','Č','Ç','Ď','É','Ě','Ë','Í','Ň','Ó','Ö','Ř','Š','Ť','Ú','Ů','Ü','Ý','Ž','á','ä','č','ç','ď','é','ě','ë','í','ň','ó','ö','ř','š','ť','ú','ů','ü','ý','ž');
105 $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');
107 function unational($text) {
108 if(!$GLOBALS['national_characters']) return $text;
109 return(str_replace($GLOBALS['nchars_f'], $GLOBALS['nchars_t'], $text));
112 function generate_m3u($dir, $prefix='', $recursive=0, $nl="\r\n", $doubleenc=0) {
114 if(isset($_GET['newline'])) $nl = $_GET['newline'];
115 if(!isset($_GET['search'])) {
117 while(($item = readdir($dd)) != false) {
118 if($item == '.' ||
$item == '..') continue;
119 if( is_file($dir.$item) && eregi(('\.('.$GLOBALS['m3u_exts'].')$'), $item) ) {
120 if($GLOBALS['sort'] > 0) {
123 $item=($prefix.'/'.str_replace('%2F', '/', (rawurlencode($dir.$item))).$nl);
124 if($doubleenc) $item = rawurlencode($item);
128 if($recursive && is_dir($dir.$item)) {
129 generate_m3u($dir.$item, $prefix, $recursive, $nl, $doubleenc);
133 if(!($searchfp = fopen($GLOBALS['search_cache'], 'r')))
134 die("Cannot read cache from $outfile<br />Refresh cache or set permissions properly!<br />\n");
135 while(!feof($searchfp)) {
136 $line = trim(fgets($searchfp));
137 if(@eregi
(str_replace(' ', '(.*)', unational($_GET['search'])), unational($line))) {
138 $line=(dirname($GLOBALS['music_dir_url']).'/'.str_replace('%2F', '/', (rawurlencode($line))).$nl);
139 if($doubleenc) $line = rawurlencode($line);
145 if($GLOBALS['sort'] > 0) {
147 foreach($temp as $item) {
148 $temp=($prefix.'/'.str_replace('%2F', '/', (rawurlencode($dir.$item))).$nl);
149 if($doubleenc) $temp = rawurlencode($temp);
155 function write_search_cache($dir, $outfp) {
158 while($item = readdir($dd)) {
159 if($item == '.' ||
$item == '..') continue;
160 if( is_file($dir.$item) && eregi(('\.('.$GLOBALS['m3u_exts'].')$'), $item) ) {
161 fwrite($outfp, $dir.$item."\n");
163 if(is_dir($dir.$item)) {
164 write_search_cache($dir.$item, $outfp);
169 function generate_search_cache($dir, $outfile) {
170 echo("Generating search cache. Please wait...<br />\n"); flush();
171 @chmod
($outfile, 0755); //At least i tryed ;D
172 if(!($outfp = fopen($outfile, 'w')))
173 die("Cannot write cache to $outfile<br />You probably haven't set the permissions properly!<br />\n");
174 write_search_cache($dir, $outfp);
176 $osize = filesize($outfile); clearstatcache();
177 if($GLOBALS['sort'] > 2) {
178 echo("Sorting search cache. Please wait...<br />\n"); flush();
180 $items = file($outfile); @sort
($items);
181 $total = ' ('.sizeof($items).' files)';
182 file_put_contents($outfile, @implode
('', $items));
184 if(abs(filesize($outfile)-$osize) > 2)
185 die('ERROR! Please disable sorting of search cache ($sort < 3)<br />'."\nSorted only ".
186 filesize($outfile).' of '.$osize.' bytes!!!\n');
188 echo('Total: '.filesize($outfile).' of '.$osize.' bytes'.$total.' <a href="?">DONE!</a>'.'<br /><META http-equiv="refresh" content="2;URL=?">'."\n");
191 function render_file_line($dir, $item, $dir_url, $index, $filesize, $parent = false) {
192 $parclass=($index%2?
'even':'odd'); $parcolor=($index%2?
'lightblue':'white');
193 $temp=str_replace('&', '%26', dirname($dir_url)).'/'.str_replace('%2F', '/', (rawurlencode($dir.$item)));
194 if(is_numeric($filesize)) $filesize = round($filesize/(1024*1024), 2);
195 echo("<tr class=\"$parclass\" bgcolor=\"$parcolor\">".'<td><a href="#up">'.$index.'</a></td><td class="btntd">');
196 echo('<a href="?download&song='.rawurlencode($temp).'" class="icon iplay">P</a>');
198 echo('/<a href="?dir='.
199 substr(str_replace(array('&','%2F'), array('%26','/'), (rawurlencode(dirname($dir.$item)))), strlen($GLOBALS['music_dir'])).
200 '" class="icon ifolder">D</a>');
202 if($GLOBALS['useflash'] && eregi(('\.('.$GLOBALS['m3u_exts'].')$'), $item)) {
203 echo('/<a href="?f&song='.rawurlencode($temp).
204 '" target="'.$GLOBALS['flash_player_frame'].'" class="icon ifplay">F</a>/'.
205 '<a href="?blank" target="'.$GLOBALS['flash_player_frame'].'" class="icon ifstop">S</a>');
207 echo(' </td><td class="maximize-width"><a href="'.$temp.'">'.unxss(str_replace('-',' - ',str_replace('_', ' ',
208 $item))).'</a></td><td>'.$filesize." MiB </td></tr>\n");
211 function render_dir_line($current_dir, $item, $i) {
212 $parclass=($i%2?
'even':'odd'); $parcolor=($i%2?
'lightblue':'white');
213 $temp=str_replace('%2F', '/', rawurlencode($current_dir)).rawurlencode($item);
214 echo("<tr class=\"$parclass directory\" bgcolor=\"$parcolor\">".
215 '<td><a href="#up">'.$i.'</a></td><td class="btntd"><a href="?download&playlist&dir='.$temp.'" class="icon iplay">P</a>/'.
216 '<a href="?download&recursive&playlist&dir='.$temp.'" class="icon irplay">R</a>');
217 if($GLOBALS['useflash']) echo('/<a href="?f&playlist&dir='.$temp.'" target="'.$GLOBALS['flash_player_frame'].'" class="icon ifplay">F</a>');
218 echo('</td><td colspan="100%" class="maximize-width"><span class="icon ifolder">[DIR] </span><a href="?dir='.$temp.'">'.unxss(str_replace('_', ' ', $item)).
222 function render_tr_playframe_show() {
223 if($GLOBALS['flash_player_frame'] == 'playframe-show' && $GLOBALS['useflash']) { ?
>
224 <tr id
="playframe-tr">
225 <td
><a href
="?blank" target
="playframe-show" title
="Stop playback" class="icon ifstop">S
</a
></td
>
229 name
="playframe-show"
233 transparentpagebg
="yes"
238 function render_footer() {
240 'This is NOT advertisments. This is just good text to think about... Remove it if you want!',
241 'Downloading without sharing and other forms of leeching equals STEALING! ;P',
242 'Do NOT support Microsoft!!! Use Linux! ;D',
243 'Don\'t steal! Steal and share!!! ;P',
244 'Linux is not matter of price, it\'s matter of freedom!',
245 'This software brought to you by <a href="http://blog.Harvie.cz">Harvie</a> free of charge! Of course...',
246 'Don\'t be looser, use GNU/Linux! ;P',
247 'Make love and not war!',
248 'Take your chance! Prove yourself!',
249 'This software is free of charge. If you wan\'t to donate, please send some money to children in Africa/etc...',
250 '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>'
253 echo('<span id="quote" style="float: left;"><i><small>'.$quotes[rand(0,sizeof($quotes)-1)]."</small></i></span>\n");
254 echo('<span id="exectime" style="float: right;"><small>Page was generated in '.(round(microtime(true), 3) - $GLOBALS['exec_time']).'
255 seconds</small></span>');
256 @readfile
($GLOBALS['footer_file']);
257 echo('</body></html>');
260 function unxss($string) {
261 return htmlspecialchars($string);
264 function explode_path($dir) {
265 $dir = substr($dir, strlen($GLOBALS['music_dir'])+
1);
266 $temp = split('/', ereg_replace('/+', '/', $dir));
268 for($j=sizeof($temp)-1;$j>0;$j--) {
270 for($i=0;$i<(sizeof($temp)-$j);$i++
) {
273 $out.='<a href="?dir='.rawurlencode($dir).'">'.unxss($temp[$i-1]).'</a>/';
275 return('<a href="?">.</a>/'.$out);
278 function flash_mp3_player() {
280 <html
><head
><title
><?
=$GLOBALS['title']?
>: Flash Music Player Plugin
</title
>
281 <style
> * { margin
: 0; padding
: 0; border
: 0; } </style
></head
><body
>
282 <object width
="100%" height
="344">
284 echo($GLOBALS['base_url'].$GLOBALS['flash_player_swf'].$GLOBALS['flash_player_options']);
285 if(isset($_GET['song'])) echo(rawurlencode($_GET['song']));
286 if(isset($_GET['playlist'])) generate_m3u($GLOBALS['dir'], dirname($GLOBALS['music_dir_url']), isset($_GET['recursive']), ',', true);
288 type
="application/x-shockwave-flash"
289 allowscriptaccess
="never"
290 allowfullscreen
="true"
291 transparentpagebg
="yes"
293 width
="100%" height
="24px"
294 >You need Adobe Flash enabled browser to play records directly in website
.</embed
>
295 </object></body
></html
>
300 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(); }
301 if(isset($_GET['download'])) serve_download($playlist_name);
302 if(isset($_GET['f'])) flash_mp3_player();
303 if(isset($_GET['song'])) {
304 die($_GET['song']."\r\n");
309 if($_POST['cache-refresh'] == $cache_passwd) {
310 generate_search_cache($music_dir, $search_cache);
314 if(isset($_GET['playlist'])) {
315 generate_m3u($dir, dirname($music_dir_url), isset($_GET['recursive']));
319 if(isset($_GET['random'])) {
321 if(!($searchfp = fopen($search_cache, 'r')))
322 die("Cannot read cache from $outfile<br />Refresh cache or set permissions properly!<br />\n");
323 while(!feof($searchfp)) { fgets($searchfp); $flen++
; }
324 for($i=0; $i<$_GET['random']; $i++
) {
326 for($j=0; $j<rand(0, $flen-1); $j++
) fgets($searchfp);
327 echo(dirname($music_dir_url).'/'.str_replace('%2F', '/', (rawurlencode(trim(fgets($searchfp)))))."\r\n");
332 if(isset($_GET['blank'])) {
334 <link rel
="stylesheet" type
="text/css" href
="<?=$css_file?>" />
335 <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
>
341 <meta http
-equiv
="Content-Type" content
="text/html; charset=<?=$charset?>" />
344 <meta charset
="<?=$charset?>" />
345 <link rel
="stylesheet" type
="text/css" href
="<?=$css_file?>" />
346 <link rel
="shortcut icon" href
="<?=$favicon_file?>" />
347 <link href
="<?=$favicon_file?>" rel
="icon" type
="image/gif" />
351 <div align
="right" style
="position: absolute; top: 5px; right: 5px;">
353 <iframe src
="about:blank" name
="playframe-hide" width
="0" height
="0" style
="border: none;" class="hide"></iframe
><!-- -----------???
--------------- -->
354 <span
class="icon"><
;</span
> <a href
="javascript: history.go(-1)" class="icon iback">BACK
</a
>
355 |
<a href
="?" target
="_parent" class="icon ihome">HOME
 
;(<?
=$music_dir?
>)</a
>
356 |
<a href
="?dj" class="icon idjmode">DJ
</a
>
357 |
<a href
="?help" class="icon ihelp">ABOUT
/HELP
</a
>
358 |
<a href
="?logout" class="icon ilogout">LOGOUT
</a
>
362 if(isset($_GET['help'])) {
363 ?
><h1
>About
/Help
</h1
><?php
364 readfile($bonus_dir.'/help.html');
369 if(!isset($_GET['search'])) {
370 echo('<title>'.$title.': '.unxss($dir).'</title>');
371 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>');
373 echo('<title>'.$title.': '.unxss($_GET['search']).'</title>');
374 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>');
382 <span style
="float: right;">
383 <form action
="?" method
="GET" align
="right" style
="display: inline;">
384 <input type
="hidden" name
="download" value
="" />
385 <input type
="number" min
="1" name
="random" value
="<?=$default_random_count?>" style
="width:4em;" title
="how many randomly selected tracks should be in
388 <input type
="submit" value
="random" title
="Generate random music playlist..." />
390 <form action
="?" method
="GET" align
="right" style
="display: inline;">
391 <span
class="icon isearch"></span
><input type
="search" name
="search" autofocus placeholder
="search regexp..."
392 title
="Search in music/google/lyrics/mp3/youtube; Hint: You can use regular expressions in search query..."
393 value
="<?=unxss($_GET['search'])?>"
395 <input type
="submit" value
="search" title
="Search in this JuKe!Box..." />
399 if(!isset($_GET['search'])) {
400 echo('<br style="clear: both;" />');
404 <span style
="float: right;">
405 <form action
="?" method
="POST" align
="right">
406 <input type
="password" name
="cache-refresh" value
="" style
="width:5em;" title
="Password for refreshing - good for avoiding DoS Attacks!!!" />
407 <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 !!!" />
411 <div align
="right" style
="clear: right;" title
="Aditional search engines...">
415 foreach($search_engines as $search_desc => $search_link) {
416 if(!$search_prefix) {
417 echo(unxss($_GET['search'])." @\n");
420 echo('<a href="'.$search_link.rawurlencode($_GET['search']).'">'.$search_desc."</a>;\n");
423 </div
><br style
="clear: both;" />
425 echo('<small>Search DB size: '.(filesize($search_cache)/1024)." kB<br /></small>\n");
427 if(!($searchfp = fopen($search_cache, 'r')))
428 die("Cannot read cache from $outfile<br />Refresh cache or set permissions properly!<br />\n");
431 echo('<table border="1" width="100%">');
432 render_tr_playframe_show();
433 echo('<tr class="directory"><td>S</td><td><a href="?download&playlist&search='.unxss($_GET['search']).'" class="icon iplay">P</a>');
434 if($GLOBALS['useflash']) echo('/<a href="?f&playlist&search='.unxss($_GET['search']).'" target="'.$GLOBALS['flash_player_frame'].'" class="icon ifplay">F</a>');
435 echo('</td><td colspan="100%">Search: '.unxss($_GET['search']).'</td></tr>');
437 while(!feof($searchfp)) {
438 $line = trim(fgets($searchfp));
439 $parclass=($i%2?
'even':'odd'); $parcolor=($i%2?
'lightblue':'white');
440 if(@eregi
(str_replace(' ', '(.*)', unational($_GET['search'])), unational($line))) {
442 $filesize = 0; if($i <= $access_limit) $filesize = filesize($line); else $filesize = 'n/a';
443 render_file_line('', $line, $music_dir_url, $i, $filesize, true);
446 echo('<tr><td colspan="100%">Total: '.$i.' results...</td></tr></table>');
447 render_footer(); die();
450 @readfile
($header_file);
451 foreach($indexlist as $index) @readfile
($dir.$index);
454 <table border
="1" width
="100%">
455 <?php
render_tr_playframe_show(); ?
>
457 <tr
class="directory"><td
>>
;</td
>
458 <td
><a href
="?download&playlist&dir=<?=str_replace('%2F', '/', rawurlencode($current_dir))?>" class="icon iplay">P
</a
>/<a
459 href
="?download&recursive&playlist&dir=<?=str_replace('%2F', '/', rawurlencode($current_dir))?>" class="icon irplay">R
</a
><?php
460 if($GLOBALS['useflash']) echo('/<a href="?f&playlist&dir='.str_replace('%2F', '/', rawurlencode($current_dir)).'" target="'.$GLOBALS['flash_player_frame'].'"
461 class="icon ifplay">F</a>'); ?
>
463 <td colspan
="100%"><?
=unxss($dir)?
></td
></tr
>
464 <tr
><td
>^
</td
><td
> 
;</td
><td colspan
="100%" class="directory"><span
class="icon ifolder">[DIR
] </span
><a href
="?dir=<?=rawurlencode($parent_dir)?>">..
465 (<?
=$parent_dir?
>)</a
></td
></tr
>
470 for($s=2;$s;$s--) { while(($item = readdir($dd)) != false) {
471 if($item == '.' ||
$item == '..') continue;
472 if(($s==2 && is_file($dir.$item)) ||
($s!=2 && is_dir($dir.$item))) continue;
474 //$parclass=($i%2?'even':'odd'); $parcolor=($i%2?'lightblue':'white');
476 if(is_file($dir.$item)) {
480 if(is_dir($dir.$item)) {
485 if(is_file($dir.$item)) {
486 render_file_line($dir, $item, $music_dir_url, $i, filesize($dir.$item));
488 if(is_dir($dir.$item)) {
489 render_dir_line($current_dir, $item, $i);
497 foreach($itemsd as $item) {
499 render_dir_line($current_dir, $item, $i);
501 foreach($itemsf as $item) {
503 render_file_line($dir, $item, $music_dir_url, $i, filesize($dir.$item));