<body>

Sitios web relacionados: PingBlog | Fotos

martes, noviembre 29, 2005

Seguridad a traves de obscuridad: El peor consejo

Les quiero mostrar el siguiente correo de una compañia de hospedaje de la cual no quiero dar muchos detalles:

Hello,

The following security alert is for anyone who uses a form mail script
on their web site. Form mail scripts are generally used to allow
browsers to submit an email from your website. This may include feedback
forms or contact forms. If you do not have any such feature on your
site, you may disregard this notice.

Recently we have seen a lot of exploit (hacker) activity on PHP and CGI
form mail scripts. The majority of exploited scripts are hand coded
form mail scripts. The exploits will use the form mail to automatically
send spam from the account. (An "exploit" is a term used for a piece
of code written by a malicious person to abuse a customer’s account.
This is not a server vulnerability but an issue specific to the coding
found in particular scripts.) The result of this is that we will receive
spam warnings from AOL, Spamcop and other reporting agencies. If we
receive too many complaints, our servers are at risk of being black
listed which will affect email on all servers.

It is very important to check your scripts to ensure they are secure.
At this time, the only form mail script we are recommending is the one
found here: http://nms-cgi.sourceforge.net/scripts.shtml. If you are
using a hand coded form mail script, it is highly recommended that you
change to the NMS form mail script.

Regardless of which form mail script you use, it is very important you
name it something random. Please DO NOT USE the following words when
naming your form mail scripts: form, mail, contact or feedback. People
exploiting these forms search for these commonly used words on search
engines to more easily identify vulnerable scripts.

We are currently scanning all servers to find scripts using those names
as well as replying to all spam complaints. If a script is found that
was exploited or has the potential to be exploited, the script will be
renamed. This may cause your script to stop functioning so it is
imperative you change your naming as soon as possible.

We apologize for the inconvenience but it is necessary to take swift
action in order to preserve the integrity of the servers so email is not
disrupted for anyone.
A ver niños, levanten la mano quienes vieron un par de cosas raras en el correo anterior. Ajá, si Jaimito, vamos a ver que es lo que huele mal aqui:
  • Recomendar una sola solución para envio de correo electrónico: Ahora ya se que script tengo que estudiar para poder reventar los servidores de este proveedor. No existe software perfecto y seguro este tiene fallas.
  • El nombre que le pongamos al script no tiene nada que ver; Sólo ponga un enlace desde su página web al script renombrado y listo, podemos usarlo de nuevo. La seguridad a traves de obscuridad no va a conseguir nada.
  • ¿No es mejor hacer responsable a los usuarios por sus metidas de pata? Si te hackean el servidor por software mal escrito, entonces la cuenta es suspendida hasta nuevo aviso. Si se envia correo con SPAM te multan, por instalar software de baja calidad. Me parece un intento heorico (y bastante nulo) el tratar de conseguir fallas de seguridad de todo el software que tienen los usuario y decidir en base a unas cuantas pruebas si es lo suficientemente seguro o no.
  • El proveedor podría evitarse este problema si tuvieran una "granja" para envio de correo electrónico. Aquellos que ralmente necesiten hacer envio masivo de correo entonces deben usar servidores especiales, de lo contrario la cantidad de correos enviados por minuto es drasticamente limitada. Los Spammers trabajan por escalas y el bajar el volumen afectaría sus margenes enormemente, además de que es más fácil de monitorear.
  • Prohiban la instalación de ciertos scripts. Admitalo, hay código de aficionados escrito en PHP que nunca debió ver la luz de el día. Si sabe que cierto script (de código gratuito) tiene una larga historia de problemas de seguridad entonces prohiba su uso.
Desgraciadamente el proveedor está siendo reactivo y no proactivo y estas medidas dudo que solucionen el problema a largo plazo. Quizas sería más efectivo que ellos suplieran los servicios de envio masivo de correos como una alternativa para aquellos que realmente lo necesitan.

¿Y usted, que opina?

Buscar en Technorati:

¿Porqué Quake no está escrito en Ruby, Perl? (Pero si en C++ y ahora en Java)



Por una sencilla razón: Son scripting languajes. Son ideales para hacer prototipos, hacer programas que necesitan ser modificados con cierta frecuencia. Pero como todas las cosas (sobre todo para los fanaticos de Ruby, Perl, Python) no esperen ver pronto a Ruby en telefonos celulares ni en juegos, ya que el lenguaje (como otros scripting languajes) no da para tanto (bueno, quizas para un juego de la la "vieja" o el "ahorcado").

