<?xml version="1.0" encoding="ISO-8859-1"?>
<rss version="2.0">
  <channel>
    <title>Blackout weblog</title>
    <link>http://blog.blackspiral.org</link>
    <description></description>
    <!-- optional tags -->
    <language>en-us</language>           <!-- valid langugae goes here -->
    <generator>Nucleus CMS v3.22</generator>
    <copyright>©</copyright>             <!-- Copyright notice -->
    <category>Weblog</category>
    <docs>http://backend.userland.com/rss</docs>
    <image>
      <url>http://blog.blackspiral.org/nucleus/nucleus2.gif</url>
      <title>Blackout weblog</title>
      <link>http://blog.blackspiral.org</link>
    </image>
    
<item>
 <title><![CDATA[Publicando archivos en la web desde Konqueror]]></title>
 <link>http://blog.blackspiral.org/index.php?itemid=28</link>
<description><![CDATA[Los que tenemos un servidor web a mano solemos aprovecharlo muchas veces para publicar archivos en él y compartirlos con otras personas de forma rápida y sencilla. La parte pesada del asunto es tener que andar haciendo un <i>scp</i> desde la consola de comandos, o usando <i>fish</i> en konqueror (y eso que <i>fish</i> es bien sencillito - para el que no sepa lo que es <i>fish</i>, que teclee <i>fish://usuario@servidorconaccesossh</i> en la barra de direcciones de su Konqueror). La idea es hacerlo aún más fácil. Pulsar con el botón derecho sobre un archivo (o archivos) y en las acciones asociadas disponer de una que nos permita subir los archivos a nuestro servidor web. Más fácil no puede ser.En primer lugar debemos tener acceso al servidor web mediante <i>ssh</i> y haberlo configurado para autenticarnos con clave pública. Para no repetirme ni hacer esto demasiado largo, <a href="http://blackspiral.org/docs/ssh.html">aquí</a> tenéis una explicación más extensa de cómo configurarlo todo.<br/><br/>

Ahora nos vamos a <i>~/.kde/share/apps/konqueror/servicemenus/</i> y creamos un archivo nuevo en el que especificaremos las acciones que hemos descrito. Por ejemplo:

<div class="code">
<h3>publicar.desktop</h3>
<pre class="bash"><span class="br0">&#91;</span>Desktop Entry<span class="br0">&#93;</span>
<span class="re2">Actions=</span>sendtmp;sendimg
<span class="re2">Encoding=</span>UTF8
<span class="re2">ServiceTypes=</span>all/all
X-KDE-<span class="re2">Submenu=</span>Publish on the web
X-KDE-Submenu<span class="br0">&#91;</span>es<span class="br0">&#93;</span>=Publicar en la web
&nbsp;
<span class="br0">&#91;</span>Desktop Action sendtmp<span class="br0">&#93;</span>
<span class="re2">Name=</span> Send to temp
Name<span class="br0">&#91;</span>es<span class="br0">&#93;</span>= Enviar a temporal
<span class="re2">Icon=</span> konqueror
<span class="re2">Exec=</span> scp -r %U usuario@servidor:/wwwroot/tmp/ ;
  kdialog --msgbox <span class="st0">"%U publicado correctamente"</span>
&nbsp;
<span class="br0">&#91;</span>Desktop Action sendimg<span class="br0">&#93;</span>
<span class="re2">Name=</span> Send to images
Name<span class="br0">&#91;</span>es<span class="br0">&#93;</span>= Enviar a imágenes
<span class="re2">Icon=</span> konqueror
<span class="re2">Exec=</span> scp -r %U usuario@servidor:/wwwroot/img/ ;
  kdialog --msgbox <span class="st0">"%U publicado correctamente"</span></pre></div>

La idea es bien sencilla. Con nuestro usuario habitual debemos tener permisos para copiar los archivos a los directorios del servidor web en los que queramos colgarlos. Añadiremos una opción por cada uno. Como podéis comprobar, utilizaremos el flag <i>-r</i> de <i>scp</i> siempre. Esto nos permitirá usar nuestro nuevo servicio también con directorios enteros. Finalmente, lanzamos un diálogo de KDE informando de que la copia del archivo o archivos ha terminado mediante el comando <i>kdialog</i>, una vez finalice <i>scp</i>.<br/><br/>

Por supuesto, este método sirve para cualquier servidor <i>ssh</i> al que tengamos acceso, y podemos añadir tantos servicios como servidores, a modo de <i>copiar a</i> pero en remoto. Basta editar el archivo o archivos <i>.desktop</i> en nuestro directorio de servicios, dejarlos a nuestro gusto, y disfrutarlos ;-)]]></description>
 <category>linux</category>
<comments>http://blog.blackspiral.org/index.php?itemid=28</comments>
 <pubDate>Thu, 5 Oct 2006 20:08:33 +0200</pubDate>
</item><item>
 <title><![CDATA[Guitar Pro 5 en Linux]]></title>
 <link>http://blog.blackspiral.org/index.php?itemid=27</link>
