Subversion Repositories oidplus

Rev

Rev 193 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
17 daniel-mar 1
<?php
2
 
90 daniel-mar 3
/*
4
 * UUID utils for PHP
5
 * Copyright 2011-2019 Daniel Marschall, ViaThinkSoft
194 daniel-mar 6
 * Version 2019-11-04
90 daniel-mar 7
 *
8
 * Licensed under the Apache License, Version 2.0 (the "License");
9
 * you may not use this file except in compliance with the License.
10
 * You may obtain a copy of the License at
11
 *
12
 *     http://www.apache.org/licenses/LICENSE-2.0
13
 *
14
 * Unless required by applicable law or agreed to in writing, software
15
 * distributed under the License is distributed on an "AS IS" BASIS,
16
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
 * See the License for the specific language governing permissions and
18
 * limitations under the License.
19
 */
17 daniel-mar 20
 
179 daniel-mar 21
if (file_exists(__DIR__ . '/mac_utils.inc.phps')) include_once __DIR__ . '/mac_utils.inc.phps';
17 daniel-mar 22
 
23
define('UUID_NAMEBASED_NS_DNS',     '6ba7b810-9dad-11d1-80b4-00c04fd430c8');
24
define('UUID_NAMEBASED_NS_URL',     '6ba7b811-9dad-11d1-80b4-00c04fd430c8');
25
define('UUID_NAMEBASED_NS_OID',     '6ba7b812-9dad-11d1-80b4-00c04fd430c8');
26
define('UUID_NAMEBASED_NS_X500_DN', '6ba7b814-9dad-11d1-80b4-00c04fd430c8');
27
 
28
function uuid_valid($uuid) {
29
        $uuid = str_replace(array('-', '{', '}'), '', $uuid);
30
        $uuid = strtoupper($uuid);
31
 
32
        if (strlen($uuid) != 32) return false;
33
 
34
        $uuid = preg_replace('@[0-9A-F]@', '', $uuid);
35
 
36
        return ($uuid == '');
37
}
38
 