Pero el punto interesante es que Java está mucho más seria como plataforma para juegos. Usando librerías nativas (las cuales están encapsuladas con el API de Sun) se hacen juegos que corren en celulares y computadoras de escritorio. Es también refrescante ver que Quake tiene nueva vida gracias a Java y que ahora cualquiera puede correrlo usando un Applet.

Oh, se me olvidaba, tampoco se puede hacer Quake con AJAX :D

Buscar en Technorati:

lunes, noviembre 28, 2005

¿Porqué Vi es el mejor editor de texto (general)?



Hablar de editores de texto y lenguajes de programación es como hablar de religión. En muchos casos es asunto de preferencia personal y en otros simplemente de fé y los milagros que han hecho en nosotros; Habiendo dicho esto, les quiero hablar de mi editor favorito y de como aún consigo cosas nuevas en él.

VI (Visual) es el mejor editor de texto que he utilizado hasta ahora. Si bien EMACS es muy bueno, yo lo prefiero porque:
  • No utiliza tanta memoria como Emacs (o Eclipse)
  • Está instalado EN TODOS los Unix que se consideren respetables
  • En el caso de VIM, es extensible y poderozo con soporte de edición para otros lenguajes
  • El dinero que usted invierta en VIM es destinado a una caridad.
  • Es lo suficientemente simple como para cargar en una emergencia. Trate de hacer eso con Eclipse, Emacs o Jedit :)
Piense en lo siguiente: Si usted es un desarrollador, y pasa mucho tiempo con sus herramientas, entonces ¿porqué no escogerlas bien? ¿porqué no volverse más diestro en estas?

En todos estos años trabajando como administrador de sistemas o programador, Vi ha estado bien adaptado para la tarea que se le ponga de frente. No es perfecto, pero es universal y lo mejor de todo: adaptable (Por otro lado, Emacs hace cosas que en Vi resultan mucho más dificiles, como intercambiar palabras de una columna a otra).

NOTA: Mi segunda opción es Eclipse. Es muy completo y para editar Java y trabajar con CVS es insuperable. Pero es mucho más lento de cargar que Vi.

Buscar en Technorati:

domingo, noviembre 27, 2005

Echando código: ¿Como hacer ping periodicamente?

Bueno, la forma más fácil es dejar que otros lo hagan por nosotros. Si usted tiene curl y alguna variante de UNIX (como Linux) podría tratar de hacer algo como lo siguiente:

   1:#!/bin/bash
2:#
3:# This script will call several ping services to notify when the site is updated.
4:#
5:# Author: josevnz@sourceforge.net
6:# License: LGPL
7:#
8:# Use 'ping-o-matic' to ping several blog indexers at the same time
9:#/usr/bin/curl 'http://pingomatic.com/ping/?title=KodeGeek&
blogurl=http%3A%2F%2Fkodegeek.com&chk_weblogscom=on&chk_blogs=on&amp;amp;amp;amp;amp;amp;
chk_technorati=on&chk_feedburner=on&chk_syndic8=on&chk_newsgator=on&chk_feedster=on&
chk_myyahoo=on&chk_pubsubcom=on&amp;chk_blogdigger=on&chk_blogrolling=on&
chk_blogstreet=on&
chk_moreover=on&chk_weblogalot=on&chk_icerocket=on'

10:# Use Technorati
11:/usr/bin/curl 'http://technorati.com/ping/http://kodegeek.com'

ACTUALIZACIÓN: Debo admitir que mi esfuerzo original fué bastante mediocre, así que con un poco más de esfuero decidí acomodar el script para hacer ping a más bitacoras, incluyendo a Veneblogs:

   1:#!/bin/bash
