uploaded framework GUACHI and minimal set to work

* closes https://codeberg.org/minenux/minenux-skindb-webdb/issues/3
This commit is contained in:
mckaygerhard 2024-04-02 17:44:15 -04:00
parent cd2f3fd9ce
commit cf430139fd
24 changed files with 3674 additions and 0 deletions

21
.editorconfig Normal file
View File

@ -0,0 +1,21 @@
# EditorConfig is awesome: https://EditorConfig.org
root = true
[*]
indent_style = space
indent_size = 4
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
end_of_line = lf
max_line_length = off
[*.md]
indent_size = false
[*.ini]
indent_size = 4
[*.sql]
indent_size = 4

44
.gitignore vendored Normal file
View File

@ -0,0 +1,44 @@
# ---> Laravel
/vendor/
node_modules/
npm-debug.log
yarn-error.log
# Laravel 4 specific
bootstrap/compiled.php
app/storage/
# Laravel 5 & Lumen specific
public/storage
public/hot
# Laravel 5 & Lumen specific with changed public path
public_html/storage
public_html/hot
storage/*.key
.env
Homestead.yaml
Homestead.json
/.vagrant
.phpunit.result.cache
bootstrap/
storage/
# guachi framework
/*.db
/*-shm
/*-wal
/guachi.ini
/modules.ini
/cache/*
/public/js/guachi.js
*.css
/node_modules/*
/.sass-cache/*
/package-lock.json
/server
/extras/pruebas/
/public/pruebas.php
/test/

378
lib/class.auth.php Normal file
View File

@ -0,0 +1,378 @@
<?php
/*
____ _ _
/ ___|_ _ __ _ ___| |__ (_)
| | _| | | |/ _` |/ __| '_ \| |
| |_| | |_| | (_| | (__| | | | |
\____|\__,_|\__,_|\___|_| |_|_|
Copyright (c) 2014 Díaz Víctor aka (Máster Vitronic)
Copyright (c) 2018 Díaz Víctor aka (Máster Vitronic)
<vitronic2@gmail.com> <mastervitronic@vitronic.com.ve>
*/
class auth {
/**
* Recurso de la db.
*
* @var resource
* @access private
*/
private $db;
/**
* El nombre de usuarios
*
* @var string
* @access private
*/
private $username;
/**
* El id del usuario den la base de datos
*
* @var int
* @access private
*/
private $id_user;
/**
* El campo en la sesion para el CSRF
*
* @var string
*/
const KEY_CSRF = "csrf";
/**
* El nombre de la session
*
* @var string
*/
const SESSION_NAME = "guachi_session_id";
/**
* El id de la sesion
*
* @var string
* @access private
*/
private $session_id = null;
/**
* Sesion persistento o no
*
* @var bool
* @access private
*/
private $session_persistent;
/**
* Instancia para el patrón de diseño singleton (instancia única)
* @var object instancia
* @access private
*/
private static $instancia = null;
/**
* __construct
*
* Constructor de la clase
*
* @access public
*
*/
private function __construct() {
if (!isset($_SESSION)) {
session_name(self::SESSION_NAME);
session_start();
}
global $db;
$this->db = $db;
/* Autenticación HTTP básica para servicios web
*/
if (isset($_SERVER["HTTP_AUTHORIZATION"])) {
list($method, $auth) = explode(" ", $_SERVER["HTTP_AUTHORIZATION"], 2);
if (($method == "Basic") && (($auth = base64_decode($auth)) !== false)) {
list($username, $password) = explode(":", $auth, 2);
if ($this->logIn($username, $password) == false) {
header("Status: 401");
} else {
$this->key('login');
}
}
}
}
/**
* __destruct
*
* Destructor, destruye automaticamente la clase.
*
* @access public
*/
public function __destruct() {
}
/**
* Inicia la instancia de la clase
* @return object
*/
public static function iniciar() {
if (!self::$instancia instanceof self) {
self::$instancia = new self;
}
return self::$instancia;
}
/**
* Método magico __clone
*/
public function __clone() {
trigger_error('Operación Invalida:' .
' clonación no permitida', E_USER_ERROR);
}
/**
* Método magico __wakeup
*/
public function __wakeup() {
trigger_error('Operación Invalida:' .
' deserializar no esta permitido ' .
get_class($this) . " Class. ", E_USER_ERROR);
}
/**
* key
* Inicia/Cierra la sesion
* parametros supportados:
* * `exit` Destruye toda la sesion.
* * `login` Inicia la sesion.
*
* @param string $mode
*
* @author Máster Vitronic
* @return bool
* @access private
*/
private function key($mode) {
switch ($mode) {
case 'exit':
unset($_COOKIE[self::SESSION_NAME]);
session_regenerate_id(true);
session_unset();
return session_destroy();
case 'login':
$_SESSION = [
'username' => $this->username,
'id_user' => $this->id_user,
'id_profile' => $this->id_profile,
'session_timeout' => is_true($this->session_persistent) ? false : (time() + session_timeout),
'ip_address' => get_ip()
];
$this->session_id = session_id();
setcookie(self::SESSION_NAME,$this->session_id,null,"/", "", is_true(enforce_https), true);
$_COOKIE[self::SESSION_NAME] = $this->session_id;
return true;
}
return false;
}
/**
* logIn
* Valida/verifica los credenciales
*
* @param string $username
* @param string $password
*
* @author Máster Vitronic
* @return bool
* @access public
*/
public function logIn($username, $password) {
$query = 'select'
.' profiles.id_profile, '
.' profiles.profile, '
.' users.id_user, '
.' users.status, '
.' users.password '
.'from users '
.' inner join users_profiles on ( '
.' users_profiles.id_user = users.id_user '
.' ) '
.' inner join profiles on ( '
.' profiles.id_profile = users_profiles.id_profile '
.' ) '
.'where users.username=%s and users.status=true ';
$resource = $this->db->query($query,$username);
$results = $this->db->get_row($resource);
if(isset($results->id_user)){
if(password_verify($password , $results->password)){
$this->username = $username;
$this->id_user = $results->id_user;
$this->id_profile = $results->id_profile;
return $this->key('login');
}
}
return false;
}
/**
* Magic method get
*
* @access public
*/
public function __get($key) {
switch ($key) {
case "username" : return isset($_SESSION['id_user']) ? $_SESSION['username'] : false;
case "id_user" : return isset($_SESSION['id_user']) ? intval($_SESSION['id_user']) : false;
}
return null;
}
/**
* hashPass
* Crea un password
*
* @param string $password
*
* @author Máster Vitronic
* @return string
* @access public
*/
public function hashPass($password) {
return password_hash($password, PASSWORD_BCRYPT);
}
/**
* logOut
* Cierra la sesion actual
*
*
* @author Máster Vitronic
* @return bool
* @access public
*/
public function logOut() {
return $this->key('exit') == true ? true : false;
}
/**
* sessionIsValid
* Verifica que la sesion actual sea valida y esta vigente
*
*
* @author Máster Vitronic
* @return bool
* @access private
*/
private function sessionIsValid() {
if( isset($_SESSION['id_user']) ){
if( $_SESSION['session_timeout'] === false ){
return true;
}
if( $_SESSION['session_timeout'] > time() ){
$_SESSION['session_timeout'] = (time() + session_timeout);
return true;
}
$this->logOut();
}
return false;
}
/**
* isLogged
* Retornara true en caso que este logeado o false en caso contrario
*
*
* @author Máster Vitronic
* @return bool
* @access public
*/
public function isLogged() {
return ($this->sessionIsValid()) ? true : false ;
}
/**
* setCsrf
* Establece un nuevo valor ser usado como CSRF
*
*
* @author Máster Vitronic
* @return string
* @access public
*/
public function setCsrf() {
$_SESSION[self::KEY_CSRF] = hash("sha256", random_string(64));
}
/**
* getCsrf
* Retorna el CSRF actual
*
*
* @author Máster Vitronic
* @return string
* @access public
*/
public function getCsrf() {
return $_SESSION[self::KEY_CSRF];
}
/**
* csrfIsValid
* Valida/Verifica el CSRF
*
* @param string $csrf
*
* @author Máster Vitronic
* @return bool
* @access public
*/
public function csrfIsValid($csrf) {
return hash_equals($this->getCsrf(), $csrf);
}
/**
* getPermission
* Retorna los permisos de un usuario sobre un modulo
*
* @param string $module
* @param integer $id_user
*
* @author Máster Vitronic
* @return array
* @access public
*/
public function getPermission($module,$id_user) {
$sql = 'select '
.' permissions.write, '
.' permissions.read, '
.' permissions.update '
.'from users '
.' inner join users_profiles on ( '
.' users_profiles.id_user = users.id_user '
.' ) '
.' inner join profiles on ( '
.' profiles.id_profile = users_profiles.id_profile '
.' ) '
.' inner join permissions on ( '
.' permissions.id_profile = profiles.id_profile '
.' ) '
.' inner join modules on ( '
.' modules.id_module = permissions.id_module '
.' ) '
.'where modules.module = %s '
.' and users.id_user = %d '
.' and current_time between profiles.beging and profiles.ending '
.'order by profiles.id_profile asc limit 1';
$permission = $this->db->execute($sql, $module, $id_user);
if ($permission) {
return $permission[0];
}
return false;
}
}

48
lib/class.controller.php Normal file
View File

@ -0,0 +1,48 @@
<?php
/*la case del controlador*/
abstract class controller {
protected $model = null;
protected $db = null;
protected $auth = null;
protected $router = null;
protected $view = null;
/* Constructor
*
* INPUT: object db, object auth, object page, object view
* OUTPUT: -
* ERROR: -
*/
public function __construct($db, $auth, $router, $view) {
$this->db = $db;
$this->auth = $auth;
$this->router = $router;
$this->view = $view;
/* Load model
*/
$model_class = str_replace("/", "_", $router->module)."_model";
if (class_exists($model_class)) {
if (is_subclass_of($model_class, "model") == false) {
print "Model class '".$model_class."' does not extend class 'model'.\n";
} else {
$this->model = new $model_class($db, $auth, $router, $view);
}
}
}
/* Default execute function
*
* INPUT: -
* OUTPUT: -
* ERROR: -
*/
public function execute() {
if ($this->page->ajax_request == false) {
print "Page controller has no execute() function.\n";
}
}
}

459
lib/class.files.php Normal file
View File

