<?php
/**
 * Metodos de uso general (Helpers) sacados de inet y recopilados.....
 * @authores anda a saber :p - algunos propietarios
 */


/**
 * Clase estatica de funciones para la Conversion de Datos
 *
 * @subpackage Conversion de datos
 * 
 */
class Convertir {
	
	const ESCAPEO_MYSQL 	= 0x1;
	const ESCAPEO_MSSQL 	= 0x2;
	const SIN_CODIFICACION					= 0x00;
	const UTF8_DECODE 						= 0x01;
	const UTF8_ENCODE						= 0x02;
	const PERMITIR_HTML						= 0x03;
	const BBCODE							= 0x04;
	const BBCODE_SIN_NL2BR					= 0x05;
	const SIN_NL2BR							= 0x05;
	const PERMITIR_HTML_SEGURO				= 0x06;
	
	const QUOTE_TEXTO		= 'dijo:';
	
	/**
	 * Data To Query: Adaptamos un dato entrante a un string preparado para trabajarlo en SQL
	 *
	 * @param string|int|real|null $dato
	 * @param bool $aceptaNull
	 * @return string
	 * 
	 * @throws ExcepcionDatoInvalido Cuando se pasa null y $aceptaNull == false.
	 */
	static function d2q($dato, $aceptaNull = false, $escapeo = self::ESCAPEO_MYSQL) {
		
		//Definimos el array de reemplazos.
		switch($escapeo) {
			case self::ESCAPEO_MYSQL:
				$tradArr = array(
					"\\" => "\\\\",
					"'" => "\\'"
				);
			break;
			
			case self::ESCAPEO_MSSQL:
				$tradArr = array(
					"'" => "''"
				);
			break;
			
			default: throw new ExcepcionParametroInvalido();
		}
		
		//Evaluamos las condiciones...
		if(is_null($dato) && $aceptaNull) {
		
			//Recibi un null y acepto nulls? devuelvo null.
			return "null";
		
		} elseif(is_null($dato) && !$aceptaNull) {
		
			throw new ExcepcionDatoInvalido("No se aceptan nulls. Modificar parametro aceptaNull.");
	
		} elseif(!is_null($dato)) {
		
			//Recibi un !null? scapeo la ' y devuelvo entre 's.
			return "'".strtr($dato, $tradArr)."'";
		
		}
	
	}
	
	/**
	 * Data To Query (Non Quoted): Adaptamos un dato entrante a un string preparado para trabajarlo en SQL (Version SIN QUOTES)
	 *
	 * @param string|int|real|null $dato
	 * @param bool $aceptaNull
	 * @return string
	 * 
	 * @throws ExcepcionDatoInvalido Cuado se pasa null y $aceptaNull == false.
	 */
	static function d2qnq($dato, $aceptaNull = false, $escapeo = self::ESCAPEO_MYSQL) {
		
	//Definimos el array de reemplazos.
		switch($escapeo) {
			case self::ESCAPEO_MYSQL:
				$tradArr = array(
					"\\" => "\\\\",
					"'" => "\\'"
				);
			break;
			
			case self::ESCAPEO_MSSQL:
				$tradArr = array(
					"'" => "''"
				);
			break;
			
			default: throw new ExcepcionParametroInvalido();
		}
		
		//Evaluamos las condiciones...
		if(is_null($dato) && $aceptaNull) {
		
			return null;
		} elseif(is_null($dato) && !$aceptaNull) {
		
			throw new ExcepcionDatoInvalido("No se aceptan nulls. Modificar parametro aceptaNull.");
		} elseif(!is_null($dato)) {
		
			//Recibi un !null? scapeo la ' y devuelvo entre 's.
			return strtr($dato, $tradArr);
		}
	}
	
	/**
	 * Data To Hex: Adaptamos un dato entrante a un string preparado para trabajarlo en SQL como nï¿½mero HEXA.
	 * Este mï¿½todo es ï¿½til para subir cadenas binarias.
	 *
	 * @param string|int|real|null $dato
	 * @return string
	 */
	static function d2hex($dato) {
		$datoHexa = "0x";
		for($i=0;$i<mb_strlen($dato);$i++) {
			$datoHexa .= mb_substr("0".dechex(ord(mb_substr($dato,$i,1))),-2);
		}
		return $datoHexa;
	}
	
	/**
	 * Data To Web: Adaptamos un string para poder ser concatenado con HTML
	 *
	 * @param string $dato
	 * @return string
	 */
	static function d2w($dato,$encoding = self::SIN_CODIFICACION,$excluirCampos = array()) {
				
		// si es un string
		if (is_string($dato)){
			$dato = self::d2wF($dato,$encoding);
		}
		// si es array
		if (is_array($dato)) {
			
			// por cada indice
			foreach ($dato as $key => $value) {
				
				if ( !empty($excluirCampos) ) {
					if ( !in_array($key,$excluirCampos) )
						$dato[$key] = self::d2w($value,$encoding);
				} else {
					$dato[$key] = self::d2w($value,$encoding);
				}
			}
		}

		if (is_object($dato) && is_callable(array($dato,'getRecord'))) {
			$record = $dato->getRecord();
			if (is_array($record)) {
				foreach ($record as $key => $value) {
					// La key se pasa por alto porque esta restringida en el offset
					if ( $key != $dato->getKeyField()) {
						$dato[$key] = self::d2w($value,$encoding = self::PERMITIR_HTML_SEGURO);
					}
				}
			}
		}
		
		return $dato;
	}

