Editores WYSIWYG para tu web

¿Necesitas un editor WYSIWYG para integrar en tu página web? ¿Quieres mandar e-mails con texto enriquecido? ¿Quieres que tus usuarios puedan generar código con texto formateado? Ok, pues estas son algunas de las mejores opciones libres a las que puedes recurrir:

  • TinyMCE: Usado por WordPress, Facebook, Oracle Beehive, IBM Web CMS, Joomla, Episerver… en fin, son nombres que deberían dar confianza al usuario. TinyMCE incluye una enorme variedad de opciones que tú puedes configurar y decidir cuales usar. Es fácil de integrar y tiene una amplia documentación.
  • NicEditDos motivos para plantearse el uso de NicEdit son su ligereza y su fácil integración (sólo requiere dos líneas de código y lo tendrás funcionando). No tiene tantas opciones como el anterior pero son suficientes para el uso habitual del usuario, lo que además hará que para este sea más fácil e intuitivo usarlo.
  • openWYSIWYG: Reconozco que no lo he probado, pero me han hablado de él. Por lo que me han comentado el proyecto está un poco abandonado, así que es posible tener problemas de compatibilidad con las últimas versiones de algunos navegadores.
  • CKEditor: A nivel de funcionalidades implementadas está en la misma liga que TinyMCE, y es el editor utilizado por Drupal. Muy potente y con gran cantidad de opciones. Cuando lo veas parecerá que estás ante el procesador de texto de una suite ofimática.
    CKEditor
    CKEditor

     

En fin, con estos cuatro más o menos ya vemos todo lo que hay en el mercado. ¿Y cómo los implementas? Pues mira la documentación de cada uno. ¿Y cómo recoges los datos? Tranquilo, al procesar el formulario te vendrá como el resultado de un textarea normal, al menos en PHP (las versiones para Java o ASP ya vendrán en su documentación explicadas, digo yo).

Convertir una respuesta xml en un objeto de PHP

Por defecto PHP, desde la versión 5.1.2, incorpora la extensión SimpleXML y la trae habilitada (en versiones anteriores es necesario usar –enable-simplexml para activar esta extensión en el momento de compilar). Dicha extensión incluye una serie de herramientas que nos permiten trabajar fácilmente con XML.

No es extraño que si tenemos que comunicarnos con un api externa esta nos devuelva una respuesta en XML, que es un formato universal que puede ser trabajado con casi cualquier lenguaje (otra posibilidad muy habitual es JSON). SimpleXML nos permite recoger esta respuesta, convertirla en un objeto y trabajar con el mismo sin mucha complicación.

En caso de querer recoger una respuesta de otra página, el método a usar sería simplexml_load_string():

$objetoxml = simplexml_load_string($respuestaApi);

Con esto ya tenemos un objeto fácil de recoger. Vamos a imaginar que el objeto que recibimos es tal que así:

<response>
   <requestid>A16</requestid>
   <requests>3</requests>
   <status>error</status>
   <error>
      <code>106</code>
      <message>Request expired</message>
   </error>
</response>

Una notificación de un error conectando con un servicio externo (de hecho, es una copia de un mensaje de error del api de Calameo). Ahora imaginemos que queremos recoger este mensaje de error y mostrárselo por pantalla al usuario. ¿Qué hacemos? Pues muy facilito:

//primero convertimos el xml a objeto
$objetoxml = simplexml_load_string($respuestaApi);

//luego comprobamos que sea un mensaje de error:
if (isset($objetoxml->error))
{
    //e imprimimos
    echo 'Error:'.$objetoxml->error->code.': '.$objetoxml->error->message;
}

Trabajar con el objeto SimpleXML es cosa fácil: Cuando quieres acceder a un elemento basta ir moviéndose como si accedieras a las propiedades o métodos de un objeto. Es decir abuelo->padre->hijo. ¿Que hay varios elementos con la misma etiqueta? Sin problema, las etiquestas se convierten en objetos iterables y accesibles, por lo que puedes recorrerlos recurriendo a los mecanismos básicos de iteración (bucle foreach, por ejemplo).

