<?php

require_once IEM_ADDONS_PATH . "/installer/api/installer.php";
require_once IEM_ADDONS_PATH . "/mta/config/config.php";

$installer = new Installer_API();
$installer->apply_patches("mta");

class Mta_API extends API {

    private $db = NULL;
    
    public $mta_data_temp = array();
    public $data_type_reputation = array( "0" => "reputation", "1" => "reputation_volume", "2" => "reputation_complaint", "3" => "reputation_unknown", "4" => "reputation_filtered", "5" => "blacklist" );

    public function __construct() {
        $this->db = IEM::getDatabase();
    }

    public function group_assign_users($uid=0, $users=array(  )) {
        $uid = (int) ($uid);
        $users = !$users || !is_array($users) ? array() : $users;
        $this->db->Query("DELETE FROM " . SENDSTUDIO_TABLEPREFIX . "addon_mta_users WHERE mta_group_uid=" . $uid);
        foreach( $users as $k => $v ) {
            $result = $this->db->InsertQuery("addon_mta_users", array( "mta_group_uid" => $this->db->Quote($uid) , "user_uid" => $this->db->Quote((int) ($v)) ));
        }

        return true;
    }

    public function mta_add_data($mta_uid=0, $value=0, $type="sent", $time=false, $extra="") {
        $ct = !$time ? time() : $time;
        if( !is_numeric($value) ) {
            return false;
        }

        $mt = $this->get_date_info($ct, "hour");
        $tmpk = md5($mt . $mta_uid . $type);
        if( !isset( $this->mta_data_temp[$tmpk] ) ) {
            $dc = $this->mta_data_create($mt, $mta_uid, $type);
            if( $dc ) {
                $this->mta_data_temp[$tmpk] = true;
            }

        }

        if( $type == "sent" || $type == "failed" || $type == "bounced" ) {
            $result = $this->db->Query("UPDATE " . SENDSTUDIO_TABLEPREFIX . "addon_mta_stats SET value=value+" . $value . ", extra='" . $this->db->Quote($extra) . "'  WHERE `mta_uid`=" . $this->db->Quote($mta_uid) . " AND `time`='" . $this->db->Quote($mt) . "' AND `type`='" . $this->db->Quote($type) . "' ");
            $result = $this->db->Query("UPDATE " . SENDSTUDIO_TABLEPREFIX . "addon_mta_data SET " . $type . "=" . $type . "+" . $value . " WHERE `uid`=" . $this->db->Quote($mta_uid) . "");
        }
        else {
            if( in_array($type, $this->data_type_reputation) ) {
                $result = $this->db->Query("UPDATE " . SENDSTUDIO_TABLEPREFIX . "addon_mta_stats SET value=" . $value . ", extra='" . $this->db->Quote($extra) . "' WHERE `mta_uid`=" . $this->db->Quote($mta_uid) . " AND `time`='" . $this->db->Quote($mt) . "' AND `type`='" . $this->db->Quote($type) . "' ");
                if( $type == "blacklist" ) {
                    $result = $this->db->Query("SELECT blacklist_extra FROM " . SENDSTUDIO_TABLEPREFIX . "addon_mta_data LIMIT 1");
                    if( !$result ) {
                        $result = $this->db->Query("ALTER TABLE `" . SENDSTUDIO_TABLEPREFIX . "addon_mta_data` ADD `blacklist_data` TEXT NOT NULL");
                    }
                    $result = $this->db->Query("UPDATE " . SENDSTUDIO_TABLEPREFIX . "addon_mta_data SET " . $type . "='" . $value . "',  blacklist_data='" . $this->db->Quote($extra) . "'  WHERE `uid`=" . $this->db->Quote($mta_uid) . "");
                }
                else {
                    $result = $this->db->Query("UPDATE " . SENDSTUDIO_TABLEPREFIX . "addon_mta_data SET " . $type . "='" . $value . "' WHERE `uid`=" . $this->db->Quote($mta_uid) . "");
                }
            }
        }

        return $result;
    }

    public function mta_data_get_hourly($mta_uid=0, $type="sent", $time=false) {
        $time = $this->get_date_info(!$time ? time() : $time, "hour");
        $this->mta_data_create($time, $mta_uid, $type);
        $result = $this->db->Query("SELECT * FROM " . SENDSTUDIO_TABLEPREFIX . "addon_mta_stats WHERE mta_uid='" . $mta_uid . "' AND time='" . $time . "' AND type='" . $type . "'");
        $result = $this->db->Fetch($result);
        return $result ? (int) ($result["value"]) : 0;
    }

    public function mta_data_get_daily($mta_uid=0, $type="sent", $time=false, $arr=false) {
        $time = $this->get_date_info(!$time ? time() : $time, "day");
        $time2 = $time + 3600 * 24;
        $this->mta_data_create($time, $mta_uid, $type);
        if( preg_match("/reputation/i", $type) || $type == "blacklist" ) {
            $result = $this->db->Query("SELECT value as total,extra FROM " . SENDSTUDIO_TABLEPREFIX . "addon_mta_stats WHERE mta_uid='" . $mta_uid . "' AND time >= '" . $time . "' AND time < '" . $time2 . "' AND type='" . $type . "' ORDER BY time DESC LIMIT 1");
        }
        else {
            $result = $this->db->Query("SELECT SUM(value) as total FROM " . SENDSTUDIO_TABLEPREFIX . "addon_mta_stats WHERE mta_uid='" . $mta_uid . "' AND time >= '" . $time . "' AND time < '" . $time2 . "' AND type='" . $type . "'");
        }

        $result = $this->db->Fetch($result);
        return $arr ? $result : $result ? (int) ($result["total"]) : 0;
    }

    public function mta_data_get_blacklist($mta_uid=0, $time=false, $date="daily", $data=false) {
        if( !$data ) {
            $time = $time ? $time : time();
            if( $date = "daily" ) {
                $bl = $this->mta_data_get_daily($mta_uid, "blacklist", $time, true);
            }
            $data = array();
            $blids = explode(",", trim($bl["extra"]));
            if( trim($bl["extra"]) == "" ) {
                return $data;
            }
        }

        $result = $this->db->Query("SELECT * FROM " . SENDSTUDIO_TABLEPREFIX . "addon_mta_ipguard WHERE uid IN (" . implode(",", $blids) . ")");
        while( $row = $this->db->Fetch($result) ) {
            $data[] = $row;
        }

        return $data;
    }

