lunes, 12 de diciembre de 2011

Redimensionando y rotando fotos desde la línea de comandos

Estamos renovando la pagina de la academia, y hay muchas fotos para publicar. El script tipo galeria donde se van mostrando mostrando las fotos ya está listo (utilizaron jquery y el easySlider).

Ahora solo falta homogenizar las fotos, que tengan el mismo tamaño y que no salgan giradas.

Para la orientación correcta podemos usar exiftran, esto si la camara almacenó la información de como se tomo la fotografía en los datos exif. En caso de no haberla almacenado, podemos utilizar algún software como eog para ver las fotos y girarlas de manera manual, al girarlas en este software, las fotos no se modifican, solo se modifica la etiqueta exif :)
exiftran -ai *
es la instrución que revisa todos los archivos de la carpeta, en este caso las fotos y si la orientación no es la adecuada las rota realmente y actualiza la etiqueta.

Como las fotos son de diferentes fuentes y diferentes cámaras, pues los tamaños varian mucho. Una vez rotadas las fotos necesitamos ajustar la altura de todas las fotos para que se vean continuas en el script. Para esto usaremos de imagemagick una utilidad que se llama mogrify.
mogrify -resize x400 *
esta instrucción fija la altura en todas fotos existentes en el directorio, y ahora si estan listas para ser usadas por el script.

La lista de fotos se genera en orden aleatorio, así que cada vez que visiten la página se vera diferente.

Como son muchas fotos, esta limitada a 25 por visita, así que si quieren ver más, refrequen la página :)

Otra situación con los archivos provenientes de diferentes camaras es que pueden repetirse los nombres de las fotos ya que todos están en la misma carpeta para que funcione el script. Así que para renombrarlos podemos utilizar el comando rename. En este caso tenemos carpetas que se llaman fotos01 hasta fotos09, y en lugar de buscar si hay nombres repetidos, modificamos los nombres de las fotos de todas las carpetas en una sola linea:


for a in $(seq 1 9); do cd fotos0$a ; rename "s//0$a/" *JPG; cd .. ; done




martes, 25 de octubre de 2011

Recuperando fotografias de un disco duro

Esta entrada es sobre recuperación de archivos de un disco duro, lo especial es que lo que se intenta recuperar son especialmente fotografías.

Así que típico y como estarán pensando conectamos el disco y lanzamos el photorec para recuperar todo, el cuestión es que queremos las fotografías y el disco duro es de 400 Gigas. Así que configuramos el photorec para que solamente nos recupera archivos jpg, en este caso las fotografias fueron guardadas durante varios años directamente de la camara.

Aún así, terminamos con muchisimos archivos recuperados y en diferentes carpetas donde fueron guardados. (Fueron 61 carpetas, casi 20 Gigas y casi 22 mil archivos). Para clasificar esto a mano pues puede llevar bastante tiempo, aquí es donde entra lo interesante de conocer el formato.

Al ser archivos de fotografías digitales, la cámara agrega datos EXIF al archivo, estos datos van desde la cámara que tomo la fotografía, características como distancia enfoque, tiempo de exposición, incluso algunas cámaras incluyen latitud y longitud para georeferenciar las fotos. Pero lo más importante ahora es la fecha.

Así que sabiendo esto, con un programa en python que lea los datos exif de los archivos, podremos discriminar los archivos y seleccionar solamente los que tengan estos datos, y renombrarlos por la fecha, en caso de no tener la fecha o que por alguna razón las fechas coincidan, pues dejamos el nombre original con el que fueron recuperadas.

Y de esta manera recuperamos 16 mil fotos, de casi 10 años.

A continuación el programa en python:


import exif
import shutil


lista = open("fotos1.jpg.txt","r").read().split("\n")

listafotos=[]

for item in lista:
print item
try:
data=exif.get_exif(item)
except:
data="NULL"

if data!="NULL":

try:
fecha=data['DateTime']
except:
fecha=item.split("/")[2]
if fecha[-1] == '\x00':
fecha = fecha[:-1]
if fecha not in listafotos:
listafotos.append(fecha)
else:
fecha=fecha+"-"+item.split("/")[2]
shutil.copy(item,"./Tusfotos/"+fecha)






y también la librería :




from PIL import Image
from PIL.ExifTags import TAGS

def get_exif(fn):
ret={}
i = Image.open(fn)
info = i._getexif()
for tag,value in info.items():
decoded = TAGS.get(tag, tag)
ret[decoded]=value
return ret

jueves, 11 de agosto de 2011

Asegurar código PHP heredado.

Estoy revisando una aplicación en PHP, ya hace lo que debe hacer, ya está en español, tiene las modificaciones necesarias .... ahora falta asegurarla.

Creo que al menos 2 procesos básicos son los necesarios, protegerla de SQLi y de RFI. (inyección de código SQL e Inclusión de archivos remotos).

Para el primer punto, hay que "limpiar" las entradas que recibe la aplicación del usuario, considerando que los usuarios pueden ser hostiles.

se me ocurren 2 cosas addslashes y mysql_real_escape_string, las cuales escapan los caracteres ' " NULL y les antepone \ y puede servir para almacenar contraseñas del tipo ' or ''=''

Al parecer la más recomendada es mysql_rel_escape_string, solo que debes tener un enlace a la base de datos, porque el trabajo lo hace el mysql.

La verdad preferiría poder utilizar algún patron de diseño que me protegiera del SQLi, pero sería reescribir casi toda la aplicación. así que mejor utilizaré el escape.

