Skip to content
Snippets Groups Projects
Commit f4bc8c3f authored by Uma's avatar Uma
Browse files

Fixes Email tracking vulnerability has been addressed

parent c874561f
No related branches found
No related tags found
1 merge request!650Fixes Email tracking vulnerability has been addressed
<?php
/**
* Copyright (C) www.vtiger.com. All rights reserved.
* @license Vtiger Commercial License 1.1. Reverse engineering restricted.
*/
include_once 'modules/Users/Users.php';
require_once 'include/events/include.inc';
vimport('includes.runtime.LanguageHandler');
class Emails_Tracker_Handler {
public function process($data = array()) {
global $current_user;
$current_user = Users::getActiveAdminUser();
$type = $data['method'];
if($type == 'click'){
$this->clickHandler($data);
} else if ($type == 'open'){
$this->openHandler($data);
}
}
protected function clickHandler($data = []) {
$redirectUrl = rawurldecode($data['redirectUrl']);
$redirectLinkName = rawurldecode($data['linkName']);
if((strpos($_SERVER['HTTP_REFERER'], vglobal('site_URL')) !== false) || (empty($_SERVER['HTTP_REFERER']) && $_REQUEST['fromcrm'])) {
if (!empty($redirectUrl)) {
return Vtiger_Functions::redirectUrl($redirectUrl);
}
exit;
}
$parentId = $data['parentId'];
$recordId = $data['record'];
if ($parentId && $recordId) {
$db = PearDatabase::getInstance();
/* PT83128::currently,To track emails we insert a hidden image whose source will be tracking URL.
* When email client loads that image, email open will be tracked. But some email client doesn't load images by default and email open will not be tracked.
* If that email has some link and user clicks on that, link click will be tracked but email will still show as not read which is not correct.
* If any link is clicked on the email and that is getting tracked, we need to check if the email is marked as Open or not and if not we need to mark it as Open on click action.
*/
$result = $db->pquery("SELECT 1 FROM vtiger_email_access WHERE crmid = ? AND mailid = ? ", array($parentId, $recordId));
if (!$db->num_rows($result)) {
$this->openHandler(array('record' => $recordId, 'parentId' => $parentId));
}
$recordModel = Emails_Record_Model::getInstanceById($recordId);
$recordModel->trackClicks($parentId);
}
if(!empty($redirectUrl)) {
return Vtiger_Functions::redirectUrl($redirectUrl);
}
}
protected function openHandler($data = array()) {
$recordId = $data['record'];
$parentId = $data['parentId'];
if($recordId && $parentId){
if((strpos($_SERVER['HTTP_REFERER'], vglobal('site_URL')) !== false) || (empty($_SERVER['HTTP_REFERER']) && $_REQUEST['fromcrm'])) {
// If a email is opened from CRM then we no need to track but need to be redirected
Vtiger_ShortURL_Helper::sendTrackerImage();
exit;
}
$recordModel = Emails_Record_Model::getInstanceById($recordId);
//If email is opened in last 1 hr, not tracking email open again.
if($recordModel->isEmailOpenedRecently($parentId)) {
Vtiger_ShortURL_Helper::sendTrackerImage();
exit;
}
$recordModel->updateTrackDetails($parentId);
Vtiger_ShortURL_Helper::sendTrackerImage();
}
}
}
\ No newline at end of file
......@@ -621,14 +621,22 @@ class Emails_Record_Model extends Vtiger_Record_Model {
public function trackClicks($parentId) {
$db = PearDatabase::getInstance();
$recordId = $this->getId();
$currentDateTime = date('Y-m-d H:i:s');
$db->pquery("INSERT INTO vtiger_email_access(crmid, mailid, accessdate, accesstime) VALUES(?, ?, ?, ?)", array($parentId, $recordId, date('Y-m-d'),$currentDateTime ));
$db->pquery("INSERT INTO vtiger_email_access(crmid, mailid, accessdate, accesstime) VALUES(?, ?, ?, ?)", array($parentId, $recordId, date('Y-m-d'), date('Y-m-d H:i:s')));
$result = $db->pquery("SELECT 1 FROM vtiger_email_track WHERE crmid = ? AND mailid = ?", array($parentId, $recordId));
if ($db->num_rows($result) > 0) {
$db->pquery("UPDATE vtiger_email_track SET click_count = click_count+1 WHERE crmid = ? AND mailid = ?", array($parentId, $recordId));
$result = $db->pquery("SELECT access_count,click_count FROM vtiger_email_track WHERE crmid = ? AND mailid = ?", array($parentId, $recordId));
$accessCount = $db->query_result($result,0,'access_count');
if ($db->num_rows($result)>0) {
$updatedAccessCount = $accessCount;
//If click is unique (i.e first click on mail), then also increase open count to 1
if($accessCount == 0)
$updatedAccessCount = $accessCount+1;
$db->pquery("UPDATE vtiger_email_track SET click_count = click_count+1,access_count=? WHERE crmid = ? AND mailid = ?", array($updatedAccessCount, $parentId, $recordId));
} else {
$db->pquery("INSERT INTO vtiger_email_track(crmid, mailid, click_count) values(?, ?, ?)", array($parentId, $recordId, 1));
$db->pquery("INSERT INTO vtiger_email_track(crmid, mailid, access_count,click_count) values(?, ?, ?,?)", array($parentId, $recordId, 1,1));
}
}
......@@ -694,16 +702,15 @@ class Emails_Record_Model extends Vtiger_Record_Model {
return $content;
}
public function getTrackUrlForClicks($parentId, $redirectUrl = false) {
$siteURL = vglobal('site_URL');
$applicationKey = vglobal('application_unique_key');
$recordId = $this->getId();
$trackURL = "$siteURL/modules/Emails/actions/TrackAccess.php?record=$recordId&parentId=$parentId&applicationKey=$applicationKey&method=click";
if ($redirectUrl) {
$encodedRedirUrl = rawurlencode($redirectUrl);
$trackURL .= "&redirectUrl=$encodedRedirUrl";
}
return $trackURL;
public function getTrackUrlForClicks($parentId, $redirectUrl = false, $linkName = false) {
$params = array();
$recordId = $this->getId();
if($redirectUrl) $params['redirectUrl'] = $redirectUrl;
if($linkName) $params['linkName'] = $linkName;
$params['record'] = $recordId;
$params['parentId'] = $parentId;
$params['method'] = 'click';
return Vtiger_Functions::generateTrackingURL($params);
}
/**
......@@ -788,4 +795,21 @@ class Emails_Record_Model extends Vtiger_Record_Model {
return $replyTo;
}
/**
* Function to check if email is opened within 1 hour.
* @param <Integer> $parentId Parent record id
* @return <Boolean> Returns TRUE if opened within 1 hr else FALSE.
*/
function isEmailOpenedRecently($parentId) {
$db = PearDatabase::getInstance();
$lastOpenTime = date('Y-m-d H:i:s', strtotime("-1 hours"));
$result = $db->pquery("SELECT 1 FROM vtiger_email_access WHERE crmid = ? AND mailid = ? AND accesstime > ?", array($parentId, $this->getId(), $lastOpenTime));
if($db->num_rows($result)) {
return true;
}
return false;
}
}
......@@ -54,7 +54,7 @@ class VTSendNotificationTask extends VTEmailTask {
//Including email tracking details
global $site_URL, $application_unique_key;
$emailId = $emailFocus->id;
$trackURL = "$site_URL/modules/Emails/actions/TrackAccess.php?record=$entityId&mailid=$emailId&app_key=$application_unique_key";
$trackURL = Vtiger_Functions::generateTrackingURL(['record'=>$entityId,'mailid'=>$emailId, 'method'=>'open']);
$content = "<img src='$trackURL' alt='' width='1' height='1'>$content";
if (stripos($content, '<img src="cid:logo" />')) {
......
......@@ -1180,11 +1180,14 @@ class Vtiger_Functions {
* @return string returns track image contents
*/
static function getTrackImageContent($recordId, $parentId) {
$siteURL = vglobal('site_URL');
$applicationKey = vglobal('application_unique_key');
$trackURL = "$siteURL/modules/Emails/actions/TrackAccess.php?record=$recordId&parentId=$parentId&applicationKey=$applicationKey";
$imageDetails = "<img src='$trackURL' alt='' width='1' height='1'>";
return $imageDetails;
$params = array();
$params['record'] = $recordId;
$params['parentId'] = $parentId;
$params['method'] = 'open';
$trackURL = Vtiger_Functions::generateTrackingURL($params);
$imageDetails = "<img src='$trackURL' alt='' width='1' height='1'>";
return $imageDetails;
}
/**
......@@ -1579,4 +1582,15 @@ class Vtiger_Functions {
}
return $attachmentIds;
}
static function generateTrackingURL($params = []){
$options = array(
'handler_path' => 'modules/Emails/handlers/Tracker.php',
'handler_class' => 'Emails_Tracker_Handler',
'handler_function' => 'process',
'handler_data' => $params
);
return Vtiger_ShortURL_Helper::generateURL($options);
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment