sábado, 17 de diciembre de 2011

Plugins Firefox II

Hace tiempo escribí una entrada sobre los plugins que venía usando en Firefox. Bueno, parece ser que he tirado hacia el minimalismo últimamente y resulta que ya no uso ninguno de los plugins mencionados. Ahora uso tan solo dos:
Adblock Plus: Te quita toooooda la publicidad de Internet. Dejas de verla. Incluso la propaganda que pone youtube.com antes de visualizar un video? Esta también dejas de verla. Es genial. Recomiendo a todo el mundo que se lo instale ni que sea para probar. Además, se va actualizando solo cada tanto, para mantener la base de datos de contenidos publicitaros que tu navegador no tiene que cargar. Super chulo.
ShareMeNot: Sirve para que todos aquellos botones "sociales" como por ejemplo el "Me gusta" de facebook, o el "+1" de Google, dejen de mandar información a Facebook/Google/Twitter sobre las páginas que visitas. Muy interesante para mantener la privacidad.

El ShareMeNot puede que requiera de una explicación adicional. Imaginemos que www.marca.com decide poner el botón "Me gusta" en todas sus páginas. Pues si estás logueado en facebook en el navegador y al mismo momento entras en www.marca.com, Facebook sabe que has entrado en esta página. Esto es debido a que automáticamente asocia el "Me gusta" con tu perfil. El problema es que Facebook sabe las páginas que vas visitando y lo va registrando. Y esto no mola. Por ejemplo, si la página web www.MeGustanLasGordasPelirrojas.com tiene un botón de "Me gusta" y estás logueado en facebook al mismo tiempo, Facebook a partir de ahora ya sabe "un poquito más" acerca de tí. Puede que a partir de ahora te haga publicidad de ciertas chicas con cierto problema de obesidad. Por esto está bien tener un plugin de firefox que te prevenga que se vaya mandando información sobre qué visito a todos los sitios web 2.0 y mantener así la privacidad de nuestros datos.

Y esto es todo por hoy. Un saludo!

domingo, 20 de noviembre de 2011

Clase de buceo

En el post anterior[1] comentaba cómo configurar las PAM para desactivar el tiempo de espera en caso de haberte equivocado escribiendo un password. Este post explica el proceso que seguí para saber que no es posible establecer un tiempo de espera personalizado. Siempre te tienes que esperar dos segundos en caso de haberte equivocado de password, o puedes desactivar el tiempo de espera. Lo que no puedes hacer es decir, "espérate 5 segundos en caso de que me haya equivocado de password antes de volver a preguntarme".. También se puede ver lo bonito que es el OpenSource, y la de que el código fuente sea público.

[Preámbulo]

Resulta que en el fichero /etc/pam.d/login hay una opción que pone: "auth optional pam_faildelay.so delay=3000000". Un comentario al lado explica claramente lo que hace esto:

"Enforce a minimal delay in case of failure (in microseconds)". O lo que es lo mismo: Fuerza una pequeña espera en caso de fallo en la autenticación. 3 segundos, para ser mas exactos.

Pues parece obvio pensar que si cambio 3000000 a 1000000, el tiempo de espera cuado haga login fallido se reducirá a 1 segundo.

Probemos antes de hacer el cambio:
$ sudo echo 1 # Comando chorra, pero lo importante es que nos pida el password
[sudo] password for inedit: badpassword
--- pasan unos dos segundos, aproximadamente ---

Hacemos el cambio en el fichero, poniendo el parámetro "delay=1000000". Probamos de nuevo:
$ sudo echo 1
[sudo] password for inedit: badpassword
--- pasan unos dos segundos, aproximadamente. Lo mismo que antes... ---


mmmm... mierda, no funciona. Probemos lo propuesto en el post anterior, o sea, poner el parámetro nodelay en el fichero /etc/pam.d/common-auth:
auth [success=2 default=ignore] pam_unix.so nullok_secure nodelay

Probamos de nuevo:

$ sudo echo 1
[sudo] password for inedit: badpassword
--- inmediatamente despues nos dice que la contraseña es incorrecta y que lo intentemos de nuevo. Tiempo de espera: cero segunos ---

Genial. Parece que el parámetro "nodelay" funciona. Pero ¿Por qué no funciona el "delay=3000000"?


[Siguiendo pasos lógicos]
Vale, resulta que el parámetro "nodelay" se lo ponemos como parámetro a un fichero llamado "pam_unix.so". Ni idea de qué coño hace este fichero, pero busquemos a ver si existe ene el sistema:

$ locate pam_unix.so
/lib/x86_64-linux-gnu/security/pam_unix.so

Touché, existe. mmmm..... vale. ¿Ahora qué hacemos con el? Ni idea de que hace realmente el fichero. Lo he abierto y es un binario....mmmm.... Vale, ya lo tengo. Descubramos qué paquete ha creado este fichero:

$ dpkg-query -S /lib/x86_64-linux-gnu/security/pam_unix.so
libpam-modules: /lib/x86_64-linux-gnu/security/pam_unix.so


Con que libpam-modules, eh? Vaaaale, pues mira, estamos siguiendo la pista y no nos va mal. Ahora ¿cuál puede ser el siguiente paso? Pues descargar el código fuente y que hace realmente el código:
$ mkdir ~/killme
$ cd ~/killme
$ apt-get source libpam-modules

Esto nos habrá creado un par de ficheros en el directorio "killme" [2].

[Buceando en el código]
Vale, ahora tenemos el código de la "libpam". ¿Qué hacemos? Lo obvio, aquí sería buscar alguna referéncia a "pam_unix.so". Pero como los ficheros ".so" son compilados y nosotros nos hemos descargado el código fuente, vamos a probar lo siguiente:
$ find -name "pam_unix*"

Oh! Genial, tenemos resultados! Parece que existe una carpeta interesante: "./pam-1.1.3/modules/pam_unix"

