Dienstag, 27. September 2011

Firefox Plugins zum neuen Leben erwecken

In der letzten Zeit sind viele neue Firefox-Versionen erschienen. Oft müssen dann auch die Plugins aktualisiert werden.
Was tun, wenn der Pluginentwickler keine neue Version zur Verfügung gestellt hat?

Ich benutze z.B. ein Tool um REST-Test zu machen, wo die Entwicklerwebseite nicht mehr vorhanden ist. (Hier kann man nachlesen was REST ist ;-) REST)

Um ein Firefox-Plugin unter eine neue Firefox-Version erneut lauffähig zu machen, ist oft nicht viel Arbeit nötig. Mann muss nur in der Datei, die das Plugin beschreibt, die maximale Firefox-Version erhöhen.
Das geht so (ich arbeite auf einem Mac, aber unter Windows ist es Äquivalent):

In dem Firefox-Menü wählen Sie Hilfe -> Informationen zur Fehlerbehebung



Alternativ können Sie auch in der Adresszeile, wo Sie sonst Ihre Webadressen eintragen, folgender Firefox-Befehl eintragen: about:support

Dann erscheint folgende Seite:



Hier klicken Sie auf „Im Finder anzeigen“.
(Der „Finder“, ist der Explorer/Dateimanager unter Mac.)

Es öffnet sich nun in etwa folgende Ansicht:



Wir interessieren uns für die Dateien, mit den Namen install.rdf

Jetzt müssen wir nur die richtige finden ;-)

In meinem Fall will ich das Tool RESTTest zum neuen Leben erwecken.
Die Suche gestaltet sich in dem Fall einfach.

Sie öffnen die Datei install.rdf mit einem Text-Editor, der den Text nicht formatiert. Also nicht Pages/Word (Mac/Win), sondern TextEdit/Notepad (Mac/Win).

Das sieht in meinem Fall so aus:



Hier müssen Sie nun nur, die maxVersion auf eine Firefox-Versionsnummer höher oder gleich die Sie im Einsatz haben. Ich nutze z.Zt. die Version 7 und habe mich hier schon auf die Version 9 für das RESTTest-Plugin vorbereitet ;-)

Nach dem Sie die Datei install.rdf geändert und gespeichert haben, starten Sie Firefox neu. Wenn das Plugin keine weitere schwer wiegende Abhängigkeiten zu der alten Version hat, ist die wieder voll funktionsfähig.

Viel Erfolg!

Donnerstag, 16. Juni 2011

Bilder vom Mondfinsternis 15.06.2011

Ich konnte es nicht sein lassen die Kamera letzte Nacht zu zucken...
Das ist das Ergebnis.
Kamera: Nikon D200
Objektiv: AF-S Nikkor 18-200mm 1.35-5.6 G ED
Einstellung: ASA1000, 1/5s, eingeschaltetet Bildstabilisator

Das erste Bild entstand um Ca. 23:05 Uhr. Das letzte um Ca. 23:30 Uhr.

















Mittwoch, 15. Juni 2011

Dienstag, 1. Februar 2011

Für Symfony einen eigenen Captcha schreiben

Einen eigenen Captcha für das eigene Symfony-Projekt ist relativ einfach, da PHP Funktionen hat um dynamisch Bilder zu erstellen.

Wir haben ein Captcha für unsere Login-Maske erstellt, da Google's reCaptcha zu lange Texte präsentiert und bei zwar seltenen aber doch Gelegenheiten nicht verfügbar war und somit eine Anmeldung auf unsere Webseite unmöglich machte.

Die Lösung besteht aus den folgenden Schritten:
1. Eine kleine Grafik als Hintergrundbild für den Captcha-Text
2. Eine PHP-Klasse, die die Captcha-Grafik produziert
3. Ein Modul "captcha" mit Action und Template
4. Routing für das Captcha-Modul anpassen
5. Eine Formularklasse mit Widget und Validator für das Captcha
6. Ein Validator für das Captcha
7. Das Anzeigen der Captcha-Grafik

1. Hintergrundbild
Oft wir eine etwas "unruhige" Hintergrundgrafik für das Captcha erstellt, um das maschinelle Auslesen des Textes zu erschweren.
Wir haben es hier nicht übertrieben, sondern nur ein par Punkte auf einem weißem Hintergrund platziert.


2. Eine PHP-Klasse für das Erzeugen der Captcha-Grafik
Wir haben uns für eine recht einfache Captche-Grafik entschieden. Es gibt mit PHP auch die Möglichkeit andere Schriftarten zu nutzen sowie den Text zu drehen usw.

Was die einzelne Funktionen in diese Klasse machen können Sie unter http://php.net nachschlagen.

