Category Archives: Programación

Limpiado Ad-Free Blogs (II), esta vez de verdad!

Hace un rato me he acordado de que aún tenía esto pendiente por hacer, el script fallaba con todas las páginas que usaban redirecciones (debido a que éstas usan frames para hacer la redirección), lo cual he arreglado modificando ligeramente el código.
 
El funcionamiento del script es sencillo, creamos un fichero de texto que se llame “content.txt” que tenga la página del wiki de microsiervos, ejecutamos el script (está en perl y requiere un paquete, $ sudo aptitude install libterm-progressbar-perl) y este creará tres ficheros de texto como salida

  • out.txt: con los blogs buenos.
  • out.txt.malos: con los blogs malos.
  • errores.txt: con blogs que no ha podido analizar, debido a errores diversos, desde URL inexistentes (404) a falta de permisos debido a la configuración del servidor (403), etc, etc…

Una vez terminada la ejecución (unos 20min le ha costado), he comprobado los blogs malos que da como resultado (unos cuantos solo, si comprobase todos no tendría sentido el script xD) y creo que esta vez no hay fallos. Los que salen como errores son debido a su mayoría a páginas no encontradas (error 404) o timeouts del servidor (error 500), aunque había algún otro error misterioso (415 por ejemplo) que lo he pasado a blogs buenos y ya está. En resumen, resultados:

En total de 399 blogs. Hay 153 MALOS, 212 BUENOS y 34 que han fallado!

Es decir, 38% son malos! WTF?. Acabo de editarlo en el wiki de microsiervos, pero si alguien se aburre mucho, mucho y encuentra fallos en la lista (o en el código del script), que no dude en cagarse en mis muertos y mencionarlo para corregirlo cuanto antes. Ahora tendremos 216 blogs en ad-free :).
 
No voy a pegar todo el código pues es similar al anterior, he aquí un tar.gz con el código y ficheros resultado.

Limpiando “Ad-Free Blogs”

Ad-Free Blogs es una iniciativa para crear una lista de weblogs libres de publicidad comercial de empresas. Microsiervos en su wiki creó la iniciativa en español de este movimiento. Un blog que quiera unirse, solo debe poner la imagen del buho y añadirse al wiki él mismo, y de ese modo incluso se tiene un enlace para navegar al azar por estos blogs (libres de publicidad).
 
Hasta aquí no estoy contanto nada nuevo. Hoy, aunque debería de haber estado estudiando, me he quedado en casa (solo “sé” estudiar en la biblio :P) y cuando por la tarde estaba con mi bocata y mi coke todo feliz vagueando y tal, le he dado al link de blog al azar (el del buho) y de diez veces que le he dado, solo uno de los diez blogs era en verdad libre de publicidad (y que contuviese la imagen del buho). Como esto me ha molestado bastante, me he puesto a hacer un script simple que pilla el contenido de la página del wiki de microsiervos (hay que descargarlo y ponerlo en un txt) y va buscando en qué blogs tienen la imagen del buho y en cuales no. El script es simple y se puede mejorar por todos lados, lo acabo de hacer :P, pero los resultado creo que son buenos, aunque quiero comprobar más a fondo las direcciones que salen como malas antes de editar el wiki de Microsiervos. Concretamente los resultados que obtengo son:

En total de 393 blogs. Hay 143 MALOS y 213 BUENOS

Eso hace un 36,4% de blogs malos y 9,4% erroneos (URL incorrecta)! Una cifra bastante considerable. El script es este:
Read More …

Peticiones HTTP con Perl

En la última Campus Party, como comenté en su post, estuve bastante tiempo con el concurso de seguridad web. Muchas veces para ir probando a mandar peticiones web concretas, GET o POST, había que usar “algo” que lo hiciese. Las opciones son varias, se podría usar un proxy, pero con él nos limitamos el poder tratar la respuesta del servidor o hacer cosas algo más complejas que una simple petición, esto mismo se puede aplicar a usar un telnet contra el servidor web remoto, así que al final, hay que usar un lenguaje de programación desde el cual abrimeros un socket contra el puerto 80 del servidor web en cuestión, por el cual hablaremos HTTP 1.1.
 
