<?xml version="1.0" encoding="utf-8"?>

<rss version="2.0"
  xmlns:cc="http://backend.userland.com/creativeCommonsRssModule"
  xmlns:icbm="http://postneo.com/icbm"
>
  <channel>
    <title>bblog</title>
    <link>http://www.drbeat.li/bblog/</link>
    <description>beating the one-way web</description>
    <image>
      <url>http://drbeat.li/pic/favicon.png</url>
      <title>drbeat.li's logo</title>
      <link>http://drbeat.li/pic/favicon.png</link>
    </image>
    <language>de-ch</language>
    <copyright>Copyright Beat Bolli &lt;bbolli@ewanet.ch&gt;
      siehe/see http://creativecommons.org/licenses/by-nc-sa/1.0/
    </copyright>
    <cc:license>http://creativecommons.org/licenses/by-nc-sa/1.0/rdf</cc:license>
    <generator>blosxom/2.0 (http://www.blosxom.com)</generator>
    <docs>http://blogs.law.harvard.edu/tech/rss</docs>
    <icbm:latitude>47.0452</icbm:latitude>
    <icbm:longitude>7.2715</icbm:longitude>
    <item>
      <title>Neue Liste meiner NTP-Server</title>
      <link>http://www.drbeat.li/bblog/software/debian/2010/04/30#ntp_servers</link>
      <pubDate>Fri, 30 Apr 2010 13:06:00 GMT</pubDate>
      <description><![CDATA[ <pre>time.inf.ethz.ch ntp.metas.ch ntp.univ-lyon1.fr zg1.ntp.carnet.hr</pre>
<p>Ändern mit <code>dpkg-reconfigure ntp-simple</code>.</p>
<p>Seinerzeit habe ich die Server anhand tiefer Ping-Zeiten ausgesucht.
<code>swisstime.ethz.ch</code> ist zum Stratum 1-Server avanciert und sollte
nicht mehr direkt von Endusern benützt werden.</p>
 ]]></description>
    </item>

    <item>
      <title>Sommer, wo bleibst du?!?</title>
      <link>http://www.drbeat.li/bblog/allgemein/2010/04/30#sommer_2004</link>
      <pubDate>Fri, 30 Apr 2010 13:06:00 GMT</pubDate>
      <description><![CDATA[ <p>Es muss einfach einmal gesagt sein: von einem Jahr war es nachts wärmer als
diesen &#8220;Sommer&#8221; am Tag!</p> ]]></description>
    </item>

    <item>
      <title>Internet-Archäologie</title>
      <link>http://www.drbeat.li/bblog/allgemein/2010/04/30#smiley1</link>
      <pubDate>Fri, 30 Apr 2010 13:06:00 GMT</pubDate>
      <description><![CDATA[ <p><a href="http://research.microsoft.com/~mbj/Smiley/Smiley.html">Das erste Smiley</a>
wurde gefunden :-) [via <a href="http://slashdot.org/article.pl?sid=02/09/12/2133216">Slashdot</a>]</p>
 ]]></description>
    </item>

    <item>
      <title>Ein gutes neues Jahr&#8230;</title>
      <link>http://www.drbeat.li/bblog/allgemein/2010/04/30#neujahr_2003</link>
      <pubDate>Fri, 30 Apr 2010 13:06:00 GMT</pubDate>
      <description><![CDATA[ <p>&#8230; wünsche ich allen!</p>
 ]]></description>
    </item>

    <item>
      <title>Apache wieder OK</title>
      <link>http://www.drbeat.li/bblog/software/debian/2010/04/30#libc6_apache_ok</link>
      <pubDate>Fri, 30 Apr 2010 13:06:00 GMT</pubDate>
      <description><![CDATA[ <p>Während meinem heutigen dist-upgrade-Prozedere wurde Apache aktualisiert.
Die <a href="$url/2002/08/12#libc6_hack">Abhängigkeit von libdb1</a> ist
tatsächlich schon kalter Kaffee:</p>
<pre>apache (1.3.26-1.1) unstable; urgency=low

  * NMU
  * The "Shouldn't you be in Whoville stealing Christmas?" release.
  * Applied patch from Ryan Murray to use db2's db185-compat functions
    instead of glibc's (nonexistant) db1 library.
    - Edited patch to include the same hack for mod_urlcount and mod_eaccess
      from apache-contrib
    - Closes: #143085 #156159 #156390 #156373 #155981

 -- Adam Conrad &lt;adconrad@0c3.net&gt;  Mon, 12 Aug 2002 21:08:40 -0600
</pre>
<p>Mein /usr/local/sbin/upgrade-Script sieht übrigens so aus:</p>
<pre class="code">#!/bin/sh

# constants
MAILTO=root
LOG=/var/log/aptitude

# mark the start of this upgrade in the log file
TAG="$(hostname | cut -f1 -d.) upgrade of $(date -Im)"
echo -e "\n${TAG}\n" &gt;&gt;$LOG

# grab the new package list
aptitude update

# do the dist-upgrade
aptitude dist-upgrade &amp;&amp; aptitude autoclean

# update the local mirror in the background
if [ "$?" -eq 0 -a -d /mirrors -a "$1" != -q ]; then
    apt-move local &gt;/var/log/apt-move 2>&amp;1 &amp;
fi

# mail the new part of the log file
sed -ne "/^$TAG/,$p" $LOG | mail -s "$TAG" $MAILTO
</pre>
<p><strong>Update:</strong> Jetzt ist es nur noch die libdav.so, die libdb1 immer noch benötigt!</p>
 ]]></description>
    </item>

    <item>
      <title>libc6 breakage</title>
      <link>http://www.drbeat.li/bblog/software/debian/2010/04/30#libc6_break</link>
      <pubDate>Fri, 30 Apr 2010 13:06:00 GMT</pubDate>
      <description><![CDATA[ <p>Heute morgen hatte ich einen Fehler von Webalizer in meinem Server-Log:
Die libdb.so.2 war verschwunden! Gestern hatte sich die libc6 auf 2.2.5-13
aktualisiert, und in deren Changelog hatte ich folgendes gelesen:
<q>- Remove db1 compat library. The only user I know of this is coda.
Coda can include it&#8217;s own version of the library now. I&#8217;ve emailed the
coda maintainer.</q>
Da musste es doch einen Zusammenhang geben; offensichtlich ist Coda nicht
das einzige Paket, das noch auf diese Bibliothek angewiesen ist. Auf Debians
<a href="http://packages.debian.org/">Paketsuchseite</a> gibt es zwar noch
ein Ergebnis für die betroffene Datei, ein Vergleich mit der Dateiliste der
libc6 aus Sarge zeigt jedoch, dass die Datei in Sid jetzt fehlt. Anyway, ich
habe einen Bugreport für libc6 geschrieben.</p>
 ]]></description>
    </item>

    <item>
      <title>Arnold Stalder&#8230;</title>
      <link>http://www.drbeat.li/bblog/allgemein/2010/04/30#noldi_presi</link>
      <pubDate>Fri, 30 Apr 2010 13:06:00 GMT</pubDate>
      <description><![CDATA[ <p>&#8230; wurde heute zum Gemeindepräsidenten von <a href="http://www.aarberg.ch">Aarberg</a> gewählt.</p>

<p>Wir gratulieren und wünschen alles Nötige für dieses Amt!</p> ]]></description>
    </item>

    <item>
      <title>Aus dem Keller</title>
      <link>http://www.drbeat.li/bblog/software/python/2010/04/30#mailsig</link>
      <pubDate>Fri, 30 Apr 2010 13:06:00 GMT</pubDate>
      <description><![CDATA[ <p>Dieses Progrämmli habe ich vor Monaten mal gebraucht, um eine Signatur zu
generieren. Heute bin ich wieder einmal darauf gestossen:</p>

<pre class="code" xml:lang="en">#!/usr/bin/python

"""
This program encodes a string reversably into a longint.

The goal is to write the reverse function as a Python one-liner so that
it fits in an email signature.

The idea is to convert each character of the string to one digit of the number.

The twist is this: the number's base depends on the string, and each digit
is offset so that the base becomes as small as possible. The offset is one less
than the lowest numbered ASCII code in the string. The base is two more
than the difference between highest and lowest ASCII code. This way, the
lowest code gets the digit value 1, the highest code gets the value (base - 1).

The reverse function u() recursively undoes this transformation.
"""

print
str = raw_input('Enter a string: ')
if not str:
    str = 'default test string'

# Convert the string to a list of ASCII codes.
codes = [ord(ch) for ch in str]

# Calculate offset and base.
ofs = min(codes) - 1
base = max(codes) + 1 - ofs

# Build the encoded number.
num = hex(reduce(lambda n, digit: base * n + digit - ofs, codes, 0L))

# Build the signature.
sig = """#!/usr/bin/python
def u(n, b, o): return n and u(n / b, b, o) + chr(n %% b + o) or ''
print u(%s, %d, %d)""" % (num, base, ofs)

print
print sig

# Verify.
print
exec sig
if u(eval(num), base, ofs) == str:
    print 'OK'
else:
    print 'not OK'</pre>

<p>Das Ergebnis sieht für meine Mail-Adresse so aus:</p>

<pre class="file">#!/usr/bin/python
def u(n, b, o): return n and u(n / b, b, o) + chr(n % b + o) or ''
print u(0x90F8CA4FAD75C381BC173DA23L, 75, 45)</pre>

<p>Das Dekodieren überlasse ich dem Leser als Übung!</p>
 ]]></description>
    </item>

    <item>
      <title>Hilfsprogramme für mein Album</title>
      <link>http://www.drbeat.li/bblog/software/2010/04/30#album_software</link>
      <pubDate>Fri, 30 Apr 2010 13:06:00 GMT</pubDate>
      <description><![CDATA[ <p>Ich denke, dass jetzt ein guter Zeitpunkt ist, einmal meine paar
Hilfsprogramme und -Scripts vorzustellen, mit denen ich die
Bilder von der Kamera ins <a href="/album/">Album</a> lade.</p>

<p>Das ganze geht in verschiedenen Schritten vor sich:</p>


<ol>
<li>Die Bilder werden mit einem <span class="caps">USB</span>-Kartenleser von der Compact-Flash-Karte in monatsweise Verzeichnisse auf der HD eingelesen. Ich benütze einen Kartenleser, weil so der Akku der Kamera geschont wird. Die HD-Verzeichnisse werden periodisch auf CD gebrannt.</li>
<li>Zur Bildbearbeitung auf dem PC verwende ich <a href="http://www.irfanview.com">IrfanView</a> und/oder Photoshop Elements, das beim Scanner dabei war. Wenn ich an den Bildern überhaupt etwas editiere, beschränkt sich das meistens auf eine Freistellung des interessanten Ausschnitts (vor allem bei stark gezoomten Fotos) oder einen Farbausgleich.</li>
<li>Als erstes rotiere ich mit der Batch-Konversion von IrfanView die Portrait-Bilder nach 90° links.</li>
<li>Das Album-Verzeichnis auf dem Server ist via <a href="http://www.samba.org">Samba</a> mit dem PC verbunden.</li>
<li>Die Bilder im Album sind meistens im Format 800&#215;600 oder 600&#215;800. Die Batch-Konversion von IrfanView ist bestens geeignet, um die Bilder zu verkleinern und gleichzeitig auf dem Server zu speichern.</li>
<li>Auf dem Server generiert der Script <a href="#mkthumb"><code>mkthumb</code></a> die Thumbnails neu, die nach dem Rotieren oder Ausschneiden natürlich nicht mehr dem Bild entsprechen.</li>
</ol>



<p>Falls das Album nur klein ist, erledigen die Scripts <a href="#mk800"><code>mk800</code></a> und
<a href="#mkportrait"><code>mkportrait</code></a> die Aufgaben von IrfanView direkt auf dem Server.</p>

<h4 id="mkthumb">mkthumb</h4>



<pre class="file">#! /bin/sh

# $Id: mkthumb 309 2004-09-14 22:10:35Z bb $

makethumb_file() {
    echo &quot;processing $f to tn_$f&quot;
    convert -size 160x160 &quot;$f&quot; -resize 160x160 -quality 50 -antialias &quot;tn_$f&quot;
}

makethumb_exif() {
    exiftran -gibp &quot;$f&quot;
}

for f; do
    case &quot;${f##*.}&quot; in
	jpg)
	    makethumb_exif;;
	png|gif)
	    makethumb_file;;
	*)
	    echo &quot;No thumbnail for $f&quot;;;
    esac
done
</pre>



<p>Die Befehle <code>convert</code> und <code>exiftran</code> entstammen den Debian-Paketen
<a href="http://packages.debian.org/imagemagick">imagemagick</a> resp.
<a href="http://packages.debian.org/exiftran">exiftran</a>.</p>

<p>Das Spezielle hier ist die Fallunterscheidung nach Dateityp. <span class="caps">EXIF</span>-Thumbnails
können natürlich nur in <span class="caps">JPEG</span>-Dateien direkt gespeichert werden, alle anderen
Bildformate brauchen eine externe Vorschaudatei.</p>

<h4 id="mk800">mk800</h4>



<pre class="file">#! /bin/sh

# $Id: mk800 301 2004-09-13 12:01:14Z bb $

make800x600() {
    bak=&quot;${f}~&quot;
    mv &quot;$f&quot; &quot;$bak&quot; || true
    convert -size 800x800 &quot;$bak&quot; -resize 800x800 -quality 80 -antialias &quot;$f&quot;
    touch -r &quot;$bak&quot; &quot;$f&quot;
}

for f; do
    make800x600
done
</pre>



<p>Ein Backup wird nur beim ersten Mal erstellt, und die originale
Modifikationszeit wird vom Script wiederhergestellt.</p>

<h4 id="mkportrait">mkportrait</h4>



<pre class="file">#! /bin/sh

# $Id: mkportrait 300 2004-09-13 12:00:33Z bb $

makeportrait() {
    exiftran -2ibp &quot;$f&quot;
}

for f; do
    makeportrait
done
</pre>



<p>Dieser Script (resp. die Option &#8220;-2&#8221; von <code>exiftran</code>) berücksichtigt die Tatsache,
dass ich die Kamera bei Portrait-Bildern nach links drehe.</p> ]]></description>
    </item>

    <item>
      <title>Unwort des Jahres</title>
      <link>http://www.drbeat.li/bblog/medien/2010/04/30#unwort_2004</link>
      <pubDate>Fri, 30 Apr 2010 13:06:00 GMT</pubDate>
      <description><![CDATA[ <p>Gestern am Radio gehört: &#8220;präsentiert von &#8230;, dem
[achtung, jetzt kommts:] Autoversicherungsprämienvergleichsdienst.&#8221;</p>

<p>Ich wusste ja immer, dass man in Deutsch zusammen gesetzte Nomen
bilden kann, aber deswegen muss man solche Monstrositäten doch nicht
am Radio in die halbe Welt hinaus posaunen&#8230; Tsk tsk!</p> ]]></description>
    </item>

    <item>
      <title>Verschwörungstheorien</title>
      <link>http://www.drbeat.li/bblog/allgemein/2010/04/30#conspiracy_theories</link>
      <pubDate>Fri, 30 Apr 2010 13:06:00 GMT</pubDate>
      <description><![CDATA[ <p><a href="http://www.rense.com/general15/tr.htm">Rense</a>
[via <a href="http://www.heise.de/tp/deutsch/special/wtc/11527/1.html">telepolis</a>
(in german)]:</p>

<blockquote xml:lang="en"><p>As one trader reported, &#8220;My God! The bottom has fallen out
and nobody calls it a crash. It&#8217;s like it&#8217;s your patriotic duty not to mention
the word. Hell, the Dow&#8217;s lost more than 1,500 points&#8212;that&#8217;s a CRASH.
But, if I&#8217;m overheard saying this, people look at me: `Where&#8217;s your
American flag? Remember who you are and what&#8217;s going on. Do you want to
help Osama bin Laden in his plot to destroy our economy?&#8217; Unbelievable!&#8221;<br />
But, as like many other media-brainwashed Americans, this trader was,
in his words, &#8220;going with the program. It&#8217;s not a crash, it&#8217;s a terrorist
event.&#8221;</p></blockquote>

<p>Wer Verschwörungstheorien liebt&#8230;</p>
 ]]></description>
    </item>

    <item>
      <title>Hundertster commit</title>
      <link>http://www.drbeat.li/bblog/software/2010/04/30#svn_rev100</link>
      <pubDate>Fri, 30 Apr 2010 13:06:00 GMT</pubDate>
      <description><![CDATA[ <p>Während dem Wochenende hat sich im Subversion-Repository, das fast mein
gesamtes <code>$HOME</code>-Verzeichnis beinhaltet, ein kleines Jubiläum ereignet:
Der <strong>einhundertste commit</strong>. Hier ist das diff (zugegebenermassen
nicht sehr blog-gen [ja, das war soeben meine erste Blog-spezifische Wortschöpfung!]):</p>

<pre class="shell">bb@bolli:~$ svn diff -r99:100

Property changes on: public_html/news
___________________________________________________________________
Name: svn:ignore
   - index.*

   + *.html
200*
</pre>
 ]]></description>
    </item>

    <item>
      <title>Microsofts brilliante Taktik</title>
      <link>http://www.drbeat.li/bblog/software/2010/04/30#reg_ms_users</link>
      <pubDate>Fri, 30 Apr 2010 13:06:00 GMT</pubDate>
      <description><![CDATA[ <p><a href="http://www.theregus.com/">The Register USA</a>:
<a href="http://www.theregus.com/content/55/26249.html">Microsoft
identifies source of Windows 2000 attacks</a></p>
<blockquote><p>Yesterday, though, Microsoft said the PSS Security Team has
finally identified the reason for the attacks - users.</p>
<p>&#8220;The attacks seek to take advantage of situations where standard precautions
have not been taken,&#8221; Microsoft said in an article posted on its web site.</p>
<p>The company listed standard precautionary measures not being adopted by
users, including the elimination of blank or weak administrator passwords,
disabling of guest accounts, running current anti-virus software with
up-to-date virus signature definitions, using firewalls to protect internal
servers including domain controllers, and maintaining up-to-date security
patches.</p></blockquote>

<p>Das ist natürlich eine brilliante Taktik. Mit solchen Aussagen wird den
Benutzern ein schlechtes Gewissen eingeredet. Kommt dann die nächste
Windows-Version mitsamt <a href="http://www.theregus.com/content/archive/25344.html">Palladium</a>
(in Verbindung mit <a href="http://www.theregus.com/content/3/26259.html">Intels
LaGrande-Chip</a>) und unter dem Label «Sicherer, Schützt Ihre Daten besser
als je zuvor», werden sich die meisten darauf stürzen (OK, sie werden ganz
einfach keine andere Wahl haben, da die neuen 12 GHz-Octiums nur mit
LaGrande erhältlich sein werden&#8230;). Nur ein paar Verwegene werden sich
fragen, was das ganze soll, da sie <a href="http://www.linux.org">ein Betriebssystem mit einem über
dreissig-jährigen, aber trotzdem sichereren Sicherheitsmodell</a> verwenden.</p>

<p>Für mich passt vieles in diesem grösseren Zusammenhang (DRM, Aufbewahren
von Email-Verbindungsdaten, «Fair use» ade, etc.) auch ganz gut in die
Nach-11.09-Atmosphäre, in der unter dem Vorwand der Terrorismusbekämpfung
eine ganze Menge neuer Regeln durchgesetzt werden können, die vorher
undenkbar gewesen wären.</p>
 ]]></description>
    </item>

    <item>
      <title>TV-Karte läuft endlich</title>
      <link>http://www.drbeat.li/bblog/software/2010/04/30#pinnacle_pctv</link>
      <pubDate>Fri, 30 Apr 2010 13:06:00 GMT</pubDate>
      <description><![CDATA[ <p>Nach langen Monaten ohne TV-Karte habe ich mich vor einigen Tagen
entschlossen, es nochmals zu versuchen. Bisher hatte immer ein IRQ-Konflikt
verhindert, dass ich ein Bild sehen konnte. Sendersuchlauf und Ton funktionierten.
Nach einer kleinen Umsteck-Orgie hatte ich es geschafft, dass sich die TV-Karte
(übrigens eine Pinnacle PCTV pro) den IRQ nur mit der Grafikkarte teilen musste,
das nützte mit den beigelegten Treibern aber nichts: immer noch kein Bild!</p>
<p>Als Pinnacles Web-Seite habe ich dann allerdings neue Software gefunden. Meine
mit der Karte gelieferte CD-ROM war Version 4.02 vom September 2000, aktuell auf dem
WWW war 5.5 vom März 2003! Eigentlich erstaunlich, dass die Treiber noch aktualisiert
werden&#8230; Nach dem 50MB-Download und einer komplizierten Installation war es dann so
weit: es funktionierte!</p>
 ]]></description>
    </item>

    <item>
      <title>OPML nach XHTML: funktioniert</title>
      <link>http://www.drbeat.li/bblog/software/blog/2010/04/30#blogroll_xsl_success</link>
      <pubDate>Fri, 30 Apr 2010 13:06:00 GMT</pubDate>
      <description><![CDATA[ <p>Ich habe mich nochmals hinter <a href="/bblog/2004/12/23#blogroll">das Problem der nicht funktionierenden <acronym title="eXtensible StyLesheet">XSL</acronym>-Transformation</a>
meiner <a href="/news/news.opml"><acronym title="Outline Processing Markup Language">OPML</acronym>-Datei</a> geklemmt und tatsächlich herausgefunden, woran es lag. Es fehlte der
Standard-Namespace, der die generierte Datei als <acronym title="eXtenslble HyperText Markup Language">XHTML</acronym> deklariert hätte.
Mit diesem neuen Vorspann in <a href="/news/opml.xsl">opml.xsl</a> geht es:</p>

<pre class="code">&lt;xsl:stylesheet
  xmlns:xsl=&quot;http://www.w3.org/1999/XSL/Transform&quot; version=&quot;1.0&quot;
  xmlns=&quot;http://www.w3.org/1999/xhtml&quot;
&gt;

&lt;xsl:output method=&quot;xml&quot; indent=&quot;yes&quot;
  doctype-system=&quot;http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd&quot;
  doctype-public=&quot;-//W3C//DTD XHTML 1.1//EN&quot;
/&gt;</pre>

<p>Weitere &#8220;Kleinigkeiten&#8221;, die mir aufgefallen sind:</p>


<ul>
<li><acronym title="Microsoft Internet Exploder 6">IE6</acronym> wendet ein per <code>&lt;xml-stylesheet&gt;</code>-processing instruction eingebundenes <acronym title="Cascading StyleSheet">CSS</acronym>-Stylesheet nicht an (wer hätte das gedacht <code>;-)</code></li>
<li>Wenn die <span class="caps">XSL</span>-output method auf <code>html</code> gesetzt wird, werden processing instructions nur mit > beendet, nicht mit ?>.</li>
<li>Es ist möglich, in <span class="caps">XHTML </span><acronym title="PHP: Hypertext Processor">PHP</acronym> einzubetten, wenn das <span class="caps">PHP</span>-Flag <code>short_open_tag</code> auf <code>false</code> gesetzt wird. Andernfalls reklamiert <span class="caps">PHP </span>bereits bei der <span class="caps">XML</span>-Deklaration einen Syntax-Fehler.</li>
</ul>

 ]]></description>
    </item>

    <item>
      <title>Endlich: die Blogroll am rechten Rand!</title>
      <link>http://www.drbeat.li/bblog/software/blog/2010/04/30#blogroll</link>
      <pubDate>Fri, 30 Apr 2010 13:06:00 GMT</pubDate>
      <description><![CDATA[ <p>Endlich habe ich es geschafft, meine Blogroll am rechten Rand zu
verewigen. Grundlage ist das <a href="/news/news.opml"><span class="caps">OPML</span>-File</a>, das auch
von <a href="/py/plagg/">plagg</a> gelesen wird. Mit Hilfe einer
<a href="/news/blogroll.xsl"><acronym title="eXtensible Style sheet">XSL</acronym>-Transformation</a> mache ich aus
news.opml ein <acronym title="eXtensible HyperText Markup Language">XHTML</acronym>-Fragment, das von
<acronym title="PHP: Hypertext Preprocessor">PHP</acronym> an der entsprechenden Stelle eingefügt wird.</p>

<p>Dies ist das Transformations-File:</p>



<pre class="file">&lt;xsl:stylesheet xmlns:xsl=&quot;http://www.w3.org/1999/XSL/Transform&quot; version=&quot;1.0&quot;&gt;

&lt;xsl:output method=&quot;xml&quot; indent=&quot;no&quot; standalone=&quot;yes&quot;/&gt;

&lt;xsl:template match=&quot;head&quot;/&gt;

&lt;xsl:template match=&quot;body&quot;&gt;
  &lt;ul class=&quot;blogroll&quot;&gt;&lt;xsl:apply-templates/&gt;&lt;/ul&gt;
&lt;/xsl:template&gt;

&lt;xsl:template match=&quot;outline&quot;&gt;
  &lt;li&gt;&lt;xsl:choose&gt;
    &lt;xsl:when test='@htmlUrl != &quot;&quot;'&gt;
      &lt;a href=&quot;{@htmlUrl}&quot;&gt;&lt;xsl:value-of select=&quot;@text&quot;/&gt;&lt;/a&gt;
    &lt;/xsl:when&gt;
    &lt;xsl:otherwise&gt;
      &lt;xsl:value-of select=&quot;@text&quot;/&gt;
    &lt;/xsl:otherwise&gt;
  &lt;/xsl:choose&gt;
  &lt;xsl:choose&gt;
    &lt;xsl:when test='@type = &quot;rss&quot;'&gt; (&lt;a href=&quot;{@xmlUrl}&quot;&gt;RSS&lt;/a&gt;)&lt;/xsl:when&gt;
    &lt;xsl:when test='@type = &quot;x-plagg-html&quot;'/&gt;
    &lt;xsl:when test='@type = &quot;x-plagg-computed&quot;'/&gt;
    &lt;xsl:otherwise&gt;
      &lt;ul&gt;&lt;xsl:apply-templates/&gt;&lt;/ul&gt;
    &lt;/xsl:otherwise&gt;
  &lt;/xsl:choose&gt;&lt;/li&gt;
&lt;/xsl:template&gt;

&lt;/xsl:stylesheet&gt;</pre>



<p>Und hier das Makefile, das mir nach Änderungen einen Haufen Schreibarbeit
spart: (habe ich eigentlich schon einmal gesagt, dass Programmierer
im Grunde genommen alle ziemlich faul sind, wenn es um automatisierbare
Abläufe geht? ;-)</p>



<pre class="file">blogroll.inc: blogroll.xsl news.opml
	xmlstarlet tr $^ | sed -e '1,3d' &amp;gt;$@</pre>



<p>Dieser <acronym title="Cascading Style Sheets">CSS</acronym>-Abschnitt formatiert die Liste schliesslich:</p>



<pre class="file">.blogroll {
	font-size: x-small;
    	margin-left: 0;
	padding-left: 0;
}

.blogroll ul {
	padding-left: 1em;
}

.blogroll li {
	list-style-type: none;
}</pre>



<p>Ich habe auch bereits versucht, die <span class="caps">OPML</span>-Datei direkt als <span class="caps">XML</span>-Datei mit
einem Stylesheet zu versehen, bin dabei aber nicht ganz ans Ziel gelangt.
Das Ergebnis sah immer so aus, wie wenn der Browser nur mein Stylesheet
anwendet, nicht aber das default <span class="caps">HTML</span>-Stylesheet:</p>

<p><img src="/pic/blog/blogroll.png" alt="" /></p> ]]></description>
    </item>

    <item>
      <title>Mehr zum Thema DRM</title>
      <link>http://www.drbeat.li/bblog/allgemein/2010/04/30#lessig_drm</link>
      <pubDate>Fri, 30 Apr 2010 13:06:00 GMT</pubDate>
      <description><![CDATA[ <p><a href="http://www.businessweek.com/">BusinessWeek</a> hat einen
<a href="http://www.businessweek.com/magazine/content/02_19/b3782610.htm">Artikel</a>
mit einem Interview mit Larry Lessig (Rechtsprofessor in Stanford) zur
Zukunft des Internet
[via <a href="http://doc.weblogs.com/2002/09/13#uglinessInside">Doc
Searls</a>].</p>

<p>Auch der <a href="http://www.redherring.com/">Red Herring</a> hat
<a href="http://www.redherring.com/insider/2002/09/codification091002.html">einen
Artikel</a> von Lessig, dieser ist Microsofts
Palladium-Iniviative gegenüber&mdash;unerwarteterweise&mdash;recht positiv
eingestellt.</p>
 ]]></description>
    </item>

    <item>
      <title>Meine Patches für blosxom und blagg</title>
      <link>http://www.drbeat.li/bblog/software/blog/2010/04/30#rael_patches</link>
      <pubDate>Fri, 30 Apr 2010 13:06:00 GMT</pubDate>
      <description><![CDATA[ <p>Gestern abend habe ich meine Patches für blosxom und blagg an Rael
Dornfest geschickt. Hier sind sie für die Nachwelt:</p>
<pre class="code" xml:lang="en">blosxom changes:
  * Build the escape map and regexp only once.
  * Allow the user to override the blog attributes from the blosxom.conf
    file in the blog directory.
  * Allow the user to define his own date and time formats. This is done
    by changing the content/date and content/time templates.
  * Add a save_title variable to be used in the Google search string.
  * Make the default templates more accessible: The blog title is a &lt;h1&gt;,
    dates are &lt;h2&gt;s, entry titles are &lt;h3&gt;s.

--- blosxom.orig	2002-06-04 04:59:31.000000000 +0200
+++ blosxom	2002-09-05 00:17:09.000000000 +0200
@@ -5,7 +5,7 @@
 # Version: 0+4i
 # Home/Docs/Licensing: http://www.oreillynet.com/~rael/lang/perl/blosxom/
 
-# --- Configurable variables -----
+# --- Configurable variables, may be overridden by blosxom.conf file -----
 
 # What's my blog's title?
 my $blog_title = 'Blosxom';
@@ -29,6 +29,7 @@
 use FileHandle;
 use File::stat;
 use Time::localtime;
+use POSIX qw(strftime);
 use CGI qw/:standard :netscape/;
 
 # Take a gander at HTTP's PATH_INFO for optional blog name, archive yr/mo/day
@@ -53,6 +54,21 @@
 	$template{$ct}{$comp} = $txt;
 }
 
+# Override blog attributes from a file in the blog directory
+if (-r "$datadir/blosxom.conf") {
+	$fh-&gt;open("$datadir/blosxom.conf");
+	foreach (&lt;$fh&gt;) {
+		$blog_title = $1 if m/^title:\s*(.*)/i;
+		$blog_description = $1 if m/^description:\s*(.*)/i;
+		$blog_language = $1 if m/^language:\s*(\w+)/i;
+		$num_entries = $1 if m/^entries:\s*(\d+)/i;
+	}
+	$fh-&gt;close;
+}
+
+my %escape = ('&lt;'=&gt;'&amp;lt;', '&gt;'=&gt;'&amp;gt;', '&amp;'=&gt;'&amp;amp;', '"'=&gt;'&amp;quot;');  
+my $escape_re  = join '|' =&gt; keys %escape;
+
 # Header
 print header($content_type);
 my $head = join '', $content_type eq 'text/html' &amp;&amp; $fh-&gt;open("&lt; $datadir/head.html") ? &lt;$fh&gt; : $template{$content_type}{'head'};
@@ -64,31 +80,34 @@
 foreach ( 
 	sort { return -M "$datadir/$a" &lt;=&gt; -M "$datadir/$b"; } 
 	grep /.txt$/, $dh-&gt;read
-	) {
+) {
 
 	last if $num_entries-- &lt;= 0 &amp;&amp; !$pi_yr;
 
 	my($fn) = ($_ =~ /^(.*)\.txt$/);
 
 	# Date fiddling for by-{year,month,day} archive views
-	my $mtime = ctime(stat("$datadir/$fn.txt")-&gt;mtime);
-	my($dw,$mo,$da,$ti,$yr) = ( $mtime =~ /(\w{3}) +(\w{3}) +(\d{1,2}) +(\d{2}:\d{2}):\d{2} +(\d{4})$/ );
+	my @mtime = @{localtime(stat("$datadir/$fn.txt")-&gt;mtime)};
+	my($yr,$mo,$da) = ($mtime[5] + 1900, $mtime[4] + 1, $mtime[3]);
 
 	next if $pi_yr &amp;&amp; $yr != $pi_yr; last if $pi_yr &amp;&amp; $yr &lt; $pi_yr; 
-	next if $pi_mo &amp;&amp; $mo ne ucfirst(lc $pi_mo);
+	next if $pi_mo &amp;&amp; $mo != $pi_mo;
 	next if $pi_da &amp;&amp; $da != $pi_da; last if $pi_da &amp;&amp; $da &lt; $pi_da; 
 
-	$content_type eq 'text/html' &amp;&amp; $curdate ne "$dw, $da $mo $yr" &amp;&amp; 
-		print span({-class=&gt;'blosxomDate'}, $curdate = "$dw, $da $mo $yr"); 
+	my $newdate = strftime($template{'content'}{'date'}, @mtime);
+	my $ti = strftime($template{'content'}{'time'}, @mtime);
+	$content_type eq 'text/html' &amp;&amp; $curdate ne $newdate &amp;&amp; 
+		print h2({-class=&gt;'blosxomDate'}, $curdate = $newdate) . "\n\n";
 
 	# Entry
 	if (-T "$datadir/$fn.txt" &amp;&amp; $fh-&gt;open("&lt; $datadir/$fn.txt")) {
 		chomp(my $title = &lt;$fh&gt;);
+		my $save_title = $title;
+		$save_title =~ s/&lt;.*?&gt;//msg;	# remove all tags
+		$save_title = escapeHTML($save_title);
 		chomp(my $body = join '', &lt;$fh&gt;);
 		if ($content_type eq 'text/xml') {
 			# Escape &lt;, &gt;, and &amp;, and to produce valid RSS
-			my %escape = ('&lt;'=&gt;'&amp;lt;', '&gt;'=&gt;'&amp;gt;', '&amp;'=&gt;'&amp;amp;', '"'=&gt;'&amp;quot;');  
-			my $escape_re  = join '|' =&gt; keys %escape;
 			$title =~ s/($escape_re)/$escape{$1}/g;
 			$body =~ s/($escape_re)/$escape{$1}/g;
 		}
@@ -105,9 +124,11 @@
 
 # Default HTML and RSS template bits
 __DATA__
-text/html head &lt;html&gt;&lt;head&gt;&lt;link rel="alternate" type="type="application/rss+xml" title="RSS" href="$url/xml" /&gt;&lt;title&gt;Blosxom&lt;/title&gt;&lt;/head&gt;&lt;body&gt;&lt;center&gt;&lt;font size="+3"&gt;$blog_title&lt;/font&gt;&lt;/center&gt;&lt;p /&gt;
-text/html story &lt;p class="blosxomEntry"&gt;&lt;a name="$fn"&gt;&lt;span class="blosxomTitle"&gt;&lt;b&gt;$title&lt;/b&gt;&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;&lt;span class="blosxomBody"&gt;$body&lt;/span&gt;&lt;br /&gt;&lt;span class="blosxomTime"&gt;Posted at $ti&lt;/span&gt; &lt;a href="$url/$yr/$mo/$da#$fn"&gt;#&lt;/a&gt; &lt;a href="http://www.google.com/search?q=$title"&gt;G&lt;/a&gt;&lt;/p&gt;\n
-text/html foot &lt;p /&gt;&lt;center&gt;&lt;h6&gt;Powered -- for some narrow definition of powered -- by &lt;a href="http://www.oreillynet.com/~rael/lang/perl/blosxom/"&gt;Blosxom&lt;/a&gt;&lt;/h6&gt;&lt;/body&gt;&lt;/html&gt;
-text/xml head &lt;?xml version="1.0"?&gt;\n&lt;!-- name="generator" content="bloxsom/0+3i" --&gt;\n&lt;!DOCTYPE rss PUBLIC "-//Netscape Communications//DTD RSS 0.91//EN" "http://my.netscape.com/publish/formats/rss-0.91.dtd"&gt;\n\n&lt;rss version="0.91"&gt;\n  &lt;channel&gt;\n    &lt;title&gt;$blog_title&lt;/title&gt;\n    &lt;link&gt;$url&lt;/link&gt;\n    &lt;description&gt;$blog_description&lt;/description&gt;\n    &lt;language&gt;$blog_language&lt;/language&gt;\n
-text/xml story   &lt;item&gt;\n    &lt;title&gt;$title&lt;/title&gt;\n    &lt;link&gt;$url/$yr/$mo/$da#$fn&lt;/link&gt;\n    &lt;description&gt;$body&lt;/description&gt;\n  &lt;/item&gt;\n
-text/xml foot   &lt;/channel&gt;\n&lt;/rss&gt;
+text/html head &lt;html&gt;&lt;head&gt;&lt;link rel="alternate" type="type=application/rss+xml" title="RSS" href="$url/xml" /&gt;&lt;title&gt;Blosxom&lt;/title&gt;&lt;/head&gt;&lt;body&gt;&lt;h1&gt;$blog_title&lt;/h1&gt;&lt;p /&gt;
+text/html story &lt;div class="blosxomEntry"&gt;&lt;a name="$fn"&gt;&lt;h3 class="blosxomTitle"&gt;$title&lt;/h3&gt;&lt;/a&gt;&lt;span class="blosxomBody"&gt;$body&lt;/span&gt;&lt;br /&gt;&lt;span class="blosxomTime"&gt;Posted at $ti&lt;/span&gt; &lt;a href="$url/$yr/$mo/$da#$fn"&gt;#&lt;/a&gt; &lt;a href="http://www.google.com/search?q=$save_title"&gt;G&lt;/a&gt;&lt;/div&gt;\n
+text/html foot &lt;p /&gt;&lt;center&gt;&lt;h6&gt;Powered -- for some narrow definition of powered -- by &lt;a href="http://www.oreillynet.com/~rael/lang/perl/blosxom/"&gt;Blosxom&lt;/a&gt;&lt;/h6&gt;&lt;/body&gt;&lt;/html&gt;
+text/xml head	&lt;?xml version="1.0"?&gt;\n&lt;!-- name="generator" content="bloxsom/0+4i" --&gt;\n&lt;!DOCTYPE rss PUBLIC "-//Netscape Communications//DTD RSS 0.91//EN" "http://my.netscape.com/publish/formats/rss-0.91.dtd"&gt;\n\n&lt;rss version="0.91"&gt;\n\n&lt;channel&gt;\n&lt;title&gt;$blog_title&lt;/title&gt;\n&lt;link&gt;$url&lt;/link&gt;\n&lt;description&gt;$blog_description&lt;/description&gt;\n&lt;language&gt;$blog_language&lt;/language&gt;\n
+text/xml story	\n&lt;item&gt;\n  &lt;title&gt;$title&lt;/title&gt;\n  &lt;link&gt;$url/$yr/$mo/$da#$fn&lt;/link&gt;\n  &lt;description&gt;$body&lt;/description&gt;\n&lt;/item&gt;\n
+text/xml foot	\n&lt;/channel&gt;\n\n&lt;/rss&gt;
+content date %Y-%m-%d
+content time %H:%M
</pre>
<p />
<pre class="code" xml:lang="en">blagg changes:
  * Build the unescape hash and regexp only once.
  * Enter ! to blog the rest of this feed in automatic mode.
  * De-emphasize the feed separator line.
  * Make the parser RSS 0.94-compatible. This version uses the &lt;guid&gt; tag.
  * The order of the title, link/guid and description tags is not defined.
    Make the parser recognize this. This caught me on Mark Pilgrim's and
    Dave Winer's feeds (http://diveintomark.org and http://www.scripting.com).
  * Make the entry's title the link to the article, remove the "(link)".
    IMO it's more intuitive to click on the title.
    This change needs the related $safe_title change in blosxom.

--- blagg.orig	2002-04-30 19:13:22.000000000 +0200
+++ blagg	2002-09-04 21:24:04.000000000 +0200
@@ -38,26 +38,36 @@
 # Does this blog specify any RSS feeds to watch?
 $fh-&gt;open("&lt; $datadir/rss.dat") or exit;
 
+my %unescape = ('&amp;lt;'=&gt;'&lt;', '&amp;gt;'=&gt;'&gt;', '&amp;amp;'=&gt;'&amp;', '&amp;quot;'=&gt;'"'); 
+my $unescape_re = join '|' =&gt; keys %unescape;
+
+my $yn = param('-mode') eq 'automatic' ? '!!' : '';
+
 # Loop through the feeds in the list and aggregate
 foreach ( &lt;$fh&gt; ) {
 	my($f_nick,$f_url,$f_mode) = split;
 	next unless $f_nick =~ /^\w+$/ &amp;&amp; $f_url =~ m#^\w+://# &amp;&amp; $f_mode =~ /^(interactive|automatic)$/ &amp;&amp; $f_mode eq param('-mode');
 
 	$fh-&gt;open("$get_prog '$f_url' |") || next;
-	print "\n_____${f_url}_______________\n";
+	print "\n*** $f_url\n";
 	my $rss = join '', &lt;$fh&gt;;
 	$fh-&gt;close;
 
 	# Feed's title and link
 	my($f_title, $f_link) = ($rss =~ m#&lt;title&gt;(.*?)&lt;/title&gt;.*?&lt;link&gt;(.*?)&lt;/link&gt;#ms);
 
-	# RSS items' title, link, and description
-	while ( $rss =~ m{&lt;item(?!s).*?&gt;.*?(?:&lt;title&gt;(.*?)&lt;/title&gt;.*?)?(?:&lt;link&gt;(.*?)&lt;/link&gt;.*?)?(?:&lt;description&gt;(.*?)&lt;/description&gt;.*?)?&lt;/item&gt;}mgis ) {
-		my($i_title, $i_link, $i_desc, $i_fn) = ($1||'', $2||'', $3||'', undef);
+	# RSS items
+	while ( $rss =~ m{&lt;item(?!s).*?&gt;(.*?)&lt;/item(?!s)&gt;}mgis ) {
+
+		# Item's title, link and description
+		my $f_item = $1;
+		$_ = $1;
+		my($i_title, $i_link, $i_desc, $i_fn) = (undef, '', '', undef);
+		$i_title = $1 if $f_item =~ m{&lt;title&gt;(.*?)&lt;/title&gt;}mis;
+		$i_link = $2 if $f_item =~ m{&lt;(link|guid.*?)&gt;(.*?)&lt;/(link|guid)&gt;}mis;
+		$i_desc = $1 if $f_item =~ m{&lt;description&gt;(.*?)&lt;/description&gt;}mis;
 
 		# Unescape &amp;amp; &amp;lt; &amp;gt; to produce useful HTML
-		my %unescape = ('&amp;lt;'=&gt;'&lt;', '&amp;gt;'=&gt;'&gt;', '&amp;amp;'=&gt;'&amp;', '&amp;quot;'=&gt;'"'); 
-		my $unescape_re = join '|' =&gt; keys %unescape;
 		$i_title &amp;&amp; $i_title =~ s/($unescape_re)/$unescape{$1}/g;
 		$i_desc &amp;&amp; $i_desc =~ s/($unescape_re)/$unescape{$1}/g;
 
@@ -76,23 +86,22 @@
 		# Skip already-aggregated items (aka filename already exists)
 		next if -e $i_fn;
 
-		my $item = "$i_title\n$i_desc&lt;br /&gt;\n(" . a({-href=&gt;$i_link},'link') . ") [" . a({-href=&gt;$f_link}, $f_title) . "]\n";
-		my $yn = '';
-		if (param('-mode') eq 'automatic') { 
-			$yn = 'y';
-		} else { 
-			print qq{\n"$i_title"\n[$i_link]\n$i_desc\n\nDo you want to blog this item? (y|n|q)?}; 
+		my $item = a({-href=&gt;$i_link}, $i_title) . "\n$i_desc&lt;br /&gt;\n[" .
+			a({-href=&gt;$f_link}, $f_title) . "]\n";
+		if ($yn !~ /!/) {
+			print qq{\n"$i_title"\n[$i_link]\n$i_desc\n\nDo you want to blog this item? (y|n|q|!)?}; 
 			while (&lt;STDIN&gt;) { 
-				/^([ynq])$/ and $yn = $1, last;
+				/^([ynq!])$/ and $yn = $1, last;
 			};
 		}
 		$yn eq 'q' &amp;&amp; exit;
 		# Save entry to file (and via plug-in if specified)
-		$yn eq 'y' &amp;&amp; 
+		$yn =~ /[y!]/ &amp;&amp; 
 			$fh-&gt;open("&gt; $i_fn") &amp;&amp; print($fh $item) &amp;&amp; $fh-&gt;close() &amp;&amp;
 			param('-plugin') &amp;&amp; 
 			blaggplug::post($i_title, $i_link, $i_desc, $f_title, $f_link);
 	}
+	$yn = '' if $yn ne '!!';
 }
 
 # Clean up plugin, if specified.
</pre>
 ]]></description>
    </item>

    <item>
      <title>Ist es Zeit für einen neuen TV-Sender?</title>
      <link>http://www.drbeat.li/bblog/allgemein/2010/04/30#war_tv</link>
      <pubDate>Fri, 30 Apr 2010 13:06:00 GMT</pubDate>
      <description><![CDATA[ <p>Heute abend nach unserem wöchentlichen
<a href="http://www.volleyballbargen.ch.vu">Volleyball</a>
hatten wir eine Idee: Wie wäre es, wenn ein Sender ausschliesslich über alle Kriege
berichten würde, dann hätten alle anderen Sender wieder Zeit, sich um die normale
Berichterstattung zu kümmern?! In Anlehnung an EuroSport könnte er sich ja WorldWar nennen&#8230;</p>
 ]]></description>
    </item>

    <item>
      <title>Kurze Album-URLs</title>
      <link>http://www.drbeat.li/bblog/software/2010/04/30#album_urls</link>
      <pubDate>Fri, 30 Apr 2010 13:06:00 GMT</pubDate>
      <description><![CDATA[ <p>In einem (vielleicht ineffektiven) Versuch, mein <a href="/album/">Album</a>
von Google &amp; Co. besser suchbar zu machen<sup class="footnote"><a href="#fn1">1</a></sup>, habe ich heute alle
<acronym title="Universal Resource Locator">URL</acronym>s umgestellt: Was vorher offensichtlicherweise
eine Query an den <a href="/php/source.php?src=album%2Findex.php">Album-Skript</a>
respektive dessen <a href="/php/source.php?src=album%2Falbum.inc.php">Library</a> war,
ist jetzt eine normale, &#8220;statische&#8221; URL, die von <a href="http://httpd.apache.org/docs/mod/mod_rewrite.html">mod_rewrite</a>
in die alte Form umgewandelt wird.</p>

<p>Die Transformationen im einzelnen:</p>

<table><tr><td>Typ</td><td>alt</td><td>neu</td></tr><tr><td>Albumübersicht</td><td>/album/?album=Musik</td><td>/album/-Musik</td></tr><tr><td>Bild</td><td>/album/?album=Musik&amp;image=bild.jpg</td><td>/album/-image/Musik/bild.jpg</td></tr><tr><td>Vorschau</td><td>/album/?album=Musik&amp;thumb=bild.jpg</td><td>/album/-thumb/Musik/bild.jpg</td></tr></table>

<p>Diese Zeilen in <code>.htaccess</code> erledigen das (habe ich schon erwähnt, dass ich
<a href="http://en.wikipedia.org/wiki/Regular_expression">Regular Expressions</a> etwas vom Geilsten
in der gesamten Informatik finde? :-):</p>

<pre class="code">RewriteEngine On
RewriteRule ^-((image)|(thumb))/(.+)/([^/]+)$ ?album=$4&amp;$1=$5 [L]
RewriteRule ^-(.+)$ ?album=$1</pre>

<p>Bei der Syntax have ich mich von <a href="http://www.tbray.org/ongoing/">Tim Bray&#8217;s Blog</a>
<a href="http://www.tbray.org/ongoing/When/200x/2005/07/08/PhotoShop-Abuse">beeinflussen</a> lassen.</p>

<p>Nachdem dieses Regeln funktioniert hatten, war es ein Leichtes, die Album-Software
und das blosxom-Plugin dazu zu bringen, anstelle der alten solche Links zu generieren.</p>

<p class="footnote" id="fn1"><sup>1</sup> Es ist eine Tatsache, dass die Crawler mit Vorliebe statische <span class="caps">URL</span>s durchsuchen!</p> ]]></description>
    </item>

  </channel>
</rss>
