1jQuery(function () {
2
3    var $passfield = jQuery('form input[type=password][name=pass], ' +
4        'form input[type=password][name=newpass], ' +
5        '#add_userpass, #modify_userpass');
6    if (!$passfield.length) return;
7
8    /**
9     * Scores a password's strength on an open scale
10     *
11     * @author Toms Baugis
12     * @link http://stackoverflow.com/a/11268104
13     * @param pass string
14     * @return int
15     */
16    function scorePassword(pass) {
17        var score = 0;
18        if (!pass)
19            return score;
20
21        // award every unique letter until 5 repetitions
22        var letters = {};
23        for (var i = 0; i < pass.length; i++) {
24            letters[pass[i]] = (letters[pass[i]] || 0) + 1;
25            score += 5.0 / letters[pass[i]];
26        }
27
28        // bonus points for mixing it up
29        var variations = {
30            digits: /\d/.test(pass),
31            lower: /[a-z]/.test(pass),
32            upper: /[A-Z]/.test(pass),
33            nonWords: /\W/.test(pass)
34        };
35
36        var variationCount = 0;
37        for (var check in variations) {
38            variationCount += (variations[check]) ? 1 : 0;
39        }
40        score += (variationCount - 1) * 10;
41
42        return parseInt(score);
43    }
44
45    /**
46     * check policy
47     *
48     * @param $field object jQuery object of the password field
49     * @param indicator DomObject where the output should go
50     */
51    function checkpolicy($field, indicator) {
52        var pass = $field.val();
53        var user = jQuery('form input[type=text][name=login]').val();
54
55        jQuery.post(
56            DOKU_BASE + 'lib/exe/ajax.php',
57            {
58                call: 'plugin_passpolicy',
59                pass: pass,
60                user: user
61            },
62            function (response) {
63                if (response === '1') {
64                    scoreit($field, indicator, true);
65                } else {
66                    scoreit($field, indicator, false);
67                }
68            }
69        );
70    }
71
72    /**
73     * Apply scoring
74     *
75     * @param {object} $field jQuery object of the password field
76     * @param {Node} indicator where the output should go
77     * @param {bool} policy true if the policy is met
78     */
79    function scoreit($field, indicator, policy) {
80        var score = scorePassword($field.val());
81
82        if (score > 80) {
83            indicator.innerHTML = LANG.plugins.passpolicy.strength3;
84            indicator.className = 'passpolicy_strength3';
85        } else if (score >= 60) {
86            indicator.innerHTML = LANG.plugins.passpolicy.strength2;
87            indicator.className = 'passpolicy_strength2';
88        } else if (score >= 30) {
89            indicator.innerHTML = LANG.plugins.passpolicy.strength1;
90            indicator.className = 'passpolicy_strength1';
91        } else {
92            indicator.innerHTML = LANG.plugins.passpolicy.strength0;
93            indicator.className = 'passpolicy_strength0';
94        }
95
96        if (!policy) {
97            indicator.innerHTML += LANG.plugins.passpolicy.nopolicy;
98            indicator.className = 'passpolicy_strength0';
99        }
100    }
101
102    /**
103     * Attach strength tester at the found password fields
104     */
105    $passfield.each(function () {
106        var $field = jQuery(this);
107
108        var indicator = document.createElement('p');
109        indicator.className = 'passpolicy__indicator';
110
111        $field.after(indicator);
112        $field.keyup(function () {
113            checkpolicy($field, indicator)
114        });
115        $field.blur(function () {
116            checkpolicy($field, indicator)
117        });
118    });
119
120
121});
122