Helper::generateID()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
c 0
b 0
f 0
ccs 2
cts 2
cp 1
rs 10
cc 1
nc 1
nop 0
crap 1
1
<?php
2
3
/*
4
 * This file is part of the LightSAML-Core package.
5
 *
6
 * (c) Milos Tomic <[email protected]>
7
 *
8
 * This source file is subject to the MIT license that is bundled
9
 * with this source code in the file LICENSE.
10
 */
11
12
namespace LightSaml;
13
14
final class Helper
15
{
16
    const TIME_FORMAT = 'Y-m-d\TH:i:s\Z';
17
18
    /**
19
     * @param string $duration
20
     */
21 5
    public static function validateDurationString($duration)
22
    {
23 5
        if ($duration) {
24
            try {
25 5
                new \DateInterval((string) $duration);
26 2
            } catch (\Exception $ex) {
27 2
                throw new \InvalidArgumentException(sprintf("Invalid duration '%s' format", $duration), 0, $ex);
28
            }
29
        }
30 3
    }
31
32
    /**
33
     * @param int $time
34
     *
35
     * @return string
36
     */
37 30
    public static function time2string($time)
38
    {
39 30
        return gmdate('Y-m-d\TH:i:s\Z', $time);
40
    }
41
42
    /**
43
     * @param int|string|\DateTime $value
44
     *
45
     * @return int
46
     *
47
     * @throws \InvalidArgumentException
48
     */
49 116
    public static function getTimestampFromValue($value)
50
    {
51 116
        if (is_string($value)) {
52 42
            return self::parseSAMLTime($value);
53 78
        } elseif ($value instanceof \DateTime) {
54 28
            return $value->getTimestamp();
55 51
        } elseif (is_int($value)) {
56 50
            return $value;
57
        } else {
58 1
            throw new \InvalidArgumentException();
59
        }
60
    }
61
62
    /**
63
     * @param string $time
64
     *
65
     * @return int
66
     *
67
     * @throws \InvalidArgumentException
68
     */
69 42
    public static function parseSAMLTime($time)
70
    {
71 42
        $matches = [];
72 42
        if (0 == preg_match(
73 42
                '/^(\\d\\d\\d\\d)-(\\d\\d)-(\\d\\d)T(\\d\\d):(\\d\\d):(\\d\\d)(?:\\.\\d+)?(Z|[+-]\\d\\d:\\d\\d)$/D',
74 42
                $time,
75 42
                $matches
76
            )) {
77 1
            throw new \InvalidArgumentException('Invalid SAML2 timestamp: '.$time);
78
        }
79
80 41
        return strtotime($time);
81
    }
82
83
    /**
84
     * @param int $length
85
     *
86
     * @return string
87
     *
88
     * @throws \InvalidArgumentException
89
     */
90 15
    public static function generateRandomBytes($length)
91
    {
92 15
        $length = intval($length);
93 15
        if ($length <= 0) {
94 1
            throw new \InvalidArgumentException();
95
        }
96
97 14
        if (function_exists('openssl_random_pseudo_bytes')) {
98 14
            return openssl_random_pseudo_bytes($length);
99
        }
100
101
        $data = '';
102
        for ($i = 0; $i < $length; ++$i) {
103
            $data .= chr(mt_rand(0, 255));
104
        }
105
106
        return $data;
107
    }
108
109
    /**
110
     * @param string $bytes
111
     *
112
     * @return string
113
     */
114 13
    public static function stringToHex($bytes)
115
    {
116 13
        $result = '';
117 13
        $len = strlen($bytes);
118 13
        for ($i = 0; $i < $len; ++$i) {
119 13
            $result .= sprintf('%02x', ord($bytes[$i]));
120
        }
121
122 13
        return $result;
123
    }
124
125
    /**
126
     * @return string
127
     */
128 13
    public static function generateID()
129
    {
130 13
        return '_'.self::stringToHex(self::generateRandomBytes(21));
131
    }
132
133
    /**
134
     * Is ID element at least 128 bits in length (SAML2.0 standard section 1.3.4).
135
     *
136
     * @param string $id
137
     *
138
     * @return bool
139
     */
140 22
    public static function validateIdString($id)
141
    {
142 22
        return is_string($id) && strlen(trim($id)) >= 16;
143
    }
144
145
    /**
146
     * @param string $value
147
     *
148
     * @return bool
149
     */
150 65
    public static function validateRequiredString($value)
151
    {
152 65
        return is_string($value) && strlen(trim($value)) > 0;
153
    }
154
155
    /**
156
     * @param string $value
157
     *
158
     * @return bool
159
     */
160 14
    public static function validateOptionalString($value)
161
    {
162 14
        return null === $value || self::validateRequiredString($value);
163
    }
164
165
    /**
166
     * @param string $value
167
     *
168
     * @return bool
169
     */
170 47
    public static function validateWellFormedUriString($value)
171
    {
172 47
        $value = trim($value);
173 47
        if ('' == $value || strlen($value) > 65520) {
174 3
            return false;
175
        }
176
177 44
        if (preg_match('|\s|', $value)) {
178 9
            return false;
179
        }
180
181 37
        $parts = parse_url($value);
182 37
        if (isset($parts['scheme'])) {
183 35
            if ($parts['scheme'] != rawurlencode($parts['scheme'])) {
184 35
                return false;
185
            }
186
        } else {
187 2
            return false;
188
        }
189
190 35
        return true;
191
    }
192
193
    /**
194
     * @param int $notBefore
195
     * @param int $now
196
     * @param int $allowedSecondsSkew
197
     *
198
     * @return bool
199
     */
200 8
    public static function validateNotBefore($notBefore, $now, $allowedSecondsSkew)
201
    {
202 8
        return null == $notBefore || (($notBefore - $allowedSecondsSkew) < $now);
203
    }
204
205
    /**
206
     * @param int $notOnOrAfter
207
     * @param int $now
208
     * @param int $allowedSecondsSkew
209
     *
210
     * @return bool
211
     */
212 7
    public static function validateNotOnOrAfter($notOnOrAfter, $now, $allowedSecondsSkew)
213
    {
214 7
        return null == $notOnOrAfter || ($now < ($notOnOrAfter + $allowedSecondsSkew));
215
    }
216
}
217