<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	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:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>El rincón de Gu</title>
	<atom:link href="http://gustavo.duranlinar.es/feed/" rel="self" type="application/rss+xml" />
	<link>http://gustavo.duranlinar.es</link>
	<description></description>
	<lastBuildDate>Fri, 19 Aug 2011 18:00:33 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Servidor Apache2 + SSL + subversion + websvn + DAV</title>
		<link>http://gustavo.duranlinar.es/2011/08/servidor-apache2-ssl-subversion-websvn-dav/</link>
		<comments>http://gustavo.duranlinar.es/2011/08/servidor-apache2-ssl-subversion-websvn-dav/#comments</comments>
		<pubDate>Fri, 19 Aug 2011 18:00:33 +0000</pubDate>
		<dc:creator>gu</dc:creator>
				<category><![CDATA[Sistemas]]></category>
		<category><![CDATA[apache2]]></category>
		<category><![CDATA[debian]]></category>
		<category><![CDATA[ssl]]></category>
		<category><![CDATA[subversion]]></category>
		<category><![CDATA[svn]]></category>

		<guid isPermaLink="false">http://gustavo.duranlinar.es/?p=151</guid>
		<description><![CDATA[Instalación y configuración básica de un servidor de repositorios y control de versiones con subversion bajo Debian squeeze]]></description>
			<content:encoded><![CDATA[<style type="text/css">
#leftcontainerBox {
	float:left;
	position: fixed;
	top: 60%;
	left: 70px;
}
#leftcontainerBox .buttons {
	float:left;
	clear:both;
	margin:4px 4px 4px 4px;
	padding-bottom:2px;
}
#bottomcontainerBox {
	width: 50%;
	padding-top: 1px;
}
#bottomcontainerBox .buttons {
	float: left;
	margin: 4px 4px 4px 4px;
}
</style>
<p>En esta entrada vamos a tratar la instalación y configuración básica de un servidor de repositorios y control de versiones con subversion bajo <em>Debian squeeze</em>.</p>
<p>Primero descargamos e instalamos los paquetes necesarios y sus dependencias, si no los tuviesemos ya, con sus configuraciones por defecto:</p>
<pre>
# apt-get install apache2 libapache2-mod-php5 openssl \
subversion libapache2-svn subversion-tools websvn
</pre>
<p>La configuración por defecto de websvn generará un archivo de configuración que interferirá con nuestros propósitos, por ello puedes borrarlo o comentar su contenido:</p>
<pre>
# rm /etc/apache2/conf.d/websvn
</pre>
<p>Acto seguido generamos el certíficado para la conexión segura, que lo haremos de la siguiente forma:</p>
<pre>
# mkdir /etc/apache2/ssl
# RANDFILE=/dev/random openssl req $@ -new -x509 -days 365 -nodes \
    -out /etc/apache2/sslcerts/websvn.pem \
    -keyout /etc/apache2/sslcerts/websvn.pem

# chmod 600 /etc/apache2/sslcerts/websvn.pem
</pre>
<p>En el momento de generar un certificado nos solicitará cierta información acerca de este, tales como el país, ciudad/provincia, empresa, área/departamento, etc.<br />
El uso de un certificado generado de esta forma hará que el navegador muestre una alerta de seguridad. Si queremos evitar esto hay que pasar por caja y comprar un certificado a una <a href="http://es.wikipedia.org/wiki/Autoridad_de_certificaci%C3%B3n">Autoridad de Certificación</a>.</p>
<h2>Configuración de Apache2 + SSL + websvn</h2>
<p>Pasamos a configurar el acceso seguro mediante SSL en Apache2, así como la ubicación de los repositorios.</p>
<p>El directorio donde alojaremos los repositorios, recordemos que debe estar accesible para websvn:</p>
<pre>
# mkdir /var/svn
# chown www-data:www-data /var/svn
# chmod 655 /var/svn
</pre>
<p>Creamos el archivo de configuración de Apache2:</p>
<pre>
# vi /etc/apache2/sites-available/svn
</pre>
<p>Contenido que agregaremos a este archivo:</p>
<pre class="brush: plain; title: ; notranslate">
NameVirtualHost *:443
&lt;VirtualHost *:443&gt;
        ServerAdmin default@exmaple.com
        SSLEngine On
        SSLCertificateFile /etc/apache2/sslcerts/websvn.pem

        DocumentRoot /var/www
        &lt;Directory /&gt;
                Options FollowSymLinks
                AllowOverride None
        &lt;/Directory&gt;

        &lt;Directory /var/www/&gt;
                Options Indexes FollowSymLinks MultiViews
                AllowOverride None
                Order allow,deny
                Allow from all
        &lt;/Directory&gt;

        Alias /websvn /usr/share/websvn
        &lt;Directory /usr/share/websvn&gt;
                DirectoryIndex index.php
                Options FollowSymLinks
                Order allow,deny
                Allow from all
                AuthType Basic
                AuthName &quot;Subversion Repository&quot;
                AuthUserFile /var/svn/.auth
                Require valid-user
       &lt;/Directory&gt;

       &lt;Location /svn/&gt;
                DAV svn
                SVNParentPath /var/svn/
                SVNListParentPath on
                AuthType Basic
                AuthName &quot;Subversion Repository&quot;
                AuthUserFile /var/svn/.auth
                Require valid-user
       &lt;/Location&gt;

