#!/usr/local/bin/php -n
<?php

//$reject_hard_score = 15;  // Reject if onky ine rule matches this score

$acl_prefix 'sa2exim_'// sa2exim_

$use_mime_regex false;

$add_rule_header ''//  X-SA2EXIM-Rule

$debug false;

//----------------------------------------------------------------------------------

$template=implode('',file('./sa2exim.tpl'));

$rules = array();
$scoring_rules = array();
$meta_acls = array();
$acl_rbl = array();
$missing_rules = array();
$blacklist = array();

$mime_acl_count=1;

$bad_scoring_rules=0;
$good_scoring_rules=0;

// Process al cf files

if ($dh opendir('rules'))
    { 
    while ((
$file readdir($dh)) !== false)
        { 
        if (
$file[0]=='.') continue;
        if (
substr($file,-3)!='.cf') continue;
        
process_cf($file='rules/'.$file);
        } 
    
closedir($dh); 
    } 

// Process normal rules

foreach ($rules as $key => $rule)
    {
    
process_rule($rule);
    }

// Pre-process meta rules

foreach ($rules as $key => $rule)
    {
    if (
$rule['action']=='meta' && $rule['acl']=='')
        
process_meta($rule);        
    }

// Expand need meta rules

foreach ($meta_acls as $key => $acl)
    {
    
build_meta($key,$acl);
    }

// Mark need rules

foreach ($rules as $key => $rule)
    {
    if (!empty(
$rule['score']))
        
$rules[$rule['name']]['ok'] = mark_need($key);
    }

// Sort rules

usort($rules,'rule_sort');

// Build acl

if (count($blacklist)>0)
    {
    
$predata.="\tdeny\tsenders = ".implode(':',$blacklist)."\n";
    }
else
    
$predata '';

$template str_replace('{predata_acl}',$predata,$template);

$mime1  '';
$mime2    '';
$body    '';
$score    '';

foreach (
$rules as $key => $rule)
    {
    if (!
$rule['used'] || !$rule['ok'])
        {
        if (
$debug)
            echo 
"~ cleaning unused/bad rule ".$rule['name']."\n";
        
        if (!empty(
$rule['score']))
            
$bad_scoring_rules++;
            
        continue;
        }
        
    if (
$rule['place']=='mime')
        {
        
$varname=$rule['varname'];
        
        if (
$rule['used']==&& !empty($rule['score']))
            {
            
/*
            if ($rule['score']>$reject_hard_score)
                {
                $acl = "\tdeny\t".$rule['acl']."\n";
                }
            else*/
                
{
                
$acl "\twarn\t!condition = \${extract {k$varname}{\$SA2E_VAR1}}\n";
                
$acl.= "\t\t".$rule['acl'];
                
$acl.= get_score($rule['score']);
                
                if (
$add_rule_header!='')
                    
$acl.="\t\tmessage = ".$add_rule_header.": ".$rule['describe'].' ('.$rule['name'].")\n";
                
                
$acl.= "\t\tset SA2E_VAR1 = \$SA2E_VAR1 k$varname=1\n\n";
                }
                
            
$mime1.=$acl;
            
$good_scoring_rules++;
            continue;
            }
            
        
$acl "\twarn\t!condition = \${extract {k$varname}{\$SA2E_VAR1}}\n";
        
$acl.= "\t\t".$rule['acl'];
        
$acl.= "\t\tset SA2E_VAR1 = \$SA2E_VAR1 k$varname=1\n\n";
        
        
$mime2.=$acl;
        }
    else        
        if (!empty(
$rule['acl']))
            {
            
$body.=$rule['acl']."\n";
            }
        
    if (!empty(
$rule['score']))
        {        
        
$good_scoring_rules++;

        
$score.="\n\twarn\t".$rule['statment']."\n".get_score($rule['score']);        
        
$score.="\t\tmessage = X-SA2EXIM-Rule: ".$rule['describe'].' ('.$rule['name'].")\n";
        }
    }
    
$template str_replace('{mime_acl}',$mime1."\n".$mime2,$template);
$template str_replace('{data_acl}',$score,$template);
$template str_replace('{extra_acl}',$body,$template);

$fp=fopen('sa2exim.acl','wt');

fputs($fp,$template);
fclose($fp);

echo 
"\n$bad_scoring_rules scoring rules not converted\n";
echo 
"$good_scoring_rules scoring rules converted\n";

/*
asort($missing_rules,SORT_NUMERIC);

foreach ($missing_rules as $key => $count)
    echo "$key $count\n";
*/

//-----------------------------------------------------

function rule_sort ($a$b)
{

if (empty(
$a['score']) && empty($b['score'])) return 0;

if (empty(
$a['score'])) return -1;
if (empty(
$b['score'])) return 1;

if (
$a['score']<&& $b['score']<0
    return (
$a['score']>$b['score'])?1:-1;

if (
$a['score']<0) return -1;
if (
$b['score']<0) return 1;
     
if (
$a['score']==$b['score']) return 0;
 
return (
$a['score']>$b['score'])?-1:1;
}

//-----------------------------------------------------

function get_score($add)
{

$score="\t\tset SA2E_VAR3 = \${eval10:\$SA2E_VAR3";
        
if (
$add[0]=='-')
    
$plus='';
else
    
$plus='+';
            
$a=round($add*1000);    
$score.=$plus.$a."}\n";    

return 
$score;
}
    
//-----------------------------------------------------

function mark_need($rule_name)
{
global 
$rules,$debug;

echo 
"Testing $rule_name needs\n";

if (!isset(
$rules[$rule_name]))
    {
    echo 
"! error: rule [$rule_name] does not exist\n";
    return 
false;
    }
    
if (!
$rules[$rule_name]['ok'])
    {
    echo 
"! error: rule [$rule_name] could not be converted\n";
    return 
false;
    }

print_r($rules[$rule_name]);

$rules[$rule_name]['used']++;
/*    
if ($rules[$rule_name]['used']>1)
    return true;
*/
if (isset($rules[$rule_name]['uses']))
    foreach (
$rules[$rule_name]['uses'] as $l=> $key)
        {
        
//if ($debug)
            
echo "~ info: $rule_name needs [$key]\n";
            
        if (!
mark_need($key))
            return 
false;
        }
        
return 
true;
}

//-----------------------------------------------------

function build_meta($key,$acl)
{
global 
$meta_acls,$rules,$debug,$acl_prefix;

$acl=trim($acl);

if (
$acl=='')
    {
    echo 
"! warning: unexpected empty meta rule $key\n";
    return;
    }
    
if (
strpos($acl,'+')>0)
    
$type_count=true;
else
    
$type_count=false;

if (
strpos($acl,'&')>0)
    
$type_and=true;
else
    
$type_and=false;

if (
strpos($acl,'|')>0)
    
$type_or=true;
else
    
$type_or=false;

// Experssion has operators ??

if ($debug)
    echo 
"~ Building rule $key ($acl)\n";
    

if (!
$type_count && !$type_and && !$type_or)
    {
    
// is equal to another meta
        
    
if ($acl[0]=='!')
        {
        
$neg='!';
        
$acl_name=trim(substr($acl,1));
        }
    else
        {
        
$acl_name=$acl;
        
$neg='';
        }

    if (
$debug)
        echo 
"~ Substituting $key for $acl_name\n";
    
    if (!isset(
$meta_acls[$acl_name]))
        {
        
// Does not refer to a meta acl
        
        
if (!isset($rules[$acl_name]))
            {
            echo 
"! warning: rule $acl_name referred in $key does not exist\n";
            return;
            }
            
        
// Points to a normal rule
        
        
if ($debug)
            echo 
"~ Adding meta rule $key as normal rule $neg$acl_name\n";
        
        if (!isset(
$rules[$key]))
            {
            
$rules[$key] = $rules[$acl_name];
            
$rules[$key]['name'] = $key;
            
$rules[$key]['ok']=true;
            }
            
        
$rules[$key]['verb'] = $neg.$rules[$acl_name]['verb'];
        
$rules[$key]['condition'] = $neg.$rules[$acl_name]['condition'];
        
$rules[$key]['statment'] = $neg.$rules[$acl_name]['statment'];
        
$rules[$key]['uses'] = $rules[$acl_name]['uses'];
        }
    else
        {
        if (
$debug)
            echo 
"~ Adding meta rule $key as meta rule $neg$acl_name\n";
            
        
$acl $neg.$meta_acls[$acl_name];
        
build_meta($key,$acl,false);
        }
        
    return;
    }

if (
$type_count)
    {    
    
make_meta_sum($key,$acl);
    }
else
    if (
$type_and)
        
make_meta_and($key,$acl);
    else
        {
        
// Remove parentesis    
        
make_meta_or($key,$acl);
        }

if (empty(
$rules[$key]['statment']))
    {
    
$rules[$key]['verb'] = 'acl';    
    
$rules[$key]['condition'] = $acl_prefix.$key;
    
$rules[$key]['statment'] = "acl = $acl_prefix".$key;    
    
$rules[$key]['uses'] = $key;
    
$rules[$key]['used'] = 1;
    }
}

//-----------------------------------------------------

function make_meta_and($key,$expression)
{
global 
$rules$debug$acl_prefix;

$parts=explode('&&',$expression);
$uses=array();
$acl='';

foreach (
$parts as $lnum => $operand)
    {
    
$operand=trim($operand);
    
    if (
$operand=='') continue;
    
    if (
$operand[0]=='!')
        {
        
$neg='!';
        
$operand=trim(substr($operand,1));
        }
    
    if (
$acl!='')
        
$acl.="\n\t\t";
        
    if (!empty(
$rules[$operand]['statment']))
        {
        
$acl.=$neg.$rules[$operand]['statment'];
        
$uses=array_merge($uses,$rules[$operand]['uses']);
        }
    else
        {
        
$acl.=$neg."acl = $acl_prefix$operand";
        
$uses[]=$operand;
        
        if (
$debug)
            echo 
"~ Rule $key needs $operand (AND)\n";
        }
    }

$rules[$key]['name']=$key;
$rules[$key]['acl']='';
$rules[$key]['action']='meta';
$rules[$key]['rule']=$expression;
$rules[$key]['statment']=$acl;
$rules[$key]['uses']=$uses;
$rules[$key]['ok']=true;
}

//-----------------------------------------------------

function make_meta_or($key,$expression,$sep='||')
{
global 
$rules$acl_prefix;

$parts=explode($sep,$expression);
$uses=array();
$acl=$acl_prefix."$key:\n";

$verb '';
$regex '';
$all_regex true;

foreach (
$parts as $lnum => $operand)
    {
    
$operand=trim($operand);
    
    if (
$operand=='') continue;
    
    if (
$operand[0]=='!')
        {
        
$neg='!';
        
$operand=substr($operand,1);
        }
    else
        
$neg='';
        
    if (isset(
$rules[$operand]))
        {
        
$acl.="\taccept\t$neg".$rules[$operand]['statment']."\n";
        
$uses=array_merge($uses,$rules[$operand]['uses']);
        
        if (
substr($rules[$operand]['verb'],-5)=='regex')
            {
            
$verb $rules[$operand]['verb'];
            
            if (
$regex=='')
                
$regex $rules[$operand]['condition'];
            else
                
$regex.=":\\\n\t\t\t".$rules[$operand]['condition'];
            }
        else
            
$all_regex false;
        }
    else
        {
        
$acl.="\taccept\t".$neg."acl = ".$acl_prefix.$operand."\n";    
        
$uses[]=$operand;
        
$all_regex false;
        }
    }

$acl.=$accept;
$acl.="\tdeny\n";

$rules[$key]['name']=$key;
$rules[$key]['action']='meta';
$rules[$key]['rule']=$expression;
$rules[$key]['uses']=$uses;
$rules[$key]['ok']=true;


if (
$all_regex)
    {
    
$rules[$key]['verb'] = $verb;
    
$rules[$key]['condition'] = $regex;
    
$rules[$key]['statment'] = $verb.' = '.$regex;
    }
else
    
$rules[$key]['acl']=$acl;

}

//-----------------------------------------------------

function make_meta_sum($key,$expression)
{
global 
$rules,$acl_prefix;

$pos=strpos($expression,'>');
    
if (
$pos==0)
    {
    echo 
"! warning: rule $key does not have comparision operator\n";
    return;
    }
        
$value=trim(substr($expression,$pos+1));
$acl=trim(substr($expression,0,$pos-1));

if (
$value==0)
    {
    
//Convert to OR
    
make_meta_or($key,$acl,'+');
    return;
    }
    
$parts=explode('+',$acl);
$uses=array();

$acl=$acl_prefix."$key:\n\twarn\tset SA2E_VAR2 = 0\n";

$accept="\taccept\tcondition = \${if >{\$SA2E_VAR2}{".$value."}}\n";

foreach (
$parts as $lnum => $operand)
    {
    
$operand=trim($operand);
    
    if (
$operand=='') continue;
    
    if (
$operand[0]=='!')
        {
        
$neg='!';
        
$operand=substr($operand,1);
        }
    else
        
$neg='';
        
    if (isset(
$rules[$operand]))
        {
        
$acl.="\twarn\t$neg".$rules[$operand]['statment']."\n";
        
$uses=array_merge($uses,$rules[$operand]['uses']);
        }
    else
        {
        
$acl.="\twarn\t".$neg."acl = ".$acl_prefix.$operand."\n";
        
$uses[]=$operand;
        }
        
    
$acl.="\t\tset SA2E_VAR2 = \${eval:\$SA2E_VAR2+1}\n";
    }

$acl.=$accept;
$acl.="\tdeny\n";

$rules[$key]['name']=$key;
$rules[$key]['acl']=$acl;
$rules[$key]['action']='meta';
$rules[$key]['rule']=$expression;
$rules[$key]['uses']=$uses;
$rules[$key]['ok']=true;
}

//-----------------------------------------------------

function process_meta($rule)
{
global 
$rules,$debug$missing_rules;

// find need rules

$rules[$rule['name']]['done']=true;

$needrules strtok($rule['rule'],'>');
//$needrules = strtok($needrules,'<');
//$needrules = strtok($needrules,'=');
$needrules str_replace('&&',' ',$needrules);
$needrules str_replace('||',' ',$needrules);
$needrules str_replace('!',' ',$needrules);
$needrules str_replace('(',' ',$needrules);
$needrules str_replace(')',' ',$needrules);
$needrules str_replace('+',' ',$needrules);

$needrules explode(' ',$needrules);

foreach (
$needrules as $key => $rulename)
    {    
    if (
$rulename=='')
        continue;
    
    
$rname=$rulename;
    
    if (
$debug)
        {
        echo 
"~ $rule[name] needs $rulename\n";
        }
        
    if (!isset(
$rules[$rname]))
        {
        echo 
"! warning: rule $rulename need by $rule[name] does not exist\n";
        if (isset(
$missing_rules[$rulename]))
            
$missing_rules[$rulename]++;
        else
            
$missing_rules[$rulename]=1;
        return;
        }
    
    if (
$rules[$rname]['action']=='meta' && !$rules[$rname]['done'])
        
process_meta($rules[$rname]);

    if (!
$rules[$rname]['ok'])
        {
        echo 
"! warning: rule $rulename need by $rule[name] cannot be converted\n";
        if (isset(
$missing_rules[$rulename]))
            
$missing_rules[$rulename]++;
        else
            
$missing_rules[$rulename]=1;
        return;
        }
    }

// Now all need rules exist

$rules[$rule['name']]['ok'] = true;

$ruleval=$rule['rule'];

if (
strpos($ruleval,'+')>0)
    {
    
$ruleval=str_replace('(','',$ruleval);
    
$ruleval=str_replace(')','',$ruleval);    
    }
    
$expr get_acl_expression($ruleval,$rule['name']);
    
if (
$debug)
    echo 
"~ meta rule $rule[name] saved as $expr\n";
}

//-----------------------------------------------------

function get_acl_expression($ruleval,$acl_name)
{
global 
$meta_acls,$debug;

// Check for parentesis

$clean $ruleval;
$pos strpos($clean,'(');
$num 1;

while (
$clean[$pos]=='(')
    {
    
// find closing )    
    
$last=0;
    
$top=strlen($clean);
    
$done=1;
    
    for (
$i=$pos+1;$i<$top;$i++)
        {
        if (
$clean[$i]==')')
            {
            
$done--;
            if (
$done==0) break;
            }
        else
            if (
$clean[$i]=='(')
                
$done++;
        }
        
    
$last=$i;
    
    
$par=trim(substr($clean,$pos+1,$last-$pos-1));
    
$acl_subname $acl_name."_PAR$num";
    
    if (
$pos==0)
        
$clean=$acl_subname.' '.substr($clean,$last+1);
    else
        
$clean=substr($clean,0,$pos).' '.$acl_subname.' '.substr($clean,$last+1);
        
    
get_acl_expression($par,$acl_subname);
    
    
$pos strpos($clean,'(');
    
$num++;
    }    
    
if (
$debug)
    echo 
"~ $acl_name converted from $ruleval to $clean\n";
    
$meta_acls[$acl_name] = $clean;
return 
$clean;
}
    
//-----------------------------------------------------

function process_header($rule)
{
global 
$rules,$debug;

if (
substr($rule['rule'],0,5)=='eval:')
    {
    
cf_eval($rule);
    return;
    }

if (
substr($rule['rule'],0,7)=='exists:')
    {
    
$header=strtolower(substr($rule['rule'],7));
    
    if (
$header=='tocc')
        
$condition "\${if def:h_to: {1}{def:h_cc:}}";        
    else
        
$condition "\${if def:h_".$header.":}";
        
    
make_acl($rule,'condition',$condition);
    return;
    }

$ius=strpos($rule['rule'],'[if-unset:');
    
if (
$ius>0)
    {
    
$ruleval=trim(substr($rule['rule'],0,$ius-1));
    
$unset=trim(strtok(substr($rule['rule'],$ius+10),']'));
    }
else
    {
    
$ruleval=$rule['rule'];
    
$unset='';
    }
            
$pos=strpos($rule['rule'],' =~');

if (
$pos>0)
    {
    
$res='';
    }
else
    {
    
$pos=strpos($rule['rule'],' !~');

    if (!
$pos)
        {
        
warn($rule);
        return;
        }
    
$res='{0}{1}';
    }

$header strtolower(trim(substr($ruleval,0,$pos)));
$match eximize_regex(trim(substr($ruleval,$pos+3)),false);

switch (
$header)
    {
    case 
'all':
        
$condition="\${if match {\$message_headers}{".$match."}$res}";    
        
make_acl($rule,'condition',$condition);
        return;
    
    case 
'messageid':
        
$compare="\$h_message-id:\\n\$h_resent-message-id:\\n\$h_x-message-id:";
        break;

    case 
'tocc':
        
$compare="\$h_to:\\n\$h_cc:";
        break;
        
    case 
'envelopefrom':
        
$compare="\$sender_address";
        break;
        
    case 
'return-path':
        
$compare="<\$sender_address>";
        break;
        
    default:
        
$compare="\$h_".$header.":";
    
        if (
substr($header,-5)==':addr')
            {
            
$header=strtok($header,':');
            
$compare="\${address:\$h_".$header.":}";
            }
    
        if (
substr($header,-4)==':raw')
            {
            
$header=strtok($header,':');
            
$compare="\$rh_".$header.":";
            }
    }
    
//$rules[$rule['name']]['describe'].=" [$compare]";
    
if ($unset!='')
    {
    
$compare="\${if eq {".$compare."}{}{".$unset."}{".$compare."}}";
    }
    
$condition="\${if match {".$compare."}{".$match."}$res}";    
make_acl($rule,'condition',$condition);
}

//-----------------------------------------------------

function make_acl($rule,$verb,$condition,$place='data')
{
global 
$rules;

$rules[$rule['name']]['verb'] = $verb;
$rules[$rule['name']]['condition'] = $condition;
$rules[$rule['name']]['statment'] = $verb.' = '.$condition;
$rules[$rule['name']]['place'] = $place;
$rules[$rule['name']]['ok'] = true;
}

//-----------------------------------------------------

function eximize_regex($regex$replace_colon)
{
if (
$replace_colon)
    
$regex=str_replace(':','::',$regex);

if (
$regex[0]=='/')
    {
    if (
substr($regex,-1)=='/')
        
$regex=substr($regex,1,-1);
    else
        {
        
$i=strlen($regex)-1;
        while (
$i>&& $regex[$i]!='/'$i--;
        
$regex='(?'.substr($regex,$i+1).')'.substr($regex,1,$i-1);
        }
    }

return 
"\\N$regex\\N";
}

//-----------------------------------------------------

function process_body($rule)
{
global 
$rules,$mime_acl_count;

if (
substr($rule['rule'],0,5)=='eval:')
    {
    
cf_eval($rule);
    return;
    }

$acl_name "sa_acl_mime_$mime_acl_count";

make_acl($rule,'condition',"\${extract {k$mime_acl_count}{\$SA2E_VAR1}}",'mime');

$regex=eximize_regex($rule['rule'],true);

$acl"mime_regex = $regex\n";

$rules[$rule['name']]['acl'] = $acl;

$rules[$rule['name']]['varname'] = $mime_acl_count;

$mime_acl_count++;
}

//-----------------------------------------------------

function process_rawbody($rule)
{
global 
$rules;

if (
substr($rule['rule'],0,5)=='eval:')
    {
    
cf_eval($rule);
    return;
    }
    
$regex=eximize_regex($rule['rule'],true);

make_acl($rule,'regex',$regex);
}

//-----------------------------------------------------

function cf_eval($rule)
{
global 
$acl_rbl;

$pos=strpos($rule['rule'],':');
$fin=strpos($rule['rule'],'(');

$cmd=substr($rule['rule'],$pos+1,$fin-$pos-1);
$arg=strtok(substr($rule['rule'],$fin+1),')');

$pre_args=explode(',',$arg);
$args=array();

foreach (
$pre_args as $key => $arg)
    {
    
$arg=trim($arg);
    
    if (
$arg=='') continue;
    
    if (
$arg[0]=="'" && substr($arg,-1)=="'")
        
$args[]=substr($arg,1,-1);
    else
        
$args[]=$arg;
    }
    

if (
$cmd=='check_rbl')
    {
    
$rbl=$args[1];
    
    if (
substr($rbl,-1)=='.')
        
$rbl=substr($rbl,0,-1);

    if (isset(
$args[2]))
        {
        if (
strpos($args[2],'/')>0)
            {
            
warn($rule);
            return;
            }
        
$acl=$rbl.'='.$args[2];
        }
    else
        
$acl=$rbl;
        
    
make_acl($rule,'dnslists',$acl);
    
    
$acl_rbl[$args[0]]=$rbl;
    
$rules[$rule['name']]['ok']=true;    
    return;
    }
    
if (
$cmd=='check_rbl_sub')
    {
    if (!isset(
$acl_rbl[$args[0]]))
        {
        echo 
"! error: unknown rbl $args[0]\n";
        return;
        }
    
    
$rbl=$acl_rbl[$args[0]];
    
$acl=$rbl.'='.$args[1];
    
make_acl($rule,'dnslists',$acl);    
    
$rules[$rule['name']]['ok']=true;    
    
    echo 
$rule['rule']." -> $cmd $acl";
    
print_r($args);
    return;
    }
//if ($cmd=='check_rbl_txt')
//check_rbl_envfrom
//check_rbl_txt

if (!empty($rule['score']))
    
warn($rule);
}

//-----------------------------------------------------
    
function process_rule($rule)
{
global 
$scoring_rules$debug$rules$use_mime_regex;

if (
$debug)
    echo 
"~ Converting rule $rule[name]\n";
    
switch (
$rule['action'])
    {
    case 
'body':
    case 
'uri':
        if (
$use_mime_regex)
            
process_body($rule);
        else
            
process_rawbody($rule);
        break;
        
    case 
'full':
    case 
'rawbody':
        
process_rawbody($rule);
        break;
        
    case 
'header':
        
process_header($rule);
        break;
        
    case 
'meta':
        break;
        
    default:
        
warn($rule);
    }
}

//-----------------------------------------------------

function warn ($rule)
{
//print_r($rule);
echo "! warning: unknown method $rule[rule] in rule $rule[name] ($rule[action])\n";
}

//-----------------------------------------------------

function process_cf ($fname)
{
global 
$rules$debug$blacklist;

if (!(
$fp=fopen($fname,'rt')))
    {
    echo 
"! error: unable to open $fname\n";
    return;
    }
    
if (
$debug)
    echo 
"~ processing $fname\n";
    
while (!
feof($fp))
    { 
    
$buffer trim(fgets($fp));
    
    if (
$buffer=='' || $buffer[0]=='#') continue;
    
    
$partspreg_split("/[\s]+/",$buffer);

    
$cmd array_shift($parts);
    
$rule array_shift($parts);
    
$value trim(implode(' ',$parts));
    
$action='';
    
$field='';
    
    if (
$cmd=='blacklist_from')
        {
        
$blacklist[]=$rule;
        continue;
        }
        
    if (
$cmd=='header' || $cmd=='body' || $cmd=='meta' || $cmd=='uri' ||
        
$cmd=='full' || $cmd=='rawbody')
        
$action=$cmd;
    else
        
$action='';
        
    if (
$cmd=='describe' || $cmd=='score' || $cmd=='tflags')
        
$field=$cmd;
    else
        
$field='';
        
    if (
$field=='' && $action=='') continue;
    
    if (
$cmd=='score')
        {
        
$value=trim(strtok($value,'#'));
        
$parts=preg_split("/[\s]+/",$value);
        
        if (
count($parts)==1)
            {
            
$rules[$rule]['score']=$parts[0];
            }
        else
            {
            
$rules[$rule]['score']=$parts[1];
            }
        
        continue;
        }
        
    if (
$action!='')
        {
        
$rules[$rule]['action']=$action;
        
$rules[$rule]['rule']=$value;
        
$rules[$rule]['name']=$rule;
        
$rules[$rule]['acl'] = '';
        
$rules[$rule]['done']=false;
        
$rules[$rule]['used']=0;
        
$rules[$rule]['ok']=false;
        }
    else
        
$rules[$rule][$field]=$value;
    }
    
fclose($fp);
}
?>