	static private function d2wF($dato,$encoding = self::SIN_CODIFICACION ) {
		
		switch ($encoding) {
			case self::SIN_CODIFICACION :
				$resultado = self::nl2br((htmlentities($dato, ENT_QUOTES, ENCODING)));
				 break;
			case self::UTF8_ENCODE:
				 $resultado = nl2br(htmlspecialchars(Convertir::utf8_safe_encode($dato), ENT_QUOTES, ENCODING));
				 break;
			case self::UTF8_DECODE:
				 $resultado = nl2br(htmlspecialchars($dato, ENT_QUOTES, ENCODING));
				 break;
			case self::PERMITIR_HTML:
				 $resultado = html_entity_decode($dato,ENT_QUOTES, ENCODING);
				break;
			case self::PERMITIR_HTML_SEGURO:
				 $resultado = self::nl2br(htmlspecialchars($dato,ENT_QUOTES, ENCODING));
				 $resultado = str_replace ( '&amp;', '&', $resultado );
				 $resultado = str_replace ( '&#039;', "'", $resultado );
				 $resultado = str_replace ( '&quot;', '"', $resultado );
				break;
			case self::BBCODE:
				$resultado = nl2br(self::bbcode( htmlspecialchars($dato, ENT_QUOTES) ));				
				break;			
			case self::BBCODE_SIN_NL2BR:
				$resultado = self::bbcode(htmlspecialchars($dato));
				break;
			case self::SIN_NL2BR:
				$resultado = htmlspecialchars($dato);
				break;
			default:
				$resultado = nl2br(htmlspecialchars($dato, ENT_QUOTES, ENCODING));
				break;
		}		
		return $resultado;
	}	
	
	public static function nl2br($str){
		$str = preg_replace('#\r?\n#', '<br />', $str);
		$str = preg_replace('#<br /><br />#', '<br />', $str);
		return $str;
	}

	/**
	 * Data To Web Property: Adaptamos un string para poder ser insertado en una propiedad de un tag HTML
	 *
	 * @param string $dato
	 * @return string
	 */
	static function d2wp($dato) {
		return '"'.htmlspecialchars($dato, ENT_COMPAT, ENCODING).'"';
	}

	static function utf8_decode( $dato ) {
		
		if ( is_array($dato) ) {
			foreach( $dato as $k => $value )
				$resultado[$k] = self::utf8_decode($value);
		} else {
			$resultado = utf8_decode($dato);
		}
		
		return isset($resultado) ? $resultado : $dato;
	}
	
		
	static function utf8_encode( $dato ) {
		
		if ( is_array($dato) ) {
			foreach( $dato as $k => $value )
				$resultado[$k] = self::utf8_encode($value);
		} else {
			$resultado = utf8_encode($dato);
		}
		
		return $resultado;
	}

	static private function is_utf8( $dato ) {
		
		// FIXME: Esto volarlo al recarajo.
		// Lo puse tras arreglar el encoding en modulos.php, pero esta funcion espera
		// que el encoding siga en ISO.
		mb_internal_encoding('ISO-8859-1');
		
		$string_utf8 = utf8_encode($dato);
		// return ( mb_strpos($string_utf8,"ï¿½",0) !== false );
		$esUtf8 = ( mb_strpos($string_utf8,chr(131),0) !== false );
		
		$a = "/(Ã‚|Ã„|Ãƒ|Å½|Â�|ÃƒÂ�Ã‚|Â�)/is";
		
		if ( preg_match( $a, $string_utf8 ) )
			$esUtf8 = true; 
			
		// FIXME: Chau!
		mb_internal_encoding(ENCODING);
		
		return $esUtf8;
	}

	static function utf8_safe_encode( $dato ) {
		
		$resultado = null;
		
		if ( is_array($dato) ) {
			foreach( $dato as $k => $value )
				$resultado[$k] = self::utf8_safe_encode($value);
		} else {
			$resultado = self::is_utf8($dato) ? $dato : utf8_encode($dato);
		}
		
		return $resultado;
	}
	
	static function utf8_safe_decode( $dato ) {
		
		$resultado = null;
		
		if ( is_array($dato) ) {
			foreach( $dato as $k => $value )
				$resultado[$k] = self::utf8_safe_decode($value);
		} else {
			//$resultado = utf8_decode($dato);
			$resultado = self::is_utf8($dato) ? utf8_decode($dato) : $dato;
			
		}
		return $resultado;
	}
	
	// permiten que se puedan enviar strings encodeados como URL
	static function urlsafe_base64_encode($string)	{
	    return strtr(base64_encode($string), "+/", "-_");
	}
	
	static function urlsafe_base64_decode($string)	{
	    return base64_decode(strtr($string, "-_", "+/"));
	} 
	
	static function limpiar_acentos ( $texto ) {
		
		if ( empty($texto) ) {
			return $texto;
		}
		
		// @todo: posibles soluciones, verificar primero el encoding, o sino, no usar
		// htmlentities y usar htmlscpecial..., el error ocurre cuando se pega texto
		// de Office, y convierte unas comillas raras.
		
		// mb_check_encoding();
		// htmlspecialchars();
		
		//$str = htmlentities(Convertir::utf8_safe_encode($texto), ENT_COMPAT, "UTF-8");
		$str = htmlentities( $texto, ENT_COMPAT, "UTF-8");
		$str = preg_replace('/&([a-zA-Z])(uml|acute|grave|circ|tilde|cedil);/', '$1',$str);
		$str = html_entity_decode($str, ENT_COMPAT, "UTF-8");
		
		//return Convertir::utf8_safe_encode($str);
		return $str;
		
	}
	
