lunes, 4 de enero de 2016

Utilizando la clase MemoryStream con imágenes en GTK# y MonoDevelop

El mecanismo de comunicación entre las aplicaciones .NET y los dispositivos de entrada y de salida se realiza mediante streams (flujos secuenciales) de bytes que se obtienen de una fuente de entrada hacia la aplicación y salen de la aplicación hacia una fuente de salida, pensemos en los flujos como corrientes de agua que van de un recipiente a otro.

Dentro del ensamblado System.IO existe la clase abstracta Stream que implementa operaciones de lectura y escritura sincrónica y asíncrona y que sirve como base para cualquier clase derivada que sea utilizada en operaciones de entrada y salida, como ejemplos de clases derivadas tenemos a FileStream, CriptoStream, NetworkStream, BufferedStream y MemoryStream. De estas clases la clase MemoryStream proporciona una área de almacenamiento temporal en memoria o sea un arreglo de bytes sin signo, entre sus usos más comunes se encuentran las operaciones con imágenes, la compresión y descompresión de archivos, el cifrado/descifrado de datos y la serialización entre otros.

Algunas propiedades y métodos de la clase MemoryStream:

    Read: Inicia la operación de lectura de forma secuencial de un número de bytes desde el inicio hasta el final del flujo.
  • ReadByte: Idéntico que Read solo que lee un byte de forma secuencial.
  • Length: Es la longitud en bytes del flujo.
  • Position: Obtiene la posición del apuntador lector del flujo.
  • ReadTimeOut: Se refiere al tiempo de espera para operaciones de lectura.
  • WriteTimeOut: Igual que ReadTimeOut solo que para operaciones de escritura.
  • Flush: Vacia el contenido de los buffers del flujo y obliga a que se escriban en el flujo.
  • GetBuffer: Regresa un arreglo de bytes sin signo que fueron utilizados para crear el flujo.
  • Seek: Coloca el apuntador lector del flujo en una determinada posición.

La clase MemoryStream se considera una buena solución siempre que se trate con grandes cantidades de datos y se requiera una rápida lectura y escritura de los mismos. Un detalle importante es que si en el constructor de la clase se establece el tamaño del arreglo, después no es posible cambiar el tamaño. Por eso es mejor utilizar un constructor vacío e ir utilizando el arreglo según se requiera.

Como ejemplo de su uso, utilizamos una sencilla proyecto GTK# de monodevelop que lee una imagen del disco duro, crea una copia de la imagen en un flujo memorystream para que esa imagen pueda ser ajustada a las medidas que el usuario proporcione y después pueda guardarla con el formato que elija de la aplicación. El diseño del GUI (Graphical User Interface) de la aplicación se muestra en la siguiente imagen, utilizando el designer de MonoDevelop.

Para este proyecto es necesario hacer referencias a los ensamblados: System.Drawing, System.Drawing.Image, System.IO como se muestra en la siguiente imagen:

Al oprimir F5 (Debug) ó Ctrl + F5 en Monodevelop se ejecutará la aplicación como se ve en la siguiente imagen:

Cuando se presiona el botón de “Select image” se ve el FileDialog para escoger la imagen desde el disco duro:

Una vez seleccionada la imagen se mostrará dentro del programa, aunque esa imagen no son los bytes originales del archivo sino los bytes que están contenidos en el buffer del objeto MemoryStream.

Una vez cargada la imagen puedes redimensionarla (en pixeles) de acuerdo a la anchura y la altura que teclees en los valores de los campos de texto width y height. Al presionar el botón “Change size”la imagen se ajustará a las nuevas dimensiones.

Una segunda imagen como ejemplo con diferentes medidas:

Puedes guardar la imagen modificada con utilizando uno de los formatos que están en los radiobuttons

Al presionar el botón “Save As” se abrirá un cuadro de dialogo (filechooser) para guardar la imagen en cualquier parte del sistema de archivos.

Podemos ver la imagen guardada en el sistema de archivos.

La aplicación inicia cuando se escoge un archivo de imagen del sistema de archivos para obtener su matriz de bytes. Esto lo hacemos con el siguiente código:

 byte[] GetBytesFromFile(string filename){
 byte[] imgBytes;
 using(FileStream fis = 
new FileStream(filename,FileMode.Open,FileAccess.Read))
 {
  BinaryReader reader = new BinaryReader(fis);
  imgBytes = reader.ReadBytes((int)fis.Length);
  reader.Close();
 }
  return imgBytes;
 } 

