domingo, abril 24, 2016

Como quitar atributos extendidos en OSX (com.apple.quarantine)

Recientemente al bajar una nueva plantilla y descomprimirla en un nuevo directorio, aparece que con un '@' a un lado de sus permisos de archivo.
jupabeans at TankerMini in ~/workspace/theme
$ ls -ls

total 0

0 drwxr-xr-x     4 jupabeans  staff   136 Apr 24 22:07 .

0 drwxr-xr-x     7 jupabeans  staff   238 Apr 24 21:56 ..

0 drwxrwxrwx@    6 jupabeans  staff   204 May 28  2015 README

0 drwxrwxrwx@  121 jupabeans  staff  4114 May 28  2015 theme
jupabeans at TankerMini in ~/workspace/theme
$ ls -@ls

total 0

0 drwxr-xr-x     4 jupabeans  staff   136 Apr 24 22:07 .

0 drwxr-xr-x     7 jupabeans  staff   238 Apr 24 21:56 ..

0 drwxrwxrwx@    6 jupabeans  staff   204 May 28  2015 README

     com.apple.quarantine 26
0 drwxrwxrwx@  121 jupabeans  staff  4114 May 28  2015 theme
     com.apple.quarantine 26
Eso indica que el archivo tiene atributos extendidos (extended attributes) en OSX.  En éste caso 'com.apple.quarantine', una bandera que OSX usa desde Leopard (10.5) para marcar archivos descargados de fuentes no confiables.  Cuando ejecutas por primera vez ese archivo, una pantalla de confirmación aparecerá en la pantalla.

Pero ¿qué pasa cuando sólo son archivos de texto? pues nada, pero siempre quedarán marcados y a mi me distraen.  Así que los voy a quitar.

Hay varios métodos para quitarlos, el inteligente sería, buscar los archivos marcados en un directorio y quitarlos uno por uno.  El brutal sería quitarlos con 'recursive' activado.
$ xattr -dr com.apple.quarantine theme
xattr es el comando para manejar los atributos extendidos, -d es la opción para borrarlo -r activa recursividad, luego el nombre del atributo y al final el directorio o archivo.

Hay varias plantillas que tienen los archivos marcados como ejecutables, para quitarlos simplemente:

$ chmod 755 $(find theme -type d)
$ chmod 644 $(find theme -type f)
En ocasiones los espacios en los nombres de archivos pueden confundir los argumentos de chmod. Se puede usar las siguientes alternativas.
$ find theme -type d -exec echo -n '"{}" ' \; | xargs chmod 755
$ find theme -type f -exec echo -n '"{}" ' \; | xargs chmod 644
*actualizado 22 noviembre 2016
Otro método para remover los atributos extendidos
$ xattr -rc .

miércoles, febrero 24, 2016

Mercurial y control de versiones

En cada proyecto de desarrollo debemos contar con una herramienta para el control de versiones. Mercurial es actualmente mi favorito, hace años fue cvs y luego svn.

Haremos un simple ejercicio para mostrar funciones básicas de uso frecuente con ésta herramienta.  No he probado como funcionarían éstos ejemplos en Windows, pero si funcionan en sistemas POSIX.  Unix, Linux y OS X.

martes, febrero 23, 2016

Creando un ambiente de desarrollo en OS X

OS X es una buena plataforma de desarrollo.  Para todos los propósitos es una tiene un API POSIX, que la hace similar a al ambiente de desarrollo que antes usaba en Linux.

Sin embargo, el shell es muy elemental y ya me acostumbré a los beneficios de herramientas que en Linux están activadas por default.  Te muestro algunas de ellas.


lunes, enero 07, 2013

AngularJS, Turbogears 2.2 y RestController

Ahora que AngularJS está en producción, me dispongo a aprovechar esa nueva herramienta, con el respaldo de Turbogears.