<description><![CDATA[Guitar Pro es uno de esos programas de Windows que a día de hoy siguen siendo insustituibles. Existen algunas alternativas libres, como <a href="http://kguitar.sourceforge.net/">kguitar</a> o <a href="http://dguitar.sourceforge.net/">dguitar</a>, pero generalmente están muy verdes y no sirven más que para un apaño. Si quieres ver/editar/escuchar partituras de Guitar Pro, que por otra parte es el formato más extendido, no te queda más remedio que arrancar una máquina con Windows. Hasta ahora.<br/><br/>

Vamos a instalar en un momento y sin complicaciones este programa en Linux, utilizando para ello <a href="http://www.winehq.org">Wine</a> para emularlo. El <i>RSE</i> (Realistic Sound Engine) de la versión 5 no funcionará del todo bien (cortes de sonido, desajustes en el tiempo...), pero la versión original en Windows tampoco es que vaya fina, y sigue siendo mejor que lo que ofrecen otros. Además, el soporte MIDI si funcionará perfectamente.Las instrucciones a continuación son válidas para Gentoo Linux, aunque la base es la misma para cualquier distribución. Para empezar instalamos los prerrequisitos necesarios. Necesitaremos ALSA, Wine y Timidity.

<div class="code">
<h3>Instalando paquetes</h3>
<pre class="bash">emerge -av alsa-lib wine timidity++</pre></div>

Muy importante asegurarse de que compilamos tanto Wine como Timidity con soporte para ALSA. Configuramos Wine en primera instancia. Para ello arrancamos <i>winecfg</i> y en la versión del sistema operativo seleccionamos <b>Windows XP, NT o 98</b>. Con el 2000 que viene seleccionado por defecto Guitar Pro se colgará nada más arrancar. En la pestaña Audio marcamos la casilla <b>ALSA Driver</b> para seleccionar este controlador, y en el desplegable de <i>Aceleración Hardware</i> seleccionamos <b>Emulation</b>. Esto último mejorará levemente la calidad de reproducción cuando usemos <i>RSE</i>.<br/><br/>

Una vez configurado Wine, hacemos lo propio con Timidity. Para empezar descargamos <a href="http://www.hammersound.net/cgi-bin/soundlink.pl?action=view_download_page;ID=699;SoundFont_Location_Selected=Download%20It;SoundFont_Filename_Selected=Download%20It">la librería de sonidos Fluid</a> y la instalamos. Simplemente la descargamos a nuestro directorio ~/.timidity/current y la descomprimimos. Para descomprimir los dos archivos sfArk debemos utilizar una utilidad llamada <a href="http://www.melodymachine.com/files/sfarkxtc_lx86.tar.gz"><b>sfarkxtc</b></a>. La descargamos y utilizamos para descomprimir dichos archivos, lo cual nos deja sendos archivos con extensión <b>.SF2</b>.<br/><br/>

Editamos el fichero de configuración de timidity, añadiendo los archivos <i>soundfont</i> mediante la directiva del mismo nombre:

<div class="code">
<h3>timidity.cfg</h3>
<pre class="bash"><span class="co1"># Instrument configuration file for timidity</span>
<span class="co1"># $Id: timidity.cfg,v 1.5 2004/08/07 15:59:19 hmh Exp $</span>
&nbsp;
<span class="co1"># You can change just about every option in TiMidity++ using</span>
<span class="co1"># This config file. Please refer to the timidity.cfg(5) manpage</span>
<span class="co1"># for more details</span>
&nbsp;
<span class="co1">## If you have a slow CPU, uncomment these:</span>
<span class="co1">#opt EFresamp=d         #disable resampling</span>
<span class="co1">#opt EFvlpf=d           #disable VLPF</span>
<span class="co1">#opt EFreverb=d         #disable reverb</span>
<span class="co1">#opt EFchorus=d         #disable chorus</span>
<span class="co1">#opt EFdelay=d          #disable delay</span>
<span class="co1">#opt no-antialias       #disable sample anti-aliasing</span>
<span class="co1">#opt EWPVSETOZ          #disable all Midi Controls</span>
<span class="co1">#opt p32a               #default to 32 voices with auto reduction</span>
<span class="co1">#opt s32kHz             #default sample frequency to 32kHz</span>
<span class="co1">#opt fast-decay         #fast decay notes</span>
&nbsp;
<span class="co1"># By default, try to use the instrument patches from freepats:</span>
&nbsp;
<span class="co1">#source /etc/timidity/freepats.cfg</span>
soundfont <span class="st0">"~/.timidity/current/FluidR3GM.SF2"</span>
soundfont <span class="st0">"~/.timidity/current/FluidR3GS.SF2"</span></pre></div>

Y lo arrancamos:

<div class="code">
<h3>Ejecutando Timidity</h3>
<pre class="bash">timidity -iA -B2,<span class="nu0">8</span> -Os -<span class="re2">EFreverb=</span><span class="nu0">0</span></pre></div>

Cuando queramos pararlo, simplemente pulsamos CTRL+C. Si queremos tener Timidity ejecutando como demonio del sistema, debemos crear el directorio <i>/usr/share/timidity/current</i>, y copiar allí tanto los archivos <i>SF2</i> como el <i>timidity.cfg</i>. Especificaremos los parámetros de entrada para el demonio:

<div class="code">
<h3>/etc/conf.d/timidity.conf</h3>
<pre class="bash"><span class="co1"># TIMIDITY_OPTS</span>
<span class="co1"># Command line arguements to be passed to timidity. -iA is always used</span>
<span class="co1"># Common options:</span>
<span class="co1"># -Os : Output to ALSA pcm device</span>
<span class="co1"># -Oe : Output to esd</span>
<span class="co1"># -On : Output to NAS</span>
<span class="co1">#</span>
<span class="co1"># -B&lt;n&gt;,&lt;m&gt; :  Set number of buffer fragments(n), and buffer size(2^m)</span>
<span class="co1">#</span>
<span class="co1"># -EFreverb=0         : Disable MIDI reverb effect control</span>
<span class="co1"># -EFreverb=1[,level] : Enable MIDI reverb effect control</span>
<span class="co1">#                       `level' is optional to specify reverb level [0..127]</span>
<span class="co1">#                       This effect is only available in stereo</span>
<span class="co1">#                       (default)</span>
<span class="co1"># -EFreverb=2         : Global reverb effect</span>
&nbsp;
<span class="re2">TIMIDITY_OPTS=</span><span class="st0">"-B2,8 -Os -EFreverb=0 -s 44100"</span>
&nbsp;
<span class="co1"># TIMIDITY_PCM_NAME</span>
<span class="co1"># This option can be used to choose an alternate ALSA pcm device.  This will</span>
<span class="co1"># be most useful for users of the dmix alsa plugin or those with multiple</span>
<span class="co1"># cards.  If you don't know what this is, chances are you want the default.</span>
&nbsp;
<span class="co1">#TIMIDITY_PCM_NAME=&quot;default&quot; </span></pre></div>

Y finalmente lo arrancaremos y lo añadiremos al nivel de ejecución por defecto:

<div class="code">
<h3>Timidity como demonio del sistema</h3>
<pre class="bash">/etc/init.d/timidity start
rc-update add timidity default</pre></div>

Hecho esto, arrancamos la instalación de Guitar Pro mediante su instalador:

<div class="code">
<h3>Instalando Guitar Pro</h3>
<pre class="bash">wine setup.exe</pre></div>

Una vez terminada la instalación y registrado el producto, lo arrancamos, asegurándonos de haber ejecutado Timidity previamente. El directorio de trabajo debe ser aquel en el que está instalado Guitar Pro, por lo que para ejecutarlo haremos lo siguiente:

<div class="code">
<h3>Ejecutando Guitar Pro</h3>
<pre class="bash"><span class="kw3">cd</span> ~/.wine/drive_c/Archivos\ de\ programa/Guitar\ Pro\ <span class="nu0">5</span>
wine GP5.exe</pre></div>

Con el programa iniciado, en <i>Opciones -> Configuración MIDI...</i> seleccionamos Timidity como puerto de dispositivo para la salida MIDI, y <i>General MIDI</i> en el juego de instrumentos. Hecho esto, ya tenemos Guitar Pro instalado y listo para utilizarse. Si vamos a utilizar el <i>RSE</i> será conveniente jugar con las opciones de sonido tanto de Guitar Pro como de Wine para obtener la mejor calidad posible en nuestra máquina.<br/><br/>

En caso de cualquier problema, puede ser útil echarle un ojo a la <a href="http://appdb.winehq.org/appview.php?iAppId=246">página de soporte de Guitar Pro de Wine</a> y a los comentarios de la versión específica que estamos instalando, en busca de ayuda.]]></description>
 <category>linux</category>
<comments>http://blog.blackspiral.org/index.php?itemid=27</comments>
 <pubDate>Sun, 1 Oct 2006 00:15:35 +0200</pubDate>
</item><item>
 <title><![CDATA[Monkey's audio]]></title>
 <link>http://blog.blackspiral.org/index.php?itemid=26</link>
<description><![CDATA[Últimamente se está extendiendo mucho la costumbre de grabar CD's de audio en el formato de esta aplicación, <a href="http://www.monkeysaudio.com/">Monkey's audio</a>, que promete supuestamente compresión sin pérdida de la calidad del sonido. Los CD's en este formato se presentan en forma de imagen con dos archivos, un típico <i>CDImage.ape</i> que contiene el audio, y <i>CDImage.ape.cue</i> que contiene toda la información del disco (hasta la duración de cada una de las pistas). Por desgracia no hay reproductores en Linux que soporten este formato (aunque hay un par de plugins para <a href="http://sourceforge.net/project/showfiles.php?group_id=123827">xmms y beep media player</a>).Lo mejor en este caso es convertirlo a un formato como <b>mp3</b>, soportado en cualquier parte. Para eso nos bajamos e instalamos el <a href="http://sourceforge.net/project/showfiles.php?group_id=123827">port de mac</a> (<i>monkey's audio codec</i>) para Linux y lo instalamos. Los usuarios de gentoo podrán encontrar <a href="http://bugs.gentoo.org/show_bug.cgi?id=94477">un ebuild listo para instalar</a>.

Una vez instalado, lo convertimos a wav:
<div class="code">
<h3>Convertir de ape a wav</h3>
<pre class="bash">mac CDImage.ape CDImage.wav -d</pre></div>

Una vez en formato <b>wav</b>, lo convertimos directamente a <b>mp3</b>:
<div class="code">
<h3>Convertir de wav a mp3</h3>
<pre class="bash">lame --preset standard CDImage.wav</pre></div>

Y finalmente utilizamos <i>mp3split</i> para partir en pistas el <b>mp3</b> resultante y mantener la información de cada una (título de la pista, artista, álbum, etc):
<div class="code">
<h3>Partir el mp3</h3>
<pre class="bash">mp3splt CDImage.wav.mp3 -c CDImage.ape.cue</pre></div>

Y si el formato de los nombres de archivo o alguno de los datos <i>id3tag</i> falta o es incorrecto, nada mejor que <a href="http://easytag.sourceforge.net/">easytag</a> para editar todos los archivos a la vez ;-)
<br/><br/>
<i>Et voila!</i>]]></description>
 <category>linux</category>
