<?php
/***********************************************************
 * dovecot.sieve饤֥
 **********************************************************/
// sieveեեޥå
// require
define("SIEVE_REQUIRE",      "require \"fileinto\";\n" .
                             "require \"envelope\";\n" .
                             "require \"variables\";\n\n");
// Ծ	
define("FROM_IS",            "    anyof (\n" .
                             "        header :is \"from\" \"%s\",\n" .
                             "        envelope :is \"from\" \"%s\"\n    )");
// Ծޤ
define("FROM_CONTAINS",      "    anyof (\n" .
                             "        header :contains \"from\" \"%s\",\n" .
                             "        envelope :contains \"from\" \"%s\"\n    )");
// Ծޤޤʤ
define("FROM_NOT_CONTAINS",  "    allof (\n" .
                             "        not header :contains \"from\" \"%s\",\n" .
                             "        not envelope :contains \"from\" \"%s\"\n    )");
// Ծ郎
define("FROM_EMPTY",         "    anyof (\n" .
                             "        not exists \"from\",\n" .
                             "        header :is \"from\" \"\",\n" .
                             "        envelope :is \"from\" \"\"\n    )");
// ̾
define("SUBJ_IS",            "    header :is :comparator \"i;octet\"" .
                             " \"subject\" \"%s\"");
// ̾ޤ
define("SUBJ_CONTAINS",      "    header :contains :comparator \"i;octet\"" .
                             " \"subject\" \"%s\"");
// ̾ޤޤʤ
define("SUBJ_NOT_CONTAINS",  "    not header :contains :comparator \"i;octet\"" .
                             " \"subject\" \"%s\"");
// ̾郎
define("SUBJ_EMPTY",         "    anyof (\n" .
                             "        not exists \"subject\",\n" .
                             "        header :is \"subject\" \"\"\n    )");
// 
define("ENV_IS",             "    anyof (\n" .
                             "        header :is [\"to\", \"cc\"] \"%s\",\n" .
                             "        envelope :is \"to\" \"%s\"\n    )");
// ޤ
define("ENV_CONTAINS",       "    anyof (\n" .
                             "        header :contains [\"to\", \"cc\"] \"%s\",\n" .
                             "        envelope :contains \"to\" \"%s\"\n" .
                             "    )");
// ޤޤʤ
define("ENV_NOT_CONTAINS",   "    allof (\n" .
                             "        not header :contains \"to\" \"%s\",\n" .
                             "        not header :contains \"cc\" \"%s\",\n" .
                             "        not envelope :contains \"to\" \"%s\"\n" .
                             "    )");
// 郎
define("ENV_EMPTY",          "    anyof (\n" .
                             "        allof (\n" .
                             "            not exists \"to\",\n" .
                             "            not exists \"cc\"\n" .
                             "        ),\n" .
                             "        allof (\n" .
                             "            header :is \"to\" \"\",\n" .
                             "            header :is \"cc\" \"\"\n" .
                             "        ),\n" .
                             "        allof (\n" .
                             "            header :is \"to\" \"\",\n" .
                             "            not exists \"cc\"\n" .
                             "        ),\n" .
                             "        allof (\n" .
                             "            header :is \"cc\" \"\",\n" .
                             "            not exists \"to\"\n" .
                             "        ),\n" .
                             "        envelope :is \"to\" \"\"\n" .
                             "    )");

// ᡼žΥեޥå
define("LIST_FORMAT",        "if allof (\n%s%s\n)\n");
define("FIRSTMATCH_RULE",    "    not string :matches \"\${firstmatch}\" " . 
                             "\"1\"");

// ᡼žΥեޥå
define("FWDPROCESS_FORMAT",  "{\n" .
                             "    redirect \"%s\";\n" .
                             "    set \"rule_match\" \"1\";\n%s%s" .
                             "}\n");
define("FIRSTMATCH_FORMAT",  "set \"firstmatch\" \"1\";\n"); 
define("RECIEVE_FORMAT",     "set \"recieve\" \"1\";\n"); 
define("ALLTRANSFER_FORMAR", "redirect \"%s\";\n" . 
                             "set \"rule_match\" \"1\";\n%s%s");
define("RECPROCESS_FORMAT",  "if anyof (\n" .
                             "    not string :matches \"\${rule_match}\" " . 
                             "\"1\",\n" . 
                             "    string :matches \"\${recieve}\" \"1\"\n" . 
                             ")\n" .
                             "{\n" . 
                             "    fileinto \"INBOX\";\n" . 
                             "}\n");


// 
define("TYPE_FROM",          "0");
define("TYPE_SUBJ",          "1");
define("TYPE_ENV",           "2");

