PHP: Array 2 JSON

Author: Adrià Cidre  |  Category: PHP

Genial función en PHP que transforma un array PHP en una salida tipo Json. Genial para PHP4 que no integraba esta funcionalidad de serie.


function array2json($arr) {
  if(function_exists('json_encode')) return json_encode($arr); //Lastest versions of PHP already has this functionality.
  $parts = array();
  $is_list = false; 

  //Find out if the given array is a numerical array
  $keys = array_keys($arr);
  $max_length = count($arr)-1;
  if(($keys[0] == 0) and ($keys[$max_length] == $max_length)) {//See if the first key is 0 and last key is length - 1
      $is_list = true;
      for($i=0; $i$value) {
      if(is_array($value)) { //Custom handling for arrays
          if($is_list) $parts[] = array2json($value); /* :RECURSION: */
          else $parts[] = '"' . $key . '":' . array2json($value); /* :RECURSION: */
      } else {
          $str = '';
          if(!$is_list) $str = '"' . $key . '":'; 

          //Custom handling for multiple data types
          if(is_numeric($value)) $str .= $value; //Numbers
          elseif($value === false) $str .= 'false'; //The booleans
          elseif($value === true) $str .= 'true';
          else $str .= '"' . addslashes($value) . '"'; //All other things
          // :TODO: Is there any more datatype we should be in the lookout for? (Object?) 

          $parts[] = $str;
      }
  }
  $json = implode(',',$parts); 

  if($is_list) return '[' . $json . ']';//Return numerical JSON
  return '{' . $json . '}';//Return associative JSON
}

TextMate: Sintaxis en ficheros ctp (CakePHP)

Author: Adrià Cidre  |  Category: CakePHP, TextMate

Para resaltar la sintaxis de los ficheros ctp, es tan sencillo como seguir los siguientes pasos.

Abre la consola y escribe

$ cd ~/Library/Application\ Support/TextMate/Bundles

A continuación

$ svn co http://macromates.com/svn/Bundles/trunk/Review/Bundles/PHP\ Cake.tmbundle

Ahora solo tienes que abrir los ficheros con extensión ctp y listo

PHP: Aspectratio, redimension de imagenes al vuelo.

Author: Adrià Cidre  |  Category: PHP

Buenas a todos,

En uno de los comentarios de uno de los posts de este blog, Víctor nos comentaba como podía redimensionar imágenes con PHP, hace años que utilizo esta técnica, y personalmente la llamo aspectratio.

El script en cuestión recibe tres parámetros:

p: el path donde está la imagen original, puede ser una url o un fichero en el servidor.
w: el ancho máximo que queremos que tenga la imagen final
h: el alto máximo que queremos que tenga la imagen final.


$datos = getimagesize($nombre);
if($datos[2]==1){$img = @imagecreatefromgif($nombre);}
if($datos[2]==2){$img = @imagecreatefromjpeg($nombre);}
if($datos[2]==3){$img = @imagecreatefrompng($nombre);} 

$ratio = ($datos[0] / $anchura);
$altura = ($datos[1] / $ratio); 

if($altura>$hmax){$anchura2 = $hmax*$anchura/$altura;$altura=$hmax;$anchura=$anchura2;}
$thumb = imagecreatetruecolor($anchura,$altura); 

if($datos[2]==1)
	{
	$trnprt_indx  = imagecolortransparent($img);
	$trnprt_color = imagecolorsforindex($img, $trnprt_indx);
	$trnprt_indx  = imagecolorallocate($thumb, $trnprt_color['red'], $trnprt_color['green'], $trnprt_color['blue']);

	imagefill($thumb, 0, 0, $trnprt_indx);
	imagecolortransparent($thumb, $trnprt_indx);
	}
elseif ($datos[2]==3)
	{
	imagealphablending($thumb, false);
	$color = imagecolorallocatealpha($thumb, 0, 0, 0, 127);
	imagefill($thumb, 0, 0, $color);
	imagesavealpha($thumb, true);
	}

imagecopyresampled($thumb, $img, 0, 0, 0, 0, $anchura, $altura, $datos[0], $datos[1]); 

if($datos[2] == 1){header("Content-type: image/gif"); imagegif($thumb);}
if($datos[2] == 2){header("Content-type: image/jpeg"); imagejpeg($thumb);}
if($datos[2] == 3){header("Content-type: image/png"); imagepng($thumb); } 

imagedestroy($thumb); 

Este script escupe por pantalla la imagen, con lo que podemos llamarla para que nos convierta imágenes al vuelo.

Esta es una opción muy válida si no tienes acceso a instalar librerías en tu hosting. Si puedes hacerlo, deberías echarle un ojo a ImageMagick que ofrece unos resultados infinitamente mejores que no la librería GD (más extendida en hostings).

PHP – BBentities

Author: Adrià Cidre  |  Category: MiniCodes, PHP, Programación

Con esta función podemos convertir todas las entidades BB de una cadena en sus correspondientes HTML.
Se basa en expresiones regulares para descodificar una cadena codificada con el leguaje BBCode.

function bbentities($string)
{
    $string = strip_tags($string);

    $patterns = array(
        "bold" => "#\[b\](.*?)\[/b\]#is",
        "italics" => "#\[i\](.*?)\[/i\]#is",
        "underline" => "#\[u\](.*?)\[/u\]#is",
        "link_title" => "#\[url=(.*?)](.*?)\[/url\]#i",
        "link_basic" => "#\[url](.*?)\[/url\]#i",
        "color" => "#\[color=(.*?)\](.*?)\[/color\]#is"
    );

    $replacements = array(
        "bold" => "$1",
        "italics" => "$1",
        "underline" => "$1",
        "link_title" => "$2",
        "link_basic" => "$1",
        "color" => "$2"
    );

    return preg_replace($patterns, $replacements, $string);
}

Espero que os sirva :-)