	/**
	 * Data To Web Property: Adaptamos un string para poder ser insertado en una propiedad de un tag HTML
	 *
	 * @param string $dato
	 * @return string
	 */
	static function d2domvalue($dato) {
		return str_replace("&", "&amp;", $dato);
	}
	
	/**
	 * Data To CSV: Adaptamos un string para trabajarlo en un CSV
	 *
	 * @param string $dato
	 * @return string
	 */
	static function d2csv($dato) {
		
		$tradArr = array(
			"\"" => "\"\""
		);

		if(is_null($dato)) {
			return "\"\"";
		
		} else {
			return "\"".strtr($dato, $tradArr)."\"";
		}
	}
	
	/**
	 * Data To JS: Adaptamos un string para trabajarlo como una cadena en JavaScript
	 *
	 * @param string $dato
	 * @return string
	 */
	static function d2js($dato) {
		
		$tradArr = array(
			"'" => "\\'",
			"\\" => "\\\\"
		);
		
		return "'".strtr($dato, $tradArr)."'";
	}
	
	/**
	 * Magic Quotes en Formularios: Remueve el efecto de las Magic Quotes. Se pueden pasar arrays.
	 * El parametro es de entrada, no devuelve nada.
	 *
	 * @param string|array $form
	 */
	static function mqForm(&$form) {
		if(get_magic_quotes_gpc())
			if(is_array($form)) {
				foreach($form as $clave=>$valor) {
					if (is_string($valor)) {
						$form[$clave] = stripslashes($valor);
					} elseif (is_array($valor)) {
						self::mqForm($form[$clave]);
					}
				}
			} elseif (is_string($form)) {
				$form = stripslashes($form);
			}
	}
	
	static function mesCastellano($mesIngles) {
		switch($mesIngles) {
			case "January": return "Enero"; break;
			case "February": return "Febrero"; break;
			case "March": return "Marzo"; break;
			case "April": return "Abril"; break;
			case "May": return "Mayo"; break;
			case "June": return "Junio"; break;
			case "July": return "Julio"; break;
			case "August": return "Agosto"; break;
			case "September": return "Septiembre"; break;
			case "October": return "Octubre"; break;
			case "November": return "Noviembre"; break;
			case "December": return "Diciembre"; break;
			default: throw new ExcepcionDatoInvalido("Se desconoce el mes entrante");
		}
	}
	
	/**
	 * Traduce el string de un mes, generado con date("l") [l = L minuscula] a castellano.
	 *
	 * @param string $diaIngles
	 * @return string
	 * 
	 * @throws ExcepcionDatoInvalido Si no se conoce el dï¿½a.
	 */
	static function diaCastellano($diaIngles) {
		switch($diaIngles) {
			case "Sunday": return "Domingo"; break;
			case "Monday": return "Lunes"; break;
			case "Thuesday": return "Martes"; break;
			case "Wednesday": return "Miercoles"; break;
			case "Thursday": return "Jueves"; break;
			case "Friday": return "Viernes"; break;
			case "Saturday": return "Sabado"; break;
			default: throw new ExcepcionDatoInvalido("Se desconoce el dï¿½a entrante");
		}
	}
	
	/**********************************************************************************************/
	
	/**
	 * Parsea una fecha con formato "dd/mm/yyyy".
	 *
	 * @param string $fecha
	 * @return int
	 */
	static function ddmmyyyy2date($fecha) {
	
		if(preg_match_all("/^(\\d{1,2})\\/(\\d{1,2})\\/(\\d{2,4})$/is", $fecha, $detallesFecha) && Validar::fecha($detallesFecha[3][0],$detallesFecha[2][0],$detallesFecha[1][0])) {
			$resultado = strtotime($detallesFecha[3][0]."-".$detallesFecha[2][0]."-".$detallesFecha[1][0]);
		} else {
			$resultado = FALSE;
		}
	
		return $resultado;
	}
	
	/**
	 * Esta funcion convierte un array en una cadena que puede ser utilizada como query string.
	 * Ademas puede ser utilizado para reemplazar valores que existen acutalmente en el query strig
	 * Incluye el "?".
	 *
	 * @param array $arrInput
	 * @param array $reemplazar
	 * @return string
	 */
	static function array2querystring($arrInput, $reemplazar = null) {
		if(!is_array($arrInput)) user_error("El primer argumento TIENE QUE ser un array.", E_USER_ERROR);
		if(!is_array($reemplazar)) user_error("El reemplazo NO es un array", E_USER_WARNING);
		if($reemplazar === null || !is_array($reemplazar)) $reemplazar = array();
		
		$clavesReemplazo = array_keys($reemplazar); $i = 0; $strFinal = "";
		foreach($arrInput as $clave=>$valor) {
			$busqueda = array_search($clave, $clavesReemplazo);
			if($busqueda === FALSE || ($busqueda !== FALSE && $reemplazar[$clavesReemplazo[$busqueda]] !== NULL)) {
				if($busqueda !== FALSE) {
					$arrInput[$clavesReemplazo[$busqueda]] = $reemplazar[$clavesReemplazo[$busqueda]];
					$valor = $arrInput[$clavesReemplazo[$busqueda]];
					$clavesReemplazo[$busqueda] = null;
				}
				
				$strFinal .= (($i==0)?"?":"&").urlencode($clave)."=".urlencode($valor);
				
				$i++;
			}
		}
		
		foreach($clavesReemplazo as $valor) {
			if($valor!=NULL && $reemplazar[$valor]!==NULL) {
				$strFinal .= (($i==0)?"?":"&").urlencode($valor)."=".urlencode($reemplazar[$valor]);
				$i++;
			}
		}
		
		return $strFinal;
	}
	
