Dynamische Signatur – e-Schrecking für Foren, MySpace, …

Dynamische Signatur von Danasoft Ich mag es sehr, Leute zu ängstigen. Früher, zu den Gothenzeiten, habe ich dafür ein ganzes Arsenal von Dingen gebraucht: Schminke, Linsen, künstliche Fingernägel, … Heute reicht meine Anwesenheit und mein Gesicht 🙂 . Wenn ich mich unter besonders verständnisvollen Menschen befinde, breche ich in spontane, apokalyptische Prophezeiungen oder aber auch abwechselnd in ebenso apokalyptisch anmutende Zuckungen aus.

Als besonders ängstigend hat sich auch folgendes Vorgehen herausgestellt: Man fixiert eine Person, lächelt wissend, nickt ebenso wissend und macht wissende Bemerkungen wie „ja, es ist schon schwer“ oder aber auch „ich denke Du machst bald einen Fehler“.

Online kommt mein Gesicht nicht so zur Geltung und Zuckungen fahren über die Webcam auch nicht so apokalyptisch durch Mark und Bein, also haben acht von neun Stimmen in meinem Kopf gesagt, ich soll den letzten Trick elektronifizieren (eine Stimme summte die Melodie von Tetris).

Danasoft hat schon was sehr Nettes, wie man am Lead-Image erkennen kann. Ich will aber nichts Nettes, sondern was Böses, darum habe ich die Pöhse Horror Pranke (PHP) hervorgeholt und was gecoded.

Grundidee

(Reload für weitere Weisheiten).
Dynamische Signatur

Es soll eine Signatur (oder Batch, Widget, Papperl, …) werden, die man in Foren (MyFace, SpaceBook, prollVZ, …) und Blogs verwenden kann, und das vorgibt mehr zu wissen als es tatsächlich tut.

Weiterlesen

Mit PHP einen Monat mit verlinkbaren Daten anzeigen

CalendarFür eine Applikation, in der man Ressourcen reservieren kann, wollte ich ein Kalender mit verlinkbaren Tagen anzeigen (grad wie im Meeting Room Booking System). Da ich aus dem Alter raus bin, in dem man alles selber machen muss und ausserdem eine PHP-Datumsfunktionsphobie (PHPYpiresiaChronophobia) entwickelt habe, wollte ich eigentlich etwas Fertiges verwenden. Es gibt vorallem Kalender in JavaScript, ein Tutorial das den Kommentaren nach nicht funktioniert (und das mittlerweile vom Web verschwunden ist), Scripts ohne Ausgabebeispiele, Riesenmonster (deren Anwendungsbeispiele mehr Code haben als eine Eigenimplementation) oder Kalender, die zwar gut sind, aber irgendwie nicht gepasst haben (I18n, …). Ich möchte auch nix mit Ajax, Sigolin und Meister Propper, denn es soll eine Enterprise-Applikation geben, und da ist JavaScript halt nicht so opportun (und erspart mir wieder ein paar graue Haare mehr). Aber vor allem (aber das verschweige ich hier) hat das wie eine spannende Aufgabe ausgesehen, und als Kontrollfreak will ich es eben doch selber gemacht haben 😀 .

Ziel

Das Ziel ist es einen Kalender zu erhalten, der die Wochen anzeigt, bei dem ein Tag (Event) markiert werden kann und das heutige Datum speziell ausgezeichnet ist. Er sollte also in etwa so aussehen (die Monatsnamen und Namen der Wochentage sollten sich auch noch der Sprache anpassen):

PHP-Kalender

Man sollte entweder ein Monat und ein Jahr übergeben können oder einfach nichts, wobei dann der aktuelle Monat und das aktuelle Jahr verwendet werden.

Vorgehen und Implementation

