A modo de explicación

Rickrolling

Enviado por jacobo el Jue, 26/06/2008 - 21:23

Hace poco alguien me preguntó qué era lo que pasaba con Rick Astley últimamente. Así que le tuve que explicar qué es el “Rick Roll”.

El Rick Roll es una broma de Internet, consistente en publicar un mensaje en un foro con un enlace que, supuestamente, apunta a alguna página interesante o a alguna información importante, pero que en realidad apunta a un video musical de la canción “Never Gonna Give You Up” de Rick Astley.

Los angloparlantes, a hacer esa bromita le llaman “Rick Rolling”, y al video le llaman “Rick Roll”. Y ya está, no hay más. Lo que pasa es que la bromita ha tenido tanto éxito que ahora hay Rick Rolls en todas partes: el 1 de abril pasado, todos los videos recomendados en la portada de Youtube eran Rick Rolls, en algunos programas de televisión pusieron el video después de decir que eran impactantes imágenes de algún tema de rabiosa actualidad, etc.

Y ahora que saben qué es un Rick Roll, si les interesa gastarle la bromita a alguien, aquí tienen un enlace al video de marras. De nada.

Cómo funciona el DNI electrónico

Enviado por jacobo el Mar, 24/06/2008 - 21:03

Hace un rato ha venido alguien para pedirme prestado mi lector de tarjetas inteligentes. Lo necesitaba para poder pagar sus impuestos (no está mal, lo hace bastante pronto, una semana antes de que acabe el plazo) usando su DNI electrónico para identificarse. Cuando le expliqué cómo instalar los controladores y utilizar el cacharro noté que no tenía muy claro cómo funcionaba la cosa, así que he decidido escribir una explicación aquí.

Lo que se utiliza hoy en día para comunicarse de forma segura a través de Internet es la criptografía de clave pública. Esto es un sistema por el que puedo generar dos claves para cifrar y descifrar mensajes, de forma que lo que se cifra con una de las claves sólo se puede descifrar con la otra, y viceversa.

Una de las claves me la guardo bien guardada y no se la comunico a nadie (clave privada) y la otra la disemino libremente, y se la doy a todos los que quiero que se puedan comunicar de forma segura conmigo (clave pública). Todo lo que alguien cifre con mi clave pública sólo se puede descifrar con mi clave privada (por lo que se puede asegurar de que sólo yo lo puedo leer) y sólo lo que yo cifre con mi clave privada se puede descifrar con mi clave pública (por lo que puedo dar garantías de que un mensaje procede de mi).

Los sitios web seguros también utilizan criptografía de clave pública; a las claves públicas les llaman “certificados”, y los certificados van a su vez firmados por otras organizaciones (llamadas “autoridades certificadoras”) que garantizan que los certificados pertenecen a quien dicen pertenecer.

Por ejemplo, si accedo a https://www.tarrio.org, el servidor firma su respuesta utilizando su clave privada, y yo puedo descifrar la firma usando el certificado de www.tarrio.org, y puedo verificar que el certificado es válido porque va firmado por una autoridad certificadora en la que confío, entonces puedo estar seguro de que he accedido realmente a www.tarrio.org.

Esto también puede funcionar al revés: si yo accedo a la web de Hacienda diciendo que soy Jacobo Tarrío y firmo la conexión con mi clave privada, y el servidor web de Hacienda puede descifrar la firma con mi clave pública que dice que soy Jacobo Tarrío, y esta clave pública va firmada por una autoridad certificadora en la que Hacienda confía, entonces el servidor web de Hacienda puede estar seguro de que yo soy Jacobo Tarrío.

Normalmente, la lista de autoridades certificadoras en las que confío está almacenada en el navegador. También puedo obtener uno o más certificados de usuario, y guardarlos en el navegador para poder usarlos para identificarme cuando navego. Por ejemplo, con el certificado digital emitido por la FNMT puedo pagar mis impuestos o acceder a mis datos de la Seguridad Social, ya que los servidores web de Hacienda y de la Seguridad Social confían en los certificados firmados por la FNMT.

El DNI electrónico es una “tarjeta inteligente” (o “Smart Card” para los anglófilos). Las tarjetas inteligentes tienen un chip que puede servir para muchas cosas; el chip del DNI electrónico contiene un certificado de usuario y su correspondiente clave privada. Mi navegador puede utilizarlos para identificarme ante los servidores web igual que en el caso anterior.

