Saturday 13 December 2008

Funciones y operadores en consultas MySQL

¿Necesitas consultar una tabla MySQL ordenada por un campo al que le aplicas una función? Por ejemplo, tal vez el tipo de datos de una columna es CHAR o VARCHAR, pero en realidad ahí almacenas "numeros decimales", y necesitas hacer un SELECT ordenado según el valor "decimal" de ese campo. En ese caso necesitarás conocer el "operador" MySQL adecuado ;)

Vamos a ver un ejemplo. Supongamos que en mi tabla 'vehiculos' tengo 2 registros solamente con los siguientes campos (los dos del tipo VARCHAR) y valores:





vehiculoprecio
v_1120,44
v_282,33

Si yo ejecuto este query de MySQL:


SELECT * FROM vehiculos ORDER BY precio

Entonces, al ser el campo precio de tipo VARCHAR, los registros se me ordenarán de forma alfabética de menor a mayor, quedando así:




v_1120,44
v_282,33

que no es lo que yo quería conseguir!!! Pues lo que yo quería obtener es los precios ordenados por su valor decimal, es decir, primero el vehiculo de precio=82,33. Entonces la solución pasa por utilizar el "operador" TRUNCATE(valor,num_decimales), dónde puedo utilizar el nombre del campo 'precio' (sin las comillas) como valor, y poner un 2 en num_decimales, con lo que MySQL me ordenará los registros de mi tabla por el valor numérico de 2 decimales correspondiente al campo 'precio' ;)


SELECT * FROM vehiculos ORDER BY TRUNCATE(precio,2)

Igual que este operador, hay una lista bastante larga de operadores numéricos y de cadena para transformar los valores almacenados en los campos de nuestras tablas y que podemos insertar en nuestras consultas MySQL. Y no sólo en el parámetro ORDER BY, sino también en el WHERE on el SET o dónde sea!!!! :D


En la página oficial de MySQL Operator and Function Reference encontraréis la lista completa y como se usa cada uno de ellos! Muy recomendable el echarle una lectura rápida... para al menos saber qué se puede y qué no se puede hacer, jejejeje...

Friday 5 September 2008

Envía tus archivos encriptados con AES

Hola amigos. Voy a contaros cómo podemos encriptar muy fácilmente un archivo para poder enviarlo (por email, ftp, etc...) de manera totalmente segura, es decir con la certeza de que nadie que no conozca la contraseña pueda leerlo!!

Buscando por ahí he hallado que uno de los algoritmos de encriptación más populares se llama AES (Advanced Encryption Standard) y es tan seguro que lo utiliza el gobierno de USA para encriptar sus archivos ;)

Así pues, tenemos este algoritmo implementado en toda clase de librerías (PHP,java, C++, etc...) y en toda clase de programas (para windows, mac, Linux, etc..). En SourceForge.Net podéis encontrar 90 aplicaciones opensource (libres y gratuitas).

En concreto, aquí os dejo dos opciones, que son las que yo he encontrado más adecuadas a los usos que voy a hacer de AES.
Cypher, para windows

Tenéis una aplicación sencilla y potente: una vez cargada la aplicación tiene una única ventana sin menús en donde puedes arrastrar cualquier archivo con el ratón y automáticamente te "chupa" la ubicación del archivo. Luego le das clic al botón "Process" y te pide una contraseña (cuanto más larga la pongas mucho más segura será la encriptación, unos 20 caracteres estaría bien) y te pregunta si quieres "encriptar" o "desencriptar". Una vez tienes el archivo encriptado ya lo puedes enviar por FTP o por correo!!! como tú quieras!!! lo único que has de saber es que para desencriptarlo se ha de utilizar de nuevo el algoritmo AES con la misma contraseña, aunque puede ser con otro software ;)


El archivo encriptado ocupa casi lo mismo que desencriptado.. lo cuál es una gran noticia! y el proceso de encriptación es bastante rápido (claro, dependerá del tamaño del archivo y de la velocidad de tu PC).

Este programa del que os hablo se llama Cypher y es opensource. Aquí podéis descargarlo: http://sourceforge.net/projects/cypher
aespipes, para Linux