Ich habe mich entschlossen, dem Enterprisefassadefrontsidedecontrollerkurtmitgurtgimmeabreak-Pattern zu folgen… Quatsch, meine Gewohnheit und die Stimmen in meinem Kopf haben mich dazu gezwungen, den Kalender in zwei verschiedenen Funktionen zu implementieren. PHP hat ein absolut geniales Array-Handling, und wenn ich an solchen datenmanipulierenden Aufgaben arbeite habe ich mir angewöhnt, zuerst die reinen Daten in einem (mehrdimensionalen, ev. assoziativen) Array abzubilden. Dies hat den grossen Vorteil, dass ich die aufbereiteten Daten nicht nur für die HTML-Ausgabe, sondern auch von anderen Funktionen aus benutzen kann. Das Ziel wäre ein Array, dass auf der einen Dimension die Wochen und auf der Anderen die Wochentage hat. Man nehme den ASCIIstift hervor und zeichne ein Beispiel für Juni 2008:

[22] => {   '',   '',   '',   '',   '',   '',  '1'}
[23] => {  '2',  '3',  '4',  '5',  '6',  '7',  '8'}
[24] => {  '8',  '9', '10', '11', '12', '13', '14'}
...
[27] => { '31',   '',   '',   '',   '',   '',   ''}

Die Benamsung ist wie folgt:
PHP-Kalender benamst
Weiterlesen

AIML: Intelligenz im XML

BrainWenn man schon keine eigene Intelligenz besitzt, ist man froh, dass es sie auch in künstlicher Form gibt. Bis vor einiger Zeit wurde ziemlich proprietär rumgewurstelt, aber nun gibt es AIML, die Artificial Intelligence Markup Language die mit XML und Standardisierung das Verwenden unter verschiedenen Plattformen möglich macht. XML und Intelligenz ist also doch nicht per se ein Widerspruch.

Interessant ist das Ziel dieser Bemühungen (wie auf Pandorabots beschrieben):

Inhalte zu erstellen, die den Besucher dazu veranlassen so lange wie möglich mit dem Bot zu reden.

Auf der Basis von AIML wurden verschiedene Interpreter für verschiedene Programmiersprache geschaffen, Inhaltsdateien erstellt, die alle von der offiziellen Homepage oder der Tools Page heruntergeladen werden können.

AIML als XML (Gimme Code!)

AIML ist ziemlich komplex. Es gibt die Möglichkeit einer Unterteilung in Themen, der Extraktion von Mustern, der spezifischen Auswahl der Antworten etc, etc… Die englischen Übersichten und Tutorials gehen tiefer in die Materie.

AIML Tags

Die wichtigsten Tags von AIML:
Weiterlesen

PHP_SELF ist böse! Potentielles Cross Site Scripting (XSS)!

Was haben wir gelernt?

EvilJa, uns wurde gelehrt, dass man wenn immer möglich nicht Dateinamen direkt, sondern eine Variable angeben soll, die für den Dateinamen steht. Warum konnte mir zwar noch niemand so genau sagen, aber ich nehme an, dass es darum geht, dass der Dateinamen oder der Pfad ändern könnte. So habe ich ziemlich oft ganz brav geschrieben:

<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method ="post">
...
</form>

Und (zum Glück) bin ich nicht der Einzige. Eine kleine Suche auf Googles Codesearch hat gezeigt, dass mindestens Mambo, PHPMyFAQ, Einige WordPressthemes und viele mehr dasselbe Problem haben. Ich bin bei Weitem auch nicht der Erste, der über Probleme mit dieser Technik erfahren und darüber geschrieben hat.

Problem? mit $_SERVER['PHP_SELF']?

Lasst mich ausholen: Der Apache Webserver hat eine Option AcceptPathInfo, welche standardmässig auf On ist. Mit dieser Option mappt der Apache beliebig lange Pfade auf Dateien, sofern diese irgendwie Bestandteil des Pfades sind. Der Rest wird in Umgebungsvariablen mitgegeben.

Gimme Code

Nehmen wir an, es gäbe eine Datei /subdir/mypath.php welche so aussieht:

<?php
echo "<pre>";
echo "REQUEST_URI: ".$_SERVER['REQUEST_URI']."\n";
echo "PHP_SELF:    ".$_SERVER['PHP_SELF']."\n";
echo "SCRIPT_NAME: ".$_SERVER['SCRIPT_NAME']."\n";
echo "</pre>";
?>

Bei einem Aufruf von: http://localhost/subdir/mypath.php/additional/stuff/nonsense.php?para=4 mappt Apache netterweise alles auf unsere Datei http://localhost/subdir/mypath.php und verstaut den Rest im $_SERVER Array. Die Ausgabe ist:

REQUEST_URI: /subdir/mypath.php/additional/stuff/nonsense.php?para=4
PHP_SELF:    /subdir/mypath.php/additional/stuff/nonsense.php
SCRIPT_NAME: /subdir/mypath.php

PHP_SELF übernimmt also den ganzen Krempel und würde ihn bei unserem Form auch so darstellen. Angenommen, wir haben ein PHP-Script mit der URL http://localhost/contact/myform.php mit folgendem Inhalt:
<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method ="post">

Ruft man dieses nun mit folgender URL auf (die aufwändiger als notwendig konstruiert und des besseren Verständnisses wegen nicht URL-encodiert ist):
http://localhost/contact/myform.php/"></form>Hier ein Javascript: <script>alert('gotcha');</script><form action="/contact/myform.php
erhält man:
<form action="/"></form>Hier ein Javascript: <script>alert('gotcha');</script><form action="/contact/myform.php" method ="post">

Also vollkommen gültiges HTML (sogar das Form funktioniert) mit fremdbestimmbaren Seiteninhalt. Das ist ja wohl hässlich…

Theorie! Gib mir Praxis!

Ich weiss nicht, wie lange folgende Links funktionieren, beziehungsweise diese Sites anfällig für diese Art von XSS sind:

Digital Postcard (Kein XSS, aber mein Text 🙂 ):
Postcard XSS

Multimediatreff: (Mittlerweile behoben)
Multimediatreff

Jobs. ch (Mittlerweile behoben):
Jobs.ch

Was nutzt das dem bösen Hacker?

Text in Fremdpages einbauen, Phishing, Indentitätenklau und noch einiges Weiteres. Ein Folgeartikel wird mindestens eine Anwendung zeigen.

Was tun?

Ganz einfach: Das oft verschmähte $_SERVER['SCRIPT_NAME'] verwenden!!!

BTW: Viele Variablen in $_SERVER sind anfällig, aber alles muss ich ja auch nicht verplappern, oder?

Kleine SEO-Tools mit Quelltext in PHP

ToolsEs gibt viele Sites, die online Tools für die Suchmaschinenoptimierung (SEO) anbieten. Es gibt Handverlesene Verzeichnisse von Linkvendor, Eigenentwicklungen von Ravenseo und riesige Zusammenstellungen von den Fachinformatikern, dem Website Spy, dem SEO-Chat und der SEO-Company. Wieso braucht es denn noch mehr? Ganz einfach: Google Schweiz wird – extrem überraschenderweise – nirgends so richtig berücksichtigt. Ausserdem will ich auf der Kommandozeile arbeiten und den Quellcode möchte ich auch, um die Bewertungen nachzuvollziehen und um darin herumzuwurschteln.

Naja, dann hab ich halt mal angefangen. Das Resultat gibts auch zum Download: PHP SEO-Tools.
Weiterlesen

Spass und Erleuchtung auf dem XPath

XPathXPath ist eine ziemlich geniale Sache. Es erlaubt die Formulierung von Ausdrücken, die in einer XML-Datei nach gewissen Dingen suchen. Dabei können einzelne, bestimmte oder alle Textinhalte eines Tags, Attributswerte und die Anzahl gesucht und gefunden werden, und das alles jeweils relativ oder absolut zum Root des XML-Dokuments. Die Möglichkeiten sind dabei ziemlich flexibel und es drängt sich ein Vergleich zu SQL auf.

Dies soll kein XPath-Tutorial werden, das machen Andere, an anderen Stellen viel besser.

Ich wollte etwas ähnliches bauen wie Futurelab (Link leider tot 🙁 ) in Java/JSP realisiert hat, allerdings in PHP. Ausserdem wollte ich, dass es auch mit dem count() Ausdruck und seinen Kollegas umgehen kann.

Programmaufbau

