#!/usr/bin/perl

require '/var/www/cgi-bin/auth.pl';

my $version="0.61i";
my $adminuid="admin";
my $adminpass="secret";
$LDAP_SERVER='imap1';
$LDAP_BASEDN='o=your org,c=ca';
my $maildomain="toshiba.ca";
my $vacationfile="/var/imap/procmail/vacationmsg";
my $replyfile="/var/imap/procmail/reply";
my $vacationdb="/var/imap/procmail/vacationdb";
my $rulefile="/var/imap/procmail/procmailrc";
my $rejectfile="/var/imap/procmail/rejectfile";
my $header="X-Customfilter:";

	
sub updateprocmail {
        my ($filterval,$uid) =@_;
	my (@mbxlist,$rulesyes,$vacationyes,$usereject);
%fields=(
	"subject",'^Subject:',
	"to2",'(^Cc:|^CC:|^To:|^TO:|^Sender:)',
	"to",'^TO_',
	"contain",'* ',
	"not contain",'* !',
	"from",'^From:',
	"address","* !^X-Loop: \$CYUSER\@$maildomain\n| \$FORMAIL -A\"X-Loop: \$CYUSER\@$maildomain\" | \$SENDMAIL ",
	"folder",'| $DELIVERTO $USERINBOX.',
	"nocopy",':0',
	"copy",':0 ic',
	"reply",':0 hc',
	"vacation",':0 Whc: locfile'
	);

$copybit=1;
$sizebit=2;
$searchbit=4;
$keepbit=8;
$regexbit=128;
	my %matchtype=(
		"0","allof",
		$searchbit,"anyof"
		);
 	
        my (@lrules)=split('\n',$filterval);
	my ($keep,$copystat,$procr,$extradefs) = "";
	my $proc="";
	my $not="";
	$copystat="";	
	$procr="";
	$rulesyes=0;
	$vacationyes=0;
	my ($fieldn,$field,$wc);
	my $regexused;
	my %vacation;
	#remove old files;
	my @remove=glob("$replyfile.*.$uid");
	while ($_=shift(@remove)) {
		unlink $_;
	}
	unlink "$vacationdb.$uid";
	unlink "$vacationfile.$uid";
		
        while (@lrules) { 
		my $tmp='';
                $line=shift(@lrules);
                if ($line=~/^ *#vacation&&(.*)&&(.*)&&(.*)&&(.*)/i) {
			$vacation{'days'}=$1;
			$vacation{'addresses'}="$2";
			$vacation{'text'}=$3;
			$vacation{'mode'}=$4;
			$vacation{'addresses'}=~s/\\@/\@/g;
			$vacation{'addresses'}=~s/\"//g;
			$usevacation=1;
			next;

		}

		chomp($line);
		my ($tag,$priority,$ruletype,$from,$to,$subject,$desttype,$dest,$flg,$fieldname,$fieldval,$size) = split("&&",$line);
		next if !$desttype;
		next if $tag=~/mode/i;
		$priority=~s/^ +//;
		$priority=~s/ +$//;
		$dest=~s/\r//g;
		$dest=~s/\\n/\r\n/g;
		if ($flg=~/copy/i) {
			$copyflg='copy';
		} 
		else {
			$copyflg= ($flg & $copybit);
		}
		if ($copyflg) {
			$copyflg='copy';
		}
		else {
			$copyflg='nocopy';
		}
		$matchflg=($flg & $searchbit);
		$keepflg=($flg & $keepbit);
		$keepflg=0 if (!$keepflg);
		$matchflg=0 if (!$matchflg);
		$sizeflg=($flg & $sizebit);
		$sizeflg=0 if (!$sizeflg);	
		$regexflg=($flg & $regexbit);
		$regexused ||=$regexflg;
		if ($ruletype !~/ENABLED|\d/i) {next};
	     	if ($desttype=~/folder/i) {
			next if !$dest;
			$dest=~s/^INBOX.INBOX/INBOX/;
			if (($dest =~s/^INBOX\.(.+)/$1/)||($alt_namespace)) {
				$msgdest=$dest;
			}
			else   {
				$msgdest="$dest";
			}
			# check if folder is in an addtional namespace
			foreach $namespace (@namespaces) {
				if ($dest=~/^$namespace./i) {
					$msgdest="$dest";
					last; # stop checking
				}
			}
		}
		elsif ($desttype=~/discard/) {
			$msgdest="/dev/null";
		}
		elsif ($desttype=~/address/i) {
		    if ($dest =~/\w+\@\w+\.\w+/) { 
			$msgdest=$dest;
		    }
		    else {
		    	next;
		    }
			next if !$dest;

		}

		else {$msgdest='';}
		$rulesyes=1;	
			
		$fieldn='0';
		$field='';	
		$not='';

		if ($to) {

			$not="!" if $to=~s/^\s*!//;
			$to=".*$to.*";
			$field.=$not.$fields{'contain'}.$fields{'to'}."$to\n";
			$fieldn++;
		}
		$not='';
		if ($from) {
			$not="!" if $from=~s/^\s*!//;
			$from=".*$from.*";	
			$field.=$not.$fields{'contain'}.$fields{'from'}."$from\n";
			$fieldn++;
		}
		$not='';
		if ($subject) {
			$not="!" if $subject=~s/^\s*!//;
			$subject=".*$subject.*";
			$field.=$not.$fields{'contain'}.$fields{'subject'}."$subject\n";
			$fieldn++;
			
		}
		$not='';
		if ($size) {
		    	$contains='< ';
		    	$contains='> ' if $sizeflg;
			$not="!" if $size=~s/^\s*!//;
			$size=~/([0-9]+)/;
			$kb='';
			$size=$1;
			$size='' if !$size;
			$field.=$not.$contains.$size."$kb\n";
			$fieldn++;
		}
		
		$not='';
		if ($fieldname && $fieldval) {
			$not="!" if $fieldval=~s/^\s*!//;
			$fieldval=".*$fieldval.*";	
			$field.=$not.$fields{'contain'}."^".$fieldname.": "."$fieldval\n";
			$fieldn++;
				
		}
		

		if (!($to || $from || $subject || $size || $fieldname || $fieldval ) && $desttype ne 'custom') {
			$tmp=''; # for now
			$copystat='';
		}
		elsif ($desttype=~/reject/) {
			$msgdest="* !^X-Loop: $uid\@$maildomain\n* !^FROM_DAEMON\n";
			$msgdest.="| (\$FORMAIL -r -I\"Precedeence: junk\" -A\"";
			$msgdest.="X-Loop: $uid\@$maildomain\";/bin/cat $rejectfile; /bin/echo \"-- \";) | \$SENDMAIL ;";
			$tmp=":0 h"."\n".$field."$msgdest\n\n";

		}
		elsif ($desttype=~/reply/i) {
			$msgdest="* !^X-Loop: $uid\@$maildomain\n* !^FROM_DAEMON\n";
			$msgdest.="| (\$FORMAIL -r -I\"Precedeence: junk\" -A \"";
			$msgdest.="X-Loop: $uid\@$maildomain\";/bin/cat $replyfile.$priority.$uid ; /bin/echo \"-- \";) | \$SENDMAIL ;";
			$tmp=$fields{$copyflg}."\n".$field."$msgdest\n\n";
			open (REP,">$replyfile.$priority.$uid");
			print REP "$dest\n";
			close REP;
			next if !$dest;
		}

		elsif ($desttype eq 'custom') {
			$tmp=$dest."\n\n";
			 next if $tmp!~/^\s*:0/;
		}
		else {
			$tmp=$fields{$copyflg}."\n".$field.$fields{lc($desttype)}."\'$msgdest\'\n\n";
		}
		$proc.=$tmp;
		$change=1;
	} #while @lrules
	$vacationyes=1 if ($vacation{'mode'}=~/on|active|yes|1/i);
	$proch="# Mail rules for user $uid\n# Created by Websieve version $version\n\n";
	
	$proc=$proch.$proc;
	
	if($vacation{'mode'}=~/on|active|yes|1/i) {
		$vacation{'text'}=~s/\\n/\r\n/g;	
		 if ($vacation{'text'}) {
			$msgdest="* !^X-Loop: $uid\@$maildomain\n* !^FROM_DAEMON\n";
			$msgdest.="| \$FORMAIL -rD 8192 $vacationdb.$uid\n\n";
			$msgdest.=":0 ehc\n| (\$FORMAIL -r -I\"Precedence: junk\" -A\"X-Loop: $uid\@$maildomain\" ; /bin/cat $vacationfile.$uid; ) | \$SENDMAIL; ";
			$proc.=":0 Whc: $vacationdb.$uid.lock"."\n"."$msgdest\n\n";
			open (VAC,">$vacationfile.$uid");
			print VAC $vacation{'text'}."\n";
			close VAC;
			open (VACDB,">$vacationdb.$uid");
			close VACDB;
			$rulesyes=1;
   		}
		else {
			$vacation{'mode'}='off';
		}
	
	}
	else {
			unlink "$vacationfile.$uid";
			unlink "$vacationdb.$uid";
	}
#	if (!$rulesyes ) { 
#                $proc=$proch;
#		$rulesyes=1;
#        }
		
        
	$change=1;
	if ($rulesyes) {
#		print "proc=\n$proc\npseudo=\n$pseudo\n";
		open (OUT,">$rulefile.$uid");
		print OUT "$proc\n";
		close OUT;
	       return;
        } # if rulesyes
	else {
		unlink "$rulefile.$uid";
	}

}
sub parseinput {
	while (<>) {
	  print $_;
	  if (/^$header +(\w+) (\S+)/) {
		  	($uid, $adminsecret)=($1,$2);
			last;
	  }
	  
	}
	return $uid;
}

#main

$uid=&parseinput;
$uid= $ARGV[0] if $ARGV[0];
$ld=&auth_connect($adminuid,$adminpass);
$dn=&auth_getdn($ld,$uid);
$rules=&auth_getatt($ld,$dn,'matchingrules');
&updateprocmail($rules,$uid) if $rules;



syntax highlighted by Code2HTML, v. 0.9.1