191 daniel-mar 39
# TODO: Don't echo
17 daniel-mar 40
function uuid_info($uuid) {
41
        if (!uuid_valid($uuid)) return false;
42
 
43
        # $uuid = str_replace(array('-', '{', '}'), '', $uuid);
44
        $uuid = strtoupper($uuid);
45
        $uuid = preg_replace('@[^0-9A-F]@', '', $uuid);
46
 
47
        $x = hexdec(substr($uuid, 16, 1));
48
             if ($x >= 14 /* 1110 */) $variant = 3;
49
        else if ($x >= 12 /* 1100 */) $variant = 2;
50
        else if ($x >=  8 /* 1000 */) $variant = 1;
51
        else if ($x >=  0 /* 0000 */) $variant = 0;
52
 
53
 
54
        switch ($variant) {
55
                case 0:
56
                        echo sprintf("%-24s %s\n", "Variant:", "[0xx] NCS (reserved for backward compatibility)");
57
 
58
                        /*
59
                         * Internal structure of variant #0 UUIDs
60
                         *
61
                         * The first 6 octets are the number of 4 usec units of time that have
62
                         * passed since 1/1/80 0000 GMT.  The next 2 octets are reserved for
63
                         * future use.  The next octet is an address family.  The next 7 octets
64
                         * are a host ID in the form allowed by the specified address family.
65
                         *
66
                         * Note that while the family field (octet 8) was originally conceived
67
                         * of as being able to hold values in the range [0..255], only [0..13]
68
                         * were ever used.  Thus, the 2 MSB of this field are always 0 and are
69
                         * used to distinguish old and current UUID forms.
70
                         *
71
                         * +--------------------------------------------------------------+
72
                         * |                    high 32 bits of time                      |  0-3  .time_high
73
                         * +-------------------------------+-------------------------------
74
                         * |     low 16 bits of time       |  4-5               .time_low
75
                         * +-------+-----------------------+
76
                         * |         reserved              |  6-7               .reserved
77
                         * +---------------+---------------+
78
                         * |    family     |   8                                .family
79
                         * +---------------+----------...-----+
80
                         * |            node ID               |  9-16           .node
81
                         * +--------------------------...-----+
82
                         *
83
                         */
84
 
85
                        // Example of an UUID: 333a2276-0000-0000-0d00-00809c000000
86
 
87
                        # TODO: See https://github.com/cjsv/uuid/blob/master/Doc
88
 
89
                        # Timestamp: Count of 4us intervals since 01 Jan 1980 00:00:00 GMT
90
                        # 1/0,000004 = 250000
91
                        # Seconds between 1970 and 1980 : 315532800
92
                        # 250000*315532800=78883200000000
93
                        $timestamp = substr($uuid, 0, 12);
94
                        $ts = gmp_init($timestamp, 16);
95
                        $ts = gmp_add($ts, gmp_init("78883200000000"));
193 daniel-mar 96
                        $ms = gmp_mod($ts, gmp_init("250000"));
17 daniel-mar 97
                        $ts = gmp_div($ts, gmp_init("250000"));
98
                        $ts = gmp_strval($ts);
99
                        $ms = gmp_strval($ms);
193 daniel-mar 100
                        $ts = gmdate('Y-m-d H:i:s', $ts)."'".str_pad($ms, 7, '0', STR_PAD_LEFT).' GMT';
101
                        echo sprintf("%-24s %s\n", "Timestamp:", "[0x$timestamp] $ts");
17 daniel-mar 102
 
103
                        $reserved = substr($uuid, 12, 4);
104
                        echo sprintf("%-24s %s\n", "Reserved:", "0x$reserved");
105
 
106
                        # Family 13 (dds) looks like node is 00 | nnnnnn 000000.
107
                        # Family 2 is presumably (ip).
108
                        # Not sure if anything else was used.
109
                        $family_hex = substr($uuid, 16, 2);
110
                        $family_dec = hexdec($family_hex);
111
                        if ($family_dec == 2) {
112
                                $family_ = 'IP';
113
                        } else if ($family_dec == 13) {
114
                                $family_ = 'DDS (Data Link)';
115
                        } else {
193 daniel-mar 116
                                $family_ = "Unknown ($family_dec)"; # There are probably no more families
17 daniel-mar 117
                        }
118
                        echo sprintf("%-24s %s\n", "Family:", "[0x$family_hex = $family_dec] $family_");
119
 
120
                        $nodeid = substr($uuid, 18, 14);
121
                        echo sprintf("%-24s %s\n", "Node ID:", "0x$nodeid");
122
                        # TODO: interprete node id (the family specifies it)
123
 
124
                        break;
125
                case 1:
126
                        echo sprintf("%-24s %s\n", "Variant:", "[10x] RFC 4122 (Leach-Mealling-Salz)");
127
 
128
                        $version = hexdec(substr($uuid, 12, 1));
129
                        switch ($version) {
130
                                case 1:
131
                                        echo sprintf("%-24s %s\n", "Version:", "[1] Time-based with unique random host identifier");
132
 
133
                                        # Timestamp: Count of 100ns intervals since 15 Oct 1582 00:00:00
134
                                        # 1/0,0000001 = 10000000
135
                                        $timestamp = substr($uuid, 13, 3).substr($uuid, 8, 4).substr($uuid, 0, 8);
136
                                        $ts = gmp_init($timestamp, 16);
137
                                        $ts = gmp_sub($ts, gmp_init("122192928000000000"));
193 daniel-mar 138
                                        $ms = gmp_mod($ts, gmp_init("10000000"));
17 daniel-mar 139
                                        $ts = gmp_div($ts, gmp_init("10000000"));
140
                                        $ts = gmp_strval($ts);
141
                                        $ms = gmp_strval($ms);
193 daniel-mar 142
                                        $ts = gmdate('Y-m-d H:i:s', $ts)."'".str_pad($ms, 7, '0', STR_PAD_LEFT).' GMT';
143
                                        echo sprintf("%-24s %s\n", "Timestamp:", "[0x$timestamp] $ts");
17 daniel-mar 144
 
145
                                        $x = hexdec(substr($uuid, 16, 4));
193 daniel-mar 146
                                        $dec = $x & 0x3FFF; // The highest 2 bits are used by "variant" (10x)
147
                                        $hex = substr($uuid, 16, 4);
148
                                        echo sprintf("%-24s %s\n", "Clock ID:", "[0x$hex] $dec");
17 daniel-mar 149
 
150
                                        $x = substr($uuid, 20, 12);
151
                                        $nodeid = '';
152
                                        for ($i=0; $i<6; $i++) {
153
                                                $nodeid .= substr($x, $i*2, 2);
154
                                                if ($i != 5) $nodeid .= ':';
155
                                        }
156
                                        echo sprintf("%-24s %s\n", "Node ID:", "$nodeid");
157
 
158
                                        if (function_exists('decode_mac')) {
159
                                                echo "\nIn case that this Node ID is a MAC address, here is the interpretation of that MAC address:\n";
160
                                                echo decode_mac($nodeid);
161
                                        }
162
 
163
                                        break;
164
                                case 2:
193 daniel-mar 165
                                        echo sprintf("%-24s %s\n", "Version:", "[2] DCE Security version");
17 daniel-mar 166
 
167
                                        # The time_low field (which represents an integer in the range [0, 232-1]) is interpreted as a local-ID; that is, an identifier (within the domain specified by clock_seq_low) meaningful to the local host. In the particular case of a POSIX host, when combined with a POSIX UID or POSIX GID domain in the clock_seq_low field (above), the time_low field represents a POSIX UID or POSIX GID, respectively.
168
                                        $x = substr($uuid, 0, 8);
169
                                        echo sprintf("%-24s %s\n", "Local ID:", "0x$x");
170
 
171
                                        # The clock_seq_low field (which represents an integer in the range [0, 28-1]) is interpreted as a local domain (as represented by sec_rgy_domain_t; see sec_rgy_domain_t ); that is, an identifier domain meaningful to the local host. (Note that the data type sec_rgy_domain_t can potentially hold values outside the range [0, 28-1]; however, the only values currently registered are in the range [0, 2], so this type mismatch is not significant.) In the particular case of a POSIX host, the value sec_rgy_domain_person is to be interpreted as the "POSIX UID domain", and the value sec_rgy_domain_group is to be interpreted as the "POSIX GID domain".
193 daniel-mar 172
                                        $x = substr($uuid, 18, 2);
173
                                        if ($x == '00') $domain_info = 'POSIX: User-ID / Non-POSIX: site-defined';
174
                                        else if ($x == '01') $domain_info = 'POSIX: Group-ID / Non-POSIX: site-defined';
175
                                        else $domain_info = 'site-defined';
176
                                        echo sprintf("%-24s %s\n", "Local Domain:", "0x$x ($domain_info)");
17 daniel-mar 177
 
178
                                        # Timestamp: Count of 100ns intervals since 15 Oct 1582 00:00:00
179
                                        # 1/0,0000001 = 10000000
193 daniel-mar 180
                                        $timestamp = substr($uuid, 13, 3).substr($uuid, 8, 4).'00000000';
17 daniel-mar 181
                                        $ts = gmp_init($timestamp, 16);
182
                                        $ts = gmp_sub($ts, gmp_init("122192928000000000"));
193 daniel-mar 183
                                        $ms = gmp_mod($ts, gmp_init("10000000"));
17 daniel-mar 184
                                        $ts = gmp_div($ts, gmp_init("10000000"));
185
                                        $ts = gmp_strval($ts);
186
                                        $ms = gmp_strval($ms);
193 daniel-mar 187
                                        $ts_min = gmdate('Y-m-d H:i:s', $ts)."'".str_pad($ms, 7, '0', STR_PAD_LEFT).' GMT';
17 daniel-mar 188
 
193 daniel-mar 189
                                        $timestamp = substr($uuid, 13, 3).substr($uuid, 8, 4).'FFFFFFFF';
190
                                        $ts = gmp_init($timestamp, 16);
191
                                        $ts = gmp_sub($ts, gmp_init("122192928000000000"));
192
                                        $ms = gmp_mod($ts, gmp_init("10000000"));
193
                                        $ts = gmp_div($ts, gmp_init("10000000"));
194
                                        $ts = gmp_strval($ts);
195
                                        $ms = gmp_strval($ms);
196
                                        $ts_max = gmdate('Y-m-d H:i:s', $ts)."'".str_pad($ms, 7, '0', STR_PAD_LEFT).' GMT';
17 daniel-mar 197
 
193 daniel-mar 198
                                        $timestamp = substr($uuid, 13, 3).substr($uuid, 8, 4).'xxxxxxxx';
199
                                        echo sprintf("%-24s %s\n", "Timestamp:", "[0x$timestamp] $ts_min - $ts_max");
200
 
201
                                        $x = hexdec(substr($uuid, 16, 2).'00');
202
                                        $dec_min = $x & 0x3FFF; // The highest 2 bits are used by "variant" (10x)
203
                                        $x = hexdec(substr($uuid, 16, 2).'FF');
204
                                        $dec_max = $x & 0x3FFF; // The highest 2 bits are used by "variant" (10x)
205
                                        $hex = substr($uuid, 16, 2).'xx';
206
                                        echo sprintf("%-24s %s\n", "Clock ID:", "[0x$hex] $dec_min - $dec_max");
207
 
17 daniel-mar 208
                                        $x = substr($uuid, 20, 12);
209
                                        $nodeid = '';
210
                                        for ($i=0; $i<6; $i++) {
211
                                                $nodeid .= substr($x, $i*2, 2);
212
                                                if ($i != 5) $nodeid .= ':';
213
                                        }
214
                                        echo sprintf("%-24s %s\n", "Node ID:", "$nodeid");
215
 
216
                                        if (function_exists('decode_mac')) {
217
                                                echo "\nIn case that this Node ID is a MAC address, here is the interpretation of that MAC address:\n";
218
                                                echo decode_mac($nodeid);
219
                                        }
220
 
221
                                        break;
222
                                case 3:
223
                                        echo sprintf("%-24s %s\n", "Version:", "[3] Name-based (MD5 hash)");
224
 
193 daniel-mar 225
                                        $hash = str_replace('-', '', strtolower($uuid));
226
                                        $hash[12] = '?'; // was overwritten by version
227
                                        $hash[16] = '?'; // was partially overwritten by variant
17 daniel-mar 228
 
193 daniel-mar 229
                                        echo sprintf("%-24s %s\n", "MD5(Namespace+Subject):", "$hash");
230
 
17 daniel-mar 231
                                        break;
232
                                case 4:
233
                                        echo sprintf("%-24s %s\n", "Version:", "[4] Random");
234
 
235
                                        $rand = '';
236
                                        for ($i=0; $i<16; $i++) {
237
                                                $bin = base_convert(substr($uuid, $i*2, 2), 16, 2);
238
                                                $bin = str_pad($bin, 8, "0", STR_PAD_LEFT);
239
 
240
                                                if ($i == 6) {
241
                                                        $bin[0] = 'x';
242
                                                        $bin[1] = 'x';
243
                                                } else if ($i == 8) {
244
                                                        $bin[0] = 'x';
245
                                                        $bin[1] = 'x';
246
                                                        $bin[2] = 'x';
247
                                                        $bin[3] = 'x';
248
                                                }
249
 
250
                                                $rand .= "$bin ";
251
                                        }
252
 
253
                                        echo sprintf("%-24s %s\n", "Random bits:", trim($rand));
254
 
255
                                        break;
256
                                case 5:
257
                                        echo sprintf("%-24s %s\n", "Version:", "[5] Name-based (SHA-1 hash)");
258
 
193 daniel-mar 259
                                        $hash = str_replace('-', '', strtolower($uuid));
260
                                        $hash[12] = '?'; // was overwritten by version
261
                                        $hash[16] = '?'; // was partially overwritten by variant
262
                                        $hash .= '????????'; // was cut off
17 daniel-mar 263
 
193 daniel-mar 264
                                        echo sprintf("%-24s %s\n", "SHA1(Namespace+Subject):", "$hash");
265
 
266
 
17 daniel-mar 267
                                        break;
268
                                default:
269
                                        echo sprintf("%-24s %s\n", "Version:", "[$version] Unknown");
270
                                        break;
271
                        }
272
 
273
                        break;
274
                case 2:
275
                        echo sprintf("%-24s %s\n", "Variant:", "[110] Reserved for Microsoft Corporation");
276
                        break;
277
                case 3:
278
                        echo sprintf("%-24s %s\n", "Variant:", "[111] Reserved for future use");
279
                        break;
280
        }
281
}
282
 
