Next Previous Contents

7. Andere CPAN-Module zur Internetprogrammierung

Aus der Vielzahl der com CPAN erhältlichen Module stellen wir im folgenden Abschnitt noch einmal zwei Module besonders heraus:

7.1 WWW-Zugriff mit libwww

Der Einsatz von PERL im WWW ist nicht auf CGI-Scripts begrenzt. Das CPAN bietet eine ganze Reihe von Modulen mit denen man http-Client- und Serverfunktionen ausführen kann. Die erforderlichen Module befinden sich meist im Archiv "libwww-perl-*.tar.gz", der "Library for WWW.Access in PERL" .

Die libwww enthält über 50(!) Module für die HTTP-relevante Programmierung, die sich auf mehrere Namespaces verteilen:

Clientzugriff mit LWP::UserAgent

Den LWP::UserAgent könnte man leger aber suggestiv als "nichtinteraktiven Browser" bezeichnen. Mit dem User Agent ist es möglich "ferngesteuert" Dokumente aus dem WWW zu laden, und anderen Anwendungen zur Verfügung zu stellen. Typische Anwendungen sind Web-Robots die das Web nach bestimmten Inhalten (Obszönitäten, Markenrechts-- oder Patentverletzungen) durchsuchen.

Der folgende Fünfzeiler "useragent_get.pl" holt ein CGI-Dokument vom Server "localhost":

 
 #!/usr/bin/perl
 #
 use LWP::UserAgent;
 #
 $myagent=LWP::UserAgent->new();
 $requesturl="http://localhost/cgi-bin2/fasttemplatedemo.cgi?name1=value1";
 $myrequest=HTTP::Request->new(GET,$requesturl);
 $myresponse=$myagent->request($myrequest);
 print ($myresponse->content());

Das Beispiel zeigt die drei typischen Schritte beim Holen eines WWW-Dokumentes:

  1. Zuerst wird ein neues User-Agent Objekt angelegt:
            $myagent=LWP::UserAgent->new();
           
    
  2. Anschließend wird eine http-Anfrage formuliert, indem ein Objekt vom Typ HTTP::Request angelegt wird, das die Request-Methode (GET) und den URL als Parameter erhält:
            $myrequest=HTTP::Request->new(GET,$requesturl);
           
    
  3. Das Dokument wird mit der "request" Methode des User Agents geholt. Die Request Methode erhält das eben erzeugte Request Objekt als Parameter, führt den Request aus, und liefert das Ergebnis der Anfrage (das Dokument) als ein Objekt der Klasse HTTP::Response zurück:
      
           $myresponse=$myagent->request($myrequest);
          
    

Auf den Inhalt (Content) des Dokuments lässt sich dann mit der "content" Methode zugreifen. Eventuell kann man auch vorher mit der Methode "is_success" anfragen, ob dem Request überhaupt Erfolg beschieden war.

Weitere Möglichkeiten des User Agents

POST-Requests

Auch ein POST-Request lässt sich mit dem UserAgent realisieren. Dazu müsen die Request-Methode des Requests auf "POST", die Felder für Content-Type und Content auf die gewünschten Werte eingestellt werden (useragent2.pl):

 
 #!/usr/bin/perl -w
 #
 use LWP::UserAgent;
 $myagent = new LWP::UserAgent;
 #
 $req = new HTTP::Request 'POST','http://localhost/cgi-bin2/cgidemo2.cgi';
 $req->content_type('application/x-www-form-urlencoded');
 $req->content('+++name=wert++++');
 #
 $res = $myagent->request($req);
 print $res->content();

Viele weitere Anregungen zum Umgang mit der libwww gibt das Libwww-Perl Cookbook von libwww Autor Gisele Aas, das einige der häufigsten Problemstellungen beispielhaft in "Kochrezepform" löst. Das libwww-cookbook erhält man nach der Installation der libwww mit dem Kommando " perldoc lwpcook". Das Kochbuch enthät u.A Kochrezepte für:

Eines der schönsten Features des UserAgent, ist die Möglichkeit den HTTP_USER_AGENT String. zu manipulieren. Per Voreinstellung liefert der HTTP_USER_AGENT String einfach die Version der libwww zurück, z.B:

libwww-perl/5.36

Will man unerfahrene Webmaster oder instabile Auswertungssoftware ärgern, dann kann man mit diesen Eintrag mit der "agent" Methode verändern (hier auf Microsoft Internet Explorer für Linux):

 $myagent->agent"(Mozilla/5.0 (compatible; MSIE 5.5 X11; U; Linux 2.6.16 i586))"

Die libwww Homepage findet man unter http://www.linpro.no/lwp/

7.2 Andere TCP/IP Protokolle

Die "libnet" von Graham Barr ist eine Sammlung von Client-Implementationen der meistgenutzten TCP/IP Protokolle. Nur HTTP-Unterstützung gibt es nicht, dafür gibt es ja die libwww. Die folgende Tabelle gibt einen Überblick über die unterstützten Protokolle, und die RFCs die diese Protokolle beschreiben:

Net::FTP

File Transfer Protocol (RFC959)

Net::SMTP

Simple Mail Transfer Protocol (RFC821)

Net::Time

Daytime Protocol (RFC867)

Net::Time

Time Protocol (RFC868)

Net::NNTP

Network News Transfer Protocol (RFC977)

Net::POP3

Post Office Protocol (RFC1939)

Net::SNPP

Simple Network Pager Protocol (RFC1861)

Eine Nichtinteraktive FTP-Sitzung

Ein weitverbreiteter Anwendungsfall für die libnet sind nichtinteraktive FTP-Sessions. Zwar lassen sich auch mit den meisten kommandozeilenorientierten FTP-Clients nichtinteraktive FTP-Sitzungen realisieren, wenn das Problem aber außer simplen Up- und Downloads auch eine kompliziertere Anwendungslogik erfordert, hat PERL schnell die Nase vorn. Das folgende Beispielscript (ftpdemo.pl) lädt alle Dateien deren Namen mit "cgi" endet vom Homedirectory des Benutzers cgidev ("/home/cgidev") in das aktuelle Verzeichnis. Danach wird eine Logdatei erstellt, und in "/home/cgidev" abgelegt. (Dieses Beispiel funktioniert aber nur, wenn der Benutzer "cgidev" das Passwort "cgipass" benutzt ):


#!/usr/bin/perl  -w
#
use Net::FTP;
#
#
$ftp = Net::FTP->new("localhost", Timeout => 60);
#
# einloggen mit Benutzernamen und Passwort
#
$ftp->login ('cgidev', 'cgipass');
#
#
# Testen ob der Login erfolgreich wr, gegenenfalls 
# Abbruch mit Fehlermeldung
#
if($ftp == undef){
  $errormsg=$@;
  onError(); 
}

#
# OK-der Login war erfolgreich, wir koennen
# weitermachen...
#
# wechseln in das richtige Verzeichnis 
# auf dem Server...
#
$ftp->cwd('/home/cgidev');
# Uebertragungstyp auf ASCII setzen
$ftp->ascii(); 
#
# Das Directory-Listing der *.cgi Dateien  abbbholen
#
@dir = $ftp->ls('*.cgi');
print @dir;
#
#
#
foreach(@dir){

  eval   { #kritischer Block: Datei herunterladen
    $cgi_filename=$_;
    print "\n\n versuche $cgi_filename herunterzuladen\n";
    $ftp->get($cgi_filename);
    print " $cgi_filename heruntergeladen\n" ;
  };
  
  if($@){ #Fehlerabfrage  
    onError("Fehler beim download von $cgi_filename : \n\n $@");
  }
}
#
#
print "\n Download beendet \n";
#
#
$now=localtime();
#
open (LOGFILE,"> ftp-log.$now");
print LOGFILE  "Download um $now";
print LOGFILE   join("\n",@dir);
close (LOGFILE);
#
#
$ftp->put("ftp-log.$now");
print "logdatei abgelegt \n";
#
sub onError($){ 
 print "Fehler im System : $errormsg"; 
 exit (1);
}

Der erste Schritt ist das Anlegen eines FTP-Objektes, das die FTP-Sitzung modelliert. Der Konstruktor "new" nimmt den Namen des FTP-Servers (hier:localhost) und eventuell weitere optionale Parameter als Einträge eines Hashes entgegen. Hier ist sind es ein Timeout von 60 Sekunden, und "True" fü Hashmark-Printing:

   $ftp = Net::FTP->new("localhost", Timeout => 60, hash => "true"  );
 

Andere Parameter könnten eventuelle Firewalls, die Größe der übertragenen Blöcke, der Serverport oder ein höheres DebugLevel sein.

Mit der login-Methode loggt sich der Client auf dem FTP-Server ein. Die Login Methode nimmt normalerweise Benutzername und Passwort des Benutzers auf dem Server als Parameter entgegen. Ohne Parameter aufgerufen versucht login ein anonymes login mit der Emailadresse als Passwort. Wenn das Login fehlschlägt, liefert login ein "undef" zurück.

 $ftp->login ('cgidev', 'cgipass');

Die nächsten Befehle sind 1:1 Entsprechungen von FTP-Kommandos. cwd ändert das Remote-Verzeichnis, ascii ändert den Übertragungsmodus, ls ruft den FTP-Listingbefehl "dir" auf. ls liefert das Directory-Listing als Array zurück:

$ftp->cwd('/home/cgidev');
$ftp->ascii(); 
@dir = $ftp->ls('*.cgi');

Eine Schleife lädt dann jede Datei aus dem Directory-Listing einzeln mit dem FTP-GET Komando herunter:

 $ftp->get($cgi_filename);

Um die Aktion zu protokollieren wird am Ende eine Logdatei angelegt und mit dem Kommando "put" auf dem Server abgelegt.

$ftp->put("ftp-log.$now");


Next Previous Contents