Vale, ahora deberíamos buscar algo de utilidad dentro de esta carpeta. Juguemos con "grep", a ver si hay suerte:
$ cd ./pam-1.1.3/modules/pam_unix2
$ grep nodelay -i # -i es para hace "ignore-case". O sea, que no distinga entre mayúsculas y minúsculas.
pam_unix.8:\fBnodelay\fR
pam_unix.8.xml:
README:nodelay
support.c: if (off(UNIX_NODELAY, ctrl)) {
support.h:#define UNIX_NODELAY 16 /* admin does not want a fail-delay */
support.h:/* UNIX_NODELAY */ {"nodelay", _ALL_ON_, 0100000},



Tenemos resultados! Parecen interesantes los ficheros "support.c" y "support.h". Revisado el fichero "support.h" parece que solo hay la declaración del parámetro UNIX_NODELAY.
Veamos el fichero "support.c", a ver que contiene:

[...]
#ifdef HAVE_PAM_FAIL_DELAY
if (off(UNIX_NODELAY, ctrl)) {
D(("setting delay"));
(void) pam_fail_delay(pamh, 2000000); /* 2 sec delay for on failure */
}
#endif
[...]


Eureka! Lo hemos encontrado! Vale, yo no tengo ni idea de C. Nunca he programado nada serio en C, ni mucho menos una librería de sistema para Linux. Pero si hemos llegado hasta este fichero buscando cosas lógicas, ahora no nos va a detener un poco de código en C. Parece que es el código fuente de "pam_unix.so".

Vamos a intentar leer lo que pone este pedacito de código. La condición "if" parece que comprueba lo siguiente:
SI (el parámetretro UNIX_NODELAY és igual a falso) ENTONCES {
Espérate 2 segundos
}


Pues ya lo tenemos, señores. Resulta que no se puede definir un tiempo de espera, ya que el tiempo de espera está puesto de modo estático en el código. En ningún momento el código va a leer la variable "delay=3000000", por lo que si ponemos "delay=5000000" es normal que lo ignore.

[conclusión]
¿Cómo hemos podido sacar todo esto? Pues la respuesta es muy simple: porque es Software Libre y se puede conseguir el código fuente muy facilmente a través de Internet. Inspeccionando el código vemos claramente lo que hace ( y mejor todavía, lo que no hace ). En este punto, y si tuviese los conocimientos de C necesarios, podría reescribir el código fuente para que aceptara un parámetro "delay" y que pudiese ser definido des de la pam.d/login. Una vez hechos los cambios, podría mandarlos al mantenedor del paquete y en caso de gustarle dichos cambios, los incorporaría en el código de la libpam. Y el mundo sería un lugar mejor y lloverían gominolas del cielo :)


[1] Recomiendo que te lo leas, sinó este pot no tiene mucho sentido.
[2] Me gusta bastante crear directorios con el nombre "kill" o "killme" para usos temporales, ya que es un modo de saber si puedo borrar el directorio sin ni tan solo preocuparme de ver que contiene. En cambio, un directorio que llamado "temp" o "temporal".... bueno, si, son datos temporales. Pero hasta cuando? Servirá lo que hay dentro? Es algo lioso. Usando "killme" el tema está claro, puedes borrar la carpeta cuando quieras sin ningun problema, ya que el contenido de la misma no es importante ;)

jueves, 8 de septiembre de 2011

Saber a qué paquete pertenece un fichero

Algunas veces hay ficheros con nombres curiosos, y uno se pregunta qué paquete debe haber instalado este fichero. Por ejemplo el fichero:

/usr/bin/pico

Yo me pregunto, ¿quién lo habrá puesto ahí?

Pues fácil:
$ sudo aptitude install dlocate -y
$ dlocate /usr/bin/pico
> perl: /usr/bin/piconv

Pues mira, ha sido el paquete "perl".

Esto también sirve para ficheros de configuración, así como carpetas del sistema. Todo lo que esté "trackeado" por dpkg, es suceptible de ser encontrado por dlocate.

Un saludo, Jan.

UPDATE: El comando "dpkg-query -S /usr/bin/see" también hace lo mismo.

"sudo su" sin espera ( nodelay )

Pues como hoy me he tirado 30 minutos buscando esta opción y considerando que hay poca información sobre ella ( y menos en castellano ), así va:

¡NODELAY en pam_unix.so!

[¿De qué va el tema?]
Pues se trata de optimización de tiempo y comodiad en la consola. Cuando ejecutamos un comando con "sudo", normalmente nos pide la contraseña ( a menos que lo hayamos desactivado ). Esto es la política de seguridad bastante recomendada, ya que si no cualquier persona te podria juankear el ordenador si lo dejas solo un momento sin bloquear.

[Total, dónde está el problema, entonces?]
Pues que si al ejectuar cualquier comando con sudo, te equivocas al picar tu password, te tienes que esperar 3 segundos para volverlo a picar. Y esto es un coñazo. Ejemplo:

inedit@tpad:~$ sudo echo 1
[sudo] password for inedit: foo
- espera de tres segundos -
Invalid password, please try again:
[sudo] password for inedit: bar
- espera otra vez de tres segundos -
....etc...

[HOWTO]
Total, que esta opción se puede desactivar a través de las PAM de linux del siguiente modo:

sudo vim /etc/pam.d/common-auth

Y modificar la lína donde pone:
auth [success=2 default=ignore] pam_unix.so nullok_secure>

Y cambiarla por:
auth [success=2 default=ignore] pam_unix.so nullok_secure nodelay

De este modo se desactiva totalmente el tiempo de espera entre logins. Cuando te equivoques al escribir tu password, automáticamente te volverá a preguntar la clave.

[Precaución]
Y uno se preguntará, ¿por qué puñetas no estaba desactivado esto ya? Pues por motivos de seguridad: previene que se lanzen ataques de fuerza bruta contra el PC, ya que el hecho de que te tengas que esperar 3 segundos tras cada intento fallido, limita mucho los ataques ( los hace inviables por la cantidad de tiempo que se necesita probar un número acceptable de claves ). Aplicando la regla anterior estamos quiando esta restricción. O sea que cuidadín en ejecutar algo así en una máquina de producción donde tenga SSH expuesto en Internet y demás. Quien avisa no es traidor.

[Nota final]
Como siempre, en un extremo tenemos seguridad, y en el otro tenemos comodidad. No podemos elegir ambos. Por lo que lo mejor es quedarse siempre en un punto medio.

Un saludo, Jan.

Posdata: Si alguien consigue sacar algo en claro sobre el fichero /etc/pam.d/login y su parámetro "pam_faildelayso delay=3000000", que por favor deje un comentario y así completamos la información. Yo no he sido capaz de ajustarlo a un segundo. Gracias de antemano.

martes, 26 de julio de 2011

Unetbootin

Un programita muy simple, pero que hace su trabajo.

[Pa que sirve?]
Cuando te descargas una ISO de un nuevo SO ( debian/arch/back track....) y la quieres instalar en un ordenador tienes varias opciones. La mas común es tostarla en un CD y instalar des de ahí. Pero hay un problema en los notebooks y servidores y es que pueden no tener unidad de cederoms.

Unetbootin te soluciona la papeleta y te pone la ISO en un pendrive.

[Cómo utilizarlo]
En mi caso me he encontrado con algún problemilla, utilizando el programa. Para ello sigo los siguientes pasos:
  1. Meto el pendrive en el PC
  2. Con gparted formateo el pendrive enterito, y le creo una partición fat16 de 4GB
  3. Abro el programa unetbootin
  4. Selecciono la ISO que quiero cargar en el pendrive ( el mismo programa te ofrece descargar la ISO vía web ).
  5. Monto el pendrive
  6. Le doy a OK
Te esperas 5 minutos a que copie los ficheritos de una lado pa otro y ya lo tienes. Al reiniciar, inicias des del pendrive y es lo mismo como si estuvieses haciendo el boot des de un CD.