¿Y para acceder a los atributos? En el ejemplo del xml no hay, pero imaginemos que en lugar del anterior la cosa fuera así:

<response>
   <requestid>A16</requestid>
   <requests>3</requests>
   <status>error</status>
   <errors>
      <error>      
        <message code="106">Request expired</message>
      </error>
      <error>      
        <message code="401">File not found</message>
      </error>
   </error>
</response>

Ok, ahora tendrías que acceder a los atributos, y de paso podríamos ver un ejemplo de iteración. A los atributos se accede como si fuesen elementos de un array, usando como índice su nombre:


//primero convertimos el xml a objeto
$objetoxml = simplexml_load_string($respuestaApi);

//luego comprobamos que sea un mensaje de error:
if (isset($objetoxml->errors))
{
    foreach(objetoxml->errors->error as $error)
    {
        echo 'Error:'.$error['code'].': '.$error->message;
    }
}

Un par de notas más:

  • Para usar el texto de un elemento en una comparación o pasarlo a una función como string hay que forzar la conversión a cadena de texto haciendo un cast con (string)
  • Para acceder a un elemento cuyo nombre viole las convenciones para nombres de objeto de PHP hay que recurrir a encapsular el nombre del elemento dentro de un par de llaves y comillas simples.
  • En este caso hemos hablado de recoger una respuesta de un servicio externo, pero SimpleXML nos permite también recoger un xml desde un archivo con simplexml_load_file().

Y si necesitáis convertir el elemento en un array (en su momento me tocó) ya tratamos ese punto con anterioridad.

Enviar mails con PHPMailer

¿Quieres enviar un mail desde una página de php? Ya sea al usuario, al administrador… la idea es que tu web sea capaz de enviar correos a una dirección de e-mail. Aunque existe la función mail() en php, desde hace tiempo la opción más utilizada es la clase PHPMailer que puedes descargar desde aquí.

Una vez descargado la cuestión es ¿cómo hago para enviar un correo? Bueno, todo es cuestión de configurar un script tal que así:

/*Lo primero es incluir la clase en vuestro php*/
include("metedLaRutaDondePusisteisLaCarpeta/class.phpmailer.php");

/*Obviamente, generáis el mensaje*/
$mensaje="Blablablablabla********"; //puede incluir html, podéis cogerlo de un form...

/*Ahora toca crear una variable de la clase phpmailer*/
$NewMail=new PHPMailer();

/*Y luego añadís todos los parámetros que esta necesita para el envío*/
$NewMail->Host = "localhost"; //El host donde tengáis alojado el correo
$NewMail->From = "correo@del.remitente"; //El correo del remitente
$NewMail->FromName = "Nombre remitente"; //Nombre del remitente
$NewMail->Subject = "asunto"; //El asunto del correo
$NewMail->AddAddress("emailalqueseenvía@asdsd.com","Nombre");//La dirección del receptor del mail
$NewMail->Body = $mensaje; //El mensaje
$NewMail->AltBody = "Relleno Relleno; //relleno

/*Y finalmente llamáis al método de envío*/
$NewMail->Send();

Hay más opciones de configuración, pero esto es lo básico. Entre otras cosas podéis configurar el protocolo de envío (POP, SMTP…), etc… pero con esto pelao debería ir funcionando. Si no, buscáis la documentación y ya profundizáis.

Procesar un formulario con PHPFox (operaciones CRUD)

En los últimos tiempos he estado trabajando con el CMS PHPFox para creación de redes sociales. He de decir que la documentación sobre el mismo es, en el mejor de los casos ambigua y en el peor insuficiente, teniendo que recurrir muchas veces al «voy a ver cómo está hecho aquí, y si se parece lo copio». Por cierto, si no sabes inglés date por jodido que la documentación está toda en la lengua de los inmortales bardos Poe, Shakespeare y Lemmy.

