diff --git a/admin/admin_reply_ticket.php b/admin/admin_reply_ticket.php
index 2b85c6cc..d7d3c4df 100644
--- a/admin/admin_reply_ticket.php
+++ b/admin/admin_reply_ticket.php
@@ -288,6 +288,12 @@ elseif ($submit_as_customer)
$customerReplyStatusRs = hesk_dbQuery('SELECT `ID` FROM `'.hesk_dbEscape($hesk_settings['db_pfix']).'statuses` WHERE `IsCustomerReplyStatus` = 1 LIMIT 1');
$customerReplyStatus = hesk_dbFetchAssoc($customerReplyStatusRs);
$new_status = $customerReplyStatus['ID'];
+
+ if ($ticket['status'] != $new_status)
+ {
+ $revision = sprintf($hesklang['thist9'],hesk_date(),$hesklang['wait_reply'],$_SESSION['name'].' ('.$_SESSION['user'].')');
+ $sql_status = " , `history`=CONCAT(`history`,'".hesk_dbEscape($revision)."') ";
+ }
}
// -> Default: submit as "Replied by staff"
else
diff --git a/admin/admin_ticket.php b/admin/admin_ticket.php
index 3b5cfc32..0dbcdf8a 100644
--- a/admin/admin_ticket.php
+++ b/admin/admin_ticket.php
@@ -2110,8 +2110,12 @@ function hesk_printCanned()
return true;
}
+ myMsg = myMsg.replace(/%%HESK_ID%%/g, '');
+ myMsg = myMsg.replace(/%%HESK_TRACKID%%/g, '');
+ myMsg = myMsg.replace(/%%HESK_TRACK_ID%%/g, '');
myMsg = myMsg.replace(/%%HESK_NAME%%/g, '');
myMsg = myMsg.replace(/%%HESK_EMAIL%%/g, '');
+ myMsg = myMsg.replace(/%%HESK_OWNER%%/g, '');
myMsg = myMsg.replace(/%%HESK_custom1%%/g, '');
myMsg = myMsg.replace(/%%HESK_custom2%%/g, '');
myMsg = myMsg.replace(/%%HESK_custom3%%/g, '');
diff --git a/admin/index.php b/admin/index.php
index 2ddf4be4..14d037e8 100644
--- a/admin/index.php
+++ b/admin/index.php
@@ -217,6 +217,10 @@ function do_login()
hesk_process_messages($hesklang['chdp'],'NOREDIRECT','NOTICE');
}
+ // Set a tag that will be used to expire sessions after username or password change
+ $_SESSION['session_verify'] = hesk_activeSessionCreateTag($user, $_SESSION['pass']);
+
+ // We don't need the password hash anymore
unset($_SESSION['pass']);
diff --git a/admin/mail.php b/admin/mail.php
index e4d2547c..13821625 100644
--- a/admin/mail.php
+++ b/admin/mail.php
@@ -328,6 +328,12 @@ function mail_send()
/* Message */
$_SESSION['mail']['message'] = hesk_input( hesk_POST('message') ) or $hesk_error_buffer .= '
diff --git a/admin/manage_canned.php b/admin/manage_canned.php
index 19c9d75f..efa0a885 100644
--- a/admin/manage_canned.php
+++ b/admin/manage_canned.php
@@ -278,8 +278,11 @@ myField.value += myValue;
}
?>
:
+
|
+
|
|
-
+
|
+
$v)
{
diff --git a/admin/profile.php b/admin/profile.php
index 6c4982ab..a6c7a83b 100644
--- a/admin/profile.php
+++ b/admin/profile.php
@@ -239,12 +239,12 @@ function update_profile() {
}
else
{
- $v = hesk_Pass2Hash($newpass);
- if ($v == '499d74967b28a841c98bb4baaabaad699ff3c079')
+ $newpass_hash = hesk_Pass2Hash($newpass);
+ if ($newpass_hash == '499d74967b28a841c98bb4baaabaad699ff3c079')
{
define('WARN_PASSWORD',true);
}
- $sql_pass = ',`pass`=\''.$v.'\'';
+ $sql_pass = ',`pass`=\''.$newpass_hash.'\'';
}
}
}
@@ -314,6 +314,21 @@ function update_profile() {
/* Process the session variables */
$_SESSION['new'] = hesk_stripArray($_SESSION['new']);
+ // Do we need a new session_verify tag?
+ if ( strlen($sql_username) && strlen($sql_pass) )
+ {
+ $_SESSION['session_verify'] = hesk_activeSessionCreateTag($_SESSION['new']['user'], $newpass_hash);
+ }
+ elseif ( strlen($sql_pass) )
+ {
+ $_SESSION['session_verify'] = hesk_activeSessionCreateTag($_SESSION['user'], $newpass_hash);
+ }
+ elseif ( strlen($sql_username) )
+ {
+ $res = hesk_dbQuery('SELECT `pass` FROM `'.hesk_dbEscape($hesk_settings['db_pfix'])."users` WHERE `id` = '".intval($_SESSION['id'])."' LIMIT 1");
+ $_SESSION['session_verify'] = hesk_activeSessionCreateTag($_SESSION['new']['user'], hesk_dbResult($res) );
+ }
+
/* Update session variables */
foreach ($_SESSION['new'] as $k => $v)
{
diff --git a/change_status.php b/change_status.php
index 62181c4f..7ffa6315 100644
--- a/change_status.php
+++ b/change_status.php
@@ -53,12 +53,18 @@ $trackingID = hesk_cleanID() or die("$hesklang[int_error]: $hesklang[no_trackID]
// Get new status
$status = intval( hesk_GET('s', 0) );
+$oldStatus = $status;
$locked = 0;
// Connect to database
hesk_dbConnect();
+// Get the close status. It'll be used later on
+$statusRes = hesk_dbQuery('SELECT `ID` FROM `'.hesk_dbEscape($hesk_settings['db_pfix']).'statuses` WHERE `IsClosedByClient` = 1');
+$statusRow = hesk_dbFetchAssoc($statusRes);
+$closedStatus = $statusRow['ID'];
+
if ($status == 3) // Closed
{
// Is customer closing tickets enabled?
@@ -66,11 +72,7 @@ if ($status == 3) // Closed
{
hesk_error($hesklang['attempt']);
}
-
- //-- They want to close the ticket, so get the status that is the default for client-side closes
- $statusRow = hesk_dbFetchAssoc(hesk_dbQuery('SELECT `ID` FROM `'.hesk_dbEscape($hesk_settings['db_pfix']).'statuses` WHERE `IsClosedByClient` = 1'));
-
- $status = $statusRow['ID'];
+ $status = $closedStatus;
$action = $hesklang['closed'];
$revision = sprintf($hesklang['thist3'],hesk_date(),$hesklang['customer']);
@@ -90,6 +92,11 @@ elseif ($status == 2) // Opened
hesk_error($hesklang['attempt']);
}
+ //-- They want to close the ticket, so get the status that is the default for client-side closes
+ $statusRes = hesk_dbQuery('SELECT `ID` FROM `'.hesk_dbEscape($hesk_settings['db_pfix']).'statuses` WHERE `IsDefaultStaffReplyStatus` = 1');
+ $statusRow = hesk_dbFetchAssoc($statusRes);
+ $status = $statusRow['ID'];
+
$action = $hesklang['opened'];
$revision = sprintf($hesklang['thist4'],hesk_date(),$hesklang['customer']);
@@ -110,6 +117,30 @@ hesk_dbConnect();
// Verify email address match if needed
hesk_verifyEmailMatch($trackingID);
+// Lets make status assignment a bit smarter when reopening tickets
+if ($oldStatus == 2)
+{
+ // Get number of replies and last replier (customer or staff)
+ $ticket = hesk_dbFetchAssoc( hesk_dbQuery( "SELECT `staffreplies`, `lastreplier` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` WHERE `trackid`='".hesk_dbEscape($trackingID)."' LIMIT 1") );
+
+ // If ticket has no staff replies set the status to "New"
+ if ($ticket['staffreplies'] < 1)
+ {
+ $statusRes = hesk_dbQuery('SELECT `ID` FROM `'.hesk_dbEscape($hesk_settings['db_pfix']).'statuses` WHERE `IsNewTicketStatus` = 1');
+ $statusRow = hesk_dbFetchAssoc($statusRes);
+ $status = $statusRow['ID'];
+ }
+ // If last reply was by customer set status to "Waiting reply from staff"
+ elseif ($ticket['lastreplier'] == 0)
+ {
+ $statusRes = hesk_dbQuery('SELECT `ID` FROM `'.hesk_dbEscape($hesk_settings['db_pfix']).'statuses` WHERE `IsCustomerReplyStatus` = 1');
+ $statusRow = hesk_dbFetchAssoc($statusRes);
+ $status = $statusRow['ID'];
+ }
+ // If nothing matches: last reply was from staff, keep status "Waiting reply from customer"
+}
+
+
// Modify values in the database
hesk_dbQuery("UPDATE `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` SET `status`='{$status}', `locked`='{$locked}' $closedby_sql , `history`=CONCAT(`history`,'".hesk_dbEscape($revision)."') WHERE `trackid`='".hesk_dbEscape($trackingID)."' AND `locked` != '1' LIMIT 1");
@@ -120,7 +151,7 @@ if (hesk_dbAffectedRows() != 1)
}
// Show success message
-if ($status == 2)
+if ($status != $closedStatus)
{
hesk_process_messages($hesklang['wrepo'],'ticket.php?track='.$trackingID.$hesk_settings['e_param'].'&Refresh='.rand(10000,99999),'NOTICE');
}
diff --git a/inc/admin_functions.inc.php b/inc/admin_functions.inc.php
index 6ba71df4..d34662f8 100644
--- a/inc/admin_functions.inc.php
+++ b/inc/admin_functions.inc.php
@@ -368,6 +368,34 @@ function hesk_getHTML($in)
} // END hesk_getHTML()
+function hesk_activeSessionValidate($username, $password_hash, $tag)
+{
+ // Salt and hash need to be separated by a |
+ if ( ! strpos($tag, '|') )
+ {
+ return false;
+ }
+
+ // Get two parts of the tag
+ list($salt, $hash) = explode('|', $tag, 2);
+
+ // Make sure the hash matches existing username and password
+ if ($hash == sha1($salt . $username . $password_hash) )
+ {
+ return true;
+ }
+
+ return false;
+} // hesk_activeSessionValidate
+
+
+function hesk_activeSessionCreateTag($username, $password_hash)
+{
+ $salt = uniqid(mt_rand(), true);
+ return $salt . '|' . sha1($salt . $username . $password_hash);
+} // END hesk_activeSessionCreateTag()
+
+
function hesk_autoLogin($noredirect=0)
{
global $hesk_settings, $hesklang, $hesk_db_link;
@@ -422,6 +450,10 @@ function hesk_autoLogin($noredirect=0)
hesk_process_messages($hesklang['chdp'],'NOREDIRECT','NOTICE');
}
+ // Set a tag that will be used to expire sessions after username or password change
+ $_SESSION['session_verify'] = hesk_activeSessionCreateTag($user, $_SESSION['pass']);
+
+ // We don't need the password hash anymore
unset($_SESSION['pass']);
/* Login successful, clean brute force attempts */
@@ -494,7 +526,7 @@ function hesk_isLoggedIn()
$referer = hesk_input($_SERVER['REQUEST_URI']);
$referer = str_replace('&','&',$referer);
- if (empty($_SESSION['id']))
+ if ( empty($_SESSION['id']) || empty($_SESSION['session_verify']) )
{
if ($hesk_settings['autologin'] && hesk_autoLogin(1) )
{
@@ -508,6 +540,7 @@ function hesk_isLoggedIn()
return true;
}
+ hesk_session_stop();
$url = 'index.php?a=login¬ice=1&goto='.urlencode($referer);
header('Location: '.$url);
exit();
@@ -516,32 +549,41 @@ function hesk_isLoggedIn()
{
hesk_session_regenerate_id();
- // Need to update permissions?
- if ( empty($_SESSION['isadmin']) )
+ // Let's make sure access data is up-to-date
+ $res = hesk_dbQuery( "SELECT `user`, `pass`, `isadmin`, `categories`, `heskprivileges` FROM `".$hesk_settings['db_pfix']."users` WHERE `id` = '".intval($_SESSION['id'])."' LIMIT 1" );
+
+ // Exit if user not found
+ if (hesk_dbNumRows($res) != 1)
{
- $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;
- }
+ hesk_session_stop();
+ $url = 'index.php?a=login¬ice=1&goto='.urlencode($referer);
+ header('Location: '.$url);
+ exit();
+ }
- // 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();
- }
- }
+ // Fetch results from database
+ $me = hesk_dbFetchAssoc($res);
+
+ // Verify this session is still valid
+ if ( ! hesk_activeSessionValidate($me['user'], $me['pass'], $_SESSION['session_verify']) )
+ {
+ hesk_session_stop();
+ $url = 'index.php?a=login¬ice=1&goto='.urlencode($referer);
+ header('Location: '.$url);
+ exit();
+ }
+
+ // Update session variables as needed
+ if ($me['isadmin'] == 1)
+ {
+ $_SESSION['isadmin'] = 1;
+ }
+ else
+ {
+ $_SESSION['isadmin'] = 0;
+ $_SESSION['categories'] = explode(',', $me['categories']);
+ $_SESSION['heskprivileges'] = $me['heskprivileges'];
+ }
// Users online
if ($hesk_settings['online'])
diff --git a/inc/common.inc.php b/inc/common.inc.php
index 0ecbccd5..ad846a09 100644
--- a/inc/common.inc.php
+++ b/inc/common.inc.php
@@ -1259,7 +1259,7 @@ function hesk_makeURL($text, $class = '', $shortenLinks = true)
// matches a xxxx://aaaaa.bbb.cccc. ...
$text = preg_replace_callback(
- '#(^|[\n\t (>.])([a-z][a-z\d+]*:/{2}(?:(?:[a-z0-9\-._~!$&\'(*+,;=:@|]+|%[\dA-F]{2})+|[0-9.]+|\[[a-z0-9.]+:[a-z0-9.]+:[a-z0-9.:]+\])(?::\d*)?(?:/(?:[a-z0-9\-._~!$&\'(*+,;=:@|]+|%[\dA-F]{2})*)*(?:\?(?:[a-z0-9\-._~!$&\'(*+,;=:@/?|]+|%[\dA-F]{2})*)?(?:\#(?:[a-z0-9\-._~!$&\'(*+,;=:@/?|]+|%[\dA-F]{2})*)?)#i',
+ '#(^|[\n\t (>.])(' . "[a-z][a-z\d+]*:/{2}(?:(?:[^\p{C}\p{Z}\p{S}\p{P}\p{Nl}\p{No}\p{Me}\x{1100}-\x{115F}\x{A960}-\x{A97C}\x{1160}-\x{11A7}\x{D7B0}-\x{D7C6}\x{20D0}-\x{20FF}\x{1D100}-\x{1D1FF}\x{1D200}-\x{1D24F}\x{0640}\x{07FA}\x{302E}\x{302F}\x{3031}-\x{3035}\x{303B}]*[\x{00B7}\x{0375}\x{05F3}\x{05F4}\x{30FB}\x{002D}\x{06FD}\x{06FE}\x{0F0B}\x{3007}\x{00DF}\x{03C2}\x{200C}\x{200D}\pL0-9\-._~!$&'(*+,;=:@|]+|%[\dA-F]{2})+|[0-9.]+|\[[a-z0-9.]+:[a-z0-9.]+:[a-z0-9.:]+\])(?::\d*)?(?:/(?:[^\p{C}\p{Z}\p{S}\p{P}\p{Nl}\p{No}\p{Me}\x{1100}-\x{115F}\x{A960}-\x{A97C}\x{1160}-\x{11A7}\x{D7B0}-\x{D7C6}\x{20D0}-\x{20FF}\x{1D100}-\x{1D1FF}\x{1D200}-\x{1D24F}\x{0640}\x{07FA}\x{302E}\x{302F}\x{3031}-\x{3035}\x{303B}]*[\x{00B7}\x{0375}\x{05F3}\x{05F4}\x{30FB}\x{002D}\x{06FD}\x{06FE}\x{0F0B}\x{3007}\x{00DF}\x{03C2}\x{200C}\x{200D}\pL0-9\-._~!$&'(*+,;=:@|]+|%[\dA-F]{2})*)*(?:\?(?:[^\p{C}\p{Z}\p{S}\p{P}\p{Nl}\p{No}\p{Me}\x{1100}-\x{115F}\x{A960}-\x{A97C}\x{1160}-\x{11A7}\x{D7B0}-\x{D7C6}\x{20D0}-\x{20FF}\x{1D100}-\x{1D1FF}\x{1D200}-\x{1D24F}\x{0640}\x{07FA}\x{302E}\x{302F}\x{3031}-\x{3035}\x{303B}]*[\x{00B7}\x{0375}\x{05F3}\x{05F4}\x{30FB}\x{002D}\x{06FD}\x{06FE}\x{0F0B}\x{3007}\x{00DF}\x{03C2}\x{200C}\x{200D}\pL0-9\-._~!$&'(*+,;=:@/?|]+|%[\dA-F]{2})*)?(?:\#(?:[^\p{C}\p{Z}\p{S}\p{P}\p{Nl}\p{No}\p{Me}\x{1100}-\x{115F}\x{A960}-\x{A97C}\x{1160}-\x{11A7}\x{D7B0}-\x{D7C6}\x{20D0}-\x{20FF}\x{1D100}-\x{1D1FF}\x{1D200}-\x{1D24F}\x{0640}\x{07FA}\x{302E}\x{302F}\x{3031}-\x{3035}\x{303B}]*[\x{00B7}\x{0375}\x{05F3}\x{05F4}\x{30FB}\x{002D}\x{06FD}\x{06FE}\x{0F0B}\x{3007}\x{00DF}\x{03C2}\x{200C}\x{200D}\pL0-9\-._~!$&'(*+,;=:@/?|]+|%[\dA-F]{2})*)?" . ')#iu',
create_function(
"\$matches",
"return make_clickable_callback(MAGIC_URL_FULL, \$matches[1], \$matches[2], '', '$class', '$shortenLinks');"
@@ -1269,7 +1269,7 @@ function hesk_makeURL($text, $class = '', $shortenLinks = true)
// matches a "www.xxxx.yyyy[/zzzz]" kinda lazy URL thing
$text = preg_replace_callback(
- '#(^|[\n\t (>.])(www\.(?:[a-z0-9\-._~!$&\'(*+,;=:@|]+|%[\dA-F]{2})+(?::\d*)?(?:/(?:[a-z0-9\-._~!$&\'(*+,;=:@|]+|%[\dA-F]{2})*)*(?:\?(?:[a-z0-9\-._~!$&\'(*+,;=:@/?|]+|%[\dA-F]{2})*)?(?:\#(?:[a-z0-9\-._~!$&\'(*+,;=:@/?|]+|%[\dA-F]{2})*)?)#i',
+ '#(^|[\n\t (>])(' . "www\.(?:[^\p{C}\p{Z}\p{S}\p{P}\p{Nl}\p{No}\p{Me}\x{1100}-\x{115F}\x{A960}-\x{A97C}\x{1160}-\x{11A7}\x{D7B0}-\x{D7C6}\x{20D0}-\x{20FF}\x{1D100}-\x{1D1FF}\x{1D200}-\x{1D24F}\x{0640}\x{07FA}\x{302E}\x{302F}\x{3031}-\x{3035}\x{303B}]*[\x{00B7}\x{0375}\x{05F3}\x{05F4}\x{30FB}\x{002D}\x{06FD}\x{06FE}\x{0F0B}\x{3007}\x{00DF}\x{03C2}\x{200C}\x{200D}\pL0-9\-._~!$&'(*+,;=:@|]+|%[\dA-F]{2})+(?::\d*)?(?:/(?:[^\p{C}\p{Z}\p{S}\p{P}\p{Nl}\p{No}\p{Me}\x{1100}-\x{115F}\x{A960}-\x{A97C}\x{1160}-\x{11A7}\x{D7B0}-\x{D7C6}\x{20D0}-\x{20FF}\x{1D100}-\x{1D1FF}\x{1D200}-\x{1D24F}\x{0640}\x{07FA}\x{302E}\x{302F}\x{3031}-\x{3035}\x{303B}]*[\x{00B7}\x{0375}\x{05F3}\x{05F4}\x{30FB}\x{002D}\x{06FD}\x{06FE}\x{0F0B}\x{3007}\x{00DF}\x{03C2}\x{200C}\x{200D}\pL0-9\-._~!$&'(*+,;=:@|]+|%[\dA-F]{2})*)*(?:\?(?:[^\p{C}\p{Z}\p{S}\p{P}\p{Nl}\p{No}\p{Me}\x{1100}-\x{115F}\x{A960}-\x{A97C}\x{1160}-\x{11A7}\x{D7B0}-\x{D7C6}\x{20D0}-\x{20FF}\x{1D100}-\x{1D1FF}\x{1D200}-\x{1D24F}\x{0640}\x{07FA}\x{302E}\x{302F}\x{3031}-\x{3035}\x{303B}]*[\x{00B7}\x{0375}\x{05F3}\x{05F4}\x{30FB}\x{002D}\x{06FD}\x{06FE}\x{0F0B}\x{3007}\x{00DF}\x{03C2}\x{200C}\x{200D}\pL0-9\-._~!$&'(*+,;=:@/?|]+|%[\dA-F]{2})*)?(?:\#(?:[^\p{C}\p{Z}\p{S}\p{P}\p{Nl}\p{No}\p{Me}\x{1100}-\x{115F}\x{A960}-\x{A97C}\x{1160}-\x{11A7}\x{D7B0}-\x{D7C6}\x{20D0}-\x{20FF}\x{1D100}-\x{1D1FF}\x{1D200}-\x{1D24F}\x{0640}\x{07FA}\x{302E}\x{302F}\x{3031}-\x{3035}\x{303B}]*[\x{00B7}\x{0375}\x{05F3}\x{05F4}\x{30FB}\x{002D}\x{06FD}\x{06FE}\x{0F0B}\x{3007}\x{00DF}\x{03C2}\x{200C}\x{200D}\pL0-9\-._~!$&'(*+,;=:@/?|]+|%[\dA-F]{2})*)?" . ')#iu',
create_function(
"\$matches",
"return make_clickable_callback(MAGIC_URL_WWW, \$matches[1], \$matches[2], '', '$class', '$shortenLinks');"
@@ -1279,7 +1279,7 @@ function hesk_makeURL($text, $class = '', $shortenLinks = true)
// matches an email address
$text = preg_replace_callback(
- '/(^|[\n\t (>])(' . '(?:(?:(?:[^@,"\[\]\x5c\x00-\x20\x7f-\xff\.]|\x5c(?=[@,"\[\]\x5c\x00-\x20\x7f-\xff]))(?:[^@,"\[\]\x5c\x00-\x20\x7f-\xff\.]|(?<=\x5c)[@,"\[\]\x5c\x00-\x20\x7f-\xff]|\x5c(?=[@,"\[\]\x5c\x00-\x20\x7f-\xff])|\.(?=[^\.])){1,62}(?:[^@,"\[\]\x5c\x00-\x20\x7f-\xff\.]|(?<=\x5c)[@,"\[\]\x5c\x00-\x20\x7f-\xff])|[^@,"\[\]\x5c\x00-\x20\x7f-\xff\.]{1,2})|"(?:[^"]|(?<=\x5c)"){1,62}")@(?:(?!.{64})(?:[a-zA-Z0-9][a-zA-Z0-9-]{1,61}[a-zA-Z0-9]\.?|[a-zA-Z0-9]\.?)+\.(?:xn--[a-zA-Z0-9]+|[a-zA-Z]{2,6})|\[(?:[0-1]?\d?\d|2[0-4]\d|25[0-5])(?:\.(?:[0-1]?\d?\d|2[0-4]\d|25[0-5])){3}\])' . ')/iu',
+ '/(^|[\n\t (>])(' . '((?:[\w\!\#$\%\&\'\*\+\-\/\=\?\^\`{\|\}\~]+\.)*(?:[\w\!\#$\%\'\*\+\-\/\=\?\^\`{\|\}\~]|&)+)@((((([a-z0-9]{1}[a-z0-9\-]{0,62}[a-z0-9]{1})|[a-z])\.)+[a-z]{2,63})|(\d{1,3}\.){3}\d{1,3}(\:\d{1,5})?)' . ')/iu',
create_function(
"\$matches",
"return make_clickable_callback(MAGIC_URL_EMAIL, \$matches[1], \$matches[2], '', '$class', '$shortenLinks');"
diff --git a/inc/knowledgebase_functions.inc.php b/inc/knowledgebase_functions.inc.php
index 53814835..54218dae 100644
--- a/inc/knowledgebase_functions.inc.php
+++ b/inc/knowledgebase_functions.inc.php
@@ -270,13 +270,20 @@ function hesk_kbSearchLarge($admin = '')
{
global $hesk_settings, $hesklang;
- if ($hesk_settings['kb_search'] != 2)
- {
+ $action = 'knowledgebase.php';
+ if ($admin)
+ {
+ if ( ! $hesk_settings['kb_search'])
+ {
+ return '';
+ }
+ $action = 'knowledgebase_private.php';
+ }
+ elseif ($hesk_settings['kb_search'] != 2)
+ {
return '';
}
- $action = $admin ? 'knowledgebase_private.php' : 'knowledgebase.php';
-
?>
diff --git a/inc/posting_functions.inc.php b/inc/posting_functions.inc.php
index 6a518064..7d30fd60 100644
--- a/inc/posting_functions.inc.php
+++ b/inc/posting_functions.inc.php
@@ -176,18 +176,34 @@ function hesk_newTicket($ticket, $isVerified = true)
function hesk_cleanFileName($filename)
{
- $filename = str_replace( array( '%20', '+' ), '-', $filename );
+ $parts = pathinfo($filename);
+
+ if ( isset($parts['filename']) )
+ {
+ $filename = $parts['filename'];
+ }
+ // PHP < 5.2 needs special care
+ elseif ( version_compare(PHP_VERSION, '5.2','<') )
+ {
+ $filename = rtrim( str_ireplace($parts['extension'], '', $filename), '.');
+ }
+ else
+ {
+ $filename = '';
+ }
+
+ $filename = str_replace( array( '%20', '+' ), '-', $filename );
$filename = preg_replace('/[\s-]+/', '-', $filename);
$filename = remove_accents($filename);
$filename = preg_replace('/[^A-Za-z0-9\.\-_]/','', $filename);
- $filename = trim($filename, '.-_');
+ $filename = trim($filename, '-_');
- if ( strlen($filename) < 1 )
+ if ( strlen($filename) < 1 || strpos($filename, '.') === 0 )
{
- $filename = mt_rand(10000,99999);
+ $filename = mt_rand(10000,99999) . $filename;
}
- return $filename;
+ return $filename . '.' . $parts['extension'];
} // END hesk_cleanFileName()
diff --git a/language/en/text.php b/language/en/text.php
index 4546cb59..bda6e9ba 100644
--- a/language/en/text.php
+++ b/language/en/text.php
@@ -2,7 +2,7 @@
/*
* Language file for Help Desk Software HESK (www.hesk.com)
* Language: ENGLISH
-* Version: 2.6.1
+* Version: 2.6.3
* Author: Klemen Stirn (http://www.hesk.com)
*
* !!! This file must be saved in UTF-8 encoding without byte order mark (BOM) !!!
@@ -865,7 +865,7 @@ $hesklang['nhid']='Notes are hidden from customers!';
$hesklang['delt']='Delete this post';
$hesklang['edtt']='Edit post';
$hesklang['edt1']='Post modified';
-$hesklang['edt2']='Changes to the selecting post have been saved';
+$hesklang['edt2']='Changes to the selected post have been saved';
$hesklang['dele']='Delete this ticket';
$hesklang['repd']='Post deleted';
$hesklang['repl']='Selected post has been deleted';
@@ -1098,7 +1098,7 @@ $hesklang['nwts']='A new ticket is submitted with owner:';
$hesklang['ncrt']='Client responds to a ticket with owner:';
$hesklang['ntam']='A ticket is assigned to me';
$hesklang['npms']='A private message is sent to me';
-$hesklang['support_remove']='A lot of time and effort went into developing HESK. Support HESK, buy a license that will also remove the credits links Powered by Help Desk Software HESK from your helpdesk';
+$hesklang['support_remove']='A lot of time and effort went into developing HESK. Support HESK by purchasing a license that will remove the credits links Powered by Help Desk Software HESK from your helpdesk';
$hesklang['ycvtao']='You are not allowed to view tickets assigned to others';
$hesklang['password_not_valid']='Password must be at least 5 chars long';
$hesklang['lkbs']='Loading knowledgebase suggestions...';
diff --git a/submit_ticket.php b/submit_ticket.php
index 89b7ffcc..b59d2387 100644
--- a/submit_ticket.php
+++ b/submit_ticket.php
@@ -188,15 +188,30 @@ $tmpvar['email'] = hesk_validateEmail( hesk_POST('email'), 'ERR', 0) or $hesk_er
if ($hesk_settings['confirm_email'])
{
- $tmpvar['email2'] = hesk_input( hesk_POST('email2') ) or $hesk_error_buffer['email2']=$hesklang['confemail2'];
+ $tmpvar['email2'] = hesk_validateEmail( hesk_POST('email2'), 'ERR', 0) or $hesk_error_buffer['email2']=$hesklang['confemail2'];
- if (strlen($tmpvar['email2']) && ( strtolower($tmpvar['email']) != strtolower($tmpvar['email2']) ))
+ // Anything entered as email confirmation?
+ if ( strlen($tmpvar['email2']) )
{
- $tmpvar['email2'] = '';
- $_POST['email2'] = '';
- $_SESSION['c_email2'] = '';
- $_SESSION['isnotice'][] = 'email';
- $hesk_error_buffer['email2']=$hesklang['confemaile'];
+ // Do we have multiple emails?
+ if ($hesk_settings['multi_eml'] && count( array_diff( explode(',', strtolower($tmpvar['email']) ), explode(',', strtolower($tmpvar['email2']) ) ) ) == 0)
+ {
+ $_SESSION['c_email2'] = $_POST['email2'];
+ }
+ // Single email address match
+ elseif ( ! $hesk_settings['multi_eml'] && strtolower($tmpvar['email']) == strtolower($tmpvar['email2']) )
+ {
+ $_SESSION['c_email2'] = $_POST['email2'];
+ }
+ else
+ {
+ // Invalid match
+ $tmpvar['email2'] = '';
+ $_POST['email2'] = '';
+ $_SESSION['c_email2'] = '';
+ $_SESSION['isnotice'][] = 'email';
+ $hesk_error_buffer['email2']=$hesklang['confemaile'];
+ }
}
else
{
diff --git a/ticket.php b/ticket.php
index 24c94315..1ff87894 100644
--- a/ticket.php
+++ b/ticket.php
@@ -178,6 +178,12 @@ else
$ticket['repliername'] = $ticket['name'];
}
+// If IP is unknown (tickets via email pipe/pop3 fetching) assume current visitor IP as customer IP
+if ($ticket['ip'] == 'Unknown' || $ticket['ip'] == $hesklang['unknown'])
+{
+ hesk_dbQuery("UPDATE `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` SET `ip` = '".hesk_dbEscape($_SERVER['REMOTE_ADDR'])."' WHERE `id`=".intval($ticket['id'])." LIMIT 1");
+}
+
/* Get category name and ID */
$result = hesk_dbQuery("SELECT `name` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."categories` WHERE `id`='".intval($ticket['category'])."' LIMIT 1");