@ -0,0 +1,459 @@
<?php
/*
___ ____
|_ _|___ _ __ / ___|___ _ __ ___
| |/ __| '_ \| | / _ \| '__/ _ \
| |\__ \ |_) | |__| (_) | | | __/
|___|___/ .__/ \____\___/|_| \___|
|_|
Copyright (c) 2014 Díaz Víctor aka (Máster Vitronic)
Copyright (c) 2018 Díaz Víctor aka (Máster Vitronic)
<vitronic2@gmail.com> <mastervitronic@vitronic.com.ve>
*/
class files {
/**
* Recurso de la db.
*
* @var resource
* @access private
*/
private $db;
/**
* El mime tipe esperado
*
* @var array
* @access private
*/
private $type_expected = [];
/**
* El id del usuario que sera dueño del archivo
*
* @var int
* @access private
*/
private $id_owner;
/**
* indica si sera afectado tambien el la db
*
* @var boolean
* @access private
*/
private $in_db = true;
/**
* El mensaje
*
* @var string
* @access private
*/
private $error;
/**
* El ambito
*
* @var string
* @access private
*/
private $scope;
/**
* El recurso hashids
*
* @var resource
* @access private
*/
private $hashids;
/**
* El file_path
*
* @var string
* @access private
*/
const file_path = ROOT . 'cloud/';
/**
* El nombre en el sistema de ficheros
*
* @var string
* @access private
*/
private $name_in_system = null;
/**
* Cuando son ficheros multiples, aqui un array con todos los nombres
*
* @var array
* @access private
*/
private $names_in_system = [];
/**
* El nombre en el arhivo
*
* @var string
* @access private
*/
private $file_name;
/**
* El nombre temporal del archivo
*
* @var string
* @access private
*/
private $tmp_name;
/**
* El tipo mime
*
* @var string
* @access private
*/
private $mime_type;
/**
* El tamaño del archivo
*
* @var string
* @access private
*/
private $file_size;
/**
* El id del campo subido $_FILES['foto'] seria foto
*
* @var string
* @access private
*/
private $file_id;
/**
* No redimencionar la imagen
*
* @var string
* @access private
*/
private $no_rzs = false;
/**
* El id del campo subido $_FILES['foto'] seria foto
*
* @var string
* @access private
*/
private $observation = null;
/**
* El id del campo subido $_FILES['foto'] seria foto
*
* @var string
* @access private
*/
private $folder_name = null;
/**
* El id del campo subido $_FILES['foto'] seria foto
*
* @var string
* @access private
*/
private $protected = 'f';
/**
* El id del campo subido $_FILES['foto'] seria foto
*
* @var string
* @access private
*/
private $private = 'f';
/**
* Instancia para el patrón de diseño singleton (instancia única)
* @var object instancia
* @access private
*/
private static $instancia = null;
/**
* __construct
*
* Constructor de la clase
*
* @access public
*
*/
private function __construct() {
global $db;
$this->db = $db;
}
/**
* __destruct
*
* Destructor, destruye automaticamente la clase.
*
* @access public
*/
public function __destruct() {
}
/**
* Inicia la instancia de la clase
* @return object
*/
public static function iniciar() {
if (!self::$instancia instanceof self) {
self::$instancia = new self;
}
return self::$instancia;
}
/**
* Método magico __clone
*/
public function __clone() {
trigger_error('Operación Invalida:' .
' clonación no permitida', E_USER_ERROR);
}
/**
* Método magico __wakeup
*/
public function __wakeup() {
trigger_error('Operación Invalida:' .
' deserializar no esta permitido ' .
get_class($this) . " Class. ", E_USER_ERROR);
}
/* Magic method get
*
* @access public
*/
public function __get($key) {
switch ($key) {
case 'name_in_system' : return $this->name_in_system;
case 'names_in_system' : return $this->names_in_system;
case 'file_path' : return self::file_path;
case 'error' : return $this->error;
}
return null;
}
/* Magic method set
*
* @access public
*/
public function __set($key,$value) {
switch ($key) {
case 'scope' : $this->scope = $value; break;
case 'in_db' : $this->in_db = $value; break;
case 'no_rzs' : $this->no_rzs = $value; break;
case 'id_owner' : $this->id_owner = $value; break;
case 'file_id' : $this->file_id = $value; break;
case 'name_in_system' : $this->name_in_system = $value; break;
case 'type_expected' : $this->type_expected = $value; break;
case 'observation' : $this->observation = $value; break;
case 'folder_name' : $this->folder_name = $value; break;
case 'protected' : $this->protected = $value; break;
case 'private' : $this->private = $value; break;
default: trigger_error('Unknown variable: '.$key);
}
}
public static function reArrayFiles(&$file_post) {
$file_ary = array();
$multiple = is_array($file_post['name']);
$file_count = $multiple ? count($file_post['name']) : 1;
$file_keys = array_keys($file_post);
for ($i=0; $i<$file_count; $i++){
foreach ($file_keys as $key){
$file_ary[$i][$key] = $multiple ? $file_post[$key][$i] : $file_post[$key];
}
}
return $file_ary;
}
/**
* get_name_in_system
* retorna el name_in_system del archivo
*
*
* @author Máster Vitronic
* @return string
* @error false
* @access public
*/
private function get_name_in_system(){
if(isset($this->name_in_system) === false){
return false;
}
$hashids = new lib\Hashids\Hashids( $this->scope );
return $hashids->encode($this->name_in_system);
}
/**
* save_in_disk
* Guarda un archivo en el disco
*
*
* @author Máster Vitronic
* @return bool
* @access public
*/
private function save_in_disk() {
if(!is_dir(self::file_path)){
mkdir(self::file_path, 0777, true);
}
if ( isset($this->name_in_system) ) {
if (($ext = strrchr($this->file_name, ".")) === false) {
$this->error = gettext('ERROR: Archivo sin extensión, no permitido.');
return false;
}
if($this->type_expected){
if(in_array( $this->mime_type , $this->type_expected ) === false ){
$this->error = gettext('ERROR: Tipo de archivo no permitido.');
return false;
}
}else{
if (in_array(substr($ext, 1), config_array(allowed_uploads)) == false) {
$this->error = gettext('ERROR: Tipo de archivo no permitido.');
return false;
}
}
/*@TODO esto debe ser seteable tambien via db setting*/
if ( $this->file_size > max_size_upload ) {
$this->error = gettext('ERROR: El tamaño del archivo supera lo permitido.');
return false;
}
/*el comportamiento esperado es que esto sobreescriba si el archivo existe*/
if ( (move_uploaded_file($this->tmp_name,self::file_path . $this->name_in_system)) == false ) {
$this->error = gettext('ERROR: no se pudo almacenar el archivo.');
return false;
}
/*No redimencionar la imagen*/
if ($this->no_rzs==true){
return true;
}
/*redimensiono la imagen y comprimo la imagen*/
if ( resizeImage(self::file_path . $this->name_in_system, 800, 600) ) {
$query = 'update cloud.files '
.'set file_size=%d, mime_type=%s '
.'where id_file=%d';
$values = [
filesize(self::file_path . $this->name_in_system),
mime_content_type(self::file_path . $this->name_in_system),
$this->name_in_system
];
$this->db->execute($query,$values);
}
return true;
}
$this->error = gettext('ERROR: Debe proveer un identificador del archivo (name_in_system).');
return false;
}
/**
* save
* guarda un archivo
*
*
* @author Máster Vitronic
* @return boolean
* @access public
* @TODO , esto guardara multiples files, pero solo retornara el ultimo id guardado
*/
public function save() {
$result = true;
$files = $this->reArrayFiles($_FILES[$this->file_id]);
$no_name = ($this->name_in_system) ? false : true;
foreach ($files as $file) {
if(isset($file['name']) == false ){
$this->error = gettext('ERROR: No se encontro ningun archivo para guardar.');
$result = false;
break;
}
$this->tmp_name = $file['tmp_name'];
if($this->in_db === true){
$this->file_name = $file['name'];
$this->mime_type = $file['type'];
$this->file_size = $file['size'];
$values=[
$this->id_owner,
self::file_path,
($no_name) ? null : $this->name_in_system,
$this->file_name,
$this->mime_type,
$this->file_size,
$this->observation,
$this->folder_name,
$this->protected,
$this->private
];
$query = "select cloud.save_file(%d, %s, %s, %s, %s, %s, %s, %s, %s, %s)";
if ( ($id_file = $this->db->execute($query,$values)) === false) {
$this->error = $this->db->error[2];
$result = false;
break;
}
$this->name_in_system = $id_file[0]['save_file'];//hash('sha256',$id_file[0]['save_file']);
array_push($this->names_in_system, $id_file[0]['save_file']);
}
if($this->save_in_disk() === false){
$result = false;
break;
}
}
return ($result) ? $this->name_in_system : false;
}
/**
* delete
* borra un archivo
*
*
* @author Máster Vitronic
* @return string
* @access public
*/
public function delete() {
if($this->in_db === true){
$query="delete from cloud.files where id_file=%d";
$this->db->query($query, $this->name_in_system) ;
}
unlink(self::file_path . $this->name_in_system);
}
/**
* getMimeType
* retorna el tipo mime de un archivo
*
*
* @author Máster Vitronic
* @return string
* @access private
*/
private function getMimeType() {
return finfo_file(finfo_open(FILEINFO_MIME_TYPE),self::file_path . $this->name_in_system);
}
}

49
lib/class.model.php Normal file
View File

@ -0,0 +1,49 @@
<?php
/*la clase del modelo*/
abstract class model {
protected $db = null;
protected $auth = null;
protected $router = null;
protected $view = null;
/* Constructor
*
* INPUT: object database, object settings, object user, object page, object view[, object language]
* OUTPUT: -
* ERROR: -
*/
public function __construct($db, $auth, $router, $view) {
$this->db = $db;
$this->auth = $auth;
$this->router = $router;
$this->view = $view;
}
/* Borrow function from other model
*
* INPUT: string module name
* OUTPUT: object model
* ERROR: null
*/
protected function borrow($module) {
if (file_exists($file = "../models/".$module.".php") == false) {
header("Content-Type: text/plain");
printf("Can't borrow model '%s'.\n", $module);
exit();
}
require_once($file);
$model_class = str_replace("/", "_", $module)."_model";
if (class_exists($model_class) == false) {
return null;
} else if (is_subclass_of($model_class, "model") == false) {
return null;
}
return new $model_class($this->db, $this->auth, $this->router, $this->view);
}
}

326
lib/class.pagination.php Normal file
View File

