commit cf52a6d61679b6abf4ce11f8903031980e2cfe66 Author: kts Date: Sat May 17 16:52:48 2014 -0700 Initial commit of kettek MediaServe. Contains basic framework and implementation. FileBrowser module fairly complete, much more to be added, including Playlist module and Player module. diff --git a/MusicServe.php b/MusicServe.php new file mode 100644 index 0000000..8bb9d88 --- /dev/null +++ b/MusicServe.php @@ -0,0 +1,132 @@ +'.PHP_EOL; + foreach(self::$modules as $module) { + if (file_exists('modules/'.$module.'.css')) { + echo ' '.PHP_EOL; + } + } + } + + static function renderProgram() { + foreach(self::$modules as $module) { + if (method_exists('ktk\\MusicServe\\'.$module, 'onRender')) { + call_user_func('ktk\\MusicServe\\'.$module.'::onRender'); + } + } + } + + static function closeProgram() { + foreach(self::$modules as $module) { + if (method_exists('ktk\\MusicServe\\'.$module, 'onClose')) { + call_user_func('ktk\\MusicServe\\'.$module.'::onClose'); + } + } + } + + static function reportError($context, $subcontext, $error) { + if(!self::$errors[$context."::".$subcontext]) + self::$errors[$context."::".$subcontext] = array(); + array_push(self::$errors[$context."::".$subcontext], $error); + } + + static function reportWarning($context, $subcontext, $warning) { + if(!self::$warnings[$context."::".$subcontext]) + self::$warnings[$context."::".$subcontext] = array(); + array_push(self::$warnings[$context."::".$subcontext], $warning); + } + + static function loadConf($file) { + if (file_exists('conf/'.$file.'.ini')) { + return parse_ini_file('conf/'.$file.'.ini'); + } else { + self::reportWarning(__CLASS__, __FUNCTION__, "Could not load ".'conf/'.$file.'.ini'); + } + return array(); + } + + static function saveConf($data) { + if ($fp = fopen($data, 'w')) { + self::writeData_r($fp, $data); + fclose($fp); + } else { + MusicServe::reportError(__CLASS__, __FUNCTION__, "Could not write to \"".$data."\", please check your permissions!"); + return NULL; + } + } + static function writeData_r($handle, $value) { + foreach ($data as $key=>$value) { + if (is_array($value)) { + fwrite($handle, '['.$key.']'.PHP_EOL); + self::writeData_r($handle, $value); + } else { + fwrite($handle, $key.'='.$value.PHP_EOL); + } + } + + } + + static function storeData($var, $data) { + $_SESSION[$var] = $data; + } + + static function &getData($data) { + if (isset($_SESSION[$data])) { + return $_SESSION[$data]; + } else { + return NULL; + } + } +} +?> diff --git a/conf/BasicAuth.ini b/conf/BasicAuth.ini new file mode 100644 index 0000000..bcad640 --- /dev/null +++ b/conf/BasicAuth.ini @@ -0,0 +1 @@ +pub = pub diff --git a/index.php b/index.php new file mode 100644 index 0000000..eeba390 --- /dev/null +++ b/index.php @@ -0,0 +1,26 @@ + + + + + + + ktk MusicServe + + + + + + + diff --git a/main.css b/main.css new file mode 100644 index 0000000..4bbed01 --- /dev/null +++ b/main.css @@ -0,0 +1,6 @@ +html,body { + margin: 0; + padding: 0; + height: 100%; + width: 100%; +} diff --git a/media b/media new file mode 120000 index 0000000..98881fa --- /dev/null +++ b/media @@ -0,0 +1 @@ +/export/home/kts/Music \ No newline at end of file diff --git a/modules/BasicAuth.css b/modules/BasicAuth.css new file mode 100644 index 0000000..21bc2f0 --- /dev/null +++ b/modules/BasicAuth.css @@ -0,0 +1,11 @@ +#ktk_MusicServe_BasicAuth { + position: absolute; + bottom:0; + right:0; + float:right; + background-color: #222; +} + +#ktk_MusicServe_BasicAuth input { + border: 0; +} diff --git a/modules/BasicAuth.php b/modules/BasicAuth.php new file mode 100644 index 0000000..8199a07 --- /dev/null +++ b/modules/BasicAuth.php @@ -0,0 +1,68 @@ +'.PHP_EOL; + echo '
'; + echo ' '; + echo ' '; + echo ' '; + echo '
'; + echo ' '; + } + static public function doLogout() { + if (ini_get("session.use_cookies")) { + $params = session_get_cookie_params(); + setcookie(session_name(), '', time() - 42000, + $params["path"], $params["domain"], + $params["secure"], $params["httponly"] + ); + session_destroy(); + session_unset($_SESSION['logged']); + header('HTTP/1.1 401 Unauthorized'); + die("Logged out, please click here to login"); + } + } + static public function doAuth() { + if (empty($_SERVER['PHP_AUTH_DIGEST'])) { + header('HTTP/1.1 401 Unauthorized'); + header('WWW-Authenticate: Digest realm="'.self::$realm.'",qop="auth",nonce="'.uniqid().'",opaque="'.md5(self::$realm).'"'); + die("Canceled - refresh or click here to try again"); + } + if (!($data = self::parseHttpDigest($_SERVER['PHP_AUTH_DIGEST'])) || !isset(self::$creds[$data['username']])) { + header('HTTP/1.1 401 Unauthorized'); + die("Incorrect credentials, please click here to try again"); + } + $A1 = md5($data['username'] . ':' . self::$realm . ':' . self::$creds[$data['username']]); + $A2 = md5($_SERVER['REQUEST_METHOD'].':'.$data['uri']); + $valid_response = md5($A1.':'.$data['nonce'].':'.$data['nc'].':'.$data['cnonce'].':'.$data['qop'].':'.$A2); + if ($data['response'] != $valid_response) { + header('HTTP/1.1 401 Unauthorized'); + die("Incorrect credentials, please click here to try again"); + } + $_SESSION['logged'] = TRUE; + } + static public function parseHttpDigest($text) { + $needed_parts = array('nonce'=>1, 'nc'=>1, 'cnonce'=>1, 'qop'=>1, 'username'=>1, 'uri'=>1, 'response'=>1); + $data = array(); + $keys = implode('|', array_keys($needed_parts)); + preg_match_all('@(' . $keys . ')=(?:([\'"])([^\2]+?)\2|([^\s,]+))@', $text, $matches, PREG_SET_ORDER); + foreach ($matches as $m) { + $data[$m[1]] = $m[3] ? $m[3] : $m[4]; + unset($needed_parts[$m[1]]); + } + return $needed_parts ? false : $data; + } +} +?> diff --git a/modules/Clock.php b/modules/Clock.php new file mode 100644 index 0000000..eb44e98 --- /dev/null +++ b/modules/Clock.php @@ -0,0 +1,24 @@ +'.PHP_EOL; + echo self::$time.PHP_EOL; + echo '12-hour'.PHP_EOL; + echo ''.PHP_EOL; + } + static function changeTime($format) { + MusicServe::storeData('time_format', $format); + } +} +?> diff --git a/modules/ErrorReporter.css b/modules/ErrorReporter.css new file mode 100644 index 0000000..68fd9ed --- /dev/null +++ b/modules/ErrorReporter.css @@ -0,0 +1,21 @@ +#ktk_MusicServe_ErrorReporter { + background-color: #633; + color: #FCA; + font-family: console, consolas, terminal; + font-size: 8pt; +} + +#ktk_MusicServe_ErrorReporter * { + padding: 0; + margin: 0; +} + +#ktk_MusicServe_ErrorReporter h1 { + text-align: center; + color: #FAA; + font-size: 10pt; +} + +#ktk_MusicServe_ErrorReporter table { + width: 100%; +} diff --git a/modules/ErrorReporter.php b/modules/ErrorReporter.php new file mode 100644 index 0000000..205743a --- /dev/null +++ b/modules/ErrorReporter.php @@ -0,0 +1,24 @@ +'; + echo '

