Cómo restaurar la fecha (aproximada) a las fotos de WhatsApp

Una de las cosas más curiosas que suceden hoy en día es que la gente se pelea por tener un teléfono con más megapíxeles que nadie, para luego mandar las fotos por WhatsApp y que pierdan toda su calidad.

Ironías aparte, lo que más me fastidia de todo en realidad es que WhatsApp le quita los metadatos EXIF a las imágenes.

¿Para qué sirven los metadatos EXIF?

Contienen un montón de información valiosa para los amantes de la fotografía, o para cualquiera que guste de organizarse bien su colección de fotos:

  • Cámara con que se tomó.
  • Coordenadas GPS de dónde se tomó.
  • Fecha en que se tomó.
  • Etc.

Con esos datos, puedes comparar qué tal saca las fotos tal o cual cámara o teléfono, y así no llevarte sorpresas si lo compras.

También (lo que más me interesa para esta entrada), un programa de organización de colecciones de fotos puede usar la fecha para organizarte las fotos automáticamente, o la ubicación para pintártelas en un mapa.

¿Qué pasa cuando le quito la fecha a las imágenes?

Programas como Shotwell ya no son capaces de determinar en qué fecha se tomó la imagen, así que no te la pueden organizar.

Por otro lado, resulta imposible determinar en qué fecha y hora exactas se tomaron, pero hay algo que todavía nos puede valer: la fecha de última modificación del fichero. Normalmente coincidirá con la fecha en que WhatsApp grabó la foto en tu teléfono.

Cómo grabar la fecha de última modificación en EXIF

He colgado un script llamado ctime2exif.sh que te servirá para eso.

Antes de usarlo, crea una copia de seguridad de las imágenes, por si algo sale mal. Copiarlas a otro directorio debería bastar.

Recuerda que puedes descargarlo y ejecutarlo con un solo comando:

$ curl --silent https://bitbucket.org/api/2.0/snippets/yajo/k75k/tip/files/ctime2exif.sh | bash /dev/stdin *.jpg

Ya tendrás tus fotos listas para organizar con Shotwell.

Cómo forzar la instalación de documentación con yum/dnf

La imágen oficial de CentOS para Docker viene preconfigurada para no instalar la documentación al instalar paquetes. Puedes comprobarlo con:

$ docker run --rm centos grep tsflags /etc/yum.conf

Verás que te devuelve tsflags=nodocs. La documentación de yum.conf nos explica lo que hace la opción tsflags.

Lo que queremos hacer es deshabilitarla al instalar ciertos paquetes. Por ejemplo CUPS la necesita para mostrar su index.html. Lo instalaríamos así en nuestro Dockerfile:

$ yum --assumeyes --setopt tsflags= install cups

Lo mismo sirve para dnf.

Cómo conectar a una impresora IPP desde Windows

Es posible que tengas un servidor CUPS al que quieras conectar con tu máquina Windows, pero no te sea posible. Veamos cómo hacerlo.

  1. Desde el cliente Windows, ve a Panel de control > Dispositivos e impresoras > Agregar una impresora > Agregar una impresora de red > La impresora deseada no está en la lista > Seleccionar una impresora compartida por nombre.
  2. En la caja de texto, introduce la dirección IPP en formato HTTP. Es decir, la dirección ipp://example.com/printers/impresora1 se transformará en http://example.com:631/printers/impresora1.
    • Si te da un error diciendo que no se puede conectar a la impresora, más abajo te explico cómo solucionarlo.
  3. Escoge el controlador Generic > MS Publisher Imagesetter.

¡Listo! Ya has conectado a tu servidor por IPP.

Claro, hay algunos problemas:

No puedo imprimir a doble cara

Lamentablemente, el controlador MS Publisher Imagesetter es muy básico y no puedes escoger bandejas, ni imprimir a doble cara, etc.

