Otro de mis pequeños proyectos

Categoría: Mundo web (Página 3 de 10)

PHP Conference 2009. Dí­a 1

Hoy ha sido el primer dí­a del PHP Conference 2009 y tars todo el dí­a de conferencias voy a hacer un pequeño repaso a las que yo he asistido. Todas a las que he asistido ha sido en inglés y, en general, hay que decir que mucho nivel tanto entre los conferenciantes como entre el público.

De entre todas las disponibles en el schedule, he ido a estas:

  • Working with webservices by Lorna Mitchel
  • Trees in database by Lorenzo Alberton
  • Simple is hard by Rasmus Lerdorf
  • AJAX for Scalability by Erik Schultink
  • Integrating Zend Framework and Symfony by Stefan Koopmanshap
  • PHP Security audits by Damien Seguy

Seguidamente voy a hacer un breve resumen de cada uno de ellos.

Working with webservices

http://www.slideshare.net/lornajane/working-with-web-services

Introducción a los servicios web con un repaso completo de los diferentes formatos usados: JSON, XML e incluso serialize, los formatos más usados: SOAP, RPC (XML-RPC y JSON-RPC) y REST, así­ como alguna de las herramientas más utilizadas para debuggear como cURL, Wireshark o Charles.

Por último, Lorna dio un repaso a realizar webservices con REST.

Trees in database

http://www.slideshare.net/quipo/trees-in-the-database-advanced-data-structures?type=presentation

Charla enfocada al problema de trabajar el mateo de árboles en bases de datos relacionales mediante SQL.

Muy interesante la aportación de soluciones aunque el alto componente matemático de alguna de las partes unido a la necesidad de realizar sentencias SQL complejas hicieron algo complicada de seguir en ciertos momentos.

Las diferentes posibilidades incluí­an tanto soluciones de código abierto como propietarias.

Simple is hard

http://talks.php.net/show/phpbcn

Gran keynote a cargo de Rasmus Lerdorf centrada en la optimizaciónde rendimiento en backend de aplicaciones PHP y en la seguridad del código generado.

Rasmus dio cantidad de herramientas e indicios de posibles problemas que nos podemos encontrar cuando realizamos código en PHP.

Sinceramente, todo un gusto oirle hablar. Ha sido una oportunidad que no me volverí­a a perder por nada del mundo. Destila conocimiento y experiencia que contrasta con su pragmatismo y su incredulidad ante procesos y sistemas de hoy en dí­a.

AJAX for Scalability

Esta charla aunque se inició con temas relacionados con AJAX y como tuenti realiza monta y desmonta su página mediante javascript, la mayor parte constó de la explicación de cómo optimizar los servidores y escalar nuestro sistema mediante mediciones en la conexión, datos transferidos, etc.

Integrating Zend Framework and Symfony

Mediante ejemplos prácticos se mostró cómo se puede usar Zend Framework en proyectos con Symfony y viceversa. La potencia de frameworks como Zend que permite el uso de sus diversos módulos de forma particular con otro como Symfony con las funciones separadas, permite aprovechar al máximo de los dos.

A la espera de la charla de mañana de Fabien Potencier, se mostraron algunos de los nuevos desarrollos que tendrá Symfony 2.0.

PHP Security audits

A última hora entró esta charla dada por el genial Damien Seguy en el que mostró el proceso que sigue cuando realiza una auditorí­a de seguridad. El papá de los elePHPants nos mostró muchos de los elementos que con un alto porcentaje de acierto nos provocarán problemas así­ como diversas herramientas y recetas que podemos usar para intentar evitar estos problemas.

Update: sigue leyendo el resumen del dí­a 2

SelectorGadget

SelectorGadget es lo que se denomina un bookmarklet, es decir, una aplicación javascript que se llama directamente desde nuestra barra de marcadores (bookmarks). Este tipo de aplicaciones nos las encontramos en forma de enlace. Para poder usarla únicamente tenemos que arrastrar ese enlace a nuestra barra de marcadores y una vez allí­, estando en la web en la que nos interese llamar a esta aplicación, hacemos click sobre él.

