PHPGangsta - Der praktische PHP Blog

PHP Blog von PHPGangsta


Archive for März, 2010

Windows-Applikation mit PHP-GTK2 erstellen

with 5 comments

Vielleicht habt ihr schon mal davon gehört, aber es wahrscheinlich noch nie genutzt: PHP GTK2.

Diese PHP-Extension ist dafür da, mit PHP eine Client-Oberfläche zu erstellen. Hört sich komisch an, geht aber ziemlich gut und einfach, habe es vor Jahren bereits gehört und heute nun endlich mal ausprobiert.

Hier zuerst ein Screenshot meines „Hello World“ Programms, bevor es zum Code geht:

Den Screenshot habe ich auf meinem Windows-Rechner gemacht, GTK läuft aber auch platformunabhängig unter Linux und Mac.

Als erstes lädt man sich das PHP-GTK2 Paket herunter, ich habe nicht den Installer gewählt sondern das normale zip-Archiv (php-gtk-2.0.1 Windows binary pack). Nach dem Entpacken erhält man einen Ordner „php-gtk2“, in dem unter anderem eine php.exe zu finden ist.

In diesem Ordner wird eine Datei erstellt: example1.php mit folgendem Inhalt:

<?php
if (!class_exists('gtk')) {
    die("Please load the php-gtk2 module in your php.ini\r\n");
}

$wnd = new GtkWindow();
$wnd->set_title('Hello world');
$wnd->connect_simple('destroy', array('gtk', 'main_quit'));

$lblHello = new GtkLabel("Just wanted to say\r\n'Hello world!'");
$wnd->add($lblHello);

$wnd->show_all();
Gtk::main();
?>

Der Start passiert aus der Kommandozeile heraus:

C:\phpgtk\php-gtk2>php.exe example1.php

… und schon öffnet sich das entsprechende Fenster.

Um etwas mehr als das einfache „Hello World“ Progrämmchen zu schreiben fiel mir der Artikel von letztem Dienstag über 7-PDF ein: Warum schreibe ich nicht schnell eine Oberfläche zur PDF-Konvertierung?

Gesagt getan, nach 30 Minuten hatte ich eine ganz rudimentäre Oberfläche inklusive PDF-Konvertierer für 84 Formate:

Einen Stolperstein gab es dabei jedoch: Bei dem GTK2 Paket war keine SOAP-Extension dabei, da mußte ich mir erst noch die passende Datei herunterladen und in die php-cli.ini einbinden. Im PHP-Museum (/php5/php-5.2.5-nts-Win32.zip) habe ich die passende php_soap.dll Datei gefunden.

<?
if (!class_exists('gtk')) {
	die("Please load the php-gtk2 module in your php.ini\r\n");
}

//Create the login window
$wnd = new GtkWindow();
$wnd->set_title('7-PDF Converter');
//Close the main loop when the window is destroyed
$wnd->connect_simple('destroy', array('gtk', 'main_quit'));

//Set up all the widgets we need
$lblCredit   = new GtkLabel('Please provide your data');
//The second parameter says that the underscore should be parsed as underline
$lblUsername = new GtkLabel('_Username', true);
$lblPassword = new GtkLabel('_Password', true);
$lblInFile = new GtkLabel('_File to convert', true);
$lblOutFile = new GtkLabel('P_DF destination filename', true);
$txtUsername = new GtkEntry();
$txtPassword = new GtkEntry();
$txtInFile = new GtkEntry();
$txtOutFile = new GtkEntry();
$btnStart    = new GtkButton('Start');

//Which widget should be activated when the
// mnemonic (Alt+U or Alt+P) is pressed?
$lblUsername->set_mnemonic_widget($txtUsername);
$lblPassword->set_mnemonic_widget($txtPassword);
$lblInFile->set_mnemonic_widget($txtInFile);
$lblOutFile->set_mnemonic_widget($txtOutFile);
//Hide the password
//$txtPassword->set_invisible_char('*');

//Call the login function when the user clicks on Login
$btnStart->connect_simple('clicked', 'convertToPdf', $wnd, $txtUsername, $txtPassword, $txtInFile, $txtOutFile);

//Lay out all the widgets in the table
$tbl = new GtkTable(5, 2);
$tbl->attach($lblCredit, 0, 2, 0, 1);
$tbl->attach($lblUsername, 0, 1, 1, 2);
$tbl->attach($txtUsername, 1, 2, 1, 2);
$tbl->attach($lblPassword, 0, 1, 2, 3);
$tbl->attach($txtPassword, 1, 2, 2, 3);
$tbl->attach($lblInFile, 0, 1, 3, 4);
$tbl->attach($txtInFile, 1, 2, 3, 4);
$tbl->attach($lblOutFile, 0, 1, 4, 5);
$tbl->attach($txtOutFile, 1, 2, 4, 5);

//Add the buttons to a button box
$bbox = new GtkHButtonBox();
$bbox->set_layout(Gtk::BUTTONBOX_EDGE);
$bbox->add($btnStart);

//Add the table and the button box to a vbox
$vbox = new GtkVBox();
$vbox->pack_start($tbl);
$vbox->pack_start($bbox);

//Add the vbox to the window
$wnd->add($vbox);
//Show all widgets
$wnd->show_all();
//Start the main loop
Gtk::main();