La solución es crear más impresoras virtuales desde CUPS que sean la misma pero con diferentes opciones por defecto, y escoger la que tenga las opciones que necesitas al imprimir.

Por ejemplo, para la impresora a color, puedes tener color-1-cara, color-2-caras, color-bandeja-1, color-bandeja-2, etc.

Esto es un rollo, pero cuando tienes problemas con un controlador (como me pasa a mí con los de HP) esto te sirve para usar un controlador más básico usando CUPS como proxy, y que sea él quien se encargue de la comunicación real con la impresora. En mi oficina, esto ha resucitado varias impresoras.

No puedo conectar a la impresora

Llegados al punto 2, puede que Windows te escupa este error:

Windows no se pudo conectar a la impresora. Compruebe el nombre de la impresora e inténtelo de nuevo. Si es una impresora de red, asegúrese de que la impresora esté encendida y de que la dirección de la impresora es correcta.
Error al agregar impresora IPP a Windows

Probablemente no esté instalado el cliente IPP en tu Windows. La ayuda de Windows nos indica cómo instalarlo:

Para instalar el Cliente de impresión en Internet, siga uno de los métodos siguientes:

  • En Windows 7: en Panel de control, haga clic en Programas y características, haga clic en Activar o desactivar las características de Windows, expanda Servicios de impresión y documentos, active la casilla Cliente de impresión en Internet y, a continuación, haga clic en Aceptar.
  • En Windows Server 2008 R2: en el Administrador del servidor, haga clic en Agregar características, active la casilla Cliente de impresión en Internet y, a continuación, haga clic en Aceptar.

Ahora reinicia el servicio de impresión. Puedes hacerlo desde services.msc o directamente desde la línea de comandos ejecutando:

sc stop spooler && sc start spooler

Por último, vuelve a repetir el tutorial y ahora debería dejarte seguir.

Si aún así no te deja, es posible que haya alguna política de seguridad bloqueando el servidor. Intenta visitarlo desde Internet Explorer (sí, has leído bien), y si te da mensajes de error por zona de confianza, agrégalo a los sitios de confianza.

Cómo usar GVFS para montar unidades de red Samba indicando usuario, dominio y contraseña; o cómo emular entrada de datos manual automáticamente con expect

Un título bien largo, pero es lo que vamos a hacer

Problema

Tengo una unidad de red llamada share en mi servidor de datos de red llamado host que quiero montar usando Samba y GVFS automáticamente, pero al ejecutar:

$ gvfs-mount smb://host/share

Siempre me pide lo siguiente:

User [tu_usuario]:
Domain [WORKGROUP]:
Password:

Y no tengo forma de automatizar eso.

Solución

Expect es un intérprete de órdenes (estilo bash) diseñado para emular a un usuario metiendo datos manualmente. Lo usaremos para montar las unidades automáticamente:

#!/usr/bin/env bash

# Montar unidades emulando a un usuario que mete datos
function mount_share {
    expect <<END
        spawn gvfs-mount $1
        set timeout -1
        expect User
        expect :
        send $2\r
        expect Domain
        expect :
        send $3\r
        expect Password:
        send $4\r
        wait
END
}

# Montar nuestra unidad de red
mount_share smb://host/share usuario dominio contraseña

Cómo crear vistas en Odoo con YAML

La documentación de Odoo 8.0 explica cómo crear ficheros de datos XML y CSV, pero se olvida de explicar los YAML, tal como hacía la antigua documentación de Odoo 6.0.

En cualquier caso, no he encontrado en ninguna parte cómo crear vistas usando YAML (técnicamente, combinándolo con XML), así que aquí va un ejemplo que enseguida entenderá todo aquel que esté acostumbrado a crear vistas en XML.

Esto sería el XML, extraído del fichero openacademy/views/openacademy.xml del tutorial:

<?xml version="1.0" encoding="utf-8"?>
<openerp>
    <data>
        <!-- Full id location:
             action="openacademy.course_list_action"
             It is not required when it is the same module -->

        <!-- session form view -->
        <record model="ir.ui.view" id="session_form_view">
            <field name="name">session.form</field>
            <field name="model">openacademy.session</field>
            <field name="arch" type="xml">
                <form string="Session Form">
                    <sheet>
                        <group>
                            <field name="name"/>
                            <field name="start_date"/>
                            <field name="duration"/>
                            <field name="seats"/>
                        </group>
                    </sheet>
                </form>
            </field>
        </record>

        <record model="ir.actions.act_window" id="session_list_action">
            <field name="name">Sessions</field>
            <field name="res_model">openacademy.session</field>
            <field name="view_type">form</field>
            <field name="view_mode">tree,form</field>
        </record>

        <menuitem id="session_menu" name="Sessions"
                  parent="openacademy_menu"
                  action="session_list_action"/>
    </data>
</openerp>

Y esto es exactamente lo mismo en YAML (lo guardaríamos como openacademy/views/openacademy.yml):

# Full id location:
# action="openacademy.course_list_action"
# It is not required when it is the same module

# Session form view
- !record {model: ir.ui.view, id: session_form_view}
    name: session.form
    model: openacademy.session
    arch: |
        <form string="Session Form">
            <sheet>
                <group>
                    <field name="name"/>
                    <field name="start_date"/>
                    <field name="duration"/>
                    <field name="seats"/>
                </group>
            </sheet>
        </form>
    
- !record {model: ir.actions.act_window, id: session_list_action}
    name: Sessions
    res_model: openacademy.session
    view_type: form
    view_mode: tree,form

- !menuitem {id: session_menu, 
             name: Sessions
             parent: openacademy_menu
             action: session_list_action}

Como ves, al crear la vista al final hay que acabar usando XML, pero desde luego el resto del documento se beneficia bastante de la sintaxis YAML.

La pega es que será complicado que encuentres un editor de texto que te resalte la sintaxis de XML y YAML en el mismo documento. Quizá convenga usar XML para las vistas y YAML para lo demás.

Por cierto, los elementos tipo !record son constructores personalizados de Odoo (es decir, no es YAML estándar). Consulta el fichero yaml_tag.py para ver todos los que hay.

La lentitud de la encriptación en Android

Problema

Mi tableta estaba encriptada e iba soporíferamente lenta.

Me extrañaba porque tengo un móvil con un hardware casi idéntico que va muy fluido, así que instalé en ambos Geekbench 3, que analiza el rendimiento del procesador y la RAM. En ambos terminales la puntuación fue casi idéntica (bueno, la velocidad de RAM en el móvil era el doble, pero es normal porque tiene el doble de RAM).

Diagnóstico

Caí en la cuenta de que la tableta estaba encriptada y el móvil no, así que instalé A1 SD Bench en ambos y pude comprobar que, donde el móvil daba una velocidad de lectura/escritura de 7MiB/s y 17MiB/s respectivamente, la tableta daba 7MiB/s y 6MiB/s.

Solución

Decidí desencriptar la tableta (hay que resetearla para ello) y ver si era ahí donde estaba el cuello de botella, y parece que sí, porque ahora me da 33MiB/s y 12MiB/s, es decir el 200% al escribir y el 550% al leer.

Conclusión: si piensas encriptar tu Android, evalúa su velocidad antes y después, y piensa si te vale la pena.

Cómo evitar que journald use demasiado espacio en disco duro

Para conocer cuánto espacio están ocupando los registros en tu sistema:

$ journalctl --disk-usage

Si te parece demasiado lo que te dice, reduzcámoslo por ejemplo a 250MB. Para ello, añade o modifica esta línea en /etc/systemd/journald.conf:

SystemMaxUse=250M

Ahora reiniciaremos el servicio para que limpie los logs antiguos:

# systemctl restart systemd-journald.service

Cómo conectar remotamente a mi escritorio GNOME 3