	/**
	 * metodo que me va a permitir convertir un string en un array, para eso va a separar 
	 * los elementos por las , (comas) y los ; (punto y coma). 
	 * Basicamente hace un explode por , o ;
	 *
	 * @param string $string
	 */
	static function stringEnArray($string) 
	{
		if (!is_string($string)) {
		    throw new Exception('El primer argumento tiene que ser un STRING en: ' . __METHOD__);
		}
			
		$string = str_replace(';',',',$string);		
		$array = explode(',',trim($string));
		
		foreach ($array as $key => $string) {
			$array[$key] = trim($string);
		}
		
		return array_values(array_diff($array, array('')));
	}
	
	static function objectEnArray($objeto) {		
			
	    if(!(is_array($objeto) || is_object($objeto))){
	    	$dato = $objeto;
	    } else {
	        foreach($objeto as $key => $valor1){
	            $dato[$key] = self::objectEnArray($valor1);
	        }
	    }
	    return $dato;	
	}
	
	/**
	 * Convierte un string en otro sin espacios ni caracteres especiales para
	 * ser apto en una url
	 */
	static public function url($sString) {
	
			$sString = self::limpiar_acentos($sString);
		
			$string = mb_strtolower(htmlentities($sString));
     	$string = preg_replace("/&(.)(uml);/", "$1e", $string);
     	$string = preg_replace("/(\!|\Â¡|\Â¿|\?|\`)/", "", $string);
     	$string = preg_replace("/&(.)(acute|cedil|circ|ring|tilde|uml);/", "$1", $string);
     	$string = preg_replace("/([^a-z0-9_]+)/", "-", html_entity_decode($string));
     	$string = trim($string, "-");
     	return $string;
	}
	
	/**
	 * obtiene la edad de una fecha que se le pase en formato "aaaa-mm-dd"
	 * @return string
	 */
	static public function edad($nacimiento)
	{
		if ( $nacimiento === '0000-00-00' || empty( $nacimiento ) ) {
			return "0";
		}
		
		try {
			$dNacimiento = new DateTime( $nacimiento );
			$dToday = new DateTime();
			$diDiff = $dToday->diff( $dNacimiento );
			return (string)$diDiff->y;
		} catch ( Exception $e ) {
			return "0";
		}
	}
    
