﻿<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
  <channel>
    <title>JuanCri.com Blog</title>
    <description>Blog de Juan C. Olivares</description>
    <link>http://www.juancri.com/</link>
    <lastBuildDate>Fri, 27 Jan 2012 03:19:37 GMT</lastBuildDate>
    <docs>http://backend.userland.com/rss</docs>
    <generator>RSS.NET: http://www.rssdotnet.com/</generator>
    <item>
      <title>Túnel para cualquier dispositivo</title>
      <description>&lt;p&gt;
	Perd&amp;oacute;n si el t&amp;iacute;tulo es malo, pero quiero mostrarles una manera elegante de poder enrutar las conexiones de cualquier dispositivo para que pueda conectarse a Internet como si estuviera en otro lugar, ya sea a Internet o una VPN.&lt;/p&gt;
&lt;h3&gt;
	Desktop&lt;/h3&gt;
&lt;p&gt;
	Mi problema original era poder utilizar Netflix como si estuviera en Estados Unidos, ya que el contenido es distinto. En OSX la soluci&amp;oacute;n es bastante simple: basta con conectarse por SSH a un servidor en Estados Unidos abriendo un proxy SOCKS (par&amp;aacute;metro -D&lt;em&gt;puerto&lt;/em&gt;) y luego configurar el navegador para que utilice ese proxy.&lt;/p&gt;
&lt;p&gt;
	Por ejemplo, supongamos que tenemos un servidor llamado servidor (&amp;iexcl;qu&amp;eacute; original!). Podemos ejecutar la siguiente l&amp;iacute;nea en el terminal:&lt;/p&gt;
&lt;p style="margin-left: 40px; "&gt;
	&lt;strong&gt;&lt;span style="font-family:courier new,courier,monospace;"&gt;ssh usuario@servidor -D1080&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;
	Este comando se conectar&amp;aacute; a servidor y abrir&amp;aacute; un puerto en el ambiente local (1080) el cual funciona como proxy SOCKS. Luego, en Firefox u otro navegador, podemos configurar el proxy SOCKS &lt;em&gt;localhost &lt;/em&gt;puerto 1080.&lt;/p&gt;
&lt;p&gt;
	Esta soluci&amp;oacute;n me funcion&amp;oacute; bastante bien hasta que quise utilizar el dispositivo Apple TV. En este caso, como su conexi&amp;oacute;n era por WiFi, y no tiene opci&amp;oacute;n de configurar una VPN, necesit&amp;eacute; encontrar una soluci&amp;oacute;n m&amp;aacute;s rebuscada.&lt;/p&gt;
&lt;h3&gt;
	Dispositivos&lt;/h3&gt;
&lt;p&gt;
	En el caso de dispositivos como Apple TV o similares, la &amp;uacute;nica opci&amp;oacute;n es enrutar el tr&amp;aacute;fico transparentemente, es decir, que el dispositivo no se de cuenta de que se est&amp;aacute; desviando el tr&amp;aacute;fico. Esto podr&amp;iacute;a ser simple si su router estuviera conectado a una VPN, ya que podr&amp;iacute;a enrutar ciertas conexiones (o todas) a trav&amp;eacute;s de esta VPN, sin embargo, el escenario cambia al usar SSH.&lt;/p&gt;
&lt;p&gt;
	Ten&amp;iacute;a dos desaf&amp;iacute;os:&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;
		Conectar el dispositivo a Internet a trav&amp;eacute;s de un PC&lt;/li&gt;
	&lt;li&gt;
		Enrutar el tr&amp;aacute;fico a trav&amp;eacute;s de la conexi&amp;oacute;n SSH&lt;/li&gt;
&lt;/ol&gt;
&lt;h4&gt;
	1.- Conectar el dispositivo a Internet a trav&amp;eacute;s de un PC&lt;/h4&gt;
&lt;p&gt;
	Supongamos que tenemos este esquema original:&lt;/p&gt;
&lt;p&gt;
	&lt;img alt="" src="http://juancri.com/imagenes/posts/nat-1.png" style="width: 280px; height: 265px; " /&gt;&lt;/p&gt;
&lt;p&gt;
	Para poder controlar el tr&amp;aacute;fico entre el dispositivo e Internet, podemos intervenir el router o agregar un nuevo eslab&amp;oacute;n en la cadena. Opt&amp;eacute; por lo segundo y el diagrama queda as&amp;iacute;:&lt;/p&gt;
&lt;p&gt;
	&lt;img alt="" src="http://juancri.com/imagenes/posts/nat-2.png" style="width: 282px; height: 356px; " /&gt;&lt;/p&gt;
&lt;p&gt;
	Para esto, en mi caso, utilic&amp;eacute; un cable ethernet entre el Dispositivo y el PC. Para la conexi&amp;oacute;n entre el PC y el Router ISP, utilic&amp;eacute; Wi-Fi. Este escenario es muy com&amp;uacute;n. Para permitir que el PC sea capaz de enrutar el tr&amp;aacute;fico, se utiliza NAT (&lt;em&gt;network address translation&lt;/em&gt;). En Linux, se utiliza iptables para esta tarea.&lt;/p&gt;
&lt;p&gt;
	NAT funciona modificando cada paquete. Cuando un paquete de datos va desde el Dispositivo a Internet, se modifica la direcci&amp;oacute;n de origen reemplaz&amp;aacute;ndola por la direcci&amp;oacute;n del PC. Cuando el paquete llega al PC desde Internet, se cambia la direcci&amp;oacute;n de destino para que apunte al Dispositivo y luego se reenv&amp;iacute;a al dispositivo. De esta forma, el Router ISP s&amp;oacute;lo sabe que est&amp;aacute; recibiendo y enviando paquetes desde y hacia el PC. Todo el trabajo de conversi&amp;oacute;n se lo lloeva el PC, en este caso.&lt;/p&gt;
&lt;p&gt;
	Supongamos que el PC tiene las siguientes interfaces de red:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;
		eth0 hacia el Router ISP&lt;/li&gt;
	&lt;li&gt;
		eth1 hacia el Dispositivo&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
	Para configurar NAT, debemos ejecutar los siguientes comandos (como root):&lt;/p&gt;
&lt;p style="margin-left: 40px; "&gt;
	&lt;strong&gt;&lt;span style="font-family:courier new,courier,monospace;"&gt;# Habilitar el reenv&amp;iacute;o de paquetes en el sistema&lt;br /&gt;
	echo 1 &amp;gt; /proc/sys/net/ipv4/ip_forward&lt;br /&gt;
	# Enmascarar el tr&amp;aacute;fico hacia Internet&lt;br /&gt;
	iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE&lt;/span&gt;&lt;/strong&gt;&lt;br /&gt;
	&lt;strong&gt;&lt;span style="font-family:courier new,courier,monospace;"&gt;# Permitir que los paquetes que vienen desde Internet y que pertenecen a una conexi&amp;oacute;n ya establecida,&lt;br /&gt;
	# puedan pasar hacia el dispositivo&lt;/span&gt;&lt;/strong&gt;&lt;br /&gt;
	&lt;strong&gt;&lt;span style="font-family:courier new,courier,monospace;"&gt;iptables -A FORWARD -i eth0 -o eth1 -m state --state RELATED,ESTABLISHED -j ACCEPT&lt;/span&gt;&lt;/strong&gt;&lt;br /&gt;
	&lt;strong&gt;&lt;span style="font-family:courier new,courier,monospace;"&gt;# Permitir el tr&amp;aacute;fico desde el Dispositivo hacia Internet&lt;/span&gt;&lt;/strong&gt;&lt;br /&gt;
	&lt;strong&gt;&lt;font face="'courier new', courier, monospace"&gt;iptables -A FORWARD -i eth1 -o eth0 -j ACCEPT&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;div&gt;
	Una vez hecho esto, s&amp;oacute;lo basta configurar manualmente las interfaces tanto en el PC como en el dispositivo. Tambi&amp;eacute;n es posible habilitar DHCP en la interfaz eth1, lo que evitar&amp;iacute;a tener que configurar la direcci&amp;oacute;n IP manualmente en el Dispositivo. Pueden Googlearlo :)&lt;/div&gt;