Facil simple y para toda la familia. Y ya sabes, para instalar simplemente lo tienes que buscar en los repositorios de tu distribución favorita.

Un saludo, Jan.

P.D: Ahora mismo estoy tostando ArchLinux de mientras escribo este post, a ver si lo puedo instalar O_0

miércoles, 29 de junio de 2011

unclutter

Estos pequeños programas, unixlike, que nos hacen la vida mas fácil en nuestro día a día. Esto es lo que realmente mola de linux.

Esta vez se trata de una pequeñez, que cuando lo tienes puesto te olvidas de que lo tienes. Cumple exactamente su propósito porque para esto ha sido creado.

unclutter, es una aplicación que simplemente te esconde el cursor del mouse de la pantalla después de un tiempo de no ser usado, o cuando estás escribiendo. Es especialmente cómodo en caso de tener una pantalla no muy grande, o si te pasas el dia programando ( como un servidor ).

[Instalación]
Bueno..... que os voy a contar que no sepais?
sudo aptitude install unclutter

[Configuración]
Qué? Nono, U-N-I-X-L-I-K-E. La configuración por defecto ya va de lujo.

[Cómo usarlo]
unclutter &

Y listo. Cada 12 segundos, aproximadamente, de inactividad del ratón, el cursor desaparece, a la que mueves el ratón, el cursor aparece de nuevo.

Genial!

domingo, 12 de junio de 2011

Famoso "noatime"

Bueno señores, hoy vamos a ver una configuración muy simple de aplicar, y que hace que el sistema vaya muuucho más flúido. Y estoy hablando del parámetro "noatime".

Qué es esto de "noatime"? Pues "noatime " es un parámetro especial en el montaje de los dispositivos como discos duros o memórias extraibles. Se acostumbra a modificar en el fichero /etc/fstab.

[Explicación]
Resulta que nuestro sistema de ficheros guarda, para cada uno de nuestros ficheros, un parámetro que se llama "atime", o "access time". Total, que cada vez que accedemos ( leemos ) un fichero, el valor "atime" se actualiza. Así podemos saber cuál fué la última vez que accedimos/leimos un determinado fichero.

Pero claro, esto tiene un comportamiento no deseado: Resulta que por cada lectura que hacemos a disco, necesitamos escribir algo a disco!! ( actualizar el valor "access time"). Esto parece absurdo! Para leer tenemos que escribir.

Habrá alguien que pensará: exagerado! No es para tanto. Total, tiene que escribir a disco tan solo unos pocos bytes, esto no es nhà.

Pues bueno, resulta que escribir estos pocos bytes si jode, y mucho. Me explico. Linux tiene un sistema fantástico de caches, completamente transparente para el usuario. Te permite hacer lo siguiente:

# cat ./bashrc
# cat ./bashrc


La primera vez que haces el "cat" de cualquier fichero ( en nuestro caso, .bashrc ), se va al disco duro, y lo lee. Pero también lo pone en la memória RAM. La segunda vez que ejecutas el comando "cat", sabe que lo tiene cacheado y lo lee directamente de memória RAM. No hace falta tocar disco duro. Esto hace que el sistema vaya muuuucho más rápido, ya que todo los ficheros que hayas leido una vez ( y no se hayan modificado ) ya están cacheados, y no se precisa leer a disco. Pero que pasa si no tenemos desactivado el "atime", pues que con cada lectura, aunque la tuvieses cacheada, tienes que hacer una escritura a disco para actualizar el tiempo de acceso. Nos ha jodido.

Esto, en portátiles tiene un impacto muy grande ya que al cabo de X segundos de no utilizar el disco duro, éste se para. Un tema de ahorro de energía. Qué pasa si queremos hacer una lectura o escritura? Pues que el disco se tiene que volver a poner a girar con el consiguiente consumo energético/tiempo perdido. Pero si intentamos leer un fichero CACHEADO por el sistema, el disco duro ni se entera. Sigue parado. Por lo que es genial.

[HOTWO]
Cómo activar la opción "noatime"?
Con tu editor preferido (gedit, nano, emacs) el fichero, en mi caso "vim":
# sudo vim /etc/fstab

Busca tu disco duro principal. Lo mas seguro es que sea una entrada como esta:
UUID=3e9532f9-226c-4f17-ae64-dad42519a1fc / ext4 errors=remount-ro 0 1

y añade simplemente "noatime" en las opciones para que quede tal que así:
UUID=3e9532f9-226c-4f17-ae64-dad42519a1fc / ext4 noatime,errors=remount-ro 0 1

y punto. Reinicia y ya lo tienes.


[Prueba de concepto]
Para los menos crédulos: que os den ¬¬. Y para los mas frikis, vamos a hacer una prueba de concepto. El siguiente comando busca TODOS los ficheros están en /etc y les hace un "cat". Redirijo la salida a /dev/null porque no me interesa ver el contenido de los ficheros, sinó que simplemente mi máquina los lea enteritos una vez y los cachee. Fijáos, de 2.62 segundos a 0.037. Y la segunda vez sin tocar disco duro!!! It rocks!!

inedit@tpad:/etc$ time find /etc -name ".*" -exec cat '{}' ";" > /dev/null 2>/dev/null

real 0m2.622s
user 0m0.024s
sys 0m0.044s
inedit@tpad:/etc$ time find /etc -name ".*" -exec cat '{}' ";" > /dev/null 2>/dev/null

real 0m0.037s
user 0m0.020s
sys 0m0.016s

[Cuándo aplicar esta configuración]
Bueno pues, recomendado, a todas las máquinas en general. Sin excepción.

Muy recomendado, en portátiles. Por el tema de ahorro de corriente, y del encendido/parado del disco.

Y OBLIGATORIO en los equipos:
- Servidores ( web-ftp-sambda ) con muchas lecturas. Aquí si que utilizar el sistema de cachés es algo básico, y no quitar el atime podría hacer que el rendimiento fuese pésimo.
- Equipos con discos duros SSD. Esto es debido a que los SSD tienen un número de escrituras máximas por bloque, y al llegar este número se desactiva el bloque y no se utiliza nunca más. Por lo que tener el "atime" activado significa que la vida del disco va a ser mucho mas corta.


El desarrollador del kernel Ingo Molnar dijo:

Atime updates are by far the biggest IO performance deficiency that Linux has today. Getting rid of atime updates would give us more everyday Linux performance than all the pagecache speedups of the past 10 years, _combined_.


Un saludo, Jan!

x201 Software - Sobre configuraciones, programas instalados y demás

En el post anterior he hecho un pequeño review sobre el Lenovo ThinkPad x201. En el hablábamos de las prestaciones a nivel de hardware. Ahora toca hablar de el software que tengo instalado en el juguetito.


[Sistema Operativo]
Pues, por supuesto, Debian 6.0 en testing. La instalación limpia, sin servidor de X, ni impresoras ni nada. Todo lo he ido instalando después "on demand".

