Wie in [1] ausführlich erläutert ist GEMScript ein Protokoll, daß die Kommunikation von GEM-Anwendungen beschreibt. Das GEMScript-Protokoll behandelt allerdings nicht den Inhalt der Kommunikation, sondern beinahe ausschließlich die Form der Kommunikation. Beinahe ausschließlich deshalb, weil in der GEMScript-Dokumentation (http://www.uni-karlsruhe.de/~Thomas.Much/GEMScript) einige Standard-Kommandos festgelegt sind, die von den meisten Anwendungen sowieso zur Verfügung gestellt werden (z.B. das Öffnen und Schließen eines Fensters).
Das GEMScript-Protokoll wird zur Zeit hauptsächlich dazu genutzt, eine GEM-Applikation durch eine andere fernzusteuern. So kann man beispielsweise jinnee mittels GEMScript anweisen, einen Notizzettel mit einen bestimmten Inhalt auf das Desktop abzulegen oder Verzeichnisfenster und Icons manipulieren.
Aber erst mit dem MagiC Scripter wird GEMScript so richtig interessant. MagiC Scripter ist zunächst eine Skriptsprache mit einer C-ähnlichem Syntax. Im Gegensatz zur Programmiersprache C gibt es aber Laufzeitprüfungen und - besonders wichtig für unkompliziertes programmieren - ein automatisches Speichermanagment. Durch die Kommunikation über GEMScript wird der Sprachumfang des MagiC Scripter um die Kommandos der betreffenden GEM-Applikation erweitert.
In diesem Beitrag will ich Sie in das 'Fernsteuern' von GEM-Applikation mit dem MagiC Scripter einführen und an einigen Skripts zeigen, wie sich wiederkehrende Vorgänge mit CAB, Fiffi und dem MagiC Scripter automatisieren lassen.
MagiC Scripter kennt drei Möglichkeiten mit GEMScript-fähigen Anwendungen zu kommunizieren: Externe Variablen, Festlegung einer Applikation mittels address() und Funktionsaufrufe der Form appname.funktionsname(<parameter>). Für diesen Beitrag wird nur die letzte Form genutzt. Sowohl der funktionsname als auch die Anzahl der Parameter hängen nur von der angesprochenen Applikation ab und können von MagiC Scripter nicht überprüft werden. Lediglich ein Scheitern der Verbindungsaufnahme zu einer Applikation und die Verwendung einer der jeweiligen Anwendung unbekannten Funktion können zu Laufzeitfehlern führen.
Will man CAB aus einem Skript heraus anweisen, die Homepage der Revolution-Redaktion anzuzeigen, so kann dies wie folgt aussehen:
CAB.open( "http://www.deltalabs.com" );
Wenn in CAB ab V2.7 dann unter Optionen/Allgemein noch 'automatisch Verbinden' aktiviert ist, wird automatisch mit IConnect eine Verbindung ins Internet aufgebaut und die Homepage geladen.
Im Gegensatz zu anderen Internet-Client benötigt ein WWW-Browser in beinahe allen Situationen die Interaktion mit dem Anwender. Es ist also es durchaus verständlich, daß die GEMScript-Kommandos von CAB größtenteils das Browser-Fenster beeinflussen. So öffnet CAB.open()
ein Fenster mit einer bestimmten URL, CAB.print()
druckt das dargestellte Dokument und CAB.save()
speichert es schließlich ab.
Das Öffnen eines Dokuments via MagiC Scripter bietet sich an, falls Sie eine WWW-Seite lesen, die sich täglich ändert (z.B. die Milan Homepage mit CAB.open( "http://www.milan-computer.de" )). Ist dann noch das Verfallsdatum Serverseitig sinnvoll gesetzt ist, entscheidet CAB ob die Seite aus dem Cache geladen wird oder ob sie neu angefordert werden müssen. Da CAB via GEMScript geladene Dokumente nicht unter einem frei wählbaren Namen abspeichert - bisher muß man den Dateinamen noch manuell über die Dateiauswahlbox festlegen - sind die Verwendungsmöglichkeiten natürlich eingeschränkt.
Weitaus interessanter für die Verwendung mit MagiC Scripter dürften daher zur Zeit die beiden Kommandos CAB.bookmarknewtopic()
und CAB.bookmarknewentry()
sein. Ersteres erweitert die Hotlist um eine neue Rubrik, zweiteres fügt in diese einen Eintrag ein. Das Skript L2H.sic
benutzt diese beiden Kommandos, um Links der Form '<a href="Url">Name</a>
' aus übergebenden (HTML-) Datei in die Hotlist von CAB einzutragen. Als Rubrik-Name wird dabei der jeweilige Dateiname benutzt.
Ein FTP-Programm eignet sich weit aus mehr zur Fernsteuerung von außen. Über GEMScript kann Fiffi eine FTP-Sitzung einrichten und alle möglichen Dateioperationen, die auch manuell möglich sind, ausführen (z.B. Dateien vom FTP-Server laden oder ablegen und Verzeichnisse erzeugen oder löschen). Im MagiC Scripter muß Fiffi dazu zunächst mit Fiffi.open()
der Name des Servers und optional der Name des Accounts, das Paßwort und ein Verzeichnis übergeben werden. Kann Fiffi die Sitzung einrichten (unter Optionen/Internet 'IConnect starten' und 'Verbindung aufbauen' aktivieren) ist der Rückgabewert größer als null und gleichzeitig das Handle für alle weiteren Kommandos, die sich auf diese Sitzung beziehen - die GEMScript-Kommunikation mit Fiffi ist im Gegensatz zu CAB also verbindungsorientiert. Ist die Rückgabe dagegen kleiner null, konnte die Sitzung nicht eingerichtet
werden und das Skript kann am Rückgabewert die mögliche Fehlerursache erkennen (s. Dokumentation zu Fiffi).
Angenommen Sie müßen regelmäßig verschiedene Dateien auf einem FTP-Server in ein bestimmtes Verzeichnis legen. Diese sich wiederholende Tätigkeit läßt sich leicht durch ein Skript erledigen. Das Skript Upload.sic
richtet eine FTP-Sitzung ein. Danach werden alle per Kommandozeile übergebenen Dateien zu dem FTP-Server transferiert. Das Verzeichnis, in das die Dateien gelangen, wird gleich beim Einrichten der Sitzung mit Fiffi.open()
festgelegt. Eine andere Möglichkeit wäre, das Verzeichnis mit Fiffi.cd()
erst nach dem Einrichten der Sitzung zu setzen.
Das Skript kann sogar für etwas ausgefallenere Anwendungen wie etwa die Bereitstellung aktueller Grafiken auf einer Homepage oder eine WebCam genutzt werden. Eine WebCam stellt regelmäßig ein von einer Digitalkamera aufgenommenes Bild einer bestimmten Situation auf einem WWW-Server zur Verfügung. Regelmäßig kann für beide Anwendungen alle zwei Sekunden (bei einem Intranet) oder auch nur alle sechs Stunden (Einwahl bei einem Provider) bedeuten. Dazu wird das Skript zu bestimmten Zeiten gestartet - beispielsweise mit 'Start Me Up!' (http://thmuch.home.pages.de) - und bekommt als Parameter die zu übertragene Datei übergeben.
Eine eigene Homepage ist auch für einen Atari-Anwender in diesen Tagen nichts besonderes mehr. Üblicherweise befindet sich eine Kopie der Homepage auf dem heimischen Rechner, um sie dort offline mit dem Duo qed/CAB oder auch mit dem Dokumentationsgenie UDO überarbeiten und erweitern zu können. So ein Dokument umfaßt mit den HTML-Files und Grafiken bisweilen einige zig Dateien, die sich oftmals der Hierarchie wegen in verschiedenen Verzeichnissen befinden. Die Dateien einer Homepage werden dann vom lokalen Rechner mittels FTP (File Transfer Protocol), also beispielsweise mit Fiffi, auf den WWW-Server übertragen. Nun ist es ziemlich mühsam, eine umfangreichere Homepage nach geänderten oder neuen Dateien zu durchsuchen und diese Dateien manuell mit Fiffi in die verschiedenen Verzeichnisse auf dem WWW-Server abzulegen. Mit einem geeigneten Skript kann man diese Arbeit getrost dem MagiC Scripter und Fiffi im Hintergrund erledigen lassen.
Das Skript UMHP.sic
sucht beim Start im Verzeichnis der Homepage auf dem lokalen Rechner die Datei Last.Update
. Wird diese gefunden, wird daraus der Zeitpunkt des letzten Abgleichs der Homepage gelesen; wird sie nicht gefunden, geht das Skript davon aus, daß alle Dateien auf dem WWW-Server abgelegt werden sollen. Anschließend durchsucht das Skript rekursiv die Verzeichnisse der Homepage auf dem lokalen Rechner nach Dateien und Verzeichnisse, die jüngeren Datums sind und merkt sich diese. Nun wird Fiffi gestartet, eine FTP-Sitzung gemäß obigen Ausführungen geöffnet und die geänderten oder neuen Dateien im Verzeichnis der Homepage abgelegt. Zum Schluß wird noch die Datei Last.Update
mit der aktuellen Systemzeit geschrieben.
Dateien, die für die Homepage nicht mehr benötigt werden, also in der lokalen Kopie nicht mehr vorhanden sind, werden von dem Skript auf dem Server nicht gelöscht. Eine mögliche Erweiterungen könnte daher nach dem Ablegen der Dateien mit Fiffi.ls()
eine Liste der Dateien und Verzeichnisse der Homepage auf dem Server erstellen und anschließend mit einem Vergleich der lokalen Daten überflüssige Einträge mit Fiffi.rm()
und Fiffi.rmdir()
löschen.
Ich hoffe, die hier gezeigten Beispiele haben Ihnen Appetit auf mehr (eigene) Skripts für die beiden Internet-Clients gemacht. Dank der GEMScript-Unterstütung lassen sich beliebig viele Funktionen nachrüsten, ohne den Programmierer des jeweiligen Clients erstmal von seinen Vorstellungen überzeugen zu müssen. Ich - und viele Anwender - würden sich freuen, wenn Sie selbst geschriebene Skripts der Öffentlichkeit zur Verfügung stellen.
Bei all der schönen neuen Funktionalität sollte Sie aber immer bedenken, daß das Einrichten der Verbindung und vorallem deren Abbau nicht immer reibungslos verläuft. Daher gilt die Warnung: Wer Internet-Zugriffe automatisiert, riskiert Telefon-Gebühren in ungeahnten Höhen!
Jürgen Koneczny
[1] GEMScript - Die ferngesteuerte Geisterhand, Revolution Januar/Februar 1998
bookmarknewentry | Fügt eine neue Rubrik in die Hotlist ein. |
bookmarknewtopic | Fügt einen neuen Eintrag in eine Rubrik ein. |
close | Schließt das Fenster mit der angegebenen URL oder das Oberste. |
new | Öffnet ein neues Fenster mit der URL des obersten Fenster von CAB. |
open | Öffnet ein neues Fenster mit einer angegebenen URL. |
Druckt das Fenster mit der angegebenen URL oder das Oberste. | |
quit | Beendet CAB. |
save | Speichert das Fenster mit der angegebenen URL oder das Oberste. |
sendmail | Versendet eine EMail. |
tofront | Bringt das Fenster mit der angegebenen URL nach oben. |
cd | Wechselt in der Sitzung in das angegebene Verzeichnis. |
close | Schließt die angegebene Sitzung oder die Oberste. |
get | Lädt die angegebene Datei vom Server auf den lokalen Rechner. |
getfront | Gibt den Namen des Host des obersten Fensters zurück. |
lcd | Setzt das Verzeichnis, in das Fiffi empfangene Dateien speichert. |
ls | Liefert den Inhalt des angegebenen bzw. aktuellen Verzeichnisses. |
mkdir | Erzeugt das angegebene Verzeichnis auf dem Server. |
open | Öffnet eine FTP-Sitzung. |
put | Speichert die angegebene Datei auf dem Server. |
pwd | Gibt das aktuelle Verzeichnis des Servers zurück. |
quit | Beendet Fiffi. |
rm | Löscht die angegebene Datei auf dem Server. |
rmdir | Löscht das angegebene Verzeichnis auf dem Server. |
tofront | Bringt das Verzeichnisfenster, das zur angegebenen Sitzung gehört, nach vorne. |
type | Stellt den Transfertyp für die angegebene Sitzung ein. |
/**********************************************************************
Name: L2H.sic (Link to Hotlist)
Autor: Jürgen Koneczny
Beschreibung: Dieses Skript durchsucht die übergebenden Dateien nach
Links der Form '<a href="Url">Name</a>' und trägt diese in die
Hotlist von CAB ein.
***********************************************************************/
// *** Anfang der Konfiguration ***
// Zugriffspfad Fiffi und CAB
const CabPath = "C:\\Gem\\CAB\\CAB.app";
// *** Ende der Konfiguration ***
const Title = "Link 2 Hotlist";
proc main( ... )
local i, Line;
{
if( argc > 0 )
{
progstart( CabPath, "" );
for( i = 0; i < argc; i++ )
{
Line = ReadFile( argv[i] );
if( Line.length )
{
CAB.bookmarknewtopic( "L2H: " + basename( argv[i] ));
GetLinks( "L2H: " + basename( argv[i] ), Line );
}
}
}
else
dialog.note( Title, "Eine HTML-Datei auf L2H ziehen!", "-bAbbruch" );
}
proc ReadFile( File )
local i, Line;
{
if( fopen( File, "r" ))
{
while( getline( File, Line[i++] ));
fclose( File );
return( Line );
}
return( 0 );
}
proc GetLinks( Topic, Line )
local i, j, Name, Tmp, Url;
{
for( i = 0; i < Line.length; i++ )
{
if( match( Line[i], "<a href=\"*\">*</a>" ))
{
Tmp = substr( Line[i], index( Line[i], "<a href=\"" ) + 9 );
strncpy( Url, Tmp, index( Tmp, "\">" ));
Tmp = substr( Tmp, index( Tmp, "\">" ) + 2 );
strncpy( Name, Tmp, index( Tmp, "</a>" ));
CAB.bookmarknewentry( Topic, Url, Name );
}
}
}
/**********************************************************************
Name: Upload.sic
Autor: Jürgen Koneczny
Beschreibung: Dieses Skript legt alle per Kommandozeile übergeben
Dateien mittels Fiffi auf einen FTP-Server.
Fiffi sollte so konfiguriert sein, daß die Internet-Verbindung
automatisch aufgebaut wird (Optionen/Internet).
***********************************************************************/
// *** Anfang der Konfiguration ***
// Server-Daten
const Server = "ftp.camelot.de";
const User = "zulu";
const Password = "****";
// Zugriffspfad der Homepage auf dem Server
const Dest = "/home/zulu/";
// Zugriffspfad Fiffi und CAB
const FiffiPath = "C:\\Gem\\Fiffi\\Fiffi.app";
// *** Ende der Konfiguration ***
const Title = "Upload";
proc main( ... )
local i;
{
if( argc > 0 )
{
progstart( FiffiPath, "" );
wait( 400 );
if(( Session = Fiffi.open( Server, User, Password, Dest )) > 0 )
{
for( i = 0; i < argc; i++ )
{
if( Fiffi.put( Session, argv[i] ) != 0 )
{
dialog.note( Title, "Fehler bei", argv[i], "-bAbbruch" );
break;
}
}
Fiffi.close( Session );
}
else
dialog.note( Title, "Fehler beim Einrichten der Sitzung", "-bAbbruch" );
}
else
dialog.note( Title, "", "Mindestens ein Argument übergeben", "-bAbbruch" );
}
/**********************************************************************
Name: UMHP.sic (Upload My Homepage)
Autor: Jürgen Koneczny
Beschreibung: Dieses Skript lädt einen Verzeichnisbaum mittels Fiffi
auf einen FTP-Server. Es werden nur Dateien und Verzeichnisse
beachtet, die jüngeren Datums sind, als der letzte Upload auf
diesen Server. Das Script eignet sich daher insbesondere zum Ab-
gleich einer Homepage auf einem WWW-Server.
Fiffi sollte so konfiguriert sein, daß die Internet-Verbindung
automatisch aufgebaut wird (Optionen/Internet).
***********************************************************************/
// *** Anfang der Konfiguration ***
// Server-Daten
const Server = "ftp.camelot.de";
const User = "zulu";
const Password = "******";
// Zugriffspfad der Homepage auf dem Server
const Dest = "/home/zulu/.html-data";
// Zugriffspfad der Homepage auf dem lokalen Rechner
const CODE = "C:\\Daten\\Prog\\Homepage";
// Zugriffspfad Fiffi und CAB
const FiffiPath = "C:\\Gem\\Fiffi\\Fiffi.app";
const CabPath = "C:\\Gem\\CAB\\CAB.app";
// *** Ende der Konfiguration ***
const Title = "Update My Homepage";
proc main()
local DateFile, i, Ret, Session, Success;
{
DateFile = CODE + "\\Last.Update";
if( fopen( DateFile, "r" ))
{
getline( DateFile, Date );
fclose( DateFile );
files.rm( DateFile );
}
else
Date = 0;
GetFiles( CODE, Dest );
if( Files.length > 0 )
{
progstart( FiffiPath, "" );
wait( 400 );
if(( Session = Fiffi.open( Server, User, Password, Dest )) > 0 )
{
Success = 1;
for( i = 0; i < Files.length; i++ )
{
if( Files[i, 2] & 16 )
Ret = Fiffi.mkdir( Session, Files[i, 1] );
else
Ret = Fiffi.put( Session, Files[i, 0], Files[i, 1] );
if( Ret != 0 && Ret != 553 ) // 553 ist die Antwort des Servers,
// falls das Verzeichnis bereits existiert
{
dialog.note( Title, "Fehler bei", Files[i, 0], "-bAbbruch" );
Success = 0;
break;
}
}
Fiffi.close( Session );
}
else
dialog.note( Title, "Fehler beim Einrichten der Sitzung", "-bAbbruch" );
}
if( fopen( DateFile, "w" ))
{
if( Success )
putline( DateFile, time());
else
putline( DateFile, Date );
fclose( DateFile );
}
}
proc GetFiles( LocalDir, ServerDir )
local Anz, i, j, List;
{
Anz = filelist( List, LocalDir );
for( i = 0; i < Anz; i++ )
{
if( List[i, 2] > Date )
{
j = Files.length;
Files[j, 0] = LocalDir + "\\" + List[i, 0];
Files[j, 1] = ServerDir + "/" + List[i, 0];
Files[j, 2] = List[i, 3];
}
if( List[i, 3] & 16 )
GetFiles( LocalDir + "\\" + List[i, 0], ServerDir + "/" + List[i, 0] );
}
}