jci's blog

Earthquakes can't stop the rock

Escrito el 08/01/11 12:38:50 pm por jci

It's Gotta Be the Ugliest Hack I Have Ever Done

Categories: GNU/Linux, Programacion, Hacks, Ubuntu

[ debido a algun NDA, no puedo revelar ciertos detalles, pero contare los importantes ]

Intentando mejorar ciertos aspectos de [ censura ], se me ocurrio implementar un sistema de alarmas rapido, eficaz, economico y audaz. Ahora, el asunto es que jugar con protocolos de comunicacion no es uno de mis fuertes pero si lo es el [ censura ] y tambien [ censura ]. Despues claro de intentar hacer funcionar rancios programas hechos en C o Python.

IMG_3489
Snowy day here at the end of the world

De pasadita, encontre un bug que afecta a finch y pidgin, pero los contare otro dia. Ya esta el bug en Launchpad :B

A lo que ibamos.

Empece primero usando XMPP, ya que [ censura ] y ya estaba corriendo, asi que fue mi primera eleccion. Debido a que el servidor estaba corriendo con [ censura ] y no dejaba conectarse por otra cosa que no fuera pidgin...

Despues de reintentos varios donde tuve cosas como hostMistmatch y cepillandome un par de bibliotecas en Python decidi abortar mision. Aunque claro, instalando un XMPP server local, incluso con negociacion con TLS, andaba de peluches.

IMG_1325
Some friends call this a quick action photo

Recorde que hace tiempo me mostraron que Pidgin era compatible con Bonjour. Bonjour (antiguamente Zeroconf) permite mostrar servicios a traves de la red usando (inserte su magia favorita aqui) y los programas que sean capaces de entender estos mensajes, pues los interpretan.

Veamos un ejemplito, sin censura, claro.

Resolved service:
  fullname   = boba\032\09100\05821\0589b\0586a\058a6\058a6\093._workstation._tcp.local.
  hosttarget = boba.local.
  port       = 9
Service added; resolving
Resolved service:
  fullname   = lacantina\032\09100\05821\0589b\05872\058ac\05828\093._workstation._tcp.local.
  hosttarget = lacantina.local.
  port       = 9

Que carajos es esto? Pues bien, un mensaje que indica solamente la presencia de una workstation en la red local. Es todo.
Ah, lo interesante. Es manejado todo por debajo del capo usando Avahi. Si no saben que es, apliquense un google. Y 1000 internets menos.

IMG_3392
Dessert

Todos los que son hosttarget son las maquinas que mDns resuelve de forma economica y audaz. Si quieren mirar la forma de resolucion de estos nombres...

jci@socrates:~/Build/pybonjour-1.1.1/examples$ more /etc/nsswitch.conf 
# /etc/nsswitch.conf
#
# Example configuration of GNU Name Service Switch functionality.
# If you have the `glibc-doc-reference' and `info' packages installed, try:
# `info libc "Name Service Switch"' for information about this file.

passwd:         compat
group:          compat
shadow:         compat

hosts:          files mdns4_minimal [NOTFOUND=return] dns mdns4 # <- LOOKIE HERE!
networks:       files

protocols:      db files
services:       db files
ethers:         db files
rpc:            db files

netgroup:       nis

Cierto. Primero mira /etc/hosts, de ahi usa mDns para la resolucion de hosts. Si no lo encuentra, usa una version mas completa. Y de ahi mDns en IPV4. Nota : este detalle de IPV4 es super importante en un problema que tuve haciendo pruebas.

Ahora miremos lo que necesitamos : Bonjour. Afortunadamente, este servicio tambien se registra en la red con el nombre de "presence". Y como Bonjour tambien identifica el tipo de conexion (tcp, en este caso), lo unico que nos queda es preguntar en la red local quienes tienen corriendo el servicio presence.

Y voila!

jci@socrates:~/Build/pybonjour-1.1.1/examples$ python browse_and_resolve.py _presence._tcp
Service added; resolving
Resolved service:
  fullname   = jci\064socrates._presence._tcp.local.
  hosttarget = socrates.local.
  port       = 5298
Service added; resolving
Resolved service:
  fullname   = user1\064lacantina._presence._tcp.local.
  hosttarget = lacantina.local.
  port       = 5298
Service added; resolving
Resolved service:
  fullname   = user2\064muldernix._presence._tcp.local.
  hosttarget = asterix.local.
  port       = 5298

Asi que lo que me queda : conectarme directo a cada uno de esos "hosts" (nota : los .local son agregados de la resolucion de mDns) y lanzarles un mensaje.

IMG_3376
Weird collection of weird toys