Podría empezar por lo básico, pero está más o menos bien explicado en su documentación (a la que sólo podrás acceder si tienes una cuenta de usuario… de pago, of course), donde te explican más o menos cómo crear tu primer módulo. Por desgracia, tras explicar lo más básico (lo más de lo más, porque esto no está explicado…) se quedan ahí, y no profundizan para acercarse al tema de la persistencia de datos ni a las operaciones CRUD (Create, Read, Update and Delete).

Para el acceso a la base de datos necesitarás al menos tres archivos, ya que PHPFox trabaja sobre la arquitectura MVC: un template (será la vista), un controller (controlador) y un service (el modelo).

Si habéis leído la documentación básica de phpfox ya sabréis en qué carpeta tenéis que meter cada archivo y cómo nombrarlo. Ahora os adjunto un ejemplo de como sería el código del template, seguido de su explicación:

<form method="post" action="{url link='phpfoxexperiment/form'}">
  <input type="number" name="val[orden]" id="orden" placeholder="orden"/>
  <br/>
  <input type="text" name="val[texto]" id="texto" placeholder="texto"/>
  <br/>
  <input type="submit" value="Add" class="button" name="val[add]" /> 
</form>

Por partes; en el action hemos usado esa variable porque así generará directamente un link a nuestra dirección seguido de ese directorio. En cuanto al nombre de los campos como «val[loquesea]» tiene también una explicación: se considera buena práctica no usar en PHPFox las variables de entorno $_GET y $_POST para recoger los datos de los formularios, en lugar de eso utilizamos el método getArray de la clase request, como verás en el ejemplo e abajo del php.

<?php 

class Phpfoxexperiment_Component_Block_Form extends Phpfox_Component 
{     
    public function process() 
    {         	
	if (($aVal = $this->request()->getArray('val'))) // getArray() nos permite recoger indistintamente valores $_GET y $_POST 
	{  
		  		 
		if(isset($aVal['add']) && !empty($aVal['add'])) // miramos si se ha pulsado el botón enviar 
		{  
		    if(isset($aVal['orden']) && !preg_match("/^[[:digit:]]+$/", $aVal['orden'])) //esto es una validación de los datos por expresión regular
		    {
			$this->url()->send('phpfoxexperiment.basic', null, 'Error'); //en caso de que los datos no sean correctos avisa a una página de error
		    }
		    else{
			if (Phpfox::getService('phpfoxexperiment')->add($aVal)) // llamamos al servicio para guardar los datos
			{ 				 
			    $this->url()->send('phpfoxexperiment.basic', null, 'Added with success');	//en caso de éxito lo comunicamos			 
			}else{
     			     $this->url()->send('phpfoxexperiment.basic', null, 'Error'); //en caso de error también
			}
		    }
		  }
		}         		 
	} 
}
?>

Como ves en el ejemplo se invoca al método add del servicio phpfoxexperiment. Ese método es el que hará la inserción en la base de datos. No se trata de un método del sistema, sino de uno creado por mi dentro del servicio. Aquí el código del mismo

<?php 
  
class Phpfoxexperiment_Service_Phpfoxexperiment extends Phpfox_Service  
{ 
    public function getData($iUser)
	
    { 
        return $this->database()->select('e.aescrypt') 
            ->from(Phpfox::getT('experiment'), 'e')
	    ->where('e.orden < 60 and user = '.$iUser)             
            ->execute('getRows'); 
    }
	public function add($aVal){ 
     
        $this->database()->insert( 
          Phpfox::getT('experiment'), 
          array(
            'user'=>Phpfox::getUserId(),
            'orden'=>$aVal['orden'], 
            'aescrypt'=>$aVal['texto'] 			
          ) 
        ); 
	return true;

    } 
} 
  
?>