Aquí hay una imagen del DNI electrónico.

Para evitar que alguien pueda, simplemente, hacerse con mi DNI, copiar el certificado y clave privada a su navegador, y luego hacerse pasar por mi, las tarjetas criptográficas están diseñadas de forma que es imposible acceder a la clave privada. Se puede acceder libremente al certificado de usuario, pero la clave privada es totalmente inaccesible desde fuera de la tarjeta.

Así que, si no se puede acceder a la clave privada, ¿cómo puede el navegador usar el DNI electrónico para garantizar mi identidad?

La solución es muy simple. El chip del DNI electrónico no sólo contiene mi clave pública y mi clave privada. Este chip también contiene un microordenador especializado en cifrar y descifrar datos. Este microordenador sí tiene acceso a mi clave privada, así que puede firmar y descifrar datos en mi nombre. Por lo tanto, cuando el navegador necesita firmar o descifrar algo, lo envía al microordenador del DNI electrónico en lugar de hacerlo él mismo.

Para aumentar la seguridad, la clave privada también está cifrada dentro del chip utilizando una contraseña que sólo yo conozco. Para poder firmar o descifrar datos utilizando esta clave privada, primero es necesario descifrarla, y para eso he de introducir mi contraseña. Si alguien me roba el DNI e intenta usarlo para acceder a la web de mi banco, no podrá hacerlo sin conocer la contraseña de mi DNI.

Al final, todo esto significa que, cuando me identifico ante un servidor web utilizando el certificado de usuario del DNI electrónico, el servidor web puede estar seguro de que, realmente, mi DNI está conectado al ordenador que yo estoy usando.

Devolución injustificada

Enviado por jacobo el Lun, 21/05/2007 - 17:22

Hace tiempo estuve programando unas cosillas en el lenguaje C. En eso que estuve programando había una serie de estructuras de datos, y había hecho funciones que reservaban espacio en memoria para esas estructuras, las inicializaban y devolvían el espacio recién inicializado. O sea, que tenía funciones similares a esta:

struct datos *datos_new(void) {
  struct datos *ret = malloc(sizeof(struct datos));
  ret->duracion = 0;
}

Compilé este código y lo probé, y funcionó. Sin embargo, unas horas más tarde se me ocurrió hacer que el compilador avisara de todos los problemas que encontrara, y salió este error:

datos.c: In function 'datos_new':
datos.c:10: warning: control reaches end of non-void function

Este error significa que, aunque había declarado que la función devolvía un valor (un puntero a una posición de memoria), no le había añadido la orden para hacerlo. Sin embargo, a pesar de tener este error, el código funcionaba. ¿Cómo era posible?

Esto es fácil de explicar, aunque para hacerlo tengo que explicar brevemente cómo se compila un programa.

Yo le proporciono ese código en C a un compilador de C, y este compilador transforma mi programa en una serie de instrucciones de código máquina. Estas instrucciones son las que entiende el ordenador directamente.

Hay una serie de convenciones obedecidas por todos los compiladores para un lenguaje, sistema operativo y ordenador dado. Estas convenciones gobiernan, por ejemplo, cómo se organizan los datos y cómo se hacen las llamadas a función.

Las convenciones para los compiladores de C para Linux en un PC dicen que para llamar a una función, primero hay que introducir sus argumentos en una zona de la memoria llamada “pila”; luego se pasa el control a la función mediante la orden “CALL”, y al volver la función, el resultado tiene que estar en el registro EAX.

(Los registros de la CPU son zonas de memoria extremadamente pequeñas situadas dentro de la CPU y que son las que se utilizan para operar, en lugar de utilizar la memoria del sistema. Los datos se copian de memoria a los registros, se opera y el resultado queda en los registros. Luego se lo puede copiar de los registros a la memoria o dejarlo en los registros para usarlo en posteriores operaciones).

Sabiendo esto, es fácil saber por qué la función “datos_new” devolvía la posición de memoria a pesar de no tener una instrucción “return” que devolviera este valor: después de llamar a la función “malloc”, el resultado de esta llamada estaba en EAX. Como no se modificaba después el contenido del registro EAX, este valor seguía ahí al volver de la función “datos_new”. Por lo tanto, la función “datos_new” devolvía el resultado de “malloc”, que era el valor correcto.

