Kategorie-Archiv:

Blogging

Auswertung der Blogparade über alten Computer-Kram

Blogparade alter Computer-Kram Vor einem Monat hatte ich euch in meiner Blogparade gebeten, etwas über euren alten Computer-Kram – Literatur, Software, Hardware – zu erzählen und sie zu zeigen. Und wie sich’s gehört, gibt’s jetzt die Auswertung dazu.

Neben einigen Wortmeldungen in den Kommentaren, die berichteten, was sie schon alles entsorgt haben, haben sich fünf Teilnehmer gefunden, die ihren Kram präsentierten – kurioserweise alles Blogs, die ich zuvor noch nicht kannte:

  • Bei abgekliert gibt’s C64- und Amiga-Zeitschriften (ab 1984), Amiga-Handbücher und einige Nicht-Computer-Elektronik. (Und eine Atari-VCS-Spielekonsole, die außerhalb des Bereichs liegt, den ich für diese Parade wollte.)
  • Computersammler Wingi zeigt ein Buch über ALGOL 60 von 1969, PC-Spiele-Disketten von 1979 und einen 1984er CP/M-Computer mit eingebautem Monitor namens Kaypro 10.
  • Der dritte Teilnehmer von Internet-DSL-Tarife.de hebt aus Platz- und Aktualitätsgründen keine alte Literatur auf und hat auch Disketten abgeschafft, dafür neben einer Ersatztastatur noch alte computerbeige Lautsprecher im Einsatz.
  • blariog.net hebt noch ein MS-DOS-5-Buch von 1991 als DOS-Befehlsreferenz auf und hat neben den zugehörigen Disketten noch welche von Windows 3.1 und ein Spiel von ca. 1993; als alte noch verwendete Hardware gibt’s „nur“ ein 2004 gekauftes Powerbook.
  • Und zu guter letzt gibt’s bei zimmerpflanzen.ws noch Hardware als Pflanzenständer…

Überall gibt es Fotos zu sehen und z.T. neben dem Erwähnten noch weitere Infos – wen das Thema interessiert, sollte die Beiträge also selbst schnell ansurfen.

Damit danke ich allen Teilnehmern – die zwar zahlreicher hätten sein können, aber dafür können die, die teilgenommen haben natürlich nichts^^ – fürs teilnehmen. :) (Und werde mir mal überlegen, ob ich ein Thema für eine Blogparade finde, die mehr Leute anzieht…)

Etwas fürs Archiv (1):
Geordnetes Monatsarchiv

Monate und Jahre Der erste von zwei weitereren kleinen WordPress-Tips, diesmal für die Archivseite. Dorthin packt man ja gerne eine Übersicht über alle Beiträge nach Monaten und nach Kategorien, und in einigen Themes steckt so eine Funktionalität bereits drin, einige Plugins bieten ebenfalls diverse Funktionen.

Wie man solche Archive mit Bordmitteln, nämlich der Funtion wp_get_archives() und einer Theme-Template-Seite macht, hat etwa Perun im Januar beschrieben; für das Kategorienarchiv benutze ich diese auch. Für mein Monatsarchiv hab ich aber „natürlich“ eine eigene Funktion geschrieben, die mir eine schönere Darstellung nach Jahren gruppiert bietet – darum geht es in diesem Beitrag. In ein paar Tagen zeige ich euch dann den Code für die Schlagwort-Mehrfachauswahl, die ihr bereits auf der Archivseite findet.

Stellt sich nur generell die Frage, ob allzu viele Besucher diese Archiv-Funktionalität auch wirklich nutzen… aber egal, im Zweifelsfall betrachtet’s man einfach als ein bisschen Blog-Spielerei.^^

In diesem Fall hab ich den PHP-Code direkt in die Seite geschrieben (im HTML-Editor von WordPress) – weshalb auch das <?php...?>-Tag mittendrin steht –, da ich hier eh schon das Plugin Exec-PHP einsetze, das ebendies ermöglicht1. Alternativ kann man den Code natürlich auch anderweitig unterbringen, etwa über entsprechende Unterscheidungen im Theme oder komfortablerweise per Template – siehe Peruns Artikel.