<comments>http://blog.blackspiral.org/index.php?itemid=26</comments>
 <pubDate>Sat, 5 Aug 2006 03:00:15 +0200</pubDate>
</item><item>
 <title><![CDATA[Teclados multimedia en KDE]]></title>
 <link>http://blog.blackspiral.org/index.php?itemid=25</link>
<description><![CDATA[La mayoría de teclados que existen hoy día en el mercado incluyen un conjunto adicional de teclas para multimedia, por lo general, dedicadas a la navegación y al audio/video. KDE soporta por sí mismo muchos esquemas de teclado que incluyen este tipo de extensiones, pero no proporciona una forma sencilla de asignar una función a cada tecla. Aquí es donde entra en juego <a href="http://lineak.sourceforge.net/">lineak</a>, un pequeño demonio que monitoriza los botones especiales del teclado  y asocia acciones a cada uno. Vamos a ver cómo sacarle partido integrándolo con KDE.Lo primero que haremos es instalar el demonio y un conjunto de plugins que nos serán de utilidad:<br/><br/>
<div class="code">
<h3>Instalando lineakd y plugins</h3>
<pre class="bash">emerge lineakd lineak-defaultplugin lineak-kdeplugins</pre></div>
Ejecutamos el demonio con la opción <b>-l</b> para ver una lista de todos los teclados soportados, y apuntamos el código que se corresponda con nuestro teclado. Por ejemplo, para un <i>Logitech Cordless Desktop Pro</i> el código es <i>LTCDP</i>. Procedemos a generar un archivo de configuración que luego modificaremos para nuestro esquema de teclado:<br/><br/>
<div class="code">
<h3>Generando un archivo de configuración</h3>
<pre class="bash">lineakd -c LTCDP</pre></div>
Editamos el archivo que acabamos de crear para configurarlo. La primera sección por lo general no hará falta tocarla. En mi caso he modificado el dispositivo de cdrom para que apunte a <i>/dev/dvdrom</i>. En el segundo bloque cada línea se corresponde con un botón en nuestro esquema de teclado, de forma que podemos asignar comandos o acciones a cada uno. En este caso usamos una combinación de comandos para el navegador (opera) con <b>macros</b> predefinidas de los plugins que hemos instalado. Podemos ver más en detalle las <a href="http://lineak.sourceforge.net/index.php?nav=showdoc&docid=lineak_defaultplugin_README&doctitle=Lineak%20Default%20Plugins">opciones del defaultplugin</a> y las <a href="http://lineak.sourceforge.net/index.php?nav=showdoc&docid=lineak_kdeplugins_README&doctitle=lineakd%20README">opciones de los plugins de KDE</a> en la <a href="http://lineak.sourceforge.net/index.php?nav=docs">documentación de lineak</a>.<br/><br/>
<div class="code">
<h3>~/.lineak/lineakd.conf</h3>
<pre class="bash">CdromDevice = /dev/dvdrom
Display_align = center
Display_color = 0aff00
Display_font = -adobe-helvetica-bold-r-normal-*-*-<span class="nu0">240</span>-*-*-p-*-*-*
Display_hoffset = <span class="nu0">0</span>
Display_plugin = internal
Display_pos = bottom
Display_soffset = <span class="nu0">1</span>
Display_timeout = <span class="nu0">3</span>
Display_voffset = <span class="nu0">50</span>
KeyboardType = LTCDP
MixerDevice = /dev/mixer
Screensaver =
conffilename = /home/icarus/.lineak/lineakd.conf
keystate_capslock =
keystate_numlock =
keystate_scrolllock =
&nbsp;
Go = opera -newpage
Internet = KMENU
Mail = opera -remote <span class="st0">'openComposer()'</span>
Mute = KMIX_MUTE
Next = <span class="st0">"EAK_MEDIADETECT(NEXT)"</span>
Play|Pause = <span class="st0">"EAK_MEDIADETECT(PLAYPAUSE)"</span>
Previous = <span class="st0">"EAK_MEDIADETECT(PREVIOUS)"</span>
Search = opera -newpage g
Sleep = KDE_LOCK_DESKTOP
Stop = <span class="st0">"EAK_MEDIADETECT(STOP)"</span>
VendorHome =
VolumeDown = KMIX_VOLDOWN
VolumeUp = KMIX_VOLUP</pre></div>
Algunas de las opciones utilizan la macro <i>EAK_MEDIADETECT()</i>, que viene incluida en el <i>defaultplugin</i>. Esta macro permite que la acción asociada a una tecla varíe dependiendo de los programas en ejecución. Es muy útil cuando utilizamos, por ejemplo, varios reproductores multimedia, y queremos que las teclas funcionen igualmente en todos. Simplemente creamos un archivo llamado <i>media-detect.conf</i> en el directorio <i>~/.lineak/</i> y especificamos las aplicaciones, su precedencia, y las acciones asociadas. Por ejemplo, si queremos asociar las teclas multimedia con KsCD y amaroK:<br/><br/>
<div class="code">
<h3>~/.lineak/media-detect.conf</h3>
<pre class="bash"><span class="br0">&#91;</span>KSCD<span class="br0">&#93;</span>
NAME = Reproductor de CDs
PROGRAM = kscd
PLAY = CDPlayer play
STOP = CDPlayer stop
PAUSE =
PLAYPAUSE =
NEXT = CDPlayer next
PREVIOUS = CDPlayer previous
TYPE = dcop
PRIORITY = <span class="nu0">1</span>
<span class="br0">&#91;</span>END<span class="br0">&#93;</span>
&nbsp;
<span class="br0">&#91;</span>AMAROK<span class="br0">&#93;</span>
NAME = Amarok Media Player
PROGRAM =amarok
PLAY = AMAROK_PLAY
STOP = AMAROK_STOP
PAUSE = AMAROK_PAUSE
PLAYPAUSE = AMAROK_PLAYPAUSE
NEXT = AMAROK_FORWARD
PREVIOUS = &lt;b&gt;AMAROK_BACK
TYPE = macro
PRIORITY = <span class="nu0">2</span>
<span class="br0">&#91;</span>END<span class="br0">&#93;</span></pre></div>
Algunas cosas a tener en cuenta:<br/><br/>
<ul><li>La aplicación con prioridad 1 será la primera en comprobarse, y el resto incrementalmente con menor prioridad.</li>
<li>El <b>tipo</b> varía dependiendo de la forma de interactuar con el programa. Algunos como amaroK o JuK traen macros predefinidas. Para estos programas usaremos el tipo <b>macro</b> y especificaremos las macros tal cual para cada botón. Para programas a los que debemos acceder mediante línea de comandos, como XMMS, utilizaremos el tipo <b>program</b>, y las acciones serán los parámetros a pasarle al programa. Para otras aplicaciones de KDE que no tengan macros podemos utilizar DCOP para acceder a ellas mediante el tipo <b>dcop</b>. Hablaremos más de ello más adelante.</li>
<li>El valor <i>program</i> tiene distintos significados dependiendo del tipo de aplicación. Para aplicaciones de tipo <b>program</b> especificará el nombre del comando a ejecutar, mientras que para aplicaciones DCOP especificará el nombre con el que se registra la aplicación en DCOP.</li></ul>
El uso de DCOP nos da una gran flexibilidad a la hora de asociar acciones a un botón, ya que nos permite ejecutar cualquier acción registrada por una aplicación. Mediante el comando <i>dcop</i> obtendremos una lista de las aplicaciones registradas actualmente. Con <i>dcop aplicación</i> veremos la lista de funciones agrupadas de la aplicación, y con <i>dcop aplicación grupo</i> podemos ver las funciones concretas. Por ejemplo, en amaroK las funciones de reproducción se encuentran en el grupo <i>player</i>:<br/><br/>
<div class="code">
<h3>Consultando las funciones de amaroK</h3>
<pre class="bash">% dcop amarok player
<span class="br0">&#91;</span>...<span class="br0">&#93;</span>
void configEqualizer<span class="br0">&#40;</span><span class="br0">&#41;</span>
void enableDynamicMode<span class="br0">&#40;</span>bool <span class="kw3">enable</span><span class="br0">&#41;</span>
void enableOSD<span class="br0">&#40;</span>bool <span class="kw3">enable</span><span class="br0">&#41;</span>
void enableRandomMode<span class="br0">&#40;</span>bool <span class="kw3">enable</span><span class="br0">&#41;</span>
void enableRepeatPlaylist<span class="br0">&#40;</span>bool <span class="kw3">enable</span><span class="br0">&#41;</span>
void enableRepeatTrack<span class="br0">&#40;</span>bool <span class="kw3">enable</span><span class="br0">&#41;</span>
void mediaDeviceMount<span class="br0">&#40;</span><span class="br0">&#41;</span>
void mediaDeviceUmount<span class="br0">&#40;</span><span class="br0">&#41;</span>
void mute<span class="br0">&#40;</span><span class="br0">&#41;</span>
void next<span class="br0">&#40;</span><span class="br0">&#41;</span>
void pause<span class="br0">&#40;</span><span class="br0">&#41;</span>
void play<span class="br0">&#40;</span><span class="br0">&#41;</span>
void playPause<span class="br0">&#40;</span><span class="br0">&#41;</span>
void prev<span class="br0">&#40;</span><span class="br0">&#41;</span>
<span class="br0">&#91;</span>...<span class="br0">&#93;</span>
void setVolume<span class="br0">&#40;</span>int volume<span class="br0">&#41;</span>
void showBrowser<span class="br0">&#40;</span>QString browser<span class="br0">&#41;</span>
void showOSD<span class="br0">&#40;</span><span class="br0">&#41;</span>
void stop<span class="br0">&#40;</span><span class="br0">&#41;</span>
<span class="br0">&#91;</span>...<span class="br0">&#93;</span>
&lt;b&gt;void volumeDown<span class="br0">&#40;</span><span class="br0">&#41;</span>
void volumeUp<span class="br0">&#40;</span><span class="br0">&#41;</span>
<span class="br0">&#91;</span>...<span class="br0">&#93;</span></pre></div>
Una vez tengamos todo configurado a nuestro gusto, basta con arrancar el demonio y empezar a disfrutar de nuestro redescubierto teclado:<br/><br/>
<div class="code">
<h3>Si todo va bien...</h3>
<pre class="bash">lineakd -v</pre></div>]]></description>
 <category>linux</category>
