This page lists files in the current directory. You can view content, get download/execute commands for Wget, Curl, or PowerShell, or filter the list using wildcards (e.g., `*.sh`).
wget 'https://lists2.roe3.org/hesk/inc/admin_functions.inc.php'
<?php
/**
*
* This file is part of HESK - PHP Help Desk Software.
*
* (c) Copyright Klemen Stirn. All rights reserved.
* https://www.hesk.com
*
* For the full copyright and license agreement information visit
* https://www.hesk.com/eula.php
*
*/
/* Check if this is a valid include */
if (!defined('IN_SCRIPT')) {die('Invalid attempt');}
// Possible fields to be displayed in ticket list
$hesk_settings['possible_ticket_list'] = array(
'id' => $hesklang['id'],
'trackid' => $hesklang['trackID'],
'dt' => $hesklang['submitted'],
'lastchange' => $hesklang['last_update'],
'category' => $hesklang['category'],
'name' => $hesklang['customer'],
'email' => $hesklang['email'],
'subject' => $hesklang['subject'],
'status' => $hesklang['status'],
'owner' => $hesklang['owner'],
'replies' => $hesklang['replies'],
'staffreplies' => $hesklang['replies'] . ' (' . $hesklang['staff'] .')',
'lastreplier' => $hesklang['last_replier'],
'time_worked' => $hesklang['ts'],
'due_date' => $hesklang['due_date']
);
define('HESK_NO_ROBOTS', true);
define('IS_ADMIN_PAGE', true);
/*** FUNCTIONS ***/
function hesk_show_column($column)
{
global $hesk_settings;
return in_array($column, $hesk_settings['ticket_list']) ? true : false;
} // END hesk_show_column()
function hesk_getHHMMSS($in)
{
$in = hesk_getTime($in);
return explode(':', $in);
} // END hesk_getHHMMSS();
function hesk_getTime($in)
{
$in = trim($in);
/* If everything is OK this simple check should return true */
if ( preg_match('/^([0-9]{2,3}):([0-5][0-9]):([0-5][0-9])$/', $in) )
{
return $in;
}
/* No joy, let's try to figure out the correct values to use... */
$h = 0;
$m = 0;
$s = 0;
/* How many parts do we have? */
$parts = substr_count($in, ':');
switch ($parts)
{
/* Only two parts, let's assume minutes and seconds */
case 1:
list($m, $s) = explode(':', $in);
break;
/* Three parts, so explode to hours, minutes and seconds */
case 2:
list($h, $m, $s) = explode(':', $in);
break;
/* Something other was entered, let's assume just minutes */
default:
$m = $in;
}
/* Make sure all inputs are integers */
$h = intval($h);
$m = intval($m);
$s = intval($s);
/* Convert seconds to minutes if 60 or more seconds */
if ($s > 59)
{
$m = floor($s / 60) + $m;
$s = intval($s % 60);
}
/* Convert minutes to hours if 60 or more minutes */
if ($m > 59)
{
$h = floor($m / 60) + $h;
$m = intval($m % 60);
}
/* MySQL accepts max time value of 838:59:59 */
if ($h > 838)
{
return '838:59:59';
}
/* That's it, let's send out formatted time string */
return str_pad($h, 2, "0", STR_PAD_LEFT) . ':' . str_pad($m, 2, "0", STR_PAD_LEFT) . ':' . str_pad($s, 2, "0", STR_PAD_LEFT);
} // END hesk_getTime();
function hesk_mergeTickets($merge_these, $merge_into)
{
global $hesk_settings, $hesklang, $hesk_db_link;
/* Target ticket must not be in the "merge these" list */
if ( in_array($merge_into, $merge_these) )
{
$merge_these = array_diff($merge_these, array( $merge_into ) );
}
/* At least 1 ticket needs to be merged with target ticket */
if ( count($merge_these) < 1 )
{
$_SESSION['error'] = $hesklang['merr1'];
return false;
}
/* Make sure target ticket exists */
$res = hesk_dbQuery("SELECT `id`,`trackid`,`category` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` WHERE `id`='".intval($merge_into)."' LIMIT 1");
if (hesk_dbNumRows($res) != 1)
{
$_SESSION['error'] = $hesklang['merr2'];
return false;
}
$ticket = hesk_dbFetchAssoc($res);
/* Make sure user has access to ticket category */
if ( ! hesk_okCategory($ticket['category'], 0) )
{
$_SESSION['error'] = $hesklang['merr3'];
return false;
}
/* Set some variables for later */
$sec_worked = 0;
$history = '';
$merged = '';
/* Get messages, replies, notes and attachments of tickets that will be merged */
foreach ($merge_these as $this_id)
{
/* Validate ID */
if ( is_array($this_id) )
{
continue;
}
$this_id = intval($this_id) or hesk_error($hesklang['id_not_valid']);
/* Get required ticket information */
$res = hesk_dbQuery("SELECT `tickets`.`id` AS `id`,`trackid`,`category`,`ticket_customers`.`customer_id` AS `customer_id`,`message`,`message_html`,`dt`,`time_worked`,`attachments`
FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` AS `tickets`
LEFT JOIN `".hesk_dbEscape($hesk_settings['db_pfix'])."ticket_to_customer` AS `ticket_customers`
ON `tickets`.`id` = `ticket_customers`.`ticket_id`
AND `ticket_customers`.`customer_type` = 'REQUESTER'
WHERE `tickets`.`id`='".intval($this_id)."' LIMIT 1");
if (hesk_dbNumRows($res) != 1)
{
continue;
}
$row = hesk_dbFetchAssoc($res);
/* Has this user access to the ticket category? */
if ( ! hesk_okCategory($row['category'], 0) )
{
continue;
}
/* Insert ticket message as a new reply to target ticket */
$customer_id = $row['customer_id'] !== null ? intval($row['customer_id']) : 'NULL';
hesk_dbQuery("INSERT INTO `".hesk_dbEscape($hesk_settings['db_pfix'])."replies` (`replyto`,`customer_id`,`message`,`message_html`,`dt`,`attachments`) VALUES ('".intval($ticket['id'])."',".$customer_id.",'".hesk_dbEscape(addslashes($row['message']))."','".hesk_dbEscape(addslashes($row['message_html']))."','".hesk_dbEscape($row['dt'])."','".hesk_dbEscape($row['attachments'])."')");
/* Update attachments */
hesk_dbQuery("UPDATE `".hesk_dbEscape($hesk_settings['db_pfix'])."attachments` SET `ticket_id`='".hesk_dbEscape($ticket['trackid'])."' WHERE `ticket_id`='".hesk_dbEscape($row['trackid'])."'");
/* Get old ticket replies and insert them as new replies */
$res = hesk_dbQuery("SELECT * FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."replies` WHERE `replyto`='".intval($row['id'])."' ORDER BY `id` ASC");
while ( $reply = hesk_dbFetchAssoc($res) )
{
$customer_id = $reply['customer_id'] !== null ? intval($reply['customer_id']) : 'NULL';
hesk_dbQuery("INSERT INTO `".hesk_dbEscape($hesk_settings['db_pfix'])."replies` (`replyto`,`message`,`message_html`,`dt`,`attachments`,`staffid`,`customer_id`,`rating`,`read`) VALUES ('".intval($ticket['id'])."','".hesk_dbEscape(addslashes($reply['message']))."','".hesk_dbEscape(addslashes($reply['message_html']))."','".hesk_dbEscape($reply['dt'])."','".hesk_dbEscape($reply['attachments'])."','".intval($reply['staffid'])."',".$customer_id.",'".intval($reply['rating'])."','".intval($reply['read'])."')");
}
/* Delete replies to the old ticket */
hesk_dbQuery("DELETE FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."replies` WHERE `replyto`='".intval($row['id'])."'");
/* Get old ticket notes and insert them as new notes */
$res = hesk_dbQuery("SELECT * FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."notes` WHERE `ticket`='".intval($row['id'])."' ORDER BY `id` ASC");
while ( $note = hesk_dbFetchAssoc($res) )
{
hesk_dbQuery("INSERT INTO `".hesk_dbEscape($hesk_settings['db_pfix'])."notes` (`ticket`,`who`,`dt`,`message`,`attachments`) VALUES ('".intval($ticket['id'])."','".intval($note['who'])."','".hesk_dbEscape($note['dt'])."','".hesk_dbEscape(addslashes($note['message']))."','".hesk_dbEscape($note['attachments'])."')");
}
/* Delete replies to the old ticket */
hesk_dbQuery("DELETE FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."notes` WHERE `ticket`='".intval($row['id'])."'");
/* Insert old ticket's requester and followers to the new tickets as followers, assuming they're not already on it */
hesk_dbQuery("INSERT INTO `".hesk_dbEscape($hesk_settings['db_pfix'])."ticket_to_customer` (`ticket_id`, `customer_id`, `customer_type`)
SELECT ".intval($ticket['id']).", `customer_id`, 'FOLLOWER'
FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."ticket_to_customer` AS `outer_ticket_to_customer`
WHERE `ticket_id` = ".intval($row['id'])."
AND NOT EXISTS (
SELECT 1
FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."ticket_to_customer` AS `inner_ticket_to_customer`
WHERE `inner_ticket_to_customer`.`ticket_id` = ".intval($ticket['id'])."
AND `inner_ticket_to_customer`.`customer_id` = `outer_ticket_to_customer`.`customer_id`
)");
/* Delete old ticket's customer mappings */
hesk_dbQuery("DELETE FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."ticket_to_customer`
WHERE `ticket_id` = ".intval($row['id']));
/* Delete old ticket */
hesk_dbQuery("DELETE FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` WHERE `id`='".intval($row['id'])."'");
/* Log that ticket has been merged */
$history .= sprintf($hesklang['thist13'],hesk_date(),$row['trackid'],addslashes($_SESSION['name']).' ('.$_SESSION['user'].')');
/* Add old ticket ID to target ticket "merged" field */
$merged .= '#' . $row['trackid'];
/* Convert old ticket "time worked" to seconds and add to $sec_worked variable */
list ($hr, $min, $sec) = explode(':', $row['time_worked']);
$sec_worked += (((int)$hr) * 3600) + (((int)$min) * 60) + ((int)$sec);
}
/* Convert seconds to HHH:MM:SS */
$sec_worked = hesk_getTime('0:'.$sec_worked);
// Get number of replies
$total = 0;
$staffreplies = 0;
$res = hesk_dbQuery("SELECT COUNT(*) as `cnt`, (CASE WHEN `staffid` = 0 THEN 0 ELSE 1 END) AS `staffcnt` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."replies` WHERE `replyto`=".intval($ticket['id'])." GROUP BY `staffcnt`");
while ( $row = hesk_dbFetchAssoc($res) )
{
$total += $row['cnt'];
$staffreplies += ($row['staffcnt'] ? $row['cnt'] : 0);
}
$replies_sql = " `replies`={$total}, `staffreplies`={$staffreplies} , ";
// Get first staff reply
if ($staffreplies)
{
$res = hesk_dbQuery("SELECT `dt`, `staffid` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."replies` WHERE `replyto`=".intval($ticket['id'])." AND `staffid`>0 ORDER BY `dt` ASC LIMIT 1");
$reply = hesk_dbFetchAssoc($res);
$replies_sql .= " `firstreply`='".hesk_dbEscape($reply['dt'])."', `firstreplyby`=".intval($reply['staffid'])." , ";
}
/* Update history (log) and merged IDs of target ticket */
hesk_dbQuery("UPDATE `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` SET $replies_sql `time_worked`=ADDTIME(`time_worked`, '".hesk_dbEscape($sec_worked)."'), `merged`=CONCAT(`merged`,'".hesk_dbEscape($merged . '#')."'), `history`=CONCAT(`history`,'".hesk_dbEscape($history)."') WHERE `id`='".intval($merge_into)."'");
return true;
} // END hesk_mergeTickets()
function hesk_updateStaffDefaults()
{
global $hesk_settings, $hesklang;
// Demo mode
if ( defined('HESK_DEMO') )
{
return true;
}
// Remove the part that forces saving as default - we don't need it every time
$default_list = str_replace('&def=1','',$_SERVER['QUERY_STRING']);
// Update database
$res = hesk_dbQuery("UPDATE `".hesk_dbEscape($hesk_settings['db_pfix'])."users` SET `default_list`='".hesk_dbEscape($default_list)."' WHERE `id`='".intval($_SESSION['id'])."'");
// Update session values so the changes take effect immediately
$_SESSION['default_list'] = $default_list;
return true;
} // END hesk_updateStaffDefaults()
function hesk_makeJsString($in)
{
return addslashes(preg_replace("/\s+/",' ',$in));
} // END hesk_makeJsString()
function hesk_json_encode_for_js($in)
{
$json = json_encode((string) $in, JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_AMP | JSON_HEX_QUOT);
return $json === false ? '""' : $json;
} // END hesk_json_encode_for_js()
function hesk_json_encode_jsString($str)
{
$str = str_replace('<br />', '', (string) $str);
$from = array('/\<a href="mailto\:([^"]*)"\>([^\<]*)\<\/a\>/i', '/\<a href="([^"]*)" target="_blank"\>([^\<]*)\<\/a\>/i');
$to = array("$1", "$1");
return hesk_json_encode_for_js(preg_replace($from, $to, $str));
} // END hesk_json_encode_jsString()
function hesk_checkNewMail()
{
global $hesk_settings, $hesklang;
$res = hesk_dbQuery("SELECT COUNT(*) FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."mail` WHERE `to`='".intval($_SESSION['id'])."' AND `read`='0' AND `deletedby`!='".intval($_SESSION['id'])."' ");
$num = hesk_dbResult($res,0,0);
return $num;
} // END hesk_checkNewMail()
function hesk_dateToString($dt, $returnName=1, $returnTime=0, $returnMonth=0, $from_database=false)
{
global $hesk_settings, $hesklang;
$dt = strtotime($dt);
// Adjust MySQL time if different from PHP time
if ($from_database)
{
if ( ! defined('MYSQL_TIME_DIFF') )
{
define('MYSQL_TIME_DIFF', time()-hesk_dbTime() );
}
if (MYSQL_TIME_DIFF != 0)
{
$dt += MYSQL_TIME_DIFF;
}
}
list($y,$m,$n,$d,$G,$i,$s) = explode('-', date('Y-n-j-w-G-i-s', $dt) );
$m = $hesklang['m'.$m];
$d = $hesklang['d'.$d];
if ($returnName)
{
return "$d, $m $n, $y";
}
if ($returnTime)
{
return "$d, $m $n, $y $G:$i:$s";
}
if ($returnMonth)
{
return "$m $y";
}
return "$m $n, $y";
} // End hesk_dateToString()
function hesk_getCategoriesArray($kb = 0) {
global $hesk_settings, $hesklang, $hesk_db_link;
$categories = array();
if ($kb)
{
$result = hesk_dbQuery('SELECT `id`, `name` FROM `'.hesk_dbEscape($hesk_settings['db_pfix']).'kb_categories` ORDER BY `cat_order` ASC');
}
else
{
$result = hesk_dbQuery('SELECT `id`, `name` FROM `'.hesk_dbEscape($hesk_settings['db_pfix']).'categories` ORDER BY `cat_order` ASC');
}
while ($row=hesk_dbFetchAssoc($result))
{
$categories[$row['id']] = $row['name'];
}
return $categories;
} // END hesk_getCategoriesArray()
function hesk_getHTML($in)
{
global $hesk_settings, $hesklang;
$replace_from = array("\t","<?","?>","$","<%","%>");
$replace_to = array("","<?","?>","\$","<%","%>");
$in = trim($in);
$in = str_replace($replace_from,$replace_to,$in);
$in = preg_replace('/\<script(.*)\>(.*)\<\/script\>/Uis',"<script$1></script>",$in);
$in = preg_replace('/\<\!\-\-(.*)\-\-\>/Uis',"<!-- comments have been removed -->",$in);
if (HESK_SLASH === true)
{
$in = addslashes($in);
}
$in = str_replace('\"','"',$in);
return $in;
} // END hesk_getHTML()
function hesk_autoLogin($noredirect=0)
{
global $hesk_settings, $hesklang, $hesk_db_link;
if (!$hesk_settings['autologin']) {
return false;
}
if (empty($remember = hesk_COOKIE('hesk_remember')) || substr_count($remember, ':') !== 1) {
return false;
}
// Login cookies exist, now lets limit brute force attempts
hesk_limitBfAttempts();
// Admin login URL
$url = $hesk_settings['hesk_url'] . '/' . $hesk_settings['admin_dir'] . '/index.php?a=login¬ice=1';
// Get and verify authentication tokens
list($selector, $authenticator) = explode(':', $remember);
$authenticator = base64_decode($authenticator);
if (strlen($authenticator) > 256) {
hesk_setcookie('hesk_remember', '');
header('Location: '.$url);
exit();
}
$result = hesk_dbQuery('SELECT * FROM `'.$hesk_settings['db_pfix']."auth_tokens` WHERE `selector` = '".hesk_dbEscape($selector)."' AND `expires` > NOW() AND `user_type` = 'STAFF' LIMIT 1");
if (hesk_dbNumRows($result) != 1) {
hesk_setcookie('hesk_remember', '');
header('Location: '.$url);
exit();
}
$auth = hesk_dbFetchAssoc($result);
if ( ! hash_equals($auth['token'], hash('sha256', $authenticator))) {
hesk_setcookie('hesk_remember', '');
header('Location: '.$url);
exit();
}
// Token OK, let's regenerate session ID and get user data
hesk_session_regenerate_id();
$result = hesk_dbQuery('SELECT * FROM `'.$hesk_settings['db_pfix']."users` WHERE `id` = ".intval($auth['user_id'])." AND `active` = 1 LIMIT 1");
if (hesk_dbNumRows($result) != 1) {
hesk_setcookie('hesk_remember', '');
header('Location: '.$url);
exit();
}
$row = hesk_dbFetchAssoc($result);
// Auto-login must not preserve a previously elevated session
hesk_cleanSessionVars(array('elevated', 'elevator_target'));
foreach ($row as $k => $v) {
if ($k == 'pass') {
continue;
}
$_SESSION[$k] = $v;
}
$user = $row['user'];
define('HESK_USER', $user);
// Each token should only be used once, so update the old one with a new one
$selector = base64_encode(random_bytes(9));
$authenticator = random_bytes(33);
hesk_dbQuery("UPDATE `".hesk_dbEscape($hesk_settings['db_pfix'])."auth_tokens` SET `selector`='".hesk_dbEscape($selector)."', `token` = '".hesk_dbEscape(hash('sha256', $authenticator))."', `created` = NOW() WHERE `id` = ".intval($auth['id']));
hesk_setcookie('hesk_remember', $selector.':'.base64_encode($authenticator), strtotime('+1 year'));
// Set a tag that will be used to expire sessions after username or password change
$_SESSION['session_verify'] = hesk_activeSessionCreateTag($user, $row['pass']);
/* Login successful, clean brute force attempts */
hesk_cleanBfAttempts();
/* Get allowed categories */
if (empty($_SESSION['isadmin']))
{
$_SESSION['categories']=explode(',',$_SESSION['categories']);
}
/* Close any old tickets here so Cron jobs aren't necessary */
if ($hesk_settings['autoclose'])
{
$revision = sprintf($hesklang['thist3'],hesk_date(),$hesklang['auto']);
$dt = date('Y-m-d H:i:s',time() - $hesk_settings['autoclose']*86400);
// Notify customer of closed ticket?
if ($hesk_settings['notify_closed'])
{
// Get list of tickets
$result = hesk_dbQuery("SELECT * FROM `".$hesk_settings['db_pfix']."tickets` WHERE `status` = '2' AND `lastchange` <= '".hesk_dbEscape($dt)."' ");
if (hesk_dbNumRows($result) > 0)
{
global $ticket;
// Load required functions?
if ( ! function_exists('hesk_notifyCustomer') )
{
require(HESK_PATH . 'inc/email_functions.inc.php');
}
while ($ticket = hesk_dbFetchAssoc($result))
{
$ticket['dt'] = hesk_date($ticket['dt'], true);
$ticket['lastchange'] = hesk_date($ticket['lastchange'], true);
$ticket = hesk_ticketToPlain($ticket, 1, 0);
hesk_notifyCustomer('ticket_closed');
}
}
}
// Update ticket statuses and history in database
hesk_dbQuery("UPDATE `".$hesk_settings['db_pfix']."tickets` SET `status`='3', `closedat`=NOW(), `closedby`='-1', `history`=CONCAT(`history`,'".hesk_dbEscape($revision)."') WHERE `status` = '2' AND `lastchange` <= '".hesk_dbEscape($dt)."' ");
}
/* If session expired while a HESK page is open just continue using it, don't redirect */
if ($noredirect)
{
return true;
}
/* Redirect to the destination page */
header('Location: ' . hesk_verifyGoto() );
exit();
} // END hesk_autoLogin()
function hesk_isLoggedIn()
{
global $hesk_settings;
$referer = hesk_input($_SERVER['REQUEST_URI']);
$referer = str_replace('&','&',$referer);
// Admin login URL
$url = $hesk_settings['hesk_url'] . '/' . $hesk_settings['admin_dir'] . '/index.php?a=login¬ice=1&goto='.urlencode($referer);
// A password reset link must never be treated as a full staff login.
// profile.php handles reset-only sessions before calling hesk_isLoggedIn().
if ( ! empty($_SESSION['password_reset']))
{
hesk_session_stop();
header('Location: '.$url);
exit();
}
if ( empty($_SESSION['id']) || empty($_SESSION['session_verify']))
{
if ($hesk_settings['autologin'] && hesk_autoLogin(1) )
{
// Users online
if ($hesk_settings['online'])
{
require(HESK_PATH . 'inc/users_online.inc.php');
hesk_initOnline($_SESSION['id']);
}
return true;
}
hesk_session_stop();
header('Location: '.$url);
exit();
}
else
{
// hesk_session_regenerate_id();
// Let's make sure access data is up-to-date
$res = hesk_dbQuery( "SELECT `id`,`user`, `pass`, `isadmin`, `categories`, `heskprivileges`, `signature` FROM `".$hesk_settings['db_pfix']."users` WHERE `id` = '".intval($_SESSION['id'])."' AND `active` = 1 LIMIT 1" );
// Exit if user not found
if (hesk_dbNumRows($res) != 1)
{
hesk_session_stop();
header('Location: '.$url);
exit();
}
// Fetch results from database
$me = hesk_dbFetchAssoc($res);
// Verify this session is still valid
if ( ! hesk_activeSessionValidate($me['user'], $me['pass'], $_SESSION['session_verify']) )
{
hesk_session_stop();
header('Location: '.$url);
exit();
}
// Update session variables as needed
if ($me['isadmin'] == 1)
{
$_SESSION['isadmin'] = 1;
}
else
{
$_SESSION['isadmin'] = 0;
$_SESSION['categories'] = explode(',', $me['categories']);
$_SESSION['heskprivileges'] = $me['heskprivileges'];
hesk_setPermissionGroupAccess($me['id']);
}
$_SESSION['signature'] = $me['signature'];
// Users online
if ($hesk_settings['online'])
{
require(HESK_PATH . 'inc/users_online.inc.php');
hesk_initOnline($_SESSION['id']);
}
return true;
}
} // END hesk_isLoggedIn()
function hesk_setPermissionGroupAccess($user_id) {
global $hesk_settings;
// Set permissions obtained via permission groups
$permission_group_categories_rs = hesk_dbQuery("SELECT DISTINCT `category_id` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."permission_group_categories`
WHERE `group_id` IN (
SELECT `group_id`
FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."permission_group_members`
WHERE `user_id` = ".intval($user_id).
")");
while ($row = hesk_dbFetchAssoc($permission_group_categories_rs)) {
$_SESSION['categories'][] = $row['category_id'];
}
$_SESSION['categories'] = array_unique($_SESSION['categories']);
$permission_group_features_rs = hesk_dbQuery("SELECT DISTINCT `feature` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."permission_group_features`
WHERE `group_id` IN (
SELECT `group_id`
FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."permission_group_members`
WHERE `user_id` = ".intval($user_id).
")");
$_SESSION['heskprivileges'] = explode(',', $_SESSION['heskprivileges']);
while ($row = hesk_dbFetchAssoc($permission_group_features_rs)) {
$_SESSION['heskprivileges'][] = $row['feature'];
}
$_SESSION['heskprivileges'] = implode(',', array_unique($_SESSION['heskprivileges']));
}
function hesk_Pass2Hash($plaintext) {
// This is a LEGACY function, only used to check and update legacy passwords
// Use hesk_password_hash/hesk_password_verify functions instead!
$majorsalt = '';
$len = strlen($plaintext);
for ($i=0;$i<$len;$i++)
{
$majorsalt .= sha1(substr($plaintext,$i,1));
}
$corehash = sha1($majorsalt);
return $corehash;
} // END hesk_Pass2Hash()
function hesk_formatDate($dt, $from_database=true)
{
$dt=hesk_date($dt, $from_database);
$dt=str_replace(' ','<br />',$dt);
return $dt;
} // End hesk_formatDate()
function hesk_jsString($str)
{
$str = addslashes($str);
$str = str_replace('<br />' , '' , $str);
$from = array("/\r\n|\n|\r/", '/\<a href="mailto\:([^"]*)"\>([^\<]*)\<\/a\>/i', '/\<a href="([^"]*)" target="_blank"\>([^\<]*)\<\/a\>/i');
$to = array("\\r\\n' + \r\n'", "$1", "$1");
return preg_replace($from,$to,$str);
} // END hesk_jsString()
function hesk_myOwnership($consider_collaborators = false)
{
// Admins can see all tickets
if ( ! empty($_SESSION['isadmin']) )
{
return '1';
}
// For staff, let's check permissions
$can_view_unassigned = hesk_checkPermission('can_view_unassigned',0);
$can_view_ass_others = hesk_checkPermission('can_view_ass_others',0);
$can_view_ass_by = hesk_checkPermission('can_view_ass_by', 0);
// Can view all tickets, regrdless of ownership
if ($can_view_unassigned == 1 && $can_view_ass_others == 1) {
return '1';
}
$sql_ownership = '';
// Can view assigned to me + unassigned
if ($can_view_unassigned == 1 && $can_view_ass_others == 0 && $can_view_ass_by == 0) {
$sql_ownership .= " `owner` IN ('0', '" . intval($_SESSION['id']) . "') ";
}
// Can view assigned to me + unassigned + tickets I assigned to others
elseif ($can_view_unassigned == 1 && $can_view_ass_others == 0 && $can_view_ass_by == 1) {
$sql_ownership .= " (`owner` IN ('0', '" . intval($_SESSION['id']) . "') OR `assignedby` = " . intval($_SESSION['id']) . ") ";
}
// Can view assigned to me + assigned to others
elseif ($can_view_unassigned == 0 && $can_view_ass_others == 1) {
$sql_ownership .= " `owner` != 0 ";
}
// Can view assigned to me + tickets I assigned to others
elseif ($can_view_unassigned == 0 && $can_view_ass_others == 0 && $can_view_ass_by == 1) {
$sql_ownership .= " (`owner` = " . intval($_SESSION['id']) . " OR `assignedby` = " . intval($_SESSION['id']) . ") ";
}
// Can only view assigned to me
elseif ($can_view_unassigned == 0 && $can_view_ass_others == 0 && $can_view_ass_by == 0) {
$sql_ownership .= " `owner` = " . intval($_SESSION['id']) . " ";
}
// Must be an internal error
else {
die('Invalid view attempt (1)');
}
// Add a collaborator check for certain use cases
if ($consider_collaborators) {
return " ($sql_ownership OR `w`.`user_id`= " . intval($_SESSION['id']) . ") ";
} else {
return $sql_ownership;
}
} // END hesk_myOwnership()
function hesk_myCategories($what='category')
{
if ( ! empty($_SESSION['isadmin']) )
{
return '1';
}
else
{
return " `".hesk_dbEscape($what)."` IN ('" . implode("','", array_map('intval', $_SESSION['categories']) ) . "')";
}
} // END hesk_myCategories()
function hesk_verifyStaffTicketAccess($trackingID, $ticket = null)
{
global $hesk_settings, $hesklang;
// Staff must be allowed to view tickets in general
hesk_checkPermission('can_view_tickets');
// Use an already-loaded ticket when possible to avoid another query
if ( ! is_array($ticket) ||
! isset($ticket['id'], $ticket['trackid'], $ticket['category'], $ticket['owner'], $ticket['assignedby']) ||
$ticket['trackid'] != $trackingID)
{
$res = hesk_dbQuery("SELECT `id`, `trackid`, `category`, `owner`, `assignedby` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` WHERE `trackid`='".hesk_dbEscape($trackingID)."' LIMIT 1");
if (hesk_dbNumRows($res) != 1)
{
hesk_error($hesklang['ticket_not_found']);
}
$ticket = hesk_dbFetchAssoc($res);
}
$collaborators = hesk_getTicketsCollaboratorIDs($ticket['id']);
$am_I_collaborator = in_array($_SESSION['id'], $collaborators);
// Permission to view this ticket based on owner / assignment / collaboration
if ($ticket['owner'] && $ticket['owner'] != $_SESSION['id'] && ! hesk_checkPermission('can_view_ass_others', 0) && ! $am_I_collaborator)
{
// Maybe this user is allowed to view tickets he/she assigned?
if ( ! hesk_checkPermission('can_view_ass_by', 0) || $ticket['assignedby'] != $_SESSION['id'])
{
hesk_error($hesklang['ycvtao']);
}
}
if ( ! $ticket['owner'] && ! hesk_checkPermission('can_view_unassigned', 0) && ! $am_I_collaborator)
{
hesk_error($hesklang['ycovtay']);
}
// Get category ID; if this category has been deleted use the default category with ID 1
$result = hesk_dbQuery("SELECT `id` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."categories` WHERE `id`='".intval($ticket['category'])."' LIMIT 1");
if (hesk_dbNumRows($result) != 1)
{
$result = hesk_dbQuery("SELECT `id` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."categories` WHERE `id`='1' LIMIT 1");
}
$category = hesk_dbFetchAssoc($result);
// Is this user allowed to view tickets inside this category?
hesk_okCategory($category['id']);
return $ticket;
} // END hesk_verifyStaffTicketAccess()
function hesk_okCategory($cat,$error=1,$user_isadmin=false,$user_cat=false)
{
global $hesklang;
/* Checking for current user or someone else? */
if ($user_isadmin === false)
{
$user_isadmin = $_SESSION['isadmin'];
}
if ($user_cat === false)
{
$user_cat = $_SESSION['categories'];
}
/* Is admin? */
if ($user_isadmin)
{
return true;
}
/* Staff with access? */
elseif (in_array($cat,$user_cat))
{
return true;
}
/* No access */
else
{
if ($error)
{
hesk_error($hesklang['not_authorized_tickets']);
}
else
{
return false;
}
}
} // END hesk_okCategory()
function hesk_checkPermission($feature,$showerror=1) {
global $hesklang;
/* Admins have full access to all features */
if ( isset($_SESSION['isadmin']) && $_SESSION['isadmin'])
{
return true;
}
/* Check other staff for permissions */
if ( isset($_SESSION['heskprivileges']) && strpos($_SESSION['heskprivileges'], $feature) === false)
{
if ($showerror)
{
hesk_error($hesklang['no_permission'].'<p> </p><p align="center"><a href="index.php">'.$hesklang['click_login'].'</a>');
}
else
{
return false;
}
}
else
{
return true;
}
} // END hesk_checkPermission()
function hesk_purge_cache($type = '', $expire_after_seconds = 0)
{
global $hesk_settings;
if ( function_exists('opcache_reset') )
{
opcache_reset();
}
$cache_dir = dirname(dirname(__FILE__)).'/'.$hesk_settings['cache_dir'].'/';
if ( ! is_dir($cache_dir))
{
return false;
}
switch ($type)
{
case 'export':
$files = glob($cache_dir.'hesk_export_*', GLOB_NOSORT);
break;
case 'status':
$files = glob($cache_dir.'status_*', GLOB_NOSORT);
break;
case 'priority':
$files = glob($cache_dir.'priority_*', GLOB_NOSORT);
break;
case 'cf':
$files = glob($cache_dir.'cf_*', GLOB_NOSORT);
break;
case 'kb':
$files = array($cache_dir.'kb.cache.php');
break;
default:
hesk_rrmdir(rtrim($cache_dir, '/'), true);
return true;
}
if (is_array($files))
{
array_walk($files, 'hesk_unlink_callable', $expire_after_seconds);
}
return true;
} // END hesk_purge_cache()
function hesk_rrmdir($dir, $keep_top_level=false)
{
if ( ! is_dir($dir)) {
return false;
}
$files = $keep_top_level ? array_diff(scandir($dir), array('.','..','index.htm')) : array_diff(scandir($dir), array('.','..'));
foreach ($files as $file)
{
(is_dir("$dir/$file")) ? hesk_rrmdir("$dir/$file") : @unlink("$dir/$file");
}
return $keep_top_level ? true : @rmdir($dir);
} // END hesk_rrmdir()
function hesk_deleteTicketsForCustomer($customer_id) {
global $hesk_settings;
$sql = "SELECT `tickets`.`id`, `tickets`.`trackid` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` AS `tickets`
INNER JOIN `".hesk_dbEscape($hesk_settings['db_pfix'])."ticket_to_customer` AS `ticket_to_customer`
ON `ticket_to_customer`.`ticket_id` = `tickets`.`id`
WHERE `ticket_to_customer`.`customer_id` = ".intval($customer_id)."
AND `ticket_to_customer`.`customer_type` = 'REQUESTER'";
$tickets_rs = hesk_dbQuery($sql);
while ($ticket = hesk_dbFetchAssoc($tickets_rs)) {
hesk_fullyDeleteTicket($ticket['id'], $ticket['trackid']);
}
}
function hesk_fullyDeleteTicket($ticket_id, $ticket_trackid)
{
global $hesk_settings;
/* Delete attachment files */
$res = hesk_dbQuery("SELECT * FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."attachments` WHERE `ticket_id`='".hesk_dbEscape($ticket_trackid)."'");
if (hesk_dbNumRows($res))
{
$hesk_settings['server_path'] = dirname(dirname(__FILE__));
while ($file = hesk_dbFetchAssoc($res))
{
hesk_unlink($hesk_settings['server_path'].'/'.$hesk_settings['attach_dir'].'/'.$file['saved_name']);
}
}
/* Delete attachments info from the database */
hesk_dbQuery("DELETE FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."attachments` WHERE `ticket_id`='".hesk_dbEscape($ticket_trackid)."'");
/* Delete the ticket */
hesk_dbQuery("DELETE FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` WHERE `id`='".intval($ticket_id)."'");
/* Delete replies to the ticket */
hesk_dbQuery("DELETE FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."replies` WHERE `replyto`='".intval($ticket_id)."'");
/* Delete ticket notes */
hesk_dbQuery("DELETE FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."notes` WHERE `ticket`='".intval($ticket_id)."'");
/* Delete ticket reply drafts */
hesk_dbQuery("DELETE FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."reply_drafts` WHERE `ticket`=".intval($ticket_id));
/* Delete ticket/customer mappings */
hesk_dbQuery("DELETE FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."ticket_to_customer` WHERE `ticket_id` = ".intval($ticket_id));
/* Delete bookmarks */
hesk_dbQuery("DELETE FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."bookmarks` WHERE `ticket_id` = ".intval($ticket_id));
/* Delete ticket/email ID mappings */
hesk_dbQuery("DELETE FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."email_id_to_ticket` WHERE `ticket_id` = ".intval($ticket_id));
return true;
}
function hesk_isTicketBookmarked($ticket_id, $user_id)
{
global $hesk_settings, $hesklang, $hesk_db_link;
$result = hesk_dbQuery('SELECT `id` FROM `'.hesk_dbEscape($hesk_settings['db_pfix']).'bookmarks` WHERE `ticket_id`='.intval($ticket_id).' AND `user_id`='.intval($user_id).' LIMIT 1');
return hesk_dbNumRows($result);
} // END hesk_isTicketBookmarked()
function hesk_json_exit($status = 'Error', $data = '') {
$json_data = [
'status' => $status,
'data' => $data,
];
echo json_encode($json_data);
exit;
} // END hesk_json_exit()
function hesk_mergeCustomers($merge_these, $merge_into)
{
global $hesk_settings, $hesklang, $hesk_db_link;
// Target customer must not be in the "merge these" list
if ( in_array($merge_into, $merge_these) ) {
$merge_these = array_diff($merge_these, array( $merge_into ) );
}
// At least 1 customer needs to be merged with target customer
if ( count($merge_these) < 1 ) {
$_SESSION['error'] = $hesklang['merge_more_error'];
return false;
}
$merge_into = intval($merge_into);
// Make sure target customer exists
$res = hesk_dbQuery("SELECT `id` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."customers` WHERE `id`={$merge_into} LIMIT 1");
if (hesk_dbNumRows($res) != 1) {
$_SESSION['error'] = $hesklang['merge_target_error'];
return false;
}
foreach ($merge_these as $this_id)
{
// Validate ID
if ( is_array($this_id) ) {
continue;
}
$this_id = intval($this_id) or hesk_error($hesklang['id_not_valid']);
// Update customer tickets to new customer
hesk_dbQuery("UPDATE `".hesk_dbEscape($hesk_settings['db_pfix'])."ticket_to_customer` SET `customer_id`={$merge_into} WHERE `customer_id`={$this_id}");
// Migrate ticket replies to new customer
hesk_dbQuery("UPDATE `".hesk_dbEscape($hesk_settings['db_pfix'])."replies` SET `customer_id`={$merge_into} WHERE `customer_id`={$this_id}");
// Remove old customer information
hesk_dbQuery("DELETE FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."customers` WHERE `id`={$this_id}");
}
return true;
} // END hesk_mergeCustomers()
function hesk_getUserIdsWithAccessToFeatureAndCategory($feature = null, $category = null)
{
global $hesk_settings;
// Need to provide at least one of the two
if ($feature === null && $category === null) {
return [];
}
$access_parts = [];
if ($feature !== null) {
$feature = hesk_dbEscape($feature);
$access_parts[] = "(
FIND_IN_SET('{$feature}', `user`.`heskprivileges`) > 0
OR EXISTS (
SELECT 1
FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."permission_group_members` AS `member_feature`
INNER JOIN `".hesk_dbEscape($hesk_settings['db_pfix'])."permission_group_features` AS `feature`
ON `member_feature`.`group_id` = `feature`.`group_id`
WHERE `user`.`id` = `member_feature`.`user_id`
AND `feature`.`feature` = '{$feature}'
)
)";
}
if ($category !== null) {
$category = intval($category);
$access_parts[] = "(
FIND_IN_SET('{$category}', `user`.`categories`) > 0
OR EXISTS (
SELECT 1
FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."permission_group_members` AS `member_category`
INNER JOIN `".hesk_dbEscape($hesk_settings['db_pfix'])."permission_group_categories` AS `category`
ON `member_category`.`group_id` = `category`.`group_id`
WHERE `user`.`id` = `member_category`.`user_id`
AND `category`.`category_id` = {$category}
)
)";
}
$access_sql = implode(' AND ', $access_parts);
$users_rs = hesk_dbQuery("SELECT `user`.`id`
FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."users` AS `user`
WHERE `active` = 1 AND (`isadmin` = '1' OR ({$access_sql}))");
$users = [];
while ($row = hesk_dbFetchAssoc($users_rs)) {
$users[] = intval($row['id']);
}
return $users;
} // END hesk_getUserIdsWithAccessToFeatureAndCategory()
function hesk_getCategoriesForUser($user_id)
{
global $hesk_settings;
$categories = [];
$sanitized_user_id = intval($user_id);
$base_categories_rs = hesk_dbQuery("SELECT `categories` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."users` WHERE `id`='{$sanitized_user_id}' AND `active` = 1 LIMIT 1");
while ($row = hesk_dbFetchAssoc($base_categories_rs)) {
$categories = explode(',', $row['categories']);
}
$categories = array_map(function($category) { return intval($category); }, $categories);
$pg_categories = hesk_dbQuery("SELECT DISTINCT `category_id`
FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."permission_group_categories`
WHERE `group_id` IN (
SELECT `group_id`
FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."permission_group_members`
WHERE `user_id` = {$sanitized_user_id}
)");
while ($row = hesk_dbFetchAssoc($pg_categories)) {
$category_id = intval($row['category_id']);
if (!in_array($category_id, $categories)) {
$categories[] = $category_id;
}
}
return $categories;
} // END hesk_getCategoriesForUser()
function hesk_getFeaturesForUser($user_id)
{
global $hesk_settings;
$features = [];
$sanitized_user_id = intval($user_id);
$base_features_rs = hesk_dbQuery("SELECT `heskprivileges` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."users` WHERE `id`='{$sanitized_user_id}' AND `active` = 1 LIMIT 1");
while ($row = hesk_dbFetchAssoc($base_features_rs)) {
$features = explode(',', $row['heskprivileges']);
}
$pg_features = hesk_dbQuery("SELECT DISTINCT `feature`
FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."permission_group_features`
WHERE `group_id` IN (
SELECT `group_id`
FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."permission_group_members`
WHERE `user_id` = {$sanitized_user_id}
)");
while ($row = hesk_dbFetchAssoc($pg_features)) {
if (!in_array($row['feature'], $features)) {
$features[] = $row['feature'];
}
}
return $features;
} // END hesk_getFeaturesForUser()
wget 'https://lists2.roe3.org/hesk/inc/admin_settings_demo.inc.php'
<?php
/**
*
* This file is part of HESK - PHP Help Desk Software.
*
* (c) Copyright Klemen Stirn. All rights reserved.
* https://www.hesk.com
*
* For the full copyright and license agreement information visit
* https://www.hesk.com/eula.php
*
*/
/* Check if this is a valid include */
if (!defined('IN_SCRIPT')) {die('Invalid attempt');}
// Override sensitive settings in the demo mode
$hesk_settings['db_host'] = $hesklang['hdemo'];
$hesk_settings['db_name'] = $hesklang['hdemo'];
$hesk_settings['db_user'] = $hesklang['hdemo'];
$hesk_settings['db_pass'] = $hesklang['hdemo'];
$hesk_settings['db_pfix'] = $hesklang['hdemo'];
$hesk_settings['url_key'] = $hesklang['hdemo'];
$hesk_settings['smtp_host_name'] = $hesklang['hdemo'];
$hesk_settings['smtp_user'] = $hesklang['hdemo'];
$hesk_settings['smtp_password'] = $hesklang['hdemo'];
$hesk_settings['pop3_host_name'] = $hesklang['hdemo'];
$hesk_settings['pop3_user'] = $hesklang['hdemo'];
$hesk_settings['pop3_password'] = $hesklang['hdemo'];
$hesk_settings['imap_host_name'] = $hesklang['hdemo'];
$hesk_settings['imap_user'] = $hesklang['hdemo'];
$hesk_settings['imap_password'] = $hesklang['hdemo'];
$hesk_settings['recaptcha_public_key'] = $hesklang['hdemo'];
$hesk_settings['recaptcha_private_key'] = $hesklang['hdemo'];
wget 'https://lists2.roe3.org/hesk/inc/admin_settings_language.inc.php'
<?php
/**
*
* This file is part of HESK - PHP Help Desk Software.
*
* (c) Copyright Klemen Stirn. All rights reserved.
* https://www.hesk.com
*
* For the full copyright and license agreement information visit
* https://www.hesk.com/eula.php
*
*/
/* Check if this is a valid include */
if (!defined('IN_SCRIPT')) {die('Invalid attempt');}
?>
<button type="button" class="btn btn--blue-border show_language" ripple="ripple">
<?php echo $hesklang['click_to_show_available_language']; ?> <div class="ripple--container"></div></button>
<div class="inner_content_lan">
<div class="lan-msg"></div>
</div>
<input type="hidden" name="current_hesk_version" id="current_hesk_version" value="<?php echo $hesk_settings['hesk_version'];?>">
<input type="hidden" name="install_lan" id="install_lan" value="<?php echo $hesklang['install_lan']; ?>">
<input type="hidden" name="remove_lan" id="remove_lan" value="<?php echo $hesklang['remove_lan']; ?>">
<input type="hidden" name="upgrade_lan" id="upgrade_lan" value="<?php echo $hesklang['upgrade_lan']; ?>">
<input type="hidden" id="ajax_action" value="0">
<input type="hidden" id="hesk_ajax_token" value="<?php hesk_token_echo(); ?>">
<div class="append_lan_html"></div>
<script>
var title_lan,description_lan,completed_lan,success_install_lan_txt,error_install_lan_txt,success_remove_lan_txt,error_remove_lan_txt,remove_default_language_error,no_language_availble;
var upgrade_lan,success_upgrade_lan_txt,error_upgrade_lan_txt,success_txt,error_txt;
var close_html = '<a href="javascript:;" class="close" data-dismiss="alert" aria-label="<?php echo $hesklang['close_button_text']; ?>">×</a>';
title_lan = "<?php echo $hesklang['title_lan'] ?>";
description_lan = "<?php echo $hesklang['description_lan'] ?>";
completed_lan = "<?php echo $hesklang['completed_lan'] ?>";
success_install_lan_txt = "<?php echo $hesklang['success_install_lan_txt']; ?>" + close_html;
error_install_lan_txt = "<?php echo $hesklang['error_install_lan_txt'].". <a target='_blank' href='https://www.hesk.com/knowledgebase/?article=89'>".$hesklang['click_for_manual_step']."</a>" ?>" + close_html;
success_remove_lan_txt = "<?php echo $hesklang['success_remove_lan_txt'] ?>" + close_html;
error_remove_lan_txt = "<?php $hesklang['error_remove_lan_txt'] ?>" + close_html;
remove_default_language_error = "<?php echo $hesklang['sm_error'].": ".$hesklang['remove_default_language_error'] ?>" + close_html;
no_language_availble = "<?php echo $hesklang['sm_error'].": ".$hesklang['no_language_availble'] .". <a target='_blank' href='https://www.hesk.com/knowledgebase/?article=89'>".$hesklang['click_for_manual_step']."</a>" ?>" + close_html;
upgrade_lan = "<?php echo $hesklang['upgrade_lan'] ?>";
success_upgrade_lan_txt = "<?php echo $hesklang['success_upgrade_lan_txt']; ?>" + close_html;
error_upgrade_lan_txt = "<?php echo $hesklang['error_upgrade_lan_txt'].". <a target='_blank' href='https://www.hesk.com/knowledgebase/?article=89'>".$hesklang['click_for_manual_step']."</a>" ?>" + close_html;
success_txt = "<?php echo $hesklang['sm_success'].": "?>";
error_txt = "<?php echo $hesklang['sm_error'].": "?>";
var unsaved_action = 0;
// Show available languages
$("body").on("click",".show_language",function(){
if($("#ajax_action").val() == "0"){
$("#overlay_loader").fadeIn(300);
$.ajax({
url:"ajax/language_list.php",
type: "post",
dataType: 'json',
data: {},
success:function(result){
$("#overlay_loader").fadeOut(300);
//Append language layout
if(result.status == "Success"){
$(".append_lan_html").html("");
$(".append_lan_html").append(result.data);
$("#ajax_action").val("1");
$(".show_language").addClass("d-none");
handleError();
}else{
$(".lan-msg").html(no_language_availble);
$(".lan-msg").addClass("error-msg");
}
}
});
}
});
// Install a Language
$("body").on("click",".install_language",function(){
<?php if (defined('HESK_DEMO')): ?>
$(".lan-msg").removeClass("warning-msg");
$(".lan-msg").html("").fadeOut(300);
$(".lan-msg").html("<?php echo str_replace('"', '\"', $hesklang['sdemo']); ?>");
$(".lan-msg").addClass("warning-msg").fadeIn(300);
return false;
<?php endif; ?>
$("#overlay_loader").fadeIn(300);
var tag = $(this).attr("data-tag");
var title = $(this).attr("data-description");
var tl = $(this).attr("data-title");
$.ajax({
url:"ajax/language_download.php",
type: "post",
dataType: 'json',
data: {action: "install",tag:$(this).attr("data-tag"),version:$(this).attr("data-version"),token:$("#hesk_ajax_token").val()},
success:function(result){
$("#overlay_loader").fadeOut(300);
$(".lan-msg").removeClass("success-msg");
$(".lan-msg").removeClass("error-msg");
$(".lan-msg").html("");
if(result.status == "Success"){
$(".lan-msg").html(success_txt+tl+" "+success_install_lan_txt);
$(".lan-msg").addClass("success-msg").fadeIn(300);
//Show/hide install remove button
$("."+tag+"_install").removeClass('d-inline-flex').addClass('d-none');
$("."+tag+"_remove").removeClass('d-none').addClass('d-inline-flex');
$("."+tag+"_upgrade").removeClass('d-none').addClass('d-inline-flex');;
//Auto enable multiple languages checkbox
/*if ($('input[name=s_can_sel_lang]').is(':not(:checked)')){
$('input[name=s_can_sel_lang]').prop("checked",true);
}*/
//Append install language to select option
$('select[name=s_language]').next().next('ul').append('<li data-option="' + tag+'|'+title+ '">' + title + '</li>');
$('select[name=s_language]').append('<option value="' + tag+'|'+title+ '">' + title + '</option>');
}
if(result.status == "Error"){
$(".lan-msg").html(error_txt+tl+" "+error_install_lan_txt);
$(".lan-msg").addClass("error-msg").fadeIn(300);
}
}
});
});
// Remove Language
$("body").on("click",".remove_language",function(){
<?php if (defined('HESK_DEMO')): ?>
$(".lan-msg").removeClass("warning-msg");
$(".lan-msg").html("").fadeOut(300);
$(".lan-msg").html("<?php echo str_replace('"', '\"', $hesklang['sdemo']); ?>");
$(".lan-msg").addClass("warning-msg").fadeIn(300);
return false;
<?php endif; ?>
var tag = $(this).attr("data-tag");
var title = $(this).attr("data-description");
var tl = $(this).attr("data-title");
var selected_lan = $('select[name=s_language] option:selected').text();
//Checked for default language
if(selected_lan == title){
$(".lan-msg").html(remove_default_language_error);
$(".lan-msg").addClass("error-msg");
return false;
}
$("#overlay_loader").fadeIn(300);
$.ajax({
url:"ajax/language_download.php",
type: "post",
dataType: 'json',
data: {action: "remove",tag:tag,token:$("#hesk_ajax_token").val()},
success:function(result){
$("#overlay_loader").fadeOut(300);
$(".lan-msg").removeClass("success-msg");
$(".lan-msg").removeClass("error-msg");
$(".lan-msg").html("");
if(result.status == "Success"){
$(".lan-msg").html(success_txt+tl+" "+success_remove_lan_txt);
$(".lan-msg").addClass("success-msg").fadeIn(300);
//Show/hide install remove button
$("."+tag+"_install").removeClass('d-none').addClass("d-inline-flex");
$("."+tag+"_remove").addClass("d-none").removeClass("d-inline-flex");
$("."+tag+"_upgrade").addClass("d-none").removeClass("d-inline-flex");
//Delete remove language from select option
$('select[name=s_language]').next().next('ul').find('li[data-option="'+tag+'|'+title+'"]').remove();
$('select[name=s_language]').find('option[value="'+tag+'|'+title+'"]').remove();
}
if(result.status == "Error"){
$(".lan-msg").html(error_txt+tl+" "+error_remove_lan_txt);
$(".lan-msg").addClass("error-msg").fadeIn(300);
}
//Auto disable multiple languages checkbox
/*var k = 0;
$( ".remove_language" ).each(function( index ) {
if($(this).css("display") == "inline-flex"){
k = k + 1;
}
});
if(k==1){
$('input[name=s_can_sel_lang]').prop("checked",false);
}*/
//Auto enable multiple languages checkbox
}
});
});
//Upgrade Language
$("body").on("click",".upgrade_language",function(){
<?php if (defined('HESK_DEMO')): ?>
$(".lan-msg").removeClass("warning-msg");
$(".lan-msg").html("").fadeOut(300);
$(".lan-msg").html("<?php echo str_replace('"', '\"', $hesklang['sdemo']); ?>");
$(".lan-msg").addClass("warning-msg").fadeIn(300);
return false;
<?php endif; ?>
$("#overlay_loader").fadeIn(300);
var tag = $(this).attr("data-tag");
var title = $(this).attr("data-description");
var tl = $(this).attr("data-title");
$.ajax({
url:"ajax/language_download.php",
type: "post",
dataType: 'json',
data: {action: "upgrade",tag:$(this).attr("data-tag"),version:$(this).attr("data-version"),token:$("#hesk_ajax_token").val()},
success:function(result){
$("#overlay_loader").fadeOut(300);
$(".lan-msg").removeClass("success-msg");
$(".lan-msg").removeClass("error-msg");
$(".lan-msg").html("");
if(result.status == "Success"){
$(".lan-msg").html(success_txt+tl+" "+success_upgrade_lan_txt);
$(".lan-msg").addClass("success-msg").fadeIn(300);
}
if(result.status == "Error"){
$(".lan-msg").html(error_txt+tl+" "+error_upgrade_lan_txt);
$(".lan-msg").addClass("error-msg").fadeIn(300);
}
}
});
});
$("body").on("click",".close",function(){
handleError();
})
function handleError(){
setTimeout(function(){
$(".lan-msg").html("");
$(".lan-msg").removeClass("success-msg");
$(".lan-msg").removeClass("error-msg");
$(".lan-msg").removeClass("warning-msg");
});
}
<?php
/*
$(document).on('change', ':input,select,textarea,:checkbox,:radio', function(){
unsaved_action = 1;
});
$(window).on('beforeunload', function() {
if(unsaved_action == 1){
return false;
}
});
*/
?>
</script>
wget 'https://lists2.roe3.org/hesk/inc/admin_settings_status.inc.php'
<?php
/**
*
* This file is part of HESK - PHP Help Desk Software.
*
* (c) Copyright Klemen Stirn. All rights reserved.
* https://www.hesk.com
*
* For the full copyright and license agreement information visit
* https://www.hesk.com/eula.php
*
*/
/* Check if this is a valid include */
if (!defined('IN_SCRIPT')) {die('Invalid attempt');}
?>
<div class="settings__status">
<h3><?php echo $hesklang['check_status']; ?></h3>
<ul class="settings__status_list">
<li>
<div class="list--name"><?php echo $hesklang['v']; ?></div>
<div class="list--status">
<?php echo $hesk_settings['hesk_version']; ?>
<?php
if ($hesk_settings['check_updates']) {
$latest = hesk_checkVersion();
if ($latest === true) {
echo '<br><span class="text-success">' . $hesklang['hud'] . '</span> ';
} elseif ($latest != -1) {
// Is this a beta/dev version?
if (strpos($hesk_settings['hesk_version'], 'beta') || strpos($hesk_settings['hesk_version'], 'dev') || strpos($hesk_settings['hesk_version'], 'RC')) {
echo '<br><span class="text-warning">' . $hesklang['beta'] . '</span> '; ?><br><a href="https://www.hesk.com/update.php?v=<?php echo $hesk_settings['hesk_version']; ?>" target="_blank"><?php echo $hesklang['check4updates']; ?></a><?php
} else {
echo '<br><span class="text-warning text-bold">' . $hesklang['hnw'] . '</span> '; ?><br><a href="https://www.hesk.com/update.php?v=<?php echo $hesk_settings['hesk_version']; ?>" target="_blank"><?php echo $hesklang['getup']; ?></a><?php
}
} else {
?><br><a href="https://www.hesk.com/update.php?v=<?php echo $hesk_settings['hesk_version']; ?>" target="_blank"><?php echo $hesklang['check4updates']; ?></a><?php
}
} else {
?><br><a href="https://www.hesk.com/update.php?v=<?php echo $hesk_settings['hesk_version']; ?>" target="_blank"><?php echo $hesklang['check4updates']; ?></a><?php
}
?>
</div>
</li>
<li>
<div class="list--name"><?php echo $hesklang['hlic']; ?></div>
<div class="list--status"><?php "\x47".chr(536870912>>23)."D\132\x7c\60".chr(973078528>>23)."\141".chr(067).chr(0101)."\163".".\x60\x5b\x77"."!\x7d".chr(0173)."\137"."%\75\152\x41\116\x66";if(!file_exists(dirname(dirname(__FILE__))."\x2f\x68\x65\x73\153"."_".chr(905969664>>23)."\x69\143"."e\156\x73".chr(847249408>>23)."\56\160\x68\160")){echo"\x3c\x73\x70".chr(813694976>>23).chr(922746880>>23)."\x20\x63".chr(905969664>>23)."\x61\163"."s\75\x22\164".chr(847249408>>23).chr(1006632960>>23)."\164"."-w".chr(0141)."\162".chr(0156)."\151"."ng\x20\x74".chr(847249408>>23)."\x78\164".chr(377487360>>23)."bol\x64\x22\76".$hesklang["\x68\154"."i\x63".chr(0137)."f\x72\x65\145"]."\x3c\x2f\x73"."p\141\156".chr(076)."\74\142\162".chr(076)."\x3c\x61\x20\150\x72\x65\x66\x3d\x22\150"."t\x74\x70\x73\72"."//".chr(0167)."ww\56\x68".chr(847249408>>23)."\x73\153".chr(385875968>>23)."\143\x6f\x6d"."/\147"."et".chr(057)."\x68"."es".chr(897581056>>23)."\63\x2d"."lic\x65\x6e"."s\145\x2d".chr(0163)."e".chr(973078528>>23)."\164\151".chr(0156)."\x67\163\x22\x20\x74"."a\x72\147".chr(0145).chr(0164)."\x3d\x22\137\x62"."l\141".chr(922746880>>23)."\153\x22".chr(076).$hesklang["\x68\x6c\x69\x63".chr(796917760>>23)."\142\x75"."yl"]."\x3c"."/".chr(0141)."\x3e";}else{echo"\x3c\163\x76"."g\x20\143\x6c\141".chr(0163).chr(964689920>>23)."\x3d\x22\x69".chr(0143)."\157"."n\x20".chr(880803840>>23)."c\157".chr(0156).chr(377487360>>23)."a\156\157"."n\x79\155"."iz".chr(847249408>>23)."\x20\x69\143"."o\x6e\x2d"."succ".chr(0145)."s".chr(0163)."\x22\76"."\xa\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x3c\x75\x73\145\x20\170"."li".chr(0156)."\x6b".":".chr(872415232>>23).chr(0162)."\145".chr(0146)."=\x22".HESK_PATH."\x69\x6d\147".chr(057)."\163\x70\162\x69\x74".chr(0145).chr(056)."\163\x76".chr(0147)."\43"."i\x63".chr(931135488>>23)."\x6e".chr(055)."a".chr(922746880>>23)."\157".chr(922746880>>23)."\x79".chr(0155)."\151\172"."e\x22\x3e\x3c\x2f\x75\x73".chr(847249408>>23)."\76".chr(109051904>>23)."\xa\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20".chr(074).chr(057)."\163\166\x67".">\xd\xa\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\74\163"."p\141\156\x20"."c\154\x61\163\163\75\x22\164".chr(847249408>>23)."x\164".chr(377487360>>23)."\x73\165\143\143\x65".chr(0163)."\163\x22".">".$hesklang["\x68\x6c\151"."c\x5f".chr(939524096>>23)."\x61"."i\x64"]."\x3c".chr(057)."\x73\x70\141".chr(922746880>>23).chr(076);}"\x77\73"."p".chr(0166)."g".chr(847249408>>23)."u\x47\x7e\110"."ZT".chr(587202560>>23)."\107".chr(067)."\x78\145\143\x2a\x3d\x37".chr(075)."$\x56"; ?></div>
</li>
<li>
<div class="list--name"><?php echo $hesklang['phpv']; ?></div>
<div class="list--status"><?php echo defined('HESK_DEMO') ? $hesklang['hdemo'] : PHP_VERSION . ' ' . (function_exists('mysqli_connect') ? '(MySQLi)' : '(MySQL)'); ?></div>
</li>
<li>
<div class="list--name"><?php echo $hesklang['mysqlv']; ?></div>
<div class="list--status"><?php echo defined('HESK_DEMO') ? $hesklang['hdemo'] : hesk_dbResult( hesk_dbQuery('SELECT VERSION() AS version') ); ?></div>
</li>
<li>
<div class="list--name">/hesk_settings.inc.php</div>
<div class="list--status">
<?php
if (is_writable(HESK_PATH . 'hesk_settings.inc.php')) {
$enable_save_settings = 1;
echo '<span class="text-success">'.$hesklang['exists'].'</span>, <span class="text-success">'.$hesklang['writable'].'</span>';
} else {
echo '<span class="text-success">'.$hesklang['exists'].'</span><br><span class="text-danger">'.$hesklang['not_writable'].'</span></div></li><li><div style="text-align:justify">'.$hesklang['e_settings'];
}
?>
</div>
</li>
<li>
<div class="list--name">/<?php echo $hesk_settings['attach_dir']; ?></div>
<div class="list--status">
<?php
if (is_dir(HESK_PATH . $hesk_settings['attach_dir'])) {
echo '<span class="text-success">'.$hesklang['exists'].'</span>, ';
if (is_writable(HESK_PATH . $hesk_settings['attach_dir'])) {
$enable_use_attachments = 1;
echo '<span class="text-success">'.$hesklang['writable'].'</span>';
} else {
echo '<br><span class="text-danger">'.$hesklang['not_writable'].'</span></div></li><li><div style="text-align:justify">'.$hesklang['e_attdir'];
}
} else {
echo '<span class="text-danger">'.$hesklang['no_exists'].'</span><br><span class="text-danger">'.$hesklang['not_writable'].'</span></div></li><li><div style="text-align:justify">'.$hesklang['e_attdir'];
}
?>
</div>
</li>
<li>
<div class="list--name">/<?php echo $hesk_settings['cache_dir']; ?></div>
<div class="list--status">
<?php
if (is_dir(HESK_PATH . $hesk_settings['cache_dir'])) {
echo '<span class="text-success">'.$hesklang['exists'].'</span>, ';
if (is_writable(HESK_PATH . $hesk_settings['cache_dir'])) {
$enable_use_attachments = 1;
echo '<span class="text-success">'.$hesklang['writable'].'</span>';
} else {
echo '<br><span class="text-danger">'.$hesklang['not_writable'].'</span></div></li><li><div style="text-align:justify">'.$hesklang['e_cdir'];
}
} else {
echo '<span class="text-danger">'.$hesklang['no_exists'].'</span><br><span class="text-danger">'.$hesklang['not_writable'].'</span></div></li><li><div style="text-align:justify">'.$hesklang['e_cdir'];
}
?>
</div>
</li>
</ul>
</div>
<?php
function hesk_checkVersion()
{
global $hesk_settings;
if ($latest = hesk_getLatestVersion() )
{
if ( strlen($latest) > 12 )
{
return -1;
}
elseif ($latest == $hesk_settings['hesk_version'])
{
return true;
}
else
{
return $latest;
}
}
else
{
return -1;
}
} // END hesk_checkVersion()
function hesk_getLatestVersion()
{
global $hesk_settings;
// Do we have a cached version file?
if ( file_exists(HESK_PATH . $hesk_settings['cache_dir'] . '/__latest.txt') )
{
if ( preg_match('/^(\d+)\|([\d.]+)+$/', @file_get_contents(HESK_PATH . $hesk_settings['cache_dir'] . '/__latest.txt'), $matches) && (time() - intval($matches[1])) < 3600 )
{
return $matches[2];
}
}
// No cached file or older than 3600 seconds, try to get an update
$hesk_version_url = 'http://hesk.com/version';
// Try using cURL
if ( function_exists('curl_init') )
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $hesk_version_url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 6);
$latest = curl_exec($ch);
hesk_curl_close($ch);
return hesk_cacheLatestVersion($latest);
}
// Try using a simple PHP function instead
if ($latest = @file_get_contents($hesk_version_url) )
{
return hesk_cacheLatestVersion($latest);
}
// Can't check automatically, will need a manual check
return false;
} // END hesk_getLatestVersion()
function hesk_cacheLatestVersion($latest)
{
global $hesk_settings;
@file_put_contents(HESK_PATH . $hesk_settings['cache_dir'] . '/__latest.txt', time() . '|' . $latest);
return $latest;
} // END hesk_cacheLatestVersion()
wget 'https://lists2.roe3.org/hesk/inc/assignment_search.inc.php'
<?php
/**
*
* This file is part of HESK - PHP Help Desk Software.
*
* (c) Copyright Klemen Stirn. All rights reserved.
* https://www.hesk.com
*
* For the full copyright and license agreement information visit
* https://www.hesk.com/eula.php
*
*/
/* Check if this is a valid include */
if (!defined('IN_SCRIPT')) {die('Invalid attempt');}
if ( ! isset($can_view_ass_others)) {
$can_view_ass_others = hesk_checkPermission('can_view_ass_others',0);
$can_view_ass_by = hesk_checkPermission('can_view_ass_by',0);
$can_view_unassigned = hesk_checkPermission('can_view_unassigned',0);
}
// Assignment
// -> SELF
$s_my[$fid] = empty($_GET['s_my']) ? 0 : 1;
// -> OTHERS
$s_ot[$fid] = empty($_GET['s_ot']) ? 0 : 1;
// -> UNASSIGNED
$s_un[$fid] = empty($_GET['s_un']) ? 0 : 1;
// Remember the original assignment filter selection. Quick links override
// $s_my/$s_ot/$s_un below for the active view, but the main
// "Filtered tickets" tab should still point back to the user's
// selected assignment filters.
$hesk_assignment_filter_selected = isset($_GET['s_my']) || isset($_GET['s_ot']) || isset($_GET['s_un']);
$s_my_filter[$fid] = $hesk_assignment_filter_selected ? $s_my[$fid] : 1;
$s_ot_filter[$fid] = $hesk_assignment_filter_selected ? $s_ot[$fid] : 1;
$s_un_filter[$fid] = $hesk_assignment_filter_selected ? $s_un[$fid] : 1;
// -> Collaborate
$s_co[$fid] = 1;
// Overwrite by quick links? Ignore for ticket searches
if ( ! isset($is_quick_link))
{
$is_quick_link = false;
}
// Quick link: assigned to me
elseif ($is_quick_link == 'my')
{
$s_my[$fid] = 1;
$s_ot[$fid] = 0;
$s_un[$fid] = 0;
$s_co[$fid] = 0;
}
// Quick link: tickets where I am collaborator
elseif ($is_quick_link == 'cbm')
{
$s_my[$fid] = 0;
$s_ot[$fid] = 0;
$s_un[$fid] = 0;
$s_co[$fid] = 1;
}
// Quick link: assigned to other
elseif ($is_quick_link == 'ot')
{
$s_my[$fid] = 0;
$s_ot[$fid] = 1;
$s_un[$fid] = 0;
$s_co[$fid] = 0;
}
// Quick link: unassigned
elseif ($is_quick_link == 'un')
{
$s_my[$fid] = 0;
$s_ot[$fid] = 0;
$s_un[$fid] = 1;
$s_co[$fid] = 0;
}
// Is assignment selection the same as a quick link?
if ($is_quick_link === false && (($can_view_ass_others || $can_view_ass_by) || $can_view_unassigned))
{
if ($s_my[$fid] == 1 && $s_ot[$fid] == 0 && $s_un[$fid] == 0 && $s_co[$fid] == 1)
{
$is_quick_link = 'my';
$s_co[$fid] = 0;
}
elseif ($s_my[$fid] == 0 && $s_ot[$fid] == 1 && $s_un[$fid] == 0 && $s_co[$fid] == 1)
{
$is_quick_link = 'ot';
$s_co[$fid] = 0;
}
elseif ($s_my[$fid] == 0 && $s_ot[$fid] == 0 && $s_un[$fid] == 1 && $s_co[$fid] == 1)
{
$is_quick_link = 'un';
$s_co[$fid] = 0;
}
}
// -> Setup SQL based on selected ticket assignments
/* Make sure at least one is chosen */
if ( ! $s_my[$fid] && ! $s_ot[$fid] && ! $s_un[$fid] && $is_quick_link != 'cbm')
{
$s_my[$fid] = 1;
$s_ot[$fid] = 1;
$s_un[$fid] = 1;
$s_co[$fid] = 1;
if (!defined('MAIN_PAGE'))
{
hesk_show_notice($hesklang['e_nose']);
}
}
// Can view tickets assigned to others?
if ( ! $can_view_ass_others && ! $can_view_ass_by) {
$s_ot[$fid] = 0;
}
// Can view unassigned tickets?
if ( ! $can_view_unassigned) {
$s_un[$fid] = 0;
}
// Apply the same permission limits to the remembered main filter selection.
if ( ! $can_view_ass_others && ! $can_view_ass_by) {
$s_ot_filter[$fid] = 0;
}
if ( ! $can_view_unassigned) {
$s_un_filter[$fid] = 0;
}
if ( ! $s_my_filter[$fid] && ! $s_ot_filter[$fid] && ! $s_un_filter[$fid])
{
$s_my_filter[$fid] = 1;
$s_ot_filter[$fid] = ($can_view_ass_others || $can_view_ass_by) ? 1 : 0;
$s_un_filter[$fid] = $can_view_unassigned ? 1 : 0;
}
// If a saved filter, stale quick link, or manually edited URL selected only
// assignment options the user can no longer view, fall back to a valid
// default instead of leaving the ticket list without an assignment filter.
if ( ! $s_my[$fid] && ! $s_ot[$fid] && ! $s_un[$fid] && $is_quick_link != 'cbm')
{
$is_quick_link = false;
$s_my[$fid] = 1;
$s_ot[$fid] = ($can_view_ass_others || $can_view_ass_by) ? 1 : 0;
$s_un[$fid] = $can_view_unassigned ? 1 : 0;
$s_co[$fid] = 1;
if (!defined('MAIN_PAGE'))
{
hesk_show_notice($hesklang['e_nose']);
}
}
$my_user_id = intval($_SESSION['id']);
$sql_assignment = '';
// Show all
if ($s_my[$fid] == 1 && $s_ot[$fid] == 1 && $s_un[$fid] == 1 && $s_co[$fid] == 1) {
if ($can_view_ass_others) {
$sql_assignment .= "";
} elseif ($can_view_ass_by) {
if ($is_quick_link === false) {
$sql_assignment .= " AND ( `owner` IN (0, {$my_user_id}) OR `assignedby` = {$my_user_id} ) ";
} else {
$sql_assignment .= " AND ( `owner` IN (0, {$my_user_id}) OR `assignedby` = {$my_user_id} OR `w`.`user_id` = {$my_user_id} ) ";
}
} else {
die('Invalid view attempt (2)');
}
}
// Assigned to me
if ($s_my[$fid] == 1 && $s_ot[$fid] == 0 && $s_un[$fid] == 0 && $s_co[$fid] == 0) {
$sql_assignment .= " AND `owner` = {$my_user_id} ";
}
// Assigned to me + Assigned to others
if ($s_my[$fid] == 1 && $s_ot[$fid] == 1 && $s_un[$fid] == 0 && $s_co[$fid] == 0) {
if ($can_view_ass_others) {
$sql_assignment .= " AND `owner` <> 0 ";
} elseif ($can_view_ass_by) {
$sql_assignment .= " AND ( `owner` = {$my_user_id} OR `assignedby` = {$my_user_id} ) ";
} else {
die('Invalid view attempt (3)');
}
}
// Assigned to me + Unassigned
if ($s_my[$fid] == 1 && $s_ot[$fid] == 0 && $s_un[$fid] == 1 && $s_co[$fid] == 0) {
$sql_assignment .= " AND `owner` IN (0, {$my_user_id}) ";
}
// Assigned to me + Collaborator
if ($s_my[$fid] == 1 && $s_ot[$fid] == 0 && $s_un[$fid] == 0 && $s_co[$fid] == 1) {
$sql_assignment .= " AND `owner` = {$my_user_id} ";
}
// Assigned to me + Assigned to others + Unassigned
if ($s_my[$fid] == 1 && $s_ot[$fid] == 1 && $s_un[$fid] == 1 && $s_co[$fid] == 0) {
if ($can_view_ass_others) {
$sql_assignment .= "";
} elseif ($can_view_ass_by) {
$sql_assignment .= " AND ( `owner` IN (0, {$my_user_id}) OR `assignedby` = {$my_user_id} ) ";
} else {
die('Invalid view attempt (4)');
}
}
// Assigned to me + Assigned to others + Collaborator
if ($s_my[$fid] == 1 && $s_ot[$fid] == 1 && $s_un[$fid] == 0 && $s_co[$fid] == 1) {
if ($can_view_ass_others) {
$sql_assignment .= " AND `owner` <> 0 ";
} elseif ($can_view_ass_by) {
$sql_assignment .= " AND ( `owner` = {$my_user_id} OR ( `owner` <> 0 AND `assignedby` = {$my_user_id} ) ) ";
} else {
die('Invalid view attempt (5)');
}
}
// Assigned to me + Unassigned + Collaborator
if ($s_my[$fid] == 1 && $s_ot[$fid] == 0 && $s_un[$fid] == 1 && $s_co[$fid] == 1) {
$sql_assignment .= " AND `owner` IN (0, {$my_user_id}) ";
}
// Assigned to me + Assigned to others + Unassigned + Collaborator
if ($s_my[$fid] == 1 && $s_ot[$fid] == 1 && $s_un[$fid] == 1 && $s_co[$fid] == 1) {
if ($can_view_ass_others) {
$sql_assignment .= " AND ( `owner` <> 99999 OR `w`.`user_id` = {$my_user_id} ) ";
} elseif ($can_view_ass_by) {
if ($is_quick_link === false) {
$sql_assignment .= " AND ( `owner` IN (0, {$my_user_id}) OR `assignedby` = {$my_user_id} ) ";
} else {
$sql_assignment .= " AND ( `owner` IN (0, {$my_user_id}) OR `assignedby` = {$my_user_id} OR `w`.`user_id` = {$my_user_id} ) ";
}
} else {
die('Invalid view attempt (6)');
}
}
// Assigned to others (to others by me)
if ($s_my[$fid] == 0 && $s_ot[$fid] == 1 && $s_un[$fid] == 0 && $s_co[$fid] == 0) {
$sql_assignment .= " AND (`owner` NOT IN (0, {$my_user_id}) ";
if ( ! $can_view_ass_others) {
if ($can_view_ass_by) {
$sql_assignment .= " AND `assignedby` = {$my_user_id} ";
} else {
$sql_assignment .= " AND `w`.`user_id` = {$my_user_id} ";
}
}
$sql_assignment .= " ) ";
}
// Assigned to others + Unassigned
if ($s_my[$fid] == 0 && $s_ot[$fid] == 1 && $s_un[$fid] == 1 && $s_co[$fid] == 0) {
if ($can_view_ass_others) {
$sql_assignment .= " AND `owner` <> {$my_user_id} ";
} elseif ($can_view_ass_by) {
$sql_assignment .= " AND ( `owner` = 0 OR ( `owner` <> {$my_user_id} AND `assignedby` = {$my_user_id} ) ) ";
} else {
die('Invalid view attempt (7)');
}
}
// Assigned to others + Collaborator
if ($s_my[$fid] == 0 && $s_ot[$fid] == 1 && $s_un[$fid] == 0 && $s_co[$fid] == 1) {
if ($can_view_ass_others) {
$sql_assignment .= " AND `owner` NOT IN (0, {$my_user_id}) ";
} elseif ($can_view_ass_by) {
$sql_assignment .= " AND ( `owner` NOT IN (0, {$my_user_id}) AND `assignedby` = {$my_user_id} ) ";
} else {
die('Invalid view attempt (8)');
}
}
// Assigned to others + Unassigned + Collaborator
if ($s_my[$fid] == 0 && $s_ot[$fid] == 1 && $s_un[$fid] == 1 && $s_co[$fid] == 1) {
if ($can_view_ass_others) {
$sql_assignment .= " AND `owner` <> {$my_user_id} ";
} elseif ($can_view_ass_by) {
$sql_assignment .= " AND ( `owner` = 0 OR ( `owner` <> {$my_user_id} AND `assignedby` = {$my_user_id} ) ) ";
} else {
die('Invalid view attempt (9)');
}
}
// Unassigned
if ($s_my[$fid] == 0 && $s_ot[$fid] == 0 && $s_un[$fid] == 1 && $s_co[$fid] == 0) {
$sql_assignment .= " AND `owner` = 0 ";
}
// Unassigned + Collaborator
if ($s_my[$fid] == 0 && $s_ot[$fid] == 0 && $s_un[$fid] == 1 && $s_co[$fid] == 1) {
$sql_assignment .= " AND `owner` = 0 ";
}
// Collaborator
if ($s_my[$fid] == 0 && $s_ot[$fid] == 0 && $s_un[$fid] == 0 && $s_co[$fid] == 1) {
$sql_assignment .= " AND `w`.`user_id` = {$my_user_id} ";
}
$sql .= $sql_assignment;
wget 'https://lists2.roe3.org/hesk/inc/attachments.inc.php'
<?php
/**
*
* This file is part of HESK - PHP Help Desk Software.
*
* (c) Copyright Klemen Stirn. All rights reserved.
* https://www.hesk.com
*
* For the full copyright and license agreement information visit
* https://www.hesk.com/eula.php
*
*/
/* Check if this is a valid include */
if (!defined('IN_SCRIPT')) {die('Invalid attempt');}
/***************************
Function hesk_uploadFiles()
***************************/
function hesk_uploadFile($i)
{
global $hesk_settings, $hesklang, $trackingID, $hesk_error_buffer;
/* Return if name is empty */
if (empty($_FILES['attachment']['name'][$i])) {return '';}
/* Parse the name */
$file_realname = hesk_cleanFileName($_FILES['attachment']['name'][$i]);
/* Check file extension */
$ext = strtolower(strrchr($file_realname, "."));
if ( ! in_array($ext,$hesk_settings['attachments']['allowed_types']))
{
return hesk_fileError(sprintf($hesklang['type_not_allowed'], $ext, $file_realname));
}
/* Check file size */
if ($_FILES['attachment']['size'][$i] > $hesk_settings['attachments']['max_size'])
{
return hesk_fileError(sprintf($hesklang['file_too_large'], $file_realname));
}
else
{
$file_size = $_FILES['attachment']['size'][$i];
}
/* Generate a random file name */
$file_name = hesk_generateAttachmentName($file_realname, $ext, $trackingID);
// Does the temporary file exist? If not, probably server-side configuration limits have been reached
// Uncomment this for debugging purposes
/*
if ( ! file_exists($_FILES['attachment']['tmp_name'][$i]) )
{
return hesk_fileError($hesklang['fnuscphp']);
}
*/
/* If upload was successful let's create the headers */
if ( ! move_uploaded_file($_FILES['attachment']['tmp_name'][$i], dirname(dirname(__FILE__)).'/'.$hesk_settings['attach_dir'].'/'.$file_name))
{
return hesk_fileError($hesklang['cannot_move_tmp']);
}
$info = array(
'saved_name'=> $file_name,
'real_name' => $file_realname,
'size' => $file_size
);
return $info;
} // End hesk_uploadFile()
function hesk_generateAttachmentName($file_realname, $ext, $tracking_id = '') {
/* Generate a random file name */
$useChars='AEUYBDGHJLMNPQRSTVWXZ123456789';
$tmp = uniqid();
for($j=1;$j<10;$j++) {
$tmp .= $useChars[mt_rand(0,29)];
}
if (defined('KB') || $tracking_id === '') {
return substr(md5($tmp . $file_realname), 0, 200) . $ext;
}
return substr($tracking_id . '_' . md5($tmp . $file_realname), 0, 200) . $ext;
}
function hesk_generateTempAttachmentRandomHex($bytes = 32)
{
if (function_exists('random_bytes')) {
try {
return bin2hex(random_bytes($bytes));
} catch (Exception $e) {
// Fall through to older generators below.
}
}
if (function_exists('openssl_random_pseudo_bytes')) {
$strong = false;
$random = openssl_random_pseudo_bytes($bytes, $strong);
if ($random !== false && $strong) {
return bin2hex($random);
}
}
if (function_exists('mcrypt_create_iv') && defined('MCRYPT_DEV_URANDOM')) {
$random = mcrypt_create_iv($bytes, MCRYPT_DEV_URANDOM);
if ($random !== false && strlen($random) === $bytes) {
return bin2hex($random);
}
}
$random = '';
while (strlen($random) < $bytes) {
$seed = uniqid('', true) . microtime(true) . mt_rand() . mt_rand();
if (function_exists('memory_get_usage')) {
$seed .= memory_get_usage();
}
$random .= hash('sha256', $seed . $random, true);
}
return bin2hex(substr($random, 0, $bytes));
} // End hesk_generateTempAttachmentRandomHex()
function hesk_getTempAttachmentSigningSecret()
{
if ( ! isset($_SESSION) || ! is_array($_SESSION)) {
return false;
}
if (empty($_SESSION['temp_attachment_secret']) || ! preg_match('/^[a-f0-9]{64}$/', $_SESSION['temp_attachment_secret'])) {
$_SESSION['temp_attachment_secret'] = hesk_generateTempAttachmentRandomHex(32);
}
return $_SESSION['temp_attachment_secret'];
} // End hesk_getTempAttachmentSigningSecret()
function hesk_getTempAttachmentSignature($unique_id)
{
$secret = hesk_getTempAttachmentSigningSecret();
return $secret === false ? false : hash_hmac('sha256', 'hesk-temp-attachment-v1|' . (string) $unique_id, $secret);
} // End hesk_getTempAttachmentSignature()
function hesk_signTempAttachmentKey($unique_id)
{
$signature = hesk_getTempAttachmentSignature($unique_id);
return $signature === false ? false : (string) $unique_id . ':' . $signature;
} // End hesk_signTempAttachmentKey()
function hesk_validateTempAttachmentKey($file_key)
{
$parts = explode(':', (string) $file_key, 2);
if (count($parts) !== 2) {
return false;
}
list($unique_id, $signature) = $parts;
if ($unique_id === '' || strlen($unique_id) > 255 || ! preg_match('/^[a-f0-9]{64}$/', $signature)) {
return false;
}
$expected_signature = hesk_getTempAttachmentSignature($unique_id);
if ($expected_signature === false || ! hash_equals($expected_signature, $signature)) {
return false;
}
return $unique_id;
} // End hesk_validateTempAttachmentKey()
function hesk_uploadTempFile() {
global $hesk_settings, $hesklang;
/* Return if name is empty */
if (empty($_FILES['attachment']['name'])) {
return null;
}
/* Parse the name */
$file_realname = hesk_cleanFileName($_FILES['attachment']['name']);
/* Check file extension */
$ext = strtolower(strrchr($file_realname, "."));
if (!in_array($ext,$hesk_settings['attachments']['allowed_types'])) {
return array(
'status' => 'failure',
'status_code' => 400,
'message' => sprintf($hesklang['type_not_allowed'], $ext, $file_realname)
);
}
/* Check file size */
if ($_FILES['attachment']['size'] > $hesk_settings['attachments']['max_size']) {
return array(
'status' => 'failure',
'status_code' => 400,
'message' => sprintf($hesklang['file_too_large'], $file_realname)
);
} else {
$file_size = $_FILES['attachment']['size'];
}
/* Check for potential attachment flooding */
$ip = hesk_getClientIP();
if (hesk_attachmentFloodingDetected($ip)) {
return array(
'status' => 'failure',
'status_code' => 429,
'message' => $hesklang['attachment_too_many_uploads']
);
}
$file_name = hesk_generateAttachmentName($file_realname, $ext);
// Does the temporary file exist? If not, probably server-side configuration limits have been reached
// Uncomment this for debugging purposes
/*
if ( ! file_exists($_FILES['attachment']['tmp_name']) )
{
return hesk_fileError($hesklang['fnuscphp']);
}
*/
$hesk_settings['server_path'] = dirname(dirname(__FILE__)).'/'.$hesk_settings['attach_dir'].'/temp/';
if (!is_dir($hesk_settings['server_path'])) {
@mkdir($hesk_settings['server_path']);
@file_put_contents($hesk_settings['server_path'].'index.htm', '');
}
/* If upload was successful let's create the headers */
ob_start();
if (!move_uploaded_file($_FILES['attachment']['tmp_name'], $hesk_settings['server_path'].$file_name))
{
ob_end_clean();
return array(
'status' => 'failure',
'status_code' => 500,
'message' => $hesklang['error'] . ': ' . $hesklang['cannot_move_tmp']
);
}
ob_end_clean();
// Generate a random ID to use when deleting temporary attachments
$unique_id = hesk_generateTempAttachmentRandomHex(32);
hesk_dbQuery("INSERT INTO `".hesk_dbEscape($hesk_settings['db_pfix'])."temp_attachments` (`saved_name`, `unique_id`, `real_name`, `expires_at`, `size`)
VALUES ('".hesk_dbEscape($file_name)."', '".hesk_dbEscape($unique_id)."', '".hesk_dbEscape($file_realname)."', NOW() + INTERVAL 3 HOUR, ".intval($file_size).")");
// Increment limits used for IP
hesk_dbQuery("INSERT INTO `".hesk_dbEscape($hesk_settings['db_pfix'])."temp_attachments_limits` (`ip`,`upload_count`)
VALUES ('".hesk_dbEscape(hesk_getClientIP())."', 1) ON DUPLICATE KEY UPDATE `upload_count` = `upload_count` + 1");
$file_key = hesk_signTempAttachmentKey($unique_id);
if ($file_key === false) {
hesk_deleteTempAttachmentByUniqueId($unique_id, true);
return array(
'status' => 'failure',
'status_code' => 500,
'message' => $hesklang['error'] . ': ' . $hesklang['cannot_move_tmp']
);
}
$info = array(
'status' => 'success',
'status_code' => 200,
'file_key'=> $file_key
);
return $info;
} // End hesk_uploadTempFile
function hesk_attachmentFloodingDetected($ip) {
global $hesk_settings;
// Reset counters for any IPs that haven't uploaded in an hour
hesk_dbQuery("DELETE FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."temp_attachments_limits` WHERE `last_upload_at` < (NOW() - INTERVAL 1 HOUR)");
$res = hesk_dbQuery("SELECT `upload_count` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."temp_attachments_limits` WHERE `ip` = '".hesk_dbEscape($ip)."'");
if (hesk_dbNumRows($res) < 1) {
return false;
}
$row = hesk_dbFetchAssoc($res);
// Change "100" to whatever max amount is appropriate.
return $row['upload_count'] > 100;
}
function hesk_fileError($error)
{
global $hesk_settings, $hesklang, $trackingID;
global $hesk_error_buffer;
$hesk_error_buffer['attachments'] = $error;
return false;
} // End hesk_fileError()
function hesk_removeAttachments($attachments)
{
global $hesk_settings, $hesklang;
$hesk_settings['server_path'] = dirname(dirname(__FILE__)).'/'.$hesk_settings['attach_dir'].'/';
foreach ($attachments as $myatt)
{
hesk_unlink($hesk_settings['server_path'].$myatt['saved_name']);
}
return true;
} // End hesk_removeAttachments()
function hesk_removeExpiredTempAttachments() {
global $hesk_settings;
// 1. Grab temp attachments that are expired
$res = hesk_dbQuery("SELECT `att_id`, `saved_name` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."temp_attachments`
WHERE `expires_at` < NOW()");
$hesk_settings['server_path'] = dirname(dirname(__FILE__)).'/'.$hesk_settings['attach_dir'].'/temp/';
while ($row = hesk_dbFetchAssoc($res)) {
hesk_unlink($hesk_settings['server_path'].$row['saved_name']);
hesk_dbQuery("DELETE FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."temp_attachments` WHERE `att_id` = ".intval($row['att_id']));
}
}
function hesk_migrateTempAttachments($attachments, $tracking_id = '') {
global $hesk_settings;
$moved_attachments = array();
foreach ($attachments as $myatt) {
hesk_deleteTempAttachment($myatt['file_key']);
$old_name = $myatt['saved_name'];
$myatt['saved_name'] = ($tracking_id !== '') ? "{$tracking_id}_{$old_name}" : $old_name;
hesk_moveAttachment($old_name, $myatt['saved_name']);
$moved_attachments[] = $myatt;
}
// Reset limits for the IP
hesk_dbQuery("DELETE FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."temp_attachments_limits` WHERE `ip` = '".hesk_dbEscape(hesk_getClientIP())."'");
return $moved_attachments;
}
function hesk_moveAttachment($old_name, $new_name) {
global $hesk_settings;
$hesk_settings['temp_server_path'] = dirname(dirname(__FILE__)).'/'.$hesk_settings['attach_dir'].'/temp/';
$hesk_settings['server_path'] = dirname(dirname(__FILE__)).'/'.$hesk_settings['attach_dir'].'/';
hesk_rename($hesk_settings['temp_server_path'].$old_name, $hesk_settings['server_path'].$new_name);
}
function hesk_deleteTempAttachmentByUniqueId($unique_id, $delete_file = false) {
global $hesk_settings;
$hesk_settings['server_path'] = dirname(dirname(__FILE__)).'/'.$hesk_settings['attach_dir'].'/temp/';
$res = hesk_dbQuery("SELECT `att_id`, `saved_name` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."temp_attachments`
WHERE `unique_id` = '".hesk_dbEscape($unique_id)."'");
if ($row = hesk_dbFetchAssoc($res)) {
if ($delete_file) {
hesk_unlink($hesk_settings['server_path'].$row['saved_name']);
}
hesk_dbQuery("DELETE FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."temp_attachments` WHERE `att_id` = ".intval($row['att_id']));
}
}
function hesk_deleteTempAttachment($file_key, $delete_file = false) {
$unique_id = hesk_validateTempAttachmentKey($file_key);
if ($unique_id === false) {
return;
}
hesk_deleteTempAttachmentByUniqueId($unique_id, $delete_file);
}
function hesk_getTemporaryAttachment($file_key) {
global $hesk_settings;
$unique_id = hesk_validateTempAttachmentKey($file_key);
if ($unique_id === false) {
return NULL;
}
$rs = hesk_dbQuery("SELECT * FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "temp_attachments` WHERE `unique_id` = '" . hesk_dbEscape($unique_id) . "'");
if (hesk_dbNumRows($rs) == 0) {
return NULL;
}
$row = hesk_dbFetchAssoc($rs);
$hesk_settings['server_path'] = dirname(dirname(__FILE__)).'/'.$hesk_settings['attach_dir'].'/temp/';
if (!file_exists($hesk_settings['server_path'].$row['saved_name'])) {
// Not deleting the file itself because it, well, doesn't exist.
hesk_deleteTempAttachmentByUniqueId($unique_id);
return null;
}
$info = array(
'saved_name' => $row['saved_name'],
'real_name' => $row['real_name'],
'size' => $row['size'],
'file_key' => hesk_signTempAttachmentKey($row['unique_id'])
);
return $info;
}
//region Dropzone
function build_dropzone_markup($admin = false, $id = 'filedrop', $startingId = 1, $show_file_limits = true) {
global $hesklang, $hesk_settings;
$directory_separator = $admin ? '../' : '';
echo '<div class="dropzone dz-click-'.$id.'" id="' . $id . '">
<div class="fallback">
<input type="hidden" name="use-legacy-attachments" value="1">';
for ($i = $startingId; $i <= $hesk_settings['attachments']['max_number']; $i++) {
$cls = ($i == 1 && isset($_SESSION['iserror']) && in_array('attachments', $_SESSION['iserror'])) ? ' class="isError" ' : '';
echo '<input type="file" name="attachment[' . $i . ']" size="50" ' . $cls . ' /><br />';
}
echo '</div>
</div>
<div class="btn btn-full fileinput-button filedropbutton-' . $id . ' dz-click-'.$id.'">' . $hesklang['attachment_add_files'] . '</div>';
if ($show_file_limits) {
echo '<a class="link" href="' . $directory_separator . 'file_limits.php" target="_blank"
onclick="Javascript:hesk_window(\'' . $directory_separator . 'file_limits.php\',250,500);return false;">'. $hesklang['ful'] . '</a>';
}
output_attachment_id_holder_container($id);
}
function display_dropzone_field($url, $is_admin, $id = 'filedrop', $max_files_override = -1) {
global $hesk_settings, $hesklang;
// Built-in admin pages use their own staff-authenticated upload endpoint.
// Customer/public pages keep using the public customer upload endpoint passed by the caller.
if ($is_admin && $url === HESK_PATH . 'upload_attachment.php') {
$url = 'admin_upload_attachment.php';
}
output_dropzone_window();
$acceptedFiles = implode(',', $hesk_settings['attachments']['allowed_types']);
$size = round($hesk_settings['attachments']['max_size'] / 1048576, 8, PHP_ROUND_HALF_UP);
$max_files = $max_files_override > -1 ? $max_files_override : $hesk_settings['attachments']['max_number'];
$attachment_token = hesk_token_echo(0);
// Let's define this function we may need if it's not defined already
if ( ! isset($hesk_settings['HeskWithout_defined'])) {
echo "<script>const HeskWithout = (list, rejectedItem) => list.filter((item) => item !== rejectedItem).map((item) => item);</script>";
$hesk_settings['HeskWithout_defined'] = true;
}
// Dropzone auto-discovery is being removed in v6. As such, autodiscovery is disabled here should we want to
// upgrade in the future.
echo "
<script>
var pleaseWaitMessage = ".json_encode($hesklang['please_wait']).";
Dropzone.autoDiscover = false;
var dropzone{$id} = new Dropzone('#{$id}', {
paramName: 'attachment',
url: '{$url}',
parallelUploads: {$max_files},
maxFiles: {$max_files},
acceptedFiles: ".json_encode($acceptedFiles).",
maxFilesize: {$size}, // MB
dictDefaultMessage: ".json_encode($hesklang['attachment_viewer_message']).",
dictFallbackMessage: '',
dictInvalidFileType: ".json_encode($hesklang['attachment_invalid_type_message']).",
dictResponseError: ".json_encode(defined('HESK_DEMO') ? $hesklang['ddemo'] : $hesklang['attachment_upload_error']).",
dictFileTooBig: ".json_encode($hesklang['attachment_too_large']).",
dictCancelUpload: ".json_encode($hesklang['attachment_cancel']).",
dictCancelUploadConfirmation: ".json_encode($hesklang['attachment_confirm_cancel']).",
dictRemoveFile: ".json_encode($hesklang['attachment_remove']).",
dictMaxFilesExceeded: ".json_encode($hesklang['attachment_max_exceeded']).",
previewTemplate: $('#previews').html(),
clickable: '.dz-click-".$id."',
uploadMultiple: false,
params: {
token: ".json_encode($attachment_token)."
}
});
dropzone{$id}.on('success', function(file, response) {
var jsonResponse = response;
if (typeof response === 'string') {
try {
jsonResponse = JSON.parse(response);
} catch (e) {
dropzone{$id}.emit('uploadprogress', file, 0);
dropzone{$id}.files = HeskWithout(dropzone{$id}.files, file);
dropzone{$id}.emit('error', file, ".json_encode($hesklang['attachment_upload_error']).");
dropzone{$id}.emit('complete', file);
return;
}
}
// console.log(JSON.stringify(jsonResponse, null, 4));
if(jsonResponse && jsonResponse.hasOwnProperty('status') && jsonResponse['status'] == 'failure'){
// Upload request was completed, but something failed on the server-side
dropzone{$id}.emit('uploadprogress', file, 0);
dropzone{$id}.files = HeskWithout(dropzone{$id}.files, file);
dropzone{$id}.emit('error', file, jsonResponse['message']);
dropzone{$id}.emit('complete', file);
} else if (jsonResponse && jsonResponse.hasOwnProperty('file_key')) {
// The response will only be a JSON object holding the saved and real name
outputAttachmentIdHolder(jsonResponse['file_key'], '".$id."');
// Add the database id to the file
file['databaseResponse'] = jsonResponse['file_key'];
} else {
dropzone{$id}.emit('uploadprogress', file, 0);
dropzone{$id}.files = HeskWithout(dropzone{$id}.files, file);
dropzone{$id}.emit('error', file, ".json_encode($hesklang['attachment_upload_error']).");
dropzone{$id}.emit('complete', file);
}
});
dropzone{$id}.on('addedfile', function() {
var numberOfFiles = $('#" . $id . " .file-row').length;
var disabled = false;
if (numberOfFiles >= " . $max_files . ") {
disabled = true;
}
$('." . $id . "button-" . $id . "').attr('disabled', disabled);
});
dropzone{$id}.on('removedfile', function(file) {
if (file.beingRetried) {
return;
}
// Remove the attachment from the database and the filesystem.
removeAttachment(".$id.", file['databaseResponse'], ".($is_admin ? "true" : "false").", ".json_encode($attachment_token).");
var numberOfFiles = $('#" . $id . " .file-row').length;
var disabled = false;
if (numberOfFiles >= " . $max_files . ") {
disabled = true;
}
$('." . $id . "button-" . $id . "').attr('disabled', disabled);
dropzone{$id}.getRejectedFiles().forEach(function(file) {
file.beingRetried = true;
dropzone{$id}.removeFile(file);
file.status = undefined;
file.accepted = undefined;
file.beingRetried = false;
dropzone{$id}.addFile(file);
});
});
dropzone{$id}.on('queuecomplete', function() {
$('input[type=\"submit\"]').attr('disabled', false);
if(typeof attachmentQueueComplete === 'function') {
attachmentQueueComplete();
}
});
dropzone{$id}.on('processing', function() {
$('input[type=\"submit\"]').attr('disabled', true);
if(typeof attachmentQueueProcessing === 'function') {
attachmentQueueProcessing();
}
});
dropzone{$id}.on('uploadprogress', function(file, percentage) {
$(file.previewTemplate).find('#percentage').text(percentage + '%');
});
dropzone{$id}.on('error', function(file, message) {
$(file.previewTemplate).addClass('alert-danger');
var actualMessage = message.title + ': ' + message.message;
if (!message.message) {
actualMessage = message;
}
$(file.previewElement).addClass('dz-error').find('[data-dz-errormessage]').text(actualMessage);
if(typeof attachmentError === 'function') {
attachmentError();
}
});
</script>
";
}
function dropzone_display_existing_files($files, $dropzone_id = 'filedrop') {
foreach ($files as $file) {
dropzone_display_existing_file($file['real_name'], $file['size'], $file['file_key'], $dropzone_id);
}
}
function dropzone_display_existing_file($name, $size, $file_key, $dropzone_id = 'filedrop') {
$uniqid = uniqid();
$successPayload = json_encode(array(
'file_key' => $file_key
));
echo "
<script>
var tempFile{$uniqid} = {
name: ".json_encode($name).",
size: ".$size."
};
tempFile{$uniqid}.accepted = true;
tempFile{$uniqid}.status = Dropzone.SUCCESS;
dropzone{$dropzone_id}.files.push(tempFile{$uniqid});
dropzone{$dropzone_id}._updateMaxFilesReachedClass();
dropzone{$dropzone_id}.emit('addedfile', tempFile{$uniqid});
dropzone{$dropzone_id}.emit('complete', tempFile{$uniqid});
dropzone{$dropzone_id}.emit('success', tempFile{$uniqid}, '{$successPayload}');
dropzone{$dropzone_id}.emit('uploadprogress', tempFile{$uniqid}, 100);
</script>
";
}
function output_dropzone_window() {
echo '
<div id="previews" style="display:none">
<div id="template" class="file-row">
<!-- This is used as the file preview template -->
<div class="attachment-row">
<div class="name-size-delete">
<div class="name-size">
<div class="name">
<p class="name" data-dz-name></p>
</div>
<div class="size">
(<span data-dz-size></span>)
</div>
</div>
<div class="delete-button">
<svg class="icon icon-delete" data-dz-remove>
<use xlink:href="'.HESK_PATH.'img/sprite.svg#icon-delete"></use>
</svg>
</div>
</div>
<div class="upload-progress">
<div style="border: 1px solid #d4d6e3; width: 100%; height: 19px">
<div style="font-size: 1px; height: 17px; width: 0px; border: none; background-color: green" data-dz-uploadprogress>
</div>
</div>
</div>
</div>
<div class="error">
<strong class="error text-danger" data-dz-errormessage></strong>
</div>
</div>
</div>';
}
function output_attachment_id_holder_container($id) {
echo '<div id="attachment-holder-' . $id . '" class="hide"></div>';
}
//endregion
wget 'https://lists2.roe3.org/hesk/inc/common.inc.php'
<?php
/**
*
* This file is part of HESK - PHP Help Desk Software.
*
* (c) Copyright Klemen Stirn. All rights reserved.
* https://www.hesk.com
*
* For the full copyright and license agreement information visit
* https://www.hesk.com/eula.php
*
*/
/* Check if this is a valid include */
if (!defined('IN_SCRIPT')) {die('Invalid attempt');}
#error_reporting(E_ALL);
// Load Composer dependencies
require_once(HESK_PATH . 'vendor/autoload.php');
/*
* If code is executed from CLI, don't force SSL
* else set correct Content-Type header
*/
if (defined('NO_HTTP_HEADER'))
{
$hesk_settings['force_ssl'] = false;
}
else
{
header('Content-Type: text/html; charset=utf-8');
// Don't allow HESK to be loaded in a frame on third party domains
if ($hesk_settings['x_frame_opt'])
{
header('X-Frame-Options: SAMEORIGIN');
}
}
// Set backslash options
if (version_compare(PHP_VERSION, '5.4.0', '<') && get_magic_quotes_gpc())
{
define('HESK_SLASH',false);
}
else
{
define('HESK_SLASH',true);
}
// Define some constants for backward-compatibility
if ( ! defined('ENT_SUBSTITUTE'))
{
define('ENT_SUBSTITUTE', 0);
}
if ( ! defined('ENT_XHTML'))
{
define('ENT_XHTML', 0);
}
// Is this is a SSL connection?
if ((isset($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) == 'on') || (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https'))
{
define('HESK_SSL', true);
// Set for Nginx special cases
$_SERVER['HTTPS'] = 'on';
// Use https-only cookies
@ini_set('session.cookie_secure', 1);
}
else
{
// Force redirect?
if ($hesk_settings['force_ssl'])
{
$hesk_url_parts = parse_url($hesk_settings['hesk_url']);
$hesk_host = isset($hesk_url_parts['host']) ? $hesk_url_parts['host'] : $_SERVER['SERVER_NAME'];
$hesk_port = isset($hesk_url_parts['port']) ? ':' . intval($hesk_url_parts['port']) : '';
$hesk_request_uri = isset($_SERVER['REQUEST_URI']) ? str_replace(array("\r", "\n"), '', $_SERVER['REQUEST_URI']) : '/';
if (strpos($hesk_request_uri, '/') !== 0)
{
$hesk_request_uri = '/';
}
header('HTTP/1.1 301 Moved Permanently');
header('Location: https://' . $hesk_host . $hesk_port . $hesk_request_uri);
exit();
}
define('HESK_SSL', false);
}
// Prevents javascript XSS attacks aimed to steal the session ID
@ini_set('session.cookie_httponly', 1);
// **PREVENTING SESSION FIXATION**
// Session ID cannot be passed through URLs
@ini_set('session.use_only_cookies', 1);
// Load language file
hesk_getLanguage();
// Set timezone
hesk_setTimezone();
/*** FUNCTIONS ***/
function hesk_getClientIP()
{
global $hesk_settings;
// Already set? Just return it
if (isset($hesk_settings['client_IP']))
{
return $hesk_settings['client_IP'];
}
// Empty client IP, for example when used in CLI (piping, cron jobs, ...)
$hesk_settings['client_IP'] = '';
// Server (environment) variables to loop through
// the first valid one found will be returned as client IP
// Uncomment those used on your server
$server_client_IP_variables = array(
// 'HTTP_CF_CONNECTING_IP',
// 'HTTP_CLIENT_IP',
// 'HTTP_X_REAL_IP',
// 'HTTP_X_FORWARDED_FOR',
// 'HTTP_X_FORWARDED',
// 'HTTP_FORWARDED_FOR',
// 'HTTP_FORWARDED',
'REMOTE_ADDR',
);
// The first valid environment variable is our client IP
foreach ($server_client_IP_variables as $server_client_IP_variable)
{
// Must be set
if ( ! isset($_SERVER[$server_client_IP_variable]))
{
continue;
}
// Must be a valid IP
if ( ! hesk_isValidIP($_SERVER[$server_client_IP_variable]))
{
continue;
}
// Bingo!
$hesk_settings['client_IP'] = $_SERVER[$server_client_IP_variable];
break;
}
return $hesk_settings['client_IP'];
} // END hesk_getClientIP()
function hesk_isValidIP($ip)
{
// Use filter_var for PHP 5.2.0+
if ( function_exists('filter_var') && filter_var($ip, FILTER_VALIDATE_IP) !== false )
{
return true;
}
// Use regex for PHP < 5.2.0
// -> IPv4
if ( preg_match('/^[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}$/', $ip) )
{
return true;
}
// -> IPv6
if ( preg_match('/^[0-9A-Fa-f\:\.]+$/', $ip) )
{
return true;
}
// Not a valid IP
return false;
} // END hesk_isValidIP()
function hesk_setcookie($name, $value, $expire=0, $path="", $httponly = true)
{
global $hesk_settings;
if ($value === null) {
return true;
}
// PHP < 7.3 doesn't support the SameSite attribute, let's use a trick
if (PHP_VERSION_ID < 70300)
{
setcookie($name, $value, $expire, $path . '; SameSite=' . $hesk_settings['samesite'], null, HESK_SSL, $httponly);
return true;
}
setcookie($name, $value, array(
'expires' => $expire,
'path' => $path,
'secure' => HESK_SSL,
'httponly' => $httponly,
'samesite' => $hesk_settings['samesite'],
));
return true;
} // END hesk_setcookie()
function hesk_create_password_reset_token()
{
return bin2hex(random_bytes(32));
} // END hesk_create_password_reset_token()
function hesk_clean_password_reset_token($token)
{
$token = trim($token);
return preg_match('/\A[a-fA-F0-9]{64}\z/', $token) ? strtolower($token) : '';
} // END hesk_clean_password_reset_token()
function hesk_hash_password_reset_token($token)
{
return hash('sha256', $token);
} // END hesk_hash_password_reset_token()
function hesk_get_service_messages($page=null, $strict_page_check=false)
{
global $hesk_settings, $hesklang, $hesk_db_link;
if (empty($page)) {
$page = 'home';
}
$res = hesk_dbQuery('SELECT `title`, `message`, `style` FROM `'.hesk_dbEscape($hesk_settings['db_pfix'])."service_messages`
WHERE `type`='0'
AND ".($strict_page_check ? "`location` LIKE '%".hesk_dbEscape($page)."%'" : "(" . ($page == 'home' ? '`location` IS NULL OR ' : '')."`location`='ALL' OR `location` LIKE '%".hesk_dbEscape($page)."%')")."
AND (`language` IS NULL OR `language` LIKE '".hesk_dbEscape($hesk_settings['language'])."')
ORDER BY `order` ASC"
);
$service_messages = array();
while ($sm=hesk_dbFetchAssoc($res)) {
$service_messages[] = $sm;
}
return $service_messages;
} // END hesk_get_service_messages()
function hesk_service_message($sm)
{
switch ($sm['style'])
{
case 1:
$style = "green";
$adaRole = "status";
break;
case 2:
$style = "blue";
$adaRole = "status";
break;
case 3:
$style = "orange";
$adaRole = "alert";
break;
case 4:
$style = "red";
$adaRole = "alert";
break;
default:
$style = "white";
$adaRole = "log";
}
?>
<div class="main__content notice-flash">
<div role="<?php echo $adaRole; ?>" class="notification <?php echo $style; ?> browser-default">
<p><b><?php echo $sm['title']; ?></b></p>
<?php echo $sm['message']; ?>
</div>
</div>
<?php
} // END hesk_service_message()
function hesk_isBannedIP($ip)
{
global $hesk_settings, $hesklang, $hesk_db_link;
$ip = ip2long($ip) or $ip = 0;
// We need positive value of IP
if ($ip < 0)
{
$ip += 4294967296;
}
elseif ($ip > 4294967296)
{
$ip = 4294967296;
}
$res = hesk_dbQuery("SELECT `id` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."banned_ips` WHERE {$ip} BETWEEN `ip_from` AND `ip_to` LIMIT 1");
return ( hesk_dbNumRows($res) == 1 ) ? hesk_dbResult($res) : false;
} // END hesk_isBannedIP()
function hesk_isBannedEmail($email)
{
global $hesk_settings, $hesklang, $hesk_db_link;
$email = strtolower($email);
$res = hesk_dbQuery("SELECT `id` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."banned_emails` WHERE `email` IN ('".hesk_dbEscape($email)."', '".hesk_dbEscape( substr($email, strrpos($email, "@") ) )."') LIMIT 1");
return ( hesk_dbNumRows($res) == 1 ) ? hesk_dbResult($res) : false;
} // END hesk_isBannedEmail()
function hesk_isMutedEmail($email)
{
global $hesk_settings, $hesklang, $hesk_db_link;
$email = strtolower($email);
$res = hesk_dbQuery("SELECT `id` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."muted_emails` WHERE `email` IN ('".hesk_dbEscape($email)."', '".hesk_dbEscape( substr($email, strrpos($email, "@") ) )."') LIMIT 1");
return ( hesk_dbNumRows($res) == 1 ) ? hesk_dbResult($res) : false;
} // END hesk_isMutedEmail()
function hesk_clean_utf8($in)
{
if ($in === null) {
return '';
}
//reject overly long 2 byte sequences, as well as characters above U+10000 and replace with ?
$in = preg_replace('/[\x00-\x08\x10\x0B\x0C\x0E-\x19\x7F]'.
'|[\x00-\x7F][\x80-\xBF]+'.
'|([\xC0\xC1]|[\xF0-\xFF])[\x80-\xBF]*'.
'|[\xC2-\xDF]((?![\x80-\xBF])|[\x80-\xBF]{2,})'.
'|[\xE0-\xEF](([\x80-\xBF](?![\x80-\xBF]))|(?![\x80-\xBF]{2})|[\x80-\xBF]{3,})/S',
'?', $in );
//reject overly long 3 byte sequences and UTF-16 surrogates and replace with ?
$in = preg_replace('/\xE0[\x80-\x9F][\x80-\xBF]'.
'|\xED[\xA0-\xBF][\x80-\xBF]/S','?', $in );
return $in;
} // END hesk_clean_utf8()
function hesk_load_database_functions()
{
// Already loaded?
if (function_exists('hesk_dbQuery'))
{
return true;
}
// Preferrably use the MySQLi functions
elseif ( function_exists('mysqli_connect') )
{
require(HESK_PATH . 'inc/database_mysqli.inc.php');
}
// Default to MySQL
else
{
require(HESK_PATH . 'inc/database.inc.php');
}
} // END hesk_load_database_functions()
function hesk_unlink($file, $older_than=0)
{
return ( is_file($file) && ( ! $older_than || (time()-filectime($file)) > $older_than ) && @unlink($file) ) ? true : false;
} // END hesk_unlink()
function hesk_copy($old_path, $new_path) {
return is_file($old_path) && @copy($old_path, $new_path);
} // END hesk_copy()
function hesk_rename($old_path, $new_path) {
return is_file($old_path) && @rename($old_path, $new_path);
} // END hesk_rename()
function hesk_unlink_callable($file, $key, $older_than=0)
{
return hesk_unlink($file, $older_than);
} // END hesk_unlink_callable()
function hesk_utf8_urldecode($in)
{
if ($in === null) {
return '';
}
$in = preg_replace("/%u([0-9a-f]{3,4})/i","&#x\\1;", urldecode($in));
return hesk_html_entity_decode($in);
} // END hesk_utf8_urldecode
function hesk_SESSION($in, $default = '')
{
if (is_array($in))
{
return isset($_SESSION[$in[0]][$in[1]]) && ! is_array(isset($_SESSION[$in[0]][$in[1]])) ? $_SESSION[$in[0]][$in[1]] : $default;
}
else
{
return isset($_SESSION[$in]) && ! is_array($_SESSION[$in]) ? $_SESSION[$in] : $default;
}
} // END hesk_SESSION();
function hesk_SESSION_array($in, $default = []) {
return isset($_SESSION[$in]) && is_array($_SESSION[$in]) ? $_SESSION[$in] : $default;
}
function hesk_COOKIE($in, $default = '')
{
return isset($_COOKIE[$in]) && ! is_array($_COOKIE[$in]) ? $_COOKIE[$in] : $default;
} // END hesk_COOKIE();
function hesk_GET($in, $default = '')
{
return isset($_GET[$in]) && ! is_array($_GET[$in]) ? $_GET[$in] : $default;
} // END hesk_GET()
function hesk_restricted_GET($in, $allowed_values, $default = '')
{
if (!isset($_GET[$in]) || is_array($_GET[$in])) {
return $default;
}
$value = $_GET[$in];
return in_array($value, $allowed_values) ? $value : $default;
} // END hesk_restricted_GET()
function hesk_POST($in, $default = '')
{
return isset($_POST[$in]) && ! is_array($_POST[$in]) ? $_POST[$in] : $default;
} // END hesk_POST()
function hesk_POST_array($in, $default = array() )
{
return isset($_POST[$in]) && is_array($_POST[$in]) ? $_POST[$in] : $default;
} // END hesk_POST_array()
function hesk_REQUEST($in, $default = false)
{
return isset($_GET[$in]) ? hesk_input( hesk_GET($in) ) : ( isset($_POST[$in]) ? hesk_input( hesk_POST($in) ) : $default );
} // END hesk_REQUEST()
function hesk_isREQUEST($in)
{
return isset($_GET[$in]) || isset($_POST[$in]) ? true : false;
} // END hesk_isREQUEST()
function hesk_mb_substr($in, $start, $length)
{
if ($in === null) {
return '';
}
return function_exists('mb_substr') ? mb_substr($in, $start, $length, 'UTF-8') : substr($in, $start, $length);
} // END hesk_mb_substr()
function hesk_mb_strlen($in)
{
if ($in === null) {
return 0;
}
return function_exists('mb_strlen') ? mb_strlen($in, 'UTF-8') : strlen($in);
} // END hesk_mb_strlen()
function hesk_mb_strtolower($in)
{
if ($in === null) {
return '';
}
return function_exists('mb_strtolower') ? mb_strtolower($in, 'UTF-8') : strtolower($in);
} // END hesk_mb_strtolower()
function hesk_mb_strtoupper($in)
{
if ($in === null) {
return '';
}
return function_exists('mb_strtoupper') ? mb_strtoupper($in, 'UTF-8') : strtoupper($in);
} // END hesk_mb_strtolower()
function hesk_ucfirst($in)
{
if ($in === null) {
return '';
}
return function_exists('mb_convert_case') ? mb_convert_case($in, MB_CASE_TITLE, 'UTF-8') : ucfirst($in);
} // END hesk_mb_ucfirst()
function hesk_htmlspecialchars_decode($in)
{
if ($in === null) {
return '';
}
return str_replace( array('&', '<', '>', '"'), array('&', '<', '>', '"'), $in);
} // END hesk_htmlspecialchars_decode()
function hesk_html_entity_decode($in)
{
if ($in === null) {
return '';
}
return html_entity_decode($in, ENT_COMPAT | ENT_XHTML, 'UTF-8');
#return html_entity_decode($in, ENT_COMPAT | ENT_XHTML, 'ISO-8859-1');
} // END hesk_html_entity_decode()
function hesk_htmlspecialchars($in)
{
if ($in === null) {
return '';
}
return htmlspecialchars($in, ENT_COMPAT | ENT_SUBSTITUTE | ENT_XHTML, 'UTF-8');
#return htmlspecialchars($in, ENT_COMPAT | ENT_SUBSTITUTE | ENT_XHTML, 'ISO-8859-1');
} // END hesk_htmlspecialchars()
function hesk_htmlentities($in)
{
if ($in === null) {
return '';
}
return htmlentities($in, ENT_COMPAT | ENT_SUBSTITUTE | ENT_XHTML, 'UTF-8');
#return htmlentities($in, ENT_COMPAT | ENT_SUBSTITUTE | ENT_XHTML, 'ISO-8859-1');
} // END hesk_htmlentities()
function hesk_slashJS($in)
{
if ($in === null) {
return '';
}
return str_replace( '\'', '\\\'', $in);
} // END hesk_slashJS()
function hesk_verifyEmailMatch($trackingID, $my_email = 0, $ticket_emails = [], $error = 1)
{
global $hesk_settings, $hesklang, $hesk_db_link;
$customer_accounts_enabled = ! empty($hesk_settings['customer_accounts']);
$customer_account_access_required = $customer_accounts_enabled && ! empty($hesk_settings['customer_accounts_required']);
$logged_in_customer = null;
if ($customer_accounts_enabled)
{
if ( ! function_exists('hesk_isCustomerLoggedIn'))
{
require_once(HESK_PATH . 'inc/customer_accounts.inc.php');
}
$logged_in_customer = hesk_isCustomerLoggedIn($customer_account_access_required && $error);
// Customer autologin may return true after setting the session;
// fetch the actual customer context before checking ticket ownership.
if ($logged_in_customer === true)
{
$logged_in_customer = hesk_isCustomerLoggedIn(false);
}
if (is_array($logged_in_customer))
{
$logged_in_customer_email = isset($logged_in_customer['email']) ? $logged_in_customer['email'] : '';
$hesk_settings['e_param'] = '';
$hesk_settings['e_query'] = '';
$hesk_settings['e_email'] = $logged_in_customer_email;
$res = hesk_dbQuery("SELECT 1
FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` `tickets`
INNER JOIN `".hesk_dbEscape($hesk_settings['db_pfix'])."ticket_to_customer` `ticket_customer`
ON `tickets`.`id` = `ticket_customer`.`ticket_id`
WHERE `tickets`.`trackid` = '".hesk_dbEscape($trackingID)."'
AND `ticket_customer`.`customer_id` = ".intval($logged_in_customer['id'])."
LIMIT 1");
if (hesk_dbNumRows($res))
{
hesk_cleanBfAttempts();
return true;
}
// If customer accounts are required, access must be tied to the logged-in
// customer account. If accounts are optional, fall back to the legacy
// email/tracking-ID rules below, but use the logged-in customer's email
// instead of any email supplied by URL, POST, or cookie. This preserves
// optional-account behavior without weakening required-account access.
if ($customer_account_access_required)
{
if ($error)
{
hesk_setcookie('hesk_myemail', '');
hesk_process_messages($hesklang['enmdb'], 'my_tickets.php');
}
return false;
}
$my_email = $logged_in_customer_email;
}
elseif ($customer_account_access_required)
{
return false;
}
}
/* Email required to view ticket? */
if ( ! $hesk_settings['email_view_ticket'])
{
$hesk_settings['e_param'] = '';
$hesk_settings['e_query'] = '';
$hesk_settings['e_email'] = '';
return true;
}
/* Limit brute force attempts */
hesk_limitBfAttempts();
// handle edge case: email is required to view tickets, but is not required to submit a ticket
// if the ticket was submitted without an email, match an empty mail
// if the ticket was submitted with an email, it must match
if ($hesk_settings['require_email'] == 0) {
if (in_array('', $ticket_emails)) {
$hesk_settings['e_param'] = '';
$hesk_settings['e_query'] = '';
$hesk_settings['e_email'] = '';
return true;
} elseif (empty($my_email)) {
return 'EMAIL_REQUIRED';
} else {
$hesk_settings['tmp_skip_redirect'] = true;
}
}
/* Get email address */
if ($my_email || is_array($logged_in_customer))
{
$hesk_settings['e_param'] = '&e=' . rawurlencode($my_email);
$hesk_settings['e_query'] = '&e=' . rawurlencode($my_email);
$hesk_settings['e_email'] = $my_email;
}
else
{
$my_email = hesk_getCustomerEmail();
}
/* Get emails from ticket */
if (empty($ticket_emails))
{
$res = hesk_dbQuery("SELECT `customers`.`email` AS `email`
FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` `tickets`
INNER JOIN `".hesk_dbEscape($hesk_settings['db_pfix'])."ticket_to_customer` `ticket_customer`
ON `tickets`.`id` = `ticket_customer`.`ticket_id`
INNER JOIN `".hesk_dbEscape($hesk_settings['db_pfix'])."customers` `customers`
ON `ticket_customer`.`customer_id` = `customers`.`id`
WHERE `trackid`='".hesk_dbEscape($trackingID)."'");
while ($row = hesk_dbFetchAssoc($res)) {
$ticket_emails[] = $row['email'];
}
if (empty($ticket_emails))
{
hesk_process_messages($hesklang['ticket_not_found'],'ticket.php');
}
}
/* Validate email */
foreach ($ticket_emails as $email) {
if (strtolower($my_email) === strtolower($email)) {
/* Match, clean brute force attempts and return true */
hesk_cleanBfAttempts();
return true;
}
}
/* Email doesn't match, clean cookies and error out */
if ($error)
{
hesk_setcookie('hesk_myemail', '');
if ( ! empty($hesk_settings['tmp_skip_redirect'])) {
return 'EMAIL_FALSE';
}
hesk_process_messages($hesklang['enmdb'],'ticket.php?track='.$trackingID.'&Refresh='.rand(10000,99999));
}
else
{
return false;
}
} // END hesk_verifyEmailMatch()
function hesk_getCustomerEmail($can_remember = 0, $field = '', $force_only_one = 0)
{
global $hesk_settings, $hesklang;
/* Email required to view ticket? */
if ( ! $hesk_settings['email_view_ticket'])
{
$hesk_settings['e_param'] = '';
$hesk_settings['e_query'] = '';
$hesk_settings['e_email'] = '';
return '';
}
/* Is this a form that enables remembering email? */
if ($can_remember)
{
global $do_remember;
}
$my_email = '';
/* Is email in session? */
if ( strlen($field) && isset($_SESSION[$field]) )
{
$my_email = hesk_validateEmail($_SESSION[$field], 'ERR', 0);
}
/* Is email in query string? */
elseif ( isset($_GET['e']) || isset($_POST['e']) )
{
$my_email = hesk_validateEmail( hesk_REQUEST('e') ,'ERR',0);
}
/* Is email in cookie? */
elseif ( isset($_COOKIE['hesk_myemail']) )
{
$my_email = hesk_validateEmail( hesk_COOKIE('hesk_myemail'), 'ERR', 0);
if ($can_remember && $my_email)
{
$do_remember = ' checked="checked" ';
}
}
// Remove unwanted side-effects
$my_email = hesk_emailCleanup($my_email);
// Force only one email address? Use the first one.
if ($force_only_one)
{
$my_email = strtok($my_email, ',');
}
$hesk_settings['e_param'] = '&e=' . rawurlencode($my_email);
$hesk_settings['e_query'] = '&e=' . rawurlencode($my_email);
$hesk_settings['e_email'] = $my_email;
return $my_email;
} // END hesk_getCustomerEmail()
function hesk_emailCleanup($my_email)
{
return preg_replace("/(\\\)+'/", "'", $my_email);
} // END hesk_emailCleanup()
function hesk_formatBytes($size, $translate_unit = 1, $precision = 2)
{
global $hesklang;
$units = array(
'GB' => 1073741824,
'MB' => 1048576,
'kB' => 1024,
'B' => 1
);
foreach ($units as $suffix => $bytes)
{
if ($bytes > $size)
{
continue;
}
$full = $size / $bytes;
$round = round($full, $precision);
if ($full == $round)
{
if ($translate_unit)
{
return $round . ' ' . $hesklang[$suffix];
}
else
{
return $round . ' ' . $suffix;
}
}
}
return false;
} // End hesk_formatBytes()
function hesk_getAutoAssignConfigDisplay($autoassign_config) {
global $hesklang;
if ($autoassign_config === '' || $autoassign_config === null) {
return '';
}
$parsed_config = hesk_parseAutoAssignConfig($autoassign_config);
if (count($parsed_config['ids']) === 0) {
return '';
}
$language_key = $parsed_config['operator'] === 'IN' ? 'included' : 'excluded';
$user_count = hesk_getCountOfActiveUsersByIds($parsed_config['ids']);
$count_key = $user_count === 1 ? 'one_user' : 'x_users';
return sprintf($hesklang["{$count_key}_{$language_key}"], $user_count);
}
function hesk_parseAutoAssignConfig($autoassign_config) {
$result = array(
'operator' => '', // '' used by autoassign check
'ids' => array()
);
if ($autoassign_config === '' || $autoassign_config === null) {
return $result;
}
// regex = !(1,2,3) or =(1,2,3) | ! - NOT IN, = - IN
$regex = '/([!=])?\((.*)\)/';
if (!is_string($autoassign_config) || !preg_match($regex, $autoassign_config, $matches) || !isset($matches[2])) {
$result['operator'] = 'IN';
return $result;
}
$result['operator'] = isset($matches[1]) && $matches[1] === '!' ? 'NOT IN' : 'IN';
$result['ids'] = $matches[2] === '' ? array() : array_map('intval', explode(',', $matches[2]));
return $result;
}
function hesk_getCountOfActiveUsersByIds($ids) {
return count(hesk_getActiveAutoassignUsersForIds($ids));
}
function hesk_getActiveAutoassignUsersForIds($ids) {
global $hesk_settings;
if (!is_array($ids) || count($ids) === 0) {
return array();
}
$ids = array_map('intval', $ids);
$res = hesk_dbQuery("SELECT `id` FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "users` WHERE `active` = 1 AND `id` IN (" . implode(',', $ids) . ")");
$ids = array();
while ($row = hesk_dbFetchAssoc($res)) {
$ids[] = $row['id'];
}
return $ids;
}
function hesk_updateAutoassignConfigs() {
global $hesk_settings;
$res = hesk_dbQuery("SELECT `id`, `autoassign_config` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."categories` WHERE `autoassign_config` <> ''");
while ($row = hesk_dbFetchAssoc($res)) {
$parsed_config = hesk_parseAutoAssignConfig($row['autoassign_config']);
$active_users = hesk_getActiveAutoassignUsersForIds($parsed_config['ids']);
// 1. No active users. Switch to either On - All, or Off
if (count($active_users) === 0) {
// Including no one is the same as off, and vice-versa
$autoassign = $parsed_config['operator'] === 'IN' ? 0 : 1;
hesk_dbQuery("UPDATE `".hesk_dbEscape($hesk_settings['db_pfix'])."categories` SET `autoassign` = '{$autoassign}', `autoassign_config` = '' WHERE `id` = {$row['id']}");
} else {
// Build a new autoassign config
$operator = $parsed_config['operator'] === 'IN' ? '=' : '!';
$stringed_users = implode(',', $active_users);
$autoassign_config = "{$operator}({$stringed_users})";
hesk_dbQuery("UPDATE `".hesk_dbEscape($hesk_settings['db_pfix'])."categories` SET `autoassign_config` = '{$autoassign_config}' WHERE `id` = {$row['id']}");
}
}
}
function hesk_autoAssignTicket($ticket_category)
{
global $hesk_settings, $hesklang;
/* Auto assign ticket enabled? */
if ( ! $hesk_settings['autoassign'])
{
return false;
}
$autoassign_owner = array();
/* Get all possible auto-assign staff, order by number of open tickets */
$res = hesk_dbQuery("SELECT `t1`.`id`,`t1`.`user`,`t1`.`name`, `t1`.`autoassign`, `t1`.`email`, `t1`.`nickname`, `t1`.`language`, `t1`.`isadmin`, `t1`.`categories`, `t1`.`notify_assigned`, `t1`.`heskprivileges`,
(SELECT COUNT(*) FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` FORCE KEY (`statuses`) WHERE `owner`=`t1`.`id` AND `status` <> '3' ) as `open_tickets`
FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."users` AS `t1`
WHERE `t1`.`active` = 1
ORDER BY `open_tickets` ASC, RAND()");
$autoassign_config_res = hesk_dbQuery("SELECT `autoassign_config` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."categories` WHERE `id` = ".intval($ticket_category));
$autoassign_config = hesk_dbFetchAssoc($autoassign_config_res);
$parsed_autoassign_config = hesk_parseAutoAssignConfig($autoassign_config['autoassign_config']);
// Fetch categories / features assigned via permission group
$permission_groups_rs = hesk_dbQuery("SELECT `member`.`user_id` AS `user_id`, `category`.`category_id` AS `category_feature_value`, 'CATEGORY' AS `category_feature_type`
FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."permission_group_members` AS `member`
INNER JOIN `".hesk_dbEscape($hesk_settings['db_pfix'])."permission_group_categories` AS `category`
ON `member`.`group_id` = `category`.`group_id`
UNION ALL
SELECT `member`.`user_id` AS `user_id`, `feature`.`feature` AS `category_feature_value`, 'FEATURE' AS `category_feature_type`
FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."permission_group_members` AS `member`
INNER JOIN `".hesk_dbEscape($hesk_settings['db_pfix'])."permission_group_features` AS `feature`
ON `member`.`group_id` = `feature`.`group_id`");
$user_to_pg_features = [];
$user_to_pg_categories = [];
while ($row = hesk_dbFetchAssoc($permission_groups_rs)) {
$user_id = intval($row['user_id']);
if (!key_exists($user_id, $user_to_pg_categories)) {
$user_to_pg_categories[$user_id] = [];
$user_to_pg_features[$user_id] = [];
}
if ($row['category_feature_type'] === 'CATEGORY') {
$user_to_pg_categories[$user_id][] = intval($row['category_feature_value']);
} else {
$user_to_pg_features[$user_id][] = $row['category_feature_value'];
}
}
/* Loop through the rows and return the first appropriate one */
while ($myuser = hesk_dbFetchAssoc($res))
{
$int_myuser_id = intval($myuser['id']);
if (!key_exists($int_myuser_id, $user_to_pg_features)) {
$user_to_pg_features[$int_myuser_id] = [];
$user_to_pg_categories[$int_myuser_id] = [];
}
/*
If "On - Select Users": Is the user allowed to be selected for this category?
If "On - All Users": Does the user have autoassign enabled on their user record?
*/
if (($parsed_autoassign_config['operator'] === 'IN' && !in_array($myuser['id'], $parsed_autoassign_config['ids'])) ||
($parsed_autoassign_config['operator'] === 'NOT IN' && in_array($myuser['id'], $parsed_autoassign_config['ids'])) ||
($parsed_autoassign_config['operator'] === '' && $myuser['autoassign'] === '0')) {
continue;
}
/* Is this an administrator? */
if ($myuser['isadmin'])
{
$autoassign_owner = $myuser;
$hesk_settings['user_data'][$myuser['id']] = $myuser;
hesk_dbFreeResult($res);
break;
}
/* Not and administrator, check two things: */
/* --> can view and reply to tickets */
$can_view_tickets = strpos($myuser['heskprivileges'], 'can_view_tickets') !== false || in_array('can_view_tickets', $user_to_pg_features[$int_myuser_id]);
$can_reply_tickets = strpos($myuser['heskprivileges'], 'can_reply_tickets') !== false || in_array('can_reply_tickets', $user_to_pg_features[$int_myuser_id]);
if (!$can_view_tickets || !$can_reply_tickets)
{
continue;
}
/* --> has access to ticket category */
$myuser['categories'] = explode(',',$myuser['categories']);
$myuser['categories'] = array_merge($myuser['categories'], $user_to_pg_categories[$int_myuser_id]);
if (in_array($ticket_category,$myuser['categories']))
{
$autoassign_owner = $myuser;
$hesk_settings['user_data'][$myuser['id']] = $myuser;
hesk_dbFreeResult($res);
break;
}
}
return $autoassign_owner;
} // END hesk_autoAssignTicket()
function hesk_cleanID($field='track', $in=false)
{
$id = '';
if ($in !== false)
{
$id = $in;
}
elseif ( isset($_SESSION[$field]) )
{
$id = $_SESSION[$field];
}
elseif ( isset($_GET[$field]) && ! is_array($_GET[$field]) )
{
$id = $_GET[$field];
}
elseif ( isset($_POST[$field]) && ! is_array($_POST[$field]) )
{
$id = $_POST[$field];
}
else
{
return false;
}
return substr( preg_replace('/[^A-Z0-9\-]/','',strtoupper($id)) , 0, 12);
} // END hesk_cleanID()
function hesk_createID()
{
global $hesk_settings, $hesklang, $hesk_error_buffer;
/*** Generate tracking ID and make sure it's not a duplicate one ***/
/* Ticket ID can be of these chars */
$useChars = 'AEUYBDGHJLMNPQRSTVWXZ123456789';
/* Set tracking ID to an empty string */
$trackingID = '';
/* Let's avoid duplicate ticket ID's, try up to 3 times */
for ($i=1;$i<=3;$i++)
{
/* Generate raw ID */
$trackingID .= $useChars[mt_rand(0,29)];
$trackingID .= $useChars[mt_rand(0,29)];
$trackingID .= $useChars[mt_rand(0,29)];
$trackingID .= $useChars[mt_rand(0,29)];
$trackingID .= $useChars[mt_rand(0,29)];
$trackingID .= $useChars[mt_rand(0,29)];
$trackingID .= $useChars[mt_rand(0,29)];
$trackingID .= $useChars[mt_rand(0,29)];
$trackingID .= $useChars[mt_rand(0,29)];
$trackingID .= $useChars[mt_rand(0,29)];
/* Format the ID to the correct shape and check wording */
$trackingID = hesk_formatID($trackingID);
/* Check for duplicate IDs */
$res = hesk_dbQuery("SELECT `id` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` WHERE `trackid` = '".hesk_dbEscape($trackingID)."' LIMIT 1");
if (hesk_dbNumRows($res) == 0)
{
/* Everything is OK, no duplicates found */
return $trackingID;
}
/* A duplicate ID has been found! Let's try again (up to 2 more) */
$trackingID = '';
}
/* No valid tracking ID, try one more time with microtime() */
$trackingID = $useChars[mt_rand(0,29)];
$trackingID .= $useChars[mt_rand(0,29)];
$trackingID .= $useChars[mt_rand(0,29)];
$trackingID .= $useChars[mt_rand(0,29)];
$trackingID .= $useChars[mt_rand(0,29)];
$trackingID .= substr(microtime(), -5);
/* Format the ID to the correct shape and check wording */
$trackingID = hesk_formatID($trackingID);
$res = hesk_dbQuery("SELECT `id` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` WHERE `trackid` = '".hesk_dbEscape($trackingID)."' LIMIT 1");
/* All failed, must be a server-side problem... */
if (hesk_dbNumRows($res) == 0)
{
return $trackingID;
}
$hesk_error_buffer['etid'] = $hesklang['e_tid'];
return false;
} // END hesk_createID()
function hesk_formatID($id)
{
$useChars = 'AEUYBDGHJLMNPQRSTVWXZ123456789';
$replace = $useChars[mt_rand(0,29)];
$replace .= mt_rand(1,9);
$replace .= $useChars[mt_rand(0,29)];
/*
Remove 3 letter bad words from ID
Possiblitiy: 1:27,000
*/
$remove = array(
'ASS',
'CUM',
'FAG',
'FUK',
'GAY',
'SEX',
'TIT',
'XXX',
);
$id = str_replace($remove,$replace,$id);
/*
Remove 4 letter bad words from ID
Possiblitiy: 1:810,000
*/
$remove = array(
'ANAL',
'ANUS',
'BUTT',
'CAWK',
'CLIT',
'COCK',
'CRAP',
'CUNT',
'DICK',
'DYKE',
'FART',
'FUCK',
'JAPS',
'JERK',
'JIZZ',
'KNOB',
'PISS',
'POOP',
'SHIT',
'SLUT',
'SUCK',
'TURD',
// Also, remove words that are known to trigger mod_security
'WGET',
);
$replace .= mt_rand(1,9);
$id = str_replace($remove,$replace,$id);
/* Format the ID string into XXX-XXX-XXXX format for easier readability */
$id = $id[0].$id[1].$id[2].'-'.$id[3].$id[4].$id[5].'-'.$id[6].$id[7].$id[8].$id[9];
return $id;
} // END hesk_formatID()
function hesk_cleanBfAttempts()
{
global $hesk_settings, $hesklang;
/* If this feature is disabled, just return */
if ( ! $hesk_settings['attempt_limit'] || defined('HESK_BF_CLEAN') )
{
return true;
}
/* Delete expired logs from the database */
$res = hesk_dbQuery("DELETE FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."logins` WHERE `ip`='".hesk_dbEscape(hesk_getClientIP())."'");
define('HESK_BF_CLEAN', 1);
return true;
} // END hesk_cleanAttempts()
function hesk_forceLogout($error_message = '', $redirect = 'index.php', $do_die = true, $message_type = 'ERROR')
{
global $hesk_settings, $hesklang;
if (($id = hesk_SESSION('id', false)) === false) {
return true;
}
// Set Offline
if ($hesk_settings['online']) {
if ( ! function_exists('hesk_setOffline')) {
require(HESK_PATH . 'inc/users_online.inc.php');
}
hesk_setOffline($id);
}
// Clear users' authentication and MFA tokens
hesk_dbQuery("DELETE FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."auth_tokens` WHERE `user_id` = {$id} AND `user_type` = 'STAFF'");
hesk_dbQuery("DELETE FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."mfa_verification_tokens` WHERE `user_id` = {$id} AND `user_type` = 'STAFF'");
// Stop the session and clear cookies
hesk_session_stop();
hesk_setcookie('hesk_username', '');
hesk_setcookie('hesk_remember', '');
// Send the user to the login page?
if ($redirect !== false) {
hesk_session_start();
hesk_process_messages($error_message, 'index.php', $message_type);
}
if ($do_die) {
exit();
}
} // END hesk_forceLogout()
function hesk_forceLogoutCustomer($error_message = '', $redirect = 'index.php', $do_die = true, $message_type = 'ERROR')
{
global $hesk_settings, $hesklang;
if (($id = hesk_SESSION(array('customer', 'id'), false)) === false) {
return true;
}
// Clear users MFA and auth tokens
hesk_dbQuery("DELETE FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."mfa_verification_tokens` WHERE `user_id` = {$id} AND `user_type` = 'CUSTOMER'");
hesk_dbQuery("DELETE FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."auth_tokens` WHERE `user_id` = {$id} AND `user_type` = 'CUSTOMER'");
// Stop the session and clear cookies
hesk_session_stop();
hesk_setcookie('hesk_customer_remember', '');
// Send the user to the login page?
if ($redirect !== false) {
hesk_session_start('CUSTOMER');
hesk_process_messages($error_message, $redirect, $message_type);
}
if ($do_die) {
exit();
}
} // END hesk_forceLogoutCustomer()
function hesk_limitInternalBfAttempts()
{
return hesk_limitBfAttempts(false);
} // END hesk_limitInternalBfAttempts()
function hesk_limitBfAttempts($die_with_error = true)
{
global $hesk_settings, $hesklang;
// Check if this IP is banned permanently
if ( hesk_isBannedIP(hesk_getClientIP()) )
{
if (isset($_SESSION['customer'])) {
hesk_forceLogoutCustomer($hesklang['baned_ip']);
} else {
hesk_forceLogout($hesklang['baned_ip']);
}
hesk_error($hesklang['baned_ip'], 0);
}
/* If this feature is disabled or already called, return false */
if ( ! $hesk_settings['attempt_limit'] || defined('HESK_BF_LIMIT') )
{
return false;
}
/* Define this constant to avoid duplicate checks */
define('HESK_BF_LIMIT', 1);
$ip = hesk_getClientIP();
/* Get number of failed attempts from the database */
$res = hesk_dbQuery("SELECT `number`, (CASE WHEN `last_attempt` IS NOT NULL AND DATE_ADD(`last_attempt`, INTERVAL ".intval($hesk_settings['attempt_banmin'])." MINUTE ) > NOW() THEN 1 ELSE 0 END) AS `banned` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."logins` WHERE `ip`='".hesk_dbEscape($ip)."' LIMIT 1");
/* Not in the database yet? Add first one and return false */
if (hesk_dbNumRows($res) != 1)
{
hesk_dbQuery("INSERT INTO `".hesk_dbEscape($hesk_settings['db_pfix'])."logins` (`ip`) VALUES ('".hesk_dbEscape($ip)."')");
return false;
}
/* Get number of failed attempts and increase by 1 */
$row = hesk_dbFetchAssoc($res);
$row['number']++;
/* If too many failed attempts either return error or reset count if time limit expired */
if ($row['number'] >= $hesk_settings['attempt_limit'])
{
if ($row['banned'])
{
// Sometimes we just want to log the user out and reset the number of attempts, not ban immediately
if ( ! $die_with_error)
{
hesk_dbQuery("DELETE FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."logins` WHERE `ip`='".hesk_dbEscape($ip)."'");
if (isset($_SESSION['customer'])) {
hesk_forceLogoutCustomer($hesklang['baned_ip']);
} else {
hesk_forceLogout($hesklang['baned_ip']);
}
}
$error = sprintf($hesklang['yhbb'], $hesk_settings['attempt_banmin']);
// If this is a logged-in user, log out
if (isset($_SESSION['customer'])) {
hesk_forceLogoutCustomer($hesklang['baned_ip']);
} else {
hesk_forceLogout($hesklang['baned_ip']);
}
// Not a logged-in user, throw an error
unset($_SESSION);
hesk_error($error, 0);
}
else
{
$row['number'] = 1;
}
}
hesk_dbQuery("UPDATE `".hesk_dbEscape($hesk_settings['db_pfix'])."logins` SET `number`=".intval($row['number'])." WHERE `ip`='".hesk_dbEscape($ip)."'");
return false;
} // END hesk_limitAttempts()
function hesk_getCategoryName($id)
{
global $hesk_settings, $hesklang;
if (empty($id))
{
return $hesklang['unas'];
}
// If we already have the name no need to query DB another time
if ( isset($hesk_settings['category_data'][$id]['name']) )
{
return $hesk_settings['category_data'][$id]['name'];
}
$res = hesk_dbQuery("SELECT `name` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."categories` WHERE `id`='".intval($id)."' LIMIT 1");
if (hesk_dbNumRows($res) != 1)
{
return $hesklang['catd'];
}
$hesk_settings['category_data'][$id]['name'] = hesk_dbResult($res,0,0);
return $hesk_settings['category_data'][$id]['name'];
} // END hesk_getCategoryName()
function hesk_getCategoryDueDateInfo($id) {
global $hesk_settings;
// If we already have the name no need to query DB another time
if ( isset($hesk_settings['category_data'][$id]['due_date_info']) )
{
return $hesk_settings['category_data'][$id]['due_date_info'];
}
$res = hesk_dbQuery("SELECT `default_due_date_amount`, `default_due_date_unit` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."categories` WHERE `id`='".intval($id)."' AND `default_due_date_amount` IS NOT NULL LIMIT 1");
if (hesk_dbNumRows($res) != 1)
{
return null;
}
$category = hesk_dbFetchAssoc($res);
$hesk_settings['category_data'][$id]['due_date_info'] = array(
'amount' => $category['default_due_date_amount'],
'unit' => $category['default_due_date_unit']
);
return $hesk_settings['category_data'][$id]['due_date_info'];
}
function hesk_getReplierNameArray($ticket)
{
global $hesk_settings, $hesklang;
// Already have this info?
if (isset($ticket['last_reply_by'])) {
return $ticket['last_reply_by'];
}
// Last reply by staff
if ( ! empty($ticket['lastreplier'])) {
// We don't know who from staff so just send "Staff"
if (empty($ticket['replierid'])) {
return array('name' => $hesklang['staff'], 'nickname' => $hesklang['staff']);
}
// Get the name using another function
$replier = hesk_getStaffNameArray($ticket['replierid']);
// If replier comes back as "unassigned", default to "Staff"
if ($replier === false) {
return array('name' => $hesklang['staff'], 'nickname' => $hesklang['staff']);
}
return $hesk_settings['user_data'][$ticket['replierid']];
}
// Last reply by customer
if ($ticket['replies'] > 0) {
// Get latest customer reply
$replier_rs = hesk_dbQuery("SELECT `customer`.`name` AS `name`, `customer`.`email` AS `email`
FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."replies` AS `reply`
LEFT JOIN `".hesk_dbEscape($hesk_settings['db_pfix'])."customers` AS `customer`
ON `reply`.`customer_id` = `customer`.`id`
WHERE `replyto` = ".intval($ticket['id'])."
AND `staffid` = 0
ORDER BY `reply`.`id` DESC
LIMIT 1");
if ($row = hesk_dbFetchAssoc($replier_rs)) {
if ($row['name'] === null || $row['name'] == '') {
$row['name'] = empty($row['email']) ? $hesklang['anon_name'] : $row['email'];
}
return array('name' => $row['name'], 'nickname' => $row['name']);
}
}
// No replies, grab the requester from the main ticket
$requester_name_rs = hesk_dbQuery("SELECT `customer`.`name`, `customer`.`email` AS `email`
FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."ticket_to_customer` AS `ticket_to_customer`
LEFT JOIN `".hesk_dbEscape($hesk_settings['db_pfix'])."customers` AS `customer`
ON `ticket_to_customer`.`customer_id` = `customer`.`id`
WHERE `ticket_to_customer`.`ticket_id` = ".intval($ticket['id'])."
AND `customer_type` = 'REQUESTER'");
if ($row = hesk_dbFetchAssoc($requester_name_rs)) {
if ($row['name'] === null || $row['name'] == '') {
$row['name'] = empty($row['email']) ? $hesklang['anon_name'] : $row['email'];
}
return array('name' => $row['name'], 'nickname' => $row['name']);
}
// Nothing found, return default name
return array('name' => $hesklang['anon_name'], 'nickname' => $hesklang['anon_name']);
} // END hesk_getReplierNameArray()
function hesk_getStaffNameArray($id)
{
global $hesk_settings, $hesklang;
if (empty($id)) {
return false;
}
$id = intval($id);
// If we already have the name no need to query DB another time
if ( isset($hesk_settings['user_data'][$id]) ) {
return $hesk_settings['user_data'][$id];
}
$res = hesk_dbQuery("SELECT `name`, `nickname` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."users` WHERE `id`={$id} LIMIT 1");
if (hesk_dbNumRows($res) != 1) {
return false;
}
$user = hesk_dbFetchAssoc($res);
$hesk_settings['user_data'][$id]['name'] = $user['name'];
$hesk_settings['user_data'][$id]['nickname'] = ($hesk_settings['staff_nicknames'] && $user['nickname'] != '') ? $user['nickname'] : $user['name'];
return $hesk_settings['user_data'][$id];
} // END hesk_getStaffNameArray()
function hesk_cleanSessionVars($arr)
{
if (is_array($arr))
{
foreach ($arr as $str)
{
if (isset($_SESSION[$str]))
{
unset($_SESSION[$str]);
}
}
}
elseif (isset($_SESSION[$arr]))
{
unset($_SESSION[$arr]);
}
} // End hesk_cleanSessionVars()
function hesk_process_messages($message,$redirect_to,$type='ERROR')
{
global $hesk_settings, $hesklang;
switch ($type)
{
case 'SUCCESS':
$_SESSION['HESK_SUCCESS'] = TRUE;
break;
case 'NOTICE':
$_SESSION['HESK_NOTICE'] = TRUE;
break;
case 'INFO':
$_SESSION['HESK_INFO'] = TRUE;
break;
default:
$_SESSION['HESK_ERROR'] = TRUE;
}
$_SESSION['HESK_MESSAGE'] = $message;
/* In some cases we don't want a redirect */
if ($redirect_to == 'NOREDIRECT')
{
return TRUE;
}
header('Location: '.$redirect_to);
exit();
} // END hesk_process_messages()
function hesk_get_messages() {
global $hesk_settings, $hesklang;
$messages = array();
// Primary message - only one can be displayed and HESK_MESSAGE is required
if ( isset($_SESSION['HESK_MESSAGE']) )
{
if ( isset($_SESSION['HESK_SUCCESS']) )
{
$messages[] = array(
'title' => $hesklang['success'],
'style' => '1',
'message' => $_SESSION['HESK_MESSAGE']
);
}
elseif ( isset($_SESSION['HESK_ERROR']) )
{
$messages[] = array(
'title' => $hesklang['error'],
'style' => '4',
'message' => $_SESSION['HESK_MESSAGE']
);
}
elseif ( isset($_SESSION['HESK_NOTICE']) )
{
$messages[] = array(
'title' => $hesklang['note'],
'style' => '3',
'message' => $_SESSION['HESK_MESSAGE']
);
}
elseif ( isset($_SESSION['HESK_INFO']) )
{
$messages[] = array(
'title' => $hesklang['info'],
'style' => '2',
'message' => $_SESSION['HESK_MESSAGE']
);
}
hesk_cleanSessionVars('HESK_MESSAGE');
}
// Cleanup any primary message types set
hesk_cleanSessionVars('HESK_ERROR');
hesk_cleanSessionVars('HESK_SUCCESS');
hesk_cleanSessionVars('HESK_NOTICE');
hesk_cleanSessionVars('HESK_INFO');
// Secondary message
if ( isset($_SESSION['HESK_2ND_NOTICE']) && isset($_SESSION['HESK_2ND_MESSAGE']) )
{
$messages[] = array(
'title' => $hesklang['note'],
'style' => '3',
'message' => $_SESSION['HESK_2ND_MESSAGE']
);
hesk_cleanSessionVars('HESK_2ND_NOTICE');
hesk_cleanSessionVars('HESK_2ND_MESSAGE');
}
return $messages;
}
function hesk_handle_messages()
{
global $hesk_settings, $hesklang;
$return_value = true;
// Primary message - only one can be displayed and HESK_MESSAGE is required
if ( isset($_SESSION['HESK_MESSAGE']) )
{
if ( isset($_SESSION['HESK_SUCCESS']) )
{
hesk_show_success($_SESSION['HESK_MESSAGE']);
}
elseif ( isset($_SESSION['HESK_ERROR']) )
{
hesk_show_error($_SESSION['HESK_MESSAGE']);
$return_value = false;
}
elseif ( isset($_SESSION['HESK_NOTICE']) )
{
hesk_show_notice($_SESSION['HESK_MESSAGE']);
}
elseif ( isset($_SESSION['HESK_INFO']) )
{
hesk_show_info($_SESSION['HESK_MESSAGE']);
}
hesk_cleanSessionVars('HESK_MESSAGE');
}
// Cleanup any primary message types set
hesk_cleanSessionVars('HESK_ERROR');
hesk_cleanSessionVars('HESK_SUCCESS');
hesk_cleanSessionVars('HESK_NOTICE');
hesk_cleanSessionVars('HESK_INFO');
// Secondary message
if ( isset($_SESSION['HESK_2ND_NOTICE']) && isset($_SESSION['HESK_2ND_MESSAGE']) )
{
hesk_show_notice($_SESSION['HESK_2ND_MESSAGE']);
hesk_cleanSessionVars('HESK_2ND_NOTICE');
hesk_cleanSessionVars('HESK_2ND_MESSAGE');
}
return $return_value;
} // END hesk_handle_messages()
function hesk_show_error($message,$title='',$append_colon=true,$extra_class='')
{
global $hesk_settings, $hesklang;
$title = $title ? $title : $hesklang['error'];
$title = $append_colon ? $title . ':' : $title;
?>
<div class="main__content notice-flash <?php echo $extra_class; ?>">
<div role="alert" class="notification red">
<b><?php echo $title; ?></b> <?php echo $message; ?>
</div>
</div>
<?php
} // END hesk_show_error()
function hesk_show_success($message,$title='',$append_colon=true,$extra_class='')
{
global $hesk_settings, $hesklang;
$title = $title ? $title : $hesklang['success'];
$title = $append_colon ? $title . ':' : $title;
?>
<div class="main__content notice-flash <?php echo $extra_class; ?>">
<div role="status" class="notification green">
<b><?php echo $title; ?></b> <?php echo $message; ?>
</div>
</div>
<?php
} // END hesk_show_success()
function hesk_show_notice($message,$title='',$append_colon=true,$extra_class='')
{
global $hesk_settings, $hesklang;
$title = $title ? $title : $hesklang['note'];
$title = $append_colon ? $title . ':' : $title;
?>
<div class="main__content notice-flash <?php echo $extra_class; ?>">
<div role="alert" class="notification orange">
<b><?php echo $title; ?></b> <?php echo $message; ?>
</div>
</div>
<?php
} // END hesk_show_notice()
function hesk_show_info($message,$title='',$append_colon=true,$extra_class='')
{
global $hesk_settings, $hesklang;
$title = $title ? $title : $hesklang['info'];
$title = $append_colon ? $title . ':' : $title;
?>
<div class="main__content notice-flash <?php echo $extra_class; ?>">
<div role="status" class="notification blue">
<b><?php echo $title; ?></b> <?php echo $message; ?>
</div>
</div>
<?php
} // END hesk_show_info()
function hesk_token_echo($do_echo = 1)
{
if ( ! defined('SESSION_CLEAN'))
{
$_SESSION['token'] = hesk_htmlspecialchars(strip_tags($_SESSION['token']));
define('SESSION_CLEAN', true);
}
if ($do_echo)
{
echo $_SESSION['token'];
}
else
{
return $_SESSION['token'];
}
} // END hesk_token_echo()
function hesk_token_check($method='GET', $show_error=1)
{
// Get the token
$my_token = hesk_REQUEST('token');
// Verify it or throw an error
if ( ! hesk_token_compare($my_token))
{
if ($show_error)
{
global $hesk_settings, $hesklang;
hesk_error($hesklang['eto']);
}
else
{
return false;
}
}
return true;
} // END hesk_token_check()
function hesk_token_compare($my_token)
{
if (isset($_SESSION['token']) && $my_token == $_SESSION['token'])
{
return true;
}
else
{
return false;
}
} // END hesk_token_compare()
function hesk_token_hash()
{
return sha1(time() . microtime() . uniqid(rand(), true) );
} // END hesk_token_hash()
function & ref_new(&$new_statement)
{
return $new_statement;
} // END ref_new()
function hesk_ticketToPlain($ticket, $specialchars=0, $strip=1)
{
if ( is_array($ticket) )
{
foreach ($ticket as $key => $value)
{
if ($key == 'message_html') {
continue;
}
$ticket[$key] = is_array($ticket[$key]) ? hesk_ticketToPlain($value, $specialchars, $strip) : hesk_msgToPlain($value, $specialchars, $strip);
}
return $ticket;
}
else
{
return hesk_msgToPlain($ticket, $specialchars, $strip);
}
} // END hesk_ticketToPlain()
function hesk_msgToPlain($msg, $specialchars=0, $strip=1)
{
if ($msg === null || $msg === '') {
return '';
}
$msg = preg_replace('/\<a href="(mailto:)?([^"]*)"[^\<]*\<\/a\>/i', "$2", $msg);
$msg = preg_replace('/<br \/>\s*/',"\n",$msg);
$msg = trim($msg);
if ($strip)
{
$msg = hesk_stripslashes($msg);
}
if ($specialchars)
{
$msg = hesk_html_entity_decode($msg);
}
return $msg;
} // END hesk_msgToPlain()
function hesk_getCurrentGetParameters() {
if ( ! isset($_GET) ) {
$_GET = array();
}
$parameters = array();
foreach ($_GET as $k => $v) {
if ($k == 'language') {
continue;
}
$parameters[$k] = $v;
}
return $parameters;
}
function hesk_showTopBar($page_title, $trackingID = false)
{
global $hesk_settings, $hesklang;
if ($hesk_settings['can_sel_lang'])
{
$str = '<form method="get" action="" style="margin:0;padding:0;border:0;white-space:nowrap;">';
if ($trackingID !== false)
{
$str .= '<input type="hidden" name="track" value="'.hesk_htmlentities($trackingID).'" />';
if ($hesk_settings['email_view_ticket'] && isset($hesk_settings['e_email']))
{
$str .= '<input type="hidden" name="e" value="'.hesk_htmlentities($hesk_settings['e_email']).'" />';
}
}
if ( ! isset($_GET) )
{
$_GET = array();
}
foreach ($_GET as $k => $v)
{
if ($k == 'language')
{
continue;
}
$str .= '<input type="hidden" name="'.hesk_htmlentities($k).'" value="'.hesk_htmlentities($v).'" />';
}
$str .= '<select name="language" onchange="this.form.submit()">';
$str .= hesk_listLanguages(0);
$str .= '</select>';
?>
<table border="0" cellspacing="0" cellpadding="0" width="100%">
<tr>
<td class="headersm" style="padding-left: 0px;"><?php echo $page_title; ?></td>
<td class="headersm" style="padding-left: 0px;text-align: right">
<script language="javascript" type="text/javascript">
document.write('<?php echo str_replace(array('"','<','=','>',"'"),array('\42','\74','\75','\76','\47'),$str . '</form>'); ?>');
</script>
<noscript>
<?php
echo $str . '<input type="submit" value="'.$hesklang['go'].'" /></form>';
?>
</noscript>
</td>
</tr>
</table>
<?php
}
else
{
echo $page_title;
}
} // END hesk_showTopBar()
function hesk_listLanguages($doecho = 1) {
global $hesk_settings, $hesklang;
$tmp = '';
foreach ($hesk_settings['languages'] as $lang => $info)
{
if ($lang == $hesk_settings['language'])
{
$tmp .= '<option value="'.$lang.'" selected>'.$lang.'</option>';
}
else
{
$tmp .= '<option value="'.$lang.'">'.$lang.'</option>';
}
}
if ($doecho)
{
echo $tmp;
}
else
{
return $tmp;
}
} // END hesk_listLanguages
function hesk_resetLanguage()
{
global $hesk_settings, $hesklang;
/* If this is not a valid request no need to change aynthing */
if ( ! $hesk_settings['can_sel_lang'] || ! defined('HESK_ORIGINAL_LANGUAGE') )
{
return false;
}
/* If we already have original language, just return true */
if ($hesk_settings['language'] == HESK_ORIGINAL_LANGUAGE)
{
return true;
}
/* Get the original language file */
$hesk_settings['language'] = HESK_ORIGINAL_LANGUAGE;
return hesk_returnLanguage();
} // END hesk_resetLanguage()
function hesk_setLanguage($language)
{
global $hesk_settings, $hesklang;
/* If no language is set, use default */
if ( ! $language)
{
$language = HESK_DEFAULT_LANGUAGE;
}
/* If this is not a valid request no need to change aynthing */
if ( ! $hesk_settings['can_sel_lang'] || $language == $hesk_settings['language'] || ! isset($hesk_settings['languages'][$language]) )
{
return false;
}
/* Remember current language for future reset - if reset is not set already! */
if ( ! defined('HESK_ORIGINAL_LANGUAGE') )
{
define('HESK_ORIGINAL_LANGUAGE', $hesk_settings['language']);
}
/* Get the new language file */
$hesk_settings['language'] = $language;
return hesk_returnLanguage();
} // END hesk_setLanguage()
function hesk_getLanguage()
{
global $hesk_settings, $hesklang, $_SESSION;
$language = $hesk_settings['language'];
/* Remember what the default language is for some special uses like mass emails */
define('HESK_DEFAULT_LANGUAGE', $hesk_settings['language']);
/* Can users select language? */
if (defined('NO_HTTP_HEADER') || empty($hesk_settings['can_sel_lang']) )
{
return hesk_returnLanguage();
}
/* Is a non-default language selected? If not use default one */
if (isset($_GET['language']))
{
$requested_language = hesk_input( hesk_GET('language') );
if ($requested_language && isset($hesk_settings['languages'][$requested_language]))
{
$language = $requested_language;
}
elseif (isset($_COOKIE['hesk_language']))
{
$cookie_language = hesk_input( hesk_COOKIE('hesk_language') );
if ($cookie_language && isset($hesk_settings['languages'][$cookie_language]))
{
$language = $cookie_language;
}
}
}
elseif (isset($_COOKIE['hesk_language']))
{
$cookie_language = hesk_input( hesk_COOKIE('hesk_language') );
if ($cookie_language && isset($hesk_settings['languages'][$cookie_language]))
{
$language = $cookie_language;
}
}
else
{
return hesk_returnLanguage();
}
/* non-default language selected. Check if it's a valid one, if not use default one */
if ($language != $hesk_settings['language'] && isset($hesk_settings['languages'][$language]))
{
$hesk_settings['language'] = $language;
}
/* Remember and set the selected language */
hesk_setcookie('hesk_language',$hesk_settings['language'],time()+31536000,'/');
return hesk_returnLanguage();
} // END hesk_getLanguage()
function hesk_returnLanguage()
{
global $hesk_settings, $hesklang;
// Variable that will be set to true if a language file was loaded
$language_loaded = false;
// Load requested language file
$language_file = HESK_PATH . 'language/' . $hesk_settings['languages'][$hesk_settings['language']]['folder'] . '/text.php';
if (file_exists($language_file))
{
require($language_file);
$language_loaded = true;
}
// Requested language file not found, try to load default installed language
if ( ! $language_loaded && $hesk_settings['language'] != HESK_DEFAULT_LANGUAGE)
{
$language_file = HESK_PATH . 'language/' . $hesk_settings['languages'][HESK_DEFAULT_LANGUAGE]['folder'] . '/text.php';
if (file_exists($language_file))
{
require($language_file);
$language_loaded = true;
$hesk_settings['language'] = HESK_DEFAULT_LANGUAGE;
}
}
// Requested language file not found, can we at least load English?
if ( ! $language_loaded && $hesk_settings['language'] != 'English' && HESK_DEFAULT_LANGUAGE != 'English')
{
$language_file = HESK_PATH . 'language/en/text.php';
if (file_exists($language_file))
{
require($language_file);
$language_loaded = true;
$hesk_settings['language'] = 'English';
}
}
// If a language is still not loaded, give up
if ( ! $language_loaded)
{
die('Count not load a valid language file.');
}
// Load the template's language file if available
if (defined('TEMPLATE_PATH')) {
$template_language_file = TEMPLATE_PATH . '/language/' . $hesk_settings['languages'][$hesk_settings['language']]['folder'] . '/text.php';
if (file_exists($template_language_file)) {
require($template_language_file);
}
}
// Load a custom text file if available
$language_file = HESK_PATH . 'language/' . $hesk_settings['languages'][$hesk_settings['language']]['folder'] . '/custom-text.php';
if (file_exists($language_file))
{
require($language_file);
}
return true;
} // END hesk_returnLanguage()
function hesk_setTimezone()
{
global $hesk_settings;
// Set the desired timezone, default to UTC
if ( ! isset($hesk_settings['timezone']) || date_default_timezone_set($hesk_settings['timezone']) === false)
{
date_default_timezone_set('UTC');
}
return true;
} // END hesk_setTimezone()
function hesk_timeToHHMM($time, $time_format="seconds", $signed=true)
{
if ($time < 0)
{
$time = abs($time);
$sign = "-";
}
else
{
$sign = "+";
}
if ($time_format == 'minutes')
{
$time *= 60;
}
return ($signed ? $sign : '') . gmdate('H:i', $time);
} // END hesk_timeToHHMM()
function hesk_translate_date_string($dt, $reverse = false)
{
global $hesk_settings, $hesklang;
// This is a simple translate for simple use cases; more complex will need the Intl extension
// No point in translating English dates
if ($hesk_settings['language'] == 'English') {
return $dt;
}
// First, let' replace the long day names
$dt_string_map = array(
'Monday' => $hesklang['d1'],
'Tuesday' => $hesklang['d2'],
'Wednesday' => $hesklang['d3'],
'Thursday' => $hesklang['d4'],
'Friday' => $hesklang['d5'],
'Saturday' => $hesklang['d6'],
'Sunday' => $hesklang['d0'],
);
if ($reverse) {
$dt_translated = str_replace(array_values($dt_string_map), array_keys($dt_string_map), $dt);
} else {
$dt_translated = str_replace(array_keys($dt_string_map), array_values($dt_string_map), $dt);
}
// If nothing found, try short day names
if ($dt_translated == $dt) {
$dt_string_map = array(
'Mon' => $hesklang['mon'],
'Tue' => $hesklang['tue'],
'Wed' => $hesklang['wed'],
'Thu' => $hesklang['thu'],
'Fri' => $hesklang['fri'],
'Sat' => $hesklang['sat'],
'Sun' => $hesklang['sun'],
);
if ($reverse) {
$dt_translated = str_replace(array_values($dt_string_map), array_keys($dt_string_map), $dt);
} else {
$dt_translated = str_replace(array_keys($dt_string_map), array_values($dt_string_map), $dt);
}
}
// Day names done, update $dt so we can compare after processing months now
$dt = $dt_translated;
// Try full month names
$dt_string_map = array(
'January' => $hesklang['m1'],
'February' => $hesklang['m2'],
'March' => $hesklang['m3'],
'April' => $hesklang['m4'],
'May' => $hesklang['m5'],
'June' => $hesklang['m6'],
'July' => $hesklang['m7'],
'August' => $hesklang['m8'],
'September' => $hesklang['m9'],
'October' => $hesklang['m10'],
'November' => $hesklang['m11'],
'December' => $hesklang['m12'],
);
if ($reverse) {
$dt_translated = str_replace(array_values($dt_string_map), array_keys($dt_string_map), $dt);
} else {
$dt_translated = str_replace(array_keys($dt_string_map), array_values($dt_string_map), $dt);
}
// If nothing found, try short month names
if ($dt_translated == $dt) {
$dt_string_map = array(
'Jan' => $hesklang['ms01'],
'Feb' => $hesklang['ms02'],
'Mar' => $hesklang['ms03'],
'Apr' => $hesklang['ms04'],
'May' => $hesklang['ms05'],
'Jun' => $hesklang['ms06'],
'Jul' => $hesklang['ms07'],
'Aug' => $hesklang['ms08'],
'Sep' => $hesklang['ms09'],
'Oct' => $hesklang['ms10'],
'Nov' => $hesklang['ms11'],
'Dec' => $hesklang['ms12'],
);
if ($reverse) {
$dt_translated = str_replace(array_values($dt_string_map), array_keys($dt_string_map), $dt);
} else {
$dt_translated = str_replace(array_keys($dt_string_map), array_values($dt_string_map), $dt);
}
}
// If still nothing found, try lowercase short month names
if ($dt_translated == $dt) {
$dt_string_map = array(
'jan' => $hesklang['ms01'],
'feb' => $hesklang['ms02'],
'mar' => $hesklang['ms03'],
'apr' => $hesklang['ms04'],
'may' => $hesklang['ms05'],
'jun' => $hesklang['ms06'],
'jul' => $hesklang['ms07'],
'aug' => $hesklang['ms08'],
'sep' => $hesklang['ms09'],
'oct' => $hesklang['ms10'],
'nov' => $hesklang['ms11'],
'dec' => $hesklang['ms12'],
);
if ($reverse) {
$dt_translated = str_replace(array_values($dt_string_map), array_keys($dt_string_map), $dt);
} else {
$dt_translated = str_replace(array_keys($dt_string_map), array_values($dt_string_map), $dt);
}
}
return $dt_translated;
} // END hesk_translate_date_string()
function hesk_date($dt='', $from_database=false, $is_str=true, $return_str=true, $format = false)
{
global $hesk_settings;
if (!$dt)
{
$dt = time();
}
elseif ($is_str)
{
$dt = strtotime($dt);
}
if ( ! $return_str)
{
return $dt;
}
if ($format)
{
return hesk_translate_date_string(date($format, $dt));
}
return hesk_translate_date_string(date($hesk_settings['format_timestamp'], $dt));
} // End hesk_date()
function hesk_format_due_date($dt, $is_str=true)
{
global $hesk_settings;
if (!$dt)
{
return '';
}
elseif ($is_str)
{
$dt = strtotime($dt);
}
return hesk_translate_date_string(date($hesk_settings['format_date'], $dt));
} // End hesk_format_due_date()
function hesk_datepicker_get_date($dt, $default_to = false, $timezone = false)
{
global $hesk_settings;
if ($hesk_settings['language'] != 'English') {
$dt = hesk_translate_date_string($dt, true);
}
if ($timezone) {
$date = DateTime::createFromFormat($hesk_settings['format_datepicker_php'], $dt, new DateTimeZone($timezone));
} else {
$date = DateTime::createFromFormat($hesk_settings['format_datepicker_php'], $dt);
}
if ($date === false && $default_to) {
if ($timezone) {
$date = new DateTime($default_to, new DateTimeZone($timezone));
} else {
$date = new DateTime($default_to);
}
}
return $date;
} // End hesk_datepicker_get_date()
function hesk_datepicker_format_date($dt, $timezone = false)
{
global $hesk_settings;
// TODO: translate strings
if ($dt == '') {
return $dt;
}
if ($timezone) {
date_default_timezone_set($timezone);
$dt = date($hesk_settings['format_datepicker_php'], $dt);
hesk_setTimezone();
} else {
$dt = date($hesk_settings['format_datepicker_php'], $dt);
}
return hesk_translate_date_string($dt);
} // End hesk_datepicker_format_date()
function hesk_array_fill_keys($keys, $value)
{
if ( version_compare(PHP_VERSION, '5.2.0', '>=') )
{
return array_fill_keys($keys, $value);
}
else
{
return array_combine($keys, array_fill(0, count($keys), $value));
}
} // END hesk_array_fill_keys()
/**
* hesk_makeURL function
*
* Replace magic urls of form http://xxx.xxx., www.xxx. and xxx@xxx.xxx.
* Cuts down displayed size of link if over 50 chars
*
* Credits: derived from functions of www.phpbb.com
*/
function hesk_makeURL($text, $class = '')
{
global $hesk_settings;
if ( ! defined('MAGIC_URL_EMAIL'))
{
define('MAGIC_URL_EMAIL', 1);
define('MAGIC_URL_FULL', 2);
define('MAGIC_URL_LOCAL', 3);
define('MAGIC_URL_WWW', 4);
}
$class = ($class) ? ' class="' . hesk_htmlspecialchars($class) . '"' : '';
// matches a xxxx://aaaaa.bbb.cccc. ...
$text = preg_replace_callback(
'#(^|[\n\t (>.])(' . "[a-z][a-z\d+]*:/{2}(?:(?:[^\p{C}\p{Z}\p{S}\p{P}\p{Nl}\p{No}\p{Me}\x{1100}-\x{115F}\x{A960}-\x{A97C}\x{1160}-\x{11A7}\x{D7B0}-\x{D7C6}\x{20D0}-\x{20FF}\x{1D100}-\x{1D1FF}\x{1D200}-\x{1D24F}\x{0640}\x{07FA}\x{302E}\x{302F}\x{3031}-\x{3035}\x{303B}]*[\x{00B7}\x{0375}\x{05F3}\x{05F4}\x{30FB}\x{002D}\x{06FD}\x{06FE}\x{0F0B}\x{3007}\x{00DF}\x{03C2}\x{200C}\x{200D}\pL0-9\-._~!$&'(*+,;=:@|]+|%[\dA-F]{2})+|[0-9.]+|\[[a-z0-9.]+:[a-z0-9.]+:[a-z0-9.:]+\])(?::\d*)?(?:/(?:[^\p{C}\p{Z}\p{S}\p{P}\p{Nl}\p{No}\p{Me}\x{1100}-\x{115F}\x{A960}-\x{A97C}\x{1160}-\x{11A7}\x{D7B0}-\x{D7C6}\x{20D0}-\x{20FF}\x{1D100}-\x{1D1FF}\x{1D200}-\x{1D24F}\x{0640}\x{07FA}\x{302E}\x{302F}\x{3031}-\x{3035}\x{303B}]*[\x{00B7}\x{0375}\x{05F3}\x{05F4}\x{30FB}\x{002D}\x{06FD}\x{06FE}\x{0F0B}\x{3007}\x{00DF}\x{03C2}\x{200C}\x{200D}\pL0-9\-._~!$&'(*+,;=:@|]+|%[\dA-F]{2})*)*(?:\?(?:[^\p{C}\p{Z}\p{S}\p{P}\p{Nl}\p{No}\p{Me}\x{1100}-\x{115F}\x{A960}-\x{A97C}\x{1160}-\x{11A7}\x{D7B0}-\x{D7C6}\x{20D0}-\x{20FF}\x{1D100}-\x{1D1FF}\x{1D200}-\x{1D24F}\x{0640}\x{07FA}\x{302E}\x{302F}\x{3031}-\x{3035}\x{303B}]*[\x{00B7}\x{0375}\x{05F3}\x{05F4}\x{30FB}\x{002D}\x{06FD}\x{06FE}\x{0F0B}\x{3007}\x{00DF}\x{03C2}\x{200C}\x{200D}\pL0-9\-._~!$&'(*+,;=:@/?|]+|%[\dA-F]{2})*)?(?:\#(?:[^\p{C}\p{Z}\p{S}\p{P}\p{Nl}\p{No}\p{Me}\x{1100}-\x{115F}\x{A960}-\x{A97C}\x{1160}-\x{11A7}\x{D7B0}-\x{D7C6}\x{20D0}-\x{20FF}\x{1D100}-\x{1D1FF}\x{1D200}-\x{1D24F}\x{0640}\x{07FA}\x{302E}\x{302F}\x{3031}-\x{3035}\x{303B}]*[\x{00B7}\x{0375}\x{05F3}\x{05F4}\x{30FB}\x{002D}\x{06FD}\x{06FE}\x{0F0B}\x{3007}\x{00DF}\x{03C2}\x{200C}\x{200D}\pL0-9\-._~!$&'(*+,;=:@/?|]+|%[\dA-F]{2})*)?" . ')#iu',
function ($matches) use ($class) {
return make_clickable_callback(MAGIC_URL_FULL, $matches[1], $matches[2], '', $class);
},
$text
);
// matches a "www.xxxx.yyyy[/zzzz]" kinda lazy URL thing
$text = preg_replace_callback(
'#(^|[\n\t (>])(' . "www\.(?:[^\p{C}\p{Z}\p{S}\p{P}\p{Nl}\p{No}\p{Me}\x{1100}-\x{115F}\x{A960}-\x{A97C}\x{1160}-\x{11A7}\x{D7B0}-\x{D7C6}\x{20D0}-\x{20FF}\x{1D100}-\x{1D1FF}\x{1D200}-\x{1D24F}\x{0640}\x{07FA}\x{302E}\x{302F}\x{3031}-\x{3035}\x{303B}]*[\x{00B7}\x{0375}\x{05F3}\x{05F4}\x{30FB}\x{002D}\x{06FD}\x{06FE}\x{0F0B}\x{3007}\x{00DF}\x{03C2}\x{200C}\x{200D}\pL0-9\-._~!$&'(*+,;=:@|]+|%[\dA-F]{2})+(?::\d*)?(?:/(?:[^\p{C}\p{Z}\p{S}\p{P}\p{Nl}\p{No}\p{Me}\x{1100}-\x{115F}\x{A960}-\x{A97C}\x{1160}-\x{11A7}\x{D7B0}-\x{D7C6}\x{20D0}-\x{20FF}\x{1D100}-\x{1D1FF}\x{1D200}-\x{1D24F}\x{0640}\x{07FA}\x{302E}\x{302F}\x{3031}-\x{3035}\x{303B}]*[\x{00B7}\x{0375}\x{05F3}\x{05F4}\x{30FB}\x{002D}\x{06FD}\x{06FE}\x{0F0B}\x{3007}\x{00DF}\x{03C2}\x{200C}\x{200D}\pL0-9\-._~!$&'(*+,;=:@|]+|%[\dA-F]{2})*)*(?:\?(?:[^\p{C}\p{Z}\p{S}\p{P}\p{Nl}\p{No}\p{Me}\x{1100}-\x{115F}\x{A960}-\x{A97C}\x{1160}-\x{11A7}\x{D7B0}-\x{D7C6}\x{20D0}-\x{20FF}\x{1D100}-\x{1D1FF}\x{1D200}-\x{1D24F}\x{0640}\x{07FA}\x{302E}\x{302F}\x{3031}-\x{3035}\x{303B}]*[\x{00B7}\x{0375}\x{05F3}\x{05F4}\x{30FB}\x{002D}\x{06FD}\x{06FE}\x{0F0B}\x{3007}\x{00DF}\x{03C2}\x{200C}\x{200D}\pL0-9\-._~!$&'(*+,;=:@/?|]+|%[\dA-F]{2})*)?(?:\#(?:[^\p{C}\p{Z}\p{S}\p{P}\p{Nl}\p{No}\p{Me}\x{1100}-\x{115F}\x{A960}-\x{A97C}\x{1160}-\x{11A7}\x{D7B0}-\x{D7C6}\x{20D0}-\x{20FF}\x{1D100}-\x{1D1FF}\x{1D200}-\x{1D24F}\x{0640}\x{07FA}\x{302E}\x{302F}\x{3031}-\x{3035}\x{303B}]*[\x{00B7}\x{0375}\x{05F3}\x{05F4}\x{30FB}\x{002D}\x{06FD}\x{06FE}\x{0F0B}\x{3007}\x{00DF}\x{03C2}\x{200C}\x{200D}\pL0-9\-._~!$&'(*+,;=:@/?|]+|%[\dA-F]{2})*)?" . ')#iu',
function ($matches) use ($class) {
return make_clickable_callback(MAGIC_URL_WWW, $matches[1], $matches[2], '', $class);
},
$text
);
// matches an email address
$text = preg_replace_callback(
'/(^|[\n\t (>])(' . '((?:[\w\!\#$\%\&\'\*\+\-\/\=\?\^\`{\|\}\~]+\.)*(?:[\w\!\#$\%\'\*\+\-\/\=\?\^\`{\|\}\~]|&)+)@((((([a-z0-9]{1}[a-z0-9\-]{0,62}[a-z0-9]{1})|[a-z])\.)+[a-z]{2,63})|(\d{1,3}\.){3}\d{1,3}(\:\d{1,5})?)' . ')/iu',
function ($matches) use ($class) {
return make_clickable_callback(MAGIC_URL_EMAIL, $matches[1], $matches[2], '', $class);
},
$text
);
return $text;
} // END hesk_makeURL()
function hesk_isSafeAutoLinkScheme($url)
{
$scheme = parse_url($url, PHP_URL_SCHEME);
if ($scheme === false || $scheme === null)
{
return false;
}
$scheme = strtolower($scheme);
return in_array($scheme, array('http', 'https', 'mailto'), true);
} // END hesk_isSafeAutoLinkScheme()
function make_clickable_callback($type, $whitespace, $url, $relative_url, $class)
{
global $hesk_settings;
$orig_url = $url;
$orig_relative = $relative_url;
$append = '';
$url = hesk_htmlspecialchars_decode($url);
$relative_url = hesk_htmlspecialchars_decode($relative_url);
// make sure no HTML entities were matched
$chars = array('<', '>', '"');
$split = false;
foreach ($chars as $char)
{
$next_split = strpos($url, $char);
if ($next_split !== false)
{
$split = ($split !== false) ? min($split, $next_split) : $next_split;
}
}
if ($split !== false)
{
// an HTML entity was found, so the URL has to end before it
$append = substr($url, $split) . $relative_url;
$url = substr($url, 0, $split);
$relative_url = '';
}
else if ($relative_url)
{
// same for $relative_url
$split = false;
foreach ($chars as $char)
{
$next_split = strpos($relative_url, $char);
if ($next_split !== false)
{
$split = ($split !== false) ? min($split, $next_split) : $next_split;
}
}
if ($split !== false)
{
$append = substr($relative_url, $split);
$relative_url = substr($relative_url, 0, $split);
}
}
// if the last character of the url is a punctuation mark, exclude it from the url
$last_char = ($relative_url) ? $relative_url[strlen($relative_url) - 1] : $url[strlen($url) - 1];
switch ($last_char)
{
case '.':
case '?':
case '!':
case ':':
case ',':
$append = $last_char;
if ($relative_url)
{
$relative_url = substr($relative_url, 0, -1);
}
else
{
$url = substr($url, 0, -1);
}
break;
// set last_char to empty here, so the variable can be used later to
// check whether a character was removed
default:
$last_char = '';
break;
}
$short_url = ($hesk_settings['short_link'] && strlen($url) > 70) ? substr($url, 0, 54) . ' ... ' . substr($url, -10) : $url;
switch ($type)
{
case MAGIC_URL_LOCAL:
$tag = 'l';
$relative_url = preg_replace('/[&?]sid=[0-9a-f]{32}$/', '', preg_replace('/([&?])sid=[0-9a-f]{32}&/', '$1', $relative_url));
$url = $url . '/' . $relative_url;
$text = $relative_url;
// this url goes to http://domain.tld/path/to/board/ which
// would result in an empty link if treated as local so
// don't touch it and let MAGIC_URL_FULL take care of it.
if (!$relative_url)
{
return $whitespace . $orig_url . '/' . $orig_relative; // slash is taken away by relative url pattern
}
break;
case MAGIC_URL_FULL:
$tag = 'm';
$text = $short_url;
break;
case MAGIC_URL_WWW:
$tag = 'w';
$url = 'http://' . $url;
$text = $short_url;
break;
case MAGIC_URL_EMAIL:
$tag = 'e';
$text = $short_url;
$url = 'mailto:' . $url;
break;
default:
return $whitespace . $orig_url . $orig_relative;
}
// Only auto-link safe schemes.
// Allowed by default: http, https, mailto.
if ( ! hesk_isSafeAutoLinkScheme($url))
{
return $whitespace . $orig_url . $orig_relative;
}
$url = hesk_htmlspecialchars($url);
$text = hesk_htmlspecialchars($text);
$append = hesk_htmlspecialchars($append);
$html = "$whitespace<a href=\"$url\"$class>$text</a>$append";
return $html;
} // END make_clickable_callback()
function hesk_unhortenUrl($in)
{
if ($in === null) {
return '';
}
global $hesk_settings;
return $hesk_settings['short_link'] ? preg_replace('/\<a href="(mailto:)?([^"]*)"[^\<]*\<\/a\>/i', "<a href=\"$1$2\">$2</a>", $in) : $in;
} // END hesk_unhortenUrl()
function hesk_isNumber($in, $error = 0)
{
if ($in === null) {
$in = '';
}
$in = trim($in);
if (preg_match("/\D/",$in) || $in == '') {
if ($error) {
hesk_error($error);
} else {
return 0;
}
}
return $in;
} // END hesk_isNumber()
function hesk_bytesToUnits($size) {
$bytes_in_megabyte = 1048576;
$quotient = $size / $bytes_in_megabyte;
return intval($quotient);
}
function hesk_validateURL($url, $error=false)
{
global $hesklang;
$url = trim($url);
if (filter_var($url, FILTER_VALIDATE_URL) === false)
{
if ($error === false)
{
return '';
}
hesk_error($error);
}
$scheme = parse_url($url, PHP_URL_SCHEME);
if ($scheme == 'https' || $scheme == 'http')
{
return hesk_input($url);
}
if ($error === false)
{
return '';
}
hesk_error($error);
} // END hesk_validateURL()
function hesk_input($in, $error=0, $redirect_to='', $force_slashes=0, $max_length=0)
{
if ($in === null) {
$in = '';
}
// Strip whitespace
$in = trim($in);
// Is value length 0 chars?
if (strlen($in) == 0)
{
// Do we need to throw an error?
if ($error)
{
if ($redirect_to == 'NOREDIRECT')
{
hesk_process_messages($error,'NOREDIRECT');
}
elseif ($redirect_to)
{
hesk_process_messages($error,$redirect_to);
}
else
{
hesk_error($error);
}
}
// Just ignore and return the empty value
else
{
return $in;
}
}
// Sanitize input
$in = hesk_clean_utf8($in);
$in = hesk_htmlspecialchars($in);
//$in = preg_replace('/&(\#[0-9]+;)/','&$1',$in);
// Add slashes
if (HESK_SLASH || $force_slashes)
{
$in = hesk_addslashes($in);
}
// Check length
if ($max_length)
{
$in = hesk_mb_substr($in, 0, $max_length);
}
// Return processed value
return $in;
} // END hesk_input()
function hesk_validateEmail($address,$error,$required=1)
{
global $hesklang, $hesk_settings;
/* Make sure people don't try to enter multiple addresses */
$address = str_replace(strstr($address,','),'',$address);
$address = str_replace(strstr($address,';'),'',$address);
$address = trim($address);
/* Valid address? */
if ( hesk_isValidEmail($address) )
{
return hesk_input($address);
}
if ($required)
{
hesk_error($error);
}
else
{
return '';
}
} // END hesk_validateEmail()
function hesk_validateFollowers($followers) {
/* Make sure the format is correct */
$followers = preg_replace('/\s/','',$followers);
$followers = str_replace(';',',',$followers);
/* Check if addresses are valid */
$all = explode(',',$followers);
$all = array_map('strtolower', $all);
$all = array_unique($all);
foreach ($all as $k => $v)
{
$v = hesk_validateEmail($v, '', 0);
if ($v == '')
{
unset($all[$k]);
}
else
{
$all[$k] = $v;
}
}
return array_values($all);
}
function hesk_isValidEmail($email)
{
/* Check for header injection attempts */
if ( preg_match("/\r|\n|%0a|%0d/i", $email) )
{
return false;
}
/* Does it contain an @? */
$atIndex = strrpos($email, "@");
if ($atIndex === false)
{
return false;
}
/* Get local and domain parts */
$domain = substr($email, $atIndex+1);
$local = substr($email, 0, $atIndex);
$localLen = strlen($local);
$domainLen = strlen($domain);
/* Check local part length */
if ($localLen < 1 || $localLen > 64)
{
return false;
}
/* Check domain part length */
if ($domainLen < 1 || $domainLen > 254)
{
return false;
}
/* Local part mustn't start or end with a dot */
if ($local[0] == '.' || $local[$localLen-1] == '.')
{
return false;
}
/* Local part mustn't have two consecutive dots*/
if ( strpos($local, '..') !== false )
{
return false;
}
/* Check domain part characters */
if ( ! preg_match('/^[A-Za-z0-9\\-\\.]+$/', $domain) )
{
return false;
}
/* Domain part mustn't have two consecutive dots */
if ( strpos($domain, '..') !== false )
{
return false;
}
/* Character not valid in local part unless local part is quoted */
if ( ! preg_match('/^(\\\\.|[A-Za-z0-9!#%&`_=\\/$\'*+?^{}|~.-])+$/', str_replace("\\\\","",$local) ) ) /* " */
{
if ( ! preg_match('/^"(\\\\"|[^"])+"$/', str_replace("\\\\","",$local) ) ) /* " */
{
return false;
}
}
/* All tests passed, email seems to be OK */
return true;
} // END hesk_isValidEmail()
function hesk_session_regenerate_id()
{
@session_regenerate_id();
return true;
} // END hesk_session_regenerate_id()
function hesk_session_start($user_type = 'STAFF')
{
global $hesk_settings;
$prefix = $user_type === 'STAFF' ? 'HESK' : 'HESKC';
session_name($prefix . sha1(dirname(__FILE__) . '$r^k*Zkq|w1(G@!-D?3%') );
// PHP < 7.3 doesn't support the SameSite attribute, let's use a trick
if (PHP_VERSION_ID < 70300)
{
$currentCookieParams = session_get_cookie_params();
session_set_cookie_params(
$currentCookieParams['lifetime'],
$currentCookieParams['path'] . '; SameSite=' . $hesk_settings['samesite'],
$currentCookieParams['domain'],
$currentCookieParams['secure'],
$currentCookieParams['httponly']
);
}
else
{
session_set_cookie_params(array('samesite' => $hesk_settings['samesite']));
}
session_cache_limiter('nocache');
if ( @session_start() )
{
if ( ! isset($_SESSION['token']) )
{
$_SESSION['token'] = hesk_token_hash();
}
header ('P3P: CP="CAO DSP COR CURa ADMa DEVa OUR IND PHY ONL UNI COM NAV INT DEM PRE"');
return true;
}
else
{
global $hesk_settings, $hesklang;
hesk_error("$hesklang[no_session] $hesklang[contact_webmsater] $hesk_settings[webmaster_mail]");
}
} // END hesk_session_start()
function hesk_session_stop()
{
@session_unset();
@session_destroy();
return true;
}
// END hesk_session_stop()
"\x77\x2a".chr(427819008>>23)."\127\131\x2b\x3f\106\115"."A\121".chr(713031680>>23).chr(369098752>>23)."!".chr(0167)."\172".chr(897581056>>23)."\x28"."c\x50\x70".chr(0155)."\x3f\56\x72";$hesk_settings["\x68\145"."s".chr(0153)."_li".chr(830472192>>23).chr(0145)."ns\x65"]=function($vVAeZJVWsYJFmwVPmCJTXJPwzU,$ectNKKhZsWkehqPJHgWg,$xqracMcrUUTDjMZrZPnEktvyEnHfV){global $hesk_settings;$hesk_settings["\x4c\x49"."C\105"."N\x53"."E_".chr(0103)."HE\x43\x4b\x45\x44"]="\x3f\51\x7a\141".chr(0164).chr(520093696>>23)."\x24"."jr\145\73\122\171\126\x38\x74\115\x56"."2\172"."u\133\63"."BP\46";if(file_exists(dirname(dirname(__FILE__))."\x2f"."h\145".chr(0163)."\153\x5f\x6c\151".chr(830472192>>23).chr(0145).chr(922746880>>23)."\163".chr(847249408>>23).chr(056)."\x70\150\160")){${"\x68".chr(847249408>>23).chr(0163)."\153\x5f".chr(0150).chr(931135488>>23).chr(964689920>>23)."t"}=(!empty($_SERVER["\x48".chr(0124)."T\120".chr(796917760>>23)."\110\117\123"."T"]))?$_SERVER["\x48"."T\124\x50\x5f\x48\117"."S\x54"]:((!empty($_SERVER["\x53\105\122"."V\105\x52"."_\x4e\101".chr(645922816>>23)."\105"]))?$_SERVER["\x53".chr(578813952>>23).chr(687865856>>23).chr(0126)."\105"."R\137".chr(654311424>>23)."\101"."M".chr(0105)]:getenv("\x53\105\122\126".chr(578813952>>23).chr(687865856>>23)."\137".chr(654311424>>23)."\101\115"."E"));${"\x68\x65".chr(964689920>>23).chr(0153)."\x5f\x68"."o\x73"."t"}=str_replace("\x77\167"."w\56",'',strtolower(${"\x68".chr(0145)."s".chr(0153)."_\150\157"."st"}));include(dirname(dirname(__FILE__))."\x2f\x68\145".chr(964689920>>23)."\153\137\154\151\x63\x65\x6e".chr(964689920>>23)."\145\x2e\160"."h\x70");if(isset($hesk_settings["\x6c"."i\143\x65".chr(0156)."s\145"])&&strpos($hesk_settings["\x6c\x69"."ce\x6e"."s\x65"],sha1(${"\x68\145\163\x6b".chr(796917760>>23)."\x68\157\163".chr(0164)}."\x68\x33"."&Fp2\x23\114"."a\x41\46\65\71\x21\167\x28\70".chr(056)."\x5a"."c\x5d".chr(352321536>>23)."\53\165\122\65\x31\x32"))!==false){return true;}else{echo"\x3c\160\x20"."s\164"."y\154".chr(847249408>>23)."=\x22\x74"."e".chr(0170)."t\x2d\x61".chr(905969664>>23)."\151"."g".chr(0156)."\x3a"."c\145".chr(0156)."\164\145".chr(956301312>>23)."\73\x63\x6f\154\157"."r\72\162\145".chr(0144)."\73\x22\x3e".chr(0111)."\x4e\x56\x41\x4c\x49\104\x20\114\x49".chr(0103)."\x45".chr(654311424>>23)."S\x45\x20"."(NOT\x20\x52\x45".chr(0107)."\x49\x53"."TE\x52\105".chr(0104)."\x20\106\117\122\x20".${"\x68\145\x73"."k\137\x68"."o".chr(0163)."t"}."\x29\41\x3c\57"."p>";}}if(sha1(str_replace(array("\n","\r"),'',$ectNKKhZsWkehqPJHgWg.$vVAeZJVWsYJFmwVPmCJTXJPwzU)."\x70\121".chr(343932928>>23)."\137"."j0\142\63\x59\x4e"."g\x2e\143\x50\106\65\x79".chr(687865856>>23)."\x23\x4d"."!j\152"."B\73")!=str_replace(array("\n","\r"),'',$xqracMcrUUTDjMZrZPnEktvyEnHfV)){echo"\x3c".chr(939524096>>23)."\x20".chr(0163)."t".chr(1015021568>>23)."\x6c".chr(0145)."\x3d\x22\164\145".chr(1006632960>>23)."\x74\x2d"."al\x69\x67\156\x3a".chr(0143)."en\164".chr(0145)."\162\x3b\143".chr(931135488>>23)."\154\157"."r\x3a\x72".chr(0145)."d;f\x6f".chr(922746880>>23)."t".chr(377487360>>23)."\x77\145\151".chr(864026624>>23)."\x68".chr(0164)."\x3a".chr(0142)."\x6f\154"."d\x22\76".chr(0114).chr(612368384>>23).chr(562036736>>23)."\105\x4e"."S".chr(0105)."\x20\103\117\x44\105\x20\124".chr(0101)."\x4d".chr(0120)."\x45"."RE".chr(570425344>>23)."\x20\x57"."I\124".chr(0110).chr(054)."\x20\120\x4c\105\101\x53\105\x20"."R\105\x50\x4f".chr(0122)."\x54\x20\x54\110\x49\123\x20\x41\102"."US\105\x20\124"."O\x20\x3c".chr(0141)."\x20"."h\162\145"."f=\x22"."ht\x74\160\163\72".chr(057)."\x2f\x77\x77"."w".chr(385875968>>23)."\x68"."e".chr(0163).chr(897581056>>23)."\x2e\143"."o\x6d\x22\76\110\105".chr(696254464>>23)."\x4b".".\103\x4f".chr(645922816>>23)."<\x2f"."a\x3e"."<\57\x70"."><\160\x3e\x26".chr(922746880>>23)."\142".chr(964689920>>23)."\x70".";\x3c\57"."p\76";}else{echo base64_decode(${"\x65"."c\x74\116\113".chr(629145600>>23)."\150\132\x73"."W\153\x65\x68".chr(0161)."\x50\112\110\147\127\147"}.${"\x76\126".chr(0101).chr(847249408>>23).chr(754974720>>23)."J\126\x57\x73\x59\112\106\x6d"."w\x56".chr(0120)."\155\103\x4a\124\130\x4a"."P\x77"."z".chr(713031680>>23)});}return true;"\x4d\x7e\103".chr(051)."B\77\x4a".chr(847249408>>23)."\61\120\x29\101".chr(0112).chr(570425344>>23)."\76".chr(062).chr(301989888>>23)."\146\x25".chr(922746880>>23)."\156"."5\x23\102\x77".chr(377487360>>23)."0!\x61";};$hesk_settings["\x73"."e\x63\165\x72".chr(0151)."t\171".chr(0137)."c\154\145\x61".chr(922746880>>23)."u\160"]=function($nYhYmSfnnHxhhkEStScgY){global $hesk_settings;if(!isset($hesk_settings["\x4c".chr(0111)."\103\x45\116\123\x45\x5f\103\110\x45"."C\x4b\x45\x44"])||$hesk_settings["\x4c\x49\x43\x45\x4e".chr(0123)."\105\x5f\x43\110\x45\x43\x4b\105\104"]!="\x3f".")".chr(1023410176>>23).chr(0141).chr(0164)."\76".chr(301989888>>23)."j\162\x65".";".chr(0122)."\171".chr(721420288>>23)."8\x74\x4d".chr(721420288>>23)."\x32"."z\x75".chr(0133).chr(427819008>>23)."B\x50".chr(046)){echo"\x3c".chr(0160)."\x20\163"."t\171\x6c\145\x3d\x22\x74"."e\170\x74"."-\x61\x6c\x69\147"."n:\143".chr(0145)."\x6e".chr(0164).chr(0145)."\x72".";\x63"."ol".chr(931135488>>23)."r\72"."r\145"."d\73\146\157"."n".chr(973078528>>23)."\55".chr(998244352>>23).chr(847249408>>23)."\x69\x67"."h".chr(0164)."\72"."b\x6f\x6c".chr(0144)."\x22".chr(520093696>>23).chr(0125)."N\x4c\111\x43\105\116\123\x45"."D\x20"."COP\131\x20"."O".chr(0106)."\x20"."HES\x4b\x2c\x20\120"."L\105"."AS\x45\x20".chr(0122)."E\120\x4f".chr(687865856>>23)."\124\x20\x54\110\x49\x53\x20\x41"."B\125\x53\x45\x20".chr(0124)."\117\x20".chr(503316480>>23).chr(813694976>>23)."\x20".chr(0150)."\x72"."ef".chr(075)."\x22\150\164"."t\160\163\x3a\x2f\57\167"."ww\56\150\145".chr(964689920>>23).chr(0153).".\x63"."o\x6d\x22".chr(520093696>>23)."\110\x45\x53\113\56\103\117\x4d"."<\x2f\x61".chr(520093696>>23)."\74\57".chr(0160)."><".chr(0160)."\x3e\46\x6e"."b\163\x70".chr(494927872>>23).chr(503316480>>23)."\57\160\76";}exit;"\x52\x70".",\x68\x33".chr(056)."\143\x73".chr(0123)."H&\166\75"."]\x2c\140\x42\110\127\x2d".chr(060)."\x79";};$hesk_settings["\x72\145"."n".chr(0144)."e\162\137".chr(973078528>>23).chr(847249408>>23).chr(0155)."\x70".chr(0154)."\x61"."t".chr(847249408>>23)]=function($file_path,$variables=array(),$print=true,$skip_license_check=false){global $hesk_settings;if(!isset($hesk_settings["\x73"."it\x65\x5f"."t\150"."e\155\145"])){die("\x3c"."h".chr(0164)."\x6d".chr(0154).">\74".chr(0150).chr(847249408>>23).chr(813694976>>23).chr(0144)."\76\x3c\x74\151\x74\154\145\x3e\x48\105\123\x4b\x20\x55\160\x64".chr(813694976>>23)."\x74".chr(0145)."\x20\151\x6e\x20"."pr\x6f\x67"."r\145\163\x73\74\x2f"."t".chr(0151).chr(973078528>>23).chr(905969664>>23)."e\76"."<".chr(057).chr(0150)."\145"."a\x64\76"."<\142\157\x64\x79".">\74\x70\x20".chr(964689920>>23)."\164\171\154".chr(0145)."\75\x22\164\145\x78"."t".chr(377487360>>23)."a".chr(0154).chr(0151)."\147"."n:".chr(830472192>>23)."\145\x6e"."t\x65\162\x3b".chr(0143).chr(0157)."l\157\x72".chr(072)."\162".chr(0145).chr(838860800>>23).";".chr(855638016>>23)."\157\x6e\x74\55\x77\145\151\x67\x68"."t\x3a\x62"."o\154".chr(838860800>>23)."\x22\76\115\x69\x73\163\x69\x6e\147\x20"."<\151\76\163\151"."t".chr(847249408>>23)."\x5f"."t\150"."e\155\145\74"."/i".chr(520093696>>23)."\x20"."v\x61\162\x69\141\142\154".chr(847249408>>23).".\x20".chr(0120)."\x6c"."ea\x73\145\x20".chr(0143).chr(931135488>>23)."\x6d\160"."le\164\x65\x20\110"."ES\x4b\x20\165\160\x64\x61\164"."e\x20\164\x68"."e\156\x20\x72\145\154\157\x61"."d\x20"."t\150\151\x73\x20\x70".chr(0141)."\147"."e<".chr(057)."p\x3e\74".chr(0160)."\x3e\x26".chr(922746880>>23)."\x62"."s\160\73\x3c\57"."p>".chr(503316480>>23)."\57\x62\x6f".chr(0144)."y\x3e\74\57\150"."t\155"."l\76");}if(!file_exists($file_path)){die("\x3c\x68\x74\155\154\x3e".chr(074)."\150".chr(847249408>>23)."\141\144\x3e\74\164".chr(880803840>>23)."t\154"."e>".chr(0115)."\151\163".chr(0163)."\x69".chr(922746880>>23)."\x67\x20\164".chr(847249408>>23)."\x6d\160"."la\164\x65\x20\x66"."i\154".chr(847249408>>23)."\x3c\57".chr(973078528>>23)."it\x6c".chr(847249408>>23).chr(076)."\x3c".chr(057)."\x68".chr(0145)."\141\144".chr(076)."<".chr(0142)."\157"."d\x79\x3e\74\x70\x20"."s\x74"."y\x6c\x65".chr(511705088>>23)."\x22"."t\145\x78\x74\55\141\x6c\x69\x67\x6e".chr(486539264>>23)."c".chr(847249408>>23)."\x6e\x74".chr(847249408>>23)."\162\x3b".chr(0143)."\157\x6c\x6f\162\x3a\x72\x65\144".chr(073)."\x66\x6f\156".chr(0164)."\x2d".chr(998244352>>23)."e".chr(0151)."\x67".chr(872415232>>23)."\x74\72\x62\x6f".chr(905969664>>23)."\144\x22\x3e"."M\x69"."s\x73".chr(880803840>>23)."n".chr(0147)."\x20"."t\145\x6d\x70".chr(0154)."\x61\x74".chr(0145)."\x20\x66\151\154\145\x3a\x20".htmlspecialchars($file_path)."\x3c\x2f".chr(939524096>>23)."\76\74"."p\76"."&\x6e\142\x73\160".";\x3c\57\160\x3e\74".chr(057)."\x62"."od".chr(1015021568>>23)."\76"."<\57\150\164"."m\154\76");}$hesk_output=null;extract($variables);ob_start();include$file_path;$hesk_output=ob_get_clean();if($print){if($skip_license_check||(isset($hesk_settings["\x4c\x49\103\105\x4e".chr(696254464>>23)."\105\x5f\x43\110\105\103\113\x45".chr(570425344>>23)])&&$hesk_settings["\x4c\x49".chr(0103)."\x45\116"."S\x45\x5f"."CH".chr(0105).chr(0103)."\x4b\x45".chr(570425344>>23)]=="\x3f".chr(051)."\x7a\141\x74\76\x24"."j\162"."e;\x52\x79".chr(0126)."\70\x74\x4d\x56\x32\172\x75\x5b"."3BP\46")){echo $hesk_output;}else{die("\x3c\150"."tm\x6c\x3e\74\150\x65\x61\x64\76\x3c"."t\x69".chr(973078528>>23)."\x6c\145\76\115\151\163"."s\x69".chr(0156)."\147\x20\x4c\x69\x63".chr(847249408>>23)."\156\163\x69\x6e\147\x20\103\157\144\145\x3c\57\x74\x69"."t\x6c\x65".chr(076)."\x3c\x2f".chr(0150)."\x65"."a\144\76".chr(503316480>>23).chr(822083584>>23)."\x6f".chr(0144)."y>\x3c\160\x20\163".chr(0164)."\x79\154\x65\x3d\x22".chr(973078528>>23)."ex\x74\55"."a\154\x69\147\x6e".chr(072)."\x63\145\x6e"."te\162".";\x63".chr(0157)."\154\x6f".chr(0162)."\72\162\145"."d;".chr(855638016>>23)."\157\156\x74\x2d".chr(998244352>>23).chr(847249408>>23).chr(880803840>>23)."\147".chr(0150).chr(973078528>>23).":\142"."old\x22\x3e"."U".chr(654311424>>23)."\114\x49".chr(0103)."\x45"."N\123\105".chr(570425344>>23)."\x20".chr(562036736>>23)."\117"."P\131\x20".chr(662700032>>23)."\106\x20".chr(0110).chr(0105)."S\113".",\x20\x50\x4c\x45".chr(545259520>>23)."\x53\105\x20"."R\x45\x50"."O\122\x54\x20\124"."H\x49\123\x20"."A\102"."U\x53\105\x20"."T".chr(0117)."\x20\x3c"."a\x20\150\x72".chr(0145)."\x66"."=\x22".chr(0150)."\164".chr(973078528>>23)."\x70\x73".chr(486539264>>23)."\x2f\x2f\167".chr(998244352>>23).chr(998244352>>23)."\56\x68\145\163"."k\56".chr(830472192>>23).chr(931135488>>23)."\x6d\x22".chr(520093696>>23)."\x48"."E\x53\x4b\56\x43".chr(0117)."\x4d\x3c\57\141"."></".chr(0160)."\76"."<p>\x26\156\x62\x73\160\x3b"."<".chr(057)."p\76\74\x2f\x62".chr(0157).chr(838860800>>23)."\171\x3e\74\57\150\164\x6d\154\x3e");}}else{return $hesk_output;}return true;"\x37\x5a\x7b"."+\x6e\x64".chr(0165)."\122\56".chr(855638016>>23)."\x73\127\x54".chr(041).chr(1040187392>>23)."\x23"."z`c".chr(0147)."T5\x68".chr(973078528>>23)."#";};"\x3a".chr(0162).">\x3e".chr(0107)."\52"."Z\x50".chr(587202560>>23)."\176".chr(1031798784>>23)."v\x43\x24".",\63"."n".chr(0153)."\124"."q".chr(072)."\x61\144\60\107".chr(0137);
function hesk_stripArray($a)
{
foreach ($a as $k => $v)
{
if (is_array($v))
{
$a[$k] = hesk_stripArray($v);
}
else
{
$a[$k] = hesk_stripslashes($v);
}
}
reset ($a);
return ($a);
} // END hesk_stripArray()
function hesk_stripslashes($in)
{
if ($in === null) {
return '';
}
return stripslashes($in);
} // END hesk_stripslashes()
function hesk_addslashes($in)
{
if ($in === null) {
return '';
}
return addslashes($in);
} // END hesk_addslashes()
function hesk_slashArray($a)
{
foreach ($a as $k => $v)
{
if (is_array($v))
{
$a[$k] = hesk_slashArray($v);
}
else
{
$a[$k] = hesk_addslashes($v);
}
}
reset ($a);
return ($a);
} // END hesk_slashArray()
function hesk_check_kb_only($redirect = true)
{
global $hesk_settings;
if ($hesk_settings['kb_enable'] != 2)
{
return false;
}
elseif ($redirect)
{
header('Location:knowledgebase.php');
exit;
}
else
{
return true;
}
} // END hesk_check_kb_only()
function hesk_check_maintenance($dodie = true)
{
global $hesk_settings, $hesklang;
// No maintenance mode - return true
if ( ! $hesk_settings['maintenance_mode'] && ! is_dir(HESK_PATH . 'install') )
{
return false;
}
// Maintenance mode, but do not exit - return true
elseif ( ! $dodie)
{
return true;
}
$hesk_installed = $hesk_settings['maintenance_mode'] == 0 &&
$hesk_settings['question_ans'] == 'PB6YM' &&
$hesk_settings['site_title'] == 'Website' &&
$hesk_settings['site_url'] == 'https://www.example.com' &&
$hesk_settings['webmaster_mail'] == 'support@example.com' &&
$hesk_settings['noreply_mail'] == 'support@example.com' &&
$hesk_settings['noreply_name'] == 'Help Desk' &&
$hesk_settings['db_host'] == 'localhost' &&
$hesk_settings['db_name'] == 'hesk' &&
$hesk_settings['db_user'] == 'test' &&
$hesk_settings['db_pass'] == 'test' &&
$hesk_settings['db_pfix'] == 'hesk_' &&
$hesk_settings['hesk_title'] == 'Help Desk' &&
$hesk_settings['hesk_url'] == 'https://www.example.com/helpdesk';
// Just exist if TEMPLATE_PATH is not defined
if ( ! defined('TEMPLATE_PATH')) {
exit($hesklang['mm1']);
}
// Maintenance mode - show notice and exit
$hesk_settings['render_template'](TEMPLATE_PATH . 'customer/maintenance.php', array(
'heskInstalled' => $hesk_installed
));
exit();
} // END hesk_check_maintenance()
function hesk_error($error,$showback=1) {
global $hesk_settings, $hesklang;
$breadcrumb_link = empty($_SESSION['id']) ?
$hesk_settings['hesk_url'] :
HESK_PATH . $hesk_settings['admin_dir'] . '/admin_main.php';
// We ONLY load the customer header, is it's not an admin page, as otherwise it can mess the layout etc.
// TODO note andraz - now it breaks the layout and error shows in the very bottom
if (!defined('IS_ADMIN_PAGE') && defined('TEMPLATE_PATH')) {
$hesk_settings['render_template'](TEMPLATE_PATH . 'customer/error.php', array(
'showDebugWarning' => $hesk_settings['debug_mode'],
'error' => $error,
'showBackLink' => $showback,
'breadcrumbLink' => $breadcrumb_link
));
exit();
}
require_once(HESK_PATH . 'inc/header.inc.php');
?>
<div class="main__content notice-flash">
<div role="alert" class="notification red">
<b><?php echo $hesklang['error']; ?></b>
<p><?php echo $error; ?></p><br>
<?php if ($hesk_settings['debug_mode']): ?>
<p>
<span class="text-danger text-bold"><?php echo $hesklang['warn']; ?></span><br>
<?php echo $hesklang['dmod']; ?>
</p>
<?php
endif;
if ($showback):
?>
<br><br><a class="link" href="javascript:history.go(-1)"><?php echo $hesklang['back']; ?></a>
<?php endif; ?>
</div>
</div>
<?php
exit();
} // END hesk_error()
function hesk_round_to_half($num)
{
if ($num >= ($half = ($ceil = ceil($num))- 0.5) + 0.25)
{
return $ceil;
}
elseif ($num < $half - 0.25)
{
return floor($num);
}
else
{
return $half;
}
} // END hesk_round_to_half()
function hesk3_get_rating($num, $votes = -1) {
$rounded_num = intval(hesk_round_to_half($num) * 10);
$vote_text = '';
if ($votes > -1) {
$vote_text = '<div class="votes">('. $votes .')</div>';
}
return '
<div class="rating">
<div class="star-rate rate-'. $rounded_num .'">
<svg class="icon icon-star-stroke">
<use xlink:href="'. HESK_PATH .'img/sprite.svg#icon-star-stroke"></use>
</svg>
<div class="star-filled">
<svg class="icon icon-star-filled">
<use xlink:href="'. HESK_PATH .'img/sprite.svg#icon-star-filled"></use>
</svg>
</div>
</div>
'. $vote_text .'
</div>';
}
function hesk_full_name_to_first_name($full_name)
{
$name_parts = explode(' ', $full_name);
// Only one part, return back the original
if (count($name_parts) < 2)
{
return $full_name;
}
$first_name = hesk_mb_strtolower($name_parts[0]);
// Name prefixes without dots
$prefixes = array('mr', 'ms', 'mrs', 'miss', 'dr', 'rev', 'fr', 'sr', 'prof', 'sir');
if (in_array($first_name, $prefixes) || in_array($first_name, array_map(function ($i) {return $i . '.';}, $prefixes)))
{
if(isset($name_parts[2]))
{
// Mr James Smith -> James
$first_name = $name_parts[1];
}
else
{
// Mr Smith (no first name given)
return $full_name;
}
}
// Detect LastName, FirstName
if (hesk_mb_substr($first_name, -1, 1) == ',')
{
if (count($name_parts) == 2)
{
$first_name = $name_parts[1];
}
else
{
return $full_name;
}
}
// If the first name doesn't have at least 2 chars, return the original
if(hesk_mb_strlen($first_name) < 2)
{
return $full_name;
}
// Return the name with first character uppercase
return hesk_ucfirst($first_name);
} // END hesk_full_name_to_first_name()
function hesk_generate_random_id() {
/* Ticket ID can be of these chars */
$useChars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890-';
/* Set tracking ID to an empty string */
$random_id = '';
$random_id .= $useChars[mt_rand(0, 62)];
$random_id .= $useChars[mt_rand(0, 62)];
$random_id .= $useChars[mt_rand(0, 62)];
$random_id .= $useChars[mt_rand(0, 62)];
$random_id .= $useChars[mt_rand(0, 62)];
$random_id .= $useChars[mt_rand(0, 62)];
$random_id .= $useChars[mt_rand(0, 62)];
$random_id .= $useChars[mt_rand(0, 62)];
$random_id .= $useChars[mt_rand(0, 62)];
$random_id .= $useChars[mt_rand(0, 62)];
$random_id .= $useChars[mt_rand(0, 62)];
$random_id .= $useChars[mt_rand(0, 62)];
$random_id .= $useChars[mt_rand(0, 62)];
$random_id .= $useChars[mt_rand(0, 62)];
$random_id .= $useChars[mt_rand(0, 62)];
return $random_id;
}
function hesk_generate_old_delete_modal($title, $body, $confirm_link, $delete_text = '') {
global $hesklang, $hesk_settings;
if ($delete_text == '') {
$delete_text = $hesklang['delete'];
}
$random_id = hesk_generate_random_id();
?>
<div class="modal delete-modal" data-modal-id="<?php echo $random_id; ?>">
<div class="modal__body" style="white-space: normal; <?php if ($hesk_settings['limit_width']) echo 'max-width:'.$hesk_settings['limit_width'].'px'; ?>">
<i class="modal__close" data-action="cancel">
<svg class="icon icon-close">
<use xlink:href="<?php echo HESK_PATH; ?>img/sprite.svg#icon-close"></use>
</svg>
</i>
<h3><?php echo $title; ?></h3>
<div class="modal__description">
<?php echo $body; ?>
</div>
<div class="modal__buttons">
<button class="btn btn-border" ripple="ripple" data-action="cancel"><?php echo $hesklang['cancel']; ?></button>
<a data-confirm-button href="<?php echo $confirm_link; ?>" class="btn btn-full text-white" ripple="ripple" style="width: 152px; height: 40px;"><?php echo $delete_text; ?></a>
</div>
</div>
</div>
<?php
return $random_id;
} // end hesk_generate_old_delete_modal()
function hesk_generate_delete_modal($modal_config) {
global $hesklang, $hesk_settings;
$defaults = [
'title' => 'MISSING TITLE',
'body' => 'MISSING BODY',
'confirm_action' => 'MISSING CONFIRM ACTION',
'use_form' => false,
'delete_text' => $hesklang['delete'],
'cancel_text' => $hesklang['cancel']
];
$options = array_merge($defaults, $modal_config);
$random_id = hesk_generate_random_id();
?>
<div class="modal delete-modal" data-modal-id="<?php echo $random_id; ?>">
<div class="modal__body" style="white-space: normal; <?php if ($hesk_settings['limit_width']) echo 'max-width:'.$hesk_settings['limit_width'].'px'; ?>">
<i class="modal__close" data-action="cancel">
<svg class="icon icon-close">
<use xlink:href="<?php echo HESK_PATH; ?>img/sprite.svg#icon-close"></use>
</svg>
</i>
<h3><?php echo $options['title']; ?></h3>
<?php if ($options['use_form']): ?>
<form action="<?php echo $options['confirm_action']; ?>" method="<?php echo $options['form_method']; ?>">
<?php endif; ?>
<div class="modal__description">
<p style="display: block; min-width: 172px; width: auto"><?php echo $options['body']; ?></p>
</div>
<div class="modal__buttons">
<button class="btn btn-border" ripple="ripple" data-action="cancel"><?php echo $options['cancel_text']; ?></button>
<?php if ($options['use_form']): ?>
<button type="submit" class="btn btn-full text-white" ripple="ripple" style="width: 152px; height: 40px;">
<?php echo $options['delete_text']; ?>
</button>
<?php else: ?>
<a data-confirm-button href="<?php echo $options['confirm_action']; ?>" class="btn btn-full text-white <?php echo $options['custom_class']; ?>" ripple="ripple" style="width: 152px; height: 40px;"><?php echo $options['delete_text']; ?></a>
<?php endif; ?>
</div>
<?php if ($options['use_form']): ?>
</form>
<?php endif; ?>
</div>
</div>
<?php
return $random_id;
}
function hesk_authorizeNonCLI()
{
global $hesklang, $hesk_settings;
// URL Access Key not set?
if ($hesk_settings['url_key'] == '') {
return true;
}
// Are we in CLI mode?
if (php_sapi_name() == 'cli' || empty($_SERVER['REMOTE_ADDR'])) {
return true;
}
// Do we have a "key" variable set?
if ( ! isset($_REQUEST['key'])) {
die($hesklang['ukeym'] . ' ' . $_SERVER['SCRIPT_NAME'] . '?key=XXXXXXXXXX');
}
// Is the correct "key" set?
if ($_REQUEST['key'] != $hesk_settings['url_key']) {
die($hesklang['ukeyw']);
}
return true;
} // END hesk_authorizeNonCLI()
function hesk_maskEmailAddress($email_address) {
$mail_parts = explode('@', $email_address);
$name = $mail_parts[0];
$domain = $mail_parts[1];
$domain_with_dot_check = preg_match('/(.+)\.(.*)/', $domain, $domain_matches);
// 1st of user's mailbox name are exposed
$masked = substr($name, 0, 1);
$masked .= str_repeat('*', strlen($name) - 1);
$masked .= '@';
// Last 2 of mailbox domain prior to .whatever are exposed
if ($domain_with_dot_check) {
// 1st match is everything before the last dot. Only mask if the domain is at least 2 characters long
if (strlen($domain_matches[1]) > 1) {
$masked .= str_repeat('*', strlen($domain_matches[1]) - 2);
$masked .= substr($domain_matches[1], strlen($domain_matches[1]) - 2, 2);
$masked .= '.' . $domain_matches[2];
} else {
$masked .= $domain;
}
} else {
// Technically a domain with just "localhost" or similar is valid in email land. Just show the last 2 of their domain
$masked .= str_repeat('*', strlen($domain) - 2);
$masked .= substr($domain, strlen($domain) - 3, 2);
}
return $masked;
}
function hesk_isThereAnotherAdmin($current_admin_id) {
global $hesk_settings;
$res = hesk_dbQuery("SELECT 1 FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."users` WHERE `active` = 1 AND `isadmin` = '1' AND `id` <> ".intval($current_admin_id));
return hesk_dbNumRows($res) > 0;
}
// Alternative to utf8_encode function for PHP 8.2 and 9+ compatibility
function hesk_iso8859_1_to_utf8($s)
{
// Before PHP 8.2 let's just use utf8_encode
if (version_compare(PHP_VERSION, '8.2', '<')) {
return utf8_encode($s);
}
$len = strlen($s);
for ($i = $len >> 1, $j = 0; $i < $len; ++$i, ++$j) {
switch (true) {
case $s[$i] < "\x80": $s[$j] = $s[$i]; break;
case $s[$i] < "\xC0": $s[$j] = "\xC2"; $s[++$j] = $s[$i]; break;
default: $s[$j] = "\xC3"; $s[++$j] = chr(ord($s[$i]) - 64); break;
}
}
return substr($s, 0, $j);
}
function hesk_password_hash($password)
{
if ( ! function_exists('password_hash')) {
global $hesklang;
die($hesklang['old_php_version']);
}
return password_hash($password, PASSWORD_DEFAULT);
} // END hesk_password_hash()
function hesk_password_verify($password, $hash)
{
if ( ! function_exists('password_verify')) {
global $hesklang;
die($hesklang['old_php_version']);
}
return password_verify($password, $hash);
} // END hesk_password_verify()
function hesk_password_needs_rehash($hash)
{
return password_needs_rehash($hash, PASSWORD_DEFAULT);
} // END hesk_password_needs_rehash()
function hesk_activeSessionCreateTag($username, $password_hash)
{
$salt = uniqid(mt_rand(), true);
return $salt . '|' . sha1($salt . hesk_mb_strtolower($username) . $password_hash);
} // END hesk_activeSessionCreateTag()
function hesk_verifyGoto($login_type = 'STAFF')
{
// Default redirect URL
$url_default = $login_type === 'STAFF' ? 'admin_main.php' : 'index.php';
// If no "goto" parameter is set, redirect to the default page
if ( ! hesk_isREQUEST('goto') )
{
return $url_default;
}
// Get the "goto" parameter and make it safe for redirect headers
$url = str_replace(array("\r", "\n", "\0"), '', hesk_REQUEST('goto'));
// Fix encoded "&"
$url = str_replace('&', '&', $url);
// Parse the URL for verification
$url_parts = parse_url($url);
// Only local relative URLs with a path are allowed
if ($url_parts === false || isset($url_parts['scheme']) || isset($url_parts['host']) || ! isset($url_parts['path']) )
{
return $url_default;
}
// Extract the file name from path
$url = basename($url_parts['path']);
// Allowed files for redirect
$OK_urls = [
'index.php' => '',
'my_tickets.php' => '',
'manage_mfa.php' => '',
'knowledgebase.php' => ''
];
if ($login_type === 'STAFF') {
$OK_urls = array(
'admin_main.php' => '',
'admin_settings_email.php' => '',
'admin_settings_general.php' => '',
'admin_settings_help_desk.php' => '',
'admin_settings_theme.php' => '',
'admin_settings_knowledgebase.php' => '',
'admin_settings_misc.php' => '',
'admin_settings_save.php' => 'admin_settings_general.php',
'admin_settings_ticket_list.php' => '',
'admin_ticket.php' => '',
'archive.php' => '',
'assign_owner.php' => '',
'banned_emails.php' => '',
'banned_ips.php' => '',
'change_status.php' => '',
'custom_fields.php' => '',
'custom_statuses.php' => '',
'edit_post.php' => '',
'email_templates.php' => '',
'export.php' => '',
'find_tickets.php' => '',
'generate_spam_question.php' => '',
'knowledgebase_private.php' => '',
'lock.php' => '',
'mail.php' => '',
'mail.php?a=read&id=1' => '',
'manage_canned.php' => '',
'manage_categories.php' => '',
'manage_knowledgebase.php' => '',
'manage_ticket_templates.php' => '',
'manage_users.php' => '',
'manage_customers.php' => '',
'module_statistics.php' => '',
'module_escalate.php' => '',
'module_recurring_tickets.php' => '',
'module_satisfaction.php' => '',
'module_satisfaction_optout.php' => '',
'new_ticket.php' => '',
'oauth_providers.php' => '',
'profile.php' => '',
'reports.php' => '',
'service_messages.php' => '',
'show_tickets.php' => '',
'muted_emails.php' => '',
);
}
// URL must match one of the allowed ones
if ( ! isset($OK_urls[$url]) )
{
return $url_default;
}
// Modify redirect?
if ( strlen($OK_urls[$url]) )
{
$url = $OK_urls[$url];
}
// All OK, return the URL with query if set
if (isset($url_parts['query']))
{
$query = str_replace(array("\r", "\n", "\0"), '', $url_parts['query']);
return strlen($query) ? $url.'?'.$query : $url;
}
return $url;
} // END hesk_verifyGoto()
function hesk_activeSessionValidate($username, $password_hash, $tag)
{
// Salt and hash need to be separated by a |
if ( ! strpos($tag, '|') )
{
return false;
}
// Get two parts of the tag
list($salt, $hash) = explode('|', $tag, 2);
// Make sure the hash matches existing username and password
if ($hash == sha1($salt . hesk_mb_strtolower($username) . $password_hash) )
{
return true;
}
return false;
} // END hesk_activeSessionValidate()
function hesk_time_since($original)
{
global $hesk_settings, $hesklang, $mysql_time;
/* array of time period chunks */
$chunks = array(
array(60 * 60 * 24 * 365 , $hesklang['abbr']['year']),
array(60 * 60 * 24 * 30 , $hesklang['abbr']['month']),
array(60 * 60 * 24 * 7, $hesklang['abbr']['week']),
array(60 * 60 * 24 , $hesklang['abbr']['day']),
array(60 * 60 , $hesklang['abbr']['hour']),
array(60 , $hesklang['abbr']['minute']),
array(1 , $hesklang['abbr']['second']),
);
/* Invalid time */
if ($mysql_time < $original)
{
// DEBUG return "T: $mysql_time (".date('Y-m-d H:i:s',$mysql_time).")<br>O: $original (".date('Y-m-d H:i:s',$original).")";
return "0".$hesklang['abbr']['second'];
}
$since = $mysql_time - $original;
// $j saves performing the count function each time around the loop
for ($i = 0, $j = count($chunks); $i < $j; $i++) {
$seconds = $chunks[$i][0];
$name = $chunks[$i][1];
// finding the biggest chunk (if the chunk fits, break)
if (($count = floor($since / $seconds)) != 0) {
// DEBUG print "<!-- It's $name -->\n";
break;
}
}
$print = "$count{$name}";
if ($i + 1 < $j) {
// now getting the second item
$seconds2 = $chunks[$i + 1][0];
$name2 = $chunks[$i + 1][1];
// add second item if it's greater than 0
if (($count2 = floor(($since - ($seconds * $count)) / $seconds2)) != 0) {
$print .= "$count2{$name2}";
}
}
return $print;
} // END hesk_time_since()
function hesk_time_lastchange($original)
{
global $hesk_settings, $hesklang;
// Save time format setting so we can restore it later
$copy = $hesk_settings['format_timestamp'];
// We need this time format for this function
$hesk_settings['format_timestamp'] = 'Y-m-d H:i:s';
// Get HESK time-adjusted start of today if not already
if ( ! defined('HESK_TIME_TODAY') )
{
// Adjust for HESK time and define constants for alter use
define('HESK_TIME_TODAY', date('Y-m-d 00:00:00', hesk_date(NULL, false, false, false) ) );
define('HESK_TIME_YESTERDAY', date('Y-m-d 00:00:00', strtotime(HESK_TIME_TODAY)-86400) ) ;
}
// Adjust HESK time difference and get day name
$ticket_time = hesk_date($original, true);
if ($ticket_time >= HESK_TIME_TODAY)
{
// For today show HH:MM
$day = substr($ticket_time, 11, 5);
}
elseif ($ticket_time >= HESK_TIME_YESTERDAY)
{
// For yesterday show word "Yesterday"
$day = $hesklang['r2'];
}
else
{
// For other days show DD MMM YY
list($y, $m, $d) = explode('-', substr($ticket_time, 0, 10) );
$day = '<span style="white-space: nowrap;">' . $d . ' ' . $hesklang['ms'.$m] . ' ' . substr($y, 2) . '</span>';
}
// Restore original time format setting
$hesk_settings['format_timestamp'] = $copy;
// Return value to display
return $day;
} // END hesk_time_lastchange()
// Checks the user if they're elevated and not expired. If not, redirect to the elevator
function hesk_check_user_elevation($post_elevation_redirect, $customer_side = false) {
if ($customer_side && (!isset($_SESSION['customer']['elevated']) || $_SESSION['customer']['elevated'] < new DateTime())) {
$_SESSION['customer']['elevated'] = null;
$_SESSION['customer']['elevator_target'] = $post_elevation_redirect;
header('Location: elevator.php');
exit();
} elseif (!$customer_side && (!hesk_SESSION('elevated') || hesk_SESSION('elevated') < new DateTime())) {
$_SESSION['elevated'] = null;
$_SESSION['elevator_target'] = $post_elevation_redirect;
header('Location: elevator.php');
exit();
}
return true;
}
function hesk_get_primary_customer_for_ticket($ticket_id, $fail_on_missing_customer = true) {
global $hesk_settings, $hesklang;
$customer_res = hesk_dbQuery("SELECT * FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."customers`
WHERE `id` = (
SELECT `customer_id`
FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."ticket_to_customer`
WHERE `ticket_id` = ".intval($ticket_id)."
AND `customer_type` = 'REQUESTER'
)");
if (hesk_dbNumRows($customer_res) !== 1) {
if ($fail_on_missing_customer) {
hesk_error($hesklang['customer_not_found']);
} else {
return null;
}
}
return hesk_dbFetchAssoc($customer_res);
}
function hesk_output_customer_name_and_email($customer, $html_encoded_brackets = true) {
global $hesklang;
if ($customer === null || empty($customer)) {
return $hesklang['anon_name'];
}
$name = $customer['name'];
$email = $customer['email'];
if ($name === null || $name === '') {
return $email;
}
if ($email === null || $email === '') {
return $name;
}
// TODO I really don't like having HTML-encoded stuff in here :/
$less_than = $html_encoded_brackets ? '<' : '<';
$greater_than = $html_encoded_brackets ? '>' : '>';
return "{$name} {$less_than}{$email}{$greater_than}";
}
function hesk_output_pager($total_count, $total_pages, $current_page, $query_url, $query_param_name = 'page-number') {
global $hesklang;
$prev_page = ($current_page - 1 <= 0) ? 0 : $current_page - 1;
$next_page = ($current_page + 1 > $total_pages) ? 0 : $current_page + 1;
$query_param = $query_url === '' ? '?' : '&';
if ($total_pages <= 1) {
return;
}
/* List pages */
echo '<div class="pagination-wrap"><div class="pagination">';
if ($total_pages >= 7) {
if ($current_page > 2) {
echo '
<a href="'.$query_url.$query_param.$query_param_name.'=1" class="btn pagination__nav-btn">
<svg class="icon icon-chevron-left" style="margin-right:-6px">
<use xlink:href="'. HESK_PATH .'img/sprite.svg#icon-chevron-left"></use>
</svg>
<svg class="icon icon-chevron-left">
<use xlink:href="'. HESK_PATH .'img/sprite.svg#icon-chevron-left"></use>
</svg>
'.$hesklang['pager_first'].'
</a>';
}
if ($prev_page) {
echo '
<a href="'.$query_url.$query_param.$query_param_name.'='.$prev_page.'" class="btn pagination__nav-btn">
<svg class="icon icon-chevron-left">
<use xlink:href="'. HESK_PATH .'img/sprite.svg#icon-chevron-left"></use>
</svg>
'.$hesklang['pager_previous'].'
</a>';
}
}
echo '<ul class="pagination__list">';
for ($i=1; $i<=$total_pages; $i++) {
if ($i <= ($current_page+5) && $i >= ($current_page-5)) {
if ($i == $current_page) {
echo '
<li class="pagination__item is-current">
<a href="javascript:" class="pagination__link">'.$i.'</a>
</li>';
} else {
echo '
<li class="pagination__item ">
<a href="'.$query_url.$query_param.$query_param_name.'='.$i.'" class="pagination__link">'.$i.'</a>
</li>';
}
}
}
echo '</ul>';
if ($total_pages >= 7) {
if ($next_page) {
echo '
<a href="'.$query_url.$query_param.$query_param_name.'='.$next_page.'" class="btn pagination__nav-btn">
'.$hesklang['pager_next'].'
<svg class="icon icon-chevron-right">
<use xlink:href="'. HESK_PATH .'img/sprite.svg#icon-chevron-right"></use>
</svg>
</a>';
}
if ($current_page < ($total_pages - 1)) {
echo '
<a href="'.$query_url.$query_param.$query_param_name.'='.$total_pages.'" class="btn pagination__nav-btn">
'.$hesklang['pager_last'].'
<svg class="icon icon-chevron-right">
<use xlink:href="'. HESK_PATH .'img/sprite.svg#icon-chevron-right"></use>
</svg>
<svg class="icon icon-chevron-right" style="margin-left:-6px">
<use xlink:href="'. HESK_PATH .'img/sprite.svg#icon-chevron-right"></use>
</svg>
</a>';
}
}
echo '</div>';
echo '<p class="pagination__amount">'.sprintf($hesklang['customers_on_pages'], $total_count, $total_pages).'</p>';
echo '</div>';
}
function hesk_isTicketCollaborator($ticket_id, $user_id)
{
global $hesk_settings, $hesklang, $hesk_db_link;
$result = hesk_dbQuery('SELECT `id` FROM `'.hesk_dbEscape($hesk_settings['db_pfix']).'ticket_to_collaborator` WHERE `ticket_id`='.intval($ticket_id).' AND `user_id`='.intval($user_id).' LIMIT 1');
return hesk_dbNumRows($result);
} // END hesk_isTicketCollaborator()
function hesk_getTicketsCollaboratorIDs($ticket_id)
{
global $hesk_settings, $hesklang, $hesk_db_link;
$collaborators = array();
$res_w = hesk_dbQuery("SELECT `user_id` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."ticket_to_collaborator` WHERE `ticket_id`=".intval($ticket_id));
while ($collaborator = hesk_dbFetchAssoc($res_w)) {
$collaborators[] = $collaborator['user_id'];
}
return $collaborators;
} // END hesk_getTicketsCollaboratorIDs()
function hesk_str_ends_with($haystack, $needle)
{
if (function_exists('str_ends_with')) {
return str_ends_with($haystack, $needle);
}
$needle_len = strlen($needle);
return ($needle_len === 0 || 0 === substr_compare($haystack, $needle, - $needle_len));
} // END hesk_str_ends_with()
function hesk_sendFileDownloadHeaders($filename, $size)
{
$filename = str_replace(array("\r", "\n"), '', (string) $filename);
$filename = basename(str_replace('\\', '/', $filename));
if ($filename === '') {
$filename = 'attachment';
}
$fallback = preg_replace('/[^A-Za-z0-9._-]/', '_', $filename);
if ($fallback === '') {
$fallback = 'attachment';
}
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Length: ' . intval($size));
header('Content-Disposition: attachment; filename="' . str_replace('"', '\"', $fallback) . '"; filename*=UTF-8\'\'' . rawurlencode($filename));
} // END hesk_sendFileDownloadHeaders()
function hesk_curl_close($handle)
{
if (PHP_VERSION_ID < 80500) {
curl_close($handle);
}
return true;
} // END hesk_curl_close()
wget 'https://lists2.roe3.org/hesk/inc/custom_fields.inc.php'
<?php
/**
*
* This file is part of HESK - PHP Help Desk Software.
*
* (c) Copyright Klemen Stirn. All rights reserved.
* https://www.hesk.com
*
* For the full copyright and license agreement information visit
* https://www.hesk.com/eula.php
*
*/
/* Check if this is a valid include */
if (!defined('IN_SCRIPT')) {die('Invalid attempt');}
// Get and append custom fields setup to the settings
hesk_load_custom_fields();
// Save number of custom fields
$hesk_settings['num_custom_fields'] = count($hesk_settings['custom_fields']);
// Append custom fields to the possible ticket table list
foreach ($hesk_settings['custom_fields'] as $k => $v) {
$hesk_settings['possible_ticket_list'][$k] = $hesk_settings['custom_fields'][$k]['title'];
$hesk_settings['possible_customer_ticket_list'][$k] = $hesk_settings['custom_fields'][$k]['title'];
}
/*** FUNCTIONS ***/
function hesk_load_custom_fields($category=0, $use_cache=1)
{
global $hesk_settings, $hesklang;
// Do we have a cached version available
$cache_dir = dirname(dirname(__FILE__)).'/'.$hesk_settings['cache_dir'].'/';
$cache_file = $cache_dir . 'cf_' . sha1($hesk_settings['language']).'.cache.php';
if ($use_cache && file_exists($cache_file))
{
require($cache_file);
return true;
}
// Get custom fields from the database
$hesk_settings['custom_fields'] = array();
// Make sure we have database connection
hesk_load_database_functions();
hesk_dbConnect();
$res = hesk_dbQuery("SELECT * FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."custom_fields` WHERE `use` IN ('1', '2') ORDER BY `place` ASC, `order` ASC");
while ($row = hesk_dbFetchAssoc($res))
{
$id = 'custom' . $row['id'];
unset($row['id']);
// Let's set field name for current language (or the first one we find)
$names = json_decode($row['name'], true);
$row['name'] = (isset($names[$hesk_settings['language']])) ? $names[$hesk_settings['language']] : reset($names);
// Name for display in ticket list; punctuation removed and shortened
$row['title'] = hesk_remove_punctuation($row['name']);
$row['title'] = hesk_mb_strlen($row['title']) > 30 ? hesk_mb_substr($row['title'], 0, 30) . '...' : $row['title'];
// A version with forced punctuation
$row['name:'] = in_array(substr($row['name'], -1), array(':', '?', '!', '.') ) ? $row['name'] : $row['name'] . ':';
// Decode categories
$row['category'] = !empty($row['category']) ? json_decode($row['category'], true) : array();
// Decode options
$row['value'] = json_decode($row['value'], true);
// Add to custom_fields array
$hesk_settings['custom_fields'][$id] = $row;
}
// Try to cache results
if ($use_cache && (is_dir($cache_dir) || ( @mkdir($cache_dir, 0777) && is_writable($cache_dir) ) ) )
{
// Is there an index.htm file?
if ( ! file_exists($cache_dir.'index.htm'))
{
@file_put_contents($cache_dir.'index.htm', '');
}
// Write data
@file_put_contents($cache_file, '<?php if (!defined(\'IN_SCRIPT\')) {die();} $hesk_settings[\'custom_fields\']=' . var_export($hesk_settings['custom_fields'], true) . ';' );
}
return true;
} // END hesk_load_custom_fields()
function hesk_is_custom_field_in_category($custom_id, $category_id)
{
global $hesk_settings;
return (
empty($hesk_settings['custom_fields'][$custom_id]['category']) ||
in_array($category_id, $hesk_settings['custom_fields'][$custom_id]['category'])
) ? true : false;
} // END hesk_is_custom_field_in_category()
function hesk_custom_field_type($type)
{
global $hesklang;
switch ($type)
{
case 'text':
return $hesklang['stf'];
case 'textarea':
return $hesklang['stb'];
case 'radio':
return $hesklang['srb'];
case 'select':
return $hesklang['ssb'];
case 'checkbox':
return $hesklang['scb'];
case 'email':
return $hesklang['email'];
case 'date':
return $hesklang['date'];
case 'hidden':
return $hesklang['sch'];
default:
return false;
}
} // END hesk_custom_field_type()
function hesk_custom_date_display_format($timestamp, $format = 'F j, Y')
{
global $hesklang;
if ($timestamp == '')
{
return '';
}
if ( ! is_int($timestamp))
{
$timestamp = $timestamp * 1;
}
if ($hesklang['LANGUAGE']=='English')
{
return gmdate($format, $timestamp);
}
// Attempt to translate date for non-English users
$translate_months = array(
'January' => $hesklang['m1'],
'February' => $hesklang['m2'],
'March' => $hesklang['m3'],
'April' => $hesklang['m4'],
'May' => $hesklang['m5'],
'June' => $hesklang['m6'],
'July' => $hesklang['m7'],
'August' => $hesklang['m8'],
'September' => $hesklang['m9'],
'October' => $hesklang['m10'],
'November' => $hesklang['m11'],
'December' => $hesklang['m12']
);
$translate_months_short = array(
'Jan' => $hesklang['ms01'],
'Feb' => $hesklang['ms02'],
'Mar' => $hesklang['ms03'],
'Apr' => $hesklang['ms04'],
'May' => $hesklang['ms05'],
'Jun' => $hesklang['ms06'],
'Jul' => $hesklang['ms07'],
'Aug' => $hesklang['ms08'],
'Sep' => $hesklang['ms09'],
'Oct' => $hesklang['ms10'],
'Nov' => $hesklang['ms11'],
'Dec' => $hesklang['ms12']
);
$translate_days = array(
'Monday' => $hesklang['d1'],
'Tuesday' => $hesklang['d2'],
'Wednesday' => $hesklang['d3'],
'Thursday' => $hesklang['d4'],
'Friday' => $hesklang['d5'],
'Saturday' => $hesklang['d6'],
'Sunday' => $hesklang['d0']
);
$translate_days_short = array(
'Mon' => $hesklang['mo'],
'Tuw' => $hesklang['tu'],
'Wes' => $hesklang['we'],
'Thu' => $hesklang['th'],
'Fri' => $hesklang['fr'],
'Sat' => $hesklang['sa'],
'Sun' => $hesklang['su']
);
$date_translate = array();
if (strpos($format, 'F') !== false)
{
$date_translate = array_merge($date_translate, $translate_months);
}
if (strpos($format, 'M') !== false)
{
$date_translate = array_merge($date_translate, $translate_months_short);
}
if (strpos($format, 'l') !== false)
{
$date_translate = array_merge($date_translate, $translate_days);
}
if (strpos($format, 'D') !== false)
{
$date_translate = array_merge($date_translate, $translate_days_short);
}
if (count($date_translate))
{
return str_replace( array_keys($date_translate), array_values($date_translate), gmdate($format, $timestamp));
}
return gmdate($format, $timestamp);
} // END hesk_custom_date_display_format()
function hesk_remove_punctuation($in)
{
return rtrim($in, ':?!.');
} // END hesk_remove_punctuation()
wget 'https://lists2.roe3.org/hesk/inc/customer_accounts.inc.php'
<?php
/**
*
* This file is part of HESK - PHP Help Desk Software.
*
* (c) Copyright Klemen Stirn. All rights reserved.
* https://www.hesk.com
*
* For the full copyright and license agreement information visit
* https://www.hesk.com/eula.php
*
*/
use RobThree\Auth\TwoFactorAuth;
/* Check if this is a valid include */
if (!defined('IN_SCRIPT')) {die('Invalid attempt');}
// Possible fields to be displayed in ticket list
$hesk_settings['possible_customer_ticket_list'] = array(
'id' => $hesklang['id'],
'trackid' => $hesklang['trackID'],
'dt' => $hesklang['submitted'],
'lastchange' => $hesklang['last_update'],
'category' => $hesklang['category'],
//'name' => $hesklang['customer'],
//'email' => $hesklang['email'],
'subject' => $hesklang['subject'],
'status' => $hesklang['status'],
'owner' => $hesklang['owner'],
'replies' => $hesklang['replies'],
'staffreplies' => $hesklang['replies'] . ' (' . $hesklang['staff'] .')',
//'lastreplier' => $hesklang['last_replier'],
'time_worked' => $hesklang['ts'],
'due_date' => $hesklang['due_date']
);
function hesk_get_customer_account_by_name($name) {
global $hesk_settings;
// Verified = 1 (approved, verified) | 2 (pending approval)
// Verified = 0, but with verification_token (pending verification)
$sql = "SELECT * FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "customers`
WHERE `name` = '" . hesk_dbEscape($name) . "'
AND TRIM(`email`) = ''";
$rs = hesk_dbQuery($sql);
if ($row = hesk_dbFetchAssoc($rs)) {
return $row;
}
return null;
}
function hesk_get_customer_account_by_name_and_email($name, $email) {
global $hesk_settings;
$sql = "SELECT * FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "customers`
WHERE `email` = '" . hesk_dbEscape(trim($email)) . "'
AND `name` = '". hesk_dbEscape(trim($name)) ."'";
$rs = hesk_dbQuery($sql);
if ($row = hesk_dbFetchAssoc($rs)) {
return $row;
}
return null;
}
function hesk_get_customer_account_by_email($email, $registration = false, $verified_only = false) {
global $hesk_settings;
// Verified = 1 (approved, verified) | 2 (pending approval)
// Verified = 0, but with verification_token (pending verification)
$sql = "SELECT * FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "customers`
WHERE `email` = '" . hesk_dbEscape($email) . "'";
// If we're registering, we should only check if an existing account is verified or pending verification
if ($registration) {
$sql .= " AND (`verified` IN (1, 2) OR (`verified` = 0 AND `verification_token` IS NOT NULL))";
}
// Only return verified accounts?
if ($verified_only) {
$sql .= " AND `verified` = '1' ";
}
$rs = hesk_dbQuery($sql);
if ($row = hesk_dbFetchAssoc($rs)) {
if (empty($row['email'])) {
$row['email'] = '';
}
return $row;
}
return null;
}
function hesk_get_customer_account_by_id($id) {
global $hesk_settings;
$sql = "SELECT * FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "customers`
WHERE `id` = " . intval($id);
$rs = hesk_dbQuery($sql);
if ($row = hesk_dbFetchAssoc($rs)) {
if (empty($row['email'])) {
$row['email'] = '';
}
return $row;
}
return null;
}
function hesk_get_or_create_customer($name, $email, $create_if_not_found = true) {
global $hesk_settings, $hesklang;
$name = ($name === null || $name == '') ? '' : trim($name);
$email = ($email === null || $email == '') ? '' : trim($email);
// If email is empty just create a new account
if (empty($email)) {
if ($create_if_not_found) {
hesk_dbQuery("INSERT INTO `".hesk_dbEscape($hesk_settings['db_pfix'])."customers` (`name`) VALUES ('".hesk_dbEscape($name)."')");
return hesk_dbInsertID();
}
return null;
}
//-- If we already have a customer record based on name and email, return its id
$existing_customer_rs = hesk_dbQuery("SELECT `id` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."customers`
WHERE `email` = '".hesk_dbEscape($email)."'
AND `name` = '".hesk_dbEscape($name)."'
LIMIT 1");
if ($row = hesk_dbFetchAssoc($existing_customer_rs)) {
return $row['id'];
}
// Is there a registered user with this email already? If so, return it as we can't create extra customers when one
// is already registered with this email.
$registered_email_rs = hesk_dbQuery("SELECT `id` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."customers`
WHERE `email` = '".hesk_dbEscape($email)."'
AND `verified` = 1");
if ($row = hesk_dbFetchAssoc($registered_email_rs)) {
return $row['id'];
}
//-- No match. Create a new customer if the user wants to
if ($create_if_not_found) {
hesk_dbQuery("INSERT INTO `".hesk_dbEscape($hesk_settings['db_pfix'])."customers` (`name`, `email`)
VALUES ('".hesk_dbEscape(trim($name))."', '".hesk_dbEscape(trim($email))."')");
return hesk_dbInsertID();
}
return null;
}
function hesk_get_or_create_follower($email, $name = '') {
global $hesk_settings;
$name = ($name === null || $name == '') ? '' : trim($name);
$email = ($email === null || $email == '') ? '' : trim($email);
$email = hesk_validateEmail(hesk_htmlspecialchars_decode($email), '', 0);
// If email is empty it's not a valid follower
if (empty($email)) {
return null;
}
//-- If we already have a customer record based on name and email, return its id
$existing_customer_rs = hesk_dbQuery("SELECT `id` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."customers`
WHERE `email` = '".hesk_dbEscape($email)."'
AND `name` = '".hesk_dbEscape($name)."'
LIMIT 1");
if ($row = hesk_dbFetchAssoc($existing_customer_rs)) {
return $row['id'];
}
// Is there a registered user with this email already? If so, return it as we can't create extra customers when one
// is already registered with this email.
$registered_email_rs = hesk_dbQuery("SELECT `id` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."customers`
WHERE `email` = '".hesk_dbEscape($email)."'
AND `verified` = 1");
if ($row = hesk_dbFetchAssoc($registered_email_rs)) {
return $row['id'];
}
//-- No match. Create a new customer
hesk_dbQuery("INSERT INTO `".hesk_dbEscape($hesk_settings['db_pfix'])."customers` (`name`, `email`)
VALUES ('".hesk_dbEscape(trim($name))."', '".hesk_dbEscape($email)."')");
return hesk_dbInsertID();
}
function hesk_get_customer_id_by_email($email, $verified_only = false) {
global $hesk_settings;
$sql = "SELECT `id` FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "customers`
WHERE `email` = '" . hesk_dbEscape($email) . "'";
// Only return verified accounts?
if ($verified_only) {
$sql .= " AND `verified` = '1' ";
}
$rs = hesk_dbQuery($sql);
if ($row = hesk_dbFetchAssoc($rs)) {
return $row['id'];
}
return null;
}
function hesk_verify_customer_account($email, $verification_token) {
global $hesk_settings;
$sql = "UPDATE `".hesk_dbEscape($hesk_settings['db_pfix'])."customers`
SET `verified` = 1,
`verification_token` = NULL
WHERE `email` = '".hesk_dbEscape($email)."'
AND `verification_token` = '".hesk_dbEscape($verification_token)."'";
hesk_dbQuery($sql);
return hesk_dbAffectedRows() === 1;
}
function hesk_merge_customer_accounts($email) {
global $hesk_settings;
$destination_customer_id_rs = hesk_dbQuery("SELECT `id` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."customers`
WHERE `email` = '".hesk_dbEscape($email)."'
AND `verified` = 1
AND `verification_token` IS NULL
LIMIT 1");
$row = hesk_dbFetchAssoc($destination_customer_id_rs);
$destination_customer_id = $row['id'];
// Migrate ticket mappings to the new customer ID
hesk_dbQuery("UPDATE `".hesk_dbEscape($hesk_settings['db_pfix'])."ticket_to_customer`
SET `customer_id` = ".intval($destination_customer_id)."
WHERE `customer_id` IN (
SELECT `id`
FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."customers`
WHERE `email` = '".hesk_dbEscape($email)."'
AND `verified` = 0
)");
// Migrate ticket replies to the new customer ID
hesk_dbQuery("UPDATE `".hesk_dbEscape($hesk_settings['db_pfix'])."replies`
SET `customer_id` = ".intval($destination_customer_id)."
WHERE `customer_id` IN (
SELECT `id`
FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."customers`
WHERE `email` = '".hesk_dbEscape($email)."'
AND `verified` = 0
)");
// Delete old customer records
hesk_dbQuery("DELETE FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."customers`
WHERE `email` = '".hesk_dbEscape($email)."'
AND `verified` = 0");
}
function hesk_mark_account_needing_approval($email) {
global $hesk_settings;
hesk_dbQuery("UPDATE `".hesk_dbEscape($hesk_settings['db_pfix'])."customers`
SET `verified` = 2
WHERE `email` = '".hesk_dbEscape($email)."'");
}
// Very similar to admin/index.php's process_successful_login function, but segregated so we don't mix staff/customer logic
function hesk_process_successful_customer_login($user, $noredirect = false, $is_autologin = false, $remember_user = null) {
global $hesk_settings, $hesklang;
if ($remember_user === null) {
$remember_user = hesk_POST('remember_user');
}
// User authenticated, let's regenerate the session ID
hesk_session_regenerate_id();
// Set a tag that will be used to expire sessions after username or password change
$_SESSION['customer']['session_verify'] = hesk_activeSessionCreateTag($user['email'], $user['pass']);
// Set data we need for the session
unset($user['pass']);
unset($user['mfa_secret']);
foreach ($user as $k => $v) {
$_SESSION['customer'][$k] = $v;
}
// Reset repeated emails session data
hesk_cleanSessionVars('mfa_emails_sent');
// On login, the customer account language is authoritative over any public-language cookie.
$user = hesk_applyCustomerLanguage($user, false);
/* Login successful, clean brute force attempts */
hesk_cleanBfAttempts();
// Give the user some time before requiring re-authentication for sensitive pages
if (!$is_autologin) {
$current_time = new DateTime();
$interval_amount = $hesk_settings['elevator_duration'];
if (in_array(substr($interval_amount, -1), array('M', 'H'))) {
$interval_amount = 'T'.$interval_amount;
}
$elevation_expiration = $current_time->add(new DateInterval("P{$interval_amount}"));
$_SESSION['customer']['elevated'] = $elevation_expiration;
} else {
// Auto-login must not preserve a previously elevated customer session
if (isset($_SESSION['customer']['elevated'])) {
unset($_SESSION['customer']['elevated']);
}
if (isset($_SESSION['customer']['elevator_target'])) {
unset($_SESSION['customer']['elevator_target']);
}
}
// Remember username?
if (!$is_autologin) {
if ($hesk_settings['customer_autologin'] && $remember_user === 'AUTOLOGIN') {
$selector = base64_encode(random_bytes(9));
$authenticator = random_bytes(33);
hesk_dbQuery("INSERT INTO `".hesk_dbEscape($hesk_settings['db_pfix'])."auth_tokens` (`selector`,`token`,`user_id`,`user_type`,`expires`) VALUES ('".hesk_dbEscape($selector)."','".hesk_dbEscape(hash('sha256', $authenticator))."','".intval($_SESSION['customer']['id'])."','CUSTOMER', NOW() + INTERVAL 1 YEAR)");
hesk_setcookie('hesk_customer_username', '');
hesk_setcookie('hesk_customer_remember', $selector.':'.base64_encode($authenticator), strtotime('+1 year'));
} elseif ($remember_user === 'JUSTUSER') {
hesk_setcookie('hesk_customer_username', $user['email'], strtotime('+1 year'));
hesk_setcookie('hesk_customer_remember', '');
} else {
hesk_setcookie('hesk_customer_username', '');
hesk_setcookie('hesk_customer_remember', '');
}
}
/* If session expired while a HESK page is open just continue using it, don't redirect */
if ($noredirect)
{
return true;
}
/* Redirect to the destination page */
header('Location: ' . hesk_verifyGoto('CUSTOMER') );
exit();
}
function hesk_applyCustomerLanguage($customer, $allow_explicit_selection = true) {
global $hesk_settings;
if (empty($hesk_settings['can_sel_lang']) || ! is_array($customer)) {
return $customer;
}
if ($allow_explicit_selection && isset($_GET['language'])) {
$language = hesk_input(hesk_GET('language'));
if ($language && isset($hesk_settings['languages'][$language])) {
if ($hesk_settings['language'] != $language) {
hesk_setLanguage($language);
}
hesk_setcookie('hesk_language', $language, time()+31536000, '/');
if (isset($customer['id']) && (!isset($customer['language']) || $customer['language'] != $language)) {
hesk_dbQuery("UPDATE `".hesk_dbEscape($hesk_settings['db_pfix'])."customers` SET `language` = '".hesk_dbEscape($language)."' WHERE `id` = ".intval($customer['id']));
$customer['language'] = $language;
}
if (isset($_SESSION['customer']) && is_array($_SESSION['customer'])) {
$_SESSION['customer']['language'] = $language;
}
return $customer;
}
}
if ( ! empty($customer['language']) && isset($hesk_settings['languages'][$customer['language']])) {
if ($hesk_settings['language'] != $customer['language']) {
hesk_setLanguage($customer['language']);
}
hesk_setcookie('hesk_language', $customer['language'], time()+31536000, '/');
if (isset($_SESSION['customer']) && is_array($_SESSION['customer'])) {
$_SESSION['customer']['language'] = $customer['language'];
}
}
return $customer;
}
// Similar to hesk_isLoggedIn(), but for customers
function hesk_isCustomerLoggedIn($redirect = true) {
global $hesk_settings, $hesklang;
// If customer accounts are disabled, no one is ever logged in, and we should simply go back to the index page
if ( ! $hesk_settings['customer_accounts']) {
if ( ! $redirect) {
return null;
}
header('Location: index.php');
exit();
}
$referer = hesk_input($_SERVER['REQUEST_URI']);
$referer = str_replace('&','&',$referer);
// Customer login URL
$url = $hesk_settings['hesk_url'] . '/login.php?notice=1&goto='.urlencode($referer);
if (empty($_SESSION['customer']['id']) || empty($_SESSION['customer']['session_verify'])) {
//-- We only want to auto-login if we're going to a page that requires authentication
if ($hesk_settings['customer_autologin'] && $redirect && hesk_customerAutoLogin(true)) {
return true;
}
} else {
// hesk_session_regenerate_id();
// Let's make sure user still exists and is verified
$res = hesk_dbQuery( "SELECT `id`, `email`, `pass`, `name`, `email`, `language`, `mfa_enrollment` FROM `".$hesk_settings['db_pfix']."customers` WHERE `id` = '".intval($_SESSION['customer']['id'])."' AND `verified` = 1 LIMIT 1" );
// Exit if user not found
if (hesk_dbNumRows($res) === 1) {
// Fetch results from database
$me = hesk_dbFetchAssoc($res);
// Was the email banned?
if (hesk_isBannedEmail($me['email'])) {
hesk_forceLogoutCustomer($hesklang['customer_accounts_email_banned']);
}
// Verify this session is still valid
if (hesk_activeSessionValidate($me['email'], $me['pass'], $_SESSION['customer']['session_verify'])) {
return hesk_applyCustomerLanguage($me);
}
}
}
// If we get here, then we're not logged in.
if ($redirect) {
// Only destroy the session if redirecting...otherwise things get messed up
hesk_session_stop();
header('Location: '.$url);
exit();
} else {
return null;
}
}
function hesk_handle_customer_password_reset_request($email) {
global $hesk_settings, $hesklang;
// Get user data from the database
$res = hesk_dbQuery("SELECT `id`, `name`, `pass` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."customers` WHERE `verified`=1 AND `email` = '".hesk_dbEscape($email)."' LIMIT 1");
if (hesk_dbNumRows($res) != 1)
{
hesk_process_messages($hesklang['novace'],'login.php?submittedForgot=1');
}
else
{
$row = hesk_dbFetchAssoc($res);
$reset_token = hesk_create_password_reset_token();
$reset_hash = hesk_hash_password_reset_token($reset_token);
$customer_id = intval($row['id']);
// Expire old verification hashes for this customer account
hesk_dbQuery("DELETE FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."reset_password` WHERE `user_type` = 'CUSTOMER' AND `user` = {$customer_id}");
// Insert the verification hash into the database
hesk_dbQuery("INSERT INTO `".hesk_dbEscape($hesk_settings['db_pfix'])."reset_password` (`user`, `hash`, `ip`, `user_type`) VALUES ({$customer_id}, '".hesk_dbEscape($reset_hash)."', '".hesk_dbEscape(hesk_getClientIP())."', 'CUSTOMER') ");
// Prepare and send email
require_once(HESK_PATH . 'inc/email_functions.inc.php');
// Get the email message
list($msg, $html_msg) = hesk_getEmailMessage('customer_reset_password',array(),1,0,1);
// Replace message special tags
list($msg, $html_msg) = hesk_replace_email_tag('%%NAME%%', hesk_msgToPlain($row['name'],1,0), $msg, $html_msg);
list($msg, $html_msg) = hesk_replace_email_tag('%%SITE_URL%%', $hesk_settings['site_url'], $msg, $html_msg);
list($msg, $html_msg) = hesk_replace_email_tag('%%SITE_TITLE%%', $hesk_settings['site_title'], $msg, $html_msg);
list($msg, $html_msg) = hesk_replace_email_tag('%%PASSWORD_RESET%%',
$hesk_settings['hesk_url'].'/reset_password.php?hash='.$reset_token,
$msg,
$html_msg);
// Check two additional tags (avoid a bug in 3.3.0)
list($msg, $html_msg) = hesk_replace_email_tag('%25%25PASSWORD_RESET%25%25',
$hesk_settings['hesk_url'].'/reset_password.php?hash='.$reset_token,
$msg,
$html_msg);
list($msg, $html_msg) = hesk_replace_email_tag('%%TRACK_URL%%',
$hesk_settings['hesk_url'].'/reset_password.php?hash='.$reset_token,
$msg,
$html_msg);
// Send email
hesk_mail($email, [], $hesklang['customer_reset_password'], $msg, $html_msg);
}
}
function hesk_verify_customer_password_reset_hash($hash, $purge_user_hashes = false) {
global $hesk_settings, $hesklang;
// Get the reset token and hash it for database lookup
$reset_token = hesk_clean_password_reset_token($hash);
$reset_hash = hesk_hash_password_reset_token($reset_token);
// Expire verification hashes older than 1 hour
hesk_dbQuery("DELETE FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."reset_password` WHERE `dt` < (NOW() - INTERVAL 1 HOUR)");
// Verify the hash exists
$res = hesk_dbQuery("SELECT `user`, `ip` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."reset_password` WHERE `hash` = '".hesk_dbEscape($reset_hash)."' AND `user_type` = 'CUSTOMER' LIMIT 1");
if (hesk_dbNumRows($res) !== 1) {
// Not a valid hash
hesk_limitBfAttempts();
return [
'success' => false,
'content' => $hesklang['ehash']
];
}
// Get info from database
$row = hesk_dbFetchAssoc($res);
// Only allow resetting password from the same IP address that submitted password reset request
if ($row['ip'] != hesk_getClientIP()) {
hesk_limitBfAttempts();
return [
'success' => false,
'content' => $hesklang['ehaip']
];
}
// Expire all verification hashes for this user if requested
if ($purge_user_hashes) {
hesk_dbQuery("DELETE FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."reset_password`
WHERE `user_type` = 'CUSTOMER'
AND `user`=".intval($row['user']));
}
// Clean brute force attempts
hesk_cleanBfAttempts();
return [
'success' => true,
'content' => $row['user']
];
}
//region MFA
function hesk_remove_mfa_for_customer($customer_id) {
global $hesk_settings;
hesk_dbQuery("UPDATE `".hesk_dbEscape($hesk_settings['db_pfix'])."customers`
SET `mfa_enrollment` = 0,
`mfa_secret` = NULL
WHERE `id` = ".intval($customer_id));
}
//endregion
function hesk_get_customers_for_ticket($ticket_id) {
global $hesk_settings;
$customers_res = hesk_dbQuery("SELECT `customers`.`id`, `customers`.`name`, `customers`.`email`, `customers`.`language`, `ticket_to_customer`.`customer_type`
FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."customers` `customers`
INNER JOIN `".hesk_dbEscape($hesk_settings['db_pfix'])."ticket_to_customer` `ticket_to_customer`
ON `customers`.`id` = `ticket_to_customer`.`customer_id`
WHERE `ticket_to_customer`.`ticket_id` = ".intval($ticket_id));
$customers = [];
while ($row = hesk_dbFetchAssoc($customers_res)) {
if (empty($row['email'])) {
$row['email'] = '';
}
$customers[] = $row;
}
if (defined('HESK_DEMO')) {
array_walk($customers, function(&$k) {
$k['email'] = 'hidden@demo.com';
});
}
return $customers;
}
function hesk_purge_expired_email_change_requests() {
global $hesk_settings;
hesk_dbQuery("DELETE FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."pending_customer_email_changes`
WHERE `expires_at` < NOW()");
}
function hesk_purge_email_change_requests($user_id) {
global $hesk_settings;
hesk_dbQuery("DELETE FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."pending_customer_email_changes`
WHERE `customer_id` = ".intval($user_id));
}
function hesk_get_pending_email_change_for_user($user_id) {
global $hesk_settings;
$res = hesk_dbQuery("SELECT `new_email`,
CASE
WHEN `expires_at` > (NOW() + INTERVAL ".intval(60 - $hesk_settings['customer_accounts_verify_email_cooldown'])." MINUTE) THEN 1
ELSE 0
END AS `email_sent_too_recently`
FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."pending_customer_email_changes`
WHERE `customer_id` = ".intval($user_id)." AND `expires_at` > NOW()");
if ($row = hesk_dbFetchAssoc($res)) {
return $row;
}
return null;
}
function hesk_get_pending_email_change_for_email($email, $user_id) {
global $hesk_settings;
$res = hesk_dbQuery("SELECT 1 FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."pending_customer_email_changes`
WHERE `new_email` = '".hesk_dbEscape($email)."' AND `customer_id` <> ".intval($user_id));
return hesk_dbNumRows($res);
}
function hesk_insert_email_change_request($email, $user_id) {
global $hesk_settings;
$verification_token = bin2hex(random_bytes(16));
hesk_dbQuery("INSERT INTO `".hesk_dbEscape($hesk_settings['db_pfix'])."pending_customer_email_changes` (`customer_id`,`new_email`,`verification_token`,`expires_at`)
VALUES (".intval($user_id).", '".hesk_dbEscape($email)."', '".hesk_dbEscape($verification_token)."', NOW() + INTERVAL 60 MINUTE)");
return $verification_token;
}
function hesk_verify_email_change_request($email, $verification_token) {
global $hesk_settings;
$change_request_rs = hesk_dbQuery("SELECT `id`, `customer_id` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."pending_customer_email_changes`
WHERE `new_email` = '".hesk_dbEscape($email)."'
AND `verification_token` = '".hesk_dbEscape($verification_token)."'
AND `expires_at` >= NOW()");
$row = hesk_dbFetchAssoc($change_request_rs);
if (!$row) {
return false;
}
$request_id = intval($row['id']);
$customer_id = intval($row['customer_id']);
// Re-check the target email when the verification link is used. The email may have become banned,
// claimed by another customer account, or reserved by another pending email-change request after this
// request was created.
if (hesk_isBannedEmail($email)) {
hesk_dbQuery("DELETE FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."pending_customer_email_changes` WHERE `id` = {$request_id}");
return false;
}
$email = hesk_dbEscape($email);
$request_id = intval($row['id']);
$customer_id = intval($row['customer_id']);
$sql = "UPDATE `".hesk_dbEscape($hesk_settings['db_pfix'])."customers` AS `target_customer`
LEFT JOIN `".hesk_dbEscape($hesk_settings['db_pfix'])."customers` AS `existing_customer`
ON `existing_customer`.`email` = '{$email}'
AND `existing_customer`.`id` <> {$customer_id}
AND (`existing_customer`.`verified` IN (1, 2) OR (`existing_customer`.`verified` = 0 AND `existing_customer`.`verification_token` IS NOT NULL))
LEFT JOIN `".hesk_dbEscape($hesk_settings['db_pfix'])."pending_customer_email_changes` AS `pending_email_change`
ON `pending_email_change`.`new_email` = '{$email}'
AND `pending_email_change`.`id` <> {$request_id}
AND `pending_email_change`.`expires_at` >= NOW()
SET `target_customer`.`email` = '{$email}',
`target_customer`.`verification_token` = NULL
WHERE `target_customer`.`id` = {$customer_id}
AND `target_customer`.`verified` = 1
AND `existing_customer`.`id` IS NULL
AND `pending_email_change`.`id` IS NULL";
hesk_dbQuery($sql);
if (hesk_dbAffectedRows() === 1) {
hesk_purge_email_change_requests($customer_id);
hesk_dbQuery("DELETE FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."auth_tokens` WHERE `user_id` = {$customer_id} AND `user_type` = 'CUSTOMER'");
return true;
}
hesk_dbQuery("DELETE FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."pending_customer_email_changes` WHERE `id` = {$request_id}");
return false;
}
function hesk_customerAutoLogin($noredirect = false)
{
global $hesk_settings, $hesklang, $hesk_db_link;
$cookie_name = 'hesk_customer_remember';
if (!$hesk_settings['customer_autologin']) {
return false;
}
if (empty($remember = hesk_COOKIE($cookie_name)) || substr_count($remember, ':') !== 1) {
return false;
}
// Login cookies exist, now lets limit brute force attempts
hesk_limitBfAttempts();
// Admin login URL
$url = $hesk_settings['hesk_url'] . '/login.php?notice=1';
// Get and verify authentication tokens
list($selector, $authenticator) = explode(':', $remember);
$authenticator = base64_decode($authenticator);
if (strlen($authenticator) > 256) {
hesk_setcookie($cookie_name, '');
header('Location: '.$url);
exit();
}
$result = hesk_dbQuery('SELECT * FROM `'.$hesk_settings['db_pfix']."auth_tokens`
WHERE `selector` = '".hesk_dbEscape($selector)."'
AND `expires` > NOW()
AND `user_type` = 'CUSTOMER'
LIMIT 1");
if (hesk_dbNumRows($result) != 1) {
hesk_setcookie($cookie_name, '');
header('Location: '.$url);
exit();
}
$auth = hesk_dbFetchAssoc($result);
if ( ! hash_equals($auth['token'], hash('sha256', $authenticator))) {
hesk_setcookie($cookie_name, '');
header('Location: '.$url);
exit();
}
// Token OK, let's regenerate session ID and get user data
hesk_session_regenerate_id();
$result = hesk_dbQuery('SELECT * FROM `'.$hesk_settings['db_pfix']."customers` WHERE `id` = ".intval($auth['user_id'])." AND `verified` = 1 LIMIT 1");
if (hesk_dbNumRows($result) != 1) {
hesk_setcookie($cookie_name, '');
header('Location: '.$url);
exit();
}
$row = hesk_dbFetchAssoc($result);
if (hesk_isBannedEmail($row['email'])) {
hesk_setcookie($cookie_name, '');
header('Location: '.$url);
exit();
}
$user = $row['email'];
define('HESK_USER_CUSTOMER', $user);
// Auto-login is a login transition, so the customer account language is authoritative
// over any public-language query parameter or cookie.
$row = hesk_applyCustomerLanguage($row, false);
// Each token should only be used once, so update the old one with a new one
$selector = base64_encode(random_bytes(9));
$authenticator = random_bytes(33);
hesk_dbQuery("UPDATE `".hesk_dbEscape($hesk_settings['db_pfix'])."auth_tokens` SET `selector`='".hesk_dbEscape($selector)."', `token` = '".hesk_dbEscape(hash('sha256', $authenticator))."', `created` = NOW() WHERE `id` = ".intval($auth['id']));
hesk_setcookie($cookie_name, $selector.':'.base64_encode($authenticator), strtotime('+1 year'));
// Set a tag that will be used to expire sessions after username or password change
$_SESSION['customer']['session_verify'] = hesk_activeSessionCreateTag($user, $row['pass']);
/* Login successful, clean brute force attempts */
hesk_cleanBfAttempts();
return hesk_process_successful_customer_login($row, $noredirect, true);
} // END hesk_customerAutoLogin()
wget 'https://lists2.roe3.org/hesk/inc/customer_modal.inc.php'
<?php
/**
*
* This file is part of HESK - PHP Help Desk Software.
*
* (c) Copyright Klemen Stirn. All rights reserved.
* https://www.hesk.com
*
* For the full copyright and license agreement information visit
* https://www.hesk.com/eula.php
*
* Common include for the "Create Customer / Follower" modal and its event handlers.
* Used by new_ticket.php and edit_post.php.
*
* Requires the following JS variables to already be defined on the page before
* the modal save button is clicked:
* - createCustomerSelectize (the customer selectize instance)
* - createFollowerSelectize (the follower selectize instance, when multi_eml is on)
*/
if (!defined('IN_SCRIPT')) { die('Hacking attempt!'); }
?>
<script>
var createUserEventHandler = function(userType = 'customer', event, extraData) {
/*
Generalized handling of creating new customers or followers.
1) By default clear the input fields before showing the modal,
but allow passing specific values to event and pre-fill the input fields (i.e. from Add Customer/Follower click from dropdown)
*/
let nameValue = '';
let emailValue = '';
if (extraData) {
if (typeof extraData.nameValue !== 'undefined' && typeof extraData.nameValue === 'string') {
nameValue = extraData.nameValue;
}
if (typeof extraData.emailValue !== 'undefined' && typeof extraData.emailValue === 'string') {
emailValue = extraData.emailValue;
}
}
$('[data-modal-id="create-customer"] input[name="name"]').val(nameValue);
$('[data-modal-id="create-customer"] input[name="email"]').val(emailValue);
// 2.) Update any titles and other related meta data
let createCustomerTitle = '<?php echo hesk_makeJsString($hesklang['new_customer']); ?>';
let customerType = 'CUSTOMER';
if (userType === 'customer') {
$('#new-customer-prompt').css('display', 'none');
} else if (userType === 'follower') {
createCustomerTitle = '<?php echo hesk_makeJsString($hesklang['new_follower']); ?>';
customerType = 'FOLLOWER';
}
$('#create-customer-title').text(createCustomerTitle);
$('[data-modal-id="create-customer"] input[name="customer_type"]').val(customerType);
if (extraData) {
// If extra data was passed also run validation checks - but only if anything is actually entered,
// otherwise it looks weird if errors shows up when user didn't enter anything yet.
if (nameValue !== '') {
$('#create_name').keyup();
}
if (emailValue!== '') {
$('#email').keyup();
}
}
// We also want to clear any unnecessary errors on empty fields, as it feels weird to leave them from previous modal opens.
updateValidation(nameValue === '', emailValue === '');
};
$('#new-customer-link').click(function(event, extraData = null) {
createUserEventHandler('customer', event, extraData);
});
$('#new-follower-link').click(function(event, extraData = null) {
createUserEventHandler('follower', event, extraData);
});
</script>
<div class="modal" data-modal-id="create-customer">
<div class="modal__body" style="white-space: normal; <?php if ($hesk_settings['limit_width']) echo 'max-width:'.$hesk_settings['limit_width'].'px'; ?>">
<i class="modal__close" data-action="cancel">
<svg class="icon icon-close">
<use xlink:href="<?php echo HESK_PATH; ?>img/sprite.svg#icon-close"></use>
</svg>
</i>
<h3 id="create-customer-title"><?php echo $hesklang['new_customer']; ?></h3>
<div class="modal__description">
<div id="new-customer-prompt" style="display: <?php echo (isset($show_create_modal) && $show_create_modal) ? 'block' : 'none'; ?>">
<?php echo $hesklang['new_customer_prompt']; ?>
</div>
<div class="form">
<div class="form-group">
<label for="create_name">
<?php echo $hesklang['name']; ?>: <span class="important">*</span>
</label>
<input type="text" id="create_name" name="name" class="form-control" maxlength="50">
<div class="form-control__error"></div>
</div>
<div class="form-group">
<label for="email">
<?php echo $hesklang['email'] . ':' . ($hesk_settings['require_email'] ? ' <span class="important">*</span>' : '') ; ?>
</label>
<input type="email"
class="form-control"
name="email" id="email" maxlength="1000">
<div class="form-control__error"></div>
</div>
<div id="email_suggestions" class="email-suggestion"></div>
</div>
</div>
<div class="modal__buttons">
<input type="hidden" name="customer_type" value="CUSTOMER">
<button class="btn btn-border" ripple="ripple" data-action="cancel"><?php echo $hesklang['cancel']; ?></button>
<a data-confirm-button href="#" class="btn btn-full text-white disabled" ripple="ripple" style="width: 152px; height: 40px;"><?php echo $hesklang['save']; ?></a>
</div>
<script>
var $name = $('#create_name');
var $email = $('#email');
var $saveButton = $("[data-modal-id='create-customer']").find('a[data-confirm-button]');
var nameValid = false;
var emailValid = false;
var emailFailureReason = '';
$name.keyup(function() {
updateNameValidation();
let emailIsEmpty = ($email.val().trim() === '');
<?php if (!$hesk_settings['require_email']): ?>
emailValid = true;
<?php endif; ?>
/* If other/email field is empty, ignore always showing its error,
UNLESS it was already shown (user interacted with that field since opening the modal)
*/
let clearEmailError = (!$email.parent().hasClass('error') && emailIsEmpty)
updateValidation(false, clearEmailError);
});
let fireCreateCustomerCallbackAfterEmailCheck = false;
var debouncedEmailCheck = hesk_debounce(function() {
/* If other/name field is empty, ignore always showing its error,
UNLESS it was already shown (user interacted with that field since opening the modal)
*/
let nameIsEmpty = ($name.val().trim() === '');
let emailIsEmpty = ($email.val().trim() === '');
let clearNameError = (!$name.parent().hasClass('error') && nameIsEmpty);
// If email is not required, and the email field is empty, we can just skip ajax validation for email.
// Otherwise, we always want to run ajax validation to maintain consistent UX.
<?php if (!$hesk_settings['require_email']): ?>
if (emailIsEmpty) {
emailValid = true;
updateValidation(clearNameError, false);
if (fireCreateCustomerCallbackAfterEmailCheck) {
// In this case, as no customer check happens, we have to call createCustomer callback directly
createCustomerOnValidationCallback(true);
fireCreateCustomerCallbackAfterEmailCheck = false;
}
return;
}
<?php endif; ?>
//-- Disable save button initially until email check is complete
emailValid = false;
updateValidation(clearNameError, false);
if (emailIsEmpty) {
emailFailureReason = '<?php echo hesk_makeJsString($hesklang['this_field_is_required']); ?>';
updateValidation(clearNameError, false);
if (fireCreateCustomerCallbackAfterEmailCheck) {
// Even in this case we call the callback, just with success : false.
// Reason is to ensure updateValidation logic is 100% the same as it was before the async request handling.
createCustomerOnValidationCallback(false);
fireCreateCustomerCallbackAfterEmailCheck = false;
}
return;
}
$.ajax({
url: 'ajax/check_customer.php',
type: 'GET',
data: {
email: $email.val(),
name: $name.val()
},
dataType: 'json',
success: function(data) {
if (!data.emailValid) {
emailValid = false;
emailFailureReason = '<?php echo hesk_makeJsString($hesklang['enter_valid_email']); ?>';
} else if (data.customerAvailable === 'NOT_AVAILABLE_REGISTERED') {
emailValid = false;
emailFailureReason = '<?php echo hesk_makeJsString($hesklang['customer_email_exists_already_registered']); ?>';
} else if (data.customerAvailable === 'NOT_AVAILABLE_IDENTICAL') {
emailValid = false;
emailFailureReason = '<?php echo hesk_makeJsString($hesklang['customer_name_email_exists']); ?>';
} else {
emailValid = true;
emailFailureReason = '';
<?php if ($hesk_settings['detect_typos']): ?>
hesk_suggestEmail('email', 'email_suggestions', 1, 1);
<?php endif; ?>
}
updateValidation(clearNameError, false);
if (fireCreateCustomerCallbackAfterEmailCheck) {
createCustomerOnValidationCallback(true);
fireCreateCustomerCallbackAfterEmailCheck = false;
}
},
error: function(err) {
console.error(err);
emailValid = false;
emailFailureReason = '<?php echo hesk_makeJsString($hesklang['an_error_occurred_validating_email']); ?>';
updateValidation(clearNameError, false);
if (fireCreateCustomerCallbackAfterEmailCheck) {
// Even in this case we call the callback, just with success : false.
// Reason is to ensure updateValidation logic is 100% the same as it was before the async request handling.
createCustomerOnValidationCallback(false);
fireCreateCustomerCallbackAfterEmailCheck = false;
}
}
});
}, 300);
$name.keyup(debouncedEmailCheck);
$email.keyup(debouncedEmailCheck);
$saveButton.click(function() {
// As the debounceEmail check is async, we can only call the createCustomer AFTER the email check has completed.
// While we could do it with async function it would require a bigger rework,
// so this simple flag checking & callback from debouncedEmailCheck does the trick on ensuring it works on all browsers.
fireCreateCustomerCallbackAfterEmailCheck = true;
debouncedEmailCheck();
});
function createCustomerOnValidationCallback(validationSuccessful = false) {
if (!nameValid || !emailValid || !validationSuccessful) {
//-- Fix validation state messages
updateValidation();
return;
}
$.ajax({
url: 'ajax/create_customer.php',
type: 'POST',
data: {
name: $name.val(),
email: $email.val(),
token: '<?php echo hesk_token_echo(0); ?>'
},
dataType: 'json',
success: function(data) {
<?php if ($hesk_settings['multi_eml']): ?>
var selectize = $('input[name="customer_type"]').val() === 'CUSTOMER' ?
createCustomerSelectize :
createFollowerSelectize;
createCustomerSelectize[0].selectize.addOption(data);
createFollowerSelectize[0].selectize.addOption(data);
<?php else: ?>
var selectize = createCustomerSelectize;
createCustomerSelectize[0].selectize.addOption(data);
<?php endif; ?>
if (typeof selectize[0].selectize.getValue() === 'string') {
selectize[0].selectize.setValue(data.id);
} else {
var currentCustomers = selectize[0].selectize.getValue();
currentCustomers.push(data.id);
selectize[0].selectize.setValue(currentCustomers);
}
$name.val('');
$email.val('');
$('[data-modal-id="create-customer"]').find('[data-action="cancel"]').click();
},
error: function(err) {
emailValid = false;
emailFailureReason = JSON.parse(err.responseText).message;
updateValidation();
}
});
}
function updateNameValidation() {
let nameIsEmpty = ($name.val().trim() === '');
nameValid = !nameIsEmpty;
if (nameIsEmpty) {
nameValid = false;
} else {
nameValid = true;
}
}
function updateValidation(forceClearNameError = false, forceClearEmailError = false) {
// Need to re-fire this always, as otherwise if closing popup, old nameValid=true value might persist
updateNameValidation();
var anyFailure = false;
/*
There are situations where we might delibarately clear errors for clearer user experience, even if inputs are empty on modal open,
BUT at same time keeping other validation/disabled buttons as they are.
*/
let clearNameError = forceClearNameError || nameValid;
if (!nameValid) {
anyFailure = true;
if (!forceClearNameError) {
$name.parent().addClass('error');
$name.parent().find('.form-control__error').text('<?php echo hesk_makeJsString($hesklang['this_field_is_required']); ?>');
}
}
if (clearNameError) {
$name.parent().removeClass('error');
$name.parent().find('.form-control__error').text('');
}
let clearEmailError = forceClearEmailError || emailValid;
if (!emailValid) {
anyFailure = true;
if (!forceClearEmailError && emailFailureReason !== '') {
$email.parent().addClass('error');
$email.parent().find('.form-control__error').text(emailFailureReason);
}
}
if (clearEmailError) {
$email.parent().removeClass('error');
$email.parent().find('.form-control__error').text('');
}
if (anyFailure) {
$saveButton.addClass('disabled');
} else {
$saveButton.removeClass('disabled');
}
}
</script>
</div>
</div>
wget 'https://lists2.roe3.org/hesk/inc/database.inc.php'
<?php
/**
*
* This file is part of HESK - PHP Help Desk Software.
*
* (c) Copyright Klemen Stirn. All rights reserved.
* https://www.hesk.com
*
* For the full copyright and license agreement information visit
* https://www.hesk.com/eula.php
*
*/
/* Check if this is a valid include */
if (!defined('IN_SCRIPT')) {die('Invalid attempt');}
function hesk_dbCollate()
{
global $hesklang;
// MySQL vesions prior to 5.6 don't support some collations
if ( in_array($hesklang['_COLLATE'], array('utf8_croatian_ci', 'utf8_german2_ci', 'utf8_vietnamese_ci')) )
{
if ( version_compare( hesk_dbResult( hesk_dbQuery('SELECT VERSION() AS version') ), '5.6', '<') )
{
$hesklang['_COLLATE'] = 'utf8_general_ci';
}
}
return hesk_dbEscape($hesklang['_COLLATE']);
} // END hesk_dbCollate()
function hesk_dbSetNames()
{
global $hesk_settings, $hesk_db_link;
mysql_set_charset('utf8', $hesk_db_link);
} // END hesk_dbSetNames()
function hesk_dbFormatEmail($email, $field = 'email')
{
$email = hesk_dbLike($email);
return " `".hesk_dbEscape($field)."` LIKE '".hesk_dbEscape($email)."' ";
} // END hesk_dbFormatEmail()
function hesk_dbTime()
{
$res = hesk_dbQuery("SELECT NOW()");
return strtotime(hesk_dbResult($res,0,0));
} // END hesk_dbTime()
function hesk_dbSetTimezone()
{
global $hesk_settings;
hesk_dbQuery('SET time_zone = "'.hesk_timeToHHMM(date('Z')).'"');
return true;
} // END hesk_dbSetTimezone()
function hesk_dbEscape($in)
{
global $hesk_db_link;
$in = mysql_real_escape_string(stripslashes($in), $hesk_db_link);
$in = str_replace('`','`',$in);
return $in;
} // END hesk_dbEscape()
function hesk_dbLike($in)
{
return str_replace( array('\\', '_', '%'), array('\\\\', '\\\\_', '\\\\%'), $in); // '
} // END hesk_dbLike()
function hesk_dbConnect()
{
global $hesk_settings;
global $hesk_db_link;
global $hesklang;
// Do we have an existing active link?
if ($hesk_db_link)
{
return $hesk_db_link;
}
// Is mysql supported?
if ( ! function_exists('mysql_connect') )
{
die($hesklang['emp']);
}
// Connect to the database
$hesk_db_link = @mysql_connect($hesk_settings['db_host'], $hesk_settings['db_user'], $hesk_settings['db_pass']);
// Errors?
if ( ! $hesk_db_link)
{
if ($hesk_settings['debug_mode'])
{
hesk_error("$hesklang[cant_connect_db]</p><p>$hesklang[mysql_said]:<br />".mysql_error()."</p>");
}
else
{
hesk_error("$hesklang[cant_connect_db]</p><p>$hesklang[contact_webmsater] <a href=\"mailto:$hesk_settings[webmaster_mail]\">$hesk_settings[webmaster_mail]</a></p>");
}
}
if ( ! @mysql_select_db($hesk_settings['db_name'], $hesk_db_link))
{
if ($hesk_settings['debug_mode'])
{
hesk_error("$hesklang[cant_connect_db]</p><p>$hesklang[mysql_said]:<br />".mysql_error()."</p>");
}
else
{
hesk_error("$hesklang[cant_connect_db]</p><p>$hesklang[contact_webmsater] <a href=\"mailto:$hesk_settings[webmaster_mail]\">$hesk_settings[webmaster_mail]</a></p>");
}
}
// Check MySQL/PHP version and set encoding to utf8
hesk_dbSetNames();
// Set the correct timezone
hesk_dbSetTimezone();
return $hesk_db_link;
} // END hesk_dbConnect()
function hesk_dbClose()
{
global $hesk_db_link;
return @mysql_close($hesk_db_link);
} // END hesk_dbClose()
function hesk_dbQuery($query)
{
global $hesk_last_query;
global $hesk_db_link;
global $hesklang, $hesk_settings;
if ( ! $hesk_db_link && ! hesk_dbConnect())
{
return false;
}
$hesk_last_query = $query;
#echo "<p>EXPLAIN $query</p>\n";
if ($res = @mysql_query($query, $hesk_db_link))
{
return $res;
} else {
hesk_dbHandleFailure($query);
}
} // END hesk_dbQuery()
function hesk_dbHandleFailure($query) {
global $hesk_settings, $hesklang;
$valid_response_types = array('json', 'throw');
if (!isset($hesk_settings['db_failure_response']) || !in_array($hesk_settings['db_failure_response'], $valid_response_types)) {
if ($hesk_settings['debug_mode']) {
hesk_error("$hesklang[cant_sql]: $query</p><p>$hesklang[mysql_said]:<br />".mysql_error()."</p>");
} else {
hesk_error("$hesklang[cant_sql]</p><p>$hesklang[contact_webmsater] <a href=\"mailto:$hesk_settings[webmaster_mail]\">$hesk_settings[webmaster_mail]</a></p>");
}
} elseif ($hesk_settings['db_failure_response'] === 'json') {
header('Content-Type: application/json');
http_response_code(500);
if ($hesk_settings['debug_mode']) {
print json_encode(array(
'status' => 'failure',
'title' => $hesklang['cant_sql'],
'message' => mysql_error()
));
} else {
print json_encode(array(
'status' => 'failure',
'title' => $hesklang['cant_sql'],
'message' => sprintf('%s: %s', $hesklang['contact_webmsater'], $hesk_settings['webmaster_mail'])
));
}
exit();
} elseif ($hesk_settings['db_failure_response'] === 'throw') {
$message = $hesk_settings['debug_mode'] ? mysql_error() : $hesklang['cant_sql'];
throw new Exception($message);
}
}
function hesk_dbFetchAssoc($res)
{
return @mysql_fetch_assoc($res);
} // END hesk_FetchAssoc()
function hesk_dbFetchRow($res)
{
return @mysql_fetch_row($res);
} // END hesk_FetchRow()
function hesk_dbResult($res, $row = 0, $column = 0)
{
return @mysql_result($res, $row, $column);
} // END hesk_dbResult()
function hesk_dbInsertID()
{
global $hesk_db_link;
if ($lastid = @mysql_insert_id($hesk_db_link))
{
return $lastid;
}
} // END hesk_dbInsertID()
function hesk_dbFreeResult($res)
{
return mysql_free_result($res);
} // END hesk_dbFreeResult()
function hesk_dbNumRows($res)
{
return @mysql_num_rows($res);
} // END hesk_dbNumRows()
function hesk_dbAffectedRows()
{
global $hesk_db_link;
return @mysql_affected_rows($hesk_db_link);
} // END hesk_dbAffectedRows()
wget 'https://lists2.roe3.org/hesk/inc/database_mysqli.inc.php'
<?php
/**
*
* This file is part of HESK - PHP Help Desk Software.
*
* (c) Copyright Klemen Stirn. All rights reserved.
* https://www.hesk.com
*
* For the full copyright and license agreement information visit
* https://www.hesk.com/eula.php
*
*/
/* Check if this is a valid include */
if (!defined('IN_SCRIPT')) {die('Invalid attempt');}
function hesk_dbCollate()
{
global $hesklang;
// MySQL vesions prior to 5.6 don't support some collations
if ( in_array($hesklang['_COLLATE'], array('utf8_croatian_ci', 'utf8_german2_ci', 'utf8_vietnamese_ci')) )
{
if ( version_compare( hesk_dbResult( hesk_dbQuery('SELECT VERSION() AS version') ), '5.6', '<') )
{
$hesklang['_COLLATE'] = 'utf8_general_ci';
}
}
return hesk_dbEscape($hesklang['_COLLATE']);
} // END hesk_dbCollate()
function hesk_dbSetNames()
{
global $hesk_settings, $hesk_db_link;
mysqli_set_charset($hesk_db_link, 'utf8');
} // END hesk_dbSetNames()
function hesk_dbFormatEmail($email, $field = 'email')
{
$email = hesk_dbLike($email);
return " `".hesk_dbEscape($field)."` LIKE '".hesk_dbEscape($email)."' ";
} // END hesk_dbFormatEmail()
function hesk_dbTime()
{
$res = hesk_dbQuery("SELECT NOW()");
return strtotime(hesk_dbResult($res,0,0));
} // END hesk_dbTime()
function hesk_dbSetTimezone()
{
global $hesk_settings;
hesk_dbQuery('SET time_zone = "'.hesk_timeToHHMM(date('Z')).'"');
return true;
} // END hesk_dbSetTimezone()
function hesk_dbEscape($in)
{
global $hesk_db_link;
$in = mysqli_real_escape_string($hesk_db_link, stripslashes($in));
$in = str_replace('`','`',$in);
return $in;
} // END hesk_dbEscape()
function hesk_dbLike($in)
{
return str_replace( array('\\', '_', '%'), array('\\\\', '\\\\_', '\\\\%'), $in); // '
} // END hesk_dbLike()
function hesk_dbConnect()
{
global $hesk_settings;
global $hesk_db_link;
global $hesklang;
// Do we have an existing active link?
if ($hesk_db_link)
{
return $hesk_db_link;
}
// Is mysqli supported?
if ( ! function_exists('mysqli_connect') )
{
die($hesklang['emp']);
}
// We want pre-PHP 8.1 behavior for now
mysqli_report(MYSQLI_REPORT_OFF);
// Do we need a special port? Check and connect to the database
if ( strpos($hesk_settings['db_host'], ':') )
{
list($hesk_settings['db_host_no_port'], $hesk_settings['db_port']) = explode(':', $hesk_settings['db_host']);
$hesk_db_link = @mysqli_connect($hesk_settings['db_host_no_port'], $hesk_settings['db_user'], $hesk_settings['db_pass'], $hesk_settings['db_name'], intval($hesk_settings['db_port']) );
}
else
{
$hesk_db_link = @mysqli_connect($hesk_settings['db_host'], $hesk_settings['db_user'], $hesk_settings['db_pass'], $hesk_settings['db_name']);
}
// Errors?
if ( ! $hesk_db_link)
{
if ($hesk_settings['debug_mode'])
{
hesk_error("$hesklang[cant_connect_db]</p><p>$hesklang[mysql_said]:<br />(".mysqli_connect_errno().") ".mysqli_connect_error()."</p>");
}
else
{
hesk_error("$hesklang[cant_connect_db]</p><p>$hesklang[contact_webmsater] <a href=\"mailto:$hesk_settings[webmaster_mail]\">$hesk_settings[webmaster_mail]</a></p>");
}
}
// Check MySQL/PHP version and set encoding to utf8
hesk_dbSetNames();
// Set the correct timezone
hesk_dbSetTimezone();
return $hesk_db_link;
} // END hesk_dbConnect()
function hesk_dbClose()
{
global $hesk_db_link;
return @mysqli_close($hesk_db_link);
} // END hesk_dbClose()
function hesk_dbQuery($query)
{
global $hesk_last_query;
global $hesk_db_link;
global $hesklang, $hesk_settings;
if ( ! $hesk_db_link && ! hesk_dbConnect())
{
return false;
}
$hesk_last_query = $query;
# echo "<p>EXPLAIN $query</p>\n";
if ($res = @mysqli_query($hesk_db_link, $query))
{
return $res;
} else {
hesk_dbHandleFailure($query);
}
} // END hesk_dbQuery()
function hesk_dbHandleFailure($query) {
global $hesk_settings, $hesklang, $hesk_db_link;
$valid_response_types = array('json', 'throw');
if (!isset($hesk_settings['db_failure_response']) || !in_array($hesk_settings['db_failure_response'], $valid_response_types)) {
if ($hesk_settings['debug_mode']) {
hesk_error("$hesklang[cant_sql]: $query</p><p>$hesklang[mysql_said]:<br />".mysqli_error($hesk_db_link)."</p>");
} else {
hesk_error("$hesklang[cant_sql]</p><p>$hesklang[contact_webmsater] <a href=\"mailto:$hesk_settings[webmaster_mail]\">$hesk_settings[webmaster_mail]</a></p>");
}
} elseif ($hesk_settings['db_failure_response'] === 'json') {
header('Content-Type: application/json');
http_response_code(500);
if ($hesk_settings['debug_mode']) {
print json_encode(array(
'status' => 'failure',
'title' => $hesklang['cant_sql'],
'message' => mysqli_error($hesk_db_link),
'query' => $query
));
} else {
print json_encode(array(
'status' => 'failure',
'title' => $hesklang['cant_sql'],
'message' => sprintf('%s: %s', $hesklang['contact_webmsater'], $hesk_settings['webmaster_mail'])
));
}
exit();
} elseif ($hesk_settings['db_failure_response'] === 'throw') {
$message = $hesk_settings['debug_mode'] ? mysqli_error($hesk_db_link) : $hesklang['cant_sql'];
throw new Exception($message);
}
}
function hesk_dbFetchAssoc($res)
{
return @mysqli_fetch_assoc($res);
} // END hesk_FetchAssoc()
function hesk_dbFetchRow($res)
{
return @mysqli_fetch_row($res);
} // END hesk_FetchRow()
function hesk_dbResult($res, $row = 0, $column = 0)
{
$i=0;
$res->data_seek(0);
while ($tmp = @mysqli_fetch_array($res, MYSQLI_NUM))
{
if ($i==$row)
{
return $tmp[$column];
}
$i++;
}
return '';
} // END hesk_dbResult()
function hesk_dbInsertID()
{
global $hesk_db_link;
if ($lastid = @mysqli_insert_id($hesk_db_link))
{
return $lastid;
}
} // END hesk_dbInsertID()
function hesk_dbFreeResult($res)
{
return @mysqli_free_result($res);
} // END hesk_dbFreeResult()
function hesk_dbNumRows($res)
{
return @mysqli_num_rows($res);
} // END hesk_dbNumRows()
function hesk_dbAffectedRows()
{
global $hesk_db_link;
return @mysqli_affected_rows($hesk_db_link);
} // END hesk_dbAffectedRows()
wget 'https://lists2.roe3.org/hesk/inc/email_functions.inc.php'
<?php
/**
*
* This file is part of HESK - PHP Help Desk Software.
*
* (c) Copyright Klemen Stirn. All rights reserved.
* https://www.hesk.com
*
* For the full copyright and license agreement information visit
* https://www.hesk.com/eula.php
*
*/
/* Check if this is a valid include */
if (!defined('IN_SCRIPT')) {
die('Invalid attempt');
}
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
use PHPMailer\PHPMailer\SMTP;
// Load required includes if not already
require_once(HESK_PATH . 'inc/customer_accounts.inc.php');
require_once(HESK_PATH . 'inc/custom_fields.inc.php');
require_once(HESK_PATH . 'inc/statuses.inc.php');
require_once(HESK_PATH . 'inc/priorities.inc.php');
function hesk_notifyCustomer($email_template = 'new_ticket')
{
global $hesk_settings, $hesklang, $ticket;
// Demo mode
if (defined('HESK_DEMO')) {
return true;
}
// We don't need to attach any original ticket files when marking as "Resolved" without replying
if ($email_template == 'ticket_closed') {
$ticket['attachments'] = '';
}
$ticket['email_original'] = $ticket['email'];
$hesk_settings['EMAIL_IDS'] = array();
$customers = hesk_get_customers_for_ticket($ticket['id']);
$ticket['customers'] = $customers;
$language_to_customers = [];
foreach ($customers as $customer) {
if ($customer['email'] === null || $customer['email'] === '') {
continue;
}
// Make sure customer gets response in correct language
$language = HESK_DEFAULT_LANGUAGE;
if (isset($customer['language'])) {
$language = $customer['language'];
} elseif (isset($ticket['language'])) {
$language = $ticket['language'];
}
if (!isset($language)) {
$language_to_customers[$language] = [];
}
$language_to_customers[$language][] = $customer;
}
foreach ($language_to_customers as $language => $customers) {
hesk_setLanguage($language);
$subject = hesk_getEmailSubject($email_template, $ticket);
$customer_emails = hesk_getEmailsForCustomers($customers);
// Customers will have to login to reply, no need to complicate
if ($hesk_settings['customer_accounts_required'] && $hesk_settings['customer_accounts']) {
list($message, $html_message, $mail_direct_attachment) = hesk_getEmailMessage($email_template, $ticket);
hesk_mail($customer_emails['requester'], $customer_emails['followers'], $subject, $message, $html_message, $ticket['trackid'], $mail_direct_attachment);
} else {
// Customers do not have to log in to reply.
// To make sure the correct replier is used, send each customer an email with a unique ticket tracking URL address with their own email address
$ticket['email'] = $customer_emails['requester'];
list($message, $html_message, $mail_direct_attachment) = hesk_getEmailMessage($email_template, $ticket);
hesk_mail($customer_emails['requester'], array(), $subject, $message, $html_message, $ticket['trackid'], $mail_direct_attachment);
foreach ($customer_emails['followers'] as $email) {
$ticket['email'] = $email;
list($message, $html_message, $mail_direct_attachment) = hesk_getEmailMessage($email_template, $ticket);
hesk_mail($email, array(), $subject, $message, $html_message, $ticket['trackid'], $mail_direct_attachment);
}
}
// Reset language if needed
hesk_resetLanguage();
}
$ticket['email'] = $ticket['email_original'];
if (count($hesk_settings['EMAIL_IDS'])) {
$sql_values = array();
foreach ($hesk_settings['EMAIL_IDS'] as $eid) {
$sql_values[] = "('".hesk_dbEscape($eid)."', ".$ticket['id'].", 1)";
}
hesk_dbQuery("INSERT INTO `".hesk_dbEscape($hesk_settings['db_pfix'])."email_id_to_ticket` (`email_id`, `ticket_id`, `from_hesk`) VALUES " . implode(', ', $sql_values));
}
unset($hesk_settings['EMAIL_IDS']);
return true;
} // END hesk_notifyCustomer()
function hesk_getEmailsForCustomers($customers) {
$requester = null;
$followers = [];
foreach ($customers as $customer) {
if ($customer['customer_type'] === 'REQUESTER') {
$requester = $customer['email'];
} else {
$followers[] = $customer['email'];
}
}
return [
'requester' => $requester,
'followers' => $followers
];
}
function hesk_notifyCollaborators($collaborator_ids, $email_template, $type = 'notify_collaborator_customer_reply', $exclude_users = array())
{
global $hesk_settings, $hesklang, $ticket;
// Demo mode
if (defined('HESK_DEMO')) {
return true;
}
if (count($exclude_users)) {
foreach ($collaborator_ids as $k => $v) {
if (in_array($v, $exclude_users)) {
unset($collaborator_ids[$k]);
}
}
}
if (count($collaborator_ids) == 0) {
return true;
}
$admins = array();
$res = hesk_dbQuery("SELECT * FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "users` WHERE `active` = 1 AND `id` IN (".implode(',', $collaborator_ids).") ORDER BY `language`");
while ($user = hesk_dbFetchAssoc($res)) {
if (empty($user[$type])) {
continue;
}
$admins[] = $user;
}
if (count($admins) > 0) {
/* Make sure each user gets email in his/her preferred language */
$current_language = 'NONE';
$recipients = array();
/* Loop through staff */
foreach ($admins as $admin) {
/* If admin language is NULL force default HESK language */
if (!$admin['language'] || !isset($hesk_settings['languages'][$admin['language']])) {
$admin['language'] = HESK_DEFAULT_LANGUAGE;
}
/* Generate message or add email to the list of recepients */
if ($admin['language'] == $current_language) {
/* We already have the message, just add email to the recipients list */
$recipients[] = $admin['email'];
} else {
/* Send email messages in previous languages (if required) */
if ($current_language != 'NONE') {
/* Send e-mail to staff */
hesk_mail(implode(',', $recipients), [], $subject, $message, $html_message);
/* Reset list of email addresses */
$recipients = array();
}
/* Set new language */
hesk_setLanguage($admin['language']);
/* Format staff email subject and message for this language */
$subject = hesk_getEmailSubject($email_template, $ticket);
list($message, $html_message, $mail_direct_attachment) = hesk_getEmailMessage($email_template, $ticket, 1);
/* Add email to the recipients list */
$recipients[] = $admin['email'];
/* Remember the last processed language */
$current_language = $admin['language'];
}
}
/* Send email messages to the remaining staff */
hesk_mail(implode(',', $recipients), [], $subject, $message, $html_message, $ticket['trackid'], $mail_direct_attachment);
/* Reset language to original one */
hesk_resetLanguage();
}
return true;
} // END hesk_notifyCollaborators()
function hesk_notifyAssignedStaff($autoassign_owner, $email_template, $type = 'notify_assigned', $type_collaborators = false, $exclude_users = array())
{
global $hesk_settings, $hesklang, $ticket;
// Demo mode
if (defined('HESK_DEMO')) {
return true;
}
$ticket['owner'] = intval($ticket['owner']);
// This will be list of staff we need to lookup from the DB
$lookup = array();
// This will be staff that we need to notify
$admins = array();
if ($autoassign_owner === false) {
$lookup[] = $ticket['owner'];
} else {
$admins[] = $autoassign_owner;
$hesk_settings['user_data'][$ticket['owner']] = $autoassign_owner;
}
if ($type_collaborators !== false && count($ticket['collaborators'])) {
$lookup = array_merge($lookup, $ticket['collaborators']);
}
$lookup = array_unique($lookup);
if (count($exclude_users)) {
foreach ($lookup as $k => $v) {
if (in_array($v, $exclude_users)) {
unset($lookup[$k]);
}
}
}
// print_r($lookup);
// Get user info from the DB if we need it
if (count($lookup)) {
$res = hesk_dbQuery("SELECT * FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "users` WHERE `active` = 1 AND `id` IN (".implode(',', $lookup).") ORDER BY `language`");
while ($user = hesk_dbFetchAssoc($res)) {
$hesk_settings['user_data'][$user['id']] = $user;
// Owner, but doesn't want to be notified
if ($user['id'] == $ticket['owner'] && empty($user[$type])) {
continue;
}
// Collaborator, but doesn't want to be notified
if ($user['id'] != $ticket['owner'] && $type_collaborators !== false && empty($user[$type_collaborators])) {
continue;
}
// Wants to be notified
$admins[] = $user;
}
}
if (count($exclude_users)) {
foreach ($admins as $k => $v) {
if (in_array($v, $exclude_users)) {
unset($admins[$k]);
}
}
}
// print_r($admins);
// We have staff to notify; make sure they get emails in ther preferred langauge
if (count($admins) > 0) {
$to = array();
$cc = array();
$current_language = 'NONE';
foreach ($admins as $admin) {
// If admin language is NULL force default HESK language
if (!$admin['language'] || !isset($hesk_settings['languages'][$admin['language']])) {
$admin['language'] = HESK_DEFAULT_LANGUAGE;
}
// Generate message or add email to the list of recepients
if ($admin['language'] == $current_language) {
// We already have the message, just add email to the recipients list
// Owner will be "To", Collaborators in "Cc"
if ($admin['id'] == $ticket['owner']) {
$to[] = $admin['email'];
} else {
$cc[] = $admin['email'];
}
} else {
// Send email messages in previous languages (if required)
if ($current_language != 'NONE') {
hesk_mail(implode(',', $to), $cc, $subject, $message, $html_message);
// Reset recipients
$to = array();
$cc = array();
}
// Set new language
hesk_setLanguage($admin['language']);
// Format staff email subject and message for this language
$subject = hesk_getEmailSubject($email_template, $ticket);
list($message, $html_message, $mail_direct_attachment) = hesk_getEmailMessage($email_template, $ticket, 1);
// Add email to the recipients list
if ($admin['id'] == $ticket['owner']) {
$to[] = $admin['email'];
} else {
$cc[] = $admin['email'];
}
// Remember the last processed language
$current_language = $admin['language'];
}
}
// Send email messages to the remaining staff
hesk_mail(implode(',', $to), $cc, $subject, $message, $html_message, $ticket['trackid'], $mail_direct_attachment);
// Reset language to original one
hesk_resetLanguage();
}
return true;
} // END hesk_notifyAssignedStaff()
function hesk_notifyStaff($email_template, $sql_where, $is_ticket = 1, $exclude_users = array())
{
global $hesk_settings, $hesklang, $ticket;
// Demo mode
if (defined('HESK_DEMO')) {
return true;
}
$admins = array();
$res = hesk_dbQuery("SELECT `id`,`email`,`language`,`isadmin`,`categories` FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "users` WHERE `active` = 1 AND ( $sql_where ) ORDER BY `language`");
while ($myuser = hesk_dbFetchAssoc($res)) {
/* Is this an administrator? */
if ($myuser['isadmin']) {
$admins[$myuser['id']] = array('email' => $myuser['email'], 'language' => $myuser['language']);
continue;
}
/* Not admin, is he/she allowed this category? */
if ( ! function_exists('hesk_getCategoriesForUser')) {
require(HESK_PATH . 'inc/admin_functions.inc.php');
}
$myuser['categories'] = hesk_getCategoriesForUser($myuser['id']);
if (in_array($ticket['category'], $myuser['categories'])) {
$admins[$myuser['id']] = array('email' => $myuser['email'], 'language' => $myuser['language']);
continue;
}
}
if (count($exclude_users)) {
foreach ($admins as $k => $v) {
if (in_array($k, $exclude_users)) {
unset($admins[$k]);
}
}
}
if (count($admins) > 0) {
/* Make sure each user gets email in his/her preferred language */
$current_language = 'NONE';
$recipients = array();
/* Loop through staff */
foreach ($admins as $admin) {
/* If admin language is NULL force default HESK language */
if (!$admin['language'] || !isset($hesk_settings['languages'][$admin['language']])) {
$admin['language'] = HESK_DEFAULT_LANGUAGE;
}
/* Generate message or add email to the list of recepients */
if ($admin['language'] == $current_language) {
/* We already have the message, just add email to the recipients list */
$recipients[] = $admin['email'];
} else {
/* Send email messages in previous languages (if required) */
if ($current_language != 'NONE') {
/* Send e-mail to staff */
hesk_mail(implode(',', $recipients), [], $subject, $message, $html_message);
/* Reset list of email addresses */
$recipients = array();
}
/* Set new language */
hesk_setLanguage($admin['language']);
/* Format staff email subject and message for this language */
$subject = hesk_getEmailSubject($email_template, $ticket);
list($message, $html_message, $mail_direct_attachment) = hesk_getEmailMessage($email_template, $ticket, $is_ticket);
/* Add email to the recipients list */
$recipients[] = $admin['email'];
/* Remember the last processed language */
$current_language = $admin['language'];
}
}
/* Send email messages to the remaining staff */
hesk_mail(implode(',', $recipients), [], $subject, $message, $html_message, $ticket['trackid'], $mail_direct_attachment);
/* Reset language to original one */
hesk_resetLanguage();
}
return true;
} // END hesk_notifyStaff()
function hesk_notifyStaffOfPendingApprovals($num)
{
global $hesk_settings, $hesklang, $ticket;
// Demo mode
if (defined('HESK_DEMO')) {
return true;
}
$admins = array();
$res = hesk_dbQuery("SELECT `email`,`language` FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "users` WHERE `active` = 1 AND (`notify_customer_approval` = '1' AND (`isadmin` = '1' OR `heskprivileges` LIKE '%can_man_customers%')) ORDER BY `language`");
while ($myuser = hesk_dbFetchAssoc($res)) {
$admins[] = array('email' => $myuser['email'], 'language' => $myuser['language']);
}
if (count($admins) == 0) {
return true;
}
$email_template = 'new_customer_approval';
$verification_url = $hesk_settings['hesk_url'] . '/' . $hesk_settings['admin_dir'] . '/manage_customers.php';
/* Make sure each user gets email in his/her preferred language */
$current_language = 'NONE';
$recipients = array();
/* Loop through staff */
foreach ($admins as $admin) {
/* If admin language is NULL force default HESK language */
if (!$admin['language'] || !isset($hesk_settings['languages'][$admin['language']])) {
$admin['language'] = HESK_DEFAULT_LANGUAGE;
}
/* Generate message or add email to the list of recepients */
if ($admin['language'] == $current_language) {
/* We already have the message, just add email to the recipients list */
$recipients[] = $admin['email'];
} else {
/* Send email messages in previous languages (if required) */
if ($current_language != 'NONE') {
/* Send e-mail to staff */
hesk_mail(implode(',', $recipients), [], $subject, $message, $html_message);
/* Reset list of email addresses */
$recipients = array();
}
/* Set new language */
hesk_setLanguage($admin['language']);
// Format email subject and message
$subject = hesk_getEmailSubject($email_template, '', 0);
list($message, $html_message) = hesk_getEmailMessage($email_template, $admin, 0, 0, 1);
// Replace message special tags
list($message, $html_message) = hesk_replace_email_tag('%%SITE_TITLE%%', hesk_msgToPlain($hesk_settings['site_title'], 1, 0), $message, $html_message);
list($message, $html_message) = hesk_replace_email_tag('%%SITE_URL%%', $hesk_settings['site_url'] . ' ', $message, $html_message);
list($message, $html_message) = hesk_replace_email_tag('%%VERIFICATION_URL%%', $verification_url, $message, $html_message);
list($message, $html_message) = hesk_replace_email_tag('%%NUM%%', $num, $message, $html_message);
/* Add email to the recipients list */
$recipients[] = $admin['email'];
/* Remember the last processed language */
$current_language = $admin['language'];
}
}
/* Send email messages to the remaining staff */
hesk_mail(implode(',', $recipients), [], $subject, $message, $html_message);
/* Reset language to original one */
hesk_resetLanguage();
return true;
} // END hesk_notifyStaffOfPendingApprovals()
function hesk_sendOverdueTicketReminder($ticket, $users)
{
if (defined('HESK_DEMO')) {
return true;
}
// --> If ticket is assigned, notify the owner plus collaborators
if ($ticket['owner']) {
hesk_notifyAssignedStaff(false, 'overdue_ticket', 'notify_overdue_my', 'notify_collaborator_overdue');
}
// --> No owner assigned, find and notify appropriate staff, including collaborators
elseif ($ticket['collaborators']) {
hesk_notifyStaff('overdue_ticket',"`notify_overdue_my`='1' OR (`notify_collaborator_overdue`='1' AND `id` IN (".implode(",", $ticket['collaborators'])."))");
}
// --> No owner assigned, find and notify appropriate staff, no collaborators
else {
hesk_notifyStaff('overdue_ticket',"`notify_overdue_my`='1'");
}
return true;
}
function hesk_sendCustomerRegistrationEmail($user, $verification_token, $email_template = 'customer_verify_registration') {
global $hesklang, $hesk_settings;
if (defined('HESK_DEMO')) {
return true;
}
hesk_setLanguage($user['language']);
// Format email subject and message
$subject = hesk_getEmailSubject($email_template, '', 0);
list($message, $html_message) = hesk_getEmailMessage($email_template,
$user,
0,
0,
1);
// Replace message special tags
$verification_url = $hesk_settings['hesk_url'] . '/verify_registration.php?email='.urlencode($user['email']).'&verificationToken='.urlencode($verification_token);
list($message, $html_message) = hesk_replace_email_tag('%%NAME%%', hesk_full_name_to_first_name(hesk_msgToPlain($user['name'], 1, 1)), $message, $html_message);
list($message, $html_message) = hesk_replace_email_tag('%%SITE_TITLE%%', hesk_msgToPlain($hesk_settings['site_title'], 1, 0), $message, $html_message);
list($message, $html_message) = hesk_replace_email_tag('%%SITE_URL%%', $hesk_settings['site_url'] . ' ', $message, $html_message);
list($message, $html_message) = hesk_replace_email_tag('%%VERIFICATION_URL%%', $verification_url, $message, $html_message);
// Send email
hesk_mail($user['email'], [], $subject, $message, $html_message);
// Reset language if needed
hesk_resetLanguage();
}
function hesk_sendCustomerRegistrationApprovedEmail($user) {
global $hesklang, $hesk_settings;
if (defined('HESK_DEMO')) {
return true;
}
hesk_setLanguage($user['language']);
// Format email subject and message
$subject = hesk_getEmailSubject('customer_approved', '', 0);
list($message, $html_message) = hesk_getEmailMessage('customer_approved',
$user,
0,
0,
1);
// Replace message special tags
list($message, $html_message) = hesk_replace_email_tag('%%NAME%%', hesk_full_name_to_first_name(hesk_msgToPlain($user['name'], 1, 1)), $message, $html_message);
list($message, $html_message) = hesk_replace_email_tag('%%SITE_TITLE%%', hesk_msgToPlain($hesk_settings['site_title'], 1, 0), $message, $html_message);
list($message, $html_message) = hesk_replace_email_tag('%%SITE_URL%%', $hesk_settings['site_url'] . ' ', $message, $html_message);
list($message, $html_message) = hesk_replace_email_tag('%%CUSTOMER_LOGIN_URL%%', $hesk_settings['hesk_url'] . '/login.php', $message, $html_message);
// Send email
hesk_mail($user['email'], [], $subject, $message, $html_message);
// Reset language if needed
hesk_resetLanguage();
}
function hesk_sendCustomerRegistrationRejectedEmail($user) {
global $hesklang, $hesk_settings;
if (defined('HESK_DEMO')) {
return true;
}
hesk_setLanguage($user['language']);
// Format email subject and message
$subject = hesk_getEmailSubject('customer_rejected', '', 0);
list($message, $html_message) = hesk_getEmailMessage('customer_rejected',
$user,
0,
0,
1);
// Replace message special tags
list($message, $html_message) = hesk_replace_email_tag('%%NAME%%', hesk_full_name_to_first_name(hesk_msgToPlain($user['name'], 1, 1)), $message, $html_message);
list($message, $html_message) = hesk_replace_email_tag('%%SITE_TITLE%%', hesk_msgToPlain($hesk_settings['site_title'], 1, 0), $message, $html_message);
list($message, $html_message) = hesk_replace_email_tag('%%SITE_URL%%', $hesk_settings['site_url'] . ' ', $message, $html_message);
// Send email
hesk_mail($user['email'], [], $subject, $message, $html_message);
// Reset language if needed
hesk_resetLanguage();
}
function hesk_sendCustomerTicket2EmailFailure($email_info, $template) {
global $hesklang, $hesk_settings;
if (defined('HESK_DEMO')) {
return true;
}
// Format email subject and message
$subject = hesk_getEmailSubject($template, '', 0);
list($message, $html_message) = hesk_getEmailMessage($template, null, 0, 0, 1);
// Replace message special tags
list($message, $html_message) = hesk_replace_email_tag('%%NAME%%', hesk_full_name_to_first_name(hesk_msgToPlain($email_info['name'], 1, 1)), $message, $html_message);
list($message, $html_message) = hesk_replace_email_tag('%%SUBJECT%%', hesk_msgToPlain($email_info['subject'], 1, 1), $message, $html_message);
list($message, $html_message) = hesk_replace_email_tag('%%CUSTOMER_REGISTER_URL%%', $hesk_settings['hesk_url'] . '/register.php', $message, $html_message);
list($message, $html_message) = hesk_replace_email_tag('%%SITE_TITLE%%', hesk_msgToPlain($hesk_settings['site_title'], 1, 0), $message, $html_message);
list($message, $html_message) = hesk_replace_email_tag('%%SITE_URL%%', $hesk_settings['site_url'] . ' ', $message, $html_message);
// Send email
hesk_mail($email_info['email'], [], $subject, $message, $html_message);
// Reset language if needed
hesk_resetLanguage();
}
function hesk_getCustomerEmailFilenames()
{
return [
'forgot_ticket_id',
'new_reply_by_staff',
'new_ticket',
'new_ticket_by_staff',
'ticket_closed',
'survey',
'customer_reset_password',
'customer_verify_registration',
'customer_verify_new_email',
'customer_approved',
'customer_rejected',
'email_rejected_can_self_register',
'email_rejected_cannot_self_register'
];
} // END hesk_getCustomerEmails()
function hesk_validEmails()
{
global $hesklang;
return array(
/*** Emails sent to CLIENT ***/
// --> Send reminder about existing tickets
'forgot_ticket_id' => $hesklang['forgot_ticket_id'],
// --> Staff replied to a ticket
'new_reply_by_staff' => $hesklang['new_reply_by_staff'],
// --> New ticket submitted
'new_ticket' => $hesklang['ticket_received'],
// --> New ticket submitted by staff
'new_ticket_by_staff' => $hesklang['new_ticket_by_staff'],
// --> Ticket closed
'ticket_closed' => $hesklang['ticket_closed'],
// --> Follow-up survey email
'survey' => $hesklang['follow_up_email'],
// --> Customer password reset email
'customer_reset_password' => $hesklang['customer_reset_password'],
// --> Customer Registration email
'customer_verify_registration' => $hesklang['customer_verify_registration'],
// --> Customer change email
'customer_verify_new_email' => $hesklang['customer_verify_new_email'],
// --> Customer registration approved
'customer_approved' => $hesklang['customer_approved'],
// --> Customer registration rejected
'customer_rejected' => $hesklang['customer_rejected'],
// --> Email-to-ticket rejection emails
'email_rejected_can_self_register' => $hesklang['email_rejected'],
'email_rejected_cannot_self_register' => $hesklang['email_rejected'],
/*** Emails sent to STAFF ***/
// --> Ticket moved to a new category
'category_moved' => $hesklang['category_moved'],
// --> Client replied to a ticket
'new_reply_by_customer' => $hesklang['new_reply_by_customer'],
// --> New ticket submitted
'new_ticket_staff' => $hesklang['new_ticket_staff'],
// --> New ticket assigned to staff
'ticket_assigned_to_you' => $hesklang['ticket_assigned_to_you'],
// --> New private message
'new_pm' => $hesklang['new_pm'],
// --> New note by someone to a ticket assigned to you
'new_note' => $hesklang['new_note'],
// --> Staff password reset email
'reset_password' => $hesklang['reset_password'],
// --> Overdue ticket email
'overdue_ticket' => $hesklang['overdue_ticket'],
// --> Staff notification of escalated ticket
'ticket_escalated' => $hesklang['ticket_escalated'],
// --> Email notifying of new customer accounts pending approval
'new_customer_approval' => $hesklang['new_customer_approval'],
// --> Added as a collaborator
'collaborator_added' => $hesklang['collaborator_added'],
// --> Staff replied to a collaborator ticket
'collaborator_staff_reply' => $hesklang['collaborator_staff_reply'],
// --> New note in a collaborator ticket
'collaborator_note' => $hesklang['collaborator_note'],
// --> A collaborator ticket is resolved
'collaborator_resolved' => $hesklang['collaborator_resolved'],
// --> A collaborator ticket is overdue
'collaborator_overdue' => $hesklang['collaborator_overdue'],
/*** Emails sent to STAFF or CUSTOMERS ***/
// --> MFA Verification email
'mfa_verification' => $hesklang['mfa_verification']
);
} // END hesk_validEmails()
function hesk_mail($to, $cc, $subject, $message, $html_message, $tracking_ID = null, $mail_direct_attachment = [])
{
global $hesk_settings, $hesklang;
// Demo mode
if (defined('HESK_DEMO')) {
return true;
}
// usleep(100);
// Let's check our recipients
if (empty($to)) {
if (empty($cc)) {
// No recipients at all
return true;
} else {
// If we don't have a To, let's use the first Cc as To; spam filters don't like empty To headers.
$to = array_shift($cc);
}
}
// Empty CCs?
if ($cc === null) {
$cc = [];
}
// Stop if we find anything suspicious in the headers
$ccstring = implode('',$cc);
if (preg_match("/\n|\r|\t|%0A|%0D|%08|%09/", $to . $ccstring . $subject)) {
return false;
}
// Encode subject to UTF-8
$subject = hesk_html_entity_decode($subject);
// Setup "name <email>" for headers
if ($hesk_settings['noreply_name']) {
$hesk_settings['from_name'] = $hesk_settings['noreply_name'];
} else {
$hesk_settings['from_name'] = $hesk_settings['noreply_mail'];
}
// Uncomment for debugging
# echo "<p>TO: $to<br >SUBJECT: $subject<br >MSG: $message</p>";
# return true;
// Remove duplicate recipients
if ($to !== null && $to !== '') {
$to_arr = array_unique(explode(',', $to));
$to_arr = array_values($to_arr);
} else {
$to_arr = [];
}
$cc_arr = array_unique($cc);
// Lowercase all emails
$to_arr = array_map('strtolower', $to_arr);
$cc_arr = array_map('strtolower', $cc_arr);
// Remove muted emails
$muted = hesk_get_muted_emails();
if (count($muted['emails'])) {
$to_arr = array_diff($to_arr, $muted['emails']);
$cc_arr = array_diff($cc_arr, $muted['emails']);
}
if (count($muted['domains'])) {
$to_arr_copy = $to_arr;
$to_arr = [];
foreach ($to_arr_copy as $to) {
$is_muted = false;
foreach ($muted['domains'] as $domain) {
if (hesk_str_ends_with($to, $domain)) {
$is_muted = true;
break;
}
}
if ($is_muted == false) {
$to_arr[] = $to;
}
}
$cc_arr_copy = $cc_arr;
$cc_arr = [];
foreach ($cc_arr_copy as $to) {
$is_muted = false;
foreach ($muted['domains'] as $domain) {
if (hesk_str_ends_with($to, $domain)) {
$is_muted = true;
break;
}
}
if ($is_muted == false) {
$cc_arr[] = $to;
}
}
}
// Let's check our recipients again after muted check
if (empty($to_arr)) {
if (empty($cc_arr)) {
return true;
} else {
$to_arr[] = array_shift($cc_arr);
}
}
// Check the number of email recipients
if ($hesk_settings['email_max_recipients']) {
$to_num = count($to_arr);
if ($to_num >= $hesk_settings['email_max_recipients']) {
$to_arr = array_splice($to_arr, 0, $hesk_settings['email_max_recipients']);
$cc_arr = [];
} elseif (($to_num + count($cc_arr)) > $hesk_settings['email_max_recipients']) {
$cc_arr = array_splice($cc_arr, 0, $hesk_settings['email_max_recipients'] - $to_num);
}
}
// Start output buffering so that any errors don't break headers
ob_start();
try {
$mailer = new PHPMailer(true);
$mailer->XMailer = ' ';
if ($hesk_settings['smtp']) {
$mailer->SMTPDebug = SMTP::DEBUG_SERVER;
$mailer->isSMTP();
$mailer->Host = $hesk_settings['smtp_host_name'];
$mailer->Port = $hesk_settings['smtp_host_port'];
if (strlen($hesk_settings['smtp_user']) || strlen($hesk_settings['smtp_password']) || $hesk_settings['smtp_oauth_provider']) {
$mailer->SMTPAuth = true;
$mailer->Username = $hesk_settings['smtp_user'];
if ($hesk_settings['smtp_conn_type'] == 'oauth') {
require_once(HESK_PATH . 'inc/oauth_functions.inc.php');
require_once(HESK_PATH . 'inc/mail/HeskOAuthTokenProvider.php');
$oauthTokenProvider = new \PHPMailer\PHPMailer\HeskOAuthTokenProvider();
$oauthTokenProvider->username = $hesk_settings['smtp_user'];
$oauthTokenProvider->provider = $hesk_settings['smtp_oauth_provider'];
$mailer->AuthType = 'XOAUTH2';
$mailer->setOAuth($oauthTokenProvider);
} else {
$mailer->Password = hesk_htmlspecialchars_decode($hesk_settings['smtp_password']);
}
}
$mailer->Timeout = $hesk_settings['smtp_timeout'];
if ($hesk_settings['smtp_noval_cert']) {
$mailer->SMTPOptions = array(
'ssl' => array(
'verify_peer' => false,
'verify_peer_name' => false,
'allow_self_signed' => true
)
);
}
if ($hesk_settings['smtp_enc'] == 'ssl') {
$mailer->SMTPSecure = PHPMailer::ENCRYPTION_SMTPS;
} elseif ($hesk_settings['smtp_enc'] == 'tls') {
$mailer->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;
}
}
$mailer->setFrom($hesk_settings['noreply_mail'], $hesk_settings['noreply_name']);
$mailer->addReplyTo($hesk_settings['noreply_mail'], $hesk_settings['noreply_name']);
foreach ($to_arr as $to) {
$mailer->addAddress($to);
}
foreach ($cc_arr as $address) {
$mailer->addCC($address);
}
$mailer->Subject = $subject;
$mailer->CharSet = $hesklang['ENCODING'];
// Save ticket ID in a custom header
if ($tracking_ID !== null) {
$mailer->addCustomHeader('X-Hesk-Tracking_ID', $tracking_ID);
}
// Do we auto-generate the AltBody from the HTML template?
if ($hesk_settings['email_formatting'] == 2) {
$mailer->msgHTML($html_message);
} else {
// HTML email?
if ($hesk_settings['email_formatting']) {
$mailer->isHTML();
}
// Body holds plaintext if we're not sending HTML
$mailer->Body = $hesk_settings['email_formatting'] ?
$html_message :
$message;
// Only include plain text in Alt if both HTML and plain text are being sent
if ($hesk_settings['email_formatting'] == 3) {
$mailer->AltBody = $message;
}
}
// Attachments
if(!empty($mail_direct_attachment)){
foreach ($mail_direct_attachment as $a => $b) {
if (file_exists($b)) {
$mailer->addAttachment($b); //Put real path of attachments
}
}
}
} catch (Exception $e) {
if ($hesk_settings['debug_mode']) {
$error = $hesklang['cnsm'] . ' ' . $to . '<br /><br />' . $hesklang['error'] . ': ' . htmlspecialchars($mailer->ErrorInfo);
if ($debug_log = ob_get_contents()) {
$error .= '<br /><br /><textarea name="smtp_log" rows="10" cols="60">' . $debug_log . '</textarea>';
}
$_SESSION['HESK_2ND_NOTICE'] = true;
$_SESSION['HESK_2ND_MESSAGE'] = $hesklang['esf'] . ' ' . $error;
} else {
$_SESSION['HESK_2ND_NOTICE'] = true;
$_SESSION['HESK_2ND_MESSAGE'] = $hesklang['esf'] . ' ' . $hesklang['contact_webmsater'] . ' <a href="mailto:' . $hesk_settings['webmaster_mail'] . '">' . $hesk_settings['webmaster_mail'] . '</a>';
}
ob_end_clean();
return false;
}
try {
ob_start();
$mailer->send();
if (isset($hesk_settings['EMAIL_IDS'])) {
$hesk_settings['EMAIL_IDS'][] = $mailer->getLastMessageID();
}
ob_end_clean();
} catch (Exception $e) {
if ($hesk_settings['debug_mode']) {
$error = $hesklang['cnsm'] . ' ' . $to . '<br /><br />' . $hesklang['error'] . ': ' . htmlspecialchars($mailer->ErrorInfo);
if ($debug_log = ob_get_contents()) {
$error .= '<br /><br /><textarea name="smtp_log" rows="10" cols="60">' . $debug_log . '</textarea>';
}
$_SESSION['HESK_2ND_NOTICE'] = true;
$_SESSION['HESK_2ND_MESSAGE'] = $hesklang['esf'] . ' ' . $error;
} else {
$_SESSION['HESK_2ND_NOTICE'] = true;
$_SESSION['HESK_2ND_MESSAGE'] = $hesklang['esf'] . ' ' . $hesklang['contact_webmsater'] . ' <a href="mailto:' . $hesk_settings['webmaster_mail'] . '">' . $hesk_settings['webmaster_mail'] . '</a>';
}
ob_end_clean();
return false;
}
ob_end_clean();
return true;
} // END hesk_mail()
function hesk_getEmailSubject($eml_file, $ticket = '', $is_ticket = 1, $strip = 0)
{
global $hesk_settings, $hesklang;
// Demo mode
if (defined('HESK_DEMO')) {
return '';
}
/* Get list of valid emails */
$valid_emails = hesk_validEmails();
/* Verify this is a valid email include */
if (!isset($valid_emails[$eml_file])) {
hesk_error($hesklang['inve']);
} else {
$msg = $valid_emails[$eml_file];
}
/* If not a ticket-related email return subject as is */
if (!$ticket) {
return $msg;
}
/* Strip slashes from the subject only if it's a new ticket */
if ($strip) {
$ticket['subject'] = stripslashes($ticket['subject']);
}
/* Not a ticket, but has some info in the $ticket array */
if (!$is_ticket) {
return str_replace('%%SUBJECT%%', $ticket['subject'], $msg);
}
/* Set category title */
$ticket['category'] = hesk_msgToPlain(hesk_getCategoryName($ticket['category']), 1, 0);
/* Get priority */
$ticket['priority'] = hesk_get_priority_name($ticket['priority']);
/* Set status */
$ticket['status'] = hesk_get_status_name($ticket['status']);
// Convert any entities in site title to plain text
$site_title = hesk_msgToPlain($hesk_settings['site_title'], 1, 0);
/* Replace all special tags */
$msg = str_replace('%%SITE_TITLE%%', $site_title, $msg);
$msg = str_replace('%%SUBJECT%%', $ticket['subject'], $msg);
$msg = str_replace('%%TRACK_ID%%', $ticket['trackid'], $msg);
$msg = str_replace('%%CATEGORY%%', $ticket['category'], $msg);
$msg = str_replace('%%PRIORITY%%', $ticket['priority'], $msg);
$msg = str_replace('%%STATUS%%', $ticket['status'], $msg);
return $msg;
} // hesk_getEmailSubject()
function hesk_getEmailMessage($eml_file, $ticket, $is_admin = 0, $is_ticket = 1, $just_message = 0)
{
global $hesk_settings, $hesklang;
// Demo mode
if (defined('HESK_DEMO')) {
return '';
}
/* Get list of valid emails */
$valid_emails = hesk_validEmails();
/* Verify this is a valid email include */
if (!isset($valid_emails[$eml_file])) {
hesk_error($hesklang['inve']);
}
/* Get email template */
$orig_eml_file = $eml_file;
$eml_file = 'language/' . $hesk_settings['languages'][$hesk_settings['language']]['folder'] . '/emails/' . $orig_eml_file . '.txt';
$html_eml_file = 'language/' . $hesk_settings['languages'][$hesk_settings['language']]['folder'] . '/html_emails/' . $orig_eml_file . '.txt';
if (file_exists(HESK_PATH . $eml_file)) {
$msg = file_get_contents(HESK_PATH . $eml_file);
} else {
hesk_error($hesklang['emfm'] . ': ' . $eml_file);
}
if (file_exists(HESK_PATH . $html_eml_file)) {
$html_msg = file_get_contents(HESK_PATH . $html_eml_file);
} else {
hesk_error($hesklang['emfm'] . ': ' . $html_eml_file);
}
/* Return just the message without any processing? */
if ($just_message) {
return array($msg, $html_msg);
}
// Convert any entities in site title to plain text
$site_title = hesk_msgToPlain($hesk_settings['site_title'], 1, 0);
// Create a HTML-version of the message if needed
if (isset($ticket['message']) && ! isset($ticket['message_html']) ) {
$ticket['message_html'] = '';
}
/* If it's not a ticket-related mail (like "a new PM") just process quickly */
if (!$is_ticket) {
$trackingURL = $hesk_settings['hesk_url'] . '/' . $hesk_settings['admin_dir'] . '/mail.php?a=read&id=' . intval($ticket['id']);
list($msg, $html_msg) = hesk_replace_email_tag('%%NAME%%', $ticket['name'], $msg, $html_msg);
list($msg, $html_msg) = hesk_replace_email_tag('%%SUBJECT%%', $ticket['subject'], $msg, $html_msg);
list($msg, $html_msg) = hesk_replace_email_tag('%%TRACK_URL%%', $trackingURL . ' ', $msg, $html_msg);
list($msg, $html_msg) = hesk_replace_email_tag('%%SITE_TITLE%%', $site_title, $msg, $html_msg);
list($msg, $html_msg) = hesk_replace_email_tag('%%SITE_URL%%', $hesk_settings['site_url'] . ' ', $msg, $html_msg);
list($msg, $html_msg) = hesk_replace_email_tag('%%FIRST_NAME%%', hesk_full_name_to_first_name($ticket['name']), $msg, $html_msg);
if (isset($ticket['message'])) {
$msg = str_replace('%%MESSAGE%%', $ticket['message'], $msg);
$html_msg = str_replace('%%MESSAGE%%', $ticket['message_html'], $html_msg);
}
return array($msg, $html_msg);
}
$is_customer_email = in_array(basename($eml_file, '.txt'), hesk_getCustomerEmailFilenames());
$hesk_settings['e_param'] = $hesk_settings['email_view_ticket'] && ! $hesk_settings['customer_accounts_required'] ? '&e=' . rawurlencode($ticket['email']) : '';
/* Generate the ticket URLs */
$trackingURL = $hesk_settings['hesk_url'];
$trackingURL .= $is_admin ? '/' . $hesk_settings['admin_dir'] . '/admin_ticket.php' : '/ticket.php';
$trackingURL .= '?track=' . $ticket['trackid'] . ($is_admin ? '' : $hesk_settings['e_param']) . '&Refresh=' . rand(10000, 99999);
/* Set category title */
$ticket['category'] = hesk_msgToPlain(hesk_getCategoryName($ticket['category']), 1, 0);
/* Set priority title */
$ticket['priority'] = hesk_get_priority_name($ticket['priority']);
/* Get owner name */
if ($owner_array = hesk_getStaffNameArray($ticket['owner'])) {
if ($is_customer_email) {
$ticket['owner'] = hesk_msgToPlain($owner_array['nickname'], 1, 0);
} else {
$ticket['owner'] = hesk_msgToPlain($owner_array['name'], 1, 0);
}
} else {
$ticket['owner'] = $hesklang['unas'];
}
/* Set status */
$ticket['status'] = hesk_get_status_name($ticket['status']);
// Get name of the person who posted the last message
if (!isset($ticket['last_reply_by'])) {
$ticket['last_reply_by'] = hesk_getReplierNameArray($ticket);
}
/* Replace all special tags */
if (!function_exists('hesk_get_customers_for_ticket')) {
require_once(HESK_PATH . 'inc/customer_accounts.inc.php');
}
if (!isset($ticket['customers'])) {
// Apparently the caller didn't get the customers for us :(
$ticket['customers'] = hesk_get_customers_for_ticket($ticket['id']);
}
$customer_info = hesk_getCustomersByRequesterAndFollowers($ticket['customers']);
$customer_info = hesk_ticketToPlain($customer_info, 1, 0);
list($msg, $html_msg) = hesk_replace_email_tag('%%REQUESTER%%', hesk_output_customer_name_and_email($customer_info['requester'], false), $msg, $html_msg);
list($msg, $html_msg) = hesk_replace_email_tag('%%REQUESTER_NAME%%', $customer_info['requester']['name'], $msg, $html_msg);
list($msg, $html_msg) = hesk_replace_email_tag('%%REQUESTER_FIRST_NAME%%', hesk_full_name_to_first_name($customer_info['requester']['name']), $msg, $html_msg);
list($msg, $html_msg) = hesk_replace_email_tag('%%REQUESTER_EMAIL%%', $customer_info['requester']['email'], $msg, $html_msg);
list($msg, $html_msg) = hesk_replace_email_tag('%%FOLLOWERS%%', hesk_emailFormatFollowers($customer_info['followers'], 'BOTH'), $msg, $html_msg);
list($msg, $html_msg) = hesk_replace_email_tag('%%FOLLOWER_NAMES%%', hesk_emailFormatFollowers($customer_info['followers'], 'NAMES'), $msg, $html_msg);
list($msg, $html_msg) = hesk_replace_email_tag('%%FOLLOWER_EMAILS%%', hesk_emailFormatFollowers($customer_info['followers'], 'EMAILS'), $msg, $html_msg);
list($msg, $html_msg) = hesk_replace_email_tag('%%SUBJECT%%', $ticket['subject'], $msg, $html_msg);
list($msg, $html_msg) = hesk_replace_email_tag('%%TRACK_ID%%', $ticket['trackid'], $msg, $html_msg);
list($msg, $html_msg) = hesk_replace_email_tag('%%TRACK_URL%%', $trackingURL . ' ', $msg, $html_msg);
list($msg, $html_msg) = hesk_replace_email_tag('%%SITE_TITLE%%', $site_title, $msg, $html_msg);
list($msg, $html_msg) = hesk_replace_email_tag('%%SITE_URL%%', $hesk_settings['site_url'] . ' ', $msg, $html_msg);
list($msg, $html_msg) = hesk_replace_email_tag('%%CATEGORY%%', $ticket['category'], $msg, $html_msg);
list($msg, $html_msg) = hesk_replace_email_tag('%%PRIORITY%%', $ticket['priority'], $msg, $html_msg);
list($msg, $html_msg) = hesk_replace_email_tag('%%OWNER%%', $ticket['owner'], $msg, $html_msg);
list($msg, $html_msg) = hesk_replace_email_tag('%%STATUS%%', $ticket['status'], $msg, $html_msg);
list($msg, $html_msg) = hesk_replace_email_tag('%%CREATED%%', $ticket['dt'], $msg, $html_msg);
list($msg, $html_msg) = hesk_replace_email_tag('%%UPDATED%%', $ticket['lastchange'], $msg, $html_msg);
list($msg, $html_msg) = hesk_replace_email_tag('%%DUE_DATE%%', $ticket['due_date'], $msg, $html_msg);
list($msg, $html_msg) = hesk_replace_email_tag('%%ID%%', $ticket['id'], $msg, $html_msg);
list($msg, $html_msg) = hesk_replace_email_tag('%%TIME_WORKED%%', $ticket['time_worked'], $msg, $html_msg);
if (is_string($ticket['last_reply_by'])) {
list($msg, $html_msg) = hesk_replace_email_tag('%%LAST_REPLY_BY%%', $ticket['last_reply_by'], $msg, $html_msg);
} elseif ($is_customer_email) {
list($msg, $html_msg) = hesk_replace_email_tag('%%LAST_REPLY_BY%%', $ticket['last_reply_by']['nickname'], $msg, $html_msg);
} else {
list($msg, $html_msg) = hesk_replace_email_tag('%%LAST_REPLY_BY%%', $ticket['last_reply_by']['name'], $msg, $html_msg);
}
// These fields are deprecated, but keeping them for backwards compatibility
// %%NAME%% can be set to Staff name is some cases
if (in_array($orig_eml_file, array('new_note', 'collaborator_staff_reply'))) {
list($msg, $html_msg) = hesk_replace_email_tag('%%NAME%%', $_SESSION['name'], $msg, $html_msg);
} else {
list($msg, $html_msg) = hesk_replace_email_tag('%%NAME%%', $customer_info['requester']['name'], $msg, $html_msg);
}
list($msg, $html_msg) = hesk_replace_email_tag('%%FIRST_NAME%%', hesk_full_name_to_first_name($customer_info['requester']['name']), $msg, $html_msg);
list($msg, $html_msg) = hesk_replace_email_tag('%%EMAIL%%', $customer_info['requester']['email'], $msg, $html_msg);
if (isset($ticket['ESCALATED_BY_RULE'])) {
list($msg, $html_msg) = hesk_replace_email_tag('%%ESCALATED_BY_RULE%%', $ticket['ESCALATED_BY_RULE'], $msg, $html_msg);
}
/* All custom fields */
for ($i = 1; $i <= 100; $i++) {
$k = 'custom' . $i;
if (isset($hesk_settings['custom_fields'][$k])) {
$v = $hesk_settings['custom_fields'][$k];
switch ($v['type']) {
case 'checkbox':
$ticket[$k] = str_replace("<br />", "\n", $ticket[$k]);
break;
case 'date':
$ticket[$k] = hesk_custom_date_display_format($ticket[$k], $v['value']['date_format']);
break;
}
list($msg, $html_msg) = hesk_replace_email_tag('%%' . strtoupper($k) . '%%', $ticket[$k], $msg, $html_msg);
} else {
list($msg, $html_msg) = hesk_replace_email_tag('%%' . strtoupper($k) . '%%', '', $msg, $html_msg);
}
}
// Let's handle the attachments tag
$att_links = array();
$html_att_links = array();
$mail_direct_attachment = [];
// Is message tag in email template?
if (strpos($msg, '%%MESSAGE%%') !== false || strpos($html_msg, '%%MESSAGE%%') !== false) {
if ($hesk_settings['attachments']['use'] && isset($ticket['attachments']) && strlen($ticket['attachments'])) {
$att = explode(',', substr($ticket['attachments'], 0, -1));
if ($hesk_settings['attachments']['attachment_in_email_type'] == '1') {
//get all attachment id,name and size
$att_ids = array();
foreach ($att as $myatt) {
list($att_id, $att_name) = explode('#', $myatt);
$att_ids[] = intval($att_id);
}
$result = hesk_dbQuery("SELECT `att_id`,`saved_name`, `size`,`real_name` FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "attachments` WHERE `att_id` IN (".implode(',', $att_ids).")");
$get_attachment_name_size = [];
while ($get_all_attachment = hesk_dbFetchAssoc($result)) {
$get_attachment_name_size[] = [
'att_id' => $get_all_attachment['att_id'],
'saved_name' => $get_all_attachment['saved_name'],
'att_name' => $get_all_attachment['real_name'],
'size' => $get_all_attachment['size']
];
}
$d = 1;
foreach ($get_attachment_name_size as $x => $y) {
$directory = $hesk_settings['attach_dir']; // get attachment directory;
$r_path = dirname( __FILE__, 2);
if ($hesk_settings['attachments']['direct_attachment_in_email'] == "0" && $y['size'] < $hesk_settings['attachments']['file_max_size'] && $hesk_settings['attachments']['direct_attachment_in_email_no_of_files'] == '3') {
$mail_direct_attachment[] = $r_path.'/'.$directory.'/'.$y['saved_name'];
} elseif ($hesk_settings['attachments']['direct_attachment_in_email'] == "0" && $y['size'] < $hesk_settings['attachments']['file_max_size'] && $hesk_settings['attachments']['direct_attachment_in_email_no_of_files'] == '2' && $d <= $hesk_settings['attachments']['first_x_attachments']){
$mail_direct_attachment[] = $r_path.'/'.$directory.'/'.$y['saved_name'];
$d = $d + 1;
} elseif ($hesk_settings['attachments']['direct_attachment_in_email'] == "1" && $hesk_settings['attachments']['direct_attachment_in_email_no_of_files'] == '2' && $d <= $hesk_settings['attachments']['first_x_attachments']){
$mail_direct_attachment[] = $r_path.'/'.$directory.'/'.$y['saved_name'];
$d = $d + 1;
} elseif ($hesk_settings['attachments']['direct_attachment_in_email'] == "1" && $hesk_settings['attachments']['direct_attachment_in_email_no_of_files'] == '3'){
$mail_direct_attachment[] = $r_path.'/'.$directory.'/'.$y['saved_name'];
} else {
$att_id = $y['att_id'];
$att_name = $y['att_name'];
$url_path = $is_customer_email ? '' : '/admin';
$att_links[] = $att_name . "\n" . $hesk_settings['hesk_url'] . $url_path . '/download_attachment.php?att_id=' . $att_id . '&track=' . $ticket['trackid'] . $hesk_settings['e_param'];
$html_att_links[] = '<a href="'.$hesk_settings['hesk_url'] . $url_path . '/download_attachment.php?att_id=' . $att_id . '&track=' . $ticket['trackid'] . str_replace('&', '&', $hesk_settings['e_param']).'">'.$att_name.'</a>';
}
}
} else {
//Direct Link to attchments in emails
foreach ($att as $myatt) {
list($att_id, $att_name) = explode('#', $myatt);
$url_path = $is_customer_email ? '' : '/admin';
$att_links[] = $att_name . "\n" . $hesk_settings['hesk_url'] . $url_path . '/download_attachment.php?att_id=' . $att_id . '&track=' . $ticket['trackid'] . $hesk_settings['e_param'];
$html_att_links[] = '<a href="'.$hesk_settings['hesk_url'] . $url_path . '/download_attachment.php?att_id=' . $att_id . '&track=' . $ticket['trackid'] . str_replace('&', '&', $hesk_settings['e_param']).'">'.$att_name.'</a>';
}
//Direct Link to attchments in emails
}
}
//Show text based on email link and direct attachment
$fatt = $hesklang['fatt'];
if (!empty($att_links) && !empty($mail_direct_attachment)) {
$fatt = $hesklang['fatt_2'];
}
$att_links = implode(" \n\n", $att_links);
$html_att_links = implode("<br/>", $html_att_links);
$msg = str_replace('%%ATTACHMENTS%%', $att_links, $msg, $count_plain);
$html_msg = str_replace('%%ATTACHMENTS%%', $html_att_links, $html_msg, $count_html);
// Is message tag in email template?
if (strpos($msg, '%%MESSAGE%%') !== false || strpos($html_msg, '%%MESSAGE%%') !== false) {
// If there are attachments to this email and the %%ATTACHMENTS%% tag was not present, add links to attachments below the message
if ($hesk_settings['attachments']['use'] && isset($ticket['attachments']) && strlen($ticket['attachments'])) {
if ($count_plain == 0 && $att_links !=='') {
$ticket['message'] .= "\n\n" . $fatt . "\n\n" . $att_links;
}
if ($count_html == 0 && $att_links !=='') {
$ticket['message_html'] .= "<br/><br/>" . $fatt . "<br/>" . $html_att_links;
}
}
// Replace message
$msg = str_replace('%%MESSAGE%%', $ticket['message'], $msg);
$html_msg = str_replace('%%MESSAGE%%', $ticket['message_html'], $html_msg);
// For customer notifications: if we allow email piping/pop 3 fetching and
// stripping quoted replies add an "reply above this line" tag
if (!$is_admin && ($hesk_settings['email_piping'] || $hesk_settings['pop3'] || $hesk_settings['imap']) && $hesk_settings['strip_quoted']) {
$msg = $hesklang['EMAIL_HR'] . "\n\n" . $msg;
$html_msg = $hesklang['EMAIL_HR'] . '<br/><br/>' . $html_msg;
}
}
}
return array($msg, $html_msg, $mail_direct_attachment);
} // END hesk_getEmailMessage
function hesk_getCustomersByRequesterAndFollowers($customers) {
$requester = null;
$followers = [];
foreach ($customers as $customer) {
if ($customer['customer_type'] === 'REQUESTER') {
$requester = $customer;
} else {
$followers[] = $customer;
}
}
if ( ! is_array($requester)) {
$requester['name'] = '';
$requester['email'] = '';
}
return [
'requester' => $requester,
'followers' => $followers
];
}
function hesk_emailFormatFollowers($followers, $format) {
$output = [];
foreach ($followers as $follower) {
if ($format === 'BOTH') {
$output[] = hesk_output_customer_name_and_email($follower, false);
} elseif ($format === 'NAMES' && $follower['name'] !== null && $follower['name'] !== '') {
$output[] = $follower['name'];
} elseif ($format === 'EMAILS' && $follower['email'] !== null && $follower['email'] !== '') {
$output[] = $follower['email'];
}
}
return implode(', ', $output);
}
function hesk_replace_email_tag($tag, $value, $message, $html_message, $nl2br = false, $html_value = false) {
if ($html_value) {
return array(
str_replace($tag, $value, $message),
str_replace($tag, ($nl2br ? nl2br($html_value) : $html_value), $html_message)
);
}
return array(
str_replace($tag, $value, $message),
str_replace($tag, ($nl2br ? nl2br(hesk_htmlspecialchars(trim($value))) : hesk_htmlspecialchars(trim($value))), $html_message)
);
}
function hesk_encodeIfNotAscii($str, $escape_header = false)
{
// Match anything outside of ASCII range
if (preg_match('/[^\x00-\x7F]/', $str)) {
return "=?UTF-8?B?" . base64_encode($str) . "?=";
}
// Do we need to wrap the header in double quotes?
if ($escape_header && preg_match("/[^-A-Za-z0-9!#$%&'*+\/=?^_`{|}~\\s]+/", $str)) {
return '"' . str_replace('"', '\\"', $str) . '"';
}
return $str;
} // END hesk_encodeIfNotAscii()
function hesk_PMtoMainAdmin($landmark)
{
global $hesk_settings, $hesklang;
$offer_license = file_exists(HESK_PATH.'hesk_license.php') ? "" : "<h3>» Look professional</h3>\r\n\r\n<p>To not only support Hesk development but also look more professional, <a href=\"https://www.hesk.com/get/hesk3-license\">remove "Powered by" links</a> from your help desk.</p>\r\n\r\n";
switch ($landmark) {
case 100:
$subject = "Congratulations on your 100th ticket!";
$message = "</p><div style=\"text-align:justify; padding-left: 10px; padding-right: 10px;\">\r\n\r\n<h2 style=\"padding-left:0px\">You are now part of the Hesk family, and we want to serve you better!</h2>\r\n\r\n<h3>» Rate us</h3>\r\n\r\n<p>Positive ratings and reviews motivate us to continue developing Hesk. Please take a moment to:</p>\r\n\r\n<ul>\r\n<li>rate or review Hesk at <a href=\"https://softaculous.com/rate/HESK\" rel=\"nofollow\">Softaculous</a></li>\r\n<li>rate or review Hesk at <a href=\"https://alternativeto.net/software/hesk/about/\" rel=\"nofollow\">AlternativeTo</a></li>\r\n</ul>\r\n\r\n<h3>» Stay updated</h3>\r\n\r\n<p>Hesk regularly receives improvements and bug fixes; make sure you know about them!</p>\r\n<ul>\r\n<li>for fast notifications, <a href=\"https://x.com/HESKdotCOM\" rel=\"nofollow\">follow Hesk on <b>X</b></a></li>\r\n<li>for email notifications, subscribe to our low-volume, zero-spam <a href=\"https://www.hesk.com/newsletter.php\">newsletter</a></li>\r\n</ul>\r\n\r\n<h3>» Look professional</h3>\r\n\r\n<p><a href=\"https://www.hesk.com/get/hesk3-license\">Remove "Powered by" links</a> to support Hesk development and make it look more professional.</p>\r\n\r\n \r\n\r\n<h3>» Upgrade to Hesk Cloud for the ultimate experience</h3>\r\n\r\n<p>Experience the best of Hesk by moving your help desk into the Hesk Cloud:</p>\r\n<ul>\r\n<li>exclusive advanced modules,</li>\r\n<li>automated updates,</li>\r\n<li>free migration of your existing Hesk tickets and settings,</li>\r\n<li>we take care of maintenance, server setup and optimization, backups, and more!</li>\r\n</ul>\r\n\r\n<p> <br><a href=\"https://www.hesk.com/get/hesk3-cloud\" class=\"btn btn--blue-border\" style=\"text-decoration:none\">Click here to learn more about Hesk Cloud</a></p>\r\n\r\n<p> </p>\r\n\r\n<p>Best regards,</p>\r\n\r\n<p>Klemen Stirn<br>\r\nFounder<br>\r\n<a href=\"https://www.hesk.com\">https://www.hesk.com</a></p>\r\n\r\n<p> </p>\r\n\r\n</div><p>";
break;
case 1000:
$subject = "We're excited about your 1,000th ticket!";
$message = "</p><div style=\"text-align:justify; padding-left: 10px; padding-right: 10px;\">\r\n\r\n<h2 style=\"padding-left:0px\">With 1,000 support tickets under the hood, you\'ve become a Hesk Power User. Congratulations!</h2>\r\n\r\n<h3>» Rate us</h3>\r\n\r\n<p>Positive ratings and reviews motivate us to continue developing Hesk. Please take a moment to:</p>\r\n\r\n<ul>\r\n<li>rate or review Hesk at <a href=\"https://softaculous.com/rate/HESK\" rel=\"nofollow\">Softaculous</a></li>\r\n<li>rate or review Hesk at <a href=\"https://alternativeto.net/software/hesk/about/\" rel=\"nofollow\">AlternativeTo</a></li>\r\n</ul>\r\n\r\n<h3>» Stay updated</h3>\r\n\r\n<p>Hesk regularly receives improvements and bug fixes; make sure you know about them!</p>\r\n<ul>\r\n<li>for fast notifications, <a href=\"https://x.com/HESKdotCOM\" rel=\"nofollow\">follow Hesk on <b>X</b></a></li>\r\n<li>for email notifications, subscribe to our low-volume, zero-spam <a href=\"https://www.hesk.com/newsletter.php\">newsletter</a></li>\r\n</ul>\r\n\r\n<h3>» Look professional</h3>\r\n\r\n<p><a href=\"https://www.hesk.com/get/hesk3-license\">Remove "Powered by" links</a> to support Hesk development and make it look more professional.</p>\r\n\r\n \r\n\r\n<h3>» Upgrade to Hesk Cloud for the ultimate experience</h3>\r\n\r\n<p>Experience the best of Hesk by moving your help desk into the Hesk Cloud:</p>\r\n<ul>\r\n<li>exclusive advanced modules,</li>\r\n<li>automated updates,</li>\r\n<li>free migration of your existing Hesk tickets and settings,</li>\r\n<li>we take care of maintenance, server setup and optimization, backups, and more!</li>\r\n</ul>\r\n\r\n<p> <br><a href=\"https://www.hesk.com/get/hesk3-cloud\" class=\"btn btn--blue-border\" style=\"text-decoration:none\">Click here to learn more about Hesk Cloud</a></p>\r\n\r\n<p> </p>\r\n\r\n<p>Best regards,</p>\r\n\r\n<p>Klemen Stirn<br>\r\nFounder<br>\r\n<a href=\"https://www.hesk.com\">https://www.hesk.com</a></p>\r\n\r\n<p> </p>\r\n\r\n</div><p>";
break;
case 10000:
$subject = "Wow, you've reached 10,000 tickets!";
$message = "</p><div style=\"text-align:justify; padding-left: 10px; padding-right: 10px;\">\r\n\r\n<h2 style=\"padding-left:0px\">You received 10,000 support tickets, outstanding! You are officially a Hesk Hero!</h2>\r\n\r\n<h3>» Rate us</h3>\r\n\r\n<p>Positive ratings and reviews motivate us to continue developing Hesk. Please take a moment to:</p>\r\n\r\n<ul>\r\n<li>rate or review Hesk at <a href=\"https://softaculous.com/rate/HESK\" rel=\"nofollow\">Softaculous</a></li>\r\n<li>rate or review Hesk at <a href=\"https://alternativeto.net/software/hesk/about/\" rel=\"nofollow\">AlternativeTo</a></li>\r\n</ul>\r\n\r\n<h3>» Stay updated</h3>\r\n\r\n<p>Hesk regularly receives improvements and bug fixes; make sure you know about them!</p>\r\n<ul>\r\n<li>for fast notifications, <a href=\"https://x.com/HESKdotCOM\" rel=\"nofollow\">follow Hesk on <b>X</b></a></li>\r\n<li>for email notifications, subscribe to our low-volume, zero-spam <a href=\"https://www.hesk.com/newsletter.php\">newsletter</a></li>\r\n</ul>\r\n\r\n<h3>» Look professional</h3>\r\n\r\n<p><a href=\"https://www.hesk.com/get/hesk3-license\">Remove "Powered by" links</a> to support Hesk development and make it look more professional.</p>\r\n\r\n \r\n\r\n<h3>» Upgrade to Hesk Cloud for the ultimate experience</h3>\r\n\r\n<p>Experience the best of Hesk by moving your help desk into the Hesk Cloud:</p>\r\n<ul>\r\n<li>exclusive advanced modules,</li>\r\n<li>automated updates,</li>\r\n<li>free migration of your existing Hesk tickets and settings,</li>\r\n<li>we take care of maintenance, server setup and optimization, backups, and more!</li>\r\n</ul>\r\n\r\n<p> <br><a href=\"https://www.hesk.com/get/hesk3-cloud\" class=\"btn btn--blue-border\" style=\"text-decoration:none\">Click here to learn more about Hesk Cloud</a></p>\r\n\r\n<p> </p>\r\n\r\n<p>Best regards,</p>\r\n\r\n<p>Klemen Stirn<br>\r\nFounder<br>\r\n<a href=\"https://www.hesk.com\">https://www.hesk.com</a></p>\r\n\r\n<p> </p>\r\n\r\n</div><p>";
break;
default:
return false;
}
// Insert private message for main admin
hesk_dbQuery("INSERT INTO `".hesk_dbEscape($hesk_settings['db_pfix'])."mail` (`id`, `from`, `to`, `subject`, `message`, `dt`, `read`, `deletedby`) VALUES (NULL, 9999, 1, '".hesk_dbEscape($subject)."', '{$message}', NOW(), '0', 9999)");
$pm_id = hesk_dbInsertID();
// Notify admin
$res = hesk_dbQuery("SELECT `name`,`email` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."users` WHERE `id`=1");
$row = hesk_dbFetchAssoc($res);
$pm = array(
'name' => 'HESK.com',
'subject' => $subject,
'message' => 'Please log in to see the message',
'id' => $pm_id,
);
// Format email subject and message for recipient
$subject = hesk_getEmailSubject('new_pm',$pm,0);
list($message, $html_message) = hesk_getEmailMessage('new_pm',$pm,1,0);
// Send e-mail
hesk_mail($row['email'], [], $subject, $message, $html_message);
return true;
} // END hesk_PMtoMainAdmin()
function hesk_get_muted_emails() {
global $hesk_settings;
$muted = array(
'emails' => array(),
'domains' => array(),
);
$res = hesk_dbQuery("SELECT `email`,`type` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."muted_emails`");
while ($row=hesk_dbFetchAssoc($res)) {
if ($row['type']) {
$muted['emails'][] = $row['email'];
} else {
$muted['domains'][] = $row['email'];
}
}
return $muted;
} // END hesk_get_muted_emails()
wget 'https://lists2.roe3.org/hesk/inc/export_functions.inc.php'
<?php
/**
*
* This file is part of HESK - PHP Help Desk Software.
*
* (c) Copyright Klemen Stirn. All rights reserved.
* https://www.hesk.com
*
* For the full copyright and license agreement information visit
* https://www.hesk.com/eula.php
*
*/
/* Check if this is a valid include */
if (!defined('IN_SCRIPT')) {die('Invalid attempt');}
/*** FUNCTIONS ***/
function hesk_export_to_XML($sql, $export_selected = false, $export_history = false, $export_replies = false)
{
global $hesk_settings, $hesklang, $ticket, $my_cat;
// We'll need HH:MM:SS format for hesk_date() here
$hesk_settings['format_timestamp'] = 'H:i:s';
// Get staff names
$admins = array();
$result = hesk_dbQuery("SELECT `id`,`name` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."users` ORDER BY `name` ASC");
while ($row=hesk_dbFetchAssoc($result))
{
$admins[$row['id']]=hesk_msgToPlain($row['name'], 1, 0);
}
// Get category names
if ( ! isset($my_cat))
{
$my_cat = array();
$res2 = hesk_dbQuery("SELECT `id`, `name` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."categories` WHERE " . hesk_myCategories('id') . " ORDER BY `cat_order` ASC");
while ($row=hesk_dbFetchAssoc($res2))
{
$my_cat[$row['id']] = hesk_msgToPlain($row['name'], 1, 0);
}
}
// This will be the export directory
$export_dir = HESK_PATH.$hesk_settings['cache_dir'].'/';
// This will be the name of the export and the XML file
$export_name = 'hesk_export_'.date('Y-m-d_H-i-s').'_'.mt_rand(100000,999999);
$save_to = $export_dir . $export_name . '.xml';
// Do we have the export directory?
if ( is_dir($export_dir) || ( @mkdir($export_dir, 0777) && is_writable($export_dir) ) )
{
// Is there an index.htm file?
if ( ! file_exists($export_dir.'index.htm'))
{
@file_put_contents($export_dir.'index.htm', '');
}
// Cleanup old files
hesk_purge_cache('export', 86400);
}
else
{
hesk_error($hesklang['ede']);
}
// Make sure the file can be saved and written to
@file_put_contents($save_to, '');
if ( ! file_exists($save_to) )
{
hesk_error($hesklang['eef']);
}
// Start generating the report message and generating the export
$success_msg = '';
$flush_me = '<br /><br />';
$flush_me .= hesk_date() . " | {$hesklang['inite']} ";
// Is this export of a date or date range?
if ($export_selected === false)
{
global $date_from, $date_to;
if ($date_from == $date_to)
{
$flush_me .= "(" . hesk_date($date_from, true, true, true, $hesk_settings['format_date']) . ")";
}
else
{
$flush_me .= "(" . hesk_date($date_from, true, true, true, $hesk_settings['format_date']) . " - " . hesk_date($date_to, true, true, true, $hesk_settings['format_date']) . ")";
}
}
$flush_me .= "<br />\n";
// Start generating file contents
$tmp = '<?xml version="1.0" encoding="UTF-8"?>
<?mso-application progid="Excel.Sheet"?>
<Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet"
xmlns:o="urn:schemas-microsoft-com:office:office"
xmlns:x="urn:schemas-microsoft-com:office:excel"
xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"
xmlns:html="http://www.w3.org/TR/REC-html40">
<OfficeDocumentSettings xmlns="urn:schemas-microsoft-com:office:office">
<AllowPNG/>
</OfficeDocumentSettings>
<ExcelWorkbook xmlns="urn:schemas-microsoft-com:office:excel">
<WindowHeight>8250</WindowHeight>
<WindowWidth>16275</WindowWidth>
<WindowTopX>360</WindowTopX>
<WindowTopY>90</WindowTopY>
<ProtectStructure>False</ProtectStructure>
<ProtectWindows>False</ProtectWindows>
</ExcelWorkbook>
<Styles>
<Style ss:ID="Default" ss:Name="Normal">
<Alignment ss:Vertical="Bottom"/>
<Borders/>
<Font ss:FontName="Calibri" x:CharSet="238" x:Family="Swiss" ss:Size="11"
ss:Color="#000000"/>
<Interior/>
<NumberFormat/>
<Protection/>
</Style>
<Style ss:ID="s62">
<NumberFormat ss:Format="General Date"/>
</Style>
<Style ss:ID="s63">
<NumberFormat ss:Format="Short Date"/>
</Style>
<Style ss:ID="s65">
<NumberFormat ss:Format="[h]:mm:ss"/>
</Style>
</Styles>
<Worksheet ss:Name="Sheet1">
<Table>
';
// Define column width
$tmp .= '
<Column ss:AutoFitWidth="0" ss:Width="50"/>
<Column ss:AutoFitWidth="0" ss:Width="84"/>
<Column ss:AutoFitWidth="0" ss:Width="100"/>
<Column ss:AutoFitWidth="0" ss:Width="100"/>
<Column ss:AutoFitWidth="0" ss:Width="100"/>
<Column ss:AutoFitWidth="0" ss:Width="100"/>
<Column ss:AutoFitWidth="0" ss:Width="90"/>
<Column ss:AutoFitWidth="0" ss:Width="90"/>
<Column ss:AutoFitWidth="0" ss:Width="90"/>
<Column ss:AutoFitWidth="0" ss:Width="87"/>
<Column ss:AutoFitWidth="0" ss:Width="57.75"/>
<Column ss:AutoFitWidth="0" ss:Width="57.75"/>
<Column ss:AutoFitWidth="0" ss:Width="100"/>
<Column ss:AutoFitWidth="0" ss:Width="100"/>
<Column ss:AutoFitWidth="0" ss:Width="80"/>
<Column ss:AutoFitWidth="0" ss:Width="50"/>
<Column ss:AutoFitWidth="0" ss:Width="50"/>
<Column ss:AutoFitWidth="0" ss:Width="70"/>
<Column ss:AutoFitWidth="0" ss:Width="70"/>
';
foreach ($hesk_settings['custom_fields'] as $k=>$v)
{
if ($v['use'])
{
$tmp .= '<Column ss:AutoFitWidth="0" ss:Width="80"/>' . "\n";
}
}
if ($export_history) {
$tmp .= '<Column ss:AutoFitWidth="0" ss:Width="100"/>' . "\n";
}
if ($export_replies) {
$tmp .= '<Column ss:AutoFitWidth="0" ss:Width="100"/>' . "\n";
}
// Define first row (header)
$tmp .= '
<Row>
<Cell><Data ss:Type="String">#</Data></Cell>
<Cell><Data ss:Type="String">'.$hesklang['trackID'].'</Data></Cell>
<Cell><Data ss:Type="String">'.$hesklang['date'].'</Data></Cell>
<Cell><Data ss:Type="String">'.$hesklang['last_update'].'</Data></Cell>
<Cell><Data ss:Type="String">'.$hesklang['first_reply_at'].'</Data></Cell>
<Cell><Data ss:Type="String">'.$hesklang['resolved_at'].'</Data></Cell>
<Cell><Data ss:Type="String">'.$hesklang['name'].'</Data></Cell>
<Cell><Data ss:Type="String">'.$hesklang['email'].'</Data></Cell>
<Cell><Data ss:Type="String">'.$hesklang['followers'].'</Data></Cell>
<Cell><Data ss:Type="String">'.$hesklang['category'].'</Data></Cell>
<Cell><Data ss:Type="String">'.$hesklang['priority'].'</Data></Cell>
<Cell><Data ss:Type="String">'.$hesklang['status'].'</Data></Cell>
<Cell><Data ss:Type="String">'.$hesklang['subject'].'</Data></Cell>
<Cell><Data ss:Type="String">'.$hesklang['message'].'</Data></Cell>
<Cell><Data ss:Type="String">'.$hesklang['owner'].'</Data></Cell>
<Cell><Data ss:Type="String">'.$hesklang['replies'].'</Data></Cell>
<Cell><Data ss:Type="String">'.$hesklang['replies'] . ' (' . $hesklang['staff'] .')'.'</Data></Cell>
<Cell><Data ss:Type="String">'.$hesklang['ts'].'</Data></Cell>
<Cell><Data ss:Type="String">'.$hesklang['due_date'].'</Data></Cell>
';
foreach ($hesk_settings['custom_fields'] as $k=>$v)
{
if ($v['use'])
{
$tmp .= '<Cell><Data ss:Type="String">'.$v['name'].'</Data></Cell>' . "\n";
}
}
if ($export_history) {
$tmp .= '<Cell><Data ss:Type="String">'.$hesklang['thist'].'</Data></Cell>' . "\n";
}
if ($export_replies) {
$tmp .= '<Cell><Data ss:Type="String">'.$hesklang['reply_messages'].'</Data></Cell>' . "\n";
}
$tmp .= '<Cell><Data ss:Type="String">'.$hesklang['ticket_url'].'</Data></Cell>' . "\n";
$tmp .= "</Row>\n";
// Write what we have by now into the XML file
file_put_contents($save_to, $tmp, FILE_APPEND);
$flush_me .= hesk_date() . " | {$hesklang['gXML']}<br />\n";
// OK, now start dumping data and writing it into the file
$tickets_exported = 0;
$save_after = 100;
$this_round = 0;
$tmp = '';
$result = hesk_dbQuery($sql);
while ($ticket=hesk_dbFetchAssoc($result))
{
$ticket['status'] = hesk_get_status_name($ticket['status']);
$ticket['priority'] = hesk_get_priority_name($ticket['priority']);
$ticket['archive'] = !($ticket['archive']) ? $hesklang['no'] : $hesklang['yes'];
$ticket['message'] = hesk_msgToPlain($ticket['message'], 1, 0);
$ticket['subject'] = hesk_msgToPlain($ticket['subject'], 1, 0);
$ticket['owner'] = isset($admins[$ticket['owner']]) ? $admins[$ticket['owner']] : '';
$ticket['category'] = isset($my_cat[$ticket['category']]) ? $my_cat[$ticket['category']] : '';
if (!function_exists('hesk_get_customers_for_ticket')) {
require_once(HESK_PATH . 'inc/customer_accounts.inc.php');
}
$customers = hesk_get_customers_for_ticket($ticket['id']);
if (defined('HESK_DEMO')) {
array_walk($customers, function(&$k) {
$k['email'] = 'hidden@demo.com';
});
}
$found_requester = false;
$requester = [];
$followers = [];
foreach ($customers as $customer) {
if ($customer['customer_type'] === 'REQUESTER') {
$found_requester = true;
$requester = $customer;
} elseif ($customer['customer_type'] === 'FOLLOWER') {
$followers[] = $customer;
}
}
if (!$found_requester) {
// Ticket has been anonymized
$requester['name'] = $hesklang['anon_name'];
$requester['email'] = $hesklang['anon_email'];
}
$follower_names = array_map(function($follower) { return format_display_name($follower); }, $followers);
// Format for export dates
$hesk_settings['format_timestamp'] = "Y-m-d\TH:i:s\.000";
// Create row for the XML file
$tmp .= '
<Row>
<Cell><Data ss:Type="Number">'.$ticket['id'].'</Data></Cell>
<Cell><Data ss:Type="String"><![CDATA['.hesk_escape_CDATA($ticket['trackid']).']]></Data></Cell>
<Cell ss:StyleID="s62"><Data ss:Type="DateTime">'.hesk_date($ticket['dt'], true).'</Data></Cell>
<Cell ss:StyleID="s62"><Data ss:Type="DateTime">'.hesk_date($ticket['lastchange'], true).'</Data></Cell>
';
if (empty($ticket['firstreply'])) {
$tmp .= '<Cell><Data ss:Type="String"></Data></Cell>' . "\n";
} else {
$tmp .= '<Cell ss:StyleID="s62"><Data ss:Type="DateTime">'.hesk_date($ticket['firstreply'], true).'</Data></Cell>' . "\n";
}
if (empty($ticket['closedat'])) {
$tmp .= '<Cell><Data ss:Type="String"></Data></Cell>'."\n";
} else {
$tmp .= '<Cell ss:StyleID="s62"><Data ss:Type="DateTime">'.hesk_date($ticket['closedat'], true).'</Data></Cell>'."\n";
}
$tmp .= '<Cell><Data ss:Type="String"><![CDATA['.hesk_escape_CDATA(hesk_msgToPlain($requester['name'], 1, 0)).']]></Data></Cell>
<Cell><Data ss:Type="String"><![CDATA['.hesk_escape_CDATA($requester['email']).']]></Data></Cell>
<Cell><Data ss:Type="String"><![CDATA['.hesk_escape_CDATA(implode(',', $follower_names)).']]></Data></Cell>
<Cell><Data ss:Type="String"><![CDATA['.hesk_escape_CDATA($ticket['category']).']]></Data></Cell>
<Cell><Data ss:Type="String"><![CDATA['.hesk_escape_CDATA($ticket['priority']).']]></Data></Cell>
<Cell><Data ss:Type="String"><![CDATA['.hesk_escape_CDATA($ticket['status']).']]></Data></Cell>
<Cell><Data ss:Type="String"><![CDATA['.hesk_escape_CDATA($ticket['subject']).']]></Data></Cell>
<Cell><Data ss:Type="String"><![CDATA['.hesk_escape_CDATA($ticket['message']).']]></Data></Cell>
<Cell><Data ss:Type="String"><![CDATA['.hesk_escape_CDATA($ticket['owner']).']]></Data></Cell>
<Cell><Data ss:Type="Number">'.$ticket['replies'].'</Data></Cell>
<Cell><Data ss:Type="Number">'.$ticket['staffreplies'].'</Data></Cell>
<Cell><Data ss:Type="String"><![CDATA['.hesk_escape_CDATA($ticket['time_worked']).']]></Data></Cell>
';
// Due date
if (empty($ticket['due_date']))
{
$tmp .= '<Cell><Data ss:Type="String"></Data></Cell>'."\n";
}
else
{
$tmp .= '<Cell ss:StyleID="s63"><Data ss:Type="DateTime">'.hesk_date($ticket['due_date'], true).'</Data></Cell>'."\n";
}
// Add custom fields
foreach ($hesk_settings['custom_fields'] as $k=>$v)
{
if ($v['use'])
{
switch ($v['type'])
{
case 'date':
$tmp_dt = hesk_custom_date_display_format($ticket[$k], 'Y-m-d\T00:00:00.000');
$tmp .= strlen($tmp_dt) ? '<Cell ss:StyleID="s63"><Data ss:Type="DateTime">'.$tmp_dt : '<Cell><Data ss:Type="String">';
$tmp .= "</Data></Cell> \n";
break;
default:
$tmp .= '<Cell><Data ss:Type="String"><![CDATA['.hesk_escape_CDATA(hesk_msgToPlain($ticket[$k], 1, 0)).']]></Data></Cell> ' . "\n";
}
}
}
if ($export_history) {
$tmp .= '<Cell><Data ss:Type="String"><![CDATA['.hesk_escape_CDATA($ticket['history']).']]></Data></Cell>' . "\n";
}
if ($export_replies) {
$tmp .= '<Cell><Data ss:Type="String"><![CDATA[';
if ($ticket['replies']) {
$replies = hesk_dbQuery("SELECT `replies`.*, `customers`.`name` AS `customer_name`, `customers`.`email` AS `customer_email`, `users`.`name` AS `staff_name`
FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."replies` AS `replies`
LEFT JOIN `".hesk_dbEscape($hesk_settings['db_pfix'])."customers` AS `customers`
ON `customers`.`id` = `replies`.`customer_id`
LEFT JOIN `".hesk_dbEscape($hesk_settings['db_pfix'])."users` AS `users`
ON `users`.`id` = `replies`.`staffid`
WHERE `replyto`='".intval($ticket['id'])."' ORDER BY `id` " . ($hesk_settings['new_top'] ? 'DESC' : 'ASC') );
while ($reply = hesk_dbFetchAssoc($replies)) {
if ($reply['staffid']) {
$reply['name'] = $reply['staff_name'] === null ?
$hesklang['staff_deleted'] :
$reply['staff_name'];
} else {
if ($reply['customer_name'] === null || $reply['customer_name'] == '') {
if ($reply['customer_email'] !== null && strlen($reply['customer_email'])) {
$reply['name'] = $reply['customer_email'];
} else {
$reply['name'] = $hesklang['anon_name'];
}
} else {
$reply['name'] = $reply['customer_name'];
}
}
$reply['message'] = hesk_msgToPlain($reply['message'], 1, 0);
$tmp .= hesk_escape_CDATA(
$hesklang['reply_by'] . ' ' . $reply['name'] . "\n" .
$hesklang['date'] . ' ' . hesk_date($reply['dt'], true) . "\n" .
$reply['message'] . "\n---\n"
);
}
}
$tmp .= ']]></Data></Cell>'."\n";
}
// Include a link to ticket
if ($hesk_settings['email_view_ticket'] && isset($requester['email'])) {
$tmp .= '<Cell><Data ss:Type="String">'.$hesk_settings['hesk_url'].'/ticket.php?track='.urlencode($ticket['trackid']).'&e='.urlencode($requester['email']).'</Data></Cell>';
} else {
$tmp .= '<Cell><Data ss:Type="String">'.$hesk_settings['hesk_url'].'/ticket.php?track='.urlencode($ticket['trackid']).'</Data></Cell>';
}
$tmp .= "</Row>\n";
// Write every 100 rows into the file
if ($this_round >= $save_after)
{
file_put_contents($save_to, $tmp, FILE_APPEND);
$this_round = 0;
$tmp = '';
usleep(1);
}
$tickets_exported++;
$this_round++;
} // End of while loop
// Go back to the HH:MM:SS format for hesk_date()
$hesk_settings['format_timestamp'] = 'H:i:s';
// Append any remaining rows into the file
if ($this_round > 0)
{
file_put_contents($save_to, $tmp, FILE_APPEND);
}
// If any tickets were exported, continue, otherwise cleanup
if ($tickets_exported > 0)
{
// Finish the XML file
$tmp = '
</Table>
<WorksheetOptions xmlns="urn:schemas-microsoft-com:office:excel">
<PageSetup>
<Header x:Margin="0.3"/>
<Footer x:Margin="0.3"/>
<PageMargins x:Bottom="0.75" x:Left="0.7" x:Right="0.7" x:Top="0.75"/>
</PageSetup>
<Selected/>
<Panes>
<Pane>
<Number>3</Number>
<ActiveRow>4</ActiveRow>
</Pane>
</Panes>
<ProtectObjects>False</ProtectObjects>
<ProtectScenarios>False</ProtectScenarios>
</WorksheetOptions>
</Worksheet>
<Worksheet ss:Name="Sheet2">
<Table ss:ExpandedColumnCount="1" ss:ExpandedRowCount="1" x:FullColumns="1"
x:FullRows="1" ss:DefaultRowHeight="15">
</Table>
<WorksheetOptions xmlns="urn:schemas-microsoft-com:office:excel">
<PageSetup>
<Header x:Margin="0.3"/>
<Footer x:Margin="0.3"/>
<PageMargins x:Bottom="0.75" x:Left="0.7" x:Right="0.7" x:Top="0.75"/>
</PageSetup>
<ProtectObjects>False</ProtectObjects>
<ProtectScenarios>False</ProtectScenarios>
</WorksheetOptions>
</Worksheet>
<Worksheet ss:Name="Sheet3">
<Table ss:ExpandedColumnCount="1" ss:ExpandedRowCount="1" x:FullColumns="1"
x:FullRows="1" ss:DefaultRowHeight="15">
</Table>
<WorksheetOptions xmlns="urn:schemas-microsoft-com:office:excel">
<PageSetup>
<Header x:Margin="0.3"/>
<Footer x:Margin="0.3"/>
<PageMargins x:Bottom="0.75" x:Left="0.7" x:Right="0.7" x:Top="0.75"/>
</PageSetup>
<ProtectObjects>False</ProtectObjects>
<ProtectScenarios>False</ProtectScenarios>
</WorksheetOptions>
</Worksheet>
</Workbook>
';
file_put_contents($save_to, $tmp, FILE_APPEND);
// Log how many rows we exported
$flush_me .= hesk_date() . " | " . sprintf($hesklang['nrow'], $tickets_exported) . "<br />\n";
// We will convert XML to Zip to save a lot of space
$save_to_zip = $export_dir.$export_name.'.zip';
// Log start of Zip creation
$flush_me .= hesk_date() . " | {$hesklang['cZIP']}<br />\n";
// Preferrably use the zip extension
if (extension_loaded('zip'))
{
$save_to_zip = $export_dir.$export_name.'.zip';
$zip = new ZipArchive;
$res = $zip->open($save_to_zip, ZipArchive::CREATE);
if ($res === TRUE)
{
$zip->addFile($save_to, "{$export_name}.xml");
$zip->close();
}
else
{
die("{$hesklang['eZIP']} <$save_to_zip>\n");
}
}
// Some servers have ZipArchive class enabled anyway - can we use it?
elseif ( class_exists('ZipArchive') )
{
require(HESK_PATH . 'inc/zip/Zip.php');
$zip = new Zip();
$zip->addLargeFile($save_to, "{$export_name}.xml");
$zip->finalize();
$zip->setZipFile($save_to_zip);
}
// If not available, use a 3rd party Zip class included with HESK
else
{
require(HESK_PATH . 'inc/zip/pclzip.lib.php');
$zip = new PclZip($save_to_zip);
$zip->add($save_to, PCLZIP_OPT_REMOVE_ALL_PATH);
}
// Delete XML, just leave the Zip archive
hesk_unlink($save_to);
// Echo memory peak usage
$flush_me .= hesk_date() . " | " . sprintf($hesklang['pmem'], (@memory_get_peak_usage(true) / 1048576)) . "<br />\r\n";
// We're done!
$flush_me .= hesk_date() . " | {$hesklang['fZIP']}<br /><br />";
// Success message
$referer = isset($_SERVER['HTTP_REFERER']) ? hesk_input($_SERVER['HTTP_REFERER']) : 'export.php';
$referer = str_replace('&','&',$referer);
if (strpos($referer, 'export.php'))
{
$referer = 'export.php';
}
$success_msg .= $hesk_settings['debug_mode'] ? $flush_me : '<br /><br />';
$success_msg .= $hesklang['step1'] . ': <a href="' . $save_to_zip . '">' . $hesklang['ch2d'] . '</a><br /><br />' . $hesklang['step2'] . ': <a href="export.php?delete='.urlencode($export_name).'&goto='.urlencode($referer).'&token='.hesk_token_echo(0).'">' . $hesklang['dffs'] . '</a>';
}
// No tickets exported, cleanup
else
{
hesk_unlink($save_to);
}
return array($success_msg, $tickets_exported);
} // END hesk_export_to_XML()
function hesk_escape_CDATA($in)
{
return str_replace(']]>', ']]]]><![CDATA[>', $in);
} // END hesk_escape_CDATA()
function format_display_name($row) {
if ($row['name']) {
return $row['email'] ? "{$row['name']} <{$row['email']}>" : $row['name'];
}
return $row['email'];
}
wget 'https://lists2.roe3.org/hesk/inc/favicon.inc.php'
<?php
/**
*
* This file is part of HESK - PHP Help Desk Software.
*
* (c) Copyright Klemen Stirn. All rights reserved.
* https://www.hesk.com
*
* For the full copyright and license agreement information visit
* https://www.hesk.com/eula.php
*
*/
// Check if this is a valid include
if (!defined('IN_SCRIPT')) {die('Invalid attempt');}
?>
<link rel="icon" href="<?php echo HESK_PATH; ?>img/favicon.ico" />
wget 'https://lists2.roe3.org/hesk/inc/footer.inc.php'
<?php
/**
*
* This file is part of HESK - PHP Help Desk Software.
*
* (c) Copyright Klemen Stirn. All rights reserved.
* https://www.hesk.com
*
* For the full copyright and license agreement information visit
* https://www.hesk.com/eula.php
*
*/
// Check if this is a valid include
if (!defined('IN_SCRIPT')) {die('Invalid attempt');}
// Users online
if (defined('SHOW_ONLINE'))
{
hesk_printOnline();
}
/*******************************************************************************
The code below handles HESK licensing and must be included in the template.
Removing this code is a direct violation of the HESK End User License Agreement,
will void all support and may result in unexpected behavior.
To purchase a HESK license and support future HESK development please visit:
https://www.hesk.com/buy.php
*******************************************************************************/
$hesk_settings['hesk_license']('GZvb3RlciBjbGFzcz0iZm9vdGVyIiBzdHlsZT0iZGlzcGxhe
TpibG9jayAhaW1wb3J0YW50OyI+PHAgY2xhc3M9InRleHQtY2VudGVyIiBzdHlsZT0iZGlzcGxheTpib
G9jayAhaW1wb3J0YW50OyI+UG93ZXJlZCBieSA8YSBocmVmPSJodHRwczovL3d3dy5oZXNrLmNvbSIgY
2xhc3M9ImxpbmsiIHN0eWxlPSJkaXNwbGF5OmlubGluZSAhaW1wb3J0YW50OyI+SGVscCBEZXNrIFNvZ
nR3YXJlPC9hPiA8c3BhbiBjbGFzcz0iZm9udC13ZWlnaHQtYm9sZCIgc3R5bGU9ImRpc3BsYXk6aW5sa
W5lICFpbXBvcnRhbnQ7Ij5IRVNLPC9zcGFuPjxicj4mbmJzcDs8L3A+PC9mb290ZXI+',"\120",
"2c6d33b92c7068eed222cfc904a0e6019a579a8d");
/*******************************************************************************
END LICENSE CODE
*******************************************************************************/
?>
<?php if ($hesk_settings['extend_admin'] && isset($_SESSION['id']) && ! isset($_SESSION['HESK_USER'])): ?>
<iframe src="<?php echo HESK_PATH . $hesk_settings['admin_dir'] . '/admin_extend_session.php'; ?>" height="10" width="10" style="border:none;"></iframe>
<?php endif; ?>
</main> <!-- End main -->
<?php
if (isset($login_wrapper)) {
echo '</div> <!-- End wrapper login -->';
}
?>
</div> <!-- End wrapper -->
<input type="hidden" name="HESK_PATH" value="<?php echo HESK_PATH; ?>">
<script src="<?php echo HESK_PATH; ?>js/svg4everybody.min.js"></script>
<?php
// Do we need the calendar functions?
if (defined('CALENDAR'))
{
?>
<script src="<?php echo HESK_PATH; ?>js/datepicker.min.js"></script>
<script type="text/javascript">
(function ($) { $.fn.datepicker.language['en'] = {
days: ['<?php echo $hesklang['d0']; ?>', '<?php echo $hesklang['d1']; ?>', '<?php echo $hesklang['d2']; ?>', '<?php echo $hesklang['d3']; ?>', '<?php echo $hesklang['d4']; ?>', '<?php echo $hesklang['d5']; ?>', '<?php echo $hesklang['d6']; ?>'],
daysShort: ['<?php echo $hesklang['sun']; ?>', '<?php echo $hesklang['mon']; ?>', '<?php echo $hesklang['tue']; ?>', '<?php echo $hesklang['wed']; ?>', '<?php echo $hesklang['thu']; ?>', '<?php echo $hesklang['fri']; ?>', '<?php echo $hesklang['sat']; ?>'],
daysMin: ['<?php echo $hesklang['su']; ?>', '<?php echo $hesklang['mo']; ?>', '<?php echo $hesklang['tu']; ?>', '<?php echo $hesklang['we']; ?>', '<?php echo $hesklang['th']; ?>', '<?php echo $hesklang['fr']; ?>', '<?php echo $hesklang['sa']; ?>'],
months: ['<?php echo $hesklang['m1']; ?>','<?php echo $hesklang['m2']; ?>','<?php echo $hesklang['m3']; ?>','<?php echo $hesklang['m4']; ?>','<?php echo $hesklang['m5']; ?>','<?php echo $hesklang['m6']; ?>', '<?php echo $hesklang['m7']; ?>','<?php echo $hesklang['m8']; ?>','<?php echo $hesklang['m9']; ?>','<?php echo $hesklang['m10']; ?>','<?php echo $hesklang['m11']; ?>','<?php echo $hesklang['m12']; ?>'],
monthsShort: ['<?php echo $hesklang['ms01']; ?>','<?php echo $hesklang['ms02']; ?>','<?php echo $hesklang['ms03']; ?>','<?php echo $hesklang['ms04']; ?>','<?php echo $hesklang['ms05']; ?>','<?php echo $hesklang['ms06']; ?>', '<?php echo $hesklang['ms07']; ?>','<?php echo $hesklang['ms08']; ?>','<?php echo $hesklang['ms09']; ?>','<?php echo $hesklang['ms10']; ?>','<?php echo $hesklang['ms11']; ?>','<?php echo $hesklang['ms12']; ?>'],
today: '<?php echo hesk_slashJS($hesklang['r1']); ?>',
clear: '<?php echo hesk_slashJS($hesklang['clear']); ?>',
dateFormat: '<?php echo hesk_slashJS($hesk_settings['format_datepicker_js']); ?>',
timeFormat: '<?php echo hesk_slashJS($hesk_settings['format_time']); ?>',
firstDay: <?php echo $hesklang['first_day_of_week']; ?>
}; })(jQuery);
</script>
<?php
}
?>
<script type="text/javascript" src="<?php echo HESK_PATH; ?>js/app<?php echo $hesk_settings['debug_mode'] ? '' : '.min'; ?>.js?<?php echo $hesk_settings['hesk_version']; ?>"></script>
<?php
// Any adjustments to datepicker?
if (isset($hesk_settings['datepicker'])):
?>
<script>
function convertDateToUTC(date) { return new Date(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), date.getUTCHours(), date.getUTCMinutes(), date.getUTCSeconds()); }
$(document).ready(function () {
const myDP = {};
<?php
foreach ($hesk_settings['datepicker'] as $selector => $data) {
echo "
myDP['{$selector}'] = $('{$selector}').datepicker(".((isset($data['position']) && is_string($data['position'])) ? "{position: '{$data['position']}'}" : "").");
";
if (isset($data['timestamp']) && ($ts = intval($data['timestamp']))) {
if ( ! empty($hesk_settings['datepicker'][$selector]['fromDB'])) {
echo "myDP['{$selector}'].data('datepicker').selectDate(convertDateToUTC(new Date({$ts} * 1000)));";
} else {
echo "myDP['{$selector}'].data('datepicker').selectDate(new Date({$ts} * 1000));";
}
}
}
?>
$('.showme').click(function (e) {
$(this).addClass('active');
$(this).parent()
.find('.datepicker')
.data("datepicker")
.show();
});
});
</script>
<?php
endif;
// Auto-select first empty or error field on non-staff pages?
if (defined('AUTOFOCUS'))
{
?>
<script language="javascript">
(function(){
var forms = document.forms || [];
for(var i = 0; i < forms.length; i++)
{
for(var j = 0; j < forms[i].length; j++)
{
if(
!forms[i][j].readonly != undefined &&
forms[i][j].type != "hidden" &&
forms[i][j].disabled != true &&
forms[i][j].style.display != 'none' &&
(forms[i][j].className == 'isError' || forms[i][j].className == 'isNotice' || forms[i][j].value == '')
)
{
forms[i][j].focus();
return;
}
}
}
})();
</script>
<?php
}
// Do we need the calendar functions?
if (defined('RRULE'))
{
?>
<script src="<?php echo HESK_PATH; ?>js/rrule_es5.js"></script>
<?php
}
// Apply status coloring to drop-down box; needs to be called after app.js
if (isset($hesk_settings['print_status_select_box_jquery']))
{
hesk_print_status_select_box_jquery();
}
echo '
</body>
</html>
';
$hesk_settings['security_cleanup']('exit');
wget 'https://lists2.roe3.org/hesk/inc/header.inc.php'
<?php
/**
*
* This file is part of HESK - PHP Help Desk Software.
*
* (c) Copyright Klemen Stirn. All rights reserved.
* https://www.hesk.com
*
* For the full copyright and license agreement information visit
* https://www.hesk.com/eula.php
*
*/
/* Check if this is a valid include */
if (!defined('IN_SCRIPT')) {die('Invalid attempt');}
// We'll use this later
$onload='';
define('TEMPLATE_PATH', HESK_PATH . "theme/{$hesk_settings['site_theme']}/");
$assetVersion = $hesk_settings['hesk_version'];
if ($hesk_settings['debug_mode']) {
// Note: For some reason, even with browser force cache refresh it's not always refreshing, so this is a way to force it additionally in debug mode if necessary.
$assetVersion .='_' . time();
}
?>
<!DOCTYPE html>
<html lang="<?php echo $hesk_settings['languages'][$hesk_settings['language']]['folder'] ?>">
<head>
<title><?php echo (isset($hesk_settings['tmp_title']) ? $hesk_settings['tmp_title'] : $hesk_settings['hesk_title']); ?></title>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
<meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0">
<?php include(HESK_PATH . 'inc/favicon.inc.php'); ?>
<meta name="format-detection" content="telephone=no">
<?php
// Do we need to load JS/CSS for attachments? Needs to go before our app.css
if (defined('ATTACHMENTS')) {
?>
<link rel="stylesheet" href="<?php echo HESK_PATH; ?>css/dropzone.min.css?<?php echo $assetVersion; ?>" type="text/css" />
<script src="<?php echo HESK_PATH; ?>js/dropzone.min.js?<?php echo $assetVersion; ?>"></script>
<?php
}
?>
<link rel="stylesheet" media="all" href="<?php echo HESK_PATH; ?>css/app<?php echo $hesk_settings['debug_mode'] ? '' : '.min'; ?>.css?<?php echo $assetVersion; ?>">
<script src="<?php echo HESK_PATH; ?>js/jquery-3.5.1.min.js"></script>
<?php
// Do we need to load customer-side theme/variables? (i.e. needed for live changes of theme settings with properly calculated colors)
if (defined('LOAD_CUSTOMER_THEME_VARS')) {
?>
<link id="default_theme" rel="stylesheet" media="all" href="<?php echo TEMPLATE_PATH; ?>customer/css/core/0_00_default_theme_vars.css?<?php echo $assetVersion; ?>" />
<?php
// Check if use has any special CSS themes selected, and if they exist, load their CSS.
// NOTE! Theme vars overrides have to be loaded in first, as they are then used as part of color calculations in 0_01_variables.css file!
$attempt_load_theme = isset($hesk_settings['customer_theme']) && $hesk_settings['customer_theme'] !== '';
if ($attempt_load_theme) {
$loaded_theme = $hesk_settings['customer_theme'];
$theme_path = TEMPLATE_PATH.'customer/css/themes/'.$loaded_theme.'.css';
if (file_exists($theme_path)) { ?>
<link id="loaded_theme" rel="stylesheet" media="all" href="<?php echo $theme_path; ?>?<?php echo $assetVersion; ?>" />
<?php
}
}
?>
<link rel="stylesheet" media="all" href="<?php echo TEMPLATE_PATH; ?>customer/css/core/0_01_variables.css?<?php echo $assetVersion; ?>" />
<?php
}
?>
<?php
// Do we need to load CSV parsing?
if (defined('CSV')) {
?>
<script src="<?php echo HESK_PATH; ?>js/jquery.csv.min.js?<?php echo $assetVersion; ?>"></script>
<?php
}
?>
<script src="<?php echo HESK_PATH; ?>js/selectize.min.js?<?php echo $assetVersion; ?>"></script>
<script type="text/javascript" src="<?php echo HESK_PATH; ?>js/hesk_javascript<?php echo $hesk_settings['debug_mode'] ? '' : '.min'; ?>.js?<?php echo $assetVersion; ?>"></script>
<?php
/* Tickets shouldn't be indexed by search engines */
if (defined('HESK_NO_ROBOTS'))
{
?>
<meta name="robots" content="noindex, nofollow" />
<?php
}
/* If page requires WYSIWYG editor include TinyMCE Javascript */
if (defined('WYSIWYG') && ($hesk_settings['staff_ticket_formatting'] == 2 || $hesk_settings['kb_wysiwyg'] || defined('HTML_EMAIL_TEMPLATE')))
{
require(HESK_PATH . 'inc/tiny_mce/tinymce.inc.php');
?>
<script type="text/javascript" src="<?php echo HESK_PATH; ?>inc/tiny_mce/7.9.1/tinymce.min.js"></script>
<?php
}
/* If page styles <code> blocks */
if (defined('STYLE_CODE'))
{
?>
<script type="text/javascript" src="<?php echo HESK_PATH; ?>js/prism.js?<?php echo $assetVersion; ?>"></script>
<link rel="stylesheet" media="all" href="<?php echo HESK_PATH; ?>css/prism.css?<?php echo $assetVersion; ?>">
<?php
}
/* If page requires timer load Javascript */
if (defined('TIMER'))
{
?>
<script type="text/javascript" src="<?php echo HESK_PATH; ?>inc/timer/hesk_timer.js"></script>
<?php
/* Need to load default time or a custom one? */
if ( isset($_SESSION['time_worked']) )
{
$t = hesk_getHHMMSS($_SESSION['time_worked']);
$onload .= "load_timer('time_worked', " . $t[0] . ", " . $t[1] . ", " . $t[2] . ");";
unset($t);
}
else
{
$onload .= "load_timer('time_worked', 0, 0, 0);";
}
/* Autostart timer? */
if ( ! empty($_SESSION['autostart']) )
{
$onload .= "ss();";
}
}
// Use ReCaptcha
if (defined('RECAPTCHA'))
{
echo '<script src="https://www.google.com/recaptcha/api.js?hl='.$hesklang['RECAPTCHA'].'" async defer></script>';
echo '<script language="Javascript" type="text/javascript">
function recaptcha_submitForm() {
document.getElementById("form1").submit();
}
</script>';
}
// Auto reload
if (defined('AUTO_RELOAD') && hesk_checkPermission('can_view_tickets',0))
{
?>
<script type="text/javascript">
var count = <?php echo empty($_SESSION['autoreload']) ? 30 : intval($_SESSION['autoreload']); ?>;
var reloadcounter;
var countstart = count;
function heskReloadTimer()
{
count=count-1;
if (count <= 0)
{
clearInterval(reloadcounter);
window.location.reload();
return;
}
document.getElementById("timer").innerHTML = "(" + count + ")";
}
function heskCheckReloading()
{
if (<?php if ($_SESSION['autoreload']) echo "getCookie('autorefresh') == null || "; ?>getCookie('autorefresh') == '1')
{
document.getElementById("reloadCB").checked=true;
document.getElementById("timer").innerHTML = "(" + count + ")";
reloadcounter = setInterval(heskReloadTimer, 1000);
}
}
function toggleAutoRefresh(cb)
{
if (cb.checked)
{
setCookie('autorefresh', '1');
document.getElementById("timer").innerHTML = "(" + count + ")";
reloadcounter = setInterval(heskReloadTimer, 1000);
}
else
{
setCookie('autorefresh', '0');
count = countstart;
clearInterval(reloadcounter);
document.getElementById("timer").innerHTML = "";
}
}
</script>
<?php
}
// Timeago
if (defined('TIMEAGO'))
{
?>
<script type="text/javascript" src="<?php echo HESK_PATH; ?>js/timeago/jquery.timeago.js?<?php echo $assetVersion; ?>"></script>
<?php
// Load language file if not English
if ($hesklang['TIMEAGO_LANG_FILE'] != 'jquery.timeago.en.js')
{
?>
<script type="text/javascript" src="<?php echo HESK_PATH; ?>js/timeago/locales/<?php echo $hesklang['TIMEAGO_LANG_FILE']; ?>?<?php echo $assetVersion; ?>"></script>
<?php
}
?>
<script type="text/javascript">
jQuery(document).ready(function() {
$("time.timeago").timeago();
});
</script>
<?php
}
// Back to top button
if (defined('BACK2TOP'))
{
?>
<script type="text/javascript">
jQuery(document).ready(function() {
var offset = 800;
var duration = 250;
jQuery(window).scroll(function() {
if (jQuery(this).scrollTop() > offset) {
jQuery('.back-to-top').fadeIn(duration);
} else {
jQuery('.back-to-top').fadeOut(duration);
}
});
jQuery('.back-to-top').click(function(event) {
event.preventDefault();
jQuery('html, body').animate({scrollTop: 0}, duration);
return false;
})
});
</script>
<?php
}
?>
<script type="text/javascript" src="<?php echo HESK_PATH; ?>js/zebra_tooltips.min.js?<?php echo $assetVersion; ?>"></script>
<link rel="stylesheet" href="<?php echo HESK_PATH; ?>css/zebra_tooltips.css">
<script type="text/javascript">
$(document).ready(function() {
// show tooltips for any element that has a class named "tooltip"
// the content of the tooltip will be taken from the element's "title" attribute
new $.Zebra_Tooltips($('.tooltip'), {animation_offset: 0, animation_speed: 100, hide_delay: 0, show_delay: 0, vertical_alignment: 'above', vertical_offset: 5});
});
</script>
<?php if ($hesk_settings['admin_css']): ?>
<link rel="stylesheet" href="<?php echo $hesk_settings['admin_css_url']; ?>">
<?php endif; ?>
<?php if ($hesk_settings['admin_js']): ?>
<script type="text/javascript" src="<?php echo $hesk_settings['admin_js_url']; ?>"></script>
<?php endif; ?>
</head>
<body onload="<?php echo $onload; unset($onload); ?>">
<a href="#maincontent" class="skiplink"><?php echo $hesklang['skip_to_main_content']; ?></a>
<div class="wrapper">
wget 'https://lists2.roe3.org/hesk/inc/index.htm'
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<HTML><HEAD>
<TITLE>403 Forbidden</TITLE>
</HEAD><BODY>
<H1>Forbidden</H1>
You don't have permission to access this folder.<P>
<hr />
</BODY></HTML>
wget 'https://lists2.roe3.org/hesk/inc/knowledgebase_functions.inc.php'
<?php
/**
*
* This file is part of HESK - PHP Help Desk Software.
*
* (c) Copyright Klemen Stirn. All rights reserved.
* https://www.hesk.com
*
* For the full copyright and license agreement information visit
* https://www.hesk.com/eula.php
*
*/
/* Check if this is a valid include */
if (!defined('IN_SCRIPT')) {die('Invalid attempt');}
hesk_kbCategoriesArray();
/*** FUNCTIONS ***/
function hesk_kbCategoriesArray($public_only = true)
{
global $hesk_settings, $hesklang;
$res = hesk_dbQuery("SELECT * FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."kb_categories` ORDER BY `cat_order` ASC");
$categories = array();
while ($category = hesk_dbFetchAssoc($res))
{
$category['children'] = array();
$category['descendants'] = array();
$categories[$category['id']] = $category;
}
// Get the full parent path for each category
foreach ($categories as $id => $category)
{
$categories[$id]['parents'] = array();
// Top category? Just translate name.
if ($category['parent'] == 0)
{
$categories[$id]['name'] = $hesklang['kb_text'];
continue;
}
$current_parrent = $category['parent'];
$categories[$id]['parents'][] = $current_parrent;
$i = 0;
while ($current_parrent > 0 && isset($categories[$current_parrent]) && $categories[$current_parrent]['id'] != $categories[$current_parrent]['parent'] && $i < 1000)
{
if (($current_parrent = $categories[$current_parrent]['parent']) > 0)
{
$categories[$id]['parents'][] = $current_parrent;
}
$i++;
}
$categories[$id]['parents'] = array_reverse($categories[$id]['parents']);
}
// Get children for each category
foreach ($categories as $id => $category) {
if ($category['parent'] == 0) {
continue;
}
$categories[$category['parent']]['children'][] = $id;
foreach ($category['parents'] as $parent) {
$categories[$parent]['descendants'][] = $id;
}
}
// If a parent is private, make sure all sub-categories are private too
foreach ($categories as $id => $category) {
if ($category['type'] == 0) {
continue;
}
foreach ($category['descendants'] as $descendant) {
if (isset($categories[$descendant])) {
$categories[$descendant]['type'] = 1;
}
}
}
// Uncomment if you want to remove direct children from "descendants"
/*
foreach ($categories as $id => $category) {
if (count($category['children']) == 0 || count($category['descendants']) == 0) {
continue;
}
$categories[$id]['descendants'] = array_diff($categories[$id]['descendants'], $categories[$id]['children']);
}
*/
$hesk_settings['all_kb_categories'] = $categories;
// Extract public categories only
foreach ($categories as $id => $category) {
if ($category['type'] == 1) {
unset($categories[$id]);
// Remove also from children and descendant arrays
foreach ($categories as $i => $c) {
if (($key = array_search($id, $categories[$i]['children'])) !== false) {
unset($categories[$i]['children'][$key]);
}
if (($key = array_search($id, $categories[$i]['descendants'])) !== false) {
unset($categories[$i]['descendants'][$key]);
}
}
}
}
$hesk_settings['public_kb_categories'] = $categories;
$hesk_settings['public_kb_categories_ids'] = array_keys($categories);
return true;
} // END hesk_kbCategoriesArray()
function hesk_kbArticleContentPreview($txt)
{
global $hesk_settings;
// Strip HTML tags
$txt = strip_tags($txt);
// If text is larger than article preview length, shorten it
if (hesk_mb_strlen($txt) > $hesk_settings['kb_substrart'])
{
// The quick but not 100% accurate way (number of chars displayed may be lower than the limit)
return hesk_mb_substr($txt, 0, $hesk_settings['kb_substrart']) . '...';
// If you want a more accurate, but also slower way, use this instead
// return hesk_htmlentities( hesk_mb_substr( hesk_html_entity_decode($txt), 0, $hesk_settings['kb_substrart'] ) ) . '...';
}
return $txt;
} // END hesk_kbArticleContentPreview()
function hesk_kbTopArticles($how_many, $index = 1)
{
global $hesk_settings, $hesklang;
$articles = array();
// Index page or KB main page?
if ($index)
{
// Disabled?
if (!$hesk_settings['kb_index_popart'])
{
return $articles;
}
}
else
{
// Disabled?
if (!$hesk_settings['kb_popart'])
{
return $articles;
}
}
// Make sure "public" categories are not nested in a "private" one
$sql_top = ' AND `t2`.`id` IN ('.implode(',', $hesk_settings['public_kb_categories_ids']).') ';
/* Get list of articles from the database */
$res = hesk_dbQuery("SELECT `t1`.`id`,`t1`.`catid`,`t1`.`subject`,`t1`.`views`, `t1`.`content`, `t2`.`name` AS `category`, `t1`.`rating`, `t1`.`votes` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."kb_articles` AS `t1`
LEFT JOIN `".hesk_dbEscape($hesk_settings['db_pfix'])."kb_categories` AS `t2` ON `t1`.`catid` = `t2`.`id`
WHERE `t1`.`type`='0' AND `t2`.`type`='0' {$sql_top}
ORDER BY `t1`.`sticky` DESC, `t1`.`views` DESC, `t1`.`art_order` ASC LIMIT ".intval($how_many));
$articles = array();
// Remember what articles are printed for "Top" so we don't print them again in "Latest"
$hesk_settings['kb_top_articles_printed'] = array();
while ($article = hesk_dbFetchAssoc($res))
{
// Top category? Translate name
if ($article['catid'] == 1)
{
$article['category'] = $hesklang['kb_text'];
}
$hesk_settings['kb_top_articles_printed'][] = $article['id'];
$article['content_preview'] = hesk_kbArticleContentPreview($article['content']);
$article['views_formatted'] = number_format($article['views'], 0, null, $hesklang['sep_1000']);
$article['votes_formatted'] = number_format($article['votes'], 0, null, $hesklang['sep_1000']);
$articles[] = $article;
}
return $articles;
} // END hesk_kbTopArticles()
function hesk_kbLatestArticles($how_many, $index = 1)
{
global $hesk_settings, $hesklang;
$articles = array();
// Index page or KB main page?
if ($index)
{
// Disabled?
if ( ! $hesk_settings['kb_index_latest'])
{
return $articles;
}
// Show title in italics
$font_weight = 'i';
}
else
{
// Disabled?
if ( ! $hesk_settings['kb_latest'])
{
return $articles;
}
// Show title in bold
$font_weight = 'b';
}
// Don't include articles that have already been printed under "Top" articles
$sql_top = '';
if (isset($hesk_settings['kb_top_articles_printed']) && count($hesk_settings['kb_top_articles_printed']))
{
$sql_top = ' AND `t1`.`id` NOT IN ('.implode(',', $hesk_settings['kb_top_articles_printed']).')';
}
// Make sure "public" categories are not nested in a "private" one
$sql_top .= ' AND `t2`.`id` IN ('.implode(',', $hesk_settings['public_kb_categories_ids']).') ';
/* Get list of articles from the database */
$res = hesk_dbQuery("SELECT `t1`.`id`,`t1`.`catid`,`t1`.`subject`,`t1`.`dt`,`t1`.`views`, `t1`.`content`, `t1`.`rating`, `t1`.`votes`, `t2`.`name` AS `category` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."kb_articles` AS `t1`
LEFT JOIN `".hesk_dbEscape($hesk_settings['db_pfix'])."kb_categories` AS `t2` ON `t1`.`catid` = `t2`.`id`
WHERE `t1`.`type`='0' AND `t2`.`type`='0' {$sql_top}
ORDER BY `t1`.`dt` DESC LIMIT ".intval($how_many));
while ($article = hesk_dbFetchAssoc($res))
{
// Top category? Translate name
if ($article['catid'] == 1)
{
$article['category'] = $hesklang['kb_text'];
}
$article['content_preview'] = hesk_kbArticleContentPreview($article['content']);
$article['views_formatted'] = number_format($article['views'], 0, null, $hesklang['sep_1000']);
$article['votes_formatted'] = number_format($article['votes'], 0, null, $hesklang['sep_1000']);
$articles[] = $article;
}
return $articles;
} // END hesk_kbLatestArticles()
function hesk_kbSearchLarge($admin = '')
{
global $hesk_settings, $hesklang;
$action = 'knowledgebase.php';
if ($admin)
{
if ( ! $hesk_settings['kb_search'])
{
return '';
}
$action = 'knowledgebase_private.php';
}
elseif ($hesk_settings['kb_search'] != 2)
{
return '';
}
?>
<form action="<?php echo $action; ?>" method="get" style="display: inline; margin: 10px" name="searchform" class="form">
<div class="form-group">
<label for="kb_largesearch"><?php echo $hesklang['ask']; ?></label>
<div style="display: flex">
<input id="kb_largesearch" type="text" name="search" class="searchfield form-control" style="flex-grow: 1; margin-right: 10px">
<button class="btn btn-full" type="submit" title="<?php echo $hesklang['search']; ?>" class="searchbutton" style="display: inline-block; height: 40px !important">
<?php echo $hesklang['search']; ?>
</button>
</div>
</div>
<!-- START KNOWLEDGEBASE SUGGEST -->
<div id="kb_suggestions" style="display:none">
<img src="<?php echo HESK_PATH; ?>img/loading.gif" width="24" height="24" alt="" border="0" style="vertical-align:text-bottom" /> <i><?php echo $hesklang['lkbs']; ?></i>
</div>
<script type="text/javascript"><!--
hesk_suggestKBsearch(<?php echo $admin; ?>);
//-->
</script>
<!-- END KNOWLEDGEBASE SUGGEST -->
</form>
<?php
} // END hesk_kbSearchLarge()
function hesk_kbSearchSmall()
{
global $hesk_settings, $hesklang;
if ($hesk_settings['kb_search'] != 1)
{
return '';
}
?>
<td style="text-align:right" valign="top" width="300">
<div style="display:inline;">
<form action="knowledgebase.php" method="get" style="display: inline; margin: 0;">
<input type="text" name="search" class="searchfield sfsmall" />
<input type="submit" value="<?php echo $hesklang['search']; ?>" title="<?php echo $hesklang['search']; ?>" class="searchbutton sbsmall" />
</form>
</div>
</td>
<?php
} // END hesk_kbSearchSmall()
function hesk_detect_bots()
{
$botlist = array('googlebot', 'msnbot', 'slurp', 'alexa', 'teoma', 'froogle',
'gigabot', 'inktomi', 'looksmart', 'firefly', 'nationaldirectory',
'ask jeeves', 'tecnoseek', 'infoseek', 'webfindbot', 'girafabot',
'crawl', 'www.galaxy.com', 'scooter', 'appie', 'fast', 'webbug', 'spade', 'zyborg', 'rabaz',
'baiduspider', 'feedfetcher-google', 'technoratisnoop', 'rankivabot',
'mediapartners-google', 'crawler', 'spider', 'robot', 'bot/', 'bot-','voila');
if ( ! isset($_SERVER['HTTP_USER_AGENT']))
{
return false;
}
$ua = strtolower($_SERVER['HTTP_USER_AGENT']);
foreach ($botlist as $bot)
{
if (strpos($ua,$bot) !== false)
{
return true;
}
}
return false;
} // END hesk_detect_bots()
wget 'https://lists2.roe3.org/hesk/inc/loader.inc.php'
<!--Installed Language Changes Add Loader-->
<div id="overlay_loader">
<div class="main-spinner">
<span class="sub-spinner"></span>
</div>
</div>
<!--Installed Language Changes Add Loader-->
wget 'https://lists2.roe3.org/hesk/inc/manage_customers_functions.inc.php'
<?php
/**
*
* This file is part of HESK - PHP Help Desk Software.
*
* (c) Copyright Klemen Stirn. All rights reserved.
* https://www.hesk.com
*
* For the full copyright and license agreement information visit
* https://www.hesk.com/eula.php
*
*/
/* Check if this is a valid include */
if (!defined('IN_SCRIPT')) {die('Invalid attempt');}
function hesk_customer_tab($session_array='new', $customer_verified = false)
{
global $hesk_settings, $hesklang;
$errors = hesk_SESSION(array($session_array, 'errors'));
$errors = is_array($errors) ? $errors : array();
?>
<div class="step-slider">
<div class="step-item step-1">
<div class="form-group">
<label for="prof_name"><?php echo $hesklang['name']; ?></label>
<input type="text" class="form-control <?php echo in_array('name', $errors) ? 'isError' : ''; ?>" id="prof_name" name="name" maxlength="50"
value="<?php echo $_SESSION[$session_array]['name']; ?>">
</div>
<div class="form-group">
<label for="prof_email"><?php echo $hesklang['email']; ?></label>
<input type="text" class="form-control <?php echo in_array('email', $errors) ? 'isError' : ''; ?>" name="email" maxlength="255" id="prof_user"
value="<?php echo $_SESSION[$session_array]['email']; ?>" aria-label="<?php echo $hesklang['email']; ?>">
</div>
<?php if ($hesk_settings['customer_accounts']): ?>
<section class="item--section customer-password">
<h4>
<?php echo $hesklang['pass']; ?>
</h4>
<div class="optional">
(<?php echo $hesklang['optional']; ?>)
</div>
<div class="form-group">
<label for="prof_newpass"><?php echo (empty($_SESSION[$session_array]['id']) ? $hesklang['pass'] : $hesklang['new_pass']); ?></label>
<input type="password" id="prof_newpass" name="newpass" autocomplete="off" class="form-control <?php echo in_array('passwords', $errors) ? 'isError' : ''; ?>"
value="<?php echo isset($_SESSION[$session_array]['cleanpass']) ? $_SESSION[$session_array]['cleanpass'] : ''; ?>"
onkeyup="hesk_checkPassword(this.value)">
</div>
<div class="form-group">
<label for="prof_newpass2"><?php echo (empty($_SESSION[$session_array]['id']) ? $hesklang['confirm_pass'] : $hesklang['confirm_new_pass']); ?></label>
<input type="password" class="form-control <?php echo in_array('passwords', $errors) ? 'isError' : ''; ?>" id="prof_newpass2" name="newpass2" autocomplete="off"
value="<?php echo isset($_SESSION[$session_array]['cleanpass']) ? $_SESSION[$session_array]['cleanpass'] : ''; ?>">
</div>
<div class="form-group">
<label><?php echo $hesklang['pwdst']; ?></label>
<div style="border: 1px solid #d4d6e3; width: 100%; height: 14px">
<div id="progressBar" style="font-size: 1px; height: 12px; width: 0px; border: none;">
</div>
</div>
</div>
<?php if (!$customer_verified) {
hesk_show_info($hesklang['customer_account_setting_password_will_verify_user']);
} ?>
</section>
<?php endif; ?>
</div>
</div>
<script>
if (document.form1.newpass) {
hesk_checkPassword(document.form1.newpass.value);
}
</script>
<?php
} // END hesk_profile_tab()
wget 'https://lists2.roe3.org/hesk/inc/mfa_functions.inc.php'
<?php
/**
*
* This file is part of HESK - PHP Help Desk Software.
*
* (c) Copyright Klemen Stirn. All rights reserved.
* https://www.hesk.com
*
* For the full copyright and license agreement information visit
* https://www.hesk.com/eula.php
*
*/
/* Check if this is a valid include */
use RobThree\Auth\TwoFactorAuth;
if (!defined('IN_SCRIPT')) {die('Invalid attempt');}
// region Email Authentication
function generate_mfa_code() {
return str_pad(random_int(100000, 999999), 6, '0', STR_PAD_LEFT);
}
function hash_and_store_mfa_verification_code($user_id, $verification_code, $user_type = 'STAFF') {
global $hesk_settings;
$hashed_verification_code = hesk_password_hash($verification_code);
// Allow 20 minutes to verify ("INTERVAL 20 MINUTE" is **very** intuitive...)
hesk_dbQuery("INSERT INTO `" . hesk_dbEscape($hesk_settings['db_pfix']) . "mfa_verification_tokens` (`user_id`, `verification_token`, `expires_at`, `user_type`)
VALUES (" . intval($user_id) . ",
'" . hesk_dbEscape($hashed_verification_code) . "',
NOW() + INTERVAL 20 MINUTE,
'".hesk_dbEscape($user_type)."')");
}
function send_mfa_email($name, $email, $verification_code) {
global $hesk_settings, $hesklang;
// Demo mode
if (defined('HESK_DEMO')) {
return '';
}
// Prepare and send email
if (!function_exists('hesk_mail')) {
require(HESK_PATH . 'inc/email_functions.inc.php');
}
// Get the email message
list($msg, $html_msg) = hesk_getEmailMessage('mfa_verification',array(),1,0,1);
// Replace message special tags
$name = hesk_msgToPlain($name, 1, 1);
list($msg, $html_msg) = hesk_replace_email_tag('%%NAME%%', $name, $msg, $html_msg);
list($msg, $html_msg) = hesk_replace_email_tag('%%FIRST_NAME%%', hesk_full_name_to_first_name($name), $msg, $html_msg);
list($msg, $html_msg) = hesk_replace_email_tag('%%SITE_TITLE%%', hesk_msgToPlain($hesk_settings['site_title'], 1, 0), $msg, $html_msg);
list($msg, $html_msg) = hesk_replace_email_tag('%%SITE_URL%%', $hesk_settings['site_url'] . ' ', $msg, $html_msg);
list($msg, $html_msg) = hesk_replace_email_tag('%%VERIFICATION_CODE%%', $verification_code, $msg, $html_msg);
// Send email
return hesk_mail($email, [], str_replace('%%VERIFICATION_CODE%%', $verification_code, $hesklang['mfa_verification']), $msg, $html_msg);
}
// Note: Deletes all verification codes upon successful validation
function is_mfa_email_code_valid($user_id, $verification_code, $user_type = 'STAFF') {
global $hesk_settings;
//-- Purge any verification codes that are expired
hesk_dbQuery("DELETE FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "mfa_verification_tokens`
WHERE `expires_at` < NOW()");
//-- Also purge all but the last 3 codes for a given user
$existing_tokens_rs = hesk_dbQuery("SELECT `id` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."mfa_verification_tokens` WHERE `user_id` = ".intval($user_id)." AND `user_type` = '".hesk_dbEscape($user_type)."' ORDER BY `id` DESC");
$index = 0;
while ($row = hesk_dbFetchAssoc($existing_tokens_rs)) {
if ($index++ < 3) {
continue;
}
hesk_dbQuery("DELETE FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."mfa_verification_tokens`
WHERE `id` = ".intval($row['id']));
}
//-- Grab remaining verification codes and see if one matches
$res = hesk_dbQuery("SELECT `verification_token` FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "mfa_verification_tokens`
WHERE `user_id` = " . intval($user_id) . "
AND `user_type` = '" . hesk_dbEscape($user_type) . "'");
while ($row = hesk_dbFetchAssoc($res)) {
if (hesk_password_verify($verification_code, $row['verification_token'])) {
delete_mfa_codes($user_id, $user_type);
return true;
}
}
return false;
}
function delete_mfa_codes($user_id, $user_type = 'STAFF') {
global $hesk_settings;
hesk_dbQuery("DELETE FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "mfa_verification_tokens`
WHERE `user_id` = " . intval($user_id) . "
AND `user_type` = '".hesk_dbEscape($user_type)."'");
}
// endregion
// region App-based Authentication
function build_tfa_instance() {
global $hesk_settings;
return new TwoFactorAuth($hesk_settings['hesk_title']);
}
function is_mfa_app_code_valid($user_id, $verification_code, $secret = null, $user_type = 'STAFF') {
global $hesk_settings, $hesklang;
$tfa = build_tfa_instance();
try {
$tfa->ensureCorrectTime(array(new \RobThree\Auth\Providers\Time\HttpTimeProvider()));
} catch (\RobThree\Auth\TwoFactorAuthException $e) {
hesk_error(sprintf($hesklang['mfa_server_time_issue'], $e->getMessage()));
}
if ($secret === null) {
$table = $user_type === 'STAFF' ? 'users' : 'customers';
$res = hesk_dbQuery("SELECT `mfa_secret` FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . $table."` WHERE `id` = " . intval($user_id));
$row = hesk_dbFetchAssoc($res);
$secret = $row['mfa_secret'];
}
return $tfa->verifyCode($secret, $verification_code);
}
// endregion
// region Backup Codes
function generate_and_store_mfa_backup_codes($user_id, $delete_old_codes = true, $user_type = 'STAFF') {
global $hesk_settings;
if ($delete_old_codes) {
delete_mfa_backup_codes($user_id, $user_type);
}
$codes = array();
for ($code_index = 0; $code_index < 10; $code_index++) {
$unique_code_generated = false;
do {
$code = generate_backup_code();
if (!in_array($code, $codes)) {
$codes[] = $code;
$unique_code_generated = true;
store_backup_code($user_id, $code, $user_type);
}
} while (!$unique_code_generated);
}
return $codes;
}
function generate_backup_code() {
$valid_chars = '0123456789abcdef';
$code = '';
for ($char_index = 0; $char_index < 8; $char_index++) {
$code .= $valid_chars[random_int(0, strlen($valid_chars) - 1)];
}
return $code;
}
function store_backup_code($user_id, $code, $user_type = 'STAFF') {
global $hesk_settings;
$hashed_code = hesk_password_hash($code);
hesk_dbQuery("INSERT INTO `".hesk_dbEscape($hesk_settings['db_pfix'])."mfa_backup_codes` (`user_id`, `code`, `user_type`)
VALUES (".intval($user_id).", '".hesk_dbEscape($hashed_code)."', '".hesk_dbEscape($user_type)."')");
}
function delete_mfa_backup_codes($user_id, $user_type = 'STAFF') {
global $hesk_settings;
hesk_dbQuery("DELETE FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."mfa_backup_codes`
WHERE `user_id` = ".intval($user_id).
" AND `user_type` = '".hesk_dbEscape($user_type)."'");
}
function delete_mfa_backup_code($user_id, $hashed_code, $user_type = 'STAFF') {
global $hesk_settings;
hesk_dbQuery("DELETE FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."mfa_backup_codes`
WHERE `user_id` = ".intval($user_id)." AND `code` = '".hesk_dbEscape($hashed_code)."' AND `user_type` = '".hesk_dbEscape($user_type)."'");
}
function verify_mfa_backup_code($user_id, $code, $user_type = 'STAFF') {
global $hesk_settings;
// Allow spaces, dashes, etc... in the backup code for easier printout
$code = preg_replace('/[^0-9a-f]/', '', strtolower($code));
$res = hesk_dbQuery("SELECT `code` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."mfa_backup_codes`
WHERE `user_id` = ".intval($user_id)."
AND `user_type` = '".hesk_dbEscape($user_type)."'");
while ($row = hesk_dbFetchAssoc($res)) {
if (hesk_password_verify($code, $row['code'])) {
delete_mfa_backup_code($user_id, $row['code'], $user_type);
return true;
}
}
return false;
}
// endregion
wget 'https://lists2.roe3.org/hesk/inc/oauth_functions.inc.php'
<?php
/**
*
* This file is part of HESK - PHP Help Desk Software.
*
* (c) Copyright Klemen Stirn. All rights reserved.
* https://www.hesk.com
*
* For the full copyright and license agreement information visit
* https://www.hesk.com/eula.php
*
*/
/* Check if this is a valid include */
if (!defined('IN_SCRIPT')) {
die('Invalid attempt');
}
function hesk_get_oauth_redirect_url() {
global $hesk_settings;
return $hesk_settings['hesk_url'] . '/' . $hesk_settings['admin_dir'] . '/oauth_providers.php';
}
function hesk_oauth_prepare_provider_state($provider_id)
{
$state = bin2hex(random_bytes(32));
if ( ! isset($_SESSION['oauth_provider_state']) || ! is_array($_SESSION['oauth_provider_state'])) {
$_SESSION['oauth_provider_state'] = array();
}
$_SESSION['oauth_provider_state'][$state] = intval($provider_id);
return $state;
} // End hesk_oauth_prepare_provider_state()
function hesk_oauth_verify_provider_state($state)
{
$state = strtolower(trim($state));
if ( ! preg_match('/\A[a-f0-9]{64}\z/', $state)) {
return false;
}
if ( ! isset($_SESSION['oauth_provider_state'][$state])) {
return false;
}
$provider_id = intval($_SESSION['oauth_provider_state'][$state]);
unset($_SESSION['oauth_provider_state'][$state]);
if (empty($_SESSION['oauth_provider_state'])) {
unset($_SESSION['oauth_provider_state']);
}
return $provider_id > 0 ? $provider_id : false;
} // End hesk_oauth_verify_provider_state()
function hesk_oauth_fetch_and_store_initial_token($provider, $code, $redirect_to = './oauth_providers.php') {
global $hesk_settings, $hesklang;
// Grab an access token and refresh token from the server
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $provider['token_url']);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 6);
curl_setopt($ch, CURLOPT_POST, 1);
if ($provider['no_val_ssl']) {
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
}
$redirect_url = hesk_get_oauth_redirect_url();
$post_fields = array(
'grant_type' => 'authorization_code',
'client_id' => $provider['client_id'],
'scope' => $provider['scope'],
'redirect_uri' => $redirect_url,
'client_secret' => $provider['client_secret'],
'code' => $code,
'access_type' => 'offline'
);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($post_fields, '', '&'));
$response = curl_exec($ch);
if ($response === false) {
$http_status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$error = curl_error($ch);
die("cURL {$hesklang['error']}: $http_status<br>\n{$hesklang['error']}: $error");
}
hesk_curl_close($ch);
$decoded_response = json_decode($response, true);
if ($decoded_response === false) {
//-- We didn't get a JSON response; this should never happen!
hesk_process_messages($hesklang['oauth_error_unknown'], $redirect_to);
} else {
if (isset($decoded_response['error'])) {
//-- Error occurred; go back to settings with an error prompt
$error = isset($decoded_response['error_description']) ? $decoded_response['error_description'] : $hesklang['oauth_error_unknown'];
$error = hesk_htmlspecialchars($error);
$debug = '';
if ($hesk_settings['debug_mode']) {
$debug = "Response: " . var_export($response, true) . "\n" .
"JSON: " . var_export($decoded_response, true) . "\n";
$debug = '<br><br><textarea rows="10" cols="60">Debug info: ' . "\n" . hesk_htmlspecialchars($debug) . '</textarea>';
}
hesk_process_messages(
$error . $debug,
$redirect_to
);
}
// Did we get an access token at all?
if ( ! isset($decoded_response['access_token'])) {
hesk_process_messages(
$hesklang['oauth_error_no_token'] . ($hesk_settings['debug_mode'] ? '<br><br><textarea rows="10" cols="60">Debug info: ' . "\n" . hesk_htmlspecialchars(
"Response: " . var_export($response, true) . "\n" .
"JSON: " . var_export($decoded_response, true) . "\n"
) . '</textarea>' : ''),
$redirect_to
);
}
//-- Save tokens to DB, return to email settings as we probably came from there.
hesk_store_oauth_token($provider['id'], $decoded_response['access_token'], 'access_token', $decoded_response['expires_in']);
// Refresh tokens are long-lasting, so we won't store an expiry as we'll always attempt to use it.
if (isset($decoded_response['refresh_token'])) {
hesk_store_oauth_token($provider['id'], $decoded_response['refresh_token'], 'refresh_token');
}
//-- This provider is now verified
hesk_dbQuery("UPDATE `".hesk_dbEscape($hesk_settings['db_pfix'])."oauth_providers` SET `verified` = 1 WHERE `id`={$provider['id']}");
hesk_process_messages($hesklang['oauth_provider_saved'] . '<br><br>' . sprintf($hesklang['oauth_provider_use'], $hesklang['settings'], $hesklang['tab_6']), $redirect_to, 'SUCCESS');
}
}
function hesk_store_oauth_token($provider_id, $token, $token_type, $expiry_in_seconds = null) {
global $hesk_settings;
// If we have another token with the same provider ID and type, purge it
hesk_dbQuery("DELETE FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."oauth_tokens`
WHERE `provider_id` = '".intval($provider_id)."'
AND `token_type` = '".hesk_dbEscape($token_type)."'");
// Store the new token. Subtracting 15 from the expiry to ensure that we won't attempt to use an expired access token down the road
$expiry_time = $expiry_in_seconds === null ?
'NULL' :
"NOW() + INTERVAL ".intval($expiry_in_seconds - 15)." SECOND";
hesk_dbQuery("INSERT INTO `".hesk_dbEscape($hesk_settings['db_pfix'])."oauth_tokens` (`provider_id`, `token_value`, `token_type`, `expires`)
VALUES ('".intval($provider_id)."',
'".hesk_dbEscape($token)."',
'".hesk_dbEscape($token_type)."',
".$expiry_time.")");
}
function hesk_fetch_access_token($provider_id) {
global $hesk_settings;
// Check if we have a token that is still valid for the next 30 seconds
$res = hesk_dbQuery("SELECT `token_value` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."oauth_tokens`
WHERE `provider_id` = '".hesk_dbEscape($provider_id)."'
AND `token_type` = 'access_token'
AND `expires` >= NOW() + INTERVAL 30 SECOND");
if ($row = hesk_dbFetchAssoc($res)) {
return $row['token_value'];
}
// No token available. Fetch a new token via its refresh token, store the new access / refresh, and return the new access token.
$res = hesk_dbQuery("SELECT `token_value` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."oauth_tokens`
WHERE `provider_id` = '".hesk_dbEscape($provider_id)."'
AND `token_type` = 'refresh_token'");
if ($row = hesk_dbFetchAssoc($res)) {
return hesk_retrieve_new_access_token($provider_id, $row['token_value']);
}
//-- Something went horribly wrong. We should never *not* have a refresh token.
return false;
}
function hesk_retrieve_new_access_token($provider_id, $refresh_token) {
global $hesk_settings, $hesklang;
$provider_rs = hesk_dbQuery("SELECT * FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."oauth_providers` WHERE `id` = ".intval($provider_id));
$provider = hesk_dbFetchAssoc($provider_rs);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $provider['token_url']);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 6);
curl_setopt($ch, CURLOPT_POST, 1);
if ($provider['no_val_ssl']) {
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
}
$redirect_url = hesk_get_oauth_redirect_url();
$post_fields = array(
'grant_type' => 'refresh_token',
'client_id' => $provider['client_id'],
'scope' => $provider['scope'],
'redirect_uri' => $redirect_url,
'client_secret' => $provider['client_secret'],
'refresh_token' => $refresh_token,
'access_type' => 'offline'
);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($post_fields, '', '&'));
$response = curl_exec($ch);
if ($response === false) {
$http_status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$error = curl_error($ch);
die("cURL {$hesklang['error']}: $http_status<br>\n{$hesklang['error']}: $error");
}
hesk_curl_close($ch);
$decoded_response = json_decode($response, true);
if ($decoded_response === false) {
// Something terribly bad happened if we get here.
return false;
}
// Did we get an access token at all?
if ( ! isset($decoded_response['access_token'])) {
return false;
}
//-- Save tokens to DB
hesk_store_oauth_token($provider_id, $decoded_response['access_token'], 'access_token', $decoded_response['expires_in']);
if (isset($decoded_response['refresh_token'])) {
hesk_store_oauth_token($provider_id, $decoded_response['refresh_token'], 'refresh_token');
}
return $decoded_response['access_token'];
}
wget 'https://lists2.roe3.org/hesk/inc/pipe_functions.inc.php'
<?php
/**
*
* This file is part of HESK - PHP Help Desk Software.
*
* (c) Copyright Klemen Stirn. All rights reserved.
* https://www.hesk.com
*
* For the full copyright and license agreement information visit
* https://www.hesk.com/eula.php
*
*/
/* Check if this is a valid include */
if (!defined('IN_SCRIPT')) {die('Invalid attempt');}
// Include all functions needed for email piping
hesk_load_database_functions();
require(HESK_PATH . 'inc/email_functions.inc.php');
require(HESK_PATH . 'inc/posting_functions.inc.php');
require(HESK_PATH . 'inc/mail/rfc822_addresses.php');
require(HESK_PATH . 'inc/mail/mime_parser.php');
require(HESK_PATH . 'inc/mail/email_parser.php');
require_once(HESK_PATH . 'inc/customer_accounts.inc.php');
/*** FUNCTIONS ***/
function hesk_email2ticket($results, $protocol = 0, $set_category = 1, $set_priority = -1)
{
global $hesk_settings, $hesklang, $hesk_db_link, $ticket;
if ( ! is_array($results)) {
return hesk_cleanExit('Email parser returned invalid data; skipping ticket creation.');
}
// Process "Reply-To:" or "From:" email
$tmpvar['email'] = isset($results['reply-to'][0]['address']) ? hesk_validateEmail($results['reply-to'][0]['address'],'ERR',0) : hesk_validateEmail($results['from'][0]['address'],'ERR',0);
// Email missing, invalid or banned?
if ( ! $tmpvar['email'])
{
return hesk_cleanExit('Customer email is missing or invalid: ' . $tmpvar['email']);
}
elseif (hesk_isBannedEmail($tmpvar['email']))
{
return hesk_cleanExit('Banned customer email address: ' . $tmpvar['email']);
}
$sender_lowercase = strtolower($tmpvar['email']);
// Ignore emails sent from the same email address we fetch tickets from or we will create a loop
// -> email sender matches Hesk's "From email"
if ($sender_lowercase == strtolower($hesk_settings['noreply_mail'])) {
return hesk_cleanExit('Email from Hesk "From email", ignoring to prevent email loops');
}
// -> email sender matches Hesk's "SMTP user"
if ($hesk_settings['smtp'] && $sender_lowercase == strtolower($hesk_settings['smtp_user'])) {
return hesk_cleanExit('Email from Hesk "SMTP user", ignoring to prevent email loops');
}
// -> email sender matches Hesk's "IMAP user"
if ($protocol == 2 && $sender_lowercase == strtolower($hesk_settings['imap_user'])) {
return hesk_cleanExit('Email from Hesk "IMAP user", ignoring to prevent email loops');
}
// -> email sender matches Hesk's "POP3 user"
if ($protocol == 1 && $sender_lowercase == strtolower($hesk_settings['pop3_user'])) {
return hesk_cleanExit('Email from Hesk "POP3 user", ignoring to prevent email loops');
}
// Process "Reply-To:" or "From:" name, convert to UTF-8, set to "[Customer]" if not set
if ( isset($results['reply-to'][0]['name']) && strlen($results['reply-to'][0]['name']) )
{
$tmpvar['name'] = $results['reply-to'][0]['name'];
if ( ! empty($results['reply-to'][0]['encoding']) )
{
$tmpvar['name'] = hesk_encodeUTF8($tmpvar['name'], $results['reply-to'][0]['encoding']);
}
}
else
{
$tmpvar['name'] = isset($results['from'][0]['name']) ? $results['from'][0]['name'] : '';
if ( ! empty($results['from'][0]['encoding']) )
{
$tmpvar['name'] = hesk_encodeUTF8($tmpvar['name'], $results['from'][0]['encoding']);
}
}
$tmpvar['name'] = hesk_input($tmpvar['name'],'','',1,50) or $tmpvar['name'] = '';
// Process email subject, convert to UTF-8, set to "[Piped email]" if none set
$tmpvar['subject'] = isset($results['subject']) ? $results['subject'] : $hesklang['pem'];
$tmpvar['subject'] = preg_replace("/(\n|\r|\t|%0A|%0D|%08|%09)+/", " ", $tmpvar['subject']);
if ( ! empty($results['subject_encoding']) )
{
$tmpvar['subject'] = hesk_encodeUTF8($tmpvar['subject'], $results['subject_encoding']);
}
$tmpvar['subject'] = hesk_input($tmpvar['subject'],'','',1,70) or $tmpvar['subject'] = $hesklang['pem'];
// Process email message, convert to UTF-8
$tmpvar['message'] = isset($results['message']) ? $results['message'] : '';
if ( ! empty($results['encoding']) )
{
$tmpvar['message'] = hesk_encodeUTF8($tmpvar['message'], $results['encoding']);
}
$tmpvar['message'] = hesk_input($tmpvar['message'],'','',1);
// Message missing?
if ( strlen($tmpvar['message']) == 0)
{
// Message required? Ignore this email.
if ($hesk_settings['eml_req_msg'])
{
return hesk_cleanExit('Missing email message');
}
// Message not required? Assign a default message
$tmpvar['message'] = $hesklang['def_msg'];
// Track duplicate emails based on subject
$message_hash = md5($tmpvar['subject']);
}
else
{
$message_hash = md5($tmpvar['message']);
}
// Strip quoted reply from email
$tmpvar['message'] = hesk_stripQuotedText($tmpvar['message']);
// Convert URLs to links, change newlines to <br />
$tmpvar['message'] = hesk_makeURL($tmpvar['message']);
$tmpvar['message'] = nl2br($tmpvar['message']);
// Store a copy for RTF-version
$tmpvar['message_html'] = $tmpvar['message'];
# For debugging purposes
# die( bin2hex($tmpvar['message']) );
# die($tmpvar['message']);
// Try to detect emails from "noreply" addresses
if ($hesk_settings['pipe_block_noreply'] && hesk_isDoNotReplyEmail($tmpvar))
{
return hesk_cleanExit('Email sent from a "noreply" email address: ' . $tmpvar['email']);
}
// Try to detect "delivery failed" emails
if ($hesk_settings['pipe_block_returned'] && hesk_isReturnedEmail($tmpvar))
{
return hesk_cleanExit('Looks like a returned email');
}
// Get email ID and Reply to ID
$tmpvar['email_id'] = isset($results['Message-ID']) ? preg_replace('[^a-zA-Z0-9!#$%&\'*+/=?^_`{|}~-]', '', $results['Message-ID']) : '';
$tmpvar['email_reply_to'] = isset($results['In-Reply-To']) ? preg_replace('[^a-zA-Z0-9!#$%&\'*+/=?^_`{|}~-]', '', $results['In-Reply-To']) : '';
// Has an email with this exact email ID been processed before?
if (strlen($tmpvar['email_id'])) {
$res = hesk_dbQuery("SELECT 1 FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."email_id_to_ticket` WHERE `email_id`='".hesk_dbEscape($tmpvar['email_id'])."' LIMIT 1");
if (hesk_dbNumRows($res)) {
return hesk_cleanExit('Email with this message ID has already been processed');
}
}
// Check for email loops
if (($reason = hesk_isEmailLoop($tmpvar['email'], $message_hash)) !== false)
{
return hesk_cleanExit($reason);
}
//-- Retrieve (or create) customer
if ($hesk_settings['customer_accounts'] === 0 || ($hesk_settings['customer_accounts'] === 1 && $hesk_settings['customer_accounts_required'] === 0)) {
$tmpvar['customer_id'] = hesk_get_or_create_customer($tmpvar['name'], $tmpvar['email']);
} else {
// Only allow existing customers to email their tickets/replies
$tmpvar['customer_id'] = hesk_get_customer_id_by_email($tmpvar['email'], true);
if ($tmpvar['customer_id'] === null) {
if ($hesk_settings['pipe_customer_rejection_notification']) {
hesk_notifyRejectedCustomer($tmpvar);
}
$reason = "Could not find customer with email '{$tmpvar['email']}' and helpdesk settings require an account to be created prior to sending tickets via e-mail.";
return hesk_cleanExit($reason);
}
}
// Process followers (additional people listed in To or Cc)
$tmpvar['followers'] = array();
$tmpvar['follower_ids'] = array();
if ($hesk_settings['multi_eml']) {
$copied = array();
// Process "To:" recipients
if ($hesk_settings['email_include_to']) {
foreach ($results['to'] as $key => $recipient) {
$recipient = hesk_processEmailContact($recipient, $protocol);
if (is_array($recipient)) {
$copied[] = $recipient;
} elseif (is_string($recipient)) {
if ($hesk_settings['debug_mode']) {
$hesk_settings['DEBUG_LOG']['NOTICES'][] = $recipient;
}
continue;
} else {
continue;
}
}
}
// Process "Cc:" recipients
if ($hesk_settings['email_include_cc']) {
foreach ($results['cc'] as $key => $recipient) {
$recipient = hesk_processEmailContact($recipient, $protocol);
if (is_array($recipient)) {
$copied[] = $recipient;
} elseif (is_string($recipient)) {
if ($hesk_settings['debug_mode']) {
$hesk_settings['DEBUG_LOG']['NOTICES'][] = $recipient;
}
continue;
} else {
continue;
}
}
}
foreach ($copied as $c) {
// Remove duplicate recipients
if (in_array($c['customer_id'], $tmpvar['follower_ids'])) {
continue;
}
// Remove "From" email address, it's already included
if ($c['email'] == $sender_lowercase) {
continue;
}
$tmpvar['followers'][] = $c['email'];
$tmpvar['follower_ids'][] = $c['customer_id'];
}
} // END if $hesk_settings['multi_eml']
// OK, everything seems OK. Now determine if this is a reply to a ticket or a new ticket
$tmpvar['trackid'] = '';
if (isset($results['X-Hesk-Tracking_ID']) && preg_match('/([A-Z0-9]{3}\-[A-Z0-9]{3}\-[A-Z0-9]{4})/', $results['X-Hesk-Tracking_ID'])) {
// Tracking ID found in custom X-Hesk-Tracking_ID email header
$tmpvar['trackid'] = $results['X-Hesk-Tracking_ID'];
if ($hesk_settings['debug_mode']) {
$hesk_settings['DEBUG_LOG']['NOTICES'][] = 'Tracking ID found in the X-Hesk-Tracking_ID email header';
}
} elseif ( preg_match('/\[#([A-Z0-9]{3}\-[A-Z0-9]{3}\-[A-Z0-9]{4})\]/', str_replace(' ', '', $tmpvar['subject']), $matches) ) {
// Tracking ID found in email subject
$tmpvar['trackid'] = $matches[1];
if ($hesk_settings['debug_mode']) {
$hesk_settings['DEBUG_LOG']['NOTICES'][] = 'Tracking ID found in the email subject';
}
} elseif (strlen($tmpvar['email_reply_to'])) {
// Can we find the ticket ID by email "In-Reply-To" header?
$res = hesk_dbQuery("SELECT `ticket_id` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."email_id_to_ticket` WHERE `email_id`='".hesk_dbEscape($tmpvar['email_reply_to'])."' LIMIT 1");
if (hesk_dbNumRows($res)) {
$ticket_id = hesk_dbResult($res);
$res = hesk_dbQuery("SELECT `trackid` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` WHERE `id`=".intval($ticket_id)." LIMIT 1");
if (hesk_dbNumRows($res)) {
$tmpvar['trackid'] = hesk_dbResult($res);
if ($hesk_settings['debug_mode']) {
$hesk_settings['DEBUG_LOG']['NOTICES'][] = 'Tracking ID found by email message ID lookup';
}
}
}
}
if ($tmpvar['trackid'] != '')
{
// Does it match one in the database?
$res = hesk_dbQuery("SELECT * FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` WHERE `trackid`='".hesk_dbEscape($tmpvar['trackid'])."' LIMIT 1");
if (hesk_dbNumRows($res))
{
$ticket = hesk_dbFetchAssoc($res);
// Do email addresses match?
$customers = hesk_get_customers_for_ticket($ticket['id']);
$customer_emails = array_map(function($customer) {return strtolower($customer['email']);}, $customers);
if (!in_array(strtolower($tmpvar['email']), $customer_emails))
{
$tmpvar['trackid'] = '';
}
// Is this ticket locked? Force create a new one if it is
if ($ticket['locked'])
{
$tmpvar['trackid'] = '';
}
}
else
{
$tmpvar['trackid'] = '';
}
}
// If tracking ID is empty, generate a new one
if ( empty($tmpvar['trackid']) )
{
$tmpvar['trackid'] = hesk_createID();
$is_reply = 0;
}
else
{
$is_reply = 1;
}
// Process attachments
$tmpvar['attachmment_notices'] = '';
$tmpvar['attachments'] = '';
$num = 0;
if ($hesk_settings['attachments']['use'] && isset($results['attachments'][0]))
{
foreach ($results['attachments'] as $k => $v)
{
// Clean attachment names
$myatt['real_name'] = hesk_cleanFileName($v['orig_name']);
// Check number of attachments, delete any over max number
if ($num >= $hesk_settings['attachments']['max_number'])
{
$tmpvar['attachmment_notices'] .= sprintf($hesklang['attnum'], $myatt['real_name']) . "\n";
continue;
}
// Check file extension
$ext = strtolower(strrchr($myatt['real_name'], "."));
if (!in_array($ext,$hesk_settings['attachments']['allowed_types']))
{
$tmpvar['attachmment_notices'] .= sprintf($hesklang['atttyp'], $myatt['real_name']) . "\n";
continue;
}
// Check file size
$myatt['size'] = $v['size'];
if ($myatt['size'] > ($hesk_settings['attachments']['max_size']))
{
$tmpvar['attachmment_notices'] .= sprintf($hesklang['attsiz'], $myatt['real_name']) . "\n";
continue;
}
// Generate a random file name
$useChars='AEUYBDGHJLMNPQRSTVWXZ123456789';
$tmp = $useChars[mt_rand(0,29)];
for($j=1;$j<10;$j++)
{
$tmp .= $useChars[mt_rand(0,29)];
}
$myatt['saved_name'] = substr($tmpvar['trackid'] . '_' . md5($tmp . $myatt['real_name']), 0, 200) . $ext;
// Rename the temporary file
$myatt['stored_name'] = isset($v['stored_name']) ? $v['stored_name'] : '';
if ( ! is_file($myatt['stored_name']) || ! rename($myatt['stored_name'], HESK_PATH.$hesk_settings['attach_dir'].'/'.$myatt['saved_name']))
{
$tmpvar['attachmment_notices'] .= $hesklang['attdel'] . ': ' . $myatt['real_name'] . "\n";
continue;
}
// Insert into database
hesk_dbQuery("INSERT INTO `".hesk_dbEscape($hesk_settings['db_pfix'])."attachments` (`ticket_id`,`saved_name`,`real_name`,`size`) VALUES ('".hesk_dbEscape($tmpvar['trackid'])."','".hesk_dbEscape($myatt['saved_name'])."','".hesk_dbEscape($myatt['real_name'])."','".intval($myatt['size'])."')");
$tmpvar['attachments'] .= hesk_dbInsertID() . '#' . $myatt['real_name'] .',';
$num++;
}
if (strlen($tmpvar['attachmment_notices']))
{
$tmpvar['message'] .= "<br /><br />" . hesk_input($hesklang['attrem'],'','',1) . "<br />" . nl2br(hesk_input($tmpvar['attachmment_notices'],'','',1));
$tmpvar['message_html'] .= "<br /><br />" . hesk_input($hesklang['attrem'],'','',1) . "<br />" . nl2br(hesk_input($tmpvar['attachmment_notices'],'','',1));
}
}
// Delete the temporary files
deleteAll($results['tempdir']);
// If this is a reply add a new reply
if ($is_reply)
{
// Set last replier name to customer name
$ticket['lastreplier'] = ($tmpvar['name'] == '') ? $tmpvar['email'] : $tmpvar['name'];
$ticket['customer_id'] = hesk_get_or_create_customer($tmpvar['name'], $tmpvar['email']);
// If staff hasn't replied yet, keep ticket status "New", otherwise set it to "Waiting reply from staff"
$ticket['status'] = $ticket['status'] ? 1 : 0;
// Update ticket as necessary
hesk_dbQuery("UPDATE `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` SET `lastchange`=NOW(),`status`='{$ticket['status']}',`replies`=`replies`+1,`lastreplier`='0' WHERE `id`='".intval($ticket['id'])."'");
// If customer replied, we assume staff replies have been read (no way to be sure if ticket.php hasn't been opened)
hesk_dbQuery("UPDATE `".hesk_dbEscape($hesk_settings['db_pfix'])."replies` SET `read` = '1' WHERE `replyto` = '".intval($ticket['id'])."' AND `staffid` != '0' ");
// Insert reply into database
hesk_dbQuery("INSERT INTO `".hesk_dbEscape($hesk_settings['db_pfix'])."replies` (`replyto`,`customer_id`,`message`,`message_html`,`dt`,`attachments`) VALUES ('".intval($ticket['id'])."','".intval($ticket['customer_id'])."','".hesk_dbEscape($tmpvar['message'])."','".hesk_dbEscape($tmpvar['message'])."',NOW(),'".hesk_dbEscape($tmpvar['attachments'])."')");
// Save the email ID map to ticket for later use
if ( ! empty($tmpvar['email_id'])) {
$reply_id = hesk_dbInsertID();
hesk_dbQuery("INSERT INTO `".hesk_dbEscape($hesk_settings['db_pfix'])."email_id_to_ticket` (`email_id`, `ticket_id`, `reply_id`, `from_hesk`) VALUES ('".hesk_dbEscape($tmpvar['email_id'])."', ".intval($ticket['id']).", {$reply_id}, 0)");
}
// --> Prepare reply message
$customers = hesk_get_customers_for_ticket($ticket['id']);
$customer_names = array_map(function($customer) { return $customer['name']; }, $customers);
$customer_emails = array_map(function($customer) { return $customer['email']; }, $customers);
// 1. Generate the array with ticket info that can be used in emails
$info = array(
'email' => implode(';', $customer_emails),
'category' => $ticket['category'],
'priority' => $ticket['priority'],
'owner' => $ticket['owner'],
'collaborators' => hesk_getTicketsCollaboratorIDs($ticket['id']),
'trackid' => $ticket['trackid'],
'status' => $ticket['status'],
'name' => implode(',', $customer_names),
'lastreplier' => $ticket['lastreplier'],
'subject' => $ticket['subject'],
'message' => stripslashes($tmpvar['message']),
'attachments' => $tmpvar['attachments'],
'dt' => hesk_date($ticket['dt'], true),
'lastchange' => hesk_date($ticket['lastchange'], true),
'due_date' => hesk_format_due_date($ticket['due_date']),
'id' => $ticket['id'],
'time_worked' => $ticket['time_worked'],
);
// 2. Add custom fields to the array
foreach ($hesk_settings['custom_fields'] as $k => $v)
{
$info[$k] = $v['use'] ? $ticket[$k] : '';
}
// 3. Add HTML message to the array
$info['message_html'] = $info['message'];
// 4. Make sure all values are properly formatted for email
$ticket = hesk_ticketToPlain($info, 1, 0);
// --> Process custom fields before sending
foreach ($hesk_settings['custom_fields'] as $k => $v)
{
$ticket[$k] = $v['use'] ? hesk_msgToPlain($ticket[$k], 1) : '';
}
// --> If ticket is assigned, notify the owner plus collaborators
if ($ticket['owner']) {
hesk_notifyAssignedStaff(false, 'new_reply_by_customer', 'notify_reply_my', 'notify_collaborator_customer_reply');
}
// --> No owner assigned, find and notify appropriate staff, including collaborators
elseif ($ticket['collaborators']) {
hesk_notifyStaff('new_reply_by_customer',"`notify_reply_unassigned`='1' OR (`notify_collaborator_customer_reply`='1' AND `id` IN (".implode(",", array_map('intval', $ticket['collaborators']))."))");
}
// --> No owner assigned, find and notify appropriate staff, no collaborators
else {
hesk_notifyStaff('new_reply_by_customer',"`notify_reply_unassigned`='1'");
}
return $ticket['trackid'];
} // END REPLY
// Not a reply, but a new ticket. Add it to the database
$tmpvar['category'] = $set_category;
$tmpvar['priority'] = $set_priority < 0 ? hesk_getCategoryPriority($tmpvar['category']) : $set_priority;
// Auto assign tickets if aplicable
$tmpvar['owner'] = 0;
// What protocol did we use to submit the ticket?
switch ($protocol)
{
// POP3 fetching
case 1:
$tmpvar['history'] = sprintf($hesklang['thist16'], hesk_date());
$tmpvar['openedby'] = -2;
break;
// IMAP fetching
case 2:
$tmpvar['history'] = sprintf($hesklang['thist17'], hesk_date());
$tmpvar['openedby'] = -3;
break;
// Email piping
default:
$tmpvar['history'] = sprintf($hesklang['thist11'], hesk_date());
$tmpvar['openedby'] = -1;
}
$autoassign_owner = hesk_autoAssignTicket($tmpvar['category']);
#print_r($autoassign_owner);
if ($autoassign_owner)
{
$tmpvar['owner'] = $autoassign_owner['id'];
$tmpvar['history'] .= sprintf($hesklang['thist10'],hesk_date(),addslashes($autoassign_owner['name']).' ('.$autoassign_owner['user'].')');
$tmpvar['assignedby'] = -1;
}
// Custom fields will be empty as there is no reliable way of detecting them
foreach ($hesk_settings['custom_fields'] as $k=>$v)
{
$tmpvar[$k] = '';
}
if (($default_due_date_info = hesk_getCategoryDueDateInfo($tmpvar['category'])) !== null)
{
$due_date = new DateTime('today midnight');
$due_date->add(DateInterval::createFromDateString("+{$default_due_date_info['amount']} {$default_due_date_info['unit']}s"));
$tmpvar['due_date'] = hesk_datepicker_format_date($due_date->getTimestamp());
// Don't set a due date if any unexpected errors
if ($tmpvar['due_date'] === false) {
$tmpvar['due_date'] = '';
}
}
// Create ticket
$ticket = hesk_newTicket($tmpvar);
// Notify the customer
if ($hesk_settings['notify_new'])
{
$possible_SPAM = false;
// Do we need to check subject for SPAM tags?
if ($hesk_settings['notify_skip_spam'])
{
foreach ($hesk_settings['notify_spam_tags'] as $tag)
{
if ( strpos($tmpvar['subject'], $tag) !== false )
{
$possible_SPAM = true;
break;
}
}
}
// SPAM tags not found or not checked, send email
if ($possible_SPAM === false)
{
hesk_notifyCustomer();
}
}
// Need to notify staff?
// --> From autoassign?
if ($tmpvar['owner'] && $autoassign_owner['notify_assigned'])
{
hesk_notifyAssignedStaff($autoassign_owner, 'ticket_assigned_to_you');
}
// --> No autoassign, find and notify appropriate staff
elseif ( ! $tmpvar['owner'] )
{
hesk_notifyStaff('new_ticket_staff', " `notify_new_unassigned` = '1' ");
}
return $ticket['trackid'];
} // END hesk_email2ticket()
function hesk_processEmailContact($contact, $protocol)
{
global $hesk_settings, $hesklang;
// Validate email
$contact['email'] = hesk_validateEmail($contact['address'], 'ERR', 0);
// Email missing?
if ( ! $contact['email']) {
return false;
}
$contact['email'] = strtolower($contact['email']);
// Ignore emails sent from the same email address we fetch tickets from or we will create a loop
// -> email sender matches Hesk's "From email"
if ($contact['email'] == strtolower($hesk_settings['noreply_mail'])) {
return 'Removed ' . $contact['email'] . ' (set as "From email" in Hesk settings, ignoring to prevent email loops)';
}
// -> email sender matches Hesk's "SMTP user"
if ($hesk_settings['smtp'] && $contact['email'] == strtolower($hesk_settings['smtp_user'])) {
return 'Removed ' . $contact['email'] . ' (set as "SMTP user" in Hesk settings, ignoring to prevent email loops)';
}
// -> email sender matches Hesk's "IMAP user"
if ($protocol == 2 && $contact['email'] == strtolower($hesk_settings['imap_user'])) {
return 'Removed ' . $contact['email'] . ' (set as "IMAP user" in Hesk settings, ignoring to prevent email loops)';
}
// -> email sender matches Hesk's "POP3 user"
if ($protocol == 1 && $contact['email'] == strtolower($hesk_settings['pop3_user'])) {
return 'Removed ' . $contact['email'] . ' (set as "POP3 user" in Hesk settings, ignoring to prevent email loops)';
}
// Email banned?
if (hesk_isBannedEmail($contact['email'])) {
return 'Removed ' . $contact['email'] . ' (banned email address)';
}
// Contact name
if (strlen($contact['name'])) {
if ( ! empty($contact['encoding']) ) {
$contact['name'] = hesk_encodeUTF8($contact['name'], $contact['encoding']);
}
$contact['name'] = hesk_input($contact['name'], '', '', 1, 50) or $contact['name'] = '';
} else {
$contact['name'] = '';
}
// Retrieve (or create) followers
if ($hesk_settings['customer_accounts'] === 0 || ($hesk_settings['customer_accounts'] === 1 && $hesk_settings['customer_accounts_required'] === 0)) {
$contact['customer_id'] = hesk_get_or_create_follower($contact['email'], $contact['name']);
} else {
// Only allow existing customers to email their tickets/replies
$contact['customer_id'] = hesk_get_customer_id_by_email($contact['email'], true);
if ($contact['customer_id'] === null) {
return 'Removed ' . $contact['email'] . ' (doesn\'t have a customer account)';
}
}
return $contact;
} // END hesk_processEmailContact()
function hesk_encodeUTF8($in, $encoding)
{
if (empty($in)) {
return $in;
}
$encoding = strtoupper($encoding);
// It's utf-8, just return it
if ($encoding == 'UTF-8') {
return $in;
}
// try with iconv
if (function_exists('iconv') && ($out = iconv($encoding, 'UTF-8', $in)) !== false) {
return $out;
}
// try with MB functions
if (function_exists('mb_convert_encoding') && ($out = mb_convert_encoding($in, 'UTF-8', $encoding)) !== false) {
return $out;
}
// last resort
return hesk_iso8859_1_to_utf8($in);
} // END hesk_encodeUTF8()
function hesk_stripQuotedText($message)
{
global $hesk_settings, $hesklang;
// Stripping quoted text disabled?
if ( ! $hesk_settings['strip_quoted'])
{
return $message;
}
// Loop through available languages and ty to find the tag
foreach ($hesk_settings['languages'] as $language => $settings)
{
if ( ($found = strpos($message, $settings['hr']) ) !== false )
{
// "Reply above this line" tag found, strip quoted reply
$message = hesk_mb_substr($message, 0, $found);
$message .= "\n" . $hesklang['qrr'];
// Set language to the detected language
hesk_setLanguage($language);
break;
}
}
return $message;
} // END hesk_stripQuotedText()
function hesk_isDoNotReplyEmail($tmpvar)
{
// Check noreply email addresses
if ( preg_match('/not?[\-_\.]?reply@/i', $tmpvar['email']) )
{
return true;
}
return false;
} // END hesk_isDoNotReplyEmail()
function hesk_isReturnedEmail($tmpvar)
{
// Check mailer daemon email addresses
if ( preg_match('/mail(er)?[\-_\.]?daemon@/i', $tmpvar['email']) )
{
return true;
}
// Check autoreply subjects
if ( preg_match('/^[\[\(]?Auto(mat(ic|ed))?[ \-]?reply/i', $tmpvar['subject']) )
{
return true;
}
// Check out of office subjects
if ( preg_match('/^Out of Office/i', $tmpvar['subject']) )
{
return true;
}
// Check delivery failed email subjects
if (
preg_match('/DELIVERY FAILURE/i', $tmpvar['subject']) ||
preg_match('/Undelivered Mail Returned to Sender/i', $tmpvar['subject']) ||
preg_match('/Delivery Status Notification \(Failure\)/i', $tmpvar['subject']) ||
preg_match('/Returned mail\: see transcript for details/i', $tmpvar['subject']) ||
preg_match('/^Undeliverable\:/i', $tmpvar['subject'])
)
{
return true;
}
// Check Mail Delivery sender name
if ( preg_match('/Mail[ \-_]?Delivery/i', $tmpvar['name']) )
{
return true;
}
// Check Delivery failed message
if ( preg_match('/postmaster@/i', $tmpvar['email']) && preg_match('/Delivery has failed to these recipients/i', $tmpvar['message']) )
{
return true;
}
// No pattern detected, seems like this is not a returned email
return false;
} // END hesk_isReturnedEmail()
function hesk_isEmailLoop($email, $message_hash)
{
global $hesk_settings, $hesklang, $hesk_db_link;
// If $hesk_settings['loop_hits'] is set to 0 this function is disabled
if ( ! $hesk_settings['pipe_block_duplicate'] && ! $hesk_settings['loop_hits'])
{
return false;
}
// Escape wildcards in email
$email_like = hesk_dbEscape(hesk_dbLike($email));
// Delete expired DB entries
hesk_dbQuery("DELETE FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."pipe_loops` WHERE `dt` < (NOW() - INTERVAL ".intval($hesk_settings['loop_time'])." SECOND) ");
// Check current entry
$res = hesk_dbQuery("SELECT `hits`, `message_hash` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."pipe_loops` WHERE `email` LIKE '{$email_like}' LIMIT 1");
// Any active entry*
if (hesk_dbNumRows($res))
{
list($num, $md5) = hesk_dbFetchRow($res);
$num++;
// Number of emails in a time period reached?
if ($hesk_settings['loop_hits'] && $num >= $hesk_settings['loop_hits'])
{
return "Email loop detected. Received {$num} emails from {$email} in {$hesk_settings['loop_time']} seconds.";
}
// Message exactly the same as in previous email?
if ($hesk_settings['pipe_block_duplicate'] && $message_hash == $md5)
{
return "Duplicate email. An email with this exact message was already received from {$email} in the last {$hesk_settings['loop_time']} seconds.";
}
// Update DB entry
hesk_dbQuery("UPDATE `".hesk_dbEscape($hesk_settings['db_pfix'])."pipe_loops` SET `hits` = `hits` + 1, `message_hash` = '".hesk_dbEscape($message_hash)."' WHERE `email` LIKE '{$email_like}'");
}
else
{
// First instance, insert a new database row
hesk_dbQuery("INSERT INTO `".hesk_dbEscape($hesk_settings['db_pfix'])."pipe_loops` (`email`, `message_hash`) VALUES ('".hesk_dbEscape($email)."', '".hesk_dbEscape($message_hash)."')");
}
// No loop rule trigered
return false;
} // END hesk_isEmailLoop()
function hesk_cleanExit($exit_reason = null)
{
global $hesk_settings, $results;
if ($hesk_settings['debug_mode']) {
$hesk_settings['DEBUG_LOG']['PIPE'] = $exit_reason;
}
// Delete the temporary files
if (is_array($results) && isset($results['tempdir']) && is_dir($results['tempdir'])) {
deleteAll($results['tempdir']);
}
return NULL;
} // END hesk_cleanExit()
function hesk_notifyRejectedCustomer($email_info) {
global $hesk_settings;
$send_failure_email_rs = hesk_dbQuery("SELECT `id`,
CASE
WHEN (`timestamp` + INTERVAL ".intval($hesk_settings['pipe_customer_rejection_email_cooldown_hours'])." HOUR) < NOW() THEN 1
ELSE 0
END AS `should_send_email`
FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."pipe_rejections`
WHERE `email` = '".hesk_dbEscape($email_info['email'])."'");
$send_failure_email = hesk_dbFetchAssoc($send_failure_email_rs);
if ($send_failure_email === null || $send_failure_email['should_send_email']) {
$possible_spam = false;
if ($hesk_settings['notify_skip_spam']) {
foreach ($hesk_settings['notify_spam_tags'] as $tag) {
if ( strpos($email_info['subject'], $tag) !== false ) {
$possible_spam = true;
break;
}
}
}
if (!$possible_spam) {
$rejection_template = $hesk_settings['customer_accounts_customer_self_register'] === 1 ?
'email_rejected_can_self_register' :
'email_rejected_cannot_self_register';
hesk_sendCustomerTicket2EmailFailure($email_info, $rejection_template);
if ($send_failure_email !== null) {
hesk_dbQuery("DELETE FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."pipe_rejections` WHERE `id` = ".intval($send_failure_email['id']));
}
hesk_dbQuery("INSERT INTO `".hesk_dbEscape($hesk_settings['db_pfix'])."pipe_rejections` (`timestamp`,`email`) VALUES (NOW(), '".hesk_dbEscape($email_info['email'])."')");
}
}
}
wget 'https://lists2.roe3.org/hesk/inc/posting_functions.inc.php'
<?php
/**
*
* This file is part of HESK - PHP Help Desk Software.
*
* (c) Copyright Klemen Stirn. All rights reserved.
* https://www.hesk.com
*
* For the full copyright and license agreement information visit
* https://www.hesk.com/eula.php
*
*/
/* Check if this is a valid include */
if (!defined('IN_SCRIPT')) {die('Invalid attempt');}
/*** FUNCTIONS ***/
function hesk_newTicket($ticket)
{
global $hesk_settings, $hesklang, $hesk_db_link;
require_once(HESK_PATH . 'inc/customer_accounts.inc.php');
$primary_customer = hesk_get_customer_account_by_id($ticket['customer_id']);
$name = $primary_customer['name'];
$email = $primary_customer['email'];
if ($primary_customer['verified'] !== 1) {
if (isset($ticket['name'])) {
$name = $ticket['name'];
}
if (isset($ticket['email'])) {
$email = $ticket['email'];
}
}
// Generate a subject if necessary
if (hesk_mb_strlen($ticket['subject']) < 1)
{
$ticket['subject'] = sprintf($hesklang['default_subject'], $primary_customer['name']);
}
// If language is not set or default, set it to NULL
if ( ! $hesk_settings['can_sel_lang'] || $hesklang['LANGUAGE'] == HESK_DEFAULT_LANGUAGE)
{
$ticket['language'] = HESK_DEFAULT_LANGUAGE;
$language = "NULL";
}
else
{
$ticket['language'] = $hesklang['LANGUAGE'];
$language = "'" . hesk_dbEscape($hesklang['LANGUAGE']) . "'";
}
$ticket['status'] = isset($ticket['status']) ? intval($ticket['status']) : 0;
if ($ticket['status'] < 0) {
$ticket['status'] = 0;
}
if ( ! isset($hesk_settings['priorities'])) {
require_once(HESK_PATH . 'inc/priorities.inc.php');
}
if ( ! isset($ticket['priority']) || ! hesk_is_valid_priority_id($ticket['priority'])) {
$ticket['priority'] = array_keys($hesk_settings['priorities'])[0];
} else {
$ticket['priority'] = intval($ticket['priority']);
}
// Prepare SQL for custom fields
$custom_where = '';
$custom_what = '';
for ($i=1; $i<=100; $i++)
{
$custom_where .= ", `custom{$i}`";
$custom_what .= ", '" . (isset($ticket['custom'.$i]) ? hesk_dbEscape($ticket['custom'.$i]) : '') . "'";
}
// Need to insert "addigned by" value?
if (isset($ticket['assignedby']))
{
$ab_where = ', `assignedby` ';
$ab_what = ', ' . intval($ticket['assignedby']);
}
else
{
$ab_where = '';
$ab_what = '';
}
if (isset($ticket['due_date']) && $ticket['due_date'] != '') {
$date = hesk_datepicker_get_date($ticket['due_date']);
if ($date === false) {
$due_date = 'NULL';
$ticket['due_date'] = '';
} else {
$formatted_date = $date->format('Y-m-d');
$due_date = "'" . hesk_dbEscape($formatted_date) . "'";
}
} else {
$due_date = 'NULL';
$ticket['due_date'] = '';
}
$locked = isset($ticket['locked']) ? 1 : 0;
$closedat = isset($ticket['closedat']) ? 'NOW()' : 'NULL';
$closedby = isset($ticket['closedby']) ? intval($ticket['closedby']) : 'NULL';
// Insert ticket into database
hesk_dbQuery("
INSERT INTO `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets`
(
`trackid`,
`u_name`,
`u_email`,
`category`,
`priority`,
`subject`,
`message`,
`message_html`,
`dt`,
`lastchange`,
`closedat`,
`articles`,
`ip`,
`language`,
`status`,
`openedby`,
`closedby`,
`owner`,
`locked`,
`attachments`,
`merged`,
`history`,
`due_date`
{$custom_where}
{$ab_where}
)
VALUES
(
'".hesk_dbEscape($ticket['trackid'])."',
'".hesk_dbEscape( hesk_mb_substr($name, 0, 255) )."',
'".hesk_dbEscape( hesk_mb_substr($email, 0, 1000) )."',
'".intval($ticket['category'])."',
'".intval($ticket['priority'])."',
'".hesk_dbEscape( hesk_mb_substr($ticket['subject'], 0, 255) )."',
'".hesk_dbEscape($ticket['message'])."',
'".hesk_dbEscape($ticket['message_html'])."',
NOW(),
NOW(),
{$closedat},
".( isset($ticket['articles']) ? "'{$ticket['articles']}'" : 'NULL' ).",
'".hesk_dbEscape(hesk_getClientIP())."',
$language,
'{$ticket['status']}',
'".( isset($ticket['openedby']) ? intval($ticket['openedby']) : 0 )."',
{$closedby},
'".intval($ticket['owner'])."',
'$locked',
'".hesk_dbEscape($ticket['attachments'])."',
'',
'".hesk_dbEscape($ticket['history'])."',
{$due_date}
{$custom_what}
{$ab_what}
)
");
$ticket_id = hesk_dbInsertID();
// Insert ticket/customer mapping(s)
hesk_dbQuery("INSERT INTO `".hesk_dbEscape($hesk_settings['db_pfix'])."ticket_to_customer` (`ticket_id`, `customer_id`, `customer_type`)
VALUES (".intval($ticket_id).", ".intval($ticket['customer_id']).", 'REQUESTER')");
foreach ($ticket['follower_ids'] as $follower_id) {
// Do we have the customer in the list of followers? If so, skip it.
if ($follower_id === $ticket['customer_id']) {
continue;
}
hesk_dbQuery("INSERT INTO `".hesk_dbEscape($hesk_settings['db_pfix'])."ticket_to_customer` (`ticket_id`, `customer_id`, `customer_type`)
VALUES (".intval($ticket_id).", ".intval($follower_id).", 'FOLLOWER')");
}
// Save the email ID map to ticket for later use
if ( ! empty($ticket['email_id'])) {
hesk_dbQuery("INSERT INTO `".hesk_dbEscape($hesk_settings['db_pfix'])."email_id_to_ticket` (`email_id`, `ticket_id`, `from_hesk`) VALUES ('".hesk_dbEscape($ticket['email_id'])."', {$ticket_id}, 0)");
}
// Generate the array with ticket info that can be used in emails
$info = array(
'email' => $primary_customer['email'],
'category' => $ticket['category'],
'priority' => $ticket['priority'],
'owner' => $ticket['owner'],
'trackid' => $ticket['trackid'],
'status' => $ticket['status'],
'name' => addslashes($primary_customer['name']),
'last_reply_by' => addslashes($primary_customer['name']),
'subject' => $ticket['subject'],
'message' => $ticket['message'],
'message_html' => stripslashes($ticket['message_html']),
'attachments' => $ticket['attachments'],
'dt' => hesk_date(),
'lastchange' => hesk_date(),
'due_date' => hesk_format_due_date($ticket['due_date']),
'id' => $ticket_id,
'time_worked' => '00:00:00',
'language' => $ticket['language'],
);
// Add custom fields to the array
foreach ($hesk_settings['custom_fields'] as $k => $v)
{
$info[$k] = $v['use'] ? $ticket[$k] : '';
}
// Extra actions for achieving landmarks
if (in_array($info['id'], array(100, 1000, 10000)))
{
hesk_PMtoMainAdmin($info['id']);
}
return hesk_ticketToPlain($info, 1);
} // END hesk_newTicket()
function hesk_cleanFileName($filename)
{
$parts = pathinfo($filename);
if ( ! isset($parts['extension']))
{
$parts['extension'] = 'unknown-file-type';
}
$parts['extension'] = preg_replace('/[^A-Za-z0-9\-_]/', '', $parts['extension']);
if ( isset($parts['filename']) )
{
$filename = $parts['filename'];
}
// PHP < 5.2 needs special care
elseif ( version_compare(PHP_VERSION, '5.2','<') )
{
$filename = rtrim( str_ireplace($parts['extension'], '', $filename), '.');
}
else
{
$filename = '';
}
$filename = str_replace( array( '%20', '+' ), '-', $filename );
$filename = preg_replace('/[\s-]+/', '-', $filename);
$filename = remove_accents($filename);
$filename = preg_replace('/[^A-Za-z0-9\.\-_]/','', $filename);
$filename = trim($filename, '-_');
if ( strlen($filename) < 1 || strpos($filename, '.') === 0 )
{
$filename = mt_rand(10000,99999) . $filename;
}
return $filename . '.' . $parts['extension'];
} // END hesk_cleanFileName()
function hesk_getCategoryPriority($id)
{
global $hesk_settings, $hesklang, $hesk_db_link;
$priority = 3;
// Does the category have a different default priority?
$res = hesk_dbQuery("SELECT `priority` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."categories` WHERE `id`=" . intval($id) . " LIMIT 1");
if ( hesk_dbNumRows($res) == 1 )
{
$priority = hesk_dbResult($res);
}
if ( ! isset($hesk_settings['priorities'])) {
require_once(HESK_PATH . 'inc/priorities.inc.php');
}
if ( ! hesk_is_valid_priority_id($priority)) {
$priority = array_keys($hesk_settings['priorities'])[0];
} else {
$priority = intval($priority);
}
return $priority;
} // END hesk_getCategoryPriority()
function hesk_verifyCategory($any_type=0)
{
global $hesk_settings, $hesklang, $hesk_db_link, $hesk_error_buffer, $tmpvar;
// Verify just by public or any category type?
$type = $any_type ? " 1 " : " `type`='0' ";
// Does the category exist?
$res = hesk_dbQuery("SELECT `name`, `autoassign` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."categories` WHERE `id`='" . $tmpvar['category'] . "' AND {$type} LIMIT 1");
if ( hesk_dbNumRows($res) == 1 )
{
$hesk_settings['category_data'][$tmpvar['category']] = hesk_dbFetchAssoc($res);
return true;
}
// OK, something wrong with the category. Get a list of categories to check few things
$res = hesk_dbQuery("SELECT `id`, `name`, `autoassign` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."categories` WHERE {$type} ORDER BY `id` ASC");
$num = hesk_dbNumRows($res);
// If more than 1 choice is available, let the user choose
if ($num > 1)
{
$hesk_error_buffer['category'] = $hesklang['sel_app_cat'];
return false;
}
// Exactly one category is available, use it
elseif ($num == 1)
{
$tmp = hesk_dbFetchAssoc($res);
$tmpvar['category'] = $tmp['id'];
$hesk_settings['category_data'][$tmpvar['category']] = $tmp;
return true;
}
// No category is available, use the first one we find (should be ID 1)
else
{
$res = hesk_dbQuery("SELECT `id`, `name`, `autoassign` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."categories` ORDER BY `id` ASC LIMIT 1");
if ( hesk_dbNumRows($res) == 1 )
{
$tmp = hesk_dbFetchAssoc($res);
$tmpvar['category'] = $tmp['id'];
$hesk_settings['category_data'][$tmpvar['category']] = $tmp;
}
else
{
// What the ...? No categories exist??? You know what, just error out...
hesk_error($hesklang['int_error'] . ': ' . $hesklang['cat_not_found']);
}
}
} // END hesk_verifyCategory()
// The following code has been borrowed from Wordpress
// Credits: http://wordpress.org
function remove_accents($string) {
if ( !preg_match('/[\x80-\xff]/', $string) )
return $string;
if (seems_utf8($string)) {
$chars = array(
// Decompositions for Latin-1 Supplement
chr(194).chr(170) => 'a', chr(194).chr(186) => 'o',
chr(195).chr(128) => 'A', chr(195).chr(129) => 'A',
chr(195).chr(130) => 'A', chr(195).chr(131) => 'A',
chr(195).chr(132) => 'A', chr(195).chr(133) => 'A',
chr(195).chr(134) => 'AE',chr(195).chr(135) => 'C',
chr(195).chr(136) => 'E', chr(195).chr(137) => 'E',
chr(195).chr(138) => 'E', chr(195).chr(139) => 'E',
chr(195).chr(140) => 'I', chr(195).chr(141) => 'I',
chr(195).chr(142) => 'I', chr(195).chr(143) => 'I',
chr(195).chr(144) => 'D', chr(195).chr(145) => 'N',
chr(195).chr(146) => 'O', chr(195).chr(147) => 'O',
chr(195).chr(148) => 'O', chr(195).chr(149) => 'O',
chr(195).chr(150) => 'O', chr(195).chr(153) => 'U',
chr(195).chr(154) => 'U', chr(195).chr(155) => 'U',
chr(195).chr(156) => 'U', chr(195).chr(157) => 'Y',
chr(195).chr(158) => 'TH',chr(195).chr(159) => 's',
chr(195).chr(160) => 'a', chr(195).chr(161) => 'a',
chr(195).chr(162) => 'a', chr(195).chr(163) => 'a',
chr(195).chr(164) => 'a', chr(195).chr(165) => 'a',
chr(195).chr(166) => 'ae',chr(195).chr(167) => 'c',
chr(195).chr(168) => 'e', chr(195).chr(169) => 'e',
chr(195).chr(170) => 'e', chr(195).chr(171) => 'e',
chr(195).chr(172) => 'i', chr(195).chr(173) => 'i',
chr(195).chr(174) => 'i', chr(195).chr(175) => 'i',
chr(195).chr(176) => 'd', chr(195).chr(177) => 'n',
chr(195).chr(178) => 'o', chr(195).chr(179) => 'o',
chr(195).chr(180) => 'o', chr(195).chr(181) => 'o',
chr(195).chr(182) => 'o', chr(195).chr(184) => 'o',
chr(195).chr(185) => 'u', chr(195).chr(186) => 'u',
chr(195).chr(187) => 'u', chr(195).chr(188) => 'u',
chr(195).chr(189) => 'y', chr(195).chr(190) => 'th',
chr(195).chr(191) => 'y', chr(195).chr(152) => 'O',
// Decompositions for Latin Extended-A
chr(196).chr(128) => 'A', chr(196).chr(129) => 'a',
chr(196).chr(130) => 'A', chr(196).chr(131) => 'a',
chr(196).chr(132) => 'A', chr(196).chr(133) => 'a',
chr(196).chr(134) => 'C', chr(196).chr(135) => 'c',
chr(196).chr(136) => 'C', chr(196).chr(137) => 'c',
chr(196).chr(138) => 'C', chr(196).chr(139) => 'c',
chr(196).chr(140) => 'C', chr(196).chr(141) => 'c',
chr(196).chr(142) => 'D', chr(196).chr(143) => 'd',
chr(196).chr(144) => 'D', chr(196).chr(145) => 'd',
chr(196).chr(146) => 'E', chr(196).chr(147) => 'e',
chr(196).chr(148) => 'E', chr(196).chr(149) => 'e',
chr(196).chr(150) => 'E', chr(196).chr(151) => 'e',
chr(196).chr(152) => 'E', chr(196).chr(153) => 'e',
chr(196).chr(154) => 'E', chr(196).chr(155) => 'e',
chr(196).chr(156) => 'G', chr(196).chr(157) => 'g',
chr(196).chr(158) => 'G', chr(196).chr(159) => 'g',
chr(196).chr(160) => 'G', chr(196).chr(161) => 'g',
chr(196).chr(162) => 'G', chr(196).chr(163) => 'g',
chr(196).chr(164) => 'H', chr(196).chr(165) => 'h',
chr(196).chr(166) => 'H', chr(196).chr(167) => 'h',
chr(196).chr(168) => 'I', chr(196).chr(169) => 'i',
chr(196).chr(170) => 'I', chr(196).chr(171) => 'i',
chr(196).chr(172) => 'I', chr(196).chr(173) => 'i',
chr(196).chr(174) => 'I', chr(196).chr(175) => 'i',
chr(196).chr(176) => 'I', chr(196).chr(177) => 'i',
chr(196).chr(178) => 'IJ',chr(196).chr(179) => 'ij',
chr(196).chr(180) => 'J', chr(196).chr(181) => 'j',
chr(196).chr(182) => 'K', chr(196).chr(183) => 'k',
chr(196).chr(184) => 'k', chr(196).chr(185) => 'L',
chr(196).chr(186) => 'l', chr(196).chr(187) => 'L',
chr(196).chr(188) => 'l', chr(196).chr(189) => 'L',
chr(196).chr(190) => 'l', chr(196).chr(191) => 'L',
chr(197).chr(128) => 'l', chr(197).chr(129) => 'L',
chr(197).chr(130) => 'l', chr(197).chr(131) => 'N',
chr(197).chr(132) => 'n', chr(197).chr(133) => 'N',
chr(197).chr(134) => 'n', chr(197).chr(135) => 'N',
chr(197).chr(136) => 'n', chr(197).chr(137) => 'N',
chr(197).chr(138) => 'n', chr(197).chr(139) => 'N',
chr(197).chr(140) => 'O', chr(197).chr(141) => 'o',
chr(197).chr(142) => 'O', chr(197).chr(143) => 'o',
chr(197).chr(144) => 'O', chr(197).chr(145) => 'o',
chr(197).chr(146) => 'OE',chr(197).chr(147) => 'oe',
chr(197).chr(148) => 'R',chr(197).chr(149) => 'r',
chr(197).chr(150) => 'R',chr(197).chr(151) => 'r',
chr(197).chr(152) => 'R',chr(197).chr(153) => 'r',
chr(197).chr(154) => 'S',chr(197).chr(155) => 's',
chr(197).chr(156) => 'S',chr(197).chr(157) => 's',
chr(197).chr(158) => 'S',chr(197).chr(159) => 's',
chr(197).chr(160) => 'S', chr(197).chr(161) => 's',
chr(197).chr(162) => 'T', chr(197).chr(163) => 't',
chr(197).chr(164) => 'T', chr(197).chr(165) => 't',
chr(197).chr(166) => 'T', chr(197).chr(167) => 't',
chr(197).chr(168) => 'U', chr(197).chr(169) => 'u',
chr(197).chr(170) => 'U', chr(197).chr(171) => 'u',
chr(197).chr(172) => 'U', chr(197).chr(173) => 'u',
chr(197).chr(174) => 'U', chr(197).chr(175) => 'u',
chr(197).chr(176) => 'U', chr(197).chr(177) => 'u',
chr(197).chr(178) => 'U', chr(197).chr(179) => 'u',
chr(197).chr(180) => 'W', chr(197).chr(181) => 'w',
chr(197).chr(182) => 'Y', chr(197).chr(183) => 'y',
chr(197).chr(184) => 'Y', chr(197).chr(185) => 'Z',
chr(197).chr(186) => 'z', chr(197).chr(187) => 'Z',
chr(197).chr(188) => 'z', chr(197).chr(189) => 'Z',
chr(197).chr(190) => 'z', chr(197).chr(191) => 's',
// Decompositions for Latin Extended-B
chr(200).chr(152) => 'S', chr(200).chr(153) => 's',
chr(200).chr(154) => 'T', chr(200).chr(155) => 't',
// Euro Sign
chr(226).chr(130).chr(172) => 'E',
// GBP (Pound) Sign
chr(194).chr(163) => '',
// Vowels with diacritic (Vietnamese)
// unmarked
chr(198).chr(160) => 'O', chr(198).chr(161) => 'o',
chr(198).chr(175) => 'U', chr(198).chr(176) => 'u',
// grave accent
chr(225).chr(186).chr(166) => 'A', chr(225).chr(186).chr(167) => 'a',
chr(225).chr(186).chr(176) => 'A', chr(225).chr(186).chr(177) => 'a',
chr(225).chr(187).chr(128) => 'E', chr(225).chr(187).chr(129) => 'e',
chr(225).chr(187).chr(146) => 'O', chr(225).chr(187).chr(147) => 'o',
chr(225).chr(187).chr(156) => 'O', chr(225).chr(187).chr(157) => 'o',
chr(225).chr(187).chr(170) => 'U', chr(225).chr(187).chr(171) => 'u',
chr(225).chr(187).chr(178) => 'Y', chr(225).chr(187).chr(179) => 'y',
// hook
chr(225).chr(186).chr(162) => 'A', chr(225).chr(186).chr(163) => 'a',
chr(225).chr(186).chr(168) => 'A', chr(225).chr(186).chr(169) => 'a',
chr(225).chr(186).chr(178) => 'A', chr(225).chr(186).chr(179) => 'a',
chr(225).chr(186).chr(186) => 'E', chr(225).chr(186).chr(187) => 'e',
chr(225).chr(187).chr(130) => 'E', chr(225).chr(187).chr(131) => 'e',
chr(225).chr(187).chr(136) => 'I', chr(225).chr(187).chr(137) => 'i',
chr(225).chr(187).chr(142) => 'O', chr(225).chr(187).chr(143) => 'o',
chr(225).chr(187).chr(148) => 'O', chr(225).chr(187).chr(149) => 'o',
chr(225).chr(187).chr(158) => 'O', chr(225).chr(187).chr(159) => 'o',
chr(225).chr(187).chr(166) => 'U', chr(225).chr(187).chr(167) => 'u',
chr(225).chr(187).chr(172) => 'U', chr(225).chr(187).chr(173) => 'u',
chr(225).chr(187).chr(182) => 'Y', chr(225).chr(187).chr(183) => 'y',
// tilde
chr(225).chr(186).chr(170) => 'A', chr(225).chr(186).chr(171) => 'a',
chr(225).chr(186).chr(180) => 'A', chr(225).chr(186).chr(181) => 'a',
chr(225).chr(186).chr(188) => 'E', chr(225).chr(186).chr(189) => 'e',
chr(225).chr(187).chr(132) => 'E', chr(225).chr(187).chr(133) => 'e',
chr(225).chr(187).chr(150) => 'O', chr(225).chr(187).chr(151) => 'o',
chr(225).chr(187).chr(160) => 'O', chr(225).chr(187).chr(161) => 'o',
chr(225).chr(187).chr(174) => 'U', chr(225).chr(187).chr(175) => 'u',
chr(225).chr(187).chr(184) => 'Y', chr(225).chr(187).chr(185) => 'y',
// acute accent
chr(225).chr(186).chr(164) => 'A', chr(225).chr(186).chr(165) => 'a',
chr(225).chr(186).chr(174) => 'A', chr(225).chr(186).chr(175) => 'a',
chr(225).chr(186).chr(190) => 'E', chr(225).chr(186).chr(191) => 'e',
chr(225).chr(187).chr(144) => 'O', chr(225).chr(187).chr(145) => 'o',
chr(225).chr(187).chr(154) => 'O', chr(225).chr(187).chr(155) => 'o',
chr(225).chr(187).chr(168) => 'U', chr(225).chr(187).chr(169) => 'u',
// dot below
chr(225).chr(186).chr(160) => 'A', chr(225).chr(186).chr(161) => 'a',
chr(225).chr(186).chr(172) => 'A', chr(225).chr(186).chr(173) => 'a',
chr(225).chr(186).chr(182) => 'A', chr(225).chr(186).chr(183) => 'a',
chr(225).chr(186).chr(184) => 'E', chr(225).chr(186).chr(185) => 'e',
chr(225).chr(187).chr(134) => 'E', chr(225).chr(187).chr(135) => 'e',
chr(225).chr(187).chr(138) => 'I', chr(225).chr(187).chr(139) => 'i',
chr(225).chr(187).chr(140) => 'O', chr(225).chr(187).chr(141) => 'o',
chr(225).chr(187).chr(152) => 'O', chr(225).chr(187).chr(153) => 'o',
chr(225).chr(187).chr(162) => 'O', chr(225).chr(187).chr(163) => 'o',
chr(225).chr(187).chr(164) => 'U', chr(225).chr(187).chr(165) => 'u',
chr(225).chr(187).chr(176) => 'U', chr(225).chr(187).chr(177) => 'u',
chr(225).chr(187).chr(180) => 'Y', chr(225).chr(187).chr(181) => 'y',
// Vowels with diacritic (Chinese, Hanyu Pinyin)
chr(201).chr(145) => 'a',
// macron
chr(199).chr(149) => 'U', chr(199).chr(150) => 'u',
// acute accent
chr(199).chr(151) => 'U', chr(199).chr(152) => 'u',
// caron
chr(199).chr(141) => 'A', chr(199).chr(142) => 'a',
chr(199).chr(143) => 'I', chr(199).chr(144) => 'i',
chr(199).chr(145) => 'O', chr(199).chr(146) => 'o',
chr(199).chr(147) => 'U', chr(199).chr(148) => 'u',
chr(199).chr(153) => 'U', chr(199).chr(154) => 'u',
// grave accent
chr(199).chr(155) => 'U', chr(199).chr(156) => 'u',
);
$string = strtr($string, $chars);
} else {
// Assume ISO-8859-1 if not UTF-8
$chars['in'] = chr(128).chr(131).chr(138).chr(142).chr(154).chr(158)
.chr(159).chr(162).chr(165).chr(181).chr(192).chr(193).chr(194)
.chr(195).chr(196).chr(197).chr(199).chr(200).chr(201).chr(202)
.chr(203).chr(204).chr(205).chr(206).chr(207).chr(209).chr(210)
.chr(211).chr(212).chr(213).chr(214).chr(216).chr(217).chr(218)
.chr(219).chr(220).chr(221).chr(224).chr(225).chr(226).chr(227)
.chr(228).chr(229).chr(231).chr(232).chr(233).chr(234).chr(235)
.chr(236).chr(237).chr(238).chr(239).chr(241).chr(242).chr(243)
.chr(244).chr(245).chr(246).chr(248).chr(249).chr(250).chr(251)
.chr(252).chr(253).chr(255);
$chars['out'] = "EfSZszYcYuAAAAAACEEEEIIIINOOOOOOUUUUYaaaaaaceeeeiiiinoooooouuuuyy";
$string = strtr($string, $chars['in'], $chars['out']);
$double_chars['in'] = array(chr(140), chr(156), chr(198), chr(208), chr(222), chr(223), chr(230), chr(240), chr(254));
$double_chars['out'] = array('OE', 'oe', 'AE', 'DH', 'TH', 'ss', 'ae', 'dh', 'th');
$string = str_replace($double_chars['in'], $double_chars['out'], $string);
}
return $string;
}
function seems_utf8($str) {
$length = strlen($str);
for ($i=0; $i < $length; $i++) {
$c = ord($str[$i]);
if ($c < 0x80) $n = 0; # 0bbbbbbb
elseif (($c & 0xE0) == 0xC0) $n=1; # 110bbbbb
elseif (($c & 0xF0) == 0xE0) $n=2; # 1110bbbb
elseif (($c & 0xF8) == 0xF0) $n=3; # 11110bbb
elseif (($c & 0xFC) == 0xF8) $n=4; # 111110bb
elseif (($c & 0xFE) == 0xFC) $n=5; # 1111110b
else return false; # Does not match any model
for ($j=0; $j<$n; $j++) { # n bytes matching 10bbbbbb follow ?
if ((++$i == $length) || ((ord($str[$i]) & 0xC0) != 0x80))
return false;
}
}
return true;
}
function utf8_uri_encode( $utf8_string, $length = 0 ) {
$unicode = '';
$values = array();
$num_octets = 1;
$unicode_length = 0;
$string_length = strlen( $utf8_string );
for ($i = 0; $i < $string_length; $i++ ) {
$value = ord( $utf8_string[ $i ] );
if ( $value < 128 ) {
if ( $length && ( $unicode_length >= $length ) )
break;
$unicode .= chr($value);
$unicode_length++;
} else {
if ( count( $values ) == 0 ) $num_octets = ( $value < 224 ) ? 2 : 3;
$values[] = $value;
if ( $length && ( $unicode_length + ($num_octets * 3) ) > $length )
break;
if ( count( $values ) == $num_octets ) {
if ($num_octets == 3) {
$unicode .= '%' . dechex($values[0]) . '%' . dechex($values[1]) . '%' . dechex($values[2]);
$unicode_length += 9;
} else {
$unicode .= '%' . dechex($values[0]) . '%' . dechex($values[1]);
$unicode_length += 6;
}
$values = array();
$num_octets = 1;
}
}
}
return $unicode;
}
wget 'https://lists2.roe3.org/hesk/inc/prepare_ticket_export.inc.php'
<?php
/**
*
* This file is part of HESK - PHP Help Desk Software.
*
* (c) Copyright Klemen Stirn. All rights reserved.
* https://www.hesk.com
*
* For the full copyright and license agreement information visit
* https://www.hesk.com/eula.php
*
*/
/* Check if this is a valid include */
if (!defined('IN_SCRIPT')) {die('Invalid attempt');}
/* Acceptable $sort values and default asc(1)/desc(0) setting */
$sort_possible = array(
'trackid' => 1,
'lastchange' => 0,
'name' => 1,
'subject' => 1,
'status' => 1,
'lastreplier' => 1,
'priority' => 1,
'category' => 1,
'dt' => 0,
'id' => 1,
);
// These values should have collate appended in SQL
$sort_collation = array(
'name',
'subject',
);
// DATE
$sql .= " AND DATE(`dt`) BETWEEN '" . hesk_dbEscape($date_from) . "' AND '" . hesk_dbEscape($date_to) . "' ";
// Start the order by part of the SQL query
$sql .= " ORDER BY ";
/* Sort by which field? */
if (isset($_GET['sort']) && ! is_array($_GET['sort']) && isset($sort_possible[$_GET['sort']]))
{
$sort = hesk_input($_GET['sort']);
$sql .= ' `'.hesk_dbEscape($sort).'` ';
// Need to set MySQL collation?
if ( in_array($_GET['sort'], $sort_collation) )
{
$sql .= " COLLATE '" . hesk_dbCollate() . "' ";
}
}
else
{
/* Default sorting by ticket status */
$sql .= ' `id` ';
$sort = 'id';
}
/* Ascending or Descending? */
if (isset($_GET['asc']) && intval($_GET['asc'])==0)
{
$sql .= ' DESC ';
$asc = 0;
$asc_rev = 1;
$sort_possible[$sort] = 1;
}
else
{
$sql .= ' ASC ';
$asc = 1;
$asc_rev = 0;
if (!isset($_GET['asc']))
{
$is_default = 1;
}
$sort_possible[$sort] = 0;
}
// Options
$history = hesk_GET('history') ? 1 : 0;
$replies = hesk_GET('replies') ? 1 : 0;
# Uncomment for debugging purposes
# echo "SQL: $sql<br>";
wget 'https://lists2.roe3.org/hesk/inc/prepare_ticket_search.inc.php'
<?php
/**
*
* This file is part of HESK - PHP Help Desk Software.
*
* (c) Copyright Klemen Stirn. All rights reserved.
* https://www.hesk.com
*
* For the full copyright and license agreement information visit
* https://www.hesk.com/eula.php
*
*/
/* Check if this is a valid include */
if (!defined('IN_SCRIPT')) {die('Invalid attempt');}
$tmp = intval( hesk_GET('limit') );
$maxresults = ($tmp > 0) ? $tmp : $hesk_settings['max_listings'];
$tmp = intval( hesk_GET('page', 1) );
$page = ($tmp > 1) ? $tmp : 1;
/* Acceptable $sort values and default asc(1)/desc(0) setting */
$sort_possible = array();
foreach (array_keys($hesk_settings['possible_ticket_list']) as $key)
{
$sort_possible[$key] = 1;
}
$sort_possible['priority'] = 1;
$sort_possible['dt'] = 0;
$sort_possible['lastchange'] = 0;
/* These values should have collate appended in SQL */
$sort_collation = array(
'name',
'subject',
);
for ($i=1;$i<=100;$i++) {
$sort_collation[] = 'custom'.$i;
}
/* Acceptable $group values and default asc(1)/desc(0) setting */
$group_possible = array(
'owner' => 1,
'priority' => 1,
'category' => 1,
);
/* Start the order by part of the SQL query */
$sql .= " ORDER BY ";
// Group parameter
$group = hesk_GET('g');
if ( ! isset($group_possible[$group]))
{
$group = '';
}
// Sort parameter
$sort = hesk_GET('sort', 'status');
if ( ! isset($sort_possible[$sort]))
{
$sort = 'status';
}
// Group tickets?
if ($group != '')
{
if ($group == 'priority' && $sort == 'priority')
{
// No need to group by priority if we are already sorting by priority
}
elseif ($group == 'owner')
{
// If group by owner place own tickets on top
$sql .= " CASE WHEN `owner` = '".intval($_SESSION['id'])."' THEN 1 ELSE 0 END DESC, `owner` ASC, ";
}
elseif ($group == 'category' && $sort == 'category')
{
// No need to group by category if we are already sorting by category
}
elseif ($group == 'category')
{
// Get list of categories
$hesk_settings['categories'] = array();
$res2 = hesk_dbQuery('SELECT `id`, `name` FROM `'.hesk_dbEscape($hesk_settings['db_pfix']).'categories` WHERE ' . hesk_myCategories('id') . ' ORDER BY `cat_order` ASC');
while ($row=hesk_dbFetchAssoc($res2))
{
$hesk_settings['categories'][$row['id']] = $row['name'];
}
// Make sure categories are in correct order
$sql .= ' FIELD(`category`, ' . preg_replace('/[^0-9,]/', '', implode(',' , array_keys($hesk_settings['categories']))) . '), ';
}
else
{
$sql .= ' `'.hesk_dbEscape($group).'` ';
$sql .= $group_possible[$group] ? 'ASC, ' : 'DESC, ';
}
}
// Show critical tickets always on top? Default: yes
$cot = hesk_GET('cot') == 1 ? 1 : 0;
if (!$cot)
{
$sql .= " CASE WHEN `priority` = '0' THEN 1 ELSE 0 END DESC , ";
}
// Prepare sorting
if ($sort == 'category')
{
// Get list of categories
$hesk_settings['categories'] = array();
$res2 = hesk_dbQuery('SELECT `id`, `name` FROM `'.hesk_dbEscape($hesk_settings['db_pfix']).'categories` WHERE ' . hesk_myCategories('id') . ' ORDER BY `cat_order` ASC');
while ($row=hesk_dbFetchAssoc($res2))
{
$hesk_settings['categories'][$row['id']] = $row['name'];
}
// Make sure categories are in correct order
$sql .= ' FIELD(`category`, ' . preg_replace('/[^0-9,]/', '', implode(',' , array_keys($hesk_settings['categories']))) . ') ';
}
else
{
if ($sort === 'lastreplier') {
$sql .= " CASE WHEN `lastreplier` = '0' THEN COALESCE(`lastreplier_customer`.`name`, `customer`.`name`) ELSE `lastreplier_staff`.`name` END ";
} elseif ($sort === 'name') {
$sql .= " COALESCE(`customer`.`name`, '".hesk_dbEscape($hesklang['anon_name'])."') ";
} elseif ($sort === 'priority') {
$sql .= ' `priority_order` ';
} else {
$sql .= ' `'.hesk_dbEscape($sort).'` ';
}
// Need to set MySQL collation?
if ( in_array($sort, $sort_collation) )
{
$sql .= " COLLATE '" . hesk_dbCollate() . "' ";
}
}
/* Ascending or Descending? */
if (isset($_GET['asc']) && intval($_GET['asc'])==0)
{
$sql .= ' DESC ';
$asc = 0;
$asc_rev = 1;
$sort_possible[$sort] = 1;
}
else
{
$sql .= ' ASC ';
$asc = 1;
$asc_rev = 0;
if (!isset($_GET['asc']))
{
$is_default = 1;
}
$sort_possible[$sort] = 0;
}
/* In the end same results should always be sorted by priority */
if ($sort != 'priority')
{
$sql .= ' , `priority_order` DESC ';
}
// Always sort by ID to make sure chached results don't cause different results between pages
if ($sort != 'id') {
$sql .= ' , `id` ASC ';
}
# Uncomment for debugging purposes
# echo "SQL: $sql<br>";
wget 'https://lists2.roe3.org/hesk/inc/print_group.inc.php'
<?php
/**
*
* This file is part of HESK - PHP Help Desk Software.
*
* (c) Copyright Klemen Stirn. All rights reserved.
* https://www.hesk.com
*
* For the full copyright and license agreement information visit
* https://www.hesk.com/eula.php
*
*/
/* Check if this is a valid include */
if (!defined('IN_SCRIPT')) {die('Invalid attempt');}
if ( ! function_exists('hesk_get_priority_name'))
{
require_once(HESK_PATH . 'inc/priorities.inc.php');
}
/* Group tickets into tables */
if ($group == 'owner')
{
if ($ticket['owner'] != $group_tmp)
{
$group_tmp = $ticket['owner'];
if ($is_table)
{
echo '</tbody></table></div>';
}
if ($space)
{
echo ' <br />';
}
if (empty($group_tmp) || ! isset($admins[$group_tmp]))
{
echo '<p>'.$hesklang['gbou'].'</p>';
$space++;
}
else
{
if ($group_tmp == $_SESSION['id'])
{
echo '<p>'.$hesklang['gbom'].'</p>';
$space++;
}
else
{
echo '<p>'.sprintf($hesklang['gboo'],$admins[$group_tmp]).'</p>';
$space++;
}
}
hesk_print_list_head();
$is_table = 1;
}
} // END if 'owner'
elseif ($group == 'priority')
{
$tmp = hesk_get_priority_name($ticket['priority']);
if ($ticket['priority'] != $group_tmp)
{
$group_tmp = $ticket['priority'];
if ($is_table)
{
echo '</tbody></table></div>';
}
if ($space)
{
echo ' <br />';
}
echo '<p>'.$hesklang['priority'].': <b>'.$tmp.'</b></p>';
$space++;
hesk_print_list_head();
$is_table = 1;
}
} // END elseif 'priority'
else
{
if ($ticket['category'] != $group_tmp)
{
$group_tmp = $ticket['category'];
if ($is_table)
{
echo '</tbody></table></div>';
}
if ($space)
{
echo ' <br />';
}
$tmp = isset($hesk_settings['categories'][$group_tmp]) ? $hesk_settings['categories'][$group_tmp] : '('.$hesklang['unknown'].')';
echo '<p>'.$hesklang['category'].': <b>'.$tmp.'</b></p>';
$space++;
hesk_print_list_head();
$is_table = 1;
}
} // END else ('category')
wget 'https://lists2.roe3.org/hesk/inc/print_template.inc.php'
<?php
/**
*
* This file is part of HESK - PHP Help Desk Software.
*
* (c) Copyright Klemen Stirn. All rights reserved.
* https://www.hesk.com
*
* For the full copyright and license agreement information visit
* https://www.hesk.com/eula.php
*
*/
/* Check if this is a valid include */
if (!defined('IN_SCRIPT')) {die('Invalid attempt');}
if ( ! function_exists('hesk_get_priority_name'))
{
require_once(HESK_PATH . 'inc/priorities.inc.php');
}
$formatted_tickets = array();
foreach ($tickets as $ticket) {
// Ticket priority
$priority_name = hesk_get_priority_name($ticket['priority']);
$ticket['priority'] = ($ticket['priority'] == 0 || $ticket['priority'] == 1) ? '<b>'.$priority_name.'</b>' : $priority_name;
// Replies
$replies = array();
foreach ($ticket['replies'] as $reply) {
$reply['dt'] = hesk_date($reply['dt'], true);
$reply['message'] = hesk_unhortenUrl($reply['message']);
if ($reply['name'] === null) {
if (intval($reply['staffid']) > 0) {
$reply['name'] = $hesklang['staff_deleted'];
} else {
$reply['name'] = $hesklang['anon_name'];
}
}
$replies[] = $reply;
}
$ticket['replies'] = $replies;
// Set last replier name
if ($ticket['lastreplier']) {
if (empty($ticket['repliername'])) {
$ticket['repliername'] = $hesklang['staff'];
}
} else {
if (!function_exists('hesk_get_customers_for_ticket')) {
require_once(HESK_PATH . 'inc/customer_accounts.inc.php');
}
// Get the last reply and pull its name
$reply_count = count($ticket['replies']);
if ($reply_count > 0) {
$last_reply = $ticket['replies'][$reply_count - 1];
$customers = hesk_get_customers_for_ticket($ticket['id']);
$customer_names = array_map(function($customer) { return $customer['name']; }, $customers);
$ticket['repliername'] = (strlen($last_reply['name']) ? $last_reply['name'] : ( ! empty($last_reply['email']) ? $last_reply['email'] : $hesklang['pde'] ));
} else {
$ticket['repliername'] = '';
}
}
// Other variables that need processing
$ticket['dt'] = hesk_date($ticket['dt'], true);
$ticket['lastchange'] = hesk_date($ticket['lastchange'], true);
$ticket['due_date'] = hesk_format_due_date($ticket['due_date']);
$random=mt_rand(10000,99999);
$ticket['status'] = hesk_get_status_name($ticket['status']);
if ($ticket['owner'] && ! empty($_SESSION['id'])) {
$owner_array = hesk_getStaffNameArray($ticket['owner']);
$ticket['owner'] = $owner_array['name'];
} else {
$ticket['owner'] = '';
}
// Custom fields
$custom_fields = array();
foreach ($hesk_settings['custom_fields'] as $k=>$v) {
if (($v['use'] == 1 || (!empty($_SESSION['id']) && $v['use'] == 2)) && (strlen($ticket[$k]) || hesk_is_custom_field_in_category($k, $ticket['category']))) {
if ($v['type'] == 'date') {
$ticket[$k] = hesk_custom_date_display_format($ticket[$k], $v['value']['date_format']);
}
$custom_fields[] = array(
'name' => $v['name:'],
'value' => hesk_unhortenUrl($ticket[$k])
);
}
}
$ticket['custom_fields'] = $custom_fields;
// Initial ticket message
if ($ticket['message'] != '')
{
$ticket['message'] = hesk_unhortenUrl($ticket['message']);
}
$formatted_tickets[] = $ticket;
}
$hesk_settings['render_template'](TEMPLATE_PATH . 'print-ticket.php', array(
'tickets' => $formatted_tickets,
'showStaffOnlyFields' => !empty($_SESSION['id'])
), true, true);
wget 'https://lists2.roe3.org/hesk/inc/print_tickets.inc.php'
<?php
/**
*
* This file is part of HESK - PHP Help Desk Software.
*
* (c) Copyright Klemen Stirn. All rights reserved.
* https://www.hesk.com
*
* For the full copyright and license agreement information visit
* https://www.hesk.com/eula.php
*
*/
/* Check if this is a valid include */
if (!defined('IN_SCRIPT')) {die('Invalid attempt');}
// Load priorities
require_once(HESK_PATH . 'inc/priorities.inc.php');
// Load custom fields
require_once(HESK_PATH . 'inc/custom_fields.inc.php');
// Load statuses
require_once(HESK_PATH . 'inc/statuses.inc.php');
// Prepare total counts that we will use later
$totals = array(
'all' => 0,
'open' => 0,
'resolved' => 0,
'filtered' => array(
'all' => 0,
'open' => 0,
'assigned_to_me' => 0,
'assigned_to_others' => 0,
'assigned_to_others_by_me' => 0,
'unassigned' => 0,
'bookmarks' => 0,
'due_soon' => 0,
'overdue' => 0,
'by_status' => array(),
'collaborator' => 0,
'collaborator_assigned_to_me' => 0,
'collaborator_assigned_to_others' => 0,
'collaborator_assigned_to_others_by_me' => 0,
'collaborator_unassigned' => 0,
),
);
// Let's check some permissions
$can_view_unassigned = hesk_checkPermission('can_view_unassigned',0);
$can_view_ass_others = hesk_checkPermission('can_view_ass_others',0);
$can_view_ass_by = hesk_checkPermission('can_view_ass_by',0);
// Is this a quick link?
$is_quick_link = hesk_GET('ql', false);
// This will get number of ALL tickets this user has access to
$sql = "SELECT COUNT(DISTINCT `ticket`.`id`) AS `cnt`, IF (`status` = 3, 1, 0) AS `is_resolved`
FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` AS `ticket`
LEFT JOIN `".hesk_dbEscape($hesk_settings['db_pfix'])."ticket_to_collaborator` AS `w` ON (`ticket`.`id` = `w`.`ticket_id` AND `w`.`user_id` = ".intval($_SESSION['id']).")
WHERE
(
`w`.`user_id`=".intval($_SESSION['id'])."
OR
(".hesk_myOwnership().")
)
AND ".hesk_myCategories()."
GROUP BY `is_resolved`";
$res = hesk_dbQuery($sql);
while ($row = hesk_dbFetchAssoc($res))
{
// Total tickets found
$totals['all'] += $row['cnt'];
// Total by status
if ($row['is_resolved'])
{
$totals['resolved'] += $row['cnt'];
}
else
{
$totals['open'] = $row['cnt'];
}
}
$sql_final = ''; // SQL that fetches ticket data from the database
$sql_count = ''; // SQL that runs a quick count of tickets by status, due date and ownership
$sql_collaborator = ''; // SQL that runs a quick count of collaborated tickets
$sql_customer_count = "SELECT COUNT(1) FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."ticket_to_customer` AS `ticket_to_customer_names`
INNER JOIN `".hesk_dbEscape($hesk_settings['db_pfix'])."customers` `customer_names`
ON `ticket_to_customer_names`.`customer_id` = `customer_names`.`id`
WHERE `ticket_id` = `ticket`.`id`";
$sql_email_count = "SELECT COUNT(1) FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."ticket_to_customer` AS `ticket_to_customer_emails`
INNER JOIN `".hesk_dbEscape($hesk_settings['db_pfix'])."customers` `customer_emails`
ON `ticket_to_customer_emails`.`customer_id` = `customer_emails`.`id`
WHERE `ticket_id` = `ticket`.`id`
AND COALESCE(`customer_emails`.`email`, '') <> ''";
// This SQL code will be used to retrieve results
$sql_final = "SELECT
`ticket`.`id` AS `id`,
`trackid`,
COALESCE(`customer`.`name`, '".hesk_dbEscape($hesklang['anon_name'])."') AS `name`,
COALESCE(`customer`.`email`, '".hesk_dbEscape($hesklang['anon_email'])."') AS `email`,
({$sql_customer_count}) AS `customer_count`,
({$sql_email_count}) AS `email_count`,
`category`,
`priority`,
`priority_order` AS `vv`,
`subject`,
LEFT(`message`, 400) AS `message`,
`dt`,
`lastchange`,
`firstreply`,
`closedat`,
`status`,
`openedby`,
`firstreplyby`,
`closedby`,
`ticket`.`replies`,
`staffreplies`,
`owner`,
`time_worked`,
`due_date`,
`lastreplier`,
`lastreplier_customer`.`name` AS `lastreplier_customername`,
`replierid`,
`archive`,
`locked`,
CASE WHEN `bookmarks`.`ticket_id` IS NOT NULL THEN 1 ELSE 0 END AS `is_bookmark`
";
foreach ($hesk_settings['custom_fields'] as $k=>$v)
{
if ($v['use'])
{
$sql_final .= ", `".$k."`";
}
}
$sql_final.= " FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` AS `ticket`
LEFT JOIN (
SELECT DISTINCT `ticket_id`, `user_id`
FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."ticket_to_collaborator`
WHERE `user_id` = ".intval($_SESSION['id'])."
) AS `w` ON (`ticket`.`id` = `w`.`ticket_id`) ";
$sql_final.= "
LEFT JOIN `".hesk_dbEscape($hesk_settings['db_pfix'])."customers` AS `customer`
ON `customer`.`id` = (
SELECT MIN(`customer_id`)
FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."ticket_to_customer` AS `ticket_to_customer`
WHERE `ticket_id` = `ticket`.`id`
AND `customer_type` = 'REQUESTER'
LIMIT 1
)
LEFT JOIN `".hesk_dbEscape($hesk_settings['db_pfix'])."customers` AS `lastreplier_customer`
ON `ticket`.`lastreplier` = '0'
AND `lastreplier_customer`.`id` = (
SELECT `customer_id`
FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."replies`
WHERE `replyto` = `ticket`.`id`
AND `customer_id` IS NOT NULL
ORDER BY `id` DESC
LIMIT 1)
LEFT JOIN `".hesk_dbEscape($hesk_settings['db_pfix'])."users` AS `lastreplier_staff`
ON `ticket`.`lastreplier` <> '0'
AND `ticket`.`replierid` = `lastreplier_staff`.`id`
LEFT JOIN (
SELECT DISTINCT `ticket_id`, `user_id`
FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."bookmarks`
WHERE `user_id` = ".intval($_SESSION['id'])."
) AS `bookmarks` ON (`ticket`.`id` = `bookmarks`.`ticket_id`)
LEFT JOIN `".hesk_dbEscape($hesk_settings['db_pfix'])."custom_priorities` AS `custom_priorities` ON `ticket`.`priority` = `custom_priorities`.`id`
WHERE
";
if ($is_quick_link == 'cbm') {
$sql_final.= " `w`.`user_id`=".intval($_SESSION['id'])." AND ".hesk_myCategories()." ";
} else {
$sql_final .= " ".hesk_myCategories()." AND ".hesk_myOwnership(1);
}
// This code will be used to count number of results for this specific search
$sql_count = " SELECT COUNT(DISTINCT `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets`.`id`) AS `cnt`, `status`,
IF (`owner` = " . intval($_SESSION['id']) . ", 1, IF (`owner` = 0, 0, IF (`assignedby` = " . intval($_SESSION['id']) . ", 3, 2) ) ) AS `assigned_to`,
IF (`due_date` < NOW(), 2, IF (`due_date` BETWEEN NOW() AND (NOW() + INTERVAL ".intval($hesk_settings['due_soon'])." DAY), 1, 0) ) AS `due`,
CASE WHEN `bookmarks`.`ticket_id` IS NOT NULL THEN 1 ELSE 0 END AS `is_bookmark`,
CASE WHEN `w`.`user_id` IS NOT NULL THEN 1 ELSE 0 END AS `is_collaborator`
FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets`
LEFT JOIN (
SELECT DISTINCT `ticket_id`, `user_id`
FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."ticket_to_collaborator`
WHERE `user_id` = ".intval($_SESSION['id'])."
) AS `w` ON (`".hesk_dbEscape($hesk_settings['db_pfix'])."tickets`.`id` = `w`.`ticket_id`)
LEFT JOIN (
SELECT DISTINCT `ticket_id`, `user_id`
FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."bookmarks`
WHERE `user_id` = ".intval($_SESSION['id'])."
) AS `bookmarks` ON (`".hesk_dbEscape($hesk_settings['db_pfix'])."tickets`.`id` = `bookmarks`.`ticket_id`)
WHERE ".hesk_myCategories()." AND ".hesk_myOwnership(1);
// This code will be used to count collaborated tickets for this specific search
$sql_collaborator = " SELECT COUNT(DISTINCT `ticket`.`id`) AS `cnt`
FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` AS `ticket` LEFT JOIN `".hesk_dbEscape($hesk_settings['db_pfix'])."ticket_to_collaborator` AS `w` ON (`ticket`.`id` = `w`.`ticket_id` AND `w`.`user_id` = ".intval($_SESSION['id']).")
WHERE `w`.`user_id`=".intval($_SESSION['id'])." AND ".hesk_myCategories();
// This is common SQL for all queries
$sql = "";
// Some default settings
$archive = array(1=>0,2=>0);
$s_my = array(1=>1,2=>1);
$s_ot = array(1=>1,2=>1);
$s_un = array(1=>1,2=>1);
// For some specific quick links we will ignore some filters
$ignore_category = false;
$ignore_status = false;
$ignore_owner = false;
$ignore_archive = false;
$ignore_category = false;
// -> All tickets
if ($is_quick_link == 'all')
{
$ignore_category = true;
$ignore_status = true;
$ignore_owner = true;
$ignore_archive = true;
$ignore_category = true;
}
// -> All open tickets
elseif ($is_quick_link == 'alo')
{
$ignore_category = true;
$ignore_status = true;
$ignore_owner = true;
$ignore_archive = true;
$ignore_category = true;
}
// -> Collaborated tickets
elseif ($is_quick_link == 'cbm')
{
$ignore_owner = true;
}
// --> TICKET CATEGORY
if (isset($_GET['c']) && is_array($_GET['c'])) {
$categories = [];
foreach ($_GET['c'] as $category) {
$category = intval($category);
if ($category && hesk_okCategory($category, 0) ) {
$categories[] = $category;
}
}
if ( ! $ignore_category && count($categories)) {
$sql .= " AND `category` IN (".implode(',', $categories).") ";
}
} elseif (isset($_GET['category'])) {
// Legacy, select a single category
$category = intval( hesk_GET('category', 0) );
$categories = array($category);
if ( ! $ignore_category && $category && hesk_okCategory($category, 0) ) {
$sql .= " AND `category`='{$category}' ";
}
} else {
$category = 0;
$categories = [0];
}
// Show only tagged tickets?
if ( ! $ignore_archive && ! empty($_GET['archive']) )
{
$archive[1]=1;
$sql .= " AND `archive`='1' ";
}
$sql_count .= $sql;
$sql_collaborator .= $sql;
// Ticket owner preferences
$fid = 1;
require(HESK_PATH . 'inc/assignment_search.inc.php');
// --> TICKET STATUS
$status = $hesk_settings['statuses'];
// Process statuses unless overridden with "s_all" variable
if ( ! $ignore_status && ! hesk_GET('s_all') )
{
foreach ($status as $k => $v)
{
if (empty($_GET['s'.$k]))
{
unset($status[$k]);
}
}
}
// How many statuses are we pulling out of the database?
$tmp = count($status);
// Do we need to search by status?
if ( $tmp < count($hesk_settings['statuses']) )
{
// If no statuses selected, show default (all except RESOLVED)
if ($tmp == 0)
{
$status = $hesk_settings['statuses'];
unset($status[3]);
}
// Add to the SQL
$sql .= " AND `status` IN ('" . implode("','", array_keys($status) ) . "') ";
$sql_count .= " AND `status` IN ('" . implode("','", array_keys($status) ) . "') ";
$sql_collaborator .= " AND `status` IN ('" . implode("','", array_keys($status) ) . "') ";
}
// --> TICKET PRIORITY
$possible_priority = hesk_possible_priorities();
$priority = $possible_priority;
foreach ($priority as $k => $v)
{
if (empty($_GET['p'.$k]))
{
unset($priority[$k]);
}
}
// How many priorities are we pulling out of the database?
$tmp = count($priority);
// Create the SQL based on the number of priorities we need
if ($tmp == 0 || $tmp == count($possible_priority))
{
// Nothing or all selected, no need to modify the SQL code
$priority = $possible_priority;
}
else
{
// A custom selection of priorities
$sql .= " AND `priority` IN ('" . implode("','", array_keys($priority) ) . "') ";
$sql_count .= " AND `priority` IN ('" . implode("','", array_keys($priority) ) . "') ";
$sql_collaborator .= " AND `priority` IN ('" . implode("','", array_keys($priority) ) . "') ";
}
// Due date
if ($is_quick_link == 'due')
{
$sql .= " AND `status` != 3 AND `due_date` BETWEEN NOW() AND (NOW() + INTERVAL ".intval($hesk_settings['due_soon'])." DAY) ";
}
elseif ($is_quick_link == 'ovr')
{
$sql .= " AND `status` != 3 AND `due_date` < NOW() ";
}
elseif ($is_quick_link == 'alo')
{
$sql .= " AND `status` != 3 ";
$sql_count .= " AND `status` != 3 ";
$sql_collaborator .= " AND `status` != 3 ";
}
elseif ($is_quick_link == 'bm')
{
$sql .= " AND `bookmarks`.`ticket_id` IS NOT NULL";
}
// Did the user specify a due date (either specific or a range)?
$duedate_search_type = hesk_restricted_GET('duedate_option', ['specific', 'range'], 'specific');
$duedate_input = hesk_GET('duedate_specific_date');
$duedate_amount_value = intval(hesk_GET('duedate_amount_value'));
$duedate_amount_unit = hesk_restricted_GET('duedate_amount_unit', ['day', 'week'], 'day');
if ($duedate_search_type === 'specific' && $duedate_input && hesk_datepicker_get_date($duedate_input) !== false) {
$formatted_due_date = hesk_datepicker_get_date($duedate_input);
$hesk_settings['datepicker'] = array();
$hesk_settings['datepicker']['#duedate_specific_date']['timestamp'] = $formatted_due_date->getTimestamp();;
$formatted_due_date = $formatted_due_date->format('Y-m-d');
$sql .= " AND DATE(`due_date`) = '".hesk_dbEscape($formatted_due_date)."' ";
$sql_count .= " AND DATE(`due_date`) = '".hesk_dbEscape($formatted_due_date)."' ";
$sql_collaborator .= " AND DATE(`due_date`) = '".hesk_dbEscape($formatted_due_date)."' ";
} elseif ($duedate_search_type === 'range' && $duedate_amount_value && $duedate_amount_unit) {
$unit = $duedate_amount_unit === 'day' ? 'DAY' : 'WEEK';
$sql .= " AND `due_date` BETWEEN NOW() AND (NOW() + INTERVAL {$duedate_amount_value} {$unit}) ";
$sql_count .= " AND `due_date` BETWEEN NOW() AND (NOW() + INTERVAL {$duedate_amount_value} {$unit}) ";
$sql_collaborator .= " AND `due_date` BETWEEN NOW() AND (NOW() + INTERVAL {$duedate_amount_value} {$unit}) ";
}
// That's all the SQL we need for count
$sql = $sql_final . $sql;
// Prepare variables used in search and forms
require(HESK_PATH . 'inc/prepare_ticket_search.inc.php');
// We need to group the count SQL by parameters to be able to extract different totals
$sql_count .= " GROUP BY `assigned_to`, `due`, `status`, `is_bookmark`, `is_collaborator` ";
// List tickets?
if (!isset($_SESSION['hide']['ticket_list']))
{
require(HESK_PATH . 'inc/ticket_list.inc.php');
}
wget 'https://lists2.roe3.org/hesk/inc/priorities.inc.php'
<?php
/**
*
* This file is part of HESK - PHP Help Desk Software.
*
* (c) Copyright Klemen Stirn. All rights reserved.
* https://www.hesk.com
*
* For the full copyright and license agreement information visit
* https://www.hesk.com/eula.php
*
*/
/* Check if this is a valid include */
if (!defined('IN_SCRIPT')) {die('Invalid attempt');}
// Load available priorities
hesk_load_priorities();
/*** FUNCTIONS ***/
function hesk_load_priorities($use_cache=1)
{
global $hesk_settings, $hesklang;
// Do we have a cached version available
$cache_dir = dirname(dirname(__FILE__)).'/'.$hesk_settings['cache_dir'].'/';
$cache_file = $cache_dir . 'priority_' . sha1($hesk_settings['language']).'.cache.php';
if ($use_cache && file_exists($cache_file))
{
require($cache_file);
return true;
}
// Define priorities array
$hesk_settings['priorities'] = array();
hesk_load_database_functions();
hesk_dbConnect();
$res = hesk_dbQuery("SELECT `id`, `name`, `color`, `can_customers_select`,`priority_order` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."custom_priorities` ORDER BY `priority_order` ASC");
while ($row = hesk_dbFetchAssoc($res))
{
// Let's set priority name for current language (or the first one we find)
$names = json_decode($row['name'], true);
//print_r($names);
$p_names = "";
if((!isset($names[$hesk_settings['language']]) && $row['id'] < 4) || (isset($names[$hesk_settings['language']]) && strtolower($names[$hesk_settings['language']]) == "null" && $row['id'] < 4)){
//Check for default priority name is NULL
switch ($row['id']) {
case 0:
$p_names = $hesklang['critical'];
break;
case 1:
$p_names = $hesklang['high'];
break;
case 2:
$p_names = $hesklang['medium'];
break;
default:
$p_names = $hesklang['low'];
}
}else{
$row['name'] = (isset($names[$hesk_settings['language']])) ? $names[$hesk_settings['language']] : reset($names);
$p_names = $row['name'];
}
// Add to priorities array
$hesk_settings['priorities'][$row['id']] = array(
'id' => $row['id'],
'name' => $p_names,
'color' => '#'.$row['color'],
'can_customers_select' => $row['can_customers_select'],
'priority_order' => $row['priority_order'],
);
}
// Try to cache results
if ($use_cache && (is_dir($cache_dir) || ( @mkdir($cache_dir, 0777) && is_writable($cache_dir) ) ) )
{
// Is there an index.htm file?
if ( ! file_exists($cache_dir.'index.htm'))
{
@file_put_contents($cache_dir.'index.htm', '');
}
// Write data
@file_put_contents($cache_file, '<?php if (!defined(\'IN_SCRIPT\')) {die();} $hesk_settings[\'priorities\']=' . var_export($hesk_settings['priorities'], true) . ';' );
}
return true;
} // END hesk_load_priorities()
function hesk_is_valid_priority_id($priority)
{
global $hesk_settings;
if (is_int($priority))
{
return isset($hesk_settings['priorities'][$priority]);
}
if ( ! is_string($priority) || ! preg_match('/^(0|[1-9][0-9]*)$/', $priority))
{
return false;
}
return isset($hesk_settings['priorities'][$priority]);
} // END hesk_is_valid_priority_id()
function hesk_get_valid_priority_id($priority, $default = null)
{
global $hesk_settings;
if (hesk_is_valid_priority_id($priority))
{
return intval($priority);
}
if ($default !== null && hesk_is_valid_priority_id($default))
{
return intval($default);
}
$priority_ids = array_keys($hesk_settings['priorities']);
return intval($priority_ids[0]);
} // END hesk_get_valid_priority_id()
function hesk_get_priority_select($ignore_priority = '', $can_select = true, $select_category = '', $select_category_multiple = array() )
{
global $hesk_settings;
$options = '';
foreach ($hesk_settings['priorities'] as $k => $v)
{
$data_style = "";
if ($k === $ignore_priority) {
continue;
}
if ($can_select == true || $v['can_customers_select'] == "1") {
$data_style ='border-top-color:'.$v['color'].';border-left-color:'.$v['color'].';border-bottom-color:'.$v['color'].';';
$options .= '<option value="'.$v['id'].'" '.( ($v['id'] == $select_category || in_array($v['id'], $select_category_multiple) ) ? 'selected' : '').' data-class="priority_img priority_dwn" data-style="'.$data_style.'" >'.$v['name'].'</option>';
}
}
return $options;
} // END hesk_get_priority_select()
function hesk_get_priority_checkboxes($selected = array())
{
global $hesk_settings;
$i = 0;
echo '<div class="checkbox-group list">';
$has_row = false;
foreach ($hesk_settings['priorities'] as $k => $v) {
if ($i % 3 === 0) {
echo '<div class="row">';
$has_row = true;
}
$data_style ='border-top-color:'.$v['color'].';border-left-color:'.$v['color'].';border-bottom-color:'.$v['color'].';';
echo '
<div class="checkbox-custom">
<input type="checkbox" id="priority_'.$k.'" name="p'.$k.'" value="1" '.(isset($selected[$k]) ? 'checked' : '').'>
<label for="priority_'.$k.'" class="td-flex"> <div class="priority_img" style='.$data_style.'></div> '.hesk_get_admin_ticket_priority($k).'</label>
</div>';
if ($i % 3 === 2) {
echo '</div>';
$has_row = false;
}
$i++;
}
if ($has_row) echo '</div>';
echo '</div>';
} // END hesk_get_priority_checkboxes()
function hesk_get_priority_name($priority)
{
global $hesk_settings, $hesklang;
return isset($hesk_settings['priorities'][$priority]['name']) ? $hesk_settings['priorities'][$priority]['name'] : $hesklang['unknown'];
} // END hesk_get_priority_name()
function hesk_get_admin_ticket_priority($priority, $append = '')
{
return hesk_get_ticket_priority($priority, $append, 0);
} // END hesk_get_admin_ticket_priority()
function hesk_get_admin_ticket_priority_for_list($priority, $append = '')
{
global $hesk_settings;
if ( ! isset($hesk_settings['priorities'][$priority])) {
$priority = array_keys($hesk_settings['priorities'])[0];
}
$color = $hesk_settings['priorities'][$priority]['color'];
$data_style ='border-top-color:'.$color.';border-left-color:'.$color.';border-bottom-color:'.$color.';';
return '<div class="priority_img" style='.$data_style.'></div> '.hesk_get_ticket_priority($priority, $append, 0);
} // END hesk_get_admin_ticket_priority_for_list()
function hesk_get_ticket_priority($priority, $append = '', $check_change = 1)
{
global $hesk_settings, $hesklang;
// Is this a valid priority?
if ( ! isset($hesk_settings['priorities'][$priority]['name']))
{
return $hesklang['unknown'];
}
// In the customer side check if this priority can be changed
if ($check_change && ! hesk_can_customer_select_priority($priority))
{
if (isset($hesk_settings['priorities'][$priority]['color']))
{
return '<div class="ml5">'.$hesk_settings['priorities'][$priority]['name'].'</div>';
}
return $hesk_settings['priorities'][$priority]['name'];
}
// Does this priority have a color code?
if (isset($hesk_settings['priorities'][$priority]['color']))
{
return '<div class="ml5">'.$hesk_settings['priorities'][$priority]['name'].'</div>' . $append;
}
// Just return the name if nothing matches
return $hesk_settings['priorities'][$priority]['name'] . $append;
} // END hesk_get_ticket_priority()
function hesk_get_ticket_priority_from_DB($trackingID)
{
global $hesk_settings, $hesklang;
if (empty($trackingID)) {
hesk_error($hesklang['no_trackID']);
}
$result = hesk_dbQuery("SELECT `priority` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` WHERE `trackid`='".hesk_dbEscape($trackingID)."' LIMIT 1");
if (hesk_dbNumRows($result) != 1) {
hesk_error($hesklang['ticket_not_found']);
}
return hesk_dbResult($result);
} // END hesk_get_ticket_priority_from_DB()
function hesk_can_customer_select_priority($priority)
{
global $hesk_settings;
return ( ! isset($hesk_settings['priorities'][$priority]['can_customers_select']) || $hesk_settings['priorities'][$priority]['can_customers_select'] == '1') ? true : false;
} // END hesk_can_customer_select_priority()
function hesk_print_priority_select_box_jquery()
{
global $hesk_settings;
?>
<script>
$(document).ready(function() {
<?php
$data_options = array();
foreach ($hesk_settings['priorities'] as $id => $data)
{
// Is this a default priority? Use style class to add color
if (isset($data['class']))
{
$data_options[$id] = array('class' => $data['class']);
echo '$("#ticket-status-div > div.dropdown-select > ul.dropdown-list > li[data-option=\''.$id.'\']").addClass("'.$data['class'].'");'."\n";
echo '
$("#ticket-status-div > div.dropdown-select > div.label > span").filter(function () {
return $(this).text() == "'.addslashes($data['name']).'";
}).addClass("'.$data['class'].'");'."\n";
echo '$("#submit-as-div > ul.dropdown-list > li[data-option=\'submit_as-'.$id.'\']").addClass("'.$data['class'].'");'."\n";
continue;
}
// Does this priority have a color code?
if (isset($data['color']))
{
$data_options[$id] = array('color' => $data['color']);
echo '$("#ticket-status-div > div.dropdown-select > ul.dropdown-list > li[data-option=\''.$id.'\']").css("color", "'.$data['color'].'");'."\n";
echo '
$("#ticket-status-div > div.dropdown-select > div.label > span").filter(function () {
return $(this).text() == "'.addslashes($data['name']).'";
}).css("color", "'.$data['color'].'");'."\n";
echo '$("#submit-as-div > ul.dropdown-list > li[data-option=\'submit_as-'.$id.'\']").css("color", "'.$data['color'].'");'."\n";
}
}
?>
});
function hesk_update_priority_color(this_id)
{
$("#ticket-status-div > div.dropdown-select > div.label > span").removeClass();
$("#ticket-status-div > div.dropdown-select > div.label > span").removeAttr('style');
<?php
foreach($data_options as $id => $data) {
echo 'if (this_id == '.$id.') {';
if (isset($data['class'])) {
echo '$("#ticket-status-div > div.dropdown-select > div.label > span").addClass("'.$data['class'].'");';
} else {
echo '$("#ticket-status-div > div.dropdown-select > div.label > span").css("color", "'.$data['color'].'");';
}
echo 'return;}';
}
?>
}
</script>
<?php
} // END hesk_print_priority_select_box_jquery()
function hesk_possible_priorities(){
global $hesk_settings;
$possible_priority = [];
foreach ($hesk_settings['priorities'] as $k => $v) {
$possible_priority[$k] = $v['name'];
}
return $possible_priority;
}// END hesk_possible_priorities()
function hesk_possible_priorities_order(){
global $hesk_settings;
$res = hesk_dbQuery("SELECT `id`, `name`, `color`, `can_customers_select`,`priority_order` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."custom_priorities` ORDER BY `priority_order` ASC");
$possible_priority_order = [];
while ($row = hesk_dbFetchAssoc($res))
{
// Let's set status name for current language (or the first one we find)
$names = json_decode($row['name'], true);
$row['name'] = (isset($names[$hesk_settings['language']])) ? $names[$hesk_settings['language']] : reset($names);
$possible_priority_order[$row['priority_order']] = $row['id'];
}
return $possible_priority_order;
}// END hesk_possible_priorities_order()
wget 'https://lists2.roe3.org/hesk/inc/privacy_functions.inc.php'
<?php
/**
*
* This file is part of HESK - PHP Help Desk Software.
*
* (c) Copyright Klemen Stirn. All rights reserved.
* https://www.hesk.com
*
* For the full copyright and license agreement information visit
* https://www.hesk.com/eula.php
*
*/
/* Check if this is a valid include */
if (!defined('IN_SCRIPT')) {die('Invalid attempt');}
/*** FUNCTIONS ***/
function hesk_anonymizeTicketsForCustomer($customer_id) {
global $hesk_settings;
$tickets = hesk_dbQuery("SELECT `ticket_id`
FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."ticket_to_customer`
WHERE `customer_id` = ".intval($customer_id)."
AND `customer_type` = 'REQUESTER'");
while ($row = hesk_dbFetchAssoc($tickets)) {
hesk_anonymizeTicket(intval($row['ticket_id']));
}
}
function hesk_anonymizeTicket($id, $trackingID = null, $have_ticket = false)
{
global $hesk_settings, $hesklang;
// Do we already have ticket info?
if ($have_ticket)
{
global $ticket;
}
else
{
// Get ticket info by tracking or numerical ID
if ($trackingID !== null)
{
$res = hesk_dbQuery("SELECT `id`, `trackid` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` WHERE `trackid`='".hesk_dbEscape($trackingID)."' AND ".hesk_myOwnership());
}
else
{
$res = hesk_dbQuery("SELECT `id`, `trackid` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` WHERE `id`=".intval($id)." AND ".hesk_myOwnership());
}
if ( ! hesk_dbNumRows($res))
{
return false;
}
$ticket = hesk_dbFetchAssoc($res);
}
if (!function_exists('hesk_get_customers_for_ticket')) {
require_once(HESK_PATH . 'inc/customer_accounts.inc.php');
}
$customers = hesk_get_customers_for_ticket($ticket['id']);
// Delete attachment files
$res = hesk_dbQuery("SELECT * FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."attachments` WHERE `ticket_id`='".hesk_dbEscape($ticket['trackid'])."'");
if (hesk_dbNumRows($res))
{
$hesk_settings['server_path'] = dirname(dirname(__FILE__));
while ($file = hesk_dbFetchAssoc($res))
{
hesk_unlink($hesk_settings['server_path'].'/'.$hesk_settings['attach_dir'].'/'.$file['saved_name']);
}
}
// Delete attachments info from the database
hesk_dbQuery("DELETE FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."attachments` WHERE `ticket_id`='".hesk_dbEscape($ticket['trackid'])."'");
// Anonymize customer names on ticket history
foreach ($customers as $customer) {
hesk_dbQuery("UPDATE `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets`
SET `history`=REPLACE(`history`, ' ".hesk_dbEscape(addslashes($customer['name']))."</li>', ' ".hesk_dbEscape($hesklang['anon_name'])."</li>')
WHERE `id` = ".intval($ticket['id']));
}
// Anonymize ticket
$sql = "UPDATE `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` SET
`u_name` = '".hesk_dbEscape($hesklang['anon_name'])."',
`u_email` = '".hesk_dbEscape($hesklang['anon_email'])."',
`subject` = '".hesk_dbEscape($hesklang['anon_subject'])."',
`message` = '".hesk_dbEscape($hesklang['anon_message'])."',
`message_html` = '".hesk_dbEscape($hesklang['anon_message'])."',
`ip` = '".hesk_dbEscape($hesklang['anon_IP'])."',
";
for($i=1; $i<=50; $i++)
{
$sql .= "`custom{$i}` = '',";
}
$sql .= "
attachments='',
`history`=CONCAT(`history`,'".hesk_dbEscape(sprintf($hesklang['thist18'],hesk_date(),addslashes($_SESSION['name']).' ('.$_SESSION['user'].')'))."')
WHERE `id`='".intval($ticket['id'])."'";
hesk_dbQuery($sql);
// Delete customer relationships
hesk_dbQuery("DELETE FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."ticket_to_customer` WHERE `ticket_id` = ".intval($ticket['id']));
// Anonymize replies
hesk_dbQuery("UPDATE `".hesk_dbEscape($hesk_settings['db_pfix'])."replies` SET `customer_id` = NULL, `message` = '".hesk_dbEscape($hesklang['anon_message'])."', `message_html` = '".hesk_dbEscape($hesklang['anon_message'])."', attachments='' WHERE `replyto`='".intval($ticket['id'])."'");
// Delete ticket notes
hesk_dbQuery("DELETE FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."notes` WHERE `ticket`='".intval($ticket['id'])."'");
// Delete ticket reply drafts
hesk_dbQuery("DELETE FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."reply_drafts` WHERE `ticket`=".intval($ticket['id']));
// Delete linked ticket associations
hesk_dbQuery("DELETE FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."linked_tickets` WHERE `ticket_id1`='".intval($ticket['id'])."' OR `ticket_id2`='".intval($ticket['id'])."'");
return true;
} // END hesk_anonymizeTicket()
wget 'https://lists2.roe3.org/hesk/inc/profile_functions.inc.php'
<?php
/**
*
* This file is part of HESK - PHP Help Desk Software.
*
* (c) Copyright Klemen Stirn. All rights reserved.
* https://www.hesk.com
*
* For the full copyright and license agreement information visit
* https://www.hesk.com/eula.php
*
*/
/* Check if this is a valid include */
if (!defined('IN_SCRIPT')) {die('Invalid attempt');}
function hesk_getPermissionGroups($group_ids = array(), $assignable_only = false)
{
global $hesk_settings;
$where = '';
if (is_array($group_ids) && count($group_ids)) {
$group_ids = array_unique(array_map('intval', $group_ids));
$where = " WHERE `group`.`id` IN (" . implode(',', $group_ids) . ")";
}
$permission_groups_rs = hesk_dbQuery("SELECT `group`.`id` AS `group_id`, `group`.`name` AS `group_name`, `category`.`category_id` AS `category_feature_value`, 'CATEGORY' AS `category_feature_type`
FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."permission_groups` AS `group`
INNER JOIN `".hesk_dbEscape($hesk_settings['db_pfix'])."permission_group_categories` AS `category`
ON `group`.`id` = `category`.`group_id`
" . $where . "
UNION ALL
SELECT `group`.`id` AS `group_id`, `group`.`name` AS `group_name`, `feature`.`feature` AS `category_feature_value`, 'FEATURE' AS `category_feature_type`
FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."permission_groups` AS `group`
INNER JOIN `".hesk_dbEscape($hesk_settings['db_pfix'])."permission_group_features` AS `feature`
ON `group`.`id` = `feature`.`group_id`
" . $where);
$permission_groups = array();
while ($row = hesk_dbFetchAssoc($permission_groups_rs)) {
if (!key_exists($row['group_id'], $permission_groups)) {
$permission_groups[$row['group_id']] = array(
'id' => $row['group_id'],
'name' => $row['group_name'],
'categories' => array(),
'features' => array()
);
}
if ($row['category_feature_type'] === 'CATEGORY') {
$permission_groups[$row['group_id']]['categories'][] = intval($row['category_feature_value']);
} else {
$permission_groups[$row['group_id']]['features'][] = $row['category_feature_value'];
}
}
if ($assignable_only && ! $_SESSION['isadmin']) {
foreach ($permission_groups as $group_id => $permission_group) {
if ( ! hesk_isPermissionGroupAssignable($permission_group)) {
unset($permission_groups[$group_id]);
}
}
}
return $permission_groups;
} // End hesk_getPermissionGroups()
function hesk_isPermissionGroupAssignable($permission_group)
{
global $hesk_settings;
if ($_SESSION['isadmin']) {
return true;
}
foreach ($permission_group['categories'] as $category_id) {
if ( ! array_key_exists($category_id, $hesk_settings['categories'])) {
return false;
}
}
foreach ($permission_group['features'] as $feature) {
if ( ! in_array($feature, $hesk_settings['features'])) {
return false;
}
}
return true;
} // End hesk_isPermissionGroupAssignable()
function hesk_validatePermissionGroupsForCurrentUser($permission_group_ids)
{
if ($_SESSION['isadmin'] || ! is_array($permission_group_ids) || count($permission_group_ids) == 0) {
return true;
}
$permission_groups = hesk_getPermissionGroups($permission_group_ids);
foreach ($permission_groups as $permission_group) {
if ( ! hesk_isPermissionGroupAssignable($permission_group)) {
return false;
}
}
return true;
} // End hesk_validatePermissionGroupsForCurrentUser()
function hesk_profile_tab($session_array='new',$is_profile_page=true)
{
global $hesk_settings, $hesklang, $can_reply_tickets, $can_view_tickets, $can_view_unassigned, $can_man_customers;
$show_permissions = false;
$show_preferences = false;
$steps = array($hesklang['pinfo']);
if (!$is_profile_page) {
$steps[] = $hesklang['permissions'];
$show_permissions = true;
}
$steps[] = $hesklang['sig'];
if (!$is_profile_page || $can_reply_tickets) {
$steps[] = $hesklang['pref'];
$show_preferences = true;
}
$steps[] = $hesklang['notn'];
$errors = hesk_SESSION(array($session_array, 'errors'));
$errors = is_array($errors) ? $errors : array();
$permission_groups = $show_permissions ? hesk_getPermissionGroups(array(), true) : array();
if ( ! isset($_SESSION[$session_array]['permission_groups'])) {
$_SESSION[$session_array]['permission_groups'] = array();
}
if ( ! isset($_SESSION[$session_array]['pg_categories'])) {
$_SESSION[$session_array]['pg_categories'] = array();
}
if ( ! isset($_SESSION[$session_array]['pg_features'])) {
$_SESSION[$session_array]['pg_features'] = array();
}
?>
<!-- TABS -->
<ul class="step-bar">
<?php
$i = 1;
foreach ($steps as $step_name): ?>
<li data-link="<?php echo $i++; ?>" data-all="<?php echo count($steps); ?>">
<?php echo $step_name; ?>
</li>
<?php endforeach; ?>
</ul>
<?php
$current_step = 1;
?>
<div class="step-slider">
<div class="step-item step-<?php echo $current_step++; ?>">
<div class="form-group">
<label for="prof_name"><?php echo $hesklang['real_name']; ?></label>
<input type="text" class="form-control <?php echo in_array('name', $errors) ? 'isError' : ''; ?>" id="prof_name" name="name" maxlength="50"
value="<?php echo $_SESSION[$session_array]['name']; ?>">
</div>
<div class="form-group">
<label for="prof_email"><?php echo $hesklang['email']; ?></label>
<input type="text" class="form-control <?php echo in_array('email', $errors) ? 'isError' : ''; ?>" name="email" maxlength="255" id="prof_email"
value="<?php echo $_SESSION[$session_array]['email']; ?>">
</div>
<?php if ($hesk_settings['staff_nicknames']): ?>
<div class="form-group">
<label for="prof_nickname">
<?php echo $hesklang['nickname']; ?>
<div class="tooltype right out-close" style="vertical-align: text-bottom;">
<svg class="icon icon-info">
<use xlink:href="../img/sprite.svg#icon-info"></use>
</svg>
<div class="tooltype__content">
<div class="tooltype__wrapper"><?php echo $hesklang['what_cust_see']; ?></div>
</div>
</div>
</label>
<input type="text" class="form-control <?php echo in_array('nickname', $errors) ? 'isError' : ''; ?>" name="nickname" maxlength="255" id="prof_nickname"
value="<?php echo isset($_SESSION[$session_array]['nickname']) ? $_SESSION[$session_array]['nickname'] : ''; ?>">
</div>
<?php endif; ?>
<?php
if ( ! $is_profile_page || $_SESSION['isadmin'])
{
?>
<section class="item--section">
<h4>
<?php echo $hesklang['login_credentials']; ?>
</h4>
<div class="form-group">
<label for="prof_user"><?php echo $hesklang['username']; ?></label>
<input type="text" class="form-control <?php echo in_array('user', $errors) ? 'isError' : ''; ?>" name="user" autocomplete="off" id="prof_user" maxlength="20"
value="<?php echo $_SESSION[$session_array]['user']; ?>">
</div>
</section>
<?php
}
if ( ! $is_profile_page || $hesk_settings['autoassign']):
?>
<section class="item--section">
<?php if ( ! $is_profile_page): ?>
<div class="form-group">
<label for="prof_newpass"><?php echo (empty($_SESSION[$session_array]['id']) ? $hesklang['pass'] : $hesklang['new_pass']); ?></label>
<input type="password" id="prof_newpass" name="newpass" autocomplete="off" class="form-control <?php echo in_array('passwords', $errors) ? 'isError' : ''; ?>"
value="<?php echo isset($_SESSION[$session_array]['cleanpass']) ? $_SESSION[$session_array]['cleanpass'] : ''; ?>"
onkeyup="hesk_checkPassword(this.value)">
</div>
<div class="form-group">
<label for="prof_newpass2"><?php echo (empty($_SESSION[$session_array]['id']) ? $hesklang['confirm_pass'] : $hesklang['confirm_new_pass']); ?></label>
<input type="password" class="form-control <?php echo in_array('passwords', $errors) ? 'isError' : ''; ?>" id="prof_newpass2" name="newpass2" autocomplete="off"
value="<?php echo isset($_SESSION[$session_array]['cleanpass']) ? $_SESSION[$session_array]['cleanpass'] : ''; ?>">
</div>
<div class="form-group">
<label><?php echo $hesklang['pwdst']; ?></label>
<div style="border: 1px solid #d4d6e3; width: 100%; height: 14px">
<div id="progressBar" style="font-size: 1px; height: 12px; width: 0px; border: none;">
</div>
</div>
</div>
<?php else: ?>
<?php hesk_show_info($hesklang['change_pass_info']); ?>
<?php endif; ?>
<?php if (!$is_profile_page && $hesk_settings['autoassign']): ?>
<div class="form-switcher">
<label class="switch-checkbox">
<input type="checkbox" name="autoassign" value="Y"
<?php if (isset($_SESSION[$session_array]['autoassign']) && !empty($_SESSION[$session_array]['autoassign'])) {echo 'checked';} ?>>
<div class="switch-checkbox__bullet">
<i>
<svg class="icon icon-close">
<use xlink:href="<?php echo HESK_PATH; ?>img/sprite.svg#icon-close"></use>
</svg>
<svg class="icon icon-tick">
<use xlink:href="<?php echo HESK_PATH; ?>img/sprite.svg#icon-tick"></use>
</svg>
</i>
</div>
<span><?php echo $hesklang['user_aa']; ?></span>
</label>
</div>
<?php endif; ?>
</section>
<?php endif; ?>
</div>
<?php if ($show_permissions): ?>
<div class="step-item step-<?php echo $current_step++; ?>">
<div class="form-group">
<label><?php echo $hesklang['atype']; ?></label>
<?php
/* Only administrators can create new administrator accounts */
if ($_SESSION['isadmin']) {
?>
<div class="radio-list">
<div class="radio-custom">
<input type="radio" id="prof_isadmin1" name="isadmin" value="1" onchange="hesk_toggleLayerDisplay('options')"
<?php if ($_SESSION[$session_array]['isadmin']) echo 'checked'; ?>>
<label for="prof_isadmin1">
<?php echo $hesklang['administrator']; ?>
<?php echo $hesklang['admin_can']; ?>
</label>
</div>
<div class="radio-custom">
<input type="radio" id="prof_isadmin0" name="isadmin" value="0" onchange="hesk_toggleLayerDisplay('options')"
<?php if (!$_SESSION[$session_array]['isadmin']) echo 'checked'; ?>>
<label for="prof_isadmin0">
<?php echo $hesklang['astaff']; ?>
<?php echo $hesklang['staff_can']; ?>
</label>
</div>
</div>
<?php
} else {
echo '<label>'.$hesklang['astaff'].' '.$hesklang['staff_can'] . '</label>';
}
?>
</div>
<div id="options" style="display: <?php echo ($_SESSION['isadmin'] && $_SESSION[$session_array]['isadmin']) ? 'none' : 'block'; ?>;">
<h4><?php echo $hesklang['permission_groups_title']; ?></h4>
<section class="item--section">
<?php foreach ($permission_groups as $permission_group): ?>
<div class="checkbox-custom <?php echo in_array('permission_groups', $errors) ? 'isError' : ''; ?>">
<input type="checkbox" id="prof_permission_group_<?php echo $permission_group['id'] ?>"
data-categories="<?php echo implode(',', $permission_group['categories']); ?>"
data-features="<?php echo implode(',', $permission_group['features']); ?>"
name="permissionGroups[]"
value="<?php echo $permission_group['id']; ?>"
<?php if (in_array($permission_group['id'],$_SESSION[$session_array]['permission_groups'])) { echo 'checked'; } ?>>
<label for="prof_permission_group_<?php echo $permission_group['id'] ?>"><?php echo $permission_group['name']; ?></label>
</div>
<?php endforeach; ?>
</section>
<h4><?php echo $hesklang['allowed_cat']; ?></h4>
<section class="item--section">
<?php foreach ($hesk_settings['categories'] as $catid => $catname): ?>
<div class="checkbox-custom <?php echo in_array('categories', $errors) ? 'isError' : ''; ?>">
<input type="checkbox" id="prof_category_<?php echo $catid; ?>" name="temp_categories[]" value="<?php echo $catid; ?>"
<?php if (in_array($catid,$_SESSION[$session_array]['categories']) || in_array($catid,$_SESSION[$session_array]['pg_categories'])) { echo 'checked'; } ?>
<?php if (in_array($catid,$_SESSION[$session_array]['pg_categories'])) { echo ' disabled'; } ?>>
<label for="prof_category_<?php echo $catid; ?>"><?php echo $catname; ?></label>
</div>
<?php endforeach; ?>
</section>
<h4><?php echo $hesklang['allow_feat']; ?></h4>
<section class="item--section">
<?php foreach ($hesk_settings['features'] as $k): ?>
<div class="checkbox-custom <?php echo in_array('features', $errors) ? 'isError' : ''; ?>">
<input type="checkbox" id="<?php echo $k; ?>" name="temp_features[]" value="<?php echo $k; ?>"
<?php if (in_array($k,$_SESSION[$session_array]['features']) || in_array($k,$_SESSION[$session_array]['pg_features'])) { echo 'checked'; } ?>
<?php if (in_array($k,$_SESSION[$session_array]['pg_features'])) { echo ' disabled'; } ?>>
<label for="<?php echo $k; ?>"><?php echo $hesklang[$k]; ?></label>
</div>
<?php endforeach; ?>
</section>
<div id="selected-user-permissions" style="display: none">
<?php foreach ($_SESSION[$session_array]['categories'] as $catid): ?>
<input type="hidden" name="categories[]" value="<?php echo $catid; ?>">
<?php endforeach; ?>
<?php foreach ($_SESSION[$session_array]['features'] as $k): ?>
<input type="hidden" name="features[]" value="<?php echo $k; ?>">
<?php endforeach; ?>
</div>
</div>
</div>
<?php endif; ?>
<div class="step-item step-<?php echo $current_step++; ?>">
<div class="form-group">
<label for="prof_signature"><?php echo $hesklang['signature_max']; ?></label>
<textarea class="form-control <?php echo in_array('signature', $errors) ? 'isError' : ''; ?>"
name="signature" rows="10" cols="60" aria-label="<?php echo $hesklang['sig']; ?>"><?php echo $_SESSION[$session_array]['signature']; ?></textarea>
<?php echo $hesklang['sign_extra']; ?>
</div>
</div>
<?php if ($show_preferences): ?>
<div class="step-item step-<?php echo $current_step++; ?>">
<section class="item--section">
<div class="form-group">
<label><?php echo $hesklang['aftrep']; ?></label>
<div class="radio-list">
<div class="radio-custom">
<input type="radio" id="prof_afterreply0" name="afterreply" value="0" <?php if (!$_SESSION[$session_array]['afterreply']) {echo 'checked';} ?>>
<label for="prof_afterreply0">
<?php echo $hesklang['showtic']; ?>
</label>
</div>
<div class="radio-custom">
<input type="radio" id="prof_afterreply1" name="afterreply" value="1" <?php if ($_SESSION[$session_array]['afterreply'] == 1) {echo 'checked';} ?>>
<label for="prof_afterreply1">
<?php echo $hesklang['gomain']; ?>
</label>
</div>
<div class="radio-custom">
<input type="radio" id="prof_afterreply2" name="afterreply" value="2" <?php if ($_SESSION[$session_array]['afterreply'] == 2) {echo 'checked';} ?>>
<label for="prof_afterreply2">
<?php echo $hesklang['shownext']; ?>
</label>
</div>
</div>
</div>
</section>
<section class="item--section defaults-section">
<h4><?php echo $hesklang['defaults']; ?></h4>
<?php if ($hesk_settings['time_worked']): ?>
<div class="checkbox-custom">
<input type="checkbox" id="prof_autostart" name="autostart" value="1" <?php if (!empty($_SESSION[$session_array]['autostart'])) {echo 'checked';}?>>
<label for="prof_autostart"><?php echo $hesklang['autoss']; ?></label>
</div>
<?php
endif;
if (empty($_SESSION[$session_array]['autoreload'])) {
$reload_time = 5;
$sec = '';
$min = 'selected="selected"';
} else {
$reload_time = intval($_SESSION[$session_array]['autoreload']);
if ($reload_time >= 60 && $reload_time % 60 == 0) {
$reload_time = $reload_time / 60;
$sec = '';
$min = 'selected="selected"';
} else {
$sec = 'selected="selected"';
$min = '';
}
}
?>
<div class="checkbox-custom">
<input type="checkbox" id="prof_notify_customer_new" name="notify_customer_new" value="1" <?php if (!empty($_SESSION[$session_array]['notify_customer_new'])) {echo 'checked';}?>>
<label for="prof_notify_customer_new"><?php echo $hesklang['pncn']; ?></label>
</div>
<div class="checkbox-custom">
<input type="checkbox" id="prof_notify_customer_reply" name="notify_customer_reply" value="1" <?php if (!empty($_SESSION[$session_array]['notify_customer_reply'])) {echo 'checked';}?>>
<label for="prof_notify_customer_reply"><?php echo $hesklang['pncr']; ?></label>
</div>
<div class="checkbox-custom">
<input type="checkbox" id="prof_show_suggested" name="show_suggested" value="1" <?php if (!empty($_SESSION[$session_array]['show_suggested'])) {echo 'checked';}?>>
<label for="prof_show_suggested"><?php echo $hesklang['pssy']; ?></label>
</div>
<div class="check-plus-input">
<div class="checkbox-custom">
<input type="checkbox" id="prof_autoreload" name="autoreload" value="1" <?php if (!empty($_SESSION[$session_array]['autoreload'])) {echo 'checked';}?>>
<label for="prof_autoreload"><?php echo $hesklang['arpp']; ?></label>
</div>
<div class="form-group">
<input type="text" class="form-control" name="reload_time" value="<?php echo $reload_time; ?>" aria-label="Reload time"
maxlength="5" onkeyup="this.value=this.value.replace(/[^\d]+/,'')">
</div>
<div class="form-group">
<div class="dropdown-select center out-close">
<select name="secmin">
<option value="sec" <?php echo $sec; ?>><?php echo $hesklang['seconds']; ?></option>
<option value="min" <?php echo $min; ?>><?php echo $hesklang['minutes']; ?></option>
</select>
</div>
</div>
</div>
</section>
</div>
<?php endif; ?>
<div class="step-item step-<?php echo $current_step; ?>">
<h5><?php echo $hesklang['nomw']; ?></h5>
<?php if (!$is_profile_page || $can_view_tickets) {
echo '<section class="item--section">';
if (!$is_profile_page || $can_view_unassigned) { ?>
<div class="checkbox-custom">
<input type="checkbox" id="prof_notify_new_unassigned" name="notify_new_unassigned" value="1"
<?php if (!empty($_SESSION[$session_array]['notify_new_unassigned'])) {echo 'checked';}?>>
<label for="prof_notify_new_unassigned"><?php echo $hesklang['nwts']; ?> <?php echo $hesklang['unas']; ?></label>
</div>
<?php
}
?>
<div class="checkbox-custom">
<input type="checkbox" id="prof_notify_new_my" name="notify_new_my" value="1"
<?php if (!empty($_SESSION[$session_array]['notify_new_my'])) {echo 'checked';}?>>
<label for="prof_notify_new_my"><?php echo $hesklang['nwts']; ?> <?php echo $hesklang['s_my']; ?></label>
</div>
<?php
echo '</section>';
echo '<section class="item--section">';
if (!$is_profile_page || $can_view_unassigned) { ?>
<div class="checkbox-custom">
<input type="checkbox" id="prof_notify_reply_unassigned" name="notify_reply_unassigned" value="1"
<?php if (!empty($_SESSION[$session_array]['notify_reply_unassigned'])) {echo 'checked';}?>>
<label for="prof_notify_reply_unassigned"><?php echo $hesklang['ncrt']; ?> <?php echo $hesklang['unas']; ?></label>
</div>
<?php
} ?>
<div class="checkbox-custom">
<input type="checkbox" id="prof_notify_reply_my" name="notify_reply_my" value="1"
<?php if (!empty($_SESSION[$session_array]['notify_reply_my'])) {echo 'checked';}?>>
<label for="prof_notify_reply_my"><?php echo $hesklang['ncrt']; ?> <?php echo $hesklang['s_my']; ?></label>
</div>
<?php
echo '</section>';
echo '<section class="item--section">';
if (!$is_profile_page || $can_view_unassigned) { ?>
<div class="checkbox-custom">
<input type="checkbox" id="prof_notify_overdue_unassigned" name="notify_overdue_unassigned" value="1"
<?php if (!empty($_SESSION[$session_array]['notify_overdue_unassigned'])) {echo 'checked';}?>>
<label for="prof_notify_overdue_unassigned"><?php echo $hesklang['ntoverdue']; ?> <?php echo $hesklang['unas']; ?>*</label>
</div>
<?php
}
?>
<div class="checkbox-custom">
<input type="checkbox" id="prof_notify_overdue_my" name="notify_overdue_my" value="1"
<?php if (!empty($_SESSION[$session_array]['notify_overdue_my'])) {echo 'checked';}?>>
<label for="prof_notify_overdue_my"><?php echo $hesklang['ntoverdue']; ?> <?php echo $hesklang['s_my']; ?>*</label>
</div>
<?php
echo '</section>';
?>
<section class="item--section">
<div class="checkbox-custom">
<input type="checkbox" id="prof_notify_assigned" name="notify_assigned" value="1"
<?php if (!empty($_SESSION[$session_array]['notify_assigned'])) {echo 'checked';}?>>
<label for="prof_notify_assigned"><?php echo $hesklang['ntam']; ?></label>
</div>
<div class="checkbox-custom">
<input type="checkbox" id="prof_notify_note" name="notify_note" value="1"
<?php if (!empty($_SESSION[$session_array]['notify_note'])) {echo 'checked';}?>>
<label for="prof_notify_note"><?php echo $hesklang['ntnote']; ?></label>
</div>
<?php
} ?>
<div class="checkbox-custom">
<input type="checkbox" id="prof_notify_pm" name="notify_pm" value="1"
<?php if (!empty($_SESSION[$session_array]['notify_pm'])) {echo 'checked';}?>>
<label for="prof_notify_pm"><?php echo $hesklang['npms']; ?></label>
</div>
</section>
<?php if (!$is_profile_page || $can_man_customers): ?>
<section class="item--section">
<div class="checkbox-custom">
<input type="checkbox" id="prof_notify_customer_approval" name="notify_customer_approval" value="1"
<?php if (!empty($_SESSION[$session_array]['notify_customer_approval'])) {echo 'checked';}?>>
<label for="prof_notify_customer_approval"><?php echo $hesklang['n_cust_app']; ?></label>
</div>
</section>
<?php endif; ?>
<?php if (!$is_profile_page || $can_view_tickets): ?>
<section class="item--section">
<div class="checkbox-custom">
<input type="checkbox" id="prof_notify_collaborator_added" name="notify_collaborator_added" value="1"
<?php if (!empty($_SESSION[$session_array]['notify_collaborator_added'])) {echo 'checked';}?>>
<label for="prof_notify_collaborator_added"><?php echo $hesklang['notify_collaborator_added']; ?></label>
</div>
<div class="checkbox-custom">
<input type="checkbox" id="prof_notify_collaborator_customer_reply" name="notify_collaborator_customer_reply" value="1"
<?php if (!empty($_SESSION[$session_array]['notify_collaborator_customer_reply'])) {echo 'checked';}?>>
<label for="prof_notify_collaborator_customer_reply"><?php echo $hesklang['notify_collaborator_customer_reply']; ?></label>
</div>
<div class="checkbox-custom">
<input type="checkbox" id="prof_notify_collaborator_staff_reply" name="notify_collaborator_staff_reply" value="1"
<?php if (!empty($_SESSION[$session_array]['notify_collaborator_staff_reply'])) {echo 'checked';}?>>
<label for="prof_notify_collaborator_staff_reply"><?php echo $hesklang['notify_collaborator_staff_reply']; ?></label>
</div>
<div class="checkbox-custom">
<input type="checkbox" id="prof_notify_collaborator_note" name="notify_collaborator_note" value="1"
<?php if (!empty($_SESSION[$session_array]['notify_collaborator_note'])) {echo 'checked';}?>>
<label for="prof_notify_collaborator_note"><?php echo $hesklang['notify_collaborator_note']; ?></label>
</div>
<div class="checkbox-custom">
<input type="checkbox" id="prof_notify_collaborator_resolved" name="notify_collaborator_resolved" value="1"
<?php if (!empty($_SESSION[$session_array]['notify_collaborator_resolved'])) {echo 'checked';}?>>
<label for="prof_notify_collaborator_resolved"><?php echo $hesklang['notify_collaborator_resolved']; ?></label>
</div>
<div class="checkbox-custom">
<input type="checkbox" id="prof_notify_collaborator_overdue" name="notify_collaborator_overdue" value="1"
<?php if (!empty($_SESSION[$session_array]['notify_collaborator_overdue'])) {echo 'checked';}?>>
<label for="prof_notify_collaborator_overdue"><?php echo $hesklang['notify_collaborator_overdue']; ?></label>
</div>
</section>
<?php endif; ?>
<?php
if ($can_view_tickets) {
hesk_show_notice($hesklang['ovdcron'] . ' <a href="https://www.hesk.com/knowledgebase/?article=103" target="_blank">'.$hesklang['instructions'].'</a>', '*', false);
}?>
</div>
</div>
<script>
hesk_checkPassword(document.form1.newpass.value);
$(document).ready(function() {
$('#can_reply_tickets').click(function() {
if($(this).prop("checked") == true) {
$('#can_view_tickets').prop("checked", true);
}
});
});
const permissionGroups = [];
const userCategories = [];
const userFeatures = [];
<?php
foreach ($permission_groups as $permission_group):
$categories = count($permission_group['categories']) === 0 ? '[]' : "[".implode(",", $permission_group['categories'])."]";
$features = count($permission_group['features']) === 0 ? '[]' : "['".implode("','", $permission_group['features'])."']";
?>
permissionGroups.push({
id: <?php echo $permission_group['id']; ?>,
categories: <?php echo $categories; ?>,
features: <?php echo $features; ?>,
selected: <?php echo in_array($permission_group['id'],$_SESSION[$session_array]['permission_groups']) ? 'true' : 'false'; ?>
});
<?php endforeach; ?>
<?php foreach ($_SESSION[$session_array]['categories'] as $catid): ?>
userCategories.push(<?php echo $catid; ?>);
<?php endforeach; ?>
<?php foreach ($_SESSION[$session_array]['features'] as $feature): ?>
userFeatures.push('<?php echo hesk_makeJsString($feature); ?>');
<?php endforeach; ?>
$('input[name="permissionGroups[]"]').change(function() {
const permissionGroup = permissionGroups.find(x => x.id === parseInt(this.value));
permissionGroup.selected = this.checked;
updateCheckboxState();
});
const $categoryCheckboxes = $('input[type="checkbox"][name="temp_categories[]"]');
const $featureCheckboxes = $('input[type="checkbox"][name="temp_features[]"]');
$categoryCheckboxes.change(function() {
const categoryId = parseInt(this.value);
if (this.checked) {
userCategories.push(categoryId);
} else {
userCategories.splice(userCategories.indexOf(categoryId), 1);
}
updateCheckboxState();
});
$featureCheckboxes.change(function() {
const feature = this.value;
if (this.checked) {
userFeatures.push(feature);
} else {
userFeatures.splice(userFeatures.indexOf(feature), 1);
}
updateCheckboxState();
});
function updateCheckboxState() {
$categoryCheckboxes.each((_, element) => {
const categoryId = parseInt(element.value);
element.disabled = permissionGroups.some(group => group.selected && group.categories.includes(categoryId));
if (element.disabled) {
element.checked = true;
} else {
element.checked = userCategories.includes(categoryId);
}
});
$featureCheckboxes.each((_, element) => {
const feature = element.value;
element.disabled = permissionGroups.some(group => group.selected && group.features.includes(feature));
if (element.disabled) {
element.checked = true;
} else {
element.checked = userFeatures.includes(feature);
}
});
const selectedUserPermissions = document.getElementById('selected-user-permissions');
selectedUserPermissions.innerHTML = '';
userCategories.forEach(category => {
const input = document.createElement('input');
input.setAttribute('type', 'hidden');
input.setAttribute('name', 'categories[]');
input.setAttribute('value', category);
selectedUserPermissions.appendChild(input);
});
userFeatures.forEach(feature => {
const input = document.createElement('input');
input.setAttribute('type', 'hidden');
input.setAttribute('name', 'features[]');
input.setAttribute('value', feature);
selectedUserPermissions.appendChild(input);
})
}
</script>
<?php
} // END hesk_profile_tab()
wget 'https://lists2.roe3.org/hesk/inc/reporting_functions.inc.php'
<?php
/**
*
* This file is part of HESK - PHP Help Desk Software.
*
* (c) Copyright Klemen Stirn. All rights reserved.
* https://www.hesk.com
*
* For the full copyright and license agreement information visit
* https://www.hesk.com/eula.php
*
*/
/* Check if this is a valid include */
if (!defined('IN_SCRIPT')) {die('Invalid attempt');}
/*** FUNCTIONS ***/
function hesk_SecondsToHHMMSS($in)
{
// Default values for hours, minutes and seconds
$h = 0;
$m = 0;
$s = intval(trim($in === null ? '' : $in));
// If time is 0 seconds just return an empty string
if ($s == 0)
{
return '';
}
// Convert seconds to minutes if 60 or more seconds
if ($s > 59)
{
$m = floor($s / 60) + $m;
$s = intval($s % 60);
}
// Convert minutes to hours if 60 or more minutes
if ($m > 59)
{
$h = floor($m / 60) + $h;
$m = intval($m % 60);
}
// That's it, let's send out formatted time string
return str_pad($h, 2, "0", STR_PAD_LEFT) . ':' . str_pad($m, 2, "0", STR_PAD_LEFT) . ':' . str_pad($s, 2, "0", STR_PAD_LEFT);
} // END hesk_SecondsToHHMMSS()
function hesk_parseXML($msg)
{
$from = array('/\<a href="mailto\:([^"]*)"\>([^\<]*)\<\/a\>/i', '/\<a href="([^"]*)" target="_blank"\>([^\<]*)\<\/a\>/i');
$to = array("$1", "$1");
$msg = preg_replace($from,$to,$msg);
$msg = preg_replace('/<br \/>\s*/',"\n",$msg);
$msg = trim($msg);
return $msg;
} // END hesk_parseXML()
function dateweek($weeknumber,$business=0)
{
$today = time();
$day_of_week = date('N', $today);
// Start from Monday of the current week, then offset by requested week number
$monday = mktime(0, 0, 0, date('m', $today), date('d', $today) - $day_of_week + 1 + (7 * $weeknumber), date('Y', $today));
// DATE BEGINNING OF THE WEEK (Monday)
$dt[0] = date('Y-m-d', $monday);
if ($business)
{
// DATE END OF BUSINESS WEEK (Friday)
$dt[1] = date('Y-m-d', strtotime('+4 days', $monday));
}
else
{
// DATE END OF THE WEEK (Sunday)
$dt[1] = date('Y-m-d', strtotime('+6 days', $monday));
}
return $dt;
} // END dateweek()
function DateArray($s,$e)
{
$start = strtotime($s);
$end = strtotime($e);
$da = array();
$loop = 0;
while ($loop < 10000 && $start <= $end)
{
$loop++;
$da[] = date('Y-m-d', $start);
$start = strtotime('+1 day', $start);
}
return $da;
} // END DateArray()
function MonthsArray($s,$e)
{
$start = date('Y-m-01', strtotime($s));
$end = date('Y-m-01', strtotime($e));
$mt = array();
while ($start <= $end)
{
$mt[] = $start;
$start = date('Y-m-01',strtotime("+1 month", strtotime($start)));
}
return $mt;
} // END MonthsArray()
function hesk_getOldestDate()
{
global $hesk_settings, $hesklang, $date_from, $date_to;
$res = hesk_dbQuery("SELECT `dt` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` ORDER BY `dt` ASC LIMIT 1");
if (hesk_dbNumRows($res) == 1)
{
$row = hesk_dbFetchAssoc($res);
return date('Y-m-d', strtotime($row['dt']) );
}
else
{
return date('Y-m-d');
}
} // END hesk_getOldestDate()
wget 'https://lists2.roe3.org/hesk/inc/secimg.inc.php'
<?php
/**
*
* This file is part of HESK - PHP Help Desk Software.
*
* (c) Copyright Klemen Stirn. All rights reserved.
* https://www.hesk.com
*
* For the full copyright and license agreement information visit
* https://www.hesk.com/eula.php
*
*/
/* Check if this is a valid include */
if (!defined('IN_SCRIPT')) {die('Invalid attempt');}
#[AllowDynamicProperties]
class PJ_SecurityImage
{
function __construct($key)
{
$this->code = '';
$this->key = $key;
} // End PJ_SecurityImage
function encrypt($plain_text)
{
$this->code = trim(sha1($plain_text.$this->key));
} // End encrypt
function checkCode($mystring,$checksum)
{
$this->encrypt($mystring);
if ($this->code == $checksum)
return true;
else
return false;
} // End checkCode
function printImage($random_number)
{
$im = @imagecreate(150, 40) or die("Cannot Initialize new GD image stream");
$background_color = imagecolorallocate($im, mt_rand(0,100), mt_rand(0,100), mt_rand(0,100));
for ($i=0;$i<strlen($random_number);$i++)
{
$text_color = imagecolorallocate($im, mt_rand(180,255), mt_rand(180,255), mt_rand(100,255));
$display = substr($random_number,$i,1);
$x = ($i*30) + mt_rand(3,16);
$y = mt_rand(3,26);
imagestring($im, 5, $x, $y, $display, $text_color);
}
if ( function_exists('imagejpeg') )
{
header("Content-type: image/jpeg");
imagejpeg($im);
}
elseif ( function_exists('imagepng') )
{
header("Content-type: image/png");
imagepng($im);
}
elseif ( function_exists('imagegif') )
{
header("Content-type: image/gif");
imagegif($im);
}
else
{
die("GD was not compiled with JPEG or PNG support");
}
if (PHP_VERSION_ID < 80500) {
imagedestroy($im);
}
} // End printImage
function get()
{
return $this->code;
} // End get
} // End class PJ_SecurityImage
wget 'https://lists2.roe3.org/hesk/inc/setup_functions.inc.php'
<?php
/**
*
* This file is part of HESK - PHP Help Desk Software.
*
* (c) Copyright Klemen Stirn. All rights reserved.
* https://www.hesk.com
*
* For the full copyright and license agreement information visit
* https://www.hesk.com/eula.php
*
*/
/* Check if this is a valid include */
if (!defined('IN_SCRIPT')) {die('Invalid attempt');}
use PHPMailer\PHPMailer\SMTP;
use PHPMailer\PHPMailer\Exception;
$hesk_settings['barcode_types'] = array(
'C128A' => 'CODE 128 A',
'C128B' => 'CODE 128 B',
'C128' => 'CODE 128',
'C39E+' => 'CODE 39 EXTENDED + CHECKSUM',
'C39E' => 'CODE 39 EXTENDED',
'C39+' => 'CODE 39 + CHECKSUM',
'C39' => 'CODE 39 - ANSI MH10.8M-1983 - USD-3 - 3 of 9.',
'C93' => 'CODE 93 - USS-93',
'DATAMATRIX' => 'DATAMATRIX (ISO/IEC 16022)',
'PDF417' => 'PDF417 (ISO/IEC 15438:2006)',
'QRCODE' => 'QR-CODE',
);
$hesk_settings['barcode_formats'] = array(
'svg' => 'SVG image',
'png' => 'PNG image',
);
/*** FUNCTIONS ***/
function hesk_map_datepicker_date_format_to_php($format)
{
$js_to_php_date_format_map = array(
'dd' => 'zzzz',
'd' => 'j',
'DD' => 'l',
'D' => 'D',
'mm' => 'wwww',
'm' => 'n',
'MM' => 'F',
'M' => 'M',
'yyyy' => 'Y',
'yy' => 'y',
// Trick to not overwrite d and m after matching dd and mm
'zzzz' => 'd',
'wwww' => 'm',
);
foreach ($js_to_php_date_format_map as $js_format => $php_format) {
$format = str_replace($js_format, $php_format, $format);
}
return $format;
} // END hesk_map_datepicker_date_format_to_php()
function hesk_translate_timezone_list($timezone_list)
{
global $hesklang;
$translate_months_short = array(
'Jan' => $hesklang['ms01'],
'Feb' => $hesklang['ms02'],
'Mar' => $hesklang['ms03'],
'Apr' => $hesklang['ms04'],
'May' => $hesklang['ms05'],
'Jun' => $hesklang['ms06'],
'Jul' => $hesklang['ms07'],
'Aug' => $hesklang['ms08'],
'Sep' => $hesklang['ms09'],
'Oct' => $hesklang['ms10'],
'Nov' => $hesklang['ms11'],
'Dec' => $hesklang['ms12']
);
return str_replace(array_keys($translate_months_short), array_values($translate_months_short), $timezone_list);
} // END hesk_translate_timezone_list()
function hesk_generate_timezone_list()
{
static $regions = array(
DateTimeZone::AFRICA,
DateTimeZone::AMERICA,
DateTimeZone::ANTARCTICA,
DateTimeZone::ASIA,
DateTimeZone::ATLANTIC,
DateTimeZone::AUSTRALIA,
DateTimeZone::EUROPE,
DateTimeZone::INDIAN,
DateTimeZone::PACIFIC,
);
$timezones = array();
foreach( $regions as $region )
{
$timezones = array_merge( $timezones, DateTimeZone::listIdentifiers( $region ) );
}
$timezone_offsets = array();
foreach( $timezones as $timezone )
{
$tz = new DateTimeZone($timezone);
$timezone_offsets[$timezone] = $tz->getOffset(new DateTime);
}
// sort timezone by timezone name
ksort($timezone_offsets);
//asort($timezone_offsets); // <-- use this to sort by time offset from UTC instead
// Add UTC as the first element
$timezone_offsets = array('UTC' => 0) + $timezone_offsets;
$timezone_list = array();
foreach( $timezone_offsets as $timezone => $offset )
{
$offset_prefix = $offset < 0 ? '-' : '+';
$offset_formatted = gmdate( 'H:i', abs($offset) );
$pretty_offset = "UTC{$offset_prefix}{$offset_formatted}";
$t = new DateTimeZone($timezone);
$c = new DateTime("now", $t);
$current_time = $c->format('d M Y, H:i');
$timezone_list[$timezone] = "{$timezone} - {$current_time}";
}
return $timezone_list;
} // END hesk_generate_timezone_list()
function hesk_testMySQL()
{
global $hesk_settings, $hesklang, $set, $mysql_error, $mysql_log;
define('REQUIRE_MYSQL_VERSION','5.0.7');
// Use MySQLi extension to connect?
$use_mysqli = function_exists('mysqli_connect') ? true : false;
// Get variables
$set['db_host'] = hesk_input( hesk_POST('s_db_host'), $hesklang['err_dbhost']);
$set['db_name'] = hesk_input( hesk_POST('s_db_name'), $hesklang['err_dbname']);
$set['db_user'] = hesk_input( hesk_POST('s_db_user'), $hesklang['err_dbuser']);
$set['db_pass'] = hesk_input( hesk_POST('s_db_pass') );
$set['db_pfix'] = preg_replace('/[^0-9a-zA-Z_]/', '', hesk_POST('s_db_pfix', 'hesk_') );
// Allow some special chars in password and username
$set['db_user'] = str_replace('&', '&', $set['db_user']);
$set['db_pass'] = str_replace(array('&', '>', '<'), array('&', '>', '<'), $set['db_pass']);
// MySQL tables used by HESK
$tables = array(
$set['db_pfix'].'attachments',
$set['db_pfix'].'auth_tokens',
$set['db_pfix'].'banned_emails',
$set['db_pfix'].'banned_ips',
$set['db_pfix'].'categories',
$set['db_pfix'].'custom_fields',
$set['db_pfix'].'custom_statuses',
$set['db_pfix'].'kb_articles',
$set['db_pfix'].'kb_attachments',
$set['db_pfix'].'kb_categories',
$set['db_pfix'].'logins',
$set['db_pfix'].'log_overdue',
$set['db_pfix'].'mail',
$set['db_pfix'].'mfa_backup_codes',
$set['db_pfix'].'mfa_verification_tokens',
$set['db_pfix'].'notes',
$set['db_pfix'].'online',
$set['db_pfix'].'pipe_loops',
$set['db_pfix'].'replies',
$set['db_pfix'].'reply_drafts',
$set['db_pfix'].'reset_password',
$set['db_pfix'].'service_messages',
$set['db_pfix'].'std_replies',
$set['db_pfix'].'tickets',
$set['db_pfix'].'ticket_templates',
$set['db_pfix'].'users',
);
$connection_OK = false;
$mysql_error = '';
ob_start();
// Connect to MySQL
if ($use_mysqli)
{
mysqli_report(MYSQLI_REPORT_OFF);
// Do we need a special port? Check and connect to the database
if ( strpos($set['db_host'], ':') )
{
list($set['db_host_no_port'], $set['db_port']) = explode(':', $set['db_host']);
try {
$set_link = mysqli_connect($set['db_host_no_port'], $set['db_user'], $set['db_pass'], $set['db_name'], intval($set['db_port']) );
} catch (Exception $e) {
$set_link = false;
}
}
else
{
try {
$set_link = mysqli_connect($set['db_host'], $set['db_user'], $set['db_pass'], $set['db_name']);
} catch (Exception $e) {
$set_link = false;
}
}
if (empty($set_link))
{
ob_end_clean();
$mysql_error = $hesklang['err_dbconn'];
$mysql_log = "(".mysqli_connect_errno().") ".mysqli_connect_error();
return false;
}
$res = mysqli_query($set_link, 'SHOW TABLES FROM `'.mysqli_real_escape_string($set_link, $set['db_name']).'`');
while ($row = mysqli_fetch_row($res))
{
foreach($tables as $k => $v)
{
if ($v == $row[0])
{
unset($tables[$k]);
break;
}
}
}
// Get MySQL version
$mysql_version = mysqli_fetch_assoc( mysqli_query($set_link, 'SELECT VERSION() AS version') );
// Close connections
mysqli_close($set_link);
}
else
{
$set_link = mysql_connect($set['db_host'], $set['db_user'], $set['db_pass']);
if ( ! $set_link)
{
ob_end_clean();
$mysql_error = $hesklang['err_dbconn'];
$mysql_log = mysql_error();
return false;
}
// Select database
if ( ! mysql_select_db($set['db_name'], $set_link) )
{
ob_end_clean();
$mysql_error = $hesklang['err_dbsele'];
$mysql_log = mysql_error();
return false;
}
$res = mysql_query('SHOW TABLES FROM `'.mysql_real_escape_string($set['db_name']).'`', $set_link);
while ($row = mysql_fetch_row($res))
{
foreach($tables as $k => $v)
{
if ($v == $row[0])
{
unset($tables[$k]);
break;
}
}
}
// Get MySQL version
$mysql_version = mysql_fetch_assoc( mysql_query('SELECT VERSION() AS version') );
// Close connections
mysql_close($set_link);
}
// Check MySQL version
if ( version_compare($mysql_version['version'], REQUIRE_MYSQL_VERSION, '<') )
{
ob_end_clean();
$mysql_error = $hesklang['err_dbversion'] . ' ' . $mysql_version['version'];
$mysql_log = '';
return false;
}
// Some tables weren't found, show an error
if (count($tables) > 0)
{
ob_end_clean();
$mysql_error = $hesklang['err_dpi2'].'<br /><br />'.implode(',<br />', $tables);
$mysql_log = '';
return false;
}
else
{
$connection_OK = true;
}
ob_end_clean();
return $connection_OK;
} // END hesk_testMySQL()
function hesk_testPOP3($check_old_settings=false)
{
global $hesk_settings, $hesklang, $set;
$set['pop3_host_name'] = hesk_input( hesk_POST('s_pop3_host_name', 'mail.example.com') );
$set['pop3_host_port'] = intval( hesk_POST('s_pop3_host_port', 110) );
$set['pop3_tls'] = empty($_POST['s_pop3_tls']) ? 0 : 1;
$set['pop3_keep'] = empty($_POST['s_pop3_keep']) ? 0 : 1;
$set['pop3_user'] = hesk_input( hesk_POST('s_pop3_user') );
$set['pop3_password'] = hesk_input( hesk_POST('s_pop3_password') );
$set['pop3_conn_type'] = hesk_input(hesk_POST('s_pop3_conn_type'));
$set['pop3_oauth_provider'] = $set['pop3_conn_type'] === 'basic' ? 0 : intval(hesk_POST('s_pop3_oauth_provider'));
// For compatibility with PHP 5.3 magic quotes...
if (HESK_SLASH === false)
{
$set['pop3_password'] = str_replace('\\"', '"', $set['pop3_password']);
}
// Are new settings the same as old? If yes, skip testing connection, assume it works
if ($check_old_settings)
{
$set['tmp_pop3_host_name'] = hesk_input( hesk_POST('tmp_pop3_host_name', 'mail.example.com') );
$set['tmp_pop3_host_port'] = intval( hesk_POST('tmp_pop3_host_port', 110) );
$set['tmp_pop3_tls'] = empty($_POST['tmp_pop3_tls']) ? 0 : 1;
$set['tmp_pop3_keep'] = empty($_POST['tmp_pop3_keep']) ? 0 : 1;
$set['tmp_pop3_user'] = hesk_input( hesk_POST('tmp_pop3_user') );
$set['tmp_pop3_password'] = hesk_input( hesk_POST('tmp_pop3_password') );
$set['tmp_pop3_conn_type'] = hesk_input(hesk_POST('tmp_pop3_conn_type'));
$set['tmp_pop3_oauth_provider'] = $set['tmp_pop3_conn_type'] === 'basic' ? 0 : intval(hesk_POST('tmp_pop3_oauth_provider'));
// For compatibility with PHP 5.3 magic quotes...
if (HESK_SLASH === false)
{
$set['tmp_pop3_password'] = str_replace('\\"', '"', $set['tmp_pop3_password']);
}
if (
$set['tmp_pop3_host_name'] != 'mail.example.com' && // Default setting
$set['tmp_pop3_host_name'] == $set['pop3_host_name'] &&
$set['tmp_pop3_host_port'] == $set['pop3_host_port'] &&
$set['tmp_pop3_tls'] == $set['pop3_tls'] &&
$set['tmp_pop3_keep'] == $set['pop3_keep'] &&
$set['tmp_pop3_user'] == $set['pop3_user'] &&
$set['tmp_pop3_password'] == $set['pop3_password'] &&
$set['tmp_pop3_conn_type'] == $set['pop3_conn_type'] &&
$set['tmp_pop3_oauth_provider'] == $set['pop3_oauth_provider']
)
{
return true;
}
}
// Initiate POP3 class and set parameters
require_once(HESK_PATH . 'inc/mail/pop3.php');
$pop3 = new pop3_class;
$pop3->hostname = $set['pop3_host_name'];
$pop3->port = $set['pop3_host_port'];
$pop3->tls = $set['pop3_tls'];
$pop3->debug = 1;
if ($set['pop3_conn_type']=='oauth') {
require_once(HESK_PATH . 'inc/oauth_functions.inc.php');
$pop3->authentication_mechanism = 'XOAUTH2';
hesk_dbConnect();
$access_token = hesk_fetch_access_token($set['pop3_oauth_provider']);
if (!$access_token) {
global $pop3_error, $pop3_log;
$pop3_error = $hesklang['oauth_error_retrieve'];
$pop3_log = $hesklang['oauth_error_retrieve'];
return false;
}
}
$connection_OK = false;
ob_start();
// Connect to POP3
if(($error=$pop3->Open())=="")
{
// Authenticate
if(($error=$pop3->Login($set['pop3_user'], ($set['pop3_conn_type']=='oauth' ? $access_token : hesk_htmlspecialchars_decode(stripslashes($set['pop3_password'])))))=="")
{
// Get number of messages and total size
if(($error=$pop3->Statistics($messages,$size))=="")
{
global $emails_found;
$emails_found = $messages;
if(($error=$pop3->Close()) == "")
{
// Connection OK
$connection_OK = true;
}
}
}
}
if($error != '')
{
global $pop3_error, $pop3_log;
$pop3_error = $error;
$pop3_log = ob_get_contents();
}
ob_end_clean();
return $connection_OK;
} // END hesk_testPOP3()
function hesk_testSMTP($check_old_settings=false)
{
global $hesk_settings, $hesklang, $set;
// Get variables
$set['smtp_host_name'] = hesk_input( hesk_POST('s_smtp_host_name', 'localhost') );
$set['smtp_host_port'] = intval( hesk_POST('s_smtp_host_port', 25) );
$set['smtp_timeout'] = intval( hesk_POST('s_smtp_timeout', 10) );
$set['smtp_enc'] = hesk_POST('s_smtp_enc');
$set['smtp_enc'] = ($set['smtp_enc'] == 'ssl' || $set['smtp_enc'] == 'tls') ? $set['smtp_enc'] : '';
$set['smtp_noval_cert'] = empty($_POST['s_smtp_noval_cert']) ? 0 : 1;
$set['smtp_user'] = hesk_input( hesk_POST('s_smtp_user') );
$set['smtp_password'] = hesk_input( hesk_POST('s_smtp_password') );
$set['smtp_conn_type'] = hesk_input(hesk_POST('s_smtp_conn_type'));
$set['smtp_oauth_provider'] = $set['smtp_conn_type'] === 'basic' ? 0 : intval(hesk_POST('s_smtp_oauth_provider'));
// For compatibility with PHP 5.3 magic quotes...
if (HESK_SLASH === false)
{
$set['smtp_password'] = str_replace('\\"', '"', $set['smtp_password']);
}
// Are new settings the same as old? If yes, skip testing connection, assume it works
if ($check_old_settings)
{
$set['tmp_smtp_host_name'] = hesk_input( hesk_POST('tmp_smtp_host_name', 'localhost') );
$set['tmp_smtp_host_port'] = intval( hesk_POST('tmp_smtp_host_port', 25) );
$set['tmp_smtp_timeout'] = intval( hesk_POST('tmp_smtp_timeout', 10) );
$set['tmp_smtp_enc'] = hesk_POST('tmp_smtp_enc');
$set['tmp_smtp_enc'] = ($set['tmp_smtp_enc'] == 'ssl' || $set['tmp_smtp_enc'] == 'tls') ? $set['tmp_smtp_enc'] : '';
$set['tmp_smtp_noval_cert'] = empty($_POST['tmp_smtp_noval_cert']) ? 0 : 1;
$set['tmp_smtp_user'] = hesk_input( hesk_POST('tmp_smtp_user') );
$set['tmp_smtp_password'] = hesk_input( hesk_POST('tmp_smtp_password') );
$set['tmp_smtp_conn_type'] = hesk_input(hesk_POST('tmp_smtp_conn_type'));
$set['tmp_smtp_oauth_provider'] = $set['tmp_smtp_conn_type'] === 'basic' ? 0 : intval(hesk_POST('tmp_smtp_oauth_provider'));
// For compatibility with PHP 5.3 magic quotes...
if (HESK_SLASH === false)
{
$set['tmp_smtp_password'] = str_replace('\\"', '"', $set['tmp_smtp_password']);
}
if (
$set['tmp_smtp_host_name'] != 'mail.example.com' && // Default setting
$set['tmp_smtp_host_name'] == $set['smtp_host_name'] &&
$set['tmp_smtp_host_port'] == $set['smtp_host_port'] &&
$set['tmp_smtp_timeout'] == $set['smtp_timeout'] &&
$set['tmp_smtp_enc'] == $set['smtp_enc'] &&
$set['tmp_smtp_noval_cert'] == $set['smtp_noval_cert'] &&
$set['tmp_smtp_user'] == $set['smtp_user'] &&
$set['tmp_smtp_password'] == $set['smtp_password'] &&
$set['tmp_smtp_conn_type'] == $set['smtp_conn_type'] &&
$set['tmp_smtp_oauth_provider'] == $set['smtp_oauth_provider']
)
{
return true;
}
}
ob_start();
//Create a new SMTP instance
$smtp = new SMTP();
//Enable connection-level debug output
if ($hesk_settings['debug_mode']) {
$smtp->do_debug = SMTP::DEBUG_CONNECTION;
// $smtp->do_debug = SMTP::DEBUG_LOWLEVEL;
} else {
$smtp->do_debug = SMTP::DEBUG_SERVER;
}
$smtp->Timeout = $set['smtp_timeout'];
$smtp->Timelimit = $set['smtp_timeout'];
if ($set['smtp_noval_cert']) {
$options = array(
'ssl' => array(
'verify_peer' => false,
'verify_peer_name' => false,
'allow_self_signed' => true
)
);
} else {
$options = array();
}
if (stripos($set['smtp_host_name'], 'ssl://') === 0) {
$set['smtp_host_name'] = substr($set['smtp_host_name'], 6);
}
$set['smtp_host_name_full'] = ($set['smtp_enc'] == 'ssl') ? 'ssl://' . $set['smtp_host_name'] : $set['smtp_host_name'];
try {
//Connect to an SMTP server
if (!$smtp->connect($set['smtp_host_name_full'], $set['smtp_host_port'], $set['smtp_timeout'], $options)) {
throw new Exception('Connect failed');
}
//Say hello
if (!$smtp->hello(gethostname())) {
throw new Exception('EHLO failed: ' . $smtp->getError()['error']);
}
//Get the list of ESMTP services the server offers
$e = $smtp->getServerExtList();
if ($set['smtp_enc'] == 'tls' && is_array($e)) {
if ( ! array_key_exists('STARTTLS', $e)) {
throw new Exception('Server does not support STARTTLS');
}
$tlsok = $smtp->startTLS();
if (!$tlsok) {
throw new Exception('Failed to start encryption: ' . $smtp->getError()['error']);
}
//Repeat EHLO after STARTTLS
if (!$smtp->hello(gethostname())) {
throw new Exception('EHLO (2) failed: ' . $smtp->getError()['error']);
}
//Get new capabilities list, which will usually now include AUTH if it didn't before
$e = $smtp->getServerExtList();
}
//If server supports authentication, do it (even if no encryption)
if (is_array($e) && array_key_exists('AUTH', $e)) {
if ($set['smtp_conn_type']=='oauth') {
require_once(HESK_PATH . 'inc/oauth_functions.inc.php');
require_once(HESK_PATH . 'inc/mail/HeskOAuthTokenProvider.php');
$oauthTokenProvider = new \PHPMailer\PHPMailer\HeskOAuthTokenProvider();
$oauthTokenProvider->username = $set['smtp_user'];
$oauthTokenProvider->provider = $set['smtp_oauth_provider'];
if ($smtp->authenticate($set['smtp_user'], null, 'XOAUTH2', $oauthTokenProvider)) {
echo 'Connected ok (OAuth)!';
} else {
throw new Exception('Authentication failed: ' . $smtp->getError()['error']);
}
} elseif ($smtp->authenticate($set['smtp_user'], hesk_htmlspecialchars_decode(stripslashes($set['smtp_password'])))) {
echo 'Connected ok!';
} else {
throw new Exception('Authentication failed: ' . $smtp->getError()['error']);
}
}
} catch (Exception $e) {
global $smtp_error, $smtp_log;
$smtp_error = $e->getMessage();
$smtp_log = ob_get_contents();
$smtp->quit();
ob_end_clean();
return false;
}
$smtp->quit();
ob_end_clean();
return true;
} // END hesk_testSMTP()
function hesk_testIMAP($check_old_settings=false)
{
global $hesk_settings, $hesklang, $set;
$set['imap_host_name'] = hesk_input( hesk_POST('s_imap_host_name', 'mail.example.com') );
$set['imap_host_port'] = intval( hesk_POST('s_imap_host_port', 993) );
$set['imap_enc'] = hesk_POST('s_imap_enc');
$set['imap_enc'] = ($set['imap_enc'] == 'ssl' || $set['imap_enc'] == 'tls') ? $set['imap_enc'] : '';
$set['imap_noval_cert'] = empty($_POST['s_imap_noval_cert']) ? 0 : 1;
$set['imap_disable_GSSAPI'] = empty($_POST['s_imap_disable_GSSAPI']) ? 0 : 1;
$set['imap_keep'] = empty($_POST['s_imap_keep']) ? 0 : 1;
$set['imap_user'] = hesk_input( hesk_POST('s_imap_user') );
$set['imap_password'] = hesk_input( hesk_POST('s_imap_password') );
$set['imap_conn_type'] = hesk_input(hesk_POST('s_imap_conn_type'));
$set['imap_oauth_provider'] = $set['imap_conn_type'] === 'basic' ? 0 : intval(hesk_POST('s_imap_oauth_provider'));
$set['imap_mailbox'] = hesk_input( hesk_POST('s_imap_mailbox', 'INBOX')); // Added for IMAP Mailbox
// For compatibility with PHP 5.3 magic quotes...
if (HESK_SLASH === false)
{
$set['imap_password'] = str_replace('\\"', '"', $set['imap_password']);
}
// Are new settings the same as old? If yes, skip testing connection, assume it works
if ($check_old_settings)
{
$set['tmp_imap_host_name'] = hesk_input( hesk_POST('tmp_imap_host_name', 'mail.example.com') );
$set['tmp_imap_host_port'] = intval( hesk_POST('tmp_imap_host_port', 993) );
$set['tmp_imap_enc'] = hesk_POST('s_imap_enc');
$set['tmp_imap_enc'] = ($set['tmp_imap_enc'] == 'ssl' || $set['tmp_imap_enc'] == 'tls') ? $set['tmp_imap_enc'] : '';
$set['tmp_imap_noval_cert'] = empty($_POST['tmp_imap_noval_cert']) ? 0 : 1;
$set['tmp_imap_disable_GSSAPI'] = empty($_POST['tmp_imap_disable_GSSAPI']) ? 0 : 1;
$set['tmp_imap_keep'] = empty($_POST['tmp_imap_keep']) ? 0 : 1;
$set['tmp_imap_user'] = hesk_input( hesk_POST('tmp_imap_user') );
$set['tmp_imap_password'] = hesk_input( hesk_POST('tmp_imap_password') );
$set['tmp_imap_conn_type'] = hesk_input(hesk_POST('tmp_imap_conn_type'));
$set['tmp_imap_oauth_provider'] = $set['tmp_imap_conn_type'] === 'basic' ? 0 : intval(hesk_POST('tmp_imap_oauth_provider'));
$set['tmp_imap_mailbox'] = hesk_input( hesk_POST('s_imap_mailbox', 'INBOX')); // Added for IMAP Mailbox
// For compatibility with PHP 5.3 magic quotes...
if (HESK_SLASH === false)
{
$set['tmp_imap_password'] = str_replace('\\"', '"', $set['tmp_imap_password']);
}
if (
$set['tmp_imap_host_name'] != 'mail.example.com' && // Default setting
$set['tmp_imap_host_name'] == $set['imap_host_name'] &&
$set['tmp_imap_host_port'] == $set['imap_host_port'] &&
$set['tmp_imap_enc'] == $set['imap_enc'] &&
$set['tmp_imap_noval_cert'] == $set['imap_noval_cert'] &&
$set['tmp_imap_disable_GSSAPI'] == $set['imap_disable_GSSAPI'] &&
$set['tmp_imap_keep'] == $set['imap_keep'] &&
$set['tmp_imap_user'] == $set['imap_user'] &&
$set['tmp_imap_password'] == $set['imap_password'] &&
$set['tmp_imap_conn_type'] == $set['imap_conn_type'] &&
$set['tmp_imap_oauth_provider'] == $set['imap_oauth_provider'] &&
$set['tmp_imap_mailbox'] == $set['imap_mailbox'] // Added for IMAP Mailbox
)
{
return true;
}
}
$connection_OK = false;
ob_start();
// IMAP mailbox based on required encryption
require_once(HESK_PATH . 'inc/mail/imap/HeskIMAP.php');
$imap = new HeskIMAP();
$imap->host = $set['imap_host_name'];
$imap->port = $set['imap_host_port'];
$imap->username = $set['imap_user'];
if ($set['imap_conn_type'] === 'basic') {
$imap->password = hesk_htmlspecialchars_decode(stripslashes($set['imap_password']));
$imap->useOAuth = false;
} elseif ($set['imap_conn_type'] === 'oauth') {
require_once(HESK_PATH . 'inc/oauth_functions.inc.php');
$access_token = hesk_fetch_access_token($set['imap_oauth_provider']);
if (!$access_token) {
global $imap_error, $imap_log;
$imap_error = $hesklang['oauth_error_retrieve'];
$imap_log = $hesklang['oauth_error_retrieve'];
return false;
}
$imap->accessToken = $access_token;
$imap->useOAuth = true;
$imap->password = null;
}
$imap->readOnly = false;
$imap->ignoreCertificateErrors = $set['imap_noval_cert'];
$imap->disableGSSAPI = $set['imap_disable_GSSAPI'];
$imap->connectTimeout = 15;
$imap->responseTimeout = 15;
$imap->imap_mailbox = $set['imap_mailbox'];// Added for IMAP Mailbox
$imap->folder = $set['imap_mailbox']; //Change for IMAP Mailbox;
if ($set['imap_enc'] === 'ssl')
{
$imap->ssl = true;
$imap->tls = false;
}
elseif ($set['imap_enc'] === 'tls')
{
$imap->ssl = false;
$imap->tls = true;
}
else
{
$imap->ssl = false;
$imap->tls = false;
}
if ($imap->login())
{
global $emails_found;
$emails_found = 0;
echo $hesk_settings['debug_mode'] ? "<pre>Connected to the IMAP server "" . $imap->host . ":" . $imap->port . "".</pre>\n" : '';
$has_unseen_message = $imap->hasUnseenMessages();
if (is_int($has_unseen_message)) {
$emails = $imap->getUnseenMessageIDs();
$emails_found = count($emails);
}
$imap->logout();
}
// Any error messages?
if($errors = $imap->getErrors())
{
global $imap_error, $imap_log;
$imap_error = end($errors);
reset($errors);
$imap_log = '';
foreach ($errors as $error)
{
$imap_log .= hesk_htmlspecialchars($error) . "\n";
}
}
else
{
$connection_OK = true;
}
ob_end_clean();
return $connection_OK;
} // END hesk_testIMAP()
function hesk_generate_SPAM_question()
{
$useChars = 'AEUYBDGHJLMNPRSTVWXZ23456789';
$ac = $useChars[mt_rand(0,27)];
for($i=1;$i<5;$i++)
{
$ac .= $useChars[mt_rand(0,27)];
}
$animals = array('dog','cat','cow','pig','elephant','tiger','chicken','bird','fish','alligator','monkey','mouse','lion','turtle','crocodile','duck','gorilla','horse','penguin','dolphin','rabbit','sheep','snake','spider');
$not_animals = array('ball','window','house','tree','earth','money','rocket','sun','star','shirt','snow','rain','air','candle','computer','desk','coin','TV','paper','bell','car','baloon','airplane','phone','water','space');
$keys = array_rand($animals,2);
$my_animals[] = $animals[$keys[0]];
$my_animals[] = $animals[$keys[1]];
$keys = array_rand($not_animals,2);
$my_not_animals[] = $not_animals[$keys[0]];
$my_not_animals[] = $not_animals[$keys[1]];
$my_animals[] = $my_not_animals[0];
$my_not_animals[] = $my_animals[0];
$e = mt_rand(1,9);
$f = $e + 1;
$d = mt_rand(1,9);
$s = intval($e + $d);
if ($e == $d)
{
$d ++;
$h = $d;
$l = $e;
}
elseif ($e < $d)
{
$h = $d;
$l = $e;
}
else
{
$h = $e;
$l = $d;
}
$spam_questions = array(
$f => 'What is the next number after '.$e.'? (Use only digits to answer)',
'white' => 'What color is snow? (give a 1 word answer to show you are a human)',
'green' => 'What color is grass? (give a 1 word answer to show you are a human)',
'blue' => 'What color is water? (give a 1 word answer to show you are a human)',
$ac => 'Access code (type <b>'.$ac.'</b> here):',
$ac => 'Type <i>'.$ac.'</i> here to fight SPAM:',
$s => 'Solve this equation to show you are human: '.$e.' + '.$d.' = ',
$my_animals[2] => 'Which of these is not an animal: ' . implode(', ',hesk_randomize_array($my_animals)),
$my_not_animals[2] => 'Which of these is an animal: ' . implode(', ',hesk_randomize_array($my_not_animals)),
$h => 'Which number is higher <b>'.$e.'</b> or <b>'.$d.'</b>:',
$l => 'Which number is lower <b>'.$e.'</b> or <b>'.$d.'</b>:',
'no' => 'Are you a robot? (yes or no)',
'yes' => 'Are you a human? (yes or no)'
);
$r = array_rand($spam_questions);
$ask = $spam_questions[$r];
$ans = $r;
return array($ask,$ans);
} // END hesk_generate_SPAM_question()
function hesk_randomize_array($array)
{
$rand_items = array_rand($array, count($array));
$new_array = array();
foreach($rand_items as $value)
{
$new_array[$value] = $array[$value];
}
return $new_array;
} // END hesk_randomize_array()
function hesk_checkMinMax($myint,$min,$max,$defval)
{
if ($myint > $max || $myint < $min)
{
return $defval;
}
return $myint;
} // END hesk_checkMinMax()
wget 'https://lists2.roe3.org/hesk/inc/show_admin_nav.inc.php'
<?php
/**
*
* This file is part of HESK - PHP Help Desk Software.
*
* (c) Copyright Klemen Stirn. All rights reserved.
* https://www.hesk.com
*
* For the full copyright and license agreement information visit
* https://www.hesk.com/eula.php
*
*/
/* Check if this is a valid include */
if (!defined('IN_SCRIPT')) {die('Invalid attempt');}
$num_mail = hesk_checkNewMail();
// Name of the page that is being requested, without '.php' at the end
$calling_script = basename($_SERVER['PHP_SELF'], '.php');
?>
<!-- NEW DESIGN -->
<aside class="main-menu">
<nav class="navbar">
<div class="navbar__header">
<button class="btn navbar__toggler" id="navbarToggler" type="button" aria-label="<?php echo $hesklang['toggle_navigation']; ?>">
<svg class="icon icon-menu">
<use xlink:href="<?php echo HESK_PATH; ?>img/sprite.svg#icon-menu"></use>
</svg>
</button>
<a class="navbar__logo" href="admin_main.php">
<?php echo $hesklang['help_desk']; ?>
</a>
</div>
<div class="navbar__menu-wrap">
<ul class="navbar__list">
<?php
$pages = array('admin_main', 'show_tickets', 'find_tickets');
$open_menu = in_array($calling_script, $pages) ? 'current' : '';
?>
<li class="listitem <?php echo $open_menu; ?>">
<div class="listitem__icon">
<a href="admin_main.php" aria-label="<?php echo $hesklang['tickets']; ?>">
<svg class="icon icon-tickets">
<use xlink:href="<?php echo HESK_PATH; ?>img/sprite.svg#icon-tickets"></use>
</svg>
</a>
</div>
<div class="listitem__menu">
<a href="admin_main.php" class="listitem__caption">
<?php echo $hesklang['tickets']; ?>
</a>
</div>
</li>
<?php if (hesk_checkPermission('can_man_canned',0) &&
hesk_checkPermission('can_man_ticket_tpl',0)) {
$pages = array('manage_canned', 'manage_ticket_templates');
$open_menu = in_array($calling_script, $pages) ? 'current submenu-is-opened' : '';
?>
<li class="listitem submenu <?php echo $open_menu; ?>">
<div class="listitem__icon">
<a href="#" aria-label="<?php echo $hesklang['responses']; ?>">
<svg class="icon icon-templates">
<use xlink:href="<?php echo HESK_PATH; ?>img/sprite.svg#icon-templates"></use>
</svg>
</a>
</div>
<div class="listitem__menu">
<a href="#" class="listitem__caption"><?php echo $hesklang['nav_templates']; ?></a>
<ul class="submenu__list">
<li class="submenu__listitem <?php if ($calling_script === 'manage_canned') { ?>current<?php } ?>">
<a href="manage_canned.php">
<?php echo $hesklang['responses']; ?>
</a>
</li>
<li class="submenu__listitem <?php if ($calling_script === 'manage_ticket_templates') { ?>current<?php } ?>">
<a href="manage_ticket_templates.php">
<?php echo $hesklang['tickets']; ?>
</a>
</li>
</ul>
</div>
</li>
<?php } elseif (hesk_checkPermission('can_man_canned',0)) { ?>
<li class="listitem <?php if ($calling_script === 'manage_canned') { ?>current<?php } ?>">
<div class="listitem__icon">
<a href="manage_canned.php" aria-label="<?php echo $hesklang['responses']; ?>">
<svg class="icon icon-tickets">
<use xlink:href="<?php echo HESK_PATH; ?>img/sprite.svg#icon-templates"></use>
</svg>
</a>
</div>
<div class="listitem__menu">
<a href="manage_canned.php" class="listitem__caption">
<?php echo $hesklang['responses']; ?>
</a>
</div>
</li>
<?php } elseif (hesk_checkPermission('can_man_ticket_tpl',0)) { ?>
<li class="listitem <?php if ($calling_script === 'manage_ticket_templates') { ?>current<?php } ?>">
<div class="listitem__icon">
<a href="manage_ticket_templates.php" aria-label="<?php echo $hesklang['nav_templates']; ?>">
<svg class="icon icon-tickets">
<use xlink:href="<?php echo HESK_PATH; ?>img/sprite.svg#icon-templates"></use>
</svg>
</a>
</div>
<div class="listitem__menu">
<a href="manage_ticket_templates.php" class="listitem__caption">
<?php echo $hesklang['nav_templates']; ?>
</a>
</div>
</li>
<?php
}
if ($hesk_settings['kb_enable'] && hesk_checkPermission('can_man_kb',0)) {
$pages = array('manage_knowledgebase', 'knowledgebase_private');
$open_menu = in_array($calling_script, $pages) ? 'current submenu-is-opened' : '';
?>
<li class="listitem submenu <?php echo $open_menu; ?>">
<div class="listitem__icon">
<a href="manage_knowledgebase.php" aria-label="<?php echo $hesklang['menu_kb_manage']; ?>">
<svg class="icon icon-knowledge">
<use xlink:href="<?php echo HESK_PATH; ?>img/sprite.svg#icon-knowledge"></use>
</svg>
</a>
</div>
<div class="listitem__menu">
<a href="#" class="listitem__caption"><?php echo $hesklang['menu_kb']; ?></a>
<ul class="submenu__list">
<li class="submenu__listitem <?php if ($calling_script === 'manage_knowledgebase') { ?>current<?php } ?>">
<a href="manage_knowledgebase.php">
<?php echo $hesklang['menu_kb_manage']; ?>
</a>
</li>
<li class="submenu__listitem <?php if ($calling_script === 'knowledgebase_private') { ?>current<?php } ?>">
<a href="knowledgebase_private.php">
<?php echo $hesklang['menu_kb_view']; ?>
</a>
</li>
</ul>
</div>
</li>
<?php
} elseif ($hesk_settings['kb_enable']) {
?>
<li class="listitem <?php if ($calling_script === 'knowledgebase_private') { ?>current<?php } ?>">
<div class="listitem__icon">
<a href="knowledgebase_private.php" aria-label="<?php echo $hesklang['menu_kb']; ?>">
<svg class="icon icon-knowledge">
<use xlink:href="<?php echo HESK_PATH; ?>img/sprite.svg#icon-knowledge"></use>
</svg>
</a>
</div>
<div class="listitem__menu">
<a href="knowledgebase_private.php" class="listitem__caption">
<?php echo $hesklang['menu_kb']; ?>
</a>
</div>
</li>
<?php
}
?>
<li class="listitem <?php if ($calling_script === 'manage_categories') { ?>current<?php } ?>">
<div class="listitem__icon">
<a href="manage_categories.php" aria-label="<?php echo $hesklang['menu_cat']; ?>">
<svg class="icon icon-categories">
<use xlink:href="<?php echo HESK_PATH; ?>img/sprite.svg#icon-categories"></use>
</svg>
</a>
</div>
<div class="listitem__menu">
<a href="manage_categories.php" class="listitem__caption">
<?php echo $hesklang['menu_cat']; ?>
</a>
</div>
</li>
<li class="separator"></li>
<?php
$number_of_accessible_pages = 0;
if (hesk_checkPermission('can_man_users',0) || hesk_checkPermission('can_view_users',0)) {
$number_of_accessible_pages++;
}
if (hesk_checkPermission('can_man_customers',0) || hesk_checkPermission('can_view_customers',0)) {
$number_of_accessible_pages++;
}
if (hesk_checkPermission('can_man_permission_groups',0)) {
$number_of_accessible_pages++;
}
if ($number_of_accessible_pages > 1):
$pages = array('manage_users', 'manage_customers', 'import_customers', 'manage_permission_groups');
$open_menu = in_array($calling_script, $pages) ? 'current submenu-is-opened' : '';
?>
<li class="listitem submenu <?php echo $open_menu; ?>">
<div class="listitem__icon">
<a href="#" aria-label="<?php echo $hesklang['team']; ?>">
<svg class="icon icon-team">
<use xlink:href="<?php echo HESK_PATH; ?>img/sprite.svg#icon-team"></use>
</svg>
</a>
</div>
<div class="separator"></div>
<div class="listitem__menu">
<?php
$show_badge = 0;
if ((hesk_checkPermission('can_man_customers', 0) || hesk_checkPermission('can_man_customers', 0)) && $hesk_settings['customer_accounts_admin_approvals']) {
$pending_customers = hesk_dbQuery("SELECT 1 FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."customers`
WHERE `verified` = 2");
$show_badge = hesk_dbNumRows($pending_customers);
}
?>
<a href="#" class="listitem__caption">
<?php
echo $hesklang['menu_users'];
if ($show_badge): ?>
<span class="admin-nav-badge"><?php echo $show_badge; ?></span>
<?php endif; ?>
</a>
<ul class="submenu__list">
<?php if (hesk_checkPermission('can_man_users',0) || hesk_checkPermission('can_view_users',0)): ?>
<li class="submenu__listitem <?php if ($calling_script === 'manage_users') { ?>current<?php } ?>">
<a href="manage_users.php">
<?php echo $hesklang['team']; ?>
</a>
</li>
<?php
endif;
if (hesk_checkPermission('can_man_customers',0) || hesk_checkPermission('can_view_customers',0)):
?>
<li class="submenu__listitem <?php if (in_array($calling_script, ['manage_customers','import_customers'])) { ?>current<?php } ?>">
<a href="manage_customers.php">
<?php
echo $hesklang['customers'];
if ($show_badge > 0):
?>
<span class="admin-nav-badge"><?php echo $show_badge; ?></span>
<?php endif; ?>
</a>
</li>
<?php
endif;
if (hesk_checkPermission('can_man_permission_groups',0)):
?>
<li class="submenu__listitem <?php if ($calling_script === 'manage_permission_groups') { ?>current<?php } ?>">
<a href="manage_permission_groups.php">
<?php echo $hesklang['permission_groups_title']; ?>
</a>
</li>
<?php endif; ?>
</ul>
</div>
</li>
<?php else: ?>
<?php if (hesk_checkPermission('can_man_users',0) || hesk_checkPermission('can_view_users',0)) { ?>
<li class="listitem <?php if (in_array($calling_script, ['manage_users'])) { ?>current<?php } ?>">
<div class="listitem__icon">
<a href="manage_users.php" aria-label="<?php echo $hesklang['team']; ?>">
<svg class="icon icon-team">
<use xlink:href="<?php echo HESK_PATH; ?>img/sprite.svg#icon-team"></use>
</svg>
</a>
</div>
<div class="listitem__menu">
<a href="manage_users.php" class="listitem__caption">
<?php echo $hesklang['team']; ?>
</a>
</div>
</li>
<?php
}
if (hesk_checkPermission('can_man_customers',0) || hesk_checkPermission('can_view_customers',0)) { ?>
<li class="listitem <?php if (in_array($calling_script, ['manage_customers','import_customers'])) { ?>current<?php } ?>">
<div class="listitem__icon">
<a href="manage_customers.php" aria-label="<?php echo $hesklang['customers']; ?>">
<svg class="icon icon-team">
<use xlink:href="<?php echo HESK_PATH; ?>img/sprite.svg#icon-team"></use>
</svg>
</a>
</div>
<div class="listitem__menu">
<a href="manage_customers.php" class="listitem__caption">
<?php echo $hesklang['customers']; ?>
</a>
</div>
</li>
<?php
}
if (hesk_checkPermission('can_man_permission_groups',0)) { ?>
<li class="listitem <?php if ($calling_script === 'manage_permission_groups') { ?>current<?php } ?>">
<div class="listitem__icon">
<a href="manage_permission_groups.php" aria-label="<?php echo $hesklang['permission_groups_title']; ?>">
<svg class="icon icon-team">
<use xlink:href="<?php echo HESK_PATH; ?>img/sprite.svg#icon-team"></use>
</svg>
</a>
</div>
<div class="listitem__menu">
<a href="manage_permission_groups.php" class="listitem__caption">
<?php echo $hesklang['permission_groups_title']; ?>
</a>
</div>
</li>
<?php
}
endif;
//Reports
if (hesk_checkPermission('can_run_reports',0)) {
$pages = array('reports', 'export');
$open_menu = in_array($calling_script, $pages) ? 'current submenu-is-opened' : '';
?>
<li class="listitem submenu <?php echo $open_menu; ?>">
<div class="listitem__icon">
<a href="#" aria-label="<?php echo $hesklang['reports_tab']; ?>">
<svg class="icon icon-reports">
<use xlink:href="<?php echo HESK_PATH; ?>img/sprite.svg#icon-reports"></use>
</svg>
</a>
</div>
<div class="separator"></div>
<div class="listitem__menu">
<a href="#" class="listitem__caption"><?php echo $hesklang['reports']; ?></a>
<ul class="submenu__list">
<li class="submenu__listitem <?php if ($calling_script === 'reports') { ?>current<?php } ?>">
<a href="reports.php">
<?php echo $hesklang['reports_tab']; ?>
</a>
</li>
<?php
if (hesk_checkPermission('can_export',0)) {
?>
<li class="submenu__listitem <?php if ($calling_script === 'export') { ?>current<?php } ?>">
<a href="export.php">
<?php echo $hesklang['export']; ?>
</a>
</li>
<?php
}
?>
</ul>
</div>
</li>
<?php
} elseif (hesk_checkPermission('can_export',0)) {
?>
<li class="listitem <?php if ($calling_script === 'export') { ?>current<?php } ?>">
<div class="listitem__icon">
<a href="export.php" aria-label="<?php echo $hesklang['export']; ?>">
<svg class="icon icon-team">
<use xlink:href="<?php echo HESK_PATH; ?>img/sprite.svg#icon-team"></use>
</svg>
</a>
</div>
<div class="listitem__menu">
<a href="export.php" class="listitem__caption">
<?php echo $hesklang['export']; ?>
</a>
</div>
</li>
<?php
}
// Modules
if (hesk_checkPermission('can_run_reports',0) ||
hesk_checkPermission('can_man_settings',0)) {
$pages = array('module_statistics', 'module_escalate', 'module_satisfaction', 'module_satisfaction_optout', 'module_recurring_tickets');
$open_menu = in_array($calling_script, $pages) ? 'current submenu-is-opened' : '';
?>
<li class="listitem submenu <?php echo $open_menu; ?>">
<div class="listitem__icon">
<a href="#" aria-label="<?php echo $hesklang['modules']; ?>">
<svg class="icon icon-modules">
<use xlink:href="<?php echo HESK_PATH; ?>img/sprite.svg#icon-modules"></use>
</svg>
</a>
</div>
<div class="listitem__menu">
<a href="#" class="listitem__caption">
<?php echo $hesklang['modules']; ?>
</a>
<ul class="submenu__list">
<?php if (hesk_checkPermission('can_run_reports',0)) {
?>
<li class="submenu__listitem <?php if ($calling_script === 'module_statistics') { ?>current<?php } ?>">
<a href="module_statistics.php">
<?php echo $hesklang['statistics']['tab']; ?>
</a>
</li>
<?php
}
if (hesk_checkPermission('can_man_settings',0)) {
?>
<li class="submenu__listitem <?php if ($calling_script === 'module_escalate') { ?>current<?php } ?>">
<a href="module_escalate.php">
<?php echo $hesklang['escalate']['tab']; ?>
</a>
</li>
<li class="submenu__listitem <?php if ($calling_script === 'module_satisfaction' || $calling_script === 'module_satisfaction_optout') { ?>current<?php } ?>">
<a href="module_satisfaction.php">
<?php echo $hesklang['satisfaction']['tab']; ?>
</a>
</li>
<li class="submenu__listitem <?php if ($calling_script === 'module_recurring_tickets') { ?>current<?php } ?>">
<a href="module_recurring_tickets.php">
<?php echo $hesklang['recurring_tickets']['tab']; ?>
</a>
</li>
<?php
}
?>
</ul>
</div>
</li>
<?php
}
// Tools
if (hesk_checkPermission('can_ban_emails',0) ||
hesk_checkPermission('can_mute_emails',0) ||
hesk_checkPermission('can_ban_ips',0) ||
hesk_checkPermission('can_service_msg',0) ||
hesk_checkPermission('can_email_tpl',0) ||
hesk_checkPermission('can_man_settings',0)) {
$pages = array('banned_emails', 'muted_emails', 'banned_ips', 'service_messages', 'email_templates', 'custom_fields', 'custom_statuses', 'oauth_providers', 'custom_priorities');
$open_menu = in_array($calling_script, $pages) ? 'current submenu-is-opened' : '';
?>
<li class="separator"></li>
<li class="listitem submenu <?php echo $open_menu; ?>">
<div class="listitem__icon">
<a href="#" aria-label="<?php echo $hesklang['tools']; ?>">
<svg class="icon icon-tools">
<use xlink:href="<?php echo HESK_PATH; ?>img/sprite.svg#icon-tools"></use>
</svg>
</a>
</div>
<div class="listitem__menu">
<a href="#" class="listitem__caption">
<?php echo $hesklang['tools']; ?>
</a>
<ul class="submenu__list">
<?php if (hesk_checkPermission('can_ban_emails',0)) {
?>
<li class="submenu__listitem <?php if ($calling_script === 'banned_emails') { ?>current<?php } ?>">
<a href="banned_emails.php">
<?php echo $hesklang['banemail']; ?>
</a>
</li>
<?php
}
if (hesk_checkPermission('can_mute_emails',0)) {
?>
<li class="submenu__listitem <?php if ($calling_script === 'muted_emails') { ?>current<?php } ?>">
<a href="muted_emails.php">
<?php echo $hesklang['mute_emails']; ?>
</a>
</li>
<?php
}
if (hesk_checkPermission('can_ban_ips',0)) {
?>
<li class="submenu__listitem <?php if ($calling_script === 'banned_ips') { ?>current<?php } ?>">
<a href="banned_ips.php">
<?php echo $hesklang['banip']; ?>
</a>
</li>
<?php
}
if (hesk_checkPermission('can_service_msg',0)) {
?>
<li class="submenu__listitem <?php if ($calling_script === 'service_messages') { ?>current<?php } ?>">
<a href="service_messages.php">
<?php echo $hesklang['sm_title']; ?>
</a>
</li>
<?php
}
if (hesk_checkPermission('can_email_tpl',0)) {
?>
<li class="submenu__listitem <?php if ($calling_script === 'email_templates') { ?>current<?php } ?>">
<a href="email_templates.php">
<?php echo $hesklang['et_title']; ?>
</a>
</li>
<?php
}
if (hesk_checkPermission('can_man_settings',0)) {
?>
<li class="submenu__listitem <?php if ($calling_script === 'custom_fields') { ?>current<?php } ?>">
<a href="custom_fields.php">
<?php echo $hesklang['tab_4']; ?>
</a>
</li>
<li class="submenu__listitem <?php if ($calling_script === 'custom_statuses') { ?>current<?php } ?>">
<a href="custom_statuses.php">
<?php echo $hesklang['statuses']; ?>
</a>
</li>
<li class="submenu__listitem <?php if ($calling_script === 'custom_priorities') { ?>current<?php } ?>">
<a href="custom_priorities.php">
<?php echo $hesklang['priorities']; ?>
</a>
</li>
<li class="submenu__listitem <?php if ($calling_script === 'oauth_providers') { ?>current<?php } ?>">
<a href="oauth_providers.php">
<?php echo $hesklang['email_oauth_providers']; ?>
</a>
</li>
<?php
}
?>
</ul>
</div>
</li>
<?php
}
if (hesk_checkPermission('can_man_settings',0)) {
$pages = array('admin_settings_custom_html', 'admin_settings_general', 'admin_settings_help_desk', 'admin_settings_theme', 'admin_settings_knowledgebase',
'admin_settings_email', 'admin_settings_ticket_list', 'admin_settings_misc');
$open_menu = in_array($calling_script, $pages) ? 'current submenu-is-opened' : '';
?>
<li class="listitem submenu <?php echo $open_menu; ?>">
<div class="listitem__icon">
<a href="#" aria-label="<?php echo $hesklang['settings']; ?>">
<svg class="icon icon-settings">
<use xlink:href="<?php echo HESK_PATH; ?>img/sprite.svg#icon-settings"></use>
</svg>
</a>
</div>
<div class="listitem__menu">
<a href="#" class="listitem__caption">
<?php echo $hesklang['settings']; ?>
</a>
<ul class="submenu__list">
<li class="submenu__listitem <?php if ($calling_script === 'admin_settings_general') { ?>current<?php } ?>">
<a href="admin_settings_general.php">
<?php echo $hesklang['tab_1']; ?>
</a>
</li>
<li class="submenu__listitem <?php if ($calling_script === 'admin_settings_help_desk') { ?>current<?php } ?>">
<a href="admin_settings_help_desk.php">
<?php echo $hesklang['tab_2']; ?>
</a>
</li>
<li class="submenu__listitem <?php if ($calling_script === 'admin_settings_theme' || $calling_script === 'admin_settings_custom_html') { ?>current<?php } ?>">
<a href="admin_settings_theme.php">
<?php echo $hesklang['tab_8']; ?>
</a>
</li>
<li class="submenu__listitem <?php if ($calling_script === 'admin_settings_knowledgebase') { ?>current<?php } ?>">
<a href="admin_settings_knowledgebase.php">
<?php echo $hesklang['tab_3']; ?>
</a>
</li>
<li class="submenu__listitem <?php if ($calling_script === 'admin_settings_email') { ?>current<?php } ?>">
<a href="admin_settings_email.php">
<?php echo $hesklang['tab_6']; ?>
</a>
</li>
<li class="submenu__listitem <?php if ($calling_script === 'admin_settings_ticket_list') { ?>current<?php } ?>">
<a href="admin_settings_ticket_list.php">
<?php echo $hesklang['tab_7']; ?>
</a>
</li>
<li class="submenu__listitem <?php if ($calling_script === 'admin_settings_misc') { ?>current<?php } ?>">
<a href="admin_settings_misc.php">
<?php echo $hesklang['tab_5']; ?>
</a>
</li>
</ul>
</div>
</li>
<?php
}
?>
<li class="separator mobile"></li>
<li class="listitem mobile <?php if ($calling_script === 'mail') { ?>current<?php } ?>">
<div class="listitem__icon">
<a href="mail.php" aria-label="<?php echo $hesklang['menu_msg']; ?>">
<svg class="icon icon-mail">
<use xlink:href="<?php echo HESK_PATH; ?>img/sprite.svg#icon-mail"></use>
</svg>
</a>
</div>
<div class="listitem__menu">
<a href="mail.php" class="listitem__caption">
<?php echo $hesklang['menu_msg']; ?>
</a>
<?php if ($num_mail > 0): ?>
<span class="badge listitem__notification">
<?php echo ($num_mail > 99) ? '99+' : $num_mail; ?>
</span>
<?php endif; ?>
</div>
</li>
<li class="listitem mobile <?php if ($calling_script === 'profile') { ?>current<?php } ?>">
<div class="listitem__icon">
<a href="profile.php" class="mobile_ava" aria-label="<?php echo $hesklang['profile']; ?>">
<?php
$letter = hesk_mb_substr($_SESSION['name'], 0, 1);
echo hesk_mb_strtoupper($letter);
?>
</a>
</div>
<div class="listitem__menu">
<a href="profile.php" class="listitem__caption">
<?php echo $hesklang['profile']; ?>
</a>
</div>
</li>
</ul>
</div>
</nav>
</aside>
<main class="main" id="maincontent">
<!-- begin header -->
<header class="header">
<div class="header__left">
</div>
<div class="header__right" style="border-left: none">
<a href="new_ticket.php" class="btn btn-full" ripple="ripple" aria-label="<?php echo $hesklang['create_new_ticket']; ?>">
<?php echo $hesklang['create_new_ticket']; ?>
</a>
<div class="profile">
<div class="profile__item profile__item--mail">
<a href="mail.php" class="btn btn-empty tooltip" title="<?php echo $hesklang['m_h']; ?>">
<div class="profile__item_rel">
<svg class="icon icon-mail">
<use xlink:href="<?php echo HESK_PATH; ?>img/sprite.svg#icon-mail"></use>
</svg>
<?php if ($num_mail > 0): ?>
<div class="badge"><?php echo ($num_mail > 99) ? '99+' : $num_mail; ?></div>
<?php
endif;
unset($num_mail);
?>
</div>
</a>
</div>
<div class="profile__item profile__user out-close">
<div class="user__ava" data-action="show-profile">
<?php
$letter = hesk_mb_substr($_SESSION['name'], 0, 1);
echo hesk_mb_strtoupper($letter);
?>
</div>
<div class="user__name" data-action="show-profile">
<p>
<span><?php echo $_SESSION['name']; ?></span>
<svg class="icon icon-chevron-down">
<use xlink:href="<?php echo HESK_PATH; ?>img/sprite.svg#icon-chevron-down"></use>
</svg>
</p>
</div>
<section class="profile__menu">
<div class="profile--view">
<a href="profile.php" class="btn btn-border" ripple="ripple"><?php echo $hesklang['view_profile']; ?></a>
</div>
<div class="profile--logout">
<a href="index.php?a=logout&token=<?php hesk_token_echo(); ?>">
<svg class="icon icon-log-out">
<use xlink:href="<?php echo HESK_PATH; ?>img/sprite.svg#icon-log-out"></use>
</svg>
<span><?php echo $hesklang['logout']; ?></span>
</a>
</div>
</section>
</div>
</div>
</div>
<div class="header__mobile">
<button class="btn btn-empty header__menu" data-action="toggle-menu" aria-label="<?php echo $hesklang['toggle_navigation']; ?>">
<svg class="icon icon-menu-mobile">
<use xlink:href="<?php echo HESK_PATH; ?>img/sprite.svg#icon-menu-mobile"></use>
</svg>
<svg class="icon icon-close-mobile">
<use xlink:href="<?php echo HESK_PATH; ?>img/sprite.svg#icon-close-mobile"></use>
</svg>
</button>
<a class="navbar__logo" href="admin_main.php"><?php echo $hesklang['help_desk']; ?></a>
<div class="header__mobile_actions">
<a href="new_ticket.php" class="btn btn-empty" data-action="create-ticket" aria-label="<?php echo $hesklang['create_new_ticket']; ?>">
<svg class="icon icon-add">
<use xlink:href="<?php echo HESK_PATH; ?>img/sprite.svg#icon-add"></use>
</svg>
</a>
</div>
</div>
</header>
<?php
// Show a notice if we are in maintenance mode
if ( hesk_check_maintenance(false) )
{
echo '<br />';
hesk_show_notice($hesklang['mma2'], $hesklang['mma1'], false);
}
// Show a notice if we are in "Knowledgebase only" mode
if ( hesk_check_kb_only(false) )
{
echo '<br />';
hesk_show_notice($hesklang['kbo2'], $hesklang['kbo1'], false);
}
?>
wget 'https://lists2.roe3.org/hesk/inc/show_search_form.inc.php'
<?php
/**
*
* This file is part of HESK - PHP Help Desk Software.
*
* (c) Copyright Klemen Stirn. All rights reserved.
* https://www.hesk.com
*
* For the full copyright and license agreement information visit
* https://www.hesk.com/eula.php
*
*/
/* Check if this is a valid include */
if (!defined('IN_SCRIPT')) {die('Invalid attempt');}
if ( ! isset($status) )
{
$status = $hesk_settings['statuses'];
unset($status[3]);
}
if ( ! isset($priority) )
{
$priority = hesk_possible_priorities();
}
if ( ! isset($priority_order) )
{
$priority_order = hesk_possible_priorities_order();
}
if ( ! isset($what) )
{
$what = 'trackid';
}
if ( ! isset($owner_input) )
{
$owner_input = 0;
}
if ( ! isset($date_input) )
{
$date_input = '';
}
if (hesk_GET('duedate_option') === '') {
$duedate_search_type = 'specific';
}
$duedate_input = hesk_GET('duedate_specific_date');
$duedate_amount_value = intval(hesk_GET('duedate_amount_value'));
$duedate_amount_unit = hesk_restricted_GET('duedate_amount_unit', ['day', 'week'], 'day');
/* Can view tickets that are unassigned or assigned to others? */
$can_view_ass_others = hesk_checkPermission('can_view_ass_others',0);
$can_view_unassigned = hesk_checkPermission('can_view_unassigned',0);
$can_view_ass_by = hesk_checkPermission('can_view_ass_by', 0);
/* Category options */
$category_options = '';
if ( isset($hesk_settings['categories']) && count($hesk_settings['categories']) )
{
foreach ($hesk_settings['categories'] as $row['id'] => $row['name'])
{
$row['name'] = (hesk_mb_strlen($row['name']) > 30) ? hesk_mb_substr($row['name'],0,30) . '...' : $row['name'];
$selected = (in_array($row['id'], $categories)) ? 'selected="selected"' : '';
$category_options .= '<option value="'.$row['id'].'" '.$selected.'>'.$row['name'].'</option>';
}
}
else
{
$res2 = hesk_dbQuery('SELECT `id`, `name` FROM `'.hesk_dbEscape($hesk_settings['db_pfix']).'categories` WHERE ' . hesk_myCategories('id') . ' ORDER BY `cat_order` ASC');
while ($row=hesk_dbFetchAssoc($res2))
{
$row['name'] = (hesk_mb_strlen($row['name']) > 30) ? hesk_mb_substr($row['name'],0,30) . '...' : $row['name'];
$selected = (in_array($row['id'], $categories)) ? 'selected="selected"' : '';
$category_options .= '<option value="'.$row['id'].'" '.$selected.'>'.$row['name'].'</option>';
}
}
/* List of staff */
if (($can_view_ass_others || $can_view_ass_by) && ! isset($admins))
{
$admins = array();
$res2 = hesk_dbQuery("SELECT `id`,`name` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."users` ORDER BY `name` ASC");
while ($row=hesk_dbFetchAssoc($res2))
{
$admins[$row['id']]=$row['name'];
}
}
$more = empty($_GET['more']) ? 0 : 1;
$more2 = empty($_GET['more2']) ? 0 : 1;
#echo "SQL: $sql";
?>
<!-- ** START SHOW TICKET FORM ** -->
<h2 style="font-size: 18px; font-weight: bold"><?php echo $hesklang['show_tickets']; ?></h2>
<div class="table-wrap">
<form name="showt" action="show_tickets.php" method="get" class="show_tickets form">
<div class="search-option">
<div class="search-name">
<?php echo $hesklang['status']; ?>
<br><a href="" id="selectAllStatus" class="plain_link"><?php echo $hesklang['a_select']; ?></a>
<br><a href="" id="deselectAllStatus" class="plain_link"><?php echo $hesklang['a_deselect']; ?></a>
<br><a href="" id="toggleAllStatus" class="plain_link"><?php echo $hesklang['a_toggle']; ?></a>
</div>
<div class="search-options">
<div class="checkbox-list">
<?php
hesk_get_status_checkboxes($status);
?>
</div>
</div>
</div>
<div id="topSubmit" style="display:<?php echo $more ? 'none' : 'block' ; ?>">
<div style="display: flex">
<button type="submit" class="btn btn-full"><?php echo $hesklang['show_tickets']; ?></button>
<a class="btn btn--blue-border" href="javascript:void(0)" onclick="Javascript:hesk_toggleLayerDisplay('divShow');Javascript:hesk_toggleLayerDisplay('topSubmit');document.showt.more.value='1';"><?php echo $hesklang['mopt']; ?></a>
</div>
</div>
<div id="divShow" style="display:<?php echo $more ? 'block' : 'none' ; ?>">
<div class="search-option">
<div class="search-name">
<?php echo $hesklang['priority']; ?>
<br><a href="" id="selectAllPriority" class="plain_link"><?php echo $hesklang['a_select']; ?></a>
<br><a href="" id="deselectAllPriority" class="plain_link"><?php echo $hesklang['a_deselect']; ?></a>
<br><a href="" id="toggleAllPriority" class="plain_link"><?php echo $hesklang['a_toggle']; ?></a>
</div>
<div class="search-options">
<div class="checkbox-list">
<?php
hesk_get_priority_checkboxes($priority);
?>
</div>
</div>
</div>
<div class="search-option">
<div class="search-name">
<?php echo $hesklang['show']; ?>
<br><a href="" id="selectAllShow" class="plain_link"><?php echo $hesklang['a_select']; ?></a>
<br><a href="" id="deselectAllShow" class="plain_link"><?php echo $hesklang['a_deselect']; ?></a>
<br><a href="" id="toggleAllShow" class="plain_link"><?php echo $hesklang['a_toggle']; ?></a>
</div>
<div class="search-options">
<div class="checkbox-list">
<div class="checkbox-custom">
<input type="checkbox" id="show_my" name="s_my" value="1" <?php if ($s_my[1]) echo 'checked'; ?>>
<label for="show_my"><?php echo $hesklang['s_my']; ?></label>
</div>
<?php
if ($can_view_unassigned)
{
?>
<div class="checkbox-custom">
<input type="checkbox" id="show_un" name="s_un" value="1" <?php if ($s_un[1]) echo 'checked'; ?>>
<label for="show_un"><?php echo $hesklang['s_un']; ?></label>
</div>
<?php
}
?>
<?php
if ($can_view_ass_others || $can_view_ass_by)
{
?>
<div class="checkbox-custom">
<input type="checkbox" id="show_ot" name="s_ot" value="1" <?php if ($s_ot[1]) echo 'checked'; ?>>
<label for="show_ot"><?php echo $hesklang['s_ot']; ?></label>
</div>
<?php
}
?>
<div class="checkbox-custom">
<input type="checkbox" id="show_archive" name="archive" value="1" <?php if ($archive[1]) echo 'checked'; ?>>
<label for="show_archive"><?php echo $hesklang['disp_only_archived']; ?></label>
</div>
</div>
</div>
</div>
<div class="search-option">
<div class="search-name">
<?php echo $hesklang['sort_by']; ?>
</div>
<div class="search-options">
<div class="radio-list">
<?php
array_unshift($hesk_settings['ticket_list'], 'priority');
$hesk_settings['possible_ticket_list']['priority'] = $hesklang['priority'];
foreach ($hesk_settings['ticket_list'] as $key):
if (!key_exists($key, $hesk_settings['possible_ticket_list'])) {
continue;
}
?>
<div class="radio-custom">
<input type="radio" id="sort<?php echo $key; ?>" name="sort" value="<?php echo $key; ?>"
<?php if ($sort == $key) { echo 'checked'; } ?>>
<label for="sort<?php echo $key; ?>">
<?php echo $hesk_settings['possible_ticket_list'][$key]; ?>
</label>
</div>
<?php endforeach; ?>
</div>
</div>
</div>
<div class="search-option">
<div class="search-name">
<?php echo $hesklang['gb']; ?>
</div>
<div class="search-options">
<div class="radio-list">
<div class="radio-custom">
<input type="radio" name="g" value="" id="g_" <?php if (!$group) {echo 'checked';} ?>>
<label for="g_">
<?php echo $hesklang['dg']; ?>
</label>
</div>
<?php
if ($can_view_unassigned || $can_view_ass_others || $can_view_ass_by)
{
?>
<div class="radio-custom">
<input type="radio" name="g" value="owner" id="g_owner" <?php if ($group == 'owner') {echo 'checked';} ?>>
<label for="g_owner">
<?php echo $hesklang['owner']; ?>
</label>
</div>
<?php
}
?>
<div class="radio-custom">
<input type="radio" name="g" value="category" id="g_category" <?php if ($group == 'category') {echo 'checked';} ?>>
<label for="g_category">
<?php echo $hesklang['category']; ?>
</label>
</div>
<div class="radio-custom">
<input type="radio" name="g" value="priority" id="g_priority" <?php if ($group == 'priority') {echo 'checked';} ?>>
<label for="g_priority">
<?php echo $hesklang['priority']; ?>
</label>
</div>
</div>
</div>
</div>
<div class="search-option">
<div class="search-name">
<?php echo $hesklang['due_date']; ?>
</div>
<div class="search-options">
<div class="radio-list">
<div class="radio-custom" style="margin-top: 0px;">
<input type="radio" id="duedate_specific" name="duedate_option" value="specific" <?php if ($duedate_search_type === 'specific') echo 'checked'; ?>>
<label for="duedate_specific"><?php echo $hesklang['search_due_date_specific']; ?></label>
<section class="param calendar">
<div class="calendar--button">
<button type="button" onclick="document.getElementById('duedate_specific').checked = true" aria-label="Search by due date">
<svg class="icon icon-calendar">
<use xlink:href="<?php echo HESK_PATH; ?>img/sprite.svg#icon-calendar"></use>
</svg>
</button>
<input name="duedate_specific_date" id="duedate_specific_date"
<?php if ($duedate_input) {echo 'value="'.hesk_htmlspecialchars($duedate_input).'"';} ?>
type="text" class="datepicker" aria-label="Search by due date">
</div>
<div class="calendar--value" <?php echo ($duedate_input ? 'style="display: block"' : ''); ?>>
<span><?php echo hesk_htmlspecialchars($duedate_input); ?></span>
<i class="close">
<svg class="icon icon-close">
<use xlink:href="<?php echo HESK_PATH; ?>img/sprite.svg#icon-close"></use>
</svg>
</i>
</div>
</section>
</div>
<div class="radio-custom">
<input type="radio" id="duedate_range" name="duedate_option" value="range" <?php if ($duedate_search_type === 'range') echo 'checked'; ?>>
<label for="duedate_range"><?php echo $hesklang['search_due_date_range']; ?></label>
<input class="form-control" type="text" id="duedate_amount_value" name="duedate_amount_value" value="<?php echo $duedate_amount_value; ?>" style="width: 25%"
onkeyup="document.getElementById('duedate_range').checked = true">
<label for="duedate_amount_value"> </label>
<select name="duedate_amount_unit" onclick="document.getElementById('duedate_range').checked = true" onchange="document.getElementById('duedate_range').checked = true" style="margin-top:5px;margin-bottom:5px;">
<option value="day" <?php if ($duedate_amount_unit === 'day') echo 'selected'; ?>><?php echo $hesklang['d_day']; ?></option>
<option value="week" <?php if ($duedate_amount_unit === 'week') echo 'selected'; ?>><?php echo $hesklang['d_week']; ?></option>
</select>
</div>
</div>
</div>
</div>
<script>
hesk_loadNoResultsSelectizePlugin('<?php echo hesk_jsString($hesklang['no_results_found']); ?>');
</script>
<div class="search-option">
<div class="search-name">
<?php echo $hesklang['category']; ?>
</div>
<div class="search-options">
<select name="c[]"
class="read-write"
multiple
auto-load-plugins="no_results,remove_button"
placeholder="<?php echo hesk_addslashes($hesklang['search_by_category']); ?>">
<?php echo $category_options; ?>
</select>
</div>
</div>
<div class="search-option">
<div class="search-name">
<?php echo $hesklang['display']; ?>
</div>
<div class="search-options">
<input class="form-control" type="text" name="limit" value="<?php echo $maxresults; ?>" style="width: 25%" aria-label="<?php echo $hesklang['tickets_page']; ?>">
<?php echo $hesklang['tickets_page']; ?>
</div>
</div>
<div class="search-option">
<div class="search-name">
<?php echo $hesklang['order']; ?>
</div>
<div class="search-options">
<div class="radio-list">
<div class="radio-custom">
<input type="radio" name="asc" value="1" id="g_asc1" <?php if ($asc) {echo 'checked';} ?>>
<label for="g_asc1">
<?php echo $hesklang['ascending']; ?>
</label>
</div>
<div class="radio-custom">
<input type="radio" name="asc" value="0" id="g_asc0" <?php if (!$asc) {echo 'checked';} ?>>
<label for="g_asc0">
<?php echo $hesklang['descending']; ?>
</label>
</div>
</div>
</div>
</div>
<div class="search-option">
<div class="search-name">
<?php echo $hesklang['opt']; ?>
</div>
<div class="search-options">
<div class="checkbox-list">
<div class="checkbox-custom">
<input type="checkbox" name="cot" id="g_cot" value="1" <?php if ($cot) {echo 'checked';} ?>>
<label for="g_cot"><?php echo $hesklang['cot']; ?></label>
</div>
<div class="checkbox-custom">
<input type="checkbox" name="def" value="1" id="g_def">
<label for="g_def"><?php echo $hesklang['def']; ?></label>
(<a href="admin_main.php?reset=1&token=<?php echo hesk_token_echo(0); ?>"><?php echo $hesklang['redv']; ?></a>)
</div>
</div>
</div>
</div>
<div id="bottomSubmit">
<div style="display: flex">
<button type="submit" id="bottom-showtickets" class="btn btn-full"><?php echo $hesklang['show_tickets']; ?></button>
<a class="btn btn--blue-border" href="javascript:void(0)" onclick="hesk_toggleLayerDisplay('divShow');hesk_toggleLayerDisplay('topSubmit');document.showt.more.value='0';"><?php echo $hesklang['lopt']; ?></a>
<input type="hidden" name="more" value="<?php echo $more ? 1 : 0 ; ?>">
</div>
</div>
</div>
</form>
</div>
<script>
// STATUS
$("#selectAllStatus").click(function(event) {
event.preventDefault();
$("[id^=status_][type=checkbox]").prop('checked', true);
});
$("#deselectAllStatus").click(function(event) {
event.preventDefault();
$("[id^=status_][type=checkbox]").prop('checked', false);
});
$("#toggleAllStatus").click(function(event) {
event.preventDefault();
$("[id^=status_][type=checkbox]").each(function() {
this.checked = !this.checked;
});
});
// PRIORITY
$("#selectAllPriority").click(function(event) {
event.preventDefault();
$("[id^=priority_][type=checkbox]").prop('checked', true);
});
$("#deselectAllPriority").click(function(event) {
event.preventDefault();
$("[id^=priority_][type=checkbox]").prop('checked', false);
});
$("#toggleAllPriority").click(function(event) {
event.preventDefault();
$("[id^=priority_][type=checkbox]").each(function() {
this.checked = !this.checked;
});
});
// SHOW
$("#selectAllShow").click(function(event) {
event.preventDefault();
$("[id^=show_][type=checkbox]").prop('checked', true);
});
$("#deselectAllShow").click(function(event) {
event.preventDefault();
$("[id^=show_][type=checkbox]").prop('checked', false);
});
$("#toggleAllShow").click(function(event) {
event.preventDefault();
$("[id^=show_][type=checkbox]").each(function() {
this.checked = !this.checked;
});
});
</script>
<!-- ** END SHOW TICKET FORM ** -->
<!-- ** START SEARCH TICKETS FORM ** -->
<h2 style="margin-top: 20px; font-size: 18px; font-weight: bold"><?php echo $hesklang['find_ticket_by']; ?></h2>
<div class="table-wrap" style="margin-bottom: 30px">
<form action="find_tickets.php" method="get" name="findby" id="findby" class="show_tickets form">
<div class="search-option">
<div class="search-name">
<?php echo $hesklang['s_in']; ?>
</div>
<div class="search-options">
<select name="what" aria-label="<?php echo $hesklang['s_in']; ?>">
<option value="trackid" <?php if ($what=='trackid') {echo 'selected="selected"';} ?> ><?php echo $hesklang['trackID']; ?></option>
<?php
if ($hesk_settings['sequential'])
{
?>
<option value="seqid" <?php if ($what=='seqid') {echo 'selected="selected"';} ?> ><?php echo $hesklang['seqid']; ?></option>
<?php
}
?>
<option value="name" <?php if ($what=='name') {echo 'selected="selected"';} ?> ><?php echo $hesklang['name']; ?></option>
<option value="email" <?php if ($what=='email') {echo 'selected="selected"';} ?> ><?php echo $hesklang['email']; ?></option>
<option value="subject" <?php if ($what=='subject') {echo 'selected="selected"';} ?> ><?php echo $hesklang['subject']; ?></option>
<option value="message" <?php if ($what=='message') {echo 'selected="selected"';} ?> ><?php echo $hesklang['message']; ?></option>
<?php
foreach ($hesk_settings['custom_fields'] as $k=>$v)
{
$selected = ($what == $k) ? 'selected="selected"' : '';
if ($v['use'])
{
$v['name'] = (hesk_mb_strlen($v['name']) > 30) ? hesk_mb_substr($v['name'],0,30) . '...' : $v['name'];
echo '<option value="'.$k.'" '.$selected.'>'.$v['name'].'</option>';
}
}
?>
<option value="customer" <?php if ($what=='customer') {echo 'selected="selected"';} ?> ><?php echo $hesklang['customer_id']; ?></option>
<option value="notes" <?php if ($what=='notes') {echo 'selected="selected"';} ?> ><?php echo $hesklang['notes']; ?></option>
<option value="ip" <?php if ($what=='ip') {echo 'selected="selected"';} ?> ><?php echo $hesklang['IP_addr']; ?></option>
</select>
</div>
</div>
<div class="search-option">
<div class="search-name">
<?php echo $hesklang['s_for']; ?>
</div>
<div class="search-options">
<input class="form-control" type="text" name="q" <?php if (isset($q)) {echo 'value="'.$q.'"';} ?> aria-label="<?php echo $hesklang['s_for']; ?>">
</div>
</div>
<div id="topSubmit2" style="display:<?php echo $more2 ? 'none' : 'block' ; ?>">
<div style="display: flex">
<button type="submit" class="btn btn-full" id="findticket"><?php echo $hesklang['find_ticket']; ?></button>
<a class="btn btn--blue-border" id="moreoptions2" href="javascript:void(0)" onclick="hesk_toggleLayerDisplay('divShow2');hesk_toggleLayerDisplay('topSubmit2');document.findby.more2.value='1';"><?php echo $hesklang['mopt']; ?></a>
</div>
</div>
<div id="divShow2" style="display:<?php echo $more2 ? 'block' : 'none' ; ?>">
<script>
hesk_loadNoResultsSelectizePlugin('<?php echo hesk_jsString($hesklang['no_results_found']); ?>');
</script>
<div class="search-option">
<div class="search-name">
<?php echo $hesklang['category']; ?>
</div>
<div class="search-options">
<select id="categoryfind" name="c[]"
class="read-write"
multiple
auto-load-plugins="no_results,remove_button"
placeholder="<?php echo hesk_addslashes($hesklang['search_by_category']); ?>">
<?php echo $category_options; ?>
</select>
</div>
</div>
<?php
if ($can_view_ass_others || $can_view_ass_by)
{
?>
<div class="search-option">
<div class="search-name">
<?php echo $hesklang['owner']; ?>
</div>
<div class="search-options">
<select id="ownerfind" name="owner">
<option value="0" ><?php echo $hesklang['anyown']; ?></option>
<?php
foreach ($admins as $staff_id => $staff_name)
{
echo '<option value="'.$staff_id.'" '.($owner_input == $staff_id ? 'selected="selected"' : '').'>'.$staff_name.'</option>';
}
?>
</select>
</div>
</div>
<?php
}
?>
<div class="search-option">
<div class="search-name">
<?php echo $hesklang['date']; ?>
</div>
<div class="search-options">
<section class="param calendar">
<div class="calendar--button">
<button type="button" aria-label="Find by due date">
<svg class="icon icon-calendar">
<use xlink:href="<?php echo HESK_PATH; ?>img/sprite.svg#icon-calendar"></use>
</svg>
</button>
<input name="dt" id="find-date"
<?php if ($date_input) {echo 'value="'.$date_input.'"';} ?>
type="text" class="datepicker" aria-label="Find by due date">
</div>
<div class="calendar--value" <?php echo ($date_input ? 'style="display: block"' : ''); ?>>
<span><?php echo $date_input; ?></span>
<i class="close">
<svg class="icon icon-close">
<use xlink:href="<?php echo HESK_PATH; ?>img/sprite.svg#icon-close"></use>
</svg>
</i>
</div>
</section>
</div>
</div>
<div class="search-option">
<div class="search-name">
<?php echo $hesklang['s_incl']; ?>
<br><a href="" id="selectAllFind" class="plain_link"><?php echo $hesklang['a_select']; ?></a>
<br><a href="" id="deselectAllFind" class="plain_link"><?php echo $hesklang['a_deselect']; ?></a>
<br><a href="" id="toggleAllFind" class="plain_link"><?php echo $hesklang['a_toggle']; ?></a>
</div>
<div class="search-options">
<div class="checkbox-list">
<div class="checkbox-custom">
<input type="checkbox" id="find_show_my" name="s_my" value="1" <?php if ($s_my[2]) echo 'checked'; ?>>
<label for="find_show_my"><?php echo $hesklang['s_my']; ?></label>
</div>
<?php
if ($can_view_ass_others || $can_view_ass_by)
{
?>
<div class="checkbox-custom">
<input type="checkbox" id="find_show_ot" name="s_ot" value="1" <?php if ($s_ot[2]) echo 'checked'; ?>>
<label for="find_show_ot"><?php echo $hesklang['s_ot']; ?></label>
</div>
<?php
}
if ($can_view_unassigned)
{
?>
<div class="checkbox-custom">
<input type="checkbox" id="find_show_un" name="s_un" value="1" <?php if ($s_un[2]) echo 'checked'; ?>>
<label for="find_show_un"><?php echo $hesklang['s_un']; ?></label>
</div>
<?php
}
?>
<div class="checkbox-custom">
<input type="checkbox" id="find_archive" name="archive" value="1" <?php if ($archive[2]) echo 'checked'; ?>>
<label for="find_archive"><?php echo $hesklang['disp_only_archived']; ?></label>
</div>
</div>
</div>
</div>
<div class="search-option">
<div class="search-name">
<?php echo $hesklang['display']; ?>
</div>
<div class="search-options">
<input type="text" name="limit" value="<?php echo $maxresults; ?>" class="form-control" style="width: 25%" aria-label="<?php echo $hesklang['results_page']; ?>">
<?php echo $hesklang['results_page']; ?>
</div>
</div>
<div id="bottomSubmit">
<div style="display: flex">
<button type="submit" id="findticket2" class="btn btn-full"><?php echo $hesklang['find_ticket']; ?></button>
<a class="btn btn--blue-border" href="javascript:void(0)" onclick="hesk_toggleLayerDisplay('divShow2');hesk_toggleLayerDisplay('topSubmit2');document.findby.more2.value='0';"><?php echo $hesklang['lopt']; ?></a>
<input type="hidden" name="more2" value="<?php echo $more2 ? 1 : 0 ; ?>">
</div>
</div>
</div>
</form>
</div>
<script>
$("#selectAllFind").click(function(event) {
event.preventDefault();
$("[id^=find_][type=checkbox]").prop('checked', true);
});
$("#deselectAllFind").click(function(event) {
event.preventDefault();
$("[id^=find_][type=checkbox]").prop('checked', false);
});
$("#toggleAllFind").click(function(event) {
event.preventDefault();
$("[id^=find_][type=checkbox]").each(function() {
this.checked = !this.checked;
});
});
</script>
<!-- ** END SEARCH TICKETS FORM ** -->
wget 'https://lists2.roe3.org/hesk/inc/statuses.inc.php'
<?php
/**
*
* This file is part of HESK - PHP Help Desk Software.
*
* (c) Copyright Klemen Stirn. All rights reserved.
* https://www.hesk.com
*
* For the full copyright and license agreement information visit
* https://www.hesk.com/eula.php
*
*/
/* Check if this is a valid include */
if (!defined('IN_SCRIPT')) {die('Invalid attempt');}
// Load available statuses
hesk_load_statuses();
/*** FUNCTIONS ***/
function hesk_load_statuses($use_cache=1)
{
global $hesk_settings, $hesklang;
// Do we have a cached version available
$cache_dir = dirname(dirname(__FILE__)).'/'.$hesk_settings['cache_dir'].'/';
$cache_file = $cache_dir . 'status_' . sha1($hesk_settings['language']).'.cache.php';
if ($use_cache && file_exists($cache_file))
{
require($cache_file);
return true;
}
// Define statuses array
$hesk_settings['statuses'] = array();
// HESK default statuses:
//
// 0 = NEW
$hesk_settings['statuses'][0] = array(
'name' => $hesklang['open'],
'class' => 'open',
);
// 1 = CUSTOMER REPLIED
$hesk_settings['statuses'][1] = array(
'name' => $hesklang['wait_reply'],
'class' => 'waitingreply',
);
// 2 = STAFF REPLIED
$hesk_settings['statuses'][2] = array(
'name' => $hesklang['replied'],
'class' => 'replied',
);
// 3 = RESOLVED
$hesk_settings['statuses'][3] = array(
'name' => $hesklang['closed'],
'class' => 'resolved',
);
// 4 = IN PROGRESS
$hesk_settings['statuses'][4] = array(
'name' => $hesklang['in_progress'],
'class' => 'inprogress',
);
// 5 = ON HOLD
$hesk_settings['statuses'][5] = array(
'name' => $hesklang['on_hold'],
'class' => 'onhold',
);
// Make sure we have database connection
hesk_load_database_functions();
hesk_dbConnect();
$res = hesk_dbQuery("SELECT `id`, `name`, `color`, `can_customers_change` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."custom_statuses` ORDER BY `id` ASC");
while ($row = hesk_dbFetchAssoc($res))
{
// Let's set status name for current language (or the first one we find)
$names = json_decode($row['name'], true);
$row['name'] = (isset($names[$hesk_settings['language']])) ? $names[$hesk_settings['language']] : reset($names);
// Add to statuses array
$hesk_settings['statuses'][$row['id']] = array(
'name' => $row['name'],
'color' => '#'.$row['color'],
'can_customers_change' => $row['can_customers_change'],
);
}
// Try to cache results
if ($use_cache && (is_dir($cache_dir) || ( @mkdir($cache_dir, 0777) && is_writable($cache_dir) ) ) )
{
// Is there an index.htm file?
if ( ! file_exists($cache_dir.'index.htm'))
{
@file_put_contents($cache_dir.'index.htm', '');
}
// Write data
@file_put_contents($cache_file, '<?php if (!defined(\'IN_SCRIPT\')) {die();} $hesk_settings[\'statuses\']=' . var_export($hesk_settings['statuses'], true) . ';' );
}
return true;
} // END hesk_load_statuses()
function hesk_get_status_select($ignore_status = '', $can_resolve = true, $select_status = '')
{
global $hesk_settings;
$options = '';
$last = '';
foreach ($hesk_settings['statuses'] as $k => $v)
{
if ($k === $ignore_status)
{
continue;
}
elseif ($k == 3)
{
if ($can_resolve || $k == $select_status)
{
$last = '<option value="'.$k.'" '.($k == $select_status ? 'selected' : '').'>'.$v['name'].'</option>';
}
}
else
{
$options .= '<option value="'.$k.'" '.($k == $select_status ? 'selected' : '').'>'.$v['name'].'</option>';
}
}
return $options . $last;
} // END hesk_get_status_select()
function hesk_get_status_checkboxes($selected = array())
{
global $hesk_settings;
$i = 0;
echo '<div class="checkbox-group list">';
$has_row = false;
foreach ($hesk_settings['statuses'] as $k => $v) {
if ($i % 3 === 0) {
echo '<div class="row">';
$has_row = true;
}
echo '
<div class="checkbox-custom">
<input type="checkbox" id="status_'.$k.'" name="s'.$k.'" value="1" '.(isset($selected[$k]) ? 'checked' : '').'>
<label for="status_'.$k.'">'.hesk_get_admin_ticket_status($k).'</label>
</div>';
if ($i % 3 === 2) {
echo '</div>';
$has_row = false;
}
$i++;
}
if ($has_row) echo '</div>';
echo '</div>';
} // END hesk_get_status_select()
function hesk_get_status_name($status)
{
global $hesk_settings, $hesklang;
return isset($hesk_settings['statuses'][$status]['name']) ? $hesk_settings['statuses'][$status]['name'] : $hesklang['unknown'];
} // END hesk_get_status_name()
function hesk_get_admin_ticket_status($status, $append = '')
{
return hesk_get_ticket_status($status, $append, 0);
} // END hesk_get_admin_ticket_status()
function hesk_get_ticket_status($status, $append = '', $check_change = 1)
{
global $hesk_settings, $hesklang;
// Is this a valid status?
if ( ! isset($hesk_settings['statuses'][$status]['name']))
{
return $hesklang['unknown'];
}
// In the customer side check if this status can be changed
if ($check_change && ! hesk_can_customer_change_status($status))
{
if (isset($hesk_settings['statuses'][$status]['color']))
{
return '<span style="color:'.$hesk_settings['statuses'][$status]['color'].'">'.$hesk_settings['statuses'][$status]['name'].'</span>';
}
return $hesk_settings['statuses'][$status]['name'];
}
// Is this a default status? Use style class to add color
if (isset($hesk_settings['statuses'][$status]['class']))
{
return '<span class="'.$hesk_settings['statuses'][$status]['class'].'">'.$hesk_settings['statuses'][$status]['name'].'</span>' . $append;
}
// Does this status have a color code?
if (isset($hesk_settings['statuses'][$status]['color']))
{
return '<span style="color:'.$hesk_settings['statuses'][$status]['color'].'">'.$hesk_settings['statuses'][$status]['name'].'</span>' . $append;
}
// Just return the name if nothing matches
return $hesk_settings['statuses'][$status]['name'] . $append;
} // END hesk_get_ticket_status()
function hesk_get_ticket_status_from_DB($trackingID)
{
global $hesk_settings, $hesklang;
if (empty($trackingID)) {
hesk_error($hesklang['no_trackID']);
}
$result = hesk_dbQuery("SELECT `status` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` WHERE `trackid`='".hesk_dbEscape($trackingID)."' LIMIT 1");
if (hesk_dbNumRows($result) != 1) {
hesk_error($hesklang['ticket_not_found']);
}
return hesk_dbResult($result);
} // END hesk_get_ticket_status_from_DB()
function hesk_can_customer_change_status($status)
{
global $hesk_settings;
return ( ! isset($hesk_settings['statuses'][$status]['can_customers_change']) || $hesk_settings['statuses'][$status]['can_customers_change'] == '1') ? true : false;
} // END hesk_get_ticket_status()
function hesk_print_status_select_box_jquery()
{
global $hesk_settings;
?>
<script>
$(document).ready(function() {
<?php
$data_options = array();
foreach ($hesk_settings['statuses'] as $id => $data)
{
// Is this a default status? Use style class to add color
if (isset($data['class']))
{
$data_options[$id] = array('class' => $data['class']);
echo '$("#ticket-status-div > div.dropdown-select > ul.dropdown-list > li[data-option=\''.$id.'\']").addClass("'.$data['class'].'");'."\n";
echo '
$("#ticket-status-div > div.dropdown-select > div.label > span").filter(function () {
return $(this).text() == "'.addslashes($data['name']).'";
}).addClass("'.$data['class'].'");'."\n";
echo '$("#submit-as-div > ul.dropdown-list > li[data-option=\'submit_as-'.$id.'\']").addClass("'.$data['class'].'");'."\n";
continue;
}
// Does this status have a color code?
if (isset($data['color']))
{
$data_options[$id] = array('color' => $data['color']);
echo '$("#ticket-status-div > div.dropdown-select > ul.dropdown-list > li[data-option=\''.$id.'\']").css("color", "'.$data['color'].'");'."\n";
echo '
$("#ticket-status-div > div.dropdown-select > div.label > span").filter(function () {
return $(this).text() == "'.addslashes($data['name']).'";
}).css("color", "'.$data['color'].'");'."\n";
echo '$("#submit-as-div > ul.dropdown-list > li[data-option=\'submit_as-'.$id.'\']").css("color", "'.$data['color'].'");'."\n";
}
}
?>
});
function hesk_update_status_color(this_id)
{
$("#ticket-status-div > div.dropdown-select > div.label > span").removeClass();
$("#ticket-status-div > div.dropdown-select > div.label > span").removeAttr('style');
<?php
foreach($data_options as $id => $data) {
echo 'if (this_id == '.$id.') {';
if (isset($data['class'])) {
echo '$("#ticket-status-div > div.dropdown-select > div.label > span").addClass("'.$data['class'].'");';
} else {
echo '$("#ticket-status-div > div.dropdown-select > div.label > span").css("color", "'.$data['color'].'");';
}
echo 'return;}';
}
?>
}
</script>
<?php
} // END hesk_print_status_select_box_jquery()
wget 'https://lists2.roe3.org/hesk/inc/theme_variables.inc.php'
<?php
/**
*
* This file is part of HESK - PHP Help Desk Software.
*
* (c) Copyright Klemen Stirn. All rights reserved.
* https://www.hesk.com
*
* For the full copyright and license agreement information visit
* https://www.hesk.com/eula.php
*
*/
/* Check if this is a valid include */
if (!defined('IN_SCRIPT')) {die('Invalid attempt');}
/*
* variable - name of the CSS variable
* derivative - whether this color is a derivative of another color (i.e. via the use of var() or color-mix())
*/
$theme_color_settings = array(
array('variable' => '--yellow-1', 'derivative' => false),
array('variable' => '--yellow-2', 'derivative' => false),
array('variable' => '--green-1', 'derivative' => false),
array('variable' => '--red-1', 'derivative' => false),
array('variable' => '--red-2', 'derivative' => false),
array('variable' => '--success', 'derivative' => true),
array('variable' => '--success-2', 'derivative' => false),
array('variable' => '--error', 'derivative' => true),
array('variable' => '--error-2', 'derivative' => false),
array('variable' => '--error-3', 'derivative' => false),
array('variable' => '--warning', 'derivative' => true),
array('variable' => '--warning-2', 'derivative' => false),
array('variable' => '--info', 'derivative' => false),
array('variable' => '--info-2', 'derivative' => false),
array('variable' => '--info-3', 'derivative' => false), // TODO sort of derivative, but from one of default color vars
array('variable' => '--notification__clr', 'derivative' => true),
array('variable' => '--primary', 'derivative' => false),
array('variable' => '--secondary', 'derivative' => false),
array('variable' => '--tertiary', 'derivative' => false),
array('variable' => '--surface', 'derivative' => false),
array('variable' => '--main-background', 'derivative' => false),
array('variable' => '--font__pri-clr', 'derivative' => false),
array('variable' => '--font__sec-clr', 'derivative' => false),
array('variable' => '--header__bg', 'derivative' => true),
array('variable' => '--header_logo__clr', 'derivative' => true),
array('variable' => '--header_nav__clr', 'derivative' => true),
array('variable' => '--header_nav__hover_clr', 'derivative' => true),
array('variable' => '--input-bg', 'derivative' => false),
array('variable' => '--input-clr', 'derivative' => false),
array('variable' => '--link__pri-clr', 'derivative' => true),
array('variable' => '--link__pri-hover-clr', 'derivative' => true),
array('variable' => '--link__sec-clr', 'derivative' => true),
array('variable' => '--link__sec-hover-clr', 'derivative' => true),
array('variable' => '--footer__link-clr', 'derivative' => true),
array('variable' => '--radio__bg', 'derivative' => true),
array('variable' => '--radio__fill-clr', 'derivative' => true),
array('variable' => '--radio__hover-bg', 'derivative' => true),
array('variable' => '--radio__hover-fill-clr', 'derivative' => true),
array('variable' => '--checkbox__bg', 'derivative' => true),
array('variable' => '--checkbox__hover-bg', 'derivative' => true),
// Navigation section
array('variable' => '--breadcrumbs__a-clr', 'derivative' => true),
array('variable' => '--breadcrumbs__a-hover-clr', 'derivative' => true),
array('variable' => '--header_profile__clr', 'derivative' => true),
array('variable' => '--header_profile__menu-bg', 'derivative' => true),
array('variable' => '--header_profile__user-avatar-bg', 'derivative' => true),
array('variable' => '--header_profile__mobile-user-avatar-bg', 'derivative' => true),
array('variable' => '--navlink__bg', 'derivative' => true),
array('variable' => '--navlink__clr', 'derivative' => true),
array('variable' => '--navlink__hover-bg', 'derivative' => true),
array('variable' => '--navlink__title-clr', 'derivative' => true),
array('variable' => '--step_bar__item-clr', 'derivative' => true),
// Articles/Previews
array('variable' => '--preview__bg', 'derivative' => true),
array('variable' => '--preview__border-clr', 'derivative' => true),
array('variable' => '--preview__hover-bg', 'derivative' => true),
array('variable' => '--preview__hover-icon-fill', 'derivative' => true),
array('variable' => '--preview__title-clr', 'derivative' => true),
array('variable' => '--suggest_preview__bg', 'derivative' => true),
array('variable' => '--suggest_preview__clr', 'derivative' => true),
array('variable' => '--suggest_preview__border-clr', 'derivative' => true),
array('variable' => '--suggest_preview__hover-bg', 'derivative' => true),
array('variable' => '--suggest_preview__hover-icon-fill', 'derivative' => true),
array('variable' => '--suggest_preview__title-clr', 'derivative' => true),
array('variable' => '--article_preview__hover-clr', 'derivative' => true),
array('variable' => '--article_preview_suggestion_clr', 'derivative' => true),
// Misc
array('variable' => '--ticket_body__bg', 'derivative' => true),
array('variable' => '--ticket_response__bg', 'derivative' => true),
array('variable' => '--table_row__bg', 'derivative' => true),
array('variable' => '--table_row__bg-even', 'derivative' => false), // TODO potentially change back later
array('variable' => '--table_row__bg-hover', 'derivative' => false), // TODO sort of derivative, but from one of default color vars
array('variable' => '--search__clr', 'derivative' => true),
array('variable' => '--search__bg', 'derivative' => true),
array('variable' => '--search__title-clr', 'derivative' => true),
array('variable' => '--search__input-placeholder-clr', 'derivative' => true),
array('variable' => '--search__icon-fill', 'derivative' => true),
array('variable' => '--search__input-bg', 'derivative' => true),
array('variable' => '--modal_body__bg', 'derivative' => true),
array('variable' => '--btn__bg-clr-pri', 'derivative' => true),
array('variable' => '--btn__clr-pri', 'derivative' => true),
array('variable' => '--btn__border-clr-pri', 'derivative' => true),
array('variable' => '--btn__disabled-bg-clr', 'derivative' => false), // TODO sort of derivative, but from one of default color vars
array('variable' => '--btn__disabled-clr', 'derivative' => false), // TODO sort of derivative, but from one of default color vars
array('variable' => '--dropdown__bg', 'derivative' => true),
array('variable' => '--dropdown__clr', 'derivative' => true),
array('variable' => '--dropdown__border-clr', 'derivative' => true),
array('variable' => '--dropdown_ver1__border-clr', 'derivative' => false), // TODO sort of derivative, but from one of default color vars
array('variable' => '--dropdown_ver2__border-clr', 'derivative' => true),
array('variable' => '--dropdown__hover-bg', 'derivative' => true),
array('variable' => '--dropdown__hover-clr', 'derivative' => true),
array('variable' => '--dropdown__hover-border-clr', 'derivative' => true),
array('variable' => '--dropdown_ver2__hover-border-clr', 'derivative' => true),
array('variable' => '--datepicker_btn__bg', 'derivative' => true),
array('variable' => '--datepicker_btn__clr', 'derivative' => true),
array('variable' => '--datepicker__bg', 'derivative' => true),
array('variable' => '--datepicker__clr', 'derivative' => true),
);
// Helper var that helps order the various settings into manageable/clear groups
/* Rough example of current variable counts:
Let's count the variables in theme_color_settings_groups:
1. main_brand: 7
2. main_elements: 17
3. buttons: 5
4. navigation: 11
5. dropdowns: 9
6. datepickers: 4
7. base_colors: 5
8. notifications: 11
9. search: 6
10. article_previews: 13
11. misc: 6
*/
$theme_color_settings_groups = array(
'main_brand' => array('--primary', '--secondary', '--tertiary', '--surface', '--main-background', '--font__pri-clr', '--font__sec-clr'),
'main_elements' => array('--header__bg', '--header_logo__clr', '--header_nav__clr', '--header_nav__hover_clr', '--input-bg', '--input-clr', '--link__pri-clr', '--link__pri-hover-clr', '--link__sec-clr', '--link__sec-hover-clr', '--footer__link-clr', '--radio__bg', '--radio__fill-clr', '--radio__hover-bg', '--radio__hover-fill-clr', '--checkbox__bg', '--checkbox__hover-bg' ),
'buttons' => array('--btn__bg-clr-pri', '--btn__clr-pri', '--btn__border-clr-pri', '--btn__disabled-bg-clr', '--btn__disabled-clr'),
'navigation' => array('--breadcrumbs__a-clr', '--breadcrumbs__a-hover-clr', '--header_profile__clr', '--header_profile__menu-bg', '--header_profile__user-avatar-bg', '--header_profile__mobile-user-avatar-bg', '--navlink__bg', '--navlink__clr', '--navlink__hover-bg', '--navlink__title-clr', '--step_bar__item-clr'),
'dropdowns' => array('--dropdown__bg', '--dropdown__clr', '--dropdown__border-clr', '--dropdown_ver1__border-clr', '--dropdown_ver2__border-clr', '--dropdown__hover-bg', '--dropdown__hover-clr', '--dropdown__hover-border-clr', '--dropdown_ver2__hover-border-clr'),
'datepickers' => array('--datepicker_btn__bg', '--datepicker_btn__clr', '--datepicker__bg', '--datepicker__clr'),
'base_colors' => array('--yellow-1', '--yellow-2', '--green-1', '--red-1', '--red-2'),
'notifications' => array('--success', '--success-2', '--error', '--error-2', '--error-3', '--warning', '--warning-2', '--info', '--info-2', '--info-3', '--notification__clr'),
'search' => array('--search__clr', '--search__bg', '--search__title-clr', '--search__input-placeholder-clr', '--search__icon-fill', '--search__input-bg'),
'article_previews' => array('--preview__bg', '--preview__border-clr', '--preview__hover-bg', '--preview__hover-icon-fill', '--preview__title-clr', '--suggest_preview__bg', '--suggest_preview__clr', '--suggest_preview__border-clr', '--suggest_preview__hover-bg', '--suggest_preview__hover-icon-fill', '--suggest_preview__title-clr', '--article_preview__hover-clr', '--article_preview_suggestion_clr'),
'misc' => array('--ticket_body__bg', '--ticket_response__bg', '--table_row__bg', '--table_row__bg-even', '--table_row__bg-hover', '--modal_body__bg'),
);
function get_theme_color_setting($css_variable_key) {
global $theme_color_settings;
$color_setting = array_filter($theme_color_settings, function($setting) use ($css_variable_key) {
return $setting['variable'] === $css_variable_key;
});
$color_setting = reset($color_setting);
return $color_setting;
}
function hesk_is_valid_color_hex($hex)
{
$hex = strtolower($hex);
return preg_match('/^\#[a-f0-9]{6}$/', $hex) ? true : false;
} // END hesk_is_valid_color_hex()
wget 'https://lists2.roe3.org/hesk/inc/ticket_list.inc.php'
<?php
/**
*
* This file is part of HESK - PHP Help Desk Software.
*
* (c) Copyright Klemen Stirn. All rights reserved.
* https://www.hesk.com
*
* For the full copyright and license agreement information visit
* https://www.hesk.com/eula.php
*
*/
/* Check if this is a valid include */
if (!defined('IN_SCRIPT')) {die('Invalid attempt');}
// List of staff and check their permissions
$staff_that_can_view_tickets = hesk_getUserIdsWithAccessToFeatureAndCategory('can_view_tickets');
$admins = array();
$can_assign_to = array();
$res2 = hesk_dbQuery("SELECT `id`,`name`,`isadmin`,`active` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."users` ORDER BY `name` ASC");
while ($row = hesk_dbFetchAssoc($res2))
{
$admins[$row['id']] = $row['name'];
if ( ! $row['active']) {
continue;
}
if ($row['isadmin'] || in_array($row['id'], $staff_that_can_view_tickets))
{
$can_assign_to[$row['id']] = $row['name'];
}
}
/* List of categories */
if ( ! isset($hesk_settings['categories']))
{
$hesk_settings['categories'] = array();
$res2 = hesk_dbQuery('SELECT `id`, `name` FROM `'.hesk_dbEscape($hesk_settings['db_pfix']).'categories` WHERE ' . hesk_myCategories('id') . ' ORDER BY `cat_order` ASC');
while ($row=hesk_dbFetchAssoc($res2))
{
$hesk_settings['categories'][$row['id']] = $row['name'];
}
}
/* Current MySQL time */
$mysql_time = hesk_dbTime();
/* Get number of tickets and page number */
$result = hesk_dbQuery($sql_count);
while ($row = hesk_dbFetchAssoc($result))
{
// Total tickets found
$totals['filtered']['all'] += $row['cnt'];
// Total by status
if (isset($totals['filtered']['by_status'][$row['status']]))
{
$totals['filtered']['by_status'][$row['status']] += $row['cnt'];
}
else
{
$totals['filtered']['by_status'][$row['status']] = $row['cnt'];
}
// Count all filtered open tickets
if (isset($row['status']) && $row['status'] != 3)
{
$totals['filtered']['open'] += $row['cnt'];
}
// Totals by assigned to
if (isset($row['assigned_to'])):
switch ($row['assigned_to'])
{
case 1:
$totals['filtered']['assigned_to_me'] += $row['cnt'];
break;
case 2:
$totals['filtered']['assigned_to_others'] += $row['cnt'];
break;
case 3:
$totals['filtered']['assigned_to_others'] += $row['cnt'];
$totals['filtered']['assigned_to_others_by_me'] += $row['cnt'];
break;
default:
$totals['filtered']['unassigned'] += $row['cnt'];
}
if ( ! empty($row['is_collaborator']))
{
switch ($row['assigned_to'])
{
case 1:
$totals['filtered']['collaborator_assigned_to_me'] += $row['cnt'];
break;
case 2:
$totals['filtered']['collaborator_assigned_to_others'] += $row['cnt'];
break;
case 3:
$totals['filtered']['collaborator_assigned_to_others'] += $row['cnt'];
$totals['filtered']['collaborator_assigned_to_others_by_me'] += $row['cnt'];
break;
default:
$totals['filtered']['collaborator_unassigned'] += $row['cnt'];
}
}
endif;
// Total by due date; ignore for Resolved tickets
if ($row['status'] != 3)
{
switch ($row['due'])
{
case 1:
$totals['filtered']['due_soon'] += $row['cnt'];
break;
case 2:
$totals['filtered']['overdue'] += $row['cnt'];
break;
}
}
// Total bookmarks
if ( ! empty($row['is_bookmark']))
{
$totals['filtered']['bookmarks'] += $row['cnt'];
}
}
$result = hesk_dbQuery($sql_collaborator);
while ($row = hesk_dbFetchAssoc($result))
{
// Total collaborator tickets
$totals['filtered']['collaborator'] += $row['cnt'];
}
// Quick link: assigned to me
if ($is_quick_link == 'my')
{
$total = $totals['filtered']['assigned_to_me'];
}
// Quick link: collaborator
elseif ($is_quick_link == 'cbm')
{
$total = $totals['filtered']['collaborator'];
}
// Quick link: assigned to other
elseif ($is_quick_link == 'ot')
{
$total = $can_view_ass_others ? $totals['filtered']['assigned_to_others'] : $totals['filtered']['assigned_to_others_by_me'];
}
// Quick link: unassigned
elseif ($is_quick_link == 'un')
{
$total = $totals['filtered']['unassigned'];
}
// Quick link: bookmarks
elseif ($is_quick_link == 'bm')
{
$total = $totals['filtered']['bookmarks'];
}
// Quick link: due soon
elseif ($is_quick_link == 'due')
{
$total = $totals['filtered']['due_soon'];
}
// Quick link: overdue
elseif ($is_quick_link == 'ovr')
{
$total = $totals['filtered']['overdue'];
}
// Quick link: all open
elseif ($is_quick_link == 'alo')
{
$total = ($href == 'find_tickets.php') ? $totals['filtered']['open'] : $totals['open'];
}
// Quick link: all
elseif ($is_quick_link == 'all')
{
$total = $totals['all'];
}
// No quick link
else
{
$is_quick_link = false;
$list_fid = ($href == 'find_tickets.php') ? 2 : 1;
$totals['filtered']['show'] = 0;
$assigned_to_others_total = $can_view_ass_others ? $totals['filtered']['assigned_to_others'] : $totals['filtered']['assigned_to_others_by_me'];
if ($s_my[$list_fid] == 1)
{
$totals['filtered']['show'] += $totals['filtered']['assigned_to_me'];
}
if ($s_ot[$list_fid] == 1)
{
$totals['filtered']['show'] += $assigned_to_others_total;
}
if ($s_un[$list_fid] == 1)
{
$totals['filtered']['show'] += $totals['filtered']['unassigned'];
}
$total = $totals['filtered']['show'];
}
// Count the main filtered assignment selection separately from quick links.
// Quick links such as "Assigned to me" override the active SQL view, but
// the main "Filtered tickets" tab should still return to the user's
// original assignment filter selection.
$list_fid = ($href == 'find_tickets.php') ? 2 : 1;
$totals['filtered']['main_show'] = 0;
$main_assigned_to_others_total = $can_view_ass_others ? $totals['filtered']['assigned_to_others'] : $totals['filtered']['assigned_to_others_by_me'];
$main_s_my = isset($s_my_filter[$list_fid]) ? $s_my_filter[$list_fid] : $s_my[$list_fid];
$main_s_ot = isset($s_ot_filter[$list_fid]) ? $s_ot_filter[$list_fid] : $s_ot[$list_fid];
$main_s_un = isset($s_un_filter[$list_fid]) ? $s_un_filter[$list_fid] : $s_un[$list_fid];
if ($main_s_my == 1)
{
$totals['filtered']['main_show'] += $totals['filtered']['assigned_to_me'];
}
if ($main_s_ot == 1)
{
$totals['filtered']['main_show'] += $main_assigned_to_others_total;
}
if ($main_s_un == 1)
{
$totals['filtered']['main_show'] += $totals['filtered']['unassigned'];
}
$hesk_main_assignment_all_selected = $main_s_my == 1
&& ( ! ($can_view_ass_others || $can_view_ass_by) || $main_s_ot == 1)
&& ( ! $can_view_unassigned || $main_s_un == 1);
if (empty($is_quick_link))
{
$totals['filtered']['show'] = $totals['filtered']['main_show'];
$total = $totals['filtered']['show'];
}
if (true)
{
/* This query string will be used to browse pages */
if ($href == 'admin_main.php' || $href == 'show_tickets.php')
{
#$query = 'status='.$status;
$query = '';
$query .= 's' . implode('=1&s',array_keys($status)) . '=1';
$query .= '&p' . implode('=1&p',array_keys($priority)) . '=1';
$query .= (count($categories) ? '&c[]=' . implode('&c[]=', $categories) : '&c[]=0');
$query .= '&sort='.$sort;
$query .= '&asc='.$asc;
$query .= '&limit='.$maxresults;
$query .= '&archive='.$archive[1];
$query .= '&s_my='.(isset($s_my_filter[1]) ? $s_my_filter[1] : $s_my[1]);
$query .= '&s_ot='.(isset($s_ot_filter[1]) ? $s_ot_filter[1] : $s_ot[1]);
$query .= '&s_un='.(isset($s_un_filter[1]) ? $s_un_filter[1] : $s_un[1]);
$query .= '&duedate_option='.$duedate_search_type;
$query .= '&duedate_specific_date='.urlencode($duedate_input);
$query .= '&duedate_amount_value='.$duedate_amount_value;
$query .= '&duedate_amount_unit='.$duedate_amount_unit;
$query .= '&cot='.$cot;
$query .= '&g='.$group;
}
else
{
$query = 'q='.urlencode($q);
$query .= '&what='.$what;
$query .= (count($categories) ? '&c[]=' . implode('&c[]=', $categories) : '&c[]=0');
$query .= '&owner='.$owner_input;
$query .= '&dt='.urlencode($date_input);
$query .= '&sort='.$sort;
$query .= '&asc='.$asc;
$query .= '&limit='.$maxresults;
$query .= '&archive='.$archive[2];
$query .= '&s_my='.(isset($s_my_filter[2]) ? $s_my_filter[2] : $s_my[2]);
$query .= '&s_ot='.(isset($s_ot_filter[2]) ? $s_ot_filter[2] : $s_ot[2]);
$query .= '&s_un='.(isset($s_un_filter[2]) ? $s_un_filter[2] : $s_un[2]);
}
$query_for_quick_links = $query;
if ($is_quick_link !== false)
{
$query .= '&ql=' . $is_quick_link;
}
$query_for_pagination = $query . '&page=';
$pages = ceil($total/$maxresults) or $pages = 1;
if ($page > $pages)
{
$page = $pages;
}
$limit_down = ($page * $maxresults) - $maxresults;
$prev_page = ($page - 1 <= 0) ? 0 : $page - 1;
$next_page = ($page + 1 > $pages) ? 0 : $page + 1;
/* We have the full SQL query now, get tickets */
$result = false;
if ($total > 0)
{
$sql .= " LIMIT ".hesk_dbEscape($limit_down)." , ".hesk_dbEscape($maxresults)." ";
$result = hesk_dbQuery($sql);
}
/* Uncomment for debugging */
# echo "SQL: $sql\n<br>";
/* This query string will be used to order and reverse display */
if ($href == 'admin_main.php' || $href == 'show_tickets.php')
{
#$query = 'status='.$status;
$query = '';
$query .= 's' . implode('=1&s',array_keys($status)) . '=1';
$query .= '&p' . implode('=1&p',array_keys($priority)) . '=1';
$query .= (count($categories) ? '&c[]=' . implode('&c[]=', $categories) : '&c[]=0');
#$query .= '&asc='.(isset($is_default) ? 1 : $asc_rev);
$query .= '&limit='.$maxresults;
$query .= '&archive='.$archive[1];
$query .= '&s_my='.(isset($s_my_filter[1]) ? $s_my_filter[1] : $s_my[1]);
$query .= '&s_ot='.(isset($s_ot_filter[1]) ? $s_ot_filter[1] : $s_ot[1]);
$query .= '&s_un='.(isset($s_un_filter[1]) ? $s_un_filter[1] : $s_un[1]);
$query .= '&page=1';
#$query .= '&sort=';
$query .= '&duedate_option='.$duedate_search_type;
$query .= '&duedate_specific_date='.urlencode($duedate_input);
$query .= '&duedate_amount_value='.$duedate_amount_value;
$query .= '&duedate_amount_unit='.$duedate_amount_unit;
$query .= '&cot='.$cot;
$query .= '&g='.$group;
}
else
{
$query = 'q='.urlencode($q);
$query .= '&what='.$what;
$query .= (count($categories) ? '&c[]=' . implode('&c[]=', $categories) : '&c[]=0');
$query .= '&owner='.$owner_input;
$query .= '&dt='.urlencode($date_input);
#$query .= '&asc='.$asc;
$query .= '&limit='.$maxresults;
$query .= '&archive='.$archive[2];
$query .= '&s_my='.(isset($s_my_filter[2]) ? $s_my_filter[2] : $s_my[2]);
$query .= '&s_ot='.(isset($s_ot_filter[2]) ? $s_ot_filter[2] : $s_ot[2]);
$query .= '&s_un='.(isset($s_un_filter[2]) ? $s_un_filter[2] : $s_un[2]);
$query .= '&page=1';
#$query .= '&sort=';
}
if ($is_quick_link !== false)
{
$query .= '&ql=' . $is_quick_link;
}
$query .= '&asc=';
/* Print the table with tickets */
$random=rand(10000,99999);
$modal_id = hesk_generate_old_delete_modal($hesklang['confirm'],
$hesklang['confirm_execute'],
"javascript:document.getElementById('delete-tickets-form').submit()",
$hesklang['confirm']);
// Are some open tickets hidden?
if ($href != 'find_tickets.php' && $hesk_main_assignment_all_selected && $totals['filtered']['open'] != $totals['open'])
{
hesk_show_info($hesklang['not_aos'], ' ', false, 'no-padding-top');
}
?>
<section class="quick-links">
<div class="filters__listing">
<!--
<a href="<?php echo $href . '?' . $query_for_quick_links . '&ql=all&s_my=1&s_ot=1&s_un=1&category=0'; ?>" class="btn btn-transparent <?php if ($is_quick_link == 'all') echo 'is-bold is-selected'; ?>"><span><?php echo $hesklang['ql_all']; ?></span> <span class="filters__btn-value"><?php echo $totals['all']; ?></span></a>
<a href="<?php echo $href . '?' . $query_for_quick_links . '&ql=alo&s_my=1&s_ot=1&s_un=1&category=0'; ?>" class="btn btn-transparent <?php if ($is_quick_link == 'alo') echo 'is-bold is-selected'; ?>"><span><?php echo $hesklang['ql_alo']; ?></span> <span class="filters__btn-value"><?php echo $totals['open']; ?></span></a>
-->
<a href="<?php echo $href . '?' . $query_for_quick_links . '&ql='; ?>" class="btn btn-transparent <?php if (empty($is_quick_link)) echo 'is-bold is-selected'; ?>"><span><?php
if ($href == 'find_tickets.php') {
echo $hesklang['tickets_found'];
}
elseif (
$totals['filtered']['open'] == $totals['open'] &&
$totals['filtered']['open'] == $totals['filtered']['all'] &&
( ! isset($totals['filtered']['main_show']) || $totals['filtered']['main_show'] == $totals['open'])) {
echo $hesklang['open_tickets'];
}
else {
echo $hesklang['ql_fit'];
}
?></span> <span class="filters__btn-value"><?php echo (isset($totals['filtered']['main_show']) ? $totals['filtered']['main_show'] : $totals['filtered']['all']); ?></span></a>
<a href="<?php echo $href . '?' . $query_for_quick_links . '&ql=my'; ?>" class="btn btn-transparent <?php if ($is_quick_link == 'my') echo 'is-bold is-selected'; ?>"><span><?php echo $hesklang['ql_a2m']; ?></span> <span class="filters__btn-value"><?php echo $totals['filtered']['assigned_to_me']; ?></span></a>
<a href="<?php echo $href . '?' . $query_for_quick_links . '&ql=cbm'; ?>" class="btn btn-transparent <?php if ($is_quick_link == 'cbm') echo 'is-bold is-selected'; ?>"><span><?php echo $hesklang['ql_cbm']; ?></span> <span class="filters__btn-value"><?php echo $totals['filtered']['collaborator']; ?></span></a>
<?php if ($can_view_ass_others || $can_view_ass_by): ?>
<a href="<?php echo $href . '?' . $query_for_quick_links . '&ql=ot'; ?>" class="btn btn-transparent <?php if ($is_quick_link == 'ot') echo 'is-bold is-selected'; ?>"><span><?php echo $hesklang['ql_a2o']; ?></span> <span class="filters__btn-value"><?php echo $can_view_ass_others ? $totals['filtered']['assigned_to_others'] : $totals['filtered']['assigned_to_others_by_me']; ?></span></a>
<?php endif; ?>
<?php if ($can_view_unassigned): ?>
<a href="<?php echo $href . '?' . $query_for_quick_links . '&ql=un'; ?>" class="btn btn-transparent <?php if ($is_quick_link == 'un') echo 'is-bold is-selected'; ?>"><span><?php echo $hesklang['ql_una']; ?></span> <span class="filters__btn-value"><?php echo $totals['filtered']['unassigned']; ?></span></a>
<?php endif; ?>
<a href="<?php echo $href . '?' . $query_for_quick_links . '&ql=bm&s_my=1&s_ot=1&s_un=1'; ?>" class="btn btn-transparent is-bookmarks <?php if ($is_quick_link == 'bm') echo 'is-bold is-selected'; ?>"><span><?php echo $hesklang['ql_bookmarks']; ?></span> <span class="filters__btn-value"><?php echo $totals['filtered']['bookmarks']; ?></span></a>
<a href="<?php echo $href . '?' . $query_for_quick_links . '&ql=due&s_my=1&s_ot=1&s_un=1'; ?>" class="btn btn-transparent is-due-soon <?php if ($is_quick_link == 'due') echo 'is-bold is-selected'; ?>"><span><?php echo $hesklang['ql_due']; ?></span> <span class="filters__btn-value"><?php echo $totals['filtered']['due_soon']; ?></span></a>
<a href="<?php echo $href . '?' . $query_for_quick_links . '&ql=ovr&s_my=1&s_ot=1&s_un=1'; ?>" class="btn btn-transparent is-overdue <?php if ($is_quick_link == 'ovr') echo 'is-bold is-selected'; ?>"><span><?php echo $hesklang['ql_ovr']; ?></span> <span class="filters__btn-value"><?php echo $totals['filtered']['overdue']; ?></span></a>
</div>
<div class="checkbox-custom auto-reload">
<input type="checkbox" id="reloadCB" onclick="toggleAutoRefresh(this);">
<label for="reloadCB"><?php echo $hesklang['arp']; ?></label> <span id="timer"></span>
<script type="text/javascript">heskCheckReloading();</script>
</div>
</section>
<?php
$hesk_settings['hesk-group-count'] = 0;
if ($total > 0)
{
?>
<form name="form1" id="delete-tickets-form" action="delete_tickets.php" method="post">
<?php
if (empty($group))
{
hesk_print_list_head();
}
}
else
{
hesk_show_info($hesklang['no_tickets_crit'], ' ', false);
}
$checkall = '
<div class="checkbox-custom">
<input type="checkbox" id="ticket_checkall" onclick="hesk_changeAll()">
<label for="ticket_checkall"> </label>
</div>';
$group_tmp = '';
$is_table = 0;
$space = 0;
if ($total > 0 && $result)
{
while ($ticket=hesk_dbFetchAssoc($result))
{
// Are we grouping tickets?
if ($group)
{
require(HESK_PATH . 'inc/print_group.inc.php');
}
// Set owner (needed for row title)
$owner = '';
$first_line = '(' . $hesklang['unas'] . ')'." \n\n";
if ($ticket['owner'] == $_SESSION['id'])
{
$owner = '<svg class="icon icon-assign" style="margin-right: 3px">
<use xlink:href="'. HESK_PATH . 'img/sprite.svg#icon-assign"></use>
</svg>';
$first_line = $hesklang['tasy2'] . " \n\n";
}
elseif ($ticket['owner'])
{
if (!isset($admins[$ticket['owner']]))
{
$admins[$ticket['owner']] = $hesklang['e_udel'];
}
$owner = '<svg class="icon icon-assign-plus" style="margin-right: 3px">
<use xlink:href="'. HESK_PATH . 'img/sprite.svg#icon-assign-plus"></use>
</svg>';
$first_line = $hesklang['taso3'] . ' ' . $admins[$ticket['owner']] . " \n\n";
}
// Set message (needed for row title)
$ticket['message'] = $first_line . hesk_mb_substr(strip_tags($ticket['message']),0,200).'...';
// Start ticket row
echo '
<tr title="'.$ticket['message'].'" class="status-'. $ticket['status'] .' '.($ticket['owner'] ? '' : 'new').($ticket['priority'] == '0' ? ' bg-critical' : '').'">
<td class="table__first_th sindu_handle">
<div class="checkbox-custom">
<input type="checkbox" id="ticket_check_'.$ticket['id'].'" name="id[]" value="'.$ticket['id'].'" class="group' . $hesk_settings['hesk-group-count'] . '">
<label for="ticket_check_'.$ticket['id'].'" aria-label="' . $hesklang['select'] . '"> </label>
</div>
</td>
';
// Print sequential ID and link it to the ticket page
if ( hesk_show_column('id') )
{
echo '<td><a href="admin_ticket.php?track='.$ticket['trackid'].'&Refresh='.$random.'">'.$ticket['id'].'</a></td>';
}
// Print tracking ID and link it to the ticket page
if ( hesk_show_column('trackid') )
{
echo '<td class="trackid">
<div class="table__td-id">
<a class="link" href="admin_ticket.php?track='.$ticket['trackid'].'&Refresh='.$random.'">'.$ticket['trackid'].'</a>
</div>
</td>';
}
// Print date submitted
if ( hesk_show_column('dt') )
{
switch ($hesk_settings['submittedformat'])
{
case 1:
$ticket['dt'] = hesk_date($ticket['dt'], true, true, true, $hesk_settings['format_timestamp']);
break;
case 2:
$ticket['dt'] = hesk_time_lastchange($ticket['dt']);
break;
case 3:
$ticket['dt'] = hesk_date($ticket['dt'], true, true, true, $hesk_settings['format_date']);
break;
case 4:
$ticket['dt'] = hesk_date($ticket['dt'], true, true, true, $hesk_settings['format_submitted']);
break;
default:
$ticket['dt'] = hesk_time_since( strtotime($ticket['dt']) );
}
echo '<td>'.$ticket['dt'].'</td>';
}
// Print last modified
if ( hesk_show_column('lastchange') )
{
// Another usage over in my_tickets.php
switch ($hesk_settings['updatedformat'])
{
case 1:
$ticket['lastchange'] = hesk_date($ticket['lastchange'], true, true, true, $hesk_settings['format_timestamp']);
break;
case 2:
$ticket['lastchange'] = hesk_time_lastchange($ticket['lastchange']);
break;
case 3:
$ticket['lastchange'] = hesk_date($ticket['lastchange'], true, true, true, $hesk_settings['format_date']);
break;
case 4:
$ticket['lastchange'] = hesk_date($ticket['lastchange'], true, true, true, $hesk_settings['format_updated']);
break;
default:
$ticket['lastchange'] = hesk_time_since( strtotime($ticket['lastchange']) );
}
echo '<td>'.$ticket['lastchange'].'</td>';
}
// Print ticket category
if ( hesk_show_column('category') )
{
$ticket['category_name'] = isset($hesk_settings['categories'][$ticket['category']]) ? $hesk_settings['categories'][$ticket['category']] : $hesklang['catd'];
echo '<td class="category-'.intval($ticket['category']).'">'.$ticket['category_name'].'</td>';
}
// Print customer name
if ( hesk_show_column('name') )
{
if ($ticket['name'] == '') {
if (strlen($ticket['email']) && $ticket['email'] != $hesklang['anon_email']) {
$ticket['name'] = $ticket['email'];
} else {
$ticket['name'] = $hesklang['anon_name'];
}
}
echo '<td>'.$ticket['name'];
if (intval($ticket['customer_count']) > 1) {
echo '<span class="customer-count">'.sprintf($hesklang['customer_count_x_more'], intval($ticket['customer_count']) - 1).'</span>';
}
echo '</td>';
}
// Print customer email
if ( hesk_show_column('email') )
{
echo '<td>' . (strlen($ticket['email']) ? '<a href="mailto:'.$ticket['email'].'">'.($hesk_settings['email_column'] ? $ticket['email'] : $hesklang['clickemail']).'</a>' : '');
if (intval($ticket['email_count']) > 1) {
$subtraction_amount = strlen($ticket['email']) ? 1 : 0;
echo '<span class="customer-count">'.sprintf($hesklang['customer_count_x_more'], intval($ticket['email_count']) - $subtraction_amount).'</span>';
}
echo '</td>';
}
// Print subject and link to the ticket page
if ( hesk_show_column('subject') )
{
echo '<td class="subject">'.($ticket['archive'] ? '<svg class="icon icon-tag '.($ticket['owner'] != $_SESSION['id'] ? 'fill-gray' : '').'" style="margin-right: 3px">
<use xlink:href="'. HESK_PATH .'img/sprite.svg#icon-tag"></use>
</svg>' : '').($ticket['is_bookmark'] ? '<svg class="icon icon-pin is-bookmark" style="margin-right: 6px">
<use xlink:href="'. HESK_PATH .'img/sprite.svg#icon-pin"></use>
</svg>' : '').$owner.'<a class="link" href="admin_ticket.php?track='.$ticket['trackid'].'&Refresh='.$random.'">'.$ticket['subject'].'</a></td>';
}
// Print ticket status
if ( hesk_show_column('status') )
{
echo '<td>' . hesk_get_admin_ticket_status($ticket['status']) . ' </td>';
}
// Print ticket owner
if ( hesk_show_column('owner') )
{
if ($ticket['owner'])
{
$ticket['owner'] = isset($admins[$ticket['owner']]) ? $admins[$ticket['owner']] : $hesklang['unas'];
}
else
{
$ticket['owner'] = $hesklang['unas'];
}
echo '<td>'.$ticket['owner'].'</td>';
}
// Print number of all replies
if ( hesk_show_column('replies') )
{
echo '<td>'.$ticket['replies'].'</td>';
}
// Print number of staff replies
if ( hesk_show_column('staffreplies') )
{
echo '<td>'.$ticket['staffreplies'].'</td>';
}
// Print last replier
if ( hesk_show_column('lastreplier') )
{
if ($ticket['lastreplier'])
{
$ticket['repliername'] = isset($admins[$ticket['replierid']]) ? $admins[$ticket['replierid']] : $hesklang['staff'];
}
else
{
$customer_name = $ticket['lastreplier_customername'] === null ? $ticket['name'] : $ticket['lastreplier_customername'];
$ticket['repliername'] = $customer_name;
}
echo '<td>'.$ticket['repliername'].'</td>';
}
// Print time worked
if ( hesk_show_column('time_worked') )
{
echo '<td>'.$ticket['time_worked'].'</td>';
}
// Print due date
if (hesk_show_column('due_date')) {
$due_date = $hesklang['none'];
if ($ticket['due_date'] != null) {
$due_date = hesk_date($ticket['due_date'], false, true, false);
$due_date = date($hesk_settings['format_date'], $due_date);
}
echo '<td>'.$due_date.'</td>';
}
// Print custom fields
foreach ($hesk_settings['custom_fields'] as $key => $value)
{
if ($value['use'] && hesk_show_column($key) )
{
echo '<td>'.($value['type'] == 'date' ? hesk_custom_date_display_format($ticket[$key], $value['value']['date_format']) : $ticket[$key]).'</td>';
}
}
// End ticket row
echo '<td class="has-flex-item"><div class="td-flex">' . hesk_get_admin_ticket_priority_for_list($ticket['priority']) . ' </div></td></tr>';
} // End while
} // End if total > 0 and tickets were queried
// Only show all this if we found any tickets
if ($total > 0)
{
if (empty($group) || $is_table)
{
?>
</tbody>
</table>
</div>
<?php
}
?>
<div class="pagination-wrap">
<div class="pagination">
<?php
if ($pages > 1) {
/* List pages */
if ($pages >= 7) {
if ($page > 2) {
echo '
<a href="'.$href.'?'.$query_for_pagination.'1" class="btn pagination__nav-btn">
<svg class="icon icon-chevron-left" style="margin-right:-6px">
<use xlink:href="'. HESK_PATH .'img/sprite.svg#icon-chevron-left"></use>
</svg>
<svg class="icon icon-chevron-left">
<use xlink:href="'. HESK_PATH .'img/sprite.svg#icon-chevron-left"></use>
</svg>
'.$hesklang['pager_first'].'
</a>';
}
if ($prev_page)
{
echo '
<a href="'.$href.'?'.$query_for_pagination.$prev_page.'" class="btn pagination__nav-btn">
<svg class="icon icon-chevron-left">
<use xlink:href="'. HESK_PATH .'img/sprite.svg#icon-chevron-left"></use>
</svg>
'.$hesklang['pager_previous'].'
</a>';
}
}
echo '<ul class="pagination__list">';
for ($i=1; $i<=$pages; $i++)
{
if ($i <= ($page+5) && $i >= ($page-5))
{
if ($i == $page)
{
echo '
<li class="pagination__item is-current">
<a href="javascript:" class="pagination__link">'.$i.'</a>
</li>';
}
else
{
echo '
<li class="pagination__item ">
<a href="'.$href.'?'.$query_for_pagination.$i.'" class="pagination__link">'.$i.'</a>
</li>';
}
}
}
echo '</ul>';
if ($pages >= 7)
{
if ($next_page)
{
echo '
<a href="'.$href.'?'.$query_for_pagination.$next_page.'" class="btn pagination__nav-btn">
'.$hesklang['pager_next'].'
<svg class="icon icon-chevron-right">
<use xlink:href="'. HESK_PATH .'img/sprite.svg#icon-chevron-right"></use>
</svg>
</a>';
}
if ($page < ($pages - 1))
{
echo '
<a href="'.$href.'?'.$query_for_pagination.$pages.'" class="btn pagination__nav-btn">
'.$hesklang['pager_last'].'
<svg class="icon icon-chevron-right">
<use xlink:href="'. HESK_PATH .'img/sprite.svg#icon-chevron-right"></use>
</svg>
<svg class="icon icon-chevron-right" style="margin-left:-6px">
<use xlink:href="'. HESK_PATH .'img/sprite.svg#icon-chevron-right"></use>
</svg>
</a>';
}
}
} // end PAGES > 1
?>
</div>
<p class="pagination__amount"><?php echo sprintf($hesklang['tickets_on_pages'],$total,$pages); ?></p>
</div>
<section class="tickets__legend">
<div>
<?php
if (hesk_checkPermission('can_add_archive',0))
{
?>
<div>
<svg class="icon icon-tag">
<use xlink:href="<?php echo HESK_PATH; ?>img/sprite.svg#icon-tag"></use>
</svg>
<?php echo $hesklang['archived2']; ?>
</div>
<?php
}
?>
<div>
<svg class="icon icon-assign">
<use xlink:href="<?php echo HESK_PATH; ?>img/sprite.svg#icon-assign"></use>
</svg> <?php echo $hesklang['tasy2']; ?>
</div>
<?php
if (hesk_checkPermission('can_view_ass_others',0) || hesk_checkPermission('can_view_ass_by',0))
{
?>
<div>
<svg class="icon icon-assign-plus">
<use xlink:href="<?php echo HESK_PATH; ?>img/sprite.svg#icon-assign-plus"></use>
</svg> <?php echo $hesklang['taso2']; ?>
</div>
<?php
}
?>
</div>
<div class="bulk-actions">
<?php echo $hesklang['with_selected']; ?>
<div class="clear-on-mobile"></div>
<div class="inline-bottom">
<select name="a" aria-label="<?php echo $hesklang['with_selected']; ?>">
<?php
foreach ($hesk_settings['priorities'] as $k => $v) {
?>
<option value="<?php echo $k;?>"><?php echo $hesklang['set_pri_to'].' '.$v['name']; ?></option>
<?php
}
?>
<?php
if ( hesk_checkPermission('can_resolve', 0) && ! defined('HESK_DEMO') )
{
?>
<option value="close"><?php echo $hesklang['close_selected']; ?></option>
<?php
}
if ( hesk_checkPermission('can_add_archive', 0) )
{
?>
<option value="tag"><?php echo $hesklang['add_archive_quick']; ?></option>
<option value="untag"><?php echo $hesklang['remove_archive_quick']; ?></option>
<?php
}
?>
<option value="print"><?php echo $hesklang['print_selected']; ?></option>
<?php
if ( ! defined('HESK_DEMO') )
{
if ( hesk_checkPermission('can_merge_tickets', 0) )
{
?>
<option value="merge"><?php echo $hesklang['mer_selected']; ?></option>
<?php
}
if ( hesk_checkPermission('can_link_tickets', 0) )
{
?>
<option value="link_tickets"><?php echo $hesklang['link_selected_tickets']; ?></option>
<?php
}
if ( hesk_checkPermission('can_export', 0) )
{
?>
<option value="export"><?php echo $hesklang['export_selected']; ?></option>
<?php
}
if ( hesk_checkPermission('can_privacy', 0) )
{
?>
<option value="anonymize"><?php echo $hesklang['anon_selected']; ?></option>
<?php
}
if ( hesk_checkPermission('can_del_tickets', 0) )
{
?>
<option value="delete"><?php echo $hesklang['del_selected']; ?></option>
<?php
}
} // End demo
?>
</select>
</div>
<input type="hidden" name="token" value="<?php hesk_token_echo(); ?>" />
<button onclick="document.getElementById('action-type').value = 'bulk'" type="button" class="btn btn-full" ripple="ripple" data-modal="[data-modal-id='<?php echo $modal_id; ?>']">
<?php echo $hesklang['execute']; ?>
</button>
<?php
if (hesk_checkPermission('can_assign_others',0))
{
?>
<div style="height:6px"></div>
<?php echo $hesklang['assign_selected']; ?>
<div class="clear-on-mobile"></div>
<div class="inline-bottom">
<select name="owner" aria-label="<?php echo $hesklang['assign_selected']; ?>">
<option value="" selected="selected"><?php echo $hesklang['select']; ?></option>
<option value="-1"> > <?php echo $hesklang['unas']; ?> < </option>
<?php
foreach ($can_assign_to as $k=>$v)
{
echo '<option value="'.$k.'">'.$v.'</option>';
}
?>
</select>
</div>
<button type="button" name="assign" class="btn btn-full" data-modal="[data-modal-id='<?php echo $modal_id; ?>']"
onclick="document.getElementById('action-type').value = 'assi'">
<?php echo $hesklang['assi']; ?>
</button>
<?php
}
?>
</div>
</section>
<input id="action-type" name="action-type" type="hidden" value="-1">
</form>
<?php
} // END ticket list if total > 0
elseif (!isset($is_search) && $href != 'find_tickets.php' && !$is_quick_link)
{
// No tickets in the DB? Show a welcome message
$res = hesk_dbQuery("SELECT COUNT(*) FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets`");
$num = hesk_dbResult($res,0,0);
if ($num == 0)
{
hesk_show_notice(
$hesklang['welcome1'] . '<br><br>' .
sprintf(
$hesklang['welcome2'],
'<a href="https://www.hesk.com/knowledgebase/?article=109" target="_blank">' . $hesklang['welcome3'] . '</a>'
), ' ', false
);
}
}
} // END ticket list if total > 0 or if this is a quick link
else
{
if (isset($is_search) || $href == 'find_tickets.php')
{
hesk_show_notice($hesklang['no_tickets_crit']);
}
}
function hesk_print_list_head()
{
global $hesk_settings, $href, $query, $sort_possible, $hesklang;
// Make sure selecting works correctly when tickets are grouped
if (isset($hesk_settings['hesk-group-count'])) {
$hesk_settings['hesk-group-count']++;
} else {
$hesk_settings['hesk-group-count'] = 1;
}
$table_id = $hesk_settings['hesk-group-count'] == 1 ? 'default-table' : 'default-table-' . $hesk_settings['hesk-group-count'];
?>
<div class="table-wrap ignore-overflow">
<table class="table sindu-table ticket-list sindu_origin_table" id="<?php echo $table_id; ?>">
<thead>
<tr>
<th class="table__first_th sindu_handle" aria-label="<?php echo $hesklang['select']; ?>">
<div class="checkbox-custom">
<input type="checkbox" id="ticket_checkall<?php echo $hesk_settings['hesk-group-count']; ?>" name="checkall" value="2" onclick="hesk_changeAll(this, '<?php echo 'group' . $hesk_settings['hesk-group-count'] . "'"; ?>)">
<label for="ticket_checkall<?php echo $hesk_settings['hesk-group-count']; ?>" aria-label="<?php echo $hesklang['a_select']; ?>"> </label>
</div>
</th>
<?php
$sort = hesk_GET('sort', 'status');
$sort_direction = '';
if (isset($_GET['asc'])) {
$sort_direction = intval($_GET['asc']) == 0 ? 'desc' : 'asc';
} else {
$sort_direction = 'asc';
}
foreach ($hesk_settings['ticket_list'] as $field)
{
if (!key_exists($field, $hesk_settings['possible_ticket_list'])) {
continue;
}
echo '<th class="sindu-handle '.($sort == $field ? $sort_direction : '').' '.($field == 'trackid' ? 'trackid' : '').'">
<a href="' . $href . '?' . $query . $sort_possible[$field] . '&sort=' . $field . '" aria-label="' . ($hesklang['sort_by'] . ' ' . $hesk_settings['possible_ticket_list'][$field]). '">
<div class="sort">
<span>' . $hesk_settings['possible_ticket_list'][$field] . '</span>
<i class="handle"></i>
</div>
</a>
</th>';
}
?>
<th class="sindu-handle <?php echo $sort == 'priority' ? $sort_direction : ''; ?>">
<a href="<?php echo $href . '?' . $query . $sort_possible['priority'] . '&sort='; ?>priority" aria-label="<?php echo ($hesklang['sort_by'] . ' ' . $hesklang['priority']); ?>">
<div class="sort">
<span><?php echo $hesklang['priority']; ?></span>
<i class="handle"></i>
</div>
</a>
</th>
</tr>
</thead>
<tbody>
<?php
} // END hesk_print_list_head()
wget 'https://lists2.roe3.org/hesk/inc/upload_attachment.inc.php'
<?php
/**
*
* This file is part of HESK - PHP Help Desk Software.
*
* (c) Copyright Klemen Stirn. All rights reserved.
* https://www.hesk.com
*
* For the full copyright and license agreement information visit
* https://www.hesk.com/eula.php
*
*/
/* Check if this is a valid include */
if (!defined('IN_SCRIPT')) {die('Invalid attempt');}
require_once(HESK_PATH . 'inc/attachments.inc.php');
require_once(HESK_PATH . 'inc/posting_functions.inc.php');
$hesk_settings['db_failure_response'] = 'json';
function hesk_tempAttachmentJsonResponse($status_code, $message = '') {
header('Content-Type: application/json; charset=utf-8');
http_response_code($status_code);
if ($message !== '') {
print json_encode(array(
'status' => 'failure',
'status_code' => $status_code,
'message' => $message
));
}
return '';
}
// Temporary attachment upload/delete requests must be POST requests protected by the session CSRF token.
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
return hesk_tempAttachmentJsonResponse(405, $hesklang['error']);
}
if (!hesk_token_compare(hesk_POST('token'))) {
return hesk_tempAttachmentJsonResponse(403, $hesklang['eto']);
}
// Remove any expired temp attachments after the request method and CSRF token have been verified.
hesk_removeExpiredTempAttachments();
// Check if we are deleting an attachment or if we have a file to upload
if (hesk_POST('action') === 'delete') {
$file_key = hesk_POST('fileKey', 'undefined');
if ($file_key === 'undefined') {
//-- Failed dropzone uploads will return an undefined saved name when removing them
return http_response_code(204);
}
hesk_deleteTempAttachment($file_key, true);
return http_response_code(204);
} elseif (!empty($_FILES)) {
$info = hesk_uploadTempFile();
header('Content-Type: application/json; charset=utf-8');
http_response_code($info['status_code']);
print json_encode($info);
return '';
}
return hesk_tempAttachmentJsonResponse(400, $hesklang['error']);
wget 'https://lists2.roe3.org/hesk/inc/users_online.inc.php'
<?php
/**
*
* This file is part of HESK - PHP Help Desk Software.
*
* (c) Copyright Klemen Stirn. All rights reserved.
* https://www.hesk.com
*
* For the full copyright and license agreement information visit
* https://www.hesk.com/eula.php
*
*/
/* Check if this is a valid include */
if (!defined('IN_SCRIPT')) {die('Invalid attempt');}
function hesk_initOnline($user_id)
{
global $hesk_settings, $hesklang;
/* Set user to online */
hesk_setOnline($user_id);
/* Can this user view online staff? */
if (hesk_checkPermission('can_view_online',0))
{
$hesk_settings['users_online'] = hesk_listOnline();
define('SHOW_ONLINE',1);
}
return true;
} // END hesk_initOnline()
function hesk_printOnline()
{
global $hesk_settings, $hesklang;
echo '
<div class="users-online">
<svg class="icon icon-team" style="fill: #000">
<use xlink:href="' . HESK_PATH . 'img/sprite.svg#icon-team"></use>
</svg> ';
$i = '';
foreach ($hesk_settings['users_online'] as $tmp)
{
$i .= '<span ' . ($tmp['isadmin'] ? 'style="font-style:italic;"' : '') . '>';
$i .= ($tmp['id'] == $_SESSION['id']) ? $tmp['name'] : '<a class="link" href="mail.php?a=new&id='.$tmp['id'].'">' . $tmp['name'] . '</a>';
$i .= '</span>, ';
}
echo substr($i,0,-2);
echo '</div>';
} // END hesk_printOnline()
function hesk_listOnline($list_names=1)
{
global $hesk_settings, $hesklang, $hesk_db_link;
$users_online = array();
/* Clean expired entries */
hesk_cleanOnline();
/* Get a list of online users */
/* --> With names */
if ($list_names)
{
$res = hesk_dbQuery("SELECT `t1`.`user_id` , `t2`.`name` , `t2`.`isadmin` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."online` AS `t1` INNER JOIN `".hesk_dbEscape($hesk_settings['db_pfix'])."users` AS `t2` ON `t1`.`user_id` = `t2`.`id`");
while ($tmp = hesk_dbFetchAssoc($res))
{
$users_online[$tmp['user_id']] = array(
'id' => $tmp['user_id'],
'name' => $tmp['name'],
'isadmin' => $tmp['isadmin']
);
}
}
/* --> Without names */
else
{
$res = hesk_dbQuery("SELECT `user_id` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."online`");
while ($tmp = hesk_dbFetchAssoc($res))
{
$users_online[] = $tmp['user_id'];
}
}
return $users_online;
} // END hesk_listOnline()
function hesk_setOnline($user_id)
{
global $hesk_settings, $hesklang, $hesk_db_link;
/* If already online just update... */
hesk_dbQuery("UPDATE `".hesk_dbEscape($hesk_settings['db_pfix'])."online` SET `tmp` = `tmp` + 1 WHERE `user_id` = '".intval($user_id)."'");
/* ... else insert a new entry */
if ( ! hesk_dbAffectedRows() )
{
hesk_dbQuery("INSERT INTO `".hesk_dbEscape($hesk_settings['db_pfix'])."online` (`user_id`) VALUES (".intval($user_id).") ");
}
return true;
} // END hesk_setOnline()
function hesk_setOffline($user_id)
{
global $hesk_settings, $hesklang, $hesk_db_link;
/* If already online just update... */
hesk_dbQuery("DELETE FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."online` WHERE `user_id` = '".intval($user_id)."'");
return true;
} // END hesk_setOffline()
function hesk_cleanOnline()
{
global $hesk_settings, $hesklang, $hesk_db_link;
/* Delete old rows from the database */
hesk_dbQuery("DELETE FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."online` WHERE `dt` < ( NOW() - INTERVAL ".intval($hesk_settings['online_min'])." MINUTE) ");
return true;
} // END hesk_cleanOnline()