Was XML angeht, kann sich PHP echt nicht beklagen; Mindestens 4 Ansatzpunkte bieten sich dem interessierten Coder. Als einfaches Gemüt mit Freude an KISS (und KISSES 🙂 ), wollte ich natürlich zuerst SimpleXML bemühen. Leider liefert die dazugehörige XPath-Funktion „nur“ die Ergebnisse als String. Dies verunmöglicht ein Highlightning im original-XML. Einen Gang hochgeschaltet und den grösseren Bruder bemüht: Die DOM Erweiterung.

Der Grundsätzliche Ablauf des Laborprogramms ist der Folgende:

  1. Flatfile XML wird in einen DOM-Tree umgewandelt: Ein Aggregat aus Objekten, Attributen, Arrays und was man sonst noch so in einem handelsüblichen Speicher findet.
  2. Er wird versucht, aus den Eingaben des Anwenders Sinn zu gewinnen → die entsprechenden Teile im DOM-Tree mittels XPath zu identifizieren.
  3. Diese Teile werden irgendwie markiert (schwierigster Teil).
  4. Der Dom-Tree wird wieder in ein XML geplättet.
  5. Die Marker werden durch Spans mit Stylesheetinfos ersetzt, um zu zeigen was gefunden wurde.

Fälle und Fallen

Wenn der Anwender etwas sucht, werden vier Fälle unterschieden. Diese Fallunterscheidung wird an Hand des Resultats der XPath Anfrage gemacht. Anzahl der Resultate und Typ (mit Hilfe des Reflection APIs herausgepfriemelt, wohoo(!!!)) bestimmen die Aktion.

Fall 1: Es gibt Nodes im Resultat und die sind vom Typ DOMElement

Juhuu, wir haben simple und einfache Dinge gefunden. Nun müssen wir sie noch schnell markieren. Meine Idee war, dies mit Kommentaren zu machen, die ich jeweils vor vor und nach dem gefundenen Element einsetze:

$start=$xo->createComment('MATCH-START');
$end=$xo->createComment('MATCH-END');
$result->parentNode->insertBefore($start,$result->previousSibling);
$result->parentNode->insertBefore($end,$result->nextSibling);

Bug-Potential 1: Es dürfen keine identischen Kommentare im original-XML enthalten sein.

Fall 2: Es gibt Nodes im Resultat und die sind vom Typ DOMAttr