vienen unas lines que podrían ser muy útiles y rápidas de implementar :

$_GET = array_map('mysql_real_escape_string', $_GET);
$_POST = array_map('mysql_real_escape_string', $_POST);
$_COOKIE = array_map('mysql_real_escape_string', $_COOKIE);
$_REQUEST = array_map('mysql_real_escape_string', $_REQUEST);
En esta presentación sobre SQLi también recomiendan utilizar procedimientos almacenados.

Otro punto muy IMPORTANTE de la presentación:
Filtra/valida las entradas escapa las salidas.

Para escapar las salidas, puedes utilizar htmlentities, a menos que permitas HTML almacenado o como parámetros, de otra forma, puedes evitar también ataques XSS.

Estas recomendaciones también se muestran acá. Donde es todo un lista de cotejación para ver si tu aplicación está asegurada.

Por último, no dejes sola la aplicación, revísala constantemente junto con sus logs. Tal vez alguién ya metió gol y tu todavía no sabes.



martes, 9 de agosto de 2011

Usar el navegador de forma "Anónima"

El título puede ser algo confuso con lo que quiero compartir, pero intentaré comenzar a explicarlo con un ejemplo.

Estoy navegando, tengo varios sitios abiertos, algunos de los cuales te dan seguimiento como google por ejemplo, o bing. Y si tengo activa mi cuenta y abro otra pagina del buscador, sabe quien soy y que estoy buscando.

Los navegadores tienen una opción de navegar de incógnito, donde "se supone" no dejas rastro en la PC en la que estás. Pero aún cuando abres una ventana o pestaña en este modo, si ingresas al buscador, sigue leyendo tus preferencias, tus cookies etc. etc. Así que te sigue reconociendo.

Existe la teoría que te pueden identificar plenamente por las cadenas del navegador, cookies y esas cosas, así que buscando una forma de que esto no sea tan sencillo progongo lo siguiente (que es lo estoy usando actualmente):

Utilizar las opciones de chromium-browser específicamente para tratar de resolver la situación de una navegación un poco mas PRIVADA.

hugo@Atenea:~/Escritorio$ chromium-browser --user-data-dir=/tmp/otra --temp-profile --incognito --user-agent="Mozilla/5.0(iPad; U; iPhone OS 3_2; en-us) AppleWebKit/531.21.10 Mobile/7B314" http://www.google.com

--user-data-dir sirve para decirle donde se almacenará la información de usuario del navegador, de esta forma no lee las cookies que ya tengas, y puedes seguir con sesiones abiertas en otras ventanas del navegador.
--temp-profile para que sea perfil temporal
--incognito modo incognito o privado
--user-agent identifica al navegador, con la cadena de ejemplo simula ser un iPad.

Así navego de manera tradicional y de manera privada al mismo tiempo.

miércoles, 27 de abril de 2011

Conectar Java con bases de datos (derby y mysql)

Del libro de Deitel vienen varios ejemplos de como hacerlo (conectar java con mysql o con derby), pero en la práctica esto puede resultar no tan evidente.

Voy a basar esta entrada en el tema 25.10 del libr de Como programar en Java (7a. edición) de Deitel & Deitel.

En linux debemos tener instalados los siguientes paquetes: (esos son los que tengo en mi sistema)

sun-java6-bin
sun-java6-jdk
sun-java6-jre
sun-java6-javadb --> este nos instala el derby.
libmysql-java
mysql-server-5.1
mysql-server-core-5.1

Sin modificar nada de los codigos que vienen en el CDROM, puedes crear la base de datos con el comando "ij", todo compila muy bien, pero al ejecutarlo marca errores, de que no sabe nada del conector sql ..

java.sql.SQLException: No suitable driver found for jdbc:derby:LibretaDirecciones
at java.sql.DriverManager.getConnection(DriverManager.java:602)
at java.sql.DriverManager.getConnection(DriverManager.java:185)
at ConsultasPersona.(ConsultasPersona.java:29)
at MostrarLibretaDirecciones.(MostrarLibretaDirecciones.java:59)
at MostrarLibretaDirecciones.main(MostrarLibretaDirecciones.java:357)

para corregir este error ejecutamos :
java -cp /usr/lib/jvm/java-6-sun/db/lib/derby.jar:/usr/lib/jvm/java-6-sun/db/lib/derbytools.jar:. MostrarLibretaDirecciones

y con esto funciona perfectamente.

Para el caso de hacerlo funcionar con MySQL, hay que modificar unas cuantas lineas:

En el archivo direccion.sql
linea 5: IDDireccion INT NOT NULL AUTO_INCREMENT,
agregamos la linea 10: key(IDDireccion)

Luego de esto creamos la base de datos y asignamos permisos a los usuarios, y ejecutamos el codigo sql sobre la base de datos.

En el código del archivo ConsultaPersona.java, modificamos 2 lineas:

linea 14: private static final String URL = "jdbc:mysql://localhost/LibretaDirecciones";
cambiamos el controlador de derby a mysql.

linea 29: DriverManager.getConnection( URL+"?user="+NOMBREUSUARIO+"&password="+CONTRASENIA );
el parametro que se le pasa es un poco diferente, tiene forma de url para agregarle el user / password al manejador.

compilamos todo con javac *java.

para ejecutarlo :

java -cp /usr/share/java/mysql-connector-java.jar:. MostrarLibretaDirecciones

y con eso podemos tener la aplicación funcionando.