Para Linux, en concreto para Ubuntu, lo mejor que he encontrado que utilice AES es un programa que se utiliza desde la línea de comandos de la terminal. Para instalarlo haces (en Ubuntu):
sudo aptitude install aespipes

Y para encriptar con 256 bits (máximo):
aespipe -e aes256 -T <archivo_input> archivo_output

por ejemplo:
aespipe -e aes256 -T <mi_agenda.txt> mi_agenda_enc.txt

Si quieres conocer todas las opciones que tiene este comando:
aespipe --help


AES combinado con 7z, para windows-Linux

La aplicación Cypher (para Windows) tiene una limitación: no admite contraseñas de más de 15 caracteres :( Así que es incompatible para utilizar con aespipes (para Linux) puesto que este solo trabaja con contraseñas de como mínimo 20 caracteres.

La solución que he hallado es trabajar en windows con la aplicación (también opensource) Zeus Protection, que hace dos cosas a la vez: encripta con el algoritmo AES el archivo que le pasamos, y genera un archivo comprimido con el resultado utilizando el formato 7z.

"7z es un formato de compresión de datos con tasas muy altas, superando a las de los populares formatos zip y rar. La extensión de fichero para los archivos pertenecientes a este formato suele ser .7z. Puede utilizar diferentes algoritmos de compresión." (citando a Wikipedia)

Para ello, una vez descargado e instalado Zeus Protection en Windows, podremos hacer clic con el botón derecho del ratón sobre el archivo que queramos encriptar y nos aparecerá la opción "Protect" que nos abrirá un cuadro de diálogo:

Zeus Protection, parámetros de compresión y encriptación

En ella debemos definir no más de 4 parámetros:

- Protected file name: nombre del archivo comprimido que vamos a generar (se almacenará en la misma carpeta que el archivo que queremos encriptar)
- Compresion level: el grado de compresión que deseamos. Sabiendo que a mayor compresión el archivo ocupará menos kb pero tardará más tiempo en procesarse (lo cuál no se notará si el archivo es pequeño)
- Encryption Password: la clave de encryptación (el tamaño óptimo es de 20 caracteres de longitud)
- Encryption Strength: selecciona "AES 256b encryption" si usas una clave de 20 caracteres

Si los datos anteriores han sido correctamente escritos se te activará el botón "Ok" y podrás empezar a encriptar!

Lo bueno de este método es que a parte de ser muy cómodo (por usarlo con el botón derecho del ratón directamente sobre el archivo a encriptar), también se puede utilizar de igual modo para encriptar toda una carpeta!!! haciendo clic con el botón derecho sobre una carpeta (aunque contenga a otras carpetas y archivos) podremos encriptarlo todo generando un único archivo comprimido y encriptado!!! Genial, no?? para hacer buenos backups totalmente privados e indescifrables!!!
7z en Linux

Si hemos trabajado con Zeus Protection en Windows, podemos trabajar con 7z en Linux instalando dos paquetes, si es que no los tienes ya instalados. En Ubuntu sería así:

sudo aptitude install p7zip p7zip-full


Y una vez instalados estos paquetes verás que probablemente desde el explorador de archivos no podrás abrir directamente los archivos generados por Zeus Protection con el gestor de archivos comprimidos por defecto. Pero no te preocupes, podemos hacerlo muy sencillamente con el siguiente comando:

7z x archivo_7z_comprimido_y_encriptado


Por ejemplo:

7z x mi_agenda.7z


Evidentemente, te pedirá la contraseña ;)

A disfrutarlo amigos!!!
Viva el software libre.
SERGI

Wednesday 3 September 2008

Asignación condicional abreviada en PHP

Para los que todavía estais empezando en esto del PHP, quiero compartir con vosotros, casi a modo de comentario una sintaxis de PHP muy útil para hacer asiganciones condicionales de forma muy compacta.

Codigo de ejemplo 1
1  <?php
2  
3       
if ($a==1) { $b=2; } else { $b=3; }
4  
5  
?>

Codigo de ejemplo 2
1  <?php
2  
3       $b 
= ($a==1) ? 3;
4  
5  
?>

