Initial commit: plantilla base PHP para webs Acai CMS

This commit is contained in:
Jordan
2026-02-21 21:13:57 +00:00
commit d083259ee9
322 changed files with 62738 additions and 0 deletions

36
.docker/Dockerfile Normal file
View File

@@ -0,0 +1,36 @@
FROM php:8.2-apache
# Instalar dependencias para GD
RUN apt-get update && apt-get install -y \
libfreetype6-dev \
libjpeg62-turbo-dev \
libpng-dev \
libwebp-dev \
libzip-dev \
&& rm -rf /var/lib/apt/lists/*
# Configurar y instalar extensiones PHP
RUN docker-php-ext-configure gd --with-freetype --with-jpeg --with-webp \
&& docker-php-ext-install -j$(nproc) gd mysqli pdo pdo_mysql zip
# Instalar extension Redis
RUN pecl install redis && docker-php-ext-enable redis
# short_open_tag
RUN echo "short_open_tag = On" > /usr/local/etc/php/conf.d/short-tags.ini
# Modulos Apache
RUN a2enmod rewrite headers deflate expires
# AllowOverride All para .htaccess
RUN sed -i '/<Directory \/var\/www\/>/,/<\/Directory>/ s/AllowOverride None/AllowOverride All/' /etc/apache2/apache2.conf && \
sed -i '/<Directory \/var\/www\/>/,/<\/Directory>/ s/Options Indexes FollowSymLinks/Options Indexes FollowSymLinks/' /etc/apache2/apache2.conf
# ServerName
RUN echo "ServerName localhost" >> /etc/apache2/apache2.conf
# Cliente MariaDB para importar SQL
RUN apt-get update && apt-get install -y mariadb-client && rm -rf /var/lib/apt/lists/*
WORKDIR /var/www/html
EXPOSE 80

View File

@@ -0,0 +1,64 @@
services:
web:
build: .
container_name: dw-quantumasis-web-completa-web
labels:
docker-web: "true"
docker-web-project: "quantumasis-web-completa"
ports:
- "8080:80"
volumes:
- /Users/jordandiaz/Documents/GitHub/quantumasis-web-completa:/var/www/html
- ./init.sh:/docker-entrypoint-init.d/init.sh
- ./quantu_web2134-209-184-114-2-2619-49.sql:/docker-entrypoint-init.d/quantu_web2134-209-184-114-2-2619-49.sql
environment:
- DB_SERVER=${DB_SERVER}
- DB_DATABASE=${DB_DATABASE}
- DB_USERNAME=${DB_USERNAME}
- DB_PASSWORD=${DB_PASSWORD}
depends_on:
db:
condition: service_healthy
command: >
bash -c "chmod +x /docker-entrypoint-init.d/init.sh &&
/docker-entrypoint-init.d/init.sh &&
apache2-foreground"
db:
image: mariadb:10.11
container_name: dw-quantumasis-web-completa-db
labels:
docker-web: "true"
docker-web-project: "quantumasis-web-completa"
environment:
- MYSQL_ROOT_PASSWORD=${DB_ROOT_PASSWORD}
- MYSQL_DATABASE=${DB_DATABASE}
- MYSQL_USER=${DB_USERNAME}
- MYSQL_PASSWORD=${DB_PASSWORD}
volumes:
- db_data:/var/lib/mysql
ports:
- "33060:3306"
healthcheck:
test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
interval: 10s
timeout: 5s
retries: 5
redis:
image: redis:7-alpine
container_name: dw-quantumasis-web-completa-redis
labels:
docker-web: "true"
docker-web-project: "quantumasis-web-completa"
restart: unless-stopped
network_mode: "service:web"
depends_on:
- web
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 5s
retries: 3
volumes:
db_data:

21
.docker/init.sh Executable file
View File

@@ -0,0 +1,21 @@
#!/bin/bash
echo "Esperando a que la base de datos este lista..."
sleep 5
TABLE_COUNT=$(mysql -h"$DB_SERVER" -u"$DB_USERNAME" -p"$DB_PASSWORD" "$DB_DATABASE" --skip-ssl -e "SHOW TABLES;" 2>/dev/null | wc -l)
if [ "$TABLE_COUNT" -le 1 ]; then
SQL_FILE=$(find /docker-entrypoint-init.d/ -name "*.sql" -type f 2>/dev/null | head -1)
if [ -n "$SQL_FILE" ]; then
echo "Importando base de datos desde $SQL_FILE..."
mysql -h"$DB_SERVER" -u"$DB_USERNAME" -p"$DB_PASSWORD" "$DB_DATABASE" --skip-ssl < "$SQL_FILE"
echo "Base de datos importada correctamente."
else
echo "Advertencia: No se encontro archivo .sql para importar"
fi
else
echo "La base de datos ya contiene $TABLE_COUNT tablas. Omitiendo importacion."
fi
echo "Inicializacion completada."

3
.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
cms/uploads/
cms/data/cache/
.DS_Store

272
.htaccess Executable file
View File

@@ -0,0 +1,272 @@
<IfModule mod_deflate.c>
AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css text/javascript application/javascript application/json
</IfModule>
<IfModule mod_headers.c>
Header set X-XSS-Protection "1; mode=block"
Header set X-Content-Type-Options nosniff
Header set Access-Control-Allow-Origin "*"
Header set Access-Control-Allow-Headers "Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With, X-Acai-Token"
</IfModule>
<FilesMatch "\.(vue)$">
<IfModule mod_expires.c>
ExpiresActive Off
</IfModule>
<IfModule mod_headers.c>
FileETag None
Header unset ETag
Header unset Pragma
Header unset Cache-Control
Header unset Last-Modified
Header set Pragma "no-cache"
Header set Cache-Control "max-age=0, no-cache, no-store, must-revalidate"
Header set Expires "jue, 1 Jan 1970 00:00:00 GMT"
</IfModule>
</FilesMatch>
#php_flag opcache.enable Off
<IfModule mod_expires.c>
ExpiresActive On
ExpiresByType image/jpg "access 1 year"
ExpiresByType image/jpeg "access 1 year"
ExpiresByType image/gif "access 1 year"
ExpiresByType image/png "access 1 year"
ExpiresByType image/webp "access 1 year"
ExpiresByType image/svg+xml "access 1 year"
ExpiresByType font/opentype "access 1 year"
ExpiresByType font/ttf "access 1 year"
ExpiresByType text/css "access 1 year"
ExpiresByType application/pdf "access 1 month"
ExpiresByType application/javascript "access 1 year"
ExpiresByType application/x-javascript "access 1 year"
ExpiresByType application/x-shockwave-flash "access 1 year"
ExpiresByType image/x-icon "access 1 year"
ExpiresDefault "access 2 days"
</IfModule>
<IfModule mod_filter.c>
AddOutputFilterByType DEFLATE "application/atom+xml" \
"application/javascript" \
"application/json" \
"application/ld+json" \
"application/manifest+json" \
"application/rdf+xml" \
"application/rss+xml" \
"application/schema+json" \
"application/vnd.geo+json" \
"application/vnd.ms-fontobject" \
"application/x-font-ttf" \
"application/x-javascript" \
"application/x-web-app-manifest+json" \
"application/xhtml+xml" \
"application/xml" \
"font/eot" \
"font/opentype" \
"image/bmp" \
"image/svg+xml" \
"image/vnd.microsoft.icon" \
"image/x-icon" \
"text/cache-manifest" \
"text/css" \
"text/html" \
"text/javascript" \
"text/plain" \
"text/vcard" \
"text/vnd.rim.location.xloc" \
"text/vtt" \
"text/x-component" \
"text/x-cross-domain-policy" \
"text/xml"
</IfModule>
# Use HTTP Strict Transport Security to force client to use secure connections only
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
<Files ~ "\.tpl$">
Order allow,deny
Deny from all
</Files>
Options -Indexes
Options +FollowSymLinks
Options -MultiViews
DirectoryIndex index.php
ErrorDocument 404 /404.php
ErrorDocument 403 /403.php
ErrorDocument 400 /400.php
ErrorDocument 500 /500.php
ErrorDocument 401 /401.php
#php_value memory_limit 256M
<IfModule mod_rewrite.c>
# Activar RewriteEngine
RewriteEngine on
RewriteCond %{REQUEST_URI} /index.php
RewriteRule ^(.+[^/])$ / [R=301,L]
RewriteCond %{REQUEST_URI} /+[^\.]+$
RewriteRule ^(.+[^/])$ %{REQUEST_URI}/ [R=301,L]
# Redirección a HTTPS y a WWW
RewriteCond %{SERVER_PORT} 80
RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R=301,L]
RewriteCond %{HTTP_HOST} ^www.quantumasis.plandeweb.com [NC]
RewriteRule ^(.*)$ https://quantumasis.plandeweb.com/$1 [L,R=301]
RewriteCond %{HTTP_HOST} ^www.lightbeecorp.com [NC]
RewriteRule ^(.*)$ https://lightbeecorp.com/$1 [L,R=301]
RewriteCond %{HTTP_HOST} ^www.lightbee-corp.com [NC]
RewriteRule ^(.*)$ https://lightbee-corp.com/$1 [L,R=301]
RewriteCond %{HTTP_HOST} ^www.opticaingenio.com [NC]
RewriteRule ^(.*)$ https://opticaingenio.com/$1 [L,R=301]
RewriteCond %{HTTP_HOST} ^www.grancanariavv.com [NC]
RewriteRule ^(.*)$ https://grancanariavv.com/$1 [L,R=301]
RewriteCond %{HTTP_HOST} ^www.vmcprevensys.com [NC]
RewriteRule ^(.*)$ https://vmcprevensys.com/$1 [L,R=301]
RewriteCond %{HTTP_HOST} ^www.clorofilachef.com [NC]
RewriteRule ^(.*)$ https://clorofilachef.com/$1 [L,R=301]
RewriteCond %{HTTP_HOST} ^www.grupoquintanas.com [NC]
RewriteRule ^(.*)$ https://grupoquintanas.com/$1 [L,R=301]
RewriteCond %{HTTP_HOST} ^www.mabriba.es [NC]
RewriteRule ^(.*)$ https://mabriba.es/$1 [L,R=301]
RewriteCond %{HTTP_HOST} ^www.nutibarainvest.com [NC]
RewriteRule ^(.*)$ https://nutibarainvest.com/$1 [L,R=301]
RewriteCond %{HTTP_HOST} ^www.seingroup.es [NC]
RewriteRule ^(.*)$ https://seingroup.es/$1 [L,R=301]
RewriteCond %{HTTP_HOST} ^www.elalpendredefelix.com [NC]
RewriteRule ^(.*)$ https://elalpendredefelix.com/$1 [L,R=301]
RewriteCond %{HTTP_HOST} ^www.marisagarcespsicologia.es [NC]
RewriteRule ^(.*)$ https://marisagarcespsicologia.es/$1 [L,R=301]
RewriteCond %{HTTP_HOST} ^www.betarealty.es [NC]
RewriteRule ^(.*)$ https://betarealty.es/$1 [L,R=301]
RewriteCond %{HTTP_HOST} ^www.comercial-yaumar.es [NC]
RewriteRule ^(.*)$ https://comercial-yaumar.es/$1 [L,R=301]
RewriteCond %{HTTP_HOST} ^www.doblelinea.com [NC]
RewriteRule ^(.*)$ https://doblelinea.com/$1 [L,R=301]
RewriteCond %{HTTP_HOST} ^www.vannagamma.com [NC]
RewriteRule ^(.*)$ https://vannagamma.com/$1 [L,R=301]
RewriteCond %{HTTP_HOST} ^www.fisioterapiamarcosleon.com [NC]
RewriteRule ^(.*)$ https://fisioterapiamarcosleon.com/$1 [L,R=301]
RewriteCond %{HTTP_HOST} ^www.clinicagaba.com [NC]
RewriteRule ^(.*)$ https://clinicagaba.com/$1 [L,R=301]
RewriteCond %{HTTP_HOST} ^www.regufarma.com [NC]
RewriteRule ^(.*)$ https://regufarma.com/$1 [L,R=301]
RewriteCond %{HTTP_HOST} ^www.mundoyc.com [NC]
RewriteRule ^(.*)$ https://mundoyc.com/$1 [L,R=301]
RewriteCond %{HTTP_HOST} ^www.usegturservicios.com [NC]
RewriteRule ^(.*)$ https://usegturservicios.com/$1 [L,R=301]
RewriteCond %{HTTP_HOST} ^www.tuyoga.es [NC]
RewriteRule ^(.*)$ https://tuyoga.es/$1 [L,R=301]
RewriteCond %{HTTP_HOST} ^www.clinica-ramos.com [NC]
RewriteRule ^(.*)$ https://clinica-ramos.com/$1 [L,R=301]
RewriteCond %{HTTP_HOST} ^www.terapeutaocupasionada.com [NC]
RewriteRule ^(.*)$ https://terapeutaocupasionada.com/$1 [L,R=301]
RewriteCond %{HTTP_HOST} ^www.pilarquijadacomunicacion.com [NC]
RewriteRule ^(.*)$ https://pilarquijadacomunicacion.com/$1 [L,R=301]
# RewriteCond %{HTTP_HOST} ^www.enredhadas.com [NC]
# RewriteRule ^(.*)$ https://enredhadas.com/$1 [L,R=301]
RewriteCond %{HTTP_HOST} ^www.bungalowselpalmital.es [NC]
RewriteRule ^(.*)$ https://bungalowselpalmital.es/$1 [L,R=301]
RewriteCond %{HTTP_HOST} ^www.barbaraleebtraducciones.com [NC]
RewriteRule ^(.*)$ https://barbaraleebtraducciones.com/$1 [L,R=301]
# FAVICON
RewriteRule ^favicon.ico$ /template/estandar/icons/favicon.ico [L]
# SITEMAP Y ROBOTS
RewriteRule ^sitemap\.xml /cms/sitemap.php [L]
RewriteRule ^robots\.txt /cms/robots.php [L]
# IDIOMAS
#RewriteRule ^es/(.*)$ /$1 [L]
# BLUR IMAGENES
RewriteRule ^blur/([a-zA-Z0-9-_./]*)(.*)$ blur.php?imagen=$1 [L]
# APARTADOS
RewriteRule ^apartados/([a-zA-Z0-9-_]*)/([0-9]+)\.html(.*)$ apartados.php?num=$2 [L]
# CONTENIDOS
RewriteRule ^contenidos/([a-zA-Z0-9-_]*)/([0-9]+)\.html(.*)$ contenidos.php?familia=$2 [L]
RewriteRule ^contenidos/([a-zA-Z0-9-_]*)/([a-zA-Z0-9-_]*)/([0-9]+)/([0-9]+)\.html(.*)$ contenidos.php?familia=$3&num=$4 [L]
# OTROS CONTENIDOS
RewriteRule ^otros-contenidos/([a-zA-Z0-9-_]*)/([0-9]+)\.html(.*)$ otros_contenidos.php?num=$2 [L]
# CONTACTO
RewriteRule ^contacto\.html(.*)$ contacto.php [L]
# CATEGORIAS
RewriteRule ^categorias/([a-zA-Z0-9-_]*)/([0-9]+)\.html(.*)$ productos.php?categoria=$2
# PRODUCTOS
RewriteRule ^productos/([a-zA-Z0-9-_]*)/([0-9]+)\.html(.*)$ productos.php?num=$2
# SERVICE WORKER
RewriteRule ^sw.js$ lib/sw/sw.php [L]
RewriteRule ^manifest.json$ lib/sw/manifest.php [L]
RewriteRule ^template/estandar/js/sw-controller.js$ lib/sw/sw-controller.php [L]
RewriteRule ^(.+)-hsh([A-Za-z0-9]+).(.+)$ $1.$3 [L]
RewriteRule ^custom-builder-style.css cms/lib/plugins/builder_saas/replace_code.php?getStyle=1 [L]
RewriteRule ^custom-builder-javascript.js cms/lib/plugins/builder_saas/replace_code.php?getJavascript=1 [L]
# CSS y JS
RewriteRule ^template/estandar/css/main.css$ lib/recursos.php?fileType=css [L]
RewriteRule ^template/estandar/js/main.js$ lib/recursos.php?fileType=js [L]
##############
# SLUG #
##############
#RewriteBase /dashboard-client/
#RewriteRule ^index\.html$ - [L]
#RewriteCond %{REQUEST_FILENAME} !-f
#RewriteCond %{REQUEST_FILENAME} !-d
#RewriteRule . /template/estandar/modulos/cuentadashboard_38o4db/index.html [L]
# Permitir acceso directo a la carpeta 2fa y sus archivos
RewriteCond %{REQUEST_URI} ^/2fa(/.*)?$
RewriteRule ^ - [L]
# ENLACES PERMANENTES
RewriteRule ^([a-zA-Z0-9-\/_]*)$ slug.php?enlace=$1&%{QUERY_STRING}&tipo=barra [L]
</IfModule>

2
.user.ini Executable file
View File

@@ -0,0 +1,2 @@
#opcache.enable = On
zlib.output_compression = 1

35
README.md Normal file
View File

@@ -0,0 +1,35 @@
# acai-vscode-webbase
Plantilla base PHP para webs locales de desarrollo con Acai CMS.
## Descripcion
Este repositorio contiene la estructura base que se usa al crear nuevas webs locales. Incluye los archivos PHP necesarios, configuracion de Apache, y la estructura de directorios del CMS.
## Estructura
```
.
├── index.php # Punto de entrada
├── header.php # Encabezado
├── footer.php # Pie de pagina
├── funciones.php # Funciones globales
├── slug.php # Gestion de URLs
├── sesion.php # Gestion de sesiones
├── apartados.php # Gestion de apartados
├── captcha.php # Verificacion CAPTCHA
├── .htaccess # Config Apache
├── .user.ini # Config PHP
├── .docker/ # Config Docker (Dockerfile, etc.)
├── cms/ # Core del CMS
│ ├── lib/ # Clases, handlers, plugins
│ ├── data/ # Schemas y cache
│ └── uploads/ # Archivos subidos
├── hooks/ # Hooks PHP del proyecto
├── template/ # Plantillas y modulos
└── cgi-bin/ # Scripts CGI
```
## Relacion con el servidor
El servidor (`acai-vscode-server`) referencia este directorio como `WEB_BASE_DIR` para copiar la estructura base al crear nuevas webs locales. Se configura en `~/.docker-web-gui/config.json` como `web_base_dir`.

35
apartados.php Executable file
View File

@@ -0,0 +1,35 @@
<?
require_once ("sesion.php");
require_once "funciones.php";
$apartado = CocoDB::get("apartados", "num=".intval(@$_REQUEST["num"]), "num DESC", 1);
$apartado = @$apartado[0]; // get first record
$configuracionRecord["titulo_de_pagina"] = t($apartado,"name")." - ".$configuracionRecord["titulo_de_pagina"];
if (@$apartado["titulo_de_pagina"]!="") $configuracionRecord["titulo_de_pagina"] = t($apartado,"titulo_de_pagina");
if (@$apartado["metatag_descripcion"]!="") $configuracionRecord["metatag_descripcion"] = t($apartado,"metatag_descripcion");
if (@$apartado["metatag_palabras"]!="") $configuracionRecord["metatag_palabras"] = t($apartado,"metatag_palabras");
if (!@$apartado) {
header("HTTP/1.0 404 Not Found");
include("header.php");
$apartado = [
"name" => '<div class="text-center"><span class="text-6xl font-bold text-gray-600">404</span></div>',
"content" => '<div class="text-center text-lg">'.t_var("La Página solicitada no existe. Disculpe las molestias")."<br><br><a href='/' class='p-4 border rounded-lg hover:bg-gray-300'>".t_var("Ir a inicio")."</a></div><style>.breadcrumb-v2{display:none;}</style>"
];
echo tpl("apartados",array("apartado" => $apartado));
include "footer.php";
die();
}
include("header.php");
$portada = CocoDB::get("portada","","",1);$portada = @$portada[0];
$config_apartados = array(
'portada' => @$portada,
'apartado' => $apartado
);
echo tpl('apartados',$config_apartados);
include("footer.php");
?>

55
captcha.php Executable file
View File

@@ -0,0 +1,55 @@
<?php
// Iniciamos sesión
session_start( );
// Indicamos el tamaño de nuestro captcha, puede ser aleatorio para mayor seguridad
$captchaTextSize = 7;
do {
// Generamos un string aleatorio y lo encriptamos con md5
$md5Hash = md5( microtime( ) * time() );
// Eliminamos cualquier caracter extraño
preg_replace( '([1aeilou0])', "", $md5Hash );
} while( strlen( $md5Hash ) < $captchaTextSize );
// necesitamos sólo 7 caracteres para este captcha
$key = substr( $md5Hash, 0, $captchaTextSize );
// Guardamos la clave en la variable de sesión. La clave esta encriptada.
$_SESSION['key_captcha'] = md5( $key );
// almacenamos la imagen base, el background.
$captchaImage = imagecreatefrompng( "template/estandar/images/captcha0.png" );
/*
Seleccionamos un color de texto. Cómo nuestro fondo es un verde agua, escogeremos un cólor verde para el texto. El color del texto es, preferentemente, el mismo que el del background, aunque un poco más oscuro para poder distnguirlo.
*/
$textColor = imagecolorallocate( $captchaImage, 255, 255, 255 );
/*
Seleccionamos un color para las líneas que queremos se dibujen en nuestro captcha. En este caso usaremos una mezcla entre verde y azul
*/
$lineColor = imagecolorallocate( $captchaImage, 200, 200, 200 );
// recuperamos el parametro tamaño de imagen
$imageInfo = getimagesize( "template/estandar/images/captcha0.png" );
// decidimos cuantas líneas queremos dibujar
$linesToDraw = 20;
// Añadimos las líneas de manera aleatoria
for( $i = 0; $i < $linesToDraw; $i++ ) {
// utilizamos la función mt_rand()
$xStart = mt_rand( 0, $imageInfo[ 0 ] );
$xEnd = mt_rand( 0, $imageInfo[ 0 ] );
// Dibujamos la linea en el captcha
imageline( $captchaImage, $xStart, 0, $xEnd, $imageInfo[1], $lineColor );
}
/*
Escribimos nuestro string aleatoriamente, utilizando una fuente true type. En este caso, estamos utilizando BitStream Vera Sans Bold, pero podemos utilizar cualquier otra.
*/
imagettftext( $captchaImage, 20, 0, 45, 35, $textColor, "template/estandar/fonts/VeraBd.ttf", $key );
/*
Mostramos nuestra imagen. Preparamos las cabeceras de la imagen previniendo que no se almacenen en la cache del navegado
*/
header ( "Content-type: image/png" );
header("Cache-Control: no-cache, must-revalidate");
header("Expires: Fri, 19 Jan 1994 05:00:00 GMT");
header("Pragma: no-cache");
imagepng( $captchaImage );
?>

2
cgi-bin/.htaccess Executable file
View File

@@ -0,0 +1,2 @@
Options -Indexes +ExecCGI
AddHandler cgi-script .cgi .pl

380
cms/lib/classes/CocoDB-copia.php Executable file
View File

@@ -0,0 +1,380 @@
<?php
class CocoDB {
private static $tableCache = [];
private static $uploadColumns = [];
/**
* Inserta registros en una tabla
* @destacar
* @category DB
* @param table: Tabla de inserción
* @param records: Lista de registros a insertar
* @param functions: Array asociativo con funciones a aplicar a cada key
* @param options: Lista de opciones posibles que pasarle al método
* @return Número de registros insertados
*/
static function insertRecords($table, $records, $functions = [], $options = []) {
if (!isset($records[0])) {
$records = [$records];
}
if (@$options["preSaveTempId"]) {
$preSave = true;
}
list($ignoreFields, $ignoreSchema, $prefix) = self::parse_options($options);
if (!$ignoreSchema) {
$schema = @loadSchema($table);
if (!@$schema) die('Error. Tabla no encontrada');
}
$sqlBase = self::prepareBaseSQL($prefix, $table, @$schema);
$result = 0;
$lastSaved = 0;
foreach ($records as $record):
$record = self::unsetKeys($record, $ignoreFields);
self::insertOrUpdate($record, $sqlBase, $result, null, $prefix.$table, $functions, $ignoreSchema, @$schema);
$lastSaved = mysql_insert_id();
foreach(self::$uploadColumns as $keyColumn => $uploadColumn){
foreach($uploadColumn as $keyCol => $urlPath){
self::insertRecords("uploads",[
"urlPath" => $urlPath,
"filePath" => realpath(__DIR__."/../../../".$urlPath),
"fieldName" => $keyColumn,
"recordNum" => $lastSaved,
"tableName" => $table,
"createdTime" => date("Y-m-d H:i:s"),
"order" => time() + $keyCol,
"width" => 640,
"height" => 480
],[],["ignoreSchema" => true]);
}
}
endforeach;
if (@$preSave) {
$query = "UPDATE {$prefix}uploads "
. " SET recordNum = LAST_INSERT_ID(), preSaveTempId = '' "
. " WHERE tableName = '".mysql_real_escape_string($table)."' AND "
. " preSaveTempId = '".mysql_real_escape_string($options["preSaveTempId"])."'";
mysql_query($query) or die("MySQL Error: ". htmlspecialchars(mysql_error()) . "\n");
$query = "UPDATE {$prefix}traducciones "
. " SET recordNum = LAST_INSERT_ID(), preSaveTempId = '' "
. " WHERE tableName = '".mysql_real_escape_string($table)."' AND "
. " preSaveTempId = '".mysql_real_escape_string($options["preSaveTempId"])."'";
mysql_query($query) or die("MySQL Error: ". htmlspecialchars(mysql_error()) . "\n");
}
if (@$options['return_last_id']) {
return $lastSaved;
}
return $result;
}
/**
* Elimina registros de una tabla
* @destacar
* @category DB
* @param table: Tabla de la que vamos a eliminar registros
* @param where: Array asociativo que recoge campo => valor, operador, or
* @return boolean que indica si se pudo ejecutar la consulta
*/
static function deleteRecords($table, $where, $options = []) {
list($_, $_, $prefix) = self::parse_options($options);
$where = self::parse_where($where, $table);
if (!@$where) return false;
$q = mysql_query("DELETE FROM $prefix$table WHERE $where");
if (!$q) return false;
return true;
}
/**
* Actualiza registros en una tabla
* @destacar
* @category DB
* @param table: Tabla de inserción
* @param records: Lista de registros a insertar
* @param functions: Array asociativo con funciones a aplicar a cada key
* @param options: Lista de opciones posibles que pasarle al método
* @return Número de registros insertados
*/
static function updateRecords($table, $records, $where, $functions = [], $options = []) {
if (!isset($records[0])) {
$records = [$records];
}
list($ignoreFields, $ignoreSchema, $prefix) = self::parse_options($options);
if (!$ignoreSchema) {
$schema = @loadSchema($table);
if (!@$schema) die('Error. Tabla no encontrada');
}
$sqlBase = self::prepareBaseSQL($prefix, $table, @$schema, true);
$result = 0;
foreach ($records as $record):
$record = self::unsetKeys($record, $ignoreFields);
// Está comentado, pero no se si hace falta, si se descomenta se rompe el guardar del Builder (Plugin)
// if (@$schema['menuType'] == 'category' && !isset($record['parentNum'])) {
// continue;
// }
self::insertOrUpdate($record, $sqlBase, $result, $where, $prefix.$table, $functions, $ignoreSchema, @$schema);
endforeach;
return $result;
}
/**
* Hace el insert o update de un único registro
* @param record: Registro con el que vamos a operar
* @param sqlBase: SQL Base
* @param result: Número de registros con los que hemos operado. In-out
* @param where: Where de la operación (solo si es un UPDATE)
* @param table: Tabla de la operación
* @param functions: Lista de funciones con las que podemos parsear un determinado valor
* @param ignoreSchema: Boolean que indica si vamos a ignorar el Schema o no
* @param schema: Schema de la tabla
*/
private static function insertOrUpdate($record, $sqlBase, &$result, $where = null, $table = null, $functions = null, $ignoreSchema = false, $schema = null) {
$sql = $sqlBase;
self::$uploadColumns = [];
foreach ($record as $key => $value):
$column_exists = self::column_exists($key, @$schema, $table);
if (!$column_exists) continue;
if (is_array($column_exists) && $column_exists["type"] === "upload"){
if (!is_array($value)) $value = [$value];
if (!isset(self::$uploadColumns[$key])) self::$uploadColumns[$key] = [];
foreach($value as $val){
self::$uploadColumns[$key][] = $val;
}
continue;
}
if (is_array($functions) && isset($functions[$key]) && is_callable($functions[$key])) {
$value = $functions[$key]($value);
}
else if (!$ignoreSchema) {
$value = self::parse_value_schema($value, $schema, $key);
}
if ($value === null) {
continue;
// return false;
}
if (is_array($value)) {
$value = json_encode($value);
}
$sql .= ", `$key`='".mysql_real_escape_string($value)."'";
endforeach;
if (@$where) {
$where = self::parse_where($where, $table);
$sql .= " WHERE ".$where;
}
if (mysql_query($sql)) {
$result++;
}else{
if(class_exists('API') && class_exists('ApiError'))
API::error(new ApiError(json_encode(["error" => mysql_error(),"sql" => $sql])));
else
die(json_encode(["error" => mysql_error(),"sql" => $sql]));
}
}
/**
* Función que prepara el SQL base dependiendo del schema y de si es INSERT o UPDATE
* @param prefix: Prefijo de la tabla
* @param table: Tabla de la operación
* @param schema: Schema de la tabla
* @param update: Boolean que indica si vamos a actualizar o insertar
* @return sql
*/
private static function prepareBaseSQL($prefix, $table, $schema = null, $update = false) {
$operation = $update ? "UPDATE" : "INSERT INTO";
if (@$schema) {
$d = date('Y-m-d H:i:s');
$t = time();
$sqlBase = "$operation $prefix$table SET updatedDate='$d'";
if (!$update) {
$sqlBase .= ", num=NULL, createdDate='$d', createdByUserNum=1, updatedByUserNum=1";
switch ($schema['menuType']) {
case 'category':
$sqlBase .= ", globalOrder=0, siblingOrder=0, lineage='', depth=0, breadcrumb=''";
break;
case 'multi':
$sqlBase .= ", dragSortOrder='$t'";
break;
default:
break;
}
}
}
else {
$sqlBase = "$operation $prefix$table SET num=".($update ? "num" : "NULL");
}
return $sqlBase;
}
/**
* Parsea las opciones de los métodos
* @return lista con las opciones ignoreFields, ignoreSchema y prefix
*/
private static function parse_options($options) {
global $TABLE_PREFIX;
$ignoreFields = ['num'];
if (@$options['ignoreFields']) {
$ignoreFields = array_merge($ignoreFields, $options['ignoreField']);
}
$ignoreSchema = @$options['ignoreSchema'] ?: false;
$prefix = isset($options["prefix"]) ? $options["prefix"] : $TABLE_PREFIX;
return [$ignoreFields, $ignoreSchema, $prefix];
}
/**
* Comprueba si una columna existe en una tabla
* @return boolean que indica si existe o no la columna
*/
private static function column_exists($key, $schema, $table) {
if (isset(self::$tableCache[$table]) && isset(self::$tableCache[$table][$key])) {
return self::$tableCache[$table][$key];
}
if ($schema && isset($schema[$key])) {
return $schema[$key];
}
$result = mysql_query("SHOW COLUMNS FROM `$table` LIKE '$key'");
$exists = mysql_num_rows($result) > 0;
self::cache_column($table, $key, $exists);
return $exists;
}
/**
* Cachea la comprobación de una columna en una tabla
*/
private static function cache_column($table, $column, $exists) {
if (!isset(self::$tableCache[$table])) {
self::$tableCache[$table] = [];
}
if (!isset(self::$tableCache[$table][$column])) {
self::$tableCache[$table][$column] = $exists;
}
}
/**
* Parsea el valor dependiendo del tipo de campo
* @return valor parseado
*/
private static function parse_value_schema($value, $schema, $key) {
switch($schema[$key]['type']) {
case 'list':
switch ($schema[$key]['listType']) {
case 'pulldownMulti':
if (is_array($value)) {
$value = "\t".join("\t", $value)."\t";
}
break;
default:
break;
}
break;
case 'multitext':
if (is_array($value)) {
$value = json_encode($value);
}
break;
case 'checkbox':
$value = @$value ? 1 : 0;
break;
default:
break;
}
return $value;
}
/**
* Parsea el where pasado por parámetro
* - or: Si se envía a true usa OR como enlace en lugar de AND
* - not: Si se envía a true se usa
* - operador: LIKE, IN, != o =
*
* @param where: String o array
* @return where
*/
private static function parse_where($where, $table) {
$builtWhere = "";
if (is_array($where)) {
foreach ($where as $key => $w):
if (is_array($w)) {
if (!isset($w["value"]) || !isset($w["column"])) return false;
$key = $w["column"];
if (!self::column_exists($key, null, $table)) return false;
$value = $w["value"];
$enlace = @$w["or"] ? "OR" : "AND";
$not = @$w["not"] ? "NOT " : "";
switch (strtoupper(@$w["operator"])) {
case "LIKE":
$value = "'".mysql_real_escape_string($value)."'";
$operador = "LIKE";
break;
case "IN":
if (is_array($value)) {
$value = join(", ", array_map(function($a) {
if (is_int($a)) return intval($a);
if (is_numeric($a)) return floatval($a);
return "'".mysql_real_escape_string($a)."'";
}, $value));
}
$value = "(".$value.")";
$operador = "IN";
break;
case "!=":
$value = "'".mysql_real_escape_string($value)."'";
$operador = "!=";
break;
default:
$value = "'".mysql_real_escape_string($value)."'";
$operador = "=";
}
if (@$builtWhere) $builtWhere .= " $enlace ";
$builtWhere .= "`$key` $not$operador $value";
}
else {
if (@$builtWhere) $builtWhere .= " AND ";
$builtWhere .= "`$key`='".mysql_real_escape_string($w)."'";
}
endforeach;
}
else {
$builtWhere = $where;
}
return $builtWhere;
}
/**
* Elimina del primer array las claves pasadas en el segundo parámetro
* @param array: Array del que vamos a eliminar las keys
* @param keys: Array que contiene las keys que queremos eliminar
* @return nuevo array
*/
private static function unsetKeys($array, $keys) {
$c = $array;
foreach ($keys as $removeKey) {
unset($c[$removeKey]);
}
return $c;
}
}

1415
cms/lib/classes/CocoDB.php Executable file

File diff suppressed because it is too large Load Diff

468
cms/lib/classes/CocoEmail.php Executable file
View File

@@ -0,0 +1,468 @@
<?php
if(!defined('COCO_EMAIL_SERVER_HTTP_HOST')) {
define("COCO_EMAIL_SERVER_HTTP_HOST", $_SERVER["HTTP_HOST"]);
}
class CocoEmail {
static $table = 'correos';
static $field_key = 'identificador';
static $field_subject = 'asunto';
static $field_header = 'cabecera';
static $field_content = 'cuerpo';
static $field_footer = 'pie';
static $field_styles = 'estilos';
//Error en clase de phpmailer en la funcion encodeFile() por set_magic_quotes y get_magic_quotes se eliminaron en php 8
//Esto espera un array de filePaths de archivos a adjuntar
static $attach_files = [];
static $encode_with_base64 = false;
static $debug = false;
static $smtp = false;
static $verify = false;
static $show_variables = false;
static $stop_sending_emails = false;
static $webhook_url = "";
static $webhook_function = null;
static $smtp_data = [
"host" => "smtp.gmail.com",
"secure" => "ssl",
"port" => 465,
"username" => "soporte@cocosolution.com",
"password" => "",
"from" => "soporte@cocosolution.com",
"from_name" => "",
];
static $use_dkim = false;
static $dkim = [
'DKIM_domain' => 'cocosolution.com',
'DKIM_selector' => 'default',
'DKIM_private' => __DIR__ . '/default',
'DKIM_identity' => 'soporte@cocosolution.com',
];
static $bloqued_emails = [];
static $mail_data = [
"from" => "",
"from_name" => "",
];
static $replyTo = [
"to" => "",
"to_name" => "",
];
static $send_copy_to = [];
static $send_blind_copy_to = [];
static $template = "
<html>
<head>
<title>{{TITLE}}</title>
<style>{{STYLES}}</style>
</head>
<body>
<div id='contenido'>
{{HEADER}}
{{CONTENIDO}}
{{FOOTER}}
</div>
</body>
</html>
";
static $styles = "
body{font-family:Arial; color:#777; background-color:#F6F8FB;padding:20px;}
#contenido{max-width:640px; margin:0 auto; padding:20px; border: 1px solid #F6F8FB; background-color:#fff; border-radius:25px; -webkit-box-shadow:0px 0px 20px rgba(0,0,0,0.1); box-shadow:0px 0px 20px rgba(0,0,0,0.1);}
#contenido img {max-width: 100%;}
h3{font-weight:normal; color:#111;}
a{color:#CE482F; text-decoration:none;}
table td{border:solid 1px #ddd; padding:5px; width:100%; margin:0px;}
";
static $header = "
<center>
<img alt='' src='https://".COCO_EMAIL_SERVER_HTTP_HOST."/template/estandar/images/logo.png' style='max-width:100%; width:200px;'>
</center>
<br>
";
static $footer = "";
/**
* Envía un correo y parsea su contenido con las variables pasadas por parámetro
*
* @param string $key
* @param array $params
* @param array $to
* @param string $subject
* @param boolean $returnHTML
* @param array options : [
"twig" : Boolean -> Twig Mode,
"base64Decode" : Boolean -> Decode content from base64 to ascii
]
* @return void
*/
static function send($key = null, $params = [], $to = [], $subject = null, $content = null, $returnHTML = false, $options = []) {
global $TABLE_PREFIX;
if ($key) {
$key = mysql_real_escape_string($key);
$record = mysql_fetch_assoc(mysql_query("SELECT * FROM $TABLE_PREFIX".self::$table." WHERE `".self::$field_key."` LIKE '$key'"));
if (!$record) {
throw new Exception('Correo no encontrado');
}
$record["tableName"] = self::$table;
}
else if ($content) {
$record = [
self::$field_subject => $subject,
self::$field_content => $content
];
}
else {
throw new Exception('Tienes que enviar la clave o el contenido');
}
if (!is_array($to)) {
$to = explode(',', $to);
}
$to = array_filter(array_map('trim', $to), function($a) {
return filter_var($a, FILTER_VALIDATE_EMAIL);
});
if (@$options["base64Decode"]) {
$content = base64_decode(t($record,self::$field_content));
}else{
$content = t($record, self::$field_content);
}
$content = self::parse($content, $params,@$options ?: []);
$subject = t($record, self::$field_subject);
$subject = self::parse($subject, $params, $options);
$header = t($record, self::$field_header);
if(@$header) self::$header = self::parse($header, $params);
$footer = t($record, self::$field_footer);
if(@$footer) self::$footer = self::parse($footer, $params);
$styles = t($record, self::$field_styles);
if(@$styles) self::$styles = self::parse($styles, $params);
if ($returnHTML) {
return $content;
}
if (empty($to)) {
throw new Exception('No hay destinatarios válidos');
}
if (!$subject && $record) $subject = t($record, self::$field_subject);
$result = [];
foreach ($to as $destinatario) {
$resultString = self::send_email_coco_proxy($destinatario, $subject, $content);
$result[] = @json_decode($resultString,true) ?: ["success" => false, "message" => "Error decoding response", "raw_response" => $resultString];
}
self::$attach_files = [];
return $result;
}
/*
options : [
"twig" : Boolean -> Twig Mode
]
*/
static function parse($content, $params, $options = []) {
if (@$options["twig"]){
if (!function_exists("compileTWIG") && file_exists(__DIR__."/../plugins/builder_saas")) require_once __DIR__."/../plugins/builder_saas/builder_functions.php";
$tempFolder = sys_get_temp_dir()."/".md5($content);
$content = html_entity_decode($content);
if (!file_exists($tempFolder)) mkdir($tempFolder);
if (!file_exists($tempFolder."/index.twig")){
$php = compileTWIG($content,$tempFolder);
file_put_contents($tempFolder."/index.twig",$php);
}else{
$php = file_get_contents($tempFolder."/index.twig");
}
ob_start();
require($tempFolder."/index.twig");
$acaiResultData->doDisplay($params);
$resultado = ob_get_clean();
return $resultado;
}else{
$params = self::array_change_key_case_recursive($params);
$params_parsed = [];
foreach ($params as $key => $param) {
if (isset($param['tablename'])) {
$params_parsed[strtolower($param['tablename'])] = $param;
}
else {
$key = str_replace(['{', '}'], ['', ''], $key);
$params_parsed[$key] = $param;
}
}
return preg_replace_callback("/{([^}]+)}/", function($matches) use($params_parsed) {
$token = explode(".", strtolower($matches[1]));
// Comprobamos si es un token simple o compuesto
if (count($token) === 1) {
// Token simple. Comprobamos si se refiere a una tabla o un valor fijo
if (isset($params_parsed[$token[0]])) {
if (is_array($params_parsed[$token[0]])) {
// Es un array. Devolvemos su mainField o, en su defecto, el primer campo que encontremos
if (isset($params_parsed[$token[0]]['mainfieldbreadcrumb'])) {
return $params_parsed[$token[0]]['mainfieldbreadcrumb'];
}
reset($params_parsed);
return t($params_parsed, key($params_parsed));
}
else {
// Es un valor fijo
return $params_parsed[$token[0]];
}
}
else {
return self::$show_variables ? '{'.$matches[1].'}' : '-';
}
}
else {
// Es un token compuesto. Lo recorremos hasta que no queden más tokens y devolvemos el resultado
if (!isset($params_parsed[$token[0]]) || !is_array($params_parsed[$token[0]])) return '{'.$matches[1].'}';
$i = 0;
$current = $params_parsed;
do {
$tok = $token[$i];
if (!isset($current[$tok])) return '{'.$matches[1].'}';
$current = $current[$tok];
$i += 1;
} while ($i < count($token));
return $current;
}
}, $content);
}
}
static function array_change_key_case_recursive($arr) {
return array_map(function($item){
if(is_array($item))
$item = self::array_change_key_case_recursive($item);
return $item;
}, array_change_key_case($arr));
}
function encrypt($string, $key) {
$result = '';
for($i=0; $i<strlen($string); $i++) {
$char = substr($string, $i, 1);
$keychar = substr($key, ($i % strlen($key))-1, 1);
$char = chr(ord($char)+ord($keychar));
$result.=$char;
}
return base64_encode($result);
}
static function send_email_coco_proxy($destinatario="soporte@cocosolution.com", $asunto="Error al enviar correo", $contenido="", $respuesta="") {
$data = [
"smtp_data" => self::$smtp_data,
"mail_data" => self::$mail_data,
"replyTo" => self::$replyTo,
"send_copy_to" => self::$send_copy_to,
"params" => [
"to" => $destinatario,
"subject" => $asunto,
"body" => $contenido
],
"bloqued_emails" => self::$bloqued_emails,
"encode_with_base64" => self::$encode_with_base64,
"template" => self::$template,
"styles" => self::$styles,
"header" => self::$header,
"footer" => self::$footer
];
//$encryptData = self::encrypt(json_encode($data), "Analiticaempresas17");
$opts = array('http' =>
array(
'method' => 'POST',
'header' => 'Content-Type: application/json',
'content' => json_encode($data)
)
);
$context = stream_context_create($opts);
$result = file_get_contents("https://cocosolution.com/?sendQuantumEmail=1", false, $context);
return $result;
}
static function send_email($destinatario="soporte@cocosolution.com", $asunto="Error al enviar correo", $contenido="", $respuesta="") {
global $configuracionRecord;
if (in_array($destinatario,self::$bloqued_emails)) die("Testing");
if (!isset($configuracionRecord)){
$configuracionRecord = @CocoDB::get("configuracion","num != 0")[0];
}
require_once __DIR__ . '/../vendor/PHPMailer/PHPMailerAutoload.php';
/*$mensaje = "
<html>
<head>
<title>".$asunto."</title>
<style>
body{font-family:Arial;color:#777;background-color:#F6F8FB}
#contenido{max-width:640px;margin:0 auto;padding:20px;background-color:#fff;border-radius:25px;-webkit-box-shadow:0px 0px 20px rgba(0,0,0,0.1);box-shadow:0px 0px 20px rgba(0,0,0,0.1);}
h3{font-weight:normal;color:#111;}
a{color:#CE482F;text-decoration:none;}
table td{border:solid 1px #ddd;padding:5px;width:100%;margin:0px;}
</style>
</head>
<body>
<div id='contenido'>
<center><img alt='' src='https://".$_SERVER["HTTP_HOST"]."/template/estandar/images/logo.png' style='max-width:100%; width:200px;'></center>
<br>
".$contenido."
</div>
</body>
</html>
";*/
$mensaje = self::$template;
$mensaje = str_replace('{{STYLES}}', self::$styles, $mensaje);
$mensaje = str_replace('{{HEADER}}', self::$header, $mensaje);
$mensaje = str_replace('{{TITLE}}', $asunto, $mensaje);
$mensaje = str_replace('{{CONTENIDO}}', $contenido, $mensaje);
$mensaje = str_replace('{{FOOTER}}', self::$footer, $mensaje);
try {
$mail = new PHPMailer();
// Basic
$mail->CharSet = "UTF-8";
if(self::$encode_with_base64) $mail->Encoding = "base64";
$mail->IsHTML(true);
//Debug
if(self::$debug) {
$mail->SMTPDebug = 4;
echo "<br>";
echo $mensaje;
echo "<br><br>";
var_dump([
'To:' => $destinatario,
'Asunto' => $asunto,
'Contenido' => $mensaje
]);
echo "<br>";
}
// SMTP
if(self::$smtp) {
$mail->Host = self::$smtp_data['host'];
$mail->IsSMTP();
$mail->SMTPAuth = true;
if(self::$smtp_data['secure'])
$mail->SMTPSecure = self::$smtp_data['secure'];
$mail->Helo = @self::$smtp_data['helo'] ?:'webs.cocosolution.com';
$mail->Port = self::$smtp_data['port'];
$mail->Username = self::$smtp_data['username'];
$mail->Password = self::$smtp_data['password'];
$mail->SetFrom(self::$smtp_data['from'], self::$smtp_data['from_name']);
}
// DKIM
if (self::$use_dkim) {
$mail->DKIM_domain = self::$dkim['DKIM_domain'];
$mail->DKIM_private = self::$dkim['DKIM_private'];
$mail->DKIM_selector = self::$dkim['DKIM_selector'];
$mail->DKIM_identity = self::$dkim['DKIM_identity'];
}
// Config
if(!self::$smtp) {
$mail->setFrom(self::$mail_data["from"] ?: $configuracionRecord["correo_admin"], self::$mail_data["from_name"] ?: $configuracionRecord["tienda_nombre_empresa"]);
}
$mail->addReplyTo(self::$replyTo["to"] ?: $configuracionRecord["correo_admin"], self::$replyTo["to_name"] ?: $configuracionRecord["tienda_nombre_empresa"]);
if(self::$verify) {
$mail->AddAddress('check-auth-soporte=cocosolution.com@verifier.port25.com');
} else {
$mail->AddAddress($destinatario);
foreach (self::$send_copy_to as $email) {
$mail->AddCC($email);
}
foreach (self::$send_blind_copy_to as $email) {
$mail->addBCC($email);
}
}
$mail->Subject = $asunto;
$mail->msgHTML($mensaje);
foreach (self::$attach_files as $file) {
$mail->addAttachment($file,basename($file));
}
if(!self::$stop_sending_emails) {
$resultMail = $mail->Send();
try{
if (self::$webhook_url || self::$webhook_function){
$dataMail = [
"from" => $mail->From,
"from_name" => $mail->FromName,
"sender" => $mail->Sender,
"subject" => $mail->Subject,
"to" => $destinatario,
"body" => $mail->Body,
"alt_body" => $mail->AltBody,
"sended" => @$mail->ErrorInfo ? false : true,
"error" => @$mail->ErrorInfo
];
if (!empty(self::$webhook_url) && filter_var(self::$webhook_url, FILTER_VALIDATE_URL)) {
$opts = array('http' =>
array(
'method' => 'POST',
'header' => 'Content-Type: application/json',
'content' => json_encode($dataMail)
)
);
$context = stream_context_create($opts);
$result = file_get_contents(self::$webhook_url, false, $context);
}
if (is_callable(self::$webhook_function)) {
$resultFunction = call_user_func(self::$webhook_function,$dataMail);
}
}
} catch (Exception $e){
// En caso de error no hacemos nada
}
}
} catch (phpmailerException $e) {
echo $e->errorMessage(); //Pretty error messages from PHPMailer
} catch (Exception $e) {
echo $e->getMessage(); //Boring error messages from anything else!
}
}
}

300
cms/lib/classes/CocoEnlace.php Executable file
View File

@@ -0,0 +1,300 @@
<?
class CocoEnlace {
function __construct(){}
static function _seteaCampoEnlace($valores,$sufijoForzado="",$table = null,$generateAlias = true){
global $tableName,$TABLE_PREFIX,$SETTINGS,$CURRENT_USER,$schema;
if (!$table) $table = $tableName;
$enlaceNuevo = "";
$enlaceAnterior = "";
// ESTABLECEMOS CUAL ES EL CAMPO DETERMINANTE
$campo = self::_getTitleField($valores,$table,$schema);
if (@$valores["num"]){
// ALMACENAMOS SI HAY UN REGISTRO ANTERIOR
$registroAnterior = mysql_query("select * from ".$TABLE_PREFIX.$table." where num=".$valores["num"]);
if($registroAnterior) {
$registroAnterior = mysql_fetch_assoc(mysql_query("select * from ".$TABLE_PREFIX.$table." where num=".$valores["num"]));
if (@$registroAnterior) $enlaceAnterior = $registroAnterior["enlace"];
}
}
$prefijo = self::_getLinkPrefix($valores,$table);
$prefijoAnterior = isset($registroAnterior) ? self::_getLinkPrefix($registroAnterior,$table) : null;
$sufijo = "/";
if (!@$valores["enlace"]){
// SI NO HA ESCRITO NADA LO SETEAMOS POR DEFECTO
$estado = "Si no ponemos enlace";
$estadoNum = 0;
$nohay = true;
$valor = (@$campo&&@$valores[$campo]) ? "/".self::parsea_enlace($valores[$campo]) : "/".time();
$enlaceNuevo = $prefijo.$valor.$sufijoForzado.$sufijo;
}else{
// SI EN CAMBIO HA ESCRITO ALGO VAMOS A VER QUE PASA
$nohay = false;
if (@$valores["preSaveTempId"]){
// SI ES UN REGISTRO NUEVO LO DEJAMOS TAL CUAL
$estado = "Si ponemos enlace pero es nuevo registro";
$estadoNum = 1;
$enlaceNuevo = $valores["enlace"];
}else{
// SI ES UN REGISTRO EXISTENTE VAMOS A COMPROBAR SI HA CAMBIADO ALGO
if (@$registroAnterior){
if ($valores["enlace"]!=$registroAnterior["enlace"]){
// SI EL ENLACE ES DISTINTO AL ANTERIOR LO SETEAMOS TAL CUAL
$estado = "Si ponemos enlace, registro existente, enlace distinto";
$estadoNum = 2;
$enlaceNuevo = $valores["enlace"];
}else if ($valores[$campo]!=$registroAnterior[$campo]){
// SI EL ENLACE ES IGUAL AL ANTERIOR COMPROBAMOS EL TITLE ( O CAMPO QUE SEA )
// A VER SI ES DISTINTO
if (strpos($valores["enlace"],self::parsea_enlace($registroAnterior[$campo]))){
// SI EL ANTIGUO TITLE TENIA RELACION CON EL ENLACE LO SISTITUIMOS
// POR EL NUEVO TITLE
$estado = "Si ponemos enlace, registro existente, title distinto con title anterior relacionado con el enlace anterior";
$estadoNum = 3;
$enlaceNuevo = str_replace(self::parsea_enlace($registroAnterior[$campo]),self::parsea_enlace($valores[$campo]),$valores["enlace"]);
$enlaceNuevo = preg_replace("|_([a-zA-z0-9]*)$|","",$enlaceNuevo);
}else{
// SI NO TENIA RELACION LO DEJAMOS TAL CUAL
$estado = "Si ponemos enlace, registro existente, title distinto con title anterior NO relacionado con el enlace anterior";
$estadoNum = 4;
$enlaceNuevo = $valores["enlace"];
}
}else{
$estado = "Si ponemos enlace, registro existente, enlace igual";
$estadoNum = 5;
$enlaceNuevo = $valores["enlace"];
}
if (@$prefijo && @$prefijoAnterior && strpos($enlaceNuevo,$prefijoAnterior) !== false) {
// SI EL ANTIGUO CAMPO BREADCRUMB TENIA RELACION CON EL ENLACE LO SISTITUIMOS
// POR EL NUEVO VALOR DEL CAMPO BREADCRUMB
$estado = "Si ponemos enlace, registro existente, campo breadcrumb distinto con campo breadcrumb anterior relacionado con el enlace anterior";
$estadoNum = 7;
$enlaceNuevo = str_replace($prefijoAnterior,$prefijo,$enlaceNuevo);
$enlaceNuevo = preg_replace("|_([a-zA-z0-9]*)$|","",$enlaceNuevo);
}
}else{
// SI NO ENCUENTRO EL REGISTRO ANTERIOR
$estado = "Si ponemos enlace, registro existente, pero no lo encontramos";
$estadoNum = 6;
$enlaceNuevo = $valores["enlace"];
}
}
}
$idiomasViejo = self::_getEnlaceIdiomas($valores,$enlaceNuevo,$enlaceAnterior,$estadoNum,$table);
$idiomasNuevo = self::_seteaEnlaceIdiomas($valores,$enlaceNuevo,$enlaceAnterior,$estadoNum,$table);
/**************************/
// YA TENEMOS EL CAMPO SETEADO AHORA VAMOS A COMPROBAR SI YA HAY UNO
// AHORA COMPRUEBO SI HAY OTRO IGUAL EN LA BASE DE DATOS
/**************************/
$sql = "
SELECT DISTINCT TABLE_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE COLUMN_NAME IN ('enlace')
AND TABLE_SCHEMA='".$SETTINGS["mysql"]["database"]."'
";
$result = mysql_query($sql) or die(mysql_error());
while($record = mysql_fetch_assoc($result)){
if ($record["TABLE_NAME"]==$TABLE_PREFIX.$table){
$cadenaBusqueda = (@$valores["preSaveTempId"]) ? "num!=0" : "num!=".@$valores["num"];
$encontrado = mysql_fetch_assoc(mysql_query("SELECT * FROM ".$record["TABLE_NAME"]." WHERE enlace='".$enlaceNuevo."' AND ".$cadenaBusqueda." LIMIT 1"));
}else{
$encontrado = mysql_fetch_assoc(mysql_query("SELECT * FROM ".$record["TABLE_NAME"]." WHERE enlace='".$enlaceNuevo."' LIMIT 1"));
}
if (@$encontrado){
if ($nohay) {
$enlaceNuevo = self::_seteaCampoEnlace($valores,"_".base_convert(time(),10,36),$table,$generateAlias);
}else{
$enlaceNuevo = $enlaceNuevo."_".base_convert(time(),10,36).$sufijo; // str_replace(".html","_".base_convert(time(),10,36).".html",$enlaceNuevo);
}
}
}
/**************************/
// AHORA CREAMOS LOS ALIAS
/**************************/
if ($generateAlias){
$pruebas = @mysql_fetch_assoc(mysql_query("SELECT pagina_publicada FROM ".$TABLE_PREFIX."configuracion LIMIT 1"));
if (@$pruebas["pagina_publicada"]){
$idiomasViejo["es"] = $enlaceAnterior;
$idiomasNuevo["es"] = $enlaceNuevo;
foreach($idiomasNuevo as $idioma => $idiomaNuevo){
if (isset($idiomasViejo[$idioma]) && isset($idiomasNuevo[$idioma]) && $idiomasViejo[$idioma] != $idiomasNuevo[$idioma]){
$preSQL = "num=null, createdDate='".date("Y-m-d H:i:s")."', updatedDate='".date("Y-m-d H:i:s")."', createdByUserNum=1, updatedByUserNum=1, dragSortOrder=".time();
mysql_query("DELETE FROM ".$TABLE_PREFIX."alias_urls where url_alias='".$idiomasNuevo[$idioma]."'");
mysql_query("DELETE FROM ".$TABLE_PREFIX."alias_urls where url_alias='".$idiomasViejo[$idioma]."' AND url_destino='".$idiomasNuevo[$idioma]."'");
mysql_query("INSERT INTO ".$TABLE_PREFIX."alias_urls set ".$preSQL.", url_alias='".$idiomasViejo[$idioma]."', url_destino='".$idiomasNuevo[$idioma]."'");
mysql_query("UPDATE ".$TABLE_PREFIX."alias_urls set url_destino='".$idiomasNuevo[$idioma]."' where url_destino='".$idiomasViejo[$idioma]."'");
mysql_query("DELETE FROM ".$TABLE_PREFIX."alias_urls where url_alias=''");
}
}
}
}
return $enlaceNuevo;
}
static function _getEnlaceIdiomas($valores,$enlaceNuevo,$enlaceAnterior,$estado=0,$table = null){
global $SETTINGS,$tableName,$TABLE_PREFIX;
$result = [];
if (!$table) $table = $tableName;
$result = mysql_query_fetch_all_assoc("SELECT prefix,fieldValue FROM ".$TABLE_PREFIX."traducciones WHERE tableName='".$table."' and fieldName='enlace' and recordNum='".$valores["num"]."'");
if (!empty($result)) {
$result2 = [];
foreach($result as $rec){
$result2[$rec["prefix"]] = base64_decode($rec["fieldValue"]);
}
return $result2;
}
return $result;
}
static function _seteaEnlaceIdiomas($valores,$enlaceNuevo,$enlaceAnterior,$estado=0,$table = null){
global $SETTINGS,$tableName,$TABLE_PREFIX;
$result = [];
if (!$table) $table = $tableName;
// REINICIAMOS LOS ENLACES DE LOS IDIOMAS
//die("Aun falta establecer los enlaces para los idiomas así que el cdn está inservible hasta que se haga");
switch($estado){
case 5:
case 6:
case 4:
case 2:
// EN ESTE CASO NO HACEMOS NADA
break;
case 1:
// AL PONER ENLACE DE FORMA MANUAL NO HACEMOS NADA EN IDIOMAS
break;
case 3:
default:
mysql_query("DELETE FROM ".$TABLE_PREFIX."traducciones where tableName='".$table."' and fieldName='enlace' and recordNum='".$valores["num"]."'");
foreach($SETTINGS["idiomas"] as $key => $value):
if ($value&&$value!="www"){
$enlace = base64_encode("/".$value.$enlaceNuevo);
$result[$value] = "/".$value.$enlaceNuevo;
mysql_query("INSERT INTO ".$TABLE_PREFIX."traducciones set num=null,prefix='".$value."', tableName='".$table."', fieldName='enlace', fieldValue='".$enlace."', recordNum='".intval(@$valores["num"])."', preSaveTempId='".@$valores["preSaveTempId"]."'") or die(mysql_error());
}
endforeach;
}
return $result;
}
static function _getLinkPrefix($record,$table = null) {
global $tableName, $TABLE_PREFIX;
if (!$table) $table = $tableName;
$enlaces = array();
$record["tableName"] = $table;
$cont = 0;
while (true && $cont++ <= 50) { // Contador de seguridad para evitar el bucle infinito (que en teoría nunca pasará, jaja)
// Comprobamos si la tabla ha cambiado para no volver a cargar el schema
if ($record["tableName"] != @$tabla) {
$tabla = $record["tableName"];
if(class_exists('SchemaAPI')) {
$schema = SchemaAPI::getInstance()->loadSchema($tabla);
} else {
$schema = loadSchema($tabla);
}
$breadcrumbField = @$schema["breadcrumbField"];
if ($breadcrumbField == "parentNum") {
$schema[$breadcrumbField]["optionsTablename"] = $tabla;
$schema[$breadcrumbField]["optionsValueField"] = "num";
}
if (@$schema[$breadcrumbField]["optionsType"] == "query"){
preg_match("/SELECT ([0-9a-z_]*),[\s?]([_0-9a-z]*) FROM ([a-z_]*)/",$schema[$breadcrumbField]["optionsQuery"],$matches);
if (@$matches[1]) $schema[$breadcrumbField]["optionsValueField"] = $matches[1];
if (@$matches[3]) $schema[$breadcrumbField]["optionsTablename"] = str_replace($TABLE_PREFIX,"",$matches[3]);
}
}
if (!@$breadcrumbField || !@$schema[$breadcrumbField]["optionsTablename"]) {
break;
}
$record = @mysql_fetch_assoc(mysql_query("SELECT * FROM ".$TABLE_PREFIX.$schema[$breadcrumbField]["optionsTablename"]." WHERE `".$schema[$breadcrumbField]["optionsValueField"]."`='".$record[$breadcrumbField]."'"));
if (!@$record) break;
$record["tableName"] = $schema[$breadcrumbField]["optionsTablename"];
array_unshift($enlaces, $record);
}
if (!@$enlaces) return "";
$prefix = "/".join("/", array_map(function($a) {
return self::parsea_enlace($a[self::_getTitleField($a, $a["tableName"])]);
}, $enlaces));
return $prefix;
}
static function _getTitleField($record, $tabla, $schema = null) {
if (@$record["name"]) return "name";
if (@$record["title"]) return "title";
if (@$record["titulo"]) return "titulo";
if (@$record["nombre"]) return "nombre";
if (!@$campo) {
if(class_exists('SchemaAPI')) {
if (!@$schemaAux) $schemaAux = SchemaAPI::getInstance()->loadSchema($tabla);
} else {
if (!@$schemaAux) $schemaAux = loadSchema($tabla);
}
foreach ($schemaAux as $key => $value):
if (@$value["type"] == "textfield" && $key != "enlace") {
return $key;
break;
}
endforeach;
}
}
static function parsea_enlace($txt) {
$transliterationTable = array("" => "", ' ' => '',' ' => '','' => '', 'á' => 'a', 'Á' => 'A', 'à' => 'a', 'À' => 'A', 'ă' => 'a', 'Ă' => 'A', 'â' => 'a', 'Â' => 'A', 'å' => 'a', 'Å' => 'A', 'ã' => 'a', 'Ã' => 'A', 'ą' => 'a', 'Ą' => 'A', 'ā' => 'a', 'Ā' => 'A', 'ä' => 'a', 'Ä' => 'A', 'æ' => 'ae', 'Æ' => 'AE', 'ḃ' => 'b', 'Ḃ' => 'B', 'ć' => 'c', 'Ć' => 'C', 'ĉ' => 'c', 'Ĉ' => 'C', 'č' => 'c', 'Č' => 'C', 'ċ' => 'c', 'Ċ' => 'C', 'ç' => 'c', 'Ç' => 'C', 'ď' => 'd', 'Ď' => 'D', 'ḋ' => 'd', 'Ḋ' => 'D', 'đ' => 'd', 'Đ' => 'D', 'ð' => 'dh', 'Ð' => 'Dh', 'é' => 'e', 'É' => 'E', 'è' => 'e', 'È' => 'E', 'ĕ' => 'e', 'Ĕ' => 'E', 'ê' => 'e', 'Ê' => 'E', 'ě' => 'e', 'Ě' => 'E', 'ë' => 'e', 'Ë' => 'E', 'ė' => 'e', 'Ė' => 'E', 'ę' => 'e', 'Ę' => 'E', 'ē' => 'e', 'Ē' => 'E', 'ḟ' => 'f', 'Ḟ' => 'F', 'ƒ' => 'f', 'Ƒ' => 'F', 'ğ' => 'g', 'Ğ' => 'G', 'ĝ' => 'g', 'Ĝ' => 'G', 'ġ' => 'g', 'Ġ' => 'G', 'ģ' => 'g', 'Ģ' => 'G', 'ĥ' => 'h', 'Ĥ' => 'H', 'ħ' => 'h', 'Ħ' => 'H', 'í' => 'i', 'Í' => 'I', 'ì' => 'i', 'Ì' => 'I', 'î' => 'i', 'Î' => 'I', 'ï' => 'i', 'Ï' => 'I', 'ĩ' => 'i', 'Ĩ' => 'I', 'į' => 'i', 'Į' => 'I', 'ī' => 'i', 'Ī' => 'I', 'ĵ' => 'j', 'Ĵ' => 'J', 'ķ' => 'k', 'Ķ' => 'K', 'ĺ' => 'l', 'Ĺ' => 'L', 'ľ' => 'l', 'Ľ' => 'L', 'ļ' => 'l', 'Ļ' => 'L', 'ł' => 'l', 'Ł' => 'L', 'ṁ' => 'm', 'Ṁ' => 'M', 'ń' => 'n', 'Ń' => 'N', 'ň' => 'n', 'Ň' => 'N', 'ñ' => 'n', 'Ñ' => 'N', 'ņ' => 'n', 'Ņ' => 'N', 'ó' => 'o', 'Ó' => 'O', 'ò' => 'o', 'Ò' => 'O', 'ô' => 'o', 'Ô' => 'O', 'ő' => 'o', 'Ő' => 'O', 'õ' => 'o', 'Õ' => 'O', 'ø' => 'o', 'Ø' => 'O', 'ō' => 'o', 'Ō' => 'O', 'ơ' => 'o', 'Ơ' => 'O', 'ö' => 'o', 'Ö' => 'O', 'ṗ' => 'p', 'Ṗ' => 'P', 'ŕ' => 'r', 'Ŕ' => 'R', 'ř' => 'r', 'Ř' => 'R', 'ŗ' => 'r', 'Ŗ' => 'R', 'ś' => 's', 'Ś' => 'S', 'ŝ' => 's', 'Ŝ' => 'S', 'š' => 's', 'Š' => 'S', 'ṡ' => 's', 'Ṡ' => 'S', 'ş' => 's', 'Ş' => 'S', 'ș' => 's', 'Ș' => 'S', 'ß' => 'SS', 'ť' => 't', 'Ť' => 'T', 'ṫ' => 't', 'Ṫ' => 'T', 'ţ' => 't', 'Ţ' => 'T', 'ț' => 't', 'Ț' => 'T', 'ŧ' => 't', 'Ŧ' => 'T', 'ú' => 'u', 'Ú' => 'U', 'ù' => 'u', 'Ù' => 'U', 'ŭ' => 'u', 'Ŭ' => 'U', 'û' => 'u', 'Û' => 'U', 'ů' => 'u', 'Ů' => 'U', 'ű' => 'u', 'Ű' => 'U', 'ũ' => 'u', 'Ũ' => 'U', 'ų' => 'u', 'Ų' => 'U', 'ū' => 'u', 'Ū' => 'U', 'ư' => 'u', 'Ư' => 'U', 'ü' => 'u', 'Ü' => 'U', 'ẃ' => 'w', 'Ẃ' => 'W', 'ẁ' => 'w', 'Ẁ' => 'W', 'ŵ' => 'w', 'Ŵ' => 'W', 'ẅ' => 'w', 'Ẅ' => 'W', 'ý' => 'y', 'Ý' => 'Y', 'ỳ' => 'y', 'Ỳ' => 'Y', 'ŷ' => 'y', 'Ŷ' => 'Y', 'ÿ' => 'y', 'Ÿ' => 'Y', 'ź' => 'z', 'Ź' => 'Z', 'ž' => 'z', 'Ž' => 'Z', 'ż' => 'z', 'Ż' => 'Z', 'þ' => 'th', 'Þ' => 'Th', 'µ' => 'u', 'а' => 'a', 'А' => 'a', 'б' => 'b', 'Б' => 'b', 'в' => 'v', 'В' => 'v', 'г' => 'g', 'Г' => 'g', 'д' => 'd', 'Д' => 'd', 'е' => 'e', 'Е' => 'E', 'ё' => 'e', 'Ё' => 'E', 'ж' => 'zh', 'Ж' => 'zh', 'з' => 'z', 'З' => 'z', 'и' => 'i', 'И' => 'i', 'й' => 'j', 'Й' => 'j', 'к' => 'k', 'К' => 'k', 'л' => 'l', 'Л' => 'l', 'м' => 'm', 'М' => 'm', 'н' => 'n', 'Н' => 'n', 'о' => 'o', 'О' => 'o', 'п' => 'p', 'П' => 'p', 'р' => 'r', 'Р' => 'r', 'с' => 's', 'С' => 's', 'т' => 't', 'Т' => 't', 'у' => 'u', 'У' => 'u', 'ф' => 'f', 'Ф' => 'f', 'х' => 'h', 'Х' => 'h', 'ц' => 'c', 'Ц' => 'c', 'ч' => 'ch', 'Ч' => 'ch', 'ш' => 'sh', 'Ш' => 'sh', 'щ' => 'sch', 'Щ' => 'sch', 'ъ' => '', 'Ъ' => '', 'ы' => 'y', 'Ы' => 'y', 'ь' => '', 'Ь' => '', 'э' => 'e', 'Э' => 'e', 'ю' => 'ju', 'Ю' => 'ju', 'я' => 'ja', 'Я' => 'ja', "!" => "", "|" => "", "'" => "", "\"" => "", "'" => "", "@" => "", "·" => "", "#" => "", "$" => "", "¢" => "", "%" => "", "" => "", "¬" => "", "/" => "", "÷" => "", "(" => "", "" => "", ")" => "", "" => "", "" => "", "?" => "", "'" => "", "¡" => "", "¿" => "", "" => "", "´" => "", "^" => "", "`" => "", "[" => "", "*" => "", "+" => "", "]" => "", "¨" => "", "´" => "", "{" => "", "}" => "", "," => "", ";" => "", "" => "", "." => "", ":" => "", "" => "", "<" => "", ">" => "", "" => "", "" => "", "»" => "", "«" => "", "œ" => "", "æ" => "", "®" => "", "" => "", "¥" => "", "π" => "", "" => "", "" => "", "" => "", "" => "", "§" => "", "~" => "", "Ω" => "", "" => "", "©" => "", "" => "", "µ" => "", "=" => "", "&" => "", " " => "-", "" => "-", "_" => "-", " " => "-", '€' => 'e', 'º' => '', '°' => '', 'ª' => '', '&' => 'y', '\'' => '');
$enlace = trim(strtolower(str_replace(array_keys($transliterationTable), array_values($transliterationTable), $txt)));
$enlace = preg_replace("/([\-]+)/", "-", $enlace);
if (substr($enlace,strlen($enlace)-1) == "-") $enlace = substr($enlace,0,strlen($enlace)-1);
$enlace = str_replace("-/","/",$enlace);
$enlace = str_replace("/-","/",$enlace);
$enlace = urlencode($enlace);
$enlace = str_replace("%C2","",$enlace);
$enlace = str_replace("%A0","",$enlace);
$enlace = str_replace("%250D","",$enlace);
return urlencode($enlace);
}
}

533
cms/lib/classes/CocoParser.php Executable file
View File

@@ -0,0 +1,533 @@
<?php
if (@$_REQUEST["__amp_source_origin"] && @$_REQUEST["dynamicForm"]){
CocoParser::amp();
}
class CocoParser {
static $captchaValido = false;
static $hayCaptcha = false;
static $parseaCodigosEnLinea = true;
static function parsea_codigos_en_linea($cadena,$options=array()){
if (!self::$parseaCodigosEnLinea) return $cadena;
if (is_array($cadena)) return $cadena;
if (is_null($cadena)) $cadena = '';
$cadena = str_replace("ql-align-", "text-", $cadena);
$cadena = str_replace("<ul>", "<ul class='bullet'>", $cadena);
$cadena = str_replace("<ol>", "<ol class='bullet'>", $cadena);
$cadena = preg_replace("/(target=\"_blank\")/", "$1 rel=\"noopener\"", $cadena);
$cadena = preg_replace_callback("|(\{FORMULARIO\_)([A-Z_]*)(\})|",
function($matches) use ($options){
return "<div data-code-replace='".$matches[0]."'>".self::dame_boton_formulario($matches,$options)."</div>";
},$cadena);
$dummy = array("cadena" => $cadena, "options" => $options);
// addPlugins("codigos_en_linea", $dummy);
// Activando este plugin el tiempo de carga aumenta CONSIDERABLEMENTE ya que se pide en cada content
$cadena = $dummy["cadena"];
return $cadena;
}
static function parsea_campo2($txt,$espacio="_") {
$transliterationTable = array('á' => 'a', 'Á' => 'A', 'à' => 'a', 'À' => 'A', 'ă' => 'a', 'Ă' => 'A', 'â' => 'a', 'Â' => 'A', 'å' => 'a', 'Å' => 'A', 'ã' => 'a', 'Ã' => 'A', 'ą' => 'a', 'Ą' => 'A', 'ā' => 'a', 'Ā' => 'A', 'ä' => 'a', 'Ä' => 'A', 'æ' => 'ae', 'Æ' => 'AE', 'ḃ' => 'b', 'Ḃ' => 'B', 'ć' => 'c', 'Ć' => 'C', 'ĉ' => 'c', 'Ĉ' => 'C', 'č' => 'c', 'Č' => 'C', 'ċ' => 'c', 'Ċ' => 'C', 'ç' => 'c', 'Ç' => 'C', 'ď' => 'd', 'Ď' => 'D', 'ḋ' => 'd', 'Ḋ' => 'D', 'đ' => 'd', 'Đ' => 'D', 'ð' => 'dh', 'Ð' => 'Dh', 'é' => 'e', 'É' => 'E', 'è' => 'e', 'È' => 'E', 'ĕ' => 'e', 'Ĕ' => 'E', 'ê' => 'e', 'Ê' => 'E', 'ě' => 'e', 'Ě' => 'E', 'ë' => 'e', 'Ë' => 'E', 'ė' => 'e', 'Ė' => 'E', 'ę' => 'e', 'Ę' => 'E', 'ē' => 'e', 'Ē' => 'E', 'ḟ' => 'f', 'Ḟ' => 'F', 'ƒ' => 'f', 'Ƒ' => 'F', 'ğ' => 'g', 'Ğ' => 'G', 'ĝ' => 'g', 'Ĝ' => 'G', 'ġ' => 'g', 'Ġ' => 'G', 'ģ' => 'g', 'Ģ' => 'G', 'ĥ' => 'h', 'Ĥ' => 'H', 'ħ' => 'h', 'Ħ' => 'H', 'í' => 'i', 'Í' => 'I', 'ì' => 'i', 'Ì' => 'I', 'î' => 'i', 'Î' => 'I', 'ï' => 'i', 'Ï' => 'I', 'ĩ' => 'i', 'Ĩ' => 'I', 'į' => 'i', 'Į' => 'I', 'ī' => 'i', 'Ī' => 'I', 'ĵ' => 'j', 'Ĵ' => 'J', 'ķ' => 'k', 'Ķ' => 'K', 'ĺ' => 'l', 'Ĺ' => 'L', 'ľ' => 'l', 'Ľ' => 'L', 'ļ' => 'l', 'Ļ' => 'L', 'ł' => 'l', 'Ł' => 'L', 'ṁ' => 'm', 'Ṁ' => 'M', 'ń' => 'n', 'Ń' => 'N', 'ň' => 'n', 'Ň' => 'N', 'ñ' => 'n', 'Ñ' => 'N', 'ņ' => 'n', 'Ņ' => 'N', 'ó' => 'o', 'Ó' => 'O', 'ò' => 'o', 'Ò' => 'O', 'ô' => 'o', 'Ô' => 'O', 'ő' => 'o', 'Ő' => 'O', 'õ' => 'o', 'Õ' => 'O', 'ø' => 'o', 'Ø' => 'O', 'ō' => 'o', 'Ō' => 'O', 'ơ' => 'o', 'Ơ' => 'O', 'ö' => 'o', 'Ö' => 'O', 'ṗ' => 'p', 'Ṗ' => 'P', 'ŕ' => 'r', 'Ŕ' => 'R', 'ř' => 'r', 'Ř' => 'R', 'ŗ' => 'r', 'Ŗ' => 'R', 'ś' => 's', 'Ś' => 'S', 'ŝ' => 's', 'Ŝ' => 'S', 'š' => 's', 'Š' => 'S', 'ṡ' => 's', 'Ṡ' => 'S', 'ş' => 's', 'Ş' => 'S', 'ș' => 's', 'Ș' => 'S', 'ß' => 'SS', 'ť' => 't', 'Ť' => 'T', 'ṫ' => 't', 'Ṫ' => 'T', 'ţ' => 't', 'Ţ' => 'T', 'ț' => 't', 'Ț' => 'T', 'ŧ' => 't', 'Ŧ' => 'T', 'ú' => 'u', 'Ú' => 'U', 'ù' => 'u', 'Ù' => 'U', 'ŭ' => 'u', 'Ŭ' => 'U', 'û' => 'u', 'Û' => 'U', 'ů' => 'u', 'Ů' => 'U', 'ű' => 'u', 'Ű' => 'U', 'ũ' => 'u', 'Ũ' => 'U', 'ų' => 'u', 'Ų' => 'U', 'ū' => 'u', 'Ū' => 'U', 'ư' => 'u', 'Ư' => 'U', 'ü' => 'u', 'Ü' => 'U', 'ẃ' => 'w', 'Ẃ' => 'W', 'ẁ' => 'w', 'Ẁ' => 'W', 'ŵ' => 'w', 'Ŵ' => 'W', 'ẅ' => 'w', 'Ẅ' => 'W', 'ý' => 'y', 'Ý' => 'Y', 'ỳ' => 'y', 'Ỳ' => 'Y', 'ŷ' => 'y', 'Ŷ' => 'Y', 'ÿ' => 'y', 'Ÿ' => 'Y', 'ź' => 'z', 'Ź' => 'Z', 'ž' => 'z', 'Ž' => 'Z', 'ż' => 'z', 'Ż' => 'Z', 'þ' => 'th', 'Þ' => 'Th', 'µ' => 'u', 'а' => 'a', 'А' => 'a', 'б' => 'b', 'Б' => 'b', 'в' => 'v', 'В' => 'v', 'г' => 'g', 'Г' => 'g', 'д' => 'd', 'Д' => 'd', 'е' => 'e', 'Е' => 'E', 'ё' => 'e', 'Ё' => 'E', 'ж' => 'zh', 'Ж' => 'zh', 'з' => 'z', 'З' => 'z', 'и' => 'i', 'И' => 'i', 'й' => 'j', 'Й' => 'j', 'к' => 'k', 'К' => 'k', 'л' => 'l', 'Л' => 'l', 'м' => 'm', 'М' => 'm', 'н' => 'n', 'Н' => 'n', 'о' => 'o', 'О' => 'o', 'п' => 'p', 'П' => 'p', 'р' => 'r', 'Р' => 'r', 'с' => 's', 'С' => 's', 'т' => 't', 'Т' => 't', 'у' => 'u', 'У' => 'u', 'ф' => 'f', 'Ф' => 'f', 'х' => 'h', 'Х' => 'h', 'ц' => 'c', 'Ц' => 'c', 'ч' => 'ch', 'Ч' => 'ch', 'ш' => 'sh', 'Ш' => 'sh', 'щ' => 'sch', 'Щ' => 'sch', 'ъ' => '', 'Ъ' => '', 'ы' => 'y', 'Ы' => 'y', 'ь' => '', 'Ь' => '', 'э' => 'e', 'Э' => 'e', 'ю' => 'ju', 'Ю' => 'ju', 'я' => 'ja', 'Я' => 'ja', "!" => "", "|" => "", "'" => "", "\"" => "", "'" => "", "@" => "", "·" => "", "#" => "", "$" => "", "¢" => "", "%" => "", "" => "", "¬" => "", "/" => "", "÷" => "", "(" => "", "" => "", ")" => "", "" => "", "" => "", "?" => "", "'" => "", "¡" => "", "¿" => "", "" => "", "´" => "", "^" => "", "`" => "", "[" => "", "*" => "", "+" => "", "]" => "", "¨" => "", "´" => "", "{" => "", "}" => "", "," => "", ";" => "", "" => "", "." => "", ":" => "", "" => "", "<" => "", ">" => "", "" => "", "" => "", "»" => "", "«" => "", "œ" => "", "æ" => "", "®" => "", "" => "", "¥" => "", "π" => "", "" => "", "" => "", "" => "", "" => "", "§" => "", "~" => "", "Ω" => "", "" => "", "©" => "", "" => "", "µ" => "", "=" => "", "&" => "", " " => "-", "" => "-", "_" => "-", " " => "-", '€' => 'e', 'º' => '', 'ª' => '', '&' => 'y');
$newString = strtolower(str_replace(array_keys($transliterationTable), array_values($transliterationTable), $txt));
$newString = preg_replace("/([\-]+)/", $espacio, $newString);
return urlencode($newString);
}
static function envia_curl($datos){
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, protocol()."://".$_SERVER["HTTP_HOST"].$_SERVER["REQUEST_URI"]);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS,$datos);
curl_setopt($ch, CURLOPT_TIMEOUT,30);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION,true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
if (protocol() == "https"){
curl_setopt($ch,CURLOPT_RESOLVE, [
$_SERVER["HTTP_HOST"].":443:".$_SERVER["SERVER_ADDR"]
]);
}else{
curl_setopt($ch,CURLOPT_RESOLVE, [
$_SERVER["HTTP_HOST"].":80:".$_SERVER["SERVER_ADDR"]
]);
}
$respond = curl_exec ($ch);
curl_close ($ch);
return $respond;
}
static function dame_boton_formulario($matches,$options=array()){
global $configuracionRecord;
$identificador = @$matches[2];
if (!$identificador) return $matches[0];
$result2 = mysql_query("SELECT * FROM cms__formularios where identificador='".$identificador."' limit 1");
$result = "";
if (mysql_num_rows($result2)>0){
$rec = mysql_fetch_assoc($result2);
if (@$options["clases"]) $rec["clase"] = $options["clases"];
$form = $rec;
$form["tableName"] = "cms__formularios";
$form["tipo"] = (@$options["tipo"]) ? $options["tipo"] : $form["tipo"];
$resultPlugin = addPlugins("pre_codigos_en_linea",$form);
echo @$resultPlugin["html"];
$datos = array(
"id" => "form_".$form["identificador"],
"title" => t($form,"title"),
"numForm" => $form["num"],
"formulario" => json_decode($form["campos"],true),
"tipo" => $form["tipo"],
"clase" => $form["clase"],
"widget" => (@$options["widget"]) ? true : false
);
foreach ($options as $index => $option):
$datos[$index] = $option;
endforeach;
if (!@$options["yaPuesto"]) {
if (!@$options["amp"]){
$respond = self::envia_curl("modulo=modal&clave=wscO4QaF&datos=".base64_encode(json_encode($datos)));
}else{
require_once realpath(dirname(__FILE__)."/../../plugins/amp/amp_static functions.php");
$respond = modulo_amp("modal",$datos);
}
}
// ENVIO DE DATOS POR CORREO
if (@$_REQUEST["dynamicForm"]){
if ($form["num"]==@$_REQUEST["numForm"]){
unset($_REQUEST["numForm"]);
// Comprobamos el captcha
self::$captchaValido = true;
if (!@$options["amp"]) {
if ((!isset($options["captcha"]) || @$options["captcha"] == true)) {
if (@hasRecaptcha()) {
$captcha = json_decode(file_get_contents("https://www.google.com/recaptcha/api/siteverify?secret=".$configuracionRecord["secret_key_recaptcha"]."&response=".@$_REQUEST["g-recaptcha-response"]), true);
if (!@$captcha["success"]) self::$captchaValido = false;
}
else {
if (md5(@$_POST["captcha"]) != @$_SESSION["key_captcha"]) self::$captchaValido = false;
}
}
}
if (self::$captchaValido) {
$datosCadena="<ul>";
$correosCliente = array();
$campos = json_decode($form["campos"],true);
$tableName = self::parsea_campo2($form["tablaDestino"]);
$schema = loadSchema($tableName);
foreach(@$_REQUEST["dynamicForm"] as $key => $value):
foreach($campos as $cont => $campo):
if ($campo["tipo"]=="email" && $key == self::parsea_campo2($campo["nombre"],"-") && !in_array($value,$correosCliente)) {
$correosCliente[] = $value;
}
if ($key==self::parsea_campo2($campo["nombre"],"-")) {
$schemaKey = self::parsea_campo2($campo["nombre"]);
$campos[$cont]["datosCliente"] = $value;
}
endforeach;
if (isset($schema[$schemaKey])) {
switch (@$schema[$schemaKey]['type']) {
case 'list':
$options = getListOptions($tableName, $schemaKey);
if (isset($options[$value])) $value = $options[$value];
$datosCadena.="<li><b>".$schema[$schemaKey]['label']."</b>: ".$value."</li>";
break;
case 'checkbox':
$datosCadena.="<li><b>".$schema[$schemaKey]['label']."</b>: ".(@$value ? 'Sí' : 'No')."</li>";
break;
default:
$datosCadena.="<li><b>".$schema[$schemaKey]['label']."</b>: ".$value."</li>";
}
} else {
$datosCadena.="<li><b>".$key."</b>: ".$value."</li>";
}
endforeach;
$datosCadena.="<li><b>URL de solicitud</b>: <a href='https://".$_SERVER["HTTP_HOST"].$_SERVER["REQUEST_URI"]."'>https://".$_SERVER["HTTP_HOST"].$_SERVER["REQUEST_URI"]."</a></li>";
$datosCadena.="</ul>";
$contenido = str_replace("{DATOS}",$datosCadena,$form["contenidoEmail"]);
if (!$form["enviarACliente"]) $correosCliente=array();
if ($form["enviarAEmpresa"]) {
$result = mysql_query("select correo_admin from cms_configuracion limit 1");
$correo = mysql_fetch_assoc($result);
if (strpos($correo["correo_admin"],",")){
$sepp = explode(",",$correo["correo_admin"]);
foreach($sepp as $seppp):
if (@$seppp){
if (!in_array($seppp,$correosCliente)) $correosCliente[]=$seppp;
}
endforeach;
}else{
if (!in_array($correo["correo_admin"],$correosCliente)) $correosCliente[]=$correo["correo_admin"];
}
}
if (@$options['correos'] && is_array($options['correos'])) {
foreach($options['correos'] as $c):
if (filter_var($c, FILTER_VALIDATE_EMAIL)) $correosCliente[] = $c;
endforeach;
}
if (count($correosCliente)>0){
$datos = array(
"destinatarios" => $correosCliente,
"numForm" => $form["num"],
"identificador" => $form["identificador"],
"asunto" => $form["title"],
"contenido" => base64_encode($contenido)
);
$respond2 = self::envia_curl("enviar_correo=1&clave=wscO4QaF&datos=".base64_encode(json_encode($datos)));
$respond = @$respond2.@$respond;
}
// AHORA LO INSERTAMOS EN LA BASE DE DATOS
if (@$form["tablaDestino"]){
$sql = "
INSERT INTO cms_".self::parsea_campo2($form["tablaDestino"])." SET
num=NULL,
createdDate='".date("Y-m-d H:i:s")."',
updatedDate='".date("Y-m-d H:i:s")."',
dragSortOrder='".time()."',
url='https://".$_SERVER["HTTP_HOST"].$_SERVER["REQUEST_URI"]."',
numFormulario='".$form["num"]."'
";
$sql_busqueda = "SELECT num FROM cms_".self::parsea_campo2($form["tablaDestino"])." WHERE numFormulario='".$form["num"]."'";
$sql_busqueda.=" AND url='https://".$_SERVER["HTTP_HOST"].$_SERVER["REQUEST_URI"]."'";
foreach($campos as $campo):
if (@$campo["datosCliente"]){
$sql.=",".self::parsea_campo2($campo["nombre"])."='".$campo["datosCliente"]."'";
$sql_busqueda.=" AND ".self::parsea_campo2($campo["nombre"])."='".$campo["datosCliente"]."'";
}
endforeach;
$result3 = @mysql_fetch_assoc(mysql_query("SHOW TABLES LIKE 'cms_".self::parsea_campo2($form["tablaDestino"])."'"));
if ($result3){
$resultadoBusqueda = mysql_fetch_assoc(mysql_query($sql_busqueda));
if (!@$resultadoBusqueda){
mysql_query($sql) or die(mysql_error());
}
}
}
$resultPlugin = addPlugins("post_codigos_en_linea",$form);
if (!@$options["amp"] && !@$options['sin_gracias']) {
$apartadoGracias = CocoDB::get("otros_contenidos", "controlador='gracias.php'", null, 1, ["ignoreSchema" => true]);
$apartadoGracias = @$apartadoGracias[0];
if (@$apartadoGracias) {
echo '<script>window.location.href = "'.t($apartadoGracias, "enlace").'"</script>';
}
}
echo @$form["html_post"];
}else{
echo "<script>alert('".t_var("El captcha introducido no es válido")."')</script>";
}
}
}
switch ($form["tipo"]){
case "fields":
$result=@$respond;
break;
case "inline":
$result=@$respond;
break;
default:
$result =@$respond;
if (@$options["textoBoton"]){
$result.= "<a href='javascript:void(0)' class='".$rec["clase"]."' data-toggle='modal' data-target='#form_".$rec["identificador"]."'>".$options["textoBoton"]."</a>";
}else{
$result.= "<a href='javascript:void(0)' class='".$rec["clase"]."' data-toggle='modal' data-target='#form_".$rec["identificador"]."'>".$rec["textoBoton"]."</a>";
}
}
}
return $result;
}
static function amp(){
require_once realpath(dirname(__FILE__)."/../../../../funciones.php");
$result2 = @mysql_fetch_assoc(mysql_query("SELECT * FROM cms__formularios where num='".intval(@$_REQUEST["numForm"])."' limit 1"));
$domain_url = protocol()."://".$_SERVER["HTTP_HOST"];
header("Content-type: application/json");
header("Access-Control-Allow-Credentials: true");
header("Access-Control-Allow-Origin:" . str_replace('.', '-', $domain_url) .".cdn.ampproject.org");
header("AMP-Access-Control-Allow-Source-Origin: " . $domain_url);
$apartadoGracias = CocoDB::get("otros_contenidos", "controlador='gracias.php'", null, 1, ["ignoreSchema" => true]);
$apartadoGracias = @$apartadoGracias[0];
if (@$apartadoGracias) {
header("AMP-Redirect-To: " . protocol()."://".$_SERVER["HTTP_HOST"].t($apartadoGracias, "enlace"));
header("Access-Control-Expose-Headers: AMP-Redirect-To, AMP-Access-Control-Allow-Source-Origin");
}
else {
header("Access-Control-Expose-Headers: AMP-Access-Control-Allow-Source-Origin");
}
if (@$result2){
$result = self::dame_boton_formulario(array(null,null,$result2["identificador"]),array("amp" => true,"yaPuesto" => true));
die(json_encode(array('successmsg'=>'ok',"result" => @$result)));
}else{
die(json_encode(array('successmsg'=>'Error')));
}
}
static function cocoForm($data = []){
global $configuracionRecord;
$defaults = [
"sendTo" => @$configuracionRecord["correo_admin"],
"messageOK" => t_var("Mensaje enviado"),
"messageKO" => t_var("Los campos son requeridos"),
"attachFiles" => false
];
foreach($data as $key => $value){
if (!is_string($value) || $value != "null") $defaults[$key] = $value;
}
$data = $defaults;
if (@$data["captcha"]) self::$hayCaptcha = true;
if (@$_REQUEST["cocoForm"] && @$_REQUEST["cocoForm"]["form"] == $data["id"]){
try{
$cocoForm = @$_REQUEST["cocoForm"];
if ($cocoForm["form"] !== $data["id"]) return;
if (@$data["captcha"] && !self::cocoFormValidateCaptcha($cocoForm)) throw new Exception(t_var('El Captcha no es válido')); // CAPTCHA
// Anael: Variable estandar que usamos de Honeypot, en caso de que exista es que la ha rellenado un bot.
if (@$cocoForm["full_user_name"]) throw new Exception(t_var('El Captcha no es válido'));
$errors = []; // COMPROBAMOS LOS REQUIRED
foreach($data["variables"] as $key => $value){
if (strpos($key,"[]") !== false) $key = str_replace("[]","",$key);
if ($value["type"]=="file" && @$_FILES["cocoForm"] && array_filter($_FILES["cocoForm"]["name"][$key]) ) {
$uploadFiles = self::upload("cocoForm",$key);
foreach($uploadFiles as $uploadFile){
if ($uploadFile['success'] === false) throw new Exception(t_var('Error en la subida de archivo'));
if (@$cocoForm[$key]) $cocoForm[$key][]=$uploadFile["urlPath"]; else $cocoForm[$key] = [$uploadFile["urlPath"]];
if(!$data["attachFiles"]){
$link = "<a href='https://".$_SERVER["HTTP_HOST"].$uploadFile["urlPath"]."'>".t_var("Descargar")." ".basename($uploadFile["urlPath"])."</a><br>";
// En banana educación hay que arreglarlo poniendo en el correo el _text
if (@$cocoForm[$key."_text"]) $cocoForm[$key."_text"].=$link; else $cocoForm[$key."_text"] = $link;
} else {
CocoEmail::$attach_files[] = $uploadFile["filePath"];
}
}
continue;
}
if (isset($value["required"]) && empty($cocoForm[$key]) && @$cocoForm[$key] !== '0' && @$cocoForm[$key] !== 0) $errors[$key] = $value;
}
if (!empty($errors)) throw new Exception(t_var('Los campos').' '.join(", ",array_map(function($rec){ return t_var($rec); },array_keys($errors))).' '.t_var('son oblitagorios'));
if (isset($data["action"])) return hook($data["action"],$cocoForm); // ACTION A HOOK
if (isset($data["tableName"])) $resultInsert = self::cocoFormInsertRecords($data,$cocoForm); // INSERCION
if (isset($data["mailRecord"]) && count($data["mailRecord"]) == 2) {
if (isset($data["tableName"]) && @$resultInsert){
//$insertedRecord = mysql_insert_id();
$recordInserted = @CocoDB::get($data["tableName"],"num=".intval($resultInsert),null,1,["relationsDepth" => 2])[0];
}
if (@$recordInserted){
self::cocoFormEmail($data, array_merge($cocoForm, $recordInserted)); // EMAIL
}else{
self::cocoFormEmail($data,$cocoForm); // EMAIL
}
}
if (isset($data["redirectTo"])) { // REDIRECT
echo "<script>document.location.href='".$data["redirectTo"]."'</script>";
}
echo strip_tags($data["messageOK"]) == $data["messageOK"] ? "<script>alert('".addslashes($data["messageOK"])."');</script>" : $data["messageOK"];
}catch(Exception $e){
echo strip_tags($data["messageKO"]) == $data["messageKO"] ? "<script>alert('".$e->getMessage()."');</script>" : "<div class='p-12 bg-red-600 rounded-lg'>".$e->getMessage()."</div>";
}
}
}
static function cocoFormValidateCaptcha($cocoForm = []){
global $configuracionRecord;
if (@hasRecaptcha()) {
$captcha = json_decode(file_get_contents("https://www.google.com/recaptcha/api/siteverify?secret=".$configuracionRecord["secret_key_recaptcha"]."&response=".@$_REQUEST["g-recaptcha-response"]), true);
if (!@$captcha["success"]) return false;
}
else {
if (md5(@$_POST["captcha"]) != @$_SESSION["key_captcha"]) return false;
}
return true;
}
static function cocoFormInsertRecords($data = [],$cocoForm = []){
if (!@loadSchema($data["tableName"])) throw new Exception(t_var('La tabla de destino no existe'));
$cocoForm["url"] = $_SERVER["REQUEST_URI"];
return CocoDB::insertRecords($data["tableName"],$cocoForm,[],['return_last_id' => true]);
}
static function cocoFormEmail($data = [],$cocoForm = []){
if (@$data["header"]) CocoEmail::$header = @$data["header"];
if (@$data["footer"]) CocoEmail::$footer = @$data["footer"];
if (@$data["styles"]) CocoEmail::$styles = @$data["styles"];
$recipients = [];
if (isset($data["sendToClient"]) && isset($cocoForm[$data["sendToClient"]])) $recipients[] = $cocoForm[$data["sendToClient"]];
if (isset($data["sendTo"])){
foreach(array_filter(explode(",",$data["sendTo"])) as $email){
$recipients[] = trim($email);
}
}
if (empty($recipients)) throw new Exception(t_var('No se encuentran destinatarios para el envío del correo'));
if (!empty($recipients) && $data["mailRecord"][1]){
if (!@loadSchema($data["mailRecord"][0])) throw new Exception(t_var('La tabla de correos no existe'));
$auxTableCocoEmail = CocoEmail::$table;
if (@loadSchema($data["mailRecord"][0])){
CocoEmail::$table = $data["mailRecord"][0];
}
$options = [];
if (trim(strtolower(@$data["emailMode"]?:'')) == "twig") $options["twig"] = true;
if (@$data["emailB64"]) $options["base64Decode"] = true;
//CocoEmail::$debug = true;
CocoEmail::send($data["mailRecord"][1],$cocoForm,$recipients,null,null,false,$options ?: []);
CocoEmail::$table = $auxTableCocoEmail;
}
return null;
}
static function slugify($text) {
// replace non letter or digits by -
$text = preg_replace('~[^\pL\d]+~u', '-', $text);
// transliterate
$text = iconv('utf-8', 'us-ascii//TRANSLIT', $text);
// remove unwanted characters
$text = preg_replace('~[^-\w]+~', '', $text);
// trim
$text = trim($text, '-');
// remove duplicate -
$text = preg_replace('~-+~', '-', $text);
// lowercase
$text = strtolower($text);
if (empty($text)) {
return substr(str_shuffle(MD5(microtime())), 0, 10);
}
return $text;
}
static function check_if_file_exist_and_get_new_name(&$file_info, $path, $count = 0) {
if(!$count) {
if(file_exists($path . $file_info['filename'] . '.' . $file_info['extension'])) {
return self::check_if_file_exist_and_get_new_name($file_info, $path, $count + 1);
}
} else {
if(file_exists($path . $file_info['filename'] . '-' . $count . '.' . $file_info['extension'])) {
return self::check_if_file_exist_and_get_new_name($file_info, $path, $count + 1);
}
}
if($count) $file_info['filename'] .= '-' . $count;
}
static function upload($prefix = null,$file = 'file') {
$arrayFiles = $prefix ? $_FILES[$prefix] : $_FILES;
if(!isset($arrayFiles["error"][$file])) return [];
$allowed = [
'application/pdf' => 'pdf',
'audio/x-aac' => 'aac',
'application/vnd.amazon.ebook' => 'azw',
'audio/x-aiff' => 'aiff',
'audio/mp3' => 'mp3',
'audio/mpeg' => 'mp3',
'image/bmp' => 'bmp',
'text/css' => 'css',
'text/csv' => 'csv',
'text/plain' => 'csv',
'application/epub+zip' => 'epub',
'image/gif' => 'gif',
'image/x-icon' => 'ico',
'image/jpeg' => ['jpg', 'jpeg'],
'image/png' => 'png',
'image/heic' => 'heic',
'image/svg+xml' => 'svg',
'image/tiff' => 'tiff',
'image/webp' => 'webp',
'video/x-m4v' => 'm4v',
'video/x-ms-wmv' => 'wmv',
'video/mpeg' => 'mpeg',
'video/mp4' => 'mp4',
'video/webm' => 'webm',
'video/ogg' => 'ogg',
'application/vnd.oasis.opendocument.text' => 'odt',
'application/vnd.oasis.opendocument.graphics' => 'odg',
'application/vnd.oasis.opendocument.spreadsheet' => 'ods',
'application/vnd.oasis.opendocument.presentation' => 'odp',
'application/vnd.openxmlformats-officedocument.wordprocessingml.document' => 'docx',
'application/msword' => 'doc',
'application/vnd.ms-excel' => 'xls',
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' => 'xlsx',
'application/vnd.ms-powerpoint' => 'ppt',
'application/vnd.openxmlformats-officedocument.presentationml.presentation' => 'pptx'
];
$countfiles = count($arrayFiles['name'][$file]);
$files_to_upload = [];
// $uploads_dir = __DIR__ . '/../../../../../uploads/';
$uploads_dir = __DIR__ . '/../../uploads/';
// Loop de archivos.
for($i=0;$i<$countfiles;$i++){
$files_to_upload[$i] = ['urlPath' => '', 'filePath' => '', 'success' => false];
// Si hay un error saltamos el archivo.
if($arrayFiles['error'][$file][$i] !== 0 || !$arrayFiles['name'][$file][$i]) continue;
// Obtenemos la info del archivo.
$file_name = $arrayFiles['name'][$file][$i];
$tmp_file = $arrayFiles['tmp_name'][$file][$i];
$file_info = pathinfo($file_name);
// Obtenemos el mime_type
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mime_type = finfo_file($finfo, $tmp_file);
finfo_close($finfo);
// Si este archivo no está permitod continuamos.
if (!isset($allowed[$mime_type])) continue;
// Comprobamos si existe ya el archivo con este nombre para cambiarlo en tal caso.
$file_info['filename'] = self::slugify($file_info['filename']);
self::check_if_file_exist_and_get_new_name($file_info, $uploads_dir);
// Movemos el archivo porque ha sido validado
$new_name = $file_info['filename'] . '.' . $file_info['extension'];
move_uploaded_file($tmp_file, $uploads_dir.$new_name);
$filePath = realpath($uploads_dir.$new_name);
$urlPath = '/cms/uploads/'.$new_name;
$files_to_upload[$i] = ['urlPath' => $urlPath, 'filePath' => $filePath, 'success' => true];
}
return $files_to_upload;
}
}

282
cms/lib/classes/CocoWS.php Executable file
View File

@@ -0,0 +1,282 @@
<?php
class CocoWS {
private static $_instances = array();
static $endpoint = "";
static $token = "";
static $cacheSchemaTables = [];
static $cacheSchemas = [];
public static function getInstance() {
$class = get_called_class();
if (!isset(self::$_instances[$class])) {
self::$_instances[$class] = new $class();
}
return self::$_instances[$class];
}
private function __construct() {}
static function request($api_method, $data = null, $method = 'GET') {
$url = rtrim(self::$endpoint, "/")."/".trim($api_method, "/")."/";
$header = array();
$header[] = 'Content-type: application/json';
$header[] = 'Authorization: Bearer '.self::$token;
$result = self::curl($url,$header,$method,$data);
return $result;
}
static function validateUploadToken($token) {
$response = self::request('upload_token', ['action' => 'validate', 'token' => $token], 'POST');
return isset($response['success']) && $response['success'];
}
/**
* Actualiza la configuracion de la pagina
* @destacar
* @category WS
* @param settings: Actualiza los settings
* @return boolean que indica el exito
*/
static function updateSettings($settings) {
return true;
}
/**
* Actualiza un Schema
* @destacar
* @category WS
* @param tableName: Identificador del schema
* @param path: ruta del archivo
* @return boolean que indica el exito
*/
static function insertOrUpdateSchema($tableName,$path,$schemaNew = null) {
if (!$schemaNew) { $schemaNew = CocoWS::loadSchema($tableName);}
saveINI($path."/".$tableName.".ini.php",$schemaNew);
return true;
}
/**
* Inserta un modulo dado en la carpeta de modulos
* @destacar
* @category WS
* @param id: Identificador del módulo
* @param zipFile: archivo Zip
* @return boolean que indica el exito
*/
static function insertOrUpdateModule($id, $zipFile) {
return true;
}
/**
* Inserta un plugin dado en la carpeta de plugins
* @destacar
* @category WS
* @param id: Identificador del plugin
* @param zipFile: archivo Zip
* @return boolean que indica el exito
*/
static function insertOrUpdatePlugin($id, $zipFile) {
return true;
}
/**
* Ejecuta un curl contra el servidor
* @destacar
* @category WS
* @param url: url del servidor
* @param header: cabeceras
* @param method: metodo utilizado
* @param data: datos que se transfieren en la consulta
* @return boolean que indica el exito
*/
static function curl($url,$header,$method = "GET",$data = null){
$ch = curl_init();
switch (strtoupper($method)) {
case 'POST':
curl_setopt($ch, CURLOPT_POST, 1);
case 'PUT':
case "DELETE":
if ($data) {
if (is_array($data)) {
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
}
else {
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
}
}
break;
default:
$url .= "?".http_build_query($data);
break;
}
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
curl_setopt($ch, CURLOPT_TIMEOUT, 3);
curl_setopt($ch, CURLOPT_REFERER, $_SERVER["HTTP_HOST"]);
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
curl_setopt($ch, CURLOPT_VERBOSE, true);
$verbose = fopen('php://temp', 'w+');
curl_setopt($ch, CURLOPT_STDERR, $verbose);
//curl_setopt($ch, CURLOPT_SAFE_UPLOAD, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_URL, $url);
$response = curl_exec($ch);
$info = curl_getinfo($ch);
if (!$response) {
rewind($verbose);
$verboseLog = stream_get_contents($verbose);
$error = "Verbose information:\n<pre>".htmlspecialchars($verboseLog)."</pre>\n";
$error.= sprintf("cUrl error (#%d): %s<br>\n", curl_errno($ch),
htmlspecialchars(curl_error($ch)));
curl_close($ch);
return self::parseError(["error" => $error,"code" => 418]);
}
$json = json_decode($response,true);
if (json_last_error() !== JSON_ERROR_NONE){
curl_close($ch);
return self::parseError(["error" => "Data response error, not a object","message" => $response]);
}
if (isset($json["error"])){
curl_close($ch);
return self::parseError($json);
}
curl_close($ch);
return $json;
}
/**
* Parsea el error de respuesta
* @destacar
* @category WS
* @param data: Datos del error
* @return devuelve los datos
*/
public static function parseError($data){
switch (@$data["code"]){
case 403:
break;
case 600:
break;
default:
throw new Exception(json_encode($data));
}
return $data;
}
/**
* Hacer Login en el servidor
* @destacar
* @category WS
* @param user: usuario
* @param pass: password
* @param domain: dominio
* @param token: token
* @param method: método utilizado
* @return devuelve el token y el usuario
*/
static function login($user=null,$pass=null,$domain=null,$token=null,$method = "POST"){
$userPass = $user && $pass ? base64_encode($user.':'.$pass.':'.$domain) : $token;
$authorization = $token ? "Bearer" : "Login";
$header = array();
$header[] = 'Content-length: 0';
$header[] = 'Content-type: application/json';
$header[] = 'Authorization: '.$authorization.' '.$userPass;
$url = rtrim(self::$endpoint,"/")."/auth/";
$result = self::curl($url,$header,$method);
if (@$result["error"]) return self::parseError($result);
return [$result["data"]["token"],$result["data"]["user"]];
}
static function setEndpoint($endpoint) {
self::$endpoint = $endpoint;
}
static function setToken($token) {
self::$token = $token;
}
static function getToken() {
return self::$token;
}
static function getSchemaTables($dir = '',$type = '') {
$respuesta = self::request("schemas",["action" => "getSchemaTables","dir" => $dir,"type" => $type]);
if (isset($respuesta["error"])){
return self::parseError($respuesta);
}else{
self::$cacheSchemaTables = $respuesta["data"];
return $respuesta["data"];
}
}
static function loadSchema($tableName, $schemaDir = '') {
if (isset(self::$cacheSchemas[$tableName])) return self::$cacheSchemas[$tableName];
if (!$tableName) { die(__FUNCTION__ . ": no tableName specified!"); }
$tableNameWithoutPrefix = getTableNameWithoutPrefix($tableName);
$respuesta = self::request("schemas",["id" => $tableNameWithoutPrefix,"dir" => $schemaDir]);
if (isset($respuesta["error"])){
return self::parseError($respuesta);
}else{
self::$cacheSchemas[$tableName] = $respuesta["data"];
return $respuesta["data"];
}
}
static function getAuthorizationHeader(){
$headers = null;
if (isset($_SERVER['Authorization'])) {
$headers = trim($_SERVER["Authorization"]);
}
else if (isset($_SERVER['HTTP_AUTHORIZATION'])) { //Nginx or fast CGI
$headers = trim($_SERVER["HTTP_AUTHORIZATION"]);
} elseif (function_exists('apache_request_headers')) {
$requestHeaders = apache_request_headers();
// Server-side fix for bug in old Android versions (a nice side-effect of this fix means we don't care about capitalization for Authorization)
$requestHeaders = array_combine(array_map('ucwords', array_keys($requestHeaders)), array_values($requestHeaders));
//print_r($requestHeaders);
if (isset($requestHeaders['Authorization'])) {
$headers = trim($requestHeaders['Authorization']);
}
}
return $headers;
}
static function getBearerToken() {
$headers = self::getAuthorizationHeader();
if (!empty($headers)) {
if (preg_match('/Bearer\s(\S+)/', $headers, $matches)) {
return $matches[1];
}
}
return null;
}
static function getLoginAccess() {
$headers = self::getAuthorizationHeader();
if (!empty($headers)) {
if (preg_match('/Login\s(\S+)/', $headers, $matches)) {
return explode(":",base64_decode($matches[1]));
}
}
return null;
}
}

131
cms/lib/classes/Db.php Executable file
View File

@@ -0,0 +1,131 @@
<?php
class Db {
private $host; // Db Host
private $user; // Db User
private $password; // Db Password
private $db; // Db Name
private $link; // MySQLi Link
private static $instance = false; // Db Class Instance
/**
* @param host: DB Host
* @param user: DB user
* @param password: DB Password
* @param db: DB Name
*/
public function __construct($host, $user, $password, $db) {
$this->host = $host;
$this->user = $user;
$this->password = $password;
$this->db = $db;
$this->link = $this->connect();
}
/**
* @param host: DB Host
* @param user: DB user
* @param password: DB Password
* @param db: DB Name
*/
public static function getInstance($host='', $user='', $password='', $db='') {
if (self::$instance) {
return self::$instance;
}
self::$instance = new Db($host, $user, $password, $db);
return self::$instance;
}
public function escape($str) {
return $this->link->quote($str);
}
/**
* Connects to the database. Returns HTTP Error Code 500 in case of error
*/
private function connect() {
$dsn = "mysql:host=".$this->host.";dbname=".$this->db.";charset=utf8mb4";
$options = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false,
PDO::MYSQL_ATTR_INIT_COMMAND => 'SET sql_mode="TRADITIONAL"'
];
try {
$link = new PDO($dsn, $this->user, $this->password, $options);
return $link;
} catch (\PDOException $e) {
throw new \PDOException($e->getMessage(), (int)$e->getCode());
}
return false;
}
/**
* Executes a SQL Query
*
* @param sql: SQL Query
* @param params: List of variables to be binded
*
* @return bool
*/
public function execute($sql, $params = null) {
if ($params) {
$stmt = $this->link->prepare($sql);
try {
$stmt->execute($params);
}
catch(Exception $e) {
return false;
}
}
else {
$stmt = $this->link->query($sql);
}
return $stmt->rowCount();
}
/**
* Executes a SQL Select Query
*
* @param sql: SQL Select Query
* @param params: List of variables to be binded
* @param indexed: If set to true, returns the indexed array instead of associative
*
* @return array
*/
public function executeS($sql, $params = null, $indexed = false) {
if ($params) {
$stmt = $this->link->prepare($sql);
$stmt->execute($params);
}
else {
$stmt = $this->link->query($sql);
}
if ($indexed) {
$result = $stmt->fetchAll(PDO::FETCH_ARRAY);
}
else {
$result = $stmt->fetchAll();
}
return $result;
}
/**
* Executes a SQL Select Query of one element
*
* @param sql: SQL Select Query
* @param params: List of variables to be binded
* @param indexed: If set to true, returns the indexed array instead of associative
*
* @return array
*/
public function fetch($sql, $params = null, $indexed = false) {
$result = $this->executeS($sql, $params, $indexed);
return empty($result) ? null : $result[0];
}
public function foundRows() {
$foundRows = $this->link->query('SELECT FOUND_ROWS()')->fetchColumn();
return $foundRows;
}
}

226
cms/lib/common.php Executable file
View File

@@ -0,0 +1,226 @@
<?php
global $cachedSchemas;
$cachedSchemas = [];
function protocol() {
return isHTTPS() ? "https" : "http";
}
function isHTTPS() {
return
(!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off')
|| $_SERVER['SERVER_PORT'] == 443;
}
function loadPlugins() {
// load plugins
if (file_exists($GLOBALS["APP"]["pluginsdir"]."/index.php")){
require_once $GLOBALS["APP"]["pluginsdir"]."/index.php";
}
}
function loadINI($filepath) {
global $cachedSchemas;
if(isset($cachedSchemas[$filepath])) return $cachedSchemas[$filepath];
// error checking
if (!file_exists($filepath)) { die("Error: Couldn't find ini file '$filepath'"); }
// load ini file
$iniValues = @parse_ini_file($filepath, true);
if (@$php_errormsg) { die(__FUNCTION__ . ": $php_errormsg"); }
$iniValues = _decodeIniValues($iniValues);
$cachedSchemas[$filepath] = $iniValues;
return $iniValues;
}
function saveINI($filepath, $array, $sortKeys = 0) {
$globals = '';
$sections = '';
$invalidKeyRegexp = '/[^a-zA-Z0-9\-\_\.]/i'; # dis-allowed chars[{}|&~![()"] (from https://ca.php.net/parse_ini_file)
$filename = pathinfo($filepath, PATHINFO_BASENAME);
// encode values
$array = _encodeIniValues($array);
### get ini data
if ($sortKeys) { ksort($array); }
foreach ($array as $key => $value) {
# save sub-sections
if (is_array($value)) {
$sections .= "\n[{$key}]\n";
$childArray = $value;
foreach ($childArray as $childKey => $childValue) {
if (preg_match($invalidKeyRegexp, $childKey)) { die("Error: Invalid character(s) in key '".htmlspecialchars($childKey)."', only the following chars are allowed in key names: a-z, A-Z, 0-9, -, _, . Filename: $filename"); }
$needsQuotes = !is_numeric($childValue) && !is_bool($childValue);
if ($needsQuotes) { $sections .= "$childKey = \"$childValue\"\n"; }
else { $sections .= "$childKey = $childValue\n"; }
}
}
# save global keys
else {
if (preg_match($invalidKeyRegexp, $key)) { die("Error: Invalid character(s) in key '".htmlspecialchars($key)."', the following chars aren't allowed in key names: a-z, A-Z, 0-9, -, _, . Filename: $filename"); }
$needsQuotes = !is_numeric($value) && !is_bool($value);
if ($needsQuotes) { $globals .= "$key = \"$value\"\n"; }
else { $globals .= "$key = $value\n"; }
}
}
# create ini content
$content = ";<?php die('This is not a program file.'); exit; ?>\n\n"; # prevent file from being executed
$content .= $globals;
$content .= $sections;
# error checking
# save ini file
if (file_exists($filepath) && !is_writable($filepath)) { die("Error writing to '$filepath'!<br/>\nFile isn't writable, check permissions!"); }
file_put_contents($filepath, $content) || die("Error writing to '$filepath'!");
}
function _encodeIniValues($array) {
static $matches = array("\\", "\n", "\r", '"');
static $replacements = array('\\\\', '\\n', '', '\\q');
foreach (array_keys($array) as $key) {
$value = &$array[$key];
if (!@$value) continue;
if (is_array($value)) { $value = _encodeIniValues($value); }
else { $value = str_replace($matches, $replacements, $value); }
}
return $array;
}
function _decodeIniValues($array) {
static $replacements = array('\\\\' => "\\", '\\n' => "\n", '\\q' => '"');
static $replaceCode = "array_key_exists('\\1', \$replacements) ? \$replacements['\\1'] : '\\1';";
$serializedData = serialize($array);
if (!preg_match("/\\\\\\\\|\\\\n|\\\\q/", $serializedData)) { return $array; }
foreach (array_keys($array) as $key) {
$value = &$array[$key];
if (is_array($value)) {
$value = _decodeIniValues($value);
}else{
$value = preg_replace_callback('|(\\\\.)|', function($m){
return str_replace("\\q","\"",str_replace("\\n","\n",str_replace("\\\\","\\",$m[1])));
}, $value);
}
}
return $array;
}
function getAdjustedLocalTimeOffsetSeconds() {
global $SETTINGS;
if (function_exists('date_default_timezone_set')) {
return 0;
}
$secondsOffset = 0;
$secondsOffset += @$SETTINGS['timezoneOffsetHours'] * 60*60;
$secondsOffset += @$SETTINGS['timezoneOffsetMinutes'] * 60;
$secondsOffset = @$SETTINGS['timezoneOffsetAddMinus'] . $secondsOffset;
return $secondsOffset;
}
function convertSecondsToTimezoneOffset($seconds) {
$offsetAddMinus = ($seconds < 0) ? '-' : '+';
$offsetHours = (int) abs($seconds / (60*60));
$offsetMinutes = (int) abs(($seconds % (60*60)) / 60);
$offsetString = sprintf("%s%02d:%02d", $offsetAddMinus, $offsetHours, $offsetMinutes);
return $offsetString;
}
function getEvalOutput($string) {
global $TABLE_PREFIX, $ESCAPED_FILTER_VALUE;
//
$containsNoPHPCode = (strpos($string,"php") === false);
if($containsNoPHPCode) { return $string; }
// eval php code
ob_start();
eval('?>' . $string);
$output = ob_get_clean();
return $output;
}
function saveResampledImageAs($targetPath, $sourcePath, $maxWidth, $maxHeight) {
global $SETTINGS;
// create target dir
$dir = dirname($targetPath);
if (!file_exists($dir)) {
try{
mkdir_recursive($dir);
}catch(Exception $e){
throw new Exception("Error creating dir '" .htmlspecialchars($dir). "'. Check permissions or try creating directory manually.");
}
}
// open source image
$sourceImage = null;
list($sourceWidth, $sourceHeight, $imageType) = getimagesize($sourcePath);
// get new height/width
$widthScale = $maxWidth / ($sourceWidth?:1);
$heightScale = $maxHeight / ($sourceHeight?:1);
$scaleFactor = min($widthScale, $heightScale, 1); # don't scale above 1:1
$targetHeight = ceil($sourceHeight * $scaleFactor); # round up
$targetWidth = ceil($sourceWidth * $scaleFactor); # round up
if ($scaleFactor == 1) {
try{ copy($sourcePath, $targetPath); }catch(Exception $e){ throw new Exception(__FUNCTION__ . ": error copying image '$sourcePath' - $php_errormsg"); }
return array($sourceWidth, $sourceHeight);
}
// create new image
switch($imageType) {
case IMAGETYPE_JPEG: $sourceImage = imagecreatefromjpeg($sourcePath); break;
case IMAGETYPE_GIF: $sourceImage = imagecreatefromgif($sourcePath); break;
case IMAGETYPE_PNG: $sourceImage = imagecreatefrompng($sourcePath); break;
default: throw new Exception(__FUNCTION__ . ": Unknown image type!"); break;
}
if (!$sourceImage) { throw new Exception("Error opening image file!"); }
$targetImage = imagecreatetruecolor($targetWidth, $targetHeight);
// save transparency - based on code from: https://ca3.php.net/manual/en/function.imagecolortransparent.php#80935
if($imageType == IMAGETYPE_GIF) {
$transparentIndex = imagecolortransparent($sourceImage);
$transparentColor = @imagecolorsforindex($sourceImage, $transparentIndex);
if ($transparentColor) {
$newTransparentIndex = imagecolorallocate($targetImage, $transparentColor['red'], $transparentColor['green'], $transparentColor['blue']);
imagefill($targetImage, 0, 0, $newTransparentIndex);
imagecolortransparent($targetImage, $newTransparentIndex);
}
}
else if ($imageType == IMAGETYPE_PNG) {
imagealphablending($targetImage, false);
$transparentColor = imagecolorallocatealpha($targetImage, 0, 0, 0, 127);
imagefill($targetImage, 0, 0, $transparentColor);
imagesavealpha($targetImage, true);
}
// resample image
try{ imagecopyresampled($targetImage, $sourceImage, 0, 0, 0, 0, $targetWidth, $targetHeight, $sourceWidth, $sourceHeight); }catch(Exception $e){ throw new Exception("There was an error resizing the uploaded image!"); }
// save target image
$savedFile = false;
switch($imageType) {
case IMAGETYPE_JPEG: $savedFile = imagejpeg($targetImage, $targetPath, $SETTINGS['advanced']['imageResizeQuality']); break;
case IMAGETYPE_GIF: $savedFile = imagegif($targetImage, $targetPath); break;
case IMAGETYPE_PNG: $savedFile = imagepng($targetImage, $targetPath); break;
default: throw new Exception(__FUNCTION__ . ": Unknown image type!"); break;
}
if (!$savedFile) { throw new Exception("Error saving file!"); }
imagedestroy($sourceImage);
imagedestroy($targetImage);
//
return array($targetWidth, $targetHeight);
}
?>

386
cms/lib/database_functions.php Executable file
View File

@@ -0,0 +1,386 @@
<?php
if (!extension_loaded("mysql")) {
require_once "mysql.php";
}
function escapeMysqlWildcards($string) {
return addcslashes($string, '%_');
}
function connectToMySQL($returnErrors = false) {
global $SETTINGS, $DBH;
addPlugins("pre_db", $SETTINGS);
### Connect to database
try {
Db::getInstance($SETTINGS['mysql']['hostname'], $SETTINGS['mysql']['username'], $SETTINGS['mysql']['password'], $SETTINGS['mysql']['database']);
$DBH = @mysql_connect($SETTINGS['mysql']['hostname'], $SETTINGS['mysql']['username'], $SETTINGS['mysql']['password']);
@mysql_select_db($SETTINGS['mysql']['database']);
}
catch (Exception $e) {
$connectionError = $e->getMessage();
$libDir = pathinfo(__FILE__, PATHINFO_DIRNAME);
ob_start();
$doc = new domdocument();
require(__DIR__."/../../template/estandar/mantenimiento.tpl");
$resultado = ob_get_clean();
echo $resultado;
exit();
}
### check for required mysql version
$currentVersion = preg_replace("/[^0-9\.]/", "", mysql_get_server_info());
if (version_compare(REQUIRED_MYSQL_VERSION, $currentVersion, '>')) {
$error = "This program requires MySQL v" .REQUIRED_MYSQL_VERSION. " or newer. This server has v$currentVersion installed.<br/>\n";
$error .= "Please ask your server administrator to install MySQL v" .REQUIRED_MYSQL_VERSION. " or newer.<br/>\n";
if ($returnErrors) { return $error; }
die($error);
}
mysql_set_charset("utf8mb4") or die("Error loading character set utf8mb4: " .mysql_error(). "");
mysqlStrictMode(true);
return '';
}
function mysqlStrictMode($strictMode) {
$currentVersion = preg_replace("/[^0-9\.]/", "", mysql_get_server_info());
$isMySql5 = version_compare($currentVersion, '5.0.0', '>=');
# only for Mysql 5
if (!$isMySql5) { return; }
# set MySQL strict mode - https://dev.mysql.com/doc/refman/5.0/en/server-sql-mode.html
if ($strictMode) {
$query = "SET SESSION sql_mode = 'STRICT_ALL_TABLES,NO_ZERO_IN_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER'";
mysql_query($query) or die("MySQL Error: " .mysql_error(). "\n");
}
else {
$query = "SET SESSION sql_mode = 'NO_ZERO_IN_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER'";
mysql_query($query) or die("MySQL Error: " .mysql_error(). "\n");
}
}
function createMissingSchemaTablesAndFields() {
global $APP, $TABLE_PREFIX;
$schemaTables = getSchemaTables();
$mysqlTables = getMysqlTablesWithPrefix();
// create missing schema tables in mysql
foreach ($schemaTables as $tableName) {
// create mysql table
$mysqlTableName = $TABLE_PREFIX . $tableName;
if (!in_array($mysqlTableName, $mysqlTables)) {
notice("Creating MySQL table for schema table: $tableName<br/>\n");
$result = mysql_query("CREATE TABLE `".mysql_real_escape_string($mysqlTableName)."` (num int(10) unsigned NOT NULL auto_increment, PRIMARY KEY (num)) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4;");
if (!$result) { alert("Error creating MySQL table: $mysqlTableName<br/>\MySQL error was: ". htmlspecialchars(mysql_error()) . "\n"); }
}
// get schema fieldnames
$schemaFieldnames = array();
$tableSchema = loadSchema($tableName);
foreach ($tableSchema as $name => $valueOrArray) {
if (is_array($valueOrArray)) { array_push($schemaFieldnames, $name); } // only fields has arrays as values
}
// get mysql fieldnames
$mysqlFieldnames = array();
$result = mysql_query("SHOW COLUMNS FROM `".mysql_real_escape_string($mysqlTableName)."`") or die("MySQL Error: ". htmlspecialchars(mysql_error()) . "\n");
while ($row = mysql_fetch_assoc($result)) { array_push($mysqlFieldnames, strtolower($row['Field'])); }
// add missing fieldnames to mysql
$addFieldSQL = '';
foreach ($schemaFieldnames as $fieldname) {
if (!in_array(strtolower($fieldname), $mysqlFieldnames)) {
$columnType = getColumnTypeFor($fieldname, @$tableSchema[$fieldname]['type'], @$tableSchema[$fieldname]['customColumnType']);
if (!$columnType) { continue; }
if ($addFieldSQL) { $addFieldSQL .= ", "; }
$addFieldSQL .= " ADD COLUMN `".mysql_real_escape_string($fieldname)."` $columnType";
}
}
if ($addFieldSQL) {
mysql_query("ALTER TABLE `".mysql_real_escape_string($mysqlTableName)."` $addFieldSQL") or die("Error adding fields to '$mysqlTableName', the error was:\n\n". htmlspecialchars(mysql_error()));
notice("Adding MySQL fields for schema table: $tableName<br/>\n");
}
}
}
function getSchemaTables($dir = '') {
if (!$dir) { $dir = realpath("{$GLOBALS['APP']['datadir']}/schema/"); }
// get schema files
$schemaTables = array();
foreach (scandir($dir) as $file) {
if (!preg_match("/([^.]+)\.ini\.php$/", $file, $matches)) { continue; } // skip non-schema files
$tableName = $matches[1];
$schemaTables[] = $tableName;
}
return $schemaTables;
}
function &getSchemaFields($tableNameOrSchema) {
// load schema
$schema = $tableNameOrSchema;
if (!is_array($schema)) { $schema = loadSchema($tableNameOrSchema); }
// load fields
$fieldList = array();
foreach ($schema as $name => $valueOrArray) {
if (is_array($valueOrArray)) { // only fields have arrays as values, other values are table metadata
$fieldList[$name] = $valueOrArray;
$fieldList[$name]['name'] = $name; // add pseudo-field for fieldname
}
}
//
return $fieldList;
}
function loadSchema($tableName, $schemaDir = '') {
global $APP;
// error checking
if (!$tableName) { die(__FUNCTION__ . ": no tableName specified!"); }
// get schemapath
$tableNameWithoutPrefix = getTableNameWithoutPrefix($tableName);
if (!$schemaDir) { $schemaFilepath = "{$APP['datadir']}/schema/$tableNameWithoutPrefix.ini.php"; }
else { $schemaFilepath = "$schemaDir/". getTableNameWithoutPrefix($tableName) . ".ini.php"; }
// load schema
$schema = array();
if (file_exists($schemaFilepath)) {
$schema = loadINI($schemaFilepath);
}
//
return $schema;
}
function getTableNameWithoutPrefix($tableName) { // add $TABLE_PREFIX to table if it isn't there already
return preg_replace("/^{$GLOBALS['TABLE_PREFIX']}/", '', $tableName); // remove prefix
}
function getColumnTypeFor($fieldName, $fieldType, $customColumnType = "") {
$columnType = "";
// special case: default column type specified
if ($customColumnType) { $columnType = $customColumnType; }
// Special Fieldnames
elseif ($fieldName == 'num') { $columnType = 'int(10) unsigned NOT NULL auto_increment'; }
elseif ($fieldName == 'createdDate') { $columnType = 'datetime NOT NULL'; }
elseif ($fieldName == 'createdByUserNum') { $columnType = 'int(10) unsigned NOT NULL'; }
elseif ($fieldName == 'updatedDate') { $columnType = 'datetime NOT NULL'; }
elseif ($fieldName == 'updatedByUserNum') { $columnType = 'int(10) unsigned NOT NULL'; }
elseif ($fieldName == 'dragSortOrder') { $columnType = 'int(10) unsigned NOT NULL'; }
// NOTE: Other special field types don't need to be specified here because they have required
// ... field types in /lib/menus/default/editField_functions.php that map to the column
// ... types below. We only need to specify the column types above because they are
// ... not available with any predefined field type.
// otherwise return columnType for fieldType
elseif ($fieldType == '') { $columnType = ''; }
elseif ($fieldType == 'none') { $columnType = ''; }
elseif ($fieldType == 'textfield') { $columnType = 'mediumtext'; }
elseif ($fieldType == 'multitext') { $columnType = 'mediumtext'; }
elseif ($fieldType == 'textbox') { $columnType = 'mediumtext'; }
elseif ($fieldType == 'codigo') { $columnType = 'mediumtext'; }
elseif ($fieldType == 'wysiwyg') { $columnType = 'mediumtext'; }
elseif ($fieldType == 'date') { $columnType = 'datetime NOT NULL'; }
elseif ($fieldType == 'list') { $columnType = 'mediumtext'; }
elseif ($fieldType == 'checkbox') { $columnType = 'tinyint(1) unsigned NOT NULL'; }
elseif ($fieldType == 'upload') { $columnType = ''; }
elseif ($fieldType == 'separator') { $columnType = ''; }
// special fields types
elseif ($fieldType == 'accessList') { $columnType = ''; }
elseif ($fieldType == 'dateCalendar') { $columnType = ''; }
else {
$columnType = 'mediumtext';
//die(__FUNCTION__ . ": Field '" .htmlspecialchars($fieldName). "' has unknown fieldType '" .htmlspecialchars($fieldType). "'.");
}
return $columnType;
}
function getMysqlTablesWithPrefix() {
global $TABLE_PREFIX;
$tableNames = array();
$escapedTablePrefix = mysql_real_escape_string($TABLE_PREFIX);
$escapedTablePrefix = preg_replace("/([_%])/", '\\\$1', $escapedTablePrefix); // escape mysql wildcard chars
$result = mysql_query("SHOW TABLES LIKE '$escapedTablePrefix%'") or die("MySQL Error: ". htmlspecialchars(mysql_error()) . "\n");
while ($row = mysql_fetch_row($result)) {
array_push($tableNames, $row[0]);
}
return $tableNames;
}
function getTablenameErrors($tablename) {
// get used tablenames
static $usedTableNamesLc = array();
static $loadedTables;
if (!$loadedTables++) {
foreach (getMysqlTablesWithPrefix() as $usedTablename) {
$withoutPrefixLc = strtolower(getTablenameWithoutPrefix($usedTablename));
array_push($usedTableNamesLc, $withoutPrefixLc);
}
foreach (getSchemaTables() as $usedTableName) {
$withoutPrefixLc = strtolower($usedTablename);
array_push($usedTableNamesLc, $withoutPrefixLc);
}
}
// get reserved tablenames
$reservedTableNamesLc = array();
array_push($reservedTableNamesLc, 'home', 'admin', 'database', 'accounts', 'license'); // the are hard coded menu names
array_push($reservedTableNamesLc, 'default'); // can't be used because menu folder exists with default menu files
array_push($reservedTableNamesLc, 'all'); // can't be used because the "all" keyword gives access to all menus in user accounts
// get error
$error = null;
$tablenameLc = strtolower(getTableNameWithoutPrefix($tablename));
if ($tablenameLc == "") { $error = "No table name specified!\n"; }
else if (preg_match("/^_/", $tablenameLc)) { $error = "Table name cannot start with an underscore!\n"; }
else if (preg_match("/[A-Z]/", $tablename)) { $error = "Table name must be lowercase!\n"; }
else if (preg_match("/[^a-z0-9\_]/", $tablename)) { $error = "Table name can only contain these characters (\"a-z, 0-9, and _\")!\n"; }
if (in_array($tablenameLc, $usedTableNamesLc)) { $error = "That table name is already in use, please choose another.\n"; }
if (in_array($tablenameLc, $reservedTableNamesLc)) { $error = "That table name is not allowed, please choose another.\n"; }
//
return $error;
}
function getListOptions($tablename, $fieldname) {
$valuesToLabels = array();
$schema = loadSchema($tablename);
$fieldSchema = $schema[$fieldname];
$fieldOptions = getListOptionsFromSchema($fieldSchema);
foreach ($fieldOptions as $valueAndLabel) {
list($value, $label) = $valueAndLabel;
$valuesToLabels[$value] = $label;
}
return $valuesToLabels;
}
function getListOptionsFromSchema($fieldSchema, $record = null) {
global $TABLE_PREFIX;
$listOptions = array();
$optionsType = @$fieldSchema['optionsType'];
### parse text options
if ($optionsType == 'text') { // parse
$optionText = explode("\n", @$fieldSchema['optionsText']);
foreach ($optionText as $optionString) {
if (preg_match("/(^|[^\|])(\|\|)*(\|)(?!\|)/", $optionString, $match, PREG_OFFSET_CAPTURE)) {
$delimiterOffset = $match[3][1];
$value = substr($optionString, 0, $delimiterOffset);
$label = substr($optionString, $delimiterOffset+1);
}
else {
$value = $optionString;
$label = $optionString;
}
$value = str_replace("||", "|", $value);
$label = str_replace("||", "|", $label);
// remove trailing whitespace
$value = rtrim($value);
$label = rtrim($label);
$listOptions[] = array($value, $label);
}
}
### lookup table values
else {
// create query
if ($optionsType == 'table') {
$selectFields = "`" . @$fieldSchema['optionsValueField'] ."`, `". @$fieldSchema['optionsLabelField'] . "`";
$selectTable = "`" . $TABLE_PREFIX . $fieldSchema['optionsTablename'] . "`";
$tableSchema = loadSchema($fieldSchema['optionsTablename']);
$orderBy = @$tableSchema['listPageOrder'] ? "ORDER BY {$tableSchema['listPageOrder']}" : "";
$query = "SELECT $selectFields FROM $selectTable $orderBy LIMIT 0, 999";
}
else if ($optionsType == 'query') {
$filterFieldValue = @$record[ @$fieldSchema['filterField'] ];
$GLOBALS['ESCAPED_FILTER_VALUE'] = mysql_real_escape_string($filterFieldValue);
$query = getEvalOutput($fieldSchema['optionsQuery']);
}
else { die("Unknown optionsType '$optionsType'!"); }
// execute query
$result = @mysql_query($query);
if (!$result) {
$error = "There was an error creating the list field.\n\n";
$error .= "MySQL Error: " .mysql_error(). "\n\n";
header("Content-type: text/plain");
die($error);
}
while ($row = mysql_fetch_row($result)) {
$listOptions[] = array($row[0],$row[1]);
}
if (is_resource($result)) { mysql_free_result($result); }
}
//
return $listOptions;
}
function mysql_select_found_rows() {
$result = mysql_query('SELECT FOUND_ROWS()') or die("MySQL Error: ". htmlspecialchars(mysql_error()) . "\n");
$count = mysql_result($result, 0);
if (is_resource($result)) { mysql_free_result($result); }
return $count;
}
function &mysql_query_fetch_all_assoc($query) {
$microtime = microtime(true);
if (class_exists("CocoDB") && isset(CocoDB::$force_redis) && CocoDB::$force_redis){
$hash = CocoDB::cacheGenerateHash("DB_".md5($query));
$data = CocoDB::cacheGet($hash);
if (@$data) {
$table = explode(" ",strtolower($query));
$table = join("",array_splice($table,array_search("from",$table)+1,1));
if (!@CocoDB::$noCacheTABLES || (CocoDB::$noCacheTABLES && !in_array($table,CocoDB::$noCacheTABLES))){
$result = json_decode($data,true);
return $result;
}
}
}
$records = array();
$result = mysql_query($query) or die("MySQL Error: ". htmlspecialchars(mysql_error()) . "\n");
while ($record = mysql_fetch_assoc($result)) {
$records[] = $record;
}
if (class_exists("CocoDB") && isset(CocoDB::$storeDebugData) && CocoDB::$storeDebugData) {
$debugData = [
"hora" => date("Y-m-d H:i:s", time()) . " " . microtime(),
"query" => $query,
"records" => $records,
"time" => microtime(true) - $microtime
];
CocoDB::$debugData[] = $debugData;
}
if (is_resource($result)) { mysql_free_result($result); }
if (class_exists("CocoDB") && isset(CocoDB::$force_redis) && CocoDB::$force_redis){
$table = explode(" ",strtolower($query));
$table = join("",array_splice($table,array_search("from",$table)+1,1));
if (!@CocoDB::$noCacheTABLES || (CocoDB::$noCacheTABLES && !in_array($table,CocoDB::$noCacheTABLES))){
CocoDB::cacheSet($hash,json_encode($records));
}
}
return $records;
}

388
cms/lib/handlers/handler_ws.php Executable file
View File

@@ -0,0 +1,388 @@
<?
// TEST 4
define('COCO_ENDPOINT',"http://ws.cocosolution.com/api/");
define('SCHEMAS_PATH',dirname(__FILE__)."/../../data/schema");
require_once dirname(__FILE__)."/../classes/CocoWS.php";
$post = json_decode(file_get_contents('php://input'), true);
if ($post && !empty($post)) {
$_REQUEST = array_merge($_REQUEST, $post);
}
require_once __DIR__."/../plugins/index.php";
CocoWS::setEndpoint(COCO_ENDPOINT);
$dummy = @$_REQUEST ?: [];
$pluginsInserted = addPlugins('handler_ws', $dummy);
if (isset($_REQUEST["action_ws"])){
header("Content-type:application/json");
switch($_REQUEST["action_ws"]){
case "updateAllSchemas" : _updateAllSchemas(); break;
case "updateSchema" : _updateSchema(@$_REQUEST["tableName"]); break;
case "getAllSchemas" : _getAllSchemas(); break;
case "validateCredentials" : _validateCredentials(); break;
case "getInstalledPlugins" : _getInstalledPlugins(); break;
case "updateAllPlugins" : _updateAllPlugins(); break;
case "updatePlugin" : _updatePLugin(@$_REQUEST["plugin"]); break;
case "saveFile": _saveFile(); break;
case "coreUpdate": _coreUpdate(realpath($GLOBALS["APP"]["pluginsdir"]."/../../lib")); break;
case "pluginsUpdate": _coreUpdate(realpath($GLOBALS["APP"]["pluginsdir"]),true); break;
case "removeFile": _removeFile(); break;
case "clearCache": _clearCache(); break;
case "renameFile": _renameFile();
default : die(json_encode(["result" => 0,"error" => "Método no permitido"]));
}
}
function _clearCache(){
CocoWS::setToken(@$_REQUEST["token"]);
if (!CocoWS::validateUploadToken(@$_REQUEST["tokenHash"])) {
die(json_encode(['error' => ['message' => 'Token no válido', 'code' => 403]]));
}
_clearCacheFiles();
header('Content-Type: application/json');
$res = array("success" => true);
die(json_encode($res));
}
function _clearCacheFiles(){
// Remove uploads Caché
if (file_exists(__DIR__.'/../../../cache')) rrmdir(__DIR__.'/../../../cache/');
mkdir(__DIR__.'/../../../cache');
}
function rrmdir($src) {
$dir = opendir($src);
while(false !== ( $file = readdir($dir)) ) {
if (( $file != '.' ) && ( $file != '..' )) {
$full = $src . '/' . $file;
if ( is_dir($full) ) {
rrmdir($full);
}
else {
unlink($full);
}
}
}
closedir($dir);
rmdir($src);
}
function _coreUpdate($path,$plugins = false){
CocoWS::setToken(@$_REQUEST["token"]);
if (!CocoWS::validateUploadToken(@$_REQUEST["tokenHash"])) {
die(json_encode(['error' => ['message' => 'Token no válido', 'code' => 403]]));
}
if (@$_REQUEST["multisite"]) $path = realpath($GLOBALS["APP"]["pluginsdir"]."/../../../");
switch(@$_REQUEST["action"]){
case "getFile":
_saveFile(true);
break;
case "diff":
header('Content-Type: application/json');
$res = array("file" => @$_REQUEST["file"],"hash" => @$_REQUEST["hash"]);
if (md5_file($path.@$_REQUEST["file"])!=@$_REQUEST["hash"]) die(json_encode(["error" => "Los hashes no coinciden"]));
$res["fileContent"] = base64_encode(file_get_contents($path.@$_REQUEST["file"]));
if (!@$_REQUEST["file"]||!@$_REQUEST["hash"]) die(json_encode(["error" => "Faltan datos"]));
die(json_encode($res));
break;
default:
//if (@$_REQUEST["token"]!=md5(md5_file($path."/lib/admin_functions.php").md5_file($path."/lib/user_functions.php"))) die("Error");
$rii = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path));
$files = array();
if (@$_REQUEST["multisite"]) $files[] = array("fileName" => "/cms/lib/plugins/builder_saas/layout.json","hash" => md5_file(__DIR__."/../plugins/builder_saas/layout.json"));
foreach ($rii as $file) {
if ($file->isDir()){ continue;}
if (!strpos($file->getPathname(),"/.")
&& !strpos($file->getPathname(),"cms/uploads/")
&& !strpos($file->getPathname(),"cache/")
&& !strpos($file->getPathname(),"template/estandar/images")
&& !strpos($file->getPathname(),"/minified/")
&& !strpos($file->getPathname(),"cms/data")){
if (!$plugins){
if (strpos($file->getPathname(),"cms/lib/plugins/index.php")){
$files[] = array("fileName" => str_replace($path,"",$file->getPathname()),"hash" => md5_file($file->getPathname()));
}else if (!strpos($file->getPathname(),"cms/lib/plugins/")){
$files[] = array("fileName" => str_replace($path,"",$file->getPathname()),"hash" => md5_file($file->getPathname()));
}
}else{
$files[] = array("fileName" => str_replace($path,"",$file->getPathname()),"hash" => md5_file($file->getPathname()));
}
}
}
header('Content-Type: application/json');
$res = array("coreHashes" => $files);
die(json_encode($res));
}
}
function _getInstalledPlugins(){
die(json_encode(["result" => 1,"data" => getSchemaPlugins()]));
}
function _updatePlugin($name){
die(json_encode(["result" => 0,"error" => "sin terminar"]));
}
function _updateAllPlugins(){
die(json_encode(["result" => 0,"error" => "sin terminar"]));
}
function _updateSchema($tableName){
CocoWS::setToken(@$_REQUEST["token"]);
if (!CocoWS::validateUploadToken(@$_REQUEST["tokenHash"])) {
die(json_encode(['error' => ['message' => 'Token no válido', 'code' => 403]]));
}
$fileData = json_decode(file_get_contents('php://input'), true);
if (@$fileData["schemaNew"] && @$fileData["tableName"]){
CocoWS::insertOrUpdateSchema(@$fileData["tableName"],SCHEMAS_PATH,$fileData["schemaNew"]);
}else{
CocoWS::insertOrUpdateSchema(@$_REQUEST["tableName"],SCHEMAS_PATH);
}
die(json_encode(["result" => 3]));
}
function _updateAllSchemas(){
CocoWS::setToken(@$_REQUEST["token"]);
if (!CocoWS::validateUploadToken(@$_REQUEST["tokenHash"])) {
die(json_encode(['error' => ['message' => 'Token no válido', 'code' => 403]]));
}
$allWSSchemas = CocoWS::getSchemaTables('','acai');
$data = array_map(function($rec){ return $rec["tableName"]; },$allWSSchemas);
$localSchemas = array_values(array_filter(array_map(function($rec){ if ($rec!==".." && $rec !== ".") return str_replace(".ini.php","",$rec); },scandir(SCHEMAS_PATH))));
$diff = array_diff($localSchemas,$data);
if (!@$data) die(json_encode(["result" => 0,"error" => "Error, schemas no encontrados"]));
foreach(scandir(SCHEMAS_PATH) as $file){
if ($file==".." || $file==".") continue;
if (in_array(str_replace(".ini.php","",$file), $diff)) unlink(SCHEMAS_PATH."/".$file);
}
foreach($data as $schema){
CocoWS::insertOrUpdateSchema($schema,SCHEMAS_PATH,@array_values(array_filter($allWSSchemas,function($rec) use ($schema) { return @$rec["tableName"] == $schema; }))[0]);
}
die(json_encode(["result" => 1]));
}
function _saveFile($coreUpdate = false) {
$fileData = json_decode(file_get_contents('php://input'), true);
CocoWS::setToken(@$fileData["token"]);
if (!CocoWS::validateUploadToken(@$fileData["tokenHash"])) {
die(json_encode(['error' => ['message' => 'Token no válido', 'code' => 403]]));
}
if (!isset($fileData['fileName']) || !isset($fileData['content'])) {
die(json_encode(['error' => ['message' => 'Datos no enviados', 'code' => 403]]));
}
$data = base64_decode($fileData['content']);
if (!$data) {
die(json_encode(['error' => ['message' => 'Datos no enviados', 'code' => 403]]));
}
$fileName = basename($fileData['fileName']);
if (empty($fileName)) {
die(json_encode(['error' => ['message' => 'Nombre no válido', 'code' => 403]]));
}
if (isset($fileData['zip'])) {
$zipname = tempnam(sys_get_temp_dir(), 'zip').'.zip';
file_put_contents($zipname, $data);
$zip = new ZipArchive;
if ($zip->open($zipname) === true) {
if (!$coreUpdate){
$zip->extractTo($GLOBALS["APP"]["pluginsdir"]."/".$fileName."/");
}else if (@$_REQUEST["multisite"]){
$zip->extractTo(realpath($GLOBALS["APP"]["pluginsdir"]."/../../../")."/");
}else{
$zip->extractTo(realpath($GLOBALS["APP"]["pluginsdir"]."/../")."/");
}
$zip->close();
unlink($zipname);
}
else {
$res["title"] = "Error";
$res["error"] = ["message" => "Ha ocurrido un error descomprimiendo el plugin. Por favor, contacta con los administradores para solventarlo.", "code" => 500];
die(json_encode($res));
}
die(json_encode(['success' => true]));
}
$allowed = [
'application/pdf' => 'pdf',
'application/zip' => 'zip',
'audio/x-aac' => 'aac',
'application/vnd.amazon.ebook' => 'azw',
'audio/x-aiff' => 'aiff',
'audio/mp3' => 'mp3',
'audio/mpeg' => 'mp3',
'image/bmp' => 'bmp',
'text/css' => 'css',
'text/csv' => 'csv',
'text/plain' => 'csv',
'text/calendar' => 'ics',
'application/epub+zip' => 'epub',
'image/gif' => 'gif',
'image/x-icon' => 'ico',
'image/vnd.microsoft.icon' => 'ico',
'image/jpeg' => ['jpg', 'jpeg'],
'image/png' => 'png',
'image/svg+xml' => 'svg',
'image/svg' => 'svg',
'image/tiff' => 'tiff',
'image/webp' => 'webp',
'video/x-m4v' => 'm4v',
'video/x-ms-wmv' => 'wmv',
'video/mpeg' => 'mpeg',
'video/mp4' => 'mp4',
'video/webm' => 'webm',
'video/ogg' => 'ogg',
'application/vnd.oasis.opendocument.text' => 'odt',
'application/vnd.oasis.opendocument.graphics' => 'odg',
'application/vnd.oasis.opendocument.spreadsheet' => 'ods',
'application/vnd.oasis.opendocument.presentation' => 'odp',
'application/vnd.openxmlformats-officedocument.wordprocessingml.document' => 'docx',
'application/msword' => 'doc',
'application/vnd.ms-excel' => 'xls',
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' => 'xlsx',
'application/vnd.ms-powerpoint' => 'ppt',
'application/vnd.openxmlformats-officedocument.presentationml.presentation' => 'pptx'
];
$f = finfo_open();
$mime_type = finfo_buffer($f, $data, FILEINFO_MIME_TYPE);
finfo_close($f);
if (!isset($allowed[$mime_type])) {
die(json_encode(['error' => ['message' => 'Tipo de archivo no válido', 'code' => 403]]));
}
$extension = strtolower(pathinfo($fileName, PATHINFO_EXTENSION));
if (is_array($allowed[$mime_type])) {
if (!in_array($extension, $allowed[$mime_type])) {
die(json_encode(['error' => ['message' => 'Nombre de archivo no válido', 'code' => 403, 'fileName' => $fileName, 'extension' => $extension, 'mime' => $mime_type]]));
}
}
else {
if ($extension !== $allowed[$mime_type]) {
die(json_encode(['error' => ['message' => 'Nombre de archivo no válido', 'code' => 403, 'fileName' => $fileName, 'extension' => $extension, 'mime' => $mime_type]]));
}
}
if (@$fileData["path"]){
$path = realpath(__DIR__.'/../../../template/estandar/'.str_replace("..","",$fileData["path"]));
if (!file_exists($path)) die(json_encode(['error' => ['message' => 'La ruta de destino no existe', 'code' => 403, 'fileName' => $fileName, 'extension' => $extension, 'mime' => $mime_type]]));
$urlPath = str_replace(realpath(__DIR__.'/../../..'),"",realpath($path));
}else{
$path = realpath(__DIR__.'/../../uploads/');
if (!file_exists($path)) die(json_encode(['error' => ['message' => 'La ruta de destino no existe', 'code' => 403, 'fileName' => $fileName, 'extension' => $extension, 'mime' => $mime_type]]));
$urlPath = str_replace(realpath(__DIR__.'/../../..'),"",realpath($path));
_clearCacheFiles();
}
file_put_contents($path."/".$fileName, $data);
die(json_encode(['success' => true, 'filePath' => $path."/".$fileName, 'urlPath' => $urlPath."/".$fileName]));
}
function _removeFile() {
$fileData = json_decode(file_get_contents('php://input'), true);
CocoWS::setToken(@$fileData["token"]);
if (!CocoWS::validateUploadToken(@$fileData["tokenHash"])) {
die(json_encode(['error' => ['message' => 'Token no válido', 'code' => 403]]));
}
if (!isset($fileData['file'])) {
die(json_encode(['error' => ['message' => 'Datos no enviados', 'code' => 403]]));
}
$filePath = $fileData['file'];
if (isset($fileData['plugin'])) {
$filePath = $GLOBALS['APP']['pluginsdir'].'/'.$filePath;
}
$deleted = _deleteAll($filePath);
die(json_encode(['success' => $deleted ? true : false]));
}
function _deleteAll($str) {
if (!file_exists($str)) return false;
if (is_file($str)) {
return unlink($str);
}
elseif (is_dir($str)) {
//Get a list of the files in this directory.
$scan = glob(rtrim($str,'/').'/*');
//Loop through the list of files.
foreach($scan as $index=>$path) {
//Call our recursive function.
_deleteAll($path);
}
//Remove the directory itself.
return @rmdir($str);
}
}
function _validateCredentials() {
$fileData = json_decode(file_get_contents('php://input'), true);
CocoWS::setToken(@$fileData["token"]);
if (!CocoWS::validateUploadToken(@$fileData["tokenHash"])) {
die(json_encode(['error' => ['message' => 'Token no válido', 'code' => 403]]));
}
$result = ["success" => true];
die(json_encode($result));
}
function _getAllSchemas(){
$fileData = json_decode(file_get_contents('php://input'), true);
CocoWS::setToken(@$fileData["token"]);
if (!CocoWS::validateUploadToken(@$fileData["tokenHash"])) {
die(json_encode(['error' => ['message' => 'Token no válido', 'code' => 403]]));
}
$result = [];
foreach(scandir(SCHEMAS_PATH) as $file){
$schemaName = str_replace(".ini.php","",$file);
if (strpos($file,".ini.php")) $result[$schemaName] = loadINI(SCHEMAS_PATH."/".$file);
}
die(json_encode($result));
}
function _renameFile() {
$fileData = json_decode(file_get_contents('php://input'), true);
CocoWS::setToken(@$fileData["token"]);
if (!CocoWS::validateUploadToken(@$fileData["tokenHash"])) {
die(json_encode(['error' => ['message' => 'Token no válido', 'code' => 403]]));
}
if (!isset($fileData['prevFile']) || !isset($fileData['newFile'])) {
die(json_encode(['error' => ['message' => 'Datos no enviados', 'code' => 403]]));
}
$path = realpath(__DIR__.'/../../uploads/').'/';
$prevFile = $path.basename($fileData['prevFile']);
$newFile = $path.basename($fileData['newFile']);
if (file_exists($prevFile)) {
rename($prevFile, $newFile);
}
die(json_encode(['success' => file_exists($newFile)]));
}

188
cms/lib/init.php Executable file
View File

@@ -0,0 +1,188 @@
<?php
$START_TIME = microtime(); // needs to be first to get accurate time reading
define('REQUIRED_PHP_VERSION', '5.6'); // Released May 2003
define('REQUIRED_MYSQL_VERSION', '4.1.7'); // Released 23 October 2004 - First Production Release
define("RUTA_PLANTILLA_FROM_INIT","/template/estandar");
enableErrorReporting();
updatePHPSettings();
displayInitErrors();
renameAndRemoveDefaultFiles();
$programDir = _getProgramDir();
require_once "$programDir/lib/classes/Db.php";
require_once "$programDir/lib/common.php";
require_once "$programDir/lib/database_functions.php";
global $SETTINGS;
setRequestGlobal(); // this must be called _AFTER_ updatePHPSettings() - uses fixed PATH_INFO _and_ undo magic_quotes
setProgramGlobals(); // this must be called _AFTER_ load libraries - uses loadINI
loadPlugins();
if (function_exists('date_default_timezone_set')) {
if (!@date_default_timezone_set($SETTINGS['timezone'])) {
@$GLOBALS['APP']['alerts'] .= "Error setting timezone to '{$SETTINGS['timezone']}', Invalid timezone name.<br/>\n";
date_default_timezone_set('UTC');
}
}
displaySocketErrors();
if ($SETTINGS['isInstalled']) {
connectToMySQL();
}
function enableErrorReporting() {
if (!defined('E_STRICT')) { define('E_STRICT', 2048); } // define E_STRICT for PHP < 5
error_reporting(E_ALL | E_STRICT); // display all errors
ini_set('display_errors', '1');
ini_set('display_startup_errors', '1');
ini_set('track_errors', '1'); // store last error in $php_errormsg
ini_set('html_errors', '0'); // don't output html links in error messages
ini_set('mysql.trace_mode', '0'); // when this is enabled SQL_CALC_FOUND_ROWS and FOUND_ROWS doesn't work: https://bugs.php.net/bug.php?id=33021
}
function updatePHPSettings() {
umask(0); // use default permission on created files
ini_set('memory_limit', '128M'); // raise memory limit (if allowed)
ini_set('magic_quotes_runtime', 0); // disable magic_quotes_runtime (backslashes quotes in input)
ini_set('default_charset', 'utf-8'); //
ini_set('mysql.connect_timeout', 5); // PHP default of 60 ties up browser for too long - mysql.connect_timeout may not work on windows
if (!ini_get('sendmail_from')) { ini_set('sendmail_from', ''); }
set_include_path(_getProgramDir() . PATH_SEPARATOR . get_include_path());
/*
// Anael: Esto ya no debería usarse para nada y da problemas en nuevas versiones de PHP
if (get_magic_quotes_gpc()) { // undo deprecated php magic_quotes feature
$in = array(&$_GET, &$_POST, &$_COOKIE); // code from: https://talks.php.net/show/php-best-practices/26
while (list($k,$v) = each($in)) {
foreach ($v as $key => $val) {
if (!is_array($val)) {
$in[$k][$key] = stripslashes($val);
continue;
}
$in[] =& $in[$k][$key];
}
}
unset($in);
}
*/
$isCgiMode = PHP_SAPI == 'cgi' || PHP_SAPI == 'cgi-fcgi';
if ($isCgiMode && @$_SERVER['REQUEST_URI']) {
list($scriptUri) = explode('?', $_SERVER['REQUEST_URI']); // remove query string
if (@$_SERVER["PATH_INFO"] && @$_SERVER["PATH_INFO"] != $scriptUri) { // remove PATH_INFO
$escapedPathInfo = preg_quote($_SERVER['PATH_INFO'], '/');
$scriptUri = preg_replace("/$escapedPathInfo$/", "", $scriptUri);
}
$_SERVER['SCRIPT_NAME'] = $scriptUri;
}
$_SERVER['PHP_'.'SELF'] = @$_SERVER['SCRIPT_NAME'];
if (@$_SERVER["PATH_INFO"] == @$_SERVER['PHP_'.'SELF']) { $_SERVER["PATH_INFO"] = ""; }
if (!@$_SERVER['DOCUMENT_ROOT']) {
$_SERVER['DOCUMENT_ROOT'] = substr(__FILE__, 0, 0-strlen(@$_SERVER['SCRIPT_NAME']));
}
$_SERVER['DOCUMENT_ROOT'] .= "/"; // make sure we have trailing slash
$_SERVER['DOCUMENT_ROOT'] = preg_replace('/[\\\\\/]+/', '/', @$_SERVER['DOCUMENT_ROOT']); // replace and collapse slashes
}
function displayInitErrors() {
$errors = "";
if (version_compare(phpversion(), REQUIRED_PHP_VERSION) < 0) {
$errors .= "This program requires PHP v" .REQUIRED_PHP_VERSION. " or greater. You have PHP v" .phpversion(). " installed.<br/>\n";
$errors .= "Please ask your server adminstrator to upgrade PHP to a newer version.<br/><br/>\n";
die($errors);
}
$missingExtensions = "";
if (!extension_loaded("gd")) { $missingExtensions .= "This program requires the PHP 'GD' extension.<br/>\n"; }
if ($missingExtensions) {
$errors .= "$missingExtensions";
$errors .= "Please ask your server administrator to install missing PHP extension(s).<br/><br/>\n";
}
if (!function_exists('imagecreatefromjpeg')) {
$errors .= "PHP doesn't support jpegs (or thumbnails). Please ask your server administrator to recompile PHP with jpeg support.<br/>\n";
$errors .= "<b>Server Administrators:</b> imagecreatefromjpeg() isn't defined.\n";
$errors .= "Search these <a href='https://www.php.net/imagecreatefromjpeg'>comments</a> on php.net for 'undefined function' for more details.<br/><br/>\n";
}
if (ini_get('magic_quotes_runtime')) { $errors .= "Please disable the 'magic_quotes_runtime' setting in php.ini or with .htaccess.<br/>\n"; }
if (ini_get('magic_quotes_sybase')) { $errors .= "Please disable the 'magic_quotes_sybase' setting in php.ini or with .htaccess.<br/>\n"; }
if (ini_get('safe_mode')) { $errors .= "Please disable the 'safe_mode' setting in php.ini.<br/>\n"; }
if ($errors) { die($errors); }
}
function renameAndRemoveDefaultFiles() {
$defaultFiles = array('data/settings.dat.php');
$programDir = _getProgramDir();
foreach ($defaultFiles as $targetFile) {
$targetPath = "$programDir/$targetFile";
$defaultPath = "$targetPath.default";
if (!file_exists($defaultPath)) {
continue;
}
if (!file_exists($targetPath)) {
rename($defaultPath, $targetPath) || die("Error renaming '$defaultPath' : $php_errormsg! Make sure this file and it's directory are writable!");
}
else {
unlink($defaultPath) || die("Error deleting '$defaultPath' : $php_errormsg! Make sure this file and it's directory are writable!");
}
}
}
function setRequestGlobal() {
$_REQUEST = $_POST + $_GET;
// define form
if (@$_SERVER['PATH_INFO']) { // add form values from PATH_INFO (example app.php/name-value/city-Vancouver/)
$pairs = explode("/", $_SERVER['PATH_INFO']);
foreach ($pairs as $pair) {
if (!$pair) { continue; } // skip blank
@list($encodedName, $encodedValue) = explode('-', $pair, 2);
$name = urldecode($encodedName);
$value = urldecode($encodedValue);
if (array_key_exists($name, $_REQUEST)) { continue; } // skip if already defined in GET/POST
$_REQUEST[$name] = $value;
}
}
}
function setProgramGlobals() {
global $TABLE_PREFIX, $PROGRAM_DIR, $APP, $SETTINGS, $MENU_OPTIONS;
$settingsPath = _getProgramDir() . "/data/settings.dat.php";
// set globals
$SETTINGS = loadINI($settingsPath);
$TABLE_PREFIX = $SETTINGS['mysql']['tablePrefix'];
$PROGRAM_DIR = _getProgramDir();
$MENU_OPTIONS = array();
$APP = array(
'version' => '1.26',
'build' => '1',
'id' => '19',
'key' => '35809',
'datadir' => "$PROGRAM_DIR/data/",
'pluginsdir' => "$PROGRAM_DIR/lib/plugins",
'settingsFilepath' => $settingsPath, // set this ABOVE and BELOW!
);
}
function displaySocketErrors() {
if (!$GLOBALS['SETTINGS']['isInstalled']) {
$handle = @fsockopen("tcp://www.google.com", 80, $errno, $errstr, 5);
if (!$handle) {
$errors = "Error: PHP fsockopen() and/or network connectivity disabled!<br/>\n";
$errors .= "Test connection to www.google.com return error #" .@$errno. " - " .@$errstr. "<br/><br/>\n";
$errors .= "Please ask your server administrator to enable network connectivity for PHP.<br/><br/>\n";
die($errors);
}
}
}
function _getProgramDir() {
static $programDir;
if (!$programDir) {
$programDir = pathinfo(pathinfo(__FILE__, PATHINFO_DIRNAME), PATHINFO_DIRNAME);
$isUncPath = substr($programDir, 0, 2) == '\\\\';
$programDir = preg_replace('/[\\\\\/]+/', '/', $programDir); // replace and collapse slashes
if ($isUncPath) { $programDir = substr_replace($programDir, '\\\\', 0, 1); } // replace UNC prefix
}
return $programDir;
}
?>

836
cms/lib/mysql.php Executable file
View File

@@ -0,0 +1,836 @@
<?php
/**
* php7-mysql-shim
*
* @author Davey Shafik <me@daveyshafik.com>
* @copyright Copyright (c) 2017 Davey Shafik
* @license MIT License
* @link https://github.com/dshafik/php7-mysql-shim
*/
/**
* A drop-in replacement for ext/mysql in PHP 7+ using ext/mysqli instead
*
* This library is meant to be a _stop-gap_. It will be slower than using
* the native functions directly.
*
* You should switch to ext/pdo_mysql or ext/mysqli, and migrate to prepared
* queries (@see http://php.net/manual/en/pdo.prepared-statements.php) to
* ensure you are securely interacting with your database.
*/
namespace {
if (!extension_loaded('mysql')) {
if (!extension_loaded('mysqli')) {
trigger_error('php7-mysql-shim: ext/mysqli is required', E_USER_ERROR);
}
define('MYSQL_ASSOC', 1);
define('MYSQL_NUM', 2);
define('MYSQL_BOTH', 3);
define('MYSQL_CLIENT_COMPRESS', 32);
define('MYSQL_CLIENT_SSL', 2048);
define('MYSQL_CLIENT_INTERACTIVE', 1024);
define('MYSQL_CLIENT_IGNORE_SPACE', 256);
function mysql_connect(
$hostname = null,
$username = null,
$password = null,
$new = false,
$flags = 0
) {
if ($new !== false) {
trigger_error('Argument $new is no longer supported in PHP > 7', E_USER_WARNING);
}
if (null === $hostname) {
$hostname = ini_get('mysqli.default_host') ?: null;
}
if (null === $username) {
$username = ini_get('mysqli.default_user') ?: null;
}
if (null === $password) {
$password = ini_get('mysqli.default_pw') ?: null;
}
$hash = sha1($hostname . $username . $flags);
/* persistent connections start with p: */
if ($hostname[1] !== ':' && isset(\Dshafik\MySQL::$connections[$hash])) {
\Dshafik\MySQL::$last_connection = \Dshafik\MySQL::$connections[$hash]['conn'];
\Dshafik\MySQL::$connections[$hash]['refcount'] += 1;
return \Dshafik\MySQL::$connections[$hash]['conn'];
}
/* No flags, means we can use mysqli_connect() */
if ($flags === 0) {
$conn = mysqli_connect($hostname, $username, $password);
if (!$conn instanceof mysqli) {
return false;
}
\Dshafik\MySQL::$last_connection = $conn;
$conn->hash = $hash;
\Dshafik\MySQL::$connections[$hash] = array('refcount' => 1, 'conn' => $conn);
return $conn;
}
/* Flags means we need to use mysqli_real_connect() instead, and handle exceptions */
try {
\Dshafik\MySQL::$last_connection = $conn = mysqli_init();
mysqli_real_connect(
$conn,
$hostname,
$username,
$password,
'',
null,
'',
$flags
);
// @codeCoverageIgnoreStart
// PHPUnit turns the warning from mysqli_real_connect into an exception, so this never runs
if ($conn === false) {
return false;
}
// @codeCoverageIgnoreEnd
$conn->hash = $hash;
\Dshafik\MySQL::$connections[$hash] = array('refcount' => 1, 'conn' => $conn);
return $conn;
} catch (\Throwable $e) {
trigger_error($e->getMessage(), E_USER_WARNING);
// @codeCoverageIgnoreStart
// PHPUnit turns the warning into an exception, so this never runs
return false;
// @codeCoverageIgnoreEnd
}
}
function mysql_pconnect(
$hostname = null,
$username = null,
$password = null,
$flags = 0
) {
$hostname = 'p:' . $hostname;
return mysql_connect($hostname, $username, $password, false, $flags);
}
function mysql_close(\mysqli $link = null)
{
$isDefault = ($link === null);
$link = \Dshafik\MySQL::getConnection($link, __FUNCTION__);
if ($link === null) {
// @codeCoverageIgnoreStart
// PHPUnit Warning -> Exception
return false;
// @codeCoverageIgnoreEnd
}
if (isset(\Dshafik\MySQL::$connections[$link->hash])) {
\Dshafik\MySQL::$connections[$link->hash]['refcount'] -= 1;
}
$return = true;
if (\Dshafik\MySQL::$connections[$link->hash]['refcount'] === 0) {
$return = mysqli_close($link);
unset(\Dshafik\MySQL::$connections[$link->hash]);
}
if ($isDefault) {
Dshafik\MySQL::$last_connection = null;
}
return $return;
}
function mysql_select_db($databaseName, \mysqli $link = null)
{
$link = \Dshafik\MySQL::getConnection($link);
return mysqli_query(
$link,
'USE `' . mysqli_real_escape_string($link, $databaseName) . '`'
) !== false;
}
function mysql_query($query, \mysqli $link = null)
{
return mysqli_query(\Dshafik\MySQL::getConnection($link), $query);
}
function mysql_unbuffered_query($query, \mysqli $link = null)
{
$link = \Dshafik\MySQL::getConnection($link);
if (mysqli_real_query($link, $query)) {
return mysqli_use_result($link);
}
return false;
}
function mysql_db_query($databaseName, $query, \mysqli $link = null)
{
if (mysql_select_db($databaseName, $link)) {
return mysql_query($query, $link);
}
return false;
}
function mysql_list_dbs(\mysqli $link = null)
{
return mysql_query('SHOW DATABASES', $link);
}
function mysql_list_tables($databaseName, \mysqli $link = null)
{
$link = \Dshafik\MySQL::getConnection($link);
$query = sprintf(
'SHOW TABLES FROM `%s`',
mysql_real_escape_string($databaseName, $link)
);
return mysql_query($query, $link);
}
function mysql_list_fields($databaseName, $tableName, \mysqli $link = null)
{
$link = \Dshafik\MySQL::getConnection($link);
$query = sprintf(
'SHOW COLUMNS FROM `%s`.`%s`',
mysqli_real_escape_string($link, $databaseName),
mysqli_real_escape_string($link, $tableName)
);
$result = mysql_query($query, $link);
if ($result instanceof \mysqli_result) {
$result->table = $tableName;
return $result;
}
trigger_error('mysql_list_fields(): Unable to save MySQL query result', E_USER_WARNING);
// @codeCoverageIgnoreStart
return false;
// @codeCoverageIgnoreEnd
}
function mysql_list_processes(\mysqli $link = null)
{
return mysql_query('SHOW PROCESSLIST', $link);
}
function mysql_error(\mysqli $link = null)
{
return @mysqli_error(\Dshafik\MySQL::getConnection($link));
}
function mysql_errno(\mysqli $link = null)
{
return mysqli_errno(\Dshafik\MySQL::getConnection($link));
}
function mysql_affected_rows(\mysqli $link = null)
{
return mysqli_affected_rows(\Dshafik\MySQL::getConnection($link));
}
function mysql_insert_id($link = null) /*|*/
{
return mysqli_insert_id(\Dshafik\MySQL::getConnection($link));
}
function mysql_result($result, $row, $field = 0)
{
if (!\Dshafik\MySQL::checkValidResult($result, __FUNCTION__)) {
// @codeCoverageIgnoreStart
return false;
// @codeCoverageIgnoreEnd
}
if (!mysqli_data_seek($result, $row)) {
trigger_error(
sprintf(
'mysql_result(): Unable to jump to row %d on MySQL result index %s',
$row,
spl_object_hash($result)
),
E_USER_WARNING
);
// @codeCoverageIgnoreStart
return false;
// @codeCoverageIgnoreEnd
}
$found = true;
if (strpos($field, '.') !== false) {
list($table, $name) = explode('.', $field);
$i = 0;
$found = false;
mysqli_field_seek($result, 0);
while ($column = mysqli_fetch_field($result)) {
if ($column->table === $table && $column->name === $name) {
$field = $i;
$found = true;
break;
}
$i++;
}
}
$row = mysql_fetch_array($result);
if ($found && array_key_exists($field, $row)) {
return $row[$field];
}
trigger_error(
sprintf(
'%s(): %s not found in MySQL result index %s',
__FUNCTION__,
$field,
spl_object_hash($result)
),
E_USER_WARNING
);
// @codeCoverageIgnoreStart
return false;
// @codeCoverageIgnoreEnd
}
function mysql_num_rows($result)
{
if (!\Dshafik\MySQL::checkValidResult($result, __FUNCTION__)) {
// @codeCoverageIgnoreStart
return false;
// @codeCoverageIgnoreEnd
}
$previous = error_reporting(0);
$rows = mysqli_num_rows($result);
error_reporting($previous);
return $rows;
}
function mysql_num_fields($result)
{
if (!\Dshafik\MySQL::checkValidResult($result, __FUNCTION__)) {
// @codeCoverageIgnoreStart
return false;
// @codeCoverageIgnoreEnd
}
return mysqli_num_fields($result);
}
function mysql_fetch_row($result)
{
if (!\Dshafik\MySQL::checkValidResult($result, __FUNCTION__)) {
// @codeCoverageIgnoreStart
return false;
// @codeCoverageIgnoreEnd
}
return mysqli_fetch_row($result) ?: false;
}
function mysql_fetch_array($result, $resultType = MYSQL_BOTH)
{
if (!\Dshafik\MySQL::checkValidResult($result, __FUNCTION__)) {
// @codeCoverageIgnoreStart
return false;
// @codeCoverageIgnoreEnd
}
return mysqli_fetch_array($result, $resultType) ?: false;
}
function mysql_fetch_assoc($result) /* : array|null */
{
if (!\Dshafik\MySQL::checkValidResult($result, __FUNCTION__)) {
// @codeCoverageIgnoreStart
return false;
// @codeCoverageIgnoreEnd
}
return mysqli_fetch_assoc($result) ?: false;
}
function mysql_fetch_object($result, $class = null, array $params = array()) /* : object|null */
{
if (!\Dshafik\MySQL::checkValidResult($result, __FUNCTION__)) {
// @codeCoverageIgnoreStart
return false;
// @codeCoverageIgnoreEnd
}
if ($class === null) {
$object = mysqli_fetch_object($result);
} else {
$object = mysqli_fetch_object($result, $class, $params);
}
return $object ?: false;
}
function mysql_data_seek($result, $offset)
{
if (!\Dshafik\MySQL::checkValidResult($result, __FUNCTION__)) {
// @codeCoverageIgnoreStart
return false;
// @codeCoverageIgnoreEnd
}
return mysqli_data_seek($result, $offset);
}
function mysql_fetch_lengths($result) /* : array|*/
{
if (!\Dshafik\MySQL::checkValidResult($result, __FUNCTION__)) {
// @codeCoverageIgnoreStart
return false;
// @codeCoverageIgnoreEnd
}
return mysqli_fetch_lengths($result);
}
function mysql_fetch_field($result) /* : object|*/
{
if (!\Dshafik\MySQL::checkValidResult($result, __FUNCTION__)) {
// @codeCoverageIgnoreStart
return false;
// @codeCoverageIgnoreEnd
}
return mysqli_fetch_field($result);
}
function mysql_field_seek($result, $field)
{
if (!\Dshafik\MySQL::checkValidResult($result, __FUNCTION__)) {
// @codeCoverageIgnoreStart
return false;
// @codeCoverageIgnoreEnd
}
return mysqli_field_seek($result, $field);
}
function mysql_free_result($result)
{
if (!\Dshafik\MySQL::checkValidResult($result, __FUNCTION__)) {
// @codeCoverageIgnoreStart
return false;
// @codeCoverageIgnoreEnd
}
return mysqli_free_result($result);
}
function mysql_field_name($result, $field)
{
if (!\Dshafik\MySQL::checkValidResult($result, __FUNCTION__)) {
// @codeCoverageIgnoreStart
return false;
// @codeCoverageIgnoreEnd
}
return \Dshafik\MySQL::mysqlFieldInfo($result, $field, 'name');
}
function mysql_field_table($result, $field)
{
if (!\Dshafik\MySQL::checkValidResult($result, __FUNCTION__)) {
// @codeCoverageIgnoreStart
return false;
// @codeCoverageIgnoreEnd
}
return \Dshafik\MySQL::mysqlFieldInfo($result, $field, 'table');
}
function mysql_field_len($result, $field)
{
if (!\Dshafik\MySQL::checkValidResult($result, __FUNCTION__)) {
// @codeCoverageIgnoreStart
return false;
// @codeCoverageIgnoreEnd
}
return \Dshafik\MySQL::mysqlFieldInfo($result, $field, 'length');
}
function mysql_field_type($result, $field)
{
if (!\Dshafik\MySQL::checkValidResult($result, __FUNCTION__)) {
// @codeCoverageIgnoreStart
return false;
// @codeCoverageIgnoreEnd
}
return \Dshafik\MySQL::mysqlFieldInfo($result, $field, 'type');
}
function mysql_field_flags($result, $field)
{
if (!\Dshafik\MySQL::checkValidResult($result, __FUNCTION__)) {
// @codeCoverageIgnoreStart
return false;
// @codeCoverageIgnoreEnd
}
return \Dshafik\MySQL::mysqlFieldInfo($result, $field, 'flags');
}
function mysql_escape_string($unescapedString)
{
if (\Dshafik\MySQL::$last_connection === null) {
trigger_error(
sprintf(
'%s() is insecure; use mysql_real_escape_string() instead!',
__FUNCTION__
),
E_USER_NOTICE
);
return \Dshafik\MySQL::escapeString($unescapedString);
}
return mysql_real_escape_string($unescapedString, null);
}
function mysql_real_escape_string($unescapedString, \mysqli $link = null)
{
return mysqli_escape_string(\Dshafik\MySQL::getConnection($link), $unescapedString);
}
function mysql_stat(\mysqli $link = null)
{
return mysqli_stat(\Dshafik\MySQL::getConnection($link));
}
function mysql_thread_id(\mysqli $link = null)
{
return mysqli_thread_id(\Dshafik\MySQL::getConnection($link));
}
function mysql_client_encoding(\mysqli $link = null)
{
return mysqli_character_set_name(\Dshafik\MySQL::getConnection($link));
}
function mysql_ping(\mysqli $link = null)
{
return mysqli_ping(\Dshafik\MySQL::getConnection($link));
}
function mysql_get_client_info(\mysqli $link = null)
{
return mysqli_get_client_info(\Dshafik\MySQL::getConnection($link));
}
function mysql_get_host_info(\mysqli $link = null)
{
return mysqli_get_host_info(\Dshafik\MySQL::getConnection($link));
}
function mysql_get_proto_info(\mysqli $link = null)
{
return mysqli_get_proto_info(\Dshafik\MySQL::getConnection($link));
}
function mysql_get_server_info(\mysqli $link = null)
{
return mysqli_get_server_info(\Dshafik\MySQL::getConnection($link));
}
function mysql_info(\mysqli $link = null)
{
return mysqli_info(\Dshafik\MySQL::getConnection($link));
}
function mysql_set_charset($charset, \mysqli $link = null)
{
return mysqli_set_charset(\Dshafik\MySQL::getConnection($link), $charset);
}
function mysql_db_name($result, $row, $field = 0)
{
if (!\Dshafik\MySQL::checkValidResult($result, __FUNCTION__)) {
// @codeCoverageIgnoreStart
return false;
// @codeCoverageIgnoreEnd
}
// Alias as per https://github.com/php/php-src/blob/PHP-5.6/ext/mysql/php_mysql.c#L319
return mysql_result($result, $row, $field);
}
function mysql_tablename($result, $row)
{
if (!\Dshafik\MySQL::checkValidResult($result, __FUNCTION__)) {
// @codeCoverageIgnoreStart
return false;
// @codeCoverageIgnoreEnd
}
// Alias as per http://lxr.php.net/xref/PHP_5_6/ext/mysql/php_mysql.c#321
return mysql_result($result, $row, 'Table');
}
/* Aliases */
function mysql_fieldname($result, $field)
{
return mysql_field_name($result, $field);
}
function mysql_fieldtable($result, $field)
{
return mysql_field_table($result, $field);
}
function mysql_fieldlen($result, $field)
{
return mysql_field_len($result, $field);
}
function mysql_fieldtype($result, $field)
{
return mysql_field_type($result, $field);
}
function mysql_fieldflags($result, $field)
{
return mysql_field_flags($result, $field);
}
function mysql_selectdb($databaseName, $link = null)
{
return mysql_select_db($databaseName, $link);
}
function mysql_freeresult($result)
{
return mysql_free_result($result);
}
function mysql_numfields($result)
{
return mysql_num_fields($result);
}
function mysql_numrows($result)
{
return mysql_num_rows($result);
}
function mysql_listdbs($link)
{
return mysql_list_dbs($link);
}
function mysql_listtables($databaseName, $link = null)
{
return mysql_list_tables($databaseName, $link);
}
function mysql_listfields($databaseName, $tableName, $link = null)
{
return mysql_list_fields($databaseName, $tableName, $link);
}
function mysql_dbname($result, $row, $field = 0)
{
return mysql_db_name($result, $row, $field);
}
function mysql_table_name($result, $row)
{
return mysql_tablename($result, $row);
}
}
}
namespace Dshafik {
class MySQL
{
public static $last_connection = null;
public static $connections = array();
public static function getConnection($link = null, $func = null)
{
if ($link !== null) {
return $link;
}
if (static::$last_connection === null) {
$err = 'A link to the server could not be established';
if ($func !== null) {
$err = $func . '(): no MySQL-Link resource supplied';
}
trigger_error($err, E_USER_WARNING);
return false;
}
return static::$last_connection;
}
public static function mysqlFieldInfo(\mysqli_result $result, $field, $what)
{
try {
$field = mysqli_fetch_field_direct($result, $field);
} catch (\Exception $e) {
trigger_error(
sprintf(
'mysql_field_%s(): Field %d is invalid for MySQL result index %s',
($what !== 'length') ? $what : 'len',
$field,
spl_object_hash($result)
),
E_USER_WARNING
);
// @codeCoverageIgnoreStart
// PHPUnit turns the warning into an exception, so this never runs
return false;
// @codeCoverageIgnoreEnd
}
if ($what === 'type') {
return static::getFieldType($field->type);
}
if ($what === 'flags') {
return static::getFieldFlags($field->flags);
}
if (isset($field->{$what})) {
return $field->{$what};
}
return false;
}
public static function checkValidResult($result, $function)
{
if (!($result instanceof \mysqli_result)) {
if ($function !== 'mysql_fetch_object') {
trigger_error(
$function . '() expects parameter 1 to be resource, ' . strtolower(gettype($result)) . ' given',
E_USER_WARNING
);
}
if ($function === 'mysql_fetch_object') {
trigger_error(
$function . '(): supplied argument is not a valid MySQL result resource',
E_USER_WARNING
);
}
return false;
}
return true;
}
public static function escapeString($unescapedString)
{
$escapedString = '';
for ($i = 0, $max = strlen($unescapedString); $i < $max; $i++) {
// $escapedString .= self::escapeChar($unescapedString{$i});
$escapedString .= self::escapeChar($unescapedString[$i]);
}
return $escapedString;
}
protected static function getFieldFlags($what)
{
// Order of flags taken from http://lxr.php.net/xref/PHP_5_6/ext/mysql/php_mysql.c#2507
$flags = array(
MYSQLI_NOT_NULL_FLAG => 'not_null',
MYSQLI_PRI_KEY_FLAG => 'primary_key',
MYSQLI_UNIQUE_KEY_FLAG => 'unique_key',
MYSQLI_MULTIPLE_KEY_FLAG => 'multiple_key',
MYSQLI_BLOB_FLAG => 'blob',
MYSQLI_UNSIGNED_FLAG => 'unsigned',
MYSQLI_ZEROFILL_FLAG => 'zerofill',
MYSQLI_BINARY_FLAG => 'binary',
MYSQLI_ENUM_FLAG => 'enum',
MYSQLI_SET_FLAG => 'set',
MYSQLI_AUTO_INCREMENT_FLAG => 'auto_increment',
MYSQLI_TIMESTAMP_FLAG => 'timestamp',
);
$fieldFlags = array();
foreach ($flags as $flag => $value) {
if ($what & $flag) {
$fieldFlags[] = $value;
}
}
return implode(' ', $fieldFlags);
}
protected static function getFieldType($what)
{
$types = array(
MYSQLI_TYPE_STRING => 'string',
MYSQLI_TYPE_VAR_STRING => 'string',
MYSQLI_TYPE_ENUM => 'string',
MYSQLI_TYPE_SET => 'string',
MYSQLI_TYPE_LONG => 'int',
MYSQLI_TYPE_TINY => 'int',
MYSQLI_TYPE_SHORT => 'int',
MYSQLI_TYPE_INT24 => 'int',
MYSQLI_TYPE_CHAR => 'int',
MYSQLI_TYPE_LONGLONG => 'int',
MYSQLI_TYPE_DECIMAL => 'real',
MYSQLI_TYPE_FLOAT => 'real',
MYSQLI_TYPE_DOUBLE => 'real',
MYSQLI_TYPE_NEWDECIMAL => 'real',
MYSQLI_TYPE_TINY_BLOB => 'blob',
MYSQLI_TYPE_MEDIUM_BLOB => 'blob',
MYSQLI_TYPE_LONG_BLOB => 'blob',
MYSQLI_TYPE_BLOB => 'blob',
MYSQLI_TYPE_NEWDATE => 'date',
MYSQLI_TYPE_DATE => 'date',
MYSQLI_TYPE_TIME => 'time',
MYSQLI_TYPE_YEAR => 'year',
MYSQLI_TYPE_DATETIME => 'datetime',
MYSQLI_TYPE_TIMESTAMP => 'timestamp',
MYSQLI_TYPE_NULL => 'null',
MYSQLI_TYPE_GEOMETRY => 'geometry',
);
return isset($types[$what]) ? $types[$what] : 'unknown';
}
protected static function escapeChar($char)
{
switch ($char) {
case "\0":
$esc = "\\0";
break;
case "\n":
$esc = "\\n";
break;
case "\r":
$esc = "\\r";
break;
case '\\':
case '\'':
case '"':
$esc = "\\{$char}";
break;
case "\032":
$esc = "\\Z";
break;
default:
$esc = $char;
break;
}
return $esc;
}
}
}

29
cms/lib/robots.php Executable file
View File

@@ -0,0 +1,29 @@
<?php
require_once __DIR__."/../sesion.php";
require_once __DIR__."/../funciones.php";
if (!function_exists("protocol")) {
function protocol() {
return _isHTTPS() ? "https" : "http";
}
function _isHTTPS() {
return (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') || $_SERVER['SERVER_PORT'] == 443;
}
}
header('Content-Type: text/plain');
$filePath = __DIR__."/../robots.txt";
if (file_exists($filePath)) {
echo file_get_contents($filePath);
die();
}
?>
# <?=strtoupper($configuracionRecord["tienda_nombre_empresa"]);?>
User-agent: *
<? if (strpos($_SERVER["HTTP_HOST"], "plandeweb.com")) {?>
Disallow: /
<? }?>
<? if (@$configuracionRecord['pagina_publicada']) {?>
# SITEMAP
Sitemap: <?=protocol();?>://<?=$_SERVER["HTTP_HOST"];?>/sitemap.xml
<? }?>

133
cms/lib/sitemap.php Executable file
View File

@@ -0,0 +1,133 @@
<?
require_once dirname(__FILE__)."/../sesion.php";
require_once dirname(__FILE__)."/../funciones.php";
if (!@$configuracionRecord['pagina_publicada'] && !@$_REQUEST['dev']) {
http_response_code(404);
die();
}
$dummy = [];
addPlugins('sitemap', $dummy);
$tablasEliminadas = array("cms_alias_urls");
$sql = "
SELECT DISTINCT TABLE_NAME,COLUMN_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE COLUMN_NAME IN ('enlace')
AND TABLE_SCHEMA='".$SETTINGS["mysql"]["database"]."'
";
$result = mysql_query($sql) or die(mysql_error());
$resultados = array();
$enlaces = array();
$idiomas = array();
while($record = mysql_fetch_assoc($result)){
if (!in_array($record["TABLE_NAME"],$tablasEliminadas)){
$res = mysql_query("SELECT * FROM ".$record["TABLE_NAME"]);
while($rec = mysql_fetch_assoc($res)){
$enlaceAnadido = false;
if (@$rec['no_indexar_en_google']) continue;
if ((isset($rec["visible"]) || isset($rec["oculto"])) && @$rec[$record["COLUMN_NAME"]]) {
if ((@$rec["visible"]==1 || isset($rec["oculto"]) && !$rec["oculto"]) && !strpos("a".$rec[$record["COLUMN_NAME"]],"#")) {
if (compruebaWeb(@$rec[$record["COLUMN_NAME"]])){
$enlaces[$record["TABLE_NAME"]."-".$record["COLUMN_NAME"]."-".$rec["num"]][] = @$rec[$record["COLUMN_NAME"]];
$idiomas[$record["TABLE_NAME"]."-".$record["COLUMN_NAME"]."-".$rec["num"]][] = "es";
$fechas[$record["TABLE_NAME"]."-".$record["COLUMN_NAME"]."-".$rec["num"]][] = @$rec["updatedDate"];
$enlaceAnadido = true;
}
}
}else if (@$rec[$record["COLUMN_NAME"]]){
if (!strpos("a".$rec[$record["COLUMN_NAME"]],"#")){
if (compruebaWeb(@$rec[$record["COLUMN_NAME"]])){
$enlaces[$record["TABLE_NAME"]."-".$record["COLUMN_NAME"]."-".$rec["num"]][] = @$rec[$record["COLUMN_NAME"]];
$idiomas[$record["TABLE_NAME"]."-".$record["COLUMN_NAME"]."-".$rec["num"]][] = "es";
$fechas[$record["TABLE_NAME"]."-".$record["COLUMN_NAME"]."-".$rec["num"]][] = @$rec["updatedDate"];
$enlaceAnadido = true;
}
}
}
if ($enlaceAnadido){
$enlaces = dameEnlacesIdiomas($enlaces,$record,$rec);
}
}
}
}
function compruebaWeb($enlace){
return 1;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, protocol()."://".$_SERVER["HTTP_HOST"].$enlace);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$respond = curl_exec ($ch);
curl_close ($ch);
//$wget = file_get_contents(protocol()."://".$_SERVER["HTTP_HOST"].$enlace);
return $respond;
}
function dameEnlacesIdiomas($enlaces,$schema,$record){
global $TABLE_PREFIX,$idiomas;
$sql = "SELECT prefix,fieldValue FROM ".$TABLE_PREFIX."traducciones where tableName='".str_replace($TABLE_PREFIX,"",$schema["TABLE_NAME"])."' and recordNum='".$record["num"]."' and fieldName='".$schema["COLUMN_NAME"]."'";
$res = mysql_query($sql);
if (@$res){
while($rec = mysql_fetch_assoc($res)){
if (compruebaWeb(base64_decode($rec["fieldValue"]))){
$idiomas[$schema["TABLE_NAME"]."-".$schema["COLUMN_NAME"]."-".$record["num"]][] = $rec["prefix"];
$enlaces[$schema["TABLE_NAME"]."-".$schema["COLUMN_NAME"]."-".$record["num"]][] = base64_decode($rec["fieldValue"]);
}
}
}
return $enlaces;
}
/*
echo "<pre>";
print_r($fechas);
echo "</pre>";
die();*/
header("Content-type: application/xml");
echo '<?xml version="1.0" encoding="UTF-8"?><urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:xhtml="http://www.w3.org/1999/xhtml">';
foreach($enlaces as $key => $valores):
foreach($valores as $cont => $valor):
echo "<url>";
echo "<loc>".protocol()."://".$_SERVER["HTTP_HOST"].$valor."</loc>";
echo '<lastmod>'.date("Y-m-d",strtotime($fechas[$key][0])).'T'.date("H:i:s",strtotime($fechas[$key][0])).'+00:00</lastmod>';
foreach($valores as $cont2 => $valor2):
if ($cont2!=$cont){
echo '<xhtml:link rel="alternate" hreflang="'.$idiomas[$key][$cont2].'" href="'.protocol()."://".$_SERVER["HTTP_HOST"].$valor2.'"/>';
//echo "<link>".$idiomas[$key][$cont2]."</link>";
}
endforeach;
echo '<changefreq>monthly</changefreq>';
echo "</url>";
endforeach;
/*if (@$idiomas[$cont]!="es"){
echo '<xhtml:link rel="alternate" hreflang="de" href="'.$enlace.'"/>';
}else{
echo "<loc>".$enlace."</loc>";
}*/
endforeach;
echo '</urlset>';
die();
?>
<script>
/*var listas = document.querySelectorAll("li");
for (i=0;i<listas.length;i++){
fetch('https://top-car-hire.com' + listas[i].innerHTML).then(function(response) {
response.text().then(function(str){
if (response.status==200){
str = str.toLowerCase();
if (str.indexOf("undefined ")!=-1){
console.log("UNDEFINED EN " + response.url);
}
}else{
console.log("ERROR EN " + response.url);
}
});
}).then(function(str) {
});
}*/
</script>

View File

@@ -0,0 +1,50 @@
<?php
/**
* PHPMailer SPL autoloader.
* PHP Version 5
* @package PHPMailer
* @link https://github.com/PHPMailer/PHPMailer/ The PHPMailer GitHub project
* @author Marcus Bointon (Synchro/coolbru) <phpmailer@synchromedia.co.uk>
* @author Jim Jagielski (jimjag) <jimjag@gmail.com>
* @author Andy Prevost (codeworxtech) <codeworxtech@users.sourceforge.net>
* @author Brent R. Matzelle (original founder)
* @copyright 2012 - 2014 Marcus Bointon
* @copyright 2010 - 2012 Jim Jagielski
* @copyright 2004 - 2009 Andy Prevost
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
* @note This program is distributed in the hope that it will be useful - WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*/
/**
* PHPMailer SPL autoloader.
* @param string $classname The name of the class to load
*/
function PHPMailerAutoload($classname)
{
//Can't use __DIR__ as it's only in PHP 5.3+
$filename = dirname(__FILE__).DIRECTORY_SEPARATOR.'class.'.strtolower($classname).'.php';
if (is_readable($filename)) {
require $filename;
}
}
if (version_compare(PHP_VERSION, '5.1.2', '>=')) {
//SPL autoloading was introduced in PHP 5.1.2
if (version_compare(PHP_VERSION, '5.3.0', '>=')) {
spl_autoload_register('PHPMailerAutoload', true, true);
} else {
spl_autoload_register('PHPMailerAutoload');
}
} else {
/**
* Fall back to traditional autoload for old PHP versions
* @param string $classname The name of the class to load
*/
die('Versión de PHP para mailer.');
// function __autoload($classname)
// {
// PHPMailerAutoload($classname);
// }
}

3542
cms/lib/vendor/PHPMailer/class.phpmailer.php vendored Executable file

File diff suppressed because it is too large Load Diff

397
cms/lib/vendor/PHPMailer/class.pop3.php vendored Executable file
View File

@@ -0,0 +1,397 @@
<?php
/**
* PHPMailer POP-Before-SMTP Authentication Class.
* PHP Version 5
* @package PHPMailer
* @link https://github.com/PHPMailer/PHPMailer/
* @author Marcus Bointon (Synchro/coolbru) <phpmailer@synchromedia.co.uk>
* @author Jim Jagielski (jimjag) <jimjag@gmail.com>
* @author Andy Prevost (codeworxtech) <codeworxtech@users.sourceforge.net>
* @author Brent R. Matzelle (original founder)
* @copyright 2012 - 2014 Marcus Bointon
* @copyright 2010 - 2012 Jim Jagielski
* @copyright 2004 - 2009 Andy Prevost
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
* @note This program is distributed in the hope that it will be useful - WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*/
/**
* PHPMailer POP-Before-SMTP Authentication Class.
* Specifically for PHPMailer to use for RFC1939 POP-before-SMTP authentication.
* Does not support APOP.
* @package PHPMailer
* @author Richard Davey (original author) <rich@corephp.co.uk>
* @author Marcus Bointon (Synchro/coolbru) <phpmailer@synchromedia.co.uk>
* @author Jim Jagielski (jimjag) <jimjag@gmail.com>
* @author Andy Prevost (codeworxtech) <codeworxtech@users.sourceforge.net>
*/
class POP3
{
/**
* The POP3 PHPMailer Version number.
* @type string
* @access public
*/
public $Version = '5.2.9';
/**
* Default POP3 port number.
* @type integer
* @access public
*/
public $POP3_PORT = 110;
/**
* Default timeout in seconds.
* @type integer
* @access public
*/
public $POP3_TIMEOUT = 30;
/**
* POP3 Carriage Return + Line Feed.
* @type string
* @access public
* @deprecated Use the constant instead
*/
public $CRLF = "\r\n";
/**
* Debug display level.
* Options: 0 = no, 1+ = yes
* @type integer
* @access public
*/
public $do_debug = 0;
/**
* POP3 mail server hostname.
* @type string
* @access public
*/
public $host;
/**
* POP3 port number.
* @type integer
* @access public
*/
public $port;
/**
* POP3 Timeout Value in seconds.
* @type integer
* @access public
*/
public $tval;
/**
* POP3 username
* @type string
* @access public
*/
public $username;
/**
* POP3 password.
* @type string
* @access public
*/
public $password;
/**
* Resource handle for the POP3 connection socket.
* @type resource
* @access private
*/
private $pop_conn;
/**
* Are we connected?
* @type boolean
* @access private
*/
private $connected = false;
/**
* Error container.
* @type array
* @access private
*/
private $errors = array();
/**
* Line break constant
*/
const CRLF = "\r\n";
/**
* Simple static wrapper for all-in-one POP before SMTP
* @param $host
* @param boolean $port
* @param boolean $tval
* @param string $username
* @param string $password
* @param integer $debug_level
* @return boolean
*/
public static function popBeforeSmtp(
$host,
$port = false,
$tval = false,
$username = '',
$password = '',
$debug_level = 0
) {
$pop = new POP3;
return $pop->authorise($host, $port, $tval, $username, $password, $debug_level);
}
/**
* Authenticate with a POP3 server.
* A connect, login, disconnect sequence
* appropriate for POP-before SMTP authorisation.
* @access public
* @param string $host The hostname to connect to
* @param integer|boolean $port The port number to connect to
* @param integer|boolean $timeout The timeout value
* @param string $username
* @param string $password
* @param integer $debug_level
* @return boolean
*/
public function authorise($host, $port = false, $timeout = false, $username = '', $password = '', $debug_level = 0)
{
$this->host = $host;
// If no port value provided, use default
if (false === $port) {
$this->port = $this->POP3_PORT;
} else {
$this->port = (integer)$port;
}
// If no timeout value provided, use default
if (false === $timeout) {
$this->tval = $this->POP3_TIMEOUT;
} else {
$this->tval = (integer)$timeout;
}
$this->do_debug = $debug_level;
$this->username = $username;
$this->password = $password;
// Reset the error log
$this->errors = array();
// connect
$result = $this->connect($this->host, $this->port, $this->tval);
if ($result) {
$login_result = $this->login($this->username, $this->password);
if ($login_result) {
$this->disconnect();
return true;
}
}
// We need to disconnect regardless of whether the login succeeded
$this->disconnect();
return false;
}
/**
* Connect to a POP3 server.
* @access public
* @param string $host
* @param integer|boolean $port
* @param integer $tval
* @return boolean
*/
public function connect($host, $port = false, $tval = 30)
{
// Are we already connected?
if ($this->connected) {
return true;
}
//On Windows this will raise a PHP Warning error if the hostname doesn't exist.
//Rather than suppress it with @fsockopen, capture it cleanly instead
set_error_handler(array($this, 'catchWarning'));
if (false === $port) {
$port = $this->POP3_PORT;
}
// connect to the POP3 server
$this->pop_conn = fsockopen(
$host, // POP3 Host
$port, // Port #
$errno, // Error Number
$errstr, // Error Message
$tval
); // Timeout (seconds)
// Restore the error handler
restore_error_handler();
// Did we connect?
if (false === $this->pop_conn) {
// It would appear not...
$this->setError(array(
'error' => "Failed to connect to server $host on port $port",
'errno' => $errno,
'errstr' => $errstr
));
return false;
}
// Increase the stream time-out
stream_set_timeout($this->pop_conn, $tval, 0);
// Get the POP3 server response
$pop3_response = $this->getResponse();
// Check for the +OK
if ($this->checkResponse($pop3_response)) {
// The connection is established and the POP3 server is talking
$this->connected = true;
return true;
}
return false;
}
/**
* Log in to the POP3 server.
* Does not support APOP (RFC 2828, 4949).
* @access public
* @param string $username
* @param string $password
* @return boolean
*/
public function login($username = '', $password = '')
{
if (!$this->connected) {
$this->setError('Not connected to POP3 server');
}
if (empty($username)) {
$username = $this->username;
}
if (empty($password)) {
$password = $this->password;
}
// Send the Username
$this->sendString("USER $username" . self::CRLF);
$pop3_response = $this->getResponse();
if ($this->checkResponse($pop3_response)) {
// Send the Password
$this->sendString("PASS $password" . self::CRLF);
$pop3_response = $this->getResponse();
if ($this->checkResponse($pop3_response)) {
return true;
}
}
return false;
}
/**
* Disconnect from the POP3 server.
* @access public
*/
public function disconnect()
{
$this->sendString('QUIT');
//The QUIT command may cause the daemon to exit, which will kill our connection
//So ignore errors here
try {
@fclose($this->pop_conn);
} catch (Exception $e) {
//Do nothing
};
}
/**
* Get a response from the POP3 server.
* $size is the maximum number of bytes to retrieve
* @param integer $size
* @return string
* @access private
*/
private function getResponse($size = 128)
{
$response = fgets($this->pop_conn, $size);
if ($this->do_debug >= 1) {
echo "Server -> Client: $response";
}
return $response;
}
/**
* Send raw data to the POP3 server.
* @param string $string
* @return integer
* @access private
*/
private function sendString($string)
{
if ($this->pop_conn) {
if ($this->do_debug >= 2) { //Show client messages when debug >= 2
echo "Client -> Server: $string";
}
return fwrite($this->pop_conn, $string, strlen($string));
}
return 0;
}
/**
* Checks the POP3 server response.
* Looks for for +OK or -ERR.
* @param string $string
* @return boolean
* @access private
*/
private function checkResponse($string)
{
if (substr($string, 0, 3) !== '+OK') {
$this->setError(array(
'error' => "Server reported an error: $string",
'errno' => 0,
'errstr' => ''
));
return false;
} else {
return true;
}
}
/**
* Add an error to the internal error store.
* Also display debug output if it's enabled.
* @param $error
*/
private function setError($error)
{
$this->errors[] = $error;
if ($this->do_debug >= 1) {
echo '<pre>';
foreach ($this->errors as $error) {
print_r($error);
}
echo '</pre>';
}
}
/**
* POP3 connection error handler.
* @param integer $errno
* @param string $errstr
* @param string $errfile
* @param integer $errline
* @access private
*/
private function catchWarning($errno, $errstr, $errfile, $errline)
{
$this->setError(array(
'error' => "Connecting to the POP3 server raised a PHP warning: ",
'errno' => $errno,
'errstr' => $errstr,
'errfile' => $errfile,
'errline' => $errline
));
}
}

1152
cms/lib/vendor/PHPMailer/class.smtp.php vendored Executable file

File diff suppressed because it is too large Load Diff

7
cms/lib/vendor/minifier/autoload.php vendored Executable file
View File

@@ -0,0 +1,7 @@
<?php
// autoload.php @generated by Composer
require_once __DIR__ . '/composer/autoload_real.php';
return ComposerAutoloaderInit223dcbee3a648ecec7c16ee350170eb0::getLoader();

45
cms/lib/vendor/minifier/bin/minifycss vendored Executable file
View File

@@ -0,0 +1,45 @@
#!/usr/bin/env php
<?php
use MatthiasMullie\Minify;
// command line utility to minify CSS
if (file_exists(__DIR__ . '/../../../autoload.php')) {
// if composer install
require_once __DIR__ . '/../../../autoload.php';
} else {
require_once __DIR__ . '/../src/Minify.php';
require_once __DIR__ . '/../src/CSS.php';
require_once __DIR__ . '/../src/Exception.php';
}
error_reporting(E_ALL);
// check PHP setup for cli arguments
if (!isset($_SERVER['argv']) && !isset($argv)) {
fwrite(STDERR, 'Please enable the "register_argc_argv" directive in your php.ini' . PHP_EOL);
exit(1);
} elseif (!isset($argv)) {
$argv = $_SERVER['argv'];
}
// check if path to file given
if (!isset($argv[1])) {
fwrite(STDERR, 'Argument expected: path to file' . PHP_EOL);
exit(1);
}
// check if script run in cli environment
if ('cli' !== php_sapi_name()) {
fwrite(STDERR, $argv[1] . ' must be run in the command line' . PHP_EOL);
exit(1);
}
// check if source file exists
if (!file_exists($argv[1])) {
fwrite(STDERR, 'Source file "' . $argv[1] . '" not found' . PHP_EOL);
exit(1);
}
try {
$minifier = new Minify\CSS($argv[1]);
echo $minifier->minify();
} catch (Exception $e) {
fwrite(STDERR, $e->getMessage(), PHP_EOL);
exit(1);
}

45
cms/lib/vendor/minifier/bin/minifyjs vendored Executable file
View File

@@ -0,0 +1,45 @@
#!/usr/bin/env php
<?php
use MatthiasMullie\Minify;
// command line utility to minify JS
if (file_exists(__DIR__ . '/../../../autoload.php')) {
// if composer install
require_once __DIR__ . '/../../../autoload.php';
} else {
require_once __DIR__ . '/../src/Minify.php';
require_once __DIR__ . '/../src/JS.php';
require_once __DIR__ . '/../src/Exception.php';
}
error_reporting(E_ALL);
// check PHP setup for cli arguments
if (!isset($_SERVER['argv']) && !isset($argv)) {
fwrite(STDERR, 'Please enable the "register_argc_argv" directive in your php.ini' . PHP_EOL);
exit(1);
} elseif (!isset($argv)) {
$argv = $_SERVER['argv'];
}
// check if path to file given
if (!isset($argv[1])) {
fwrite(STDERR, 'Argument expected: path to file' . PHP_EOL);
exit(1);
}
// check if script run in cli environment
if ('cli' !== php_sapi_name()) {
fwrite(STDERR, $argv[1] . ' must be run in the command line' . PHP_EOL);
exit(1);
}
// check if source file exists
if (!file_exists($argv[1])) {
fwrite(STDERR, 'Source file "' . $argv[1] . '" not found' . PHP_EOL);
exit(1);
}
try {
$minifier = new Minify\JS($argv[1]);
echo $minifier->minify();
} catch (Exception $e) {
fwrite(STDERR, $e->getMessage(), PHP_EOL);
exit(1);
}

View File

@@ -0,0 +1,445 @@
<?php
/*
* This file is part of Composer.
*
* (c) Nils Adermann <naderman@naderman.de>
* Jordi Boggiano <j.boggiano@seld.be>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Composer\Autoload;
/**
* ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
*
* $loader = new \Composer\Autoload\ClassLoader();
*
* // register classes with namespaces
* $loader->add('Symfony\Component', __DIR__.'/component');
* $loader->add('Symfony', __DIR__.'/framework');
*
* // activate the autoloader
* $loader->register();
*
* // to enable searching the include path (eg. for PEAR packages)
* $loader->setUseIncludePath(true);
*
* In this example, if you try to use a class in the Symfony\Component
* namespace or one of its children (Symfony\Component\Console for instance),
* the autoloader will first look for the class under the component/
* directory, and it will then fallback to the framework/ directory if not
* found before giving up.
*
* This class is loosely based on the Symfony UniversalClassLoader.
*
* @author Fabien Potencier <fabien@symfony.com>
* @author Jordi Boggiano <j.boggiano@seld.be>
* @see http://www.php-fig.org/psr/psr-0/
* @see http://www.php-fig.org/psr/psr-4/
*/
class ClassLoader
{
// PSR-4
private $prefixLengthsPsr4 = array();
private $prefixDirsPsr4 = array();
private $fallbackDirsPsr4 = array();
// PSR-0
private $prefixesPsr0 = array();
private $fallbackDirsPsr0 = array();
private $useIncludePath = false;
private $classMap = array();
private $classMapAuthoritative = false;
private $missingClasses = array();
private $apcuPrefix;
public function getPrefixes()
{
if (!empty($this->prefixesPsr0)) {
return call_user_func_array('array_merge', $this->prefixesPsr0);
}
return array();
}
public function getPrefixesPsr4()
{
return $this->prefixDirsPsr4;
}
public function getFallbackDirs()
{
return $this->fallbackDirsPsr0;
}
public function getFallbackDirsPsr4()
{
return $this->fallbackDirsPsr4;
}
public function getClassMap()
{
return $this->classMap;
}
/**
* @param array $classMap Class to filename map
*/
public function addClassMap(array $classMap)
{
if ($this->classMap) {
$this->classMap = array_merge($this->classMap, $classMap);
} else {
$this->classMap = $classMap;
}
}
/**
* Registers a set of PSR-0 directories for a given prefix, either
* appending or prepending to the ones previously set for this prefix.
*
* @param string $prefix The prefix
* @param array|string $paths The PSR-0 root directories
* @param bool $prepend Whether to prepend the directories
*/
public function add($prefix, $paths, $prepend = false)
{
if (!$prefix) {
if ($prepend) {
$this->fallbackDirsPsr0 = array_merge(
(array) $paths,
$this->fallbackDirsPsr0
);
} else {
$this->fallbackDirsPsr0 = array_merge(
$this->fallbackDirsPsr0,
(array) $paths
);
}
return;
}
$first = $prefix[0];
if (!isset($this->prefixesPsr0[$first][$prefix])) {
$this->prefixesPsr0[$first][$prefix] = (array) $paths;
return;
}
if ($prepend) {
$this->prefixesPsr0[$first][$prefix] = array_merge(
(array) $paths,
$this->prefixesPsr0[$first][$prefix]
);
} else {
$this->prefixesPsr0[$first][$prefix] = array_merge(
$this->prefixesPsr0[$first][$prefix],
(array) $paths
);
}
}
/**
* Registers a set of PSR-4 directories for a given namespace, either
* appending or prepending to the ones previously set for this namespace.
*
* @param string $prefix The prefix/namespace, with trailing '\\'
* @param array|string $paths The PSR-4 base directories
* @param bool $prepend Whether to prepend the directories
*
* @throws \InvalidArgumentException
*/
public function addPsr4($prefix, $paths, $prepend = false)
{
if (!$prefix) {
// Register directories for the root namespace.
if ($prepend) {
$this->fallbackDirsPsr4 = array_merge(
(array) $paths,
$this->fallbackDirsPsr4
);
} else {
$this->fallbackDirsPsr4 = array_merge(
$this->fallbackDirsPsr4,
(array) $paths
);
}
} elseif (!isset($this->prefixDirsPsr4[$prefix])) {
// Register directories for a new namespace.
$length = strlen($prefix);
if ('\\' !== $prefix[$length - 1]) {
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
}
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
$this->prefixDirsPsr4[$prefix] = (array) $paths;
} elseif ($prepend) {
// Prepend directories for an already registered namespace.
$this->prefixDirsPsr4[$prefix] = array_merge(
(array) $paths,
$this->prefixDirsPsr4[$prefix]
);
} else {
// Append directories for an already registered namespace.
$this->prefixDirsPsr4[$prefix] = array_merge(
$this->prefixDirsPsr4[$prefix],
(array) $paths
);
}
}
/**
* Registers a set of PSR-0 directories for a given prefix,
* replacing any others previously set for this prefix.
*
* @param string $prefix The prefix
* @param array|string $paths The PSR-0 base directories
*/
public function set($prefix, $paths)
{
if (!$prefix) {
$this->fallbackDirsPsr0 = (array) $paths;
} else {
$this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
}
}
/**
* Registers a set of PSR-4 directories for a given namespace,
* replacing any others previously set for this namespace.
*
* @param string $prefix The prefix/namespace, with trailing '\\'
* @param array|string $paths The PSR-4 base directories
*
* @throws \InvalidArgumentException
*/
public function setPsr4($prefix, $paths)
{
if (!$prefix) {
$this->fallbackDirsPsr4 = (array) $paths;
} else {
$length = strlen($prefix);
if ('\\' !== $prefix[$length - 1]) {
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
}
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
$this->prefixDirsPsr4[$prefix] = (array) $paths;
}
}
/**
* Turns on searching the include path for class files.
*
* @param bool $useIncludePath
*/
public function setUseIncludePath($useIncludePath)
{
$this->useIncludePath = $useIncludePath;
}
/**
* Can be used to check if the autoloader uses the include path to check
* for classes.
*
* @return bool
*/
public function getUseIncludePath()
{
return $this->useIncludePath;
}
/**
* Turns off searching the prefix and fallback directories for classes
* that have not been registered with the class map.
*
* @param bool $classMapAuthoritative
*/
public function setClassMapAuthoritative($classMapAuthoritative)
{
$this->classMapAuthoritative = $classMapAuthoritative;
}
/**
* Should class lookup fail if not found in the current class map?
*
* @return bool
*/
public function isClassMapAuthoritative()
{
return $this->classMapAuthoritative;
}
/**
* APCu prefix to use to cache found/not-found classes, if the extension is enabled.
*
* @param string|null $apcuPrefix
*/
public function setApcuPrefix($apcuPrefix)
{
$this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null;
}
/**
* The APCu prefix in use, or null if APCu caching is not enabled.
*
* @return string|null
*/
public function getApcuPrefix()
{
return $this->apcuPrefix;
}
/**
* Registers this instance as an autoloader.
*
* @param bool $prepend Whether to prepend the autoloader or not
*/
public function register($prepend = false)
{
spl_autoload_register(array($this, 'loadClass'), true, $prepend);
}
/**
* Unregisters this instance as an autoloader.
*/
public function unregister()
{
spl_autoload_unregister(array($this, 'loadClass'));
}
/**
* Loads the given class or interface.
*
* @param string $class The name of the class
* @return bool|null True if loaded, null otherwise
*/
public function loadClass($class)
{
if ($file = $this->findFile($class)) {
includeFile($file);
return true;
}
}
/**
* Finds the path to the file where the class is defined.
*
* @param string $class The name of the class
*
* @return string|false The path if found, false otherwise
*/
public function findFile($class)
{
// class map lookup
if (isset($this->classMap[$class])) {
return $this->classMap[$class];
}
if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
return false;
}
if (null !== $this->apcuPrefix) {
$file = apcu_fetch($this->apcuPrefix.$class, $hit);
if ($hit) {
return $file;
}
}
$file = $this->findFileWithExtension($class, '.php');
// Search for Hack files if we are running on HHVM
if (false === $file && defined('HHVM_VERSION')) {
$file = $this->findFileWithExtension($class, '.hh');
}
if (null !== $this->apcuPrefix) {
apcu_add($this->apcuPrefix.$class, $file);
}
if (false === $file) {
// Remember that this class does not exist.
$this->missingClasses[$class] = true;
}
return $file;
}
private function findFileWithExtension($class, $ext)
{
// PSR-4 lookup
$logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
$first = $class[0];
if (isset($this->prefixLengthsPsr4[$first])) {
$subPath = $class;
while (false !== $lastPos = strrpos($subPath, '\\')) {
$subPath = substr($subPath, 0, $lastPos);
$search = $subPath . '\\';
if (isset($this->prefixDirsPsr4[$search])) {
$pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
foreach ($this->prefixDirsPsr4[$search] as $dir) {
if (file_exists($file = $dir . $pathEnd)) {
return $file;
}
}
}
}
}
// PSR-4 fallback dirs
foreach ($this->fallbackDirsPsr4 as $dir) {
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
return $file;
}
}
// PSR-0 lookup
if (false !== $pos = strrpos($class, '\\')) {
// namespaced class name
$logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
. strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
} else {
// PEAR-like class name
$logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
}
if (isset($this->prefixesPsr0[$first])) {
foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
if (0 === strpos($class, $prefix)) {
foreach ($dirs as $dir) {
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
return $file;
}
}
}
}
}
// PSR-0 fallback dirs
foreach ($this->fallbackDirsPsr0 as $dir) {
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
return $file;
}
}
// PSR-0 include paths.
if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
return $file;
}
return false;
}
}
/**
* Scope isolated include.
*
* Prevents access to $this/self from included files.
*/
function includeFile($file)
{
include $file;
}

21
cms/lib/vendor/minifier/composer/LICENSE vendored Executable file
View File

@@ -0,0 +1,21 @@
Copyright (c) Nils Adermann, Jordi Boggiano
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@@ -0,0 +1,9 @@
<?php
// autoload_classmap.php @generated by Composer
$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);
return array(
);

View File

@@ -0,0 +1,9 @@
<?php
// autoload_namespaces.php @generated by Composer
$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);
return array(
);

View File

@@ -0,0 +1,11 @@
<?php
// autoload_psr4.php @generated by Composer
$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);
return array(
'MatthiasMullie\\PathConverter\\' => array($vendorDir . '/matthiasmullie/path-converter/src'),
'MatthiasMullie\\Minify\\' => array($vendorDir . '/matthiasmullie/minify/src'),
);

View File

@@ -0,0 +1,52 @@
<?php
// autoload_real.php @generated by Composer
class ComposerAutoloaderInit223dcbee3a648ecec7c16ee350170eb0
{
private static $loader;
public static function loadClassLoader($class)
{
if ('Composer\Autoload\ClassLoader' === $class) {
require __DIR__ . '/ClassLoader.php';
}
}
public static function getLoader()
{
if (null !== self::$loader) {
return self::$loader;
}
spl_autoload_register(array('ComposerAutoloaderInit223dcbee3a648ecec7c16ee350170eb0', 'loadClassLoader'), true, true);
self::$loader = $loader = new \Composer\Autoload\ClassLoader();
spl_autoload_unregister(array('ComposerAutoloaderInit223dcbee3a648ecec7c16ee350170eb0', 'loadClassLoader'));
$useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
if ($useStaticLoader) {
require_once __DIR__ . '/autoload_static.php';
call_user_func(\Composer\Autoload\ComposerStaticInit223dcbee3a648ecec7c16ee350170eb0::getInitializer($loader));
} else {
$map = require __DIR__ . '/autoload_namespaces.php';
foreach ($map as $namespace => $path) {
$loader->set($namespace, $path);
}
$map = require __DIR__ . '/autoload_psr4.php';
foreach ($map as $namespace => $path) {
$loader->setPsr4($namespace, $path);
}
$classMap = require __DIR__ . '/autoload_classmap.php';
if ($classMap) {
$loader->addClassMap($classMap);
}
}
$loader->register(true);
return $loader;
}
}

View File

@@ -0,0 +1,36 @@
<?php
// autoload_static.php @generated by Composer
namespace Composer\Autoload;
class ComposerStaticInit223dcbee3a648ecec7c16ee350170eb0
{
public static $prefixLengthsPsr4 = array (
'M' =>
array (
'MatthiasMullie\\PathConverter\\' => 29,
'MatthiasMullie\\Minify\\' => 22,
),
);
public static $prefixDirsPsr4 = array (
'MatthiasMullie\\PathConverter\\' =>
array (
0 => __DIR__ . '/..' . '/matthiasmullie/path-converter/src',
),
'MatthiasMullie\\Minify\\' =>
array (
0 => __DIR__ . '/..' . '/matthiasmullie/minify/src',
),
);
public static function getInitializer(ClassLoader $loader)
{
return \Closure::bind(function () use ($loader) {
$loader->prefixLengthsPsr4 = ComposerStaticInit223dcbee3a648ecec7c16ee350170eb0::$prefixLengthsPsr4;
$loader->prefixDirsPsr4 = ComposerStaticInit223dcbee3a648ecec7c16ee350170eb0::$prefixDirsPsr4;
}, null, ClassLoader::class);
}
}

View File

@@ -0,0 +1,115 @@
[
{
"name": "matthiasmullie/minify",
"version": "1.3.61",
"version_normalized": "1.3.61.0",
"source": {
"type": "git",
"url": "https://github.com/matthiasmullie/minify.git",
"reference": "d5acb8ce5b6acb7d11bafe97cecc533f6e4fd751"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/matthiasmullie/minify/zipball/d5acb8ce5b6acb7d11bafe97cecc533f6e4fd751",
"reference": "d5acb8ce5b6acb7d11bafe97cecc533f6e4fd751",
"shasum": ""
},
"require": {
"ext-pcre": "*",
"matthiasmullie/path-converter": "~1.1",
"php": ">=5.3.0"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "~2.0",
"matthiasmullie/scrapbook": "~1.0",
"phpunit/phpunit": "~4.8"
},
"suggest": {
"psr/cache-implementation": "Cache implementation to use with Minify::cache"
},
"time": "2018-11-26T23:10:39+00:00",
"bin": [
"bin/minifycss",
"bin/minifyjs"
],
"type": "library",
"installation-source": "dist",
"autoload": {
"psr-4": {
"MatthiasMullie\\Minify\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Matthias Mullie",
"role": "Developer",
"email": "minify@mullie.eu",
"homepage": "http://www.mullie.eu"
}
],
"description": "CSS & JavaScript minifier, in PHP. Removes whitespace, strips comments, combines files (incl. @import statements and small assets in CSS files), and optimizes/shortens a few common programming patterns.",
"homepage": "http://www.minifier.org",
"keywords": [
"JS",
"css",
"javascript",
"minifier",
"minify"
]
},
{
"name": "matthiasmullie/path-converter",
"version": "1.1.2",
"version_normalized": "1.1.2.0",
"source": {
"type": "git",
"url": "https://github.com/matthiasmullie/path-converter.git",
"reference": "5e4b121c8b9f97c80835c1d878b0812ba1d607c9"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/matthiasmullie/path-converter/zipball/5e4b121c8b9f97c80835c1d878b0812ba1d607c9",
"reference": "5e4b121c8b9f97c80835c1d878b0812ba1d607c9",
"shasum": ""
},
"require": {
"ext-pcre": "*",
"php": ">=5.3.0"
},
"require-dev": {
"phpunit/phpunit": "~4.8"
},
"time": "2018-10-25T15:19:41+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
"psr-4": {
"MatthiasMullie\\PathConverter\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Matthias Mullie",
"role": "Developer",
"email": "pathconverter@mullie.eu",
"homepage": "http://www.mullie.eu"
}
],
"description": "Relative path converter",
"homepage": "http://github.com/matthiasmullie/path-converter",
"keywords": [
"converter",
"path",
"paths",
"relative"
]
}
]

View File

@@ -0,0 +1,59 @@
# How to contribute
## Issues
When [filing bugs](https://github.com/matthiasmullie/minify/issues/new),
try to be as thorough as possible:
* What version did you use?
* What did you try to do? ***Please post the relevant parts of your code.***
* What went wrong? ***Please include error messages, if any.***
* What was the expected result?
## Pull requests
Bug fixes and general improvements to the existing codebase are always welcome.
New features are also welcome, but will be judged on an individual basis. If
you'd rather not risk wasting your time implementing a new feature only to see
it turned down, please start the discussion by
[opening an issue](https://github.com/matthiasmullie/minify/issues/new).
Don't forget to add your changes to the [changelog](CHANGELOG.md).
### Testing
Please include tests for every change or addition to the code.
To run the complete test suite:
```sh
vendor/bin/phpunit
```
When submitting a new pull request, please make sure that that the test suite
passes (Travis CI will run it & report back on your pull request.)
To run the tests on Windows, run `tests/convert_symlinks_to_windows_style.sh`
from the command line in order to convert Linux-style test symlinks to
Windows-style.
### Coding standards
All code must follow [PSR-2](http://www.php-fig.org/psr/psr-2/). Just make sure
to run php-cs-fixer before submitting the code, it'll take care of the
formatting for you:
```sh
vendor/bin/php-cs-fixer fix src
vendor/bin/php-cs-fixer fix tests
```
Document the code thoroughly!
## License
Note that minify is MIT-licensed, which basically allows anyone to do
anything they like with it, without restriction.

View File

@@ -0,0 +1,13 @@
ARG version=cli
FROM php:$version
COPY . /var/www
WORKDIR /var/www
RUN apt-get update
RUN apt-get install -y zip unzip zlib1g-dev
RUN docker-php-ext-install zip
RUN docker-php-ext-install pcntl
RUN curl -sS https://getcomposer.org/installer | php
RUN mv composer.phar /usr/local/bin/composer
RUN composer install

View File

@@ -0,0 +1,18 @@
Copyright (c) 2012 Matthias Mullie
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@@ -0,0 +1,45 @@
#!/usr/bin/env php
<?php
use MatthiasMullie\Minify;
// command line utility to minify CSS
if (file_exists(__DIR__ . '/../../../autoload.php')) {
// if composer install
require_once __DIR__ . '/../../../autoload.php';
} else {
require_once __DIR__ . '/../src/Minify.php';
require_once __DIR__ . '/../src/CSS.php';
require_once __DIR__ . '/../src/Exception.php';
}
error_reporting(E_ALL);
// check PHP setup for cli arguments
if (!isset($_SERVER['argv']) && !isset($argv)) {
fwrite(STDERR, 'Please enable the "register_argc_argv" directive in your php.ini' . PHP_EOL);
exit(1);
} elseif (!isset($argv)) {
$argv = $_SERVER['argv'];
}
// check if path to file given
if (!isset($argv[1])) {
fwrite(STDERR, 'Argument expected: path to file' . PHP_EOL);
exit(1);
}
// check if script run in cli environment
if ('cli' !== php_sapi_name()) {
fwrite(STDERR, $argv[1] . ' must be run in the command line' . PHP_EOL);
exit(1);
}
// check if source file exists
if (!file_exists($argv[1])) {
fwrite(STDERR, 'Source file "' . $argv[1] . '" not found' . PHP_EOL);
exit(1);
}
try {
$minifier = new Minify\CSS($argv[1]);
echo $minifier->minify();
} catch (Exception $e) {
fwrite(STDERR, $e->getMessage(), PHP_EOL);
exit(1);
}

View File

@@ -0,0 +1,45 @@
#!/usr/bin/env php
<?php
use MatthiasMullie\Minify;
// command line utility to minify JS
if (file_exists(__DIR__ . '/../../../autoload.php')) {
// if composer install
require_once __DIR__ . '/../../../autoload.php';
} else {
require_once __DIR__ . '/../src/Minify.php';
require_once __DIR__ . '/../src/JS.php';
require_once __DIR__ . '/../src/Exception.php';
}
error_reporting(E_ALL);
// check PHP setup for cli arguments
if (!isset($_SERVER['argv']) && !isset($argv)) {
fwrite(STDERR, 'Please enable the "register_argc_argv" directive in your php.ini' . PHP_EOL);
exit(1);
} elseif (!isset($argv)) {
$argv = $_SERVER['argv'];
}
// check if path to file given
if (!isset($argv[1])) {
fwrite(STDERR, 'Argument expected: path to file' . PHP_EOL);
exit(1);
}
// check if script run in cli environment
if ('cli' !== php_sapi_name()) {
fwrite(STDERR, $argv[1] . ' must be run in the command line' . PHP_EOL);
exit(1);
}
// check if source file exists
if (!file_exists($argv[1])) {
fwrite(STDERR, 'Source file "' . $argv[1] . '" not found' . PHP_EOL);
exit(1);
}
try {
$minifier = new Minify\JS($argv[1]);
echo $minifier->minify();
} catch (Exception $e) {
fwrite(STDERR, $e->getMessage(), PHP_EOL);
exit(1);
}

View File

@@ -0,0 +1,38 @@
{
"name": "matthiasmullie/minify",
"type": "library",
"description": "CSS & JavaScript minifier, in PHP. Removes whitespace, strips comments, combines files (incl. @import statements and small assets in CSS files), and optimizes/shortens a few common programming patterns.",
"keywords": ["minify", "minifier", "css", "js", "javascript"],
"homepage": "http://www.minifier.org",
"license": "MIT",
"authors": [
{
"name": "Matthias Mullie",
"homepage": "http://www.mullie.eu",
"email": "minify@mullie.eu",
"role": "Developer"
}
],
"require": {
"php": ">=5.3.0",
"ext-pcre": "*",
"matthiasmullie/path-converter": "~1.1"
},
"require-dev": {
"matthiasmullie/scrapbook": "~1.0",
"phpunit/phpunit": "~4.8",
"friendsofphp/php-cs-fixer": "~2.0"
},
"suggest": {
"psr/cache-implementation": "Cache implementation to use with Minify::cache"
},
"autoload": {
"psr-4": {
"MatthiasMullie\\Minify\\": "src/"
}
},
"bin": [
"bin/minifycss",
"bin/minifyjs"
]
}

View File

@@ -0,0 +1,7 @@
in
public
extends
private
protected
implements
instanceof

View File

@@ -0,0 +1,26 @@
do
in
let
new
var
case
else
enum
void
with
class
const
yield
delete
export
import
public
static
typeof
extends
package
private
function
protected
implements
instanceof

View File

@@ -0,0 +1,63 @@
do
if
in
for
let
new
try
var
case
else
enum
eval
null
this
true
void
with
break
catch
class
const
false
super
throw
while
yield
delete
export
import
public
return
static
switch
typeof
default
extends
finally
package
private
continue
debugger
function
arguments
interface
protected
implements
instanceof
abstract
boolean
byte
char
double
final
float
goto
int
long
native
short
synchronized
throws
transient
volatile

View File

@@ -0,0 +1,46 @@
+
-
*
/
%
=
+=
-=
*=
/=
%=
<<=
>>=
>>>=
&=
^=
|=
&
|
^
~
<<
>>
>>>
==
===
!=
!==
>
<
>=
<=
&&
||
!
.
[
]
?
:
,
;
(
)
{
}

View File

@@ -0,0 +1,43 @@
+
-
*
/
%
=
+=
-=
*=
/=
%=
<<=
>>=
>>>=
&=
^=
|=
&
|
^
<<
>>
>>>
==
===
!=
!==
>
<
>=
<=
&&
||
.
[
]
?
:
,
;
(
)
}

View File

@@ -0,0 +1,43 @@
+
-
*
/
%
=
+=
-=
*=
/=
%=
<<=
>>=
>>>=
&=
^=
|=
&
|
^
~
<<
>>
>>>
==
===
!=
!==
>
<
>=
<=
&&
||
!
.
[
?
:
,
;
(
{

View File

@@ -0,0 +1,31 @@
version: '2.1'
services:
php:
build:
context: .
dockerfile: Dockerfile
volumes:
- ./src:/var/www/src
- ./data:/var/www/data
- ./tests:/var/www/tests
- ./phpunit.xml.dist:/var/www/phpunit.xml.dist
'7.2':
extends: php
build:
args:
version: 7.2-cli
'7.1':
extends: php
build:
args:
version: 7.1-cli
'7.0':
extends: php
build:
args:
version: 7.0-cli
'5.6':
extends: php
build:
args:
version: 5.6-cli

View File

@@ -0,0 +1,752 @@
<?php
/**
* CSS Minifier
*
* Please report bugs on https://github.com/matthiasmullie/minify/issues
*
* @author Matthias Mullie <minify@mullie.eu>
* @copyright Copyright (c) 2012, Matthias Mullie. All rights reserved
* @license MIT License
*/
namespace MatthiasMullie\Minify;
use MatthiasMullie\Minify\Exceptions\FileImportException;
use MatthiasMullie\PathConverter\ConverterInterface;
use MatthiasMullie\PathConverter\Converter;
/**
* CSS minifier
*
* Please report bugs on https://github.com/matthiasmullie/minify/issues
*
* @package Minify
* @author Matthias Mullie <minify@mullie.eu>
* @author Tijs Verkoyen <minify@verkoyen.eu>
* @copyright Copyright (c) 2012, Matthias Mullie. All rights reserved
* @license MIT License
*/
class CSS extends Minify
{
/**
* @var int maximum inport size in kB
*/
protected $maxImportSize = 5;
/**
* @var string[] valid import extensions
*/
protected $importExtensions = array(
'gif' => 'data:image/gif',
'png' => 'data:image/png',
'jpe' => 'data:image/jpeg',
'jpg' => 'data:image/jpeg',
'jpeg' => 'data:image/jpeg',
'svg' => 'data:image/svg+xml',
'woff' => 'data:application/x-font-woff',
'tif' => 'image/tiff',
'tiff' => 'image/tiff',
'xbm' => 'image/x-xbitmap',
);
/**
* Set the maximum size if files to be imported.
*
* Files larger than this size (in kB) will not be imported into the CSS.
* Importing files into the CSS as data-uri will save you some connections,
* but we should only import relatively small decorative images so that our
* CSS file doesn't get too bulky.
*
* @param int $size Size in kB
*/
public function setMaxImportSize($size)
{
$this->maxImportSize = $size;
}
/**
* Set the type of extensions to be imported into the CSS (to save network
* connections).
* Keys of the array should be the file extensions & respective values
* should be the data type.
*
* @param string[] $extensions Array of file extensions
*/
public function setImportExtensions(array $extensions)
{
$this->importExtensions = $extensions;
}
/**
* Move any import statements to the top.
*
* @param string $content Nearly finished CSS content
*
* @return string
*/
protected function moveImportsToTop($content)
{
if (preg_match_all('/(;?)(@import (?<url>url\()?(?P<quotes>["\']?).+?(?P=quotes)(?(url)\)));?/', $content, $matches)) {
// remove from content
foreach ($matches[0] as $import) {
$content = str_replace($import, '', $content);
}
// add to top
$content = implode(';', $matches[2]).';'.trim($content, ';');
}
return $content;
}
/**
* Combine CSS from import statements.
*
* @import's will be loaded and their content merged into the original file,
* to save HTTP requests.
*
* @param string $source The file to combine imports for
* @param string $content The CSS content to combine imports for
* @param string[] $parents Parent paths, for circular reference checks
*
* @return string
*
* @throws FileImportException
*/
protected function combineImports($source, $content, $parents)
{
$importRegexes = array(
// @import url(xxx)
'/
# import statement
@import
# whitespace
\s+
# open url()
url\(
# (optional) open path enclosure
(?P<quotes>["\']?)
# fetch path
(?P<path>.+?)
# (optional) close path enclosure
(?P=quotes)
# close url()
\)
# (optional) trailing whitespace
\s*
# (optional) media statement(s)
(?P<media>[^;]*)
# (optional) trailing whitespace
\s*
# (optional) closing semi-colon
;?
/ix',
// @import 'xxx'
'/
# import statement
@import
# whitespace
\s+
# open path enclosure
(?P<quotes>["\'])
# fetch path
(?P<path>.+?)
# close path enclosure
(?P=quotes)
# (optional) trailing whitespace
\s*
# (optional) media statement(s)
(?P<media>[^;]*)
# (optional) trailing whitespace
\s*
# (optional) closing semi-colon
;?
/ix',
);
// find all relative imports in css
$matches = array();
foreach ($importRegexes as $importRegex) {
if (preg_match_all($importRegex, $content, $regexMatches, PREG_SET_ORDER)) {
$matches = array_merge($matches, $regexMatches);
}
}
$search = array();
$replace = array();
// loop the matches
foreach ($matches as $match) {
// get the path for the file that will be imported
$importPath = dirname($source).'/'.$match['path'];
// only replace the import with the content if we can grab the
// content of the file
if (!$this->canImportByPath($match['path']) || !$this->canImportFile($importPath)) {
continue;
}
// check if current file was not imported previously in the same
// import chain.
if (in_array($importPath, $parents)) {
throw new FileImportException('Failed to import file "'.$importPath.'": circular reference detected.');
}
// grab referenced file & minify it (which may include importing
// yet other @import statements recursively)
$minifier = new static($importPath);
$minifier->setMaxImportSize($this->maxImportSize);
$minifier->setImportExtensions($this->importExtensions);
$importContent = $minifier->execute($source, $parents);
// check if this is only valid for certain media
if (!empty($match['media'])) {
$importContent = '@media '.$match['media'].'{'.$importContent.'}';
}
// add to replacement array
$search[] = $match[0];
$replace[] = $importContent;
}
// replace the import statements
return str_replace($search, $replace, $content);
}
/**
* Import files into the CSS, base64-ized.
*
* @url(image.jpg) images will be loaded and their content merged into the
* original file, to save HTTP requests.
*
* @param string $source The file to import files for
* @param string $content The CSS content to import files for
*
* @return string
*/
protected function importFiles($source, $content)
{
$regex = '/url\((["\']?)(.+?)\\1\)/i';
if ($this->importExtensions && preg_match_all($regex, $content, $matches, PREG_SET_ORDER)) {
$search = array();
$replace = array();
// loop the matches
foreach ($matches as $match) {
$extension = substr(strrchr($match[2], '.'), 1);
if ($extension && !array_key_exists($extension, $this->importExtensions)) {
continue;
}
// get the path for the file that will be imported
$path = $match[2];
$path = dirname($source).'/'.$path;
// only replace the import with the content if we're able to get
// the content of the file, and it's relatively small
if ($this->canImportFile($path) && $this->canImportBySize($path)) {
// grab content && base64-ize
$importContent = $this->load($path);
$importContent = base64_encode($importContent);
// build replacement
$search[] = $match[0];
$replace[] = 'url('.$this->importExtensions[$extension].';base64,'.$importContent.')';
}
}
// replace the import statements
$content = str_replace($search, $replace, $content);
}
return $content;
}
/**
* Minify the data.
* Perform CSS optimizations.
*
* @param string[optional] $path Path to write the data to
* @param string[] $parents Parent paths, for circular reference checks
*
* @return string The minified data
*/
public function execute($path = null, $parents = array())
{
$content = '';
// loop CSS data (raw data and files)
foreach ($this->data as $source => $css) {
/*
* Let's first take out strings & comments, since we can't just
* remove whitespace anywhere. If whitespace occurs inside a string,
* we should leave it alone. E.g.:
* p { content: "a test" }
*/
$this->extractStrings();
$this->stripComments();
$this->extractCalcs();
$css = $this->replace($css);
$css = $this->stripWhitespace($css);
$css = $this->shortenColors($css);
$css = $this->shortenZeroes($css);
$css = $this->shortenFontWeights($css);
$css = $this->stripEmptyTags($css);
// restore the string we've extracted earlier
$css = $this->restoreExtractedData($css);
$source = is_int($source) ? '' : $source;
$parents = $source ? array_merge($parents, array($source)) : $parents;
$css = $this->combineImports($source, $css, $parents);
$css = $this->importFiles($source, $css);
/*
* If we'll save to a new path, we'll have to fix the relative paths
* to be relative no longer to the source file, but to the new path.
* If we don't write to a file, fall back to same path so no
* conversion happens (because we still want it to go through most
* of the move code, which also addresses url() & @import syntax...)
*/
$converter = $this->getPathConverter($source, $path ?: $source);
$css = $this->move($converter, $css);
// combine css
$content .= $css;
}
$content = $this->moveImportsToTop($content);
return $content;
}
/**
* Moving a css file should update all relative urls.
* Relative references (e.g. ../images/image.gif) in a certain css file,
* will have to be updated when a file is being saved at another location
* (e.g. ../../images/image.gif, if the new CSS file is 1 folder deeper).
*
* @param ConverterInterface $converter Relative path converter
* @param string $content The CSS content to update relative urls for
*
* @return string
*/
protected function move(ConverterInterface $converter, $content)
{
/*
* Relative path references will usually be enclosed by url(). @import
* is an exception, where url() is not necessary around the path (but is
* allowed).
* This *could* be 1 regular expression, where both regular expressions
* in this array are on different sides of a |. But we're using named
* patterns in both regexes, the same name on both regexes. This is only
* possible with a (?J) modifier, but that only works after a fairly
* recent PCRE version. That's why I'm doing 2 separate regular
* expressions & combining the matches after executing of both.
*/
$relativeRegexes = array(
// url(xxx)
'/
# open url()
url\(
\s*
# open path enclosure
(?P<quotes>["\'])?
# fetch path
(?P<path>.+?)
# close path enclosure
(?(quotes)(?P=quotes))
\s*
# close url()
\)
/ix',
// @import "xxx"
'/
# import statement
@import
# whitespace
\s+
# we don\'t have to check for @import url(), because the
# condition above will already catch these
# open path enclosure
(?P<quotes>["\'])
# fetch path
(?P<path>.+?)
# close path enclosure
(?P=quotes)
/ix',
);
// find all relative urls in css
$matches = array();
foreach ($relativeRegexes as $relativeRegex) {
if (preg_match_all($relativeRegex, $content, $regexMatches, PREG_SET_ORDER)) {
$matches = array_merge($matches, $regexMatches);
}
}
$search = array();
$replace = array();
// loop all urls
foreach ($matches as $match) {
// determine if it's a url() or an @import match
$type = (strpos($match[0], '@import') === 0 ? 'import' : 'url');
$url = $match['path'];
if ($this->canImportByPath($url)) {
// attempting to interpret GET-params makes no sense, so let's discard them for awhile
$params = strrchr($url, '?');
$url = $params ? substr($url, 0, -strlen($params)) : $url;
// fix relative url
$url = $converter->convert($url);
// now that the path has been converted, re-apply GET-params
$url .= $params;
}
/*
* Urls with control characters above 0x7e should be quoted.
* According to Mozilla's parser, whitespace is only allowed at the
* end of unquoted urls.
* Urls with `)` (as could happen with data: uris) should also be
* quoted to avoid being confused for the url() closing parentheses.
* And urls with a # have also been reported to cause issues.
* Urls with quotes inside should also remain escaped.
*
* @see https://developer.mozilla.org/nl/docs/Web/CSS/url#The_url()_functional_notation
* @see https://hg.mozilla.org/mozilla-central/rev/14abca4e7378
* @see https://github.com/matthiasmullie/minify/issues/193
*/
$url = trim($url);
if (preg_match('/[\s\)\'"#\x{7f}-\x{9f}]/u', $url)) {
$url = $match['quotes'] . $url . $match['quotes'];
}
// build replacement
$search[] = $match[0];
if ($type === 'url') {
$replace[] = 'url('.$url.')';
} elseif ($type === 'import') {
$replace[] = '@import "'.$url.'"';
}
}
// replace urls
return str_replace($search, $replace, $content);
}
/**
* Shorthand hex color codes.
* #FF0000 -> #F00.
*
* @param string $content The CSS content to shorten the hex color codes for
*
* @return string
*/
protected function shortenColors($content)
{
$content = preg_replace('/(?<=[: ])#([0-9a-z])\\1([0-9a-z])\\2([0-9a-z])\\3(?:([0-9a-z])\\4)?(?=[; }])/i', '#$1$2$3$4', $content);
// remove alpha channel if it's pointless...
$content = preg_replace('/(?<=[: ])#([0-9a-z]{6})ff?(?=[; }])/i', '#$1', $content);
$content = preg_replace('/(?<=[: ])#([0-9a-z]{3})f?(?=[; }])/i', '#$1', $content);
$colors = array(
// we can shorten some even more by replacing them with their color name
'#F0FFFF' => 'azure',
'#F5F5DC' => 'beige',
'#A52A2A' => 'brown',
'#FF7F50' => 'coral',
'#FFD700' => 'gold',
'#808080' => 'gray',
'#008000' => 'green',
'#4B0082' => 'indigo',
'#FFFFF0' => 'ivory',
'#F0E68C' => 'khaki',
'#FAF0E6' => 'linen',
'#800000' => 'maroon',
'#000080' => 'navy',
'#808000' => 'olive',
'#CD853F' => 'peru',
'#FFC0CB' => 'pink',
'#DDA0DD' => 'plum',
'#800080' => 'purple',
'#F00' => 'red',
'#FA8072' => 'salmon',
'#A0522D' => 'sienna',
'#C0C0C0' => 'silver',
'#FFFAFA' => 'snow',
'#D2B48C' => 'tan',
'#FF6347' => 'tomato',
'#EE82EE' => 'violet',
'#F5DEB3' => 'wheat',
// or the other way around
'WHITE' => '#fff',
'BLACK' => '#000',
);
return preg_replace_callback(
'/(?<=[: ])('.implode('|', array_keys($colors)).')(?=[; }])/i',
function ($match) use ($colors) {
return $colors[strtoupper($match[0])];
},
$content
);
}
/**
* Shorten CSS font weights.
*
* @param string $content The CSS content to shorten the font weights for
*
* @return string
*/
protected function shortenFontWeights($content)
{
$weights = array(
'normal' => 400,
'bold' => 700,
);
$callback = function ($match) use ($weights) {
return $match[1].$weights[$match[2]];
};
return preg_replace_callback('/(font-weight\s*:\s*)('.implode('|', array_keys($weights)).')(?=[;}])/', $callback, $content);
}
/**
* Shorthand 0 values to plain 0, instead of e.g. -0em.
*
* @param string $content The CSS content to shorten the zero values for
*
* @return string
*/
protected function shortenZeroes($content)
{
// we don't want to strip units in `calc()` expressions:
// `5px - 0px` is valid, but `5px - 0` is not
// `10px * 0` is valid (equates to 0), and so is `10 * 0px`, but
// `10 * 0` is invalid
// we've extracted calcs earlier, so we don't need to worry about this
// reusable bits of code throughout these regexes:
// before & after are used to make sure we don't match lose unintended
// 0-like values (e.g. in #000, or in http://url/1.0)
// units can be stripped from 0 values, or used to recognize non 0
// values (where wa may be able to strip a .0 suffix)
$before = '(?<=[:(, ])';
$after = '(?=[ ,);}])';
$units = '(em|ex|%|px|cm|mm|in|pt|pc|ch|rem|vh|vw|vmin|vmax|vm)';
// strip units after zeroes (0px -> 0)
// NOTE: it should be safe to remove all units for a 0 value, but in
// practice, Webkit (especially Safari) seems to stumble over at least
// 0%, potentially other units as well. Only stripping 'px' for now.
// @see https://github.com/matthiasmullie/minify/issues/60
$content = preg_replace('/'.$before.'(-?0*(\.0+)?)(?<=0)px'.$after.'/', '\\1', $content);
// strip 0-digits (.0 -> 0)
$content = preg_replace('/'.$before.'\.0+'.$units.'?'.$after.'/', '0\\1', $content);
// strip trailing 0: 50.10 -> 50.1, 50.10px -> 50.1px
$content = preg_replace('/'.$before.'(-?[0-9]+\.[0-9]+)0+'.$units.'?'.$after.'/', '\\1\\2', $content);
// strip trailing 0: 50.00 -> 50, 50.00px -> 50px
$content = preg_replace('/'.$before.'(-?[0-9]+)\.0+'.$units.'?'.$after.'/', '\\1\\2', $content);
// strip leading 0: 0.1 -> .1, 01.1 -> 1.1
$content = preg_replace('/'.$before.'(-?)0+([0-9]*\.[0-9]+)'.$units.'?'.$after.'/', '\\1\\2\\3', $content);
// strip negative zeroes (-0 -> 0) & truncate zeroes (00 -> 0)
$content = preg_replace('/'.$before.'-?0+'.$units.'?'.$after.'/', '0\\1', $content);
// IE doesn't seem to understand a unitless flex-basis value (correct -
// it goes against the spec), so let's add it in again (make it `%`,
// which is only 1 char: 0%, 0px, 0 anything, it's all just the same)
// @see https://developer.mozilla.org/nl/docs/Web/CSS/flex
$content = preg_replace('/flex:([0-9]+\s[0-9]+\s)0([;\}])/', 'flex:${1}0%${2}', $content);
$content = preg_replace('/flex-basis:0([;\}])/', 'flex-basis:0%${1}', $content);
return $content;
}
/**
* Strip empty tags from source code.
*
* @param string $content
*
* @return string
*/
protected function stripEmptyTags($content)
{
$content = preg_replace('/(?<=^)[^\{\};]+\{\s*\}/', '', $content);
$content = preg_replace('/(?<=(\}|;))[^\{\};]+\{\s*\}/', '', $content);
return $content;
}
/**
* Strip comments from source code.
*/
protected function stripComments()
{
// PHP only supports $this inside anonymous functions since 5.4
$minifier = $this;
$callback = function ($match) use ($minifier) {
$count = count($minifier->extracted);
$placeholder = '/*'.$count.'*/';
$minifier->extracted[$placeholder] = $match[0];
return $placeholder;
};
$this->registerPattern('/\n?\/\*(!|.*?@license|.*?@preserve).*?\*\/\n?/s', $callback);
$this->registerPattern('/\/\*.*?\*\//s', '');
}
/**
* Strip whitespace.
*
* @param string $content The CSS content to strip the whitespace for
*
* @return string
*/
protected function stripWhitespace($content)
{
// remove leading & trailing whitespace
$content = preg_replace('/^\s*/m', '', $content);
$content = preg_replace('/\s*$/m', '', $content);
// replace newlines with a single space
$content = preg_replace('/\s+/', ' ', $content);
// remove whitespace around meta characters
// inspired by stackoverflow.com/questions/15195750/minify-compress-css-with-regex
$content = preg_replace('/\s*([\*$~^|]?+=|[{};,>~]|!important\b)\s*/', '$1', $content);
$content = preg_replace('/([\[(:>\+])\s+/', '$1', $content);
$content = preg_replace('/\s+([\]\)>\+])/', '$1', $content);
$content = preg_replace('/\s+(:)(?![^\}]*\{)/', '$1', $content);
// whitespace around + and - can only be stripped inside some pseudo-
// classes, like `:nth-child(3+2n)`
// not in things like `calc(3px + 2px)`, shorthands like `3px -2px`, or
// selectors like `div.weird- p`
$pseudos = array('nth-child', 'nth-last-child', 'nth-last-of-type', 'nth-of-type');
$content = preg_replace('/:('.implode('|', $pseudos).')\(\s*([+-]?)\s*(.+?)\s*([+-]?)\s*(.*?)\s*\)/', ':$1($2$3$4$5)', $content);
// remove semicolon/whitespace followed by closing bracket
$content = str_replace(';}', '}', $content);
return trim($content);
}
/**
* Replace all `calc()` occurrences.
*/
protected function extractCalcs()
{
// PHP only supports $this inside anonymous functions since 5.4
$minifier = $this;
$callback = function ($match) use ($minifier) {
$length = strlen($match[1]);
$expr = '';
$opened = 0;
for ($i = 0; $i < $length; $i++) {
$char = $match[1][$i];
$expr .= $char;
if ($char === '(') {
$opened++;
} elseif ($char === ')' && --$opened === 0) {
break;
}
}
$rest = str_replace($expr, '', $match[1]);
$expr = trim(substr($expr, 1, -1));
$count = count($minifier->extracted);
$placeholder = 'calc('.$count.')';
$minifier->extracted[$placeholder] = 'calc('.$expr.')';
return $placeholder.$rest;
};
$this->registerPattern('/calc(\(.+?)(?=$|;|}|calc\()/', $callback);
$this->registerPattern('/calc(\(.+?)(?=$|;|}|calc\()/m', $callback);
}
/**
* Check if file is small enough to be imported.
*
* @param string $path The path to the file
*
* @return bool
*/
protected function canImportBySize($path)
{
return ($size = @filesize($path)) && $size <= $this->maxImportSize * 1024;
}
/**
* Check if file a file can be imported, going by the path.
*
* @param string $path
*
* @return bool
*/
protected function canImportByPath($path)
{
return preg_match('/^(data:|https?:|\\/)/', $path) === 0;
}
/**
* Return a converter to update relative paths to be relative to the new
* destination.
*
* @param string $source
* @param string $target
*
* @return ConverterInterface
*/
protected function getPathConverter($source, $target)
{
return new Converter($source, $target);
}
}

View File

@@ -0,0 +1,20 @@
<?php
/**
* Base Exception
*
* @deprecated Use Exceptions\BasicException instead
*
* @author Matthias Mullie <minify@mullie.eu>
*/
namespace MatthiasMullie\Minify;
/**
* Base Exception Class
* @deprecated Use Exceptions\BasicException instead
*
* @package Minify
* @author Matthias Mullie <minify@mullie.eu>
*/
abstract class Exception extends \Exception
{
}

View File

@@ -0,0 +1,23 @@
<?php
/**
* Basic exception
*
* Please report bugs on https://github.com/matthiasmullie/minify/issues
*
* @author Matthias Mullie <minify@mullie.eu>
* @copyright Copyright (c) 2012, Matthias Mullie. All rights reserved
* @license MIT License
*/
namespace MatthiasMullie\Minify\Exceptions;
use MatthiasMullie\Minify\Exception;
/**
* Basic Exception Class
*
* @package Minify\Exception
* @author Matthias Mullie <minify@mullie.eu>
*/
abstract class BasicException extends Exception
{
}

View File

@@ -0,0 +1,21 @@
<?php
/**
* File Import Exception
*
* Please report bugs on https://github.com/matthiasmullie/minify/issues
*
* @author Matthias Mullie <minify@mullie.eu>
* @copyright Copyright (c) 2012, Matthias Mullie. All rights reserved
* @license MIT License
*/
namespace MatthiasMullie\Minify\Exceptions;
/**
* File Import Exception Class
*
* @package Minify\Exception
* @author Matthias Mullie <minify@mullie.eu>
*/
class FileImportException extends BasicException
{
}

View File

@@ -0,0 +1,21 @@
<?php
/**
* IO Exception
*
* Please report bugs on https://github.com/matthiasmullie/minify/issues
*
* @author Matthias Mullie <minify@mullie.eu>
* @copyright Copyright (c) 2012, Matthias Mullie. All rights reserved
* @license MIT License
*/
namespace MatthiasMullie\Minify\Exceptions;
/**
* IO Exception Class
*
* @package Minify\Exception
* @author Matthias Mullie <minify@mullie.eu>
*/
class IOException extends BasicException
{
}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,497 @@
<?php
/**
* Abstract minifier class
*
* Please report bugs on https://github.com/matthiasmullie/minify/issues
*
* @author Matthias Mullie <minify@mullie.eu>
* @copyright Copyright (c) 2012, Matthias Mullie. All rights reserved
* @license MIT License
*/
namespace MatthiasMullie\Minify;
use MatthiasMullie\Minify\Exceptions\IOException;
use Psr\Cache\CacheItemInterface;
/**
* Abstract minifier class.
*
* Please report bugs on https://github.com/matthiasmullie/minify/issues
*
* @package Minify
* @author Matthias Mullie <minify@mullie.eu>
* @copyright Copyright (c) 2012, Matthias Mullie. All rights reserved
* @license MIT License
*/
abstract class Minify
{
/**
* The data to be minified.
*
* @var string[]
*/
protected $data = array();
/**
* Array of patterns to match.
*
* @var string[]
*/
protected $patterns = array();
/**
* This array will hold content of strings and regular expressions that have
* been extracted from the JS source code, so we can reliably match "code",
* without having to worry about potential "code-like" characters inside.
*
* @var string[]
*/
public $extracted = array();
/**
* Init the minify class - optionally, code may be passed along already.
*/
public function __construct(/* $data = null, ... */)
{
// it's possible to add the source through the constructor as well ;)
if (func_num_args()) {
call_user_func_array(array($this, 'add'), func_get_args());
}
}
/**
* Add a file or straight-up code to be minified.
*
* @param string|string[] $data
*
* @return static
*/
public function add($data /* $data = null, ... */)
{
// bogus "usage" of parameter $data: scrutinizer warns this variable is
// not used (we're using func_get_args instead to support overloading),
// but it still needs to be defined because it makes no sense to have
// this function without argument :)
$args = array($data) + func_get_args();
// this method can be overloaded
foreach ($args as $data) {
if (is_array($data)) {
call_user_func_array(array($this, 'add'), $data);
continue;
}
// redefine var
$data = (string) $data;
// load data
$value = $this->load($data);
$key = ($data != $value) ? $data : count($this->data);
// replace CR linefeeds etc.
// @see https://github.com/matthiasmullie/minify/pull/139
$value = str_replace(array("\r\n", "\r"), "\n", $value);
// store data
$this->data[$key] = $value;
}
return $this;
}
/**
* Add a file to be minified.
*
* @param string|string[] $data
*
* @return static
*
* @throws IOException
*/
public function addFile($data /* $data = null, ... */)
{
// bogus "usage" of parameter $data: scrutinizer warns this variable is
// not used (we're using func_get_args instead to support overloading),
// but it still needs to be defined because it makes no sense to have
// this function without argument :)
$args = array($data) + func_get_args();
// this method can be overloaded
foreach ($args as $path) {
if (is_array($path)) {
call_user_func_array(array($this, 'addFile'), $path);
continue;
}
// redefine var
$path = (string) $path;
// check if we can read the file
if (!$this->canImportFile($path)) {
throw new IOException('The file "'.$path.'" could not be opened for reading. Check if PHP has enough permissions.');
}
$this->add($path);
}
return $this;
}
/**
* Minify the data & (optionally) saves it to a file.
*
* @param string[optional] $path Path to write the data to
*
* @return string The minified data
*/
public function minify($path = null)
{
$content = $this->execute($path);
// save to path
if ($path !== null) {
$this->save($content, $path);
}
return $content;
}
/**
* Minify & gzip the data & (optionally) saves it to a file.
*
* @param string[optional] $path Path to write the data to
* @param int[optional] $level Compression level, from 0 to 9
*
* @return string The minified & gzipped data
*/
public function gzip($path = null, $level = 9)
{
$content = $this->execute($path);
$content = gzencode($content, $level, FORCE_GZIP);
// save to path
if ($path !== null) {
$this->save($content, $path);
}
return $content;
}
/**
* Minify the data & write it to a CacheItemInterface object.
*
* @param CacheItemInterface $item Cache item to write the data to
*
* @return CacheItemInterface Cache item with the minifier data
*/
public function cache(CacheItemInterface $item)
{
$content = $this->execute();
$item->set($content);
return $item;
}
/**
* Minify the data.
*
* @param string[optional] $path Path to write the data to
*
* @return string The minified data
*/
abstract public function execute($path = null);
/**
* Load data.
*
* @param string $data Either a path to a file or the content itself
*
* @return string
*/
protected function load($data)
{
// check if the data is a file
if ($this->canImportFile($data)) {
$data = file_get_contents($data);
// strip BOM, if any
if (substr($data, 0, 3) == "\xef\xbb\xbf") {
$data = substr($data, 3);
}
}
return $data;
}
/**
* Save to file.
*
* @param string $content The minified data
* @param string $path The path to save the minified data to
*
* @throws IOException
*/
protected function save($content, $path)
{
$handler = $this->openFileForWriting($path);
$this->writeToFile($handler, $content);
@fclose($handler);
}
/**
* Register a pattern to execute against the source content.
*
* @param string $pattern PCRE pattern
* @param string|callable $replacement Replacement value for matched pattern
*/
protected function registerPattern($pattern, $replacement = '')
{
// study the pattern, we'll execute it more than once
$pattern .= 'S';
$this->patterns[] = array($pattern, $replacement);
}
/**
* We can't "just" run some regular expressions against JavaScript: it's a
* complex language. E.g. having an occurrence of // xyz would be a comment,
* unless it's used within a string. Of you could have something that looks
* like a 'string', but inside a comment.
* The only way to accurately replace these pieces is to traverse the JS one
* character at a time and try to find whatever starts first.
*
* @param string $content The content to replace patterns in
*
* @return string The (manipulated) content
*/
protected function replace($content)
{
$processed = '';
$positions = array_fill(0, count($this->patterns), -1);
$matches = array();
while ($content) {
// find first match for all patterns
foreach ($this->patterns as $i => $pattern) {
list($pattern, $replacement) = $pattern;
// we can safely ignore patterns for positions we've unset earlier,
// because we know these won't show up anymore
if (array_key_exists($i, $positions) == false) {
continue;
}
// no need to re-run matches that are still in the part of the
// content that hasn't been processed
if ($positions[$i] >= 0) {
continue;
}
$match = null;
if (preg_match($pattern, $content, $match, PREG_OFFSET_CAPTURE)) {
$matches[$i] = $match;
// we'll store the match position as well; that way, we
// don't have to redo all preg_matches after changing only
// the first (we'll still know where those others are)
$positions[$i] = $match[0][1];
} else {
// if the pattern couldn't be matched, there's no point in
// executing it again in later runs on this same content;
// ignore this one until we reach end of content
unset($matches[$i], $positions[$i]);
}
}
// no more matches to find: everything's been processed, break out
if (!$matches) {
$processed .= $content;
break;
}
// see which of the patterns actually found the first thing (we'll
// only want to execute that one, since we're unsure if what the
// other found was not inside what the first found)
$discardLength = min($positions);
$firstPattern = array_search($discardLength, $positions);
$match = $matches[$firstPattern][0][0];
// execute the pattern that matches earliest in the content string
list($pattern, $replacement) = $this->patterns[$firstPattern];
$replacement = $this->replacePattern($pattern, $replacement, $content);
// figure out which part of the string was unmatched; that's the
// part we'll execute the patterns on again next
$content = (string) substr($content, $discardLength);
$unmatched = (string) substr($content, strpos($content, $match) + strlen($match));
// move the replaced part to $processed and prepare $content to
// again match batch of patterns against
$processed .= substr($replacement, 0, strlen($replacement) - strlen($unmatched));
$content = $unmatched;
// first match has been replaced & that content is to be left alone,
// the next matches will start after this replacement, so we should
// fix their offsets
foreach ($positions as $i => $position) {
$positions[$i] -= $discardLength + strlen($match);
}
}
return $processed;
}
/**
* This is where a pattern is matched against $content and the matches
* are replaced by their respective value.
* This function will be called plenty of times, where $content will always
* move up 1 character.
*
* @param string $pattern Pattern to match
* @param string|callable $replacement Replacement value
* @param string $content Content to match pattern against
*
* @return string
*/
protected function replacePattern($pattern, $replacement, $content)
{
if (is_callable($replacement)) {
return preg_replace_callback($pattern, $replacement, $content, 1, $count);
} else {
return preg_replace($pattern, $replacement, $content, 1, $count);
}
}
/**
* Strings are a pattern we need to match, in order to ignore potential
* code-like content inside them, but we just want all of the string
* content to remain untouched.
*
* This method will replace all string content with simple STRING#
* placeholder text, so we've rid all strings from characters that may be
* misinterpreted. Original string content will be saved in $this->extracted
* and after doing all other minifying, we can restore the original content
* via restoreStrings().
*
* @param string[optional] $chars
* @param string[optional] $placeholderPrefix
*/
protected function extractStrings($chars = '\'"', $placeholderPrefix = '')
{
// PHP only supports $this inside anonymous functions since 5.4
$minifier = $this;
$callback = function ($match) use ($minifier, $placeholderPrefix) {
// check the second index here, because the first always contains a quote
if ($match[2] === '') {
/*
* Empty strings need no placeholder; they can't be confused for
* anything else anyway.
* But we still needed to match them, for the extraction routine
* to skip over this particular string.
*/
return $match[0];
}
$count = count($minifier->extracted);
$placeholder = $match[1].$placeholderPrefix.$count.$match[1];
$minifier->extracted[$placeholder] = $match[1].$match[2].$match[1];
return $placeholder;
};
/*
* The \\ messiness explained:
* * Don't count ' or " as end-of-string if it's escaped (has backslash
* in front of it)
* * Unless... that backslash itself is escaped (another leading slash),
* in which case it's no longer escaping the ' or "
* * So there can be either no backslash, or an even number
* * multiply all of that times 4, to account for the escaping that has
* to be done to pass the backslash into the PHP string without it being
* considered as escape-char (times 2) and to get it in the regex,
* escaped (times 2)
*/
$this->registerPattern('/(['.$chars.'])(.*?(?<!\\\\)(\\\\\\\\)*+)\\1/s', $callback);
}
/**
* This method will restore all extracted data (strings, regexes) that were
* replaced with placeholder text in extract*(). The original content was
* saved in $this->extracted.
*
* @param string $content
*
* @return string
*/
protected function restoreExtractedData($content)
{
if (!$this->extracted) {
// nothing was extracted, nothing to restore
return $content;
}
$content = strtr($content, $this->extracted);
$this->extracted = array();
return $content;
}
/**
* Check if the path is a regular file and can be read.
*
* @param string $path
*
* @return bool
*/
protected function canImportFile($path)
{
$parsed = parse_url($path);
if (
// file is elsewhere
isset($parsed['host']) ||
// file responds to queries (may change, or need to bypass cache)
isset($parsed['query'])
) {
return false;
}
return strlen($path) < PHP_MAXPATHLEN && @is_file($path) && is_readable($path);
}
/**
* Attempts to open file specified by $path for writing.
*
* @param string $path The path to the file
*
* @return resource Specifier for the target file
*
* @throws IOException
*/
protected function openFileForWriting($path)
{
if (($handler = @fopen($path, 'w')) === false) {
throw new IOException('The file "'.$path.'" could not be opened for writing. Check if PHP has enough permissions.');
}
return $handler;
}
/**
* Attempts to write $content to the file specified by $handler. $path is used for printing exceptions.
*
* @param resource $handler The resource to write to
* @param string $content The content to write
* @param string $path The path to the file (for exception printing only)
*
* @throws IOException
*/
protected function writeToFile($handler, $content, $path = '')
{
if (($result = @fwrite($handler, $content)) === false || ($result < strlen($content))) {
throw new IOException('The file "'.$path.'" could not be written to. Check your disk space and file permissions.');
}
}
}

View File

@@ -0,0 +1,18 @@
Copyright (c) 2015 Matthias Mullie
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@@ -0,0 +1,28 @@
{
"name": "matthiasmullie/path-converter",
"type": "library",
"description": "Relative path converter",
"keywords": ["relative", "path", "converter", "paths"],
"homepage": "http://github.com/matthiasmullie/path-converter",
"license": "MIT",
"authors": [
{
"name": "Matthias Mullie",
"homepage": "http://www.mullie.eu",
"email": "pathconverter@mullie.eu",
"role": "Developer"
}
],
"require": {
"php": ">=5.3.0",
"ext-pcre": "*"
},
"require-dev": {
"phpunit/phpunit": "~4.8"
},
"autoload": {
"psr-4": {
"MatthiasMullie\\PathConverter\\": "src/"
}
}
}

View File

@@ -0,0 +1,196 @@
<?php
namespace MatthiasMullie\PathConverter;
/**
* Convert paths relative from 1 file to another.
*
* E.g.
* ../../images/icon.jpg relative to /css/imports/icons.css
* becomes
* ../images/icon.jpg relative to /css/minified.css
*
* Please report bugs on https://github.com/matthiasmullie/path-converter/issues
*
* @author Matthias Mullie <pathconverter@mullie.eu>
* @copyright Copyright (c) 2015, Matthias Mullie. All rights reserved
* @license MIT License
*/
class Converter implements ConverterInterface
{
/**
* @var string
*/
protected $from;
/**
* @var string
*/
protected $to;
/**
* @param string $from The original base path (directory, not file!)
* @param string $to The new base path (directory, not file!)
* @param string $root Root directory (defaults to `getcwd`)
*/
public function __construct($from, $to, $root = '')
{
$shared = $this->shared($from, $to);
if ($shared === '') {
// when both paths have nothing in common, one of them is probably
// absolute while the other is relative
$root = $root ?: getcwd();
$from = strpos($from, $root) === 0 ? $from : preg_replace('/\/+/', '/', $root.'/'.$from);
$to = strpos($to, $root) === 0 ? $to : preg_replace('/\/+/', '/', $root.'/'.$to);
// or traveling the tree via `..`
// attempt to resolve path, or assume it's fine if it doesn't exist
$from = @realpath($from) ?: $from;
$to = @realpath($to) ?: $to;
}
$from = $this->dirname($from);
$to = $this->dirname($to);
$from = $this->normalize($from);
$to = $this->normalize($to);
$this->from = $from;
$this->to = $to;
}
/**
* Normalize path.
*
* @param string $path
*
* @return string
*/
protected function normalize($path)
{
// deal with different operating systems' directory structure
$path = rtrim(str_replace(DIRECTORY_SEPARATOR, '/', $path), '/');
/*
* Example:
* /home/forkcms/frontend/cache/compiled_templates/../../core/layout/css/../images/img.gif
* to
* /home/forkcms/frontend/core/layout/images/img.gif
*/
do {
$path = preg_replace('/[^\/]+(?<!\.\.)\/\.\.\//', '', $path, -1, $count);
} while ($count);
return $path;
}
/**
* Figure out the shared path of 2 locations.
*
* Example:
* /home/forkcms/frontend/core/layout/images/img.gif
* and
* /home/forkcms/frontend/cache/minified_css
* share
* /home/forkcms/frontend
*
* @param string $path1
* @param string $path2
*
* @return string
*/
protected function shared($path1, $path2)
{
// $path could theoretically be empty (e.g. no path is given), in which
// case it shouldn't expand to array(''), which would compare to one's
// root /
$path1 = $path1 ? explode('/', $path1) : array();
$path2 = $path2 ? explode('/', $path2) : array();
$shared = array();
// compare paths & strip identical ancestors
foreach ($path1 as $i => $chunk) {
if (isset($path2[$i]) && $path1[$i] == $path2[$i]) {
$shared[] = $chunk;
} else {
break;
}
}
return implode('/', $shared);
}
/**
* Convert paths relative from 1 file to another.
*
* E.g.
* ../images/img.gif relative to /home/forkcms/frontend/core/layout/css
* should become:
* ../../core/layout/images/img.gif relative to
* /home/forkcms/frontend/cache/minified_css
*
* @param string $path The relative path that needs to be converted
*
* @return string The new relative path
*/
public function convert($path)
{
// quit early if conversion makes no sense
if ($this->from === $this->to) {
return $path;
}
$path = $this->normalize($path);
// if we're not dealing with a relative path, just return absolute
if (strpos($path, '/') === 0) {
return $path;
}
// normalize paths
$path = $this->normalize($this->from.'/'.$path);
// strip shared ancestor paths
$shared = $this->shared($path, $this->to);
$path = mb_substr($path, mb_strlen($shared));
$to = mb_substr($this->to, mb_strlen($shared));
// add .. for every directory that needs to be traversed to new path
$to = str_repeat('../', count(array_filter(explode('/', $to))));
return $to.ltrim($path, '/');
}
/**
* Attempt to get the directory name from a path.
*
* @param string $path
*
* @return string
*/
protected function dirname($path)
{
if (@is_file($path)) {
return dirname($path);
}
if (@is_dir($path)) {
return rtrim($path, '/');
}
// no known file/dir, start making assumptions
// ends in / = dir
if (mb_substr($path, -1) === '/') {
return rtrim($path, '/');
}
// has a dot in the name, likely a file
if (preg_match('/.*\..*$/', basename($path)) !== 0) {
return dirname($path);
}
// you're on your own here!
return $path;
}
}

View File

@@ -0,0 +1,24 @@
<?php
namespace MatthiasMullie\PathConverter;
/**
* Convert file paths.
*
* Please report bugs on https://github.com/matthiasmullie/path-converter/issues
*
* @author Matthias Mullie <pathconverter@mullie.eu>
* @copyright Copyright (c) 2015, Matthias Mullie. All rights reserved
* @license MIT License
*/
interface ConverterInterface
{
/**
* Convert file paths.
*
* @param string $path The path to be converted
*
* @return string The new path
*/
public function convert($path);
}

View File

@@ -0,0 +1,23 @@
<?php
namespace MatthiasMullie\PathConverter;
/**
* Don't convert paths.
*
* Please report bugs on https://github.com/matthiasmullie/path-converter/issues
*
* @author Matthias Mullie <pathconverter@mullie.eu>
* @copyright Copyright (c) 2015, Matthias Mullie. All rights reserved
* @license MIT License
*/
class NoConverter implements ConverterInterface
{
/**
* {@inheritdoc}
*/
public function convert($path)
{
return $path;
}
}

818
cms/lib/viewer_functions.php Executable file
View File

@@ -0,0 +1,818 @@
<?php
# load modules
$noSessionStart = true; // don't call session start (not needed for viewers)
$libDir = pathinfo(__FILE__, PATHINFO_DIRNAME);
require_once "$libDir/init.php";
// error checking
if (!$SETTINGS['isInstalled']) { die("Error: You must install the program before you can use the viewers."); }
// globals
global $VIEWER_NAME;
global $FORM;
$FORM = $_REQUEST; // eventually we'll migrate from FORM to _REQUEST
global $hashTraducciones;
$hashTraducciones = array();
global $__allowedTranslateFields;
$__allowedTranslateFields = null;
/*
list($records, $details) = getRecords(array(
'tableName' => 'listings', // REQUIRED, error if not specified, tableName is prefixed with $TABLE_PREFIX
'where' => '', // optional, defaults to blank
'orderBy' => '', // optional, defaults to table sort order if undefined
'limit' => '', // optional, defaults to blank
'offset' => '', // optional, defaults to blank (if set but no limit then limit is set to high number as per mysql docs)
'perPage' => '', // optional, number of records to show per page - loads page number from $_REQUEST['page']
'allowSearch' => '', // optional, defaults to yes, adds search info from query string
'requireSearchMatch' => '', // optional, don't show any results unless search keyword submitted and matched
'loadUploads' => '', // optional, defaults to yes, loads upload array into upload field
'loadCreatedBy' => '', // optional, defaults to yes, adds createdBy. fields for created user
'loadListDetails' => '', // optional, defaults to yes, adds $details with prev/next page, etc info
'orWhere' => '', // optional, adding " OR ... " to end of where clause
'useSeoUrls' => false, // optional, use SEO urls, defaults to no
'leftJoin' => array( // Note: leftJoins require you to use fully qualified fieldnames in WHERE and ORDER BY, such as tablename.fieldname
'grocery_aisle' => 'aisleNum', // foreign table => local field (that matches num in foreign field)
'brands' => 'brandNum',
),
'debugSql' => false, // optional, display SQL query, defaults to no
));
*/
require_once dirname(__FILE__)."/classes/CocoParser.php";
require_once dirname(__FILE__)."/classes/CocoDB.php";
require_once dirname(__FILE__)."/classes/CocoEmail.php";
require_once dirname(__FILE__)."/vendor/minifier/autoload.php";
require_once dirname(__FILE__)."/handlers/handler_ws.php";
$configuracionRecord = isset($configuracionRecord) ? $configuracionRecord : CocoDB::get("configuracion",null,null,null,["relationsDepth" => 0])[0];
//Se cambia linea de abajo por llamada a cocodb por no tener datos schema y no poder realizar traducciones en algunos casos - REVISAR
// $configuracionRecord = Db::getInstance()->fetch("SELECT * FROM {$TABLE_PREFIX}configuracion LIMIT 1");
function h($file, $plantilla = true, &$version = null) {
$absolute = strpos($file, 'http') === 0 || strpos($file, '//') === 0;
if ($absolute) return $file;
if ($plantilla) {
$file = substr(RUTA_PLANTILLA_FROM_INIT.$file, 1); // Para quitar el '/' del principio
}
$root = realpath(__DIR__.'/../../');
if (file_exists($root.'/'.$file)) {
$timestamp = filemtime($root.'/'.$file);
}
if (@$timestamp) { // Archivo encontrado y todo ok
if ($version !== null) {
$version += $timestamp;
}
$timestamp = base_convert($timestamp, 10, 36);
// Añadimos -timestamp al final del nombre del archivo
$parts = pathinfo($file);
$carpeta = str_replace($parts['basename'], '', $file);
$path = $carpeta.$parts['filename'].'-hsh'.$timestamp.'.'.$parts['extension'];
return minify_file(@$plantilla ? '/'.$path : $path, $timestamp);
}
return @$plantilla ? '/'.$file : $file;
}
function minify_file($path, $timestamp) {
if (strpos($path, '/') !== 0) return $path;
$root = realpath(__DIR__.'/../../');
$fileType = strtolower(pathinfo($path, PATHINFO_EXTENSION));
$originalFilePath = preg_replace('/-hsh([\w]+)/', '', $path);
$originalFileName = preg_replace('/-hsh([\w]+)/', '', basename($path));
$baseFolder = str_replace($root, '', pathinfo($path, PATHINFO_DIRNAME));
$minifiedDir = $root.$baseFolder.'/minified';
if (!file_exists($minifiedDir)) {
mkdir($minifiedDir);
}
switch ($fileType) {
case 'css':
$minifier = new MatthiasMullie\Minify\CSS($root.$originalFilePath);
break;
case 'js':
$minifier = new MatthiasMullie\Minify\JS($root.$originalFilePath);
break;
default:
return $path;
}
$parts = pathinfo($originalFileName);
$minifiedFileName = $parts['filename'].'-hsh'.$timestamp.'.'.$parts['extension'];
$urlPath = str_replace($root, '', $minifiedDir).'/'.$minifiedFileName;
if (file_exists($minifiedDir.'/'.$originalFileName)) {
// Si el archivo no ha cambiado, lo devolvemos
if (filemtime($minifiedDir.'/'.$originalFileName) >= filemtime($root.$originalFilePath)) {
return $urlPath;
}
}
$minifier->minify($minifiedDir.'/'.$originalFileName);
return $urlPath;
}
function t_var($identificador){
global $TABLE_PREFIX;
// $identifier = strtoupper(CocoParser::parsea_campo2(utf8_encode($identificador))); // SE QUITO PARA PONER LAS TILDES EN ACAI
$identifier = strtoupper(CocoParser::parsea_campo2($identificador)); // ANAEL SE EQUIVOCO
if (defined($identifier)) return constant($identifier);
$DB = Db::getInstance();
$recordtr = $DB->fetch("SELECT * FROM {$TABLE_PREFIX}textos_generales WHERE identificador=? LIMIT 1", [$identifier]);
if (@$recordtr){
$recordtr["tableName"] = "textos_generales";
return t($recordtr, "texto");
}else{
CocoDB::insertRecords('textos_generales', ['identificador' => $identifier, 'texto' => $identificador]);
return t_var($identificador);
}
}
function parsea_texto2($data){
if(!$data) return '';
if (base64_encode(base64_decode($data)) === $data) {
if (mb_detect_encoding(base64_decode($data), 'UTF-8', true)){
return base64_decode($data);
}else{
return $data;
}
}else {
return $data;
}
}
function t($record, $campo = "title", $options = array(), $idioma=null){
global $TABLE_PREFIX, $hashTraducciones,$__allowedTranslateFields;
if (isset($record[$campo]) === false) return null;
if (is_array(@$record[$campo])) return @$record[$campo];
if (!$idioma) $idioma = @$_REQUEST["idioma"];
if(!@$record['num'] || !@$record['tableName'] || !@$idioma) return CocoParser::parsea_codigos_en_linea(@$record[$campo], $options);
if (@$idioma){
if(is_null($__allowedTranslateFields)) {
$__allowedTranslateFields = array_flip(array_map(function($field) {
return $field['fieldName'];
}, mysql_query_fetch_all_assoc("SELECT DISTINCT fieldName FROM {$TABLE_PREFIX}traducciones")));
}
if (!isset($__allowedTranslateFields[$campo]) && isset($record[$campo])) return CocoParser::parsea_codigos_en_linea(parsea_texto2($record[$campo]),$options);
}
$hash = md5(@$record["num"].$campo.@$record["tableName"].$idioma.json_encode(@$_REQUEST));
// Comprobamos si el hash pedido ya está en la tabla
if (@$hashTraducciones[$hash] && @$record['num']) return $hashTraducciones[$hash];
if (@CocoDB::$redis) {
$redisHash = CocoDB::cacheGenerateHash("TRANSLATE-".@$_REQUEST["idioma"].$hash);
if (CocoDB::cacheGet($redisHash)) {
return CocoDB::cacheGet($redisHash);
}
}
$DB = Db::getInstance();
if (@$idioma){
if (@$record["urlPath"] || @$record["info1"]){
$recordtr = $DB->fetch("SELECT fieldValue FROM {$TABLE_PREFIX}traducciones WHERE tableName='uploads' AND recordNum=? AND fieldName=? AND prefix=? AND uploadNum=? LIMIT 1", [$record['recordNum'], $campo, @$idioma, $record['num']]);
}else{
$recordtr = $DB->fetch("SELECT fieldValue FROM {$TABLE_PREFIX}traducciones WHERE tableName=? AND recordNum=? AND fieldName=? AND prefix=? LIMIT 1", [@$record['tableName'], @$record['num'], $campo, @$idioma]);
}
if ($recordtr) {
$trad = CocoParser::parsea_codigos_en_linea(parsea_texto2($recordtr["fieldValue"]),$options);
$hashTraducciones[$hash] = $trad;
if (@CocoDB::$redis) CocoDB::cacheSet($redisHash,$trad);
return $trad;
}
else {
$trad = CocoParser::parsea_codigos_en_linea(@$record[$campo],$options);
$hashTraducciones[$hash] = $trad;
if (@CocoDB::$redis) CocoDB::cacheSet($redisHash,$trad);
return $trad;
}
}else{
$trad = CocoParser::parsea_codigos_en_linea(@$record[$campo],$options);
$hashTraducciones[$hash] = $trad;
if (@CocoDB::$redis) CocoDB::cacheSet($redisHash,$trad);
return $trad;
}
}
function getRecords($options) {
global $VIEWER_NAME, $TABLE_PREFIX;
$VIEWER_NAME = "getRecords(" . @$options['tableName'] . ")";
// error checking
_getRecords_errorChecking($options);
// load schema
$schema = loadSchema($options['tableName']);
if (!$schema) { die("$VIEWER_NAME: Couldn't load schema for '" .htmlspecialchars($options['tableName']). "'!"); }
// set defaults
if (!array_key_exists('orderBy', $options)) { $options['orderBy'] = $schema['listPageOrder']; } // default orderBy to section editor OrderBy value
if (!array_key_exists('loadUploads', $options)) { $options['loadUploads'] = true; }
if (!array_key_exists('allowSearch', $options)) { $options['allowSearch'] = true; }
if (!array_key_exists('requireSearchMatch', $options)) { $options['requireSearchMatch'] = false; }
if (!array_key_exists('loadCreatedBy', $options)) { $options['loadCreatedBy'] = true; }
if (!array_key_exists('loadListDetails', $options)) { $options['loadListDetails'] = true; }
$options['pageNum'] = @$options['pageNum'] ? @$options['pageNum'] : max(@$_REQUEST['page'], 1);
$options['limit'] = @$options['perPage'] ? $options['perPage'] : @$options['limit'];
$options['offset'] = @$options['perPage'] ? (($options['pageNum']-1) * $options['perPage']) + @$options['offset'] : @$options['offset'];
if ($options['offset'] && !$options['limit']) { $options['limit'] = 1000000; } // if offset and no limit set limit to high number as per MySQL docs
// Get records
list($rows, $totalRecords) = _getRecords_loadResults($options, $schema);
// Add uploads
if (@$options['loadUploads']) { _getRecords_addUploadFields($rows, $options, $schema); }
// Add createdBy.fields to records
if (@$options['loadCreatedBy'] && @$schema['createdByUserNum']) { _getRecords_joinTable($rows, $options, 'accounts'); }
// Add joinTable fields
if (@$options['joinTable']) { _getRecords_joinTable($rows, $options); }
// get List Details
$listDetails = array();
if ($options['loadListDetails']) {
$listDetails = _getRecords_getListDetails($options, count($rows), $totalRecords, $schema);
}
//
return array($rows, $listDetails, $schema);
}
//
function _createDefaultWhereWithFormInput($schema, $where) {
global $VIEWER_NAME;
if ($where != "") { return $where; } // don't set default where if it's already been specified
$seenQueries = array();
//
$andConditions = array();
foreach ($_REQUEST as $name => $value) {
if ($value == '') { continue; } // skip fields with empty values
if (!preg_match("/^(.+?)(_min|_max|_match|_keyword|_prefix|_query|)$/", $name, $matches)) { continue; } // skip fields without search suffixes
$fieldnamesAsCSV = $matches[1];
$searchType = $matches[2];
$fieldnames = explode(',',$fieldnamesAsCSV);
$orConditions = array();
foreach ($fieldnames as $fieldnameString) {
// get field value for date searches
if (preg_match("/^(.+?)_(year|month|day)$/", $fieldnameString, $matches)) {
$fieldname = $matches[1];
$dateValue = $matches[2];
if (!is_array(@$schema[$fieldname])) { continue; } // skip invalid fieldnames
if ($dateValue == 'year') { $fieldValue = "YEAR(`$fieldname`)"; }
elseif ($dateValue == 'month') { $fieldValue = "MONTH(`$fieldname`)"; }
elseif ($dateValue == 'day') { $fieldValue = "DAYOFMONTH(`$fieldname`)"; }
else { die("unknown date value '$dateValue'!"); }
}
// get field value for everything else
else {
if (!is_array(@$schema[$fieldnameString])) { continue; } // skip invalid fieldnames
$fieldValue = '`' .str_replace('.', '`.`', $fieldnameString). '`'; // quote bare fields and qualified fieldnames (table.field)
}
// add conditions
$fieldSchema = @$schema[$fieldnameString];
$isMultiList = @$fieldSchema['type'] == 'list' && (@$fieldSchema['listType'] == 'pulldownMulti' || @$fieldSchema['listType'] == 'checkboxes');
$valueAsNumberOnly = preg_replace('/[^\d\.]/', '', $value);
if (!$fieldValue) { die("No fieldValue defined!"); }
if ($searchType == '_min') { $orConditions[] = "$fieldValue+0 >= $valueAsNumberOnly"; }
else if ($searchType == '_max') { $orConditions[] = "$fieldValue+0 <= $valueAsNumberOnly"; }
else if ($searchType == '_match' || $searchType == '') {
if ($isMultiList) { $orConditions[] = "$fieldValue LIKE '%\\t" .mysql_real_escape_string($value). "\\t%'"; }
else { $orConditions[] = "$fieldValue = '" .mysql_real_escape_string($value). "'"; }
}
else if ($searchType == '_keyword') { $orConditions[] = "$fieldValue LIKE '%" .escapeMysqlWildcards(mysql_real_escape_string($value)). "%'"; }
else if ($searchType == '_prefix') { $orConditions[] = "$fieldValue LIKE '" .escapeMysqlWildcards(mysql_real_escape_string($value)). "%'"; }
else if ($searchType == '_query') {
if (@$seenQueries["$fieldnamesAsCSV=$searchType"]++) { continue; } // only add each query once since we're add all fields at once
$orConditions[] = _getWhereForSearchQuery($value, $fieldnames, $schema);
}
else { die($VIEWER_NAME . ": Unknown search type '$searchType'!"); }
}
$condition = join(' OR ', $orConditions);
if ($condition) { $andConditions[] = "($condition)"; }
}
$where = join(" AND ", $andConditions);
return $where;
}
//
function _addWhereConditionsForSpecialFields($schema, $extraConditions) {
$where = "";
$conditions = array();
if ($extraConditions) { array_push($conditions, "($extraConditions)"); }
if (@$schema['hidden']) { array_push($conditions, "hidden = 0"); }
if (@$schema['publishDate']) { array_push($conditions, "publishDate <= NOW()"); }
if (@$schema['removeDate']) {
$thisCondition = "removeDate >= NOW()"; // NULL end date or future end date
if (@$schema['neverRemove']) { $thisCondition .= " OR neverRemove = 1"; } // never expires checked
array_push($conditions, "($thisCondition)");
}
if ($conditions) {
$where = " WHERE " . implode(" AND ", $conditions) . " ";
}
return $where;
}
// return MySQL WHERE clause for google style query: +word -word "multi word phrase"
function _getWhereForSearchQuery($query, $fieldnames, $schema = null) {
// error checking
if (!is_array($fieldnames)) { die(__FUNCTION__ . ": fieldnames must be an array!"); }
// parse out "quoted strings"
$searchTerms = array();
$quotedStringRegexp = "/([+-]?)(['\"])(.*?)\\2/";
preg_match_all($quotedStringRegexp, $query, $matches, PREG_SET_ORDER);
foreach ($matches as $match) {
list(,$plusOrMinus,,$phrase) = $match;
$phrase = trim($phrase);
$searchTerms[$phrase] = $plusOrMinus;
}
$query = preg_replace($quotedStringRegexp, "", $query); // remove quoted strings
// parse out keywords
$keywords = preg_split('/[\\s,;]+/', $query);
foreach ($keywords as $keyword) {
$plusOrMinus = "";
if (preg_match("/^([+-])/", $keyword, $matches)) {
$keyword = preg_replace("/^([+-])/", "", $keyword, 1);
$plusOrMinus = $matches[1];
}
$searchTerms[$keyword] = $plusOrMinus;
}
// create query
$where = "";
$conditions = array();
foreach ($searchTerms as $term => $plusOrMinus) {
if ($term == '') { continue; }
$likeOrNotLike = ($plusOrMinus == '-') ? "NOT LIKE" : "LIKE";
$andOrOr = ($plusOrMinus == '-') ? " AND " : " OR ";
$termConditions = array();
foreach ($fieldnames as $fieldname) {
if ($schema && !is_array(@$schema[$fieldname])) { continue; } // fields are stored as arrays, other entries are table metadata
$fieldname = trim($fieldname);
$escapedKeyword = escapeMysqlWildcards( mysql_real_escape_string($term) );
$quotedFieldname = '`' . str_replace('.', '`.`', $fieldname) . '`';
$termConditions[] = "$quotedFieldname $likeOrNotLike '%$escapedKeyword%'";
}
if ($termConditions) {
$conditions[] = "(" . join($andOrOr, $termConditions) . ")\n";
}
}
//
$where = join(" AND ", $conditions);
return $where;
}
function getFilenameFieldValue($record, $filenameFields) {
global $VIEWER_NAME;
$filenameValue = "";
// convert string to array
if (!is_array($filenameFields)) {
$filenameFields = preg_split("/\s*,\s*/", $filenameFields);
}
// error checking
foreach ($filenameFields as $fieldname) {
if ($fieldname == "") { continue; }
if (!array_key_exists($fieldname, $record)) { die("$VIEWER_NAME: Unknown field '" .htmlspecialchars($fieldname). "' in filenameFields or titleField options!"); }
}
// get first defined field value
foreach ($filenameFields as $fieldname) {
if (@$record[$fieldname] == "") { continue; }
$filenameValue = @$record[$fieldname];
$filenameValue = preg_replace('/[^a-z0-9\.\-\_]+/i', '-', $filenameValue);
$filenameValue = preg_replace("/(^-+|-+$)/", '', $filenameValue); # remove leading and trailing underscores
if ($filenameValue) { $filenameValue .= "-"; }
break;
}
//
return $filenameValue;
}
// return an array of list values
function getListValues($tableName, $fieldName, $fieldValue) {
$array = explode("\t", $fieldValue);
$array = array_slice($array, 1, -1); // remove blanks from leading/trailing tabs
return $array;
}
// return an array of list labels
function getListLabels($tableName, $fieldName, $fieldValue) {
$values = getListValues($tableName, $fieldName, $fieldValue);
// load values to labels
static $valuesToLabels;
if (!@$valuesToLabels[$tableName][$fieldName]) {
$valuesToLabels[$tableName][$fieldName] = getListOptions($tableName, $fieldName);
}
//
$labels = array();
foreach ($values as $value) {
if (@$valuesToLabels[$tableName][$fieldName][$value]) {
array_push($labels, $valuesToLabels[$tableName][$fieldName][$value]);
}
else {
array_push($labels, $value);
}
}
return $labels;
}
//
function _getRecords_errorChecking($options) {
global $VIEWER_NAME;
### error checking
$errors = "";
if (!is_array($options)) { $errors .= "First argument for getRecords() must be an array!<br/>\n"; }
elseif (!@$options['tableName']) { $errors .= "No 'tableName' value specified in options!<br/>\n"; }
// check for unknown options!
$validOptions = array('tableName', 'where', 'orWhere', 'orderBy', 'limit', 'offset', 'perPage', 'loadUploads', 'allowSearch', 'requireSearchMatch', 'loadCreatedBy', 'useSeoUrls', 'loadListDetails', 'joinTable', 'debugSql', 'leftJoin');
foreach (array_keys($options) as $optionName) {
if (!in_array($optionName, $validOptions)) {
$validOptionsAsCSV = implode(', ', $validOptions);
$errors .= "Unknown option '$optionName' specified. Valid option names are: ($validOptionsAsCSV)<br/>\n";
}
}
//
if (@$options['perPage'] && (@$options['limit'] || @$options['offset'])) {
$errors .= "Can't set both 'perPage' and 'limit' or 'offset' options at the same time, choose one!<br/>\n";
}
//
if ($errors) { die("$VIEWER_NAME errors<br/>\n$errors"); }
}
//
function _getRecords_loadResults($options, $schema) {
global $VIEWER_NAME, $TABLE_PREFIX;
// create fieldlist
$selectFields = "`{$options['tableName']}`.*";
// add left joins
$LEFT_JOIN = "";
if (@$options['leftJoin']) {
// Fix $_REQUEST keys containing tablename
__replaceUnderscoresInRequest($options['tableName']);
// add qualified fieldsnames to schema
foreach (array_keys(getSchemaFields($schema)) as $fieldname) {
$schema["{$options['tableName']}.$fieldname"] = $schema[$fieldname];
$schema["{$options['tableName']}.$fieldname"]['name'] = $fieldname;
}
//
foreach ($options['leftJoin'] as $foreignTable => $foreignKey) {
// get ON condition
if (preg_match("/\s*ON\b/i", $foreignKey)) { $ON_CONDITION = $foreignKey; }
else {
$ON_CONDITION = "ON {$options['tableName']}.`$foreignKey` = $foreignTable.num\n";
}
// add left join
$LEFT_JOIN .= "LEFT JOIN `{$TABLE_PREFIX}{$foreignTable}` AS `$foreignTable` $ON_CONDITION";
// add fieldnames to SELECT
$foreignSchemaFields = getSchemaFields($foreignTable);
$validFieldTypes = array('textfield','textbox','wysiwyg','date','list','checkbox');
foreach (array_keys($foreignSchemaFields) as $fieldname) {
if (in_array(@$foreignSchemaFields[$fieldname]['type'], $validFieldTypes)) {
$selectFields .= ",\n $foreignTable.`$fieldname` as `$foreignTable.$fieldname`";
}
// Fix $_REQUEST keys containing tablename
__replaceUnderscoresInRequest($foreignTable);
// add fieldnames to schema
$schema["{$foreignTable}.$fieldname"] = $foreignSchemaFields[$fieldname];
$schema["{$foreignTable}.$fieldname"]['name'] = $fieldname;
}
}
}
// create where
$where = @$options['where'];
if ($options['allowSearch']) {
$defaultWhere = _createDefaultWhereWithFormInput($schema, '');
if ($options['requireSearchMatch'] && !$defaultWhere) { $defaultWhere = "0 = 1"; } // always false
if (!$where) { $where = $defaultWhere; }
elseif ($where && $defaultWhere) { $where = "$where AND $defaultWhere"; }
}
if (@$schema['createdByUserNum'] && @$schema['_hideRecordsFromDisabledAccounts']) {
if ($where) { $where .= " AND "; }
$subquery = "SELECT num FROM `{$TABLE_PREFIX}accounts` WHERE disabled != 1 AND (expiresDate > NOW() OR neverExpires = 1)";
$where .= "{$options['tableName']}.createdByUserNum IN ($subquery)";
}
$where = _addWhereConditionsForSpecialFields($schema, $where); // adds WHERE to beginning of string, do this LAST
if (@$options['orWhere']) {
$where = preg_replace("/^\s*WHERE\s*/i", "", $where); // remove WHERE keyword
if ($where) { $where = "($where) OR {$options['orWhere']}"; }
else { $where = $options['orWhere']; }
if ($where) { $where = "\nWHERE $where"; }
}
// create query
$query = "SELECT SQL_CALC_FOUND_ROWS $selectFields\n";
$query .= "FROM `$TABLE_PREFIX{$options['tableName']}` as `{$options['tableName']}`\n";
$query .= $LEFT_JOIN;
$query .= "$where\n";
$query .= (@$options['orderBy']) ? " ORDER BY {$options['orderBy']}" : "";
if (@$options['limit']) { $query .= "\n LIMIT " . (int) $options['limit']; }
if (@$options['offset']) { $query .= "\nOFFSET " . (int) $options['offset']; }
if (@$options['debugSql']) { print "<xmp>$query</xmp>"; }
// execute query
$result = mysql_query($query) or die("$VIEWER_NAME MySQL Error: ". htmlspecialchars(mysql_error()) . "\n");
$records = array();
while ($record = mysql_fetch_assoc($result)) {
$filenameValue = getFilenameFieldValue($record, @$schema['_filenameFields']);
$record['_filename'] = rtrim($filenameValue, '-');
$record['tableName'] = @$options['tableName'];
if (@!$schema['_detailPage']) { $record['_link'] = "javascript:alert('Set Detail Page Url for this section in: Admin > Section Editors > Viewer Urls')"; }
elseif(@$options['useSeoUrls']) { $record['_link'] = @$schema['_detailPage'] . '/' . $filenameValue . $record['num'] . "/"; }
else { $record['_link'] = @$schema['_detailPage'] . '?' . $filenameValue . $record['num']; }
array_push($records, $record);
}
if (is_resource($result)) { mysql_free_result($result); }
// modify field values
foreach ($schema as $fieldname => $fieldSchema) {
if (!is_array($fieldSchema)) { continue; } // fields are stored as arrays, other entries are table metadata
// assign checkbox values
if (@$fieldSchema['type'] != 'checkbox') {
if (array_key_exists('checkedValue', $fieldSchema)) { // skip checkbox fields without checked/unchecked values
foreach (array_keys($records) as $index) {
$record = &$records[$index];
$record[$fieldname] = $record[$fieldname] ? $fieldSchema['checkedValue'] : $fieldSchema['uncheckedValue'];
}
}
}
}
// get record count
$totalRecords = (int) mysql_select_found_rows();
//
return array($records, $totalRecords);
}
// Fix $_REQUEST keys. Reference: PHP replaces dots with underscores: https://ca.php.net/variables.external#Dots_in_incoming_variable_names
// Note: We're doing this here because we have the foreign table names, it's used in _createDefaultWhereWithFormInput()
function __replaceUnderscoresInRequest($tablename) {
foreach ($_REQUEST as $key => $value) {
$newKey = preg_replace("/^($tablename)_/", '\1.', $key);
if ($newKey != $key) {
$_REQUEST[$newKey] = $_REQUEST[$key];
# unset($_REQUEST[$key]); // unset original
}
}
}
//
function _getRecords_joinTable(&$rows, $options, $joinTable = '') {
global $VIEWER_NAME, $TABLE_PREFIX;
$joinTable = $joinTable ? $joinTable : $options['joinTable'];
$isAccounts = ($joinTable == 'accounts');
$joinFieldA = 'createdByUserNum';
$joinFieldB = $isAccounts ? 'num' : 'createdByUserNum';
// get fieldA values as CSV
$fieldAValues = array();
foreach ($rows as $row) {
if ($row[$joinFieldA]) { $fieldAValues[] = $row[$joinFieldA]; }
}
$fieldAValues = array_unique($fieldAValues);
if (!$fieldAValues) { return; }
$fieldAValuesAsCSV = implode(',', $fieldAValues);
// load rows
list($joinrows,,$schema) = getRecords(array(
'tableName' => $joinTable,
'where' => "`$joinFieldB` IN ($fieldAValuesAsCSV)",
'loadUploads' => $options['loadUploads'],
'allowSearch' => false,
'loadCreatedBy' => false,
'loadListDetails' => false,
'useSeoUrls' => @$options['useSeoUrls'],
'debugSql' => @$options['debugSql'],
));
// get join rows by num
$joinRowsByNum = array();
foreach ($joinrows as $record) {
$joinRowsByNum[ $record[$joinFieldB] ] = $record;
}
// get tableBfields
$joinTableFields = array();
foreach ($schema as $fieldname => $fieldSchema) {
if (!is_array($fieldSchema)) { continue; }
if (@$fieldSchema['type'] == 'separator') { continue; }
$joinTableFields[] = $fieldname;
}
$joinTableFields[] = "_filename";
$joinTableFields[] = "_link";
// add tableB rows
$fieldnamePrefix = $isAccounts ? 'createdBy' : $joinTable;
foreach (array_keys($rows) as $index) {
$record = &$rows[$index];
$joinRecord = @$joinRowsByNum[$record[$joinFieldA]];
foreach ($joinTableFields as $fieldname) {
if ($isAccounts && $fieldname == 'password') { continue; }
$record["$fieldnamePrefix.$fieldname"] = @$joinRecord[$fieldname];
}
}
}
//
function _getRecords_addUploadFields(&$rows, $options, $schema) {
global $VIEWER_NAME, $TABLE_PREFIX;
if (@!$options['loadUploads']) { return; }
// get recordNums
$recordNums = array();
foreach ($rows as $record) {
if (@$record['num']) { $recordNums[] = $record['num']; }
}
if (!$recordNums) { return; }
// get upload fields
$uploadFields = array();
$uploadFieldsAsCSV = "";
foreach ($schema as $fieldname => $fieldSchema) {
if (!is_array($fieldSchema)) { continue; } // fields are stored as arrays, other entries are table metadata, skip metadata
if (@$fieldSchema['type'] != 'upload') { continue; } // skip all but upload fields
if ($uploadFieldsAsCSV) { $uploadFieldsAsCSV .= ","; }
$uploadFields[] = $fieldname;
$uploadFieldsAsCSV .= "'$fieldname'";
}
// load uploads
$uploadsByNumAndField = array();
$recordNumsAsCSV = implode(',', $recordNums);
if ($recordNumsAsCSV && $uploadFieldsAsCSV) {
$query = "SELECT * FROM `{$TABLE_PREFIX}uploads`\n";
$query .= " WHERE tableName = '" .mysql_real_escape_string($options['tableName']). "' AND\n";
$query .= " fieldName IN ($uploadFieldsAsCSV) AND\n";
$query .= " recordNum IN ($recordNumsAsCSV)\n";
$query .= " ORDER BY `order`, num";
if (@$options['debugSql']) { print "<xmp>$query</xmp>"; }
$result = mysql_query($query) or die("MySQL Error: ". htmlspecialchars(mysql_error()) . "\n");
while ($record = mysql_fetch_assoc($result)) {
$record['filename'] = pathinfo($record['filePath'], PATHINFO_BASENAME);
$record['extension'] = pathinfo($record['filePath'], PATHINFO_EXTENSION);
$record['isImage'] = preg_match("/\.(gif|jpg|jpeg|png)$/i", $record['filePath']);
$record['hasThumbnail'] = $record['isImage'] && $record['thumbUrlPath'];
$uploadsByNumAndField[$record['recordNum']][$record['fieldName']][] = $record;
}
if (is_resource($result)) { mysql_free_result($result); }
}
// add uploads to records
foreach (array_keys($rows) as $index) {
$record = &$rows[$index];
foreach ($uploadFields as $fieldname) {
$record[$fieldname] = array();
$uploadsArray = @$uploadsByNumAndField[$record['num']][$fieldname];
if ($uploadsArray) { $record[$fieldname] = $uploadsArray; }
}
}
}
//
function _getRecords_getListDetails($options, $rowCount, $totalRecords, $schema) {
global $VIEWER_NAME;
$details = array();
### get list details
$details = array();
$details['invalidPageNum'] = !$rowCount && $options['pageNum'] > 1;
$details['noRecordsFound'] = !$rowCount && $options['pageNum'] == 1;
$details['page'] = $options['pageNum'];
$details['perPage'] = @$options['perPage'];
$details['totalPages'] = 1;
if (@$options['perPage'] && $totalRecords > $options['perPage']) {
$details['totalPages'] = ceil($totalRecords / $options['perPage']);
}
$details['totalRecords'] = $totalRecords;
$details['pageResultsStart'] = min($totalRecords, $options['offset'] + 1);
$details['pageResultsEnd'] = min($totalRecords, $options['offset'] + $options['limit']);
# get page nums
$_minOfPageNumAndTotalPages = min($options['pageNum'], $details['totalPages']);
$details['prevPage'] = ($_minOfPageNumAndTotalPages > 1) ? $_minOfPageNumAndTotalPages-1 : '';
$details['nextPage'] = ($_minOfPageNumAndTotalPages < $details['totalPages']) ? $_minOfPageNumAndTotalPages+1 : '';
if ($details['invalidPageNum']) {
$details['prevPage'] = $details['totalPages'];
}
# pass query arguments forward in page links
$extraQueryArgs = "";
$extraPathInfoArgs = "";
foreach ($_REQUEST as $key => $value) {
if (!is_array($key) && !is_array($value) && !is_null($value)){
if ($key == 'page') { continue; } // skip page value, we set it below
$extraQueryArgs .= urlencode($key) .'='. urlencode($value) . '&';
$extraPathInfoArgs .= urlencode($key) .'-'. urlencode($value) . '/';
}
}
# get page links
$listViewer = $_SERVER['SCRIPT_NAME'];
if (@$options['useSeoUrls']) {
$details['prevPageLink'] = "$listViewer/{$extraPathInfoArgs}page-{$details['prevPage']}/";
$details['nextPageLink'] = "$listViewer/{$extraPathInfoArgs}page-{$details['nextPage']}/";
$details['firstPageLink'] = "$listViewer/{$extraPathInfoArgs}page-1/";
$details['lastPageLink'] = "$listViewer/{$extraPathInfoArgs}page-{$details['totalPages']}/";
}
else {
$details['prevPageLink'] = "$listViewer?{$extraQueryArgs}page={$details['prevPage']}";
$details['nextPageLink'] = "$listViewer?{$extraQueryArgs}page={$details['nextPage']}";
$details['firstPageLink'] = "$listViewer?{$extraQueryArgs}page=1";
$details['lastPageLink'] = "$listViewer?{$extraQueryArgs}page=" . $details['totalPages'];
}
//
$details['_detailPage'] = @$schema['_detailPage'];
$details['_listPage'] = @$schema['_listPage'] ? $schema['_listPage'] : "javascript:alert('Set List Page Url for this section in: Admin > Section Editors > Viewer Urls')"; ;
return $details;
}

29
cms/robots.php Executable file
View File

@@ -0,0 +1,29 @@
<?php
require_once __DIR__."/../sesion.php";
require_once __DIR__."/../funciones.php";
if (!function_exists("protocol")) {
function protocol() {
return _isHTTPS() ? "https" : "http";
}
function _isHTTPS() {
return (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') || $_SERVER['SERVER_PORT'] == 443;
}
}
header('Content-Type: text/plain');
$filePath = __DIR__."/../robots.txt";
if (file_exists($filePath)) {
echo file_get_contents($filePath);
die();
}
?>
# <?=strtoupper($configuracionRecord["tienda_nombre_empresa"]);?>
User-agent: *
<? if (strpos($_SERVER["HTTP_HOST"], "plandeweb.com")) {?>
Disallow: /
<? }?>
<? if (@$configuracionRecord['pagina_publicada']) {?>
# SITEMAP
Sitemap: <?=protocol();?>://<?=$_SERVER["HTTP_HOST"];?>/sitemap.xml
<? }?>

133
cms/sitemap.php Executable file
View File

@@ -0,0 +1,133 @@
<?
require_once dirname(__FILE__)."/../sesion.php";
require_once dirname(__FILE__)."/../funciones.php";
if (!@$configuracionRecord['pagina_publicada'] && !@$_REQUEST['dev']) {
http_response_code(404);
die();
}
$dummy = [];
addPlugins('sitemap', $dummy);
$tablasEliminadas = array("cms_alias_urls");
$sql = "
SELECT DISTINCT TABLE_NAME,COLUMN_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE COLUMN_NAME IN ('enlace')
AND TABLE_SCHEMA='".$SETTINGS["mysql"]["database"]."'
";
$result = mysql_query($sql) or die(mysql_error());
$resultados = array();
$enlaces = array();
$idiomas = array();
while($record = mysql_fetch_assoc($result)){
if (!in_array($record["TABLE_NAME"],$tablasEliminadas)){
$res = mysql_query("SELECT * FROM ".$record["TABLE_NAME"]);
while($rec = mysql_fetch_assoc($res)){
$enlaceAnadido = false;
if (@$rec['no_indexar_en_google']) continue;
if ((isset($rec["visible"]) || isset($rec["oculto"])) && @$rec[$record["COLUMN_NAME"]]) {
if ((@$rec["visible"]==1 || isset($rec["oculto"]) && !$rec["oculto"]) && !strpos("a".$rec[$record["COLUMN_NAME"]],"#")) {
if (compruebaWeb(@$rec[$record["COLUMN_NAME"]])){
$enlaces[$record["TABLE_NAME"]."-".$record["COLUMN_NAME"]."-".$rec["num"]][] = @$rec[$record["COLUMN_NAME"]];
$idiomas[$record["TABLE_NAME"]."-".$record["COLUMN_NAME"]."-".$rec["num"]][] = "es";
$fechas[$record["TABLE_NAME"]."-".$record["COLUMN_NAME"]."-".$rec["num"]][] = @$rec["updatedDate"];
$enlaceAnadido = true;
}
}
}else if (@$rec[$record["COLUMN_NAME"]]){
if (!strpos("a".$rec[$record["COLUMN_NAME"]],"#")){
if (compruebaWeb(@$rec[$record["COLUMN_NAME"]])){
$enlaces[$record["TABLE_NAME"]."-".$record["COLUMN_NAME"]."-".$rec["num"]][] = @$rec[$record["COLUMN_NAME"]];
$idiomas[$record["TABLE_NAME"]."-".$record["COLUMN_NAME"]."-".$rec["num"]][] = "es";
$fechas[$record["TABLE_NAME"]."-".$record["COLUMN_NAME"]."-".$rec["num"]][] = @$rec["updatedDate"];
$enlaceAnadido = true;
}
}
}
if ($enlaceAnadido){
$enlaces = dameEnlacesIdiomas($enlaces,$record,$rec);
}
}
}
}
function compruebaWeb($enlace){
return 1;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, protocol()."://".$_SERVER["HTTP_HOST"].$enlace);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$respond = curl_exec ($ch);
curl_close ($ch);
//$wget = file_get_contents(protocol()."://".$_SERVER["HTTP_HOST"].$enlace);
return $respond;
}
function dameEnlacesIdiomas($enlaces,$schema,$record){
global $TABLE_PREFIX,$idiomas;
$sql = "SELECT prefix,fieldValue FROM ".$TABLE_PREFIX."traducciones where tableName='".str_replace($TABLE_PREFIX,"",$schema["TABLE_NAME"])."' and recordNum='".$record["num"]."' and fieldName='".$schema["COLUMN_NAME"]."'";
$res = mysql_query($sql);
if (@$res){
while($rec = mysql_fetch_assoc($res)){
if (compruebaWeb(base64_decode($rec["fieldValue"]))){
$idiomas[$schema["TABLE_NAME"]."-".$schema["COLUMN_NAME"]."-".$record["num"]][] = $rec["prefix"];
$enlaces[$schema["TABLE_NAME"]."-".$schema["COLUMN_NAME"]."-".$record["num"]][] = base64_decode($rec["fieldValue"]);
}
}
}
return $enlaces;
}
/*
echo "<pre>";
print_r($fechas);
echo "</pre>";
die();*/
header("Content-type: text/xml");
echo '<?xml version="1.0" encoding="UTF-8"?><urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:xhtml="http://www.w3.org/1999/xhtml">';
foreach($enlaces as $key => $valores):
foreach($valores as $cont => $valor):
echo "<url>";
echo "<loc>".protocol()."://".$_SERVER["HTTP_HOST"].$valor."</loc>";
echo '<lastmod>'.date("Y-m-d",strtotime($fechas[$key][0])).'T'.date("H:i:s",strtotime($fechas[$key][0])).'+00:00</lastmod>';
foreach($valores as $cont2 => $valor2):
if ($cont2!=$cont){
echo '<xhtml:link rel="alternate" hreflang="'.$idiomas[$key][$cont2].'" href="'.protocol()."://".$_SERVER["HTTP_HOST"].$valor2.'"/>';
//echo "<link>".$idiomas[$key][$cont2]."</link>";
}
endforeach;
echo '<changefreq>monthly</changefreq>';
echo "</url>";
endforeach;
/*if (@$idiomas[$cont]!="es"){
echo '<xhtml:link rel="alternate" hreflang="de" href="'.$enlace.'"/>';
}else{
echo "<loc>".$enlace."</loc>";
}*/
endforeach;
echo '</urlset>';
die();
?>
<script>
/*var listas = document.querySelectorAll("li");
for (i=0;i<listas.length;i++){
fetch('https://top-car-hire.com' + listas[i].innerHTML).then(function(response) {
response.text().then(function(str){
if (response.status==200){
str = str.toLowerCase();
if (str.indexOf("undefined ")!=-1){
console.log("UNDEFINED EN " + response.url);
}
}else{
console.log("ERROR EN " + response.url);
}
});
}).then(function(str) {
});
}*/
</script>

14
footer.php Executable file
View File

@@ -0,0 +1,14 @@
<?
$otros_contenidos = CocoDB::get("otros_contenidos", "visible_en_el_menu=1", "siblingOrder DESC", null, ["ignoreSchema" => true]);
$config_footer = array(
'pie_de_pagina' => t($configuracionRecord,"pie_de_pagina"),
'configuracionRecord' => @$configuracionRecord,
'configuracionTienda' => @$configuracionTienda,
'thisrecord' => @$apartado,
'index' => @$index,
'otros_contenidos' => $otros_contenidos,
'apartadoCesta' => @$apartadoCesta
);
if (@$customCode) echo modulo('custom-footer',$config_footer); else echo tpl('pie',$config_footer);

223
funciones.php Executable file
View File

@@ -0,0 +1,223 @@
<?
require_once CMS_VIEWER_LIB;
// VARIABLES RELACIONADAS CON LA EXTRACCION DE CSS
$contadorImagenes = 0;
$modulosCargados = array();
$recursosCSS = array();
// HASTA AUQI
if (!file_exists(__DIR__.'/'.CMS_FOLDER.'/uploads/webp/')) {
mkdir(__DIR__.'/'.CMS_FOLDER.'/uploads/webp/');
}
global $configuracionTienda;
$configuracionRecord = CocoDB::get("configuracion", "", null, 1);
$configuracionRecord = @$configuracionRecord[0];
$configuracionTienda = CocoDB::get("configuracion_tienda", "", null, 1);
$configuracionTienda = @$configuracionTienda[0];
define("HAY_TIENDA", @$configuracionTienda["tienda_activa"]);
if (@$configuracionRecord["pagina_publicada"] && !@$_SESSION["pruebas"]) error_reporting(0);
// COMPROBAMOS SI HAY CUSTOM HEADER Y FOOTER Y ACTIVAMOS LA VARIABLE
// ARCHIVOS AFECTADOS : header.php - footer.php - funciones.php - htaccess
$layoutFile = __DIR__."/".CMS_FOLDER."/lib/plugins/builder_saas/layout.json";
if (file_exists($layoutFile)){
$layoutJson = json_decode(file_get_contents($layoutFile),true);
if (@$layoutJson["active"]){
global $customCode;
$customCode = true;
}
}
/******** NUEVAS FUNCIONES ********/
function dame_alternates($link) {
global $SETTINGS, $TABLE_PREFIX,$tabla, $num;
$enlaces = array();
$idiomasPermitidos = array_filter(array_map(function($idioma) {
return str_replace("/", "", $idioma["valor"]);
}, dame_idiomas()));
if (!@$tabla) return [];
$encontrado = mysql_fetch_assoc(mysql_query("SELECT * FROM ".$tabla." WHERE num=".$num." limit 1"));
if (@$encontrado) $encontrado["tableName"] = str_replace($TABLE_PREFIX,"",$tabla);
if (!@$encontrado["num"]) return $enlaces;
$enlaces[] = array(
"prefix" => "es",
"fieldValue" => base64_encode($encontrado["enlace"])
);
$sql = mysql_query("SELECT * FROM ".$TABLE_PREFIX."traducciones WHERE fieldName='enlace' AND prefix IN('".join("','", $idiomasPermitidos)."') AND tableName='".$encontrado["tableName"]."' AND recordNum=".$encontrado["num"]);
while ($row = mysql_fetch_assoc($sql)) {
$enlaces[] = $row;
}
return $enlaces;
}
/******** FIN NUEVAS FUNCIONES ********/
function hasRecaptcha() {
global $configuracionRecord;
return @$configuracionRecord["site_key_recaptcha"] && @$configuracionRecord["secret_key_recaptcha"];
}
function dame_registros($tabla,$where="",$order="",$limit=1000,$depth=0){
global $TABLE_PREFIX;
list($configuracionRecords, $configuracionMetaData,$schema) = getRecords(array(
'tableName' => $tabla,
'where' => $where,
'allowSearch' => 0,
'orderBy' => $order,
'limit' => $limit
));
/*
EXPERIMENTAL - EN DESARROLLO
*/
foreach ($configuracionRecords as $index => $record) {
if (@$schema["menuType"] == "category"){
$configuracionRecords[$index]["childs"] = mysql_num_rows(mysql_query("SELECT * FROM ".$TABLE_PREFIX.$tabla." WHERE parentNum=".$record["num"]));
}
foreach ($record as $key => $value) {
if (!isset($schema[$key]["type"]) || !is_array($schema[$key])) continue;
switch (@$schema[$key]["type"]) {
case "list":
if (@$schema[$key]["optionsType"] == "table") {
$nums = array_filter(explode("\t", $value ?? ''));
if (@$nums && !$depth) {
$newSchema = loadSchema($schema[$key]["optionsTablename"]);
if (@$newSchema["dragSortOrder"]) $order = "dragSortOrder DESC";
if (@$newSchema["siblingOrder"]) $order = "siblingOrder ASC";
if (!@$order) $order = "num DESC";
$newRecord = dame_registros($schema[$key]["optionsTablename"], $schema[$key]["optionsValueField"]." IN (".join(",", $nums).")", $order,1000,1);
$configuracionRecords[$index][$key."_bd"] = $newRecord;
}else {
$configuracionRecords[$index][$key."_bd"] = array();
}
}else{
$configuracionRecords[$index][$key."_bd"] = array();
}
break;
case "multitext":
$result = (@$value) ? json_decode(t($record, $key), true) : array();
$configuracionRecords[$index][$key."_bd"] = $result;
break;
case "textfield":
if (@$schema[$key]["tipoTags"]) {
$tags = array_filter(explode(",", $value));
$configuracionRecords[$index][$key."_bd"] = $tags;
}
break;
default:
break;
}
}
$configuracionRecords[$index]["breadcrumbField"] = @$schema["breadcrumbField"];
// Si es parentNum ponemos valores por defecto
if (@$configuracionRecords[$index]["breadcrumbField"] == "parentNum") {
$configuracionRecords[$index]["optionsTablename"] = $configuracionRecords[$index]["tableName"];
$configuracionRecords[$index]["optionsValueField"] = "num";
} else if (@$configuracionRecords[$index]["breadcrumbField"]) {
// Si no es parentNum, ponemos los que dicte el schema
$configuracionRecords[$index]["optionsTablename"] = @$schema[$schema["breadcrumbField"]]["optionsTablename"];
$configuracionRecords[$index]["optionsValueField"] = @$schema[$schema["breadcrumbField"]]["optionsValueField"];
}
// Para el campo principal (para la generación de enlaces y el breadcrumb)
if (@$record["name"]) {
$configuracionRecords[$index]["mainFieldBreadcrumb"] = t($record, "name");
}
else if (@$record["title"]) {
$configuracionRecords[$index]["mainFieldBreadcrumb"] = t($record, "title");
}
else if (@$record["titulo"]) {
$configuracionRecords[$index]["mainFieldBreadcrumb"] = t($record, "titulo");
}
else if (@$record["nombre"]) {
$configuracionRecords[$index]["mainFieldBreadcrumb"] = t($record, "nombre");
}
else {
foreach ($schema as $key => $value):
if (!is_array($value)) continue;
if (@$value["type"] == "textfield" && $key != "enlace") {
$configuracionRecords[$index]["mainFieldBreadcrumb"] = t($record, $key);
break;
}
endforeach;
}
}
if ($configuracionRecords) {
return $configuracionRecords;
}else {
return array();
}
}
function dame_idiomas(){
$array_ini = parse_ini_file($_SERVER["DOCUMENT_ROOT"]."/".CMS_FOLDER."/data/settings.dat.php", true);
$resultado = array();
if (@$array_ini["idiomas"]){
foreach ($array_ini["idiomas"] as $idioma => $valor):
if ($valor!=""){
if ($valor=="www") $valor=""; else $valor="/".$valor;
if ($idioma=="espanol") $idioma="Español";
if ($idioma=="ingles") $idioma ="Inglés";
if ($idioma=="aleman") $idioma="Alemán";
if ($idioma=="frances") $idioma ="Francés";
if ($idioma=="portugues") $idioma ="Portugués";
if ($idioma=="catalan") $idioma ="Catalán";
if ($idioma=="italiano") $idioma ="Italiano";
if ($idioma=="koreano") $idioma ="Koreano";
if ($idioma=="chino") $idioma ="Chino";
if ($idioma=="noruego") $idioma ="Noruego";
if ($idioma=="ruso") $idioma ="Ruso";
if ($idioma=="nigeriano") $idioma ="Nigeriano";
array_push($resultado,array("idioma" => $idioma,"valor" => $valor));
}
endforeach;
}
return $resultado;
}
function tpl($p,$d=array()){
global $configuracionRecord,$recursosCSS,$SETTINGS;
extract($d);
ob_start();
$doc = new domdocument();
require("./".PLANTILLA."/".$p.'.tpl');
$resultado = ob_get_clean();
return minify_html($resultado);
}
function modulo($p,$d=array()){
return Module::load($p, $d);
}
// Parsea enlace definitivo
function parsea_enlace($txt) {
$transliterationTable = array('á' => 'a', 'Á' => 'A', 'à' => 'a', 'À' => 'A', 'ă' => 'a', 'Ă' => 'A', 'â' => 'a', 'Â' => 'A', 'å' => 'a', 'Å' => 'A', 'ã' => 'a', 'Ã' => 'A', 'ą' => 'a', 'Ą' => 'A', 'ā' => 'a', 'Ā' => 'A', 'ä' => 'a', 'Ä' => 'A', 'æ' => 'ae', 'Æ' => 'AE', 'ḃ' => 'b', 'Ḃ' => 'B', 'ć' => 'c', 'Ć' => 'C', 'ĉ' => 'c', 'Ĉ' => 'C', 'č' => 'c', 'Č' => 'C', 'ċ' => 'c', 'Ċ' => 'C', 'ç' => 'c', 'Ç' => 'C', 'ď' => 'd', 'Ď' => 'D', 'ḋ' => 'd', 'Ḋ' => 'D', 'đ' => 'd', 'Đ' => 'D', 'ð' => 'dh', 'Ð' => 'Dh', 'é' => 'e', 'É' => 'E', 'è' => 'e', 'È' => 'E', 'ĕ' => 'e', 'Ĕ' => 'E', 'ê' => 'e', 'Ê' => 'E', 'ě' => 'e', 'Ě' => 'E', 'ë' => 'e', 'Ë' => 'E', 'ė' => 'e', 'Ė' => 'E', 'ę' => 'e', 'Ę' => 'E', 'ē' => 'e', 'Ē' => 'E', 'ḟ' => 'f', 'Ḟ' => 'F', 'ƒ' => 'f', 'Ƒ' => 'F', 'ğ' => 'g', 'Ğ' => 'G', 'ĝ' => 'g', 'Ĝ' => 'G', 'ġ' => 'g', 'Ġ' => 'G', 'ģ' => 'g', 'Ģ' => 'G', 'ĥ' => 'h', 'Ĥ' => 'H', 'ħ' => 'h', 'Ħ' => 'H', 'í' => 'i', 'Í' => 'I', 'ì' => 'i', 'Ì' => 'I', 'î' => 'i', 'Î' => 'I', 'ï' => 'i', 'Ï' => 'I', 'ĩ' => 'i', 'Ĩ' => 'I', 'į' => 'i', 'Į' => 'I', 'ī' => 'i', 'Ī' => 'I', 'ĵ' => 'j', 'Ĵ' => 'J', 'ķ' => 'k', 'Ķ' => 'K', 'ĺ' => 'l', 'Ĺ' => 'L', 'ľ' => 'l', 'Ľ' => 'L', 'ļ' => 'l', 'Ļ' => 'L', 'ł' => 'l', 'Ł' => 'L', 'ṁ' => 'm', 'Ṁ' => 'M', 'ń' => 'n', 'Ń' => 'N', 'ň' => 'n', 'Ň' => 'N', 'ñ' => 'n', 'Ñ' => 'N', 'ņ' => 'n', 'Ņ' => 'N', 'ó' => 'o', 'Ó' => 'O', 'ò' => 'o', 'Ò' => 'O', 'ô' => 'o', 'Ô' => 'O', 'ő' => 'o', 'Ő' => 'O', 'õ' => 'o', 'Õ' => 'O', 'ø' => 'o', 'Ø' => 'O', 'ō' => 'o', 'Ō' => 'O', 'ơ' => 'o', 'Ơ' => 'O', 'ö' => 'o', 'Ö' => 'O', 'ṗ' => 'p', 'Ṗ' => 'P', 'ŕ' => 'r', 'Ŕ' => 'R', 'ř' => 'r', 'Ř' => 'R', 'ŗ' => 'r', 'Ŗ' => 'R', 'ś' => 's', 'Ś' => 'S', 'ŝ' => 's', 'Ŝ' => 'S', 'š' => 's', 'Š' => 'S', 'ṡ' => 's', 'Ṡ' => 'S', 'ş' => 's', 'Ş' => 'S', 'ș' => 's', 'Ș' => 'S', 'ß' => 'SS', 'ť' => 't', 'Ť' => 'T', 'ṫ' => 't', 'Ṫ' => 'T', 'ţ' => 't', 'Ţ' => 'T', 'ț' => 't', 'Ț' => 'T', 'ŧ' => 't', 'Ŧ' => 'T', 'ú' => 'u', 'Ú' => 'U', 'ù' => 'u', 'Ù' => 'U', 'ŭ' => 'u', 'Ŭ' => 'U', 'û' => 'u', 'Û' => 'U', 'ů' => 'u', 'Ů' => 'U', 'ű' => 'u', 'Ű' => 'U', 'ũ' => 'u', 'Ũ' => 'U', 'ų' => 'u', 'Ų' => 'U', 'ū' => 'u', 'Ū' => 'U', 'ư' => 'u', 'Ư' => 'U', 'ü' => 'u', 'Ü' => 'U', 'ẃ' => 'w', 'Ẃ' => 'W', 'ẁ' => 'w', 'Ẁ' => 'W', 'ŵ' => 'w', 'Ŵ' => 'W', 'ẅ' => 'w', 'Ẅ' => 'W', 'ý' => 'y', 'Ý' => 'Y', 'ỳ' => 'y', 'Ỳ' => 'Y', 'ŷ' => 'y', 'Ŷ' => 'Y', 'ÿ' => 'y', 'Ÿ' => 'Y', 'ź' => 'z', 'Ź' => 'Z', 'ž' => 'z', 'Ž' => 'Z', 'ż' => 'z', 'Ż' => 'Z', 'þ' => 'th', 'Þ' => 'Th', 'µ' => 'u', 'а' => 'a', 'А' => 'a', 'б' => 'b', 'Б' => 'b', 'в' => 'v', 'В' => 'v', 'г' => 'g', 'Г' => 'g', 'д' => 'd', 'Д' => 'd', 'е' => 'e', 'Е' => 'E', 'ё' => 'e', 'Ё' => 'E', 'ж' => 'zh', 'Ж' => 'zh', 'з' => 'z', 'З' => 'z', 'и' => 'i', 'И' => 'i', 'й' => 'j', 'Й' => 'j', 'к' => 'k', 'К' => 'k', 'л' => 'l', 'Л' => 'l', 'м' => 'm', 'М' => 'm', 'н' => 'n', 'Н' => 'n', 'о' => 'o', 'О' => 'o', 'п' => 'p', 'П' => 'p', 'р' => 'r', 'Р' => 'r', 'с' => 's', 'С' => 's', 'т' => 't', 'Т' => 't', 'у' => 'u', 'У' => 'u', 'ф' => 'f', 'Ф' => 'f', 'х' => 'h', 'Х' => 'h', 'ц' => 'c', 'Ц' => 'c', 'ч' => 'ch', 'Ч' => 'ch', 'ш' => 'sh', 'Ш' => 'sh', 'щ' => 'sch', 'Щ' => 'sch', 'ъ' => '', 'Ъ' => '', 'ы' => 'y', 'Ы' => 'y', 'ь' => '', 'Ь' => '', 'э' => 'e', 'Э' => 'e', 'ю' => 'ju', 'Ю' => 'ju', 'я' => 'ja', 'Я' => 'ja', "!" => "", "|" => "", "'" => "", "\"" => "", "'" => "", "@" => "", "·" => "", "#" => "", "$" => "", "¢" => "", "%" => "", "" => "", "¬" => "", "/" => "", "÷" => "", "(" => "", "" => "", ")" => "", "" => "", "" => "", "?" => "", "'" => "", "¡" => "", "¿" => "", "" => "", "´" => "", "^" => "", "`" => "", "[" => "", "*" => "", "+" => "", "]" => "", "¨" => "", "´" => "", "{" => "", "}" => "", "," => "", ";" => "", "" => "", "." => "", ":" => "", "" => "", "<" => "", ">" => "", "" => "", "" => "", "»" => "", "«" => "", "œ" => "", "æ" => "", "®" => "", "" => "", "¥" => "", "π" => "", "" => "", "" => "", "" => "", "" => "", "§" => "", "~" => "", "Ω" => "", "" => "", "©" => "", "" => "", "µ" => "", "=" => "", "&" => "", " " => "-", "" => "-", "_" => "-", " " => "-", '€' => 'e', 'º' => '', 'ª' => '', '&' => 'y', '\'' => '');
$enlace = strtolower(str_replace(array_keys($transliterationTable), array_values($transliterationTable), $txt));
$enlace = preg_replace("/([\-]+)/", "-", $enlace);
return urlencode($enlace);
}
?>

78
header.php Executable file
View File

@@ -0,0 +1,78 @@
<?
require_once ("sesion.php");
if (isset($_GET["pruebas"])) $_SESSION["pruebas"]=true;
require_once "funciones.php";
if (!isset($current)) $current=0;
if (HAY_TIENDA) {
$categorias = CocoDB::get("categorias_productos", "parentNum=0", "siblingOrder ASC", null, ["ignoreSchema" => true]);
}
$idiomas = dame_idiomas();
$idiomaSeleccionado = "Español";
foreach ($idiomas as $idioma):
if ($idioma["valor"]=="/".@$_REQUEST["idioma"]) $idiomaSeleccionado=$idioma["idioma"];
endforeach;
$apartadoCesta = CocoDB::get("apartados", "controlador='cesta.php'", null, 1, ["ignoreSchema" => true]);
$apartadoCesta = @$apartadoCesta[0];
$apartadoFavoritos = CocoDB::get("apartados", "controlador='favoritos.php'", null, 1, ["ignoreSchema" => true]);
$apartadoFavoritos = @$apartadoFavoritos[0];
$apartadoLogin = CocoDB::get("apartados", "controlador='login.php'", null, 1, ["ignoreSchema" => true]);
$apartadoLogin = @$apartadoLogin[0];
$apartadoRegistro = CocoDB::get("apartados", "controlador='registro.php'", null, 1, ["ignoreSchema" => true]);
$apartadoRegistro = @$apartadoRegistro[0];
$alternate = dame_alternates($_SERVER["REQUEST_URI"]);
$config_header = array(
'titulo_de_pagina' => $configuracionRecord["titulo_de_pagina"],
'categorias' => @$categorias,
'pagina_publicada' => $configuracionRecord["pagina_publicada"],
'current' => $current,
'portada' => @$portada,
'index' => @$index,
'configuracionRecord' => $configuracionRecord,
'configuracionTienda' => $configuracionTienda,
'meta_descripcion' => $configuracionRecord["metatag_descripcion"],
'meta_palabras' => @$configuracionRecord["metatag_palabras"],
'otros_metas' => @$otros_metas,
'color_base' => @$color_base,
'categorias' => @$categorias,
'idiomas' => @$idiomas,
'idiomaSeleccionado'=> @$idiomaSeleccionado,
'apartadoCesta' => @$apartadoCesta,
'apartadoFavoritos' => @$apartadoFavoritos,
'apartadoLogin' => @$apartadoLogin,
'apartadoRegistro' => @$apartadoRegistro,
'sitebuilder' => @$apartado["plantilla_sitebuilder"],
'alternate' => @$alternate
);
if ($configuracionRecord["pagina_publicada"]){
if (@$customCode) echo modulo('custom-header',$config_header); else echo tpl('cabecera',$config_header);
}else{
if (!isset($_SESSION["pruebas"])){
die(tpl('mantenimiento',$config_header));
}else{
if (@$customCode) echo modulo('custom-header',$config_header); else echo tpl('cabecera',$config_header);
if (isset($_SESSION["pruebas"])){
if ($configuracionRecord["pagina_publicada"]==0){
?>
<div style="position:absolute;top:0px;width:150px;background-color:red;color:#fff;font-size:12px;padding:0 10px;z-index:99999999;transform:translateZ(1000px);">SITIO EN PRUEBAS</div>
<?
}
}
}
}
?>

25
index.php Executable file
View File

@@ -0,0 +1,25 @@
<?
$index=true;
include("header.php");
$apartado = CocoDB::get("apartados", "enlace LIKE '%index%'", "siblingOrder DESC", 1);
$apartado = @$apartado[0];
$configuracionRecord["titulo_de_pagina"] = t($apartado,"name")." - ".$configuracionRecord["titulo_de_pagina"];
if (@$apartado["titulo_de_pagina"]!="") $configuracionRecord["titulo_de_pagina"] = t($apartado,"titulo_de_pagina");
if (@$apartado["metatag_descripcion"]!="") $configuracionRecord["metatag_descripcion"] = t($apartado,"metatag_descripcion");
if (@$apartado["metatag_palabras"]!="") $configuracionRecord["metatag_palabras"] = t($apartado,"metatag_palabras");
$portada = CocoDB::get("portada", "", "num DESC", 1);
$portada = @$portada[0];
$config_portada = array(
'portada' => $portada,
'apartado' => @$apartado
);
echo tpl("portada", $config_portada);
?>
<? include("footer.php");?>

58
lib/FileJoiner.php Executable file
View File

@@ -0,0 +1,58 @@
<?
class FileJoiner {
private $_files;
private $_fileContent;
private $_type;
private $_target;
public function __construct($files, $type, $target) {
$this->_files = $files;
$this->_type = $type;
$this->_target = $target;
}
private function _joinFiles() {
$this->_fileContent = "";
foreach ($this->_files as $file):
$file = $file;
if (file_exists($file)) {
$this->_fileContent .= file_get_contents($file)."\n";
}
endforeach;
}
public function getFile() {
$target = $this->_target;
if (file_exists($target)) {
$targetTime = filemtime($target);
// Recorremos la lista de archivos a ver si hay alguno más nuevo que el generado
foreach ($this->_files as $file):
$file = $file;
if (file_exists($file)) {
if (filemtime($file) > $targetTime) {
$hayNuevos = true;
break;
}
}
endforeach;
if (!@$hayNuevos) return file_get_contents($target);
}
// Generamos un nuevo archivo
$this->_joinFiles();
file_put_contents($target, $this->_fileContent);
return file_get_contents($target);
}
public function getContentType() {
$ct = "Content-Type: ";
switch ($this->_type) {
case "js":
return $ct."application/javascript";
case "css":
return $ct."text/css";
default: return $ct."text/plaintext";
}
}
}
?>

7
lib/IPNGenerica.php Executable file
View File

@@ -0,0 +1,7 @@
<?php
if (isset($_REQUEST["ipn"]) || isset($_REQUEST["forma_de_pago"]) || isset($_REQUEST['cancel']) || (isset($_REQUEST['data']) && isset($_REQUEST['data']["object"]) ) ){
require_once(__DIR__."/../cms/lib/plugins/builder_saas/builder_functions.php");
hook("/hooks/1607710458061/");
hook("/hooks/ipn/");
}
?>

76
lib/Module.php Executable file
View File

@@ -0,0 +1,76 @@
<?
class Module {
public static $css = array();
public static $cssHash = array();
public static $js = array();
public static $jsHash = array();
public static $loaded = array();
public static $path = './'.PLANTILLA.'/modulos/';
public static function load($folder, $params) {
$folderAbs = Module::$path.$folder;
if (!isset(Module::$loaded[$folder])) {
$files = scandir($folderAbs);
// Los dos primeros elementos son ../ y ./
array_splice($files, 0, 2);
foreach ($files as $file):
$ext = pathinfo($folderAbs.'/'.$file, PATHINFO_EXTENSION);
switch ($ext) {
case 'css':
$md5File = md5_file($folderAbs.'/'.$file);
if (!in_array($md5File,Module::$cssHash)) {
Module::$css[] = '/modulos/'.$folder.'/'.$file;
Module::$cssHash[] = $md5File;
}
break;
case 'js':
$md5File = md5_file($folderAbs.'/'.$file);
if (!in_array($md5File,Module::$jsHash)) {
Module::$js[] = '/modulos/'.$folder.'/'.$file;
Module::$jsHash[] = $md5File;
}
break;
default:
break;
}
endforeach;
Module::$loaded[$folder] = true;
}
extract($params);
ob_start();
require($folderAbs.'/index.tpl');
$resultado = ob_get_clean();
return $resultado;
}
/**
* Devuelve una string con todos los link que ha sacado de los módulos
*/
public static function links() {
Module::$css = array_unique(Module::$css);
$links=''; if (defined('USE_MIN_TAILWIND') && USE_MIN_TAILWIND) return '';
foreach (Module::$css as $c):
$links .= '<link rel="stylesheet" href="'.h($c).'">';
endforeach;
return $links;
}
/**
* Devuelve una string con todos los scripts que ha sacado de los módulos
*/
public static function scripts() {
Module::$js = array_unique(Module::$js);
$scripts=''; if (defined('USE_MIN_JS_TAILWIND') && USE_MIN_JS_TAILWIND) return '';
foreach (Module::$js as $s):
$scripts .= '<script src="'.h($s).'"></script>';
endforeach;
return $scripts;
}
}
?>

49
lib/PHPMailerAutoload.php Executable file
View File

@@ -0,0 +1,49 @@
<?php
/**
* PHPMailer SPL autoloader.
* PHP Version 5
* @package PHPMailer
* @link https://github.com/PHPMailer/PHPMailer/ The PHPMailer GitHub project
* @author Marcus Bointon (Synchro/coolbru) <phpmailer@synchromedia.co.uk>
* @author Jim Jagielski (jimjag) <jimjag@gmail.com>
* @author Andy Prevost (codeworxtech) <codeworxtech@users.sourceforge.net>
* @author Brent R. Matzelle (original founder)
* @copyright 2012 - 2014 Marcus Bointon
* @copyright 2010 - 2012 Jim Jagielski
* @copyright 2004 - 2009 Andy Prevost
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
* @note This program is distributed in the hope that it will be useful - WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*/
/**
* PHPMailer SPL autoloader.
* @param string $classname The name of the class to load
*/
function PHPMailerAutoload($classname)
{
//Can't use __DIR__ as it's only in PHP 5.3+
$filename = dirname(__FILE__).DIRECTORY_SEPARATOR.'class.'.strtolower($classname).'.php';
if (is_readable($filename)) {
require $filename;
}
}
if (version_compare(PHP_VERSION, '5.1.2', '>=')) {
//SPL autoloading was introduced in PHP 5.1.2
if (version_compare(PHP_VERSION, '5.3.0', '>=')) {
spl_autoload_register('PHPMailerAutoload', true, true);
} else {
spl_autoload_register('PHPMailerAutoload');
}
} else {
/**
* Fall back to traditional autoload for old PHP versions
* @param string $classname The name of the class to load
*/
function __autoload($classname)
{
PHPMailerAutoload($classname);
}
}

23
lib/Resource.class.php Executable file
View File

@@ -0,0 +1,23 @@
<?php
class Resource {
static function link($path, $async = false, $hash = true) {
$existMinimalCSSFile = array_filter(Module::$css,function($rec){ return strpos($rec,"cache") !== false; });
if ($existMinimalCSSFile) $existMinimalCSSFile = array_values($existMinimalCSSFile);
if (strpos($path,"cache") !== false && $existMinimalCSSFile) return;
if (strpos($path,"tailwind") !== false && defined("USE_MIN_TAILWIND") && USE_MIN_TAILWIND) $path = str_replace("tailwind","cocotail",$path);
if (strpos($path,"tailwind") !== false && $existMinimalCSSFile) $path = $existMinimalCSSFile[0];
if (strpos($path,"tailwind") == false && !$existMinimalCSSFile && @$_REQUEST["generateMinCss"]) return;
$absolute = strpos($path, 'http') === 0 || strpos($path, '//') === 0;
if ($absolute) $hash = false;
if ($hash) $path = h($path);
if ($async) {
echo '<link rel="preload" as="style" href="'.$path.'" onload="this.onload=null;this.rel=\'stylesheet\'">
<noscript><link rel="stylesheet" href="'.$path.'"></noscript>
';
}
else {
echo '<link rel="stylesheet" href="'.$path.'">';
}
}
}

3541
lib/class.phpmailer.php Executable file

File diff suppressed because it is too large Load Diff

397
lib/class.pop3.php Executable file
View File

@@ -0,0 +1,397 @@
<?php
/**
* PHPMailer POP-Before-SMTP Authentication Class.
* PHP Version 5
* @package PHPMailer
* @link https://github.com/PHPMailer/PHPMailer/
* @author Marcus Bointon (Synchro/coolbru) <phpmailer@synchromedia.co.uk>
* @author Jim Jagielski (jimjag) <jimjag@gmail.com>
* @author Andy Prevost (codeworxtech) <codeworxtech@users.sourceforge.net>
* @author Brent R. Matzelle (original founder)
* @copyright 2012 - 2014 Marcus Bointon
* @copyright 2010 - 2012 Jim Jagielski
* @copyright 2004 - 2009 Andy Prevost
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
* @note This program is distributed in the hope that it will be useful - WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*/
/**
* PHPMailer POP-Before-SMTP Authentication Class.
* Specifically for PHPMailer to use for RFC1939 POP-before-SMTP authentication.
* Does not support APOP.
* @package PHPMailer
* @author Richard Davey (original author) <rich@corephp.co.uk>
* @author Marcus Bointon (Synchro/coolbru) <phpmailer@synchromedia.co.uk>
* @author Jim Jagielski (jimjag) <jimjag@gmail.com>
* @author Andy Prevost (codeworxtech) <codeworxtech@users.sourceforge.net>
*/
class POP3
{
/**
* The POP3 PHPMailer Version number.
* @type string
* @access public
*/
public $Version = '5.2.9';
/**
* Default POP3 port number.
* @type integer
* @access public
*/
public $POP3_PORT = 110;
/**
* Default timeout in seconds.
* @type integer
* @access public
*/
public $POP3_TIMEOUT = 30;
/**
* POP3 Carriage Return + Line Feed.
* @type string
* @access public
* @deprecated Use the constant instead
*/
public $CRLF = "\r\n";
/**
* Debug display level.
* Options: 0 = no, 1+ = yes
* @type integer
* @access public
*/
public $do_debug = 0;
/**
* POP3 mail server hostname.
* @type string
* @access public
*/
public $host;
/**
* POP3 port number.
* @type integer
* @access public
*/
public $port;
/**
* POP3 Timeout Value in seconds.
* @type integer
* @access public
*/
public $tval;
/**
* POP3 username
* @type string
* @access public
*/
public $username;
/**
* POP3 password.
* @type string
* @access public
*/
public $password;
/**
* Resource handle for the POP3 connection socket.
* @type resource
* @access private
*/
private $pop_conn;
/**
* Are we connected?
* @type boolean
* @access private
*/
private $connected = false;
/**
* Error container.
* @type array
* @access private
*/
private $errors = array();
/**
* Line break constant
*/
const CRLF = "\r\n";
/**
* Simple static wrapper for all-in-one POP before SMTP
* @param $host
* @param boolean $port
* @param boolean $tval
* @param string $username
* @param string $password
* @param integer $debug_level
* @return boolean
*/
public static function popBeforeSmtp(
$host,
$port = false,
$tval = false,
$username = '',
$password = '',
$debug_level = 0
) {
$pop = new POP3;
return $pop->authorise($host, $port, $tval, $username, $password, $debug_level);
}
/**
* Authenticate with a POP3 server.
* A connect, login, disconnect sequence
* appropriate for POP-before SMTP authorisation.
* @access public
* @param string $host The hostname to connect to
* @param integer|boolean $port The port number to connect to
* @param integer|boolean $timeout The timeout value
* @param string $username
* @param string $password
* @param integer $debug_level
* @return boolean
*/
public function authorise($host, $port = false, $timeout = false, $username = '', $password = '', $debug_level = 0)
{
$this->host = $host;
// If no port value provided, use default
if (false === $port) {
$this->port = $this->POP3_PORT;
} else {
$this->port = (integer)$port;
}
// If no timeout value provided, use default
if (false === $timeout) {
$this->tval = $this->POP3_TIMEOUT;
} else {
$this->tval = (integer)$timeout;
}
$this->do_debug = $debug_level;
$this->username = $username;
$this->password = $password;
// Reset the error log
$this->errors = array();
// connect
$result = $this->connect($this->host, $this->port, $this->tval);
if ($result) {
$login_result = $this->login($this->username, $this->password);
if ($login_result) {
$this->disconnect();
return true;
}
}
// We need to disconnect regardless of whether the login succeeded
$this->disconnect();
return false;
}
/**
* Connect to a POP3 server.
* @access public
* @param string $host
* @param integer|boolean $port
* @param integer $tval
* @return boolean
*/
public function connect($host, $port = false, $tval = 30)
{
// Are we already connected?
if ($this->connected) {
return true;
}
//On Windows this will raise a PHP Warning error if the hostname doesn't exist.
//Rather than suppress it with @fsockopen, capture it cleanly instead
set_error_handler(array($this, 'catchWarning'));
if (false === $port) {
$port = $this->POP3_PORT;
}
// connect to the POP3 server
$this->pop_conn = fsockopen(
$host, // POP3 Host
$port, // Port #
$errno, // Error Number
$errstr, // Error Message
$tval
); // Timeout (seconds)
// Restore the error handler
restore_error_handler();
// Did we connect?
if (false === $this->pop_conn) {
// It would appear not...
$this->setError(array(
'error' => "Failed to connect to server $host on port $port",
'errno' => $errno,
'errstr' => $errstr
));
return false;
}
// Increase the stream time-out
stream_set_timeout($this->pop_conn, $tval, 0);
// Get the POP3 server response
$pop3_response = $this->getResponse();
// Check for the +OK
if ($this->checkResponse($pop3_response)) {
// The connection is established and the POP3 server is talking
$this->connected = true;
return true;
}
return false;
}
/**
* Log in to the POP3 server.
* Does not support APOP (RFC 2828, 4949).
* @access public
* @param string $username
* @param string $password
* @return boolean
*/
public function login($username = '', $password = '')
{
if (!$this->connected) {
$this->setError('Not connected to POP3 server');
}
if (empty($username)) {
$username = $this->username;
}
if (empty($password)) {
$password = $this->password;
}
// Send the Username
$this->sendString("USER $username" . self::CRLF);
$pop3_response = $this->getResponse();
if ($this->checkResponse($pop3_response)) {
// Send the Password
$this->sendString("PASS $password" . self::CRLF);
$pop3_response = $this->getResponse();
if ($this->checkResponse($pop3_response)) {
return true;
}
}
return false;
}
/**
* Disconnect from the POP3 server.
* @access public
*/
public function disconnect()
{
$this->sendString('QUIT');
//The QUIT command may cause the daemon to exit, which will kill our connection
//So ignore errors here
try {
@fclose($this->pop_conn);
} catch (Exception $e) {
//Do nothing
};
}
/**
* Get a response from the POP3 server.
* $size is the maximum number of bytes to retrieve
* @param integer $size
* @return string
* @access private
*/
private function getResponse($size = 128)
{
$response = fgets($this->pop_conn, $size);
if ($this->do_debug >= 1) {
echo "Server -> Client: $response";
}
return $response;
}
/**
* Send raw data to the POP3 server.
* @param string $string
* @return integer
* @access private
*/
private function sendString($string)
{
if ($this->pop_conn) {
if ($this->do_debug >= 2) { //Show client messages when debug >= 2
echo "Client -> Server: $string";
}
return fwrite($this->pop_conn, $string, strlen($string));
}
return 0;
}
/**
* Checks the POP3 server response.
* Looks for for +OK or -ERR.
* @param string $string
* @return boolean
* @access private
*/
private function checkResponse($string)
{
if (substr($string, 0, 3) !== '+OK') {
$this->setError(array(
'error' => "Server reported an error: $string",
'errno' => 0,
'errstr' => ''
));
return false;
} else {
return true;
}
}
/**
* Add an error to the internal error store.
* Also display debug output if it's enabled.
* @param $error
*/
private function setError($error)
{
$this->errors[] = $error;
if ($this->do_debug >= 1) {
echo '<pre>';
foreach ($this->errors as $error) {
print_r($error);
}
echo '</pre>';
}
}
/**
* POP3 connection error handler.
* @param integer $errno
* @param string $errstr
* @param string $errfile
* @param integer $errline
* @access private
*/
private function catchWarning($errno, $errstr, $errfile, $errline)
{
$this->setError(array(
'error' => "Connecting to the POP3 server raised a PHP warning: ",
'errno' => $errno,
'errstr' => $errstr,
'errfile' => $errfile,
'errline' => $errline
));
}
}

1152
lib/class.smtp.php Executable file

File diff suppressed because it is too large Load Diff

307
lib/minifier.php Executable file
View File

@@ -0,0 +1,307 @@
<?php
// Based on <https://github.com/mecha-cms/extend.minify>
define('MINIFY_STRING', '"(?:[^"\\\]|\\\.)*"|\'(?:[^\'\\\]|\\\.)*\'');
define('MINIFY_COMMENT_CSS', '/\*[\s\S]*?\*/');
define('MINIFY_COMMENT_HTML', '<!\-{2}[\s\S]*?\-{2}>');
define('MINIFY_COMMENT_JS', '//[^\n]*');
define('MINIFY_PATTERN_JS', '/[^\n]+?/[gimuy]*');
define('MINIFY_HTML', '<[!/]?[a-zA-Z\d:.-]+[\s\S]*?>');
define('MINIFY_HTML_ENT', '&(?:[a-zA-Z\d]+|\#\d+|\#x[a-fA-F\d]+);');
define('MINIFY_HTML_KEEP', '<pre(?:\s[^<>]*?)?>[\s\S]*?</pre>|<code(?:\s[^<>]*?)?>[\s\S]*?</code>|<script(?:\s[^<>]*?)?>[\s\S]*?</script>|<style(?:\s[^<>]*?)?>[\s\S]*?</style>|<textarea(?:\s[^<>]*?)?>[\s\S]*?</textarea>');
// get URL
$protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' || $_SERVER['SERVER_PORT'] === 443 ? 'https' : 'http') . '://';
$host = isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : (isset($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : "");
$url = $protocol . $host;
// escape character
define('X', "\x1A");
// normalize linebreak(s)
function n($s) {
return str_replace(["\r\n", "\r"], "\n", $s);
}
// trim once
function tr($a, $b) {
if ($a && strpos($a, $b) === 0 && substr($a, -strlen($b)) === $b) {
return substr(substr($a, strlen($b)), 0, -strlen($b));
}
return $a;
}
function fn_minify($pattern, $input) {
return preg_split('#(' . implode('|', $pattern) . ')#', $input, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
}
function fn_minify_css($input, $comment = 2, $quote = 2) {
if (!is_string($input) || !$input = n(trim($input))) return $input;
$output = $prev = "";
foreach (fn_minify([MINIFY_COMMENT_CSS, MINIFY_STRING], $input) as $part) {
if (trim($part) === "") continue;
if ($comment !== 1 && strpos($part, '/*') === 0 && substr($part, -2) === '*/') {
if (
$comment === 2 && (
// Detect special comment(s) from the third character. It should be a `!` or `*` → `/*! keep */` or `/** keep */`
strpos('*!', $part[2]) !== false ||
// Detect license comment(s) from the content. It should contains character(s) like `@license`
stripos($part, '@licence') !== false || // noun
stripos($part, '@license') !== false || // verb
stripos($part, '@preserve') !== false
)
) {
$output .= $part;
}
continue;
}
if ($part[0] === '"' && substr($part, -1) === '"' || $part[0] === "'" && substr($part, -1) === "'") {
// Remove quote(s) where possible …
$q = $part[0];
if (
$quote !== 1 && (
// <https://www.w3.org/TR/CSS2/syndata.html#uri>
substr($prev, -4) === 'url(' && preg_match('#\burl\($#', $prev) ||
// <https://www.w3.org/TR/CSS2/syndata.html#characters>
substr($prev, -1) === '=' && preg_match('#^' . $q . '[a-zA-Z_][\w-]*?' . $q . '$#', $part)
)
) {
$part = tr($part, $q); // trim quote(s)
}
$output .= $part;
} else {
$output .= fn_minify_css_union($part);
}
$prev = $part;
}
return trim($output);
}
function fn_minify_css_union($input) {
if (stripos($input, 'calc(') !== false) {
// Keep important whitespace(s) in `calc()`
$input = preg_replace_callback('#\b(calc\()\s*(.*?)\s*\)#i', function($m) {
return $m[1] . preg_replace('#\s+#', X, $m[2]) . ')';
}, $input);
}
$input = preg_replace([
// Fix case for `#foo<space>[bar="baz"]`, `#foo<space>*` and `#foo<space>:first-child` [^1]
'#(?<=[\w])\s+(\*|\[|:[\w-]+)#',
// Fix case for `[bar="baz"]<space>.foo`, `*<space>.foo`, `:nth-child(2)<space>.foo` and `@media<space>(foo: bar)<space>and<space>(baz: qux)` [^2]
'#([*\]\)])\s+(?=[\w\#.])#', '#\b\s+\(#', '#\)\s+\b#',
// Minify HEX color code … [^3]
'#\#([a-f\d])\1([a-f\d])\2([a-f\d])\3\b#i',
// Remove whitespace(s) around punctuation(s) [^4]
'#\s*([~!@*\(\)+=\{\}\[\]:;,>\/])\s*#',
// Replace zero unit(s) with `0` [^5]
'#\b(?:0\.)?0([a-z]+\b)#i',
// Replace `0.6` with `.6` [^6]
'#\b0+\.(\d+)#',
// Replace `:0 0`, `:0 0 0` and `:0 0 0 0` with `:0` [^7]
'#:(0\s+){0,3}0(?=[!,;\)\}]|$)#',
// Replace `background(?:-position)?:(0|none)` with `background$1:0 0` [^8]
'#\b(background(?:-position)?):(?:0|none)([;,\}])#i',
// Replace `(border(?:-radius)?|outline):none` with `$1:0` [^9]
'#\b(border(?:-radius)?|outline):none\b#i',
// Remove empty selector(s) [^10]
'#(^|[\{\}])(?:[^\{\}]+)\{\}#',
// Remove the last semicolon and replace multiple semicolon(s) with a semicolon [^11]
'#;+([;\}])#',
// Replace multiple whitespace(s) with a space [^12]
'#\s+#'
], [
// [^1]
X . '$1',
// [^2]
'$1' . X, X . '(', ')' . X,
// [^3]
'#$1$2$3',
// [^4]
'$1',
// [^5]
'0',
// [^6]
'.$1',
// [^7]
':0',
// [^8]
'$1:0 0$2',
// [^9]
'$1:0',
// [^10]
'$1',
// [^11]
'$1',
// [^12]
' '
], $input);
return trim(str_replace(X, ' ', $input));
}
function fn_minify_html($input, $comment = 2, $quote = 1) {
if (!is_string($input) || !$input = n(trim($input))) return $input;
$output = $prev = "";
foreach (fn_minify([MINIFY_COMMENT_HTML, MINIFY_HTML_KEEP, MINIFY_HTML, MINIFY_HTML_ENT], $input) as $part) {
if ($part === "\n") continue;
if ($part !== ' ' && trim($part) === "" || $comment !== 1 && strpos($part, '<!--') === 0) {
// Detect IE conditional comment(s) by its closing tag …
if ($comment === 2 && substr($part, -12) === '<![endif]-->') {
$output .= $part;
}
continue;
}
if ($part[0] === '<' && substr($part, -1) === '>') {
$output .= fn_minify_html_union($part, $quote);
} else if ($part[0] === '&' && substr($part, -1) === ';' && $part !== '&lt;' && $part !== '&gt;' && $part !== '&amp;') {
$output .= html_entity_decode($part); // Evaluate HTML entit(y|ies)
} else {
$output .= preg_replace('#\s+#', ' ', $part);
}
$prev = $part;
}
$output = str_replace(' </', '</', $output);
// Force space with `&#x0020;` and linebreak with `&#x000A;`
return str_ireplace(['&#x0020;', '&#x20;', '&#x000A;', '&#xA;'], [' ', ' ', "\n", "\n"], trim($output));
}
function fn_minify_html_union($input, $quote) {
if (
strpos($input, ' ') === false &&
strpos($input, "\n") === false &&
strpos($input, "\t") === false
) return $input;
global $url;
return preg_replace_callback('#<\s*([^\/\s]+)\s*(?:>|(\s[^<>]+?)\s*>)#', function($m) use($quote, $url) {
if (isset($m[2])) {
// Minify inline CSS(s)
if (stripos($m[2], ' style=') !== false) {
$m[2] = preg_replace_callback('#( style=)([\'"]?)(.*?)\2#i', function($m) {
return $m[1] . $m[2] . fn_minify_css($m[3]) . $m[2];
}, $m[2]);
}
// Minify URL(s)
if (strpos($m[2], '://') !== false) {
// $m[2] = str_replace([
// $url . '/',
// $url . '?',
// $url . '&',
// $url . '#',
// $url . '"',
// $url . "'"
// ], [
// '/',
// '?',
// '&',
// '#',
// '/"',
// "/'"
// ], $m[2]);
}
$a = 'a(sync|uto(focus|play))|c(hecked|ontrols)|d(efer|isabled)|hidden|ismap|loop|multiple|open|re(adonly|quired)|s((cop|elect)ed|pellcheck)';
$a = '<' . $m[1] . preg_replace([
// From `a="a"`, `a='a'`, `a="true"`, `a='true'`, `a=""` and `a=''` to `a` [^1]
'#\s(' . $a . ')(?:=([\'"]?)(?:true|\1)?\2)#i',
// Remove extra whitespace(s) between HTML attribute(s) [^2]
'#\s*([^\s=]+?)(=(?:\S+|([\'"]?).*?\3)|$)#',
// From `<img />` to `<img/>` [^3]
'#\s+\/$#'
], [
// [^1]
' $1',
// [^2]
' $1$2',
// [^3]
'/'
], str_replace("\n", ' ', $m[2])) . '>';
return $quote !== 1 ? fn_minify_html_union_attr($a) : $a;
}
return '<' . $m[1] . '>';
}, $input);
}
function fn_minify_html_union_attr($input) {
if (strpos($input, '=') === false) return $input;
return preg_replace_callback('#=(' . MINIFY_STRING . ')#', function($m) {
$q = $m[1][0];
if (strpos($m[1], ' ') === false && preg_match('#^' . $q . '[a-zA-Z_][\w-]*?' . $q . '$#', $m[1])) {
return '=' . tr($m[1], $q);
}
return $m[0];
}, $input);
}
function fn_minify_js($input, $comment = 2, $quote = 2) {
if (!is_string($input) || !$input = n(trim($input))) return $input;
$output = $prev = "";
foreach (fn_minify([MINIFY_COMMENT_CSS, MINIFY_STRING, MINIFY_COMMENT_JS, MINIFY_PATTERN_JS], $input) as $part) {
if (trim($part) === "") continue;
if ($comment !== 1 && (
strpos($part, '//') === 0 || // Remove inline comment(s)
strpos($part, '/*') === 0 && substr($part, -2) === '*/'
)) {
if (
$comment === 2 && (
// Detect special comment(s) from the third character. It should be a `!` or `*` → `/*! keep */` or `/** keep */`
strpos('*!', $part[2]) !== false ||
// Detect license comment(s) from the content. It should contains character(s) like `@license`
stripos($part, '@licence') !== false || // noun
stripos($part, '@license') !== false || // verb
stripos($part, '@preserve') !== false
)
) {
$output .= $part;
}
continue;
}
if ($part[0] === '/' && (substr($part, -1) === '/' || preg_match('#\/[gimuy]*$#', $part))) {
} else if ($part[0] === '"' && substr($part, -1) === '"' || $part[0] === "'" && substr($part, -1) === "'") {
// TODO: Remove quote(s) where possible …
$output .= $part;
} else {
$output .= fn_minify_js_union($part);
}
$prev = $part;
}
return $output;
}
function fn_minify_js_union($input) {
return preg_replace([
// Remove whitespace(s) around punctuation(s) [^1]
'#\s*([!%&*\(\)\-=+\[\]\{\}|;:,.<>?\/])\s*#',
// Remove the last semicolon and comma [^2]
'#[;,]([\]\}])#',
// Replace `true` with `!0` and `false` with `!1` [^3]
'#\btrue\b#', '#\bfalse\b#', '#\b(return\s?)\s*\b#',
// Replace `new Array(x)` with `[x]` … [^4]
'#\b(?:new\s+)?Array\((.*?)\)#', '#\b(?:new\s+)?Object\((.*?)\)#'
], [
// [^1]
'$1',
// [^2]
'$1',
// [^3]
'!0', '!1', '$1',
// [^4]
'[$1]', '{$1}'
], $input);
}
/**
* Backward Compatibility
* ----------------------
*/
function minify_css(...$lot) {
return fn_minify_css(...$lot);
}
function minify_html(...$lot) {
return fn_minify_html(...$lot);
}
function minify_js(...$lot) {
return fn_minify_js(...$lot);
}

42
lib/recursos.php Executable file
View File

@@ -0,0 +1,42 @@
<?
require_once "variables.php";
require_once "FileJoiner.php";
$fileType = "css";
switch (@$_REQUEST["fileType"]) {
case "css":
$files = array(
"..".RUTA_PLANTILLA."/css/bootstrap.min.css",
"..".RUTA_PLANTILLA."/css/bxslider.min.css",
"..".RUTA_PLANTILLA."/css/swipebox.min.css",
"..".RUTA_PLANTILLA."/css/animate.css",
"..".RUTA_PLANTILLA."/css/rrssb.css",
"..".RUTA_PLANTILLA."/css/cesta.css",
"..".RUTA_PLANTILLA."/style-base.css",
"..".RUTA_PLANTILLA."/style.css"
);
$fileName = "..".RUTA_PLANTILLA."/css/main.css";
break;
case "js":
$fileType = "js";
$files = array(
"..".RUTA_PLANTILLA."/js/bootstrap.min.js",
"..".RUTA_PLANTILLA."/js/bxslider.min.js",
"..".RUTA_PLANTILLA."/js/jquery.swipebox.min.js",
"..".RUTA_PLANTILLA."/js/wow.min.js",
"..".RUTA_PLANTILLA."/js/rrssb.min.js",
"..".RUTA_PLANTILLA."/js/fetch.js",
"..".RUTA_PLANTILLA."/js/lazy-loader.js",
"..".RUTA_PLANTILLA."/js/liveSearchModal.js",
"..".RUTA_PLANTILLA."/js/cesta_class.js",
"..".RUTA_PLANTILLA."/js/mis-scripts.js"
);
$fileName = "..".RUTA_PLANTILLA."/js/main.js";
break;
default: die("");
}
$fj = new FileJoiner($files, $fileType, @$fileName);
header($fj->getContentType());
die($fj->getFile());
?>

78
lib/variables.php Executable file
View File

@@ -0,0 +1,78 @@
<?php
define("CMS_FOLDER","cms");
define("CMS_VIEWER_LIB",CMS_FOLDER."/lib/viewer_functions.php");
define('USAR_WEBP', false);
require_once str_replace("/lib","",dirname(__FILE__))."/".CMS_VIEWER_LIB;
CocoParser::$parseaCodigosEnLinea = false;
CocoDB::$defaultRelationsDepth = 1;
// if (isset($_REQUEST["enlace"]) && $_REQUEST["enlace"] == "") define("USE_MIN_TAILWIND",true);
define("BUILDER_JSON_RESPONSE",@$_REQUEST["builderJson"] ? true : false);
if(property_exists('CocoDB', 'force_json_cache_uploads')) {
CocoDB::$force_json_cache_uploads = false;
}
// EN SERVIDORES EXTERNOS HAY QUE DEFINIR LA RUTA DE TAILWINDCSS SINO NO FUNCIONARA EL MINCSS
// define("TAILWIND_PATH","./node_modules/.bin/tailwindcss");
/*****************/
/* CACHE HANDLER */
/*****************/
// define("USE_INFORMATION_SCHEMA_CACHE", true);
// Cache local que cachea las consultas en cada petición cuando se repitan (sin Redis)
// CocoDB::$noCacheURIS = ["\/mi(s)?-(.*)(\/)(.*)","\/hooks\/(.*)?","\/login\/(.*)?"];
// CocoDB::$noCacheTABLES = ["aux_plg_payments","cms_cestas_abandonadas","cms_direcciones","cms_posibles_pedidos","cms_stock","cms_usuarios_metas","cms_usuarios"];
//
// // Activamos el Cache en general y de consultas
// CocoDB::fullCache(3);
//
// // Activamos el Cache local que cache las consultas en cada carga cuando se repitan
CocoDB::localCache();
//
// CocoDB::$force_redis_module = @CocoDB::bloquedCacheByURL($_SERVER["REQUEST_URI"]) ? false : true;
// CocoDB::$force_redis_html = @CocoDB::bloquedCacheByURL($_SERVER["REQUEST_URI"]) ? false : true;
CocoEmail::$smtp = true;
CocoEmail::$smtp_data["host"] = "mail.quantumasis.com";
CocoEmail::$smtp_data["port"] = "587";
CocoEmail::$smtp_data["secure"] = "STARTTLS";
CocoEmail::$smtp_data["username"] = "noreply@quantumasis.com";
CocoEmail::$smtp_data["password"] = "uK5DDSa7sjPm7YtBbkRR";
CocoEmail::$smtp_data["from"] = "noreply@quantumasis.com";
CocoEmail::$smtp_data["from_name"] = "QuantumASIS";
$plantilla = "template/estandar";
define("PLANTILLA",$plantilla);
define("RUTA_PLANTILLA","/".$plantilla);
if (@$_REQUEST["idioma"]=="es") $_REQUEST["idioma"] = "";
if (substr($_SERVER["REQUEST_URI"],0,4)=="/en/") $_REQUEST["idioma"]="en";
if (substr($_SERVER["REQUEST_URI"],0,4)=="/es/") $_REQUEST["idioma"]="es";
if (substr($_SERVER["REQUEST_URI"],0,4)=="/de/") $_REQUEST["idioma"]="de";
if (substr($_SERVER["REQUEST_URI"],0,4)=="/fr/") $_REQUEST["idioma"]="fr";
if (substr($_SERVER["REQUEST_URI"],0,4)=="/pt/") $_REQUEST["idioma"]="pt";
if (substr($_SERVER["REQUEST_URI"],0,4)=="/se/") $_REQUEST["idioma"]="se";
if (substr($_SERVER["REQUEST_URI"],0,5)=="/cat/") $_REQUEST["idioma"]="cat";
if (substr($_SERVER["REQUEST_URI"],0,4)=="/it/") $_REQUEST["idioma"]="it";
if (substr($_SERVER["REQUEST_URI"],0,4)=="/ko/") $_REQUEST["idioma"]="ko";
if (substr($_SERVER["REQUEST_URI"],0,4)=="/ch/") $_REQUEST["idioma"]="ch";
if (substr($_SERVER["REQUEST_URI"],0,4)=="/nu/") $_REQUEST["idioma"]="nu";
if (substr($_SERVER["REQUEST_URI"],0,4)=="/ru/") $_REQUEST["idioma"]="ru";
if (substr($_SERVER["REQUEST_URI"],0,4)=="/ni/") $_REQUEST["idioma"]="ni";
if (@$_REQUEST["idioma"]) define("RUTA_RAIZ","/".$_REQUEST["idioma"]); else define("RUTA_RAIZ","");
if (@$_REQUEST["idioma"]) define("ROOT","/".$_REQUEST["idioma"]); else define("ROOT","");
?>

15
sesion.php Executable file
View File

@@ -0,0 +1,15 @@
<?
if (session_status() == PHP_SESSION_NONE) { session_start(); }
require_once(dirname(__FILE__)."/lib/Module.php");
require_once(dirname(__FILE__)."/lib/Resource.class.php");
require_once(dirname(__FILE__)."/lib/variables.php");
require_once(dirname(__FILE__)."/lib/minifier.php");
if (!isset($_SESSION["user"])) {$_SESSION["user"]=null;}
if (isset($_GET["cerrarsesion"])){
unset($_SESSION["user"]);
session_destroy();
}
?>

397
slug.php Executable file
View File

@@ -0,0 +1,397 @@
<?
$sep = explode("?enlace=", @$_SERVER["REQUEST_URI"]);
if (@$sep[1]){
header("HTTP/1.1 301 Moved Permanently");
header("Location: http://".$_SERVER["HTTP_HOST"].$sep[0]."");
}
require_once "lib/variables.php";
$sufijo = ".html";
if (@$_REQUEST["tipo"]=="barra") $sufijo="";
// SISTEMA DE CACHE DE SLUGS PARA EVITAR CONSULTAS A LA BASE DE DATOS EN CADA PETICIÓN, SE ALMACENAN EN REDIS SI ESTÁ DISPONIBLE O EN MEMORIA SI NO
function slugCacheRedisKey($cacheKey){
return "SLUG_CACHE_".$_SERVER["HTTP_HOST"]."_".$cacheKey;
}
function slugRedisAvailable(){
static $available = null;
if (!is_null($available)) return $available;
if (!class_exists("CocoDB")) return false;
try{
CocoDB::initCache();
if (!@CocoDB::$redis) {
$available = false;
return $available;
}
if (!@CocoDB::$redis->isConnected()) {
$available = false;
return $available;
}
$available = true;
return $available;
}catch(Exception $e){
$available = false;
return $available;
}
}
function slugCacheRead($cacheKey){
global $slugRedisAvailable;
if (!$slugRedisAvailable) return null;
$redisKey = slugCacheRedisKey($cacheKey);
$rawRedis = CocoDB::cacheGet($redisKey);
if (!$rawRedis) return null;
$dataRedis = @json_decode($rawRedis,true);
return is_array($dataRedis) ? $dataRedis : null;
}
function slugCacheWrite($cacheKey,$data,$ttl = 0){
global $slugRedisAvailable;
if (!$slugRedisAvailable) return;
$redisKey = slugCacheRedisKey($cacheKey);
$expire = intval($ttl) > 0 ? intval($ttl) : null;
CocoDB::cacheSet($redisKey,json_encode($data),$expire);
}
function slugCacheDelete($cacheKey){
global $slugRedisAvailable;
if (!$slugRedisAvailable) return;
$redisKey = slugCacheRedisKey($cacheKey);
CocoDB::cacheSet($redisKey,"",1);
}
function slugRouteCacheKey($enlace){
return "slug-route-".md5($_SERVER["HTTP_HOST"]."|".$enlace);
}
function slugAliasCacheKey($aliasPath){
return "slug-alias-".md5($_SERVER["HTTP_HOST"]."|".$aliasPath);
}
function slugTranslationCacheKey($enlaceAux,$sufijo){
return "slug-translation-".md5($_SERVER["HTTP_HOST"]."|".$enlaceAux."|".$sufijo);
}
function slugGetCachedRoute($enlace){
$data = slugCacheRead(slugRouteCacheKey($enlace));
if (!is_array($data)) return null;
if (!@$data["expiresAt"] || intval($data["expiresAt"]) < time()) {
slugCacheDelete(slugRouteCacheKey($enlace));
return null;
}
return $data;
}
function slugSetCachedRoute($enlace,$data,$ttl = 120){
$ttl = max(5,intval($ttl));
$data["expiresAt"] = time() + $ttl;
slugCacheWrite(slugRouteCacheKey($enlace),$data,$ttl);
}
function slugGetCachedAlias($aliasPath){
$data = slugCacheRead(slugAliasCacheKey($aliasPath));
if (!is_array($data)) return null;
if (!@$data["expiresAt"] || intval($data["expiresAt"]) < time()) {
slugCacheDelete(slugAliasCacheKey($aliasPath));
return null;
}
return $data;
}
function slugSetCachedAlias($aliasPath,$data,$ttl = 120){
$ttl = max(5,intval($ttl));
$data["expiresAt"] = time() + $ttl;
slugCacheWrite(slugAliasCacheKey($aliasPath),$data,$ttl);
}
function slugGetCachedTranslation($enlaceAux,$sufijo){
$data = slugCacheRead(slugTranslationCacheKey($enlaceAux,$sufijo));
if (!is_array($data)) return null;
if (!@$data["expiresAt"] || intval($data["expiresAt"]) < time()) {
slugCacheDelete(slugTranslationCacheKey($enlaceAux,$sufijo));
return null;
}
return $data;
}
function slugSetCachedTranslation($enlaceAux,$sufijo,$data,$ttl = 120){
$ttl = max(5,intval($ttl));
$data["expiresAt"] = time() + $ttl;
slugCacheWrite(slugTranslationCacheKey($enlaceAux,$sufijo),$data,$ttl);
}
function slugGetTablesWithEnlace($database){
$cacheKey = "slug-tables-enlace-".md5($_SERVER["HTTP_HOST"]."|".$database);
$cacheData = slugCacheRead($cacheKey);
if (is_array($cacheData) && intval(@$cacheData["expiresAt"]) >= time() && is_array(@$cacheData["data"])) {
return $cacheData["data"];
}
$sql = "
SELECT DISTINCT TABLE_NAME,COLUMN_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE COLUMN_NAME IN ('enlace')
AND TABLE_SCHEMA='".mysql_real_escape_string($database)."'
";
$result = mysql_query($sql) or die(mysql_error());
$tables = array();
while($row = mysql_fetch_assoc($result)){
$tables[] = $row;
}
slugCacheWrite($cacheKey,array(
"expiresAt" => time() + 600,
"data" => $tables
),600);
return $tables;
}
// HASTA AQUI
$padre = 0;
$padreContenidos = false;
$controlador = "";
$tabla = null;
$registro = null;
$useInformationSchemaCache = defined("USE_INFORMATION_SCHEMA_CACHE") && USE_INFORMATION_SCHEMA_CACHE && class_exists("CocoDB");
$slugRedisAvailable = $useInformationSchemaCache ? slugRedisAvailable() : false;
$slugCacheEnabled = $useInformationSchemaCache && $slugRedisAvailable;
/********/
// GESTION DEL ALIAS
/********/
$aliasPath = "/".@$_REQUEST["enlace"].$sufijo;
$aliasData = $slugCacheEnabled ? slugGetCachedAlias($aliasPath) : null;
if (!is_array($aliasData)){
$aliasPathEscaped = mysql_real_escape_string($aliasPath);
$existe_alias = mysql_fetch_assoc(mysql_query("SELECT url_destino FROM cms_alias_urls WHERE url_alias = '".$aliasPathEscaped."' LIMIT 1"));
if (@$existe_alias && isset($existe_alias["url_destino"])) {
$aliasData = array(
"found" => true,
"url_destino" => $existe_alias["url_destino"]
);
if ($slugCacheEnabled) slugSetCachedAlias($aliasPath,$aliasData,300);
}else{
$aliasData = array("found" => false);
if ($slugCacheEnabled) slugSetCachedAlias($aliasPath,$aliasData,60);
}
}
if (@$aliasData["found"] && @$_REQUEST["enlace"]) {
$protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' || $_SERVER['SERVER_PORT'] == 443) ? "https://" : "http://";
header("HTTP/1.1 301 Moved Permanently");
if (strpos(@$aliasData["url_destino"],"http") > -1){
header("Location: ".$aliasData["url_destino"]."");
}else{
header("Location: ".$protocol.$_SERVER["HTTP_HOST"].$aliasData["url_destino"]."");
}
die();
}
$_REQUEST["enlace"] = str_replace("amp/", "", @$_REQUEST["enlace"]);
$enlace_aux = @$_REQUEST["enlace"];
if (@$_REQUEST["idioma"]) {
$enlace_aux = $_REQUEST["idioma"]."/".$enlace_aux;
$enlace_aux = str_replace($_REQUEST["idioma"]."/".$_REQUEST["idioma"]."/", $_REQUEST["idioma"]."/", $enlace_aux);
}
$translationData = $slugCacheEnabled ? slugGetCachedTranslation($enlace_aux,$sufijo) : null;
if (is_array($translationData) && isset($translationData["found"])) {
if (@$translationData["found"]){
$_REQUEST["enlace"] = @$translationData["enlace"];
$_REQUEST["idioma"] = @$translationData["idioma"];
}else{
$_REQUEST["idioma"]="";
}
}else{
$fieldValue = @$enlace_aux.$sufijo;
$fieldValueB64 = base64_encode($fieldValue);
$fieldValueB64Slash = base64_encode("/".$fieldValue);
$result = mysql_query("SELECT prefix,tableName,recordNum,fieldName FROM cms_traducciones
WHERE fieldValue IN ('".mysql_real_escape_string($fieldValue)."','".mysql_real_escape_string($fieldValueB64)."','".mysql_real_escape_string($fieldValueB64Slash)."')
AND fieldName = 'enlace'
AND tableName != 'builder_custom'
LIMIT 1");
$foundTranslation = false;
if ($result){
$record = mysql_fetch_assoc($result);
if ($record){
$tableName = "cms_".preg_replace("/[^a-zA-Z0-9_]/","",@$record["tableName"]);
$fieldName = preg_replace("/[^a-zA-Z0-9_]/","",@$record["fieldName"]);
$recordNum = intval(@$record["recordNum"]);
if ($tableName && $fieldName && $recordNum > 0){
$result2 = mysql_query("SELECT ".$fieldName." FROM ".$tableName." WHERE num=".$recordNum." LIMIT 1");
if ($result2){
$record2 = mysql_fetch_assoc($result2);
if (is_array($record2) && isset($record2[$fieldName])) {
$_REQUEST["enlace"] = (@$sufijo=="/") ? substr($record2[$fieldName],1,strlen($record2[$fieldName])-2) : substr(str_replace($sufijo,"",$record2[$fieldName]),1,10000);
$_REQUEST["idioma"] = @$record["prefix"];
$foundTranslation = true;
}
}
}
}
}
if ($foundTranslation){
if ($slugCacheEnabled){
slugSetCachedTranslation($enlace_aux,$sufijo,array(
"found" => true,
"enlace" => @$_REQUEST["enlace"],
"idioma" => @$_REQUEST["idioma"]
),300);
}
}else{
$_REQUEST["idioma"]="";
if ($slugCacheEnabled){
slugSetCachedTranslation($enlace_aux,$sufijo,array(
"found" => false
),60);
}
}
}
$enlace = "/".@$_REQUEST["enlace"].$sufijo;
$enlaceEscaped = mysql_real_escape_string($enlace);
$routeFromCache = $slugCacheEnabled ? slugGetCachedRoute($enlace) : null;
$routeResolved = false;
if (is_array($routeFromCache) && isset($routeFromCache["found"])) {
if (@$routeFromCache["found"]) {
$tablaCache = @$routeFromCache["tabla"];
$registroCache = intval(@$routeFromCache["registro"]);
if ($tablaCache && $registroCache) {
$encontrado = mysql_fetch_assoc(mysql_query("SELECT * FROM ".$tablaCache." WHERE num=".$registroCache." AND enlace='".$enlaceEscaped."' LIMIT 1"));
if (@$encontrado){
$tabla = $tablaCache;
$registro = intval($encontrado["num"]);
$padre = intval(@$encontrado["parentNum"]);
if (isset($encontrado["layout"])&&$padre) $padreContenidos = mysql_fetch_assoc(mysql_query("select * from ".$tabla." where num=".$padre." AND layout=1 LIMIT 1")) ? true : false;
$controlador = @$encontrado["controlador"];
$routeResolved = true;
}else{
slugCacheDelete(slugRouteCacheKey($enlace));
}
}
}else{
$routeResolved = true;
}
}
if (!$routeResolved){
if ($slugCacheEnabled){
$resultados = slugGetTablesWithEnlace($SETTINGS["mysql"]["database"]);
}else{
$sql = "
SELECT DISTINCT TABLE_NAME,COLUMN_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE COLUMN_NAME IN ('enlace')
AND TABLE_SCHEMA='".mysql_real_escape_string($SETTINGS["mysql"]["database"])."'
";
$result = mysql_query($sql) or die(mysql_error());
$resultados = array();
while($row = mysql_fetch_assoc($result)){
$resultados[] = $row;
}
}
foreach($resultados as $record){
$tableName = isset($record["TABLE_NAME"]) ? $record["TABLE_NAME"] : @$record["table_name"];
$columnName = isset($record["COLUMN_NAME"]) ? $record["COLUMN_NAME"] : @$record["column_name"];
if (!$tableName || !$columnName) continue;
$encontrado = mysql_fetch_assoc(mysql_query("SELECT * FROM ".$tableName." WHERE ".$columnName."='".$enlaceEscaped."' LIMIT 1"));
if (@$encontrado){
$tabla = $tableName;
$registro = $encontrado["num"];
$padre = intval(@$encontrado["parentNum"]);
if (isset($encontrado["layout"])&&$padre) $padreContenidos = mysql_fetch_assoc(mysql_query("select * from ".$tableName." where num=".$padre." AND layout=1 LIMIT 1")) ? true : false;
$controlador = @$encontrado["controlador"];
if ($columnName!="enlace") {
$controlador="reserva.php";
}
}
}
if ($slugCacheEnabled){
if (@$tabla && @$registro){
slugSetCachedRoute($enlace,array(
"found" => true,
"tabla" => $tabla,
"registro" => intval($registro)
),300);
}else{
slugSetCachedRoute($enlace,array(
"found" => false
),60);
}
}
}
/*var_dump(CocoDB::$force_redis_html);
var_dump($_SERVER["REQUEST_URI"]);*/
if (class_exists("CocoDB") && isset(CocoDB::$force_redis_html) && CocoDB::$force_redis_html){
$hash = CocoDB::cacheGenerateHash("HTML_".md5(json_encode($_REQUEST)));
$data2 = CocoDB::cacheGet($hash);
if (@$data2) {
echo CocoDB::replaceHooksToken($data2);
die();
}
}
$resultInclude = null;
ob_start();
if (!@$tabla){
$num=0;
addPlugins("slug", $pluginData);
include("apartados.php");
}else{
$schema = loadSchema($tabla);
if (@$schema["controller"]!=""&&@$schema["controller"]!="apartados.php"){
if (@$registro) {
$num=$registro;
if (@$num && !@$_REQUEST["num"]) $_REQUEST["num"] = $num;
$pluginData = array("num" => $registro, "tabla" => $tabla, "schema" => $schema);
addPlugins("slug", $pluginData);
}
if (@$controlador){
include(dirname(__FILE__)."/".$controlador);
}else{
include(dirname(__FILE__)."/".$schema["controller"]);
}
}else{
$num=$registro;
if (@$num && !@$_REQUEST["num"]) $_REQUEST["num"] = $num;
$pluginData = array("num" => $registro, "tabla" => $tabla, "schema" => $schema);
addPlugins("slug", $pluginData);
if (!@$padre){
if (@$controlador){
$num=(@$_REQUEST["num"]) ? $_REQUEST["num"] : @$registro;
if (@$num && !@$_REQUEST["num"]) $_REQUEST["num"] = $num;
include(dirname(__FILE__)."/".$controlador);
}else{
include(dirname(__FILE__)."/apartados.php");
}
}else{
$familia = $padre;
if (@$controlador){
$num=(@$_REQUEST["num"]) ? $_REQUEST["num"] : @$registro;
if (@$num && !@$_REQUEST["num"]) $_REQUEST["num"] = $num;
include($controlador);
}else{
if ($padreContenidos){
include(dirname(__FILE__)."/contenidos.php");
}else{
include(dirname(__FILE__)."/apartados.php");
}
}
}
}
}
$resultInclude = ob_get_clean();
addPlugins("pre_render",$resultInclude);
if (class_exists("CocoDB") && isset(CocoDB::$force_redis_html) && CocoDB::$force_redis_html && @$hash){
CocoDB::cacheSet(@$hash,$resultInclude);
}
echo $resultInclude;
?>

26
template/estandar/apartados.tpl Executable file
View File

@@ -0,0 +1,26 @@
<section id="contenido_principal">
<div class="container mx-auto">
<h1 class="titular"><?=@$apartado["titulo_alternativo"] ? t($apartado, "titulo_alternativo") : t($apartado, "name");?></h1>
<div class="h-2"></div>
<div class="text-gray-600 text-xl">
<?=t($apartado,"content");?>
</div>
</div>
<div class="h-4"></div>
<? if (@$apartado["galeria_de_fotos"]) {?>
<div class="container">
<?=modulo("galeria_interno", array("galeria" => $apartado["galeria_de_fotos"]));?>
</div>
<div class="h-4"></div>
<?}?>
<? if (@$apartado["archivos_adjuntos"]) {?>
<div class="container">
<?=modulo("adjuntos_interno", array("adjuntos" => $apartado["archivos_adjuntos"]));?>
<div class="h-4"></div>
</div>
<?}?>
<div class="h-12"></div>
</section>

View File

@@ -0,0 +1,115 @@
<!DOCTYPE html>
<html lang="<?=(@$_REQUEST["idioma"]) ? @$_REQUEST["idioma"] : "es";?>">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<meta name="description" content="<?=$meta_descripcion;?>">
<meta name="keywords" content="<?=$meta_palabras;?>">
<meta name="author" content="Coco Solution">
<? if (@$configuracionRecord["pwa_theme_color"]) {?>
<meta name="theme-color" content="<?=$configuracionRecord["pwa_theme_color"];?>">
<? }?>
<?=@$otros_metas;?>
<title><?=$titulo_de_pagina;?></title>
<? if (@$configuracionRecord["usar_service_worker"]) {?>
<link rel="manifest" href="/manifest.json">
<? }?>
<? $dummy = []; addPlugins("tpl_head",$dummy);?>
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
<![endif]-->
<link rel="shortcut icon" href="<?=RUTA_PLANTILLA;?>/icons/favicon.ico" type="image/x-icon" />
<link rel="apple-touch-icon" href="<?=RUTA_PLANTILLA;?>/icons/apple-touch-icon.png" />
<link rel="apple-touch-icon" sizes="57x57" href="<?=RUTA_PLANTILLA;?>/icons/apple-touch-icon-57x57.png" />
<link rel="apple-touch-icon" sizes="72x72" href="<?=RUTA_PLANTILLA;?>/icons/apple-touch-icon-72x72.png" />
<link rel="apple-touch-icon" sizes="76x76" href="<?=RUTA_PLANTILLA;?>/icons/apple-touch-icon-76x76.png" />
<link rel="apple-touch-icon" sizes="114x114" href="<?=RUTA_PLANTILLA;?>/icons/apple-touch-icon-114x114.png" />
<link rel="apple-touch-icon" sizes="120x120" href="<?=RUTA_PLANTILLA;?>/icons/apple-touch-icon-120x120.png" />
<link rel="apple-touch-icon" sizes="144x144" href="<?=RUTA_PLANTILLA;?>/icons/apple-touch-icon-144x144.png" />
<link rel="apple-touch-icon" sizes="152x152" href="<?=RUTA_PLANTILLA;?>/icons/apple-touch-icon-152x152.png" />
<?
if (@$alternate) {
foreach ($alternate as $alt):
?>
<link rel="alternate" href="<?=protocol()."://".$_SERVER["HTTP_HOST"].base64_decode($alt["fieldValue"]);?>" hreflang="<?=$alt["prefix"];?>" />
<?
endforeach;
}
?>
<link rel="preconnect" href="https://fonts.gstatic.com/" crossorigin>
<link rel="preconnect" href="https://maxcdn.bootstrapcdn.com/" crossorigin>
<style>#loading{position: fixed; z-index: 9999; transform: translateZ(100px); -webkit-transform: translateZ(100px); -moz-transform: translateZ(100px); background-color: #fff; left: 0; top: 0; width: 100%; height: 100%; display: flex; justify-content: center; -webkit-justify-content: center; align-items: center; -webkit-align-items: center;}.sk-folding-cube{margin:20px auto;width:40px;height:40px;position:relative;-webkit-transform:rotateZ(45deg);transform:rotateZ(45deg)}.sk-folding-cube .sk-cube{float:left;width:50%;height:50%;position:relative;-webkit-transform:scale(1.1);-ms-transform:scale(1.1);transform:scale(1.1)}.sk-folding-cube .sk-cube:before{content:'';position:absolute;top:0;left:0;width:100%;height:100%;background-color:#40A83C;-webkit-animation:sk-foldCubeAngle 2.4s infinite linear both;animation:sk-foldCubeAngle 2.4s infinite linear both;-webkit-transform-origin:100% 100%;-ms-transform-origin:100% 100%;transform-origin:100% 100%}.sk-folding-cube .sk-cube2{-webkit-transform:scale(1.1) rotateZ(90deg);transform:scale(1.1) rotateZ(90deg)}.sk-folding-cube .sk-cube3{-webkit-transform:scale(1.1) rotateZ(180deg);transform:scale(1.1) rotateZ(180deg)}.sk-folding-cube .sk-cube4{-webkit-transform:scale(1.1) rotateZ(270deg);transform:scale(1.1) rotateZ(270deg)}.sk-folding-cube .sk-cube2:before{-webkit-animation-delay:.3s;animation-delay:.3s}.sk-folding-cube .sk-cube3:before{-webkit-animation-delay:.6s;animation-delay:.6s}.sk-folding-cube .sk-cube4:before{-webkit-animation-delay:.9s;animation-delay:.9s}@-webkit-keyframes sk-foldCubeAngle{0%,10%{-webkit-transform:perspective(140px) rotateX(-180deg);transform:perspective(140px) rotateX(-180deg);opacity:0}25%,75%{-webkit-transform:perspective(140px) rotateX(0);transform:perspective(140px) rotateX(0);opacity:1}100%,90%{-webkit-transform:perspective(140px) rotateY(180deg);transform:perspective(140px) rotateY(180deg);opacity:0}}@keyframes sk-foldCubeAngle{0%,10%{-webkit-transform:perspective(140px) rotateX(-180deg);transform:perspective(140px) rotateX(-180deg);opacity:0}25%,75%{-webkit-transform:perspective(140px) rotateX(0);transform:perspective(140px) rotateX(0);opacity:1}100%,90%{-webkit-transform:perspective(140px) rotateY(180deg);transform:perspective(140px) rotateY(180deg);opacity:0}}</style>
<?
if (@$configuracionRecord["otros_scripts"]) {
echo base64_decode(t($configuracionRecord, "otros_scripts"));
}
?>
</head>
<body <? if (@$index) {?>class="portada"<?}?>>
<? if (@$configuracionRecord["pagina_publicada"] || true) {?>
<div id="loading">
<div class="sk-folding-cube">
<div class="sk-cube1 sk-cube"></div>
<div class="sk-cube2 sk-cube"></div>
<div class="sk-cube4 sk-cube"></div>
<div class="sk-cube3 sk-cube"></div>
</div>
</div>
<? }?>
<header>
<nav class="navbar navbar-default navbar-fixed-top">
<div class="container">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="<?=RUTA_RAIZ;?>/"><img src="<?=RUTA_PLANTILLA;?>/images/logo.png" alt="<?=t($configuracionRecord, "tienda_nombre_empresa");?>"></a>
</div>
<!-- Collect the nav links, forms, and other content for toggling -->
<div class="collapse navbar-collapse" id="navbar">
<ul class="nav navbar-nav navbar-right">
<? muestramenu();?>
</ul>
</div><!-- /.navbar-collapse -->
</div><!-- /.container-fluid -->
<? if (@$configuracionTienda["categorias_nav"] && HAY_TIENDA) {?>
<div id="postnav">
<div class="container">
<ul class="lista-destacadas">
<? foreach ($configuracionTienda["categorias_nav_bd"] as $categoria):?>
<li<?=comprueba_si_activo($categoria)?>>
<a href="<?=t($categoria, "enlace");?>" data-category="<?=$categoria["num"];?>">
<? if (@$categoria["icono"]) {?>
<img src="<?=parsea_imagen($categoria["icono"][0]["urlPath"]);?>" alt="<?=addslashes(t($categoria, "name"));?>">
<? }?>
<?=t($categoria, "name");?>
</a>
</li>
<? endforeach;?>
</ul>
</div>
</div>
<? }?>
</nav>
</header>

3340
template/estandar/css/animate.css vendored Executable file

File diff suppressed because it is too large Load Diff

9
template/estandar/css/animate.min.css vendored Executable file

File diff suppressed because one or more lines are too long

1
template/estandar/css/aos.css Executable file

File diff suppressed because one or more lines are too long

1353
template/estandar/css/bootstrap-grid.css vendored Executable file

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

330
template/estandar/css/bootstrap-reboot.css vendored Executable file
View File

@@ -0,0 +1,330 @@
html {
box-sizing: border-box;
font-family: sans-serif;
line-height: 1.15;
-webkit-text-size-adjust: 100%;
-ms-text-size-adjust: 100%;
-ms-overflow-style: scrollbar;
-webkit-tap-highlight-color: transparent;
}
*,
*::before,
*::after {
box-sizing: inherit;
}
@-ms-viewport {
width: device-width;
}
article, aside, dialog, figcaption, figure, footer, header, hgroup, main, nav, section {
display: block;
}
body {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
font-size: 1rem;
font-weight: normal;
line-height: 1.5;
color: #212529;
background-color: #fff;
}
[tabindex="-1"]:focus {
outline: none !important;
}
hr {
box-sizing: content-box;
height: 0;
overflow: visible;
}
h1, h2, h3, h4, h5, h6 {
margin-top: 0;
margin-bottom: .5rem;
}
p {
margin-top: 0;
margin-bottom: 1rem;
}
abbr[title],
abbr[data-original-title] {
text-decoration: underline;
-webkit-text-decoration: underline dotted;
text-decoration: underline dotted;
cursor: help;
border-bottom: 0;
}
address {
margin-bottom: 1rem;
font-style: normal;
line-height: inherit;
}
ol,
ul,
dl {
margin-top: 0;
margin-bottom: 1rem;
}
ol ol,
ul ul,
ol ul,
ul ol {
margin-bottom: 0;
}
dt {
font-weight: bold;
}
dd {
margin-bottom: .5rem;
margin-left: 0;
}
blockquote {
margin: 0 0 1rem;
}
dfn {
font-style: italic;
}
b,
strong {
font-weight: bolder;
}
small {
font-size: 80%;
}
sub,
sup {
position: relative;
font-size: 75%;
line-height: 0;
vertical-align: baseline;
}
sub {
bottom: -.25em;
}
sup {
top: -.5em;
}
a {
color: #007bff;
text-decoration: none;
background-color: transparent;
-webkit-text-decoration-skip: objects;
}
a:hover {
color: #0056b3;
text-decoration: underline;
}
a:not([href]):not([tabindex]) {
color: inherit;
text-decoration: none;
}
a:not([href]):not([tabindex]):focus, a:not([href]):not([tabindex]):hover {
color: inherit;
text-decoration: none;
}
a:not([href]):not([tabindex]):focus {
outline: 0;
}
pre,
code,
kbd,
samp {
font-family: monospace, monospace;
font-size: 1em;
}
pre {
margin-top: 0;
margin-bottom: 1rem;
overflow: auto;
}
figure {
margin: 0 0 1rem;
}
img {
vertical-align: middle;
border-style: none;
}
svg:not(:root) {
overflow: hidden;
}
a,
area,
button,
[role="button"],
input,
label,
select,
summary,
textarea {
-ms-touch-action: manipulation;
touch-action: manipulation;
}
table {
border-collapse: collapse;
}
caption {
padding-top: 0.75rem;
padding-bottom: 0.75rem;
color: #868e96;
text-align: left;
caption-side: bottom;
}
th {
text-align: left;
}
label {
display: inline-block;
margin-bottom: .5rem;
}
button:focus {
outline: 1px dotted;
outline: 5px auto -webkit-focus-ring-color;
}
input,
button,
select,
optgroup,
textarea {
margin: 0;
font-family: inherit;
font-size: inherit;
line-height: inherit;
}
button,
input {
overflow: visible;
}
button,
select {
text-transform: none;
}
button,
html [type="button"],
[type="reset"],
[type="submit"] {
-webkit-appearance: button;
}
button::-moz-focus-inner,
[type="button"]::-moz-focus-inner,
[type="reset"]::-moz-focus-inner,
[type="submit"]::-moz-focus-inner {
padding: 0;
border-style: none;
}
input[type="radio"],
input[type="checkbox"] {
box-sizing: border-box;
padding: 0;
}
input[type="date"],
input[type="time"],
input[type="datetime-local"],
input[type="month"] {
-webkit-appearance: listbox;
}
textarea {
overflow: auto;
resize: vertical;
}
fieldset {
min-width: 0;
padding: 0;
margin: 0;
border: 0;
}
legend {
display: block;
width: 100%;
max-width: 100%;
padding: 0;
margin-bottom: .5rem;
font-size: 1.5rem;
line-height: inherit;
color: inherit;
white-space: normal;
}
progress {
vertical-align: baseline;
}
[type="number"]::-webkit-inner-spin-button,
[type="number"]::-webkit-outer-spin-button {
height: auto;
}
[type="search"] {
outline-offset: -2px;
-webkit-appearance: none;
}
[type="search"]::-webkit-search-cancel-button,
[type="search"]::-webkit-search-decoration {
-webkit-appearance: none;
}
::-webkit-file-upload-button {
font: inherit;
-webkit-appearance: button;
}
output {
display: inline-block;
}
summary {
display: list-item;
}
template {
display: none;
}
[hidden] {
display: none !important;
}
/*# sourceMappingURL=bootstrap-reboot.css.map */

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,2 @@
html{box-sizing:border-box;font-family:sans-serif;line-height:1.15;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;-ms-overflow-style:scrollbar;-webkit-tap-highlight-color:transparent}*,::after,::before{box-sizing:inherit}@-ms-viewport{width:device-width}article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}body{margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;font-size:1rem;font-weight:400;line-height:1.5;color:#212529;background-color:#fff}[tabindex="-1"]:focus{outline:0!important}hr{box-sizing:content-box;height:0;overflow:visible}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem}p{margin-top:0;margin-bottom:1rem}abbr[data-original-title],abbr[title]{text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;border-bottom:0}address{margin-bottom:1rem;font-style:normal;line-height:inherit}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}dfn{font-style:italic}b,strong{font-weight:bolder}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#007bff;text-decoration:none;background-color:transparent;-webkit-text-decoration-skip:objects}a:hover{color:#0056b3;text-decoration:underline}a:not([href]):not([tabindex]){color:inherit;text-decoration:none}a:not([href]):not([tabindex]):focus,a:not([href]):not([tabindex]):hover{color:inherit;text-decoration:none}a:not([href]):not([tabindex]):focus{outline:0}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}pre{margin-top:0;margin-bottom:1rem;overflow:auto}figure{margin:0 0 1rem}img{vertical-align:middle;border-style:none}svg:not(:root){overflow:hidden}[role=button],a,area,button,input,label,select,summary,textarea{-ms-touch-action:manipulation;touch-action:manipulation}table{border-collapse:collapse}caption{padding-top:.75rem;padding-bottom:.75rem;color:#868e96;text-align:left;caption-side:bottom}th{text-align:left}label{display:inline-block;margin-bottom:.5rem}button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,input{overflow:visible}button,select{text-transform:none}[type=reset],[type=submit],button,html [type=button]{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{padding:0;border-style:none}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=date],input[type=datetime-local],input[type=month],input[type=time]{-webkit-appearance:listbox}textarea{overflow:auto;resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;max-width:100%;padding:0;margin-bottom:.5rem;font-size:1.5rem;line-height:inherit;color:inherit;white-space:normal}progress{vertical-align:baseline}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:none}[type=search]::-webkit-search-cancel-button,[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}summary{display:list-item}template{display:none}[hidden]{display:none!important}
/*# sourceMappingURL=bootstrap-reboot.min.css.map */

File diff suppressed because one or more lines are too long

263
template/estandar/css/bootstrap-select.css vendored Executable file
View File

@@ -0,0 +1,263 @@
/*!
* Bootstrap-select v1.7.2 (http://silviomoreto.github.io/bootstrap-select)
*
* Copyright 2013-2015 bootstrap-select
* Licensed under MIT (https://github.com/silviomoreto/bootstrap-select/blob/master/LICENSE)
*/
.bootstrap-select {
width: 220px \0;
/*IE9 and below*/
}
.bootstrap-select > .dropdown-toggle {
width: 100%;
padding-right: 25px;
}
.has-error .bootstrap-select .dropdown-toggle,
.error .bootstrap-select .dropdown-toggle {
border-color: #b94a48;
}
.bootstrap-select.fit-width {
width: auto !important;
}
.bootstrap-select:not([class*="col-"]):not([class*="form-control"]):not(.input-group-btn) {
width: 220px;
}
.bootstrap-select .dropdown-toggle:focus {
outline: thin dotted #333333 !important;
outline: 5px auto -webkit-focus-ring-color !important;
outline-offset: -2px;
}
.bootstrap-select.form-control {
margin-bottom: 0;
padding: 0;
border: none;
}
.bootstrap-select.form-control:not([class*="col-"]) {
width: 100%;
}
.bootstrap-select.form-control.input-group-btn {
z-index: auto;
}
.bootstrap-select.btn-group:not(.input-group-btn),
.bootstrap-select.btn-group[class*="col-"] {
float: none;
display: inline-block;
margin-left: 0;
}
.bootstrap-select.btn-group.dropdown-menu-right,
.bootstrap-select.btn-group[class*="col-"].dropdown-menu-right,
.row .bootstrap-select.btn-group[class*="col-"].dropdown-menu-right {
float: right;
}
.form-inline .bootstrap-select.btn-group,
.form-horizontal .bootstrap-select.btn-group,
.form-group .bootstrap-select.btn-group {
margin-bottom: 0;
}
.form-group-lg .bootstrap-select.btn-group.form-control,
.form-group-sm .bootstrap-select.btn-group.form-control {
padding: 0;
}
.form-inline .bootstrap-select.btn-group .form-control {
width: 100%;
}
.bootstrap-select.btn-group.disabled,
.bootstrap-select.btn-group > .disabled {
cursor: not-allowed;
}
.bootstrap-select.btn-group.disabled:focus,
.bootstrap-select.btn-group > .disabled:focus {
outline: none !important;
}
.bootstrap-select.btn-group .dropdown-toggle .filter-option {
display: inline-block;
overflow: hidden;
width: 100%;
text-align: left;
}
.bootstrap-select.btn-group .dropdown-toggle .caret {
position: absolute;
top: 50%;
right: 12px;
margin-top: -2px;
vertical-align: middle;
}
.bootstrap-select.btn-group[class*="col-"] .dropdown-toggle {
width: 100%;
}
.bootstrap-select.btn-group .dropdown-menu {
min-width: 100%;
z-index: 1035;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
.bootstrap-select.btn-group .dropdown-menu.inner {
position: static;
float: none;
border: 0;
padding: 0;
margin: 0;
border-radius: 0;
-webkit-box-shadow: none;
box-shadow: none;
}
.bootstrap-select.btn-group .dropdown-menu li {
position: relative;
}
.bootstrap-select.btn-group .dropdown-menu li.active small {
color: #fff;
}
.bootstrap-select.btn-group .dropdown-menu li.disabled a {
cursor: not-allowed;
}
.bootstrap-select.btn-group .dropdown-menu li a {
cursor: pointer;
}
.bootstrap-select.btn-group .dropdown-menu li a.opt {
position: relative;
padding-left: 2.25em;
}
.bootstrap-select.btn-group .dropdown-menu li a span.check-mark {
display: none;
}
.bootstrap-select.btn-group .dropdown-menu li a span.text {
display: inline-block;
}
.bootstrap-select.btn-group .dropdown-menu li small {
padding-left: 0.5em;
}
.bootstrap-select.btn-group .dropdown-menu .notify {
position: absolute;
bottom: 5px;
width: 96%;
margin: 0 2%;
min-height: 26px;
padding: 3px 5px;
background: #f5f5f5;
border: 1px solid #e3e3e3;
-webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);
pointer-events: none;
opacity: 0.9;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
.bootstrap-select.btn-group .no-results {
padding: 3px;
background: #f5f5f5;
margin: 0 5px;
white-space: nowrap;
}
.bootstrap-select.btn-group.fit-width .dropdown-toggle .filter-option {
position: static;
}
.bootstrap-select.btn-group.fit-width .dropdown-toggle .caret {
position: static;
top: auto;
margin-top: -1px;
}
.bootstrap-select.btn-group.show-tick .dropdown-menu li.selected a span.check-mark {
position: absolute;
display: inline-block;
right: 15px;
margin-top: 5px;
}
.bootstrap-select.btn-group.show-tick .dropdown-menu li a span.text {
margin-right: 34px;
}
.bootstrap-select.show-menu-arrow.open > .dropdown-toggle {
z-index: 1036;
}
.bootstrap-select.show-menu-arrow .dropdown-toggle:before {
content: '';
border-left: 7px solid transparent;
border-right: 7px solid transparent;
border-bottom: 7px solid rgba(204, 204, 204, 0.2);
position: absolute;
bottom: -4px;
left: 9px;
display: none;
}
.bootstrap-select.show-menu-arrow .dropdown-toggle:after {
content: '';
border-left: 6px solid transparent;
border-right: 6px solid transparent;
border-bottom: 6px solid white;
position: absolute;
bottom: -4px;
left: 10px;
display: none;
}
.bootstrap-select.show-menu-arrow.dropup .dropdown-toggle:before {
bottom: auto;
top: -3px;
border-top: 7px solid rgba(204, 204, 204, 0.2);
border-bottom: 0;
}
.bootstrap-select.show-menu-arrow.dropup .dropdown-toggle:after {
bottom: auto;
top: -3px;
border-top: 6px solid white;
border-bottom: 0;
}
.bootstrap-select.show-menu-arrow.pull-right .dropdown-toggle:before {
right: 12px;
left: auto;
}
.bootstrap-select.show-menu-arrow.pull-right .dropdown-toggle:after {
right: 13px;
left: auto;
}
.bootstrap-select.show-menu-arrow.open > .dropdown-toggle:before,
.bootstrap-select.show-menu-arrow.open > .dropdown-toggle:after {
display: block;
}
.bs-searchbox,
.bs-actionsbox,
.bs-donebutton {
padding: 4px 8px;
}
.bs-actionsbox {
float: left;
width: 100%;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
.bs-actionsbox .btn-group button {
width: 50%;
}
.bs-donebutton {
float: left;
width: 100%;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
.bs-donebutton .btn-group button {
width: 100%;
}
.bs-searchbox + .bs-actionsbox {
padding: 0 8px 4px;
}
.bs-searchbox .form-control {
margin-bottom: 0;
width: 100%;
}
select.bs-select-hidden,
select.selectpicker {
display: none !important;
}
select.mobile-device {
position: absolute !important;
top: 0;
left: 0;
display: block !important;
width: 100%;
height: 100% !important;
opacity: 0;
}
/*# sourceMappingURL=bootstrap-select.css.map */

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Some files were not shown because too many files have changed in this diff Show More