GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Branch improve-rating (2b7f64)
by Renan
01:53
created

Punycode::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1
Metric Value
dl 0
loc 4
ccs 3
cts 3
cp 1
rs 10
cc 1
eloc 2
nc 1
nop 1
crap 1
1
<?php
2
namespace TrueBV;
3
4
/**
5
 * Punycode implementation as described in RFC 3492
6
 *
7
 * @link http://tools.ietf.org/html/rfc3492
8
 */
9
class Punycode
10
{
11
12
    /**
13
     * Bootstring parameter values
14
     *
15
     */
16
    const BASE         = 36;
17
    const TMIN         = 1;
18
    const TMAX         = 26;
19
    const SKEW         = 38;
20
    const DAMP         = 700;
21
    const INITIAL_BIAS = 72;
22
    const INITIAL_N    = 128;
23
    const PREFIX       = 'xn--';
24
    const DELIMITER    = '-';
25
26
    /**
27
     * Encode table
28
     *
29
     * @param array
30
     */
31
    protected static $encodeTable = array(
32
        'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
33
        'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
34
        'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
35
    );
36
37
    /**
38
     * Decode table
39
     *
40
     * @param array
41
     */
42
    protected static $decodeTable = array(
43
        'a' =>  0, 'b' =>  1, 'c' =>  2, 'd' =>  3, 'e' =>  4, 'f' =>  5,
44
        'g' =>  6, 'h' =>  7, 'i' =>  8, 'j' =>  9, 'k' => 10, 'l' => 11,
45
        'm' => 12, 'n' => 13, 'o' => 14, 'p' => 15, 'q' => 16, 'r' => 17,
46
        's' => 18, 't' => 19, 'u' => 20, 'v' => 21, 'w' => 22, 'x' => 23,
47
        'y' => 24, 'z' => 25, '0' => 26, '1' => 27, '2' => 28, '3' => 29,
48
        '4' => 30, '5' => 31, '6' => 32, '7' => 33, '8' => 34, '9' => 35
49
    );
50
51
    /**
52
     * Character encoding
53
     *
54
     * @param string
55
     */
56
    protected $encoding;
57
58
    /**
59
     * Constructor
60
     *
61
     * @param string $encoding Character encoding
62
     */
63 76
    public function __construct($encoding = 'UTF-8')
64
    {
65 76
        $this->encoding = $encoding;
66 76
    }
67
68
    /**
69
     * Encode a domain to its Punycode version
70
     *
71
     * @param string $input Domain name in Unicode to be encoded
72
     * @return string Punycode representation in ASCII
73
     */
74 38
    public function encode($input)
75
    {
76 38
        $input = mb_strtolower($input, $this->encoding);
77 38
        $parts = explode('.', $input);
78
79 38
        foreach ($parts as &$part) {
80 38
            if (preg_match('/^[\x20-\x7F]+$/', $part)) {
81 14
                continue;
82
            }
83
84 38
            $prefix = static::PREFIX;
85 38
            $codePoints = $this->listCodePoints($part);
86
87 38
            if (!empty($codePoints['basic'])) {
88 6
                $basicChars = array_map(array($this, 'codePointToChar'), $codePoints['basic']);
89 6
                $prefix .= implode('', $basicChars) . static::DELIMITER;
90
            }
91
92 38
            $part = $prefix . $this->encodeNonBasic($part, $codePoints);
93
        }
94
95 38
        return implode('.', $parts);
96
    }
97
98
    /**
99
     * Encode non code code points 
100
     *
101
     * @param string $input
102
     * @param array $codePoints
103
     * @return string
104
     */
105 38
    protected function encodeNonBasic($input, $codePoints)
106
    {
107 38
        $codePoints['nonBasic'] = array_unique($codePoints['nonBasic']);
108 38
        sort($codePoints['nonBasic']);
109
110 38
        $output = '';
111 38
        $n = static::INITIAL_N;
112 38
        $bias = static::INITIAL_BIAS;
113 38
        $delta = 0;
114 38
        $h = $b = count($codePoints['basic']);
115
116 38
        $i = 0;
117 38
        $length = mb_strlen($input, $this->encoding);
118 38
        while ($h < $length) {
119 38
            $m = $codePoints['nonBasic'][$i++];
120 38
            $delta = $delta + ($m - $n) * ($h + 1);
121 38
            $n = $m;
122
123 38
            foreach ($codePoints['all'] as $c) {
124 38
                if ($c < $n || $c < static::INITIAL_N) {
125 38
                    $delta++;
126
                }
127 38
                if ($c === $n) {
128 38
                    $q = $delta;
129 38
                    for ($k = static::BASE;; $k += static::BASE) {
130 38
                        $t = $this->calculateThreshold($k, $bias);
131 38
                        if ($q < $t) {
132 38
                            break;
133
                        }
134
135 38
                        $code = $t + (($q - $t) % (static::BASE - $t));
136 38
                        $output .= static::$encodeTable[$code];
137
138 38
                        $q = ($q - $t) / (static::BASE - $t);
139
                    }
140
141 38
                    $output .= static::$encodeTable[$q];
142 38
                    $bias = $this->adapt($delta, $h + 1, ($h === $b));
143 38
                    $delta = 0;
144 38
                    $h++;
145
                }
146
            }
147
148 38
            $delta++;
149 38
            $n++;
150
        }
151
152 38
        return $output;
153
    }
154
155
    /**
156
     * Decode a Punycode domain name to its Unicode counterpart
157
     *
158
     * @param string $input Domain name in Punycode
159
     * @return string Unicode domain name
160
     */
161 38
    public function decode($input)
162
    {
163 38
        $input = strtolower($input);
164 38
        $parts = explode('.', $input);
165 38
        foreach ($parts as &$part) {
166 38
            if (strpos($part, static::PREFIX) !== 0) {
167 14
                continue;
168
            }
169
170 38
            $part = substr($part, strlen(static::PREFIX));
171 38
            $part = $this->decodePart($part);
172
        }
173
174 38
        return implode('.', $parts);
175
    }
176
177
    /**
178
     * Decode a part of domain name, such as tld
179
     *
180
     * @param string $input Part of a domain name
181
     * @return string Unicode domain part
182
     */
183 38
    protected function decodePart($input)
184
    {
185 38
        $n = static::INITIAL_N;
186 38
        $i = 0;
187 38
        $bias = static::INITIAL_BIAS;
188 38
        $output = '';
189
190 38
        $pos = strrpos($input, static::DELIMITER);
191 38
        if ($pos !== false) {
192 6
            $output = substr($input, 0, $pos++);
193
        } else {
194 32
            $pos = 0;
195
        }
196
197 38
        $outputLength = strlen($output);
198 38
        $inputLength = strlen($input);
199 38
        while ($pos < $inputLength) {
200 38
            $oldi = $i;
201 38
            $w = 1;
202
203 38
            for ($k = static::BASE;; $k += static::BASE) {
204 38
                $digit = static::$decodeTable[$input[$pos++]];
205 38
                $i = $i + ($digit * $w);
206 38
                $t = $this->calculateThreshold($k, $bias);
207
208 38
                if ($digit < $t) {
209 38
                    break;
210
                }
211
212 38
                $w = $w * (static::BASE - $t);
213
            }
214
215 38
            $bias = $this->adapt($i - $oldi, ++$outputLength, ($oldi === 0));
216 38
            $n = $n + (int) ($i / $outputLength);
217 38
            $i = $i % ($outputLength);
218 38
            $output = mb_substr($output, 0, $i, $this->encoding) . $this->codePointToChar($n) . mb_substr($output, $i, $outputLength - 1, $this->encoding);
219
220 38
            $i++;
221
        }
222
223 38
        return $output;
224
    }
225
226
    /**
227
     * Calculate the bias threshold to fall between TMIN and TMAX
228
     *
229
     * @param integer $k
230
     * @param integer $bias
231
     * @return integer
232
     */
233 76
    protected function calculateThreshold($k, $bias)
234
    {
235 76
        if ($k <= $bias + static::TMIN) {
236 76
            return static::TMIN;
237 76
        } elseif ($k >= $bias + static::TMAX) {
238 76
            return static::TMAX;
239
        }
240 52
        return $k - $bias;
241
    }
242
243
    /**
244
     * Bias adaptation
245
     *
246
     * @param integer $delta
247
     * @param integer $numPoints
248
     * @param boolean $firstTime
249
     * @return integer
250
     */
251 76
    protected function adapt($delta, $numPoints, $firstTime)
252
    {
253
        $delta = (int) (
254 76
            ($firstTime)
255 76
                ? $delta / static::DAMP
256 76
                : $delta / 2
257
            );
258 76
        $delta += (int) ($delta / $numPoints);
259
260 76
        $k = 0;
261 76
        while ($delta > ((static::BASE - static::TMIN) * static::TMAX) / 2) {
262 28
            $delta = (int) ($delta / (static::BASE - static::TMIN));
263 28
            $k = $k + static::BASE;
264
        }
265 76
        $k = $k + (int) (((static::BASE - static::TMIN + 1) * $delta) / ($delta + static::SKEW));
266
267 76
        return $k;
268
    }
269
270
    /**
271
     * List code points for a given input
272
     *
273
     * @param string $input
274
     * @return array Multi-dimension array with basic, non-basic and aggregated code points
275
     */
276 38
    protected function listCodePoints($input)
277
    {
278
        $codePoints = array(
279 38
            'all'      => array(),
280
            'basic'    => array(),
281
            'nonBasic' => array(),
282
        );
283
284 38
        $length = mb_strlen($input, $this->encoding);
285 38
        for ($i = 0; $i < $length; $i++) {
286 38
            $char = mb_substr($input, $i, 1, $this->encoding);
287 38
            $code = $this->charToCodePoint($char);
288 38
            if ($code < 128) {
289 6
                $codePoints['all'][] = $codePoints['basic'][] = $code;
290
            } else {
291 38
                $codePoints['all'][] = $codePoints['nonBasic'][] = $code;
292
            }
293
        }
294
295 38
        return $codePoints;
296
    }
297
298
    /**
299
     * Convert a single or multi-byte character to its code point
300
     *
301
     * @param string $char
302
     * @return integer
303
     */
304 38
    protected function charToCodePoint($char)
305
    {
306 38
        $code = ord($char[0]);
307 38
        if ($code < 128) {
308 6
            return $code;
309 38
        } elseif ($code < 224) {
310 22
            return (($code - 192) * 64) + (ord($char[1]) - 128);
311 18
        } elseif ($code < 240) {
312 16
            return (($code - 224) * 4096) + ((ord($char[1]) - 128) * 64) + (ord($char[2]) - 128);
313
        } else {
314 2
            return (($code - 240) * 262144) + ((ord($char[1]) - 128) * 4096) + ((ord($char[2]) - 128) * 64) + (ord($char[3]) - 128);
315
        }
316
    }
317
318
    /**
319
     * Convert a code point to its single or multi-byte character
320
     *
321
     * @param integer $code
322
     * @return string
323
     */
324 44
    protected function codePointToChar($code)
325
    {
326 44
        if ($code <= 0x7F) {
327 6
            return chr($code);
328 38
        } elseif ($code <= 0x7FF) {
329 22
            return chr(($code >> 6) + 192) . chr(($code & 63) + 128);
330 18
        } elseif ($code <= 0xFFFF) {
331 16
            return chr(($code >> 12) + 224) . chr((($code >> 6) & 63) + 128) . chr(($code & 63) + 128);
332
        } else {
333 2
            return chr(($code >> 18) + 240) . chr((($code >> 12) & 63) + 128) . chr((($code >> 6) & 63) + 128) . chr(($code & 63) + 128);
334
        }
335
    }
336
}
337