| 
0
 | 
     1 //     uuid.js
 | 
| 
 | 
     2 //
 | 
| 
 | 
     3 //     Copyright (c) 2010-2012 Robert Kieffer
 | 
| 
 | 
     4 //     MIT License - http://opensource.org/licenses/mit-license.php
 | 
| 
 | 
     5 define(
 | 
| 
 | 
     6     [],
 | 
| 
 | 
     7     function () {
 | 
| 
 | 
     8         'use strict';
 | 
| 
 | 
     9 
 | 
| 
 | 
    10         var _window = 'undefined' !== typeof window ? window : null;
 | 
| 
 | 
    11 
 | 
| 
 | 
    12         // Unique ID creation requires a high quality random # generator. We
 | 
| 
 | 
    13         // feature
 | 
| 
 | 
    14         // detect to determine the best RNG source, normalizing to a function
 | 
| 
 | 
    15         // that
 | 
| 
 | 
    16         // returns 128-bits of randomness, since that's what's usually required
 | 
| 
 | 
    17         var _rng, _mathRNG, _nodeRNG, _whatwgRNG, _previousRoot;
 | 
| 
 | 
    18 
 | 
| 
 | 
    19         function setupBrowser() {
 | 
| 
 | 
    20             // Allow for MSIE11 msCrypto
 | 
| 
 | 
    21             var _crypto = _window.crypto || _window.msCrypto;
 | 
| 
 | 
    22 
 | 
| 
 | 
    23             if (!_rng && _crypto && _crypto.getRandomValues) {
 | 
| 
 | 
    24                 // WHATWG crypto-based RNG - http://wiki.whatwg.org/wiki/Crypto
 | 
| 
 | 
    25                 //
 | 
| 
 | 
    26                 // Moderately fast, high quality
 | 
| 
 | 
    27                 try {
 | 
| 
 | 
    28                     var _rnds8 = new Uint8Array(16);
 | 
| 
 | 
    29                     _whatwgRNG = _rng = function whatwgRNG() {
 | 
| 
 | 
    30                         _crypto.getRandomValues(_rnds8);
 | 
| 
 | 
    31                         return _rnds8;
 | 
| 
 | 
    32                     };
 | 
| 
 | 
    33                     _rng();
 | 
| 
 | 
    34                 } catch (e) {}
 | 
| 
 | 
    35             }
 | 
| 
 | 
    36 
 | 
| 
 | 
    37             if (!_rng) {
 | 
| 
 | 
    38                 // Math.random()-based (RNG)
 | 
| 
 | 
    39                 //
 | 
| 
 | 
    40                 // If all else fails, use Math.random(). It's fast, but is of
 | 
| 
 | 
    41                 // unspecified
 | 
| 
 | 
    42                 // quality.
 | 
| 
 | 
    43                 var _rnds = new Array(16);
 | 
| 
 | 
    44                 _mathRNG = _rng = function () {
 | 
| 
 | 
    45                     for (var i = 0, r; i < 16; i++) {
 | 
| 
 | 
    46                         if ((i & 0x03) === 0) {
 | 
| 
 | 
    47                             r = Math.random() * 0x100000000;
 | 
| 
 | 
    48                         }
 | 
| 
 | 
    49                         _rnds[i] = r >>> ((i & 0x03) << 3) & 0xff;
 | 
| 
 | 
    50                     }
 | 
| 
 | 
    51 
 | 
| 
 | 
    52                     return _rnds;
 | 
| 
 | 
    53                 };
 | 
| 
 | 
    54                 if ('undefined' !== typeof console && console.warn) {
 | 
| 
 | 
    55                     console
 | 
| 
 | 
    56                         .warn("[SECURITY] node-uuid: crypto not usable, falling back to insecure Math.random()");
 | 
| 
 | 
    57                 }
 | 
| 
 | 
    58             }
 | 
| 
 | 
    59         }
 | 
| 
 | 
    60 
 | 
| 
 | 
    61         function setupNode() {
 | 
| 
 | 
    62             // Node.js crypto-based RNG -
 | 
| 
 | 
    63             // http://nodejs.org/docs/v0.6.2/api/crypto.html
 | 
| 
 | 
    64             //
 | 
| 
 | 
    65             // Moderately fast, high quality
 | 
| 
 | 
    66             if ('function' === typeof require) {
 | 
| 
 | 
    67                 try {
 | 
| 
 | 
    68                     var _rb = require('crypto').randomBytes;
 | 
| 
 | 
    69                     _nodeRNG = _rng = _rb && function () {
 | 
| 
 | 
    70                         return _rb(16);
 | 
| 
 | 
    71                     };
 | 
| 
 | 
    72                     _rng();
 | 
| 
 | 
    73                 } catch (e) {}
 | 
| 
 | 
    74             }
 | 
| 
 | 
    75         }
 | 
| 
 | 
    76 
 | 
| 
 | 
    77         if (_window) {
 | 
| 
 | 
    78             setupBrowser();
 | 
| 
 | 
    79         } else {
 | 
| 
 | 
    80             setupNode();
 | 
| 
 | 
    81         }
 | 
| 
 | 
    82 
 | 
| 
 | 
    83         // Buffer class to use
 | 
| 
 | 
    84         var BufferClass = ('function' === typeof Buffer) ? Buffer : Array;
 | 
| 
 | 
    85 
 | 
| 
 | 
    86         // Maps for number <-> hex string conversion
 | 
| 
 | 
    87         var _byteToHex = [];
 | 
| 
 | 
    88         var _hexToByte = {};
 | 
| 
 | 
    89         for (var i = 0; i < 256; i++) {
 | 
| 
 | 
    90             _byteToHex[i] = (i + 0x100).toString(16).substr(1);
 | 
| 
 | 
    91             _hexToByte[_byteToHex[i]] = i;
 | 
| 
 | 
    92         }
 | 
| 
 | 
    93 
 | 
| 
 | 
    94         // **`parse()` - Parse a UUID into it's component bytes**
 | 
| 
 | 
    95         function parse(s, buf, offset) {
 | 
| 
 | 
    96             var i = (buf && offset) || 0,
 | 
| 
 | 
    97                 ii = 0;
 | 
| 
 | 
    98 
 | 
| 
 | 
    99             buf = buf || [];
 | 
| 
 | 
   100             s.toLowerCase().replace(/[0-9a-f]{2}/g, function (oct) {
 | 
| 
 | 
   101                 if (ii < 16) { // Don't overflow!
 | 
| 
 | 
   102                     buf[i + ii++] = _hexToByte[oct];
 | 
| 
 | 
   103                 }
 | 
| 
 | 
   104             });
 | 
| 
 | 
   105 
 | 
| 
 | 
   106             // Zero out remaining bytes if string was short
 | 
| 
 | 
   107             while (ii < 16) {
 | 
| 
 | 
   108                 buf[i + ii++] = 0;
 | 
| 
 | 
   109             }
 | 
| 
 | 
   110 
 | 
| 
 | 
   111             return buf;
 | 
| 
 | 
   112         }
 | 
| 
 | 
   113 
 | 
| 
 | 
   114         // **`unparse()` - Convert UUID byte array (ala parse()) into a string**
 | 
| 
 | 
   115         function unparse(buf, offset) {
 | 
| 
 | 
   116             var i = offset || 0,
 | 
| 
 | 
   117                 bth = _byteToHex;
 | 
| 
 | 
   118             return bth[buf[i++]] + bth[buf[i++]] + bth[buf[i++]] +
 | 
| 
 | 
   119                 bth[buf[i++]] + '-' + bth[buf[i++]] + bth[buf[i++]] + '-' +
 | 
| 
 | 
   120                 bth[buf[i++]] + bth[buf[i++]] + '-' + bth[buf[i++]] +
 | 
| 
 | 
   121                 bth[buf[i++]] + '-' + bth[buf[i++]] + bth[buf[i++]] +
 | 
| 
 | 
   122                 bth[buf[i++]] + bth[buf[i++]] + bth[buf[i++]] + bth[buf[i++]];
 | 
| 
 | 
   123         }
 | 
| 
 | 
   124 
 | 
| 
 | 
   125         // **`v1()` - Generate time-based UUID**
 | 
| 
 | 
   126         //
 | 
| 
 | 
   127         // Inspired by https://github.com/LiosK/UUID.js
 | 
| 
 | 
   128         // and http://docs.python.org/library/uuid.html
 | 
| 
 | 
   129 
 | 
| 
 | 
   130         // random #'s we need to init node and clockseq
 | 
| 
 | 
   131         var _seedBytes = _rng();
 | 
| 
 | 
   132 
 | 
| 
 | 
   133         // Per 4.5, create and 48-bit node id, (47 random bits + multicast bit =
 | 
| 
 | 
   134         // 1)
 | 
| 
 | 
   135         var _nodeId = [
 | 
| 
 | 
   136             _seedBytes[0] | 0x01,
 | 
| 
 | 
   137             _seedBytes[1],
 | 
| 
 | 
   138             _seedBytes[2],
 | 
| 
 | 
   139             _seedBytes[3],
 | 
| 
 | 
   140             _seedBytes[4],
 | 
| 
 | 
   141             _seedBytes[5]
 | 
| 
 | 
   142         ];
 | 
| 
 | 
   143 
 | 
| 
 | 
   144         // Per 4.2.2, randomize (14 bit) clockseq
 | 
| 
 | 
   145         var _clockseq = (_seedBytes[6] << 8 | _seedBytes[7]) & 0x3fff;
 | 
| 
 | 
   146 
 | 
| 
 | 
   147         // Previous uuid creation time
 | 
| 
 | 
   148         var _lastMSecs = 0,
 | 
| 
 | 
   149             _lastNSecs = 0;
 | 
| 
 | 
   150 
 | 
| 
 | 
   151         // See https://github.com/broofa/node-uuid for API details
 | 
| 
 | 
   152         function v1(options, buf, offset) {
 | 
| 
 | 
   153             var i = buf && offset || 0;
 | 
| 
 | 
   154             var b = buf || [];
 | 
| 
 | 
   155 
 | 
| 
 | 
   156             options = options || {};
 | 
| 
 | 
   157 
 | 
| 
 | 
   158             var clockseq = (options.clockseq != null) ? options.clockseq : _clockseq;
 | 
| 
 | 
   159 
 | 
| 
 | 
   160             // UUID timestamps are 100 nano-second units since the Gregorian
 | 
| 
 | 
   161             // epoch,
 | 
| 
 | 
   162             // (1582-10-15 00:00). JSNumbers aren't precise enough for this, so
 | 
| 
 | 
   163             // time is handled internally as 'msecs' (integer milliseconds) and
 | 
| 
 | 
   164             // 'nsecs'
 | 
| 
 | 
   165             // (100-nanoseconds offset from msecs) since unix epoch, 1970-01-01
 | 
| 
 | 
   166             // 00:00.
 | 
| 
 | 
   167             var msecs = (options.msecs != null) ? options.msecs : new Date()
 | 
| 
 | 
   168                 .getTime();
 | 
| 
 | 
   169 
 | 
| 
 | 
   170             // Per 4.2.1.2, use count of uuid's generated during the current
 | 
| 
 | 
   171             // clock
 | 
| 
 | 
   172             // cycle to simulate higher resolution clock
 | 
| 
 | 
   173             var nsecs = (options.nsecs != null) ? options.nsecs : _lastNSecs + 1;
 | 
| 
 | 
   174 
 | 
| 
 | 
   175             // Time since last uuid creation (in msecs)
 | 
| 
 | 
   176             var dt = (msecs - _lastMSecs) + (nsecs - _lastNSecs) / 10000;
 | 
| 
 | 
   177 
 | 
| 
 | 
   178             // Per 4.2.1.2, Bump clockseq on clock regression
 | 
| 
 | 
   179             if (dt < 0 && options.clockseq == null) {
 | 
| 
 | 
   180                 clockseq = clockseq + 1 & 0x3fff;
 | 
| 
 | 
   181             }
 | 
| 
 | 
   182 
 | 
| 
 | 
   183             // Reset nsecs if clock regresses (new clockseq) or we've moved onto
 | 
| 
 | 
   184             // a new
 | 
| 
 | 
   185             // time interval
 | 
| 
 | 
   186             if ((dt < 0 || msecs > _lastMSecs) && options.nsecs == null) {
 | 
| 
 | 
   187                 nsecs = 0;
 | 
| 
 | 
   188             }
 | 
| 
 | 
   189 
 | 
| 
 | 
   190             // Per 4.2.1.2 Throw error if too many uuids are requested
 | 
| 
 | 
   191             if (nsecs >= 10000) {
 | 
| 
 | 
   192                 throw new Error(
 | 
| 
 | 
   193                     'uuid.v1(): Can\'t create more than 10M uuids/sec');
 | 
| 
 | 
   194             }
 | 
| 
 | 
   195 
 | 
| 
 | 
   196             _lastMSecs = msecs;
 | 
| 
 | 
   197             _lastNSecs = nsecs;
 | 
| 
 | 
   198             _clockseq = clockseq;
 | 
| 
 | 
   199 
 | 
| 
 | 
   200             // Per 4.1.4 - Convert from unix epoch to Gregorian epoch
 | 
| 
 | 
   201             msecs += 12219292800000;
 | 
| 
 | 
   202 
 | 
| 
 | 
   203             // `time_low`
 | 
| 
 | 
   204             var tl = ((msecs & 0xfffffff) * 10000 + nsecs) % 0x100000000;
 | 
| 
 | 
   205             b[i++] = tl >>> 24 & 0xff;
 | 
| 
 | 
   206             b[i++] = tl >>> 16 & 0xff;
 | 
| 
 | 
   207             b[i++] = tl >>> 8 & 0xff;
 | 
| 
 | 
   208             b[i++] = tl & 0xff;
 | 
| 
 | 
   209 
 | 
| 
 | 
   210             // `time_mid`
 | 
| 
 | 
   211             var tmh = (msecs / 0x100000000 * 10000) & 0xfffffff;
 | 
| 
 | 
   212             b[i++] = tmh >>> 8 & 0xff;
 | 
| 
 | 
   213             b[i++] = tmh & 0xff;
 | 
| 
 | 
   214 
 | 
| 
 | 
   215             // `time_high_and_version`
 | 
| 
 | 
   216             b[i++] = tmh >>> 24 & 0xf | 0x10; // include version
 | 
| 
 | 
   217             b[i++] = tmh >>> 16 & 0xff;
 | 
| 
 | 
   218 
 | 
| 
 | 
   219             // `clock_seq_hi_and_reserved` (Per 4.2.2 - include variant)
 | 
| 
 | 
   220             b[i++] = clockseq >>> 8 | 0x80;
 | 
| 
 | 
   221 
 | 
| 
 | 
   222             // `clock_seq_low`
 | 
| 
 | 
   223             b[i++] = clockseq & 0xff;
 | 
| 
 | 
   224 
 | 
| 
 | 
   225             // `node`
 | 
| 
 | 
   226             var node = options.node || _nodeId;
 | 
| 
 | 
   227             for (var n = 0; n < 6; n++) {
 | 
| 
 | 
   228                 b[i + n] = node[n];
 | 
| 
 | 
   229             }
 | 
| 
 | 
   230 
 | 
| 
 | 
   231             return buf ? buf : unparse(b);
 | 
| 
 | 
   232         }
 | 
| 
 | 
   233 
 | 
| 
 | 
   234         // **`v4()` - Generate random UUID**
 | 
| 
 | 
   235 
 | 
| 
 | 
   236         // See https://github.com/broofa/node-uuid for API details
 | 
| 
 | 
   237         function v4(options, buf, offset) {
 | 
| 
 | 
   238             // Deprecated - 'format' argument, as supported in v1.2
 | 
| 
 | 
   239             var i = buf && offset || 0;
 | 
| 
 | 
   240 
 | 
| 
 | 
   241             if (typeof (options) === 'string') {
 | 
| 
 | 
   242                 buf = (options === 'binary') ? new BufferClass(16) : null;
 | 
| 
 | 
   243                 options = null;
 | 
| 
 | 
   244             }
 | 
| 
 | 
   245             options = options || {};
 | 
| 
 | 
   246 
 | 
| 
 | 
   247             var rnds = options.random || (options.rng || _rng)();
 | 
| 
 | 
   248 
 | 
| 
 | 
   249             // Per 4.4, set bits for version and `clock_seq_hi_and_reserved`
 | 
| 
 | 
   250             rnds[6] = (rnds[6] & 0x0f) | 0x40;
 | 
| 
 | 
   251             rnds[8] = (rnds[8] & 0x3f) | 0x80;
 | 
| 
 | 
   252 
 | 
| 
 | 
   253             // Copy bytes to buffer, if provided
 | 
| 
 | 
   254             if (buf) {
 | 
| 
 | 
   255                 for (var ii = 0; ii < 16; ii++) {
 | 
| 
 | 
   256                     buf[i + ii] = rnds[ii];
 | 
| 
 | 
   257                 }
 | 
| 
 | 
   258             }
 | 
| 
 | 
   259 
 | 
| 
 | 
   260             return buf || unparse(rnds);
 | 
| 
 | 
   261         }
 | 
| 
 | 
   262 
 | 
| 
 | 
   263         // Export public API
 | 
| 
 | 
   264         var uuid = function() {
 | 
| 
 | 
   265             return new String(v4());
 | 
| 
 | 
   266         };
 | 
| 
 | 
   267         uuid.v1 = v1;
 | 
| 
 | 
   268         uuid.v4 = v4;
 | 
| 
 | 
   269         uuid.create = v4;
 | 
| 
 | 
   270         uuid.empty = "00000000-0000-0000-0000-000000000000";
 | 
| 
 | 
   271         uuid.parse = parse;
 | 
| 
 | 
   272         uuid.unparse = unparse;
 | 
| 
 | 
   273         uuid.BufferClass = BufferClass;
 | 
| 
 | 
   274         uuid._rng = _rng;
 | 
| 
 | 
   275         uuid._mathRNG = _mathRNG;
 | 
| 
 | 
   276         uuid._nodeRNG = _nodeRNG;
 | 
| 
 | 
   277         uuid._whatwgRNG = _whatwgRNG;
 | 
| 
 | 
   278 
 | 
| 
 | 
   279         return uuid;
 | 
| 
 | 
   280     }); |