<comments>http://blog.blackspiral.org/index.php?itemid=25</comments>
 <pubDate>Sun, 26 Mar 2006 19:01:13 +0200</pubDate>
</item><item>
 <title><![CDATA[Pantallas "multi-táctiles"]]></title>
 <link>http://blog.blackspiral.org/index.php?itemid=23</link>
<description><![CDATA[Creo que no dejaré de sorprenderme viendo los avances que hay día a día en dispositivos de interfaz de usuario. <a href="http://www.signal11.org/">Álvaro</a> me ha pasado hoy un video realmente increíble sobre lo que sus propios autores definen como una <a href="http://mrl.nyu.edu/~jhan/ftirtouch/"><i>superficie gráfica interactiva</i></a> que es <i>bimanual</i>, <i>multipunto</i> y <i>multiusuario</i>. Es decir, una especie de pantalla táctil en la que se pueden usar ambas manos, todos los dedos, y varias personas a la vez. No perdáis detalle al video en la continuación de esta entrada.<object width="425" height="350"><param name="movie" value="http://www.youtube.com/p.swf?video_id=zp-y3ZNaCqs"></param><embed src="http://www.youtube.com/p.swf?video_id=zp-y3ZNaCqs" type="application/x-shockwave-flash" width="425" height="350"></embed></object>]]></description>
 <category>tecnología</category>
<comments>http://blog.blackspiral.org/index.php?itemid=23</comments>
 <pubDate>Sun, 12 Feb 2006 18:49:57 +0100</pubDate>
</item><item>
 <title><![CDATA[Lectores de e-books]]></title>
 <link>http://blog.blackspiral.org/index.php?itemid=22</link>
<description><![CDATA[Parece que por fin se ha encontrado una aplicación para el <a href="http://www.eink.com/">papel electrónico</a> y diversos fabricantes, entre ellos Sony, se han lanzado ha fabricar aparatos <a href="http://products.sel.sony.com/pa/prs/index.html?DCMP=reader&HQS=showcase_reader">lectores de libros electrónicos</a>. Suelen soportar textos en pdf, html, texto plano u otros formatos propios, y utilizan la tecnología del papel electrónico para ofrecer una calidad de imagen monocromática. Esto, unido a la capacidad de reproducir música y a la capacidad de interconexión que presentan (tarjetas SD, conexiones Ethernet e incluso inalámbricas), hace verdaderamente interesantes estos dispositivos. Algunos como el <a href="http://www.jinke.com.cn/compagesql/English/embedpro/prodetail.asp?id=20">Jinke</a> incluso utilizan Linux como sistema operativo.<br/><br/>
Lo malo, como siempre, el precio. Para el Jinke los precios varían entre los $299 y los $349. Otros como <a href="http://www.irextechnologies.com/shop/products/iliad.htm">iLiad</a> de <a href="http://www.irextechnologies.com/">iRex</a> o el propio PRS-500 de Sony ni siquiera están a la venta, al menos hasta esta primavera.]]></description>
 <category>tecnología</category>
<comments>http://blog.blackspiral.org/index.php?itemid=22</comments>
 <pubDate>Sat, 11 Feb 2006 20:25:42 +0100</pubDate>
</item><item>
 <title><![CDATA[Organizando enlaces]]></title>
 <link>http://blog.blackspiral.org/index.php?itemid=21</link>