Etwas komplexer: Es ist nach Attributen gesucht worden. Hier wollte ich zuerst Regexpe zum Highlightnen speichern, aber das funktioniert nicht, da einzelne Attribute bestimmter Knoten ausgewählt werden können (//cd[2]/@currency). Naja, dann wurschteln wir hier Marker <!--MATCH-START--> und <!--MATCH-END--> in den Attributsinhalt. Leider werden die Klammern schon mal mit ihren HTML-Entities ersetzt, was dann zum Schluss eine doppelte Codierung ergibt.

Fall 3: Es gibt keine Nodes im Resultat, aber evaluate bringt ein Ergebnis

Es wird eine Funktion wie etwa count() verwendet. Nundenn: Evaluieren, ausgeben, danke.

Fall 4: Es gibt keine Nodes im Resultat und evaluate bringt kein Ergebnis

Das ist eine ID-10-T Eingabe. Fehlermeldung und tschüss.

Das Resultat

Das Resultat kann angesehen und als Gesamtheit mit Quellcode heruntergeladen werden. Kommentare und Bugreports würden mich freuen. Happy coding!!!!

oncode.info XPath Laboratory small

Active Record Pattern in PHP

StorageIn PHP gibt es verschiedene Implementierungen des Active Record Patterns. Auch wenn es uns nimmer so auffällt, die objektorientierte Welt des Codes und die relationale Welt der Daten sind zwei verschiedene Paradigmen, und es braucht unheimlich viel Leim um sie zusammenzukleben. Objektorientierte Datenbanken entwickeln sich, sind jedoch noch nicht Standard (um es mal vorsichtig auszudrücken). Das Active Record Pattern hilft uns mit ein Bisschen Standard-Klebe.

Mit diesem Pattern können Daten aus der Datenbank gesucht und direkt in Objekte übergeführt werden. Änderungen an den Objekten und das Speichern bewirken, dass diese Änderungen auch in die Datenbank übernommen werden.

Ich habe mich für MyActiveRecord von Jake Grimley entschieden, weil es sauber implementiert, nicht zu gross und trotzdem nicht featurearm ist. Die Dokumentation ist ziemlich gut und reicht aus um zu starten.

Benutzung von MyActiveRecord

Suchen und finden

Der Dreh- und Angelpunkt dürfte die Funktion FindAll($class, $where=0, $orderby='id ASC', $limit=10000, $offset=0) sein. Sie liefert eine Kollektion von Objekten der entsprechenden Klasse zurück:

foreach (MyActiveRecord :: FindAll('thing') as $thing) {
  echo "I am a {$thing->name}!<br />\n";
}

Weiterlesen

PHP-UWA Widget Library

[lang_de]Update Jan 2011: Die PHP-UWA-Library wurde völlig überarbeitet und funktioniert nun mit der aktuellen IFrame-Methode. Das Prinzip bleibt das Gleiche, die Aufrufe sind leicht anders: Projekt auf oncode.info.[/lang_de]
[lang_en]Update Jan 2011: The PHP-Update library has been completely rewritten and does now support the current IFrame-Method. The principles are still the same, but the API has changed quite a bit: Projekt auf oncode.info.[/lang_en]
[lang_de]

Widgets und Web 2.0

Universal Widget ArchitectureWidgets sind kleine Miniapplikationen, die übersichtlich wichtige Daten anzeigen oder kleinere Funktionen ausführen. Es gibt sie für Windows Vista, Mac, iPhone sowie Webbasiert für iGoogle, Yahoo!, Netvibes und so weiter und so fort. Um die Entwicklung zu forcieren, stellt nun Netvibes ein Rahmenwerk vor, das die Entwicklung von Widgets für alle diese Plattformen vereinfachen soll: Die Universal Widget Architecture. Die Widgets, die nach diesem Standard programmiert sind, sollen unter allen diesen Plattformen laufen…[/lang_de]
[lang_en]

Widgets and Web 2.0

Universal Widget ArchitectureWidgets are little miniapplications which show data in a clearly arranged way or perform a more or less simple task for the user. Widgets are present on Windows Vista, Mac, iPhone and also in a webbased form for iGoogle, Yahoo!, Netvibes and many other portals. To give a boost to widget development, Netvibes presented a new framework which shall facilate the coding of widgets. The child is called Universal Widget Architecture. Widgets coded with the help of this framework should work on all the mentioned plattforms.[/lang_en]

[lang_de]

UWA Standard

Ein Widget im UWA-Standard ist ein XML-Dokument. Es enthält Metadaten, Einstellungen und den aktiven Teil, geschrieben in Javascript. Besonders die Einstellungen sind interessant, denn über diese können widgetspezifische Parameter angepasst werden. Einige Toolfunktionen runden das UWA-Paket ab.[/lang_de]
[lang_en]

UWA Standard

A widged, coded with UWA is basically a XML-Dokument. It contains metadata, settings and the active part, written in Javascript. Especially the Preferences are of interest, because they are dynamic and allow widgetspecific settings. There are also some convenience-functions in the UWA-library.[/lang_en]

[lang_de]Die UWA-Spezifikation hat ihre eigene Homepage und ist gut dokumentiert. Es gibt Beispiele, ein Code-Skelett mit Erklärung, ein Schritt-für-Schritt Tutorial, ein Forum und sogar ein Cheat-Sheet. Der Einstieg wird einem wirklich so einfach wie möglich gemacht.[/lang_de]
[lang_en]The UWA specification has its own homepage and is very well documented. There are examples, a code-skeleton with explanations, a step-by-step tutorial, a forum and even a cheat-sheet. The start is very easy with such a lot of documentation.[/lang_en]

[lang_de]

Widget Repository

Fertige Widgets können im Widget Repository (Ecosystem) der Öffentlichkeit zur Verfügung gestellt werden. Von diesem System aus können die Widgets zu den verschiedenen Plattformen mittels Mausklick hinzugefügt werden. Im Repository hat es auch noch Widgets, die nach dem veralteten Mini-API Standard funktionieren, diese werden jedoch (hoffentlich) bald verschwinden.[/lang_de]
[lang_en]

Widget Repository

Finished and released widgets can be made available for the public and published in the Widget Repository (Ecosystem). Widgets ion this website can be added to the different platforms with a single (or double) click). There are some widgets in the repository which are coded in the deprecated Mini-API standard, but these will dissappear soon (hopefully).[/lang_en]