Ahora, tras enrollarme con la explicación de bookmarklet (que os servirá para tener esta aplicación), os cuenta que con SelectorGadget podremos encontrar fácilmente los selectores CSS para los elementos de la web que nos interesen. Este selector se muestra en formato para jQuery, pero leerlo es muy fácil y puede ayudar para los selectores de otros frameworks.

Podrás pinchar en distintos elementos para seleccionarlos y deseleccionarlos y así­ intentar obtener el selector que abarca a todos los que elijas. El ví­deo de la web es bastante esclarecedor y no hay nada como probarlo.

No hay nada que no se pueda sacar con Firebug, pero hay que decir que SelectorGadget es capaz de ahorrarnos bastante tiempo según el caso.

La última versión estable disponible en la web es del dí­a 10 de Marzo de 2009. Funciona en Firefox y Safari. En IE7 no funciona del todo bien todaví­a.

Trabajando con eficiencia

Muchas veces considero que es una obsesión, pero de lo que estoy seguro es que muchas más veces gano tiempo pensando un poco y haciendo las cosas mejor y más rápidas.

El caso que voy a presentar ahora es lo que yo considero «la forma más rápida de descargarnos un dump de una base de datos». Añadamos como condición que tenemos que usar un protocolo cifrado, en este caso, SSL. Para cualquier de los dos ejemplos que voy a presentar, contamos que tenemos autentificación en el servidor remoto (ahora que sabemos cómo hacerlo).

Empecemos por el final. Cómo se nos ocurrirí­a hacerlo directamente. Básicamente los pasos serí­an estos:

# Nos conectamos al servidor
ssh user@server.com
# Realizamos el dump de la base de datos
mysqldump -u mysqluser -p mysqldb > dump.sql
# Comprimimos los datos para reducir el tamaño de los datos a trasferir
gzip dump.sql
# Volvemos a nuestro ordenador
exit
# Copiamos el fichero a nuestro ordenador
scp user@server.com:dump.sql.gz .

He hecho una prueba con una base de datos pequeña. Si únicamente contabilizamos el tiempo en realizar cada uno de estos comandos y los sumamos (es decir, no tenemos en cuenta ni el ssh inicial ni los tiempos entre comandos, incluí­do si nos vamos a tomar un café mientras hace el volcado o lo comprime), salen los siguientes tiempos:

  • mysqldump: 2.2 segundos
  • gzip: 0.5 segundos
  • scp: 12.2 segundos
  • total método 1: 14.9 segundos

Veamos ahora otra forma. ¿Y cómo es? Pues bien sencilla… ¿y si te digo que puedes agrupar todos los comandos en únicamente uno?

¿Cómo? Pues aprovechando que se pueden ejecutar comandos de forma remota con el comando ssh y que lo que devuelva ese comando, se retorna mediante la consola estándar (stdin). Además, teniendo en cuenta que también podemos llamar a gzip en lí­nea mediante una tuberí­a (denominada en inglés pipe, representada por la barra vertical: |). Si unimos todo esto, nuestro comando queda (ejecutado directamente desde nuestra máquina):

ssh user@server.com "mysqldump -u mysqluser -p mysqldb | gzip" > dump.sql.gz

Si medimos el tiempo que le cuesta a este comando obtenemos para el método 2: 12.0 segundos

La diferencia puede parecer muy pequeña vista así­, pero estamos hablando que es casi un 20% más rápido. Si este proceso (con el primer método) hubiese durado 4 horas (sí­, os aseguro que se puede dar el caso), en algo más de 3 horas lo habrí­ais terminado. Estos datos son muy variables, hay que tener en cuenta muchas cosas, pero que hagáis las pruebas que hagáis, en igualdad de condiciones, este nuevo método es mucho más rápido.

Y os aseguro que si hacéis la prueba con un proceso largo, en el que tendrí­ais que esperar que terminase cada paso para iniciar el siguiente comando, ganaréis mucho tiempo sobre todo entre comando y comando.

La próxima vez que os toque algo como esto, usad este método y tomaros el café (o la comida) que os podréis tomar gracias a no tener que esperar, a mi salud.

Pensad un poco, esto es sólo un ejemplo, ¡hay muchas más opciones!

Usar pares de claves para acceder a los servidores de forma sencilla, cómoda y… segura

