#!/usr/bin/env python # -*- coding: utf-8 -*- # # (c) Copyright 2003-2015 HP Development Company, L.P. # # 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 the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # Author: Gaurav Sood, Sanjay Kumar # __version__ = '1.1' __title__ = 'PostScript Finishing Filter (hpps)' __doc__ = "CUPS filter that implements job storage (secure printing), Job Accounting and Born On Date (BOD) features on specific capable printers." # StdLib import sys import getopt import os.path import os import syslog import time import tempfile import subprocess import time PY3 = sys.version_info[0] == 3 if PY3: import configparser else: import ConfigParser as configparser CUPS_FILTER_OK = 0 CUPS_FILTER_FAILED = 1 input_fd = 0 output_fd = 1 job_id = 0 pid = os.getpid() config_file = '/@unixroot/etc/hp/hplip.conf' home_dir = '' def bug(m): log.stderr("ERROR: %s" % m) def msg(m): log.stderr("INFO: %s" % m) if os.path.exists(config_file): config = configparser.ConfigParser() config.read(config_file) try: home_dir = config.get('dirs', 'home') except: bug("Error setting home directory: home= under [dirs] not found.") sys.exit(CUPS_FILTER_FAILED) else: bug("Error setting home directory: /@unixroot/etc/hp/hplip.conf not found") sys.exit(CUPS_FILTER_FAILED) if not home_dir or not os.path.exists(home_dir): bug("Error setting home directory: Home directory %s not found." % home_dir) sys.exit(CUPS_FILTER_FAILED) sys.path.insert(0, home_dir) os.chdir(home_dir) # HPLIP try: from base.g import * from base.codes import * from base import device from base import utils from prnt import cups from base.sixext import to_bytes_utf8, to_string_utf8 except ImportError as e: bug("Error importing HPLIP modules:%s %s\n" % (pid, e)) sys.exit(CUPS_FILTER_FAILED) def usage(typ='text'): if typ == 'text': utils.log_title(__title__, __version__) utils.format_text(USAGE, typ, title=__title__, crumb='pscfilter') sys.exit(CUPS_FILTER_OK) try: opts, args = getopt.getopt(sys.argv[1:], 'l:hg', ['level=', 'help', 'help-rest', 'help-man']) except getopt.GetoptError: usage() for o, a in opts: if o in ('-l', '--logging'): log_level = a.lower().strip() log.set_level(log_level) elif o == '-g': log.set_level('debug') elif o in ('-h', '--help'): usage() elif o == '--help-rest': usage('rest') elif o == '--help-man': usage('man') # CUPS provided environment try: device_uri = os.environ['DEVICE_URI'] printer_name = os.environ['PRINTER'] ppd_file = os.environ['PPD'] except KeyError: bug("Improper environment: Must be run by CUPS.") sys.exit(CUPS_FILTER_FAILED) try: job_id, username, title, copies, options = args[0:5] job_id = int(job_id) except IndexError: bug("Invalid command line: invalid arguments.") sys.exit(CUPS_FILTER_FAILED) START_JOB = b"\x1b%-12345X@PJL JOBNAME=" UEL = b"@PJL ENTER LANGUAGE=POSTSCRIPT\x0a" END_JOB = b"\x1b%-12345X@PJL EOJ\x0a\x1b%-12345X" #output_fd = os.open("/tmp/PSC.out", os.O_WRONLY | os.O_CREAT) os.write(output_fd, START_JOB) os.write(output_fd, to_bytes_utf8("hplip_%s_%s\x0a" % (username, job_id))) opts = {} for opt in options.split(): try: o, v = opt.split('=') except ValueError: continue else: opts[o] = v try: ppd_str = to_string_utf8(open(ppd_file, 'rb').read()) except IOError: bug("Unabel to read PPD File") sys.exit(CUPS_FILTER_FAILED) # --------------------Secure Printing--------------------- # Embeds private job PJL's into the print stream # ---------------------------------------------------------- if 'HPPinPrnt' in options and 'noHPPinPrnt' not in options: os.write(output_fd, b"@PJL SET HOLD=ON\x0a") os.write(output_fd, b"@PJL SET HOLDTYPE=PRIVATE\x0a") secpin = "" if "HPDigit" in ppd_str: try: tmp = opts['HPDigit'] if "Custom." in tmp: tmp = tmp[7:] if tmp.isdigit() and len(tmp) == 4: secpin += tmp else: secpin = "0000" except KeyError as e: msg("Setting Pin to default") else: szKeyInitials = ['HPFIDigit', 'HPSEDigit', 'HPTHDigit', 'HPFTDigit'] for x in szKeyInitials: try: secpin += opts[x] except KeyError: secpin += '0' os.write(output_fd, to_bytes_utf8('@PJL SET HOLDKEY="%s"\x0a' % secpin)) os.write(output_fd, to_bytes_utf8('@PJL SET USERNAME="%s"\x0a' % username)) os.write(output_fd, to_bytes_utf8('@PJL SET JOBNAME="%s"\x0a' % title)) #os.write(output_fd, to_bytes_utf8('@PJL SET COPIES="%s"\x0a' % copies)) #----------------Job Accouting---------------------------- # Embeds the job accouting (1-8) PJL's into print stream # ----------------------------------------------------- key_list = [x for x in ['HPAccountingInfo', 'HPBOD', 'HPPJLEconoMode', 'HPPJLEconoMode2', 'HPPJLOutputMode', 'HPPJLDryTime', 'HPPJLSaturation', 'HPPJLInkBleed', 'HPPJLColorAsGray', 'HPPJLTrueBlack'] if x in ppd_str] if 'HPAccountingInfo' in key_list: p = subprocess.Popen(['hostname', '-s'], stdout=subprocess.PIPE, stderr=subprocess.PIPE) system_name , err = p.communicate() if system_name == '': system_name = 'unknown_system_name' p = subprocess.Popen(['hostname', '-d'], stdout=subprocess.PIPE, stderr=subprocess.PIPE) domain_name, err = p.communicate() if domain_name == '': domain_name = 'unknown_domain_name' os.write(output_fd, to_bytes_utf8('@PJL SET JOBATTR=\"JobAcct1=%s\"\x0a' % username)) os.write(output_fd, to_bytes_utf8('@PJL SET JOBATTR=\"JobAcct2=%s\"\x0a' % system_name.rstrip(b'\n'))) os.write(output_fd, to_bytes_utf8('@PJL SET JOBATTR=\"JobAcct3=%s\"\x0a' % domain_name.rstrip(b'\n'))) os.write(output_fd, to_bytes_utf8('@PJL SET JOBATTR=\"JobAcct4=%s\"\x0a' % time.strftime("%Y%m%d%I%M%S", time.localtime()))) os.write(output_fd, to_bytes_utf8('@PJL SET JOBATTR=\"JobAcct5=%s\"\x0a' % opts['job-uuid'])) os.write(output_fd, to_bytes_utf8('@PJL SET JOBATTR=\"JobAcct6=%s\"\x0a' % "HP Linux Printing")) os.write(output_fd, to_bytes_utf8('@PJL SET JOBATTR=\"JobAcct7=%s\"\x0a' % "HP Linux Printing")) os.write(output_fd, to_bytes_utf8('@PJL SET JOBATTR=\"JobAcct8=%s\"\x0a' % username)) # -------------------------Born On Date ---------------------------- # Embeds the born on date PJL's in to print stream. Uses GMT Time Stamp # Based upon the "BornOnDate_PJL_DMINFO_PJL_TIMESTAMP.doc # ----------------------------------------------------------------- if 'HPBOD' in key_list: BOD_fixed = "0400040101020D10100115" # HEX value of the time stamp OID BOD_time = time.strftime("%Y%m%d%I%M%S", time.gmtime()) # Timestamp GMT BOD_Var = '' for x in BOD_time: BOD_Var = BOD_Var + hex(ord(x))[2:] os.write(output_fd, to_bytes_utf8('@PJL DMINFO ASCIIHEX=\"%s%s\"\x0A' % (BOD_fixed, BOD_Var))) # -------------------------Other Features ---------------------------- if 'HPPJLEconoMode' in key_list: if 'HPPJLEconoMode' in options and 'noHPPJLEconoMode' not in options: os.write(output_fd, b"@PJL SET ECONOMODE=ON\x0a") else: os.write(output_fd, b"@PJL SET ECONOMODE=OFF\x0a") os.write(output_fd, b"@PJL SET RESOLUTION=600\x0a") os.write(output_fd, b"@PJL SET BITSPERPIXEL=2\x0a") if 'HPPJLEconoMode2' in key_list: try: if opts['HPPJLEconoMode2'] == 'yes' or opts['HPPJLEconoMode2'] == 'on': os.write(output_fd, b"@PJL SET ECONOMODE=ON\x0a") elif opts['HPPJLEconoMode2'] == 'no' or opts['HPPJLEconoMode2'] == 'off': os.write(output_fd, b"@PJL SET ECONOMODE=OFF\x0a") os.write(output_fd, b"@PJL SET RESOLUTION=600\x0a") os.write(output_fd, b"@PJL SET BITSPERPIXEL=1\x0a") except: pass if 'HPPJLPrintQuality' in key_list: try: if opts['HPPJLPrintQuality'] == 'FastRes1200': os.write(output_fd, b"@PJL SET RESOLUTION=600<0A>@PJL SET BITSPERPIXEL=2<0A>") elif opts['HPPJLPrintQuality'] == '600dpi': os.write(output_fd, b"@PJL SET RESOLUTION=600<0A>@PJL SET BITSPERPIXEL=1<0A>") elif opts['HPPJLPrintQuality'] == 'ProRes1200': os.write(output_fd, b"@PJL SET RESOLUTION=1200<0A>@PJL SET BITSPERPIXEL=1<0A>") except: os.write(output_fd, b"@PJL SET RESOLUTION=600<0A>@PJL SET BITSPERPIXEL=2<0A>") if 'HPPJLOutputMode' in key_list: try: if opts['HPPJLOutputMode'] == 'GeneralOffice': os.write(output_fd, b'@PJL SET PRINTQUALITY=DRAFT\x0a') elif opts['HPPJLOutputMode'] == 'Professional': os.write(output_fd, b'@PJL SET PRINTQUALITY=NORMAL\x0a') elif opts['HPPJLOutputMode'] == 'Presentation': os.write(output_fd, b'@PJL SET PRINTQUALITY=BEST\x0a') if opts['HPPJLOutputMode'] == 'MaximumDPI': os.write(output_fd, b'@PJL SET PRINTQUALITY=MAX\x0a') except: os.write(output_fd, b'@PJL SET PRINTQUALITY=NORMAL\x0a') if 'HPPJLDryTime' in key_list: try: if opts['HPPJLDryTime'] == '0' or opts['HPPJLDryTime'] == 'Default': os.write(output_fd, b'@PJL SET DRYTIME=0\x0a') elif opts['HPPJLDryTime'] == 'Medium': os.write(output_fd, b'@PJL SET DRYTIME=4\x0a') if opts['HPPJLDryTime'] == 'Long': os.write(output_fd, b'@PJL SET DRYTIME=7\x0a') except: os.write(output_fd, b'@PJL SET DRYTIME=0\x0a') if 'HPPJLSaturation' in key_list: try: if opts['HPPJLSaturation'] == '-2': os.write(output_fd, b'@PJL SET SATURATION=0\x0a') elif opts['HPPJLSaturation'] == '-1': os.write(output_fd, b'@PJL SET SATURATION=2\x0a') elif opts['HPPJLSaturation'] == '0' or opts['HPPJLSaturation'] == 'default': os.write(output_fd, b'@PJL SET SATURATION=4\x0a') elif opts['HPPJLSaturation'] == '+1': os.write(output_fd, b'@PJL SET SATURATION=6\x0a') if opts['HPPJLSaturation'] == '+2': os.write(output_fd, b'@PJL SET SATURATION=8\x0a') except: os.write(output_fd, b'@PJL SET SATURATION=4\x0a') if 'HPPJLInkBleed' in key_list: try: if opts['HPPJLInkBleed'] == '-2' or opts['HPPJLInkBleed'] == 'Default': os.write(output_fd, b'@PJL SET INKBLEED=0\x0a') elif opts['HPPJLInkBleed'] == '-1': os.write(output_fd, b'@PJL SET INKBLEED=2\x0a') elif opts['HPPJLInkBleed'] == '0' or opts['HPPJLInkBleed'] == 'Less': os.write(output_fd, b'@PJL SET INKBLEED=4\x0a') elif opts['HPPJLInkBleed'] == '+1': os.write(output_fd, b'@PJL SET INKBLEED=6\x0a') elif opts['HPPJLInkBleed'] == 'Least': os.write(output_fd, b'@PJL SET INKBLEED=7\x0a') elif opts['HPPJLInkBleed'] == '+2': os.write(output_fd, b'@PJL SET INKBLEED=8\x0a') except: os.write(output_fd, b'@PJL SET INKBLEED=4\x0a') if 'HPPJLColorAsGray' in key_list: try: if opts['HPPJLColorAsGray'] == 'Off' or opts['HPPJLColorAsGray'] == 'off' or opts['HPPJLColorAsGray'] == 'False': os.write(output_fd, b'@PJL SET GRAYSCALE=OFF\x0a') elif opts['HPPJLColorAsGray'] == 'HighQuality': os.write(output_fd, b'@PJL SET GRAYSCALE=COMPOSITE\x0a') elif opts['HPPJLColorAsGray'] == 'BlackInkOnly': os.write(output_fd, b'@PJL SET GRAYSCALE=BLACKONLY\x0a') elif opts['HPPJLColorAsGray'] == 'yes' or opts['HPPJLColorAsGray'] == 'on' : os.write(output_fd, b'@PJL SET RESOLUTION=600\x0a') os.write(output_fd, b'@PJL SET BITSPERPIXEL=8\x0a') os.write(output_fd, b'@PJL SET GRAYSCALE=COMPOSITE\x0a') elif opts['HPPJLColorAsGray'] == 'no': os.write(output_fd, b'@PJL SET RESOLUTION=600\x0a') os.write(output_fd, b'@PJL SET BITSPERPIXEL=8\x0a') elif opts['HPPJLColorAsGray'] == 'Plain' or opts['HPPJLColorAsGray'] == 'True': # for device 586 and device 586 flow os.write(output_fd, b'@PJL SET PLANESINUSE=1\x0a') # elif opts['HPPJLColorAsGray'] == 'check': # for device 556 no value is passed # os.write(output_fd, b'') except: os.write(output_fd, b'@PJL SET GRAYSCALE=OFF\x0a') if 'HPPJLTrueBlack' in key_list: try: if opts['HPPJLTrueBlack'] == 'HighQuality': os.write(output_fd, b'@PJL SET GRAYSCALE=COMPOSITE\x0a') elif opts['HPPJLTrueBlack'] == 'BlackInkOnly': os.write(output_fd, b'@PJL SET GRAYSCALE=BLACKONLY\x0a') except: os.write(output_fd, b'@PJL SET GRAYSCALE=BLACKONLY\x0a') os.write(output_fd, UEL) while True: try: data = os.read(0, 4096) except IOError: bug('Unable to read from standart input') sys.exit(CUPS_FILTER_FAILED) if not data: break os.write(output_fd, data) os.write(output_fd, END_JOB) sys.exit(CUPS_FILTER_OK)