[lang_de]

Implementationen

Das klingt echt faszinierend und schreit danach, genutzt zu werden. Widgets selbst werde ich später implementieren, als erstes wollte ich sie wirklich für eigene Projekte nutzbar machen. Dafür habe ich eine kleine PHP- Klasse entworfen und sie grosskotzig PHP-UWA Widget Library genannt. Mit ihr ist die Handhabung von Widgets ziemlich einfach. Etwas ambitionierter ist das Parsing der widgetabhängigen Einstellungen.[/lang_de]
[lang_en]

Implementations

That sounded fascinating and must have a use somewhere… I will implement some widgets later, I needed to make these widgets usable in our own projects first. So I wrote a little PHP-class which I called pretentious PHP-UWA Widget Library.Handling widged should be easy, using this class. A little bit more ambitious is the handling of widget dependend preferences.[/lang_en]

[lang_de]Ein Minimalbeispiel ist im Download-Paket dabei und kann auch online aufgerufen werden.[/lang_de]
[lang_en]A minimal example is included in the download-package and can also be checked online.[/lang_en]

PHP-UWA Widget Library Example

[lang_de]Ein Widget anzuzeigen geht recht fix:[/lang_de]
[lang_en]Displaying a widget should be straight forward:[/lang_en]

<?php
require_once('uwawidget.php');
$uwawidget=new uwawidget('http://www.netvibes.com/api/uwa/examples/digg.xhtml');
echo $uwawidget->getWidgetHTML();
?>

[lang_de]Informationen über das Widget (sobald die URL angegeben wurde) geben die folgenden zwei Methoden:[/lang_de]
[lang_en]There are two classmembers which can give more information about the widget:[/lang_en]

getMetaData()
[lang_de]Metadaten wie Autor, Keywords, Beschreibung, … Siehe Doku.[/lang_de][lang_en]Metadaten like author, keywörds, description, … See the docu.[/lang_en]
getAdditionalData()
[lang_de]Zusätzliche Daten wie Icon, Stylesheet, …[/lang_de][lang_en]Additional info like icons, stylesheets, …[/lang_en]

[lang_de]Grundsätzlich gibt folgende Einstellungsbereiche:[/lang_de][lang_en]Basically, there are the following sections for settings:[/lang_en]

general
[lang_de]Die URL zum Widget.[/lang_de][lang_en]The widgets URL.[/lang_en]
configuration
[lang_de]Anzeigeparameter, die in der Doku beschrieben sind.[/lang_de][lang_en]Displayparameters, which described in the docs.[/lang_en]
preferences
[lang_de]Widgetabhängige Einstellungen, die ebenfalls in der Doku erwähnt sind.[/lang_de][lang_en]Widget dependent preferences, also mentioned in the docs[/lang_en]

[lang_de]Zu allen diesen Einstellungen gibt es folgende Methoden:[/lang_de][lang_en]For all these settings, there are the following classmembers:[/lang_en]

[lang_de]Setters und Getters[/lang_de][lang_en]Setters and Getters[/lang_en]
setModuleUrl(), setConfiguration(), setPreferences()
getModuleUrl(), getConfiguration(), getPreferences()
getSettingsFormData($section)
[lang_de]Gibt die Settings in einem lesefreundlichen Array wieder, aus welchem ziemlich einfach ein Form generiert werden kann. $section ist dabei "general", "configuration" oder "preferences"[/lang_de][lang_en]Returns the settings in a friendly array, from which a form can be generated. $section can be "general", "configuration" or "preferences"[/lang_en]
getSettingsHTML($section)
[lang_de]Gibt die Settings in Array der Form "Label" => "HTML" zurück. $section ist dabei "general", "configuration" oder "preferences"[/lang_de][lang_en]Returns the settings in an array with the format "Label" => "HTML". $section can be "general", "configuration" or "preferences"[/lang_en]

