Completed
Push — master ( fe5fd9...28190b )
by Sam
07:00 queued 04:19
created

PTR::expandIpv6()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 13
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 3.0261

Importance

Changes 0
Metric Value
cc 3
eloc 6
nc 3
nop 1
dl 0
loc 13
ccs 6
cts 7
cp 0.8571
crap 3.0261
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of Badcow DNS Library.
7
 *
8
 * (c) Samuel Williams <[email protected]>
9
 *
10
 * For the full copyright and license information, please view the LICENSE
11
 * file that was distributed with this source code.
12
 */
13
14
namespace Badcow\DNS\Rdata;
15
16
use Badcow\DNS\Validator;
17
18
/**
19
 * @see https://tools.ietf.org/html/rfc1035#section-3.3.12
20
 */
21
class PTR extends CNAME
22
{
23
    const TYPE = 'PTR';
24
    const TYPE_CODE = 12;
25
26
    /**
27
     * Expands an IPv6 address to its full, non-shorthand representation.
28
     *
29
     * E.g. 2001:db8:9a::42 -> 2001:0db8:009a:0000:0000:0000:0000:0042
30
     *
31
     * @param string $ip IPv6 address
32
     *
33
     * @throws \InvalidArgumentException
34
     */
35 10
    public static function expandIpv6(string $ip): string
36
    {
37 10
        if (!Validator::ipv6($ip)) {
38 2
            throw new \InvalidArgumentException(sprintf('"%s" is not a valid IPv6 address.', $ip));
39
        }
40
41 9
        if (false === $packed = inet_pton($ip)) {
42
            throw new \InvalidArgumentException(sprintf('"%s" is not a valid IPv6 address.', $ip));
43
        }
44
45 9
        $hex = unpack('H*hex', $packed);
46
47 9
        return implode(':', str_split($hex['hex'], 4));
48
    }
49
50
    /**
51
     * This function will expand in incomplete IPv6 address.
52
     * An incomplete IPv6 address is of the form `2001:db8:ff:abcd`
53
     * i.e. one where there is less than eight hextets.
54
     *
55
     * @param string $ip IPv6 address
56
     *
57
     * @return string Expanded incomplete IPv6 address
58
     */
59 2
    public static function expandIncompleteIpv6(string $ip): string
60
    {
61 2
        $hextets = array_map(function ($hextet) {
62 2
            return str_pad($hextet, 4, '0', STR_PAD_LEFT);
63 2
        }, explode(':', $ip));
64
65 2
        return implode(':', $hextets);
66
    }
67
68
    /**
69
     * Takes a valid IPv6 address and contracts it
70
     * to its shorter version.
71
     *
72
     * E.g.: 2001:0000:0000:acad:0000:0000:0000:0001 -> 2001:0:0:acad::1
73
     *
74
     * Note: If there is more than one set of consecutive hextets, the function
75
     * will favour the larger of the sets. If both sets of zeroes are the same
76
     * the first will be favoured in the omission of zeroes.
77
     *
78
     * E.g.: 2001:0000:0000:ab80:2390:0000:0000:000a -> 2001:0:0:ab80:2390::a
79
     *
80
     * @param string $ip IPv6 address
81
     *
82
     * @throws \InvalidArgumentException
83
     *
84
     * @return string Contracted IPv6 address
85
     */
86 11
    public static function contractIpv6(string $ip): string
87
    {
88 11
        $packed = inet_pton($ip);
89
90 11
        if (!Validator::ipv6($ip) || false === $packed) {
91 1
            throw new \InvalidArgumentException(sprintf('"%s" is not a valid IPv6 address.', $ip));
92
        }
93
94 10
        $unpacked = inet_ntop($packed);
95
96 10
        if (false === $unpacked) {
97
            throw new \InvalidArgumentException(sprintf('"%s" could not be contracted.', $ip));
98
        }
99
100 10
        return $unpacked;
101
    }
102
103
    /**
104
     * Creates a reverse IPv4 address.
105
     *
106
     * E.g. 192.168.1.213 -> 213.1.168.192.in-addr.arpa.
107
     *
108
     * @param string $ip Valid IPv4 address
109
     *
110
     * @return string Reversed IP address appended with ".in-addr.arpa."
111
     */
112 2
    public static function reverseIpv4(string $ip): string
113
    {
114 2
        $octets = array_reverse(explode('.', $ip));
115
116 2
        return implode('.', $octets).'.in-addr.arpa.';
117
    }
118
119
    /**
120
     * Creates a reverse IPv6 address.
121
     *
122
     * E.g. 2001:db8::567:89ab -> b.a.9.8.7.6.5.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa.
123
     *
124
     * @param string $ip           A full or partial IPv6 address
125
     * @param bool   $appendSuffix Whether or not to append ".ip6.arpa.' suffix.
126
     *
127
     * @return string The reversed address appended with ".ip6.arpa."
128
     */
129 2
    public static function reverseIpv6(string $ip, bool $appendSuffix = true): string
130
    {
131
        try {
132 2
            $ip = self::expandIpv6($ip);
133 2
        } catch (\InvalidArgumentException $e) {
134 2
            $ip = self::expandIncompleteIpv6($ip);
135
        }
136
137 2
        $ip = str_replace(':', '', $ip);
138 2
        $ip = strrev($ip);
139 2
        $ip = implode('.', str_split($ip));
140 2
        $ip .= $appendSuffix ? '.ip6.arpa.' : '';
141
142 2
        return $ip;
143
    }
144
}
145