<?php

ob_start();
$er = error_reporting(0);
require_once dirname(__FILE__).'/admin/inc/unregister_globals.php';
require_once dirname(__FILE__).'/admin/inc/magic_quotes.php';

//# none of our parameters can contain html for now
$_GET = removeXss($_GET);
$_POST = removeXss($_POST);
$_REQUEST = removeXss($_REQUEST);

if (isset($_SERVER['ConfigFile']) && is_file($_SERVER['ConfigFile'])) {
    include $_SERVER['ConfigFile'];
} elseif (is_file('config/config.php')) {
    include 'config/config.php';
} else {
    echo "Error, cannot find config file\n";
    exit;
}

require_once dirname(__FILE__).'/admin/init.php';

$GLOBALS['database_module'] = basename($GLOBALS['database_module']);
$GLOBALS['language_module'] = basename($GLOBALS['language_module']);

require_once dirname(__FILE__).'/admin/'.$GLOBALS['database_module'];

// load default english and language
include_once dirname(__FILE__).'/admin/defaultFrontendTexts.php';
// Allow customisation per installation
if (is_file($_SERVER['DOCUMENT_ROOT'].'/'.$GLOBALS['language_module'])) {
    include_once $_SERVER['DOCUMENT_ROOT'].'/'.$GLOBALS['language_module'];
}

require_once dirname(__FILE__).'/admin/inc/random_compat/random.php';
include_once dirname(__FILE__).'/admin/languages.php';
require_once dirname(__FILE__).'/admin/defaultconfig.php';
require_once dirname(__FILE__).'/admin/connect.php';
include_once dirname(__FILE__).'/admin/lib.php';