2:#
3:# This script will call several ping services to notify when the site is updated.
4:#
5:# Author: josevnz@sourceforge.net
6:# License: LGPL
7:#
8:
9:declare -r URL='http://kodegeek.com'
10:declare -r TITLE='KodeGeek'
11:declare -r SCRIPT=${0##*/}
12:
13:# Make sure we have a place to put our results
14:if [ ! -d $HOME/public_html/pings ]; then
15: mkdir -p $HOME/public_html/pings
16:fi
17:
18:# Put a plain index.html file if none is found
19:if [ ! -f $HOME/public_html/pings/index.html ]; then
20: echo '<html><head><title>KodeGeek<
/title></head><body
bgcolor="white"></body></html>'
21:
> $HOME/public_html/pings/index.html
22:fi
23:
24:function usage {
25:cat << EOF
26:$SCRIPT [-p|-t|-b|-n|-v]
27:Where:
28:
29:-p Use Ping-O-Matic
30:-t Use Technorati
31:-b Use Bitacoras.com
32:-n Use Bitacoras.net
33:-v Use Veneblogs (currently broken)
34:
35:NOTE: If you use Veneblogs, define your user and
password and environmental variables:
36:export VENEBLOGS_USERNAME=josevnz@kodegeek.com
37:export VENEBLOGS_PASSWORD=joserulez
38:
39:You can use all the flags if you want!
40:
41:Blog: KodeGeek - http://kodegeek.com
42:EOF
43:}
44:
45:if [ -z "$*" ]; then
46: usage
47: exit 192
48:fi
49:
50:while getopts "ptbnv" option; do
51: case $option in
52: p)
53: # Use 'ping-o-matic' to ping several blog indexers at the same time
54: /usr/bin/curl --show-error --user-agent 'Mozilla/4.0'
55:
--form "title=$TITLE" --form "blogurl=$URL" --form "chk_weblogscom=on"
--form "chk_blogs=on" --form "chk_feedburner=on" --form "chk_syndic8=on"
--form "chk_newsgator=on" --form "chk_feedster=on" --form "chk_myyahoo=on"
--form "chk_pubsubcom=on" --form "chk_blogdigger=on" --form "chk_blogrolling=on"
--form "chk_blogstreet=on" --form "chk_moreover=on" --form "chk_icerocket=on"
56:
-o $HOME/public_html/pings/pingomatic.com.html http://pingomatic.com/ping/
57: ;;
58: t)
59: # Use Technorati
60: /usr/bin/curl --user-agent 'Mozilla/4.0'
61:
-o $HOME/public_html/pings/technorati.com.html
'http://technorati.com/ping/'$URL
62: ;;
63: b)
64: # Use bitacoras.com
65: /usr/bin/curl --user-agent 'Mozilla/4.0'
66:
--referer http://bitacoras.com
67:
--form "weblog_name=$TITLE"
68: --form "weblog_url=$URL"
69:
--form "submit=Notificar actualización"
70:
-o $HOME/public_html/pings/bitacoras.com.html
71: http://bitacoras.com/directorio/ping.php
72: ;;
73: n)
74: # Use Bitacoras.net
75: /usr/bin/curl --user-agent 'Mozilla/4.0'
76:
--referer http://bitacoras.com
77:
--form "name=$TITLE"
78:
--form "url=$URL"
79:
--form "pnet=on"
80:
--form "escribe=1"
81:
-o $HOME/public_html/pings/bitacoras.net.html
82:
http://bitacoras.net/pingform/pingformulario.php
83: ;;
84: v)
85: # Use Veneblogs
86: if [ -z "$VENEBLOGS_USERNAME" ] || [ -z "$VENEBLOGS_PASSWORD" ]; then
87: printf "[ERROR]: Define VENEBLOGS_USERNAME and VENEBLOGS_PASSWORD\n"
88: else
89: /usr/bin/curl --user-agent 'Mozilla/4.0'
90:
--referer http://www.veneblogs.com/ping/pingmanual.php
91:
--form "name=login"
92: --form "username=$VENEBLOGS_USERNAME"
93:
--form "password=$VENEBLOGS_PASSWORD"
94: --form "operation=in"
95:
--form "submit= Enviar "
96:
-o $HOME/public_html/pings/veneblogs.com.html
97:
http://www.veneblogs.com/ping/prlogin.php
98: fi
99: ;;
100: *)
101: # Show the help
102: usage
103: exit 0
104: ;;
105: esac
106:done

El problema que tengo ahora es que Veneblogs es increiblemente ANAL a la hora de hacer pings (es el único directorio que pide usuario y clave. Ni siquiera Technorati lo hace). Los parametros de la forma no son el problema, así como no es suficiente pasarler el "referer", así que sospecho que hay una sesión involucrada (revicé los "cookies" pero no conseguí nada que me ayudara).

De esa manera les escribí a los chamos de VeneBlogs para ver que me decian al respecto:
Hola,

Estoy tratando de hacer una aplicación que haga pings a Veneblogs sin necesidad de utilizar un navegador, pero veneblogs simplemente no coopera; Pese a tener todos los campos correctos en una forma, usar post y usar el referer apropiado no logro hacer un ping.

