<?PHP
/**
* /logic/router/router.class.php
*
* Routes URL requests to the proper place
*
* @package AgaresCore4
* @author Agares Media <hide@address.com>
* @copyright Copyright (c) 2007, 2008 Agares Media. All rights reserved.
*/
/**
* router() Class
*
* Routes URL requests to the proper place
* @package AgaresCore4
*/
class router extends rootclass {
public function __construct() { // Constructor
//
}
// The destructor warns if headers have already been sent.
public function __destruct() { // Destructor
if(headers_sent($file, $line)){
$this->debug("Warning - Headers were already sent in $file on line $line...");
}
}
/**
* reroute() Method
*
* This method simply sends a 301 redirect, so headers cannot already have been sent or else the method will fail.
* The user will be redirected to the URL specified in $location
*
* @access public
* @param string $location The fully qualified URI to redirect to
* @return void
*/
public function reroute($location) {
try {
if(!headers_sent($file, $line)) {
header("HTTP/1.1 301 Moved Permanently");
header("Location: $location");
} else {
throw new Exception("Cannot redirect to $location - Headers were already sent in $file on line $line...");
}
} catch(Exception $e) {
$this->errorReport($e);
}
}
/**
* get() Method
*
* Get the command, santitized for SQL use if necessary. The .htaccess file forces all URI's to be parsed so that
* all requests above the root directory are contained in the GET variable "command". For example:
*
* This URI request: http://www.example.com/admin/
* Becomes this URI request after the .htaccess rules are applied: http://www.example.com/index.php?command=admin
*
* @access public
* @return string Returns the command, santitized for SQL use if necessary
*/
public function get() {
try {
if(isset($_GET['command'])) {
$command = $this->clean($_GET['command']);
return $command;
}
} catch(Exception $e) {
$this->errorReport($e);
}
}
/**
* process() Method
*
* Note: This method is called in /index.php and there is no real reason that anyone should directly invoke this
* method. If you're looking to route a window to a specific location, use the reroute() method instead.
*
* Takes the command and processes the result, loads the appropriate app or URL, depending on the case. When you
* access an Application from a URI such as http://www.example.com/admin/ you are calling the default logic
* and view files for that application. Specifically, the AC4 router will load /applications/admin/logic/index.php
* followed by /applications/admin/views/index.php
*
* Aside from the default logic and view files, there can be an infinite number of logic/view combinations for each
* application. For example, the admin application has a logic/view pair to display the Applications Menu. To access
* the App Menu directly, you would visit this URL: http://www.example.com/admin/appmenu/ which in turn loads this
* logic file: /applications/admin/logic/appmenu.php and this view file: /applications/admin/views/appmenu.php
*
* When a page cannot be found, it will always generate a 404 error. If the global $debug variable is set to true,
* it will also give a full detailed error report. When $debug is set to false, it will still trigger a 404 HTTP
* error, and in addition it will load the 404 error page that is specified in /data/html/404.html If you want a
* custom error page, simply edit that file.
*
* @access public
* @return void
* @see reroute()
*/
public function process() {
try {
global $defaultapp, $defaultloc, $debug;
$command = $this->get();
$history = NULL;
$count = 0;
// This if block simply checks to see if the URL ends with a forward slash, if so, it removes it and reloads the page.
if(substr($command, -1)== "/") {
if (isset($_SERVER['HTTPS'])) { // Used so that we automatically support SSL secured URLs
$httpProtocal = 'https';
} else {
$httpProtocal = 'http';
}
$newUrl= substr("$httpProtocal://" . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'], 0, -1);
if(!headers_sent($file, $line)) {
header("HTTP/1.0 307 Temporary redirect"); // 307 keeps the post data if any, but requires user confirmation to resubmit post data
header("Location: $newUrl");
} else {
throw new Exception("Cannot redirect to $location - Headers were already sent in $file on line $line...");
}
exit();
}
$commandArray = explode("/", $command, 25); // Max 25 arguments to help mitigate DOS attacks and memory issues
// This loop determines if we're dealing with an app or not.
$possibleApp = true; // By default, we'll assume the request is for an app. In the foreach loop below, we'll determine the truth
foreach($commandArray as $checkIfRealFile) { // In this loop, we'll determine if we're dealing with an app,
$history.= $checkIfRealFile . '/';
$count++;
if (file_exists('./applications/'.$history) && $count >= 2) {
$possibleApp = false; // This means the URL is a true URL, and not a command to be processed, so lets give the user the actual URL they requested.
}
}
// Kind of a backwards way to find out whether or not we're on the homepage, however using NULL, "", '', or even ' ' didn't work when trying to determine if $commandArray[0] was blank
if ('./applications/'.$commandArray[0].'/logic/index.php' == './applications//logic/index.php' || './applications/'.$commandArray[0].'/logic/index.php' == './applications/index.php/logic/index.php') {
$possibleApp = false; //
global $localpath, $homedir, $body_output, $bodymarkup, $headtop_output, $headbottom_output, $router, $database;
require('./applications/'.$defaultapp.'/config.php'); // This loads the application's settings
require('./applications/'.$defaultapp.'/logic/'.$defaultloc.'.php'); // This executes the app's logic
require('./applications/'.$defaultapp.'/views/'.$defaultloc.'.php'); // This opens the view associated with the logic.
}
if ($possibleApp == true && !file_exists('./applications/'.$commandArray[0].'/logic/')) { // Throws a fatal error if there is no application installed that matches the argument 0
throw new Exception('The Application: '. $commandArray[0] . ' could not be found. Try reupload the application to the /applications/ folder and try again.');
}
if ($possibleApp == true && !file_exists('./applications/'.$commandArray[0].'/logic/index.php')) { // All apps must have a index.php, if not, then its a fatal error. This file implements the logic in /applications/yourapp/classes.php
throw new Exception('The Application: '. $commandArray[0] . ' does not have an executable file located in its directory. Try reupload the application to the /applications/ folder and try again.');
}
if ($possibleApp == true) {
if(!isset($commandArray[1]) || !file_exists('./applications/'.$commandArray[0].'/logic/'.$commandArray[1].'.php')) {$filename = 'index';} else {$filename = $commandArray[1];} // This logic code will treat $commandArray[1] to point to specific logic/view partners within the app. If no suitable logic file is found, then the default logic file for the application will handle the request.
// First lets load/declare all of our global variables.
global $localpath, $homedir, $body_output, $bodymarkup, $headtop_output, $headbottom_output, $router, $database;
$this->debug('Router enacted. Routing to '.$commandArray[0]);
require('./applications/'.$commandArray[0].'/config.php'); // This loads the application's settings
require('./applications/'.$commandArray[0].'/logic/'.$filename.'.php'); // This executes the app's logic
require('./applications/'.$commandArray[0].'/views/'.$filename.'.php'); // This opens the view associated with the logic.
} else {
//
}
return $commandArray;
} catch(Exception $e) {
if($debug==true) {
// For debugging purposes, its useful if we spit out the variable $commandArray
echo '<h1>404 Page not found.</h1><br /><br />';
echo 'Turn off debugging to disable the following error report:<br /><br />';
echo 'process() METHOD DETAILED ERROR REPORT:<br /><br />Router Array:<br /><pre>';
print_r($commandArray);
echo '</pre><br /><br />';
$this->errorReport($e);
} else {
global $homedir;
header("HTTP/1.0 404 Not Found");
include('./data/html/404.html');
}
}
}
}
?>