if (isset($_GET['tid'])) {
    if (!is_string($_GET['tid'])) {
        echo 'Invalid Request';
        exit;
    }
    $tid = $_GET['tid'];

    if (SIGN_WITH_HMAC) {
        $hmac = $_GET['hm'];
        if (empty($hmac)) {
            echo 'Invalid Request';
            exit;
        }
        $myUrl = sprintf('%s://%s%s', $_SERVER['REQUEST_SCHEME'], $_SERVER['HTTP_HOST'], $_SERVER['REQUEST_URI']);
        $myUrl = str_replace('&hm='.$hmac, '', $myUrl);

        if (!hash_equals(hash_hmac(HASH_ALGO, $myUrl, HMACKEY), $hmac)) {
            echo 'Invalid Request';
            exit;
        }
    }

    if (strlen($tid) == 64) {
        $tid = str_replace(' ', '+', $tid);
        $dec = bin2hex(base64_decode($tid));
        $track = 'T|'.substr($dec, 0, 8).'-'.substr($dec, 8, 4).'-4'.substr($dec, 13, 3).'-'.substr($dec, 16, 4).'-'.substr($dec, 20, 12).'|'.
            substr($dec, 32, 8).'-'.substr($dec, 40, 4).'-4'.substr($dec, 45, 3).'-'.substr($dec, 48, 4).'-'.substr($dec, 52, 12).'|'.
            substr($dec, 64, 8).'-'.substr($dec, 72, 4).'-4'.substr($dec, 77, 3).'-'.substr($dec, 80, 4).'-'.substr($dec, 84, 12);
    } else {
        $track = base64_decode($tid);
        $track = $track ^ XORmask;
    }

    if (!preg_match(
            '/^(H|T)
            \|([a-f0-9]{8}-?[a-f0-9]{4}-?[a-f0-9]{4}-?[89ab][a-f0-9]{3}-?[a-f0-9]{12})
            \|([a-f0-9]{8}-?[a-f0-9]{4}-?[a-f0-9]{4}-?[89ab][a-f0-9]{3}-?[a-f0-9]{12})
            \|([a-f0-9]{8}-?[a-f0-9]{4}-?[a-f0-9]{4}-?[89ab][a-f0-9]{3}-?[a-f0-9]{12})$/x',
            $track,
            $matches
        )) {
        FileNotFound();
    }
    $msgtype = $matches[1];
    $fwduuid = $matches[2];
    $messageuuid = $matches[3];
    $useruuid = $matches[4];

//    print $msgtype . '<br/>';
//    print $fwduuid . '<br/>';
//    print $messageuuid . '<br/>';
//    print $useruuid . '<br/>';

    $linkdata = Sql_Fetch_Assoc_query(sprintf('select * from %s where uuid = "%s"', $GLOBALS['tables']['linktrack_forward'],
        $fwduuid));

    if (empty($linkdata)) {
        FileNotFound();
    }
    $fwdid = $linkdata['id'];

    $userdata = Sql_Fetch_array_query(sprintf('select id from %s where uuid = "%s"', $GLOBALS['tables']['user'],
        $useruuid));

    if (empty($userdata)) {
        FileNotFound();
    }
    $userid = $userdata['id'];
    $messagedata = Sql_Fetch_array_query(sprintf('select id from %s where uuid = "%s"', $GLOBALS['tables']['message'],
        $messageuuid));

    if (empty($messagedata)) {
        FileNotFound();
    }
    $messageid = $messagedata['id'];
    $allowPersonalised = true;
} elseif (isset($_GET['id'])) {
    if (!is_string($_GET['id'])) {
        echo 'Invalid Request';
        exit;
    }
    $id = $_GET['id'];
    $track = base64_decode($id);
    $track = $track ^ XORmask;

    if (!preg_match('/^(H|T)\|([1-9]\d*)\|([1-9]\d*)\|([1-9]\d*)$/', $track, $matches)) {
        FileNotFound();
    }
    $msgtype = $matches[1];
    $fwdid = $matches[2];
    $messageid = $matches[3];
    $userid = $matches[4];
    $linkdata = Sql_Fetch_array_query(sprintf('select * from %s where id = %d', $GLOBALS['tables']['linktrack_forward'],
        $fwdid));

    if (!$linkdata) {
        //# try the old table to avoid breaking links
        $linkdata = Sql_Fetch_array_query(sprintf('select * from %s where linkid = %d and userid = %d and messageid = %d',
            $GLOBALS['tables']['linktrack'], $fwdid, $userid, $messageid));
        if (!empty($linkdata['forward'])) {
            //# we're not recording clicks, but at least links from older phpList versions won't break.
            header('Location: '.$linkdata['forward'], true, 303);
            exit;
        }
//  echo 'Invalid Request';
        // maybe some logging?
        FileNotFound();
    }
    //# verify that this subscriber actually received this message, otherwise they're allowed
    //# normal URLS on test messages, but not personalised ones
    $allowed = Sql_Fetch_Row_Query(sprintf('select userid from %s where userid = %d and messageid = %d',
        $GLOBALS['tables']['usermessage'], $userid, $messageid));

    $allowPersonalised = empty($allowed[0])
        ? !empty($_SESSION['adminloggedin'])
        : true;
} else {
    echo 'Invalid Request';
    exit;
}

//# hmm a bit heavy to use here @@@optimise
$messagedata = loadMessageData($messageid);
//print "$track<br/>";
//print "User $userid, Mess $messageid, Link $linkid";

$ml = Sql_Fetch_Array_Query(sprintf('select * from %s where messageid = %d and forwardid = %d',
    $GLOBALS['tables']['linktrack_ml'], $messageid, $fwdid));

if (empty($ml['firstclick'])) {
    Sql_query(sprintf('update %s set firstclick = now(),latestclick = now(),clicked = clicked + 1 where forwardid = %d and messageid = %d',
        $GLOBALS['tables']['linktrack_ml'], $fwdid, $messageid));
} else {
    Sql_query(sprintf('update %s set clicked = clicked + 1, latestclick = now() where forwardid = %d and messageid = %d',
        $GLOBALS['tables']['linktrack_ml'], $fwdid, $messageid));
}

if ($msgtype == 'H') {
    Sql_query(sprintf('update %s set htmlclicked = htmlclicked + 1 where forwardid = %d and messageid = %d',
        $GLOBALS['tables']['linktrack_ml'], $fwdid, $messageid));
} else {
    Sql_query(sprintf('update %s set textclicked = textclicked + 1 where forwardid = %d and messageid = %d',
        $GLOBALS['tables']['linktrack_ml'], $fwdid, $messageid));
}

