Category: internet


Estado de desecho

Enlazo un post de Kriptopolis escrito por Carlos Sánchez Almeida que merece ser leído y divulgado.

http://www.kriptopolis.org/estado-de-desecho

Ayer añadí y activé un plugin que supuestamente iba a proteger mi blog de spam en forma de comentarios (además de pingbacks y trackbacks) sin la necesidad de usar métodos Captcha (era una capa de protección previa a la que ofrece Akismet). El plugin se llama Anti-Captcha, y la teoría sobre su funcionamiento era bonita (aunque no llegué a entenderla del todo pues tenía sueño y sólo quería probar qué tal iba, ahora tengo serias dudas sobre si había algo que entender).

Al parecer la instalación de dicho plugin había causado que incluso los comentarios legítimos no aparecieran en la lista de comentarios, y para postres me impedía a mi entrar al menú de administración. Mi decisión, obviamente, fue eliminar el plugin, ¿pero cómo hacerlo si no puedo acceder al panel de administración? Borrar los ficheros parece una solución buena, eso si no se piensa que su activación ha modificado la base de datos del blog y nos puede ocasionar problemas que haya referencias a ficheros inexistentes.

Así pues, la solución pasa por otro camino, casi igual de simple también. Lo primero que debemos hacer es acceder a la base de datos y visitar la tabla options (que tendrá un prefijo wp_ o el que hayáis decidido vosotros durante la instalación o tras una posterior modificación). En esa tabla debemos buscar una entrada tal que en el campo option_name tenga el valor active_plugins , vamos a editar esa entrada :) .