@ -0,0 +1,326 @@
<?php
/*
___ ____
|_ _|___ _ __ / ___|___ _ __ ___
| |/ __| '_ \| | / _ \| '__/ _ \
| |\__ \ |_) | |__| (_) | | | __/
|___|___/ .__/ \____\___/|_| \___|
|_|
Copyright (c) 2014 Díaz Víctor aka (Máster Vitronic)
Copyright (c) 2021 Díaz Víctor aka (Máster Vitronic)
<vitronic2@gmail.com> <mastervitronic@vitronic.com.ve>
*/
class pagination {
/**
* Recurso de la db.
*
* @var resource
* @access private
*/
private $db;
/**
* La pagina
*
* @var integer
* @access private
*/
private $page = 1;
/**
* el numero de registros
*
* @var integer
* @access private
*/
private $records;
/**
* el limite por pagina
*
* @var integer
* @access private
*/
private $limit;
/**
* el template
*
* @var array
* @access private
*/
private $template;
/**
* el numero de paginas
*
* @var integer
* @access private
*/
private $pages;
/**
* el offset
*
* @var integer
* @access private
*/
private $offset;
/**
* el la pagina anterior
*
* @var integer
* @access private
*/
private $prev_page;
/**
* el la pagina siguiente
*
* @var integer
* @access private
*/
private $next_page;
/**
* la cantidad de enlaces a mostrar
*
* @var integer
* @access private
*/
private $show_links;
/**
* El mensaje
*
* @var string
* @access private
*/
private $error;
/**
* Instancia para el patrón de diseño singleton (instancia única)
* @var object instancia
* @access private
*/
private static $instancia = null;
/**
* __construct
*
* Constructor de la clase
*
* @access public
*
*/
private function __construct() {
global $db;
$this->db = $db;
}
/**
* __destruct
*
* Destructor, destruye automaticamente la clase.
*
* @access public
*/
public function __destruct() {
//$this->close();
}
/**
* Inicia la instancia de la clase
* @return object
*/
public static function iniciar() {
if (!self::$instancia instanceof self) {
self::$instancia = new self;
}
return self::$instancia;
}
/**
* Método magico __clone
*/
public function __clone() {
trigger_error('Operación Invalida:' .
' clonación no permitida', E_USER_ERROR);
}
/**
* Método magico __wakeup
*/
public function __wakeup() {
trigger_error('Operación Invalida:' .
' deserializar no esta permitido ' .
get_class($this) . " Class. ", E_USER_ERROR);
}
/* Magic method get
*
* @access public
*/
public function __get($key) {
switch ($key) {
case 'error' : return $this->error;
}
return null;
}
/* Magic method set
*
* @access public
*/
public function __set($key,$value) {
switch ($key) {
//case 'page' : $this->page = $value; break;
//case 'records' : $this->records = $value; break;
//case 'limit' : $this->limit = $value; break;
//default: trigger_error('Unknown variable: '.$key);
}
}
/**
* Setea la pagina actual, si no se le pasan
* parametros sera seteado en la pagina 1
* @author Máster Vitronic
* @param page integer el numero de pagina
* @access public
*/
public function set_page($page) {
$this->page = (isset($page) and intval($page)) ? $page : 1;
}
/**
* Retorna el total de paginas
*
* @author Máster Vitronic
* @return integer el numero de paginas
* @access public
*/
public function get_pages( ){
return ceil($this->records/$this->limit);
}
/**
* Retorna la pagina siguiente
*
* @author Máster Vitronic
* @return integer the next page
* @access public
*/
public function get_netx_page() {
return ($this->records==0)?1:($this->page + 1);
}
/**
* Retorna la pagina anterior
*
* @author Máster Vitronic
* @param integer $timeout el timeout
* @return radius instance of $this (for fluent interfaces)
* @access public
*/
public function get_prev_page(){
return ($this->records==0)?1:($this->page - 1);
}
/**
* Inicializa el paginador
*
* @author Máster Vitronic
* @access public
*/
public function initialized($config) {
if(is_array($config)==false){
return false;
}
$config = (object) $config;
$this->records = $config->records;
$this->limit = $config->limit;
$this->show_links = $config->show_links;
if ( isset($config->template) == false ) {
$this->template = [];
}else{
$this->template = $config->template;
}
$this->offset = ($this->limit*($this->page-1));
$this->pages = $this->get_pages();
$this->next_page= $this->get_netx_page();
$this->prev_page= $this->get_prev_page();
if ( $this->page >= $this->pages ) {
$this->next_page = 1;
}
if ( $this->page == 1 ) {
$this->prev_page = 1;
}
if ( $this->offset > $this->records ) {
$this->offset = $this->records; //--@FIXME, esto esta mal
}
if ( $this->page > $this->pages ) {
$this->page = $this->pages;
}
}
/**
* Retorna los links de paginas
*
* @author Máster Vitronic
* @access public
*/
public function get_links() {
if (isset($this->template['link'])==false) {
return false;
}
if(($this->page-$this->show_links) >= 1) {
$begin = ($this->page-$this->show_links);
$ending= ($this->page+$this->show_links);
}else{
$begin = 1;
$ending= ($this->records==0) ? 1 : ($this->show_links*2);
}
$links = [];
$current = '';
$page = 0;
for ($page=$begin; $page<=$ending; $page++){
if($page == $this->page or $this->page==0){
$current = isset($this->template['current']) ? $this->template['current'] : '';
}
$template = sprintf($this->template['link'],$current,$page,$page,$page);
$current='';
//array_push($links,$template);
$links[] = ['link'=>$template];/*Para Mustache*/
if($page == $this->pages) {
break;
}
}
return $links;
}
/**
* Retorna toda la informacion sobre la paginacion en curso
*
* @author Máster Vitronic
* @access public
*/
public function get_pagination() {
return [
'page' => $this->page,
'pages' => $this->pages,
'prev_page' => $this->prev_page,
'next_page' => $this->next_page,
'links' => $this->get_links(),
'limit' => $this->limit,
'offset' => $this->offset,
'records' => $this->records,
//'begin' => ($this->offset),
//'ending' => ($this->records-$this->offset)
];
}
}

277
lib/class.router.php Normal file
View File

@ -0,0 +1,277 @@
<?php
/*
____ _ _
/ ___|_ _ __ _ ___| |__ (_)
| | _| | | |/ _` |/ __| '_ \| |
| |_| | |_| | (_| | (__| | | | |
\____|\__,_|\__,_|\___|_| |_|_|
Copyright (c) 2014 Díaz Víctor aka (Máster Vitronic)
Copyright (c) 2018 Díaz Víctor aka (Máster Vitronic)
<vitronic2@gmail.com> <mastervitronic@vitronic.com.ve>
*/
class router {
/**
* El nombre del modulo
*
* @var string
* @access private
*/
private $module = null;
/**
* El tipo de modulo public|private
*
* @var string
* @access private
*/
private $type_module = null;
/**
* La url
*
* @var string
* @access private
*/
private $url = null;
/**
* La pagina solicitada
*
* @var string
* @access private
*/
private $page = null;
private $request = array();
/**
* Los parametros pasados a la url
*
* @var array
* @access private
*/
private $parameters = array();
/**
* Indica si el request es ajax
*
* @var bool
* @access private
*/
private $ajax_request = false;
/**
* El recuerso de la clase auth
*
* @var resource
* @access private
*/
private $auth = null;
/**
* Code HTTP
*
* @var int
* @access private
*/
private $http_status = 200;
/**
* Instancia para el patrón de diseño singleton (instancia única)
* @var object instancia
* @access private
*/
private static $instancia = null;
private function __construct() {
$this->auth = auth::iniciar();
/* AJAX request
*/
if (isset($_SERVER['HTTP_X_REQUESTED_WITH']) and strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest' and !empty($_SERVER['HTTP_X_REQUESTED_WITH'])) {
$this->ajax_request = true;
}
list($this->url) = explode("?", $_SERVER["REQUEST_URI"], 2);
$path = $this->url;
if (substr($path, 0, 1) == "/") {
$path = substr($path, 1);
}
$path = rtrim($path, "/");
if ($path == "") {
$page = start_module;
} else if (valid_input($path, VALIDATE_URL, VALIDATE_NONEMPTY)) {
$page = $path;
} else {
$this->module = ERROR_MODULE;
}
if(isset($page)){
$this->pathinfo = explode("/", $page);
}
if ($this->module === null) {
$this->select_module($page);
}
}
public function __destruct() {
}
/**
* Inicia la instancia de la clase
* @return object
*/
public static function iniciar() {
if (!self::$instancia instanceof self) {
self::$instancia = new self;
}
return self::$instancia;
}
/**
* Método magico __clone
*/
public function __clone() {
trigger_error("Operación Invalida:" .
" clonación no permitida", E_USER_ERROR);
}
/**
* Método magico __wakeup
*/
public function __wakeup() {
trigger_error("Operación Invalida:" .
" deserializar no esta permitido " .
get_class($this) . " Class. ", E_USER_ERROR);
}
/* Magic method get
*
* INPUT: string key
* OUTPUT: mixed value
* ERROR: null
*/
public function __get($key) {
switch ($key) {
case "module" : return $this->module;
case "type_module" : return $this->type_module;
case "page" : return $this->page;
case "url" : return $this->url;
case "request" : return $this->request;
case "parameters" : return $this->parameters;
case "ajax_request" : return $this->ajax_request;
}
return null;
}
/**
* module_on_disk
* Module available on disk
*
* @param string $url la url
* @param string $pages public|private
*
* @author Hugo Leisink <hugo@leisink.net>
* @return string module identifier
* @access private
*
* @see https://banshee-php.org/
*/
private function module_on_disk($url, $pages) {
$module = null;
$url = explode("/", $url);
$url_count = count($url);
foreach ($pages as $line) {
$page = explode("/", $line);
$parts = count($page);
$match = true;
for ($i = 0; $i < $parts; $i++) {
if ($page[$i] == "*" ) {
continue;
} else if ( !isset($url[$i]) or $page[$i] !== $url[$i] ) {
$match = false;
break;
}
}
if ($match && (strlen($line) >= strlen($module))) {
$module = page_to_module($line);
}
}
return $module;
}
/**
* select_module
* Determina qué módulo necesita ser cargado basándose en la página solicitada.
*
* @param string $page La pagina solicitada
*
* @author Hugo Leisink <hugo@leisink.net>
* @author Máster Vitronic
* @access public
*
* @see https://banshee-php.org/
*/
public function select_module($page) {
if (($this->module !== null) && ($this->module !== LOGIN_MODULE)) {
return;
}
if (($public_module = $this->module_on_disk($page, getModules("public",'page'))) !== null) {
$public_count = substr_count($public_module, "/") + 1;
} else {
$public_count = 0;
}
if (($private_module = $this->module_on_disk($page, getModules("private",'admin') )) !== null) {
$private_count = substr_count($private_module, "/") + 1;
} else {
$private_count = 0;
}
if (($public_module == null) && ($private_module == null)) {
/* La pagina no existe
*/
$this->module = ERROR_MODULE;
//$this->http_code = 404;
return;
}
if ($public_count >= $private_count) {
/* La pagina es publica
*/
$this->type_module = 'public';
$this->module = $public_module;
$this->parameters = array_slice($this->pathinfo, $public_count);
return;
}
/* La pagina es privada
*/
$this->type_module = 'private';
$this->module = $private_module;
$this->parameters = array_slice($this->pathinfo, $private_count);
if ($this->auth->isLogged() == false) {
/* Usuario no esta logueado
*/
$this->module = LOGIN_MODULE;
} //else if ($this->auth->permiso($this->__get("page")) == false) {
/* Acceso denegado a causa de que no hay permisos sufucientes
*/
//$this->module = ERROR_MODULE;
//$this->http_code = 403;
//$this->type = "";
//$this->user->log_action("unauthorized request for page %s", $page);
//}
}
}