283
function uuid_canonize($uuid) {
284
        if (!uuid_valid($uuid)) return false;
285
        return oid_to_uuid(uuid_to_oid($uuid));
286
}
287
 
288
function oid_to_uuid($oid) {
289
        if (!is_uuid_oid($oid)) return false;
290
 
291
        if ($oid[0] == '.') {
292
                $oid = substr($oid, 1);
293
        }
294
        $ary = explode('.', $oid);
295
        $val = $ary[2];
296
 
297
        $x = gmp_init($val, 10);
298
        $y = gmp_strval($x, 16);
299
        $y = str_pad($y, 32, "0", STR_PAD_LEFT);
300
        return substr($y,  0, 8).'-'.
301
               substr($y,  8, 4).'-'.
302
               substr($y, 12, 4).'-'.
303
               substr($y, 16, 4).'-'.
304
               substr($y, 20, 12);
305
}
306
 
307
function is_uuid_oid($oid, $only_allow_root=false) {
194 daniel-mar 308
        if ($oid[0] == '.') $oid = substr($oid, 1); // remove leading dot
17 daniel-mar 309
 
310
        $ary = explode('.', $oid);
311
 
312
        if ($only_allow_root) {
313
                if (count($ary) != 3) return false;
314
        }
315
 
194 daniel-mar 316
        if ($ary[0] != '2') return false;
317
        if ($ary[1] != '25') return false;
17 daniel-mar 318
        for ($i=2; $i<count($ary); $i++) {
319
                $v = $ary[$i];
320
                if (!is_numeric($v)) return false;
194 daniel-mar 321
                if ($i == 2) {
322
                        // Must be in the range of 128 bit UUID
323
                        $test = gmp_init($v, 10);
324
                        if (strlen(gmp_strval($test, 16)) > 32) return false;
325
                }
17 daniel-mar 326
                if ($v < 0) return false;
327
        }
328
 
329
        return true;
330
}
331
 
