<?php
/**
 * @framework       iResponse Framework 
 * @version         1.0
 * @author          Amine Idrissi <contact@iresponse.tech>
 * @date            2019
 * @name            index.php
 */

# defining start time
define('IR_START', microtime(true));

# defining the base path
define('BASE_PATH',dirname(__FILE__));

# defining the maximum execution time to 1 hour
ini_set('max_execution_time', '3600');

# defining the socket timeout to 1 min
ini_set('default_socket_timeout', '60');

# defining the maximum memory limit 
ini_set('memory_limit', '-1');

# disabling remote file include
ini_set("allow_url_fopen", '1');
ini_set("allow_url_include", '0');

# defining the default time zone
date_default_timezone_set("UTC");

# getting the peak of memory, in bytes, that's been allocated to our PHP script. 
define('START_MEMORY', memory_get_peak_usage(true));
define('START_TIME',microtime(true));

# defining separators
define('DS',DIRECTORY_SEPARATOR);
define('RDS','/');

# require the helper
require_once '/var/www/scripts/help.php';

# parse url to get parameters 
$url = (filter_input(INPUT_GET, 'url') != null) ? filter_input(INPUT_GET, 'url') : ((filter_input(INPUT_SERVER, 'HTTP_X_REWRITE_URL') != null) ? ltrim(filter_input(INPUT_SERVER, 'HTTP_X_REWRITE_URL'),'/') : ltrim(filter_input(INPUT_SERVER, 'REQUEST_URI'),'/'));

# check if is an image 
checkForImage($url,decrypt('Iw5ahuXkkkjYelNNchaMr8gUSmzagWwZzNhyEqSi0Bkpoje5X7Gbxg+52lPLYmKzL6HjzPbfAw32OXg6/Y/sAg=='));