    public function mta_data_get_stats($mta_uid=0, $hm=7, $from="daily", $when="previous", $time=false) {
        $_time = !$time ? time() : $time;
        $data = array( "time" => array() , "sent" => array() , "failed" => array() , "bounced" => array() , "reputation" => array() , "blacklist" => array() );
        $i = 0;
        while( $i < $hm ) {
            $interval = $from == "daily" ? 24 * 60 * 60 * $i : 24 * 60 * 60 * $i;
            $time = $when == "previous" ? $_time - $interval : $_time + $interval;
            $data["time"][] = date("M j", $time);
            $data["sent"][] = (int) ($from == "daily" ? $this->mta_data_get_daily($mta_uid, "sent", $time) : $this->mta_data_get_hourly($mta_uid, "sent", $time));
            $data["failed"][] = (int) ($from == "daily" ? $this->mta_data_get_daily($mta_uid, "failed", $time) : $this->mta_data_get_hourly($mta_uid, "failed", $time));
            $data["bounced"][] = (int) ($from == "daily" ? $this->mta_data_get_daily($mta_uid, "bounced", $time) : $this->mta_data_get_hourly($mta_uid, "bounced", $time));
            $data["reputation"][] = (int) ($from == "daily" ? $this->mta_data_get_daily($mta_uid, "reputation", $time) : $this->mta_data_get_hourly($mta_uid, "reputation", $time));
            $complaint = (int) ($from == "daily" ? $this->mta_data_get_daily($mta_uid, "reputation_complaint", $time) : $this->mta_data_get_hourly($mta_uid, "reputation_complaint", $time));
            $complaint_reversed = 0 < $complaint ? 100 - $complaint : $complaint;
            $data["reputation_complaint"][] = $complaint;
            $volume = (int) ($from == "daily" ? $this->mta_data_get_daily($mta_uid, "reputation_volume", $time) : $this->mta_data_get_hourly($mta_uid, "reputation_volume", $time));
            $volume_reversed = 0 < $volume ? 100 - $volume : $volume;
            $data["reputation_volume"][] = $volume;
            $unknown = (int) ($from == "daily" ? $this->mta_data_get_daily($mta_uid, "reputation_unknown", $time) : $this->mta_data_get_hourly($mta_uid, "reputation_unknown", $time));
            $data["reputation_unknown"][] = $unknown;
            $data["reputation_filtered"][] = (int) ($from == "daily" ? $this->mta_data_get_daily($mta_uid, "reputation_filtered", $time) : $this->mta_data_get_hourly($mta_uid, "reputation_filtered", $time));
            $data["blacklist"][] = (int) ($from == "daily" ? $this->mta_data_get_daily($mta_uid, "blacklist", $time) : $this->mta_data_get_hourly($mta_uid, "blacklist", $time));
            $data["whitelist"][] = (int) ($from == "daily" ? $this->mta_data_get_daily($mta_uid, "whitelist", $time) : $this->mta_data_get_hourly($mta_uid, "whitelist", $time));
            ++$i;
        }

        $data["time"] = array_reverse($data["time"]);
        $data["sent"] = array_reverse($data["sent"]);
        $data["failed"] = array_reverse($data["failed"]);
        $data["bounced"] = array_reverse($data["bounced"]);
        $data["reputation"] = array_reverse($data["reputation"]);
        $data["reputation_complaint"] = array_reverse($data["reputation_complaint"]);
        $data["reputation_volume"] = array_reverse($data["reputation_volume"]);
        $data["reputation_unknown"] = array_reverse($data["reputation_unknown"]);
        $data["reputation_filtered"] = array_reverse($data["reputation_filtered"]);
        $data["blacklist"] = array_reverse($data["blacklist"]);
        $data["whitelist"] = array_reverse($data["whitelist"]);
        
        return $data;
    }

    public function mta_data_create($time=0, $mta_uid=0, $type="send") {
        if( !$this->mta_data_isset($time, $mta_uid, $type) ) {
            $result = $this->db->InsertQuery("addon_mta_stats", array( "mta_uid" => $this->db->Quote($mta_uid) , "time" => $this->db->Quote($time) , "type" => $this->db->Quote($type) ));
            return true;
        }

        return false;
    }

    public function mta_data_isset($time=0, $mta_uid=0, $type="send") {
        $result = $this->db->Query("SELECT * FROM " . SENDSTUDIO_TABLEPREFIX . "addon_mta_stats WHERE mta_uid='" . $mta_uid . "' AND time='" . $time . "' AND type='" . $type . "'");
        $ex = $this->db->Fetch($result) ? true : false;
        return $ex;
    }

    public function get_date_interval($timestam=0, $g="day", $hm=40, $t="-") {
        // nothing? why?
    }

    public function get_date_info($timestamp=0, $g="day") {
        $timestamp = $timestamp ? $timestamp : time();
        $ta = explode("-", date("Y-n-d-H-i-s", $timestamp));
        $t = 0;
        if( $g == "day" ) {
            $t = mktime(0, 0, 0, $ta[1], $ta[2], $ta[0]);
        }
        else {
            if( $g == "hour" ) {
                $t = mktime($ta[3], 0, 0, $ta[1], $ta[2], $ta[0]);
            }
            else {
                if( $g == "month" ) {
                    $t = mktime(0, 0, 0, $ta[1], 0, $ta[0]);
                }
            }
        }

        return $t;
    }

    public function group_add($data=array(  )) {
        $name = empty( $data["mta_group_name"] ) ? time() : $data["mta_group_name"];
        $method = is_numeric($data["mta_group_rotation"]) ? $data["mta_group_rotation"] : 1;
        $result = $this->db->InsertQuery("addon_mta_group", array( "name" => $this->db->Quote($name) , "rotation" => $method ));
        
        return $result;
    }