Ein kleiner Hinweis noch. Da später der Aufruf unseres Symfony-Moduls eine Grafik liefern soll und kein HTML, ist es wichtig, dass wir den Header mit

header ("Content-type: image/png");

definieren (siehe unten). Wir sehen hier auch, dass unsere Grafik eine png ist. Es sind aber auch andere Formate möglich. Siehe http://php.net.

class CaptchaImage {

function generate($CaptchaText) {
$fontsize = 5;
header ("Content-type: image/png");

$image = ImageCreateFromPNG($_SERVER['DOCUMENT_ROOT'].'/images/captcha.png'); //Backgroundimage

imagecolorallocate ($image, 0, 0, 0);
$text_color = ImageColorAllocate ($image, 7, 29, 192);

ImageString ($image, $fontsize, 5, 7, $CaptchaText, $text_color);
ImagePNG ($image);
ImageDestroy($img);
}
}

3. Ein Symfony-Modul
Da wir die Captcha-Angelegenheit schön in Symfony-Stil organisiert haben möchten, haben wir ein eigenes Modul dafür erstellt.
Das ist einfach und bringt etwas Struktur in die Anwendung.
Das Modul trägt den Namen "captcha" und die Action "captchagen"

Das Template captchagenSuccess.php ist leer, da die Action das Captcha-Bild liefern soll.

Die "captchagen" Action ist nicht sehr umfangreich und besteht hauptsächlich aus dem Generieren des Captche-Textes und das
Erzeugen des Bildes. In der Action wir der Captcha-Text in der Session aufgehängt, damit wir den Später gegen Benutzereingabe in unserem Validator prüfen können. Mehr dazu später.

class captchaActions extends sfActions
{

public function executeCaptchagen($request) {
//Captche-Text generieren
$captchatext = '';
$pool1 = 'ABDEFGHIJKLMNPRSTUVWXYZ';
for ($i = 1; $i <= 3; $i++) {
$captchatext .= substr($pool1, rand(0, 22), 1);
}
$captchatext .= " ";
$pool2 = '123456789';
for ($i = 1; $i <= 3; $i++) {
$captchatext .= substr($pool2, rand(0, 8), 1);
}

//Captche-Text in der Session aufhängen
$_SESSION['captchatext'] = $captchatext;

//Captcha-Text mit Hilfe unsere Klasse "CaptchaImage" erstellen $tmpCaptchaImage = new CaptchaImage(); $tmpCaptchaImage->generate($captchatext);
}

}

4. Routing anpassen
Damit wir unser Somfony-Modul "captcha" rufen können, passen wir das Routing an.
Das machen wir in der Datei apps/frontend/config/routing.yml

captcha:
  url: /captcha
  param: { module: captcha, action: captchagen }


5. Widget und Validator für das Captcha
Wir benutzen bereits das sfDoctrineGuardPlugin und haben daher die darin enthaltene Form-Klasse "sfGuardFormSignin" um unser
Captcha erweitert. Selbstverständlich können Sie Ihre eigene Form-Klasse für die (Anmelde-)Maske entsprechend erweitern.

So sieht die erweiterte Klasse aus:

class sfGuardFormSignin extends BasesfGuardFormSignin
{
public function configure()
{
//Widgets erstellen und konfigurieren
$this->widgetSchema['username'] = new sfWidgetFormInputText();
$this->widgetSchema['password'] = new sfWidgetFormInputPassword(array('type' => 'password'));
$this->widgetSchema['remember'] = new sfWidgetFormInputCheckbox();
$this->widgetSchema['captcha'] = new sfWidgetFormInputText();

//Validators erstellen und konfigurieren
$this->validatorSchema['username'] = new sfValidatorString();
$this->validatorSchema['password'] = new sfValidatorString();
$this->validatorSchema['remember'] = new sfValidatorBoolean();
$this->validatorSchema['captcha'] = new sfValidatorCaptcha();

$this->validatorSchema->setPostValidator(new sfGuardValidatorUser());

$this->widgetSchema->setLabels(array(
'username' => 'Benutzername:',
'password' => 'Passwort:',
'remember' => 'Bitte heute eingeloggt bleiben:',
'captcha' => 'Sicherheitscode:'
));
}
}

Wir haben in diese Klasse folgende Erweiterungen gemacht:
Ein Captcha-Widget hinzugefüht:
$this->widgetSchema['captcha'] = new sfWidgetFormInputText();
Das ist einfach ein normales Textfeld, wo der Anwender den Captcha-Text eintragen kann.

Ein Validator für den Captcha hinzugfügt:
$this->validatorSchema['captcha'] = new sfValidatorCaptcha();
Dieser Validator, den wir selber geschrieben haben, wird unten erläutert.

