#!/usr/bin/perl -w

###############################################################################
#
# Version:	2.5
# Date:		2007-08-08
# Author:	Joerg Soos
#
# Because of changed PJL commands in Mosel and Thames:
# KMCOE into KMCOETYPE
# KMSECTIONKEY into KMSECTIONKEY2
# KMUSERKEY into KMUSERKEY2
# additional options for HOLD: KMWAITPROOF and KMWAITSTORE
#
###############################################################################
#
# Version:	2.0
# Date:		2007-06-14
# Author:	Joerg Soos
#
# Added support for the pc fax functionality
# only sending fax to one, single recipient
# fax numbers can be specified by the user in two ways:
# 1. selecting fax digit by fax digit
# 2. selecting fixed stored complete fax numbers (PPD-Phonebook)
#
# changed all "HQ" prefixes into "KM"
#
# deleted unnecessary sub-function get_LockJobInformation
#
###############################################################################
#
# Version:	1.2
# Date:		April 18th 2007
# Author:	Joerg Soos
#
# Added support for the box printing functionality
# named in the driver "store and print" and "store"
#
# deleted unnecessary sub-functions 
# "do_insert_leadingZero" "mk_random_name" "create_new_filename"
##
###############################################################################
#
# Version:	1.1
# Date:		August 11th 2005
# Author:	Markus Timpner
#
# This filter is written to use Konica Minolta's XXXXXX print controllers with
# CUPS on Linux. To use this filter you have to use a specially adapted PPD file
# from Konica Minolta.
# To use this filter you have to copy it into the filter directory on your system.
# On SUSE Linux this is '/usr/lib/cups/filter'.
# After that restart CUPS ( type 'rccups restart' on SUSE Linux).
#
##############################################################################

# Starting and be strict
use strict;

# to use big interf for the 20(23) digit fax number
use Math::BigInt;

# Toggle between standard mode and debug mode
# In debug mode a log file with data of important steps is written
# Debug mode OFF: $dbg_mode=0
# Debug Mode ON: $dbg_mode=1
# By default this is $dbg_mode=0
my $dbg_mode=0;

# Debug file
# This is the logfile to be written in debug mode
# change to a suitable path if needed
# The printer daemon must have write access to that file
my $dbg_file="/var/tmp/kmfilterpcl.dbg";

# Debug file handle
# This will be used later as handle for file I/O operations
my $dbg_handle;


# The file to read from 
# This can be a file given as argument or STDIN 
# See CUPS Software Programmers manual  
my $inputfile;

# Array to store the postscript code generated by CUPS 
# MIME-type:application/vnd.cups-postscript 
# This array is a dummy array in KM filter template 
# Use it if nescessary or remove it 
my @pscore=();

# Array to store PJL commands 
# This array stores PJL commands, to be send to the printer before 
# the actual job data 
my @pjlcommands=();

# Array to store Options for foomatic
my @foomaticoptions=();

#Array to store Options for Ghostscript
my @gs_options=();

# PJL header and footer
# This regular expressions are used to insert closing PJL commands 
# at the end of a print job which uses PJL commands
my $pjlhead="\e\%-12345X\@PJL JOB\n";
my $pjlfoot="\e\%-12345X\@PJL EOJ\n\e\%-12345X";

###########################
# Code for Accounting
###########################
my $AccountCode=0;
my @ReturnAccountCode=();
my $AccountCodeDigits=0;
my $AccountName=0;
my @ReturnAccountName=();
my $AccountNameDigits=0;
my $accountcodeline=0;
my $accountnameline=0;
my $AccountNamePattern='%KMAccUN';
my $AccountCodePattern='%KMAccCode';
my $SecurePrintPasswordPattern='%KMPassCode';
my $SecurePrintUsernamePattern='%KMPassUN';
# Pattern to search for Account track sequences
my $AccountNameCommand='@PJL SET KMSECTIONNAME=';
# Pattern to search for Account track sequences
my $AccountCodeCommand='@PJL SET KMSECTIONKEY2=';
###########################