332
function uuid_to_oid($uuid) {
333
        if (!uuid_valid($uuid)) return false;
334
 
335
        $uuid = str_replace(array('-', '{', '}'), '', $uuid);
336
        $x = gmp_init($uuid, 16);
191 daniel-mar 337
        return '2.25.'.gmp_strval($x, 10); # TODO: parameter with or without leading dot
17 daniel-mar 338
}
339
 
193 daniel-mar 340
function gen_uuid($prefer_timebased = true) {
341
        if ($prefer_timebased) $uuid = gen_uuid_timebased();
342
        if ($uuid === false) $uuid = gen_uuid_random();
343
        return $uuid;
17 daniel-mar 344
}
345
 
193 daniel-mar 346
// Version 1 (Time based) UUID
347
function gen_uuid_timebased() {
17 daniel-mar 348
        # On Debian: aptitude install php-uuid
349
        # extension_loaded('uuid')
350
        if (function_exists('uuid_create')) {
351
                # OSSP uuid extension like seen in php5-uuid at Debian 8
352
                /*
353
                $x = uuid_create($context);
193 daniel-mar 354
                uuid_make($context, UUID_MAKE_V1);
17 daniel-mar 355
                uuid_export($context, UUID_FMT_STR, $uuid);
356
                return trim($uuid);
357
                */
358
 
359
                # PECL uuid extension like seen in php-uuid at Debian 9
193 daniel-mar 360
                return trim(uuid_create(UUID_TYPE_TIME));
17 daniel-mar 361
        }
362
 
363
        # On Debian: aptitude install uuid-runtime
193 daniel-mar 364
        $out = array();
365
        exec('uuidgen -t', $out, $ec);
17 daniel-mar 366
        if ($ec == 0) return $out[0];
367
 
193 daniel-mar 368
        # TODO: Implement the time based generation routine ourselves!
369
        # At the moment we cannot determine the time based UUID
370
        return false;
371
}
372
 