    public function group_update($data=array(  )) {
        $name = empty( $data["mta_group_name"] ) ? time() : $data["mta_group_name"];
        $method = is_numeric($data["mta_group_rotation"]) ? $data["mta_group_rotation"] : 1;
        $result = $this->db->UpdateQuery("addon_mta_group", array( "name" => $this->db->Quote($name) , "rotation" => $method ), "`uid`=" . $data["mta_group_uid"]);
        
        return $result;
    }

    public function group_delete($id=0) {
        $mtas = $this->group_mtas($id, true);
        foreach( $mtas as $k => $value ) {
            $this->db->DeleteQuery("addon_mta_data", "WHERE `uid`=" . $value["uid"]);
            $this->db->DeleteQuery("addon_mta_stats", "WHERE `mta_uid`=" . $value["uid"]);
        }

        return $this->db->DeleteQuery("addon_mta_group", "WHERE `uid`=" . $id, 1);
    }

    public function rotation_name($r=1) {
        $ro = array( 1 => "Random" , 2 => "Cycle" );
        
        return $ro[$r];
    }

    public function group_info($id=false) {
        $id = $id ? "WHERE uid='" . $id . "'" : "";
        $data = array();
        $query = "SELECT * FROM " . SENDSTUDIO_TABLEPREFIX . "addon_mta_group " . $id;
        $result = $this->db->Query($query);
        while( $row = $this->db->Fetch($result) ) {
            $row["rotation_raw"] = $row["rotation"];
            $row["rotation"] = $this->rotation_name($row["rotation"]);
            $data[] = array_merge($row, $this->group_info_single($row["uid"]));
        }
        if( !$id ) {
            $data[] = $this->nongrouped_info();
        }

        return $data;
    }

    public function group_info_no_empty($id=false, $mtas=false, $blacklistdata=false, $user=false) {
        $user =& GetUser();
        $is_admin = $user->isAdmin();
        if( $is_admin ) {
            $id = $id ? "WHERE uid='" . $id . "'" : "";
            $query = "SELECT * FROM " . SENDSTUDIO_TABLEPREFIX . "addon_mta_group " . $id;
        }
        else {
            $id = $id ? "WHERE uid='" . $id . "'" : "";
            $query = "SELECT * FROM " . SENDSTUDIO_TABLEPREFIX . "addon_mta_group a LEFT JOIN " . SENDSTUDIO_TABLEPREFIX . "addon_mta_users b ON a.uid=b.mta_group_uid WHERE b.user_uid=" . $user->userid;
        }
        $data = array();
        $result = $this->db->Query($query);
        while( $row = $this->db->Fetch($result) ) {
            $row["rotation"] = $this->rotation_name($row["rotation"]);
            if( $mtas ) {
                $row["mtas_data"] = $this->group_mtas($row["uid"], false, true, false, false, $blacklistdata);
            }
            $data[] = array_merge($row, $this->group_info_single($row["uid"]));
        }

        return $data;
    }

    public function nongrouped_info() {
        $data = array();
        $data["uid"] = 0;
        $data["name"] = GetLang("Addon_mta_nongrouped");
        $data["rotation"] = "N/A";
        
        return array_merge($data, $this->group_info_single(0));
    }

    public function group_info_single($id=0) {
        $data = array();
        $data["mtas"] = $this->group_info_mtas($id);
        $data["users"] = $this->group_info_users($id);
        $data = array_merge($data, $this->group_info_mails($id));
        
        return $data;
    }

    public function group_info_mtas($id=0) {
        $query = "SELECT COUNT(*) as total FROM " . SENDSTUDIO_TABLEPREFIX . "addon_mta_data WHERE mta_group='" . $id . "'";
        $result = $this->db->Query($query);
        if( $result ) {
            $row = $this->db->Fetch($result);
            return (int) $row["total"];
        }

        return 0;
    }

    public function group_info_users($id=0) {
        $query = "SELECT COUNT(*) as total FROM " . SENDSTUDIO_TABLEPREFIX . "addon_mta_users WHERE mta_group_uid='" . $id . "'";
        $result = $this->db->Query($query);
        if( $result ) {
            $row = $this->db->Fetch($result);
            return (int) $row["total"];
        }

        return 0;
    }

    public function group_info_mails($id=0) {
        $query = "SELECT SUM(sent) as sent,SUM(failed) as failed, SUM(bounced) as bounced FROM " . SENDSTUDIO_TABLEPREFIX . "addon_mta_data WHERE mta_group='" . $id . "'";
        $result = $this->db->Query($query);
        if( $result ) {
            $row = $this->db->Fetch($result);
            $row["sent"] = (int) ($row["sent"]);
            $row["failed"] = (int) ($row["failed"]);
            $row["bounced"] = (int) ($row["bounced"]);
            return $row;
        }

        return 0;
    }

    public function group_details($id, $partial=false) {
        if( $id ) {
            $query = "SELECT * FROM " . SENDSTUDIO_TABLEPREFIX . "addon_mta_group WHERE uid='" . $id . "'";
            $result = $this->db->Query($query);
            if( $result ) {
                $row = $this->db->Fetch($result);
                return array( "exist" => true , "data" => array( "mta_group_uid" => $id , "mta_group_name" => $row["name"] , "mta_group_rotation" => $row["rotation"] , "users" => $this->group_users($id) ) );
            }
            return $this->group_details_empty();
        }

        return $this->group_details_empty();
    }

    public function group_users($id=0) {
        $id = (int) ($id);
        $users = array();
        $query = "SELECT * FROM " . SENDSTUDIO_TABLEPREFIX . "addon_mta_users WHERE mta_group_uid='" . $id . "'";
        $result = $this->db->Query($query);
        if( $result ) {
            while( $row = $this->db->Fetch($result) ) {
                $users[] = (int) ($row["user_uid"]);
            }
        }

        return $users;
    }

