<?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>Enrique Chávez Garcia- Desarrollo de Web &#187; Flex 4</title>
	<atom:link href="http://tmeister.net/category/flex-4/feed/" rel="self" type="application/rss+xml" />
	<link>http://tmeister.net</link>
	<description>Blog acerca de desarrollo orientado hacia Flash, Flex y Actionscript.</description>
	<lastBuildDate>Thu, 19 Jan 2012 20:25:41 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	
		<item>
		<title>Air 2.0 Conexi&#243;n IMAP mediante SecureSocket</title>
		<link>http://tmeister.net/2010/02/26/air-2-0-conexin-imap-mediante-securesocket/</link>
		<comments>http://tmeister.net/2010/02/26/air-2-0-conexin-imap-mediante-securesocket/#comments</comments>
		<pubDate>Sat, 27 Feb 2010 01:56:24 +0000</pubDate>
		<dc:creator>Tmeister</dc:creator>
				<category><![CDATA[ActionScript]]></category>
		<category><![CDATA[Adobe AIR]]></category>
		<category><![CDATA[AS3]]></category>
		<category><![CDATA[Ejemplos]]></category>
		<category><![CDATA[Flex 4]]></category>
		<category><![CDATA[AIR 2.0]]></category>
		<category><![CDATA[FlashBuilder]]></category>

		<guid isPermaLink="false">http://tmeister.net/?p=546</guid>
		<description><![CDATA[Una de las nuevas características de Adobe Air 2.0 es la conexión a servidores mediante sockets encriptados (SSL). Uno de los servicios mas comunes que utiliza una conexión encriptado son los proveedores de correo usando IMAP. Para este ejemplo vamos a conectarnos al servidor IMAP de Gmail y obtener el numero de mensajes nuevos y [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://tmeister.net/wp-content/uploads/2010/02/Adobe_Air-logo-8BE840B3A1.gif" alt="" title="Adobe_Air-logo-8BE840B3A1" width="200" height="200" class="alignright size-full wp-image-548" /><br />
Una de las nuevas características de Adobe Air 2.0 es la conexión a servidores mediante sockets encriptados (SSL).</p>
<p>Uno de los servicios mas comunes que utiliza una conexión encriptado son los proveedores de correo usando IMAP.</p>
<p>Para este ejemplo vamos a conectarnos al servidor IMAP de Gmail y obtener el numero de mensajes nuevos y mensajes en total que existen en nuestra cuenta.</p>
<p>Para fines prácticos de este ejemplo necesitamos:</p>
<ul>
<li>Una cuenta de Gmail, <a href="http://mail.google.com/mail/#settings/fwdandpop">con IMAP habilitado</a></li>
<li><a href="http://labs.adobe.com/technologies/flashbuilder4/">FlashBuilder</a></li>
<li><a href="http://labs.adobe.com/technologies/air2/">Adobe AIR 2.0</a></li>
</ul>
<p><span style="font-family: Georgia;">Lo primero es crear una interfaz sencilla en donde se pueda insertar el nombre de usuario, la contraseña, campos de output y un boton para iniciar el proceso.</span></p>
<pre class="brush: xml; light: true; title: ; notranslate">
	&lt;s:Label x=&quot;10&quot; y=&quot;17&quot; text=&quot;Gmail username:&quot;/&gt;
	&lt;s:Label x=&quot;10&quot; y=&quot;45&quot; text=&quot;Gmail password:&quot;/&gt;
	&lt;s:TextInput y=&quot;10&quot; id=&quot;username_txt&quot; change=&quot;_username = username_txt.text&quot; right=&quot;10&quot; left=&quot;120&quot;/&gt;
	&lt;s:TextInput y=&quot;40&quot; id=&quot;password_txt&quot; change=&quot;_password = password_txt.text&quot; displayAsPassword=&quot;true&quot; right=&quot;10&quot; left=&quot;120&quot;/&gt;
	&lt;s:Button y=&quot;70&quot; label=&quot;Tell me!!&quot; click=&quot;start()&quot; right=&quot;10&quot;/&gt;
	&lt;s:Label x=&quot;10&quot; y=&quot;100&quot; width=&quot;280&quot; id=&quot;result_txt&quot;/&gt;
	&lt;s:TextArea id=&quot;out_txt&quot; editable=&quot;false&quot; right=&quot;10&quot; bottom=&quot;10&quot; top=&quot;130&quot; left=&quot;10&quot;/&gt;
</pre>
<p><span id="more-546"></span></p>
<p>El resultado de esto se ve de esta forma:</p>
<div align="center">
<img src="http://tmeister.net/wp-content/uploads/2010/02/gmailSSL.png" alt="" title="gmailSSL" width="308" height="280" class="aligncenter size-full wp-image-547" />
</div>
<p>Despues de tener nuestra interfaz vamos a declarar todas la variables y constantes que vamos a necesitar:</p>
<pre class="brush: as3; light: true; title: ; notranslate">
			/******************************************************************
			 *	Datos de la cuenta (Gmail IMAP)
			 * ***************************************************************/

			private static const INCOMING_SERVER:String = &quot;imap.gmail.com&quot;;
			private static const PORT:int = 993;
			private var _username:String = &quot;&quot;;
			private var _password:String = &quot;&quot;;

			/******************************************************************
			 * Socket &amp;&amp; Stuff
			 * ***************************************************************/ 

			private var _server:Socket;
			private var _buffer:ByteArray;
			private var _action:String;
			private var _totalMessages:String;
			private var _newMessages:String;

			/******************************************************************
			 * Respuestas del servidor (para filtar el contenido)
			 * http://tools.ietf.org/html/draft-gahrns-imap-namespace-00
			 * ****************************************************************/

			private static const CONNECT:String = &quot;*&quot;;
			private static const LOGIN:String = &quot;A002&quot;;
			private static const STATUS:String = &quot;A006&quot;;
			private static const CRLF:String = &quot;\r\n&quot;;
			private var _regSearch:RegExp = RegExp(&quot;\\&quot;+_action+&quot;\\r\\n&quot;);
</pre>
<p>Aqui hay un par de cosas que debo resaltar:</p>
<pre class="brush: as3; light: true; title: ; notranslate">
			private var _buffer:ByteArray;
</pre>
<p>En esta variable almacenaremos las respuestas que nos envié el servidor.</p>
<pre class="brush: as3; light: true; title: ; notranslate">
			private var _regSearch:RegExp = RegExp(&quot;\\&quot;+_action+&quot;\\r\\n&quot;);
</pre>
<p>Con esta expresion regular verificaremos si el mensaje que recibimos del servidor es util para nosotros.</p>
<pre class="brush: as3; light: true; title: ; notranslate">
			private static const CONNECT:String = &quot;*&quot;;
			private static const LOGIN:String = &quot;A002&quot;;
			private static const STATUS:String = &quot;A006&quot;;
</pre>
<p>Estas constantes son los identificadores de los mensajes que se mandan desde y hacia el servidor para saber mas de estos identificadores recomiendo esta lectura <a href="http://tools.ietf.org/html/draft-gahrns-imap-namespace-00">http://tools.ietf.org/html/draft-gahrns-imap-namespace-00</a></p>
<p>Ahora nos queda inicializar nuestro socket y crear los eventos que usaremos para comunicarnos con el servidor</p>
<pre class="brush: as3; light: true; title: ; notranslate">
				_server = new SecureSocket();
				_server.addEventListener(Event.CONNECT, onConnect);
				_server.addEventListener(Event.CLOSE, onClose);
				_server.addEventListener(ProgressEvent.SOCKET_DATA, onData);
				_server.addEventListener(IOErrorEvent.IO_ERROR, onIOError);
</pre>
<p>El único cambio con respecto a trabajar con Sockets sin encriptar es el constructor de la clase en lugar de usar </p>
<pre class="brush: as3; light: true; title: ; notranslate">
				_server = new Socket();
</pre>
<p>Ahora debemos utilizar</p>
<pre class="brush: as3; light: true; title: ; notranslate">
				_server = new SecureSocket();
</pre>
<p>Así de simple; Bien, hemos seteado los listeners para CONNECT, SOCKET_DATA, CLOSE y IO_ERROR vamos a concentranos solamente en SOCKET_DATA que es el evento que se dispara al momento de recibir un mensaje del servidor.</p>
<pre class="brush: as3; light: true; title: ; notranslate">
			private function onData(e:ProgressEvent):void
			{
				out_txt.text += &quot;Data &quot; + e+&quot;\n&quot;;
				var socket:Socket = e.target as Socket;
				var bufferString:String;
				socket.readBytes(_buffer, _buffer.length, socket.bytesAvailable);
				bufferString = _buffer.toString();
				out_txt.text += &quot;SERVER: &quot; + _buffer.toString()+&quot;\n&quot;;
				if (  bufferString.search( _regSearch ) )
				{
					out_txt.text += &quot;Es una respuesta valida parsea\n&quot;;
					parseResponse();
				}
				cursorManager.removeBusyCursor()
			}
</pre>
<p>En esta función recibimos el evento y tomamos el contenido del mensaje mediante el método readBytes y lo almacenamos en la variable _buffer</p>
<pre class="brush: as3; light: true; title: ; notranslate">
				socket.readBytes(_buffer, _buffer.length, socket.bytesAvailable);
</pre>
<p>Verificamos que el mensaje corresponda a nuestra petición, en este caso solo usamos 3 peticiones CONNECT, LOGIN, STATUS y si el mensaje es correcto parseamos el contenido.</p>
<p>El primer mensaje que recibimos del servidor es el de conexión</p>
<p><strong>SERVER: * OK Gimap ready for requests from 189.216.40.184 14if7528374pzk.62</strong></p>
<p>Una vez que estemos conectados mandamos nuestras credenciales para que el servidor nos autentique y cambiamos el mensaje a LOGIN indicando que estamos esperando el mensaje de respuesta de la solicitud de logueo.</p>
<pre class="brush: as3; light: true; title: ; notranslate">
				if ( _action == CONNECT )
				{
					out_txt.text += &quot;Es es tag de conexion manda login\n&quot;;
					_server.writeUTFBytes(LOGIN + &quot; LOGIN &quot; + _username + &quot; &quot; + _password + CRLF);
					_action = LOGIN;
					_server.flush();
					return;
				}
</pre>
<p>Se envia el mensaje y de inmediato recibimos la respuesta del servidor, en caso de login correcto:</p>
<p><strong>A002 OK tmeister@gmail.com authenticated (Success)</strong></p>
<p>Si es incorrecto:</p>
<p><strong>A002 NO [ALERT] Invalid credentials (Failure)</strong></p>
<p>Con esto es muy fácil saber el resultado de la operación, usemos indexOf para saber si la palabra &#8220;OK&#8221; existe</p>
<pre class="brush: as3; light: true; title: ; notranslate">
				if ( _action == LOGIN )
				{
					out_txt.text += &quot;Es la respuesta del login\n&quot;;
					if( bufferString.indexOf(&quot;OK&quot;) != -1 )
					{
						out_txt.text += &quot;El login es correcto, estamos autenticados - Pedir correos sin leer\n&quot;;
						_action = STATUS;
						_server.writeUTFBytes(STATUS + &quot; STATUS inbox (MESSAGES UNSEEN)&quot; + CRLF);
						_server.flush();
					}else
					{
						out_txt.text += &quot;Ooops!! Las credenciales no son validas.\n&quot;;
						Alert.show(&quot;Ooops!! Las credenciales no son validas.&quot;, &quot;Error&quot;);
						_server.close();
					}
					return;
				}
</pre>
<p>Excelente estamos autenticados, Ahora que? solo nos falta pedir el estatus de la cuenta pidiendo los mensajes totales y los mensajes nuevos de la carpeta Inbox</p>
<pre class="brush: as3; light: true; title: ; notranslate">
						_server.writeUTFBytes(STATUS + &quot; STATUS inbox (MESSAGES UNSEEN)&quot; + CRLF);
</pre>
<p>El ultimo paso es recibir el mensaje del servidor con la información que pedimos y parsearla, al ser texto solo tenemos que usar indexOf y substring para acceder a lo que nos interesa</p>
<p><strong>STATUS &#8220;inbox&#8221; (MESSAGES 61298 UNSEEN 5)</strong></p>
<pre class="brush: as3; light: true; title: ; notranslate">
				if( _action == STATUS )
				{
					out_txt.text += &quot;Es la respuesta del Status &quot; + bufferString+&quot;\n&quot;;
					var startSub:int = bufferString.indexOf(&quot;(&quot;);
					var endSub:int = bufferString.indexOf(&quot;)&quot;);
					var message:String = bufferString.substring(startSub+1, endSub);
					var slides:Array = message.split(&quot; &quot;);
					var count:int = 0;
					for each( var slide:String in slides )
					{
						switch( slide )
						{
							case &quot;MESSAGES&quot;:
								_totalMessages = slides[count + 1];
								break;
							case &quot;UNSEEN&quot;:
								_newMessages = slides[count + 1];
								break;
						}
						count++;
					}
					result_txt.text = _newMessages + &quot; mensajes nuevos, de &quot; + _totalMessages + &quot; en total&quot;;
					out_txt.text += _totalMessages;
					out_txt.text += _newMessages;
					_action = null;
					_server.close();
				}
			}
</pre>
<p>Sin duda, lo mas complejo al momento de trabajar con Sockets es saber utilizar e implementar el protocolo de comunicación pero esa ya es otra historia.</p>
<p>Por ultimo les dejo el código completo</p>
<pre class="brush: as3; title: ; notranslate">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;s:WindowedApplication xmlns:fx=&quot;http://ns.adobe.com/mxml/2009&quot;
					   xmlns:s=&quot;library://ns.adobe.com/flex/spark&quot;
					   xmlns:mx=&quot;library://ns.adobe.com/flex/halo&quot;
					   creationComplete=&quot;init(event)&quot;
					    width=&quot;300&quot; height=&quot;250&quot;&gt;
	&lt;fx:Script&gt;
		&lt;![CDATA[
			import flash.events.Event;
			import flash.events.IOErrorEvent;
			import flash.events.MouseEvent;
			import flash.events.ProgressEvent;
			import flash.net.SecureSocket;
			import flash.net.Socket;
			import flash.utils.ByteArray;

			import mx.controls.Alert;
			import mx.events.FlexEvent;

			private static const INCOMING_SERVER:String = &quot;imap.gmail.com&quot;;
			private static const PORT:int = 993;
			private var _username:String = &quot;&quot;;
			private var _password:String = &quot;&quot;;

			private var _server:Socket;
			private var _buffer:ByteArray;
			private var _action:String;
			private var _totalMessages:String;
			private var _newMessages:String;

			private static const CONNECT:String = &quot;*&quot;;
			private static const LOGIN:String = &quot;A002&quot;;
			private static const STATUS:String = &quot;A006&quot;;
			private static const CRLF:String = &quot;\r\n&quot;;
			private var _regSearch:RegExp = RegExp(&quot;\\&quot;+_action+&quot;\\r\\n&quot;);

			protected function init(event:FlexEvent):void
			{

				_server = new SecureSocket();
				_server.addEventListener(Event.CONNECT, onConnect);
				_server.addEventListener(Event.CLOSE, onClose);
				_server.addEventListener(ProgressEvent.SOCKET_DATA, onData);
				_server.addEventListener(IOErrorEvent.IO_ERROR, onIOError);

				_buffer = new ByteArray()
			}
			private function onConnect(e:Event):void
			{
				out_txt.text += &quot;Conexion establecida &quot; + e.toString()+&quot;\n&quot;;
			}
			private function onClose(e:Event):void
			{
				out_txt.text += &quot;Conexion cerrada &quot; + e+&quot;\n&quot;;
			}
			private function onData(e:ProgressEvent):void
			{
				out_txt.text += &quot;Data &quot; + e+&quot;\n&quot;;
				var socket:Socket = e.target as Socket;
				var bufferString:String;
				socket.readBytes(_buffer, _buffer.length, socket.bytesAvailable);
				bufferString = _buffer.toString();
				out_txt.text += &quot;SERVER: &quot; + _buffer.toString()+&quot;\n&quot;;
				if (  bufferString.search( _regSearch ) )
				{
					out_txt.text += &quot;Es una respuesta valida parsea\n&quot;;
					parseResponse();
				}
				cursorManager.removeBusyCursor()
			}
			private function onIOError(e:IOErrorEvent):void
			{
				out_txt.text += &quot;IOError &quot; + e+&quot;\n&quot;;
			}

			private function parseResponse():void
			{
				var bufferString:String = _buffer.toString();
				_buffer.clear();
				if ( _action == CONNECT )
				{
					out_txt.text += &quot;Es es tag de conexion manda login\n&quot;;
					_server.writeUTFBytes(LOGIN + &quot; LOGIN &quot; + _username + &quot; &quot; + _password + CRLF);
					_action = LOGIN;
					_server.flush();
					return;
				}
				if ( _action == LOGIN )
				{
					out_txt.text += &quot;Es la respuesta del login\n&quot;;
					if( bufferString.indexOf(&quot;OK&quot;) != -1 )
					{
						out_txt.text += &quot;El login es correcto, estamos autenticados - Pedir correos sin leer\n&quot;;
						_action = STATUS;
						_server.writeUTFBytes(STATUS + &quot; STATUS inbox (MESSAGES UNSEEN)&quot; + CRLF);
						_server.flush();
					}else
					{
						out_txt.text += &quot;Ooops!! Las credenciales no son validas.\n&quot;;
						Alert.show(&quot;Ooops!! Las credenciales no son validas.&quot;, &quot;Error&quot;);
						_server.close();
					}
					return;
				}
				if( _action == STATUS )
				{
					out_txt.text += &quot;Es la respuesta del Status &quot; + bufferString+&quot;\n&quot;;
					var startSub:int = bufferString.indexOf(&quot;(&quot;);
					var endSub:int = bufferString.indexOf(&quot;)&quot;);
					var message:String = bufferString.substring(startSub+1, endSub);
					var slides:Array = message.split(&quot; &quot;);
					var count:int = 0;
					for each( var slide:String in slides )
					{
						switch( slide )
						{
							case &quot;MESSAGES&quot;:
								_totalMessages = slides[count + 1];
								break;
							case &quot;UNSEEN&quot;:
								_newMessages = slides[count + 1];
								break;
						}
						count++;
					}
					result_txt.text = _newMessages + &quot; mensajes nuevos, de &quot; + _totalMessages + &quot; en total&quot;;
					out_txt.text += _totalMessages;
					out_txt.text += _newMessages;
					_action = null;
					_server.close();
				}
			}

			private function start():void
			{
				out_txt.text = &quot;iniciando Conexion\n&quot;;
				if( _server != null &amp;&amp; _server.connected )
				{
					_server.close();
				}
				if( _username.length &amp;&amp; _password.length )
				{
					_action = CONNECT;
					_server.connect(INCOMING_SERVER, PORT);
					cursorManager.setBusyCursor();
				}else
				{
					Alert.show(&quot;Escribe tus credenciales..&quot;, &quot;Error&quot;);
				}
			}

		]]&gt;
	&lt;/fx:Script&gt;
	&lt;s:Label x=&quot;10&quot; y=&quot;17&quot; text=&quot;Gmail username:&quot;/&gt;
	&lt;s:Label x=&quot;10&quot; y=&quot;45&quot; text=&quot;Gmail password:&quot;/&gt;
	&lt;s:TextInput y=&quot;10&quot; id=&quot;username_txt&quot; change=&quot;_username = username_txt.text&quot; right=&quot;10&quot; left=&quot;120&quot;/&gt;
	&lt;s:TextInput y=&quot;40&quot; id=&quot;password_txt&quot; change=&quot;_password = password_txt.text&quot; displayAsPassword=&quot;true&quot; right=&quot;10&quot; left=&quot;120&quot;/&gt;
	&lt;s:Button y=&quot;70&quot; label=&quot;Tell me!!&quot; click=&quot;start()&quot; right=&quot;10&quot;/&gt;
	&lt;s:Label x=&quot;10&quot; y=&quot;100&quot; width=&quot;280&quot; id=&quot;result_txt&quot;/&gt;
	&lt;s:TextArea id=&quot;out_txt&quot; editable=&quot;false&quot; right=&quot;10&quot; bottom=&quot;10&quot; top=&quot;130&quot; left=&quot;10&quot;/&gt;
&lt;/s:WindowedApplication&gt;
</pre>
<h1>Descarga</h1>
<p>Rendering of template dTemplate.php failed</p>
<p>Espero les sea de ayuda y nos estamos leyendo.</p>
]]></content:encoded>
			<wfw:commentRss>http://tmeister.net/2010/02/26/air-2-0-conexin-imap-mediante-securesocket/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Obtener tweets usando PHP &amp; Flex 4 (Gumbo)</title>
		<link>http://tmeister.net/2009/12/09/obtener-tweets-usando-php-flex-4-gumbo/</link>
		<comments>http://tmeister.net/2009/12/09/obtener-tweets-usando-php-flex-4-gumbo/#comments</comments>
		<pubDate>Wed, 09 Dec 2009 23:17:49 +0000</pubDate>
		<dc:creator>Tmeister</dc:creator>
				<category><![CDATA[Flex 4]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[twitter]]></category>
		<category><![CDATA[api ejemplo]]></category>

		<guid isPermaLink="false">http://tmeister.net/?p=512</guid>
		<description><![CDATA[En este ejemplo, ya no muy básico, les mostrare como obtener los últimos tweets de un usuario y mostrarlos en Flex 4 (Gumbo) para ello haremos uso de PHP como gateway, con PHP obtendremos los tweets por medio del API de Twitter y los desplegaremos en forma de XML para poder leerlos en Flex. Este ejemplo esta hecho [...]]]></description>
			<content:encoded><![CDATA[<p>En este <a href="http://tmeister.net/category/flex-4/">ejemplo</a>, ya no muy básico, les mostrare como obtener los últimos tweets de un usuario y mostrarlos en <a href="http://tmeister.net/category/flex-4/">Flex 4 (Gumbo)</a> para ello haremos uso de PHP como gateway, con PHP obtendremos los tweets por medio del <a href="http://apiwiki.twitter.com/">API de Twitter</a> y los desplegaremos en forma de XML para poder leerlos en Flex.</p>
<div class="info">Este ejemplo esta hecho con <a href="http://labs.adobe.com/technologies/flashbuilder4/" target="_blank">Flash Builder 4 Beta 2</a> y necesita el <a href="https://www.adobe.com/go/getflashplayer">FlashPlayer 10</a> para poder visualizarlo correctamente</div>
<h1>Ejemplo</h1>
<div>
<object width="600" height="350">
<param name="movie" value="http://tmeister.net/flex/gumbo/last-tweet/tweets.swf"></param>
<param name="quality" value="high"></param>
<param name="wmode" value="transparent"></param>
<param name="menu" value="false"></param>
<param name="bgcolor" value="#ffffff"></param>
<param name="allowScriptAccess" value="always"></param>
<param name="allowFullScreen" value="true"></param>
<embed type="application/x-shockwave-flash" width="600" height="350" src="http://tmeister.net/flex/gumbo/last-tweet/tweets.swf" quality="high" bgcolor="#ffffff" wmode="transparent" menu="false" allowFullScreen="true" ></embed>
</object>
</div>
<p>Lo primero que necesitamos es crear el script en PHP para poder conectarnos al <a href="http://apiwiki.twitter.com/">API de Twitter</a>, obtener los tweets y desplegarlos en XML.</p>
<h1>PHP</h1>
<pre class="brush: php; title: ; notranslate">
&lt;?php
/**
 * get_user_tweets()
 *
 * @param mixed $username
 * @param integer $count
 * @return array $out
 */
function get_user_tweets($username, $count = 10)
{
	/**
	 * URL para obtener los tweets en formato JSON
	 * Utilizaremos curl para hacer la conexion al API de Twitter
	 * */
	$url = 'http://twitter.com/statuses/user_timeline/'.$username.'.json?count='.$count;
	$curl = curl_init();

	/**
	 * Iniciamos CURL pasando que URL vamos a cargar
	 * */
	curl_setopt($curl, CURLOPT_URL, $url);
	/**
	 * Indicamos que querremos el output de regreso
	 * */
	curl_setopt ($curl, CURLOPT_RETURNTRANSFER, 1);
	/**
	 * Ponemos un TimeOut al script
	 */
	curl_setopt ($curl, CURLOPT_CONNECTTIMEOUT, 10);

	/**
	 * Ejecutamos CURL
	 */
	$json = curl_exec($curl);

	/**
	 * Cerramos la conexion
	 */
	curl_close($curl);

	/**
	 * Tomanos el resultado (JSON) y lo parseamos en PHP
	 */
	$tweets = json_decode($json);
	$out;

	/**
	 * Por ultimo por cada tweet tomanos el contenido y lo metemos en un Array
	 */
	foreach($tweets as $tweet)
	{
		$out[] = $tweet-&gt;text;
	}

	return $out;
}

/**
 * Con la informacion obtenida del API construimos un XML y lo mostramos
 */
$out = '&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf8&quot;?&gt;';
$out .= &quot;&lt;tweets&gt;&quot;;
$tweets = get_user_tweets('tmeister', 10);
foreach($tweets as $tweet)
{
	$out .= &quot;&lt;tweet&gt;$tweet&lt;/tweet&gt;&quot;;
}
$out .= &quot;&lt;/tweets&gt;&quot;;
header (&quot;content-type: text/xml&quot;);
echo $out;
?&gt;
</pre>
<p>El resultado del script lo puedes ver en <a href="http://tmeister.net/flex/gumbo/last-tweet/last.php">http://tmeister.net/flex/gumbo/last-tweet/last.php</a></p>
<h1>MXML</h1>
<p>Una vez que tenemos el XML solo falta mostrar su contenido en Flex.</p>
<pre class="brush: xml; title: ; notranslate">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;s:Application
    xmlns:fx=&quot;http://ns.adobe.com/mxml/2009&quot;
    xmlns:s=&quot;library://ns.adobe.com/flex/spark&quot;
    xmlns:mx=&quot;library://ns.adobe.com/flex/halo&quot;
    width=&quot;100%&quot;
    height=&quot;100%&quot;
    creationComplete=&quot;{service.send()}&quot;
    viewSourceURL=&quot;http://tmeister.net/flex/gumbo/last-tweet/srcview/index.html&quot;
    &gt;

    &lt;fx:Script&gt;
        &lt;![CDATA[
            import mx.collections.ArrayCollection;
            import mx.controls.Alert;
            import mx.rpc.events.FaultEvent;
            import mx.rpc.events.ResultEvent;

            [Bindable]
            private var _tweets:ArrayCollection;

            protected function service_resultHandler(event:ResultEvent):void
            {

                _tweets = new ArrayCollection();

                for each( var tweet:String in event.result.tweet  )
                {
                    _tweets.addItem(tweet);
                }
            }

            protected function service_faultHandler(event:FaultEvent):void
            {
                Alert.show(event.fault.faultString, &quot;Error&quot;);
            }

        ]]&gt;
    &lt;/fx:Script&gt;

    &lt;fx:Declarations&gt;
        &lt;s:HTTPService
            id=&quot;service&quot;
            result=&quot;service_resultHandler(event)&quot;
            fault=&quot;service_faultHandler(event)&quot;
            url=&quot;http://tmeister.net/flex/gumbo/last-tweet/last.php&quot;
            showBusyCursor=&quot;true&quot;
            resultFormat=&quot;e4x&quot;
            &gt;
        &lt;/s:HTTPService&gt;
    &lt;/fx:Declarations&gt;

    &lt;mx:VBox verticalCenter=&quot;0&quot; horizontalCenter=&quot;0&quot;&gt;
        &lt;mx:Repeater id=&quot;rep&quot; dataProvider=&quot;{_tweets}&quot;&gt;
            &lt;s:Label text=&quot;{rep.currentItem}&quot; /&gt;
            &lt;mx:HRule width=&quot;100%&quot; /&gt;
        &lt;/mx:Repeater&gt;
    &lt;/mx:VBox&gt;

&lt;/s:Application&gt;
</pre>
<p>Con esto ya podemos mostrar los últimos tweets de un timeline sin necesidad de usar librerias ni de PHP o de ActionScript.</p>
]]></content:encoded>
			<wfw:commentRss>http://tmeister.net/2009/12/09/obtener-tweets-usando-php-flex-4-gumbo/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Cambiando el symbolColor en el &#8220;Spark CheckBox&#8221;</title>
		<link>http://tmeister.net/2009/12/08/cambiando-el-symbolcolor-en-el-spark-checkbox/</link>
		<comments>http://tmeister.net/2009/12/08/cambiando-el-symbolcolor-en-el-spark-checkbox/#comments</comments>
		<pubDate>Tue, 08 Dec 2009 14:00:20 +0000</pubDate>
		<dc:creator>Tmeister</dc:creator>
				<category><![CDATA[Ejemplos]]></category>
		<category><![CDATA[Flex 4]]></category>
		<category><![CDATA[checkbox]]></category>
		<category><![CDATA[Gumbo]]></category>
		<category><![CDATA[spark]]></category>
		<category><![CDATA[symbolColor]]></category>

		<guid isPermaLink="false">http://tmeister.net/?p=492</guid>
		<description><![CDATA[Este es una entrada de la serie de ejemplos basicos de Flex 4 (Gumbo) En el siguiente ejemplo les mostrare como pueden cambiar el color de la marca de seleccion de un Spark Checkbox en Flex 4, asi como el basecolor de fondo y el texto del label. Este ejemplo esta hecho con Flash Builder [...]]]></description>
			<content:encoded><![CDATA[<p>Este es una entrada de la <a href="http://tmeister.net/category/flex-4/">serie de ejemplos basicos de Flex 4</a> (Gumbo)</p>
<p>En el siguiente ejemplo les mostrare como pueden cambiar el color de la marca de seleccion de un Spark Checkbox en Flex 4, asi como el <a href="http://tmeister.net/2009/12/07/cambiando-el-color-de-fondo-del-spark-button" target="_blank">basecolor de fondo</a> y el texto del label.</p>
<div class="info">Este ejemplo esta hecho con <a href="http://labs.adobe.com/technologies/flashbuilder4/" target="_blank">Flash Builder 4 Beta 2</a> y necesita el <a href="https://www.adobe.com/go/getflashplayer">FlashPlayer 10</a> para poder visualizarlo correctamente</div>
<h1>Ejemplo</h1>
<div>
<object width="600" height="200">
<param name="movie" value="http://tmeister.net/flex/gumbo/checkbox/checkBox.swf"></param>
<param name="quality" value="high"></param>
<param name="wmode" value="transparent"></param>
<param name="menu" value="false"></param>
<param name="bgcolor" value="#ffffff"></param>
<param name="allowScriptAccess" value="always"></param>
<param name="allowFullScreen" value="true"></param>
<embed type="application/x-shockwave-flash" width="600" height="200" src="http://tmeister.net/flex/gumbo/checkbox/checkBox.swf" quality="high" bgcolor="#ffffff" wmode="transparent" menu="false" allowFullScreen="true" ></embed>
</object>
</div>
<p>Para ello usaremos las propiedades</p>
<ul>
<li>symbolColor</li>
<li><a href="http://tmeister.net/2009/12/07/cambiando-el-color-de-fondo-del-spark-button">baseColor</a></li>
<li>color</li>
</ul>
<h1>MXML</h1>
<pre class="brush: xml; title: ; notranslate">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;s:Application
    xmlns:fx=&quot;http://ns.adobe.com/mxml/2009&quot;
    xmlns:s=&quot;library://ns.adobe.com/flex/spark&quot;
    xmlns:mx=&quot;library://ns.adobe.com/flex/halo&quot;
    width=&quot;100%&quot; height=&quot;100%&quot;
 &gt;
   &lt;mx:ApplicationControlBar width=&quot;100%&quot; cornerRadius=&quot;0&quot;&gt;
        &lt;s:Label text=&quot;baseColor:&quot; /&gt;
        &lt;mx:ColorPicker id=&quot;colorPickerBase&quot; selectedColor=&quot;#cccccc&quot; /&gt;
        &lt;s:Label text=&quot;symbolColor:&quot; /&gt;
        &lt;mx:ColorPicker id=&quot;colorPickerSymbol&quot; selectedColor=&quot;#000000&quot; /&gt;
        &lt;s:Label text=&quot;textColor:&quot; /&gt;
        &lt;mx:ColorPicker id=&quot;colorPickerText&quot; selectedColor=&quot;#000000&quot; /&gt;
    &lt;/mx:ApplicationControlBar&gt;

    &lt;s:CheckBox
        label=&quot;Spark CheckBox&quot;
        selected=&quot;true&quot;
        baseColor=&quot;{colorPickerBase.selectedColor}&quot;
        symbolColor=&quot;{colorPickerSymbol.selectedColor}&quot;
        color=&quot;{colorPickerText.selectedColor}&quot;
        horizontalCenter=&quot;0&quot; verticalCenter=&quot;0&quot;
    /&gt;

&lt;/s:Application&gt;
</pre>
]]></content:encoded>
			<wfw:commentRss>http://tmeister.net/2009/12/08/cambiando-el-symbolcolor-en-el-spark-checkbox/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Cambiando el color de fondo del &#8220;Spark Button&#8221;</title>
		<link>http://tmeister.net/2009/12/07/cambiando-el-color-de-fondo-del-spark-button/</link>
		<comments>http://tmeister.net/2009/12/07/cambiando-el-color-de-fondo-del-spark-button/#comments</comments>
		<pubDate>Mon, 07 Dec 2009 21:05:43 +0000</pubDate>
		<dc:creator>Tmeister</dc:creator>
				<category><![CDATA[Flex 4]]></category>
		<category><![CDATA[BaseColor]]></category>
		<category><![CDATA[Button]]></category>
		<category><![CDATA[Ejemplos]]></category>
		<category><![CDATA[Gumbo]]></category>

		<guid isPermaLink="false">http://tmeister.net/?p=475</guid>
		<description><![CDATA[Con este post comenzare una serie de ejemplos básicos para irnos metiendo a lo nuevo de Flex 4 (aka Gumbo), su nuevo modelo de componentes y nuevas características. En este primer ejemplo mostrare como se puede cambiar el &#8220;baseColor&#8221; o background del componente Spark Button. Antes de continuar cabe resaltar que estos ejemplo estan hechos [...]]]></description>
			<content:encoded><![CDATA[<p>Con este post comenzare una serie de <strong>ejemplos básicos</strong> para irnos metiendo a lo nuevo de Flex 4 (aka Gumbo), su nuevo modelo de componentes y nuevas características.</p>
<p>En este primer ejemplo mostrare como se puede cambiar el &#8220;baseColor&#8221; o background del componente Spark Button.</p>
<div class="info">Antes de continuar cabe resaltar que estos ejemplo estan hechos con <a href="http://labs.adobe.com/technologies/flashbuilder4/" target="_blank">Flash Builder 4 Beta 2</a> y se necesita el <a href="https://www.adobe.com/go/getflashplayer">FlashPlayer 10</a> para poder visualizarlos correctamente</div>
<h1>Ejemplo</h1>
<div>
<object width="600" height="200">
<param name="movie" value="http://tmeister.net/flex/gumbo/basecolor/baseColor.swf"></param>
<param name="quality" value="high"></param>
<param name="wmode" value="transparent"></param>
<param name="menu" value="false"></param>
<param name="bgcolor" value="#ffffff"></param>
<param name="allowScriptAccess" value="always"></param>
<param name="allowFullScreen" value="true"></param>
<embed type="application/x-shockwave-flash" width="600" height="200" src="http://tmeister.net/flex/gumbo/basecolor/baseColor.swf" quality="high" bgcolor="#ffffff" wmode="transparent" menu="false" allowFullScreen="true" ></embed>
</object>
</div>
<p>Hay 3 maneras como podemos cambiar el baseColor, usando MXML, Actionscript o CSS.</p>
<h1>MXML</h1>
<p>Este es el source del ejemplo anterior.</p>
<pre class="brush: xml; title: ; notranslate">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;

&lt;s:Application
    xmlns:fx=&quot;http://ns.adobe.com/mxml/2009&quot;
    xmlns:s=&quot;library://ns.adobe.com/flex/spark&quot;
    xmlns:mx=&quot;library://ns.adobe.com/flex/halo&quot;
    width=&quot;100%&quot; height=&quot;100%&quot;
&gt;
    &lt;mx:ApplicationControlBar width=&quot;100%&quot;&gt;
        &lt;s:Label text=&quot;baseColor: &quot; /&gt;
        &lt;mx:ColorPicker id=&quot;colorSelector&quot; selectedColor=&quot;#cccccc&quot; /&gt;
    &lt;/mx:ApplicationControlBar&gt;

    &lt;s:Button
        id=&quot;button&quot;
        baseColor=&quot;{colorSelector.selectedColor}&quot;
        horizontalCenter=&quot;0&quot;
        verticalCenter=&quot;0&quot;
        label=&quot;baseColor&quot;
    /&gt;

&lt;/s:Application&gt;
</pre>
]]></content:encoded>
			<wfw:commentRss>http://tmeister.net/2009/12/07/cambiando-el-color-de-fondo-del-spark-button/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

<!-- Performance optimized by W3 Total Cache. Learn more: http://www.w3-edge.com/wordpress-plugins/

Object Caching 564/614 objects using disk: basic

Served from: tmeister.net @ 2012-02-04 03:36:35 -->

<!-- W3 Total Cache: Db cache debug info:
Engine:             disk: basic
Total queries:      31
Cached queries:     4
Total query time:   0.0198
SQL info:
    # | Time (s) |    Caching (Reject reason)     |   Status   | Data size (b) | Query
    1 |   0.0009 |  disabled (Query is rejected)  | not cached |             0 | SHOW TABLES LIKE 'wp_tla_data'
    2 |    0.001 |  disabled (Query is rejected)  | not cached |             0 | SHOW COLUMNS FROM wp_tla_data LIKE 'xml_key'
    3 |   0.0005 |            enabled             |   cached   |          4215 | SELECT * FROM wp_tla_data
    4 |   0.0003 |            enabled             | not cached |           714 | SELECT post_modified_gmt FROM wp_posts WHERE post_status = 'publish' AND post_type IN ('post', 'page', 'attachment', 'slideshow', 'portfolio') ORDER BY post_modified_gmt DESC LIMIT 1
    5 |   0.0002 |            enabled             | not cached |           698 | SELECT post_date_gmt FROM wp_posts WHERE post_status = 'publish' AND post_type IN ('post', 'page', 'attachment', 'slideshow', 'portfolio') ORDER BY post_date_gmt DESC LIMIT 1
    6 |   0.0002 |            enabled             | not cached |           675 | SELECT wp_term_taxonomy.term_id
					FROM wp_term_taxonomy
					INNER JOIN wp_terms USING (term_id)
					WHERE taxonomy = 'category'
					AND wp_terms.slug IN ('flex-4')
    7 |   0.0002 |            enabled             | not cached |           693 | SELECT term_taxonomy_id
					FROM wp_term_taxonomy
					WHERE taxonomy = 'category'
					AND term_id IN (64,63)
    8 |   0.0002 |            enabled             | not cached |          3459 | SELECT t.*, tt.* FROM wp_terms AS t INNER JOIN wp_term_taxonomy AS tt ON t.term_id = tt.term_id WHERE tt.taxonomy = 'category' AND t.slug = 'flex-4' LIMIT 1
    9 |   0.0013 |  disabled (Query is rejected)  | not cached |             0 | SELECT SQL_CALC_FOUND_ROWS  wp_posts.* FROM wp_posts  INNER JOIN wp_term_relationships ON (wp_posts.ID = wp_term_relationships.object_id) WHERE 1=1  AND ( wp_term_relationships.term_taxonomy_id IN (76,77) ) AND wp_posts.post_type = 'post' AND (wp_posts.post_status = 'publish') GROUP BY wp_posts.ID ORDER BY wp_posts.post_date DESC LIMIT 0, 15
   10 |   0.0053 |  disabled (Query is rejected)  | not cached |             0 | SELECT FOUND_ROWS()
   11 |   0.0003 |            enabled             |   cached   |          3459 | SELECT t.*, tt.* FROM wp_terms AS t INNER JOIN wp_term_taxonomy AS tt ON t.term_id = tt.term_id WHERE tt.taxonomy = 'category' AND t.slug = 'flex-4' LIMIT 1
   12 |   0.0002 |            enabled             | not cached |          4578 | SELECT t.*, tt.* FROM wp_terms AS t INNER JOIN wp_term_taxonomy AS tt ON tt.term_id = t.term_id INNER JOIN wp_term_relationships AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tt.taxonomy IN ('category') AND tr.object_id IN (546) ORDER BY t.name ASC
   13 |   0.0002 |            enabled             | not cached |          3830 | SELECT t.*, tt.* FROM wp_terms AS t INNER JOIN wp_term_taxonomy AS tt ON tt.term_id = t.term_id INNER JOIN wp_term_relationships AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tt.taxonomy IN ('post_tag') AND tr.object_id IN (546) ORDER BY t.name ASC
   14 |   0.0002 |            enabled             | not cached |          5449 | SELECT wp_drainhole_files.*,wp_drainhole_version.version,wp_drainhole_version.created_at FROM wp_drainhole_files INNER JOIN wp_drainhole_version ON (wp_drainhole_files.version_id=wp_drainhole_version.id OR wp_drainhole_files.version_id=0) AND wp_drainhole_files.id='11' GROUP BY id
   15 |   0.0002 |            enabled             | not cached |          3073 | SELECT wp_drainhole_holes.*,SUM(wp_drainhole_files.hits) AS hits,COUNT(wp_drainhole_files.id) AS files FROM wp_drainhole_holes LEFT JOIN wp_drainhole_files ON wp_drainhole_holes.id=wp_drainhole_files.hole_id WHERE wp_drainhole_holes.id=3 GROUP BY wp_drainhole_holes.id
   16 |   0.0001 |            enabled             | not cached |          2006 | SELECT post_id, meta_key, meta_value FROM wp_postmeta WHERE post_id IN (546)
   17 |   0.0004 |            enabled             |   cached   |          5449 | SELECT wp_drainhole_files.*,wp_drainhole_version.version,wp_drainhole_version.created_at FROM wp_drainhole_files INNER JOIN wp_drainhole_version ON (wp_drainhole_files.version_id=wp_drainhole_version.id OR wp_drainhole_files.version_id=0) AND wp_drainhole_files.id='11' GROUP BY id
   18 |   0.0003 |            enabled             |   cached   |          3073 | SELECT wp_drainhole_holes.*,SUM(wp_drainhole_files.hits) AS hits,COUNT(wp_drainhole_files.id) AS files FROM wp_drainhole_holes LEFT JOIN wp_drainhole_files ON wp_drainhole_holes.id=wp_drainhole_files.hole_id WHERE wp_drainhole_holes.id=3 GROUP BY wp_drainhole_holes.id
   19 |   0.0003 |            enabled             | not cached |         25487 | SELECT * FROM wp_posts WHERE ID = 546 LIMIT 1
   20 |   0.0002 |            enabled             | not cached |          4058 | SELECT t.*, tt.* FROM wp_terms AS t INNER JOIN wp_term_taxonomy AS tt ON tt.term_id = t.term_id INNER JOIN wp_term_relationships AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tt.taxonomy IN ('category') AND tr.object_id IN (512) ORDER BY t.name ASC
   21 |   0.0011 |            enabled             | not cached |          4078 | SELECT t.*, tt.* FROM wp_terms AS t INNER JOIN wp_term_taxonomy AS tt ON tt.term_id = t.term_id INNER JOIN wp_term_relationships AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tt.taxonomy IN ('post_tag') AND tr.object_id IN (512) ORDER BY t.name ASC
   22 |   0.0004 |            enabled             | not cached |          1814 | SELECT post_id, meta_key, meta_value FROM wp_postmeta WHERE post_id IN (512)
   23 |   0.0008 |            enabled             | not cached |         14100 | SELECT * FROM wp_posts WHERE ID = 512 LIMIT 1
   24 |   0.0006 |            enabled             | not cached |          3817 | SELECT t.*, tt.* FROM wp_terms AS t INNER JOIN wp_term_taxonomy AS tt ON tt.term_id = t.term_id INNER JOIN wp_term_relationships AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tt.taxonomy IN ('category') AND tr.object_id IN (492) ORDER BY t.name ASC
   25 |   0.0018 |            enabled             | not cached |          4576 | SELECT t.*, tt.* FROM wp_terms AS t INNER JOIN wp_term_taxonomy AS tt ON tt.term_id = t.term_id INNER JOIN wp_term_relationships AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tt.taxonomy IN ('post_tag') AND tr.object_id IN (492) ORDER BY t.name ASC
   26 |   0.0007 |            enabled             | not cached |          1814 | SELECT post_id, meta_key, meta_value FROM wp_postmeta WHERE post_id IN (492)
   27 |   0.0004 |            enabled             | not cached |         11436 | SELECT * FROM wp_posts WHERE ID = 492 LIMIT 1
   28 |   0.0002 |            enabled             | not cached |          3562 | SELECT t.*, tt.* FROM wp_terms AS t INNER JOIN wp_term_taxonomy AS tt ON tt.term_id = t.term_id INNER JOIN wp_term_relationships AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tt.taxonomy IN ('category') AND tr.object_id IN (475) ORDER BY t.name ASC
   29 |   0.0008 |            enabled             | not cached |          4570 | SELECT t.*, tt.* FROM wp_terms AS t INNER JOIN wp_term_taxonomy AS tt ON tt.term_id = t.term_id INNER JOIN wp_term_relationships AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tt.taxonomy IN ('post_tag') AND tr.object_id IN (475) ORDER BY t.name ASC
   30 |   0.0002 |            enabled             | not cached |          1925 | SELECT post_id, meta_key, meta_value FROM wp_postmeta WHERE post_id IN (475)
   31 |   0.0003 |            enabled             | not cached |         10673 | SELECT * FROM wp_posts WHERE ID = 475 LIMIT 1
-->

<!-- W3 Total Cache: Page cache debug info:
Engine:             disk: enhanced
Cache key:          category/flex-4/feed/_index.html
Caching:            disabled
Reject reason:      DONOTCACHEPAGE constant is defined
Status:             not cached
Creation Time:      0.595s
Header info:
X-Pingback:         http://tmeister.net/xmlrpc.php
Last-Modified:      Thu, 19 Jan 2012 20:25:41 GMT
ETag:               "5128b61493d147f8e15e42f284d2c6d2"
X-Powered-By:       W3 Total Cache/0.9.2.4
Content-Type:       text/xml; charset=utf-8
-->