Sospecho que necesito definir un cookie o una sesión apropiada y antes de sentarme a invertir mucho más tiempo en Veneblogs quería saber si hay alguna manera de hacer el proceso más amigable con scripts (como Technorati, Bitacoras.com, etc) o es que estoy haciendo algo definitivamente mal :)

Por cierto, gracias por el esfuerzo en mantener el sitio web.

Atentamente,

José Vicente Núñez Zuleta (KodeGeek.com)


¿Se le ocurre una manera más fácil?. Por cierto, el código está en CVS.

Buscar en Technorati:

sábado, noviembre 26, 2005

Echando código: Es Ruby más fácil de usar que Java para validar HTML?



Bueno, depende de lo que usted defina como fácil. Los invito a discutirlo en la Cara Obscura De El Software.

Buscar en Technorati:

viernes, noviembre 25, 2005

Opinión de juego: The Path Of Neo



Bueno, otro de mis escapismos: The Path Of Neo para XBOX. La trama es simple: Seguir los pasos de Neo, el elegido ("The One") es su lucha contra las máquinas.

Matrix: The Path Of Neo
Neo tiene upgrades. Eso significa mejores peleas y acrobacias


La pregunta que se debe estar haciendo es: ¿Vale la pena jugarlo, aún si no es un admirador de el juego?, Yo creo que si, por las siguientes razones:
  • Admitalo, si le dieran la oportunidad, ¿que caracter jugaría en The Matrix?
  • Los gráficos son bastante buenos, aunque el sonido no es excelente
  • Las acrobacias son bestiales. Todo está allí: Bullet Time, peleas con espadas, Wire-Fu, y armas, muchas armas...
Matrix: The Path Of Neo
There is no spoon...


El juego me entretuvo bastante y es muy fácil de aprender . Lo mejor es el final, ya que es un final alternativo al de la tercera y última pelicula de Matrix (sobre todo, la ironia de el final es lo que salva a este juego de ser un título repetitivo).

Mis unicas quejas:
  • Sonido mediocre en algunos niveles
  • No tiene modo de dos jugadores ni opción para Internet con otros jugadores (aunque debo admtir que sería bien dificil balancear las cosas)
Pero es un título sólido. Y si usted es fanatico de la saga entonces es algo que no debe dejar de tener :)

Matrix: The Path Of Neo
¿Les mencioné que habian peleas?


Y es que estos días, prefiero tomarme la pildora azul para entretenerme un rato :)


Buscar en Technorati:

jueves, noviembre 24, 2005

Hoy es Thanks Giving

Thanks giving parade
Thanks Giving Day


Si, hoy dejo de pensar en corporate actions, OTC's, monitoreo de sistemas, darle soporte a los traders neuroticos y en vez de eso juego con mi viejo XBOX, comeré pavo hasta reventar y la pasaré tranquilo con mi esposa y amigos.

Ahhh, micro vacaciones, como las necesitaba después de 3 semanas realmente fuertes :D

Buscar en Technorati:

¿Criptografía para todos?: La solución de el arquitecto

Aún no hemos encontrado una forma segura y fácil de enviar información sensitiva por medio de el correo electrónico. Si bien PGP es fácil de usar, hay que admitir que es intimidante al principio y que requiere leer un poco para entender como funciona.

¿Porqué les hablo de todo esto?

XXX (Un arquitecto, miembro de la familia) decidió que podríamos ayudarlo con el hospedaje de su sitio web y nos envio la información y clave de su cuenta. Vero le advirtió que enviar eso sin ningún tipo de protección no era buena idea, y de la noche a la mañana el personaje de esta historia vino con lo siguiente:

Vero:

Creo que vas a tener que leerte "El hombre que
calculaba" para poder resolver el misterio....
el customer #= (27 x CI Maya) + ( 7426 x la edad que
josé dice que tiene en el angel negro)
el password #= customer # - {( El # apto. de Maya en
Conanza x el # apto. nuevo en San José) + cantidad de
dias de un año}.

Si se te olvidaron las matemáticas, llámame y te digo
el número.


XXX
Muy ingenioso, lo cual pone en evidencia que siempre hay más de una manera de resolver un problema (o de freir un pescado).

¿Y usted, qué trucos ha utilizado para enviar información sensitiva por correo electrónico?

Buscar en Technorati:

miércoles, noviembre 23, 2005

Echando código: Cuando optimizamos y la defecamos...