	/**
	 * Procesa codigo BBCode, escapando previamente todo el HTML que haya escrito.
	 * @todo Hacer que esto realmente parsee en vez de hacer reemplazos, ya que no soporta anidaciï¿½n
	 *
	 * @param	string	$texto	El textoa procesar.
	 * @return	string	El texto ya interpretado como BBCOde y lsito para msotrar en HTML.
	 */
	static public function bbcode($texto) {

		$baseUrl = preg_replace( '|/|', '\/', URL);

   		$a = array(
   			//	"/\n/is"=>"<br />",
	    		"/\[\s*i\s*\](.*?)\[\s*\/\s*i\s*\]/is" => "<i>$1</i>", //Italic
   				"/\[\s*b\s*\](.*?)\[\s*\/\s*b\s*\]/is" => "<b>$1</b>", //Negrita
	    		"/\[\s*u\s*\](.*?)\[\s*\/\s*u\s*\]/is" => "<u>$1</u>", //Underline
	    		
	    		"/\[img\](.*?)\[\/img\]/si" => "<img src=\"$1\" />",
	    		"/\[quote\]/is" =>"<blockquote>",
   				"/\[quote=(.*?)\]/is" => "<blockquote><cite>$1 dijo: </cite>",
   				"/\[\/quote\]/is"=>"</blockquote>",
				"/\[email\](.*?)\[\/email\]/is"=>"<a href=\"mailto:$1\">$1</a>",				
				"/\[size=(.*?)\]/is"=>"<span style=\"font-size:$1px\">",
				"/\[\/size\]/is"=>"</span>",
   		
   				// Listas
   				
   				// Listas desordenadas ...
   				"/\[\s*list\s*\]/is" => "<ul>",
   				"/\[list:o\]/is" => "<ol>",//	Listas ordenadas por numero..
   				"/\[\/list\]/is" => "</ul>",
   				"/\[\/list:o\]/is" => "</ol>",
   		   		// Elementos de lista
   				"/\[\*\]/is" => "<li>",
				"/\[\/\*\]/is" => "</li>",

   				// Colores
   				"/\[color=(.*?)\]/is" =>"<font color=\"$1\">",
   				"/\[\/color\]/is" => "</font>",

   				// Emails ..
				
				/**
				 * Es un poco trucho porque depende del orden de evaluacion de las expresiones.
				 */
				"|\[url=$baseUrl([^\[]+)\]([^\[]+)\[/url\]|" => "<a href=\"\\1\">\\2</a>",
				"|\[url=([^\[]+)\]([^\[]+)\[/url\]|" => "<a href=\"\\1\" rel=\"nofollow\">\\2</a>",

				"|\[url\]$baseUrl\[/url\]|" => "<a href=\"\\1\">\\1</a>",
				"|\[url\]([^\[]+)\[/url\]|" => "<a href=\"\\1\" rel=\"nofollow\">\\1</a>",

   				// Eliminar <br /> innecesarios
				"/<\/blockquote>\s*<br \/\>/is"=>"</blockquote>",
				"/<ul>\s*<br\s*\/>/is"=>"<ul>",
				"/<\/ul>\s*<br\s*\/>/is"=>"</ul>",
				"/<ol>\s*<br\s*\/>/is"=>"<ol>",
				"/<\/ol>\s*<br\s*\/>/is"=>"</ol>",
				"/<\/li>\s*<br\s*\/>/is"=>"</li>",
				

				// Eliminar saltos de lÃ­nea innecesarios				
				"/\r/is"=>"",
				"/<blockquote>\s*\r?\n/is"=>"<blockquote>",
				"/<\/blockquote>\s*\r?\n/is"=>"</blockquote>",
				"/<ul>\s*\r?\n/is"=>"<ul>",
				"/<\/ul>\s*\r?\n/is"=>"</ul>",
				"/<ol>\s*\r?\n/is"=>"<ol>",
				"/<\/ol>\s*\r?\n/is"=>"</ol>",
				"/<\/li>\s*\r?\n/is"=>"</li>",

				"/\r?\n\s*<ol>/is"=>"<ol>",
				"/\r?\n\s*<ul>/is"=>"<ul>",

   		
   				// SMILEYS
				"/:oops:/s" =>  "<img src=\"" . HTML ."/img/smileys/icon_redface.gif\" />",//"Embarassed"
				"/:\?\?\?:/s" => "<img src=\"" . HTML ."/img/smileys/icon_confused.gif\" />", //"Confused"
				"/:D/s" => "<img src=\"" . HTML ."/img/smileys/icon_biggrin.gif\" />",//"Very Happy"
   				"/:-D/s" => "<img src=\"" . HTML ."/img/smileys/icon_biggrin.gif\" />",//"Very Happy"
				"/:grin:/s" => "<img src=\"" . HTML ."/img/smileys/icon_biggrin.gif\" />",//,"Very Happy"
				"/:\)/s" => "<img src=\"" . HTML ."/img/smileys/icon_smile.gif\" />",//"Smile"
				"/:-\)/s" => "<img src=\"" . HTML ."/img/smileys/icon_smile.gif\" />",//"Smile"
				"/:smile:/s" =>  "<img src=\"" . HTML ."/img/smileys/icon_smile.gif\" />",//"Smile"
				"/:\(/s" =>  "<img src=\"" . HTML ."/img/smileys/icon_sad.gif\" />",// "Sad"
				"/:-\(/s" =>  "<img src=\"" . HTML ."/img/smileys/icon_sad.gif\" />",//"Sad"
				"/:sad:/s" =>  "<img src=\"" . HTML ."/img/smileys/icon_sad.gif\" />",// "Sad"
				"/:o/is" => "<img src=\"" . HTML ."/img/smileys/icon_surprised.gif\" />", // "Surprised"
				"/:-o/is" => "<img src=\"" . HTML ."/img/smileys/icon_surprised.gif\" />", // "Surprised"
				"/:eek:/is" => "<img src=\"" . HTML ."/img/smileys/icon_surprised.gif\" />", // "Surprised"
				"/8O/s" =>  "<img src=\"" . HTML ."/img/smileys/icon_eek.gif\" />",// "Shocked"
				"/8-O/s" =>  "<img src=\"" . HTML ."/img/smileys/icon_eek.gif\" />",//"Shocked"
				"/:shock:/s" =>  "<img src=\"" . HTML ."/img/smileys/icon_eek.gif\" />",//"Shocked"
				"/:\?/s" => "<img src=\"" . HTML ."/img/smileys/icon_confused.gif\" />", //"Confused"
				"/:-\?/s" => "<img src=\"" . HTML ."/img/smileys/icon_confused.gif\" />", //"Confused"
				"/8\)/s" =>  "<img src=\"" . HTML ."/img/smileys/icon_cool.gif\" />",//"Cool"
				"/8-\)/s" =>  "<img src=\"" . HTML ."/img/smileys/icon_cool.gif\" />",//"Cool"
				"/:cool:/s" => "<img src=\"" . HTML ."/img/smileys/icon_cool.gif\" />", //"Cool"
				"/:lol:/s" =>  "<img src=\"" . HTML ."/img/smileys/icon_lol.gif\" />",//"Laughing"
				"/:x/is" =>  "<img src=\"" . HTML ."/img/smileys/icon_mad.gif\" />",//""Mad"
				"/:-x/is" =>  "<img src=\"" . HTML ."/img/smileys/icon_mad.gif\" />",//"Mad"
				"/:mad:/is" =>  "<img src=\"" . HTML ."/img/smileys/icon_mad.gif\" />",//"Mad"
				"/:P/s" =>  "<img src=\"" . HTML ."/img/smileys/icon_razz.gif\" />",// "Razz"
				"/:-P/s" =>  "<img src=\"" . HTML ."/img/smileys/icon_razz.gif\" />",//"Razz"
				"/:razz:/s" =>  "<img src=\"" . HTML ."/img/smileys/icon_razz.gif\" />",//"Razz"
				"/:cry:/s" =>  "<img src=\"" . HTML ."/img/smileys/icon_cry.gif\" />",//""Crying or Very sad"
				"/:evil:/s" => "<img src=\"" . HTML ."/img/smileys/icon_evil.gif\" />", //"Evil or Very Mad"
				"/:twisted:/s" => "<img src=\"" . HTML ."/img/smileys/icon_twisted.gif\" />", //"Twisted Evil"
				"/:roll:/s" =>  "<img src=\"" . HTML ."/img/smileys/icon_rolleyes.gif\" />",//"Rolling Eyes"
				"/:wink:/s" => "<img src=\"" . HTML ."/img/smileys/icon_wink.gif\" />", //"Wink"			
				 
				// Quickfix pedorro para carita justo luego de entidad.
				
				"/[^(acute|tilde)];\)|^;\)/s" =>  " <img src=\"" . HTML ."/img/smileys/icon_wink.gif\" />",//"Wink"
				"/;-\)/s" => "<img src=\"" . HTML ."/img/smileys/icon_wink.gif\" />", //"Wink"
				"/:!:/s" =>  "<img src=\"" . HTML ."/img/smileys/icon_exclaim.gif\" />",//"Exclamation"
				"/:\?:/s" =>  "<img src=\"" . HTML ."/img/smileys/icon_question.gif\" />",//"Question"
				"/:idea:/s" => "<img src=\"" . HTML ."/img/smileys/icon_idea.gif\" />", //"Idea"
				"/:arrow:/s" => "<img src=\"" . HTML ."/img/smileys/icon_arrow.gif\" />", //"Arrow"
				"/:\|/s" =>  "<img src=\"" . HTML ."/img/smileys/icon_neutral.gif\" />",//"Neutral"
				"/:-\|/s" => "<img src=\"" . HTML ."/img/smileys/icon_neutral.gif\" />", //"Neutral"
				"/:neutral:/s" => "<img src=\"" . HTML ."/img/smileys/icon_neutral.gif\" />", //"Neutral"
				"/:mrgreen:/s" =>  "<img src=\"" . HTML ."/img/smileys/icon_mrgreen.gif\" />",//"Mr. Green"

				// Quickfix #676
				"/&Acirc;&iexcl;/is" => "&iexcl;",
				"/&Acirc;&iquest;/is" => "&iquest;",
				
				// Quickfix #796
				"/:euro:/is" => "&euro;",
			);   				

   		$texto = preg_replace(array_keys($a), array_values($a), $texto );
		
   		return $texto;
	}
    
	
	static public function stripbbcode($texto) {
		
   		$a = array(
  				"/\<br\s?\/\>/is"=>" ",
		   		"/\[([^\]]*)\]/is" => "",
				"/\[b\]/s" => "",
				"/\[\/b\]/s" => "",
				"/\[i\]/s" => "",
				"/\[\/i\]/s" => "",
				"/\[u\]/s" => "",
				"/\[\/u\]/s" => "",
				
	    		"/\[img\](.*?)\[\/img\]/si" => "",
	    		"/\[quote\]/is" =>"&quot;",
   				"/\[quote=(.*?)\]/is" => "$1 dijo: ",
   				"/\[\/quote\]/is"=>"&quot;",
				"/\[url=(.*?)\](.*?)\[\/url\]/is"=>"$2",
				"/\[url\](.*?)\[\/url\]/is"=>"$1",
				"/\[email\](.*?)\[\/email\]/is"=>"$1",				
				"/\[size=(.*?)\]/is"=>"",
				"/\[\/size\]/is"=>"",
   		
   				// Listas
   				
   				// Listas desordenadas ...
   				"/\[\s*list\s*\]/is" => "",
   				"/\[list:o\]/is" => "",//	Listas ordenadas por numero..
   				"/\[\/list\]/is" => "",
   				"/\[\/list:o\]/is" => "",
   		   		// Elementos de lista
   				"/\[\*\]/is" => "*",
				"/\[\/\*\]/is" => "<br \/>",

   				// Colores
   				"/\[color=(.*?)\]/is" =>"",
   				"/\[\/color\]/is" => "",
				
				"/\r/is"=>"",
				"/<blockquote>\s*\r?\n/is"=>"&quot;",
				"/<\/blockquote>\s*\r?\n/is"=>"&quot;",
				"/<ul>\s*\r?\n/is"=>"",
				"/<\/ul>\s*\r?\n/is"=>"",
				"/<ol>\s*\r?\n/is"=>"",
				"/<\/ol>\s*\r?\n/is"=>"",
				"/<\/li>\s*\r?\n/is"=>""
			);   				
		
   		$return = preg_replace( array_keys($a), array_values($a), strip_tags($texto));
   		return $return;
	}
	