Spamming time!

#!/bin/bash

for i in `cat listahosts.txt`
do
      echo '<message type="chat"><body>'Feed me a stray cat'</body></message> ^] quit' \ 
      | telnet $i 5298
done

Les dije que el hack era algo feo.

Por supuesto que el mensaje de ejemplo de aca es bastante burdo. El real mensaje que debo enviar es [ censura ].

Si, yo tambien odio los NDA. Pero a fin de cuentas, lo importante no esta censurado. [ censura ]. Creo.

IMG_3431

That's not fog. It's a freaking cloud

Ah, y el problema que tuve con IPV4. Pues bien, al usar Bonjour con Pidgin, si esta habilitado IPV6, va a intentar resolver...con errores. Deshabilitar IPV6 con

# echo 1 > /proc/sys/net/ipv6/conf/all/disable_ipv6

Dije que esto se veia feo.

5279 views » Send feedback »

Escrito el 05/23/11 02:40:36 pm por jci

After all this bullshit, something must come to a good end

Categories: Web Link Blog, GNOME, GNU/Linux, Programacion, Hacks

Hace un tiempo atras, Claudio subio un script en Python que permite esto:

jci@rock:~/Photos/l$ ls
IMG_1190.JPG  IMG_1191.JPG  IMG_1192.JPG  IMG_1193.JPG
jci@rock:~/Photos/l$ ~/scripts/picsdir.py .
IMG_1191.JPG
creating dir ./2011-05-23
./2011-05-23
IMG_1192.JPG
./2011-05-23
IMG_1193.JPG
./2011-05-23
IMG_1190.JPG
./2011-05-23
Traceback (most recent call last):
  File "/home/jci/scripts/picsdir.py", line 66, in <module>
    print sum(getsize(join(root, name)) for name in files)
NameError: name 'files' is not defined
jci@rock:~/Photos/l$ ls
2011-05-23

Pero desde que me dio por actualizar a Natty...

jci@socrates:~/Photos/untitled folder 2$ ~/scripts/picsdir.py  .
IMG_1101.JPG
Traceback (most recent call last):
  File "/home/jci/scripts/picsdir.py", line 64, in <module>
    start=Main(sys.argv)
  File "/home/jci/scripts/picsdir.py", line 62, in Main
    move_smartly (filename, dir_in, dir_out)
  File "/home/jci/scripts/picsdir.py", line 29, in move_smartly
    image = pyexiv2.Image(image_file)
AttributeError: 'module' object has no attribute 'Image'

Nada que un hack no pueda hacer :-)

#!/usr/bin/env python

# Copyright (C) 2008  Claudio Saavedra 
# modified by jci :-)
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see .

import sys
import pyexiv2
import os
import os.path
import shutil
import mimetypes

def move_smartly(file, dir_in, dir_out):
    image_file = os.path.join (dir_in, file)
    image = pyexiv2.ImageMetadata(image_file)
    image.read()
    try:
    	date_creation = image['Exif.Image.DateTime']  
    except:
	print "i'm ignoring this"
        return
    print date_creation
    str_date = date_creation.value.strftime('%Y-%m-%d')
    target_dir = os.path.join (dir_out, str_date)

    if (not os.path.exists(target_dir)):
        print "creating dir " + target_dir
        os.mkdir(target_dir)
    print target_dir
    shutil.move (image_file, target_dir)


def Main(args):
    if (len (args) < 1):
        sys.exit("not enough parameters")
    dir_in = args[1]
    if (len (args) < 3):
        dir_out = dir_in
    else:
        dir_out = args[2]

    for root, dirs, files in os.walk (dir_in):
        for f in files:
	    print f
            filename = os.path.join (root, f)
            if mimetypes.guess_type(filename)[0] == 'image/jpeg':
                move_smartly (filename, dir_in, dir_out)

start=Main(sys.argv)

print sum(getsize(join(root, name)) for name in files)
2851 views » Send feedback »

Escrito el 01/14/09 10:39:15 am por jci

Damn, now that's crazy

Categories: GNU/Linux, Programacion

Sabian que QT ya posee un modelo multiple de licencias?

Hasta hace unos dias, QT se distribuia con dos licencias, GPL para aplicaciones no comerciales, y comercial (duh). Ahora, agreguenle LGPL. O sea, aplicaciones comerciales pueden ahora enlazar con QT sin tener que comprar una licencia.

A elegir su veneno! Esto se esta poniendo interesante :-D

4773 views » 1 feedback »

Escrito el 08/13/07 11:34:55 pm por jci

When you realized you needed this more than me, it's a little too early

