Closes #73: Send email to customer when ticket closed
parent
f1f62cbe3c
commit
83b4b16d48
@ -0,0 +1,292 @@
|
||||
<?php
|
||||
/*******************************************************************************
|
||||
* Title: Help Desk Software HESK
|
||||
* Version: 2.5.3 from 16th March 2014
|
||||
* Author: Klemen Stirn
|
||||
* Website: http://www.hesk.com
|
||||
********************************************************************************
|
||||
* COPYRIGHT AND TRADEMARK NOTICE
|
||||
* Copyright 2005-2014 Klemen Stirn. All Rights Reserved.
|
||||
* HESK is a registered trademark of Klemen Stirn.
|
||||
|
||||
* The HESK may be used and modified free of charge by anyone
|
||||
* AS LONG AS COPYRIGHT NOTICES AND ALL THE COMMENTS REMAIN INTACT.
|
||||
* By using this code you agree to indemnify Klemen Stirn from any
|
||||
* liability that might arise from it's use.
|
||||
|
||||
* Selling the code for this program, in part or full, without prior
|
||||
* written consent is expressly forbidden.
|
||||
|
||||
* Using this code, in part or full, to create derivate work,
|
||||
* new scripts or products is expressly forbidden. Obtain permission
|
||||
* before redistributing this software over the Internet or in
|
||||
* any other medium. In all cases copyright and header must remain intact.
|
||||
* This Copyright is in full effect in any country that has International
|
||||
* Trade Agreements with the United States of America or
|
||||
* with the European Union.
|
||||
|
||||
* Removing any of the copyright notices without purchasing a license
|
||||
* is expressly forbidden. To remove HESK copyright notice you must purchase
|
||||
* a license for this script. For more information on how to obtain
|
||||
* a license please visit the page below:
|
||||
* https://www.hesk.com/buy.php
|
||||
*******************************************************************************/
|
||||
|
||||
define('IN_SCRIPT',1);
|
||||
define('HESK_PATH','../');
|
||||
|
||||
/* Get all the required files and functions */
|
||||
require(HESK_PATH . 'hesk_settings.inc.php');
|
||||
require(HESK_PATH . 'inc/common.inc.php');
|
||||
require(HESK_PATH . 'inc/admin_functions.inc.php');
|
||||
hesk_load_database_functions();
|
||||
|
||||
hesk_session_start();
|
||||
hesk_dbConnect();
|
||||
hesk_isLoggedIn();
|
||||
|
||||
/* Set correct return URL */
|
||||
if (isset($_SERVER['HTTP_REFERER']))
|
||||
{
|
||||
$url = hesk_input($_SERVER['HTTP_REFERER']);
|
||||
$url = str_replace('&','&',$url);
|
||||
if ($tmp = strstr($url,'show_tickets.php'))
|
||||
{
|
||||
$referer = $tmp;
|
||||
}
|
||||
elseif ($tmp = strstr($url,'find_tickets.php'))
|
||||
{
|
||||
$referer = $tmp;
|
||||
}
|
||||
elseif ($tmp = strstr($url,'admin_main.php'))
|
||||
{
|
||||
$referer = $tmp;
|
||||
}
|
||||
else
|
||||
{
|
||||
$referer = 'admin_main.php';
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$referer = 'admin_main.php';
|
||||
}
|
||||
|
||||
/* Is this a delete ticket request from within a ticket ("delete" icon)? */
|
||||
if ( isset($_GET['delete_ticket']) )
|
||||
{
|
||||
/* Check permissions for this feature */
|
||||
hesk_checkPermission('can_del_tickets');
|
||||
|
||||
/* A security check */
|
||||
hesk_token_check();
|
||||
|
||||
// Tracking ID
|
||||
$trackingID = hesk_cleanID() or die($hesklang['int_error'].': '.$hesklang['no_trackID']);
|
||||
|
||||
/* Get ticket info */
|
||||
$result = hesk_dbQuery("SELECT `id`,`trackid`,`category` 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']);
|
||||
}
|
||||
$ticket = hesk_dbFetchAssoc($result);
|
||||
|
||||
/* Is this user allowed to delete tickets inside this category? */
|
||||
hesk_okCategory($ticket['category']);
|
||||
|
||||
hesk_fullyDeleteTicket();
|
||||
|
||||
hesk_process_messages(sprintf($hesklang['num_tickets_deleted'],1),$referer,'SUCCESS');
|
||||
}
|
||||
|
||||
|
||||
/* This is a request from ticket list. Must be POST and id must be an array */
|
||||
if ( ! isset($_POST['id']) || ! is_array($_POST['id']) )
|
||||
{
|
||||
hesk_process_messages($hesklang['no_selected'], $referer, 'NOTICE');
|
||||
}
|
||||
/* If not, then needs an action (a) POST variable set */
|
||||
elseif ( ! isset($_POST['a']) )
|
||||
{
|
||||
hesk_process_messages($hesklang['invalid_action'], $referer);
|
||||
}
|
||||
|
||||
$i=0;
|
||||
|
||||
/* DELETE */
|
||||
if ($_POST['a']=='delete')
|
||||
{
|
||||
/* Check permissions for this feature */
|
||||
hesk_checkPermission('can_del_tickets');
|
||||
|
||||
/* A security check */
|
||||
hesk_token_check('POST');
|
||||
|
||||
foreach ($_POST['id'] as $this_id)
|
||||
{
|
||||
if ( is_array($this_id) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
$this_id = intval($this_id) or hesk_error($hesklang['id_not_valid']);
|
||||
$result = hesk_dbQuery("SELECT `id`,`trackid`,`category` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` WHERE `id`='".intval($this_id)."' LIMIT 1");
|
||||
if (hesk_dbNumRows($result) != 1)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
$ticket = hesk_dbFetchAssoc($result);
|
||||
|
||||
hesk_okCategory($ticket['category']);
|
||||
|
||||
hesk_fullyDeleteTicket();
|
||||
$i++;
|
||||
}
|
||||
|
||||
hesk_process_messages(sprintf($hesklang['num_tickets_deleted'],$i),$referer,'SUCCESS');
|
||||
}
|
||||
/* MERGE TICKETS */
|
||||
elseif ($_POST['a']=='merge')
|
||||
{
|
||||
/* Check permissions for this feature */
|
||||
hesk_checkPermission('can_merge_tickets');
|
||||
|
||||
/* A security check */
|
||||
hesk_token_check('POST');
|
||||
|
||||
/* Sort IDs, tickets will be merged to the lowest ID */
|
||||
sort($_POST['id'], SORT_NUMERIC);
|
||||
|
||||
/* Select lowest ID as the target ticket */
|
||||
$merge_into = array_shift($_POST['id']);
|
||||
|
||||
/* Merge tickets or throw an error */
|
||||
if ( hesk_mergeTickets( $_POST['id'] , $merge_into ) )
|
||||
{
|
||||
hesk_process_messages($hesklang['merged'],$referer,'SUCCESS');
|
||||
}
|
||||
else
|
||||
{
|
||||
$hesklang['merge_err'] .= ' ' . $_SESSION['error'];
|
||||
hesk_cleanSessionVars($_SESSION['error']);
|
||||
hesk_process_messages($hesklang['merge_err'],$referer);
|
||||
}
|
||||
}
|
||||
/* TAG/UNTAG TICKETS */
|
||||
elseif ($_POST['a']=='tag' || $_POST['a']=='untag')
|
||||
{
|
||||
/* Check permissions for this feature */
|
||||
hesk_checkPermission('can_add_archive');
|
||||
|
||||
/* A security check */
|
||||
hesk_token_check('POST');
|
||||
|
||||
if ($_POST['a']=='tag')
|
||||
{
|
||||
$archived = 1;
|
||||
$action = $hesklang['num_tickets_tag'];
|
||||
}
|
||||
else
|
||||
{
|
||||
$archived = 0;
|
||||
$action = $hesklang['num_tickets_untag'];
|
||||
}
|
||||
|
||||
foreach ($_POST['id'] as $this_id)
|
||||
{
|
||||
if ( is_array($this_id) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
$this_id = intval($this_id) or hesk_error($hesklang['id_not_valid']);
|
||||
$result = hesk_dbQuery("SELECT `id`,`trackid`,`category` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` WHERE `id`='".intval($this_id)."' LIMIT 1");
|
||||
if (hesk_dbNumRows($result) != 1)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
$ticket = hesk_dbFetchAssoc($result);
|
||||
|
||||
hesk_okCategory($ticket['category']);
|
||||
|
||||
hesk_dbQuery("UPDATE `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` SET `archive`='$archived' WHERE `id`='".intval($this_id)."' LIMIT 1");
|
||||
$i++;
|
||||
}
|
||||
|
||||
hesk_process_messages(sprintf($action,$i),$referer,'SUCCESS');
|
||||
}
|
||||
/* JUST CLOSE */
|
||||
else
|
||||
{
|
||||
/* Check permissions for this feature */
|
||||
hesk_checkPermission('can_view_tickets');
|
||||
hesk_checkPermission('can_reply_tickets');
|
||||
|
||||
/* A security check */
|
||||
hesk_token_check('POST');
|
||||
require(HESK_PATH . 'inc/email_functions.inc.php');
|
||||
|
||||
$revision = sprintf($hesklang['thist3'],hesk_date(),$_SESSION['name'].' ('.$_SESSION['user'].')');
|
||||
|
||||
foreach ($_POST['id'] as $this_id)
|
||||
{
|
||||
if ( is_array($this_id) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
$this_id = intval($this_id) or hesk_error($hesklang['id_not_valid']);
|
||||
|
||||
$result = hesk_dbQuery("SELECT * FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` WHERE `id`='".intval($this_id)."' LIMIT 1");
|
||||
$ticket = hesk_dbFetchAssoc($result);
|
||||
|
||||
hesk_okCategory($ticket['category']);
|
||||
|
||||
$closedStatusRS = hesk_dbQuery("SELECT * FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` WHERE `IsStaffClosedOption` = 1");
|
||||
$closedStatus = hesk_dbFetchAssoc($closedStatusRS);
|
||||
|
||||
hesk_dbQuery("UPDATE `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` SET `status`='".$closedStatus['ID']."', `history`=CONCAT(`history`,'".hesk_dbEscape($revision)."') WHERE `id`='".intval($this_id)."' LIMIT 1");
|
||||
$i++;
|
||||
|
||||
hesk_notifyCustomer('ticket_closed');
|
||||
}
|
||||
|
||||
hesk_process_messages(sprintf($hesklang['num_tickets_closed'],$i),$referer,'SUCCESS');
|
||||
}
|
||||
|
||||
|
||||
/*** START FUNCTIONS ***/
|
||||
|
||||
|
||||
function hesk_fullyDeleteTicket()
|
||||
{
|
||||
global $hesk_settings, $hesklang, $ticket;
|
||||
|
||||
/* 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'])."'");
|
||||
|
||||
return true;
|
||||
}
|
||||
?>
|
@ -0,0 +1,694 @@
|
||||
<?php
|
||||
/*******************************************************************************
|
||||
* Title: Help Desk Software HESK
|
||||
* Version: 2.5.4 from 4th August 2014
|
||||
* Author: Klemen Stirn
|
||||
* Website: http://www.hesk.com
|
||||
********************************************************************************
|
||||
* COPYRIGHT AND TRADEMARK NOTICE
|
||||
* Copyright 2005-2014 Klemen Stirn. All Rights Reserved.
|
||||
* HESK is a registered trademark of Klemen Stirn.
|
||||
|
||||
* The HESK may be used and modified free of charge by anyone
|
||||
* AS LONG AS COPYRIGHT NOTICES AND ALL THE COMMENTS REMAIN INTACT.
|
||||
* By using this code you agree to indemnify Klemen Stirn from any
|
||||
* liability that might arise from it's use.
|
||||
|
||||
* Selling the code for this program, in part or full, without prior
|
||||
* written consent is expressly forbidden.
|
||||
|
||||
* Using this code, in part or full, to create derivate work,
|
||||
* new scripts or products is expressly forbidden. Obtain permission
|
||||
* before redistributing this software over the Internet or in
|
||||
* any other medium. In all cases copyright and header must remain intact.
|
||||
* This Copyright is in full effect in any country that has International
|
||||
* Trade Agreements with the United States of America or
|
||||
* with the European Union.
|
||||
|
||||
* Removing any of the copyright notices without purchasing a license
|
||||
* is expressly forbidden. To remove HESK copyright notice you must purchase
|
||||
* a license for this script. For more information on how to obtain
|
||||
* a license please visit the page below:
|
||||
* https://www.hesk.com/buy.php
|
||||
*******************************************************************************/
|
||||
|
||||
/* Check if this is a valid include */
|
||||
if (!defined('IN_SCRIPT')) {die('Invalid attempt');}
|
||||
|
||||
/*** FUNCTIONS ***/
|
||||
|
||||
|
||||
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 */
|
||||
$merge['attachments'] = '';
|
||||
$merge['replies'] = array();
|
||||
$merge['notes'] = array();
|
||||
$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 `id`,`trackid`,`category`,`name`,`message`,`dt`,`time_worked`,`attachments` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` WHERE `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 */
|
||||
hesk_dbQuery("INSERT INTO `".hesk_dbEscape($hesk_settings['db_pfix'])."replies` (`replyto`,`name`,`message`,`dt`,`attachments`) VALUES ('".intval($ticket['id'])."','".hesk_dbEscape($row['name'])."','".hesk_dbEscape($row['message'])."','".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'])."'");
|
||||
while ( $reply = hesk_dbFetchAssoc($res) )
|
||||
{
|
||||
hesk_dbQuery("INSERT INTO `".hesk_dbEscape($hesk_settings['db_pfix'])."replies` (`replyto`,`name`,`message`,`dt`,`attachments`,`staffid`,`rating`,`read`) VALUES ('".intval($ticket['id'])."','".hesk_dbEscape($reply['name'])."','".hesk_dbEscape($reply['message'])."','".hesk_dbEscape($reply['dt'])."','".hesk_dbEscape($reply['attachments'])."','".intval($reply['staffid'])."','".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'])."'");
|
||||
while ( $note = hesk_dbFetchAssoc($res) )
|
||||
{
|
||||
hesk_dbQuery("INSERT INTO `".hesk_dbEscape($hesk_settings['db_pfix'])."notes` (`ticket`,`who`,`dt`,`message`) VALUES ('".intval($ticket['id'])."','".intval($note['who'])."','".hesk_dbEscape($note['dt'])."','".hesk_dbEscape($note['message'])."')");
|
||||
}
|
||||
|
||||
/* Delete replies to the old ticket */
|
||||
hesk_dbQuery("DELETE FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."notes` WHERE `ticket`='".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'],$_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);
|
||||
|
||||
/* Update history (log) and merged IDs of target ticket */
|
||||
hesk_dbQuery("UPDATE `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` SET `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)."' LIMIT 1");
|
||||
|
||||
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_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;
|
||||
}
|
||||
|
||||
// Add HESK set time difference
|
||||
$dt += 3600*$hesk_settings['diff_hours'] + 60*$hesk_settings['diff_minutes'];
|
||||
|
||||
// Daylight saving?
|
||||
if ($hesk_settings['daylight'] && date('I', $dt))
|
||||
{
|
||||
$dt += 3600;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
$user = hesk_htmlspecialchars( hesk_COOKIE('hesk_username') );
|
||||
$hash = hesk_htmlspecialchars( hesk_COOKIE('hesk_p') );
|
||||
define('HESK_USER', $user);
|
||||
|
||||
if (empty($user) || empty($hash))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Login cookies exist, now lets limit brute force attempts */
|
||||
hesk_limitBfAttempts();
|
||||
|
||||
/* Check username */
|
||||
$result = hesk_dbQuery('SELECT * FROM `'.$hesk_settings['db_pfix']."users` WHERE `user` = '".hesk_dbEscape($user)."' LIMIT 1");
|
||||
if (hesk_dbNumRows($result) != 1)
|
||||
{
|
||||
setcookie('hesk_username', '');
|
||||
setcookie('hesk_p', '');
|
||||
header('Location: index.php?a=login¬ice=1');
|
||||
exit();
|
||||
}
|
||||
|
||||
$res=hesk_dbFetchAssoc($result);
|
||||
foreach ($res as $k=>$v)
|
||||
{
|
||||
$_SESSION[$k]=$v;
|
||||
}
|
||||
|
||||
/* Check password */
|
||||
if ($hash != hesk_Pass2Hash($_SESSION['pass'] . strtolower($user) . $_SESSION['pass']) )
|
||||
{
|
||||
setcookie('hesk_username', '');
|
||||
setcookie('hesk_p', '');
|
||||
header('Location: index.php?a=login¬ice=1');
|
||||
exit();
|
||||
}
|
||||
|
||||
/* Check if default password */
|
||||
if ($_SESSION['pass'] == '499d74967b28a841c98bb4baaabaad699ff3c079')
|
||||
{
|
||||
hesk_process_messages($hesklang['chdp'],'NOREDIRECT','NOTICE');
|
||||
}
|
||||
|
||||
unset($_SESSION['pass']);
|
||||
|
||||
/* Login successful, clean brute force attempts */
|
||||
hesk_cleanBfAttempts();
|
||||
|
||||
/* Regenerate session ID (security) */
|
||||
hesk_session_regenerate_id();
|
||||
|
||||
/* Get allowed categories */
|
||||
if (empty($_SESSION['isadmin']))
|
||||
{
|
||||
$_SESSION['categories']=explode(',',$_SESSION['categories']);
|
||||
}
|
||||
|
||||
/* Renew cookies */
|
||||
setcookie('hesk_username', "$user", strtotime('+1 year'));
|
||||
setcookie('hesk_p', "$hash", strtotime('+1 year'));
|
||||
|
||||
/* Close any old tickets here so Cron jobs aren't necessary */
|
||||
if ($hesk_settings['autoclose'])
|
||||
{
|
||||
$dt = date('Y-m-d H:i:s',time() - $hesk_settings['autoclose']*86400);
|
||||
|
||||
$waitingForCustomerRS = hesk_dbQuery("SELECT `ID` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."statuses` WHERE `IsDefaultStaffReplyStatus` = 1");
|
||||
$waitingForCustomerStatus = hesk_dbFetchAssoc($waitingForCustomerRS);
|
||||
|
||||
$result = hesk_dbQuery("SELECT * FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` WHERE `status` = ".$waitingForCustomerStatus['ID']." AND `lastchange` <= '".hesk_dbEscape($dt)."' ");
|
||||
if (hesk_dbNumRows($result) > 0)
|
||||
{
|
||||
require(HESK_PATH . 'inc/email_functions.inc.php');
|
||||
global $ticket;
|
||||
while ($ticket = hesk_dbFetchAssoc($result)) {
|
||||
hesk_notifyCustomer('ticket_closed');
|
||||
}
|
||||
|
||||
$revision = sprintf($hesklang['thist3'],hesk_date(),$hesklang['auto']);
|
||||
|
||||
$closedStatusRS = hesk_dbQuery("SELECT `ID` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."statuses` WHERE `IsStaffClosedOption` = 1");
|
||||
$closedStatus = hesk_dbFetchAssoc($closedStatusRS);
|
||||
|
||||
$sql = "UPDATE `".$hesk_settings['db_pfix']."tickets` SET `status`=".$closedStatus['ID'].", `history`=CONCAT(`history`,'".hesk_dbEscape($revision)."') WHERE `status` = ".$waitingForCustomerStatus['ID']." AND `lastchange` <= '".hesk_dbEscape($dt)."' ";
|
||||
hesk_dbQuery($sql);
|
||||
}
|
||||
}
|
||||
|
||||
/* 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 */
|
||||
if ( hesk_isREQUEST('goto') && $url=hesk_REQUEST('goto') )
|
||||
{
|
||||
$url = str_replace('&','&',$url);
|
||||
header('Location: '.$url);
|
||||
}
|
||||
else
|
||||
{
|
||||
header('Location: admin_main.php');
|
||||
}
|
||||
exit();
|
||||
} // END hesk_autoLogin()
|
||||
|
||||
|
||||
function hesk_isLoggedIn()
|
||||
{
|
||||
global $hesk_settings;
|
||||
|
||||
$referer = hesk_input($_SERVER['REQUEST_URI']);
|
||||
$referer = str_replace('&','&',$referer);
|
||||
|
||||
if (empty($_SESSION['id']))
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
// Some pages cannot be redirected to
|
||||
$modify_redirect = array(
|
||||
'admin_reply_ticket.php' => 'admin_main.php',
|
||||
'admin_settings_save.php' => 'admin_settings.php',
|
||||
'delete_tickets.php' => 'admin_main.php',
|
||||
'move_category.php' => 'admin_main.php',
|
||||
'priority.php' => 'admin_main.php',
|
||||
);
|
||||
|
||||
foreach ($modify_redirect as $from => $to)
|
||||
{
|
||||
if ( strpos($referer,$from) !== false )
|
||||
{
|
||||
$referer = $to;
|
||||
}
|
||||
}
|
||||
|
||||
$url = 'index.php?a=login¬ice=1&goto='.urlencode($referer);
|
||||
header('Location: '.$url);
|
||||
exit();
|
||||
}
|
||||
else
|
||||
{
|
||||
hesk_session_regenerate_id();
|
||||
|
||||
// Need to update permissions?
|
||||
if ( empty($_SESSION['isadmin']) )
|
||||
{
|
||||
$res = hesk_dbQuery("SELECT `isadmin`, `categories`, `heskprivileges` FROM `".$hesk_settings['db_pfix']."users` WHERE `id` = '".intval($_SESSION['id'])."' LIMIT 1");
|
||||
if (hesk_dbNumRows($res) == 1)
|
||||
{
|
||||
$me = hesk_dbFetchAssoc($res);
|
||||
foreach ($me as $k => $v)
|
||||
{
|
||||
$_SESSION[$k]=$v;
|
||||
}
|
||||
|
||||
// Get allowed categories
|
||||
if (empty($_SESSION['isadmin']) )
|
||||
{
|
||||
$_SESSION['categories']=explode(',',$_SESSION['categories']);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
hesk_session_stop();
|
||||
$url = 'index.php?a=login¬ice=1&goto='.urlencode($referer);
|
||||
header('Location: '.$url);
|
||||
exit();
|
||||
}
|
||||
}
|
||||
|
||||
// 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_Pass2Hash($plaintext) {
|
||||
$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)
|
||||
{
|
||||
$dt=hesk_date($dt);
|
||||
$dt=str_replace(' ','<br />',$dt);
|
||||
return $dt;
|
||||
} // End hesk_formatDate()
|
||||
|
||||
|
||||
function hesk_jsString($str)
|
||||
{
|
||||
$str = str_replace( array('\'','<br />') , array('\\\'','') ,$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_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_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;
|
||||
|
||||
|
||||
/* Check if this is for managing settings */
|
||||
if ($feature == 'can_manage_settings')
|
||||
{
|
||||
if ($_SESSION['can_manage_settings']) {
|
||||
return true;
|
||||
} else {
|
||||
if ($showerror) {
|
||||
hesk_error($hesklang['no_permission'].'<p> </p><p align="center"><a href="index.php">'.$hesklang['click_login'].'</a>');
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Admins have full access to all features, besides possibly settings */
|
||||
if ($_SESSION['isadmin'])
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Check other staff for permissions */
|
||||
if (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()
|
@ -0,0 +1,617 @@
|
||||
<?php
|
||||
/*******************************************************************************
|
||||
* Title: Help Desk Software HESK
|
||||
* Version: 2.5.3 from 16th March 2014
|
||||
* Author: Klemen Stirn
|
||||
* Website: http://www.hesk.com
|
||||
********************************************************************************
|
||||
* COPYRIGHT AND TRADEMARK NOTICE
|
||||
* Copyright 2005-2014 Klemen Stirn. All Rights Reserved.
|
||||
* HESK is a registered trademark of Klemen Stirn.
|
||||
|
||||
* The HESK may be used and modified free of charge by anyone
|
||||
* AS LONG AS COPYRIGHT NOTICES AND ALL THE COMMENTS REMAIN INTACT.
|
||||
* By using this code you agree to indemnify Klemen Stirn from any
|
||||
* liability that might arise from it's use.
|
||||
|
||||
* Selling the code for this program, in part or full, without prior
|
||||
* written consent is expressly forbidden.
|
||||
|
||||
* Using this code, in part or full, to create derivate work,
|
||||
* new scripts or products is expressly forbidden. Obtain permission
|
||||
* before redistributing this software over the Internet or in
|
||||
* any other medium. In all cases copyright and header must remain intact.
|
||||
* This Copyright is in full effect in any country that has International
|
||||
* Trade Agreements with the United States of America or
|
||||
* with the European Union.
|
||||
|
||||
* Removing any of the copyright notices without purchasing a license
|
||||
* is expressly forbidden. To remove HESK copyright notice you must purchase
|
||||
* a license for this script. For more information on how to obtain
|
||||
* a license please visit the page below:
|
||||
* https://www.hesk.com/buy.php
|
||||
*******************************************************************************/
|
||||
|
||||
/* Check if this is a valid include */
|
||||
if (!defined('IN_SCRIPT')) {die('Invalid attempt');}
|
||||
|
||||
|
||||
/* Get includes for SMTP */
|
||||
if ($hesk_settings['smtp'])
|
||||
{
|
||||
require(HESK_PATH . 'inc/mail/smtp.php');
|
||||
if (strlen($hesk_settings['smtp_user']) || strlen($hesk_settings['smtp_password']))
|
||||
{
|
||||
require_once(HESK_PATH . 'inc/mail/sasl/sasl.php');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function hesk_notifyCustomer($email_template = 'new_ticket')
|
||||
{
|
||||
global $hesk_settings, $hesklang, $ticket;
|
||||
|
||||
// Demo mode
|
||||
if ( defined('HESK_DEMO') )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Format email subject and message
|
||||
$subject = hesk_getEmailSubject($email_template,$ticket);
|
||||
$message = hesk_getEmailMessage($email_template,$ticket);
|
||||
|
||||
// Send e-mail
|
||||
hesk_mail($ticket['email'], $subject, $message);
|
||||
|
||||
return true;
|
||||
|
||||
} // END hesk_notifyCustomer()
|
||||
|
||||
|
||||
function hesk_notifyAssignedStaff($autoassign_owner, $email_template, $type = 'notify_assigned')
|
||||
{
|
||||
global $hesk_settings, $hesklang, $ticket;
|
||||
|
||||
// Demo mode
|
||||
if ( defined('HESK_DEMO') )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
$ticket['owner'] = intval($ticket['owner']);
|
||||
|
||||
/* Need to lookup owner info from the database? */
|
||||
if ($autoassign_owner === false)
|
||||
{
|
||||
$res = hesk_dbQuery("SELECT `name`, `email`,`language`,`notify_assigned`,`notify_reply_my` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."users` WHERE `id`='" . $ticket['owner'] . "' LIMIT 1");
|
||||
|
||||
$autoassign_owner = hesk_dbFetchAssoc($res);
|
||||
$hesk_settings['user_data'][$ticket['owner']] = $autoassign_owner;
|
||||
|
||||
/* If owner selected not to be notified or invalid stop here */
|
||||
if ( empty($autoassign_owner[$type]) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* Set new language if required */
|
||||
hesk_setLanguage($autoassign_owner['language']);
|
||||
|
||||
/* Format email subject and message for staff */
|
||||
$subject = hesk_getEmailSubject($email_template,$ticket);
|
||||
$message = hesk_getEmailMessage($email_template,$ticket,1);
|
||||
|
||||
/* Send email to staff */
|
||||
hesk_mail($autoassign_owner['email'], $subject, $message);
|
||||
|
||||
/* Reset language to original one */
|
||||
hesk_resetLanguage();
|
||||
|
||||
return true;
|
||||
|
||||
} // END hesk_notifyAssignedStaff()
|
||||
|
||||
|
||||
function hesk_notifyStaff($email_template,$sql_where,$is_ticket=1)
|
||||
{
|
||||
global $hesk_settings, $hesklang, $ticket;
|
||||
|
||||
// Demo mode
|
||||
if ( defined('HESK_DEMO') )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
$admins = array();
|
||||
|
||||
$res = hesk_dbQuery("SELECT `email`,`language`,`isadmin`,`categories` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."users` WHERE $sql_where ORDER BY `language`");
|
||||
while ($myuser = hesk_dbFetchAssoc($res))
|
||||
{
|
||||
/* Is this an administrator? */
|
||||
if ($myuser['isadmin'])
|
||||
{
|
||||
$admins[] = array('email' => $myuser['email'], 'language' => $myuser['language']);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Not admin, is he/she allowed this category? */
|
||||
$myuser['categories']=explode(',',$myuser['categories']);
|
||||
if (in_array($ticket['category'],$myuser['categories']))
|
||||
{
|
||||
$admins[] = array('email' => $myuser['email'], 'language' => $myuser['language']);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
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 );
|
||||
|
||||
/* 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);
|
||||
$message = 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 );
|
||||
|
||||
/* Reset language to original one */
|
||||
hesk_resetLanguage();
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
} // END hesk_notifyStaff()
|
||||
|
||||
|
||||
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'],
|
||||
|
||||
// --> Ticket closed
|
||||
'ticket_closed' => $hesklang['ticket_closed'],
|
||||
|
||||
|
||||
/*** 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'],
|
||||
|
||||
);
|
||||
} // END hesk_validEmails()
|
||||
|
||||
|
||||
function hesk_mail($to,$subject,$message)
|
||||
{
|
||||
global $hesk_settings, $hesklang;
|
||||
|
||||
// Demo mode
|
||||
if ( defined('HESK_DEMO') )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Encode subject to UTF-8
|
||||
$subject = "=?UTF-8?B?" . base64_encode( hesk_html_entity_decode($subject) ) . "?=";
|
||||
|
||||
// Setup "name <email>" for headers
|
||||
if ($hesk_settings['noreply_name'])
|
||||
{
|
||||
$hesk_settings['from_header'] = "=?UTF-8?B?" . base64_encode( hesk_html_entity_decode($hesk_settings['noreply_name']) ) . "?= <" . $hesk_settings['noreply_mail'] . ">";
|
||||
}
|
||||
else
|
||||
{
|
||||
$hesk_settings['from_header'] = $hesk_settings['noreply_mail'];
|
||||
}
|
||||
|
||||
// Uncomment for debugging
|
||||
# echo "<p>TO: $to<br >SUBJECT: $subject<br >MSG: $message</p>";
|
||||
# return true;
|
||||
|
||||
// Use PHP's mail function
|
||||
if ( ! $hesk_settings['smtp'])
|
||||
{
|
||||
// Set additional headers
|
||||
$headers = "From: $hesk_settings[from_header]\n";
|
||||
$headers.= "Reply-To: $hesk_settings[from_header]\n";
|
||||
$headers.= "Return-Path: $hesk_settings[webmaster_mail]\n";
|
||||
$headers.= "Date: " . date(DATE_RFC2822) . "\n";
|
||||
$headers.= "Content-Type: text/plain; charset=" . $hesklang['ENCODING'];
|
||||
|
||||
// Send using PHP mail() function
|
||||
ob_start();
|
||||
mail($to,$subject,$message,$headers);
|
||||
$tmp = trim(ob_get_contents());
|
||||
ob_end_clean();
|
||||
|
||||
return (strlen($tmp)) ? $tmp : true;
|
||||
}
|
||||
|
||||
// Use a SMTP server directly instead
|
||||
$smtp = new smtp_class;
|
||||
$smtp->host_name = $hesk_settings['smtp_host_name'];
|
||||
$smtp->host_port = $hesk_settings['smtp_host_port'];
|
||||
$smtp->timeout = $hesk_settings['smtp_timeout'];
|
||||
$smtp->ssl = $hesk_settings['smtp_ssl'];
|
||||
$smtp->start_tls = $hesk_settings['smtp_tls'];
|
||||
$smtp->user = $hesk_settings['smtp_user'];
|
||||
$smtp->password = hesk_htmlspecialchars_decode($hesk_settings['smtp_password']);
|
||||
$smtp->debug = 1;
|
||||
|
||||
// Start output buffering so that any errors don't break headers
|
||||
ob_start();
|
||||
|
||||
// Send the e-mail using SMTP
|
||||
$to_arr = explode(',',$to);
|
||||
if ( ! $smtp->SendMessage($hesk_settings['noreply_mail'], $to_arr, array(
|
||||
"From: $hesk_settings[from_header]",
|
||||
"To: $to",
|
||||
"Reply-To: $hesk_settings[from_header]",
|
||||
"Return-Path: $hesk_settings[webmaster_mail]",
|
||||
"Subject: " . $subject,
|
||||
"Date: " . date(DATE_RFC2822),
|
||||
"Content-Type: text/plain; charset=" . $hesklang['ENCODING']
|
||||
), $message))
|
||||
{
|
||||
// Suppress errors unless we are in debug mode
|
||||
if ($hesk_settings['debug_mode'])
|
||||
{
|
||||
$error = $hesklang['cnsm'] . ' ' . $to . '<br /><br />' .
|
||||
$hesklang['error'] . ': ' . htmlspecialchars($smtp->error). '<br /><br />' .
|
||||
'<textarea name="smtp_log" rows="10" cols="60">' . ob_get_contents() . '</textarea>';
|
||||
ob_end_clean();
|
||||
hesk_error($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 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);
|
||||
|
||||
/* Get priority */
|
||||
switch ($ticket['priority'])
|
||||
{
|
||||
case 0:
|
||||
$ticket['priority'] = $hesklang['critical'];
|
||||
break;
|
||||
case 1:
|
||||
$ticket['priority'] = $hesklang['high'];
|
||||
break;
|
||||
case 2:
|
||||
$ticket['priority'] = $hesklang['medium'];
|
||||
break;
|
||||
default:
|
||||
$ticket['priority'] = $hesklang['low'];
|
||||
}
|
||||
|
||||
/* Set status */
|
||||
switch ($ticket['status'])
|
||||
{
|
||||
case 1:
|
||||
$ticket['status'] = $hesklang['wait_reply'];
|
||||
break;
|
||||
case 2:
|
||||
$ticket['status'] = $hesklang['replied'];
|
||||
break;
|
||||
case 3:
|
||||
$ticket['status'] = $hesklang['closed'];
|
||||
break;
|
||||
case 4:
|
||||
$ticket['status'] = $hesklang['in_progress'];
|
||||
break;
|
||||
case 5:
|
||||
$ticket['status'] = $hesklang['on_hold'];
|
||||
break;
|
||||
default:
|
||||
$ticket['status'] = $hesklang['open'];
|
||||
}
|
||||
|
||||
/* Replace all special tags */
|
||||
$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 */
|
||||
$eml_file = 'language/' . $hesk_settings['languages'][$hesk_settings['language']]['folder'] . '/emails/' . $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);
|
||||
}
|
||||
|
||||
/* Return just the message without any processing? */
|
||||
if ($just_message)
|
||||
{
|
||||
return $msg;
|
||||
}
|
||||
|
||||
// Convert any entities in site title to plain text
|
||||
$hesk_settings['site_title'] = hesk_msgToPlain($hesk_settings['site_title'], 1);
|
||||
|
||||
/* 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']);
|
||||
|
||||
$msg = str_replace('%%NAME%%', $ticket['name'] ,$msg);
|
||||
$msg = str_replace('%%SUBJECT%%', $ticket['subject'] ,$msg);
|
||||
$msg = str_replace('%%TRACK_URL%%', $trackingURL ,$msg);
|
||||
$msg = str_replace('%%SITE_TITLE%%',$hesk_settings['site_title'] ,$msg);
|
||||
$msg = str_replace('%%SITE_URL%%', $hesk_settings['site_url'] ,$msg);
|
||||
|
||||
if ( isset($ticket['message']) )
|
||||
{
|
||||
return str_replace('%%MESSAGE%%', $ticket['message'], $msg);
|
||||
}
|
||||
else
|
||||
{
|
||||
return $msg;
|
||||
}
|
||||
}
|
||||
|
||||
// Is email required to view ticket (for customers only)?
|
||||
$hesk_settings['e_param'] = $hesk_settings['email_view_ticket'] ? '&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);
|
||||
|
||||
/* Set priority title */
|
||||
switch ($ticket['priority'])
|
||||
{
|
||||
case 0:
|
||||
$ticket['priority'] = $hesklang['critical'];
|
||||
break;
|
||||
case 1:
|
||||
$ticket['priority'] = $hesklang['high'];
|
||||
break;
|
||||
case 2:
|
||||
$ticket['priority'] = $hesklang['medium'];
|
||||
break;
|
||||
default:
|
||||
$ticket['priority'] = $hesklang['low'];
|
||||
}
|
||||
|
||||
/* Get owner name */
|
||||
$ticket['owner'] = hesk_msgToPlain( hesk_getOwnerName($ticket['owner']), 1);
|
||||
|
||||
/* Set status */
|
||||
switch ($ticket['status'])
|
||||
{
|
||||
case 1:
|
||||
$ticket['status'] = $hesklang['wait_reply'];
|
||||
break;
|
||||
case 2:
|
||||
$ticket['status'] = $hesklang['replied'];
|
||||
break;
|
||||
case 3:
|
||||
$ticket['status'] = $hesklang['closed'];
|
||||
break;
|
||||
case 4:
|
||||
$ticket['status'] = $hesklang['in_progress'];
|
||||
break;
|
||||
case 5:
|
||||
$ticket['status'] = $hesklang['on_hold'];
|
||||
break;
|
||||
default:
|
||||
$ticket['status'] = $hesklang['open'];
|
||||
}
|
||||
|
||||
/* Replace all special tags */
|
||||
$msg = str_replace('%%NAME%%', $ticket['name'] ,$msg);
|
||||
$msg = str_replace('%%SUBJECT%%', $ticket['subject'] ,$msg);
|
||||
$msg = str_replace('%%TRACK_ID%%', $ticket['trackid'] ,$msg);
|
||||
$msg = str_replace('%%TRACK_URL%%', $trackingURL ,$msg);
|
||||
$msg = str_replace('%%SITE_TITLE%%',$hesk_settings['site_title'],$msg);
|
||||
$msg = str_replace('%%SITE_URL%%', $hesk_settings['site_url'] ,$msg);
|
||||
$msg = str_replace('%%CATEGORY%%', $ticket['category'] ,$msg);
|
||||
$msg = str_replace('%%PRIORITY%%', $ticket['priority'] ,$msg);
|
||||
$msg = str_replace('%%OWNER%%', $ticket['owner'] ,$msg);
|
||||
$msg = str_replace('%%STATUS%%', $ticket['status'] ,$msg);
|
||||
$msg = str_replace('%%EMAIL%%', $ticket['email'] ,$msg);
|
||||
$msg = str_replace('%%CREATED%%', $ticket['dt'] ,$msg);
|
||||
$msg = str_replace('%%UPDATED%%', $ticket['lastchange'] ,$msg);
|
||||
|
||||
/* All custom fields */
|
||||
foreach ($hesk_settings['custom_fields'] as $k=>$v)
|
||||
{
|
||||
if ($v['use'])
|
||||
{
|
||||
if ($v['type'] == 'checkbox')
|
||||
{
|
||||
$ticket[$k] = str_replace("<br />","\n",$ticket[$k]);
|
||||
}
|
||||
|
||||
$msg = str_replace('%%'.strtoupper($k).'%%',stripslashes($ticket[$k]),$msg);
|
||||
}
|
||||
else
|
||||
{
|
||||
$msg = str_replace('%%'.strtoupper($k).'%%','',$msg);
|
||||
}
|
||||
}
|
||||
|
||||
// Is message tag in email template?
|
||||
if (strpos($msg, '%%MESSAGE%%') !== false)
|
||||
{
|
||||
// Replace message
|
||||
$msg = str_replace('%%MESSAGE%%',$ticket['message'],$msg);
|
||||
|
||||
// Add direct links to any attachments at the bottom of the email message
|
||||
if ($hesk_settings['attachments']['use'] && isset($ticket['attachments']) && strlen($ticket['attachments']) )
|
||||
{
|
||||
$msg .= "\n\n\n" . $hesklang['fatt'];
|
||||
|
||||
$att = explode(',', substr($ticket['attachments'], 0, -1));
|
||||
foreach ($att as $myatt)
|
||||
{
|
||||
list($att_id, $att_name) = explode('#', $myatt);
|
||||
$msg .= "\n\n" . $att_name . "\n" . $hesk_settings['hesk_url'] . '/download_attachment.php?att_id='.$att_id.'&track='.$ticket['trackid'].$hesk_settings['e_param'];
|
||||
}
|
||||
}
|
||||
|
||||
// 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['strip_quoted'])
|
||||
{
|
||||
$msg = $hesklang['EMAIL_HR'] . "\n\n" . $msg;
|
||||
}
|
||||
}
|
||||
|
||||
return $msg;
|
||||
|
||||
} // END hesk_getEmailMessage
|
@ -0,0 +1,14 @@
|
||||
Dear %%NAME%%,
|
||||
|
||||
Your support ticket "%%SUBJECT%%" has been updated to a closed/resolved status.
|
||||
|
||||
Ticket tracking ID: %%TRACK_ID%%
|
||||
|
||||
You can view the status of your ticket here:
|
||||
%%TRACK_URL%%
|
||||
|
||||
|
||||
Sincerely,
|
||||
|
||||
%%SITE_TITLE%%
|
||||
%%SITE_URL%%
|
Loading…
Reference in New Issue