&lt;/VirtualHost&gt;
</pre>
<p>Ahora agregamos usuarios que tendrán permiso para acceder a nuesto repositorio:</p>
<pre>
# touch /var/svn/.auth
# chown www-data:www-data /var/svn/.auth
# htpasswd -m /var/svn/.auth nombre_del_usuario
</pre>
<p>Para agregar varios usuarios repetir la última línea tantas veces como sea necesario. Recuerda que con esta configuración todos los usuarios tendrán los mismos privilegios de acceso. Para afinar puedes consultar la documentación de <em>mod_authz_svn</em></p>
<p>Observación de seguridad: el archivo con los datos de usuarios y contraseñas encriptadas únicamente sería accesible desde el exterior mediante el intérprete DAV. Si aun así queremos asegurarnos que no es accesible podemos agregar una directiva de seguridad en <i>/etc/apache2/sites-available/svn</i>, dentro del apartado VirtualHost:</p>
<pre class="brush: plain; title: ; notranslate">
&lt;Files ~ &quot;/var/svn/.auth&quot;&gt;
Order allow,deny
Deny from all
&lt;/Files&gt;
</pre>
<p>Activamos el sitio en Apache:</p>
<pre>
# ln -s /etc/apache2/sites-available/svn \
/etc/apache2/sites-enabled/svn
</pre>
<p>O bien:</p>
<pre>
# a2ensite svn
</pre>
<p>Tras esto reiniciamos el servicio Apache:</p>
<pre>
# /etc/init.d/apache2 restart
</pre>
<p>Y ya podremos verlo!! Por supuesto debemos autenticarnos antes.<br />
https://direccion_de_mi_sitio/websvn/ para acceder a <i>websvn</i><br />
https://direccion_de_mi_sitio/svn/ para acceder a <i>subversion</i></p>
<h2>Configurar y usar repositorios</h2>
<p>Para agregar un nuevo repositorio:</p>
<pre>
# cd /var/svn
# mkdir mirepositorio
# svnadmin create mirepositorio
# chown www-data:www-data mirepositorio -R
</pre>
<p>En la interfaz de websvn aparece un repositorio de muestra llamado &#8220;repos 1&#8243;, para eliminar este hay que editar el archivo <i>/etc/websvn/svn_deb_conf.inc</i> y comentar o eliminar la línea donde se crea este.</p>
<pre>
...
#$config->addRepository("repos 1", "file:///var/svn");
...
</pre>
<p>Y ya por último, cómo agregar la información al repositorio. En mi caso he utilizado el cliente <a href="http://tortoisesvn.tigris.org/">TortoiseSVN</a>. Su uso es tan sencillo como abrir el &#8220;Repo-browser&#8221;, dar la dirección del repositorio (eg: https://misitio/svn/repositorio1), autenticarse y arrastrar los archivos a añadir o actualizar.</p>
<p><a href="http://gustavo.duranlinar.es/wp-content/uploads/2011/08/Tortoisesvn.png"><img src="http://gustavo.duranlinar.es/wp-content/uploads/2011/08/Tortoisesvn-300x230.png" alt="" title="Tortoisesvn" width="300" height="230" class="aligncenter size-medium wp-image-188" /></a></p>
<p>Fuentes consultadas:</p>
<ul>
<li><a href="http://subversion.apache.org/">http://subversion.apache.org/</a></li>
<li><a href="http://svnbook.red-bean.com/index.es.html">http://svnbook.red-bean.com/index.es.html</a></li>
<li><a href="http://tortoisesvn.net/docs/release/TortoiseSVN_en/tsvn-serversetup-apache.html">http://tortoisesvn.net/docs/release/TortoiseSVN_en/tsvn-serversetup-apache.html</a></li>
<li><a href="http://www.esdebian.org/wiki/subversion-apache2-ssl-interface-web-websvn">http://www.esdebian.org/wiki/subversion-apache2-ssl-interface-web-websvn</a></li>
<li><a href="http://wiki.freaks-unidos.net/Apache2%20SSL%20and%20Subversion%20in%20Debian">http://wiki.freaks-unidos.net/Apache2%20SSL%20and%20Subversion%20in%20Debian</a></li>
<li><a href="http://httpd.apache.org/docs/2.0/mod/core.html">http://httpd.apache.org/docs/2.0/mod/core.html</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://gustavo.duranlinar.es/2011/08/servidor-apache2-ssl-subversion-websvn-dav/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>In memorian</title>
		<link>http://gustavo.duranlinar.es/2011/03/in-memorian/</link>
		<comments>http://gustavo.duranlinar.es/2011/03/in-memorian/#comments</comments>
		<pubDate>Sat, 19 Mar 2011 00:59:22 +0000</pubDate>
		<dc:creator>gu</dc:creator>
				<category><![CDATA[Off Topic]]></category>
		<category><![CDATA[cancer]]></category>
		<category><![CDATA[in memorian]]></category>
		<category><![CDATA[victor garcia]]></category>

		<guid isPermaLink="false">http://gustavo.duranlinar.es/?p=136</guid>
		<description><![CDATA[<style type="text/css">
#leftcontainerBox {
	float:left;
	position: fixed;
	top: 60%;
	left: 70px;
}
#leftcontainerBox .buttons {
	float:left;
	clear:both;
	margin:4px 4px 4px 4px;
	padding-bottom:2px;
}
#bottomcontainerBox {
	width: 50%;
	padding-top: 1px;
}
#bottomcontainerBox .buttons {
	float: left;
	margin: 4px 4px 4px 4px;
}
</style>
Victor García Valero (1977-2011) Si tuviera que decir cómo conocí a Victor no podría recordar el momento ni la situación, igual que recordar cómo aprendí a andar&#8230; Mayormente porque ambas cosas ocurrieron más o menos el mismo año. La verdad que podíamos pasar sin vernos durante 2 ó 3 años, y me arrepiento de no [...]]]></description>
			<content:encoded><![CDATA[<style type="text/css">
#leftcontainerBox {
	float:left;
	position: fixed;
	top: 60%;
	left: 70px;
}
#leftcontainerBox .buttons {
	float:left;
	clear:both;
	margin:4px 4px 4px 4px;
	padding-bottom:2px;
}
#bottomcontainerBox {
	width: 50%;
	padding-top: 1px;
}
#bottomcontainerBox .buttons {
	float: left;
	margin: 4px 4px 4px 4px;
}
</style>
<h3>Victor García Valero (1977-2011)</h3>
<p>Si tuviera que decir cómo conocí a Victor no podría recordar el momento ni la situación, igual que recordar cómo aprendí a andar&#8230; Mayormente porque ambas cosas ocurrieron más o menos el mismo año. La verdad que podíamos pasar sin vernos durante 2 ó 3 años, y me arrepiento de no haberlo visitado en esta última etapa. No ya asiduamente, sino simplemente pasar a darle ánimos. &#8220;No te rindas Victor&#8221; le hubiera dicho. &#8220;El cáncer es uno y cobarde, tú puedes&#8221;&#8230; Pero se ve que no pudo.</p>
<p><a href="http://gustavo.duranlinar.es/wp-content/uploads/2011/03/victor.jpg"><img src="http://gustavo.duranlinar.es/wp-content/uploads/2011/03/victor-224x300.jpg" alt="" title="Victor Garcia Valero - Málaga - Julio 2008" width="224" height="300" class="aligncenter size-medium wp-image-137" /></a></p>
<p>Sinceramente a él le debo gran parte de mi frikismo informático. Por &#8220;su culpa&#8221; instalé OS/2 Warp sin haberlo tocado en mi vida (ni lo he vuelto a tocar desde entonces). Instalé Windows 95 el mismo dia que salió a la venta&#8230; Sí, por él me he metido en jaleos informáticos que me sobrepasaban y los superé. Y gracias a él aprendí muchas cosas, fue como una musa. No ya pasarnos juegos del <a href="http://es.wikipedia.org/wiki/Commodore_64">Commodore 64</a>, sino que cuando yo apenas me saltaba las claves del PC de casa (un Inves con procesador NEC V20 a 10MHz)  para continuar mi ciudad del SimCity (en blanco y negro) o jugar al Dyna Blaster, él ya andaba liado con <a href="http://es.wikipedia.org/wiki/Bulletin_Board_System">BBS</a> con un MODEM 28kbps. Cuando yo ya jugaba al Alone in the Dark en un 486, él estaba conectando a Internet directamente a EEUU (con un MODEM de 96Kbps), porque en España era imposible. El primer ordenador con <a href="http://es.wikipedia.org/wiki/Acpi">ACPI</a> que vi fue el suyo. A su nivel fue pionero en muchas cosas, siempre relacionado con las telecomunicaciones. Si existía algún aparato raro o lo tenía o lo iba a conseguir o se lo habían prestado.</p>
<p>Victor, ya no hace falta que te mande un abrazo, porque siempre estarás entre nosotros. Ahora no estás más lejos, sino que te tenemos al lado.</p>
<p>Repercusión mediática:</p>
<ul>
<li><a href="http://www.victorgarciavalero.com/">http://www.victorgarciavalero.com/</a></li>
<li><a href="http://www.myspace.com/nono1978/blog/542506169">http://www.myspace.com/nono1978/blog/542506169</a></li>
<li><a href="http://jagelado.com/post/3938370435/hoy-nos-ha-dejado-victor-el-reportero-de-las">http://jagelado.com/post/3938370435/hoy-nos-ha-dejado-victor-el-reportero-de-las</a></li>
<li><a href="http://www.elultimoblog.com/nos-ha-dejado-victor-el-reportero-de-lascosascuriosas-com/">http://www.elultimoblog.com/nos-ha-dejado-victor-el-reportero-de-lascosascuriosas-com/</a></li>
<li><a href="http://www.kafelog.com/2011/03/victor-el-reportero-de-lascosascuriosas-com-nos-ha-dejado/">http://www.kafelog.com/2011/03/victor-el-reportero-de-lascosascuriosas-com-nos-ha-dejado/</a></li>
<li><a href="http://asociacionpodcast.es/2011/03/18/victor-gracias/">http://asociacionpodcast.es/2011/03/18/victor-gracias/</a></li>
<li><a href="http://www.filmica.com/sonia_blanco/archivos/011108.html">http://www.filmica.com/sonia_blanco/archivos/011108.html</a></li>
<li><a href="http://podcastfera.com/profesorbacterio/?p=280">http://podcastfera.com/profesorbacterio/?p=280</a></li>
<li><a href="http://podcastellano.es/victor-el-reportero-de-lascosascuriosas-com-nos-ha-dejado?utm_medium=twitter&#038;utm_source=twitterfeed">http://podcastellano.es/victor-el-reportero-de-lascosascuriosas-com-nos-ha-dejado?utm_medium=twitter&#038;utm_source=twitterfeed</a></li>
<li><a href="http://www.luisbermejo.com/2011/03/victor-garcia-valero-podcaster-de.html">http://www.luisbermejo.com/2011/03/victor-garcia-valero-podcaster-de.html</a></li>
<li>Y más&#8230;</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://gustavo.duranlinar.es/2011/03/in-memorian/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Formularios y juego de caracteres</title>
		<link>http://gustavo.duranlinar.es/2010/10/formularios-y-juego-de-caracteres/</link>
		<comments>http://gustavo.duranlinar.es/2010/10/formularios-y-juego-de-caracteres/#comments</comments>
		<pubDate>Tue, 19 Oct 2010 09:02:52 +0000</pubDate>
		<dc:creator>gu</dc:creator>
				<category><![CDATA[HTML]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[ansi]]></category>
		<category><![CDATA[codificación]]></category>
		<category><![CDATA[iso]]></category>
		<category><![CDATA[juego de caracteres]]></category>
		<category><![CDATA[utf8]]></category>

		<guid isPermaLink="false">http://gustavo.duranlinar.es/?p=129</guid>
		<description><![CDATA[<style type="text/css">
#leftcontainerBox {
	float:left;
	position: fixed;
	top: 60%;
	left: 70px;
}
#leftcontainerBox .buttons {
	float:left;
	clear:both;
	margin:4px 4px 4px 4px;
	padding-bottom:2px;
}
#bottomcontainerBox {
	width: 50%;
	padding-top: 1px;
}
#bottomcontainerBox .buttons {
	float: left;
	margin: 4px 4px 4px 4px;
}
</style>
¿A quién que haya programado un sitio web no le ha ocurrido que en el texto aparecieran caracteres extraños en lugar de vocales con tilde y eñes? Pues eso se debe al uso de distintos juegos de caracteres entre las distintas partes que componen nuestro sitio. Lo más normal es entre el Sistema Gestor de [...]]]></description>
			<content:encoded><![CDATA[<style type="text/css">
#leftcontainerBox {
	float:left;
	position: fixed;
	top: 60%;
	left: 70px;
}
#leftcontainerBox .buttons {
	float:left;
	clear:both;
	margin:4px 4px 4px 4px;
	padding-bottom:2px;
}
#bottomcontainerBox {
	width: 50%;
	padding-top: 1px;
}
#bottomcontainerBox .buttons {
	float: left;
	margin: 4px 4px 4px 4px;
}
</style>
<p>¿A quién que haya programado un sitio web no le ha ocurrido que en el texto aparecieran caracteres extraños en lugar de vocales con tilde y eñes? Pues eso se debe al uso de distintos juegos de caracteres entre las distintas partes que componen nuestro sitio. Lo más normal es entre el Sistema Gestor de Bases de Datos y los archivos de script, pero hay más casos, como el envío asíncrono de datos mediante JavaScript.</p>
<p>La recomendación es utilizar UTF8 en todos los casos, esto nos quitaría gran cantidad de problemas. Sin embargo debemos tener especial cuidado en la codificación de los archivos de copia de seguridad, ya que al recuperar los datos pueden hacer un estropicio importante; e incluso la que utilizan los programas de gestión adicionales que utilicemos (PHPMyAdmin, MySQL Query Browser, etc).</p>
<p>Igual de importante es la codificación utilizada en los archivos que componen nuestro sitio (.htm, .php, .js, .css&#8230;), ya que un archivo codificado en ANSI, Unicode o UTF8 y mostrado en una codificación diferente nos mostrará caracteres raros igualmente. Así pues si nuestro sitio está completamente realizado con un juego de caracteres ISO, utilizaremos ficheros ANSI; y UTF8 con su par. Mi experiencia con Unicode ha sido de auténticos dolores de cabeza, de modo que no recomiendo su uso, al menos para trabajar con páginas en español.<br />
El software de edición debe tener la posibilidad de trabajar con distintas codificaciones, hasta si eres un masoquista y utilizas el <em>bloc de notas</em> de MS-Windows tienes esta posibilidad en &#8220;Guardar como&#8230;&#8221;.</p>
<p>Ahora bien ¿qué ocurre al transferir datos de un script a otro? Pues lo mismo, ambos deberían tener la misma codificación. No obstante en PHP disponemos de las funciones <a href="http://es.php.net/manual/es/function.utf8-encode.php">utf8_encode</a> y <a href="http://es.php.net/manual/es/function.utf8-decode.php">utf8_decode</a>, siempre que el cambio sea entre UTF-8 e ISO-8859-1. Estas funciones nos serán muy útiles a la hora de recodificar los datos recibidos para alojarlos en la base de datos con el juego de caracteres adecuado. También nos serán útiles cuando los datos los recibimos de otro sitio web sobre el que no tengamos control.</p>
<p>Existe una problemática adicional cuando trabajamos con ISO-8859-1 y enviamos los datos mediante AJAX, ya que siempre se envían en UTF.</p>
<p>Como recomendación adicional, especificar el juego de caracteres utilizado tanto en las cabeceras de HTML como en la del documento mediante PHP, ya que el servidor web por defecto enviará las establecidas. Por ejemplo MS-IIS por defecto informa que se usa el juego de caracteres ISO-8859-1.</p>
<pre class="brush: php; title: ; notranslate">
&lt;?php
header (&quot;Content-type: text/html; charset=UTF-8&quot;);
?&gt;
&lt;html&gt;
&lt;head&gt;
&lt;meta http-equiv=&quot;Content-type&quot; content=&quot;text/html; charset=UTF-8&quot; /&gt;
&lt;title&gt;ejemplo&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
...
&lt;/body&gt;
&lt;/html&gt;
</pre>
<p>Por último, para una reconversión de los datos recibidos, podemos utilizar un sencillo bucle:</p>
<pre class="brush: php; title: ; notranslate">
foreach ($_POST as $key =&gt; $val)
    $$key = utf8_decode($val);
</pre>
<p>Si además esos datos los vamos a incluir en una consulta MySQL:</p>
<pre class="brush: php; title: ; notranslate">
foreach ($_POST as $key =&gt; $val)
    $$key = mysql_real_esacape_string(utf8_decode($val));
</pre>
<p>Espero que sea de utilidad.</p>
]]></content:encoded>
			<wfw:commentRss>http://gustavo.duranlinar.es/2010/10/formularios-y-juego-de-caracteres/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>BackUp de MySQL con PHP y compresión ZIP</title>
		<link>http://gustavo.duranlinar.es/2010/10/backup-de-mysql-con-php-y-compresion-zip/</link>
		<comments>http://gustavo.duranlinar.es/2010/10/backup-de-mysql-con-php-y-compresion-zip/#comments</comments>
		<pubDate>Wed, 13 Oct 2010 10:32:15 +0000</pubDate>
		<dc:creator>gu</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Sistemas]]></category>
		<category><![CDATA[backup]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://gustavo.duranlinar.es/?p=125</guid>
		<description><![CDATA[<style type="text/css">
#leftcontainerBox {
	float:left;
	position: fixed;
	top: 60%;
	left: 70px;
}
#leftcontainerBox .buttons {
	float:left;
	clear:both;
	margin:4px 4px 4px 4px;
	padding-bottom:2px;
}
#bottomcontainerBox {
	width: 50%;
	padding-top: 1px;
}
#bottomcontainerBox .buttons {
	float: left;
	margin: 4px 4px 4px 4px;
}
</style>
Rescato un tema que tenía publicado en Foros del Web. La base de datos del trabajo ha superado 1GB de tamaño, por lo que seguir haciendo dumps a lo bruto no es viable. Es por ello que me he currado un script y lo he añadido al &#8220;cron diario&#8221; del servidor. La forma de funcionar [...]]]></description>
			<content:encoded><![CDATA[<style type="text/css">
#leftcontainerBox {
	float:left;
	position: fixed;
	top: 60%;
	left: 70px;
}
#leftcontainerBox .buttons {
	float:left;
	clear:both;
	margin:4px 4px 4px 4px;
	padding-bottom:2px;
}
#bottomcontainerBox {
	width: 50%;
	padding-top: 1px;
}
#bottomcontainerBox .buttons {
	float: left;
	margin: 4px 4px 4px 4px;
}
</style>
<p>Rescato un tema que tenía publicado en <a href="http://www.forosdelweb.com/f18/backup-mysql-con-php-compresion-zip-774288/">Foros del Web</a>.</p>
<hr />
<p>La base de datos del trabajo ha superado 1GB de tamaño, por lo que seguir haciendo dumps a lo bruto no es viable.</p>
<p>Es por ello que me he currado un script y lo he añadido al &#8220;cron diario&#8221; del servidor.</p>
<p>La forma de funcionar es ver las distintas bases de datos de usuario y volcarlas mediante el comando mysqldump. Posteriormente se comprime en ZIP y se eliminan los archivos temporales utilizados. Luego eliminaría las copias antiguas (en este caso, anteriores a 3 dias).</p>
<pre class="brush: php; title: ; notranslate">
#############################################
#
# Tarea de copia seguridad de todas las bases de datos en MySQL
#
# CopyLeft, puedes hacer con este script lo que te de la gana
#
#############################################
set_time_limit(0);
header(&quot;Content-type: text/plain; charset=UTF-8&quot;);
echo date(&quot;Y-m-d H:i&quot;, time()) . &quot; Creando copia de seguridad MySQL...\r\n&quot;;