171
lib/class.validator.php Normal file
View File

@ -0,0 +1,171 @@
<?php
/* Copyright (c) by Hugo Leisink <hugo@leisink.net>
* This file is part of the Banshee PHP framework
* https://www.banshee-php.org/
*
* Licensed under The MIT License
*/
class validator {
private $msg = null;
private $messages = array(
"boolean" => "El campo [label] debería contener un booleano",
"charset" => "El campo [label] contiene caracteres no válidos.",
"email" => "El campo [label] contiene una dirección de correo electrónico no válida.",
"enum" => "El campo [label] es invalido.",
"integer" => "The field [label] should contain an integer.",
"float" => "El campo [label] debe contener un número decimal.",
"intmin" => "El valor de [label] debe ser al menos [min].",
"intmax" => "El valor de [label] debe ser como máximo [max].",
"pattern" => "El campo [label] no coincide con el patrón requerido.",
"required" => "El campo [label] no puede estar vacío.",
"timestamp" => "El campo [label] contiene una marca de tiempo no válida.",
"minlen" => "La longitud de [label] debe ser al menos [minlen].",
"maxlen" => "La longitud de [label] no debe exceder de [maxlen].."
);
/* Constructor
*
* INPUT: object view
* OUTPUT: -
* ERROR: -
*/
public function __construct() {
}
/* Add validation feedback to output
*
* INPUT: int message index, array message replacements
* OUTPUT: -
* ERROR: -
*/
private function add_message($msg_idx, $replacements) {
if (isset($replacements["message"])) {
$message = $replacements["message"];
} else {
$message = $this->messages[$msg_idx];
foreach ($replacements as $from => $to) {
$message = str_replace("[".$from."]", $to, $message);
}
}
$this->msg = $message;
}
/* Start validation process
*
* INPUT: array pattern to validate POST data
* OUTPUT: boolean validation oke
* ERROR: -
*/
public function execute($pattern) {
$result = true;
foreach ($pattern as $name => $rule) {
if (isset($rule["label"]) == false) {
$rule["label"] = $name;
}
if ($rule["required"] === true) {
if ($_POST[$name] == "") {
$this->add_message("required", $rule);
$result = false;
continue;
}
}
switch ($rule["type"]) {
case "boolean":
if (($_POST[$name] != null) && ($_POST[$name] != "On")) {
$this->add_message("boolean", $rule);
$result = false;
}
break;
case "email":
if ($_POST[$name] != "") {
if (valid_email($_POST[$name]) == false) {
$this->add_message("email", $rule);
$result = false;
}
}
break;
case "enum":
if ($_POST[$name] != "") {
if (in_array($_POST[$name], $rule["values"]) == false) {
$this->add_message("enum", $rule);
$result = false;
}
}
break;
case "integer":
if (valid_input($_POST[$name], VALIDATE_NUMBERS) == false) {
$this->add_message("integer", $rule);
$result = false;
} else {
if (isset($rule["min"])) {
if ($_POST[$name] < $rule["min"]) {
$this->add_message("intmin", $rule);
$result = false;
}
}
if (isset($rule["max"])) {
if ($_POST[$name] > $rule["max"]) {
$this->add_message("intmax", $rule);
$result = false;
}
}
}
break;
case "float":
if (is_numeric($_POST[$name]) == false) {
$this->add_message("float", $rule);
$result = false;
}
break;
case "string":
if (isset($rule["minlen"])) {
if (strlen($_POST[$name]) < $rule["minlen"]) {
$this->add_message("minlen", $rule);
$result = false;
}
}
if (isset($rule["maxlen"])) {
if (strlen($_POST[$name]) > $rule["maxlen"]) {
$this->add_message("maxlen", $rule);
$result = false;
}
}
if (isset($rule["charset"])) {
if (valid_input($_POST[$name], $rule["charset"]) == false) {
$this->add_message("charset", $rule);
$result = false;
}
}
if (isset($rule["pattern"])) {
if (preg_match("/".$rule["pattern"]."/", $_POST[$name]) == false) {
$this->add_message("pattern", $rule);
$result = false;
}
}
break;
case "timestamp":
if ($_POST[$name] != "") {
if (valid_timestamp($_POST[$name]) == false) {
$this->add_message("timestamp", $rule);
$result = false;
}
}
break;
default:
$this->view->add_message("Tipo de valor no válido para ".$rule["label"].".");
}
}
return [$result, $this->msg];
}
}
?>

View File

@ -0,0 +1,501 @@
<?php
/* Copyright (c) by Hugo Leisink <hugo@leisink.net>
* This file is part of the Banshee PHP framework
* https://www.banshee-php.org/
*
* Licensed under The MIT License
*/
namespace lib\db;
abstract class database_connection {
protected $link = null;
protected $db_close = null;
protected $db_escape_string = null;
protected $db_query = null;
protected $db_fetch = null;
protected $db_free_result = null;
protected $db_insert_id = null;
protected $db_affected_rows = null;
protected $db_error = null;
protected $db_errno = null;
protected $id_delim = null;
private $read_only = false;
private $insert_id_history = array();
/* Desctructor
*
* INPUT: -
* OUTPUT: -
* ERROR: -
*/
public function __destruct() {
if ($this->link !== null) {
call_user_func($this->db_close, $this->link);
$this->link = null;
}
}
/* Magic method get
*
* INPUT: string key
* OUTPUT: mixed value
* ERROR: null
*/
public function __get($key) {
switch ($key) {
case "connected":
return $this->link !== null;
case "last_insert_id":
return $this->last_insert_id(0);
case "affected_rows":
if ($this->db_affected_rows !== null) {
return call_user_func($this->db_affected_rows, $this->link);
}
break;
case "error":
if ($this->db_error !== null) {
return call_user_func($this->db_error, $this->link);
}
break;
case "errno":
if ($this->db_errno !== null) {
return call_user_func($this->db_errno, $this->link);
}
break;
}
return null;
}
/* Make database connection read-only
*/
public function make_read_only() {
$this->read_only = true;
}
/* Flatten array to new array with depth 1
*
* INPUT: array data
* OUTPUT: array data
* ERROR: -
*/
protected function flatten_array($data) {
$result = array();
foreach ($data as $item) {
if (is_array($item)) {
$result = array_merge($result, $this->flatten_array($item));
} else {
array_push($result, $item);
}
}
return $result;
}
/* Delimit an identifier
*
* INPUT: string identifier
* OUTPUT: string delimited identifier
* ERROR: -
*/
protected function delimit_identifier($identifier) {
if ($this->id_delim === null) {
return $identifier;
} else if (is_array($this->id_delim)) {
return $this->id_delim[0].$identifier.$this->id_delim[1];
} else {
return $this->id_delim.$identifier.$this->id_delim;
}
}
/* Validates a table name
*
* INPUT: string table
* OUTPUT: bool valid table name
* ERROR: -
*/
private function valid_table_name($table) {
static $table_name_chars = null;
if ($table == "") {
return false;
}
if ($table_name_chars === null) {
$table_name_chars = str_split("-_".
"ABCDEFGHIJKLMNOPQRSTUVWXYZ".
"abcdefghijklmnopqrstuvwxyz");
}
$diff = array_diff(str_split($table), $table_name_chars);
return count($diff) == 0;
}
/* Return printf format for variable
*
* INPUT: mixed variable
* OUTPUT: string printf format
* ERROR: -
*/
private function type_to_format($variable) {
if (is_integer($variable)) {
return "%d";
}
if (is_float($variable)) {
return "%f";
}
if (is_bool($variable)) {
return "%d";
}
return "%s";
}
/* Returns the id of the latest created record
*
* INPUT: [int history offset, [resource query resource]
* OUTPUT: int insert identifier
* ERROR: false
*/
public function last_insert_id($history = null, $resource = null) {
$param = ($resource !== null) ? $resource : $this->link;
if ($history !== null) {
$size = count($this->insert_id_history);
return $history < $size ? $this->insert_id_history[(int)$history] : 0;
} else if ($this->db_insert_id == null) {
return false;
} else if (($last_id = call_user_func($this->db_insert_id, $param)) == 0) {
return $this->last_insert_id(0);
} else {
return $last_id;
}
}
/* Create an SQL query by securely inserting the parameters in the query string
*
* INPUT: string query[, mixed query parameter, ...]
* OUTPUT: string
* ERROR: -
*/
protected function make_query() {
if (func_num_args() == 0) {
return false;
}
$args = func_get_args();
$format = array_shift($args);
$values = $this->flatten_array($args);
unset($args);
/* Security checks
*/
foreach (array("'", "`", "\"") as $char) {
if (strpos($format, $char) !== false) {
print $format."\nQuery not accepted.\n";
return false;
}
}
$format = str_replace("%s", "'%s'", $format);
$format = str_replace("%S", $this->delimit_identifier("%s"), $format);
/* Escape arguments
*/
foreach ($values as $key => $value) {
$values[$key] = call_user_func($this->db_escape_string, $value);
}
/* Apply arguments to format
*/
return vsprintf($format, $values);
}
/* Execute an SQL query and return the resource identifier
*
* INPUT: string query[, mixed query parameter, ...]
* OUTPUT: mixed resource identifier
* ERROR: false
*/
public function query() {
static $notified = false;
if ($this->connected == false) {
if ($notified == false) {
printf("%s: not connected to the database!\n", get_class($this));
$notified = true;
}
return false;
}
$args = func_get_args();
if (($query = call_user_func_array(array($this, "make_query"), $args)) === false) {
return false;
}
if ($this->read_only) {
$parts = explode(" ", ltrim($args[0]), 2);
$statement = strtolower(array_shift($parts));
if (in_array($statement, array("select", "show")) == false) {
print "Dropped query that tried to alter the database via a read-only database connection.\n";
return false;
}
}
$result = call_user_func($this->db_query, $query, $this->link);
if ($result === false) {
//print "SQL query: ".$query."\n";
//print "Error message: ".$this->error."\n";
} else if (($insert_id = $this->last_insert_id()) != 0) {
array_unshift($this->insert_id_history, $insert_id);
}
return $result;
}
/* Fetch one item from result by resource
*
* INPUT: mixed resource identifier
* OUTPUT: array( string key => string value[, ...] )|null
* ERROR: false
*/
public function fetch($resource) {
if (in_array($resource, array(null, false, true), true)) {
$result = false;
}
return call_user_func($this->db_fetch, $resource);
}
/* Free query result memory
*
* INPUT: mixed resource identifier
* OUTPUT: true
* ERROR: false
*/
public function free_result($resource) {
if ($this->db_free_result === null) {
return true;
}
return call_user_func($this->db_free_result, $resource);
}
/* Execute an SQL query and return the result
*
* INPUT: string query[, mixed query parameter, ...]
* OUTPUT: mixed result for 'select' and 'show' queries / int affected rows
* ERROR: false
*/
public function execute() {
$args = func_get_args();
if (($resource = call_user_func_array(array($this, "query"), $args)) === false) {
return false;
}
$parts = explode(" ", ltrim($args[0]), 2);
$statement = strtolower(array_shift($parts));
if (in_array($statement, array("select", "show", "describe", "explain"))) {
$result = array();
while (($data = $this->fetch($resource)) != false) {
array_push($result, $data);
}
$this->free_result($resource);
return $result;
} else if ($this->db_affected_rows !== null) {
return call_user_func($this->db_affected_rows, $this->link);
}
return true;
}
/* Execute queries via transaction
*
* INPUT: array( array( string query[, mixed query parameter, ...] )[, ...] )
* OUTPUT: boolean transaction succesful
* ERROR: -
*/
public function transaction($queries) {
$this->query("begin");
foreach ($queries as $args) {
if (is_array($args) == false) {
$query = $args;
$args = array();
} else {
$query = array_shift($args);
}
/* Handle insert ids
*/
if (strpos($query, "INSERT_ID") !== false) {
$query = str_replace("{LAST_INSERT_ID}", $this->last_insert_id, $query);
$history_size = count($this->insert_id_history);
for ($q = 0; $q < $history_size; $q++) {
$query = str_replace("{INSERT_ID_".$q."}", $this->last_insert_id($q), $query);
}
}
/* Execute query
*/
if ($this->query($query, $args) === false) {
$this->query("rollback");
return false;
}
}
return $this->query("commit") !== false;
}
/* Retrieve an entry from a table
*
* INPUT: string table, int entry identifier
* OUTPUT: array( value[, ....] )
* ERROR: false
*/
public function entry($table, $id, $col = "id") {
$type = (is_int($id) || ($col == "id")) ? "%d" : "%s";
$query = "select * from %S where %S=".$type." limit 1";
if (($resource = $this->query($query, $table, $col, $id)) === false) {
return false;
}
return $this->fetch($resource);
}
/* Retorna true si un campo existe
*
* INPUT: string table, array( string column name[, ...] ) , array( column => value, ... ), string , int
* OUTPUT: mixed string or false
* ERROR: -
*/
public function exist($table, $uniques, $target, $id_target = false, $id = false ) {
if(is_array($uniques)){
foreach ($uniques as $key => $value) {
if(isset($target[$value])){
$type = ( is_int($target[$value]) ) ? "%d" : "%s";
$query = "select %S from %S where %S=".$type." ";
if ( $id_target and $id ) {
$type = ( is_int($id) ) ? "%d" : "%s";
$query .="and %S!=".$type." limit 1";
$resource = $this->query($query, $value, $table, $value, $target[$value], $id_target, $id);
}else{
$query .= " limit 1";
$resource = $this->query($query, $value, $table, $value, $target[$value]);
}
if ( $this->fetch($resource)[$value] ) {
return $value;
}
}
}
return false;
}
}
/* Insert new entry in table
*
* INPUT: string table, array( string value[, ...] ), array( string column name[, ...] )
* OUTPUT: true|integer inserted rows
* ERROR: false
*/
public function insert($table, $data, $keys = null) {
// if ($this->valid_table_name($table) == false) {
// return false;
// }
if ($keys == null) {
$keys = array_keys($data);
}
$format = $values = array();
foreach ($keys as $key) {
if ($data[$key] === null) {
array_push($format, "null");
} else {
array_push($format, $this->type_to_format($data[$key]));
array_push($values, $data[$key]);
}
}
$columns = implode(", ", array_fill(1, count($keys), "%S"));
$query = "insert into %S (".$columns.") values (".implode(", ", $format).")";
if ($this->query($query, $table, $keys, $values) === false) {
return false;
}
if ($this->db_affected_rows != null) {
return call_user_func($this->db_affected_rows, $this->link);
}
return true;
}
/* Update entry in table
*
* INPUT: string table, int entry identifier, array( mixed value[, ...] ), array( string column name[, ...] )
* OUTPUT: true|integer updated rows
* ERROR: false
*/
public function update($table, $id, $index, $data, $keys = null) {
// if ($this->valid_table_name($table) == false) {
// return false;
// }
if ($keys === null) {
$keys = array_keys($data);
}
$format = $values = array();
foreach ($keys as $key) {
if (empty($data[$key]) or $data[$key] === null) {
array_push($format, "%S=null");
array_push($values, $key);
} else {
array_push($format, "%S=".$this->type_to_format($data[$key]));
array_push($values, $key, $data[$key]);
}
}
$query = "update %S set ".implode(", ", $format)." where $index=%d";
if ($this->query($query, $table, $values, $id) === false) {
return false;
}
if ($this->db_affected_rows != null) {
return call_user_func($this->db_affected_rows, $this->link);
}
return true;
}
/* Delete entry from table
*
* INPUT: string table, int entry identifier
* OUTPUT: true|integer deleted rows
* ERROR: false
*/
public function delete($table, $index, $id) {
if ($this->valid_table_name($table) == false) {
return false;
}
$query = "delete from %S where $index=%d";
if ($this->query($query, $table, $id) === false) {
return false;
}
if ($this->db_affected_rows != null) {
return call_user_func($this->db_affected_rows, $this->link);
}
return true;
}
}
?>