function convertToPdf(GtkWindow $wnd, GtkEntry $txtUsername, GtkEntry $txtPassword, GtkEntry $txtInFile, GtkEntry $txtOutFile)
{
	//fetch the values from the widgets into variables
	$strUsername = $txtUsername->get_text();
	$strPassword = $txtPassword->get_text();
	$strinFile = $txtInFile->get_text();
	$strOutFile = $txtOutFile->get_text();

	try {
		$path = realpath(dirname(__FILE__) . '/classes');
		set_include_path($path . PATH_SEPARATOR . get_include_path());

		// create a new object, provide options by array in constructor
		require_once 'SevenPdf/Client.php';
		$sevenPdfClient = new SevenPdf_Client(
			array(
				'username' => $strUsername,
				'password' => $strPassword
			)
		);
		$sevenPdfClient->convertToPdf($strinFile, $strOutFile);
		$dialog = new GtkMessageDialog($wnd, Gtk::DIALOG_MODAL,
				Gtk::MESSAGE_INFO, Gtk::BUTTONS_OK, 'convert complete');
		$dialog->set_markup('convert complete');
		$dialog->run();
		$dialog->destroy();
	} catch (Exception $e) {
		$dialog = new GtkMessageDialog($wnd, Gtk::DIALOG_MODAL,
				Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, $e->getMessage());
		$dialog->set_markup($e->getMessage());
		$dialog->run();
		$dialog->destroy();
	}
} ?>

Der Wiederverwendung von PHP-Code und Benutzung für eine Desktop-Anwendung steht also nichts im Weg.

Written by Michael Kliewe

März 22nd, 2010 at 9:25 am

Die „Technik“ hinter 7-PDF Server

with one comment

So, nachdem Michael dankenswerterweise seinen ersten Blogartikel über die 7-PDF PHP Library verfasst hat, wird es nun Zeit euch meinem ersten Gastbeitrag überhaupt in einem Online-Blog zu präsentieren. Ich muss gestehen, ich bin daher ein wenig aufgeregt.

Ich möchte euch zuerst einmal einige technische Hintergrundinformationen zum 7-PDF Server geben, bevor es dann weiter zu den Installationschritten des Servers unter Windows geht.

Fangen wir also an…

Was genau verbirgt sich eigentlich hinter 7-PDF Server?

7-PDF Server basiert im Kern aus zwei „Softwarekomponenten“ die unter Java entwickelt, und auf einem Tomcat Applikationsserver laufen, sowie einer OpenOffice.org Instanz. Im einzelnen handelt es bei den Komponenten also um:

  • …einem von mir entwickelten J2EE-Webservice, den ich „7-PDF API“ getauft habe,
  • …einer ebenfalls von mir entwickelten J2EE-Webapplikation, die „7-PDF Web Portal“ heisst, und als PDF-Browsertool PDF-Erzeugung über ein „Webinterface“ ermöglich,
  • …sowie einer selbst kompilierten, und für den Serverbetrieb optimierten OpenOffice.org Instanz

Das „Zusammenspiel“ zwischen der 7-PDF PHP Library, 7-PDF API und Openoffice.org…

Werfen wir nun einen Blick unter die „Motorhaube“ des 7-PDF Servers um einen ersten Einblick in die Technologie und das Zusammenspiel der oben genannten Softwarekomponenten zu erhalten:

Ausgangspunkt soll hier einmal die Verwendung der 7-PDF PHP Library sein. Nutzen wir die Library dazu eine Datei nach PDF zu konvertieren, wie im Artikel von Michael beschrieben, so sprechen wir als erste Komponente die 7-PDF API, also den „Webservice“ des 7-PDF Servers an. Der „7-PDF API“ Webservice bietet erst einmal die simple Möglichkeit, von nahezu jeder webservicefähigen Programmiersprache, mittels SOAP angesprochen und verwendet werden zu können. Mit Blick auf die 7-PDF PHP Library steht euch für PHP bereits eine fertige PHP-Library zur Verfügung um diesen „Service“ mit Dateikonvertierungen nach PDF zu „beauftragen“.
Beauftragen wir nun einmal gedanklich den „Service“ mit einer Dateikonvertierung nach PDF. Die Datei wird hierfür von der PHP-Library via WebDAV an den 7-PDF Server übermittelt. Der Service erhält, nach erfolgreicher Übertragung der Eingangsdatei, von der PHP-Library eine SOAP-Meldung mit darin enthaltenen Informationen wie Speicherort der Eingangsdatei am Server, PDF-Konvertierungseinstellungen (Bildkompressionsrate, PDF-Sicherheitseinstellungen etc.) etc. Die empfangene SOAP Meldung leitet der Webservice über eine Java-Softwareschnittstelle (Java UNO-Bridge) an OpenOffice.org weiter. Die Java UNO-Bridge wird von OpenOffice.org zur Verfügung gestellt, dass heisst, Sie ist quasi Bestandteil von OpenOffice.org selbst und ermöglicht es Funktionalitäten der Office-Suite in eigene Java-Anwendungen zu nutzen. Im Falle von 7-PDF Server, bedienen wir uns des „genial integrierten“ PDF-Exports von OpenOffice.org, und sprechen diesen für die angestoßene Konvertierung an. Das Eingangsdokument wird nun, von dem im Servermodus laufenden OpenOffice.org, nach PDF konvertiert. Ist diese Konvertierung beendet, sendet der Webservice eine entsprechende Meldung an den (SOAP)-Client zurück. In der Meldung enthalten ist dann der Speicherpfad des zuvor erzeugten PDF-Dokuments am Server. Die PHP – Library, die in unserem Beispiel nun den SOAP-Client darstellt, kann dann mit dem Download der fertigen PDF-Datei beginnen.