// Datos de acceso a MySQL
$myhost = &quot;localhost&quot;;
$myuser = 'root';
$mypass = 'miclave';
$DB = mysql_connect($myhost, $myuser, $mypass) or die(date(&quot;Y-m-d H:i&quot;, time()) . &quot; ERROR!! No se pudo conectar a MySQL.\r\n&quot;);

// Otros parámetros
$OUTDIR = &quot;D:\\backup\\&quot;; // Cambiar segun necesidades y tipo servidor
$now = date(&quot;YmdHi&quot;, time());
$outfile = &quot;MySQL_$now.zip&quot;;
$periodo = time() - 259200; // Los archivos anteriores a este periodo (3 dias = 259200 segundos) serán borrados

// Crear nuevo archivo ZIP
# Más información sobre la clase PHP
# http://es.php.net/manual/en/class.ziparchive.php
echo date(&quot;Y-m-d H:i&quot;, time()) . &quot; Creando '$OUTDIR$outfile.zip' ... &quot;;
$zip = new ZipArchive;
if (!$zip-&gt;open(&quot;$OUTDIR$outfile&quot;, ZIPARCHIVE::CREATE)) die(&quot;ERROR!!\r\n&quot;);
echo &quot;OK.\r\n&quot;;

// Tomar un listado de bases de datos
$q = mysql_query(&quot;SHOW DATABASES&quot;);