[lang_de]Zum Test habe ich Moodleblock erstellt, welcher nun die Darstellung von UWA-Widgets innerhalb des LMS erlaubt. Heyo, WordPress, Xoops, etc-Coderz, wie wärs bei Euch mit einer UWA Integration???[lang_de]
[lang_en]For a test, I coded a Moodle block, which allows to use UWA Widgets inside the LMS. Heyo, WordPress, Xoops, etc-Coderz, how about an integration of the Widgets in your system???[/lang_en]

[lang_de]Beispiele vom Moodleblock:[lang_de]
[lang_en]Examples from the Moodle block:[/lang_en]

Moodle UWA Calculator Moodle UWA Converter Moodle UWA Translator
Moodle UWA Google Notes Moodle UWA Spider Moodle UWA ToDo
[lang_de]Die Konfiguration unter Moodle:[/lang_de][lang_en]The configuration in Moodle:[/lang_en]
Widget settings in Moodle

[lang_de]

Ui, fast…

…wäre ich schneller als das aktuelle c’t gewesen, welches eine gute aber knappe Einführung in UWA-Widgets enthält.[/lang_de]
[lang_en]

Uh, almost…

…I was almost faster than the german computer magazine c’t which has a short bit good introduction into UWA-Widgets.[/lang_en]

Drupal mit neuen Google AdSense Werbeblöcken (Serverbasiert)

Neues AdSense


(Affilliate Link 🙂 ) sind neuerdings Serverbasiert. Das heisst: Aussehen, Inhalt, etc kann grösstenteils von der AdSense-Seite aus gemanaged und muss nicht mehr mühsam von Hand auf jeder Seite eingepflegt, geftpt und gecheckt werden. Das geniale Drupal AdSense Modul beherrscht diese neue Variante leider (noch) nicht von Haus aus. Mit einem kleinen Patch geht das aber.

Vorgehen

  1. Die Datei adsense.module mit diesem Patch so patchen, wie in diesem Beitrag beschrieben.
  2. Auf der Google AdSense Seite AdSense-Setup → Anzeigen Verwalten aufrufen und eine neue Anzeige designen.
  3. Den Code anzeigen lassen und die Slot-Nummer notieren. Es sollte etwas sein wie 2666876213.
  4. In Dupal als Administrator Administer → Site configuration → Google AdSense aufrufen und Custom Channels aufklappen.
  5. Die Slotnummer in einen Channel schreiben.
  6. Diesen Channel beim Block für die Anzeige einsetzen.
  7. Warten… Und sich freuen…

PHP: NHL-Spielerstatistiken in Excel ausgeben für Fantasy-Leagues

Das Problem

HockeyIch habe mir sagen lassen, dass es auch hier bei uns Leute gibt die in einer Fantasy League mitspielen. Irgendwie werden da virtuelle aber real existierende Sportler gezogen und verkauft und nach einem speziellen Algorithmus werden Punkte verteilt, die abhängig von den tatsächlichen Resultaten sind, die dieser Spieler erzielt. Nun, auf jeden Fall wird da viel mit Statistiken gewurstelt. Ein Fantasy League-Mitglied ist an mich herangetreten, weil er die online publizierten Resultate der Skaters und Goalies der NHL in einem Excel haben wollte.

Zuerst dachte ich, das sei ein Fall für Dapper. War es aber nicht, da auf der Webpage reine Text-Exporte waren.

Die Erfahrung hat gezeigt, dass die Form der Ausgabe auf diesen Seiten oftmals ändert und man sich auf so wenig wie möglich verlassen sollte.

Die Felder dieser Tabelle haben keine Trennzeichen, sondern eine feste Breite und sind links- oder rechtsbündig formatiert.

Einige Punkte der Lösung

Download der Webseite in eine Variable