373
// Version 2 (DCE Security) UUID
374
function gen_uuid_dce($domain, $id) {
375
        # Start with a version 1 UUID
376
        $uuid = gen_uuid_timebased();
377
 
378
        # Add ID
379
        $uuid = str_pad(dechex($id), 8, '0', STR_PAD_LEFT) . substr($uuid, 8);
380
 
381
        # Add domain
382
        $uuid = substr($uuid,0,21) . str_pad(dechex($domain), 2, '0', STR_PAD_LEFT) . substr($uuid, 23);
383
 
384
        # Change version to 2
385
        $uuid[14] = '2';
386
 
387
        return $uuid;
388
}
389
 
390
// Version 3 (MD5 name based) UUID
391
function gen_uuid_md5_namebased($namespace_uuid, $name) {
392
        if (!uuid_valid($namespace_uuid)) return false;
393
        $namespace_uuid = uuid_canonize($namespace_uuid);
394
        $namespace_uuid = str_replace('-', '', $namespace_uuid);
395
        $namespace_uuid = hex2bin($namespace_uuid);
396
 
397
        $hash = md5($namespace_uuid.$name);
398
        $hash[12] = '3'; // Set version: 3 = MD5
399
        $hash[16] = dechex(hexdec($hash[16]) & 0x3 | 0x8); // Set variant to "10xx" (RFC4122)
400
 
401
        return substr($hash,  0, 8).'-'.
402
               substr($hash,  8, 4).'-'.
403
               substr($hash, 12, 4).'-'.
404
               substr($hash, 16, 4).'-'.
405
               substr($hash, 20, 12);
406
}
407
 