Y por eso mi función, a pesar de tener un error gordo, funcionaba.

Aún así, al final le puse una instrucción “return” para asegurarme :-)

Los fregados en los que me meto

Enviado por jacobo el Mar, 23/01/2007 - 19:28

Esto no es una pregunta, sino algo que les enseño para qué vean en qué jardines me meto yo solo (y a qué venía lo de ayer). Aquí hablo de programación y enseño código en Java y es largo (aunque no tanto como parece), así que si esto no es lo suyo, les eximo de la obligación de leerlo. De todos modos, me he esforzado en hacerlo apto para todos los públicos, así que hagan un esfuerzo, porfa. Luego me dicen en un comentario qué les ha parecido.

Estoy haciendo una aplicación web en Java; por un lado, reaprendiendo cosas que se supone que ya sabía (algo de Java por aquí, algo de Struts por allá, ...) y aprendiendo cosas nuevas para mi (Hibernate, Eclipse, etc.).

Esta aplicación es el típico programa de gestión en el que se tiene una base de datos con unas cuantas tablas sobre las que hay que realizar siempre los mismos tipos de operaciones. Es decir, tengo una tabla de clientes y tengo que poder añadir, listar, modificar, buscar y borrar clientes; tengo otra tabla de proveedores y tengo que poder añadir, listar, modificar, buscar y borrar proveedores; tengo otra tabla de productos y tengo que...

Mientras exploraba el entorno y las APIs y, en general, aprendía a programar el programa, me hice un prototipo de la parte que gestiona los clientes: la clase que accede a los datos, las clases que realizan las acciones que solicita el usuario en su navegador, las páginas JSP que muestran los datos y los formularios, etc.

Una vez que funcionó todo, y aprovechando que ya tenía prácticamente definido el esquema de la base de datos, me puse a modelarla en el Hibernate y después hice copias de la clase que accede a los datos del Cliente, modificándolas para las otras clases, y así acabé con unas clases con unos interfaces similares a esto:

public class ClienteOps {
  public Cliente getCliente();
  public void crearCliente();
  public void cargarCliente(long id);
  public void grabarCliente();
  public void borrarCliente();
  public static List listaClientes();
}

public class ProveedorOps {
  public Proveedor getProveedor();
  public void crearProveedor();
  public void cargarProveedor(long id);
  public void grabarProveedor();
  public void borrarProveedor();
  public static List listaProveedores();
}

public class ProductoOps {
  public Producto getProducto();
  public void crearProducto();
  public void cargarProducto(long id);
  public void grabarProducto();
  public void borrarProducto();
  public static List listaProductos();
}

Enseguida vi (en realidad lo sabía antes de empezar) que estaba cometiendo el error fatal de la muerte número 1: me estaba repitiendo más que el ajo. Tenía un montón de código casi igual, y lo estaba copiando, y si había un error en una parte tendría que corregirlo en todas las clases, y si hacía una mejora tendría que arreglarla en todas las clases, y...

Se imponía simplificar esto. En primer lugar, dejar “cargaProducto”, “cargaCliente”, etc., en sólo “carga”, “grabaLoQueSea” en sólo “graba”, etc. En segundo lugar, crear una superclase que contenga las funciones comunes, y dejar lo específico en las subclases:

abstract public class AbstractOps<T> {
  public T get();
  public void crear();
  public void cargar(long id);
  public void grabar();
  public void borrar();
  public static List lista();
}

public class ClienteOps extends AbstractOps<Cliente> { }

public class ProveedorOps extends AbstractOps<Proveedor> { }

public class ProductoOps extends AbstractOps<Producto> { }

Ese <T> es lo que la especificación de Java llama una “variable de tipo”. Lo que quiere decir es que yo puedo poner esa T donde normalmente pondría el nombre de una clase, y después le puedo decir a Java “oye, lo que te dije antes de que era T, pues no, que es Cliente”, o Proveedor, o Producto... Y eso es lo que hice: creé una superclase con toda la funcionalidad, pero donde antes ponía Cliente, o Producto, o lo que fuera, ahora ponía T. Luego creé varias subclases vacías, y en cada una le decía “la clase ClienteOps es una subclase de AbstractOps que hereda toda su funcionalidad sustituyendo T por Cliente”, y así sucesivamente, y así solucionaba el problema sin escribir más líneas de código de las justas. O sea: esto es la pera, Java es la hostia y yo soy un puto genio.