Categories: GNU/Linux, Misc Crap, Programacion

Odie Python hasta hace unos 20 minutos atras.

Siempre he tirado las mejores focas contra Python. No quise asumirlo como lenguaje, ni tampoco lo aprendi lo suficiente para hacer un "hola mundo". De hecho, durante una charla en Valparaiso, si no fuera por Eduardo, no habria podido mostrar un ejemplo en vivo de un script para una ventanita con un ... "hola mundo".

De ahi que he mirado con mejores ojos al lenguaje ese.

Penguined!

Bueh, en tema relacionado, por fin pude salir del limbo de la programacion abierta y contratar cable. Asi que ahora debo anotar las horas en que mis series favoritas o peliculas del mes van a salir.

Diablos, no tengo la revista del cable. Asi que tendre que empezar a buscar la programacion en la pagina de VTR. Y ahi es donde la cosa se torna excesivamente incomoda.

Por ejemplo, si quiero ver que estan dando en Cinemax, debo seleccionar la señal, la region, la comuna (!) y el canal. Y de ahi, recien el boton "Buscar". Se torna mas color de hormiga cuando hago mas de una busqueda, o equivocadamente apreto el boton "Volver". Despues de unos 20 minutos, ya estaba podrido. Asi que pense en usar el musculo cerebral para hacer algo rapido, sencillo, y que un bipedo como yo entendiera.

Manos a la obra.

River Raid

La pagina de programacion de VTR contiene Ajax. Cuando seleccionas el tipo de señal, automaticamente carga un selector de regiones. De ahi el selector de comunas. Y el selector de canales. Para peor, no hay cosa que mas odie en este mundo que Ajax. Puedes escudriñar muy poco dentro de el, a no ser que ya te sepas Javascript o manejar XmlHTTPRequests o similares. No, no se una pizca de Ajax. Y no quiero andar aprendiendo a estas alturas.

Afortunadamente, una extension de Firefox me ayudo en la tarea : GreaseMonkey. Pero hay que instalar ademas XMLHTTPRequest Debugging.

Una vez instalado y funcionando con el dominio, pude ver como se pasaban las variables entre las paginas que cargaba. Mejor aun, el request completo. Una pagina de prueba y funciona. Excelente.

Botella de Coca Cola

Empece programando un pequeño script en PHP para mandar las peticiones via POST. Pero el muy cochino no tenia ninguna facilidad para poder inyectar de forma "facil" (digamos, a prueba de humanos) las variables a pasar al script del otro lado del cable.

Aparecio Perl pero dije "y por que no Python?".

Encontre un pequeño ejemplo de una rutina en POST. Asi que un par de modificaciones, bastante cafe de por medio y una tarde lavando ropa nos da como resultado...

...Un lindo script que guarda una pagina completa con la programacion del dia.

Pedro y Ricardo

Necesitan ademas este archivo : MultipartPostHandler.py que hay que colocar en el mismo directorio del script grab1.py.

Se genera un archivo programacion.html.

Nota : solo funciona para Santiago. Aun no he decifrado como es la disponibilidad de las regiones. Tampoco para la señal premium.


Update: Tengo un ejemplo del posible RSS que se puede generar. No voy a tirar el script aun en linea, por que tengo que arreglarlo. Esta charchamente hecho el rss, pero que va.

Aqui los feeds de VTR Cable Full, actualizados diariamente :)

Insomnio es la palabra del dia.

1080 views » 4 feedbacks »

Escrito el 04/08/07 02:48:24 am por jci

The date there is a little funny...

Categories: Tarros, GNU/Linux, Programacion, Blogging

jci@marvin:~/fotos$ find | grep g$ -i | wc -l
10116

Todo empezo por ahi. Como diablos se mantiene una coleccion de al menos unas 10000 fotos? O quizas mas? Y con las fechas correctas?

Siempre he tenido pesima memoria. Sobre todo para acordarme en que he eventos he estado, como asistente o expositor. Aparte de tambien algunos carretes con amigos, photoshoots y otras. Asi que como dicen por ahi, "la foto es la mejor maquina del tiempo que existe"

Bueh, creo que conocen F-spot. Asi que empece la titanica tarea de agregar toda esa cantidad de imagenes ahi. Aunque digamos que no se porta tan mal como crei (excepto por unos errores bien raros de Xlib).

Claudio Saavedra
Showing the tools of the trade

Hace ya un par de años, compre una Sony Cybershot P72. Pero olvide un pequeño detalle al momento de comprarla : colocarle la fecha correcta a la camara. Asi que estuve mas menos unos 5 meses sacando fotos con 1 año y 12 horas de diferencia. Y esos se ven en F-spot, ya que las ordena de acuerdo a algunos parametros que pueden o no estar en el archivo:

  • Fecha de creacion del archivo
  • Exif metadata : Date and Time (0x0132)