6. Validator
Um den, vom Anwender eingegebener, Captcha-Text zu prüfen, schreiben wir in Symfony-Manier ein Validator.
Wir haben den "sfValidatorCaptcha" genannt und in der Datei sfValidatorCaptcha.class.php unter lib/form/ abgelegt.

class sfValidatorCaptcha extends sfValidatorString
{
protected function configure($options = array(), $messages = array())
{
parent::configure($options, $messages);

$this->setMessage('invalid', 'Der Sicherheitscode stimmt nicht mit dem im Bild überein');
}


protected function doClean($value)
{
parent::doClean($value);
$clean = (string) $value;

//Captcha-Text aus der Sesson holen
$captchatext = $_SESSION['captchatext'];

if($captchatext != $clean) {
throw new sfValidatorError($this, 'invalid', array('value' => $value));
}

return $clean;
}
}

In der Methode configure, definieren wir den Hinweis für den Anwender, sollte er den Captcha-Text in der Captcha-Grafik falsch abtippen.

Die Methode doClean vergleicht den vom Anwender eingegebenen Text, mit dem in der Action captchagen generierten Text (den wir aus der Session holen). Rekapitulation: Der Captcha-Text hatten wir ja in der Action "captchagen", wo der Text generiert wird, in der Session aufgehängt, damit der uns später zwecks Validierung zur Verfügung steht.

7. Anzeigen der Captcha-Grafik
Für das Anzeigen der Captcha-Grafik, erweitern wir das ensprechende Template des sfDoctrineGuardPlugins.
Da wir in dem Template nicht das Symfony-Rendering nutzen, sondern ein eigenes Layout mit eine Tabelle erstellt haben, müssen wir hier nur diese Zeilen aufnehmen:

<tr>
<td colspan="2">
<?php echo $form['captcha']->renderError() ?>
</td>
</tr>
<tr>
<td>
Sicherheitscode:
</td>
<td>
<?php echo image_tag(url_for('@captcha'), array('raw_name' => true)) ?>
</td>
</tr>
<tr>
<td>
<?php echo $form['captcha']->renderLabel() ?>
</td>
<td>
<?php echo $form['captcha']->render() ?>
</td>
</tr>

Das interessanteste hier ist diese Zeile:

<?php echo image_tag(url_for('@captcha'), array('raw_name' => true)) ?>

Die Symfony-Hilfsroutine "image_tag" generiert ein img-Tag.
In unserem Fall sieht das Ergebnis so aus:

<img src="/captcha" />

Der Hilfsroutine-Parameter "raw_name" verhindert, dass Symfony ein ".png" hinten dran an "/captcha" hängt.
Auch wenn der Header ein Bild in png-Format vorgibt, wäre das ja nicht korrekt, da hier die Bildquelle (src) eine Symfony-Action ist.
Vergleiche hier den url_for-Parameter "@captcha" mit unser Routing-Definition unter Punkt 4 oben. Das hier verwendete "@captcha" ist der Routing-Name "captcha:".

Das fertige Ergebnis sieht so aus:



Ich denke das war's jetzt :-)
Viel Spaß beim Ausprobieren!

PS. Wenn Jemandem veraten könnte, wie man hier Quellcode formatieren kann, wäre das sehr nett ;-)

Sonntag, 30. Januar 2011

Einen erfolgreichen Unternehmer...

...traf ich dieses Wochenende auf einer Motorradmesse in Dettelbach bei Würzburg.

Der Airbrush-Künstler ist unglaublich talentiert und hat sein Bodypainting-Model in Ca. 20 Minuten bemalt. Das Ergebnis können Sie unten bestaunen.
(ein Klick auf das Bild bringt eine Vergrößerung)

Schön ist es auch, wenn man sein Hobby zum Beruf machen kann.

Sie finden den Künstler unter http://www.brusher.de
















Ob ich nur wegen den Mädels da war? ;-)
Nein... :-)

Donnerstag, 13. Januar 2011

Bookmarks aus Delicious in XML-Format exportieren

Da Yahoo eventuell den Bookmark-Dienst http://www.delicious.com/ schließen will, ist es empfehlenswert die Bookmarks zu sichern. Auf der Webseite von Delicious gibt es ein Export in HTML (https://secure.delicious.com/settings/bookmarks/export).

Wenn Sie aber die Bookmarks in XML exportieren möchten, können Sie diesen Befehl auf der Kommandozeile nutzen:

curl https://{username}:{password}@api.del.icio.us/v1/posts/all > bookmarks.xml

Voraussetzung ist, dass Sie das Programm curl installiert haben. Auf dem Mac ist es schon drauf ;-)

In dem Befehl oben ersetzen Sie username und password mit Ihren Daten. Die geschweiften Klammern müssen bleiben!

Viel Erfolg!
Und hoffen wir, dass Yahoo sich es anders überlegt!