From 7277b5e4a2960b620d8d66ee1807868758142fa0 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Mon, 10 Apr 2017 21:32:29 -0400 Subject: [PATCH] #544 Rest of the 2.7.3 updates --- inc/common.inc.php | 158 ++++++++++++++++++++++++---- inc/knowledgebase_functions.inc.php | 6 +- inc/pipe_functions.inc.php | 1 - inc/posting_functions.inc.php | 2 +- index.php | 79 +++++++++++--- install/install_functions.inc.php | 2 +- knowledgebase.php | 20 +++- reply_ticket.php | 4 +- submit_ticket.php | 10 +- ticket.php | 4 +- 10 files changed, 230 insertions(+), 56 deletions(-) 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() @@ -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 */