<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2enclosuresfull.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:media="http://search.yahoo.com/mrss/" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>César D. Rodas</title>
	
	<link>http://cesar.la</link>
	<description>It’s very simple — you read the protocol and write the code</description>
	<pubDate>Fri, 20 Mar 2009 03:11:27 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.7</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<media:copyright>Every text used here is protected under the GNU GPL license</media:copyright><media:keywords>internet,php,mysql,apache,server,saddor</media:keywords><media:category scheme="http://www.itunes.com/dtds/podcast-1.0.dtd">Technology/Tech News</media:category><media:category scheme="http://www.itunes.com/dtds/podcast-1.0.dtd">Technology/Software How-To</media:category><media:category scheme="http://www.itunes.com/dtds/podcast-1.0.dtd">Technology</media:category><itunes:owner><itunes:email>saddor@cesarodas.com</itunes:email><itunes:name>Cesar D. Rodas</itunes:name></itunes:owner><itunes:author>Cesar D. Rodas</itunes:author><itunes:explicit>clean</itunes:explicit><itunes:keywords>internet,php,mysql,apache,server,saddor</itunes:keywords><itunes:subtitle>Saddor Blog</itunes:subtitle><itunes:summary>This is my blog that I will write about technology, internet (php, mysql, servers), trends, and many others subjects.</itunes:summary><itunes:category text="Technology"><itunes:category text="Tech News" /></itunes:category><itunes:category text="Technology"><itunes:category text="Software How-To" /></itunes:category><itunes:category text="Technology" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" href="http://feeds.feedburner.com/crodas" type="application/rss+xml" /><feedburner:emailServiceId>crodas</feedburner:emailServiceId><feedburner:feedburnerHostname>http://feedburner.google.com</feedburner:feedburnerHostname><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com" /><item>
		<title>PHP Application server - GSoC proposal</title>
		<link>http://feedproxy.google.com/~r/crodas/~3/x_JU4BVQrZk/php-application-server-gsoc-proposal.html</link>
		<comments>http://cesar.la/php-application-server-gsoc-proposal.html#comments</comments>
		<pubDate>Fri, 20 Mar 2009 02:35:35 +0000</pubDate>
		<dc:creator>saddor@cesarodas.com (Cesar D. Rodas)</dc:creator>
		
		<category><![CDATA[Open Source]]></category>

		<guid isPermaLink="false">http://cesar.la/?p=185</guid>
		<description><![CDATA[After, no so good feedback after present my idea on the PHP Dev maillist I&#8217;ve deicide to write a blog post about it, and I will try to clarify all those dark sides.
Objectives

Simple principle of work.
Migration painless process, people should be able to copy existence code and put on the worker and it should work.
Easy [...]]]></description>
			<content:encoded><![CDATA[<p>After, no so good feedback after present my idea on the PHP Dev maillist I&#8217;ve deicide to write a blog post about it, and I will try to clarify all those dark sides.</p>
<h3>Objectives</h3>
<ol>
<li>Simple principle of work.</li>
<li>Migration painless process, people should be able to copy existence code and put on the worker and it should work.</li>
<li>Easy scalability, just add more workers on need.</li>
<li>Provide a simple and effortless way to deploy application across many servers.</li>
</ol>
<h3>Some concepts</h3>
<ol>
<li><strong>Client</strong>: The project has a list of workers, he choose one randomly and query a function or queue a job.</li>
<li><strong>Worker</strong>: C or C++ application with PHP embed, which listen a TCP port (probably 25887). The work can accept request from any where, but only a single IP (from the master process) can submit and deploy</li>
<li><strong>Master process</strong>: PHP web page, where the sysadmin can upload PHP code and &#8220;deploy&#8221; (submit to every worker).</li>
</ol>
<h3>System overview</h3>
<p><a href="http://cesar.la/wp-content/uploads/2009/03/phpserver.png"><img class="aligncenter size-medium wp-image-190" title="phpserver - system overview" src="http://cesar.la/wp-content/uploads/2009/03/phpserver-300x223.png" alt="phpserver - system overview" width="300" height="223" /></a><br />
The graphic above show how the system will look like, the clients (PHP scripts that runs on the webserver) can connect to any worker and request a function or queue a procedure. In the case of a function the client spects and response, otherwise it will not. The master process is the only one allowed to submiy PHP code to the workers, with this the system has an really easy way to deploy applications.</p>
<h3>Adventages</h3>
<ol>
<li>Single point of source code distributions.</li>
<li>There is not a manager process, the client speak directly to a worker, that keep it really simple and fault tolerant. In traditional models if the manager crash, nothing works.</li>
<li>I am plannig to add a Cache layer on the client, to avoid call same functions with same parameters, if the function is cacheable, in order to reduce the network latency.</li>
<li> It can be used to process large amount of datas in parallel, as hadoop does.</li>
</ol>
<img src="http://feeds.feedburner.com/~r/crodas/~4/x_JU4BVQrZk" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://cesar.la/php-application-server-gsoc-proposal.html/feed</wfw:commentRss>
		<feedburner:origLink>http://cesar.la/php-application-server-gsoc-proposal.html</feedburner:origLink></item>
		<item>
		<title>MVC Hecho en casa - Simple, lindo y efectivo</title>
		<link>http://feedproxy.google.com/~r/crodas/~3/JivrrhA0_lA/mvc-hecho-en-casa-simple-lindo-y-efectivo.html</link>
		<comments>http://cesar.la/mvc-hecho-en-casa-simple-lindo-y-efectivo.html#comments</comments>
		<pubDate>Mon, 02 Mar 2009 20:14:08 +0000</pubDate>
		<dc:creator>saddor@cesarodas.com (Cesar D. Rodas)</dc:creator>
		
		<category><![CDATA[Open Source]]></category>

		<category><![CDATA[PHP]]></category>

		<category><![CDATA[Programación]]></category>

		<guid isPermaLink="false">http://cesar.la/?p=132</guid>
		<description><![CDATA[Este post va dedicado a mi amiga Piojita, que gracias a sus  ganas de aprender tengo ánimos e ideas para escribir acá, ojalá puedan ser de utilidad a los que por miedo no preguntan
En estos días está muy de moda todo lo que sea MVC, que no es otra que escribir aplicaciones en tres [...]]]></description>
			<content:encoded><![CDATA[<blockquote><p>Este post va dedicado a mi amiga <a href="http://piojita.net/">Piojita</a>, que gracias a sus  ganas de aprender tengo ánimos e ideas para escribir acá, ojalá puedan ser de utilidad a los que por miedo no preguntan</p></blockquote>
<p>En estos días está muy de moda todo lo que sea <a href="http://es.wikipedia.org/wiki/Modelo_Vista_Controlador">MVC</a>, que no es otra que escribir aplicaciones en tres niveles, Modelo (acceso a los datos), Vista (la presentación al usuario) y el Controlador (Encargada de los eventos, y en muchos casos es el nexo entre el modelo y la vista). Como Rasmus dice en su post <a href="http://toys.lerdorf.com/archives/38-The-no-framework-PHP-MVC-framework.html">The non-framework PHP MVC Framework,</a> que en su época trajo polémica, utilizar frameworks tiene ventajas y desventajas, para mi gusto más desventajas que ventajas.</p>
<p>Primero que nada los frameworks webs convencionales, realizan muchas tareas automáticamente, y abstrae muchos detalles al programador que si bien ahora un montón de tiempo, no es efectiva, ya que asúme varías cosas por defecto. Cuando digo que no es efectiva hablo de que lo que se gana en tiempo, se pierde en el rendimiento de la aplicación, ¿de que nos sirve hacer una aplicación web en 5 minutos si sólo puede tener hasta 5 visitas en simultáneo? ¿No sería acaso mejor tardar 40 minutos y que soporte 30 visitas en simultáneo?, quizá  parezca una  exageración pero se acerca mucho a la realidad.</p>
<p>No estoy diciendo que utilizar frameworks es algo malo, depende de las necesidades del sitio web a ser realizado. &lt;ironic&gt;Si fuésemos radicales cada uno escribiría programas en asembler que corra con en nuestro propio sistema operativo,&lt;/ironic&gt;</p>
<p>Mi idea con esta entrada es mostrar que <strong>no sólo</strong> utilizando frameworks que <em>fuerzan a uno a utilizar uno u otro modelo de programación </em>es posible escribir aplicaciones web en poco tiempo manteniendo la simpleza y mantenibilidad del código como primer meta. En otras palabras escribiré, o al menos esbozaré, un <em>mini-framework</em> MVC en PHP.</p>
<h3>Modelo</h3>
<p>El modelo es, probablemente, la parte más delicada del sistema ya que es la encargada de interactuar con las bases de datos. Siempre es bueno diseñar una buena API de datos persistentes, para no tener que escribir SQL en todas partes. Aparte de mantener el código ordenado, ayuda a la legibilidad del mismo, ya que sabemos si hay un error en base de datos, sabremos con seguridad de que parte del código hay que <em>parchar</em>.</p>
<p>A mi me gusta usar clases para definir una tabla y relaciones, sería algo así como lo siguiente (no es código funcional, solo un ejemplo).</p>
<pre class="prettyprint" style="height: 300px;">&lt;?php
class Users {
    function GetAll() {
        return $this-&gt;Select();
    }

    function Select($params=array()) {
        $sql = "SELECT * FROM users";
        if (is_array($params) &amp;&amp; count($params)) {
            $where=array();
            foreach($values as $col=&gt;$val) {
                $where[] = "$col='".addslashes($val)."'";
            }
            $sql .= " WHERE ".implode(" and ",$where);
        }
        return db_exec($sql);
    }

    function Update($id,$values) {
        if (!is_numeric($id)||!is_array($values)||!count($values))
            return false;
        $id  = addslashes($id);
        $cols = "";
        foreach($values as $col=&gt;$val) {
            $cols .= "$col='".addslashes($val)."',";
        }
        $cols[strlen($cols)-1] = ' '; /* borrar el ultimo , */
        $sql = "UPDATE users SET $cols WHERE id = $id";
        db_exec($exec); /* call some db */
    }
}

?&gt;</pre>
<p>Algo un poco más automático es esta parte sería grandioso, es un poco molesto escribir mucho SQL, especialmente para las relaciones y esas cosas. Actualmente estoy trabajando, con un <a href="http://twitter.com/crisbarros">amigo brasilero</a>, en una implementación de ActiveRecord (con API similar al de AppEngine) para PHP 5 (es que quiero hacer algo útil también con PHP5). No voy a dar más detalles hasta que esté terminado, pero doy la primicia, se podrán definir relaciones en las clases.  Ejemplo:</p>
<pre class="prettyprint" style="height: 300px;">&lt;?php
class Author extends XXORM {
    function data() {
        $this-&gt;name = DB::String(array("size"=&gt;50,"required"=&gt;true));
        $this-&gt;book = DB::Relation("Books",DB::MANY);
    }
}

class Books extends XXORM {
    function data() {
        $this-&gt;author = DB::Relation("Author",DB::ONE);
        $this-&gt;title = DB::String(array("required"=&gt;true,"size"=&gt;50));
    }
}
?&gt;</pre>
<p>El proyecto, creara las estructuras de las tablas (si se ejecuta en modo development), también vendrá con una API para extender utilizando <a href="http://en.wikipedia.org/wiki/Hooking">Hooks</a>, especial para el cacheado de consultas  y demás. Se podrán crear filtros de validaciones por campos, entre otras caracteristicas, si están <a href="http://twitter.com/crodas">interesados pueden seguirme twitter</a></p>
<h3>La vista</h3>
<p>Una de las características de PHP es que puede ser mezclada con HTML, pues entonces ¿para que <em>el overhead</em> de utilizar un <em>template engine?</em></p>
<pre class="prettyprint">&lt;html&gt;
&lt;head&gt;
    &lt;title&gt;&lt;?php echo $title?&gt;&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;?php foreach($users as $user): ?&gt;
        &lt;?php echo $user?&gt;
    &lt;?php endforeach;?&gt;
&lt;/body&gt;
&lt;/html&gt;</pre>
<p>Algunos consejos, evitar los <em>short tags</em>(&lt;?=, &lt;?), evitar utilizar las llaves ({}) para ello utilizar los : y los end*; asi como el ejemplo.</p>
<h3>El controlador</h3>
<p>El controlador no es nada mas que una función que la mayoría del tiempo llama a la vista y al modelo, aunque no se limíta solamente a eso (ej. enviar un e-mail, subir un archivo de un a ftp, etc).</p>
<pre class="prettyprint" style="height: 300px;">&lt;?php

function user_controller($params) {
    if (
            !is_array($params) ||
            !isSet($params[1]) ||
            !is_numeric($params[1])
        )
            return false;
    /* llamamos el modelo */
    $dbu   = new User;
    $users = $dbu-&gt;Select(array("id"=&gt;$params[1]));
    /* incluimos la vista */
    /* la variable $users es visible para vista */
    include("vista.php");
}

?&gt;</pre>
<h3>Ruteo de URL a Controladores</h3>
<pre class="prettyprint" style="height: 300px;">&lt;?php
class Router {
    function AddRoute($reg_expr,$action) {
        if (!is_callable($action) &amp;&amp; !is_file($action))
            return false;
        $this-&gt;route[$reg_expr] = $action;
    }

    function FindAction($url) {
        $routes = &amp; $this-&gt;route;
        foreach((array)$routes as $route) {
            extract($route);
            if (preg_match($reg_expr,$url,$params)) {
                $ret = true;
                if (is_callable($action))
                    $ret = call_user_func($action,$params);
                else
                    include($action);
                return true;
            }
        }
        if (!isset($ret) &amp;&amp; !$ret)
            $this-&gt;err();
        return false;

    }

    function err() {
        header("HTTP/1.1 404 Not Found");
        include("not-found.php");
    }
}

?&gt;</pre>
<h3>Poniendo todo en orden</h3>
<p>Hasta ahora vimos el MVC, separados, ahora ¿como juntamos todo eso?, pues sería algo así</p>
<pre class="prettyprint" style="height: 300px;">&lt;?php
/* la clase de ruteo URL -&gt; Controlador*/
include("routes.php");
/* los modelos de datos */
include("model.php");
/* controladores */
include("controllers.php");

/* */
$router = new Router;
/* ruta hacia un controlador */
$router-&gt;addRoute('/user\/([0-9]+)$/i',"user_controller");
/* ruta hacia una vista, por no se necesite un */
/* controlador */
$router-&gt;addRoute("/","principal.php");
#... Demas reglas

/*
 * buscamos el controlador, basado en el URI,
 * suponiendo que tenemos el URL Rewrite activado
 * un uri com "/user/11" haria match, y se ejecutaria
 * un controlador.
 */
$route-&gt;FindAction($_SERVER['REQUEST_URI']);
?&gt;</pre>
<p>Como verán, un poco de orden en la forma de programar, utilizando un mini-framework, que en realidad son buenos hábitos a la hora de programar, fácilita nuestro trabajo (y de los que mantendrán nuestro código), a la vez de hacerlo efecto (¿para que derrochar valiosos ciclos de procesador?).</p>
<img src="http://feeds.feedburner.com/~r/crodas/~4/JivrrhA0_lA" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://cesar.la/mvc-hecho-en-casa-simple-lindo-y-efectivo.html/feed</wfw:commentRss>
		<feedburner:origLink>http://cesar.la/mvc-hecho-en-casa-simple-lindo-y-efectivo.html</feedburner:origLink></item>
		<item>
		<title>How to unlock the audio device on fedora</title>
		<link>http://feedproxy.google.com/~r/crodas/~3/lNhnOeTHw90/how-to-unlock-the-audio-device-on-fedora.html</link>
		<comments>http://cesar.la/how-to-unlock-the-audio-device-on-fedora.html#comments</comments>
		<pubDate>Tue, 24 Feb 2009 02:25:00 +0000</pubDate>
		<dc:creator>saddor@cesarodas.com (Cesar D. Rodas)</dc:creator>
		
		<category><![CDATA[English]]></category>

		<category><![CDATA[GNU/Linux]]></category>

		<category><![CDATA[Open Source]]></category>

		<category><![CDATA[Programación]]></category>

		<category><![CDATA[Shell Scripting]]></category>

		<guid isPermaLink="false">http://cesar.la/?p=119</guid>
		<description><![CDATA[If use Fedora (I didn&#8217;t get yet this problems on Debian nor FreeBSD), probably you got stuck with the famous &#8220;Audio Device  Locked&#8221; (or some similar text) when your viewing a flash-video on firefox. It is really annoying restart the computer or Xorg to solve that little problem, so I decide to Googling about its [...]]]></description>
			<content:encoded><![CDATA[<p>If use Fedora (I didn&#8217;t get yet this problems on Debian nor FreeBSD), probably you got stuck with the famous &#8220;Audio Device  Locked&#8221; (or some similar text) when your viewing a flash-video on firefox. It is really annoying restart the computer or Xorg to solve that little problem, so I decide to Googling about its answer, despite I didn&#8217;t found anything, then I&#8217;ve tried a simple command that works, so I am sharing here a solution.</p>
<p>Execute the follow command as root, </p>
<pre class="prettyprint">
$ kill -9 `lsof -t /dev/snd/*  2> /dev/null`
</pre>
<p>Warning, the previous command will close all the audio programs (i.e xmms, amarok, etc).</p>
<p>I love UNIX, I can&#8217;t figure out live without it.</p>
<img src="http://feeds.feedburner.com/~r/crodas/~4/lNhnOeTHw90" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://cesar.la/how-to-unlock-the-audio-device-on-fedora.html/feed</wfw:commentRss>
		<feedburner:origLink>http://cesar.la/how-to-unlock-the-audio-device-on-fedora.html</feedburner:origLink></item>
		<item>
		<title>Concatenando videos</title>
		<link>http://feedproxy.google.com/~r/crodas/~3/yrJTTndmFK4/concatenando-videos.html</link>
		<comments>http://cesar.la/concatenando-videos.html#comments</comments>
		<pubDate>Mon, 16 Feb 2009 00:05:01 +0000</pubDate>
		<dc:creator>saddor@cesarodas.com (Cesar D. Rodas)</dc:creator>
		
		<category><![CDATA[Open Source]]></category>

		<category><![CDATA[Programación]]></category>

		<category><![CDATA[Shell Scripting]]></category>

		<guid isPermaLink="false">http://cesar.la/?p=110</guid>
		<description><![CDATA[Si son como yo, de los que se pasa  bajando videos de sitios (ya que no es un delito), se habran encontrado con los videos que vienen en dos partes (especialmente los conciertos musicales). Bueno, aquí  comparto en este post relámpago como hacerlo:

#!/bin/bash
#el archivo de salida
SALIDA="concat.avi"
#  si tienen poco espacio en disco [...]]]></description>
			<content:encoded><![CDATA[<p>Si son como yo, de los que se pasa  bajando videos de sitios (<a href="http://www.youtube.com/watch?v=beFxvwEMQFU">ya que no es un delito</a>), se habran encontrado con los videos que vienen en dos partes (especialmente los conciertos musicales). Bueno, aquí  comparto en este post relámpago como hacerlo:</p>
<pre class="prettyprint">
#!/bin/bash
#el archivo de salida
SALIDA="concat.avi"
#  si tienen poco espacio en disco pal-vcd es mejor
ARGS="-target pal-dvd"
# archivo temporal, si o si tiene que ser mpg
TMP="concat.mpg"
> $TMP

for i in "$@"
do
    ffmpeg -i "$i" $ARGS - >> $TMP
done
ffmpeg -i "$TMP" $SALIDA
rm -rf $TMP
</pre>
<p>Su utilización es sencilla</p>
<pre class="prettyprint">
$ ./concat.sh video-part-1.avi video-part-2.avi video-part3.avi
</pre>
<img src="http://feeds.feedburner.com/~r/crodas/~4/yrJTTndmFK4" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://cesar.la/concatenando-videos.html/feed</wfw:commentRss>
		<feedburner:origLink>http://cesar.la/concatenando-videos.html</feedburner:origLink></item>
		<item>
		<title>Los “ayudadores” del calamar</title>
		<link>http://feedproxy.google.com/~r/crodas/~3/xlmFXSzlP8Q/los-ayudadores-del-calamar.html</link>
		<comments>http://cesar.la/los-ayudadores-del-calamar.html#comments</comments>
		<pubDate>Thu, 29 Jan 2009 19:33:50 +0000</pubDate>
		<dc:creator>saddor@cesarodas.com (Cesar D. Rodas)</dc:creator>
		
		<category><![CDATA[FreeBSD]]></category>

		<category><![CDATA[GNU/Linux]]></category>

		<category><![CDATA[Network]]></category>

		<category><![CDATA[Open Source]]></category>

		<category><![CDATA[Programación]]></category>

		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://cesar.la/?p=79</guid>
		<description><![CDATA[El título les parecerá que este entrada sería una mera perdida de tiempo, que sería un off-topic total o una entrada de la GreenPeace, pero no es así es que quería ser nacionalista y escribir en Español (Squid helpers).
Hoy en día necesité  autenticar un Squid-cache contra el Active Directory de Windows, y como a la [...]]]></description>
			<content:encoded><![CDATA[<p>El título les parecerá que este entrada sería una mera perdida de tiempo, que sería un off-topic total o una entrada de la GreenPeace, pero no es así es que quería ser nacionalista y escribir en Español (Squid helpers).</p>
<p>Hoy en día necesité  autenticar un Squid-cache contra el Active Directory de Windows, y como a la primera no me funcionó el helper LDAP que viene por defecto escribí un pequeño script en python que funciona, capaz a alguien le sea útil.</p>
<pre class="prettyprint">#!/usr/bin/env python  

import ldap, sys
from syslog import *

LDAP_SERVER='ldap://' + sys.argv[1]
try:
    ldap_client = ldap.initialize(LDAP_SERVER)
except:
    syslog(LOG_ERR,"Couldn't connect to the LDAP")
    sys.exit()

while (1):
    try:
        (user,passwd) = sys.stdin.readline().strip().split(" ")
        ldap_client.simple_bind_s(user,passwd)
        syslog(LOG_INFO,"%s login" % user)
        # Login success
        print "OK"
    except:
        syslog(LOG_INFO,"%s login failed" % user)
        # Sorry, an error
        print "ERR"
        sys.stdout.flush() # Requerido en algunas distros
ldap_client.unbind()</pre>
<p>Es un simple script como lo ven, puede estar escrito en cualquier lenguaje (que tenga stdin y stdout) como PHP, C, Ruby, Haskell, Bash, pero elegí python para mostrar que tambíen hablo otro lenguajes (aparte de PHP y C). Tambíen pueden autenticar contra cualqueir cosa (ejemplo contra una DB como hacen acá) y por ejemplo asignar usuario por tiempos. Por último, para configurar el helper (asumiendo que el 192.168.1.1 es el servidor de ActiveDirectory):</p>
<pre class="prettyprint">auth_param basic program /path/to/login.py 192.168.1.1

# Aquí vi que algunos muggles que ponian 20, es muy alto, y no vale la pena
# a no ser que se tenga miles de usuarios.
auth_param basic children 5 

auth_param basic realm Type your password
# tiempo que será valido el login, para no hacer
# overhead tendría que ser un tiempo razonable
auth_param basic credentialsttl 5 minutes</pre>
<p>Espero que mis días como sysadm lleguen a su fin, extraño los días de programar para vivir, no es lo mismo que pase a ser solo un hobbie.</p>
<img src="http://feeds.feedburner.com/~r/crodas/~4/xlmFXSzlP8Q" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://cesar.la/los-ayudadores-del-calamar.html/feed</wfw:commentRss>
		<feedburner:origLink>http://cesar.la/los-ayudadores-del-calamar.html</feedburner:origLink></item>
		<item>
		<title>SQLite - Una breve intro</title>
		<link>http://feedproxy.google.com/~r/crodas/~3/KuznDqWAeqc/sqlite-una-breve-intro.html</link>
		<comments>http://cesar.la/sqlite-una-breve-intro.html#comments</comments>
		<pubDate>Tue, 27 Jan 2009 21:34:34 +0000</pubDate>
		<dc:creator>saddor@cesarodas.com (Cesar D. Rodas)</dc:creator>
		
		<category><![CDATA[C]]></category>

		<category><![CDATA[DB]]></category>

		<category><![CDATA[Open Source]]></category>

		<category><![CDATA[Programación]]></category>

		<guid isPermaLink="false">http://cesar.la/?p=63</guid>
		<description><![CDATA[Hace varios años conocí SQLite, una excelente base de datos escrita por D. Ricard Hipp, quien también escribió otros proyectos como CVSTrac (sirvió de inspiración para el famoso The Trac), Fossil-SCM el scm que adoro, entre otros proyectos. La idea de escribir sobre SQLite mientras leía el artículo sobre SQLite en el IPhone
Lo que me [...]]]></description>
			<content:encoded><![CDATA[<p>Hace varios años conocí <a href="http://sqlite.org/">SQLite</a>, una excelente base de datos escrita por <a href="http://en.wikipedia.org/wiki/D._Richard_Hipp">D. Ricard Hipp</a>, quien también escribió otros proyectos como <a href="http://www.cvstrac.org/">CVSTrac</a> (sirvió de inspiración para el famoso <a href="http://trac.edgewall.org/wiki/CvsTrac">The Trac</a>), <a href="http://www.fossil-scm.org/">Fossil-SCM</a> el scm que adoro, entre otros proyectos. La idea de escribir sobre SQLite mientras leía el artículo sobre <a href="http://www.notasdesamuel.com/usando-sqlite-en-el-iphone-tips-que-tal-vez-no-sabias-de-tu-iphone-part-iii/">SQLite en el IPhone</a></p>
<p>Lo que me gusta de <a href="http://sqlite.org/">SQLite</a> es que su API es muy sencilla y que cuanta con cosas para los perezosos (&#8221;sqlite3_execute&#8221;) y con cosas para personas que piensan que lo primordial es el performance. Un código vale más que mil palabras, miren un pequeño ejemplo de SQLite&#8230;</p>
<pre class="prettyprint">/**
 * Coded by crodas,
 *
 * The author disclaims the copyright of this code.
 */
#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;sqlite3.h&gt;

int table_exists(sqlite3 * dbh, const char * table) {
    sqlite3_stmt* pStmtPrep;
    int rc,exists;
    /* preparamos el SQL a ejecutar, muy util para evitar SQL injections */
    rc=sqlite3_prepare(dbh,"select * from sqlite_master where type='table' and name=?",-1 /* null terminated str*/, &amp;pStmtPrep,NULL);
    if (rc!=SQLITE_OK) {
        printf("This is an SQL bug %s",sqlite3_errmsg(dbh));
        exit(-1);
    }

    /* asignamos a la primera variabla (?) el valor de table*/
    sqlite3_bind_text(pStmtPrep,1,table,-1,0);

    /* ejecutamos */
    rc = sqlite3_step(pStmtPrep);
    switch(rc) {
        case SQLITE_ERROR:
        case SQLITE_BUSY:
            printf("Database locked or unknown error");
            fflush(stdout);
            exit(-1);
            break;
        case SQLITE_DONE:
            exists = -1; /* no existe */
            break;
        case SQLITE_ROW:
            exists = 1; /* existe */

    }

    /* a liberar memoria! */
    sqlite3_finalize(pStmtPrep);
    return exists;
}

int main() {
    sqlite3 *  dbh;
    int rc,i;
    sqlite3_stmt* pStmtPrep;

    if (sqlite3_open_v2("test.db",&amp;dbh,SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE,0)!=SQLITE_OK) {
        printf("Can't  open db, please check permissions on this folder. %s\n",sqlite3_errmsg(dbh));
        return -1;
    }

    /**
     *  Hice una pequenha funcion que ve si existe.
     *  lo bueno de la funcion es que muestra el primer ejemplo
     *  el SQLPrepare, y muestra como saber si la consulta
     *  tiene resultado o no
     */
    if (table_exists(dbh,"testing")==-1) {
        printf("Table doesn't exists,execute\n");
        /* tabla sencilla, utilizo exec porque no espero resultado */
        sqlite3_exec(dbh,"create table testing (id int, text varchar(250))",0,0,0);
        /* sql preparada para el insert */

        int data_id[] = {5,5,5,8,0}; /* el ID no es PK, en la vida real seria PK*/
        const char*  data_data[] = {"Some text","Another text","foobar","This is the 8 text",0};
        rc=sqlite3_prepare(dbh,"insert into testing values(?,?)",-1, &amp;pStmtPrep,NULL);
        /* no controlo nada porque ya mostre en la funcion anterior como controlar errores */
        for(i=0;;i++) {
            if (data_id[i] == 0) break;
            /* cambiamos ? ? por sus valores */
            sqlite3_bind_int(pStmtPrep,1,data_id[i]);
            sqlite3_bind_text(pStmtPrep,2,data_data[i],-1,0);

            /* ejecutamos */
            rc=sqlite3_step(pStmtPrep);
            /* se tendria que controlar la salida*/

            /* ya que no hay ciclos, para cambiar los parametros */
            /* debemos reinicar al Statement */
            sqlite3_reset(pStmtPrep);
        }

        sqlite3_finalize(pStmtPrep);
    }

    /* ahora queremos los datos con id 5,6,7,8 */
    int data[] = {5,6,7,8,0};
    char * text;
    rc=sqlite3_prepare(dbh,"select * from testing where id=?",-1 /* null terminated str*/, &amp;pStmtPrep,NULL);
    /* no controlo nada porque ya mostre en la funcion anterior como controlar errores */
    for(i=0;;i++) {
        if (data[i] == 0) break;
        /* asignar valor a ? */
        sqlite3_bind_int(pStmtPrep,1,data[i]);
        /* mientas haya resultado */
        while (sqlite3_step(pStmtPrep)==SQLITE_ROW) {
            text = sqlite3_column_text(pStmtPrep,1); /* id = 0, text=1 */
            printf("%d: %s\n",data[i],text);
        }

        /* reinicar el stmt */
        sqlite3_reset(pStmtPrep);
    }

    /* */
    sqlite3_finalize(pStmtPrep);

    sqlite3_close(dbh);
}</pre>
<p>Lo que me gusta es que tenemos a toda una base de datos relacional en nuestro programa, y si de rendimiento se trata se puede hacer &#8220;prepare&#8221; de todas las consultas SQL al principio del programa y luego ir ejecutando, no es cosa complicada,  se ahoraría un montón de tiempo y procesador.</p>
<p>Otra cosa que me gusta mucho es que fácilmente extendible, una vez necesitaba una función para comprimir y descomprimir (la función compress y decompress del MySQL), <a href="http://www.mail-archive.com/sqlite-users@sqlite.org/msg17018.html">envíe mi consulta en la lista de SQLite</a>, y Dr. Hipp me respondío lo siguiente:</p>
<pre class="prettyprint">/*
** SQL function to compress content into a blob using libz
*/
static void compressFunc(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  int nIn, nOut;
  long int nOut2;
  const unsigned char *inBuf;
  unsigned char *outBuf;
  assert( argc==1 );
  nIn = sqlite3_value_bytes(argv[0]);
  inBuf = sqlite3_value_blob(argv[0]);
  nOut = 13 + nIn + (nIn+999)/1000;
  outBuf = malloc( nOut+4 );
  outBuf[0] = nIn&gt;&gt;24 &amp; 0xff;
  outBuf[1] = nIn&gt;&gt;16 &amp; 0xff;
  outBuf[2] = nIn&gt;&gt;8 &amp; 0xff;
  outBuf[3] = nIn &amp; 0xff;
  nOut2 = (long int)nOut;
  compress(&amp;outBuf[4], &amp;nOut2, inBuf, nIn);
  sqlite3_result_blob(context, outBuf, nOut2+4, free);
}

/*
** An SQL function to decompress.
*/
static void uncompressFunc(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  unsigned int nIn, nOut, rc;
  const unsigned char *inBuf;
  unsigned char *outBuf;
  long int nOut2;

  assert( argc==1 );
  nIn = sqlite3_value_bytes(argv[0]);
  if( nIn&lt;=4 ){
    return;
  }
  inBuf = sqlite3_value_blob(argv[0]);
  nOut = (inBuf[0]&lt;&lt;24) + (inBuf[1]&lt;&lt;16) + (inBuf[2]&lt;&lt;8) + inBuf[3];
  outBuf = malloc( nOut );
  nOut2 = (long int)nOut;
  rc = uncompress(outBuf, &amp;nOut2, &amp;inBuf[4], nIn);
  if( rc!=Z_OK ){
    free(outBuf);
  }else{
    sqlite3_result_blob(context, outBuf, nOut2, free);
  }
}

/* Make the functions above accessible to SQLite as follows:
*/
  sqlite3_create_function(db, "compress", 1, SQLITE_UTF8, 0,
     compressFunc, 0, 0);
  sqlite3_create_function(db, "uncompress", 1, SQLITE_UTF8, 0,
     uncompressFunc, 0, 0);</pre>
<p>Como vieron no es cosa de otro mundo, muy sencillo, y ya extendimos SQLite!. Ahora que estaré de vacaciones empiezaré a jugar con el SQlite VFS, veremos que sale&#8230;</p>
<img src="http://feeds.feedburner.com/~r/crodas/~4/KuznDqWAeqc" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://cesar.la/sqlite-una-breve-intro.html/feed</wfw:commentRss>
		<feedburner:origLink>http://cesar.la/sqlite-una-breve-intro.html</feedburner:origLink></item>
		<item>
		<title>Seven Things you might not know about me</title>
		<link>http://feedproxy.google.com/~r/crodas/~3/C-T-kTgUm0U/seven-things-you-might-not-know-about-me.html</link>
		<comments>http://cesar.la/seven-things-you-might-not-know-about-me.html#comments</comments>
		<pubDate>Sat, 10 Jan 2009 22:10:55 +0000</pubDate>
		<dc:creator>saddor@cesarodas.com (Cesar D. Rodas)</dc:creator>
		
		<category><![CDATA[English]]></category>

		<category><![CDATA[Open Source]]></category>

		<category><![CDATA[Personal]]></category>

		<guid isPermaLink="false">http://cesar.la/?p=61</guid>
		<description><![CDATA[
Last week I was &#8220;pinged&#8221; by two Brazilians friends (Augusto and Bruno &#8220;Porkaria&#8221;) to follow a funny chain of blog posts, and I read a lot about this on several blogs and it is funny, I never thought that I&#8217;d could be included in the circle, so now I&#8217;m in, so here I come (I [...]]]></description>
			<content:encoded><![CDATA[<p><ins datetime="2009-01-10T19:12:32+00:00"></ins></p>
<p>Last week I was &#8220;pinged&#8221; by two Brazilians friends (<a href="http://www.augustopascutti.com/dev/seven-things-you-might-not-know-about-me">Augusto</a> and <a href="http://porkaria.wordpress.com/2009/01/08/sete-coisas-que-provavelmente-voce-nao-sabe-sobre-mim-seven-things-that-probably-you-may-not-know-about-me/">Bruno &#8220;Porkaria&#8221;</a>) to follow a funny chain of blog posts, and I read a lot about this on several blogs and it is funny, I never thought that I&#8217;d could be included in the circle, so now I&#8217;m in, so here I come (I apologise, probably I am not very interesting).</p>
<ol>
<li>I start coding with Visual Basic 5 (my dark side), then I switch to PHP3.</li>
<li>I love Metal Music (heavy, death, black, heavy), and to me there is not other kind of music.</li>
<li>I disliked PHP5 &#8216;coz it&#8217;s look as a Java&#8217;s ripe off, but now I am trying out, and it looks nice, probably I will drop off PHP4 soon.</li>
<li>I&#8217;d like to be a designer, but it&#8217;s really really hard, I know CSS and the basic of GIMP, but still I don&#8217;t have inspiration,</li>
<li>I want to work outside this country ASAP, and no one wants to hire me, I think I need to finish my University first, <img src='http://cesar.la/wp-includes/images/smilies/icon_sad.gif' alt=':(' class='wp-smiley' /> </li>
<li>I am coke addict, I can&#8217;t live without it (1l per day), I need to leave it ASAP,</li>
<li>I don&#8217;t like beer nor Whisky, I prefer Sprite + sugar + Vodka.</li>
</ol>
<p><strong>Now let&#8217;s choose seven people (I don&#8217;t warranty they will follow this chain):</strong></p>
<ul>
<li><a href="http://gallir.wordpress.com/">Richardo Galli</a>: He is a PHP/Ninja, a great GTalk friend, and the creator of <a href="http://meneame.net/">Menéame.net</a>, He is the second guy that I met with a profile in Wikipedia (English &amp;&amp; Spanish).</li>
<li><a href="http://www.phpclasses.org/blog">Manuel Lemos</a>: The greatest PHPDev I meet in person, I don&#8217;t think he will write about this (usually he is busy), but let&#8217;s try.</li>
<li><a href="http://matt.techagau.com.py/">Matias Insaurralde</a>: He is a &#8220;Railer&#8221; but I am PHPzing him&#8230; soon he will be a great PHPdev.</li>
<li><a href="http://blog.feliperibeiro.com/">Felipe Ribeiro</a>: A great friend, he taught me &#8217;bout the RESTful in one great talk in ConaPHP 2008.</li>
<li><a href="http://pablo.lnxsoluciones.com/">Pablo Castillo</a>: Great developer, great friend&#8230; together we&#8217;re planning to move this poor country.</li>
<li><a href="http://ma.tt/">Matt Mullenweg</a>: Everybody knows him, I meet him at the Latinoware 2008, very nice person.</li>
<li><a href="http://calaveradigital.blogspot.com/">Matias Montes</a>: I meet him at the Latinoware 2008, great speecher, great PHPdev.</li>
</ul>
<p>I have several other friend, but probably they already done this, or they don&#8217;t have a blog (as my friend Cristian Medeiros, come on man open a blog!)<br/><br />
<strong>Rules are quite simple:</strong><br/><br />
- Link your Original tagger(s), and list these rules on you blog<br/><br />
- Share seven facts about yourself in the post - some random, some weird.<br/><br />
- Tag seven people at the end of your post by leaving their names and the links to their blogs.<br/><br />
- Let them know they&#8217;ve been tagged by leaving a comment on their blogs and/or Twitter.<br/></p>
<img src="http://feeds.feedburner.com/~r/crodas/~4/C-T-kTgUm0U" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://cesar.la/seven-things-you-might-not-know-about-me.html/feed</wfw:commentRss>
		<feedburner:origLink>http://cesar.la/seven-things-you-might-not-know-about-me.html</feedburner:origLink></item>
		<item>
		<title>“You type, we guess” (mi nuevo juguete)</title>
		<link>http://feedproxy.google.com/~r/crodas/~3/G3QoZrgGATc/you-type-we-guess-mi-nuevo-juguete.html</link>
		<comments>http://cesar.la/you-type-we-guess-mi-nuevo-juguete.html#comments</comments>
		<pubDate>Sun, 04 Jan 2009 20:38:38 +0000</pubDate>
		<dc:creator>saddor@cesarodas.com (Cesar D. Rodas)</dc:creator>
		
		<category><![CDATA[Open Source]]></category>

		<guid isPermaLink="false">http://cesar.la/?p=60</guid>
		<description><![CDATA[Les presento mi nuevo jueguete, Language Guess, una pagina que hice para poner en practica mis conocimientos sobre clasificación  de textos, al mismo tiempo para poner en producción mi futura contribución para PHPClasses y crear mi primer webservice RESTful (esta ultima parte todavía no termine).
Algunos de mis beta testers (osea gtalk-friends) creyeron al principio [...]]]></description>
			<content:encoded><![CDATA[<p>Les presento mi nuevo jueguete, <a href="http://www.languess.com/">Language Guess</a>, una pagina que hice para poner en practica mis <a href="http://www.prophp.com.br/downloads/phpconf2007/text_categorization.zip">conocimientos sobre clasificación  de textos</a>, al mismo tiempo para poner en producción mi futura contribución para <a href="http://cesars.users.phpclasses.org/">PHPClasses</a> y crear mi primer webservice RESTful (esta ultima parte todavía no termine).</p>
<p>Algunos de mis beta testers (osea <em>gtalk-friends</em>) creyeron al principio que solo utilizaba el <a href="http://code.google.com/apis/ajaxlanguage/documentation/#Translation">API de Google</a>, cosa que ni sabia que existía. Afortunadamente hace algún tiempo atrás pude ver la luz al leer el <a href="http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.53.9367">Paper que cambio mi forma de pensar</a>, desde ahí me tuve la idea de armar un como languess.com, hasta que finalmente le gané a la pereza y ahí lo tienen.</p>
<p>Obviamente es casi imposible que sea perfecto, pero según mis pruebas detectaba bastante bien. Claro que si se equivoca se le puede enseñar y la próxima vez que genere los n-gramas aprenderá mejor.</p>
<p>Ahora mismo languess aprendió Español, Ingles, Francés y Portugués teniendo como ejemplo la Santa Biblia (obviamente en cada idioma citado), y por su parte Alemán y Esperanto gracias a los ejemplos proveídos por <a href="http://matt.techagau.com.py/">Matias</a> que hizo un script en 5 min. (probablemente en ruby) que extrae textos de Wikipedia. Si alguien tiene textos puede enviarme a mi mail asi Languess puede aprender mas y mas idiomas (no se necesitan muchos textos de ejemplos, pero mientras mas mejor), seria genial si alguien puede enviarme algo de Guaraní.</p>
<p>Para el futuro queda afinar el detector para que sea casi perfecto, para ello <em>creo</em> que tengo que afinar el método de aprendizaje, pero hay una sola forma de saber, con las pruebas de los visitantes.</p>
<p>Saludos a todos, y feliz a&ntilde;o 2009.</p>
<img src="http://feeds.feedburner.com/~r/crodas/~4/G3QoZrgGATc" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://cesar.la/you-type-we-guess-mi-nuevo-juguete.html/feed</wfw:commentRss>
		<enclosure url="http://www.prophp.com.br/downloads/phpconf2007/text_categorization.zip" length="340253" type="application/zip" /><media:content url="http://www.prophp.com.br/downloads/phpconf2007/text_categorization.zip" fileSize="340253" type="application/zip" /><itunes:explicit>clean</itunes:explicit><itunes:subtitle>Les presento mi nuevo jueguete, Language Guess, una pagina que hice para poner en practica mis conocimientos sobre clasificación de textos, al mismo tiempo para poner en producción mi futura contribución para PHPClasses y crear mi primer webservice RESTfu</itunes:subtitle><itunes:author>Cesar D. Rodas</itunes:author><itunes:summary>Les presento mi nuevo jueguete, Language Guess, una pagina que hice para poner en practica mis conocimientos sobre clasificación de textos, al mismo tiempo para poner en producción mi futura contribución para PHPClasses y crear mi primer webservice RESTful (esta ultima parte todavía no termine). Algunos de mis beta testers (osea gtalk-friends) creyeron al principio [...]</itunes:summary><itunes:keywords>internet,php,mysql,apache,server,saddor</itunes:keywords><feedburner:origLink>http://cesar.la/you-type-we-guess-mi-nuevo-juguete.html</feedburner:origLink></item>
		<item>
		<title>La “blogosfera” Paraguaya en un solo lugar…</title>
		<link>http://feedproxy.google.com/~r/crodas/~3/uA-gfcnhfes/la-blogosfera-paraguaya-en-un-solo-lugar.html</link>
		<comments>http://cesar.la/la-blogosfera-paraguaya-en-un-solo-lugar.html#comments</comments>
		<pubDate>Wed, 17 Dec 2008 19:24:58 +0000</pubDate>
		<dc:creator>saddor@cesarodas.com (Cesar D. Rodas)</dc:creator>
		
		<category><![CDATA[Open Source]]></category>

		<guid isPermaLink="false">http://cesar.la/?p=58</guid>
		<description><![CDATA[Hace dos días, si mal no recuerdo, entre en contacto con César Sanchez, paraguayo que vive en Argentina, y chateando surgió la idea de hacer una página para mostrar los blogs nacionales, aprovechando que desde hace algún tiempo he querido hacer algo similar pero no tan elitista (como los actuales) sobre PHP (http://phpne.ws).
A simple vista [...]]]></description>
			<content:encoded><![CDATA[<p>Hace dos días, si mal no recuerdo, entre en contacto con <a href="http://www.thelemongroup.blogspot.com/">César Sanchez</a>, paraguayo que vive en Argentina, y chateando surgió la idea de hacer una página para mostrar los blogs nacionales, aprovechando que desde hace algún tiempo he querido hacer algo similar pero no tan <em>elitista </em>(como los actuales) sobre PHP (http://phpne.ws).</p>
<p>A simple vista parece una simple instalación del los Planetarios (ej: <a href="http://planet-php.net/">Planet PHP</a>), pero no, aunque el diseño es totalmente copiado (como podrán ver, no soy diseñador.. diseñadores.. donde estan??) el código no tiene nada que ver con el Planetario. Se preguntaran por que&#8230; y simplemente porque yo quería <a href="http://www.phpclasses.org/browse/author/232276.html">usar mis clases</a> y armar algo 100% paraguayo y que funcione con PHP4 y PHP5.  Además ya que programé toda la página es sencilla extender.</p>
<p>Ahora lo que estoy viendo que haría falta es organizar los posts por temas, ciudades, departamentos e idiomas, para que sea más útil, comentarios y sugerencias son bienvenidos.</p>
<p>Los fuentes del sitio son está muy beta, pero si la gente está interesada puedo estructurar mejor y liberar como Open Source (claro como BSD).</p>
<p><a href="http://pygosfera.com/">PyGosfera</a> es el nombre, como se darán cuenta no soy muy creativo, también se aceptan sugerencias para nombre nuevo&#8230; <img src='http://cesar.la/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Saludos y que lo disfruten.</p>
<img src="http://feeds.feedburner.com/~r/crodas/~4/uA-gfcnhfes" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://cesar.la/la-blogosfera-paraguaya-en-un-solo-lugar.html/feed</wfw:commentRss>
		<feedburner:origLink>http://cesar.la/la-blogosfera-paraguaya-en-un-solo-lugar.html</feedburner:origLink></item>
		<item>
		<title>El nuevo jueguete.. “is out”</title>
		<link>http://feedproxy.google.com/~r/crodas/~3/BYjrnNPnVQE/el-nuevo-jueguete-is-out.html</link>
		<comments>http://cesar.la/el-nuevo-jueguete-is-out.html#comments</comments>
		<pubDate>Thu, 11 Dec 2008 17:12:09 +0000</pubDate>
		<dc:creator>saddor@cesarodas.com (Cesar D. Rodas)</dc:creator>
		
		<category><![CDATA[GNU/Linux]]></category>

		<category><![CDATA[PHP]]></category>

		<category><![CDATA[Personal]]></category>

		<category><![CDATA[ue]]></category>

		<guid isPermaLink="false">http://cesar.la/?p=57</guid>
		<description><![CDATA[Después de el lanzamiento de File S3, gracias al feedback de los diggers y de amigos, me sentí realizado ya que pude dejar la pereza a un lado y comenzar a hacer sitios webs que tengo planeado desde hace varios meses o inclusos años.
Ahora les presento mi nuevo juguete read2.us (Read to us), un página [...]]]></description>
			<content:encoded><![CDATA[<p>Después de el lanzamiento de <a href="http://files3.com/">File S3</a>, gracias al <em>feedback</em> de los <em>diggers</em> y de amigos, me sentí realizado ya que pude dejar la <em>pereza</em> a un lado y comenzar a hacer sitios webs que tengo planeado desde hace varios meses o inclusos años.</p>
<p>Ahora les presento mi nuevo juguete <a href="http://read2.us/">read2.us</a> (Read to us), un página web que hace <em>text to speech</em>, es decir genera un <em>mp3</em> apartir de un texto ingresado. Ahora mismo<em> </em>son soportados el Español y el Inglés.</p>
<p>Aquí les dejo una pequeña prueba de como suena. Obviamente faltan algunos detalles para el parseado mismo del texto, es decir para que lea correo electrónico, páginas webs y demás detalles que estare terminando lo más rápido posible.<span id="more-57"></span></p>
<p><object type="application/x-shockwave-flash" data="http://read2-us.partners.clusters.files3.com/player.swf?son=http%3A%2F%2Fread2-us.partners.clusters.files3.com%2Fd2ddea18f00665ce8623e36bd4e3c7c5.mp3&#038;autoplay=1" width="200" height="20"><param name="movie" value="http://read2-us.partners.clusters.files3.com/player.swf?son=http%3A%2F%2Fread2-us.partners.clusters.files3.com%2Fd2ddea18f00665ce8623e36bd4e3c7c5.mp3&#038;autplay=1" /></object></p>
<p>Luego si el proyecto tiene la atención y el <em>feedback</em> que estoy esperando crearé algún webservice para la generación de audios de textos, para por ejemplo poner a algún diario, blogs o cualquier otro sitio. Así los que tienen visión disminuida podrán disfrutar de la web.</p>
<p>Está por demás decir que el servicio es <em>beta,</em> y que tendrá algunos inconvenientes, pero daré lo mejor de mí para que el proyecto siga adelante.</p>
<img src="http://feeds.feedburner.com/~r/crodas/~4/BYjrnNPnVQE" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://cesar.la/el-nuevo-jueguete-is-out.html/feed</wfw:commentRss>
		<enclosure url="http://read2-us.partners.clusters.files3.com/player.swf?son=http%3A%2F%2Fread2-us.partners.clusters.files3.com%2Fd2ddea18f00665ce8623e36bd4e3c7c5.mp3&amp;#038;autoplay=1" length="4795" type="application/x-shockwave-flash" /><media:content url="http://read2-us.partners.clusters.files3.com/player.swf?son=http%3A%2F%2Fread2-us.partners.clusters.files3.com%2Fd2ddea18f00665ce8623e36bd4e3c7c5.mp3&amp;#038;autoplay=1" fileSize="4795" type="application/x-shockwave-flash" /><itunes:explicit>clean</itunes:explicit><itunes:subtitle>Después de el lanzamiento de File S3, gracias al feedback de los diggers y de amigos, me sentí realizado ya que pude dejar la pereza a un lado y comenzar a hacer sitios webs que tengo planeado desde hace varios meses o inclusos años. Ahora les presento mi</itunes:subtitle><itunes:author>Cesar D. Rodas</itunes:author><itunes:summary>Después de el lanzamiento de File S3, gracias al feedback de los diggers y de amigos, me sentí realizado ya que pude dejar la pereza a un lado y comenzar a hacer sitios webs que tengo planeado desde hace varios meses o inclusos años. Ahora les presento mi nuevo juguete read2.us (Read to us), un página [...]</itunes:summary><itunes:keywords>internet,php,mysql,apache,server,saddor</itunes:keywords><feedburner:origLink>http://cesar.la/el-nuevo-jueguete-is-out.html</feedburner:origLink></item>
		<item>
		<title>Por esto amo el Open Source!</title>
		<link>http://feedproxy.google.com/~r/crodas/~3/n3SvzMX9fMc/por-esto-amo-el-open-source.html</link>
		<comments>http://cesar.la/por-esto-amo-el-open-source.html#comments</comments>
		<pubDate>Tue, 09 Dec 2008 14:17:37 +0000</pubDate>
		<dc:creator>saddor@cesarodas.com (Cesar D. Rodas)</dc:creator>
		
		<category><![CDATA[Open Source]]></category>

		<category><![CDATA[Personal]]></category>

		<guid isPermaLink="false">http://cesar.la/?p=56</guid>
		<description><![CDATA[He aquí el porque escribo  Open Source&#8230;, para que miles de personas utilicen mis códigos. Aquí esta una prueba de ello, un popular (casi 20mil descargas) plug-in de Wordpress.


Grande Photo Xhibit
Gracias a Sarita por avisarme.
]]></description>
			<content:encoded><![CDATA[<blockquote><p><em>He aquí el porque escribo  Open Source&#8230;, para que miles de personas utilicen mis códigos. Aquí esta una prueba de ello, un popular (casi 20mil descargas) plug-in de Wordpress.<br />
</em></p></blockquote>
<p><a title="Cool by Cesar Rodas, on Flickr" href="http://www.flickr.com/photos/crodas/3095624016/"><img src="http://farm4.static.flickr.com/3007/3095624016_6ab7873bb6.jpg" alt="Cool" width="500" height="375" /></a></p>
<p>Grande <a href="http://benjaminsterling.com/photoxhibit/">Photo Xhibit</a></p>
<p>Gracias a <a href="http://www.caacupe.com.py/admin">Sarita</a> por avisarme.</p>
<img src="http://feeds.feedburner.com/~r/crodas/~4/n3SvzMX9fMc" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://cesar.la/por-esto-amo-el-open-source.html/feed</wfw:commentRss>
		<feedburner:origLink>http://cesar.la/por-esto-amo-el-open-source.html</feedburner:origLink></item>
		<item>
		<title>Backup seguro y gratuito.</title>
		<link>http://feedproxy.google.com/~r/crodas/~3/2lZPEWbxkNA/backup-seguro-y-gratuito.html</link>
		<comments>http://cesar.la/backup-seguro-y-gratuito.html#comments</comments>
		<pubDate>Sun, 07 Dec 2008 16:58:49 +0000</pubDate>
		<dc:creator>saddor@cesarodas.com (Cesar D. Rodas)</dc:creator>
		
		<category><![CDATA[FreeBSD]]></category>

		<category><![CDATA[GNU/Linux]]></category>

		<category><![CDATA[Open Source]]></category>

		<category><![CDATA[Programación]]></category>

		<category><![CDATA[Shell Scripting]]></category>

		<guid isPermaLink="false">http://cesar.la/?p=54</guid>
		<description><![CDATA[Siguiendo con mi post sobre servidores, una parte fundamental es la parte de backup, ya que siempre es importante estar preparados los desastres. Lo importante de los backups es la redundancia, y la seguridad. Nadie mas que nosotros tiene que poder ver nuestros backups.
Anteriormente mencione que Amazon S3 es una solución barata, muchas veces barata [...]]]></description>
			<content:encoded><![CDATA[<p>Siguiendo con mi <a href="http://cesar.la/servidores-baratos-seguros-y-eficientes.html">post sobre servidores</a>, una parte fundamental es la parte de <em>backup</em>, ya que siempre es importante estar preparados los desastres. Lo importante de los backups es la redundancia, y la seguridad. Nadie mas que nosotros tiene que poder ver nuestros backups.</p>
<p>Anteriormente mencione que Amazon S3 es una solución barata, muchas veces <em>barata</em> no es suficiente (especialmente si pagas a Amazon S3 una fortuna <a href="http://files3.com/">por otros sitios</a>). Luego de pensar, y pensar en un medio de almacenamiento mas o menos seguro y gratis de ser posible, se ocurrió que tengo bastante espacio ocioso en mi gmail (65% para ser exacto). La única limitación es que el backup generado tiene que ser menor de 20MB. El único problema que ahora surge es que Google podría leer nuestros backups y ahí obtener valiosa información sobre nuestro sitio web, base de dato u otra cosa que este contenida en el backup,</p>
<p>Para solucionar ese problema podríamos usar <em>encriptació</em><em>n</em>, de manera que <em>nadie</em> pueda ver el contenido del archivo sin una clave.</p>
<p>Aqui les presento el script que yo utilizo para hacer los backups de mis servidores.</p>
<pre class="prettyprint">#!/bin/bash -x
MAIL=foobar@gmail.com #Obviamente, no solo funciona con @gmail.
SQL=/tmp/tables.sql
DATE=`date '+%F'`

# Password que es un MD5
# de un string que tiene la fecha,
# cada dia, tiene un password unico
echo "password con $DATE " &gt; /tmp/foo
PASS=`md5sum /tmp/foo |  sed "s/ .*//g"`
rm /tmp/foo

# backup de mysql.
mysqldump -u root --all-databases | bzip2  | openssl des3 -salt -k $PASS | dd of=$SQL
# Ahora comprimimos
tar cfj  -  /www/foobar.com | openssl des3 -salt -k $PASS | dd of=foobar.com-$DATE.bin
# /etc
tar cfj - /etc/  | openssl des3 -salt -k $PASS | dd of=etc-$DATE.bin

# Ahora enviar los mails
echo  | mutt -s "[backup] $DATE foobar.com " $MAIL -a foobar.com-$DATE.bin
echo  | mutt -s "[backup] $DATE /etc" $MAIL -a etc-$DATE.bin
echo  | mutt -s "[backup] $DATE MySQL" $MAIL -a $SQL
rm $SQL</pre>
<p>Para restaurar el backup simplemente hay que ejecutar el siguiente script. Lo importante es proveer siempre la clave correcta, que cambia para cada día (utiliza la fecha). Sin la clave es literalmente imposible que recuperemos el contenido, de ahi la importancia de no olvidar la clave.</p>
<pre class="prettyprint">#!/bin/bash -x

dd if=$1 |openssl des3 -d -k $3 | dd of=$2
</pre>
<p>Para restaurar el backup simplemente debe realizar lo siguiente:</p>
<pre class="prettyprint">$ restore archivo-encriptado archivo-salida-desencriptado clave
</pre>
<p>Si se preguntan cuan seguro es el encriptado?, pues la respuesta es suficiente para que yo ponga informacion real sobre una de mis tarjetas de creditos con algunos dolares (sobrantes del Google Summer of code) en un sitio de descarga para que la gente intente romper la seguridad. <a href="http://files3.com/a9r/creditcard.secure.html">Si deseas intentar puedes bajarte de aqui.</a></p>
<img src="http://feeds.feedburner.com/~r/crodas/~4/2lZPEWbxkNA" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://cesar.la/backup-seguro-y-gratuito.html/feed</wfw:commentRss>
		<feedburner:origLink>http://cesar.la/backup-seguro-y-gratuito.html</feedburner:origLink></item>
		<item>
		<title>Un poco de humor “friki”</title>
		<link>http://feedproxy.google.com/~r/crodas/~3/MiimO9V4QU0/un-poco-de-humor-friki.html</link>
		<comments>http://cesar.la/un-poco-de-humor-friki.html#comments</comments>
		<pubDate>Wed, 03 Dec 2008 14:35:09 +0000</pubDate>
		<dc:creator>saddor@cesarodas.com (Cesar D. Rodas)</dc:creator>
		
		<category><![CDATA[Open Source]]></category>

		<guid isPermaLink="false">http://cesar.la/?p=52</guid>
		<description><![CDATA[Luego de leer esta increíble página con algunos chistes frikis, me acorde que despues de mucho googlear encontre un mirror del desaparecido raulito el friki, sin pensarlo dos veces escribí un rápido script en bash para que me bajara todas las tiras.
Para aquellos desconocedores de la tira; Raulito es un friki con unos 30 años [...]]]></description>
			<content:encoded><![CDATA[<p>Luego de leer esta <a href="http://www.devtopics.com/best-programming-jokes/">increíble página</a> con algunos chistes <em>frikis</em>, me acorde que despues de mucho googlear encontre un <em>mirror</em> del desaparecido <em>raulito el friki</em>, sin pensarlo dos veces escribí un rápido script en bash para que me bajara todas las tiras.</p>
<p><span>Para aquellos desconocedores de la tira; Raulito es un friki con unos 30 años amante de Debian GNU/Linux y con la desgracia de que las iniciales de su nombre son R P M (Raúl Peñáez Martinez), que no puede encajar en la sociedad (¿O la sociedad no encaja con él?). Sus padres frustrados de su anómalo hijo (el cual reiteradas veces piensa y actúa como un kernel de Linux) tratan de cambiarlo e integrarlo a la sociedad, por ejemplo llamando a un cura (del opus dei) para que lo guíe por el buen camino. Al final éste termina creyendo que esta poseído y que es un ferviente y apasionado homosexual.<br />
</span></p>
<p>Si se preguntan porque no dudé ni un segundo en bajarte &#8220;la temporada&#8221;, vean porque: <a href="http://cesar.la/wp-content/uploads/2008/12/tira00.png"><img class="aligncenter size-medium wp-image-53" title="Primera tira, raulido" src="http://cesar.la/wp-content/uploads/2008/12/tira00-300x105.png" alt="Primera tira, raulido" width="300" height="105" /></a></p>
<p>Si quieren bajarse las demás tiras, <strong><a href="http://files3.com/a97/raulito.tar.bz2.html">aquí están de la tira 1 hasta el 95</a></strong>.</p>
<p>Si alguien quiere también tengo todas las <a href="http://www.google.com.py/search?hl=es&amp;q=bilo+y+nano&amp;btnG=Buscar+con+Google&amp;lr="><em>bilo y nano</em></a>.</p>
<img src="http://feeds.feedburner.com/~r/crodas/~4/MiimO9V4QU0" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://cesar.la/un-poco-de-humor-friki.html/feed</wfw:commentRss>
		<feedburner:origLink>http://cesar.la/un-poco-de-humor-friki.html</feedburner:origLink></item>
		<item>
		<title>Servidores baratos, seguros y eficientes.</title>
		<link>http://feedproxy.google.com/~r/crodas/~3/9fH7mK5dBuc/servidores-baratos-seguros-y-eficientes.html</link>
		<comments>http://cesar.la/servidores-baratos-seguros-y-eficientes.html#comments</comments>
		<pubDate>Mon, 01 Dec 2008 18:35:11 +0000</pubDate>
		<dc:creator>saddor@cesarodas.com (Cesar D. Rodas)</dc:creator>
		
		<category><![CDATA[FreeBSD]]></category>

		<category><![CDATA[Network]]></category>

		<category><![CDATA[Open Source]]></category>

		<category><![CDATA[PHP]]></category>

		<category><![CDATA[Programación]]></category>

		<category><![CDATA[Redes]]></category>

		<category><![CDATA[Virtualización]]></category>

		<category><![CDATA[ue]]></category>

		<guid isPermaLink="false">http://cesar.la/?p=50</guid>
		<description><![CDATA[En estos días me he dedicado a ahondar en temas de performance para sitios relativamente grandes para shared hostings, y pequeños para servidores dedicados (posiblemente tenga que hostear un periodico local con 50.000 visitas diarias, todavía no está confirmado). Aunque el título de este post suena un poco marketinero, en realidad este artículo será la [...]]]></description>
			<content:encoded><![CDATA[<p>En estos días me he dedicado a ahondar en temas de <em>performance</em> para sitios relativamente grandes para <em>shared hostings</em>, y pequeños para servidores dedicados (posiblemente tenga que hostear un periodico local con 50.000 visitas diarias, todavía no está confirmado). Aunque el título de este post suena un poco <em>marketinero, </em>en realidad este artículo será la continuación de  <a href="http://cesar.la/como-mejorar-el-rendimiento-de-un-sitio-web.html">como mejorar el rendimiento de una web</a>.</p>
<h3><span style="color: #96bf55;">Baratos</span></h3>
<p>Para la mayoría de los sitios webs no se justifica un servidor dedicado y un  <em>shared hosting </em>que pequeño, entonces ¿cuál sería el punto medio?, ahí cuando entran en juego las <a href="http://en.wikipedia.org/wiki/Virtual_private_server">VPS</a>. Básicamente las <a href="http://en.wikipedia.org/wiki/Virtual_private_server">VPS</a> son máquinas virtuales en donde tenemos acceso total, casi todos utilizan <a href="http://es.wikipedia.org/wiki/Xen">Xen</a> aunque personalmente me encanta el <a href="http://es.wikipedia.org/wiki/Linux-VServer">Linux-VServer</a> (esto es totalmente irrelevante en este artículo), hablando mal  y rápido son <em>como</em> máquinas dedicadas con menores recursos y lo más importante mucho menos precio.</p>
<p>Yo utilizo <a href="http://www.linode.com/?r=f27b185bd960df59798f065da107793ecf0bd00c">Linode</a>, y realmente no me puedo quejar de su servicio, pero existen varios otra opciones en el mercado.</p>
<h3><span style="color: #96bf55;">Seguros</span></h3>
<p>La seguridad es un tópico bastante extenso, y básicamente es una buena práctica. Ya que nadie no velará por la seguridad de nuestro server, más que nosotros mismos tenemos que tomar algunas medidas, básicamente ocultar los detalles de nuestro servidores. En todos los ataques <em>&#8220;hackers&#8221;</em> que fui parte (siempre como victima, en algún trabajo) fue por que el &#8220;atacante&#8221; conocía como funcionaba el servidor (ex-funcionario) o por culpa del administrador del servidor que dejó las configuraciones por defecto.</p>
<p>Algunas de las buenas prácticas son las siguientes:</p>
<ul>
<li><strong>Secure Shell (<a href="http://es.wikipedia.org/wiki/Ssh">SSh</a>)</strong>: Esta herramienta es fundamental a la hora de conectarnos al servidor y administrarlo remotamente, al mismo tiempo de ser necesario puede volverse peligrosa, aunque es cierto es difícil de vulnerar (casi siempre por error humano, como una contraseña sencilla), pero en caso de vulnerar los resultados serán fatales.
<ul>
<li>Desabilitar el <em>root login.</em></li>
<li>Utilizar contraseñas dificiles de adivinar (ej: 12 caracteres, mezclas entre mayusculas, minusculas y números) y anotar la contraseña. Para utilizar la anotación a cada vez que se necesite conectarse al servidor, se podría en una máquina personal, generar claves (<em>ssh-keygen</em>) y luego copiar las claves (<em>ssh-copy-id</em>) al servidor así a cada vez que nos hagamos login en el servidor, este no nos pedirá contraseña.</li>
<li>Escuchar en un puerto distinto del puerto 22, es preferible escuchar en un puerto superior al 20000 así sería un poquito más complicado de detectar con con algún scanner de puertos.</li>
<li>Guardar Log de los login fallidos.</li>
<li>Vía firewall permitir el acceso al SSH de algunos rangos de IPs si es posible.</li>
</ul>
</li>
<li>Siempre tener un firewall (IPtables o ipfw).</li>
<li>Evitar el <a href="http://es.wikipedia.org/wiki/Ataque_de_denegaci%C3%B3n_de_servicio"><strong>DoS attack</strong></a>:<strong> </strong><a href="http://es.wikipedia.org/wiki/Ricardo_Galli">Ricardo Galli</a>, creador de <a href="http://meneame.net/">Menéame</a> (y mi amigo vía <a href="http://talk.google.com/">talk</a>), escribió en su <a href="http://gallir.wordpress.com/">blog</a>, un interesante artículo de como él <a href="http://gallir.wordpress.com/2008/06/14/limitar-a-los-bots-agresivos-en-las-iptables/">evitó el ataque de DoS</a> en su sitio, bastante interesante.</li>
<li><a href="http://www.php.net/">PHP</a>:
<ul>
<li>Nunca mostrar los <a href="http://www.php.net/manual/es/errorfunc.configuration.php#ini.display-errors">errores al usuario,</a> siempre hacer <a href="http://www.php.net/manual/es/errorfunc.configuration.php#ini.log-errors">logging de los errores</a> y mostrar al usuario <a href="http://www.php.net/manual/es/function.set-error-handler.php">alguna página con información genérica del error</a> sin datos técnicos.</li>
<li>Limitar los recursos como memoria RAM, tamaño máximo de las peticiones GET, POST, tiempo máximo de ejecución, etc.</li>
</ul>
</li>
<li><a href="http://www.mysql.org/">MySQL</a>:
<ul>
<li>El <em>mysqld </em>debe escuchar 127.0.0.1 si la  base de datos se encuentra en la misma máquina que el servidor web, en caso contrario siempre asegurarse que este en una red privada, <em><strong>nunca colocar en una red pública escuchando 0.0.0.0</strong></em></li>
</ul>
</li>
<li>Backup: realizar backup de los datos (códigos fuentes, dump de la base de datos) y configuraciones (/etc/, /var/logs/ y otros) frecuentemente como máximo a cada día, y copiar en otro servidor, si no se cuenta con otro servidor, una alternativa efectiva y barata es colocar en <a href="http://aws.amazon.com/s3">Amazon S3</a>.</li>
<li>Generalidades: limitar los recursos de los servicios, siempre tener logs de los deamons.</li>
</ul>
<h3><span style="color: #96bf55;">Eficientes</span></h3>
<p>Como decía en mi articulo anterior (<a href="http://cesar.la/como-mejorar-el-rendimiento-de-un-sitio-web.html">como mejorar el rendimiento de una web</a>), si deseamos tener un servidor para atender un gran número de visitas lo más importante despues de la buena práctica de programación era tener un servidor web efectivo, parte de la efectividad era separa las consultas dinámicas y las estáticas hacia diversos servidores. Esto no es problema si hacemos las aplicaciones <em>from scratch, </em>pero que pasaría si por ejemplo queremos instalar una aplicación Open Source (ej: <a href="http://wordpress.org/">wordpress</a>), cambiar las direcciones de los archivos estáticos hacia otro dominio sería un poco trabajoso (todos sabemos que no sería un problema que con <a href="http://wordpress.org/">wp</a>, solo es un ejemplo). La solución más simple sería un <em><a href="http://es.wikipedia.org/wiki/Proxy#Reverse_Proxy">reverse proxy</a> </em>que redirija  la petición dependiendo de que si el recurso requerido es estático o dinámico.</p>
<p>Ahí es cuando entra en juego el <span style="color: black;"> </span><a href="http://nginx.net/">NGinx</a> ya que aparte de ser un increíble webserver, también es <em>reverse proxy</em> entre otras cosas. La configuración será la siguiente.</p>
<p style="text-align: center;"><img src="/wp-content/uploads/2008/11/image.png" alt="Arquitectura básica" /></p>
<p>Aquí va la configuración.</p>
<p><span style="color: black;"> </span></p>
<pre><span style="color: black;"># El usuario va a ser nginx, siempre es importante
# ejecutar como usuario sin privilegio.
user  nginx;
# número de procesos "workers" que se encargaran de
# atender a la peticiones entrantes.
worker_processes 2;
# log
error_log  logs/error.log;
# pid, útil para reiniciar el "servicio"
pid        logs/nginx.pid;

events {
    # procesos que se encargaran de responder la petición
    worker_connections  1024;
}

http {
    include       mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] $request '
                      '"$status" $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  logs/access.log  main;
    sendfile        on;
    keepalive_timeout  65;
    # Comprimir todo, útil para ahorrar ancho de banda.
    gzip  on;

    server {
        listen       80;
        server_name  www.servidor,com;
        access_log  logs/host.access.log  main;
        location / {
            # Por defecto pasar todas las peticiones al Apache.
            proxy_pass http://127.0.0.1:8080/;
            proxy_redirect off;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;

            client_max_body_size 10m;
            client_body_buffer_size 128k;
            proxy_connect_timeout 90;
            proxy_send_timeout 90;
            proxy_read_timeout 90;
            proxy_buffer_size       4k;
            proxy_buffers       4   32k;
            proxy_busy_buffers_size 64k;
            proxy_temp_file_write_size   64k;
        }
        # Si lo requerido es una archivo "estático", nginx tiene que responder,
        # y el cliente no tiene que volver a preguntar (gracias al cache).
        location ~* ^.+.(jpg|jpeg|gif|png|ico|css|zip|tgz|gz|rar|bz2|doc|xls|exe|pdf|ppt|txt|tar|mid|midi|wav|bmp|rtf|js)$ {
             root   /var/www/html/;
             expires max;
        }
        # Página estática de error
        error_page  404              /404.html;

        # redirect server error pages to the static page /50x.html
        #
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }

}
</span></pre>
<p>Para este ejemplo el Apache tiene que escuchar el puerto 8080 del IP 127.0.0.1. También sería razonable desabilitar los logs de acceso (pero los de error no, ya que PHP escribiría ahí los errores) ya que esos logs son generados por nginx, y para qué repetir datos?</p>
<img src="http://feeds.feedburner.com/~r/crodas/~4/9fH7mK5dBuc" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://cesar.la/servidores-baratos-seguros-y-eficientes.html/feed</wfw:commentRss>
		<feedburner:origLink>http://cesar.la/servidores-baratos-seguros-y-eficientes.html</feedburner:origLink></item>
		<item>
		<title>Mitos y verdades sobre el “hackeo” al NIC</title>
		<link>http://feedproxy.google.com/~r/crodas/~3/eVZMIa0W980/mitos-y-verdades-sobre-el-hackeo-al-nic.html</link>
		<comments>http://cesar.la/mitos-y-verdades-sobre-el-hackeo-al-nic.html#comments</comments>
		<pubDate>Thu, 27 Nov 2008 12:39:25 +0000</pubDate>
		<dc:creator>saddor@cesarodas.com (Cesar D. Rodas)</dc:creator>
		
		<category><![CDATA[Personal]]></category>

		<guid isPermaLink="false">http://cesar.la/?p=49</guid>
		<description><![CDATA[Lo aquí expresado es estrictamente personal y nada tiene que ver con el CNC o el NIC, aunque yo trabaje en el CNC.
En estos días se hizo eco el &#8220;hackeo&#8221; a la página del NIC, un buen hackeo realizado por un conocido bastante inteligente (nada contra él, todo bien) que aprovechaba algunos bugs del CGI [...]]]></description>
			<content:encoded><![CDATA[<blockquote><p>Lo aquí expresado es estrictamente personal y nada tiene que ver con el CNC o el NIC, aunque yo trabaje en el CNC.</p></blockquote>
<p>En estos días se hizo eco el &#8220;hackeo&#8221; a la página del <a href="http://www.nic.py/">NIC</a>, un buen hackeo realizado por un conocido bastante inteligente (nada contra él, todo bien) que aprovechaba algunos bugs del CGI escrito en Perl (hace más de 10 años) haciendo un inyección (no voy a entrar en detalles). Los &#8220;daños&#8221; realizado fueron mínimos ya que solo entraron al servidor web que no tiene nada de información, bases de datos ni nada relacionado al <a href="http://www.nic.py/">NIC</a> o al <a href="http://www.cnc.una.py/">CNC</a>, si desearían hackear necesitarían hacer algo mejor que eso ya que todo está en una red privada.</p>
<p>Si piensan que los culpables somos los funcionarios actuales del <a href="http://www.cnc.una.py/">CNC</a>, la respuesta es NO, ya que esa página está desde hace mas de 10 años, y tenemos una larga lista de actividades de cosas a hacer, no podemos pasar la vida controlando cosas que fueron hechas hace años y que funcionan (o así parece).</p>
<p>Hasta ahí todo bien, ahora lo que me molesta y bastante es que algunas personas anden opinando por foros o algo así, y mucho más un tal Lucho Benítez (ex funcionario del CNC, de la misma época cuando el CGI fue escrito) esté escribiendo <a href="http://ticpy.blogspot.com/2008/11/el-cnc-y-una-nueva-negligencia_4917.html">artículos amarillistas</a> y aprovechándose de la ignorancia de los medios de prensa, para hacer polémicas (flameware) y así tener unas cuantas visitas en su blog (y hacer unos cuantos dolares), típico <a href="http://es.wikipedia.org/wiki/Troll_(Internet)">troll</a>, alguien debería comentarle que si quiere visitantes existe <a href="http://digg.com/">digg,</a> o <a href="http://meneame.net/">meneame</a> si solo habla español.</p>
<p>Investigué algo referente a Lucho Benítez,  lastimosamente google no me dijo nada, pregunté a gente del CNC, y tampoco me dijeron nada, por lo visto su paso por el CNC no marcó historia como el de algunos legendarios que sus nombres aún se escuchan por los pasillos. A continuación responderé algunas cosas de su <a href="http://ticpy.blogspot.com/2008/11/el-cnc-y-una-nueva-negligencia_4917.html">artículo amarillista</a>.</p>
<blockquote><p><em>Que sucedió en el CNC? ya no tienen presupuesto para el mantenimiento de los servicios? Habría que recordar que este también es un MONOPOLIO al que ni la prensa ni los proveedores hacen referencia.</em></p>
<p>Monopolio?!, que otra empresa está preparada para tener el servicio de NIC?, algún grupito de &#8220;hackers&#8221; o usuarios Unix?, otro ente público? alguna empresa privada?. Si tienen problemas deberían hablar con el Rectorado UNA, no con el CNC.</p>
<p><em>Por qué este evento desnuda un problema grave? Simplemente por que el <a href="http://es.wikipedia.org/wiki/DNS">DNS</a> forma parte de los protocolos que hacen a la arquitectura de Internet. Sin el DNS del NIC.py nadie en ninguna parte del mundo podrá llegar a servidores que tienen su dominio bajo .py. Podrían hacerlo por el número IP, pero no por el nombre de dominio. Al tomar cierto control de este equipo es solo cuestión de tiempo, (y si se tiene el conocimiento adecuado) tomar el control del resto de la infraestructura.</em></p>
<p>Linda clase para <a href="http://es.wikipedia.org/wiki/Muggle_(Harry_Potter)">muggles</a> pero totalmente irrelevante, y nada tiene que ver con el servidor web que fue &#8220;hackeado&#8221;.</p>
<p><em>Es por ello que me parece gravisima la <a href="http://buscon.rae.es/draeI/SrvltConsulta?TIPO_BUS=3&amp;LEMA=desidia">desidia</a> y/o <a href="http://buscon.rae.es/draeI/SrvltConsulta?TIPO_BUS=3&amp;LEMA=negligencia">negligencia</a> del personal del CNC, y ante todo una vez más la población (sobre todo los usuarios) de vuelta esta desprotegida, y seguirá así, si no cambian ciertas prácticas.</em></p>
<p>Que tiene que ver eso con un servidor web?</p></blockquote>
<p>Otra cosa que me molesta es la gente ignorante que se quejan por los precios del NIC asociando al CNC como responsable, si tienen problemas con el precio (o burocracia) deberían hablar con la gente del Rectorado (somos dependiente del Rectorado UNA) o comprarse <a href="http://www.godaddy.com/">.com</a></p>
<p>Modestia aparte, en el CNC sólo trabaja gente muy buena (entre las mejores del Paraguay, si no me creen pueden googlear el nombre de algún funcionario del área técnica), pero el problema principal es la constante rotación del personal debido al bajo salario (somos funcionarios del Rectorado).</p>
<img src="http://feeds.feedburner.com/~r/crodas/~4/eVZMIa0W980" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://cesar.la/mitos-y-verdades-sobre-el-hackeo-al-nic.html/feed</wfw:commentRss>
		<feedburner:origLink>http://cesar.la/mitos-y-verdades-sobre-el-hackeo-al-nic.html</feedburner:origLink></item>
		<item>
		<title>And finally the beta is out!</title>
		<link>http://feedproxy.google.com/~r/crodas/~3/350DmahQu_M/and-finally-the-beta-is-out.html</link>
		<comments>http://cesar.la/and-finally-the-beta-is-out.html#comments</comments>
		<pubDate>Thu, 20 Nov 2008 03:02:38 +0000</pubDate>
		<dc:creator>saddor@cesarodas.com (Cesar D. Rodas)</dc:creator>
		
		<category><![CDATA[FileS3]]></category>

		<guid isPermaLink="false">http://cesar.la/?p=48</guid>
		<description><![CDATA[After some time of the alpha version, FileS3 beta is finally out. As you can see the site now have a new, simplest design, much faster than the others sites.
Probably you may be wondering why another file share system?, the answer is quite simple, I got tired of wait more than a  minute because I [...]]]></description>
			<content:encoded><![CDATA[<p>After some time of the alpha version, <a href="http://files3.com/" target="_blank">FileS3</a> beta is finally out. As you can see the site now have a new, simplest design, much faster than the others sites.</p>
<p>Probably you may be wondering why another file share system?, the answer is quite simple, I got tired of wait more than a  minute because I was not a premium user, or download slower over the time when download a bunch of things.</p>
<p>Another things that really really bother me is that if my connection goes down during a large download, I need to start again, and also, I cannot have parallel download.</p>
<p>So, I created <a href="http://files3.com/" target="_blank">FileS3</a>, a simple share system, where every user is a premium user.</p>
<p>What is next:</p>
<ul>
<li>Right now the Link live time is two hours, What I will do next is calculate the LLT (link live time) based on the file size.</li>
<li>MP3-embedding, if you upload an mp3 file, <a href="http://files3.com/" target="_blank">FileS3</a> will generate the HTML code for embedded an mp3 player in your blog.</li>
<li>Internationalization, because not all the people speak only English&#8230;</li>
<li>Desktop uploader: This will be a cool Python+Gtk2 (Of course will be Free Software) app that will help user to upload largest file and pause.</li>
</ul>
<img src="http://feeds.feedburner.com/~r/crodas/~4/350DmahQu_M" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://cesar.la/and-finally-the-beta-is-out.html/feed</wfw:commentRss>
		<feedburner:origLink>http://cesar.la/and-finally-the-beta-is-out.html</feedburner:origLink></item>
		<item>
		<title>¿como  mejorar el rendimiento de un sitio web?</title>
		<link>http://feedproxy.google.com/~r/crodas/~3/KF4IYOSN1j8/como-mejorar-el-rendimiento-de-un-sitio-web.html</link>
		<comments>http://cesar.la/como-mejorar-el-rendimiento-de-un-sitio-web.html#comments</comments>
		<pubDate>Sun, 16 Nov 2008 22:13:31 +0000</pubDate>
		<dc:creator>saddor@cesarodas.com (Cesar D. Rodas)</dc:creator>
		
		<category><![CDATA[Open Source]]></category>

		<category><![CDATA[PHP]]></category>

		<category><![CDATA[Programación]]></category>

		<category><![CDATA[Redes]]></category>

		<category><![CDATA[2]]></category>

		<guid isPermaLink="false">http://cesar.la/?p=47</guid>
		<description><![CDATA[En estos días, después de terminar la beta de mi nuevo sitio para compartir archivos FileS3, me puesto en teoría mis conocimientos sobre optimización de paginas webs (para mejor rendimiento, nada que ver con el SEO, esa es otra rama). Mi motivación para escribir este post es que hay varios sitios webs en el Paraguay [...]]]></description>
			<content:encoded><![CDATA[<p>En estos días, después de terminar la beta de mi nuevo sitio para compartir archivos <a href="http://files3.com/">FileS3</a>, me puesto en teoría mis conocimientos sobre optimización de paginas webs (para mejor rendimiento, nada que ver con el SEO, esa es otra rama). Mi motivación para escribir este post es que hay varios sitios webs en el Paraguay con mucho trafico (o al menos eso dicen) , y todos ellos desoptimizados. Esta desoptimización es costosa para la empresa que gasta millones en hardware (supongo&#8230; no trabajo para ninguna) y en ancho de banda, y para el usuario ya que el tiempo de respuesta no es optimo.</p>
<h3><span style="color: black;">Archivos estáticos (*.png, *.jpg, *.js, *.css, etc)<br />
</span></h3>
<p>Aunque Apache es un gran servidor web, perfecto para todas las consultas dinámicas (mod_php, mod_*), consultas CGI, pero es demasiado costosa para procesar archivos estáticos, con esto no estoy diciendo que tener archivo estáticos con Apache este mal, solamente digo que si quieren ahorrar recursos para recibir mas visitantes se debe cambiar esto.</p>
<p>Para eso existen varios servidores &#8220;lightweight&#8221;, yo recomendaría <a href="http://nginx.net/">NGinx</a> (se lee engine x) pero hay varias alterativas, solo basta googlear un poco (también leí mucho sobre el <tt><a title="http://www.lighttpd.net/" href="http://www.lighttpd.net/">http://www.lighttpd.net/</a></tt>).</p>
<p>Si se pregunta porque estos servidores &#8220;lightweight&#8221; son mejores que Apache para archivos estáticos, la respuesta es que estos servidores usan hilos (o métodos similares) para atender a varias consultas en simultaneo, ademas cuenta con una arquitectura mucho mas simple y pequeña, lo que se adecua a las necesitas de los archivos estáticos, ya que no necesitan nada mas que ser leídas del disco duro y ser enviada al cliente.</p>
<p><span style="color: black;">Otra cosa muy importante para ahorrar ancho de banda, es el cacheo en el cliente. Este cacheo es simplemente que el servidor le dice al browser (claro, a firefox casi siempre) que estos archivos estáticos no cambiaran en un tiempo dado (10 días, 20 días, 10 meses, etc), entonces el browser una vez que obtiene los archivos no vuelve a bajar  el mismo archivo ya que sabe que ese archivo no va a cambiar, y tiene una copia del archivo en el disco. Para realizar esta configuracion con  el </span><a href="http://nginx.net/">NGinx</a><span style="color: black;"> pueden leer esta <a href="http://wiki.codemongers.com/NginxHttpHeadersModule#expires">pagina</a>, si usan otro servidor deben buscar como manipular el header &#8220;Expires&#8221;.<br />
</span></p>
<p><span style="color: black;">Seguramente se estarán preguntando, que pasaría si actualizamos algún archivo estático, bueno, el browser no se enteraría mientras que no se alcance el tiempo de validez del cache.</span> Pero no se alarmen, existe una solución bastante simple, un poco de orden todo lo arregla.</p>
<p>Ya que nuestro contenido dinámico no se debe cachear (o se debe cachear por un tiempo mínimo como 10 min, 1h ,etc), y ya que el contenido dinámico incluye,  es la que incluye a el contenido estático, nuestro problema esta resuelto!, simplemente tendremos que crear un sistema rudimentario de versionamiento. Ejemplo:</p>
<blockquote>
<pre id="line1"><span style="color: #000000;">Esta es la manera como una pagina incluye a un elemento estático, un archivo css:
&lt;<span class="start-tag">link</span><span class="attribute-name"> rel</span>=<span class="attribute-value">'stylesheet' </span><span class="attribute-name">href</span>=<span class="attribute-value">'/style.css' </span><span class="attribute-name">type</span>=<span class="attribute-value">'text/css' </span><span class="error"><span class="attribute-name">/</span></span>&gt;

Con el versionamiento seria algo asi:
&lt;<span class="start-tag">link</span><span class="attribute-name"> rel</span>=<span class="attribute-value">'stylesheet' </span><span class="attribute-name">href</span>=<span class="attribute-value">'/css/1/style.css' </span><span class="attribute-name">type</span>=<span class="attribute-value">'text/css' </span><span class="error"><span class="attribute-name">/</span></span>&gt;

Entonces cuando cambiamos algo, simplemente tendremos que crear una
nueva carpeta y actualizar las referencias de la pagina hacia el elemento
estatico (si es una web en serio organizada no seria un problema).
&lt;<span class="start-tag">link</span><span class="attribute-name"> rel</span>=<span class="attribute-value">'stylesheet' </span><span class="attribute-name">href</span>=<span class="attribute-value">'/css/2/style.css' </span><span class="attribute-name">type</span>=<span class="attribute-value">'text/css' </span><span class="error"><span class="attribute-name">/</span></span>&gt;</span></pre>
</blockquote>
<p>Como ven, no es una solución complicada y así no tenemos excusas para utilizar el cacheo de archivos y así empezar a ahorrar un montón de ancho de banda.</p>
<p>Otro tip importante, para ahorrar ancho de banda es utilizar algún módulo del servidor que pueda comprimir los archivos antes de enviar (si el browser soporta). <a href="http://topfunky.net/svn/shovel/nginx/conf/nginx.conf">Aquí</a> está un ejemplo de configuración para el NGinx que tiene activado la compression (gzip).</p>
<h2><span style="color: black;">Consultas dinámicas. (*.php, cualquier otro)<br />
</span></h2>
<h3><span style="color: black;">Bases de datos&#8230;<br />
</span></h3>
<p>En esta sección hay mucho para hablar, yo me voy a enfocar en lo mas conozco, y en lo que pienso es en donde mayor desoptimización hay, las bases de datos.</p>
<p>La base de datos es un mal necesario, digo mal, porque es bastante costosa, pero no podemos vivir sin ella, es costosa porque hay autenticación (casi siempre, excepto SQLite), comunicación por la red (casi todos), compilación del código SQL, ejecución del código y acceder al disco duro. Pero como dije antes, no podemos vivir sin el, entonces la solución es evitarlo cuando sea posible, para eso podemos cachear el resultado de una consulta con un TTL (time to live) apropiado. El medio de almacenamiento puede ser un archivo en el disco duro, aunque es costoso el acceso al disco duro hoy en día los sistemas operativos tienen en memoria RAM los archivos que son leídos frecuentemente. Cuando hay varios servidores webs, la mejor alternativa seria guardar el cache en un servidor de Memcached, así no se duplica el cache.</p>
<p>Para ayudar a todo que es cacheo, en mi opinión, se debería construir un Capa de abstracción entre el acceso a base de datos y la aplicación (similiar al PDO del PHP5) y ahí implementar todo lo que sea cache. Ahora mismo estoy escribiendo un lenguaje de modelado de datos y su generador de código. Su misión sera que genera  las tablas y el código PHP (mas adelante python, java,etc) para acceder a la tablas sin escribir SQL (similar a <a href="http://www.metastorage.net/">www.metastorage.net</a>) y ahí estará implementado cacheo de consultas a disco duro, memcached o cualquier otro medio. Más adelante estaré hablando mas sobre este proyecto, que espero que muy pronto este todo terminado.</p>
<h3><span><span style="color: black;">Minimizando el tráfico.<br />
</span></span></h3>
<p>Al igual que los archivos estáticos, los archivos dinámicos pueden ser cacheado y comprimidos. Claro que el TTL tiene que ser un tiempo razonable. Imagínense la página principal de un diario digital, esa página si tiene último momento, no cambiaría tan frecuentemente, cambiaría a cada 5 minutos o 10 minutos, entonces para que generar toda la página para cada visitante?. La solución sería (para los usuarios que no este logueados, si soporta logueo) cachear toda la página (en el disco duro) y comprimir así tenemos dos versiones del mismo cache, la comprimida y la descomprimida, porque comprimir &#8220;on the fly&#8221; es costosa, se pierde tiempo y valiosos ciclos de CPU. Para cada visitante enviamos el cache comprimido si soporta o el cache normal y también le enviamos el tiempo que falta para que el cache sea recreado (para un diario yo pondria 5 ~ 10 min). Y para los artículos que generalmente no cambian creo que un TTL adecuado es de 2 horas o algo así.</p>
<p>Hace algún tiempo escribí una clase que hace eso mismo, <a href="http://www.phpclasses.org/browse/package/3972.html">gCache</a>.</p>
<h3><span><span><span style="color: black;"><a href="http://pecl.php.net/package/APC">APC</a>.</span></span></span></h3>
<p><a href="http://pecl.php.net/package/APC">APC</a> (Alternative PHP Cache) es un excelente cache en RAM del bytecode del PHP (PHP no es interpretado desde la versión 4). Para demostrar la diferencia, hice una simple prueba con la pagina principal del  <a href="http://files3.com/">FileS3</a>, cuya pagina esta bien optimizada ya que cuenta con un cache y en el momento de la prueba el cache existia, lo que significa que solo una par de lineas de códigos PHP fueron ejecutadas, ademas fue probada en el servidor para que no haya retardo de red.</p>
<p>Para la prueba utilice ApacheBench (ab -c 30 -t 30 http://local.files3.com/) simulando a 30 usuarios concurrentes que visitaban a http://local.files3.com/ por 30 seguntos.</p>
<blockquote>
<pre><span style="color: black;">This is ApacheBench, Version 2.0.40-dev &lt;$Revision: 1.146 $&gt; apache-2.0
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Copyright 2006 The Apache Software Foundation, http://www.apache.org/

Benchmarking local.files3.com (be patient)

Server Software:        Apache/2.2.8
Server Hostname:        local.files3.com
Server Port:            80

Document Path:          /
Document Length:        7232 bytes

Concurrency Level:      30
Time taken for tests:   30.8135 seconds
Complete requests:      3166
Failed requests:        0
Write errors:           0
Total transferred:      23656585 bytes
HTML transferred:       22918208 bytes
Requests per second:    105.50 [#/sec] (mean)
Time per request:       284.347 [ms] (mean)
Time per request:       9.478 [ms] (mean, across all concurrent requests)
Transfer rate:          769.86 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0  10.1      0     117
Processing:    19  281  75.0    282     675
Waiting:        1  248  75.2    252     653
Total:         20  282  74.0    283     675

Percentage of the requests served within a certain time (ms)
  50%    283
  66%    302
  75%    316
  80%    328
  90%    364
  95%    408
  98%    472
  99%    499
 100%    675 (longest request)
</span></pre>
</blockquote>
<p>Como verán, con toda la optimizaci<span><span style="color: black;">ó</span></span>n pudimos responder <span><span style="color: black;">3166 paginas. Ahora instale APC ( yum install php-pecl-apc.i386  -y), y la configuración  de facto, realice la misma prueba y aquí están los resultados.<br />
</span></span></p>
<blockquote>
<pre><span style="color: black;">This is ApacheBench, Version 2.0.40-dev &lt;$Revision: 1.146 $&gt; apache-2.0
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Copyright 2006 The Apache Software Foundation, http://www.apache.org/

Benchmarking local.files3.com (be patient)

Server Software:        Apache/2.2.8
Server Hostname:        local.files3.com
Server Port:            80

Document Path:          /
Document Length:        7244 bytes

Concurrency Level:      30
Time taken for tests:   30.1087 seconds
Complete requests:      7028
Failed requests:        0
Write errors:           0
Total transferred:      52570787 bytes
HTML transferred:       50932564 bytes
Requests per second:    234.26 [#/sec] (mean)
Time per request:       128.064 [ms] (mean)
Time per request:       4.269 [ms] (mean, across all concurrent requests)
Transfer rate:          1711.20 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   4.2      0      69
Processing:    39  126  23.1    123     300
Waiting:        1  123  22.7    120     300
Total:         39  127  22.9    123     300

Percentage of the requests served within a certain time (ms)
  50%    123
  66%    130
  75%    136
  80%    141
  90%    154
  95%    169
  98%    191
  99%    206
 100%    300 (longest request)</span></pre>
</blockquote>
<p>El resultado es asombroso, <span><span style="color: black;">ahora pudimos servir 7028 paginas, con solamente haber instalado APC, si pasan un poco mas de tiempo tuneando, podríamos mejor mucho mas.</span></span></p>
<h3><span><span><span style="color: black;">Tu experiencia!</span></span></span></h3>
<p>Seria espectacular si ustedes comparten aqui sus metodos de optimizacion para ayudarnos entre todos, varias cabezas son mejores que una.</p>
<p>Saludos.</p>
<img src="http://feeds.feedburner.com/~r/crodas/~4/KF4IYOSN1j8" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://cesar.la/como-mejorar-el-rendimiento-de-un-sitio-web.html/feed</wfw:commentRss>
		<feedburner:origLink>http://cesar.la/como-mejorar-el-rendimiento-de-un-sitio-web.html</feedburner:origLink></item>
		<item>
		<title>GeekSlides - Presentaciones con LaTeX</title>
		<link>http://feedproxy.google.com/~r/crodas/~3/VQhXAi7VRQM/geekslides-presentaciones-con-latex.html</link>
		<comments>http://cesar.la/geekslides-presentaciones-con-latex.html#comments</comments>
		<pubDate>Mon, 03 Nov 2008 14:06:38 +0000</pubDate>
		<dc:creator>saddor@cesarodas.com (Cesar D. Rodas)</dc:creator>
		
		<category><![CDATA[GNU/Linux]]></category>

		<category><![CDATA[LaTeX]]></category>

		<category><![CDATA[Open Source]]></category>

		<category><![CDATA[Programación]]></category>

		<category><![CDATA[English]]></category>

		<category><![CDATA[gslides]]></category>

		<category><![CDATA[talks]]></category>

		<guid isPermaLink="false">http://cesar.la/?p=45</guid>
		<description><![CDATA[Despues de hacer algunas presentaciones, y cansado del Impress (el mouse no fue creado para mi), he decidido utilizar Latex para crear mis presentaciones, como una prueba, para ver que tal me va.
Basicamente en este post voy a describir, paso por paso lo que hice para tener hermosas presentaciones en pdf (código fuente), escribiendo un [...]]]></description>
			<content:encoded><![CDATA[<p>Despues de hacer algunas presentaciones, y cansado del Impress (el mouse no fue creado para mi), he decidido utilizar Latex para crear mis presentaciones, como una prueba, para ver que tal me va.</p>
<p>Basicamente en este post voy a describir, paso por paso lo que hice para tener hermosas <a href="http://cesar.la/wp-content/uploads/2008/11/phpajax.pdf">presentaciones en pdf</a> (<a href="http://p.sourcehub.org/crodas-playground/artifact/180">código fuente</a>), escribiendo un poco de <a href="http://p.sourcehub.org/crodas-playground/artifact/180">codigo con LaTeX</a>. Antes que nada utilize la guia escrita por  <a href="http://www.eecs.harvard.edu/%7Emdw">Matt Welsh</a> (<a href="http://www.eecs.harvard.edu/~mdw/proj/texslides/">Creating Presentations in PDFLaTeX</a>), por cierto muy buena guia, excepto que no pude instarlas las fuentes con el script perl que esta en esa pagina.</p>
<ul>
<li>Deben bajarse el <a href="http://files3.com/a41">textslides.tbz2</a>.</li>
<li>Descomprimir ( tar xfvj  textslides.tbz2  -C  $HOME)</li>
<li>Editar el archivo de configuración de cuenta
<ul>
<li>echo &#8220;export TEXINPUTS=\$TEXINPUTS:~/.texslides/&#8221; &gt;&gt; ~/.bashrc</li>
<li>echo &#8220;export PATH=\$PATH:~/.texslides/&#8221; &gt;&gt; ~/.bashrc</li>
</ul>
</li>
<li>Para instalar fuentes nuevas, hacer lo siguiente:
<ul>
<li>Copiar las fuentes en una carpeta dada (archivos *.ttf)</li>
<li>Luego ejecutar &#8220;addfont&#8221;</li>
<li>Si siguieron todos los pasos las fuentes estaran bien instaladas.</li>
</ul>
</li>
<li>Luego para compilar el archivos Latex deben realizar lo siguiente:
<ul>
<li> pdflatex archivo.tex</li>
<li> ppower4 archivo.pdf carchivo.pdf</li>
<li> mv carchivo.pdf archivo.pdf</li>
</ul>
</li>
</ul>
<p>Básicamente crear presentaciones con LaTeX, es algo sencillo, y vale la pena si la presentación es simple, como imágenes de fondos, incluir imágenes, citar cosas. La cosa se va complicando (cosa que me pasó) cuando se requiere hacer cosas complejas, como resaltar código (escribí un pequeño script en <a href="http://p.sourcehub.org/crodas-playground/artifact/170">python</a> que con otro <a href="http://p.sourcehub.org/crodas-playground/artifact/164">script bash</a> hace eso, es algo grocero, pero funciona más o menos). Aún asi para presentaciones normales, lo mejor es utilizar LaTeX (claro con ViM), porque todo está en su lugar, no hay utilizar el mouse para alinear textos, ni nada.</p>
<p>Como me encanto el LaTeX (la idea de no depender del Impress me encanta), decidí comenzar un proyecto llamado GeekSlide, que básicamente será un generador de presentaciones (por ahora a HTML) basado en modelado de texto bastante sencillo (similar pero no igual al <a href="http://en.wikipedia.org/wiki/ReStructuredText">RST</a>), que será modular, el &#8220;core&#8221; no generará ninguna presentación, solo parseará el texto y pasara esa información a un &#8220;render&#8221; (un plug-in) que será el encargado de generar la presentación.</p>
<p>Así será un típico archivo de gslides (ojo: no es gnu/slides, es GeekSlides).</p>
<blockquote><p><span style="color: #993300;">% Esto es un comentario que será ignorado por el parseador<br />
% Definir variables globales<br />
% Estas variables serán pasadas al render, generalmente será</span><span style="color: #0000ff;"><span style="color: #993300;"><br />
% útil para generar la primera página</span><br />
title:</span> Introducción a GeekSlides.<span style="color: #0000ff;"><br />
author: </span>Cesar Rodas<span style="color: #0000ff;"><br />
email:</span> talks@cesar.la<span style="color: #993300;"><br />
% &#8220;&#8212;&#8221; Es el separador de páginas.</span><br />
&#8212;<br />
=Que es GeekSlides= <span style="color: #993300;">% Típico Título (header<span style="color: #993300;"> 1)</span></span><span style="color: #993300;"><br />
% Llamamos a la  función &#8220;gradient&#8221; definida en el &#8220;render&#8221;.<br />
</span><span style="color: #993300;">% Básicamente mostrará los items en un color claro, luego<br />
% cambiarán de color en los siguientes slides.</span><br />
{gradient}<br />
* Generador de Presentaciones.<br />
* Totalmente modular.<br />
* Open source.<br />
&#8212;<br />
=Caracteristicas=<br />
==Textos==<br />
{font,¨arial&#8221;,&#8221;14px&#8221;}<br />
* *Texto en negríta*<br />
* _Texto en cursiva_<br />
* Resalto de código.<br />
{source,&#8221;foobar.php&#8221;,&#8221;grey&#8221;}<br />
&#8211;<br />
{center}<br />
=¿Preguntas?=</p></blockquote>
<p>Como se darán cuenta la sintaxis es mucho más amigable que el LaTeX, y es bastante útil (a no ser que necesiten realizar complejas formulas matemáticas). El proyecto ahora mismo es solo un prototipo que estoy armando, y creo que pronto estará disponible para que lo puedan utilizar, extender, o lo que quiera. El proyecto será publicado en PHPClasses, y la documentación estará aqui mismo.</p>
<img src="http://feeds.feedburner.com/~r/crodas/~4/VQhXAi7VRQM" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://cesar.la/geekslides-presentaciones-con-latex.html/feed</wfw:commentRss>
		<enclosure url="http://cesar.la/wp-content/uploads/2008/11/phpajax.pdf" length="184172" type="application/pdf" /><media:content url="http://cesar.la/wp-content/uploads/2008/11/phpajax.pdf" fileSize="184172" type="application/pdf" /><itunes:explicit>clean</itunes:explicit><itunes:subtitle>Despues de hacer algunas presentaciones, y cansado del Impress (el mouse no fue creado para mi), he decidido utilizar Latex para crear mis presentaciones, como una prueba, para ver que tal me va. Basicamente en este post voy a describir, paso por paso lo </itunes:subtitle><itunes:author>Cesar D. Rodas</itunes:author><itunes:summary>Despues de hacer algunas presentaciones, y cansado del Impress (el mouse no fue creado para mi), he decidido utilizar Latex para crear mis presentaciones, como una prueba, para ver que tal me va. Basicamente en este post voy a describir, paso por paso lo que hice para tener hermosas presentaciones en pdf (código fuente), escribiendo un [...]</itunes:summary><itunes:keywords>internet,php,mysql,apache,server,saddor</itunes:keywords><feedburner:origLink>http://cesar.la/geekslides-presentaciones-con-latex.html</feedburner:origLink></item>
		<item>
		<title>PHPAJAX 3 - Write an AJAX app was never this easy</title>
		<link>http://feedproxy.google.com/~r/crodas/~3/D6tJS7hmKZE/phpajax-3-write-an-ajax-app-was-never-this-easy.html</link>
		<comments>http://cesar.la/phpajax-3-write-an-ajax-app-was-never-this-easy.html#comments</comments>
		<pubDate>Fri, 03 Oct 2008 18:31:39 +0000</pubDate>
		<dc:creator>saddor@cesarodas.com (Cesar D. Rodas)</dc:creator>
		
		<category><![CDATA[AJAX]]></category>

		<category><![CDATA[English]]></category>

		<category><![CDATA[Open Source]]></category>

		<category><![CDATA[PHP]]></category>

		<category><![CDATA[PHPAjax]]></category>

		<category><![CDATA[Programación]]></category>

		<guid isPermaLink="false">http://cesar.la/?p=39</guid>
		<description><![CDATA[After some time of inactivity due personal activities (University, work, investigations, etc) I had large to-do list, basically rewrite and improve some of my classes, talking fast the Amazon S3 class and the PHPAJAX. Right now I am working on Rewrite the PHPAJAX and release its version 3 with major changes, and in the background [...]]]></description>
			<content:encoded><![CDATA[<p>After some time of inactivity due personal activities (University, work, investigations, etc) I had large to-do list, basically rewrite and improve some of my classes, talking fast the Amazon S3 class and the <a href="http://www.phpajax.org/">PHPAJAX</a>. Right now I am working on Rewrite the <a href="http://www.phpajax.org/">PHPAJAX</a> and release its version 3 with major changes, and in the background I&#8217;m working on the PHP Pagerank (php-coding pagerank &amp;), but ut will wait some time until the <a href="http://www.phpajax.org/">PHPAJAX</a> is fully working.</p>
<p>As in previous versions, <a href="http://www.phpajax.org/">PHPAJAX</a> aims to help developer to write AJAX app. without write javascript (or writing just a little of). In previous versions execute PHP functions directly from the browser (as most of AJAX libraries), with some little advantages, such as read data directly from the HTML objects, File upload, and others.</p>
<p>The new version of PHPAJAX will be completely rewritten from scratch, and it will not use anymore Prototype, it will have its own set of <span class="spellmod" title="Spelling error - suggestions: java script, java-script, conscript, manuscript, script, subscript, prescript, typescript">javascript code</span>, optimized to what the PHPAJAX program does. The idea  is produce the Javascript code on the fly (then in a near future js-cache the code). The code by default will be obfuscated and minimized.</p>
<p>Basically the PHPAJAX compatibility will be broken right now, later I&#8217;ll code a wrapper that will execute PHPAJAX 2 code.</p>
<p>Some features of the PHPAJAX 3 will be:</p>
<ul>
<li>File Upload.</li>
<li>Better PHP-DOM functions, to manipulate HTML objects as if they were PHP objects.</li>
<li>Special Objects.
<ul>
<li>Drag and Drop (containers and objects)</li>
<li>Autocomplete fields.</li>
</ul>
</li>
<li> PHP to JS API for write Javascript code using just PHP.</li>
<li>Easy to extends.</li>
</ul>
<p>I have not an official release date, but I&#8217;m doing my best, I think it will be available in two weeks, you can keep an eye on my blog, I promise that I will disclose the repository URL soon.</p>
<p>BTW, you can take a look on <a href="http://www.fossil-scm.org/">Fossil SCM</a>, because I&#8217;m using it for this project.</p>
<p>Happy hacking, have a nice weekend!</p>
<img src="http://feeds.feedburner.com/~r/crodas/~4/D6tJS7hmKZE" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://cesar.la/phpajax-3-write-an-ajax-app-was-never-this-easy.html/feed</wfw:commentRss>
		<feedburner:origLink>http://cesar.la/phpajax-3-write-an-ajax-app-was-never-this-easy.html</feedburner:origLink></item>
		<item>
		<title>Europe, DNSSEC and more! (Powered by ISOC)</title>
		<link>http://feedproxy.google.com/~r/crodas/~3/vVF9cfgPJTo/eurore-dnssec-and-more-powered-by-isoc.html</link>
		<comments>http://cesar.la/eurore-dnssec-and-more-powered-by-isoc.html#comments</comments>
		<pubDate>Sat, 20 Sep 2008 22:49:15 +0000</pubDate>
		<dc:creator>saddor@cesarodas.com (Cesar D. Rodas)</dc:creator>
		
		<category><![CDATA[English]]></category>

		<category><![CDATA[FreeBSD]]></category>

		<category><![CDATA[Network]]></category>

		<category><![CDATA[Open Source]]></category>

		<guid isPermaLink="false">http://cesar.la/?p=37</guid>
		<description><![CDATA[After a great week in Amsterdam (pictures?) in a wonderful ISOC&#8217;s workshop at the RIPE.net, I learnt many useful things, specially about the weakness of the DNS and the benefits about the DNSSEC. Also I had a brief overview about the network monitoring.
The greatest part was that I met the administrator of the l.root-servers.net (If [...]]]></description>
			<content:encoded><![CDATA[<p>After a great week in Amsterdam (<a href="http://flickr.com/photos/crodas/tags/eurocrodas/">pictures?</a>) in a wonderful <a href="http://ws.edu.isoc.org/workshops/2008/cctld-ams/">ISOC&#8217;s workshop</a> at the <a href="http://www.ripe.net/">RIPE.net</a>, I learnt many useful things, specially about the weakness of the <a href="http://en.wikipedia.org/wiki/DNS">DNS </a>and the benefits about the <a href="http://en.wikipedia.org/wiki/DNSSEC">DNSSEC.</a> Also I had a brief overview about the network monitoring.</p>
<p>The greatest part was that I met the <a href="http://www.icann.org/en/biog/crain.htm">administrator </a>of the l.root-servers.net (If you don&#8217;t know what is the root-servers.net <a href="http://www.root-servers.org/">read this</a>) and he gave us useful tricks of how to manage a huge network (just figure out the hard work of a root server).</p>
<p>Also I met people from other NICs, it was a great experiences.</p>
<p>From now on, I&#8217;ll start to write in English and Spanish (depending of my mood) about these topics, and also I&#8217;ll write some scripts to manage the DNSSEC, also I&#8217;ll write about the DNS poisoning and other attacks (just to show how weak is the DNS), so if you&#8217;re interested just keep watching my site.</p>
<img src="http://feeds.feedburner.com/~r/crodas/~4/vVF9cfgPJTo" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://cesar.la/eurore-dnssec-and-more-powered-by-isoc.html/feed</wfw:commentRss>
		<feedburner:origLink>http://cesar.la/eurore-dnssec-and-more-powered-by-isoc.html</feedburner:origLink></item>
		<item>
		<title>Welcome to my playground!</title>
		<link>http://feedproxy.google.com/~r/crodas/~3/5fV4UR8jGP0/welcome-to-my-playground.html</link>
		<comments>http://cesar.la/welcome-to-my-playground.html#comments</comments>
		<pubDate>Mon, 25 Aug 2008 23:54:12 +0000</pubDate>
		<dc:creator>saddor@cesarodas.com (Cesar D. Rodas)</dc:creator>
		
		<category><![CDATA[English]]></category>

		<category><![CDATA[Personal]]></category>

		<guid isPermaLink="false">http://cesar.la/?p=28</guid>
		<description><![CDATA[As you may know, I have an old blog in English, but I stop to write there because I have this blog in Spanish. Then I notice that most of my friends (most of them not Spanish speakers) stops to read my blog for obvious reasons ;), so I decided to also write in English [...]]]></description>
			<content:encoded><![CDATA[<p>As you may know, I have an <a href="http://www.cesarodas.com/">old blog in English</a>, but I stop to write there because I have this blog in Spanish. Then I notice that most of my friends (most of them not Spanish speakers) stops to read my blog for obvious reasons ;), so I decided to also write in English here, and you be wondering why don&#8217;t you write at cesarodas.com in English?, and the answer is quite simple, I like this domain, and I&#8217;d like to have everything in a single place, Spanish and English, all together.</p>
<p>I&#8217;d try to talk about *similar* things (not just translations) in both languages, and of course, I&#8217;ll try to improve my English (now <a href="http://www.anglo.edu.py/">I&#8217;m studying</a>).</p>
<p>So welcome back to my playground!</p>
<img src="http://feeds.feedburner.com/~r/crodas/~4/5fV4UR8jGP0" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://cesar.la/welcome-to-my-playground.html/feed</wfw:commentRss>
		<feedburner:origLink>http://cesar.la/welcome-to-my-playground.html</feedburner:origLink></item>
		<item>
		<title>Al fin la facultad fue útil</title>
		<link>http://feedproxy.google.com/~r/crodas/~3/olZvzMNcJiU/al-fin-la-facultad-fue-util.html</link>
		<comments>http://cesar.la/al-fin-la-facultad-fue-util.html#comments</comments>
		<pubDate>Sat, 23 Aug 2008 22:12:50 +0000</pubDate>
		<dc:creator>saddor@cesarodas.com (Cesar D. Rodas)</dc:creator>
		
		<category><![CDATA[Open Source]]></category>

		<category><![CDATA[PHP]]></category>

		<category><![CDATA[Personal]]></category>

		<category><![CDATA[Programación]]></category>

		<guid isPermaLink="false">http://cesar.la/?p=27</guid>
		<description><![CDATA[Luego de tres años de estar en la facultad, siempre pensé que todo lo que aprendí ahí no me serviría para la vida, aunque suena un poco arrogante, pero la verdad es que pensarían lo mismo si sólo algunos profesores de los 25 profesores que me enseñaron, valen la pena. Esto es un simple comentario [...]]]></description>
			<content:encoded><![CDATA[<p>Luego de tres años de estar en la facultad, siempre pensé que todo lo que aprendí ahí no me serviría para la vida, aunque suena un poco arrogante, pero la verdad es que pensarían lo mismo si sólo algunos profesores de los 25 profesores que me enseñaron, valen la pena. Esto es un simple comentario personal, y le moleste a quien le moleste es la verdad.</p>
<p>En  la semana tuve una nueva meta, tener un nuevo mail <a href="http://www.apache.org/">@apache.org</a>, <a href="http://www.php.net/">@php.net</a>, ambos antes de tener 23 años, aprovechando que me quedan 2 años y dos dias ;).</p>
<p>Bueno, me puse manos a la  obra,  comenzé por el que creía que sería más difícil, por apache (sin desprestigiar a <a href="http://www.php.net/">@php.net</a>), y la verdad que <a href="http://mail-archives.apache.org/mod_mbox/incubator-general/200808.mbox/%3c48AC7E08.8080603@gmx.de%3e">no me fué tan bien</a>, pero claro que eso no me va a desanimar. Luego le llego al turno a php, y para eso la manera más fácil para mí y donde me sentiría mas cómodo, fue hacer una contribución  en <a href="http://pear.php.net/">PEAR</a>, y la verdad que mi primer &#8220;contacto&#8221; con PEAR el año pasado <a href="http://www.google.com/search?q=cesar+rodas+till+pear">no me fue tan bien</a>, pero por suerte este año me fue <a href="http://news.php.net/php.pear.dev/50602">mejor de lo que estaba esperando</a>.</p>
<p>Como habrán leído, estoy trabajando en mis tiempos libres en mi proyecto PEAR, una implementación del <a href="http://citeseer.ist.psu.edu/page98pagerank.html">PageRank</a> en PHP, que podrá ser ejecutada como un solo proceso, o en paralelo en varias máquinas.</p>
<p>El diseño de la clase, es bastante modular, y la persona que desea  usarla debería tener una lista de números (fuente-&gt;destino), que se puede tener con un <a href="http://en.wikipedia.org/wiki/Web_crawler">crawler</a>, o bien puede ser útil para alguna red social para saber quienes son los &#8220;mejores&#8221; (más famosos, más activos, etc). usuarios.</p>
<p>Para mis pruebas, hice un pequeño y genérico crawler en PHP (que pronto estará publicado en<a href="http://cesars.users.phpclasses.org/"> PHPClasses</a>), e indexé 116.396 páginas, 7.132.973 links, y 23.598.922 &#8220;nodos de links&#8221; (los intercambios de links origen-&gt;destino).</p>
<p>Como sabrán, el PageRank, es un proceso recursivo, que se necesitan iteraciones, osea repetir el proceso del calculado N veces (en el paper dice que ~52 veces fueron suficientes para sus pruebas), también menciona que es un proceso lento.</p>
<p>En mis pruebas, use a MySQL, como repositorio de mis datos, y para mi sorpresa la iteración tardó 2 horas exactamente, lo que significa que tardaría 104 horas (4 días) para calcular el PR de todo mi ejemplo, lo que es un tiempo inaceptable para tan insignificante grupo de páginas. Entonces  buscando una solución, me acorde de mis magistrales clases de Sistemas Operativos con el <a href="http://www.carloszayas.com/">Prof.  Carlos Zayas</a>, el capítulo  de sistemas de archivos, específicamente la parte de cacheo en memoria, y empecé  a desarrollar una capa de cacheo entre el PHP y el origen de los datos (en mi caso MySQL), el primer algoritmo fue el <a href="http://en.wikipedia.org/wiki/Cache_algorithms">MRU</a>. Alguna vez implementé este algoritmo en C, lo cual fue sencillo gracias a los punteros, pero en PHP me fue complicado, ya que no hay punteros sólo referencias, lo cual es un concepto nuevo para mí (humanware-error), y la solución era peor que la cura. Luego me di cuenta que los datos eran secuenciales, y que pensé que un cacheo usando <a href="http://es.wikipedia.org/wiki/FIFO">FIFO</a> sería suficiente, y empecé a codificar.</p>
<p>Para mi sorpresa, el FIFO con un buen tamaño (100MB), es perfecto, de 2 horas por iteración pasó a ser 16 minutos por iteración. Y viendo en los logs, me dí cuenta que el cache respondió a 14.598.272 consultas. Gracias a <a href="http://www.carloszayas.com/">Prof.  Carlos Zayas</a>, mis problemas fueron resueltos.</p>
<p>Espero terminar pronto con este proyecto, por si alguien quiera ver el código, lo puede hacer <a href="http://p.sourcehub.org/crodas-playground">en mi lugar de juego.</a></p>
<img src="http://feeds.feedburner.com/~r/crodas/~4/olZvzMNcJiU" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://cesar.la/al-fin-la-facultad-fue-util.html/feed</wfw:commentRss>
		<feedburner:origLink>http://cesar.la/al-fin-la-facultad-fue-util.html</feedburner:origLink></item>
		<item>
		<title>Combatiendo el SPAM - ataques de diccionario</title>
		<link>http://feedproxy.google.com/~r/crodas/~3/z7_UIS8QXmU/combatiendo-el-spam-ataques-de-diccionario.html</link>
		<comments>http://cesar.la/combatiendo-el-spam-ataques-de-diccionario.html#comments</comments>
		<pubDate>Fri, 15 Aug 2008 06:48:28 +0000</pubDate>
		<dc:creator>saddor@cesarodas.com (Cesar D. Rodas)</dc:creator>
		
		<category><![CDATA[Open Source]]></category>

		<category><![CDATA[PHP]]></category>

		<category><![CDATA[Programación]]></category>

		<category><![CDATA[Shell Scripting]]></category>

		<guid isPermaLink="false">http://cesar.la/?p=19</guid>
		<description><![CDATA[El spam es uno de los males que está plagando la Internet. Si tienes tu propio servidor de e-mail para uso personal o administras uno en el trabajo, lidiar con ellos es un verdadero dolor de cabezas. Existen varios tipos de ataques, en este artículo muestro como combatir y bloquear  a los spammers que [...]]]></description>
			<content:encoded><![CDATA[<p>El spam es uno de los males que está plagando la Internet. Si tienes tu propio servidor de e-mail para uso personal o administras uno en el trabajo, lidiar con ellos es un verdadero dolor de cabezas. Existen varios tipos de ataques, en este artículo muestro como combatir y bloquear  a los spammers que realizan el ataque de diccionario.</p>
<p>El ataque de diccionario, es el ataque más tonto que un pseudo-spammer puede hacer, y ya que es un ataque tonto, tiene una solución bastante sencilla. El ataque consiste en lo siguiente.</p>
<ul>
<li>Toman un e-mail real (Ejemplo: crodas@foo-bar.com)</li>
<li>Luego se le agregan letras randomicas al inicio al final</li>
</ul>
<p>La solución se simple, hay que seleccionar todos lo mails que fueron enviados a destinatarios no existentes, luego agrupar por IP, y comparar a ver si los destinatarios son similares, si son es un ataque de diccionario. Este script funciona con el output del Log del sendmail.</p>
<pre class="prettyprint">#!/usr/bin/php -q
&lt;?php
# Dedicado para los que piensan que PHP es solo para páginas webs
# y para las personas tontas que comparan un framework cualquiera
# con un lenguaje de programación.
#
if ( isset($argv[1]) &amp;&amp; $argv[1] == "--debug")
    define("DEBUG",1);

function x_readline()
{
    return trim(fgets(STDIN));
}

function asum($x,$y)
{
    $x += $y;
    return $x;
}

$ip=array();
$dst=array();
while ($line=x_readline())
{
    $line = strtolower($line);

    preg_match("/\]\: ([a-zA-Z0-9]+):.*from\=.*relay=.*\[([0-9\.]+)\]/i",$line,$result);
    if ( count($result) &gt; 0) $ip[$result[1]] = $result[2];
    if ( strpos($line,"user unknown") !== false )
    {
        preg_match("/]\: ([a-zA-Z0-9]+):.*to=&lt;?([^\@]+)&gt;?/i",$line,$result);
        if ( count($result) &gt; 0 &amp;&amp; isset($ip[$result[1]]) )
            $dst[ $ip[$result[1]] ][] = $result[2];
    }
}
$result=array();
#ahora a buscar los posibles candidatos
foreach($dst as $ip =&gt; $mail)
{
    $tmp=array();
    $t = count($mail);
    if ( $t &lt; 5) continue; /* una regla mia, un mínimo de 5 mails fallidos para el control */
    for($i=0; $i &lt; $t-1; $i++)
    {
        $threshold = (strlen($mail[$i]) + strlen($mail[$i]))/2 * 0.3;
        $weight = levenshtein($mail[$i],$mail[$i+1]);
        $tmp[] = $weight &lt; $threshold &amp;&amp; $weight!=0  ? 1 : -1;
    }
    $result[$ip] = array_reduce($tmp,"asum");
}

foreach($result as $ip =&gt; $weight)
{
    if ( $weight &lt; 0) continue;
    print "$ip\n";
    if (defined("DEBUG")) print_r($dst[$ip]);
}
?&gt;</pre>
<p>El script devuelve una lista de IPs que realizan ataques de SPAM. Esta lista es suficiente para poder combatirlo, ejemplo ejecutar  periodicamente (crontab) a cada 3 (es un ejemplo) horas y agregar en la lista de bloqueos del sendmail. Aquí un script bash que hace el trabajo &#8220;duro&#8221; de darle forma a el &#8220;output&#8221; del php.</p>
<pre class="prettyprint">#!/bin/bash
#configuracion
LOG=/var/log/maillog
SENDMAIL=/etc/mail/
DB=/etc/mail/access
DATE=`date`
TEXT="550 We don't accept mail from spammers # Auto added $DATE"
#el programa en sí
if [ `whoami` != "root" ]
then
    echo "Only root can run this script"
    exit
fi

find_in_access() {
    VALUE=$1
    local ACCESSIP
    for ACCESSIP in $( cat $DB | awk '{print $1}' );
    do
        if [  "$ACCESSIP" = "$VALUE" ];
        then
            return 0
        fi
    done
    return 1
}

for SPAMMER in `cat $LOG | php php_dict_attack.php`
do
    find_in_access $IP
    if [ $? -eq 1 ];
    then
        echo "$SPAMMER			$TEXT" &gt;&gt; $DB
    fi
done
cd $SENDMAIL
make</pre>
<img src="http://feeds.feedburner.com/~r/crodas/~4/z7_UIS8QXmU" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://cesar.la/combatiendo-el-spam-ataques-de-diccionario.html/feed</wfw:commentRss>
		<feedburner:origLink>http://cesar.la/combatiendo-el-spam-ataques-de-diccionario.html</feedburner:origLink></item>
		<item>
		<title>YouTube desde FreeBSD</title>
		<link>http://feedproxy.google.com/~r/crodas/~3/eznQt0Gdcig/youtube-desde-freebsd.html</link>
		<comments>http://cesar.la/youtube-desde-freebsd.html#comments</comments>
		<pubDate>Tue, 05 Aug 2008 03:34:21 +0000</pubDate>
		<dc:creator>saddor@cesarodas.com (Cesar D. Rodas)</dc:creator>
		
		<category><![CDATA[FreeBSD]]></category>

		<category><![CDATA[GNU/Linux]]></category>

		<category><![CDATA[Programación]]></category>

		<guid isPermaLink="false">http://cesar.la/?p=25</guid>
		<description><![CDATA[Cuando me instalé mi FreeBSD, de la emoción de tener un verdadero Unix me olvidé de ver algunos detalles *también* importantes, la historia comienza cuando quería ver un video educativo acerca de la cultura de los Norteamericaos, para mi mala suerte me dí cuenta de que cometí dos estupideces, no instale el plug-in de Flash [...]]]></description>
			<content:encoded><![CDATA[<p>Cuando <a href="http://cesar.la/conviviendo-con-un-verdadero-unix.html">me instalé mi FreeBSD,</a> de la emoción de tener un verdadero Unix me olvidé de ver algunos detalles *también* importantes, la historia comienza cuando quería ver un video <a href="http://www.youtube.com/watch?v=QVbobdL3yi0">educativo acerca de la cultura de los Norteamericaos</a>, para mi mala suerte me dí cuenta de que cometí dos estupideces, no instale el plug-in de Flash para Firefox, y mi tarjeta de sonido no estaba configurada&#8230; Luego me puse a laburar a full en ver como solucionar mi problemas, y el vídeo cultural se retrasaría por una hora más aproximadamente.</p>
<p>Primero es lo primero, tuve que &#8220;instalar&#8221; el driver de sonido, y digo &#8220;instalar&#8221; porque solo faltaba levantar el módulo en el kernel, como lo describe el <a href="http://www.freebsd.org/doc/en_US.ISO8859-1/books/handbook/book.html">glorioso handbook del diablito</a>, pero no había nada emocionante ahi&#8230; aparte que ganas me sobraban de recompilar el kernel, y eso fue lo que hice (para este paso necesitan haber instalado los fuentes)</p>
<pre class="prettyprint">cd /usr/src/sys/$ARCH/conf; #en mi caso $ARCH=i386
cat GENERIC  |  sed "s/GENERIC/CRODAS/g" &gt; CRODAS # "CRODAS" va a ser el kernel (soy un narcisista :P)
echo device sound &gt;&gt; CRODAS
echo device snd_emu10k1 &gt;&gt; CRODAS
echo device snd_sbc &gt;&gt; CRODAS
echo device snd_sb16 &gt;&gt; CRODAS
cd /usr/src
make buildkernel KERNCONF=CRODAS # compilar el kernel
make installkernel KERNCONF=CRODAS # instalando el kernel
reboot # algunas (solo raras) veces hay que reiniciar un verdadero sistema operativo</pre>
<p>Luego de esperar no mas de media hora (depende del hardware) ya podía escuchar música con XMMS (/usr/ports/multimedia/xmms), pero todavía no era suficiente para ver el vídeo &#8220;cultural&#8221;, entonces me puse a googlear y encontre los alternativas:</p>
<ul>
<li><span style="text-decoration: line-through;">Instalar el Firefox de Linux, luego instalar los drivers  como si fuera en cualquier distro</span> (no es un reto)<span style="text-decoration: line-through;">
<p></span></li>
<li>Instalar el plugin flash con un &#8220;wrapper&#8221; para Freebsd (como Stallman diría &#8220;the lesser evil&#8221;)<span style="text-decoration: line-through;">
<p></span></li>
</ul>
<p>Para ello hice los siquiente:</p>
<pre class="prettyprint">cd /usr/ports/www/nspluginwrapper &amp;&amp; make install clean
cd /usr/ports/www/linux-flashplugin7 &amp;&amp; make install clean
nspluginwrapper -v -a -i # como el usuario que va a ejecutar firefox</pre>
<p>Y al fin ya pude ver el video educativo&#8230;</p>
<p>Como verán la versión del flash es 7, y existe algunos sitios (gracias a Dios Youtube no) que su &#8220;player&#8221; necesita flash 9, para esos casos una buena mirada hacia sus fuentes y &#8220;wget&#8221; lo pueden solucionar.</p>
<p>Larga vida a UNIX</p>
<img src="http://feeds.feedburner.com/~r/crodas/~4/eznQt0Gdcig" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://cesar.la/youtube-desde-freebsd.html/feed</wfw:commentRss>
		<feedburner:origLink>http://cesar.la/youtube-desde-freebsd.html</feedburner:origLink></item>
		<item>
		<title>Conviviendo con un verdadero Unix</title>
		<link>http://feedproxy.google.com/~r/crodas/~3/uats58sopaU/conviviendo-con-un-verdadero-unix.html</link>
		<comments>http://cesar.la/conviviendo-con-un-verdadero-unix.html#comments</comments>
		<pubDate>Wed, 30 Jul 2008 02:22:51 +0000</pubDate>
		<dc:creator>saddor@cesarodas.com (Cesar D. Rodas)</dc:creator>
		
		<category><![CDATA[FreeBSD]]></category>

		<category><![CDATA[Open Source]]></category>

		<category><![CDATA[Personal]]></category>

		<guid isPermaLink="false">http://cesar.la/?p=23</guid>
		<description><![CDATA[Luego de bastante tiempo de usar GNU/Linux en mi notebook (y solamente GNU/Linux, no soy de esas personas con &#8220;dual booting&#8221; :P) , y después de bastante tiempo de usar FreeBSD como router en mi trabajo, me decidí instalar FreeBSD en mi notebook a ver que tal me iva con este increíble sistema operativo (ahora [...]]]></description>
			<content:encoded><![CDATA[<p>Luego de bastante tiempo de usar GNU/Linux en mi notebook (y solamente GNU/Linux, no soy de esas personas con &#8220;dual booting&#8221; :P) , y después de bastante tiempo de usar <a href="http://www.freebsd.org/">FreeBSD</a> como router en <a href="http://www.cnc.una.py/">mi trabajo</a>, me decidí instalar FreeBSD en mi notebook a ver que tal me iva con este increíble sistema operativo (ahora si ya tengo dual booting).</p>
<p>Antes que nada tuve que cambiar el <a href="http://www.howtoforge.com/linux_resizing_ext3_partitions">tamaño de una partición</a> (dejar libre unos 12GB) para poder instalar FreeBSD 7, en mi notebook. La instalación no fue nada fuera de lo normal, excepto que el FreeBSD no modifico mi MBR, ya que es más fácil (para mí) modificar el grub.</p>
<p>La mejor característica que tiene FreeBSD es el mágico directorio &#8220;/usr/src&#8221; donde se encuentra los fuentes de todos los fuentes, lo que se hace bastante fácil recompilar la &#8220;base&#8221; de FreeBSD. Los demás programas se encuentran en &#8220;/usr/ports&#8221;.</p>
<p>Otra cosa que me gusta mucho, es que viene con menos abstracción, (casi) no existen utilitarios para configurar cosas, solo archivos *.conf.</p>
<p>La instalación fue con X11 y por supuesto con Gnome, ya que no soy partidario de escritorios que mal gastan recursos (ya que tan escritos con &#8220;extensiones&#8221; de grandes lenguajes). Para que el FreeBSD inicie en modo gráfico, hay que modificar el archivo /etc/ttys que es similar al /etc/inittab de GNU/Linux, pero más simple y más poderoso, ya que se puede configurar fácilmente para ejecute un programa en tty, en mi caso el gdm de gnome. El archivo quedo similar al siguiente:</p>
<blockquote><p>ttyv0   &#8220;/usr/libexec/getty Pc&#8221;         cons25  on  secure<br />
# Virtual terminals<br />
ttyv1   &#8220;/usr/libexec/getty Pc&#8221;         cons25  on  secure<br />
ttyv2   &#8220;/usr/libexec/getty Pc&#8221;         cons25  on  secure<br />
ttyv3   &#8220;/usr/libexec/getty Pc&#8221;         cons25  on  secure<br />
ttyv4   &#8220;/usr/libexec/getty Pc&#8221;         cons25  on  secure<br />
ttyv5   &#8220;/usr/libexec/getty Pc&#8221;         cons25  on  secure<br />
ttyv6   &#8220;/usr/libexec/getty Pc&#8221;         cons25  on  secure<br />
ttyv7   &#8220;/usr/local/sbin/gdm&#8221;           gdm     on  secure</p></blockquote>
<p>Los ports que instalé en mi máquina son:</p>
<ul>
<li>/usr/ports/devel/kdevelop   = El mejor IDE que conocí del mundo para mí.</li>
<li>/usr/ports/security/openssh = El servidor OpenSSH</li>
<li>/usr/ports/net-im/pidgin       = Todos necesitamos comunicarnos</li>
<li>/usr/ports/multimedia/vlc = Lo mejor para ver vídeos</li>
<li>/usr/ports/multimedia/xmms = Músicas, músicas</li>
</ul>
<p>Para esas carpetas hice lo siguiente:</p>
<blockquote><p>cd $DIR; make install clean</p></blockquote>
<p>Larga vida a UNIX!</p>
<img src="http://feeds.feedburner.com/~r/crodas/~4/uats58sopaU" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://cesar.la/conviviendo-con-un-verdadero-unix.html/feed</wfw:commentRss>
		<feedburner:origLink>http://cesar.la/conviviendo-con-un-verdadero-unix.html</feedburner:origLink></item>
		<item>
		<title>CodeJAM - Saving the Universe - Resuelto en PHP (otra más)</title>
		<link>http://feedproxy.google.com/~r/crodas/~3/VF_pYgcdxT8/codejam-saving-the-universe-resuelto-en-php-otra-mas.html</link>
		<comments>http://cesar.la/codejam-saving-the-universe-resuelto-en-php-otra-mas.html#comments</comments>
		<pubDate>Thu, 17 Jul 2008 21:17:27 +0000</pubDate>
		<dc:creator>saddor@cesarodas.com (Cesar D. Rodas)</dc:creator>
		
		<category><![CDATA[CodeJAM]]></category>

		<category><![CDATA[Open Source]]></category>

		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://cesar.la/?p=21</guid>
		<description><![CDATA[Otro problema más CodeJAM resuelto en PHP&#8230; larga vida a PHP.
#!/usr/bin/php
&#60;?php
# Dedicado para los que piensan que PHP es solo para páginas webs
# y para las personas tontas que comparan un framework cualquiera
# con un lenguaje de programación.
#

/**/
function x_readline()
{
    return trim(fgets(STDIN));
}

function get_better_search_engine($Query,$Server,&#38;$steps_done)
{
    $result=array();
    $max = 0;
 [...]]]></description>
			<content:encoded><![CDATA[<p>Otro problema más CodeJAM resuelto en PHP&#8230; larga vida a PHP.</p>
<pre class="prettyprint">#!/usr/bin/php
&lt;?php
# Dedicado para los que piensan que PHP es solo para páginas webs
# y para las personas tontas que comparan un framework cualquiera
# con un lenguaje de programación.
#

/**/
function x_readline()
{
    return trim(fgets(STDIN));
}

function get_better_search_engine($Query,$Server,&amp;$steps_done)
{
    $result=array();
    $max = 0;
    $max_pos = 0;
    for($e=0; $e &lt; count($Server); $e++)
    {
        $perfect = true;

        for ($i=$steps_done; $i &lt; count($Query); $i++)
        {
            if ( $Query[$i] == $Server[$e])
            {
                $perfect=false;
                if ( $max &lt; $i)
                {
                    $max = $i;
                    $max_pos = $e;
                }
                break;
            }
        }
        if ( $perfect === true)
            return true; #perfect search engine
    }
    $steps_done = $max;
    return false; # we got a good search, but it cannot handle all queries
}

function get_lowest_switch($Query,$Server)
{
    $pos = 0;
    $switch=0;
    $i=0;
    while( get_better_search_engine($Query,$Server,$i) === false )
    {
        $switch++;

    }
    return $switch;
}

define('NO_WHERE',0);   # todavia no comenzamos
define('IN_INPUT_PHASE_1',1);  # inicializacion de servidores
define('IN_INPUT_PHASE_2',2);  # leyendo servidores
define('IN_INPUT_PHASE_3',3);  # inicializacion de consultas
define('IN_INPUT_PHASE_4',4);  # leyendo consultas
$status = NO_WHERE;
$total=0; # numero total a "inputs" a procesar
$cnt=0;
while ( ($line = x_readline()) != "")
{
    switch($status)
    {
        case NO_WHERE: # primera linea
            $total = (int) $line;
            $status++;
            break;
        case IN_INPUT_PHASE_1:
            $cnt++;
            $nServer= (int) $line;
            $Server = array();
            $status++;
            break;
        case IN_INPUT_PHASE_2:
            $Server[] = $line;
            if ( count($Server)==$nServer)
                $status++;
            break;
        case IN_INPUT_PHASE_3:
            $nQuery= (int) $line;
            if($nQuery==0) # no hay consultas, no hay switch
            {
                echo "Case #$cnt: 0\n";
                $status=IN_INPUT_PHASE_1;
                break;
            }
            $Query = array();
            $status++;
            break;
        case IN_INPUT_PHASE_4:
            $Query[] = $line;
            if ( count($Query)==$nQuery)
            {
                echo "Case #$cnt: ".get_lowest_switch($Query,$Server)."\n";
                $status=IN_INPUT_PHASE_1;
            }
            break;
    }
}
?&gt;</pre>
<p>El enunciado del problema:</p>
<blockquote>
<div id="dsb-problem-content-div0" class="dsb-problem-content-div">
<p class="problem-item">Problem</p>
<p>The urban legend goes that if you go to the Google homepage and search for &#8220;Google&#8221;, the universe will implode. We have a secret to share&#8230; It is true! Please don&#8217;t try it, or tell anyone. All right, maybe not. We are just kidding.</p>
<p>The same is not true for a universe far far away. In that universe, if you search on any search engine for that search engine&#8217;s name, the universe does implode!</p>
<p>To combat this, people came up with an interesting solution. All queries are pooled together. They are passed to a central system that decides which query goes to which search engine. The central system sends a series of queries to one search engine, and can switch to another at any time. Queries must be processed in the order they&#8217;re received. The central system must never send a query to a search engine whose name matches the query. In order to reduce costs, the number of switches should be minimized.</p>
<p>Your task is to tell us how many times the central system will have to switch between search engines, assuming that we program it optimally.</p>
<p class="problem-item">Input</p>
<p>The first line of the input file contains the number of cases, <strong>N</strong>. <strong>N</strong> test cases follow.</p>
<p>Each case starts with the number <strong>S</strong> &#8212; the number of search engines. The next <strong>S</strong> lines each contain the name of a search engine. Each search engine name is no more than one hundred characters long and contains only uppercase letters, lowercase letters, spaces, and numbers. There will not be two search engines with the same name.</p>
<p>The following line contains a number <strong>Q</strong> &#8212; the number of incoming queries. The next <strong>Q</strong> lines will each contain a query. Each query will be the name of a search engine in the case.</p>
<p class="problem-item">Output</p>
<p>For each input case, you should output:</p>
<pre>Case #<strong>X</strong>: <strong>Y</strong></pre>
<p>where <strong>X</strong> is the number of the test case and <strong>Y</strong> is the number of search engine switches.  Do not count the initial choice of a search engine as a switch.</p>
<p class="problem-item">Limits</p>
<p>0 &lt; <strong>N</strong> ≤ 20</p>
<p class="problem-item">Small dataset</p>
<p>2 ≤ <strong>S</strong> ≤ 10</p>
<p>0 ≤ <strong>Q</strong> ≤ 100</p>
<p class="problem-item">Large dataset</p>
<p>2 ≤ <strong>S</strong> ≤ 100</p>
<p>0 ≤ <strong>Q</strong> ≤ 1000</p>
<p>In the first case, one possible solution is to start by using Dont Ask, and switch to NSM after query number 8.<br />
For the second case, you can use B9, and not need to make any switches.</p>
</div>
</blockquote>
<img src="http://feeds.feedburner.com/~r/crodas/~4/VF_pYgcdxT8" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://cesar.la/codejam-saving-the-universe-resuelto-en-php-otra-mas.html/feed</wfw:commentRss>
		<feedburner:origLink>http://cesar.la/codejam-saving-the-universe-resuelto-en-php-otra-mas.html</feedburner:origLink></item>
		<item>
		<title>CodeJAM - Train Timetable - Resuelto en PHP</title>
		<link>http://feedproxy.google.com/~r/crodas/~3/XL118QDK_h0/codejam-train-timetable-resuelto-en-php.html</link>
		<comments>http://cesar.la/codejam-train-timetable-resuelto-en-php.html#comments</comments>
		<pubDate>Thu, 17 Jul 2008 19:40:54 +0000</pubDate>
		<dc:creator>saddor@cesarodas.com (Cesar D. Rodas)</dc:creator>
		
		<category><![CDATA[CodeJAM]]></category>

		<category><![CDATA[Open Source]]></category>

		<category><![CDATA[PHP]]></category>

		<category><![CDATA[Personal]]></category>

		<category><![CDATA[Programación]]></category>

		<guid isPermaLink="false">http://cesar.la/?p=20</guid>
		<description><![CDATA[Para aquellos que duden de PHP, o que piensen que PHP eso solo para páginas webs, aqui les va esta:
#!/usr/bin/php
&#60;?php
# Dedicado para los que piensan que PHP es solo para pàginas webs
# y para las personas tontas que comparan un framework cualquiera
# con un lenguaje de programación
#

/**/
function x_readline()
{
    return trim(fgets(STDIN));
}

function hour2minutes($hour)
{
  [...]]]></description>
			<content:encoded><![CDATA[<p>Para aquellos que duden de PHP, o que piensen que PHP eso solo para páginas webs, aqui les va esta:</p>
<pre class="prettyprint">#!/usr/bin/php
&lt;?php
# Dedicado para los que piensan que PHP es solo para pàginas webs
# y para las personas tontas que comparan un framework cualquiera
# con un lenguaje de programación
#

/**/
function x_readline()
{
    return trim(fgets(STDIN));
}

function hour2minutes($hour)
{
    $tmp = explode(":",$hour);
    return $tmp[0] * 60  + $tmp[1];
}

function get_number_train($depart, $arrival, $ttime)
{
    $ret=$tmp=0;
    sort($depart);
    sort($arrival);
    if ( count($arrival)==0)
        $ret = count($depart);
    else
    {
        foreach($depart as $pzTrain)
        {
            if ( $tmp &lt; count($arrival) &amp;&amp; $pzTrain &gt;= ($arrival[$tmp] + $ttime))
                $tmp++;
            else
                $ret++;
        }
    }
    return $ret;
}

$total=0; # numero total a "inputs" a procesar

define('NO_WHERE',0);   # todavia no comenzamos
define('IN_INPUT_PHASE_1',1);  # ttime
define('IN_INPUT_PHASE_2',2);  # cantidad de "viajes"
define('IN_READ_TIME',3);

$status = NO_WHERE;
$inp=0;
while ( ($line = x_readline()) != "")
{
    #print "+".$line." ($status)\n";
    switch($status)
    {
        case NO_WHERE: # primera linea
            $total = (int) $line;
            $status++;
            break;
        case IN_INPUT_PHASE_1:
            #limpieza del estado anterior
            $inp++;
            #print "Input $inp\n";
            $input_line=$ttime=$cnt=$pzTrainA=$pzTrainB=0;
            $trips=$inA=$outA=$inB=$outB=array();
            #
            $ttime = (int) $line;
            $status++;
            break;
        case IN_INPUT_PHASE_2:
            $trips=explode(" ",$line);
            $input_line = $trips[0] + $trips[1];
            $status++;
            break;
        case IN_READ_TIME:
            $time = array_map("hour2minutes",explode(" ",$line));
            if ( $cnt &lt; $trips[0]) {
                $outA[]  = $time[0];
                $inB[]   = $time[1];
            } else {
                $outB[]  = $time[0];
                $inA[]   = $time[1];
            }
            if ( ++$cnt == $input_line)  {
                $pzTrainA = get_number_train($outA,$inA,$ttime);
                $pzTrainB = get_number_train($outB,$inB,$ttime);
                print "Case #".($inp).": $pzTrainA $pzTrainB\n";
                $status = IN_INPUT_PHASE_1;
            }
            break;
    }
}
?&gt;</pre>
<p>Nada mas y nada menos un problema de CodeJam resuelto en PHP&#8230; no miré si PHP se puede usar, de cualquier manera estoy realizado&#8230; demostrando que no solo la viborita (o la mala extension de una gran Lenguaje) pueden hacer cosas así&#8230;</p>
<p>Para los que no tiene acceso al CodeJam, aqui escribo el enunciado del problema:</p>
<blockquote>
<p class="problem-item">Problem</p>
<p>A train line has two stations on it, A and B. Trains can take trips from A to B or from B to A multiple times during a day. When a train arrives at B from A (or arrives at A from B), it needs a certain amount of time before it is ready to take the return journey - this is the <em>turnaround time</em>.  For example, if a train arrives at 12:00 and the turnaround time is 0 minutes, it can leave immediately, at 12:00.</p>
<p>A train timetable specifies departure and arrival time of all trips between A and B. The train company needs to know how many trains have to start the day at A and B in order to make the timetable work: whenever a train is supposed to leave A or B, there must actually be one there ready to go.  There are passing sections on the track, so trains don&#8217;t necessarily arrive in the same order that they leave.  Trains may not travel on trips that do not appear on the schedule.</p>
<p class="problem-item">Input</p>
<p>The first line of input gives the number of cases, <strong>N</strong>. <strong>N</strong> test cases follow.Each case contains a number of lines.  The first line is the turnaround time, <strong>T</strong>, in minutes. The next line has two numbers on it, <strong>NA</strong> and <strong>NB</strong>.  <strong>NA</strong> is the number of trips from A to B, and <strong>NB</strong> is the number of trips from B to A.  Then there are <strong>NA</strong> lines giving the details of the trips from A to B.</p>
<p>Each line contains two fields, giving the HH:MM departure and arrival time for that trip. The departure time for each trip will be earlier than the arrival time. All arrivals and departures occur on the same day. The trips may appear in any order - they are not necessarily sorted by time. The hour and minute values are both two digits, zero-padded, and are on a 24-hour clock (00:00 through 23:59).After these <strong>NA</strong> lines, there are <strong>NB</strong> lines giving the departure and arrival times for the trips from B to A.</p>
<p class="problem-item">Output</p>
<p>For each test case, output one line containing &#8220;Case #<strong>x</strong>: &#8221; followed by the number of trains that must start at A and the number of trains that must start at B.</p>
<p class="problem-item">Limits</p>
<p>1 ≤ <strong>N</strong> ≤ 100</p>
<p class="problem-item">Small dataset</p>
<p>0 ≤ <strong>NA</strong>, <strong>NB</strong> ≤ 20</p>
<p>0 ≤ <strong>T</strong> ≤ 5</p>
<p class="problem-item">Large dataset</p>
<p>0 ≤ <strong>NA</strong>, <strong>NB</strong> ≤ 100</p>
<p>0 ≤ <strong>T</strong> ≤ 60</p></blockquote>
<img src="http://feeds.feedburner.com/~r/crodas/~4/XL118QDK_h0" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://cesar.la/codejam-train-timetable-resuelto-en-php.html/feed</wfw:commentRss>
		<feedburner:origLink>http://cesar.la/codejam-train-timetable-resuelto-en-php.html</feedburner:origLink></item>
		<item>
		<title>Virtualizando GNU/Linux con  VServer</title>
		<link>http://feedproxy.google.com/~r/crodas/~3/aHCfgMC13KU/virtualizando-gnulinux-con-vserver.html</link>
		<comments>http://cesar.la/virtualizando-gnulinux-con-vserver.html#comments</comments>
		<pubDate>Thu, 10 Jul 2008 05:47:53 +0000</pubDate>
		<dc:creator>saddor@cesarodas.com (Cesar D. Rodas)</dc:creator>
		
		<category><![CDATA[GNU/Linux]]></category>

		<category><![CDATA[Open Source]]></category>

		<category><![CDATA[Virtualización]]></category>

		<guid isPermaLink="false">http://cesar.la/?p=15</guid>
		<description><![CDATA[En estos días es más y más común tener computadoras con muchos recursos (memoria ram, discos duros, procesadores). La virtualización permite simular a varias computadoras y/o sistemas opertivos en un mismo hardware.
Un poco de teoría - Porque VServer?
Existen muchos métodos de virtualizar un sistema operativo, con los mismos resultados, el poder simular varias computadoras en [...]]]></description>
			<content:encoded><![CDATA[<p>En estos días es más y más común tener computadoras con muchos recursos (memoria ram, discos duros, procesadores). La virtualización permite simular a varias computadoras y/o sistemas opertivos en un mismo hardware.</p>
<h3><span style="color: black;">Un poco de teoría - Porque VServer?</span></h3>
<p>Existen muchos métodos de virtualizar un sistema operativo, con los mismos resultados, el poder simular varias computadoras en un solo hardware. El método más común (y mas costoso) es el de simular todo el hardware real o ficticio (<a href="http://bellard.org/qemu/">Qemu</a>, VirtualBox, etc). Su popularidad está basada a que ni el sistema operativo anfitrión ni el huésped necesita ninguna modificación.</p>
<p>Otro método utilizado para virtualizar consiste en pequeños drivers aplicados al anfitrión o húesped para miniminizar el trabajo adicional de simular el hardware para el húesped. Apesar del gran mejora aún se desperdicián recursos en la mediación entre el anfitrión y el huesped Las más populares implementaciones son <a href="http://user-mode-linux.sourceforge.net/">UML</a> y <a href="http://www.xen.org/">XEN</a>.</p>
<p>La gran mayoría de las veces no se dese tener maquinas virtuales con sistemas operativos distintos, sino solo tener varias instancias de del mismo sistema operativo huésped, ya que la gran mayoría de las veces las aplicaciones no necesitan acceso directo al hardware o al kernel del sistema operativo. Para esa opción se puede usar el &#8220;chroot&#8221; de unix, pero también se puede obtener una solución más avanzada como ser <a href="http://www.linux-vserver.org/">VServer.</a></p>
<p>Para más detalles de la implementación de VServer pueden <a href="http://linux-vserver.org/Paper">leer este Paper</a> de su implementación (muy interesante)</p>
<h3><span><span style="color: black;">Instalando VServer</span></span></h3>
<p>Algunas personas critican a VServer porque el huésped necesita  tener un kernel Linux &#8220;patcheado&#8221;, cosa que me parece críticas sin fundamentos, porque compilar el kernel es un juego de niños, con unos cuantos comandos y ~20 minutos (dependiendo del hardware) tendremos nuestro kernel listo para la virtualización. Para ello hay que bajar el patch necesario para la versión del kernel que se desea utilizar de la <a href="http://linux-vserver.org/Downloads#Kernel_Patches">página de VServer</a>.</p>
<pre class="prettyprint">wget "http://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.22.19.tar.bz2"
wget "http://ftp.linux-vserver.org/pub/kernel/vs2.2/patch-2.6.22.19-vs2.2.0.7.diff"
tar xfvj "linux-2.6.22.19.tar.bz2"
cd "linux-2.6.22.19"
patch -p1 &lt; "../patch-2.6.22.19-vs2.2.0.7.diff"</pre>
<p>Ahora ya tenemos preparado nuestro kernel, solo tenemos que configurarlo y compilarlo. El kernel viene con varias aplicaciones que facilitan su configuración, yo uso el menuconfig, pero existe varias otras opciones (make help ayudaría)</p>
<pre class="prettyprint">make menuconfig</pre>
<p><a href="http://cesar.la/wp-content/uploads/2008/07/screenshot.png"><img class="alignnone size-medium wp-image-16" title="screenshot" src="http://cesar.la/wp-content/uploads/2008/07/screenshot-300x187.png" alt="Configuring the kernel" width="300" height="187" /></a></p>
<p>Si puede ven en la lista principal VServer significa que &#8220;parchearon&#8221; correctamente su kernel, ahora tienen que elegir las opciones de VServer, aqui estan las opciones con las que compilé mi kernel (el Dynamic context id no me funcionó&#8230;)</p>
<p><a href="http://cesar.la/wp-content/uploads/2008/07/screenshot-2.png"><img class="alignnone size-medium wp-image-17" title="screenshot-2" src="http://cesar.la/wp-content/uploads/2008/07/screenshot-2-300x187.png" alt="Configuring the kernel" width="300" height="187" /></a></p>
<p>Luego también puede personalizar su kernel sacando lo que no hace falta, y agregando atras necesarias que no <a href="http://cesar.la/acer-aspire-4310-y-linux-26257.html">estan incluidas por defecto</a>. Una vez configurado el kernel hay que compilarlo (make help para mas info)</p>
<pre class="prettyprint">#compilamos todo
make all
#instalamos
make install
#reiniciamos
reboot</pre>
<p>Luego si el sistema operativo inicia bien, ya terminamos con la parte mas complicada (que no es complicado) del proceso de instalación de VServer, ahora tenemos que instalar <a href="http://savannah.nongnu.org/projects/util-vserver/">algunos utilitarios</a> que nos ayudaran para crear a los huéspedes. Si son &#8220;redhateros&#8221; pueden hacer lo siguiente:</p>
<pre class="prettyprint">yum install util-vserver* -y</pre>
<p>O si usan debian <span style="text-decoration: line-through;">(no probé personalmente)</span></p>
<pre class="prettyprint">apt-get install util-vserver\*</pre>
<p>Una vez instalado las aplicaciones *-vserver y con el kernel nuevo tenemos que testear si todo nos fue bien, para eso podemos hacer lo siguiente:</p>
<pre class="prettyprint">wget http://vserver.13thfloor.at/Stuff/SCRIPT/testme.sh
chmod +x testme.sh
./testme.sh</pre>
<p>Si todo esta funcionando correctamente tendras que ver algo similar a esto:<br />
<a href="http://cesar.la/wp-content/uploads/2008/07/pantallazo-1.png"><img class="alignnone size-medium wp-image-18" title="pantallazo-1" src="http://cesar.la/wp-content/uploads/2008/07/pantallazo-1-300x203.png" alt="" width="300" height="203" /></a></p>
<h3><span><span><span style="color: black;">Creando a los huespedes</span></span></span></h3>
<p>Antes que nada existen <a href="http://linux-vserver.org/Building_Guest_Systems">varias formas de crear máquinas huésped</a>, yo utilizo Yum para instalar los paquetes necesarios para el la distro huésped, para utilizar yum, necesita ser <a href="http://linux-vserver.org/Yum-patch">recompilado con un patch</a>.</p>
<pre class="prettyprint">#!/bin/bash
NAME=virt01
HOSTNAME=virt01.foo-bar.com
#
ROOTDIR="/virtual/"
PKGBASE=$ROOTDIR/.pkg
VSERVER=$HOSTNAME
IP="eth0:192.168.1.106/24"
INTERFACE=$NAME
CONTEXT="43"
# por defecto VServer solo soporta hasta FC6,
# mas adelante escribiré como instalar versiones posteriores
# de Fedora
DIST="fc6"
PM="yum" 

/usr/sbin/vserver $VSERVER build -m $PM --context $CONTEXT --hostname=$HOSTNAME \
--interface $INTERFACE=$IP --rootdir $ROOTDIR --pkgbase $PKGBASE -- -d $DIST
</pre>
<p>Ahora tenemos una maquina huésped, y para comenzar a jugar con</p>
<pre class="prettyprint">#para iniciar la máquina virtual
vserver $NAME start
#para "entrar" a la máquina virtual
vserver $NAME enter
#para detener la máquina virtual
vserver $NAME stop
# ejecuta "something" en la máquina virtual
vserver $NAME exec something
# instalar algo en la máquina virtual
vyum $NAME -- install algo
# te queda la curiosidad?
man vserver
</pre>
<h3><span><span><span><span style="color: black;">Algunas peculiaridades del VServer</span></span></span></span></h3>
<p>VServer no cuenta con aislamiento de red, en vez de la virtualización, lo que en otras palabras significa que si la máquina huésped y el anfitrión utilizan una misma tarjeta pero diferentes IP, en realidad el IP de la máquina huésped es un Alias del IP del host. Claro que desde el huésped (por seguridad) solo se puede ver su IP. Esto es una gran punto a favor en rendimiento, ya que no hay desperdicios de tiempo en el CPU para la virtualización de los paquetes de red.</p>
<p>Sin embargo no todo es tan bueno, ya que generalmente los servicios que escuchan puertos, escuchan utilizando 0.0.0.0 (escucha en todo los IPs y alias de la máquina). Si que queremos tener httpd (o cualquier otro progama) instalado en el anfitrión y el huésped tenemos que fijarnos que desde el anfitrión no escuche desde el IP 0.0.0.0, para ver esto solo pueden ejecutar:</p>
<pre class="prettyprint">$ netstat -nlp | grep httpd
tcp        0      0 0.0.0.0:80                0.0.0.0:*                   LISTEN      2400/httpd
</pre>
<p>Si la httpd-anfitrión escucha 0.0.0.0:80, todas las consultas que le hagamos a nuestro httpd-huésped serán recibidas y procesadas por el http-anfitrión (por lo explicado anteriormente). Para solucionar el conflicto tendremos que forzar al httpd-anfitrión que escuche el IP-anfitrión. Si configuramos todo correctamente tendremos que ver algo similar a esto.</p>
<pre class="prettyprint">$ netstat -nlp | grep httpd
tcp        0      192.168.1.14:80                0.0.0.0:*                   LISTEN      2400/httpd
</pre>
<p>Debemos repetir el mismo proceso para cada aplicación que escucha el IP 0.0.0.0 y que queríamos ejecutar en el huésped y el anfitrión  (eg: mysql, sshd, etc).</p>
<h3><span><span><span><span style="color: black;">Lo que se viene</span></span></span></span></h3>
<p>Conocí VServer gracias a que tuve la necesidad de virtualizar servidores en mi trabajo, y me encanto, ya que es muy similar a los Jails de FreeBSD, ademas que todo el filesystem del huésped es visto desde el anfitrión, ademas que las máquinas pueden compartir directorios entre si. Más adelante escribiré sobre como virtualizar servidores existentes, como instalar versiones más nuevas de Fedora, como forzar a vyum que lea desde el DVD de Fedora en vez de internet, esto es verdaderamente útil para instalaciones nuevas.</p>
<p>Espero que les haya gustado este introducción a VServer&#8230; espero sus comentarios con dudas o sugerencias.</p>
<img src="http://feeds.feedburner.com/~r/crodas/~4/aHCfgMC13KU" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://cesar.la/virtualizando-gnulinux-con-vserver.html/feed</wfw:commentRss>
		<feedburner:origLink>http://cesar.la/virtualizando-gnulinux-con-vserver.html</feedburner:origLink></item>
		<item>
		<title>La pseudo-problemática de Stallman en Paraguay</title>
		<link>http://feedproxy.google.com/~r/crodas/~3/wQ398E9dNgY/la-pseudo-problematica-de-stallman-en-paraguay.html</link>
		<comments>http://cesar.la/la-pseudo-problematica-de-stallman-en-paraguay.html#comments</comments>
		<pubDate>Mon, 07 Jul 2008 14:51:44 +0000</pubDate>
		<dc:creator>saddor@cesarodas.com (Cesar D. Rodas)</dc:creator>
		
		<category><![CDATA[Open Source]]></category>

		<category><![CDATA[Personal]]></category>

		<guid isPermaLink="false">http://cesar.la/?p=14</guid>
		<description><![CDATA[Richard Stallman, fundador del Free Software Foundation, y el sistema operativo GNU, estará en Paraguay en noviembre. Dicha noticia alegra a todos lo que estamos de acuerdo (aunque sea parcialmente) con su filosofía, y los que usamos un increíble sistema operativo, como es GNU/Linux.
Al parecer el hecho que el Dr. Stallman venga a nuestro país [...]]]></description>
			<content:encoded><![CDATA[<p>Richard Stallman, fundador del Free Software Foundation, y el sistema operativo GNU, estará en Paraguay en noviembre. Dicha noticia alegra a todos lo que estamos de acuerdo (aunque sea parcialmente) con su filosofía, y los que usamos un increíble sistema operativo, como es GNU/Linux.</p>
<p>Al parecer el hecho que el Dr. Stallman venga a nuestro país auspiciado por una Universidad Privada, no <a href="http://www.tekaka.com/publicaciones/richard-stallman-en-paraguay-y-la-problematica-de-apropiacion/">gusta a mucho a algunos &#8220;jakers&#8221;</a>, que tiene un concepto errado de lo que es el software libre, por eso me tomé la molestia de tratar de explicar. En la página del <a href="http://www.gnu.org/">movimiento GNU</a> encontramos la definición del <a href="http://www.gnu.org/philosophy/free-sw.html">Sofware Libre</a> cuatro libertades esenciales:</p>
<ol>
<li>Libertad de usar el programa como queramos</li>
<li>Libertad de estudiar y cambiar el programa como queramos, para ello es necesario el acceso a los fuentes del programa.</li>
<li>Libertad de redistribuir el programa.</li>
<li>Libertad para distribuir nuestras versiones del programa.</li>
</ol>
<p>En ninguna de esas libertades ni siquiera se insinúa que debemos odiar el dinero, o no aceptar ayudas que vienen del sector privado, ni mucho menos criticar a algunas personas que hacen todo lo posible para hacer las cosas bien, sabiendo que los que critican nunca, jamás hicieron nada por la comunidad del SL del Paraguay, ni mucho menos del mundo…</p>
<p>Me pregunto,  que es esa moda de tener tal confusión a tal punto de odiar todo lo que genere dinero, que es ese pensamiento comunista, esas personas deberían mudarse a Cuba o a la China, para que sean plenamente felices. Acaso esas personas no trabajan en el sector privado?, acaso esas personas no tienen dinero? o por lo menos hicieron algún aporte a algún proyecto libre (<a href="http://www.fsf.org/register_form?referrer=6603">en dinero</a> o con códigos)?. Como Linus Torvalds dice &#8220;Talk is cheap, show me the code&#8221; hablar es fácil, lo que les falta es más acción.</p>
<p>Ojala entiendan que SL no es solamente instalar un sistema operativo y hacer algunos trucos en la consola.</p>
<p>Más textos sobre la <a href="http://www.linux.org.py/pipermail/lista-sl/">&#8220;pelea&#8221;</a></p>
<img src="http://feeds.feedburner.com/~r/crodas/~4/wQ398E9dNgY" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://cesar.la/la-pseudo-problematica-de-stallman-en-paraguay.html/feed</wfw:commentRss>
		<enclosure url="http://www.fsf.org/register_form?referrer=6603" length="629" type="application/octet-stream" /><media:content url="http://www.fsf.org/register_form?referrer=6603" fileSize="629" type="application/octet-stream" /><itunes:explicit>clean</itunes:explicit><itunes:subtitle>Richard Stallman, fundador del Free Software Foundation, y el sistema operativo GNU, estará en Paraguay en noviembre. Dicha noticia alegra a todos lo que estamos de acuerdo (aunque sea parcialmente) con su filosofía, y los que usamos un increíble sistema </itunes:subtitle><itunes:author>Cesar D. Rodas</itunes:author><itunes:summary>Richard Stallman, fundador del Free Software Foundation, y el sistema operativo GNU, estará en Paraguay en noviembre. Dicha noticia alegra a todos lo que estamos de acuerdo (aunque sea parcialmente) con su filosofía, y los que usamos un increíble sistema operativo, como es GNU/Linux. Al parecer el hecho que el Dr. Stallman venga a nuestro país [...]</itunes:summary><itunes:keywords>internet,php,mysql,apache,server,saddor</itunes:keywords><feedburner:origLink>http://cesar.la/la-pseudo-problematica-de-stallman-en-paraguay.html</feedburner:origLink></item>
		<item>
		<title>Optimizando sitios webs utilizando gcache</title>
		<link>http://feedproxy.google.com/~r/crodas/~3/b6nD18ENhns/optimizando-sitios-webs-utilizando-gcache.html</link>
		<comments>http://cesar.la/optimizando-sitios-webs-utilizando-gcache.html#comments</comments>
		<pubDate>Fri, 27 Jun 2008 04:42:38 +0000</pubDate>
		<dc:creator>saddor@cesarodas.com (Cesar D. Rodas)</dc:creator>
		
		<category><![CDATA[Open Source]]></category>

		<category><![CDATA[PHP]]></category>

		<category><![CDATA[Programación]]></category>

		<guid isPermaLink="false">http://cesar.la/?p=12</guid>
		<description><![CDATA[Hoy en día con sitios como digg, meneame o similares, es muy fácil llegar a tener miles de visitas diarias. Esas visitas pueden producirnos algún dinero, por esa razón o simplemente por respeto a nuestros visitantes, tenemos que  tener un sitio que pueda funcionar para todos los visitantes. Y ya que miles de visitas [...]]]></description>
			<content:encoded><![CDATA[<p>Hoy en día con sitios como <a href="http://digg.com">digg</a>, <a href="http://meneame.net/">meneame</a> o similares, es muy fácil llegar a tener miles de visitas diarias. Esas visitas pueden producirnos <a href="http://www.google.com/adsense">algún dinero</a>, por esa razón o simplemente por respeto a nuestros visitantes, tenemos que  tener un sitio que pueda funcionar para todos los visitantes. Y ya que miles de visitas significan mucho trabajo para el servidor web, bases de datos, gran consumo de ancho de banda, entre otros cosas, tenemos que buscar la forma de optimizar todo al máximo.</p>
<p>Para tener una solución escribí una clase en php, llamado <a href="http://cesars.users.phpclasses.org/browse/package/3972.html">gCache</a>, que ofrece una interfaz amigable para cachear fácilmente contenidos webs. En esta nueva versión que recién terminé soporta responder páginas comprimidas, que es bastante útil para ahorrar ancho de banda.</p>
<p>Aquí esta un ejemplo de uso:</p>
<pre class="prettyprint">&lt;?php
include("gCache.php");
$cache = new gCache;
$cache-&gt;folder = "./cache/";
$cache-&gt;contentId="var45";
$cache-&gt;timeout = 1; /* 1 minuto */
/* gCache cachea toda la página */
/* entonces gCache puede decidir si enviar comprimido o no */
$cache-&gt;isPage=true;
if ($cache-&gt;Valid()) {
    echo $cache-&gt;content;
} else {
$cache-&gt;capture();
?&gt;
&lt;html&gt;
&lt;head&gt;
&lt;title&gt;Cached page&lt;/title&gt;
&lt;head&gt;
&lt;body bgcolor="#CCCCCC"&gt;
    &lt;h1&gt;Testing Cesar D. Rodas' gCache Class&lt;/h1&gt;
    &lt;hr&gt;
    &lt;h2&gt;Example of how to cache a hole page&lt;/h2&gt;
    &lt;hr&gt;
&lt;p&gt;Basicaly what the gCache do, is to store a web-page or a portion of it into
  a&lt;em&gt; &lt;em&gt;cache file&lt;/em&gt;. &lt;/em&gt;The &lt;em&gt;&lt;em&gt;cache file&lt;/em&gt;&lt;/em&gt; has a $timeout
  in second of cache vitality, after that the cache will be re-created.&lt;/p&gt;
&lt;p&gt;Also this class provides and locking system which is not depending of POSIX
  or other OS, this feature becomes to this class very portable.&lt;/p&gt;
&lt;hr&gt;
&lt;font size="1"&gt;This cache page was generated at
&lt;?php echo date("Y/m/d H:i:s")?&gt;
&lt;/font&gt;&lt;font size="1"&gt; by &lt;a href="http://cesars.users.phpclasses.org/gcache"&gt;gCache&lt;/a&gt;
&lt;/font&gt;
&lt;/body&gt;
&lt;/html&gt;
&lt;?
$cache-&gt;endcapture();
}
?&gt;</pre>
<p>Si se tiene mucha memoria RAM, optimizaría bastante que los caches que cambian frecuentemente sea hagan en un <a href="http://www.vanemery.com/Linux/Ramdisk/ramdisk.html">&#8220;RAM DISK&#8221;</a> o  <a href="http://en.wikipedia.org/wiki/TMPFS">tmpfs</a>:</p>
<p><a href="http://cesars.users.phpclasses.org/browse/author/1.html">Manuel Lemos</a> escribió en su <a href="http://cesars.users.phpclasses.org/blog/">blog</a> otros consejos de como <a href="http://cesas.users.phpclasses.org/blog/post/66-More-defensive-programming-practices-to-survive-Web-site-traffic-peaks.html">optimizar sitios webs</a>.</p>
<img src="http://feeds.feedburner.com/~r/crodas/~4/b6nD18ENhns" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://cesar.la/optimizando-sitios-webs-utilizando-gcache.html/feed</wfw:commentRss>
		<feedburner:origLink>http://cesar.la/optimizando-sitios-webs-utilizando-gcache.html</feedburner:origLink></item>
	<copyright>Every text used here is protected under the GNU GPL license</copyright><media:credit role="author">Cesar D. Rodas</media:credit><media:rating>nonadult</media:rating><media:description type="plain">Saddor Blog</media:description></channel>
</rss><!-- Dynamic Page Served (once) in 0.885 seconds -->