Por qué Debian y no otra? Bueno, al final hay 1000 distribuciones y cada uno elige la que más se adapta a sus necesidades. En mi caso:

Es estable: esto es importante ya que utilizo el portátil tanto para ocio como para el trabajo. No me puedo permitir el lujo de actualizar por la noche y que la mañana siguiente en el curro me peten las X, o que me quede sin audio (para poder recibir llamdas por VozIP y demás).
Sistema gestor de paquetes: es genial, muy práctico y simple de usar. Cualquier cosa que necesite está ahí.
Altamente configurable: me encanta toquetear y personalizar todo. Pero las configuraciones por defecto ya te lo dejan listo para trabajar.
Actualizan cada vez que hace falta: Antes usaba Ubuntu y sacaban muchas cosas en poco tiempo. Cada 6 meses, nueva versión. Esto va en contra de la estabilidad del sistema.
Y la mas importante de todas: porque me sale de los mismísimos _ _ _ _ _ _ _ (rellénese con "cojones")


[Programas básicos]
Nótese que me he tirado muchas horas ( debería decir dias? ) configurando el juguetito. Primero porque me la pone morcillona, segundo porque trabajo mas cómdo/rápido/mejor. Quiero decir que todas estas configuraciones no las he hecho en una tarde. Pero es cosa de ir haciendo poco a poco. Vale bastante la pena tener las cosas exactamente como a uno le gustan.

  • Gestor de ventanas: OpenBox # MUY tuneado
  • Navegadores: Chromium, Firefox4.0
  • Editor de texto: vim
  • Terminal: gnome-terminal y xterm, también uso tilda # bastante personalizado, tanto .bashrc como .inputrc
  • File Manager: Thunar ( no lo utilizo para un carajo )
  • Visor de imágenes: feh
  • Visor de PDF's: xpdf / evince
  • Mensajería (MSN/Jabber): Pidgin
  • Dock: tint2
  • Gestor de escritorio: ninguno. Lo tengo siempre vacío de iconos.
  • Información sistema: conky en el escritorio.
  • Conexiones: network-manager ( a falta de alternativa mejor ).
  • Cliente IRC: irssi
  • Cliente correo: Normalmente utilizo el navegador, pero tengo el mutt configurado también.
  • Servicios: ssh, básico. openvpn que se conecta a un servidorcillo dándome un canal seguro por si lo necesito.
  • Lanzador de comandos: gmrun
  • Cliente de VozIP: blink o sjphone. También uso Skype para el curro
  • Reproductor de música: moc (básico, es un reproductor por línea de comandos)
  • Escriotorio remoto: rdesktop para cuando tengo que trabajar con Juindous, y TeamView para dar soporte a clientes.
  • Volumen audio: aumix / alsamixer. Los dos por línea de comandos.
  • Ofimatica: libreoffice (casi no lo uso para nada)


[Scripts]
Pues tengo un script, que iré comentado en los próximos posts, que es el centro del universo de mi portátil. Ahí he ido recopilando todos los procedimientos que voy repitiendo cada día en un solo script. El script se llama "tpad" en un alarde de originalidad (el portátil es un ThinkPAD). Me permite hacer cosas tan variadas como: blockear las pantalla, añadir las claves SSH al ssh-agent, montar de forma segura un flash drive con encriptación Luks, cambiar el idioma del teclado, apagar/reiniciar el equipo, control de la salida de video, etc... la mayoría de estos comandos son accesibles mediante un shortcut configurado en .config/openbox/rc.conf, así como des de cualquier termianl. Al comando en cuestión le he puesto completion y ayuda. Como digo, ya os iré mostrando lo que hace este ficherito.

[Configuraciones de sistema]
Por ejemplo:
  • Modificar /etc/fstab para poner el parámetro "noatime" a los discos, así como crear puntos de montaje de tipo /tmpfs par hacer que vaya todo mas flúido.
  • Que tanto Firefox como Chrome utilizen la memória RAM para almacenar sus ficheros temporales ( normalmente van sobre disco ).
  • Quitar servicios innecesarios al inicio del sistema.
  • Cambiar el sistema de completion de bash, para que cuando inicies una nueva terminal todo cargue mucho mas rápido.
  • Cachear ficheros para que estén en memória y tenga que hacer menos lecturas a disco cuando trabajo.
  • Desactivar la memória swap.
  • Configurar "iptables" para blindar el PC contra ataques en red local.
  • Quitar el puto "beep" de los cojones del sistema.
  • Remapear algunas teclas del teclado.



Bueno vamos, que estos son los programas mínimos que necesito para ir tirando. Como ya os he dicho, voy a ir comentado próximamente algunos de ellos, y las configuraciones que me han sido más útiles a mi, tanto por un tema de usabilidad, como por un tema de eficiencia.

Os dejo con una captura de pantalla del escritorio, y otra con un benchmarck sacado por el programa bootchart, para ponerle los dientes largos a mas de uno ;) [1]. Si por lo sea has leido algo que te interesa en este post, y quieres que amplie un poco la información, no dudes en dejar un comentario y te soluciono las dudas que tengas!




[1]: Arranque en 21 segundos ;) Y sin SSD. Todavía.
Un saludo, y hasta la próxima!

Lenovo X201 review

Hace tiempo ya -sobre noviembre del año pasao- me compré un portátil nuevo.

El juguete en cuestión es un Lenovo ThinkPad x201. Una monada, la verdad. Con decir que ha sido una de las mejores compras que he hecho en la vida, creo que lo digo todo. Y voy a hacer un poquito de review:

[PRESTACIONES]
Veamos de prestaciones quetal está:
Modelo: Lenovo ThinkPad x201 - 3249
  • Procesador: Intel i5 M540 a 2.53GHz. 3M de caché. 2 cores o 4 con HyperThreading ( 5053.44 bogomits cada uno ). [1]
  • Memória RAM: 6GB (4GB+2GB) DDR3 a 1066. No soporta Dual Channel.
  • Disco duro: 240GB a 5200rpms.
  • Gráfica: Integrada en el procesador [1]. Soporta video de alta definición así como dos pantallas conectadas al mismo tiempo.
  • Pantalla: 12.1 pulgadas, WXGA Display (16:10)
  • Batería: 6 celdas, nos da una autonomia de entre 3.5 horas de trabajo intensivo, o unas 5 si no utilizamos internet ni mucho disco.
  • Puertos: Gibabit Ethernet, Modem, 3USB, microfono/audio, ExpressCard, 5-1 MediaCard Reader, VGA
  • Otros: Lector de huella digital, LED que ilumina el teclado
  • Teclado: De lo mejorcito, full-size con un tacto espectacular.
  • Mouse: TrackPad y TouchPad (utilizo el TrackPad, es MUY cómodo)
  • Peso: 1,47 Kg

[HARDWARE]
Y ahora que hemos visto los datos en bruto, vamos a comentarlos un poquito.