// Volcar todas las bases
while ($database = mysql_fetch_row($q))
    if ($database[0] != &quot;information_schema&quot; &amp;&amp; $database[0] != &quot;mysql&quot;)
        {
        // Nombrar archivo
        $filename = &quot;{$database[0]}.sql&quot;;
        $tempfile = date(&quot;YmdHis&quot;, time()) . &quot;.~swap&quot;;

        echo date(&quot;Y-m-d H:i&quot;, time()) . &quot; Volcando '$filename' ... &quot;;

        // Volcar datos
        system(&quot;mysqldump -h $myhost -u $myuser -p$mypass --opt {$database[0]} &gt; $OUTDIR$tempfile&quot;);

        echo &quot;OK.\r\n&quot;
        . date(&quot;Y-m-d H:i&quot;, time()) . &quot; Agregando '$filename' a '$outfile' ... &quot;;

        //  Agregar archivo al ZIP
        $zip-&gt;addFile($OUTDIR.$tempfile, $filename);

        // Recordar los temporales utilizados
        $DUMPFILES[] = $OUTDIR.$tempfile;

        echo &quot;OK.\r\n&quot;;
        }

// Desconectar de la base de datos
mysql_close($DB);

// Cerrar archivo ZIP
$zip-&gt;close();

// Eliminar temporales. Importante hacerlo DESPUÉS de cerrar el ZIP
foreach($DUMPFILES as $file)
    unlink($file);

