Ervin Peters

Archiv 2003: pdf-Druck-Service für Samba via E-Mail

Aktualisiert (updated) 2003-03-25.

Voraussetzungen: Ein Server mit Samba ab 2.2.1a (2.2.8a ist aktuell und empfohlen), Ghostscript (ghostscript.com), Perl, MIME::Entity und einem funktionierenden Mailsystem.

Step 1 : Das Perlscript

Folgendes perl-Script als gepackte pdfservice.zip herunterladen (5.621 Bytes) und in einem beliebigen Verzeichnis $install (z.B. /usr/share/samba/ps2mailpdf ) entpacken.

#!/usr/bin/perl -w
# (c) Ervin Peters 6/2002
# pdf Druckservice für Windows Clients:
# Samba / Ghostscript / Linux
# Anregungen aus pdfprint.pl v0.9.1 (c) Mattias Schlenker
# Übergabeparameter Username, Spooldateiname, Spooldir

use strict;       # Variablendeklarationen sind was feines
use MIME::Entity; # die email Funktionalität

# Parameter:
my $howtomsg = <<END_DATA;
USAGE:
 ps2mail [user] [psfile] [workdir]

user: username im System, via mail erreichbar
psfile: name des Postscriptfiles zum konvertieren
workdir: Arbeitsverzeichnis, in dem psfile liegt
        und pdffile erzeugt wird

