<?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>Usuario de Internet &#187; Desarrollo</title>
	<atom:link href="http://www.usuariodeinternet.es/categoria/desarrollo/feed" rel="self" type="application/rss+xml" />
	<link>http://www.usuariodeinternet.es</link>
	<description>Experiencias técnicas y lúdicas</description>
	<lastBuildDate>Sun, 02 Oct 2011 02:09:16 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Script Caza Unfollowers de Twitter</title>
		<link>http://www.usuariodeinternet.es/desarrollo/twitter-unfollowers</link>
		<comments>http://www.usuariodeinternet.es/desarrollo/twitter-unfollowers#comments</comments>
		<pubDate>Wed, 16 Mar 2011 09:00:30 +0000</pubDate>
		<dc:creator>fer</dc:creator>
				<category><![CDATA[Desarrollo]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[twitter]]></category>

		<guid isPermaLink="false">http://www.usuariodeinternet.es/?p=831</guid>
		<description><![CDATA[Las reacciones ante un unfollow en Twitter suelen ser diversas, desde la acción recíproca inmediata (cosa que no logro entender ¿has dejado de ver el telediario porque el presentador no se dirija a ti en persona? pues eso&#8230;) hasta la más absoluta indeferencia. A mi más bien me mueve la curiosidad, saber si ha sido [...]]]></description>
			<content:encoded><![CDATA[<p>Las reacciones ante un unfollow en Twitter suelen ser diversas, desde la acción recíproca inmediata (cosa que no logro entender ¿has dejado de ver el telediario porque el presentador no se dirija a ti en persona? pues eso&#8230;) hasta la más absoluta indeferencia. A mi más bien me mueve la curiosidad, saber si ha sido la posible reacción ante un tuit concreto, el perfil de la persona que deja de seguirme, etc&#8230;</p>
<p>Aquí os traigo un pequeño script que he hecho para enterarme de esto. Sé que hay por ahi muchos servicios que hacen lo mismo, los he probado y todos me han parecido una chusta, publicidad, desfase en la notificación y en general nada que cumpla bien algo tan simple como esto. Por eso he acabado tirando unas líneas de código para tenerlo en mi propio servidor y hacer exáctamente lo que espero, que es muy sencillo: <strong>recibir un email cada vez que alguien deje de seguirme en Twitter</strong>. A continuación explico algunos detalles de esta mini aplicación que podéis descargar desde <a href="https://github.com/ferjgar/twitter-unfollowers">github</a>.</p>
<p style="text-align: center;"><img src="http://www.usuariodeinternet.es/img/post/twitter-unfollowers.jpg" alt="Esos que te hacen unfollow en Twitter..." /></p>
<p><span id="more-831"></span><br />
Lo primero aclarar que obviamente no es una aplicación de uso general, por las siguientes peculiaridades:</p>
<ul style="margin-left: 30px;">
<li>Aunque fácilmente modificable, hace únicamente lo que yo necesito, explicado al principio</li>
<li>Está limitada a 5000 followers (por defecto el límite de la API de Twitter si no se utiliza paginación), cuando sobrepase esa cifra ya lo modificaré ;)</li>
<li>Utiliza un fichero para almacenar los followers y arrays para comparar, lo cual con un número elevado de ellos no sé cómo rendirá</li>
</ul>
<p>Al turronaco. El único requerimiento es la extensión <strong>curl</strong> de PHP, que se utiliza para llamar a las APIs de Twitter. La gestión de errores es como un martillo, si no hay curl o alguna API devuelve un error el script termina, no necesito nada más sofisticado.</p>
<p>La única personalización necesaria está en el fichero <span class="codigo">twitter_unfollowers.php</span>, para los campos del email que recibiremos:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>11
12
13
14
15
16
17
18
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">// fichero donde se guardan los followers para posteriormente compararlos con los actuales</span>
<span style="color: #990000;">define</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'FIC_GUARDADO'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'twitter_followers_{USUARIO}.db'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #666666; font-style: italic;">// poner a 0 si no quieres recibir un email con la lista de unfollowers</span>
<span style="color: #990000;">define</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'ENVIAR_EMAIL'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'1'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #990000;">define</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'EMAIL_DIRECCION'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'xxxx@yyyy.com'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #990000;">define</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'EMAIL_ASUNTO'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'[TWITTER] Te ha(n) desfollogüeado {NUM} usuario(s)'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #666666; font-style: italic;">// dirección válida en el servidor donde se ejecuta el script para que el email no se vaya al spam</span>
<span style="color: #990000;">define</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'EMAIL_REMITENTE'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'iiii@jjjj.com'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>Podemos utilizar esta clase en un simple script que se pondría en el <a href="http://es.wikipedia.org/wiki/Cron_%28Unix%29">cron</a>, como por ejemplo:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
&nbsp;
	<span style="color: #b1b100;">require</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'twitter_unfollowers.php'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #000088;">$tuiter</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Twitter_unfollowers<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'&lt;id_usuario_twitter&gt;'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #000088;">$tuiter</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">check_unfollow</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #b1b100;">echo</span> <span style="color: #0000ff;">'fin'</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></td></tr></table></div>

<div class="descarga">
<a href="https://github.com/ferjgar/twitter-unfollowers">descargar en <strong>github</strong></a></p>
<p>Twitter Unfollowers [v1.2]</p>
</div>
<p class="relacionados">Changelog</p>
<blockquote><p>v1.0 &#8211; Desarrollo inicial<br />
v1.1 &#8211; Eliminada la necesidad de autenticarse con OAuth para utilizar las APIs<br />
v1.2 &#8211; Arreglados problemas de codificación y control de errores de la API</p></blockquote>
]]></content:encoded>
			<wfw:commentRss>http://www.usuariodeinternet.es/desarrollo/twitter-unfollowers/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Conflicto de herencia en htaccess entre Rewrite y Auth</title>
		<link>http://www.usuariodeinternet.es/desarrollo/conflicto-de-herencia-en-htaccess-entre-rewrite-y-auth</link>
		<comments>http://www.usuariodeinternet.es/desarrollo/conflicto-de-herencia-en-htaccess-entre-rewrite-y-auth#comments</comments>
		<pubDate>Thu, 23 Sep 2010 10:26:01 +0000</pubDate>
		<dc:creator>fer</dc:creator>
				<category><![CDATA[Desarrollo]]></category>
		<category><![CDATA[apache]]></category>

		<guid isPermaLink="false">http://www.usuariodeinternet.es/?p=774</guid>
		<description><![CDATA[Atención al titulo, soy un hacha jugando con keywords para atraer a todo tipo de audiencia al blog&#8230; y no, no se ha muerto Apache y los módulos se pelean por la pasta&#8230; en fin, al turrón. Pongamos que tenemos una web http://www.pepe.com, que en el servidor corresponde al path /home/web/pepe, y un subdirectorio http://www.pepe.com/admin, [...]]]></description>
			<content:encoded><![CDATA[<p>Atención al titulo, soy un hacha jugando con keywords para atraer a todo tipo de audiencia al blog&#8230; y no, no se ha muerto Apache y los módulos se pelean por la pasta&#8230; en fin, al turrón. Pongamos que tenemos una web http://www.pepe.com, que en el servidor corresponde al path <em>/home/web/pepe</em>, y un subdirectorio http://www.pepe.com/admin, cuya ruta es <em>/home/web/pepe/admin</em>.</p>
<p>En mi caso concreto pepe.com es un dominio antiguo, y quiero que toda referencia a él acabe en el nuevo, digamos paco.com. Para ello utilizo un htaccess que hace una redirección 301 a lo bruto:</p>

<div class="wp_syntax"><div class="code"><pre class="apache" style="font-family:monospace;"><span style="color: #adadad; font-style: italic;"># colocado en /home/web/pepe/.htaccess</span>
<span style="color: #00007f;">Options</span> +<span style="color: #0000ff;">FollowSymlinks</span>
<span style="color: #00007f;">RewriteEngine</span> <span style="color: #0000ff;">on</span>
<span style="color: #00007f;">RewriteRule</span> ^(.*)$ http://www.paco.com [R=<span style="color: #ff0000;">301</span>,L]</pre></div></div>

<p>Éste es mi problema concreto, pero por ejemplo es también muy común en frameworks y CMS hacer una redirección general de todas las peticiones a un único fichero. Vamos, que aquí lo importante es la <strong>reescritura general</strong>.</p>
<p>Ahora lo que quiero es <strong>proteger con contraseña</strong> el acceso a mi administración, por lo que utilizo otro htaccess con el contenido estándar para ésto:</p>

<div class="wp_syntax"><div class="code"><pre class="apache" style="font-family:monospace;"><span style="color: #adadad; font-style: italic;"># colocado en /home/web/pepe/admin/.htaccess</span>
<span style="color: #00007f;">AuthType</span> Basic
<span style="color: #00007f;">AuthUserFile</span> /home/web/pepe/admin/.htpasswd
<span style="color: #00007f;">AuthName</span> <span style="color: #7f007f;">&quot;Acceso Administrador&quot;</span>
<span style="color: #00007f;">Require</span> valid-<span style="color: #00007f;">user</span></pre></div></div>

<p>Y como no podía ser de otra forma el invento no funciona. Cuando intento acceder a http://www.pepe.com/admin me redirige a http://www.paco.com, luego el primer cambio es meter una excepción para que no aplique la regla de reescritura para la URL que nos interesa. Lo podemos hacer en el htaccess principal con una condición:</p>

<div class="wp_syntax"><div class="code"><pre class="apache" style="font-family:monospace;"><span style="color: #adadad; font-style: italic;"># colocado en /home/web/pepe/.htaccess</span>
<span style="color: #00007f;">Options</span> +<span style="color: #0000ff;">FollowSymlinks</span>
<span style="color: #00007f;">RewriteEngine</span> <span style="color: #0000ff;">on</span>
<span style="display:block;background-color: #ffc;"><span style="color: #00007f;">RewriteCond</span> %{REQUEST_URI} !^/admin/?</span><span style="color: #00007f;">RewriteRule</span> ^(.*)$ http://www.paco.com [R=<span style="color: #ff0000;">301</span>,L]</pre></div></div>

<p>O si no necesitamos de ninguna reescritura en el directorio hijo podemos directamente desactivar el engine:</p>

<div class="wp_syntax"><div class="code"><pre class="apache" style="font-family:monospace;"><span style="color: #adadad; font-style: italic;"># colocado en /home/web/pepe/admin/.htaccess</span>
<span style="display:block;background-color: #ffc;"><span style="color: #00007f;">RewriteEngine</span> <span style="color: #0000ff;">off</span></span><span style="color: #00007f;">AuthType</span> Basic
<span style="color: #00007f;">AuthUserFile</span> /home/web/pepe/admin/.htpasswd
<span style="color: #00007f;">AuthName</span> <span style="color: #7f007f;">&quot;Acceso Administrador&quot;</span>
<span style="color: #00007f;">Require</span> valid-<span style="color: #00007f;">user</span></pre></div></div>

<p>Cojonudo, pero sigue haciendo la redirección. <u>Primera comida de cabeza importante</u>: comento todas las reglas de reescritura y sigue redirigiendo ¿? resulta que <strong>Firefox cachea las redirecciones</strong> (al menos las 301), así que ya puedes darle a F5 y estar correctas las reglas, que no te enterarás si no borras la caché del navegador, eso o utilizar Explorer (no lo he probado en el resto).</p>
<p>Descartado el navegador, ésto sigue sin rular. Utilizando el imprescindible <a href="https://addons.mozilla.org/es-ES/firefox/addon/6647/">HttpFox</a> y Google descubro que la autenticación básica de Apache que queremos usar manda una cabecera <strong>401 Unauthorized</strong>, que el navegador recibe y es cuando muestra el cuadro de usuario/contraseña. <u>Segunda comida de cabeza importante</u>: el servidor está buscando un mensaje de error personalizado para el 401 (en una directiva <a href="http://httpd.apache.org/docs/2.0/mod/core.html#errordocument">ErrorDocument</a>), que no encuentra y por tanto lanza, adicionalmente, un 404. Y resulta que, no me preguntes por qué, este último error pasa por la reescritura general y es lo que está provocando la redirección. Acojonante. La solución es definir dicho ErrorDocument en nuestro htaccess:</p>

<div class="wp_syntax"><div class="code"><pre class="apache" style="font-family:monospace;"><span style="color: #adadad; font-style: italic;"># colocado en /home/web/pepe/.htaccess</span>
<span style="color: #00007f;">Options</span> +<span style="color: #0000ff;">FollowSymlinks</span>
<span style="color: #00007f;">RewriteEngine</span> <span style="color: #0000ff;">on</span>
<span style="color: #00007f;">RewriteCond</span> %{REQUEST_URI} !^/admin/?
<span style="color: #00007f;">RewriteRule</span> ^(.*)$ http://www.paco.com [R=<span style="color: #ff0000;">301</span>,L]
<span style="display:block;background-color: #ffc;"><span style="color: #00007f;">ErrorDocument</span> <span style="color: #ff0000;">401</span> <span style="color: #7f007f;">&quot;Acceso restringido&quot;</span></span></pre></div></div>

<p>¡Aparece el cuadro para meter usuario/contraseña! joder, ha costado.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.usuariodeinternet.es/desarrollo/conflicto-de-herencia-en-htaccess-entre-rewrite-y-auth/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Scroll infinito con jQuery</title>
		<link>http://www.usuariodeinternet.es/desarrollo/scroll-infinito-con-jquery</link>
		<comments>http://www.usuariodeinternet.es/desarrollo/scroll-infinito-con-jquery#comments</comments>
		<pubDate>Mon, 12 Apr 2010 19:15:36 +0000</pubDate>
		<dc:creator>fer</dc:creator>
				<category><![CDATA[Desarrollo]]></category>
		<category><![CDATA[ajax]]></category>
		<category><![CDATA[jquery]]></category>
		<category><![CDATA[tumblr]]></category>

		<guid isPermaLink="false">http://www.usuariodeinternet.es/?p=674</guid>
		<description><![CDATA[También conocido como endless scrolling, endless pageless, paginación sin páginas, etc&#8230; es un patrón de interfaz de usuario del que se viene hablando desde hace unos años, aunque es últimamente cuando parece que lo veo implementado en cada vez más sitios. El ejemplo por antonomasia es por supuesto el de Google Reader, pero hay muchos [...]
Entradas relacionadas:<ol>
<li><a href='http://www.usuariodeinternet.es/desarrollo/error-en-la-codificacion-con-ajax' rel='bookmark' title='Error en la codificación con AJAX'>Error en la codificación con AJAX</a></li>
<li><a href='http://www.usuariodeinternet.es/desarrollo/internacionalizacion-con-smarty' rel='bookmark' title='Internacionalización con Smarty'>Internacionalización con Smarty</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>También conocido como <em>endless scrolling</em>, <em>endless pageless</em>, <em>paginación sin páginas</em>, etc&#8230; es un <strong>patrón de interfaz de usuario</strong> del que se viene hablando desde hace unos años, aunque es últimamente cuando parece que lo veo implementado en cada vez más sitios.</p>
<p>El ejemplo por antonomasia es por supuesto el de Google Reader, pero hay muchos más: Facebook (fijaros que lo hace una vez cuando vas a mitad de página), Digg, Bing, Vimeo, Dropular&#8230;.</p>
<p>Básicamente consiste en cargar más contenido dinámicamente conforme te acercas al final de la página, de forma que la navegación por el mismo no queda interrumpida en ningún momento. Viene a ser un <strong>sustitutivo de la paginación tradicional</strong>.</p>
<p>Luego comentaré los pros y contras que pienso tiene esta técnica. Antes contar cómo lo he implementado en mi tumblr, <a href="http://micro.usuariodeinternet.es/">micro Usuario de Internet</a>, algo que llevaba bastante tiempo queriendo hacer y que sin duda opino le va como anillo al dedo.</p>
<p style="text-align:center;"><img src="/img/post/scroll_infinito.png" alt="Scroll infinito en micro.usuariodeinternet.es" /></p>
<p>Aunque en principio tenía intención de remangarme, encontré un plugin, <a href="http://plugins.jquery.com/project/de-pagify" target="_blank"><strong>de-pagify</strong></a>, que lo implementa de forma muy flexible y aprovechando parte de la <em>magia</em> de jQuery. Utilizar un framework de javascript simplifica considerablemente la codificación del método, que de otra forma sería bastante más laboriosa, sobre todo el paso de procesar el contenido para pintarlo en pantalla.</p>
<p>En la página del plugin viene todo explicado muy claramente, sólo destacar dos cosas:</p>
<ul style="margin-left:30px;">
<li>Hay 4 formas de lanzar el evento para traerse más contenido. Se configura con el párametro <strong>trigger</strong>, y puede ser cuando se llegue a un % de altura de la página, a una altura determinada (pixels), cuando se vea un determinado elemento de la página (mi elección) o incluso dependiendo de la salida de una función propia. La flexibilidad es máxima.</li>
<li>Como he comentado, utilizar jQuery ahorra mucho código, y una de las perlas que más me ha gustado es la siguiente línea:

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #006600; font-style: italic;">// Format url as &quot;?page=1 div#wrapper div.post&quot;</span>
<span style="color: #003366; font-weight: bold;">var</span> url <span style="color: #339933;">=</span> <span style="color: #009900;">&#91;</span>next.<span style="color: #660066;">attr</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'href'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> options.<span style="color: #660066;">container</span><span style="color: #339933;">,</span> options.<span style="color: #660066;">filter</span><span style="color: #009900;">&#93;</span>.<span style="color: #660066;">join</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">' '</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>El método de ajax <a href="http://api.jquery.com/load/" target="_blank">load</a>, que es con el que nos vamos a traer el contenido de la <em>siguiente página</em> para pintarlo dinámicamente, permite especificar la URL con selectores separados por espacios, de manera que podemos controlar qué elementos, qué HTML al fin y al cabo, queremos que se cargue en la capa que eligamos. Ésto nos ahorra de una tacada tener que hacer alguna modificación en el código de la aplicación (se van a ir pidiendo por ajax sucesivas páginas como si la navegación fuera la clásica) y tener que procesar el HTML que recibimos (se pinta tal cual porque ya viene filtrado con el contenido, lo único que he tenido que modificar de la página es un poco la maquetación).</p>
</li>
</ul>
<p>En definitiva, y en mi opinión:</p>
<p><strong>PROS</strong></p>
<ul style="margin-left:30px;">
<li><em>Experiencia de usuario</em>: no tengo la menor duda de que, para cierto tipo de webs y, sobre todo, de contenido, el eliminar la paginación supone una mejora muy significativa en la forma de navegar por el sitio, comportándose de la forma natural en la que uno esperaría moverse por él.</li>
<li><em>Consumo</em>: cuando desaparece el punto final (pie de página y paginación) pasa a ser un comportamiento natural el hacer scroll indefinidamente y por tanto seguir consumiendo el contenido de manera <em>indefinida</em>.</li>
</ul>
<p><strong>CONTRAS</strong></p>
<ul style="margin-left:30px;">
<li><em>Experiencia de usuario</em>: y no es una contradicción, la <em>nueva</em> forma de navegación puede confundir a muchos usuarios menos duchos en esto de Internet, acostumbrados a los puntos de ruptura (paginación), a saber por qué página del libro van y a una estructura de web más convencional.</li>
<li><em>Implementación</em>: no es tema trivial, ya no técnicamente, sino desde el punto de vista de la usabilidad. Por ejemplo está muy unido al dispositivo utilizado: con la rueda del ratón todo es maravilloso, con el teclado o arrastrando la barra de scroll ya pueden darse saltos incómodos. La norma aquí es que sea prácticamente imperceptible para el usuario lo que se está cociendo de fondo (aquí tengo que mejorar mi implementación).</li>
<li><em>Monetización</em>: en sitios que se ganan las habichuelas con la publicidad puede suponer un problema la ubicación de los bloques de anuncios. Un esquema típico de jumbobanner arriba, roba a la derecha y Adsense bajo el contenido queda bastante desvirtuado con esta navegación. Lo mismo con páginas vistas (solucionable con una buena semilla).</li>
</ul>
<p>Entradas relacionadas:<ol>
<li><a href='http://www.usuariodeinternet.es/desarrollo/error-en-la-codificacion-con-ajax' rel='bookmark' title='Error en la codificación con AJAX'>Error en la codificación con AJAX</a></li>
<li><a href='http://www.usuariodeinternet.es/desarrollo/internacionalizacion-con-smarty' rel='bookmark' title='Internacionalización con Smarty'>Internacionalización con Smarty</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.usuariodeinternet.es/desarrollo/scroll-infinito-con-jquery/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Internacionalización con Smarty</title>
		<link>http://www.usuariodeinternet.es/desarrollo/internacionalizacion-con-smarty</link>
		<comments>http://www.usuariodeinternet.es/desarrollo/internacionalizacion-con-smarty#comments</comments>
		<pubDate>Mon, 23 Nov 2009 08:16:06 +0000</pubDate>
		<dc:creator>fer</dc:creator>
				<category><![CDATA[Desarrollo]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[smarty]]></category>

		<guid isPermaLink="false">http://www.usuariodeinternet.es/?p=532</guid>
		<description><![CDATA[El temita de la internacionalización (i18n para los amigos) en una aplicación web puede dar para largo y tendido, yo voy a hablar aquí concretamente de la forma de guardar y utilizar las cadenas de texto del site en varios idiomas utilizando el framework de templates Smarty. Hay muchas formas de hacerlo, se pueden encontrar [...]
Entradas relacionadas:<ol>
<li><a href='http://www.usuariodeinternet.es/desarrollo/error-en-la-codificacion-con-ajax' rel='bookmark' title='Error en la codificación con AJAX'>Error en la codificación con AJAX</a></li>
<li><a href='http://www.usuariodeinternet.es/desarrollo/scroll-infinito-con-jquery' rel='bookmark' title='Scroll infinito con jQuery'>Scroll infinito con jQuery</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p style="text-align: center;"><img title="Internacionalización con Smarty" src="/img/post/smarty_i18n.png" border="0" alt="Internacionalización con Smarty" width="640" height="97" /></p>
<p>El temita de la internacionalización (<em>i18n</em> para los amigos) en una aplicación web puede dar para largo y tendido, yo voy a hablar aquí concretamente de la <strong>forma de guardar y utilizar las cadenas de texto</strong> del site en varios idiomas utilizando el framework de templates <a href="http://www.smarty.net" target="_blank">Smarty</a>.</p>
<p>Hay muchas formas de hacerlo, se pueden encontrar varias alternativas en este post de <a href="http://www.smarty.net/forums/viewtopic.php?t=84&#038;postdays=0&#038;postorder=asc&#038;start=0" target="_blank">best way to build a multi-language site with smarty</a>, que empezó en el ¡2003! (el frenético ritmo que lleva la tecnología hace que no me crea nada que no sea de ayer&#8230;). Todas tienen sus ventajas e inconvenientes, y dado que no hay nada en el core de Smarty para ésto ni una solución popularmente aceptada como la <em>estándar</em>, cada uno debe analizar lo que necesita para su proyecto y tener unas preferencias subjetivas, que en mi caso son:</p>
<ul style="margin-left:30px;">
<li><strong>Que no implique PHP</strong>: obviamente hay opciones mucho más sofisticadas, eficientes, etc&#8230; para solucionar el tema del i18n con programación (por ejemplo <a href="http://sourceforge.net/projects/smarty-gettext/" target="_blank">smarty-gettext</a>), pero precisamente el uso de Smarty es para separar la lógica de la aplicación de la de presentación, y dado que considero que ésto es problema de front-end puro, yo quiero resolverlo únicamente con Smarty.</li>
<li><strong>Que sea sencillo y eficiente</strong>: con el tiempo me estoy conviertiendo en un talibán del código, en el sentido bueno (creo) de intentar que las cosas se hagan de la forma más clara posible (<a href="http://es.wikipedia.org/wiki/Principio_KISS" target="_blank">KISS</a> power!) y que note un pinchazo en el corazón con cada ciclo de reloj que se consume en código prescindible.</li>
</ul>
<p><span id="more-532"></span><br />
 Por ejemplo, hay una solución <strong>muy buena</strong> y que he utilizado en otros proyectos, <a href="http://smarty.incutio.com/?page=SmartyMultilanguageSupport" target="_blank">SmartyML</a>, pero es una clase más en PHP (una capa más para procesar) y viendo tanto código pienso que debe haber una forma mejor de hacerlo.</p>
<p>Pero vamos al turrón. Al final encontré en el foro antes mencionado la solución que me parece más sencilla y adecuada para lo que necesito. Se trata de utilizar <a href="http://smarty.net/manual/es/config.files.php" target="_blank"><strong>archivos de configuración</strong></a> (1ª ventaja: es una funcionalidad core de Smarty, con lo que no hay que añadir más complejidad). En estos ficheros se definen variables globales para los templates y se pueden aplicar de varias formas:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">// desde el PHP</span>
<span style="color: #000088;">$smarty</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">config_load</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'fichero.conf'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// desde el template</span>
<span style="color: #009900;">&#123;</span>config_load <span style="color: #990000;">file</span><span style="color: #339933;">=</span><span style="color: #0000ff;">'fichero.conf'</span><span style="color: #009900;">&#125;</span></pre></div></div>

<p>Yo prefiero hacerlo desde PHP porque la gestión del idioma de la web es lógica de aplicación y hay que poner cada cosa en su sitio. El directorio donde se almacenan estos ficheros debe ser definido en el código:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$smarty</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Smarty<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$smarty</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">config_dir</span>   <span style="color: #339933;">=</span> <span style="color: #0000ff;">'/path/al/directorio/'</span><span style="color: #339933;">;</span></pre></div></div>

<p>Crearemos un archivo por idioma, en los que tendremos todas las cadenas de texto que vamos a utilizar traducidas, por ejemplo:</p>

<div class="wp_syntax"><div class="code"><pre class="smarty" style="font-family:monospace;"># /path/al/directorio/es.conf (español)
saludo = hola!
enviar = Enviar
cancelar = Cancelar</pre></div></div>


<div class="wp_syntax"><div class="code"><pre class="smarty" style="font-family:monospace;"># /path/al/directorio/en.conf (inglés)
saludo = hi!
enviar = Send
cancelar = Cancel</pre></div></div>

<p>Utilizar estas variables en los templates es tan sencillo como usar la sintaxis <strong>{#variable#}</strong>, por ejemplo:</p>

<div class="wp_syntax"><div class="code"><pre class="html4strict" style="font-family:monospace;"><span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">strong</span>&gt;</span>{#saludo#}<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">strong</span>&gt;</span>
<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">input</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;button&quot;</span> <span style="color: #000066;">name</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;enviar&quot;</span> <span style="color: #000066;">value</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;{#enviar#}&quot;</span> <span style="color: #66cc66;">/</span>&gt;</span>
<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">input</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;button&quot;</span> <span style="color: #000066;">name</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;cancelar&quot;</span> <span style="color: #000066;">value</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;{#cancelar#}&quot;</span> <span style="color: #66cc66;">/</span>&gt;</span></pre></div></div>

<p>¡Y ya está! desde el PHP se puede controlar qué archivo de configuración de idioma cargar y de esta manera tener montada nuestra web multilenguaje. Unos últimos apuntes:</p>
<ul style="margin-left:30px;">
<li>Las cadenas también pueden llevar <strong>texto variable</strong>, como por ejemplo un saludo del tipo <em>Hola Fernando, bienvenido!</em> Ésto se puede solucionar de dos formas:

<div class="wp_syntax"><div class="code"><pre class="smarty" style="font-family:monospace;"># forma CUTRE: en el tpl
<span style="color: #009000;">&lt;strong&gt;</span><span style="color: #D36900;">&#123;</span>#saludo1#<span style="color: #D36900;">&#125;</span><span style="color: #D36900;">&#123;</span><span style="color: #00aaff;">$nombre_usuario</span><span style="color: #D36900;">&#125;</span><span style="color: #D36900;">&#123;</span>#saludo2#<span style="color: #D36900;">&#125;</span><span style="color: #009000;">&lt;/strong&gt;</span>
&nbsp;
# en el archivo de configuración de idioma
saludo1 = Hola
saludo2 = bienvenido!</pre></div></div>


<div class="wp_syntax"><div class="code"><pre class="smarty" style="font-family:monospace;"># forma CORRECTA: en el tpl
<span style="color: #009000;">&lt;strong&gt;</span><span style="color: #D36900;">&#123;</span><span style="color: #0600FF;">eval</span> var<span style="color: #D36900;">=</span>#saludo#<span style="color: #D36900;">&#125;</span><span style="color: #009000;">&lt;/strong&gt;</span>
&nbsp;
# en el archivo de configuración de idioma
saludo = Hola <span style="color: #D36900;">&#123;</span><span style="color: #00aaff;">$nombre_usuario</span><span style="color: #D36900;">&#125;</span>, bienvenido!</pre></div></div>

</li>
<li>En lo que entiendo es una <strong>optimizacion</strong> (supongo que a nivel interno se controlará), se pueden utilizar <strong>secciones</strong> (referenciadas así <em>[seccion]</em>) en el archivo de configuración, de manera que si se especifica una en el <em>config_load</em> sólo esas variables se <em>cargarán</em> (la que estén fuera de una sección estarán siempre disponibles). Ésto nos puede servir para organizar las cadenas de texto por página y suponer que Smarty lo manejará mejor que el chorro completo de variables. Quedaría así:

<div class="wp_syntax"><div class="code"><pre class="smarty" style="font-family:monospace;"># cadenas globales
saludo = Hola!
enviar = Enviar
&nbsp;
# página de login
[login]
titulo = Introduce tu usuario y contraseña</pre></div></div>

<p>Y desde el PHP:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$smarty</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">config_load</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'es.conf'</span><span style="color: #339933;">,</span><span style="color: #0000ff;">'login'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$smarty</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">display</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'login.tpl'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

</li>
<li>Una desventaja es que no maneja de manera nativa los <strong>plurales</strong> como otras soluciones, de forma que hay que controlarlo a manubrio, por ejemplo:

<div class="wp_syntax"><div class="code"><pre class="smarty" style="font-family:monospace;"># en el tpl
<span style="color: #D36900;">&#123;</span><span style="color: #0600FF;">eval</span> var<span style="color: #D36900;">=</span>#subida_fotos#<span style="color: #D36900;">&#125;</span><span style="color: #D36900;">&#123;</span><span style="color: #0600FF;">if</span> <span style="color: #00aaff;">$num_fotos</span> <span style="color: #D36900;">&gt;</span> <span style="color: #cc66cc;">1</span><span style="color: #D36900;">&#125;</span>s<span style="color: #D36900;">&#123;</span><span style="color: #D36900;">/</span><span style="color: #0600FF;">if</span><span style="color: #D36900;">&#125;</span>
&nbsp;
# en el archivo de configuración de idioma
subida_fotos = Has subido <span style="color: #D36900;">&#123;</span><span style="color: #00aaff;">$num_fotos</span><span style="color: #D36900;">&#125;</span> foto</pre></div></div>

</li>
</ul>
<p>Entradas relacionadas:<ol>
<li><a href='http://www.usuariodeinternet.es/desarrollo/error-en-la-codificacion-con-ajax' rel='bookmark' title='Error en la codificación con AJAX'>Error en la codificación con AJAX</a></li>
<li><a href='http://www.usuariodeinternet.es/desarrollo/scroll-infinito-con-jquery' rel='bookmark' title='Scroll infinito con jQuery'>Scroll infinito con jQuery</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.usuariodeinternet.es/desarrollo/internacionalizacion-con-smarty/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Integrar las APIs de login de Facebook, Yahoo y Windows Live</title>
		<link>http://www.usuariodeinternet.es/desarrollo/integrar-las-apis-de-login-de-facebook-yahoo-y-windows-live</link>
		<comments>http://www.usuariodeinternet.es/desarrollo/integrar-las-apis-de-login-de-facebook-yahoo-y-windows-live#comments</comments>
		<pubDate>Fri, 20 Feb 2009 09:37:55 +0000</pubDate>
		<dc:creator>fer</dc:creator>
				<category><![CDATA[Desarrollo]]></category>
		<category><![CDATA[api]]></category>
		<category><![CDATA[facebook]]></category>
		<category><![CDATA[windows live]]></category>
		<category><![CDATA[yahoo]]></category>

		<guid isPermaLink="false">http://www.usuariodeinternet.es/?p=414</guid>
		<description><![CDATA[La filosofía del single sign-on ha terminado imponiéndose por pura lógica de saturamiento 2.0, con los grandes jugadores vendiendo sus nuevas propuestas (OpenID lo intentó y no lo consiguió&#8230;) y los usuarios cansados de procesos de registro y contraseñas varias. Darles a éstos la oportunidad de usar sus credenciales de alguno de los servicios top [...]
Entradas relacionadas:<ol>
<li><a href='http://www.usuariodeinternet.es/navegando/windows-live-maps-se-un-pajaro' rel='bookmark' title='Windows Live Maps: Sé un Pájaro'>Windows Live Maps: Sé un Pájaro</a></li>
<li><a href='http://www.usuariodeinternet.es/navegando/segundo-facebook-developer-garage-en-madrid' rel='bookmark' title='Segundo Facebook Developer Garage en Madrid'>Segundo Facebook Developer Garage en Madrid</a></li>
<li><a href='http://www.usuariodeinternet.es/desarrollo/nuevas-apis-de-google' rel='bookmark' title='Nuevas APIs de Google'>Nuevas APIs de Google</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p style="text-align: center;">
<img height="150" width="640" border="0" alt="El bonito single sign-on" src="/img/post/singlesignon.jpg" title="El bonito single sign-on"/>
</p>
<p>La filosofía del <strong>single sign-on</strong> ha terminado imponiéndose por pura lógica de saturamiento 2.0, con los grandes jugadores vendiendo sus nuevas propuestas (OpenID lo intentó y no lo consiguió&#8230;) y los usuarios cansados de procesos de registro y contraseñas varias. Darles a éstos la oportunidad de usar sus credenciales de alguno de los servicios top para utilizar tu sitio debería ser ya a estas alturas planteado como una funcionalidad primaria de cualquier proyecto web.</p>
<p>Lo que viene a continuación es una guía para implementar en tu web la funcionalidad de &#8220;login externo&#8221; usando las APIs de tres de los grandes: <strong>Facebook</strong>, <strong>Yahoo</strong> y <strong>Windows Live</strong> (Google y OpenID vendrán en otro post). El proceso es similar en todos los casos, y el objetivo es acabar teniendo para utilizar en nuestro código el id único externo (la variable <em>$id_unico</em> en los ejemplos) que nos sirva para identificar y validar al usuario en nuestro sistema local.<br />
<span id="more-414"></span></p>
<h2>Facebook</h2>
<p>La integración más sencilla de todas ¡5 líneas de código!</p>
<p>La <a href="http://developers.facebook.com/">documentación para desarrolladores de Facebook</a> es de las mejores, con muchos ejemplos prácticos y una comunidad muy activa. Vamos a hacer <strong>la implementación más sencilla</strong>, sin meternos en <a href="http://developers.facebook.com/connect.php">Facebook Connect</a>, que será chicha para otro post. Los pasos serían los siguientes:</p>
<ol style="margin-left:30px;">
<li>Logueado en tu cuenta de Facebook debes añadirte la <a href="http://www.facebook.com/developers/">aplicación para desarrolladores</a>.</li>
<li>Creamos una nueva aplicación, y rellenamos lo básico para que funcione (el resto es para configuraciones más avanzadas)
<p style="text-align: center;margin-top:10px;"><img src="/img/post/apilog_facebook_campos.png" alt="Campos mínimos para rellenar en la aplicación de Facebook" title="Campos mínimos para rellenar en la aplicación de Facebook" width="701" height="244" /></p>
</li>
<li>Nos bajamos la <a href="http://svn.facebook.com/svnroot/platform/clients/packages/facebook-platform.tar.gz">librería cliente de PHP</a>.</li>
<li>¡Y a picar!</li>
</ol>
<p>Resumiendo, tenemos una api key, otra key privada, hemos especificado una URL propia de retorno de Facebook, y tenemos su clase de PHP (nos sobraría con los ficheros <em>facebook.php</em> y <em>facebookapi_php5_restlib.php</em>). Pues el script para loguearse con Facebook sería tan sencillo como esto:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
&nbsp;
	<span style="color: #666666; font-style: italic;">// cargamos la clase que nos proporcionan</span>
	<span style="color: #b1b100;">require_once</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'apis_externas/facebook/class_facebook.php'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #666666; font-style: italic;">// datos de la aplicación que se nos facilitan cuando la registramos en Facebook </span>
	<span style="color: #000088;">$appapikey</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'000000000000'</span><span style="color: #339933;">;</span>
	<span style="color: #000088;">$appsecret</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'111111111111'</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #666666; font-style: italic;">// inicializamos el objeto de la clase</span>
	<span style="color: #000088;">$facebook</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Facebook<span style="color: #009900;">&#40;</span><span style="color: #000088;">$appapikey</span><span style="color: #339933;">,</span><span style="color: #000088;">$appsecret</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #666666; font-style: italic;">// si el usuario no está logueado en Facebook le redirigirá allí</span>
	<span style="color: #000088;">$id_unico</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$facebook</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">require_login</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">empty</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$id_unico</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
	<span style="color: #009900;">&#123;</span>
		<span style="color: #666666; font-style: italic;">// si a estas alturas no tenemos el id único algo ha salido mal</span>
		<span style="color: #000088;">$error_api</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></td></tr></table></div>

<p>Hay varias formas de hacer esto en Facebook, y no digo que esta sea la más correcta, pero seguro que la más sencilla. La importante es la línea 14, en la que si el usuario está logueado nos devolverá su id único, y sino le enviará a la página de login de Facebook.</p>
<h2>Yahoo</h2>
<p>Otra API con integración <em>no traumática</em> gracias a la tecnología <a href="https://developer.yahoo.com/auth/">BBAuth de Yahoo</a>. Aquí también se pueden elegir varias implementaciones (OAuth, OpenID), pero de nuevo vamos a optar por la más sencilla y rápida de desarrollar. Los pasos son los siguientes:</p>
<ol style="margin-left:30px;">
<li>Vamos a la página de <a href="https://developer.yahoo.com/dashboard/">alta de aplicaciones</a> (se necesita usuario de Yahoo).</li>
<li>Creamos una nueva <em>Browser-Based Authentication Protected Application</em>
<p style="text-align: center;margin-top:10px;"><img src="/img/post/apilog_yahoo_campos.gif" alt="Campos mínimos para rellenar en la aplicación de Yahoo" title="Campos mínimos para rellenar en la aplicación de Yahoo" width="665" height="586" /></p>
</li>
<li>Nos pedirán confirmar el dominio subiendo un fichero determinado a nuestra web.</li>
<li>Nos bajamos la <a href="https://developer.yahoo.com/auth/quickstart/bbauth_quickstart.zip">librería cliente de PHP</a>.</li>
<li>¡Y a picar!</li>
</ol>
<p>Resumiendo de nuevo, tenemos la aplicación creada, apuntadas las dos keys que necesitamos y la clase para comunicarnos con Yahoo (usaremos el fichero <em>ybrowserauth.class.php4</em> o <em>ybrowserauth.class.php5</em> dependiendo de nuestra versión de PHP). El código final quedará así:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
&nbsp;
	<span style="color: #666666; font-style: italic;">// datos de la aplicación que se nos facilitan cuando la registramos en Yahoo</span>
	<span style="color: #990000;">define</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'APPID'</span><span style="color: #339933;">,</span><span style="color: #0000ff;">'000000000000'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #990000;">define</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'SECRET'</span><span style="color: #339933;">,</span><span style="color: #0000ff;">'111111111111'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>	
&nbsp;
	<span style="color: #666666; font-style: italic;">// cargamos la clase que nos proporcionan (en este caso tenemos PHP 5 en el servidor)</span>
	<span style="color: #b1b100;">require_once</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'apis_externas/yahoo/ybrowserauth.class.php5'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #666666; font-style: italic;">// inicializamos el objeto de la clase</span>
	<span style="color: #000088;">$authObj</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> YBBauthREST<span style="color: #009900;">&#40;</span>APPID<span style="color: #339933;">,</span>SECRET<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">empty</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$_GET</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'token'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> 
	<span style="color: #009900;">&#123;</span>
		<span style="color: #666666; font-style: italic;">// si no tenemos token mandamos a la página de login</span>
		<span style="color: #000088;">$url</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$authObj</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getAuthURL</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">''</span><span style="color: #339933;">,</span><span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #990000;">header</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Location: '</span><span style="color: #339933;">.</span><span style="color: #000088;">$url</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #990000;">exit</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$authObj</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">validate_sig</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> 
	<span style="color: #009900;">&#123;</span>
		<span style="color: #666666; font-style: italic;">// si validamos el token ya podemos sacar el id único</span>
		<span style="color: #000088;">$id_unico</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$authObj</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">userhash</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
	<span style="color: #b1b100;">else</span>
	<span style="color: #009900;">&#123;</span>
		<span style="color: #666666; font-style: italic;">// el token recibido no es correcto</span>
		<span style="color: #000088;">$error_api</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></td></tr></table></div>

<p>Es muy importante recordar que esta API es especial en el sentido que el id que se recibe finalmente es un <strong>hash del id único real del usuario en Yahoo y el id de la aplicación</strong>, es decir, si el mismo usuario de loguea con otra aplicación recibiremos un hash distinto, por lo que tenemos que tener en cuenta qué significa exactamente este id <em>único</em> que recibimos de la API.</p>
<h2>Windows Live</h2>
<p>Haciendo honor a su fama, y con mucha diferencia, la API de Windows Live es la más complicada de implementar, tanto por su <a href="http://msdn.microsoft.com/en-us/library/bb676633.aspx">horrenda documentación</a> (lo de msdn es terminal&#8230;) como por el engorro general que supone lidiar con sus múltiples archivos y su extraño flujo de información.</p>
<p>Los pasos iniciales son similares a las anteriores APIs, la diversión viene después&#8230;</p>
<ol style="margin-left:30px;">
<li>Vamos a la página de <a href="https://lx.azure.microsoft.com/">alta de aplicaciones</a> (se necesita usuario de Windows Live).</li>
<li>Creamos un proyecto de <em>Live Services: Existing APIs</em>
<p style="text-align: center;margin-top:10px;"><img src="/img/post/apilog_windowslive_campos.gif" alt="Campos mínimos para rellenar en la aplicación de Windows Live" title="Campos mínimos para rellenar en la aplicación de Windows Live" width="685" height="440" /></p>
<p>Es en este formulario cuando nos enfrentamos al primer problema absurdo, y es que el campo <em>Return URL</em> permite un <strong>máximo de 50 caracteres</strong> wtf?? cualquier ruta que no vaya a la raíz va a tener más de 50 letras! la única solución es tener una herramienta tipo <a href="http://getfirebug.com/">firebug</a> para poder editar online el HTML y cambiar el atributo <em>maxlength</em> del campo para poder enviar una URL en condiciones (lo que confirma lo absurdo de la limitación es que la página no te comprueba si has escrito más de esos 50 caracteres, se envía sin problemas&#8230;)<br />
Y atención también que la <strong>URL de retorno no es la misma que el resto de las APIs</strong>, es a un script que nos bajaremos luego con el SDK.</li>
<li>Nos bajamos el <a href="http://www.microsoft.com/downloads/details.aspx?FamilyId=E565FC92-D5F6-4F5F-8713-4DD1C90DE19F&#038;displaylang=en#filelist">Web Authentication SDK</a> para el lenguaje que vayamos a utilizar.</li>
<li>¡Y a picar!</li>
</ol>
<p>De nuevo tenemos una api key, otra key privada, hemos especificado una URL de retorno nueva, y tenemos su SDK con varios archivos. Lo primero es poner las keys en el fichero <strong><em>Application-Key.xml</em></strong> (debe ser innaccesible desde internet, bien limitándolo con un htaccess o colocándolo fuera del document root):</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
</pre></td><td class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;windowslivelogin<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;appid<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>000000000000<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/appid<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;secret<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>111111111111<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/secret<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;securityalgorithm<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>wsignin1.0<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/securityalgorithm<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/windowslivelogin<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></td></tr></table></div>

<p>Ahora en el directorio <em>sample</em> tenemos una implementación de ejemplo a la que podemos quitarle bastante paja. Lo primero es editar el fichero <strong><em>settings.php</em></strong>:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
&nbsp;
	<span style="color: #666666; font-style: italic;">// por si las cosas no salen y se necesita consultar logs de errores </span>
	<span style="color: #000088;">$DEBUG</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #666666; font-style: italic;">// path completo al XML de configuración de la aplicación</span>
	<span style="color: #000088;">$KEYFILE</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'/home/usuario/Application-Key.xml'</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #666666; font-style: italic;">// nombre de la cookie que almacena el token de usuario que manda la API</span>
	<span style="color: #000088;">$COOKIE</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'webauthtoken'</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #666666; font-style: italic;">// URL a la que tiene que redirigir cuando todo termine</span>
	<span style="color: #000088;">$INDEX</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'/login_externo.php'</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #666666; font-style: italic;">// páginas a las que tiene que llevar cuanto se haga login o logout</span>
	<span style="color: #000088;">$LOGIN</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$INDEX</span><span style="color: #339933;">;</span>
	<span style="color: #000088;">$LOGOUT</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$INDEX</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #666666; font-style: italic;">// la URL de la API ¡no tocar!</span>
	<span style="color: #000088;">$CONTROLURL</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'http://login.live.com/controls/WebAuth.htm'</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></td></tr></table></div>

<p>En el fichero <strong><em>webauth-handler.php</em></strong> (recordar que es éste el que hemos puesto como URL de retorno al crear la aplicación) tenemos que poner la rutas correcta al fichero de configuración y a la librería de la API (el fichero <em>windowslivelogin.php</em> en el directorio <em>lib</em>):</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
&nbsp;
	<span style="color: #b1b100;">require</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'/home/usuario/dominio/windows_live/settings.php'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #b1b100;">require</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'/home/usuario/dominio/windows_live/lib/windowslivelogin.php'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #339933;">....</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></td></tr></table></div>

<p>Y finalmente el código que implementa la autenticación con Windows Live:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
&nbsp;
	<span style="color: #666666; font-style: italic;">// el fichero de configuración de la API</span>
	<span style="color: #b1b100;">require</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'/home/usuario/dominio/windows_live/settings.php'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #666666; font-style: italic;">// la librería del SDK</span>
	<span style="color: #b1b100;">require</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'/home/usuario/dominio/windows_live/lib/windowslivelogin.php'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #666666; font-style: italic;">// inicializamos las variables</span>
	<span style="color: #000088;">$wll</span> <span style="color: #339933;">=</span> WindowsLiveLogin<span style="color: #339933;">::</span><span style="color: #004000;">initFromXml</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$KEYFILE</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #000088;">$wll</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setDebug</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$DEBUG</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #000088;">$APPID</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$wll</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getAppId</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #000088;">$userid</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #666666; font-style: italic;">// comprobamos si el token de usuario está en la cookie</span>
	<span style="color: #000088;">$token</span> <span style="color: #339933;">=</span> <span style="color: #339933;">@</span><span style="color: #000088;">$_COOKIE</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$COOKIE</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
	<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #990000;">empty</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$token</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
	<span style="color: #009900;">&#123;</span>
		<span style="color: #000088;">$user</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$wll</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">processToken</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$token</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #666666; font-style: italic;">// tenemos token, intentamos sacar de él el id único del usuario</span>
		<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #990000;">empty</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$user</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
		<span style="color: #009900;">&#123;</span>
			<span style="color: #000088;">$userid</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$user</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getId</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #009900;">&#125;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #990000;">empty</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$userid</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
	<span style="color: #009900;">&#123;</span>
		<span style="color: #666666; font-style: italic;">// guardamos el id único</span>
		<span style="color: #000088;">$id_unico</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$userid</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
	<span style="color: #b1b100;">else</span>
	<span style="color: #009900;">&#123;</span>
		<span style="color: #666666; font-style: italic;">// si no tenemos token, redirigimos al usuario a la página de login de Windows Live</span>
		<span style="color: #990000;">header</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Location: http://login.live.com/wlogin.srf?appid=0000000040009631&amp;alg=wsignin1.0'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #990000;">exit</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></td></tr></table></div>

<p>Quedaría, como en el resto de APIs, hacer una gestión eficiente de los errores que se pueden dar, aunque eso ya son detalles de implementación de cada aplicación.</p>
<p>Tampoco comento nada sobre los módulos de PHP que es necesario tener activados en el servidor para hacer funcionar las APIs. En principio los únicos que considero pudieran salirse de una configuración básica son <a href="http://es.php.net/curl"><strong>curl</strong></a> y <a href="http://es.php.net/mhash"><strong>mhash</strong></a>. Curl se utiliza en la librería de Yahoo y es complicado buscarle una alternativa. Mhash se utiliza en la de Windows Live, y en este caso, siendo una extensión mucho menos común, se puede <em>puentear</em> su uso parcheando el fichero <strong>windowslivelogin.php</strong>, en concreto la línea:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1515
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$key</span> <span style="color: #339933;">=</span> <span style="color: #990000;">mhash</span><span style="color: #009900;">&#40;</span>MHASH_SHA256<span style="color: #339933;">,</span> <span style="color: #000088;">$key</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>Cambiándola para utilizar funciones del core de PHP5 que también realizan el hash binario SHA256:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1515
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$key</span> <span style="color: #339933;">=</span> <span style="color: #990000;">pack</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;H*&quot;</span><span style="color: #339933;">,</span> <span style="color: #990000;">hash</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'sha256'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$key</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>Entradas relacionadas:<ol>
<li><a href='http://www.usuariodeinternet.es/navegando/windows-live-maps-se-un-pajaro' rel='bookmark' title='Windows Live Maps: Sé un Pájaro'>Windows Live Maps: Sé un Pájaro</a></li>
<li><a href='http://www.usuariodeinternet.es/navegando/segundo-facebook-developer-garage-en-madrid' rel='bookmark' title='Segundo Facebook Developer Garage en Madrid'>Segundo Facebook Developer Garage en Madrid</a></li>
<li><a href='http://www.usuariodeinternet.es/desarrollo/nuevas-apis-de-google' rel='bookmark' title='Nuevas APIs de Google'>Nuevas APIs de Google</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.usuariodeinternet.es/desarrollo/integrar-las-apis-de-login-de-facebook-yahoo-y-windows-live/feed</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Error en la codificación con AJAX</title>
		<link>http://www.usuariodeinternet.es/desarrollo/error-en-la-codificacion-con-ajax</link>
		<comments>http://www.usuariodeinternet.es/desarrollo/error-en-la-codificacion-con-ajax#comments</comments>
		<pubDate>Tue, 09 Dec 2008 02:43:05 +0000</pubDate>
		<dc:creator>fer</dc:creator>
				<category><![CDATA[Desarrollo]]></category>
		<category><![CDATA[ajax]]></category>
		<category><![CDATA[javascript]]></category>

		<guid isPermaLink="false">http://www.usuariodeinternet.es/?p=20</guid>
		<description><![CDATA[Pelearse con la codificación de los caracteres en una aplicación web es pan nuestro de cada día. En un desarrollo sencillo uno puede olvidarse de ese detalle y dejar el trabajo de cloacas al navegador y el PHP. Pero en el momento en que entran en juego javascript y fuentes externas de datos, es entonces [...]
Entradas relacionadas:<ol>
<li><a href='http://www.usuariodeinternet.es/desarrollo/scroll-infinito-con-jquery' rel='bookmark' title='Scroll infinito con jQuery'>Scroll infinito con jQuery</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p style="text-align: center"><img title="¿Matrix utiliza UTF-8?" src="/img/post/matrix_code.jpg" border="0" alt="¿Matrix utiliza UTF-8?" width="640" height="150" /></p>
<p>Pelearse con la codificación de los caracteres en una aplicación web es pan nuestro de cada día. En un desarrollo sencillo uno puede olvidarse de ese detalle y dejar el trabajo de cloacas al navegador y el PHP. Pero en el momento en que entran en juego <strong>javascript y fuentes externas de datos</strong>, es entonces cuando la posibilidades de <strong>cagarla</strong> se multiplican.</p>
<p>Una de las formas más sencillas de prevenir problemas con la codificación es utilizar siempre <strong>UTF-8</strong> para el desarrollo completo de la aplicación. Ésto incluye la base de datos, una línea al principio de todo script:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #990000;">header</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Content-type: text/html; charset=utf-8'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>También en los HTML:</p>

<div class="wp_syntax"><div class="code"><pre class="html4strict" style="font-family:monospace;"><span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">meta</span> <span style="color: #000066;">http-equiv</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;Content-Type&quot;</span> <span style="color: #000066;">content</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;text/html; charset=UTF-8&quot;</span> <span style="color: #66cc66;">/</span>&gt;</span></pre></div></div>

<p>Y por supuesto, que el fichero esté <strong>físicamente</strong> codificado en UTF-8, cosa que cada uno deberá hacer con el editor de código correspondiente (mi experiencia con <a href="http://www.ultraedit.com/">Ultraedit</a> en este sentido es inmejorable).</p>
<p>El horror comienza cuando no has hecho los deberes, y a una aplicación sencilla se le quiere empezar a meter AJAX y datos de diversas fuentes. Por defecto tu tinglado estará utilizando seguramente <strong>ISO 8859-1</strong>, la codificación del alfabeto latino, y éso es lo que va a estar esperando el navegador a no ser que le indiques lo contrario&#8230;</p>
<p style="text-align: center"><img title="Mala codificación de los caracteres" src="/img/post/char_raros.gif" border="0" alt="Mala codificación de los caracteres" width="374" height="169" /></p>
<p>Estos problemas de codificación se pueden deber a múltiples razones, sería imposible cubrirlas todas en un post, así que me centraré en las dos con las que he tenido que lidiar estos días:</p>
<ul style="padding-left:30px;">
<li><strong>API EXTERNA</strong>. Aquí no queda otra, Si la API no ofrece un parámetro para especificar la codificación, va a venir en UTF-8 prácticamente seguro y tocará hacer en el código, por ejemplo en PHP, un <a href="http://es.php.net/utf8-decode" target="_blank">utf8_decode</a> de lo que devuelva.</li>
<li style="margin-top:15px;"><strong>AJAX</strong>. La diversión con la codificación de caracteres cuando entra en juego el javascript puede no llegar a tener límite. Si, para más inri, utilizamos AJAX para comunicar con un script pongamos de PHP, entonces tenemos todos los ingredientes para la empanada de caracteres raros.
<p style="margin-top:10px;">Obviando detalles de bajo nivel como que el objeto XMLHttpRequest que se encarga de esta comunicación utiliza siempre UTF-8, o que dependiendo de si utilizas GET o POST e Internet Explorer o Firefox se usará una codificación u otra, vemos que las combinaciones pueden marear hasta la náusea, así que hay que buscar una solución que funcione independientemente de la codificación origen-destino, el navegador o el protocolo utilizado.</p>
<p>Tras varios intentos, dí con una combinación que parece comerse cualquier barbaridad que se pueda poner en un formulario (una caja de texto que acepte código de programación, textos chinos o búlgaros&#8230; es un reto). El flujo sería el siguiente:</p>
<ol>
<li>Desde el javascript mandamos los datos codificados con la función <a href="http://xkr.us/articles/javascript/encode-compare/"><strong>encodeURIComponent</strong></a> (utilizar otra nos dará problemas con los caracteres <em>&#038;</em> y <em>+</em>), por ejemplo:

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;">ajax.<span style="color: #000066;">open</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'get'</span><span style="color: #339933;">,</span><span style="color: #3366CC;">'url_script.php?datos='</span><span style="color: #339933;">+</span>encodeURIComponent<span style="color: #009900;">&#40;</span>datos<span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span><span style="color: #003366; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

</li>
<li>Dependiendo del lenguaje de programación que se utilice en el script que recibe los datos habrá que hacer una decodificación o no de los mismos. PHP automáticamente lo realiza para lo que recibe por GET, como en este ejemplo.</li>
<li>Para devolver la respuesta, con PHP utilizamos <a href="http://es.php.net/manual/es/function.rawurlencode.php"><strong>rawurlencode</strong></a> para codificarla (esta función lo realiza de forma más estricta que <a href="http://es.php.net/manual/es/function.urlencode.php">urlencode</a>). Por ejemplo:

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #b1b100;">echo</span> <span style="color: #990000;">rawurlencode</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$respuesta</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

</li>
<li>Finalmente, de vuelta a javascript, decodificamos la respuesta con <a href="http://www.w3schools.com/jsref/jsref_decodeURIComponent.asp"><strong>decodeURIComponent</strong></a>, y ya tenemos una bonita cadena de caracteres lista para utilizar sin problemas de codificación. Por ejemplo:

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> respuesta <span style="color: #339933;">=</span> ajax.<span style="color: #660066;">responseText</span><span style="color: #339933;">;</span>
div.<span style="color: #660066;">innerHTML</span> <span style="color: #339933;">=</span> decodeURIComponent<span style="color: #009900;">&#40;</span>respuesta<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

</li>
</ol>
</li>
</ul>
<p>En definitiva, <strong>hay que utilizar UTF-8</strong>, hay que dejarle al navegador muy claro que lo estamos haciendo, y tenemos que usar una serie de métodos para que en el trasiego de la información entre distintos lenguajes y scripts no se pierda la codificación.</p>
<p>Entradas relacionadas:<ol>
<li><a href='http://www.usuariodeinternet.es/desarrollo/scroll-infinito-con-jquery' rel='bookmark' title='Scroll infinito con jQuery'>Scroll infinito con jQuery</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.usuariodeinternet.es/desarrollo/error-en-la-codificacion-con-ajax/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Plantilla personalizada para las Páginas de WordPress</title>
		<link>http://www.usuariodeinternet.es/desarrollo/plantilla-personalizada-para-las-paginas-de-wordpress</link>
		<comments>http://www.usuariodeinternet.es/desarrollo/plantilla-personalizada-para-las-paginas-de-wordpress#comments</comments>
		<pubDate>Sat, 11 Oct 2008 19:16:02 +0000</pubDate>
		<dc:creator>fer</dc:creator>
				<category><![CDATA[Desarrollo]]></category>
		<category><![CDATA[wordpress]]></category>

		<guid isPermaLink="false">http://www.usuariodeinternet.es/?p=140</guid>
		<description><![CDATA[Los que hayan utilizado WordPress para crear un blog saben que en él se pueden escribir Posts (Entradas) y Páginas. Los Posts son el núcleo del blog, y van a tener el diseño del tema que estés utilizando. Las Páginas por su parte son entidades estáticas, o más bien atemporales, que puedes añadir a la [...]
Entradas relacionadas:<ol>
<li><a href='http://www.usuariodeinternet.es/desarrollo/integrar-las-apis-de-login-de-facebook-yahoo-y-windows-live' rel='bookmark' title='Integrar las APIs de login de Facebook, Yahoo y Windows Live'>Integrar las APIs de login de Facebook, Yahoo y Windows Live</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>Los que hayan utilizado WordPress para crear un blog saben que en él se pueden escribir <strong>Posts</strong> (Entradas) y <strong>Páginas</strong>. Los Posts son el núcleo del blog, y van a tener el diseño del tema que estés utilizando. Las Páginas por su parte son entidades estáticas, o más bien atemporales, que puedes añadir a la estructura de tu blog.</p>
<p>El tema es que si ves un Post y una Página de un blog no se puede diferenciar a simple vista qué es cada cosa. Mi problema era que quería tener Páginas que cuando estuvieran publicadas no mostraran elementos propios de los Posts, como la fecha de publicación, comentarios, tags, categoría&#8230; así como la posibilidad de tunear si fuera necesario un poco la estructura que me impone el tema que utilizo.</p>
<p>Indagando un poco descubrí una <a href="http://codex.wordpress.org/Pages#Page_Templates" target="_blank">funcionalidad que ofrece WordPress para las Páginas</a>, los <strong>Page Templates</strong>. Al final es todo tan sencillo como añadir la siguientes líneas al principio de un fichero php que debes tener en la carpeta del tema que utilices:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
  <span style="color: #666666; font-style: italic;">/*
  Template Name: pagina limpia
  */</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></div></div>

<p>Lo que yo hice fue coger el fichero <em>page.php</em>, que es el que se utiliza por defecto para las Páginas, renombrarlo a <em>page-limpia.php</em>, añadirle al principio las líneas arriba mencionadas, y quitar lo que me sobraba (comentarios, fechas&#8230;). Al ir a crear una nueva página, WordPress detectará esta nueva plantilla y aparecerá una nueva opción avanzada en el editor:</p>
<p align="center"><img title="Opción en el editor para cambiar la plantilla de la Página" src="/img/post/plantilla_pagina.gif" alt="Opción en el editor para cambiar la plantilla de la Página" width="758" height="260" /></p>
<p>Entradas relacionadas:<ol>
<li><a href='http://www.usuariodeinternet.es/desarrollo/integrar-las-apis-de-login-de-facebook-yahoo-y-windows-live' rel='bookmark' title='Integrar las APIs de login de Facebook, Yahoo y Windows Live'>Integrar las APIs de login de Facebook, Yahoo y Windows Live</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.usuariodeinternet.es/desarrollo/plantilla-personalizada-para-las-paginas-de-wordpress/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Extensiones de Firefox para Programadores Web</title>
		<link>http://www.usuariodeinternet.es/desarrollo/extensiones-de-firefox-para-programadores-web</link>
		<comments>http://www.usuariodeinternet.es/desarrollo/extensiones-de-firefox-para-programadores-web#comments</comments>
		<pubDate>Wed, 28 May 2008 10:01:29 +0000</pubDate>
		<dc:creator>fer</dc:creator>
				<category><![CDATA[Desarrollo]]></category>
		<category><![CDATA[firefox]]></category>
		<category><![CDATA[navegadores]]></category>

		<guid isPermaLink="false">http://www.fernandogarciatorres.es/?p=9</guid>
		<description><![CDATA[¡Sí, yet another post sobre Las Mejores, Las Imprescindibles, Las Más Útiles&#8230; extensiones para Firefox! Soy de los que les gusta probar extensiones, y como lo suelo hacer en horario laboral (en mi tiempo de productividad leve), acabo desechando la gran mayoría y quedándome sólo con las que me ayudan en mi trabajo de desarrollador [...]
Entradas relacionadas:<ol>
<li><a href='http://www.usuariodeinternet.es/desarrollo/pon-un-messenger-o-google-talk-en-tu-web' rel='bookmark' title='Pon un Messenger o Google Talk en tu web'>Pon un Messenger o Google Talk en tu web</a></li>
<li><a href='http://www.usuariodeinternet.es/desarrollo/plantilla-personalizada-para-las-paginas-de-wordpress' rel='bookmark' title='Plantilla personalizada para las Páginas de WordPress'>Plantilla personalizada para las Páginas de WordPress</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>¡Sí, <em>yet another post</em> sobre Las Mejores, Las Imprescindibles, Las Más Útiles&#8230; extensiones para Firefox!</p>
<p>Soy de los que les gusta probar extensiones, y como lo suelo hacer en horario laboral (en mi tiempo de productividad <em>leve</em>), acabo desechando la gran mayoría y quedándome sólo con las que me ayudan en mi trabajo de <strong>desarrollador web</strong>. Muchas se han convertido para mi por su <strong>utilidad </strong>en complementos básicos del Firefox en cualquier ordenador que utilice.</p>
<p>Por lo tanto la selección que pongo a continuación va enfocada a ayudar a ese programador web <em>total</em>, el que necesita tener herramientas y control sobre todos los aspectos del desarrollo.</p>
<p><span id="more-9"></span></p>
<p><img src="/img/post/ext_firefox_desarrollador.png" alt="Extensiones de Firefox útiles para programadores web" width="261" height="989" align="left" /></p>
<p style="font-weight:bold;margin:10px 0px 10px 0px;">DESARROLLO</p>
<ul>
<li><a title="Ir a extensión Console2" href="https://addons.mozilla.org/es-ES/firefox/addon/1815" target="_blank"><strong>Console²</strong></a>: un básico antes del descubrimiento del Firebug, ya que hacía útil la consola de errores del Firefox añadiendo mucho más detalle en sus mensajes.</li>
<li><a title="Ir a extensión Firebug" href="http://www.getfirebug.com/" target="_blank"><strong>Firebug</strong></a>: la única que es sencillamente <span style="color: #000000;"><strong>BÁSICA</strong></span> para cualquier programador web. Monitor de llamadas AJAX, inspección/edición inline del DOM, debugger javascript, análisis de tráfico de red&#8230;</li>
<li><a title="Ir a extensión Web Developer" href="https://addons.mozilla.org/es-ES/firefox/addon/60" target="_blank"><strong>Web Developer</strong></a>: otra A MUST, con más funcionalidades que una minipimer. Yo la verdad la utilizo poco por Firebug, pero tiene muchas posibilidades para jugar con los elementos de la página.</li>
<li><a title="Ir a extensión Yellowpipe Lynx Viewer" href="https://addons.mozilla.org/es-ES/firefox/addon/1944" target="_blank"><strong>Yellowpipe Lynx Viewer Tool</strong></a>: muestra la página como un navegador de texto, o lo que es lo mismo, como la indexarán las arañas de los buscadores. Muy útil para tareas de SEO.</li>
<li><a title="Ir a extensión YSlow" href="http://developer.yahoo.com/yslow/" target="_blank"><strong>YSlow</strong></a>: extensión oficial de Yahoo que se basa en 13 parámetros de optimización para dar notas de rendimiento a una página. Necesita tener instalado Firebug. Muy útil para llegar al detalle máximo y sacarle punta a páginas de carga masiva.</li>
</ul>
<p style="font-weight:bold;margin:10px 0px 10px 0px;">PRODUCTIVIDAD</p>
<ul>
<li><a title="Ir a extensión Download Statusbar" href="https://addons.mozilla.org/es-ES/firefox/addon/26" target="_blank"><strong>Download Statusbar</strong></a>: el gestor de descargas por defecto de Firefox es bastante incómodo. Con esta extensión tendrás una indicador de progreso integrado en la barra de estado.</li>
<li><a title="Ir a extensión DownloadHelper" href="https://addons.mozilla.org/es-ES/firefox/addon/3006" target="_blank"><strong>DownloadHelper</strong></a>: para bajarse FLVs (entre otras cosas) con un click de ratón y sin tener que utilizar servicios de terceros.</li>
<li><a title="Ir a extensión FireShot" href="https://addons.mozilla.org/es-ES/firefox/addon/5648" target="_blank"><strong>FireShot</strong></a>: permite crear capturas de la página que estás viendo, incluso utilizar un editor gráfico básico con ellas. Muy útil la opción de crear la captura de la página ENTERA, no más capturas múltiples moviendo el scroll vertical.</li>
<li><a title="Ir a extensión PDF Download" href="https://addons.mozilla.org/es-ES/firefox/addon/636" target="_blank"><strong>PDF Download</strong></a>: lo mio con los PDFs es personal, siempre me ha supuesto un coñazo lo mucho que tarda en cargar el programa (sí, utilizo el Acrobat de Adobe&#8230;) y más de una vez me ha colgado el Firefox. Con esta extensión al acceder a un PDF te da la opción de visualizarlo, descargarlo o convertirlo a HTML.</li>
<li><a title="Ir a Google Bloc de Notas" href="http://www.google.es/notebook/download/" target="_blank"><strong>Google Bloc de Notas</strong></a>: para poder añadir notas a tu cuenta de Google Notes directamente desde Firefox. Muy útil para copiar cachos de código o ideas que convenientemente luego plagiarás en tu blog.</li>
<li><a title="Ir a extensión ShowIP" href="https://addons.mozilla.org/es-ES/firefox/addon/590" target="_blank"><strong>ShowIP</strong></a>: esta es básica en mi trabajo, donde tenemos una docena de servidores entre los que se reparten muchos servicios. Antes quemábamos el ping para adivinar la IP del servidor al que debíamos acceder para modificar algo de un canal, pero con esta extensión es inmediato ya que aparece dicha IP en la barra de estado según visitas la página.</li>
<li><a title="Ir a extensión Remember The Milk para Gmail" href="http://www.rememberthemilk.com/services/gmail/" target="_blank"><strong>Remember The Milk for Gmail</strong></a>: necesitaba un gestor de tareas MUY BÁSICO para servir de apoyo a mi memoria de pez y poder recordar mis proyectos del trabajo. Ya había oído hablar de la web <a title="Organizador de tareas" href="http://www.rememberthemilk.com/" target="_blank">rememberthemilk.com</a>, y descubrí en su propia web esta extensión que se integra perfectamente en Gmail, añadiendo un bloque a la derecha de los mensajes con tu lista de tareas pendientes, permitiendo añadir/modificarlas. Los problemas: sigo necesitando entrar a Gmail (a un click con las extensión Gmail Notifier) y que sólo funciona poniendo el idioma en inglés (al menos la versión que yo tengo instalada).</li>
</ul>
<p style="font-weight:bold;margin:10px 0px 10px 0px;">MARCADORES</p>
<ul>
<li><a title="Ir a extensión Bookmark Duplicate Detector" href="https://addons.mozilla.org/es-ES/firefox/addon/1553" target="_blank"><strong>Bookmark Duplicate Detector</strong></a>: soy de los que guarda una cantidad ingente de favoritos y tengo una memoria de pez, así que necesito esta extensión que te avisa si vas a añadir un marcador duplicado.</li>
<li><a title="Ir a extensión Foxmarks" href="http://www.foxmarks.com/" target="_blank"><strong>Foxmarks Bookmark Synchronizer</strong></a>: sincroniza automáticamente tus favoritos desde cualquier ordenador que la instales. Prefiero utilizar una extensión a servicios web como delicious porque mi objetivo es tenerlo todo integrado en el navegador, ya tengo cien pestañas abiertas y no puedo tener otra más siempre ahí. Pierdo accesibilidad desde donde quiera pero gano comodidad y rapidez.</li>
<li><a title="Ir a extensión Taboo" href="https://addons.mozilla.org/es-ES/firefox/addon/5756" target="_blank"><strong>Taboo</strong></a>: esta extensión se convierte es una capa intermedia entre la navegación y los favoritos. Sirve para marcar esas páginas que pintan interesantes y que te quieres guardar para leerlas después de comer, manteniendo tus favoritos limpios de webs de &#8220;leer y tirar&#8221;. Taboo gestiona ese listado de forma local.</li>
</ul>
<p style="font-weight:bold;margin:10px 0px 10px 0px;">DISEÑO</p>
<ul>
<li><a title="Ir a extensión ColorZilla" href="http://www.iosart.com/firefox/colorzilla/" target="_blank"><strong>ColorZilla</strong></a>: entre otras funcionalidades, la que más uso es el práctico cursor que te muestra el color en hexadecimal que selecciones en pantalla, muy útil para el berrido del diseñador &#8220;<em>¿de qué color es el fondooooo?</em>&#8220;</li>
<li><a title="Ir a extensión MeasureIt" href="https://addons.mozilla.org/es-ES/firefox/addon/539" target="_blank"><strong>MeasureIt</strong></a>: Permite de forma rápida medir en pixeles zonas en la pantalla. Esencial para otro de los grandes desafíos de los diseñadores: &#8220;<em>¿de qué tamaño quieres la imagen?</em>&#8220;</li>
</ul>
<p style="font-weight:bold;margin:10px 0px 10px 0px;">PIJADITAS</p>
<ul>
<li><a title="Ir a extensión PicLens" href="http://www.piclens.com/site/firefox/mac/" target="_blank"><strong>PicLens</strong></a>: la pijadita de la lista. Muestra con efectos bastante chulos el listado de las imágenes que hay en una web. Yo lo uso sobre todo para la búsqueda de imágenes en Google, es más rápido que la paginación.</li>
<li><a title="Ir a extensión Gmail Notifier" href="https://addons.mozilla.org/es-ES/firefox/addon/173" target="_blank"><strong>Gmail Notifier</strong></a>: muestra un pequeño popup cuando recibes un mail en la cuenta de gmail asociada. Sólo apto para la cuenta que pones en tu CV&#8230;</li>
<li><a title="Ir a extensión SearchStatus" href="https://addons.mozilla.org/es-ES/firefox/addon/321" target="_blank"><strong>SearchStatus</strong></a>: entre otras funcionalidades relacionadas con SEO, la que a mi me resulta más interesante, aunque sin mucha aplicación útil, son unos pequeños indicadores en la barra de estado que te muestran el pagerank de Google y el rank en Alexa de la página que estás visitando.</li>
<li><a title="Ir a extensión StumbleUpon" href="http://www.stumbleupon.com/" target="_blank"><strong>StumbleUpon</strong></a>: la productivity killer de la lista. Es una comunidad enorme de usuarios que recomiendan contenido de internet y lo catalogan para uso y disfrute del personal. Empieza simplemente por la categoría de Juegos y di adiós&#8230; (decir que yo la uso para buscar contenido para <a title="El canal de humor de OZÚ" href="http://humor.ozu.es" target="_blank">humor.ozu.es</a>&#8230;)</li>
<li><a title="Ir a extensión TwitterFox" href="https://addons.mozilla.org/es-ES/firefox/addon/5081" target="_blank"><strong>TwitterFox</strong></a>: yo soy de los que están todavía en el estado de &#8220;<em>¿para qué mierdas sirve el twitter este?</em>&#8221; del que no se si saldré, pero espero que esta extensión, que avisa de nuevos mensajes de mis contactos y permite mandarlos, me ayude.</li>
</ul>
<p style="margin-top:20px;">Huelga decir que el <strong>Firefox no será el navegador más liviano con todas estas extensiones</strong> instaladas. Yo con Windows XP y 1gb de RAM no he tenido nunca problemas, teniendo simultáneamente abiertas múltiples pestañas, un editor de código, el cliente FTP, telnet, messenger, reproductor de audio&#8230; ya sabéis ;)</p>
<p>Os pongo unas capturas de cómo quedan integradas el mogollón de extensiones en mi navegador:</p>
<p style="text-align:center;"><a class="lightview" style="border-bottom:0px;" title="Integración de las extensiones en la parte superior de Firefox" href="/img/post/ext_arriba_gr.gif"><img title="Todas las extensiones en la parte superior de Firefox" src="/img/post/ext_arriba.gif" alt="Todas las extensiones en la parte superior de Firefox" /></a> <a class="lightview" style="border-bottom:0px;" title="Integración de las extensiones en la parte inferior de Firefox" href="/img/post/ext_abajo_gr.gif"><img title="Todas las extensiones en la parte inferior de Firefox" src="/img/post/ext_abajo.gif" alt="Todas las extensiones en la parte inferior de Firefox" /></a></p>
<p style="margin-top:20px;"><strong style="font-size:12px;">Información Relacionada</strong></p>
<blockquote><p>Página principal del navegador Firefox: <a title="Página principal del navegador Firefox" href="http://www.mozilla-europe.org/es/products/firefox/" target="_blank">Mozilla Firefox</a><br />
Directorio de extensiones/addons de Firefox: <a title="Directorio de extensiones/addons de Firefox" href="https://addons.mozilla.org/es-ES/firefox/" target="_blank">Firefox Add-ons</a></p></blockquote>
<p>Entradas relacionadas:<ol>
<li><a href='http://www.usuariodeinternet.es/desarrollo/pon-un-messenger-o-google-talk-en-tu-web' rel='bookmark' title='Pon un Messenger o Google Talk en tu web'>Pon un Messenger o Google Talk en tu web</a></li>
<li><a href='http://www.usuariodeinternet.es/desarrollo/plantilla-personalizada-para-las-paginas-de-wordpress' rel='bookmark' title='Plantilla personalizada para las Páginas de WordPress'>Plantilla personalizada para las Páginas de WordPress</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.usuariodeinternet.es/desarrollo/extensiones-de-firefox-para-programadores-web/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Pon un Messenger o Google Talk en tu web</title>
		<link>http://www.usuariodeinternet.es/desarrollo/pon-un-messenger-o-google-talk-en-tu-web</link>
		<comments>http://www.usuariodeinternet.es/desarrollo/pon-un-messenger-o-google-talk-en-tu-web#comments</comments>
		<pubDate>Wed, 12 Mar 2008 01:50:44 +0000</pubDate>
		<dc:creator>fer</dc:creator>
				<category><![CDATA[Desarrollo]]></category>
		<category><![CDATA[google]]></category>
		<category><![CDATA[windows live]]></category>

		<guid isPermaLink="false">http://www.fernandogarciatorres.es/personal/tu-estado-en-tu-programa-de-im-en-la-web</guid>
		<description><![CDATA[Andaba buscando para una web una solución sencilla para mostrar si un usuario estaba conectado o no con su cuenta de Windows Live Messenger y, si fuera posible, la posibilidad de hablar directamente de forma anónima con él desde la misma página, es decir, complementar el típico formulario de contacto con algo más de vidilla. [...]
Entradas relacionadas:<ol>
<li><a href='http://www.usuariodeinternet.es/desarrollo/nuevas-apis-de-google' rel='bookmark' title='Nuevas APIs de Google'>Nuevas APIs de Google</a></li>
<li><a href='http://www.usuariodeinternet.es/navegando/propaganda-de-google-chrome' rel='bookmark' title='Propaganda de Google Chrome'>Propaganda de Google Chrome</a></li>
<li><a href='http://www.usuariodeinternet.es/desarrollo/extensiones-de-firefox-para-programadores-web' rel='bookmark' title='Extensiones de Firefox para Programadores Web'>Extensiones de Firefox para Programadores Web</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>Andaba buscando para una web una <strong>solución sencilla</strong> para mostrar si un usuario estaba conectado o no con su cuenta de <a href="http://get.live.com/messenger/" title="Descarga Windows Live Messenger" target="_blank">Windows Live Messenger</a> y, si fuera posible, la posibilidad de hablar directamente de forma anónima con él desde la misma página, es decir, complementar el típico formulario de contacto con algo más de vidilla. Lo primero es relativamente común, para lo segundo sólo encontraba soluciones complicadas, feas y sospechosas&#8230;</p>
<p>Al final, antes de verme tentando de probar servicios que daban miedito por pedirte tu usuario y contraseña demasiado pronto, me he dado cuenta de que la solución estaba en casa! He encontrado sendas <strong>páginas oficiales </strong>para dos de los clientes de mensajería instantánea más populares que ofrecen una interfaz para mostrar tu estado online en tu web y lo que es más importante, para poder <strong>iniciar una conversación desde la misma web</strong> sin la más mínima complicación y sin requerimientos previos:</p>
<ul>
<li><strong>Windows Live Messenger</strong>: <a href="http://msdn2.microsoft.com/en-us/library/bb936683.aspx" title="Muestra tu estado en Windows Live Messenger en tu web" target="_blank">http://msdn2.microsoft.com/en-us/library/bb936683.aspx</a><br />
Logueándote en tu cuenta de Passport podrás configurar un icono o directamente una ventana como ésta para mostrar tu estado online y permitir que los usuarios inicien una conversación directamente desde tu web:</p>
<p style="margin: 15px; text-align: center"><iframe src="http://settings.messenger.live.com/Conversation/IMMe.aspx?invitee=6b61749f5f309864@apps.messenger.live.com&amp;mkt=es-ES" style="border: 1px solid #dcdcdc; width: 300px; height: 300px" frameborder="0" height="300" width="300"></iframe></p>
</li>
<li><strong>Google Talk</strong>: <a href="http://www.google.com/talk/service/badge/New" title="Muestra tu estado en Google Talk  en tu web" target="_blank">http://www.google.com/talk/service/badge/New</a><br />
Con un diseño más sencillo, pero las mismas funcionalidades que el anterior, Google proporciona un iframe tal que así:</p>
<p style="margin: 15px; text-align: center"><iframe src="http://www.google.com/talk/service/badge/Show?tk=z01q6amlqqio7utnbm0ksfhmmo02imas55rmml24bhp8eegtli0dksd3ln9tlf3ll8dc3ukguosmug75krt8i0844psppls8dpsdhtum97k0d7n39obro8v3pb3peivi3rogaesanbkkc4kus0rtl36k5gku2lcah8l0e35pk3o5mcjqd1kbbds2jnggru5d9pg65dmb6j1em5gmkrngjsci3ov0g&amp;w=200&amp;h=60" allowtransparency="true" frameborder="0" height="60" width="200"></iframe></p>
</li>
</ul>
<p>Entradas relacionadas:<ol>
<li><a href='http://www.usuariodeinternet.es/desarrollo/nuevas-apis-de-google' rel='bookmark' title='Nuevas APIs de Google'>Nuevas APIs de Google</a></li>
<li><a href='http://www.usuariodeinternet.es/navegando/propaganda-de-google-chrome' rel='bookmark' title='Propaganda de Google Chrome'>Propaganda de Google Chrome</a></li>
<li><a href='http://www.usuariodeinternet.es/desarrollo/extensiones-de-firefox-para-programadores-web' rel='bookmark' title='Extensiones de Firefox para Programadores Web'>Extensiones de Firefox para Programadores Web</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.usuariodeinternet.es/desarrollo/pon-un-messenger-o-google-talk-en-tu-web/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Nuevas APIs de Google</title>
		<link>http://www.usuariodeinternet.es/desarrollo/nuevas-apis-de-google</link>
		<comments>http://www.usuariodeinternet.es/desarrollo/nuevas-apis-de-google#comments</comments>
		<pubDate>Fri, 29 Feb 2008 14:15:53 +0000</pubDate>
		<dc:creator>fer</dc:creator>
				<category><![CDATA[Desarrollo]]></category>
		<category><![CDATA[api]]></category>
		<category><![CDATA[google]]></category>
		<category><![CDATA[mapas]]></category>

		<guid isPermaLink="false">http://www.fernandogarciatorres.es/personal/nuevas-apis-de-google</guid>
		<description><![CDATA[Google es La Luz, el Faro de Internet que guía a necios e ignorantes hasta la Revelación. Practican su máxima de &#8220;Don&#8217;t be evil&#8221; (siempre que nos me toques las cuentas, gañán) y suelen compartir su Infinita Sabiduría con la plebe en forma de APIs que degustamos con placer. Su última ofrenda es doble, por [...]
Entradas relacionadas:<ol>
<li><a href='http://www.usuariodeinternet.es/desarrollo/pon-un-messenger-o-google-talk-en-tu-web' rel='bookmark' title='Pon un Messenger o Google Talk en tu web'>Pon un Messenger o Google Talk en tu web</a></li>
<li><a href='http://www.usuariodeinternet.es/navegando/windows-live-maps-se-un-pajaro' rel='bookmark' title='Windows Live Maps: Sé un Pájaro'>Windows Live Maps: Sé un Pájaro</a></li>
<li><a href='http://www.usuariodeinternet.es/navegando/propaganda-de-google-chrome' rel='bookmark' title='Propaganda de Google Chrome'>Propaganda de Google Chrome</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>Google es La Luz, el Faro de Internet que guía a necios e ignorantes hasta la Revelación. Practican su máxima de &#8220;<em>Don&#8217;t be evil</em>&#8221; (siempre que nos me toques las cuentas, gañán) y suelen compartir su Infinita Sabiduría con la plebe en forma de APIs que degustamos con placer. Su última ofrenda es doble, por un lado una forma de <strong>estatificar sus gloriosos mapas</strong> y por otro el acceso global a las <strong>relaciones entre las personas</strong> en Internet. Gracias, oh Google.</p>
<p><span id="more-8"></span></p>
<h2><strong><u>Mapas Estáticos con Google Maps</u></strong></h2>
<p>Esta nueva API de Google viene a ser una &#8220;involución&#8221; lógica de la archifamosa <a href="http://code.google.com/apis/maps/" title="Todos los detalles sobre Google Maps API" target="_blank">Google Maps API</a>. Ya todos sabemos el partido que se le pueden sacar a esos mapas, pero muchas veces se usan para <strong>fines muy concretos y poco sofisticados</strong>. En esos casos sobra toda la interactividad que nos ofrece la API, y es precisamento éso lo que han venido a cubrir los nuevos mapas estáticos. Su uso es insultántemente sencillo, y se reduce a utilizar la etiqueta &lt;img&gt; de HTML con un src determinado, limpio y fácil:</p>
<p style="text-align: center; font-size: 12px">&lt;<span class="start-tag">img</span><span class="attribute-name"> src</span>=<span class="attribute-value">&#8220;http://maps.google.com/staticmap?center=<font color="#ff0000">&lt;coor1&gt;</font>,<font color="#ff0000">&lt;coor2&gt;</font>&amp;zoom=<font color="#ff0000">&lt;nivel de zoom&gt;</font>&amp;size=<font color="#ff0000">&lt;ancho&gt;</font>x<font color="#ff0000">&lt;alto&gt;</font>&amp;key=<font color="#ff0000">&lt;API key&gt;</font>&#8221; </span><span class="error"><span class="attribute-name">/</span></span>&gt;</p>
<p>Esta llamada te devuelve una imagen de los servidores de Google con un bonito mapa centrado en las coordenadas dadas. Las <strong>diferencias en cuanto a rendimiento</strong> son muy claras, pongo a continuación dos capturas del análisis de la carga de dos páginas hecha con la extensión <a href="http://www.getfirebug.com/" title="Extensión Firebug para el navegador Firefox" target="_blank">Firebug</a>, ambas mostrando exáctamente el mismo punto del mapa:</p>
<p align="center"><span style="font-size: 12px">Google Maps API &#8211; ejem: <a href="http://www.desfasetotal.com/gmaps.html" title="Ejemplo de utilización de Google Maps API" target="_blank">http://www.desfasetotal.com/gmaps.html</a></span><br />
<img src="/img/post/api.gif" alt="Tiempos y objetos con google maps API" height="496" width="571" /></p>
<p align="center"><span style="font-size: 12px">Google Maps Estáticos API &#8211; ejem: <a href="http://www.desfasetotal.com/gmaps_static.html" title="Ejemplo de utilización de Google Maps API estáticos" target="_blank">http://www.desfasetotal.com/gmaps_static.html</a></span><br />
<img src="/img/post/api_estat.gif" alt="Tiempos y objetos con google maps API estática" height="156" width="570" /></p>
<p align="left">Las cifras cantan:</p>
<table style="border: 1px solid #000000; padding: 15px; margin-bottom: 10px; width: 500px" border="0">
<tr>
<td>&nbsp;</td>
<td align="right"><strong>objetos</strong></td>
<td align="right"><strong>transferencia</strong></td>
<td align="right"><strong>latencia</strong></td>
</tr>
<tr>
<td align="right"><strong>Google Maps</strong></td>
<td align="right">22</td>
<td align="right">294 KB</td>
<td align="right">4.24 seg</td>
</tr>
<tr>
<td align="right"><strong>Google Maps Estáticos</strong></td>
<td align="right">2</td>
<td align="right">61 KB</td>
<td align="right">0.7 seg</td>
</tr>
</table>
<p>Quedan muy a las claras las <strong>ventajas </strong>de esta nueva API.  Cuando el uso de los mapas se reduce a colocar un marcador en un sitio determinado, como en una web de bares para situar los locales (se pueden crear pines en las imágenes generadas añadiendo otro campo con las coordenadas en la llamada), es de uso obligatorio este nuevo método, primero por las <strong>diferencias en tiempos/peso de carga</strong>, y segundo por la <strong>sencillez de uso</strong> de la nueva llamada. Otra ventaja que puede resultar útil es la posibilidad de <strong>guardar la imagen</strong> del mapa, cosa que con la API normal de Google Maps no se puede hacer de forma directa.</p>
<p>Supongo que las dos APIs van a convivir perfectamente en muchas webs, por ejemplo un perfil de usuario que permita geolocalización utilizará la API dinámica cuando lo esté editando, y la API estática en el front para mostrar el mapa de donde me encuentro. Un servicio muy útil, sí señor.</p>
<p>Anuncio en español: <a href="http://programa-con-google.blogspot.com/2008/02/mapas-estticos-con-google-maps.html" title="Nueva API de Google para obtener mapas estáticos de Google Maps" target="_blank">Mapas estáticos con Google Maps</a></p>
<p>Web oficial de la API: <a href="http://code.google.com/apis/maps/documentation/staticmaps/index.html" title="Google Static Maps API" target="_blank">Google Static Maps API</a></p>
<p align="left">&nbsp;</p>
<h2><u><strong>API de Gráfico Social</strong></u></h2>
<p align="left"><img src="/img/post/the-web.png" webdeveloper-inline-style="border: medium none ; background: transparent none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;" alt="La nueva Social Graph API de Google" align="left" height="389" width="375" />Sería la traducción literal de esta API &#8220;social&#8221; que cuesta entender. Google se lanza a la <strong>búsqueda de relaciones</strong> en el apogeo de las redes sociales.</p>
<p align="left">Basándose en los estándares <a href="http://gmpg.org/xfn/" title="Estándar Xhtml Friends Network" target="_blank">XFN</a> (Xhtml Friends Network) y <a href="http://www.foaf-project.org/" title="The Friend of a Friend project" target="_blank">FOAF</a> (The Friend of a Friend), de forma simplificada se trata de analizar la <strong>etiqueta rel</strong> (en el caso de XFN) que se puede añadir a los enlaces de una web y los <strong>documentos FOAF</strong> para formar un gráfico social a nivel global que permita, usando la API, establecer relaciones entre las personas a través de su presencia pública en Internet.</p>
<p align="left">En la página oficial hay un video con un ejemplo muy bueno que viene a sugerir la utilidad que puede tener ésto. Pongamos que tengo un blog con una serie de enlaces a páginas de amigos a los que añado la etiqueta <em><strong>rel=&#8221;friend&#8221;</strong></em>. Un día me apunto a <a href="http://twitter.com" title="http://twitter.com" target="_blank">Twitter</a> y me encuentro hablando con la pared porque no tengo añadido a nadie. Si he puesto mi blog en mi perfil público, automáticamente el enlace aparece con la etiqueta <em><strong>rel=&#8221;me&#8221;</strong></em>. Pues bien, Twitter puede desarrollar una aplicación utilizando la API de Google de manera que me pueda sugerir añadir a gente de mi &#8220;red social&#8221; que ya están registrados en el portal. Google sabe por la etiqueta <em>rel=&#8221;me&#8221;</em> que tengo un blog y desde él ve que tengo también una serie de amigos por la etiqueta <em>rel=&#8221;friends&#8221;</em>. Al final aquellos que estén registrados en Twitter y hayan puesto la dirección de su página en su perfil cerrarán el círculo de mi minigrafo social aplicado a Twitter.</p>
<p>Es lioso y a mi por ahora no se me ocurre una aplicación realmente útil que pueda usar en nuestros proyectos, aparte del hecho de depender de que se adopte algunos de los estándares citados para poder establecer las relaciones, pero estoy seguro que en este panorama de Red Social esta API dará que hablar.</p>
<p>Web oficial de la API: <a href="http://code.google.com/apis/socialgraph/" title="Google Social Graph API" target="_blank">Social Graph API</a></p>
<p>Entradas relacionadas:<ol>
<li><a href='http://www.usuariodeinternet.es/desarrollo/pon-un-messenger-o-google-talk-en-tu-web' rel='bookmark' title='Pon un Messenger o Google Talk en tu web'>Pon un Messenger o Google Talk en tu web</a></li>
<li><a href='http://www.usuariodeinternet.es/navegando/windows-live-maps-se-un-pajaro' rel='bookmark' title='Windows Live Maps: Sé un Pájaro'>Windows Live Maps: Sé un Pájaro</a></li>
<li><a href='http://www.usuariodeinternet.es/navegando/propaganda-de-google-chrome' rel='bookmark' title='Propaganda de Google Chrome'>Propaganda de Google Chrome</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.usuariodeinternet.es/desarrollo/nuevas-apis-de-google/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