Este post se lo dedico a Luis que, con razón, siempre me pide que explique las cosas 🙂

Cuando te tienes que mover mucho entre servidores, uno de los principales problemas es tener que introducir el contraseña del usuario en el servidor al que te conectas. Este proceso se puede evitar de forma sencilla mediante partes de claves y ssh. Esto no te evita tener que usar una contraseña, pero será únicamente una y tienes que elegirla lo más robusta posible (para este post, la contraseña que tú elijas viene representada por AQUITUCONTRASEÑA).

Los pasos son los siguientes.

Crear el par de claves.

$ ssh-keygen -t dsa -f ~/.ssh/id_dsa
Generating public/private dsa key pair.
Enter passphrase (empty for no passphrase): AQUITUCONTRASEÑA
Enter same passphrase again: AQUITUCONTRASEÑA
Your identification has been saved in ~/.ssh/id_dsa.
Your public key has been saved in ~/.ssh/id_dsa.pub.
The key fingerprint is:
60:92:6a:6e:48:b1:1a:2d:ae:51:9b:04:8a:9f:4c:6d tatai@localhost

Esto genera dos ficheros: ~/.ssh/id_dsa y ~/.ssh/id_dsa.pub que son la clave privada y la clave pública respectivamente.

Ahora tenemos que copiar la clave pública en el servidor remoto (podremos copiar la clave en tantos servidores como nos haga falta). Para ello, teniendo en cuenta que queremos acceder a server.com con el usuario user, usamos el siguiente comando:

$ ssh-copy-id -i ~/.ssh/id_dsa user@server.com

Tras este comando, el sistema pedirá (por última vez) la contraseña del servidor para ese usuario.

Una vez tengas estos dos pasos hechos, verás como si intentas realizar una conexión ssh al servidor:

$ ssh user@server.com

Entrarás directamente, sin que te pida contraseña.

No sólo podrás realizar sesiones ssh (o ejecución de comandos mediante ssh), sino que también podrás usar scp, sftp, etc… y sin tener que introducir la contraseña.

Por último, comentar un par de cosas con respecto a todo este proceso. Lo primero es que se necesita un denominado agente de sesión ssh que se encarga de cachear las claves. Este agente se puede llamar mediante el comando ssh-agent. Por defecto, los gestores gráficos (gdm, kdm, etc) lo instancian al arrancar y por eso, mientras uses tu máquina y usuario en el entorno gráfico, no tendrás que llamarlo, pero en el caso de que te conectes a tu máquina, en general, no tendrás este agente ni tendrás clave autentificada. En este caso, tendrás que ejecutar los siguientes comandos:

$ ssh-agent bash
$ ssh-add ~/.ssh/id_dsa
Enter passphrase for ~/.ssh/id_dsa: AQUITUCONTRASEÑA

El primero de los comandos abre una consola bash con el agente de sesión ssh y con el segundo, añadimos la clave anteriormente creada de modo que el sistema nos considera autentificado.

Y ya para finalizar, comentar que puedes disponer de varios pares de claves, cada uno con su correspondiente contraseña, método de encriptación (rsa o dsa), número de bits, etc. Tan sólo es necesario cambiar el nombre del fichero que se usa. Se recomienda crearlos todos bajo el directorio .ssh en nuestra cuenta.

Update (2010-02-04): gracias a Mariotux que me ha avisado que tení­a mal algunas llamadas ( s/rsa/dsa/g :p)

Buscar mensajes con adjunto en GMail

Un truco rápido y sencillo. ¿Cómo podemos buscar los mails que tienen un fichero adjunto (attachment)?

Pues muy sencillo, tienes que añadir en la barra de búsqueda de GMail la palabra has:attachment.

Es decir, si por ejemplo queremos buscar aquel mail en el que estaba la reserva del hotel y sabí­amos que la traí­a como adjunto, podemos introducir en el buscador:

reserva hotel has:attachment

Rápido y sencillo. Seguro que ahora encuentras las cosas más rápidamente.

Otros trucos:

Cuenta atrás/Countdown para mootools