    public function mta_details($group, $id, $partial=false) {
        if( $id ) {
            $query = "SELECT * FROM " . SENDSTUDIO_TABLEPREFIX . "addon_mta_data WHERE mta_group='" . $this->db->Quote($group) . "' AND uid='" . $this->db->Quote($id) . "'";
            $result = $this->db->Query($query);
            if( $result ) {
                $row = $this->db->Fetch($result);
                return array( "exist" => true , "data" => $row );
            }
            return $this->mta_details_empty();
        }

        return $this->mta_details_empty();
    }

    public function mta_details_by_uid($uid=0) {
        if( $uid ) {
            $query = "SELECT * FROM " . SENDSTUDIO_TABLEPREFIX . "addon_mta_data WHERE uid='" . $this->db->Quote($uid) . "'";
            $result = $this->db->Query($query);
            if( $result ) {
                $row = $this->db->Fetch($result);
                return array( "exist" => true , "data" => $row );
            } else {
                return $this->mta_details_empty();
            }
        } else {
            return $this->mta_details_empty();
        }
    }

    public function group_mtas($id=0, $lite=false, $active=false, $random=false, $limit=false, $blacklistdata=false) {
        $active = $active ? " AND status=1" : "";
        $order = $random ? " ORDER BY RAND()" : "";
        $limit = $limit && is_numeric($limit) ? " LIMIT " . $limit : "";
        if( !$lite ) {
            $mtas = array();
            $query = "SELECT * FROM " . SENDSTUDIO_TABLEPREFIX . "addon_mta_data WHERE mta_group='" . $id . "' " . $active . " " . $order . " " . $limit;
            $result = $this->db->Query($query);
            while( $row = $this->db->Fetch($result) ) {
                $row["sent"] = number_format($row["sent"]);
                $row["failed"] = number_format($row["failed"]);
                $row["bounced"] = number_format($row["bounced"]);
                $row["reputation"] = number_format($row["reputation"]);
                $row["blacklist"] = number_format($row["blacklist"]);
                if( $blacklistdata ) {
                    $row["blacklist_data"] = $this->mta_data_get_blacklist($row["uid"], time(), explode(",", $row["blacklist_data"]));
                }
                $mtas[] = $row;
            }

        }

        return $mtas;
    }

    public function mta_data_total($mta_uid, $type) {
        if( $type == "reputation" || $type == "blacklist" ) {
            $sent = $this->db->Fetch($this->db->Query("SELECT value as total FROM " . SENDSTUDIO_TABLEPREFIX . "addon_mta_stats WHERE mta_uid='" . $mta_uid . "' AND type='" . $type . "' ORDER BY time DESC LIMIT 1"));
        }
        else {
            $sent = $this->db->Fetch($this->db->Query("SELECT SUM(value) as total FROM " . SENDSTUDIO_TABLEPREFIX . "addon_mta_stats WHERE mta_uid='" . $mta_uid . "' AND type='" . $type . "'"));
        }

        return (int) ($sent["total"]);
    }

    public function mta_data_update($mta_uid, $value, $key) {
        $result = $this->db->UpdateQuery("addon_mta_data", array( $key => $this->db->Quote($value) ), "`uid`=" . $mta_uid);
        
        return $value;
    }

    public function mta_data_group_total($group_id=0, $type="sent") {
        $total = 0;
        if( $type == "reputation" ) {
            $query = "SELECT * FROM " . SENDSTUDIO_TABLEPREFIX . "addon_mta_data WHERE mta_group='" . $group_id . "'";
            $result = $this->db->Query($query);
            while( $row = $this->db->Fetch($result) ) {
                $total = $total + (int) ($this->mta_data_total($row["uid"], $type));
            }
        }

        $query = "SELECT * FROM " . SENDSTUDIO_TABLEPREFIX . "addon_mta_data WHERE mta_group='" . $group_id . "'";
        $result = $this->db->Query($query);
        while( $row = $this->db->Fetch($result) ) {
            $total = $total + (int) ($this->mta_data_total($row["uid"], $type));
        }

        return $total;
    }

    public function mta_details_empty() {
        return array( "exist" => false , "data" => array( "name" => time() ) );
    }

    public function group_details_empty() {
        return array( "exist" => false , "data" => array( "mta_group_name" => time() , "mta_group_rotation" => 1 ) );
    }

    public function get_mta_name_by_job($job=0) {
        $job = $this->db->Quote($job);
        $query = "SELECT * FROM " . SENDSTUDIO_TABLEPREFIX . "jobs WHERE jobid='" . $job . "'";
        $result = $this->db->Query($query);
        $r = array();
        $mta = 0;
        $row = $this->db->Fetch($result);
        if( !$row ) {
            return "None";
        }

        $mta = $this->get_mta_by_user($row["ownerid"]);
        if( $mta == 0 ) {
            $md = unserialize($row["jobdetails"]);
            return $this->get_mta_name($md["mta"], "J");
        }

        return $this->get_mta_name($mta, "U");
    }

    public function get_mta_name_by_stat($stat=0) {
        $stat = $this->db->Quote($stat);
        $query = "SELECT * FROM " . SENDSTUDIO_TABLEPREFIX . "stats_newsletters WHERE statid='" . $stat . "'";
        $result = $this->db->Query($query);
        $r = array();
        $mta = 0;
        $row = $this->db->Fetch($result);
        if( !$row ) {
            return "None";
        }

        return $this->get_mta_name_by_job($row["jobid"]);
    }

    public function get_mta_by_user($user) {
        $query = "SELECT * FROM " . SENDSTUDIO_TABLEPREFIX . "users WHERE userid='" . $user . "'";
        $result = $this->db->Query($query);
        $mta = 0;
        while( $row = $this->db->Fetch($result) ) {
            $mta = (int) $row["mta"];
        }

        return $mta;
    }

    public function get_mta_name($mta=0, $default="None", $type="J") {
        $query = "SELECT * FROM " . SENDSTUDIO_TABLEPREFIX . "smtp WHERE uid='" . $mta . "'";
        $result = $this->db->Query($query);
        $mta = $default;
        while( $row = $this->db->Fetch($result) ) {
            $mta = "<img src='images/" . ($type == "J" ? "mnu_contactlist_button" : "user") . ".gif'> " . $row["name"];
        }

        return $mta;
    }