Uno de los primeros programas que hice para la compañia en la que trabajo actualmente es un script en Perl que valida los contenidos de un archivo de texto. El archivo gobierna como se comportan instancias de al menos 500+ programas en Java, los cuales generan cientos de miles de calculos por segundo. El script nació para evitar que errores de configuración volvieran sopa al sistema, el cual por decirlo de alguna manera es bastante sensible.

Aprendiendo de experiencias pasadas, evité optimizar al principio, concentrandome en que el programa corriera bien; Poco a poco (y al ver que el sistema de verdad atabaja metidas de pata) los compañeros de el grupo decidieron que yo le agregara más pruebas, mientras que al mismo tiempo el script crecia y crecia hasta que de ejecutarse en 10 segundos pasó a 4 minutos.

¡Hora de optimizar! dije yo. Como el programa verifica un archivo de texto y este no es muy grande, decidí cargarlo todo en memoria. Para acelerar las pruebas, entonces decidí paralelizarlo utilizando "Perl Threads" y que cada una de ellas ejecutara sus pruebas en un pedazo de el archivo. Solamente algunas de ellas requerian procesar el archivo completo (como buscando duplicados) pero la mayoría eran independientes.

Ni corto ni perezoso lo parelicé; ¡De 4 minutos bajo a 30 segundos!. Emocionado, me disponía a publicarlo y se me ocurrió hacer una prueba más formal, con algunos casos obscuros. Para mi sopresa, el código sufria de condiciones de carrera, las pruebas no eran confiables y el código ahora era más complejo.

Que ladilla; Y justo cuando estaba a punto de ponerme a depurar el script algo me pegó en la cabeza:

¿Tu ya revizaste en donde pasa la mayor parte de el tiempo el programa?

No, no se me habia ocurrido hacerle un "profiling" a mi script. Recordando como hacerlo en Perl, encontré que el script pasaba %30 de el tiempo en dos rutinas, una de ellas la cual utilizaba la red para bajarse datos y la otra que buscaba el mismo valor una y otra vez.

El problema lo resolví utilizando un arreglo asociativo (Hash) para guardar valores de ambas pruebas (en hash distintos claro) y el tiempo bajó de 4 minutos a 6 segundos. Y lo mejor, el código es aún simple, sin threads.

Por supuesto no descarto usar threads en el futuro, pero por ahora 6 segundos es un tiempo bastante razonable. La moral de la historía es obvia, no empieces a optimizar sin saber que es lo que se puede mejorar (si suena obvio, pero más de una ves esto pasa cuando nos sentamos a programar sin planear un poquito).

Buscar en Technorati:

lunes, noviembre 21, 2005

Cambiando la forma de pensar: Los mejores regalos son los inesperados

Hace unas dos semanas tuve el placer de tomarme unas cervezas con Sebastian; Después de un día de trabajo terrible, necesitaba subir los animos y como siempre el pana Seba trajo ideas interesantes a la mesa. Una de ellas fué un regalo, el libro "The Pragmatic Programmer" el cual yo ya habia hojeado con anterioridad (sólo unos pedazos).

Debo admitir que estaba un poco "reacio" a leer el libro, ya que no estaba seguro si este iba a aportarme algo útil, además de que mi tiempo está ya bastante estirado entre las 1000 cosas que tengo que hacer.

Que equivocado estaba; Si bien aún no lo he terminado de leer, el libro está lleno de consejos útiles los cuales espero poder aplicar dentro de poco, todos ellos escritos en un lenguaje sencillo y con ejemplos concretos.

Aunque el libro tiene un sitio web con libros con algunos titulos con nombres que no inspiran mucha confianza (como "mi trabajo se fué a la India") debo decir que hasta ahora va por buen camino.

Así que las gracias a Sebastian. Por cierto, me encargaré de darselo a dos personas más las cuales seguro lo apreciaran bastante.


Buscar en Technorati:

domingo, noviembre 20, 2005

Opinión de pelicula: Harry Potter and the Goblet of Fire



Este Sabado logramos ver Harry Potter and The Goblet Of Fire (la mejor pelicula de la serie hasta la fecha). Como yo ya he repetido más de una vez en este blog, yo soy del %1 que no ha leido los libros todavía (aunque debo admitir públicamente que estoy cambiando de opinión).

Pero en fin, hablemos de la pelicula...

Los efectos especiales y el vestuario es de primera; Cada uno de ellos es increiblemente detallado y bien logrado, y está allí para soportar la historia, no porqué si.