<description><![CDATA[Cuando utilizas varios ordenadores de forma habitual se hace un poco complicado mantener una lista de favoritos y enlaces. Ya que el procedimiento habitual consiste en guardarlos en el propio navegador, eso hace que sólo puedas consultar la lista estando en ese ordenador concreto, y por tanto pierde toda su utilidad.<br/><br/>
La idea es buscar una forma sencilla de guardar una lista de favoritos que pueda ser consultada desde cualquier sitio. Lo que haremos será utilizar el correo electrónico para almacenarlos y organizarlos, y la web para publicarlos y así poder consultarlos desde cualquier parte.Partimos de la base de que tenemos un servicio de correo que soporte IMAP en el que podamos añadir nuevas cuentas o añadir carpetas a las ya existentes, y un servidor web que soporte PHP.<br/><br/>
Para empezar, creamos una cuenta a la que enviar nuestros favoritos por correo, y dentro de ella carpetas IMAP en las que organizaremos nuestros favoritos según categorías. Por ejemplo, supongamos que queremos guardar enlaces a documentos con una pequeña sinopsis de cada uno. Nos creamos por tanto una carpeta <i>docs</i>, y configuramos un filtro (en este caso de exim) para que todos los correos que comiencen por <i>[doc]</i> sean almacenados en esta carpeta:<br/><br/>
<div class="code">
<h3>Filtrando el correo</h3>
<pre class="bash"><span class="kw1">if</span> <span class="re1">$header_subject</span> contains <span class="st0">"[doc]"</span>
<span class="kw1">then</span>
  save /home/favs/.maildir/.docs/
  finish
endif</pre></div>
Repetimos este paso con tantas categorías como queramos tener. Enviamos varios correos de prueba que tengan en el asunto la cadena <i>[doc]</i> para verificar que todo funciona correctamente. Una vez listo, hacemos un pequeño script PHP que hará el resto. Por ejemplo, para listar el contenido de la carpeta de documentos:<br/><br/>
<div class="code">
<h3>favoritos.php</h3>
<pre class="php""><span class="kw2">&lt;?php</span>
  <span class="kw2">function</span> parseSubject<span class="br0">&#40;</span><span class="re0">$s</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
    <span class="re0">$s</span> = imap_mime_header_decode<span class="br0">&#40;</span><span class="re0">$s</span><span class="br0">&#41;</span>;
&nbsp;
    <span class="coMULTI">/* una vez obtenido y decodificado el asunto,
        unimos los resultados de la decodificacion */</span>
    <span class="kw1">foreach</span> <span class="br0">&#40;</span><span class="re0">$s</span> <span class="kw1">as</span> <span class="re0">$key</span> =&gt; <span class="re0">$part</span><span class="br0">&#41;</span>
      <span class="re0">$subject</span> .= <span class="re0">$part</span>-&gt;<span class="me1">text</span>;
&nbsp;
    <span class="co1">// eliminamos la cabecera del mensaje</span>
    <span class="re0">$subject</span> = imap_utf8<span class="br0">&#40;</span><span class="re0">$subject</span><span class="br0">&#41;</span>;
    <span class="re0">$subject</span> = <a href="http://www.php.net/ereg_replace"><span class="kw3">ereg_replace</span></a><span class="br0">&#40;</span><span class="st0">"^ *<span class="es0">\[</span>doc<span class="es0">\]</span> *"</span>,<span class="st0">""</span>,<span class="re0">$subject</span><span class="br0">&#41;</span>;
&nbsp;
    <span class="kw1">return</span> <span class="re0">$subject</span>;
  <span class="br0">&#125;</span>
&nbsp;
  <span class="kw2">function</span> parseMessageId<span class="br0">&#40;</span><span class="re0">$s</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
    <span class="coMULTI">/* obtenemos el id del mensaje y nos
        quedamos con la parte variable */</span>
    <span class="re0">$message_id</span> = <a href="http://www.php.net/ereg_replace"><span class="kw3">ereg_replace</span></a><span class="br0">&#40;</span><span class="st0">"^ *&lt;op<span class="es0">\.</span>"</span>,<span class="st0">""</span>,<span class="re0">$s</span><span class="br0">&#41;</span>;
    <span class="re0">$message_id</span> = <a href="http://www.php.net/ereg_replace"><span class="kw3">ereg_replace</span></a><span class="br0">&#40;</span><span class="st0">"@localhost&gt; *"</span>,<span class="st0">""</span>,<span class="re0">$message_id</span><span class="br0">&#41;</span>;
&nbsp;
    <span class="kw1">return</span> <span class="re0">$message_id</span>;
  <span class="br0">&#125;</span>
&nbsp;
  <span class="coMULTI">/* conectamos al directorio IMAP en modo
      solo lectura y sin validar el certificado */</span>
   <span class="re0">$mbox</span> = imap_open<span class="br0">&#40;</span><span class="st0">"{localhost:143/imap/tls/novalidate-cert}INBOX.docs"</span>,
                    <span class="st0">"favs"</span>,<span class="st0">"pass"</span>,OP_READONLY<span class="br0">&#41;</span>;
&nbsp;
  <span class="kw1">if</span> <span class="br0">&#40;</span>!<span class="re0">$mbox</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
  <span class="co1">// no hemos podido conectar</span>
    <a href="http://www.php.net/echo"><span class="kw3">echo</span></a> <span class="st0">"       &lt;h3&gt;Error&lt;/h3&gt;"</span>;
    <a href="http://www.php.net/echo"><span class="kw3">echo</span></a> <span class="st0">"&lt;p&gt;"</span>.imap_last_error<span class="br0">&#40;</span><span class="br0">&#41;</span>.<span class="st0">"&lt;/p&gt;"</span>;
&nbsp;
  <span class="br0">&#125;</span> <span class="kw1">else</span> <span class="br0">&#123;</span>
  <span class="co1">// conexion al servidor realizada</span>
&nbsp;
    <span class="kw1">if</span> <span class="br0">&#40;</span><span class="re0">$_REQUEST</span><span class="br0">&#91;</span><span class="st0">'mid'</span><span class="br0">&#93;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
    <span class="co1">// peticion de un MENSAJE concreto</span>
      <span class="re0">$subject</span> = <span class="kw2">false</span>;
      <span class="kw1">for</span> <span class="br0">&#40;</span><span class="re0">$i</span> = <span class="nu0">1</span>; <span class="re0">$i</span> &lt;= imap_num_msg<span class="br0">&#40;</span><span class="re0">$mbox</span><span class="br0">&#41;</span>; <span class="re0">$i</span>++<span class="br0">&#41;</span> <span class="br0">&#123;</span>
        <span class="re0">$headers</span> = imap_header<span class="br0">&#40;</span><span class="re0">$mbox</span>,<span class="re0">$i</span><span class="br0">&#41;</span>;
&nbsp;
        <span class="co1">// obtenemos y comparamos el message_id con el solicitado</span>
        <span class="re0">$message_id</span> = parseMessageId<span class="br0">&#40;</span><span class="re0">$headers</span>-&gt;<span class="me1">message_id</span><span class="br0">&#41;</span>;
        <span class="kw1">if</span> <span class="br0">&#40;</span><span class="re0">$_REQUEST</span><span class="br0">&#91;</span><span class="st0">'mid'</span><span class="br0">&#93;</span> == <span class="re0">$message_id</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
          <span class="co1">// obtenemos el asunto</span>
          <span class="re0">$subject</span> = parseSubject<span class="br0">&#40;</span><span class="re0">$headers</span>-&gt;<span class="me1">subject</span><span class="br0">&#41;</span>;
&nbsp;
          <span class="co1">// obtenemos la fecha de envio</span>
          <span class="re0">$udate</span> = <span class="re0">$headers</span>-&gt;<span class="me1">udate</span>;
          <span class="re0">$date</span> = <a href="http://www.php.net/date"><span class="kw3">date</span></a><span class="br0">&#40;</span><span class="st0">"F j, Y, g:i a"</span>, <span class="re0">$udate</span><span class="br0">&#41;</span>;
&nbsp;
          <span class="co1">// obtenemos el cuerpo del mensaje y lo recodificamos</span>
          <span class="re0">$body</span> = imap_body<span class="br0">&#40;</span><span class="re0">$mbox</span>,<span class="re0">$i</span><span class="br0">&#41;</span>;
          <span class="re0">$body</span> = <a href="http://www.php.net/quoted_printable_decode"><span class="kw3">quoted_printable_decode</span></a><span class="br0">&#40;</span><span class="re0">$body</span><span class="br0">&#41;</span>;
          <span class="re0">$body</span> = <a href="http://www.php.net/htmlentities"><span class="kw3">htmlentities</span></a><span class="br0">&#40;</span><span class="re0">$body</span>,ENT_NOQUOTES,<span class="st0">"UTF-8"</span><span class="br0">&#41;</span>;
&nbsp;
          <span class="co1">// sustituimos lineas en blanco por dos &lt;br/&gt;</span>
          <span class="re0">$body</span> = <a href="http://www.php.net/ereg_replace"><span class="kw3">ereg_replace</span></a><span class="br0">&#40;</span><span class="st0">"<span class="es0">\r</span><span class="es0">\n</span>[ <span class="es0">\t</span>]*<span class="es0">\r</span><span class="es0">\n</span>|<span class="es0">\n</span>[ <span class="es0">\t</span>]*<span class="es0">\n</span>"</span>,
                               <span class="st0">"&lt;br/&gt;&lt;br/&gt;<span class="es0">\n</span>"</span>,<span class="re0">$body</span><span class="br0">&#41;</span>;
         <span class="coMULTI">/* eliminamos retornos de carro simple para
             agrupar parrafos */</span>
          <span class="re0">$body</span> = <a href="http://www.php.net/ereg_replace"><span class="kw3">ereg_replace</span></a><span class="br0">&#40;</span><span class="st0">"<span class="es0">\r</span><span class="es0">\n</span>|<span class="es0">\n</span>"</span>,<span class="st0">" "</span>,<span class="re0">$body</span><span class="br0">&#41;</span>;
          <span class="co1">// convertimos las URLs</span>
          <span class="re0">$body</span> = <a href="http://www.php.net/ereg_replace"><span class="kw3">ereg_replace</span></a><span class="br0">&#40;</span><span class="st0">"(http://[^( |<span class="es0">\t</span>|<span class="es0">\n</span>|<span class="es0">\r</span>|&lt;)]*)"</span>,
                               <span class="st0">"&lt;a href=<span class="es0">\"</span><span class="es0">\\</span>0<span class="es0">\"</span>&gt;<span class="es0">\\</span>0&lt;/a&gt;"</span>,<span class="re0">$body</span><span class="br0">&#41;</span>;
        <span class="br0">&#125;</span>
      <span class="br0">&#125;</span>
&nbsp;
      <span class="kw1">if</span> <span class="br0">&#40;</span><span class="re0">$subject</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
      <span class="co1">// si todo ha ido bien devolvemos los datos</span>
        <a href="http://www.php.net/echo"><span class="kw3">echo</span></a> <span class="st0">"&lt;h3&gt;$subject&lt;/h3&gt;<span class="es0">\n</span>"</span>;
        <a href="http://www.php.net/echo"><span class="kw3">echo</span></a> <span class="st0">"       &lt;h4&gt;$date&lt;/h4&gt;"</span>;
        <a href="http://www.php.net/echo"><span class="kw3">echo</span></a> <span class="st0">"       &lt;p&gt;$body&lt;/p&gt;"</span>;
      <span class="br0">&#125;</span> <span class="kw1">else</span> <span class="br0">&#123;</span>
      <span class="co1">// en caso contrario informamos del error</span>
        <a href="http://www.php.net/echo"><span class="kw3">echo</span></a> <span class="st0">"&lt;h3&gt;Error&lt;/h3&gt;<span class="es0">\n</span>"</span>;
        <a href="http://www.php.net/echo"><span class="kw3">echo</span></a> <span class="st0">"       &lt;p&gt;No existe el mensaje seleccionado.&lt;/p&gt;"</span>;
      <span class="br0">&#125;</span>
    <span class="br0">&#125;</span> <span class="kw1">else</span> <span class="br0">&#123;</span>
    <span class="co1">// peticion de la LISTA DE MENSAJES</span>
      <a href="http://www.php.net/echo"><span class="kw3">echo</span></a> <span class="st0">"&lt;h3&gt;&amp;Iacute;ndice de documentos&lt;/h3&gt;<span class="es0">\n</span>"</span>;
      <a href="http://www.php.net/echo"><span class="kw3">echo</span></a> <span class="st0">"       &lt;p&gt;Este es un listado din&amp;aacute;mico de documentos<span class="es0">\n</span>"</span>;
      <a href="http://www.php.net/echo"><span class="kw3">echo</span></a> <span class="st0">"        interesantes que se pueden encontrar en Internet.&lt;/p&gt;<span class="es0">\n</span>"</span>;
      <a href="http://www.php.net/echo"><span class="kw3">echo</span></a> <span class="st0">"       &lt;ul&gt;<span class="es0">\n</span>"</span>;
&nbsp;
      <span class="co1">// iteramos sobre la lista de mensajes</span>
      <span class="kw1">for</span> <span class="br0">&#40;</span><span class="re0">$i</span> = <span class="nu0">1</span>; <span class="re0">$i</span> &lt;= imap_num_msg<span class="br0">&#40;</span><span class="re0">$mbox</span><span class="br0">&#41;</span>; <span class="re0">$i</span>++<span class="br0">&#41;</span> <span class="br0">&#123;</span>
        <span class="re0">$headers</span> = imap_header<span class="br0">&#40;</span><span class="re0">$mbox</span>,<span class="re0">$i</span><span class="br0">&#41;</span>;
        <span class="re0">$subject</span> = parseSubject<span class="br0">&#40;</span><span class="re0">$headers</span>-&gt;<span class="me1">subject</span><span class="br0">&#41;</span>;
&nbsp;
        <span class="re0">$message_id</span> = parseMessageId<span class="br0">&#40;</span><span class="re0">$headers</span>-&gt;<span class="me1">message_id</span><span class="br0">&#41;</span>;
&nbsp;
        <span class="co1">// imprimimos el elemento de la lista con su enlace</span>
        <a href="http://www.php.net/echo"><span class="kw3">echo</span></a> <span class="st0">"        &lt;li&gt;&lt;a href=<span class="es0">\"</span>"</span>.<span class="re0">$_DIR</span><span class="br0">&#91;</span><span class="st0">'DOCS'</span><span class="br0">&#93;</span>.
             <span class="st0">"ptr.php?mid=$message_id<span class="es0">\"</span>&gt;"</span>.<span class="re0">$subject</span>.<span class="st0">"&lt;/a&gt;&lt;/li&gt;<span class="es0">\n</span>"</span>;
      <span class="br0">&#125;</span>
      <a href="http://www.php.net/echo"><span class="kw3">echo</span></a> <span class="st0">"       &lt;/ul&gt;"</span>;
    <span class="br0">&#125;</span>
    imap_close<span class="br0">&#40;</span><span class="re0">$mbox</span><span class="br0">&#41;</span>;
  <span class="br0">&#125;</span>
<span class="kw2">?&gt;</span></pre></div>
Basta intruducir este código en el cuerpo de una página HTML, o en tantas como categorías tengamos. Otra opción es mejorar el código para que obtenga la lista de carpetas y muestre en la raíz una lista de enlaces para acceder a cada una de ellas. Aparte de eso, sólo queda <a href="http://blackspiral.org/docs/ptr.php">disfrutar del resultado</a>.]]></description>
 <category>programación</category>
