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
Push — master ( 9bb5cc...d08348 )
by Joni
02:00
created

Identifier::intTag()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 0
crap 1
1
<?php
2
3
declare(strict_types = 1);
4
5
namespace ASN1\Component;
6
7
use ASN1\Exception\DecodeException;
8
use ASN1\Feature\Encodable;
9
use ASN1\Util\BigInt;
10
11
/**
12
 * Class to represent BER/DER identifier octets.
13
 */
14
class Identifier implements Encodable
15
{
16
    // Type class enumerations
17
    const CLASS_UNIVERSAL = 0b00;
18
    const CLASS_APPLICATION = 0b01;
19
    const CLASS_CONTEXT_SPECIFIC = 0b10;
20
    const CLASS_PRIVATE = 0b11;
21
    
22
    /**
23
     * Mapping from type class to human readable name.
24
     *
25
     * @internal
26
     *
27
     * @var array
28
     */
29
    const MAP_CLASS_TO_NAME = [ /* @formatter:off */
30
        self::CLASS_UNIVERSAL => "UNIVERSAL", 
31
        self::CLASS_APPLICATION => "APPLICATION", 
32
        self::CLASS_CONTEXT_SPECIFIC => "CONTEXT SPECIFIC", 
33
        self::CLASS_PRIVATE => "PRIVATE",
34
        /* @formatter:on */
35
    ];
36
    
37
    // P/C enumerations
38
    const PRIMITIVE = 0b0;
39
    const CONSTRUCTED = 0b1;
40
    
41
    /**
42
     * Type class.
43
     *
44
     * @var int
45
     */
46
    private $_class;
47
    
48
    /**
49
     * Primitive or Constructed.
50
     *
51
     * @var int
52
     */
53
    private $_pc;
54
    
55
    /**
56
     * Content type tag.
57
     *
58
     * @var BigInt
59
     */
60
    private $_tag;
61
    
62
    /**
63
     * Constructor.
64
     *
65
     * @param int $class Type class
66
     * @param int $pc Primitive / Constructed
67
     * @param int|string $tag Type tag number
68
     */
69 315
    public function __construct(int $class, int $pc, $tag)
70
    {
71 315
        $this->_class = 0b11 & $class;
72 315
        $this->_pc = 0b1 & $pc;
73 315
        $this->_tag = new BigInt($tag);
74 315
    }
75
    
76
    /**
77
     * Decode identifier component from DER data.
78
     *
79
     * @param string $data DER encoded data
80
     * @param int|null $offset Reference to the variable that contains offset
81
     *        into the data where to start parsing. Variable is updated to
82
     *        the offset next to the parsed identifier. If null, start from
83
     *        offset 0.
84
     * @throws DecodeException If decoding fails
85
     * @return self
86
     */
87 217
    public static function fromDER(string $data, int &$offset = null): self
88
    {
89 217
        $idx = $offset ? $offset : 0;
90 217
        $datalen = strlen($data);
91 217
        if ($idx >= $datalen) {
92 1
            throw new DecodeException("Invalid offset.");
93
        }
94 216
        $byte = ord($data[$idx++]);
95
        // bits 8 and 7 (class)
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
96
        // 0 = universal, 1 = application, 2 = context-specific, 3 = private
97 216
        $class = (0b11000000 & $byte) >> 6;
98
        // bit 6 (0 = primitive / 1 = constructed)
99 216
        $pc = (0b00100000 & $byte) >> 5;
100
        // bits 5 to 1 (tag number)
101 216
        $tag = (0b00011111 & $byte);
102
        // long-form identifier
103 216
        if (0x1f == $tag) {
104 8
            $tag = self::_decodeLongFormTag($data, $idx);
105
        }
106 215
        if (isset($offset)) {
107 201
            $offset = $idx;
108
        }
109 215
        return new self($class, $pc, $tag);
110
    }
111
    
112
    /**
113
     * Parse long form tag.
114
     *
115
     * @param string $data DER data
116
     * @param int $offset Reference to the variable containing offset to data
117
     * @throws DecodeException If decoding fails
118
     * @return string Tag number
119
     */
120 8
    private static function _decodeLongFormTag(string $data, int &$offset): string
121
    {
122 8
        $datalen = strlen($data);
123 8
        $tag = gmp_init(0, 10);
124 8
        while (true) {
125 8
            if ($offset >= $datalen) {
126 1
                throw new DecodeException(
127
                    "Unexpected end of data while decoding" .
128 1
                         " long form identifier.");
129
            }
130 8
            $byte = ord($data[$offset++]);
131 8
            $tag <<= 7;
132 8
            $tag |= 0x7f & $byte;
133
            // last byte has bit 8 set to zero
134 8
            if (!(0x80 & $byte)) {
135 7
                break;
136
            }
137
        }
138 7
        return gmp_strval($tag, 10);
139
    }
140
    
141
    /**
142
     *
143
     * @see Encodable::toDER()
144
     * @return string
145
     */
146 117
    public function toDER(): string
147
    {
148 117
        $bytes = [];
149 117
        $byte = $this->_class << 6 | $this->_pc << 5;
150 117
        $tag = $this->_tag->gmpObj();
151 117
        if ($tag < 0x1f) {
152 114
            $bytes[] = $byte | $tag;
153
        } else { // long-form identifier
154 4
            $bytes[] = $byte | 0x1f;
155 4
            $octets = [];
156 4
            for (; $tag > 0; $tag >>= 7) {
157 4
                array_push($octets, gmp_intval(0x80 | ($tag & 0x7f)));
158
            }
159
            // last octet has bit 8 set to zero
160 4
            $octets[0] &= 0x7f;
161 4
            foreach (array_reverse($octets) as $octet) {
162 4
                $bytes[] = $octet;
163
            }
164
        }
165 117
        return pack("C*", ...$bytes);
166
    }
167
    
168
    /**
169
     * Get class of the type.
170
     *
171
     * @return int
172
     */
173 6
    public function typeClass(): int
174
    {
175 6
        return $this->_class;
176
    }
177
    
178
    /**
179
     * Get P/C.
180
     *
181
     * @return int
182
     */
183 1
    public function pc(): int
184
    {
185 1
        return $this->_pc;
186
    }
187
    
188
    /**
189
     * Get the tag number.
190
     *
191
     * @return string Base 10 integer string
192
     */
193 203
    public function tag(): string
194
    {
195 203
        return $this->_tag->base10();
196
    }
197
    
198
    /**
199
     * Get the tag as an integer.
200
     *
201
     * @return int
202
     */
203 2
    public function intTag(): int
204
    {
205 2
        return $this->_tag->intVal();
206
    }
207
    
208
    /**
209
     * Check whether type is of an universal class.
210
     *
211
     * @return boolean
212
     */
213 186
    public function isUniversal(): bool
214
    {
215 186
        return self::CLASS_UNIVERSAL == $this->_class;
216
    }
217
    
218
    /**
219
     * Check whether type is of an application class.
220
     *
221
     * @return boolean
222
     */
223 1
    public function isApplication(): bool
224
    {
225 1
        return self::CLASS_APPLICATION == $this->_class;
226
    }
227
    
228
    /**
229
     * Check whether type is of a context specific class.
230
     *
231
     * @return boolean
232
     */
233 194
    public function isContextSpecific(): bool
234
    {
235 194
        return self::CLASS_CONTEXT_SPECIFIC == $this->_class;
236
    }
237
    
238
    /**
239
     * Check whether type is of a private class.
240
     *
241
     * @return boolean
242
     */
243 1
    public function isPrivate(): bool
244
    {
245 1
        return self::CLASS_PRIVATE == $this->_class;
246
    }
247
    
248
    /**
249
     * Check whether content is primitive type.
250
     *
251
     * @return boolean
252
     */
253 79
    public function isPrimitive(): bool
254
    {
255 79
        return self::PRIMITIVE == $this->_pc;
256
    }
257
    
258
    /**
259
     * Check hether content is constructed type.
260
     *
261
     * @return boolean
262
     */
263 23
    public function isConstructed(): bool
264
    {
265 23
        return self::CONSTRUCTED == $this->_pc;
266
    }
267
    
268
    /**
269
     * Get self with given type class.
270
     *
271
     * @param int $class One of <code>CLASS_*</code> enumerations
272
     * @return self
273
     */
274 6
    public function withClass(int $class): self
275
    {
276 6
        $obj = clone $this;
277 6
        $obj->_class = $class;
278 6
        return $obj;
279
    }
280
    
281
    /**
282
     * Get self with given type tag.
283
     *
284
     * @param int|string $tag Tag number
285
     * @return self
286
     */
287 6
    public function withTag($tag): self
288
    {
289 6
        $obj = clone $this;
290 6
        $obj->_tag = new BigInt($tag);
291 6
        return $obj;
292
    }
293
    
294
    /**
295
     * Get human readable name of the type class.
296
     *
297
     * @param int $class
298
     * @return string
299
     */
300 8
    public static function classToName(int $class): string
301
    {
302 8
        if (!array_key_exists($class, self::MAP_CLASS_TO_NAME)) {
303 1
            return "CLASS $class";
304
        }
305 7
        return self::MAP_CLASS_TO_NAME[$class];
306
    }
307
}
308