View File

@ -0,0 +1,33 @@
<?php
/* Copyright (c) by Hugo Leisink <hugo@leisink.net>
* This file is part of the Banshee PHP framework
* https://www.banshee-php.org/
*
* Licensed under The MIT License
*/
namespace lib\db;
class MSSQL_connection extends database_connection {
public function __construct($hostname, $database, $username, $password) {
$this->db_close = "mssql_close";
$this->db_escape_string = "addslashes";
$this->db_query = "mssql_query";
$this->db_fetch = "mssql_fetch_assoc";
$this->db_free_result = "mssql_free_result";
$this->db_affected_rows = "mssql_rows_affected";
$this->db_error = array($this, "db_error_wrapper");
$this->id_delim = array("[", "]");
if (($this->link = mssql_connect($hostname, $username, $password, true)) == false) {
$this->link = null;
} else if (mssql_select_db($database, $this->link) == false) {
mssql_close($this->link);
$this->link = null;
}
}
protected function db_error_wrapper($link) {
return mssql_get_last_message();
}
}
?>

View File

@ -0,0 +1,26 @@
<?php
/* Copyright (c) by Hugo Leisink <hugo@leisink.net>
* This file is part of the Banshee PHP framework
* https://www.banshee-php.org/
*
* Licensed under The MIT License
*/
namespace lib\db;
class MySQL_PDO_connection extends PDO_connection {
protected $type = "mysql";
protected $id_delim = "`";
protected $options = array(
\PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => true,
\PDO::ATTR_EMULATE_PREPARES => true);
public function __construct() {
$args = func_get_args();
call_user_func_array(array("parent", "__construct"), $args);
if ($this->link !== null) {
//$this->link->set_charset("utf8");
}
}
}
?>

View File

@ -0,0 +1,82 @@
<?php
/* Copyright (c) by Hugo Leisink <hugo@leisink.net>
* This file is part of the Banshee PHP framework
* https://www.banshee-php.org/
*
* Licensed under The MIT License
*/
namespace lib\db;
class MySQLi_connection extends database_connection {
public function __construct($hostname, $database, $username, $password, $port = 3306) {
$this->db_close = "mysqli_close";
$this->db_insert_id = "mysqli_insert_id";
$this->db_escape_string = array($this, "db_escape_string_wrapper");
$this->db_query = array($this, "db_query_wrapper");
$this->db_fetch = "mysqli_fetch_assoc";
$this->db_free_result = "mysqli_free_result";
$this->db_affected_rows = "mysqli_affected_rows";
$this->db_error = "mysqli_error";
$this->db_errno = "mysqli_errno";
$this->id_delim = "`";
if ($database != "") {
if (($this->link = mysqli_connect($hostname, $username, $password, $database, $port)) == false) {
$this->link = null;
} else {
$this->link->set_charset("utf8");
}
}
}
protected function db_escape_string_wrapper($str) {
return mysqli_real_escape_string($this->link, $str);
}
protected function db_query_wrapper($query) {
return mysqli_query($this->link, $query);
}
public function get_var($resource) {
if ($this->link === null) {
return false;
}
$result = $resource->fetch_assoc();
if($result){
$data = array_values($result)[0];
$resource->free_result();
return $data;
}
}
public function get_results($resource) {
if ($this->link === null) {
return false;
}
$num_rows=0;
while ($row = $resource->fetch_assoc() ){
$obj= (object) $row;
$result[$num_rows] = $obj;
$num_rows++;
}
$resource->free_result();
if(isset($result)){
return $result;
}
}
public function get_row($resource) {
if ($this->link === null) {
return false;
}
$result = $this->get_results($resource);
if($result){
return $result[0]?$result[0]:null;
}
}
}
?>

218
lib/db/pdo_connection.php Normal file
View File