###########################
# Code for LockJob
###########################
my @ReturnLockJobName=();
my $LockJobCode=0;
my $LockJobName=0;
my @ReturnLockJob=();
my $LockJobDigits=0;

# Pattern to find lockjob sequences
my $PatternLockJob="\@PJL SET HOLDTYPE=PRIVATE";

# Lock Job PJL command
my $LockJobCodeCommand="\@PJL SET HOLDKEY=";
my $LockJobNameCommand="\@PJL SET KMJOBID=";

my $LockJobNameLine=0;
my $LockJobCodeLine=0;
#############################


#############################
# User Authentication
#############################
my $PatternAuthPrivate='@PJL SET BOXHOLDTYPE=PRIVATE';
my $AuthNameCommand='@PJL SET KMUSERNAME=';
my $AuthCodeCommand='@PJL SET KMUSERKEY2=';
my $AuthNamePattern='%KMAuthUN';
my $AuthCodePattern='%KMAuthCode';
my $PatternAuthPublic='@PJL SET BOXHOLDTYPE=PUBLIC';
my $AuthNameCommandPublic='\@PJL SET KMUSERNAME=\"Public\"';
my $AuthCodeCommandPublic='\@PJL SET KMUSERKEY2="Public"';
my $AuthCodeLine="";
my $AuthNameLine="";
my $AuthName="";
my $AuthCode="";
my @ReturnAuthCode=();
my @ReturnAuthName=();
################################


################################
# Code for Distribution Numbering
################################
my $DistNumSeq=0;
my @ReturnDistNum=();
my $DistNumDigits=0;
################################


################################
# Code for "Box Printing"
################################
my $PatternBoxStore='%@PJL SET BOXHOLD = STORE';
my $PatternBoxStorePrint='%@PJL SET BOXHOLD = STOREANDPRINT';
my $BoxNumberCommand='@PJL SET BOXNUM=';
my $BoxFileNameCommand='@PJL SET BOXFILENAME=';
my $BoxNumberPattern='%KMBoxUN';
my $BoxFileNamePattern='%KMFileCode';
my $BoxNumberLine="";
my $BoxFileNameLine="";
my $BoxNumber="";
my $BoxFileName="";
my @ReturnBoxNumber=();
my @ReturnBoxFileName=();
################################


################################
# Code for "PC FAX Sending"
################################
my $PatternKMPCFAXOnOff='%@PJL SET PCFAXMODE=FAX';

my $KMPCFAXResolutionPattern='%KMPCFAXRESOLUTION';
my $KMPCFAXResolutionCommand='@PJL SET RESOLUTION=';
my $KMPCFAXResolutionLine="";
my $KMPCFAXResolution="";

my $KMPCFAXPasPattern='%KMPCFAXPAS';
my $KMPCFAXPasCommand='@PJL SET PCFAXPAS=';
my $KMPCFAXPasValue="";
my $KMPCFAXPasLine="";
my $KMPCFAXPas="";

my $KMPCFAXNUMCommand='@PJL SET PCFAXNUM0=';
my $KMPCFAXNUMLine=0;
my $KMPCFAXNUM=0;

my $KMPCFAXPHONEBOOKPattern='%KMPCFAXPHONEBOOK';
my $KMPCFAXPHONEBOOK=0;

my $KMPCFAXPBXIntCodePattern='%KMPCFAXPBXIntCodeValue';
my $KMPCFAXPBXIntCodeValue="";
my $KMPCFAXPBXIntCodeDial="";

my $KMPCFAXTransSetPattern='%KMPCFAXTS';
my $KMPCFAXTransSetValue="";
my $KMPCFAXTransSetDial="";

my $KMPCFAXCodePattern='%KMPCFAXCode';
# to use big inter for the 20(23) digit fax number
my $KMPCFAXCode= new Math::BigInt 0;