Pues no.

Aquí creo que hay gente que sabe más de Java de lo que yo sabía ayer a estas horas y ya sabrá cuál era el problema; y si no, lo explico. Esto de las variables de tipo sirve para sustituir los nombres de las clases a la hora de compilar en las declaraciones de las variables y de los atributos y de las funciones miembro y de otras clases, etc. Sin embargo, no sirve a la hora de ejecutar para crear una instancia de una clase o para obtener un objeto de una clase, o...

O, viéndolo en código:

class C<T> {
  void fun() {
    T a = new T(T.class);
  }
}

En la línea del medio, la que contiene “new”, la primera T está bien puesta porque está en la definición de una variable. Sin embargo, ni la segunda ni la tercera valen.

Y créanme que en la clase AbstractOps había muchas cosas como la segunda y la tercera T. O sea, que la solución, tal como estaba, no servía. Había que arreglarlo de alguna manera. ¿Cómo? Pues esto es lo que probé:

abstract public class AbstractOps<T> {
  protected static Class<?> clase;
  public T get();
  public void crear();
  public void cargar(long id);
  public void grabar();
  public void borrar();
  public static List lista();
}

public class ClienteOps extends AbstractOps<Cliente> {
  protected static Class<?> clase = Cliente.class;
}

... y así sucesivamente.

Y, si se fijan, es aquí donde me encontraron ayer. El método "lista" es estático, y dentro de él tengo que hacer referencia a la propia clase (para decirle a Hibernate de qué objetos hay que hacer una lista), y no podía obtener la referencia mediante una variable de tipo, sino que tenía que guardarla en una variable estática que definía en cada subclase. Pero, claro, cuando ejecutaba ClienteOps.lista() me salía una excepción como una casa porque intentaba acceder a una variable no inicializada (porque se ejecutaba el método lista() de AbstractOps, que accedía al atributo estático "clase" de AbstractOps, que no está inicializado).

Así que al final he hecho lo que dije en el comentario 4 de la historia anterior y me ha quedado algo parecido a esto:

abstract public class AbstractOps<T> {
  protected Class<?> clase = laClase();
  protected abstract Class<?> laClase();
  public T get();
  public void crear();
  public void cargar(long id);
  public void grabar();
  public void borrar();
  public List lista();
}

public class ClienteOps extends AbstractOps<Cliente> {
  protected Class<?> laClase() { return Cliente.class; }
}

Y ahora funciona correctamente. Ahora sí que soy un puto genio. Lo único malo es que así la función miembro "lista()" no es de clase, sino de instancia, pero bueno, no me quejo...

Y, por supuesto, ahora que he contado todo esto, resultará que habrá un método mucho mejor que conoce todo el mundo menos yo, y habré quedado como un idiota :-) Por favor, ilumínenme...

Una pregunta para el respetable

Enviado por jacobo el Lun, 22/01/2007 - 23:41

Hoy, para variar, tengo una pregunta para mis lectores (si es que me queda alguno).

Resulta que estoy programando algo en Java; sin embargo, no estoy muy ducho en ese lenguaje. Mientras trataba de simplificar una situación en la que me estaba repitiendo muchas veces, he llegado a otra situación en la que obtengo los resultados que no me interesan, y no sé cómo hacer que funcione como yo quiero.

Esta situación se puede ilustrar mediante el siguiente código:

abstract public class Super {
  private static String texto = "Super";

  public static void run() {
    System.out.println(texto);
  }
}

class Sub extends Super {
  private static String texto = "Sub";
}

class Principal {
  public static void main(String[] args) {
    Sub.run();
  }
}

Alguien muy ingenuo (o sea, yo hace unas horas) pensaría que al ejecutar el programa aparecería en la pantalla la palabra “Sub”, ya que se ejecuta el método “run” de la clase “Sub”, en la que el atributo “texto” se define para que tenga el valor “Sub”.

Pues no; aparece “Super”.

Esto es porque como el método “run” no está definido en “Sub”, se ejecuta el de su clase antecesora, que es “Super”. Y, como en “Super” el atributo “texto” tiene el valor “Super”, aparece en la pantalla un “Super” como una casa.

