2012-03-09

Jugando con el name mangling en python

No tiene sentido, pero a veces se puede cambiar el comportamiento de los objetos cambiando los nombres de las clases pero sin mencionar su nombre en el código, jugando con la forma cabeza de hacer name-mangling de los atributos privados:

$ python
Python 2.7.2+ (default, Oct 4 2011, 20:03:08)
[GCC 4.6.1] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> class A(object):
... def __init__(self): self.__sarlanga = 1
... def s(self): return self.__sarlanga
...
>>> B = A
>>> B

>>> class A(B):
... def __init__(self):
... B.__init__(self)
... self.__sarlanga = 2
...
>>> aa = A()
>>> aa.s()
2
>>> class C(B):
... def __init__(self):
... B.__init__(self)
... self.__sarlanga = 3
...
>>> c = C()
>>> c.s()
1

Happy hacking,
Aure.

2012-03-02

Derechos y deberes de padres y madres separados

Como muchos de ustedes saben, soy padre y estoy divorciado. Eso hizo que me preocupe por encontrar cuál es la forma éticamente correcta de manejar un montón de situaciones bastante complicadas, y estoy buscando un marco moral que me permita tomar decisiones correctas y justas.

Sé que "correcto" y "justo" son palabras complicadas, así que estoy tratando de tener una guía para mi mismo, que me permita evaluar si mis acciones, y las de mi ex, son justas y correctas.
Esto es lo que tengo hasta ahora:
  • Tanto la madre como el padre son igualmente responsables por el bienestar de sus hijos
  • Los gastos y esfuerzos necesarios para asegurar su bienestar deben ser equitativos.
  • Ninguno de los dos es responsable por el bienestar del otro.
  • Cada uno es responsable por la manutención de sí mismo, sin derecho a reclamar por gastos que son propios de cada uno a la otra parte.
  • La riqueza generada por ambos mientras fueron una pareja debe ser repartida equitativamente.
  • La riqueza generada por ambos antes de formar nuestra pareja o después de romperla es exclusivamente de cada uno de uno, y cada uno tiene potestad exclusiva sobre ella.
Espero comentarios. Me interesan especialmente aquellos de madres separadas (incluyendo divorciadas).

2012-02-09

Obteniendo las VMWare tools para usarlas con VMWare Player 4.0.2

