pdfprinter

download


#!/usr/bin/perl -w
#
#######################################################################
#
#                   This PERL script emulates PDF printer
#
#  *** Introduction ***
#
#  The main idea is to create PDF files in *nix/windows mixed environment
#  by printing to a printer. This is called PRINT-TO-PDF. To create a PDF
#  file a user just prints from any application to a network printer. The
#  output PDF file is sent to a user via email as an attachment.
#  The printer is available to to windows users via SAMBA and to *nix
#  users via CUPS. PDF printer is a postscript printer, i.e. Windows
#  machines should use postscript driver and *nix machines can use it
#  natively. #  The output PDF file
#
#
#  *** Legal ****
#
#  Written by Konstantin Antselovich [email protected]
#  (C) 2003. Some part of the program is taken from
#  salsafax script from http://www.purpel3.nl
#
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#  This program is free software; you can redistribute it
#  and/or modify    it under the terms of the GNU General Public
#  License as published by    the Free Software Foundation; version 2
#  of the License.  http://www.gnu.org/licenses/gpl.txt
#
#
#  *** Requirements ***
#
#    perl (I tested with v5.6 and its likely any v5 will do)
#    perl module Getopt-Long-2.32
#    perl module Mail-Sendmail-0.78
#    perl module MIME-Lite-3.01.tar.gz
#    CUPS (standard printing system on *nix)
#    sendmail (or postfix, that is standard thing on *nix)
#    ps2pdf (comes with the ghostscript package)
#
#
#  *** Installation ***
#
#  1. copy and paste this to a text file, or download gz from
#  http://kostik.orangecode.net/perl/pdfprinter.gz
#
#  2. copy it to /usr/lib/cups/backend
#     `chmod +x pdfprinter`
#     then run this script from the commandline:
#     `echo blah | ./pdfprinter'
#     This will tell if there are any dependencies unsolved.
#
#  3. Create new CUPS printer by running this command
#     `lpadmin -p pdfprinter -E -v pdfprinter`
#
#  4. Check you cups config file, it should look similar to this:
#
#
#    ............................................
# 	[global]
#     	....
#           printcap name = /etc/printcap
#       	printing = cups
#       	use client driver = Yes
#       	printer admin = <root or yourloginname>
# 	[printers]
#      	....
#        	printable = Yes
#		browseble = No
#		Show Add printer wizard = Yes
#		....
#     ...............................................
#
#
#  5.  Installation on the clients
#
#      Windows: go START->CONTROL PANEL->PRINERS AND FAXES->ADD PRINTER
#			 ->NETWORK PRINTER-> browse for the printer, right-click
#			 opt "Connect". At this point windows will offer you to
#			 install a new driver. Pick any Color laser postscript
#			 printer. I suggest this one:
#                        "Schlumberger 5232 Color PostScript Printer v50.3"
#
#       *nix:   setup network printer as ipp://<yourhost>/printers/pdfprinter
# 		     pick postscript printer.
#
#  6.  Email issues.
#
#      Emails will be send to <user>@<this.host.name> If this server doesn't
#      handle mail for your domain, configure this mail server to use your
#      real mail server as a 'smarthost', and add the name of this server
#      to your real mailserver as 'local'
#
#
#  *** Troubleshooting ***
#
#  Check log files for samba and cups for any errors.
#
#
################ And finally, the text of the program ########################

use strict;
use Getopt::Long;
use MIME::Lite;
use Mail::Sendmail;

### constants you must check if they are ok

# the command to convert postscript to pdf
my $PS2PDF = "/usr/bin/ps2pdf";               

# the default mailaddress for errormessages
my $MAILADDRESS = 'konstantin@localhost';

### constants you can alter but should consider not to

# the directory to store temporary files
my $TMPDIR = "/tmp/";

# the name of this tool
my $MYNAME = "pdfprint";

# the location of sendmail binary
my $SENDMAIL = "/usr/sbin/sendmail";

# the name of the logfile - debugging sessions only
my $LOGFILE = $TMPDIR . $MYNAME . ".log";

# the name of the postscript temporary file
my $PSFILE = $TMPDIR . $MYNAME . ".ps." . $$;

# the name of the pdf tempolary file
my $PDFFILE = $TMPDIR . $MYNAME . ".pdf." . $$; 

# from email address that pdfprinter uses to send emails
my $FROM = 'Your PDF Printer <pdf.printer@localhost>';

########################################################################
#  from here on, leave the code alone, unless you are really sure
########################################################################