Entonces podemos esa matriz de bytes en el flujo MemoryStream y colocamos su buffer en el control (widget) Image.

 ms = new MemoryStream(fileBytes);
image2.Pixbuf = new Gdk.Pixbuf(ms.ToArray()); 

Aquí ya la aplicación esta lista para redimensionar la imagen esto se logra con el código del evento para el botón “Change Size”.

 protected virtual void OnBtnMakeThumbClicked (object sender, System.EventArgs e)
 {
  int w,h;
  try{
   if(!string.IsNullOrEmpty(txtWidth.Text) && 
      !string.IsNullOrEmpty(txtHeight.Text))
   {
    w = Convert.ToInt32(txtWidth.Text);
    h = Convert.ToInt32(txtHeight.Text);
    Bitmap bitmap = new Bitmap(ms);
    System.Drawing.Image.GetThumbnailImageAbort thumbnailCallback = 
    new System.Drawing.Image.GetThumbnailImageAbort(delegate(){ return false; });
    System.Drawing.Image thumbnail = bitmap.GetThumbnailImage(w,h,thumbnailCallback,IntPtr.Zero);
    byte[] thumbnailBytes = 
((byte[])new ImageConverter().ConvertTo(thumbnail,typeof(byte[])));
    ms = new MemoryStream(thumbnailBytes);
    image2.Pixbuf = new Gdk.Pixbuf(ms.ToArray());
   }
   else
    ShowMessageBox("width & height must be integers.");
  }catch(ApplicationException ex){
   ShowMessageBox(ex.Message);
  }
 } 

En este código se utiliza el método GetThumbnailImage de la clase Image:

 System.Drawing.Image thumbnail = bitmap.GetThumbnailImage(w,h,thumbnailCallback,IntPtr.Zero); 

NOTA: para este código hay que poner toda la ruta de los ensamblados para la clase image ya que exiten dos clases Image una en el ensamblado Gtk y otra en el ensambaldo System.Drawing por lo que hay que diferenciarlas o el compilador se confundirá.

De nueva cuenta se convierte la imagen en una matriz de bytes y la ponemos dentro del buffer del objeto MemoryStream, para después ponerla en el widget de imagen, esto lo realiza las siguientes líneas de código:

 
byte[] thumbnailBytes = 
((byte[])new ImageConverter().ConvertTo(thumbnail,typeof(byte[])));
 ms = new MemoryStream(thumbnailBytes);
image2.Pixbuf = new Gdk.Pixbuf(ms.ToArray()); 

Por último el código del botón para guardar la imagen en el sistema de archivos con el formato seleccionado en los botones de radio.

 protected virtual void OnBtnSaveAsClicked (object sender, System.EventArgs e)
 {
  string filename = null;
  ImageFormat imageFormat = (rbjpg.Active ? ImageFormat.Jpeg : (rbwmf.Active ? ImageFormat.Wmf:
                (rbpng.Active ? ImageFormat.Png : ImageFormat.Bmp)));
  try{
   Gtk.FileChooserDialog fc=  new Gtk.FileChooserDialog("Save image",
                              this,
                              FileChooserAction.Save,
                              "Cancel",ResponseType.Cancel,
                              "Save",ResponseType.Accept);
   if (fc.Run() == (int)ResponseType.Accept) 
{
    filename = fc.Filename + "." + imageFormat.ToString();
    fc.Hide();
    fc.Dispose();
    using(FileStream foutput = 
new FileStream(filename,FileMode.Create,FileAccess.Write))
   {
     Bitmap bmp = new Bitmap(ms);
     bmp.Save(foutput,imageFormat);
    }
   }
   else{
    fc.Hide();
    fc.Dispose();
   }
   
  }catch(Exception ex){
   ShowMessageBox(ex.Message);
  }
 } 

Aquí se utiliza la clase FileStream la cual representa un flujo hacia un archivo para guardar la imagen que se construye a partir de la matriz de imagen del buffer del objeto MemoryStream.