Un amigo que también participó en el concurso, OddBug, como es un poco windosero (aunque ahora es medio GentooManPr0 xD) usó Visual Basic :o, en mi caso opté por usar Perl porque mola mogollón :). Así que vamos al asunto!, como narices crear una petición (y obtener la respuesta por parte del servidor) http. Vamos a crear un socket y ya está, más facil no puede ser :). Tenemos dos formas, la tradicional:

#! /usr/bin/perl -w
use Socket;
use strict;
my( $host, $in_addr, $proto, $port, $addr, $file);
 
$host = "www.marca.es";
$file = "/"; # el index vamos...
$port = 80;
$proto = getprotobyname('tcp');
$in_addr = inet_aton($host);
$addr = sockaddr_in($port, $in_addr);
# creamos el socket y conectamos al servidor
socket(S, AF_INET, SOCK_STREAM, $proto) or die "socket: $!";
connect(S, $addr) or die "connect: $!";
# para flushear nada mas escribir en el socket
select(S); $| = 1; select(STDOUT);
 
# Una peticion normal GET
print S "GET $file HTTP/1.1\nHOST: $host\n\n";
 
while(<S>)
{
	print;
}

Que es un poco fea, bastante similar a C, y no muy limpia. Y la forma maja, usar los modulos de CPAN que hacen grande a Perl. Lo anterior queda simplificado a esto:

#! /usr/bin/perl -w
use IO::Socket;
use strict;
 
my $host = "www.marca.es";
my $file = "/"; # el index vamos...
my $port = 80;
my $S = IO::Socket::INET->new
(
	Proto    => "tcp",
	PeerAddr => "$host",
	PeerPort => "$port",
)  or die "cannot connect!";
# para flushear nada mas escribir en el socket
select($S); $| = 1; select(STDOUT);
 
print $S "GET $file HTTP/1.1\nHOST: $host\n\n";
while(<$S>){ print }

Más simple ya, imposible. Ahora ya solo queda variar las peticiones que se mandan. Un GET no tiene mucha complejidad, solo recordar que en HTTP 1.1 hay que indicar el host y al final hay dos saltos de linea:

$peticion = 'GET /fichero/que/quiero/lala.php HTTP 1.1
HOST: www.LAwebQUEsea.com'."\n\n";
 
print $S $peticion

Para una peticion POST, tenemos que indicar la longitud de los datos que se envían, podemos usar algo del estilo (es un ejemplo inventado de un supuesto formulario para votar):

$voto = 10;
$discoID = 28912;
 
$peticionPost='POST /discos/votar.asp HTTP/1.1
Host: www.paginaQUEsea.com
Content-Type: application/x-www-form-urlencoded
Content-Length: ';
 
$post = 'accion=votar&id='.$discoID.'&voto='.$voto
$peticion = $peticionPost.length($post)."\n\n".$post
 
print $S $peticion;

Además de esto podemos enviar muchas más cabeceras (Cookies con sesiones php u otras cosas, Referer’s, User-Agents, etc, etc…). Luego ya, según el escenario, después de obtener el resultado del servidor, se podría tratar y buscar patrones o lo que nos interesase, las combinaciones y posibilidades son infinitas.

Capas con imagen de fondo en Java

Java es un lenguaje muy potente, pero hacer interfaces es algo que puede llegar a ser tan divertido como una patada en los cojones xD. El editor de Netbeans es muy potente, pero como usa un layout propio (auque puedes usar otros, los estandar de la API de Java) luego para exportarlo y empaquetarlo todo en un jar, debo de ser muy tonto que no se hacerlo, luego tenemos Eclipse, un IDE que es el puro desorden personificado, por mucho que intento ponerme con él, pierdo más tiempo mirando donde están las cosas que trabajando, es decir, toca hacerse las GUI’s a mano.
Una de las cosas que más he hecho y más veces he perdido el tiempo, es crear una capa/ventana/cuadrado/ComoQuierasLlamarlo con una imagen de fondo. Para hacer esta trivialidad, en Java tenemos que hacer la de dios para lograrlo, lo que viene a ser usar un JPanel y sobrecargar el método de pintado en el cual pintaremos toda la superficie con una textura creada de la imagen. Vamos que es una puta mierda. Este post me lo escribo para mi mismo :P, para que otras veces venga aquí y haga copy paste y deje de tener que estar siempre mirando código viejo. Let’s go!