<comments>http://blog.blackspiral.org/index.php?itemid=21</comments>
 <pubDate>Sat, 11 Feb 2006 18:03:10 +0100</pubDate>
</item><item>
 <title><![CDATA[Filtrando spam en tiempo SMTP]]></title>
 <link>http://blog.blackspiral.org/index.php?itemid=20</link>
<description><![CDATA[¿Harto de recibir cada día toneladas de spam? Yo desde luego sí. La idea de este mini tutorial es evitar el spam directamente en su recepción, de modo que no llegue nunca a ocupar recursos del buzón del usuario. De este modo, los mensajes se analizan <b>durante</b> su recepción, y nuestro <i>MTA</i> los rechaza en caso de que den positivo en el análisis de spam. En este caso vamos a utilizar <a href="http://exim.org/">Exim</a> como <i>MTA</i>, y <a href="http://spamassassin.apache.org/">SpamAssassin</a> para analizar y marcar el spam, sobre un servidor <a href="http://www.gentoo.org">gentoo linux</a>.Para empezar nos aseguramos de tener todo instalado y configurado correctamente:<br/>
<div class="code">
<h3>Instalación de exim y spamassassin</h3>
<pre class="bash"><span class="co1"># USE=&quot;exiscan exiscan-acl&quot; emerge -av exim spamassassin </span></pre></div><br/>
<div class="code">
<h3>Configuración de spamassassin</h3>
<pre class="bash">rewrite_subject <span class="nu0">0</span>
report_safe <span class="nu0">1</span>
use_bayes <span class="nu0">1</span>
auto_learn <span class="nu0">1</span>
bayes_auto_learn <span class="nu0">1</span>
bayes_auto_learn_threshold_nonspam <span class="nu0">1</span>
bayes_auto_learn_threshold_spam <span class="nu0">14</span>.<span class="nu0">00</span>
skip_rbl_checks <span class="nu0">0</span></pre></div><br/>
Una vez tengamos exim configurado <b>sin</b> spamassassin y funcionando (haced unas cuantas pruebas de envío y recepción de correo), pasamos a incluir el soporte spamassassin en tiempo SMTP y algunas otras funcionalidades. Debemos tener el demonio <b>spamd</b> como servicio, así que lo añadimos al nivel de ejecución por defecto con <i>rc-update</i>. Configuramos ahora exim:<br/>
<div class="code">
<h3>Configuración de exim</h3>
<pre class="bash"><span class="br0">&#91;</span>...<span class="br0">&#93;</span>
<span class="co1"># definimos una lista de hosts y redes desde la que hacemos relay</span>
hostlist relay_from_hosts = <span class="nu0">127</span>.<span class="nu0">0</span>.<span class="nu0">0</span>.<span class="nu0">1</span> : <span class="nu0">10</span>.<span class="nu0">0</span>.<span class="nu0">0</span>.<span class="nu0">0</span>/<span class="nu0">24</span>
&nbsp;
<span class="co1"># verificamos el helo y ehlo para el resto de hosts</span>
helo_try_verify_hosts = !+relay_from_hosts
&nbsp;
<span class="co1"># indicamos las comprobaciones que queremos hacer</span>
acl_smtp_rcpt = acl_check_rcpt
acl_smtp_connect = acl_check_host
acl_smtp_data = acl_check_data
acl_smtp_helo = acl_check_helo
&nbsp;
<span class="co1"># configuramos la localización del demonio spamd</span>
spamd_address = <span class="nu0">127</span>.<span class="nu0">0</span>.<span class="nu0">0</span>.<span class="nu0">1</span> <span class="nu0">783</span>
&nbsp;
<span class="br0">&#91;</span>...<span class="br0">&#93;</span>
&nbsp;
begin acl
&nbsp;
<span class="co1"># definimos las listas de control de acceso</span>
&nbsp;
acl_check_host:
  accept
    hosts = +relay_from_hosts
  deny
    log_message = match host_reject.list
    hosts = /etc/exim/filters/host_reject.list
  accept
&nbsp;
acl_check_helo:
  accept
    hosts = +relay_from_hosts
  <span class="co1"># alguien trata de identificarse como nosotros mismos</span>
  <span class="co1"># o con un &quot;helo&quot; típico: &quot;friend&quot;</span>
  deny  condition = $<span class="br0">&#123;</span><span class="kw1">if</span> or <span class="br0">&#123;</span> \
              <span class="br0">&#123;</span>eq <span class="br0">&#123;</span>$<span class="br0">&#123;</span>lc:<span class="re1">$sender_helo_name</span><span class="br0">&#125;</span><span class="br0">&#125;</span><span class="br0">&#123;</span>blackspiral.org<span class="br0">&#125;</span><span class="br0">&#125;</span> \
              <span class="br0">&#123;</span>eq <span class="br0">&#123;</span>$<span class="br0">&#123;</span>lc:<span class="re1">$sender_helo_name</span><span class="br0">&#125;</span><span class="br0">&#125;</span><span class="br0">&#123;</span>blackout.homelinux.org.org<span class="br0">&#125;</span><span class="br0">&#125;</span> \
              <span class="br0">&#123;</span>eq <span class="br0">&#123;</span>$<span class="br0">&#123;</span>lc:<span class="re1">$sender_helo_name</span><span class="br0">&#125;</span><span class="br0">&#125;</span><span class="br0">&#123;</span>friend<span class="br0">&#125;</span><span class="br0">&#125;</span> \
         <span class="br0">&#125;</span> <span class="br0">&#123;</span>true<span class="br0">&#125;</span><span class="br0">&#123;</span>false<span class="br0">&#125;</span> <span class="br0">&#125;</span>
&nbsp;
  <span class="co1"># aceptamos por defecto</span>
  accept
&nbsp;
acl_clean_helo:
  accept
   verify     = helo
   condition  = $<span class="br0">&#123;</span><span class="kw1">if</span> match<span class="br0">&#123;</span><span class="re1">$sender_helo_name</span><span class="br0">&#125;</span><span class="br0">&#123;</span> \ 
                       \N<span class="br0">&#40;</span>\d<span class="br0">&#123;</span><span class="nu0">1</span>,<span class="nu0">3</span><span class="br0">&#125;</span><span class="br0">&#91;</span>.-<span class="br0">&#93;</span>\d<span class="br0">&#123;</span><span class="nu0">1</span>,<span class="nu0">3</span><span class="br0">&#125;</span><span class="br0">&#91;</span>.-<span class="br0">&#93;</span>\d<span class="br0">&#123;</span><span class="nu0">1</span>,<span class="nu0">3</span><span class="br0">&#125;</span><span class="br0">&#91;</span>.-<span class="br0">&#93;</span>\d\
                       <span class="br0">&#123;</span><span class="nu0">1</span>,<span class="nu0">3</span><span class="br0">&#125;</span><span class="br0">&#41;</span>|<span class="br0">&#40;</span><span class="br0">&#91;</span><span class="nu0">0</span>-9a-f<span class="br0">&#93;</span><span class="br0">&#123;</span><span class="nu0">8</span><span class="br0">&#125;</span><span class="br0">&#41;</span>|<span class="br0">&#40;</span><span class="br0">&#91;</span><span class="nu0">0</span>-9A-F<span class="br0">&#93;</span><span class="br0">&#123;</span><span class="nu0">8</span><span class="br0">&#125;</span><span class="br0">&#41;</span>\N\
          <span class="br0">&#125;</span> <span class="br0">&#123;</span>false<span class="br0">&#125;</span><span class="br0">&#123;</span>true<span class="br0">&#125;</span><span class="br0">&#125;</span>
&nbsp;
acl_check_rcpt:
<span class="br0">&#91;</span>...<span class="br0">&#93;</span>
&nbsp;
acl_check_data:
  accept  hosts = +relay_from_hosts
&nbsp;
  <span class="co1"># no permitimos ejecutables de windows</span>
  deny    message = This message contains an attachment\
             of a <span class="kw3">type</span> which we <span class="kw1">do</span> not accept <span class="br0">&#40;</span>.<span class="re1">$found_extension</span><span class="br0">&#41;</span>
    demime = bat:btm:cmd:com:cpl:dll:exe:lnk:msi:pif:prf:reg:scr:vbs:url
&nbsp;
  <span class="co1"># spamassassin</span>
&nbsp;
  <span class="co1"># añadimos las cabeceras mínimas de SA</span>
  warn    message = X-SA-Score: <span class="re1">$spam_score</span>
    spam = nobody:true
  warn    message = X-SA-Report: <span class="re1">$spam_report</span>
    spam = nobody:true
    condition = $<span class="br0">&#123;</span><span class="kw1">if</span> &gt;<span class="br0">&#123;</span><span class="re1">$spam_score_int</span><span class="br0">&#125;</span><span class="br0">&#123;</span><span class="nu0">0</span><span class="br0">&#125;</span><span class="br0">&#123;</span>true<span class="br0">&#125;</span><span class="br0">&#123;</span>false<span class="br0">&#125;</span><span class="br0">&#125;</span>
&nbsp;
  <span class="co1"># marcamos el mensaje como spam si no super el umbral</span>
  <span class="co1"># maximo pero si un minimo</span>
  warn    message = X-SA-Status: Yes
     spam = nobody:true
     condition = $<span class="br0">&#123;</span><span class="kw1">if</span> &gt;<span class="br0">&#123;</span><span class="re1">$spam_score_int</span><span class="br0">&#125;</span><span class="br0">&#123;</span><span class="nu0">40</span><span class="br0">&#125;</span><span class="br0">&#123;</span>true<span class="br0">&#125;</span><span class="br0">&#123;</span>false<span class="br0">&#125;</span><span class="br0">&#125;</span>
&nbsp;
  <span class="co1"># denegamos todos los mensajes que superen un umbral,</span>
  <span class="co1"># expresado multiplicado por 10. En este ejemplo, 5.0</span>
  deny    message = This message scored <span class="re1">$spam_score</span> spam points.
      spam = nobody:true
      condition = $<span class="br0">&#123;</span><span class="kw1">if</span> &gt;<span class="br0">&#123;</span><span class="re1">$spam_score_int</span><span class="br0">&#125;</span><span class="br0">&#123;</span><span class="nu0">50</span><span class="br0">&#125;</span><span class="br0">&#123;</span>true<span class="br0">&#125;</span><span class="br0">&#123;</span>false<span class="br0">&#125;</span><span class="br0">&#125;</span>
&nbsp;
   <span class="co1"># aceptamos por defecto</span>
   accept</pre></div><br/>
Arrancamos el servicio y hacemos una prueba. Lo mejor es un mensaje de spam que hayamos recibido anteriormente y sea muy claro, de forma que un spamassassin recién instalado no tenga duda. Para no complicarnos, vamos a utilizar un ejemplo sencillo:<br/>
<div class="code">
<h3>Probando el filtrado</h3>
<pre class="bash"><span class="co1"># telnet localhost 25</span>
Trying <span class="nu0">127</span>.<span class="nu0">0</span>.<span class="nu0">0</span>.<span class="nu0">1</span>...
Connected to localhost.
Escape character is <span class="st0">'^]'</span>.
<span class="nu0">220</span> blackspiral.org ESMTP Wed, <span class="nu0">01</span> Feb <span class="nu0">2006</span> <span class="nu0">19</span>:<span class="nu0">29</span>:<span class="nu0">45</span> +<span class="nu0">0100</span>
mail from: <a href="mailto:foo@bar.com">foo[en]bar[punto]com</a>
<span class="nu0">250</span> OK
rcpt to: <a href="mailto:spam@blackspiral.org">spam[en]blackspiral[punto]org</a>
<span class="nu0">250</span> Accepted
data
<span class="nu0">354</span> Enter message, ending with <span class="st0">"."</span> on a line by itself
From: <a href="mailto:foo@bar.com">foo[en]bar[punto]com</a>
To: <a href="mailto:spam@blackspiral.org">spam[en]blackspiral[punto]org</a>
Subject: $$$ Make Money Fast $$$ !!!
&nbsp;
viagra <span class="nu0">100</span>% GARANTEE AMAZING FULL REFUND 
This is not spam
.
<span class="nu0">550</span> Rejected</pre></div><br/>
Deberíamos obtener un resultado similar con cualquier correo que supere el umbral tolerable que hemos configurado (5.0 en nuestro caso). Si echamos un ojo al <i>exim_reject.log</i> veremos el análisis detallado de spamassassin y la puntuación que ha dado al correo (y una explicación acorde), mientras que en el <i>exim_main.log</i> simplemente aparece una reseña indicando que un correo ha sido denegado por considerarse spam.<br/><br/>
Para los que quieran un nivel más de protección en su MTA, deberían leer algo sobre <a href="http://projects.puremagic.com/greylisting/">greylisting</a>.<br/><br/>
Como medida de calidad de esta forma de filtrar spam, baste decir que desde que he configurado exim para que realice estas comprobaciones ("helo" inválido, spamd, etc), he pasado de hasta 20 correos diarios de spam (algunos de ellos no marcados por spamassassin y que por tanto llegaban al INBOX) a <b>cero</b>. Yo creo que merece la pena probarlo ;-)]]></description>
 <category>linux</category>