@ -0,0 +1,218 @@
<?php
/* Copyright (c) by Hugo Leisink <hugo@leisink.net>
* This file is part of the Banshee PHP framework
* https://www.banshee-php.org/
*
* Licensed under The MIT License
*/
namespace lib\db;
abstract class PDO_connection extends database_connection {
protected $type = null;
protected $options = null;
private $last_query = null;
protected $errorInfo = null;
protected $errorCode = null;
public function __construct($hostname, $database, $username, $password) {
$this->db_close = array($this, "db_close_wrapper");
$this->db_insert_id = array($this, "db_insert_id_wrapper");
$this->db_escape_string = array($this, "db_escape_wrapper");
$this->db_fetch = array($this, "db_fetch_wrapper");
$this->db_affected_rows = array($this, "db_affected_rows_wrapper");
$this->db_error = array($this, "db_error_wrapper");
$this->db_errno = array($this, "db_errno_wrapper");
try {
$this->link = new \PDO($this->type.":host=".$hostname.";dbname=".$database, $username, $password, $this->options);
} catch (exception $e) {
$this->link = null;
}
}
protected function db_close_wrapper() {
$this->link = null;
}
protected function db_insert_id_wrapper() {
return $this->link->lastInsertId();
}
protected function db_escape_wrapper($string) {
return substr($this->link->quote((string)$string), 1, -1);
}
public function query() {
if ($this->connected == false) {
print "Not connected to database!\n";
return false;
} else if (func_num_args() == 0) {
return false;
}
$this->last_query = null;
$args = func_get_args();
$format = array_shift($args);
$values = $this->flatten_array($args);
unset($args);
$query_lower = strtolower(trim($format));
if (($query_lower == "begin") || ($query_lower == "start transaction")) {
/* Start transaction
*/
try {
return $this->link->beginTransaction();
} catch (exception $e) {
return false;
}
} else if ($query_lower == "rollback") {
/* Rollback transaction
*/
try {
return $this->link->rollBack();
} catch (exception $e) {
return false;
}
} else if ($query_lower == "commit" ) {
/* Commit transaction
*/
try {
return $this->link->commit();
} catch (exception $e) {
return false;
}
} else {
/* Other queries
*/
/* -----------------------------------------------------------
* Work-around for not being able to delimit an indentifier
* via PDOStatement::bindValue()
*/
$offset = 0;
$nr = 0;
while (($pos = strpos($format, "%", $offset)) !== false) {
if ($format[$pos + 1] == "S") {
$identifier = $this->delimit_identifier($values[$nr]);
$format = substr($format, 0, $pos).$identifier.substr($format, $pos + 2);
$pos += strlen($values[$nr]);
unset($values[$nr]);
}
if (isset($format[$pos + 1]) and $format[$pos + 1] == "%") {
$pos++;
} else {
$nr++;
}
$offset = $pos + 1;
}
$values = array_values($values);
/* -----------------------------------------------------------
*/
try {
$query = str_replace(array("%d", "%f", "%s", "%S"), "?", $format);
$resource = $this->link->prepare($query);
} catch (exception $e) {
return false;
}
$offset = 0;
$nr = 0;
while (($pos = strpos($format, "%", $offset)) !== false) {
if ($format[$pos + 1] == "d") {
// Integer
$resource->bindValue($nr + 1, (int)$values[$nr], \PDO::PARAM_INT);
} else if ($format[$pos + 1] == "f") {
// Float
$resource->bindValue($nr + 1, (float)$values[$nr], \PDO::PARAM_STR);
} else if ($format[$pos + 1] == "s") {
// String
$resource->bindValue($nr + 1, (string)$values[$nr], \PDO::PARAM_STR);
} else if ($format[$pos + 1] == "S") {
// Identifier
$resource->bindValue($nr + 1, (string)$values[$nr], \PDO::PARAM_STR);
} else {
return false;
}
$offset = $pos + 1;
$nr++;
}
$this->last_query = $resource;
if ($resource->execute() === false) {
/*declaro los errores*/
$this->errorInfo = $resource->errorInfo();
$this->errorCode = $resource->errorCode();
return false;
}
return $resource;
}
}
protected function db_fetch_wrapper($resource) {
return $resource->fetch(\PDO::FETCH_ASSOC);
}
protected function db_affected_rows_wrapper() {
if ($this->last_query === null) {
return -1;
}
return $this->last_query->rowCount();
}
protected function db_error_wrapper() {
$this->errorInfo[2] = substr($this->errorInfo[2], 0, strpos($this->errorInfo[2], PHP_EOL));
return $this->errorInfo;
}
protected function db_errno_wrapper() {
return $this->errorCode;
}
public function get_var($resource) {
if ($this->link === null or $resource === false) {
return false;
}
$result = $resource->fetch(\PDO::FETCH_ASSOC);
if($result){
$data = array_values($result)[0];
return $data;
}
}
public function get_results($resource) {
if ($this->link === null or $resource === false) {
return false;
}
$num_rows=0;
while ($row = $resource->fetch(\PDO::FETCH_ASSOC) ){
$obj= (object) $row;
$result[$num_rows] = $obj;
$num_rows++;
}
if(isset($result)){
return $result;
}
}
public function get_row($resource) {
if ($this->link === null or $resource === false) {
return false;
}
$result = $this->get_results($resource);
if($result){
return $result[0]?$result[0]:null;
}
}
}
?>

21
lib/db/pgsql_pdo_connection.php Executable file
View File

@ -0,0 +1,21 @@
<?php
/* Copyright (c) by Hugo Leisink <hugo@leisink.net>
* This file is part of the Banshee PHP framework
* https://www.banshee-php.org/
*
* Licensed under The MIT License
*/
namespace lib\db;
class PGSQL_PDO_connection extends PDO_connection {
protected $type = "pgsql";
protected $id_delim = "`";
protected $options = array();
public function __construct() {
$args = func_get_args();
call_user_func_array(array("parent", "__construct"), $args);
}
}
?>

View File

@ -0,0 +1,103 @@
<?php
/* Copyright (c) by Hugo Leisink <hugo@leisink.net>
* This file is part of the Banshee PHP framework
* https://www.banshee-php.org/
*
* Licensed under The MIT License
*/
namespace lib\db;
class PostgreSQL_connection extends database_connection {
private $last_query_resource = null;
public function __construct($hostname, $database, $username, $password, $port = 5432) {
$this->db_close = "pg_close";
$this->db_insert_id = "pg_last_oid";
$this->db_escape_string = array($this, "db_escape_string_wrapper");
$this->db_query = array($this, "db_query_wrapper");
$this->db_fetch = "pg_fetch_assoc";
$this->db_free_result = "pg_free_result";
$this->db_affected_rows = array($this, "db_affected_rows_wrapper");
$this->db_error = "pg_last_error";
$this->id_delim = '"';
if (($this->link = pg_connect("host=".$hostname." port=".$port." dbname=".$database." user=".$username." password=".$password)) == false) {
$this->link = null;
}
}
public function __get($key) {
switch ($key) {
case "last_insert_id":
return $this->last_insert_id(0, $this->last_query_resource);
}
return parent::__get($key);
}
public function last_insert_id($history = null, $resource = null) {
parent::last_insert_id($history, $resource !== null ? $resource : $this->last_query_resource);
}
protected function db_escape_string_wrapper($str) {
return pg_escape_string($this->link, $str);
}
protected function db_query_wrapper($query, $link) {
$this->last_query_resource = pg_query($link, $query);
return $this->last_query_resource;
}
protected function db_affected_rows_wrapper($link) {
pg_affected_rows($this->last_query_resource);
}
public function affected_rows($resource) {
$this->db_affected_rows_wrapper($resource);
}
public function get_var($resource) {
if ($this->link === null) {
return false;
}
$result = pg_fetch_assoc($resource);
if($result){
$data = array_values($result)[0];
pg_free_result($this->last_query_resource);
return $data;
}
}
public function get_results($resource) {
if ($this->link === null) {
return false;
}
$num_rows=0;
while ($row = pg_fetch_assoc($resource) ){
$obj= (object) $row;
$result[$num_rows] = $obj;
$num_rows++;
}
pg_free_result($this->last_query_resource);
if(isset($result)){
return $result;
}
}
public function get_row($resource) {
if ($this->link === null) {
return false;
}
$result = $this->get_results($resource);
if($result){
return $result[0]?$result[0]:null;
}
}
}
?>

View File

@ -0,0 +1,104 @@
<?php
/* Copyright (c) by Hugo Leisink <hugo@leisink.net>
* This file is part of the Banshee PHP framework
* https://www.banshee-php.org/
*
* Licensed under The MIT License
*/
namespace lib\db;
class SQLite3_connection extends database_connection {
public function __construct($filename, $mode = null, $encryption_key = null) {
$this->db_close = array($this, "db_close_wrapper");
$this->db_insert_id = array($this, "db_last_insert_wrapper");
$this->db_escape_string = array($this, "db_escape_wrapper");
$this->db_query = array($this, "db_query_wrapper");
$this->db_fetch = array($this, "db_fetch_wrapper");
$this->id_delim = '"';
if ($mode === null) {
$mode = SQLITE3_OPEN_READWRITE | SQLITE3_OPEN_CREATE;
}
$this->link = new \SQLite3($filename, $mode, $encryption_key);
}
protected function db_close_wrapper() {
if ($this->link !== null) {
$this->link->close();
$this->link = null;
}
}
protected function db_last_insert_wrapper() {
if ($this->link === null) {
return false;
}
return $this->link->lastInsertRowID();
}
protected function db_escape_wrapper($string) {
if ($this->link === null) {
return false;
}
return $this->link->escapeString($string);
}
protected function db_query_wrapper($query) {
if ($this->link === null) {
return false;
}
return $this->link->query($query);
}
protected function db_fetch_wrapper($resource) {
if ($this->link === null) {
return false;
}
return $resource->fetchArray(SQLITE3_ASSOC);
}
public function get_var($resource) {
if ($this->link === null) {
return false;
}
$result = $resource->fetchArray(SQLITE3_ASSOC);
if($result){
return array_values($result)[0];
}
}
public function get_results($resource) {
if ($this->link === null) {
return false;
}
$num_rows=0;
while ($row = $resource->fetchArray(SQLITE3_ASSOC) ){
$obj= (object) $row;
$result[$num_rows] = $obj;
$num_rows++;
}
if(isset($result)){
return $result;
}
}
public function get_row($resource) {
if ($this->link === null) {
return false;
}
$result = $this->get_results($resource);
if($result){
return $result[0]?$result[0]:null;
}
}
}
?>

View File

@ -0,0 +1,41 @@
<?php
/* Copyright (c) by Hugo Leisink <hugo@leisink.net>
* This file is part of the Banshee PHP framework
* https://www.banshee-php.org/
*
* Licensed under The MIT License
*/
namespace lib\db;
class SQLite_connection extends database_connection {
public function __construct($filename, $mode = null) {
$this->db_close = "sqlite_close";
$this->db_insert_id = "sqlite_last_insert_rowid";
$this->db_escape_string = "sqlite_escape_string";
$this->db_query = "sqlite_query";
$this->db_fetch = array($this, "db_fetch_wrapper");
$this->db_affected_rows = "sqlite_changes";
$this->db_error = array($this, "db_error_wrapper");
$this->db_errno = "sqlite_last_error";
$this->id_delim = '"';
if (($this->link = sqlite_open($filename, $mode)) == false) {
$this->link = null;
}
}
protected function db_fetch_wrapper($resource) {
if (in_array($resource, array(null, false, true), true)) {
$result = false;
} else if (($result = sqlite_fetch_array($resource, SQLITE_ASSOC)) === null) {
$result = false;
}
return $result;
}
protected function db_error_wrapper($db_handle) {
return sqlite_error_string(sqlite_last_error($db_handle));
}
}
?>

414
lib/guachi.php Normal file
View File

