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
bit-form / includes / Core / Util / IpTool.php

IpTool.php in Bit Form – Contact Form, Payment Forms, Multi Step Forms, Calculator & Custom Form Builder V3.3.2, at includes/Core/Util/IpTool.php

375 lines 12.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * Provides IP related functionality
5 */
6
7 namespace BitCode\BitForm\Core\Util;
8
9 final class IpTool
10 {
11 /**
12 * Check ip address
13 *
14 * @return string IP address of current visitor
15 */
16
17 /**
18 * Stored form of an IP: IPv4 as unsigned number (existing rows), IPv6 as text (numeric form was lossy).
19 *
20 * @param mixed $ip IP address
21 *
22 * @return string '' when $ip is not a valid address
23 */
24 public static function storageValue($ip)
25 {
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);
33
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 '';
49 }
50 if (ctype_digit($stored)) {
51 return (strlen($stored) <= 10 && (float) $stored <= 4294967295) ? long2ip((int) $stored) : '';
52 }
53
54 return false === filter_var($stored, FILTER_VALIDATE_IP) ? '' : $stored;
55 }
56
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)
65 {
66 if (!is_string($value) || '' === $value) {
67 return '';
68 }
69
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 }
86 }
87
88 return '';
89 }
90
91 private static function _checkIP()
92 {
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 }
99 }
100
101 return IpTool::extractValidIp(isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : '');
102 }
103
104 /**
105 * Check device info
106 *
107 * @return void
108 */
109 private static function _checkDevice()
110 {
111 if (isset($_SERVER, $_SERVER['HTTP_USER_AGENT'])) {
112 $user_agent = sanitize_text_field(wp_unslash($_SERVER['HTTP_USER_AGENT']));
113 } else {
114 $user_agent = '';
115 }
116 return IpTool::_getBrowserName($user_agent) . '|' . IpTool::_getOS($user_agent);
117 }
118
119 /**
120 * Get browser name
121 *
122 * @link https://stackoverflow.com/questions/18070154/get-operating-system-info
123 *
124 * @param string $user_agent $_SERVER['HTTP_USER_AGENT']
125 *
126 * @return void
127 */
128 private static function _getBrowserName($user_agent)
129 {
130 // Make case insensitive.
131 $t = strtolower($user_agent);
132
133 // If the string *starts* with the string, strpos returns 0 (i.e., FALSE). Do a ghetto hack and start with a space.
134 // "[strpos()] may return Boolean FALSE, but may also return a non-Boolean value which evaluates to FALSE."
135 // http://php.net/manual/en/function.strpos.php
136 $t = ' ' . $t;
137
138 // Humans / Regular Users
139 if (strpos($t, 'opera') || strpos($t, 'opr/')) {
140 return 'Opera';
141 } elseif (strpos($t, 'edge')) {
142 return 'Edge';
143 } elseif (strpos($t, 'Edg')) {
144 return 'Edge';
145 } elseif (strpos($t, 'chrome')) {
146 return 'Chrome';
147 } elseif (strpos($t, 'safari')) {
148 return 'Safari';
149 } elseif (strpos($t, 'firefox')) {
150 return 'Firefox';
151 } elseif (strpos($t, 'msie') || strpos($t, 'trident/7')) {
152 return 'Internet Explorer';
153 } elseif (strpos($t, 'google')) {
154 return 'Googlebot';
155 } elseif (strpos($t, 'bing')) {
156 return 'Bingbot';
157 } elseif (strpos($t, 'slurp')) {
158 return 'Yahoo! Slurp';
159 } elseif (strpos($t, 'duckduckgo')) {
160 return 'DuckDuckBot';
161 } elseif (strpos($t, 'baidu')) {
162 return 'Baidu';
163 } elseif (strpos($t, 'yandex')) {
164 return 'Yandex';
165 } elseif (strpos($t, 'sogou')) {
166 return 'Sogou';
167 } elseif (strpos($t, 'exabot')) {
168 return 'Exabot';
169 } elseif (strpos($t, 'msn')) {
170 return 'MSN';
171 }
172
173 // Common Tools and Bots
174 elseif (strpos($t, 'mj12bot')) {
175 return 'Majestic';
176 } elseif (strpos($t, 'ahrefs')) {
177 return 'Ahrefs';
178 } elseif (strpos($t, 'semrush')) {
179 return 'SEMRush';
180 } elseif (strpos($t, 'rogerbot') || strpos($t, 'dotbot')) {
181 return 'Moz';
182 } elseif (strpos($t, 'frog') || strpos($t, 'screaming')) {
183 return 'Screaming Frog';
184 } elseif (strpos($t, 'facebook')) {
185 return 'Facebook';
186 } elseif (strpos($t, 'pinterest')) {
187 return 'Pinterest';
188 } elseif (
189 strpos($t, 'crawler') || strpos($t, 'api')
190 || strpos($t, 'spider') || strpos($t, 'http')
191 || strpos($t, 'bot') || strpos($t, 'archive')
192 || strpos($t, 'info') || strpos($t, 'data')
193 ) {
194 return 'Bot';
195 }
196
197 return 'Other (Unknown)';
198 }
199
200 /**
201 * Provide Operating System Information of User
202 *
203 * @link https://stackoverflow.com/questions/18070154/get-operating-system-info
204 *
205 * @return void
206 */
207 private static function _getOS($user_agent)
208 {
209 $ros[] = ['Windows XP', 'Windows XP', false];
210 $ros[] = ['Windows NT 5.1|Windows NT5.1', 'Windows XP', true];
211 $ros[] = ['Windows 2000', 'Windows 2000', false];
212 $ros[] = ['Windows NT 5.0', 'Windows 2000', false];
213 $ros[] = ['Windows NT 4.0|WinNT4.0', 'Windows NT', true];
214 $ros[] = ['Windows NT 5.2', 'Windows Server 2003', false];
215 $ros[] = ['Windows NT 6.0', 'Windows Vista', false];
216 $ros[] = ['Windows NT 7.0', 'Windows 7', false];
217 $ros[] = ['Windows CE', 'Windows CE', false];
218 $ros[] = ['(media center pc).([0-9]{1,2}\.[0-9]{1,2})', 'Windows Media Center', true];
219 $ros[] = ['(win)([0-9]{1,2}\.[0-9x]{1,2})', 'Windows', true];
220 $ros[] = ['(win)([0-9]{2})', 'Windows', true];
221 $ros[] = ['(windows)([0-9x]{2})', 'Windows', true];
222 // Doesn't seem like these are necessary...not totally sure though..
223 //$ros[] = array('(winnt)([0-9]{1,2}\.[0-9]{1,2}){0,1}', 'Windows NT');
224 //$ros[] = array('(windows nt)(([0-9]{1,2}\.[0-9]{1,2}){0,1})', 'Windows NT'); // fix by bg
225 $ros[] = ['Windows ME', 'Windows ME', false];
226 $ros[] = ['Win 9x 4.90', 'Windows ME', false];
227 $ros[] = ['Windows 98|Win98', 'Windows 98', true];
228 $ros[] = ['Windows 95', 'Windows 95', false];
229 $ros[] = ['(windows)([0-9]{1,2}\.[0-9]{1,2})', 'Windows', true];
230 $ros[] = ['win32', 'Windows', false];
231 $ros[] = ['(java)([0-9]{1,2}\.[0-9]{1,2}\.[0-9]{1,2})', 'Java', true];
232 $ros[] = ['(Solaris)([0-9]{1,2}\.[0-9x]{1,2}){0,1}', 'Solaris', true];
233 $ros[] = ['dos x86', 'DOS', false];
234 $ros[] = ['unix', 'Unix', false];
235 //Android
236 $ros[] = ['SM', 'Samsung', false];
237 $ros[] = ['HTC', 'HTC', false];
238 $ros[] = ['LG', 'LG', false];
239 $ros[] = ['Microsoft', 'Microsoft', false];
240 $ros[] = ['Pixel', 'Pixel', false];
241 $ros[] = ['MI', 'Xiaomi', false];
242 $ros[] = ['Xiaomi', 'Xiaomi', false];
243 $ros[] = ['Android', 'Android', false];
244 $ros[] = ['android', 'Android', false];
245
246 //iPhone
247 $ros[] = ['iPhone', 'iPhone', false];
248
249 $ros[] = ['Mac OS X', 'Mac OS X', false];
250 $ros[] = ['Mac OS X Puma', 'Mac OS X 10.1[^0-9]', true];
251 $ros[] = ['Mac_PowerPC', 'Macintosh PowerPC', false];
252 $ros[] = ['(mac|Macintosh)', 'Mac OS', true];
253 $ros[] = ['(sunos)([0-9]{1,2}\.[0-9]{1,2}){0,1}', 'SunOS', true];
254 $ros[] = ['(beos)([0-9]{1,2}\.[0-9]{1,2}){0,1}', 'BeOS', true];
255 $ros[] = ['(risc os)([0-9]{1,2}\.[0-9]{1,2})', 'RISC OS', true];
256 $ros[] = ['os\/2', 'OS/2', true];
257 $ros[] = ['freebsd', 'FreeBSD', false];
258 $ros[] = ['openbsd', 'OpenBSD', false];
259 $ros[] = ['netbsd', 'NetBSD', false];
260 $ros[] = ['irix', 'IRIX', false];
261 $ros[] = ['plan9', 'Plan9', false];
262 $ros[] = ['osf', 'OSF', false];
263 $ros[] = ['aix', 'AIX', false];
264 $ros[] = ['GNU Hurd', 'GNU Hurd', false];
265 $ros[] = ['(fedora)', 'Linux - Fedora', true];
266 $ros[] = ['(kubuntu)', 'Linux - Kubuntu', true];
267 $ros[] = ['(ubuntu)', 'Linux - Ubuntu', true];
268 $ros[] = ['(debian)', 'Linux - Debian', true];
269 $ros[] = ['(CentOS)', 'Linux - CentOS', true];
270 $ros[] = ['(Mandriva).([0-9]{1,3}(\.[0-9]{1,3})?(\.[0-9]{1,3})?)', 'Linux - Mandriva', true];
271 $ros[] = ['(SUSE).([0-9]{1,3}(\.[0-9]{1,3})?(\.[0-9]{1,3})?)', 'Linux - SUSE', true];
272 $ros[] = ['(Dropline)', 'Linux - Slackware (Dropline GNOME)', true];
273 $ros[] = ['(ASPLinux)', 'Linux - ASPLinux', true];
274 $ros[] = ['(Red Hat)', 'Linux - Red Hat', true];
275 // Loads of Linux machines will be detected as unix.
276 // Actually, all of the linux machines I've checked have the 'X11' in the User Agent.
277 //$ros[] = array('X11', 'Unix');
278 $ros[] = ['(linux)', 'Linux', true];
279 $ros[] = ['(amigaos)([0-9]{1,2}\.[0-9]{1,2})', 'AmigaOS', true];
280 $ros[] = ['amiga-aweb', 'AmigaOS', false];
281 $ros[] = ['amiga', 'Amiga', false];
282 $ros[] = ['AvantGo', 'PalmOS', false];
283 //$ros[] = array('(Linux)([0-9]{1,2}\.[0-9]{1,2}\.[0-9]{1,3}(rel\.[0-9]{1,2}){0,1}-([0-9]{1,2}) i([0-9]{1})86){1}', 'Linux');
284 //$ros[] = array('(Linux)([0-9]{1,2}\.[0-9]{1,2}\.[0-9]{1,3}(rel\.[0-9]{1,2}){0,1} i([0-9]{1}86)){1}', 'Linux');
285 //$ros[] = array('(Linux)([0-9]{1,2}\.[0-9]{1,2}\.[0-9]{1,3}(rel\.[0-9]{1,2}){0,1})', 'Linux');
286 $ros[] = ['[0-9]{1,2}\.[0-9]{1,2}\.[0-9]{1,3}', 'Linux', true];
287 $ros[] = ['(webtv)/([0-9]{1,2}\.[0-9]{1,2})', 'WebTV', true];
288 $ros[] = ['Dreamcast', 'Dreamcast OS', false];
289 $ros[] = ['GetRight', 'Windows', false];
290 $ros[] = ['go!zilla', 'Windows', false];
291 $ros[] = ['gozilla', 'Windows', false];
292 $ros[] = ['gulliver', 'Windows', false];
293 $ros[] = ['ia archiver', 'Windows', false];
294 $ros[] = ['NetPositive', 'Windows', false];
295 $ros[] = ['mass downloader', 'Windows', false];
296 $ros[] = ['microsoft', 'Windows', false];
297 $ros[] = ['offline explorer', 'Windows', false];
298 $ros[] = ['teleport', 'Windows', false];
299 $ros[] = ['web downloader', 'Windows', false];
300 $ros[] = ['webcapture', 'Windows', false];
301 $ros[] = ['webcollage', 'Windows', false];
302 $ros[] = ['webcopier', 'Windows', false];
303 $ros[] = ['webstripper', 'Windows', false];
304 $ros[] = ['webzip', 'Windows', false];
305 $ros[] = ['wget', 'Windows', false];
306 $ros[] = ['Java', 'Unknown', false];
307 $ros[] = ['flashget', 'Windows', false];
308 // delete next line if the script show not the right OS
309 //$ros[] = array('(PHP)/([0-9]{1,2}.[0-9]{1,2})', 'PHP');
310 $ros[] = ['MS FrontPage', 'Windows', false];
311 $ros[] = ['(msproxy)/([0-9]{1,2}\.[0-9]{1,2})', 'Windows', true];
312 $ros[] = ['(msie)([0-9]{1,2}\.[0-9]{1,2})', 'Windows', true];
313 $ros[] = ['libwww-perl', 'Unix', false];
314 $ros[] = ['UP.Browser', 'Windows CE', false];
315 $ros[] = ['NetAnts', 'Windows', false];
316 $ros[] = ['Android', 'Android', false];
317 $file = count($ros);
318 $os = '';
319 for ($n = 0; $n < $file; $n++) {
320 $isRegex = isset($ros[$n][2]) && true === $ros[$n][2];
321 $pattern = $ros[$n][0];
322
323 if ($isRegex) {
324 if (@preg_match('/' . $pattern . '/i', $user_agent)) {
325 $os = $ros[$n][1];
326 break;
327 }
328 } else {
329 if (false !== stripos($user_agent, $pattern)) {
330 $os = $ros[$n][1];
331 break;
332 }
333 }
334 }
335 return trim($os);
336 }
337
338 /**
339 * Set user details ip,cdevice, user_id, user's visited page, current mysql formatted time
340 *
341 * @return array of user details
342 */
343 private static function _setUserDetail()
344 {
345 $referer = wp_get_referer();
346 $user_details['ip'] = IpTool::storageValue(IpTool::_checkIP());
347 $user_details['device'] = IpTool::_checkDevice();
348 $user_details['id'] = get_current_user_id();
349 $user_details['page'] = $referer ? $referer : '';
350 $user_details['time'] = current_time('mysql');
351
352 return $user_details;
353 }
354
355 /**
356 * Provide user details
357 *
358 * @return array user details array
359 */
360 public static function getUserDetail()
361 {
362 return IpTool::_setUserDetail();
363 }
364
365 /**
366 * Provide user IP address
367 *
368 * @return string IP address, or ''
369 */
370 public static function getIP()
371 {
372 return IpTool::_checkIP();
373 }
374 }
375