Merge remote-tracking branch 'origin/master' into 357-calendar-planning-phase-two

master
Mike Koch 7 years ago
commit 8050e10c30
No known key found for this signature in database
GPG Key ID: 9BA5D7F8391455ED

@ -189,9 +189,9 @@ if ($hesk_settings['attachments']['use'] && !empty($attachments)) {
// Add reply // Add reply
$html = $modsForHesk_settings['rich_text_for_tickets']; $html = $modsForHesk_settings['rich_text_for_tickets'];
if ($submit_as_customer) { if ($submit_as_customer) {
hesk_dbQuery("INSERT INTO `" . hesk_dbEscape($hesk_settings['db_pfix']) . "replies` (`replyto`,`name`,`message`,`dt`,`attachments`,`html`) VALUES ('" . intval($replyto) . "','" . hesk_dbEscape(addslashes($ticket['name'])) . "','" . hesk_dbEscape($message . "<br /><br /><i>{$hesklang['creb']} {$_SESSION['name']}</i>") . "','" . hesk_dbEscape(hesk_date()) . "','" . hesk_dbEscape($myattachments) . "', '" . $html . "')"); hesk_dbQuery("INSERT INTO `" . hesk_dbEscape($hesk_settings['db_pfix']) . "replies` (`replyto`,`name`,`message`,`dt`,`attachments`,`html`) VALUES ('" . intval($replyto) . "','" . hesk_dbEscape(addslashes($ticket['name'])) . "','" . hesk_dbEscape($message . "<br /><br /><i>{$hesklang['creb']} {$_SESSION['name']}</i>") . "', NOW(),'" . hesk_dbEscape($myattachments) . "', '" . $html . "')");
} else { } else {
hesk_dbQuery("INSERT INTO `" . hesk_dbEscape($hesk_settings['db_pfix']) . "replies` (`replyto`,`name`,`message`,`dt`,`attachments`,`staffid`,`html`) VALUES ('" . intval($replyto) . "','" . hesk_dbEscape(addslashes($_SESSION['name'])) . "','" . hesk_dbEscape($message) . "','" . hesk_dbEscape(hesk_date()) . "','" . hesk_dbEscape($myattachments) . "','" . intval($_SESSION['id']) . "', '" . $html . "')"); hesk_dbQuery("INSERT INTO `" . hesk_dbEscape($hesk_settings['db_pfix']) . "replies` (`replyto`,`name`,`message`,`dt`,`attachments`,`staffid`,`html`) VALUES ('" . intval($replyto) . "','" . hesk_dbEscape(addslashes($_SESSION['name'])) . "','" . hesk_dbEscape($message) . "', NOW(),'" . hesk_dbEscape($myattachments) . "','" . intval($_SESSION['id']) . "', '" . $html . "')");
} }
/* Track ticket status changes for history */ /* Track ticket status changes for history */
@ -294,6 +294,15 @@ $sql .= $submit_as_customer ? "`lastreplier`='0', `replierid`='0' " : "`lastrepl
if ($time_worked == '00:00:00') { if ($time_worked == '00:00:00') {
$sql .= ", `lastchange` = NOW() "; $sql .= ", `lastchange` = NOW() ";
} else { } else {
$parts = explode(':', $ticket['time_worked']);
$seconds = ($parts[0] * 3600) + ($parts[1] * 60) + $parts[2];
$parts = explode(':', $time_worked);
$seconds += ($parts[0] * 3600) + ($parts[1] * 60) + $parts[2];
require(HESK_PATH . 'inc/reporting_functions.inc.php');
$ticket['time_worked'] = hesk_SecondsToHHMMSS($seconds);
$sql .= ",`time_worked` = ADDTIME(`time_worked`,'" . hesk_dbEscape($time_worked) . "') "; $sql .= ",`time_worked` = ADDTIME(`time_worked`,'" . hesk_dbEscape($time_worked) . "') ";
} }
@ -363,7 +372,9 @@ $info = array(
'dt' => hesk_date($ticket['dt'], true), 'dt' => hesk_date($ticket['dt'], true),
'lastchange' => hesk_date($ticket['lastchange'], true), 'lastchange' => hesk_date($ticket['lastchange'], true),
'id' => $ticket['id'], 'id' => $ticket['id'],
'language' => $ticket['language'] 'language' => $ticket['language'],
'time_worked' => $ticket['time_worked'],
'last_reply_by' => ($submit_as_customer ? $ticket['name'] : $_SESSION['name']),
); );
// 2. Add custom fields to the array // 2. Add custom fields to the array

@ -62,6 +62,7 @@ $set['noreply_mail'] = hesk_validateEmail(hesk_POST('s_noreply_mail'), $hesklang
$set['noreply_name'] = hesk_input(hesk_POST('s_noreply_name')); $set['noreply_name'] = hesk_input(hesk_POST('s_noreply_name'));
$set['noreply_name'] = str_replace(array('\\&quot;', '&lt;', '&gt;'), '', $set['noreply_name']); $set['noreply_name'] = str_replace(array('\\&quot;', '&lt;', '&gt;'), '', $set['noreply_name']);
$set['noreply_name'] = trim(preg_replace('/\s{2,}/', ' ', $set['noreply_name'])); $set['noreply_name'] = trim(preg_replace('/\s{2,}/', ' ', $set['noreply_name']));
$set['noreply_name'] = preg_replace("/\n|\r|\t|%0A|%0D|%08|%09/", '', $set['noreply_name']);
/* --> Language settings */ /* --> Language settings */
$set['can_sel_lang'] = empty($_POST['s_can_sel_lang']) ? 0 : 1; $set['can_sel_lang'] = empty($_POST['s_can_sel_lang']) ? 0 : 1;

@ -423,13 +423,14 @@ if (isset($_POST['notemsg']) && hesk_token_check('POST')) {
'trackid' => $ticket['trackid'], 'trackid' => $ticket['trackid'],
'status' => $ticket['status'], 'status' => $ticket['status'],
'name' => $_SESSION['name'], 'name' => $_SESSION['name'],
'lastreplier' => $ticket['lastreplier'],
'subject' => $ticket['subject'], 'subject' => $ticket['subject'],
'message' => stripslashes($msg), 'message' => stripslashes($msg),
'dt' => hesk_date($ticket['dt'], true), 'dt' => hesk_date($ticket['dt'], true),
'lastchange' => hesk_date($ticket['lastchange'], true), 'lastchange' => hesk_date($ticket['lastchange'], true),
'attachments' => $myattachments, 'attachments' => $myattachments,
'id' => $ticket['id'], 'id' => $ticket['id'],
'time_worked' => $ticket['time_worked'],
'last_reply_by' => $ticket['repliername'],
); );
// 2. Add custom fields to the array // 2. Add custom fields to the array
@ -1561,7 +1562,7 @@ function hesk_getAdminButtons($category_id)
function hesk_getAdminButtonsInTicket($reply = 0, $white = 1) function hesk_getAdminButtonsInTicket($reply = 0, $white = 1)
{ {
global $hesk_settings, $hesklang, $ticket, $reply, $trackingID, $can_edit, $can_archive, $can_delete, $isManager; global $hesk_settings, $hesklang, $ticket, $trackingID, $can_edit, $can_archive, $can_delete, $isManager;
$options = $reply ? '' : '<div class="pull-right">'; $options = $reply ? '' : '<div class="pull-right">';
@ -1828,7 +1829,7 @@ function hesk_printTicketReplies()
} }
// Re-sort them so they're in order by date // Re-sort them so they're in order by date
usort($combined_records, function ($a, $b) { usort($combined_records, function ($a, $b) use (&$hesk_settings) {
$a_date = null; $a_date = null;
$b_date = null; $b_date = null;
if ($a['SORT_TYPE'] == 'REPLY') { if ($a['SORT_TYPE'] == 'REPLY') {
@ -1844,12 +1845,14 @@ function hesk_printTicketReplies()
} }
if ($a_date === $b_date && $a['SORT_TYPE'] != $b['SORT_TYPE']) { if ($a_date === $b_date && $a['SORT_TYPE'] != $b['SORT_TYPE']) {
if ($a['SORT_TYPE'] != $b['SORT_TYPE']) { if ($hesk_settings['new_top']) {
return $a['SORT_TYPE'] == 'REPLY' ? -1 : 1; return $a['SORT_TYPE'] == 'REPLY' ? 1 : -1;
} }
return $a['SORT_TYPE'] == 'REPLY' ? -1 : 1;
} }
return $a_date - $b_date; return $hesk_settings['new_top'] ? $b_date - $a_date : $a_date - $b_date;
}); });
@ -1934,7 +1937,7 @@ function mfh_print_reply($reply) {
?> ?>
</div> </div>
<div class="col-md-6 text-right"> <div class="col-md-6 text-right">
<?php echo hesk_getAdminButtonsInTicket(); ?> <?php echo hesk_getAdminButtonsInTicket($reply); ?>
</div> </div>
</div> </div>
</div> </div>

@ -129,13 +129,14 @@ $info = array(
'trackid' => $ticket['trackid'], 'trackid' => $ticket['trackid'],
'status' => $ticket['status'], 'status' => $ticket['status'],
'name' => $ticket['name'], 'name' => $ticket['name'],
'lastreplier' => $ticket['lastreplier'],
'subject' => $ticket['subject'], 'subject' => $ticket['subject'],
'message' => $ticket['message'], 'message' => $ticket['message'],
'attachments' => $ticket['attachments'], 'attachments' => $ticket['attachments'],
'dt' => hesk_date($ticket['dt'], true), 'dt' => hesk_date($ticket['dt'], true),
'lastchange' => hesk_date($ticket['lastchange'], true), 'lastchange' => hesk_date($ticket['lastchange'], true),
'id' => $ticket['id'], 'id' => $ticket['id'],
'time_worked' => $ticket['time_worked'],
'last_reply_by' => hesk_getReplierName($ticket),
); );
// 2. Add custom fields to the array // 2. Add custom fields to the array

@ -368,7 +368,7 @@ require_once(HESK_PATH . 'inc/show_admin_nav.inc.php');
<label for="subject" class="col-sm-3 control-label"><?php echo $hesklang['subject'] . $required; ?></label> <label for="subject" class="col-sm-3 control-label"><?php echo $hesklang['subject'] . $required; ?></label>
<div class="col-sm-9"> <div class="col-sm-9">
<input class="form-control" type="text" name="subject" size="40" maxlength="40" <input class="form-control" type="text" name="subject" size="40" maxlength="70"
value="<?php echo $ticket['subject']; ?>" value="<?php echo $ticket['subject']; ?>"
placeholder="<?php echo htmlspecialchars($hesklang['subject']); ?>"/> placeholder="<?php echo htmlspecialchars($hesklang['subject']); ?>"/>
</div> </div>
@ -380,7 +380,7 @@ require_once(HESK_PATH . 'inc/show_admin_nav.inc.php');
</label> </label>
<div class="col-sm-9"> <div class="col-sm-9">
<input class="form-control" type="text" name="name" size="40" maxlength="30" <input class="form-control" type="text" name="name" size="40" maxlength="50"
value="<?php echo $ticket['name']; ?>" value="<?php echo $ticket['name']; ?>"
placeholder="<?php echo htmlspecialchars($hesklang['name']); ?>" placeholder="<?php echo htmlspecialchars($hesklang['name']); ?>"
data-error="<?php echo $hesklang['this_field_is_required']; ?>" data-error="<?php echo $hesklang['this_field_is_required']; ?>"