<comments>http://blog.blackspiral.org/index.php?itemid=20</comments>
 <pubDate>Wed, 1 Feb 2006 18:37:00 +0100</pubDate>
</item><item>
 <title><![CDATA[Blackspiral]]></title>
 <link>http://blog.blackspiral.org/index.php?itemid=19</link>
<description><![CDATA[Como habréis podido comprobar, año nuevo, dominio nuevo. Desde ahora el servidor cuenta con un nuevo dominio mucho más sencillo: <a href="http://blackspiral.org">blackspiral.org</a>, que es además el dominio de correo, y varios subdominios para servir el <a href="http://blog.blackspiral.org/">blog</a> y la <a href="http://gallery.blackspiral.org/">galería</a>.<br/><br/>
He reconfigurado todos los servicios de forma que la migración sea transparente y todas las viejas URLs sigan siendo válidas, aunque el viejo dominio tenderá a desaparecer. Actualizad vuestros favoritos. Espero que el nuevo dominio sea de vuestro agrado y os resulte mucho más <b>fácil de recordar</b> ;-)]]></description>
 <category>general</category>
<comments>http://blog.blackspiral.org/index.php?itemid=19</comments>
 <pubDate>Sun, 15 Jan 2006 03:47:07 +0100</pubDate>
</item><item>
 <title><![CDATA[Resaltado de sintaxis en PHP]]></title>
 <link>http://blog.blackspiral.org/index.php?itemid=18</link>