    public function mta_add($data=array(  )) {
        $mta_data = array( "hostname" => $this->db->Quote(trim($data["hostname"])) , "username" => $this->db->Quote(trim($data["username"])) , "password" => $this->db->Quote(trim($data["password"])) , "port" => $this->db->Quote((int) (trim($data["port"]))) , "name" => $this->db->Quote(trim($data["name"])) , "mail_from" => $this->db->Quote(trim($data["mail_from"])) , "mail_reply" => $this->db->Quote(trim($data["mail_reply"])) , "mail_bounce" => $this->db->Quote(trim($data["mail_bounce"])) , "mail_test" => $this->db->Quote(trim($data["mail_test"])) , "mta_group" => $this->db->Quote((int) ($data["mta_group_uid"])) );
        $result = $this->db->InsertQuery("addon_mta_data", $mta_data);
        
        return $result;
    }

    public function mta_delete($id=0) {
        $result = $this->db->DeleteQuery("addon_mta_data", "WHERE `uid`=" . $id);
        $this->db->DeleteQuery("addon_mta_stats", "WHERE `mta_uid`=" . $id);
        
        return $result;
    }

    public function mta_update($data=array(  )) {
        $result = $this->db->UpdateQuery("addon_mta_data", array( "hostname" => $this->db->Quote($data["hostname"]) , "username" => $this->db->Quote($data["username"]) , "password" => $this->db->Quote($data["password"]) , "port" => $this->db->Quote((int) ($data["port"])) , "name" => $this->db->Quote($data["name"]) , "mail_from" => $this->db->Quote($data["mail_from"]) , "mail_reply" => $this->db->Quote($data["mail_reply"]) , "mail_bounce" => $this->db->Quote($data["mail_bounce"]) , "mail_test" => $this->db->Quote($data["mail_test"]) ), "`uid`=" . $data["uid"]);
        
        return $result;
    }

    public function mta_modify($data=array(  )) {
        $valid = array( "hostname" , "username" , "password" , "port" , "name" , "mail_from" , "mail_reply" , "mail_bounce" , "mail_test" );
        $fields = array();
        foreach( $data as $k => $v ) {
            if( in_array($k, $valid) ) {
                $fields[$k] = $this->db->Quote($v);
            }
        }
        $result = $this->db->UpdateQuery("addon_mta_data", $fields, "`uid`=" . (int) ($data["uid"]));
        
        return $result;
    }

    public function mta_test($data=array(), $mta=false) {
        $user =& GetUser();
        $user_email = $user->Get("emailaddress");
        $sf = new SendStudio_Functions();
        $email_test = empty( $data["mail_test"] ) ? MTA_DEFAULT_TEST_MAIL : $data["mail_test"];
        $subject = GetLang("TestSendingSubject");
        $text = GetLang("TestSendingEmail");
        $email_api = $sf->GetApi("Email");
        $smtp = false;
        if( !empty( $data["hostname"] ) ) {
            $email_api->Set("SMTPServer", urldecode($data["hostname"]));
            $smtp = true;
        }

        if( !empty( $data["username"] ) ) {
            $email_api->Set("SMTPUsername", urldecode($data["username"]));
        }

        if( !empty( $data["password"] ) ) {
            $email_api->Set("SMTPPassword", urldecode($data["password"]));
        }

        if( !empty( $data["port"] ) ) {
            $email_api->Set("SMTPPort", urldecode($data["port"]));
        }

        $email_api->Set("Subject", $subject);
        $email_api->Set("CharSet", SENDSTUDIO_CHARSET);
        $email_api->Set("FromAddress", !empty( $data["mail_from"] ) ? $data["mail_from"] : $user_email);
        $email_api->Set("ReplyTo", !empty( $data["mail_reply"] ) ? $data["mail_reply"] : $user_email);
        $email_api->Set("BounceAddress", !empty( $data["mail_bounce"] ) ? $data["mail_bounce"] : $user_email);
        $email_api->Set("FromName", $user->Get("fullname"));
        $email_api->AddBody("text", $text);
        $email_api->AddRecipient($email_test, "", "t");
        $send_result = $email_api->Send();
        if( $mta ) {
            $this->mta_add_data($mta, 1, isset( $send_result["success"] ) && 0 < $send_result["success"] ? "sent" : "failed", time());
        }

        $result = array();
        $result["success"] = $send_result["success"];
        $result["mail_test"] = $email_test;
        if( isset( $send_result["success"] ) && 0 < $send_result["success"] ) {
            $result["msg"] = vsprintf(GetLang("TestEmailSent"), $email_test);
        }
        else {
            if( $smtp ) {
                $failure = array_shift($send_result["fail"]);
                $result["msg"] = sprintf(GetLang("TestEmailNotSent"), $email_test, htmlspecialchars($failure[1], ENT_QUOTES, SENDSTUDIO_CHARSET));
            }
            else {
                $result["msg"] = sprintf(GetLang("TestEmailNotSent"), $email_test, GetLang("ProblemWithLocalMailServer"));
            }
        }

        return $result;
    }

    public function nslookup($ip) {
        $this->log($ip);
        exec("nslookup " . $ip, $op);
        if( is_array($op) && 5 < count($op) ) {
            $a = str_replace("\"", "", $op["5"]);
            $b = explode(" ", $a);
            $c = $b[1];
            $d = explode(".", $c);
            return (int) ($d[0]) == 127 ? (int) ($d[3]) : false;
        }

        return false;
    }

