Passed
Branch master (8940db)
by Sam
02:38
created

NAPTR::getPreference()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 1
c 0
b 0
f 0
nc 1
nop 0
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
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\Parser\Tokens;
17
use Badcow\DNS\Validator;
18
19
/**
20
 * {@link https://tools.ietf.org/html/rfc3403}.
21
 */
22
class NAPTR implements RdataInterface
23
{
24
    use RdataTrait;
25
26
    const TYPE = 'NAPTR';
27
    const TYPE_CODE = 35;
28
29
    /**
30
     * A 16-bit unsigned integer specifying the order in which the NAPTR
31
     * records MUST be processed in order to accurately represent the
32
     * ordered list of Rules.  The ordering is from lowest to highest.
33
     * If two records have the same order value then they are considered
34
     * to be the same rule and should be selected based on the
35
     * combination of the Preference values and Services offered.
36
     *
37
     * @var int|null
38
     */
39
    private $order;
40
41
    /**
42
     * It is a 16-bit unsigned integer that specifies the order in which
43
     * NAPTR records with equal Order values SHOULD be processed, low
44
     * numbers being processed before high numbers.
45
     *
46
     * @var int
47
     */
48
    private $preference;
49
50
    /**
51
     * A <character-string> containing flags to control aspects of the
52
     * rewriting and interpretation of the fields in the record.  Flags
53
     * are single characters from the set A-Z and 0-9.  The case of the
54
     * alphabetic characters is not significant.  The field can be empty.
55
     *
56
     * @var string|null
57
     */
58
    private $flags;
59
60
    /**
61
     * A <character-string> that specifies the Service Parameters
62
     * applicable to this this delegation path.  It is up to the
63
     * Application Specification to specify the values found in this
64
     * field.
65
     *
66
     * @var string|null
67
     */
68
    private $services;
69
70
    /**
71
     * A <character-string> containing a substitution expression that is
72
     * applied to the original string held by the client in order to
73
     * construct the next domain name to lookup.
74
     *
75
     * @var string|null
76
     */
77
    private $regexp;
78
79
    /**
80
     * A <domain-name> which is the next domain-name to query for
81
     * depending on the potential values found in the flags field.  This
82
     * field is used when the regular expression is a simple replacement
83
     * operation.  Any value in this field MUST be a fully qualified
84
     * domain-name.
85
     *
86
     * @var string
87
     */
88
    private $replacement;
89
90
    /**
91
     * @return int
92
     */
93 4
    public function getOrder(): ?int
94
    {
95 4
        return $this->order;
96
    }
97
98
    /**
99
     * @param int $order
100
     *
101
     * @throws \InvalidArgumentException
102
     */
103 8
    public function setOrder(int $order): void
104
    {
105 8
        if ($order < 0 || $order > 65535) {
106
            throw new \InvalidArgumentException(sprintf('$order must be between 0 and 65535. "%d" given.', $order));
107
        }
108
109 8
        $this->order = $order;
110 8
    }
111
112
    /**
113
     * @return int
114
     */
115 4
    public function getPreference(): ?int
116
    {
117 4
        return $this->preference;
118
    }
119
120
    /**
121
     * @param int $preference
122
     *
123
     * @throws \InvalidArgumentException
124
     */
125 8
    public function setPreference(int $preference): void
126
    {
127 8
        if ($preference < 0 || $preference > 65535) {
128
            throw new \InvalidArgumentException(sprintf('$preference must be between 0 and 65535. "%d" given.', $preference));
129
        }
130
131 8
        $this->preference = $preference;
132 8
    }
133
134
    /**
135
     * @return string
136
     */
137 4
    public function getFlags(): ?string
138
    {
139 4
        return $this->flags;
140
    }
141
142
    /**
143
     * @param string $flags
144
     */
145 8
    public function setFlags(?string $flags): void
146
    {
147 8
        $this->flags = $flags;
148 8
    }
149
150
    /**
151
     * @return string
152
     */
153 4
    public function getServices(): ?string
154
    {
155 4
        return $this->services;
156
    }
157
158
    /**
159
     * @param string $services
160
     */
161 8
    public function setServices(?string $services): void
162
    {
163 8
        $this->services = $services;
164 8
    }
165
166
    /**
167
     * @return string
168
     */
169 4
    public function getRegexp(): ?string
170
    {
171 4
        return $this->regexp;
172
    }
173
174
    /**
175
     * @param string $regexp
176
     */
177 8
    public function setRegexp(?string $regexp): void
178
    {
179 8
        $this->regexp = $regexp;
180 8
    }
181
182
    /**
183
     * @return string
184
     */
185 4
    public function getReplacement(): ?string
186
    {
187 4
        return $this->replacement;
188
    }
189
190
    /**
191
     * @param string $replacement
192
     */
193 8
    public function setReplacement(string $replacement): void
194
    {
195 8
        if (!Validator::fullyQualifiedDomainName($replacement)) {
196
            throw new \InvalidArgumentException(sprintf('Replacement must be a fully qualified domain name. "%s" given.', $replacement));
197
        }
198
199 8
        $this->replacement = $replacement;
200 8
    }
201
202
    /**
203
     * {@inheritdoc}
204
     */
205 2
    public function toText(): string
206
    {
207 2
        return sprintf('%d %d "%s" "%s" "%s" %s',
208 2
            $this->order,
209 2
            $this->preference,
210 2
            $this->flags ?? '',
211 2
            $this->services ?? '',
212 2
            $this->regexp,
213 2
            $this->replacement
214
        );
215
    }
216
217
    /**
218
     * {@inheritdoc}
219
     */
220 2
    public function toWire(): string
221
    {
222 2
        $encoded = pack('nn', $this->order, $this->preference);
223 2
        $encoded .= sprintf('"%s""%s""%s"', $this->flags ?? '', $this->services ?? '', $this->regexp);
224 2
        $encoded .= RdataTrait::encodeName($this->replacement);
225
226 2
        return $encoded;
227
    }
228
229
    /**
230
     * {@inheritdoc}
231
     *
232
     * @return NAPTR
233
     */
234 2
    public static function fromText(string $text): RdataInterface
235
    {
236 2
        $rdata = explode(Tokens::SPACE, $text);
237 2
        $naptr = new self();
238 2
        $naptr->setOrder((int) array_shift($rdata));
239 2
        $naptr->setPreference((int) array_shift($rdata));
240 2
        $naptr->setFlags(trim((string) array_shift($rdata), Tokens::DOUBLE_QUOTES));
241 2
        $naptr->setServices(trim((string) array_shift($rdata), Tokens::DOUBLE_QUOTES));
242 2
        $naptr->setRegexp(trim((string) array_shift($rdata), Tokens::DOUBLE_QUOTES));
243 2
        $naptr->setReplacement((string) array_shift($rdata));
244
245 2
        return $naptr;
246
    }
247
248
    /**
249
     * {@inheritdoc}
250
     *
251
     * @return NAPTR
252
     */
253 2
    public static function fromWire(string $rdata): RdataInterface
254
    {
255 2
        $naptr = new self();
256 2
        $integers = unpack('nOrder/nPreference', $rdata);
257
258 2
        $naptr->setOrder($integers['Order']);
259 2
        $naptr->setPreference($integers['Preference']);
260 2
        $offset = 4;
261 2
        $naptr->setFlags(self::extractText($rdata, $offset));
262 2
        $naptr->setServices(self::extractText($rdata, $offset));
263 2
        $naptr->setRegexp(self::extractText($rdata, $offset));
264 2
        $naptr->setReplacement(self::decodeName($rdata, $offset));
265
266 2
        return $naptr;
267
    }
268
269
    /**
270
     * Extract text from within quotation marks and advance the offset.
271
     *
272
     * @param string $string
273
     * @param int    $offset
274
     *
275
     * @return string
276
     */
277 2
    private static function extractText(string $string, int &$offset): string
278
    {
279 2
        if (Tokens::DOUBLE_QUOTES !== $char = substr($string, $offset, 1)) {
280
            throw new \InvalidArgumentException(sprintf('The starting point of $string must be double quotes. "%s" given.', $char));
281
        }
282
283 2
        $value = '';
284 2
        ++$offset;
285
286 2
        while (Tokens::DOUBLE_QUOTES !== $char = substr($string, $offset, 1)) {
287 2
            $value .= $char;
288 2
            ++$offset;
289
        }
290
291 2
        ++$offset;
292
293 2
        return $value;
294
    }
295
}
296