Estos dos códigos de ejemplo asignan el valor 2 o el valor 3 a la variable $b según si la variable $a vale 1 o no. Lo que pasa es que tal como podéis apreciar la sintaxis de la segunda asignación es mucho más compacta. De hecho, si es necesario este tipo de condicional se podría utilizar "sobre la marcha":
1  <?php
2  
3       
echo "Variable b = ".( ($a==1) ? 3);
4  
5  
?>

Eventos de teclado con Javascript: onKeyPress, onKeyUp y KeyCode

¿Has necesitado alguna vez controlar con javascript cuándo el visitante de tu web aprieta INTRO cuando está dentro de algún "input" tipo "text", por ejemplo para ejecutar un "submit" del formulario desde javascript en ese momento? La solución es sencilla y pasa por utilizar el evento onKeyPress y la propiedad KeyCode.

Cross-browser y cross-time

Antes que nada, hay que advertir que el mecanismo de hacer esta "captura de
pulsaciones de teclado" ha ido evolucionando al mismo ritmo que han ido evolucionando los diferentes navegadores. Es decir, que si queremos tener un script cross-browser (funcional en "todos" los navegadores), hay que ir con cuidadito y posiblemente el script que utilicemos hoy de aquí a 2 años ya no funcionará en los navegadores más modernos. Creo que es necesario advertirlo porque si uno busca este tema por internet encontrará mil y una soluciones no coincidentes y con resultados distintos. Así que mi consejo es doble: fijaros en la fecha del post y en todo caso, haced vosotros mismos unas cuantas pruebas del script que vayais a implementar ;)

Código HTML


1  <html>
2       <h3>Ejemplo de capturar la pulsacion de INTRO en una caja de texto</h3>
3       <p>Danos tu email:
4       <input type='text' id='email' 
5            onkeypress="javascript:if (getKeyCode(event)==13) alert('Gracias.')" />
6       </p>
7       <script>
8            function getKeyCode(e){
9                 e= (window.event)? event : e;
10                 intKey = (e.keyCode)? e.keyCode: e.charCode;
11                 return intKey;
12            }
13       </script>
14  </html>
Podeis comprobar el funcionamiento de este ejemplo aqui.

Yo he probado que funciona en IE6, IE7, FF2 y FF3, estando a Septiembre de 2008. No puedo comprobarlo en otros navegadores porque no tengo más instalados, pero si alguien lo hace, por favor, comenta aquí tu resultado ;)

Nota: en vuestros comentarios leo que también funciona sin problemas en Opera 9.62

Nota: la sintaxis utilizada en la línea e= (window.event)?event:e; se llama asignación abreviada. Si no las ha utilizado nunca, lee esta breve explicación que acabo de postear.

Ampliación 04-02-2009: onKeyUp

La semana pasada decubrí que se puede usar onKeyUp en lugar de onKeyPress, y ciertamente con mejores resultados. Voy a explicar brevemente la diferencia porque creo que a más de uno le va a interesar.


Obviamente ya sabemos todos los que hemos programado en otros lenguajes que contienen eventos que ambos son muy parecidos. Pero en concreto, me gustó más el resultado obtenido con onKeyUp porque detecta "mejor" el momento en el que los valores de la caja de texto cambian! He rehecho la página de ejemplo para que podáis probar la diferencia.


En donde se aprecia muy bien la diferencia es haciendo lo siguiente: escribimos algo de texto en la caja (probadlo en ambas cajas para ver la diferencia) y el texto se irá "copiando" automaticamente en una etiqueta span que tengamos debajo. Hasta aquí ambos eventos funcionan "aparentemente" igual: cada vez que escribimos una letra, se dispara el evento y replica el contenido de la caja en el span.

Sin embargo, una vez tengais escrito algo de texto, seleccionad parte del texto y pulsad una tecla cualquiera y veréis la diferencia entre ambos eventos: onKeyPress no actualiza el contenido del span, pero onKeyUp sí lo hace!. es decir, sí lo hace, pero solamente si luego seguimos pulsando más teclas, pero no lo hace inmediatamente :(



Jejeje, no me preguntéis el porqué ocurre eso, pero creo que nos es útil saberlo, verdad?! Yo lo descubrí proque estaba haciendo una especie de calculadora de precios: necesitaba que en el span saliera automaticamente el precio con IVA de un precio que yo introducía en un input, y necesitaba que funcionara sincronizadamente (como sucede usando onKeyUp).

Tuesday 26 August 2008

En PHP recuperar el ultimo ID de un INSERT MySQL

Programando en PHP, ¿alguna vez has necesitado saber el valor generado para un ID autoincremental después de una consulta tipo INSERT? ¿eres de los que -como yo- se ha complicado la vida haciendo una consulta SELECT para encontrar el id más alto en esa tabla o el max(ID)? Pues anota la siguiente instrucción ;)