Sus personajes han evolucionado junto con la historia y las actuaciones son bien convincentes. La película mantiene un buen balance de humor y temor, algo que ya había caracterizado a la anterior, aunque está es mucho más violenta (sin llegar a ser desagradable).

¿Y como reaccionó la gente? Nosotros no la vimos el día de el estreno (Viernes 18) sino el día después y sin embargo sólo logramos conseguir entradas para las 9:00 PM. El teatro estaba lleno de gente como siempre, la mayoría de ellos niños acompañados de sus padres.

Y pensar que aún faltan 2 peliculas, y el libro final de este fenonemo...

Buscar en Technorati:

Las 10 cosas que la tecnología prometió y mintió

Siempre que leo los avisos de que una compañia de tecnología se vuelve pública con un IPO o cuando me llega correo con SPAM prometiendome como van a cambiar mi vida porque me gané el loto en un país pobre de Africa me pregunto, que tantas cosas ha dejado de hacer esta que prometió hace tiempo. Así que decidi sacar una lista de las 10 cosas que debieron y aún no están listas:

  • Computación más segura: Virus en celulares, Windows es destrozado al menos una vez al mes por un virus que sale en Internet, ningún navegador es seguro (Firefox y Explorer comparten problemas de seguridad serios). Compañias de música como Sony introducen software para controlar como utilizamos sus productos y los hackers abusan el truco. Linux aún sufre de el problema clásico de "buffer overrun" y la lista no para aquí. Lo peor, el software es tan complejo hoy en día y es manejado por espectativas tan irrealistas que seguirá así por un buen tiempo.
  • Programas sin errores: Tenemos programación orientada a objetos, tenemos sistemas distribuidos pero aún no podemos hacer software sin errores. Las herramientas de depuración y desarrollo en lenguajes interpretados como Perl, Python y Ruby simplemente son mediocres, aún hay errores en la máquina virtual de SUN, por poner ejemplos de donde los esfuerzos se han quedado cortos.
  • Internet para todos: Eso es mentira. Si bien ha habido cierta democratización en como utilizamos Internet, aún estamos muy lejos de decir que es democratica (por ejemplo los Estados Unidos es quien controla el manejo de DNS) y no es para todos (los paises desarollados han visto un desarrollo en el uso de Internet, pero otros sitios como Africa no tienen el suficiente poder adquisitivo como para hacer esto posible). La brecha entre ricos y pobres es aún mas evidente con el uso de Internet.
  • Clientes web más ricos: AJAX, Flash, Applets, la lista de intentos por llevar la experiencia del escritorio al web es larga. Todas estas tecnologías han atacado el problema con algo de exito pero todas tienen limitaciones y aún hacen que esta promesa siga siendo una fantasía.
  • Dispositivos móbiles eficientes: Tengo camara, grabadora, juegos pero no tengo una vida de batería que me permita utilizar mi dispositivo por más tiempo, como siempre hay problemas de cobertura, tengo virus en mi telefono y para rematar me envian SPAM todo el tiempo. En vez de perder el tiempo en agregarle más accesorios a mi celular, porqué no lo hacen más útil, y hacen que la bateria dure más tiempo?
  • Correo electronico es inútil: SPAM y virus se encargaron de matar a la aplicación #1 de Internet. El correo electrónico no ha evolucionado con los cambios requeridos para mantenerlo como una herramienta útil. Pese al ejercito de personas que vigilan que no llegue SPAM a mi cuenta de correo, y pese a todas las tecnologías aún estamos donde empezamos y peor. La mayoría de el correo que recibo es basura, y la situación no pareciera que vaya a mejorar en el futuro.
  • IPv6: Si, ya todos sabemos que IPv4 tienen deficiencias y que el espacio de direcciones se esta acabando. Pero y en ¿donde está IPv6 con su seguridad y la promesa de un espacio ampliado de direcciones? Tiene muchos desafios por delante y la migración promete ser dolorosa.
  • Javascript para todos: Mucha gente grita AJAX, pero Javascript aún no es %100 compatible entre navegadores. Cualquiera que se haya dedicado un poco a trabajar con DHTML sabe de lo que hablo. Y no me vengan con la excusa de que un programador competente puede resolver creativamente esos problemas, ya que si bien eso es cierto es también aceptar que podemos trabajar con herramientas defectuosas y eso está bien (cuando lo qu debería hacerse es resolver el problema al negocio).
  • Perl 6: Llevan años hablando de la nueva versión de Perl, pero simplemente no llega. ¿Será que algún dia la tendremos, o será que el futuro es simplemente cualquier otro lenguaje de scripting?
  • Buscadores %100 completos para la web. Contrariamente a lo que usted pueda pensar, Internet aún es un sitio que tiene lugares invisibles. La Web no es Internet y mucho antes de que esta viniera, existian herramientas como la USENET, Archive, Gopher. Las cosas no han mejorado mucho, y falta un buen tiempo para que la información este completamente al alcance de sus manos.