Demo 1 – Ventanita simple con un fondo:

    Recursos:

  • -GUI.java: la “aplicación” verdadera
  • -images.java: Clase estática para crear texturas de una imagen
  • -fondo.png: Fondo, puede ser más pequeño que la ventana y de esa forma se repetirá. Acabo de hacer una imagén de 300x10px donde la mitad superior es negra y la mitad inferior es blanca. Adivinas el efecto que surgirá?, yeah, una cebra xD.

GUI.java

import java.awt.*;
import javax.swing.*;
import java.net.URL;
 
public class GUI extends JFrame
{
	private static GUI ventanaPrincipal; // Ventana principal
	private JPanel panel; // Capa sobre la que se trabajará
 
	private final URL imgFondo =  this.getClass().getResource("fondo.png");	
	private static TexturePaint fondo; // Textura con la que se pintará el fondo
 
	public static void main(String [] arg)
	{	// lanzamos aplicación
		javax.swing.SwingUtilities.invokeLater(new Runnable(){
			public void run()
			{
				lanzarAplicacion();
			}
		});
	}
	/**
	 * construye los objetos requeridos para el funcionamiento de la aplicacion
	 */
	private static void lanzarAplicacion()
	{
		// se crea la ventana
		ventanaPrincipal = new GUI("Demo guays");		
		// y la mostramos!
		ventanaPrincipal.setVisible(true);		
	}
 
	private GUI(String Titulo)
	{
		super(Titulo);
 
		panel = new JPanel()
		{
			private TexturePaint fondo = images.carga(imgFondo, this);
			protected void paintComponent(Graphics g)
			{
				super.paintComponent(g);
				Graphics2D g2d = (Graphics2D)g;
				Dimension d = getSize();
				g2d.setPaint(fondo);
				g2d.fill(new Rectangle(0,0,d.width,d.height));
			}
		};			
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setPreferredSize(new Dimension(300, 300));
		setSize(300,300);	
		getContentPane().add(panel);
	}
 
}

Images.java: Es un clase estática de la cual nos interesa el método carga(nombre_imagen, componente), el cual nos dará el tan preciado TexturePaint, la textura con la cual pintaremos felizmente. (nota: par de funciones no son mias, las saqué de un tutorial de java2d)

import java.awt.*;
import javax.swing.ImageIcon;
import java.awt.image.*;
import java.net.URL;
 
public class images
{
	private static TexturePaint cargaTextura(URL imageFile, Component c)
	{
		TexturePaint imageDev;
		try
		{
			Image img = (new ImageIcon(imageFile)).getImage();
			BufferedImage image = getBufferedImage(img , c);
			imageDev =  new TexturePaint(image, 
					new Rectangle(0, 0, image.getWidth(), image.getHeight())	
			);
		}catch(Exception e){
      	imageDev = null;
      	System.out.println(e.getMessage());	
      }
      return imageDev;
  }
 
	private static BufferedImage getBufferedImage(Image image, Component c)
	{
		waitForImage(image, c);
		BufferedImage bufferedImage = new BufferedImage(
			image.getWidth(c), image.getHeight(c), BufferedImage.TYPE_INT_RGB
		);
		Graphics2D g2d = bufferedImage.createGraphics();
		g2d.drawImage(image, 0, 0, c);
		return(bufferedImage);
	}
 
	private static boolean waitForImage(Image image, Component c)
	{
		MediaTracker tracker = new MediaTracker(c);
		tracker.addImage(image, 0);
		try{
			tracker.waitForAll();
		}catch(InterruptedException ie){}
		return(!tracker.isErrorAny());
	}
	/**
	 * Crea un textura de una imagen para un componente concreto
	 * @param s imagen a cargar
	 * @param c componente sobre el cual pintaremos
	 */
	public static TexturePaint carga(URL s, Component c)
	{
		TexturePaint image;
		image = cargaTextura(s, c);
		if (image == null)
			System.err.println("OMG! No puedo leer la imagen " + s);
		return image;
	}
}

Con esto obtenemos:

ventanajavapintada.jpg

Demo 2 – JPanelBackground: ya que estamos, hacemos un nuevo JPanel nuevo, no?

JPanelBackground

import javax.swing.JPanel;
import java.awt.*;
import java.net.URL;
 
public  class JPanelBackground extends JPanel
{
	private TexturePaint fondo;
 