El primero siempre va a existir, pero el segundo no.

Codec?!
Damn LoopholeDamn LoopholeDamn LoopholeDamn Loophole...

Antes de la Cybershot, tenia una camara bastante humilde, marca Benq (que aun debe funcionar). No tiene tan buena resolucion como la Cybershot (debe ser de 1.3 Megapixeles), pero era lo mas portatil posible (se podia echar hasta en el bolsillo interior de una chaqueta). El unico inconveniente de la camara es que no guardaba metadatos en el archivo de imagen. Bueh, la camara con suerte tenia un display indicando la cantidad de fotos restantes, y si ibas a sacar con flash, asi que ni modo que guardara esa info.

Exif (Exchangeable Image Format) contiene una coleccion de metadatos bastante interesante. Por ejemplo, la velocidad de obturacion, exposicion, foco, etc. Si han usado Flickr alguna vez, se daran cuenta que al ver la imagen, contiene la descripcion de la imagen, junto con la camara y otros datos que son mas importantes para alguien que sabe que significan.

Un ejemplo es esta imagen (obtenida sin permiso del autor). La imagen dice que fue tomada el "2007:04:07 23:29:53".

Ahora, como diablos corrijo el famoso problema de fotos tomadas con la Cybershot, con la famosa diferencia horaria, para que f-spot pudiera ordenarlas bien?

Tuve varias opciones.

La primera fue usar exif para detectar el problema de la fecha:

jci@marvin:/tmp/f$ exif -m -i dsc00001.jpg | grep 0x0132
0x0132 2003:07:23 00:00:30

Llegue de casualidad a jhead para alterar el valor:

jci@marvin:/tmp/f$ jhead -ts2004:07:23-12:00:30 dsc00001.jpg
Modified: dsc00001.jpg

Ahora veamos como quedo..

jci@marvin:/tmp/f$ exif -m -i dsc00001.jpg | grep 0x0132
0x0132 2004:07:23 12:00:30

Olvide si un detalle antes : hay mas tags de Exif que indican la fecha y hora.

jci@marvin:/tmp/f$ exiftran -d dsc00001.jpg | grep Date
0x0132 Date and Time 2004:07:23 12:00:30
0x9003 Date and Time (original) 2004:07:23 12:00:30
0x9004 Date and Time (digitized) 2004:07:23 12:00:30

Hasta el momento se ve correcto.

La unica lata : debia parsear el valor de la imagen, ver si estaba en el 2003 y corregir la fecha. Para 10 imagenes, manualmente, no era problema. Pero me tope con casi 500 imagenes. E intentar hacer un script en Perl o en Bash habria sido una real lata.

Tomas (y juguete)
Photogenic Dog

Pero la empece.

Antes de terminar, me tope con esta interesante pieza de joyeria : Exiftool. Permite hacer transformaciones bastante buenas sobre los metadatos. La que mas me gusto? Y de acuerdo a la documentacion:

Have you ever forgotten to set the date/time on your digital camera before taking a bunch of pictures?

Bingo! No debia por que reinventar la rueda. Asi que a bajar, ni siquiera se instala, y funciona de maravilla.

Asi que mi problema se pudo resolver con este sencillo comando:

jci@marvin:~/code/Image-ExifTool-6.85$ ./exiftool "-AllDates+=1:0:0 12:00:00" directorio


Life can be peaceful again

Eso fue solo con las imagenes que tenian metadatos. Las que no, simplemente leer detenidamente el man de touch...

jci@marvin:~/fptos/2003/$ touch -d "18 Oct 2003 00:00:00" file.jpg

Claro, la lata va tambien en pillar la fecha correcta. Pero solo eran 4 imagenes que estaban datadas de 1999 (!), del Encuentro Linux 2003.

De que sirve tener todas las fotos en un solo lugar? Aparte de borrar las que realmente son innecesarias, permite encontrar joyas de la fotografia.

Como esta (no la saque yo, pero fue durante unas charlas en La Serena)

Disfraz
That hand was not supposed to be there.

1066 views » 2 feedbacks »

Escrito el 02/23/05 08:38:43 pm por jci

:: Next >>

Acerca de este glob

On the Sixth Day, there was a Running Man looking for a Predator to stop a Raw Deal with a Commando. Only True Lies were said. But nao, Junior is about to get Twins, with the help of a Kindergarden Cop. That will be the Terminator of all struggles.

Archives