Le aseguro que la lista podría seguir creciendo. ¿cuales cree usted que deberían ser agregados y porqué?

Tópico largo, pero después de una semana de trabajo agitada no pude dejar de pensar en estos problemas al menos más de una vez.

Buscar en Technorati:

domingo, noviembre 13, 2005

Echando código: Borrón y cuenta nueva


Estoy trabajando (de puro ocio dominical) en un pequeño script que se baja los datos de un par de sitios en Internet, los cuales (grátis) te hacen la correspondencia entre direcciones IP y un pais (con latitud y longitud). Así que sin pensar mucho me senté a escribir y al final terminé haciendo un script en Bash que hacia todo, con ayuda de muchas herramientas que ya vienen instaladas bajo Linux:

   1:#!/bin/bash
2:
3:# This script does the following tasks for the Yahoo log mapping:
4:# - Download the data from several sources on the Internet
5:# - Performs basic cleanup to allow the data import
6:# - Imports the data
7:
8:declare -r SCRIPT="${0##*/}"
9:declare -r DATA="$HOME/data"
10:declare -r GEO_FILE="country.db"
11:declare -r GEO_URL="http://ip.ludost.net/raw/${GEO_FILE}.gz"
12:declare -r ASLATLONG_FILE="aslatlong.txt"
13:declare -r ASLATLONG_URL="http://netgeo.caida.org/$ASLATLONG_FILE"
14:declare -r DATABASE="kodeg2_kodegeek"
15:declare -r USER="kodeg2_rw"
16:
17:if [ ! -d "$DATA" ]; then
18: /bin/mkdir "$DATA"
19: if [ $? != 0 ]; then
20: printf "Unable to create %s\n" "$DATA"
21: fi
22:fi
23:
24:function cleanup {
25: test -f "$DATA/$GEO_FILE" && /bin/rm -f "$DATA/$GEO_FILE"
26: test -f "$DATA/$ASLATLONG_FILE" && /bin/rm -f "$DATA/$ASLATLONG_FILE"
27:}
28:#declare trap cleanup exit
29:
30:# Download and unpack the files
31:cleanup
32:
33:cd $DATA
34:if [ $? != 0 ]; then
35: exit 192
36:fi
37:
38:/usr/bin/wget -nv $ASLATLONG_URL
39:if [ $? != 0 ]; then
40: exit 192
41:else
42: # Remove the comments from the original file
43: egrep -v "^#" $ASLATLONG_FILE > ${ASLATLONG_FILE}.$$ &&
44:
mv ${ASLATLONG_FILE}.$$ $ASLATLONG_FILE &&
45: /bin/chmod a+r $DATA/$ASLATLONG_FILE
46: if [ $? != 0 ]; then
47: exit 193
48: fi
49:fi
50:
51:# A IP address can be mapped up to 6 countries.
52:# The file is not properly escaped, fix the first delimiters
53:/usr/bin/wget -nv $GEO_URL &&
54:/usr/bin/gunzip -f "$DATA/${GEO_FILE}.gz" &&
55:perl -p -i -e's# #\t#' "$DATA/${GEO_FILE}.gz" &&
56:
perl -p -i -e's# #\t#' "$DATA/${GEO_FILE}.gz"
57:/bin/chmod a+r $DATA/${GEO_FILE}
58:if [ $? != 0 ]; then
59: exit 192
60:fi
61:
62:# Import the files into the database
63:cat <<EOF > $DATA/${SCRIPT}.sql
64:truncate table geo_ip;
65:\\copy geo_ip FROM '$DATA/$GEO_FILE' DELIMITERS ' '
66:truncate table aslatlong;
67:\\copy aslatlong FROM '$DATA/$ASLATLONG_FILE' DELIMITERS '\t'
68:EOF
69:if [ $? != 0 ]; then
70: exit 192
71:fi
72:
73:#psql $DATABASE -U $USER < $DATA/${SCRIPT}.sql
74:if [ $? != 0 ]; then
75: exit 192
76:fi
Y fué aqui en donde me pegó de frente: ¿Que hacia yo llamando a Perl varias veces dentro de el código, para acomodar al archivo antes de cargarlo? Lo peor fué que me di cuenta justo cuando un caso especial para procesar ciertas lineas de uno de los archivos fué requerido (un "perl one liner") simplemente no podía.