408
// Version 4 (Random) UUID
409
function gen_uuid_random() {
410
        # On Debian: aptitude install php-uuid
411
        # extension_loaded('uuid')
412
        if (function_exists('uuid_create')) {
413
                # OSSP uuid extension like seen in php5-uuid at Debian 8
414
                /*
415
                $x = uuid_create($context);
416
                uuid_make($context, UUID_MAKE_V4);
417
                uuid_export($context, UUID_FMT_STR, $uuid);
418
                return trim($uuid);
419
                */
420
 
421
                # PECL uuid extension like seen in php-uuid at Debian 9
422
                return trim(uuid_create(UUID_TYPE_RANDOM));
17 daniel-mar 423
        }
424
 
193 daniel-mar 425
        # On Debian: aptitude install uuid-runtime
426
        $out = array();
427
        exec('uuidgen -r', $out, $ec);
428
        if ($ec == 0) return $out[0];
17 daniel-mar 429
 
193 daniel-mar 430
        # On Debian Jessie: UUID V4 (Random)
17 daniel-mar 431
        if (file_exists('/proc/sys/kernel/random/uuid')) {
432
                return file_get_contents('/proc/sys/kernel/random/uuid');
433
        }
434
 
193 daniel-mar 435
        # Make the UUID by ourselves
436
        # Source: http://rogerstringer.com/2013/11/15/generate-uuids-php
437
        return sprintf( '%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
438
                mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff ),
439
                mt_rand( 0, 0xffff ),
440
                mt_rand( 0, 0x0fff ) | 0x4000,
441
                mt_rand( 0, 0x3fff ) | 0x8000,
442
                mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff )
443
        );
17 daniel-mar 444
}
445
 
193 daniel-mar 446
// Version 5 (SHA1 name based) UUID
447
function gen_uuid_sha1_namebased($namespace_uuid, $name) {
448
        $namespace_uuid = str_replace('-', '', $namespace_uuid);
449
        $namespace_uuid = hex2bin($namespace_uuid);
450
 
451
        $hash = sha1($namespace_uuid.$name);
452
        $hash[12] = '5'; // Set version: 5 = SHA1
453
        $hash[16] = dechex(hexdec($hash[16]) & 0x3 | 0x8); // Set variant to "10xx" (RFC4122)
454
 
455
        return substr($hash,  0, 8).'-'.
456
               substr($hash,  8, 4).'-'.
457
               substr($hash, 12, 4).'-'.
458
               substr($hash, 16, 4).'-'.
459
               substr($hash, 20, 12);
460
}
461
 
17 daniel-mar 462
function uuid_numeric_value($uuid) {
463
        $oid = uuid_to_oid($uuid);
464
        if (!$oid) return false;
465
        return substr($oid, strlen('2.25.'));
466
}
467
 
468
function uuid_c_syntax($uuid) {
469
        $uuid = str_replace('{', '', $uuid);
470
        return '{ 0x' . substr($uuid, 0, 8) .
471
                ', 0x' . substr($uuid, 9, 4) .
472
                ', 0x' . substr($uuid, 14, 4) .
473
                ', { 0x' . substr($uuid, 19, 2).
474
                ', 0x' . substr($uuid, 21, 2) .
475
                ', 0x' . substr($uuid, 24, 2) .
476
                ', 0x' . substr($uuid, 26, 2) .
477
                ', 0x' . substr($uuid, 28, 2) .
478
                ', 0x' . substr($uuid, 30, 2) .
479
                ', 0x' . substr($uuid, 32, 2) .
480
                ', 0x' . substr($uuid, 34, 2) . ' } }';
481
}
482
 
483
# ---
484
 
485
// http://php.net/manual/de/function.hex2bin.php#113057
486
if ( !function_exists( 'hex2bin' ) ) {
487
    function hex2bin( $str ) {
488
        $sbin = "";
489
        $len = strlen( $str );
490
        for ( $i = 0; $i < $len; $i += 2 ) {
491
            $sbin .= pack( "H*", substr( $str, $i, 2 ) );
492
        }
493
 
494
        return $sbin;
495
    }
496
}