using(FileStream foutput = 
new FileStream(filename,FileMode.Create,FileAccess.Write))
{
 Bitmap bmp = new Bitmap(ms);
 bmp.Save(foutput,imageFormat);
}

Obteniendo las características del browser en ASP.NET

La portabilidad en el browser (navegador) ha sido siempre un tema discutible desde los primeros inicios del desarrollo Web.

Aunque durante todos estos años han habido avances en el uso de estándares para el desarrollo Web y los niveles de incompatibilidad en los navegadores se han disminuido, no se puede garantizar que una página o interfaz web conserve su aspecto (look-and-feel) o sus funcionalidades en todos los dispositivos y navegadores cliente que la muestren.

Es por eso que las aplicaciones ASP.NET con frecuencia necesitan conocer las características del browser (navegador) para ejecutar un código personalizado que se asegure que una página funcionará correctamente independientemente del navegador donde se despliegue.

Para consultar los tipos de browser y sus características ASP .NET consulta la clase HttpBrowserCapabilities, este objeto encapsula la información que envía el cliente durante una petición HTTP.

Con el siguiente código se ejemplifica la utilización de esta clase en una página ASP .NET que despliega la información del browser.

Fig 1. El código markup del programa.

Toda la funcionalidad se encuentra al consultar la clase Request.Browser que regresa una clase System.Web.HttpBrowserCapabilities.

Fig 2. El código de la clase C# (CodeBehind).

Al ejecutar la página ASP.NET, el resultado es el siguiente:

martes, 22 de diciembre de 2015

Utilizando Clamav Antivirus en GNU Linux OpenSuse

Siempre ha sido un eje de debate si existen o no los códigos maliciosos (virus, gusanos, etc.) para GNU/Linux , sea cierto o falso, lo verdadero es que siempre es conveniente tener un buen antivirus instalado en el sistema y más si se se ocupa como servidor de correo o servidor de archivos para otros sistemas operativos, sin un antivirus estaremos esparciendo código malicioso por la organización sin darnos cuenta.

Un antivirus es un programa que detecta cierta actividad sospechosa en la computadora, como el acceso a un disco de almacenamiento, la firma de un código malicioso en memoria o un intento para borrar o modificar un archivo, etc.

Hoy día existen varias opciones de antivirus para Linux, siendo ClamAv antivirus (www.clamav.net) una de las más reconocidas y utilizadas, por ofrecer las siguientes características:

  • Open source GNU Public License version 2
  • Escaneo rápido (fast scanning)
  • POSIX compatible
  • Detecta aprox 1 millon de virus, gusanos y troyanos incluyendo los virus de macro de microsoft Office, malware, etc.
  • Escaneo dentro de archivos comprimidos. (zip,rar, 7zip, arj,tar,gzip,bzip2, sfx, cab, etc)

Los dos comandos básicos para empezar a utilizar este antivirus son freshclam y clamscan. El primero actualiza la base de datos de definiciones de códigos maliciosos y el segundo escanea los archivos en su búsqueda.

Lo primero que debe hacerse antes de escanear cualquier archivo o directorio, es actualizar la lista de definiciones de virus.

NOTA: Si un antivirus no tiene actualizada su lista de definiciones, es totalmente inservible.

Para actualizar las definiciones ejecutamos el siguiente comando como root

    # freshclam
  

como un usuario sin privilegios esto se ejecuta de la siguiente forma:

    $ sudo root freshclam
  

Bien ya una vez que actualizamos las definiciones podemos proceder a escanear con el comando clamscan de la siguiente manera:

   clamscan [options] [filename or directory]
  

Por ejemplo para escanear un archivo ejecutable de Windows llamado IPEYE.EXE utilizamos el siguiente comando:

   $ clamscan IPEYE.EXE
  

Cuando ClamAv encuentra un código malicioso en el archivo escaneado, muestra el nombre del código entre el nombre de este archivo y la palabra FOUND, tal como se muestra en la imagen.

Para escanear todos los archivos en el directorio actual, utilizamos el siguiente comando:

   $ clamscan
  

A manera de una guía rápida, aquí presento una lista de las opciones más útiles para utilizar ClamAV:

1) Para escanear todos los archivos desde la raíz, pero unicamente mostrar los archivos infectados y al detectar una amenaza hacer sonar una alerta.

    $ clamscan -r --bell -i /
   