Estoy usando VMWare Player 4.0.2 en un Linux Mint de 64 bits y quiero instalar las VMWare Tools en los guests que vaya haciendo. El problema es que VMWare Player no viene con los tools y la opción del menú para instalar las tools no anda :(.

Workarround:

  • Bajar el bundle de VMWare Workstation (en mi caso, se llama: VMware-Workstation-Full-8.0.2-591240.x86_64.bundle)
  • Extraerlo en un directorio. Para eso ejecuté: /usr/lib/vmware-installer/2.0/vmware-installer --install-bundle VMware-Workstation-Full-8.0.2-591240.x86_64.bundle --extract /tmp/vmware
  • Ejecutando find /tmp/vmware -name "*.iso" podés ver los ISOs de todos los sistemas operativos. Para instalarlos, montalos como CD en la VM correspondiente.

Happy hacking!

Fuente: http://brandonhutchinson.com/Installing_VMware_Tools_with_VMware_Player.html

2012-01-26

2012-01-14

¿En qué pensar cuándo bailamos tango?

Algo que es muy común cuando uno lleva a una principiante es que "baile sola". O sea, que da pasos que no son marcados. ¿Por qué? Creo que es el miedo al vacío, a que había que hacer algo en ese compás y el paso que le enseñaron era ése.
Poder esperar hasta el siguiente paso, manteniendo el equilibrio, no es fácil. Y a mi me gusta mucho hacer pausas cuando bailo y pasar 2 o 3 compases sin pisar (o sea, conservando el peso de los pies tanto míos como los de mi pareja). Entonces estuve buscando alguna forma de poder ayudar a que puedan estar sin pisar, cosa que hace que yo disfrute más del baile y que ellas bailen mejor (y, espero, que lo disfruten también). A lo que llegué, es que están demasiado enfocadas en los pasos. Creo que esto es algo común tanto para cuando llevamos como para cuando somos llevados.
Mi contrapropuesta es que pensemos en otra cosa. Pensemos en nuestra pareja de baile y como interactúa con nosotros. En el calor que se siente en las partes del cuerpo que están en contacto. Brazo con espalda, mano con mano, pecho con pecho, panza con panza, etc. Y hagamos eso todo el tiempo. Pensemos en cómo va variando cuando hacemos diferentes pasos, con la respiración. Si nos concentramos, a veces también podemos sentir los latidos del corazón.
Lamentablemente, cuando llevamos tenemos otras responsabilidades. Manejar el espacio y la circulación en la pista. Empezar y terminar las frases de la música. Preveer el final para no quedar pagando. Pero si tenés la suerte de estar siguiendo, podés entregarte 100% a sentir a tu pareja de baile, que es lo más lindo del tango.
Nos vemos en la milonga,
Aureliano.
PD: No, no doy clases de tango.

2011-12-12

El plagio es la forma más sincera de halago

Hoy salió la versión 4.0 de bindiff, y le incluyeron un feature que se llama "Combined visualization of two flowgraphs" que se parece mucho a lo que presenté en Hack.lu 2010 (y que presenté anteriormente en este blog). De todas maneras, me parece que les faltó ir hasta el fondo y unir cada par de basic-blocks en uno solo (si alguien de Zynamics ve este blog, miren mi paper para ver cómo hacerlo).

Happy hacking,
Aureliano.

2011-12-08

Un día bizarro

Ayer fue un día bizarro. A la mañana participé de la grabación de un programa del History Channel que se llama "Super Humanos" o algo así. En el mismo estuve con 2 amigos evaluando a Jaime García Serrano, que calculó raíces cuadradas, logaritmos, funciones trigonométricas, las inversas de las trigonométricas y factoriales, mientras nosotros teníamos que decir si lo calculaba bien o no, mirando los resultados en una compu.
Salí corriendo porque a la tarde tenía otro compromiso. A las 14.15 tenía turno para que me saquen una muela de juicio. Me sacaron la muela y ahora estoy tomando antibióticos y analgésicos, y el helado es mi principal alimento.
A la noche fui a La Glorieta, donde bailé algunos tangos y me encontré con amigos.
Al final, me fui a dormir.
PD: Me dijeron que el programa sale en abril.

2011-11-21

Zipeando working directories

Para zippear un directorio controlado por svn sin poner la info administrativa de svn podés ejecutar este comando en bash y va a andar:

find . -not \( -type d -name ".svn" -prune \) -type f -print | zip -@ ~/zip_file_name

Happy hacking,
Aureliano.

2011-11-17

La biblia y el calefón

EXPLICACIÓN DE UNA COMPARACIÓN EN LA LETRA CAMBALACHE

¡EXACTA REAL DEMOSTRABLE Y CREIBLE;PARECE MENTIRA QUE JAMAS LO EXPLICARAN LOS MILES DE ESCRIBAS, LITERATOS E INTELECTUALOIDES QUE DICEN " ESTUDIAR EL TANGO"

La Biblia y el Calefón –
Se habla de ello y la mayoría no sabe de qué se trata:
He aquí la historia de un hecho de la vida cotidiana, que acontecía en la ciudad de Buenos Aires –no sé si en otros lugares pasaba o no–, y que explica el porqué de la aparentemente surrealista asociación de la Biblia junto al calefón que aparece en el tango "Cambalache", cuyas letra y música fueron compuestas por Enrique Santos Discépolo en 1935.

La historia tiene relación con los baños, la higiene personal y la forma de realizarla; y como no se me escapa que algunos lectores pueden ser jóvenes y pueden no haber conocido otro tipo de baños que los que se estila usar en la actualidad al menos en el mundo occidental y cristiano, voy a recordar primero un par de datos que considero necesario sean tenidos en cuenta.

Los baños que conocemos y que en algunos lugares son llamados 'completos', es decir, los que constan como mínimo de retrete inodoro, lavabo y ducha (algunos exquisitos, como el irresponsable que escribe, exigen que además tenga bidet –artefacto desconocido en muchos sitios–) son relativamente nuevos.

Hasta finales del siglo XIX se utilizaban bacinillas (también llamadas ‘tazas de noche’), cuyos contenidos eran arrojados por las ventanas al grito de "agua va"; y antes aún, letrinas, que solían estar en los fondos de las casas.

En Buenos Aires coexistieron bacinillas y letrinas hasta principios del siglo XX, época en que las familias ‘acomodadas’ comenzaron a instalar baños.

Luego el uso de baños se generalizó y se empezó a construirlos en todas las viviendas, aun en las más modestas. El sencillo 'miniambiente' constaba al menos de retrete y lavabo y si los lujuriosos dueños de casa gustaban de practicar la morisca costumbre de lavarse todo el cuerpo más o menos seguido, y si además tenían medios económicos suficientes como para costearse ese capricho, los baños también tenían una ducha. Claro, si había una ducha era necesario calentar el agua, así que al lado de la ducha se instalaba un calefón.

Sin embargo, el papel higiénico tardó en obtener su carta de ciudadanía

para poder trabajar en limpio en estas sucias tierras y aun cuando apareció era bastante caro y no estaba al alcance de todas las familias, las cuales se veían obligadas a utilizar para esos fines sanitarios el vulgar papel de diario o, en su defecto, cualquier otro.

Por supuesto, eran muy estimados los papeles más sedosos, así que los sufridos usuarios trataban de conseguir en las verdulerías y fruterías los papeles con los que venían envueltas las manzanas y otros productos de campo.

Otro muy apreciado era el llamado ‘papel biblia’, especialmente delgado y suave.

Ahora bien, ya por entonces existía la Sociedad Bíblica, una de cuyas misiones parece ser la de difundir la Biblia protestante, para lo cual regalaba ejemplares del sagrado libro –en la actualidad, lo sigue haciendo–.

Pues, muchos de los habitantes de Buenos Aires deben de haber parecido devotos creyentes, ya que aceptaban de continuo esas gentilezas, y que siendo mayoría la grey católica, lo mismo pasaban y retiraban la biblia protestante tantas veces como sabían que la Sociedad las tenía en obsequio en las calles, plazas o en su sede central .
LA BIBLIA Y EL CALEFÓN

Sin embargo, cuentan los hombres dignos de fe (aunque Alá sabe más) que quienes obtenían esas Biblias les perforaban una tapa y las colgaban de un gancho de alambre, al lado del calefón, cerca del retrete, e iban arrancando las suaves hojas para usarlas como papel higiénico.

En este hecho se habría inspirado Enrique Santos Discépolo para decir con elegancia propia de un grande autor:

Igual que en la vidriera
irrespetuosa
de los cambalaches
se ha mezclao la vida,

Y HERIDA POR UN SABLE SIN REMACHE
VES LLORAR LA BIBLIA
JUNTO AL CALEFÓN.

Edgardo G. Maggiora
BARILOCHE

Gracias Mayca por este material!

Cómo, esto también es matemática?

Un post de este blog se va para arriba. Los números de Aure aparecen en el último libro de Paenza. Mirá la página 224.

Happy hacking,
Aureliano.

2011-11-07

Cortando video con ffmpeg

Para cortar video usando ffmpeg hay un comando que me resultó re-práctico. Lo pongo acá para acordarme.

ffmpeg -sameq -ss [start_seconds] -t [duration_seconds] -i [input_file] [outputfile]


Fuente: joeldare

2011-08-25

Por si alguna vez entran palomas en su server room.....

adapté una conocida canción para conmemorarlo. Pongo acá abajo letra y acordes.


Mim Sim Mim
Se equivocó la paloma, se equivocaba,
en vez de al norte, al server room
Do Sim MIm
pensó que el cable era paja, se equivocaba

Sol
Pensó que Sun era el cielo,
Mim
la mudanza era mañana,
Do Lam MIm
se equivocaba, se equivocaba
Lam Si7 Mim
que las bandejas manzanas,
Lam Si7 Mim Re
que la calor la nevada,
Sol Si7 Lam
se equivocaba, se equivocaba.

Si7 MIm
Que tu CAT,era tu blusa,
Do Si7 Do Re
que tu bandeja, su casa,
Mim Re Mim Mi7-Lam
se equivocaba, se equivocaba,
Re7 Sol Mim Lam
ella se durmio en la silla,
Si7 Mim
tu en la cumbre de un ra-ack.

Si7 MIm
Que tu CAT,era tu blusa,
Do Si7 Do Re
que tu bandeja, su casa,
Do Mim
se equivocaba, se equivocaba.

Enjoy!,
Aureliano


2011-08-04

Qué semana de mierda!

  • El domingo me levanté con 38 grados de fiebre. Como estaba enfermo no pude ver a mi hijo. A la noche tenía casi 39 de fiebre.
  • El lunes seguía con fiebre, así que falté al laburo. Como no me mejoraba, llamé al médico. El médico vino, me dijo que tenía una angina, me recetó un antibiótico y me dijo que tomara ibuprofeno para bajar la fiebre. Fui a la farmacia, compré todo, volví a casa, tomé el antibiótico y el ibuprofeno. Me bajó la temperatura y me fui a dormir.
  • Me desperté el martes a las 2 AM todo sudado y cagado de frío. Cuando vi que no podía dormirme del frío me levanté para sacarme la ropa toda mojada y me agarraron unos espasmos impresionantes. No podía dejar de temblar. Así que me cambié la remera y me volví a acostar. Seguía cagandome de frío.
  • Pasó como una hora y se me pasó el tembleque. Así que agarré el termómetro. Marcó 39.3. Me tomé otro ibuprofeno y me fui a dormir.
  • El martes me desperté sin fiebre, pero al mediodía ya estaba con fiebre de nuevo. A la noche me tomé otro ibuprofeno y el antibiótico. Como seguía hecho mierda, de nuveo no vi a mi hijo.
  • El miércoles me desperté un poco mejor, sin fiebre. Pero después del mediodía me agarró diarrea. Por suerte había tomado mucha agua y me la pude bancar. A la noche no tomé el ibuprofeno y me fui a dormir.
  • El jueves (hoy) me sentí un poco mejor, así que ¡fui a hacerme un tratamiento de conducto!. Ahora estoy bajo los efectos de los analgésicos recetados por la dentista.
Así que sumarizando mi semana queda así: angina, fiebre, diarrea y conducto.

Hasta la próxima,
Aureliano.

2011-06-17

Integración paver fabric

Update: Parece que se viene esto como parte de paver 1.1

Hice un pequeño hack y ahora puedo usar el API de fabric cuando escribo tasks de paver y que la tarea se ejecute una vez para cada host.

Para hacer eso, hice un decorator, que se llama multihost y es así:

from fabric import state, network

def multi_host(f):
"""\
Run the decorated function for each host in options.get("host_strings").

Will use the private key set in options.pk if set.
"""
def decoratee(options):
for host_string in options.get("host_strings"):
network.interpret_host_string(host_string)
pk = options.get("pk", None)
state.env.key_filename = [pk] if pk else None
f(options)

decoratee.func_name = f.func_name

return cmdopts((
("pk=", None, "Private key file"),
))(decoratee)

El uso es así:


from paver.easy import task, needs
from fabric import api

@task
def find_hosts(options):
options["host_strings"] = ["host1", "user@host2", "user2@host3:2222"]

@task
@needs("find_hosts")
@multi_host
def remote_hello_world(options):
api.run("echo hello world")


Happy hacking,
Aureliano.

2011-06-14

Tamaños de ventanas extraños en eclipse y workaround

En el laburo desde hace un tiempo estoy haciendo el experimento de correr varias VMs con los distintos proyectos en los que trabajo. Por lo tanto tengo varias VMs distintas (guests) corriendo que se conectan usando X a mi host.

En una de ellas tengo eclipse instalado con pydev. Y como host tengo un Windows 7 con X-Ming como server X. Y anda todo bastante bien salvo porque algunas ventanas de diálogo se van agrandando de formas extrañas hasta que se vuelve imposible usarlas. Y aparte, no sé por qué, no se pueden resizear usando el mouse (que sí se puede si lo corrés en Windows, gnome o kde normalmente).

Por lo tanto, busqué y encontré un workaround al problema, y edito a mano algunos archivos de configuración del workspace de eclipse para cambiar estos tamaños a una medida razonable para mi y para que quede documentado lo dejo anotado acá.

En el archivo ./org.eclipse.ui.ide/dialog_settings.xml sección DialogBoundsSettings setié:

<item value="1024" key="DIALOG_WIDTH"/>
<item value="768" key="DIALOG_HEIGHT"/>


En el archivo org.eclipse.ui.workbench.texteditor/dialog_settings.xml sección org.eclipse.ui.texteditor.FindReplaceDialog_dialogBounds setié:
<item value="1024" key="DIALOG_WIDTH"/>
<item value="768" key="DIALOG_HEIGHT"/>


En el archivo org.eclipse.search/dialog_settings.xml sección DialogBounds_SearchDialog setié:
<item value="1024" key="DIALOG_WIDTH"/>
<item value="768" key="DIALOG_HEIGHT"/>


Y por último, en el archivo org.tigris.subversion.subclipse.ui/dialog_settings.xml hice algo un toque distinto, seteando en la sección Workbench esto:
<item value="1280" key="CommitDialog.size.x"/>
<item value="768" key="CommitDialog.size.y"/>


Por supuesto, todos estos archivos hay que tocarlos con el eclipse apagado.

Happy hacking,
Aureliano.

2011-06-06

Sé lo que hiciste el verano pasado

Hola,

estuve ocupado últimamente así que no pude darle mucha pelota a mi blog. Hoy suspendo este silencio para contarles que estuve haciendo en el laburo los últimos meses. Lo que hicimos es un servicio para pentestear instancias y páginas web que estén hosteadas en AWS. Aunque mucho el nombre no me gusta (lo eligió la gente de marketing), se llama Core CloudInspect y está acá.

La idea es hacer pentests en 5 clicks y 20 dólares y, los primeros 3 son gratarola!.

Happy hacking,
Aureliano.

2010-10-28

Presentación en Hack.lu

Hace unas horas presenté en Hack.lu mi charla sobre aureliax. Aureliax es un software que sirve para mostrar diferencias entre diferentes versiones de una misma función, que es mostrada mediante un grafo de basic blocks. En cuanto pueda voy a poner on-line el white paper que explica cómo funciona y cuál es la base teórica que lo sustenta.
Por ahora estoy contento y cansado (acá en Luxemburgo son las 2 menos 20), y mañana tengo un largo día por delante.

Happy hacking,
Aureliano.

2010-09-21

Bajo el farol


Les recomiendo que vayan a ver esto. Yo fui la vez anterior, en abril, estuvo buenísimo y voy a ir de nuevo.

2010-09-04

Cómo trato de bailar a Pugliese

  • Escuchando el fraseo y siguiendo su intensidad.
  • Escuchando el compás, que aunque no siempre se note siempre está ahí.
  • Variando estilo y distancia del abrazo, pasando desde un tango milonguero, al tango salón y a veces hasta con abrazos típicos del tango nuevo. Todo dentro de un mismo tema.
  • Dando tiempo a la mujer para que también pueda hacer su propia interpretación y lucirse. Generalmente esos tiempos se dan en las partes más piano, que generalmente son a cargo del violín y/o en el final de la frase musical.
  • Es muy raro que haga paradas y el sanguchito, aunque si me parece que mi pareja lo quiere puedo llegar a marcar uno.
  • Giro en la parte ligada y camino usando contratiempos en la parte marcada.
  • En las pausas no hay cambios de peso, pero trato de mantener un dejo del movimiento que veníamos haciendo justo antes.
  • La elección del paso y la intensidad depende de la música, la pareja y la pista.
  • El final generalmente incluye una corrida de 5 o 7 pasos hasta el acorde dominante y quitar toda la tensión cuando suena la tónica suavemente en el piano.
Happy dancing,
Aureliano.

2010-07-30

Arte efímero


Marcador al agua sobre pizarrón blanco

2010-07-12

Una pequeña delicia del JavaScript

Qué valor debería dar el siguiente código:

"aDb".replace("D","$$")

Si pensaron "a$$b" se equivocaron. Da "a$b" (con un solo $).
Para que de el valor que esperaba ("a$$b") hay que hacer este hack:
"aDb".replace("D",function() { return "$$" })

¿Por qué?
Ni idea, pero anda así en rhino y V8, así que debe estar en la especificación.

Happy hacking,
Aureliano

2010-06-01

Flechas con RaphaelJS

Me encontré con que no hay ningún método para dibujar flechas en raphaelJS, así que me puse las pilas y programé uno:

 /**
* Returns a path in form of an arrow
* @param arrowSize is the size of the arrow end. Defaults to 10 pixels.
*/
Raphael.fn.arrow = function(x1, y1, x2, y2, arrowSize) {
var arrowSize = arrowSize || 10
var l = Math.sqrt( Math.pow( x2 - x1, 2 ) + Math.pow( y2 - y1, 2 ) )
var xStep = (x2 - x1) / l
var yStep = (y2 - y1) / l

// arrow point ends
var arrX1 = x2 + arrowSize * (yStep - xStep) / 2
var arrY1 = y2 + arrowSize * (-xStep - yStep) / 2
var arrX2 = x2 + arrowSize * (-yStep - xStep) / 2
var arrY2 = y2 + arrowSize * (xStep - yStep) / 2

var path = ["M", x1, y1, "L", x2, y2, //main line
"M", arrX1, arrY1, "L", x2, y2, "L", arrX2, arrY2] //arrow end

return this.path(path.join(" "))
}

Para usarlo hay que hacer:

var r = Raphael(....)
.....
var arrow = r.arrow(150,100,250,300)

2010-05-19

Cambiando el context-root

Esto es lo que tuve que hacer para que la webapp en java que estoy desarrollando con eclipse 3.5 y web tools platform ande en el context-path root:

  • Abrir el archivo .settings/org.eclipse.wst.common.component
  • Cambiar la entrada <property name="context-root" value="risky"> por <property name="context-root" value="/">
Happy hacking,
Aureliano

2010-04-27

Ahora tengo twitter

Saqué cuenta en twitter y voy a empezar a twittear (¿se escribe así?). Si quieren seguirme mi usuario es aurelianito.

En cuanto tenga alguna idea de lo que opino de twitter la mando por acá.

Happy hacking,
Aureliano

2010-04-06

Bajo el farol

Update: si quieren pueden escuchar algunas canciones del show en su página de myspace

Este sábado 10 de abril a las 23:30 hs mi amiga y gran cantante Natalia Iñón presenta su espectáculo "Bajo el farol" en la Casona del Teatro, que queda en Corrientes 1975 (Ciudad de Buenos Aires). El repertorio está compuesto por canciones de Edith Piaf, Marlene Dietrich y algunos tangos. Les sugiero que vayan a escucharla ya que es una cantante exquisita.

Nos vemos allá,
Aureliano

2010-03-08

Pequeñas cosas que me molestan

Un compañero de laburo dice que las personas que nos dedicamos a la programación y aledaños generalmente tenemos alguna tendencia al desorden obsesivo-compulsivo. Yo hice mi mea-culpa y acá escribo una lista de pequeñas cosas que creo que me molestan por tener algo de esa tendencia:
  • Salir a comer y que algunos pidan postre y otros no.
  • Salir a comer y que algunos pidan entrada y otros no.
  • Jugar fútbol en cantidades impares (ej: 5 contra 4)
  • Que los platos colocados en el escurridor no estén cada uno en una rendija y ocupando rendijas consecutivas desde el extremo más lejano del mismo.
¿Qué cosas equivalentes les molestan a ustedes?,
Aureliano

2010-03-03

Configurando lyx para escribir proceedings de ACM

Hoy configuré el lyx para que use la clase de LaTeX que piden para los proceedings de ACM y fue bastante más molesto de lo que esperaba. Esto lo hice en un ubuntu 9.10 casi pelado (con lyx y no mucho más). Acá les cuento los pasos:

  1. Copiá acm_proc_article-sp.cls a $HOME/texmf/tex/latex
  2. Corré "texhash ." en $HOME/texmf/tex/latex
  3. Poné en ./lyx/layouts el archivo acm_proc_article-sp.layout
  4. Arrancá lyx, andá a Tools->Reconfigure y volvé a arrancar lyx.
  5. Ahora en Document->Settings->Document Class está disponible la clase de los proceedings de ACM bajo el nombre "ACM Sig Proceedings".
Happy hacking,
Aureliano.

2010-02-22

Una reflexión sobre facebook

El otro día estaba cenando con unos amigos y estabamos hablando de como me echaron de FB. Y un amigo hizo una analogía re-buena.
¿Qué pasa si te ponés a bailar en los pasillos de un shopping? Lo más probable es que venga alguien de seguridad y te pida "amablemente" que te retires del lugar. En cambio si te ponés a bailar en el medio de una plaza, más allá de algunas miradas raras no debería pasarte nada.
¿Y por qué? El asunto es que nos olvidamos que el shopping no es un espacio público sino un espacio privado al que te dejan entrar cuando quieren, como quieren y en el que pueden aplicar toda clase de reglas arbitrarias. En cambio, una plaza es un lugar mucho más público.
Y con facebook pasa lo mismo. Es un espacio que nos olvidamos que es privado, pero lo es. Entonces nos molesta que nos apliquen reglas raras.
Ojalá estas cosas que me pasaron a mi (y a otros) sirvan para que entendamos la diferencia.

Happy hacking,
Aureliano.

2010-02-09

Exportando gráficos en dia a pdflatex

  1. Hacé tu gráfico en dia
  2. Exportarlo como "LaTeX PGF macros"
  3. En el principio de tu .tex poné:
  4. \usepackage{tikz}
  5. En el lugar donde quieras poner tu caption poné
    \begin{figure}
    \centering
    \input{archivo_exportado_de_dia.tex}
    \caption{Acá va el caption}
    \label{aca_va_la_label}
    \end{figure}
  6. Compilá el .tex principal con pdflatex
  7. Miralo con tu visor de pdfs favorito
Happy hacking,
Aureliano.

2010-02-07

Como ven los fanas de un lenguaje a los otros

Mirar lambda the ultimate es siempre interesante. Y esta vez me crucé con una perlita que quiero compartir con ustedes:

2010-02-05

Segundo advisory

Ayer salió mi segundo advisory. Lo que encontramos con Manuk es que parte administrativa de la aplicación LanDesk Manager tiene un cross-site request forgery que hace que si enganchás a un administrador se pueda hacer un cross-site scripting no persistente y, aún más divertido, hacer un OS command injection.
Aún más divertido, es que se puede usar modprobe y cargar módulos de kernel de linux que uplodee usando el command injection.
Más detalles en la página de Core.
Happy hacking,
Aureliano

2010-01-27

Simplificando

Ayer me di cuenta que no necesito rehacer los classloaders de java para cargar scripts de JavaScript, ya que puedo usarlos y son todo lo flexibles que necesito (y más). Inclusive, si por una de esas casualidades llegara a hace falta, creo que puedo hacer uno en rhino y todo. Por lo tanto decidí que mi lógica para cargar módulos tenía una indirección de más (la lista de loaders) y lo cambié para que use el classloader y listo. Fíjense en la nueva implementación de loadMod y como se simplificó el uso de los loaders.
En la versión del código que estoy usando ahora, también hice que los módulos se carguen un toque distintos para que haya mejores stack-traces (ese cambio está en la función require). Bueno, abajo pongo el código:


/*
* Does not support relative paths (yet?).
* Can be invoked by several threads.
*
* Uses the classloader to fetch js modules.
*/
var require = function (id) {

try {

require.lock.lock() // Avoid threading issues while loading modules.

if (!require.modules[id]) {

var modCode = require.loadMod(id)

var exports = {}
require.modules[id] = exports
var module = {
id : id
}

var context = {
exports: exports,
module: module,
}

if(!modCode) {
throw new require.RequireError(id, "module not found")
}

org.mozilla.javascript.Context.getCurrentContext().evaluateString(
context,
modCode,
id,
1,
null
)
/*
Old style invocation, should work in the browser but has worst error messages.

var f = new Function("require", "exports", "module", modCode)
f.call(context, require, exports, module) */
}

return require.modules[id]
} catch (x) {
if (x instanceof require.RequireError) {
throw x
} else {
throw new require.RequireError(id, x)
}
} finally {
require.lock.unlock()
}
}

require.loaders = []
require.modules = {}
require.lock = new java.util.concurrent.locks.ReentrantLock()

var RequireErrorProto = {}

require.RequireError = function(moduleId, cause) {
this.moduleId = moduleId
this.cause = cause

}
require.RequireError.prototype = RequireErrorProto
require.RequireError.prototype.toString = function() {
return "Error loading " + this.moduleId + ( this.cause ? ". Cause: " + this.cause : "" )
}
require.RequireError.prototype.name = "RequireError"

require.load = function(path) {
return java.lang.Class.forName("java.lang.String").getResourceAsStream(path)
}

require.loadMod = function(id) {
function path(id) {
return "/" + id + ".js"
}

function readFromStream(stream) {
var io = java.io
var reader = new io.BufferedReader( new io.InputStreamReader(stream) )
try {
var stringBuffer = new java.lang.StringBuffer()

var line = ""
while( line = reader.readLine()) {
stringBuffer.append(line)
stringBuffer.append("\n")
}

return stringBuffer.toString()
} finally {
reader.close()
}
}

var stream = require.load(path(id))
if (!stream) { return null }

return readFromStream(stream)
}

/**
* Resets the module cache.
*
* It will reload all the modules. Old modules referenced will still be working.
*/
require.reset = function() {
try {
require.lock.lock()
require.modules = {}
} finally {
require.lock.unlock()
}

}

Este cambio también simplifico el RhinoServlet, y ahora toma sus scripts del classpath también.

Happy hacking,
Aureliano

2010-01-25

Parseando CSVs con una expresión de JavaScript

Para parsear un CSV con datos numéricos hay que hacer esto:


text.split("\n").map( function(r){
return r.split(",").map( function(d) {
return parseFloat(d)
} )
} )

Esto solo anda si tu intérprete de JavaScript tiene Array.prototype.map definido. Sino antes de eso tenés que definirlo así:

Array.prototype.map = Array.prototype.map || function( f ) {
var r = []
for (var i=0; i<this.length; i++) {
r[i] = f(this[i])
}
return r
}

2010-01-18

2010-01-17

Generando xhtml con e4x

Primero hay que setear el namespace por default:

default xml namespace = "http://www.w3.org/1999/xhtml"


Para generar elementos, uso esta función:
function elem(name) { return <{name} /> }


Para setear un attributo cualquiera esta función:
function attr(elem, key, value) { elem["@"+key] = value }


Y puedo usar elem.appendChild para agregar como hijo de un elemento otro o un texto como string que es escapado.

Happy hacking,
Aureliano.

2010-01-12

Entrada de BibTeX en Google Scholar

Si estás logueado en Google, podés setear Google Scholar para que te muestre las entradas de bibtex.
Para eso tenés que ir a Scholar Preferences -> Bibliography Manager y elegir Show links to import citations into BibTeX.

Happy hacking,
Aureliano

(Sacado de acá)

2010-01-10

Implementación de require en Rhino

Hoy estuve hackeando un toque y modifiqué el RhinoServlet que les mostré en este post para poder tener módulos en Javascript. El API que hice es un subset de lo definido en CommonJS. En particular, soporta require pero no los paths relativos de módulos (o sea, los que empiezan con . o ..). También le puse a todo un lock para que pueda usarse en un entorno concurrente, pero si un módulo tarda mucho en cargarse puede llegar a ser un problema.
Lo que me parece más interesante de mi prototipo es que se pueden agregar fácilmente nuevos loaders de módulos de JavasScript. Ya vienen por defecto loaders para cargar desde el classpath y desde la webapp, pero si quieren poder poner sus módulos en /WEB-INF/example, alcanza con agregar una línea en init.js:

require.loaders.push( require.stdLoader(servlet.servletContext, "/WEB-INF/example/"))

Bueno, basta de cháchara, acá está la versión modificada del RhinoServlet:
package aure.jslib;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.mozilla.javascript.Context;
import org.mozilla.javascript.Scriptable;
import org.mozilla.javascript.ScriptableObject;

public class RhinoServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
private Scriptable initialScope = null;

public void runJs(Context cx, String scriptLocation, Scriptable scope) throws IOException {

InputStream is = this.getClass().getResourceAsStream(scriptLocation);
if( is == null) {
is = this.getServletContext().getResourceAsStream("/WEB-INF/js/" + scriptLocation);
}
Reader jsReader = new InputStreamReader(is);

cx.evaluateReader(scope, jsReader, scriptLocation, 1, null);
}

public static void addJavaObjectToScope(Scriptable scope, String name, Object obj) {
ScriptableObject.putProperty(scope, name, Context.javaToJS(obj, scope) );
}

@Override
public void init(ServletConfig config) throws ServletException {
super.init(config);
Context cx = Context.enter();
try {
Scriptable scope = cx.initStandardObjects();
addJavaObjectToScope(scope, "servlet", this);
addJavaObjectToScope(scope, "config", config);

this.runJs(cx, "initRequire.js", scope);
this.runJs(cx, "init.js", scope);

this.initialScope = scope;
} catch (IOException e) {
throw new ServletException(e);
} finally {
Context.exit();
}
}

@Override
protected void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
Context cx = Context.enter();
try {
Scriptable scope = cx.initStandardObjects();
scope.setParentScope(this.initialScope);

addJavaObjectToScope(scope, "request", request);
addJavaObjectToScope(scope, "response", response);

this.runJs(cx, "start.js", scope);
} finally {
Context.exit();
}
}
}