// 롼
define("RULE_IS",            "1");
define("RULE_CONTAINS",      "2");
define("RULE_NOT_CONTAINS",  "3");
define("RULE_EMPTY",         "4");
define("FIRSTMATCH_ON",      "1");

// ʸ
define("STRCODE_FROM",         "eucjp-win");
define("STRCODE_TO",           "UTF-8");

// ڤʸ
define("RULE_DELIM",           ",\n");

// ʸ
define("FWDLIST",              "forward");
define("SENDER",               " sender");
define("SUBJECT",              " subject");

// ե̾
define("SIEVEFILENAME",        "dovecot.sieve");
define("TMPFILENAME",          "tmp");

// ޥ
define("MAKESIEVE_PATH",        "%sbin/make_sieve");
define("MAKESIEVE_COMMAND",     "sudo -u vmail %sbin/make_sieve %s");
define("MAIL_DIR",              "Maildir/");

/***********************************************************
 * make_sieve_rules()
 *
 * 롼κԤ
 *
 * []
 * $rule     롼Ǽѿ(Ϥ)
 * $type     롼μ
 * $ruletype 롼ξ
 * $val      Υ
 *
 * [֤]
 * TRUE      
 * FALSE     ˼
 ************************************************************/
function make_sieve_rules(&$rule, $type, $ruletype, $val)
{

    /* ʸΥ */
    if ($val !== "") {
        $escval = addslashes($val);
    } else {
        $escval = "";
    }

    /* ऴȤʬ */
    switch($type) {

        /* Ծ */
        case TYPE_FROM:

            /* 롼뤴Ȥʬ */
            switch ($ruletype) {

                /*  */
                case RULE_IS:
                    $tmp = sprintf(FROM_IS, $escval, $escval);
                break;

                /* ޤ */
                case RULE_CONTAINS:
                    $tmp = sprintf(FROM_CONTAINS, $escval, $escval);
                break;

                /* ޤޤʤ */
                case RULE_NOT_CONTAINS:
                    $tmp = sprintf(FROM_NOT_CONTAINS, $escval, $escval, $escval);
                break;

                /*  */
                case RULE_EMPTY:
                    $tmp = sprintf(FROM_EMPTY);
                break;

                /* ʳ */
                default:
                    return FALSE;
            }
        break;

        /* ̾ */
        case TYPE_SUBJ:

            /* 롼뤴Ȥʬ */
            switch ($ruletype) {

                /*  */
                case RULE_IS:
                    $tmp = sprintf(SUBJ_IS, $escval);
                break;

                /* ޤ */
                case RULE_CONTAINS:
                    $tmp = sprintf(SUBJ_CONTAINS, $escval);
                break;

                /* ޤޤʤ */
                case RULE_NOT_CONTAINS:
                    $tmp = sprintf(SUBJ_NOT_CONTAINS, $escval);
                break;

                /*  */
                case RULE_EMPTY:
                    $tmp = sprintf(SUBJ_EMPTY);
                break;

                /* ʳ */
                default:
                    return FALSE;
            }
        break;

        /*  */
        case TYPE_ENV:

            /* 롼뤴Ȥʬ */
            switch ($ruletype) {

                /*  */
                case RULE_IS:
                    $tmp = sprintf(ENV_IS, $escval, $escval);
                break;

                /* ޤ */
                case RULE_CONTAINS:
                    $tmp = sprintf(ENV_CONTAINS, $escval, $escval);
                break;

                /* ޤޤʤ */
                case RULE_NOT_CONTAINS:
                    $tmp = sprintf(ENV_NOT_CONTAINS, $escval, $escval, $escval);
                break;

                /*  */
                case RULE_EMPTY:
                    $tmp = sprintf(ENV_EMPTY);
                break;

                /* ʳ */
                default:
                    return FALSE;
            }
        break;

        /* إåμब */
        default:
            return FALSE;
    }

    /* ʸɤѴ */
    $rule = mb_convert_encoding($tmp, STRCODE_TO, STRCODE_FROM);

    return TRUE;
}

/***********************************************************
 * write_fwdlist_rules()
 *
 * ž롼ν񤭹ߤԤ
 *
 * []
 * $data             롼Υǡ
 * $o_array          롼ν
 * $path             롼Υѥ
 * &$sieve_detail    sieveեʸ
 *
 * [֤]
 * TRUE      
 * FALSE     ˼
 ************************************************************/
