= 1024 && $i < $l; $bytes /= 1024, $i++ );
// Return a rounded figure with unit
return ( round($bytes, 2) . ' ' . $types[$i] );
}
// Convert path to URL
function pathToURL($filePath) {
// Run through realpath to normalise path
$realPath = realpath($filePath);
// Verify that the path passed is real and find the directory
if ( is_file($realPath)) {
$dir = dirname($realPath);
} elseif ( is_dir($realPath) ) {
$dir = $realPath;
} else {
// Path does not exist, fails
return false;
}
// Expand the document root path
$_SERVER['DOCUMENT_ROOT'] = realpath($_SERVER['DOCUMENT_ROOT']);
// Make sure the path is not lower than the server root
if ( strlen($dir) < strlen($_SERVER['DOCUMENT_ROOT']) ) {
return false;
}
// Determine path from web root
$rootPos = strlen($_SERVER['DOCUMENT_ROOT']);
// Make sure $rootPos includes the first slash
if ( ( $tmp = substr($_SERVER['DOCUMENT_ROOT'], -1) ) && ( $tmp == '/' || $tmp == '\\' ) ) {
--$rootPos;
}
// Extract path below webroot and discard path above webroot
$pathFromRoot = substr($realPath, $rootPos);
// Build URL from parts
$path = 'http' . ( isset($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) != 'off' ? 's' : '' ) . '://' . $_SERVER['HTTP_HOST'] . $pathFromRoot;
// Convert to forward slash if on Windows
if ( DIRECTORY_SEPARATOR == '\\' ) {
$path = str_replace('\\', '/', $path);
}
return $path;
}
// Hide from non-js browsers by using document.write() to output
function jsWrite($str) {
return '';
}
// Convert a string of bool value to bool
function bool($str) {
if ( $str == 'false' ) {
return false;
}
if ( $str == 'true' ) {
return true;
}
return NULL;
}
/*****************************************************************
* CLASSES
******************************************************************/
/*****************************************************************
* Location wrapper - allows us to have observers on the location
******************************************************************/
class Location {
// Observers
private $observers;
// Redirect elsewhere
public function redirect($to = '') {
// Notify observers
$this->notifyObservers('redirect');
// Redirect and quit
header('Location: ' . ADMIN_URI . '?' . $to);
exit;
}
// Redirect elsewhere but without observer
public function cleanRedirect($to = '') {
// Redirect and quit
header('Location: ' . ADMIN_URI . '?' . $to);
exit;
}
// Register observers
public function addObserver(&$obj) {
$this->observers[] = $obj;
}
// Notify observers
public function notifyObservers($action) {
// Determine method to call
$method = 'on' . ucfirst($action);
// Prepare parameters
$params = func_get_args();
array_shift($params);
// Loop through all observers
foreach ( $this->observers as $obj ) {
// If an observing method exists, call it
if ( method_exists($obj, $method) ) {
call_user_func_array(array(&$obj, $method), $params);
}
}
}
}
/*****************************************************************
* Input wrapper for incoming data
******************************************************************/
class Input {
// Set up inputs
public function __construct() {
$this->GET = $this->prepare($_GET);
$this->POST = $this->prepare($_POST);
$this->COOKIE = $this->prepare($_COOKIE);
}
// Return array with keys converted to lowercase and values cleaned
private function prepare($array) {
$return = array();
foreach ( $array as $key => $value ) {
$return[strtolower($key)] = self::clean($value);
}
return $return;
}
// Get an input - inputs can be requested in the form pVarName
// where VarName is (case insensitive) name of variable (duh!)
// and p denotes from _POST. G and C are also available.
public function __get($name) {
// Do we have a varname?
if ( ! isset($name[1]) ) {
return NULL;
}
// Split into GPC and VarName (case insensitive)
$from = strtolower($name[0]);
$var = strtolower(substr($name, 1));
// Define $from to target relationships
$targets = array('g' => $this->GET,
'p' => $this->POST,
'c' => $this->COOKIE);
// Look for the value and return it
if ( isset($targets[$from][$var]) ) {
return $targets[$from][$var];
}
// Not found, return false
return NULL;
}
// Clean a value
static public function clean($val) {
static $magicQuotes;
// What is our magic quotes setting?
if ( ! isset($magicQuotes) ) {
$magicQuotes = get_magic_quotes_gpc();
}
// What type is this?
switch ( true ) {
case is_string($val):
// Strip slashes and trim
if ( $magicQuotes ) {
$val = stripslashes($val);
}
$val = trim($val);
break;
case is_array($val):
$val = array_map(array('Input', 'clean'), $val);
break;
default:
return $val;
}
return $val;
}
}
/*****************************************************************
* Output wrappers
******************************************************************/
// A simple overloading object
class Overloader {
// Store variables in this array
protected $data;
// Set value (case insensitive)
public function __set($name, $value) {
$this->data[strtolower($name)] = $value;
}
// Get value (case insensitive)
public function __get($name) {
$name = strtolower($name);
return isset($this->data[$name]) ? $this->data[$name] : '';
}
}
// Base wrapper object
abstract class Output extends Overloader {
// Full page to output
protected $output;
// Content only
protected $content;
// Array of observers
protected $observers = array();
// Output the page
final public function out() {
// Notify our observers we're about to print
$this->notifyObservers('print', $this);
// Wrap content in our wrapper
$this->wrap();
// Send headers
$this->sendHeaders();
// Send body
print $this->output;
// Page completed, finish
exit;
}
// Override this to send custom headers instead of default (html)
protected function sendHeaders() {}
// Wrapper for body content
protected function wrap() {
$this->output = $this->content;
}
// Add content
public function addContent($content) {
$this->content .= $content;
}
// Register observers
public function addObserver(&$obj) {
$this->observers[] = $obj;
}
// Notify observers
public function notifyObservers($action) {
// Determine method to call
$method = 'on' . ucfirst($action);
// Prepare parameters
$params = func_get_args();
array_shift($params);
// Loop through all observers
foreach ( $this->observers as $obj ) {
// If an observing method exists, call it
if ( method_exists($obj, $method) ) {
call_user_func_array(array(&$obj, $method), $params);
}
}
}
// Send status code
public function sendStatus($code) {
header(' ', true, $code);
}
// More overloading. Set value with key.
public function __call($func, $args) {
if ( substr($func, 0, 3) == 'add' && strlen($func) > 3 && ! isset($args[2]) ) {
// Saving with key or not?
if ( isset($args[1]) ) {
$this->data[strtolower(substr($func, 3))][$args[0]] = $args[1];
} else {
$this->data[strtolower(substr($func, 3))][] = $args[0];
}
}
}
}
// Output with our HTML skin
class SkinOutput extends Output {
// Print all
private function printAll($name) {
$name = strtolower($name);
if ( isset($this->data[$name]) && is_array($this->data[$name]) ) {
foreach ( $this->data[$name] as $item ) {
echo $item;
}
}
}
// Wrap content in HTML skin
protected function wrap() {
// Prepare the "get image" path
$imgs = ADMIN_URI . '?image=';
// Self
$self = ADMIN_URI;
// Prepare date
$date = date('H:i, d F Y');
// Append "glype control panel" to title
$title = $this->title . ( $this->title ? ' : ' : '' ) . 'glype control panel';
// Buffer so we can get this into a variable
ob_start();
// Print output
echo <<
{$date}
OUT;
// Add the "welcome" and log out link
if ( $this->admin ) {
echo "welcome, {$this->admin} : log out\n";
}
echo <<
admin control panel
for glype proxy
{$this->bodyTitle}
OUT;
// Do we have any error messages?
if ( $this->error ) {
// Print all
foreach ( $this->error as $id => $message ) {
echo <<
See also
';
foreach ( $this->footerLinks as $text => $href ) {
echo "
Attempted to load: ' . ADMIN_GLYPE_SETTINGS . '');
$output->out();
}
/*****************************************************************
* Verify a valid action and force to something else if not.
******************************************************************/
// Are we an admin? If not, force login page.
if ( ! $user->isAdmin() ) {
$action = 'login';
}
// Do we even have any user details? If not, force installer.
if ( ! isset($adminDetails) ) {
$action = 'install';
}
/*****************************************************************
* Prepare template variables
******************************************************************/
// URI to self
$self = ADMIN_URI;
// Links to other sections of the control panel
if ( $user->isAdmin() ) {
$output->addNavigation('Home', $self);
$output->addNavigation('Edit Settings', $self . '?settings');
$output->addNavigation('Cache Status', $self . '?cache');
$output->addNavigation('View Logs', $self . '?logs');
}
/*****************************************************************
* Process current request.
******************************************************************/
switch ( $action ) {
/*****************************************************************
* INSTALL - save an admin username/password in our settings file
******************************************************************/
case 'install':
// Do we have any admin details already?
if ( isset($adminDetails) ) {
// Add error
$error->add('An administrator account already exists. For security reasons, you must manually create additional administrator accounts.');
// And redirect to index
$location->redirect();
}
// Do we have any submitted details to process?
if ( $input->pSubmit ) {
// Verify inputs
if ( ! ( $username = $input->pAdminUsername ) ) {
$error->add('You must enter a username to protect access to your control panel!');
}
if ( ! ( $password = $input->pAdminPassword ) ) {
$error->add('You must enter a password to protect access to your control panel!');
}
// In case things go wrong, add this into the template
$tpl->username = $username;
// Process the installation if no errors
if ( ! $error->hasMsg() && is_writable(ADMIN_GLYPE_SETTINGS) ) {
// Load up the file
$file = file_get_contents(ADMIN_GLYPE_SETTINGS);
// Clear any closing php tag ? > (unnecessary and gets in the way)
if ( substr(trim($file), -2) == '?>' ) {
$file = substr(trim($file), 0, -2);
}
// Look for a "Preserve Me" section
if ( strpos($file, '//---PRESERVE ME---') === false ) {
// If it doesn't exist, add it
$file .= "\n//---PRESERVE ME---
// Anything below this line will be preserved when the admin control panel rewrites
// the settings. Useful for storing settings that don't/can't be changed from the control panel\n";
}
// Prepare the inputs
$password = md5($password);
// Add to file
$file .= "\n\$adminDetails[" . quote($username) . "] = " . quote($password) . ";\n";
// Save updated file
if ( file_put_contents(ADMIN_GLYPE_SETTINGS, $file) ) {
// Add confirmation
$confirm->add('Installation successful. You have added ' . $username . ' as an administrator and are now logged in.');
// Log in the installer
$user->login($username);
} else {
// Add error message
$error->add('Installation failed. The settings file appears writable but file_put_contents() failed.');
}
// Redirect
$location->redirect();
}
}
// Prepare skin variables
$output->title = 'install';
$output->bodyTitle = 'First time use installation';
// Add javascript
$output->addDomReady("document.getElementById('username').focus();");
// Is the settings file writable?
if ( ! ( $writable = is_writable(ADMIN_GLYPE_SETTINGS) ) ) {
$error->add('The settings file was found at ' . ADMIN_GLYPE_SETTINGS . ' but is not writable. Please set the appropriate permissions to make the settings file writable.');
// And disable the submit button
$tpl->disabled = ' disabled="disabled"';
} else {
$confirm->add('Settings file was found and is writable. Installation can proceed. Do not leave the script at this stage!');
}
// Print form
echo <<
Environment check failed. You will not be able to run glype proxy until you fix the above issue(s).
'; } else { echo 'Environment okay. You can run glype proxy on this server.
'; } // // Script versions // $acpVersion = ADMIN_VERSION; $proxyVersion = isset($CONFIG['version']) ? $CONFIG['version'] : 'unknown - pre 1.0'; // Create javascript to update the latest stable version $javascript = <<Note: Your settings file needs updating. Use the Edit Settings page and click Update.
"; } // // Glype news // echo <<This has obvious privacy issues - if using this option, ensure your site clearlystates how it handles cookies and protect the cookie data from unauthorised access.
]]>Note: You can also set up your proxy to automatically empty the cache periodically with the maintenance feature.
OUT; $output->addDomReady("document.getElementById('trim').focus();"); break; /***************************************************************** * LOG INDEX ******************************************************************/ case 'logs': // Are we updating the log destination? if ( $input->pDestination !== NULL ) { // Attempt to validate path $path = realpath($input->pDestination); // Is the path OK? if ( $path ) { $confirm->add('Log folder updated.'); } else { $error->add('Log folder not updated. ' . $input->pDestination . ' does not exist.'); } // Normalize $path = str_replace('\\', '/', $path); // Add trailing slash if ( isset($path[strlen($path)-1]) && $path[strlen($path)-1] != '/' ) { $path .= '/'; } // Save in session $_SESSION['logging_destination'] = $path; // Redirect to avoid "Resend Post?" on refresh $location->redirect('logs'); } // Find status $enabled = empty($CONFIG['enable_logging']) == false; $status = $enabled ? 'enabled' : 'disabled'; $destination = isset($CONFIG['logging_destination']) ? $CONFIG['logging_destination'] : ''; // Are we overriding the real destination with some other value? if ( ! empty($_SESSION['logging_destination']) ) { $destination = $_SESSION['logging_destination']; } // Print header $output->title = 'log viewer'; $output->bodyTitle = 'Logging'; echo <<Logging feature: | {$status} |
Log folder: |
No log files to analyse.
'; break; } // Print starting table echo <<{$month} {$yearNumeric} | [popular sites] | OUT; // Update vars so we don't do this again until we want to $currentYearMonth = $yearMonth; $first = false; } // Format size $filesize = filesize($destination . $file); $totalSize += $filesize; $size = formatSize($filesize); // Row colour is grey if weekend $row = ( $day == 'Saturday' || $day == 'Sunday' ) ? '3' : '1'; // Print log file row echo <<{$display} | {$size} | [raw log] [popular sites] | OUT; } // End table $total = formatSize($totalSize); echo <<
{$site} | OUT; } // Table footer echo << | Others | {$others} |
« Back
OUT; break; // Anything else - ignore default: $error->add('Missing input. No log view specified.'); } break; /***************************************************************** * Everything else - 404 ******************************************************************/ default: // Send 404 status $output->sendStatus(404); // And print the error page $output->title = 'page not found'; $output->bodyTitle = 'Page Not Found (404)'; echo <<