Zuerst muss man mal an die Seite rankommen. In PHP den Inhalt einer URL in einen String laden ist in der Theorie relativ einfach. In der Praxis jedoch ist aus Sicherheitsgründen der Zugriff auf URLs für die file* Funktionen oftmals eingeschränkt. Nunja, dann wird halt ein cURL-Fallback mit eingebaut, so dass wir auf jeden Fall in $page ein Array aus den Zeilen der HTML-Datei haben:

  if(!($page = @file($url))) {
    $ch = curl_init();
    curl_setopt ($ch, CURLOPT_URL, $url);
    curl_setopt ($ch, CURLOPT_USERAGENT, 'User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.6) Gecko/20070723 Iceweasel/2.0.0.6 (Debian-2.0.0.6-0etch1+lenny1)');
    curl_setopt ($ch, CURLOPT_HEADER, 0);
    curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1);
    $result = curl_exec ($ch);
    curl_close ($ch);
    $page=explode("\n",$result);
  }

Überschriften auslesen

Ich lese die Tabellenübberschriften mit einem regulären Ausdruck aus (man beachte dass die Sternchen sich der Formatierung (links/rechts) anpassen), aus dem danach die Spaltenbreiten gelesen werden können. Aus den Spaltenbreiten wiederum kann ein regulärer Ausdruck gebaut werden über den auf die Werte zugegriffen werden kann.

Beispielsweise steht auf der Webpage:

NAME                                   POS GP   G    A PTS SOG +/- PIM PPG SHG

daraus lese ich mit folgendem Regexp die Feldbreiten:

'@^(NAME *)(POS *)(GP)( *G)( *A)( *PTS)( *SOG)( *\\+/\\-)( *PIM)( *PPG)( *SHG)$@'

Damit baue ich dynamisch einen neuen regulären Ausdruck, der die Tabellendaten auslesen kann:

/^(.{39})(.{4})(.{2})(.{4})(.{5})(.{4})(.{4})(.{4})(.{4})(.{4})(.{4})$/

Codiert sieht es so aus. $tline im Codebeispiel beinhaltet eine getrimmte Zeile aus dem HTML.

// Überschriften und Feldgrössen
if(preg_match('@^(NAME *)(POS *)(GP)( *G)( *A)( *PTS)( *SOG)( *\\+/\\-)( *PIM)( *PPG)( *SHG)$@',$tline,$matches)) {
  if(!$inresults) {
    // Nach den Überschriften kommen die Tabelleneinträge
    $inresults=true;
    // Überschriften auslesen
    $headercaptions=preg_split('/ +/', $tline, -1, PREG_SPLIT_NO_EMPTY);
    // Überschriften ausgeben
    echo "\r\n".join("\t",$headercaptions)."\r\n";
  }
  // Wie breit ist ein Feld (in Zeichen)
  $sizes=array();
  for($i=1;$i<count($matches);$i++) {
    $sizes[$i-1]=strlen($matches[$i]);
  }

  // Suchmuster für Einträge aufbauen
  $searchpattern="";
  foreach($sizes as $size) {
    $searchpattern.='(.{'.$size.'})';
  }
  //print $searchpattern."<br />";
  $searchpattern='/^'.$searchpattern.'$/';
  continue;
}
// Tabellenzeilen auslesen
if($inresults && preg_match($searchpattern, $tline, $matches)) {
   $row=array();
   for($i=1; $i<count($matches); $i++) {
     $row[]=trim($matches[$i]);
   }
   // Und ausgeben
   echo join("\t",$row)."\r\n";
   continue;
}

Ausgabe als Excel

Hier bescheisse ich… Ich gebe nur eine tabulatorseparierte Liste aus. Excel schnallts, OpenOffice leider nicht (hat da wer eine gescheitere Lösung? HTML-Tabellen?)…

Zuerst die Headers:

header("Content-type: application/vnd.ms-excel");
header('Content-Disposition: inline; filename="'.$dateiname.'.xls"');

Einzelne Zellen werden mittels Tabulator (\t) voneinander getrennt, Zeilenenden werden durch "\r\n" markiert:

echo join("\t",$row)."\r\n";

Die Lösung

Die komplette Lösung kann hier fantasy-league heruntergeladen werden und eine Demo gibts auf apps.oncode.info