function write_fwdlist_rules($ruledata, $o_array, &$sieve_detail)
{
    // ѿν
    $data = array();
    global $log_msg;
    global $msgarr;
    global $web_conf;
    global $url_data;

    /* foreach ǽ֤˥å */
    foreach($o_array as $key => $value) {

        // OFFΥ̵
        if ($value['state'] === "0") {
            continue;
        }
        if ($value['filter_id'] === "") {
            continue;
        }

        /* ѿν */
        $tmp = "";
        $onerule = "";
        $rules = "";
        $save = "";
        $data = array();
        $id = $value['filter_id'];

        // žξ
        if ($ruledata[$id][FROM_TERM] === INVALID_TERM && 
            $ruledata[$id][SUBJECT_TERM] === INVALID_TERM &&
            $ruledata[$id][RECIPIENT_TERM] === INVALID_TERM) {

            // FirstMatch郎ONξ
            if ($web_conf[$url_data["script"]]["forwardfirstmatch"]
                === FIRSTMATCH_ON) {
                // 롼
                $first_match = FIRSTMATCH_RULE;

                // 롼ִ
                $rules = sprintf(LIST_FORMAT, $first_match, "");

                // 롼Ǽ
                $sieve_detail .= $rules;

                // 
                $first_match = "    " . FIRSTMATCH_FORMAT;
                // Ĥ/Ĥʤ
                $recieve = "";
                if ($ruledata[$id][RECEIVED_MAIL] === RECEIVED_ON) {
                    $recieve = "    " . RECIEVE_FORMAT;
                }

                // 롼ִ
                $rules = sprintf(FWDPROCESS_FORMAT,
                                 $ruledata[$id][TRANS_ADDR],
                                 $first_match, $recieve);

                // 롼Ǽ
                $sieve_detail .= $rules;

            // FirstMatch郎OFFξ
            } else {
                // 
                $first_match = "";

                // Ĥ/ĤʤΥ롼
                $recieve = "";
                if ($ruledata[$id][RECEIVED_MAIL] === RECEIVED_ON) {
                    $recieve = RECIEVE_FORMAT;
                }

                // 롼ִ
                $rules = sprintf(ALLTRANSFER_FORMAR,
                                 $ruledata[$id][TRANS_ADDR],
                                 $first_match, $recieve);

                // 롼Ǽ
                $sieve_detail .= $rules;
            }

        // ̵žꤵƤʤȤƥ롼Ǽ
        } else {

            // ԥ롼뤬гǼ
            if ($ruledata[$id][FROM_TERM] !== INVALID_TERM) {
                $input_value = "";
                if (isset($ruledata[$id][FROM_FLAG])) {
                    $input_value = $ruledata[$id][FROM_FLAG];
                }
                $ret = make_sieve_rules($tmp, TYPE_FROM,
                                        $ruledata[$id][FROM_TERM],
                                        $input_value);
                if ($ret === FALSE) {
                    // 顼
                    $log_msg = sprintf($msgarr['26001'][LOG_MSG],
                                  FWDLIST . SENDER, $ruledata[$id][FROM_FLAG],
                                       $ruledata[$id][FROM_TERM]);
                    return FALSE;
                } else {
                    $data[] =  $tmp;
                }
            }

            // ̾롼뤬гǼ
            if ($ruledata[$id][SUBJECT_TERM] !== INVALID_TERM) {
                $input_value = "";
                if (isset($ruledata[$id][SUBJECT_FLAG])) {
                    $input_value = $ruledata[$id][SUBJECT_FLAG];
                }
                $ret = make_sieve_rules($tmp, TYPE_SUBJ,
                                        $ruledata[$id][SUBJECT_TERM],
                                        $input_value);
                if ($ret === FALSE) {
                    // 顼
                    $log_msg = sprintf($msgarr['26001'][LOG_MSG],
                               FWDLIST . SENDER, $ruledata[$id][SUBJECT_FLAG],
                                       $ruledata[$id][SUBJECT_TERM]);
                    return FALSE;
                } else {
                    $data[] =  $tmp;
                }
            }

            // 롼뤬гǼ
            if ($ruledata[$id][RECIPIENT_TERM] !== INVALID_TERM) {
                $input_value = "";
                if (isset($ruledata[$id][RECIPIENT_FLAG])) {
                    $input_value = $ruledata[$id][RECIPIENT_FLAG];
                }
                $ret = make_sieve_rules($tmp, TYPE_ENV,
                                        $ruledata[$id][RECIPIENT_TERM],
                                        $input_value);
                if ($ret === FALSE) {
                    // 顼
                    $log_msg = sprintf($msgarr['26001'][LOG_MSG],
                             FWDLIST . SENDER, $ruledata[$id][RECIPIENT_FLAG],
                                       $ruledata[$id][RECIPIENT_TERM]);
                    return FALSE;
                } else {
                    $data[] =  $tmp;
                }
            }

            // 롼
            $oneline = implode(RULE_DELIM, $data);

            // FirstMatchȽ
            $first_match = "";
            if ($web_conf[$url_data["script"]]["forwardfirstmatch"] 
                === FIRSTMATCH_ON) {
                $first_match = FIRSTMATCH_RULE . RULE_DELIM;
            }

            // 롼ִ
            $rules = sprintf(LIST_FORMAT, $first_match, $oneline);

            // 롼Ǽ
            $sieve_detail .= $rules;

            // 
            $first_match = "";
            if ($web_conf[$url_data["script"]]["forwardfirstmatch"] === 
                                                               FIRSTMATCH_ON) {
                $first_match = "    " . FIRSTMATCH_FORMAT;
            }
            $recieve = "";
            if ($ruledata[$id][RECEIVED_MAIL] === RECEIVED_ON) {
                $recieve = "    " . RECIEVE_FORMAT;
            }

            // 롼ִ
            $rules = sprintf(FWDPROCESS_FORMAT, $ruledata[$id][TRANS_ADDR], 
                             $first_match, $recieve);

            // 롼Ǽ
            $sieve_detail .= $rules;

        }
    }

    // Ĥ/Ĥʤν񤭹
    $sieve_detail .= RECPROCESS_FORMAT;

    return TRUE;
}