	static public function str2time($strStr, $patternEntrada = null, $patternSalida = null) {

		// an array of the valide date characters, see: http://php.net/date#AEN21898
		$arrCharacters = array(
		        'd', // day
		        'm', // month
		        'y', // year, 2 digits
		        'Y', // year, 4 digits
		        'H', // hours
		        'i', // minutes
		        's'  // seconds
		);

		// transform the characters array to a string
		$strCharacters = implode('', $arrCharacters);
	
		// splits up the pattern by the date characters to get an array of the delimiters between the date characters
		$arrDelimiters = preg_split('~['.$strCharacters.']~', $patternEntrada);
		if ( !is_null($patternSalida) ) { 
		     $arrDelimitersSalida = preg_split('~['.$strCharacters.']~', $patternSalida);   
		}
		
		// transform the delimiters array to a string
		$strDelimiters = quotemeta(implode('', array_unique($arrDelimiters)));
		if ( !is_null($patternSalida) ) { 
		    $strDelimitersSalida = quotemeta(implode('', array_unique($arrDelimitersSalida))); 
		}
		
		// splits up the date by the delimiters to get an array of the declaration
		$arrStr     = preg_split('~['.$strDelimiters.']~', $strStr);
		
		// splits up the pattern by the delimiters to get an array of the used characters
		$arrPattern = preg_split('~['.$strDelimiters.']~', $patternEntrada);
		if ( !is_null($patternSalida) ) { 
		    $arrPatternSalida = preg_split('~['.$strDelimitersSalida.']~', $patternSalida); 
		}
		
		// if the numbers of the two array are not the same, return false, because the cannot belong together
		if (count($arrStr) !== count($arrPattern)) {
            return false;
		}
		
		 // creates a new array which has the keys from the $arrPattern array and the values from the $arrStr array
		$arrTime = array();
	    for ($i = 0;$i < count($arrStr);$i++) {
	        $arrTime[$arrPattern[$i]] = $arrStr[$i];
	    }
	
	    // gernerates a 4 digit year declaration of a 2 digit one by using the current year
	    if (isset($arrTime['y']) && !isset($arrTime['Y'])) {
	        $arrTime['Y'] = mb_substr(date('Y'), 0, 2) . $arrTime['y'];
	    }
	
	    // if a declaration is empty, it will be filled with the current date declaration
	    foreach ($arrCharacters as $strCharacter) {
	        if (empty($arrTime[$strCharacter])) {
	            $arrTime[$strCharacter] = date($strCharacter);
	        }
	    }
		
	    // checks if the date is a valide date
	    if (!checkdate($arrTime['m'], $arrTime['d'], $arrTime['Y'])) {
	        return false;
	    }
	
	      // generates the timestamp
	    if ( is_null($patternSalida)) {
	    	$intTime = mktime($arrTime['H'], $arrTime['i'], $arrTime['s'], $arrTime['m'], $arrTime['d'], $arrTime['Y']);
	    	return $intTime;
	    }
	    
	    return $arrTime[$arrPatternSalida[0]] . '-' . $arrTime[$arrPatternSalida[1]] . '-' . $arrTime[$arrPatternSalida[2]];
	}
}