Ich habe bewusst keine SOAP-Attachments bei der Realisierung der 7-PDF API in Erwägung gezogen, da ich speziell für den Dateiupload WebDAV für das „geeignetere“ Protokoll hielt. Den die Anforderungen an 7-PDF Server haben gezeigt, dass auch sehr große Dateien sicher nach PDF umgewandelt werden müssen. Im Grunde wird also mittels SOAP nur die gewünschte Konvertierungsabsicht an den Webservice übermittelt.

Ein Abschnitt zur Rechteverwaltung…

WebDAV hat zudem noch einen weiteren entscheidenden Vorteil in Verbindung mit Tomcat: Das benötigte WebDAV-Servlet ist Teil des Tomcat-Applikationsservers, und es kann direkt mit der Rechtesteuerung des Applikationsservers „Tomcat“ (Security-Constraints / Realm) verwendet werden. Also kann man die Übertragung der Eingangsdokumente recht einfach mit einer Rechteverwaltung versehen. Ich habe beispielsweise auf meiner 7-pdf.de – Website die Typo3-Frontendregistrierung des CMS-Systems für den freien Online- und Testkonvertierungsserver, an die Rechtesteuerung des Tomcat Applicationservers gebunden. Die Rechteverwaltung findet damit dynamisch, über entsprechende MySQL-Tabellen von Typo3 statt. Es ist grundsätzlich auch möglich 7-PDF Server beispielsweise über LDAP an ein Active Directory anzubinden usw. Entsprechende Dokumentationen findet man unter den Stichworten „Tomcat“ und „Realm“ im Web.

Damit sollte euch nun das prinzipielle Zusammenspiel der Softwarekomponenten des 7-PDF Servers klar sein, und auch klar sein wie eine PDF-Konvertierung auf dem 7-PDF Server grundsätzlich abläuft.

Einige Zeilen möchte ich an dieser Stelle noch über die Performance dieser PDF-Erzeugung „verlieren“: OpenOffice.org arbeitet im Servermodus derart performant, dass 2000 – 4000 Dateikonvertierungen pro Stunde nach PDF kein Problem darstellen. Vorausgesetzt das Hardware-Sizing und die Bandbreite zwischen „Server“ und „Client“ stimmen. Auch wenn ich mich persönlich bereits seit Jahren intensiv mit dieser „Technologie“ auseinandersetze, finde ich doch hauptsächlich diese Performance „bis heute“ – bemerkenswert.

Wer sich näher mit der Programmierung von Java Webservices oder der Programmierung von OpenOffice.org beschäftigen möchte, den seien die jeweiligen SDK’s der Softwarehersteller ans Herz gelegt. Nähere Informationen speziell zur erwähnten Java UNO-Bridge sind der Dokumentation des OpenOffice.org SDK’s auf der OpenOffice.org Website zu entnehmen.

Die Installation des 7-PDF Servers…

Kommen wir also nach dem Blick unter die Motorhaube von 7-PDF Server zur eigentlichen Installation. Hierfür steht bereits eine fertige Setupinstallation für das Betriebsystem Windows auf www.7-pdf.de/download zur Verfügung. Diese installiert dabei den 7-PDF Server als „lokalen Dienst“, optional steht auch die Startoption „Manuell“ zur Auswahl. Alle notwendigen Verknüpfungen stehen nach der Installation in einem entsprechenden Programmgruppen-Verzeichnis unter „Start → Programme → 7-PDF → 7-PDF Server“ zur Verfügung. Neben den Start/Stop – Verknüpfungen für das manuelle Anstarten des Servers, findet man hier auch Direktlinks zu den Web- und Downloadseiten der 7-PDF Libraries (Java und PHP).

Unter meinem Windows 7 „Professional“ 64Bit – System sieht das nach der Installation so aus:

Die Abbildung zeigt die Programmgruppe des 7-PDF Servers nach der Installation.

Einige Shortcut-Infos zur Installation…

  • 7-PDF Server installiert sich als „7pSrv“ – Dienst auf Windows-Systemen
  • Man benötigt eine funktionsfähige JRE-Installation >= Version 1.5 (JRE5) auf dem System
  • Port 8080 → Der primäre Netzwerkport, auf dem der 7-PDF Server kommuniziert.
    Hinweis: Dieser Port sollte über eventuell laufende Firewalls freigeschaltet werden, damit der 7-PDF Server auch im lokalen Netzwerk erreicht werden kann.
  • Folgende Ports sollten auf deinem System nicht bereits belegt sein:
    Port 8100 → für die im Servermodus betriebene OpenOffice.org Instanz
    Port 8005, 8009 → Sind vom Tomcat-Applikationsserver benötigte Ports
  • Für einen „richtig flüssigen“ Betrieb des Servers empfiehlt sind eine Hardware mit folgenden „Eckdaten“:
    2-4GB RAM, >=2 GHz CPU, 230MB Festplattenspeicher für die Serverinstallation, sowie ausreichend Festplattenspeicher für temporär erzeugte Dateien.
  • Als Betriebssystem tut es im Grunde Windows XP Professional, eine Installation unter Windows 2003 + 2008 Server, sowie VISTA und Windows 7 ist natürlich grundsätzlich auch möglich. Der Betrieb des Servers unter Windows 64-Bit Betriebssystemen ist ebenfalls möglich. Für den produktiven Einsatz, sollte 7-PDF Server generell aber auf einem Serverbetriebssystem installiert und betrieben werden. Ich habe 7-PDF Server unter Windows 2003 Server (64 Bit) im produktiven Einsatz.

