]>
git.immae.eu Git - github/wallabag/wallabag.git/blob - inc/3rdparty/libraries/PHPePub/lib.uuid.php
3 DrUUID RFC4122 library for PHP5
4 by J. King (http://jkingweb.ca/)
5 Licensed under MIT license
7 See http://jkingweb.ca/code/php/lib.uuid/
10 Last revised 2010-02-15
14 Copyright (c) 2009 J. King
16 Permission is hereby granted, free of charge, to any person
17 obtaining a copy of this software and associated documentation
18 files (the "Software"), to deal in the Software without
19 restriction, including without limitation the rights to use,
20 copy, modify, merge, publish, distribute, sublicense, and/or sell
21 copies of the Software, and to permit persons to whom the
22 Software is furnished to do so, subject to the following
25 The above copyright notice and this permission notice shall be
26 included in all copies or substantial portions of the Software.
28 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
29 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
30 OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
31 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
32 HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
33 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
34 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
35 OTHER DEALINGS IN THE SOFTWARE.
42 const clearVer
= 15; // 00001111 Clears all bits of version byte with AND
43 const clearVar
= 63; // 00111111 Clears all relevant bits of variant byte with AND
44 const varRes
= 224; // 11100000 Variant reserved for future use
45 const varMS
= 192; // 11000000 Microsft GUID variant
46 const varRFC
= 128; // 10000000 The RFC 4122 variant (this variant)
47 const varNCS
= 0; // 00000000 The NCS compatibility variant
48 const version1
= 16; // 00010000
49 const version3
= 48; // 00110000
50 const version4
= 64; // 01000000
51 const version5
= 80; // 01010000
52 const interval
= 0x01b21dd213814000; // Time (in 100ns steps) between the start of the UTC and Unix epochs
53 const nsDNS
= '6ba7b810-9dad-11d1-80b4-00c04fd430c8';
54 const nsURL
= '6ba7b811-9dad-11d1-80b4-00c04fd430c8';
55 const nsOID
= '6ba7b812-9dad-11d1-80b4-00c04fd430c8';
56 const nsX500
= '6ba7b814-9dad-11d1-80b4-00c04fd430c8';
57 protected static $randomFunc = 'randomTwister';
58 protected static $randomSource = NULL;
69 public static function mint($ver = 1, $node = NULL, $ns = NULL) {
70 /* Create a new UUID based on provided data. */
73 return new self(self
::mintTime($node));
75 // Version 2 is not supported
76 throw new UUIDException("Version 2 is unsupported.");
78 return new self(self
::mintName(self
::MD5
, $node, $ns));
80 return new self(self
::mintRand());
82 return new self(self
::mintName(self
::SHA1
, $node, $ns));
84 throw new UUIDException("Selected version is invalid or unsupported.");
88 public static function import($uuid) {
89 /* Import an existing UUID. */
90 return new self(self
::makeBin($uuid, 16));
93 public static function compare($a, $b) {
94 /* Compares the binary representations of two UUIDs.
95 The comparison will return true if they are bit-exact,
96 or if neither is valid. */
97 if (self
::makeBin($a, 16)==self
::makeBin($b, 16)) {
104 public function __toString() {
105 return $this->string;
108 public function __get($var) {
113 return bin2hex($this->bytes
);
115 return $this->__toString();
117 return "urn:uuid:".$this->__toString();
119 return ord($this->bytes
[6]) >> 4;
121 $byte = ord($this->bytes
[8]);
122 if ($byte >= self
::varRes
) {
125 if ($byte >= self
::varMS
) {
128 if ($byte >= self
::varRFC
) {
133 if (ord($this->bytes
[6])>>4==1) {
134 return bin2hex(substr($this->bytes
,10));
139 if (ord($this->bytes
[6])>>4==1) {
140 // Restore contiguous big-endian byte order
141 $time = bin2hex($this->bytes
[6].$this->bytes
[7].$this->bytes
[4].$this->bytes
[5].$this->bytes
[0].$this->bytes
[1].$this->bytes
[2].$this->bytes
[3]);
142 // Clear version flag
144 // Do some reverse arithmetic to get a Unix timestamp
145 $time = (hexdec($time) - self
::interval
) / 10000000;
155 protected function __construct($uuid) {
156 if (strlen($uuid) != 16) {
157 throw new UUIDException("Input must be a 128-bit integer.");
159 $this->bytes
= $uuid;
160 // Optimize the most common use
162 bin2hex(substr($uuid,0,4))."-".
163 bin2hex(substr($uuid,4,2))."-".
164 bin2hex(substr($uuid,6,2))."-".
165 bin2hex(substr($uuid,8,2))."-".
166 bin2hex(substr($uuid,10,6));
169 protected static function mintTime($node = NULL) {
170 /* Generates a Version 1 UUID.
171 These are derived from the time at which they were generated. */
172 // Get time since Gregorian calendar reform in 100ns intervals
173 // This is exceedingly difficult because of PHP's (and pack()'s)
174 // integer size limits.
175 // Note that this will never be more accurate than to the microsecond.
176 $time = microtime(1) * 10000000 + self
::interval
;
177 // Convert to a string representation
178 $time = sprintf("%F", $time);
179 preg_match("/^\d+/", $time, $time); //strip decimal point
180 // And now to a 64-bit binary representation
181 $time = base_convert($time[0], 10, 16);
182 $time = pack("H*", str_pad($time, 16, "0", STR_PAD_LEFT
));
183 // Reorder bytes to their proper locations in the UUID
184 $uuid = $time[4].$time[5].$time[6].$time[7].$time[2].$time[3].$time[0].$time[1];
185 // Generate a random clock sequence
186 $uuid .= self
::randomBytes(2);
188 $uuid[8] = chr(ord($uuid[8]) & self
::clearVar
| self
::varRFC
);
190 $uuid[6] = chr(ord($uuid[6]) & self
::clearVer
| self
::version1
);
191 // Set the final 'node' parameter, a MAC address
193 $node = self
::makeBin($node, 6);
196 // If no node was provided or if the node was invalid,
197 // generate a random MAC address and set the multicast bit
198 $node = self
::randomBytes(6);
199 $node[0] = pack("C", ord($node[0]) | 1);
205 protected static function mintRand() {
206 /* Generate a Version 4 UUID.
207 These are derived soly from random numbers. */
208 // generate random fields
209 $uuid = self
::randomBytes(16);
211 $uuid[8] = chr(ord($uuid[8]) & self
::clearVar
| self
::varRFC
);
213 $uuid[6] = chr(ord($uuid[6]) & self
::clearVer
| self
::version4
);
217 protected static function mintName($ver, $node, $ns) {
218 /* Generates a Version 3 or Version 5 UUID.
219 These are derived from a hash of a name and its namespace, in binary form. */
221 throw new UUIDException("A name-string is required for Version 3 or 5 UUIDs.");
223 // if the namespace UUID isn't binary, make it so
224 $ns = self
::makeBin($ns, 16);
226 throw new UUIDException("A binary namespace is required for Version 3 or 5 UUIDs.");
229 $version = self
::version3
;
232 $version = self
::version3
;
233 $uuid = md5($ns.$node,1);
236 $version = self
::version5
;
237 $uuid = substr(sha1($ns.$node,1),0, 16);
241 $uuid[8] = chr(ord($uuid[8]) & self
::clearVar
| self
::varRFC
);
243 $uuid[6] = chr(ord($uuid[6]) & self
::clearVer
| $version);
247 protected static function makeBin($str, $len) {
248 /* Insure that an input string is either binary or hexadecimal.
249 Returns binary representation, or false on failure. */
250 if ($str instanceof self
) {
253 if (strlen($str)==$len) {
256 $str = preg_replace("/^urn:uuid:/is", "", $str); // strip URN scheme and namespace
258 $str = preg_replace("/[^a-f0-9]/is", "", $str); // strip non-hex characters
259 if (strlen($str) != ($len * 2)) {
262 return pack("H*", $str);
266 public static function initRandom() {
267 /* Look for a system-provided source of randomness, which is usually crytographically secure.
268 /dev/urandom is tried first simply out of bias for Linux systems. */
269 if (is_readable('/dev/urandom')) {
270 self
::$randomSource = fopen('/dev/urandom', 'rb');
271 self
::$randomFunc = 'randomFRead';
273 else if (class_exists('COM', 0)) {
275 self
::$randomSource = new COM('CAPICOM.Utilities.1'); // See http://msdn.microsoft.com/en-us/library/aa388182(VS.85).aspx
276 self
::$randomFunc = 'randomCOM';
278 catch(Exception
$e) {
281 return self
::$randomFunc;
284 public static function randomBytes($bytes) {
285 return call_user_func(array('self', self
::$randomFunc), $bytes);
288 protected static function randomTwister($bytes) {
289 /* Get the specified number of random bytes, using mt_rand().
290 Randomness is returned as a string of bytes. */
292 for ($a = 0; $a < $bytes; $a++
) {
293 $rand .= chr(mt_rand(0, 255));
298 protected static function randomFRead($bytes) {
299 /* Get the specified number of random bytes using a file handle
300 previously opened with UUID::initRandom().
301 Randomness is returned as a string of bytes. */
302 return fread(self
::$randomSource, $bytes);
305 protected static function randomCOM($bytes) {
306 /* Get the specified number of random bytes using Windows'
307 randomness source via a COM object previously created by UUID::initRandom().
308 Randomness is returned as a string of bytes. */
309 return base64_decode(self
::$randomSource->GetRandom($bytes,0)); // straight binary mysteriously doesn't work, hence the base64
313 class UUIDException
extends Exception
{