&lt;div&gt;
	&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
	Un punto importante a &amp;nbsp;tener claro es que las direcciones de red en eth0 y eth1 deben ser distintas. Por ejemplo, si el router ISP nos entrega una direcci&amp;oacute;n IP de la red 192.168.0.0/24 (la m&amp;aacute;scara 24 significa que la red es 192.168.0.X), la direcci&amp;oacute;n en eth1 debe pertenecer a otra red (por ejemplo, 192.168.1.0/24).&lt;/div&gt;
&lt;div&gt;
	&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
	En este punto, ya deber&amp;iacute;amos poder utilizar el PC como puente para el Dispositivo, aunque todav&amp;iacute;a falta enrutar el tr&amp;aacute;fico hacia el servidor SSH.&lt;/div&gt;
&lt;h4&gt;
	2.- Enrutar el tr&amp;aacute;fico a trav&amp;eacute;s de la conexi&amp;oacute;n SSH&lt;/h4&gt;
&lt;div&gt;
	Si bien, muchas veces he configurado un puente con NAT, el enrutamiento hacia un servidor SSH era lo novedoso para m&amp;iacute; :) Para esto, la forma m&amp;aacute;s simple que encontr&amp;eacute; es utilizando la conexi&amp;oacute;n SOCKS que provee SSH; la misma que utilic&amp;eacute; en el ambiente de escritorio, pero esta vez sin configurar el proxy en el Dispositivo, sino en el puente.&lt;/div&gt;
&lt;div&gt;
	&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
	Para lograrlo, podemos crear una tercera interfaz de red en el PC, pero esta vez, esta interfaz es virtual y env&amp;iacute;a todo el tr&amp;aacute;fico hacia un servidor SOCKS. Este proceso es muy simple utilizando tun2socks, disponible &lt;a href="http://code.google.com/p/badvpn/wiki/tun2socks"&gt;aqu&amp;iacute;&lt;/a&gt;.&lt;/div&gt;
&lt;div&gt;
	&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
	tun2socks se encarga de subir una interfaz virtual y enrutar todo el tr&amp;aacute;fico que recibe a trav&amp;eacute;s de un servidor SOCKS. Para poder utilizarlo, antes debemos tener nuestra conexi&amp;oacute;n SSH abierta, de la misma forma que lo hice en el ambiente de escritorio:&lt;/div&gt;
&lt;div&gt;
	&amp;nbsp;&lt;/div&gt;
&lt;div style="margin-left: 40px; "&gt;
	&lt;strong&gt;&lt;span style="font-family: 'courier new', courier, monospace; "&gt;ssh usuario@servidor -D1080&lt;/span&gt;&lt;/strong&gt;&lt;/div&gt;
&lt;div&gt;
	&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
	Ahora, podemos ejecutar tun2socks:&lt;/div&gt;
&lt;div&gt;
	&amp;nbsp;&lt;/div&gt;
&lt;div style="margin-left: 40px; "&gt;
	&lt;strong&gt;&lt;span style="font-family:courier new,courier,monospace;"&gt;./badvpn-tun2socks --tundev tun0 \&lt;br /&gt;
	&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; --netif-ipaddr 192.168.100.2 \&lt;br /&gt;
	&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; --netif-netmask 255.255.255.0 \&lt;br /&gt;
	&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; --socks-server-addr 127.0.0.1:1080&lt;/span&gt;&lt;/strong&gt;&lt;/div&gt;
&lt;div&gt;
	&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
	Los par&amp;aacute;metros utilizados aqu&amp;iacute; son:&lt;/div&gt;
&lt;div&gt;
	&amp;nbsp;&lt;/div&gt;
&lt;ul&gt;
	&lt;li&gt;
		&lt;strong&gt;&lt;span style="font-family: 'courier new', courier, monospace; "&gt;--netif-ipaddr 192.168.100.2&lt;/span&gt;&lt;/strong&gt;: Configura la direcci&amp;oacute;n IP del gateway virtual que tendremos en la interfaz. Es decir, esta no es la direcci&amp;oacute;n que tendr&amp;aacute; nuestro PC en esta interfaz virtual, sino el gateway o router [tambi&amp;eacute;n virtual] que deberemos utilizar en esa interfaz.&lt;/li&gt;
	&lt;li&gt;
		&lt;strong&gt;&lt;span style="font-family: 'courier new', courier, monospace; "&gt;--netif-netmask 255.255.255.0&lt;/span&gt;&lt;/strong&gt;: La m&amp;aacute;scara de la interfaz. Generalmente 255.255.255.0 (24 bits) est&amp;aacute; bien.&lt;/li&gt;
	&lt;li&gt;
		&lt;strong&gt;&lt;span style="font-family: 'courier new', courier, monospace; "&gt;--socks-server-addr 127.0.0.1:1080&lt;/span&gt;&lt;/strong&gt;: Direcci&amp;oacute;n&amp;nbsp;y puerto donde est&amp;aacute; corriendo el servidor SOCKS. Ya que utilizamos -D1080 en el comando SSH, &amp;eacute;se es el&amp;nbsp;puerto que definimos aqu&amp;iacute;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
	Una vez ejecutado este comando, ya se habr&amp;aacute; creado una nueva Interfaz, sin embargo, a&amp;uacute;n tenemos que configurar la interfaz en el PC y las rutas para que el tr&amp;aacute;fico a ciertas -o todas- las direcciones vaya a trav&amp;eacute;s de esta interfaz virtual.&lt;/p&gt;
&lt;p&gt;
	Para configurar la interfaz en el PC local, debemos ejecutar:&lt;/p&gt;
&lt;p style="margin-left: 40px; "&gt;
	&lt;span style="font-family:courier new,courier,monospace;"&gt;&lt;strong&gt;ifconfig tun0 192.168.100.1 netmask 255.255.255.0&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;
	Pueden notar que la direcci&amp;oacute;n local en la interfaz virtual (192.168.100.1) est&amp;aacute; en la misma red que la direcci&amp;oacute;n del router virtual (192.168.100.2). Esto es imprescindible.&lt;/p&gt;
&lt;p&gt;
	&amp;Eacute;ste deber&amp;iacute;a ser el estado actual:&lt;/p&gt;
&lt;p&gt;
	&lt;img alt="" src="http://juancri.com/imagenes/posts/nat-3.png" style="width: 481px; height: 366px; " /&gt;&lt;/p&gt;