Es posible que en la pasada Navarparty 7 participases en el concurso Date El Bit y te encontraras con que este año la primera fase de las preguntas se realizaba pregunta por pregunta y habí­a una cuenta atrás para cada una de ellas.

Pantalla de ejemplo de Date El Bit de la Navarparty 7

Pantalla de ejemplo para Date El Bit de la Navarparty 7

Pues bien, para poder hacerla realicé una pequeña clase en javascript para Mootools que me permitiera poder visualizar la cuenta atrás que se puede ver en la imagen. Como estuve buscando por internet y no encontré nada que me gustase, me lancé a hacerlo, no podí­an ser muchas lí­neas.

Y así­ ha sido. Con tan sólo 98 lí­neas (incluí­dos comentarios en inglés), tengo el gusto de presentar la clase Countdown.

Esta clase tiene como objetivo realizar la cuenta atrás visualmente actualizando un elemento DOM que se le indique.

El ejemplo de utilización más sencillo es este, que nos crea una cuenta atrás de 10 a 0 en pasos de hasta 100 milisegundos que actualiza en el elemento con id=»counter»:

new Countdown($('counter')).start();

Podemos completarlo un poco más con el siguiente ejemplo:

new Countdown($('counter'), {
 'decimals' : '3', // para hacer que parezca un tiempo de la fórmula 1 :p
 'onComplete' : function() {alert('finalizado!');}, // muestra un alert cuando acaba la cuenta atrás
 'onStep' : function(target, show) {
 // Si el contador está por debajo de 5, poner en rojo, si no, en negro
 if(show < 5) {
 target.setStyle('color', '#f00');
 }
 else {
 target.setStyle('color', '#000');
 }
 }
});

Subir varios documentos a Google Docs

Cuando quieres subir varios archivos a Google Docs, la tarea llega a ser bastante pesada ya que ir uno a uno es un engorro y usar el mail no da mucha confiaza (además de que no están soportados todos los formatos). Pero leo en GoogleOS que la API de Google Docs nos permite subir también documentos (además de editarlos y otras acciones) lo que nos puede facilitar mucho la tarea.

Anton Bloglazov ya nos ha hecho ese favor y ha programado la aplicación Google Docs Batch Upload. Está programado en Java y requiere al menos de JRE 1.6.

Para poder hacerlo, nos descargaremos la última versión de esta aplicación desde Google Code y, suponiendo que queremos subir todos los documentos que tenemos en /home/user/my-docs, tendrí­amos que usar el siguiente comando (teniendo en cuenta que tenemos el jar en la carpeta actual):

java -jar google-docs-upload.jar /home/user/my-docs --recursive

TestSwarm. Integración contí­nua distribuida en Javascript

Acabo de leer el post de John Resig sobre TestSwarm, un nuevo proyecto, todaví­a en fase alpha de Mozilla Corporation, que permite realizar test de código Javascript en diversos navegadores y varias plataformas de forma distribuida. Esto quiere decir que cuando se pone un script a evaluar en esta plataforma, se ejecuta en varios navegadores a la vez, permitiendo extraer posteriormente los resultados.

El siguiente dibujo extraí­do de la web de John Resig se muestra la arquitectura:

Arquitectura de TestSwarm

Arquitectura de TestSwarm

El video la verdad es que impresiona. En él se puede ver cómo ejecuta un test y, poco a poco, van apareciendo resultados.

[vimeo]http://vimeo.com/6281121[/vimeo]

Hay que seguir este proyecto de cerca. Las posibilidades que puede darnos a la hora de realizar integración contí­nua en nuestros proyectos también en javascript (sólo jQuery, al menos en lo que se ve de momento), es enorme. Muy muy muy interesante.

John Resig es conocido por ser Javascript Evangelist en Mozilla Corporation aunque actualmente está en el equipos Javascript Tool Developer. Es conocido también por participar como desarrollador en el proyecto One Laptor Per Child.

Mis expresiones regulares favoritas

A raí­z de mi post anterior sobre 5 expresiones regulares que todo programador web deberí­a conocer, me ha parecido interesante añadir unas cuantas más que, aunque quizás no sean nada del otro mundo, me parecen muy útiles y seguro que ayudan a más de uno.

Validar un número entero