2) para escanear todos los archivos dentro del directorio /home.

    $ clamscan -r /home
   

3) para escanear todos los archivos dentro del directorio /home/martin y mover los archivos infectados al directorio /home/martin/quarantine.

    $ clamscan -r --move=/home/martin/quarantine /home/martin 
   

4) para escanear todos los archivos del directorio /home/martin y eliminar los archivos infectados.

    $ clamscan -r /home/martin --remove
   

5) Para escanear todos los archivos dentro del directorio /home/martin y copiar los archivos al directorio /home/martin/quarantine.

    $ clamscan -r --copy=/home/martin/quarantine /home/martin
   

6) Para escanear los archivos línea a línea contenidos en un archivo de texto llamado: [files2scan.txt]

    $ clamscan -file-list=files2scan.txt
   

Es importante mencionar que ClamAV únicamente escaneara los archivos en donde el usuario tenga permisos, si se requiere un escaneo completo de todo el sistema se deberá ejecutar con una cuenta con permisos de superusuario.

Si tienes un virus no detectado por ClamAV incluso con la última actualización de sus definiciones, favor de envialo a la siguiente dirección: http://www.clamav.net/sendvirus

domingo, 13 de diciembre de 2015

Agregando el soporte para diagramas en SQL Server

Cuando se hacen ciertas operaciones sobre una base de datos, por ejemplo al restaurarla de un respaldo o recrearla con un script,etc. Para que después cuando se intente realizar un diagrama ER en el diseñador nos envié el siguiente mensaje:

Este mensaje se refiere sobre la propiedad que un usuario tiene sobre un schema (esquema), un schema solo puede tener un unico dueño en la base de datos. Y cuando se requiera otorgar el permiso de propiedad a un nuevo usuario , el usuario con el permiso anterior pierde su propiedad. Para cambiar la propiedad de un schema a un usuario se ejecuta el siguiente comando:

use [myDataBase]
go
ALTER AUTHORIZATION ON DATABASE::[myDataBase] TO [newUser] 

Aquí un ejemplo de como poner como dueño al usuario [sa] de una base de datos llamada [Books].

use [Books]
go
ALTER AUTHORIZATION ON DATABASE::[Books] TO [sa] 

Al ejecutar con éxito este comando ya es posible instalar el soporte para diagramas en SQL Server y crear un nuevo diagrama.

miércoles, 25 de noviembre de 2015

Utilizando los controles Kendo UI DatePicker y TimePicker

Otro par de controles muy útiles incluidos en la suite de controles Kendo UI, son los controles Kendo UI DatePicker y TimePicker con estos controles se logra que las interfaces web tengan una apariencia intuitiva y muy profesional como si se tratase de una aplicación de escritorio (Desktop).

Kendo UI DatePicker

Este control proporciona una manera muy intuitiva para la selección de una fecha, tiene un campo de texto en donde puedes teclear la fecha deseada o bien seleccionarla de un calendario dropdown que aparece al momento de activar el control, como muestro en la siguiente imagen.

Kendo UI DateTimePicker

Este control es similar al DateTimePicker, permite teclear horas y segundos o bien seleccionarlo de una lista de las horas del día, como muestro en la siguiente imagen.

Ahora como ejemplo del uso de estos controles pondré el código de un formulario que tiene un control DatePicker, un DateTimePicker y unos radiobuttons que configuran la fecha y la hora de los controles según la opción seleccionada. La configuración de este ejemplo es igual a la configuración utilizada para el ejemplo de este post.. Aquí el código fuente JavaScript (dateTimeSample.js):

Aquí el código fuente de la página HTML:

Al ejecutarlo en el navegador lo veremos como en la siguiente imagen

Observamos como los controles datePicker y dateTimePicker cambian sus valores según la opción seleccionada en los radiobuttons. En la imagen al seleccionar la opción “yesterday”

Al seleccionar la opción “Last 24 hours” vemos el resultado en la siguiente imagen

Enlaces relacionados:

domingo, 18 de octubre de 2015

Utilizando el Kendo UI Grid de Telerik con JQuery