Die Windowsinstallation – „Step by Step“…

Das eigentliche Setup des 7-PDF Servers gestaltet sich, wie bereits Eingangs erwähnt, unter Windows ziemlich rudimentär und ist selbsterklärend. Die nachfolgenden Screenshots zeigen dies anschaulich:

1. Schritt: Sprache wählen

2. Schritt: Willkommen-Dialog

3. Schritt: Lizenzvereinbarungen

4. Schritt: UserGuide zum Server

5. Schritt: Installationspfad wählen

6. Schritt: Programmgruppe wählen

7. Schritt: Java und 7-PDF Server Startoptionen wählen

8. Schritt: Einstellungen prüfen

9. Schritt: Installationsvorgang

10. Schritt: Neustart nach Installation

Nach dem Neustart des Systems, startet 7-PDF Server nach Auswahl der oben gezeigten Installationsschritte als Windows-Dienst „7pSrv“ automatisch. Der nachfolgende Screenshot zeigt den Servereintrag in der „Dienste“-Verwaltung von Windows nach dem Neustart des Systems:

Auf dem Desktop werden euch zudem zwei Verknüpfungen angelegt, unter anderem auch eine Verknüpfung um 7-PDF Web Portal im Browser direkt „lokal“ zu öffnen.

Ein Doppelklick darauf beschert uns folgendes Bild:

An der URL sehen wir, dass 7-PDF Server lokal unter http://localhost:8080 läuft und damit auch der 7-PDF API Webservice, den wir direkt mit unserer 7-PDF PHP Library „ansprechen“ können.

Es bietet sich aber auch an dieser Stelle an, zuerst einmal eine Datei nach PDF über das „Webinterface“ – 7-PDF Web Portal zu konvertieren. Die „zweite“ Softwarekomponente des 7-PDF Servers bietet uns nämlich interessante Möglichkeiten der PDF-Erzeugung. Das „Webinterface“ ist dem „7-PDF Maker“, also meinem Freeware PDF-Erzeuger für Windows, nachempfunden und ideal für Endanwender.
Neben Bildkompressionsraten, der Erzeugung automatischer Hyperlinks im PDF, bietet das Webinterface auch Option der Passwort- und Rechteverschlüsselung von PDF-Dateien unter dem Reiter „Sicherheit…“.

Und das Beste für uns Entwickler: Alle Funktionen, welche im Webinterface zur Verfügung stehen, werden von der 7-PDF API, und natürlich damit auch von der 7-PDF PHP Library unterstützt. Einen vollwertigen PDF-Konverter kannst du so also direkt in deine eigenen PHP-Applikationen einbinden.

Aus der Praxis für die Praxis…oder besser – zwei konkrete Anwendungsfälle…

Eine Firma nutzt 7-PDF Server in Verbindung mit der PHP-Library dafür, erzeugte Officedokumente erst einmal nach PDF umzuwandeln, um danach diese PDF-Dateien mit FPDI (Erweiterte PHP FPDF Library) an Firmen-CI’s anzugleichen und mit einer Versionierung zu versehen. Diese „Technik“ wird in einem Qualitätsmanagement-System (QM-System) des Kunden, welches auf Typo3 basiert, eingesetzt.

Ein weiterer Anwender nutzt 7-PDF Server in seinem Dokumenten-Management-System (DMS). Alle Officedokumente werden hier vor der Abspeicherung im DMS von 7-PDF Server nach PDF umgewandelt. Und warum nutzt man nicht die interne PDF-Funktion des DMS-Systems?
Da das DMS mehrere hundert Dateien pro Stunde bewältigen musste, konnte man aus Performancegründen nicht mehr auf die „interne“ druckstreambasierte PDF-Erzeugung des DMS-Systems zurückgreifen. Man bediente sich der Technologie von 7-PDF Server, welches diese Last der PDF-Erzeugung locker bewältigen konnte. Welcher Anwender „verarbeitet“ so viele Dokumente in einem DMS könnte man Fragen. Nun, dieser Anwender ist eine Landesregierung aus Österreich, die ihr komplettes eGovernment auf Basis von workflowgestützten DMS-Systemen abwickelt und verwaltet.

So – jetzt widmen wir uns aber wieder der eigentlichen Installation zu. Sonst schweife ich gleich bei meinem ersten Blogartikel zu weit vom Thema ab, das wäre euch sicherlich nicht recht 😉

Die 7-PDF PHP Library für eine Lokalinstallation anpassen…

Wollen wir eine lokale PDF-Konvertierung über den nun installierten 7-PDF Server mit Hilfe der 7-PDF PHP Library durchführen, so liegt es nahe das in der PHP-Library enthaltene Beispielscript von Michael „convert2.php“ für die erste lokale Konvertierung anzupassen:

<?php
// make sure that the classes folder is in include path
$path = realpath(dirname(__FILE__) . '/../classes');
set_include_path($path . PATH_SEPARATOR . get_include_path());

// create a new object
require_once 'SevenPdf/Client.php';
$sevenPdfClient = new SevenPdf_Client();
$sevenPdfClient->setUsername('sevenpdf')
 ->setPassword('sevenpdf')
 ->useSsl(false)
 ->setServicePort(8080)
 ->setServiceHost('localhost');

