diff options
| author | Shinigami <[email protected]> | 2022-01-24 19:30:46 +0100 |
|---|---|---|
| committer | GitHub <[email protected]> | 2022-01-24 19:30:46 +0100 |
| commit | a3792251766ed9a87a59c760ea87f64792e54caa (patch) | |
| tree | 9a9dc7ee3b67bf08f9db7b14326385f118d39ca0 /src | |
| parent | be6ea47ffab857e3328bc620502b31732d53d82d (diff) | |
| download | faker-a3792251766ed9a87a59c760ea87f64792e54caa.tar.xz faker-a3792251766ed9a87a59c760ea87f64792e54caa.zip | |
chore: migrate vendor (#254)
Diffstat (limited to 'src')
| -rw-r--r-- | src/internet.ts | 2 | ||||
| -rw-r--r-- | src/mersenne.ts | 2 | ||||
| -rw-r--r-- | src/unique.ts | 13 | ||||
| -rw-r--r-- | src/vendor/mersenne.ts | 292 | ||||
| -rw-r--r-- | src/vendor/unique.ts | 121 | ||||
| -rw-r--r-- | src/vendor/user-agent.ts | 389 |
6 files changed, 811 insertions, 8 deletions
diff --git a/src/internet.ts b/src/internet.ts index 6384b155..3b7f0291 100644 --- a/src/internet.ts +++ b/src/internet.ts @@ -1,6 +1,6 @@ import type { Faker } from '.'; -const random_ua = require('../vendor/user-agent'); +import * as random_ua from './vendor/user-agent'; export class Internet { constructor(private readonly faker: Faker) { diff --git a/src/mersenne.ts b/src/mersenne.ts index fe7fbb44..7f42501e 100644 --- a/src/mersenne.ts +++ b/src/mersenne.ts @@ -1,4 +1,4 @@ -const Gen = require('../vendor/mersenne').MersenneTwister19937; +import Gen from './vendor/mersenne'; export class Mersenne { private gen = new Gen(); diff --git a/src/unique.ts b/src/unique.ts index c077ea58..382d2e2d 100644 --- a/src/unique.ts +++ b/src/unique.ts @@ -1,4 +1,4 @@ -const uniqueExec = require('../vendor/unique'); +import * as uniqueExec from './vendor/unique'; export class Unique { // maximum time unique.exec will attempt to run before aborting @@ -25,17 +25,18 @@ export class Unique { * * @method unique */ - unique( - method: any, - args: any, + unique<Method extends (args: Args) => string, Args extends any[]>( + method: Method, + args: Args, opts?: { startTime?: number; maxTime?: number; maxRetries?: number; currentIterations?: number; - [key: string]: any; + exclude?: string | string[]; + compare?: (obj: Record<string, string>, key: string) => 0 | -1; } - ): any { + ): string { opts ||= {}; opts.startTime = new Date().getTime(); if (typeof opts.maxTime !== 'number') { diff --git a/src/vendor/mersenne.ts b/src/vendor/mersenne.ts new file mode 100644 index 00000000..6a94522b --- /dev/null +++ b/src/vendor/mersenne.ts @@ -0,0 +1,292 @@ +// this program is a JavaScript version of Mersenne Twister, with concealment and encapsulation in class, +// an almost straight conversion from the original program, mt19937ar.c, +// translated by y. okada on July 17, 2006. +// and modified a little at july 20, 2006, but there are not any substantial differences. +// in this program, procedure descriptions and comments of original source code were not removed. +// lines commented with //c// were originally descriptions of c procedure. and a few following lines are appropriate JavaScript descriptions. +// lines commented with /* and */ are original comments. +// lines commented with // are additional comments in this JavaScript version. +// before using this version, create at least one instance of MersenneTwister19937 class, and initialize the each state, given below in c comments, of all the instances. + +/* + * A C-program for MT19937, with initialization improved 2002/1/26. + * Coded by Takuji Nishimura and Makoto Matsumoto. + * + * Before using, initialize the state by using init_genrand(seed) + * or init_by_array(init_key, key_length). + * + * Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura, + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. The names of its contributors may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * + * Any feedback is very welcome. + * http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html + * email: m-mat @ math.sci.hiroshima-u.ac.jp (remove space) + */ + +let dbg: number; + +function MersenneTwister19937(): void { + /* constants should be scoped inside the class */ + /* Period parameters */ + //c//#define N 624 + //c//#define M 397 + //c//#define MATRIX_A 0x9908b0dfUL /* constant vector a */ + //c//#define UPPER_MASK 0x80000000UL /* most significant w-r bits */ + //c//#define LOWER_MASK 0x7fffffffUL /* least significant r bits */ + const N = 624; + const M = 397; + const MATRIX_A = 0x9908b0df; /* constant vector a */ + const UPPER_MASK = 0x80000000; /* most significant w-r bits */ + const LOWER_MASK = 0x7fffffff; /* least significant r bits */ + //c//static unsigned long mt[N]; /* the array for the state vector */ + //c//static int mti=N+1; /* mti==N+1 means mt[N] is not initialized */ + const mt: number[] = new Array(N); /* the array for the state vector */ + let mti = N + 1; /* mti==N+1 means mt[N] is not initialized */ + + function unsigned32(n1: number): number { + // returns a 32-bits unsiged integer from an operand to which applied a bit operator. + return n1 < 0 ? (n1 ^ UPPER_MASK) + UPPER_MASK : n1; + } + + function subtraction32(n1: number, n2: number): number { + // emulates lowerflow of a c 32-bits unsiged integer variable, instead of the operator -. these both arguments must be non-negative integers expressible using unsigned 32 bits. + return n1 < n2 + ? unsigned32((0x100000000 - (n2 - n1)) & 0xffffffff) + : n1 - n2; + } + + function addition32(n1: number, n2: number): number { + // emulates overflow of a c 32-bits unsiged integer variable, instead of the operator +. these both arguments must be non-negative integers expressible using unsigned 32 bits. + return unsigned32((n1 + n2) & 0xffffffff); + } + + function multiplication32(n1: number, n2: number): number { + // emulates overflow of a c 32-bits unsiged integer variable, instead of the operator *. these both arguments must be non-negative integers expressible using unsigned 32 bits. + let sum = 0; + for (let i = 0; i < 32; ++i) { + if ((n1 >>> i) & 0x1) { + sum = addition32(sum, unsigned32(n2 << i)); + } + } + return sum; + } + + /* initializes mt[N] with a seed */ + //c//void init_genrand(unsigned long s) + this.init_genrand = function (s: number) { + //c//mt[0]= s & 0xffffffff; + mt[0] = unsigned32(s & 0xffffffff); + for (mti = 1; mti < N; mti++) { + mt[mti] = + //c//(1812433253 * (mt[mti-1] ^ (mt[mti-1] >> 30)) + mti); + addition32( + multiplication32( + 1812433253, + unsigned32(mt[mti - 1] ^ (mt[mti - 1] >>> 30)) + ), + mti + ); + /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */ + /* In the previous versions, MSBs of the seed affect */ + /* only MSBs of the array mt[]. */ + /* 2002/01/09 modified by Makoto Matsumoto */ + //c//mt[mti] &= 0xffffffff; + mt[mti] = unsigned32(mt[mti] & 0xffffffff); + /* for >32 bit machines */ + } + }; + + /* initialize by an array with array-length */ + /* init_key is the array for initializing keys */ + /* key_length is its length */ + /* slight change for C++, 2004/2/26 */ + //c//void init_by_array(unsigned long init_key[], int key_length) + this.init_by_array = function (init_key, key_length) { + //c//init_genrand(19650218); + this.init_genrand(19650218); + let i = 1; + let j = 0; + let k = N > key_length ? N : key_length; + for (; k; k--) { + //c//mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1664525)) + //c// + init_key[j] + j; /* non linear */ + mt[i] = addition32( + addition32( + unsigned32( + mt[i] ^ + multiplication32( + unsigned32(mt[i - 1] ^ (mt[i - 1] >>> 30)), + 1664525 + ) + ), + init_key[j] + ), + j + ); + mt[i] = + //c//mt[i] &= 0xffffffff; /* for WORDSIZE > 32 machines */ + unsigned32(mt[i] & 0xffffffff); + i++; + j++; + if (i >= N) { + mt[0] = mt[N - 1]; + i = 1; + } + if (j >= key_length) { + j = 0; + } + } + for (k = N - 1; k; k--) { + //c//mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1566083941)) + //c//- i; /* non linear */ + mt[i] = subtraction32( + unsigned32( + (dbg = mt[i]) ^ + multiplication32( + unsigned32(mt[i - 1] ^ (mt[i - 1] >>> 30)), + 1566083941 + ) + ), + i + ); + //c//mt[i] &= 0xffffffff; /* for WORDSIZE > 32 machines */ + mt[i] = unsigned32(mt[i] & 0xffffffff); + i++; + if (i >= N) { + mt[0] = mt[N - 1]; + i = 1; + } + } + mt[0] = 0x80000000; /* MSB is 1; assuring non-zero initial array */ + }; + + /* moved outside of genrand_int32() by jwatte 2010-11-17; generate less garbage */ + const mag01 = [0x0, MATRIX_A]; + + /* generates a random number on [0,0xffffffff]-interval */ + //c//unsigned long genrand_int32(void) + this.genrand_int32 = function () { + //c//unsigned long y; + //c//static unsigned long mag01[2]={0x0UL, MATRIX_A}; + let y: number; + /* mag01[x] = x * MATRIX_A for x=0,1 */ + + if (mti >= N) { + /* generate N words at one time */ + //c//int kk; + let kk: number; + + if (mti == N + 1) { + /* if init_genrand() has not been called, */ + //c//init_genrand(5489); /* a default initial seed is used */ + this.init_genrand(5489); + } /* a default initial seed is used */ + + for (kk = 0; kk < N - M; kk++) { + //c//y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK); + //c//mt[kk] = mt[kk+M] ^ (y >> 1) ^ mag01[y & 0x1]; + y = unsigned32((mt[kk] & UPPER_MASK) | (mt[kk + 1] & LOWER_MASK)); + mt[kk] = unsigned32(mt[kk + M] ^ (y >>> 1) ^ mag01[y & 0x1]); + } + for (; kk < N - 1; kk++) { + //c//y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK); + //c//mt[kk] = mt[kk+(M-N)] ^ (y >> 1) ^ mag01[y & 0x1]; + y = unsigned32((mt[kk] & UPPER_MASK) | (mt[kk + 1] & LOWER_MASK)); + mt[kk] = unsigned32(mt[kk + (M - N)] ^ (y >>> 1) ^ mag01[y & 0x1]); + } + //c//y = (mt[N-1]&UPPER_MASK)|(mt[0]&LOWER_MASK); + //c//mt[N-1] = mt[M-1] ^ (y >> 1) ^ mag01[y & 0x1]; + y = unsigned32((mt[N - 1] & UPPER_MASK) | (mt[0] & LOWER_MASK)); + mt[N - 1] = unsigned32(mt[M - 1] ^ (y >>> 1) ^ mag01[y & 0x1]); + mti = 0; + } + + y = mt[mti++]; + + /* Tempering */ + //c//y ^= (y >> 11); + //c//y ^= (y << 7) & 0x9d2c5680; + //c//y ^= (y << 15) & 0xefc60000; + //c//y ^= (y >> 18); + y = unsigned32(y ^ (y >>> 11)); + y = unsigned32(y ^ ((y << 7) & 0x9d2c5680)); + y = unsigned32(y ^ ((y << 15) & 0xefc60000)); + y = unsigned32(y ^ (y >>> 18)); + + return y; + }; + + /* generates a random number on [0,0x7fffffff]-interval */ + //c//long genrand_int31(void) + this.genrand_int31 = function (): number { + //c//return (genrand_int32()>>1); + return this.genrand_int32() >>> 1; + }; + + /* generates a random number on [0,1]-real-interval */ + //c//double genrand_real1(void) + this.genrand_real1 = function (): number { + //c//return genrand_int32()*(1.0/4294967295.0); + return this.genrand_int32() * (1.0 / 4294967295.0); + /* divided by 2^32-1 */ + }; + + /* generates a random number on [0,1)-real-interval */ + //c//double genrand_real2(void) + this.genrand_real2 = function (): number { + //c//return genrand_int32()*(1.0/4294967296.0); + return this.genrand_int32() * (1.0 / 4294967296.0); + /* divided by 2^32 */ + }; + + /* generates a random number on (0,1)-real-interval */ + //c//double genrand_real3(void) + this.genrand_real3 = function (): number { + //c//return ((genrand_int32()) + 0.5)*(1.0/4294967296.0); + return (this.genrand_int32() + 0.5) * (1.0 / 4294967296.0); + /* divided by 2^32 */ + }; + + /* generates a random number on [0,1) with 53-bit resolution*/ + //c//double genrand_res53(void) + this.genrand_res53 = function (): number { + //c//unsigned long a=genrand_int32()>>5, b=genrand_int32()>>6; + const a = this.genrand_int32() >>> 5, + b = this.genrand_int32() >>> 6; + return (a * 67108864.0 + b) * (1.0 / 9007199254740992.0); + }; + /* These real versions are due to Isaku Wada, 2002/01/09 added */ +} + +// Exports: Public API + +// Export the twister class +export default MersenneTwister19937; diff --git a/src/vendor/unique.ts b/src/vendor/unique.ts new file mode 100644 index 00000000..1fc80d5f --- /dev/null +++ b/src/vendor/unique.ts @@ -0,0 +1,121 @@ +// global results store +// currently uniqueness is global to entire faker instance +// this means that faker should currently *never* return duplicate values across all API methods when using `Faker.unique` +// it's possible in the future that some users may want to scope found per function call instead of faker instance +const found: Record<string, string> = {}; + +// global exclude list of results +// defaults to nothing excluded +const exclude: string[] = []; + +// current iteration or retries of unique.exec ( current loop depth ) +let currentIterations = 0; + +// uniqueness compare function +// default behavior is to check value as key against object hash +function defaultCompare<T, Key extends keyof T>(obj: T, key: Key): 0 | -1 { + if (typeof obj[key] === 'undefined') { + return -1; + } + return 0; +} + +// common error handler for messages +function errorMessage( + now: number, + code: string, + opts: { startTime: number } +): never { + console.error('error', code); + console.log( + 'found', + Object.keys(found).length, + 'unique entries before throwing error. \nretried:', + currentIterations, + '\ntotal time:', + now - opts.startTime, + 'ms' + ); + throw new Error( + code + + ' for uniqueness check \n\nMay not be able to generate any more unique values with current settings. \nTry adjusting maxTime or maxRetries parameters for faker.unique()' + ); +} + +// TODO @Shinigami92 2022-01-24: We should investigate deeper into the types +// Especially the `opts.compare` parameter and `Result` type +export function exec<Method extends (args: Args) => string, Args extends any[]>( + method: Method, + args: Args, + opts: { + maxTime?: number; + maxRetries?: number; + exclude?: string | string[]; + compare?: (obj: Record<string, string>, key: string) => 0 | -1; + currentIterations?: number; + startTime?: number; + } +): string { + const now = new Date().getTime(); + + opts = opts || {}; + opts.maxTime = opts.maxTime || 3; + opts.maxRetries = opts.maxRetries || 50; + opts.exclude = opts.exclude || exclude; + opts.compare = opts.compare || defaultCompare; + + if (typeof opts.currentIterations !== 'number') { + opts.currentIterations = 0; + } + + if (typeof opts.startTime === 'undefined') { + opts.startTime = new Date().getTime(); + } + + const startTime = opts.startTime; + + // support single exclude argument as string + if (typeof opts.exclude === 'string') { + opts.exclude = [opts.exclude]; + } + + if (opts.currentIterations > 0) { + // console.log('iterating', currentIterations) + } + + // console.log(now - startTime) + if (now - startTime >= opts.maxTime) { + return errorMessage( + now, + 'Exceeded maxTime:' + opts.maxTime, + // @ts-expect-error: we know that opts.startTime is defined + opts + ); + } + + if (opts.currentIterations >= opts.maxRetries) { + return errorMessage( + now, + 'Exceeded maxRetries:' + opts.maxRetries, + // @ts-expect-error: we know that opts.startTime is defined + opts + ); + } + + // execute the provided method to find a potential satisfied value + const result: string = method.apply(this, args); + + // if the result has not been previously found, add it to the found array and return the value as it's unique + if ( + opts.compare(found, result) === -1 && + opts.exclude.indexOf(result) === -1 + ) { + found[result] = result; + opts.currentIterations = 0; + return result; + } else { + // console.log('conflict', result); + opts.currentIterations++; + return exec(method, args, opts); + } +} diff --git a/src/vendor/user-agent.ts b/src/vendor/user-agent.ts new file mode 100644 index 00000000..4aef3381 --- /dev/null +++ b/src/vendor/user-agent.ts @@ -0,0 +1,389 @@ +/* + * Copyright (c) 2012-2014 Jeffrey Mealo + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and + * to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * ------------------------------------------------------------------------------------------------------------------------ + * + * Based loosely on Luka Pusic's PHP Script: http://360percents.com/posts/php-random-user-agent-generator/ + * + * The license for that script is as follows: + * + * "THE BEER-WARE LICENSE" (Revision 42): + * + * <[email protected]> wrote this file. As long as you retain this notice you can do whatever you want with this stuff. + * If we meet some day, and you think this stuff is worth it, you can buy me a beer in return. Luka Pusic + */ + +import type { Faker } from '..'; + +export type Arch = 'lin' | 'mac' | 'win'; + +export function generate(faker: Faker) { + function rnd( + a?: string[] | number | Record<string, number>, + b?: number + ): string | number { + //calling rnd() with no arguments is identical to rnd(0, 100) + a = a || 0; + b = b || 100; + + if (typeof b === 'number' && typeof a === 'number') { + // 9/2018 - Added faker random to ensure mersenne and seed + return faker.datatype.number({ min: a, max: b }); + } + + if (Array.isArray(a)) { + //returns a random element from array (a), even weighting + return faker.random.arrayElement(a); + } + + if (a && typeof a === 'object') { + //returns a random key from the passed object; keys are weighted by the decimal probability in their value + return ((obj) => { + const rand = (rnd(0, 100) as number) / 100; + let min = 0; + let max = 0; + let return_val: string; + + for (let key in obj) { + if (obj.hasOwnProperty(key)) { + max = obj[key] + min; + return_val = key; + if (rand >= min && rand <= max) { + break; + } + min = min + obj[key]; + } + } + + return return_val; + })(a); + } + + throw new TypeError( + 'Invalid arguments passed to rnd. (' + (b ? a + ', ' + b : a) + ')' + ); + } + + function randomLang(): string | number { + return rnd([ + 'AB', + 'AF', + 'AN', + 'AR', + 'AS', + 'AZ', + 'BE', + 'BG', + 'BN', + 'BO', + 'BR', + 'BS', + 'CA', + 'CE', + 'CO', + 'CS', + 'CU', + 'CY', + 'DA', + 'DE', + 'EL', + 'EN', + 'EO', + 'ES', + 'ET', + 'EU', + 'FA', + 'FI', + 'FJ', + 'FO', + 'FR', + 'FY', + 'GA', + 'GD', + 'GL', + 'GV', + 'HE', + 'HI', + 'HR', + 'HT', + 'HU', + 'HY', + 'ID', + 'IS', + 'IT', + 'JA', + 'JV', + 'KA', + 'KG', + 'KO', + 'KU', + 'KW', + 'KY', + 'LA', + 'LB', + 'LI', + 'LN', + 'LT', + 'LV', + 'MG', + 'MK', + 'MN', + 'MO', + 'MS', + 'MT', + 'MY', + 'NB', + 'NE', + 'NL', + 'NN', + 'NO', + 'OC', + 'PL', + 'PT', + 'RM', + 'RO', + 'RU', + 'SC', + 'SE', + 'SK', + 'SL', + 'SO', + 'SQ', + 'SR', + 'SV', + 'SW', + 'TK', + 'TR', + 'TY', + 'UK', + 'UR', + 'UZ', + 'VI', + 'VO', + 'YI', + 'ZH', + ]); + } + + function randomBrowserAndOS(): Array<string | number> { + const browser = rnd({ + chrome: 0.45132810566, + iexplorer: 0.27477061836, + firefox: 0.19384170608, + safari: 0.06186781118, + opera: 0.01574236955, + }); + const os = { + chrome: { win: 0.89, mac: 0.09, lin: 0.02 }, + firefox: { win: 0.83, mac: 0.16, lin: 0.01 }, + opera: { win: 0.91, mac: 0.03, lin: 0.06 }, + safari: { win: 0.04, mac: 0.96 }, + iexplorer: ['win'], + }; + + return [browser, rnd(os[browser])]; + } + + function randomProc(arch: Arch): string | number { + const procs = { + lin: ['i686', 'x86_64'], + mac: { Intel: 0.48, PPC: 0.01, 'U; Intel': 0.48, 'U; PPC': 0.01 }, + win: ['', 'WOW64', 'Win64; x64'], + }; + return rnd(procs[arch]); + } + + function randomRevision(dots: number): string { + let return_val = ''; + //generate a random revision + //dots = 2 returns .x.y where x & y are between 0 and 9 + for (let x = 0; x < dots; x++) { + return_val += '.' + rnd(0, 9); + } + return return_val; + } + + const version_string = { + net() { + return [rnd(1, 4), rnd(0, 9), rnd(10000, 99999), rnd(0, 9)].join('.'); + }, + nt() { + return rnd(5, 6) + '.' + rnd(0, 3); + }, + ie() { + return rnd(7, 11); + }, + trident() { + return rnd(3, 7) + '.' + rnd(0, 1); + }, + osx(delim?: string) { + return [10, rnd(5, 10), rnd(0, 9)].join(delim || '.'); + }, + chrome() { + return [rnd(13, 39), 0, rnd(800, 899), 0].join('.'); + }, + presto() { + return '2.9.' + rnd(160, 190); + }, + presto2() { + return rnd(10, 12) + '.00'; + }, + safari() { + return rnd(531, 538) + '.' + rnd(0, 2) + '.' + rnd(0, 2); + }, + }; + + const browser = { + firefox(arch: Arch): string { + //https://developer.mozilla.org/en-US/docs/Gecko_user_agent_string_reference + const firefox_ver = rnd(5, 15) + randomRevision(2), + gecko_ver = 'Gecko/20100101 Firefox/' + firefox_ver, + proc = randomProc(arch), + os_ver = + arch === 'win' + ? '(Windows NT ' + version_string.nt() + (proc ? '; ' + proc : '') + : arch === 'mac' + ? '(Macintosh; ' + proc + ' Mac OS X ' + version_string.osx() + : '(X11; Linux ' + proc; + + return ( + 'Mozilla/5.0 ' + + os_ver + + '; rv:' + + firefox_ver.slice(0, -2) + + ') ' + + gecko_ver + ); + }, + + iexplorer(): string { + const ver = version_string.ie(); + + if (ver >= 11) { + //http://msdn.microsoft.com/en-us/library/ie/hh869301(v=vs.85).aspx + return ( + 'Mozilla/5.0 (Windows NT 6.' + + rnd(1, 3) + + '; Trident/7.0; ' + + rnd(['Touch; ', '']) + + 'rv:11.0) like Gecko' + ); + } + + //http://msdn.microsoft.com/en-us/library/ie/ms537503(v=vs.85).aspx + return ( + 'Mozilla/5.0 (compatible; MSIE ' + + ver + + '.0; Windows NT ' + + version_string.nt() + + '; Trident/' + + version_string.trident() + + (rnd(0, 1) === 1 ? '; .NET CLR ' + version_string.net() : '') + + ')' + ); + }, + + opera(arch: Arch): string { + //http://www.opera.com/docs/history/ + const presto_ver = + ' Presto/' + + version_string.presto() + + ' Version/' + + version_string.presto2() + + ')', + os_ver = + arch === 'win' + ? '(Windows NT ' + + version_string.nt() + + '; U; ' + + randomLang() + + presto_ver + : arch === 'lin' + ? '(X11; Linux ' + + randomProc(arch) + + '; U; ' + + randomLang() + + presto_ver + : '(Macintosh; Intel Mac OS X ' + + version_string.osx() + + ' U; ' + + randomLang() + + ' Presto/' + + version_string.presto() + + ' Version/' + + version_string.presto2() + + ')'; + + return 'Opera/' + rnd(9, 14) + '.' + rnd(0, 99) + ' ' + os_ver; + }, + + safari(arch: Arch): string { + const safari = version_string.safari(), + ver = rnd(4, 7) + '.' + rnd(0, 1) + '.' + rnd(0, 10), + os_ver = + arch === 'mac' + ? '(Macintosh; ' + + randomProc('mac') + + ' Mac OS X ' + + version_string.osx('_') + + ' rv:' + + rnd(2, 6) + + '.0; ' + + randomLang() + + ') ' + : '(Windows; U; Windows NT ' + version_string.nt() + ')'; + + return ( + 'Mozilla/5.0 ' + + os_ver + + 'AppleWebKit/' + + safari + + ' (KHTML, like Gecko) Version/' + + ver + + ' Safari/' + + safari + ); + }, + + chrome(arch: Arch): string { + const safari = version_string.safari(), + os_ver = + arch === 'mac' + ? '(Macintosh; ' + + randomProc('mac') + + ' Mac OS X ' + + version_string.osx('_') + + ') ' + : arch === 'win' + ? '(Windows; U; Windows NT ' + version_string.nt() + ')' + : '(X11; Linux ' + randomProc(arch); + + return ( + 'Mozilla/5.0 ' + + os_ver + + ' AppleWebKit/' + + safari + + ' (KHTML, like Gecko) Chrome/' + + version_string.chrome() + + ' Safari/' + + safari + ); + }, + }; + + const random = randomBrowserAndOS(); + return browser[random[0]](random[1]); +} |