&lt;p&gt;
	En este paso debemos tener mucho cuidado. Ya que esta interfaz virtual depende de nuestra conexi&amp;oacute;n SSH, debemos asegurarnos de que el tr&amp;aacute;fico hacia el servidor SSH siga saliendo directamente por el Router ISP. Tambi&amp;eacute;n debemos tener claro que SOCKS s&amp;oacute;lo soporta conexiones TCP (y no UDP, ICMP o cualquier otro tipo). Esto previene que usemos la configuraci&amp;oacute;n actual para enrutar las consultas al DNS, ya que el protocolo DNS utiliza principalmente UDP. A fin de cuentas, necesitamos mantener tanto el tr&amp;aacute;fico al servidor SSH como al DNS a trav&amp;eacute;s del router ISP. Para esto, ejecutamos los siguientes comandos:&lt;/p&gt;
&lt;p style="margin-left: 40px; "&gt;
	&lt;strong&gt;&lt;span style="font-family:courier new,courier,monospace;"&gt;# Agregamos el servidor SSH (en este ejemplo 1.2.3.4)&lt;br /&gt;
	# hacia 192.168.0.1 suponiendo que es la direcci&amp;oacute;n del Router ISP.&lt;br /&gt;
	# Utilizamos la m&amp;eacute;trica 5 para que tenga prioridad sobre otras reglas&lt;br /&gt;
	route add 1.2.3.4 gw 192.168.0.1 metric 5&lt;br /&gt;
	# Agregamos el servidor DNS (en este caso, un servidor de Google)&lt;br /&gt;
	route add 8.8.8.8 gw 192.168.0.1 metric 5&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;
	En este momento, ya podemos eliminar la ruta por defecto actual, que utiliza el Router ISP, y cambiarla por una ruta hacia nuestro router virtual en la interfaz virtual tun0:&lt;/p&gt;
&lt;div style="margin-left: 40px; "&gt;
	&lt;span style="font-family:courier new,courier,monospace;"&gt;&lt;strong&gt;route del default&lt;/strong&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style="margin-left: 40px; "&gt;
	&lt;span style="font-family:courier new,courier,monospace;"&gt;&lt;strong&gt;route add default gw 192.168.100.2 metric 6&lt;/strong&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
	&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
	Este comando toma todo el tr&amp;aacute;fico (excepto hacia nuestro servidor SSH, hacia el DNS o hacia redes locales) y los env&amp;iacute;a a trav&amp;eacute;s del router virtual. Para comprobar que el tr&amp;aacute;fico est&amp;eacute; saliendo por la interfaz virtual, podemos visitar&amp;nbsp;&lt;a href="http://www.whatismyip.com/"&gt;http://www.whatismyip.com/&lt;/a&gt;. La direcci&amp;oacute;n en pantalla deber&amp;iacute;a ser la direcci&amp;oacute;n del servidor SSH.&lt;/div&gt;
&lt;div&gt;
	&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
	El &amp;uacute;ltimo paso consiste en habilitar las reglas de iptables que permitan utilizar NAT, pero ahora hacia la interfaz virtual:&lt;/div&gt;
&lt;div&gt;
	&amp;nbsp;&lt;/div&gt;
&lt;div style="margin-left: 40px; "&gt;
	&lt;strong&gt;&lt;span style="font-family: 'courier new', courier, monospace; "&gt;iptables -t nat -A POSTROUTING -o tun0 -j MASQUERADE&lt;/span&gt;&lt;/strong&gt;&lt;br /&gt;
	&lt;strong&gt;&lt;span style="font-family: 'courier new', courier, monospace; "&gt;iptables -A FORWARD -i tun0 -o eth1 -m state --state RELATED,ESTABLISHED -j ACCEPT&lt;/span&gt;&lt;/strong&gt;&lt;br /&gt;
	&lt;strong&gt;&lt;font face="'courier new', courier, monospace"&gt;iptables -A FORWARD -i eth1 -o tun0 -j ACCEPT&lt;/font&gt;&lt;/strong&gt;&lt;/div&gt;
&lt;div&gt;
	&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
	&amp;iexcl;Ya est&amp;aacute;! Ya podemos utilizar el Dispositivo como si estuvi&amp;eacute;ramos utilizando el servidor SSH :) Suficiente, me voy a ver una pel&amp;iacute;cula. &amp;iexcl;Suerte!&lt;/div&gt;
&lt;div&gt;
	&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
	Por favor, av&amp;iacute;senme si hay dudas o errores :) &lt;a href="http://twitter.com/juancriolivares"&gt;@juancriolivares&lt;/a&gt;&lt;/div&gt;
</description>
      <link>http://www.juancri.com/blog/tunel_para_cualquier_dispositivo</link>
      <guid isPermaLink="True">http://www.juancri.com/blog/tunel_para_cualquier_dispositivo</guid>
      <pubDate>Fri, 27 Jan 2012 03:19:37 GMT</pubDate>
    </item>
    <item>
      <title>Intercambiar los valores de dos variables: parte 2</title>
      <description>&lt;p&gt;
&lt;b&gt;NOTA:&lt;/b&gt; Recomiendo leer antes &lt;a href="/blog/intercambiar_los_valores_de_dos_variables"&gt;la primera parte&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
Estuve pensando bastante en esto e, inspirado en el &lt;a href="http://en.wikipedia.org/wiki/Parity_bit"&gt;bit de paridad&lt;/a&gt; de los RAID, hice lo mismo con operaciones &lt;a href="http://en.wikipedia.org/wiki/Xor"&gt;XOR&lt;/a&gt;. Por ejemplo, sin variable auxiliar en varias expresiones:
&lt;/p&gt;
&lt;pre class="c-sharp" name="code"&gt;a = a ^ b;
b = a ^ b;
a = a ^ b;&lt;/pre&gt;
&lt;p&gt;Y, ahora, sin variable auxiliar en una sola expresión:&lt;/p&gt;
&lt;pre class="c-sharp" name="code"&gt;a = (b ^= (a ^= b)) ^ a;&lt;/pre&gt;
&lt;p&gt;Una de las características interesantes de la operación XOR es que es conmutativa, lo que permite acortar la expresión.&lt;/p&gt;
&lt;p&gt;Se reciben sugerencias :)&lt;/p&gt;</description>
      <link>http://www.juancri.com/blog/intercambiar_los_valores_de_dos_variables_parte_2</link>
      <guid isPermaLink="True">http://www.juancri.com/blog/intercambiar_los_valores_de_dos_variables_parte_2</guid>
      <pubDate>Mon, 09 Jan 2012 04:01:16 GMT</pubDate>
    </item>
    <item>
      <title>Intercambiar los valores de dos variables</title>
      <description>&lt;p&gt;
Éste es probablemente uno de los ejercicios más comunes en un curso de introducción a la programación. Tenemos dos variables y necesitamos intercambiar sus valores. Hay dos approaches que conocía:
&lt;/p&gt;
&lt;p&gt;&lt;b&gt;1.- Variable auxiliar&lt;/b&gt;&lt;/p&gt;
&lt;pre class="c-sharp" name="code"&gt;var a = 1; // Primera variable
var b = 2; // Segunda variable
var c = 3; // Variable auxiliar
c = a;
a = b;
b = c;&lt;/pre&gt;

&lt;p&gt;&lt;b&gt;2.- Sin variable auxiliar&lt;/b&gt;&lt;/p&gt;
&lt;pre class="c-sharp" name="code"&gt;var a = 1; // Primera variable
var b = 2; // Segunda variable
a = a + b;
b = a - b;
a = a - b;&lt;/pre&gt;

