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 ( a25647...c0e57f )
by Joni
03:42
created

Length::expectFromDER()   B

Complexity

Conditions 5
Paths 4

Size

Total Lines 21
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 14
CRAP Score 5

Importance

Changes 0
Metric Value
dl 0
loc 21
ccs 14
cts 14
cp 1
rs 8.7624
c 0
b 0
f 0
cc 5
eloc 14
nc 4
nop 3
crap 5
1
<?php
2
3
namespace ASN1\Component;
4
5
use ASN1\Exception\DecodeException;
6
use ASN1\Feature\Encodable;
7
8
9
/**
10
 * Class to represent BER/DER length octets.
11
 */
12
class Length implements Encodable
13
{
14
	/**
15
	 * Length.
16
	 *
17
	 * @var int|string
18
	 */
19
	private $_length;
20
	
21
	/**
22
	 * Whether length is indefinite.
23
	 *
24
	 * @var boolean
25
	 */
26
	private $_indefinite;
27
	
28
	/**
29
	 * Constructor
30
	 *
31
	 * @param int|string $length Length
32
	 * @param boolean $indefinite Whether length is indefinite
33
	 */
34 307
	public function __construct($length, $indefinite = false) {
35 307
		$this->_length = $length;
36 307
		$this->_indefinite = $indefinite;
37 307
	}
38
	
39
	/**
40
	 * Decode length component from DER data.
41
	 *
42
	 * @param string $data DER encoded data
43
	 * @param int|null $offset Reference to the variable that contains offset
44
	 *        into the data where to start parsing. Variable is updated to
45
	 *        the offset next to the parsed length component. If null, start
46
	 *        from offset 0.
47
	 * @throws DecodeException If decoding fails
48
	 * @return self
49
	 */
50 211
	public static function fromDER($data, &$offset = null) {
51 211
		assert('is_string($data)', "got " . gettype($data));
52 210
		$idx = $offset ? $offset : 0;
53 210
		$datalen = strlen($data);
54 210
		if ($idx >= $datalen) {
55 1
			throw new DecodeException("Invalid offset.");
56
		}
57 209
		$indefinite = false;
58 209
		$byte = ord($data[$idx++]);
59
		// bits 7 to 1
60 209
		$length = (0x7f & $byte);
61
		// long form
62 209
		if (0x80 & $byte) {
63 10
			if (!$length) {
64 3
				$indefinite = true;
65 3
			} else {
66 7
				if ($idx + $length > $datalen) {
67 1
					throw new DecodeException("Too many length octets.");
68
				}
69 6
				$length = self::_decodeLongFormLength($length, $data, $idx);
70
			}
71 8
		}
72 207
		if (isset($offset)) {
73 199
			$offset = $idx;
74 199
		}
75 207
		return new self($length, $indefinite);
76
	}
77
	
78
	/**
79
	 * Decode long form length.
80
	 *
81
	 * @param int $length Number of octets
82
	 * @param string $data Data
83
	 * @param int $offset Reference to the variable containing offset to the
84
	 *        data.
85
	 * @throws DecodeException If decoding fails
86
	 * @return int|string
87
	 */
88 6
	private static function _decodeLongFormLength($length, $data, &$offset) {
89
		// first octet must not be 0xff (spec 8.1.3.5c)
90 6
		if ($length == 127) {
91 1
			throw new DecodeException("Invalid number of length octets.");
92
		}
93 5
		$num = gmp_init(0, 10);
94 5
		while (--$length >= 0) {
95 5
			$byte = ord($data[$offset++]);
96 5
			$num <<= 8;
97 5
			$num |= $byte;
98 5
		}
99 5
		return gmp_strval($num);
100
	}
101
	
102
	/**
103
	 * Decode length from DER.
104
	 *
105
	 * Throws an exception if length doesn't match with expected or if data
106
	 * doesn't contain enough bytes.
107
	 *
108
	 * @see self::fromDER
109
	 * @param string $data DER data
110
	 * @param int $offset Reference to the offset variable
111
	 * @param int|null $expected Expected length, null to bypass checking
112
	 * @throws DecodeException If decoding or expectation fails
113
	 * @return self
114
	 */
115 199
	public static function expectFromDER($data, &$offset, $expected = null) {
116 199
		$idx = $offset;
117 199
		$length = self::fromDER($data, $idx);
118
		// DER encoding must have definite length (spec 10.1)
119 199
		if ($length->isIndefinite()) {
120 1
			throw new DecodeException("DER encoding must have definite length.");
121
		}
122
		// if certain length was expected
123 198
		if (isset($expected) && $expected != $length->_length) {
124 3
			throw new DecodeException(
125 3
				"Expected length $expected, got {$length->_length}.");
126
		}
127
		// check that enough data is available
128 195
		if (strlen($data) < $idx + $length->_length) {
129 4
			throw new DecodeException(
130 4
				"Length {$length->_length} overflows data, " .
131 4
					 (strlen($data) - $idx) . " bytes left.");
132
		}
133 191
		$offset = $idx;
134 191
		return $length;
135
	}
136
	
137
	/**
138
	 *
139
	 * @see Encodable::toDER()
140
	 * @throws \DomainException If length is too large to encode
141
	 * @return string
142
	 */
143 118
	public function toDER() {
144 118
		$bytes = array();
145 118
		if ($this->_indefinite) {
146 1
			$bytes[] = 0x80;
147 1
		} else {
148 117
			$num = gmp_init($this->_length, 10);
149
			// long form
150 117
			if ($num > 127) {
151 7
				$octets = array();
152 7
				for (; $num > 0; $num >>= 8) {
153 7
					$octets[] = gmp_intval(0xff & $num);
154 7
				}
155 7
				$count = count($octets);
156
				// first octet must not be 0xff
157 7
				if ($count >= 127) {
158 2
					throw new \DomainException("Too many length octets.");
159
				}
160 5
				$bytes[] = 0x80 | $count;
161 5
				foreach (array_reverse($octets) as $octet) {
162 5
					$bytes[] = $octet;
163 5
				}
164 5
			} else { // short form
165 110
				$bytes[] = gmp_intval($num);
166
			}
167
		}
168 116
		return pack("C*", ...$bytes);
169
	}
170
	
171
	/**
172
	 * Get the length.
173
	 *
174
	 * @throws \LogicException If length is indefinite
175
	 * @return int|string
176
	 */
177 179
	public function length() {
178 179
		if ($this->_indefinite) {
179 1
			throw new \LogicException("Length is indefinite.");
180
		}
181 178
		return $this->_length;
182
	}
183
	
184
	/**
185
	 * Whether length is indefinite.
186
	 *
187
	 * @return boolean
188
	 */
189 201
	public function isIndefinite() {
190 201
		return $this->_indefinite;
191
	}
192
}
193