Archivo

Archivo para enero, 2005

¿Como Halo 2 salvó al XBOX?

Lunes, 31 de enero de 2005

Halo 2 Master Chief Action Figure

De la collección: El Pana Master Chief

No es un secreto para nadie que Halo 2 es el mejor juego para XBOX que se haya creado alguna vez; Los criticos (si pajudos ellos) y los usuarios (si con más de 6 millones de copias vendidas hasta ahora y un coñazo de gente jugandolo en línea) respaldan esta afirmación. Lo curioso es que ahora, por primera vez XBOX ha logrado no sólo salir de los número rojos, sino que hasta han contribuido enormente a la salud económica de Microsoft.

Muy poca gente habia apostado por el XBOX, pese a tener mejores gráficos que el PS2; En Japón las ventas de XBOX han sido bañaperro, aunque en europa les ha ido mejor. Entonces, en una jugada interesante Microsoft decide que va a liberar el XBOX2 en algún momento de este año. Según ellos, prometen gráficos estilo “Jurasik Park, aunque la gente de Sony con su PS3 promete lo mismo, excepto que ellos no han liberado un kit de desarrollo a diferencia de Microsoft (aunque se habla que el PS3 estará mucho mejor entonada que el XBOX2). El precio es especulativo ya que se dice que el XBOX2 se va a vender por algo así como $400 (con lo cual yo quizas le diré a Microsoft que bien gracias).

Yo en particular me voy a esperar a ver las comparaciones entre XBOX2 y PS3; Seguramente me quedaré con mi XBOX al menos por otro año más, al menos que vea algo que haga cambiar de opinión (quizas Quake IV, pero lo dudo, aún faltan 2 meses para tener DOOM3 en el XBOX y hay muchas dudas con respecto a su rendimiento). Hasta ahora he sido fiel a XBOX por su excelente consola, pero si PS3 me ofrece lo mismo por menos, entonces allí iré (no me interesa un producto que me haga de todo como promete Microsoft con su XBOX2, yo sólo quiero jugar juegos).

Y ya para dejarlos, no podian faltar los rumores de Halo3 y XBOX2 (lealo, hay bastante información aquí).

Halo 2 Master Chief in store

Master Chief en una tienda de juegos de East Village, Manhattan, New York

Sin categoría

Opinión de Pelicula: Appleseed, el futuro del Manga Japonés

Domingo, 30 de enero de 2005

Ayer sabado 29 de Enero logré ver en el cine el futuro del Manga Japonés y se llama Appleseed; De vaina casi la veo, resulta que una semana después de su estreno en todo los Estados Unidos ya la habían quitado de todos los cines en Manhattan, excepto uno localizado en East Village, llamado “East Village cinema” (el cual por cierto es uno de los pocos cines en Manhattan de principio de siglo con historia, que aún funcionan). Así que Vero (armada de paciencia) me acompañó a mi a ver la pelicula en la única función del día, a las 9:25PM.

¿Y valió la pena? Bueno, siga leyendo porque en mi opinión esta pelicula va a redefinir completamente como se hacen los Manga para peliculas de ahora en adelante.

La escena de combate inicial entre la protagonista de la pelicula y un grupo de Cyborgs es impactante, visualmente es una obra de arte; Es increiblemente arrogante en los detalles, además de estar cargada de acción muy bien lograda. Yo me atrevo a catalogarla de perfecta…

Appleseed es la historia de como los humanos y los clones humanos alcanzan un grado de simbiosis único (debido a que los clones ayudan a contrarrestar las malas emociones humanas) y se desarrolla en la tierra después de una tercera guerra mundial (sin armas nucleares, la cuales dejan sin embargo la mayoría de el planeta en ruinas excepto una ciudad llamada Utopia).

La historia es muy compleja, y no pienso contarle mucho más de ella aquí para no arruinarle el encanto, el desarrollo de los personajes durante la pelicula esta muy bien llevado (la pelicula se toma su tiempo para alcanzar el climax) y los gráficos y batallas son del otro mundo; Cada detalle está tan bien cuidado y la acción es tan fluida que es simplemente imposible no dejarse absorber completamente.

Los robots (Mechs) y el estilo de animación (una mezcla de graficos por computadora con rederizaciones espectaculares y animación convencional al estilo Manga) es perfecta. Nunca había visto nada así ya que combina el estilo de Final fantasy (la pelicula) con el estilo de dibujo de Ghost in th Shell (Este manga es de la misma gente que hizo Ghost in the Shell y lo impresionante es que todos los planteamientos que aparecen en el filme fueron hechos ya hace 20 años atrás…)

Ya para terminar, en el sitio web encontrará fondos de escritorio, peliculas cortas y hasta un kit de fanaticos con los cuales puedes decorar su página web. También si quiere, está el sitio oficial del Anime. Allí el autor original del Manga describe humildemente como su trabajo se convirtió en una pelicula.

En Venezuela se puede conseguir por el sitio web de AnimeVen

Sin categoría

La vida de el SA: Lidiando con Firewalls en Linux

Sábado, 29 de enero de 2005

Uno de los “proyectos” en los cuales estoy trabajando ahorita es la construcción de una nueva red para la compañia en la que trabajo; Con ayuda de Firewall Builder estoy depurando una cucaracha que me impide enrutar los paquetes entre los dos firewalls que definí en mi DMZ (y ahorita anto medio jodido, ya que aún aplicando todos los trucos que tengo bajo la manga, y no se ha dejado depurar. Siempre pasa con versiones nuevas y sistema operativo nuevo :) ).

Por lo menos la configuración de la línea T1 entre la oficina y el nuevo datacenter ya está lista (después de entrarme a coñazos con un par de Cisco 1700 con su respectivo módulo para T1).

Sin embargo hoy me lanzo para Manhattan a tomar fotos y a ver si puedo ver de una vez por todas a Appleseed (sin importar el frio máldito, hoy está a -15C)

Sin categoría

SPAWN: ¿O como quedar atrapado entre la guerra de el cielo contra el infierno?