&lt;p&gt;
Hoy estaba pensando en cómo hacer esta operación en una sola expresión y llegué a esto:
&lt;/p&gt;
&lt;pre class="c-sharp" name="code"&gt;var a = 1; // Primera variable
var b = 2; // Segunda variable
a = ((b = (a = a + b) - b) - a) * -1;&lt;/pre&gt;
&lt;p&gt;
¿Habrá alguna otra más simple?
&lt;/p&gt;
&lt;p&gt;&lt;b&gt;ACTUALIZACIÓN:&lt;/b&gt; Hasta ahora, logré simplificarla de esta forma:&lt;/p&gt;
&lt;pre class="c-sharp" name="code"&gt;a = -((b = (a += b) - b) - a);&lt;/pre&gt;
&lt;p&gt;&lt;b&gt;ACTUALIZACIÓN 2:&lt;/b&gt; Pueden leer &lt;a href="/blog/intercambiar_los_valores_de_dos_variables_parte_2"&gt;la segunda parte aquí&lt;/a&gt;.&lt;/p&gt;</description>
      <link>http://www.juancri.com/blog/intercambiar_los_valores_de_dos_variables</link>
      <guid isPermaLink="True">http://www.juancri.com/blog/intercambiar_los_valores_de_dos_variables</guid>
      <pubDate>Tue, 03 Jan 2012 14:18:02 GMT</pubDate>
    </item>
    <item>
      <title>Vos no lo digai</title>
      <description>&lt;p&gt;
Mi obsesión por el correcto uso del lenguaje -o, a lo menos, el conocimiento de cómo usarlo correctamente- me ha llevado a crear un nuevo blog donde estoy publicando algunos de los errores que escucho más a menudo. Los invito a suscribirse :)
&lt;/p&gt;

&lt;p&gt;
&lt;a href="http://vosnolodigai.blogspot.com/"&gt;http://vosnolodigai.blogspot.com&lt;/a&gt;
&lt;/p&gt;</description>
      <link>http://www.juancri.com/blog/vos_no_lo_digai</link>
      <guid isPermaLink="True">http://www.juancri.com/blog/vos_no_lo_digai</guid>
      <pubDate>Mon, 19 Dec 2011 02:27:02 GMT</pubDate>
    </item>
    <item>
      <title>Problemas concretos en .Net</title>
      <description>&lt;p&gt;
Para nadie es sorpresa que yo sea fan de .Net como plataforma. C#, su lenguaje principal, es una elegante evolución de Java y C++, mientras que su máquina virtual que incluye generics de verdad desde hace 6 años, value types, enums y un sin fin de otros azúcares, es muy atractiva. Nada de esto compensa la frustración que he sentido durante la última semana gracias a los requerimientos de un querido cliente. Acá una lista de ellas:
&lt;/p&gt;
&lt;p&gt;
&lt;ul&gt;
&lt;li&gt;
Visual studio depende fuertemente de IIS para lanzar sitios web, debiendo cambiar la configuración de la aplicación desarrollada para poder utilizar alternativas como un servidor liviano de desarrollo. Además, si llegamos a tener algún problema de configuración del debugging, Visual Studio no es capaz siquiera de entregar el detalle del error. En vez de esto, la web de MSDN publica una lista con 4 recetas distintas de cómo solucionar el DI'S problema.
&lt;/li&gt;
&lt;li&gt;
A pesar de que ASP.NET MVC 3 es software libre (bajo licencia MS-PL), depende de componentes cerrados que no son parte del runtime estándar .Net, lo que en la práctica se traduce en una plataforma casi inutilizable en entornos de software libre (como Linux + Mono + MonoDevelop).
&lt;/li&gt;
&lt;li&gt;
Bibliotecas como Unity y otros componentes liberados por el grupo de trabajo pattern and practices no tienen descarga directa de bibliotecas, sino que se amarran a la vieja y mala práctica de tener instaladores para componentes que deberían ser simples bibliotecas. Mi cariño por el stack Spring.Net/log4net/NUnit se reafirma.
&lt;/li&gt;
&lt;/ul&gt;
&lt;/p&gt;
&lt;p&gt;¿Alguna otra queja?&lt;/p&gt;</description>
      <link>http://www.juancri.com/blog/problemas_concretos_en_net</link>
      <guid isPermaLink="True">http://www.juancri.com/blog/problemas_concretos_en_net</guid>
      <pubDate>Sun, 14 Aug 2011 16:09:53 GMT</pubDate>
    </item>
    <item>
      <title>Desarrollador PHP</title>
      <description>&lt;p&gt;
¿Te apasiona la programación? ¿Te gusta PHP? ¡Postula ahora! &lt;a href="mailto:info@cxsoftware.com"&gt;info@cxsoftware.com&lt;/a&gt;.
&lt;/p&gt;</description>
      <link>http://www.juancri.com/blog/desarrollador_php</link>
      <guid isPermaLink="True">http://www.juancri.com/blog/desarrollador_php</guid>
      <pubDate>Mon, 20 Jun 2011 23:47:50 GMT</pubDate>
    </item>
    <item>
      <title>Misión Imposible: Comprar Visual Studio</title>
      <description>&lt;p&gt;Misión: Comprar Visual Studio&lt;/p&gt;

&lt;p&gt;
&lt;ul&gt;
&lt;li&gt;Voy al sitio de microsoft, intento comprar en línea. Al finalizar, la compra parece estar restringida a Estados Unidos.&lt;/li&gt;
&lt;li&gt;Intento ir a microsoft.cl, pero en contacto aparecen números telefónicos de España.&lt;/li&gt;
&lt;li&gt;Busco en la guía telefónica y llamo al número 800, pero éste parece ser sólo de activaciones&lt;/li&gt;
&lt;/ul&gt;
&lt;/p&gt;
&lt;p&gt;Y ahora, ¿quién podrá defenderme?&lt;/p&gt;</description>
      <link>http://www.juancri.com/blog/mision_imposible_comprar_visual_studio</link>
      <guid isPermaLink="True">http://www.juancri.com/blog/mision_imposible_comprar_visual_studio</guid>
      <pubDate>Mon, 20 Jun 2011 23:13:32 GMT</pubDate>
    </item>
    <item>
      <title>Validación de RUT con programación funcional</title>
      <description>&lt;p&gt;
Hoy leí &lt;a href="http://coder.cl/2011/03/functional-rut-validator/"&gt;este artículo&lt;/a&gt; y decidí hacer una versión en C#. Éste fue el resultado:
&lt;/p&gt;
&lt;pre class="c-sharp" name="code"&gt;var valido = 
	("0123456789K" [11 - (rut.ToCharArray ().Take (rut.Length - 2).Reverse ()
	.Select ((a, b) =&gt; ((b % 6) + 2) * int.Parse (a.ToString ())).Sum () % 11)]) == rut [rut.Length - 1];&lt;/pre&gt;

&lt;p&gt;
Tal vez no es tan eficiente, pero parece funcionar. Acepto comentarios :)
&lt;/p&gt;</description>
      <link>http://www.juancri.com/blog/validacion_de_rut_con_programacion_funcional</link>
      <guid isPermaLink="True">http://www.juancri.com/blog/validacion_de_rut_con_programacion_funcional</guid>
      <pubDate>Sun, 03 Apr 2011 20:20:42 GMT</pubDate>
    </item>
    <item>
      <title>PCM y TDM</title>
      <description>&lt;p&gt;
