xref: /plugin/passwd/script.js (revision eb872c2a652d2b4294f9c5ebca2ba18675c61627)
1*eb872c2aStomLin1998567/**
2*eb872c2aStomLin1998567 * PASSWD Plugin — unlock password-protected sections with captcha verification.
3*eb872c2aStomLin1998567 *
4*eb872c2aStomLin1998567 * On page load, each .passwd_block fetches a fresh captcha via AJAX.
5*eb872c2aStomLin1998567 * The user enters a password and solves the captcha, then submits the form.
6*eb872c2aStomLin1998567 * If both are correct the protected content is revealed inline;
7*eb872c2aStomLin1998567 * otherwise a new captcha is returned automatically.
8*eb872c2aStomLin1998567 */
9*eb872c2aStomLin1998567
10*eb872c2aStomLin1998567/**
11*eb872c2aStomLin1998567 * Toggle password visibility for a PASSWD input field.
12*eb872c2aStomLin1998567 */
13*eb872c2aStomLin1998567function passwd_toggle(btn) {
14*eb872c2aStomLin1998567    var wrapper = btn.parentNode;
15*eb872c2aStomLin1998567    var input = wrapper.querySelector('.passwd_input');
16*eb872c2aStomLin1998567    if (input.type === 'password') {
17*eb872c2aStomLin1998567        input.type = 'text';
18*eb872c2aStomLin1998567        btn.textContent = '��';
19*eb872c2aStomLin1998567        btn.title = 'Hide password';
20*eb872c2aStomLin1998567    } else {
21*eb872c2aStomLin1998567        input.type = 'password';
22*eb872c2aStomLin1998567        btn.textContent = '��';
23*eb872c2aStomLin1998567        btn.title = 'Show password';
24*eb872c2aStomLin1998567    }
25*eb872c2aStomLin1998567}
26*eb872c2aStomLin1998567
27*eb872c2aStomLin1998567/**
28*eb872c2aStomLin1998567 * Attempt to unlock a PASSWD block identified by its numeric index.
29*eb872c2aStomLin1998567 *
30*eb872c2aStomLin1998567 * @param {number} idx  The data-idx attribute of the target block.
31*eb872c2aStomLin1998567 */
32*eb872c2aStomLin1998567function passwd_unlock(idx) {
33*eb872c2aStomLin1998567    var $block = jQuery('.passwd_block[data-idx="' + idx + '"]');
34*eb872c2aStomLin1998567    var $form = $block.find('.passwd_form');
35*eb872c2aStomLin1998567    var data = $form.serializeArray();
36*eb872c2aStomLin1998567    data.push({name: 'call', value: 'passwd_check'});
37*eb872c2aStomLin1998567    data.push({name: 'block', value: idx});
38*eb872c2aStomLin1998567    if (typeof JSINFO !== 'undefined') {
39*eb872c2aStomLin1998567        data.push({name: 'id', value: JSINFO.id});
40*eb872c2aStomLin1998567    }
41*eb872c2aStomLin1998567
42*eb872c2aStomLin1998567    jQuery.post(
43*eb872c2aStomLin1998567        DOKU_BASE + 'lib/exe/ajax.php',
44*eb872c2aStomLin1998567        data,
45*eb872c2aStomLin1998567        function(resp) {
46*eb872c2aStomLin1998567            if (resp.indexOf('CAPTCHA_FAILED|') === 0) {
47*eb872c2aStomLin1998567                // Reset to the default error text (from config) and show
48*eb872c2aStomLin1998567                $block.find('.passwd_error').show();
49*eb872c2aStomLin1998567                $block.find('.passwd_captcha')
50*eb872c2aStomLin1998567                      .html(resp.substring('CAPTCHA_FAILED|'.length));
51*eb872c2aStomLin1998567            } else if (resp.indexOf('WRONG_PASSWORD|') === 0) {
52*eb872c2aStomLin1998567                $block.find('.passwd_error').show();
53*eb872c2aStomLin1998567                $block.find('.passwd_captcha')
54*eb872c2aStomLin1998567                      .html(resp.substring('WRONG_PASSWORD|'.length));
55*eb872c2aStomLin1998567            } else if (resp === 'BLOCK_NOT_FOUND' || resp === 'PASSWORD_NOT_FOUND') {
56*eb872c2aStomLin1998567                $block.find('.passwd_error').text('System error, contact admin').show();
57*eb872c2aStomLin1998567            } else {
58*eb872c2aStomLin1998567                // Success — show decrypted content, hide the form
59*eb872c2aStomLin1998567                $block.find('.passwd_form').hide();
60*eb872c2aStomLin1998567                $block.find('.passwd_content').html(resp).show();
61*eb872c2aStomLin1998567            }
62*eb872c2aStomLin1998567        }
63*eb872c2aStomLin1998567    );
64*eb872c2aStomLin1998567}
65*eb872c2aStomLin1998567
66*eb872c2aStomLin1998567// On DOM ready: fetch a captcha for every passwd block and bind form submission.
67*eb872c2aStomLin1998567jQuery(function() {
68*eb872c2aStomLin1998567    // Fetch a fresh captcha for each block, so cached pages never show stale tokens.
69*eb872c2aStomLin1998567    jQuery('.passwd_block').each(function() {
70*eb872c2aStomLin1998567        var $block = jQuery(this);
71*eb872c2aStomLin1998567        jQuery.get(DOKU_BASE + 'lib/exe/ajax.php', {
72*eb872c2aStomLin1998567            call: 'passwd_refresh_captcha'
73*eb872c2aStomLin1998567        }, function(html) {
74*eb872c2aStomLin1998567            $block.find('.passwd_captcha').html(html);
75*eb872c2aStomLin1998567        });
76*eb872c2aStomLin1998567    });
77*eb872c2aStomLin1998567
78*eb872c2aStomLin1998567    // Intercept form submission to use AJAX instead of a full page reload.
79*eb872c2aStomLin1998567    jQuery(document).on('submit', '.passwd_block .passwd_form', function(e) {
80*eb872c2aStomLin1998567        e.preventDefault();
81*eb872c2aStomLin1998567        var idx = jQuery(this).closest('.passwd_block').data('idx');
82*eb872c2aStomLin1998567        passwd_unlock(idx);
83*eb872c2aStomLin1998567    });
84*eb872c2aStomLin1998567});
85