On 05-Nov-2003/10:11 -0500, Timothy Stone <citylists@xxxxxxxxxxxxxx> wrote: >List, > >I'm trying to find my way thru the maze of supporting software to get >something that appears to be "cookbook" by some standards to work: >Anonymously Produce PDF documents via a PDF Pseudo Printer in Samba. #!/usr/bin/perl # # print2pdf v1.2 # # ------------ # Purpose # ------------ # This script allows Windows users to create PDF files by printing to a # "network printer". This "network printer" is actually a Samba share that # takes the printjob, converts it to PDF, then sends the PDF back to the # user via email. To a Windows user, the process looks like this: # # 1. Print a document to a shared printer named PDF-Maker (or whatever # you name it). # # 2. Wait for a popup message saying that the conversion is done. # # 3. Check email for delivery of the PDF. # # # ------------ # Legal # ------------ # Copyright (c) 2002, Anthony E. Greene <mailto:agreene@xxxxxxxxx> # License: GNU GPL, v2 or later <http://www.fsf.org/licenses/gpl.txt> # # 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; either version 2 # of the License, or (at your option) any later version. # # 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. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to: # # Free Software Foundation, Inc. # 59 Temple Place - Suite 330 # Boston, MA 02111-1307, USA. # # ------------ # Requirements # ------------ # 1. The ps2pdf utility included with Ghostscript. # # 2. A Postscript printer driver that creates Postscript code that # includes the document name in the "Title:" header. I recommend # the "HP Color LaserJet PS" driver that ships with Windows. This # driver must be installed on each client machine. # # 3. The mimencode utility included with metamail. # # 4. A sendmail-like program that accepts mail data from a pipe and # delivers it via SMTP. # # 5. The login name provided on the command line (by Samba) must be # resolvable to a valid email address or alias. # # ------------ # How It Works # ------------ # # The Windows user prints to this print share using a Postscript printer # driver (HP Color LaserJet PS). Samba spools the Postscript into a temp # file, then calls this script to process the file. # # The script parses the header of the Postscript document specified by # Samba on the command line and extracts the contents of the Title field. # The title is used to construct the filename of the resulting PDF # document. The Samba-provided username is used to generate the email # address used to deliver the PDF. # # In my environment, the username is not a valid email alias. So I use it # to query our LDAP server to get the user's SMTP email address and full # name. An alternative would be to use the system alias file # (/etc/aliases) to map usernames to email addresses. # # If your users all have local accounts or aliases on the Samba server or # the usernames map to mailboxes in your domain, then you can disable the # LDAP lookup by setting "$useldap = 0;" in this script. In this case you # will also need to specify the domain name that should be appended to # create the email address: "$maildomain = 'yourdomain';". # # If the username is not provided on the command line, or the LDAP query # fails to match the username to an email address, then the PDF will be # sent to the the sysadmin/default recipient (root). # # The machine name specified on the command line (see Samba Setup below) # is the NETBIOS name of the machine that submitted the printjob to Samba. # The script uses it to send a WinPopup/Messenger Service message to the # user's machine when the job is complete. If this command line argument # is set to 'localhost' then the script will not attempt to send a popup. # # ----------- # Samba Setup # ----------- # For a complete explanation of the Samba setup for this, see John # Bright's Linux Gazette article "PDF Service with Samba" at: # # <http://www.linuxgazette.com/issue72/bright.html> # # Remember to add %m (the machine name) and %U (requested username) to # the end of the command line of the print command setting in smb.conf: # # print command = /usr/local/bin/print2pdf %s %m %U # # John Bright's article also includes instructions for making the printer # driver available to Windows clients from the Samba server. The driver # must be installed on each client machine. # # # --------- # ChangeLog # --------- # # v1.3 12-Dec-2002 # ---------------- # - Allow the sysadmin to specify a domain to be used along with the # username to construct the recipient email address when LDAP is not # used to resolve the address. Allows delivery to username@yourdomain. # # - If the machine name of the client is given as 'localhost' on the # command line, then the script will not attempt to send a popup. This # makes it easier to use the script separately from Samba. # # - Use 'To: username@domain' as the email address format instead of # 'To: "Full Name" <username@domain>'. This script is intended for use # by Windows clients, who will most likely receive mail via Exchange # Server and Outlook clients. This software combination will always # display the user's Display Name on incoming messages, so specifying # a name in this script is unneccessary. # # - Rewrote the Purpose and How It Works sections. # # v1.2 20-May-2002 # ---------------- # - Allow sysadmin to specify whether or not LDAP should be used to # resolve username to email address. If LDAP is not used, PDF will be # mailed to username@localhost. This assumes that the user is either # local or has an alias entry in /etc/aliases. # # - Expanded some of the comments. # # v1.1 10-May-2002 # ---------------- # - Use the %U Samba variable to specify the user instead of parsing # the Postscript for a "For:" header. This allows different print # drivers to be used, as long as there is a Title header. Every # driver I've tested includes a Title header. The %U variable still # needs to be resolvable to a valid email alias/address. # # - Tell the default recipient that they are receiving the file because # it was not deliverable to the actual owner. # ############################# ## User-defined settings ## ############################# # Set this to any non-zero value to see diagnostics when running # the script in a console. $debug = 0; # Specify if LDAP should be used to do username -> email address mapping. # 1 == True; 0 == False $useldap = 0; # Use this domain to construct the recipient email address if LDAP is not # used to find the address. You only need to set this if the username is # part of a valid email address in your organization's domain, but users # do not have an account on this machine (ie; username@yourdomain is a # valid email address, but username@localhost is not). # Default: localhost $maildomain = 'localhost'; # Large documents will generate multi-megabyte Postscript files. You'll # need a lot of space for temp file. My /home partition has the most # available space, so that's where I'll put the temp files. The path in # the Samba share that calls this script should match this path. $tmpdir = '/tmp'; # Specify the Postscript-to-PDF conversion command. $ps2pdf = '/usr/bin/ps2pdf'; # Specify the LDAP attribute that contains the login name. $keyattr = 'rdn'; # This user gets notified about errors and receives PDF documents when # the email address of the actual document owner cannot be determined. $sysadminaddr = 'root'; # Specify the location of a sendmail-like MTA. # Default: '| /usr/sbin/sendmail -oi -U -t' $sendmail = '| /usr/sbin/sendmail -oi -U -t'; ######################################################################### ######################################################################### ## ## ## You should not have to change anything below this line ## ## ## ######################################################################### ######################################################################### ############################## ## Program initialization ## ############################## # Get the Process ID for use in generating unique filenames. $pid = $$; # Get the start time for metrics. $starttime = time; # Get the name of this script for generating filenames. $scriptname = `basename $0`; chomp $scriptname; # Get the name and size of the Postscript file for logging. $psfile = @ARGV[0]; $pssize = (stat($psfile))[7]; # The name of the machine that sent the printjob. This is where the popup # notification message will be sent. If this is 'localhost', then # the script will not attempt to send a popup message. $winbox = @ARGV[1]; if ($winbox eq 'localhost') { $usepopup = 0; } else { $usepopup = 1; } # Get the username of the Samba user. This will be used for email and # logging. $sambauser = @ARGV[2]; # Find out who's running this script and on what machine. This is for # debugging. $sender = $ENV{'LOGNAME'}; $host = $ENV{'HOSTNAME'}; ################################### ## Parse the Postscript header ## ################################### # Get the document title from the header of the Postscript doc. $doctitle = ''; open(PS,"$psfile"); while (($line = <PS>) && ($line !~ /^\%\%EndComments/)) { if ($line =~ /^\%\%Title: /) { # Remove the CR and LF, then get the doc title. $line =~ s/\r//; $line =~ s/\n//; $doctitle = substr($line,9); } } close(PS); # If there was no Title field in the header, # then we need to set a document title. if ($doctitle eq '') { $timestamp = time; $doctitle = "$winbox_$timestamp"; } ############################################# ## Figure out where to send the document ## ############################################# # If Samba provided a username, use it to find the email # address via LDAP. If there's no username or if the LDAP # lookup fails, then send the doc to the sysadmin. $recipientaddr = ''; if ($sambauser eq '') { # Samba did not provide a username. Send doc to Sysadmin. $nosambauser = 1; $recipientaddr = $sysadminaddr; } else { # Samba provided a username. See if we can use it or if it needs to be # looked up via LDAP. if ($useldap) { # Lookup the name and email address via LDAP. This search should # return the dn and mail attributes, one per line. The ldaphost, # searchbase, and other settings are in the system LDAP client config # file: /etc/openldap.ldap.conf. $ldapfailed = 0; @rcpt_attributes = `ldapsearch -LLL -x "$keyattr=$sambauser" mail`; foreach $attr (@rcpt_attributes) { chomp $attr; # Keep track of the number of records returned by the query. Any # number other than 1 will indicate an unsuccessful search. if ($attr =~ /^dn: /) { $resultcount++; } # Parse out the email address. if ($attr =~ /^mail: /) { $recipientaddr = substr($attr,6); } } # If the LDAP search didn't find any records, or if it found more # than one record, then it failed and we need to set the # recipient address. if (($recipientaddr eq '') || ($resultcount != 1)) { # The LDAP lookup failed. Send the doc to the sysadmin. $ldapfailed = 1; $recipientaddr = $sysadminaddr; } } else { # The username does not need to be looked up via LDAP. The username # is a valid email alias. $recipientaddr = $sambauser . '@' . $maildomain; } } ## See what it's going to do. if ($debug) { print "PrintJob by: $sambauser at $winbox\n"; print " Document: $doctitle ($pssize bytes)\n"; print " Recipient: $recipientaddr\n"; } ########################## ## Run the conversion ## ########################## # Specify the temp files for PDF and Base64 (MIME) versions of the doc. $temppdf = "$tmpdir/$scriptname.$pid.pdf"; $tempmime = "$tmpdir/$scriptname.$pid.mime"; # Convert Postscript to PDF and detect a non-zero (failed) return code. $conversionfailed = system("$ps2pdf $psfile $temppdf"); # Encode PDF using Base64 for email. $mimefailed = system("mimencode $temppdf -o $tempmime"); # Get the file sizes of the PDF and MIME files for # metrics and diagnostics. $pdfsize = (stat($temppdf))[7]; $mimesize = (stat($tempmime))[7]; # Calculate the elapsed time. $stoptime = time; $elapsed = $stoptime - $starttime; #################################################### ## Deliver the document or send an error notice ## #################################################### # Check for failure of either the ps2pdf conversion or # the MIME encoding process. if (($conversionfailed) || ($mimefailed)) { # Log the failure and notify the sysadmin. $logmsg = "Failed. PS2PDF: $conversionfailed, MIME: $mimefailed "; $logmsg .= "User: $sambauser at $winbox "; $logmsg .= "Document: $doctitle ($pssize -> $pdfsize bytes) "; $logmsg .= "Time: $elapsed seconds"; system("logger -i -t $scriptname '$logmsg'"); # Send error message to user and Sysadmin via email. open(MAIL,"$sendmail"); &stdheaders(); print MAIL "Cc: $sysadminaddr\n"; print MAIL "Subject: Error creating PDF: $doctitle.pdf\n\n"; print MAIL "The document titled $doctitle \n"; print MAIL "that you submitted for conversion to PDF "; print MAIL "was not converted.\n"; print MAIL "The System Administrator has been notified.\n\n"; print MAIL "Please try again later.\n"; close(MAIL); # Send user a "conversion failed" popup message. if (($sambauser) && ($winbox) && ($usepopup)) { $popupmsg = "From: PDF Convertor at $host\n"; $popupmsg .= " To: $sambauser on $winbox\n"; $popupmsg .= " Subj: $doctitle\n\n"; $popupmsg .= "*******************************\n"; $popupmsg .= "** PDF CONVERSION FAILED **\n"; $popupmsg .= "*******************************\n"; system("echo '$popupmsg' | smbclient -M $winbox &"); } &cleanup; exit 1; } else { # The conversion succeeded. Log the success. $logmsg = "Conversion succeeded. "; $logmsg .= "User: $sambauser on $winbox "; $logmsg .= "Document: $doctitle ($pssize -> $pdfsize bytes) "; $logmsg .= "$elapsed sec"; system("logger -i -t $scriptname \"$logmsg\""); # Send PDF doc to user. open(MAIL,"$sendmail"); &stdheaders(); print MAIL "MIME-Version: 1.0\n"; print MAIL "Content-Type: multipart/mixed; "; print MAIL "boundary=\"$scriptname-$pid-mime-boundary\"\n"; print MAIL "Subject: $doctitle.pdf\n\n"; print MAIL "--$scriptname-$pid-mime-boundary\n"; print MAIL "Content-Type: text/plain; charset=\"us-ascii\"\n\n"; if ($recipientaddr eq $sysadminaddr) { print MAIL "This PDF conversion is being delivered to you because\n"; print MAIL "the system was unable to determine the email address\n"; print MAIL "of the actual owner of the document. See the headers\n"; print MAIL "of this message for detailed diagnostics.\n"; } else { print MAIL "This is the result of your PDF conversion print job. "; print MAIL "If you cannot open the attached PDF document, please "; print MAIL "notify the System Administrator.\n\n"; } print MAIL "--$scriptname-$pid-mime-boundary\n"; print MAIL "Content-Type: application/pdf\n"; print MAIL "Content-Transfer-Encoding: base64\n"; print MAIL "Content-Description: $doctitle\n"; print MAIL "Content-Disposition: attachment; "; print MAIL "filename=\"$doctitle.pdf\"\n\n"; open(MIME,"$tempmime"); while ($line = <MIME>) { print MAIL "$line"; } close(MIME); print MAIL "\n\n--$scriptname-$pid-mime-boundary--\n"; close(MAIL); # Send the user a "conversion succeeded" popup message. if (($sambauser) && ($winbox) && ($usepopup)) { $popupmsg = "From: PDF Convertor on $host\n"; $popupmsg .= " To: $sambauser on $winbox\n"; $popupmsg .= " Subj: $doctitle\n\n"; $popupmsg .= "Your document was converted to PDF "; $popupmsg .= "and sent via email to\n"; $popupmsg .= "$recipientaddr"; system("echo '$popupmsg' | smbclient -M $winbox &"); } &cleanup; exit 0; } ##################### ## Subroutines ## ##################### # Generate standard email headers. sub stdheaders { print MAIL "From: \"PDF Convertor at $host\" <$sender>\n"; print MAIL "To: $recipientaddr\n"; print MAIL "X-Scriptname: $scriptname\n"; print MAIL "X-SambaUser: $sambauser on $winbox\n"; print MAIL "X-PS-File: $psfile ($pssize bytes)\n"; print MAIL "X-PDF-File: $temppdf ($pdfsize bytes)\n"; print MAIL "X-MIME-File: $tempmime ($mimesize bytes)\n"; print MAIL "X-LDAP-Failed: $ldapfailed\n"; print MAIL "X-Conversion-Failed: $conversionfailed\n"; print MAIL "X-MIME-Failed: $mimefailed\n"; print MAIL "X-Elapsed: $elapsed seconds\n"; } # Delete temp files. sub cleanup { unlink $psfile; unlink $temppdf; unlink $tempmime; } -- Anthony E. Greene <mailto:Anthony%20E.%20Greene%20%3Cagreene@xxxxxxxxx%3E> OpenPGP Key: 0x6C94239D/7B3D BD7D 7D91 1B44 BA26 C484 A42A 60DD 6C94 239D AOL/Yahoo Messenger: TonyG05 HomePage: <http://www.pobox.com/~agreene/> Linux. The choice of a GNU generation <http://www.linux.org/> -- redhat-list mailing list unsubscribe mailto:redhat-list-request@xxxxxxxxxx?subject=unsubscribe https://www.redhat.com/mailman/listinfo/redhat-list