Noten que toqué el init para que agregue el require y cambié la forma de levantar javascript. Por otro lado este es el javascript en initRequire.js, que tiene la implementación del require:

/* Based on http://www.davidflanagan.com/demos/require.js
* but heavily modified.
*
* Does not support relative paths (yet?).
* Can be invoked by several threads.
*
* Uses the servletContext and the classloader to fetch js modules.
*/
var logger = java.util.logging.Logger.getLogger("sarasa")

var require = function (id) {

try {

require.lock.lock() // Avoid threading issues while loading modules.

if (!require.modules[id]) {

var modText = require.loadMod(id)

var context = {}
var exports = {}
require.modules[id] = exports
var module = {
id : id
}

var f = new Function("require", "exports", "module", modText)
f.call(context, require, exports, module)
}

return require.modules[id]
} catch (x) {
throw new Error("Can't load module: " + id + ": " + x)
} finally {
require.lock.unlock()
}
}

require.loaders = []
require.modules = {}
require.lock = new java.util.concurrent.locks.ReentrantLock()
require.loadMod = function(id) {
var modText = null
var i = 0
while (modText == null && i < require.loaders.length) {
modText = require.loaders[i](id)
i++
}
return modText
}

// Setup loaders for files in the classpath, files in WEB-INF and files in the
// web-app (usually served to the client)
require.stdLoader = function(source, prepend) {
// Support functions
function readFromStream(stream) {
var io = java.io
var reader = new io.BufferedReader( new io.InputStreamReader(stream) )
var stringBuffer = new java.lang.StringBuffer()

var line = ""
while( line = reader.readLine()) {
stringBuffer.append(line)
stringBuffer.append("\n")
}

return stringBuffer.toString()
}

function path(id) {
return prepend + id + ".js"
}

var f = function(id) {
var stream = source.getResourceAsStream(path(id))
return stream ? readFromStream(stream) : null
}

return f

}