<description><![CDATA[Esta mañana, via <a href="http://www.blackshell.usebox.net/archivo/728.php">Blackshell</a>, he descubierto un curioso proyecto llamado <a href="http://qbnz.com/highlighter/">GeSHi</a> (<i>General Syntax Highlighter</i>) y escrito en PHP, para resaltar la sintaxis del código fuente escrito en múltiples lenguajes (muchos más de los que yo podría necesitar nunca). Parece una tontería, pero me parece muy útil si se quiere publicar código a través de la web y mantenerlo educativo y legible a la vez. Me iba a poner a integrarlo en <a href="http://www.nucleuscms.org">nucleus</a> para poder usarlo aquí cuando he visto que <a href="http://wakka.xiffy.nl/geshi">alguien se me ha adelantado</a>. Una vez instalado (reconozco que ha costado un poco, el soporte CSS está un poco verde en el <i>plugin</i>), éste es el resultado:<br/>
<div class="code">
<h3>foobar.py</h3>
<pre class="python"><span class="kw1">import</span> <span class="kw3">sys</span>
&nbsp;
<span class="kw1">if</span> __name__ == <span class="st0">'__main__'</span>:
    <span class="kw1">print</span> <span class="st0">"foobar"</span>
    <span class="kw3">sys</span>.<span class="me1">exit</span><span class="br0">&#40;</span><span class="nu0">0</span><span class="br0">&#41;</span></pre></div>Para los que uséis nucleus, aparte de las instrucciones de instalación del <i>plugin</i>, os sugiero que sigáis los siguientes pasos:
<br/><br/>
<ul><li>En el archivo <i>NP_Geshi.php</i>, sustituye la línea <pre class="php"><span class="re0">$geshi</span>-&gt;<span class="me1">set_overall_class</span><span class="br0">&#40;</span><span class="st0">"code"</span><span class="br0">&#41;</span>;</pre> por <pre class="php"><span class="re0">$geshi</span>-&gt;<span class="me1">set_overall_class</span><span class="br0">&#40;</span><a href="http://www.php.net/strtolower"><span class="kw3">strtolower</span></a><span class="br0">&#40;</span><span class="re0">$r</span><span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;</pre></li>
<li>Créate un archivo css donde prefieras (es una buena idea juntar todos los css en un mismo sitio) e incluye dentro de él los estilos para los lenguajes que vayas a utilizar. Puedes acceder a ellos usando la <a href="http://qbnz.com/highlighter/demo.php">demo de GeSHi</a>. Por ejemplo, yo uso <a href="/css/lang.css">éste</a>.</li>
<li>En el archivo <i>head.inc</i> de tu <i>skin</i> de <i>nucleus</i>, incluye una línea que apunte a dicho css: <pre class="html4strict"><span class="sc2"><a href="http://december.com/html/4/element/link.html"><span class="kw2">&lt;link</span></a> <span class="kw3">rel</span>=<span class="st0">"stylesheet"</span> <span class="kw3">type</span>=<span class="st0">"text/css"</span> <span class="kw3">href</span>=<span class="st0">"/css/lang.css"</span>/<span class="kw2">&gt;</span></span></pre></li></ul>
Una vez hecho esto basta que incluyas tu código entre etiquetas <i>pre</i> de la siguiente forma:<br>
<pre>&lt;pre <b>lenguaje</b>>código&lt;/pre></pre>]]></description>
 <category>programación</category>
<comments>http://blog.blackspiral.org/index.php?itemid=18</comments>
 <pubDate>Tue, 29 Nov 2005 22:42:59 +0100</pubDate>
</item>
  </channel>
</rss>