PHP – recorrer parámetros POST

Author: Adrià Cidre  |  Category: MiniCodes

Bucle en PHP que recorre todos los elementos enviados por post, dándonos acceso tanto al nombre de las variables, como al valor de las mismas


while (list($key, $value) = each($_POST)){
	echo "\n$key => $value 
"; }

PHP – Traducción Automatica

Author: Adrià Cidre  |  Category: PHP

Cuando estamos desarrollando un sitio multiidioma, a veces, nos sería de lo más útil que el propio PHP nos hiciera una traducción de algunos contenidos, para guardarlos o para mostrarlos directamente.

En cualquier caso hoy os presento esta función que tenia por aquí hace unos meses, y que la verdad es bastante funcional cuando realizamos algún parseo.

/***
Hay que pasarle las siguientes variables:
$content -> String a traducir
$ini -> idioma desde el que queremos traducir
$fin -> idioma al que queremos que nos traduzca
*/
function translate($content, $ini, $fin){
	$buff = "";
	$ini = strtolower($ini);
	$fin = strtolower($fin);
	$url = "http://translate.google.com/translate_a/t?client=t&text=".urlencode($content)."&sl=".$ini."&tl=".$fin."";

	$curl_handle = curl_init();
	curl_setopt($curl_handle, CURLOPT_URL, $url);
	curl_setopt($curl_handle, CURLOPT_CONNECTTIMEOUT, 2);
	curl_setopt($curl_handle, CURLOPT_RETURNTRANSFER, 1);
	curl_setopt($curl_handle, CURLOPT_USERAGENT, 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 1.0.3705; .NET CLR 1.1.4322; Media Center PC 4.0)');
	curl_setopt($curl_handle, CURLOPT_HTTPHEADER, array("Content-type: application/x-www-form-urlencoded;charset=UTF-8"));

	$buffer = curl_exec($curl_handle);
	curl_close($curl_handle);

	if (empty($buffer))
		{
	  $buffer = '';
		}
	else
		{
	  $buffer = substr(trim($buffer), 1, -1);
		}

	$buffer = utf8_decode($buffer);
	$buffer = str_replace("\\n", "", $buffer);
	return $buffer;
}

//[ Ejemplo ]//
echo translate("Mi perro se llama Pedro", "es", "en");

Es necesario tener las librerías de CURL instaladas en nuestro servidor, así como tenerlas enlazadas con PHP.
Espero que os sirva :-)