//Set some additional PDF Settings
$sevenPdfClient->setEncryptFile(true); //set PDF Encryption
$sevenPdfClient->setDocumentOpenPassword('test'); //set Open Password

$sevenPdfClient->convertToPdf('invoice.html', 'invoice.pdf');

Unsere Anpassungen beschränken sich dabei lediglich auf die Zugangsdaten, Host und Port anzupassen, sowie SSL zu deaktivieren.

Wichtig an dieser Stelle ist auch zu erwähnen, dass mit der Installation des 7-PDF Servers bereits ein „vorkonfigurierter“ WebDAV – Zugang für die Eingangsdokumente installiert wird. Der Benutzername ist: sevenpdf, das Passwort ebenfalls (siehe Sourcebeispiel!)

Neben den bereits weiter oben angesprochenen recht „komplexen“ Realm-Rechteverwaltungskonzept des Tomcat-Applikationsservers, gibt es auch eine einfache Rechtesteuerung die direkt im Applikationsserver selbst über „eine“ XML-Datei zentral „gesteuert“ werden kann. Dieser habe ich mich, für den bereits oben erwähnten „vorkonfigurierten“ WebDAV-Zugang, bedient. Will man seinen eigenen „WebDAV“-User anlegen, oder auch das Passwort ändern (aus Sicherheitsgründen immer sinnvoll), so ist hierzu im Installationspfad des 7-PDF Servers die „tomcat-users.xml“ Datei die richtige Anlaufstelle. Zu finden unter:

[InstallPfad]\tomcat\conf\tomcat_users.xml

In dieser Datei verwaltet der Applikationsserver “zentral” Benutzer- und Gruppenrechte.
Der XML-Aufbau der “Rechte”-Datei des Tomcats ist nicht wirklich komplex. Und man kann sie recht leicht mit einem Editor anpassen und erweitern:

<?xml version='1.0' encoding='utf-8'?>
<tomcat-users>
 <role rolename="manager"/>
 <role rolename="tomcat"/>
 <role rolename="sevenpdf"/>
 <role rolename="role1"/>
 <user username="both" password="tomcat" roles="tomcat,role1"/>
 <user username="tomcat" password="tomcat" roles="tomcat"/>
 <user username="sevenpdf" password="sevenpdf" roles="sevenpdf"/>
 <user username="thorsten" password="hodes" roles="sevenpdf"/>
 <user username="admin" password="admin" roles="manager"/>
 <user username="role1" password="tomcat" roles="role1"/>
</tomcat-users>

Als Beispiel habe ich den username=“thorsten“ mit dem Passwort password=“hodes“ angelegt bzw. diese Zeile in der tomcat_users.xml dafür hinzugefügt. Fehlt nur noch der eigene WebDAV-Konvertierungsordner und eine kleine Erweiterung der WebDAV-Rechte darauf. Das machen wir als nächstes.

Zuerst legen wir den benötigten WebDAV Ordern für den User „thorsten“ an:

Als nächstes setzen wir die WebDAV-Rechte. Das geht wieder über eine XML-Datei „web.xml“ im Verzeichnis: [InstallPfad]\tomcat\webapps\webdav\WEB-INF

Die XML-Datei bindet das WebDAV-Servlet des Tomcat Applikationsservers an entsprechend definierte Benutzer- und Gruppenrechte des Servers – hier speziell aus der „tomcat-users.xml“ – Datei. Man kann die Datei mit einem normalen Editor bearbeiten:

<?xml version="1.0" encoding="ISO-8859-1"?>
<!--
 Copyright 2004 The Apache Software Foundation

 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at

 http://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
-->

