diff --git a/frontend/cphp/.gitignore b/frontend/cphp/.gitignore new file mode 100644 index 0000000..962a88e --- /dev/null +++ b/frontend/cphp/.gitignore @@ -0,0 +1 @@ +config.mysql.php diff --git a/frontend/cphp/LICENSE b/frontend/cphp/LICENSE new file mode 100644 index 0000000..5a8e332 --- /dev/null +++ b/frontend/cphp/LICENSE @@ -0,0 +1,14 @@ + DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE + Version 2, December 2004 + + Copyright (C) 2004 Sam Hocevar + + Everyone is permitted to copy and distribute verbatim or modified + copies of this license document, and changing it is allowed as long + as the name is changed. + + DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. You just DO WHAT THE FUCK YOU WANT TO. + diff --git a/frontend/cphp/base.php b/frontend/cphp/base.php new file mode 100644 index 0000000..9dd7062 --- /dev/null +++ b/frontend/cphp/base.php @@ -0,0 +1,41 @@ +Load($cphp_locale_name); + +setlocale(LC_ALL, $locale->locale); + +require("class.base.php"); +require("class.databaserecord.php"); + +foreach($cphp_components as $component) +{ + require("components/component.{$component}.php"); +} diff --git a/frontend/cphp/class.base.php b/frontend/cphp/class.base.php new file mode 100644 index 0000000..fe58777 --- /dev/null +++ b/frontend/cphp/class.base.php @@ -0,0 +1,154 @@ +$variable_name) && is_numeric($this->$variable_name)) + { + $timestamp = $this->$variable_name; + + 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->format("%G"); + $months = (int)$interval->format("%m"); + $weeks = (int)$interval->format("%U"); + $days = (int)$interval->format("%d"); + $hours = (int)$interval->format("%H"); + $minutes = (int)$interval->format("%i"); + $seconds = (int)$interval->format("%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']; + } + + } + + $sDate = local_from_unix($timestamp, $locale->datetime_long); + + return $this->RenderTemplateExternal($template, array( + 'local-time' => $sDate, + 'time-ago' => $sTimeAgo, + 'timestamp' => $timestamp + )); + } + else + { + $classname = get_class($this); + throw new Exception("Property {$classname}.{$property} does not exist or is not of a valid format."); + } + } + + public function RenderTemplateExternal($template, $strings) + { + return $this->DoRenderTemplate($template, $strings); + } + + public function DoRenderTemplate($template, $strings) + { + global $locale; + + try + { + $tpl = new Templater(); + $tpl->Load($template); + $tpl->Localize($locale->strings); + $tpl->Compile($strings); + return $tpl->Render(); + } + catch(Exception $e) + { + $classname = get_class($this); + throw new Exception("Failed to render template {$classname}.{$template}."); + } + } +} diff --git a/frontend/cphp/class.databaserecord.php b/frontend/cphp/class.databaserecord.php new file mode 100644 index 0000000..c9ae522 --- /dev/null +++ b/frontend/cphp/class.databaserecord.php @@ -0,0 +1,397 @@ +ConstructDataset($uDataSource, $uCommunityId); + } + + public function ConstructDataset($uDataSource, $uCommunityId = 0) + { + $bind_datasets = true; + + if(is_numeric($uDataSource)) + { + if($uDataSource != 0) + { + if(!empty($this->fill_query)) + { + $this->sId = (is_numeric($uDataSource)) ? $uDataSource : 0; + + $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."); + } + } + else + { + $classname = get_class($this); + throw new PrototypeException("No fill query defined for {$classname} class."); + } + } + else + { + $bind_datasets = false; + } + } + 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 + { + $classname = get_class($this); + throw new ConstructorException("Invalid type passed on to constructor for object of type {$classname}."); + } + + if($bind_datasets === true) + { + $this->sId = (is_numeric($uDataSource['Id'])) ? $uDataSource['Id'] : 0; + + $this->uData = $uDataSource; + + foreach($this->prototype as $type => $dataset) + { + $this->BindDataset($type, $dataset); + } + + $this->sFound = true; + } + else + { + $this->sFound = false; + } + + if(!empty($uCommunityId) && !empty($this->sCommunityId)) + { + $sCommunityId = (is_numeric($uCommunityId)) ? $uCommunityId : 0; + + if($sCommunityId != $this->sCommunity->sId) + { + $classname = get_class($this); + throw new OwnershipException("{$classname} {$this->sId} does not belong to Community {$sCommunityId}."); + } + } + } + + public function BindDataset($type, $dataset) + { + global $cphp_class_map; + + if(is_array($dataset)) + { + foreach($dataset as $variable_name => $column_name) + { + $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) + { + if($type == $class_type) + { + $value = new $class_name($original_value); + $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; + } + + $variable_name_unsafe = "u" . $variable_name; + $this->$variable_name_unsafe = $original_value; + } + } + else + { + $classname = get_class($this); + throw new Exception("Invalid dataset passed on to {$classname}.BindDataset."); + } + } + + public function DoRenderInternalTemplate() + { + if(!empty($this->render_template)) + { + $strings = array(); + foreach($this->prototype_render as $template_var => $object_var) + { + $variable_name = "s" . $object_var; + $strings[$template_var] = $this->$variable_name; + } + return $this->DoRenderTemplate($this->render_template, $strings); + } + else + { + $classname = get_class($this); + throw new Exception("Cannot render template: no template defined for {$classname} class."); + } + } + + public function InsertIntoDatabase() + { + if(!empty($this->verify_query)) + { + if($this->sId == 0) + { + $insert_mode = CPHP_INSERTMODE_INSERT; + } + else + { + $query = sprintf($this->verify_query, $this->sId); + if($result = mysql_query_cached($query)) + { + $insert_mode = CPHP_INSERTMODE_UPDATE; + } + else + { + $insert_mode = CPHP_INSERTMODE_INSERT; + } + } + + $element_list = array(); + + foreach($this->prototype as $type_key => $type_value) + { + foreach($type_value as $element_key => $element_value) + { + switch($type_key) + { + case "none": + case "numeric": + case "boolean": + case "timestamp": + case "string": + $element_list[$element_value] = array( + 'key' => $element_key, + 'type' => $type_key + ); + break; + default: + break; + } + } + } + + $sKeyList = array(); + $sValueList = array(); + + foreach($element_list as $sKey => $value) + { + $variable_name_safe = "s" . $value['key']; + $variable_name_unsafe = "u" . $value['key']; + + if(isset($this->$variable_name_safe) || isset($this->$variable_name_unsafe)) + { + switch($value['type']) + { + case "none": + $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; + $sFinalValue = (is_numeric($number)) ? $number : 0; + break; + case "boolean": + $bool = (isset($this->$variable_name_unsafe)) ? $this->$variable_name_unsafe : $this->$variable_name_safe; + $sFinalValue = ($bool) ? "1" : "0"; + break; + case "timestamp": + $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": + $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": + $sFinalValue = mysql_real_escape_string($this->$variable_name_unsafe); + break; + } + + $sFinalValue = "'{$sFinalValue}'"; + $sKey = "`{$sKey}`"; + + $sKeyList[] = $sKey; + $sValueList[] = $sFinalValue; + } + else + { + $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) + { + $sQueryKeys = implode(", ", $sKeyList); + $sQueryValues = implode(", ", $sValueList); + $query = "INSERT INTO {$this->table_name} ({$sQueryKeys}) VALUES ({$sQueryValues})"; + } + elseif($insert_mode == CPHP_INSERTMODE_UPDATE) + { + $sKeyValueList = array(); + + for($i = 0; $i < count($sKeyList); $i++) + { + $sKey = $sKeyList[$i]; + $sValue = $sValueList[$i]; + $sKeyValueList[] = "{$sKey} = {$sValue}"; + } + + $sQueryKeysValues = implode(", ", $sKeyValueList); + $query = "UPDATE {$this->table_name} SET {$sQueryKeysValues} WHERE `Id` = '{$this->sId}'"; + } + + if($result = mysql_query($query)) + { + if($insert_mode == CPHP_INSERTMODE_INSERT) + { + $this->sId = mysql_insert_id(); + } + + return $result; + } + else + { + $classname = get_class($this); + throw new DatabaseException("Database insertion query failed in object of type {$classname}. Error message: " . mysql_error()); + } + } + else + { + $classname = get_class($this); + throw new Exception("No verification query defined for {$classname} class."); + } + } + + public function RetrieveChildren($type, $field) + { + 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_class_map[$type]); + if($parent_type !== "CPHPDatabaseRecordClass") + { + $parent_type = ($parent_type === false) ? "NONE" : $parent_type; + $classname = get_class($this); + throw new TypeException("{$classname}.RetrieveChildren expected 'type' argument of parent-type CPHPDatabaseRecordClass, but got {$parent_type} instead."); + } + + $query = ""; + } + + public function PurgeCache() + { + $query = sprintf($this->fill_query, $this->sId); + $key = md5($query) . md5($query . "x"); + mc_delete($key); + } + + public function RenderTemplate($template = "") + { + if(!empty($template)) + { + $this->render_template = $template; + } + + return $this->DoRenderInternalTemplate(); + } +} diff --git a/frontend/cphp/class.localizer.php b/frontend/cphp/class.localizer.php new file mode 100644 index 0000000..1c4465d --- /dev/null +++ b/frontend/cphp/class.localizer.php @@ -0,0 +1,79 @@ +strings = array(); + $this->LoadInternal("english"); + $this->LoadInternal($locale); + } + + public function LoadInternal($locale) + { + 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); + foreach($lines as $line) + { + $line = str_replace("\r", "", $line); + if(preg_match("/(.+?[^\\\]);(.+)/", $line, $matches)) + { + $key = trim(str_replace("\;", ";", $matches[1])); + $value = trim(str_replace("\;", ";", $matches[2])); + switch($key) + { + case "_locale": + $this->locale = explode(",", $value); + break; + case "_datetime_short": + $this->datetime_short = $value; + break; + case "_datetime_long": + $this->datetime_long = $value; + break; + case "_date_short": + $this->date_short = $value; + break; + case "_date_long": + $this->date_long = $value; + break; + case "_time": + $this->time = $value; + break; + default: + $this->strings[$key] = $value; + break; + } + } + } + } + else + { + Throw new Exception("Failed to load locale {$locale}."); + } + } +} diff --git a/frontend/cphp/class.templater.php b/frontend/cphp/class.templater.php new file mode 100644 index 0000000..f67a794 --- /dev/null +++ b/frontend/cphp/class.templater.php @@ -0,0 +1,123 @@ +basedir . $template . $this->extension); + $template_cache[$template] = $tpl_contents; + } + + if($tpl_contents !== false) + { + $this->tpl = $tpl_contents; + $this->tpl_rendered = $tpl_contents; + } + else + { + Throw new Exception("Failed to load template {$template}."); + } + } + + public function Reset() + { + if(!is_null($this->tpl)) + { + $this->tpl_rendered = $this->tpl; + } + else + { + Throw new Exception("No template loaded."); + } + } + + public function Localize($strings) + { + if(!is_null($this->tpl)) + { + preg_match_all("/<%!([a-zA-Z0-9_-]+)>/", $this->tpl_rendered, $strlist); + foreach($strlist[1] as $str) + { + if(isset($strings[$str])) + { + $this->tpl_rendered = str_replace("<%!{$str}>", $strings[$str], $this->tpl_rendered); + } + } + } + else + { + Throw new Exception("No template loaded."); + } + } + + public function Compile($strings) + { + if(!is_null($this->tpl)) + { + preg_match_all("/<%\?([a-zA-Z0-9_-]+)>/", $this->tpl_rendered, $strlist); + foreach($strlist[1] as $str) + { + if(isset($strings[$str])) + { + $this->tpl_rendered = str_replace("<%?{$str}>", $strings[$str], $this->tpl_rendered); + } + } + } + else + { + Throw new Exception("No template loaded."); + } + } + + public function Render() + { + if(!is_null($this->tpl)) + { + return $this->tpl_rendered; + } + else + { + Throw new Exception("No template loaded."); + } + } + + public function Output() + { + if(!is_null($this->tpl)) + { + echo($this->tpl_rendered); + } + else + { + Throw new Exception("No template loaded."); + } + } +} diff --git a/frontend/cphp/components/component.errorhandler.php b/frontend/cphp/components/component.errorhandler.php new file mode 100644 index 0000000..7a53977 --- /dev/null +++ b/frontend/cphp/components/component.errorhandler.php @@ -0,0 +1,72 @@ +sErrorType = $type; + $this->sLogError = $log; + $this->sTitle = $title; + $this->sMessage = $message; + } + + public function LogError($context, $message) + { + // FIXME placeholder function, error logging has not been implemented yet + } + + public function Render() + { + global $locale; + + $template['error'] = new Templater(); + + switch($this->sErrorType) + { + case CPHP_ERRORHANDLER_TYPE_ERROR: + $template['error']->Load("errorhandler.error"); + break; + case CPHP_ERRORHANDLER_TYPE_INFO: + $template['error']->Load("errorhandler.info"); + break; + case CPHP_ERRORHANDLER_TYPE_WARNING: + $template['error']->Load("errorhandler.warning"); + break; + case CPHP_ERRORHANDLER_TYPE_SUCCESS: + $template['error']->Load("errorhandler.success"); + break; + } + + $template['error']->Localize($locale->strings); + $template['error']->Compile(array( + 'title' => $this->sTitle, + 'message' => $this->sMessage + )); + + return $template['error']->Render(); + } +} +?> diff --git a/frontend/cphp/components/component.formbuilder.php b/frontend/cphp/components/component.formbuilder.php new file mode 100644 index 0000000..d3b8d5a --- /dev/null +++ b/frontend/cphp/components/component.formbuilder.php @@ -0,0 +1,319 @@ +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 "
{$this->note}
"; + } + 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 "{$rendered_elements}"; + } +} + +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 = "{$this->label}"; + } + 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 "{$legend}
{$rendered_elements}
"; + } + else + { + return "
{$rendered_elements}
"; + } + } +} + +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 "
{$this->label}{$rendered_note}
"; + } +} + +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 "
{$this->label}{$rendered_note}
{$rendered_elements}
"; + } +} + +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 "
"; + } +} + +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 "
{$this->label}
"; + } +} + +class CPHPFormSubmitButton extends CPHPFormButton +{ + public $type = "submit"; +} + +class CPHPFormResetButton extends CPHPFormButton +{ + public $type = "reset"; +} + +class CPHPFormSelect extends CPHPFormInputElement +{ + public $options = array(); +} +?> diff --git a/frontend/cphp/components/component.router.php b/frontend/cphp/components/component.router.php new file mode 100644 index 0000000..2d54e8a --- /dev/null +++ b/frontend/cphp/components/component.router.php @@ -0,0 +1,62 @@ +custom_query)) + { + $requestpath = $this->custom_query; + } + else + { + if(!empty($_SERVER['REQUEST_URI'])) + { + $requestpath = trim($_SERVER['REQUEST_URI']); + } + else + { + $requestpath = "/"; + } + } + + $found = false; // Workaround because a break after an include apparently doesn't work in PHP. + + foreach($this->routes as $priority) + { + foreach($priority as $route_regex => $route_destination) + { + if($found === false) + { + $regex = str_replace("/", "\/", $route_regex); + if(preg_match("/{$regex}/i", $requestpath, $matches)) + { + $this->uParameters = $matches; + include($route_destination); + $found = true; + } + } + } + } + } +} +?> diff --git a/frontend/cphp/config.php b/frontend/cphp/config.php new file mode 100644 index 0000000..78227d4 --- /dev/null +++ b/frontend/cphp/config.php @@ -0,0 +1,50 @@ + "User" +); + +$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"); + +/* Please create a new file in this directory named config.mysql.php + * that holds the following contents (modified to the correct settings): + +$cphp_mysql_host = "localhost"; +$cphp_mysql_user = "username"; +$cphp_mysql_pass = "password"; +$cphp_mysql_db = "database"; + +*/ + +$cphp_components = array( + "router", + "errorhandler" +); diff --git a/frontend/cphp/include.constants.php b/frontend/cphp/include.constants.php new file mode 100644 index 0000000..49265a1 --- /dev/null +++ b/frontend/cphp/include.constants.php @@ -0,0 +1,24 @@ + '(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 & Canada)', + 'America/Tijuana' => '(GMT-08:00) Tijuana, Baja California', + 'America/Denver' => '(GMT-07:00) Mountain Time (US & 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 & Canada)', + 'America/Mexico_City' => '(GMT-06:00) Mexico City', + 'America/Monterrey' => '(GMT-06:00) Monterrey', + 'America/New_York' => '(GMT-05:00) Eastern Time (US & 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', + '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' +); + +function unix_from_local($timestamp) +{ + global $user_preferences; + date_default_timezone_set($user_preferences[CPHP_SETTING_TIMEZONE]); + return strtotime($timestamp); +} + +function unix_from_mysql($timestamp) +{ + date_default_timezone_set("GMT"); + return strtotime($timestamp); +} + +function local_from_unix($timestamp, $format) +{ + global $user_preferences; + date_default_timezone_set($user_preferences[CPHP_SETTING_TIMEZONE]); + return strftime($format, $timestamp); +} + +function gmt_from_unix($timestamp, $format) +{ + date_default_timezone_set("GMT"); + return strftime($format, $timestamp); +} + +function mysql_from_unix($timestamp) +{ + date_default_timezone_set("GMT"); + return date("Y-m-d H:i:s", $timestamp); +} + +function floor_to_day($timestamp) +{ + return floor($timestamp / (60 * 60 * 24)) * (60 * 60 * 24); +} diff --git a/frontend/cphp/include.dependencies.php b/frontend/cphp/include.dependencies.php new file mode 100644 index 0000000..80133c1 --- /dev/null +++ b/frontend/cphp/include.dependencies.php @@ -0,0 +1,101 @@ + $f_min) + { + return true; + } + else + { + return false; + } + } + else + { + if($f_cur > $f_min && $f_cur < $f_max) + { + return true; + } + else + { + return false; + } + } + } + } +} diff --git a/frontend/cphp/include.exceptions.php b/frontend/cphp/include.exceptions.php new file mode 100644 index 0000000..229efa2 --- /dev/null +++ b/frontend/cphp/include.exceptions.php @@ -0,0 +1,23 @@ +connect($cphp_memcache_server, $cphp_memcache_port); + + if($cphp_memcache_established !== false) + { + $cphp_memcache_connected = true; + } + else + { + $cphp_memcache_connected = false; + } +} + +function mc_get($key) +{ + global $cphp_memcache_enabled, $cphp_memcache_connected, $memcache; + + if($cphp_memcache_enabled === false || $cphp_memcache_connected === false) + { + return false; + } + else + { + $get_result = $memcache->get($key); + if($get_result !== false) + { + return $get_result; + } + else + { + return false; + } + } +} + +function mc_set($key, $value, $expiry) +{ + global $cphp_memcache_enabled, $cphp_memcache_connected, $cphp_memcache_compressed, $memcache; + + if($cphp_memcache_enabled === false || $cphp_memcache_connected === false) + { + return false; + } + else + { + if($cphp_memcache_compressed === true) + { + $flag = MEMCACHE_COMPRESSED; + } + else + { + $flag = false; + } + + $set_result = $memcache->set($key, $value, $flag, $expiry); + return $set_result; + } +} + +function mc_delete($key) +{ + global $cphp_memcache_enabled, $cphp_memcache_connected, $memcache; + + if($cphp_memcache_enabled === false || $cphp_memcache_connected === false) + { + return false; + } + else + { + return $memcache->delete($key); + } +} + +function mysql_query_cached($query, $expiry = 60, $key = "") +{ + 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) +{ + if($res = mc_get(md5($path) . md5($path . "x"))) + { + $return_object->source = "memcache"; + $return_object->data = $res; + return $return_object; + } + else + { + if($result = file_get_contents($path)) + { + $return_object->source = "disk"; + $return_object->data = $result; + mc_set(md5($path) . md5($path . "x"), $return_object->data, $expiry); + return $return_object; + } + else + { + return false; + } + } +} diff --git a/frontend/cphp/include.misc.php b/frontend/cphp/include.misc.php new file mode 100644 index 0000000..8ccf6ae --- /dev/null +++ b/frontend/cphp/include.misc.php @@ -0,0 +1,101 @@ + $value){ + $vars[] = "$".$key; + } + + return "global " . join(",", $vars) . ";"; +} + +function utf8entities($utf8) +{ + // Credits to silverbeat@gmx.at (http://www.php.net/manual/en/function.htmlentities.php#96648) + $encodeTags = true; + $result = ''; + for ($i = 0; $i < strlen($utf8); $i++) + { + $char = $utf8[$i]; + $ascii = ord($char); + if ($ascii < 128) + { + $result .= ($encodeTags) ? htmlentities($char) : $char; + } + else if ($ascii < 192) + { + // Do nothing. + } + else if ($ascii < 224) + { + $result .= htmlentities(substr($utf8, $i, 2), ENT_QUOTES, 'UTF-8'); + $i++; + } + else if ($ascii < 240) + { + $ascii1 = ord($utf8[$i+1]); + $ascii2 = ord($utf8[$i+2]); + $unicode = (15 & $ascii) * 4096 + + (63 & $ascii1) * 64 + + (63 & $ascii2); + $result .= "&#$unicode;"; + $i += 2; + } + else if ($ascii < 248) + { + $ascii1 = ord($utf8[$i+1]); + $ascii2 = ord($utf8[$i+2]); + $ascii3 = ord($utf8[$i+3]); + $unicode = (15 & $ascii) * 262144 + + (63 & $ascii1) * 4096 + + (63 & $ascii2) * 64 + + (63 & $ascii3); + $result .= "&#$unicode;"; + $i += 3; + } + } + return $result; +} + +function clean_array($arr) +{ + $result = array(); + foreach($arr as $key => $value) + { + if(!empty($value)) + { + $result[$key] = $value; + } + } + return $result; +} + +/*function is_empty($variable) +{ + return (trim($variable) == ""); +}*/ diff --git a/frontend/cphp/include.mysql.php b/frontend/cphp/include.mysql.php new file mode 100644 index 0000000..71880c0 --- /dev/null +++ b/frontend/cphp/include.mysql.php @@ -0,0 +1,27 @@ +