// Elminar archivos antiguos
echo date(&quot;Y-m-d H:i&quot;, time()) . &quot; Eliminando copias antiguas...\r\n&quot;;
$D = opendir($OUTDIR);
while ($F = readdir($D))
    if ($F != &quot;.&quot; &amp;&amp; $F != &quot;..&quot;)
        if (filectime($OUTDIR.$F) &lt; $periodo)
            if (!unlink($OUTDIR.$F))
                echo date(&quot;Y-m-d H:i&quot;, time()) . &quot; No se pudo eliminar el archivo $F.\r\n&quot;;
closedir($D);

echo date(&quot;Y-m-d H:i&quot;, time()) . &quot; Tarea finalizada.\r\n&quot;;
</pre>
<p>Gracias a la compresión en ZIP ahora la copia diaria ocupa ~77MB en vez de ~1GB.</p>
<p>Espero que os sirva a muchos/as.</p>
]]></content:encoded>
			<wfw:commentRss>http://gustavo.duranlinar.es/2010/10/backup-de-mysql-con-php-y-compresion-zip/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Gestión de la navegación de una web (básico)</title>
		<link>http://gustavo.duranlinar.es/2010/10/gestion-de-la-navegacion-de-una-web/</link>
		<comments>http://gustavo.duranlinar.es/2010/10/gestion-de-la-navegacion-de-una-web/#comments</comments>
		<pubDate>Thu, 07 Oct 2010 15:58:09 +0000</pubDate>
		<dc:creator>gu</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[básico]]></category>
		<category><![CDATA[get]]></category>
		<category><![CDATA[navegación]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://gustavo.duranlinar.es/?p=114</guid>
		<description><![CDATA[<style type="text/css">
#leftcontainerBox {
	float:left;
	position: fixed;
	top: 60%;
	left: 70px;
}
#leftcontainerBox .buttons {
	float:left;
	clear:both;
	margin:4px 4px 4px 4px;
	padding-bottom:2px;
}
#bottomcontainerBox {
	width: 50%;
	padding-top: 1px;
}
#bottomcontainerBox .buttons {
	float: left;
	margin: 4px 4px 4px 4px;
}
</style>
A la hora de maquetar un sitio web debemos tener en cuenta la estructura que va a tener. Aquí os propongo un método de navegación por parámetros GET, que si además lo combinais con mod_rewrite o similar, quedará bastante mejor desde el punto de vista SEO al tener una URI más amigable. Pero esa es [...]]]></description>
			<content:encoded><![CDATA[<style type="text/css">
#leftcontainerBox {
	float:left;
	position: fixed;
	top: 60%;
	left: 70px;
}
#leftcontainerBox .buttons {
	float:left;
	clear:both;
	margin:4px 4px 4px 4px;
	padding-bottom:2px;
}
#bottomcontainerBox {
	width: 50%;
	padding-top: 1px;
}
#bottomcontainerBox .buttons {
	float: left;
	margin: 4px 4px 4px 4px;
}
</style>
<p>A la hora de maquetar un sitio web debemos tener en cuenta la estructura que va a tener. Aquí os propongo un método de navegación por parámetros GET, que si además lo combinais con <a href="http://httpd.apache.org/docs/2.0/mod/mod_rewrite.html" target="_blank">mod_rewrite</a> o similar, quedará bastante mejor desde el punto de vista SEO al tener una <a href="http://es.wikipedia.org/wiki/Uniform_Resource_Identifier" target="_blank">URI</a> más amigable. Pero esa es otra historia que lo mismo toco en el futuro.</p>
<p>La cosa es que en nuestro sitio web tendremos el contenido almacenado en archivos o en una base de datos y accederemos a una u otra parte por unos enlaces internos. Para el artículo y para que sea más comprensible la explicación voy a prescindir del uso de la base de datos. Es decir, voy a poner un ejemplo de un sitio hecho <em>a jierro</em>, si bien en la práctica no es lo más adecuado.</p>
<p>Pues considerando que nuestro sitio va a tener distintos apartados o secciones y sus correspondientes subsecciones, utilizaremos para navegar dos variables &#8220;sec&#8221; y &#8220;sub&#8221;.</p>
<p>Los enlaces pues quedarán algo parecido a <em>./?sec=catalogo&amp;sub=productos</em>. Con mod_rewrite quedaría un enlace tipo <em>./catalogo/productos/</em>.</p>
<p>Para obtener estos valores, podemos hacer algo como esto:</p>
<pre class="brush: php; title: ; notranslate">
// inicializar valores
$sec = $sub = &quot;&quot;;