Problema

Antiguamente podíamos configurar conexiones a nuestro escritorio Linux a través del protocolo FreeNX o su descendiente directo X2Go, pero poco a poco va haciéndose más imposible, ya que los escritorios completos modernos (GNOME 3, KDE, Cinnamon) utilizan ciertas extensiones de X11 (GLX, si no me equivoco) que no son compatibles con esos protocolos. En cualquiera de los casos, al ser ambos protocolos basados directamente en X11, y teniendo en cuenta que en breve X11 va a empezar a desaparecer en favor de Wayland y Mir, deduzco que NX y derivados también tenderán a desaparecer, ya que ni son ni serán compatibles.

Solución propuesta

Visto lo anterior, recurriremos al protocolo VNC, que es bastante más pobre que los otros mencionados, ya que es inseguro, no soporta autenticación por clave pública, no permite iniciar sesión (tan solo se conecta a una sesión que ya esté abierta) y ofrece peor compresión.

¿Por qué recurrimos a él entonces? Parece que es el que soporta oficialmente GNOME 3 y el más fácil de configurar, y dentro de lo que cabe se puede hacer más seguro pasándolo por un túnel SSH.

Cómo configurarlo

Servidor VNC

Para empezar, vamos a Configuración > Compartir > Compartición de la pantalla, y la activamos:

Activar el servidor VNC en el puerto 9000
Activar el servidor VNC en el puerto 9000

 

Como podéis observar en la foto, nos da la opción de usar una contraseña o no:

  • Si estableces una contraseña, podrás conectar siempre que quieras si te la sabes.
  • Si no pones contraseña, al solicitar conexión aparecerá en el escritorio un cartel avisando al usuario local de que alguien quiere conectarse remotamente a su escritorio, y dándole la opción a aceptar o rechazar dicha conexión.

Como en nuestro caso se supone que no habrá nadie sentado en la máquina cuando queramos conectarnos desde fuera, optaremos por poner una contraseña.

Esto pone a escuchar el servicio VNC en el puerto 9000, pero este puerto no lo publicaremos en el router.

Servidor SSH

A continuación activaremos el inicio de sesión remoto, que es como llaman al servidor SSH:

Activar el servidor SSH en el puerto 22
Activar el servidor SSH en el puerto 22

Esto pone a escuchar el servidor SSH en el puerto 22.

A continuación, tendrás que ponerle una IP fija a tu ordenador y configurar tu router para que redirija un puerto público (puede ser el 22 o cualquier otro) al puerto 22 de tu ordenador.

Puesto que cada red y cada router es diferente, asumiré que sabes cómo realizar estos pasos o cómo usar un buscador de Internet. Si no dispones de una IP pública fija, tal vez te interese también buscar información sobre DNS dinámico. Quizá te interese también saber cómo bloquear los ataques por SSH, que sin duda empezarás a recibir.

Para este ejemplo, supondremos que redireccionamos el puerto 22000 del router al puerto 22 del ordenador, y que hemos habilitado el inicio de sesión por clave pública.

Cliente Remmina

Hecho todo esto, ya tenemos el equipo servidor listo para recibir conexiones remotas (siempre que se deje la sesión local abierta, recuerda). Ahora hay que ir al otro ordenador desde el que te conectarás (el que hará de cliente) y configurarlo. Usaremos Remmina; si prefieres otro, configúralo igual y ya está.

Primero hay que instalarlo. En Fedora 21 es:

# dnf install remmina-plugins-vnc

Creamos una nueva conexión como la siguiente:

Configurar la conexión VNC. La contraseña es la que hemos puesto antes al compartir el escritorio.
Configurar la conexión VNC. La contraseña es la que hemos puesto antes al compartir el escritorio.
Configurar el túnel SSH para la conexión VNC. Hay que usar el puerto que hayas abierto en tu router (si es el 22, basta con marcar la opción "Mismo servidor en el puerto 22"). Si no has puesto autenticación con clave pública, marca la opción "Contraseña".
Configurar el túnel SSH para la conexión VNC. Hay que usar el puerto que hayas abierto en tu router (si es el 22, basta con marcar la opción “Mismo servidor en el puerto 22″). Si no has puesto autenticación con clave pública, marca la opción “Contraseña”.

Pulsa Conectar y listo.

Conclusión

Es lamentable que sigamos dependiendo de VNC para estos menesteres. Espero que, con la llegada de Wayland y los avances del equipo de FreeRDP, pronto veamos una opción por defecto para compartir por RDP, que parece que hoy en día es la única alternativa digna, pero en Linux está bastante atrasada.

Corregir error “Could not get content for X defined in bundle ‘X'” en Odoo 8.0

Problema

Hoy tras actualizar mi Odoo, me he encontrado estos errores al entrar:

Could not get content for /website/static/src/css/bootswatch/spacelab.min.css defined in bundle 'website.assets_frontend'.
Could not get content for /website/static/src/css/bootswatch/spacelab.fix.css defined in bundle 'website.assets_frontend'.
Could not get content for /website/static/src/css/website.css defined in bundle 'website.assets_frontend'.
Could not get content for /website_mail/static/src/css/website_mail.css defined in bundle 'website.assets_frontend'.
Could not get content for /website_blog/static/src/css/website_blog.css defined in bundle 'website.assets_frontend'.

Un error un tanto extraño.

Diagnóstico

Revisando los registros, encontré este error:

ERROR ? werkzeug: Error on request:
Traceback (most recent call last):
  File "/usr/lib/python2.7/site-packages/werkzeug/serving.py", line 177, in run_wsgi
    execute(self.server.app)
  File "/usr/lib/python2.7/site-packages/werkzeug/serving.py", line 165, in execute
    application_iter = app(environ, start_response)
  File "/usr/lib/python2.7/site-packages/openerp/service/server.py", line 281, in app
    return self.app(e, s)
  File "/usr/lib/python2.7/site-packages/openerp/service/wsgi_server.py", line 216, in application
    return application_unproxied(environ, start_response)
  File "/usr/lib/python2.7/site-packages/openerp/service/wsgi_server.py", line 202, in application_unproxied
    result = handler(environ, start_response)
  File "/usr/lib/python2.7/site-packages/openerp/http.py", line 1274, in __call__
    self.load_addons()
  File "/usr/lib/python2.7/site-packages/openerp/http.py", line 1293, in load_addons
    m = __import__('openerp.addons.' + module)
  File "/usr/lib/python2.7/site-packages/openerp/modules/module.py", line 79, in load_module
    mod = imp.load_module('openerp.addons.' + module_part, f, path, descr)
  File "/opt/odoo/extra-addons/l10n-spain/account_balance_reporting_xls/__init__.py", line 8, in <module>
    from . import report
  File "/opt/odoo/extra-addons/l10n-spain/account_balance_reporting_xls/report/__init__.py", line 7, in <module>
    from . import reporting_xls
  File "/opt/odoo/extra-addons/l10n-spain/account_balance_reporting_xls/report/reporting_xls.py", line 5, in <module>
    import xlwt
ImportError: No module named xlwt

Al parecer, tras actualizar los módulos comunitarios del paquete l10n-spain, se introdujo una nueva dependencia (xlwt) que no ha quedado satisfecha. Como ese módulo no se ha cargado, el proceso se ha interrumpido y no ha llegado a cargar el módulo website, que es en el que se encuentran los CSS que me daban error al principio.

Solución

# yum install python-xlwt

Evidentemente, dependiendo de cuál sea el fallo en tu Odoo, deberás instalar un paquete u otro. Sigue mis pasos y llegarás en seguida al problema.

Por ejemplo, en mi caso, además de esto tuve que añadir el repositorio comunitario reporting-engine.