my @ReturnKMPCFAXResolution=();
my @ReturnKMPCFAXPas=();
my @ReturnKMPCFAXCode=();
my @ReturnKMPCFAXPBXIntCode=();
my @ReturnKMPCFAXPHONEBOOK=();
my @ReturnKMPCFAXTransSet=();
################################


# We use this later for tray selection with pcl code
# The number defines the used escape sequence
# Example $inputslot=7 --> l7H
# $inputlot =7 will set Auto Select tray function in most cases
# we use this as default here
my $inputslot=7;

# Command to switch to POSTSCRIPT
# The last PJL command included before the actual job data switches from PJL to POSTSCRIPT
my $pjlsetpcl="\@PJL ENTER LANGUAGE = POSTSCRIPT\n ";

# Array to store the postscript file generated by pstops
# MIME-type:application/vnd.cups-postscript
# This Array will later be included in the final job file send to the printer
my @output=();

# The complete job with PJL commands and job data will be stored 
# in the outputfinal array. This array will finally be send to the printer
my @outputfinal=();

# Before any job data the pjl commands must be inserted into
# the print file
# The Array pjlcommands collects all preceding PJL commands
# The PJL header is inserted here
push @pjlcommands,$pjlhead;

if($dbg_mode==1)
{
	open( $dbg_handle, ">$dbg_file") or die "Can't open file:$dbg_file\n";
	print $dbg_handle '<?xml version="1.0"?>';
	print $dbg_handle "\n";
	print $dbg_handle '<debugdata>';
	print $dbg_handle "\n";
	
}


# Open the input file, if a filename is given, this must be ARGV[5] according to
# CUPS Software Programmers Manual
# A file argument may be provided to the filter in the filter chain
# If no file argument is given, STDIN is used
if (defined $ARGV[5])
{	
	# choose ARGV[5] as inputfile
	$inputfile= $ARGV[5];
}
else
{
	# choose STDIN as inputfile
	$inputfile = "-";
}
# open inputfile (file handle: INFILE) or create error message
open(INFILE, $inputfile) or die "Can't open file: $inputfile\n";
if ($dbg_mode==1)
{
	print $dbg_handle '<inputfile>';
	print $dbg_handle "$inputfile";
	print $dbg_handle '</inputfile>';
	print $dbg_handle "\n";
}
# Loop over $inputfile - line by line
# The next section seperates postscript commands and PJL commands