my $mailaddress = ""; # how do we treat the errormessages
my $lpuser = "";      # username retrieved from lprng or lpd commandline
my $lphost = "";      # hostname retrieved from lprng or lpd commandline
my @emaillines;       # stores the documentlines containing EMAILDOC
my $errormsg ="";     # stores error message that gets send via email

# check some dependencies
if ( ! -d $TMPDIR ) {
  print("Error: temporary directory not found: ", $TMPDIR );
  exit 1;
}

if ( ! -e $SENDMAIL ) {
  Log("Error: Sendmail command not found: ", $SENDMAIL );
  exit 1;
}

if ( ! -e $PS2PDF ) {
  Log("Error: ghostscript command not found: ", $PS2PDF );
  exit 1;
}

# get usefull parameters
my $cupsfile = $ARGV[5];      # CUPS parses a filename with the printdata as the 6th parametr
                              # this could be undef (after lpr -d blah) or a filename (after a samba action)
my $cupsuser = $ARGV[1];      # CUPS paresed the username with the printdata as the 2nd parameter
                              # this is usually a user from localhost
my $filename = $ARGV[2];      # CUPS parces a file names that was submitted as print job 4th parameter 

my $printjob = $ARGV[0];      # CUPS parses a print job number as 1st parameter

 #as we got some useful info from CUPS, now we can compose a text message that will be sent
 # along with created PDF file
my $MSGBODY = "Dear " . $cupsuser . ",\n\n"
              . "Print job " . $filename . " number " . $printjob . "\n"
              . "has been completed \n\n"
              . "File " . "\"" . $filename . ".pdf\" has been attached to this msg \n"
              . "You can download it and use it as you wish \n\n"
              . "Yours, \n"
              . "PDF Printer"; 

GetOptions( 'h=s' => \$lphost,  # LPD and LPRng parse host and user name under the -h and -n parameter
            'n=s' => \$lpuser); # the postscript is parsed to it in a pipe - to be found in STDIN

# ok lets find out where we can send the mail to
if ( ( $lphost ) and ( $lpuser ) ) {  #if the user and host can be found on the commandline
  $mailaddress = $lpuser . '@' . $lphost ;
} elsif ( $cupsuser) {
  $mailaddress = $cupsuser . '@localhost' ;
} else {
  $mailaddress = $MAILADDRESS;
  $errormsg = "cannot get email address";
  &SendErrorMail($errormsg);
}

# where is the printerdata?
if ( ( $cupsfile ) and ( -e $cupsfile ) ) {
  $PSFILE = $cupsfile;
} else {
  &SavePostscriptdata;
}

#####################################################################
#  mail subroutine
#####################################################################
# ok we have a postscriptfile, now we are going to convert it and send
# it by mail

# carry out ps2pdf on the ps-file and return the output into perl

my $status = `$PS2PDF $PSFILE $PDFFILE`;
if ( $status ne "" ) {
   Log($status);
}

# check if we got output pdf file
if ( ! -e $PDFFILE ) {
  $errormsg =   "Error: pdfprinter was unable to create file $PDFFILE because: ";
  Log($errormsg, $PDFFILE );
  SendErrorMail($errormsg);
}
 # create mail object mime mixed multipart
my $msg = MIME::Lite->new( From    => $FROM,
                           To      => $mailaddress,
                           Subject => "Pdf file " . $filename . ".pdf" . " attached",
                           Type    => 'multipart/mixed');

 # attache file part
$msg->attach( Type       => 'application/pdf',
              Path	 => $PDFFILE,
              Filename   => $filename . ".pdf" );

 # attach msg body part
$msg->attach( Type  	  => 'TEXT',
              Disposition => 'inline',
              Data        => $MSGBODY);

 # obviously, send a message
$msg->send();

# delete PS and PDF files  in any case
unlink $PSFILE;
unlink $PDFFILE;

# always exit gracefully.
exit 0;

### sub ###################################################
#  save the information in the pipe to the ps tmp file

sub SavePostscriptdata {

  open PS, ">".$PSFILE or die("Sorry, cannot open temporary postscript file $PSFILE .\n");
  while (<STDIN>) {
    print PS $_ ;
  }
  close PS;
}

#### sub #################################################

sub SendErrorMail  {

  my $text = @_;

  sendmail( To => $mailaddress ,
            From => $FROM,
            Subject => 'Your print job failed.',
            Message => $text
          );

  Log("sent errormail to $mailaddress");

}

# sub #################################################
sub Log {
  open LG, ">>" . $LOGFILE;
  print LG join(" ", @_), "\n";
  close LG;
}