/**
 * Clase estatica de funciones para la Validaciï¿½n de Datos
 *
 * @subpackage Validaciï¿½n de datos
 * 
 * @static
 */
class Validar {

	/**********************************************************************************************/

	/**
	 * Valida una fecha en base a sus datos en forma descompuesta.
	 *
	 * @param int $anio
	 * @param int $mes
	 * @param int $dia
	 * @return bool
	 */
	static function fecha($anio, $mes, $dia) {
		//Bardeaste?
		if (($dia>31||$dia<1)||($mes<1||$mes>12)) return false;
		
		//Si mes >= 8, entonces tiene que ser par para permitir dia 31, sino, impar
		if($dia==31 && ($mes%2)!=(($mes<8)?1:0)) return false;
		
		//Si mes es febrero, anio no es bisiesto, y dia mayor a 28, error. Admeas, si anio es bisiesto, y dia mayor a 29, tambien error.
		if($mes==2 && $dia>((($anio%4)==0)?29:28)) return false;
		
		return true;
	}
	
	/**********************************************************************************************/
	
	static public function IdValido(&$Id, $strict = true, $string = false) {
		if (!$string){
			if(!is_null($Id) && is_numeric($Id) && (int)$Id > 0) {
				return (int)$Id;
			} else {
				if($strict) {
					throw new ExcepcionDatoInvalido();
				} else {
					return null;
				}
			}
		}else{
			if(!is_null($Id) && is_numeric($Id) && (int)$Id > 0) {
				return $Id;
			}else{
				return null;
			}
		}
	}
	
	/**
	 * @todo Documentar
	 * @param <type> $email
	 * @return <type>
	 */
	static public function email($email) {
		$email = trim($email);
		$regex = "/^[a-zA-Z][\w\.-]*[a-zA-Z0-9]@[a-zA-Z0-9][\w\.-]*[a-zA-Z0-9]\.[a-zA-Z][a-zA-Z\.]*[a-zA-Z]$/is";
		
		if (!preg_match($regex,$email,$match) ) {
			return false;
		}
		
		return $match[0];	
	}

}

/**
 * Funciones que quedaron colgadas
 *
 * @todo Ubicar estas funciones donde corresponde
 */
class Extras {

	const EXTENCION_XML 	= 'xml';
	const EXTENCION_HTML	= 'html';
	const EXTENCION_JPG		= 'jpg';
	
	// Activa o desactiva que cada fetch guarde un log de cambios
	// Normalmente en false
	const FETCH_LOG_ACTIVO	= false;
	
	static function generarPassword($longitud = 6) {
		
		$str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890";
		$cad = "";
		for($i=0;$i<$longitud;$i++) {
		$cad .= mb_substr($str,rand(0,62),1);
		}
		return $cad;
	}
	
	static function generarNombresRandom($longitud = 6) {
		
		$str = "abcdefghijklmnopqrstuvwxyz";
		$cad = "";
		for($i=0;$i<$longitud;$i++) {
		$cad .= mb_substr($str,rand(0,25),1);
		}
		return $cad;
	}

	static function var_dump($variable) {
		echo '<pre>';
		var_dump($variable);
		echo '</pre>';
	}
	
	static function print_r($variable) {
		echo '<pre>';
		print_r($variable);
		echo '</pre>';
	}
	
	static function getBacktraceAsString() {
		
		$trace = debug_backtrace();
		$s = '';
		$i = 0;
		foreach ($trace as &$t) {
			$s .= "$i: {$t['function']} en {$t['file']}: {$t['line']} " . PHP_EOL;	 
			$i++;
		}
		return $s;
	}
	
	public static function microtime_float () {
		list ($msec, $sec) = explode(' ', microtime());
		$microtime = (float)$msec + (float)$sec;
		return $microtime;
	}
	
	/**
	 * @param $oUserAgent
	 * @desc Esta función detecta si el visitante es un crawler. Usa la función get_browser, con lo cual, para funcionar correctamente 
	 * el archivo browscap debe estar configurado y actualizado en el servidor.
	 */
	public static function isCrawler( $oUserAgent = null )
	{
	   try {
			if ( !$oUserAgent )
			{
				// Pongo este chequeo porque si no está la variable falla el get_browser
				if ( isset( $_SERVER['HTTP_USER_AGENT']) )
				{
					$bc = new Browscap( DIR_ABSOLUTO.'/Engine/Paquetes/Browscap/cache' );
					$oUserAgent = $bc->getBrowser();
					return isset($oUserAgent->Crawler) ? (boolean)$oUserAgent->Crawler : false;
				}
				else
				{
					return true; // Se asume que si no hay user_agent es un bot
				}
			}
		} catch (Exception $ex) {				
			return true;				
		}
	}
	