Viernes, 28 de enero de 2005

Spawn meeting

(Reunión de diferentes tipos, mi colleción; De izquierda a derecha: Redemption, Cyber y classic Spawn)

SPAWN es uno de mis personajes preferidos; Es un personaje realmente obscuro el cual (como Wolverine de lox X-MEN) tiene mucho gris, y una crisis existencial gigante. En el caso de la serie SPAWN, no es más que una historia que se viene repitiendo desde el inicio de la humanidad; El infierno (malebolgia) encabezado por el Diablo (quien más, ¿no?) está reclutando generales para dirigir su guerra contra el cielo e iniciar el fin de el mundo. En el proceso reviven y transforman a un asesino a sueldo (el mejor del mundo, una máquina de combate) llamado Al Simmons, el cual aún extraña a su hija y a su esposa Wanda, en un tipo de creatura llamado SPAWN. Lo que malevolencia no cuenta es que Al no quiere destruir el mundo de los vivos, y para complicar las cosas el cielo también quiere eliminar a este engendro enviando Angeles asesinos entrenados en esta tarea

El tema de la serie de por si es provocador; El personaje es muy interesante, ya que además de sus extraordinarios poderes infernales nos encontramos siempre como un monstruo se decide a pelear por la justicia, aunque muy a su manera; Este SPAWN es una creatura atormentada por el hecho de no poder reunirse con su familia, además de ser un perseguido (tanto por el cielo como por el infierno). No hay lealtad a las facciones aqui, y de hecho en varias oportunidades el comic nos deja pensando realmente que bando es peor…

El personaje tiene tanto peso propio que ya ha hecho series con otros superheores igual de obscuros como Batman (los cuales no se llevan para nada bien), sacó una pelicula (no muy buena debo admitir), y hoy en día su creador (Todd McFarlane) tiene una cadena de juguetes ultra exitosa que abarca casi todo los generos (ustedes ya han visto muchisimos de ellos en este sitio web).

Otro aspecto cautivante de SPAWN son sus poderes; Además de tener habilidades propias de una creatura de el infierno, este tiene una armadura la cual se puede convertir en cualquier cosa (gracias a su capa la cual actua como una entidad viviente), cadenas que salen de su cuerpo (las cuales nos recuerdan mucho al Doctor Octopus de Spider Man) y la habilidad innata de Al Simmons en el manejo de poderozas armas de guerra (hey, es como montar bicicleta, no se olvida…).

¿Y que bando va a tomar usted en la guerra de el cielo contra el infierno?

Sin categoría

Echando código: CGI para generar listado de archivos MP3 a descargar, en Perl

Viernes, 28 de enero de 2005

Este ejercicio asume que usted sabe lo que es un CGI y algo de el protocolo HTTP, si no es así consulte un tutorial de Perl / CGI y Javascript que hice unos años atrás (cuando era administrador de sistemas para la ULA).

Imaginese que usted quiere ofrecerle a sus usuarios la opción de bajar una serie de archivos como un sólo archivo comprimido (.tar.gz) y a la vez desea recibir un correo cada vez que eso ocurra; Esto lo podemos hacer fácilmente con Perl usando el módulo CGI para generar la plantilla de HTML de manera dinámica, el módulo Archive::Tar para generar el archivo comprimido en tiempo real y el módulo Net::SMTP. El otro detalle importante es devolver el ‘content type‘ adecuado para forzar al navegador a guardar el archivo.

Para concretar el ejemplo, vamos a utilizar una variación de el programa que hice para el tutorial de como crear un indice de mis archivos MP3, por lo que usaremos de nuevo a File::Find y a MP3::Tag para generar el indice de manera dinámica…

Como siempre Perl se encarga de las tareas ladillas, así nosotros podemos concentrarnos en la lógica principal de la aplicación.

Primero configuramos a el servidor Apache (asumo que usted también utiliza Apache) para poder ejecutar el programa en un directorio arbitrario, además de protegerlo con palabra clave (el archivo es el ‘/etc/http/conf/httpd.conf‘, en Fedora Core 2):

   1:Alias /mp3/ "/mp3/"
   2:Alias /mp3  "/mp3/"
   3:<Directory "/mnt/usb/mp3">
   4:    Options Indexes ExecCGI
   5:    AllowOverride None
   6:    Order allow,deny
   7:    Allow from all
   8:    AuthName "El Angel Negro security"
   9:    AuthType Basic
  10:    AuthUserFile /etc/httpd/conf/users-mp3
  11:    require valid-user
  12:</Directory>
  13:
  14:
  15:# The index.html.var file (a type-map) is used to deliver content-
  16:# negotiated documents.  The MultiViews Option can be used for the
  17:# same purpose, but it is much slower.
  18:#
  19:DirectoryIndex index.html index.html.var index.cgi
  20:
  21:# To use CGI scripts outside of ScriptAliased directories:
  22:# (You will also need to add "ExecCGI" to the "Options" directive.)
  23:#
  24:AddHandler cgi-script .cgi

Luego deberá agregar un usuario y un password, para finalmente reiniciar al servidor web:

[root@localhost root]# htpasswd -c /etc/httpd/conf/users-mp3 mp3

New password:

Re-type new password:

Adding password for user mp3

[root@localhost root]# /etc/init.d/httpd restart

Stopping httpd: [FAILED]

Starting httpd: [ OK ]

[root@localhost root]#

También deberemos instalar los módulos requeridos; Por ejemplo para instalar Archive::tar lo hacemos así:

[root@localhost root]# perl -MCPAN -e’install Archive::Tar’

