# HG changeset patch # User Dan # Date 1220302273 14400 # Node ID 92dd253f501c2d45d69306f78f0705f819977446 # Parent 2634d550a97bdc99e2ca3200f05333bf7b62a8fe First shot at getting a session management system in place. Login and logout pages are there, and auth seems to be working and sufficiently secure for the moment. Sessions last indefinitely and are cookie-based. diff -r 2634d550a97b -r 92dd253f501c ajax.php --- a/ajax.php Mon Sep 01 16:50:03 2008 -0400 +++ b/ajax.php Mon Sep 01 16:51:13 2008 -0400 @@ -39,27 +39,8 @@ global $playlist, $mime_types, $json, $allowcontrol; global $use_auth, $auth_data; - if ( $use_auth ) - { - if ( !isset($_SERVER['PHP_AUTH_USER']) ) - { - $httpd->header('WWW-Authenticate: basic'); - $httpd->send_http_error($socket, 401, "A username and password are required to access this resource. Either you did not specify a username and password, or the supplied credentials were incorrect."); - return true; - } - if ( !isset($auth_data[$_SERVER['PHP_AUTH_USER']]) ) - { - $httpd->header('WWW-Authenticate: basic'); - $httpd->send_http_error($socket, 401, "A username and password are required to access this resource. Either you did not specify a username and password, or the supplied credentials were incorrect."); - return true; - } - else if ( $_SERVER['PHP_AUTH_PW'] !== $auth_data[$_SERVER['PHP_AUTH_USER']] ) - { - $httpd->header('WWW-Authenticate: basic'); - $httpd->send_http_error($socket, 401, "A username and password are required to access this resource. Either you did not specify a username and password, or the supplied credentials were incorrect."); - return true; - } - } + if ( !session_check() ) + return true; // Set content type $httpd->header("Content-type: {$mime_types['js']}"); diff -r 2634d550a97b -r 92dd253f501c greyhound.php --- a/greyhound.php Mon Sep 01 16:50:03 2008 -0400 +++ b/greyhound.php Mon Sep 01 16:51:13 2008 -0400 @@ -12,6 +12,8 @@ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. */ +define('GREY_VERSION', '0.1a4'); + // Try to trap termination signals to cleanly close the socket when needed // AmaroK sends a SIGTERM when it is shut down or the user requests to stop // the script @@ -37,15 +39,13 @@ // set this to false, it will only display the playlist. $allowcontrol = true; // The default theme. This should be a name of a directory in ./themes. -$theme = 'grey'; +$theme = 'funkymonkey'; // Allow forking when an HTTP request is received. This has advantages // and disadvantages. If this experimental option is enabled, it will // result in faster responses and load times but more memory usage. $allow_fork = true; // set to true to enable authentication -// WARNING: THIS HAS SOME SERIOUS SECURITY PROBLEMS RIGHT NOW. I don't -// know what's causing it to not prompt for authentication from any -// client after the first successful auth. +// this uses cookies, so make sure they're enabled in your browser $use_auth = false; // valid users and passwords $auth_data = array( @@ -69,7 +69,7 @@ // start up... -status('Starting Greyhound Web Control v0.1a3'); +status('Starting Greyhound Web Control v' . GREY_VERSION); status('loading files'); require('webserver.php'); @@ -79,6 +79,7 @@ require(GREY_ROOT . '/json.php'); require(GREY_ROOT . '/ajax.php'); require(GREY_ROOT . '/imagetools.php'); +require(GREY_ROOT . '/sessions.php'); // signal handler function sigterm($signal) @@ -102,6 +103,11 @@ burnout('SimpleXML required to continue. You may have an outdated version of PHP; most versions of PHP 5 have SimpleXML built-in. Check your distribution\'s documentation to find out how to enable PHP\'s SimpleXML support.'); } +if ( !function_exists('imagepng') || !function_exists('imagecopyresampled') || !function_exists('imagecreatefromjpeg') || !function_exists('imagecreatefromwbmp') ) +{ + warning('Can\'t find support for GD 2.0. Artwork will not be displayed. Look around in your distro\'s package manager for php-gd or php5-gd.'); +} + status('initializing playlist'); // init playlist object @@ -121,6 +127,8 @@ // setup handlers status('initializing handlers'); $httpd->add_handler('index', 'function', 'amarok_playlist'); + $httpd->add_handler('login', 'function', 'greyhound_login_page'); + $httpd->add_handler('logout', 'function', 'greyhound_logout'); $httpd->add_handler('action.json', 'function', 'ajax_request_handler'); $httpd->add_handler('artwork', 'function', 'artwork_request_handler'); $httpd->add_handler('scripts', 'dir', GREY_ROOT . '/scripts'); diff -r 2634d550a97b -r 92dd253f501c playlist.php --- a/playlist.php Mon Sep 01 16:50:03 2008 -0400 +++ b/playlist.php Mon Sep 01 16:51:13 2008 -0400 @@ -16,28 +16,14 @@ function amarok_playlist($httpd, $socket) { global $theme, $playlist, $allowcontrol; - global $use_auth, $auth_data; + global $use_auth; - if ( $use_auth ) + if ( !session_check() ) { - if ( !isset($_SERVER['PHP_AUTH_USER']) ) - { - $httpd->header('WWW-Authenticate: basic'); - $httpd->send_http_error($socket, 401, "A username and password are required to access this resource. Either you did not specify a username and password, or the supplied credentials were incorrect."); - return true; - } - if ( !isset($auth_data[$_SERVER['PHP_AUTH_USER']]) ) - { - $httpd->header('WWW-Authenticate: basic'); - $httpd->send_http_error($socket, 401, "A username and password are required to access this resource. Either you did not specify a username and password, or the supplied credentials were incorrect."); - return true; - } - else if ( $auth_data[$_SERVER['PHP_AUTH_USER']] !== $_SERVER['PHP_AUTH_PW'] ) - { - $httpd->header('WWW-Authenticate: basic'); - $httpd->send_http_error($socket, 401, "A username and password are required to access this resource. Either you did not specify a username and password, or the supplied credentials were incorrect."); - return true; - } + $httpd->header('HTTP/1.1 307 Temporary Redirect'); + $httpd->header('Location: /login'); + + return; } $iphone = ( ( strpos($_SERVER['HTTP_USER_AGENT'], 'iPhone') || @@ -61,6 +47,8 @@ 'position.js' )); $smarty->assign('allow_control', $allowcontrol); + $smarty->assign('use_auth', $use_auth); + $smarty->assign('greyhound_version', GREY_VERSION); $smarty->register_function('sprite', 'smarty_function_sprite'); $smarty->display('playlist.tpl'); } diff -r 2634d550a97b -r 92dd253f501c sessions.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sessions.php Mon Sep 01 16:51:13 2008 -0400 @@ -0,0 +1,177 @@ +header('HTTP/1.1 307 Temporary Redirect'); + $httpd->header('Location: /'); + + return; + } + $tried = false; + $success = false; + if ( isset($_POST['username']) && isset($_POST['password']) ) + { + $tried = true; + if ( $sessionid = login($_POST['username'], $_POST['password']) ) + { + $success = true; + $httpd->setcookie('grey_session', $sessionid, time() + ( 86400 * 3650 )); + } + } + + global $theme; + $iphone = ( ( strpos($_SERVER['HTTP_USER_AGENT'], 'iPhone') || + strpos($_SERVER['HTTP_USER_AGENT'], 'iPod') || + strpos($_SERVER['HTTP_USER_AGENT'], 'BlackBerry') || + isset($_GET['m']) ) + && !isset($_GET['f']) + ); + $theme_id = ( $iphone ) ? 'iphone' : $theme; + $smarty = load_theme($theme_id); + + $smarty->assign('theme', $theme_id); + $smarty->assign('greyhound_version', GREY_VERSION); + $smarty->assign('tried', $tried); + $smarty->assign('success', $success); + $smarty->display('login.tpl'); +} + +function greyhound_logout($httpd, $socket) +{ + // destroy the session + if ( isset($_COOKIE['grey_session']) ) + { + load_session_data(); + global $session_data; + unset($session_data[$_COOKIE['grey_session']]); + session_commit_db(); + } + + $httpd->setcookie('grey_session', '', time() - 864000); + $httpd->header('HTTP/1.1 307 Temporary Redirect'); + $httpd->header('Location: /'); +} + +/** + * Check to see if we're logged in + */ + +function session_check() +{ + global $use_auth, $auth_data; + if ( isset($_COOKIE['grey_session']) ) + { + load_session_data(); + global $session_data; + if ( isset($session_data[$_COOKIE['grey_session']]) ) + { + // has a cookie with a valid session ID, check credentials + $session =& $session_data[$_COOKIE['grey_session']]; + if ( isset($auth_data[$session['user']]) ) + { + if ( $session['hash'] === md5($auth_data[$session['user']] . $session['salt']) ) + { + // session is valid, logged in + return true; + } + } + } + } + return ( $use_auth ) ? false : true; +} + +function login($username, $password) +{ + global $use_auth, $auth_data; + if ( !$use_auth ) + return false; + + if ( isset($auth_data[$username]) ) + { + if ( $auth_data[$username] === $password ) + { + return create_session($username, $password); + } + } + return false; +} + +function create_session($username, $password) +{ + load_session_data(); + global $session_data; + + $sessid = md5(sha1(microtime() . mt_rand())); + $salt = md5(sha1(md5(mt_rand() . microtime() . microtime() . mt_rand()))); + + $session_data[$sessid] = array( + 'user' => $username, + 'hash' => md5($password . $salt), + 'salt' => $salt + ); + session_commit_db(); + + return $sessid; +} + +function var_export_string($arr) +{ + ob_start(); + var_export($arr); + $r = ob_get_contents(); + ob_end_clean(); + return $r; +} + +function session_commit_db() +{ + global $session_data; + $d = var_export_string($session_data); + $fp = @fopen('./session_db.php', 'w'); + if ( !$fp ) + { + warning('Could not open the session database for writing. Logins may not work.'); + return false; + } + $d = << diff -r 2634d550a97b -r 92dd253f501c themes/funkymonkey/images/greylogo.png Binary file themes/funkymonkey/images/greylogo.png has changed diff -r 2634d550a97b -r 92dd253f501c themes/funkymonkey/images/login.png Binary file themes/funkymonkey/images/login.png has changed diff -r 2634d550a97b -r 92dd253f501c themes/funkymonkey/images/src/login.xcf Binary file themes/funkymonkey/images/src/login.xcf has changed diff -r 2634d550a97b -r 92dd253f501c themes/funkymonkey/login.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/themes/funkymonkey/login.css Mon Sep 01 16:51:13 2008 -0400 @@ -0,0 +1,85 @@ +/** + * Based upon the AmaroK WebControl interface by: + * Jonas Christian Drewsen ( kde at xspect dot dk ) + * André Kelpe ( fs111 at web dot de ) + * Peter C. Ndikuwera ( pndiku at gmail dot com ) + */ + +html, body { + margin: 0; + padding: 0; + height: 100%; +} + +body { + font-family: sans-serif; + background-color: #212251; + color: #ffffff; + padding: 0; +} + +body > table { + width: 100%; + height: 100%; +} + +div.login-main { + background-image: url(images/login.png); + width: 340px; + height: 220px; + margin: 0 auto; + padding: 40px; + background-position: center center; + background-repeat: no-repeat; +} + +table.loginform { + margin: 0 auto; +} + +table.loginform td { + padding-top: 20px; +} + +table.loginform td.left { + width: 33%; + text-align: left; +} + +table.loginform td.right { + width: 66%; + text-align: left; +} + +table.loginform td.error, table.loginform td.success { + text-align: center; + color: #ff5321; + padding-top: 2px; +} + +table.loginform td.success { + color: #53ff21; +} + +table.loginform td.submit { + font-size: larger; + padding-top: 12px; +} + +input { + border-width: 0px; + background-color: #b1b5cd; + padding: 2px; + color: #383f61; +} + +input.submit { + font-size: larger; + padding: 2px 5px; +} + +input.submit:hover, input.submit:focus { + background-color: #b1b5cd; + cursor: pointer; +} + diff -r 2634d550a97b -r 92dd253f501c themes/funkymonkey/login.tpl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/themes/funkymonkey/login.tpl Mon Sep 01 16:51:13 2008 -0400 @@ -0,0 +1,65 @@ +{** + * Template file for default Grey theme + * Greyhound: Web control interface script for Amarok + * Written by Dan Fuhry - (C) 2008 + *} + + + + + Greyhound: Login + + + + {if $success} + + {/if} + + + + + + +
+ + +
+ + + diff -r 2634d550a97b -r 92dd253f501c themes/funkymonkey/playlist.tpl --- a/themes/funkymonkey/playlist.tpl Mon Sep 01 16:50:03 2008 -0400 +++ b/themes/funkymonkey/playlist.tpl Mon Sep 01 16:51:13 2008 -0400 @@ -85,7 +85,11 @@
- Powered by Greyhound + Powered by Greyhound v{$greyhound_version} + {if $use_auth} + – + log out + {/if}
diff -r 2634d550a97b -r 92dd253f501c themes/grey/images/ajax.gif Binary file themes/grey/images/ajax.gif has changed diff -r 2634d550a97b -r 92dd253f501c themes/grey/images/greylogo.png Binary file themes/grey/images/greylogo.png has changed diff -r 2634d550a97b -r 92dd253f501c themes/grey/images/login.png Binary file themes/grey/images/login.png has changed diff -r 2634d550a97b -r 92dd253f501c themes/grey/images/src/login.xcf Binary file themes/grey/images/src/login.xcf has changed diff -r 2634d550a97b -r 92dd253f501c themes/grey/login.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/themes/grey/login.css Mon Sep 01 16:51:13 2008 -0400 @@ -0,0 +1,85 @@ +/** + * Based upon the AmaroK WebControl interface by: + * Jonas Christian Drewsen ( kde at xspect dot dk ) + * André Kelpe ( fs111 at web dot de ) + * Peter C. Ndikuwera ( pndiku at gmail dot com ) + */ + +html, body { + margin: 0; + padding: 0; + height: 100%; +} + +body { + font-family: sans-serif; + background-color: #262626; + color: #ffffff; + padding: 0; +} + +body > table { + width: 100%; + height: 100%; +} + +div.login-main { + background-image: url(images/login.png); + width: 340px; + height: 220px; + margin: 0 auto; + padding: 40px; + background-position: center center; + background-repeat: no-repeat; +} + +table.loginform { + margin: 0 auto; +} + +table.loginform td { + padding-top: 20px; +} + +table.loginform td.left { + width: 33%; + text-align: left; +} + +table.loginform td.right { + width: 66%; + text-align: left; +} + +table.loginform td.error, table.loginform td.success { + text-align: center; + color: #ff5321; + padding-top: 2px; +} + +table.loginform td.success { + color: #53ff21; +} + +table.loginform td.submit { + font-size: larger; + padding-top: 12px; +} + +input { + border-width: 0px; + background-color: #272727; + padding: 2px; + color: #a8a8a8; +} + +input.submit { + font-size: larger; + padding: 2px 5px; +} + +input.submit:hover, input.submit:focus { + background-color: #323232; + cursor: pointer; +} + diff -r 2634d550a97b -r 92dd253f501c themes/grey/login.tpl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/themes/grey/login.tpl Mon Sep 01 16:51:13 2008 -0400 @@ -0,0 +1,65 @@ +{** + * Template file for default Grey theme + * Greyhound: Web control interface script for Amarok + * Written by Dan Fuhry - (C) 2008 + *} + + + + + Greyhound: Login + + + + {if $success} + + {/if} + + + + + + +
+ + +
+ + + diff -r 2634d550a97b -r 92dd253f501c themes/grey/playlist.tpl --- a/themes/grey/playlist.tpl Mon Sep 01 16:50:03 2008 -0400 +++ b/themes/grey/playlist.tpl Mon Sep 01 16:51:13 2008 -0400 @@ -85,7 +85,11 @@
- Powered by Greyhound + Powered by Greyhound v{$greyhound_version} + {if $use_auth} + – + log out + {/if}
diff -r 2634d550a97b -r 92dd253f501c themes/iphone/images/greylogo.png Binary file themes/iphone/images/greylogo.png has changed diff -r 2634d550a97b -r 92dd253f501c themes/iphone/images/login.png Binary file themes/iphone/images/login.png has changed diff -r 2634d550a97b -r 92dd253f501c themes/iphone/images/src/login.xcf Binary file themes/iphone/images/src/login.xcf has changed diff -r 2634d550a97b -r 92dd253f501c themes/iphone/login.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/themes/iphone/login.css Mon Sep 01 16:51:13 2008 -0400 @@ -0,0 +1,91 @@ +/** + * Based upon the AmaroK WebControl interface by: + * Jonas Christian Drewsen ( kde at xspect dot dk ) + * André Kelpe ( fs111 at web dot de ) + * Peter C. Ndikuwera ( pndiku at gmail dot com ) + */ + +html, body { + margin: 0; + padding: 0; + height: 100%; + font-size: 120%; +} + +body { + font-family: sans-serif; + background-color: #212251; + color: #ffffff; + padding: 0; +} + +body > table { + width: 100%; + height: 100%; +} + +div.login-main { + background-image: url(images/login.png); + width: 240px; + height: 276px; + margin: 0 auto; + padding: 40px; + background-position: center center; + background-repeat: no-repeat; +} + +table.loginform { + margin: 0 auto; +} + +table.loginform td { + padding-top: 20px; +} + +table.loginform td.left { + width: 33%; + text-align: left; +} + +table.loginform td.right { + width: 66%; + text-align: left; +} + +table.loginform td.error, table.loginform td.success { + text-align: center; + color: #ff5321; + padding-top: 2px; +} + +table.loginform td.success { + color: #53ff21; +} + +table.loginform td.submit { + font-size: larger; + padding-top: 12px; +} + +input { + border-width: 0px; + background-color: #b1b5cd; + padding: 2px; + color: #383f61; + width: 120px; + height: 28px; + font-size: 23px; +} + +input.submit { + font-size: larger; + padding: 2px 5px; + height: 36px; + font-size: 24px; +} + +input.submit:hover, input.submit:focus { + background-color: #b1b5cd; + cursor: pointer; +} + diff -r 2634d550a97b -r 92dd253f501c themes/iphone/login.tpl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/themes/iphone/login.tpl Mon Sep 01 16:51:13 2008 -0400 @@ -0,0 +1,69 @@ +{** + * Template file for default Funky Monkey theme + * Web control interface script for Amarok + * Written by Dan Fuhry - 2008 + * + * This script is in the public domain. Use it for good, not evil. + *} + + + + + AmaroK playlist + + + + + + {if $success} + + {/if} + + + + + + +
+ + +
+ + + diff -r 2634d550a97b -r 92dd253f501c themes/iphone/playlist.tpl --- a/themes/iphone/playlist.tpl Mon Sep 01 16:50:03 2008 -0400 +++ b/themes/iphone/playlist.tpl Mon Sep 01 16:51:13 2008 -0400 @@ -67,7 +67,7 @@ Track {foreach key=tid item=track from=$playlist} - {* strip *} + {strip} @@ -86,14 +86,18 @@ - {* /strip *} + {/strip} {/foreach}