Pues bien; una vez que entiendo por qué sucede esto... ¿puedo evitarlo? ¿Puedo hacer que aparezca “Sub” en la pantalla? (Y que la respuesta, por supuesto, no consista en cambiar “Super” por “Sub” en el código fuente ;-) )

Se agradecen las respuestas en los comentarios.

Actualización: ya he decidido lo que voy a hacer al final, en el cuarto comentario.

L10n e i18n, vaya sopa de l4s.

Enviado por jacobo el Lun, 30/10/2006 - 18:03

Cuando hay que adaptar un programa para que se pueda utilizar en varios países, lo primero en lo que piensa uno es en las traducciones. Sin embargo, traducir un programa a otro idioma no es más que el primer paso.

La gente que estudia la adaptación del software y del hardware para que se pueda utilizar en varias partes del mundo distingue entre dos conceptos. El primero es la internacionalización, que consiste en modificar el sistema (software, hardware, ...) para que sea posible adaptarlo a otro país, otro idioma, otra cultura... El segundo paso es la localización, que consiste en tomar un sistema y adaptarlo a un país, idioma y cultura concretos.

Como los que se dedican a ese tema utilizan las palabras “internacionalización” y “localización” muy a menudo, las han abreviado, llamando a la primera i18n y a la segunda l10n. Estos jeroglíficos son fáciles de recordar si se observa que la palabra “internacionalización” empieza por la letra “i”, le siguen 18 letras, y termina por la letra “n”, (“i”-18-“n”) y que la palabra “localización” empieza por la “l”, le siguen 10 letras, y termina también en “n” (“l”-10-“n”). Anda que son listillos...

Si uno quiere que un programa quede bien localizado, antes tiene que estar bien internacionalizado. Lo mínimo es que se pueda traducir; para ello existe un montón de sistemas, entre los cuales mi favorito es GNU Gettext. Con Gettext, el programador tiene que marcar las cadenas de texto que el usuario va a ver; después, con un conjunto de herramientas especiales esas cadenas se pueden extraer, y luego los traductores pueden trabajar sobre esas cadenas, traducirlas y hacer que el programa pueda utilizar esas traducciones sin tener que recompilarlo. Existen herramientas para editar traducciones, actualizar traducciones para adaptarlas a nuevas versiones de los programas, gestionar traducciones que proceden de muchas fuentes, etc.

Pero la traducción del software no es lo único que se ha de tener en cuenta. Por ejemplo, el programa debería aceptar (y tratar correctamente) caracteres propios de idiomas distintos del inglés. Hasta no hace mucho, muchos programas no podían tragar la eñe, y ahora se les pide que traguen la eñe (ñ), el sigma (Σ), el alef (א), unos cuantos caracteres árabes como ش, ت o ﺿ, e incluso unos cuantos caracteres coreanos (y, lamentablemente, acabo de ver que no tengo instalado un tipo de letra coreano). Para esto, el programa debe utilizar correctamente Unicode, un conjunto de especificaciones para la codificación y empleo de los alfabetos de los lenguajes de todo el mundo. Hay un montón de idiomas y un montón de reglas, pero afortunadamente, es relativamente fácil hacerlo... pero antes hay que saber que todo eso existe.

Lo que separa a la gente no es sólo el idioma. Otra cosa que se ha de tener en cuenta al internacionalizar un programa es que en distintas partes del mundo se utilizan distintos estándares. Por ejemplo, los estadounidenses pagan y cobran en dólares, miden en pulgadas, pesan en libras e imprimen en papel de tamaño “legal” o “letter”, mientras que los españoles pagamos y cobramos en euros, medimos en metros y centímetros, pesamos en kilogramos e imprimimos en papel de tamaño DIN A4. Además, cuando te dan un precio, los estadounidenses ponen el símbolo del dólar antes del número ($400) y los españoles ponemos el símbolo del euro después del número (400 €). Ellos usan un punto para separar los decimales y una coma para separar los miles (4,394,394.93), y nosotros al revés (4.394.394,93). Y ellos escriben las fechas poniendo el día entre el mes y el año (03-24-1999) y nosotros ponemos el mes entre el día y el año (24-03-1999).