Te pondré un simple ejemplo de 3 líneas, y verás qué sencillo: supongamos que tienes una tabla llamada 'mi_tabla1' que tiene un campo ID de tipo AUTO_INCREMENT, y necesitas insertar un registro y luego saber inmediatamente cuál es el ID que se ha generado para él, con tal de poder aprovecharlo en otras tablas.

Veamos esas 3 líneas de código:

mysql_query("INSERT mi_tabla1 SET `mi_campo`='mi_valor'");
$ultimo_ID = mysql_insert_id();
mysql_query("INSERT mi_tabla2 SET `id1`='".$ultimo_ID."'");


Breve explicación: en la primera línea insertamos un nuevo registro en la tabla 'mi_tabla1'. En la segunda línea recuperamos CON UNA SOLA INSTRUCCIÓN el último valor "autogenerado" (tiene que haber un campo AUTO_INCREMENT en esa tabla) por la última inserción realizada en la conexión MySQL establecida por el script en ejecución. En la tercera línea utilizamos ese valor para añadir un nuevo registro con ese ID asociado a un campo que esta vez no será AUTO_INCREMENT, pero que permitirá relacionar los registros de ambas tablas.

Cómo habréis notado, el quit de la cuestión está en la función de PHP mysql_insert_id().

Tuesday 19 February 2008

Cómo evitar que los buscadores indexen nuestras páginas seguras

¿Has incluido páginas SSL seguras en tu sitio web, y los buscadores han empezado a indexarte de nuevo todas tus páginas HTTP como HTTPS, cual duplicados? ¿Sabías que curiosamente eso puede penalizar la posición de tu web en los rankings de esos mismos buscadores?

Como este era mi caso, estuve buscando información para solucionarlo, y aquí os he traducido del inglés un articulo que detalla dos soluciones. El original podéis leerlo en www.seoworkers.com.


Muchos sitios web tienen páginas que utilizan SSL. Esto permite que el intercambio de información entre el servidor y el navegador del visitante suceda en una conexión encriptada, para garantizar la provacidad y la integridad de la misma.

Las URLs (direcciones) de páginas encriptadas con SSL comienzan con https en lugar de con http, para indicar que trabajan sobre un protocolo seguro.

El caso es que si las páginas seguras de tu sitio web han sido indexadas por los buscadores juntamente con el resto de páginas estandar, puedes experimentar serios problemas de canonicalización.