El procesador es un i5, y va muy muy fino. Haciendo "vida normal" (navegando, programando, etc...) el uso siempre está en un 1% [2]. La temperatura ronda los 46 grados en invierno y los 50 en verano. El ventilador que refrigera todo se oye muy poquito ( almenos no parece que el portátil vaya a hacer un despegue vertical, como hacen muchos otros portátiles ). Con 6GB de memória voy mas que sobrado; al iniciar el sistema hay 100MB de memória usados, a la horita de utilizar el PC hay entre 400MB y 600MB usados. Nunca lo he visto superar el GB[2]. La targeta gráfica funciona muy bien para el uso doméstico/trabajo. Nunca lo he probado para jugar a juegos de última generación, pero seguramente se quede un poco corto. Para reproducir flash o ver videos HD va muy fina, aunque utiliza el 25% de la CPU, por lo que el portátil inevitablemente se calienta.

El disco duro es mas que suficiente, y con mi configuración[2] necesito solo 6GB para el sistema/programas. Los demás son para mis cosicas. Aún así dentro de muy poquito lo voy a cambiar por un SSD y disco que hay ahora montado lo usaré de disco extraible USB. Esto si va a ser la caña.

Todo lo demás: pues la pantalla tiene el tampaño perfecto para mi: no es un netbook donde no puedes ver casi nhà, pero tampoco es una pantalla de cine enorme que hace que la batería del portátil se gaste antes, y el tamaño/peso del juguete aumente considerablemente. La batería es suficiente, aunque siempre tienes que ir con el cargador ( con 4 horas de autonomía lo tengo que cargar 3 veces al día, como os podeis imaginar ). Sobre los puertos solo se hecha en falta otro conector de vídeo que no sea VGA, pero bueno. El TrackPad va de lujo y lo mejor sin duda es el teclado. Si os fijais en las fotos, ocupa el 100% de la superfície del portátil pero el tamaño de las teclas es el estándart. Va muy muy bien. Un tacto genial. Cuando cambias a cualquier otro teclado te das cuenta de lo cómodo que es el del x201.

Lo que le falla: Los altavoces, sin duda, son una mierda. La calidad del audio deja bastante que desear. Y le falta otra salida de vídeo como DVI. Y en el modelo que compré también le falta una webcam. Pero hay modelos que si la incluyen. Estaría bien un puerto USB 3.0, que no tiene. Y le sobra el Modem. Ya no estamos en los años noventa.

Estética: se puede ver en las fotos. Pequeño, ligero, el teclado ocupa toda la superfície. Cuando lo coges se nota sólido. El diseño es algo austero, pero a mi personalmente me gusta así.

[PRECIO]
Pues no lo regalan. Yo lo compré en EEUU por unos 920€. En españa creo que el precio base ronda los 1100€. Pero, sin duda alguna, vale mucho la pena gastarse este dinero. Yo, antes de comprarlo me decía: "vale Jan, por 1100€ puedes tener un porátil de 600€ un PC de sobremesa de 500€". Si ahora mismo tuviese que volver a comprarlo, compraría exactamente este mismo modelo. Mis compañeros y gente del mundillo de la informática me ha dicho que me va a durar 4-5 años fácil fácil. Mi jefe y un compañero mio tienen un x60s de hace 5 años y todavía trabajan a diario con ellos.

[CONLUSIÓN]
Un porátil con unas prestaciones muy buenas. Tiene muchos pros y pocos contras. Es un portátil para trabajar y navegar, no para jugar. Portable, ligero pero con la última tecnología del mercado. Lo recomiendo al 100%. No es barato, pero la inversión vale la pena con creces. Yo, después de 7 meses ya lo he amortizado :)


[FOTICAS]
http://tpholic.com/xe/files/attach/images/63/226/373/004/SNC00489.jpg
http://buildaroo.com/wp-content/uploads/2010/12/Lenovo-ThinkPad-x201-side-and-back.jpeg
http://ultimosavances.com/wp-content/uploads/2010/02/x201.jpg
http://www.abeststore.com/blog/wp-content/uploads/2010/07/Lenovo-ThinkPad-X201.jpg

Nótese que algunos portátiles tienen touchPad o webcam y otros no. Todo esto es opcional.

[1]: http://ark.intel.com/Product.aspx?id=43544
[2]: Ya hablaremos porqué en el apartado de Software

domingo, 27 de marzo de 2011

El Mínimo Absoluto que Todos los Desarrolladores Deberían Conocer Sobre Unicode y Codificaciones.

Este artículo pretende ser una traducción más o menos fiel [1] de el artículo de Joel Spolsky. Me ha gustado tanto que me he decidido a traducirlo para hacerlo accesible a todos aquellos que no dominan el inglés, o que prefieren leer en castellano. Es un magnífico texto que todavía hoy sigue vigente. Te recomiendo la lectura, ya seas programador, administrador de sistemas, o simplemente un curioso de la informática.


----------------------------------------------------------------------------------------------

El Mínimo Absoluto que Todos los Desarrolladores Deberían Conocer Sobre Unicode y Codificaciones.

Miércoles, 08 de Octubre de 2003 by Joel Spolsky

Alguna vez te has preguntado acerca de la etiqueta misteriosa "Content-Type"? Ya sabes, la que se supone que debes poner en el HTML y que nunca has sabido realmente que poner?

Alguna vez has recibido un correo de tus amigos de Bulgaria con un asunto igual a "???? ??? ?? ????? ??" ?

Me he molestado al descubrir que muchos desarrolladores no saben realmente como funciona el misterioso mundo de las codificaciones de caracteres, Unicode, etc... Unos años atrás un beta tester de FogBUGZ se estaba preguntando si podría recibir correos en Japonés. Japonés? Ellos escriben correos en Japonés? No tenía ni idea. Cuando miré mas de cerca el componente comercial que estábamos desarrollando en ActiveX para parsear las cabeceras MIME de los e-mails, nos dimos cuenta de que lo estábamos haciendo mal con las codificaciones de caracteres, por lo que tuvimos que reescribir el código de conversión. Cuando miré el código de otra aplicación comercial, también tenia una mala implementación en la codificación de caracteres. Mandé un par de e-mails al desarrollador del paquete, pero el dijo algo así como: "no puedo hacer nada al respecto".

Cuando descubrí que en el lenguaje de programación PHP no se habían tenido en cuenta las condificaciones y que usaba tan solo 8 bits para la codificación de caracteres, haciendo prácticamente imposible el desarrollo de buenas aplicaciones internacionales, pensé: ya es suficiente.

Tengo un anuncio que hacer: si eres un programador y no tienes unos conocimientos mínimos sobre caracteres, tabas de caracteres, codificaciones y Unicode, te voy a pillar y te castigaré haciéndote pelar cebollas durante 6 meses en un submarino. Te juro que te pillaré.

Y algo más:
** NO ES TAN DIFÍCIL **