Si nos fijamos bien, veremos que en el campo option_value hay una cadena muy larga que empieza por “a:numero:{i:0;…“, ese primer número que nos encontramos indica la cantidad de plugins activados que tenemos en nuestro blog, dado que vamos a desactivar uno de ellos, cambiamos ese número por el mismo decrementado en una unidad, así, si tenemos 20, pondremos 19. Fijémonos ahora que para cada plugin encontramos una subcadena del estilo ‘i:numero;s:numero:”nombre_fichero_plugin.php”;‘, el número que acompaña a la i es una especie de índice que indica la “posición” del plugin dentro del blog, ahora sabiendo ésto ya podemos decidir qué hacer para eliminar el plugin de la base de datos sin que aparezcan inconsistencias en ésta. Primero de todo eliminamos la subcadena que hace referencia a ése plugin, depués debemos decrementar en una unidad todos los números que van precedidos de una i después de la aparición de la subcadena que hemos eliminado. Con ésto habremos acabado.

Lo que nos queda, si queremos eliminar cualquier rastro del plugin que nos ha amargado la existencia, es eliminar físicamente los ficheros del bicho en cuestión que tenemos en el servidor, lo podemos hacer desde el servicio ftp, ssh o desde el mismo panel de administración del blog, para gustos los colores.

Esto pretende ser un artículo corto sobre una experiencia vivida ayer, que corroboró algo que ya venían diciendo muchos bloggers de alrededor del mundo acerca de la enemistad que sienten los periodistas hacia las nuevas tecnologías, lo que está provocando que sean cada vez más innecesarios… al menos si siguen actuando como hasta ahora.

Ayer fui a la Fira de Barcelona para colaborar con Greenpeace en la campaña de presión a los políticos que se estaba ejerciendo para intentar lograr que se llegue a acuerdos serios sobre las medidas a tomar en toda la problemática del cambio climático. Desgraciadamente no se ha llegado a conclusiones importantes y todo ésto no ha servido “prácticamente para nada”.

Al margen de todo ésto, a media mañana (más bien a principios.. pues estaba allí desde muy pronto yo) apareció por allí un fotógrafo de la agencia EFE que me preguntó si por casualidad sabía qué harían los de Greenpeace durante el día, tenían la corazonada de que harían alguna protesta importante a parte de la presión en los pasillos de la Fira, y obviamente acertaban. ¿El problema? No saben aprovechar las fuentes de información. Yo tuve que decir que no sabía nada porque había estado muy desconectado éstos últimos días y le comenté que si se pasaban por el blog de Greenpeace o por su cuenta de twitter podrían descubrir algo, ¡¡por lo visto ni se les había pasado por la cabeza!!

Hoy he abierto mi cuenta de twitter y me mirado el registro de twitts… he visto que el primer twitt referente al acto del día de ayer se hizo a las 6:06 de la mañana.. a mi el fotógrafo me lo preguntó sobre las 9:45, lo que supone más de tres horas y media de retraso desde que la información se hizo pública hasta que se le pasó por la cabeza preguntar a un colaborador de greenpeace del que no obtuvo casi información alguna. Al final, después de 20 minutos de llamadas consiguió el dato. ¿No sería mejor que empezaran a modernizarse estos periodistas?

Saludos!

Wt : C++ Webtoolkit, un gran descubrimiento

Hoy he descubierto a través del planet de gnome ( planet.gnome.org -> http://jaap.haitsma.org/ -> Make AJAX Web Applications with C++ ) las librerías Wt (Webtoolkit) que permiten crear aplicaciones web AJAX con el lenguaje de programación C++. Me ha resultado muy interesante porque la velocidad de ejecución de C++ es mucho mayor que la de la mayoría de lenguajes interpretados, ya sea con simples intérpretes, con bytecodes o incluso con JITs, hay que añadir que el consumo de memoria también acostumbra a ser inferior. Otras ventajas podrían ser la facildad para usar casi cualquier librería imaginable

Por otro lado tenemos que considerar los inconvenientes: el manejo de memoria con sus punteros, la asignación y la liberación de memoria puede resultar un engorro. Y no solo eso, la sintaxis de C++ es mucho más compleja de lo que puede ser la de Python, Ruby, C#, PHP u otros lenguajes más modernos, hay que tener verdadera paciencia con él.

Voy a ver que tal es trabajar con ella, ya os diré algo :) , pero parece que promete.

Referencias

Hace unos minutos me encuentro con que mi sitio web se llenó de mierda a más no poder durante el ataque… o bién fue antes o después, el caso es que estaba infectado de Malware :s .

Pasando el ClamAV me encuentro con los siguientes ficheros infectados:

  • wp-contenty/themes/c99_Xrogue.php ( "Virus" PHP.C99-3 )
  • wp-content/uploads/2009/08/Xrogue_r57.php ( PHP Shell )

Por otro lado habían instalado un iframe en el index.php todos los ficheros index.php e index.html del sitio que llevaba a un sitio llamado odmarco.com (no vayáis, me parece que instala malware… si vais con Linux o algo del estilo simplemente vigilad las cookies y ese tipo de cosas no sea que hayan encontrado un modo de leerlas ilegítimamente a través del sitio, por los virus no creo que haya problema).

Me he enterado porque los de google han clasificado mi sitio como sospechoso (gracias a lo del iframe)… Me tendré que poner a cambiar claves de inmediato.

Actualización:

He corregido un bug que supuestamente se había corregido en la última versión de WP.. pero resulta que no. consiste en cambiar la línea:

if( empty( $key)  )

del fichero wp-login.php por la línea

if( empty( $key) || is_array( $key )  )

Por otro lado he borrado el fichero readme.html y he modificado algo más WP y el tema que uso para que no muestre el número de versión (instalé un plugin que en teoría hacía eso… pero no, otra vez anunciaban funcionalidades que no existían :s).

Skype 4.1 sobre Wine

Ésta mañana ha sido la primera vez en mi vida que he probado Skype. Dado que no tengo ni Windows ni Mac OS X en ninguno de mis ordenadores.. (solo GNU/Linux) la cosa no ha sido tan fácil como desearía… siempre con lo de la falta de soporte :s .

Es cierto que hay una versión para Ubuntu 8.04 (y para otras distros también)( … pero yo tengo Ubuntu 9.04 y hay incompatibilidades con algunos paquetes.. y tampoco tenía ganas de andar “guarreando” (aunque al final lo haya hecho pero de otra manera.. que considero menos peligrosa para el sistema). Además, por lo que tengo entendido la versión para Linux no es la 4… ni tansiquiera llega a la 3, es la 2 y seguramente no se puede utilizar todo el potencial de Skype.
La solución pasaba por instalarlo con el instalador de Windows sobre Wine … pero aunque conseguía instalar correctamente Skype, éste acababa por no funcionar cuando iniciaba su ejecución. Se limitaba a abrir la ventana principal y acto seguido aparecía un error relacionado con la imposibilidad de encotrar un recurso… que todavía no sé cual es.
Por suerte han lanzado la última actualización de Wine (la 1.1.28) que combinada con la configuración que seguidamente indicaré, ha conseguido que pueda utilizar Skype. ¿Qué se tiene que hacer? Pues ir a la configuración de Wine, y en la pestaña gráficos, en el primer marco que se llama configuración de ventanas tenemos que marcar todas las casillas y indicar las dimensiones del escritorio virtual (yo he puesto las dimensiones acordes a la resolución de mi pantalla).
Con ésto Skype funcionará (almenos sobre Ubuntu 9.04) .. sí, aparecerá un error cada vez que iniciemos el programa.. pero funcionará igual :D . (No he probado el soporte para las webcams ni la mayoría de opciones… puede que haya alguna opción del programa que lo deje tieso).
Espero que le haya servido a alguien :p , ¡Saludos!
P.D.:
Skype es de código cerrado y posiblemente está plagado de errores de seguridad, por otro lado a ésto le tenemos que añadir los errores que surgirán de su uso combinado con Wine… y los posibles errores que tal vez no sean errores… no es que tenga ganas de pensar en conspiranoias, pero siempre cabe la posibilidad de que haya puertas traseras intencionadas sin que tengamos forma de descubrirlo.

Ataque a mi blog

Hace unos minutos he recibido un ataque en mi blog bastante curioso. Alguien ha conseguido entrar y usurpar mi indentidad de administrador, me he dado cuenta cuando he recibido un email con el siguiente texto:

Contraseña perdida y cambiada para el usuario: castarco

Rápidamente he accedido a mi blog y he visto que no podía acceder, lo de la contraseña era cierto. Creo que he sido suficientemente rápido y he podido arreglarlo a tiempo… he ido al panel de administración de la web y he cambiado las tablas referentes a mi usuario para volver a poner mi dirección de email sin antes olvidarme de tomar nota de la que habían puesto allí. La dirección era ésta:

satanic.hellboy@yahoo.com

Buscando en Google he encontrado una sóla referencia a él, un artículo escrito en un documento Pdf sobre algo de pings.. está escrito en árabe persa… espero que no continúe así pues mi racismo puede verse incrementado de forma sustancial. El articulito de los cojones es el que se puede descargar desde aquí:

satanicboot.persiangig.com/document/Ping/Ping.pdf

si nos fijamos veremos que tiene todo un repositorio de programas, imágenes y documentos en

http://satanicboot.persiangig.com/

parece sin duda un buen punto de partida para investigar al sujeto… lástima lo de no saber árabe persa.

Lo que me ha llevado a su puto blog… también escrito en árabe (o algo parecido) persa:

http://www.shirazboot.blogfa.com/

La investigación continúa… no creo que pueda llegar a denunciar a éste energúmeno ante ningún tipo de autoridad pero es probable que me dedique a aprender lo suficiente como para joderlo tanto como pueda. La guerra sólo acaba de empezar.

Actualización:

Aquí podéis ver el resultado del whois que he hecho a la ip que he encontrado… parece ser de iran, cosa que concuerda con que sus textos estén escritos en árabe persa.. no sé si se ha escondido.. si me ha atacado desde el trabajo.. o desde su casa, si alguien me ayuda con éstos datos lo agradeceré.

whois 217.219.59.82

% This is the RIPE Database query service.
% The objects are in RPSL format.
%
% The RIPE Database is subject to Terms and Conditions.
% See http://www.ripe.net/db/support/db-terms-conditions.pdf

% Note: This output has been filtered.
%       To receive output for a database update, use the "-B" flag.

% Information related to '217.219.59.0 - 217.219.59.127'

inetnum:        217.219.59.0 - 217.219.59.127
netname:        ARAF
descr:          Aranik Fars Company
country:        IR
admin-c:        PH3105-RIPE
tech-c:         PH3105-RIPE
status:         ASSIGNED PA
mnt-by:         AS12880-MNT
source:         RIPE # Filtered

person:         Peyman Homayoun
address:        2nd floor , Bahar Building, Molasadra street , Shiraz ,Fars, Iran
phone:          +98 711 626 9933
e-mail:         info@aranic.net
nic-hdl:        PH3105-RIPE
source:         RIPE # Filtered

% Information related to '217.218.0.0/15AS12880'

route:        217.218.0.0/15
descr:        DCI-Route
origin:       AS12880
mnt-by:       AS12880-MNT
source:       RIPE # Filtered

% Information related to '217.219.56.0/21AS12880'

route:          217.219.56.0/21
descr:          DCI-Route
descr:          Shiraz
origin:         AS12880
mnt-by:         AS12880-MNT
source:         RIPE # Filtered

% Information related to '217.219.0.0/18AS12880'

route:          217.219.0.0/18
descr:          DCI-Route
origin:         AS12880
mnt-by:         AS12880-MNT
source:         RIPE # Filtered

% Information related to '217.219.0.0/16AS12880'

route:          217.219.0.0/16
descr:          DCI-Route
origin:         AS12880
mnt-by:         AS12880-MNT
source:         RIPE # Filtered

% Information related to '217.219.0.0/17AS12880'

route:          217.219.0.0/17
descr:          DCI-Route
origin:         AS12880
mnt-by:         AS12880-MNT
source:         RIPE # Filtered

% Information related to '217.219.32.0/19As12880'

route:          217.219.32.0/19
descr:          DCI-Route
origin:         As12880
mnt-by:         AS12880-MNT
source:         RIPE # Filtered

Ésto es todo por ahora.

Cmd Twitt

Hace tres días empecé a programar Cmd Twitt (y lo acabé ayer, bueno, supongo que todavía se puede mejorar pero no le voy a dedicar mucho más tiempo a no ser que se reporten bugs alguien tenga buenas ideas para mejorarlo). Éste programa es un simple programa de consola que permite acceder a los servicios de la popular red social Twitter.

Lo programé en Python usando la librería python-twitter, que se puede instalar mediante aptitude o apt-get en sistemas Debian o Ubuntu. Hay algunos detalles interesantes del programa sobre los que me gustaría escribir porque aprendí algunas cosillas mientras lo estaba haciendo, entre otras cosas las siguientes:

  • Internacionalización de aplicaciones Python
  • Correcto funcionamiento con diferentes codificaciones de texto
  • Gestión sencilla de ficheros de configuración
  • Poner colorines en la consola, jeje
  • Esto tiene poco que ver con la programación en sí, pero es interesante también: Trabajar con git y gitorious

Os cuelgo el código y acto seguido vamos con la explicación:

#!/usr/bin/env python
# encoding: utf-8
# -*- coding: utf-8 -*-

############################################################################
#                     --- cmd-twitt 2009.08.16 ---                         #
#                                                                          #
#   Copyright (C) 2009 by Andreu Correa Casablanca  (Original Author)      #
#                                                                          #
#   Email: castarco@gmail.com (Andreu Correa Casablanca)                   #
#                                                                          #
#   This program is free software; you can redistribute it and/or modify   #
#   it under the terms of the GNU General Public License as published by   #
#   the Free Software Foundation; either version 3 of the License, or      #
#   (at your option) any later version.                                    #
#                                                                          #
#   This program is distributed in the hope that it will be useful,        #
#   but WITHOUT ANY WARRANTY; without even the implied warranty of         #
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          #
#   GNU General Public License for more details.                           #
#                                                                          #
#   You should have received a copy of the GNU General Public License      #
#   along with this program; if not, write to the                          #
#   Free Software Foundation, Inc.,                                        #
#   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.              #
############################################################################

import ConfigParser
import getpass
import gettext
import locale
import optparse
import os
import sys
import twitter
import urllib2

# An alias that allows us to imitate the touch command
touch = lambda file: open(file, "w").close()

cmd_usage   = 'usage: %prog [option] [num_of_twits_per_timeline]'
cmd_version = '2009.08.16'

conf_dir  = os.environ["HOME"] + "/.cmdtwitt/"
conf_file = conf_dir + "user.conf"

encoding  = locale.getpreferredencoding().lower()

user = ''
pswd = ''

color = {}
color['green']   = '\033[1;32m'
color['nocolor'] = '\033[1;0m'
color['red']     = '\033[1;31m'
color['white']   = '\033[1;37m'
color['yellow']  = '\033[1;33m'

# Translate some global vars
def init_vars():
        global cmd_usage

        cmd_usage   = _(cmd_usage)

# Load the account settings
def load_config():
        global user, pswd

        cfg = ConfigParser.ConfigParser()

        try:
                cfg.readfp(file(conf_file))
        except:
              raise

        user = cfg.get ('TWIT_ACCOUNT', 'User')
        pswd = cfg.get ('TWIT_ACCOUNT', 'Pswd')

#Set the account settings
def set_config():
        global conf_dir, conf_file

        print _("Settings:")

        cfg = ConfigParser.ConfigParser()
        cfg.add_section('TWIT_ACCOUNT')

        cfg.set('TWIT_ACCOUNT', 'User', raw_input(_('\tUser: ')) )

        pswd_not_set = True
        while pswd_not_set:
                pswd1 = getpass.getpass(_('\tPassword       : '))
                pswd2 = getpass.getpass(_('\tRepeat password: '))

                if pswd1 == pswd2:
                        pswd_not_set = False
                else:
                        print _('The passwords don\'t match. Please try to write it again.')

        cfg.set('TWIT_ACCOUNT', 'Pswd', pswd1)

        if os.access(conf_file, os.F_OK) == False:
                try:
                        touch(conf_file)
                except IOError:
                        try:
                                os.mkdir(conf_dir, 0700)
                        except IOError:
                                print _('It was impossible to create the config dir.')
                                raise

                        try:
                                touch(conf_file)
                        except:
                                print _('It was impossible to create the config file.')
                                raise

        try:
                cfg.write(file(conf_file, 'w'))
        except:
                raise

# Manage connection errors
def manage_connection_error(e, code):
        if e.getcode() == code:
                print _('\tUnauthorized acces, you should set a correct username and password.')
        else:
                print _('It seems twitter is down. Try it later.')

# Sends a message to a user
def send_msg_to_user(_user):
        global user, pswd, cmd_version

        api = twitter.Api(username=user, password=pswd)

        msg = unicode(raw_input( _('Type your message:\n\t') ), encoding)[:140]

        try:
                api.PostDirectMessage(_user, msg)

        except urllib2.HTTPError, e:
                print _('Error sending the message:')

                manage_connection_error(e, 401)

# Show the user status
def show_status():
        global user, pswd

        api = twitter.Api(username=user, password=pswd)

        try:
                status = api.GetUserTimeline(user)[0].text

                print _('Your status is:\n\t' + status)
        except urllib2.HTTPError, e:
                print _('Error reading your status:')

                manage_connection_error(e, 404)

# Format the timeline to show in the console
def show_timeline(num_msgs, statuses):
        global color

        _status = statuses[0]
        print color['green']+_status.user.name + ' :\n' + color['yellow'] + _status.GetRelativeCreatedAt() + ' > ' + color['nocolor'] + _status.text + '\n'

        for status in statuses[1:num_msgs]:
                if status.user.name == _status.user.name:
                        name = color['yellow'] + status.GetRelativeCreatedAt()+' > ' + color['nocolor']
                else:
                        name = color['green']+status.user.name + ' :\n' + color['yellow'] + status.GetRelativeCreatedAt() + ' > ' + color['nocolor']

                print name + status.text + '\n'
                _status = status

# Shows the timeline of a specific twitter user
def show_usertimeline(_user, num_msgs):
        global user, pswd, color

        api = twitter.Api(username=user, password=pswd)

        try:
                statuses = api.GetUserTimeline(_user)

                print color['red'] + _user + _(' Timeline:\n') + color['nocolor']

                show_timeline(num_msgs, statuses)

        except urllib2.HTTPError, e:
                print _('Error reading the timeline:')

                manage_connection_error(e, 401)

# Shows the Home timeline
def show_friendstimeline(num_msgs):
        global user, pswd, color

        api = twitter.Api(username=user, password=pswd)

        try:
                statuses = api.GetFriendsTimeline(user)

                print color['red'] +_('Home Timeline:\n') + color['nocolor']

                show_timeline(num_msgs, statuses)

        except urllib2.HTTPError, e:
                print _('Error reading the timeline:')

                manage_connection_error(e, 401)

# Shows the Home timeline
def show_publictimeline(num_msgs):
        global user, pswd

        api = twitter.Api(username=user, password=pswd)

        try:
                statuses = api.GetPublicTimeline()

                print color['red'] + _('Public Timeline:\n') + color['nocolor']

                show_timeline(num_msgs, statuses)

        except urllib2.HTTPError, e:
                print _('Error reading the timeline:')

                manage_connection_error(e, 401)

# Send a message to twitter
def send_msg(_user):
        global user, pswd, cmd_version

        api = twitter.Api(username=user, password=pswd)

        try:
                if _user != '':
                        _user = '@'+_user+' '

                api.PostUpdate( ( _user + unicode(raw_input( _('Write your message and press Enter:\n\t') ), encoding) )[:140] )

        except urllib2.HTTPError, e:
                print _('Error sending the message:')

                manage_connection_error(e, 401)

# The main program
def main(argv=None):
        global user, pswd

        if argv == None:
                argv = sys.argv

        # Internationalization
        gettext.install('cmd-twitt')

        init_vars()

        cmd_parser = optparse.OptionParser(usage=cmd_usage, version=cmd_version, conflict_handler='resolve')

        cmd_parser.add_option('-h', '--help',    action='help',    help=_('print this help text and exit'))
        cmd_parser.add_option('-v', '--version', action='version', help=_('print program version and exit'))

        cmd_parser.add_option('-c', '--config', dest='config', action='store_true', help=_('Configure your twitter account'))
        cmd_parser.add_option('-s', '--status', dest='status', action='store_true', help=_('Shows your status'))

        cmd_parser.add_option('-p', '--publictimeline',  dest='publictimeline',  action='store_true', help=_('Shows the public timeline'))
        cmd_parser.add_option('-u', '--usertimeline',    dest='usertimeline',    action='store_true', help=_('Shows the user timeline'))
        cmd_parser.add_option('-F', '--friendtimeline',  dest='friendtimeline',  metavar='FRIEND',    help=_('Shows the timeline of a friend'))
        cmd_parser.add_option('-f', '--friendstimeline', dest='friendstimeline', action='store_true', help=_('Shows the friends timeline'))

        cmd_parser.add_option('-m', '--private-message', dest='private_msg', metavar='USER', help=_('Sends a private message to a twitter user'))
        cmd_parser.add_option('-M', '--public-message',  dest='public_msg',  metavar='USER', help=_('Sends a public message to a twitter user'))

        (cmd_opts, cmd_args) = cmd_parser.parse_args()

        if cmd_opts.config:
                try:
                        set_config()
                except:
                        print _("It was impossible to set the settings.")
                        return 1
        else:
                try:
                        load_config()
                except:
                        print _('There is not a config file, you should set your user and password in the settings option.\n')
                        cmd_parser.print_help()
                        return 1

                try:
                        num_msgs = int(cmd_args[0])
                except:
                        num_msgs = 10

                if cmd_opts.private_msg:
                        send_msg_to_user(cmd_opts.private_msg)
                elif cmd_opts.public_msg:
                        send_msg(cmd_opts.public_msg)
                elif cmd_opts.status:
                        show_status()
                elif cmd_opts.usertimeline:
                        show_usertimeline(user, num_msgs)
                elif cmd_opts.friendtimeline:
                        show_usertimeline(cmd_opts.friendtimeline, num_msgs)
                elif cmd_opts.friendstimeline:
                        show_friendstimeline(num_msgs)
                elif cmd_opts.publictimeline:
                        show_publictimeline (num_msgs)
                else:
                        send_msg('')

if __name__ == "__main__":
        sys.exit(main())

Internacionalización

Lo primero que se tiene que hacer es escribir la linia import gettext para cargar el módulo que nos ayudará en nuestro quehacer. La segunda línea (no del texto, sino referente a la internacionalización, la podemos encontrar en la función main) gettext.install('cmd-twitt') se dedica a cargar la traducción al idioma por defecto del sistema para las cadenas de texto que usa el programa. La traducción se cargará desde el directorio /usr/share/locale/[abreviatura para el lenguaje por defecto del sistema]/LC_MESSAGES/cmd-twitt.mo.

Por último (en cuanto se refiere al código) lo que se tiene que hacer para que todas las cadenas que queramos sean susceptibles de traducción a través del módulo gettext es escribirlas de ésta forma _('cadena'). La función _() es un alias para gettext.gettext().

Quedan otros pasos que no tienen mucho que ver con el código, sinó con la traducción en sí. Para empezar a traducir el programa lo primero que debemos hacer es obtener un fichero especial sobre el que se basarán las traducciones. Lo haremos así:

gettext cmd-twitt.py

Ésto generará un fichero llamado messages.po que contendrá parejas de cadenas, las originales junto con sus traducciones. Para empezar la traducción al castellano generamos un nuevo fichero a partir de messages.po que será el que contendrá la traducción en sí (messages.po lo guardamos como base para traducciones a otros lenguajes). Lo haremos como se sigue:

msginit --locale=es -i messages.po

Éste programa nos pedirá algunos datos acerca de nosotros (para que quede constancia de quienes son los traductores,  está bien que se sepa de quien es la autoría) y finalmente creará un fichero llamado es.po , que es el que nos dedicaremos a modificar.

Finalmente el fichero puede ser editado por herramientas tales como gtranslator o ktranslator para luego ser compilado a un fichero con extensión .mo que será el que irá al directorio de traducciones que mencionamos anteriormente. (Cambiando su nombre es.mo a cmd-twitt.mo)

Codificaciones de texto

Éste es un tema que ha dado mucho por saco, la verdad sea dicha. De hecho la librería python-twitter no funciona demasiado bien en este aspecto, falta que la pulan un poco (y no solo por lo de la codificación de texto, yo ya he tenido que corregir algunos bugs en la versión de mi sistema, tengo que ver ahora si es la versión de Ubuntu o la del repositorio oficial de código tiene los mismos errores).

Percibí el problema en cuanto intenté enviar mensajes con acentos a través de Cmd Twitt a Twitter, ¿Cual era el problema? El programa reventaba. Mi primer logro consistió en hacer que funcionara para mi sistema, pero luego ajusté un poco mejor el funcionamiento.. y CREO (no estoy del todo seguro) que funcionará en sistemas con diferentes codificaciones de texto.

Primera solución:

Supongamos que str es una cadena que hemos obtenido a través de la función raw_input() , la solución consistía en usar la cadena resultantde de aplicar la función unicode() a str, de la siguiente forma: unicode(str, 'utf-8') . Si no se añade el segundo argumento la función unicode() intenta leer str como si fuera ASCII y el programa revienta igualmente (que es justo lo que se hace en la librería python-twitter, un error un poco burdo, se nota que no deben hablar otras lenguas los creadores de la librería).

Ésta solución funciona en mi sistema porque usa UTF-8 para la codificación de las cadenas… pero eso no es necesariamente así en todos los sistemas.

Segunda solución:

La segunda solución pasa por el uso del módulo locale, así que tenemos que hacer un import de éste. Simplemente tenemos que sustituir la cadena ‘utf-8′ por el resultado de locale.getpreferredencoding().lower() .

Ficheros de configuración

No me extenderé mucho con ésto. He usado el módulo ConfigParser , y en cuanto a la introducción de la contraseña de usuario para twitter he utilizado un módulo llamado getpass que permite introducir caracteres sin tener que mostrarlos por pantalla. És fácil de aprender viendo el código como ejemplo.

Colorines

Lo reconozco, hay que estar un poco zumbado para dedicar una sección entera de la explicación ssólo para los colorines, qué le vamos a hacer, soy así. Aunque se reduce a algo tan simple como añadir al principio de la cadena que queremos colorear ciertas cadenas características que harán cambiar el color del texto de la consola (incluso después de haberse cerrado el programa). Ésto solo funciona para algunas consolas concretas.. no las he provado, pero aseguro que funciona con Bash, y también aseguro que no funciona en MS Windows.

Las cadenas son de la forma ‘\033[1;32m’ en la que para escoger el color sólo se tienen que cambiar los dos números del final, ésta en particular es para el color verde. Al final del artículo encontraréis un enlace para ver la tabla de códigos y sus colores correspondientes.

Git y Gitorious

Me da pereza seguir explicándolo todo como si fuera un cuento, voy al grano:

  • Crear una cuenta en gitorious.org
  • Subir una clave pública de ssh a Gitorious, si ya existe en vuestro sistema la tendréis en el fichero /home/usuario/.ssh/id_rsa.pub . En caso de no tenerla, lo podéis hacer mediante el comando ssh-keygen -t rsa .
  • Crear un proyecto y un repositorio, es todo guiado así que resulta muy sencillo.
  • Ahora toca la parte de configurar el repositorio en nuestro ordenador de trabajo. Tendremos que tener instalados ssh y git antes que nada. Los pasos que seguiremos son:
    • cd directorio_proyecto
    • git init  # Creamos el repositorio local
    • git add . # Ésto añade el directorio a la lista de ficheros del repositorio git
    • git commit -a -m "Y se hizo la luz"  # El comentario no es realmente importante (almenos en el primer commit, vamos)
    • git remote add origin git@gitorious.org:miproyecto/mainline.git # Esto nos servirá para "conectar" nuestro repositorio local con el remoto de Gitorious.org, en la documentación que encontré ponían origen en vez de origin pero luego el siguiente paso no se podía hacer de la manera "corta" que seguidamente indico
    • git push origin master # Con ésto subimos los cambios que hemos hecho al repositorio remoto, las próximas veces sólo tendremos que escribir git push

Ahora os dejo las fuentes que me han servido para informarme un poco:

Internacionalización:

Ficheros de configuración en Python:

Colorines:

Configuración de Git y Gitorious:

Hasta otra :) .

Pdf Mod

Hace una semana descubrí en el agregador de blogs Monologue (de Mono-Project) un proyecto iniciado por Gabriel Burt llamado Pdf Mod que parece avanzar a pasos agigantados y puede resultar muy útil.

Se trata de un programa diseñado para modificar PDFs escrito en C# para la plataforma Mono. Utiliza las librerías Poppler, PdfSharp, Gtk#, Cairo, y la librería Hyena de Banshee, y es precisamente ésto lo que ha permitido el rápido desarrollo que ha tenido.

Sus características actuales son:

  • Abrir documentos arrastrándolos desde Nautilus y soltándolos sobre Pdf Mod.
  • Soporta ficheros Pdf protegidos por contraseña.
  • Rotar, extraer y eliminar páginas.
  • Añadir páginas arrastrándolas desde otro documento abierto.
  • Cambiar el orden de las páginas mediante “Arrastrar y soltar”
  • Leer y cambiar las propiedades del documento.
  • Exportar imágenes.
  • Traducido a un porrón de idiomas (yo lo he traducido a castellano, y lo voy a traducir al catalán a no ser que se adelante alguien)
  • Y supongo que algunas más, ahora van por la versión 0.5 y me parece que han ido aumentando el número de versión aproximadamente cada 3 días.

Yo por mi parte lo utilizaré para unificar los Pdfs de Linux Magazine, que ofrecen todas sus revistas digitales separadas en artículos individuales… creo que será más sencillo tener sólo tantos pdfs como revistas y no tantos como artículos (ah, y podré quitar la publi para reducir peso, jeje).

Saludos :) .

Actualización: he añadido enlaces a traducciones de los tres primeros Documentos de Halloween.

Navegando por internet buscando información sobre Mono (lo que en realidad buscaba era un benchmark comparativo entre Mono y Java) he acabado encontrando unos documentos bastante interesantes elaborados por ciertos ingenieros de Microsoft que datan del año 1998 (almenos el primero, no sé de qué años son los siguientes). Estos documentos son llamados los Documentos de Halloween y tratan sobre las estrategias que planeaba seguir Microsoft para luchar contra el movimiento del Open Source ( o Software libre ).

Es interesante ver como desde Microsoft veían este movimiento, cómo pensaban atajarlo y la evolución que ha tenido todo este mundillo desde el año 1998, la verdad es que las cosas han empeorados para el gigante del software.

Aquí os dejo una traducción al castellano del primer documento (de hecho es el primero que he encontrado):

Y aquí un enlace a los documentos completos (comentados por Eric S. Raymond) (en inglés):

http://www.catb.org/~esr/halloween/

Por si alguien lo duda, parece ser que estos documentos son reales, Microsoft confirmó que esos documentos habían sido redactados en su seno. Sé que es un asunto antiguo y medio olvidado, pero como yo tenía por aquel entonces unos 10 añitos, era improbable que me hubiera enterado de algo en esa época de mi vida.

Un cabo suelto que me queda es leer un escrito de Eric S. Raymond (fue él quien publicó los Documentos de Halloween) , en la traducción se enlaza a un texto en inglés (pero han traducido el título como Cuidando la Noósfera), en cambio en la Wikipedia (en el artículo de Eric S. Raymond) lo traducen como Colonizando la Noosfera y en su página particular de la Wikipedia Colonizando la Noosfera se enlaza a una traducción que lleva por título Cultivando la Noosfera, parece que nadie se pone de acuerdo pero almenos no tendré que hacer el esfuerzo de leer en inglés, buscando en google y altavista con el primer nombre que encontré, obtuve que no había ni una sola traducción (de hecho la he encontrado sobre la marcha mientras escribía este post).

Powered by WordPress | Theme: Motion by 85ideas.