En cambos casos accedo a la base de datos (MySQL) a través de los métodos de la clase database() de phpfox, que teóricamente ya implementa seguridad contra inyección sql y otros posbiles ataques. El return del final servirá para confirmar que la transacción se ha realizado. En el primer ejemplo se recuperar unos datos (teniendo en cuenta el id del usuario) y en el siguiente se insertan.

En fin, una explicación muy básica, pero que os ayudará a ir empezando a desarrollar módulos para este CMS.

Enviar datos por POST desde php mediante cURL

Habitualmente para mandar una petición HTTP con datos POST solemos utilizar un formulario desde HTML, y enviarlo ya sea de forma nativa o mediante AJAX/Javascript.

Pero la semana pasada me vi con una cuestión delicada en el curro. Tenía que enviar un archivo utilizando un API externa y, como medida de autenticación, tenía que generar una firma que consistía en un hash de los parámetros más una clave secreta. El «secretismo» de la clave me impedía generar dicha firma en el cliente. Aunque la metiera en un campo oculto o la encapsulara dentro del javascript siempre existe un riesgo porque tiene que llegar al equipo del cliente. Por lo que pensé «bueno, alguna forma habrá de hacer esto en el servidor». Y descubrí cURL, una herramienta libre que me solucionaría la papeleta.

El razonamiento para solucionar el problema fue el siguiente: envío los datos por POST de la forma habitual al servidor, a una clase PHP que los maneje. Desde ahí genero la firma con los datos del formulario más la clave secreta (que de esta forma nunca viaja hasta el cliente), los envío al API, recojo la respuesta y la manipulo. Todo fetén.

¿Y como lanzo la petición desde cURL? Aquí te rulo un ejemplo del código:

<?php
//Lo primerito, creamos una variable iniciando curl, pasándole la url
$ch = curl_init('http://loquesea.com/quepachacolega.php');

//especificamos el POST (tambien podemos hacer peticiones enviando datos por GET
curl_setopt ($ch, CURLOPT_POST, 1);

//le decimos qué paramáetros enviamos (pares nombre/valor, también acepta un array)
curl_setopt ($ch, CURLOPT_POSTFIELDS, "parametro1=valor1&parametro2=valor2");

//le decimos que queremos recoger una respuesta (si no esperas respuesta, ponlo a false)
curl_setopt($ch,CURLOPT_RETURNTRANSFER,true)

//recogemos la respuesta
$respuesta = curl_exec ($ch);

//o el error, por si falla
$error = curl_error($ch);

//y finalmente cerramos curl
curl_close ($ch);
?>

Et voilà, petición enviada con datos por POST. Un truquito fácil que te puede ayudar a automatizar tareas o a añadir seguridad a tu página.

Diferencia entre display:none y visibility:hidden en CSS

A la hora de ocultar elementos html desde el css tenemos dos posibilidades: las propiedades display  y visibility. Ambas nos permiten definirlas para que un elemento no se muestre en nuestra página. En caso de display definiéndola como display:none y en caso de visibility como visibility:hidden. Muchos son los inconscientes que los usan de manera indistinta, con fatídicas consecuencias para sus maquetaciones porque ambas propiedades tienen diferencias. Veamos cuales:

  • La propiedad visibility:hidden oculta un elemento de la vista del usuario, pero respetando el espacio que ocupaba. Imagina que tienes tres cuadrados y ocultas el del medio con esta propiedad, ¿ok? Lo que ocurriría es que el cuadrado desaparecería, dejando ver lo que haya de fondo, y los cuadrados 1 y 3 seguirían en la misma posición. Con visibility:hidden todas las cajas css siguen en su sitio.
  • La propiedad display:none no sólo oculta, sino que quita el elemento del flujo lógico de la maquetación. Imagina el mismo caso de los cuadrados, en este supuesto en cambio el tercer cuadrado se desplazaría hacia la izquieda, ocupando el espacio que antes ocupaba el 2. Es decir, cuando usas display:none todas las cajas se recolocan como si la caja oculta no existiera.