    public function get_multirbl() {
        require_once (dirname(__FILE__) . "/simple_html_dom.php");
        $html = file_get_html("http://multirbl.valli.org/lookup/184.154.76.66.html");
        $data = array( "blacklist" => array() , "combined" => array() , "whitelist" => array() , "informational" => array() );
        foreach( $html->find("table[id=dnsbl_data]") as $a ) {
            foreach( $a->find("tr") as $b ) {
                $trid = $b->id;
                if( preg_match("/DNSBLBlacklistTest/i", $trid) ) {
                    $data["blacklist"][] = array( "name" => $b->find("td", 2)->plaintext , "url" => $b->find("td", 2)->find("a", 0)->href , "dns" => $b->find("td", 3)->plaintext );
                }
                else {
                    if( preg_match("/DNSBLCombined/i", $trid) ) {
                        $data["combined"][] = array( "name" => $b->find("td", 2)->plaintext , "url" => $b->find("td", 2)->find("a", 0)->href , "dns" => $b->find("td", 3)->plaintext );
                    }
                    else {
                        if( preg_match("/DNSBLWhitelist/i", $trid) ) {
                            $data["whitelist"][] = array( "name" => $b->find("td", 2)->plaintext , "url" => $b->find("td", 2)->find("a", 0)->href , "dns" => $b->find("td", 3)->plaintext );
                        }
                        else {
                            if( preg_match("/DNSBLInformational/i", $trid) ) {
                                $data["informational"][] = array( "name" => $b->find("td", 2)->plaintext , "url" => $b->find("td", 2)->find("a", 0)->href , "dns" => $b->find("td", 3)->plaintext );
                            }
                        }
                    }
                }
            }
        }

        $data["reputation"] = array( array( "name" => "SenderScore score" , "url" => "https://www.senderscore.org/faq/" , "dns" => "score.senderscore.com" ) , array( "name" => "SenderScore complaint" , "url" => "https://www.senderscore.org/faq/" , "dns" => "cmplt.rating.senderscore.com" ) , array( "name" => "SenderScore volume" , "url" => "https://www.senderscore.org/faq/" , "dns" => "vol.rating.senderscore.com" ) , array( "name" => "SenderScore unknown" , "url" => "https://www.senderscore.org/faq/" , "dns" => "uus.rating.senderscore.com" ) , array( "name" => "SenderScore filtered" , "url" => "https://www.senderscore.org/faq/" , "dns" => "filtered.rating.senderscore.com" ) );
        
        return $data;
    }

    public function log($data) {
        if( IEM_CLI_MODE && ADDON_MTA_DEBUG == true ) {
            echo PHP_EOL . print_r($data, true);
        }
    }

    public function populate_ipguard() {
        $this->log("Downloading Data...");
        $data = $this->get_multirbl();
        foreach( $data as $k => $v ) {
            foreach( $v as $_k => $_v ) {
                if( !$this->isset_rbl($_v["dns"], $k) && !empty( $_v["dns"] ) ) {
                    $rbl = array( "name" => $this->db->Quote($_v["name"]) , "url" => $this->db->Quote($_v["url"]) , "dns" => $this->db->Quote($_v["dns"]) , "type" => $this->db->Quote($k) );
                    $result = $this->db->InsertQuery("addon_mta_ipguard", $rbl);
                    if( $result ) {
                        $this->log("Added new entry: " . print_r($rbl, true));
                    }
                }
                else {
                    $this->log("Already Added [" . $k . "]: " . print_r($_v, true));
                    usleep(50000);
                }
            }
        }
    }

    public function isset_rbl($dns, $type) {
        $query = "SELECT * FROM " . SENDSTUDIO_TABLEPREFIX . "addon_mta_ipguard WHERE `dns`='" . $this->db->Quote(trim($dns)) . "' AND `type`='" . $this->db->Quote(trim($type)) . "'";
        $result = $this->db->Query($query);
        return $this->db->Fetch($result) ? true : false;
    }

    public function get_rbls($type=false) {
        $type = $type ? "WHERE `type`='" . $this->db->Quote(trim($type)) . "'" : "";
        $query = "SELECT * FROM " . SENDSTUDIO_TABLEPREFIX . "addon_mta_ipguard " . $type;
        $result = $this->db->Query($query);
        $rbls = array();
        while( $row = $this->db->Fetch($result) ) {
            $rbls[] = $row;
        }

        return $rbls;
    }

    public function query_rbl($ip, $rbl) {
        $rip = explode(".", $ip);
        $reverse_ip = $rip[3] . "." . $rip[2] . "." . $rip[1] . "." . $rip[0];
        return $this->nslookup($reverse_ip . "." . $rbl);
    }

    public function check_ipguard($mta=array(  ), $type="reputation", $time=false) {
        $time = !$time ? time() : $time;
        $type = !$type ? "reputation" : $type;
        $rbls = $this->get_rbls($type);
        $result = array();
        $ip = gethostbyname($mta["hostname"]);
        if( filter_var($ip, FILTER_VALIDATE_IP) ) {
            $bl = array();
            $this->log("\tChecking " . $type . " for " . $ip . ":");
            foreach( $rbls as $k => $v ) {
                $result = $this->query_rbl($ip, $v["dns"]);
                $this->log("\t\t" . $v["dns"] . " : " . $result);
                if( $type == "reputation" && $v["dns"] == "score.senderscore.com" ) {
                    $this->mta_add_data($mta["uid"], (int) ($result), "reputation", $time);
                }
                if( $type == "reputation" && $v["dns"] == "cmplt.rating.senderscore.com" ) {
                    $this->mta_add_data($mta["uid"], (int) ($result), "reputation_complaint", $time);
                }
                if( $type == "reputation" && $v["dns"] == "vol.rating.senderscore.com" ) {
                    $this->mta_add_data($mta["uid"], (int) ($result), "reputation_volume", $time);
                }
                if( $type == "reputation" && $v["dns"] == "uus.rating.senderscore.com" ) {
                    $this->mta_add_data($mta["uid"], (int) ($result), "reputation_unknown", $time);
                }
                if( $type == "reputation" && $v["dns"] == "filtered.rating.senderscore.com" ) {
                    $this->mta_add_data($mta["uid"], (int) ($result), "reputation_filtered", $time);
                }
                if( $type == "blacklist" && 0 < (int) ($result) ) {
                    $bl[] = $v["uid"];
                }
            }
            if( $type == "blacklist" ) {
                $this->mta_add_data($mta["uid"], count($bl), "blacklist", $time, implode(",", $bl));
            }

        }
        else {
            $this->log("Invalid IP: " . $ip);
            $result["result"] = false;
        }

        return $result;
    }

