<?php

/*
  MailBeez Automatic Trigger Email Campaigns
  http://www.mailbeez.com

  Copyright (c) 2010, 2011, 2012 MailBeez

  inspired and in parts based on
  Copyright (c) 2003 osCommerce

  Released under the GNU General Public License

  rewrite emails to add tracking code


 */

///////////////////////////////////////////////////////////////////////////////
///																			 //
///                 MailBeez Core file - do not edit                         //
///                                                                          //
///////////////////////////////////////////////////////////////////////////////

/*
 * lightweight clicktracker API:
 *
 * Log open:
 *  mailhive.php?mi=:messageId
 *
 *  return 1x1 pixel gif
 *
 * :messageId   MailBeez messageId

 *
 * Log click:
 *  mailhive.php?mid=:messageId[&url=:pageUrl]
 *
 *  return json
 *
 * :messageId   MailBeez messageId
 * :pageUrl     entrypoint Url to track
 *
 * Log order:
 *  mailhive.php?mid=:messageId&orders_id=:orders_id
 *
 *  return json
 *
 * :messageId   MailBeez messageId
 * :orders_id   orders_id (if prefix 'oid:' will match agains orders_oid)
 *
 *
 */


/*
 * test cases
 * log open mailhive.php?mi=123
 * Frontend click /?mid=123
 * Frontend order place order after /?mid=123

 * API log click mailhive.php?mid=123&url=123
 * API log order ?mid=123&orders_id=123
 *
 */


if (defined('MH_DIR_FS_CATALOG')) {
    // in case of open tracking
    require_once(MH_DIR_FS_CATALOG . MH_ROOT_PATH . 'common/classes/mailbeez_analytics.php');
}

// set paths for performance context in inc_mailhive.php
if (getenv('SAAS_LOCAL_PATH')) {
    if (!defined('MH_DIR_WORK')) {
        define('MH_DIR_WORK', 'work/');
    }
    define('MH_DIR_WORK_TRACKER', MH_DIR_WORK . 'app/');
} else {
    if (!defined('MH_DIR_WORK')) {
        define('MH_DIR_WORK', 'common/templates_c/');
    }
    define('MH_DIR_WORK_TRACKER', MH_DIR_WORK);
}

if (!defined('MAILBEEZ_MESSAGE_ID_TOKEN')) {
    define('MAILBEEZ_MESSAGE_ID_TOKEN', '%message-id%');
}
if (!defined('MAILBEEZ_TRACKER_MID_PARAM')) {
    define('MAILBEEZ_TRACKER_MID_PARAM', 'mid');
}


class mb_clicktracker
{
    const MAILBEEZ_CLICKTRACKER_TIMESTAMP_PATH = MH_DIR_FS_WORK; //only used in full context
    const MAILBEEZ_CLICKTRACKER_TIMESTAMP_FILE = 'clicktracker_timestamp.txt';
    const MAILBEEZ_CLICKTRACKER_LOG_FOLDER = MH_DIR_WORK_TRACKER;
    const MAILBEEZ_CLICKTRACKER_OPEN_LOG_FILE = 'open_log.txt';
    const MAILBEEZ_CLICKTRACKER_CLICK_LOG_FILE = 'click_log.txt';
    const MAILBEEZ_CLICKTRACKER_ORDER_LOG_FILE_PREFIX = 'order_log-';
    const MAILBEEZ_CLICKTRACKER_ORDER_LOG_FILE_EXT = '.txt';
    const MAILBEEZ_CLICKTRACKER_CYCLE = 30; // sec

    var $code;

// class constructor
    function __construct()
    {

    }

    function mb_clicktracker()
    {
        self::__construct();
    }

    function process()
    {
        if (mh_cfg('MAILBEEZ_ANALYTICS_OPEN_RATES_AUTO') == 'True') {
            if ($this->doRun()) {
                $this->import_open_log_file(true);
                $this->import_click_log_file(true);
                $this->import_order_log_file(true);
                $this->consolidate_coupon_data(true);
                $this->updateTimeStamp();
            }
        }
    }