/***********************************************************
 * make_sievefile
 *
 * dovecot.sieveեκ
 *
 * []
 *       ̵
 *
 * [֤]
 * TRUE      
 * FALSE     ˼
 ************************************************************/
function make_sievefile()
{
    // ѿ
    global $log_msg;
    global $msgarr;
    global $err_msg;
    global $basedir;
    global $ldapdata;
    $tmpname = "";
    $filterorder = array();
    $filterarticle = array();
    $sieve_detail = "";

    // ldapμ

    // γǼ
    $path = $ldapdata[0]['mailDirectory'][0];

    // dovecot.sieveեΥѥ
    $sievefile = $path . "/" . MAIL_DIR . SIEVEFILENAME;

    // ե륿
    // μ
    order_analysis($ldapdata[0]['mailFilterOrder'][0], $filterorder);

    // ƥμ
    $ret = article_analysis($ldapdata[0]['mailFilterArticle'], $filterarticle);
    if ($ret === FALSE) {
        $err_msg = $msgarr['25005'][SCREEN_MSG];
        return FALSE;
    }

    // require
    $sieve_detail .= SIEVE_REQUIRE;

    // ᡼žΥ¸ߤȤ
    if (isset($filterarticle)){

        // ᡼ž񤭹
        $ret = write_fwdlist_rules($filterarticle, $filterorder,
                                   $sieve_detail);

        if ($ret === FALSE) {
            return FALSE;
        }
    }

    // ޥɤ¸ߥå
    $cmdpath = sprintf(MAKESIEVE_PATH, $basedir);
    if (is_file($cmdpath) === FALSE) { 
        $log_msg = sprintf($msgarr['26004'][LOG_MSG], $cmdpath);
        return FALSE;
    }

    // ޥɤ
    $cmd = sprintf(MAKESIEVE_COMMAND, $basedir, $sievefile);

    // ޥɤpopen
    $handle = popen($cmd, 'w');

    // ޥɤμ¹
    fwrite($handle, $sieve_detail);

    // ޥɥϥɥĤޥɤ֤ͤ
    $ret = pclose($handle);

    // ޥɤΥ顼
    switch ($ret) {

        // ­ʤ
        case 1:
            $log_msg = sprintf($msgarr['26005'][LOG_MSG], $cmd);
            return FALSE;

        // ŤեΥХååפ˼
        case 2:
            $log_msg = sprintf($msgarr['26006'][LOG_MSG], $cmd);
            return FALSE;

        // TMPեmvΤ˼
        // sieveեδᤷԤʤ
        case 3:
            $log_msg = sprintf($msgarr['26007'][LOG_MSG], $cmd);
            return FALSE;

        // ѡߥåѹ˼
        // sieveեδᤷԤʤ
        case 4:
            $log_msg = sprintf($msgarr['26008'][LOG_MSG], $cmd);
            return FALSE;

        // եκ˼
        case 5:
            $log_msg = sprintf($msgarr['26009'][LOG_MSG], $cmd);
            return FALSE;

        // եؤν񤭹ߤ˼
        case 6:
            $log_msg = sprintf($msgarr['26010'][LOG_MSG], $cmd);
            return FALSE;
    }

    return TRUE;
}

?>