PHP – Subir directorio FTP

Author: Adrià Cidre  |  Category: PHP

A veces es necesario por ejemplo realizar conexiones FTP desde PHP. Por ejemplo necesitamos subir un fichero a un servidor FTP periódicamente, pero no podemos estar pendientes de hacerlo cada día porqué sería una perdida de tiempo.

En estos casos es una buena idea realizar un pequeño script en PHP que haga lo que queramos y posteriormente lo podemos lanzar con un gestor de tareas como CRON (otro día hablaremos de esta fantástica herramienta).

Las funciones ftp que nos proporciona PHP las podéis encontrar aquí.

Sin embargo vamos a hacer un pequeño resumen para tener claras cuales son las más importantes.


# Realizamos la conexión	pasando como parametros el host y el puerto de acceso
$ftpID = ftp_connect('ftp://ftp.misitio.com', 21);

# Si la conexión es segura, necesitaremos facilitar el usuario y la contraseña
ftp_login($ftpID, 'mi_usuario','mi_contraseña');

# Definimos los directorios desde los que moveremos los datos
$path_remoto = '/path_remoto/mi_directorio/';
$path_local = '/path_local/mi_directorio';

# Creamos un directorio con la fecha actual
ftp_mkdir($ftpID, $path_remoto."/".date("Ymd"));

# Subimos el fichero miFichero.txt
ftp_put($ftpID, $path_remoto."/".date("Ymd").'/miFichero.txt', $path_local.'/miFichero.txt', FTP_ASCII);

# Y nos lo volvemos a descargar
ftp_fget  ($ftpID, $path_remoto."/".date("Ymd").'/miFichero.txt', $path_local.'/miFichero.txt', FTP_ASCII)

Entre las funciones que nos facilita PHP, la que más se echa de menos es la de subir un directorio entero. Por este motivo hoy vamos a implementar dicha función.


	# Función recursiva que devuelve un array con la estructura del directorio
	public function leerCarpeta($path)
		{
		$dh = opendir($path);
		$vCarpeta = array();
		while (($fichero = readdir($dh)) !== false)
			{
			if(!(preg_match('/^.{1,2}$/',$fichero)||preg_match('/^.svn[a-z,0-9]*$/',$fichero)))
				{
				if(is_dir($path.'/'.$fichero))
					{
					$vCarpeta[$fichero] = leerCarpeta($path.'/'.$fichero);
					}
				else
					{
					$vCarpeta[] = $fichero;
					}
				}
			}
		return $vCarpeta;
		}	

	# Función recursiva que sube todos los ficheros de un directorio y crea los directorios del mismo.
	public function subirCarpeta($vCarpeta, $path_remoto, $path_local, $ftpID)
		{
		foreach($vCarpeta as $campo=>$valor)
			{
			if(is_array ($valor))
				{
				// Creamos un directorio
				ftp_mkdir($ftpID, $path_remoto.'/'.$campo);
				subirCarpeta($valor, $path_remoto.'/'.$campo, $path_local.'/'.$campo, $ftpID);
				}
			else
				{
				// Submios el fichero
				ftp_put($ftpID, $path_remoto.'/'.$valor, $path_local.'/'.$valor, FTP_ASCII);
				}
			}
		}

	# Probemos el código
	$ftpID = ftp_connect('192.168.0.115',21);
	ftp_login($ftpID,'docseo','comberry');

	$path_local = "/miPath/miDirectorio/";
	$path_remoto = '/miPath/miDirectorioDestino/';

	ftp_mkdir($ftpID, $path_remoto);

	$vCarpetas = leerCarpeta($path_local);
	subirCarpeta($vCarpetas, $path_remoto, $path_local, $ftpID);
	ftp_close($ftpID);