El webshow &lt;a href="http://revision3.com/hak5/"&gt;Hak5&lt;/a&gt; ha iniciado un ciclo de programas sobre telefonía y telecomunicaciones. Hasta ahora hay dos episodios:
&lt;/p&gt;
&lt;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://revision3.com/hak5/pulse-code-modulation"&gt;PCM&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://revision3.com/hak5/time-division-multiplexing"&gt;TDM&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/p&gt;
&lt;p&gt;
Como &lt;i&gt;bonus track&lt;/i&gt;, pueden seguir a otros shows interesantes de &lt;a href="http://revision3.com/"&gt;Revision3&lt;/a&gt; como &lt;a href="http://revision3.com/hdnation"&gt;HD Nation&lt;/a&gt;, &lt;a href="http://revision3.com/scamschool"&gt;Scam School&lt;/a&gt; o &lt;a href="http://revision3.com/scientifictuesdays"&gt;Scientific Tuesdays&lt;/a&gt;.
&lt;/p&gt;</description>
      <link>http://www.juancri.com/blog/pcm_y_tdm</link>
      <guid isPermaLink="True">http://www.juancri.com/blog/pcm_y_tdm</guid>
      <pubDate>Wed, 08 Dec 2010 01:49:54 GMT</pubDate>
    </item>
    <item>
      <title>Trucos JavaScript</title>
      <description>&lt;p&gt;Contraro a lo que muchos creen, &lt;a href="http://es.wikipedia.org/wiki/JavaScript"&gt;JavaScript&lt;/a&gt; (o &lt;a href="http://es.wikipedia.org/wiki/ECMAScript"&gt;ECMAScript&lt;/a&gt; para ser más neutros), es un lenguaje muy poderoso y es el responsable de que tengamos aplicaciones web como GMail, Google Reader, Facebook, etc.&lt;/p&gt;

&lt;p&gt;Como ya conté antes, JavaScript es uno de los pilares de la nueva arquitectura de aplicaciones web que estamos desarrollando en CxSoftware. Al utilizar JavaScript a diario, he encontrado algunos tips que creo pueden ser útiles para todo quien quiera ser un ninja JavaScript:&lt;/p&gt;

&lt;p&gt;&lt;b&gt;jQuery&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;
Para comenzar, debes elegir un framework para desarrollar. Podrías no hacerlo, pero eso te traería muchos dolores de cabeza en el futuro. Recomiendo jQuery por su simplicidad, estabilidad y gran cantidad de plugins. Puedes ver más sobre jQuery en su &lt;a href="http://jquery.com/"&gt;sitio oficial&lt;/a&gt;. También recomeindo ver el podcast &lt;a href="http://yayquery.com/"&gt;yayQuery&lt;/a&gt;.
&lt;/p&gt;

&lt;p&gt;&lt;b&gt;linq.js&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://msdn.microsoft.com/en-us/netframework/aa904594.aspx"&gt;LINQ&lt;/a&gt; es originalmente una tecnología utilizada desde .NET 3.5 en adelante que permite utilizar programación funcional, pero además es capaz de traducir expresiones y utilizarlas en distintos contextos como SQL, XML y objetos. &lt;a href="http://linqjs.codeplex.com/"&gt;linq.js&lt;/a&gt; es una implementación de LINQ para objetos y permite realizar tareas comunes de manera simple, especialmente al tratar con listas y condiciones. Existen dos versiones: una standalone y otra que funciona como plugin de jQuery.
&lt;/p&gt;

&lt;p&gt;&lt;b&gt;alert&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;
¿Cuántas veces has utilizado alert("Hola"); en tus scripts? Bueno, window.alert es en realidad una variable que apunta a una función que muestra el message box en pantalla, pero puede ser reescrito. Puedes escribir, por ejemplo window.alert = function (texto) {}; para deshabilitar todas las llamadas a alert desde la página. Esto puede servir para otras cosas, como mostrar las notificaciones con algún sistema como &lt;a href="http://www.erichynds.com/jquery/a-jquery-ui-growl-ubuntu-notification-widget/"&gt;ui notify&lt;/a&gt;.
&lt;/p&gt;

&lt;p&gt;&lt;b&gt;jQueryControls&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Ya hablé de esto antes y vuelvo a recomendárselo. &lt;a href="http://jquerycontrols.com"&gt;jquerycontrols.com&lt;/a&gt;.&lt;/p&gt;</description>
      <link>http://www.juancri.com/blog/trucos_javascript</link>
      <guid isPermaLink="True">http://www.juancri.com/blog/trucos_javascript</guid>
      <pubDate>Wed, 20 Oct 2010 03:50:50 GMT</pubDate>
    </item>
    <item>
      <title>Controles jQuery</title>
      <description>&lt;p&gt;
Como ya les &lt;a href="http://www.juancri.com/blog/jquery_json_parte_1_la_busqueda"&gt;conté antes&lt;/a&gt;, estamos en búsqueda de una arquitectura para desarrollo web que incluye ASP.NET MVC, JSON, jQuery y otros.
&lt;/p&gt;
&lt;p&gt;
Dentro de ese proceso, se presenta el siguiente problema. Dede JavaScript se llama a servicios JSON (o AJAX). Una vez recibida la respuesta, se deben agregar elementos HTML a una lista. Un caso práctico sería, por ejemplo, un sistema que muestra una lista dinámica de personas, incluyendo datos personales de cada una.
&lt;/p&gt;
&lt;p&gt;
La manera simple de hacerlo es recorriendo la lista y agregando elementos a una lista (elementos &amp;lt;li&amp;gt; dentro de una lista &amp;lt;ul&amp;gt;). El problema se produce cuando estos elementos son complejos e incluyen elementos como fotografía, tablas, enlaces, botones, etc.
&lt;/p&gt;
&lt;p&gt;
Si la generación estuviera en el lado del servidor, utilizando el modelo clásico ASP.NET (Web forms), se crearían controles de usuario (user controls), los cuales se definen en HTML, se asocian los datos y, finalmente, se agregan a un conteedor. En el caso de JavaScript, utilizando jQuery, el código sería así:
&lt;/p&gt;
&lt;pre name="code" class="js"&gt;
$.each (lista, function (item, i)
{
    var divItem = $("&amp;lt;div&amp;gt;")
        .append ($("&amp;lt;table&amp;gt;")
            .append ($("&amp;lt;tr&amp;gt;")
                .append ("&amp;lt;td&amp;gt;Nombre:&amp;lt;/td&amp;gt;")
                .append ($("&amp;lt;td&amp;gt;")
                    .text (item.nombre)))
            .append ($("&amp;lt;tr&amp;gt;")
                .append ("&amp;lt;td&amp;gt;Apellido:&amp;lt;/td&amp;gt;")
                .append ($("&amp;lt;td&amp;gt;")
                    .text (item.apellido)))
            .append ($("&amp;lt;tr&amp;gt;")
                .append ("&amp;lt;td&amp;gt;Foto:&amp;lt;/td&amp;gt;")
                .append ($("&amp;lt;td&amp;gt;")
                    .append ($("&amp;lt;img&amp;gt;")
                        .attr ("src", item.urlfoto)))));

    divLista.append (divItem);
});
&lt;/pre&gt;
&lt;p&gt;
Existen varios problemas con este código, incluyendo mantenibilidad, separación inexistente del código con el layout (HTML + JavaScript), etc. Para solucionar esto, decidimos crear una pequeña aplicación que transforma código HTML a objetos jQuery. Así, tenemos este código de origen:
&lt;/p&gt;
&lt;pre name="code" class="xml"&gt;
&amp;lt;div id="principal"&amp;gt;
    &amp;lt;table&amp;gt;
        &amp;lt;tr&amp;gt;
            &amp;lt;td&amp;gt;Nombre:&amp;lt;/td&amp;gt;
            &amp;lt;td id="celdaNombre" /&amp;gt;
        &amp;lt;/tr&amp;gt;
        &amp;lt;tr&amp;gt;
            &amp;lt;td&amp;gt;Apellido:&amp;lt;/td&amp;gt;
            &amp;lt;td id="celdaApellido" /&amp;gt;
        &amp;lt;/tr&amp;gt;
        &amp;lt;tr&amp;gt;
            &amp;lt;td&amp;gt;Foto:&amp;lt;/td&amp;gt;
            &amp;lt;td&amp;gt;&amp;lt;img id="foto" /&amp;gt;&amp;lt;/td&amp;gt;
        &amp;lt;/tr&amp;gt;
    &amp;lt;/table&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/pre&gt;