Uno de los conjuntos de controles que he encontrado con más frecuencia en los desarrollos profesionales de sistemas son sin duda el conjunto de los controles Telerik, Telerik ofrece una amplia gama de controles para diseñar la interfaz gráfica de usuario o GUI (Graphical User Interface) en diferentes frameworks de .NET como: WPF, ASP.NET, Windows Form o Silverlight.

Voy a mostrar una breve utilización básica del kendo UI Grid con un formulario que hace una petición mediante JQuery a un servidor web en este caso Apache.

Paso 1:
Voy a crear un directorio de trabajo llamado “KendoUISamples” debajo de ~/public_html que es el directorio predeterminado por OpenSuSe para ser el sitio web del usuario, todo lo que está dentro de ese directorio se publica en Apache con la siguiente dirección: http://127.0.0.1/~martin/

Paso 2:
Dentro de ese directorio voy a crear un archivo de texto llamado "Authors.js" que contendrá los siguientes datos en formato JSON:

   [
  {"Id" : "1",  "Name" : "George", "LastName": "Orwell",
  "BirthDate" : "1903-01-25","Gender" : "true" },
  {"Id" : "2",  "Name" : "Norman", "LastName": "Mailer",
  "BirthDate" : "1976-01-31","Gender" : "true" },
  {"Id" : "3",  "Name" : "Richard","LastName": "Dawkins",
  "BirthDate" : "1941-03-26","Gender" : "true" },
  {"Id" : "4",  "Name" : "Doris",  "LastName": "Lessing",
  "BirthDate" : "1919-10-22","Gender" : "false" },
  {"Id" : "5",  "Name" : "Stephen","LastName": "Hawkins",
  "BirthDate" : "1942-01-08","Gender" : "true" },
  {"Id" : "6",  "Name" : "Carl",   "LastName": "Sagan",
  "BirthDate" : "1934-11-09","Gender":"true" },
  {"Id" : "7",  "Name" : "William","LastName": "Gibson",
  "BirthDate" : "1948-03-17","Gender":"true" },
  {"Id" : "8",  "Name" : "Arthur", "LastName": "C. Clarke",
  "BirthDate": "1917-12-16","Gender":"true" },
  {"Id" : "9",  "Name" : "Leonard","LastName": "Mlodinow",
  "BirthDate": "","Gender":"true" },
  {"Id" : "10", "Name" : "Grary",  "LastName": "Booch",
  "BirthDate": "1955-02-27","Gender":"true" },
  {"Id" : "11", "Name" : "James",  "LastName": "Rumbaugh",
  "BirthDate": "1947-08-22","Gender":"true" },
  {"Id" : "12", "Name" : "Ivar",   "LastName": "Jacobson",
  "BirthDate": "1939-09-02","Gender":"true" }
  ]
      
Estos datos servirán para ser el DataSource del control Kendo UI Grid que voy a mostrar. El directorio de trabajo se verá como en la siguiente imagen:

Paso 3:

Descargamos el HTML5 Boiler template (ver este post) y lo descomprimimos dentro del directorio de trabajo para que se genere la estructura básica de un proyecto Front-End HTML5, se verá una estructura como en la siguiente imagen

Paso 4:
Copiamos los archivos css y js de JQuery y Kendo UI Telerik a los directorios css y js que están en el directorio de trabajo para tener una estructura como la que se muestra en la imagen

Paso 5:
Completamos el código del archivo [index.html] con las siguientes líneas dentro de las etiquetas <head> y </head> para incluir a los archivos css y js de JQuery y Telerik para que que queden de la siguiente manera:

 <head>  
   <meta charset="utf-8">  
   <meta http-equiv="x-ua-compatible" content="ie=edge">  
   <title>Kendo Grid example 1.0</title>  
   <link rel="stylesheet" href="css/kendo/kendo.common.min.css">  
      <link rel="stylesheet" href="css/kendo/kendo.bootstrap.min.css">  
      <script src="js/jquery-1.11.3.min.js"></script>  
      <script src="js/kendo.all.min.js"></script>  
      <script src="js/kendo.aspnetmvc.min.js"></script>  
   </head>  
En este paso se llaman a los archivos css y js de Jquery y Telerik respectivamente.

Paso 6:
Inmediatamente después de la etiqueta agregamos el siguiente código para crear los controles del formulario en donde están contenidos el control Kendo UI Grid y el botón que hará la petición.

 <p>  
 <ul>  
      <li><div id="grid"></div></li>  
      <li><div><button id="btnButton">Get data from server</button></div></li>  
 </ul>  
 </p>  