// Tomar valores si estuviesen disponibles.
if (isset($_GET['sec'])) $sec = $_GET['sec'];
if (isset($_GET['sub'])) $sub = $_GET['sub'];
</pre>
<p>¿Como manejamos internamente estas variables?<br />
Pues lo más cómodo es con un &#8220;switch&#8221;, de forma que validamos todas las opciones y si no es correcta podemos mostrar una página de error personalizada.<br />
En función de cada valor cargaremos una página u otra. Es más, podemos (de hecho es recomendable) cambiar el título de la página, las metaetiquetas y otros detalles en función de cada sección.<br />
Así pués hagamos una plantilla de la página.</p>
<pre class="brush: xml; title: ; notranslate">
&lt;html&gt;
&lt;head&gt;
&lt;title&gt;$TITULO - mi sitio&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;!-- Menu de ejemplo --&gt;
&lt;div id=&quot;menu&quot;&gt;
  &lt;ul&gt;
    &lt;li&gt;&lt;a href=&quot;/&quot;&gt;Inicio&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;/?sec=seccion1&quot;&gt;sección 1&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;/?sec=seccion2&quot;&gt;sección 2&lt;/a&gt;
      &lt;ul&gt;
        &lt;li&gt;&lt;a href=&quot;/?sec=seccion2&amp;amp;sub=apartado1&quot;&gt;sección 2.1&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&quot;/?sec=seccion2&amp;amp;sub=apartado2&quot;&gt;sección 2.2&lt;/a&gt;&lt;/li&gt;
      &lt;/ul&gt;
    &lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;/?sec=seccion3&quot;&gt;sección 3&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
&lt;/div&gt;
&lt;!-- Contenido de la página --&gt;
&lt;div id=&quot;contenido&quot;&gt;
&lt;?php include $FILE; ?&gt;
&lt;/div&gt;
&lt;/body&gt;
&lt;/html&gt;
</pre>
<p>En el ejemplo he introducido 2 variables<br />
<strong>$TITULO</strong>: el título dinámico de la página<br />
<strong>$FILE</strong>: el archivo a incluir con el contenido</p>
<p>Pues ahora vamos a gestionar la navegación:</p>
<pre class="brush: php; title: ; notranslate">
switch ($sec)
  {
  case &quot;&quot;: // Inicio
    break;
  case &quot;seccion1&quot;:
    $TITULO = &quot;asdf 1&quot;;
    $FILE = &quot;s1.htm&quot;;
    break;
  case &quot;seccion2&quot;:
    switch ($sub)
      {
      case &quot;apartado1&quot;:
        $TITULO = &quot;asdf 2.1&quot;;
        $FILE = &quot;s2a1.htm&quot;;
        break;
      case &quot;apartado2&quot;:
        $TITULO = &quot;asdf 2.2&quot;;
        $FILE = &quot;s2a2.htm&quot;;
        break;
      }
    break;
  case &quot;seccion3&quot;:
    $TITULO = &quot;asdf 3&quot;;
    $FILE = &quot;s3.htm&quot;;
    break;
  default: // La sección no se ha encontrado, mostramos la página de error
    header(&quot;HTTP/1.0 404 Not Found&quot;);
    $TITULO = &quot;Error 404&quot;;
    $FILE = &quot;error.htm&quot;;
  }