ERRORS

'; + echo ''; + echo ''; + foreach (MusicServe::$errors as $context=>$error_context) { + foreach($error_context as $error) { + echo ''; + } + } + echo '
contexterror
'.$context.''.$error.'
'; + echo ''; + } +} +?> diff --git a/modules/FileBrowser.css b/modules/FileBrowser.css new file mode 100644 index 0000000..679887b --- /dev/null +++ b/modules/FileBrowser.css @@ -0,0 +1,57 @@ +#ktk_MusicServe_FileBrowser { + float: left; + overflow: auto; + margin: auto; + width:200px; + display: block; + height:100%; + background-color: #444; + overflow-x: hidden; + overflow-y: scroll; +} + +#ktk_MusicServe_FileBrowser * { + margin: 0; + padding: 0; + border: 0; + font-family: console, consolas, terminal; + font-size: 10px; + text-align: left; +} + +#ktk_MusicServe_FileBrowser h1 { + display: block; + height: 24px; + overflow: hidden; + color: #CCC; +} + +#ktk_MusicServe_FileBrowser table { + width: 100%; +} + +#ktk_MusicServe_FileBrowser table, +#ktk_MusicServe_FileBrowser tr, +#ktk_MusicServe_FileBrowser td, +#ktk_MusicServe_FileBrowser input +{ + background-color: #444; + color: #CCC; +} + +#ktk_MusicServe_FileBrowser th, +#ktk_MusicServe_FileBrowser th input { + min-width: 32px; + background-color:#777; +} + +#ktk_MusicServe_FileBrowser td input { + width: 160px; + background-color: #111; + color: #CCC; +} + +#ktk_MusicServe_FileBrowser input:hover { + background-color: #777; + cursor: pointer; +} diff --git a/modules/FileBrowser.php b/modules/FileBrowser.php new file mode 100644 index 0000000..9af4266 --- /dev/null +++ b/modules/FileBrowser.php @@ -0,0 +1,168 @@ +'.PHP_EOL; + echo '