Y aquí está el código fuente:

   1:#!/usr/bin/perl
   2:
   3:use strict;
   4:use CGI qw/:standard/;
   5:use CGI::Carp qw(fatalsToBrowser);
   6:$CGI::DISABLE_UPLOADS = 1;  # no uploads
   7:use Archive::Tar;
   8:use Net::SMTP;
   9:use File::Find;
  10:use MP3::Tag;
  11:use Date::Format;
  12:
  13:use constant BASEDIR            => "/mnt/usb/Sepultura";
  14:use constant TITLE              => "MP3 Download";
  15:use constant MIME_TYPE          => "application/octet-stream";
  16:use constant URL                => "http://localhost/cgi-bin/MP3Download.cgi";
  17:use constant MAIL_SERVER        => "localhost";
  18:use constant MAIL_SUBJECT       => "MP3 file download report";
  19:use constant MAIL_TO            => 'josevnz@localhost.';
  20:use constant ERROR_REPORT_EMAIL => 'root@localhost.';
  21:use constant DEFAULT_COMPRESS   => 1;
  22:# We need a unique file
  23:use constant TMP_FILE           => "/tmp/MP3Download.cgi-$$";
  24:use constant CLIENT_FILE        => "elangelnegro-mp3-files.tar.gz";
  25:# Pointers to common used names
  26:use vars qw/*name *dir *prune/;
  27:*name   = *File::Find::name;
  28:*dir    = *File::Find::dir;
  29:*prune  = *File::Find::prune;
  30:use constant DEBUG => 0;
  31:use constant TIME_TEMPLATE => "%c"; # man Date::Format
  32:my $date = time2str(TIME_TEMPLATE, time);
  33:
  34:# Each one of these colors is used on the data rows (for even and pair columns)
  35:my @table_colors = (
  36:        "255, 102, 0",
  37:        "255, 153, 0"
  38:);
  39:# Global counter for the row colors
  40:my $color_counter = 1;
  41:
  42:my $error = $@;
  43:my $option = param("option");
  44:
  45:eval {
  46:        if (!defined $option) {
  47:                print
  48:                        header,
  49:                        start_html(-title => TITLE . " - " . $date);
  50:                print <<EOF
  51:<form action="" method="POST">
  52:<table style="width: 100\%; text-align: left;" border="1" cellpadding="2"
  53:cellspacing="2">
  54:<tbody>
  55:<tr>
  56:<th style="vertical-align: top; background-color: rgb(0, 102, 0);"><span
  57:style="color: rgb(255, 255, 255);">Title</span><br
  58:style="color: rgb(255, 255, 255);">
  59:</th>
  60:<th
  61:style="vertical-align: top; color: rgb(255, 255, 255); background-color: 
  62:rgb(0, 102, 0);">Track<br>
  63:</th>
  64:<th
  65:style="vertical-align: top; color: rgb(255, 255, 255); background-color: 
  66:rgb(0, 102, 0);">Artist<br>
  67:</th>
  68:<th
  69:style="vertical-align: top; color: rgb(255, 255, 255); background-color: 
  70:rgb(0, 102, 0);">Album<br>
  71:</th>
  72:<th
  73:style="vertical-align: top; color: rgb(255, 255, 255); background-color: 
  74:rgb(0, 102, 0);">Comment<br>
  75:</th>
  76:<th
  77:style="vertical-align: top; color: rgb(255, 255, 255); background-color: 
  78:rgb(0, 102, 0);">Year<br>
  79:</th>
  80:<th style="vertical-align: top; background-color: rgb(0, 102, 0);"><span
  81:style="color: rgb(255, 255, 255);">Genre</span><br>
  82:</th>
  83:</tr>
  84:EOF
  85:;
  86:        eval {
  87:                # Traverse desired filesystems
  88:                File::Find::find({wanted => \&count}, BASEDIR);
  89:        };
  90:                print <<EOF
  91: </tbody>
  92:</table>
  93:<input type="hidden" name="option" value="download">
  94:<input type="submit" value="Download ALL the selected files!">
  95:<input type="reset" value="Reset">
  96:</form>
  97:<br>
  98:EOF
  99:;
 100:        print end_html;
 101:        if ($@) {
 102:                # Print the HTML end, so at least the document is well formed...
 103:                die "$!";
 104:        }
 105:} elsif (! defined param("filenames")) {
 106:                print
 107:                        header,
 108:                        start_html(-title => -title => TITLE . " - (Error) "),
 109:                        a({href=> URL},
 110:                        h1("Please select at least one file!. " .
 111:                                "<br>Click here to retry.")),
 112:                        end_html();
 113:
 114:} else {
 115:                my @filenames = param("filenames");
 116:                my $tar = Archive::Tar->new();
 117:                $tar->add_files(@filenames);
 118:                print header(
 119:                        -type           => MIME_TYPE,
 120:                        -attachment     => CLIENT_FILE);
 121:                $tar->write(TMP_FILE, DEFAULT_COMPRESS);
 122:                # Send the file back the client, through STDOUT
 123:                open(FILE, TMP_FILE) || die "$!";
 124:                while (<FILE>) {
 125:                        print $_;
 126:                }
 127:                close(FILE);
 128:                my $smtp = Net::SMTP->new(MAIL_SERVER);
 129:                $smtp->mail(ERROR_REPORT_EMAIL);
 130:                $smtp->to(MAIL_TO);
 131:                $smtp->data();
 132:                $smtp->datasend("To: " . MAIL_TO . "\n");
 133:                $smtp->datasend("Subject: " . MAIL_SUBJECT . "\n");
 134:                $smtp->datasend("\n");
 135:                $smtp->datasend("Remote address: $ENV{REMOTE_ADDR}\n");
 136:                $smtp->datasend("Request URI:    $ENV{REQUEST_URI}\n");
 137:                $smtp->datasend("Remote user:    $ENV{REMOTE_USER}\n");
 138:                $smtp->datasend("Referer:        $ENV{HTTP_REFERER}\n");
 139:                $smtp->datasend("Files requested:\n");
 140:                my $totalSize = 0;
 141:                foreach my $file (@filenames) {
 142:                        my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
 143:                                $atime,$mtime,$ctime,$blksize,$blocks) =
 144:                                        lstat($file);
 145:                        $smtp->datasend("\t$file ($size bytes)\n");
 146:                        $totalSize += $size;
 147:                }
 148:                $smtp->datasend("Total size: $totalSize\n");
 149:                $smtp->dataend();
 150:                $smtp->quit;
 151:        }
 152:};
 153:my $error = $@;
 154:if (-f TMP_FILE) {
 155:        # Delete the temp file after we finish
 156:        unlink TMP_FILE;
 157:}
 158:if ($@) {
 159:        die "[ERROR]: Please report this error to '" . ERROR_REPORT_EMAIL . "', $@";
 160:}
 161:
 162:# Callback function that will perform the search
 163:# Argument: Current file being transversed
 164:# Returns:  void
 165:sub count {
 166:    my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
 167:        $atime,$mtime,$ctime,$blksize,$blocks) = lstat($_);
 168:    # Does it look like an MP3 file?
 169:    if ( ( -f $_ ) && ( $_ =~ /^.*\.mp3\z/s ) ) {
 170:                my $mp3 = MP3::Tag->new($_);
 171:                my ($title, $track, $artist, $album, $comment, $year, $genre) =
 172:                        $mp3->autoinfo();
 173:                if (DEBUG) {
 174:                        printf STDERR "%s\n", $date;
 175:                        printf STDERR
 176:                                "title: %s, track: %s, artist: %s, album: %s, 
 177:                                comment: %s,year: %s, genre: %s\n",
 178:                                $title, $track, $artist, $album, $comment,
 179:                                $year, $genre;
 180:                }
 181:                my $index = $color_counter % 2;
 182:                print <<EOF;
 183: <tr>
 184:<td
 185:style="vertical-align: top; background-color: rgb(
 186:        $table_colors[$index]);"><input type="checkbox" name="filenames" value="$name">$title</td>
 187:<td
 188:style="vertical-align: top; background-color: rgb(
 189:        $table_colors[$index]);">$track</td>
 190:<td
 191:style="vertical-align: top; background-color: rgb(
 192:        $table_colors[$index]);">$artist</td>
 193:<td
 194:style="vertical-align: top; background-color: rgb(
 195:        $table_colors[$index]);">$album</td>
 196:<td
 197:style="vertical-align: top; background-color: rgb(
 198:        $table_colors[$index]);">$comment ($mtime, $size)</td>
 199:<td
 200:style="vertical-align: top; background-color: rgb(
 201:        $table_colors[$index]);">$year</td>
 202:<td
 203:style="vertical-align: top; background-color: rgb(
 204:        $table_colors[$index]);">$genre</td>
 205:</tr>
 206:EOF
 207:;
 208:                $color_counter++;
 209:                $mp3->close();
 210:    }
 211:}
 212:
 213:__END__
 214:
 215:=head1 NAME
 216:
 217:MP3Download.plx - A cgi program that returns a set of MP3 files to the caller
 218:
 219:=head1 DESCRIPTION
 220:
 221:This program will allow you to download a list of MP3 files as a single
 222:compressed tar file. After the download finishes it will send you an email
 223:to confirm the status of the download.
 224:
 225:=head1 AUTHOR
 226:
 227:Jose Vicente Nunez Zuleta
 228:
 229:=head1 LICENSE
 230:
 231:GPL
 232:
 233:=head1 BLOG
 234:
 235:El Angel Negro - http://elangelnegro.blogspot.com
 236:
 237:=cut

Usted puede llamar al programa al URL ‘http://localhost/cgi-bin/MP3Download.plx’ y la primera vez que lo llame le creará una tabla así.

Y al final de la descarga debería recibir un reporte como el siguiente:

From root@localhost Thu Jan 27 21:27:46 2005

Date: Thu, 27 Jan 2005 21:27:46 -0500

From: root

To: josevnz@localhost

Subject: MP3 file download report

Remote address: 127.0.0.1

Request URI: /cgi-bin/MP3Download.cgi

Remote user:

Referer: http://localhost/cgi-bin/MP3Download.cgi

Files requested:

/mnt/usb/Sepultura/Nation/08 – Who_Must_Die_.mp3 (5707777 bytes)

/mnt/usb/Sepultura/Nation/09 – Saga.mp3 (8894298 bytes)

Total size: 14602075

Note que el programa no es perfecto, usted deberá mejorar los siguientes aspectos:

  • Eficiencia: El programa es lento (de por si el proceso de crear el archivo Tar es mucho más lento en Perl que el tar de Unix. También el programa puede consumir bastante CPU dependiendo del nivel de compresión utilizado. Finalmente debido a que es un CGI hay que hacer un fork de un programa pesado cada vez que el usuario quiere bajarse archivos; Usando Servlets y un diseño más cuidadoso se pueden evitar estos problemas.
  • Flexibilidad: El programa tiene una ruta de donde debe buscar por archivos de configuración escrita en el código en Perl. Debería ser más flexible y quizas buscar en un grupo de directorios, por ejemplo.
  • Patrón MVC (Model View Controller): La presentación y la lógica de negocios están atadas dentro de el mismo programa (sufre de el sindrome de PHP :) ). Debería haber una separación más clara de roles, usando templates.

Como ve, se puede mejorar bastante y usted puede practicar haciendolo. Ya para terminar, se puede bajar el código fuente desde aqui.

Sin categoría

Seguridad en redes: ¿Como configurar SSL en su servidor Apache?

Viernes, 28 de enero de 2005

La gente de Security Focus tiene un articulo bestial (con ilustraciones y todo), escrito por Artur Maj, acerca de como configurar SSL en Apache 2.0 para poder hacer transacciones seguras. De verdad muy bueno, tenía tiempo que no leia un articulo como este con explicaciones bien claras y precisas.

Sin categoría

Tutorial de DNS: Otra joya antigua circulando por la red

Jueves, 27 de enero de 2005

Dado que conseguí las versiones de unos tutoriales que yo había hecho anteriormente, me decidí a la tarea de buscar uno que había hecho sobre DNS (el servicio que le permite hacer la conversión de nombres a direcciones IP y viceversa) por allá en 1997; Resulta que los amigos de Redes Linux tienen una copia en formato PDF en uno de sus servidores. Aquí hay otra copia, y aquí (proyecto Lucas).

Hmm, de repente me he dado cuenta que me será muy dificil desaparecer de Internet :D .

Allí se los dejo, espero que les guste como les gustó a aquellos que lo utilizaron en aquel entonces (sip, aún la mayoría del contenido está vigente).

Sin categoría

¿Qué tan difícil es hacer el mínimo esfuerzo?

Jueves, 27 de enero de 2005

Coño, hay dias en los cuales no provoca lidiar con nulos; Hoy la conectividad entre nuestra oficina de desarrollo y la red de producción ha estado piche (ya está bastante estable y no es desde toda la Internet, sólo unos puntos por que pude comprobar). Lo cierto es que este uno de los administradores de sistemas contratado en la otra oficina entró en panico y empezó a fastidiarme, preguntando porqué no podía conectarse a la red en producción:

10:41

(10:41:50) moronsa: hi

(10:42:03) angelnegro: Hi

(10:42:21) moronsa: getting request timed out for mail.XXXXX.com

(10:42:44) angelnegro: And, what you think it could be the problem?

(10:42:50) angelnegro: Are you an user or a SA?

(10:42:56) angelnegro: How you can troubleshoot that?

(10:43:02) angelnegro: :|

(10:44:01) moronsa: we can able to ping the outside world except xxxx.com

(10:44:29) moronsa: now it is working jose

(10:44:47) angelnegro: Anyone can say that….

(10:44:54) angelnegro: Do you know how to use traceroute?

(10:45:02) moronsa: yes

(10:45:03) angelnegro: If not learn, you’re an SA….

(10:46:33) moronsa: tnx



Ojo, no todos son nulos, de hecho tengo suerte de trabajar con otros tres chamos que les encanta resolver problemas, pero este en particular fué bastante exasperante. Lo que más me irrita es que no hizo ni siquiera el más minimo esfuerzo para averiguar acerca de el porque del problema, sino que a la menor indicación de dificultad empezó a mendigar para que alguien le resolviera sus problema.

Ahhh, bueno, ya lo eliminé de mi sistema… :)

Sin categoría

Echando código: ¿Como usar File::Find y MP3::Tar de Perl para catalogar nuestros archivos MP3?

Jueves, 27 de enero de 2005

La idea es hacer una búsqueda en el dispositivo en donde están nuestros MP3 y crear un indice en HTML con todas nuestras canciones; Usando un navegador pudieramos tocarlos en la computadora sin necesidad de copiarlos fuera de nuestro tocador de MP3, el cual está conectado por el puerto USB…

Pienselo, imaginese que usted tiene un servidor de archivos en su casa protegido por su firewall y desea bajarse algunas canciones desde el trabajo o un hotel a su laptop; Todas sus canciones están indexadas (y el servidor web está protegido por clave y usa protección con SSL).

Depinga, ¿no?

Idealmente pudieramos concentrarnos en escribir una rutina recursiva en la cual almacenariamos los contadores; Por otro lado si decidimos hacerlo en Perl, podemos utilizar un módulo llamado File::Find el cual viene con Perl 5.6.1 o superior (yo para este ejemplo utilizaré 5.8.0).

Si usted no esta familizarizado con Unix, quizas no conozca la herramienta find. Por ejemplo, para mostrar el tamaño de mis archivos mp3 puedo utilizar lo siguiente:


[josevnz@localhost josevnz]$ find /mnt/usb/ -type f -name ‘*.mp3′ -ls

548 12976 -rwxr-xr-x 1 josevnz josevnz 13287049 Jan 23 18:08 /mnt/usb/Anthrax/Persistence_of_Time/01\ -\ Time.mp3

549 13552 -rwxr-xr-x 1 josevnz josevnz 13869684 Jan 23 18:12 /mnt/usb/Anthrax/Persistence_of_Time/02\ -\ Blood.mp3

550 13408 -rwxr-xr-x 1 josevnz josevnz 13729250 Jan 23 18:15 /mnt/usb/Anthrax/Persistence_of_Time/03\ -\ Keep_It_in_the_Family.mp3

551 12048 -rwxr-xr-x 1 josevnz josevnz 12326579 Jan 23 18:19 /mnt/usb/Anthrax/Persistence_of_Time/04\ -\ In_My_World.mp3

552 9920 -rwxr-xr-x 1 josevnz josevnz 10148176 Jan 23 18:21 /mnt/usb/Anthrax/Persistence_of_Time/05\ -\ Gridlock.mp3

553 6384 -rwxr-xr-x 1 josevnz josevnz 6530321 Jan 23 18:22 /mnt/usb/Anthrax/Persistence_of_Time/06\ -\ Intro_to_Reality.mp3

554 9008 -rwxr-xr-x 1 josevnz josevnz 9210275 Jan 23 18:25 /mnt/usb/Anthrax/Persistence_of_Time/07\ -\ Belly_of_the_Beast.mp3

555 5152 -rwxr-xr-x 1 josevnz josevnz 5263905 Jan 23 18:26 /mnt/usb/Anthrax/Persistence_of_Time/08\ -\ Got_the_Time.mp3

556 9504 -rwxr-xr-x 1 josevnz josevnz 9731052 Jan 23 18:28 /mnt/usb/Anthrax/Persistence_of_Time/09\ -\ H8_Red.mp3

557 10576 -rwxr-xr-x 1 josevnz josevnz 10821090 Jan 23 18:30 /mnt/usb/Anthrax/Persistence_of_Time/10\ -\ One_Man_Stands.mp3

558 7904 -rwxr-xr-x 1 josevnz josevnz 8093488 Jan 23 18:32 /mnt/usb/Anthrax/Persistence_of_Time/11\ -\ Discharge.mp3

569 11984 -rwxr-xr-x 1 josevnz josevnz 12264721 Jan 23 18:43 /mnt/usb/Anthrax/State_Of_Euphoria/01\ -\ Be_All,_End_All.mp3

570 9808 -rwxr-xr-x 1 josevnz josevnz 10033655 Jan 23 18:46 /mnt/usb/Anthrax/State_Of_Euphoria/02\ -\ Out_Of_Sight,_Out_Of_Mind.mp3

571 10688 -rwxr-xr-x 1 josevnz josevnz 10933939 Jan 23 18:49 /mnt/usb/Anthrax/State_Of_Euphoria/03\ -\ Make_Me_Laugh.mp3

572 8320 -rwxr-xr-x 1 josevnz josevnz 8513955 Jan 23 18:51 /mnt/usb/Anthrax/State_Of_Euphoria/04\ -\ Antisocial.mp3

573 14256 -rwxr-xr-x 1 josevnz josevnz 14588574 Jan 23 18:55 /mnt/usb/Anthrax/State_Of_Euphoria/05\ -\ Who_Cares_Wins.mp3

574 10512 -rwxr-xr-x 1 josevnz josevnz 10752545 Jan 23 18:57 /mnt/usb/Anthrax/State_Of_Euphoria/06\ -\ Now_It_s_Dark.mp3

575 10288 -rwxr-xr-x 1 josevnz josevnz 10530190 Jan 23 19:00 /mnt/usb/Anthrax/State_Of_Euphoria/07\ -\ Schism.mp3

Entonces nos quedaría la tarea de capturar esta salida en un archivo, para procesarla luego.

¿Pero, y que tal y si quisiera hacer lo mismo en Windows, sin find? ¿Que tal si lo quiero hacer con Perl?. Bueno, no se desespere, para ello utilice el program ‘find2perl’ y listo:

[josevnz@localhost josevnz]$ find2perl /mnt/usb/ -type f -name '*.mp3' -ls

¡Que arrecho!. Resulta que ‘find2perl‘ le va a convertir a usted su expresión de find en un programa en Perl, toda una belleza.

Pero nosotros, como carajos vergachú, vamos más bien a hacer un programita un poco más sofisticado. La idea básica detrás de File::Find es llamar a una rutina que hace la búsqueda y utilizar una función de ‘callback’ (la cual será llamada cada vez que encontremos un archivo) para filtrar los resultados.

Ahh… y antes de empezar: Si usted es como yo, ni de vaina se acordará de todos los pasos anteriores, así que más bien redirija la salida de find2perl a un archivo y utilicelo como una plantilla.

Ahora vamos a concentrarnos en como obtener información de el catalogo; Una forma eficiente y segura es revizando la metadata que viene dentro de cada archivo MP3, para ello usamos otro módulo disponible en CPAN llamado MP3::Tag.

File::Find ya viene con Perl (al menos con Fedora Core 2) así que sólo les voy a mostrar como instalar el módulo que lee la metadata de los MP3:

[josevnz@localhost josevnz]$ su -

Password:

[root@localhost root]# perl -MCPAN -e'install MP3::Tag'

CPAN: Storable loaded ok

Going to read /root/.cpan/Metadata

Database was generated on Sat, 23 Oct 2004 12:07:36 GMT

CPAN: LWP::UserAgent loaded ok

Fetching with LWP:

ftp://ftp.perl.org/pub/CPAN/authors/01mailrc.txt.gz

Going to read /root/.cpan/sources/authors/01mailrc.txt.gz

Fetching with LWP:

ftp://ftp.perl.org/pub/CPAN/modules/02packages.details.txt.gz

Going to read /root/.cpan/sources/modules/02packages.details.txt.gz

Database was generated on Wed, 26 Jan 2005 07:42:35 GMT

Fetching with LWP:

ftp://ftp.perl.org/pub/CPAN/modules/03modlist.data.gz

Going to read /root/.cpan/sources/modules/03modlist.data.gz

Going to write /root/.cpan/Metadata

Running install for module MP3::Tag

Running make for I/IL/ILYAZ/modules/MP3-Tag-0.94.tar.gz

Fetching with LWP:

ftp://ftp.perl.org/pub/CPAN/authors/id/I/IL/ILYAZ/modules/MP3-Tag-0.94.tar.gz

CPAN: Digest::MD5 loaded ok

Fetching with LWP:

ftp://ftp.perl.org/pub/CPAN/authors/id/I/IL/ILYAZ/modules/CHECKSUMS

Checksum for /root/.cpan/sources/authors/id/I/IL/ILYAZ/modules/MP3-Tag-0.94.tar.gz ok

Scanning cache /root/.cpan/build for sizes

Deleting from cache: /root/.cpan/build/GD-2.16 (10.3>10.0 MB)

MP3-Tag-0.94/

MP3-Tag-0.94/cddb.tm

MP3-Tag-0.94/cddb.tmp

MP3-Tag-0.94/Changes

MP3-Tag-0.94/data_pod.PL

MP3-Tag-0.94/examples/

MP3-Tag-0.94/examples/audio_rename.pl

MP3-Tag-0.94/examples/extractID3v2.pl

MP3-Tag-0.94/examples/mod/

MP3-Tag-0.94/examples/mod/Music_Translate_Fields.pm

MP3-Tag-0.94/examples/mod/transliterate_win1251.pm

MP3-Tag-0.94/examples/mp3info.pl

MP3-Tag-0.94/examples/mp3info2.pl

MP3-Tag-0.94/examples/README.txt

MP3-Tag-0.94/examples/tagged.pl

MP3-Tag-0.94/examples/tagit.pl

MP3-Tag-0.94/examples/type_mp3_dir.pl

MP3-Tag-0.94/Makefile.PL

MP3-Tag-0.94/MANIFEST

MP3-Tag-0.94/META.yml

MP3-Tag-0.94/README.txt

MP3-Tag-0.94/t/

MP3-Tag-0.94/t/mp3tag.t

MP3-Tag-0.94/t/parser.t

MP3-Tag-0.94/t/set_v2.t

MP3-Tag-0.94/t/update_tags.t

MP3-Tag-0.94/t/v2_comments.t

MP3-Tag-0.94/Tag/

MP3-Tag-0.94/Tag/CDDB_File.pm

MP3-Tag-0.94/Tag/File.pm

MP3-Tag-0.94/Tag/ID3v1.pm

MP3-Tag-0.94/Tag/ID3v2.pm

MP3-Tag-0.94/Tag/Inf.pm

MP3-Tag-0.94/Tag/LastResort.pm

MP3-Tag-0.94/Tag/ParseData.pm

MP3-Tag-0.94/Tag.pm

MP3-Tag-0.94/test.mp3

MP3-Tag-0.94/tk-tag/

MP3-Tag-0.94/tk-tag/README

MP3-Tag-0.94/tk-tag/tk-tag.pl

MP3-Tag-0.94/TODO

CPAN.pm: Going to build I/IL/ILYAZ/modules/MP3-Tag-0.94.tar.gz

Checking if your kit is complete...

Looks good

Writing Makefile for MP3::Tag

cp Tag/CDDB_File.pm blib/lib/MP3/Tag/CDDB_File.pm

cp Tag.pm blib/lib/MP3/Tag.pm

cp Tag/ParseData.pm blib/lib/MP3/Tag/ParseData.pm

cp Tag/Inf.pm blib/lib/MP3/Tag/Inf.pm

cp Tag/ID3v2.pm blib/lib/MP3/Tag/ID3v2.pm

cp Tag/ID3v1.pm blib/lib/MP3/Tag/ID3v1.pm

cp Tag/File.pm blib/lib/MP3/Tag/File.pm

cp Tag/LastResort.pm blib/lib/MP3/Tag/LastResort.pm

/usr/bin/perl "-Iblib/arch" "-Iblib/lib" data_pod.PL ID3v2-Data.pod

Manifying blib/man3/MP3::Tag.3pm

Manifying blib/man3/MP3::Tag::ID3v1.3pm

Manifying blib/man3/MP3::Tag::File.3pm

Manifying blib/man3/MP3::Tag::CDDB_File.3pm

Manifying blib/man3/MP3::Tag::ParseData.3pm

Manifying blib/man3/MP3::Tag::Inf.3pm

Manifying blib/man3/MP3::Tag::ID3v2.3pm

Manifying blib/man3/MP3::Tag::ID3v2-Data.3pm

Manifying blib/man3/MP3::Tag::LastResort.3pm

/usr/bin/make -- OK

Running make test

PERL_DL_NONLAZY=1 /usr/bin/perl "-MExtUtils::Command::MM" "-e" "test_harness(0, 'blib/lib', 'blib/arch')" t/*.t

t/mp3tag.........ok

t/parser.........ok

t/set_v2.........ok

t/update_tags....ok

t/v2_comments....ok

All tests successful.

Files=5, Tests=172, 1 wallclock secs ( 1.13 cusr + 0.14 csys = 1.27 CPU)

/usr/bin/make test -- OK

Running make install

Installing /usr/lib/perl5/site_perl/5.8.3/MP3/Tag.pm

Installing /usr/lib/perl5/site_perl/5.8.3/MP3/Tag/File.pm

Installing /usr/lib/perl5/site_perl/5.8.3/MP3/Tag/Inf.pm

Installing /usr/lib/perl5/site_perl/5.8.3/MP3/Tag/ID3v2.pm

Installing /usr/lib/perl5/site_perl/5.8.3/MP3/Tag/ParseData.pm

Installing /usr/lib/perl5/site_perl/5.8.3/MP3/Tag/ID3v1.pm

Installing /usr/lib/perl5/site_perl/5.8.3/MP3/Tag/CDDB_File.pm

Installing /usr/lib/perl5/site_perl/5.8.3/MP3/Tag/LastResort.pm

Installing /usr/share/man/man3/MP3::Tag::File.3pm

Installing /usr/share/man/man3/MP3::Tag::CDDB_File.3pm

Installing /usr/share/man/man3/MP3::Tag::ParseData.3pm

Installing /usr/share/man/man3/MP3::Tag::ID3v2.3pm

Installing /usr/share/man/man3/MP3::Tag::LastResort.3pm

Installing /usr/share/man/man3/MP3::Tag.3pm

Installing /usr/share/man/man3/MP3::Tag::ID3v2-Data.3pm

Installing /usr/share/man/man3/MP3::Tag::Inf.3pm

Installing /usr/share/man/man3/MP3::Tag::ID3v1.3pm

Writing /usr/lib/perl5/site_perl/5.8.3/i386-linux-thread-multi/auto/MP3/Tag/.packlist

Appending installation info to /usr/lib/perl5/5.8.3/i386-linux-thread-multi/perllocal.pod

/usr/bin/make install -- OK

[root@localhost root]#

Este es el código que hace el truco:

   1:#!/usr/bin/perl
   2:
   3:use strict;
   4:use File::Find;
   5:use MP3::Tag;
   6:use Date::Format;
   7:
   8:# Pointers to common used names
   9:use vars qw/*name *dir *prune/;
  10:*name   = *File::Find::name;
  11:*dir    = *File::Find::dir;
  12:*prune  = *File::Find::prune;
  13:use constant MAX_SIZE => 99999999;
  14:use constant DEBUG => 0;
  15:use constant TIME_TEMPLATE => "%c"; # man Date::Format
  16:my $color_counter = 1; # Global counter
  17:
  18:# Each one of these colors is used on the data rows (for even and pair columns)
  19:my @table_colors = (
  20:        "255, 102, 0",
  21:        "255, 153, 0"
  22:);
  23:
  24:sub count;
  25:
  26:if ( ! -d $ARGV[0] ) {
  27:        die "Please provide a valid directory! ('$ARGV[0]')";
  28:}
  29:my $date = time2str(TIME_TEMPLATE, time);
  30:        print <<EOF
  31:<html>
  32:<head>
  33:<meta content="text/html; charset=ISO-8859-1"
  34:http-equiv="content-type">
  35:<title>My Music Collection - $date</title>
  36:</head>
  37:<body>
  38:<table style="width: 100\%; text-align: left;" border="1" cellpadding="2"
  39:cellspacing="2">
  40:<tbody>
  41:<tr>
  42:<th style="vertical-align: top; background-color: rgb(0, 102, 0);"><span
  43:style="color: rgb(255, 255, 255);">Title</span><br
  44:style="color: rgb(255, 255, 255);">
  45:</th>
  46:<th
  47:style="vertical-align: top; color: rgb(255, 255, 255); background-color: rgb(0, 102, 0);">Track<br>
  48:</th>
  49:<th
  50:style="vertical-align: top; color: rgb(255, 255, 255); background-color: rgb(0, 102, 0);">Artist<br>
  51:</th>
  52:<th
  53:style="vertical-align: top; color: rgb(255, 255, 255); background-color: rgb(0, 102, 0);">Album<br>
  54:</th>
  55:<th
  56:style="vertical-align: top; color: rgb(255, 255, 255); background-color: rgb(0, 102, 0);">Comment<br>
  57:</th>
  58:<th
  59:style="vertical-align: top; color: rgb(255, 255, 255); background-color: rgb(0, 102, 0);">Year<br>
  60:</th>
  61:<th style="vertical-align: top; background-color: rgb(0, 102, 0);"><span
  62:style="color: rgb(255, 255, 255);">Genre</span><br>
  63:</th>
  64:</tr>
  65:EOF
  66:;
  67:
  68:eval {
  69:
  70:        # Traverse desired filesystems
  71:        File::Find::find({wanted => \&count}, $ARGV[0]);
  72:};
  73:
  74:if ($@) {
  75:        # Print the HTML end, so at least the document is well formed...
  76:        print <<EOF
  77: </tbody>
  78:</table>
  79:<br>
  80:</body>
  81:</html>
  82:EOF
  83:;
  84:        die "$!";
  85:}
  86:exit;
  87:
  88:# Callback function that will perform the search
  89:# Argument: Current file being transversed
  90:# Returns:  void
  91:sub count {
  92:    my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
  93:        $atime,$mtime,$ctime,$blksize,$blocks) = lstat($_);
  94:    # Does it look like an MP3 file?
  95:    if ( ( -f $_ ) && ( $_ =~ /^.*\.mp3\z/s ) ) {
  96:                my $mp3 = MP3::Tag->new($_);
  97:                my ($title, $track, $artist, $album, $comment, $year, $genre) =
  98:                        $mp3->autoinfo();
  99:                if (DEBUG) {
 100:                        printf STDERR "%s\n", $date;
 101:                        printf STDERR
 102:                                "title: %s, track: %s, artist: %s, album: %s, 
 103:                                comment: %s,year: %s, genre: %s\n",
 104:                                $title, $track, $artist, $album, $comment,
 105:                                $year, $genre;
 106:                }
 107:                my $index = $color_counter % 2;
 108:                print <<EOF;
 109: <tr>
 110:<td
 111:style="vertical-align: top; background-color: rgb(
 112:        $table_colors[$index]);"><a href="file:\/\/$name">$title</a></td>
 113:<td
 114:style="vertical-align: top; background-color: rgb(
 115:        $table_colors[$index]);">$track</td>
 116:<td
 117:style="vertical-align: top; background-color: rgb(
 118:        $table_colors[$index]);">$artist</td>
 119:<td
 120:style="vertical-align: top; background-color: rgb(
 121:        $table_colors[$index]);">$album</td>
 122:<td
 123:style="vertical-align: top; background-color: rgb(
 124:        $table_colors[$index]);">$comment</td>
 125:<td
 126:style="vertical-align: top; background-color: rgb(
 127:        $table_colors[$index]);">$year</td>
 128:<td
 129:style="vertical-align: top; background-color: rgb(
 130:        $table_colors[$index]);">$genre</td>
 131:</tr>
 132:EOF
 133:;
 134:                $color_counter++;
 135:                $mp3->close();
 136:    }
 137:}
 138:
 139:__END__
 140:
 141:=head1 NAME
 142:
 143:MP3Counter.plx - A program that creates an HTML index from your MP3 collection
 144:   
 145:=head1 DESCRIPTION
 146:
 147:This program asumes that you are ordering your MP3 collection like this:
 148:
 149:        Artist name--->
 150:                      Album name--->
 151:                                   Song name
 152:
 153:Then you can use the program like this:
 154:
 155:MP3Counter.plx <directory> > /directory/index.html
 156:
 157:But that really doesn't matter as we read the metadata directly from the MP3 
 158:file!
 159:
 160:=head1 AUTHOR
 161:
 162:Jose Vicente Nunez Zuleta.
 163:
 164:=head1 BLOG
 165:
 166:El Angel Negro - http://elangelnegro.blogspot.com
 167:
 168:=head1 LICENSE
 169:
 170:GPL
 171:
 172:=head1 TODO
 173:
 174:Improve paging and HTML output!
 175:
 176:=cut

Lo corremos así:

[josevnz@localhost MP3]$ time ./MP3Counter.plx /mnt/usb/ > index.html

real 0m3.091s

user 0m2.229s

sys 0m0.789s

[josevnz@localhost MP3]$

(Corre bastante rápido).

Blogger me vuelve mierda las tablas, así que le dejo a usted la tarea de correr el programa para ver como se ve el asunto (si, que ladilla…). Si quiere ver una salida de ejemplo, haga click aqui.

Si no quiere generar un archivo estático, entonces tendrá que modificar el programa para que se comporte como un CGI; Sin embargo dado lo poco (digo yo) que cambia su colección de MP3 entonces quizas será mejor poner el script como un trabajo en Cron. Otra cosa que seguro usted deberá mejorar es la paginación, ya que todas las canciones salen en una sola pagina.

Como siempre, puede bajarse el código fuente desde aqui. Será hasta el próximo programa :)

Sin categoría

Echando código: ¡Mis tutoriales en la red!

Miércoles, 26 de enero de 2005

Revizando en la red me encontré una serie de tutoriales que escribí mientras aún estudiaba en la ULA y daba clases en la Escuela Latinoamericana de Redes; Curiosamente aún existen (cortesía de el equipo TLDP-ES – Tutoriales) y quisiera compartirlos con todos ustedes:

Espero les gusten ;)

Sin categoría