    public function get_users_groups() {
        $query = "SELECT * FROM " . SENDSTUDIO_TABLEPREFIX . "usergroups";
        $result = $this->db->Query($query);
        $groups = array();
        while( $row = $this->db->Fetch($result) ) {
            $row["users"] = $this->get_users($row["groupid"]);
            $groups[] = $row;
        }

        return $groups;
    }

    public function get_users($group=0) {
        $query = "SELECT * FROM " . SENDSTUDIO_TABLEPREFIX . "users WHERE groupid='" . $group . "'";
        $result = $this->db->Query($query);
        $users = array();
        while( $row = $this->db->Fetch($result) ) {
            $users[] = $row;
        }

        return $users;
    }

    public function iem_show_mtas_in_email_campaign() {
        error_log ("im here2");

        $mtas = array();
        $mtas["groups"] = $this->group_info_no_empty(false, true, false, false);
        $this->template_system->Assign("mtas", $mtas);
        $GLOBALS["MTA_SEND_SELECT_MTA"] = $this->template_system->ParseTemplate("iem_mta_send_select_mta", true);
    }

    public function iem_email_campaign_save_mta($send_details, $data=array()) {
        if( isset( $data["mta"] ) && is_array($data["mta"]) ) {
            $send_mta = array( "mtas_uid" => array() );
            $mta_raw = array();
            foreach( $data["mta"] as $key => $value ) {
                $_mta = explode("_", $value);
                if( count($_mta) != 2 || $_mta[0] != "s" ) {
                    continue;
                }
                $_m = $this->mta_details_by_uid($_mta[1]);
                if( $_m["exist"] ) {
                    $group_id = $_m["data"]["mta_group"];
                    if( !isset( $mta_raw[$group_id] ) ) {
                        $group_info = $this->group_info($group_id);
                        $mta_raw[$group_id] = array( "group" => $group_info[0] , "mtas" => array() );
                    }
                    $mta_raw[$group_id]["mtas"][] = $_m["data"]["uid"];
                    $send_mta["mtas_uid"][] = $_m["data"]["uid"];
                    continue;
                }
            }

            error_log ("im here");
            error_log (var_export($mta_raw, TRUE));

            $send_mta["data"] = $mta_raw;
            $send_mta["mail"] = array();
            $send_mta["mail"]["from"] = isset( $data["mta_mail_from"] ) ? true : false;
            $send_mta["mail"]["reply"] = isset( $data["mta_mail_reply"] ) ? true : false;
            $send_mta["mail"]["bounce"] = isset( $data["mta_mail_bounce"] ) ? true : false;
            $send_details["mta"] = $send_mta;
            if( 0 < count($send_mta["data"]) ) {
                $this->template_system->Assign("mta", $send_mta);
                $this->template_system->Assign("mf", $send_mta["mail"]["from"]);
                $this->template_system->Assign("mr", $send_mta["mail"]["reply"]);
                $this->template_system->Assign("mb", $send_mta["mail"]["bounce"]);
                $GLOBALS["MTA_SEND_SELECT_MTA_CONFIRM"] = $this->template_system->ParseTemplate("iem_mta_send_select_mta_confirm", true);
            }
            return $send_mta;
        }
    }

    public function iem_switch_smtp($_this, $disconnect) {
        if( isset( $_this->jobdetails["mta"] ) ) {
            $mta = $_this->jobdetails["mta"];
            if( 0 < count($mta["mtas_uid"]) ) {
                if( 1 < count($mta["data"]) ) {
                    $rotation = MTA_ROTATION_RANDOM;
                }
                else {
                    $guid = 0;
                    foreach( $mta["data"] as $k => $v ) {
                        $guid = $k;
                    }
                    $rotation = $this->db->Fetch($this->db->Query("SELECT rotation FROM " . SENDSTUDIO_TABLEPREFIX . "addon_mta_group WHERE uid='" . $guid . "' LIMIT 1"));
                    $rotation = (int) ($rotation["rotation"]);
                }

                if( $rotation == MTA_ROTATION_RANDOM ) {
                    $mtas_uid = implode(",", $mta["mtas_uid"]);
                    $query = "SELECT * FROM " . SENDSTUDIO_TABLEPREFIX . "addon_mta_data WHERE uid IN(" . $mtas_uid . ") ORDER BY RAND() LIMIT 1";
                    $switched_mta = $this->db->Fetch($this->db->Query($query));
                }
                else {
                    if( $rotation == MTA_ROTATION_CYCLE ) {
                        $mtas_uid = $mta["mtas_uid"];
                        if( 1 < count($mtas_uid) ) {
                            $statid = (int) ($_this->statid);
                            $cycle = $this->db->Fetch($this->db->Query("SELECT pointer FROM " . SENDSTUDIO_TABLEPREFIX . "addon_mta_cycle WHERE statid='" . $statid . "' LIMIT 1"));
                            if( !$cycle ) {
                                $pointer = 0;
                                $this->db->InsertQuery("addon_mta_cycle", array( "statid" => $this->db->Quote($statid) , "pointer" => $pointer ), "`uid`=" . $statid);
                            }
                            else {
                                $pointer = (int) ($cycle["pointer"]);
                            }

                            $pointernow = $pointer + 1;
                            if( isset( $mtas_uid[$pointernow] ) ) {
                                $pointer = $pointernow;
                            }
                            else {
                                $pointer = 0;
                            }

                            $selected_mta = $mtas_uid[$pointer];
                            $this->db->UpdateQuery("addon_mta_cycle", array( "pointer" => $this->db->Quote($pointer) ), "`statid`=" . $statid);
                        }
                        else {
                            $selected_mta = $mtas_uid[0];
                        }

                        $query = "SELECT * FROM " . SENDSTUDIO_TABLEPREFIX . "addon_mta_data WHERE uid IN(" . $selected_mta . ") LIMIT 1";
                        $switched_mta = $this->db->Fetch($this->db->Query($query));
                    }

                }

                if( $switched_mta ) {
                    $_this->jobdetails["mta_data"] = $switched_mta;
                    $_this->Email_API->SetSmtp(trim($switched_mta["hostname"]), trim($switched_mta["username"]), trim($switched_mta["password"]), trim($switched_mta["port"]));
                    if( $mta["mail"]["from"] && !empty( $switched_mta["mail_from"] ) ) {
                        $_this->Email_API->Set("FromAddress", trim($switched_mta["mail_from"]));
                        $GLOBALS["addon_mta_umf"] = true;
                    }
                    else {
                        $GLOBALS["addon_mta_umf"] = false;
                    }
                    if( $mta["mail"]["reply"] && !empty( $switched_mta["mail_reply"] ) ) {
                        $_this->Email_API->Set("ReplyTo", trim($switched_mta["mail_reply"]));
                        $GLOBALS["addon_mta_umr"] = true;
                    }
                    else {
                        $GLOBALS["addon_mta_umr"] = false;
                    }
                    if( $mta["mail"]["bounce"] && !empty( $switched_mta["mail_bounce"] ) ) {
                        $_this->Email_API->Set("BounceAddress", trim($switched_mta["mail_bounce"]));
                        $GLOBALS["addon_mta_umb"] = true;
                    }
                    else {
                        $GLOBALS["addon_mta_umb"] = false;
                    }

                    $_this->Email_API->_AssembledEmail["Headers"]["m"] = NULL;
                    $_this->Email_API->_AssembledEmail["Headers"]["t"] = NULL;
                    $_this->Email_API->_AssembledEmail["Headers"]["h"] = NULL;
                    $_this->Email_API->_AssembledEmail["Body"]["t"] = NULL;
                    $_this->Email_API->_AssembledEmail["Body"]["h"] = NULL;
                    $this->log(array( "Recipients" => $_this->Email_API->_Recipients , "From" => $_this->Email_API->FromAddress , "ReplyTo" => $_this->Email_API->ReplyTo , "BounceAddress" => $_this->Email_API->BounceAddress , "mta" => $switched_mta ));
                    if( isset( $GLOBALS["cmta"] ) && $GLOBALS["cmta"] == $switched_mta["hostname"] ) {
                        // empty
                    } else {
                        $_this->Email_API->_Close_Smtp_Connection();
                    }
                    $GLOBALS["cmta"] = $switched_mta["hostname"];
                }
            }
        }
    }

