😑 Fixed bug detected in 1.1.1

pull/40/head 1.1.3
rodolfoberrios 2019-02-19 17:35:48 -03:00
parent f33b7e1a50
commit c9998cfb06
7 changed files with 1078 additions and 1346 deletions

View File

@ -1,6 +1,6 @@
<?php
define('G_APP_NAME', 'Chevereto Free');
define('G_APP_VERSION', '1.1.2');
define('G_APP_VERSION', '1.1.3');
define('G_APP_GITHUB_OWNER', 'Chevereto');
define('G_APP_GITHUB_REPO', 'Chevereto-Free');
define('G_APP_GITHUB_REPO_URL', 'https://github.com/' . G_APP_GITHUB_OWNER . '/' . G_APP_GITHUB_REPO);

View File

@ -254,6 +254,7 @@ try {
],
'1.1.1' => NULL,
'1.1.2' => NULL,
'1.1.3' => NULL,
];
// Settings that must be renamed from NAME to NEW NAME and DELETE old NAME
$settings_rename = [];

View File

@ -16,14 +16,12 @@
namespace G;
if (!defined('access') or !access) {
die("This file cannot be directly accessed.");
}
if(!defined('access') or !access) die("This file cannot be directly accessed.");
define('G_VERSION', '1.0.42');
// Error reporting setup
@ini_set('log_errors', true);
@ini_set('log_errors', TRUE);
error_reporting(E_ALL ^ E_NOTICE);
// Set default locale
@ -33,7 +31,7 @@ setlocale(LC_ALL, 'en_US.UTF8');
@ini_set('default_charset', 'utf-8');
// Set G\ paths and files
define('G_ROOT_PATH', rtrim(str_replace('\\', '/', dirname(dirname(__DIR__))), '/') . '/');
define('G_ROOT_PATH', rtrim(str_replace('\\','/', dirname(dirname(__DIR__))), '/') . '/');
define('G_ROOT_PATH_RELATIVE', rtrim(dirname($_SERVER['SCRIPT_NAME']), '\/') . '/');
define('G_ROOT_LIB_PATH', G_ROOT_PATH . 'lib/');
define('G_PATH', G_ROOT_LIB_PATH . 'G/');
@ -54,75 +52,65 @@ define('G_APP_SETTINGS_FILE_ERROR', '<br />There are errors in the <strong>%%FIL
// Include the static app config file
(file_exists(G_APP_PATH . 'settings.php')) ? require_once(G_APP_PATH . 'settings.php') : die("G\: Can't find app/settings.php");
if (headers_sent()) {
die(str_replace('%%FILE%%', 'app/settings.php', G_APP_SETTINGS_FILE_ERROR));
} // Stop on premature headers
if(headers_sent()) die(str_replace('%%FILE%%', 'app/settings.php', G_APP_SETTINGS_FILE_ERROR)); // Stop on premature headers
// TZ failover
$tz = @date_default_timezone_get();
$dtz = @date_default_timezone_set($tz);
if (!$dtz && !@date_default_timezone_set('America/Santiago')) {
if(!$dtz && !@date_default_timezone_set('America/Santiago')) {
die(strtr('Invalid timezone identifier: %i. Configure php.ini with a valid timezone identifier %l', ['%i' => $tz, '%l' => 'http://php.net/manual/en/timezones.php']));
}
// Session hack
if ($settings['session.save_path']) {
if($settings['session.save_path']) {
session_save_path($settings['session.save_path']);
}
// Can work with sessions?
if (!@session_start()) {
die("G\: Sessions are not working on this server (session_start).");
}
if(!@session_start()) die("G\: Sessions are not working on this server (session_start).");
// Is session save path OK? (you won't believe how many people has session issues!)
$session_save_path = @realpath(session_save_path());
if ($session_save_path) { // realpath on this needs pre-webroot directories access
foreach (['write'] as $k) {
if($session_save_path) { // realpath on this needs pre-webroot directories access
foreach(['write'] as $k) {
$fn = 'is_' . $k . 'able';
if (!$fn($session_save_path)) {
$session_errors[] = $k;
}
}
if (isset($session_errors)) {
die(strtr("G\: Sessions are not working on this server due to missing %s permission on session save path (%f session.save_path).", ['%s' => implode('/', $session_errors), '%f' => $settings['session.save_path'] ? 'app/settings.php' : 'php.ini']));
if(!$fn($session_save_path)) $session_errors[] = $k;
}
if(isset($session_errors)) die(strtr("G\: Sessions are not working on this server due to missing %s permission on session save path (%f session.save_path).", ['%s' => implode('/', $session_errors), '%f' => $settings['session.save_path'] ? 'app/settings.php' : 'php.ini']));
}
// Are sessions working properly?
$_SESSION['G'] = true;
if (!$_SESSION['G']) {
die("G\: Sessions are not working properly. Check for any conflicting server setting.");
}
$_SESSION['G'] = TRUE;
if(!$_SESSION['G']) die("G\: Sessions are not working properly. Check for any conflicting server setting.");
// Set the starting execution time
define('G_APP_TIME_EXECUTION_START', microtime(true));
// Include G\ core functions
(file_exists(__DIR__ . '/functions.php')) ? require_once(__DIR__ . '/functions.php') : die("G\: Can't find <strong>" . __DIR__ . '/functions.php' . '</strong>. Make sure that this file exists.');
if (file_exists(__DIR__ . '/functions.render.php')) {
if(file_exists(__DIR__ . '/functions.render.php')) {
require_once(__DIR__ . '/functions.render.php');
}
if (isset($settings) && $settings['error_reporting'] === false) {
if(isset($settings) && $settings['error_reporting'] === false) {
error_reporting(0);
}
// Set the default timezone
if (isset($settings['default_timezone']) && is_valid_timezone($settings['default_timezone'])) {
if (!@date_default_timezone_set($settings['default_timezone'])) {
if(isset($settings['default_timezone']) && is_valid_timezone($settings['default_timezone'])) {
if(!@date_default_timezone_set($settings['default_timezone'])) {
die(strtr("G\: Can't set %s timezone on line %l", ['%s' => $settings['default_timezone'], '%l' => __LINE__ - 1]));
}
}
// Set the system environment
if (isset($settings['environment'])) {
if(isset($settings['environment'])) {
define('G_APP_ENV', $settings['environment']);
}
// Set the HTTP definitions
define('G_HTTP_HOST', $_SERVER['HTTP_HOST']);
define('G_HTTP_PROTOCOL', 'http' . ((((!empty($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) == 'on') || $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https') || $settings['https']) ? 's' : null));
define('G_HTTP_PROTOCOL', 'http' . ((((!empty($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) == 'on' ) || $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https') || $settings['https']) ? 's' : NULL));
// La cumbia me divierte y mesita
@ -130,23 +118,23 @@ define('G_HTTP_PROTOCOL', 'http' . ((((!empty($_SERVER['HTTPS']) && strtolower($
$_SERVER['SCRIPT_FILENAME'] = forward_slash($_SERVER['SCRIPT_FILENAME']);
$_SERVER['SCRIPT_NAME'] = forward_slash($_SERVER['SCRIPT_NAME']);
// Fix CloudFlare REMOTE_ADDR
if (isset($_SERVER['HTTP_CF_CONNECTING_IP'])) {
if(isset($_SERVER['HTTP_CF_CONNECTING_IP'])) {
$_SERVER['REMOTE_ADDR'] = $_SERVER['HTTP_CF_CONNECTING_IP'];
}
// Inherit application definitions
if (file_exists(G_APP_PATH . 'app.php')) {
if(file_exists(G_APP_PATH . 'app.php')) {
require_once(G_APP_PATH . 'app.php');
}
// Set the DB constants
foreach (['host', 'port', 'name', 'user', 'pass', 'driver', 'pdo_attrs'] as $k) {
define('G_APP_DB_' . strtoupper($k), isset($settings['db_' . $k]) ? (is_array($settings['db_' . $k]) ? serialize($settings['db_' . $k]) : $settings['db_' . $k]) : null);
foreach(['host', 'port', 'name', 'user', 'pass', 'driver', 'pdo_attrs'] as $k) {
define('G_APP_DB_' . strtoupper($k), isset($settings['db_' . $k]) ? (is_array($settings['db_' . $k]) ? serialize($settings['db_' . $k]) : $settings['db_' . $k]) : NULL);
}
// Include app functions
(file_exists(G_APP_FILE_FUNCTIONS)) ? require_once(G_APP_FILE_FUNCTIONS) : die("G\: Can't find <strong>" . G_APP_FILE_FUNCTIONS . '</strong>. Make sure that this file exists.');
if (file_exists(G_APP_FILE_FUNCTIONS_RENDER)) {
if(file_exists(G_APP_FILE_FUNCTIONS_RENDER)) {
require_once(G_APP_FILE_FUNCTIONS_RENDER);
}
@ -157,11 +145,11 @@ define("G_APP_LIB_URL", absolute_to_url(G_APP_PATH_LIB));
// Define the app theme
define('G_APP_PATH_THEMES', G_APP_PATH . 'themes/');
if (!file_exists(G_APP_PATH_THEMES)) {
if(!file_exists(G_APP_PATH_THEMES)) {
die("G\: Theme path doesn't exists!");
}
if (isset($settings['theme']) and file_exists(G_APP_PATH_THEMES . $settings['theme'])) {
if(isset($settings['theme']) and file_exists(G_APP_PATH_THEMES . $settings['theme'])) {
define('G_APP_PATH_THEME', G_APP_PATH_THEMES . $settings['theme'].'/');
define('BASE_URL_THEME', absolute_to_url(G_APP_PATH_THEME));
}

View File

@ -20,13 +20,10 @@
*/
namespace G;
use PDO, PDOException, Exception;
use PDO;
use PDOException;
use Exception;
class DB {
class DB
{
private static $instance;
private $host = G_APP_DB_HOST;
@ -37,39 +34,39 @@ class DB
private $driver = G_APP_DB_DRIVER;
private $pdo_attrs = G_APP_DB_PDO_ATTRS;
public static $dbh;
static $dbh;
public $query;
/**
* Connect to the DB server
* Throws an Exception on error (tay weando? en serio?)
*/
public function __construct($conn=[])
{
public function __construct($conn=[]) {
try {
// PDO already connected
if (empty($conn) and isset(self::$dbh) and get_class(self::$dbh) == 'PDO') {
return true;
if(empty($conn) and isset(self::$dbh) and get_class(self::$dbh) == 'PDO') {
return TRUE;
}
if (!empty($conn)) {
if(!empty($conn)) {
// Inject connection info
foreach (['host', 'user', 'name', 'pass', 'port', 'driver', 'pdo_attrs'] as $k) {
foreach(['host', 'user', 'name', 'pass', 'port', 'driver', 'pdo_attrs'] as $k) {
$this->{$k} = $conn[$k];
}
}
$pdo_connect = $this->driver . ':host=' . $this->host . ';dbname=' . $this->name;
if ($this->port) {
if($this->port) {
$pdo_connect .= ';port=' . $this->port;
}
// $pdo_connect .= ';charset=UTF8';
$this->pdo_attrs = @unserialize($this->pdo_attrs) ?: $this->pdo_attrs;
// PDO defaults
$this->pdo_default_attrs = [
PDO::ATTR_TIMEOUT => 30,
//PDO::ATTR_PERSISTENT => FALSE
];
// Override PDO defaults ?
@ -77,7 +74,7 @@ class DB
// PDO hard overrides
$this->pdo_attrs[PDO::ATTR_ERRMODE] = PDO::ERRMODE_EXCEPTION;
$this->pdo_attrs[PDO::MYSQL_ATTR_INIT_COMMAND] = "SET time_zone = '+00:00', NAMES 'UTF8'"; // UTC for timestamps
$this->pdo_attrs[PDO::MYSQL_ATTR_INIT_COMMAND] = "SET NAMES 'UTF8'";
// Turn off PHP error reporting just for the connection here (invalid host names will trigger a PHP warning)
$error_reporting = error_reporting();
@ -90,24 +87,25 @@ class DB
error_reporting($error_reporting);
// PDO emulate prepares if needed
if (version_compare(self::$dbh->getAttribute(PDO::ATTR_SERVER_VERSION), '5.1.17', '<')) {
if(version_compare(self::$dbh->getAttribute(PDO::ATTR_SERVER_VERSION), '5.1.17', '<')) {
self::$dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, true);
}
self::$instance = $this;
} catch (Exception $e) {
self::$dbh = null;
} catch(Exception $e) {
self::$dbh = NULL;
throw new DBException($e->getMessage(), 400);
}
}
/**
* Singleton instance handler
* Used for the static methods of this class
*/
public static function getInstance()
{
if (is_null(self::$instance)) {
public static function getInstance() {
if(is_null(self::$instance)) {
self::$instance = new self;
}
return self::$instance;
@ -117,8 +115,7 @@ class DB
* Populates the class DB own PDO attributes array with an entire array
* Attribute list here: http://php.net/manual/en/pdo.setattribute.php
*/
public function setPDOAttrs($attributes)
{
public function setPDOAttrs($attributes) {
$this->pdo_attrs = $attributes;
}
@ -126,13 +123,11 @@ class DB
* Populates the class DB own PDO attributes array with a single key
* Attributes list here: http://php.net/manual/en/pdo.setattribute.php
*/
public function setPDOAttr($key, $value)
{
public function setPDOAttr($key, $value) {
$this->pdo_attrs[$key] = $value;
}
public function getAttr($attr)
{
public function getAttr($attr) {
return self::$dbh->getAttribute($attr);
}
@ -140,13 +135,11 @@ class DB
* Prepares an SQL statement to be executed by the PDOStatement::execute() method
* http://php.net/manual/en/pdo.prepare.php
*/
public function query($query)
{
public function query($query) {
$this->query = self::$dbh->prepare($query);
}
public function errorInfo()
{
public function errorInfo() {
return self::$dbh->errorInfo();
}
@ -154,10 +147,9 @@ class DB
* Binds a value to a corresponding named or question mark placeholder in the SQL statement that was used to prepare the statement
* http://php.net/manual/en/pdostatement.bindvalue.php
*/
public function bind($param, $value, $type = null)
{
if (is_null($type)) {
switch (true) {
public function bind($param, $value, $type = null) {
if(is_null($type)) {
switch(true) {
case is_int($value):
$type = PDO::PARAM_INT;
break;
@ -175,23 +167,19 @@ class DB
$this->query->bindValue($param, $value, $type);
}
public function exec()
{
public function exec() {
return $this->query->execute();
}
public function fetchColumn()
{
public function fetchColumn() {
return $this->query->fetchColumn();
}
public function closeCursor()
{
public function closeCursor() {
return $this->query->closeCursor();
}
public function fetchAll($mode=PDO::FETCH_ASSOC)
{
public function fetchAll($mode=PDO::FETCH_ASSOC) {
$this->exec();
return $this->query->fetchAll(is_int($mode) ? $mode : PDO::FETCH_ASSOC);
}
@ -200,8 +188,7 @@ class DB
* Execute and returns the single result from the prepared statement
* http://php.net/manual/en/pdostatement.fetch.php
*/
public function fetchSingle($mode=PDO::FETCH_ASSOC)
{
public function fetchSingle($mode=PDO::FETCH_ASSOC) {
$this->exec();
return $this->query->fetch(is_int($mode) ? $mode : PDO::FETCH_ASSOC);
}
@ -209,13 +196,12 @@ class DB
/**
* Query and exec, return number of affected rows or FALSE
*/
public static function queryExec($query)
{
public static function queryExec($query) {
try {
$db = self::getInstance();
$db->query($query);
return $db->exec() ? $db->rowCount() : false;
} catch (Exception $e) {
return $db->exec() ? $db->rowCount() : FALSE;
} catch(Exception $e) {
throw new DBException($e->getMessage(), 400);
}
}
@ -223,11 +209,10 @@ class DB
/**
* Query and fetch single record
*/
public static function queryFetchSingle($query, $fetch_style=null)
{
public static function queryFetchSingle($query, $fetch_style=NULL) {
try {
return self::queryFetch($query, 1, $fetch_style);
} catch (Exception $e) {
} catch(Exception $e) {
throw new DBException($e->getMessage(), 400);
}
}
@ -235,11 +220,10 @@ class DB
/**
* Query and fetch all records
*/
public static function queryFetchAll($query, $fetch_style=null)
{
public static function queryFetchAll($query, $fetch_style=NULL) {
try {
return self::queryFetch($query, null, $fetch_style);
} catch (Exception $e) {
return self::queryFetch($query, NULL, $fetch_style);
} catch(Exception $e) {
throw new DBException($e->getMessage(), 400);
}
}
@ -247,13 +231,12 @@ class DB
/**
* Query fetch (core version)
*/
public static function queryFetch($query, $limit=1, $fetch_style=null)
{
public static function queryFetch($query, $limit=1, $fetch_style=NULL) {
try {
$db = self::getInstance();
$db->query($query);
return $limit == 1 ? $db->fetchSingle($fetch_style) : $db->fetchAll($fetch_style);
} catch (Exception $e) {
} catch(Exception $e) {
throw new DBException($e->getMessage(), 400);
}
}
@ -262,8 +245,7 @@ class DB
* Returns the number of rows affected by the last DELETE, INSERT, or UPDATE statement executed
* http://php.net/manual/en/pdostatement.rowcount.php
*/
public function rowCount()
{
public function rowCount() {
return $this->query->rowCount();
}
@ -271,8 +253,7 @@ class DB
* Returns the ID of the last inserted row, or the last value from a sequence object, depending on the underlying driver
* http://php.net/manual/en/pdo.lastinsertid.php
*/
public function lastInsertId()
{
public function lastInsertId() {
return self::$dbh->lastInsertId();
}
@ -280,8 +261,7 @@ class DB
* Turns off autocommit mode
* http://php.net/manual/en/pdo.begintransaction.php
*/
public function beginTransaction()
{
public function beginTransaction(){
return self::$dbh->beginTransaction();
}
@ -289,8 +269,7 @@ class DB
* Commits a transaction, returning the database connection to autocommit mode until the next call to PDO::beginTransaction() starts a new transaction
* http://php.net/manual/en/pdo.commit.php
*/
public function endTransaction()
{
public function endTransaction(){
return self::$dbh->commit();
}
@ -298,8 +277,7 @@ class DB
* Rolls back the current transaction, as initiated by PDO::beginTransaction()
* http://php.net/manual/en/pdo.rollback.php
*/
public function cancelTransaction()
{
public function cancelTransaction(){
return self::$dbh->rollBack();
}
@ -307,8 +285,7 @@ class DB
* Dumps the informations contained by a prepared statement directly on the output
* http://php.net/manual/en/pdostatement.debugdumpparams.php
*/
public function debugDumpParams()
{
public function debugDumpParams(){
return $this->query->debugDumpParams();
}
@ -317,23 +294,22 @@ class DB
/**
* Get the table with its prefix
*/
public static function getTable($table)
{
public static function getTable($table) {
return get_app_setting('db_table_prefix') . $table;
}
/**
* Get values from DB
*/
public static function get($table, $values, $clause='AND', $sort=[], $limit=null, $fetch_style=null)
{
if (!is_array($values) and $values !== 'all') {
public static function get($table, $values, $clause='AND', $sort=[], $limit=NULL, $fetch_style=NULL) {
if(!is_array($values) and $values !== 'all') {
throw new DBException('Expecting array values, '.gettype($values).' given in ' . __METHOD__, 100);
}
self::validateClause($clause, __METHOD__);
if (is_array($table)) {
if(is_array($table)) {
$join = $table['join'];
$table = $table['table'];
}
@ -342,14 +318,14 @@ class DB
$query = 'SELECT * FROM '.$table;
if ($join) {
if($join) {
$query .= ' ' . $join . ' ';
}
if (is_array($values) and !empty($values)) {
if(is_array($values) and !empty($values)) {
$query .= ' WHERE ';
foreach ($values as $k => $v) {
if (is_null($v)) {
foreach($values as $k => $v) {
if(is_null($v)) {
$query .= '`'.$k.'` IS :'.$k.' '.$clause.' ';
} else {
$query .= '`'.$k.'`=:'.$k.' '.$clause.' ';
@ -359,30 +335,30 @@ class DB
$query = rtrim($query, $clause . ' ');
if (is_array($sort) and !empty($sort)) {
if (!$sort['field']) {
if(is_array($sort) and !empty($sort)) {
if(!$sort['field']) {
$sort['field'] = 'date';
}
if (!$sort['order']) {
if(!$sort['order']) {
$sort['order'] = 'desc';
}
$query .= ' ORDER BY '.$sort['field'].' '.strtoupper($sort['order']).' ';
}
if ($limit and is_int($limit)) {
if($limit and is_int($limit)) {
$query .= " LIMIT $limit";
}
try {
$db = self::getInstance();
$db->query($query);
if (is_array($values)) {
foreach ($values as $k => $v) {
if(is_array($values)) {
foreach($values as $k => $v) {
$db->bind(':'.$k, $v);
}
}
return $limit == 1 ? $db->fetchSingle($fetch_style) : $db->fetchAll($fetch_style);
} catch (Exception $e) {
} catch(Exception $e) {
throw new DBException($e->getMessage(), 400);
}
}
@ -391,12 +367,12 @@ class DB
* Update target table row(s)
* Returns the number of affected rows or false
*/
public static function update($table, $values, $wheres, $clause='AND')
{
if (!is_array($values)) {
public static function update($table, $values, $wheres, $clause='AND') {
if(!is_array($values)) {
throw new DBException('Expecting array values, '.gettype($values).' given in '. __METHOD__, 100);
}
if (!is_array($wheres)) {
if(!is_array($wheres)) {
throw new DBException('Expecting array values, '.gettype($wheres).' given in '. __METHOD__, 100);
}
@ -407,13 +383,13 @@ class DB
$query = 'UPDATE `'.$table.'` SET ';
// Set the value pairs
foreach ($values as $k => $v) {
foreach($values as $k => $v) {
$query .= '`' . $k . '`=:value_' . $k . ',';
}
$query = rtrim($query, ',') . ' WHERE ';
// Set the where pairs
foreach ($wheres as $k => $v) {
foreach($wheres as $k => $v) {
$query .= '`'.$k.'`=:where_'.$k.' '.$clause.' ';
}
$query = rtrim($query, $clause.' ');
@ -423,32 +399,33 @@ class DB
$db->query($query);
// Bind the values
foreach ($values as $k => $v) {
foreach($values as $k => $v) {
$db->bind(':value_'.$k, $v);
}
foreach ($wheres as $k => $v) {
foreach($wheres as $k => $v) {
$db->bind(':where_'.$k, $v);
}
return $db->exec() ? $db->rowCount() : false;
} catch (Exception $e) {
return $db->exec() ? $db->rowCount() : FALSE;
} catch(Exception $e) {
throw new DBException($e->getMessage(), 400);
}
}
/**
* Insert single row to the table
*/
public static function insert($table, $values)
{
if (!is_array($values)) {
public static function insert($table, $values) {
if(!is_array($values)) {
throw new DBException('Expecting array values, '.gettype($values).' given in '. __METHOD__, 100);
}
$table = DB::getTable($table);
$table_fields = [];
foreach ($values as $k => $v) {
foreach($values as $k => $v) {
$table_fields[] = $k;
}
@ -459,13 +436,14 @@ class DB
try {
$db = self::getInstance();
$db->query($query);
foreach ($values as $k => $v) {
foreach($values as $k => $v) {
$db->bind(':'.$k, $v);
}
return $db->exec() ? $db->lastInsertId() : false;
} catch (Exception $e) {
return $db->exec() ? $db->lastInsertId() : FALSE;
} catch(Exception $e) {
throw new DBException($e->getMessage(), 400);
}
}
/**
@ -473,10 +451,10 @@ class DB
* Returns the number of affected rows or false
* Note: Minimum value to be set is zero, no negative values here
*/
public static function increment($table, $values, $wheres, $clause='AND')
{
foreach (['values', 'wheres'] as $k) {
if (!is_array(${$k})) {
public static function increment($table, $values, $wheres, $clause='AND') {
foreach(['values', 'wheres'] as $k) {
if(!is_array(${$k})) {
throw new DBException('Expecting array values, '.gettype(${$k}).' given in '. __METHOD__, 100);
}
}
@ -484,13 +462,13 @@ class DB
$table = DB::getTable($table);
$query = 'UPDATE `'.$table.'` SET ';
foreach ($values as $k => $v) {
if (preg_match('/^([+-]{1})\s*([\d]+)$/', $v, $matches)) { // 1-> op 2-> number
foreach($values as $k => $v) {
if(preg_match('/^([+-]{1})\s*([\d]+)$/', $v, $matches)) { // 1-> op 2-> number
$query .= '`' . $k . '`=';
if ($matches[1] == '+') {
if($matches[1] == '+') {
$query .= '`' . $k . '`' . $matches[1] . $matches[2] . ',';
}
if ($matches[1] == '-') {
if($matches[1] == '-') {
$query .= 'GREATEST(cast(`'.$k.'` AS SIGNED) - '.$matches[2].', 0),';
}
}
@ -499,7 +477,7 @@ class DB
$query = rtrim($query, ',') . ' WHERE ';
// Set the where pairs
foreach ($wheres as $k => $v) {
foreach($wheres as $k => $v) {
$query .= '`'.$k.'`=:where_'.$k.' '.$clause.' ';
}
$query = rtrim($query, $clause.' ');
@ -507,22 +485,23 @@ class DB
try {
$db = self::getInstance();
$db->query($query);
foreach ($wheres as $k => $v) {
foreach($wheres as $k => $v) {
$db->bind(':where_'.$k, $v);
}
return $db->exec() ? $db->rowCount() : false;
} catch (Exception $e) {
} catch(Exception $e) {
throw new DBException($e->getMessage(), 400);
}
}
/**
* Delete row(s) from table
* Returns the number of affected rows or false
*/
public static function delete($table, $values, $clause='AND')
{
if (!is_array($values)) {
public static function delete($table, $values, $clause='AND') {
if(!is_array($values)) {
throw new DBException('Expecting array values, '.gettype($values).' given in '. __METHOD__, 100);
}
@ -532,7 +511,7 @@ class DB
$query = 'DELETE FROM `'.$table.'` WHERE ';
$table_fields = array();
foreach ($values as $k => $v) {
foreach($values as $k => $v) {
$query .= '`'.$k.'`=:'.$k.' '.$clause.' ';
}
$query = rtrim($query, $clause.' ');
@ -540,30 +519,29 @@ class DB
try {
$db = self::getInstance();
$db->query($query);
foreach ($values as $k => $v) {
foreach($values as $k => $v) {
$db->bind(':'.$k, $v);
}
return $db->exec() ? $db->rowCount() : false;
} catch (Exception $e) {
return $db->exec() ? $db->rowCount() : FALSE;
} catch(Exception $e) {
throw new DBException($e->getMessage(), 400);
}
}
/**
* Validate clause
*/
private static function validateClause($clause, $method=null)
{
if (!is_null($clause)) {
private static function validateClause($clause, $method=NULL) {
if(!is_null($clause)) {
$clause = strtoupper($clause);
if (!in_array($clause, ['AND', 'OR'])) {
if(!in_array($clause, ['AND', 'OR'])) {
throw new DBException('Expecting clause string \'AND\' or \'OR\' in ' . (!is_null($method) ? $method : __CLASS__), 100);
}
}
}
}
// DB class own Exception
class DBException extends Exception
{
}
class DBException extends Exception {}

View File

@ -20,35 +20,24 @@
*/
namespace G;
use Exception;
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;
class Handler {
public static $route, $route_request, $route_name, $base_request, $doctitle, $vars, $conds, $routes, $template_used, $prevented_route, $mapped_args;
/**
* Build a valid request
*/
public function __construct($hook=[])
{
if (!defined('G_APP_PATH_THEME')) {
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->base_url = G_ROOT_URL;
$this->path_theme = G_APP_PATH_THEME;
// Parse the request
@ -57,29 +46,29 @@ class Handler
$query_string = '?' . $_SERVER['QUERY_STRING'];
if (!empty($_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'])) {
if(!empty($_SERVER['QUERY_STRING'])) {
$this->request_uri = $_SERVER['REQUEST_URI'];
$this->valid_request .= /*'/' .*/ $query_string;
$this->valid_request .= '/' . $query_string;
}
// Store the canonical request, used for redirect to a valid request
// Store the canonical request, useful for redirect to a valid request
$this->canonical_request = $this->valid_request;
if (is_dir(G_ROOT_PATH . $this->valid_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->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] == '') {
if($this->request_array[0] == '') {
$this->request_array[0] = '/';
}
@ -87,29 +76,29 @@ class Handler
self::$base_request = $this->request_array[0];
// Reserved route (index)
if (self::$base_request == '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'])) {
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') {
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) {
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', '/'])) {
if(in_array(self::$base_request, ['', 'index.php', '/'])) {
self::$base_request = 'index';
}
@ -123,59 +112,55 @@ class Handler
$this->request = array_values($this->request);
// Hook a fn BEFORE the process
if (is_array($hook) and is_callable($hook['before'])) {
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();
}
if($this->isIndex()) $this->processRequest();
// Hook a fn AFTER the process
if (is_array($hook) and is_callable($hook['after'])) {
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) {
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) {
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;
}
private static function routeIterator($path) {
foreach (new \DirectoryIterator($path) as $fileInfo) {
if ($fileInfo->isDot() or $fileInfo->isDir()) {
continue;
}
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)) {
if(file_exists($route_override)) {
$route_file = $route_override;
}
if (file_exists($route_file)) {
if(file_exists($route_file)) {
require_once($route_file);
$route = array(substr(substr($fileInfo->getFilename(), 0, -4), 6) => $route);
self::$routes += $route;
@ -187,8 +172,7 @@ class Handler
* Stock (save) the valid routes of the G\ app
* This method is optional because the routeIterator takes some memory
*/
public static function stockRoutes()
{
public static function stockRoutes() {
self::$routes = [];
self::routeIterator(G_APP_PATH_ROUTES);
self::routeIterator(G_APP_PATH_ROUTES_OVERRIDES);
@ -197,68 +181,69 @@ class Handler
/**
* Process the dynamic request
*/
private function processRequest()
{
if (is_null(self::$routes)) { // Route array is not set
private function processRequest() {
if(is_null(self::$routes)) { // Route array is not set
$route = $this->getRouteFn(self::$base_request);
if (is_callable($route)) {
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)) {
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,
'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) {
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])) {
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) {
if($this->template == 404) {
self::$route = 404;
}
self::setCond('404', $this->template == 404); // is_404 binding
if (self::$vars['pre_doctitle']) {
if(self::$vars['pre_doctitle']) {
$stock_doctitle = self::$vars['doctitle'];
self::$vars['doctitle'] = self::$vars['pre_doctitle'];
if ($stock_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)
{
public function bindGetFn($var, $value) {
$fn_name = strtolower(str_replace('-', '_', $var));
if (!function_exists('get_' . $fn_name)) {
if(!function_exists('get_' . $fn_name)) {
eval('function get_' . $fn_name . '(){ return G\Handler::$vars["' . $var . '"]; }');
}
}
@ -266,10 +251,9 @@ class Handler
/**
* Bind route conditional to global functions
*/
public function bindIsFn($var, $value)
{
public function bindIsFn($var, $value) {
$fn_name = strtolower(str_replace('-', '_', $var));
if (!function_exists('is_' . $fn_name)) {
if(!function_exists('is_' . $fn_name)) {
eval('function is_' . $fn_name . '(){ return G\Handler::$conds["' . $var . '"]; }');
}
}
@ -277,23 +261,20 @@ class Handler
/**
* Inject the 404 page
*/
public function issue404()
{
public function issue404() {
set_status_header(404);
if ($this->getCond('mapped_route')) {
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) {
public function preventRoute($tpl=NULL) {
if($tpl) {
$this->template = $tpl;
}
self::$prevented_route = true;
@ -303,20 +284,19 @@ class Handler
* 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)
{
public function getRouteFn($route_name) {
// Route is already in the stack
if (is_array(self::$routes) and array_key_exists($route_name, Handler::$routes)) {
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)) {
if(file_exists($route_override_file)) {
$route_file = $route_override_file;
}
if (file_exists($route_file)) {
if(file_exists($route_file)) {
require($route_file);
// Append this new route fn to the Handler::$routes stack
self::$routes[$route_name] = $route;
@ -330,12 +310,11 @@ class Handler
/**
* Maps the current route which is useful to make route aliases
*/
public function mapRoute($route_name, $args=null)
{
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)) {
if(!is_null($args)) {
self::$mapped_args = $args;
}
return $this->getRouteFn($route_name);
@ -344,16 +323,14 @@ class Handler
/**
* Return (bool) the request level of the current request
*/
public function isRequestLevel($level)
{
public function isRequestLevel($level) {
return isset($this->request_array[$level - 1]);
}
/**
* Redirect to the base url/request
*/
public function baseRedirection($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);
@ -362,8 +339,7 @@ class Handler
/**
* Return (bool) if the request is handled by index.php
*/
private function isIndex()
{
private function isIndex() {
return preg_match('{/index.php$}', $this->script_name);
}
@ -371,10 +347,9 @@ class Handler
* Hook code for loadTemplate()
* @args ['code' => '<code>', 'where' => 'before|after']
*/
public function hookTemplate($args=[])
{
if (in_array($args['where'], ['before', 'after']) and $args['code']) {
if (!isset($this->hook_template)) {
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'];
@ -384,9 +359,8 @@ class Handler
/**
* load the setted (or argument) template view
*/
private function loadTemplate($template=null)
{
if (!is_null($template)) {
private function loadTemplate($template=NULL) {
if(!is_null($template)) {
$this->template = $template;
}
@ -397,8 +371,8 @@ class Handler
$this->path_theme . 'overrides/' . $functions_basename,
$this->path_theme . $functions_basename
];
foreach ($template_functions as $file) {
if (file_exists($file)) {
foreach($template_functions as $file) {
if(file_exists($file)) {
require_once($file);
break;
}
@ -406,7 +380,7 @@ class Handler
$view_basename = $this->template;
$view_extension = get_file_extension($this->template);
if (!$view_extension) {
if(!$view_extension) {
$view_extension = 'php';
$view_basename .= '.php';
}
@ -416,23 +390,23 @@ class Handler
$this->path_theme . 'views/'. $view_basename,
$this->path_theme . $view_basename,
];
foreach ($template_file as $file) {
if (file_exists($file)) {
if ($view_extension == 'html') {
foreach($template_file as $file) {
if(file_exists($file)) {
if($view_extension == 'html') {
Render\include_theme_header();
}
if ($this->hook_template['before']) {
if($this->hook_template['before']) {
echo $this->hook_template['before'];
}
if ($view_extension == 'php') {
if($view_extension == 'php') {
require_once($file);
} else {
echo file_get_contents($file);
}
if ($this->hook_template['after']) {
if($this->hook_template['after']) {
echo $this->hook_template['after'];
}
if ($view_extension == 'html') {
if($view_extension == 'html') {
Render\include_theme_footer();
}
return;
@ -448,8 +422,7 @@ class Handler
/**
* Returns the 40 char length safe request token
*/
public static function getAuthToken()
{
public static function getAuthToken() {
$token = isset($_SESSION['G_auth_token']) ? $_SESSION['G_auth_token'] : random_string(40);
$_SESSION['G_auth_token'] = $token;
return $token;
@ -458,28 +431,23 @@ class Handler
/**
* Checks the integrity and validation of the given request token
*/
public static function checkAuthToken($token)
{
if (strlen($token) < 40) {
return false;
}
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)
{
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) {
public static function setVars($array) {
foreach((array)$array as $var => $value) {
self::$vars[$var] = $value;
}
}
@ -487,17 +455,15 @@ class Handler
/**
* Sets a Handler::$conds -> is_cond() binding
*/
public static function setCond($conds, $bool)
{
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) {
public static function setConds($array=[]) {
foreach((array)$array as $conds => $bool) {
self::$conds[$conds] = !$bool ? false : true;
}
}
@ -505,41 +471,36 @@ class Handler
/**
* Get a Handler::$vars[var]
*/
public static function getVar($var)
{
public static function getVar($var) {
return self::getVars()[$var];
}
/**
* Get all Handler::$vars
*/
public static function getVars()
{
public static function getVars() {
return self::$vars;
}
/**
* Get a Handler::$condss[cond]
*/
public static function getCond($cond)
{
public static function getCond($cond) {
return self::getConds()[$cond];
}
/**
* Get all Handler::$conds
*/
public static function getConds()
{
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)) {
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);
@ -550,16 +511,14 @@ class Handler
/**
* Unset a given var
*/
public static function unsetVar($var)
{
public static function unsetVar($var) {
unset(self::$vars[$var]);
}
/**
* Get the template file basename used
*/
public static function getTemplateUsed()
{
public static function getTemplateUsed() {
return self::$template_used;
}
@ -567,9 +526,8 @@ class Handler
* 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)) {
public static function getRoutePath($full=true) {
if(is_array(self::$route)) {
return $full ? implode('/', self::$route) : self::$route[0];
} else {
return self::$route;
@ -579,12 +537,10 @@ class Handler
/**
* Get the current route name from route.name.php
*/
public static function getRouteName()
{
public static function getRouteName() {
return self::$route_name;
}
}
class HandlerException extends Exception
{
}
class HandlerException extends Exception {}

View File

@ -310,12 +310,9 @@ namespace G {
*/
function abbreviate_number($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) {
@ -563,7 +560,7 @@ namespace G {
function exception_to_error($e, $die=true)
{
$internal_code = 500;
$internal_error = '<b>Aw, snap!</b> ' . get_set_status_header_desc($internal_code) . ' - Check your error_log or enable debug_mode = 3 (chevereto.com/docs/debug).';
$internal_error = '<b>'.G_APP_NAME.' error:</b> ' . get_set_status_header_desc($internal_code);
set_status_header($internal_code);
@ -819,20 +816,18 @@ namespace G {
function get_client_ip()
{
if(isset($_SERVER['G_CLIENT_IP'])) {
return $_SERVER['G_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['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']) {
if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
$entries = preg_split('/[\s,]/', $_SERVER['HTTP_X_FORWARDED_FOR'], -1, PREG_SPLIT_NO_EMPTY);
reset($entries);
foreach ($entries as $entry) {
while (list(, $entry) = each($entries)) {
$entry = trim($entry);
if (preg_match('/^([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)/', $entry, $ip_list)) {
$private_ip = array(
@ -843,6 +838,7 @@ 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;
@ -850,7 +846,7 @@ namespace G {
}
}
}
$_SERVER['G_CLIENT_IP'] = $client_ip;
return $client_ip;
}
@ -1133,23 +1129,6 @@ 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)
@ -1459,7 +1438,7 @@ namespace G {
function relative_to_url($filepath, $root_url=null)
{
if (!check_value($root_url)) {
$root_url = get_root_url();
$root_url = G_ROOT_URL;
}
return str_replace(G_ROOT_PATH_RELATIVE, $root_url, forward_slash($filepath));
}
@ -1468,7 +1447,7 @@ namespace G {
function url_to_relative($url, $root_url=null)
{
if (!check_value($root_url)) {
$root_url = get_root_url();
$root_url = G_ROOT_URL;
}
return str_replace($root_url, G_ROOT_PATH_RELATIVE, $url);
}
@ -1483,7 +1462,7 @@ namespace G {
function absolute_to_url($filepath, $root_url=null)
{
if (!check_value($root_url)) {
$root_url = get_root_url();
$root_url = G_ROOT_URL;
}
if (G_ROOT_PATH === G_ROOT_PATH_RELATIVE) {
return $root_url . ltrim($filepath, '/');
@ -1495,7 +1474,7 @@ namespace G {
function url_to_absolute($url, $root_url=null)
{
if (!check_value($root_url)) {
$root_url = get_root_url();
$root_url = G_ROOT_URL;
}
return str_replace($root_url, G_ROOT_PATH, $url);
}
@ -1529,43 +1508,21 @@ namespace G {
return get_global('settings')[$key];
}
function get_domain()
{
return HTTP_HOST;
}
function get_base_url($path='')
{
$path = sanitize_relative_path($path);
$return = get_root_url() . ltrim($path, '/');
$return = G_ROOT_URL . ltrim($path, '/');
return rtrim($return, '/');
}
function get_host()
function get_current_url()
{
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);
return get_base_url(preg_replace('#'.G_ROOT_PATH_RELATIVE.'#', '', $_SERVER['REQUEST_URI'], 1));
}
function settings_has_db_info()
@ -1937,26 +1894,9 @@ namespace G {
return basename($file);
}
function get_basename_without_extension($filename)
function get_filename_without_extension($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";
return preg_replace('/\\.[^.\\s]{2,4}$/', '', basename($file));
}
/**
@ -2262,9 +2202,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);
@ -2585,126 +2525,6 @@ 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 <http://spdx.org/licenses/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('<strong style="color:green">&raquo;</strong> 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("<br>\n" . '[*] Two level TLD: <strong>' . join('.', $_sub) . '</strong> ') : 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("<br>\n" .'[*] One level TLD: <strong>'.join('.', $_sub).'</strong> ') : false;
}
else // more than 3 levels, something is wrong
{
for ($i = count($_sub); $i > 1; $i--)
{
$removed = array_shift($arr);
}
$debug ? print("<br>\n" . '[*] Three level TLD: <strong>' . join('.', $_sub) . '</strong> ') : 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("<br>\n" .'Seems invalid domain: <strong>'.join('.', $arr).'</strong> re-adding: <strong>'.$arr0.'</strong> ') : false;
// seems invalid domain, restore it
array_unshift($arr, $arr0);
}
}
$debug ? print("<br>\n".'<strong style="color:gray">&laquo;</strong> Done parsing: <span style="color:red">' . $original . '</span> as <span style="color:blue">'. join('.', $arr) ."</span><br>\n") : false;
return join('.', $arr);
}
} // G Namespace
// Global namespace
@ -2947,4 +2767,5 @@ namespace {
return $status === 0;
}
}
}

View File

@ -15,7 +15,6 @@
--------------------------------------------------------------------- */
namespace G\Render;
use G;
/**
@ -23,36 +22,32 @@ use G;
* ---------------------------------------------------------------------
*/
function include_theme_file($filename, $args=[])
{
function include_theme_file($filename, $args=[]) {
$file = G_APP_PATH_THEME . $filename;
$override = G_APP_PATH_THEME . 'overrides/' . $filename;
if (!file_exists($file)) {
if(!file_exists($file)) {
$file .= '.php';
$override .= '.php';
}
if (file_exists($override)) {
if(file_exists($override)) {
$file = $override;
}
if (file_exists($file)) {
if(file_exists($file)) {
$GLOBALS['theme_include_args'] = $args;
include($file);
unset($GLOBALS['theme_include_args']);
}
}
function include_theme_header()
{
function include_theme_header() {
include_theme_file('header');
}
function include_theme_footer()
{
function include_theme_footer() {
include_theme_file('footer');
}
function get_theme_file_contents($filename)
{
function get_theme_file_contents($filename) {
$file = G_APP_PATH_THEME . $filename;
return file_exists($file) ? file_get_contents($file) : null;
}
@ -62,8 +57,7 @@ function get_theme_file_contents($filename)
* ---------------------------------------------------------------------
*/
function get_theme_file_url($string)
{
function get_theme_file_url($string) {
return BASE_URL_THEME . $string;
}
@ -73,15 +67,13 @@ function get_theme_file_url($string)
*/
// Return app lib file url
function get_app_lib_file_url($string)
{
return (defined('APP_G_APP_LIB_URL') ? APP_G_APP_LIB_URL : G_APP_LIB_URL) . $string;
function get_app_lib_file_url($string){
return G_APP_LIB_URL . $string;
}
// Returns the HTML input with the auth token
function get_input_auth_token($name='auth_token')
{
return '<input type="hidden" name="'.$name.'" value="'. G\Handler::getAuthToken() . '">';
function get_input_auth_token($name='auth_token') {
return '<input type="hidden" name="'.$name.'" value="'.G\Handler::getAuthToken().'">';
}
@ -91,11 +83,10 @@ function get_input_auth_token($name='auth_token')
*/
// Outputs the REST_API array to xml
function xml_output($array=array())
{
function xml_output($array=array()) {
error_reporting(0);
//@ini_set('display_errors', false);
if (ob_get_level() === 0 and !ob_start('ob_gzhandler')) {
if(ob_get_level() === 0 and !ob_start('ob_gzhandler')) {
ob_start();
}
header("Last-Modified: ".gmdate("D, d M Y H:i:s")."GMT");
@ -106,9 +97,9 @@ function xml_output($array=array())
$out .= "<response>\n";
$out .= " <status_code>$array[status_code]</status_code>\n";
$out .= " <status_txt>$array[status_txt]</status_txt>\n";
if (count($array["data"])>0) {
if(count($array["data"])>0) {
$out .= " <data>\n";
foreach ($array["data"] as $key => $value) {
foreach($array["data"] as $key => $value) {
$out .= " <$key>$value</$key>\n";
}
$out .= " </data>\n";
@ -118,54 +109,51 @@ function xml_output($array=array())
}
// Procedural function to output an array to json
function json_output($data=[], $callback=null)
{
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();
}
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))) {
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
'code' => NULL
]
];
die(json_encode($json_fail));
}
// Populate missing values
if ($data['status_code'] && !$data['status_txt']) {
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
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
'code' => NULL
]
];
die(json_encode($json_fail));
}
G\set_status_header($data['status_code']);
if (!is_null($callback)) {
if(!is_null($callback)) {
print sprintf('%s(%s);', $callback, $json_encode);
} else {
print $json_encode;