	public JPanelBackground(URL imgFondo)
	{
		fondo = images.carga(imgFondo, this);
	}
	public void paintComponent(Graphics g)
	{
		super.paintComponent(g);
		Graphics2D g2d = (Graphics2D)g;
		Dimension d = getSize();
		g2d.setPaint(fondo);
		g2d.fill(new Rectangle(0,0,d.width,d.height));
	}
}

Con esto GUI.java cambiará a ser más simple y limpio, concretamente los cambios serían:

(...)
public class GUI extends JFrame
{
	(...)
	private JPanelBackground panel; // Capa sobre la que se trabajará
	(...)
	private GUI(String Titulo)
	{
		super(Titulo);
 
		panel = new JPanelBackground(imgFondo);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		(...)
	}	
}

Todos los códigos fuentes están en este archivo 😉

Unos comentarios finales, todo esto nos permite, posteriormente, crear nuevos elementos sobre este JPanel que estarán por encima de la imagen que hemos pintado, si nos da igual esto (es decir, que no vamos a poner más cosas por encima), se podría hacer con un JLabel usando su método setIcon(new ImageIcon(“imagen.png”)), otra forma que muchos dirán sería usar un Canvas y su método setBackground, el cual es una ponzoña, pues al usarlo, el Canvas estará disparando eventos de repintado aparte de los usuales de su método Paint(), es decir, que con un Canvas habría que hacer lo que hemos hecho arriba con JPanel.

Manuales curiosos

Llevo toda la semana con dolor de cabeza más garganta todo en uno, agitado no mezclado y por ello no estoy ni escribiendo aquí, ni estudiando, ni haciendo nada salvo dormir y sobrevivir mediante la ingestión de pizzas y alimentos ricos en hidratos de carbono (sobres de pasta para los friends).

Hoy que ya me encuentro con ganas de hacer algo sin que tenga ganas de darme cabezazos contra la pared, para que se me vaya el dolor de cabeza. Revisando mis RSS, me encuentro en el blog de JJ las transparencias que usó en su charla/taller sobre Perl en la Campus party. Leyendo un poco por encima, me arrepiento por no haber ido, sobre todo por la ironía y sentido del humor que parece que tiene el mozo, debió de estar muy ameno (y no como el puto taller de python al que fuí, que aunque didactico era, fue un coñazo en mayusculas, los talleres tienen que ser divertidos xD, si no es así, casi mejor leerte tu un pdf).