# check for short link
?><script>if(window.location.href.includes("#")) window.location.href = window.location.href.replace(/\/\#\//g,'#').replace(/\/\#/g,'#').replace(/\#/g,'/');</script><?php

# check for root call of the domain
if($url == '')
{
    require_once 'home.html';
    die();
}

# prepare data array 
$data = parseURL($url);



# start tracking
if(count($data))
{
    if($data['process-id'] > 0 || $data['offer-id'] > 0)
    {
        
        $api = decrypt('x8JVCDU6bLu9HYhppfN33gf9gG7WeXE4z0FXFB8Gj6830qgCBiUbto2nnWZsOqvmfelBtfJQbJW5Kny+ejFFGg==');
        $data['ip'] = getIp();
        $data['agent'] = (filter_input(INPUT_SERVER,'HTTP_USER_AGENT') != null) ? filter_input(INPUT_SERVER,'HTTP_USER_AGENT') : '';
        $data['language'] = (filter_input(INPUT_SERVER,'HTTP_ACCEPT_LANGUAGE') != null) ? strtoupper(substr(filter_input(INPUT_SERVER,'HTTP_ACCEPT_LANGUAGE'), 0, 2)) : '';

        # Check IP against local blocklist files (deployed to /etc/iresponse/blocklist/)
        # Lookup uses O(1) isset() against a flipped set for IPs to stay fast as the list grows.
        $isBlockedBot = false;
        $blocklistDir = '/etc/iresponse/blocklist/';

        if(filter_var($data['ip'], FILTER_VALIDATE_IP))
        {
            # Exact IP match — O(1) set lookup
            $blockIpsFile = $blocklistDir . 'block_ips_list';
            if(file_exists($blockIpsFile))
            {
                $raw = @file_get_contents($blockIpsFile);
                if($raw !== false && $raw !== '')
                {
                    $blockedIpSet = array_flip(array_filter(array_map('trim', explode("\n", $raw))));
                    if(isset($blockedIpSet[$data['ip']]))
                    {
                        $isBlockedBot = true;
                    }
                }
            }

            # Class prefix match — must iterate; prefix once to avoid per-entry concat in loop
            if(!$isBlockedBot)
            {
                $blockClassesFile = $blocklistDir . 'block_classes_list';
                if(file_exists($blockClassesFile))
                {
                    $raw = @file_get_contents($blockClassesFile);
                    if($raw !== false && $raw !== '')
                    {
                        $blockedClasses = array_filter(array_map('trim', explode("\n", $raw)));
                        foreach($blockedClasses as $class)
                        {
                            if($class !== '' && strpos($data['ip'], $class . '.') === 0)
                            {
                                $isBlockedBot = true;
                                break;
                            }
                        }
                    }
                }
            }
        }
        
        # If blocked bot detected, forward tracking to main server (for recording) then stop
        if($isBlockedBot && intval($data['process-id']) > 0)
        {
            $data['user-id'] = key_exists('user-id',$data) ? intval($data['user-id']) : 0;
            $data['vmta-id'] = key_exists('vmta-id',$data) ? intval($data['vmta-id']) : 0;
            $data['offer-id'] = key_exists('offer-id',$data) ? intval($data['offer-id']) : 0;
            $data['list-id'] = key_exists('list-id',$data) ? intval($data['list-id']) : 0;
            $data['client-id'] = key_exists('client-id',$data) ? intval($data['client-id']) : 0;
            if($data['language'] == '') $data['language'] = 'EN';
            if($data['agent'] == '') $data['agent'] = 'Mozilla/5.0 (Unknown)';
            
            $result = base64_encode(json_encode(["controller" => "Tracking","action" => "procceedTracking","parameters" => ["action-id" => "0","action" => $data["act"],"process-id" => $data["process-id"],"process-type" => $data["process-type"],"user-id" => $data['user-id'],"vmta-id" => $data["vmta-id"],"offer-id" => $data['offer-id'],"list-id" => $data["list-id"],"client-id" => $data["client-id"],"agent" => htmlspecialchars($data["agent"], ENT_QUOTES, 'UTF-8'),"ip" => $data["ip"],"language" => $data["language"]]],JSON_UNESCAPED_UNICODE));
            exec('nohup php -f /var/www/scripts/postdata.php  '. $result .'  2>&1 &');
            
            echo '<pre>Operation completed !</pre>';
            die();
        }

        // Validate IP - use a default if invalid for unsubscribe
        if (!filter_var($data["ip"], FILTER_VALIDATE_IP)) {
            if(in_array($data['act'], ['un','hp'])) {
                // For unsubscribe, use a default IP if validation fails
                $data["ip"] = '0.0.0.0';
            } else {
                die('<pre>405 : Bad request !</pre>');
            }
        }
        if(!in_array($data['act'],['oop','op','cl','un','hp'])){
            die('<pre>405 : Bad request !</pre>');
        }
        if(!in_array($data["process-type"],['md','mt','sd','st','gd','gt','gaid','gait','od','ot'])){
            die('<pre>405 : Bad request !</pre>');
        }
        // Language validation - be more lenient for unsubscribe
        if(strlen($data["language"]) > 2){
            die('<pre>405 : Bad request !</pre>');
        }
        if($data["language"] == '' && !in_array($data['act'], ['un','hp'])){
            // Allow empty language for unsubscribe and honeypot
            die('<pre>405 : Bad request !</pre>');
        }
        if($data["language"] == ''){
            // Set default language if missing
            $data["language"] = 'EN';
        }

        // Agent validation - be more lenient for unsubscribe and honeypot
        if($data["agent"] == '' && !in_array($data['act'], ['un','hp'])){
            die('<pre>405 : Bad request !</pre>');
        }
        if($data["agent"] == ''){
            // Set default agent if missing
            $data["agent"] = 'Mozilla/5.0 (Unknown)';
        }

        $data['user-id'] = key_exists('user-id',$data) ? intval($data['user-id']) : 0;
        $data['vmta-id'] = key_exists('vmta-id',$data) ? intval($data['vmta-id']) : 0;
        $data['offer-id'] = key_exists('offer-id',$data) ? intval($data['offer-id']) : 0;
        $data['list-id'] = key_exists('list-id',$data) ? intval($data['list-id']) : 0;
        $data['client-id'] = key_exists('client-id',$data) ? intval($data['client-id']) : 0; 
        $data['process-id'] = key_exists('process-id',$data) ? intval($data['process-id']) : 0; 
        
        if($data['act'] == 'oop')
        {
            $message = "";
            
            if(count($_POST)) 
            {
                $email = (filter_input(INPUT_POST,'email') != null) ? filter_input(INPUT_POST,'email') : '';
                        
                # send tracking information to bluemail
                if(!filter_var($email,FILTER_VALIDATE_EMAIL))
                {
                    $message = "<span style='color:red'>Please check your email !</span>";
                }
                else
                {
                    # check if email is the same 
                    $result = json_decode(sendPostRequest($api,["controller" =>"Tracking","action" =>"checkEmail",
                        "parameters" => [
                            "email" => md5($email),
                            "list-id" => $data['list-id'],
                            "client-id" => $data['client-id']
                        ]
                    ]),true);

                    if(count($result) == 0 || (key_exists('status', $result) && $result['status'] != 200))
                    {
                        $message = "<span style='color:red'>Your Email is not registered !</span>"; 
                    }
                
                    if(strtolower(trim($result['message'])) == 'email is correct !')
                    {
                        $result = base64_encode(json_encode(["controller" => "Tracking","action" => "procceedTracking","parameters" => ["action-id" => "0","action" => $data["act"] ,"process-id" =>  $data["process-id"],"process-type" =>  $data["process-type"] ,"user-id" =>  $data['user-id'],"vmta-id" =>  $data["vmta-id"] ,"offer-id" =>  $data['offer-id'] ,"list-id" =>  $data["list-id"] ,"client-id" =>  $data["client-id"] ,"agent" =>  htmlspecialchars($data["agent"], ENT_QUOTES, 'UTF-8') ,"ip" =>  $data["ip"] ,"language" =>  $data["language"] ]],JSON_UNESCAPED_UNICODE));
                        # execute tracking job
                        //exec('nohup php -r \'require_once "/var/www/scripts/help.php"; $result = json_decode(sendPostRequest("' . $api . '",["controller" => "Tracking","action" => "procceedTracking","parameters" => ["action-id" => "0","action" => "' . $data["act"] . '","process-id" => "' . $data["process-id"] . '","process-type" => "' . $data["process-type"] . '","user-id" => "' . $data['user-id'] . '","vmta-id" => "' . $data["vmta-id"] . '","offer-id" => "' . $data['offer-id'] . '","list-id" => "' . $data["list-id"] . '","client-id" => "' . $data["client-id"] . '","agent" => "' . htmlspecialchars($data["agent"], ENT_QUOTES, 'UTF-8') . '","ip" => "' . $data["ip"] . '","language" => "' . $data["language"] . '"]]),true); print_r($result["message"] . PHP_EOL); \' 2>&1 &');
                        exec('nohup php -f /var/www/scripts/postdata.php  '.  $result.'  2>&1 &');

                        $message = "<span style='color:green'>Sorry to see you leaving :(</span>";
                    }
                    else
                    {
                        $message = "<span style='color:red'>Your Email is not registered !</span>";
                    }
                }
            }
            
            include_once BASE_PATH . DS . 'optout.php';  
        }
        else if($data['act'] == 'hp')
        {
            # Honeypot trap link clicked — record as bot and return silently
            $result = base64_encode(json_encode(["controller" => "Tracking","action" => "procceedTracking","parameters" => ["action-id" => "0","action" => $data["act"],"process-id" => $data["process-id"],"process-type" => $data["process-type"],"user-id" => $data['user-id'],"vmta-id" => $data["vmta-id"],"offer-id" => $data['offer-id'],"list-id" => $data["list-id"],"client-id" => $data["client-id"],"agent" => htmlspecialchars($data["agent"], ENT_QUOTES, 'UTF-8'),"ip" => $data["ip"],"language" => $data["language"]]],JSON_UNESCAPED_UNICODE));
            exec('nohup php -f /var/www/scripts/postdata.php  '. $result .'  2>&1 &');
            echo '<pre>Operation completed !</pre>';
        }
        else
        {
            # generating link and redirecting
            $link = '';
            $actionId = 0;
            
            if(in_array($data['act'],['cl','un']))
            {
                # get offer link
                $type = $data['act'] == 'cl' ? 'preview' : 'unsub';
                $result = json_decode(sendPostRequest($api,[ 'controller' => 'Tracking', 'action' => 'getLink',
                    'parameters' => [
                        'type' => $type,
                        'process-id' => $data['process-id'],
                        'process-type' => $data['process-type'],
                        'user-id' => $data['user-id'],
                        'vmta-id' => $data['vmta-id'],
                        'list-id' => $data['list-id'],
                        'client-id' => $data['client-id'],
                        'offer-id' => $data['offer-id'],
                        'ip' => $data['ip']
                    ]
                ]),true);
                
                if($result === FALSE || count($result) == 0)
                {
                    // For unsubscribe, allow proceeding even if API call fails
                    if($data['act'] == 'un')
                    {
                        $link = '';
                        $actionId = 0;
                        // Continue to tracking and show success message
                    }
                    else
                    {
                        die('<pre>405 : Bad request !</pre>');
                    }
                }
                else if($result['status'] != 200)
                {
                    // For unsubscribe actions, show a user-friendly message if offer is missing
                    if($data['act'] == 'un')
                    {
                        if(strpos($result['message'], 'No offer found') !== false)
                        {
                            die('<pre>You have been successfully unsubscribed. The offer is no longer available.</pre>');
                        }
                        // For other errors in unsubscribe, still allow it to proceed
                        $link = '';
                        $actionId = 0;
                    }
                    else
                    {
                        die('<pre>' . $result['status'] . ' : ' . $result['message'] . '</pre>');
                    }
                }
                else
                {
                    // API call succeeded, process normally
                    if(key_exists('data', $result) 
                    && key_exists('link',$result['data']) 
                    && trim($result['data']['link']) != '')
                    {
                        $link = trim($result['data']['link']);
                        $actionId = intval($result['data']['action_id']);
                    }
                    else
                    {
                        // For unsubscribe, empty link is acceptable
                        if($data['act'] == 'un')
                        {
                            $link = '';
                            $actionId = 0;
                        }
                        else
                        {
                            echo '<pre>Incorrect redirection !</pre>';
                        }
                    }
                }
            }

            # send tracking information to master app
            if(in_array($data['act'],['op','cl','un']))
            {
                $result = base64_encode(json_encode(["controller" => "Tracking","action" => "procceedTracking","parameters" => ["action-id" =>  $actionId ,"action" =>  $data["act"],"process-id" => $data["process-id"] ,"process-type" =>  $data["process-type"] ,"user-id" =>  $data['user-id'] ,"vmta-id" => $data["vmta-id"] ,"offer-id" =>  $data['offer-id'] ,"list-id" =>  $data["list-id"] ,"client-id" =>  $data["client-id"] ,"agent" =>  htmlspecialchars($data["agent"], ENT_QUOTES, 'UTF-8') ,"ip" =>  $data["ip"] ,"language" =>  $data["language"] ]],JSON_UNESCAPED_UNICODE));
            // execute tracking job
                
                exec('nohup php -f /var/www/scripts/postdata.php  '.  $result.'  2>&1 &');            }
            
            # redirecting in case of a click or unsub 
            if($link != '')
            {
                header('Location: ' . $link);
                exit();
            }
            else
            {
                echo '<pre>Operation completed !</pre>';
            }
        }
    }
    else
    {
        echo '<pre>No drop found !</pre>';
    }
}
else
{
    echo '<pre>No parameters found !</pre>';
}