require.initStdLoaders = function() {
// classpath loader
require.loaders.push( this.stdLoader(servlet["class"], "/") )

// web-app context loader
require.loaders.push( this.stdLoader(servlet.servletContext, "/") )
}

require.initStdLoaders()

Empecé a hacer esto mirando el código en http://www.davidflanagan.com/demos/require.js pero al final quedó bastante distinto, sobre todo porque tiene la opción de tener muchos loaders.
Las cosas que me quedan para hacer son hacer que acepte paths relativos (que para que sea thread-safe hace falta que haga algunos truquitos) y hacer que en vez de usar
   var f = new Function("require", "exports", "module", modText)
f.call(context, require, exports, module)

para invocar el módulo haga algo usando el API de rhino para poder tener errores donde aparezca el nombre del módulo y el número de línea si hubo algún problema.

Escucho comentarios y sugerencias.

Happy hacking,
Aureliano.

Eclipse plug-in para app-engine

¿Por qué te negás a usar dependencias de otros proyectos de eclipse?
¿Por qué no recompilás bien cuando está corriendo el web-server en modo debug y uso resources de adentro del classpath?

Bueno, por ahora son 2 problemas que creo poder "workarroundear".

Happy hacking,
Aureliano.

2010-01-08

2 placas y default gateway

Hoy estuve configurando una VM con ubuntu que tiene una placa en modo bridged por DHCP y otra host-only estática. El problema que tuve fue que no encontraba la forma que la ruta por default sea la ruta por default que informa el dhcp. La solución que encontré fue hacer que la métrica de la ruta por default de la ip estática sea más grande.

Este es el archivo /etc/network/interfaces que terminé usando:

auto lo eth1 eth0
iface lo inet loopback

iface eth0 inet dhcp

iface eth1 inet static
address 172.17.17.16
netmask 255.255.255.0
network 172.17.17.0
broadcast 172.17.17.255
gateway 172.17.17.1
metric 200

Y la posta está en la última línea.

Probé sacar la entrada de gateway y agregar una entrada borrando la ruta que me sobraba (up route del default gw 172.17.17.1) y no funcionó.

Se les ocurre alguna otra forma de arreglar esto?

Happy hacking,
Aureliano.

2010-01-05

2 servlets para correr javascript

Estuve con algo de tiempo y me puse a probar como hacer para ejecutar JavaScript en el server. E hice 2 implementaciones (o sea, 2 servlets programados en Java). La primera que hice usa javax.script (que viene por defecto en Java 6) y me parece que el API es más cómoda pero tiene 2 limitaciones que no me gustaron, no se puede heredar de clases Java en JavaScript y no encontré cómo hacer para bindear un método de Java a JavaScript. Este es el código:

package aure;

import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;