while (<INFILE>)
{
	# chomp $_;
	# The actual line is $_ , it is pushed to the output array which stores 
	# all job data 
	push @output,$_;
}
# Now the job data and the PJL commands are stored, the postscript file is not needed
# any longer
# Close the input file handle
close(INFILE);
my $line;
foreach $line (@output)
{
	last if ($line =~ m/\%\%Page:/ );
	#last if ($line =~ m/KMPJLAcc8/);
	$_ = $line;

	if ( m/\%\%EndFeature/ || m/stopped cleartomark/ || m/\[\{/ || m/BeginFeature/)
	{
		next;
	}

	# The actual line might contain an Account Name
	# we will look for it and retrieve it now		
	@ReturnAccountName=get_PPDPrintInformation($_,$AccountNamePattern);	
	# If we found one we add its digits to our total number 
	# of digits
	$AccountNameDigits=$AccountNameDigits+$ReturnAccountName[1];
	# If the line contained a code we will add it to the final code now
	$AccountName=$AccountName+$ReturnAccountName[0];

	# The actual line might contain an Account Code
	# we will look for it and retrieve it now		
	@ReturnAccountCode=get_PPDPrintInformation($_,$AccountCodePattern);	
	# If the line contained a code we will add it to the final code now
	$AccountCode=$AccountCode+$ReturnAccountCode[0];
	
	# The actual line might contain an Authentication User Name
	# we will look for it and retrieve it now		
	@ReturnAuthName=get_PPDPrintInformation($_,$AuthNamePattern);	
	# If the line contained a code we will add it to the final code now
	$AuthName=$AuthName+$ReturnAuthName[0];

	# The actual line might contain an Authentication User Password
	# we will look for it and retrieve it now		
	@ReturnAuthCode=get_PPDPrintInformation($_,$AuthCodePattern);	
	# If the line contained a code we will add it to the final code now
	$AuthCode=$AuthCode+$ReturnAuthCode[0];

	# The actual line might contain an Box Number
	# we will look for it and retrieve it now		
	@ReturnBoxNumber=get_PPDPrintInformation($_,$BoxNumberPattern);	
	# If the line contained a code we will add it to the final code now
	$BoxNumber=$BoxNumber+$ReturnBoxNumber[0];

	# The actual line might contain an Box File Name
	# we will look for it and retrieve it now		
	@ReturnBoxFileName=get_PPDPrintInformation($_,$BoxFileNamePattern);	
	# If the line contained a code we will add it to the final code now
	$BoxFileName=$BoxFileName+$ReturnBoxFileName[0];
	
	# The actual line might contain a lock job name
	# we will look for it and retrieve it now
	@ReturnLockJobName=get_PPDPrintInformation($_,$SecurePrintUsernamePattern);
	# If we found one we add its digits to our total number of digits
	$LockJobDigits=$LockJobDigits+$ReturnLockJob[1];
	# If the line contained a code we will add it to the final code now
	$LockJobName=$LockJobName+$ReturnLockJobName[0];
	
	# The actual line might contain a lock job code
	# we will look for it and retrieve it now
	@ReturnLockJob=get_PPDPrintInformation($_,$SecurePrintPasswordPattern);
	# If we found one we add its digits to our total number of digits
	$LockJobDigits=$LockJobDigits+$ReturnLockJob[1];
	# If the line contained a code we will add it to the final code now
	$LockJobCode=$LockJobCode+$ReturnLockJob[0];

	# The actual line might contain the PC Fax Resolution
	#  we will look for it and retrieve it now
	@ReturnKMPCFAXResolution=get_PPDPrintInformation($_,$KMPCFAXResolutionPattern);
	# If the line contained a code we will add it to the final code now
	$KMPCFAXResolution=$KMPCFAXResolution+$ReturnKMPCFAXResolution[0];

	# The actual line might contain the PrintRecipient command
	#  we will look for it and retrieve it now
	@ReturnKMPCFAXPas=get_PPDPrintInformation($_,$KMPCFAXPasPattern);
	# If the line contained a code we will add it to the final code now
	$KMPCFAXPasValue=$KMPCFAXPasValue+$ReturnKMPCFAXPas[0];

	# The actual line might contain an PC Fax Transmission Setting
	# we will look for it and retrieve it now		
	@ReturnKMPCFAXTransSet=get_PPDPrintInformation($_,$KMPCFAXTransSetPattern);
	# If the line contained a code we will add it to the final code now
	$KMPCFAXTransSetValue=$KMPCFAXTransSetValue+$ReturnKMPCFAXTransSet[0];

	# The actual line might contain an PC Fax PBXIntCodeValue
	# we will look for it and retrieve it now		
	@ReturnKMPCFAXPBXIntCode=get_PPDPrintInformation($_,$KMPCFAXPBXIntCodePattern);
	# If the line contained a code we will add it to the final code now
	$KMPCFAXPBXIntCodeValue=$KMPCFAXPBXIntCodeValue+$ReturnKMPCFAXPBXIntCode[0];

	# The actual line might contain an PC Fax Number by single digits
	# we will look for them, retrieve them and add them together
	@ReturnKMPCFAXCode=get_PPDPrintInformation($_,$KMPCFAXCodePattern);
	# If the line contained a code we will add it to the final code now
	$KMPCFAXCode=$KMPCFAXCode+$ReturnKMPCFAXCode[0];

	# The actual line might contain an PC Fax Phonebook Number
	# we will look for it and retrieve it now		
	@ReturnKMPCFAXPHONEBOOK=get_PPDPrintInformation($_,$KMPCFAXPHONEBOOKPattern);
	# If the line contained a code we will add it to the final code now
	$KMPCFAXPHONEBOOK=$KMPCFAXPHONEBOOK+$ReturnKMPCFAXPHONEBOOK[0];


	# First translate the TransmissionSettings
	if ($KMPCFAXTransSetValue==1)
	  {
	    $KMPCFAXTransSetDial="1,0,1";
	    # V.34 and ECM, no IntTransMode
	  }
	if ($KMPCFAXTransSetValue==2)
	  {
	    $KMPCFAXTransSetDial="1,1,1";
	    # V.34 and ECM and IntTransMode
	  }
	if ($KMPCFAXTransSetValue==3)
	  {
	    $KMPCFAXTransSetDial="1,1,0";
	    # ECM and IntTransMode
	  }
	if ($KMPCFAXTransSetValue==4)
	  {
	    $KMPCFAXTransSetDial="1,0,0";
	    # ECM only
	  }
	if ($KMPCFAXTransSetValue==5)
	  {
	    $KMPCFAXTransSetDial="0,1,0";
	    # IntTransMode only
	  }
	if ($KMPCFAXTransSetValue==6)
	  {
	    $KMPCFAXTransSetDial="0,0,0";
	    # None selected
	  }


        # Second, check if PBX-IntCode is greater then 0
	# and if it is then set the correct PBX-IntCode-prefix-dial value
	if ($KMPCFAXPBXIntCodeValue>0)
	  {
	    if ($KMPCFAXPBXIntCodeValue==1)
	      {
		$KMPCFAXPBXIntCodeDial="0";
	      }
	    if ($KMPCFAXPBXIntCodeValue==2)
	      {
		$KMPCFAXPBXIntCodeDial="00";
	      }
	    if ($KMPCFAXPBXIntCodeValue==3)
	      {
		$KMPCFAXPBXIntCodeDial="000";
	      }
	  }


        # Start to create the PCFAXNUM-PJL command line
	if ($_=~m/$PatternKMPCFAXOnOff/)
	  {
	    # create PC FAX Resolution PJL-command line
 	    $KMPCFAXResolutionLine=$KMPCFAXResolutionCommand . $KMPCFAXResolution . "\n";

	    $_=~s/^%//;
            push(@pjlcommands,$_);
	    push @pjlcommands,$KMPCFAXResolutionLine;


	    # create PC FAX PrintRecipient PJL-command line
	    if ($KMPCFAXPasValue==0)
	      {
		$KMPCFAXPas="OFF";
	      }
	    if ($KMPCFAXPasValue==1)
	      {
		$KMPCFAXPas="ON";
	      }

 	    $KMPCFAXPasLine=$KMPCFAXPasCommand . $KMPCFAXPas . "\n";

	    $_=~s/^%//;
	    push @pjlcommands,$KMPCFAXPasLine;


            # Now find out if PHONEBOOK-Number is used
	    if ($KMPCFAXPHONEBOOK==0)
	      {
		# use the digits to create the PCFAXNUM-PJL-command
 		 $KMPCFAXNUMLine=$KMPCFAXNUMCommand . '"' . 'FAX,' . $KMPCFAXPBXIntCodeDial . $KMPCFAXCode . ',' . $KMPCFAXTransSetDial . '"' . "\n";

		 $_=~s/^%//;
		 push @pjlcommands,$KMPCFAXNUMLine;
		 next;
	      }
	    else
	      {
	    # or use the PHONEBOOK to create the PCFAXNUM-PJL-command
		$KMPCFAXNUMLine=$KMPCFAXNUMCommand . '"' . 'FAX,' . $KMPCFAXPHONEBOOK . ',' . $KMPCFAXTransSetDial . '"' . "\n";

		 $_=~s/^%//;
		 push @pjlcommands,$KMPCFAXNUMLine;
		 next;
	       }
	  }


	# Debug lines for the Faxnumbercreation
	if ($dbg_mode==1)
	  {
	   print $dbg_handle '<KMPCFAXResolutionLine>',$KMPCFAXResolutionLine,'</KMPCFAXResolutionLine>',"\n";
	   print $dbg_handle '<KMPCFAXPasLine>',$KMPCFAXPasLine,'</KMPCFAXPasLine>',"\n";
	   print $dbg_handle '<KMPCFAXPBXIntCodeValue>',$KMPCFAXPBXIntCodeValue,'</KMPCFAXPBXIntCodeValue>',"\n";
 	   print $dbg_handle '<KMPCFAXNUMLine>',$KMPCFAXNUMLine,'</KMPCFAXNUMLine>',"\n";
 	   print $dbg_handle '<KMPCFAXPHONEBOOK>',$KMPCFAXPHONEBOOK,'</KMPCFAXPHONEBOOK>',"\n";

	   print $dbg_handle '<KMPCFAXTransSetValue>',$KMPCFAXTransSetValue,'</KMPCFAXTransSetValue>',"\n";
          }


	# If the line contains an accounting command we will find it now
	# All parts of the account code are collected then. PPD structure makes
	# this sure
	if ($_=~m/$AccountNameCommand/)
   {
		
		$accountnameline=$AccountNameCommand . '"' . $AccountName . '"' . "\n";
		$accountcodeline=$AccountCodeCommand . '"' . $AccountCode . '"' . "\n";
		push @pjlcommands,$accountnameline;
		push @pjlcommands,$accountcodeline;
		next;
   }

	

	if ($dbg_mode==1)
{
	print $dbg_handle '<AccountNameLine>',$accountnameline,'</AccountNameLine>',"\n";
	print $dbg_handle '<AccountCodeLine>',$accountcodeline,'</AccountCodeLine>',"\n";
	
	
}

	# If the line contains an authentification command we will find it now
	# All parts of the authentification code are collected then. 
  # PPD structure makes this sure
	if ($_=~m/$PatternAuthPrivate/)
   {
		$AuthCodeLine=$AuthCodeCommand . '"' . $AuthCode . '"' . "\n";
		$AuthNameLine=$AuthNameCommand . '"' . $AuthName . '"' . "\n";
		$_=~s/^%//;
		push(@pjlcommands,$_);
		push(@pjlcommands,$AuthNameLine);
		push(@pjlcommands,$AuthCodeLine);
		next;
   }

	# If the line contains a box print command we will find it now
	# All parts of the box print code are collected then. PPD structure makes
	# this sure
	if ($_=~m/$PatternBoxStore/)
   {
		$BoxNumberLine=$BoxNumberCommand . '' . $BoxNumber . '' . "\n";
		$BoxFileNameLine=$BoxFileNameCommand . '"' . $BoxFileName . '"' . "\n";
		$_=~s/^%//;
		push(@pjlcommands,$_);
		push(@pjlcommands,$BoxNumberLine);
		push(@pjlcommands,$BoxFileNameLine);
		next;
   }

	if ($_=~m/$PatternBoxStorePrint/)
   {
		$BoxNumberLine=$BoxNumberCommand . '' . $BoxNumber . '' . "\n";
		$BoxFileNameLine=$BoxFileNameCommand . '"' . $BoxFileName . '"' . "\n";
		$_=~s/^%//;
		push(@pjlcommands,$_);
		push(@pjlcommands,$BoxNumberLine);
		push(@pjlcommands,$BoxFileNameLine);
		next;
   }
	
	 # If the line contains a lock job command we will find it now
   # All the parts of the lock job code are collected then. PPD structure makes
   # this sure

   if ($line=~m/$PatternLockJob/i)
   {
		
		$LockJobCodeLine=$LockJobCodeCommand . '"'. $LockJobCode . '"' . "\n";
		$LockJobNameLine=$LockJobNameCommand . '"' . $LockJobName . '"'. "\n" ;
		$_=~s/^%//;
		push(@pjlcommands,$_);
		push(@pjlcommands,$LockJobNameLine);
		push(@pjlcommands,$LockJobCodeLine);
		next;
   }
	
	my $tmppjlcommand=getPJL($_);
	if($tmppjlcommand ne undef)
	{
		push(@pjlcommands,$tmppjlcommand);
		undef $tmppjlcommand;
		next;
	}

}

if ($dbg_mode==1)
{
	print $dbg_handle '<psdata>';
	print $dbg_handle "\n@output\n";
	print $dbg_handle '</psdata>';
	print $dbg_handle "\n";
}


# The last command in the PJL command block preceding the actual job data
# must switch to the correct PDL, in this case PCL 
# The command is stored in the variable $pjlsetpcl and will be pushed
# into the pjlcommand array now
push(@pjlcommands,$pjlsetpcl);

# The PJL command block is complete now and can be pushed into the 
# final output array @outputfinal
push(@outputfinal, @pjlcommands);


push(@outputfinal,@output);


#undef $tmpoutputfinal;

# Now all of the data is stored in outputfinal
# We have to finish the print file with a closing PJL footer
push(@outputfinal,$pjlfoot);

# The job is done and the result can be handed to CUPS 
# According to the CUPS Software Programmers Manual the job file
# must be printed to STDOUT
# We do so
print @outputfinal;
if ($dbg_mode==1)
{
	print $dbg_handle '<finaloutput>';
	my $xmloutputfinal=join ("",@outputfinal);
	#$xmloutputfinal=~s/\</\&lt;/;
	#$xmloutputfinal=~s/\>/\&gt;/;
	print $dbg_handle "\n$xmloutputfinal\n";
	print $dbg_handle '</finaloutput>';
	print $dbg_handle "\n";
	print $dbg_handle '</debugdata>'
	
}
# now we are finished completely and can terminate
exit;

sub getPJL
{
	# subroutine to extract PJL commands
	# give a line or a string where to get the commands from 
	# example: $pjlcommand=getPJL($line)
	
	my @arguments=@_;
	my $line=$arguments[0];


	# Pattern to search for PJL commands
	# PJL command sequences in KM PPD files are invoked by '%@PJL'
	# the regular expression in the next variable is used to search for
	# PJL command sequences inside the postscript code
	# The corresponding PPD file must have
	# this line '*Protocols: PJL' included in its header
	# otherwise CUPS will NOT insert PJL commands into the postscript file 
	my $patternPJL="^\%\@PJL";
	
	# Additionally each line is examinded if it contains an PJL command or not
	# If it contains one, a %-character in front of the command will be removed
	# In KM PPD files every PJL command is preceded by an %-character
	# After removal the command is pushed into the pjlcommand array 
	
	if($line=~m/$patternPJL/i)
	{
		if($line=~m/^%/)
		{
			$line=~s/^%//;
			# following <0A> must be removed
         if($line=~m/\<0A\>$/)
         {
         	$line=~s/\<0A\>$//;
         }
			return $line;
		}
	}
}

sub get_PPDPrintInformation
{
	# This function checks if the current line contains group codes
	# If the line contains a code,
	# the function returns a list containing the code and 1
	# If there is no code in the line the function returns undef

	my @arguments=@_;
   # The current line stored in $line
	my $line=$arguments[0];
	# Search Pattern
   my $pattern=$arguments[1];

	
	# define the returncode	
	my @ReturnCode=();

	
   if ($line=~m/$pattern/i)
   {
   	# Extracting the code from the line 
		my ( $tmp, $code)  = split /\s/,$line,2;
   	# Create return code
		push(@ReturnCode,$code,1);
		# return the code to main program
		return @ReturnCode;
	}
	else
	{
		# If there is no code in the line return undef
		push(@ReturnCode,0,0);
		return @ReturnCode;
	}
	
}

