mirror of
https://github.com/YGGverse/net-php.git
synced 2026-03-31 17:15:35 +00:00
Compare commits
24 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5ae447bcf0 | ||
|
|
b28658d041 | ||
|
|
9524c8fdec | ||
|
|
0079e2a755 | ||
|
|
0acff609f4 | ||
|
|
4f369bac45 | ||
|
|
7c918ff99c | ||
|
|
5e17d40245 | ||
|
|
27bf47ec0d | ||
|
|
b37f28ce4f | ||
|
|
f6a3b1bbfa | ||
|
|
18ec72362e | ||
|
|
d3bea00b02 | ||
|
|
38f33eb584 | ||
|
|
96cd4163be | ||
|
|
1e5b42d407 | ||
|
|
a57028f609 | ||
|
|
16f90cb23b | ||
|
|
92eb9b3ba2 | ||
|
|
3329a90819 | ||
|
|
bbdc276db6 | ||
|
|
b2e0750d1e | ||
|
|
fc2b0822af | ||
|
|
c602ad503f |
5 changed files with 852 additions and 16 deletions
182
README.md
182
README.md
|
|
@ -12,7 +12,7 @@ Network Library for PHP with native Yggdrasil support
|
||||||
|
|
||||||
#### Check socket is open
|
#### Check socket is open
|
||||||
|
|
||||||
```
|
``` php
|
||||||
var_dump(
|
var_dump(
|
||||||
\Yggverse\Net\Socket::isOpen('yo.index', 80)
|
\Yggverse\Net\Socket::isOpen('yo.index', 80)
|
||||||
);
|
);
|
||||||
|
|
@ -20,7 +20,7 @@ var_dump(
|
||||||
|
|
||||||
#### Check host valid
|
#### Check host valid
|
||||||
|
|
||||||
```
|
``` php
|
||||||
var_dump(
|
var_dump(
|
||||||
\Yggverse\Net\Socket::isHost('yo.index')
|
\Yggverse\Net\Socket::isHost('yo.index')
|
||||||
);
|
);
|
||||||
|
|
@ -28,7 +28,7 @@ var_dump(
|
||||||
|
|
||||||
#### Check port valid
|
#### Check port valid
|
||||||
|
|
||||||
```
|
``` php
|
||||||
var_dump(
|
var_dump(
|
||||||
\Yggverse\Net\Socket::isPort(80)
|
\Yggverse\Net\Socket::isPort(80)
|
||||||
);
|
);
|
||||||
|
|
@ -38,15 +38,15 @@ var_dump(
|
||||||
|
|
||||||
#### Resolve records
|
#### Resolve records
|
||||||
|
|
||||||
```
|
``` php
|
||||||
var_dump(
|
var_dump(
|
||||||
\Yggverse\Net\Dig::records('yo.index', ['A', 'AAAA'])
|
\Yggverse\Net\Dig::records('yo.index', ['A', 'AAAA'], &$result = [], &$error = [], $provider = null, $timeout = 5)
|
||||||
);
|
);
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Check hostname valid
|
#### Check hostname valid
|
||||||
|
|
||||||
```
|
``` php
|
||||||
var_dump(
|
var_dump(
|
||||||
\Yggverse\Net\Dig::isHostName('yo.index')
|
\Yggverse\Net\Dig::isHostName('yo.index')
|
||||||
);
|
);
|
||||||
|
|
@ -54,7 +54,7 @@ var_dump(
|
||||||
|
|
||||||
#### Check record valid
|
#### Check record valid
|
||||||
|
|
||||||
```
|
``` php
|
||||||
var_dump(
|
var_dump(
|
||||||
\Yggverse\Net\Dig::isRecord('A')
|
\Yggverse\Net\Dig::isRecord('A')
|
||||||
);
|
);
|
||||||
|
|
@ -62,8 +62,172 @@ var_dump(
|
||||||
|
|
||||||
#### Check record value valid
|
#### Check record value valid
|
||||||
|
|
||||||
```
|
``` php
|
||||||
var_dump(
|
var_dump(
|
||||||
\Yggverse\Net\Dig::isRecordValue('A', '127.0.0.1')
|
\Yggverse\Net\Dig::isRecordValue('A', '127.0.0.1')
|
||||||
);
|
);
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Resolve
|
||||||
|
|
||||||
|
#### Init resolver
|
||||||
|
|
||||||
|
``` php
|
||||||
|
$resolve = new \Yggverse\Net\Resolve(
|
||||||
|
[
|
||||||
|
'A',
|
||||||
|
'AAAA'
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'1.1.1.1',
|
||||||
|
'8.8.8.8'
|
||||||
|
],
|
||||||
|
// ..
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Get resolved URL string
|
||||||
|
|
||||||
|
``` php
|
||||||
|
$resolved = $resolve->url(
|
||||||
|
'https://en.wikipedia.org/wiki/Domain_Name_System'
|
||||||
|
// next arguments contain debug variables and new address object
|
||||||
|
);
|
||||||
|
|
||||||
|
if ($resolved)
|
||||||
|
{
|
||||||
|
var_dump(
|
||||||
|
$resolved // https://185.15.59.224/wiki/Domain_Name_System
|
||||||
|
);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Resolve Address object
|
||||||
|
|
||||||
|
``` php
|
||||||
|
$resolved = $resolve->address(
|
||||||
|
new \Yggverse\Net\Address(
|
||||||
|
'https://en.wikipedia.org/wiki/Domain_Name_System'
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
if ($resolved)
|
||||||
|
{
|
||||||
|
var_dump(
|
||||||
|
$resolved->get() // https://185.15.59.224/wiki/Domain_Name_System
|
||||||
|
);
|
||||||
|
|
||||||
|
var_dump(
|
||||||
|
$resolved->getHost() // 185.15.59.224
|
||||||
|
);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Address
|
||||||
|
|
||||||
|
Includes methods to work with network addresses.
|
||||||
|
|
||||||
|
#### Base address methods
|
||||||
|
|
||||||
|
Different operations with address parts:
|
||||||
|
|
||||||
|
* `scheme`
|
||||||
|
* `user`
|
||||||
|
* `password`
|
||||||
|
* `host`
|
||||||
|
* `protocol`
|
||||||
|
* `path`
|
||||||
|
* `query`
|
||||||
|
* `fragment`
|
||||||
|
|
||||||
|
#### Address conversion from relative to absolute format
|
||||||
|
|
||||||
|
**Document root**
|
||||||
|
|
||||||
|
``` php
|
||||||
|
$base = new \Yggverse\Net\Address(
|
||||||
|
'http://yo.ygg/a1/b1/c1'
|
||||||
|
);
|
||||||
|
|
||||||
|
$address = new \Yggverse\Net\Address(
|
||||||
|
'/a2'
|
||||||
|
);
|
||||||
|
|
||||||
|
var_dump(
|
||||||
|
$address->getAbsolute(
|
||||||
|
$base
|
||||||
|
) // return http://yo.ygg/a2
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
**Current folder**
|
||||||
|
|
||||||
|
``` php
|
||||||
|
$base = new \Yggverse\Net\Address(
|
||||||
|
'http://yo.ygg/a1/b1/c1'
|
||||||
|
);
|
||||||
|
|
||||||
|
$address = new \Yggverse\Net\Address(
|
||||||
|
'c2'
|
||||||
|
);
|
||||||
|
|
||||||
|
var_dump(
|
||||||
|
$address->getAbsolute(
|
||||||
|
$base
|
||||||
|
) // return http://yo.ygg/a1/b1/c2
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
**Ending slash**
|
||||||
|
|
||||||
|
``` php
|
||||||
|
$base = new \Yggverse\Net\Address(
|
||||||
|
'http://yo.ygg/a1/b1/c1/'
|
||||||
|
);
|
||||||
|
|
||||||
|
$address = new \Yggverse\Net\Address(
|
||||||
|
'../../b2/c2'
|
||||||
|
);
|
||||||
|
|
||||||
|
var_dump(
|
||||||
|
$address->getAbsolute(
|
||||||
|
$base
|
||||||
|
) // return http://yo.ygg/a1/b2/c2
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
**All options**
|
||||||
|
|
||||||
|
``` php
|
||||||
|
$base = new \Yggverse\Net\Address(
|
||||||
|
'http://user:password@yo.ygg/a1/b1/c1?attribute=value#anchor'
|
||||||
|
);
|
||||||
|
|
||||||
|
$address = new \Yggverse\Net\Address(
|
||||||
|
'../../a2/b2?attribute2=value2#anchor2'
|
||||||
|
);
|
||||||
|
|
||||||
|
var_dump(
|
||||||
|
$address->getAbsolute(
|
||||||
|
$base
|
||||||
|
) // return http://user:password@yo.ygg/a2/b2?attribute2=value2#anchor2
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
### Valid
|
||||||
|
|
||||||
|
Network entities validation
|
||||||
|
|
||||||
|
**Supported methods**
|
||||||
|
|
||||||
|
* `Valid::ip`
|
||||||
|
* `Valid::ip4`
|
||||||
|
* `Valid::ip6`
|
||||||
|
* `Valid::domainHostName`
|
||||||
|
|
||||||
|
## Integrations
|
||||||
|
|
||||||
|
* [gemini-dl](https://github.com/YGGverse/gemini-dl) - CLI batch downloader for Gemini protocol
|
||||||
|
* [web-api](https://github.com/YGGverse/web-api) - Network API with native Yggdrasil/IPv6 support
|
||||||
|
* [Yo!](https://github.com/YGGverse/Yo) - Crawler and search engine for different networks
|
||||||
|
* [Yoda](https://github.com/YGGverse/Yoda) - Experimental PHP-GTK browser for Gemini protocol
|
||||||
|
|
|
||||||
401
src/Address.php
Normal file
401
src/Address.php
Normal file
|
|
@ -0,0 +1,401 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Yggverse\Net;
|
||||||
|
|
||||||
|
class Address
|
||||||
|
{
|
||||||
|
private ?string $_scheme = null;
|
||||||
|
private ?string $_host = null;
|
||||||
|
private ?string $_user = null;
|
||||||
|
private ?string $_pass = null;
|
||||||
|
private ?int $_port = null;
|
||||||
|
private ?string $_path = null;
|
||||||
|
private ?string $_query = null;
|
||||||
|
private ?string $_fragment = null;
|
||||||
|
|
||||||
|
private string $_separator = '/';
|
||||||
|
|
||||||
|
private array $_segments = [];
|
||||||
|
|
||||||
|
public function __construct(?string $address = null)
|
||||||
|
{
|
||||||
|
if ($address)
|
||||||
|
{
|
||||||
|
if ($scheme = parse_url($address, PHP_URL_SCHEME))
|
||||||
|
{
|
||||||
|
$this->setScheme(
|
||||||
|
(string) $scheme
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($user = parse_url($address, PHP_URL_USER))
|
||||||
|
{
|
||||||
|
$this->setUser(
|
||||||
|
(string) $user
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($pass = parse_url($address, PHP_URL_PASS))
|
||||||
|
{
|
||||||
|
$this->setPass(
|
||||||
|
(string) $pass
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($host = parse_url($address, PHP_URL_HOST))
|
||||||
|
{
|
||||||
|
$this->setHost(
|
||||||
|
(string) $host
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($port = parse_url($address, PHP_URL_PORT))
|
||||||
|
{
|
||||||
|
$this->setPort(
|
||||||
|
(int) $port
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($path = parse_url($address, PHP_URL_PATH))
|
||||||
|
{
|
||||||
|
$this->setPath(
|
||||||
|
(string) $path
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($query = parse_url($address, PHP_URL_QUERY))
|
||||||
|
{
|
||||||
|
$this->setQuery(
|
||||||
|
(string) $query
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($fragment = parse_url($address, PHP_URL_FRAGMENT))
|
||||||
|
{
|
||||||
|
$this->setFragment(
|
||||||
|
(string) $fragment
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isAbsolute(): bool
|
||||||
|
{
|
||||||
|
return boolval(
|
||||||
|
$this->_scheme || $this->_host
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isRelative(): bool
|
||||||
|
{
|
||||||
|
return !$this->isAbsolute();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getScheme(): ?string
|
||||||
|
{
|
||||||
|
return $this->_scheme;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setScheme(?string $value): void
|
||||||
|
{
|
||||||
|
$this->_scheme = $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getHost(): ?string
|
||||||
|
{
|
||||||
|
return $this->_host;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setHost(?string $value): void
|
||||||
|
{
|
||||||
|
$this->_host = $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getUser(): ?string
|
||||||
|
{
|
||||||
|
return $this->_user;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setUser(?string $value): void
|
||||||
|
{
|
||||||
|
$this->_user = $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPass(): ?string
|
||||||
|
{
|
||||||
|
return $this->_pass;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setPass(?string $value): void
|
||||||
|
{
|
||||||
|
$this->_pass = $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPort(): ?int
|
||||||
|
{
|
||||||
|
return $this->_port;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setPort(?int $value): void
|
||||||
|
{
|
||||||
|
$this->_port = $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPath(): ?string
|
||||||
|
{
|
||||||
|
return $this->_path;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setPath(?string $value): void
|
||||||
|
{
|
||||||
|
if (false !== strpos($value, '\\'))
|
||||||
|
{
|
||||||
|
$this->setSeparator(
|
||||||
|
'\\'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->_segments = explode(
|
||||||
|
$this->_separator,
|
||||||
|
$value
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->_path = $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getSegments(): array
|
||||||
|
{
|
||||||
|
return $this->_segments;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getQuery(): ?string
|
||||||
|
{
|
||||||
|
return $this->_query;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setQuery(?string $value): void
|
||||||
|
{
|
||||||
|
$this->_query = $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFragment(): ?string
|
||||||
|
{
|
||||||
|
return $this->_fragment;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setFragment(?string $value): void
|
||||||
|
{
|
||||||
|
$this->_fragment = $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getSeparator(): string
|
||||||
|
{
|
||||||
|
return $this->_separator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setSeparator(?string $value): void
|
||||||
|
{
|
||||||
|
$this->_separator = $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function get(
|
||||||
|
bool $scheme = true,
|
||||||
|
bool $user = true,
|
||||||
|
bool $pass = true,
|
||||||
|
bool $host = true,
|
||||||
|
bool $port = true,
|
||||||
|
bool $path = true,
|
||||||
|
bool $query = true,
|
||||||
|
bool $fragment = true,
|
||||||
|
): string
|
||||||
|
{
|
||||||
|
$address = '';
|
||||||
|
|
||||||
|
if ($scheme && $this->getScheme())
|
||||||
|
{
|
||||||
|
$address .= sprintf(
|
||||||
|
'%s:%s%s',
|
||||||
|
$this->getScheme(),
|
||||||
|
$this->getSeparator(),
|
||||||
|
$this->getSeparator()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($user && $this->getUser())
|
||||||
|
{
|
||||||
|
if ($pass && $this->getPass())
|
||||||
|
{
|
||||||
|
$address .= sprintf(
|
||||||
|
'%s:%s@',
|
||||||
|
$this->getUser(),
|
||||||
|
$this->getPass()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$address .= sprintf(
|
||||||
|
'%s@',
|
||||||
|
$this->getUser()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($host && $this->getHost())
|
||||||
|
{
|
||||||
|
$address .= $this->getHost();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($port && $this->getPort())
|
||||||
|
{
|
||||||
|
$address .= sprintf(
|
||||||
|
':%d',
|
||||||
|
$this->getPort()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($path && $this->getPath())
|
||||||
|
{
|
||||||
|
if (!str_starts_with($this->getPath(), $this->getSeparator()))
|
||||||
|
{
|
||||||
|
$address .= $this->getSeparator();
|
||||||
|
}
|
||||||
|
|
||||||
|
$address .= $this->getPath();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($query && $this->getQuery())
|
||||||
|
{
|
||||||
|
$address .= sprintf(
|
||||||
|
'?%s',
|
||||||
|
$this->getQuery()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($fragment && $this->getFragment())
|
||||||
|
{
|
||||||
|
$address .= sprintf(
|
||||||
|
'#%s',
|
||||||
|
$this->getFragment()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $address;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function toAbsolute(
|
||||||
|
\Yggverse\Net\Address $base
|
||||||
|
): bool
|
||||||
|
{
|
||||||
|
if ($this->isAbsolute())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($base->isRelative())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->setScheme(
|
||||||
|
$base->getScheme()
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->setUser(
|
||||||
|
$base->getUser()
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->setPass(
|
||||||
|
$base->getPass()
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->setHost(
|
||||||
|
$base->getHost()
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->setPort(
|
||||||
|
$base->getPort()
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->setSeparator(
|
||||||
|
$base->getSeparator()
|
||||||
|
);
|
||||||
|
|
||||||
|
if (str_starts_with((string) $this->getPath(), $this->getSeparator()))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($path = $this->getPath())
|
||||||
|
{
|
||||||
|
$prefix = array_reverse(
|
||||||
|
$base->getSegments()
|
||||||
|
);
|
||||||
|
|
||||||
|
array_shift(
|
||||||
|
$prefix
|
||||||
|
);
|
||||||
|
|
||||||
|
$navigate = true;
|
||||||
|
|
||||||
|
$postfix = [];
|
||||||
|
|
||||||
|
foreach ($this->getSegments() as $index => $segment)
|
||||||
|
{
|
||||||
|
if ($segment == '.')
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($navigate && $segment == '..')
|
||||||
|
{
|
||||||
|
if (empty($prefix[$index]))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
unset(
|
||||||
|
$prefix[$index]
|
||||||
|
);
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$navigate = false;
|
||||||
|
|
||||||
|
$postfix[] = $segment;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->setPath(
|
||||||
|
implode(
|
||||||
|
$this->getSeparator(),
|
||||||
|
array_merge(
|
||||||
|
array_reverse(
|
||||||
|
$prefix
|
||||||
|
),
|
||||||
|
$postfix
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// @TODO deprecated, legacy needs only
|
||||||
|
public function getAbsolute(
|
||||||
|
\Yggverse\Net\Address $base
|
||||||
|
): ?string
|
||||||
|
{
|
||||||
|
if ($this->toAbsolute($base))
|
||||||
|
{
|
||||||
|
return $this->get();
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
41
src/Dig.php
41
src/Dig.php
|
|
@ -17,32 +17,59 @@ class Dig
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function isProvider(mixed $value): bool
|
||||||
|
{
|
||||||
|
return
|
||||||
|
(
|
||||||
|
is_string($value) &&
|
||||||
|
false !== filter_var($value, FILTER_VALIDATE_IP)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
public static function isHostName(mixed $value, array $find = ['_'], array $replace = []): bool
|
public static function isHostName(mixed $value, array $find = ['_'], array $replace = []): bool
|
||||||
{
|
{
|
||||||
return is_string($value) && false !== filter_var(str_replace($find, $replace, $value), FILTER_VALIDATE_DOMAIN, FILTER_FLAG_HOSTNAME);
|
return (
|
||||||
|
is_string($value) &&
|
||||||
|
false !== filter_var(str_replace($find, $replace, $value), FILTER_VALIDATE_DOMAIN, FILTER_FLAG_HOSTNAME)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function isRecord(mixed $value): bool
|
public static function isRecord(mixed $value): bool
|
||||||
{
|
{
|
||||||
return is_string($value) && isset(self::_records()[$value]);
|
return
|
||||||
|
(
|
||||||
|
is_string($value) &&
|
||||||
|
isset(self::_records()[$value])
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function isRecordValue(mixed $record, mixed $value): bool
|
public static function isRecordValue(mixed $record, mixed $value): bool
|
||||||
{
|
{
|
||||||
return is_string($record) &&
|
return
|
||||||
is_string($value) &&
|
(
|
||||||
isset(self::_records()[$record]) && self::_records()[$record]($value);
|
is_string($record) &&
|
||||||
|
is_string($value) &&
|
||||||
|
isset(self::_records()[$record]) && self::_records()[$record]($value)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function records(string $hostname, array $records, array &$result = [], array &$error = []): array
|
public static function records(string $hostname, array $records, array &$result = [], array &$error = [], ?string $provider = null, int $timeout = 5): array
|
||||||
{
|
{
|
||||||
|
if (self::isProvider($provider))
|
||||||
|
{
|
||||||
|
$provider = sprintf(
|
||||||
|
'@%s',
|
||||||
|
$provider
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if (self::isHostName($hostname))
|
if (self::isHostName($hostname))
|
||||||
{
|
{
|
||||||
foreach ($records as $record)
|
foreach ($records as $record)
|
||||||
{
|
{
|
||||||
if (self::isRecord($record))
|
if (self::isRecord($record))
|
||||||
{
|
{
|
||||||
if ($values = exec(sprintf('dig %s %s +short', $record, $hostname)))
|
if ($values = exec(sprintf('dig %s %s %s +short +time=%d', (string) $provider, $record, $hostname, $timeout)))
|
||||||
{
|
{
|
||||||
foreach (explode(PHP_EOL, $values) as $value)
|
foreach (explode(PHP_EOL, $values) as $value)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
204
src/Resolve.php
Normal file
204
src/Resolve.php
Normal file
|
|
@ -0,0 +1,204 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Yggverse\Net;
|
||||||
|
|
||||||
|
class Resolve
|
||||||
|
{
|
||||||
|
private array $_providers =
|
||||||
|
[
|
||||||
|
'1.1.1.1',
|
||||||
|
'8.8.8.8'
|
||||||
|
];
|
||||||
|
|
||||||
|
private array $_records =
|
||||||
|
[
|
||||||
|
'A',
|
||||||
|
'AAAA'
|
||||||
|
];
|
||||||
|
|
||||||
|
private int $_timeout = 5;
|
||||||
|
|
||||||
|
private bool $_shuffle = false;
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
?array $records = null,
|
||||||
|
?array $providers = null,
|
||||||
|
?int $timeout = null,
|
||||||
|
bool $shuffle = false
|
||||||
|
) {
|
||||||
|
if ($records)
|
||||||
|
{
|
||||||
|
$this->setRecords(
|
||||||
|
$records
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($providers)
|
||||||
|
{
|
||||||
|
$this->setProviders(
|
||||||
|
$providers
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($timeout)
|
||||||
|
{
|
||||||
|
$this->setTimeout(
|
||||||
|
$timeout
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->setShuffle(
|
||||||
|
$shuffle
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getRecords(): array
|
||||||
|
{
|
||||||
|
return $this->_records;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setRecords(array $records): void
|
||||||
|
{
|
||||||
|
foreach ($records as $record)
|
||||||
|
{
|
||||||
|
$this->addRecord(
|
||||||
|
$record
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function addRecord(string $record): void
|
||||||
|
{
|
||||||
|
$this->_records[] = $record;
|
||||||
|
|
||||||
|
$this->_records = array_unique(
|
||||||
|
$this->_records
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getProviders(): array
|
||||||
|
{
|
||||||
|
return $this->_providers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setProviders(array $providers): void
|
||||||
|
{
|
||||||
|
foreach ($providers as $provider)
|
||||||
|
{
|
||||||
|
$this->addProvider(
|
||||||
|
$provider
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function addProvider(string $provider): void
|
||||||
|
{
|
||||||
|
$this->_providers[] = $provider;
|
||||||
|
|
||||||
|
$this->_providers = array_unique(
|
||||||
|
$this->_providers
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setTimeout(
|
||||||
|
int $timeout
|
||||||
|
): void
|
||||||
|
{
|
||||||
|
$this->_timeout = $timeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getTimeout(): int
|
||||||
|
{
|
||||||
|
return $this->_timeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setShuffle(
|
||||||
|
bool $shuffle
|
||||||
|
): void
|
||||||
|
{
|
||||||
|
$this->_shuffle = $shuffle;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isShuffle(): bool
|
||||||
|
{
|
||||||
|
return $this->_shuffle;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function url(
|
||||||
|
string $url,
|
||||||
|
array &$result = [],
|
||||||
|
array &$error = [],
|
||||||
|
?\Yggverse\Net\Address &$resolved = null
|
||||||
|
): ?string
|
||||||
|
{
|
||||||
|
$resolved = $this->address(
|
||||||
|
new \Yggverse\Net\Address(
|
||||||
|
$url
|
||||||
|
),
|
||||||
|
$result,
|
||||||
|
$error
|
||||||
|
);
|
||||||
|
|
||||||
|
if ($resolved)
|
||||||
|
{
|
||||||
|
return $resolved->get();
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function address(
|
||||||
|
\Yggverse\Net\Address $address,
|
||||||
|
array &$result = [],
|
||||||
|
array &$error = []
|
||||||
|
): ?\Yggverse\Net\Address
|
||||||
|
{
|
||||||
|
foreach ($this->_providers as $provider)
|
||||||
|
{
|
||||||
|
foreach (
|
||||||
|
\Yggverse\Net\Dig::records(
|
||||||
|
$address->getHost(),
|
||||||
|
$this->_records,
|
||||||
|
$result,
|
||||||
|
$error,
|
||||||
|
$provider,
|
||||||
|
$this->_timeout
|
||||||
|
) as $record => $data
|
||||||
|
) {
|
||||||
|
|
||||||
|
if ($this->_shuffle)
|
||||||
|
{
|
||||||
|
shuffle(
|
||||||
|
$data
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($data as $host)
|
||||||
|
{
|
||||||
|
if (\Yggverse\Net\Valid::ip6($host))
|
||||||
|
{
|
||||||
|
$address->setHost(
|
||||||
|
sprintf(
|
||||||
|
'[%s]',
|
||||||
|
$host
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$address->setHost(
|
||||||
|
$host
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $address;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
40
src/Valid.php
Normal file
40
src/Valid.php
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Yggverse\Net;
|
||||||
|
|
||||||
|
class Valid
|
||||||
|
{
|
||||||
|
public static function ip(mixed $value): bool
|
||||||
|
{
|
||||||
|
return self::ip4($value) || self::ip6($value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function ip4(mixed $value): bool
|
||||||
|
{
|
||||||
|
return false !== filter_var(
|
||||||
|
$value,
|
||||||
|
FILTER_VALIDATE_IP,
|
||||||
|
FILTER_FLAG_IPV4
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function ip6(mixed $value): bool
|
||||||
|
{
|
||||||
|
return false !== filter_var(
|
||||||
|
$value,
|
||||||
|
FILTER_VALIDATE_IP,
|
||||||
|
FILTER_FLAG_IPV6
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function domainHostName(mixed $value): bool
|
||||||
|
{
|
||||||
|
return false !== filter_var(
|
||||||
|
$value,
|
||||||
|
FILTER_VALIDATE_DOMAIN,
|
||||||
|
FILTER_FLAG_HOSTNAME
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue