PocketMine-MP 5.27.1 git-9af3cde03fabbe4129c79e46dc87ffa0fff446e6
Loading...
Searching...
No Matches
Internet.php
1<?php
2
3/*
4 *
5 * ____ _ _ __ __ _ __ __ ____
6 * | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
7 * | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
8 * | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
9 * |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
10 *
11 * This program is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License as published by
13 * the Free Software Foundation, either version 3 of the License, or
14 * (at your option) any later version.
15 *
16 * @author PocketMine Team
17 * @link http://www.pocketmine.net/
18 *
19 *
20 */
21
22declare(strict_types=1);
23
24namespace pocketmine\utils;
25
27use function array_merge;
28use function curl_close;
29use function curl_error;
30use function curl_exec;
31use function curl_getinfo;
32use function curl_init;
33use function curl_setopt_array;
34use function explode;
35use function is_string;
36use function preg_match;
37use function socket_close;
38use function socket_connect;
39use function socket_create;
40use function socket_getsockname;
41use function socket_last_error;
42use function socket_strerror;
43use function strip_tags;
44use function strtolower;
45use function substr;
46use function trim;
47use const AF_INET;
48use const CURLINFO_HEADER_SIZE;
49use const CURLINFO_HTTP_CODE;
50use const CURLOPT_AUTOREFERER;
51use const CURLOPT_CONNECTTIMEOUT_MS;
52use const CURLOPT_FOLLOWLOCATION;
53use const CURLOPT_FORBID_REUSE;
54use const CURLOPT_FRESH_CONNECT;
55use const CURLOPT_HEADER;
56use const CURLOPT_HTTPHEADER;
57use const CURLOPT_POST;
58use const CURLOPT_POSTFIELDS;
59use const CURLOPT_RETURNTRANSFER;
60use const CURLOPT_SSL_VERIFYHOST;
61use const CURLOPT_SSL_VERIFYPEER;
62use const CURLOPT_TIMEOUT_MS;
63use const PHP_INT_MAX;
64use const SOCK_DGRAM;
65use const SOL_UDP;
66
68 public static string|false $ip = false;
69 public static bool $online = true;
70
76 public static function getIP(bool $force = false) : string|false{
77 if(!self::$online){
78 return false;
79 }elseif(self::$ip !== false && !$force){
80 return self::$ip;
81 }
82
83 $ip = self::getURL("http://api.ipify.org/");
84 if($ip !== null){
85 return self::$ip = $ip->getBody();
86 }
87
88 $ip = self::getURL("http://checkip.dyndns.org/");
89 if($ip !== null && preg_match('#Current IP Address\: ([0-9a-fA-F\:\.]*)#', trim(strip_tags($ip->getBody())), $matches) > 0){
90 return self::$ip = $matches[1];
91 }
92
93 $ip = self::getURL("http://www.checkip.org/");
94 if($ip !== null && preg_match('#">([0-9a-fA-F\:\.]*)</span>#', $ip->getBody(), $matches) > 0){
95 return self::$ip = $matches[1];
96 }
97
98 $ip = self::getURL("http://checkmyip.org/");
99 if($ip !== null && preg_match('#Your IP address is ([0-9a-fA-F\:\.]*)#', $ip->getBody(), $matches) > 0){
100 return self::$ip = $matches[1];
101 }
102
103 $ip = self::getURL("http://ifconfig.me/ip");
104 if($ip !== null && ($addr = trim($ip->getBody())) !== ""){
105 return self::$ip = $addr;
106 }
107
108 return false;
109 }
110
117 public static function getInternalIP() : string{
118 $sock = @socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
119 if($sock === false){
120 throw new InternetException("Failed to get internal IP: " . trim(socket_strerror(socket_last_error())));
121 }
122 try{
123 if(!@socket_connect($sock, "8.8.8.8", 65534)){
124 throw new InternetException("Failed to get internal IP: " . trim(socket_strerror(socket_last_error($sock))));
125 }
126 if(!@socket_getsockname($sock, $name)){
127 throw new InternetException("Failed to get internal IP: " . trim(socket_strerror(socket_last_error($sock))));
128 }
129 return $name;
130 }finally{
131 socket_close($sock);
132 }
133 }
134
148 public static function getURL(string $page, int $timeout = 10, array $extraHeaders = [], &$err = null) : ?InternetRequestResult{
149 try{
150 return self::simpleCurl($page, $timeout, $extraHeaders);
151 }catch(InternetException $ex){
152 $err = $ex->getMessage();
153 return null;
154 }
155 }
156
171 public static function postURL(string $page, array|string $args, int $timeout = 10, array $extraHeaders = [], &$err = null) : ?InternetRequestResult{
172 try{
173 return self::simpleCurl($page, $timeout, $extraHeaders, [
174 CURLOPT_POST => 1,
175 CURLOPT_POSTFIELDS => $args
176 ]);
177 }catch(InternetException $ex){
178 $err = $ex->getMessage();
179 return null;
180 }
181 }
182
197 public static function simpleCurl(string $page, float $timeout = 10, array $extraHeaders = [], array $extraOpts = [], ?\Closure $onSuccess = null) : InternetRequestResult{
198 if(!self::$online){
199 throw new InternetException("Cannot execute web request while offline");
200 }
201
202 $ch = curl_init($page);
203 if($ch === false){
204 throw new InternetException("Unable to create new cURL session");
205 }
206
207 curl_setopt_array($ch, $extraOpts + [
208 CURLOPT_SSL_VERIFYPEER => false,
209 CURLOPT_SSL_VERIFYHOST => 2,
210 CURLOPT_FORBID_REUSE => 1,
211 CURLOPT_FRESH_CONNECT => 1,
212 CURLOPT_AUTOREFERER => true,
213 CURLOPT_FOLLOWLOCATION => true,
214 CURLOPT_RETURNTRANSFER => true,
215 CURLOPT_CONNECTTIMEOUT_MS => (int) ($timeout * 1000),
216 CURLOPT_TIMEOUT_MS => (int) ($timeout * 1000),
217 CURLOPT_HTTPHEADER => array_merge(["User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:12.0) Gecko/20100101 Firefox/12.0 " . VersionInfo::NAME . "/" . VersionInfo::VERSION()->getFullVersion(true)], $extraHeaders),
218 CURLOPT_HEADER => true
219 ]);
220 try{
221 $raw = curl_exec($ch);
222 if($raw === false){
223 throw new InternetException(curl_error($ch));
224 }
225 if(!is_string($raw)) throw new AssumptionFailedError("curl_exec() should return string|false when CURLOPT_RETURNTRANSFER is set");
226 $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
227 $headerSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
228 $rawHeaders = substr($raw, 0, $headerSize);
229 $body = substr($raw, $headerSize);
230 $headers = [];
231 //TODO: explore if we can set these limits lower
232 foreach(explode("\r\n\r\n", $rawHeaders, limit: PHP_INT_MAX) as $rawHeaderGroup){
233 $headerGroup = [];
234 foreach(explode("\r\n", $rawHeaderGroup, limit: PHP_INT_MAX) as $line){
235 $nameValue = explode(":", $line, 2);
236 if(isset($nameValue[1])){
237 $headerGroup[trim(strtolower($nameValue[0]))] = trim($nameValue[1]);
238 }
239 }
240 $headers[] = $headerGroup;
241 }
242 if($onSuccess !== null){
243 $onSuccess($ch);
244 }
245 return new InternetRequestResult($headers, $body, $httpCode);
246 }finally{
247 curl_close($ch);
248 }
249 }
250}
static getIP(bool $force=false)
Definition Internet.php:76
static simpleCurl(string $page, float $timeout=10, array $extraHeaders=[], array $extraOpts=[], ?\Closure $onSuccess=null)
Definition Internet.php:197
static getURL(string $page, int $timeout=10, array $extraHeaders=[], &$err=null)
Definition Internet.php:148
static postURL(string $page, array|string $args, int $timeout=10, array $extraHeaders=[], &$err=null)
Definition Internet.php:171