// Comprobar que existe el fichero a incluir
if (!is_file($FILE))
  { // Es un error gordo, mostramos un mensaje y paramos la ejecución
  header(&quot;HTTP/1.0 404 Not Found&quot;);
  die(&quot;Error: archivo no encontrado&quot;);
  }
</pre>
<p>Este código, como es lógico, debe ir ANTES de la plantilla. Incluso podemos tener la plantilla por un lado, el control de navegación por otro y en index.php los <em>includes</em> necesarios.</p>
<p>¿Qué me dejo en el tintero?<br />
Para hacer esto mismo pero usando una base de datos hay un paso sencillo ya que en vez de tener varios <em>switch</em> anidados monstruosamente largos tendríamos una consulta de búsqueda a nuestra tabla de artículos, de donde obtendríamos tantos datos como necesitasemos (títulos, meta-etiquetas, privilegios de acceso, &#8230;); al igual que el menú, podría estar almacenado en otra tabla. Por supuesto tenemos que prevenirnos ante ataques de SQL-Injection. NUNCA pongas el valor de una variable GET o POST directamente en una consulta SQL.</p>
<p>Variante: Podemos simplificar mucho el control si el valor de &#8220;sec&#8221; fuese el nombre del fichero a incluir (sin la extensión). Por supuesto esto trae algunos inconvenientes de seguridad, así que no está de más comprobar que el nombre no contiene más que caracteres alfanuméricos y que el fichero se trata de un artículo.</p>
]]></content:encoded>
			<wfw:commentRss>http://gustavo.duranlinar.es/2010/10/gestion-de-la-navegacion-de-una-web/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Paginación de listados</title>
		<link>http://gustavo.duranlinar.es/2010/09/paginacion-de-listados/</link>
		<comments>http://gustavo.duranlinar.es/2010/09/paginacion-de-listados/#comments</comments>
		<pubDate>Thu, 30 Sep 2010 09:56:26 +0000</pubDate>
		<dc:creator>gu</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[paginacion]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://gustavo.duranlinar.es/?p=94</guid>
		<description><![CDATA[<style type="text/css">
#leftcontainerBox {
	float:left;
	position: fixed;
	top: 60%;
	left: 70px;
}
#leftcontainerBox .buttons {
	float:left;
	clear:both;
	margin:4px 4px 4px 4px;
	padding-bottom:2px;
}
#bottomcontainerBox {
	width: 50%;
	padding-top: 1px;
}
#bottomcontainerBox .buttons {
	float: left;
	margin: 4px 4px 4px 4px;
}
</style>
En muchas ocasiones, ya sea por estética o por reducir tiempos de carga, es preciso mostrar un listado en varias páginas. Esto lo haremos mediante el uso de LIMIT en nuestra consulta. En MySQL, LIMIT puede tener 1 ó 2 argumentos numéricos. Para nuestras necesidades usaremos los 2: el primero determina el nº de registro [...]]]></description>
			<content:encoded><![CDATA[<style type="text/css">
#leftcontainerBox {
	float:left;
	position: fixed;
	top: 60%;
	left: 70px;
}
#leftcontainerBox .buttons {
	float:left;
	clear:both;
	margin:4px 4px 4px 4px;
	padding-bottom:2px;
}
#bottomcontainerBox {
	width: 50%;
	padding-top: 1px;
}
#bottomcontainerBox .buttons {
	float: left;
	margin: 4px 4px 4px 4px;
}
</style>
<p>En muchas ocasiones, ya sea por estética o por reducir tiempos de carga, es preciso mostrar un listado en varias páginas. Esto lo haremos mediante el uso de LIMIT en nuestra consulta. En MySQL, LIMIT puede tener 1 ó 2 argumentos numéricos. Para nuestras necesidades usaremos los 2: el primero determina el nº de registro inicial y el 2º la cantidad de registros a mostrar.</p>
<p>Para el ejemplo imaginemos que tenemos una tabla <em>productos</em> y que el listado lo realizaremos por familia o por un criterio de búsqueda del usuario y para no extendernos mucho será simplemente una búsqueda por nombre o descripción del artículo.<br />
A la hora de generar los enlaces a las distintas páginas debemos mantener los criterios de la búsqueda, para ello usaremos 2 campos GET: <em>familia</em> para búsqueda por familia y <em>desc</em> para búsqueda por descripción; de forma que los enlaces quedarán algo parecido a <em>./catalog.php?family=4&amp;desc=pedal+freno</em>.</p>
<p>Pues ¡pasemos a la acción! Definamos los pasos a realizar:</p>
<ol>
<li>validar los criterios de búsqueda</li>
<li>construir la consulta</li>
<li>calcular el total de artículos</li>
<li>generar el listado de páginas</li>
<li>mostrar la página de resultados</li>
</ol>
<p>Los 2 primeros pasos los vamos a mezclar.</p>
<pre class="brush: php; title: ; notranslate">
$familia = 0;
$where = $busqueda = &quot;&quot;;
if (isset($_GET['familia']))
    { // Se trata de un valor numérico para búsqueda de un identificador
    $familia = intval($_GET['familia']);
    if ($familia) // Esta 2ª comprobación es para que no busque por la familia 0, considerando que se trata de un campo clave autonumérico.
        $where .= &quot; AND familia_id=$familia&quot;;
    }

if (isset($_GET['desc']))
    { // Es un valor introducido por el visitante, NUNCA te fies de lo que envía el cliente
    $busqueda = mysql_real_escape_string($_GET['desc'])
    $where .= &quot; AND (nombre LIKE '%$busqueda%' OR descripcion LIKE '%$busqueda%')&quot;;
    }

$pag = 1;
if (isset($_GET['pag'])) // página actual
    $pag = intval($_GET['pag']);