En el homepage de AngularJS existe un demo ('Wire up a Backend') que está respaldado por MondoDB de MongoLabs y aunque funciona excelente y la plataforma de MongoDB parece muy sólida, yo quise experimentar con otras herramientas.

miércoles, mayo 18, 2011

Python, Genshi, fechas y UnicodeDecodeError

Hace unas semanas agregué el locale es_MX.UTF-8 para publicar fechas en español. Me llevó poco más de una hora descubrir un error en una aplicación que había funcionado perfectamente ayer. Los errores de python no siempre son los más claros.

La causa, 'UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 2: ordinal not in range(128)', yo creo el error más odiado para los hispano parlantes de python. La función que uso para publicar la fecha de hoy en Genshi es:
...
<link rel="stylesheet" type="text/css" media="screen" href="${tg.url('/css/tables.css')}" />
</head>
<?python
import locale
locale.setlocale(locale.LC_ALL, 'es_MX.utf8')
import datetime
?>
<body>
 <div id="wrap">
  <h2>
  Cotizaci&oacute;n
   <span>${datetime.datetime.now().strftime("%a %d de %B del %Y").upper()}</span>
  </h2>
  <div id="navcontainer">
...

Nunca se me ocurrió que tenía que preocuparme por días como hoy, Miércoles.
La función queda así:
...
<link rel="stylesheet" type="text/css" media="screen" href="${tg.url('/css/tables.css')}" />
</head>
<?python
import locale
locale.setlocale(locale.LC_ALL, 'es_MX.utf8')
import datetime
?>
<body>
 <div id="wrap">
  <h2>
  Cotizaci&oacute;n
   <span>${datetime.datetime.now().strftime("%a %d de %B del %Y").decode('utf-8').upper()}</span>
  </h2>
  <div id="navcontainer">
...


Agregar .decode('utf-8') funciona la mayoría de las veces que se presenta el UnicodeDecodeError.

miércoles, mayo 11, 2011

Importando desde CSV con Python

Siendo Excel la herramienta más común en todas las pequeñas y medianas empresas, es casi ley que los proyectos inicien con datos ya capturados en tablas. Estas tablas las exporto y las ordeno de acuerdo a mis necesidades.
Comúnmente las exporto a CSV, delimitado por coma con doble comilla como separador.
Creo mi modelo en forma declarativa.
class CoberturaCame(DeclarativeBase):
    """ Beneficios Adicionales """
    __tablename__ = "came"
    
    #{ Columns
    
    id = Column(Integer, autoincrement=True, primary_key=True)    
    tipo = Column(Integer)
    vendedor = Column(Unicode(32))
    edad_inf = Column(u'edad_inf', Integer, nullable=True)
    edad_sup = Column(u'edad_sup', Integer, nullable=True)
    hombre = Column(Float(precision=2), default=0.0)
    mujer = Column(Float(precision=2), default=0.0)
    
    #}
    
    #{ Helpers

    def from_csv_row(self, row):
        self.tipo = row[1]
        self.vendedor = row[2]
        self.edad_inf = row[3]
        self.edad_sup = row[4]
        self.hombre = row[5]
        self.mujer = row[5]
            
    
    @classmethod
    def by_edad_tipo(cls, edad, tipo):
        """Return the BenAdicionales object whose edad is between``edad``."""
        return DBSession.query(cls).filter(
            and_(cls.edad_inf <= edad, 
                cls.edad_sup >= edad,
                cls.tipo==tipo)).first()
        
    #}

y agrego una simple rutina de importación.

from miproyecto import model
import cvs

csvreader = csv.reader(open('res/janem_cobertura_came.csv'))
# skip first row
csvreader.next()
for row in csvreader:
    if len(row) == 0:
        continue
    d = model.CoberturaCame()
    
    d.from_csv_row(row)
    
    model.DBSession.add(d)

model.DBSession.flush()