(c) 2002/2003 Ervin Peters (ervin.peters\@ervnet.de}
pdf Druckservice für Windows Clients:
Samba / Ghostscript / Linux
Anregungen aus pdfprint.pl v0.9.1 (c) Mattias Schlenker
Anregungen aus iX 3/2003, Heise Verlag, S.139ff
(http://www.heise.de/ix/)
END_DATA

$ARGV[0] or die "Übergabeparameter fehlen!\n$howtomsg";
$ARGV[1] or die "Übergabeparameter fehlen!\n$howtomsg";
$ARGV[2] or die "Übergabeparameter fehlen!\n$howtomsg";

my $user = $ARGV[0];
my $tmpdir = $ARGV[2];
my $psfile = "$tmpdir/$ARGV[1]";
my $pdffile = "$psfile.pdf";
my $domain = "[mydomain].[tld]";    # MailDomain anpassen !
my $to = "$user\@$domain";
my $from = "pdfservice\@$domain";
my $subject = "PDF";
my $inhalt = "...im Anhang.\n";
my $mailpipe = '| /usr/lib/sendmail -t -oi';
my $result;
my $starttime = - time();
my $npdffile;

# Dies kann aus Sicherheitsgründen entfernt werden....
$result .= "PS-File nicht gefunden" if ( ! open(PSF, $psfile) );
while (<PSF>)
{
  # ist ein Title vorhanden? -> versuche Dateiname zu generieren
  if ( /^%%Title:(.*)$/ )
  {
    $npdffile = $1;
     # DosStyle-Endung löschen, falls vorhanden
    $npdffile =~ s/\..{3}$//;

    # remove everything before (and including) last "/"
    # this gets rid of directories, URLs, ... (from Michel Lanners)
    $npdffile =~ s,^.*/(\w+)$,$1,g;

    # löschen unerwünschter aller 'nicht Wort Zeichen'
    # der Name wird nicht schöner aber sicherer.
    $npdffile =~ s/\W//g;

    $npdffile =~ s/MicrosoftWord//; # Das kann auch weg!
    $npdffile =~ s/MicrosoftExcel//; # Das auch...

    # nehmen, wenn noch was übrig ist ;-)
    $pdffile = "$tmpdir/$npdffile.pdf" if ( $npdffile );
    last;
  }
}
close( PSF );
# ...bis hier.
# Eine Überprüfung ob das ps-File existiert
# gibt es dann erst bei ps2pdf.

$result .= "\n$npdffile\n";

$result .= `ps2pdf $psfile $pdffile`;
$result .= `rm -f $psfile`;
$starttime += time();
$inhalt .= "\nKonvertierzeit: $starttime s.\n\n$from\n";
$inhalt .= "user: $user\n";
$inhalt .= "tmp:  $tmpdir\n";
$inhalt .= "ps:   $psfile\n";
$inhalt .= "pdf:  $pdffile\n";
$inhalt .= "\n---------------\n$result";

my $coat = MIME::Entity->build( Type    => 'text/plain',
                                From    => $from,
                                To      => $to,
                                Subject => $subject,
                                Data    => $inhalt
                              );

$coat->attach( Path     => $pdffile,
               Type     => 'application/pdf',
               Encoding => 'base64'
             );

open MAIL, "$mailpipe"
    or die "Mailpipe \"$mailpipe\" nicht zu öffnen: $!\n";
$coat->print(\*MAIL);
close MAIL;
`rm -f $pdffile`;

Das Script nimmt eine Postscriptdatei [psfile] im Verzeichnis [workdir] von Samba entgegen. Es schaut nach ob ein '%%Title: ' - Eintrag in der Datei vorhanden ist und generiert einen pdf-Ausgabedateinamen, im Zweifelssfall heißt die Datei [user].pdf.
Nach der Konvertierung wird eine Mail mit ein paar Daten generiert und der pdf als Anhang. Im Falle eines Fehler sollte in der Mail die Fehlerausgabe von ps2pdf stehen.

Step 2 : Anpassung, Test

Das Script anpassen: Maildomain / Mailer nach den eigenen Gegebenheiten eintragen.

Test:
Eine Postscript Datei 'psfile' in ein temporäres Verzeichnis 'tmpdir' kopieren, /usr/local/bin/ps2mailpdf [user] [psfile] [tmpdir] mit den eigenen Daten aufrufen...

Wenn keine Fehler und kurze Zeit später eine Mail mit einer PDF-Datei im Anhang für [user] ankommt, dann ist alles in Ordnung, und das -w in der 1.Zeile kann entfernt werden.
Ansonsten: Fehler suchen und beheben.

Step 3 : Samba Freigabe erstellen

Drucker in der smb.conf kreieren. Dazu folgenden smb.conf Schnipsel vor der Freigabe [printers] einfügen (natürlich muß $install durch den Installationspfad des Scriptes ersetzt werden):

[ps2pdf]
  path = /tmp
  comment = print ps to pdf - mail
  guest ok = yes
  print command = $install/ps2mailpdf.pl %U %s /tmp/
  printable = yes

Möchte man die Vorzüge der Remote-Printer Installation erfahren, dann braucht man noch eine Samba-Freigabe [print$] - siehe auch samba printing howto / samba printer driver 2 in der samba Dokumentation.
Unter Verzicht auf Sicherheit kann die Freigabe z.B. so aussehen:

[print$]
  path = /usr/share/samba/printers
  guest ok = yes
  browseable = yes
  read only = no

Nach den Änderungen sollte man testparm aufrufen um die Konfigurationsdatei zu testen und dann samba neu starten.
Hinweis: die Dateiberechtigungen in den betroffenen Verzeichnissen müssen passend gesetzt sein.

Step 4 : Client Installation (NT/2k)

Auf dem Client wird nun der Drucker installiert. Nach einem Klick auf Neuer Drucker erscheint in der Regel der Druckerassistent. Netzwerkdrucker auswählen: \\server\ps2pdf. Es erscheint eine Box das der Server keinen Treiber bereitstellt mit der Frage ob lokal ein Treiber installiert werden soll: ja!.
In der Auswahlbox einen Postscript Drucker wählen, z.B. 'Apple Color LaserWriter 12/600'.
OK.
Der Treiber wird jetzt lokal installiert.
Um den Treiber für alle verfügbar zu machen, muß man z.B. die Eigenschaften des Druckers aufrufen und den Treiber neu installieren (BUTTON: Neuer Treiber). Den gleichen Treiber auswählen, der wird jetzt nicht mehr nach %systemroot%\system32\spool\drivers\W32X86\ installiert sondern nach \\server\print$\W32X86\. Wenn es Probleme gibt -> Dokumentation Samba...

Step 5 : abschließender Test

Wir nehmen uns einen anderen NT-client und stellen uns den ps2pdf als Netzwerkdrucker her, dies muß jetzt ohne explizite Treiberinstallation funktionieren.
Nach dem Druck einer Testseite sollte eine Mail im mit dieser Testseite als pdf im Postfach ankommen.

Sicherheit?

Wer das Script sicherer gestalten möchte, kann die Dateinamengenerierung aus dem %%Title der Postscriptdatei komplett entfernen (Der open/close{} Block). Dann wird die PDF-Datei nach dem Samba-Zufallszahlen-Namen der Druckdatei benannt.
Es gelangt dann kein vom User beeinflussbares Datum an die ausführende Shell. Prinzipiell könnte man sonst mit einem präpariertem %%title Unsinn treiben, da Samba ja mit ziemlich vielen Rechten läuft.
Die Regex in der Titelgenerierung entschärfen das Problem ziemlich, führen aber manchmal auch mit der Kreativität der druckenden Programme zu kryptischen Namen der PDF-Datei.

Step 6 : Bekanngeben

Dann steht der pdf-Service allen zur Verfügung. Und wenn jemand fragt 'Funktioniert das denn auch?' antworten wir mit einem klaren und eindeutigen: 'Woomööchlich!'.