En este artículo voy a explicar exactamente lo que todos los programadores deberían saber. Todo esto de que "texto en claro = ASCII = caracteres de 8 bits" no está solamente mal, sino que está fatal, y si sigues programando de este modo, no eres mucho mejor que un doctor que no cree en los gérmenes. POR FAVOR, no escribas otra línea de código antes de haber acabado de leer este artículo.

Antes de que empiece, debería advertirte de que si eres una de estas raras personas que sabe algo sobre la internacionalización, vas a encontrar todo lo de este posto un poco "simplificado". Yo estoy intentando establecer un mínimo, para que todo el mundo pueda entender de qué va el tema, y pueda escribir código que tenga alguna oportunidad de funcionar en textos escritos en cualquier lenguaje ( o en otro subset de inglés que no incluya palabras acentuadas ¬¬ ). Y debo advertirte que el tratamiento de caracteres es solo una pequeña parte de lo que conlleva crear software que funcione intencionalmente. Me temo que yo solo puedo escribir artículos sobre una cosa a la vez, o sea que hoy tocan codificaciones de caracteres.

Des de la perspectiva histórica
========================

La manera mas fácil de entender todo esto es ir viéndolo de manera cronológica.

Probablemente estarás pensando que voy a hablar sobre antiguas tablas de caracteres como EBCDIC. Bueno, no voy a hacerlo. EBCDIC no es relevante para tu vida. No tenemos que ir tan atrás en el tiempo.


Volviendo atrás en los tiempos semi-antiguos, cuando Unix fue inventado y K&R estaba escribiendo The C Programming Language, todo parecía muy simple. EBCDIC estaba ya de salida. Los únicos caracteres que importaban eran los caracteres del inglés, con letras no acentuadas. Así se creó el ASCII que eran unas tablas capaces de representar todos los caracteres usando números del 32 al 127. El carácter que se correspondía con el espacio era el 32, la letra "A" se correspondía con el 65, etc. Todo esto se podía guardar perfectamente en 7 bits. La mayoría de ordenadores en estos días usan bytes de 8 bits, entonces no solo podrías almacenar todos los caracteres ASCII, sino que tenías un bit adicional que "sobraba" ( no se usaba ) y que, si querías podías utilizar para tus propios ( y maléficos ) fines. Este bit adicional se utilizó en WordStar para indicar la última letra de una palabra, condenando, así, WordStart a que sólo funcionara en inglés. Los códigos por debajo de 32 se llamaban "unprintables" ( que no se pueden escribir ) y se utilizaban para insultar. Estaba bromeando. Realmente se usaban como caracteres de control, como el 7, que hacía que ordenador emitiese un "beep", y el 12, que se interpretaba por las impresoras como un salto de página, por lo que dejaba de imprimir en la hoja actual y cargaba otra hoja.

Todo esto estaba muy bien. Suponiendo, claro, que fueses de habla inglesa.

Como el código ASCII solo ocupaba 7 bits, mucha gente pensó "caramba, puedo utilizar los código 128 hasta el 255 para almacenar mis cosas". El problema fue que MUCHA gente pensó esto en el mismo momento, pero cada uno tuvo su propia idea de qué debería ir en el espacio de 128 a 255. El IBM-PC creó algo que se llegó a conocer como mapa de caracteres OEM, que contenía caracteres acentuados para los lenguajes Europeos, así como muchos caracteres para dibujar líneas.... barras horizontales, barras verticales, etc... así que tu podías usar estas líneas para dibujar caracteres en la pantalla y hacer cuadros y líneas a tu gusto ( era un recurso para embellecer las aplicaciones de línea de comandos ). Asimismo, cuando la gente empezó a comprar ordenadores fuera de EEUU, se diseñaron muchos tipos diferentes de tablás de caracteres OEM. Cada una de ellas usaba los últimos 128 caracteres para sus propios propósitos. Por ejemplo, en algunos ordenadores el código 130 se mostraba como "é", pero en los ordenadores vendidos en Isael se veía la letra Hebrea Gimel (ג), así que si des de Estados Unidos enviaban un documento con la palabra "résumés" los israelitas las recibían como "rגsumגs". En muchos casos, como en Rusia, hubieron muchas ideas sobre qué hacer con los últimos 128 caracteres, por lo que intercambiar documentos en la misma Rusia se convertía en un problema.

Eventualmente, este "libre albedrío" de qué hacer en los últimos 128 caracteres se acabó con el estándar ANSI. En este nuevo estándar, todo el mundo accedió en "qué hacer con estos 128 caracteres". Pero este nuevo método establecía muchos maneras de tratar los últimos 128 caracteres, dependiendo del sitio donde vivieras. Estos sistemas diferentes se llamaron *code pages* (páginas de código). En Israel, por ejemplo, el sistema operativo DOS usaba la página con código 862, mientras que en Grecia usaban la página de códigos 737. O sea, sus tablas de códigos eran igual por debajo de los 128 ( ASCII ), pero eran diferentes por encima de los 128 ( donde se ponían todos aquellos "caracteres divertidos" de cada país o región ). Las versiones de MS-DOS tenían docenas de páginas de códigos, que permitían hacer que un mismo ordenador fuera "multilenguaje", de modo que podían abrir documentos escritos en inglés, islandés o esperanto (usando una tabla de códigos que suportara los tres idiomas al mismo tiempo). Pero qué pasaba si querías usar el hebreo y el griego en el mismo ordenador? Pues que no podías ya que cada uno tenía su tabla de códigos específica, y no había ninguna tabla de códigos "compartida" entre estos dos idiomas.

Mientras tanto en Asia, estaban pasando cosas bastante mas complicadas por el hecho de que los alfabetos asiáticos tienen cientos de carácteres. Ellos lo solucionaron con un sistema muy lioso llamado DBCS, "double byte charse set" en el que _algunas_ letras se guardaban en un byte, otras letras se guardaban en dos bytes. Este sistema te permitía moverte sin problemas hacia "adelante" en un string, pero era realmente complicado moverte "hacia atrás". Por esto los programadores dejaron de usar s++ o s-- y empezaron a usar las funciones de Windows AnsiNext y AnsiPrev para no tener que pelearse con este complicado sistema.

Pero aún así la gente seguía programando de modo que un carácter fuese un byte, y que un carácter tenía 8 bits, lo que significava que "nunca muevas un texto de un ordenador a otro". Pero claro, con la aparición de Internet hubo un sitio muy propicio para intercambiar textos de un ordenador a otro, y todo el tema de las codificaciones se vino abajo. Por suerte se inventó Unicode.


Unicode
=======
Unicode fue el resultado de un gran esfuerzo por crear un solo set de caracteres que incluía cualquier sistema de escritura razonable en el planeta, y algún otro como el Klingon, también. Algunas personas, malentendiendo lo que Unicode es, piensan realmente que es un sistema de 16 bits, donde cada carácter ocupa 16 bits. Esto significaría que con este sistema se podrían escribir hasta 65.536 caracteres. Pero esto no es realmente cierto. Es uno de los mitos mas tontos sobre Unicode, por lo que si creías que que era así, no te sientas mal.