import javax.script.Bindings;
import javax.script.ScriptContext;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class JsServlet extends HttpServlet {
private static final long serialVersionUID = 1L;

private ScriptEngine jsEng = new ScriptEngineManager()
.getEngineByName("js");
private Bindings initBindings = this.jsEng
.getBindings(ScriptContext.ENGINE_SCOPE);

public JsServlet() {
super();
}

@Override
public void init(ServletConfig config) throws ServletException {
try {
super.init(config);

this.initBindings.put("config", config);
this.initBindings.put("servlet", this);

this.runJs("init.js", this.initBindings);
} catch (ScriptException e) {
throw new ServletException("Error running init.js", e);
}
}

public void runJs(String scriptLocation, Bindings bindings)
throws ScriptException {
Reader jsReader = new InputStreamReader(this.getServletContext()
.getResourceAsStream(scriptLocation));

this.jsEng.eval(jsReader, bindings);
}

protected void service(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {

try {
Bindings bindings = jsEng.createBindings();
bindings.putAll(this.initBindings);
bindings.put("request", request);
bindings.put("response", response);

this.runJs("start.js", bindings);
} catch (ScriptException e) {
throw new ServletException("Error running javascript", e);
}
}

}

La segunda usa rhino bajado desde mozilla y por lo tanto no tiene esas limitaciones, pero el API para embeber JavaScript en Java es más fea. Acá está el código de la segunda versión:
package aure;

import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.mozilla.javascript.Context;
import org.mozilla.javascript.Scriptable;
import org.mozilla.javascript.ScriptableObject;

public class RhinoServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
private Scriptable initialScope = null;

public void runJs(Context cx, String scriptLocation, Scriptable scope) throws IOException {
Reader jsReader = new InputStreamReader(this.getServletContext()
.getResourceAsStream("/WEB-INF/js" + scriptLocation));

cx.evaluateReader(scope, jsReader, scriptLocation, 1, null);
}

public static void addJavaObjectToScope(Scriptable scope, String name, Object obj) {
ScriptableObject.putProperty(scope, name, Context.javaToJS(obj, scope) );
}

@Override
public void init(ServletConfig config) throws ServletException {
super.init(config);
Context cx = Context.enter();
try {
Scriptable scope = cx.initStandardObjects();
addJavaObjectToScope(scope, "servlet", this);
addJavaObjectToScope(scope, "config", config);

this.runJs(cx, "/init.js", scope);

this.initialScope = scope;
} catch (IOException e) {
throw new ServletException(e);
} finally {
Context.exit();
}
}

@Override
protected void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
Context cx = Context.enter();
try {
Scriptable scope = cx.initStandardObjects();
scope.setParentScope(this.initialScope);

addJavaObjectToScope(scope, "request", request);
addJavaObjectToScope(scope, "response", response);

this.runJs(cx, "/start.js", scope);
} finally {
Context.exit();
}
}
}

