286 lines
		
	
	
		
			22 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			286 lines
		
	
	
		
			22 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
(function () {
 | 
						|
 | 
						|
/* Imports */
 | 
						|
var Meteor = Package.meteor.Meteor;
 | 
						|
var _ = Package.underscore._;
 | 
						|
 | 
						|
/* Package-scope variables */
 | 
						|
var Random;
 | 
						|
 | 
						|
(function () {
 | 
						|
 | 
						|
//////////////////////////////////////////////////////////////////////////////////////
 | 
						|
//                                                                                  //
 | 
						|
// packages/random/random.js                                                        //
 | 
						|
//                                                                                  //
 | 
						|
//////////////////////////////////////////////////////////////////////////////////////
 | 
						|
                                                                                    //
 | 
						|
// We use cryptographically strong PRNGs (crypto.getRandomBytes() on the server,    // 1
 | 
						|
// window.crypto.getRandomValues() in the browser) when available. If these         // 2
 | 
						|
// PRNGs fail, we fall back to the Alea PRNG, which is not cryptographically        // 3
 | 
						|
// strong, and we seed it with various sources such as the date, Math.random,       // 4
 | 
						|
// and window size on the client.  When using crypto.getRandomValues(), our         // 5
 | 
						|
// primitive is hexString(), from which we construct fraction(). When using         // 6
 | 
						|
// window.crypto.getRandomValues() or alea, the primitive is fraction and we use    // 7
 | 
						|
// that to construct hex string.                                                    // 8
 | 
						|
                                                                                    // 9
 | 
						|
if (Meteor.isServer)                                                                // 10
 | 
						|
  var nodeCrypto = Npm.require('crypto');                                           // 11
 | 
						|
                                                                                    // 12
 | 
						|
// see http://baagoe.org/en/wiki/Better_random_numbers_for_javascript               // 13
 | 
						|
// for a full discussion and Alea implementation.                                   // 14
 | 
						|
var Alea = function () {                                                            // 15
 | 
						|
  function Mash() {                                                                 // 16
 | 
						|
    var n = 0xefc8249d;                                                             // 17
 | 
						|
                                                                                    // 18
 | 
						|
    var mash = function(data) {                                                     // 19
 | 
						|
      data = data.toString();                                                       // 20
 | 
						|
      for (var i = 0; i < data.length; i++) {                                       // 21
 | 
						|
        n += data.charCodeAt(i);                                                    // 22
 | 
						|
        var h = 0.02519603282416938 * n;                                            // 23
 | 
						|
        n = h >>> 0;                                                                // 24
 | 
						|
        h -= n;                                                                     // 25
 | 
						|
        h *= n;                                                                     // 26
 | 
						|
        n = h >>> 0;                                                                // 27
 | 
						|
        h -= n;                                                                     // 28
 | 
						|
        n += h * 0x100000000; // 2^32                                               // 29
 | 
						|
      }                                                                             // 30
 | 
						|
      return (n >>> 0) * 2.3283064365386963e-10; // 2^-32                           // 31
 | 
						|
    };                                                                              // 32
 | 
						|
                                                                                    // 33
 | 
						|
    mash.version = 'Mash 0.9';                                                      // 34
 | 
						|
    return mash;                                                                    // 35
 | 
						|
  }                                                                                 // 36
 | 
						|
                                                                                    // 37
 | 
						|
  return (function (args) {                                                         // 38
 | 
						|
    var s0 = 0;                                                                     // 39
 | 
						|
    var s1 = 0;                                                                     // 40
 | 
						|
    var s2 = 0;                                                                     // 41
 | 
						|
    var c = 1;                                                                      // 42
 | 
						|
                                                                                    // 43
 | 
						|
    if (args.length == 0) {                                                         // 44
 | 
						|
      args = [+new Date];                                                           // 45
 | 
						|
    }                                                                               // 46
 | 
						|
    var mash = Mash();                                                              // 47
 | 
						|
    s0 = mash(' ');                                                                 // 48
 | 
						|
    s1 = mash(' ');                                                                 // 49
 | 
						|
    s2 = mash(' ');                                                                 // 50
 | 
						|
                                                                                    // 51
 | 
						|
    for (var i = 0; i < args.length; i++) {                                         // 52
 | 
						|
      s0 -= mash(args[i]);                                                          // 53
 | 
						|
      if (s0 < 0) {                                                                 // 54
 | 
						|
        s0 += 1;                                                                    // 55
 | 
						|
      }                                                                             // 56
 | 
						|
      s1 -= mash(args[i]);                                                          // 57
 | 
						|
      if (s1 < 0) {                                                                 // 58
 | 
						|
        s1 += 1;                                                                    // 59
 | 
						|
      }                                                                             // 60
 | 
						|
      s2 -= mash(args[i]);                                                          // 61
 | 
						|
      if (s2 < 0) {                                                                 // 62
 | 
						|
        s2 += 1;                                                                    // 63
 | 
						|
      }                                                                             // 64
 | 
						|
    }                                                                               // 65
 | 
						|
    mash = null;                                                                    // 66
 | 
						|
                                                                                    // 67
 | 
						|
    var random = function() {                                                       // 68
 | 
						|
      var t = 2091639 * s0 + c * 2.3283064365386963e-10; // 2^-32                   // 69
 | 
						|
      s0 = s1;                                                                      // 70
 | 
						|
      s1 = s2;                                                                      // 71
 | 
						|
      return s2 = t - (c = t | 0);                                                  // 72
 | 
						|
    };                                                                              // 73
 | 
						|
    random.uint32 = function() {                                                    // 74
 | 
						|
      return random() * 0x100000000; // 2^32                                        // 75
 | 
						|
    };                                                                              // 76
 | 
						|
    random.fract53 = function() {                                                   // 77
 | 
						|
      return random() +                                                             // 78
 | 
						|
        (random() * 0x200000 | 0) * 1.1102230246251565e-16; // 2^-53                // 79
 | 
						|
    };                                                                              // 80
 | 
						|
    random.version = 'Alea 0.9';                                                    // 81
 | 
						|
    random.args = args;                                                             // 82
 | 
						|
    return random;                                                                  // 83
 | 
						|
                                                                                    // 84
 | 
						|
  } (Array.prototype.slice.call(arguments)));                                       // 85
 | 
						|
};                                                                                  // 86
 | 
						|
                                                                                    // 87
 | 
						|
var UNMISTAKABLE_CHARS = "23456789ABCDEFGHJKLMNPQRSTWXYZabcdefghijkmnopqrstuvwxyz"; // 88
 | 
						|
var BASE64_CHARS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" +         // 89
 | 
						|
  "0123456789-_";                                                                   // 90
 | 
						|
                                                                                    // 91
 | 
						|
// If seeds are provided, then the alea PRNG will be used, since cryptographic      // 92
 | 
						|
// PRNGs (Node crypto and window.crypto.getRandomValues) don't allow us to          // 93
 | 
						|
// specify seeds. The caller is responsible for making sure to provide a seed       // 94
 | 
						|
// for alea if a csprng is not available.                                           // 95
 | 
						|
var RandomGenerator = function (seedArray) {                                        // 96
 | 
						|
  var self = this;                                                                  // 97
 | 
						|
  if (seedArray !== undefined)                                                      // 98
 | 
						|
    self.alea = Alea.apply(null, seedArray);                                        // 99
 | 
						|
};                                                                                  // 100
 | 
						|
                                                                                    // 101
 | 
						|
RandomGenerator.prototype.fraction = function () {                                  // 102
 | 
						|
  var self = this;                                                                  // 103
 | 
						|
  if (self.alea) {                                                                  // 104
 | 
						|
    return self.alea();                                                             // 105
 | 
						|
  } else if (nodeCrypto) {                                                          // 106
 | 
						|
    var numerator = parseInt(self.hexString(8), 16);                                // 107
 | 
						|
    return numerator * 2.3283064365386963e-10; // 2^-32                             // 108
 | 
						|
  } else if (typeof window !== "undefined" && window.crypto &&                      // 109
 | 
						|
             window.crypto.getRandomValues) {                                       // 110
 | 
						|
    var array = new Uint32Array(1);                                                 // 111
 | 
						|
    window.crypto.getRandomValues(array);                                           // 112
 | 
						|
    return array[0] * 2.3283064365386963e-10; // 2^-32                              // 113
 | 
						|
  } else {                                                                          // 114
 | 
						|
    throw new Error('No random generator available');                               // 115
 | 
						|
  }                                                                                 // 116
 | 
						|
};                                                                                  // 117
 | 
						|
                                                                                    // 118
 | 
						|
RandomGenerator.prototype.hexString = function (digits) {                           // 119
 | 
						|
  var self = this;                                                                  // 120
 | 
						|
  if (nodeCrypto && ! self.alea) {                                                  // 121
 | 
						|
    var numBytes = Math.ceil(digits / 2);                                           // 122
 | 
						|
    var bytes;                                                                      // 123
 | 
						|
    // Try to get cryptographically strong randomness. Fall back to                 // 124
 | 
						|
    // non-cryptographically strong if not available.                               // 125
 | 
						|
    try {                                                                           // 126
 | 
						|
      bytes = nodeCrypto.randomBytes(numBytes);                                     // 127
 | 
						|
    } catch (e) {                                                                   // 128
 | 
						|
      // XXX should re-throw any error except insufficient entropy                  // 129
 | 
						|
      bytes = nodeCrypto.pseudoRandomBytes(numBytes);                               // 130
 | 
						|
    }                                                                               // 131
 | 
						|
    var result = bytes.toString("hex");                                             // 132
 | 
						|
    // If the number of digits is odd, we'll have generated an extra 4 bits         // 133
 | 
						|
    // of randomness, so we need to trim the last digit.                            // 134
 | 
						|
    return result.substring(0, digits);                                             // 135
 | 
						|
  } else {                                                                          // 136
 | 
						|
    var hexDigits = [];                                                             // 137
 | 
						|
    for (var i = 0; i < digits; ++i) {                                              // 138
 | 
						|
      hexDigits.push(self.choice("0123456789abcdef"));                              // 139
 | 
						|
    }                                                                               // 140
 | 
						|
    return hexDigits.join('');                                                      // 141
 | 
						|
  }                                                                                 // 142
 | 
						|
};                                                                                  // 143
 | 
						|
                                                                                    // 144
 | 
						|
RandomGenerator.prototype._randomString = function (charsCount,                     // 145
 | 
						|
                                                    alphabet) {                     // 146
 | 
						|
  var self = this;                                                                  // 147
 | 
						|
  var digits = [];                                                                  // 148
 | 
						|
  for (var i = 0; i < charsCount; i++) {                                            // 149
 | 
						|
    digits[i] = self.choice(alphabet);                                              // 150
 | 
						|
  }                                                                                 // 151
 | 
						|
  return digits.join("");                                                           // 152
 | 
						|
};                                                                                  // 153
 | 
						|
                                                                                    // 154
 | 
						|
RandomGenerator.prototype.id = function (charsCount) {                              // 155
 | 
						|
  var self = this;                                                                  // 156
 | 
						|
  // 17 characters is around 96 bits of entropy, which is the amount of             // 157
 | 
						|
  // state in the Alea PRNG.                                                        // 158
 | 
						|
  if (charsCount === undefined)                                                     // 159
 | 
						|
    charsCount = 17;                                                                // 160
 | 
						|
                                                                                    // 161
 | 
						|
  return self._randomString(charsCount, UNMISTAKABLE_CHARS);                        // 162
 | 
						|
};                                                                                  // 163
 | 
						|
                                                                                    // 164
 | 
						|
RandomGenerator.prototype.secret = function (charsCount) {                          // 165
 | 
						|
  var self = this;                                                                  // 166
 | 
						|
  // Default to 256 bits of entropy, or 43 characters at 6 bits per                 // 167
 | 
						|
  // character.                                                                     // 168
 | 
						|
  if (charsCount === undefined)                                                     // 169
 | 
						|
    charsCount = 43;                                                                // 170
 | 
						|
  return self._randomString(charsCount, BASE64_CHARS);                              // 171
 | 
						|
};                                                                                  // 172
 | 
						|
                                                                                    // 173
 | 
						|
RandomGenerator.prototype.choice = function (arrayOrString) {                       // 174
 | 
						|
  var index = Math.floor(this.fraction() * arrayOrString.length);                   // 175
 | 
						|
  if (typeof arrayOrString === "string")                                            // 176
 | 
						|
    return arrayOrString.substr(index, 1);                                          // 177
 | 
						|
  else                                                                              // 178
 | 
						|
    return arrayOrString[index];                                                    // 179
 | 
						|
};                                                                                  // 180
 | 
						|
                                                                                    // 181
 | 
						|
// instantiate RNG.  Heuristically collect entropy from various sources when a      // 182
 | 
						|
// cryptographic PRNG isn't available.                                              // 183
 | 
						|
                                                                                    // 184
 | 
						|
// client sources                                                                   // 185
 | 
						|
var height = (typeof window !== 'undefined' && window.innerHeight) ||               // 186
 | 
						|
      (typeof document !== 'undefined'                                              // 187
 | 
						|
       && document.documentElement                                                  // 188
 | 
						|
       && document.documentElement.clientHeight) ||                                 // 189
 | 
						|
      (typeof document !== 'undefined'                                              // 190
 | 
						|
       && document.body                                                             // 191
 | 
						|
       && document.body.clientHeight) ||                                            // 192
 | 
						|
      1;                                                                            // 193
 | 
						|
                                                                                    // 194
 | 
						|
var width = (typeof window !== 'undefined' && window.innerWidth) ||                 // 195
 | 
						|
      (typeof document !== 'undefined'                                              // 196
 | 
						|
       && document.documentElement                                                  // 197
 | 
						|
       && document.documentElement.clientWidth) ||                                  // 198
 | 
						|
      (typeof document !== 'undefined'                                              // 199
 | 
						|
       && document.body                                                             // 200
 | 
						|
       && document.body.clientWidth) ||                                             // 201
 | 
						|
      1;                                                                            // 202
 | 
						|
                                                                                    // 203
 | 
						|
var agent = (typeof navigator !== 'undefined' && navigator.userAgent) || "";        // 204
 | 
						|
                                                                                    // 205
 | 
						|
if (nodeCrypto ||                                                                   // 206
 | 
						|
    (typeof window !== "undefined" &&                                               // 207
 | 
						|
     window.crypto && window.crypto.getRandomValues))                               // 208
 | 
						|
  Random = new RandomGenerator();                                                   // 209
 | 
						|
else                                                                                // 210
 | 
						|
  Random = new RandomGenerator([new Date(), height, width, agent, Math.random()]);  // 211
 | 
						|
                                                                                    // 212
 | 
						|
Random.createWithSeeds = function () {                                              // 213
 | 
						|
  if (arguments.length === 0) {                                                     // 214
 | 
						|
    throw new Error('No seeds were provided');                                      // 215
 | 
						|
  }                                                                                 // 216
 | 
						|
  return new RandomGenerator(arguments);                                            // 217
 | 
						|
};                                                                                  // 218
 | 
						|
                                                                                    // 219
 | 
						|
//////////////////////////////////////////////////////////////////////////////////////
 | 
						|
 | 
						|
}).call(this);
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
(function () {
 | 
						|
 | 
						|
//////////////////////////////////////////////////////////////////////////////////////
 | 
						|
//                                                                                  //
 | 
						|
// packages/random/deprecated.js                                                    //
 | 
						|
//                                                                                  //
 | 
						|
//////////////////////////////////////////////////////////////////////////////////////
 | 
						|
                                                                                    //
 | 
						|
// Before this package existed, we used to use this Meteor.uuid()                   // 1
 | 
						|
// implementing the RFC 4122 v4 UUID. It is no longer documented                    // 2
 | 
						|
// and will go away.                                                                // 3
 | 
						|
// XXX COMPAT WITH 0.5.6                                                            // 4
 | 
						|
Meteor.uuid = function () {                                                         // 5
 | 
						|
  var HEX_DIGITS = "0123456789abcdef";                                              // 6
 | 
						|
  var s = [];                                                                       // 7
 | 
						|
  for (var i = 0; i < 36; i++) {                                                    // 8
 | 
						|
    s[i] = Random.choice(HEX_DIGITS);                                               // 9
 | 
						|
  }                                                                                 // 10
 | 
						|
  s[14] = "4";                                                                      // 11
 | 
						|
  s[19] = HEX_DIGITS.substr((parseInt(s[19],16) & 0x3) | 0x8, 1);                   // 12
 | 
						|
  s[8] = s[13] = s[18] = s[23] = "-";                                               // 13
 | 
						|
                                                                                    // 14
 | 
						|
  var uuid = s.join("");                                                            // 15
 | 
						|
  return uuid;                                                                      // 16
 | 
						|
};                                                                                  // 17
 | 
						|
                                                                                    // 18
 | 
						|
//////////////////////////////////////////////////////////////////////////////////////
 | 
						|
 | 
						|
}).call(this);
 | 
						|
 | 
						|
 | 
						|
/* Exports */
 | 
						|
if (typeof Package === 'undefined') Package = {};
 | 
						|
Package.random = {
 | 
						|
  Random: Random
 | 
						|
};
 | 
						|
 | 
						|
})();
 | 
						|
 | 
						|
//# sourceMappingURL=random.js.map
 |