[NT: por ejemplo, que los buscadores consideren que tu página principal sea https://www.midominio.com antes que http://www.midominio.com -tal vez no conteniendo la misma información!!! O también -aún peor- puede que los buscadores interpreten que estás intentando "duplicar" el contenido de tu web con modos fraudulentos, y pueden penalizarte por ello!!! En cualquier caso, es perjudicial para la adecuada presencia de tu web en los buscadores.]

Estos problemas aparecen solo si tienes las páginas seguras dentro del mismo subdominio en el que tienes las páginas estandar.

En cambio, en el caso de que tus páginas seguras las tengas bajo un subdominio exclusivo [NT, por ejemplo: https://pagos.midominio.com] puedes fácilmente excluirlas de la indexación usando el archivo robots.txt en la raíz del directorio de ese subdominio.

En algunos casos solamente una página requiere el uso de SSL (como el formulario de contacto o de pagar). La opción más cómoda y habitual en esos casos es tener esa página siguiendo la estructura estandar del resto del sitio web. Cambiando solamente el "prefijo de protocolo" de la dirección de esa página (de http a https).


Sin embargo, esta técnica es la que nos puede llevar a los problemas de indexación en los buscadores que antes hemos comentado, puesto que los buscadores, si siguen los enlaces que salgan de esa única página SSL, son llevados a "duplicados" de las páginas estandar del sitio, pero con el prefijo https [NT: hay que recalcar aquí que para los buscadores la dirección http://www.midominio.com/servicios.htm es en principio diferente que https://www.midominio.com/servicios.htm, con lo cuál indexará las dos direcciones como páginas diferentes].

Esto sucede porque normalmente todos los enlaces internos dentro de un sitio web son enlaces relativos y por tanto heredan el protocolo y el dominio de la página en donde aparecen.En conclusión, Google -y posiblemente los otros buscadores- pueden considerar esta situación como un intento de "duplicación" de contenidos [NT: técnica que algunos desarrolladores de webs intentan de vez en cuando para engañar a los buscadores, y que por tanto está muy penalizado]. Y esto se traduciría en que los buscadores que quisiseran penalizarte rebajarían la posición de tu página en el ranking páginas en las búsquedas de los internautas.

Una vez indexadas, Google continuará visitando esas páginas seguras de tu sitio, a menos que las excluyas mediante el archivo robots.txt o con meta tags [NT: meta etiquetas] especiales en la cabecera de cada página.


Entonces, ¿cómo puedo evitar que Google visite esas páginas?

Si te encuentras en la posición descrita, te parecerá que no hay manera de solucionarlo fácilmente.

Hay una manera de que el archivo robots.txt redireccione las peticiones de páginas seguras a un segundo archivo que excluiría las páginas seguras a los programas de rastreo.

Para aplicar esta solución, sin embargo, debes usar el servidor Apache en tu hosting con el mod_rewrite activado [NT en inglés "enabled"].

Primero, deberías crear un segundo archivo robots.txt, llamándolo robots_ssl.txt (o el nombre que prefieras), asegurándote de que bloquea a los rastreadores de todos los buscadores. Súbelo a la raíz de tu dominio.

Para más información acerca del archivo robots.txt, qué es y cómo funciona, visita The web Robots Pages [NT: en habla hispana es recomendable WebRecursos - robots.txt].

Aquí tienes un ejemplo de este archivo:


User-agent: Googlebot
Disallow: /

User-agent: *
Disallow: /


Además, necesitarás añadir los siguientes comandos al archivo .htaccess que haya en la raíz de archivos de tu servidor [NT: root document folder]:

RewriteEngine on
Options +FollowSymlinks
RewriteCond %{SERVER_PORT} ^443$
RewriteRule ^robots.txt$ robots_ssl.txt

Resumidamente, este comando ordena al servidor web a dirigir cualquier petición para el archivo robots.txt que provenga del puerto 443 (usado para las conexiones SSL, en lugar del puerto 80 habitual para las conexiones web estandar) al segundo archivo que creamos, y que bloquea la indexación.

Para poder comprobar que está funcionando esta técnica, escribe la URL de tu archivo robots.txt en tu navegador para ver el comportamiento habitual del mismo para comandos estandar. Y luego prueba a escribir la misma URL pero con el prefijo de protocolo seguro (https) y deberías ver el contenido del segundo archivo, robots_ssl.txt.

¿Qué puedo hacer si no puedo utilizar mod_rewrite?

Si te es imposible activar mod_rewrite, ya sea porque no utilizas un servidor Apache, o porque no está habilitada esta función, todo lo anterior no te sirve de nada.

Si utilizas PHP para generar las páginas de tu site, puedes utilizarlo para comprobar si se está llamando a tu página mediante SSL, y en caso afirmativo puedes incluir un meta tag en la cabecera [NT: head] de tus documentos para desactivar la indexación por los buscadores.

El siguiente código, situado en cualquier parte de la cabecera de tu documento [NT: entre <head> y </head>] insertará el meta tag robots si el valor de la variable HTTPS del servidor está establecida a 'on':

1  <?php
2  
3       
if (isset($_SERVER['HTTPS']) 
4                 && 
strtolower($_SERVER['HTTPS'])=='on'){
5  
6       echo 
"\n<meta name='robots' content='noindex,nofollow'>";
7  
8       }
9  
10  
?>
Para verificar el funcionamiento correcto de este código, visita cualquier página en la que lo hayas incluido utilizando SSL (https://www.midominio.com/archivo.php). Y luego usa el comando ver codigo fuente de tu navegador para comprobar que el metatag aparece insertado en la cabecera del documento.


Enlaces de interés