    function rewriteContent($input, $type = 'html')
    {
        if (mh_cfg('MAILBEEZ_ANALYTICS_STATUS') == 'False') {
            return $input;
        }

        $this->code = MAILBEEZ_TRACKER_MID_PARAM . '=' . MAILBEEZ_MESSAGE_ID_TOKEN;
        $rewrite_mode = MAILBEEZ_TRACKER_REWRITE_MODE;
        $rewritten = $input;

        switch ($rewrite_mode) {
            case 'all':
                // rewrite all links
                $rewritten = preg_replace("#href=\"(([a-zA-Z]+://)([a-zA-Z0-9%.;:/=+_-]*[?]+[a-zA-Z0-9&%.;:/=+_-]*))\"#", "href=\"$1" . "&" . $this->code . "\"", $rewritten);
                $rewritten = preg_replace("#href=\"(([a-zA-Z]+://)([a-zA-Z0-9%.;:/=+_-]*))\"#", "href=\"$1" . "?" . $this->code . "\"", $rewritten);
                break;

            case 'shop':
                // rewrite only internal links
                // html links
                if ($type == 'html') {
                    $rewritten = preg_replace("#href=\"" . HTTP_SERVER . "(([a-zA-Z0-9%.;:/=+_-]*[?]+[a-zA-Z0-9&%.;:/=+_-]*))\"#", "href=\"" . HTTP_SERVER . "$1" . "&" . $this->code . "\"", $rewritten);
                    $rewritten = preg_replace("#href=\"" . HTTP_SERVER . "(([a-zA-Z0-9%.;:/=+_-]*))\"#", "href=\"" . HTTP_SERVER . "$1" . "?" . $this->code . "\"", $rewritten);

                    if (defined('HTTPS_SERVER') && HTTPS_SERVER != '') {
                        $rewritten = preg_replace("#href=\"" . HTTPS_SERVER . "(([a-zA-Z0-9%.;:/=+_-]*[?]+[a-zA-Z0-9&%.;:/=+_-]*))\"#", "href=\"" . HTTP_SERVER . "$1" . "&" . $this->code . "\"", $rewritten);
                        $rewritten = preg_replace("#href=\"" . HTTPS_SERVER . "(([a-zA-Z0-9%.;:/=+_-]*))\"#", "href=\"" . HTTP_SERVER . "$1" . "?" . $this->code . "\"", $rewritten);
                    }

                } elseif ($type == 'txt' && mh_cfg('MAILBEEZ_ANALYTICS_REWRITE_FORMAT') == 'True') {
                    // txt links
                    $rewritten = preg_replace("#" . HTTP_SERVER . "(([a-zA-Z0-9%.;:/=+_-]*[?]+[a-zA-Z0-9&%.;:/=+_-]*))\s#", "" . HTTP_SERVER . "$1" . "&" . $this->code . "", $rewritten);
                    $rewritten = preg_replace("#" . HTTP_SERVER . "(([a-zA-Z0-9%.;:/=+_-]*))\s#", "" . HTTP_SERVER . "$1" . "?" . $this->code . "", $rewritten);
                    if (defined('HTTPS_SERVER') && HTTPS_SERVER != '') {

                        $rewritten = preg_replace("#" . HTTPS_SERVER . "(([a-zA-Z0-9%.;:/=+_-]*[?]+[a-zA-Z0-9&%.;:/=+_-]*))\s#", "" . HTTP_SERVER . "$1" . "&" . $this->code . "", $rewritten);
                        $rewritten = preg_replace("#" . HTTPS_SERVER . "(([a-zA-Z0-9%.;:/=+_-]*))\s#", "" . HTTP_SERVER . "$1" . "?" . $this->code . "", $rewritten);
                    }
                }

                //fix rewritten urls
                $rewritten = str_replace('/&', '/?', $rewritten);

                // avoid rewriting of image engine urls on gambio cloud
                // like https://localhost74.com/GX4_v4.4.0.1/mailhive.php?/api/public/v1.0/editor/imgengine/&id=234
                $rewritten = str_replace('editor/imgengine/?id=', 'editor/imgengine/&id=', $rewritten);

                // remove double mid
                $rewritten = str_replace($this->code . '&' . $this->code, $this->code, $rewritten);

                break;
        }
        return $rewritten;
    }


    static function _get($name, $fallback = null, $type = 'string')
    {
        return self::mh_get($name, $fallback, $type);
    }

    static function mh_get($name, $fallback = null, $type = 'string')
    {
        if (!isset($_GET[$name])) {
            return $fallback;
        }
        $value = trim($_GET[$name]);

        try {
            $value = self::mh_clean_input($value, $fallback, $type);
        } catch (Exception $e) {
            return $fallback;
        }

        return $value;
    }

    static function mh_clean_input($value, $fallback = null, $type = 'string')
    {

        // Define validation rules based on type
        $patterns = [
            'hex' => '/^[a-f0-9]{3,32}$/',       // 12-character hexadecimal (set to 3..32 chars)
            'int' => '/^\d+$/',                // Only digits
            'string' => '/^[a-zA-Z0-9-:_\/]+$/',     // Alphanumeric, dash, underscore
            'uuid' => '/^[a-f0-9\-]{36}$/',     // UUID format
            'email' => '/^[\w.\-]+@[\w.\-]+\.[a-zA-Z]{2,}$/', // Basic email validation
            'slug' => '/^[a-z0-9-]+$/',         // SEO-friendly slug
            'urlencoded' => '/^[a-zA-Z0-9%\-._~:\/?#\[\]@!$&\'()*+,;=]+$/',

        ];

        // Validate input against defined pattern
        if (isset($patterns[$type]) && !preg_match($patterns[$type], $value)) {
            throw new Exception('Invalid value for type ' . $type . ': ' . $value);
        }
        return $value;
    }

    static function record_event($store_basedir)
    {
        // store front context?
        if (defined('MH_DIR_CONFIG')) {
            return true;
        }

        // message event API call
        // handle events captured on mailhive.php
        // - open
        // - click api
        // - order api
        // - product view api
        //
        // tracker image
        // for best performance write tracking data into log file
        // log file is imported by the mailbeez framework

        $app_basedir = self::getBaseDir($store_basedir);


        if (self::_get('mi') && (!self::_get('n2go_rid') || (self::_get('n2go_rid') && (self::_get('n2go_rid') != '{{recipient.id}}') && self::_get('n2go_rid') != ''))) {
            mb_clicktracker::record_open_log(self::_get('mi'), $app_basedir);
            self::outputSuccess('image');
            return true;
        }

        // click/order event
        if (self::_get('mid')) {
            // click
            if (self::_get('url', null, 'urlencoded')) {
                mb_clicktracker::record_click_log(self::_get('mid'), $app_basedir, self::_get('url', null, 'urlencoded'));
                self::outputSuccess('image');
            }

            // order
            if (self::_get('orders_id')) {
                mb_clicktracker::record_order_log(self::_get('mid'), $app_basedir, self::_get('orders_id'), self::_get('customers_id'));
                self::outputSuccess('image');
            } elseif (self::_get('oid')) {
                mb_clicktracker::record_order_log(self::_get('mid'), $app_basedir, 'oid:' . self::_get('oid'), 'cid:' . self::_get('cid'));
                self::outputSuccess('image');
            }

            return true;
        }


        // product viewed event
        // todo
        // mb_clicktracker::record_product_view();

        return false; // no event recorded
    }


    static function record_open_log($message_id, $app_basedir)
    {

        $log_IP = false;

        // to not track opens from these user agents
        $exclude_ua = array('SpamBayes');

        $ua = $_SERVER['HTTP_USER_AGENT'];
        $track = true;
        foreach ($exclude_ua as $ex_ua) {
            if (stristr($ua, $ex_ua)) {
                $track = false;
            }
        }

        // exclude newsletter2go thumbnail service from opening email
        if ($track && $message_id != MAILBEEZ_MESSAGE_ID_TOKEN && $_SERVER['REMOTE_ADDR'] != '144.76.95.74') {
            $logfile_path = $app_basedir . self::MAILBEEZ_CLICKTRACKER_LOG_FOLDER . self::MAILBEEZ_CLICKTRACKER_OPEN_LOG_FILE;

            $content = $message_id . "|" . time() . "|" . $_SERVER['HTTP_USER_AGENT'];
            if ($log_IP) {
                $content .= ' IP:' . $_SERVER['REMOTE_ADDR'];
            }
            self::logFileWriter($logfile_path, $content);
        }
    }