@ -697,7 +697,7 @@ require_once(HESK_PATH . 'inc/show_admin_nav.inc.php');
(<?php echo $hesklang['m' . date('n')]; ?>) (<?php echo $hesklang['m' . date('n')]; ?>)
</option> </option>
<option value="4" <?php echo $selected['time'][4]; ?>><?php echo $hesklang['r4']; ?> <option value="4" <?php echo $selected['time'][4]; ?>><?php echo $hesklang['r4']; ?>
(<?php echo $hesklang['m' . date('n', mktime(0, 0, 0, date('m') - 1, date('d'), date('Y')))]; ?> (<?php echo $hesklang['m' . date('n', mktime(0, 0, 0, date('m') - 1, 1, date('Y')))]; ?>
) )
</option> </option>
<option value="5" <?php echo $selected['time'][5]; ?>><?php echo $hesklang['r5']; ?></option> <option value="5" <?php echo $selected['time'][5]; ?>><?php echo $hesklang['r5']; ?></option>

@ -145,21 +145,21 @@ LEFT(`message`, 400) AS `message`,
$sql .= " ( `trackid` = '" . hesk_dbEscape($q) . "' OR `merged` LIKE '%#" . hesk_dbEscape($q) . "#%' ) "; $sql .= " ( `trackid` = '" . hesk_dbEscape($q) . "' OR `merged` LIKE '%#" . hesk_dbEscape($q) . "#%' ) ";
break; break;
case 'name': case 'name':
$sql .= "`name` LIKE '%" . hesk_dbEscape($q) . "%' COLLATE '" . hesk_dbCollate() . "' "; $sql .= "`name` LIKE '%".hesk_dbEscape( hesk_dbLike($q) )."%' COLLATE '" . hesk_dbCollate() . "' ";
break; break;
case 'email': case 'email':
$sql .= "`email` LIKE '%" . hesk_dbEscape($q) . "%' "; $sql .= "`email` LIKE '%" . hesk_dbEscape($q) . "%' ";
break; break;
case 'subject': case 'subject':
$sql .= "`subject` LIKE '%" . hesk_dbEscape($q) . "%' COLLATE '" . hesk_dbCollate() . "' "; $sql .= "`subject` LIKE '%".hesk_dbEscape( hesk_dbLike($q) )."%' COLLATE '" . hesk_dbCollate() . "' ";
break; break;
case 'message': case 'message':
$sql .= " ( `message` LIKE '%" . hesk_dbEscape($q) . "%' COLLATE '" . hesk_dbCollate() . "' $sql .= " ( `message` LIKE '%".hesk_dbEscape( hesk_dbLike($q) )."%' COLLATE '" . hesk_dbCollate() . "'
OR OR
`id` IN ( `id` IN (
SELECT DISTINCT `replyto` SELECT DISTINCT `replyto`
FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "replies` FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "replies`
WHERE `message` LIKE '%" . hesk_dbEscape($q) . "%' COLLATE '" . hesk_dbCollate() . "' ) WHERE `message` LIKE '%".hesk_dbEscape( hesk_dbLike($q) )."%' COLLATE '" . hesk_dbCollate() . "' )
) )
"; ";
break; break;
@ -170,7 +170,7 @@ LEFT(`message`, 400) AS `message`,
$sql .= "`id` IN ( $sql .= "`id` IN (
SELECT DISTINCT `ticket` SELECT DISTINCT `ticket`
FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "notes` FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "notes`
WHERE `message` LIKE '%" . hesk_dbEscape($q) . "%' COLLATE '" . hesk_dbCollate() . "' ) WHERE `message` LIKE '%".hesk_dbEscape( hesk_dbLike($q) )."%' COLLATE '" . hesk_dbCollate() . "' )
"; ";
break; break;
default: default:
@ -220,6 +220,9 @@ LEFT(`message`, 400) AS `message`,
$sql_count .= $sql; $sql_count .= $sql;
$sql = $sql_final . $sql; $sql = $sql_final . $sql;
// Strip extra slashes
$q = stripslashes($q);
/* Prepare variables used in search and forms */ /* Prepare variables used in search and forms */
require_once(HESK_PATH . 'inc/prepare_ticket_search.inc.php'); require_once(HESK_PATH . 'inc/prepare_ticket_search.inc.php');
?> ?>

@ -158,7 +158,7 @@ function do_login()
exit(); exit();
} }
$pass_enc = hesk_Pass2Hash($_SESSION['pass'] . strtolower($user) . $_SESSION['pass']); $pass_enc = hesk_Pass2Hash($_SESSION['pass'].hesk_mb_strtolower($user).$_SESSION['pass']);
/* Check if default password */ /* Check if default password */
if ($_SESSION['pass'] == '499d74967b28a841c98bb4baaabaad699ff3c079') { if ($_SESSION['pass'] == '499d74967b28a841c98bb4baaabaad699ff3c079') {
@ -330,7 +330,7 @@ function print_login()
<select class="form-control" name="user"> <select class="form-control" name="user">
<?php <?php
while ($row = hesk_dbFetchAssoc($res)): while ($row = hesk_dbFetchAssoc($res)):
$sel = (strtolower($savedUser) == strtolower($row['user'])) ? 'selected' : ''; $sel = (hesk_mb_strtolower($savedUser) == hesk_mb_strtolower($row['user'])) ? 'selected="selected"' : '';
?> ?>
<option value="<?php echo $row['user']; ?>" <?php echo $sel; ?>> <option value="<?php echo $row['user']; ?>" <?php echo $sel; ?>>
<?php echo $row['user']; ?> <?php echo $row['user']; ?>

@ -374,7 +374,7 @@ echo '</script>';
<div class="input-group"> <div class="input-group">
<input type="text" id="link" class="form-control white-readonly" <input type="text" id="link" class="form-control white-readonly"
title="<?php echo $hesklang['genl']; ?>" readonly> title="<?php echo $hesklang['genl']; ?>" readonly>
<div class="input-group-addon button" data-toggle="tooltip" title="Copy to clipboard" <div class="generate-link-button input-group-addon button" data-toggle="tooltip" title="Copy to clipboard"
style="padding:0; border: none"> style="padding:0; border: none">
<button class="btn btn-primary"> <button class="btn btn-primary">
<i class="fa fa-files-o"></i> <i class="fa fa-files-o"></i>

@ -328,6 +328,8 @@ function getSpecialTagMap()
$map['%%OWNER%%'] = $hesklang['ticket_owner']; $map['%%OWNER%%'] = $hesklang['ticket_owner'];
$map['%%PRIORITY%%'] = $hesklang['ticket_priority']; $map['%%PRIORITY%%'] = $hesklang['ticket_priority'];
$map['%%STATUS%%'] = $hesklang['ticket_status']; $map['%%STATUS%%'] = $hesklang['ticket_status'];
$map['%%LAST_REPLY_BY%%'] = $hesklang['last_reply_by'];
$map['%%TIME_WORKED%%'] = $hesklang['ts'];
$i = 1; $i = 1;
foreach ($hesk_settings['custom_fields'] as $key => $value) { foreach ($hesk_settings['custom_fields'] as $key => $value) {

@ -900,7 +900,7 @@ function import_article()
$_SESSION['new_article'] = array( $_SESSION['new_article'] = array(
'html' => 0, 'html' => 0,
'subject' => $ticket['subject'], 'subject' => $ticket['subject'],
'content' => hesk_msgToPlain($ticket['message']), 'content' => hesk_msgToPlain($ticket['message'], 0, 0),
); );
} }
@ -915,10 +915,14 @@ function import_article()
} }
else else
{ {
$_SESSION['new_article']['content'] .= "\n\n" . hesk_msgToPlain($reply['message']); $_SESSION['new_article']['content'] .= "\n\n" . hesk_msgToPlain($reply['message'], 0, 0);
} }
} }
// Make sure everything is extra slashed as stripslashes will be called later
$_SESSION['new_article']['subject'] = addslashes($_SESSION['new_article']['subject']);
$_SESSION['new_article']['content'] = addslashes($_SESSION['new_article']['content']);
hesk_process_messages($hesklang['import'],'NOREDIRECT','NOTICE'); hesk_process_messages($hesklang['import'],'NOREDIRECT','NOTICE');
} // END add_article() } // END add_article()

@ -59,7 +59,7 @@ if (!$row['autoassign']) {
$category_ok = hesk_okCategory($category, 0); $category_ok = hesk_okCategory($category, 0);
// Is user allowed to move tickets to this category? // Is user allowed to move tickets to this category?
if (!$category_ok && !hesk_checkPermission('can_submit_any_cat', 0)) { if ( ! $category_ok && ! hesk_checkPermission('can_change_cat', 0) ) {
hesk_process_messages($hesklang['noauth_move'],'admin_main.php'); hesk_process_messages($hesklang['noauth_move'],'admin_main.php');
} }
@ -128,13 +128,13 @@ $info = array(
'trackid' => $ticket['trackid'], 'trackid' => $ticket['trackid'],
'status' => $ticket['status'], 'status' => $ticket['status'],
'name' => $ticket['name'], 'name' => $ticket['name'],
'lastreplier' => $ticket['lastreplier'],
'subject' => $ticket['subject'], 'subject' => $ticket['subject'],
'message' => $ticket['message'], 'message' => $ticket['message'],
'attachments' => $ticket['attachments'], 'attachments' => $ticket['attachments'],
'dt' => hesk_date($ticket['dt'], true), 'dt' => hesk_date($ticket['dt'], true),
'lastchange' => hesk_date($ticket['lastchange'], true), 'lastchange' => hesk_date($ticket['lastchange'], true),
'id' => $ticket['id'], 'id' => $ticket['id'],'time_worked' => $ticket['time_worked'],
'last_reply_by' => hesk_getReplierName($ticket),
); );
// 2. Add custom fields to the array // 2. Add custom fields to the array