De hecho, Unicode tiene un modo diferente de pensar sobre los caracteres, y tu tienes que entender este modo de pensar, o nada va a tener ningún sentido para ti.

Hasta ahora, hemos asumido que un carácter se guarda en un número determinado de bytes como por ejemplo:

A = 0100 0001

En Unicode, los caracteres se llaman "code point", que son solo un concepto teórico. El cómo un "code point" se representa en memoria o en disco, es otra historia.

En Unicode, la letra A es una idea platónica. Solo está flotando en el aire:
A
Esta platónica A es diferente de B, y diferente de a, pero igual a A, y A, y A. La es idea que A en el tipo de letra Times Roman es lo mismo que A en el tipo de fuente Helvetica, pero diferente de "a" en minúscula. Esto no parece que tenga que causar mucha controversia, pero en algunos lenguajes, determinar lo que realmente una letra es puede ser complicado. Por ejemplo en Alemán la letra ß es una letra real o es otro modo de escribir ss? Si una letra cambia, por el hecho de estar escrita al final de una palabra, es la misma letra? Los hebreos dicen que si. Los arábigos dicen que no. De todos modos, la gente inteligente de el consorcio de Unicode, se han estado preguntando todo esto durante la última década, acompañado por un gran debate político. Por esto tu no debes preocuparte por todo esto. Ellos ya lo han calculado todo ya.

Cualquier letra platónica ( concepto de letra ) en todos los alfabetos, es un número mágico en el consorcio Unicode, que se escribe tal que así: U+0639. Este número mágico es llamado "code point". El U+ significa Unicode y los números son hexadecimal.

No hay un límite real en el número de letras que Unicode puede definir, aún a pesar de que parezca de que solo se utilicen 2 bytes, y por tanto, solo se pueden definir 65535 letras. Esto es otro mito sobre Unicode.

Bien, aquí tenemos una cadena de texto:
Hello

que, en Unicode, corresponde a estos cinco puntos de código:

U+0048 U+0065 U+006C U+006C U+006F

Solo sólo un montón de puntos de código (codepoints). Números, en realidad. Todavía no hemos hablado de cómo guardar esto en memoria o en disco, o cómo representarlo en un mensaje de correo electrónico.


Econdings
=========
Aquí es donde entran los "encodings" (codificaciones).

La primera idea de las codificaciones en Unicode, que nos deja el mito sobre los dos bytes, fué: "ei! vamos a guardar estos números en dos bytes cada uno". Así que "Hello" se convierte en:
00 48 00 65 00 6C 00 6C 00 6F

Bien? No, demasiado rápido! No podría escribirse como?
48 00 65 00 6C 00 6C 00 6F 00 ?

Bueno, técnicamente, si. Creo que se podría, y de hecho, los primeros programadores querían ser capaces de guardar los "code points" de Unicode en "high-endian" o "low-endian" en función de si su procesador iba mas rápido en un sistema que en el otro. Entonces la gente estuvo forzada a adoptar la convención bizarra de guardar FE FF al principio de cada texto Unicode; esto se llama Unicode Byte Order Mark ( Marca de orden de bytes Unicode ), y, si tu estabas girando el orden tus bytes de mayor y menor peso, esta marca sería FF FE, así la persona que leyera tu texto sabría si tiene que girar el orden de los bytes o no. Ufff. No todos los textos Unicode tendría la marca de orden al principio, o sea que ya os podéis imaginar los problemas que conllevaría esto.

Durante un tiempo, esto parecía que debería suficiente, pero los programadores se estaban quejando y diciendo: "Ei! Mira todos estos ceros!", ya que ellos eran americanos y estaban mirando texto en inglés. El texto en inglés cumplía la propiedad de que rara vez habían "code points"por encima de U+00FF. También estaban los hippies liberales de California que querían conservar (grrr). Si fueran tejanos, no les habría importado el consumo del doble de memoria para guardar un texto en inglés ( chiste americano ). Pero los cobardes de California no podían soportar la idea de duplicar la cantidad de espacio almacenado para guardar textos. De todos modos habían muchos documentos antiguos por ahí almacenados en ANSI y DBCS. Y que iban a hacer, convertirlos todos? Ellos? Solo por esta razón hubo mucha gente que decidió hacer caso omiso a Unicode durante varios años, y por tanto la cosa empeoró.

Así, se inventó el concepto brillante de UTF-8. UTF-8 fue otro sistema para guardar "code points" en Unicode, pero solo usando 8 bits de memoria. En UTF-8, cada "code point" de 0 a 127 solo se guarda en un solo byte". Solo los "code points" de 128 para arriba se guardan en 2, 3, 4, 5 o 6 bytes.

Esto también tuvo un "efecto secundario" muy bueno en los textos escritos inglés. El texto era exactamente igual en UTF-8, que en ASCII, así que los americanos no verían nada extraño. Solo el resto del mundo debía pasar por el aro. Específicamente "Hello", que es: U+0048 U+0065 U+006C U+006C U+006F, se guardaría como: 48 65 6C 6C 6F!! Exactamente igual como se guardaría en ASCII y ANSI, y en todos los grupos de caracteres OEM del planeta! Ahora bien, si eres tan valiente como para utilizar letras acentuadas, o letras griegas o letras Klingon, tendrás que utilizar varios bytes para almacenar un "code point" único, pero los estadounidenses nunca se darán cuenta de eso.

Hasta ahora te he dicho tres formas de codificación Unicode. Los métodos tradicionales guardalo-en-dos-bytes son llamados UCS-2 ( por que tiene 2 bytes ) o UTF-16 ( porque tiene 16 bytes ), y uno todavía tiene que averiguar si se trata de UCS-2 big-endian o UCS-2 low-endian. Y también tenemos el nuevo y popular estándar UTF-8 que tiene la agradable propiedad de funcionar perfectamente bien con el texto en ingles ( tanto ASCII como ANSI ) y con programas que no tienen ni idea de que existan otras cosas que no sean ASCII.

Hoy en día hay un montón de otras formas de codificar Unicode. Hay algo llamado UTF-7, que se parece mucho a UTF-8 pero que garantiza que el mayor bit va a ser siempre cero. Si tienes, por ejemplo, algún tipo de servidor de correo nazi, que cree que 7 bits son "suficientes, gracias", todavía puedes salir ileso y enviar tus e-mails codificándolos con UTF-7. También hay UCS-4, que guarda cada "code point" en 4 bytes, y tiene la bonita propiedad de que cada "code point" puede ser guardado en el mismo número de bytes, pero, caramba! Incluso la gente de Texas no sería tan osada como para gastar tanta memoria.

