<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Mauricio Pastrana - Since 1982 &#187; Gadgets y Tecnologia</title>
	<atom:link href="http://mauriciopastrana.com/category/gadgets-y-tecnologia/feed/" rel="self" type="application/rss+xml" />
	<link>http://mauriciopastrana.com</link>
	<description>Ad Rem, Ad Hominem, Ad Lib!</description>
	<lastBuildDate>Mon, 05 Oct 2009 21:49:54 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>Entendiendo los Mysql JOIN</title>
		<link>http://mauriciopastrana.com/gadgets-y-tecnologia/entendiendo-los-mysql-join/</link>
		<comments>http://mauriciopastrana.com/gadgets-y-tecnologia/entendiendo-los-mysql-join/#comments</comments>
		<pubDate>Sun, 02 Nov 2008 16:19:46 +0000</pubDate>
		<dc:creator>Mauricio Pastrana</dc:creator>
				<category><![CDATA[Gadgets y Tecnologia]]></category>
		<category><![CDATA[join]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[venn]]></category>

		<guid isPermaLink="false">http://mauriciopastrana.com/?p=283</guid>
		<description><![CDATA[Este es un problema bastante común para los desarrolladores que trabajan sobre bases de datos: Llaman un set de resultados y se encuentran que uno de los campos no es mas sino un listado de ID&#8217;s. Ahora como traigo los datos de ese campo? Muy a menudo me encuentro con desarrolladores SQL que aplican la siguiente lógica para solucionar este problema: SELECT * FROM países [...]]]></description>
			<content:encoded><![CDATA[<p><img class="alignleft size-full wp-image-296" style="margin: 10px;" title="cocoa_mysql" src="http://mauriciopastrana.com/wp-content/uploads/2008/11/picture-1.png" alt="" width="287" height="168" /></p>
<p style="text-align: justify;">Este es un problema bastante común para los desarrolladores que trabajan sobre bases de datos:</p>
<p style="text-align: justify;">Llaman un <span class="misspell">set</span> de resultados y se encuentran que uno de los campos no es mas sino un listado de ID&#8217;s. <em>Ahora como traigo los datos de ese campo?</em></p>
<p style="text-align: justify;">Muy a menudo me encuentro con desarrolladores <span class="misspell">SQL</span> que aplican la siguiente lógica para solucionar este problema:</p>
<p>SELECT * FROM países</p>
<blockquote><p>          foreach($países as $país) {<br />
                    SELECT * FROM ciudades WHERE país = $país<br />
                              foreach ($ciudades as $ciudad) {<br />
                                        &#8230;</p></blockquote>
<p style="text-align: justify;">Que como pueden ver, no solo es <span class="misspell">dif</span>í<span class="misspell">cil</span> de manejar sino que es imposible de crecer logicamente y en ultimas, confuso de leer. Mas que genera una cantidad de gasto de memoria tanto en el <span class="misspell">PC</span> corriendo <span class="misspell">php</span> como en la base de datos que genera la busqueda especifica.</p>
<p style="text-align: justify;">Afortunadamente, tenemos la flexibilidad de una <span id="bad_word" class="misspell">funci</span>ón MySQL hecha precisamente para llamar datos entre dos tablas conectadas con un campo en <span class="misspell">com</span>ún: <strong><span class="misspell">JOIN</span></strong></p>
<p><span id="more-283"></span></p>
<p style="text-align: justify;">Por ejemplo, usando <span class="misspell"><strong>JOIN</strong></span>, llamar un <span class="misspell">set</span> de resultados de direcciones a base de país requeriría del siguiente <span class="misspell">query</span>:</p>
<blockquote><p>SELECT * FROM direcciones. AS dir<br />
JOIN países AS p ON p.país = dir.pais<br />
WHERE &#8230;<em> cualquier condicion</em></p></blockquote>
<p style="text-align: justify;">Mejor! Esta búsqueda generaría el siguiente <span class="misspell">set</span> hipotético de resultados para presentar usando <span class="misspell">php</span> (ojo que esta organizado por las columnas de &#8220;país&#8221;):</p>
<pre> p.id  |  p.pais   | dir.id  | dir.pais  | dir.direccion
 1     |  USA      | 3       | USA       | 200 West Chadderdon Avenue
 2     |  Mexico   | 4       | Mexico    | 823 Monte Libano
 4     |  Colombia | 2       | Colombia  | Carrera 9B Bis #117-32
 3     |  Colombia | 1       | Colombia  | Calle 127 #42-45</pre>
<p style="text-align: justify;">Fácil, no? Bueno, a simple vista si, pero con esto estamos tan solo raspando la superficie del problema en el que nos podemos encontrar si tenemos dos tablas que no necesariamente contengan datos simétricos.</p>
<p style="text-align: justify;">Para solucionar este problema, hay que considerar el juego de herramientas <strong>JOIN</strong> entero: <br />
<strong>LEFT JOIN</strong>, <strong>RIGHT JOIN</strong>, <strong>INNER JOIN</strong> y <strong>OUTER JOIN</strong>.</p>
<p style="text-align: justify;">Cuando me lo cruce originalmente, <a href="http://www.codinghorror.com/blog/archives/000976.html">este post de Jeff Atwood</a> que explica como funcionan los JOIN me soluciono una cantidad de problemas, hoy en día ya lo he reenviado tanto que decidí colgarlo aquí:</p>
<h3>JOIN, una explicacion visual</h3>
<p>Entonces, para lograr entender entonces que tan poderosa es la utilidad <strong>JOIN</strong>, voy a visualizar dos tablas que contengan tan solo algunos datos en común:</p>
<pre>id nombre       id  nombre
-- ----         --  ----
1  <span style="color: #ff0000;">Pirata</span>       1   Rutabaga
2  Mico         2   <span style="color: #ff0000;">Pirata</span>
3  <span style="color: red;">Ninja</span>        3   Darth Vader
4  Spaghetti    4   <span style="color: red;">Ninja</span></pre>
<p>Listo? ahora veamos a ver como como caen las mezclas de datos usando JOIN</p>
<h4>INNER JOIN</h4>
<pre>SELECT * FROM TablaA
<strong>INNER JOIN</strong> TablaB
ON TablaA.name = TablaB.name

id  name       id   name
--  ----       --   ----
1   Pirata     2    Pirata
3   Ninja      4    Ninja</pre>
<p>Este genera una lista de resultados que existan tanto en A como en B simultaneamente</p>
<p><img class="aligncenter size-full wp-image-289" title="join-inner" src="http://mauriciopastrana.com/wp-content/uploads/2008/11/join-inner.png" alt="" width="500" height="327" /></p>
<p> </p>
<p> </p>
<hr /><strong>FULL OUTER JOIN</strong></p>
<pre>SELECT * FROM TablaA
<strong>FULL OUTER JOIN TablaB
<span style="font-weight: normal;">ON TablaA.name = TablaB.name</span></strong></pre>
<pre>id    name       id    name
--    ----       --    ----
1     Pirata     2     Pirata
2     Mico       <span style="color: gray;">null</span>  <span style="color: gray;">null</span>
3     Ninja      4     Ninja
4     Spaghetti  <span style="color: gray;">null</span>  <span style="color: gray;">null</span>
<span style="color: gray;">null</span>  <span style="color: gray;">null</span>       1     Rutabaga
<span style="color: gray;">null</span>  <span style="color: gray;">null</span>       3     Darth Vader</pre>
<p>Genera un listado que incluya todos los resultados en A y en B, asi no exista relacion entre algun campo</p>
<p><img class="aligncenter size-full wp-image-290" title="join-cartesian" src="http://mauriciopastrana.com/wp-content/uploads/2008/11/join-cartesian.png" alt="" width="500" height="327" /></p>
<p> </p>
<hr /><strong>LEFT OUTER JOIN</strong></p>
<pre>SELECT * FROM TablaA
<strong>LEFT OUTER JOIN TablaB
<span style="font-weight: normal;">ON TablaA.name = TablaB.name</span></strong></pre>
<pre>id  name       id    name
--  ----       --    ----
1   Pirata     2     Pirata
2   Mico       <span style="color: gray;">null</span>  <span style="color: gray;">null</span>
3   Ninja      4     Ninja
4   Spaghetti  <span style="color: gray;">null</span>  <span style="color: gray;">null</span></pre>
<p>Entrega todos los resultados que encuentra en la tabla A, pero tambien trae los resultados que empaten que aparezcan en la tabla B.<br />
<img class="aligncenter size-full wp-image-293" title="join-left" src="http://mauriciopastrana.com/wp-content/uploads/2008/11/join-left.png" alt="" width="500" height="327" /></p>
<p> </p>
<hr /><strong>Usos y Derivados</strong></p>
<p>&#8230; Conociendo como funcionan los JOIN, estos son otros ejemplos que se pueden generar usando la sintáxis <strong>JOIN <span style="font-weight: normal;">completa.</span></strong></p>
<pre>SELECT * FROM TablaA
LEFT OUTER JOIN TablaB
ON TablaA.name = TablaB.name
<strong>WHERE TablaB.id IS null</strong>

id  name       id     name
--  ----       --     ----
2   Mico       <span style="color: gray;">null</span>   <span style="color: gray;">null</span>
4   Spaghetti  <span style="color: gray;">null</span>   <span style="color: gray;">null</span></pre>
<p>Solo quiero ver los records unicos que existan en la tabla A</p>
<p><img class="aligncenter size-full wp-image-292" title="join-left-outer" src="http://mauriciopastrana.com/wp-content/uploads/2008/11/join-left-outer.png" alt="" width="500" height="327" /></p>
<p> </p>
<pre><span style="color: #000000;">SELECT * FROM TablaA
FULL OUTER JOIN TablaB
ON TablaA.name = TablaB.name
</span><strong><span style="color: #000000;">WHERE TablaA.id IS null
OR TablaB.id IS null</span>
</strong>
<span style="color: #000000;">id    name       id    name
--    ----       --    ----</span>
<span style="color: #000000;">2     Mico  </span>     <span style="color: gray;">null</span>  <span style="color: gray;">null</span>
<span style="color: #000000;">4     Spaghetti</span>  <span style="color: gray;">null</span>  <span style="color: gray;">null</span>
<span style="color: gray;">null</span>  <span style="color: gray;">null</span>       <span style="color: #000000;">1     Rutabaga</span>
<span style="color: gray;">null</span>  <span style="color: gray;">null</span>       <span style="color: #000000;">3     Darth Vader</span></pre>
<pre><span style="color: #000000;"><span style="font-family: 'Lucida Grande'; line-height: 19px; white-space: normal;">Muestrame los records que no tengan relacion alguna entre la tabla A y la tabla B</span></span></pre>
<p><img class="aligncenter size-full wp-image-294" title="join-outer" src="http://mauriciopastrana.com/wp-content/uploads/2008/11/join-outer.png" alt="" width="500" height="327" /></p>
<p> </p>
<hr />Y ojo que el <strong>LEFT JOIN</strong> es intercambiable en sintaxis (mas no en logica) con un <strong>RIGHT JOIN</strong> donde</p>
<pre>SELECT * FROM TablaA
LEFT JOIN TablaB
ON TablaA.name = TablaB.name</pre>
<p>&#8230; es equivalente a</p>
<pre>
<pre>SELECT * FROM TablaB
RIGHT JOIN TablaA
ON TablaA.name = TablaB.name</pre>
</pre>
]]></content:encoded>
			<wfw:commentRss>http://mauriciopastrana.com/gadgets-y-tecnologia/entendiendo-los-mysql-join/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Guia: Subtitula tus peliculas Divx en (casi) cualquier idioma</title>
		<link>http://mauriciopastrana.com/gadgets-y-tecnologia/guia-subtitula-tus-peliculas-divx-en-casi-cualquier-idioma/</link>
		<comments>http://mauriciopastrana.com/gadgets-y-tecnologia/guia-subtitula-tus-peliculas-divx-en-casi-cualquier-idioma/#comments</comments>
		<pubDate>Wed, 29 Oct 2008 23:59:55 +0000</pubDate>
		<dc:creator>Mauricio Pastrana</dc:creator>
				<category><![CDATA[Gadgets y Tecnologia]]></category>
		<category><![CDATA[descargas]]></category>
		<category><![CDATA[divx]]></category>
		<category><![CDATA[guia]]></category>
		<category><![CDATA[peliculas]]></category>
		<category><![CDATA[subtitulos]]></category>

		<guid isPermaLink="false">http://mauriciopastrana.com/?p=256</guid>
		<description><![CDATA[Si ustedes son en lo mas mínimo como yo y viven en algún país donde les encanta ofrecer las películas en cine meses después que los norteamericanos ya se cansaron de tenerlas de alquiler, se van a encontrar haciendo uso fuerte del tan llamado &#8220;Centro de entretenimiento BitTorrent&#8221;. Como sea el caso, no hay cosa [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: justify;"><img class="alignleft size-full wp-image-258" style="margin: 10px;" title="VLC" src="http://mauriciopastrana.com/wp-content/uploads/2008/10/picture-1.png" alt="" width="171" height="177" />Si ustedes son en lo mas mínimo como yo y viven en algún país donde les encanta ofrecer las películas en cine <a href="http://www.exonline.com.mx/diario/noticia/dinero/economia/mexico,_muy_atrasado_en_convergencia:_slim_domit/128508" target="_blank">meses después que los norteamericanos ya se cansaron de tenerlas de alquiler</a>, se van a encontrar haciendo uso fuerte del tan llamado &#8220;Centro de entretenimiento BitTorrent&#8221;.</p>
<p style="text-align: justify;">Como sea el caso, no hay cosa mas frustrante que acabar <a href="http://tubabel.com/definicion/7026-en-cuatro-bloques" target="_blank">varado</a> con una película o episodio en su nativo alemán [ingles, francés, italiano, mandarín] después de aguantarse <a href="http://mauriciopastrana.com/gadgets-y-tecnologia/guia-descargas-usando-torrents/" target="_self">una </a><a href="http://mauriciopastrana.com/gadgets-y-tecnologia/guia-descargas-usando-torrents/" target="_self">larguísima </a><a href="http://mauriciopastrana.com/gadgets-y-tecnologia/guia-descargas-usando-torrents/" target="_self">descarga</a>.<a href="http://mauriciopastrana.com/gadgets-y-tecnologia/guia-descargas-usando-torrents/" target="_self"><br />
</a></p>
<p style="text-align: justify;">Esta guía viene a base de la cantidad de correo que me llego desde que publique mi <a href="http://mauriciopastrana.com/gadgets-y-tecnologia/guia-descargas-usando-torrents/" target="_self">guía de descargas</a> que hice un poco atrás y les explica como subtitular sus películas o episodios de tele en formato Divx a [virtualmente] cualquier idioma usando el mismísimo reproductor de video <a href="http://www.videolan.org" target="_blank">VLC</a>. Créanlo o no, <a href="http://www.videolan.org/doc/play-howto/en/ch03.html#id306989" target="_blank">es bien simple</a>.</p>
<p style="text-align: left;"><span id="more-256"></span></p>
<h3 style="text-align: left;">Como funcionan los subtitulos?</h3>
<p style="text-align: justify;">Básicamente, son archivos en texto plano. Tal cual! de hecho, un &#8220;archivo de subtitulos&#8221; en notepad se vería así:</p>
<blockquote style="text-align: left;"><p>1<br />
00:00:01,000 &#8211;&gt; 00:00:02,000<br />
Primer subtitulo</p>
<p>2<br />
00:00:02,500 &#8211;&gt; 00:00:10,000<br />
Segundo subtitulo &lt;font size=&#8221;5&#8243;&gt;con opcion de texto grande&lt;/font&gt;, o con texto en  &lt;i&gt;itálicas&lt;/i&gt;.</p></blockquote>
<p style="text-align: justify;">El &#8220;formato estándar&#8221; entonces se le conoce como un archivo <a href="http://www.fileinfo.net/extension/srt" target="_blank">.srt</a>, y solo con conseguirlo, hemos hecho la parte mas tediosa de la tarea.</p>
<p style="text-align: justify;">Ahora, aviso antes que venga lo demás; para Windows hay una opción bastante viable, un programita que llama <a href="http://www.free-codecs.com/download/DirectVobSub.htm" target="_blank">DirectVobSub</a> (lean mas saltando a la sección mas abajo &#8220;Y &#8230; sin VLC?&#8221;).</p>
<p style="text-align: justify;">Para Mac (o Windows si no quieren un programa que corra de fondo a todas horas), <a href="http://www.videolan.org" target="_blank">VLC</a>, el reproductor de videos, es de lejos el programa que mas nos va a simplificar la vida en el momento de unir archivos .srt y películas divx (.avi) así que me voy a enfocar en este.</p>
<p style="text-align: justify;">VLC solito se encarga de <em>pintar</em> el texto subtitulado encima de la imagen, y de hecho tiene varias opciones ajustables al respecto, acá la pantalla de configuración:</p>
<p style="text-align: left;"><img class="aligncenter size-full wp-image-261" title="VLC subtitle configuration" src="http://mauriciopastrana.com/wp-content/uploads/2008/10/picture-2.png" alt="" width="500" height="294" /></p>
<p style="text-align: left;">
<h3 style="text-align: left;">Subtitulos hechos por cualquier persona!</h3>
<p style="text-align: justify;">Esta es una interesante. &#8230; No, no hay ninguna casa productora detrás de los subtitulos (sobretodo en series de tele), por lo menos en cuanto a las películas o series que no existan disponibles en DVD.</p>
<p style="text-align: justify;">Por lo general, los subtitulos vienen de aficionados. Gente como <a href="http://www.wired.com/entertainment/theweb/magazine/16-11/st_torrent" target="_blank">Pablo Diaz</a> o <a href="http://www.wired.com/entertainment/theweb/magazine/16-11/st_torrent" target="_blank">Lilia Carone</a> quienes solo requieren de tiempo y un editor de texto para salir corriendo a traducir tan solo minutos después que pasa al aire la primera edición. El trabajo de estos dos y varios otros lo encuentran en <a href="http://www.subscene.com" target="_blank">subscene.com</a>, por ejemplo.</p>
<p style="text-align: justify;">Y sobre el que los motiva? bueno, en las mismas palabras de Pablo: <em>Me gustan los idiomas</em></p>
<p style="text-align: justify;">Es notable el hecho que, por lo general, aun después que se publica el DVD con una versión oficial de los subtitulos en varios idiomas, <a href="http://subscene.com/statistics.aspx" target="_blank">todavía se mantiene alto el trafico de los archivos de subtitulos hechos &#8220;a mano&#8221;</a>.</p>
<h3 style="text-align: left;">Subtitulando una pelicula en ingles, un ejemplo</h3>
<p style="text-align: justify;">Primero lo primero. A buscar el archivo .srt. Para esto, me dirijo a <a href="http://www.subscene.com" target="_blank">http://www.subscene.com</a> (aunque hay una infinidad de sitios, pueden saltar hasta el final para ver una lista).</p>
<p style="text-align: left;"><img class="aligncenter size-full wp-image-265" title="subscene search" src="http://mauriciopastrana.com/wp-content/uploads/2008/10/picture-4.png" alt="" width="487" height="208" /></p>
<p style="text-align: left;">una búsqueda rápida me genera los siguientes resultados: estos son solo los que están en ingles!</p>
<p style="text-align: center;"><img class="size-medium wp-image-266 aligncenter" title="subscene speed racer results" src="http://mauriciopastrana.com/wp-content/uploads/2008/10/picture-5-300x251.png" alt="" width="300" height="251" /></p>
<p style="text-align: left;">Y podemos ver que cada archivo tiene un espacio para añadir comentarios</p>
<p style="text-align: left;"><img class="aligncenter size-full wp-image-267" title="picture-6" src="http://mauriciopastrana.com/wp-content/uploads/2008/10/picture-6.png" alt="" width="500" height="79" /></p>
<p style="text-align: justify;">&#8230; Ahora, después de su respectiva descarga, ubicamos el archivo .srt al lado del archivo de la película (.avi, mas que todo para no perderlo). Acá pueden ver como yo decidí descargar un archivo que coincida en nombre al archivo .avi que descargue, aunque no es necesario.</p>
<p style="text-align: center;"><img class="size-medium wp-image-269 aligncenter" title="speed racer files" src="http://mauriciopastrana.com/wp-content/uploads/2008/10/picture-8.png" alt="" width="285" height="68" /></p>
<p style="text-align: left;">y listo! ahora solo es abrir VLC y buscar <strong>File-&gt;Open FIle</strong>. Antes que cualquier cosa, le damos una pasada al cuadrito de &#8220;cargar archivo de subtitulos&#8221;</p>
<p style="text-align: center;"><img class="aligncenter size-full wp-image-271" title="load subtitles file" src="http://mauriciopastrana.com/wp-content/uploads/2008/10/picture-9.png" alt="" width="162" height="32" /></p>
<p style="text-align: justify;">Ojo que hay que configurar las opciones de subtitulos (el botón próximo &#8211; <em>Settings&#8230;</em>), donde tenemos que navegar hacia donde se ubique el archivo .srt, se debería de ver algo similar a esto</p>
<p style="text-align: left;"><img class="aligncenter size-full wp-image-272" title="srt settings" src="http://mauriciopastrana.com/wp-content/uploads/2008/10/picture-10.png" alt="" width="500" height="294" /></p>
<p style="text-align: justify;">Válgase anotar que no siempre se va a ver así. Por ejemplo, no es raro que los subtitulos tengan un ligero desajuste con el video y muestren texto antes o después de lo debido, para lo cual hay que estar atentos a los parámetros &#8220;<em>Delay</em>&#8221; y &#8220;<em>FPS</em>&#8220;. Por lo general es mas recomendable descargar una versión alterna del archivo .srt antes que molestar con la sincronización de video a texto.</p>
<p style="text-align: justify;">&#8230; Ahora, le damos OK y VLC nos devuelve al dialogo de &#8220;Abrir Archivo&#8221;.</p>
<p style="text-align: left;"><a href="http://mauriciopastrana.com/wp-content/uploads/2008/10/picture-11.png" rel="lightbox[256]"><img class="aligncenter size-full wp-image-273" title="open file VLC" src="http://mauriciopastrana.com/wp-content/uploads/2008/10/picture-11.png" alt="" width="500" height="379" /></a></p>
<p style="text-align: left;">Y listo! Cuando arranque la pelicula (o serie) esta ya lleva los subtitulos encima.</p>
<p style="text-align: left;"><a href="http://mauriciopastrana.com/wp-content/uploads/2008/10/picture-12.png" rel="lightbox[256]"><img class="aligncenter size-full wp-image-274" title="speed racer w subs" src="http://mauriciopastrana.com/wp-content/uploads/2008/10/picture-12.png" alt="" width="500" height="284" /></a></p>
<h3 style="text-align: left;">Y&#8230; sin VLC?</h3>
<p style="text-align: justify;">Para Windows, hay una opción aun mas viable. <a href="http://www.free-codecs.com/download/DirectVobSub.htm" target="_blank">DirectVobSub</a>. Este es un programita que corre de fondo, y siempre y cuando tengan un archivo de subtitulos,<strong> con extension .sub y el mismo nombre de archivo que la pelicula en la misma carpeta</strong>, este auto-carga los subtitulos sin preguntar. Sirve sobre Windows Media Player!</p>
<p style="text-align: justify;">Un tip? DirectVobSub entiende subtitulos de casi cualquier formato pero tiene el requisito de que el archivo de subtitulos igual se &#8220;apellide&#8221; .sub, asi que lo unico que tienen que hacer después de conseguirlos en su website favorito es ponerlo contiguo al archivo .avi y renombrarlo a [nombre_de_pelicula].<strong>sub</strong> y voila!</p>
<h3 style="text-align: left;">Sitios de descarga de archivos .srt</h3>
<p style="text-align: left;">Multi-idioma:</p>
<ul style="text-align: left;">
<li><a rel="nofollow" href="http://www.opensubtitles.org/" target="parent">OpenSubtitles</a></li>
<li><a rel="nofollow" href="http://www.subscene.com/" target="parent">Subscene</a></li>
<li><a rel="nofollow" href="http://www.divxsubtitles.net/" target="parent">DivX Subtitles</a></li>
<li><a rel="nofollow" href="http://www.subtitles.cz/en/" target="parent">DivX Subtitles World</a></li>
<li><a rel="nofollow" href="http://www.rdwsubs.com/" target="parent">RDW Subtitles</a></li>
<li><a rel="nofollow" href="http://www.subbiee.com/" target="parent">Subbiee Search</a></li>
<li><a rel="nofollow" href="http://www.anysubs.com/" target="parent">Any Subs</a></li>
</ul>
<p style="text-align: left;">Idiomas Específicos:</p>
<ul style="text-align: left;">
<li><a rel="nofollow" href="http://subs.unacs.bg/" target="parent">Bulgarian Subtitles</a> (Bulgaro)</li>
<li><a rel="nofollow" href="http://www.central-subtitles.com/legendas/" target="parent">Central Subtitles</a> (Portugues)</li>
<li><a rel="nofollow" href="http://www.divxforever.net/" target="parent">DivXForever</a> (Turco)</li>
<li><a rel="nofollow" href="http://www.divxnorway.com/" target="parent">DivX Norway</a> (Noruego)</li>
<li><a rel="nofollow" href="http://kapsi.fi/%7Edivx/tekstitykset.php?dir=0" target="parent">DivX Nurkka</a> (Finlandes)</li>
<li><a rel="nofollow" href="http://www.divxplanet.com/" target="parent">DivX Planet</a> (Turco)</li>
<li><a rel="nofollow" href="http://forum.divxsweden.net/subs.php" target="parent">DivX Sweden</a> (Sueco)</li>
<li><a rel="nofollow" href="http://www.greeksubs.com/" target="parent">Greek Subs</a> (Griego)</li>
<li><a rel="nofollow" href="http://www.hosszupuska.fw.hu/" target="parent">Hosszupuska</a> (Hungaro)</li>
<li><a rel="nofollow" href="http://www.ondertitel.com/" target="parent">Ondertitels</a> (Holandes)</li>
<li><a rel="nofollow" href="http://www.movieplace.gr/" target="parent">MoviePlace</a> (Griego)</li>
<li><a rel="nofollow" href="http://www.napisy.info/" target="parent">Napisy.info</a> (Polaco)</li>
<li><a rel="nofollow" href="http://www.nlondertitels.com/" target="parent">NL Ondertitels</a> (Holandes)</li>
<li><a rel="nofollow" href="http://www.podnapisi.net/" target="parent">Podnapisi</a> (Eslovaco, Croata, Serbio, &#8230;)</li>
<li><a rel="nofollow" href="http://www.subdivx.com/" target="parent">SubDivX</a> (Español)</li>
<li><a rel="nofollow" href="http://www.subiarkisto.org/" target="parent">Subiarkisto</a> (Finlandes)</li>
<li><a rel="nofollow" href="http://www.subtitlesource.org/" target="parent">Subtitle Source</a> (Sueco, Finlandes, Danes y Noruego)</li>
<li><a rel="nofollow" href="http://www.subtitles.de/" target="parent">Subtitles.de</a> (Aleman)</li>
<li><a rel="nofollow" href="http://www.subtitles.ee/" target="parent">Subtitles.ee</a> (Ruso)</li>
<li><a rel="nofollow" href="http://www.torec.net/" target="parent">Torec.net</a> (Hebreo)</li>
<li><a rel="nofollow" href="http://www.undertexter.se/" target="parent">Undertexter</a> (Sueco)</li>
<li><a rel="nofollow" href="http://www.videometre.com/" target="parent">Videometre</a> (Turco)</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://mauriciopastrana.com/gadgets-y-tecnologia/guia-subtitula-tus-peliculas-divx-en-casi-cualquier-idioma/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Mi Web Mobil</title>
		<link>http://mauriciopastrana.com/gadgets-y-tecnologia/mi-web-mobil/</link>
		<comments>http://mauriciopastrana.com/gadgets-y-tecnologia/mi-web-mobil/#comments</comments>
		<pubDate>Sat, 11 Oct 2008 17:24:10 +0000</pubDate>
		<dc:creator>Mauricio Pastrana</dc:creator>
				<category><![CDATA[Gadgets y Tecnologia]]></category>
		<category><![CDATA[celular]]></category>
		<category><![CDATA[iphone]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://mauriciopastrana.com/gadgets-y-tecnologia/mi-web-mobil/</guid>
		<description><![CDATA[Soni soni&#8230; Sonido. Ya era hora! Estrenando wordpress para iphone que me canse del límite de 140 caracteres. Aún así, por si ver los updates de mi -otro blog no fuese suficiente, los invito a pasarse por http://twitter.com/mpastrana]]></description>
			<content:encoded><![CDATA[<p>Soni soni&#8230; Sonido.</p>
<p>Ya era hora! Estrenando wordpress para iphone que me canse del límite de 140 caracteres.</p>
<p>Aún así, por si ver los updates de mi -otro blog no fuese suficiente, los invito a pasarse por http://twitter.com/mpastrana</p>
]]></content:encoded>
			<wfw:commentRss>http://mauriciopastrana.com/gadgets-y-tecnologia/mi-web-mobil/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Esquemas URI</title>
		<link>http://mauriciopastrana.com/gente/esquemas-uri/</link>
		<comments>http://mauriciopastrana.com/gente/esquemas-uri/#comments</comments>
		<pubDate>Tue, 13 May 2008 20:53:03 +0000</pubDate>
		<dc:creator>Mauricio Pastrana</dc:creator>
				<category><![CDATA[Freelance]]></category>
		<category><![CDATA[Gadgets y Tecnologia]]></category>
		<category><![CDATA[Gente]]></category>
		<category><![CDATA[Listas]]></category>

		<guid isPermaLink="false">http://mauriciopastrana.com/?p=93</guid>
		<description><![CDATA[No es mas que un repost (Gracias! Gregorio), que: como todo aquello en este blog, existe solo con el proposito de no olvidarme de su existencia (aquello de la mala memoria). Al parecer, aparte de los &#8220;usuales&#8221; enlaces mailto: y callto: existe una larga lista de esquemas URI no-universalmente aceptados por los navegadores&#8230; ahora, primero, que es un [...]]]></description>
			<content:encoded><![CDATA[<p>No es mas que <a href="http://tempusfugit.ionosfera.com/2008/04/15/esquemas-uri-no-oficiales-callto-msnim-etc" target="_blank">un repost</a> (Gracias! <a href="http://tempusfugit.ionosfera.com/acerca-de" target="_blank">Gregorio</a>), que: como todo aquello en este blog, existe solo con el proposito de no olvidarme de su existencia (<a href="http://mauriciopastrana.com/gadgets-y-tecnologia/por-lo-menos-con-mi-memoria-no-cuento/" target="_blank">aquello de la mala memoria</a>).</p>
<p>Al parecer, aparte de los &#8220;usuales&#8221; enlaces <strong>mailto:</strong> y <strong>callto:</strong> existe una <a href="http://www.iana.org/assignments/uri-schemes.html" target="_blank">larga lista de esquemas URI</a> <em>no-universalmente aceptados por los navegadores&#8230;</em> ahora<em>,</em> primero, que es un URI?</p>
<p>Segun <a href="http://en.wikipedia.org/wiki/URI_scheme" target="_blank">el documento que lo especifica</a> (<a href="http://tools.ietf.org/html/rfc3986">rfc3986</a>), la URI (o, <a href="http://www.google.com/search?q=define%3A+uri&amp;rls=com.microsoft:*&amp;ie=UTF-8&amp;oe=UTF-8&amp;startIndex=&amp;startPage=1" target="_blank"><em>Uniform Resource Identifier</em></a>) es el puente sintactico entre tu navegador, el protocolo de comunicacion y el servidor. En su uso mas comun este refiere a websites, y asi como hay mucha habla sobre <a href="http://www.codinghorror.com/blog/archives/001109.html" target="_blank">la eliminacion del &#8220;tripledobleu&#8221;</a>, este es otro de aquellos que espero ver menos a medida que pasa el tiempo.</p>
<p>La sintaxis URI <a href="http://en.wikipedia.org/wiki/URI_scheme#Examples" target="_blank">trabaja del siguiente modo</a>:</p>
<p style='font-size:.7em'>  foo://usuario:clave@ejemplo.com:8042/pagpor/alla/index.dtb;tipo=animal?nombre=gato#nariz<br />
   \ /     \___________/\__________/ \__/\__________/ \___/ \_/ \_________/ \_________/ \__/<br />
    |           |            |        |          |         |         |                 |       |              |<br />
esquema info_usuario   dominio    puerto   ruta      archivo extension parametro(s)/consulta<br />
    |    \______________________________/<br />
    |                autoridad<br />
    |     ______________________<br />
   / \ /                                      \<br />
  urn:ejemplo:animal:gato:nariz</p>
<p>En su blog, Gregorio da una fila de los mas utiles:</p>
<ul>
<li style="TEXT-ALIGN: left"><strong>VoIP (general)</strong>: <em>callto:&lt;screenname&gt;</em> o <em>callto:&lt;phonenumber&gt;</em></li>
<li style="TEXT-ALIGN: left"><strong>Windows Live Messenger</strong>: <em>msnim:[add|chat|voice|video]?contact=&lt;username&gt;</em></li>
<li style="TEXT-ALIGN: left"><strong>GTalk</strong>: <em>gtalk:&lt;username&gt;</em></li>
<li style="TEXT-ALIGN: left"><strong>Yahoo! Messenger</strong>: <em>ymsgr:sendIM?&lt;screenname&gt;</em></li>
<li style="TEXT-ALIGN: left"><strong>Jabber</strong>: <em>xmpp:&lt;username&gt;</em></li>
<li style="TEXT-ALIGN: left"><strong>AOL Instant Messenger</strong>: <em>aim:[goim|addbuddy|buddyicon]?&lt;parameters&gt;</em></li>
<li style="TEXT-ALIGN: left"><strong>Skype</strong>: <em>skype:&lt;username|phonenumber&gt;[?[add|call|chat|sendfile|userinfo]]</em></li>
<li style="TEXT-ALIGN: left"><strong>Feeds</strong>: <em>feed:&lt;absolute_uri&gt;</em> or <em>feed://&lt;hierarchical part&gt;</em></li>
<li style="TEXT-ALIGN: left"><strong>IRC</strong>: <em>irc://&lt;host&gt;[:&lt;port&gt;]/[&lt;channel&gt;[?&lt;password&gt;]]</em></li>
<li style="TEXT-ALIGN: left"><strong>Last.fm</strong>: <em>lastfm://&lt;radio_stream&gt;</em> or <em>lastfm://globaltags/&lt;genre&gt;</em> o <em>lastfm://user/&lt;username&gt;/&lt;stuff&gt;</em></li>
<li style="TEXT-ALIGN: left"><strong>eDonkey2000</strong>: <em>ed2k://|file|&lt;filename&gt;|&lt;size of file&gt;|&lt;hash of file&gt;|/</em> o <em>ed2k://|server|&lt;host&gt;|&lt;port&gt;|/</em></li>
<li style="TEXT-ALIGN: left"><strong>iCalendar</strong>: <em>webcal://&lt;hierarchical part&gt;</em></li>
</ul>
<p style="TEXT-ALIGN: left">pero aca una lista que demuestra de que tan <span style="text-decoration: line-through;">inutiles</span> detallados estos pueden llegar a ser,</p>
<ul>
<li>
<div style="TEXT-ALIGN: left"><strong>Andrew File System global file names</strong> afs://</div>
</li>
<li>
<div style="TEXT-ALIGN: left"><strong>Prospero Directory Service</strong> prospero://</div>
</li>
<li>
<div style="TEXT-ALIGN: left"><strong>xmlrpc.beeps</strong>: xmlrpc.beeps://</div>
</li>
<li>
<div style="TEXT-ALIGN: left"><strong>Uniform Resource Names</strong> urn://</div>
</li>
<li>
<div style="TEXT-ALIGN: left"><strong>opaquelocktokent </strong>opaquelocktoken:// </div>
</li>
<li>
<div style="TEXT-ALIGN: left"><strong>Diameter: Protocol</strong> aaa://</div>
</li>
<li>
<div style="TEXT-ALIGN: left"><strong>Diameter: Protocol with Secure Transport</strong> aaas://</div>
</li>
</ul>
<p style="TEXT-ALIGN: left">&#8230; y mi favorito en inutilidad,</p>
<ul>
<li>
<div style="TEXT-ALIGN: left"><strong>TV-Anytime Content Reference Identifier </strong>crid://</div>
</li>
</ul>
<p style="TEXT-ALIGN: left">Entonces, sabiendo esto, tecnicamente yo podria decir: <a href="callto:6467367748">llamame</a>(<a href="skype://mauriciopastrana" target="_blank">skype</a>) o <a href="msnim:chat?contact=mauricio@pastrana.co.uk" target="_blank">buscame</a> <a href="webcal://www.michaelronkin.com/webcalendar/wc200602.html" target="_blank">hoy en la tarde</a>, que van a presentar algo sobre <a href="crid://bbc.co.uk/olympics/2008/ " target="_self">las proximas olimpiadas</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://mauriciopastrana.com/gente/esquemas-uri/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Por lo menos con mi memoria, no cuento.</title>
		<link>http://mauriciopastrana.com/gadgets-y-tecnologia/por-lo-menos-con-mi-memoria-no-cuento/</link>
		<comments>http://mauriciopastrana.com/gadgets-y-tecnologia/por-lo-menos-con-mi-memoria-no-cuento/#comments</comments>
		<pubDate>Sat, 19 Apr 2008 20:01:42 +0000</pubDate>
		<dc:creator>Mauricio Pastrana</dc:creator>
				<category><![CDATA[Gadgets y Tecnologia]]></category>

		<guid isPermaLink="false">http://mauriciopastrana.com/?p=92</guid>
		<description><![CDATA[Compulsivo. &#8230; Sip, asi fue como me categorizaron hoy en la mañana cuando le explicaba a un amigo las vueltas que hago para mantener mi vida organizada. Y como le decia a el, lo impresionante no es la cantidad de trabajo que hay que dedicarle a mantener en orden las cosas, sino la cantidad de [...]]]></description>
			<content:encoded><![CDATA[<p><em>Compulsivo</em>. &#8230; Sip, asi fue como me categorizaron hoy en la mañana cuando le explicaba a un amigo las vueltas que hago para mantener mi vida organizada. Y como le decia a el, lo impresionante no es la cantidad de trabajo que hay que dedicarle a mantener en orden las cosas, sino la cantidad de herramientas y servicios que hay que manejar para lograr hacerlo.</p>
<p>Si ustedes son algo como yo, y por el hecho que esten leyendo este blog asumo lo son, van a tener algun aspecto de vida digital por administrar. En mi caso; no es uno sin por dos, venga y contamos los servicios:</p>
<ul>
<li><a href="http://www.facebook.com/people/Mauricio_Pastrana/33412235" target="_blank">Facebook</a> (y <a href="http://www.facebook.com/apps/application.php?id=2442338999&amp;b&amp;ref=pd" target="_blank">Fonebook</a>)</li>
<li><a href="http://www.linkedin.com/pub/3/256/809" target="_blank">LinkedIn</a></li>
<li><a href="http://www.allocatus.com/Home/en/images/outlook_calendar_split.png" rel="lightbox[92]" target="_blank">Outlook</a></li>
<li><a href="http://osx.iusethis.com/screenshot/addressbook.png" rel="lightbox[92]" target="_blank">Address Book</a></li>
<li><a href="http://mauriciopastrana.myplaxo.com/" target="_blank">Plaxo</a></li>
<li><a href="http://twitter.com/mpastrana/" target="_blank">Twitter</a></li>
<li><a href="http://www.flickr.com/photos/mauriciopastrana" target="_blank">Flickr</a></li>
<li><a href="http://mauriciopastrana.com" target="_blank">WordPress</a></li>
<li><a href="mailto:5613198320@txt.att.net" target="_blank">iPhone</a> (incluye el Address book, Mail, Flickr, Twitter, &#8230; y <em>demás</em>)</li>
<li><a href="http://www.geni.com/profile/index/4632836426760072382?view_as=public" target="_blank">Geni</a></li>
<li><a href="http://www.netvibes.com/mauriciopastrana" target="_blank">Netvibes</a></li>
<li><a href="http://pastrana.co.uk/mail" target="_blank">Open WebMail</a></li>
<li><a href="http://usa2me.com" target="_blank">USA2me</a></li>
<li><a href="http://skype.com" target="_blank">Skype</a></li>
<li><a href="mailto:mauricio@pastrana.co.uk" target="_blank">MSN</a></li>
<li>Post-its!</li>
</ul>
<p>Y FIJO hay otro por ahi que se me quedo &#8230; pero bueno, como es esto de dos? pues:</p>
<p>Offline: USA2me, Outlook, Address Book, iPhone y los Post-its</p>
<p>Online: Twitter, Flickr, WordPress, Geni, Netvibes, WebMail, Skype y MSN</p>
<p>O mejor, esta grafica:</p>
<p style="text-align: center;"><img src="http://farm4.static.flickr.com/3008/2425285319_8be5f6cd81_d.jpg" alt="" /></p>
<p>Ya? Facil. Que impresion! para pensar que hace nada uno se memorizaba los telefonos y direcciones de sus amigos y familiares!. Tan solo piensen que cada servicio tiene su propia configuracion, estandar, plataforma e interaccion. El reto mas dificil aca es mantener el relajo pegado como un solo conjunto, mejor dicho:</p>
<p>- En mi blog (via plugins), hospedo a Twitter y Flickr.</p>
<p>- En Facebook (via aplicaciones), hospedo a Twitter, Flickr y WordPress.</p>
<p>- En Outlook (via extensiones y subscripciones) hospedo a Plaxo, WordPress, Netvibes y Facebook</p>
<p>Queda claro? Por supuesto, que&#8230; pensandolo bien, mi herramienta mas util en el embrollo viene a ser mi mac donde hospedo a Facebook, Outlook, Address Book, Plaxo, Twitter, Flickr, WordPress. el iPhone (sync), Geni, Netvibes, WebMail, USA2me (consola administrativa), Skype, MSN y si consideramos su superficie sin uso, tambien los Post-its! <em>Phew</em>! Saben que? Me alegro de tener mi mac.</p>
<p>Y con todo esto que me gano? 551 contactos en Facebook, 838 contactos en Outlook, mas de 150 familiares registrados en Geni, 30 contactos en Plaxo y un sinnumero de fotos en Flickr, Facebook, Plaxo, Twitter&#8230; sigh. Ah si, y un relajo de menciones en <a href="http://www.google.com/search?q=%22Mauricio+Pastrana%22&amp;ie=utf-8&amp;oe=utf-8&amp;aq=t&amp;rls=org.mozilla:en-US:official&amp;client=firefox-a" target="_blank">Google,</a> <a href="http://search.yahoo.com/search?p=%22Mauricio+Pastrana%22" target="_blank">Yahoo</a> y <a href="http://technorati.com/search/%22Mauricio+Pastrana%22?authority=n&amp;language=n" target="_blank">Technorati</a>. Bueno; por lo menos ya sabemos el porque no se puede seguir contando con la cabeza eh?</p>
]]></content:encoded>
			<wfw:commentRss>http://mauriciopastrana.com/gadgets-y-tecnologia/por-lo-menos-con-mi-memoria-no-cuento/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Guia: Descarga tus contactos de facebook a Outlook</title>
		<link>http://mauriciopastrana.com/gente/guia-descarga-tus-contactos-de-facebook-a-outlook/</link>
		<comments>http://mauriciopastrana.com/gente/guia-descarga-tus-contactos-de-facebook-a-outlook/#comments</comments>
		<pubDate>Fri, 11 Jan 2008 00:40:33 +0000</pubDate>
		<dc:creator>Mauricio Pastrana</dc:creator>
				<category><![CDATA[Freelance]]></category>
		<category><![CDATA[Gadgets y Tecnologia]]></category>
		<category><![CDATA[Gente]]></category>
		<category><![CDATA[codigo]]></category>
		<category><![CDATA[facebook]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[programacion]]></category>

		<guid isPermaLink="false">http://mauriciopastrana.com/gente/guia-descarga-tus-contactos-de-facebook-a-outlook/</guid>
		<description><![CDATA[Cada 4 a seis meses me encuentro con el siguiente problema: 400 contactos en outlook, 500 contactos en Facebook. Dejando de lado la discusión de si son &#8220;amigos&#8221; o no, yo mas bien me pregunto: quienes son esos extra 100? (o 200, 300?). De costumbre, me gusta tener todos mis contactos en Outlook, que a [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://mauriciopastrana.com/wp-content/uploads/2008/01/picture-1asa.png" rel="lightbox[84]" title="fb friends"><img src="http://mauriciopastrana.com/wp-content/uploads/2008/01/picture-1asa.png" alt="fb friends" align="left" border="0" hspace="5" vspace="5" /></a>Cada 4 a seis meses me encuentro con el siguiente problema: 400 contactos en outlook, 500 contactos en Facebook. Dejando de lado la discusión de si son &#8220;amigos&#8221; o no, yo mas bien me pregunto: quienes son esos extra 100? (o 200, 300?).</p>
<p>De costumbre, me gusta tener todos mis contactos en Outlook, que a su ves se vuelve mi lista de números en el iphone, mac address book y otro sinnúmero de lugares gracias al <a href="http://www.plaxo.com/info">plaxo sync</a>. Así que amigo o no amigo, igual clasifica como contacto.</p>
<p>De costumbre, y gracias al hecho que facebook no permite hacer descargas de listas a Outlook (o a cualquier cosa ya que va en contra del <a href="http://www.facebook.com/terms.php" target="_blank">EULA</a>), por los últimos 2 años me he llevado a la costumbre de planear una noche, mañana o día para que, en viñetas únicas de firefox, cargue cada uno de mis contactos y, con mucho café en mano; me dedico a copiar la información a Outlook, uno a uno. Si ya se, que tedio!.</p>
<p>Hoy decidí hacerle corte a este vicio. De hecho, con los 530-yalgo contactos que encuentro bajo mi perfil de Facebook, estaría viendo unos dos o tres días de labor manual, esta guia explica el como solucione mi problema con un poco de PHP, MySQL y paciencia.</p>
<p>De antemano me disculpo si el articulo cae un poco, técnico. Traten de seguirme la bola. <a href="http://www.dataportability.org/" target="_blank">Algún día muy pronto, Facebook y Plaxo harán un import/export tool</a>, pero por ahora, es así o así.</p>
<p><span id="more-84"></span></p>
<h2>Screen Scraping &#8211; Que es?</h2>
<p>Primero que todo, no esta bien visto esto del &#8220;scraping&#8221;. A través de PHP, es la practica de programar un website para que &#8220;a mano automatizada&#8221; lea otro website (ej: programar una pagina _mía_ que da los precios del NASDAQ en el instante que cargue, leyendolos del código fuente de CNNMoney.com). Y que es lo que pasa con el scraping? no solo anota visitas &#8220;falsas&#8221; del lado de CNNMoney, sino que trae a luz moderna la vieja practica del &#8220;hotlinking&#8221;, donde yo en esencia me estoy robando ancho de banda de otros al colgar imágenes en mis paginas, que no estén hospedadas en mi servidor.</p>
<h2>Estrategia</h2>
<p>Primero lo primero. Para aquellos que no lo tengan bien medido, hay tres (si, tres) portales de facebook (en la plataforma publica). Facebook estandar (en <a href="http://www.facebook.com/" target="_blank">www.facebook.com</a>), Facebook Mobile (en <a href="http://m.facebook.com" target="_blank">m.facebook.com</a>) y Facebook para iphone (en <a href="http://iphone.facebook.com" target="_blank">iphone.facebook.com</a>). Para los curiosos, facebook tambien tiene portales privados (en los casos de compañias que compran facebook corporate -ejemplo: <a href="http://www.scribd.com/doc/81162/RedBull-Case-Study-FINAL" target="_blank">redbull</a>). Para este proyecto voy a explotar la diferencia entre portales, mas importantemente; el hecho que facebook mobile es un mini-facebook en html plano (de minimo uso de ancho de banda), que le da la vuelta al problema que en los otros portales, los llamados de datos son tablas en ajax o flash, para el caso de PHP cURL, es lo que llaman un &#8220;showstopper&#8221;.</p>
<p>De hecho, los invito a pasarse por m.facebook.com, desde firefox o desde el celular (el portal de iphone tambien sirve!).</p>
<p>El proyecto entonces, gracias a las <a href="http://textsnippets.com/posts/show/1204" target="_blank">herramientas disponibles</a>, lo armo del siguiente modo:</p>
<ul>
<li> Paso 1: Un levante de información que trae a mi base de datos una lista de todos mis contactos y su identificador privado dentro de Facebook</li>
</ul>
<ul>
<li> Paso 2: Un proceso iterativo que se base en la lista generada en el paso 1, que mire cada pagina de perfil de usuario según el id privado, levante cuanta información pueda de este y la anote a otra tabla en la base de datos</li>
</ul>
<ul>
<li> Paso 3: Un script que deje descargar los datos desde la base de datos en formato vcard (vcf)</li>
</ul>
<p>Retos y problemas previstos? Uno, y grande. Facebook no presenta las direcciones de email en texto plano sino en ves genera una imagen con el email impreso (trata de hacer copy paste de cualquier email en algun perfil de usuario!). De todos modos, para traer la foto del perfil del usuario <a href="http://www.facebook.com/applications/Fonebook/2442338999" target="_blank">existen soluciones simples</a>.</p>
<h2>Un poco de codigo</h2>
<p>Asi que, manos a la obra.</p>
<h3>Paso 1:</h3>
<p>Primero voy a generar un script que me deje emular el sistema de login a facebook mobile, para este; voy a explotar el hecho que www.facebook.com (un login por html), envía una variable que genera una redirección. Para aquellos que no saben nada de cURL, <a href="http://www.higherpass.com/php/Tutorials/Using-Curl-To-Query-Remote-Servers/" target="_blank">aca hay una guia</a>.</p>
<p>Las variables importantes acá son:<br />
<strong>curl_setopt($ch, CURLOPT_URL, &#8216;https://login.facebook.com/login.php?m&amp;next=http%3A%2F%2Fm.facebook.com%2Fhome.php&#8217;);curl_setopt($ch, CURLOPT_POSTFIELDS,&#8217;email=&#8217;.urlencode($login_email).&#8217;&amp;pass=&#8217;.urlencode($login_pass).&#8217;&amp;login=Login&#8217;);</strong></p>
<p>Y ojo que también hay que decirle a cURL donde dejar las cookies que entregue Facebook (ojo que el archivo tiene que existir, y <em>debe de tener privilegios de acceso para escritura, osea: chmod 777</em>):<br />
<strong> curl_setopt($ch, CURLOPT_COOKIEJAR, &#8220;myCookieFile.txt&#8221;);<br />
curl_setopt($ch, CURLOPT_COOKIEFILE, &#8220;myCookieFile.txt&#8221;);</strong></p>
<p>Y una mas, a facebook no le gustan los headers básicos de cURL, asi que toca simular que somos alguien en un browser normal, ya que planeo ejecutar el codigo desde el browser, voy a decirle a cURL que recicle el agente:<br />
<strong> curl_setopt($ch, CURLOPT_POST, 1);<br />
curl_setopt($ch, CURLOPT_HEADER, 0);<br />
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);<br />
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);<br />
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);<br />
curl_setopt($ch, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']);</strong></p>
<p>Va? Nuestro script entero, para hacer login a facebook y traerse el contenido entero al browser entonces es:</p>
<p><strong>//login a fb<br />
$login_email = &#8216;FACEBOOK@EMAIL.COM&#8217;;<br />
$login_pass = &#8216;PASSWORD&#8217;;</strong></p>
<p><strong>$ch = curl_init();<br />
curl_setopt($ch, CURLOPT_URL, &#8216;https://login.facebook.com/login.php?m&amp;next=http%3A%2F%2Fm.facebook.com%2Fhome.php&#8217;);<br />
curl_setopt($ch, CURLOPT_POSTFIELDS,&#8217;email=&#8217;.urlencode($login_email).&#8217;&amp;pass=&#8217;.urlencode($login_pass).&#8217;&amp;login=Login&#8217;);<br />
curl_setopt($ch, CURLOPT_POST, 1);<br />
curl_setopt($ch, CURLOPT_HEADER, 0);<br />
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);<br />
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);<br />
curl_setopt($ch, CURLOPT_COOKIEJAR, &#8220;myCookieFile.txt&#8221;);<br />
curl_setopt($ch, CURLOPT_COOKIEFILE, &#8220;myCookieFile.txt&#8221;);<br />
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);<br />
curl_setopt($ch, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']);<br />
curl_exec($ch);</strong></p>
<p><strong>//So what? bueno, ahora hagamos un llamado con cURL! <img src='http://mauriciopastrana.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </strong></p>
<p><strong>curl_setopt($ch, CURLOPT_POST, 0);<br />
curl_setopt($ch, CURLOPT_URL, &#8216;http://m.facebook.com/home.php&#8217;);<br />
$page = curl_exec($ch);<br />
print_r($page);</strong></p>
<p>Guarda, abre el script desde firefox (ojo a los permisos del archivo txt de cookies -myCookieFile.txt) y:</p>
<p><a href="http://mauriciopastrana.com/wp-content/uploads/2008/01/ytre.png" rel="lightbox[84]" title="facebook mobile"></a></p>
<p style="text-align: center"><a href="http://mauriciopastrana.com/wp-content/uploads/2008/01/ytre.png" rel="lightbox[84]" title="facebook mobile"><img src="http://mauriciopastrana.com/wp-content/uploads/2008/01/ytre.png" alt="facebook mobile" border="0" height="416" width="501" /></a></p>
<p>Fácil ah? Bueno, ahora lo divertido.</p>
<p>Primero, me dirijo a la pagina que me interesa http://m.facebook.com/friends.php?a, y le digo a cURL que envie todo a una variable $html :</p>
<p><strong>curl_setopt($ch, CURLOPT_POST, 0);<br />
curl_setopt($ch, CURLOPT_URL, &#8220;http://m.facebook.com/friends.php?a&#8221;);<br />
$page = curl_exec($ch);</strong></p>
<p><strong>curl_setopt($ch, CURLOPT_FAILONERROR, true);<br />
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);<br />
curl_setopt($ch, CURLOPT_AUTOREFERER, true);<br />
curl_setopt($ch, CURLOPT_RETURNTRANSFER,true);<br />
curl_setopt($ch, CURLOPT_TIMEOUT, 10);<br />
$html= curl_exec($ch);<br />
if (!$html) {<br />
echo &#8220;&lt;br /&gt;cURL error number:&#8221; .curl_errno($ch);<br />
echo &#8220;&lt;br /&gt;cURL error:&#8221; . curl_error($ch);<br />
exit;<br />
}</strong></p>
<p>y despues, le digo a PHP que lo traduzca a un DOM&#8230;</p>
<p><strong>$dom = new DOMDocument();<br />
@$dom-&gt;loadHTML($html);</strong></p>
<p>&#8230; se pesque solo los items &lt;a href&gt; (links)&#8230;</p>
<p><strong>$xpath = new DOMXPath($dom);<br />
$hrefs = $xpath-&gt;evaluate(&#8220;/html/body//a&#8221;);</strong></p>
<p>&#8230; y finalmente, lo pongo en un loop a analizar cada enlace por si solo:</p>
<p><strong>//iteramos &#8230;<br />
for ($i = 0; $i &lt; $hrefs-&gt;length; $i++) {<br />
$href = $hrefs-&gt;item($i);<br />
$profile_url = $href-&gt;getAttribute(&#8216;href&#8217;);</strong></p>
<p><strong>//&#8230; filtrando solo los enlaces que lleven a perfiles<br />
if((strpos($profile_url,&#8221;/profile.php?id=&#8221;) !== false) &amp;&amp; strpos($profile_url,&#8221;http://m.facebook.com/&#8221;) === false){</strong></p>
<p><strong>//&#8230; y nos guardamos en la base de datos el nombre del contacto y la URL que apunta al perfil<br />
$profile_name = $href-&gt;nodeValue;<br />
storeLink($profile_url,$profile_name);<br />
echo &#8220;&lt;br /&gt;Profile URL Stored: $profile_name ($profile_url)&#8221;;</strong></p>
<p><strong>} //end filter</strong></p>
<p><strong>}//end single page reading</strong></p>
<p>BTW, esa funcion que guarda en la base de datos (storeLink), la arme del siguiente modo (usando ADOdb):</p>
<p><strong>function storeLink($url,$profile_name) {<br />
global $db;<br />
$query = &#8220;INSERT INTO fb_profiles_list (profile_url, profile_name) VALUES (&#8216;$url&#8217;, &#8216;$profile_name&#8217;)&#8221;;<br />
$insert = $db-&gt;Execute($query);<br />
}</strong></p>
<p>Listos? bueno pues falta. resulta que la pagina que estamos mirando solo muestra 10 records, asi que hay que iterar, segun la cantidad de contactos, la estructura es la siguiente: http://m.facebook.com/friends.php?a&amp;p=$page_counter. Personalmente, tengo el loop estructurado a mano, asi que; como poseo 532 contactos, a 10 contactos por pagina; pues me preparo un loop que cuente 54 pasadas de pagina.</p>
<p><strong>$num_pageflips = 54;<br />
for  ($page_counter = 1; $page_counter &lt;= $num_pageflips; $page_counter++) {<br />
&#8230;<br />
curl_setopt($ch, CURLOPT_URL, &#8220;http://m.facebook.com/friends.php?a&amp;p=$page_counter&#8221;);<br />
&#8230;</strong></p>
<p>Asi que, nuestro script para el paso 1 (incluyendo el archivo de los cookies), lee asi (Phew!):</p>
<p><strong>&lt;?<br />
/*******************************<br />
*    Facebook Downloader (to MySQL)<br />
*    Mauricio Pastrana<br />
*    http://www.via-the-internet.com<br />
*    January 2008<br />
*<br />
*    Many Thanks to:     Christian Flickinger (http://nexdot.net/blog) and (http://textsnippets.com/posts/show/1204)<br />
*                Justin Laing (http://www.merchantos.com/makebeta/php/scraping-links-with-php/)<br />
*<br />
*        **DONT RUN BLINDLY, DONT DISTRIBUTE SO FREELY, WATCH OUT FOR LINES 26, 27 and 56<br />
*<br />
*******************************/</strong></p>
<p><strong>//get our database (using ADODB: http://adodb.sourceforge.net/)<br />
require(&#8216;includes/database/connection.inc&#8217;);</strong></p>
<p><strong>//a function to write to the database<br />
function storeLink($url,$profile_name) {<br />
global $db;<br />
$query = &#8220;INSERT INTO fb_profiles_list (profile_url, profile_name) VALUES (&#8216;$url&#8217;, &#8216;$profile_name&#8217;)&#8221;;<br />
$insert = $db-&gt;Execute($query);<br />
}</strong></p>
<p><strong>//login to fb<br />
$login_email = &#8216;FACEBOOK@EMAIL.COM&#8217;;<br />
$login_pass = &#8216;PASSWORD&#8217;;</strong></p>
<p><strong>$ch = curl_init();<br />
curl_setopt($ch, CURLOPT_URL, &#8216;https://login.facebook.com/login.php?m&amp;next=http%3A%2F%2Fm.facebook.com%2Fhome.php&#8217;);<br />
curl_setopt($ch, CURLOPT_POSTFIELDS,&#8217;email=&#8217;.urlencode($login_email).&#8217;&amp;pass=&#8217;.urlencode($login_pass).&#8217;&amp;login=Login&#8217;);<br />
curl_setopt($ch, CURLOPT_POST, 1);<br />
curl_setopt($ch, CURLOPT_HEADER, 0);<br />
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);<br />
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);<br />
curl_setopt($ch, CURLOPT_COOKIEJAR, &#8220;myCookieFile.txt&#8221;);<br />
curl_setopt($ch, CURLOPT_COOKIEFILE, &#8220;myCookieFile.txt&#8221;);<br />
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);<br />
curl_setopt($ch, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']);<br />
curl_exec($ch);</strong></p>
<p><strong>//need to test this? comment the uncomment this, comment everything else below it and browse to the script, you should get the m.facebook.com home page <img src='http://mauriciopastrana.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </strong></p>
<p><strong>/*curl_setopt($ch, CURLOPT_POST, 0);<br />
curl_setopt($ch, CURLOPT_URL, &#8216;http://m.facebook.com/home.php&#8217;);<br />
$page = curl_exec($ch);<br />
print_r($page);<br />
*/</strong></p>
<p><strong>//ok, we&#8217;re in! now head over to friends, if you have more than 10 (most likely), then we will have to iterate</strong></p>
<p><strong>// ok so: I know this can be done on automatic, but it makes the script more readable if you do some manual work (ugh).<br />
// It&#8217;s real easy, find out how many friends you have (login, then go to:  http://m.facebook.com/friends.php?a), and<br />
// divide the number by 10! Easy, see? now input the number here:<br />
$num_pageflips = 54;<br />
// I have 532 &#8220;friends&#8221; at the moment, so expect 54 pages of friends and set $num_pageflips = 54</strong></p>
<p><strong>for  ($page_counter = 1; $page_counter &lt;= $num_pageflips; $page_counter++) {</strong></p>
<p><strong>//head over to our friend page, note the first page is &amp;p=1<br />
curl_setopt($ch, CURLOPT_POST, 0);<br />
curl_setopt($ch, CURLOPT_URL, &#8220;http://m.facebook.com/friends.php?a&amp;p=$page_counter&#8221;);<br />
$page = curl_exec($ch);</strong></p>
<p><strong>curl_setopt($ch, CURLOPT_FAILONERROR, true);<br />
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);<br />
curl_setopt($ch, CURLOPT_AUTOREFERER, true);<br />
curl_setopt($ch, CURLOPT_RETURNTRANSFER,true);<br />
curl_setopt($ch, CURLOPT_TIMEOUT, 10);<br />
$html= curl_exec($ch);<br />
if (!$html) {<br />
echo &#8220;&lt;br /&gt;cURL error number:&#8221; .curl_errno($ch);<br />
echo &#8220;&lt;br /&gt;cURL error:&#8221; . curl_error($ch);<br />
exit;<br />
}</strong></p>
<p><strong>// parse the html into a DOMDocument<br />
$dom = new DOMDocument();<br />
@$dom-&gt;loadHTML($html);</strong></p>
<p><strong>// grab all the links on the page<br />
$xpath = new DOMXPath($dom);<br />
$hrefs = $xpath-&gt;evaluate(&#8220;/html/body//a&#8221;);</strong></p>
<p><strong>//now iterate through the whole HTML to grab what we need<br />
for ($i = 0; $i &lt; $hrefs-&gt;length; $i++) {<br />
$href = $hrefs-&gt;item($i);<br />
$profile_url = $href-&gt;getAttribute(&#8216;href&#8217;);</strong></p>
<p><strong>//filter out only the profile links and names!<br />
if((strpos($profile_url,&#8221;/profile.php?id=&#8221;) !== false) &amp;&amp; strpos($profile_url,&#8221;http://m.facebook.com/&#8221;) === false){</strong></p>
<p><strong>//get the actual person&#8217;s name (from the link as well), and store it on the db. also, let me know how it&#8217;s going<br />
$profile_name = $href-&gt;nodeValue;<br />
storeLink($profile_url,$profile_name);<br />
echo &#8220;&lt;br /&gt;Profile URL Stored: $profile_name ($profile_url)&#8221;;</strong></p>
<p><strong>} //end filter</strong></p>
<p><strong>}//end single page reading</strong></p>
<p><strong>}//end pageflips<br />
?&gt;</strong></p>
<p>Bien ejecutado, este script les debe de dejar una base de datos con un listado de todos los contactos, mas las URL que refieren a su pagina de perfil. Como si no fuera suficiente, aca va el SQL que genera la tabla referente al paso 1:</p>
<p><strong>CREATE TABLE `fb_profiles_list` (<br />
`id` int(11) NOT NULL auto_increment,<br />
`profile_url` varchar(255) default NULL,<br />
`profile_name` varchar(255) default NULL,<br />
PRIMARY KEY  (`id`)<br />
) ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=latin1;</strong></p>
<h3>Paso 2:</h3>
<p>Bueno, ya tenemos ahora una lista larga de URLs, no? ahora la estrategia es la siguiente. Vamos a iterar y pasar por cada uno de estos URL (usando la estructura del paso 1 para hacer &#8220;login&#8221;), y de este; leer el HTML que nos de items de interes. Voy a preparar una funcion en PHP que me rebote todo el texto en un string entre un punto de inicio y un final:</p>
<p><strong>// Funcion para extraer algo atrapado entre dos strings definidas por el usuario.<br />
// Ejemplo: $string = &#8220;&lt;div style=&#8217;blablabla&#8217;&gt;texto&lt;/div&gt;&#8221;<br />
// get_string_between($string,&#8221;&lt;div style=&#8217;&#8221;,&#8221;&#8216;&gt;texto&#8221;) &#8211;&gt; entrega blablabla<br />
//<br />
function get_string_between($string, $start, $end){<br />
$string = &#8221; &#8220;.$string;<br />
$ini = strpos($string,$start);<br />
if ($ini == 0) return &#8220;&#8221;;<br />
$ini += strlen($start);<br />
$len = strpos($string,$end,$ini) &#8211; $ini;<br />
return substr($string,$ini,$len);<br />
}</strong></p>
<p>Listo? bueno, ahora esta facil, repito la estructura del script del paso 1, solo que ahora mirando a una pagina de perfil: http://m.facebook.com/profile.php?id=12345&amp;full (y ojo a incluir la variable &amp;full!)</p>
<p><strong>curl_setopt($ch, CURLOPT_POST, 0);<br />
curl_setopt($ch, CURLOPT_URL, &#8220;http://m.facebook.com/profile.php?id=&#8221;.$profile_id.&#8221;&amp;full&#8221;);<br />
$page = curl_exec($ch);</strong></p>
<p>y estando adentro del perfil, no es sino identificar que item queremos enviar a la base de datos, generamos una variable que lo archive, y al final hacemos un &#8220;mega&#8221;llamado a store, ejemplo:</p>
<p><strong>//AIM<br />
$aim = get_string_between($page, &#8216;AIM:  &#8216;, &#8216;&lt;br /&gt;&#8217;);<br />
echo &#8220;AIM: &#8220;.$aim.&#8221;&lt;br /&gt;&#8221;;</strong></p>
<p><strong>//Yahoo<br />
$yahoo = get_string_between($page, &#8216;Yahoo:  &#8216;, &#8216;&lt;br /&gt;&#8217;);<br />
echo &#8220;Yahoo: &#8220;.$yahoo.&#8221;&lt;br /&gt;&#8221;;</strong></p>
<p>y al final:</p>
<p><strong>storeProfileData($first_name, $last_name, $website, $aim, $yahoo, $windows_live, $skype, $tel, $current_address, $current_town, $home_town, $birthday, $work_info, $position);</strong></p>
<p>donde:</p>
<p><strong>function storeProfileData($first_name, $last_name, $website, $aim, $yahoo, $windows_live, $skype, $tel, $current_address, $current_town, $home_town, $birthday, $work_info, $position){<br />
global $db;<br />
$query = &#8220;INSERT INTO fb_specific_profiles (first_name, last_name, website, aim, yahoo, windows_live, skype, tel, current_address, current_town, home_town, birthday, work_info, position) VALUES (&#8216;$first_name&#8217;, &#8216;$last_name&#8217;, &#8216;$website&#8217;, &#8216;$aim&#8217;, &#8216;$yahoo&#8217;, &#8216;$windows_live&#8217;, &#8216;$skype&#8217;, &#8216;$tel&#8217;, &#8216;$current_address&#8217;, &#8216;$current_town&#8217;, &#8216;$home_town&#8217;, &#8216;$birthday&#8217;, &#8216;$work_info&#8217;, &#8216;$position&#8217;)&#8221;;<br />
$insert = $db-&gt;Execute($query);<br />
}</strong></p>
<p>LISTOS! Ahora iteramos por todo el data set del paso 1, para generar el del paso 2!</p>
<p>Ya a estas alturas creo, no hay nadie conmigo. &#8230; pero si tuvieron la paciencia, acá esta el script entero de la parte 2:</p>
<p><strong>&lt;?<br />
/*******************************<br />
*    Facebook Downloader (to MySQL)<br />
*    Mauricio Pastrana<br />
*    http://www.via-the-internet.com<br />
*    January 2008<br />
*<br />
*    Many Thanks to:     Christian Flickinger (http://nexdot.net/blog) and (http://textsnippets.com/posts/show/1204)<br />
*                Justin Laing (http://www.merchantos.com/makebeta/php/scraping-links-with-php/)<br />
*<br />
*        **DONT RUN BLINDLY, DONT DISTRIBUTE SO FREELY, NOTE YOU NEED TO RUN THE FIRST SCRAPER FIRST<br />
*<br />
*******************************/</strong></p>
<p><strong>//get our database (using ADODB: http://adodb.sourceforge.net/)<br />
require(&#8216;includes/database/connection.inc&#8217;);</strong></p>
<p><strong>//a function to write to the database<br />
function storeProfileData($first_name, $last_name, $website, $aim, $yahoo, $windows_live, $skype, $tel, $current_address, $current_town, $home_town, $birthday, $work_info, $position){<br />
global $db;<br />
$query = &#8220;INSERT INTO fb_specific_profiles (first_name, last_name, website, aim, yahoo, windows_live, skype, tel, current_address, current_town, home_town, birthday, work_info, position) VALUES (&#8216;$first_name&#8217;, &#8216;$last_name&#8217;, &#8216;$website&#8217;, &#8216;$aim&#8217;, &#8216;$yahoo&#8217;, &#8216;$windows_live&#8217;, &#8216;$skype&#8217;, &#8216;$tel&#8217;, &#8216;$current_address&#8217;, &#8216;$current_town&#8217;, &#8216;$home_town&#8217;, &#8216;$birthday&#8217;, &#8216;$work_info&#8217;, &#8216;$position&#8217;)&#8221;;<br />
$insert = $db-&gt;Execute($query);<br />
}</strong></p>
<p><strong>//a function to get the text between to user defined strings<br />
function get_string_between($string, $start, $end){<br />
$string = &#8221; &#8220;.$string;<br />
$ini = strpos($string,$start);<br />
if ($ini == 0) return &#8220;&#8221;;<br />
$ini += strlen($start);<br />
$len = strpos($string,$end,$ini) &#8211; $ini;<br />
return substr($string,$ini,$len);<br />
}</strong></p>
<p><strong>//login to fb<br />
$login_email = &#8216;FACEBOOK@EMAIL.COM&#8217;;<br />
$login_pass = &#8216;PASSWORD&#8217;;</strong></p>
<p><strong>$ch = curl_init();<br />
curl_setopt($ch, CURLOPT_URL, &#8216;https://login.facebook.com/login.php?m&amp;next=http%3A%2F%2Fm.facebook.com%2Fhome.php&#8217;);<br />
curl_setopt($ch, CURLOPT_POSTFIELDS,&#8217;email=&#8217;.urlencode($login_email).&#8217;&amp;pass=&#8217;.urlencode($login_pass).&#8217;&amp;login=Login&#8217;);<br />
curl_setopt($ch, CURLOPT_POST, 1);<br />
curl_setopt($ch, CURLOPT_HEADER, 0);<br />
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);<br />
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);<br />
curl_setopt($ch, CURLOPT_COOKIEJAR, &#8220;myCookieFile.txt&#8221;);<br />
curl_setopt($ch, CURLOPT_COOKIEFILE, &#8220;myCookieFile.txt&#8221;);<br />
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);<br />
curl_setopt($ch, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']);<br />
curl_exec($ch);</strong></p>
<p><strong>//need to test this? comment the uncomment this, comment everything else below it and browse to the script, you should get the m.facebook.com home page <img src='http://mauriciopastrana.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </strong></p>
<p><strong>/*curl_setopt($ch, CURLOPT_POST, 0);<br />
curl_setopt($ch, CURLOPT_URL, &#8216;http://m.facebook.com/home.php&#8217;);<br />
$page = curl_exec($ch);<br />
print_r($page);<br />
*/</strong></p>
<p><strong>//ok, we&#8217;re in! now head over to each specific profile page, we&#8217;re going to have to loop through the whole dataset and use a LOT of substring magic</strong></p>
<p><strong>//first, we find out where we are as far as id&#8217;s in the db (if you&#8217;re lucky, yours starts at 1, i did some testing, so my first profile begins at id=127!)</strong></p>
<p><strong>echo &#8220;profiles found in db: &#8220;.$num_profiles = $db-&gt;GetOne(&#8220;SELECT COUNT(*) FROM fb_profiles_list&#8221;).&#8221;&lt;br /&gt;&#8221;;<br />
echo &#8220;first profile id: &#8220;.$first_profile_id = $db-&gt;GetOne(&#8220;SELECT id FROM fb_profiles_list&#8221;).&#8221;&lt;br /&gt;&#8221;;</strong></p>
<p><strong>for  ($profile_counter = 0; $profile_counter &lt; $num_profiles; $profile_counter++) {</strong></p>
<p><strong>//be a little verbose<br />
echo $profile_counter.&#8221;&lt;br /&gt;&lt;br /&gt;&#8221;;<br />
$profile_id = get_string_between($db-&gt;GetOne(&#8220;SELECT profile_url FROM fb_profiles_list WHERE id=&#8221;.($first_profile_id+$profile_counter)), &#8216;/profile.php?id=&#8217;, &#8216;&amp;r&#8217;);<br />
echo &#8220;Now Trying: &#8221; .<br />
$db-&gt;GetOne(&#8220;SELECT profile_name FROM fb_profiles_list WHERE id=&#8221;.($first_profile_id+$profile_counter)) . //profile_name<br />
&#8221; (&#8221; . $profile_id . &#8220;) &lt;br /&gt;&#8221;; // profile_id</strong></p>
<p><strong>curl_setopt($ch, CURLOPT_POST, 0);<br />
curl_setopt($ch, CURLOPT_URL, &#8220;http://m.facebook.com/profile.php?id=&#8221;.$profile_id.&#8221;&amp;full&#8221;);<br />
$page = curl_exec($ch);<br />
//print_r($page);</strong></p>
<p><strong>//Name<br />
$name = explode(&#8221; &#8220;,get_string_between($page, &#8216;&lt;title&gt;Facebook | &#8216;, &#8216;\&#8217;s Profile&lt;/title&gt;&#8217;));</strong></p>
<p><strong>$first_name = $name[0];<br />
$last_name = $name[1];</strong></p>
<p><strong>echo &#8220;First Name :$first_name &lt;br /&gt;&#8221;;<br />
echo &#8220;Last Name :$last_name &lt;br /&gt;&#8221;;</strong></p>
<p><strong>//Website<br />
$website = get_string_between($page, &#8216;Website:  &lt;a href=&#8221;&#8216;, &#8216;?refid=17&#8243;&gt;&#8217;);<br />
echo &#8220;Website: &#8220;.$website.&#8221;&lt;br /&gt;&#8221;;</strong></p>
<p><strong>//AIM<br />
$aim = get_string_between($page, &#8216;AIM:  &#8216;, &#8216;&lt;br /&gt;&#8217;);<br />
echo &#8220;AIM: &#8220;.$aim.&#8221;&lt;br /&gt;&#8221;;</strong></p>
<p><strong>//Yahoo<br />
$yahoo = get_string_between($page, &#8216;Yahoo:  &#8216;, &#8216;&lt;br /&gt;&#8217;);<br />
echo &#8220;Yahoo: &#8220;.$yahoo.&#8221;&lt;br /&gt;&#8221;;</strong></p>
<p><strong>//Windows Live<br />
$windows_live = get_string_between($page, &#8216;Windows Live:  &#8216;, &#8216;&lt;br /&gt;&#8217;);<br />
echo &#8220;Windows Live: &#8220;.$windows_live.&#8221;&lt;br /&gt;&#8221;;</strong></p>
<p><strong>//Skype<br />
$skype = get_string_between($page, &#8216;Skype:  &#8216;, &#8216;&lt;br /&gt;&#8217;);<br />
echo &#8220;Skype: &#8220;.$skype.&#8221;&lt;br /&gt;&#8221;;</strong></p>
<p><strong>//Tel<br />
$tel = get_string_between($page, &#8216;&lt;a href=&#8221;tel:&#8217;, &#8216;&#8221;&gt;&#8217;);<br />
echo &#8220;Tel: &#8220;.$tel.&#8221;&lt;br /&gt;&#8221;;</strong></p>
<p><strong>//Current Address<br />
$current_address = get_string_between($page, &#8216;Current Address:  &#8216;, &#8216;&lt;br /&gt;&#8217;);<br />
echo &#8220;Current Address: &#8220;.$current_address.&#8221;&lt;br /&gt;&#8221;;</strong></p>
<p><strong>//Current Town<br />
$current_town = get_string_between($page, &#8216;Current Town:  &#8216;, &#8216;&lt;br /&gt;&#8217;);<br />
echo &#8220;Current Town: &#8220;.$current_town.&#8221;&lt;br /&gt;&#8221;;</strong></p>
<p><strong>//Home Town<br />
$home_town = get_string_between($page, &#8216;Hometown:  &#8216;, &#8216;&lt;br /&gt;&#8217;);<br />
echo &#8220;Home Town: &#8220;.$home_town.&#8221;&lt;br /&gt;&#8221;;</strong></p>
<p><strong>//Birthday<br />
$birthday = get_string_between($page, &#8216;Birthday:  &#8216;, &#8216;&lt;br /&gt;&#8217;);<br />
echo &#8220;Birthday: &#8220;.$birthday.&#8221;&lt;br /&gt;&#8221;;</strong></p>
<p><strong>//Work Info<br />
$work_info = get_string_between($page, &#8216;Company:  &#8216;, &#8216;&lt;br /&gt;&#8217;);<br />
echo &#8220;Work Info: &#8220;.$work_info.&#8221;&lt;br /&gt;&#8221;;</strong></p>
<p><strong>//Position<br />
$position = get_string_between($page, &#8216;Position:  &#8216;, &#8216;&lt;br /&gt;&#8217;);<br />
echo &#8220;Position: &#8220;.$position.&#8221;&lt;br /&gt;&#8221;;</strong></p>
<p><strong>storeProfileData($first_name, $last_name, $website, $aim, $yahoo, $windows_live, $skype, $tel, $current_address, $current_town, $home_town, $birthday, $work_info, $position);</strong></p>
<p><strong>echo &#8220;&lt;hr&gt;&#8221;;<br />
}//end pageflips<br />
?&gt;</strong></p>
<p>Ojo con Facebook!<br />
Tengan cuidado, hay que tener en cuenta que cuando llaman este script, lo hacen desde su propia cuenta de FaceBook. Si hacen algo muy dañino (como, golpear los servidores con miles de hits de una sentada), los pueden rastrear! Ya hay mas de un caso donde <a href="http://nexdot.net/blog" target="_blank">Facebook tumba scripts de usuarios propagando otros &#8220;facebook downloaders</a>.</p>
<p>Acá de paso dejo los archivos fuente que use, ojo a los comentarios; ahí les incluyo el paso 3, que es un script extra para extraer la informacion de la base de datos a vcards (que lee outlook). Otra sugerencia? Busquense algun <a href="http://www.facebook.com/applications/Fonebook/2442338999" target="_blank">app de facebook que coordine las fotos de los contactos online con las offline</a>. Y estamos!</p>
<p><a href="http://mauriciopastrana.com/wp-content/uploads/2008/01/contacts.png" rel="lightbox[84]" title="contacts"></a></p>
<p style="text-align: center"><a href="http://mauriciopastrana.com/wp-content/uploads/2008/01/contacts.png" rel="lightbox[84]" title="contacts"><img src="http://mauriciopastrana.com/wp-content/uploads/2008/01/contacts.png" alt="contacts" border="0" height="340" hspace="5" vspace="5" width="426" /></a></p>
<p style="text-align: center"><a href="http://mauriciopastrana.com/wp-content/uploads/2008/01/contacts.png" rel="lightbox[84]" title="contacts"> </a><a href="http://mauriciopastrana.com/wp-content/uploads/2008/01/contactnum.png" rel="lightbox[84]" title="contact number"><img src="http://mauriciopastrana.com/wp-content/uploads/2008/01/contactnum.png" alt="contact number" border="0" /></a></p>
<p>Tiempo total de desarrollo: 20 horas-hombre. Wow! Que lastima no poder hacer un servicio web fuera de este.</p>
<p><a href="http://mauriciopastrana.com/wp-content/uploads/2008/01/facebook-downloader.zip" target="_blank"><em>Aca puedes descargar los archivos fuente que incluyen los tres scripts y la conexion a la base de datos.</em></a></p>
]]></content:encoded>
			<wfw:commentRss>http://mauriciopastrana.com/gente/guia-descarga-tus-contactos-de-facebook-a-outlook/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>Se vende, Audi A3</title>
		<link>http://mauriciopastrana.com/sydney/se-vende-audi-a3/</link>
		<comments>http://mauriciopastrana.com/sydney/se-vende-audi-a3/#comments</comments>
		<pubDate>Mon, 17 Dec 2007 11:05:29 +0000</pubDate>
		<dc:creator>Mauricio Pastrana</dc:creator>
				<category><![CDATA[Gadgets y Tecnologia]]></category>
		<category><![CDATA[Sydney]]></category>
		<category><![CDATA[audi]]></category>
		<category><![CDATA[venta]]></category>

		<guid isPermaLink="false">http://mauriciopastrana.com/sydney/muere-una-leyenda-y-hombre-como-ando-de-vago/</guid>
		<description><![CDATA[Se acuerdan de cuando compre el Audi recien llegado? (no? ok aca el post). Este para mi es el paso crucial de toda &#8220;despedida de país&#8221; (ya mi tercera!), vender mis wheels&#8230; No solo quiere decir que entro a la rutina de bus y metro (bueno hombre, como todos en sydney, no joda), sino que [...]]]></description>
			<content:encoded><![CDATA[<p>Se acuerdan de cuando compre el Audi recien llegado? (no? ok <a href="http://mauriciopastrana.com/gadgets-y-tecnologia/wheels-audi-a3/">aca el post</a>).</p>
<p>Este para mi es el paso crucial de toda &#8220;despedida de país&#8221; (ya mi tercera!), vender mis <em>wheels</em>&#8230; No solo quiere decir que entro a la rutina de bus y metro (bueno hombre, como todos en sydney, no joda), sino que ya ahora, que vendi mis muebles, y entregue mis bienes pesados a Mexico&#8230; no tengo pertenencia alguna! (el laptop?).</p>
<p>De paso, este paseo por mi nostalgia me llevo a buscar la venta anterior en Miami, que demuestra como ando de low-standards en Sydney, mientras acá arme un <a href="http://www.drive.com.au/used-cars/AUDI/A3/Sydney/detail.aspx?id=3962634&amp;pg=1&amp;pp=4&amp;d=0&amp;nv=1&amp;SG=1350945126&amp;pt=1" target="_blank">ad con tres o cuatro datos descriptivos</a>, en Miami arme una <a href="http://cgi.ebay.com/ebaymotors/ws/eBayISAPI.dll?ViewItem&amp;item=4636208491" target="_blank">pagina en eBay sobre XHTML y CSS</a>, detalles a fondo de todos los &#8220;action items&#8221; del carro (que, de paso, los tenia escritos en una hoja que llevaba conmigo en el carro) y: <strong>64 fotos con rollover</strong>! wow.  (claro esta que gracias a que en australia hasta ahora oyen de <em>esa cosa</em> del eBay, igual no hay &#8220;sistema&#8221; en el cual sacar a relucir todo el tiempo libre del que dispongo, ah?)</p>
<p>Asi que&#8230; si hay alguien en Sydney, que le interese un bello A3 del 97, bajo en kilometros con menos de 61,000, barato y de uso estudiantil -si, estudiantil, solo que de la clase de estudiantes responsables, creo&#8230; Ya saben.</p>
<p><a href="http://mauriciopastrana.com/wp-content/uploads/2007/12/audi-sales.png" rel="lightbox[77]" title="audi"></a></p>
<p style="text-align: center"><a href="http://www.drive.com.au/used-cars/AUDI/A3/Sydney/detail.aspx?id=3962634&amp;pg=1&amp;pp=4&amp;d=0&amp;nv=1&amp;SG=1350945126&amp;pt=1" target="_blank"><img src="http://mauriciopastrana.com/wp-content/uploads/2007/12/audi-sales.png" alt="audi" border="0" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://mauriciopastrana.com/sydney/se-vende-audi-a3/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Top-5: Errores &#8220;tontos&#8221; de desarrollo</title>
		<link>http://mauriciopastrana.com/gadgets-y-tecnologia/top-5-errores-tontos-de-desarrollo/</link>
		<comments>http://mauriciopastrana.com/gadgets-y-tecnologia/top-5-errores-tontos-de-desarrollo/#comments</comments>
		<pubDate>Thu, 13 Dec 2007 01:15:49 +0000</pubDate>
		<dc:creator>Mauricio Pastrana</dc:creator>
				<category><![CDATA[Gadgets y Tecnologia]]></category>
		<category><![CDATA[Listas]]></category>

		<guid isPermaLink="false">http://mauriciopastrana.com/gadgets-y-tecnologia/top-5-errores-tontos-de-desarrollo/</guid>
		<description><![CDATA[Jah! Ya mismo arranco a hablar como si fuera todo un profesional! De todos modos, esta es una que le tenia ganas de escribir hace bastante tiempo, sobretodo desde que me eche mi primera pasada por la versión 1999 de esta lista (escrita por Jakob Nielsen). Algunos son problemas de diseño y usabilidad, otros son [...]]]></description>
			<content:encoded><![CDATA[<p align="justify">Jah! Ya mismo arranco a hablar como si fuera todo un profesional!</p>
<p align="justify">De todos modos, esta es una que le tenia ganas de escribir hace bastante tiempo, sobretodo desde que me eche mi primera pasada por la <a href="http://www.useit.com/alertbox/990530.html" target="_blank">versión 1999 de esta lista</a> (escrita por Jakob Nielsen). Algunos son problemas de diseño y usabilidad, otros son mas como de infraestructura y logica. Ni me quiero acercar a proponer soluciones, pero de lejos este es el top-5 de lo que mas me gusta quejarme (van en reversa, estilo letterman).</p>
<p align="justify">&nbsp;</p>
<p style="text-align: center"><img src="http://web.mit.edu/is/usability/IAP/2003/Session1/Images/reboot.gif" border="0" height="210" width="557" /></p>
<p align="justify">Hay de todo, la lista despues del salto&#8230;</p>
<p><span id="more-69"></span></p>
<h3 align="justify">5. Complicando el nombre de dominio</h3>
<p align="justify">&nbsp;</p>
<p align="justify">(o peor, <em>metiendo las patas</em> con el nombre)</p>
<p align="justify">&nbsp;</p>
<p align="justify"><a href="http://www.iana.org/domain-names.htm" target="_blank">IANA</a> es la autoridad encargada de la numeracion y distribucion de &#8220;apellidos&#8221; (<em>top-level-domains</em>, los &#8220;.com&#8221;, &#8220;.net&#8221;, &#8220;.us&#8221;) en el internet, la opera <a href="http://www.icann.org" target="_blank">ICANN</a> (Internet Corporation for Assigned Names and Numbers). Esta parte los <em>tld</em>s en tres categorias: <a href="http://www.iana.org/cctld/">Paises</a> (.uk, .de, .jp, .us, etc.), <a href="http://www.iana.org/gtld/gtld.htm">Dominios Genericos </a>(.aero, .asia, .biz, .cat, .com, .coop, .edu, .gov, .info, .jobs, .mobi, .int, .mil, .museum, .name, .net, .org, .pro, .tel and .travel) e <a href="http://www.iana.org/arpa-dom/">Infraestructura</a> (.arpa). De hecho, hay mas de <a href="http://en.wikipedia.org/wiki/List_of_Internet_top-level_domains" target="_blank">50 variaciones en tld&#8217;s</a>.</p>
<p align="justify">&nbsp;</p>
<p align="justify">Y aun asi, constantemente me encuentro con desarrolladores que rompen esta convencion. Claro; no existe usuario Internet en el planeta que no asuma que el nombre &#8220;.com&#8221; es el primario y de ahí <em>para abajo</em>, pero aun asi (ademas de que complican el estandar por el uso de dominios canonicos -el <em>algo  </em>en http://algo.dominio.com). Como es esto? ejemplo claro esta en el website del ISG, el International Sales Group en Miami quien en ves de buscarse internationalsalesgroup.us, isg.us (o variantes para ajustar disponibilidad), prefieren confundir al usuario con intlsalesgroup.us.com &#8230;  como? .us.com ? es algo asi como .co.uk solo que al reves? ahora que tenemos un tld para los estados unidos .us, se vuelve mas peluda la cosa.</p>
<p align="justify">&nbsp;</p>
<p align="justify">Asi mismo, tambien hay casos famosos de errores de transcripcion, como cartunes.com (siendo cartoons.com), penisland.com (pen &#8211; island) o expertsexchange.com (experts &#8211; exchange). Ultimamente tambien se ve una cantidad de juego con el termino .us (del.icio.us) o (amarill.us) &#8230; no se. Dudo que los <em><a href="http://en.wikipedia.org/wiki/Baby_boomer" target="_blank">boomers</a> </em>la cachen así de fácil.</p>
<p align="justify">&nbsp;</p>
<h3 align="justify">4. Desarrollar para tan solo una plataforma</h3>
<p align="justify">&nbsp;</p>
<p align="justify">Que? esto es el 2007! la web2, linux! &#8230; esto es cosa del pasado! (y de hecho, si; este error aparece en la lista de errores de Nielsen en 1996). Y aun asi; me topo con que &#8230; sigue sucediendo!</p>
<p align="justify">&nbsp;</p>
<p align="justify">El internet es una jungla. Tan solo yo en mi dia a dia navego desde Firefox OS X, windows sobre IE7 y también desde Safari en mi iPhone para hacer hasta las tareas mas meniales. A esto hay que sumarle que hay Linx en texto plano (y lectores para usuarios deshabilitados), Blazer (en las treo y palm), Opera&#8230; el Browser de Symbian, Explorer en Windows Mobile y los enemil clones de Firefox (Flock?)&#8230; para muchos de los cuales; en especial, no hay flash player! &#8230; y hasta el sol de hoy, todavia me sigo topando con sitios hechos en su totalidad para trabajar <a href="http://imaginamos.com/" target="_blank">sobre</a> <a href="http://swonn.net/" target="_blank">flash</a>.</p>
<p align="justify">&nbsp;</p>
<p align="justify">Pero no es todo, los hay de todos los sabores (sobretodo en latinoamerica), sitios que <a href="http://www.avianca.com">solo corren sobre IE</a>, o que <a href="http://www.banamex.com" target="_blank">requieren de un plugin especial solo para windows</a>. Cual es el problema? dices&#8230; bueno; ventas perdidas, usuarios frustrados, pero mas peligrosamente; el correr código que solo ejecuta en un servidor puede ser una vulnerabilidad de seguridad bajo otro cliente. Este problema me saca de quicio porque <a href="http://www.webstandards.org/" target="_blank">hace mas de 4 años que se soluciono en el &#8220;mundo desarrollado&#8221;</a> (y hoy en día el esfuerzo es en <a href="http://www.email-standards.org/">replicar el efecto sobre clientes web</a>).</p>
<p align="justify">&nbsp;</p>
<h3 align="justify">3. Andar con la ciber-bragueta abajo</h3>
<p align="justify">&nbsp;</p>
<p align="justify">Mis estadisticas son privadas. Si; hay muchos sitios donde busco pautar y &#8230; asi mismo hay sitios que tengo solo para uso privado&#8230; Pero no creo que valga la pena andar mostrando cuanta gente entra a mi sitio, de donde y porque. Pero aun asi, cada rato me topo con gente que arma sitios, y en ves de contratar servicios inteligentes de rastreo de uso (como <a href="http://www.google.com/analytics" target="_blank">google analytics</a>), dejan un link -al abierto- hacia su stats counter (<a href="http://www.sitemeter.com/?a=stats&amp;s=s37jezebel" target="_blank">hasta los grandes</a>!). Es mas, cuando sucede por lo general se trae una bella imagen que te invita a hacer el click y &#8220;sapear&#8221;. Es que acaso estan haciendo parte de un concurso de alguna clase? Bueno&#8230;</p>
<p align="justify">&nbsp;</p>
<p align="justify">Para mi, este error esta a la altura de dejar <a href="http://www.techcrunch.com/2006/08/06/aol-proudly-releases-massive-amounts-of-user-search-data/" target="_blank">información de la compañía al aire</a> o, <a href="http://www.eweek.com/article2/0,1759,1751689,00.asp" target="_blank">perder claves de acceso</a>, etc.</p>
<p align="justify">&nbsp;</p>
<h3 align="justify">2. Hacer uso de mensajes 404</h3>
<p align="justify">&nbsp;</p>
<p align="justify">Esta bien, este&#8230; esta abierto a debate. Las <a href="http://en.wikipedia.org/wiki/404_error" target="_blank">paginas 404</a> son las que el servidor muestra en caso que le hagas un pedido a una pagina que no existe. En su gran mayoría, estas se quedan con <a href="http://www.elated.com/res/Image/articles/management/apache/making-a-custom-error-page/apache_404_default.gif" rel="lightbox[69]" target="_blank">su templete original</a>.</p>
<p align="justify">&nbsp;</p>
<p align="justify">Así mismo hay una gran escuela de diseñadores que les encanta meterle mano al 404 y <a href="http://www.ibm.com/what?" target="_blank">hacerlo de una herramienta de usabilidad</a>  -tratar de adivinar que queria el usuario, sugerir opciones, proponer acciones o &#8230; tan solo <em>pedir disculpas</em> por no ubicar la pagina. Esta bien; pero hay una opcion mejor, hace rato, en mi trabajo anterior, mi jefe me ilumino hacia el uso correcto de una direccion inventada o erronea &#8230; redirect! &#8230; la lógica es así, si tu llegas a una pagina que no sirve (o que ya no existe), en ves de varar tu experiencia; el 404 te debería de reenviar al home! es mas, bien hecho, quizás te podría mostrar un error en un lightbox con la disculpa (lo unico que me quedo de los 404 bien hechos), pero ahí me detengo. Así previenes gente adivinando direcciones y varados en su uso tan solo mientras descifran que es el 404.</p>
<p align="justify">&nbsp;</p>
<p align="justify">En ultimas, mi pregunta es: para que <a href="http://en.wikipedia.org/wiki/Red_Screen_of_Death" target="_blank">diseñar una pagina que nadie se supone va a ver</a>?</p>
<p align="justify">&nbsp;</p>
<h3 align="justify">1. Usar direcciones complejas</h3>
<p align="justify">(pageID, query=?, phpusersessid que no usen mod_rewrite)</p>
<p align="justify">&nbsp;</p>
<p align="justify">mod_re&#8230; que?</p>
<p align="justify">&nbsp;</p>
<p align="justify">mod_rewrite es un componente del servidor web apache que permite todo tipo de genialidades cuando viene la hora de guardar direcciones en el address bar. A esto me refiero, que en ves de tener sitios misitio.com/index.php?get_page=12312&amp;user=mauricio, tienes misitio.com/mauricio/personal-page.</p>
<p align="justify">&nbsp;</p>
<p align="justify">Nosotros no somos maquinas! cada rato me encuentro que las direcciones se vuelven mas y mas y mas largas. No es acaso el autofill uno de los modos mas frecuentes de busqueda de direcciones? (imaginate esta, quieres ir a ebay.com y estas buscando entre los previos&#8230; pero todos son una coleccion de letras y numeros que parecen como si hubieses dejado al gato caminar encima del teclado). En ultimas, <a href="http://www.ilovejackdaniels.com/cheat-sheets/mod_rewrite-cheat-sheet/" target="_blank">mod_rewrite es bien simple de implementar</a>.</p>
<p align="justify">&nbsp;</p>
<p align="justify">De hecho, la existencia de estos mega-direcciones ha llevado a la creación de sitios que <a href="http://www.tinyurl.com" target="_blank">agarran la dirección y la vuelven corta</a> para poder enviar a tus amigos y conocidos.</p>
<p align="justify">&nbsp;</p>
<p align="justify">&#8230;</p>
<p align="justify">&nbsp;</p>
<p align="justify">En ultimas, el #1 se remonta al error #5 (pero es de naturaleza diferente). Que lastima que no funciono muy bien el sistema de keywords de AOL aunque, tan solo hay tantas palabras, no? por lo menos no estamos escribiendo IPs directas al address bar (que te aprenderías los websites como teléfonos?).</p>
<p align="justify">Y obvio, fijo alguien encuentra uno de estos en mis propios sitio, ah? (como el 404?) &#8230; bueno, pero en el publico; ahi vamos, no? por lo menos ya nos deshicimos del &lt;blink&gt; &#8230; <a href="http://www.google.com/codesearch?q=%3Cblink%3E&amp;hl=en&amp;btnG=Search+Code" target="_blank">creo</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://mauriciopastrana.com/gadgets-y-tecnologia/top-5-errores-tontos-de-desarrollo/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Guia: Descargas usando torrents</title>
		<link>http://mauriciopastrana.com/gadgets-y-tecnologia/guia-descargas-usando-torrents/</link>
		<comments>http://mauriciopastrana.com/gadgets-y-tecnologia/guia-descargas-usando-torrents/#comments</comments>
		<pubDate>Mon, 03 Dec 2007 01:38:10 +0000</pubDate>
		<dc:creator>Mauricio Pastrana</dc:creator>
				<category><![CDATA[Gadgets y Tecnologia]]></category>
		<category><![CDATA[descargas]]></category>
		<category><![CDATA[guia]]></category>
		<category><![CDATA[torrents]]></category>

		<guid isPermaLink="false">http://mauriciopastrana.com/gadgets-y-tecnologia/guia-descargas-usando-torrents/</guid>
		<description><![CDATA[&#160; Esto me sucede cada tantas semanas: &#8220;Oye, que ya viste la nueva temporada de Desperate Housewives?, Pero si acá [en Australia] todavía ni la venden&#8221; a lo cual yo respondo, &#8220;Ahh tranquilo, ya te mando el .torrent para que las descargues&#8221;, y de seguro; a la semana o dos: &#8220;Oye, que ese archivo que [...]]]></description>
			<content:encoded><![CDATA[<p align="right">&nbsp;</p>
<p align="justify"><a href="http://mauriciopastrana.com/wp-content/uploads/2007/12/transmission.png" rel="lightbox[46]" title="transmission dock icon"><img src="http://mauriciopastrana.com/wp-content/uploads/2007/12/transmission.png" alt="transmission dock icon" align="left" border="0" height="120" hspace="5" vspace="5" width="120" /></a>Esto me sucede cada tantas semanas: &#8220;Oye, que ya viste la nueva temporada de Desperate Housewives?, Pero si acá [en Australia] todavía ni la venden&#8221; a lo cual yo respondo, &#8220;Ahh tranquilo, ya te mando el .torrent para que las descargues&#8221;, y de seguro; a la semana o dos: &#8220;Oye, que ese archivo que me mandaste no funciona, ni siquiera winzip lo puede abrir para ver las series&#8221;. No. <em>Así</em> no es.</p>
<p align="justify">De hecho, hacer descargas con torrents es super-facil! como? bueno, primero unas básicas.</p>
<p><span id="more-46"></span></p>
<h3>Que es un torrent?</h3>
<p>Hace mas de un buen rato, cuando <a href="http://www.dcita.gov.au/__data/assets/image/57683/home_internet_users_graph.gif" rel="lightbox[46]" target="_blank">la gran mayoria de usuarios usaban el internet sobre discado</a> (dial-up), el modo estándar de compartir archivos era el tan afamado <a href="http://" target="_blank">p2p</a> (peer-to-peer, vuelto grande por <a href="http://www.napster.com/" target="_blank">Napster</a>, <a href="http://www.google.com.au/url?q=http://www.kazaa.com/us/help/index.htm&amp;sa=X&amp;oi=smap&amp;resnum=1&amp;ct=result&amp;cd=2&amp;usg=AFQjCNEMosG2IgtHt_JNZvvWTBpYQzHkOQ" target="_blank">KaZaa</a> y las versiones originales de <a href="http://www.google.com.au/url?q=http://www.limewire.com/features/&amp;sa=X&amp;oi=smap&amp;resnum=1&amp;ct=result&amp;cd=3&amp;usg=AFQjCNEbRp3GbvmmlywEjzqLd59HAACHnQ" target="_blank">Limewire</a> por mencionar los mas famosos). Bajo p2p,  solo aquellos quienes disponían de conexiones rápidas y permanentes (cable/dsl/t1) podrían darse el lujo de dejar una conexión abierta a los archivos que compartían. Nosotros, mas via destapada que <a href="http://en.wikipedia.org/wiki/Information_superhighway" target="_blank">internet superhighway</a>, tendríamos que vivir pendientes de estos &#8220;superusuarios&#8221; y en su mayoría, tan solo la pasábamos descargando ya que compartir archivos para cargar se podría <a href="http://en.wikipedia.org/wiki/Modem#Increasing_speeds_.28V.21_V.22_V.22bis.29" target="_blank">comer el ancho de banda</a> bien rapidito. Bien por nosotros, pero mal por la economía compartida de todo el asunto gracias a la demanda masiva y oferta limitada que generaba esta practica. Acá es donde entra en juego el Torrent.</p>
<p><a href="http://en.wikipedia.org/wiki/BitTorrent" target="_blank">BitTorrent</a>, el protocolo hijo de <a href="http://bitconjurer.org/" target="_blank">Bram Cohen</a> que ataco este problema, funciona del siguiente modo, en efecto, este parte todo archivo compartido en <em>bloques</em> (casi siempre de 1mb, creo), y trafica en bloques, no en archivos, con la idea que al final se reconstituya el archivo original (y la guía de que bloques arman cual rompecabezas? el archivo .torrent del que hablaba ahí arriba). Para este, ya no depende uno de un superusuario que ande compartiendo películas a 700mb, sino mas fácil encontrar ~40 que cada uno entregue un pedazo aleatorio y al final armen el mismo entero.<br />
Bajo la cultura torrent, se mira uno en quien esta compartiendo y quien esta solo descargando, aunque esto no nos molesta; importa saber si hay usuarios &#8220;<a href="http://answers.yahoo.com/question/index?qid=20070613224743AA5GEky" target="_blank">seeders</a>&#8221; quienes estan en esencia compartiendo el archivo completo. -Esto importa! en su minucia, un archivo esta en potencia en existir compartido al 80%, pero si no hay seeder, no hay modo de descargar el archivo entero (si me entiendo? veamos este escenario: digamos que hay 4 usuarios, y todos descargaron hasta 80% del archivo original de un seeder quien después se puso offline, pues ahora todos estamos jugando al trueque, y nadie tiene el completo!).</p>
<p>Trivial? parece, pero hay que considerar que en el 2005, hasta el 52% del trafico en el internet se comprometía de BitTorrent (que incluyen la arquitectura detrás de <a href="http://blogs.nmss.com/communications/2007/04/realworld_p2p_j.html" target="_blank">Skype y Joost</a> por ejemplo). Hoy en día, aunque la RIAA y MPAA miren la practica de para abajo, igual es el modo mas rápido y eficiente de adquirir medios, aun cuando <a href="http://www.apple.com/itunes/store/" target="_blank">existen opciones</a>! (aunque, siendo honestos, gracias a la practica común de <a href="http://dynamic.abc.go.com/" target="_blank">limitar servicio</a> a <a href="http://www.netflix.com/MediaCenter?id=5384">ciertas zonas geograficas</a>, se encuentra uno descargando antes que mercando de seguro).</p>
<p>De paso, acá una <a href="http://geocities.com/siddharth_dawara/torrent/howtotorrent#jargon" target="_blank">guia cortita de los términos mas importantes</a>.</p>
<h3>Como descargar archivos usando torrents, un ejemplo.</h3>
<p>Para usar torrents se necesitan tres cosas:</p>
<ul>
<li>un cliente de descargas (alias, el programa para descargar, lo que antes era KaZaa o Limewire).</li>
<li>un motor de búsquedas de torrents (ya que los programas de descargas por lo general se desentienden de este).</li>
<li>una idea de que es lo que se quiere obtener.</li>
</ul>
<p>Porque incluyo el tercero? gracias a su naturaleza y eficacia, es muy común ver torrents de 20gb con titulos como: &#8220;<a href="http://www.mininova.org/tor/926111" target="_blank">nip/tuck, all seasons</a>&#8220;. Asi mismo, encuentras colecciones enteras de autores de libros, peliculas, sistemas operativos y demás. Es simplemente muy difícil encontrar algo &#8220;rapido&#8221; y puntual en caso que uno este solamente: <em>browsing</em>.</p>
<p>Voy a hacer el ejemplo de arrancar la descarga de una serie al azar de tele, como para mostrar como lo hago con <a href="http://www.tuaw.com/2007/10/08/found-footage-apple-tv-composite-hack-in-full-color/" target="_blank">mi apple tv.</a></p>
<h4>El cliente de descargas</h4>
<p>Esta guía la estoy escribiendo desde mi mac, asi que me perdonan si no me llevo los screenshots para windows. De todos modos, la naturaleza del uso es la misma.</p>
<p>Para descargar, yo hago uso de uno de dos programas, sobre OS X, <a href="http://transmission.m0k.org/" target="_blank">Transmission</a>. Sobre Windows, <a href="http://www.utorrent.com/download.php" target="_blank">uTorrent</a>. Ambos son clientes-clon del <a href="http://www.bittorrent.com/download">cliente original</a>, pero en mi opinion (y sobre las versiones disponibles hoy), ambas son mas completas y mas simples de usar.</p>
<h4>El motor de busqueda</h4>
<p>Este es el lugar donde se siente la mejora sobre los programas de descargas viejos. Por lo general, los motores de busqueda son websites que, gracias a su generosidad y afinidad por el riesgo, comparten la ubicacion de los archivos compartidos (y sus respectivos &#8220;trackers&#8221;, pero esto no esta siendo discutido aca). Entre los mas famosos (del momento):</p>
<ul>
<li><a href="http://www.mininova.org" target="_blank">Mininova</a></li>
<li><a href="http://www.thepiratebay.org">The Pirate Bay</a></li>
<li><a href="http://isohunt.com/" target="_blank">ISOHunt</a></li>
<li><a href="http://inferno.demonoid.com:3394/" target="_blank">Demonoid</a></li>
</ul>
<p>Asi que, para mi cortito &#8220;demo&#8221;, voy a hacer el ejercicio de descargar un episodio de nip/tuck bajo mininova.</p>
<p>primero lo primero, mininova.org</p>
<p><a href="http://mauriciopastrana.com/wp-content/uploads/2007/12/picture-3.png" rel="lightbox[46]" title="torrents screenshot 1"></a></p>
<p style="text-align: center"><a href="http://mauriciopastrana.com/wp-content/uploads/2007/12/picture-3.png" rel="lightbox[46]" title="torrents screenshot 1"><img src="http://mauriciopastrana.com/wp-content/uploads/2007/12/picture-3.png" alt="torrents screenshot 1" border="0" /></a></p>
<p>y aunque este a su entrada tiene una lista de los torrents mas populares, igual vamos a usar la barra de busqueda.</p>
<p><a href="http://mauriciopastrana.com/wp-content/uploads/2007/12/picture-4.png" rel="lightbox[46]" title="mininova search box"></a></p>
<p style="text-align: center"><a href="http://mauriciopastrana.com/wp-content/uploads/2007/12/picture-4.png" rel="lightbox[46]" title="mininova search box"><img src="http://mauriciopastrana.com/wp-content/uploads/2007/12/picture-4.png" alt="mininova search box" border="0" height="41" width="453" /></a></p>
<p>que genera este set de resultados (notese que esta organizado por cantidad de seeders, mientras mas, mejor):</p>
<p><a href="http://mauriciopastrana.com/wp-content/uploads/2007/12/picture-5.png" rel="lightbox[46]" title="niptuck resultados"></a></p>
<p style="text-align: center"><a href="http://mauriciopastrana.com/wp-content/uploads/2007/12/picture-5.png" rel="lightbox[46]" title="niptuck resultados"><img src="http://mauriciopastrana.com/wp-content/uploads/2007/12/picture-5.png" alt="niptuck resultados" border="0" height="224" width="511" /></a></p>
<p>&#8230; y mas importantemente, ojo a los iconitos azules en el centro (al lado de &#8220;Size&#8221;), que tienen la cantidad de comentarios por torrent, estos sirven para saber si el archivo en cuestión esta bueno o malo en calidad, o si este es un virus, etc. los comentarios por lo general se ven asi:</p>
<p><a href="http://mauriciopastrana.com/wp-content/uploads/2007/12/picture-6.png" rel="lightbox[46]" title="comentarios niptuck"></a></p>
<p style="text-align: center"><a href="http://mauriciopastrana.com/wp-content/uploads/2007/12/picture-6.png" rel="lightbox[46]" title="comentarios niptuck"><img src="http://mauriciopastrana.com/wp-content/uploads/2007/12/picture-6.png" alt="comentarios niptuck" border="0" height="305" width="569" /></a></p>
<p>volviendo a la lista de resultados, un click en la flecha verde al lado del nombre y listo! descargamos el archivo .torrent</p>
<p><a href="http://mauriciopastrana.com/wp-content/uploads/2007/12/picture-7.png" rel="lightbox[46]" title="torrent download"></a></p>
<p style="text-align: center"><a href="http://mauriciopastrana.com/wp-content/uploads/2007/12/picture-7.png" rel="lightbox[46]" title="torrent download"><img src="http://mauriciopastrana.com/wp-content/uploads/2007/12/picture-7.png" alt="torrent download" border="0" /></a></p>
<p>a su ves, este archivo lo abrimos con nuestro cliente ahora para iniciar la descarga</p>
<p><a href="http://mauriciopastrana.com/wp-content/uploads/2007/12/picture-8.png" rel="lightbox[46]" title="transmission 1"></a></p>
<p style="text-align: center"><a href="http://mauriciopastrana.com/wp-content/uploads/2007/12/picture-8.png" rel="lightbox[46]" title="transmission 1"><img src="http://mauriciopastrana.com/wp-content/uploads/2007/12/picture-8.png" alt="transmission 1" border="0" /></a></p>
<p>y este solito arranca su descarga!</p>
<p><a href="http://mauriciopastrana.com/wp-content/uploads/2007/12/picture-9.png" rel="lightbox[46]" title="transmission 2"></a></p>
<p style="text-align: center"><a href="http://mauriciopastrana.com/wp-content/uploads/2007/12/picture-9.png" rel="lightbox[46]" title="transmission 2"><img src="http://mauriciopastrana.com/wp-content/uploads/2007/12/picture-9.png" alt="transmission 2" border="0" /></a></p>
<p>phew!  por igual, entre amigos si encuentras un torrent util que descargue un archivo que quieras compartir, en ves de andar enviando 600gb de esa ultima peli que viste y quieres compartir, tan solo tienes que poner el archivo .torrent en un email; que este despues se le puede usar para descargar la temporada, serie de canciones, etc.</p>
<p>Notese que es normal que el cliente se vuelva seeder una vez tengas todo el archivo en tu disco duro, si tienes problemas de ancho de banda, recomiendo irlos sacando de la lista, pero técnicamente es mejor para todos no hacerlo.</p>
<h3>Concluye</h3>
<p>De todos modos, que quede dicho que, en su mejor practica, uno deberia de <strong>comprar</strong> antes que descargar (sin mencionar que la gran mayoria de descargas de seguro es ilegal y te puede meter en problemas).</p>
]]></content:encoded>
			<wfw:commentRss>http://mauriciopastrana.com/gadgets-y-tecnologia/guia-descargas-usando-torrents/feed/</wfw:commentRss>
		<slash:comments>19</slash:comments>
		</item>
		<item>
		<title>Olympus IR</title>
		<link>http://mauriciopastrana.com/gadgets-y-tecnologia/olympus-ir/</link>
		<comments>http://mauriciopastrana.com/gadgets-y-tecnologia/olympus-ir/#comments</comments>
		<pubDate>Mon, 16 Oct 2006 05:39:34 +0000</pubDate>
		<dc:creator>Mauricio Pastrana</dc:creator>
				<category><![CDATA[Gadgets y Tecnologia]]></category>

		<guid isPermaLink="false">http://mauriciopastrana.com/uncategorized/olympus-ir/</guid>
		<description><![CDATA[Que se hace con una camara que no enfoca bien? Bueno, tras arreglar la camara de Paola Suarez que &#8220;aparecio&#8221; llena de arena y no abria el lente bien, me inspire a hacer algo con mi camara digital vieja cuyo lente no enfocaba muy bien por eso de su uso y desgaste (para aquellos que [...]]]></description>
			<content:encoded><![CDATA[<p>Que se hace con una camara que no enfoca bien?</p>
<p>Bueno, tras arreglar la camara de <a href="http://www.landnull.com/2006/10/16/colombianos-en-sydney/">Paola Suarez</a> que &#8220;aparecio&#8221; llena de arena y no abria el lente bien, me inspire a hacer algo con mi camara digital vieja cuyo lente no enfocaba muy bien por eso de su uso y desgaste (para aquellos que conocen esta Olympus&#8230; estoy hablando de &#8220;la papita&#8221;).</p>
<p>Basicamente el proyecto fue abrir la camara para quitar el filtro infrarojo, y con algo que me quedo de mis clases de fisica, reemplace el filtro con un pedazo de rollo velado (que filtra la luz visible, actua como proteccion y permite pasar la luz infraroja).</p>
<p>Resultado? una camara que puede ver en la noche sin iluminar! (sisi, yo se, como la de <a href="http://www.trustedreviews.com/article.aspx?art=1754">paris hilton</a>)</p>
<p>ahi van fotos:</p>
<p><img src="http://www.mauriciopastrana.com/wp-content/uploads/2006/image_box/2006_1016_ircamera/DSC00472.jpg" alt=" " /><br />
<img src="http://www.mauriciopastrana.com/wp-content/uploads/2006/image_box/2006_1016_ircamera/DSC00473.jpg" alt=" " /><br />
Este&#8230; el filtro infrarojo, aca no se ve muy claro pero es un filtro polar asi que si se ve de angulo refleja color verde o rojo<br />
<img src="http://www.mauriciopastrana.com/wp-content/uploads/2006/image_box/2006_1016_ircamera/DSC00475.jpg" alt=" " /><br />
Y aca como quedo despues, notese el pedazo de cinta pegante para sostener el rollo velado<br />
<img src="http://www.mauriciopastrana.com/wp-content/uploads/2006/image_box/2006_1016_ircamera/DSC00474.jpg" alt=" " /><br />
<img src="http://www.mauriciopastrana.com/wp-content/uploads/2006/image_box/2006_1016_ircamera/DSC00476.jpg" alt=" " /></p>
<p>visible<br />
<img src="http://www.mauriciopastrana.com/wp-content/uploads/2006/image_box/2006_1016_ircamera/DSC00477.jpg" alt=" " /><br />
infrarojo<br />
<img src="http://www.mauriciopastrana.com/wp-content/uploads/2006/image_box/2006_1016_ircamera/P1010005.jpg" alt=" " /></p>
<p>visible<br />
<img src="http://www.mauriciopastrana.com/wp-content/uploads/2006/image_box/2006_1016_ircamera/DSC00478.jpg" alt=" " /><br />
infrarojo<br />
<img src="http://www.mauriciopastrana.com/wp-content/uploads/2006/image_box/2006_1016_ircamera/P1010004.jpg" alt=" " /></p>
<p>visible<br />
<img src="http://www.mauriciopastrana.com/wp-content/uploads/2006/image_box/2006_1016_ircamera/DSC00479.jpg" alt=" " /><br />
infrarojo<br />
<img src="http://www.mauriciopastrana.com/wp-content/uploads/2006/image_box/2006_1016_ircamera/P1010003.jpg" alt=" " /></p>
<p>como pueden ver, el filtro no es perfecto y todavia agarra un poco de rojo visible<br />
<img src="http://www.mauriciopastrana.com/wp-content/uploads/2006/image_box/2006_1016_ircamera/P1010006.jpg" alt=" " /></p>
<p>y esta, hasta la fecha mi mejor foto de frente<br />
<img src="http://www.mauriciopastrana.com/wp-content/uploads/2006/image_box/2006_1016_ircamera/P1010001.jpg" alt=" " /></p>
<p>de hecho la camara agarra la luz del control remoto (fotos despues), asi que solo hace falta una lampara infraroja y quedo hecho para poder tomar fotos en &#8220;cero&#8221; luz.</p>
<p>-mp</p>
]]></content:encoded>
			<wfw:commentRss>http://mauriciopastrana.com/gadgets-y-tecnologia/olympus-ir/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
	</channel>
</rss>
