diff --git a/inc/common.inc.php b/inc/common.inc.php
index ba3c43ef..5f4f4aa5 100644
--- a/inc/common.inc.php
+++ b/inc/common.inc.php
@@ -77,9 +77,81 @@ if (isset($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) == 'on') {
// Load language file
hesk_getLanguage();
+// Set timezone
+hesk_setTimezone();
+
/*** FUNCTIONS ***/
+function hesk_getClientIP() {
+ global $hesk_settings;
+
+ // Already set? Just return it
+ if (isset($hesk_settings['client_IP'])) {
+ return $hesk_settings['client_IP'];
+ }
+
+ // Empty client IP, for example when used in CLI (piping, cron jobs, ...)
+ $hesk_settings['client_IP'] = '';
+
+ // Server (environment) variables to loop through
+ // the first valid one found will be returned as client IP
+ // Uncomment those used on your server
+ $server_client_IP_variables = array(
+ // 'HTTP_CF_CONNECTING_IP', // CloudFlare
+ // 'HTTP_CLIENT_IP',
+ // 'HTTP_X_FORWARDED_FOR',
+ // 'HTTP_X_FORWARDED',
+ // 'HTTP_FORWARDED_FOR',
+ // 'HTTP_FORWARDED',
+ 'REMOTE_ADDR',
+ );
+
+ // The first valid environment variable is our client IP
+ foreach ($server_client_IP_variables as $server_client_IP_variable) {
+ // Must be set
+ if (!isset($_SERVER[$server_client_IP_variable])) {
+ continue;
+ }
+
+ // Must be a valid IP
+ if (!hesk_isValidIP($_SERVER[$server_client_IP_variable])) {
+ continue;
+ }
+
+ // Bingo!
+ $hesk_settings['client_IP'] = $_SERVER[$server_client_IP_variable];
+ break;
+ }
+
+ return $hesk_settings['client_IP'];
+
+} // END hesk_getClientIP()
+
+
+function hesk_isValidIP($ip) {
+ // Use filter_var for PHP 5.2.0
+ if (function_exists('filter_var') && filter_var($ip, FILTER_VALIDATE_IP) !== false) {
+ return true;
+ }
+
+ // Use regex for PHP < 5.2.0
+
+ // -> IPv4
+ if (preg_match('/^[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}$/', $ip)) {
+ return true;
+ }
+
+ // -> IPv6
+ if (preg_match('/^[0-9A-Fa-f\:\.]$/', $ip)) {
+ return true;
+ }
+
+ // Not a valid IP
+ return false;
+
+} // END hesk_isValidIP()
+
function hesk_setcookie($name, $value, $expire=0, $path=""){
if (HESK_SSL) {
setcookie($name, $value, $expire, $path, "", true, true);
@@ -415,6 +487,9 @@ function hesk_getCustomerEmail($can_remember = 0, $field = '')
}
}
+ // Remove unwanted side-effects
+ $my_email = hesk_emailCleanup($my_email);
+
$hesk_settings['e_param'] = '&e=' . rawurlencode($my_email);
$hesk_settings['e_query'] = '&e=' . rawurlencode($my_email);
$hesk_settings['e_email'] = $my_email;
@@ -423,6 +498,10 @@ function hesk_getCustomerEmail($can_remember = 0, $field = '')
} // END hesk_getCustomerEmail()
+function hesk_emailCleanup($my_email) {
+ return preg_replace("/(\\\)'/", "'", $my_email);
+} // END hesk_emailCleanup()
+
function hesk_formatBytes($size, $translate_unit = 1, $precision = 2)
{
@@ -670,7 +749,7 @@ function hesk_cleanBfAttempts()
}
/* Delete expired logs from the database */
- $res = hesk_dbQuery("DELETE FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "logins` WHERE `ip`='" . hesk_dbEscape($_SERVER['REMOTE_ADDR']) . "'");
+ hesk_dbQuery("DELETE FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."logins` WHERE `ip`='".hesk_dbEscape(hesk_getClientIP())."'");
define('HESK_BF_CLEAN', 1);
@@ -683,7 +762,7 @@ function hesk_limitBfAttempts($showError = 1)
global $hesk_settings, $hesklang;
// Check if this IP is banned permanently
- if (hesk_isBannedIP($_SERVER['REMOTE_ADDR'])) {
+ if (hesk_isBannedIP(hesk_getClientIP())) {
hesk_error($hesklang['baned_ip'], 0);
}
@@ -695,7 +774,7 @@ function hesk_limitBfAttempts($showError = 1)
/* Define this constant to avoid duplicate checks */
define('HESK_BF_LIMIT', 1);
- $ip = $_SERVER['REMOTE_ADDR'];
+ $ip = hesk_getClientIP();
/* Get number of failed attempts from the database */
$res = hesk_dbQuery("SELECT `number`, (CASE WHEN `last_attempt` IS NOT NULL AND DATE_ADD(`last_attempt`, INTERVAL " . intval($hesk_settings['attempt_banmin']) . " MINUTE ) > NOW() THEN 1 ELSE 0 END) AS `banned` FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "logins` WHERE `ip`='" . hesk_dbEscape($ip) . "' LIMIT 1");
@@ -1207,6 +1286,58 @@ function hesk_returnLanguage()
return true;
} // END hesk_returnLanguage()
+function hesk_setTimezone() {
+ global $hesk_settings;
+
+ // Get Hesk time difference from UTC in seconds
+ $seconds = date('Z') + 3600*$hesk_settings['diff_hours'] + 60*$hesk_settings['diff_minutes'];
+
+ // Daylight saving?
+ if ($hesk_settings['daylight'] && date('I')) {
+ $seconds = 3600;
+ $is_daylight = 1;
+ } else {
+ $is_daylight = 0;
+ }
+
+ // Get timezone name from seconds
+ $tz = timezone_name_from_abbr('', $seconds, $is_daylight);
+
+ // Workaround for bug #44780
+ if($tz === false) {
+ $tz = timezone_name_from_abbr('', $seconds, 0);
+ }
+
+ // Still false? Disregards minutes
+ if($tz === false) {
+ $seconds = date('Z') + 3600*$hesk_settings['diff_hours'];
+ $tz = timezone_name_from_abbr('', $seconds, 0);
+ }
+
+ // Set timezone
+ date_default_timezone_set($tz);
+
+ return true;
+
+} // END hesk_setTimezone()
+
+
+function hesk_timeToHHMM($time, $time_format="seconds", $signed=true) {
+ if ($time < 0) {
+ $time = abs($time);
+ $sign = "-";
+ } else {
+ $sign = "";
+ }
+
+ if ($time_format == 'minutes') {
+ $time *= 60;
+ }
+
+ return ($signed ? $sign : '') . gmdate('H:i', $time);
+
+} // END hesk_timeToHHMM()
+
function hesk_date($dt = '', $from_database = false, $is_str = true, $return_str = true)
{
@@ -1218,25 +1349,6 @@ function hesk_date($dt = '', $from_database = false, $is_str = true, $return_str
$dt = strtotime($dt);
}
- // Adjust MySQL time if different from PHP time
- if ($from_database) {
- if (!defined('MYSQL_TIME_DIFF')) {
- define('MYSQL_TIME_DIFF', time() - hesk_dbTime());
- }
-
- if (MYSQL_TIME_DIFF != 0) {
- $dt += MYSQL_TIME_DIFF;
- }
- }
-
- // Add HESK set time difference
- $dt += 3600 * $hesk_settings['diff_hours'] + 60 * $hesk_settings['diff_minutes'];
-
- // Daylight savings?
- if ($hesk_settings['daylight'] && date('I', $dt)) {
- $dt += 3600;
- }
-
// Return formatted date
return $return_str ? date($hesk_settings['timeformat'], $dt) : $dt;
@@ -1729,7 +1841,7 @@ function hesk_check_maintenance($dodie = true)
$hesk_settings['maintenance_mode'] == 0 &&
$hesk_settings['question_ans'] == 'PB6YM' &&
- $hesk_settings['site_title'] == 'My Web site' &&
+ $hesk_settings['site_title'] == 'Website' &&
$hesk_settings['site_url'] == 'http://www.example.com' &&
$hesk_settings['webmaster_mail'] == 'support@example.com' &&
$hesk_settings['noreply_mail'] == 'support@example.com' &&
diff --git a/inc/knowledgebase_functions.inc.php b/inc/knowledgebase_functions.inc.php
index b5f8df6b..8d4b7f7f 100644
--- a/inc/knowledgebase_functions.inc.php
+++ b/inc/knowledgebase_functions.inc.php
@@ -59,9 +59,6 @@ function hesk_kbTopArticles($how_many, $index = 1)
// Show title in bold
$font_weight = 'b';
-
- // Print a line for spacing
- echo '
';
}
?>
@@ -108,6 +105,8 @@ function hesk_kbTopArticles($how_many, $index = 1)
$hesk_settings['kb_top_articles_printed'] = array();
while ($article = hesk_dbFetchAssoc($res)) {
+ $hesk_settings['kb_spacing']--;
+
$hesk_settings['kb_top_articles_printed'][] = $article['id'];
$icon = 'fa fa-file';
@@ -217,6 +216,7 @@ function hesk_kbLatestArticles($how_many, $index = 1)
/* We have some results, print them out */
$colspan = $hesk_settings['kb_date'] ? '' : 'colspan="2"';
while ($article = hesk_dbFetchAssoc($res)) {
+ $hesk_settings['kb_spacing']--;
$icon = 'fa fa-file';
$style = '';
diff --git a/inc/pipe_functions.inc.php b/inc/pipe_functions.inc.php
index df064e07..4b92df4a 100755
--- a/inc/pipe_functions.inc.php
+++ b/inc/pipe_functions.inc.php
@@ -266,7 +266,6 @@ function hesk_email2ticket($results, $pop3 = 0, $set_category = 1, $set_priority
// Not a reply, but a new ticket. Add it to the database
$tmpvar['category'] = $set_category;
$tmpvar['priority'] = $set_priority < 0 ? hesk_getCategoryPriority($tmpvar['category']) : $set_priority;
- $_SERVER['REMOTE_ADDR'] = $hesklang['unknown'];
// Auto assign tickets if aplicable
$tmpvar['owner'] = 0;
diff --git a/inc/posting_functions.inc.php b/inc/posting_functions.inc.php
index a3471411..a2cd5221 100644
--- a/inc/posting_functions.inc.php
+++ b/inc/posting_functions.inc.php
@@ -101,7 +101,7 @@ function hesk_newTicket($ticket, $isVerified = true)
NOW(),
NOW(),
" . (isset($ticket['articles']) ? "'{$ticket['articles']}'" : 'NULL') . ",
- '" . hesk_dbEscape($_SERVER['REMOTE_ADDR']) . "',
+ '" . hesk_dbEscape(hesk_getClientIP()) . "',
'" . hesk_dbEscape($language) . "',
'" . (isset($ticket['openedby']) ? intval($ticket['openedby']) : 0) . "',
'" . intval($ticket['owner']) . "',
diff --git a/index.php b/index.php
index a3b5f43c..41fddc81 100644
--- a/index.php
+++ b/index.php
@@ -721,7 +721,7 @@ function print_add_ticket()
@@ -1116,7 +1116,7 @@ function print_add_ticket()
:
@@ -1206,16 +1206,26 @@ function print_start()
{
global $hesk_settings, $hesklang;
- if ($hesk_settings['kb_enable'])
- {
- require(HESK_PATH . 'inc/knowledgebase_functions.inc.php');
- }
-
// Connect to database
+ hesk_load_database_functions();
hesk_dbConnect();
define('PAGE_TITLE', 'CUSTOMER_HOME');
+ // This will be used to determine how much space to print after KB
+ $hesk_settings['kb_spacing'] = 4;
+
+ // Include KB functionality only if we have any public articles
+ has_public_kb();
+ if ($hesk_settings['kb_enable'])
+ {
+ require(HESK_PATH . 'inc/knowledgebase_functions.inc.php');
+ }
+ else
+ {
+ $hesk_settings['kb_spacing'] += 2;
+ }
+
/* Print header */
require_once(HESK_PATH . 'inc/header.inc.php');
@@ -1418,7 +1428,7 @@ require(HESK_PATH . 'inc/email_functions.inc.php');
/* Get ticket(s) from database */
hesk_dbConnect();
-$email = hesk_validateEmail(hesk_POST('email'), 'ERR', 0) or hesk_process_messages($hesklang['enter_valid_email'], 'ticket.php?remind=1');
+$email = hesk_emailCleanup(hesk_validateEmail(hesk_POST('email'), 'ERR', 0)) or hesk_process_messages($hesklang['enter_valid_email'], 'ticket.php?remind=1');
if (isset($_POST['open_only'])) {
$hesk_settings['open_only'] = $_POST['open_only'] == 1 ? 1 : 0;
@@ -1437,9 +1447,9 @@ $res = hesk_dbQuery('SELECT * FROM `' . hesk_dbEscape($hesk_settings['db_pfix'])
$num = hesk_dbNumRows($res);
if ($num < 1) {
if ($hesk_settings['open_only']) {
- hesk_process_messages($hesklang['noopen'], 'ticket.php?remind=1&e=' . $email);
+ hesk_process_messages($hesklang['noopen'],'ticket.php?remind=1&e='.rawurlencode($email));
} else {
- hesk_process_messages($hesklang['tid_not_found'], 'ticket.php?remind=1&e=' . $email);
+ hesk_process_messages($hesklang['tid_not_found'],'ticket.php?remind=1&e='.rawurlencode($email));
}
}
@@ -1505,8 +1515,7 @@ require_once(HESK_PATH . 'inc/header.inc.php');
} // End forgot_tid()
- function processEmail($msg, $name, $num, $tid_list)
- {
+ function processEmail($msg, $name, $num, $tid_list) {
global $hesk_settings;
$msg = str_replace('%%NAME%%', $name, $msg);
@@ -1517,4 +1526,48 @@ require_once(HESK_PATH . 'inc/header.inc.php');
return $msg;
}
- ?>
+function has_public_kb($use_cache=1) {
+ global $hesk_settings;
+
+ // Return if KB is disabled
+ if ( ! $hesk_settings['kb_enable']) {
+ return 0;
+ }
+
+ // Do we have a cached version available
+ $cache_dir = $hesk_settings['cache_dir'].'/';
+ $cache_file = $cache_dir . 'kb.cache.php';
+
+ if ($use_cache && file_exists($cache_file)) {
+ require($cache_file);
+ return $hesk_settings['kb_enable'];
+ }
+
+ // Make sure we have database connection
+ hesk_load_database_functions();
+ hesk_dbConnect();
+
+ // Do we have any public articles at all?
+ $res = hesk_dbQuery("SELECT `t1`.`id` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."kb_articles` AS `t1`
+ LEFT JOIN `".hesk_dbEscape($hesk_settings['db_pfix'])."kb_categories` AS `t2` ON `t1`.`catid` = `t2`.`id`
+ WHERE `t1`.`type`='0' AND `t2`.`type`='0' LIMIT 1");
+
+ // If no public articles, disable the KB functionality
+ if (hesk_dbNumRows($res) < 1) {
+ $hesk_settings['kb_enable'] = 0;
+ }
+
+ // Try to cache results
+ if ($use_cache && (is_dir($cache_dir) || (@mkdir($cache_dir, 0777) && is_writable($cache_dir)))) {
+ // Is there an index.htm file?
+ if ( ! file_exists($cache_dir.'index.htm')) {
+ @file_put_contents($cache_dir.'index.htm', '');
+ }
+
+ // Write data
+ @file_put_contents($cache_file, ' NOW() LIMIT 1");
+$res = hesk_dbQuery("SELECT `number` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."logins` WHERE `ip`='".hesk_dbEscape(hesk_getClientIP())."' AND `last_attempt` IS NOT NULL AND DATE_ADD(`last_attempt`, INTERVAL ".intval($hesk_settings['attempt_banmin'])." MINUTE ) > NOW() LIMIT 1");
if (hesk_dbNumRows($res) == 1) {
if (hesk_dbResult($res) >= $hesk_settings['attempt_limit']) {
unset($_SESSION);
@@ -157,7 +157,7 @@ if (hesk_dbNumRows($res) > 0) {
$sequential_customer_replies = $tmp['staffid'] ? 0 : $sequential_customer_replies + 1;
}
if ($sequential_customer_replies > 10) {
- hesk_dbQuery("INSERT INTO `" . hesk_dbEscape($hesk_settings['db_pfix']) . "logins` (`ip`, `number`) VALUES ('" . hesk_dbEscape($_SERVER['REMOTE_ADDR']) . "', " . intval($hesk_settings['attempt_limit'] + 1) . ")");
+ hesk_dbQuery("INSERT INTO `".hesk_dbEscape($hesk_settings['db_pfix'])."logins` (`ip`, `number`) VALUES ('".hesk_dbEscape(hesk_getClientIP())."', ".intval($hesk_settings['attempt_limit'] + 1).")");
hesk_error(sprintf($hesklang['yhbr'], $hesk_settings['attempt_banmin']), 0);
}
}
diff --git a/submit_ticket.php b/submit_ticket.php
index 00fafb1b..03c710e4 100644
--- a/submit_ticket.php
+++ b/submit_ticket.php
@@ -87,7 +87,7 @@ if ($hesk_settings['secimg_use'] && !isset($_SESSION['img_verified'])) {
require(HESK_PATH . 'inc/recaptcha/recaptchalib.php');
$resp = recaptcha_check_answer($hesk_settings['recaptcha_private_key'],
- $_SERVER['REMOTE_ADDR'],
+ hesk_getClientIP(),
hesk_POST('recaptcha_challenge_field', ''),
hesk_POST('recaptcha_response_field', '')
);
@@ -268,9 +268,9 @@ foreach ($hesk_settings['custom_fields'] as $k=>$v) {
$_SESSION["c_$k"] = '';
if (preg_match("/^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])$/", $tmpvar[$k])) {
- $date = strtotime($tmpvar[$k] . ' t00:00:00');
- $dmin = strlen($v['value']['dmin']) ? strtotime($v['value']['dmin'] . ' t00:00:00') : false;
- $dmax = strlen($v['value']['dmax']) ? strtotime($v['value']['dmax'] . ' t00:00:00') : false;
+ $date = strtotime($tmpvar[$k] . ' t00:00:00 UTC');
+ $dmin = strlen($v['value']['dmin']) ? strtotime($v['value']['dmin'] . ' t00:00:00 UTC') : false;
+ $dmax = strlen($v['value']['dmax']) ? strtotime($v['value']['dmax'] . ' t00:00:00 UTC') : false;
$_SESSION["c_$k"] = $tmpvar[$k];
@@ -317,7 +317,7 @@ foreach ($hesk_settings['custom_fields'] as $k=>$v) {
}
// Check bans
-if ($email_available && ! isset($hesk_error_buffer['email']) && hesk_isBannedEmail($tmpvar['email']) || hesk_isBannedIP($_SERVER['REMOTE_ADDR'])) {
+if ($email_available && ! isset($hesk_error_buffer['email']) && hesk_isBannedEmail($tmpvar['email']) || hesk_isBannedIP(hesk_getClientIP())) {
hesk_error($hesklang['baned_e']);
}
diff --git a/ticket.php b/ticket.php
index ad46c9ef..fd413808 100644
--- a/ticket.php
+++ b/ticket.php
@@ -159,8 +159,8 @@ if ($ticket['lastreplier']) {
}
// 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']));
+if ($ticket['ip'] == '' || $ticket['ip'] == 'Unknown' || $ticket['ip'] == $hesklang['unknown']) {
+ hesk_dbQuery("UPDATE `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` SET `ip` = '".hesk_dbEscape(hesk_getClientIP())."' WHERE `id`=".intval($ticket['id']));
}
/* Get category name and ID */