Paso 7:
Ahora viene la parte más importante de la página, en donde se escribe toda su funcionalidad, aquí iniciamos los controles DataSource, Kendo Grid y agregamos el evento del botón que realiza la petición al servidor.

 <script>  
      $(document).ready(function()  
      {  
           //init the kendo UI control  
           $("#grid").kendoGrid(  
                {  
                     height: 366,  
                     width: 300,  
                     pageable: false,  
                     sortable: false,  
                     columns: [  
                          { field: "Id", title: "id"},  
                          { field: "Name", title: "name"},  
                          { field: "LastName", title: "lastName"},  
                          { field: "BirthDate", title: "birthDate"},  
                     ]  
                });  
           //Attach the function to button  
           $("#btnButton").click(function(){  
                var url = "http://127.0.0.1/~martin/KendoUISamples/Authors.js";  
                var data = [];  
                $.getJSON(url,data,function(data,status){  
                          var dataSource = new kendo.data.DataSource({  
                               type: "json",  
                               data: data  
                          });  
                          dataSource.read();  
                          var grid = $("#grid").data("kendoGrid");  
                          grid.setDataSource(dataSource);  
                     }).error(function()  
                     {  
                     alert("some errors ")  
                     });  
                });  
      });  
  </script>  

Al abrir la página, y pulsar el botón se vera el siguiente resultado:

Aquí esta el código completo de la página:

 <!doctype html>  
 <html class="no-js" lang="">  
   <head>  
   <meta charset="utf-8">  
   <meta http-equiv="x-ua-compatible" content="ie=edge">  
   <title>Kendo Grid example 1.0</title>  
   <link rel="stylesheet" href="css/kendo/kendo.common.min.css">  
      <link rel="stylesheet" href="css/kendo/kendo.bootstrap.min.css">  
      <script src="js/jquery-1.11.3.min.js"></script>  
      <script src="js/kendo.all.min.js"></script>  
      <script src="js/kendo.aspnetmvc.min.js"></script>  
   </head>  
   <body>  
           <p>  
                <ul>  
                     <li><div id="grid"></div></li>  
                     <li><div><button id="btnButton">Get data from server</button></div></li>  
                </ul>  
           </p>  
           <script>  
      $(document).ready(function()  
      {  
           //init the kendo UI control  
           $("#grid").kendoGrid(  
                {  
                     height: 366,  
                     width: 300,  
                     pageable: false,  
                     sortable: false,  
                     columns: [  
                          { field: "Id", title: "id"},  
                          { field: "Name", title: "name"},  
                          { field: "LastName", title: "lastName"},  
                          { field: "BirthDate", title: "birthDate"},  
                     ]  
                });  
           //Attach the function to button  
           $("#btnButton").click(function(){  
                var url = "http://127.0.0.1/~martin/KendoUISamples/Authors.js";  
                var data = [];  
                $.getJSON(url,data,function(data,status){  
                          var dataSource = new kendo.data.DataSource({  
                               type: "json",  
                               data: data  
                          });  
                          dataSource.read();  
                          var grid = $("#grid").data("kendoGrid");  
                          grid.setDataSource(dataSource);  
                     }).error(function()  
                     {  
                     alert("some errors ")  
                     });  
                });  
      });  
  </script>  
   </body>  
 </html>  

lunes, 5 de octubre de 2015

Utilizando el HTML 5 Boiler template

El HTML 5 Boilerplate es como dicen sus autores (The web's most popular front-end template) o sea una plantilla que contiene una estructura básica para construir el front-end de cualquier aplicación web que utilice como base de su construcción HTML5, CSS y JavaScript.

Una vez descargado el comprimido de este enlace, solamente se descomprime y ya está listo para utilizarse en cualquier proyecto web.

Aquí una imagen de la estructura de la plantilla, una vez extraída.

Como se muestra, tiene todo lo necesario para empezar: directorio css y js para las hojas de estilo y archivo JavaScript respectivamente, hasta un archivo index y 404 listos para personalizarse según las necesidades.

Si se desea conocer la documentación, hay que ir a este sitio.