&lt;p&gt;
Utilizando el generador, esta estructura HTML es transformada en este código JavaScript:
&lt;/p&gt;
&lt;pre name="code" class="js"&gt;
var controlTest = function ()
{
	principal = $('&amp;lt;div&amp;gt;')
		.append ($('&amp;lt;table&amp;gt;')
			.append ($('&amp;lt;tr&amp;gt;')
				.append ($('&amp;lt;td&amp;gt;')
					.append ($('&lt;span&gt;').text ('Nombre:')))
				.append (celdaNombre = $('&amp;lt;td&amp;gt;')))
			.append ($('&amp;lt;tr&amp;gt;')
				.append ($('&amp;lt;td&amp;gt;')
					.append ($('&amp;lt;span&gt;').text ('Apellido:')))
				.append (celdaApellido = $('&amp;lt;td&amp;gt;')))
			.append ($('&amp;lt;tr&amp;gt;')
				.append ($('&amp;lt;td&amp;gt;')
					.append ($('&amp;lt;span&gt;').text ('Foto:')))
				.append ($('&amp;lt;td&amp;gt;')
					.append (foto = $('&amp;lt;img&amp;gt;')))));
	
	this.principal = principal;
	this.celdaNombre = celdaNombre;
	this.celdaApellido = celdaApellido;
	this.foto = foto;
};
&lt;/pre&gt;
&lt;p&gt;
Finalmente, podemos utilizarlo de esta manera:
&lt;/p&gt;
&lt;pre name="code" class="js"&gt;
$.each (lista, function (item, i)
{
    var ct = new controlTest ();
    ct.celdaNombre.text (item.nombre);
    ct.celdaApellido.text (item.apellido);
    ct.foto.attr ('src', item.urlfoto);
    divLista.append (ct.principal);
}
&lt;/pre&gt;
&lt;p&gt;
Tenemos intenciones de distribuir este generador con una licencia libre. Tendremos noticias pronto.
&lt;/p&gt;</description>
      <link>http://www.juancri.com/blog/controles_jquery</link>
      <guid isPermaLink="True">http://www.juancri.com/blog/controles_jquery</guid>
      <pubDate>Mon, 09 Aug 2010 06:13:52 GMT</pubDate>
    </item>
    <item>
      <title>xmlstarlet</title>
      <description>&lt;p&gt;
&lt;a href="http://xmlstar.sourceforge.net/"&gt;xmlstarlet&lt;/a&gt; se autodefine como un &lt;i&gt;toolkit XML para línea de comando&lt;/i&gt;.
&lt;/p&gt;
&lt;p&gt;
He usado esta herramienta desde hace varios años, generalmente para validar un xml, ya sea que esté bien formado como también contra un esquema (XSD) o DTD. Para lo primero, basta con:
&lt;/p&gt;
&lt;pre name="code"&gt;xmlstarlet val test.xml&lt;/pre&gt;
&lt;p&gt;
Hoy, sin embargo, estaba buscando una forma rápida de obtener un valor desde un archivo XML. Tomemos como ejemplo este archivo:
&lt;/p&gt;
&lt;pre class="xml" name="code"&gt;
&lt;root&gt;
	&lt;hijo&gt;
		&lt;elemento atributo="valor"&gt;
			textoelemento
		&lt;/elemento&gt;
	&lt;/hijo&gt;
&lt;/root&gt;
&lt;/pre&gt;
&lt;p&gt;Si queremos, por ejemplo, seleccionar el texto de elemento, podemos ejecutar:&lt;/p&gt;
&lt;pre name="code"&gt;xmlstarlet sel --text -t -v /root/hijo/elemento test.xml&lt;/pre&gt;
&lt;p&gt;Si queremos encontrar el valor del &lt;i&gt;atributo&lt;/i&gt;, ejecutamos:&lt;/p&gt;
&lt;pre name="code"&gt;xmlstarlet sel --text -t -v /root/hijo/elemento/@atributo test.xml&lt;/pre&gt;
&lt;p&gt;Para seleccionar elementos se utiliza la sintaxis XPath. Más info &lt;a href="http://www.w3schools.com/XPath/xpath_syntax.asp"&gt;aquí&lt;/a&gt;.&lt;/p&gt;</description>
      <link>http://www.juancri.com/blog/xmlstarlet</link>
      <guid isPermaLink="True">http://www.juancri.com/blog/xmlstarlet</guid>
      <pubDate>Tue, 27 Jul 2010 03:57:36 GMT</pubDate>
    </item>
    <item>
      <title>Cómo NO hacer un captcha</title>
      <description>&lt;p&gt;
Niños: NUNCA HAGAN ESTO:
&lt;/p&gt;
&lt;p&gt;
Sitio web:&lt;br /&gt;
&lt;img src="http://www.juancri.com/imagenes/posts/captcha1.png" /&gt;
&lt;/p&gt;
&lt;p&gt;
Código fuente:&lt;br /&gt;
&lt;img src="http://www.juancri.com/imagenes/posts/captcha2.png" /&gt;
&lt;/p&gt;
</description>
      <link>http://www.juancri.com/blog/como_no_hacer_un_captcha</link>
      <guid isPermaLink="True">http://www.juancri.com/blog/como_no_hacer_un_captcha</guid>
      <pubDate>Wed, 12 May 2010 10:22:47 GMT</pubDate>
    </item>
    <item>
      <title>Magnetoscopio.net</title>
      <description>&lt;p&gt;Hoy lanzo oficialmente mi nuevo blog: &lt;a href="http://magnetoscopio.net"&gt;magnetoscopio.net&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;En &amp;eacute;l, pretendo publicar todos mis posts referentes a TV, video e Internet. Tal vez ver&amp;aacute;n algunos posts que ya han visto aqu&amp;iacute;, pero hay mucha informaci&amp;oacute;n interesante que comenzar&amp;eacute; a publicar. &amp;iexcl;Suscr&amp;iacute;bete! &amp;iexcl;Cu&amp;eacute;ntale a tus amigos! :)&lt;/p&gt;</description>
      <link>http://www.juancri.com/blog/magnetoscopio_net</link>
      <guid isPermaLink="True">http://www.juancri.com/blog/magnetoscopio_net</guid>
      <pubDate>Tue, 04 May 2010 00:28:07 GMT</pubDate>
    </item>
    <item>
      <title>CNN Chile en Vivo</title>
      <description>&lt;p&gt;