Por si esto parecía poco, los japoneses dan las fechas diciendo primero el año, luego el mes y finalmente el día (1999-03-24), y los indios (de la India) no escriben los números separando los dígitos de tres en tres, sino de dos en dos a partir del cuarto (4,39,4394.93).

Todas esas diferencias, y muchas más, se han de tener en cuenta al internacionalizar un programa. Afortunadamente, los sistemas operativos proporcionan funciones para formatear correctamente los números y las fechas, y los sistemas de impresión saben qué tipo de papel han de ofrecer al usuario según el país en el que se encuentre. Igual que antes, no es difícil; sólo es necesario saber que todo esto existe.

Pero aún hay más. Si su programa trata datos de usuarios, tendrá que tener en cuenta que en cada país los datos que ha de solicitar son distintos. Por ejemplo, en los Estados Unidos tienen un solo apellido, mientras que en España tenemos dos apellidos (el primero del padre y de la madre, respectivamente). En Portugal también tienen dos apellidos, pero son el segundo de la madre y del padre, respectivamente (además, el segundo apellido es el que se utiliza para ordenar listas o cuando se abrevia el nombre). En Rusia, además de nombre y apellido tienen patronímico. Los nativos de Java no tienen apellido. Los húngaros dicen el apellido antes que el nombre.

Y esto para empezar: en muchos países no se utilizan códigos postales (o no se utilizan fuera de algunas ciudades, como en Irlanda), las direcciones se escriben de forma muy diferente dependiendo del país, las madres pueden no tener apellidos de soltera...

Por eso es recomendable que dejen a los usuarios bastante libertad para proporcionar su información, si pretenden que puedan acceder usuarios de todo el mundo: hay tantas variantes, que preverlas todas es muy complicado.

Y hasta aquí mi “pequeño” artículo de hoy. Espero que estén tan maravillados como yo por todas las formas de complicarse la vida que puede inventar el ser humano. Si les ha gustado el tema y quieren que escriba más sobre él, en mi wishlist de Amazon hay un libro sobre internacionalización; ustedes me lo compran, yo me lo leo y escribo.

Si cuela, cuela.

Arreglado planet.gpul.org

Enviado por jacobo el Lun, 13/03/2006 - 23:31

Por fin he arreglado Planet GPUL. He descargado la última versión de Planet Planet (via Bazaar, qué cosa más horrible) y he copiado (como he podido la configuración).

Ahora la configuración está en pule:/var/www/planet.gpul.org/planet-gpul, para quien quiera modificarla. He trasladado la vieja instalación de Planet a una "morgue", por si necesitamos rescatar algo de ella.

Ahora, a disfrutarlo.

Cócteles Molotov

Enviado por jacobo el Lun, 20/06/2005 - 23:09

La Audiencia Nacional dice que Jarrai no es un grupo terrorista porque, aunque perseguían los mismos objetivos que ETA, no utilizaban armas.

Pues ya que los cócteles Molotov no son armas, vamos a hablar de ellos.

Una foto de copas de cóctel ardiendo ilustra este artículo. Los cócteles Molotov son un tipo de bomba incendiaria. Fueron inventados por las milicias republicanas durante el sitio de Madrid; más tarde se utilizaron como arma anticarro durante la “Guerra de Invierno”, que enfrentó a Finlandia y la Unión Soviética en el año 1939, y en la que recibieron su nombre actual.

Por aquella época, Vyacheslav Molotov tenía en la URSS el cargo equivalente al de Ministro de Asuntos Exteriores, y afirmaba en la radio que los aviones soviéticos no estaban lanzando bombas, sino raciones alimenticias humanitarias; a esto, los finlandeses respondieron que, ya que Molotov ponía la comida, ellos ponían los cócteles.

Los finlandeses convirtieron el cóctel Molotov en parte de su armamento anticarro, y llegaron a fabricarse de forma industrial en una planta embotelladora estatal.

Un cóctel Molotov se compone, en su forma más común, de una botella de vidrio rellena hasta la mitad de una mezcla a base de gasolina, aceite de motores y jabón líquido. Esta botella va tapada con un corcho o tapón de rosca, y sujeto al cuello de la botella va un trapo también empapado en algún líquido inflamable.

