# HG changeset patch # User Dan # Date 1198816331 18000 # Node ID bfa2e9c23f0346108183e6acf2781a785441dd2b # Parent 67bd3121a12ee5085ec9ead608b13b669801749f Added ability to require CAPTCHA for guests when editing pages (AJAX INTERFACE ONLY) diff -r 67bd3121a12e -r bfa2e9c23f03 ajax.php --- a/ajax.php Thu Dec 27 22:09:33 2007 -0500 +++ b/ajax.php Thu Dec 27 23:32:11 2007 -0500 @@ -114,13 +114,24 @@ $allowed = false; $src = ''; } + + $auth_edit = ( $session->get_permissions('edit_page') && ( $session->get_permissions('even_when_protected') || !$paths->page_protected ) ); + $return = array( 'mode' => 'editor', 'src' => $src, 'auth_view_source' => $allowed, - 'auth_edit' => $session->get_permissions('edit_page'), - 'time' => time() + 'auth_edit' => $auth_edit, + 'time' => time(), + 'require_captcha' => false, ); + + if ( $auth_edit && !$session->user_logged_in && getConfig('guest_edit_require_captcha') == '1' ) + { + $return['require_captcha'] = true; + $return['captcha_id'] = $session->make_captcha(); + } + echo enano_json_encode($return); break; case "getpage": @@ -178,6 +189,27 @@ break; } + // Verify captcha, if needed + if ( !$session->user_logged_in && getConfig('guest_edit_require_captcha') == '1' ) + { + if ( !isset($request['captcha_id']) || !isset($request['captcha_code']) ) + { + die('Invalid request, need captcha metadata'); + } + $code_correct = strtolower($session->get_captcha($request['captcha_id'])); + $code_input = strtolower($request['captcha_code']); + if ( $code_correct !== $code_input ) + { + $return = array( + 'mode' => 'errors', + 'errors' => array($lang->get('editor_err_captcha_wrong')), + 'new_captcha' => $session->make_captcha() + ); + echo enano_json_encode($return); + break; + } + } + // Verification complete. Start the PageProcessor and let it do the dirty work for us. $page = new PageProcessor($paths->page_id, $paths->namespace); if ( $page->update_page($request['src'], $request['summary'], ( $request['minor_edit'] == 1 )) ) @@ -197,6 +229,10 @@ 'mode' => 'errors', 'errors' => array_values($errors) ); + if ( !$session->user_logged_in && getConfig('guest_edit_require_captcha') == '1' ) + { + $return['new_captcha'] = $session->make_captcha(); + } } echo enano_json_encode($return); diff -r 67bd3121a12e -r bfa2e9c23f03 includes/clientside/static/acl.js --- a/includes/clientside/static/acl.js Thu Dec 27 22:09:33 2007 -0500 +++ b/includes/clientside/static/acl.js Thu Dec 27 23:32:11 2007 -0500 @@ -471,7 +471,7 @@ b.appendChild(document.createTextNode($lang.get('acl_lbl_delete_success_title'))); note.appendChild(b); note.appendChild(document.createElement('br')); - note.appendChild(document.createTextNode($lang.get('acl_lbl_delete_success_title', { target_name: aclDataCache.target_name }))); + note.appendChild(document.createTextNode($lang.get('acl_lbl_delete_success_body', { target_name: aclDataCache.target_name }))); note.appendChild(document.createElement('br')); a = document.createElement('a'); a.href = '#'; diff -r 67bd3121a12e -r bfa2e9c23f03 includes/clientside/static/editor.js --- a/includes/clientside/static/editor.js Thu Dec 27 22:09:33 2007 -0500 +++ b/includes/clientside/static/editor.js Thu Dec 27 23:32:11 2007 -0500 @@ -80,12 +80,15 @@ return false; } - ajaxBuildEditor(response.src, (!response.auth_edit), response.time); + // do we need to enter a captcha before saving the page? + var captcha_hash = ( response.require_captcha ) ? response.captcha_id : false; + + ajaxBuildEditor(response.src, (!response.auth_edit), response.time, captcha_hash); } }); } -function ajaxBuildEditor(content, readonly, timestamp) +function ajaxBuildEditor(content, readonly, timestamp, captcha_hash) { // Set flags // We don't want the fancy confirmation framework to trigger if the user is only viewing the page source @@ -255,6 +258,47 @@ tr2.appendChild(td2_1); tr2.appendChild(td2_2); + if ( captcha_hash ) + { + // generate captcha field (effectively third row) + var tr4 = document.createElement('tr'); + var td4_1 = document.createElement('td'); + var td4_2 = document.createElement('td'); + td4_1.className = 'row2'; + td4_2.className = 'row1'; + + td4_1.appendChild(document.createTextNode($lang.get('editor_lbl_field_captcha'))); + td4_1.appendChild(document.createElement('br')); + var small2 = document.createElement('small'); + small2.appendChild(document.createTextNode($lang.get('editor_msg_captcha_pleaseenter'))); + small2.appendChild(document.createElement('br')); + small2.appendChild(document.createElement('br')); + small2.appendChild(document.createTextNode($lang.get('editor_msg_captcha_blind'))); + td4_1.appendChild(small2); + + var img = document.createElement('img'); + img.src = makeUrlNS('Special', 'Captcha/' + captcha_hash); + img._captchaHash = captcha_hash; + img.id = 'enano_editor_captcha_img'; + img.onclick = function() + { + this.src = makeUrlNS('Special', 'Captcha/' + this._captchaHash + '/' + Math.floor(Math.random() * 100000)); + } + img.style.cursor = 'pointer'; + td4_2.appendChild(img); + td4_2.appendChild(document.createElement('br')); + td4_2.appendChild(document.createTextNode($lang.get('editor_lbl_field_captcha_code') + ' ')); + var input = document.createElement('input'); + input.type = 'text'; + input.id = 'enano_editor_field_captcha'; + input._captchaHash = captcha_hash; + input.size = '9'; + td4_2.appendChild(input); + + tr4.appendChild(td4_1); + tr4.appendChild(td4_2); + } + // Third row: controls var tr3 = document.createElement('tr'); var td3 = document.createElement('th'); @@ -302,6 +346,10 @@ metatable.appendChild(tr1); metatable.appendChild(tr2); + if ( captcha_hash ) + { + metatable.appendChild(tr4); + } metatable.appendChild(tr3); } tblholder.appendChild(metatable); @@ -339,6 +387,14 @@ { ajaxSetEditorLoading(); var ta_content = $('ajaxEditArea').getContent(); + + if ( ta_content == '' || ta_content == '
' || ta_content == '' ) + { + new messagebox(MB_OK|MB_ICONSTOP, $lang.get('editor_err_no_text_title'), $lang.get('editor_err_no_text_body')); + ajaxUnSetEditorLoading(); + return false; + } + var edit_summ = $('enano_editor_field_summary').object.value; if ( !edit_summ ) edit_summ = ''; @@ -351,6 +407,21 @@ minor_edit: is_minor, time: timestamp }; + + // Do we need to add captcha info? + if ( document.getElementById('enano_editor_field_captcha') ) + { + var captcha_field = document.getElementById('enano_editor_field_captcha'); + if ( captcha_field.value == '' ) + { + new messagebox(MB_OK|MB_ICONSTOP, $lang.get('editor_err_need_captcha_title'), $lang.get('editor_err_need_captcha_body')); + ajaxUnSetEditorLoading(); + return false; + } + json_packet.captcha_code = captcha_field.value; + json_packet.captcha_id = captcha_field._captchaHash; + } + json_packet = ajaxEscape(toJSONString(json_packet)); ajaxPost(stdAjaxPrefix + '&_mode=savepage_json', 'r=' + json_packet, function() { @@ -374,6 +445,21 @@ // This will be used if the PageProcessor generated errors (usually security/permissions related) if ( response.mode == 'errors' ) { + // This will be true if the user entered a captcha code incorrectly, thus + // invalidating the code and requiring a new image to be generated. + if ( response.new_captcha ) + { + // Generate the new captcha field + var img = document.getElementById('enano_editor_captcha_img'); + var input = document.getElementById('enano_editor_field_captcha'); + if ( img && input ) + { + img._captchaHash = response.new_captcha; + input._captchaHash = response.new_captcha; + img.src = makeUrlNS('Special', 'Captcha/' + response.new_captcha); + input.value = ''; + } + } var errors = '