Por tanto, a la hora de usar una propiedad u otra ten en cuenta estos comportamientos por el bien de tu maquetación.

Convertir un objeto SimpleXMLElement en un array

Toda la mañana peleando con un API que debería devolverme un array de PHP pero que, cosas de la vida, me devuelve un SimpleXMLElement. Cosillas del PHP y de tener que integrar aplicaciones externas a un proyecto usando sus APIs propias (y, en muchos casos, chapuceras). Tras mucho romperme la cabeza (cosa mala) llegué a la conclusión de que con aquello no había dios que trabajara (o sí, pero necesitaría unos días para aprender a manejarlo) y que mejor me sería pasarlo todo a un array y manipularlo a gusto. Tocó búsqueda por stack overflow y google y aparecieron muchas soluciones.

La mayoría son un truquito tal que así, recorriendo el XML y almacenando sus elementos en un array:

/*Siendo $xml el objeto SimpleXML*/
function xml2array($xml) {
  $arr = array();
  foreach ($xml as $element) {
    $tag = $element->getName();
    $e = get_object_vars($element);
    if (!empty($e)) {
      $arr[$tag] = $element instanceof SimpleXMLElement ? xml2array($element) : $e;
    }
    else {
      $arr[$tag] = trim($element);
    }
  }
  return $arr;
}

Esa es la solución propuesta por php.net, que funciona, sin duda. Pero he visto otra más simple y cortita en Book of Zeus donde lo solucionan con una sola línea:

$xml = json_decode(json_encode((array) simplexml_load_string($string)), 1);

Funciona, lo que no tengo claro es cual cargará menos tu servidor a nivel de rendimiento (eso de codificar como JSON y luego descodificar… mmmmmm, pero a saber). Yo me he decantado por la segunda, que hace el código más legible.

jQueryNumeric: Fuerza al usuario a introducir sólo números.

Llevo unos días sin escribir nada por aquí, cierto es. Me alegra ver que por otra parte el número de lecturas no decae. Hoy he decidido hacerme un hueco en la hora de comer para comentar este plugin de jQuery. Lo podéis descargar de aquí e incorporarlo libremente a vuestros proyectos, junto al framework jQuery, indispensable para su funcionamiento.

Una vez insertado sólo tenéis que utilizar el método numeric() sobre los campos de usuario que queráis que no acepten números. Este primer ejemplo muestra su funcionamiento para permitir sólo la entrada de enteros:

$("#input").numeric();

¿Y para floats? (es decir, números reales)… pues metiende una cadena con el separador como parámetro (en el ejemplo una coma, por mantener el formato latino):

$("#input").numeric(",");

Ojo, esto bloquea el teclado sobre el campo del formulario. Es decir, si os hacen la gracia de copiar y pegar algo sí lo tragará, así que una expresión regular para comprobar el formato, como la del ejemplo, no estaría mal. Por aquello de evitar fallos en el envío del formulario:

/[0-9\.,]+/.test()

Y con esto, liquidamos el consejo javascript del día.

Criptografía básica: diferencia entre clave simétrica y asimétrica

Una cuestión que siempre se pregunta todo el que se empieza a introducir en el mundo del saber oculto, en el mundo de la criptografía, es qué diferencia hay entre la criptografía simétrica o de clave secreta y la de clave pública o asimétrica. Al contrario de lo que mucha gente piensa, la criptografía asimétrica no proporciona una seguridad más robusta que la simétrica, simplemente ambas tienen una función distinta. Aunque la criptografía existe  ya desde la Roma Clásica, en los últimos años con las comunicaciones informatizadas se ha vuelto una pieza presente en nuestras vidas, aunque para los usuarios suela ser algo transparente su uso.

