1<?php
2/**
3 * Class for generating RFC 4122 UUIDs. Usage:
4 *
5 * <code>
6 * $uuid = (string)new Horde_Support_Uuid;
7 * </code>
8 *
9 * Copyright 2008-2017 Horde LLC (http://www.horde.org/)
10 *
11 * @category   Horde
12 * @package    Support
13 * @license    http://www.horde.org/licenses/bsd
14 */
15class Horde_Support_Uuid
16{
17    /**
18     * Generated UUID
19     * @var string
20     */
21    private $_uuid;
22
23    /**
24     * New UUID.
25     */
26    public function __construct()
27    {
28        $this->generate();
29    }
30
31    /**
32     * Generate a 36-character RFC 4122 UUID, without the urn:uuid: prefix.
33     *
34     * @see http://www.ietf.org/rfc/rfc4122.txt
35     * @see http://labs.omniti.com/alexandria/trunk/OmniTI/Util/UUID.php
36     */
37    public function generate()
38    {
39        $this->_uuid = null;
40        if (extension_loaded('uuid')) {
41            if (function_exists('uuid_export')) {
42                // UUID extension from http://www.ossp.org/pkg/lib/uuid/
43                if (uuid_create($ctx) == UUID_RC_OK &&
44                    uuid_make($ctx, UUID_MAKE_V4) == UUID_RC_OK &&
45                    uuid_export($ctx, UUID_FMT_STR, $str) == UUID_RC_OK) {
46                    $this->_uuid = $str;
47                    uuid_destroy($ctx);
48                }
49            } else {
50                // UUID extension from http://pecl.php.net/package/uuid
51                $this->_uuid = uuid_create();
52            }
53        }
54        if (!$this->_uuid) {
55            list($time_mid, $time_low) = explode(' ', microtime());
56            $time_low = (int)$time_low;
57            $time_mid = (int)substr($time_mid, 2) & 0xffff;
58            $time_high = mt_rand(0, 0x0fff) | 0x4000;
59
60            $clock = mt_rand(0, 0x3fff) | 0x8000;
61
62            $node_low = function_exists('zend_thread_id')
63                ? zend_thread_id()
64                : getmypid();
65            $node_high = isset($_SERVER['SERVER_ADDR'])
66                ? ip2long($_SERVER['SERVER_ADDR'])
67                : crc32(php_uname());
68            $node = bin2hex(pack('nN', $node_low, $node_high));
69
70            $this->_uuid = sprintf('%08x-%04x-%04x-%04x-%s',
71                $time_low, $time_mid, $time_high, $clock, $node);
72        }
73    }
74
75    /**
76     * Cooerce to string.
77     *
78     * @return string  UUID.
79     */
80    public function __toString()
81    {
82        return $this->_uuid;
83    }
84
85}
86