Compare commits

..

No commits in common. 'feature/formhandler' and 'master' have entirely different histories.

2
.gitignore vendored

@ -1,2 +0,0 @@
config.php
config.mysql.php

@ -13,8 +13,7 @@
require("include.constants.php");
require("include.config.php");
require("include.debug.php");
require("cphp/config.php");
require("include.dependencies.php");
require("include.exceptions.php");
@ -24,271 +23,19 @@ require("include.misc.php");
require("include.memcache.php");
require("include.mysql.php");
require("include.session.php");
require("include.csrf.php");
require("include.forms.php");
require("include.lib.php");
require("class.templater.php");
require("class.localizer.php");
require("include.locale.php");
$locale = new Localizer();
$locale->Load($cphp_locale_name);
if(empty($not_html))
{
header("Content-Type:text/html; charset=UTF-8");
}
setlocale(LC_ALL, $locale->locale);
require("class.base.php");
require("class.databaserecord.php");
foreach($cphp_config->components as $component)
foreach($cphp_components as $component)
{
require("components/component.{$component}.php");
}
/* lighttpd (and perhaps some other HTTPds) won't pass on GET parameters
* when using the server.error-handler-404 directive that is required to
* use the CPHP router. This patch will try to detect such problems, and
* manually extract the GET data from the request URI. I admit, it's a
* bit of a hack, but there doesn't really seem to be a different way of
* solving this issue. */
/* Detect whether the request URI and the $_GET array disagree on the
* existence of GET parameters. */
if(strpos($_SERVER['REQUEST_URI'], "?") !== false && empty($_GET))
{
/* Separate the protocol/host/path component from the query string. */
list($uri, $query) = explode("?", $_SERVER['REQUEST_URI'], 2);
/* Store the entire query string in the relevant $_SERVER variable -
* lighttpds strange behaviour breaks this variable as well. */
$_SERVER['QUERY_STRING'] = $query;
/* Finally, run the query string through PHPs own internal GET data
* parser, and have it store the result in the $_GET variable. This
* should yield an identical result to a well-functioning HTTPd. */
parse_str($query, $_GET);
}
if(get_magic_quotes_gpc())
{
/* By default, get rid of all quoted variables. Magic quotes are evil. */
foreach($_POST as &$var)
{
$var = stripslashes($var);
}
foreach($_GET as &$var)
{
$var = stripslashes($var);
}
}
if(!empty($cphp_config->autoloader))
{
function cphp_autoload_class($class_name)
{
global $_APP;
$class_name = str_replace("\\", "/", strtolower($class_name));
if(file_exists("classes/{$class_name}.php"))
{
require_once("classes/{$class_name}.php");
}
}
spl_autoload_register('cphp_autoload_class');
}
/* https://stackoverflow.com/a/1159235/1332715 */
set_error_handler(function($errno, $errstr, $errfile, $errline, $errcontext) {
if(!(error_reporting() & $errno))
return;
switch($errno) {
case E_WARNING :
case E_USER_WARNING :
case E_STRICT :
case E_NOTICE :
case E_USER_NOTICE :
$type = 'warning';
$fatal = false;
break;
default :
$type = 'fatal error';
$fatal = true;
break;
}
$trace = array_reverse(debug_backtrace());
array_pop($trace);
if(php_sapi_name() == 'cli') {
echo 'Backtrace from ' . $type . ' \'' . $errstr . '\' at ' . $errfile . ' ' . $errline . ':' . "\n";
foreach($trace as $item)
echo ' ' . (isset($item['file']) ? $item['file'] : '<unknown file>') . ' ' . (isset($item['line']) ? $item['line'] : '<unknown line>') . ' calling ' . $item['function'] . '()' . "\n";
} else {
echo '<p class="error_backtrace">' . "\n";
echo ' Backtrace from ' . $type . ' \'' . $errstr . '\' at ' . $errfile . ' ' . $errline . ':' . "\n";
echo ' <ol>' . "\n";
foreach($trace as $item)
echo ' <li>' . (isset($item['file']) ? $item['file'] : '<unknown file>') . ' ' . (isset($item['line']) ? $item['line'] : '<unknown line>') . ' calling ' . $item['function'] . '()</li>' . "\n";
echo ' </ol>' . "\n";
echo '</p>' . "\n";
}
if(ini_get('log_errors')) {
$items = array();
foreach($trace as $item)
$items[] = (isset($item['file']) ? $item['file'] : '<unknown file>') . ' ' . (isset($item['line']) ? $item['line'] : '<unknown line>') . ' calling ' . $item['function'] . '()';
$message = 'Backtrace from ' . $type . ' \'' . $errstr . '\' at ' . $errfile . ' ' . $errline . ': ' . join(' | ', $items);
error_log($message);
}
if($fatal)
exit(1);
});
set_exception_handler(function($e){
/* Intentionally not using the templater here; any inner exceptions
* cause serious debugging issues. Avoiding potential issues by just
* hardcoding the response here, with no code that could raise an
* exception. */
$exception_class = get_class($e);
$exception_message = $e->getMessage();
$exception_file = $e->getFile();
$exception_line = $e->getLine();
$exception_trace = $e->getTraceAsString();
error_log("Uncaught {$exception_class} in {$exception_file}:{$exception_line} ({$exception_message}). Traceback: {$exception_trace}");
switch(strtolower(ini_get('display_errors')))
{
case "1":
case "on":
case "true":
$inner_exceptions = array();
$inner_e = $e;
while(true)
{
$inner_e = $inner_e->getPrevious();
if($inner_e === null)
{
break;
}
else
{
$inner_exceptions[] = array($inner_e->getMessage(), $inner_e->getTraceAsString());
}
}
if(empty($inner_exceptions))
{
$inner_traces = "";
}
else
{
$inner_traces = "<h2>One or more previous exceptions were also recorded.</h2>";
}
foreach($inner_exceptions as $inner_e)
{
$inner_traces .= "
<p>
<span class='message'>{$inner_e[0]}</span>
</p>
<pre>{$inner_e[1]}</pre>
";
}
$error_body = "
<p>
An uncaught <span class='detail'>{$exception_class}</span> was thrown, in <span class='detail'>{$exception_file}</span> on line <span class='detail'>{$exception_line}</span>.
</p>
<p>
<span class='message'>{$exception_message}</span>
</p>
<pre>{$exception_trace}</pre>
{$inner_traces}
<p><strong>Important:</strong> These errors should never be displayed on a production server! Make sure that <em>display_errors</em> is turned off in your PHP configuration, if you want to hide these tracebacks.</p>
";
break;
default:
$error_body = "
<p>
Something went wrong while creating this page, but we're not yet quite sure what it was.
</p>
<p>
If the issue persists, please contact the administrator for this application or website.
</p>
";
break;
}
http_status_code(500);
echo("
<!doctype html>
<html>
<head>
<title>An unexpected error occurred.</title>
<style>
body
{
margin: 24px auto;
padding: 24px 16px;
font-family: sans-serif;
font-size: 18px;
width: 960px;
color: #676767;
}
h1
{
border-bottom: 2px solid black;
color: #444444;
font-size: 26px;
padding-bottom: 6px;
}
h2
{
color: #575757;
border-bottom: 2px solid #444444;
padding-top: 22px;
padding-bottom: 6px;
font-size: 21px;
}
pre
{
overflow: auto;
font-size: 13px;
color: black;
padding: 10px;
border: 1px solid gray;
border-radius: 6px;
background-color: #F8F8F8;
}
.message
{
font-weight: bold;
color: #5B0000;
}
.detail
{
color: black;
}
</style>
</head>
<body>
<h1>An unexpected error occurred.</h1>
{$error_body}
</body>
</html>
");
die();
});

@ -19,8 +19,6 @@ class CPHPBaseClass
public function RenderTimeAgo($template, $property)
{
/* DEPRECATED: Please do not use this function if you can avoid it.
* The time_ago function can now be used to accomplish the same. */
global $locale;
$variable_name = "s{$property}";
@ -132,18 +130,11 @@ class CPHPBaseClass
public function RenderTemplateExternal($template, $strings)
{
/* DEPRECATED: Please do not use this function.
* Instead, you can use Templater::AdvancedParse for rendering arbitrary templates
* without instantiating a Templater yourself. */
return $this->DoRenderTemplate($template, $strings);
}
public function DoRenderTemplate($template, $strings)
{
/* DEPRECATED: Please do not use this function.
* Class-specific templater functions have been discontinued. Instead, you can use
* Templater::AdvancedParse for rendering templates without instantiating a Templater
* yourself. */
global $locale;
try

@ -19,131 +19,40 @@ abstract class CPHPDatabaseRecordClass extends CPHPBaseClass
public $verify_query = "";
public $table_name = "";
public $query_cache = 60;
public $id_field = "Id";
public $autoloading = true;
public $prototype = array();
public $prototype_render = array();
public $prototype_export = array();
public $uData = array();
public $sIsNewObject = true;
public $sId = 0;
public function __construct($uDataSource = 0, $defaultable = null)
public function __construct($uDataSource, $uCommunityId = 0)
{
global $cphp_config;
if(!isset($cphp_config->class_map))
{
die("No class map was specified. Refer to the CPHP manual for instructions.");
}
$this->ConstructDataset($uDataSource);
$this->ConstructDataset($uDataSource, $uCommunityId);
$this->EventConstructed();
}
public function __get($name)
{
/* TODO: Don't overwrite current value in uVariable when sVariable is requested and uVariable is already set. */
if($name[0] == "s" || $name[0] == "u")
{
$actual_name = substr($name, 1);
$found = false;
foreach($this->prototype as $type => $dataset)
{
if(isset($dataset[$actual_name]))
{
$found = true;
$found_type = $type;
$found_field = $dataset[$actual_name];
}
}
if($found === false)
{
$classname = get_class($this);
throw new PrototypeException("The {$actual_name} variable was not found in the prototype of the {$classname} class.");
}
$this->SetField($found_type, $actual_name, $found_field);
return $this->$name;
}
}
public function RefreshData()
public function ConstructDataset($uDataSource, $uCommunityId = 0)
{
$this->PurgeCache();
$this->ConstructDataset($this->sId, 0);
if($this->autoloading === true)
{
$this->PurgeVariables();
}
}
public function PurgeVariables()
{
foreach($this->prototype as $type => $dataset)
{
foreach($dataset as $key => $field)
{
$variable_name_safe = "s" . $key;
$variable_name_unsafe = "u" . $key;
unset($this->$variable_name_safe);
unset($this->$variable_name_unsafe);
}
}
}
public function ConstructDataset($uDataSource, $expiry = -1)
{
global $database;
$bind_datasets = true;
if(is_object($uDataSource))
{
if(isset($uDataSource->data[0]))
{
$uDataSource = $uDataSource->data[0];
}
else
{
throw new NotFoundException("No result set present in object.");
}
}
elseif(is_array($uDataSource))
{
if(isset($uDataSource[0]))
{
$uDataSource = $uDataSource[0];
}
}
elseif(is_string($uDataSource) || is_numeric($uDataSource))
if(is_numeric($uDataSource))
{
if($uDataSource !== 0)
if($uDataSource != 0)
{
if(!empty($this->fill_query))
{
/* TODO: Figure out a way to store the ID internally without post-processing... */
$this->sId = htmlspecialchars($uDataSource);
$expiry = ($expiry == -1) ? $this->query_cache : $expiry;
$this->sId = (is_numeric($uDataSource)) ? $uDataSource : 0;
/* Use PDO to fetch the object from the database. */
if($result = $database->CachedQuery($this->fill_query, array(":Id" => (string) $uDataSource), $expiry))
$query = sprintf($this->fill_query, $uDataSource);
if($result = mysql_query_cached($query, $this->query_cache))
{
$uDataSource = $result->data[0];
}
else
{
$classname = get_class($this);
throw new NotFoundException("Could not locate {$classname} {$uDataSource} in database.", 0, null, "");
throw new NotFoundException("Could not locate {$classname} {$uDataSource} in database.");
}
}
else
@ -155,7 +64,24 @@ abstract class CPHPDatabaseRecordClass extends CPHPBaseClass
else
{
$bind_datasets = false;
$this->FillDefaults();
}
}
elseif(is_object($uDataSource))
{
if(isset($uDataSource->data[0]))
{
$uDataSource = $uDataSource->data[0];
}
else
{
throw new NotFoundException("No result set present in object.");
}
}
elseif(is_array($uDataSource))
{
if(isset($uDataSource[0]))
{
$uDataSource = $uDataSource[0];
}
}
else
@ -166,17 +92,13 @@ abstract class CPHPDatabaseRecordClass extends CPHPBaseClass
if($bind_datasets === true)
{
$this->sId = htmlspecialchars($uDataSource[$this->id_field]);
$this->sIsNewObject = false;
$this->sId = (is_numeric($uDataSource['Id'])) ? $uDataSource['Id'] : 0;
$this->uData = $uDataSource;
if($this->autoloading === false)
foreach($this->prototype as $type => $dataset)
{
foreach($this->prototype as $type => $dataset)
{
$this->BindDataset($type, $dataset, $defaultable);
}
$this->BindDataset($type, $dataset);
}
$this->sFound = true;
@ -185,167 +107,106 @@ abstract class CPHPDatabaseRecordClass extends CPHPBaseClass
{
$this->sFound = false;
}
}
public function BindDataset($type, $dataset, $defaultable)
{
global $cphp_config;
if(is_array($dataset))
if(!empty($uCommunityId) && !empty($this->sCommunityId))
{
foreach($dataset as $variable_name => $column_name)
$sCommunityId = (is_numeric($uCommunityId)) ? $uCommunityId : 0;
if($sCommunityId != $this->sCommunity->sId)
{
$this->SetField($type, $variable_name, $column_name);
$classname = get_class($this);
throw new OwnershipException("{$classname} {$this->sId} does not belong to Community {$sCommunityId}.");
}
}
else
{
$classname = get_class($this);
throw new Exception("Invalid dataset passed on to {$classname}.BindDataset.");
}
}
public function SetField($type, $variable_name, $column_name)
public function BindDataset($type, $dataset)
{
global $cphp_config;
if(!isset($this->uData[$column_name]))
{
throw new Exception("The column name {$column_name} was not found in the resultset - ensure the prototype corresponds to the table schema.");
}
global $cphp_class_map;
$original_value = $this->uData[$column_name];
if($original_value === "" && ($type == "timestamp" || $type == "numeric" || $type == "boolean"))
{
$variable_name_safe = "s" . $variable_name;
$this->$variable_name_safe = null;
$variable_name_unsafe = "u" . $variable_name;
$this->$variable_name_unsafe = null;
}
else
if(is_array($dataset))
{
switch($type)
foreach($dataset as $variable_name => $column_name)
{
case "string":
$value = htmlspecialchars(stripslashes($original_value));
$variable_type = CPHP_VARIABLE_SAFE;
break;
case "html":
$value = filter_html(stripslashes($original_value));
$variable_type = CPHP_VARIABLE_SAFE;
break;
case "simplehtml":
$value = filter_html_strict(stripslashes($original_value));
$variable_type = CPHP_VARIABLE_SAFE;
break;
case "nl2br":
$value = nl2br(htmlspecialchars(stripslashes($original_value)), false);
$variable_type = CPHP_VARIABLE_SAFE;
break;
case "numeric":
$value = (is_numeric($original_value)) ? $original_value : 0;
$variable_type = CPHP_VARIABLE_SAFE;
break;
case "timestamp":
$value = unix_from_mysql($original_value);
$variable_type = CPHP_VARIABLE_SAFE;
break;
case "boolean":
$value = (empty($original_value)) ? false : true;
$variable_type = CPHP_VARIABLE_SAFE;
break;
case "none":
$value = $original_value;
$variable_type = CPHP_VARIABLE_UNSAFE;
break;
default:
$found = false;
foreach(get_object_vars($cphp_config->class_map) as $class_type => $class_name)
{
if($type == $class_type)
$original_value = $this->uData[$column_name];
switch($type)
{
case "string":
$value = htmlspecialchars(stripslashes($original_value));
$variable_type = CPHP_VARIABLE_SAFE;
break;
case "html":
$value = filter_html(stripslashes($original_value));
$variable_type = CPHP_VARIABLE_SAFE;
break;
case "simplehtml":
$value = filter_html_strict(stripslashes($original_value));
$variable_type = CPHP_VARIABLE_SAFE;
break;
case "nl2br":
$value = nl2br(htmlspecialchars(stripslashes($original_value)), false);
$variable_type = CPHP_VARIABLE_SAFE;
break;
case "numeric":
$value = (is_numeric($original_value)) ? $original_value : 0;
$variable_type = CPHP_VARIABLE_SAFE;
break;
case "timestamp":
$value = unix_from_mysql($original_value);
$variable_type = CPHP_VARIABLE_SAFE;
break;
case "boolean":
$value = (empty($original_value)) ? false : true;
$variable_type = CPHP_VARIABLE_SAFE;
break;
case "user":
$value = new User($original_value);
$variable_type = CPHP_VARIABLE_SAFE;
break;
case "none":
$value = $original_value;
$variable_type = CPHP_VARIABLE_UNSAFE;
break;
default:
$found = false;
foreach($cphp_class_map as $class_type => $class_name)
{
try
if($type == $class_type)
{
$value = new $class_name($original_value);
$variable_type = CPHP_VARIABLE_SAFE;
$found = true;
}
catch (NotFoundException $e)
{
$e->field = $variable_name;
throw $e;
}
$variable_type = CPHP_VARIABLE_SAFE;
$found = true;
}
}
if($found == false)
{
$classname = get_class($this);
throw new Exception("Cannot determine type of dataset ({$type}) passed on to {$classname}.BindDataset.");
break;
}
}
if($variable_type == CPHP_VARIABLE_SAFE)
{
$variable_name_safe = "s" . $variable_name;
$this->$variable_name_safe = $value;
if($found == false)
{
$classname = get_class($this);
throw new Exception("Cannot determine type of dataset ({$type}) passed on to {$classname}.BindDataset.");
break;
}
}
if($variable_type == CPHP_VARIABLE_SAFE)
{
$variable_name_safe = "s" . $variable_name;
$this->$variable_name_safe = $value;
}
$variable_name_unsafe = "u" . $variable_name;
$this->$variable_name_unsafe = $original_value;
}
$variable_name_unsafe = "u" . $variable_name;
$this->$variable_name_unsafe = $original_value;
}
}
public function FillDefaults()
{
foreach($this->prototype as $type => $dataset)
else
{
switch($type)
{
case "string":
case "simplehtml":
case "html":
case "nl2br":
case "none":
$safe_default_value = "";
$unsafe_default_value = "";
break;
case "numeric":
$safe_default_value = 0;
$unsafe_default_value = "0";
break;
case "boolean":
$safe_default_value = false;
$unsafe_default_value = "0";
break;
case "timestamp":
$safe_default_value = null;
$unsafe_default_value = null;
break;
default:
continue 2;
}
foreach($dataset as $property)
{
$safe_variable_name = "s" . $property;
$this->$safe_variable_name = $safe_default_value;
$unsafe_variable_name = "u" . $property;
$this->$unsafe_variable_name = $unsafe_default_value;
}
$classname = get_class($this);
throw new Exception("Invalid dataset passed on to {$classname}.BindDataset.");
}
}
public function DoRenderInternalTemplate()
{
/* DEPRECATED: Please do not use this function.
* Class-specific templater functions have been discontinued. Instead, you can use
* Templater::AdvancedParse for rendering templates without instantiating a Templater
* yourself. */
if(!empty($this->render_template))
{
$strings = array();
@ -363,25 +224,18 @@ abstract class CPHPDatabaseRecordClass extends CPHPBaseClass
}
}
public function InsertIntoDatabase($force_data = false)
public function InsertIntoDatabase()
{
global $cphp_config, $database;
if(!empty($this->verify_query))
{
if(strpos($this->verify_query, ":Id") === false)
{
throw new DeprecatedException("Support for mysql_* has been removed from CPHP. Please update your queries to be in CachedPDO-style.");
}
if($this->sIsNewObject === true)
if($this->sId == 0)
{
$insert_mode = CPHP_INSERTMODE_INSERT;
}
else
{
/* FIXME: This can probably be optimized... */
if($result = $database->CachedQuery($this->verify_query, array(":Id" => $this->sId), 0))
$query = sprintf($this->verify_query, $this->sId);
if($result = mysql_query_cached($query))
{
$insert_mode = CPHP_INSERTMODE_UPDATE;
}
@ -391,29 +245,6 @@ abstract class CPHPDatabaseRecordClass extends CPHPBaseClass
}
}
if($force_data === true)
{
foreach($this->prototype as $type_key => $type_value)
{
foreach($type_value as $element_key => $element_value)
{
$variable_name_unsafe = "u" . $element_key;
if(!isset($this->$variable_name_unsafe))
{
foreach($this->prototype as $type => $dataset)
{
if(isset($dataset[$element_key]))
{
$column_name = $dataset[$element_key];
$this->$variable_name_unsafe = $this->uData[$column_name];
}
}
}
}
}
}
$element_list = array();
foreach($this->prototype as $type_key => $type_value)
@ -427,9 +258,6 @@ abstract class CPHPDatabaseRecordClass extends CPHPBaseClass
case "boolean":
case "timestamp":
case "string":
case "simplehtml":
case "html":
case "nl2br":
$element_list[$element_value] = array(
'key' => $element_key,
'type' => $type_key
@ -442,8 +270,7 @@ abstract class CPHPDatabaseRecordClass extends CPHPBaseClass
}
$sKeyList = array();
$sKeyIdentifierList = array();
$uValueList = array();
$sValueList = array();
foreach($element_list as $sKey => $value)
{
@ -455,121 +282,77 @@ abstract class CPHPDatabaseRecordClass extends CPHPBaseClass
switch($value['type'])
{
case "none":
$uFinalValue = $this->$variable_name_unsafe;
$sFinalValue = mysql_real_escape_string($this->$variable_name_unsafe);
break;
case "numeric":
$number = (isset($this->$variable_name_unsafe)) ? $this->$variable_name_unsafe : $this->$variable_name_safe;
$uFinalValue = (is_numeric($number)) ? $number : 0;
$sFinalValue = (is_numeric($number)) ? $number : 0;
break;
case "boolean":
$bool = (isset($this->$variable_name_unsafe)) ? $this->$variable_name_unsafe : $this->$variable_name_safe;
$uFinalValue = ($bool) ? "1" : "0";
$sFinalValue = ($bool) ? "1" : "0";
break;
case "timestamp":
if(is_numeric($this->$variable_name_unsafe))
{
$uFinalValue = mysql_from_unix($this->$variable_name_unsafe);
}
else
{
if(isset($this->$variable_name_safe))
{
$uFinalValue = mysql_from_unix($this->$variable_name_safe);
}
else
{
$uFinalValue = mysql_from_unix(unix_from_local($this->$variable_name_unsafe));
}
}
$sFinalValue = (isset($this->$variable_name_safe)) ? mysql_from_unix($this->$variable_name_safe) : mysql_from_unix(unix_from_local($this->$variable_name_unsafe));
break;
case "string":
case "simplehtml":
case "html":
case "nl2br":
$uFinalValue = (isset($this->$variable_name_unsafe)) ? $this->$variable_name_unsafe : $this->$variable_name_safe;
$sFinalValue = (isset($this->$variable_name_unsafe)) ? mysql_real_escape_string($this->$variable_name_unsafe) : mysql_real_escape_string($this->$variable_name_safe);
break;
case "default":
$uFinalValue = $this->$variable_name_unsafe;
$sFinalValue = mysql_real_escape_string($this->$variable_name_unsafe);
break;
}
$sIdentifier = ":{$sKey}";
$sFinalValue = "'{$sFinalValue}'";
$sKey = "`{$sKey}`";
$sKeyList[] = "`{$sKey}`";
$sKeyIdentifierList[] = $sIdentifier;
$uValueList[$sIdentifier] = $uFinalValue;
$sKeyList[] = $sKey;
$sValueList[] = $sFinalValue;
}
else
{
if($this->autoloading === false)
{
$classname = get_class($this);
throw new Exception("Database insertion failed: prototype property {$value['key']} not found in object of type {$classname}.");
}
$classname = get_class($this);
throw new Exception("Database insertion failed: prototype property {$value['key']} not found in object of type {$classname}.");
}
}
if($insert_mode == CPHP_INSERTMODE_INSERT)
{
if(!empty($this->uId))
{
$sIdentifier = ":{$this->id_field}";
$sKeyList[] = "`{$this->id_field}`";
$sKeyIdentifierList[] = $sIdentifier;
$uValueList[$sIdentifier] = $this->uId;
}
$sQueryKeys = implode(", ", $sKeyList);
$sQueryKeyIdentifiers = implode(", ", $sKeyIdentifierList);
$query = "INSERT INTO {$this->table_name} ({$sQueryKeys}) VALUES ({$sQueryKeyIdentifiers})";
$sQueryValues = implode(", ", $sValueList);
$query = "INSERT INTO {$this->table_name} ({$sQueryKeys}) VALUES ({$sQueryValues})";
}
elseif($insert_mode == CPHP_INSERTMODE_UPDATE)
{
$sKeysIdentifiersList = array();
$sKeyValueList = array();
for($i = 0; $i < count($sKeyList); $i++)
{
$sKey = $sKeyList[$i];
$sValue = $sKeyIdentifierList[$i];
$sKeysIdentifiersList[] = "{$sKey} = {$sValue}";
$sValue = $sValueList[$i];
$sKeyValueList[] = "{$sKey} = {$sValue}";
}
$sQueryKeysIdentifiers = implode(", ", $sKeysIdentifiersList);
/* We use :CPHPID here because it's unlikely to be used in the application itself. */
$query = "UPDATE {$this->table_name} SET {$sQueryKeysIdentifiers} WHERE `{$this->id_field}` = :CPHPID";
$uValueList[':CPHPID'] = $this->sId;
$sQueryKeysValues = implode(", ", $sKeyValueList);
$query = "UPDATE {$this->table_name} SET {$sQueryKeysValues} WHERE `Id` = '{$this->sId}'";
}
try
if($result = mysql_query($query))
{
$result = $database->CachedQuery($query, $uValueList, 0);
if($insert_mode == CPHP_INSERTMODE_INSERT)
{
$this->sId = $database->lastInsertId();
$this->sIsNewObject = false;
$this->sId = mysql_insert_id();
}
$this->RefreshData();
$this->PurgeCache();
return $result;
}
catch (DatabaseException $e)
else
{
$classname = get_class($this);
$error = $database->errorInfo();
if(empty($error[2]))
{
$errmsg = $e->getMessage();
}
else
{
$errmsg = $error[2];
}
throw new DatabaseException("Database insertion query failed in object of type {$classname}. Error message: " . $errmsg);
throw new DatabaseException("Database insertion query failed in object of type {$classname}. Error message: " . mysql_error());
}
}
else
@ -581,15 +364,13 @@ abstract class CPHPDatabaseRecordClass extends CPHPBaseClass
public function RetrieveChildren($type, $field)
{
/* Probably won't ever be fully implemented, now that there is CreateFromQuery. */
if(!isset($cphp_config->class_map->$type))
if(!isset($cphp_class_map[$type]))
{
$classname = get_class($this);
throw new NotFoundException("Non-existent 'type' argument passed on to {$classname}.RetrieveChildren function.");
}
$parent_type = get_parent_class($cphp_config->class_map->$type);
$parent_type = get_parent_class($cphp_class_map[$type]);
if($parent_type !== "CPHPDatabaseRecordClass")
{
$parent_type = ($parent_type === false) ? "NONE" : $parent_type;
@ -602,13 +383,9 @@ abstract class CPHPDatabaseRecordClass extends CPHPBaseClass
public function PurgeCache()
{
$parameters = array(":Id" => (string) $this->sId);
$query_hash = md5($this->fill_query);
$parameter_hash = md5(serialize($parameters));
$cache_hash = $query_hash . $parameter_hash;
mc_delete($cache_hash);
$query = sprintf($this->fill_query, $this->sId);
$key = md5($query) . md5($query . "x");
mc_delete($key);
}
public function RenderTemplate($template = "")
@ -621,69 +398,6 @@ abstract class CPHPDatabaseRecordClass extends CPHPBaseClass
return $this->DoRenderInternalTemplate();
}
public function Export()
{
/* This function is DEPRECATED and should not be used. Please manually build your arrays instead. */
$export_array = array();
foreach($this->prototype_export as $field)
{
$variable_name = "s{$field}";
if(is_object($this->$variable_name))
{
if(!empty($this->$variable_name->sId))
{
$export_array[$field] = $this->$variable_name->Export();
}
else
{
$export_array[$field] = null;
}
}
else
{
$export_array[$field] = $this->$variable_name;
}
}
return $export_array;
}
public static function CreateFromQuery($query, $parameters = array(), $expiry = 0, $first_only = false)
{
global $database;
$result = $database->CachedQuery($query, $parameters, $expiry);
if($result)
{
if($first_only === true)
{
/* TODO: Try to run the query with LIMIT 1 if only the first result is desired. */
return new static($result);
}
elseif(count($result->data) == 1)
{
return array(new static($result));
}
else
{
$result_array = array();
foreach($result->data as $row)
{
$result_array[] = new static($row);
}
return $result_array;
}
}
else
{
throw new NotFoundException("No results for specified query.");
}
}
// Define events
protected function EventConstructed() { }

@ -22,7 +22,6 @@ class Localizer
public $date_short = "";
public $date_long = "";
public $time = "";
public $name = "";
public function Load($locale)
{
@ -33,14 +32,8 @@ class Localizer
public function LoadInternal($locale)
{
global $cphp_config;
if(!isset($cphp_config->locale->path) || !isset($cphp_config->locale->extension))
{
throw new Exception("The locale path settings are not specified correctly. Refer to the CPHP manual for instructions.");
}
$lng_contents = file_get_contents("{$cphp_config->locale->path}/{$locale}.{$cphp_config->locale->extension}");
global $cphp_locale_path, $cphp_locale_ext;
$lng_contents = file_get_contents("{$cphp_locale_path}/{$locale}.{$cphp_locale_ext}");
if($lng_contents !== false)
{
$lines = explode("\n", $lng_contents);
@ -77,8 +70,6 @@ class Localizer
}
}
}
$this->name = $locale;
}
else
{

File diff suppressed because it is too large Load Diff

@ -42,27 +42,31 @@ class CPHPErrorHandler
{
global $locale;
$template['error'] = new Templater();
switch($this->sErrorType)
{
case CPHP_ERRORHANDLER_TYPE_ERROR:
$template = "errorhandler.error";
$template['error']->Load("errorhandler.error");
break;
case CPHP_ERRORHANDLER_TYPE_INFO:
$template = "errorhandler.info";
$template['error']->Load("errorhandler.info");
break;
case CPHP_ERRORHANDLER_TYPE_WARNING:
$template = "errorhandler.warning";
$template['error']->Load("errorhandler.warning");
break;
case CPHP_ERRORHANDLER_TYPE_SUCCESS:
$template = "errorhandler.success";
$template['error']->Load("errorhandler.success");
break;
default:
return false;
}
return Templater::AdvancedParse($template, $locale->strings, array(
$template['error']->Localize($locale->strings);
$template['error']->Compile(array(
'title' => $this->sTitle,
'message' => $this->sMessage
));
return $template['error']->Render();
}
}
?>

@ -0,0 +1,319 @@
<?php
/*
* CPHP is more free software. It is licensed under the WTFPL, which
* allows you to do pretty much anything with it, without having to
* ask permission. Commercial use is allowed, and no attribution is
* required. We do politely request that you share your modifications
* to benefit other developers, but you are under no enforced
* obligation to do so :)
*
* Please read the accompanying LICENSE document for the full WTFPL
* licensing text.
*/
cphp_dependency_provides("cphp_formbuilder", "1.0");
$cphp_formbuilder_increment = 0;
abstract class CPHPFormBuilderBaseClass
{
public $parameters = array();
public function AddParameter($key, $value)
{
$this->parameters[$key] = $value;
}
public function RenderParameters($parameters)
{
if(empty($parameters))
{
return "";
}
$rendered = array();
foreach($parameters as $key => $value)
{
$value = utf8entities($value);
$rendered[] = "{$key}=\"{$value}\"";
}
return " " . implode(" ", $rendered);
}
public function RenderNote()
{
if(!empty($this->note))
{
return "<div class=\"cphp_fbd_note\">{$this->note}</div>";
}
else
{
return "";
}
}
}
abstract class CPHPFormBuilderContainer extends CPHPFormBuilderBaseClass
{
public $elements = array();
public function AddElement($element)
{
$this->elements[] = $element;
}
}
class CPHPFormBuilder extends CPHPFormBuilderContainer
{
public $method = "";
public $action = "";
public function __construct($method, $target)
{
$this->method = strtolower($method);
$this->action = $target;
}
public function Render()
{
$rendered_elements = "";
foreach($this->elements as $element)
{
$rendered_elements .= $element->Render();
}
$this->AddParameter("method", $this->method);
$this->AddParameter("action", $this->action);
$rendered_parameters = $this->RenderParameters($this->parameters);
return "<form{$rendered_parameters}>{$rendered_elements}</form>";
}
}
class CPHPFormSection extends CPHPFormBuilderContainer
{
public $label = "";
public $fieldset = true;
public $classname = "";
public function __construct($fieldset = true, $label = "")
{
if(!empty($label))
{
$this->label = $label;
}
$this->fieldset = $fieldset;
}
public function Render()
{
if(!empty($this->label))
{
$legend = "<legend>{$this->label}</legend>";
}
else
{
$legend = "";
}
if($this->fieldset === true)
{
$this->classname = trim("{$this->classname} cphp_fbd_fieldset");
}
$rendered_elements = "";
foreach($this->elements as $element)
{
$rendered_elements .= $element->Render();
}
if($this->fieldset === true)
{
$this->AddParameter("class", $this->classname);
$rendered_parameters = $this->RenderParameters($this->parameters);
return "<fieldset{$rendered_parameters}>{$legend}<div class=\"cphp_fbd_form\">{$rendered_elements}</div></fieldset>";
}
else
{
return "<div class=\"cphp_fbd_form\"{$rendered_parameters}>{$rendered_elements}</div>";
}
}
}
abstract class CPHPFormInputElement extends CPHPFormBuilderBaseClass
{
public $id = "";
public $name = "";
public $value = "";
public $label = "";
public function __construct($label, $name, $value = "", $note = "", $id = "")
{
global $cphp_formbuilder_increment;
$this->name = $name;
$this->value = $value;
$this->label = $label;
$this->note = $note;
if(empty($id))
{
$this->id = "cphp_fbd_{$cphp_formbuilder_increment}";
$cphp_formbuilder_increment += 1;
}
else
{
$this->id = $id;
}
}
}
abstract class CPHPFormInput extends CPHPFormInputElement
{
public function Render()
{
$this->AddParameter("id", $this->id);
$this->AddParameter("type", $this->type);
$this->AddParameter("name", $this->name);
$this->AddParameter("value", $this->value);
$rendered_parameters = $this->RenderParameters($this->parameters);
$rendered_note = $this->RenderNote();
return "<div class=\"cphp_fbd_row\"><div class=\"cphp_fbd_label\">{$this->label}{$rendered_note}</div><div class=\"cphp_fbd_field\"><input{$rendered_parameters}></div></div>";
}
}
class CPHPFormTextInput extends CPHPFormInput
{
public $type = "text";
}
class CPHPFormPasswordInput extends CPHPFormInput
{
public $type = "password";
}
class CPHPFormDateInput extends CPHPFormInput
{
public $type = "date";
}
class CPHPFormTimeInput extends CPHPFormInput
{
public $type = "time";
}
class CPHPFormEmailInput extends CPHPFormInput
{
public $type = "email";
}
class CPHPFormUrlInput extends CPHPFormInput
{
public $type = "url";
}
class CPHPFormRangeInput extends CPHPFormInput
{
public $type = "range";
}
class CPHPFormColorInput extends CPHPFormInput
{
public $type = "color";
}
class CPHPFormSearchInput extends CPHPFormInput
{
public $type = "search";
}
class CPHPFormCheckboxGroup extends CPHPFormBuilderContainer
{
public function __construct($label, $note = "")
{
global $cphp_formbuilder_increment;
$this->label = $label;
$this->note = $note;
}
public function Render()
{
$rendered_note = $this->RenderNote();
$rendered_elements = "";
foreach($this->elements as $element)
{
$rendered_elements .= $element->Render();
}
return "<div class=\"cphp_fbd_row\"><div class=\"cphp_fbd_label\">{$this->label}{$rendered_note}</div><div class=\"cphp_fbd_field\">{$rendered_elements}</div></div>";
}
}
class CPHPFormCheckbox extends CPHPFormInputElement
{
public function Render()
{
$this->AddParameter("id", $this->id);
$this->AddParameter("type", "checkbox");
$this->AddParameter("name", $this->name);
if($this->value === true)
{
$this->AddParameter("checked", "");
}
$rendered_parameters = $this->RenderParameters($this->parameters);
$rendered_note = $this->RenderNote();
return "<div class=\"cphp_fbd_cblabel\"><input{$rendered_parameters}><label for=\"{$this->id}\">{$this->label}{$rendered_note}</label></div>";
}
}
class CPHPFormRadioButton extends CPHPFormInput
{
public $type = "radio";
}
class CPHPFormButton extends CPHPFormInputElement
{
public $type = "button";
public function Render()
{
$this->AddParameter("type", $this->type);
$this->AddParameter("name", $this->name);
$this->AddParameter("value", $this->value);
$rendered_parameters = $this->RenderParameters($this->parameters);
return "<div class=\"cphp_fbd_row\"><div class=\"cphp_fbd_label\"></div><div class=\"cphp_fbd_field\"><button{$rendered_parameters}>{$this->label}</button></div></div>";
}
}
class CPHPFormSubmitButton extends CPHPFormButton
{
public $type = "submit";
}
class CPHPFormResetButton extends CPHPFormButton
{
public $type = "reset";
}
class CPHPFormSelect extends CPHPFormInputElement
{
public $options = array();
}
?>

@ -11,18 +11,13 @@
* licensing text.
*/
cphp_dependency_provides("cphp_router", "1.1");
class RouterException extends Exception {}
cphp_dependency_provides("cphp_router", "1.0");
class CPHPRouter extends CPHPBaseClass
{
public $routes = array();
public $parameters = array();
public $uVariables = array();
public $custom_query = "";
public $allow_slash = false;
public $ignore_query = false;
public function RouteRequest()
{
@ -44,17 +39,6 @@ class CPHPRouter extends CPHPBaseClass
}
}
// Save request path in Router object to make it accessible to other scripts.
$this->uRequestPath = $requestpath;
if($this->ignore_query === true)
{
if(strpos($requestpath, "?") !== false)
{
list($requestpath, $bogus) = explode("?", $requestpath, 2);
}
}
$found = false; // Workaround because a break after an include apparently doesn't work in PHP.
foreach($this->routes as $priority)
@ -63,101 +47,16 @@ class CPHPRouter extends CPHPBaseClass
{
if($found === false)
{
if($this->allow_slash === true)
{
if(strpos($route_regex, "$") !== false)
{
$route_regex = str_replace("$", "/?$", $route_regex);
}
else
{
$route_regex = "{$route_regex}/?";
}
}
$regex = str_replace("/", "\/", $route_regex);
if(preg_match("/{$regex}/i", $requestpath, $matches))
{
$this->uParameters = $matches;
$this->uMethod = strtolower($_SERVER['REQUEST_METHOD']);
if(is_array($route_destination))
{
// Options were provided.
if(!isset($route_destination['target']))
{
throw new InvalidArgumentException("Target is missing from CPHPRoute options element.");
}
if(!empty($route_destination['methods']))
{
$sMethods = (!is_array($route_destination['methods'])) ? array($route_destination['methods']) : $route_destination['methods'];
if(!in_array($this->uMethod, $sMethods))
{
continue;
}
}
$authenticated = false;
if(!isset($route_destination['authenticator']))
{
$authenticated = true;
}
else
{
if(!isset($route_destination['auth_error']))
{
throw new InvalidArgumentException("When specifying an authenticator, you must also specify a default error destination.");
}
$sRouterAuthenticated = false;
$sRouterErrorDestination = $route_destination['auth_error'];
require($route_destination['authenticator']);
if($sRouterAuthenticated === true)
{
$authenticated = true;
}
}
foreach($route_destination as $key => $value)
{
if(strlen($key) > 1 && substr($key, 0, 1) == "_")
{
$key = substr($key, 1);
$this->uVariables[$key] = $value;
}
}
if($authenticated === true)
{
$destination = $route_destination['target'];
$this->sAuthenticated = true;
}
else
{
$destination = $sRouterErrorDestination;
$this->sAuthenticated = false;
}
}
else
{
$destination = $route_destination;
}
include($destination);
include($route_destination);
$found = true;
}
}
}
}
if($found === false)
{
throw new RouterException("No suitable route found");
}
}
}
?>

@ -11,16 +11,9 @@
* licensing text.
*/
if($_CPHP !== true) { die(); }
$cphp_mysql_host = "localhost";
$cphp_mysql_user = "root";
$cphp_mysql_pass = "";
$cphp_mysql_db = "";
if(!empty($cphp_config->locale->default_locale))
{
$locale = new Localizer();
$locale->Load($cphp_config->locale->default_locale);
setlocale(LC_ALL, $locale->locale);
}
else
{
die("No default locale was specified. Refer to the CPHP manual for instructions.");
}
?>

@ -0,0 +1,42 @@
<?php
/*
* CPHP is more free software. It is licensed under the WTFPL, which
* allows you to do pretty much anything with it, without having to
* ask permission. Commercial use is allowed, and no attribution is
* required. We do politely request that you share your modifications
* to benefit other developers, but you are under no enforced
* obligation to do so :)
*
* Please read the accompanying LICENSE document for the full WTFPL
* licensing text.
*/
if($_CPHP !== true) { die(); }
$cphp_class_map = array(
'classa' => "ClassA",
'classb' => "ClassB"
);
$cphp_locale_name = "english";
$cphp_locale_path = "locales";
$cphp_locale_ext = "lng";
$cphp_usersettings[CPHP_SETTING_TIMEZONE] = "Europe/Amsterdam";
/* These are the memcache settings. You will need to have memcache set
* up on your server to use these. Compression requires zlib. */
$cphp_memcache_enabled = true; // Whether to user memcache.
$cphp_memcache_server = "localhost"; // The hostname of the memcached
$cphp_memcache_port = 11211; // The port number of memcached
$cphp_memcache_compressed = true; // Whether to compress memcache objects
$cphp_mysql_enabled = true;
require("config.mysql.php");
$cphp_components = array(
"router",
"errorhandler",
"formbuilder"
);

@ -1,33 +0,0 @@
<?php
/*
* CPHP is more free software. It is licensed under the WTFPL, which
* allows you to do pretty much anything with it, without having to
* ask permission. Commercial use is allowed, and no attribution is
* required. We do politely request that you share your modifications
* to benefit other developers, but you are under no enforced
* obligation to do so :)
*
* Please read the accompanying LICENSE document for the full WTFPL
* licensing text.
*/
if($_CPHP !== true) { die(); }
if(empty($_CPHP_CONFIG))
{
die("No valid CPHP configuration path was specified. Refer to the CPHP manual for instructions.");
}
$confdata = @file_get_contents($_CPHP_CONFIG);
if($confdata === false)
{
die("The specified CPHP configuration path was not found. Refer to the CPHP manual for instructions.");
}
$cphp_config = @json_decode($confdata);
if(json_last_error() != JSON_ERROR_NONE)
{
die("Failed to parse CPHP configuration. Refer to the CPHP manual for instructions.");
}

@ -1,74 +0,0 @@
<?php
/*
* CPHP is more free software. It is licensed under the WTFPL, which
* allows you to do pretty much anything with it, without having to
* ask permission. Commercial use is allowed, and no attribution is
* required. We do politely request that you share your modifications
* to benefit other developers, but you are under no enforced
* obligation to do so :)
*
* Please read the accompanying LICENSE document for the full WTFPL
* licensing text.
*/
if($_CPHP !== true) { die(); }
class CSRF
{
public static function GenerateToken()
{
$key = random_string(12);
$token = random_string(25);
if(!isset($_SESSION['_CPHP_CSRF_KEYS']))
{
$_SESSION['_CPHP_CSRF_KEYS'] = array();
}
$_SESSION['_CPHP_CSRF_KEYS'][$key] = $token;
return array(
'key' => $key,
'token' => $token
);
}
public static function GenerateReplacement($matches)
{
$pair = CSRF::GenerateToken();
return $matches[0] . "
<input name=\"_CPHP_CSRF_KEY\" type=\"hidden\" value=\"{$pair['key']}\">
<input name=\"_CPHP_CSRF_TOKEN\" type=\"hidden\" value=\"{$pair['token']}\">";
}
public static function InsertTokens($input)
{
return preg_replace_callback("/<form[^>]*>(?!\s*<input name=\"_CPHP_CSRF)/i", "CSRF::GenerateReplacement", $input);
}
public static function VerifyToken($source = null)
{
if($source == null)
{
$source = $_POST;
}
if(!empty($source['_CPHP_CSRF_KEY']) && !empty($source['_CPHP_CSRF_TOKEN']))
{
$key = $source['_CPHP_CSRF_KEY'];
$token = $source['_CPHP_CSRF_TOKEN'];
if(empty($_SESSION['_CPHP_CSRF_KEYS'][$key]) || $_SESSION['_CPHP_CSRF_KEYS'][$key] != $token)
{
throw new CsrfException("The given CSRF token does not match the given CSRF key.");
}
}
else
{
throw new CsrfException("No CSRF token present in submitted data.");
}
}
}
class CsrfException extends Exception {}

@ -13,142 +13,133 @@
if($_CPHP !== true) { die(); }
if(!empty($cphp_config->locale->default_timezone))
{
$user_preferences[CPHP_SETTING_TIMEZONE] = $cphp_config->locale->default_timezone;
}
else
{
die("No default timezone was specified. Refer to the CPHP manual for instructions.");
}
$timezones = array(
'Pacific/Kwajalein' => '(GMT-12:00) International Date Line West',
'Pacific/Midway' => '(GMT-11:00) Midway Island',
'Pacific/Samoa' => '(GMT-11:00) Samoa',
'Pacific/Honolulu' => '(GMT-10:00) Hawaii',
'America/Anchorage' => '(GMT-09:00) Alaska',
'America/Los_Angeles' => '(GMT-08:00) Pacific Time (US &amp; Canada)',
'America/Tijuana' => '(GMT-08:00) Tijuana, Baja California',
'America/Denver' => '(GMT-07:00) Mountain Time (US &amp; Canada)',
'America/Chihuahua' => '(GMT-07:00) Chihuahua',
'America/Mazatlan' => '(GMT-07:00) Mazatlan',
'America/Phoenix' => '(GMT-07:00) Arizona',
'America/Regina' => '(GMT-06:00) Saskatchewan',
'America/Tegucigalpa' => '(GMT-06:00) Central America',
'America/Chicago' => '(GMT-06:00) Central Time (US &amp; Canada)',
'America/Mexico_City' => '(GMT-06:00) Mexico City',
'America/Monterrey' => '(GMT-06:00) Monterrey',
'America/New_York' => '(GMT-05:00) Eastern Time (US &amp; Canada)',
'America/Bogota' => '(GMT-05:00) Bogota',
'America/Lima' => '(GMT-05:00) Lima',
'America/Rio_Branco' => '(GMT-05:00) Rio Branco',
'Pacific/Kwajalein' => '(GMT-12:00) International Date Line West',
'Pacific/Midway' => '(GMT-11:00) Midway Island',
'Pacific/Samoa' => '(GMT-11:00) Samoa',
'Pacific/Honolulu' => '(GMT-10:00) Hawaii',
'America/Anchorage' => '(GMT-09:00) Alaska',
'America/Los_Angeles' => '(GMT-08:00) Pacific Time (US &amp; Canada)',
'America/Tijuana' => '(GMT-08:00) Tijuana, Baja California',
'America/Denver' => '(GMT-07:00) Mountain Time (US &amp; Canada)',
'America/Chihuahua' => '(GMT-07:00) Chihuahua',
'America/Mazatlan' => '(GMT-07:00) Mazatlan',
'America/Phoenix' => '(GMT-07:00) Arizona',
'America/Regina' => '(GMT-06:00) Saskatchewan',
'America/Tegucigalpa' => '(GMT-06:00) Central America',
'America/Chicago' => '(GMT-06:00) Central Time (US &amp; Canada)',
'America/Mexico_City' => '(GMT-06:00) Mexico City',
'America/Monterrey' => '(GMT-06:00) Monterrey',
'America/New_York' => '(GMT-05:00) Eastern Time (US &amp; Canada)',
'America/Bogota' => '(GMT-05:00) Bogota',
'America/Lima' => '(GMT-05:00) Lima',
'America/Rio_Branco' => '(GMT-05:00) Rio Branco',
'America/Indiana/Indianapolis' => '(GMT-05:00) Indiana (East)',
'America/Caracas' => '(GMT-04:30) Caracas',
'America/Halifax' => '(GMT-04:00) Atlantic Time (Canada)',
'America/Manaus' => '(GMT-04:00) Manaus',
'America/Santiago' => '(GMT-04:00) Santiago',
'America/La_Paz' => '(GMT-04:00) La Paz',
'America/St_Johns' => '(GMT-03:30) Newfoundland',
'America/Argentina/Buenos_Aires' => '(GMT-03:00) Georgetown',
'America/Sao_Paulo' => '(GMT-03:00) Brasilia',
'America/Godthab' => '(GMT-03:00) Greenland',
'America/Montevideo' => '(GMT-03:00) Montevideo',
'America/Caracas' => '(GMT-04:30) Caracas',
'America/Halifax' => '(GMT-04:00) Atlantic Time (Canada)',
'America/Manaus' => '(GMT-04:00) Manaus',
'America/Santiago' => '(GMT-04:00) Santiago',
'America/La_Paz' => '(GMT-04:00) La Paz',
'America/St_Johns' => '(GMT-03:30) Newfoundland',
'America/Argentina/Buenos_Aires' => '(GMT-03:00) Georgetown',
'America/Sao_Paulo' => '(GMT-03:00) Brasilia',
'America/Godthab' => '(GMT-03:00) Greenland',
'America/Montevideo' => '(GMT-03:00) Montevideo',
'Atlantic/South_Georgia' => '(GMT-02:00) Mid-Atlantic',
'Atlantic/Azores' => '(GMT-01:00) Azores',
'Atlantic/Cape_Verde' => '(GMT-01:00) Cape Verde Is.',
'Europe/Dublin' => '(GMT) Dublin',
'Europe/Lisbon' => '(GMT) Lisbon',
'Europe/London' => '(GMT) London',
'Africa/Monrovia' => '(GMT) Monrovia',
'Atlantic/Reykjavik' => '(GMT) Reykjavik',
'Africa/Casablanca' => '(GMT) Casablanca',
'Europe/Belgrade' => '(GMT+01:00) Belgrade',
'Europe/Bratislava' => '(GMT+01:00) Bratislava',
'Europe/Budapest' => '(GMT+01:00) Budapest',
'Europe/Ljubljana' => '(GMT+01:00) Ljubljana',
'Europe/Prague' => '(GMT+01:00) Prague',
'Europe/Sarajevo' => '(GMT+01:00) Sarajevo',
'Europe/Skopje' => '(GMT+01:00) Skopje',
'Europe/Warsaw' => '(GMT+01:00) Warsaw',
'Europe/Zagreb' => '(GMT+01:00) Zagreb',
'Europe/Brussels' => '(GMT+01:00) Brussels',
'Europe/Copenhagen' => '(GMT+01:00) Copenhagen',
'Europe/Madrid' => '(GMT+01:00) Madrid',
'Europe/Paris' => '(GMT+01:00) Paris',
'Africa/Algiers' => '(GMT+01:00) West Central Africa',
'Europe/Amsterdam' => '(GMT+01:00) Amsterdam',
'Europe/Berlin' => '(GMT+01:00) Berlin',
'Europe/Rome' => '(GMT+01:00) Rome',
'Europe/Stockholm' => '(GMT+01:00) Stockholm',
'Europe/Vienna' => '(GMT+01:00) Vienna',
'Europe/Minsk' => '(GMT+02:00) Minsk',
'Africa/Cairo' => '(GMT+02:00) Cairo',
'Europe/Helsinki' => '(GMT+02:00) Helsinki',
'Europe/Riga' => '(GMT+02:00) Riga',
'Europe/Sofia' => '(GMT+02:00) Sofia',
'Europe/Tallinn' => '(GMT+02:00) Tallinn',
'Europe/Vilnius' => '(GMT+02:00) Vilnius',
'Europe/Athens' => '(GMT+02:00) Athens',
'Europe/Bucharest' => '(GMT+02:00) Bucharest',
'Europe/Istanbul' => '(GMT+02:00) Istanbul',
'Asia/Jerusalem' => '(GMT+02:00) Jerusalem',
'Asia/Amman' => '(GMT+02:00) Amman',
'Asia/Beirut' => '(GMT+02:00) Beirut',
'Africa/Windhoek' => '(GMT+02:00) Windhoek',
'Africa/Harare' => '(GMT+02:00) Harare',
'Asia/Kuwait' => '(GMT+03:00) Kuwait',
'Asia/Riyadh' => '(GMT+03:00) Riyadh',
'Asia/Baghdad' => '(GMT+03:00) Baghdad',
'Africa/Nairobi' => '(GMT+03:00) Nairobi',
'Asia/Tbilisi' => '(GMT+03:00) Tbilisi',
'Europe/Moscow' => '(GMT+03:00) Moscow',
'Europe/Volgograd' => '(GMT+03:00) Volgograd',
'Asia/Tehran' => '(GMT+03:30) Tehran',
'Asia/Muscat' => '(GMT+04:00) Muscat',
'Asia/Baku' => '(GMT+04:00) Baku',
'Asia/Yerevan' => '(GMT+04:00) Yerevan',
'Asia/Yekaterinburg' => '(GMT+05:00) Ekaterinburg',
'Asia/Karachi' => '(GMT+05:00) Karachi',
'Asia/Tashkent' => '(GMT+05:00) Tashkent',
'Asia/Kolkata' => '(GMT+05:30) Calcutta',
'Asia/Colombo' => '(GMT+05:30) Sri Jayawardenepura',
'Asia/Katmandu' => '(GMT+05:45) Kathmandu',
'Asia/Dhaka' => '(GMT+06:00) Dhaka',
'Asia/Almaty' => '(GMT+06:00) Almaty',
'Asia/Novosibirsk' => '(GMT+06:00) Novosibirsk',
'Asia/Rangoon' => '(GMT+06:30) Yangon (Rangoon)',
'Asia/Krasnoyarsk' => '(GMT+07:00) Krasnoyarsk',
'Asia/Bangkok' => '(GMT+07:00) Bangkok',
'Asia/Jakarta' => '(GMT+07:00) Jakarta',
'Asia/Brunei' => '(GMT+08:00) Beijing',
'Asia/Chongqing' => '(GMT+08:00) Chongqing',
'Asia/Hong_Kong' => '(GMT+08:00) Hong Kong',
'Asia/Urumqi' => '(GMT+08:00) Urumqi',
'Asia/Irkutsk' => '(GMT+08:00) Irkutsk',
'Asia/Ulaanbaatar' => '(GMT+08:00) Ulaan Bataar',
'Asia/Kuala_Lumpur' => '(GMT+08:00) Kuala Lumpur',
'Asia/Singapore' => '(GMT+08:00) Singapore',
'Asia/Taipei' => '(GMT+08:00) Taipei',
'Australia/Perth' => '(GMT+08:00) Perth',
'Asia/Seoul' => '(GMT+09:00) Seoul',
'Asia/Tokyo' => '(GMT+09:00) Tokyo',
'Asia/Yakutsk' => '(GMT+09:00) Yakutsk',
'Australia/Darwin' => '(GMT+09:30) Darwin',
'Australia/Adelaide' => '(GMT+09:30) Adelaide',
'Australia/Canberra' => '(GMT+10:00) Canberra',
'Australia/Melbourne' => '(GMT+10:00) Melbourne',
'Australia/Sydney' => '(GMT+10:00) Sydney',
'Australia/Brisbane' => '(GMT+10:00) Brisbane',
'Australia/Hobart' => '(GMT+10:00) Hobart',
'Asia/Vladivostok' => '(GMT+10:00) Vladivostok',
'Pacific/Guam' => '(GMT+10:00) Guam',
'Pacific/Port_Moresby' => '(GMT+10:00) Port Moresby',
'Asia/Magadan' => '(GMT+11:00) Magadan',
'Pacific/Fiji' => '(GMT+12:00) Fiji',
'Asia/Kamchatka' => '(GMT+12:00) Kamchatka',
'Pacific/Auckland' => '(GMT+12:00) Auckland',
'Pacific/Tongatapu' => '(GMT+13:00) Nukualofa'
'Atlantic/Azores' => '(GMT-01:00) Azores',
'Atlantic/Cape_Verde' => '(GMT-01:00) Cape Verde Is.',
'Europe/Dublin' => '(GMT) Dublin',
'Europe/Lisbon' => '(GMT) Lisbon',
'Europe/London' => '(GMT) London',
'Africa/Monrovia' => '(GMT) Monrovia',
'Atlantic/Reykjavik' => '(GMT) Reykjavik',
'Africa/Casablanca' => '(GMT) Casablanca',
'Europe/Belgrade' => '(GMT+01:00) Belgrade',
'Europe/Bratislava' => '(GMT+01:00) Bratislava',
'Europe/Budapest' => '(GMT+01:00) Budapest',
'Europe/Ljubljana' => '(GMT+01:00) Ljubljana',
'Europe/Prague' => '(GMT+01:00) Prague',
'Europe/Sarajevo' => '(GMT+01:00) Sarajevo',
'Europe/Skopje' => '(GMT+01:00) Skopje',
'Europe/Warsaw' => '(GMT+01:00) Warsaw',
'Europe/Zagreb' => '(GMT+01:00) Zagreb',
'Europe/Brussels' => '(GMT+01:00) Brussels',
'Europe/Copenhagen' => '(GMT+01:00) Copenhagen',
'Europe/Madrid' => '(GMT+01:00) Madrid',
'Europe/Paris' => '(GMT+01:00) Paris',
'Africa/Algiers' => '(GMT+01:00) West Central Africa',
'Europe/Amsterdam' => '(GMT+01:00) Amsterdam',
'Europe/Berlin' => '(GMT+01:00) Berlin',
'Europe/Rome' => '(GMT+01:00) Rome',
'Europe/Stockholm' => '(GMT+01:00) Stockholm',
'Europe/Vienna' => '(GMT+01:00) Vienna',
'Europe/Minsk' => '(GMT+02:00) Minsk',
'Africa/Cairo' => '(GMT+02:00) Cairo',
'Europe/Helsinki' => '(GMT+02:00) Helsinki',
'Europe/Riga' => '(GMT+02:00) Riga',
'Europe/Sofia' => '(GMT+02:00) Sofia',
'Europe/Tallinn' => '(GMT+02:00) Tallinn',
'Europe/Vilnius' => '(GMT+02:00) Vilnius',
'Europe/Athens' => '(GMT+02:00) Athens',
'Europe/Bucharest' => '(GMT+02:00) Bucharest',
'Europe/Istanbul' => '(GMT+02:00) Istanbul',
'Asia/Jerusalem' => '(GMT+02:00) Jerusalem',
'Asia/Amman' => '(GMT+02:00) Amman',
'Asia/Beirut' => '(GMT+02:00) Beirut',
'Africa/Windhoek' => '(GMT+02:00) Windhoek',
'Africa/Harare' => '(GMT+02:00) Harare',
'Asia/Kuwait' => '(GMT+03:00) Kuwait',
'Asia/Riyadh' => '(GMT+03:00) Riyadh',
'Asia/Baghdad' => '(GMT+03:00) Baghdad',
'Africa/Nairobi' => '(GMT+03:00) Nairobi',
'Asia/Tbilisi' => '(GMT+03:00) Tbilisi',
'Europe/Moscow' => '(GMT+03:00) Moscow',
'Europe/Volgograd' => '(GMT+03:00) Volgograd',
'Asia/Tehran' => '(GMT+03:30) Tehran',
'Asia/Muscat' => '(GMT+04:00) Muscat',
'Asia/Baku' => '(GMT+04:00) Baku',
'Asia/Yerevan' => '(GMT+04:00) Yerevan',
'Asia/Yekaterinburg' => '(GMT+05:00) Ekaterinburg',
'Asia/Karachi' => '(GMT+05:00) Karachi',
'Asia/Tashkent' => '(GMT+05:00) Tashkent',
'Asia/Kolkata' => '(GMT+05:30) Calcutta',
'Asia/Colombo' => '(GMT+05:30) Sri Jayawardenepura',
'Asia/Katmandu' => '(GMT+05:45) Kathmandu',
'Asia/Dhaka' => '(GMT+06:00) Dhaka',
'Asia/Almaty' => '(GMT+06:00) Almaty',
'Asia/Novosibirsk' => '(GMT+06:00) Novosibirsk',
'Asia/Rangoon' => '(GMT+06:30) Yangon (Rangoon)',
'Asia/Krasnoyarsk' => '(GMT+07:00) Krasnoyarsk',
'Asia/Bangkok' => '(GMT+07:00) Bangkok',
'Asia/Jakarta' => '(GMT+07:00) Jakarta',
'Asia/Brunei' => '(GMT+08:00) Beijing',
'Asia/Chongqing' => '(GMT+08:00) Chongqing',
'Asia/Hong_Kong' => '(GMT+08:00) Hong Kong',
'Asia/Urumqi' => '(GMT+08:00) Urumqi',
'Asia/Irkutsk' => '(GMT+08:00) Irkutsk',
'Asia/Ulaanbaatar' => '(GMT+08:00) Ulaan Bataar',
'Asia/Kuala_Lumpur' => '(GMT+08:00) Kuala Lumpur',
'Asia/Singapore' => '(GMT+08:00) Singapore',
'Asia/Taipei' => '(GMT+08:00) Taipei',
'Australia/Perth' => '(GMT+08:00) Perth',
'Asia/Seoul' => '(GMT+09:00) Seoul',
'Asia/Tokyo' => '(GMT+09:00) Tokyo',
'Asia/Yakutsk' => '(GMT+09:00) Yakutsk',
'Australia/Darwin' => '(GMT+09:30) Darwin',
'Australia/Adelaide' => '(GMT+09:30) Adelaide',
'Australia/Canberra' => '(GMT+10:00) Canberra',
'Australia/Melbourne' => '(GMT+10:00) Melbourne',
'Australia/Sydney' => '(GMT+10:00) Sydney',
'Australia/Brisbane' => '(GMT+10:00) Brisbane',
'Australia/Hobart' => '(GMT+10:00) Hobart',
'Asia/Vladivostok' => '(GMT+10:00) Vladivostok',
'Pacific/Guam' => '(GMT+10:00) Guam',
'Pacific/Port_Moresby' => '(GMT+10:00) Port Moresby',
'Asia/Magadan' => '(GMT+11:00) Magadan',
'Pacific/Fiji' => '(GMT+12:00) Fiji',
'Asia/Kamchatka' => '(GMT+12:00) Kamchatka',
'Pacific/Auckland' => '(GMT+12:00) Auckland',
'Pacific/Tongatapu' => '(GMT+13:00) Nukualofa'
);
function unix_from_local($timestamp)
@ -187,101 +178,3 @@ function floor_to_day($timestamp)
{
return floor($timestamp / (60 * 60 * 24)) * (60 * 60 * 24);
}
function time_ago($timestamp, $locale)
{
if(is_numeric($timestamp))
{
if($timestamp > time())
{
$sTimeAgo = $locale->strings['event-future'];
}
elseif($timestamp == time())
{
$sTimeAgo = $locale->strings['event-now'];
}
else
{
$date1 = new DateTime("@{$timestamp}", new DateTimeZone("GMT"));
$date2 = new DateTime("now", new DateTimeZone("GMT"));
$interval = $date1->diff($date2);
$years = (int)$interval->y;
$months = (int)$interval->m;
$weeks = (int)$interval->format("%U");
$days = (int)$interval->d;
$hours = (int)$interval->h;
$minutes = (int)$interval->i;
$seconds = (int)$interval->s;
if($years > 1)
{
$sTimeAgo = sprintf($locale->strings['event-years-ago'], $years);
}
elseif($years == 1)
{
$sTimeAgo = $locale->strings['event-1year-ago'];
}
elseif($months > 1)
{
$sTimeAgo = sprintf($locale->strings['event-months-ago'], $months);
}
elseif($months == 1)
{
$sTimeAgo = $locale->strings['event-1month-ago'];
}
elseif($weeks > 1)
{
$sTimeAgo = sprintf($locale->strings['event-weeks-ago'], $weeks);
}
elseif($weeks == 1)
{
$sTimeAgo = $locale->strings['event-1week-ago'];
}
elseif($days > 1)
{
$sTimeAgo = sprintf($locale->strings['event-days-ago'], $days);
}
elseif($days == 1)
{
$sTimeAgo = $locale->strings['event-1day-ago'];
}
elseif($hours > 1)
{
$sTimeAgo = sprintf($locale->strings['event-hours-ago'], $hours);
}
elseif($hours == 1)
{
$sTimeAgo = $locale->strings['event-1hour-ago'];
}
elseif($minutes > 1)
{
$sTimeAgo = sprintf($locale->strings['event-minutes-ago'], $minutes);
}
elseif($minutes == 1)
{
$sTimeAgo = $locale->strings['event-1minute-ago'];
}
elseif($seconds > 1)
{
$sTimeAgo = sprintf($locale->strings['event-seconds-ago'], $seconds);
}
elseif($seconds == 1)
{
$sTimeAgo = $locale->strings['event-1second-ago'];
}
else
{
/* If you see this, there's probably something wrong. */
$sTimeAgo = $locale->strings['event-past'];
}
}
return $sTimeAgo;
}
else
{
throw new Exception("The given timestamp is not numeric. Timestamps must be provided in Unix timestamp format.");
}
}

@ -1,388 +0,0 @@
<?php
$cphp_debug_start = microtime(true);
$cphp_debug_log = array();
$cphp_debug_enabled = false;
function cphp_debug_enable()
{
global $cphp_debug_enabled;
$cphp_debug_enabled = true;
}
function cphp_debug_disable()
{
global $cphp_debug_enabled;
$cphp_debug_enabled = false;
}
function cphp_debug_snapshot($data)
{
global $cphp_debug_start, $cphp_debug_log, $cphp_debug_enabled;
if($cphp_debug_enabled === true)
{
$timestamp = microtime(true) - $cphp_debug_start;
$cphp_debug_log[] = array(
'timestamp' => $timestamp,
'data' => $data
);
}
}
function cphp_debug_dump()
{
global $cphp_debug_log;
return json_encode($cphp_debug_log);
}
function cphp_debug_display($data)
{
/* We can't use the templater for this, because that would make this function unusable if the
* templater itself were to ever be the subject of the debugging. */
?>
<!doctype html>
<html>
<head>
<title>CPHP Debuglog Viewer</title>
<style>
body
{
font-family: monospace;
}
#slider
{
background-color: #DDDDDD;
position: absolute;
left: 0px;
right: 0px;
top: 0px;
height: 100px;
user-select: none;
-moz-user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
}
#slider_bar
{
background-color: #C8C8C8;
height: 24px;
position: relative;
}
#slider_handle
{
width: 24px;
height: 24px;
position: absolute;
left: 0px;
top: 0px;
background-color: #6F6F6F;
cursor: pointer;
}
#slider_handle.dragging
{
background-color: #000000;
}
#datapoint_info
{
padding: 7px;
}
#details
{
position: absolute;
left: 0px;
right: 0px;
bottom: 0px;
top: 100px;
overflow: auto;
}
.variable
{
padding-left: 48px;
border-top: 1px solid silver;
}
.variable .name
{
font-size: 15px;
font-weight: bold;
margin-right: 6px;
}
.variable .data
{
font-size: 13px;
}
a.expander
{
text-decoration: none;
color: blue;
font-weight: bold;
font-size: 14px;
}
.data.undefined
{
color: silver;
}
.data.text
{
color: #A000B2;
}
.data.numeric
{
color: red;
}
</style>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<script>
var data_points = <?php echo($data); ?>;
var total_data_points = data_points.length;
var current_point = 0;
function sliderUpdate()
{
total_width = $('#slider_bar').width() - $('#slider_handle').width();
current_position = $('#slider_handle').offset().left;
point_width = total_width / (total_data_points - 1);
closest_data_point = Math.round(current_position / point_width);
current_point = closest_data_point;
real_position = closest_data_point * point_width;
$('#slider_handle').css({'left': real_position});
relevant_data_point = data_points[closest_data_point];
$('#datapoint_info').html("<strong>Data point:</strong> " + closest_data_point + "<br><strong>Timestamp:</strong> " + relevant_data_point['timestamp'])
updateTree(relevant_data_point['data']);
}
function switchDataPoint(i)
{
total_width = $('#slider_bar').width() - $('#slider_handle').width();
point_width = total_width / (total_data_points - 2);
real_position = i * point_width;
$('#slider_handle').css({'left': real_position});
current_point = i;
$('#datapoint_info').html("<strong>Data point:</strong> " + i + "<br><strong>Timestamp:</strong> " + data_points[i]['timestamp'])
updateTree(data_points[i]['data']);
}
function updateTree(data)
{
$('.variable.array').children('.variable').remove();
$('.data.text, .data.numeric').html("undefined").addClass("undefined").removeClass("text").removeClass("numeric");
updateElements(data, "root", "item");
$('a.expander').each(function(){
if($(this).text() == "[+]")
{
$(this).parent().children('.variable').hide();
}
});
hookExpanders();
}
function initializeElements()
{
/* Build a prototype for display, out of all the available datapoints. */
prototype = {};
for(x in data_points)
{
prototype = $.extend(true, prototype, data_points[x]);
}
createElements(prototype['data'], "root", "item").appendTo('#details');
}
function createElements(source, key, hierarchy)
{
var item;
var id = hierarchy + "_" + key.replace(/[^a-z0-9_]/gi,'');
if($.isArray(source))
{
/* Array. */
var me = $('<div class="variable array" id="' + id + '"><a class="expander" href="javascript:void(0);">[-]</a><span class="name">' + key + '</span><span class="data undefined">Array</span></div>');
}
else if($.isPlainObject(source))
{
/* Object. */
var me = $('<div class="variable object" id="' + id + '"><a class="expander" href="javascript:void(0);">[-]</a><span class="name">' + key + '</span><span class="data undefined">Object</span></div>');
for(item in source)
{
me.append(createElements(source[item], item, id));
}
}
else
{
/* Value. */
var me = $('<div class="variable value" id="' + id + '"><span class="name">' + key + '</span><span class="data undefined">undefined</span></div>');
}
return me;
}
function updateElements(source, key, hierarchy)
{
var item;
var id = hierarchy + "_" + key.replace(/[^a-z0-9_]/gi,'');
if($.isArray(source))
{
/* Array. */
//$('#' + id).children('.variable').remove();
for(item in source)
{
$('#' + id).append(createElements(source[item], item, id));
updateElements(source[item], item, id);
}
}
else if($.isPlainObject(source))
{
/* Object. */
for(item in source)
{
updateElements(source[item], item, id);
}
}
else
{
/* Value. */
var target = $('#' + id).children('.data');
target.html(source);
target.removeClass("undefined");
if(typeof(source) == "number")
{
target.addClass("numeric");
}
else
{
target.addClass("text");
}
}
}
function hookExpanders()
{
$('a.expander').click(function(){
if($(this).text() == "[-]")
{
/* Collapse */
$(this).text("[+]");
$(this).parent().children(".variable").hide();
}
else
{
/* Expand */
$(this).text("[-]");
$(this).parent().children(".variable").show();
}
});
}
$(function(){
var drag_start_x = 0;
var drag_start_y = 0;
var dragging_slider = false;
$('#slider_handle').mousedown(function(e){
dragging_slider = true;
parent_offset = $(this).offset();
drag_start_x = e.pageX - parent_offset.left;
$('#slider_handle').addClass("dragging");
});
$('body').mouseup(function(e){
if(dragging_slider == true)
{
dragging_slider = false;
$('#slider_handle').removeClass("dragging");
}
});
$('body').mousemove(function(e){
//$('#details').html("Dragging: "+dragging_slider+", drag_start_x: "+drag_start_x+", pageX: "+e.pageX);
if(dragging_slider == true)
{
newpos = e.pageX - drag_start_x;
if(newpos > 0 && newpos < (total_width))
{
$('#slider_handle').css({'left': newpos});
}
else if(newpos < 0)
{
$('#slider_handle').css({'left': 0});
}
else if(newpos > (total_width))
{
$('#slider_handle').css({'left': total_width});
}
sliderUpdate();
}
});
$(document).keydown(function(e){
if(e.keyCode == 37 && current_point > 0)
{
switchDataPoint(current_point - 1);
}
else if(e.keyCode == 39 && current_point < total_data_points - 2)
{
switchDataPoint(current_point + 1);
}
});
var total_width = $('#slider_bar').width() - $('#slider_handle').width();
initializeElements();
sliderUpdate();
});
</script>
</head>
<body>
<div id="slider">
<div id="slider_bar">
<div id="slider_handle"></div>
</div>
<div id="datapoint_info">
</div>
</div>
<div id="details">
</div>
</body>
</html>
<?php
}

@ -13,54 +13,11 @@
if($_CPHP !== true) { die(); }
class BaseException extends Exception
{
public function __construct($message, $code = 0, $previous = null, $data = array())
{
$this->data = $data;
parent::__construct($message, $code, $previous);
}
}
class OwnershipException extends BaseException {}
class UserAccessException extends BaseException {}
class PrototypeException extends BaseException {}
class ConstructorException extends BaseException {}
class MissingDataException extends BaseException {}
class DatabaseException extends BaseException {}
class DatabaseDuplicateException extends DatabaseException {}
class DatabaseConstraintException extends DatabaseException {}
class TypeException extends BaseException {}
class DeprecatedException extends BaseException {}
class TemplateException extends Exception
{
public $message = "";
public $file = "";
public $startpos = 0;
public $endpos = 0;
public $code = 0;
public function __construct($message, $file, $startpos, $endpos = 0, $code = "")
{
$this->message = $message;
$this->file = $file;
$this->startpos = $startpos;
$this->endpos = $endpos;
}
}
class NotFoundException extends BaseException
{
public function __construct($message, $code = 0, $previous = null, $field = "", $data = array())
{
$this->field = $field;
parent::__construct($message, $code, $previous, $data);
}
}
class TemplateSyntaxException extends TemplateException {}
class TemplateParsingException extends TemplateException {}
class TemplateEvaluationException extends BaseException {}
class OwnershipException extends Exception {}
class UserAccessException extends Exception {}
class NotFoundException extends Exception {}
class PrototypeException extends Exception {}
class ConstructorException extends Exception {}
class MissingDataException extends Exception {}
class DatabaseException extends Exception {}
class TypeException extends Exception {}

@ -1,700 +0,0 @@
<?php
/*
* CPHP is more free software. It is licensed under the WTFPL, which
* allows you to do pretty much anything with it, without having to
* ask permission. Commercial use is allowed, and no attribution is
* required. We do politely request that you share your modifications
* to benefit other developers, but you are under no enforced
* obligation to do so :)
*
* Please read the accompanying LICENSE document for the full WTFPL
* licensing text.
*/
/* TODO:
* - Freak out if there are invalid CSRF tokens.
* - Let the user choose not to have it freak out if there are invalid CSRF tokens.
*/
if($_CPHP !== true) { die(); }
class FormValidationException extends Exception {
private function DoGetOffendingKeys($exceptions)
{
$results = array();
foreach($exceptions as $exception)
{
if(isset($exception['key']))
{
$results[] = array(
"key" => $exception["key"],
"index" => isset($exception["index"]) ? $exception["index"] : 0
);
}
if(isset($exception["children"]))
{
$results = array_merge($results, $this->DoGetOffendingKeys($exception["children"]));
}
}
return $results;
}
public function __construct($message, $exceptions)
{
$this->message = $message;
$this->exceptions = $exceptions;
}
public function GetErrors()
{
/* We just need to return a flattened version of the exception list here. */
$results = array();
foreach($this->exceptions as $exception_list)
{
$results = array_merge($results, $exception_list);
}
return $results;
}
public function GetErrorMessages($custom_map = array())
{
$flattened = $this->GetErrors();
$results = array();
foreach($flattened as $exception)
{
if(!empty($custom_map) && array_key_exists($exception["error_type"], $custom_map) && array_key_exists($exception["key"], $custom_map[$exception["error_type"]]))
{
/* A custom error message was defined for this particular key/type error combination. */
$results[] = $custom_map[$exception["error_type"]][$exception["key"]];
}
else
{
/* Use default error message. */
$results[] = $exception["error_msg"];
}
}
return $results;
}
public function GetOffendingKeys()
{
$results = array();
foreach($this->exceptions as $exception_list)
{
$results = array_merge($results, $this->DoGetOffendingKeys($exception_list));
}
return $results;
}
}
class ImmediateAbort extends FormValidationException { }
class CPHPFormValidatorPromiseBaseClass
{
public $previous = null;
public $next = null;
public function __construct($creator)
{
$this->previous = $creator;
}
public function StartResolve()
{
/* Back and forth! */
if($this->previous == $this->handler)
{
$this->ContinueResolve(array());
}
else
{
$this->previous->StartResolve();
}
}
public function ContinueResolve($results)
{
$own_result = $this->Resolve($results);
if(is_null($own_result) === false)
{
$results[] = $own_result;
}
if(is_null($this->next) === false)
{
$this->next->ContinueResolve($results);
}
else
{
$this->ValidationFinished($results);
}
}
public function ValidationFinished($results)
{
if(count($results) > 0)
{
throw new FormValidationException("One or more validation steps failed.", $results);
}
}
/* Operators */
public function Either($error_message)
{
$this->next = new CPHPFormValidatorOperatorEither($this, $error_message, array_slice(func_get_args(), 1));
$this->next->handler = $this->handler;
return $this->next;
}
public function All($error_message)
{
$this->next = new CPHPFormValidatorOperatorAll($this, $error_message, array_slice(func_get_args(), 1));
$this->next->handler = $this->handler;
return $this->next;
}
public function Switch_($varname, $error_message)
{
$this->next = new CPHPFormValidatorOperatorSwitch($this, $varname, $error_message, array_slice(func_get_args(), 2));
$this->next->handler = $this->handler;
return $this->next;
}
public function Case_($value)
{
$this->next = new CPHPFormValidatorOperatorCase($this, $value, array_slice(func_get_args(), 1));
$this->next->handler = $this->handler;
return $this->next;
}
/* Special instructions */
public function AbortIfErrors()
{
$this->next = new CPHPFormValidatorAbortIfErrors($this, $this->handler);
$this->next->handler = $this->handler;
return $this->next;
}
public function Done()
{
/* Trigger validation routine */
try
{
$this->StartResolve();
}
catch (ImmediateAbort $e)
{
throw new FormValidationException("A critical validation step failed.", $e->exceptions);
}
}
/* Validators */
public function RequireKey($key, $critical = false)
{
$this->next = new CPHPFormValidatorPromise($this, $this->handler, $key, array(), "required", "A value is required for this field.", $critical, function($key, $value, $args, $handler){
return isset($handler->formdata[$key]);
});
$this->next->handler = $this->handler;
return $this->next;
}
public function RequireNonEmpty($key, $critical = false)
{
$this->next = new CPHPFormValidatorPromise($this, $this->handler, $key, array(), "required", "The value for this field must not be empty.", $critical, function($key, $value, $args, $handler){
return trim($value) !== "";
});
$this->next->handler = $this->handler;
return $this->next;
}
public function ValidateEmail($key, $critical = false)
{
$this->next = new CPHPFormValidatorPromise($this, $this->handler, $key, array(), "email", "The value is not a valid e-mail address.", $critical, function($key, $value, $args, $handler){
return filter_var($value, FILTER_VALIDATE_EMAIL) !== false;
});
$this->next->handler = $this->handler;
return $this->next;
}
public function ValidateNumeric($key, $critical = false)
{
$this->next = new CPHPFormValidatorPromise($this, $this->handler, $key, array(), "numeric", "The value is not numeric.", $critical, function($key, $value, $args, $handler){
return is_numeric($value) !== false;
});
$this->next->handler = $this->handler;
return $this->next;
}
public function ValidateUrl($key, $critical = false)
{
$this->next = new CPHPFormValidatorPromise($this, $this->handler, $key, array(), "url", "The value is not a valid URL.", $critical, function($key, $value, $args, $handler){
return filter_var($value, FILTER_VALIDATE_URL) !== false;
});
$this->next->handler = $this->handler;
return $this->next;
}
public function ValidateIp($key, $critical = false)
{
$this->next = new CPHPFormValidatorPromise($this, $this->handler, $key, array(), "ip", "The value is not a valid IP address.", $critical, function($key, $value, $args, $handler){
return filter_var($value, FILTER_VALIDATE_IP) !== false;
});
$this->next->handler = $this->handler;
return $this->next;
}
public function ValidateIpv4($key, $critical = false)
{
$this->next = new CPHPFormValidatorPromise($this, $this->handler, $key, array(), "ip4", "The value is not a valid IPv4 address.", $critical, function($key, $value, $args, $handler){
return filter_var($value, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) !== false;
});
$this->next->handler = $this->handler;
return $this->next;
}
public function ValidateIpv6($key, $critical = false)
{
$this->next = new CPHPFormValidatorPromise($this, $this->handler, $key, array(), "ip6", "The value is not a valid IPv6 address.", $critical, function($key, $value, $args, $handler){
return filter_var($value, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) !== false;
});
$this->next->handler = $this->handler;
return $this->next;
}
public function ValidatePublicIp($key, $critical = false)
{
$this->next = new CPHPFormValidatorPromise($this, $this->handler, $key, array(), "ip_public", "The value is not an IP in a publicly usable range.", $critical, function($key, $value, $args, $handler){
return filter_var($value, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) !== false;
});
$this->next->handler = $this->handler;
return $this->next;
}
public function ValidatePrivateIp($key, $critical = false)
{
$this->next = new CPHPFormValidatorPromise($this, $this->handler, $key, array(), "ip_private", "The value is not an IP in a private range.", $critical, function($key, $value, $args, $handler){
return (filter_var($value, FILTER_VALIDATE_IP, FILTER_FLAG_NO_RES_RANGE | FILTER_FLAG_NO_PRIV_RANGE) === false && filter_var($value, FILTER_VALIDATE_IP, FILTER_FLAG_NO_RES_RANGE) !== false);
});
$this->next->handler = $this->handler;
return $this->next;
}
public function ValidateRegex($key, $error_message, $pattern, $critical = false)
{
$this->next = new CPHPFormValidatorPromise($this, $this->handler, $key, array("pattern" => $pattern), "regex", $error_message, $critical, function($key, $value, $args, $handler){
return preg_match($args["pattern"], $value) === 1;
});
$this->next->handler = $this->handler;
return $this->next;
}
public function ValidateValue($key, $error_message, $values, $critical = false)
{
$this->next = new CPHPFormValidatorPromise($this, $this->handler, $key, array("values" => $values), "value", $error_message, $critical, function($key, $value, $args, $handler){
if(is_array($args["values"]))
{
return in_array($value, $args["values"]);
}
else
{
return ($args["values"] == $value);
}
});
$this->next->handler = $this->handler;
return $this->next;
}
public function ValidateCustom($key, $error_message, $validator, $critical = false)
{
$this->next = new CPHPFormValidatorPromise($this, $this->handler, $key, array(), "custom", $error_message, $critical, $validator);
$this->next->handler = $this->handler;
return $this->next;
}
}
class CPHPFormValidatorPromise extends CPHPFormValidatorPromiseBaseClass
{
public function __construct($creator, $handler, $key, $args, $error_type, $error_message, $critical, $function)
{
parent::__construct($creator);
$this->key = $key;
$this->func = $function;
$this->args = $args;
$this->error_type = $error_type;
$this->error_message = $error_message;
$this->critical = $critical;
$this->handler = $handler;
}
public function Resolve($results)
{
$func = $this->func; /* WTF PHP? Why can't I call $this->func directly? */
$exceptions = array();
$values = isset($this->handler->formdata[$this->key]) ? $this->handler->formdata[$this->key] : null;
if(is_array($values) === true)
{
/* Array */
foreach($values as $i => $value)
{
if($func($this->key, $value, $this->args, $this->handler) !== true)
{
$exceptions[] = array(
"type" => "array_value",
"key" => $this->key,
"index" => $i,
"error_type" => $this->error_type,
"error_msg" => $this->error_message
);
}
}
}
else
{
/* Single value */
if($func($this->key, $values, $this->args, $this->handler) !== true)
{
$exceptions[] = array(
"type" => "single",
"key" => $this->key,
"index" => 0,
"error_type" => $this->error_type,
"error_msg" => $this->error_message
);
}
}
if(count($exceptions) > 0 && $this->critical === true)
{
$results[] = $exceptions;
throw new ImmediateAbort("Critical validation did not pass.", $results);
}
if(count($exceptions) == 0)
{
return null;
}
else
{
return $exceptions;
}
}
}
class CPHPFormValidatorAbortIfErrors extends CPHPFormValidatorPromiseBaseClass
{
public function __construct($creator, $handler)
{
parent::__construct($creator);
$this->handler = $handler;
}
public function Resolve($exceptions)
{
if(count($exceptions) > 0)
{
throw new FormValidationException("One or more validation errors before an AbortIfErrors statement.", $exceptions);
}
else
{
return null;
}
}
}
class CPHPFormValidatorOperator extends CPHPFormValidatorPromiseBaseClass
{
public function __construct($creator, $error_message, $children)
{
parent::__construct($creator);
$this->error_message = $error_message;
$this->children = $children;
}
}
class CPHPFormValidatorOperatorEither extends CPHPFormValidatorOperator
{
public function Resolve($results)
{
$exceptions = array();
foreach($this->children as $child)
{
$result = $child->Resolve($exceptions);
if(is_null($result) === false)
{
$exceptions[] = $result;
}
}
if(count($exceptions) == count($this->children))
{
return array(array(
"type" => "operator",
"error_type" => "either",
"error_msg" => $this->error_message,
"children" => $exceptions
));
}
else
{
return null;
}
}
}
class CPHPFormValidatorOperatorAll extends CPHPFormValidatorOperator
{
public function Resolve($results)
{
$exceptions = array();
foreach($this->children as $child)
{
$result = $child->Resolve($exceptions);
if(is_null($result) === false)
{
$exceptions[] = $result;
}
}
if(count($exceptions) > 0)
{
return array(array(
"type" => "operator",
"error_type" => "both",
"error_msg" => $this->error_message,
"children" => $exceptions
));
}
else
{
return null;
}
}
}
class CPHPFormValidatorOperatorSwitch extends CPHPFormValidatorOperator
{
/* The 'case' operator has a different constructor; it needs to accept both
* an error message, and a variable to check. */
public function __construct($creator, $varname, $error_message, $children)
{
$this->varname = $varname;
parent::__construct($creator, $error_message, $children);
}
public function Resolve($results)
{
$exceptions = array();
foreach($this->children as $child)
{
/* We have to set the variable name in the child here... only at
* runtime can we establish the link between parent and child. */
$child->varname = $this->varname;
$result = $child->Resolve($exceptions);
if(is_null($result) === false)
{
$exceptions[] = $result;
}
}
if(count($exceptions) > 0)
{
return array(array(
"type" => "operator",
"error_type" => "switch",
"error_msg" => $this->error_message,
"children" => $exceptions
));
}
else
{
return null;
}
}
}
class CPHPFormValidatorOperatorCase extends CPHPFormValidatorOperator
{
/* The 'case' operator has a different constructor; instead of an error message,
* it is passed a "trigger value"; that is, the value on which it will execute. */
public function __construct($creator, $value, $children)
{
/* FIXME: Check if the parent really is a Switch operator... */
/* Grab the variable name to check from the parent. */
$this->value = $value;
parent::__construct($creator, "", $children);
}
public function Resolve($results)
{
if(in_array($this->value, $this->handler->GetValues($this->varname)))
{
$exceptions = array();
foreach($this->children as $child)
{
$result = $child->Resolve($exceptions);
if(is_null($result) === false)
{
$exceptions[] = $result;
}
}
if(count($exceptions) > 0)
{
return array(array( /* TODO: Unpack case errors upon handling? Insignificant wrapper.. */
"type" => "operator",
"error_type" => "case",
"error_msg" => "Errors occurred.",
"children" => $exceptions
));
}
else
{
return null;
}
}
else
{
/* Case didn't trigger; always treat as success in that case. */
return null;
}
}
}
class CPHPFormHandler extends CPHPFormValidatorPromiseBaseClass
{
public function __construct($formdata = null, $no_csrf = false)
{
if(is_null($formdata))
{
$this->formdata = $_POST;
}
else
{
$this->formdata = $formdata;
}
$this->no_csrf = $no_csrf;
$this->handler = $this;
$this->validation_exceptions = array();
$this->exception_buffer = array();
$this->first_validation = true;
if($no_csrf === false)
{
CSRF::VerifyToken($this->formdata);
}
}
public function StoreValidationException($exception, $validator_object)
{
if($validator_object == $this)
{
if($this->first_validation === true)
{
$this->first_validation = false;
$this->validation_exceptions[] = $exception;
}
else
{
$this->exception_buffer[] = $exception;
}
}
else
{
$this->validation_exceptions[] = $exception;
}
}
public function RaiseValidationExceptions($aborted)
{
if(count($this->validation_exceptions) > 0)
{
throw new FormValidationException("One or more validation errors occurred.", $this->validation_exceptions);
}
$this->validation_exceptions = array();
}
public function GetGroupedValues()
{
/* Returns an array of associative arrays. This is used for forms that have
* multiple array inputs, and where each input has a corresponding element
* for another input name. */
$keys = func_get_args();
$sCounts = array();
foreach($keys as $key)
{
$sCounts[] = count($this->formdata[$key]);
}
$sTotalItems = max($sCounts);
$sAllValues = array();
for($i = 0; $i < $sTotalItems; $i++)
{
$sValues = array();
foreach($keys as $key)
{
$sValues[$key] = $this->formdata[$key][$i];
}
$sAllValues[] = $sValues;
}
return $sAllValues;
}
public function GetValues($key)
{
/* Returns an array with zero or more values for the given key. If the key
* does not exist, an empty array is returned. */
if(!isset($this->formdata[$key]))
{
return array();
}
elseif(is_array($this->formdata[$key]))
{
return $this->formdata[$key];
}
else
{
return array($this->formdata[$key]);
}
}
public function GetValue($key, $default=null)
{
/* Returns a single value for the given key. If the key contains an array, it
* will return the first element. If the key does not exist, it will return null. */
if(!isset($this->formdata[$key]))
{
return $default;
}
elseif(is_array($this->formdata[$key]))
{
return $this->formdata[$key][0];
}
else
{
return $this->formdata[$key];
}
}
}

@ -1,99 +0,0 @@
<?php
/*
* CPHP is more free software. It is licensed under the WTFPL, which
* allows you to do pretty much anything with it, without having to
* ask permission. Commercial use is allowed, and no attribution is
* required. We do politely request that you share your modifications
* to benefit other developers, but you are under no enforced
* obligation to do so :)
*
* Please read the accompanying LICENSE document for the full WTFPL
* licensing text.
*/
if($_CPHP !== true) { die(); }
if(!isset($cphp_config->libraries))
{
/* No library configuration has been specified. We don't need to
* execute the rest of this file. */
return;
}
/* Some libraries want to have a cache directory. Instead of storing all
* this stuff in the document root, we'll put it into /tmp (or any other
* config-specified directory). We should probably make sure the needed
* directories exist, though... */
$tmp_dir = (isset($cphp_config->tmp_dir)) ? $cphp_config->tmp_dir : "/tmp";
if(!file_exists("{$tmp_dir}/cphp"))
{
mkdir("{$tmp_dir}/cphp", 0700);
}
if(!file_exists("{$tmp_dir}/cphp/cache"))
{
mkdir("{$tmp_dir}/cphp/cache", 0700);
}
/* We'll set up HTMLPurifier here if so desired. */
if(isset($cphp_config->libraries->htmlpurifier))
{
if(!is_dir("{$tmp_dir}/cphp/cache/htmlpurifier"))
{
mkdir("{$tmp_dir}/cphp/cache/htmlpurifier", 0700);
}
$library_config = $cphp_config->libraries->htmlpurifier;
$library_path = (isset($library_config->path)) ? $library_config->path : "lib/htmlpurifier/HTMLPurifier.auto.php";
require_once($library_path);
$purifier_config = HTMLPurifier_Config::createDefault();
if(isset($library_config->doctype))
{
$purifier_config->set("HTML.Doctype", $library_config->doctype);
}
if(isset($library_config->encoding))
{
$purifier_config->set("Core.Encoding", $library_config->encoding);
}
$purifier_config->set("Cache.SerializerPath", "{$tmp_dir}/cphp/cache/htmlpurifier");
$cphp_purifier = new HTMLPurifier($purifier_config);
$cphp_hash_purifier_config = md5(serialize($purifier_config));
function purify_html($input, $cache_duration = 3600, $config = null)
{
if(isset($config))
{
$config->set("Cache.SerializerPath", "{$tmp_dir}/cphp/cache/htmlpurifier");
$cphp_purifier = new HTMLPurifier($config);
$hash_config = md5(serialize($config));
}
else
{
global $cphp_purifier;
global $cphp_hash_purifier_config;
$hash_config = $cphp_hash_purifier_config;
}
$hash_input = md5($input) . md5($input . "x");
$memcache_key = "purify_{$hash_config}_{$hash_input}";
if($result = mc_get($memcache_key))
{
return $result;
}
else
{
$result = $cphp_purifier->purify($input);
mc_set($memcache_key, $result, $cache_duration);
return $result;
}
}
}

@ -13,10 +13,10 @@
if($_CPHP !== true) { die(); }
if(!empty($cphp_config->memcache->enabled))
if($cphp_memcache_enabled)
{
$cphp_memcache = new Memcache;
$cphp_memcache_established = @$cphp_memcache->connect($cphp_config->memcache->hostname, $cphp_config->memcache->port);
$memcache = new Memcache;
$cphp_memcache_established = $memcache->connect($cphp_memcache_server, $cphp_memcache_port);
if($cphp_memcache_established !== false)
{
@ -30,16 +30,15 @@ if(!empty($cphp_config->memcache->enabled))
function mc_get($key)
{
global $cphp_config, $cphp_memcache_connected, $cphp_memcache;
global $cphp_memcache_enabled, $cphp_memcache_connected, $memcache;
if(empty($cphp_config->memcache->enabled) || $cphp_memcache_connected === false)
if($cphp_memcache_enabled === false || $cphp_memcache_connected === false)
{
return false;
}
else
{
$get_result = $cphp_memcache->get($key);
$get_result = $memcache->get($key);
if($get_result !== false)
{
return $get_result;
@ -53,15 +52,15 @@ function mc_get($key)
function mc_set($key, $value, $expiry)
{
global $cphp_config, $cphp_memcache_connected, $cphp_memcache;
global $cphp_memcache_enabled, $cphp_memcache_connected, $cphp_memcache_compressed, $memcache;
if(empty($cphp_config->memcache->enabled) || $cphp_memcache_connected === false)
if($cphp_memcache_enabled === false || $cphp_memcache_connected === false)
{
return false;
}
else
{
if(!empty($cphp_config->memcache->compressed) === true)
if($cphp_memcache_compressed === true)
{
$flag = MEMCACHE_COMPRESSED;
}
@ -70,29 +69,66 @@ function mc_set($key, $value, $expiry)
$flag = false;
}
$set_result = $cphp_memcache->set($key, $value, $flag, $expiry);
$set_result = $memcache->set($key, $value, $flag, $expiry);
return $set_result;
}
}
function mc_delete($key)
{
global $cphp_config, $cphp_memcache_connected, $cphp_memcache;
global $cphp_memcache_enabled, $cphp_memcache_connected, $memcache;
if(empty($cphp_config->memcache->enabled) || $cphp_memcache_connected === false)
if($cphp_memcache_enabled === false || $cphp_memcache_connected === false)
{
return false;
}
else
{
$delete_result = $cphp_memcache->delete($key);
return $delete_result;
return $memcache->delete($key);
}
}
function mysql_query_cached($query, $expiry = 60, $key = "", $exec = false)
function mysql_query_cached($query, $expiry = 60, $key = "")
{
throw new DeprecatedException("All mysql_* functionality in CPHP has been removed. Use CachedPDO syntax instead.");
if($key == "")
{
$key = md5($query) . md5($query . "x");
}
if($res = mc_get($key))
{
$return_object->source = "memcache";
$return_object->data = $res;
return $return_object;
}
else
{
if($res = mysql_query($query))
{
$found = false;
while($row = mysql_fetch_assoc($res))
{
$return_object->data[] = $row;
$found = true;
}
if($found === true)
{
$return_object->source = "database";
mc_set($key, $return_object->data, $expiry);
return $return_object;
}
else
{
return false;
}
}
else
{
return false;
}
}
}
function file_get_contents_cached($path, $expiry = 3600)

@ -13,79 +13,14 @@
if($_CPHP !== true) { die(); }
function random_string($length, $insecure = false)
function random_string($length)
{
/* This was changed to return cryptographically secure
* random strings by default. The $insecure parameter
* can be used to indicate that cryptographically insecure
* (but faster) random data is desired. Note that, absent
* a source for cryptographically secure random data,
* this function will raise an exception. */
$required_bytes = ceil($length / 4) * 3; /* Accounting for base64 overhead */
$bytes = random_bytes($required_bytes, $insecure);
/* Since we want a string, we will base64-encode the
* resulting bytes, and then replace + and / with - and _
* respectively. We'll also cut down on the amount of
* bytes - since we're requesting bytes in chunks of 4,
* we might have a few too many. */
return substr(str_replace("+", "-", str_replace("/", "_", base64_encode($bytes))), 0, $length);
}
function random_bytes($length, $insecure = false)
{
if($insecure === true)
{
$output = "";
for ($i = 0; $i < $length; $i++)
{
$output .= chr(mt_rand(0, 255));
}
return $output;
}
else
{
$success = false;
/* Prefer /dev/urandom if it is available. */
if(file_exists("/dev/urandom"))
{
$handle = fopen("/dev/urandom", "r");
$bytes = fread($handle, $length);
$success = true;
}
/* Fall back to openssl_random_pseudo_bytes if it is available. */
if($success === false && function_exists("openssl_random_pseudo_bytes"))
{
$crypto_secure = false;
$bytes = openssl_random_pseudo_bytes($length, $crypto_secure);
if($crypto_secure === true)
{
$success = true;
}
}
/* If we also don't have that, let's try mcrypt_create_iv... but only if
* we are running on PHP 5.3, since it behaves unpredictably on
* Windows in lower versions. */
if($success === false && function_exists("mcrypt_create_iv") && version_compare(phpversion(), "5.3", ">="))
{
$bytes = mcrypt_create_iv($length, MCRYPT_DEV_URANDOM);
$success = true;
}
/* There are no secure random data sources available. Fix your
* system! */
if($success === false)
{
throw new Exception("No secure sources for random bytes found. Install the OpenSSL or mcrypt extension.");
}
return $bytes;
$output = "";
for ($i = 0; $i < $length; $i++)
{
$output .= substr("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", mt_rand(0, 61), 1);
}
return $output;
}
function extract_globals()
@ -179,293 +114,7 @@ function pretty_dump($input)
echo($output);
}
function rgb_from_hex($hex)
{
if(strlen($hex) == 6)
{
$r = substr($hex, 0, 2);
$g = substr($hex, 2, 2);
$b = substr($hex, 4, 2);
$rgb['r'] = base_convert($r, 16, 10);
$rgb['g'] = base_convert($g, 16, 10);
$rgb['b'] = base_convert($b, 16, 10);
return $rgb;
}
else
{
return false;
}
}
function hex_from_rgb($rgb)
{
if(!empty($rgb['r']) && !empty($rgb['g']) && !empty($rgb['b']))
{
return base_convert($rgb['r'], 10, 16) . base_convert($rgb['g'], 10, 16) . base_convert($rgb['b'], 10, 16);
}
else
{
return false;
}
}
function strip_tags_attr($string, $allowtags = NULL, $allowattributes = NULL)
{
/* Thanks to nauthiz693@gmail.com (http://www.php.net/manual/en/function.strip-tags.php#91498) */
$string = strip_tags($string,$allowtags);
if (!is_null($allowattributes))
{
if(!is_array($allowattributes))
{
$allowattributes = explode(",",$allowattributes);
}
if(is_array($allowattributes))
{
$allowattributes = implode(")(?<!",$allowattributes);
}
if (strlen($allowattributes) > 0)
{
$allowattributes = "(?<!".$allowattributes.")";
}
$string = preg_replace_callback("/<[^>]*>/i",create_function('$matches', 'return preg_replace("/ [^ =]*'.$allowattributes.'=(\"[^\"]*\"|\'[^\']*\')/i", "", $matches[0]);'),$string);
}
return $string;
}
function cut_text($input, $length)
{
if(strlen($input) > $length)
{
if(preg_match("/^(.{0,{$length}})\W/s", $input, $matches))
{
return $matches[1] . "...";
}
else
{
return "";
}
}
else
{
return $input;
}
}
function filter_html($input)
{
return strip_tags_attr($input, "<a><b><i><u><span><div><p><img><br><hr><font><ul><li><ol><dt><dd><h1><h2><h3><h4><h5><h6><h7><del><map><area><strong><em><big><small><sub><sup><ins><pre><blockquote><cite><q><center><marquee><table><tr><td><th>", "href,src,alt,class,style,align,valign,color,face,size,width,height,shape,coords,target,border,cellpadding,cellspacing,colspan,rowspan");
}
function filter_html_strict($input)
{
return strip_tags_attr($input, "<strong><em><br><hr><img><a><span><p><div>", "src,href,style");
}
function parse_rss($url)
{
$rss = new DOMDocument();
$rss->load($url);
$items = array();
foreach($rss->getElementsByTagName('item') as $item)
{
$items[] = array(
'title' => $item->getElementsByTagName('title')->item(0)->nodeValue,
'description' => $item->getElementsByTagName('description')->item(0)->nodeValue,
'url' => $item->getElementsByTagName('link')->item(0)->nodeValue,
'date' => strtotime($item->getElementsByTagName('pubDate')->item(0)->nodeValue)
);
}
return $items;
}
function fix_utf8($input)
{
return utf8_encode(utf8_decode($input));
}
function generate_pagination($min, $max, $current, $around, $start, $end)
{
/* Generates an array with pages that should be shown in a pagination bar.
* $min The first page number (this will usually be 1).
* $max The last page number (this is usually the total amount of pages).
* $current The page the user is currently on.
* $around The amount of pages that should at least be shown around the current page.
* $start The amount of pages that should at least be shown at the start.
* $end The amount of pages that should at least be shown at the end.
*
* Returns:
* Array, containing integers (for the pages) and null objects (for the boundaries). */
if($max < ($start + $end + ($around * 2) + 1))
{
/* There are less pages than there would be elements. */
$return_array = array();
for($i = 1; $i <= $max; $i++)
{
$return_array[] = $i;
}
return $return_array;
}
else
{
/* Calculation time... */
$return_array = array();
/* Start with the left segment. */
for($i = 1; $i <= $start; $i++)
{
$return_array[] = $i;
}
/* Now the middle segment. */
if($start + $around >= $current - 1)
{
$left_start = $i;
}
else
{
$return_array[] = null;
$left_start = $current - $around;
}
for($i = $left_start; $i <= $current + $around; $i++)
{
if($i >= $max)
{
break;
}
$return_array[] = $i;
}
/* And finally the right segment. */
if($max - ($end + $around) <= $current + 1)
{
$right_start = $i;
}
else
{
$return_array[] = null;
$right_start = $max - $end;
}
for($i = $right_start; $i <= $max; $i++)
{
$return_array[] = $i;
}
/* All done! */
return $return_array;
}
}
function starts_with($haystack, $needle)
{
return (substr($haystack, 0, strlen($needle)) == $needle);
}
function ends_with($haystack, $needle)
{
return (substr($haystack, -strlen($needle)) == $needle);
}
function redirect($target)
{
header("Location: {$target}");
die();
}
function ceil_precision($value, $precision = 0)
{
$multiplier = pow(10, $precision);
return ceil($value * $multiplier) / $multiplier;
}
function str_lreplace($search, $replace, $subject)
{
$pos = strrpos($subject, $search);
if($pos !== false)
{
$subject = substr_replace($subject, $replace, $pos, strlen($search));
}
return $subject;
}
function http_status_code($code)
/*function is_empty($variable)
{
$codes = array(
100 => "Continue",
101 => "Switching Protocols",
200 => "OK",
201 => "Created",
202 => "Accepted",
203 => "Non-Authoritative Information",
204 => "No Content",
205 => "Reset Content",
206 => "Partial Content",
300 => "Multiple Choices",
301 => "Moved Permanently",
302 => "Moved Temporarily",
303 => "See Other",
304 => "Not Modified",
305 => "Use Proxy",
400 => "Bad Request",
401 => "Unauthorized",
402 => "Payment Required",
403 => "Forbidden",
404 => "Not Found",
405 => "Method Not Allowed",
406 => "Not Acceptable",
407 => "Proxy Authentication Required",
408 => "Request Time-out",
409 => "Conflict",
410 => "Gone",
411 => "Length Required",
412 => "Precondition Failed",
413 => "Request Entity Too Large",
414 => "Request-URI Too Large",
415 => "Unsupported Media Type",
418 => "I'm a teapot",
422 => "Unprocessable Entity",
500 => "Internal Server Error",
501 => "Not Implemented",
502 => "Bad Gateway",
503 => "Service Unavailable",
504 => "Gateway Time-out",
505 => "HTTP Version not supported",
);
if(array_key_exists($code, $codes))
{
$text = $codes[$code];
}
else
{
throw new Exception("The specified HTTP status code does not exist.");
}
if(strpos(php_sapi_name(), "cgi") !== false)
{
header("Status: {$code} {$text}");
}
else
{
$protocol = (isset($_SERVER['SERVER_PROTOCOL']) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0');
header("{$protocol} {$code} {$text}");
}
}
return (trim($variable) == "");
}*/

@ -15,161 +15,13 @@ if($_CPHP !== true) { die(); }
$cphp_mysql_connected = false;
class CachedPDO extends PDO
if($cphp_mysql_enabled === true)
{
public function CachedQuery($query, $parameters = array(), $expiry = 60)
if(mysql_connect($cphp_mysql_host, $cphp_mysql_user, $cphp_mysql_pass))
{
/* TODO: Do type guessing before checking cache, so as to avoid
* different parameter hashes depending on input type for
* numbers. */
$query_hash = md5($query);
$parameter_hash = md5(serialize($parameters));
$cache_hash = $query_hash . $parameter_hash;
$return_object = new stdClass;
if($expiry != 0 && $result = mc_get($cache_hash))
{
$return_object->source = "memcache";
$return_object->data = $result;
}
else
{
$statement = $this->prepare($query);
if(count($parameters) > 0)
{
foreach($parameters as $key => $value)
{
$type = $this->GuessType($value);
if(preg_match("/^[0-9]+$/", $value) && is_string($value))
{
/* PDO library apparently thinks it's part of a strongly typed language and doesn't do any typecasting.
* We'll do it ourselves then. */
$int_value = (int) $value;
if($int_value < PHP_INT_MAX)
{
/* We only want to cast to integer if the result doesn't exceed INT_MAX, to avoid overflows. The
* only way to do this appears to be aborting when it *equals* or exceeds INT_MAX, as an overflow
* would occur during this check also. */
$value = $int_value;
$type = PDO::PARAM_INT;
}
}
if($type == PDO::PARAM_STR)
{
$value = strval($value);
}
$statement->bindValue($key, $value, $type);
}
}
if($statement->execute() === true)
{
if($result = $statement->fetchAll(PDO::FETCH_ASSOC))
{
if(count($result) > 0)
{
if($expiry != 0)
{
mc_set($cache_hash, $result, $expiry);
}
$return_object->source = "database";
$return_object->data = $result;
}
else
{
return false;
}
}
else
{
$last_id = $this->lastInsertId();
if($last_id == "0" || !starts_with(strtoupper($query), "INSERT"))
{
/* There were zero results. Return null instead of an object without results, to allow for statements
* of the form if($result = $database->CachedQuery()) . */
return null;
}
else
{
/* This was an INSERT query. Return the primary ID of the created row. */
return $last_id;
}
}
}
else
{
/* The query failed. */
$err = $statement->errorInfo();
if($err[0] == "23000")
{
if(starts_with($err[2], "Duplicate entry")) /* There does not seem to be a better way of doing this. */
{
throw new DatabaseDuplicateException("The query failed because one of the keys was not unique: {$err[2]}", 0, null, array('query' => $query, 'parameters' => $parameters));
}
else
{
throw new DatabaseConstraintException("The query violates a database constraint: {$err[2]}", 0, null, array('query' => $query, 'parameters' => $parameters));
}
}
else
{
throw new DatabaseException("The query failed: {$err[2]}", 0, null, array('query' => $query, 'parameters' => $parameters));
}
}
}
return $return_object;
}
public function GuessType($value)
{
if(is_object($value))
{
throw new DatabaseException("Query parameters must be numeric, boolean, null, a string value, or something that can be auto-cast to a string. You provided an object.");
}
if(is_int($value))
{
return PDO::PARAM_INT;
}
elseif(is_bool($value))
{
return PDO::PARAM_BOOL;
}
elseif(is_null($value))
{
return PDO::PARAM_NULL;
}
else
if(mysql_select_db($cphp_mysql_db))
{
return PDO::PARAM_STR;
$cphp_mysql_connected = true;
}
}
}
if(!empty($cphp_config->database->driver))
{
if(empty($cphp_config->database->database))
{
die("No database was configured. Refer to the CPHP manual for instructions.");
}
try
{
$database = new CachedPDO("mysql:host={$cphp_config->database->hostname};dbname={$cphp_config->database->database}", $cphp_config->database->username, $cphp_config->database->password);
$database->setAttribute(PDO::ATTR_ORACLE_NULLS, PDO::NULL_TO_STRING);
$cphp_mysql_connected = true;
}
catch (Exception $e)
{
die("Could not connect to the specified database. Refer to the CPHP manual for instructions.");
}
}

Loading…
Cancel
Save