<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
 version="2.4">

 <display-name>Webdav Content Management</display-name>
 <description>
 Webdav Content Management
 </description>

 <servlet>
 <servlet-name>webdav</servlet-name>
 <servlet-class>org.apache.catalina.servlets.WebdavServlet</servlet-class>
 <init-param>
 <param-name>debug</param-name>
 <param-value>0</param-value>
 </init-param>
 <init-param>
 <param-name>listings</param-name>
 <param-value>false</param-value>
 </init-param>
 <!-- Uncomment this to enable read and write access -->

 <init-param>
 <param-name>readonly</param-name>
 <param-value>false</param-value>
 </init-param>

 <!--load-on-startup>1</load-on-startup-->
 </servlet>

 <!-- The mapping for the webdav servlet -->
 <!-- Using /* as the mapping ensures that jasper, welcome files etc are
 over-ridden and all requests are processed by the webdav servlet.
 This also overcomes a number of issues with some webdav clients
 (including MS Webfolders) that do not respond correctly
 to the
 redirects (302) that result from using a mapping of / -->
 <servlet-mapping>
 <servlet-name>webdav</servlet-name>
 <url-pattern>/*</url-pattern>
 </servlet-mapping>

 <!-- ================ Security Constraints for 7-PDF Server (Windows Setup Version) =============== -->

 <!-- Secure WebDAV - ROOT with these Authentification Role -->
 <security-constraint>
 <web-resource-collection>
 <web-resource-name>WebDAV-Root Authentification</web-resource-name>
 <url-pattern>/*</url-pattern>
 </web-resource-collection>
 <auth-constraint>
 <role-name>admin</role-name>
 </auth-constraint>
 </security-constraint>

 <!-- Secure CONVERTS - DIRECTORY with these Authentification Role -->
 <security-constraint>
 <web-resource-collection>
 <web-resource-name>WebDAV-CONVERTS Authentification</web-resource-name>
 <url-pattern>/sevenpdf/*</url-pattern>
 </web-resource-collection>
 <auth-constraint>
 <role-name>sevenpdf</role-name>
 </auth-constraint>
 </security-constraint>

 <!-- Secure CONVERTS - DIRECTORY with these Authentification Role -->
 <!-- ADDED FOR FOLDER "thorsten" -->
 <security-constraint>
 <web-resource-collection>
 <web-resource-name>WebDAV-CONVERTS Authentification</web-resource-name>
 <url-pattern>/thorsten/*</url-pattern>
 </web-resource-collection>
 <auth-constraint>
 <role-name>sevenpdf</role-name>
 </auth-constraint>
 </security-constraint>

 <!-- Security Role Settings -->
 <security-role>
 <description>
 An webdav role defined in "conf/tomcat-users.xml"
 </description>
 <role-name>sevenpdf</role-name>
 </security-role>

 <security-role>
 <description>
 An webdav role defined in "conf/tomcat-users.xml"
 </description>
 <role-name>admin</role-name>
 </security-role>

 <login-config>
 <auth-method>BASIC</auth-method>
 <realm-name>7-PDF Server - Security Login</realm-name>
 </login-config>

</web-app>

Ich habe hier einfach eine sogenannte „Security-Constraint“ für den User „thorsten“ angelegt und diese an die Rolle (role) „sevenpdf“ angebunden. Das war es auch schon. Damit der neue Benutzer in 7-PDF Server „bekannt“ wird, startet man den „7pSrv“-Dienst neu durch.

Kommen wir nun wieder zu unserem PHP-Konvertierungsscript „convert2.php“. Wir passen es natürlich schnell auf unseren neuen 7-PDF Server – „Benutzer“ an:

<?php
// make sure that the classes folder is in include path
$path = realpath(dirname(__FILE__) . '/../classes');
set_include_path($path . PATH_SEPARATOR . get_include_path());

// create a new object
require_once 'SevenPdf/Client.php';
$sevenPdfClient = new SevenPdf_Client();
$sevenPdfClient->setUsername('thorsten')
 ->setPassword('hodes')
 ->useSsl(false)
 ->setServicePort(8080)
 ->setServiceHost('localhost');

//Set some additional PDF Settings
$sevenPdfClient->setEncryptFile(true); //set PDF Encryption
$sevenPdfClient->setDocumentOpenPassword('test'); //set Open Password

$sevenPdfClient->convertToPdf('invoice.html', 'invoice.pdf');

GESCHAFFT!

Es bietet sich nun an das Beispielscript convert2.php auszuführen. Ich habe parallel auf Port 80 dafür eine aktuelle XAMPP-Installation mit Apache+PHP5 unter Windows laufen lassen.

Hinweis: Vergesst nicht die SOAP-Extension für PHP5 „aktiv“ zu haben, da wir ja mittels SOAP den 7-PDF Server bzw. die 7-PDF API zum Arbeiten bewegen wollen 😉

Damit ist im Grunde neben den Hintergrundinformationen zum 7-PDF Server, nun auch die lokale Installation des Servers erklärt. Ich hoffe, euch hat mein allererster Blogartikel gefallen? In einem der folgenden Blog-Artikel werde ich die Installation des 7-PDF Servers unter Linux beschreiben. Diese ist im Gegensatz zur Windows-Installation um einiges komplexer, generell machbar, und sehr interessant 🙂

Bis dahin wünsche ich euch alles Gute.

Euer Thorsten Hodes

Written by Thorsten Hodes

März 17th, 2010 at 8:58 am

84 Formate nach PDF konvertieren mit 7-PDF

with 5 comments

Vor kurzem bin ich von Thorsten Hodes auf sein Projekt aufmerksam gemacht worden und er fragte, ob das vielleicht von Interesse ist und ich es hier mal vorstellen möchte. Natürlich möchte ich!

Sein Projekt heißt 7-PDF und ist ein Service bzw. Server, mit dessen Hilfe man nahezu jedes bekannte Bild- und Textformat (aktuell werden 84 Formate unterstützt) nach PDF konvertieren kann. Das ist natürlich besonders interessant für Dateien, die bereits vorliegen und zusätzlich noch als PDF zur Verfügung stehen sollen, als auch zur Erstellung neuer PDFs. Häufig ist es einfacher, einen Text schnell via HTML zusammenzustellen, zu formatieren und dieses HTML dann in ein PDF-Dokument zu konvertieren, als z.B. mit Hilfe von Zend_Pdf, FPDF, PDFlib und wie sie alle heißen programmatisch neue PDF-Dokumente zu erstellen.

Nehmen wir also an, wie haben bereits ein fertiges Word-2007-Dokument, zum Beispiel eine Rechnung. Diese möchten wir dem Kunden nun auch als PDF zum Download zur Verfügung stellen. Mit den oben genannten programmatischen Lösungen funktioniert das nicht, was wir brauchen ist ein Konverter, und genau das ist 7-PDF.

7-PDF ist ein Service, den man sowohl kostenlos online nutzen kann (Thorsten stellt dort einen Server im Internet bereit, den man zum Konvertieren nutzen kann), oder man lädt sich den 7-PDF Server herunter und installiert ihn lokal, dann verlassen die Rechnungen nicht den eigenen Server bzw. die Firma.

Diesem Service übersendet man die zu konvertierende Datei, definiert einige Einstellungen (PDF-Passwort, Bilderkomprimierung usw.), startet dann den Konvertierungsprozess und erhält das generierte PDF-Dokument. Dazu gibt es als Client sowohl eine Windows-Anwendung, eine Java-Client-Library und auch eine PHP-Client-Library, die ich hier natürlich vorstellen möchte.

Der Server, der intern auf OpenOffice zurückgreift, kann dabei ca. 2000 PDF-Dokumente pro Stunde konvertieren. Das ist natürlich abhängig von der Größe der Dateien und ob der Service parallel befeuert wird oder nicht. Aber es ist recht performant, soviel kann man sagen.

Nun zur Praxis: Wir wollen also eine .docx-Datei nach PDF konvertieren. Das ist schnell gemacht mit dem kostenlosen Online-Service und dem PHP-Client:

require_once 'SevenPdf/Client.php';
$sevenPdfClient = new SevenPdf_Client();
$sevenPdfClient->setUsername('libdemouser')
		->setPassword('12345')
		->useSsl(true);

//Set some additional PDF Settings
$sevenPdfClient->setEncryptFile(true); //set PDF Encryption
$sevenPdfClient->setDocumentOpenPassword('test'); //set Open Password

$sevenPdfClient->convertToPdf('invoice.docx', 'invoice.pdf');

Das ist etwas mehr als ein Minimalbeispiel, aber man kann dort schön sehen, was so alles möglich ist. Zur Demonstration reicht hier der „libdemouser“ aus, sobald man aber vertrauliche Daten nutzt sollte man sich einen kostenlosen Account auf der Webseite registrieren auf den andere keinen Zugriff haben, oder sich lokal einen Server installieren. SSL wird für die Verbindung aktiviert ebenso wie die PDF-Verschlüsselung bzw. der Passwortschutz. Dann wird der Funktion „convertToPdf“ die Word-Datei und der Speicherort für die PDF-Datei übergeben. Das war es schon.

Morgen wird Thorsten selbst hier auch noch einen Artikel veröffentlichen und die Installation des Servers vorstellen (*jubel*, der erste Gastbeitrag!).

Written by Michael Kliewe

März 16th, 2010 at 9:10 am

Twitter-Applikationen mit Zend_Oauth

with 12 comments

Kurz vorab: Ich möchte mich bei euch Lesern bedanken, ihr habt mich dazu gebracht hier nun den 100. Artikel zu verfassen. Außerdem folgen mir aktuell 98 Leute bei Twitter (vielleicht werden es ja heute 100?), wenn das kein Grund zu feiern ist! Danke euch dafür! Doch nun gehts los:

In den Kommentaren zu meinem Artikel über das Twittern via PHP wurde ich darum gebeten die Twitter-API-Benutzung auch mittels OAuth zu zeigen. Das werde ich hier nun tun, mit einer kleinen Erklärung zu OAuth und dann natürlich auch PHP-Code.

Doch was ist OAuth? Normalerweise nutzt man zur API-Kommunikation die Twitter-Login-Informationen. Nehmen wir an wir wollen einen kleinen Dienst im Internet anbieten, den andere Leute nutzen können. Dabei soll unser Dienst auf den Account der Nutzer zugreifen und Daten auslesen oder gar verändern. Damit wir den Dienst umsetzen können müssen unsere Nutzer also ihre Login-Usernamen und Passwörter bei uns eintragen. Damit verfügen wir über die volle Kontrolle über diese Accounts, könnten sie also auch löschen, das Passwort ändern usw. Da sicherheitsbewusste Benutzer ihr Passwort nicht hergeben, wird niemand unseren Dienst nutzen. Von dem Problem, dass der Nutzer bei einem Passwortwechsel auch alle Applikationen in Kenntnis setzen müßte mal ganz abgesehen.

OAuth ist nun eine Möglichkeit, unserer Applikation begrenzten Zugang zu den Accounts zu geben, aber nicht mittels dem normalen Login-Passwort, sondern einem extra Passwort (Access-Token) für die Kombination aus unserer Applikation und dem Nutzerkonto. Dieser Zugang kann dann auch beschränkt werden zum Beispiel auf nur lesenden Zugriff. Außerdem kann der Zugang wieder entzogen werden. Der Accountbesitzer behält also die volle Kontrolle über seinen Account.

Unser Vorgehen sieht nun wie folgt aus:

  1. Unsere Applikation benötigt von Twitter einen sogenannten Consumer-Key und ein Consumer-Secret. Das müssen wir uns von Twitter besorgen und identifiziert unsere Applikation später beim Token-Austausch. Außerdem wird beides dann zu einer Art Verschlüsselung beim Token-Austausch genutzt.
  2. Nachdem der potentielle Nutzer nun auf unsere Webseite gegangen ist müssen wir uns für ihn einen Token besorgen. Dazu holen wir uns einen temporären unauthorisierten Token von Twitter.
  3. Mit diesem unauthorisierten Token leiten wir den User auf eine Seite von Twitter, wo er dann gefragt wird, ob er unserer Applikation den begrenzten API-Zugriff erlauben möchte. Falls er das tut, wird er zurück auf unsere Seite geleitet
  4. Wir erhalten nun den authorisierten Token, den wir in einer Datenbank abspeichern. Ab jetzt können wir auf das Nutzerkonto zugreifen, und der Nutzer hat seine Twitter-Logininformation nicht preisgeben müssen.

Da diese OAuth-Kommunikation standardisiert ist und im Detail auch etwas komplizierter, werden wir das nicht selbst implementieren sondern die Zend_Oauth-Klasse nutzen. Seit Zend Framework 1.10 ist diese im Lieferumfang enthalten. Es gibt auch noch weitere OAuth-Klassen, die genutzt werden können. Danach werden wir in Zusammenspiel mit Zend_Service_Twitter auf den Account zugreifen und einen Tweet absetzen.

Fangen wir also an:

Um den Consumer-Key und das Consumer-Secret zu erhalten registrieren wir unsere neue Applikation: http://twitter.com/oauth_clients

Wir benötigen auch Write-Rechte, da wir ja einen Tweet absetzen möchten. Nach erfolgreicher Applikationsregistrierung erhalten wie die besagten beiden Informationen:

Nun schreiben wir unsere kleine Testapplikation. Darin sind die Punkte 2-4 abgehandelt. Der Einfachkeit halber speichern wir den ACCESS_TOKEN nur in der Session, normalerweise würde man diesen zu den Nutzerinformationen in die Datenbank schreiben.

<?php
session_start();

require_once 'Zend/Oauth/Consumer.php';

$options = array(
        'callbackUrl'    => 'https://www.phpgangsta.de/twitter.php',
        'siteUrl'        => 'http://twitter.com/oauth',
        'consumerKey'    => '4c2jXXXXXXXXXXXXXXBkw',
        'consumerSecret' => 'iPkXiOXXXXXXXXXXXXXXXXXXXXXXbSAJRhE',
);

$consumer = new Zend_Oauth_Consumer($options);

if (!isset($_SESSION['ACCESS_TOKEN'])) {
    if (empty($_GET)) {
        $token = $consumer->getRequestToken();
        $_SESSION['REQUEST_TOKEN'] = serialize($token);
        $consumer->redirect();
    } else {
        $token = $consumer->getAccessToken($_GET, unserialize($_SESSION['REQUEST_TOKEN']));
        $_SESSION['ACCESS_TOKEN'] = serialize($token);
        unset($_SESSION['REQUEST_TOKEN']);
    }
}

if (isset($_SESSION['ACCESS_TOKEN'])) {
    $token = unserialize($_SESSION['ACCESS_TOKEN']);
    $client = $token->getHttpClient($options);

    require_once 'Zend/Service/Twitter.php';
    $twitter = new Zend_Service_Twitter();
    $twitter->setLocalHttpClient($client);
    $response = $twitter->status->update('Nachricht gesendet authentifiziert via OAuth');
}

Der Ablauf ist klar und wie oben beschrieben: Das Script holt sich einen Request-Token, der Nutzer wird dann auf die Twitter-Seite redirected und gefragt ob er den Zugriff erlauben möchte. Danach kommt er zurück auf unsere Seite (die wir bei der Registrierung angegeben haben, man kann diese auch mit dem Request abändern), wir holen uns aus den GET-Parametern den ACCESS_TOKEN und speichern ihn (in der Session). Danach können wir den TOKEN nutzen um zu twittern.

Dazu können wir entweder die oben beschriebene Methode nutzen und mit Hilfe des $token einen Http_Client erstellen den wir dann an den Twitter-Service geben. Dieser Client erledigt das Mitsenden der OAuth-Informationen bei jedem Request automatisch für uns. Oder aber wir nutzen den Http_Client direkt:

$client = $token->getHttpClient($options);
$client->setUri('http://twitter.com/statuses/update.json');
$client->setMethod(Zend_Http_Client::POST);
$client->setParameterPost('status', 'Nachricht gesendet authentifiziert via OAuth');
$response = $client->request();

Natürlich kann man die vergebenen Berechtigungen an Applikationen auch zurückziehen. Das geht auf der Seite https://twitter.com/account/connections:

Das war es auch schon für heute, ich hoffe das Prinzip von OAuth ist etwas klarer geworden und ihr könnt den Code nutzen um eigene Twitter-Applikationen zu erstellen.

Hier noch einige interessante Links zu (englischsprachigen) Tutorials und Übersichtsseiten:

Written by Michael Kliewe

März 14th, 2010 at 2:54 pm

Posted in PHP

Tagged with , , , ,

Linkpool Nummer 3

without comments

Interessante Vorstellung, Maßnahmen zu ergreifen innerhalb von 3 Minuten, um den Server zu retten während er überrannt wird:
http://www.stochasticgeometry.ie/2010/03/10/performance-tuning-a-server-in-three-minutes-while-being-slashdotte/

Schöne Übersicht von Ralf Eggert zum Zend Framework 2.0 Fortschritt:
http://blog.zf-info.de/2010/03/11/die-entwicklung-vom-zend-framework-2-0-hat-begonnen/

Interessantes Webinar am 17.03.2010 zu den Neuerungen von Zend Framework 1.10, mit Matthew Weier O’Phinney und Ralph Schindler:
http://devzone.zend.com/article/11954-Webinar—New-in-Zend-Framework-1.10

Noch ein interessantes Webinar am 17.03.2010 der „Velocity Online Conference“:
http://en.oreilly.com/velocity-mar2010

Kurze und gute Übersicht über Namespaces für diejenigen, die es noch nicht kennen, incl. Code:
http://pehbehbeh.de/webentwicklung/php/namespaces-grundlagen/

Cheat Sheet für das Zend Framework (6 Seiten):
http://refcardz.dzone.com/refcardz/getting-started-zend-framework?oid=hom19239

Written by Michael Kliewe

März 13th, 2010 at 12:35 pm

Posted in Allgemein