@ -0,0 +1,414 @@
<?php
define('GUACHI_VERSION','2.1');
define('DS', DIRECTORY_SEPARATOR);
define('ROOT', realpath(dirname( __DIR__ ) ) . DS );
define("YES", 1);
define("NO", 0);
define("HOUR", 3600);
define("DAY", 86400);
define("PASSWORD_MIN_LENGTH", 8);
define("PASSWORD_MAX_LENGTH", 1000);
define("DIR_CONTROLLERS", ROOT . 'controllers' . DS );
define("DIR_MODELS", ROOT . 'models' . DS );
define("DIR_VIEWS", ROOT . 'views' . DS );
define("ERROR_MODULE",'notFound');
define("LOGIN_MODULE",'login');
/**
* guachi_autoload
*
* @access public
*/
function guachi_autoload($class_name) {
$parts = explode("\\", $class_name);
$class = array_pop($parts);
array_shift($parts);
$class = strtolower($class);
$path = ROOT . 'lib/' .implode("/", $parts);
if (file_exists($file = $path."/class.".strtolower($class).".php")) {
include_once($file);
} else if (file_exists($file = $path."/".strtolower($class).".php")) {
include_once($file);
} else if (file_exists($file = $path."/".$class.".php")) {
include_once($file);
}
};
/* Convert a page path to a module path
*
* INPUT: array / string page path
* OUTPUT: array / string module path
* ERROR: -
*/
function page_to_module($page) {
if (is_array($page) == false) {
if (($pos = strrpos($page, ".")) !== false) {
$page = substr($page, 0, $pos);
}
} else foreach ($page as $i => $item) {
$page[$i] = page_to_module($item);
}
return $page;
}
/**
* metodo getModules
*
* @access public
*/
function getModules($type,$section) {
static $cache = array();
if (isset($cache[$type][$section])) {
return $cache[$type][$section];
}
$modules = parse_ini_file(ROOT . 'modules.ini', true);
$cache = $modules;
return isset($modules[$type][$section])?$modules[$type][$section] : [];
}
/* Check for module existence
*
* INPUT: string module
* OUTPUT: bool module exists
* ERROR: -
*/
function module_exists($module, $type, $warn = false) {
$section = ($type == 'private') ? 'admin' : 'page';
if (in_array($module, getModules($type , $section)) ) {
if ($warn) {
printf("Ya existe un módulo %s '%s'.\n", $type, $module);
}
return true;
}
return false;
}
/**
* metodo setConfig
*
* @access public
*/
function setConfig() {
$config = parse_ini_file(ROOT . 'guachi.ini', true) ;
foreach ($config as $bloque => $conf) {
foreach ($config[$bloque] as $var => $valor) {
if(!is_array($valor)){
define(trim($var), trim($valor));
}
}
}
}
/**
* get_ip
*
* Si es posible retorna la ip del visitante
*
* @access public
* @return string
*/
function get_ip(){
$ip = false;
if (isset($_SERVER["HTTP_X_FORWARDED_FOR"])) {
$_SERVER["REMOTE_ADDR"] = $_SERVER["HTTP_X_FORWARDED_FOR"];
}
if( filter_var($_SERVER['REMOTE_ADDR'], FILTER_VALIDATE_IP) ) {
$ip = $_SERVER['REMOTE_ADDR'];
}
return $ip;
}
/**
* Formatea un numero a su correspondiente en moneda
* @param int
* @param strin
* @param bool
* @return string
*/
function format_money($number, $locale, $remove = false) {
$money = new NumberFormatter($locale, NumberFormatter::CURRENCY);
return $remove ? str_replace($remove, '', $money->format($number)) : $money->format($number);
}
/**
* Redondeo bancario
* @param int
* @param int
* @return mixed
*/
function bround($dVal,$iDec) {
static $dFuzz=0.00001; // to deal with floating-point precision loss
$iRoundup=0; // amount to round up by
$iSign=($dVal!=0.0) ? intval($dVal/abs($dVal)) : 1;
$dVal=abs($dVal);
// get decimal digit in question and amount to right of it as a fraction
$dWorking=$dVal*pow(10.0,$iDec+1)-floor($dVal*pow(10.0,$iDec))*10.0;
$iEvenOddDigit=floor($dVal*pow(10.0,$iDec))-floor($dVal*pow(10.0,$iDec-1))*10.0;
if (abs($dWorking-5.0)<$dFuzz) $iRoundup=($iEvenOddDigit & 1) ? 1 : 0;
else $iRoundup=($dWorking>5.0) ? 1 : 0;
return $iSign*((floor($dVal*pow(10.0,$iDec))+$iRoundup)/pow(10.0,$iDec));
}
/**
* Convierte mixed a boolean
* @param mixed
* @return boolean
*/
function is_true($bool) {
if (is_string($bool)) {
$bool = strtolower($bool);
}
return in_array($bool, array(true, YES, "1", "yes", "true", "on"), true);
}
/* Convert mixed to boolean
*
* INPUT: mixed
* OUTPUT: boolean
* ERROR: -
*/
function is_false($bool) {
return (is_true($bool) === false);
}
/* Convert boolean to string
*
* INPUT: boolean
* OUTPUT: string "yes"|"no"
* ERROR: -
*/
function show_boolean($bool) {
return (is_true($bool) ? "yes" : "no");
}
/* Convert empty string to null
*
* INPUT: string
* OUTPUT: string|null
* ERROR: -
*/
function null_if_empty($str) {
if (is_string($str) == false) {
return $str;
}
if (trim($str) == "") {
$str = null;
}
return $str;
}
/* Localized date string
*
* INPUT: string format[, integer timestamp]
* OUTPUT: string date
* ERROR: -
*/
function date_string($format, $timestamp = null) {
if ($timestamp === null) {
$timestamp = time();
}
$days_of_week = config_array(days_of_week);
$months_of_year = config_array(months_of_year);
$format = strtr($format, "lDFM", "#$%&");
$result = date($format, $timestamp);
$day = $days_of_week[(int)date("N", $timestamp) - 1];
$result = str_replace("#", $day, $result);
$day = substr($days_of_week[(int)date("N", $timestamp) - 1], 0, 3);
$result = str_replace("$", $day, $result);
$month = $months_of_year[(int)date("n", $timestamp) - 1];
$result = str_replace("%", $month, $result);
$month = substr($months_of_year[(int)date("n", $timestamp) - 1], 0, 3);
$result = str_replace("&", $month, $result);
return $result;
}
/* Convert configuration line to array
*
* INPUT: string config line[, bool look for key-value
* OUTPUT: array config line
* ERROR: -
*/
function config_array($line, $key_value = true) {
$items = explode("|", $line);
if ($key_value == false) {
return $items;
}
$result = array();
foreach ($items as $item) {
@list($key, $value) = explode(":", $item, 2);
if ($value === null) {
array_push($result, $key);
} else {
$result[$key] = $value;
}
}
return $result;
}
/**
* https://stackoverflow.com/questions/5695145/how-to-read-and-write-to-an-ini-file-with-php
* Write an ini configuration file
*
* @param string $file
* @param array $array
* @return bool
*/
function write_ini_file($file, $array = []) {
// check first argument is string
if (!is_string($file)) {
throw new \InvalidArgumentException('Function argument 1 must be a string.');
}
// check second argument is array
if (!is_array($array)) {
throw new \InvalidArgumentException('Function argument 2 must be an array.');
}
// process array
$data = array();
foreach ($array as $key => $val) {
if (is_array($val)) {
$data[] = "[$key]";
foreach ($val as $skey => $sval) {
if (is_array($sval)) {
foreach ($sval as $_skey => $_sval) {
if (is_numeric($_skey)) {
$data[] = $skey.'[] = '.(is_numeric($_sval) ? $_sval : (ctype_upper($_sval) ? $_sval : '"'.$_sval.'"'));
} else {
$data[] = $skey.'['.$_skey.'] = '.(is_numeric($_sval) ? $_sval : (ctype_upper($_sval) ? $_sval : '"'.$_sval.'"'));
}
}
} else {
$data[] = $skey.' = '.(is_numeric($sval) ? $sval : (ctype_upper($sval) ? $sval : '"'.$sval.'"'));
}
}
} else {
$data[] = $key.' = '.(is_numeric($val) ? $val : (ctype_upper($val) ? $val : '"'.$val.'"'));
}
// empty line
$data[] = null;
}
// open file pointer, init flock options
$fp = fopen($file, 'w');
$retries = 0;
$max_retries = 100;
if (!$fp) {
return false;
}
// loop until get lock, or reach max retries
do {
if ($retries > 0) {
usleep(rand(1, 5000));
}
$retries += 1;
} while (!flock($fp, LOCK_EX) && $retries <= $max_retries);
// couldn't get the lock
if ($retries == $max_retries) {
return false;
}
// got lock, write data
fwrite($fp, implode(PHP_EOL, $data).PHP_EOL);
// release lock
flock($fp, LOCK_UN);
fclose($fp);
return true;
}
/**
* set_cache_header
*
* establece un header cache con un tiempo determinado
*
* @access public
* @return
*/
function set_cache_header($seconds = false) {
$seconds_to_cache = ($seconds) ? $seconds : $seconds_to_cache = 3600;
$ts = gmdate("D, d M Y H:i:s", time() + $seconds_to_cache) . " GMT";
header("Expires: $ts");
header("Pragma: cache");
header("Cache-Control: max-age=$seconds_to_cache");
}
/**
* no_cache
*
* no-cache al browser
*
* @access public
* @return
*/
function set_no_cache_header() {
header("Expires: Tue, 03 Jul 2001 06:00:00 GMT");
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
header("Cache-Control: no-store, no-cache, must-revalidate, max-age=0");
header("Cache-Control: post-check=0, pre-check=0", false);
header("Pragma: no-cache");
}
/*seteo toda la configuracion*/
setConfig();
/*cosas por default*/
date_default_timezone_set(default_date_timezone);
setlocale(LC_TIME, locale);
// error_reporting(0);
error_reporting(E_ALL);
/*autocargo las dependencias*/
spl_autoload_register("guachi_autoload", true, true);
ini_set("zlib.output_compression", "Off");
// if (ini_get("allow_url_include") != 0) {
// exit("Set 'allow_url_include' to 0.");
// }
/*configuro la conexion a la base de datos*/
if( is_true(use_db) ){
switch (db_type){
case 'sqlite':
$db = new \lib\db\SQLite_connection(db_database);
break;
case 'sqlite3':
$db = new \lib\db\SQLite3_connection(db_database);
break;
case 'pgsql':
$db = new \lib\db\PostgreSQL_connection(db_hostname, db_database, db_username, db_password, db_port);
break;
case 'mysqli':
$db = new \lib\db\MySQLi_connection(db_hostname, db_database, db_username, db_password, db_port);
break;
case 'mysql_pdo':
$db = new \lib\db\MySQL_PDO_connection(db_hostname, db_database, db_username, db_password);
break;
case 'pgsql_pdo':
$db = new \lib\db\PGSQL_PDO_connection(db_hostname, db_database, db_username, db_password);
break;
}
}

182
lib/security.php Normal file
View File

