diff --git a/app/app.php b/app/app.php index 91adc35..61de49f 100644 --- a/app/app.php +++ b/app/app.php @@ -1,6 +1,6 @@ diff --git a/app/install/installer.php b/app/install/installer.php index 96c4c52..c9a6cb0 100644 --- a/app/install/installer.php +++ b/app/install/installer.php @@ -253,6 +253,7 @@ try { 'listing_viewer' => 1, ], '1.1.1' => NULL, + '1.1.2' => NULL, ]; // Settings that must be renamed from NAME to NEW NAME and DELETE old NAME $settings_rename = []; diff --git a/app/routes/route.dashboard.php b/app/routes/route.dashboard.php index a607d83..2fe28f7 100644 --- a/app/routes/route.dashboard.php +++ b/app/routes/route.dashboard.php @@ -136,7 +136,7 @@ $route = function ($handler) { ], 'g_version' => [ 'label' => 'G\\', - 'content' => 'G\\ Library '.G\get_version().'' + 'content' => 'G\\ Library '.G\get_version().'' ], 'php_version' => [ 'label' => _s('PHP version'), diff --git a/content/pages/default/privacy.php b/content/pages/default/privacy.php index 9eabf52..fec3266 100644 --- a/content/pages/default/privacy.php +++ b/content/pages/default/privacy.php @@ -1,4 +1,6 @@ - +
If you need more help we suggest you to go to Chevereto support and read the G\ Library documentation. View the code of this file will also help you to understand the magic behind this system.
+If you need more help we suggest you to go to Chevereto support and read the G\ Library documentation. View the code of this file will also help you to understand the magic behind this system.
If you need more help we suggest you to go to Chevereto support and read the G\ Library documentation. View the code of this file will also help you to understand the magic behind this system.
+If you need more help we suggest you to go to Chevereto support and read the G\ Library documentation. View the code of this file will also help you to understand the magic behind this system.
', 'where' => 'before|after']
- */
- public function hookTemplate($args=[]) {
- if(in_array($args['where'], ['before', 'after']) and $args['code']) {
- if(!isset($this->hook_template)) {
- $this->hook_template = [];
- }
- $this->hook_template[$args['where']] = $args['code'];
- }
- }
-
- /**
- * load the setted (or argument) template view
- */
- private function loadTemplate($template=NULL) {
- if(!is_null($template)) {
- $this->template = $template;
- }
-
- /** Overrides are loaded from highest to lowest priority **/
-
- $functions_basename = 'functions.php';
- $template_functions = [
- $this->path_theme . 'overrides/' . $functions_basename,
- $this->path_theme . $functions_basename
- ];
- foreach($template_functions as $file) {
- if(file_exists($file)) {
- require_once($file);
- break;
- }
- }
-
- $view_basename = $this->template;
- $view_extension = get_file_extension($this->template);
- if(!$view_extension) {
- $view_extension = 'php';
- $view_basename .= '.php';
- }
- $template_file = [
- $this->path_theme . 'overrides/views/' . $view_basename,
- $this->path_theme . 'overrides/' . $view_basename,
- $this->path_theme . 'views/'. $view_basename,
- $this->path_theme . $view_basename,
- ];
- foreach($template_file as $file) {
- if(file_exists($file)) {
- if($view_extension == 'html') {
- Render\include_theme_header();
- }
- if($this->hook_template['before']) {
- echo $this->hook_template['before'];
- }
- if($view_extension == 'php') {
- require_once($file);
- } else {
- echo file_get_contents($file);
- }
- if($this->hook_template['after']) {
- echo $this->hook_template['after'];
- }
- if($view_extension == 'html') {
- Render\include_theme_footer();
- }
- return;
- }
- }
-
- $end = end($template_file);
- $key = key($template_file);
-
- throw new HandlerException('Missing ' . absolute_to_relative($template_file[$key]) . ' template file', 400);
- }
-
- /**
- * Returns the 40 char length safe request token
- */
- public static function getAuthToken() {
- $token = isset($_SESSION['G_auth_token']) ? $_SESSION['G_auth_token'] : random_string(40);
- $_SESSION['G_auth_token'] = $token;
- return $token;
- }
-
- /**
- * Checks the integrity and validation of the given request token
- */
- public static function checkAuthToken($token) {
- if(strlen($token) < 40) return false;
- return timing_safe_compare($_SESSION['G_auth_token'], $token);
- }
-
- /**
- * Sets a Handler::$var > get_var() binding
- */
- public static function setVar($var, $value) {
- self::$vars[$var] = $value;
- }
-
- /**
- * Sets a multiple Handler::$var > get_var() binding
- */
- public static function setVars($array) {
- foreach((array)$array as $var => $value) {
- self::$vars[$var] = $value;
- }
- }
-
- /**
- * Sets a Handler::$conds -> is_cond() binding
- */
- public static function setCond($conds, $bool) {
- self::$conds[$conds] = !$bool ? false : true;
- }
-
- /**
- * Sets a multiple Handler::$conds -> is_cond() binding
- */
- public static function setConds($array=[]) {
- foreach((array)$array as $conds => $bool) {
- self::$conds[$conds] = !$bool ? false : true;
- }
- }
-
- /**
- * Get a Handler::$vars[var]
- */
- public static function getVar($var) {
- return self::getVars()[$var];
- }
-
- /**
- * Get all Handler::$vars
- */
- public static function getVars() {
- return self::$vars;
- }
-
- /**
- * Get a Handler::$condss[cond]
- */
- public static function getCond($cond) {
- return self::getConds()[$cond];
- }
-
- /**
- * Get all Handler::$conds
- */
- public static function getConds() {
- return self::$conds;
- }
-
- /**
- * Smart update a Handler::$vars
- */
- public static function updateVar($var, $value) {
- if(is_array(self::$vars[$var]) and is_array($value)) {
- //self::$vars[$var] = array_merge(self::$vars[$var], $value);
- $value += self::$vars[$var]; // replacement + replaced
- ksort($value);
- }
- self::$vars[$var] = $value;
- }
-
- /**
- * Unset a given var
- */
- public static function unsetVar($var) {
- unset(self::$vars[$var]);
- }
-
- /**
- * Get the template file basename used
- */
- public static function getTemplateUsed() {
- return self::$template_used;
- }
-
- /**
- * Get the current route path
- * @args $full (bool true) outputs the full route 'like/this' or 'this'
- */
- public static function getRoutePath($full=true) {
- if(is_array(self::$route)) {
- return $full ? implode('/', self::$route) : self::$route[0];
- } else {
- return self::$route;
- }
- }
-
- /**
- * Get the current route name from route.name.php
- */
- public static function getRouteName() {
- return self::$route_name;
- }
-
+class Handler
+{
+ public static $route;
+ public static $route_request;
+ public static $route_name;
+ public static $base_request;
+ public static $doctitle;
+ public static $vars;
+ public static $conds;
+ public static $routes;
+ public static $template_used;
+ public static $prevented_route;
+ public static $mapped_args;
+
+ /**
+ * Build a valid request
+ */
+ public function __construct($hook=[])
+ {
+ if (!defined('G_APP_PATH_THEME')) {
+ throw new HandlerException('G_APP_PATH_THEME is not defined', 100);
+ }
+
+ // Parse the definitions to this object.. This is not necessary but in case of changes...
+ $this->relative_root = G_ROOT_PATH_RELATIVE; // nota: realmente necesitamos estos this?
+ $this->base_url = get_root_url();
+ $this->path_theme = G_APP_PATH_THEME;
+
+ // Parse the request
+ $this->request_uri = $_SERVER['REQUEST_URI'];
+ $this->script_name = $_SERVER['SCRIPT_NAME'];
+
+ $query_string = '?' . $_SERVER['QUERY_STRING'];
+
+ if (!empty($_SERVER['QUERY_STRING'])) {
+ $this->request_uri = str_replace($query_string, '/', $this->request_uri);
+ }
+
+ $this->valid_request = '/' . ltrim(rtrim(sanitize_path_slashes($this->request_uri), '/'), '/');
+
+ if (!empty($_SERVER['QUERY_STRING'])) {
+ $this->request_uri = $_SERVER['REQUEST_URI'];
+ $this->valid_request .= /*'/' .*/ $query_string;
+ }
+
+ // Store the canonical request, used for redirect to a valid request
+ $this->canonical_request = $this->valid_request;
+
+ if (is_dir(G_ROOT_PATH . $this->valid_request) && $this->valid_request !== '/') {
+ $this->canonical_request .= '/';
+ }
+
+ $this->handled_request = strtok($this->relative_root == '/' ? $this->valid_request : preg_replace('#' . $this->relative_root . '#', '/', $this->request_uri, 1), '?');
+ $this->request_array = explode('/', rtrim(str_replace('//', '/', ltrim($this->handled_request, '/')), '/'));
+
+ // Index request
+ if ($this->request_array[0] == '') {
+ $this->request_array[0] = '/';
+ }
+
+ $this->request_array = array_values(array_filter($this->request_array, 'strlen'));
+ self::$base_request = $this->request_array[0];
+
+ // Reserved route (index)
+ if (self::$base_request == 'index') {
+ redirect('/', 301);
+ }
+
+ // Fix the canonical request /something?q= to /something/?q=
+ if (self::$base_request !== '' && !empty($_SERVER['QUERY_STRING'])) {
+ $path_request = add_trailing_slashes(rtrim(str_replace($_SERVER['QUERY_STRING'], '', $this->canonical_request), '?'));
+ $fixed_qs_request = $path_request.'?'.$_SERVER['QUERY_STRING'];
+ $this->canonical_request = $fixed_qs_request;
+ }
+
+ // No /index.php request
+ if (self::$base_request == 'index.php') {
+ $this->canonical_request = rtrim($this->canonical_request, '/');
+ redirect((sanitize_path_slashes(str_replace('index.php', '', $this->canonical_request))), 301);
+ }
+
+ // If the request is invalid we make a 301 redirection to the canonical url.
+ if ($this->relative_root !== $this->request_uri and $this->canonical_request !== $this->request_uri) {
+ $this->baseRedirection($this->canonical_request);
+ }
+
+ if (in_array(self::$base_request, ['', 'index.php', '/'])) {
+ self::$base_request = 'index';
+ }
+
+ $this->template = self::$base_request;
+ $this->request = $this->request_array;
+
+ self::$route_request = $this->request_array;
+ self::$route = $this->template !== 404 ? $this->request_array[0] == '/' ? 'index' : $this->request_array : 404;
+
+ unset($this->request[0]);
+ $this->request = array_values($this->request);
+
+ // Hook a fn BEFORE the process
+ if (is_array($hook) and is_callable($hook['before'])) {
+ $hook['before']($this);
+ }
+
+ // It is a valid request on index.php?
+ if ($this->isIndex()) {
+ $this->processRequest();
+ }
+
+ // Hook a fn AFTER the process
+ if (is_array($hook) and is_callable($hook['after'])) {
+ $hook['after']($this);
+ }
+
+ // Auto-bind the route vars
+ if (is_array(self::$vars)) {
+ foreach (self::$vars as $k => $v) {
+ $this->bindGetFn($k, $v);
+ }
+ }
+ // Auto-bind the route conditionals
+ if (is_array(self::$conds)) {
+ foreach (self::$conds as $k => $v) {
+ $this->bindIsFn($k, $v);
+ }
+ }
+
+ $this->loadTemplate();
+ }
+
+ /**
+ * Iterate over the route app folder
+ * This populates Handler::$routes with all the valid routes
+ */
+ private static function routeIterator($path)
+ {
+ if (!file_exists($path)) {
+ return;
+ }
+
+ foreach (new \DirectoryIterator($path) as $fileInfo) {
+ if ($fileInfo->isDot() or $fileInfo->isDir()) {
+ continue;
+ }
+
+ $route_file = $path . $fileInfo->getFilename();
+ $route_override = $path . 'overrides/' . $fileInfo->getFilename();
+
+ if (file_exists($route_override)) {
+ $route_file = $route_override;
+ }
+
+ if (file_exists($route_file)) {
+ require_once($route_file);
+ $route = array(substr(substr($fileInfo->getFilename(), 0, -4), 6) => $route);
+ self::$routes += $route;
+ }
+ }
+ }
+
+ /**
+ * Stock (save) the valid routes of the G\ app
+ * This method is optional because the routeIterator takes some memory
+ */
+ public static function stockRoutes()
+ {
+ self::$routes = [];
+ self::routeIterator(G_APP_PATH_ROUTES);
+ self::routeIterator(G_APP_PATH_ROUTES_OVERRIDES);
+ }
+
+ /**
+ * Process the dynamic request
+ */
+ private function processRequest()
+ {
+ if (is_null(self::$routes)) { // Route array is not set
+ $route = $this->getRouteFn(self::$base_request);
+ if (is_callable($route)) {
+ $routes[self::$base_request] = $route; // Build a single $routes array
+ }
+ } else {
+ $routes = self::$routes;
+ }
+
+ if (is_array($routes) and array_key_exists(self::$base_request, $routes)) {
+
+ // Autoset some magic
+ $magic = array(
+ 'post' => $_POST ? $_POST : null,
+ 'get' => $_GET ? $_GET : null,
+ 'request' => $_REQUEST ? $_REQUEST : null,
+ 'safe_post' => $_POST ? safe_html($_POST) : null,
+ 'safe_get' => $_GET ? safe_html($_GET) : null,
+ 'safe_request' => $_REQUEST ? safe_html($_REQUEST) : null,
+ 'auth_token' => self::getAuthToken()
+ );
+
+ if (self::$vars && count(self::$vars) > 0) {
+ self::$vars = array_merge(self::$vars, $magic);
+ } else {
+ self::$vars = $magic;
+ }
+
+ // Only call a valid route fn
+ if (!self::$prevented_route and is_callable($routes[self::$base_request])) {
+ $routes[self::$base_request]($this);
+ }
+ } else {
+ $this->issue404();
+ $this->request = $this->request_array;
+ }
+
+ if ($this->template == 404) {
+ self::$route = 404;
+ }
+ self::setCond('404', $this->template == 404); // is_404 binding
+
+ if (self::$vars['pre_doctitle']) {
+ $stock_doctitle = self::$vars['doctitle'];
+ self::$vars['doctitle'] = self::$vars['pre_doctitle'];
+ if ($stock_doctitle) {
+ self::$vars['doctitle'] .= ' - ' . $stock_doctitle;
+ }
+ }
+
+ self::$template_used = $this->template;
+ }
+
+ /**
+ * Bind route var to global functions
+ */
+ public function bindGetFn($var, $value)
+ {
+ $fn_name = strtolower(str_replace('-', '_', $var));
+ if (!function_exists('get_' . $fn_name)) {
+ eval('function get_' . $fn_name . '(){ return G\Handler::$vars["' . $var . '"]; }');
+ }
+ }
+
+ /**
+ * Bind route conditional to global functions
+ */
+ public function bindIsFn($var, $value)
+ {
+ $fn_name = strtolower(str_replace('-', '_', $var));
+ if (!function_exists('is_' . $fn_name)) {
+ eval('function is_' . $fn_name . '(){ return G\Handler::$conds["' . $var . '"]; }');
+ }
+ }
+
+ /**
+ * Inject the 404 page
+ */
+ public function issue404()
+ {
+ set_status_header(404);
+ if ($this->getCond('mapped_route')) {
+ self::$base_request = self::$route_request[0];
+ self::$route_name = 404;
+ }
+ $this->is404 = true;
+ $this->template = 404;
+ }
+
+ /**
+ * Prevent the rest of the execution loading the target view
+ */
+ public function preventRoute($tpl=null)
+ {
+ if ($tpl) {
+ $this->template = $tpl;
+ }
+ self::$prevented_route = true;
+ }
+
+ /**
+ * Get the route fn for a given route
+ * If the route doesn't exists it will add it to the routes stack
+ */
+ public function getRouteFn($route_name)
+ {
+ // Route is already in the stack
+ if (is_array(self::$routes) and array_key_exists($route_name, Handler::$routes)) {
+ return self::$routes[$route_name];
+ }
+ // Route doesn't exists in the stack
+ $filename = 'route.' . $route_name . '.php';
+ $route_file = G_APP_PATH_ROUTES . $filename;
+ $route_override_file = G_APP_PATH_ROUTES_OVERRIDES . $filename;
+ if (file_exists($route_override_file)) {
+ $route_file = $route_override_file;
+ }
+ if (file_exists($route_file)) {
+ require($route_file);
+ // Append this new route fn to the Handler::$routes stack
+ self::$routes[$route_name] = $route;
+ self::$route_name = $route_name;
+ return $route;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Maps the current route which is useful to make route aliases
+ */
+ public function mapRoute($route_name, $args=null)
+ {
+ $this->template = $route_name;
+ self::$base_request = $route_name;
+ self::setCond('mapped_route', true);
+ if (!is_null($args)) {
+ self::$mapped_args = $args;
+ }
+ return $this->getRouteFn($route_name);
+ }
+
+ /**
+ * Return (bool) the request level of the current request
+ */
+ public function isRequestLevel($level)
+ {
+ return isset($this->request_array[$level - 1]);
+ }
+
+ /**
+ * Redirect to the base url/request
+ */
+ public function baseRedirection($request)
+ {
+ $request = trim(sanitize_path_slashes($request), '/');
+ $url = preg_replace('{'.$this->relative_root.'}', '/', $this->base_url, 1) . $request;
+ redirect($url, 301);
+ }
+
+ /**
+ * Return (bool) if the request is handled by index.php
+ */
+ private function isIndex()
+ {
+ return preg_match('{/index.php$}', $this->script_name);
+ }
+
+ /**
+ * Hook code for loadTemplate()
+ * @args ['code' => '', 'where' => 'before|after']
+ */
+ public function hookTemplate($args=[])
+ {
+ if (in_array($args['where'], ['before', 'after']) and $args['code']) {
+ if (!isset($this->hook_template)) {
+ $this->hook_template = [];
+ }
+ $this->hook_template[$args['where']] = $args['code'];
+ }
+ }
+
+ /**
+ * load the setted (or argument) template view
+ */
+ private function loadTemplate($template=null)
+ {
+ if (!is_null($template)) {
+ $this->template = $template;
+ }
+
+ /** Overrides are loaded from highest to lowest priority **/
+
+ $functions_basename = 'functions.php';
+ $template_functions = [
+ $this->path_theme . 'overrides/' . $functions_basename,
+ $this->path_theme . $functions_basename
+ ];
+ foreach ($template_functions as $file) {
+ if (file_exists($file)) {
+ require_once($file);
+ break;
+ }
+ }
+
+ $view_basename = $this->template;
+ $view_extension = get_file_extension($this->template);
+ if (!$view_extension) {
+ $view_extension = 'php';
+ $view_basename .= '.php';
+ }
+ $template_file = [
+ $this->path_theme . 'overrides/views/' . $view_basename,
+ $this->path_theme . 'overrides/' . $view_basename,
+ $this->path_theme . 'views/'. $view_basename,
+ $this->path_theme . $view_basename,
+ ];
+ foreach ($template_file as $file) {
+ if (file_exists($file)) {
+ if ($view_extension == 'html') {
+ Render\include_theme_header();
+ }
+ if ($this->hook_template['before']) {
+ echo $this->hook_template['before'];
+ }
+ if ($view_extension == 'php') {
+ require_once($file);
+ } else {
+ echo file_get_contents($file);
+ }
+ if ($this->hook_template['after']) {
+ echo $this->hook_template['after'];
+ }
+ if ($view_extension == 'html') {
+ Render\include_theme_footer();
+ }
+ return;
+ }
+ }
+
+ $end = end($template_file);
+ $key = key($template_file);
+
+ throw new HandlerException('Missing ' . absolute_to_relative($template_file[$key]) . ' template file', 400);
+ }
+
+ /**
+ * Returns the 40 char length safe request token
+ */
+ public static function getAuthToken()
+ {
+ $token = isset($_SESSION['G_auth_token']) ? $_SESSION['G_auth_token'] : random_string(40);
+ $_SESSION['G_auth_token'] = $token;
+ return $token;
+ }
+
+ /**
+ * Checks the integrity and validation of the given request token
+ */
+ public static function checkAuthToken($token)
+ {
+ if (strlen($token) < 40) {
+ return false;
+ }
+ return timing_safe_compare($_SESSION['G_auth_token'], $token);
+ }
+
+ /**
+ * Sets a Handler::$var > get_var() binding
+ */
+ public static function setVar($var, $value)
+ {
+ self::$vars[$var] = $value;
+ }
+
+ /**
+ * Sets a multiple Handler::$var > get_var() binding
+ */
+ public static function setVars($array)
+ {
+ foreach ((array)$array as $var => $value) {
+ self::$vars[$var] = $value;
+ }
+ }
+
+ /**
+ * Sets a Handler::$conds -> is_cond() binding
+ */
+ public static function setCond($conds, $bool)
+ {
+ self::$conds[$conds] = !$bool ? false : true;
+ }
+
+ /**
+ * Sets a multiple Handler::$conds -> is_cond() binding
+ */
+ public static function setConds($array=[])
+ {
+ foreach ((array)$array as $conds => $bool) {
+ self::$conds[$conds] = !$bool ? false : true;
+ }
+ }
+
+ /**
+ * Get a Handler::$vars[var]
+ */
+ public static function getVar($var)
+ {
+ return self::getVars()[$var];
+ }
+
+ /**
+ * Get all Handler::$vars
+ */
+ public static function getVars()
+ {
+ return self::$vars;
+ }
+
+ /**
+ * Get a Handler::$condss[cond]
+ */
+ public static function getCond($cond)
+ {
+ return self::getConds()[$cond];
+ }
+
+ /**
+ * Get all Handler::$conds
+ */
+ public static function getConds()
+ {
+ return self::$conds;
+ }
+
+ /**
+ * Smart update a Handler::$vars
+ */
+ public static function updateVar($var, $value)
+ {
+ if (is_array(self::$vars[$var]) and is_array($value)) {
+ //self::$vars[$var] = array_merge(self::$vars[$var], $value);
+ $value += self::$vars[$var]; // replacement + replaced
+ ksort($value);
+ }
+ self::$vars[$var] = $value;
+ }
+
+ /**
+ * Unset a given var
+ */
+ public static function unsetVar($var)
+ {
+ unset(self::$vars[$var]);
+ }
+
+ /**
+ * Get the template file basename used
+ */
+ public static function getTemplateUsed()
+ {
+ return self::$template_used;
+ }
+
+ /**
+ * Get the current route path
+ * @args $full (bool true) outputs the full route 'like/this' or 'this'
+ */
+ public static function getRoutePath($full=true)
+ {
+ if (is_array(self::$route)) {
+ return $full ? implode('/', self::$route) : self::$route[0];
+ } else {
+ return self::$route;
+ }
+ }
+
+ /**
+ * Get the current route name from route.name.php
+ */
+ public static function getRouteName()
+ {
+ return self::$route_name;
+ }
}
-class HandlerException extends Exception {}
\ No newline at end of file
+class HandlerException extends Exception
+{
+}
diff --git a/lib/G/classes/class.minify.php b/lib/G/classes/class.minify.php
index 2fd5634..b7a7f36 100644
--- a/lib/G/classes/class.minify.php
+++ b/lib/G/classes/class.minify.php
@@ -3,7 +3,7 @@
/* --------------------------------------------------------------------
G\ library
- http://gbackslash.com
+ https://g.chevereto.com
@author Rodolfo Berrios A.
diff --git a/lib/G/functions.php b/lib/G/functions.php
index 1ba2b65..c3ed684 100644
--- a/lib/G/functions.php
+++ b/lib/G/functions.php
@@ -3,7 +3,7 @@
/* --------------------------------------------------------------------
G\ library
- http://gbackslash.com
+ https://g.chevereto.com
@author Rodolfo Berrios A.
@@ -310,9 +310,12 @@ namespace G {
*/
function abbreviate_number($number)
{
-
- // strip any formatting
- $number = (0+str_replace(',', '', $number));
+ if ($number === null) {
+ $number = 0;
+ } else {
+ // strip any formatting
+ $number = (0+str_replace(',', '', $number));
+ }
// Not a number, keep it "as is"
if (!is_numeric($number) or $number == 0) {
@@ -560,7 +563,7 @@ namespace G {
function exception_to_error($e, $die=true)
{
$internal_code = 500;
- $internal_error = ''.G_APP_NAME.' error: ' . get_set_status_header_desc($internal_code);
+ $internal_error = 'Aw, snap! ' . get_set_status_header_desc($internal_code) . ' - Check your error_log or enable debug_mode = 3 (chevereto.com/docs/debug).';
set_status_header($internal_code);
@@ -816,18 +819,20 @@ namespace G {
function get_client_ip()
{
- $client_ip = !empty($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : (!empty($_ENV['REMOTE_ADDR']) ? $_ENV['REMOTE_ADDR'] : null);
-
- if (array_key_exists('HTTP_CF_CONNECTING_IP', $_SERVER) && $_SERVER['HTTP_CF_CONNECTING_IP'] == $_SERVER['REMOTE_ADDR']) {
- return $_SERVER['HTTP_CF_CONNECTING_IP'];
+ if(isset($_SERVER['G_CLIENT_IP'])) {
+ return $_SERVER['G_CLIENT_IP'];
}
-
- if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
+ if (isset($_SERVER['HTTP_CF_CONNECTING_IP'])) {
+ $client_ip = $_SERVER['HTTP_CF_CONNECTING_IP'];
+ } else {
+ $client_ip = isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : null;
+ }
+ if (isset($_SERVER['HTTP_X_FORWARDED_FOR']) && $client_ip != $_SERVER['HTTP_X_FORWARDED_FOR']) {
$entries = preg_split('/[\s,]/', $_SERVER['HTTP_X_FORWARDED_FOR'], -1, PREG_SPLIT_NO_EMPTY);
reset($entries);
- while (list(, $entry) = each($entries)) {
+ foreach ($entries as $entry) {
$entry = trim($entry);
if (preg_match('/^([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)/', $entry, $ip_list)) {
$private_ip = array(
@@ -838,7 +843,6 @@ namespace G {
'/^10\..*/');
$found_ip = preg_replace($private_ip, $client_ip, $ip_list[1]);
-
if ($client_ip != $found_ip) { // and !isset($_SERVER['HTTP_CF_CONNECTING_IP']
$client_ip = $found_ip;
break;
@@ -846,7 +850,7 @@ namespace G {
}
}
}
-
+ $_SERVER['G_CLIENT_IP'] = $client_ip;
return $client_ip;
}
@@ -1129,6 +1133,23 @@ namespace G {
return $path;
}
+ function rrmdir($dir)
+ {
+ if (is_dir($dir)) {
+ $objects = scandir($dir);
+ foreach ($objects as $object) {
+ if ($object != "." && $object != "..") {
+ if (is_dir($dir."/".$object)) {
+ rrmdir($dir."/".$object);
+ } else {
+ unlink($dir."/".$object);
+ }
+ }
+ }
+ rmdir($dir);
+ }
+ }
+
/**
* Returns a sanitized string, typically for URLs
* This function was borrowed from chyrp.net (MIT License)
@@ -1438,7 +1459,7 @@ namespace G {
function relative_to_url($filepath, $root_url=null)
{
if (!check_value($root_url)) {
- $root_url = G_ROOT_URL;
+ $root_url = get_root_url();
}
return str_replace(G_ROOT_PATH_RELATIVE, $root_url, forward_slash($filepath));
}
@@ -1447,7 +1468,7 @@ namespace G {
function url_to_relative($url, $root_url=null)
{
if (!check_value($root_url)) {
- $root_url = G_ROOT_URL;
+ $root_url = get_root_url();
}
return str_replace($root_url, G_ROOT_PATH_RELATIVE, $url);
}
@@ -1462,7 +1483,7 @@ namespace G {
function absolute_to_url($filepath, $root_url=null)
{
if (!check_value($root_url)) {
- $root_url = G_ROOT_URL;
+ $root_url = get_root_url();
}
if (G_ROOT_PATH === G_ROOT_PATH_RELATIVE) {
return $root_url . ltrim($filepath, '/');
@@ -1474,7 +1495,7 @@ namespace G {
function url_to_absolute($url, $root_url=null)
{
if (!check_value($root_url)) {
- $root_url = G_ROOT_URL;
+ $root_url = get_root_url();
}
return str_replace($root_url, G_ROOT_PATH, $url);
}
@@ -1508,21 +1529,43 @@ namespace G {
return get_global('settings')[$key];
}
- function get_domain()
- {
- return HTTP_HOST;
- }
-
function get_base_url($path='')
{
$path = sanitize_relative_path($path);
- $return = G_ROOT_URL . ltrim($path, '/');
+ $return = get_root_url() . ltrim($path, '/');
return rtrim($return, '/');
}
- function get_current_url()
+ function get_host()
{
- return get_base_url(preg_replace('#'.G_ROOT_PATH_RELATIVE.'#', '', $_SERVER['REQUEST_URI'], 1));
+ return defined('APP_G_HTTP_HOST') ? APP_G_HTTP_HOST : G_HTTP_HOST;
+ }
+
+ function get_root_url()
+ {
+ return defined('APP_G_ROOT_URL') ? APP_G_ROOT_URL : G_ROOT_URL;
+ }
+
+ /**
+ * @param string Querystring keys to remove (comma separated)
+ */
+ function get_current_url($safe=true, $removeQs=[])
+ {
+ $request_uri = $_SERVER['REQUEST_URI'];
+ $request_path = rtrim(strtok($request_uri, '?'), '/');
+ if ($_SERVER['QUERY_STRING'] && $removeQs) {
+ parse_str($_SERVER['QUERY_STRING'], $parse);
+ foreach ($removeQs as $v) {
+ unset($parse[$v]);
+ }
+ $querystring = $parse ? http_build_query($parse) : null;
+ $request_uri = $request_path;
+ if ($querystring) {
+ $request_uri .= '/?' . $querystring;
+ }
+ }
+ $path = preg_replace('#'.G_ROOT_PATH_RELATIVE.'#', '', rtrim($request_uri, '/') . '/', 1);
+ return get_base_url($path);
}
function settings_has_db_info()
@@ -1894,9 +1937,26 @@ namespace G {
return basename($file);
}
- function get_filename_without_extension($file)
+ function get_basename_without_extension($filename)
{
- return preg_replace('/\\.[^.\\s]{2,4}$/', '', basename($file));
+ $extension = pathinfo($filename, PATHINFO_EXTENSION);
+ $filename = basename($filename);
+ return str_replace_last(".$extension", null, $filename);
+ }
+
+ function get_pathname_without_extension($filename)
+ {
+ $extension = pathinfo($filename, PATHINFO_EXTENSION);
+ return str_replace_last(".$extension", null, $filename);
+ }
+
+ function change_pathname_extension($filename, $extension)
+ {
+ $chop = get_pathname_without_extension($filename);
+ if ($chop == $filename) {
+ return $filename;
+ }
+ return "$chop.$extension";
}
/**
@@ -2202,9 +2262,9 @@ namespace G {
// https://github.com/Chevereto/Chevereto-Free/pull/35
function imagecreatefrombmp($file)
{
- if (function_exists('imagecreatefrombmp')) {
- return imagecreatefrombmp($file);
- }
+ // if (function_exists('imagecreatefrombmp')) {
+ // return imagecreatefrombmp($file);
+ // }
// version 1.00
if (!($fh = fopen($file, 'rb'))) {
trigger_error('imagecreatefrombmp: Can not open ' . $file, E_USER_WARNING);
@@ -2525,6 +2585,126 @@ namespace G {
return trim(preg_replace('/\s*(?:\*\/|\?>).*/', '', $string));
}
+ /**
+ * function xml2array
+ *
+ * This function is part of the PHP manual.
+ *
+ * The PHP manual text and comments are covered by the Creative Commons
+ * Attribution 3.0 License, copyright (c) the PHP Documentation Group
+ *
+ * @author k dot antczak at livedata dot pl
+ * @date 2011-04-22 06:08 UTC
+ * @link http://www.php.net/manual/en/ref.simplexml.php#103617
+ * @license http://www.php.net/license/index.php#doc-lic
+ * @license http://creativecommons.org/licenses/by/3.0/
+ * @license CC-BY-3.0
+ */
+ function xml2array($xmlObject, $out = array())
+ {
+ foreach ((array) $xmlObject as $index => $node) {
+ $out[$index] = (is_object($node)) ? xml2array($node) : $node;
+ }
+
+ return $out;
+ }
+
+ /**
+ * @param string $domain Pass $_SERVER['SERVER_NAME'] here
+ * @param bool $debug
+ *
+ * @debug bool $debug
+ * @return string
+ *
+ * @link https://gist.github.com/pocesar/5366899
+ */
+ function get_domain($domain, $debug = false)
+ {
+ $original = $domain = strtolower($domain);
+ if (filter_var($domain, FILTER_VALIDATE_IP)) { return $domain; }
+ $debug ? print('» Parsing: '.$original) : false;
+ $arr = array_slice(array_filter(explode('.', $domain, 4), function($value){
+ return $value !== 'www';
+ }), 0); //rebuild array indexes
+ if (count($arr) > 2)
+ {
+ $count = count($arr);
+ $_sub = explode('.', $count === 4 ? $arr[3] : $arr[2]);
+ $debug ? print(" (parts count: {$count})") : false;
+ if (count($_sub) === 2) // two level TLD
+ {
+ $removed = array_shift($arr);
+ if ($count === 4) // got a subdomain acting as a domain
+ {
+ $removed = array_shift($arr);
+ }
+ $debug ? print("
\n" . '[*] Two level TLD: ' . join('.', $_sub) . ' ') : false;
+ }
+ elseif (count($_sub) === 1) // one level TLD
+ {
+ $removed = array_shift($arr); //remove the subdomain
+ if (strlen($_sub[0]) === 2 && $count === 3) // TLD domain must be 2 letters
+ {
+ array_unshift($arr, $removed);
+ }
+ else
+ {
+ // non country TLD according to IANA
+ $tlds = array(
+ 'aero',
+ 'arpa',
+ 'asia',
+ 'biz',
+ 'cat',
+ 'com',
+ 'coop',
+ 'edu',
+ 'gov',
+ 'info',
+ 'jobs',
+ 'mil',
+ 'mobi',
+ 'museum',
+ 'name',
+ 'net',
+ 'org',
+ 'post',
+ 'pro',
+ 'tel',
+ 'travel',
+ 'xxx',
+ );
+ if (count($arr) > 2 && in_array($_sub[0], $tlds) !== false) //special TLD don't have a country
+ {
+ array_shift($arr);
+ }
+ }
+ $debug ? print("
\n" .'[*] One level TLD: '.join('.', $_sub).' ') : false;
+ }
+ else // more than 3 levels, something is wrong
+ {
+ for ($i = count($_sub); $i > 1; $i--)
+ {
+ $removed = array_shift($arr);
+ }
+ $debug ? print("
\n" . '[*] Three level TLD: ' . join('.', $_sub) . ' ') : false;
+ }
+ }
+ elseif (count($arr) === 2)
+ {
+ $arr0 = array_shift($arr);
+ if (strpos(join('.', $arr), '.') === false
+ && in_array($arr[0], array('localhost','test','invalid')) === false) // not a reserved domain
+ {
+ $debug ? print("
\n" .'Seems invalid domain: '.join('.', $arr).' re-adding: '.$arr0.' ') : false;
+ // seems invalid domain, restore it
+ array_unshift($arr, $arr0);
+ }
+ }
+ $debug ? print("
\n".'« Done parsing: ' . $original . ' as '. join('.', $arr) ."
\n") : false;
+ return join('.', $arr);
+ }
+
} // G Namespace
// Global namespace
@@ -2767,5 +2947,4 @@ namespace {
return $status === 0;
}
}
-
}
diff --git a/lib/G/functions.render.php b/lib/G/functions.render.php
index f0caf33..1dbde36 100644
--- a/lib/G/functions.render.php
+++ b/lib/G/functions.render.php
@@ -3,18 +3,19 @@
/* --------------------------------------------------------------------
G\ library
- http://gbackslash.com
+ https://g.chevereto.com
@author Rodolfo Berrios A.
Copyright (c) Rodolfo Berrios All rights reserved.
-
+
Licensed under the MIT license
http://opensource.org/licenses/MIT
-
+
--------------------------------------------------------------------- */
namespace G\Render;
+
use G;
/**
@@ -22,34 +23,38 @@ use G;
* ---------------------------------------------------------------------
*/
-function include_theme_file($filename, $args=[]) {
- $file = G_APP_PATH_THEME . $filename;
- $override = G_APP_PATH_THEME . 'overrides/' . $filename;
- if(!file_exists($file)) {
- $file .= '.php';
- $override .= '.php';
- }
- if(file_exists($override)) {
- $file = $override;
- }
- if(file_exists($file)) {
- $GLOBALS['theme_include_args'] = $args;
- include($file);
- unset($GLOBALS['theme_include_args']);
- }
+function include_theme_file($filename, $args=[])
+{
+ $file = G_APP_PATH_THEME . $filename;
+ $override = G_APP_PATH_THEME . 'overrides/' . $filename;
+ if (!file_exists($file)) {
+ $file .= '.php';
+ $override .= '.php';
+ }
+ if (file_exists($override)) {
+ $file = $override;
+ }
+ if (file_exists($file)) {
+ $GLOBALS['theme_include_args'] = $args;
+ include($file);
+ unset($GLOBALS['theme_include_args']);
+ }
}
-function include_theme_header() {
- include_theme_file('header');
+function include_theme_header()
+{
+ include_theme_file('header');
}
-function include_theme_footer() {
- include_theme_file('footer');
+function include_theme_footer()
+{
+ include_theme_file('footer');
}
-function get_theme_file_contents($filename) {
- $file = G_APP_PATH_THEME . $filename;
- return file_exists($file) ? file_get_contents($file) : null;
+function get_theme_file_contents($filename)
+{
+ $file = G_APP_PATH_THEME . $filename;
+ return file_exists($file) ? file_get_contents($file) : null;
}
/**
@@ -57,8 +62,9 @@ function get_theme_file_contents($filename) {
* ---------------------------------------------------------------------
*/
-function get_theme_file_url($string) {
- return BASE_URL_THEME . $string;
+function get_theme_file_url($string)
+{
+ return BASE_URL_THEME . $string;
}
/**
@@ -67,13 +73,15 @@ function get_theme_file_url($string) {
*/
// Return app lib file url
-function get_app_lib_file_url($string){
- return G_APP_LIB_URL . $string;
+function get_app_lib_file_url($string)
+{
+ return (defined('APP_G_APP_LIB_URL') ? APP_G_APP_LIB_URL : G_APP_LIB_URL) . $string;
}
// Returns the HTML input with the auth token
-function get_input_auth_token($name='auth_token') {
- return '';
+function get_input_auth_token($name='auth_token')
+{
+ return '';
}
@@ -83,80 +91,84 @@ function get_input_auth_token($name='auth_token') {
*/
// Outputs the REST_API array to xml
-function xml_output($array=array()) {
- error_reporting(0);
- //@ini_set('display_errors', false);
- if(ob_get_level() === 0 and !ob_start('ob_gzhandler')) {
- ob_start();
- }
- header("Last-Modified: ".gmdate("D, d M Y H:i:s")."GMT");
- header("Cache-Control: no-cache, must-revalidate");
- header("Pragma: no-cache");
- header("Content-Type:text/xml; charset=UTF-8");
- $out = ''."\n";
- $out .= "\n";
- $out .= " $array[status_code] \n";
- $out .= " $array[status_txt] \n";
- if(count($array["data"])>0) {
- $out .= " \n";
- foreach($array["data"] as $key => $value) {
- $out .= " <$key>$value$key>\n";
- }
- $out .= " \n";
- }
- $out .= " ";
- echo $out;
+function xml_output($array=array())
+{
+ error_reporting(0);
+ //@ini_set('display_errors', false);
+ if (ob_get_level() === 0 and !ob_start('ob_gzhandler')) {
+ ob_start();
+ }
+ header("Last-Modified: ".gmdate("D, d M Y H:i:s")."GMT");
+ header("Cache-Control: no-cache, must-revalidate");
+ header("Pragma: no-cache");
+ header("Content-Type:text/xml; charset=UTF-8");
+ $out = ''."\n";
+ $out .= "\n";
+ $out .= " $array[status_code] \n";
+ $out .= " $array[status_txt] \n";
+ if (count($array["data"])>0) {
+ $out .= " \n";
+ foreach ($array["data"] as $key => $value) {
+ $out .= " <$key>$value$key>\n";
+ }
+ $out .= " \n";
+ }
+ $out .= " ";
+ echo $out;
}
// Procedural function to output an array to json
-function json_output($data=[], $callback=NULL) {
- error_reporting(0);
- //@ini_set('display_errors', false);
- if(ob_get_level() === 0 and !ob_start('ob_gzhandler')) ob_start();
- header('Last-Modified: '.gmdate('D, d M Y H:i:s').'GMT');
- header('Cache-Control: no-cache, must-revalidate');
- header('Pragma: no-cache');
- header('Content-type: application/json; charset=UTF-8');
-
- // Invalid json request
- if(!G\check_value($data) || (G\check_value($callback) and preg_match('/\W/', $callback))) {
- G\set_status_header(400);
- $json_fail = [
- 'status_code' => 400,
- 'status_txt' => G\get_set_status_header_desc(400),
- 'error' => [
- 'message' => 'no request data present',
- 'code' => NULL
- ]
- ];
- die(json_encode($json_fail));
- }
-
- // Populate missing values
- if($data['status_code'] && !$data['status_txt']){
- $data['status_txt'] = G\get_set_status_header_desc($data['status_code']);
- }
-
- $json_encode = json_encode($data);
-
- if(!$json_encode) { // Json failed
- G\set_status_header(500);
- $json_fail = [
- 'status_code' => 500,
- 'status_txt' => G\get_set_status_header_desc(500),
- 'error' => [
- 'message' => "data couldn't be encoded into json",
- 'code' => NULL
- ]
- ];
- die(json_encode($json_fail));
- }
- G\set_status_header($data['status_code']);
-
- if(!is_null($callback)) {
- print sprintf('%s(%s);', $callback, $json_encode);
- } else {
- print $json_encode;
- }
- die();
-}
\ No newline at end of file
+function json_output($data=[], $callback=null)
+{
+ error_reporting(0);
+ //@ini_set('display_errors', false);
+ if (ob_get_level() === 0 and !ob_start('ob_gzhandler')) {
+ ob_start();
+ }
+ header('Last-Modified: '.gmdate('D, d M Y H:i:s').'GMT');
+ header('Cache-Control: no-cache, must-revalidate');
+ header('Pragma: no-cache');
+ header('Content-type: application/json; charset=UTF-8');
+
+ // Invalid json request
+ if (!G\check_value($data) || (G\check_value($callback) and preg_match('/\W/', $callback))) {
+ G\set_status_header(400);
+ $json_fail = [
+ 'status_code' => 400,
+ 'status_txt' => G\get_set_status_header_desc(400),
+ 'error' => [
+ 'message' => 'no request data present',
+ 'code' => null
+ ]
+ ];
+ die(json_encode($json_fail));
+ }
+
+ // Populate missing values
+ if ($data['status_code'] && !$data['status_txt']) {
+ $data['status_txt'] = G\get_set_status_header_desc($data['status_code']);
+ }
+
+ $json_encode = json_encode($data);
+
+ if (!$json_encode) { // Json failed
+ G\set_status_header(500);
+ $json_fail = [
+ 'status_code' => 500,
+ 'status_txt' => G\get_set_status_header_desc(500),
+ 'error' => [
+ 'message' => "data couldn't be encoded into json",
+ 'code' => null
+ ]
+ ];
+ die(json_encode($json_fail));
+ }
+ G\set_status_header($data['status_code']);
+
+ if (!is_null($callback)) {
+ print sprintf('%s(%s);', $callback, $json_encode);
+ } else {
+ print $json_encode;
+ }
+ die();
+}