PluginProbe
Bit Form – Contact Form, Payment Forms, Multi Step Forms, Calculator & Custom Form Builder / V3.3.2
Bit Form – Contact Form, Payment Forms, Multi Step Forms, Calculator & Custom Form Builder vV3.3.2
V3.3.2 3.3.1 V-3.3.0 3.2.2 3.2.1 3.2.0 3.1.4 3.1.3 3.1.2 3.1.1 3.1.0 V3.0.3 V3.0.2 -3.0.1 V_3.0.0 1.1.1 1.1.8 1.2 1.3 1.4 1.4.18 1.5.2 1.9 2.0 2.10.0 All 139 releases
← All changes | includes/Core/Util/IpTool.php +70 -35 3.1.3 → V3.3.2 View file →
@@ -14,57 +14,92 @@
14 14 * @return string IP address of current visitor
15 15 */
16 16
17 17 /**
18 + * Stored form of an IP: IPv4 as unsigned number (existing rows), IPv6 as text (numeric form was lossy).
18 19 *
19 - ipaddress converted to number digit
20 - */
21 - private static function ip2Number($ipAdr)
20 + * @param mixed $ip IP address
21 + *
22 + * @return string '' when $ip is not a valid address
23 + */
24 + public static function storageValue($ip)
22 25 {
23 - $ipTobytes = @inet_pton($ipAdr);
26 + if (!is_string($ip) || false === filter_var($ip, FILTER_VALIDATE_IP)) {
27 + return '';
28 + }
29 + if (false !== filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
30 + return sprintf('%u', ip2long($ip));
31 + }
32 + $packed = inet_pton($ip);
24 33
25 - if (!$ipTobytes) {
26 - return false;
34 + return false === $packed ? '' : (string) inet_ntop($packed);
35 + }
36 +
37 + /**
38 + * Readable IP for a stored user_ip value.
39 + *
40 + * @param mixed $stored Value from user_ip
41 + *
42 + * @return string IP address, or '' for empty/lossy pre-3.3.2 IPv6 values
43 + */
44 + public static function displayValue($stored)
45 + {
46 + $stored = trim((string) $stored);
47 + if ('' === $stored) {
48 + return '';
27 49 }
28 -
29 - $number = '';
30 - foreach (unpack('C*', $ipTobytes) as $byte) {
31 - $number .= str_pad(decbin($byte), 8, '0', STR_PAD_LEFT);
50 + if (ctype_digit($stored)) {
51 + return (strlen($stored) <= 10 && (float) $stored <= 4294967295) ? long2ip((int) $stored) : '';
32 52 }
33 53
34 - return base_convert(ltrim($number, '0'), 2, 10);
54 + return false === filter_var($stored, FILTER_VALIDATE_IP) ? '' : $stored;
35 55 }
36 56
37 - private static function validateIpAddress($ip)
57 + /**
58 + * First valid IP in a client-controlled header value; anything else is rejected (injection guard).
59 + *
60 + * @param mixed $value Raw header value
61 + *
62 + * @return string IP address, or ''
63 + */
64 + public static function extractValidIp($value)
38 65 {
39 - $ipv4Pattern = '/(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:[.](?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}/';
40 - $ipv6Pattern = '/([A-Fa-f0-9]{1,4})\:([A-Fa-f0-9]{1,4})\:([A-Fa-f0-9]{1,4})\:([A-Fa-f0-9]{1,4})\:([A-Fa-f0-9]{1,4})\:([A-Fa-f0-9]{1,4})\:([A-Fa-f0-9]{1,4})\:([A-Fa-f0-9]{1,4})/';
66 + if (!is_string($value) || '' === $value) {
67 + return '';
68 + }
41 69
42 - if (preg_match($ipv4Pattern, $ip, $patternMatchIp)) {
43 - $ip = $patternMatchIp[0];
44 - } elseif (preg_match($ipv6Pattern, $ip, $patternMatchIp)) {
45 - $ip = $patternMatchIp[0];
70 + $ipv4Pattern = '/(?<![\d.])(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:[.](?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}(?![\d.])/';
71 +
72 + foreach (preg_split('/[\s,;]+/', $value) as $part) {
73 + $part = trim(preg_replace('/^for=/i', '', $part), "\"'");
74 + if (preg_match('/^\[([^\]]+)\]/', $part, $bracketed)) {
75 + $part = $bracketed[1];
76 + }
77 +
78 + if (false !== filter_var($part, FILTER_VALIDATE_IP)) {
79 + return $part;
80 + }
81 +
82 + // IPv4 with port, e.g. "203.0.113.7:8080"
83 + if (preg_match($ipv4Pattern, $part, $match) && false !== filter_var($match[0], FILTER_VALIDATE_IP)) {
84 + return $match[0];
85 + }
46 86 }
47 87
48 - return $ip;
88 + return '';
49 89 }
50 90
51 91 private static function _checkIP()
52 92 {
53 - if (getenv('HTTP_CLIENT_IP')) {
54 - $ip = getenv('HTTP_CLIENT_IP');
55 - } elseif (getenv('HTTP_X_FORWARDED_FOR')) {
56 - $ip = getenv('HTTP_X_FORWARDED_FOR');
57 - } elseif (getenv('HTTP_X_FORWARDED')) {
58 - $ip = getenv('HTTP_X_FORWARDED');
59 - } elseif (getenv('HTTP_FORWARDED_FOR')) {
60 - $ip = getenv('HTTP_FORWARDED_FOR');
61 - } elseif (getenv('HTTP_FORWARDED')) {
62 - $ip = getenv('HTTP_FORWARDED');
63 - } else {
64 - $ip = isset($_SERVER['REMOTE_ADDR']) ? sanitize_text_field(wp_unslash($_SERVER['REMOTE_ADDR'])) : '';
93 + $headers = ['HTTP_CLIENT_IP', 'HTTP_X_FORWARDED_FOR', 'HTTP_X_FORWARDED', 'HTTP_FORWARDED_FOR', 'HTTP_FORWARDED'];
94 + foreach ($headers as $header) {
95 + $ip = IpTool::extractValidIp(getenv($header));
96 + if ('' !== $ip) {
97 + return $ip;
98 + }
65 99 }
66 - return IpTool::validateIpAddress($ip);
100 +
101 + return IpTool::extractValidIp(isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : '');
67 102 }
68 103
69 104 /**
70 105 * Check device info
@@ -307,9 +342,9 @@
307 342 */
308 343 private static function _setUserDetail()
309 344 {
310 345 $referer = wp_get_referer();
311 - $user_details['ip'] = IpTool::ip2Number(IpTool::_checkIP());
346 + $user_details['ip'] = IpTool::storageValue(IpTool::_checkIP());
312 347 $user_details['device'] = IpTool::_checkDevice();
313 348 $user_details['id'] = get_current_user_id();
314 349 $user_details['page'] = $referer ? $referer : '';
315 350 $user_details['time'] = current_time('mysql');
@@ -319,9 +354,9 @@
319 354
320 355 /**
321 356 * Provide user details
322 357 *
323 - * @return _setUserDetail user details array
358 + * @return array user details array
324 359 */
325 360 public static function getUserDetail()
326 361 {
327 362 return IpTool::_setUserDetail();
@@ -329,9 +364,9 @@
329 364
330 365 /**
331 366 * Provide user IP address
332 367 *
333 - * @return ip
368 + * @return string IP address, or ''
334 369 */
335 370 public static function getIP()
336 371 {
337 372 return IpTool::_checkIP();