Me gusta el tema de las transmisiones de video online. No por nada, hemos estado más de un año trabajando para desarrollar &lt;a href="http://iptvadventista.cl"&gt;IPTV Adventista&lt;/a&gt; (que, de paso, lanzó su versión 2.0 hace algunos días).
&lt;/p&gt;
&lt;p&gt;
Desde hace un tiempo (semanas al parecer), CNN Chile está transmitiendo su señal online para clientes VTR (CNN Chile es un proyecto de CNN y VTR).
&lt;/p&gt;
&lt;p&gt;
Si desean acceder directamente al stream, puede usar &lt;a href="http://www.videolan.org"&gt;VLC&lt;/a&gt;, así:&lt;br/&gt;
vlc rtsp://200.83.4.17/broadcast/cnn
&lt;/p&gt;
&lt;p&gt;
La transmisión funciona bien, pero podría ser mejor. Aquí va una lista de problemas y sugerencias:
&lt;/p&gt;
&lt;p&gt;
&lt;ul&gt;
&lt;li&gt;Se desperdicia en transmitir el audio en estéreo&lt;/li&gt;
&lt;li&gt;La transmisión utiliza 30 cuadros por segundos, pero el encoder parece emitir menos&lt;/li&gt;
&lt;li&gt;La imagen tirita, evidenciando la utilización de sistemas analógicos con interferencia de estática&lt;/li&gt;
&lt;li&gt;El bitrate es de 700Kbps aprox, pero la calidad no corresponde a ese uso de ancho de banda&lt;/li&gt;
&lt;/ul&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;b&gt;ACTUALIZACION:&lt;/b&gt; CNN Chile cambió su sistema de streaming por RTMP (Flash) y sólo está disponible desde conexiones VTR.
&lt;/p&gt;
&lt;p&gt;
&lt;b&gt;ACTUALIZACIÓN 2:&lt;/b&gt; Sé que muchas personas ingresan a esta página buscando la transmisión de CNN Chile. Clientes VTR (y algunos otros, según he visto), pueden ingresar a &lt;a href="http://www.tv-chile.com/cnnchile/"&gt;http://www.tv-chile.com/cnnchile/&lt;/a&gt;.
&lt;/p&gt;</description>
      <link>http://www.juancri.com/blog/cnn_chile_en_vivo</link>
      <guid isPermaLink="True">http://www.juancri.com/blog/cnn_chile_en_vivo</guid>
      <pubDate>Tue, 16 Mar 2010 04:25:49 GMT</pubDate>
    </item>
    <item>
      <title>ChileAyuda</title>
      <description>&lt;p&gt;
Se están reuniendo esfuerzos en el grupo &lt;a href="http://groups.google.com/group/digitales-por-chile"&gt;Digitales Por Chile&lt;/a&gt; de   profesionales y empresas relacionadas con tecnología. Dos personas de CxNet estaremos a partir de esta tarde colaborando.
&lt;/p&gt;</description>
      <link>http://www.juancri.com/blog/chileayuda</link>
      <guid isPermaLink="True">http://www.juancri.com/blog/chileayuda</guid>
      <pubDate>Tue, 02 Mar 2010 16:15:15 GMT</pubDate>
    </item>
    <item>
      <title>Terremoto</title>
      <description>&lt;p&gt;
El terremoto ya pasó, pero queda mucho por hacer. Yo y mi familia estamos muy bien gracias a Dios.
&lt;/p&gt;
&lt;p&gt;
Aquí hay una lista de sitios que pueden visitar para colaborar:
&lt;/p&gt;
&lt;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.google.com/intl/es/relief/chileearthquake/"&gt;Google Crisis Response Chile&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.onemi.cl"&gt;Oficina Nacional de Emergencias&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://nadaseralomismo.com/2010/02/28/lista-de-lugares-donde-comprar-provisiones/"&gt;Lista de lugares donde comprar provisiones&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;/ul&gt;
&lt;/p&gt;</description>
      <link>http://www.juancri.com/blog/terremoto</link>
      <guid isPermaLink="True">http://www.juancri.com/blog/terremoto</guid>
      <pubDate>Sun, 28 Feb 2010 23:26:44 GMT</pubDate>
    </item>
    <item>
      <title>Google sabe de mí...</title>
      <description>&lt;p&gt;
&lt;ul&gt;
  &lt;li&gt;Lo que busco&lt;/li&gt;
  &lt;li&gt;Quiénes son mis contactos&lt;/li&gt;
  &lt;li&gt;Lo que escribo y leo (Gmail)&lt;/li&gt;
  &lt;li&gt;Dónde estoy (Latitude)&lt;/li&gt;
  &lt;li&gt;Lo que me gusta leer (Reader)&lt;/li&gt;
  &lt;li&gt;Adónde voy (Maps / Navigator)&lt;/li&gt;
  &lt;li&gt;Dónde y qué compro (Checkout)&lt;/li&gt;
  &lt;li&gt;A quién llamo (Android)&lt;/li&gt;
  &lt;li&gt;Los sitios web que visito (Chrome)&lt;/li&gt;
  &lt;li&gt;Mi agenda diaria (Calendar)&lt;/li&gt;
  &lt;li&gt;Los proyectos que tengo (Docs)&lt;/li&gt;
  &lt;li&gt;Mis tareas pendientes (Tasks)&lt;/li&gt;
&lt;/ul&gt;
&lt;/p&gt;
&lt;p&gt;Sólo eso. ¿Se les ocurren más?&lt;/p&gt;</description>
      <link>http://www.juancri.com/blog/google_sabe_de_mi</link>
      <guid isPermaLink="True">http://www.juancri.com/blog/google_sabe_de_mi</guid>
      <pubDate>Wed, 17 Feb 2010 19:08:43 GMT</pubDate>
    </item>
    <item>
      <title>jQuery + JSon (Parte 1): La búsqueda</title>
      <description>&lt;p&gt;