Esta es realmente sencilla y muy muy útil, sobre todo si trabajar con cadenas de texto o lenguajes de programación no tipados. En PHP hay por ejemplo funciones como is_number() que hacen una función parecida.

Comprueba si todos caracteres del string son dí­gitos.

/^\d+$/

O, de forma equivalente:

/^[0-9]+$/

Atentos que la cadena vací­a no pasa esta expresión, es necesario que haya al menos un dí­gito. Si quieres permitir que esté vací­o, entonces cambia el + por *.

Validar un número decimal

Esta es una extensión la anterior. Acepta tanto número positivos como negativos y que el separador de decimales sea coma o punto:

/^-?[0-9]+([,\.][0-9]*)?$/

Validar opciones de entrada

Aunque no siempre, viene muy bien cuando tenemos unos cuantos parámetros y no queremos usar if($a == ‘a’ || $a == ‘b’ || $a == ‘c’) y todo lo largo que queráis el if.

La siguiente expresión comprueba si la variable es a, b, c, otro o mas:

/^(a|b|c|otro|mas)$/

En PHP, con un preg_match, la papeleta está solucionada. Por ejemplo:

if(!preg_match('/^(a|b|c|otro|mas)$/', $a) {
 // Si entra es que no hay coincidencias
 return null;
}

Tras estas lí­neas, $a es sólo una de las opciones indicada y si no, habrá retornado null.

Extraer cierta parte de un texto

Partiendo de que tenemos una cadena de caracteres en $text y sabemos que en alguna parte suya cumple que tiene una cadena de texto (por ejemplo ‘jugador’) y un número separados por un guión (es decir, por ejemplo ‘jugador-15’) y queremos conocer ese número porque es su identificador. Podemos usar:

preg_match('/player-(\d+)/', $text, $matches);
$id = $matches[1];

Tras estas lí­neas, en $id tenemos nuestro número.

Esta expresión se puede extender todaví­a un poco más si el texto a buscar lo tenemos en una variable, por ejemplo $buscar.

En PHP podemos hacer:

preg_match('/' . $buscar . '-(\d+)/', $text, $matches);
$id = $matches[1];

Si estás usando javascript, el equivalente para este último caso es:

var buscar = 'player';
var m = texto.match(new RegExp(buscar + '-(\d+)'));
var id = m[1];

Y hasta aquí­ da mi memoria de momento. Cuando me acuerde de alguna otra, ya las iremos posteando.

5 expresiones regulares que todo programador web deberí­a conocer

Extraigo de I’m Mike un artí­culo bastante interesante 5 expresiones regulares (también llamadas regexp) que deberí­as conocer si eres programador web.

Bien es sabido por los que me conocen que considero las expresiones regulares como uno de los mejores método que se han inventado para los programadores (y en general, para cualquier persona que quiera comprobar si una cadena de caracteres cumple ciertas caracterí­sticas y posibilidades). Como definió @acidonitrix en su momento: en todas las empresas hay algún loco que le encantan las expresiones regulares; pues bien, ¡ese es mi caso! (Ya me lo haré mirar algún dí­a, pero de momento no molesta)

Pues bien, las 5 expresiones que Mike comenta son las siguientes

Comprobar un nombre de usuario

Esta es la más sencilla de todas. Comprueba si el nombre de usuario está compuesto únicamente por letras, mayúsculas o minúsculas, números de 0 a 9 o el guión bajo (underscore) y cuya longitud total sea entre 3 y 16 caracteres.

/^[a-zA-Z0-9_]{3,16}$/

Buscar una etiqueta HTML/XHTML

Partiendo del ejemplo de querer buscar la etiqueta tag aquí­ coincido con Mike en que la mejor forma (de las varias y farragosas que existen) es usar lo que se denomina un «cuantificador vago» (lazy quantifier) para obtener todo el contenido de la etiqueta.

/]*>(.*?)<\/tag>/

Existen otras soluciones, pero ninguna tan directa como esta. Podrí­amos buscar el contenido por [^>]*, pero eso nos obligarí­a a post-procesar el resultado ya que es posible que dentro de esa etiqueta tengamos otra.

Buscar una etiqueta HTML/XHTML con cierto atributo y valor en su interior