OK, sientate un poco. ¿Lo hago en Java? No, el formato puede cambiar y no me quiero ver compilando el parser, además de que no quiero meterme con las clases java.net.URL ni lidiar com compresión en streams. En pocas palabras quería un hack, algo rápido para poder dedicarme a la parte de el problema que realmente me interesa. Perl es fácil de usar, muy bueno manipulando texto así que ¿porqué no?:

   1:#!/usr/bin/perl
2:
3:use strict;
4:use LWP::UserAgent;
5:use threads;
6:use threads::shared;
7:
8:use constant DATA => "$ENV{HOME}/data";
9:use constant GEO_FILE => "country.db";
10:use constant GEO_URL => "http://ip.ludost.net/raw/" . GEO_FILE . ".gz";
11:use constant GEO_PARSED_FILE => DATA . "/country.db";
12:use constant ASLATLONG_FILE => "aslatlong.txt";
13:use constant ASLATLONG_URL => "http://netgeo.caida.org/" . ASLATLONG_FILE;
14:use constant ASLATLONG_PARSED_FILE => DATA . "/aslatlong_parsed.txt";
15:
16:if ( ! -d DATA ) {
17: printf "%s\n", DATA;
18: mkdir DATA;
19:}
20:
21:my (@downloadThreads, @parseThreads);
22:
23:# Set the callbacks. Order is important
24:my @parseCallbacks = (\&parseGeoFile, \&parseASFile);
25:# Set the files. Order is important
26:my @files = (DATA . "/" . GEO_FILE . ".gz", DATA . "/" . ASLATLONG_FILE);
27:# Set the URL. Order is important
28:my @url = (GEO_URL, ASLATLONG_URL);
29:
30:for (my $idx=0; $idx < scalar(@url); $idx++) {
31: $downloadThreads[$idx] = threads->new(
32: \&getURL,
33: $url[$idx],
34: $files[$idx]);
35:}
36:
37:for (my $idx=0; $idx < scalar(@downloadThreads); $idx++) {
38: my $result = $downloadThreads[$idx]->join();
39: if (! (($result eq "304 Not Modified") || ($result eq "200 OK")) ) {
40: printf "[ERROR]: Downloading one of the files, %s, %s",
41: $downloadThreads[$idx]->tid(), $result;
42: exit 192;
43: }
44: $parseThreads[$idx] = threads->new(\&{$parseCallbacks[$idx]}, $files[$idx]);
45:}
46:
47:for (my $idx=0; $idx < scalar(@parseThreads); $idx++) {
48: my $result = $parseThreads[$idx]->join();
49:}
50:
51:
52:# Download the file from the desired URL
53:sub getURL {
54: my ($url, $file) = @_;
55: printf "[INFO]: Downloading %s -> %s\n", $url, $file;
56: my $ua = LWP::UserAgent->new(
57: agent => "kodeGeek/GeoData 1.0",
58: from => 'josevnz@kodegeek.com'
59: );
60: my $response = $ua->mirror($url, $file);
61: return $response->status_line;
62:}
63:
64:# Parse the GeoFile
65:sub parseGeoFile {
66: my $file = $_[0];
67: printf "[INFO]: Parsing GeoFile %s -> %s\n",
68: $file, GEO_PARSED_FILE;
69: open(INPUT_FILE, "/bin/zcat $file |") || die "$!";
#
Not portable, but who cares!
70: open(PARSED_FILE, "> " . GEO_PARSED_FILE) || die "$!";
71: while(<INPUT_FILE>) {
72: chomp($_);
73: my @tokens = split(' ', $_);
74: # Fix the separator and make the countries
appear
as a single token
75: printf PARSED_FILE "%s\t%s\t%s\n",
76: shift @tokens, shift @tokens, join(' ', @tokens);
77: }
78: close(INPUT_FILE);
79: close(PARSED_FILE);
80:}
81:
82:# Parse the AS file
83:sub parseASFile {
84: my $file = $_[0];
85: printf "[INFO]: Parsing ASFile %s ->%s\n",
86: $file, ASLATLONG_PARSED_FILE;
87: open(PARSED_FILE, "> " . ASLATLONG_PARSED_FILE) || die "$!";
88: open(INPUT_FILE, "$file") ||