@ -244,7 +244,7 @@ $show_quick_help = $show['show'];
class="important">*</span></label> class="important">*</span></label>
<div class="col-sm-9"> <div class="col-sm-9">
<input type="text" class="form-control" name="name" size="40" maxlength="30" <input type="text" class="form-control" name="name" size="40" maxlength="50"
value="<?php if (isset($_SESSION['as_name'])) { value="<?php if (isset($_SESSION['as_name'])) {
echo stripslashes(hesk_input($_SESSION['as_name'])); echo stripslashes(hesk_input($_SESSION['as_name']));
} else if (isset($_GET['name'])) { } else if (isset($_GET['name'])) {
@ -700,7 +700,7 @@ $show_quick_help = $show['show'];
?> ?>
</label> </label>
<div class="col-sm-9"> <div class="col-sm-9">
<span id="HeskSub"><input class="form-control" type="text" name="subject" id="subject" size="40" maxlength="40" <span id="HeskSub"><input class="form-control" type="text" name="subject" id="subject" size="40" maxlength="70"
value="<?php if (isset($_SESSION['as_subject']) || isset($_GET['subject'])) { value="<?php if (isset($_SESSION['as_subject']) || isset($_GET['subject'])) {
echo stripslashes(hesk_input($_SESSION['as_subject'])); echo stripslashes(hesk_input($_SESSION['as_subject']));
} ?>" placeholder="<?php echo htmlspecialchars($hesklang['subject']); ?>" } ?>" placeholder="<?php echo htmlspecialchars($hesklang['subject']); ?>"

@ -166,7 +166,7 @@ function update_profile()
$hesk_error_buffer = ''; $hesk_error_buffer = '';
$_SESSION['new']['name'] = hesk_input(hesk_POST('name')) or $hesk_error_buffer .= '<li>' . $hesklang['enter_your_name'] . '</li>'; $_SESSION['new']['name'] = hesk_input(hesk_POST('name')) or $hesk_error_buffer .= '<li>' . $hesklang['enter_your_name'] . '</li>';
$_SESSION['new']['email'] = hesk_validateEmail(hesk_POST('email'), 'ERR', 0) or $hesk_error_buffer = '<li>' . $hesklang['enter_valid_email'] . '</li>'; $_SESSION['new']['email'] = hesk_validateEmail( hesk_POST('email'), 'ERR', 0) or $hesk_error_buffer .= '<li>' . $hesklang['enter_valid_email'] . '</li>';
$_SESSION['new']['signature'] = hesk_input(hesk_POST('signature')); $_SESSION['new']['signature'] = hesk_input(hesk_POST('signature'));
/* Signature */ /* Signature */

@ -249,7 +249,7 @@ require_once(HESK_PATH . 'inc/show_admin_nav.inc.php');
(<?php echo $hesklang['m' . date('n')]; ?>) (<?php echo $hesklang['m' . date('n')]; ?>)
</option> </option>
<option value="4" <?php echo $selected['time'][4]; ?>><?php echo $hesklang['r4']; ?> <option value="4" <?php echo $selected['time'][4]; ?>><?php echo $hesklang['r4']; ?>
(<?php echo $hesklang['m' . date('n', mktime(0, 0, 0, date('m') - 1, date('d'), date('Y')))]; ?> (<?php echo $hesklang['m' . date('n', mktime(0, 0, 0, date('m') - 1, 1, date('Y')))]; ?>
) )
</option> </option>
<option <option

@ -10,6 +10,10 @@ use PHPMailer;
class BasicEmailSender extends \BaseClass implements EmailSender { class BasicEmailSender extends \BaseClass implements EmailSender {
function sendEmail($emailBuilder, $heskSettings, $modsForHeskSettings, $sendAsHtml) { function sendEmail($emailBuilder, $heskSettings, $modsForHeskSettings, $sendAsHtml) {
if (preg_match("/\n|\r|\t|%0A|%0D|%08|%09/", $emailBuilder->to . $emailBuilder->subject)) {
return false;
}
$mailer = new PHPMailer(); $mailer = new PHPMailer();
if ($heskSettings['smtp']) { if ($heskSettings['smtp']) {

@ -247,6 +247,17 @@ class EmailTemplateParser extends \BaseClass {
$msg = str_replace('%%CREATED%%', $ticket->dateCreated, $msg); $msg = str_replace('%%CREATED%%', $ticket->dateCreated, $msg);
$msg = str_replace('%%UPDATED%%', $ticket->lastChanged, $msg); $msg = str_replace('%%UPDATED%%', $ticket->lastChanged, $msg);
$msg = str_replace('%%ID%%', $ticket->id, $msg); $msg = str_replace('%%ID%%', $ticket->id, $msg);
$msg = str_replace('%%TIME_WORKED%%', $ticket->timeWorked, $msg);
$lastReplyBy = '';
// Get the last reply by
if (!empty($ticket->lastReplier)) {
$lastReplyBy = $ticket->lastReplier;
} else {
$lastReplyBy = $ticket->name;
}
$msg = str_replace('%%LAST_REPLY_BY%%', $lastReplyBy, $msg);
/* All custom fields */ /* All custom fields */
for ($i=1; $i<=50; $i++) { for ($i=1; $i<=50; $i++) {

@ -26,4 +26,8 @@ class Helpers extends \BaseClass {
? $array[$key] ? $array[$key]
: null; : null;
} }
static function boolval($val) {
return $val == true;
}
} }

@ -3,6 +3,8 @@
namespace BusinessLogic\Security; namespace BusinessLogic\Security;
use BusinessLogic\Helpers;
class UserContext extends \BaseClass { class UserContext extends \BaseClass {
/* @var $id int */ /* @var $id int */
public $id; public $id;
@ -79,7 +81,7 @@ class UserContext extends \BaseClass {
$userContext = new UserContext(); $userContext = new UserContext();
$userContext->id = intval($dataRow['id']); $userContext->id = intval($dataRow['id']);
$userContext->username = $dataRow['user']; $userContext->username = $dataRow['user'];
$userContext->admin = boolval($dataRow['isadmin']); $userContext->admin = Helpers::boolval($dataRow['isadmin']);
$userContext->name = $dataRow['name']; $userContext->name = $dataRow['name'];
$userContext->email = $dataRow['email']; $userContext->email = $dataRow['email'];
$userContext->signature = $dataRow['signature']; $userContext->signature = $dataRow['signature'];
@ -90,34 +92,34 @@ class UserContext extends \BaseClass {
$userContext->categories = explode(',', $dataRow['categories']); $userContext->categories = explode(',', $dataRow['categories']);
} }
$userContext->permissions = explode(',', $dataRow['heskprivileges']); $userContext->permissions = explode(',', $dataRow['heskprivileges']);
$userContext->autoAssign = boolval($dataRow['autoassign']); $userContext->autoAssign = Helpers::boolval($dataRow['autoassign']);
$userContext->ratingNegative = intval($dataRow['ratingneg']); $userContext->ratingNegative = intval($dataRow['ratingneg']);
$userContext->ratingPositive = intval($dataRow['ratingpos']); $userContext->ratingPositive = intval($dataRow['ratingpos']);
$userContext->rating = floatval($dataRow['rating']); $userContext->rating = floatval($dataRow['rating']);
$userContext->totalNumberOfReplies = intval($dataRow['replies']); $userContext->totalNumberOfReplies = intval($dataRow['replies']);
$userContext->active = boolval($dataRow['active']); $userContext->active = Helpers::boolval($dataRow['active']);
$preferences = new UserContextPreferences(); $preferences = new UserContextPreferences();
$preferences->afterReply = intval($dataRow['afterreply']); $preferences->afterReply = intval($dataRow['afterreply']);
$preferences->autoStartTimeWorked = boolval($dataRow['autostart']); $preferences->autoStartTimeWorked = Helpers::boolval($dataRow['autostart']);
$preferences->autoreload = intval($dataRow['autoreload']); $preferences->autoreload = intval($dataRow['autoreload']);
$preferences->defaultNotifyCustomerNewTicket = boolval($dataRow['notify_customer_new']); $preferences->defaultNotifyCustomerNewTicket = Helpers::boolval($dataRow['notify_customer_new']);
$preferences->defaultNotifyCustomerReply = boolval($dataRow['notify_customer_reply']); $preferences->defaultNotifyCustomerReply = Helpers::boolval($dataRow['notify_customer_reply']);
$preferences->showSuggestedKnowledgebaseArticles = boolval($dataRow['show_suggested']); $preferences->showSuggestedKnowledgebaseArticles = Helpers::boolval($dataRow['show_suggested']);
$preferences->defaultCalendarView = intval($dataRow['default_calendar_view']); $preferences->defaultCalendarView = intval($dataRow['default_calendar_view']);
$preferences->defaultTicketView = $dataRow['default_list']; $preferences->defaultTicketView = $dataRow['default_list'];
$userContext->preferences = $preferences; $userContext->preferences = $preferences;
$notifications = new UserContextNotifications(); $notifications = new UserContextNotifications();
$notifications->newUnassigned = boolval($dataRow['notify_new_unassigned']); $notifications->newUnassigned = Helpers::boolval($dataRow['notify_new_unassigned']);
$notifications->newAssignedToMe = boolval($dataRow['notify_new_my']); $notifications->newAssignedToMe = Helpers::boolval($dataRow['notify_new_my']);
$notifications->replyUnassigned = boolval($dataRow['notify_reply_unassigned']); $notifications->replyUnassigned = Helpers::boolval($dataRow['notify_reply_unassigned']);
$notifications->replyToMe = boolval($dataRow['notify_reply_my']); $notifications->replyToMe = Helpers::boolval($dataRow['notify_reply_my']);
$notifications->ticketAssignedToMe = boolval($dataRow['notify_assigned']); $notifications->ticketAssignedToMe = Helpers::boolval($dataRow['notify_assigned']);
$notifications->privateMessage = boolval($dataRow['notify_pm']); $notifications->privateMessage = Helpers::boolval($dataRow['notify_pm']);
$notifications->noteOnTicketAssignedToMe = boolval($dataRow['notify_note']); $notifications->noteOnTicketAssignedToMe = Helpers::boolval($dataRow['notify_note']);
$notifications->noteOnTicketNotAssignedToMe = boolval($dataRow['notify_note_unassigned']); $notifications->noteOnTicketNotAssignedToMe = Helpers::boolval($dataRow['notify_note_unassigned']);
$notifications->overdueTicketUnassigned = boolval($dataRow['notify_overdue_unassigned']); $notifications->overdueTicketUnassigned = Helpers::boolval($dataRow['notify_overdue_unassigned']);
$userContext->notificationSettings = $notifications; $userContext->notificationSettings = $notifications;
return $userContext; return $userContext;

@ -41,6 +41,10 @@ class ResendTicketEmailToCustomerController extends InternalApiController {
$reply = null; $reply = null;
$emailTemplate = EmailTemplateRetriever::NEW_TICKET; $emailTemplate = EmailTemplateRetriever::NEW_TICKET;
// Use 0 for new tickets
$ticket->lastReplier = 0;
if (isset($_GET['replyId'])) { if (isset($_GET['replyId'])) {
$replyId = $_GET['replyId']; $replyId = $_GET['replyId'];
$emailTemplate = EmailTemplateRetriever::NEW_REPLY_BY_STAFF; $emailTemplate = EmailTemplateRetriever::NEW_REPLY_BY_STAFF;

@ -97,7 +97,7 @@ function hesk_dbEscape($in)
function hesk_dbLike($in) function hesk_dbLike($in)
{ {
return str_replace( array('_', '%'), array('\\\\_', '\\\\%'), $in); return str_replace( array('_', '%', '\\'), array('\\\\_', '\\\\%', '\\\\'), $in); // '
} // END hesk_dbLike() } // END hesk_dbLike()

@ -97,7 +97,7 @@ function hesk_dbEscape($in)
function hesk_dbLike($in) function hesk_dbLike($in)
{ {
return str_replace( array('_', '%'), array('\\\\_', '\\\\%'), $in); return str_replace( array('_', '%', '\\'), array('\\\\_', '\\\\%', '\\\\'), $in); // '
} // END hesk_dbLike() } // END hesk_dbLike()

@ -4,118 +4,128 @@ require_once 'RequestMethod.php';
/** /**
* @class Main class of the Link router that helps you create and deploy routes * @class Main class of the Link router that helps you create and deploy routes
*/ */
class Link class Link
{ {
/** /**
* @var array A collection of the routes originally passed into all function. Used by static function route * @var array A collection of the routes originally passed into all function. Used by static function route
*/ */
private static $routes = array(); private static $routes = array();
/** /**
* @var array A collection of functions that are executed before a route completion ( valid for all routes ), aka universal before functions * @var array A collection of functions that are executed before a route completion ( valid for all routes ), aka universal before functions
*/ */
private static $beforeFuncs = array(); private static $beforeFuncs = array();
/** /**
* @var array A collection of function that are executed after a route completion ( valid for all routes ), aka universal after functions * @var array A collection of function that are executed after a route completion ( valid for all routes ), aka universal after functions
*/ */
private static $afterFuncs = array(); private static $afterFuncs = array();
/** /**
* Static function of the class Link that deploys the route according to the passed handler and path * Static function of the class Link that deploys the route according to the passed handler and path
* *
* @param array $routes An array of combination of the path and its handler, that are final deployed for a particular url * @param array $routes An array of combination of the path and its handler, that are final deployed for a particular url
*/ */
public static function all( $routes ) public static function all( $routes )
{ {
/* Call all functions that are to be executed before routing */ /* Call all functions that are to be executed before routing */
foreach( self::$beforeFuncs as $beforeFunc ) { foreach( self::$beforeFuncs as $beforeFunc ) {
if( $beforeFunc[1] ) { if( $beforeFunc[1] ) {
call_user_func_array( $beforeFunc[0] , $beforeFunc[1] ); call_user_func_array( $beforeFunc[0] , $beforeFunc[1] );
} else { } else {
call_user_func( $beforeFunc[0] ); call_user_func( $beforeFunc[0] );
} }
} }
self::$routes = $routes; self::$routes = $routes;
$method = self::getRequestMethod(); $method = self::getRequestMethod();
$acceptedMethods = RequestMethod::all(); $acceptedMethods = RequestMethod::all();
$path = '/'; $path = '/';
$handler = null; $handler = null;
$matched = array(); $matched = array();
$middleware = null; $middleware = null;
if ( !empty ( $_SERVER['PATH_INFO'] ) ) { if ( !empty ( $_SERVER['PATH_INFO'] ) ) {
$path = $_SERVER['PATH_INFO']; $path = $_SERVER['PATH_INFO'];
} else if ( !empty ( $_SERVER['REQUEST_URI'] ) ) { } else if ( !empty ( $_SERVER['REQUEST_URI'] ) ) {
$path = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH); $parts = explode('/', $_SERVER['REQUEST_URI']);
} $startingIndex = -1;
for ($i = count($parts) - 1; $i > -1 && $startingIndex === -1; $i--) {
if ( isset($routes[$path] ) ) { if ($parts[$i] === 'index.php' || $parts[$i] === 'api') {
if( is_array( $routes[$path] ) ) { $startingIndex = $i + 1;
$handler = $routes[$path][0]; }
$middleware = $routes[$path][2]; }
$acceptedMethods = $routes[$path][3]; $path = '';
} else { for ($i = $startingIndex; $i < count($parts); $i++) {
$handler = $routes[$path]; $path .= "/{$parts[$i]}";
} }
} else if ( $routes ) { }
$regex = array( if ( isset($routes[$path] ) ) {
'/{i}/', if( is_array( $routes[$path] ) ) {
'/{s}/', $handler = $routes[$path][0];
'/{a}/' $middleware = $routes[$path][2];
); $acceptedMethods = $routes[$path][3];
} else {
$replacements = array( $handler = $routes[$path];
'([\d]+)' , }
'([a-zA-Z]+)', } else if ( $routes ) {
'([\w-]+)'
); $regex = array(
'/{i}/',
foreach ( $routes as $routePath => $routeDesc ){ '/{s}/',
$routePath = preg_replace( $regex, $replacements, $routePath ); '/{a}/'
if( preg_match( '#^/?' . $routePath . '/?$#', $path, $matches ) ){ );
if( is_array( $routeDesc ) ) {
$handler = $routeDesc[0]; $replacements = array(
if( isset( $routeDesc[2] )) { '([\d]+)' ,
$middleware = $routeDesc[2]; '([a-zA-Z]+)',
$acceptedMethods = $routeDesc[3]; '([\w-]+)'
} );
}
else foreach ( $routes as $routePath => $routeDesc ){
$handler = $routeDesc; $routePath = preg_replace( $regex, $replacements, $routePath );
$matched = $matches; if( preg_match( '#^/?' . $routePath . '/?$#', $path, $matches ) ){
break; if( is_array( $routeDesc ) ) {
} $handler = $routeDesc[0];
} if( isset( $routeDesc[2] )) {
} $middleware = $routeDesc[2];
unset( $matched[0] ); $acceptedMethods = $routeDesc[3];
}
if( isset($middleware) ){ }
$newMatched = self::callFunction( $middleware, $matched, $method, $acceptedMethods ); else
/* If new wildcard param are there pass them to main handler */ $handler = $routeDesc;
if( $newMatched ) { $matched = $matches;
self::callFunction( $handler, $newMatched, $method, $acceptedMethods ); break;
} else { }
self::callFunction( $handler, $matched, $method, $acceptedMethods ); }
} }
} else { unset( $matched[0] );
self::callFunction( $handler, $matched, $method, $acceptedMethods );
} if( isset($middleware) ){
$newMatched = self::callFunction( $middleware, $matched, $method, $acceptedMethods );
/* Call all the function that are to be executed after routing */ /* If new wildcard param are there pass them to main handler */
foreach( self::$afterFuncs as $afterFunc ) if( $newMatched ) {
if( $afterFunc[1] ) { self::callFunction( $handler, $newMatched, $method, $acceptedMethods );
call_user_func_array( $afterFunc[0] , $afterFunc[1] ); } else {
} else { self::callFunction( $handler, $matched, $method, $acceptedMethods );
call_user_func( $afterFunc[0] ); }
} } else {
} self::callFunction( $handler, $matched, $method, $acceptedMethods );
}
private static function getRequestMethod() {
/* Call all the function that are to be executed after routing */
foreach( self::$afterFuncs as $afterFunc )
if( $afterFunc[1] ) {
call_user_func_array( $afterFunc[0] , $afterFunc[1] );
} else {
call_user_func( $afterFunc[0] );
}
}
private static function getRequestMethod() {
$headers = getallheaders(); $headers = getallheaders();
$uppercaseHeaders = array(); $uppercaseHeaders = array();
@ -130,42 +140,42 @@ class Link
return $_SERVER['REQUEST_METHOD']; return $_SERVER['REQUEST_METHOD'];
} }
/** /**
* Static function that helps you generate links effortlessly and pass parameters to them, thus enabling to generate dynamic links * Static function that helps you generate links effortlessly and pass parameters to them, thus enabling to generate dynamic links
* *
* @param string $name name of the route for which the link has to be generated * @param string $name name of the route for which the link has to be generated
* @param array $params An array of parameters that are replaced in the route if it contains wildcards * @param array $params An array of parameters that are replaced in the route if it contains wildcards
* For e.g. if route is /name/{i}/{a} and parameters passed are 1, aps then link generated will be /name/1/aps * For e.g. if route is /name/{i}/{a} and parameters passed are 1, aps then link generated will be /name/1/aps
*/ */
public static function route( $name, $params = array() ) public static function route( $name, $params = array() )
{ {
$href = null; $href = null;
foreach ( self::$routes as $routePath => $routeDesc ) { foreach ( self::$routes as $routePath => $routeDesc ) {
if( is_array( $routeDesc ) ){ if( is_array( $routeDesc ) ){
if( $name == $routeDesc[1] ){ if( $name == $routeDesc[1] ){
$href = $routePath; $href = $routePath;
for( $i = 0; $i < count($params); $i++){ for( $i = 0; $i < count($params); $i++){
$href = preg_replace('#{(.*?)}#', $params[$i], $href, 1); $href = preg_replace('#{(.*?)}#', $params[$i], $href, 1);
} }
} }
} }
} }
return $href; return $href;
} }
/** /**
* Static function to handle cases when route is not found, call handler of 404 if defined else * Static function to handle cases when route is not found, call handler of 404 if defined else
* sends a 404 header * sends a 404 header
*/ */
public static function handle404() public static function handle404()
{ {
/* Call '404' route if it exists */ /* Call '404' route if it exists */
if( isset ( self::$routes['404'] ) ) { if( isset ( self::$routes['404'] ) ) {
call_user_func( self::$routes['404'] ); call_user_func( self::$routes['404'] );
} else { } else {
header($_SERVER["SERVER_PROTOCOL"]." 404 Not Found"); header($_SERVER["SERVER_PROTOCOL"]." 404 Not Found");
} }
} }
/** /**
* Static function to handle both middlewares' call and main handler's call. * Static function to handle both middlewares' call and main handler's call.
@ -178,64 +188,64 @@ class Link
* the wildcards that were originally passed, this newParams will * the wildcards that were originally passed, this newParams will
* be next passed to main handler * be next passed to main handler
*/ */
public static function callFunction( $handler , $matched, $method, $acceptedMethods ) public static function callFunction( $handler , $matched, $method, $acceptedMethods )
{ {
if (!in_array($method, $acceptedMethods)) { if (!in_array($method, $acceptedMethods)) {
print_r('Request method ' . $method . ' not allowed'); print_r('Request method ' . $method . ' not allowed');
header($_SERVER['SERVER_PROTOCOL'] . ' 405 Method Not Allowed', true, 405); header($_SERVER['SERVER_PROTOCOL'] . ' 405 Method Not Allowed', true, 405);
die(); die();
} }
if ( $handler ) { if ( $handler ) {
if ( is_callable( $handler ) ) { if ( is_callable( $handler ) ) {
$newParams = call_user_func_array( $handler, $matched ) ; $newParams = call_user_func_array( $handler, $matched ) ;
} else { } else {
/* Check if class exists in the case user is using RESTful pattern */ /* Check if class exists in the case user is using RESTful pattern */
if( class_exists( $handler ) ) { if( class_exists( $handler ) ) {
$instanceOfHandler = new $handler(); // Won't work in case of middleware since we aren't using RESTful in that $instanceOfHandler = new $handler(); // Won't work in case of middleware since we aren't using RESTful in that
} else { } else {
print_r('Class or function ' . $handler . ' not found'); print_r('Class or function ' . $handler . ' not found');
header($_SERVER['SERVER_PROTOCOL'] . ' 500 Internal Server Error', true, 500); header($_SERVER['SERVER_PROTOCOL'] . ' 500 Internal Server Error', true, 500);
die(); die();
} }
} }
} else { } else {
self::handle404(); self::handle404();
} }
if( isset( $instanceOfHandler ) ) { if( isset( $instanceOfHandler ) ) {
if( method_exists( $instanceOfHandler, $method ) ) { if( method_exists( $instanceOfHandler, $method ) ) {
$newParams = call_user_func_array( array( $instanceOfHandler, $method ), $matched ); $newParams = call_user_func_array( array( $instanceOfHandler, $method ), $matched );
} }
} }
if( isset( $newParams ) && $newParams ) { if( isset( $newParams ) && $newParams ) {
return $newParams; return $newParams;
} }
} }
/** /**
* Static function to add functions that are to be excuted before each routing, must be called before Link::all * Static function to add functions that are to be excuted before each routing, must be called before Link::all
* *
* @param string $funcName Name of the funtion to be called upon before * @param string $funcName Name of the funtion to be called upon before
* @param array $params Array of parameters that are to be passed to before function, can be null but if not * @param array $params Array of parameters that are to be passed to before function, can be null but if not
* it must be an array * it must be an array
*/ */
public static function before( $funcName, $params = null ) public static function before( $funcName, $params = null )
{ {
array_push( self::$beforeFuncs, array($funcName, $params)); array_push( self::$beforeFuncs, array($funcName, $params));
} }
/** /**
* Static function to add functions that are to be excuted after each routing, must be called before Link::all * Static function to add functions that are to be excuted after each routing, must be called before Link::all
* *
* @param string $funcName Name of the funtion to be called upon after * @param string $funcName Name of the funtion to be called upon after
* @param array $params Array of parameters that are to be passed to after function, can be null but if not * @param array $params Array of parameters that are to be passed to after function, can be null but if not
* it must be an array * it must be an array
*/ */
public static function after( $funcName, $params = null ) public static function after( $funcName, $params = null )
{ {
array_push( self::$afterFuncs, array($funcName, $params)); array_push( self::$afterFuncs, array($funcName, $params));
} }
} }

@ -10,15 +10,12 @@
} }
], ],
"require-dev": { "require-dev": {
"phpunit/phpunit": "6.3.0" "phpunit/phpunit": "6.3.0",
"clue/graph-composer": "^1.0"
}, },
"require": { "require": {
"phpmailer/phpmailer": "^5.2", "phpmailer/phpmailer": "^5.2",
"mailgun/mailgun-php": "^2.1", "mailgun/mailgun-php": "1.7.2",
"php-http/guzzle6-adapter": "^1.1",
"php-http/message": "^1.5",
"php-http/curl-client": "^1.7",
"guzzlehttp/psr7": "^1.3",
"mike-koch/php-di": "4.4.11", "mike-koch/php-di": "4.4.11",
"doctrine/annotations": "1.2" "doctrine/annotations": "1.2"
} }

1534
api/composer.lock generated

File diff suppressed because it is too large Load Diff

@ -1,4 +1,4 @@
<?php <?php
// Define the current build // Define the current build
define('MODS_FOR_HESK_BUILD', 43); define('MODS_FOR_HESK_BUILD', 46);

@ -12,7 +12,7 @@ while test $# -gt 0; do
continue continue
fi fi
for file in `find $current -type f -not -path "*vendor/*" -not -path "*/api/Tests/*" -name "*.php"` ; do for file in `find $current -type f -not -path "*vendor/phpunit/*" -not -path "*/api/Tests/*" -name "*.php"` ; do
RESULTS=`php -l $file` RESULTS=`php -l $file`
echo $RESULTS echo $RESULTS

@ -98,7 +98,7 @@ function hesk_dbEscape($in)
function hesk_dbLike($in) function hesk_dbLike($in)
{ {
return str_replace( array('_', '%'), array('\\\\_', '\\\\%'), $in); return str_replace( array('_', '%', '\\'), array('\\\\_', '\\\\%', '\\\\'), $in); // '
} // END hesk_dbLike() } // END hesk_dbLike()

@ -97,7 +97,7 @@ function hesk_dbEscape($in)
function hesk_dbLike($in) function hesk_dbLike($in)
{ {
return str_replace( array('_', '%'), array('\\\\_', '\\\\%'), $in); return str_replace( array('_', '%', '\\'), array('\\\\_', '\\\\%', '\\\\'), $in); // '
} // END hesk_dbLike() } // END hesk_dbLike()

@ -331,12 +331,12 @@ div.ticket-info {
opacity: 1; opacity: 1;
} }
.input-group-addon { .generate-link-button {
padding: 0; padding: 0;
border: 0; border: 0;
} }
.input-group-addon.button > button { .generate-link-button.button > button {
border-radius: 0; border-radius: 0;
} }

@ -334,7 +334,7 @@ function hesk_activeSessionValidate($username, $password_hash, $tag)
list($salt, $hash) = explode('|', $tag, 2); list($salt, $hash) = explode('|', $tag, 2);
// Make sure the hash matches existing username and password // Make sure the hash matches existing username and password
if ($hash == sha1($salt . strtolower($username) . $password_hash)) { if ($hash == sha1($salt . hesk_mb_strtolower($username) . $password_hash) ) {
return true; return true;
} }
@ -345,7 +345,7 @@ function hesk_activeSessionValidate($username, $password_hash, $tag)
function hesk_activeSessionCreateTag($username, $password_hash) function hesk_activeSessionCreateTag($username, $password_hash)
{ {
$salt = uniqid(mt_rand(), true); $salt = uniqid(mt_rand(), true);
return $salt . '|' . sha1($salt . strtolower($username) . $password_hash); return $salt . '|' . sha1($salt . hesk_mb_strtolower($username) . $password_hash);
} // END hesk_activeSessionCreateTag() } // END hesk_activeSessionCreateTag()
@ -383,7 +383,7 @@ function hesk_autoLogin($noredirect = 0)
$res = hesk_dbFetchAssoc($result); $res = hesk_dbFetchAssoc($result);
/* Check password */ /* Check password */
if ($hash != hesk_Pass2Hash($res['pass'] . strtolower($user) . $res['pass'])) { if ($hash != hesk_Pass2Hash($res['pass'] . hesk_mb_strtolower($user) . $res['pass']) ) {
hesk_setcookie('hesk_username', ''); hesk_setcookie('hesk_username', '');
hesk_setcookie('hesk_p', ''); hesk_setcookie('hesk_p', '');
header('Location: '.$url); header('Location: '.$url);

@ -357,6 +357,10 @@ function hesk_isREQUEST($in)
return isset($_GET[$in]) || isset($_POST[$in]) ? true : false; return isset($_GET[$in]) || isset($_POST[$in]) ? true : false;
} // END hesk_isREQUEST() } // END hesk_isREQUEST()
function hesk_mb_strtolower($in) {
return function_exists('mb_strtolower') ? mb_strtolower($in) : strtolower($in);
} // END hesk_mb_strtolower()
function hesk_htmlspecialchars_decode($in) function hesk_htmlspecialchars_decode($in)
{ {
@ -835,7 +839,39 @@ function hesk_getCategoryName($id)
$hesk_settings['category_data'][$id]['name'] = hesk_dbResult($res, 0, 0); $hesk_settings['category_data'][$id]['name'] = hesk_dbResult($res, 0, 0);
return $hesk_settings['category_data'][$id]['name']; return $hesk_settings['category_data'][$id]['name'];
} // END hesk_getOwnerName() } // END hesk_getCategoryName()
function hesk_getReplierName($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 $hesklang['staff'];
}
// Get the name using another function
$replier = hesk_getOwnerName($ticket['replierid']);
// If replier comes back as "unassigned", default to "Staff"
if ($replier == $hesklang['unas']) {
return $hesklang['staff'];
}
return $replier;
}
// Last reply by customer
return $ticket['name'];
} // END hesk_getReplierName()
function hesk_getOwnerName($id) function hesk_getOwnerName($id)
@ -2160,6 +2196,10 @@ function mfh_get_hidden_fields_for_language($keys) {
function mfh_insert_audit_trail_record($entity_id, $entity_type, $language_key, $date, $replacement_values = array()) { function mfh_insert_audit_trail_record($entity_id, $entity_type, $language_key, $date, $replacement_values = array()) {
global $hesk_settings; global $hesk_settings;
$oldTimeFormat = $hesk_settings['timeformat'];
$hesk_settings['timeformat'] = 'Y-m-d H:i:s';
$date = hesk_date();
hesk_dbQuery("INSERT INTO `" . hesk_dbEscape($hesk_settings['db_pfix']) . "audit_trail` (`entity_id`, `entity_type`, hesk_dbQuery("INSERT INTO `" . hesk_dbEscape($hesk_settings['db_pfix']) . "audit_trail` (`entity_id`, `entity_type`,
`language_key`, `date`) VALUES (" . intval($entity_id) . ", '" . hesk_dbEscape($entity_type) . "', `language_key`, `date`) VALUES (" . intval($entity_id) . ", '" . hesk_dbEscape($entity_type) . "',
'" . hesk_dbEscape($language_key) . "', '" . hesk_dbEscape($date) . "')"); '" . hesk_dbEscape($language_key) . "', '" . hesk_dbEscape($date) . "')");
@ -2172,6 +2212,8 @@ function mfh_insert_audit_trail_record($entity_id, $entity_type, $language_key,
" . intval($replacement_index) . ", '" . hesk_dbEscape($replacement_value) . "')"); " . intval($replacement_index) . ", '" . hesk_dbEscape($replacement_value) . "')");
} }
$hesk_settings['timeformat'] = $oldTimeFormat;
return $audit_id; return $audit_id;
} }

@ -418,15 +418,21 @@ function hesk_mail($to, $subject, $message, $htmlMessage, $modsForHesk_settings,
return true; return true;
} }
// Stop if we find anything suspicious in the headers
if ( preg_match("/\n|\r|\t|%0A|%0D|%08|%09/", $to . $subject) ) {
return false;
}
// Encode subject to UTF-8 // Encode subject to UTF-8
$subject = "=?UTF-8?B?" . base64_encode(hesk_html_entity_decode($subject)) . "?="; $subject = hesk_encodeIfNotAscii( hesk_html_entity_decode($subject) );
// Auto-generate URLs for HTML-formatted emails // Auto-generate URLs for HTML-formatted emails
$htmlMessage = hesk_makeURL($htmlMessage, '', false); $htmlMessage = hesk_makeURL($htmlMessage, '', false);
// Setup "name <email>" for headers // Setup "name <email>" for headers
if ($hesk_settings['noreply_name']) { 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'] . ">"; $hesk_settings['from_header'] = hesk_encodeIfNotAscii( hesk_html_entity_decode($hesk_settings['noreply_name']) ) . " <" . $hesk_settings['noreply_mail'] . ">";
} else { } else {
$hesk_settings['from_header'] = $hesk_settings['noreply_mail']; $hesk_settings['from_header'] = $hesk_settings['noreply_mail'];
} }
@ -505,6 +511,10 @@ function hesk_mail($to, $subject, $message, $htmlMessage, $modsForHesk_settings,
//-- Close the email //-- Close the email
$message .= "--" . $innerboundary . "--"; $message .= "--" . $innerboundary . "--";
// Remove duplicate recipients
$to_arr = array_unique(explode(',', $to));
$to = implode(',', $to_arr);
// Use PHP's mail function // Use PHP's mail function
if (!$hesk_settings['smtp']) { if (!$hesk_settings['smtp']) {
// Set additional headers // Set additional headers
@ -512,10 +522,10 @@ function hesk_mail($to, $subject, $message, $htmlMessage, $modsForHesk_settings,
$headers .= "MIME-Version: 1.0\n"; $headers .= "MIME-Version: 1.0\n";
$headers .= "From: $hesk_settings[from_header]\n"; $headers .= "From: $hesk_settings[from_header]\n";
if (count($cc) > 0) { if (count($cc) > 0) {
$headers .= "Cc: " . implode(',', $cc); $headers .= "Cc: " . implode(',', $cc) . "\n";
} }
if (count($bcc) > 0) { if (count($bcc) > 0) {
$headers .= "Bcc: " . implode(',', $bcc); $headers .= "Bcc: " . implode(',', $bcc) . "\n";
} }
$headers .= "Reply-To: $hesk_settings[from_header]\n"; $headers .= "Reply-To: $hesk_settings[from_header]\n";
$headers .= "Return-Path: $hesk_settings[webmaster_mail]\n"; $headers .= "Return-Path: $hesk_settings[webmaster_mail]\n";
@ -552,8 +562,6 @@ function hesk_mail($to, $subject, $message, $htmlMessage, $modsForHesk_settings,
ob_start(); ob_start();
// Send the e-mail using SMTP // Send the e-mail using SMTP
$to_arr = explode(',', $to);
$headersArray = array( $headersArray = array(
"From: $hesk_settings[from_header]", "From: $hesk_settings[from_header]",
"To: $to", "To: $to",
@ -728,6 +736,16 @@ function hesk_getEmailMessage($eml_file, $ticket, $modsForHesk_settings, $is_adm
} // END hesk_getEmailMessage } // END hesk_getEmailMessage
function hesk_encodeIfNotAscii($str) {
// Match anything outside of ASCII range
if (preg_match('/[^\x00-\x7F]/', $str)) {
return "=?UTF-8?B?" . base64_encode($str) . "?=";
}
return $str;
} // END hesk_encodeIfNotAscii()
function hesk_doesTemplateHaveTag($eml_file, $tag, $modsForHesk_settings) function hesk_doesTemplateHaveTag($eml_file, $tag, $modsForHesk_settings)
{ {
global $hesk_settings; global $hesk_settings;
@ -795,7 +813,7 @@ function hesk_processMessage($msg, $ticket, $is_admin, $is_ticket, $just_message
$trackingURL .= '?track=' . $ticket['trackid'] . ($is_admin ? '' : $hesk_settings['e_param']) . '&Refresh=' . rand(10000, 99999); $trackingURL .= '?track=' . $ticket['trackid'] . ($is_admin ? '' : $hesk_settings['e_param']) . '&Refresh=' . rand(10000, 99999);
/* Set category title */ /* Set category title */
$ticket['category'] = hesk_msgToPlain(hesk_getCategoryName($ticket['category']), 1); $ticket['category'] = hesk_msgToPlain(hesk_getCategoryName($ticket['category']), 1, 0);
/* Set priority title */ /* Set priority title */
switch ($ticket['priority']) { switch ($ticket['priority']) {
@ -821,6 +839,12 @@ function hesk_processMessage($msg, $ticket, $is_admin, $is_ticket, $just_message
$row = hesk_dbFetchAssoc($statusRs); $row = hesk_dbFetchAssoc($statusRs);
$ticket['status'] = $row['text']; $ticket['status'] = $row['text'];
// Get name of the person who posted the last message
if ( ! isset($ticket['last_reply_by'])) {
$ticket['last_reply_by'] = hesk_getReplierName($ticket);
}
/* Replace all special tags */ /* Replace all special tags */
$msg = str_replace('%%NAME%%', $ticket['name'], $msg); $msg = str_replace('%%NAME%%', $ticket['name'], $msg);
$msg = str_replace('%%SUBJECT%%', $ticket['subject'], $msg); $msg = str_replace('%%SUBJECT%%', $ticket['subject'], $msg);
@ -836,6 +860,8 @@ function hesk_processMessage($msg, $ticket, $is_admin, $is_ticket, $just_message
$msg = str_replace('%%CREATED%%', $ticket['dt'], $msg); $msg = str_replace('%%CREATED%%', $ticket['dt'], $msg);
$msg = str_replace('%%UPDATED%%', $ticket['lastchange'], $msg); $msg = str_replace('%%UPDATED%%', $ticket['lastchange'], $msg);
$msg = str_replace('%%ID%%', $ticket['id'], $msg); $msg = str_replace('%%ID%%', $ticket['id'], $msg);
$msg = str_replace('%%TIME_WORKED%%', $ticket['time_worked'] ,$msg);
$msg = str_replace('%%LAST_REPLY_BY%%',$ticket['last_reply_by'] ,$msg);
/* All custom fields */ /* All custom fields */
for ($i=1; $i<=50; $i++) { for ($i=1; $i<=50; $i++) {

@ -54,16 +54,12 @@ header('X-UA-Compatible: IE=edge');
<meta name="theme-color" content="<?php echo '#414a5c'; ?>"> <meta name="theme-color" content="<?php echo '#414a5c'; ?>">
<link href="<?php echo HESK_PATH; ?>hesk_style.css?v=<?php echo MODS_FOR_HESK_BUILD; ?>" type="text/css" rel="stylesheet"/> <link href="<?php echo HESK_PATH; ?>hesk_style.css?v=<?php echo MODS_FOR_HESK_BUILD; ?>" type="text/css" rel="stylesheet"/>
<link href="<?php echo HESK_PATH; ?>css/datepicker.css" type="text/css" rel="stylesheet"/> <link href="<?php echo HESK_PATH; ?>css/datepicker.css" type="text/css" rel="stylesheet"/>
<link href="<?php echo HESK_PATH; ?>css/bootstrap.css?v=<?php echo MODS_FOR_HESK_BUILD; ?>" type="text/css" <link href="<?php echo HESK_PATH; ?>css/bootstrap.css?v=<?php echo MODS_FOR_HESK_BUILD; ?>" type="text/css" rel="stylesheet"/>
rel="stylesheet"/>
<?php if ($modsForHesk_settings['use_bootstrap_theme'] != 0) { ?> <?php if ($modsForHesk_settings['use_bootstrap_theme'] != 0) { ?>
<link href="<?php echo HESK_PATH; ?>css/bootstrap-theme.css?v=<?php echo MODS_FOR_HESK_BUILD; ?>" type="text/css" <link href="<?php echo HESK_PATH; ?>css/bootstrap-theme.css?v=<?php echo MODS_FOR_HESK_BUILD; ?>" type="text/css" rel="stylesheet" />
rel="stylesheet" />
<?php } ?> <?php } ?>
<link href="<?php echo HESK_PATH; ?>css/mods-for-hesk.css?v=<?php echo MODS_FOR_HESK_BUILD; ?>" type="text/css" <link href="<?php echo HESK_PATH; ?>css/mods-for-hesk.css?v=<?php echo MODS_FOR_HESK_BUILD; ?>" type="text/css" rel="stylesheet"/>
rel="stylesheet"/> <link href="<?php echo HESK_PATH; ?>css/hesk_newStyle.css?v=<?php echo MODS_FOR_HESK_BUILD; ?>" type="text/css" rel="stylesheet"/>
<link href="<?php echo HESK_PATH; ?>css/hesk_newStyle.css?v=<?php echo MODS_FOR_HESK_BUILD; ?>" type="text/css"
rel="stylesheet"/>
<link href="<?php echo HESK_PATH; ?>css/bootstrap-iconpicker.min.css?v=<?php echo MODS_FOR_HESK_BUILD; ?>" rel="stylesheet"> <link href="<?php echo HESK_PATH; ?>css/bootstrap-iconpicker.min.css?v=<?php echo MODS_FOR_HESK_BUILD; ?>" rel="stylesheet">
<link href="//netdna.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css?v=<?php echo MODS_FOR_HESK_BUILD; ?>" rel="stylesheet"> <link href="//netdna.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css?v=<?php echo MODS_FOR_HESK_BUILD; ?>" rel="stylesheet">
<link rel="stylesheet" href="<?php echo HESK_PATH; ?>css/octicons.css?v=<?php echo MODS_FOR_HESK_BUILD; ?>" type="text/css"> <link rel="stylesheet" href="<?php echo HESK_PATH; ?>css/octicons.css?v=<?php echo MODS_FOR_HESK_BUILD; ?>" type="text/css">
@ -73,6 +69,7 @@ header('X-UA-Compatible: IE=edge');
<link rel="stylesheet" href="<?php echo HESK_PATH; ?>css/fullcalendar.min.css?v=<?php echo MODS_FOR_HESK_BUILD; ?>"> <link rel="stylesheet" href="<?php echo HESK_PATH; ?>css/fullcalendar.min.css?v=<?php echo MODS_FOR_HESK_BUILD; ?>">
<link rel="stylesheet" href="<?php echo HESK_PATH; ?>css/bootstrap-clockpicker.min.css?v=<?php echo MODS_FOR_HESK_BUILD; ?>"> <link rel="stylesheet" href="<?php echo HESK_PATH; ?>css/bootstrap-clockpicker.min.css?v=<?php echo MODS_FOR_HESK_BUILD; ?>">
<link rel="stylesheet" href="<?php echo HESK_PATH; ?>css/bootstrap-colorpicker.min.css?v=<?php echo MODS_FOR_HESK_BUILD; ?>"> <link rel="stylesheet" href="<?php echo HESK_PATH; ?>css/bootstrap-colorpicker.min.css?v=<?php echo MODS_FOR_HESK_BUILD; ?>">
<link rel="stylesheet" href="<?php echo HESK_PATH; ?>css/bootstrap-select.min.css?v=<?php echo MODS_FOR_HESK_BUILD; ?>">
<link rel="stylesheet" href="<?php echo HESK_PATH; ?>css/toastr.min.css?v=<?php echo MODS_FOR_HESK_BUILD; ?>"> <link rel="stylesheet" href="<?php echo HESK_PATH; ?>css/toastr.min.css?v=<?php echo MODS_FOR_HESK_BUILD; ?>">
<link rel="stylesheet" href="<?php echo HESK_PATH; ?>css/magnific-popup.css?v=<?php echo MODS_FOR_HESK_BUILD; ?>"> <link rel="stylesheet" href="<?php echo HESK_PATH; ?>css/magnific-popup.css?v=<?php echo MODS_FOR_HESK_BUILD; ?>">
<?php if (defined('USE_JQUERY_2')): ?> <?php if (defined('USE_JQUERY_2')): ?>
@ -83,10 +80,8 @@ header('X-UA-Compatible: IE=edge');
<script language="Javascript" type="text/javascript" src="<?php echo HESK_PATH; ?>hesk_javascript.js?v=<?php echo MODS_FOR_HESK_BUILD; ?>"></script> <script language="Javascript" type="text/javascript" src="<?php echo HESK_PATH; ?>hesk_javascript.js?v=<?php echo MODS_FOR_HESK_BUILD; ?>"></script>
<script language="Javascript" type="text/javascript" src="<?php echo HESK_PATH; ?>js/bootstrap.min.js?v=<?php echo MODS_FOR_HESK_BUILD; ?>"></script> <script language="Javascript" type="text/javascript" src="<?php echo HESK_PATH; ?>js/bootstrap.min.js?v=<?php echo MODS_FOR_HESK_BUILD; ?>"></script>
<script type="text/javascript" src="<?php echo HESK_PATH; ?>js/dropzone.min.js?v=<?php echo MODS_FOR_HESK_BUILD; ?>"></script> <script type="text/javascript" src="<?php echo HESK_PATH; ?>js/dropzone.min.js?v=<?php echo MODS_FOR_HESK_BUILD; ?>"></script>
<script language="Javascript" type="text/javascript" <script language="Javascript" type="text/javascript" src="<?php echo HESK_PATH; ?>js/modsForHesk-javascript.js?v=<?php echo MODS_FOR_HESK_BUILD; ?>"></script>
src="<?php echo HESK_PATH; ?>js/modsForHesk-javascript.js?v=<?php echo MODS_FOR_HESK_BUILD; ?>"></script> <script language="JavaScript" type="text/javascript" src="<?php echo HESK_PATH; ?>js/bootstrap-datepicker.js?v=<?php echo MODS_FOR_HESK_BUILD; ?>"></script>
<script language="JavaScript" type="text/javascript"
src="<?php echo HESK_PATH; ?>js/bootstrap-datepicker.js?v=<?php echo MODS_FOR_HESK_BUILD; ?>"></script>
<script type="text/javascript" src="<?php echo HESK_PATH; ?>js/bootstrap-clockpicker.min.js?v=<?php echo MODS_FOR_HESK_BUILD; ?>"></script> <script type="text/javascript" src="<?php echo HESK_PATH; ?>js/bootstrap-clockpicker.min.js?v=<?php echo MODS_FOR_HESK_BUILD; ?>"></script>
<script type="text/javascript" src="<?php echo HESK_PATH; ?>js/iconset-fontawesome-4.3.0.js?v=<?php echo MODS_FOR_HESK_BUILD; ?>"></script> <script type="text/javascript" src="<?php echo HESK_PATH; ?>js/iconset-fontawesome-4.3.0.js?v=<?php echo MODS_FOR_HESK_BUILD; ?>"></script>
<script type="text/javascript" src="<?php echo HESK_PATH; ?>js/iconset-octicon-2.1.2.js?v=<?php echo MODS_FOR_HESK_BUILD; ?>"></script> <script type="text/javascript" src="<?php echo HESK_PATH; ?>js/iconset-octicon-2.1.2.js?v=<?php echo MODS_FOR_HESK_BUILD; ?>"></script>
@ -95,6 +90,7 @@ header('X-UA-Compatible: IE=edge');
<script type="text/javascript" src="<?php echo HESK_PATH; ?>js/platform.js?v=<?php echo MODS_FOR_HESK_BUILD; ?>"></script> <script type="text/javascript" src="<?php echo HESK_PATH; ?>js/platform.js?v=<?php echo MODS_FOR_HESK_BUILD; ?>"></script>
<script type="text/javascript" src="<?php echo HESK_PATH; ?>js/bootstrap-validator.min.js?v=<?php echo MODS_FOR_HESK_BUILD; ?>"></script> <script type="text/javascript" src="<?php echo HESK_PATH; ?>js/bootstrap-validator.min.js?v=<?php echo MODS_FOR_HESK_BUILD; ?>"></script>
<script type="text/javascript" src="<?php echo HESK_PATH; ?>js/bootstrap-colorpicker.min.js?v=<?php echo MODS_FOR_HESK_BUILD; ?>"></script> <script type="text/javascript" src="<?php echo HESK_PATH; ?>js/bootstrap-colorpicker.min.js?v=<?php echo MODS_FOR_HESK_BUILD; ?>"></script>
<script type="text/javascript" src="<?php echo HESK_PATH; ?>js/bootstrap-select.js?v=<?php echo MODS_FOR_HESK_BUILD; ?>"></script>
<script type="text/javascript" src="<?php echo HESK_PATH; ?>js/toastr.min.js?v=<?php echo MODS_FOR_HESK_BUILD ?>"></script> <script type="text/javascript" src="<?php echo HESK_PATH; ?>js/toastr.min.js?v=<?php echo MODS_FOR_HESK_BUILD ?>"></script>
<script type="text/javascript" src="<?php echo HESK_PATH; ?>js/jquery.magnific-popup.min.js?v=<?php echo MODS_FOR_HESK_BUILD ?>"></script> <script type="text/javascript" src="<?php echo HESK_PATH; ?>js/jquery.magnific-popup.min.js?v=<?php echo MODS_FOR_HESK_BUILD ?>"></script>
<script type="text/javascript" src="<?php echo HESK_PATH; ?>internal-api/js/alerts.js?v=<?php echo MODS_FOR_HESK_BUILD; ?>"></script> <script type="text/javascript" src="<?php echo HESK_PATH; ?>internal-api/js/alerts.js?v=<?php echo MODS_FOR_HESK_BUILD; ?>"></script>

@ -347,7 +347,7 @@ function hesk_encodeUTF8($in, $encoding)
return utf8_encode($in); return utf8_encode($in);
break; break;
default: default:
return iconv($encoding, 'UTF-8', $in); return function_exists('iconv') ? iconv($encoding, 'UTF-8', $in) : utf8_encode($in);
break; break;
} }
} // END hesk_encodeUTF8() } // END hesk_encodeUTF8()

@ -129,7 +129,7 @@ function hesk_newTicket($ticket, $isVerified = true)
'trackid' => $ticket['trackid'], 'trackid' => $ticket['trackid'],
'status' => $ticket['status'], 'status' => $ticket['status'],
'name' => $ticket['name'], 'name' => $ticket['name'],
'lastreplier' => $ticket['name'], 'last_reply_by' => $ticket['name'],
'subject' => $ticket['subject'], 'subject' => $ticket['subject'],
'message' => $ticket['message'], 'message' => $ticket['message'],
'attachments' => $ticket['attachments'], 'attachments' => $ticket['attachments'],
@ -138,7 +138,8 @@ function hesk_newTicket($ticket, $isVerified = true)
'id' => hesk_dbInsertID(), 'id' => hesk_dbInsertID(),
'language' => $language, 'language' => $language,
'html' => $ticket['html'], 'html' => $ticket['html'],
'due_date' => $ticket['due_date'] 'due_date' => $ticket['due_date'],
'time_worked' => '00:00:00',
); );
// Add custom fields to the array // Add custom fields to the array

@ -340,7 +340,7 @@ function print_add_ticket()
class="important">*</span></label> class="important">*</span></label>
<div class="col-sm-9"> <div class="col-sm-9">
<input type="text" class="form-control" id="name" name="name" size="40" maxlength="30" <input type="text" class="form-control" id="name" name="name" size="40" maxlength="50"
value="<?php if (isset($_SESSION['c_name'])) { value="<?php if (isset($_SESSION['c_name'])) {
echo stripslashes(hesk_input($_SESSION['c_name'])); echo stripslashes(hesk_input($_SESSION['c_name']));
} ?>" <?php if (in_array('name', $_SESSION['iserror'])) { } ?>" <?php if (in_array('name', $_SESSION['iserror'])) {
@ -711,7 +711,7 @@ function print_add_ticket()
<div class="col-sm-9"> <div class="col-sm-9">
<input type="text" id="subject" class="form-control" name="subject" size="40" <input type="text" id="subject" class="form-control" name="subject" size="40"
maxlength="40" maxlength="70"
value="<?php if (isset($_SESSION['c_subject'])) { value="<?php if (isset($_SESSION['c_subject'])) {
echo stripslashes(hesk_input($_SESSION['c_subject'])); echo stripslashes(hesk_input($_SESSION['c_subject']));
} ?>" <?php if (in_array('subject', $_SESSION['iserror'])) { } ?>" <?php if (in_array('subject', $_SESSION['iserror'])) {

@ -15,8 +15,8 @@
if (!defined('IN_SCRIPT')) {die('Invalid attempt');} if (!defined('IN_SCRIPT')) {die('Invalid attempt');}
// We will be installing this HESK version: // We will be installing this HESK version:
define('HESK_NEW_VERSION','2.7.3'); define('HESK_NEW_VERSION','2.7.5');
define('MODS_FOR_HESK_NEW_VERSION','3.2.0'); define('MODS_FOR_HESK_NEW_VERSION','3.2.4');
define('REQUIRE_PHP_VERSION','5.3.0'); define('REQUIRE_PHP_VERSION','5.3.0');
define('REQUIRE_MYSQL_VERSION','5.0.7'); define('REQUIRE_MYSQL_VERSION','5.0.7');

@ -213,5 +213,10 @@ function getAllMigrations() {
157 => new \v320\AddAuditTrail\CreateAuditTrailToReplacementValuesTable(), 157 => new \v320\AddAuditTrail\CreateAuditTrailToReplacementValuesTable(),
158 => new \v320\AddMigrationSetting(), 158 => new \v320\AddMigrationSetting(),
159 => new UpdateMigration('3.2.0', '3.1.1', 159), 159 => new UpdateMigration('3.2.0', '3.1.1', 159),
//3.2.1 - 3.2.3
160 => new UpdateMigration('3.2.1', '3.2.0', 160),
161 => new UpdateMigration('3.2.2', '3.2.1', 161),
162 => new UpdateMigration('3.2.3', '3.2.2', 162),
163 => new UpdateMigration('3.2.4', '3.2.3', 163),
); );
} }

@ -97,7 +97,7 @@ function hesk_dbEscape($in)
function hesk_dbLike($in) function hesk_dbLike($in)
{ {
return str_replace( array('_', '%'), array('\\\\_', '\\\\%'), $in); return str_replace( array('_', '%', '\\'), array('\\\\_', '\\\\%', '\\\\'), $in); // '
} // END hesk_dbLike() } // END hesk_dbLike()

@ -97,7 +97,7 @@ function hesk_dbEscape($in)
function hesk_dbLike($in) function hesk_dbLike($in)
{ {
return str_replace( array('_', '%'), array('\\\\_', '\\\\%'), $in); return str_replace( array('_', '%', '\\'), array('\\\\_', '\\\\%', '\\\\'), $in); // '
} // END hesk_dbLike() } // END hesk_dbLike()

@ -286,8 +286,8 @@ if (!$show['show']) {
if ($hesk_settings['kb_rating'] && strpos(hesk_COOKIE('hesk_kb_rate'), 'a' . $artid . '%') === false) { if ($hesk_settings['kb_rating'] && strpos(hesk_COOKIE('hesk_kb_rate'), 'a' . $artid . '%') === false) {
echo ' echo '
<div id="rating" class="rate" align="right">&nbsp;<br />' . $hesklang['rart'] . ' <div id="rating" class="rate" align="right">&nbsp;<br />' . $hesklang['rart'] . '
<a href="Javascript:void(0)" onclick="Javascript:window.location=\'knowledgebase.php?rating=5&amp;id=' . $article['id'] . '\'" rel="nofollow">' . strtolower($hesklang['yes']) . '</a> / <a href="Javascript:void(0)" onclick="Javascript:window.location=\'knowledgebase.php?rating=5&amp;id=' . $article['id'] . '\'" rel="nofollow">' . hesk_mb_strtolower($hesklang['yes']) . '</a> /
<a href="Javascript:void(0)" onclick="Javascript:window.location=\'knowledgebase.php?rating=1&amp;id=' . $article['id'] . '\'" rel="nofollow">' . strtolower($hesklang['no']) . '</a> <a href="Javascript:void(0)" onclick="Javascript:window.location=\'knowledgebase.php?rating=1&amp;id=' . $article['id'] . '\'" rel="nofollow">' . hesk_mb_strtolower($hesklang['no']) . '</a>
</div> </div>
'; ';
} }

@ -1,6 +1,6 @@
<p>Hello,</p> <p>Hello,</p>
<p>A customer has just replied to ticket "%%SUBJECT%%".</p> <p>A customer has just replied to ticket "%%SUBJECT%%".</p>
<p>You can manage this ticket here: <p>You can read the reply message and manage this ticket here:
%%TRACK_URL%%</p> %%TRACK_URL%%</p>
<p>Regards,</p> <p>Regards,</p>
%%SITE_TITLE%% <br> %%SITE_TITLE%% <br>

@ -1,8 +1,9 @@
<p>Dear %%NAME%%,</p> <p>Dear %%NAME%%,</p>
<p>Our staff has just replied to your ticket "%%SUBJECT%%".</p> <p>We have just replied to your ticket "%%SUBJECT%%".</p>
<p>You can view the ticket here:</p> <p>To read the message, submit a reply and view details, please visit:</p>
%%TRACK_URL%% %%TRACK_URL%%
<br><br> <br><br>
<p>If the above link is not clickable, try copying and pasting it into the address bar of your web browser.</p>
<p>Sincerely,</p> <p>Sincerely,</p>
%%SITE_TITLE%% %%SITE_TITLE%%
<br> <br>

@ -1,8 +1,8 @@
<p>Dear %%NAME%%,</p> <p>Dear %%NAME%%,</p>
<p>Your support ticket "%%SUBJECT%%" has been updated to a closed/resolved status.</p> <p>Your support ticket "%%SUBJECT%%" has been updated to a closed/resolved status.</p>
<p>Ticket tracking ID: %%TRACK_ID%%</p>
<p>You can view the status of your ticket here: <p>You can view the status of your ticket here:
%%TRACK_URL%%</p> %%TRACK_URL%%</p>
<p>If the above link is not clickable, try copying and pasting it into the address bar of your web browser.</p>
<p>Sincerely,</p> <p>Sincerely,</p>
%%SITE_TITLE%% <br> %%SITE_TITLE%% <br>
%%SITE_URL%% %%SITE_URL%%

@ -2,11 +2,10 @@ Dear %%NAME%%,
Your support ticket "%%SUBJECT%%" has been updated to a closed/resolved status. 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: You can view the status of your ticket here:
%%TRACK_URL%% %%TRACK_URL%%
If the above link is not clickable, try copying and pasting it into the address bar of your web browser.
Sincerely, Sincerely,

@ -1239,7 +1239,7 @@ $hesklang['cat_pri_ch']='Category priority has been set to:';
$hesklang['err_dbversion']='Too old MySQL version:'; // %s will be replaced with MySQL version $hesklang['err_dbversion']='Too old MySQL version:'; // %s will be replaced with MySQL version
$hesklang['signature_max']='Signature (max 1000 chars)'; $hesklang['signature_max']='Signature (max 1000 chars)';
$hesklang['signature_long']='User signature is too long! Please limit the signature to 1000 chars'; $hesklang['signature_long']='User signature is too long! Please limit the signature to 1000 chars';
$hesklang['ip_whois']='IP whois'; $hesklang['ip_whois']='IP WHOIS';
$hesklang['ednote']='Edit note message'; $hesklang['ednote']='Edit note message';
$hesklang['ednote2']='Note message saved'; $hesklang['ednote2']='Note message saved';
$hesklang['perm_deny']='Permission denied'; $hesklang['perm_deny']='Permission denied';
@ -1284,7 +1284,6 @@ $hesklang['click_unban']='Click here to unban.';
$hesklang['banip_intro']='Visitors from banned IP addresses will not be able to view or submit tickets and login into the help desk.'; $hesklang['banip_intro']='Visitors from banned IP addresses will not be able to view or submit tickets and login into the help desk.';
$hesklang['ipperm']='Permanent IP bans:'; $hesklang['ipperm']='Permanent IP bans:';
$hesklang['iptemp']='Login failure bans:'; $hesklang['iptemp']='Login failure bans:';
$hesklang['savebanip']='Ban this IP';
$hesklang['no_banips']='<i>No IPs are being banned.</i>'; $hesklang['no_banips']='<i>No IPs are being banned.</i>';
$hesklang['bananip']='IP address to ban'; $hesklang['bananip']='IP address to ban';
$hesklang['banex']='Examples:'; $hesklang['banex']='Examples:';
@ -2192,7 +2191,7 @@ $hesklang['changing_permissions_will_reset_permission_group'] = 'Changing a user
// --> Ticket audit trail // --> Ticket audit trail
$hesklang['audit_moved_category']='%s moved ticket to category %s'; // %s = new category, user making change, thist1 $hesklang['audit_moved_category']='%s moved ticket to category %s'; // %s = new category, user making change, thist1
$hesklang['audit_assigned']='%s assigned ticket to %s'; // %s = assigned user, user making change $hesklang['audit_assigned']='%s assigned ticket to %s'; // %s = assigned user, user making change
$hesklang['audit_assigned_self'] = '%s assigned ticket to themself'; $hesklang['audit_assigned_self'] = '%s self-assigned ticket';
$hesklang['audit_unassigned'] = '%s unassigned ticket'; $hesklang['audit_unassigned'] = '%s unassigned ticket';
$hesklang['audit_closed']='%s closed ticket'; // thist3 $hesklang['audit_closed']='%s closed ticket'; // thist3
$hesklang['audit_automatically_closed'] ='Ticket automatically closed'; $hesklang['audit_automatically_closed'] ='Ticket automatically closed';

@ -206,13 +206,14 @@ $info = array(
'trackid' => $ticket['trackid'], 'trackid' => $ticket['trackid'],
'status' => $ticket['status'], 'status' => $ticket['status'],
'name' => $ticket['name'], 'name' => $ticket['name'],
'lastreplier' => $ticket['name'],
'subject' => $ticket['subject'], 'subject' => $ticket['subject'],
'message' => stripslashes($message), 'message' => stripslashes($message),
'attachments' => $myattachments, 'attachments' => $myattachments,
'dt' => hesk_date($ticket['dt'], true), 'dt' => hesk_date($ticket['dt'], true),
'lastchange' => hesk_date($ticket['lastchange'], true), 'lastchange' => hesk_date($ticket['lastchange'], true),
'id' => $ticket['id'], 'id' => $ticket['id'],
'time_worked' => $ticket['time_worked'],
'last_reply_by' => $ticket['name'],
); );
// 2. Add custom fields to the array // 2. Add custom fields to the array

@ -73,7 +73,7 @@ if ($hesk_settings['question_use']) {
if (strlen($question) == 0) { if (strlen($question) == 0) {
$hesk_error_buffer['question'] = $hesklang['q_miss']; $hesk_error_buffer['question'] = $hesklang['q_miss'];
} elseif (strtolower($question) != strtolower($hesk_settings['question_ans'])) { } elseif (hesk_mb_strtolower($question) != hesk_mb_strtolower($hesk_settings['question_ans'])) {
$hesk_error_buffer['question'] = $hesklang['q_wrng']; $hesk_error_buffer['question'] = $hesklang['q_wrng'];
} else { } else {
$_SESSION['c_question'] = $question; $_SESSION['c_question'] = $question;

@ -722,8 +722,8 @@ function hesk_printCustomerTicketReplies()
echo ' echo '
<div id="rating' . $reply['id'] . '" class="rate"> <div id="rating' . $reply['id'] . '" class="rate">
' . $hesklang['r'] . ' ' . $hesklang['r'] . '
<a href="Javascript:void(0)" onclick="Javascript:hesk_rate(\'rate.php?rating=5&amp;id=' . $reply['id'] . '&amp;track=' . $trackingID . '\',\'rating' . $reply['id'] . '\')">' . strtolower($hesklang['yes']) . '</a> / <a href="Javascript:void(0)" onclick="Javascript:hesk_rate(\'rate.php?rating=5&amp;id=' . $reply['id'] . '&amp;track=' . $trackingID . '\',\'rating' . $reply['id'] . '\')">' . hesk_mb_strtolower($hesklang['yes']) . '</a> /
<a href="Javascript:void(0)" onclick="Javascript:hesk_rate(\'rate.php?rating=1&amp;id=' . $reply['id'] . '&amp;track=' . $trackingID . '\',\'rating' . $reply['id'] . '\')">' . strtolower($hesklang['no']) . '</a> <a href="Javascript:void(0)" onclick="Javascript:hesk_rate(\'rate.php?rating=1&amp;id=' . $reply['id'] . '&amp;track=' . $trackingID . '\',\'rating' . $reply['id'] . '\')">' . hesk_mb_strtolower($hesklang['no']) . '</a>
</div> </div>
'; ';
} }

Loading…
Cancel
Save