Para utilizar el cóctel Molotov, se prende fuego al trapo y se arroja la botella; al estrellarse ésta, el líquido que contiene se desparrama y se incendia con la llama del trapo. El aceite de motores hace que el cóctel Molotov produzca humo al arder (interesa por el efecto psicológico) y el jabón líquido hace que la mezcla inflamable se adhiera mejor a las superficies.

Y ya está. Si, llegados a este punto, a alguien le escandaliza que yo haya explicado cómo se hace un cóctel Molotov, que tenga en cuenta que esta información ya está disponible con sólo hacer una búsqueda en Google. Además, prácticamente cualquiera que haya visto un cóctel Molotov puede hacerse uno sin ayuda, aunque no sea del todo efectivo. De todos modos, recuerden que corren un grave riesgo de quemarse si andan jugando con fuego. ¡Mucho cuidado!.

Hala, bibliografía: artículo en Wikipedia, página sobre armas antitanque en la Guerra de Invierno, otra web sobre el particular.

Barajas (pero no el aeropuerto)

Enviado por jacobo el Jue, 16/06/2005 - 06:30

Cagüen... tenía yo aquí ayer de madrugada una historia la mar de buena sobre la baraja española, pero el disco duro del servidor comenzó a hacer extraños y se ve que restauraron una copia de seguridad de una hora antes, que se perdió. O, lo más probable, al final me olvidé de darle a “Publicar” :-)

En fin, en ella les comentaba que desde hace unas semanas tengo pensado programar un juego de Escoba en C# para aprender a usar Mono de una vez, que no quiero haber gastado 150 euros en libros para nada. El problema ahora mismo es que hace tiempo que no me apetece nada programar, así que...

Pero bueno, mientras no me llegan las ganas, he investigado un poco, porque resulta que a la Escoba se juega con una baraja española, y no he encontrado ninguna baraja española digitalizada que se pueda utilizar libremente (sí he encontrado una francesa), así que si quiero tener una baraja española en el juego me toca hacer una de estas tres cosas:

  • pedir permiso a Heraclio Fournier para digitalizar una baraja suya y distribuirla libremente (no creo que sea fácil convencerles de ello)
  • conseguir una baraja tan antigua como para que su diseño haya pasado al dominio público, digitalizarla y distribuirla libremente
  • aprender todo lo que pueda sobre las barajas y diseñarme una yo mismo (o pedirle a alguien que lo haga, pero tampoco es para ponerme a molestar)

A pesar de que dibujo como el carallo, esto último es lo que he decidido, de momento :-)

Cosas interesantes que he aprendido sobre la baraja:

La baraja española se compone de 48 cartas, divididas en 4 palos (“oros”, “copas”, “espadas” y “bastos”), cada uno de 12 cartas numeradas del 1 al 12. Cada naipe tiene dibujado el elemento que representa al palo, repetido tantas veces como indica su numeral (por ejemplo, el 3 de espadas tiene tres espadas dibujadas), salvo las cartas del 10, 11 y 12, que tienen pajes o infantes (“sotas”), caballeros (“caballos”) y reyes sosteniendo el atributo del palo, respectivamente.

En la mayoría de los juegos, las cartas 8 y 9 no se utilizan, por lo que muchas barajas se venden directamente sin ellas (son barajas de 40 naipes).

La baraja española está emparentada con la italiana, que posee los mismos palos, y en ciertas partes de Italia posee diseños similares a la baraja española.

Los naipes utilizados en España pertenecen a tres estilos distintos, principalmente: el estilo de Cádiz; el estilo catalán y el estilo castellano. Hoy en día se ven principalmente los estilos castellano y catalán; el estilo de Cádiz es un estilo muy antiguo en el que se fabricaban las cartas destinadas a la exportación.

También tenía ayer algo sobre el juego de la escoba, pero no hay mucho que decir si se conocen las reglas: es una versión del juego italiano de la “scopa di quindici”, que la única diferencia es un detalle a la hora de contar los puntos. Que casi todos están de acuerdo en que si, al repartir las cartas, se dejan 15 puntos sobre la mesa, éstos son para el que reparte, pero no todos están de acuerdo en el caso de los 30 puntos (algunos recogen, otros no). Y que en italiano el 7 de oros se llama “sette bello” (y supongo que por eso se llama “o belo” o “o velo” en gallego :-)

suministro XML