Además de este corto, irónico y práctico tutorial, hay otro sobre ruby también con bastante humor en él. He aquí enlaces a ambos, si alguien conoce más tutoriales/manuales/howtos/* del mismo estilo, comentario pero ya! xD

HowTo: Integrando Rails con apache

railsApache.pngBueno, como dije en el anterior post, voy a explicar como integrar Rails con Apache, para que sea éste nuestro servidor Web. El servidor de Rails WEBrick (ejecutando script/server en el directorio de nuestra aplicación de Rails) cumple su función, sobre todo es útil para el desarrollo, pues muestra mucha información. Pero para un entorno real, no puede competir con un servidor web “de los de verdad” (estaría bien respaldar ésto con números, para otro día que me aburra…). Otra opción sería usar Rails con lighttpd, ésto lo he visto mucho por la red, y parece dar buenos resultados, pero como Apache es mucho Apache, prefiero usarlo :P.

Seguiré desde el HowTo anterior, es decir, tenemos una aplicación básica en ~/dev/rails la cual al final de este tutorial será servida a los clientes mediante apache. Supongo que estamos usando Ubuntu Dapper, para otra distro sería todo perfectamente aplicable, pero habría que cambiar, posiblemente, algunos de los binarios/directorios/archivos/nombres_de_paquetes por otros ligeramente diferentes. Intentaré ir explicando las cosas de la forma más generica posible… ok, entonces ¿qué necesitamos para poder servir aplicaciones RoR con apache?

  • Mod_rewrite (para apache)
  • Mod_fcgid (para apache)
  • fcgid en nuestro sistema
  • Modulo fcgid para ruby
  • Configurar apache, añadiendo un virtualhost (o un Directory + Alias)

Vayamos por partes, como dijo Jack el destripador. Mod_rewrite lo tendrás casi 100% seguro, a no ser que hayas compilado apache indicandole que no quieres ese modulo. ¿Cómo sabemos que lo tenemos?

$ /usr/sbin/apache2 -l # [el binario de apache] -l
Compiled in modules:
core.c
(…)
mod_alias.c
mod_so.c
$ ls /etc/apache2/mods-enabled/ # aquí aparecerán los módulos activos

Debe de salir en uno de esos dos comandos, si lo tienes instalado de los repositorios de ubuntu, saldrá en mods-enabled ;).

Mod_fcgid para apache, ok. Instalemoslo o si eres un autentico macho ibérico que compila todo, compila tu apache con este modulo!. Para el resto de mortales, simplemente esto:

$ sudo aptitude install libapache2-mod-fcgid
$ sudo /etc/init.d/apache2 force-reload
$ more /etc/apache2/mods-enabled/fcgid.conf # ahora tendremos estos dos ficheros, este

AddHandler fcgid-script .fcgi
SocketPath /var/lib/apache2/fcgid/sock

$ more /etc/apache2/mods-enabled/fcgid.load # y este!
LoadModule fcgid_module /usr/lib/apache2/modules/mod_fcgid.so

Ahora instalemos fcgi en nuestro sistema como librería compartida, podemos hacer un aptitude search fcgi para ver paquetes candidatos, en el caso de Ubuntu Dapper, simplemente:

$ sudo aptitude install libfcgi0

Ahora solo nos queda por instalar el modulo fcgi para ruby, para ello hacemos un:

$ sudo aptitude install libfcgi-ruby1.8 # o la que nos corresponda

Ahora hagamos la prueba definitiva, para saber si todo va bien:

$ irb
irb(main):001:0> require ‘fcgi.so’
=> true
irb(main):002:0> require ‘fcgi’
=> true

Muy bien!, ya tenemos todo preparado, ahora configuremos apache!. Haré la configuración con un Virtualhost, pues lo veo más cómodo (pero se podría hacer también con un “Directory” más un alias). Añadimos a la configuración de apache lo siguiente:

$ sudo vi /etc/apache2/sites-available/default # en dapper, sería en este fichero


ServerName rails
DocumentRoot /home/blaxter/dev/rails/public/
ErrorLog /home/blaxter/dev/rails/log/apache.log

Options ExecCGI +FollowSymLinks
AllowOverride all
Allow from all
Order allow,deny



$ sudo vi /etc/hosts # añadimos un linea como esto:
127.0.0.1 rails
$ sudo /etc/init.d/apache2 force-reload # reiniciamos apache

Debes cambiar /home/blaxter/dev/rails por la ruta de tu aplicación rails!.

Ahora debemos hacer un par de cosas antes de dejar todo listo. Primero borrar las sesiones actuales

$ cd ~/dev/rails # dir de nuestra aplicación
$ rm tmp/sessions/* # es importante hacer esto, hazlo!

luego permitir al servidor leer y escribir en nuestra aplicación, Apache corre como usuario www-data, una forma de permitirle leer los archivos y escribir (concretamente debe escribir en ./tmp/*), sería poner el proyecto con nombre de usuario www-data y luego añadirnos a nosotros como miembro de www-data, esta es una opción, puede haber cientas, dependiendo del sistema de cada uno…

$ chown www-data:www-data -R . # apache corre como usuario www-data
$ sudo vigr # modificamos la linea de www-data, si teníamos algo como esto:
www-data:x:33:
la modificamos a algo como esto:
www-data:x:33:blaxter

Ahora, ya para finalizar, solo nos queda modificar el .htaccess, concretamente ~/dev/rails/public/.htaccess, que debe quedar así:

Options +FollowSymLinks +ExecCGI
RewriteEngine On
#####################################
# Si configuramos la aplicacion con un Directory mas un alias tipo
# Alias /rails /home/blaxter/dev/rails/public
# Deberíamos descomentar la siguiente linea
# RewriteBase /rails
#####################################
RewriteRule ^$ index.html [QSA]
RewriteRule ^([^.]+)$ $1.html [QSA]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ dispatch.fcgi [QSA,L]

ErrorDocument 500 “Application error. Rails application failed to start properly”

Ok, todo hecho. Ya solo queda entrar a http://rails/ o http://rails/adminDeCosas o http://rails/prueba y todo funcionará!. Además podremos ver el log en ~/dev/rails/log/apache.log :). Suerte!