Ambas versiones ejecutan WEB-INF/js/init.js cuando se carga el servlet (tiene bindeados el servlet y la configuración del servlet) y WEB-INF/js/start.js cuando se atiende un pedido (agrega a los bindings lo que se haya puesto en init.js, el servlet, la configuración, el request y el response.

La idea de todo esto es ponerme las pilas e implementar las cosas que dije en este post hace casi 3 años, ya que ahora parece que se está poniendo de moda usar JavaScript.

Espero que les parezca interesante, me voy a dormir.

Happy hacking,
Aureliano.

2009-12-07

Cómo me echaron de facebook


Esta es la lista de eventos que pasaron hasta que me echaron de Facebook:
  1. 2007-11-10: Primera invitación a facebook recibida por mail
  2. 2009-09-27: Me suscribo a facebook
  3. 2009-09-30: Creo el grupo "Destruyendo facebook desde adentro"
  4. 2009-10-04: Publicito el grupo en un post de mi blog.
  5. 2009-10-17: Me linkea vivalinux. Entran más de 500 personas al blog en 2 días. El post del punto anterior es trolleado.
  6. 2009-10-18: Sin ningún tipo de aviso bloquean mi cuenta en facebook.
  7. 2009-10-19: Empieza la seguidilla de mails de/a facebook. El primero es este: "I've checked out on the links of the http://www.facebook.com/help.php?page=45 page and I didn't violate any rules.

    Can you inform me why the account was disabled?

    Thanks in advance,
    Aureliano Calvo."
  8. 2009-10-22: Contesta facebook (enfasis mío):"Hi Aureliano,

    Fake accounts are a violation of our Statement of Rights and Responsibilities. Facebook requires users to provide their real first and last names. Impersonating anyone or anything is prohibited. Unfortunately, we will not be able to reactivate this account for any reason. This decision is final.

    Thanks for your understanding,

    Johanna
    User Operations
    Facebook"
  9. 2009-10-22: Contesto yo (enfasis mío):"Hi,
    I've been falsely accused of impersonating someone else and this is just not true. I'm Aureliano Calvo, this is my e-mail and you can google for me. I can also provide several proofs of my identity and I'm willing to send photographs of my driver license, my passport or my identity card.

    Can you reactivate the account?

    Aureliano.
    "
  10. 2009-10-23: Vuelve facebook :"Hi Aureliano,

    Unfortunately, your account has been permanently disabled for violating Facebook's Statement of Rights and Responsibilities. We will not be able to reactivate it for any reason, nor will we provide further explanation of your violation or the systems we have in place. This decision is absolutely final.

    Thanks,

    Johanna
    User Operations
    Facebook"
  11. 2009-11-21: Pido por mail que borren todos mis datos de facebook:"I would like to have removed all my data from the facebook servers (generated from the account asociated with this e-mail).

    Thank you very much in advance,
    Aureliano Calvo"
  12. 2009-11-25: Contesta facebook sobre la remoción de datos:"Hi Aureliano,

    Facebook users have the option to either deactivate or delete their accounts. The differences between the two options are described below.

    If you deactivate your account, your profile and all information associated with it are immediately made inaccessible to other Facebook users. What this means is that you effectively disappear from the Facebook service. However, we do save your profile information (friends, photos, interests, etc.), so if you want to reactivate at some point, your account will look just the way it did when you deactivated. Many users deactivate their accounts for temporary reasons and expect their information to be there when they return to the service. You can deactivate your account through the "Deactivate Account" link on the Account page.

    If you do not think you will use Facebook again and you would like to delete your account, you can do this yourself by navigating to the following page:

    http://www.facebook.com/help/contact.php?show_form=delete_account

    Please keep in mind that once your account is deleted, you will not be able to reactivate the account or retrieve any of the content or information you have added.

    If you are currently unable to access your account, you will need to reset your password in order to log in. In order to do so, click the "Forgot your password?" link that appears above the field where you would normally enter your password. Entering your login email address on the next page will cause a new password to be sent to that email address. Once you receive your new password and can log in, you can deactivate or delete your account using the steps outlined above. We apologize for any inconvenience this may cause.

    Thanks for contacting Facebook,

    Brett
    User Operations
    Facebook"
  13. 2009-11-25: Contesto que no puedo porque deshabilitaron la cuenta:"I've requested that all my data should be removed from the facebook servers by email because my account has been disabled.
    Please remove all my data from the facebook system.

    Thank you very much,
    Aureliano Calvo."
  14. 2009-11-29: Me dicen que me joda que se quedan con todos los datos:"Hi Aureliano,

    When an account is disabled, the profile and all information associated with it are immediately made inaccessible to other Facebook users. What this means is that you effectively disappear from the Facebook service. In addition, Facebook does not use information associated with disabled accounts.

    Unfortunately, for safety and security reasons, we cannot delete from our servers information associated with disabled accounts. We also cannot grant you access to a disabled account to retrieve content from it, nor can we provide you with any content that was associated with this account. We apologize for any inconvenience this may cause. This decision is final.

    Thanks for your understanding,

    Brett
    User Operations
    Facebook"
Conclusiones:
  • Facebook contesta en tiempo y forma los pedidos por mail.
  • Facebook no identifica a las personas que contestan y no toma responsabilidades.
  • Facebook echa gente que no viola sus términos y condiciones (el punto que dicen que violé es mentira)
  • Facebook se niega a dar información sobre que hiciste mal (probablemente para cubrirse del punto uno) y encima lo hacen mal (como se ve en el punto anterior).
  • Facebook se niega a borrar los datos de la gente que echa (cosa que, hasta donde yo sé, es ilegal en Argentina).
O sea, mejor irse lo antes posible de ahí. No dejes que los mercaderes de relaciones te dominen.

Happy hacking,
Aureliano.

2009-12-02

Deshabilitando autoindent de () en vim

Para editar html con javascript con algo más de onda en gvim adopté el siguiente seteo:

:set inde=
:set ai

Para más detalles mirá acá.

Happy hacking,
Aureliano.

2009-11-26

Invitaciones para Google Wave

¿Querés una invitación para Google Wave?

Avisame y te la mando (tengo 16 para repartir).

Seguridad nacional

Esto le pasó ayer a un compañero de trabajo. Espero que sirva para que sepamos que no hay que creer todo lo que pasa en la tele:

Ayer fue al super (disco)  a buscar la compra que habia hecho antes de
ayer ya que me avisaron que los empleados del delivery estaban de paro
por un reclamo sindical. cuando estoy llegando veo que en la esquina hay
una especia de muchedumbre de 20-30 personas y una camara de TV. No doy
bola y paso de largo hasta el super, que encuentro cerrado, en las
puertas de vidrio habia pagadas que decia qu ella empres ales mando la
policia a los que estaban reclamando para "apretarlos" y por ese se
metieron adentro y cerraron. Digo.. "uh que mal" y me voy pensando que
la muchedumbre de la esquina tendra algo que ver con eso. cuando llego a
la esquina y presto atencion a lo que pasa me doy cuenta que en realidad
hay 20-30 energumenos en chomba, camisa rosa+sweater al cuello y/o
vestido largo y ollas de fondue gritandole a la camara "seguridad!
seguridad!" mientras esgrimen cartelitos escritos prolijamente con
marcador con la palabra en cuestion ("seguridad"). Detras de todos
ellos, sentado en el piso esta durmiendo un señor de entre 50-60 años
que vive en la calle en esa esquina desde hace una semanas. Los
protestantes lo ignoran olimpicamente, pero el señor se despierta y
percibe que hay algun quilombo y desde el piso se une a los canticos al
tiempo que ademas aplaude (!?)

Me abro paso vocifereando que son todos unos payasos mediaticos (como
osvaldo pagani) pero a nadie parece importarle o molestarle lo que digo
o hago (que lastima! ya que estan todos hipnotizados cantando su mantra
a la camara.

Minutos despues cuando llego a casa me dicen que en el noticiero de
America transmitian en vivo una "protesta de los vecinos de palermo"
demandando mas seguridad o algo asi.

Media hora mas tarde cuando paso otra vez por la esquina paseando al
perro "los vecinos de palermo" no estan mas (el noticiero de america ya
termino) pero sigue estando el señor que vive en la esquina condiciones
de "seguridad" bastante precarias (hasta tanto no se entere la UZZEP).

Alguien vio algo de esto en el noticiero de America ayer? que dijeron?


Happy hacking,
Aureliano.

2009-11-25

Firewall, Windows 7 y guests bridgeados de VMWare

Si dejo el firewall de Windows 7 activado filtra las conexiones entrantes a las VMs del VMWare Server que están conectadas en modo "bridged" a la red. No sé el ip del guest ya que se obtiene por DHCP. Si apago el firewall, las conexiones entrantes llegan hasta las VMs.

Saben como hacer para dejar el firewall prendido pero que las conexiones que van a los guests en modo bridged pasen sin ser filtradas? Qué reglas tengo que agregar/sacar?

Muchas gracias,
Aureliano

2009-11-22

Como facebook cuida tu privacidad

Vía slashdot.

Una mina con tratamiento por depresión en Canadá le niegan el tratamiento porque tiene fotos en la playa y en una fiesta en facebook (en una cuenta "lockeada"). Más detalles ver acá.

Esperemos que no se mate por esto,
Aureliano.

2009-11-20

Visualizando más

En este post prometí que iba a contar que cosas vi en VisWeek 2009. Y como lo prometí, aunque un poco tarde acá pongo mis notas de la conferencia (tienen mezcla con inglés):

Domingo 11:

8:30am
* Keynote: Bill Cheswick
*"Visualization is about coolness"
* Lots of developments. But almost nothing in the industry

Problemas:

* Layout arbitrario
* La evolución no es clara
* Las cosas que se sacan no se muestran
* Destruyen el contexto

Usa minimum distance spanning trees todo el tiempo para mostrar cosas aunque descarta el 30-40% de las conexiones.

How do you measure security?
* Generals and CIOs want to know.
Trusecure. Always and human in a step.

Network Access Security: contar cantidad de puertos abiertos
privilege scalation: programas que corren como root desde un usuario normal.

Parte difícil, como hacer los reportes.

2D sin tiempo -> 3D para el tiempo?

Ninguna buena visualización buena de IPv6


--------------------------------------------------------------------
Sesión de visualización de redes
10:30am

Visualization of complex attacks.
* Desde el pto de vista del sysadmin.
* Ataque simple: Una acción
* Ataque complejo: combinación de los anteriores
* DDNS
* "Multi-step"
* Worm propagation
* Interesante: las líneas hacen un "fade-out" con el tiempo. Las cosas nuevas son menos transparentes.
* El IDS informa que ataques simples pertenecen al mismo ataque complejo.

OverFlow: An Overview Visualization for network analisis
FloVis -> http://www.flovis.net

Security visualization tools and ipv6 addresses
* Demasiadas direcciones (128 bits)
* La mayoría de las visualizaciones no bancan ipv6
* muestra cambios en headers 4->6
* Se enfoca en "process and reformat" y "display"
* Muestra las comunicaciones con un scatter plot
* Le da un índice ordenado a cada dirección
* Usa la estructura de la dirección para agrupar direcciones
* Treemap (no me gusta, parece muy "cluttereado":
* Color: tipo de paquete (tcp, udp, etc)
* Tamaño: volumen de tráfico

1:00p
Malware and forensics
A visual Analytic framework for Exploring Relationships in Textual Content of Digital Forensics Evidence
Muestra como indexan el disco rígido y después filtran para ir buscando cosas en el disco rígido

Visual Analysis of Malware Behaviour Using Treemaps and Thread Graphs
CWSandbox.org
* Analisis automático de malware porque les mandan como 4000 ejemplos todos los días.
* Hacen un treemap con syscalls clasificados por tipo c/ color y cantidad de llamadas en el tamaño.
* El análisis es dinámico (o sea, ejecutan el malware).
* Por eso no los jode tanto la ofuscación
* Pueden detectar pdfs "malvados" mirando los treemaps (o clusterizando los datos).

Visualizing Compiled Executables for Malware Analysis
http://www.offensivetechnology.net (VERA)
* Dibuja los basic blocks que se ejecutan (todos, también los que se generan dinámicamente)
* Arma el grafo de los basic blocks
* les da más peso a los basic blocks que más se ejecutan
* por eso los loops que más se ejecutan quedan más grandes.
* pone diferentes colores a los basic blocks en función de cómo se generan
(ej: en el ejecutable en una sección de código,
en el ejecutable en una sección de datos,
generado dinamicamente,
etc)

2:30p
Users and Usability
Visualizing Cyber Security: Usable Workspaces
* Los analistas se quejan de que no pueden interactuar con los datos.
* Usan muuuuuuuuuuucha definición (10240x3200) y pueden mostrar simultáneamente los datos y los patrones que se forman en
alto nivel.
* History trees. Parecen como los branches en un control de versiones o algo así.

Visualization is Better! A Comparative Evaluation
http://tnv.sf.net vs ethereal en newbies
* Controlled experiment comparing two tools
* http://vizsec.org/datasets/

4:45p
Visualizing Keyboard Pattern Passwords
* Muestra como mostrar que teclas apretaron con una secuencia de reglas sobre como dibujarlos.
* Encontraron patrones mirando los passwds de a 25 (500 en total)
* Generaron diccionario con algunos patrones (500K passwords)
* Con ese diccionario crackeron passwds de verdad que John The Ripper no encontró

Visualizing Firewall Configurations Using Created Voids
Espacio:
5 dimensiones escalares (host1, port1, protocol, host2, port2) y un valor categorico (allow, deny).
regla:
(min_max de (host1, port1, protocol, host2, port2), (allow|deny))
Usa paralell coordinates :( (problemas de oclusión)

Panel (Visualization + Security = Science?):
Fue una pedorrada

Lunes 12:
Keynote VAST.
Storytelling.
Contó como es la estructura de un cuento clásico (introducción, nudo y desenlace), el camino del héroe (los 12 pasos que siguen casi todos los libros y películas) y dio una heurística para darse cuenta si algo es una buena historia o no. La misma consiste en si es posible responder estas 4 preguntas facilmente:
1. Quién es el héroe?
2. Qué quiere el héroe?
3. Qué impide que el héroe lo consiga?
4. Qué hace el héroe para solucionar el problema?
El chabón afirma que todos tenemos una habilidad natural para entender cuentos, y que por eso es bueno organizar las visualizaciones y presentaciones en forma de cuento.

VAST
Multidimentional Data session

A framework for uncertainty-aware visual analytics
Proponer manejar la incertidumbre todo a lo largo del pipeline de procesamiento de datos. Puede ser que los datos vengan con "incertidumbre" o que las transformaciones agreguen incertidumbre. Al final muestra la incertidumbre de varias maneras. Ej: color (segun que variable introduce mas incerteza), transparencia (para esconder datos menos confiables), o desagregando (pero solo para pocos datos)

Combining automated analysis and visualization techniques for efective exploration of high-dimentional data
Intenta detectar automáticamente que visualización de los datos es mejor. Creo que puede servir para mostrarle al usuario automáticamente vistas de datos que tengan algún sentido (muestran en scatter plots y paralell coordinates). También dicen que vistas muestran mejor una categorización dada.

Two-stage framework for visualization of clustered high dimentional data.
Hace algo parecido que la charla de arriba pero proyectando muchas dimensiones en 2 o 3.

Model space visualization for multivariate linear trend discovery.
Muestra una técnica manual para encontrar correlaciones lineales de dimensiones cuando hay muchas dimensiones

Martes 13:
Vast. Text analytics session.

LSAView: A tool for visual exploration of latent semantic modelling.
Sirve para clasificar documentos en función del tema. Visualiza el documento para que un analista decida si el clustering está bien.

Parallel tag clouds to explore and analyze faceted text corpora.
Analizan fallos de cortes EEUUenses. POnen las palabras que son más comunes en un documento y menos comunes en el resto (Dunning's log likehood). Ponen los tags con tamaño en gráfico de paralell coordinates. Parece interesante.

Describing story evolution from dynamic information streams.
No me gustó. Muestra como intentan detectar historias que se extienden a lo largo de diferentes artículos periodísticos.

What's being said near "Martha"? Exploring name entities in literature.
Muestra varias herramientas usando como ejemplo el análisis de literatura "rara":
* FeatureLens
* Wordle (Dunning's log likehood)
* POSvis
Necesitaban los Stop-words para analizar el texto.

VAST contest dataset use in education.
Hay un montón de datos de los diferentes VAST contest. Muestran como los usan para dar clases.

VARIAS DE LAS PRESENTACIONES DESTACARON LA NECESIDAD DE PODER IR AL TEXTO ORIGINAL QUE GENERÓ LOS DATOS QUE ESTÁN MOSTRANDO LAS HERRAMIENTAS. Posiblemente pase lo mismo con gráficos sumarizados de ataques.

Vast. Analysis Process & Graph Analytics

Connecting the dots in visual analysis.
Integran notas y flujos de trabajo en el proceso de analisis de los datos. Hacen todo un manejo bastante complicado de los flujos de trabajo (action trails?) del analista. También sugiere a los analistas que miren cosas que ya hicieron. Les preguntaron a 2 analistas sobre si les gustó el enfoque y dijeron que sí.

Capturing and supporting the analysis process.
Otro paper que explica como soportar el proceso del analista. Ejemplo con data set del VAST challenge 2008.

Evaluating visual analytics systems for interactive analysis: Deriving design principles from a case study.
Estudian como un analista usa jigsaw y otras herramientas para hacer tareas de analisis de datos.

A multi-level middle-out cross-zooming approach for large graph analytics.
Muestra una parte del grafo con una "resolución" y otra parte con otra "resolución". Cuando hace zoom-in en algún lado hace zoom-out en otro para mantener + o - constante la cantidad de cosas que muestra. Sirve para grafos de tipo small-worlds (algo parecido a esparsos). La implementación es un bolonqui porque quieren que todo sea interactivo (quién no?).
http://www.pnl.gov/wong

Visual analytics of graphs with multiple connected components.
Share-holder networks == Weighted directed acyclic graph.
Buscan estructuras comunes en estos grafos. Para eso hacen un proceso iterativo donde buscan los componentes.

Tutorial: Exploring design decisions for effective information visualization
Usando datos de las últimas 8 elecciones norteamericanas hicimos un montón de treemaps distintos analizando que se ve en cada uno, que no se ve y buscando la mejor forma de mostrar cosas.

Miércoles 14:
8:30a Keynote: Visual thinking and visual thingking tools
En esta charla Collin Ware estuvo hablando sobre como percibimos las cosas y como esto afecta como nos relacionamos con las herramientas de visualizacion. En particular mostró como se compara una interfase zoomeable con una que abre ventanitas para mostrar detalles y dio algunas formas muy simples de calcular que esfuerzo requiere hacer tareas en ambas interfaces. Usando el mismo ejemplo, también mostró porqué en otro estudio que él hizo convino usar imagenes en vez de video para mostrar movimiento. Esta charla también le da sustento teórico a la necesidad de tener más espacio disponible en el/los monitor(es).

4:15p Models and theories
A nested model for visualization design and validation
* problem
* data/op abstraction
* enc/interact technique
* algorithm
Intenta ordenar cómo saber si una visualización es "buena" o no. Divide en 4 diferentes "aspectos" a una visualización.

Conjunctive visual form.
Hace una especie de query by example pero en vez de poner un ejemplo pone un conjunto para cada dimensión (cross-filtered views, paper del año pasado).

Jueves 15:
Interaction Techniques for Selecting and Manipulating Subgraphs in Network Visualizations
Explica un montón de diferentes formas de operar sobre conjuntos de nodos en un grafo y elegir que conjunto de nodos. Están buenos pero son un quilombo.
Software: Navigator.

ActiviTree: Interactive Visual Exploration of Sequences in Event-Based Data Using Graph Similarity
Buscar patrones en eventos. ¿Puede servir para analizar logs?

“Search, Show Context, Expand on Demand”: Supporting Large Graph Exploration with Degree-of-Interest
Enfoque bottom-up para explorar grafos. Search, show context, expand on demand.
cada nodo tiene un "interes". Con eso, la query que hace el usuario y la estructura del grafo hacen una cuenta y definen el "degree of interest" (DOI) de un nodo. El contexto es el subgrafo conexo que contiene a ese nodo y tiene mayor interés. Para hacer que ande mejor un algoritmo greedy "difunden" el interés en los nodos vecinos. Lo usan para buscar fallos judiciales y como se relacionan.

A Comparison of User-Generated and Automatic Graph Layouts.
Probaron layouts generados a mano por usuarios (usando Surface, de MS) para las tareas que iban a pedir a otros participantes. Después agarraron esos layouts y 3 layouts automáticos más e hicieron que otra gente haga esas cosas. Al final, el mejor fue el force directed layout.

Smooth Graphs for Visual Exploration of Higher-Order State Transitions.
En vez de tomar A-B como "edge" se fijan en secuencias más largas (A-B-C-D, por ejemplo). Usaron esto para analizar el comportamiento de pingüinos.

Harnessing the Web Information Ecosystem with Wiki-based Visualization Dashboards.
Muestra un wiki que sirve para armar dashboards con algunos tipos de visualizaciones.

Viernes
code swarm: A Design Study in Organic Software Visualization
MOstró codeswarm.

Towards Utilizing GPUs in Information Visualization: A Model and Implementation of Image-Space Operations
Mostró un prototipo que usa la GPU para hacer visualizaciones (basado de shaders) y un programa que sirve para implementar los shaders uniendo cajas con flechas.

A Multi-Threading Architecture to Support Interactive Visual Exploration
Arquitectura para hacer visualizaciones:
1 thread de eventos
n threads para n visualizaciones
Los threads de las visualizaciones son interrumpidos cuando los datos que usan para calcular cosas cambian.
Hay un cache de cachos de dibujos y datos intermedios

Protovis: A Graphical Toolkit for Visualization
Toolkit para hacer visualizaciones en JavaScript de los autores de Flare y Prefuse
http://protovis.org

2009-10-30

Wipeando discos en el tercer mundo

Tuve que wipear un disco rígido y las herramientas de wipeo que tenía a mano no lo reconocían.
La solución:

# yes > /dev/sda

¿Se les ocurre alguna solución más corta? (wipe-golfing)

Happy hacking,
Aureliano.

2009-10-15

Reflexiones sobre las colas

Como les conté en el post anterior, estoy en VisWeek 2009. En esta conferencia hay gente de alrededor de todo el mundo, pero el grueso es de Europa y EEUU. Y hay algunas cosas que me llamaron la atención (positivamente) sobre el comportamiento de la gente por acá.
La primera cosa es que las charlas empiezan y terminan en horario (cronométricamente). El primer día de la conferencia me fui a comer y pensé que la sesión de la tarde iba a empezar algo así como media hora más tarde y en vez de eso empezó en horario y me perdí una charla. Comparado con la laxitud de la Eko, que terminó 2 horas y media después del horario planificado, es mucho mejor. Así que aprendí y empecé a llegar en horario. No como en Argentina que las cosas se van atrasando cada vez más y llegamos a situaciones ridículas donde el horario de entrada a un boliche es las 3 AM.
Pero lo que más me asombró es como se arman colas automáticamente cuando se requiere acceso a un recurso escaso. Es en todos lados. Cuando hay que entrar a una sala grande y la puerta es un cuello de botella. Cuando sacamos comida de las mesas de la conferencia. Esperando el ascensor (!). Si prestás atención, se arman colas en todos lados y todo el mundo las respeta.
¿Será realmente más eficiente hacer las cosas más ordenadamente?,
Aureliano.

2009-10-13

Visualizando

El viernes pasado partí a Atlantic City para participar de Visweek, enfocándome especialmente en Vizsec. Como el avión llegó a la mañana del sábado a Filadelfia y la conferencia empezó el domingo, dediqué parte del sábado a caminar por Filadelfia. Y me gustó bastante. Es una ciudad linda, con alma. A pesar de que me mojé porque llovía de a ratos y estaba bastante mareado porque el vuelo desde Washington fue en un avión diminuto que se movía mucho lo disfruté un montón.
A las 13:47 me tomé el tren a Atlantic City, y colapsé por falta de sueño. Alrededor de las 16:30hs llegué a Atlantic City y fui al hotel. El hotel de Atlantic City es una mole gigantesca y el casino es increíblemente grande (no me creen, fíjense).
Y la posta es que no me gusta, pero tiene todas las comodidades que hacen falta para la conferencia, que viene super-interesante. Estoy tomando notas de las charlas a las que voy, así que probablemente las ponga en el blog una vez que las muestre en Core (ellos pagan el viaje así que me parece bien que las vean primero).
Acá estoy empezando a conocer gente y hay un grupo de alemanes que son buena onda y me adoptaron. Estoy contento de que estoy aprendiendo un montón y que estoy conociendo gente super-interesante. Espero saber mucho más sobre visualización cuando termine la conferencia. En particular, estoy buscando herramientas para hacer visualizaciones que sean medianamente razonables (para una definición mía y absolutamente arbitraria de razonable). Por ahora no encontré nada :( y los investigadores con los que hablé todos implementaron sus propias herramientas para hacer visualizaciones.
Por último, cuando termine la conferencia me voy 3 días a Nueva York. ¿Qué me sugieren que haga por allá? Lo que tengo pensado es ir al Central Park, subir al Empire State, cruzar caminando el puente de Brooklin, ir a Wall Street, ir a Broadway, ir a la Quinta Avenida (y quizás hacerme el muerto donde mataron a John Lennon), tomarme el ferry a Staten Island para ver la estatua de la Libertad e ir al Museo de Arte Moderno.
Cuando pueda subo fotos de la conferencia, el viaje, etc.
Happy hacking,
Aureliano.

2009-10-06

Mi primer advisory

Encontré un XSS persistente en una aplicación de ejemplo de Jetty. Si quieren ver el advisory, pueden verlo acá.

Jetty es un container de servlets (como Tomcat) que mantiene la Apache foundation (como Tomcat) pero que intenta ser liviano (no como Tomcat).

Happy hacking,
Aureliano.

2009-10-04

Destruyendo facebook desde adentro

Update: Estuve refleccionando sobre todos estos eventos en este post.
Update: Puse todos los eventos sobre como me echaron de facebook y se niegan a borrar mis datos en este post.
Update: Mi cuenta de facebook está deshabilitada. Mandé un mail para preguntar porqué la deshabilitaron, porque hasta donde yo sé no violé ninguna de las reglas del servicio. Los voy a mantener al tanto de la respuesta.

Hola a tod@s,
quería contarles que tengo un nuevo proyecto. El mismo se llama "Destruyendo facebook desde adentro" y consiste en ver cómo hacer para que en vez de que haya una sola empresa que maneje la red social de amigos y conocidos cada persona pueda tener sus datos donde quiera e igualmente pueda relacionarse con otra gente. Un poco como el mail, se puede mandar correos a personas que tienen un proveedor de correo distinto del tuyo.
Para eso, hay algunas actividades que pueden hacer:
  • sacar la propaganda con greasemonkey (http://userscripts.org/scripts/show/13787)
  • taggear mal las fotos
  • hacer apps que hagan cagadas
  • hacer bots que molesten en facebook (¿convendrá greasemonkey o WATiR para esto?)
  • hacer una red social distribuida que use cripto de clave pública para autenticar a las personas (tipo PGP).
Si quieren adherir a mi causa, pueden hacer todo esto (o alguna otra cosa que les parezca conducente) y unirse al grupo en http://www.facebook.com/group.php?gid=141856259260

Happy hacking,
Aureliano.

2009-08-06

¡Me atacó el phishing gallego!

Leanlo, ¡no tiene desperdicio!

from Phanida_Roidoung 
reply-to allaccountuser@live.com
to
date Thu, Aug 6, 2009 at 2:20 PM
subject Dear dc.uba.ar Owner

hide details 2:20 PM (34 minutes ago)


Reply

Follow up message
Dear dc.uba.ar Owner,

We are currently carrying-out a mentaiance
process to your dc.uba.ar account, to
complete this process you must reply to
this email immediately,and enter your User
Name here (******) And Password here(*****)
if you are the rightful owner of this account.

This process we help us to fight against
SPAM MAILS.
Failure to summit your password, will render
your email address n-active from our database.
You can also confirm your email address by
logging into your dc.uba.ar
account at:http://dc.uba.ar

NOTE: You will be send a password reset
messenge in next two (2)
working days after undergoing this process
for security reasons.

Thank you form dc.uba.ar!
THE dc.uba.ar TEAM

En particular, me hace cagar de risa esta parte:
to
complete this process you must reply to
this email immediately,and enter your User
Name here (******) And Password here(*****)
if you are the rightful owner of this account.

Es la versión de mails de phishing del virus gallego.
Happy hacking,
Aureliano

2009-08-01

Algunas cosas buenas y malas de python (para mi)

Cosas buenas:

  • Duck-typing
  • Los espacios sirven para marcar bloques de código
  • Los bloques de código son elementos de primer orden del lenguaje
  • Soporte para un montón de cosas (por ejemplo pyCUDA)
  • Matches por nombre en expresiones regulares
Cosas malas:
  • Los objetos no son más que un mejunje de 2 diccionarios (el de la clase y el del objeto, sin orden)
  • Un montón de cosas están sacadas de los objetos, pero otras no. Esto lo deja inconsistente y molesto (teniendo que definir un montón de métodos mágicos de la forma __magic__)
  • Sin sintaxis buena para llamar al método de la clase padre (super, ¿dónde estás?)
  • "There is only one way to do it" salvo por las reglas para poner nombres de métodos ni clases. Por ejemplo, no queda claro si debe ser method_name, methodName o methodname (hay de los 3 en las biliotecas estándares)
  • No hay forma de definir bloques de código sin nombre (aunque con el agregado del with_statement, están bastante cerca del manejo de bloques de ruby). Los lambdas son una cosa que se queda muy corta.
  • Sintaxis especiales para demasiadas cosas (ejemplo: list comprehensions, for, while, decorators, etc)
  • Falta de separación entre strings y listas de bytes (¿Python 3000 lo arregla?, no sé)
  • Metaprogramar es complicado porque no hay bloques sin nombre y hay que definir/ llamar un montón de métodos __mágicos__.
  • Separación entre comandos y expresiones.
Happy hacking,
Aureliano.

2009-07-25

Tests en rapidito

En rapidito los tests siguen creciendo. Ahora le agregué un test al modelo de la base de datos (que por ahora tiene una sola tabla, pero espero que crezca bastante) y otro a los views y controllers (que también tienen que crecer).
Todo está agregado en el rakefile:

$ rake -T
(in /home/aure/devel/rapidito)
rake db:initial # Generate the initial pages for the wiki
rake db:migrate # Migrate the database
rake default # Run all tests
rake test # All tests
rake test:functional # Test controllers and views
rake test:lib # Library tests
rake test:model # Model tests

Sigo usando una sqlite3 en memoria para todos los tests (parece que esto paga) y para hacer los tests funcionales usé la gem rack-test como dice en la documentación de sinatra. Es impresionante como sirve esa lib tan chiquitita.
Y los tests siguen creciendo, ya van 651 líneas de código
~/devel/rapidito$ find test -name "*.rb" | xargs wc -l
26 test/lib/test_lang_hacks.rb
60 test/lib/elem_stack_test.rb
35 test/lib/rapidito_data_test.rb
187 test/lib/rapidito_html_test.rb
81 test/lib/state_test.rb
48 test/lib/nodes_test.rb
110 test/lib/tokenizer_test.rb
55 test/model/pages_test.rb
49 test/functional/start_test.rb
651 total

Happy hacking,
Aureliano

2009-07-19

rapidito en github

Hola,
puse un repo de rapidito (mi proyecto de base de datos basado en wikis) en github. Está disponible en http://github.com/aurelianito/rapidito/tree/master.
Si quieren usarlo, solo hay que hacer en el directorio clonado:


rake db:migrate
rake db:initial
rackup

Una vez que está corriendo, te conectás a http://localhost:9292 y tenés todas las instrucciones.
Tiene como requerimientos sinatra, activerecord, markaby y sqlite3 (con su gem).
Voy a ir avanzando este proyecto cuando tenga algo de tiempo. Por ahora es solo un wiki más, pero espero que se transforme en algo distinto. A medida que tenga más cosas agregadas voy a ir avisando en el blog.
Escucho sugerencias, y acepto patches ;).

Happy hacking,
Aureliano.

2009-07-16

rake sh en otro directorio

Problema: Quiero ejecutar un comando desde otro directorio en rake (por ejemplo, ejecutar un makefile que está en un subdirectorio).
Solución: Agrego al rakefile la posibilidad de ejecutar comandos en otro directorio. Para eso, al principio de mi rakefile puse:

require 'fileutils'

def sh_in_dir( dirname, *args, &block )
old_path = pwd
FileUtils.chdir( dirname )
sh( *args, &block )
FileUtils.chdir( old_path )
end


Happy hacking,
Aureliano.

Firefox remoto y local

Problema: Tengo un firefox corriendo en X11 y quiero correr otro firefox remotamente por X11 en otro host (usando el mismo display). Si lo ejecuto directamente, haciendo ssh -X -n host firefox en vez de ejecutar el Firefox en la otra máquina, abre otra ventana del firefox que ya tengo corriendo.
Solución: Usando la opción -no-remote evito que el firefox busque ventanas de firefox abiertas para abrir una ventana nueva y se ejecuta remotamente. La línea de comando entera es: ssh -X -n host firefox -no-remote.

Gracias Pedro Varangot por contarme del parámetro -no-remote

Happy hacking,
Aureliano.

2009-07-14

Logo versión 2


Esta versión del logo de rapidito se viene con texto y fondo. Y me parece que se "mueve" un poco más. De a poco voy aprendiendo a usar el inkscape.

2009-07-12

Logo para rapidito


Estoy pensando en un logo para la base de datos/wiki que estoy haciendo. ¿Qué les parece este? La idea es ponerlo arriba a la izquierda en todas las páginas y como ícono en la barra de navegación del browser.

2009-07-05

Patch en Regexp para poder usarlas como clave en un Hash

Siguiendo mi proyecto de hacer mi wiki en Ruby, encontré un comportamiento muy raro.
Generé un hash (que se llama @rules) que no tiene un elemento que tiene. O sea, @rules[@rules.keys[2]] da nil, pero @rules.values[2] devuelve el objeto asociado a la clave @rules.keys[2]. Como este hash tiene como claves un montón de expresiones regulares, me imaginé que había un problema con el hash y el eql? de Regexp, así que los implementé de nuevo y monkeypatchié.
Este es el código:

class Regexp
alias_method :old_rapidito_inspect, :inspect

def inspect
@inspect = old_rapidito_inspect if @inspect.nil?
@inspect
end

def eql?( other )
false if other.class != Regexp
self.inspect == other.inspect
end

alias_method :"==", :eql?

def hash
self.inspect.hash
end
end


Esta corrección me anduvo con la siguiente versión de ruby:
$ ruby --version
ruby 1.8.7 (2008-08-11 patchlevel 72) [i486-linux]


Espero que les sirva.
Happy hacking,
Aureliano.

2009-07-03

Upcase con acentos

En ruby no se calculan los cambios minúscula mayúscula para las letras acentuadas. Por ejemplo:

irb(main):002:0> puts "áa".upcase
áA
=> nil

Para que ande un poco mejor (y tome las letras acentuadas de un montón de lenguajes), encontré un hack que en 10 líneas de código hace que puedan pasarse a mínusculas y mayúsculas los caracteres acentuados. Usando que todas las letras minúsculas y mayúsculas acentuadas están todas juntas, armé un par de gsubs que resuelven el problema.
class String
alias_method :old_rapidito_upcase, :upcase
def upcase
self.gsub( /\303[\240-\277]/ ) do
|match|
match[0].chr + (match[1] - 040).chr
end.old_rapidito_upcase
end

alias_method :old_rapidito_downcase, :downcase
def downcase
self.gsub( /\303[\200-\237]/ ) do
|match|
match[0].chr + (match[1] + 040).chr
end.old_rapidito_downcase
end
end

Lo que hago acá es reemplazar las funciones upcase y downcase para que manejen los acentos, sumando o restando 32 (40 en octal) al segundo byte. Pongo este código en lang_hacks.rb y sale todo con fritas. Mirando el irb
irb(main):001:0> require 'lang_hacks'
=> true
irb(main):002:0> "aÁ".upcase
=> "A\303\201"
irb(main):003:0> puts "aÁ".upcase

=> nil

Espero que les sirva.
Happy hacking,
Aureliano.