</pre>
<p>En la búsqueda por descripción podríamos tener un campo adicional tipo <em>checkbox</em> para indicar si queremos buscar en la descripción del artículo además de en el nombre de este.</p>
<p>Definidos los criterios, calculamos la cantidad total de resultados, tal que así:</p>
<pre class="brush: php; title: ; notranslate">
$total = mysql_fetch_row(mysql_query(&quot;SELECT COUNT(*) FROM articulos WHERE activo=1 $where&quot;));
$total = $total[0];
</pre>
<p>Llegado a este punto si no hay resultados (<em>$total == 0</em> o símplemente <em>!$total</em>) podemos parar y ahorramos tiempo ejecutando el resto.</p>
<p>Nótese  que podría haber hecho una consulta de un campo (o de todos) y luego utilizar la función mysql_num_rows(). Sin embargo usar COUNT en la consulta es mucho más rápido, además de darle menos trabajo a nuestro servidor.</p>
<p>Pues ahora que tenemos lo básico, generamos los enlaces para la navegación por páginas. </p>
<pre class="brush: php; title: ; notranslate">
// Definimos cuantos resultados por página (rpp) queremos. Nuevamente esto podría ser una opción del formulario de búsqueda.
define(&quot;_RPP&quot;, 10);
function paginas($total=0, $familia=0, $criterio=&quot;&quot;, $actual=1)
	{
	$OUT = &quot;&quot;;
	// Calculamos el total de páginas
	$paginas = ceil($total/_RPP);
	for ($p=1, $p&lt;$paginas+1, $p+=1)
		{
		if ($p != $actual)
			$OUT .= &quot;\t&lt;li&gt;&lt;a href=\&quot;./catalogo.php?familia=$familia&amp;amp;desc=&quot;.htmlentities($criterio).&quot;&amp;amp;pag=$p\&quot;&gt;$p&lt;/a&gt;&lt;/li&gt;\n&quot;;
		else
			$OUT .= &quot;\t&lt;li&gt;$p&lt;/li&gt;\n&quot;;
		}

	 // Definos los enlaces para &quot;pagina anterior&quot; y &quot;página siguiente&quot;
	 $anterior = &quot;\t&lt;li&gt;&amp;laquo;&lt;/li&gt;\n&quot;;
	 $siguiente = &quot;\t&lt;li&gt;&amp;raquo;&lt;/li&gt;\n&quot;;

	 if ($actual != 1)
		 $anterior = &quot;\t&lt;li&gt;&lt;a href=\&quot;./catalogo.php?familia=$familia&amp;amp;desc=&quot;.htmlentities($criterio).&quot;&amp;amp;pag=&quot;.($actual-1).&quot;\&quot; title=\&quot;ir a la p&amp;aacute;gina anterior\&quot;&gt;&amp;laquo;&lt;/a&gt;&lt;/li&gt;\n&quot;;
	 if ($actual != $paginas)
		 $siguiente = &quot;\t&lt;li&gt;&lt;a href=\&quot;./catalogo.php?familia=$familia&amp;amp;desc=&quot;.htmlentities($criterio).&quot;&amp;amp;pag=&quot;.($actual+1).&quot;\&quot; title=\&quot;ir a la p&amp;aacute;gina siguiente\&quot;&gt;&amp;raquo;&lt;/a&gt;&lt;/li&gt;\n&quot;;

	// Es cuestión de gustos, a mi me gusta usar listas para este tipo de cosas y aplicarle un estilo
	$OUT = &quot;&lt;ul class=\&quot;paginas\&quot;&gt;\n&quot;
	. $anterior
	. $OUT
	. $siguiente
	. &quot;&lt;/ul&gt;\n&quot;

	return $OUT;
	}
</pre>
<p>El estilo de la lista de páginas podría ser algo así:</p>
<pre class="brush: css; title: ; notranslate">
ul.paginas { clear:both; }
ul.paginas &gt; li { float:left; padding:2px 4px 2px; }
ul.paginas &gt; li &gt; a { font-weight:bold; text-decoration:none; }
</pre>
<p>Pues ahora la traca final: hacer la consulta y mostrar los artículos.</p>
<pre class="brush: php; title: ; notranslate">
// Calcular registro inicial (nº de página actual multiplicado por los registros por página)
$registro = ($pag - 1) * _RPP;

// Construir consulta SQL
$sql = &quot;SELECT a.*, f.nombre&quot;
. &quot; FROM articulos a&quot;
. &quot; INNER JOIN familias f ON f.id=a.familia_id&quot;
. &quot; WHERE a.activo=1 &quot;. $where
. &quot; ORDER BY a.nombre&quot; // Esto podría ser otro criterio para la búsqueda
. &quot; LIMIT $registro, &quot;. _RPP;

// Realizar la consulta
$query = mysql_query($sql);
if (mysql_num_rows($query)
    {
    $BODY = &quot;&quot;;
    while ($a = mysql_fetch_array($query))
        {
        $BODY = &quot;&lt;div class=\&quot;articulo\&quot;&gt;\n&quot;
        . &quot;&lt;div&gt;Art&amp;iacute;culo: {$a['nombre']}&lt;/div&gt;\n&quot;
        . &quot;&lt;div&gt;Descripci&amp;oacute;n: {$a['descripcion']}&lt;/div&gt;\n&quot;
        . &quot;&lt;/div&gt;\n&quot;;
        }

    // Presentarlo todo
    echo paginas($total, $familia, $busqueda, $pag)
    . $BODY
    . paginas($total, $familia, $busqueda, $pag);
    }
</pre>
<p>Espero que el artículo sea interesante y útil! No dudes en criticarme en los comentarios <img src='http://gustavo.duranlinar.es/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' /><br />
Me tomé la libertad de darle formato a la salida, así como agregar tabulaciones y saltos de línea. Es una costumbre que tengo que facilita la revisión del código HTML generado.</p>
]]></content:encoded>
			<wfw:commentRss>http://gustavo.duranlinar.es/2010/09/paginacion-de-listados/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