De hecho, ahora que estás pensando en la idea platónica que representan los "code points" en Unicode, te puedes dar cuenta que estos "code points" se pueden encodear en cualquier encoding de la "vieja escuela". Por ejemplo, podrías encodear "Hello" ( U+0048 U+0065 U+006C U+006C U+006F ) en ASCII, o el OEM de Grecia, o en la codificación ASCII del Hebreo, o con cualquier codificación anteriormente inventada. Solo con una pega: dejarás de ver algunas letras! Si no existe ningún equivalente para el "code point" de Unicode en el encoding en el que lo estas intentando transformar, normalmente vas a ver el símbolo de pregunta, "?", o quizás puedes llegar a ver el símbolo �. Te suena?

Hay cientos de encodings tradicionales, que solo pueden almacenar ALGUNOS de los "code points" de Unicode. Los "code points" que no tienen una representación en el encoding viejo, se cambian por símbolos de interrogación. Algunos encodings populares en inglés son: Windows-1252 ( el estándar Europeo para Windows 9x ), y el ISO 8859-1 ( también llamado Latin-1 ), también usado por los idiomas del oeste Europeo. Pero intenta almacenar Ruso, o Hebreo en estos encodings, y solo vas a ver un montón de símbolos de interrogación. UTF 7, 8, 16 y 32 tienen la propiedad de poder almacenar cualquier "code point" de manera correcta.


La cosa mas importante sobre los encodings
==========================================
Si has olvidado todo lo que te acabo de explicar, por favor aprende una cosa muy importante. No tiene ningún sentido tener una cadena de texto sin saber que encoding usa. Ya no puedes seguir pensando que "texto claro" es ASCII.

El texto claro (plain text) no existe.

Si tu tienes un texto, en memoria, o en un fichero, o en un e-mail DEBES saber en que encoding ha sido guardado, o no serás capaz de mostrar los caracteres correctamente.

Casi todos los problemas estúpidos "mi web parece un galimatías" o "mi amiga no puede leer mi correo electrónico cuando lleva acentos", se reducen a que un programador ingenuo que no comprendía el simple hecho de que si no me dices como has codificado el texto, ya sea en UTF-8, o ASCII, o ISO-8859-1 o Windows 1252 yo SIMPLEMENTE no puedo mostrar correctamente el texto ( ni saber donde el texto termina )!

¿Dónde podemos preservar la información sobre qué codificación usa el texto que mandamos? Bueno, hay maneras estándar para hacer esto. Por ejemplo, para un correo electrónico, uno espera encontrar en la cabecera un string que ponga:

Content-Type: text/plain; charset="UTF-8"

Para una página web, la idea original era que el servidor web devolviese una cabecera (HTTP) con el Content-Type, ( y no en el HTML ). De manera que uno ya sepa la codificación de la página antes de recibir el HTML.

Esto da problemas. Imagina que tienes un gran servidor web con muchos sitios, y con cientos de páginas con contribuciones de gente de todo el mundo, en diferentes idiomas. Y que todas utilizan la codificación que quiera que use el Microsfot FrontPage. El servidor web no nunca sabrá realmente qué encoding tiene cada archivo, por lo que no podrá mandar una cabecera con el Content-Type.

Sería conveniente que pudieses poner un Content-Type en el HTML donde va el fichero mismo, utilizando algún tipo de tag especial. Por supuesto esto llevó a la locura a los puristas... "¿Cómo se puede leer un fichero HTML hasta que no sepas que codificación lleva?!" Por suerte, casi cada encoding común usa los mismos caracteres entre 32 y 127, entonces siempre podemos empezar a leer HTML sin ver caracteres estaños:


<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">


Por lo que el meta tag tiene que estar estar justo después de declarar la sección head ya que, tan pronto como el navegador web vea este tag, va a parar de interpretar la página y volverá a empezar reinterpretando toda la página con el encoding que has especificado.

¿Que hacen los navegadores si no encuentran ningún Content-Type y ningún tag en el header HTML? Internet Exploiter hace algo bastante interesante: intenta adivinar, basado en la frecuencia en la que aparecen algunos bytes en los típicos encodings en diferentes idiomas. Ya que varios encodings de 8 bits intentaban poner sus letras de su idioma nativo entre el rango entre 128 y 255, y ya que todos los idiomas tienen diferentes características de frecuencia en el uso de determinadas letras en texto escrito, se podía adivinar mas o menos el encoding en el que ha sido escrito el texto. Es bastante raro, pero parece funcionar bastante bien para las páginas programadas por ingenuos programadores que necesitarían echarle un vistazo a lo que es el Content-Type de su página web. ¿ Que pasa? Que si no se ajusta bien el encoding ( la detección falla ), y si Internet Exploiter decide que el idioma es coreano, pues el usuario que ha cargado la página no puede entender nada. Esto prueba, creo, la Ley de Postel sobre: "conservador en lo que dices y liberal en lo que aceptas" no es un principio bueno para un trabajo de ingeniería. De todos modos, ¿Qué hace el pobre lector que entra en una página escrita en búlgaro y la ve en coreano? Va al menú View>Encoding y prueba diferentes codificaciones (hay varias docenas de codificaciones en el Este de Europa ), hasta que ve bien el texto. Esto si sabe que puede hacerlo, claro, y mucha gente ni lo sabe.

Para la última versión de CityDesk un sitio de administración web publicado por mi compañía, decidimos internamente utilizar Unicode UCS-2 (dos bytes), que es el tipo nativo de Visual Basic, COM y Windows NT/2000/XP para los tipos de datos string. En C++, declarábamos los strings como wchar_t, en vez de char, y usábamos la función wcs en vez de str. Para crear un literal UCS-2 en C, simplemente poníamos un L antes, así quedaba algo como: L"Hello".

Cuando CityDesk publicó su página, se convirtió todo en UTF-8, que siempre ha sido una codificación muy bien soportada por todos los navegadores. Aquí tenemos el muro de las 29 versiones en las que está ecodeada la página de "Joel on Software", y yo nunca he escuchado a ninguna persona que haya tenido algún problema al visitar mi página.

Este artículo se está haciendo demasiado largo, y me es imposible explicar todo lo relacionado con la codificación de caracteres en Unicode, pero creo que si has leído hasta aquí, has aprendido suficiente como para volver a programar, y usar antibióticos, en vez de sanguijuelas y hechizos.



--------------------------------------------------------------------------------------------------------



[1]: Teniendo en cuenta que mi nivel de inglés es bastante.... humilde. Aún así he hecho un gran esfuerzo para traducir del mejor modo que he podido el artículo. Se aceptan correcciones.

Nota: Se ha usado “cadena de texto” como sinónimo de “string”.
Nota2: Se ha cambiado intencionadamente “Internet Explorer(tm)(r)” por “Internet Exploiter”. Seguramente el autor no estaría de acuerdo con esto. Es un chiste fácil.
Nota 3: Si te ha gustado el artículo y eres un blogger, agradecería que creases un post mencionando el al artículo original ( o hacia esta traducción, o ambos ). Un mundo con mejor comprensión sobre el Unicode, es un mundo mejor. Gracias. ;)