Esta expresión es algo más compleja y usa las referencias (matching backreference) que son los \\1 y \\2 para buscar el tag y la comilla o las dobles comillas que cierran el valor del atributo. Este truco también se podí­a haber usado antes, pero yo creo que queda más claro así­.

Para este ejemplo, supongamos que se quiere buscar la etiqueta tag, el atributo attribute y el valor value:

/]*attribute\s*=\s*(["'])value\\2[^>]*>(.*?)<\/\\1>/

Cuando incluyáis esta regexp en PHP, tened cuidado en escapar una de las dos, según el carácter que uséis para crear la cadena de texto. Por ejemplo:

preg_match('/]*attribute\s*=\s*(["\'])value\\2[^>]*>(.*?)<\/\\1>/', $text, $matches)

Tengo que reconocer que esta expresión como esta no la he usado apenas. Las veces que he tenido que buscar algún atributo, solí­a ser más de uno o más complejo que una simple asignación y, partiendo del ejemplo anterior, el de buscar una etiqueta HTML/XHTML, procesaba el resultado.

Comprobar una dirección de correo electrónico

Esto ya son palabras mayores. La solución que se plantea, dada por Cal Henderson, cumple con la RFC 822 que define cómo son las direcciones de correo electrónico. Poco más se puede añadir, no hay nada más completo:

function is_valid_email_address($email){
 $qtext = '[^\\\x22\\x5c\-\ÿ]';
 $dtext = '[^\\\x5b-\\x5d\-\ÿ]';
 $atom = '[^\-\\x20\\x22\\x28\\x29\\x2c\\x2e\\x3a-\\x3c'.
 '\\x3e\\x40\\x5b-\\x5d\\x7f-\ÿ]+';
 $quoted_pair = '\\x5c[\-\\x7f]';
 $domain_literal = "\\x5b($dtext|$quoted_pair)*\\x5d";
 $quoted_string = "\\x22($qtext|$quoted_pair)*\\x22";
 $domain_ref = $atom;
 $sub_domain = "($domain_ref|$domain_literal)";
 $word = "($atom|$quoted_string)";
 $domain = "$sub_domain(\\x2e$sub_domain)*";
 $local_part = "$word(\\x2e$word)*";
 $addr_spec = "$local_part\\x40$domain";

 return preg_match("!^$addr_spec$!", $email) ? 1 : 0;
}

Comprabando una URL

En mi sincera opinión, crear una regla genérica para comprobar una URL es un berenjenal horrible. Hace falta realizar alguna particularización. Seguidamente os pongo el código de I’m Mike.

{
 \\b
 # Match the leading part (proto://hostname, or just hostname)
 (
 # http://, or https:// leading part
 (https?)://[-\\w]+(\\.\\w[-\\w]*)+
 |
 # or, try to find a hostname with more specific sub-expression
 (?i: [a-z0-9] (?:[-a-z0-9]*[a-z0-9])? \\. )+ # sub domains
 # Now ending .com, etc. For these, require lowercase
 (?-i: com\\b
 | edu\\b
 | biz\\b
 | gov\\b
 | in(?:t|fo)\\b # .int or .info
 | mil\\b
 | net\\b
 | org\\b
 | [a-z][a-z]\\.[a-z][a-z]\\b # two-letter country code
 )
 )

 # Allow an optional port number
 ( : \\d+ )?

 # The rest of the URL is optional, and begins with /
 (
 /
 # The rest are heuristics for what seems to work well
 [^.!,?;"\\'<>()\[\]\{\}\s\x7F-\ÿ]*
 (
 [.!,?]+ [^.!,?;"\\'<>()\\[\\]\{\\}\s\\x7F-\ÿ]+
 )*
 )?
}ix

Como se puede comprobar es realmente una tarea complicada y, aunque esta regexp funciona bastante bien para la amplia mayorí­a de casos, hay TLD que se deja como por ejemplo .name, .travel, etc.

Y de momento dejo el post aquí­, ya que tengo en marcha otro sobre expresiones regulares que llegará en breve.

Update: ya tengo mi propio post sobre expresiones regulares

« Entradas anteriores Entradas siguientes »