$viewed = Sql_Fetch_Row_query(sprintf('select viewed from %s where messageid = %d and userid = %d',
    $GLOBALS['tables']['usermessage'], $messageid, $userid));
if (!$viewed[0]) {
    Sql_Query(sprintf('update %s set viewed = now() where messageid = %d and userid = %d',
        $GLOBALS['tables']['usermessage'], $messageid, $userid));
    Sql_Query(sprintf('update %s set viewed = viewed + 1 where id = %d',
        $GLOBALS['tables']['message'], $messageid));

    $metaData = array();
    foreach (array('HTTP_USER_AGENT', 'HTTP_REFERER') as $key) {
        if (isset($_SERVER[$key])) {
            $metaData[$key] = htmlspecialchars(strip_tags($_SERVER[$key]));
        }
    }

    Sql_Query(sprintf('insert into %s (messageid,userid,viewed,ip,data) values(%d,%d,now(),"%s","%s")',
        $GLOBALS['tables']['user_message_view'], $messageid, $userid, getClientIP(), sql_escape(serialize($metaData))));
}

$uml = Sql_Fetch_Array_Query(sprintf('select * from %s where messageid = %d and forwardid = %d and userid = %d',
    $GLOBALS['tables']['linktrack_uml_click'], $messageid, $fwdid, $userid));

if (empty($uml['firstclick'])) {
    Sql_query(sprintf('insert into %s set firstclick = now(), forwardid = %d, messageid = %d, userid = %d',
        $GLOBALS['tables']['linktrack_uml_click'], $fwdid, $messageid, $userid));
}
Sql_query(sprintf('update %s set clicked = clicked + 1, latestclick = now() where forwardid = %d and messageid = %d and userid = %d',
    $GLOBALS['tables']['linktrack_uml_click'], $fwdid, $messageid, $userid));

if ($msgtype == 'H') {
    Sql_query(sprintf('update %s set htmlclicked = htmlclicked + 1 where forwardid = %d and messageid = %d and userid = %d',
        $GLOBALS['tables']['linktrack_uml_click'], $fwdid, $messageid, $userid));
} elseif ($msgtype == 'T') {
    Sql_query(sprintf('update %s set textclicked = textclicked + 1 where forwardid = %d and messageid = %d and userid = %d',
        $GLOBALS['tables']['linktrack_uml_click'], $fwdid, $messageid, $userid));
}

$url = $linkdata['url'];
if ($linkdata['personalise']) {
    if (!$allowPersonalised) {
        FileNotFound('<br/><i>'.s('Profile links in test campaigns only work when you are logged in as an administrator.').'</i><br/>');
    }

    $uid = Sql_Fetch_Row_Query(sprintf('select uniqid from %s where id = %d', $GLOBALS['tables']['user'], $userid));
    if ($uid[0]) {
        if (strpos($url, '?')) {
            $url .= '&uid='.$uid[0];
        } else {
            $url .= '?uid='.$uid[0];
        }
    }
}
//print "$url<br/>";
if (!isset($_SESSION['entrypoint'])) {
    $_SESSION['entrypoint'] = $url;
}

// Add analytics tracking parameters only to http and https URLs
if (!empty($messagedata['google_track']) && preg_match('/^http/i', $url)) {
    require __DIR__ . '/admin/analytics.php';

    $analytics = getAnalyticsQuery();
    $format = $msgtype == 'H' ? 'HTML' : 'text';
    $trackingParameters = $analytics->trackingParameters($format, loadMessageData($messageid));
    $prefix = $analytics->prefix();
    $url = addAnalyticsTracking($url, $trackingParameters, $prefix);
}

foreach ($plugins as $pi) {
    $pi->linkClick($msgtype, $fwdid, $messageid, $userid, $url);
}
//print "Location $url"; exit;
header('Location: '.$url, true, 303); //# use 303, because Location only uses 302, which gets indexed
exit;
