shell bypass 403
<?
App::uses('Model', 'Model');
App::uses('Folder', 'Utility');
App::uses('File', 'Utility');
class AppModel extends Model {
public function beforeSave($options = array()) {
//Comprobamos si se trata de una entidad de galería de imágenes
$this->galeria = (bool) substr_count($this->name, 'Galeria');
//Galería
if ($this->galeria) {
//Preparamos la galería
$this->prepararGaleria();
} else {
//Archivos
if (!empty($this->archivos)) {
$this->prepararArchivos();
}
//Fechas
if (array_key_exists('fecha', $this->data[$this->name]) && $this->_schema['fecha']['type'] == 'date') {
if (!empty($this->data[$this->name]['fecha'])) {
$this->setDate($this->data[$this->name]['fecha']);
} else {
$this->data[$this->name]['fecha'] = null;
}
}
if (array_key_exists('fecha_inicio', $this->data[$this->name]) && $this->_schema['fecha_inicio']['type'] == 'date') {
if (!empty($this->data[$this->name]['fecha_inicio'])) {
$this->setDate($this->data[$this->name]['fecha_inicio']);
} else {
$this->data[$this->name]['fecha_inicio'] = null;
}
}
if (array_key_exists('fecha_fin', $this->data[$this->name]) && $this->_schema['fecha_fin']['type'] == 'date') {
if (!empty($this->data[$this->name]['fecha_fin'])) {
$this->setDate($this->data[$this->name]['fecha_fin']);
} else {
$this->data[$this->name]['fecha_fin'] = null;
}
}
}
}
public function afterSave($created, $options = array()) {
if (array_key_exists('id', $this->_schema)) {
$this->entidad = $this->findById($this->id); //necesario para obtener información guardada para la generación de ciertos campos (búsqueda...)
}
//Galería
if ($this->galeria) {
//Guardamos la galería
$this->guardarGaleria();
$this->generarImagenDn();
} else {
//Archivos
if (!empty($this->archivos)) {
$this->guardarArchivos();
}
//Actualizamos campos de la entidad
if (!empty($this->entidad)) {
$datos = array();
$db = $this->getDataSource();
//Seo
if (array_key_exists('nombre', $this->data[$this->name]) && array_key_exists('seo', $this->_schema)) {
$datos['seo'] = $db->value($this->getSeo($this->id, $this->data[$this->name]['nombre']), 'string');
}
if (!empty($datos)) {
$this->updateAll($datos, array($this->name . '.id' => $this->id));
}
}
}
}
public function beforeDelete($cascade = true) {
//Comprobamos si se trata de una entidad de galería de imágenes
$this->galeria = (bool) substr_count($this->name, 'Galeria');
//Galería
if ($this->galeria) {
$galeria = $this->read(null, $this->id);
if (!empty($galeria[$this->name]['imagen'])) {
$this->removeFile(substr($galeria[$this->name]['imagen'], 1));
}
$this->generarImagenDn($this->id);
} else {
//Eliminamos los ficheros de la entidad
$this->removeDir('blobs' . DS . strtolower(Inflector::slug($this->name)) . DS . $this->id);
exec('rm -rf ' . WWW_ROOT . 'i/*/' . strtolower(Inflector::slug($this->name)) . '/' . $this->id); //eliminamos las imágenes cacheadas de la entidad
}
}
public function afterDelete() {
//Galería
if ($this->galeria) {
$this->reordenarGaleria();
}
}
protected function getSeo($id, $texto, $field = 'seo') {
$seo = strtolower(Inflector::slug($texto, '-'));
//Comprobamos si existe una entidad previa
$prev = $this->find('first', array('conditions' => array($this->name . '.' . $field => $seo, 'NOT' => array($this->name . '.id' => $id))));
if (!empty($prev)) {
$seo .= '-' . $this->id;
}
return $seo;
}
//Elimina el contenido completo de directorios
protected function removeFile($path) {
$file = new File($path);
$file->delete();
}
//Elimina el contenido completo de directorios
protected function removeDir($path) {
$folder = new Folder($path);
$folder->delete();
}
//Genera el string de búsqueda para las entidades
protected function generarBusqueda($busqueda) {
$out = array();
foreach ($busqueda as $b) {
if (!empty($b)) {
$out[] = $b;
}
}
return mb_strtolower(str_replace(array('_', '-'), array(' ', ' '), (implode(',', $out))), 'UTF-8');
}
//Prepara los archivos para su posterior guardado
protected function prepararArchivos() {
foreach ($this->archivos as $img) {
if (!empty($this->data[$this->name][$img]) && is_array($this->data[$this->name][$img])) {
$this->data[$this->name][$img . '.file'] = $this->data[$this->name][$img];
}
unset($this->data[$this->name][$img]);
}
}
//Validación que comprueba que el archivo a guardar no está vacío a la hora de crear el registro
public function notEmptyFile($check) {
$campo = key($check);
if (empty($this->id) && empty($this->data[$this->name][$campo]['name'])) {
return false; //error
}
return true; //ok
}
//Guarda las imágenes de un modelo
protected function guardarArchivos() {
foreach ($this->archivos as $img) {
$ok = false;
if (!empty($this->data[$this->name][$img . '.file']) && is_array($this->data[$this->name][$img . '.file'])) {
$file = $this->data[$this->name][$img . '.file']; //obtenemos el fichero
if ($file['error'] === UPLOAD_ERR_OK) {
//Path /blobs/entidad/entidad_id
$path = 'blobs' . DS . strtolower(Inflector::slug($this->name)) . DS . $this->id;
if (!is_dir(WWW_ROOT . $path)) {
mkdir(WWW_ROOT . $path, 0777, true);
}
//Name
$name = explode('.', $file['name']);
$name = $img . '.' . str_replace('jpeg', 'jpg', strtolower($name[1]));
//Movemos el fichero y actualizamos el registro
if (move_uploaded_file($file['tmp_name'], WWW_ROOT . $path . DS . $name)) {
exec('rm -rf ' . WWW_ROOT . 'i/*/' . strtolower(Inflector::slug($this->name)) . '/' . $this->id); //eliminamos las imágenes cacheadas de la entidad
$db = $this->getDataSource();
$this->updateAll(array(
$img => $db->value("/$path/$name", 'string'),
"{$img}_name" => $db->value($name, 'string'),
"{$img}_size" => $db->value($file['size'], 'string'),
"{$img}_mime" => $db->value($file['type'], 'string'),
), array($this->name . '.id' => $this->id));
$ok = true;
}
}
}
}
}
protected function prepararGaleria() {
//ID de la entidad
$this->data[$this->name][$this->getVirtualField('entidad_id')] = $this->data[$this->name]['entidad_id'];
if (!empty($this->data[$this->name]['imagen']) && !empty($this->data[$this->name]['imagen']['name'])) { //imagen
//La imagen se sube después de guardar, ya que antes no tenemos el ID de la galería
$this->imagen = $this->data[$this->name]['imagen']; //obtenemos el fichero
$this->data[$this->name]['imagen'] = Configure::read('App.vacio');
} elseif (!empty($this->data[$this->name]['video_source']) && !empty($this->data[$this->name]['video_code'])) { //vídeo
$this->data[$this->name]['imagen'] = null;
}
}
protected function guardarGaleria() {
//Generamos el orden del elemento
$db = $this->getDataSource();
$this->updateAll(array(
'orden' => $db->value($this->getNuevoOrdenGaleria(), 'string'),
), array($this->name . '.id' => $this->id));
//Obtenemos el path de la imagen que vamos a guardar
$path = 'blobs' . DS . strtolower(Inflector::slug(preg_replace('/Galeria/', '', $this->name, 1))) . DS . $this->data[$this->name]['entidad_id'] . DS . 'galeria'; //Path /blobs/entidad/entidad_id/galeria
if (!is_dir(WWW_ROOT . $path)) {
mkdir(WWW_ROOT . $path, 0777, true);
}
//Procesamos la imagen del elemento de la galería
if (!empty($this->imagen)) {
$file = $this->imagen;
if ($file['error'] === UPLOAD_ERR_OK) {
//Name
$ext = strrpos($file['name'], '.');
$ext = substr($file['name'], $ext + 1);
$name = $this->id . '.' . str_replace('jpeg', 'jpg', strtolower($ext));
//Movemos el fichero y actualizamos el registro
if (move_uploaded_file($file['tmp_name'], WWW_ROOT . $path . DS . $name)) {
exec('rm -rf ' . WWW_ROOT . 'i/*/' . strtolower(Inflector::slug(preg_replace('/Galeria/', '', $this->name, 1))) . '/' . $this->data[$this->name]['entidad_id']); //eliminamos las imágenes cacheadas de la entidad
$this->updateAll(array(
'imagen' => $db->value("/$path/$name", 'string'),
'imagen_name' => $db->value($name, 'string'),
'imagen_size' => $db->value($file['size'], 'string'),
'imagen_mime' => $db->value($file['type'], 'string'),
), array($this->name . '.id' => $this->id));
}
}
} else { //vídeo
$img = null;
//Obtenemos la imgagen del vídeo según la fuente
switch ($this->data[$this->name]['video_source']) {
case 'youtube':
$img = 'http://img.youtube.com/vi/' . $this->data[$this->name]['video_code'] . '/0.jpg';
break;
case 'vimeo':
$ch = curl_init('http://vimeo.com/api/v2/video/' . (int) $this->data[$this->name]['video_code'] . '.xml');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); //sacamos la salidad directamente como string
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); //seguimos la petición por si hay algún redireccionamiento
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 15); //tiempo máximo espera
$xml = curl_exec($ch);
curl_close($ch);
@$xml = simpleXML_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA);
if (!empty($xml)) {
$xml = get_object_vars($xml->video);
$img = $xml['thumbnail_large'];
}
break;
}
if (!empty($img)) {
$name = $this->id . '.jpg';
$this->imageSaveFromUrl($img, WWW_ROOT . $path . DS . $name);
//Comprobamos si la imagen existe en el sistema de ficheros
$file = new File(WWW_ROOT . $path . DS . $name);
if ($file->exists()) {
exec('rm -rf ' . WWW_ROOT . 'i/*/' . strtolower(Inflector::slug(preg_replace('/Galeria/', '', $this->name, 1))) . '/' . $this->data[$this->name]['entidad_id']); //eliminamos las imágenes cacheadas de la entidad
$fileInfo = $file->info();
$this->updateAll(array(
'imagen' => $db->value("/$path/$name", 'string'),
'imagen_name' => $db->value($name, 'string'),
'imagen_size' => $db->value($fileInfo['filesize'], 'string'),
'imagen_mime' => $db->value($fileInfo['mime'], 'string'),
), array($this->name . '.id' => $this->id));
}
}
}
}
//Genera la imagen_dn de la entidad
public function generarImagenDn($imagenID = null) {
$galeria = $this->findById($this->id);
$imagen = $this->find('first', array('conditions' => array('entidad_id' => $galeria[$this->name]['entidad_id'], 'NOT' => array($this->name . '.id' => $imagenID, $this->name . '.imagen' => null)), 'order' => $this->name . '.orden'));
$this->query('UPDATE ' . str_replace('_galerias', '', $this->tablePrefix . $this->useTable) . ' SET imagen_dn = "' . ((!empty($imagen)) ? $imagen[$this->name]['imagen'] : '' ) . '" WHERE id = ' . $galeria[$this->name]['entidad_id']);
}
//Método que devuelve el orden que ha de llevar la nueva imagen
protected function getNuevoOrdenGaleria() {
$orden = 1;
$ultima = $this->find('first', array('conditions' => array('NOT' => array($this->name . '.id' => $this->id), 'entidad_id' => $this->data[$this->name]['entidad_id']), 'order' => array($this->name . '.orden' => 'DESC')));
if (!empty($ultima)) {
$orden = (int) $ultima[$this->name]['orden'] + 1;
}
return $orden;
}
//Método que actualiza el campo orden de la galería
public function reordenarGaleria() {
foreach ($this->find('all', array('conditions' => array('entidad_id' => $this->data[$this->name]['entidad_id']), 'order' => array($this->name . '.orden'))) as $k => $v) {
$this->updateAll(array($this->name . '.orden' => (int) $k + 1), array($this->name . '.id' => $v[$this->name]['id']));
}
}
//Validación que comprueba que el elemento a guardar de la galería de imágenes no está vacío
public function notEmptyGaleria($check) {
if (empty($this->data[$this->name]['imagen']['name']) && (empty($this->data[$this->name]['video_source']) || empty($this->data[$this->name]['video_code']))) {
return false; //error
}
return true; //ok
}
//Validación que comprueba que el elemento a guardar de la galería de imágenes es de una fuente de vídeo válida
public function checkExistGaleria($check) {
$elemento = null;
$campo = key($check);
switch ($campo) {
case 'video_source':
$elementos = Configure::read('App.videoSources');
if (array_key_exists($this->data[$this->name][$campo], $elementos)) {
$elemento = $elementos[$this->data[$this->name][$campo]];
}
break;
}
if (empty($elemento)) {
return false; //error
}
return true; //ok
}
//Método que actualiza el campo orden de las entidades
public function reordenarEntidades($conditions = array()) {
foreach ($this->find('all', array('fields' => array($this->name . '.id', $this->name . '.orden'), 'recursive' => false, 'conditions' => $conditions, 'order' => array($this->name . '.orden' => 'ASC'))) as $k => $v) {
$this->updateAll(array($this->name . '.orden' => (int) $k + 1), array($this->name . '.id' => $v[$this->name]['id']));
}
}
public function checkExtension($check, $extensiones) {
$campo = key($check);
if (!empty($this->data[$this->name][$campo]) && !empty($this->data[$this->name][$campo]['name'])) {
$file = explode('.', $this->data[$this->name][$campo]['name']);
//Obtenemos la extensión
end($file);
$key = key($file);
$ext = $file[$key];
return in_array(strtolower($ext), $extensiones);
}
return true; //ok
}
public function checkDatetime($check) {
$campo = key($check);
$pattern = "/^((((31\/(0?[13578]|1[02]))|((29|30)\/(0?[1,3-9]|1[0-2])))\/(1[6-9]|[2-9]\d)?\d{2})|(29\/0?2\/(((1[6-9]|[2-9]\d)?(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00))))|(0?[1-9]|1\d|2[0-8])\/((0?[1-9])|(1[0-2]))\/((1[6-9]|[2-9]\d)?\d{2})) (20|21|22|23|[0-1]?\d):[0-5]?\d:[0-5]?\d$/";
return (bool) preg_match($pattern, $this->data[$this->name][$campo] . ':00');
}
public function setDatetime(&$datetime) {
$datetime = DateTime::createFromFormat('d/m/Y H:i:s', $datetime . ':00');
$datetime = date_format($datetime, 'Y-m-d H:i:s');
}
public function getDate(&$date) {
if (!empty($date)) {
$date = date('d/m/Y', strtotime($date));
}
}
public function getDateTime(&$date) {
if (!empty($date)) {
$date = date('d/m/Y', strtotime(substr($date, 0, 10))) . ' ' . substr($date, 11, 5);
}
}
protected function setDate(&$date, $time = null) {
$out = null;
if (!empty($date)) {
$out = DateTime::createFromFormat('d/m/Y', $date);
$out = date_format($out, 'Y-m-d');
if (!empty($time)) {
$out .= " $time:00";
}
}
$date = $out;
}
/**
* http://stackoverflow.com/questions/2461267/cakephp-isunique-for-2-fields
*
* checks is the field value is unqiue in the table
* note: we are overriding the default cakephp isUnique test as the original appears to be broken
*
* @param string $data Unused ($this->data is used instead)
* @param mnixed $fields field name (or array of field names) to validate
* @return boolean true if combination of fields is unique
*/
public function checkUnique($data, $fields) {
if (!is_array($fields)) {
$fields = array($fields);
}
foreach ($fields as $key) {
$tmp[$key] = $this->data[$this->name][$key];
}
if (isset($this->data[$this->name][$this->primaryKey])) {
$tmp[$this->primaryKey] = "<>" . $this->data[$this->name][$this->primaryKey];
}
return $this->isUnique($tmp, false);
}
/*
* http://bavotasan.com/2011/convert-hex-color-to-rgb-using-php/
*/
protected function hex2rgb($hex) {
$hex = substr($hex, 1);
if (strlen($hex) == 3) {
$r = hexdec(substr($hex, 0, 1) . substr($hex, 0, 1));
$g = hexdec(substr($hex, 1, 1) . substr($hex, 1, 1));
$b = hexdec(substr($hex, 2, 1) . substr($hex, 2, 1));
} else {
$r = hexdec(substr($hex, 0, 2));
$g = hexdec(substr($hex, 2, 2));
$b = hexdec(substr($hex, 4, 2));
}
$rgb = array($r, $g, $b);
return implode(",", $rgb); // returns the rgb values separated by commas
}
protected function imageSaveFromUrl($img, $path) {
$ch = curl_init($img);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_BINARYTRANSFER, 1);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
$rawdata = curl_exec($ch);
curl_close($ch);
$fp = fopen($path, 'x');
fwrite($fp, $rawdata);
fclose($fp);
}
function getLastQuery()
{
$dbo = $this->getDatasource();
$logs = $dbo->getLog();
$lastLog = end($logs['log']);
return $lastLog['query'];
}
}