    static function record_click_log($message_id, $app_basedir, $url)
    {
        $log_IP = false;

        if ($message_id != MAILBEEZ_MESSAGE_ID_TOKEN) {
            $logfile_path = $app_basedir . self::MAILBEEZ_CLICKTRACKER_LOG_FOLDER . self::MAILBEEZ_CLICKTRACKER_CLICK_LOG_FILE;

            $content = $message_id . "|" . time() . "|" . $url . "|" . $_SERVER['HTTP_USER_AGENT'];
            if ($log_IP) {
                $content .= ' IP:' . $_SERVER['REMOTE_ADDR'];
            }
            self::logFileWriter($logfile_path, $content);
        }
    }

    static function record_order_log($message_id, $app_basedir, $orders_id, $customers_id)
    {
        $log_IP = false;
        if ($message_id != MAILBEEZ_MESSAGE_ID_TOKEN) {
            $logfile_path = $app_basedir . self::MAILBEEZ_CLICKTRACKER_LOG_FOLDER . self::MAILBEEZ_CLICKTRACKER_ORDER_LOG_FILE_PREFIX;
            $logfile_path .= md5("$orders_id|$customers_id") . self::MAILBEEZ_CLICKTRACKER_ORDER_LOG_FILE_EXT;

            if (file_exists($logfile_path)) {
                return true;
            }
            $content = $message_id . "|" . time() . "|" . $orders_id . "|" . $customers_id . "|" . $_SERVER['HTTP_USER_AGENT'];
            if ($log_IP) {
                $content .= ' IP:' . $_SERVER['REMOTE_ADDR'];
            }

            self::logFileWriter($logfile_path, $content);
        }
    }


    function record_click($message_id, $url, $timestamp = null)
    {
        $check_query_raw = "SELECT autoemail_id
                                FROM " . TABLE_MAILBEEZ_TRACKING . "
                                WHERE message_id='" . $message_id . "'";
        $check_query = mh_db_query($check_query_raw);
        $result_size = mh_db_num_rows($check_query);
        if ($result_size == 0) {
            return false;
        }

        if (mh_cfg('MAILBEEZ_ANALYTICS_STATUS') == 'False') {
            return false;
        }

        try {
            $_SESSION['mailbeez_message_id'] = self::mh_clean_input($message_id);
        } catch (Exception $e) {
            return false;
        }

        $tstamp = (is_null($timestamp)) ? 'now()' : date("Y-m-d H:i:s", $timestamp);

        // record click
        $sql_data_array = array('message_id' => $message_id,
            'url' => $url,
            'date_record' => $tstamp);
        mh_db_perform(TABLE_MAILBEEZ_TRACKING_CLICKS, $sql_data_array);

        // mark message as opened
        // mark message as clicked
        $sql_data_array = array('opened' => $tstamp,
            'clicked' => $tstamp);
        mh_db_perform(TABLE_MAILBEEZ_TRACKING, $sql_data_array, 'update', 'message_id="' . $message_id . '"');
    }


