Skip to content

Commit

Permalink
Adding IPv6 Converter and usage in uri-interfaces and uri-components
Browse files Browse the repository at this point in the history
  • Loading branch information
nyamsprod committed Jun 24, 2024
1 parent 432681a commit 8a83c7d
Show file tree
Hide file tree
Showing 6 changed files with 116 additions and 4 deletions.
4 changes: 4 additions & 0 deletions components/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ All Notable changes to `League\Uri\Components` will be documented in this file

- `UrlSearchParams::uniqueKeyCount`
- `Modifier::getIdnUriString`
- `Modifier::hostToIpv6Compressed`
- `Modifier::hostToIpv6Expanded`
- `Host::expand`
- `Host::compress`;

### Fixed

Expand Down
34 changes: 34 additions & 0 deletions components/Components/Host.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
use League\Uri\Idna\Converter as IdnConverter;
use League\Uri\IPv4\Converter as IPv4Converter;
use League\Uri\IPv4Normalizer;
use League\Uri\IPv6\Converter;
use Psr\Http\Message\UriInterface as Psr7UriInterface;
use Stringable;

Expand Down Expand Up @@ -333,6 +334,39 @@ public function toUnicode(): ?string
};
}

public function compress(): ?string
{
if ('6' !== $this->ipVersion) {
return $this->host;
}

/** @var string $ip */
$ip = $this->getIp();
if (! $this->hasZoneIdentifier) {
return '['. Converter::compress($ip) .']';
}

[$ipv6, $zoneId] = explode('%', $ip, 2);

return '['. Converter::compress($ipv6) . '%' . $zoneId . ']';
}

public function expand(): ?string
{
if ('6' !== $this->ipVersion) {
return $this->host;
}

/** @var string $ip */
$ip = $this->getIp();
[$ipv6, $zoneId] = explode('%', $ip, 2);

return match ($this->hasZoneIdentifier) {
false => '['.Converter::expand($ipv6).']',
true => '['.Converter::expand($ipv6). '%' . $zoneId.']',
};
}

public function getIpVersion(): ?string
{
return $this->ipVersion;
Expand Down
21 changes: 18 additions & 3 deletions components/Components/UserInfo.php
Original file line number Diff line number Diff line change
Expand Up @@ -113,9 +113,8 @@ public static function new(#[SensitiveParameter] Stringable|string|null $value =
public function value(): ?string
{
return match (true) {
null === $this->username => null,
null === $this->password => Encoder::encodeUser($this->username),
default => Encoder::encodeUser($this->username).':'.Encoder::encodePassword($this->password),
null === $this->password => $this->getUsername(),
default => $this->getUsername().':'.$this->getPassword(),
};
}

Expand All @@ -134,6 +133,22 @@ public function getPass(): ?string
return $this->password;
}

public function getUsername(): ?string
{
return match ($this->username) {
null => null,
default => Encoder::encodeUser($this->username)
};
}

public function getPassword(): ?string
{
return match ($this->password) {
null => null,
default => Encoder::encodePassword($this->password)
};
}

/**
* @return array{user: ?string, pass: ?string}
*/
Expand Down
10 changes: 10 additions & 0 deletions components/Modifier.php
Original file line number Diff line number Diff line change
Expand Up @@ -451,6 +451,16 @@ public function hostToHexadecimal(): static
};
}

public function hostToIpv6Compressed(): static
{
return new static($this->uri->withHost(Host::fromUri($this->uri)->compress()));
}

public function hostToIpv6Expanded(): static
{
return new static($this->uri->withHost(Host::fromUri($this->uri)->expand()));
}

/**
* Prepend a label or a host to the current URI host.
*
Expand Down
2 changes: 1 addition & 1 deletion interfaces/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ All Notable changes to `League\Uri\Interfaces` will be documented in this file

- `UriInterface::getUsername` returns the encoded user component of the URI.
- `UriInterface::getPassword` returns the encoded scheme-specific information about how to gain authorization to access the resource.

- `Uri\IPv6\Converter` allow expanding and compressing IPv6.
### Fixed

- Adding Host resolution caching to speed up URI parsing in `UriString`
Expand Down
49 changes: 49 additions & 0 deletions interfaces/IPv6/Converter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?php

declare(strict_types=1);

namespace League\Uri\IPv6;

use Stringable;
use const FILTER_FLAG_IPV6;
use const FILTER_VALIDATE_IP;

use function filter_var;
use function inet_pton;
use function implode;
use function str_split;
use function strtolower;
use function unpack;

final class Converter
{
public static function compress(Stringable|string|null $ipv6): ?string
{
return match (true) {
null === $ipv6 => null,
self::isValidIpv6($ipv6) => (string) inet_ntop((string) inet_pton((string) $ipv6)),
default => (string) $ipv6,
};
}

public static function expand(Stringable|string|null $ipv6): ?string
{
if (null === $ipv6) {
return null;
}

$ipv6 = (string) $ipv6;
if (!self::isValidIpv6($ipv6)) {
return $ipv6;
}

$hex = (array) unpack("H*hex", (string) inet_pton($ipv6));

return implode(':', str_split(strtolower($hex['hex'] ?? ''), 4));
}

private static function isValidIpv6(Stringable|string|null $ipv6): bool
{
return (bool) filter_var((string) $ipv6, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6);
}
}

0 comments on commit 8a83c7d

Please sign in to comment.