* * Licensed under the GNU GPL. For full terms see the file COPYING that came * with the Squirrelmail distribution. * * $Id: buildrule.php,v 1.15 2004/05/12 14:16:09 avel Exp $ */ /** * Script Variables Schema * NB: Might be Incomplete. * * The following table tries to describe the variables schema that is used by * avelsieve. * * VARIABLES * --------- * AVELSIEVE_CREATED * AVELSIEVE_MODIFIED * AVELSIEVE_COMMENT * AVELSIEVE_VERSION * * Condition * * 1 // Address Match * 1 // Not implemented yet. * 2 header[$n] // Header Match * 2 matchtype[$n] "is" | "contains" | "matches" | "lt" | "regex" | ... * 2 headermatch[$n] string * 2 condition undefined | "or" | "and" * 3 sizerel "bigger" | "smaller" // Size match * 3 sizeamount int * 3 sizeunit "kb" | "mb" * 4 // Always * 10 score int // Spam Rule * 10 tests array * 10 action 'trash' | 'junk' | 'discard' * * Action * * action 1 | 2 | 3 | 4 | 5 | 6 * * 1) // Keep * * 2) // Discard * * 3) // Reject w/ excuse * * excuse string valid only for: action==3 * * 4) // Redirect * * redirectemail string (email) valid only for: action==4 * keep string (email) valid only for: action==4 (?TBC) * * 5) // Fileinto * * folder valid only for: action==5 * * 6) // Vacation * * vac_days int * vac_addresses string * vac_message string valid only for: action==6 * * * -) // All * * keepdeleted boolean * stop boolean * notify array * 'method' => string * 'id' => string * 'options' => array( [0]=> foo, [1] => bar ) * 'priority' => low|normal|high * 'message' => string * * */ /** * Build a snippet which is used for header rules and spam rule whitelists. * Takes arguments in natural English language order: 'From contains foo'. * @param string $header * @param string $matchtype * @param string $headermatch * @param string $type 'verbose', 'terse' or 'rule' * verbose = return a (verbose) textual description of the rule. * terse = return a very terse description * rule = return a string with the appropriate SIEVE code. * @return string */ function build_headerrule_snippet($header, $matchtype, $headermatch, $type='rule') { $out = ''; $text = ''; $terse = ''; if($header == 'toorcc') { $text .= " "To" / "Cc" "; $terse .= " TO OR CC"; } else { $text .= " "".htmlspecialchars($header)."" "; $terse .= " ".htmlspecialchars($header)." "; } // $escapeslashes = false; switch ($matchtype) { case "is": $out .= "header :is"; $text .= _("is"); $terse .= "="; break 1; case "is not": $out .= "not header :is"; $text .= _("is not"); $terse .= "!="; break 1; case "contains": $out .= "header :contains"; $text .= _("contains"); $terse .= "="; break 1; case "does not contain": $out .= "not header :contains"; $text .= _("does not contain"); $terse .= "!~="; break 1; case "matches": $out .= "header :matches"; $text .= _("matches"); $terse .= "M="; $escapeslashes = true; break 1; case "does not match": $out .= "not header :matches"; $text .= _("does not match"); $terse .= "!M="; $escapeslashes = true; break 1; case "gt": $out .= "header :value \"gt\" :comparator \"i;ascii-numeric\""; $text .= _("is greater than"); $terse .= ">"; break 1; case "ge": $out .= "header :value \"ge\" :comparator \"i;ascii-numeric\""; $text .= _("is greater or equal to"); $terse .= ">="; break 1; case "lt": $out .= "header :value \"lt\" :comparator \"i;ascii-numeric\""; $text .= _("is lower than"); $terse .= "<"; break 1; case "le": $out .= "header :value \"le\" :comparator \"i;ascii-numeric\""; $text .= _("is lower or equal to"); $terse .= "<="; break 1; case "eq": $out .= "header :value \"eq\" :comparator \"i;ascii-numeric\""; $text .= _("is equal to"); $terse .= "=="; break 1; case "ne": $out .= "header :value \"ne\" :comparator \"i;ascii-numeric\""; $text .= _("is not equal to"); $terse .= "!="; break 1; case "regex": $out .= "header :regex :comparator \"i;ascii-casemap\""; $text .= _("matches the regural expression"); $terse .= "R="; $escapeslashes = true; break 1; case "not regex": $out .= "not header :regex :comparator \"i;ascii-casemap\""; $text .= _("does not match the regural expression"); $terse .= "!R="; $escapeslashes = true; break 1; case "exists": $out .= "exists"; $text .= _("exists"); $terse .= "E"; break 1; case "not exists": $out .= "not exists"; $text .= _("does not exist"); $terse .= "!E"; break 1; default: break 1; } if($header == 'toorcc') { $out .= ' ["to", "cc"] '; } else { $out .= " \"" . $header . "\" "; } /* Escape slashes and double quotes */ $out .= "\"". avelsieve_addslashes($headermatch) . "\""; $text .= " \"". htmlspecialchars($headermatch) . "\""; if ($matchtype == "contains") { $terse .= " *".htmlspecialchars($headermatch)."* "; } else { $terse .= " ".htmlspecialchars($headermatch)." "; } if ($type == "terse") { return $terse; } elseif (($type == "text") || ($type == "verbose")) { return $text; } else { return $out; } } /** * Gets a $rule array and builds a part of a SIEVE script (aka a rule). * * @param $rule A rule array. * @param $type What to return. Can be one of: * verbose = return a (verbose) textual description of the rule. * terse = return a very terse description * rule = return a string with the appropriate SIEVE code. */ function makesinglerule($rule, $type="rule") { global $maxitems; /* Step zero :-) : serialize & encode my array */ $coded = urlencode(base64_encode(serialize($rule))); $out = "#START_SIEVE_RULE".$coded."END_SIEVE_RULE\n"; /* Step one: make the if clause */ /* The actual 'if' will be added by makesieverule() */ $terse = '
'; if($rule['type']=="4") { $text = _("For ALL incoming messages; "); $terse .= "ALL"; $terse .= ' | ';
} elseif($rule['type'] == "10") {
/* SpamRule */
global $spamrule_score_default, $spamrule_score_header,
$spamrule_tests, $spamrule_tests_header, $spamrule_action_default;
$spamrule_advanced = false;
if(isset($rule['advanced'])) {
$spamrule_advanced = true;
}
if(isset($rule['score'])) {
$sc = $rule['score'];
} else {
$sc = $spamrule_score_default;
}
if(isset($rule['tests'])) {
$te = $rule['tests'];
} else {
$te = array_keys($spamrule_tests);
}
if(isset($rule['action'])) {
$ac = $rule['action'];
} else {
$ac = $spamrule_action_default;
}
/*
if allof( anyof(header :contains "X-Spam-Rule" "Open.Relay.Database" ,
header :contains "X-Spam-Rule" "Spamhaus.Block.List"
),
header :value "gt" :comparator "i;ascii-numeric" "80" ) {
fileinto "INBOX.Junk";
discard;
}
// Whitelist scenario:
if allof( anyof(header :contains "X-Spam-Rule" "Open.Relay.Database" ,
header :contains "X-Spam-Rule" "Spamhaus.Block.List"
),
header :value "gt" :comparator "i;ascii-numeric" "80" ,
anyof(header :contains "From" "Important Person",
header :contains "From" "Foo Person"
)
) {
fileinto "INBOX.Junk";
discard;
}
*/
$out .= 'allof( ';
$text = _("All messages considered as SPAM (unsolicited commercial messages)");
$terse .= "SPAM";
if(sizeof($te) > 1) {
$out .= ' anyof( ';
for($i=0; $i '; $out .= " ,\n"; $out .= ' not anyof( '; for($i=0; $i | ';
$text .= "";
$text .= _("then");
$text .= " ";
}
if(isset($rule['keep'])) {
$out .= "keep;\n";
}
switch ($rule['action']) {
case "1": /* keep (default) */
$out .= "keep;";
$text .= _("keep it.");
$terse .= "KEEP";
break;
case "2": /* discard */
$out .= "discard;";
$text .= _("discard it.");
$terse .= "DISCARD";
break;
case "3": /* reject w/ excuse */
$out .= "reject text:\n".$rule['excuse']."\r\n.\r\n;";
$text .= _("reject it, sending this excuse back to the sender:")." \"".htmlspecialchars($rule['excuse'])."\".";
$terse .= "REJECT";
break;
case "4": /* redirect to address */
$out .= "redirect \"".$rule['redirectemail']."\";";
$text .= _("redirect it to the email address")." ".htmlspecialchars($rule['redirectemail']).".";
$terse .= "REDIRECT ".htmlspecialchars($rule['redirectemail']);
break;
case "5": /* fileinto folder */
$out .= 'fileinto "'.$rule['folder'].'";';
$text .= _("file it into the folder ");
/* FIXME - funny stuff has entered gettext function ... */
$text .= " " . htmlspecialchars(imap_utf7_decode_local($rule['folder'])) . "";
$text .= ".";
$terse .= "FILEINTO ".htmlspecialchars(imap_utf7_decode_local($rule['folder']));
break;
case "6": /* vacation message */
$out .= 'vacation :days '.$rule['vac_days'];
/* If vacation address does not exist, do not set the :addresses
* argument. */
if(isset($rule['vac_addresses']) && trim($rule['vac_addresses'])!="") {
$addresses = str_replace(",",'","',str_replace(" ","",$rule['vac_addresses']));
$out .= ' :addresses ["'.$addresses.'"]';
}
$out .= " text:\n".$rule['vac_message']."\r\n.\r\n;";
$text .= _("reply with this vacation message: ") . htmlspecialchars($rule['vac_message']);
$terse .= "VACATION";
break;
default:
break;
}
if(isset($rule['keep'])) {
$text .= ' ' . _("Also keep a local copy.");
$terse .= " KEEP"; } if (isset($rule['keepdeleted'])) { $text .= _(" Also keep a copy in INBOX, marked as deleted."); $out .= "\naddflag \"\\\\\\\\\\\\\\\\Deleted\";\nkeep;"; $terse .= " KEEP DELETED"; } /* Notify extension */ if (array_key_exists("notify", $rule) && is_array($rule['notify']) && ($rule['notify']['method'] != '')) { global $notifystrings, $prioritystrings; $text .= _(" Also notify using the method") . " " . htmlspecialchars($notifystrings[$rule['notify']['method']]) . ", ". _("with") . " " . htmlspecialchars($prioritystrings[$rule['notify']['priority']]) . " " . _("priority and the message") . " "" . htmlspecialchars($rule['notify']['message']) . ""."; $out .= "\nnotify :method \"".$rule['notify']['method']."\" "; $out .= ":options \"".$rule['notify']['options']."\" "; if(isset($rule['notify']['id'])) { $out .= ":id \"".$rule['notify']['id']."\" "; } if(isset($rule['notify']['priority']) && array_key_exists($rule['notify']['priority'], $prioritystrings)) { $out .= ":".$rule['notify']['priority'] . " "; } $out .= ":message \"".$rule['notify']['message']."\""; $out .= ";\n"; $terse .= " NOTIFY"; } /* Stop processing other rules */ if (isset($rule['stop'])) { $text .= _(" Then STOP processing rules."); $out .= "\nstop;"; $terse .= " STOP"; } $out .= "\n}"; $terse .= " |