    function record_order($message_id = null)
    {
        if (mh_cfg('MAILBEEZ_ANALYTICS_STATUS') == 'False') {
            return false;
        }

        // write to session
        // track in mailbeez
        // track when order is placed
        // get order id, customers id
        if (is_null($message_id)) {
            $message_id = self::mh_clean_input($_SESSION['mailbeez_message_id']);
        }

        $mailbeez_orders_query = mh_db_query("SELECT orders_id, orders_status
                                  FROM " . TABLE_ORDERS . "
                                  WHERE customers_id = '" . $_SESSION['customer_id'] . "'
                                  ORDER BY orders_id DESC LIMIT 1");
        $mailbeez_orders = mh_db_fetch_array($mailbeez_orders_query);
        $mailbeez_last_order = $mailbeez_orders['orders_id'];
        //$mailbeez_order_status = $mailbeez_orders['orders_status'];

        mb_clicktracker::write_record_order($message_id, $mailbeez_last_order, $_SESSION['customer_id']);
    }


    function record_product_view($products_id, $visitors_token, $customers_id)
    {
        // todo

        // move to pro

        // reset after purchase?
        // a customer can have multiple visitor tokens (e.g. different devices)
        // a vistor (=browser) can have different customers

        $visitors_token; // cookie or fingerprint library
        $customers_id; // session

        TABLE_MAILBEEZ_SITEBEEZ_VISITORS;
        TABLE_MAILBEEZ_SITEBEEZ_PRODUCTS_VIEWED;

        return true;

    }


    static function write_record_order($message_id, $orders_id, $customers_id, $timestamp = null)
    {


        if (isset($_SESSION['mailbeez_tracking_orders_id']) && $_SESSION['mailbeez_tracking_orders_id'] == $orders_id) {
            return true;
        }

        $_SESSION['mailbeez_tracking_orders_id'] = $orders_id;

        // check if entry exists
        $check_query_sql = "SELECT count(*) as cnt
                                FROM " . TABLE_MAILBEEZ_TRACKING_ORDERS . "
                             WHERE orders_id = '" . $orders_id . "'  ";
        $check_query = mh_db_query($check_query_sql);
        $check_result = mh_db_fetch_array($check_query);

        if ($check_result['cnt'] > 0) {
            return true;
        }


        $query_sql = "SELECT date_purchased, last_modified
                                FROM " . TABLE_ORDERS . "
                             WHERE orders_id = '" . $orders_id . "'  ";
        $query = mh_db_query($query_sql);
        $result = mh_db_fetch_array($query);


        $tstamp = (is_null($timestamp)) ? $result['date_purchased'] : date("Y-m-d H:i:s", $timestamp);

        $sql_data_array = array('message_id' => $message_id,
            'orders_id' => $orders_id,
            'customers_id' => $customers_id,
            'date_record' => $tstamp);
        mh_db_perform(TABLE_MAILBEEZ_TRACKING_ORDERS, $sql_data_array);


        if ($result['date_purchased'] == '') {
            $result['date_purchased'] = $result['last_modified'];
        }

        $sql = "update " . TABLE_MAILBEEZ_TRACKING . " 
                    set ordered='{$result['date_purchased']}', 
                    opened = IFNULL( opened, '{$result['date_purchased']}'), 
                    clicked = IFNULL( clicked, '{$result['date_purchased']}'),
                    bounce_status = null  
                    where message_id='{$message_id}'";

        mh_db_query($sql);


//        $sql_data_array = array('ordered' => $result['date_purchased']);
//        mh_db_perform(TABLE_MAILBEEZ_TRACKING, $sql_data_array, 'update', 'message_id="' . $message_id . '"');
    }

    function consolidate_coupon_data($silent = false)
    {
        if (file_exists(MH_DIR_CONFIG . 'config_coupon_engine.php')) {
            require_once(MH_DIR_CONFIG . 'config_coupon_engine.php');
            $cfg_ce = new config_coupon_engine();
            if ($cfg_ce->version > 2.2 && $cfg_ce->enabled) {
                $log = couponbeez::consolidate_order_data($silent);
                return $log;
            }
        }
        return false;

    }


    function import_open_log_file($silent = false)
    {
        require_once(MH_DIR_FS_CATALOG . MH_ROOT_PATH . 'common/classes/mailbeez_analytics.php');

        if (getenv('SAAS_LOCAL_PATH')) {
            $logfilePath = getenv('SAAS_LOCAL_PATH');
        } else {
            $logfilePath = MH_DIR_FS_CATALOG . MH_ROOT_PATH;
        }

        $logfile = $logfilePath . self::MAILBEEZ_CLICKTRACKER_LOG_FOLDER . self::MAILBEEZ_CLICKTRACKER_OPEN_LOG_FILE;

        $log = array();

        if (file_exists($logfile)) {
            $logfile_process = $logfile . '_' . time();
            if (!@rename($logfile, $logfile_process)) {
                return false;
            }

            $fp = fopen($logfile_process, "r");
            if ($fp) {
                while (!feof($fp)) {
                    $line = fgets($fp);
                    if (substr_count($line, '|') < 2) {
                        continue;
                    }
                    list($message_id, $timestamp, $user_agent) = explode("|", $line);
                    try {
                        $message_id = self::mh_clean_input($message_id);
                    } catch (Exception $e) {
                        continue;
                    }
                    if ($message_id != '') {
                        if (!$silent) {
                            $log[] = "processed open: $message_id, $timestamp";
                        }
                        // mark message as opened

                        $mobile_flag = mailbeez_analytics::is_mobile_useragent($user_agent);
                        if ($mobile_flag) {
                            $sql_data_array = array('opened' => date("Y-m-d H:i:s", $timestamp),
                                'mobile' => mailbeez_analytics::is_mobile_useragent($user_agent));
                        } else {
                            // do not overwrite mobile status in case of later non-mobile open
                            $sql_data_array = array('opened' => date("Y-m-d H:i:s", $timestamp));
                        }

                        mh_db_perform(TABLE_MAILBEEZ_TRACKING, $sql_data_array, 'update', 'message_id="' . $message_id . '"');

                        $sql_data_array = array('message_id' => $message_id,
                            'date' => date("Y-m-d H:i:s", $timestamp),
                            'user_agent' => $user_agent);
                        mh_db_perform(TABLE_MAILBEEZ_OPENS_LOG, $sql_data_array);
                    }
                }
            }

            fclose($fp);
            // http://stringoftheseus.com/blog/2010/12/22/php-unlink-permisssion-denied-error-on-windows/
            // fix unlink issue on windows server
            @chmod($logfile_process, 0776);
            @unlink($logfile_process);
        } else {
            //  echo "no open tracking file";
        }
        return $log;
    }


    function import_click_log_file($silent = false)
    {
        if (getenv('SAAS_LOCAL_PATH')) {
            $logfilePath = getenv('SAAS_LOCAL_PATH');
        } else {
            $logfilePath = MH_DIR_FS_CATALOG . MH_ROOT_PATH;
        }

        $logfile = $logfilePath . self::MAILBEEZ_CLICKTRACKER_LOG_FOLDER . self::MAILBEEZ_CLICKTRACKER_CLICK_LOG_FILE;

        $log = array();

        if (file_exists($logfile)) {
            $logfile_process = $logfile . '_' . time();
            if (!@rename($logfile, $logfile_process)) {
                return false;
            }

            $fp = fopen($logfile_process, "r");
            if ($fp) {
                while (!feof($fp)) {
                    $line = fgets($fp);
                    if (substr_count($line, '|') < 2) {
                        continue;
                    }
                    list($message_id, $timestamp, $url, $user_agent) = explode("|", $line);
                    try {
                        $message_id = self::mh_clean_input($message_id);
                    } catch (Exception $e) {
                        continue;
                    }

                    if ($message_id != '') {
                        if (!$silent) {
                            $log[] = "processed click: $message_id, $timestamp";
                        }

                        $this->record_click($message_id, $url, $timestamp);
                    }
                }
            }

            fclose($fp);
            // http://stringoftheseus.com/blog/2010/12/22/php-unlink-permisssion-denied-error-on-windows/
            // fix unlink issue on windows server
            @chmod($logfile_process, 0776);
            @unlink($logfile_process);
        } else {
            //  echo "no click tracking file";
        }
        return $log;
    }

    function import_order_log_file($silent = false)
    {
        if (getenv('SAAS_LOCAL_PATH')) {
            $logfilePath = getenv('SAAS_LOCAL_PATH');
            $orders_id_field = 'orders_oid';
        } else {
            $logfilePath = MH_DIR_FS_CATALOG . MH_ROOT_PATH;
            $orders_id_field = 'orders_id';
        }

        $logFiles = glob($logfilePath . self::MAILBEEZ_CLICKTRACKER_LOG_FOLDER . self::MAILBEEZ_CLICKTRACKER_ORDER_LOG_FILE_PREFIX . '*' . self::MAILBEEZ_CLICKTRACKER_ORDER_LOG_FILE_EXT);
        $log = array();

        if (!is_array($logFiles)) {
            return $log;
        }

        foreach ($logFiles as $logfile) {

            if (file_exists($logfile)) {

                $found = false;
                $fp = fopen($logfile, "r");
                if ($fp) {
                    while (!feof($fp)) {
                        $line = fgets($fp);
                        if (substr_count($line, '|') < 2) {
                            continue;
                        }
                        list($message_id, $timestamp, $orders_id, $customers_id, $user_agent) = explode("|", $line);
                        try {
                            $message_id = self::mh_clean_input($message_id);
                            $orders_id = self::mh_clean_input($orders_id);
                            $customers_id = self::mh_clean_input($customers_id);
                        } catch (Exception $e) {
                            // invalid characters in one of the parameters like \ or "
                            continue;
                        }
                        if ($message_id != '') {
                            if (stristr($orders_id, 'oid:')) {
                                // find real data or oid identifier
                                $query = mh_db_query("SELECT orders_id, customers_id FROM " . TABLE_ORDERS . " WHERE $orders_id_field='" . str_replace('oid:', '', $orders_id) . "'");
                                if (mh_db_num_rows($query) == 0) {
                                    if (!$silent) {
                                        $log[] = "order not found: $orders_id , $timestamp";
                                    }
                                    if (!mh_saas()) {
                                        // on saas the order might not be imported yet
                                        $found = true; // delete log file
                                    }
                                    continue; // skip this log, order not yet sync
                                }
                                $orderData = mh_db_fetch_array($query);

                                $orders_id = $orderData['orders_id'];
                                $customers_id = $orderData['customers_id'];
                            }
                            if (!$silent) {
                                $log[] = "processed order: $orders_id , $timestamp";
                            }
                            $found = mb_clicktracker::write_record_order($message_id, $orders_id, $customers_id);
                        }
                    }
                }

                fclose($fp);

                if ($found) {
                    // http://stringoftheseus.com/blog/2010/12/22/php-unlink-permisssion-denied-error-on-windows/
                    // fix unlink issue on windows server
                    @chmod($logfile, 0776);
                    @unlink($logfile);
                }
            } else {
                //  echo "no click tracking file";
            }
        }

        $clean_sql = "DELETE o.* FROM " . TABLE_MAILBEEZ_TRACKING_ORDERS . " o, 
            (SELECT min(id) as min_id, orders_id
                FROM " . TABLE_MAILBEEZ_TRACKING_ORDERS . " k
                GROUP BY orders_id, customers_id
                HAVING COUNT(*) > 1
            ) k 
            WHERE o.id > k.min_id AND o.orders_id = k.orders_id";
        mh_db_query($clean_sql);

        return $log;
    }

    function updateTimeStamp()
    {
        $timestamp_file_path = self::MAILBEEZ_CLICKTRACKER_TIMESTAMP_PATH . self::MAILBEEZ_CLICKTRACKER_TIMESTAMP_FILE;

        if ($fp = fopen($timestamp_file_path, 'w')) {
            flock($fp, LOCK_EX);
            fputs($fp, 'clicktracker timestamp');
            flock($fp, LOCK_UN);
            fclose($fp);
        }
    }

    function doRun()
    {
        $timestamp_file_path = self::MAILBEEZ_CLICKTRACKER_TIMESTAMP_PATH . self::MAILBEEZ_CLICKTRACKER_TIMESTAMP_FILE;
        if (!file_exists($timestamp_file_path)) {
            return true; // do run
        }

        $timedif = @(time() - filemtime($timestamp_file_path));

        if ($timedif < (self::MAILBEEZ_CLICKTRACKER_CYCLE)) {
            return false; // do not run
        } else {
            return true; // do run
        }
    }

    static function getBaseDir($store_basedir)
    {

        if (getenv('SAAS_LOCAL_PATH')) {
            $store_basedir = getenv('SAAS_LOCAL_PATH');
        } else {
            $store_basedir .= MH_ROOT_PATH;
        }
        return $store_basedir;
    }

    static function outputPixel()
    {
        header('Content-type: image/png');
        header("Content-length: 87");
        echo gzinflate(base64_decode('6wzwc+flkuJiYGDg9fRwCQLSjCDMwQQkJ5QH3wNSbCVBfsEMYJC3jH0ikOLxdHEMqZiTnJCQAOSxMDB+E7cIBcl7uvq5rHNKaAIA'));
    }

    static function outputJson($result)
    {
        header('Content-type: application/json');
        echo json_encode($result);
    }

    static function outputSuccess($format = 'image', $silent = true, $log = null)
    {

        switch ($format) {
            case 'image':
                self::outputPixel();
                break;
            case 'json':
                $result = array('success' => true);
                if (!$silent) {
                    $result['log'] = $log;
                }
                self::outputJson($result);
                break;
        }
    }

    static function logFileWriter($logfile_path, $content)
    {
        if (($fp = fopen($logfile_path, 'ab')) !== FALSE) {
            if (flock($fp, LOCK_EX) === TRUE) {
                fwrite($fp, $content . "\n");
                flock($fp, LOCK_UN);
            }
            fclose($fp);
        }
    }

}