Wie ihr auf dem Bild oben erkennen dürftet, sind hier Monate vor dem Blogbeginn und nach dem aktuellen Datum gar nicht dargestellt und Lücken der Regelmäßigkeit halber grau; zudem – was aber nur eine Stylingfrage ist – gibt’s keine unnötigen ansonsten listentypischen • Bullets und Einrückungen. Und in Klammern steht die Anzahl der Beiträge.

Das ist der Code dazu:

<style type="text/css">
div.yeararch { float: left; color:#777; margin-right: 2em; }
ul.montharch { list-style-type: none; padding-left: 0px; }
</style>

<?php global $wpdb;
$mnames = array (1=>'Januar', 2=>'Februar', 3=>'März', 4=>'April', 5=>'Mai', 6=>'Juni', 7=>'Juli', 8=>'August', 9=>'September', 10=>'Oktober', 11=>'November', 12=>'Dezember');
$started = false;
$years = $wpdb->get_results("SELECT YEAR(post_date) AS year, COUNT(*) AS count
FROM $wpdb->posts
WHERE post_type='post'
  AND post_status='publish'
GROUP BY year
ORDER BY year ASC");
foreach ($years as $y) {
  echo '<div class="yeararch"><h4><a href="/'.$y->year.'/">'.$y->year.'</a> <small>('.$y->count.')</small></h4><ul class="montharch">';
  $months = $wpdb->get_results("SELECT MONTH(post_date) AS month, COUNT(*) AS count
  FROM $wpdb->posts
  WHERE post_type='post'
    AND post_status='publish'
    AND YEAR(post_date)=$y->year
  GROUP BY month
  ORDER BY month ASC");
  $ms = array();
  foreach ($months as $m) { $ms[$m->month] = $m->count; }
  for ($i=1; $i<=12; $i++) {
    $m0 = sprintf('%02d',$i);
    $mname = $mnames[$i];
    if ($ms[$i]>0) {
      echo '<li><a href="/'.$y->year.'/'.$m0.'/">'.$mname.'</a> ('.$ms[$i].')</li>';
      $started = true;
    } else {
      if ($y->year<date('Y') || $i<=date('n')) {
        if (!$started) echo '<li>&nbsp;</li>'; else echo '<li>'.$mname.' (0)</li>';
      }
    }
  }
  echo "</ul></div>\n";
}
?>

<div style="clear:both;"></div>

Großes Hexenwerk ist der Code nicht: Nach der kleinen CSS-Definition (direkt auf der Seite, da ja nur hier benötigt) schaut der PHP-Code erst in der Datenbank nach, welche Jahre denn in Frage kommen – YEAR(post_date) AS year ... GROUP BY year – und nimmt auch die Beitragsanzahl – COUNT(*) AS count gleich mit.

Für jedes Jahr wird dann ein div-Container generiert, die dank des CSS am Anfang nebeneinander stehen – so viele wie halt auf die Seite passen, bei mir geht’s 2011 dann darunter weiter; ihr könnt ja mit den Abständen (margin-right) spielen. (Der div am Ende mit clear:both; sorgt dafür, dass nachfolgender Text darunter und nicht daneben landet.)

Dann gibt’s für jedes Jahr natürlich eine analoge Datenbank-Abfrage für die nach Monaten gruppierten Beiträge des jeweiligen Jahres, die dann nacheinander ausgegeben werden. Da diese Abfrage nur so viele Array-Einträge liefert, wie Monate benutzt wurden, sortiere ich sie ins Array $ms um, um in der Schleife alle Monate von 1 bis 12 durchlaufen und für leere Monate je nachdem, ob das Blog noch gar nicht begonnen wurde (!$started) oder ob es eine Lücke ist, eine Leerzeile bzw. eine nicht verlinkte Zeile mit der traurigen Null ausgeben zu können.

(Die Monatsnamen bekäme man an sich auch eleganter über PHP-Funktionen, aber irgendwie hatte ich da Probleme im Zusammenhang mit meiner Sprachumschaltung, deshalb die Lösung mit dem $mnames-Array.)

Bei den Links zu den Monatsarchivseiten geht der Code davon aus, dass sie dem Schema /2009/12/ folgen – wer ein anderes Schema mit pretty permalinks verwendet (kommt das denn vor?), muss sie entsprechend anpassen, ebenso wer die „unschöne“ Variante mit ? und Argumenten verwendet; das wäre dann ?m=200912 etc.

So, das war der erste Beitrag zum Archiv – wer Fragen, Anregungen, Verbesserungsvorschläge o.ä. hat, möge jetzt sprechen oder für immer schweigen… Wie erwähnt geht’s dann demnächst um die Mehrfachauswahl bei den Schlagwörtern, aber vielleicht schiebe ich auch noch die Einbindung von WP.com-Stats anstelle von WP-PostViews für die Ermittlung der beliebtesten Beiträge dazwischen, wie Robert angeregt hatte. Mal sehen.

  1. Nebenwirkung: Man muss den HTML-Editor von WordPress verwenden, weil der visuelle nicht mehr möglich ist. ↺

Links und Video der Woche (2010/21+22)

  1. ob ich die Buttons auf den Index-/Archivseiten weglassen soll? ↺

WordPress: Hinweis bei Spam-Falscherkennung

Papierspam ?! Und wieder eine kleine Code-für-das-Blog-Lösung von mir, die zwar nicht unbedingt perfekt ist, aber doch hilfreich sein kann…

Viele sind dem Problem schon begegnet, dass ein Kommentar fälschlicherweise im Spam landet, weil der Spamfilter – sei es das bekannte Akismet (wie bei meinem Blog), sei es ein anderes Plugin oder einfach eine versehentlich zu scharf eingestellte Blacklist – übereifrig ist. Auf meinem Blog kommt so ein false positive im Schnitt alle drei Wochen einmal vor.

Der erfahrene Blogger oder Blogkommentierer weiß, dass er dann i.d.R. einfach darauf warten muss, dass der Blogbetreiber den Kommentar (hoffentlich) herausfischt und freigibt. Der unerfahrenere Kommentierende steht aber nicht selten wie der (Pfingst-)Ochse vor dem Berg, wenn er nach dem Absenden des Kommentars oben auf der Seite landet und auch beim Runterscrollen seinen Kommentar nicht findet; manche versuchen es dann auch erneut, manche kommen vielleicht gar nicht wieder.

Ein Hinweis könnte da helfen – doch WordPress bietet da (anders als bei noch zu moderierenden Kommentaren) keinen. Die normale Schleife, die die Kommentare ausgibt, weiß auch nicht direkt, welcher Kommentar aktuell vom Aufrufenden ist, denn der Teil der URL, in der das steht – #comment-123, was ja insbesondere für die Positionierung der Ansicht im Browser sorgt1 – ist nicht Teil der Anforderung, die der Server sieht, sondern bleibt im Browser.

Nun könnte man vielleicht die Kommentarnummer bei der Weiterleitung nach dem Abschicken auch als &-Parameter in die URL einbauen (und dann in der Ausgabeschleife mit abfragen), doch finde ich das irgendwie unschön – wer weiß, ob dadurch nicht mehrere solche URLs durch die Suchmaschinen geistern. Mir kamen zwei andere Ideen, die ich hier vorstellen will:

Lösung 1: Spam-Kommentar von derselben IP-Adresse?

Die erste Idee: Man schaut nach der Kommentarausgabe nach, ob in den letzten paar Minuten ein Spam-Kommentar von derselben IP-Adresse kam, von der die aktuelle Anfrage kommt. Das sieht dann in einer Funktion für die functions.php des Themes so aus:

function ag_spammed_comment ($gotcomments) {
    global $wpdb, $post;
    $spamcom = $wpdb->get_results ("
        SELECT * FROM $wpdb->comments
        WHERE comment_post_ID = '$post->ID'
          AND comment_author_IP = '".$_SERVER['REMOTE_ADDR']."'
          AND comment_approved = 'spam'
          AND comment_type = ''
          AND TIME_TO_SEC(TIMEDIFF(NOW(),comment_date))<120");
    if ($spamcom) {
        if (!$gotcomments) echo '<ol class="commentlist">';
        foreach ($spamcom as $sc) {
            echo '<li id="comment-'.$sc->comment_ID.'" class="comment caughtasspam">'.
            '<strong>Anscheinend wurde Ihr Kommentar von der Automatik als Spam markiert.</strong><br/>'.
            'Falls das ein Versehen war: bitte etwas Geduld, bis er manuell freigeschaltet wird.'.
            '</li>'."\n";
        }
        if (!$gotcomments) echo '</ol>';
    }
}

Aufzurufen dann in der comments.php mit ag_spammed_comment (true); (in <?php ?> eingeschlossen) nach der Ausgabe der vorhandenen Kommentare und mit false statt true im Zweig für den Fall, dass es noch keine Kommentare gibt – wobei diese Unterscheidung nur nötig ist, wenn man den Hinweis wie einen Kommentar in die ol/ul mit einbinden (und gestalten) will; wer einen separaten div-Block verwenden will, kann sich die Unterscheidung sparen.

Die Klasse .caughtasspam Ist dann natürlich noch in der style.css angemessen (z.B. mit rotem Rahmen) zu formatieren.

Allerdings gibt’s da ein…

Problem: Der Cache

Wer ein Cache-Plugin wie WP Super Cache einsetzt, das die erzeugten Seiten zwischenspeichert, steht dann vor dem Problem, dass dieses – eigentlich sinnvollerweise – den Cache der betroffenen Seite bei einem Spam-Kommentar nicht invalidiert, d.h. noch dieselbe alte Seite ausliefert, ohne dass der Code oben zur Ausführung kommt und seinen Hinweis ausgeben kann.

Eine Lösung dafür: Man ändert das Plugin so, dass Spam-Kommentare (aber nicht Spam-Trackbacks) doch die gecachete Seite löschen. Das geht bei WP Super Cache in wp-cache-phase2.php in der function wp_cache_get_postid_from_comment, wo man nach

} elseif ( $comment['comment_approved'] == 'spam' ) { 

die beiden Zeilen

if ( isset( $GLOBALS[ 'wp_super_cache_debug' ] ) && $GLOBALS[ 'wp_super_cache_debug' ] ) wp_cache_debug( "Spam comment. Don't delete any cache files.", 4 );
return $postid;

durch diese ersetzt:

//--ag: for false-positive message
if ( $comment['comment_type'] == '' ) {
    if ( isset( $GLOBALS[ 'wp_super_cache_debug' ] ) && $GLOBALS[ 'wp_super_cache_debug' ] ) wp_cache_debug( "Spam comment. But update cache for post $postid to allow for false-positive message.", 4 );
    return wp_cache_post_change($postid);
} else {
    if ( isset( $GLOBALS[ 'wp_super_cache_debug' ] ) && $GLOBALS[ 'wp_super_cache_debug' ] ) wp_cache_debug( "Spam trackback. Don't delete any cache files.", 4 );
    return $postid;
}

Dann funktioniert’s auch mit dem Hinweis. Allerdings auf Kosten der Performance, falls zufällig echte Spammer viele Spamkommentare auf eine Seite abzuladen versuchen, die auch häufig von Besuchern aufgerufen wird – was bei den meisten Blogs aber nicht so häufig sein dürfte, denke ich.

Der größere Nachteil ist m.E., dass man ein (weiteres?) Plugin hat, bei dem man bei einem Update aufpassen muss, dass man die Änderungen auch in die neue Version übernimmt. Diesen Aufwand will ich mir sparen, deshalb habe ich hier eine andere Lösung eingebaut:

Lösung 2: JavaScript (mit jQuery)

Diese Lösung funktioniert natürlich nicht, wenn der Kommentator JavaScript deaktiviert hat – ein Nachteil, den ich hier aber in Kauf nehme in der Hoffnung, dass diese Kombination selten genug auftritt – dafür funktioniert sie aber auch, wenn jemand über für jede Anfrage wechselnde Proxy-Server surft.

Hier gibt’s sogar zwei Lösungsvarianten, deren erste ich nur kurz anschneiden will: Man ändert mittels comment_post_redirect-Filter (der von wp-comments-post.php aufgerufen wird) die Ziel-URL so, dass bei einem Spam-Kommentar das #comment-123 durch etwas wie #spammed ersetzt wird, und sorgt dann per JavaScript dafür, dass ein im Theme eingebauter, anfangs auf display: none gesetzter (oder leerer) Hinweisblock eingeblendet (oder mit dem Hinweistext gefüllt) wird, wenn #spammed in der URL vorkommt – denn anders als der Server hat JavaScript auf diesen Teil Zugriff.

Variante 2, die auch hier eingebaut ist, kommt ohne einen solchen Filter aus und schaut einfach nach, ob es ein Element namens #comment-123 auf der (vollständig geladenen) Seite überhaupt gibt. Wenn nicht, wird der Hinweistext eingefügt (durch JavaScript deswegen, damit Suchmaschinen den Hinweis nicht indizieren):

<div id="spammedhint" class="comment caughtasspam" style="display:none;"></div>
<script type="text/javascript">
<!--
var theUrl = document.location.toString();
if (theUrl.match("#comment-")) {
    var theHash = theUrl.substr(theUrl.indexOf("#"));
    if (jQuery(theHash).length==0) {
        jQuery(document).ready(function() {
            jQuery("#spammedhint").html("<strong>Anscheinend wurde Dein Kommentar von der Automatik als Spam markiert.</strong><br/>"+
            "Falls das ein Versehen war: bitte etwas Geduld, bis er manuell freigeschaltet wird.").fadeIn();
            var targetOfs = jQuery("#spammedhint").offset().top;
            jQuery("html,body").animate({scrollTop: targetOfs-20}, 500);
        });
    }
}
//-->
</script>

Die Frage der Existenz wird mit if (jQuery(theHash).length==0) abgefragt, da jQuery() immer ein Objekt zurückliefert und ein ansonsten naheliegendes if (jQuery(theHash)) immer wahr ist. Mit der letzten jQuery-Zeile wird dann innerhalb 500 ms zum Hinweisblock gescrollt (bzw. knapp drüber); mit einer ganz kurzen Zeit gab’s manchmal Probleme, weil das document irgendwie doch noch nicht ganz ready war und der Browser dann an eine andere Stelle zurücksprang. (Kann aber sein, dass das nur beim Neuladen einer Seite, wie man’s beim Testen nunmal macht, passiert.)

Ich habe diesen HTML/JS-Code direkt (und natürlich nicht in <?php ?> eingeschlossen) in die comments.php eingefügt (also nicht in die functions.php ausgelagert), und zwar direkt nach <?php if ('open' == $post->comment_status) : ?> und damit direkt vor die Ausgabe der Eingabefelder.

Auch hier sollte man die Klasse .caughtasspam dann natürlich noch in der style.css angemessen formatieren.

Nun hat auch diese Methode einen Nebeneffekt, der sowohl unerwünschterweise (aber wohl sehr selten) auftritt, wenn jemand irgendwoher einen falschen Link mit einer nicht existierenden bzw. unsinnigen Kommentarnummer hat, als auch erwünschterweise, wenn jemand den Link mit seinem erstmal durchgegangenen Kommentar gebookmarkt hat und dieser nachträglich in den Spameimer geworfen wird, denn dann wird dieser Hinweis auch ausgegeben.

Was es euch auch ermöglicht, diese Funktion einfach zu testen – ich habe hier einen Link für euch vorbereitet. :) Ihr könnt aber auch einen neuen Kommentar schreiben und dort „diesisteinspamtest“ einfügen, dieses Wortkonglomerat hab ich für ebendiesen Zweck auf die Blacklist gesetzt. Aber übertreibt’s nicht, ich muss die schließlich alle freischalten…

Wer kein Cache-Plugin verwendet, kann also die erste Lösung gut verwenden, andernfalls gilt es eben Vor- und Nachteile abzuwägen; ich habe mich wie gesagt für die JavaScript-Lösung entschieden.

Meinungen, Kritik, Anregungen, Probleme, Fragen…?

  1. wer ein fehlerhaftes Theme hat, das diese ID für die Kommentare nicht erzeugt und somit alle Kommentatoren nach dem Kommentieren am Seitenanfang landen, sollte das jetzt endlich auch reparieren… ↺

Blogparade: Alter Computer-Kram –
Literatur, Software, Hardware

Blogparade alter Computer-Kram Angeregt durch BeetFreeQs Blogparade „Multimediale Kuriositäten“, die sich Tonträgern, DVDs, Videos, Büchern und Computer-/Videospielen widmet (» mein Beitrag), dachte ich mir, ich veranstalte selber eine Blogparade, die sich auf Computer konzentriert, insbesondere auf diese Fragen:

  • Was ist die älteste Computer-Literatur, die ihr noch habt?
  • Welche alten Originaldisketten oder sonstige Software liegen noch rum?
  • Welches alte Stück Hardware ist tatsächlich noch im Einsatz?

Zu allen drei Themenbereichen könnt ihr sowohl die ältesten, nicht mehr verwendeten und nur noch aus Nostalgie aufgehobenen Stücke nennen als auch die ältesten, die ihr noch benutzt, und ihr müsst auch nicht zu jedem Teilthema ein Stück herauskramen. Ich habe auch nichts dagegen, wenn ihr mehr Wert auf die Kuriosität als aufs Alter legt – bei einer Überschneidung mit BeetFreeQs Parade könnt ihr ja bei beiden mitmachen, wenn er nichts dagegen hat. :)

Gültig sind sowohl Heim- als auch Personal Computer1, aber keine Spielekonsolen, Handys u.ä. Fotos von euren „Schätzen“ wären natürlich auch nett.

Die Blogparade geht bis zum 20. Juni 2010, und es gelten die üblichen Regeln: Schreibt einen Beitrag mit eurem Computer-Kram in eurem Blog2 und verlinkt zu diesem Beitrag; wenn der automatische Trackback nicht kommt, schreibt einen Kommentar mit dem Link, damit ich weiß, wer alles teilnimmt. Das Bild oben dürft ihr für euren Beitrag natürlich auch verwenden.

So, dann legt mal los – auch wenn’s nichts zu gewinnen gibt.^^ Zur Einstimmung zeige ich euch auch gleich meinen Kram:


ROM-Listing CPC innen ROM-Listing CPC Front → Mein ältestes Buch ist dieses ROM-Listing für den guten alten Schneider CPC – ich hatte damals den CPC 664, und wer den ernsthaft (oder verspielt, das aber ernsthaft) und effizient program­mieren wollte, kam um Z80-Assemb­ler, direkte Hard­ware­zugriffe und die im ROM vorhan­denen Routinen nicht herum. Und eben letzteres fand sich – natürlich mit vielen weiteren Infos – in diesem Wälzer von 1986. Eine Beispiel-Doppelseite ist im zweiten Bild zu sehen.

Übrigens gab es damals durchaus Spiele, die schöner waren und flüssiger liefen als so manche Flash-Browserspiele heutzutage…

alte Disketten ← Beim weiteren Stöbern bin ich dann noch auf einige alte DOS-Disketten gestoßen – MS-DOS 6 Update, Novell DOS 7, PTS-DOS 6.4 –, dazu die Entwick­lungs­umgebung Borland Pascal 7, das gelegentlich sogar noch im Einsatz ist – wenn mal kleine DOS-Tools gefragt sind; aber dann muss auch nur der Befehlszeilen-Compiler arbeiten, der integrierte Textmodus-Editor ist mir dann doch zu antiquiert.

Sowie einige alte Spiele auf 5¼“-Disketten, bei denen ich mich frage, warum ich sie noch habe… ob sie noch lesbar wären, wenn ich noch ein Laufwerk dafür hätte?

Tastatur → Das ist eine Cherry G81-8308 mit 24 in 10 Ebenen mit beliebigen Zeichen- bzw. Tasten­druck­folgen programmier­baren Zusatz­tasten (mit Kappe, unter die man eine papierne Beschrif­tung legen kann) – ist zwar von 2002 und damit noch nicht sooo alt, aber anders als hier oder da ein altes Zubehör­teil, das auf einen gelegentlichen Einsatz in einem alten Test-PC wartet (oder ein Handscanner mit ISA-Karte, der noch im Keller versteckt sein könnte), noch (fast) täglich im Einsatz am Haupt-PC.

Die dunkelgraue Handballenauflage ist allerdings von einer anderen Tastatur – passt aber leidlich auch an diese und macht das ganze etwas bequemer.

Nun denn, dann bin ich mal auf eure Auswahl gespannt – wie gesagt und wie ihr seht, müsst ihr nicht zu allen 3×2 Kategorien (Literatur, Software, Hardware, je noch und nicht mehr in Gebrauch) etwas nennen. Ich freue mich auf hoffentlich zahlreiche Beteiligung…

Update 21.6.: » Zur Auswertung

  1. und das beschränkt sich auch nicht auf Intel-Windows-PCs ↺
  2. wer kein Blog hat, darf auch gern einfach hier kommentieren ↺