',$cwd,'

'.PHP_EOL; + if (MusicServe::checkModule("Playlist")) { + echo '
'; + echo ' '; + echo ' '; + echo ' '; + echo '
'; + } + echo ' '.PHP_EOL; + echo ' '; + echo ' '; + echo ' '; + echo ' '.PHP_EOL; + echo ' '.PHP_EOL; + echo ' '; + echo ' '; + echo ' '; + echo ' '.PHP_EOL; + foreach(MusicServe::getData('dirs') as $dir) { + echo ' '.PHP_EOL; + } + echo ' '.PHP_EOL; + + echo ' '; + echo ' '; + echo ' '; + foreach(MusicServe::getData('files') as $file) { + echo ' '.PHP_EOL; + } + echo ' '.PHP_EOL; + echo '
'.$file[FileBrowser::F_EXT].'
'.PHP_EOL; + echo ' '.PHP_EOL; + } + + /* COMMAND FUNCTIONS */ + static function changeCwd($directory) { + // NOTE: temporarily resolving any ".." to one dir up, rather than all + if (substr_count($directory, "..")) { + if (MusicServe::getData('cwd') == FileBrowser::ROOT) { + return NULL; + } + $directory = dirname(MusicServe::getData('cwd')).'/'; + } else { + $directory = MusicServe::getData('cwd').$directory; + } + if (!file_exists($directory)) { + MusicServe::reportError(__CLASS__, __FUNCTION__, + "Cannot change working directory to \"'.$directory.'\", as it does not exist!\n" + ); + return NULL; + } + MusicServe::storeData('cwd', $directory); + self::getFiles(); + self::sortFiles(); + } + + static function changeSort($type) { + MusicServe::storeData('sort_by', $type); + if (($sort_order = MusicServe::getData('sort_order')) != SORT_ASC) { + MusicServe::storeData('sort_order', SORT_ASC); + } else { + MusicServe::storeData('sort_order', SORT_DESC); + } + self::sortFiles(); + } + + static function openFile($file) { + if (MusicServe::checkModule("Playlist")) { + Playlist::addFile(MusicServe::getData('cwd').$file); + } + } + + static function openFiles() { + if (MusicServe::checkModule("Playlist")) { + foreach(MusicServe::getData('files') as $file) { + Playlist::addFile(MusicServe::getData('cwd').$file[FileBrowser::F_NAME]); + } + } + } + + /* GENERAL FUNCTIONS */ + static function getFiles() { + $directory = MusicServe::getData('cwd'); + if (!file_exists($directory)) { + MusicServe::reportError(__CLASS__, __FUNCTION__, + "Directory \"'.$directory.'\"does not exist!\n" + ); + return NULL; + } + + $directory_handle = opendir($directory); + $i = 0; + while (false !== ($filename = readdir($directory_handle))) { + if ($filename[0] != '.' && $filename != "..") { + $files[$i] = array(); + if (is_dir($directory.$filename)) { + $files[$i][FileBrowser::F_TYPE] = FileBrowser::T_DIR; + } else { + $files[$i][FileBrowser::F_TYPE] = FileBrowser::T_FILE; + } + $files[$i][FileBrowser::F_NAME] = $filename; + $files[$i][FileBrowser::F_EXT] = pathinfo($filename, PATHINFO_EXTENSION); + $i++; + } + } + MusicServe::storeData('dir_list', $files); + } + + /* INTERNAL FUNCTIONS */ + static function sortFiles() { + $sort = array(); + $sort_by = MusicServe::getData('sort_by'); + $sort_order = MusicServe::getData('sort_order'); + $i = 0; + if ($sort_by == "ext") { + foreach (MusicServe::getData('dir_list') as $file) { + $sort[$i++] = $file[FileBrowser::F_EXT]; + } + } else { + foreach (MusicServe::getData('dir_list') as $file) { + $sort[$i++] = $file[FileBrowser::F_NAME]; + } + } + array_multisort($sort, $sort_order, MusicServe::getData('dir_list')); + // Wasteful, but we want directories always on top + $dirs = array(); + $files = array(); + foreach (MusicServe::getData('dir_list') as $file) { + if ($file[FileBrowser::F_TYPE] == FileBrowser::T_DIR) { + $dirs[] = $file; + } else { + $files[] = $file; + } + } + MusicServe::storeData('files', $files); + MusicServe::storeData('dirs', $dirs); + } +} +?> diff --git a/modules/Player.css b/modules/Player.css new file mode 100644 index 0000000..6c5e582 --- /dev/null +++ b/modules/Player.css @@ -0,0 +1,4 @@ +#ktk_MusicServe_Player { + background-color: #111; + height: 65%; +} diff --git a/modules/Player.php b/modules/Player.php new file mode 100644 index 0000000..661fa9b --- /dev/null +++ b/modules/Player.php @@ -0,0 +1,17 @@ +',PHP_EOL; + echo "Player goes here"; + echo '',PHP_EOL; + } + static public function onClose() { + } +} +?> diff --git a/modules/Playlist.css b/modules/Playlist.css new file mode 100644 index 0000000..a64897d --- /dev/null +++ b/modules/Playlist.css @@ -0,0 +1,10 @@ +#ktk_MusicServe_Playlist * { + font-size: 10px; +} +#ktk_MusicServe_Playlist { + background-color: #444; + color: #BBA; + height: 35%; + overflow-y: auto; + font-size: 12px; +} diff --git a/modules/Playlist.php b/modules/Playlist.php new file mode 100644 index 0000000..39927c8 --- /dev/null +++ b/modules/Playlist.php @@ -0,0 +1,27 @@ +',PHP_EOL; + foreach (MusicServe::getData('playlist') as $file) { + echo $file.'
'; + } + echo ' ',PHP_EOL; + } + static public function onClose() { + } + + static public function addFile($file) { + MusicServe::getData('playlist')[] = $file; + } +} +?> diff --git a/modules/TemplateModule.php b/modules/TemplateModule.php new file mode 100644 index 0000000..f90ff78 --- /dev/null +++ b/modules/TemplateModule.php @@ -0,0 +1,14 @@ + diff --git a/modules/inactive/Devel.css b/modules/inactive/Devel.css new file mode 100644 index 0000000..b497b06 --- /dev/null +++ b/modules/inactive/Devel.css @@ -0,0 +1,5 @@ +#ktk_MusicServe_Devel { + position: absolute; + bottom: 0; + right: 0; +} diff --git a/modules/inactive/Devel.php b/modules/inactive/Devel.php new file mode 100644 index 0000000..38d3bd7 --- /dev/null +++ b/modules/inactive/Devel.php @@ -0,0 +1,26 @@ +',PHP_EOL; + echo '
',PHP_EOL; + echo '',PHP_EOL; + echo '',PHP_EOL; + echo '
',PHP_EOL; + echo '',PHP_EOL; + } + static public function endSession() { + if (ini_get("session.use_cookies")) { + $params = session_get_cookie_params(); + setcookie(session_name(), '', time() - 42000, + $params["path"], $params["domain"], + $params["secure"], $params["httponly"] + ); + session_destroy(); + header('Location: '.$_SERVER['PHP_SELF']); + die; + } + } +} +?> diff --git a/modules/inactive/SimpleClock.php b/modules/inactive/SimpleClock.php new file mode 100644 index 0000000..406fb06 --- /dev/null +++ b/modules/inactive/SimpleClock.php @@ -0,0 +1,24 @@ +'.PHP_EOL; + echo self::$time.PHP_EOL; + echo '12-hour'.PHP_EOL; + echo ''.PHP_EOL; + } + static function changeTime($format) { + SimpleDB::storeData('time_format', $format); + } +} +?> diff --git a/modules/inactive/SimpleDB.php b/modules/inactive/SimpleDB.php new file mode 100644 index 0000000..6454fd7 --- /dev/null +++ b/modules/inactive/SimpleDB.php @@ -0,0 +1,52 @@ +$value) { + if (is_array($value)) { + fwrite($handle, '['.$key.']'.PHP_EOL); + self::writeData_r($handle, $value); + } else { + fwrite($handle, $key.'='.$value.PHP_EOL); + } + } + } +} +?> diff --git a/modules/inactive/StyledClock.css b/modules/inactive/StyledClock.css new file mode 100644 index 0000000..90e2757 --- /dev/null +++ b/modules/inactive/StyledClock.css @@ -0,0 +1,7 @@ +#ktk_MusicServe_StyledClock { + background-color: #222; + color: #999; + position: fixed; + top:0; + right:0; +} diff --git a/modules/inactive/StyledClock.php b/modules/inactive/StyledClock.php new file mode 100644 index 0000000..de40f94 --- /dev/null +++ b/modules/inactive/StyledClock.php @@ -0,0 +1,24 @@ +'.PHP_EOL; + echo self::$time.PHP_EOL; + echo '12-hour'.PHP_EOL; + echo ''.PHP_EOL; + } + static function changeTime($format) { + MusicServe::storeData('time_format', $format); + } +} +?> diff --git a/sdb.ini b/sdb.ini new file mode 100644 index 0000000..1285eb5 --- /dev/null +++ b/sdb.ini @@ -0,0 +1 @@ +time_format=g:i:s a