Completed
Push — add/module-registration-refact... ( af2fe6...74b9d5 )
by
unknown
295:53 queued 288:51
created

Jetpack_Password_Checker::run_tests()   B

Complexity

Conditions 7
Paths 6

Size

Total Lines 36

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
nc 6
nop 2
dl 0
loc 36
rs 8.4106
c 0
b 0
f 0
1
<?php //phpcs:ignore WordPress.Files.FileName.InvalidClassFileName
2
/**
3
 * The password strength checker.
4
 *
5
 * @package jetpack
6
 */
7
8
/**
9
 * Checks passwords strength.
10
 */
11
class Jetpack_Password_Checker {
12
13
	/**
14
	 * Minimum entropy bits a password should contain. 36 bits of entropy is considered
15
	 * to be a reasonable password, 28 stands for a weak one.
16
	 *
17
	 * @const Integer
18
	 */
19
	const MINIMUM_BITS = 28;
20
21
	/**
22
	 * Currently tested password.
23
	 *
24
	 * @var String
25
	 */
26
	public $password = '';
27
28
	/**
29
	 * Test results array.
30
	 *
31
	 * @var Array
32
	 */
33
	public $test_results = '';
34
35
	/**
36
	 * Current password score.
37
	 *
38
	 * @var Integer
39
	 */
40
	public $score = 0;
41
42
	/**
43
	 * Current multiplier affecting the score.
44
	 *
45
	 * @var Integer
46
	 */
47
	public $multiplier = 4;
48
49
	/**
50
	 * A common password blacklist, which on match will immediately disqualify the password.
51
	 *
52
	 * @var Array
53
	 */
54
	public $common_passwords = array();
55
56
	/**
57
	 * Minimum password length setting.
58
	 *
59
	 * @var Integer
60
	 */
61
	public $min_password_length = 6;
62
63
	/**
64
	 * User defined strings that passwords need to be tested for a match against.
65
	 *
66
	 * @var Array
67
	 */
68
	private $user_strings_to_test = array();
69
70
	/**
71
	 * The user object for whom the password is being tested.
72
	 *
73
	 * @var WP_User
74
	 */
75
	protected $user;
76
77
	/**
78
	 * The user identifier for whom the password is being tested, used if there's no user object.
79
	 *
80
	 * @var WP_User
81
	 */
82
	protected $user_id;
83
84
	/**
85
	 * Creates an instance of the password checker class for the specified user, or
86
	 * defaults to the currently logged in user.
87
	 *
88
	 * @param Mixed $user can be an integer ID, or a WP_User object.
89
	 */
90
	public function __construct( $user = null ) {
91
92
		/**
93
		 * Filters Jetpack's password strength enforcement settings. You can supply your own passwords
94
		 * that should not be used for authenticating in addition to weak and easy to guess strings for
95
		 * each user. For example, you can add passwords from known password databases to avoid compromised
96
		 * password usage.
97
		 *
98
		 * @since 7.2.0
99
		 *
100
		 * @param Array $restricted_passwords strings that are forbidden for use as passwords.
101
		 */
102
		$this->common_passwords = apply_filters( 'jetpack_password_checker_restricted_strings', array() );
103
104
		if ( is_null( $user ) ) {
105
			$this->user_id = get_current_user_id();
106
		} elseif ( is_object( $user ) && isset( $user->ID ) ) {
107
108
			// Existing user, using their ID.
109
			$this->user_id = $user->ID;
110
111
		} elseif ( is_object( $user ) ) {
112
113
			// Newly created user, using existing data.
114
			$this->user    = $user;
115
			$this->user_id = 'new_user';
0 ignored issues
show
Documentation Bug introduced by
It seems like 'new_user' of type string is incompatible with the declared type object<WP_User> of property $user_id.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
116
117
		} else {
118
			$this->user_id = $user;
0 ignored issues
show
Documentation Bug introduced by
It seems like $user of type integer or double or string or array or boolean is incompatible with the declared type object<WP_User> of property $user_id.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
119
		}
120
		$this->min_password_length = apply_filters( 'better_password_min_length', $this->min_password_length );
121
	}
122
123
	/**
124
	 * Run tests against a password.
125
	 *
126
	 * @param String  $password      the tested string.
127
	 * @param Boolean $required_only only test against required conditions, defaults to false.
128
	 * @return Array $results an array containing failed and passed test results.
129
	 */
130
	public function test( $password, $required_only = false ) {
131
132
		$this->password = $password;
133
		$results        = $this->run_tests( $this->list_tests(), $required_only );
134
135
		// If we've failed on the required tests, return now.
136
		if ( ! empty( $results['failed'] ) ) {
137
			return array(
138
				'passed'       => false,
139
				'test_results' => $results,
140
			);
141
		}
142
143
		/**
144
		 * Filters Jetpack's password strength enforcement settings. You can modify the minimum
145
		 * entropy bits requirement using this filter.
146
		 *
147
		 * @since 7.2.0
148
		 *
149
		 * @param Array $minimum_entropy_bits minimum entropy bits requirement.
150
		 */
151
		$bits         = apply_filters( 'jetpack_password_checker_minimum_entropy_bits', self::MINIMUM_BITS );
152
		$entropy_bits = $this->calculate_entropy_bits( $this->password );
153
154
		// If we have failed the entropy bits test, run the regex tests so we can suggest improvements.
155
		if ( $entropy_bits < $bits ) {
156
			$results['failed']['entropy_bits'] = $entropy_bits;
157
			$results                           = array_merge(
158
				$results,
159
				$this->run_tests( $this->list_tests( 'preg_match' ), false )
0 ignored issues
show
Documentation introduced by
'preg_match' is of type string, but the function expects a false|array.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
160
			);
161
		}
162
163
		return( array(
164
			'passed'       => empty( $results['failed'] ),
165
			'test_results' => $results,
166
		) );
167
	}
168
169
	/**
170
	 * Run the tests using the currently set up object values.
171
	 *
172
	 * @param Array   $tests tests to run.
173
	 * @param Boolean $required_only whether to run only required tests.
174
	 * @return Array test results.
175
	 */
176
	protected function run_tests( $tests, $required_only = false ) {
177
178
		$results = array(
179
			'passed' => array(),
180
			'failed' => array(),
181
		);
182
183
		foreach ( $tests as $test_type => $section_tests ) {
184
			foreach ( $section_tests as $test_name => $test_data ) {
185
186
				// Skip non-required tests if required_only param is set.
187
				if ( $required_only && ! $test_data['required'] ) {
188
					continue;
189
				}
190
191
				$test_function = 'test_' . $test_type;
192
193
				$result = call_user_func( array( $this, $test_function ), $test_data );
194
195
				if ( $result ) {
196
					$results['passed'][] = array( 'test_name' => $test_name );
197
				} else {
198
					$results['failed'][] = array(
199
						'test_name'   => $test_name,
200
						'explanation' => $test_data['error'],
201
					);
202
203
					if ( isset( $test_data['fail_immediately'] ) ) {
204
						return $results;
205
					}
206
				}
207
			}
208
		}
209
210
		return $results;
211
	}
212
213
	/**
214
	 * Returns a list of tests that need to be run on password strings.
215
	 *
216
	 * @param Array $sections only return specific sections with the passed keys, defaults to all.
0 ignored issues
show
Documentation introduced by
Should the type for parameter $sections not be false|array?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
217
	 * @return Array test descriptions.
218
	 */
219
	protected function list_tests( $sections = false ) {
220
		// Note: these should be in order of priority.
221
		$tests = array(
222
			'preg_match'      => array(
223
				'no_backslashes'   => array(
224
					'pattern'          => '^[^\\\\]*$',
225
					'error'            => __( 'Passwords may not contain the character "\".', 'jetpack' ),
226
					'required'         => true,
227
					'fail_immediately' => true,
228
				),
229
				'minimum_length'   => array(
230
					'pattern'          => '^.{' . $this->min_password_length . ',}',
231
					/* translators: %d is a number of characters in the password. */
232
					'error'            => sprintf( __( 'Password must be at least %d characters.', 'jetpack' ), $this->min_password_length ),
233
					'required'         => true,
234
					'fail_immediately' => true,
235
				),
236
				'has_mixed_case'   => array(
237
					'pattern'  => '([a-z].*?[A-Z]|[A-Z].*?[a-z])',
238
					'error'    => __( 'This password is too easy to guess: you can improve it by adding additional uppercase letters, lowercase letters, or numbers.', 'jetpack' ),
239
					'trim'     => true,
240
					'required' => false,
241
				),
242
				'has_digit'        => array(
243
					'pattern'  => '\d',
244
					'error'    => __( 'This password is too easy to guess: you can improve it by mixing both letters and numbers.', 'jetpack' ),
245
					'trim'     => false,
246
					'required' => false,
247
				),
248
				'has_special_char' => array(
249
					'pattern'  => '[^a-zA-Z\d]',
250
					'error'    => __( 'This password is too easy to guess: you can improve it by including special characters such as !#=?*&.', 'jetpack' ),
251
					'required' => false,
252
				),
253
			),
254
			'compare_to_list' => array(
255
				'not_a_common_password'       => array(
256
					'list_callback'    => 'get_common_passwords',
257
					'compare_callback' => 'negative_in_array',
258
					'error'            => __( 'This is a very common password. Choose something that will be harder for others to guess.', 'jetpack' ),
259
					'required'         => true,
260
				),
261
				'not_same_as_other_user_data' => array(
262
					'list_callback'    => 'get_other_user_data',
263
					'compare_callback' => 'test_not_same_as_other_user_data',
264
					'error'            => __( 'Your password is too weak: Looks like you\'re including easy to guess information about yourself. Try something a little more unique.', 'jetpack' ),
265
					'required'         => true,
266
				),
267
			),
268
		);
269
270
		/**
271
		 * Filters Jetpack's password strength enforcement settings. You can determine the tests run
272
		 * and their order based on whatever criteria you wish to specify.
273
		 *
274
		 * @since 7.2.0
275
		 *
276
		 * @param Array $minimum_entropy_bits minimum entropy bits requirement.
277
		 */
278
		$tests = apply_filters( 'jetpack_password_checker_tests', $tests );
279
280
		if ( ! $sections ) {
281
			return $tests;
282
		}
283
284
		$sections = (array) $sections;
285
		return array_intersect_key( $tests, array_flip( $sections ) );
286
	}
287
288
	/**
289
	 * Provides the regular expression tester functionality.
290
	 *
291
	 * @param Array $test_data the current test data.
292
	 * @return Boolean does the test pass?
293
	 */
294
	protected function test_preg_match( $test_data ) {
295
		$password = stripslashes( $this->password );
296
297
		if ( isset( $test_data['trim'] ) ) {
298
			$password = substr( $password, 1, -1 );
299
		}
300
301
		if ( ! preg_match( '/' . $test_data['pattern'] . '/u', $password ) ) {
302
			return false;
303
		}
304
305
		return true;
306
	}
307
308
	/**
309
	 * Provides the comparison tester functionality.
310
	 *
311
	 * @param Array $test_data the current test data.
312
	 * @return Boolean does the test pass?
313
	 */
314
	protected function test_compare_to_list( $test_data ) {
315
		$list_callback    = $test_data['list_callback'];
316
		$compare_callback = $test_data['compare_callback'];
317
318
		if (
319
			! is_callable( array( $this, $list_callback ) )
320
			|| ! is_callable( array( $this, $compare_callback ) )
321
		) {
322
			return false;
323
		}
324
325
		$list = call_user_func( array( $this, $list_callback ) );
326
		if ( empty( $list ) ) {
327
			return true;
328
		}
329
330
		return call_user_func( array( $this, $compare_callback ), $this->password, $list );
331
	}
332
333
	/**
334
	 * Getter for the common password list.
335
	 *
336
	 * @return Array common passwords.
337
	 */
338
	protected function get_common_passwords() {
339
		return $this->common_passwords;
340
	}
341
342
	/**
343
	 * Returns the widely known user data that can not be used in the password to avoid
344
	 * predictable strings.
345
	 *
346
	 * @return Array user data.
347
	 */
348
	protected function get_other_user_data() {
349
350
		if ( ! isset( $this->user ) ) {
351
			$user_data = get_userdata( $this->user_id );
352
353
			$first_name = get_user_meta( $user_data->ID, 'first_name', true );
354
			$last_name  = get_user_meta( $user_data->ID, 'last_name', true );
355
			$nickname   = get_user_meta( $user_data->ID, 'nickname', true );
356
357
			$this->add_user_strings_to_test( $nickname );
358
			$this->add_user_strings_to_test( $user_data->user_nicename );
359
			$this->add_user_strings_to_test( $user_data->display_name );
360
		} else {
361
			$user_data = $this->user;
362
363
			$first_name = $user_data->first_name;
364
			$last_name  = $user_data->last_name;
365
		}
366
		$email_username = substr( $user_data->user_email, 0, strpos( $user_data->user_email, '@' ) );
367
368
		$this->add_user_strings_to_test( $user_data->user_email );
369
		$this->add_user_strings_to_test( $email_username, '.' );
370
		$this->add_user_strings_to_test( $first_name );
371
		$this->add_user_strings_to_test( $last_name );
372
373
		return $this->user_strings_to_test;
374
	}
375
376
	/**
377
	 * Compare the password for matches with known user data.
378
	 *
379
	 * @param String $password the string to be tested.
380
	 * @param Array  $strings_to_test known user data.
381
	 * @return Boolean does the test pass?
382
	 */
383
	protected function test_not_same_as_other_user_data( $password, $strings_to_test ) {
384
		$password_lowercase = strtolower( $password );
385
		foreach ( array_unique( $strings_to_test ) as $string ) {
386
			if ( empty( $string ) ) {
387
				continue;
388
			}
389
390
			$string          = strtolower( $string );
391
			$string_reversed = strrev( $string );
392
393
			if ( $password_lowercase === $string || $password_lowercase === $string_reversed ) {
394
				return false;
395
			}
396
397
			// Also check for the string or reversed string with any numbers just stuck to the end to catch things like bob123 as passwords.
398
			if (
399
				preg_match( '/^' . preg_quote( $string, '/' ) . '\d+$/', $password_lowercase )
400
				|| preg_match( '/^' . preg_quote( $string_reversed, '/' ) . '\d+$/', $password_lowercase )
401
			) {
402
				return false;
403
			}
404
		}
405
		return true;
406
	}
407
408
	/**
409
	 * A shorthand for the not in array construct.
410
	 *
411
	 * @param Mixed $needle the needle.
412
	 * @param Array $haystack the haystack.
413
	 * @return is the needle not in the haystack?
414
	 */
415
	protected function negative_in_array( $needle, $haystack ) {
416
		if ( in_array( $needle, $haystack, true ) ) {
417
			return false;
418
		}
419
420
		return true;
421
	}
422
423
	/**
424
	 * A helper function used to break a single string into its constituents so
425
	 * that both the full string and its constituents and any variants thereof
426
	 * can be tested against the password.
427
	 *
428
	 * @param String $string the string to be broken down.
429
	 * @param String $explode_delimiter delimiter.
430
	 * @return NULL|Array array of fragments, or NULL on empty string.
431
	 */
432
	protected function add_user_strings_to_test( $string, $explode_delimiter = ' ' ) {
433
434
		// Don't check against empty strings.
435
		if ( empty( $string ) ) {
436
			return;
437
		}
438
439
		$strings = explode( $explode_delimiter, $string );
440
441
		// Remove any non alpha numeric characters from the strings to check against.
442
		foreach ( $strings as $key => $_string ) {
443
			$strings[ $key ] = preg_replace( '/[^a-zA-Z0-9]/', '', $_string );
444
		}
445
446
		// Check the original too.
447
		$strings[] = $string;
448
449
		// Check the original minus non alpha numeric characters.
450
		$strings[] = preg_replace( '/[^a-zA-Z0-9]/', '', $string );
451
452
		// Remove any empty strings.
453
		$strings                    = array_filter( $strings );
454
		$this->user_strings_to_test = array_merge( $this->user_strings_to_test, $strings );
455
	}
456
457
	/**
458
	 * Return a character set size that is used in the string.
459
	 *
460
	 * @param String $password the password.
461
	 * @return Integer number of different character sets in use.
462
	 */
463
	protected function get_charset_size( $password ) {
464
		$size = 0;
465
466
		// Lowercase a-z.
467
		if ( preg_match( '/[a-z]/', $password ) ) {
468
			$size += 26;
469
		}
470
471
		// Uppercase A-Z.
472
		if ( preg_match( '/[A-Z]/', substr( $password, 1, -1 ) ) ) {
473
			$size += 26;
474
		}
475
476
		// Digits.
477
		if ( preg_match( '/\d/', substr( $password, 1, -1 ) ) ) {
478
			$size += 10;
479
		}
480
481
		// Over digits symbols.
482
		if ( preg_match( '/[!|@|#|$|%|^|&|*|(|)]/', $password ) ) {
483
			$size += 10;
484
		}
485
486
		// Other symbols.
487
		if ( preg_match( '#[`|~|-|_|=|+|\[|{|\]|}|\\|\|;:\'",<\.>/\?]#', $password ) ) {
488
			$size += 20;
489
		}
490
491
		// Spaces.
492
		if ( strpos( $password, ' ' ) ) {
493
			$size++;
494
		}
495
496
		return $size;
497
	}
498
499
	/**
500
	 * Shorthand for getting a character index.
501
	 *
502
	 * @param String $char character.
503
	 * @return Integer the character code.
504
	 */
505
	protected function get_char_index( $char ) {
506
		$char = strtolower( $char[0] );
507
		if ( $char < 'a' || $char > 'z' ) {
508
			return 0;
509
		} else {
510
			return ord( $char[0] ) - ord( 'a' ) + 1;
511
		}
512
	}
513
514
	/**
515
	 * This is the password strength calculation algorithm, based on the formula H = L(logN/log2).
516
	 *
517
	 * H = Entropy
518
	 * L = String length (the for iterator)
519
	 * N = Our charset size, via get_charset_size()
520
	 *
521
	 * @see http://en.wikipedia.org/wiki/Password_strength#Random_passwords
522
	 *
523
	 * On top of the base formula, we're also multiplying the bits of entropy for every char
524
	 * by 1 - (the probabily of it following the previous char)
525
	 * i.e.: the probablity of U following Q is ~0.84. If our password contains this pair of characters,
526
	 * the u char will only add ( 0.16^2 * charset_score ) to our total of entropy bits.
527
	 *
528
	 * @param String $password the password.
529
	 */
530
	protected function calculate_entropy_bits( $password ) {
531
		$bits          = 0;
532
		$charset_score = log( $this->get_charset_size( $password ) ) / log( 2 );
533
534
		$aidx   = $this->get_char_index( $password[0] );
535
		$length = strlen( $password );
536
537
		for ( $b = 1; $b < $length; $b++ ) {
538
			$bidx = $this->get_char_index( $password[ $b ] );
539
540
			// 27 = number of chars in the index (a-z,' ').
541
			$c     = 1.0 - $this->frequency_table[ $aidx * 27 + $bidx ];
542
			$bits += $charset_score * $c * $c;
543
544
			// Move on to next pair.
545
			$aidx = $bidx;
546
		}
547
548
		return $bits;
549
	}
550
551
	/**
552
	 * A frequency table of character pairs, starting with  '  ' then  ' a', ' b' [...] , 'a ', 'aa' etc.
553
	 *
554
	 * @see http://rumkin.com/tools/password/passchk.php
555
	 * @var Array
556
	 */
557
	public $frequency_table = array(
558
		0.23653710453418866,
559
		0.04577693541332556,
560
		0.03449832337075375,
561
		0.042918209651552706,
562
		0.037390873305146524,
563
		0.028509112115468728,
564
		0.02350896632162123,
565
		0.022188657238664526,
566
		0.028429800262428927,
567
		0.04357019973757107,
568
		0.00913602565971716,
569
		0.03223093745443942,
570
		0.02235311269864412,
571
		0.04438081352966905,
572
		0.04512377897652719,
573
		0.020055401662049863,
574
		0.055903192885260244,
575
		0.0024388394809739026,
576
		0.035207464644991984,
577
		0.07355941099285611,
578
		0.036905671380667734,
579
		0.026134421927394666,
580
		0.023787724158040528,
581
		0.011352092141711621,
582
		0.0032354570637119114,
583
		0.005986878553725033,
584
		0.008861933226417843,
585
		0.11511532293337222,
586
		0.027556203528211108,
587
		0.024331243621519172,
588
		0.039266365359381834,
589
		0.031599941682461,
590
		0.014403265782183991,
591
		0.015480973902901297,
592
		0.027770812071730572,
593
		0.00942761335471643,
594
		0.039872867764980315,
595
		0.0078122175244204695,
596
		0.02808456043154979,
597
		0.08429100451960927,
598
		0.04688963405744277,
599
		0.13831170724595424,
600
		0.002540311998833649,
601
		0.025211838460416972,
602
		0.001543082081936142,
603
		0.09519638431258201,
604
		0.061845750109345385,
605
		0.08907071001603732,
606
		0.02137571074500656,
607
		0.027093162268552268,
608
		0.005521504592506197,
609
		0.003023181221752442,
610
		0.007086747339262283,
611
		0.010262720513194342,
612
		0.08785070710016038,
613
		0.14617757690625455,
614
		0.03417291150313457,
615
		0.0059635515381250915,
616
		0.006146668610584633,
617
		0.195202799241872,
618
		0.002774748505613063,
619
		0.004715556203528212,
620
		0.0044776206444088066,
621
		0.11205481848665985,
622
		0.005654468581425864,
623
		0.0028820527773727946,
624
		0.07383000437381543,
625
		0.005516839189386207,
626
		0.006496573844583759,
627
		0.09843067502551392,
628
		0.0027140982650532145,
629
		0.0006893133109782768,
630
		0.08425368129464937,
631
		0.021325557661466685,
632
		0.006493074792243767,
633
		0.07023414491908442,
634
		0.002077270739174807,
635
		0.0024633328473538415,
636
		0.0007744569179180639,
637
		0.015413325557661468,
638
		0.0011990086018370024,
639
		0.13162851727657093,
640
		0.10115993585070711,
641
		0.0026989357049132527,
642
		0.03319317684793702,
643
		0.002946202070272634,
644
		0.0783216212275842,
645
		0.0018358361277154103,
646
		0.00258813238081353,
647
		0.2141688292754046,
648
		0.09853681294649366,
649
		0.0032482869222918796,
650
		0.04359352675317102,
651
		0.01993526753171016,
652
		0.0036880011663507797,
653
		0.008011663507799971,
654
		0.12014696019827964,
655
		0.0029846916460125384,
656
		0.0017553579238956116,
657
		0.029470185158186325,
658
		0.010413179763813967,
659
		0.030699518880303252,
660
		0.03508499781309229,
661
		0.002021285901734947,
662
		0.0010613792097973467,
663
		0.0005295232541186761,
664
		0.009677212421635807,
665
		0.010585799679253535,
666
		0.17101734946785244,
667
		0.07968625164018078,
668
		0.007839043592360402,
669
		0.005438693687126403,
670
		0.0183606939787141,
671
		0.2732701559994168,
672
		0.004953491762647616,
673
		0.007259367254701851,
674
		0.008104971570199739,
675
		0.13274588132380813,
676
		0.004210526315789474,
677
		0.004997813092287506,
678
		0.017006560723137484,
679
		0.007442484327161393,
680
		0.016789619478058026,
681
		0.08477737279486806,
682
		0.005106283714827234,
683
		0.0005026971861787433,
684
		0.04040355736987899,
685
		0.037535500801866156,
686
		0.00885960052485785,
687
		0.0336410555474559,
688
		0.007066919376002332,
689
		0.005344219273946639,
690
		0.0006333284735384167,
691
		0.010684939495553289,
692
		0.0063064586674442345,
693
		0.15386849394955532,
694
		0.015049424114302375,
695
		0.012162705933809595,
696
		0.020425134859308938,
697
		0.037366379938766583,
698
		0.02157165767604607,
699
		0.009373961218836564,
700
		0.0173214754337367,
701
		0.009616562181075958,
702
		0.029522670943286193,
703
		0.010154249890654615,
704
		0.018600962239393497,
705
		0.06362210234728094,
706
		0.03157078291296107,
707
		0.151603440734801,
708
		0.0062329785683044175,
709
		0.014775331681003062,
710
		0.0020854351946347867,
711
		0.1826342032366234,
712
		0.0878017203674005,
713
		0.054190989940224525,
714
		0.010329202507654177,
715
		0.012763376585508092,
716
		0.0064872430383437815,
717
		0.006381105117364048,
718
		0.005388540603586529,
719
		0.0090800408222773,
720
		0.09611196967487973,
721
		0.09940691062837148,
722
		0.01033969966467415,
723
		0.004034407348009914,
724
		0.008826942703017933,
725
		0.11474675608689314,
726
		0.07132584924916169,
727
		0.012388977985129028,
728
		0.005435194634786413,
729
		0.1417174515235457,
730
		0.0037066627788307337,
731
		0.0045802595130485495,
732
		0.060800699810468,
733
		0.005341886572386646,
734
		0.005683627350925791,
735
		0.12434932205860913,
736
		0.004596588423968508,
737
		0.0007534626038781163,
738
		0.07107041842834232,
739
		0.022361277154104096,
740
		0.04784720804782038,
741
		0.06277533168100306,
742
		0.003441901151771395,
743
		0.005828254847645429,
744
		0.0009669047966175828,
745
		0.009470768333576322,
746
		0.002077270739174807,
747
		0.12797667298440007,
748
		0.08797783933518005,
749
		0.005388540603586529,
750
		0.0024913252660737715,
751
		0.007550954949701123,
752
		0.2786866890217233,
753
		0.002509986878553725,
754
		0.029002478495407494,
755
		0.0303204548768042,
756
		0.07576614666861058,
757
		0.00246799825047383,
758
		0.00592389561160519,
759
		0.039574281965301064,
760
		0.00706808572678233,
761
		0.03304505029887739,
762
		0.05474150750838315,
763
		0.0028633911648928414,
764
		0.0005073625892987316,
765
		0.07293541332555767,
766
		0.053528502697186175,
767
		0.022566554891383584,
768
		0.038151334013704616,
769
		0.002716430966613209,
770
		0.005049132526607377,
771
		0.0009902318122175246,
772
		0.008997229916897508,
773
		0.0011861787432570347,
774
		0.1666377022889634,
775
		0.14414462749671964,
776
		0.003374252806531564,
777
		0.005169266656947077,
778
		0.008468873013558828,
779
		0.16337541915731155,
780
		0.002873888321912815,
781
		0.004305000728969237,
782
		0.0031141565825922144,
783
		0.1241172182533897,
784
		0.0052800699810468,
785
		0.008969237498177577,
786
		0.024094474413179766,
787
		0.017029887738737422,
788
		0.01722700102055693,
789
		0.10618457501093455,
790
		0.006147834961364631,
791
		0.0008269427030179326,
792
		0.03303571949263741,
793
		0.024188948826359528,
794
		0.05213937891820965,
795
		0.04505846333284735,
796
		0.0035270447587111824,
797
		0.006799825047383001,
798
		0.0008199445983379502,
799
		0.02206735675754483,
800
		0.001010059775477475,
801
		0.11971191135734072,
802
		0.04656538854060359,
803
		0.011243621519171892,
804
		0.06513019390581717,
805
		0.032375564951159064,
806
		0.06347047674588133,
807
		0.013678961947805804,
808
		0.03309870243475726,
809
		0.006982942119842543,
810
		0.009726199154395685,
811
		0.010121592068814697,
812
		0.032514360693978714,
813
		0.04986032949409535,
814
		0.039734072022160664,
815
		0.15690683773144773,
816
		0.03949963551538125,
817
		0.014790494241143023,
818
		0.002722262720513194,
819
		0.02614375273363464,
820
		0.10753637556495116,
821
		0.06764834523983088,
822
		0.006221315060504448,
823
		0.021317393206006705,
824
		0.0030826651115322934,
825
		0.002399183554454002,
826
		0.0019069835252952323,
827
		0.015595276279341012,
828
		0.0925126111678087,
829
		0.18437906400349907,
830
		0.006538562472663654,
831
		0.008719638431258201,
832
		0.02116693395538708,
833
		0.18241376293920394,
834
		0.007290858725761773,
835
		0.005976381396705059,
836
		0.005629975215045925,
837
		0.09721300481119698,
838
		0.004810030616707975,
839
		0.024303251202799244,
840
		0.012954658113427612,
841
		0.011057005394372358,
842
		0.02733459688001166,
843
		0.10135121737862662,
844
		0.012016912086309959,
845
		0.001055547455897361,
846
		0.009027555037177431,
847
		0.07162326869806095,
848
		0.01007143898527482,
849
		0.07297623560285756,
850
		0.006741507508383147,
851
		0.0036891675171307776,
852
		0.0008409389123778977,
853
		0.011272780288671819,
854
		0.007020265344802449,
855
		0.1030389269572824,
856
		0.15350809155853623,
857
		0.004232686980609419,
858
		0.004353987461729115,
859
		0.0023385333138941536,
860
		0.14450386353695874,
861
		0.002546143752733635,
862
		0.0024470039364338824,
863
		0.01200758128006998,
864
		0.0981227584195947,
865
		0.003161976964572095,
866
		0.040695145064878264,
867
		0.03460446129173349,
868
		0.003908441463770229,
869
		0.01598483743986004,
870
		0.13107216795451232,
871
		0.003129319142732177,
872
		0.00032307916605919226,
873
		0.04050386353695874,
874
		0.05452689896486368,
875
		0.03589677795597026,
876
		0.07087097244496282,
877
		0.006143169558244642,
878
		0.008684647907858289,
879
		0.0004607085580988482,
880
		0.022010205569324977,
881
		0.0009097536083977258,
882
		0.07328765126111678,
883
		0.14751421490013122,
884
		0.008015162560139961,
885
		0.006601545414783497,
886
		0.025279486805656802,
887
		0.1682449336637994,
888
		0.008313748359819215,
889
		0.007010934538562473,
890
		0.005886572386645284,
891
		0.16889575739903775,
892
		0.004123050007289692,
893
		0.011925936725470185,
894
		0.10007289692374982,
895
		0.013380376148126549,
896
		0.009021723283277445,
897
		0.08650823735238372,
898
		0.007756232686980609,
899
		0.0007243038343781893,
900
		0.0026791077416533026,
901
		0.02797492345823006,
902
		0.032384895757399036,
903
		0.04187432570345531,
904
		0.00882461000145794,
905
		0.0032401224668318998,
906
		0.00033357632307916605,
907
		0.027878116343490307,
908
		0.0022277299897944304,
909
		0.14333518005540166,
910
		0.1725534334451086,
911
		0.02781629975215046,
912
		0.006909462020702727,
913
		0.005264907420906838,
914
		0.16661437527336345,
915
		0.004325995043009185,
916
		0.003334596880011664,
917
		0.005312727802886718,
918
		0.14024668318996938,
919
		0.0013261408368566844,
920
		0.003504884093891238,
921
		0.006375273363464061,
922
		0.04964922000291588,
923
		0.008290421344219274,
924
		0.09536783787724158,
925
		0.05394372357486515,
926
		0.005505175681586237,
927
		0.005339553870826651,
928
		0.01782067356757545,
929
		0.006710016037323225,
930
		0.05105933809593235,
931
		0.002983525295232541,
932
		0.002940370316372649,
933
		0.0004548768041988629,
934
		0.01208456043154979,
935
		0.000915585362297711,
936
		0.20146260387811635,
937
		0.067196967487972,
938
		0.006158332118384605,
939
		0.025438110511736407,
940
		0.07753783350342616,
941
		0.1273876658405015,
942
		0.009337804344656656,
943
		0.07683452398308792,
944
		0.0070412596588423975,
945
		0.08747164309666132,
946
		0.0038827817466102928,
947
		0.018116926665694706,
948
		0.005017641055547455,
949
		0.004567429654468581,
950
		0.028277008310249308,
951
		0.05271555620352821,
952
		0.004394809739029013,
953
		0.0013343052923166642,
954
		0.00411605190260971,
955
		0.059621519171890944,
956
		0.09073859163143316,
957
		0.01446858142586383,
958
		0.006770666277883074,
959
		0.003425572240851436,
960
		0.0004455459979588861,
961
		0.010401516256013998,
962
		0.005825922146085436,
963
		0.10833882490158916,
964
		0.007584779122321038,
965
		0.016903921854497742,
966
		0.02719580113719201,
967
		0.0304814112844438,
968
		0.02206385770520484,
969
		0.013064295086747339,
970
		0.02696369733197259,
971
		0.009581571657676046,
972
		0.026761918647033093,
973
		0.006510570053943724,
974
		0.021941390873305145,
975
		0.07042659279778393,
976
		0.05437410701268406,
977
		0.1425175681586237,
978
		0.027802303542790494,
979
		0.037690625455605774,
980
		0.0019606356611750987,
981
		0.1095623268698061,
982
		0.06157748942994606,
983
		0.044618749088788455,
984
		0.04955124653739612,
985
		0.03608689313310978,
986
		0.018381688292754043,
987
		0.003404577926811489,
988
		0.015036594255722409,
989
		0.009600233270156,
990
		0.10794693103951014,
991
		0.12447528794284882,
992
		0.0031981338387520046,
993
		0.0074716430966613205,
994
		0.003202799241871993,
995
		0.13437643971424407,
996
		0.006655197550663361,
997
		0.0036693395538708266,
998
		0.049338970695436656,
999
		0.09486863974340283,
1000
		0.0015990669193760023,
1001
		0.0026604461291733486,
1002
		0.051775477474850555,
1003
		0.0041347135150896636,
1004
		0.005450357194926374,
1005
		0.12030325120279925,
1006
		0.04581309228750547,
1007
		0.0004537104534188657,
1008
		0.12425601399620935,
1009
		0.025981629975215047,
1010
		0.023926519900860182,
1011
		0.04423385333138941,
1012
		0.0017950138504155123,
1013
		0.002661612479953346,
1014
		0.0006333284735384167,
1015
		0.008449045050298877,
1016
		0.000653156436798367,
1017
		0.04816678816153958,
1018
		0.008625164018078437,
1019
		0.0039037760606502403,
1020
		0.005228750546726928,
1021
		0.004531272780288672,
1022
		0.0056672984400058316,
1023
		0.00359585945473101,
1024
		0.0032179618020119548,
1025
		0.0038093016474704767,
1026
		0.011452398308791368,
1027
		0.002519317684793702,
1028
		0.00280390727511299,
1029
		0.005572824026826068,
1030
		0.004554599795888614,
1031
		0.004531272780288672,
1032
		0.0035841959469310393,
1033
		0.004400641492928998,
1034
		0.0036670068523108326,
1035
		0.004839189386207902,
1036
		0.006258638285464354,
1037
		0.004897506925207757,
1038
		0.840776789619478,
1039
		0.004968654322787578,
1040
		0.002886718180492783,
1041
		0.0019757982213150604,
1042
		0.0018568304417553576,
1043
		0.001691208630995772,
1044
		0.09009243329931477,
1045
		0.14030150167662925,
1046
		0.013242746756086894,
1047
		0.013746610293045632,
1048
		0.027342761335471644,
1049
		0.16938912377897652,
1050
		0.006607377168683481,
1051
		0.01661933226417845,
1052
		0.008173786266219566,
1053
		0.13297448607668758,
1054
		0.0034675608689313307,
1055
		0.016641492928998396,
1056
		0.011722991689750693,
1057
		0.021493512173786266,
1058
		0.03430820819361423,
1059
		0.10099548039072752,
1060
		0.00873596734217816,
1061
		0.0018323370753754193,
1062
		0.020103222044029742,
1063
		0.047197550663362,
1064
		0.040833940807697915,
1065
		0.03361189677795597,
1066
		0.010844729552412887,
1067
		0.005544831608106138,
1068
		0.0007522962530981193,
1069
		0.01525120279924187,
1070
		0.00815512465373961,
1071
		0.2109648636827526,
1072
		0.058258055110074355,
1073
		0.007181221752442048,
1074
		0.043560868931331105,
1075
		0.004058900714389853,
1076
		0.10618107595859454,
1077
		0.0062399766729844,
1078
		0.004835690333867911,
1079
		0.02679224376731302,
1080
		0.08414637702288964,
1081
		0.0030698352529523252,
1082
		0.03637498177576906,
1083
		0.01592885260242018,
1084
		0.017413617145356466,
1085
		0.008430383437818923,
1086
		0.037231083248286924,
1087
		0.03290275550371775,
1088
		0.007538125091121154,
1089
		0.004500947660008748,
1090
		0.05932409972299169,
1091
		0.16006764834523984,
1092
		0.03309636973319726,
1093
		0.007766729844000583,
1094
		0.005225251494386936,
1095
		0.0006321621227584196,
1096
		0.012989648636827526,
1097
		0.005274238227146815,
1098
		0.1254503571949264,
1099
		0.12852719055255868,
1100
		0.0035433736696311416,
1101
		0.005203090829566993,
1102
		0.0019314768916751715,
1103
		0.20520775623268697,
1104
		0.002509986878553725,
1105
		0.00343606939787141,
1106
		0.027138649948972155,
1107
		0.13926578218399185,
1108
		0.004565096952908587,
1109
		0.005614812654905963,
1110
		0.00874413179763814,
1111
		0.004109053797929727,
1112
		0.008300918501239247,
1113
		0.08270943286193323,
1114
		0.002912377897652719,
1115
		0.0037066627788307337,
1116
		0.06909578655780726,
1117
		0.03242805073625893,
1118
		0.05237614812654906,
1119
		0.04723487388832191,
1120
		0.0038991106575302524,
1121
		0.006299460562764251,
1122
		0.00043388249015891526,
1123
		0.020029741944889927,
1124
		0.005311561452106721,
1125
		0.09334072022160665,
1126
		0.022940953491762648,
1127
		0.024658988190698353,
1128
		0.02901297565242747,
1129
		0.03531593526753171,
1130
		0.0758023035427905,
1131
		0.013711619769645722,
1132
		0.021597317393206007,
1133
		0.009670214316955824,
1134
		0.044728386062108175,
1135
		0.010596296836273509,
1136
		0.03264382563055839,
1137
		0.0604822860475288,
1138
		0.05489546581134276,
1139
		0.11501851581863246,
1140
		0.01837585653885406,
1141
		0.026237060796034405,
1142
		0.0011255285026971862,
1143
		0.08704125965884241,
1144
		0.10156349322058608,
1145
		0.06660562764251349,
1146
		0.023434319871701415,
1147
		0.010777081207173057,
1148
		0.005409534917626476,
1149
		0.003123487388832191,
1150
		0.0028762210234728096,
1151
		0.0089995626184575,
1152
		0.07518297127861205,
1153
		0.2314868056568013,
1154
		0.002226563639014434,
1155
		0.003285610147251786,
1156
		0.0027455897361131363,
1157
		0.2724537104534189,
1158
		0.0016655489138358362,
1159
		0.0019209797346551977,
1160
		0.0022137337804344656,
1161
		0.17690392185449774,
1162
		0.0014532730718763668,
1163
		0.0024994897215337513,
1164
		0.015302522233561744,
1165
		0.003441901151771395,
1166
		0.015303688584341741,
1167
		0.09314593964134713,
1168
		0.0017833503426155418,
1169
		0.0005108616416387229,
1170
		0.017828838023035427,
1171
		0.010385187345094037,
1172
		0.003168975069252078,
1173
		0.01902901297565243,
1174
		0.005525003644846187,
1175
		0.0010088934246974776,
1176
		0.0009272488700976819,
1177
		0.036282840064149294,
1178
		0.0022977110365942554,
1179
		0.0766805656801283,
1180
		0.22270418428342326,
1181
		0.005283569033386791,
1182
		0.007155562035282111,
1183
		0.01173582154833066,
1184
		0.1715620352821111,
1185
		0.003925936725470185,
1186
		0.004425134859308937,
1187
		0.020040239101909902,
1188
		0.14243242455168392,
1189
		0.0016737133692958156,
1190
		0.0066808572678232975,
1191
		0.011980755212130047,
1192
		0.012638577052048404,
1193
		0.07206065024055984,
1194
		0.08115701997375711,
1195
		0.00710424260096224,
1196
		0.0007278028867181805,
1197
		0.02347630849978131,
1198
		0.04595538708266512,
1199
		0.01481965301064295,
1200
		0.013925061962385188,
1201
		0.0018125091121154687,
1202
		0.00529173348884677,
1203
		0.0016340574427759146,
1204
		0.03072401224668319,
1205
		0.0023746901880740633,
1206
		0.25174165330223064,
1207
		0.06673392622831317,
1208
		0.00878378772415804,
1209
		0.03956261845750109,
1210
		0.010077270739174807,
1211
		0.0844787869951888,
1212
		0.00985216503863537,
1213
		0.004973319725907567,
1214
		0.01893220586091267,
1215
		0.11200583175389998,
1216
		0.0028715556203528212,
1217
		0.004095057588569762,
1218
		0.01202391019098994,
1219
		0.01756757544831608,
1220
		0.014825484764542934,
1221
		0.05312961073042717,
1222
		0.06746872721971132,
1223
		0.003845458521650386,
1224
		0.0210806239976673,
1225
		0.019443067502551394,
1226
		0.08017028721387957,
1227
		0.01825572240851436,
1228
		0.005365213587986587,
1229
		0.01959702580551101,
1230
		0.026184575010934536,
1231
		0.02474879720075813,
1232
		0.002171745152354571,
1233
		0.25827321767021433,
1234
		0.048050153083539875,
1235
		0.01043184137629392,
1236
		0.03930485493512174,
1237
		0.027640180784370902,
1238
		0.03294007872867765,
1239
		0.006474413179763814,
1240
		0.018314039947514214,
1241
		0.015119405161102202,
1242
		0.014706516984983233,
1243
		0.005494678524566263,
1244
		0.03309870243475726,
1245
		0.043864120134130345,
1246
		0.058996355153812505,
1247
		0.06265986295378335,
1248
		0.04633328473538417,
1249
		0.03790756670068523,
1250
		0.0004642076104388394,
1251
		0.037849249161685375,
1252
		0.08369966467415076,
1253
		0.04999679253535501,
1254
		0.02392768625164018,
1255
		0.010998687855372504,
1256
		0.009881323808135296,
1257
		0.003867619186470331,
1258
		0.012434465665548913,
1259
		0.007253535500801866,
1260
		0.11106225397288234,
1261
		0.17624726636535937,
1262
		0.008209943140399476,
1263
		0.008390727511299025,
1264
		0.012682898381688294,
1265
		0.1825653885406036,
1266
		0.001538416678816154,
1267
		0.004590756670068524,
1268
		0.008710307625018223,
1269
		0.1299513048549351,
1270
		0.002677941390873305,
1271
		0.012309666132089225,
1272
		0.014087184720804781,
1273
		0.01199941682461,
1274
		0.031246537396121883,
1275
		0.07206648199445984,
1276
		0.008254264470039366,
1277
		0.0007033095203382417,
1278
		0.007034261554162415,
1279
		0.006599212713223502,
1280
		0.013906400349905234,
1281
		0.050098265053214755,
1282
		0.007133401370462167,
1283
		0.017750692520775622,
1284
		0.0008257763522379356,
1285
		0.03918821985712203,
1286
		0.06015454147834961,
1287
	);
1288
}
1289