    public function iem_log_send_pre($_this, $mail_results) {
        error_log ("im here3");
        if( isset( $_this->jobdetails["mta"] ) ) {
            $mta_uid = $_this->jobdetails["mta_data"]["uid"];
            if( !isset( $_this->mta_used_to_sent) ) {
                $_this->mta_used_to_sent = array();
            }
            if( !isset( $_this->mta_used_to_sent[$mta_uid] ) ) {
                $_this->mta_used_to_sent[$mta_uid] = array( "sent" => 0 , "failed" => 0 );
            }
            if( 0 < $mail_results["success"] ) {
                ++$_this->mta_used_to_sent[$mta_uid]["sent"];
                return NULL;
            }
            ++$_this->mta_used_to_sent[$mta_uid]["failed"];
        }

    }

    public function iem_log_send($_this, $mail_result) {
        error_log ("im here4");
        if( isset( $_this->jobdetails["mta"] ) ) {
            foreach( $_this->mta_used_to_sent as $k => $v ) {
                if( 0 < $v["sent"] ) {
                    $this->mta_add_data($k, $v["sent"], "sent");
                }
                if( 0 < $v["failed"] ) {
                    $this->mta_add_data($k, $v["failed"], "failed");
                }
                $_this->mta_used_to_sent[$k] = array( "sent" => 0 , "failed" => 0 );
            }
        }
    }

    public function iem_mta_schedule_details($details) {
        error_log (var_export($details, TRUE));

        $job_details = unserialize($details["jobdetails"]);
        $real_send_size = $this->real_job_size($details["jobid"]);
        $job_details["SendSize"] = isset( $real_send_size["sendsize"] ) ? $real_send_size["sendsize"] : $job_details["SendSize"];
        $this->template_system->Assign("job_details", $job_details);
        $GLOBALS["MTA_SCHEDULE_INFO_TITLE"] = $this->template_system->ParseTemplate("iem_mta_schedule_info_title", true);
        $GLOBALS["MTA_SCHEDULE_INFO_CONTENT"] = $this->template_system->ParseTemplate("iem_mta_schedule_info_content", true);
    }

    public function real_job_size($jobid=0) {
        $jobid = (int) $jobid;
        if( $jobid <= 0 ) {
            return array();
        }
        $query = "SELECT COUNT(statid) AS statcount, SUM(htmlrecipients + textrecipients + multipartrecipients) AS totalsent, SUM(sendsize) AS sendsize FROM " . SENDSTUDIO_TABLEPREFIX . "jobs j, " . SENDSTUDIO_TABLEPREFIX . "stats_newsletters n WHERE j.jobid='" . $jobid . "' AND n.queueid=j.queueid";
        $result = $this->db->Query($query);
        $row = $this->db->Fetch($result);
        while( 1 < $row["statcount"] ) {
            $row["sendsize"] = (int) ($row["sendsize"]) / $row["statcount"];
        }

        return array( "totalsent" => $row["totalsent"] , "sendsize" => $row["sendsize"] );
    }

    public function bench($key="mta_b", $type="start") {
        if( !isset( $GLOBALS["bench_" . $key] ) && $type != "start" ) {
            return false;
        }
        if( $type == "start" ) {
            $GLOBALS["bench_" . $key] = array( "start" => time() , "calls" => 0 );
            return NULL;
        }
        if( $type == "call" ) {
            ++$GLOBALS["bench_" . $key]["calls"];
            return NULL;
        }
        if( $type == "end" ) {
            $GLOBALS["bench_" . $key]["end"] = time();
            $GLOBALS["bench_" . $key]["time"] = $GLOBALS["bench_" . $key]["end"] - $GLOBALS["bench_" . $key]["start"];
            return ( $GLOBALS["bench_" . $key] );
        }
    }
}

?>