La función miembro from_csv_row(row) definida en el modelo, es una ayuda visual y no tiene otro propósito mas que copiar los valores de la fila a un objeto nuevo. En algunos casos pudiera servir para realizar alguna transformación como fechas, minúsculas y mayúsculas o alguna operación aritmética antes de entrar. Aunque yo aconsejo realizar todas esas transformaciones desde la tabla de Excel y exportar el CSV ya listo para importar.

Cabe mencionar que las cantidades numéricas deben de estar sin formato, por que los caractéres '$' o las ',' dentro de las cifras confunden el lector de python.

martes, mayo 03, 2011

Forzando phpmyadmin sobre SSL en Ubuntu Lucid (10.04)

Un día me quedé sin conexión a Internet así que decidí tomar prestada la de algún vecino.  Después de algunas horas de trabajo, me vino un extraño pensamiento ... '¿y si mi vecino captura todos los passwords que pasan por su red como lo hago yo?' He entrado a los phpmyadmins de tres servidores haciendo modificaciones, fácilmente pudo capturar tres credenciales de root.

Resulta que no está bien documentado en la red cómo asegurar phpmyadmin en un Ubuntu Lucid.

Tengo que crear las llaves de seguridad
# apt-get update
# apt-get upgrade
# apt-get install openssl
# mkdir /etc/ssl/localcerts
# openssl req -new -x509 -days 365 -nodes -out /etc/ssl/localcerts/apache.pem -keyout /etc/ssl/localcerts/apache.key
# chmod 600 /etc/ssl/localcerts/apache*

Habilitar el módulo SSL del Apache
# cd /etc/apache2/mods-enabled
# ln -s ../mods-available/ssl.* .

Habilitar el sitio por default SSL de Apache
# cd /etc/apache2/sites-enabled
# ln -s ../sites-available/default-ssl .

Modificar default-ssl
<IfModule mod_ssl.c>
- <VirtualHost _default_:443>
------
  <IfModule mod_ssl.c>
+ <VirtualHost *:443>

Modificar /etc/apache2/ports.conf
<IfModule mod_ssl.c>
    # If you add NameVirtualHost *:443 here, you will also have to change
    # the VirtualHost statement in /etc/apache2/sites-available/default-ssl
    # to <VirtualHost *:443>
    # Server Name Indication for SSL named virtual hosts is currently not
    # supported by MSIE on Windows XP.
+   NameVirtualHost *:443
    Listen 443
</IfModule>

Adaptar /etc/apache2/conf.d/phpmyadmin.conf, aquí yo envuelvo la configuración dentro de un VirtualHost con el nombre de mi servidor, en este ejemplo my.servername.com
+<VirtualHost *:443>
+       ServerName my.servername.com
+       ServerAdmin webmaster@servername.com
+
+ DocumentRoot /var/www
  Alias /phpmyadmin /usr/share/phpmyadmin
al inicio y
+   #   SSL Engine Switch:
+   #   Enable/Disable SSL for this virtual host.
+   SSLEngine on
+
+   #   A self-signed (snakeoil) certificate can be created by installing
+   #   the ssl-cert package. See
+   #   /usr/share/doc/apache2.2-common/README.Debian.gz for more info.
+   #   If both key and certificate are stored in the same file, only the
+   #   SSLCertificateFile directive is needed.
+   SSLCertificateFile    /etc/ssl/localcerts/apache.pem
+   SSLCertificateKeyFile /etc/ssl/localcerts/apache.key
+</VirtualHost>
al final. Reiniciamos el servidor y probamos.

Parece mucho trabajo para algo que debería de ser aún más simple, sin embargo, los beneficios en seguridad valen la pena.

Mas info en: Creating a Self-Signed Certificate, phpmyadmin Documentation, Configure Apache to support multiple SSL sites on a single IP address

Actualizado 20 enero 2013 me faltó incluir una forma para obligar a phpmyadmin editando config.inc.php

// poner esto hasta abajo
$cfg['ForceSSL'] = true;