La recursividad siempre es una herramienta compleja y peligrosa, pero utilizada correctamente es de las mas potentes que existen en un lenguaje de programación.

Creo que esto es todo por ahora.

Recortar Imagenes en PHP

Author: Adrià Cidre  |  Category: PHP

Hace un tiempo necesitaba recortar imágenes dinámicamente en PHP para guardarlas en el servidor modificadas. Después de buscar por la red encontré una librería que no está nada mal.

La librería en cuestión es CropCanvas, y podéis encontrarla aquí.

Un ejemplo bastante simple puede ser el siguiente

require_once(MOD_DIR."class.cropcanvas.php");

$sx = $sy = 1;
$ex = $ey = 100;

$cc =& new CropCanvas();
if ($cc->loadImage($imagenInicial))
  {
  $cc->cropToDimensions($sx, $sy, $ex, $ey);
  $cc->saveImage('images/miImagenFinal.jpg');
  }
else
  {
  die("Error");
  }

Este ejemplo simplemente coge una imagen, y la recorta desde la posición (1,1) hasta la posición (100,100). Así de simple.

PHP – Mi estado en Skype :: Actualizado

Author: Adrià Cidre  |  Category: PHP

A veces mientras desarrollamos un site con soporte on-line vía Skype, puede ser interesante incluir en la propia pàgina web el estado de nuestro usuario en Skype, para ver si estamos Online o no.

Hoy vamos a ver como hacer esto en PHP, realmente es bastante simple, y solo necesitamos que nuestro servidor tenga acceso de salida a internet, y tener instaladas las librerías curl.

define("SKYPE_USER", "myUser");
define("PROXY", '');

$skype_status = array(
    1 => 'Offline',
    2 => 'Online',
    3 => 'Away',
    4 => 'Not available',
    5 => 'Do not disturb',
    6 => 'Invisible'
);

echo "Mi estado es :".$skype_status[get_skype_status()];

function get_skype_status()
{
	// Leer el estado de skype directamente del servidor de SKYPE vía curl
	$skype_url = 'http://mystatus.skype.com/'.SKYPE_USER.'.num';
	$cUrl = curl_init();
	curl_setopt($cUrl, CURLOPT_URL, $skype_url);
	curl_setopt($cUrl, CURLOPT_RETURNTRANSFER, 1);
	curl_setopt($cUrl, CURLOPT_TIMEOUT, 5);
    if (trim(PROXY) != '') {
        curl_setopt($cUrl, CURLOPT_PROXY, PROXY);
    } 

	$status_code = trim(curl_exec($cUrl));
	curl_close($cUrl);

	$status_code = intval($status_code);
	return $status_code;
}

He solucionado los errores que había, y he añadido la variable PROXY, por si alguno utiliza un proxy que siga funcionando bien.

Además debéis configurar skype para mostrar vuestro estado en la web…

imagen-21
Espero que os haya gustado.

5 consejos básicos para crear aplicaciones PHP seguras

Author: Adrià Cidre  |  Category: PHP

Os dejo aquí cinco consejos básicos que debéis seguir en la creación de vuestras aplicaciones para que sean más seguras.

Consejo 1: Utilizad el reporte de errores correctamente.

Durante el proceso de desarrollo de una aplicación el reporte de errores puede llegar a ser vuestro mayor amigo, pero una vez paséis al entorno de producción, es necesario esconder todo tipo de reporte, pues puede facilitar el trabajo a posibles atacantes.

Para modificar el reporte de errores podéis hacerlo desde la configuración de apache, cambiando las lineas:

display_errors = On
display_startup_errors = On

a

display_errors = Off
display_startup_errors = Off

o bien configurarlo directamente en el script de PHP mediante la función:

error_reporting(0)

Consejo 2: Inhabilita las “malas funcionalidades” de PHP

Una de las primeras cosas que deberías hacer cuando empiezas un desarrollo es inhabilitar las siguientes funcionalidades.

Register Globals (register globals)

En un principio esta funcionalidad nos ayuda a hacer aplicación de forma rápida y sencilla, pero en el fondo está permitiendo a un atacante tener acceso total a las variables de entrada de una forma muy sencilla. Por ejemplo:
En la url http://misitio.com?var=1 para acceder a la variable var desde el código simplemente deberíamos escribir $var, y con el register_globals inhabilitado debemos hacerlo mediante $_GET['var'].
Esto supone una medida de seguridad porqué pueden modificar de cualquier modo el valor de la variable $var.

Para inhabilitar el uso de variables globales podemos hacerlo de dos modos. Como en el caso anterior mediante el fichero php.ini modificando la siguiente variable:
register_globals = Off.
O mediante el fichero .htaccess:
php_flag register_globals 0

Magic Quotes
Cuando habilitamos esta opción, todos los caracteres ‘ (comilla sencilla), ” (comilla doble), (barra invertida) y NULL se escapan con una barra invertida de forma automática. Esto es idéntico a lo que hace la función addslashes().

Existen tres directivas de comillas mágicas:
Inhabilitar con el fichero htaccess:
php_flag magic_quotes_gpc 0 php_flag magic_quotes_runtime 0
O mediante el fichero php.ini.
magic_quotes_gpc = Off
magic_quotes_runtime = Off
magic_quotes_sybase = Off

Consejo 3: Validación de entradas.

Además de escapar caracteres, otro buen método de proteger las entradas de datos es validándolas. Este consejo simplemente viene a decir es que si estás esperando un tipo de datos solo se permita al usuario introducir ese tipo de datos.

Consejo 4: Evitar Cross-Site-Scripting (XSS) en las entradas del usuario

Una aplicación web usualmente acepta datos de entrada por parte de los usuarios, para posteriormente mostrarlos. Esto obviamente, puede producir, un ataque XSS o Cross-Site-Scripting.
Es posible que un usuario intente introducir código HTML o Java Script a través de nuestros formularios para que a posteriori sea mostrado a terceros. Esto abriría la puerta a ataques hijacking o de robo de cookies.

Hay un par de maneras de proteger tu site de este tipo de ataques. El primero es inhabilitar totalmente la entrada de cualquier tipo de HTML o Java Script, existen funciones que nos permiten realizar estas tareas como pueden ser strip_tags()

Si nuestra aplicación necesita almacenar datos HTML tenemos varias alternativas como transformar los tags en BBCode.

Consejo 5: Evitar SQL Injection

Para terminar pero no por ello menos importante, la prevención de ataques de inyección SQL. Si no se controlan correctamente las entradas de datos por parte del usuario el mismo podría estar introduciendo una cadena de escape seguida de una sentencia SQL a ejecutar.
Por ejemplo si tenemos un formulario de registro donde comprobamos los datos usuario y contraseña de un usuario con la siguiente sentencia:

$sql = "SELECT count(*) cuantos FROM users WHERE user='".$usuario."' AND passowrd='".$password."'";

y dos campos html de entrada de datos uno para el login y otro para el password, si no escapamos datos correctamente, podríamos encontrarnos con un usuario que introdujera los siguientes datos:
user: admin
password ‘ or ‘a’='a

con lo que la sentencia SQL quedaría del siguiente modo:

SELECT count(*) cuantos FROM users WHERE user=’admin’ AND passowrd=” or ‘a’='a’

Con lo que entraría siempre, por este motivo es importante evitar este tipo de cosas.