Hace algunas semanas, comenzamos un experimento para definir la arquitectura
básica de las aplicaciones web que desarrollaremos en CxNet de aquí en adelante.
&lt;/p&gt;
&lt;p&gt;
Aunque uno de los lenguajes que más utilizado es PHP (principalmente entre 2001 y 2004),
no me siento cómo desarrollando "web". Comparado a la satisfacción de programar software
sin interfaz de usuario, que sólo debe cumplir con los protocolos de los sistemas a los
cuales se conecta, la web tiene un sin fin de complejidades.
&lt;/p&gt;
&lt;p&gt;
Ésta es mi historia:
&lt;/p&gt;
&lt;p&gt;
&lt;ul&gt;
  &lt;li&gt;HTML: Aprendí gracias a Mosaic y algunas páginas de muestra que venían en el CD
  de mi primer módem. Luego, cuando por fin pude usarlo para conectarme a internet,
  seguí experimentando y creé algunas páginas, pero nada de lo que me sienta muy
  orgulloso.&lt;/li&gt;
  &lt;li&gt;Perl: Hace unos 11 años, alguien me pidió investigar una forma de listar
  información sobre empresas en un sitio web. Hice pruebas con Perl, el lenguaje
  más utilizado para desarrollar CGI en la época, y logré buenos resultados.
  Perl se convertiría en mi segundo lenguaje de programación (después de BASIC...
  aunque pasando por alto algunas pruebas con JavaScript).&lt;/li&gt;
  &lt;li&gt;PHP: Ya el 2001, cuando comencé a trabajar (semi) formalmente, PHP resonaba
  como la &lt;i&gt;maravilla&lt;/i&gt; del desarrollo web. Me tomé algunos días y, utilizando
  unas mil hojas tamaño carta y varios cartuchos recargables de tinta, imprimí
  la documentación de la, entonces nueva, versión 4 de PHP. Éste sería uno de
  los lenguajes que utilizaría por más tiempo. Si bien no habían frameworks en
  la época, y todas las variables se importaban mágicamente (nada de $_POST o
  similares), hace algunos años comencé a buscar alternativas como PRADO Framework.&lt;/li&gt;
  &lt;li&gt;ASP.NET:&lt;/li&gt; Durante la búsqueda de un lenguaje y plataforma más poderosos que
  me permitieran desarrollar para web y para escritorio, y luego de probar Java y
  Delphi, encontré el proyecto Mono (allá por la versión 0.16). De inmediato me sentí
  muy atraido por el lenguaje principal, C#. Luego, descubriría ASP.NET y su
  revolucionaria arquitectura de controles y estados. Ha sido mi principal plataforma
  de desarrollo web desde 2003 hasta 2009.&lt;/li&gt;
  &lt;li&gt;Java Struts: Este conocido motor MVC para Java me fue impuesto por el cruel
  mercado. Nunca me sentí cómodo con él y, después de menos de seis meses de práctica,
  renuncié a mi trabajo y decidí enfocarme en .NET/Mono, lo que incluía ASP.NET.&lt;/li&gt;
&lt;/ul&gt;
&lt;/p&gt;
&lt;p&gt;
Si bien el modelo de ASP.NET, también ocupado en JSF, PRADO Framework y otros, es cómodo
y ordenado, uno de los problemas que tiene es el uso de servicios Ajax o JSON y la
interacción con JavaScript, nada de natural. Hay varios intentos de amalgamar estas
tecnologías que parecen haber sido diseñadas para lo mismo pero que, sin embargo,
tienen arquitecturas totalmente opuestas. Un intento es ASP.NET Ajax, el cual incluye
un "update panel", en el cual se pueden insertar otros controles que utilizar AJAX
por debajo. Otro intento, muy bueno, es Gaia Ajax Widgets. En este caso, sus desarrolladores
crearon toda una gama de controles "ajaxosos", extendiendo la funcionalidad de los controles
originales. Incluso llegué a comprar una licencia durante una oferta. El viewstate se seguía
ocupando, pero no todo era color de rosas. Hay que saber muchos detalles de cómo funcionan
estos sistemas, a bajo nivel, para poder resolver problemas que seguramente ocurrirán tarde
o temprano, síntomas de una relación ilícita entre dos mundos que se niegan a convivir.
&lt;/p&gt;
&lt;p&gt;
Como todo cambia, especialmente en este mundillo de la computación, siempre hay que
replantearse las cosas. En el caso de las plataformas web, esto me ha ocurrido varias
veces.
&lt;/p&gt;
&lt;p&gt;
Hay dos criterios muy importantes que deben ser tomados en cuenta cuando se elige una
plataforma: el usuario y el desarrollador. GMail es tal vez el gran ejemplo de AJAX.
La primera aplicación masiva donde no había que esperar por un &lt;i&gt;refresh&lt;/i&gt; o
&lt;i&gt;postback&lt;/i&gt; y donde el usuario es complacido con una interfaz intuitiva y simple.
En el caso del desarrollador, hay un gran problema en el típico framework web mezclado
con AJAX (o JSON, etc). Cierto contenido es &lt;i&gt;rendereado&lt;/i&gt; en el servidor mientras
otro contenido es generado dinámicamente al cargarse datos a través de un request AJAX.
&lt;/p&gt;
&lt;p&gt;
Luego de la popularidad alcanzada por JQuery y la facilidad de uso de JSON en ASP.NET MVC,
decidí probar esta combinación. En los próximos posts, les contaré cómo.
&lt;/p&gt;</description>
      <link>http://www.juancri.com/blog/jquery_json_parte_1_la_busqueda</link>
      <guid isPermaLink="True">http://www.juancri.com/blog/jquery_json_parte_1_la_busqueda</guid>
      <pubDate>Wed, 17 Feb 2010 08:36:23 GMT</pubDate>
    </item>
    <item>
      <title>Consultas recursivas</title>
      <description>&lt;p&gt;
Cuando se llevan estructuras de árbol a una base de datos, es común utilizar un esquema como este:
&lt;/p&gt;
&lt;pre class="sql" name="code"&gt;CREATE TABLE nodos
(
    id int primary key,
    idpadre integer REFERENCES nodos (id),
    nombre varchar
);&lt;/pre&gt;
&lt;p&gt;
Una vez hecho esto, podemos insertar algunos datos para crear la estructura:
&lt;/p&gt;
&lt;pre class="sql" name="code"&gt;INSERT INTO nodos (id, nombre) VALUES (1, 'Raíz');
INSERT INTO nodos (id, nombre, idpadre) VALUES (2, 'Nodo 1', 1);
INSERT INTO nodos (id, nombre, idpadre) VALUES (3, 'Nodo 2', 1);
INSERT INTO nodos (id, nombre, idpadre) VALUES (4, 'Nodo 3', 2);
INSERT INTO nodos (id, nombre, idpadre) VALUES (5, 'Nodo 4', 4);&lt;/pre&gt;
&lt;p&gt;
Con estos datos, tendremos una estructura como esta:
&lt;/p&gt;
&lt;pre&gt;Raíz (1)
 |-- Nodo 1 (2)
 |    |-- Nodo 3 (4)
 |         |-- Nodo 4 (5)
 |-- Nodo 2 (3)&lt;/pre&gt;
&lt;p&gt;
Supongamos que queremos saber todos los nodos padres del "Nodo 4" (ID: 5). Para esto, PostgreSQL provee consultas recursivas. Acá un ejemplo de cómo podemos realizar la consulta para este nodo:
&lt;/p&gt;
&lt;pre class="sql" name="code"&gt;WITH RECURSIVE arbol (idpadre, idnodo) AS (
    SELECT
	n.idpadre,
	n.id
    FROM
	nodos n
    WHERE
	n.id = 5
  UNION ALL
    SELECT n2.idpadre, n2.id
    FROM arbol a INNER JOIN nodos n2
      ON (n2.id = a.idpadre)
  )
SELECT * FROM arbol&lt;/pre&gt;
&lt;p&gt;
Esta simple consulta, retornará:
&lt;/p&gt;
&lt;pre&gt; idpadre | idnodo 
---------+--------
       4 |      5
       2 |      4
       1 |      2
         |      1
&lt;/pre&gt;
&lt;p&gt;
Espero que les sirva ;)
&lt;/p&gt;</description>
      <link>http://www.juancri.com/blog/consultas_recursivas</link>
      <guid isPermaLink="True">http://www.juancri.com/blog/consultas_recursivas</guid>
      <pubDate>Fri, 12 Feb 2010 02:00:44 GMT</pubDate>
    </item>
  </channel>
</rss>