	/**
	 * Indica si el dispositivo es un iPad, iPhone o iPod Touch
	 * Se utiliza para habilitar/deshabilitar los editores ricos
	 *
	 * @return bool
	 */
	public static function isIDevice()
	{	
		try {
			if ( isset( $_SERVER['HTTP_USER_AGENT']) ) {
				$bc = new Browscap( DIR_ABSOLUTO.'/Engine/Paquetes/Browscap/cache' );
				$caps = $bc->getBrowser(null, true);
				$ret = is_array($caps) && isset($caps['Browser']) && preg_match('/(iPad|iPhone|iPod)/i', $caps['Browser']);
			} else {
				$ret = false;
			}
			return (boolean)$ret;
		} catch (Exception $ex) {				
			return false;				
		}
	}

	/**
	 * @desc Esta función es el handler para las excepciones de conexión a MySql. La usamos para atrapar las excepciones
	 *     'MySql server has gone away' y por si se murió el servidor. 
	 * @param $e El objeto PDOException
	 * @return La función no devuelve nada, en caso de que no pueda manejar la excepción la vuelve a arrojar.
	 */
	public static function manejarExcepcionPDO( PDOException $e )
	{
		switch (  $e->getCode() )
	    {
	        case 0: // MySQL Server has gone away
	            error_log( "La conexion a MySQL se perdio, reconectando. " . $e->getMessage() );
	            require_once 'Engine/Paquetes/Base/DB.class.php';
	            // Reintento la conexión por si es error MySql 2006
	            try
	            {
	               $c = DB::getInstance( true );
	            
		            header( "HTTP/1.1 307 Temporary Redirect" );
		            header('Location: '.$_SERVER['REQUEST_URI'] );
		            die(); 
	            }
	            catch ( PDOException $e )
	            {
	            	// Si falló el 2do intento se asume que el servicio está muerto.
	            	error_log( "El servidor MySQL no responde." );
	            	
                    asignar::quinientos();
	            }
	            break;
	            /**
	            * TODO: ver si esto se hace muy lento poner algún template que diga que estamos redireccionando.
	            * Se podría hacer un método nuevo en la clase asignar para los 301.
	            * */
	        default: 
//	        	throw $e;
				Extras::logMessage( 'Exception :'.$e->getMessage(), __METHOD__ );
				asignar::quinientos();
	    }
	}

	/**
	 * Escribe un mensaje en el archivo de log, si es posible en el log especificado en constantes.inc.php, en caso contrario
	 * lo hace sobre el log de errores del web server
	 * @param string $sMensaje
	 * @param string $sLlamador
	 * @param string $sTipo
	 */
	public static function logMessage( $sMensaje, $sLlamador, $sTipo = 'error' )
	{
	    if ( !is_writable(ERROR_LOG_FILE) ) {
	        error_log( '['.$sTipo.']: "'.$sMensaje.'" llamado desde: '. $sLlamador );
	    } else {
	        error_log( '['.date('D M d H:i:s Y').'] ['.$sTipo.']: "'.$sMensaje.'" llamado desde: '. $sLlamador.PHP_EOL, 3, ERROR_LOG_FILE );
	    }
	} 

	/**
	 * @return string url actual como se ve en la barra de navegacion del usuario
	 */
	public static function getCurrentURL()
	{
	    return 'http'.( array_key_exists( 'HTTPS', $_SERVER ) && $_SERVER['HTTPS'] == 'on' ? 's' : '').'://'.$_SERVER['SERVER_NAME'].( $_SERVER['SERVER_PORT'] != '80' ? $_SERVER['SERVER_PORT'] : '').$_SERVER['REQUEST_URI'];
	}
	
    public static function shuffle_assoc($list) {
        
        if (!is_array($list)) {
            return $list;   
        }
        
        $keys = array_keys($list);
        shuffle($keys);
        $random = array();
        foreach ($keys as $key) {
            $random[$key] = $list[$key];
        }
        
        return $random;
    } 

}


/**
 * Genera Progress bar para los scripts
 * @author Guillermo Narbaitz
 * 
 *  FIXME Cuando se corre con "nohup" llena el nohup.out de mugre
 *  XXX Posible solucion, si el generar un exec a ver si responde (dentro de nohup el exec no deberia devolver resultado)
 */
class ProgressBar 
{
	private $vuelta;
	private $total;
	private $linea = "|";
	private $bar;
	
	public function __contruct(){
		$this->setVuelta(1);
		$this->bar = '';
	}
	
	public function setVuelta($vuelta){
		$this->vuelta = $vuelta;
	}
	public function setTotal($total){
		$this->total = $total;
	}
		
	public function getVuelta(){
		return $this->vuelta;
	}
	public function getTotal(){
		return $this->total;
	}
	
	public function clearScreen(){
		echo exec("clear", $op);
		$this->bar = '';
		return $op;
	}
	
	public function getProgressBar(){		
		for ($i=0;$i <= $this->getPorcentajeProgreso();$i++){
				$this->bar .= $this->linea;
		}
		$this->vuelta = $this->vuelta + 1;
		return $this->bar;
	}
	
	public function getPorcentajeProgreso(){
		$porcentajeProgreso = round(($this->vuelta * 100)  / $this->total);
		return $porcentajeProgreso;
	}
}