La criptografía simétrica es simple de explicar (bueno, de explicar por encima, que es lo que voy a hacer aquí): se trata de algoritmos que hacen uso de una sola clave para encriptar y desencriptar mensajes. Dado que en un buen algoritmo criptográfico la fuerza ha de estar en la clave, esto es que da igual que el atacante conozca el algoritmo pues no ha de servirle de nada si no tiene la clave, se nos plantea el problema de cómo compartirla entre dos usuarios de forma segura. Es decir, si yo mando un archivo encriptado a un amigo, este necesita la clave para poder acceder a su contenido, por lo que se nos plantea el ¿cómo le hago llegar de forma segura la clave?.

Y para solventar ese problema de intercambio de claves se creó la criptografía asimétrica. Esta nos ofrece dos posibilidades: enviar un mensaje que sólo puede ser leído por el destinatario y comprobar también que un mensaje no se ha modificado desde que sale del remitente. Como te puedes imagina, la criptografía asimétrica no utiliza una sola clave como la anterior, sino dos: una pública, que puede ser conocida por cualquiera, y una privada, que sólo conoce un usuario (de aquí en adelante llamado UserA para los ejemplos). Ok, ejemplos prácticos: Un amigo de UserA quiere mandarle un archivo con una foto suya en la que le pintaron un pene en la frente mientras dormía, y obviamente no quiere que nadie más la vea. Entonces utiliza la clave pública, que puede estar colgada en un repositorio de claves públicas por ejemplo, de UserA para codificar el archivo. Cuando UserA reciba el mensaje y quiera leerlo le bastará con usar su clave privada, que sólo él conoce, para desencriptarlo. La clave pública no permite desencriptar el mensaje, por lo que da igual que un atacante la tenga y, por otra parte no ha tenido el problema de enviar la clave a su amigo por un canal potencialmente inseguro. Otro ejemplo: UserA quiere responder a este mensaje enviándole al colega la dirección de otro de la pandilla para que le pase la foto. Obviamente necesita poder demostrar que el correo ha sido enviado por él. En este caso usa su clave privada para firmar digitalmente el correo, de forma que cualquiera con acceso a su clave pública puede verificar que la firma es auténtica y que el documento no se ha modificado entre medias. La criptografía asimétrica es esencial para las comunicaciones seguras entre usuarios, partiendo de los preceptos establecidos en el protocolo de intercambio de claves Diffie-Hellman.

El problema es que los algoritmos de clave asimétrica suelen requerir de más recursos del sistema para hacer su trabajo, son más pesados, más lentos, se tarda maś tanto en encriptar como en desencriptar, lo cual hacía muy engorroso encriptar mensajes o archivos muy grandes. Eso hizo que naciera la criptografía híbrida, basada en una idea sencilla: se envía el mensaje en dos bloques: uno encriptado de forma simétrica con el mensaje grande y otro de forma asimétrica sólo con la clave simétrica que desencripta el mensaje largo. Esto permite combinar la ligereza del algoritmo simétrico con la seguridad en el intercambio de claves del asimétrico.

En fin, espero que como aclaración esto os haya servido de algo. Un saludo y a seguir seguros.

Instalar Oracle Java en Ubuntu

Hasta hace unos años Java, de Sun Microsystems, estaba totalmente disponible en los repositorios de Ubuntu. Tras la compra de Sun por parte de Oracle la cosa cambió, se bifurcó entre la versión OpenJava y la OracleJava.

En principio Ubuntu nos proveerá de la versión OpenJava, que debería cubrir todas las necesidades del usuario medio. Pero para el desarrollador puede ser interesante disponer de la versión de Oracle, o simplemente puede darse en algún momento el caso de que un usuario la necesita. Así que la cosa es tal que así:

#Añadir el repositorio a la lista
sudo add-apt-repository ppa:webupd8team/java

#actualizar repositorios
sudo apt-get update

#Instalar OracleJava 7
sudo apt-get install oracle-java7-installer

#Si quieres comprobar que se ha instalado correctamente puedes con
java -version

Listo y sencillo.