@ -0,0 +1,182 @@
<?php
/* Copyright (c) by Hugo Leisink <hugo@leisink.net>
* This file is part of the Banshee PHP framework
* https://www.banshee-php.org/
*
* Licensed under The MIT License
*/
/* Pre-defined validation strings for valid_input()
*/
define("VALIDATE_CAPITALS", "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
define("VALIDATE_NONCAPITALS", "abcdefghijklmnopqrstuvwxyz");
define("VALIDATE_LETTERS", VALIDATE_CAPITALS.VALIDATE_NONCAPITALS);
define("VALIDATE_PHRASE", VALIDATE_LETTERS." ,.?!:;-'");
define("VALIDATE_NUMBERS", "0123456789");
define("VALIDATE_SYMBOLS", "!@#$%^&*()_-+={}[]|\:;\"'`~<>,./?");
define("VALIDATE_URL", VALIDATE_LETTERS.VALIDATE_NUMBERS."-_/.=");
define("VALIDATE_NONEMPTY", 0);
/* Validate input
*
* INPUT: string input, string valid characters[, int length]
* OUTPUT: boolean input oke
* ERROR: -
*/
function valid_input($data, $allowed, $length = null) {
if (is_array($data) == false) {
$data_len = strlen($data);
if ($length !== null) {
if ($length == VALIDATE_NONEMPTY) {
if ($data_len == 0) {
return false;
}
} else if ($data_len !== $length) {
return false;
}
} else if ($data_len == 0) {
return true;
}
$data = str_split($data);
$allowed = str_split($allowed);
$diff = array_diff($data, $allowed);
return count($diff) == 0;
} else foreach ($data as $item) {
if (valid_input($item, $allowed, $length) == false) {
return false;
}
}
return true;
}
/* Validate an e-mail address
*
* INPUT: string e-mail address
* OUTPUT: boolean e-mail address oke
* ERROR: -
*/
function valid_email($email) {
return preg_match("/^[0-9A-Za-z]([-_.~]?[0-9A-Za-z])*@[0-9A-Za-z]([-.]?[0-9A-Za-z])*\\.[A-Za-z]{2,4}$/", $email) === 1;
}
/* Validate a date string
*
* INPUT: string date
* OUTPUT: boolean date oke
* ERROR: -
*/
function valid_date($date) {
if ($date == "0000-00-00") {
return false;
}
return preg_match("/^[0-9]{4}-[0-9]{1,2}-[0-9]{1,2}$/", $date) === 1;
}
/* Validate a time string
*
* INPUT: string time
* OUTPUT: boolean time oke
* ERROR: -
*/
function valid_time($time) {
return preg_match("/^(([01]?[0-9])|(2[0-3])):[0-5][0-9](:[0-5][0-9])?$/", $time) === 1;
}
/* Validate a timestamp
*
* INPUT: string timestamp
* OUTPUT: boolean timestamp oke
* ERROR: -
*/
function valid_timestamp($timestamp) {
list($date, $time) = explode(" ", $timestamp, 2);
return valid_date($date) && valid_time($time);
}
/* Validate a telephone number
*
* INPUT: string telephone number
* OUTPUT: boolean telephone number oke
* ERROR: -
*/
function valid_phonenumber($phonenr) {
return preg_match("/^\+?(\(?\d+\)?[- ]?)*\d+$/", $phonenr) === 1;
}
/* Validate password security
*
* INPUT: string password[, object view]
* OUTPUT: boolean password secure
* ERROR: -
*/
function is_secure_password($password, $view = null) {
$result = true;
$pwd_len = strlen($password);
if ($pwd_len < PASSWORD_MIN_LENGTH) {
if ($view == null) {
return false;
}
$view->add_message("La contraseña debe tener al menos %d caracteres.", PASSWORD_MIN_LENGTH);
$result = false;
} else if ($pwd_len > PASSWORD_MAX_LENGTH) {
if ($view == null) {
return false;
}
$view->add_message("La contraseña es demasiado larga.");
$result = false;
}
$numbers = 0;
$letters = 0;
$symbols = 0;
for ($i = 0; $i < $pwd_len; $i++) {
$c = ord(strtolower(substr($password, $i, 1)));
if (($c >= 48) && ($c <= 57)) {
$numbers++;
} else if (($c >= 97) && ($c <= 122)) {
$letters++;
} else {
$symbols++;
}
}
if (($letters == 0) || (($numbers == 0) && ($symbols == 0))) {
if ($view == null) {
return false;
}
$view->add_message("La contraseña debe contener al menos una letra y un número o carácter especial.");
$result = false;
}
return $result;
}
/* Generate random string
*
* INPUT: int length
* OUTPUT: string random string
* ERROR: -
*/
function random_string($length) {
$characters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
$max_chars = strlen($characters) - 1;
$result = "";
for ($i = 0; $i < $length; $i++) {
$result .= $characters[is_php('8.0') ? random_int(0, $max_chars) : mt_rand(0,$max_chars)];
}
return $result;
}
?>

100
new_module Executable file
View File

@ -0,0 +1,100 @@
#!/usr/bin/php
<?php
chdir(__DIR__);
require ("lib/guachi.php");
require ('lib/security.php');
/* Muestro la ayuda y salgo*/
function help_exit() {
printf("Usage: %s public|private <module name> \n", $GLOBALS["argv"][0]);
exit;
}
/* Copia un archivo, pero no lo sobreescribe*/
function safe_copy($source, $dest) {
if (file_exists($source) == false) {
return false;
}else{
if (file_exists($dest)) {
printf("Warning, Archivo ya existe: %s\n", $dest);
return false;
}
copy($source, $dest);
return true;
}
}
/* Setea los nombres dentro de las plantillas */
function set_nombres($directory, $module) {
$filename = $directory . "/" . $module . ".php";
if (($file = file($filename)) === false) {
return false;
}
$module = str_replace("/", "_", $module);
$file[1] = str_replace("XXX", $module, $file);
if (($fp = fopen($filename, "w")) == false) {
return false;
}
fputs($fp, implode("", $file[1]));
fclose($fp);
return true;
}
/* Comienza la diversion*/
error_reporting(E_ALL & ~E_NOTICE); /*activo todos los errores de php*/
/*cuento la cantdad de argumentos*/
if (count($argv) < 3) {
help_exit();
} else if (in_array($argv[1], array("public", "private")) == false) {
help_exit();
}
/*guardo el primer argumento en la variable modulos*/
$module = $argv[2];
/* Valida el nombre del modulo*/
$module_characters = VALIDATE_NONCAPITALS . VALIDATE_NUMBERS . "/_";
if (valid_input($module, $module_characters) == false) {
exit("Nombre de modulo invalido.\n");
}
/* Verifica si el modulo ya existe*/
if ( module_exists($module, $argv[1], true) ) {
exit;
}
/* Creo los directorios*/
$locations = array("controllers", "models");
$ofs = 0;
while (($pos = strpos($module, "/", $ofs)) !== false) {
$ofs = $pos + 1;
$subdir = "/".substr($module, 0, $pos);
foreach ($locations as $location) {
if (file_exists($location.$subdir) == false) {
printf("Creando directorios %s%s.\n", $location, $subdir);
mkdir($location.$subdir, 0755, true);
}
}
}
/* Copia de la plantillas*/
print "Creando el controlador, el modelo, la vista y los archivos asociados.\n";
safe_copy("extras/plantillas/controller.php", "controllers/$module.php");
print "Creando controllers/$module.php.\n";
safe_copy("extras/plantillas/model.php", "models/$module.php");
/* Seteando el nombre del modulo*/
print "Configurando...\n";
set_nombres('controllers', $module);
set_nombres('models', $module);
/* cargo el archivo de configuracion*/
$config = parse_ini_file('modules.ini', true);
$mode = ($argv[1] == 'private') ? 'admin' : 'page';
/*añado la informacion nueva*/
$config[$argv[1]][$mode][] = $module;
/*finalmente escribo el archivo*/
write_ini_file('modules.ini', $config);
print "Listo!.\n";

10
public/.htaccess Normal file
View File

@ -0,0 +1,10 @@
RewriteCond %{HTTP:Authorization} .
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
<IfModule rewrite_module>
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !/(css|fonts|img|js)(/|$)
RewriteCond %{REQUEST_FILENAME} !/(favicon.ico|robots.txt)$
RewriteRule . /index.php [QSA,L]
</IfModule>

40
public/index.php Executable file
View File

@ -0,0 +1,40 @@
<?php
/*
____ _ _
/ ___|_ _ __ _ ___| |__ (_)
| | _| | | |/ _` |/ __| '_ \| |
| |_| | |_| | (_| | (__| | | | |
\____|\__,_|\__,_|\___|_| |_|_|
Copyright (c) 2014 Díaz Víctor aka (Máster Vitronic)
Copyright (c) 2018 Díaz Víctor aka (Máster Vitronic)
<vitronic2@gmail.com> <mastervitronic@vitronic.com.ve>
*/
require_once realpath(dirname( __DIR__ ) ) . '/lib/guachi.php';
require_once realpath(dirname( __DIR__ ) ) . '/lib/security.php';
/*Iniciamos todas las instancias*/
$auth = auth::iniciar();
$router = router::iniciar();
//$view = view::iniciar();
$view = null;
/*Se incluye el modelo*/
if (file_exists($file = DIR_MODELS.$router->module.".php")) {
require_once($file);
}
/*Se incluye el controlador*/
if (file_exists($file = DIR_CONTROLLERS.$router->module.".php")) {
require_once($file);
$controller_class = str_replace("/", "_", $router->module)."_controller";
if (class_exists($controller_class) == false) {
print "Controller class '".$controller_class."' does not exist.\n";
} else if (is_subclass_of($controller_class, "controller") == false) {
print "Controller class '".$controller_class."' does not extend controller class.\n";
} else {
$_controller = new $controller_class($db, $auth, $router, $view);
$_controller->execute();
unset($_controller);
}
}

26
server-sample Executable file
View File

@ -0,0 +1,26 @@
#!/usr/bin/env sh
# Guachi (Lightweight and very simple web development framework)
# https://gitlab.com/vitronic/Guachi_Framework
#
# Copyright (c) 2018 Díaz Devera Víctor (Máster Vitronic)
# Licensed under the MIT license.
# For development use only!
# @see https://secure.php.net/manual/en/features.commandline.webserver.php
# Warning!
# This web server was designed to aid application development. It may also be
# useful for testing purposes or for application demonstrations that are run
# in controlled environments. It is not intended to be a full-featured web server.
# It should not be used on a public network.
. ./.env
if [ -s env ]; then
. env
fi
# to run this must be `authbind --deep ./server-sample`
# previously do instalation of authbind and chown the owner by user that run of /etc/authbind/byport/$APP_PORT}
env php -S ${APP_HOST} -S ${APP_HOST}:${APP_PORT} -t public