From b6dac7da20d6394a25f44c16666fa8aefe67b0a9 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 21 Nov 2018 15:40:15 +0100 Subject: [PATCH] FIX Remote ip detection was wrong with proxy (example: cloudflare) --- htdocs/admin/geoipmaxmind.php | 4 +- htdocs/core/class/events.class.php | 5 +- htdocs/core/lib/functions.lib.php | 264 ++++++++++++++++++++++++++++- 3 files changed, 267 insertions(+), 6 deletions(-) diff --git a/htdocs/admin/geoipmaxmind.php b/htdocs/admin/geoipmaxmind.php index 9b755d9bf57..47c51069299 100644 --- a/htdocs/admin/geoipmaxmind.php +++ b/htdocs/admin/geoipmaxmind.php @@ -152,7 +152,7 @@ if ($geoip) else print $langs->trans("Error"); */ //var_dump($_SERVER); - $ip = $_SERVER['REMOTE_ADDR']?$_SERVER['REMOTE_ADDR']:(($_SERVER['HTTP_X_FORWARDED_FOR']?$_SERVER['HTTP_X_FORWARDED_FOR']:$_SERVER['HTTP_CLIENT_IP'])); + $ip = getUserRemoteIP(); //$ip='91.161.249.43'; $isip=is_ip($ip); if ($isip == 1) @@ -162,7 +162,7 @@ if ($geoip) if ($result) print $result; else print $langs->trans("Error"); } - elseif ($isip == 2) + else { print '
'.$ip.' -> '; $result=dol_print_ip($ip,1); diff --git a/htdocs/core/class/events.class.php b/htdocs/core/class/events.class.php index c4b726b19d1..78439af1134 100644 --- a/htdocs/core/class/events.class.php +++ b/htdocs/core/class/events.class.php @@ -137,6 +137,7 @@ class Events // extends CommonObject // Clean parameters $this->description=trim($this->description); + if (empty($this->user_agent) && !empty($_SERVER['HTTP_USER_AGENT'])) $this->user_agent=$_SERVER['HTTP_USER_AGENT']; // Check parameters if (empty($this->description)) { $this->error='ErrorBadValueForParameterCreateEventDesc'; return -1; } @@ -153,8 +154,8 @@ class Events // extends CommonObject $sql.= ") VALUES ("; $sql.= " '".$this->db->escape($this->type)."',"; $sql.= " ".$conf->entity.","; - $sql.= " '".$this->db->escape($_SERVER['REMOTE_ADDR'])."',"; - $sql.= " ".($_SERVER['HTTP_USER_AGENT']?"'".$this->db->escape(dol_trunc($_SERVER['HTTP_USER_AGENT'],250))."'":'NULL').","; + $sql.= " '".$this->db->escape(getUserRemoteIP())."',"; + $sql.= " ".($this->user_agent ? "'".$this->db->escape(dol_trunc($this->user_agent,250))."'" : 'NULL').","; $sql.= " '".$this->db->idate($this->dateevent)."',"; $sql.= " ".($user->id?"'".$this->db->escape($user->id)."'":'NULL').","; $sql.= " '".$this->db->escape(dol_trunc($this->description,250))."'"; diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 947b3800d60..48f6242bf66 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -2665,6 +2665,20 @@ function dol_print_ip($ip,$mode=0) return $ret; } +/** + * Return the IP of remote user. + * Take HTTP_X_FORWARDED_FOR (defined when using proxy) + * Then HTTP_CLIENT_IP if defined (rare) + * Then REMOTE_ADDR (not way to be modified by user but may be wrong if using proxy) + * + * @return string Ip of remote user. + */ +function getUserRemoteIP() +{ + $ip = $_SERVER['HTTP_X_FORWARDED_FOR']?$_SERVER['HTTP_X_FORWARDED_FOR']:(($_SERVER['HTTP_CLIENT_IP']?$_SERVER['HTTP_CLIENT_IP']:$_SERVER['REMOTE_ADDR'])); + return $ip; +} + /** * Return a country code from IP. Empty string if not found. * @@ -2708,7 +2722,7 @@ function dol_user_country() $ret=''; if (! empty($conf->geoipmaxmind->enabled)) { - $ip=$_SERVER["REMOTE_ADDR"]; + $ip=getUserRemoteIP(); $datafile=$conf->global->GEOIPMAXMIND_COUNTRY_DATAFILE; //$ip='24.24.24.24'; //$datafile='E:\Mes Sites\Web\Admin1\awstats\maxmind\GeoIP.dat'; @@ -5783,7 +5797,7 @@ function getCommonSubstitutionArray($outputlangs, $onlykey=0, $exclude=null, $ob '__USER_FIRSTNAME__' => (string) $user->firstname, '__USER_FULLNAME__' => (string) $user->getFullName($outputlangs), '__USER_SUPERVISOR_ID__' => (string) ($user->fk_user ? $user->fk_user : '0'), - '__USER_REMOTE_IP__' => (string) $_SERVER['REMOTE_ADDR'] + '__USER_REMOTE_IP__' => (string) getUserRemoteIP() ) ); } @@ -6770,6 +6784,252 @@ function picto_from_langcode($codelang, $moreatt = '') return img_picto_common($codelang, 'flags/'.strtolower($flagImage).'.png', $moreatt); } +/** + * Return default language from country code + * + * @param string $countrycode Country code like 'US', 'FR', 'CA', ... + * @return string Value of locale like 'en_US', 'fr_FR', ... + */ +function getLanguageCodeFromCountryCode($countrycode) +{ + $countrycodetolanguage = array( + 'SA' => 'ar_AR', + 'DK' => 'da_DA', + 'CA' => 'en_CA', + 'SE' => 'sv_SV' + ); + if (! empty($countrycodetolanguage[$countrycode])) return $countrycodetolanguage[$countrycode]; + + // Locale list taken from: + // http://stackoverflow.com/questions/3191664/ + // list-of-all-locales-and-their-short-codes + $locales = array( + 'af-ZA', + 'am-ET', + 'ar-AE', + 'ar-BH', + 'ar-DZ', + 'ar-EG', + 'ar-IQ', + 'ar-JO', + 'ar-KW', + 'ar-LB', + 'ar-LY', + 'ar-MA', + 'arn-CL', + 'ar-OM', + 'ar-QA', + 'ar-SA', + 'ar-SY', + 'ar-TN', + 'ar-YE', + 'as-IN', + 'az-Cyrl-AZ', + 'az-Latn-AZ', + 'ba-RU', + 'be-BY', + 'bg-BG', + 'bn-BD', + 'bn-IN', + 'bo-CN', + 'br-FR', + 'bs-Cyrl-BA', + 'bs-Latn-BA', + 'ca-ES', + 'co-FR', + 'cs-CZ', + 'cy-GB', + 'da-DK', + 'de-AT', + 'de-CH', + 'de-DE', + 'de-LI', + 'de-LU', + 'dsb-DE', + 'dv-MV', + 'el-GR', + 'en-029', + 'en-AU', + 'en-BZ', + 'en-CA', + 'en-GB', + 'en-IE', + 'en-IN', + 'en-JM', + 'en-MY', + 'en-NZ', + 'en-PH', + 'en-SG', + 'en-TT', + 'en-US', + 'en-ZA', + 'en-ZW', + 'es-AR', + 'es-BO', + 'es-CL', + 'es-CO', + 'es-CR', + 'es-DO', + 'es-EC', + 'es-ES', + 'es-GT', + 'es-HN', + 'es-MX', + 'es-NI', + 'es-PA', + 'es-PE', + 'es-PR', + 'es-PY', + 'es-SV', + 'es-US', + 'es-UY', + 'es-VE', + 'et-EE', + 'eu-ES', + 'fa-IR', + 'fi-FI', + 'fil-PH', + 'fo-FO', + 'fr-BE', + 'fr-CA', + 'fr-CH', + 'fr-FR', + 'fr-LU', + 'fr-MC', + 'fy-NL', + 'ga-IE', + 'gd-GB', + 'gl-ES', + 'gsw-FR', + 'gu-IN', + 'ha-Latn-NG', + 'he-IL', + 'hi-IN', + 'hr-BA', + 'hr-HR', + 'hsb-DE', + 'hu-HU', + 'hy-AM', + 'id-ID', + 'ig-NG', + 'ii-CN', + 'is-IS', + 'it-CH', + 'it-IT', + 'iu-Cans-CA', + 'iu-Latn-CA', + 'ja-JP', + 'ka-GE', + 'kk-KZ', + 'kl-GL', + 'km-KH', + 'kn-IN', + 'kok-IN', + 'ko-KR', + 'ky-KG', + 'lb-LU', + 'lo-LA', + 'lt-LT', + 'lv-LV', + 'mi-NZ', + 'mk-MK', + 'ml-IN', + 'mn-MN', + 'mn-Mong-CN', + 'moh-CA', + 'mr-IN', + 'ms-BN', + 'ms-MY', + 'mt-MT', + 'nb-NO', + 'ne-NP', + 'nl-BE', + 'nl-NL', + 'nn-NO', + 'nso-ZA', + 'oc-FR', + 'or-IN', + 'pa-IN', + 'pl-PL', + 'prs-AF', + 'ps-AF', + 'pt-BR', + 'pt-PT', + 'qut-GT', + 'quz-BO', + 'quz-EC', + 'quz-PE', + 'rm-CH', + 'ro-RO', + 'ru-RU', + 'rw-RW', + 'sah-RU', + 'sa-IN', + 'se-FI', + 'se-NO', + 'se-SE', + 'si-LK', + 'sk-SK', + 'sl-SI', + 'sma-NO', + 'sma-SE', + 'smj-NO', + 'smj-SE', + 'smn-FI', + 'sms-FI', + 'sq-AL', + 'sr-Cyrl-BA', + 'sr-Cyrl-CS', + 'sr-Cyrl-ME', + 'sr-Cyrl-RS', + 'sr-Latn-BA', + 'sr-Latn-CS', + 'sr-Latn-ME', + 'sr-Latn-RS', + 'sv-FI', + 'sv-SE', + 'sw-KE', + 'syr-SY', + 'ta-IN', + 'te-IN', + 'tg-Cyrl-TJ', + 'th-TH', + 'tk-TM', + 'tn-ZA', + 'tr-TR', + 'tt-RU', + 'tzm-Latn-DZ', + 'ug-CN', + 'uk-UA', + 'ur-PK', + 'uz-Cyrl-UZ', + 'uz-Latn-UZ', + 'vi-VN', + 'wo-SN', + 'xh-ZA', + 'yo-NG', + 'zh-CN', + 'zh-HK', + 'zh-MO', + 'zh-SG', + 'zh-TW', + 'zu-ZA', + ); + + foreach ($locales as $locale) + { + $locale_region = locale_get_region($locale); + $locale_language = locale_get_primary_language($locale); + $locale_array = array('language' => $locale_language, 'region' => $locale_region); + if (strtoupper($countrycode) == $locale_region) + { + return locale_compose($locale_array); + } + } + + return null; +} + /** * Complete or removed entries into a head array (used to build tabs). * For example, with value added by external modules. Such values are declared into $conf->modules_parts['tab'].