]> git.mjollnir.org Git - moodle.git/commitdiff
MDL-13796 Most of the recaptcha implementation is done.
authornicolasconnault <nicolasconnault>
Mon, 10 Mar 2008 17:32:32 +0000 (17:32 +0000)
committernicolasconnault <nicolasconnault>
Mon, 10 Mar 2008 17:32:32 +0000 (17:32 +0000)
12 files changed:
admin/settings/users.php
auth/email/auth.php
auth/email/config.html
lang/en_utf8/admin.php
lang/en_utf8/auth.php
lang/en_utf8/help/grade/decimalpoints.html
lang/en_utf8/help/grade/index.html
lib/form/recaptcha.php [new file with mode: 0644]
lib/formslib.php
lib/recaptchalib.php [new file with mode: 0644]
login/signup.php
login/signup_form.php

index aafbfffd2f64f7b688b40d5bd18f3f402b4a1bcd..9922d0b5cf0160a946766aa294d072023cadf0b5 100644 (file)
@@ -25,7 +25,9 @@ if ($hassiteconfig
                                                 get_string('authinstructions', 'auth'), ''));
     $temp->add(new admin_setting_configtext('allowemailaddresses', get_string('allowemailaddresses', 'admin'), get_string('configallowemailaddresses', 'admin'), '', PARAM_NOTAGS));
     $temp->add(new admin_setting_configtext('denyemailaddresses', get_string('denyemailaddresses', 'admin'), get_string('configdenyemailaddresses', 'admin'), '', PARAM_NOTAGS));
-
+    
+    $temp->add(new admin_setting_configtext('recaptchapublickey', get_string('recaptchapublickey', 'admin'), get_string('configrecaptchapublickey', 'admin'), '', PARAM_NOTAGS));
+    $temp->add(new admin_setting_configtext('recaptchaprivatekey', get_string('recaptchaprivatekey', 'admin'), get_string('configrecaptchaprivatekey', 'admin'), '', PARAM_NOTAGS));
     $ADMIN->add('authsettings', $temp);
 
 
index 2480271ec5a55ff840c10951bc712bfd3bdab446..82e0ba29a6cab27e8da49280c7e067259b7f9cb3 100644 (file)
@@ -197,6 +197,13 @@ class auth_plugin_email extends auth_plugin_base {
      * Processes and stores configuration data for this authentication plugin.
      */
     function process_config($config) {
+        // set to defaults if undefined
+        if (!isset($config->recaptcha)) { 
+            $config->recaptcha = false; 
+        }
+        
+        // save settings
+        set_config('recaptcha', $config->recaptcha, 'auth/email');
         return true;
     }
 
index a2c1bcd5fa1838d5b23194a88c7b4ff6ebd9d897..3b11a09a8d6f26cb3d09877b967d6ae5c044befb 100644 (file)
@@ -1,7 +1,25 @@
 <!-- No config needed -->
-<div style="text-align: center"><?php print_string('none'); ?></div>
+<?php
+    // set to defaults if undefined
+    if (!isset($config->recaptcha)) {
+        $config->recaptcha = false;
+    }
+
+    $yesno = array( get_string('no'), get_string('yes') );
+
+?>
 
 <table cellspacing="0" cellpadding="5" border="0">
+<tr>
+   <td colspan="3">
+        <h2 class="main"><?php print_string('auth_emailsettings', 'auth') ?> </h2>
+   </td>
+</tr>
+<tr>
+    <td align="right"><label for="recaptcha"><?php print_string('auth_emailrecaptcha_key', 'auth') ?></label></td>
+    <td><?php choose_from_menu($yesno, 'recaptcha', $config->recaptcha, ''); ?></td> 
+    <td><?php print_string('auth_emailrecaptcha', 'auth') ?></td>
+</tr>    
 <?php
 
 print_auth_lock_options('email', $user_fields, get_string('auth_fieldlocks_help', 'auth'), false, false);
index 6c64dc9dbc37b3b1adf1038c64dc7872b3825261..b287411eb9fb80b84f6cb30b11079629dd3382f7 100644 (file)
@@ -188,6 +188,8 @@ $string['configcronremotepassword'] = 'This means that the cron.php script canno
 </pre>If this is left empty, no password is required.';
 $string['configrcache'] = 'Use the cache to store database records. Remember to set \'cachetype\' as well!';
 $string['configrcachettl'] = 'Time-to-live for cached records, in seconds. Use a short (&lt;15) value here.';
+$string['configrecaptchaprivatekey'] = 'String of characters used to communicate between your Moodle server and the recaptcha.net server. Obtain one for this site by visiting http://recaptcha.net';
+$string['configrecaptchapublickey'] = 'String of characters used to display the reCAPTCHA element in the signup form. Generated by http://recaptcha.net';
 $string['configrequestedstudentname'] = 'Word for student used in requested courses';
 $string['configrequestedstudentsname'] = 'Word for students used in requested courses';
 $string['configrequestedteachername'] = 'Word for teacher used in requested courses';
@@ -586,6 +588,8 @@ $string['questioncwqpfscheck'] = 'One or more \'random\' questions in a quiz are
 $string['questioncwqpfsok'] = 'Good. There are no \'random\' questions in your quizzes that are set up to select questions from a mixture of shared and unshared question categories.';
 $string['rcache'] = 'Record cache';
 $string['rcachettl'] = 'Record cache TTL';
+$string['recaptchapublickey'] = 'ReCAPTCHA public key';
+$string['recaptchaprivatekey'] = 'ReCAPTCHA private key';
 $string['releasenoteslink'] = 'For information about this version of Moodle, please see the online <a target=\"_blank\" href=\"$a\">Release Notes</a>';
 $string['remotelangnotavailable'] = 'Because Moodle can not connect to download.moodle.org, we are unable to do language pack installation automatically. Please download the appropriate zip file(s) from the list below, copy them to your $a directory and unzip them manually.';
 $string['renameerrors'] = 'Rename errors';
index dcb4d9bb0b462b10f44a1a89d17d97bb437ff849..bf0c32399d44821c3dca3518ac444970994cd0a4 100644 (file)
@@ -117,6 +117,9 @@ $string['auth_emaildescription'] = 'Email confirmation is the default authentica
 $string['auth_emailtitle'] = 'Email-based self-registration';
 $string['auth_emailnoinsert'] = 'Could not add your record to the database!';
 $string['auth_emailnoemail'] = 'Tried to send you an email but failed!';
+$string['auth_emailrecaptcha'] = 'Adds a visual/audio confirmation form element to the signup page for email self-registering users. This protects your site against spammers and contributes to a worthwhile cause. See http://recaptcha.net/learnmore.html for more details.';
+$string['auth_emailrecaptcha_key'] = 'Enable reCAPTCHA element';
+$string['auth_emailsettings'] = 'Settings';
 
 // FirstClass plugin
 $string['auth_fccreators'] = 'List of groups whose members are allowed to create new courses. Separate multiple groups with \';\'. Names must be spelled exactly as on FirstClass server. System is case-sensitive.';
@@ -374,5 +377,10 @@ $string['update_never']    = 'Never';
 $string['unlocked'] = 'Unlocked';
 $string['unlockedifempty'] = 'Unlocked if empty';
 $string['locked'] = 'Locked';
-
+$string['incorrectpleasetryagain'] = 'Incorrect. Please try again.';
+$string['enterthewordsabove'] = 'Enter the words above:';
+$string['enterthenumbersyouhear'] = 'Enter the numbers you hear:';
+$string['getanothercaptcha'] = 'Get another CAPTCHA';
+$string['getanaudiocaptcha'] = 'Get an audio CAPTCHA';
+$string['getanimagecaptcha'] = 'Get an image CAPTCHA';
 ?>
index fbf61e2f932485a73c6d025dd752107336d7cd4f..a4e89f2b835e5cc610c28afaebba4e8041b35984 100644 (file)
@@ -1,2 +1,2 @@
 <h1>Overall decimal points</h1>
-<p>Specifies the number of decimal points to display for each grade. This setting may be overridden per grading item.</p>
+<p>Specifies the number of decimal points to display for each grade. This setting has no effect on grade calculations, which are made with an accuracy of 5 decimal places.</p>
index 091bde856daa94b82914b650243e1a9ca75b696b..450410edc4440efc6803681bf30f6f5c02438d4a 100644 (file)
@@ -1,10 +1,71 @@
 <h2>Grade</h2>
 <ul>
-  <li><a href="help.php?module=grade&amp;file=category.html">Category</a></li>
-  <li><a href="help.php?module=grade&amp;file=exceptions.html">Exceptions</a></li>
-  <li><a href="help.php?module=grade&amp;file=teacher.html">Grades</a></li>
-  <li><a href="help.php?module=grade&amp;file=letter.html">Letter Scale</a></li>
-  <li><a href="help.php?module=grade&amp;file=preferences.html">Set Preferences</a></li>
-  <li><a href="help.php?module=grade&amp;file=student.html">Student Grade Help</a></li>
-  <li><a href="help.php?module=grade&amp;file=weight.html">Weight</a></li>
-</ul>
\ No newline at end of file
+       <li><a href="help.php?module=grade&amp;file=aggregateonlygraded.html">Aggregate only non-empty grades</a></li>
+       <li><a href="help.php?module=grade&amp;file=aggregateoutcomes.html">Include outcomes in aggregation</a></li>
+       <li><a href="help.php?module=grade&amp;file=aggregatesubcats.html">Aggregate including subcategories</a></li>
+       <li><a href="help.php?module=grade&amp;file=aggregation.html">Category aggregation</a></li>
+       <li><a href="help.php?module=grade&amp;file=aggregationcoefextra.html">Extra credit</a></li>
+       <li><a href="help.php?module=grade&amp;file=aggregationcoefextrasum.html">Extra credit</a></li>
+       <li><a href="help.php?module=grade&amp;file=aggregationcoefweight.html">Item weight</a></li>
+       <li><a href="help.php?module=grade&amp;file=aggregationposition.html">Aggregation position</a></li>
+       <li><a href="help.php?module=grade&amp;file=aggregationview.html">Aggregation view</a></li>
+       <li><a href="help.php?module=grade&amp;file=averagesdecimalpoints.html">Decimals in column averages</a></li>
+       <li><a href="help.php?module=grade&amp;file=averagesdisplaytype.html">Column averages display type</a></li>
+       <li><a href="help.php?module=grade&amp;file=calculation.html">Calculations</a></li>
+       <li><a href="help.php?module=grade&amp;file=category.html">Category</a></li>
+       <li><a href="help.php?module=grade&amp;file=decimalpoints.html">Overall decimal points</a></li>
+       <li><a href="help.php?module=grade&amp;file=droplow.html">Drop the lowest</a></li>
+       <li><a href="help.php?module=grade&amp;file=exceptions.html">Exceptions</a></li>
+       <li><a href="help.php?module=grade&amp;file=excluded.html">Excluded grades</a></li>
+       <li><a href="help.php?module=grade&amp;file=exportdecimalpoints.html">Export decimal points</a></li>
+       <li><a href="help.php?module=grade&amp;file=feedback.html">Feedback</a></li>
+       <li><a href="help.php?module=grade&amp;file=finalgrade.html">Final grade</a></li>
+       <li><a href="help.php?module=grade&amp;file=gradeboundary.html">Grade boundary</a></li>
+       <li><a href="help.php?module=grade&amp;file=gradedisplaytype.html">Grade display type</a></li>
+       <li><a href="help.php?module=grade&amp;file=gradeexportdisplaytype.html">Grade export display type</a></li>
+       <li><a href="help.php?module=grade&amp;file=gradeletter.html">Grade letters</a></li>
+       <li><a href="help.php?module=grade&amp;file=grademax.html">Maximum Grade</a></li>
+       <li><a href="help.php?module=grade&amp;file=grademin.html">Minimum Grade</a></li>
+       <li><a href="help.php?module=grade&amp;file=gradepass.html">Grade to pass</a></li>
+       <li><a href="help.php?module=grade&amp;file=gradetype.html">Grade type</a></li>
+       <li><a href="help.php?module=grade&amp;file=hidden.html">Hidden</a></li>
+       <li><a href="help.php?module=grade&amp;file=hiddenuntil.html">Hidden until</a></li>
+       <li><a href="help.php?module=grade&amp;file=idnumber.html">Id numbers</a></li>
+       <li><a href="help.php?module=grade&amp;file=iteminfo.html">Item info</a></li>
+       <li><a href="help.php?module=grade&amp;file=keephigh.html">Keep the highest</a></li>
+       <li><a href="help.php?module=grade&amp;file=letter.html">Letter scale</a></li>
+       <li><a href="help.php?module=grade&amp;file=linkedactivity.html">Linked activity</a></li>
+       <li><a href="help.php?module=grade&amp;file=locked.html">Locked</a></li>
+       <li><a href="help.php?module=grade&amp;file=lockedafter.html">Locked after</a></li>
+       <li><a href="help.php?module=grade&amp;file=meanselection.html">Grades selected for column averages</a></li>
+       <li><a href="help.php?module=grade&amp;file=multfactor.html">Multiplicator</a></li>
+       <li><a href="help.php?module=grade&amp;file=outcomeid.html">Outcome</a></li>
+       <li><a href="help.php?module=grade&amp;file=outcomestandard.html">Standard outcomes</a></li>
+       <li><a href="help.php?module=grade&amp;file=overridden.html">Overridden</a></li>
+       <li><a href="help.php?module=grade&amp;file=overridesitedefaultgradedisplaytype.html">Override site defaults</a></li>
+       <li><a href="help.php?module=grade&amp;file=plusfactor.html">Offset</a></li>
+       <li><a href="help.php?module=grade&amp;file=preferences.html">Set Preferences</a></li>
+       <li><a href="help.php?module=grade&amp;file=quickgrading.html">Quick grading</a></li>
+       <li><a href="help.php?module=grade&amp;file=rangesdecimalpoints.html">Decimals shown in ranges</a></li>
+       <li><a href="help.php?module=grade&amp;file=rangesdisplaytype.html">Range display type</a></li>
+       <li><a href="help.php?module=grade&amp;file=scaleid.html">Scale</a></li>
+       <li><a href="help.php?module=grade&amp;file=scalestandard.html">Standard scales</a></li>
+       <li><a href="help.php?module=grade&amp;file=showactivityicons.html">Show activity icons</a></li>
+       <li><a href="help.php?module=grade&amp;file=showaverages.html">Show averages</a></li>
+       <li><a href="help.php?module=grade&amp;file=showcalculations.html">Show calculations</a></li>
+       <li><a href="help.php?module=grade&amp;file=showeyecons.html"></a>Show show/hide icons</li>
+       <li><a href="help.php?module=grade&amp;file=showfeedback.html">Show feedback</a></li>
+       <li><a href="help.php?module=grade&amp;file=showgroups.html">Show groups</a></li>
+       <li><a href="help.php?module=grade&amp;file=showhiddenitems.html">Show hidden items</a></li>
+       <li><a href="help.php?module=grade&amp;file=showlocks.html">Show locks</a></li>
+       <li><a href="help.php?module=grade&amp;file=shownumberofgrades.html">Show number of grades</a></li>
+       <li><a href="help.php?module=grade&amp;file=showquickfeedback.html">Show quick feedback</a></li>
+       <li><a href="help.php?module=grade&amp;file=showranges.html">Show ranges</a></li>
+       <li><a href="help.php?module=grade&amp;file=showrank.html">Show rank</a></li>
+       <li><a href="help.php?module=grade&amp;file=showuseridnumber.html">Show user id numbers</a></li>
+       <li><a href="help.php?module=grade&amp;file=student.html">Student Grade Help</a></li>
+       <li><a href="help.php?module=grade&amp;file=studentsperpage.html">Students per page</a></li>
+       <li><a href="help.php?module=grade&amp;file=teacher.html">Grades</a></li>
+       <li><a href="help.php?module=grade&amp;file=userkey.html">User key</a></li>
+       <li><a href="help.php?module=grade&amp;file=weight.html">Weight</a></li> 
+</ul>
diff --git a/lib/form/recaptcha.php b/lib/form/recaptcha.php
new file mode 100644 (file)
index 0000000..34ce626
--- /dev/null
@@ -0,0 +1,84 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * textarea_counter.php
+ *
+ * @category  Admin
+ * @package   admin
+ * @author    Nicolas Connault <nicolasconnault@gmail.com>
+ * @version   $Id$
+ */
+
+
+/**
+ * @category Admin
+ * @package  admin
+ */
+class MoodleQuickForm_recaptcha extends HTML_QuickForm_input {
+
+    /**
+     * <code>
+     * $form->addElement('textarea_counter', 'message', 'Message',
+     *   array('cols'=>60, 'rows'=>10), 160);
+     * </code>
+     */
+    function HTML_QuickForm_recaptcha($elementName = null, $elementLabel = null, $attributes = null) {
+        parent::HTML_QuickForm_input($elementName, $elementLabel, $attributes);
+        $this->_type = 'recaptcha';
+    }
+
+    /**
+     * Returns the recaptcha element in HTML
+     *
+     * @since     1.0
+     * @access    public
+     * @return    string
+     */
+    function toHtml() {
+        global $CFG;
+        require_once $CFG->libdir . '/recaptchalib.php';
+
+        $html = '<script type="text/javascript">
+            var RecaptchaOptions = {
+                theme : \'custom\',
+                tabindex : 2,
+                custom_theme_widget : \'recaptcha_widget\'
+            };
+              </script>' . "\n";
+
+              
+        if (empty($_SESSION['recaptcha_error'])) {
+            $_SESSION['recaptcha_error'] = null;
+        }
+        $error = $_SESSION['recaptcha_error'];
+        unset($_SESSION['recaptcha_error']);
+        
+        $strincorrectpleasetryagain = get_string('incorrectpleasetryagain', 'auth');
+        $strenterthewordsabove = get_string('enterthewordsabove', 'auth');
+        $strenterthenumbersyouhear = get_string('enterthenumbersyouhear', 'auth');
+        $strgetanothercaptcha = get_string('getanothercaptcha', 'auth');
+        $strgetanaudiocaptcha = get_string('getanaudiocaptcha', 'auth');
+        $strgetanimagecaptcha = get_string('getanimagecaptcha', 'auth');
+
+        $html .= '
+<div id="recaptcha_widget" style="display:none">
+
+<div id="recaptcha_image"></div>
+<div class="recaptcha_only_if_incorrect_sol" style="color:red">' . $strincorrectpleasetryagain . '</div>
+
+<span class="recaptcha_only_if_image">' . $strenterthewordsabove . '</span>
+<span class="recaptcha_only_if_audio">' . $strenterthenumbersyouhear . '</span>
+
+<input type="text" id="recaptcha_response_field" name="recaptcha_response_field" />
+
+<div><a href="javascript:Recaptcha.reload()">' . $strgetanothercaptcha . '</a></div>
+<div class="recaptcha_only_if_image"><a href="javascript:Recaptcha.switch_type(\'audio\')">' . $strgetanaudiocaptcha . '</a></div>
+<div class="recaptcha_only_if_audio"><a href="javascript:Recaptcha.switch_type(\'image\')">' . $strgetanimagecaptcha . '</a></div>
+</div>'; 
+
+        return $html . recaptcha_get_html($CFG->recaptchapublickey, $error);
+    }
+}
+
+?>
index 57ebb4173f3827d11672c667573f66ffde4b3a4e..e2f3e7dea04c29c47341d3cd858068d91108fb34 100644 (file)
@@ -1876,4 +1876,5 @@ MoodleQuickForm::registerElementType('header', "$CFG->libdir/form/header.php", '
 MoodleQuickForm::registerElementType('submit', "$CFG->libdir/form/submit.php", 'MoodleQuickForm_submit');
 MoodleQuickForm::registerElementType('questioncategory', "$CFG->libdir/form/questioncategory.php", 'MoodleQuickForm_questioncategory');
 MoodleQuickForm::registerElementType('advcheckbox', "$CFG->libdir/form/advcheckbox.php", 'MoodleQuickForm_advcheckbox');
+MoodleQuickForm::registerElementType('recaptcha', "$CFG->libdir/form/recaptcha.php", 'MoodleQuickForm_recaptcha');
 ?>
diff --git a/lib/recaptchalib.php b/lib/recaptchalib.php
new file mode 100644 (file)
index 0000000..aea6e0d
--- /dev/null
@@ -0,0 +1,276 @@
+<?php
+/*
+ * This is a PHP library that handles calling reCAPTCHA.
+ *    - Documentation and latest version
+ *          http://recaptcha.net/plugins/php/
+ *    - Get a reCAPTCHA API Key
+ *          http://recaptcha.net/api/getkey
+ *    - Discussion group
+ *          http://groups.google.com/group/recaptcha
+ *
+ * Copyright (c) 2007 reCAPTCHA -- http://recaptcha.net
+ * AUTHORS:
+ *   Mike Crawford
+ *   Ben Maurer
+ *
+ * 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.
+ */
+
+/**
+ * The reCAPTCHA server URL's
+ */
+define("RECAPTCHA_API_SERVER", "http://api.recaptcha.net");
+define("RECAPTCHA_API_SECURE_SERVER", "https://api-secure.recaptcha.net");
+define("RECAPTCHA_VERIFY_SERVER", "api-verify.recaptcha.net");
+
+/**
+ * Encodes the given data into a query string format
+ * @param $data - array of string elements to be encoded
+ * @return string - encoded request
+ */
+function _recaptcha_qsencode ($data) {
+        $req = "";
+        foreach ( $data as $key => $value )
+                $req .= $key . '=' . urlencode( stripslashes($value) ) . '&';
+
+        // Cut the last '&'
+        $req=substr($req,0,strlen($req)-1);
+        return $req;
+}
+
+
+
+/**
+ * Submits an HTTP POST to a reCAPTCHA server
+ * @param string $host
+ * @param string $path
+ * @param array $data
+ * @param int port
+ * @return array response
+ */
+function _recaptcha_http_post($host, $path, $data, $port = 80) {
+
+        $req = _recaptcha_qsencode ($data);
+
+        $http_request  = "POST $path HTTP/1.0\r\n";
+        $http_request .= "Host: $host\r\n";
+        $http_request .= "Content-Type: application/x-www-form-urlencoded;\r\n";
+        $http_request .= "Content-Length: " . strlen($req) . "\r\n";
+        $http_request .= "User-Agent: reCAPTCHA/PHP\r\n";
+        $http_request .= "\r\n";
+        $http_request .= $req;
+
+        $response = '';
+        if( false == ( $fs = @fsockopen($host, $port, $errno, $errstr, 10) ) ) {
+                die ('Could not open socket');
+        }
+
+        fwrite($fs, $http_request);
+
+        while ( !feof($fs) )
+                $response .= fgets($fs, 1160); // One TCP-IP packet
+        fclose($fs);
+        $response = explode("\r\n\r\n", $response, 2);
+
+        return $response;
+}
+
+
+
+/**
+ * Gets the challenge HTML (javascript and non-javascript version).
+ * This is called from the browser, and the resulting reCAPTCHA HTML widget
+ * is embedded within the HTML form it was called from.
+ * @param string $pubkey A public key for reCAPTCHA
+ * @param string $error The error given by reCAPTCHA (optional, default is null)
+ * @param boolean $use_ssl Should the request be made over ssl? (optional, default is false)
+
+ * @return string - The HTML to be embedded in the user's form.
+ */
+function recaptcha_get_html ($pubkey, $error = null, $use_ssl = false)
+{
+       if ($pubkey == null || $pubkey == '') {
+               die ("To use reCAPTCHA you must get an API key from <a href='http://recaptcha.net/api/getkey'>http://recaptcha.net/api/getkey</a>");
+       }
+       
+       if ($use_ssl) {
+                $server = RECAPTCHA_API_SECURE_SERVER;
+        } else {
+                $server = RECAPTCHA_API_SERVER;
+        }
+
+        $errorpart = "";
+        if ($error) {
+           $errorpart = "&amp;error=" . $error;
+        }
+        return '<script type="text/javascript" src="'. $server . '/challenge?k=' . $pubkey . $errorpart . '"></script>
+
+       <noscript>
+               <iframe src="'. $server . '/noscript?k=' . $pubkey . $errorpart . '" height="300" width="500" frameborder="0"></iframe><br>
+               <textarea name="recaptcha_challenge_field" rows="3" cols="40"></textarea>
+               <input type="hidden" name="recaptcha_response_field" value="manual_challenge">
+       </noscript>';
+}
+
+
+
+
+/**
+ * A ReCaptchaResponse is returned from recaptcha_check_answer()
+ */
+class ReCaptchaResponse {
+        var $is_valid;
+        var $error;
+}
+
+
+/**
+  * Calls an HTTP POST function to verify if the user's guess was correct
+  * @param string $privkey
+  * @param string $remoteip
+  * @param string $challenge
+  * @param string $response
+  * @return ReCaptchaResponse
+  */
+function recaptcha_check_answer ($privkey, $remoteip, $challenge, $response)
+{
+       if ($privkey == null || $privkey == '') {
+               die ("To use reCAPTCHA you must get an API key from <a href='http://recaptcha.net/api/getkey'>http://recaptcha.net/api/getkey</a>");
+       }
+
+       if ($remoteip == null || $remoteip == '') {
+               die ("For security reasons, you must pass the remote ip to reCAPTCHA");
+       }
+
+       
+       
+        //discard spam submissions
+        if ($challenge == null || strlen($challenge) == 0 || $response == null || strlen($response) == 0) {
+                $recaptcha_response = new ReCaptchaResponse();
+                $recaptcha_response->is_valid = false;
+                $recaptcha_response->error = 'incorrect-captcha-sol';
+                return $recaptcha_response;
+        }
+
+        $response = _recaptcha_http_post (RECAPTCHA_VERIFY_SERVER, "/verify",
+                                          array (
+                                                 'privatekey' => $privkey,
+                                                 'remoteip' => $remoteip,
+                                                 'challenge' => $challenge,
+                                                 'response' => $response
+                                                 )
+                                          );
+
+        $answers = explode ("\n", $response [1]);
+        $recaptcha_response = new ReCaptchaResponse();
+
+        if (trim ($answers [0]) == 'true') {
+                $recaptcha_response->is_valid = true;
+        }
+        else {
+                $recaptcha_response->is_valid = false;
+                $recaptcha_response->error = $answers [1];
+        }
+        return $recaptcha_response;
+
+}
+
+/**
+ * gets a URL where the user can sign up for reCAPTCHA. If your application
+ * has a configuration page where you enter a key, you should provide a link
+ * using this function.
+ * @param string $domain The domain where the page is hosted
+ * @param string $appname The name of your application
+ */
+function recaptcha_get_signup_url ($domain = null, $appname = null) {
+       return "http://recaptcha.net/api/getkey?" .  _recaptcha_qsencode (array ('domain' => $domain, 'app' => $appname));
+}
+
+function _recaptcha_aes_pad($val) {
+       $block_size = 16;
+       $numpad = $block_size - (strlen ($val) % $block_size);
+       return str_pad($val, strlen ($val) + $numpad, chr($numpad));
+}
+
+/* Mailhide related code */
+
+function _recaptcha_aes_encrypt($val,$ky) {
+       if (! function_exists ("mcrypt_encrypt")) {
+               die ("To use reCAPTCHA Mailhide, you need to have the mcrypt php module installed.");
+       }
+       $mode=MCRYPT_MODE_CBC;   
+       $enc=MCRYPT_RIJNDAEL_128;
+       $val=_recaptcha_aes_pad($val);
+       return mcrypt_encrypt($enc, $ky, $val, $mode, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0");
+}
+
+
+function _recaptcha_mailhide_urlbase64 ($x) {
+       return strtr(base64_encode ($x), '+/', '-_');
+}
+
+/* gets the reCAPTCHA Mailhide url for a given email, public key and private key */
+function recaptcha_mailhide_url($pubkey, $privkey, $email) {
+       if ($pubkey == '' || $pubkey == null || $privkey == "" || $privkey == null) {
+               die ("To use reCAPTCHA Mailhide, you have to sign up for a public and private key, " .
+                    "you can do so at <a href='http://mailhide.recaptcha.net/apikey'>http://mailhide.recaptcha.net/apikey</a>");
+       }
+       
+
+       $ky = pack('H*', $privkey);
+       $cryptmail = _recaptcha_aes_encrypt ($email, $ky);
+       
+       return "http://mailhide.recaptcha.net/d?k=" . $pubkey . "&c=" . _recaptcha_mailhide_urlbase64 ($cryptmail);
+}
+
+/**
+ * gets the parts of the email to expose to the user.
+ * eg, given johndoe@example,com return ["john", "example.com"].
+ * the email is then displayed as john...@example.com
+ */
+function _recaptcha_mailhide_email_parts ($email) {
+       $arr = preg_split("/@/", $email );
+
+       if (strlen ($arr[0]) <= 4) {
+               $arr[0] = substr ($arr[0], 0, 1);
+       } else if (strlen ($arr[0]) <= 6) {
+               $arr[0] = substr ($arr[0], 0, 3);
+       } else {
+               $arr[0] = substr ($arr[0], 0, 4);
+       }
+       return $arr;
+}
+
+/**
+ * Gets html to display an email address given a public an private key.
+ * to get a key, go to:
+ *
+ * http://mailhide.recaptcha.net/apikey
+ */
+function recaptcha_mailhide_html($pubkey, $privkey, $email) {
+       $emailparts = _recaptcha_mailhide_email_parts ($email);
+       $url = recaptcha_mailhide_url ($pubkey, $privkey, $email);
+       
+       return htmlentities($emailparts[0]) . "<a href='" . htmlentities ($url) .
+               "' onclick=\"window.open('" . htmlentities ($url) . "', '', 'toolbar=0,scrollbars=0,location=0,statusbar=0,menubar=0,resizable=0,width=500,height=300'); return false;\" title=\"Reveal this e-mail address\">...</a>@" . htmlentities ($emailparts [1]);
+
+}
+
+
+?>
index b5b780ed7bb2f6451a6fa0dfbe524b7ce1620ab4..1cac1cb109227c7464e7b504da69a98fa6e849ab 100644 (file)
@@ -1,7 +1,18 @@
 <?php  // $Id$
 
     require_once('../config.php');
+    
+    /**
+     * Returns whether or not the captcha element is enabled, and the admin settings fulfil its requirements.
+     * @return bool
+     */
+    function signup_captcha_enabled() {
+        global $CFG;
+        return isset($CFG->recaptchapublickey) && isset($CFG->recaptchaprivatekey) && get_config('auth/email', 'recaptcha');
+    }
+    
     require_once('signup_form.php');
+    
 
     if (empty($CFG->registerauth)) {
         error("Sorry, you may not use this page.");
@@ -48,7 +59,7 @@
     $navlinks[] = array('name' => $newaccount, 'link' => null, 'type' => 'misc');
     $navigation = build_navigation($navlinks);
     print_header($newaccount, $newaccount, $navigation, $mform_signup->focus(), "", true, "<div class=\"langmenu\">$langmenu</div>");
-
+    
     $mform_signup->display();
     print_footer();
 
index fc6e9ea87e12b2be4f0725a7342b4ab3a0e00cad..5a5e3ac3e3a1f3be6e45a9fcd201ecd06ea9bf05 100644 (file)
@@ -62,6 +62,10 @@ class login_signup_form extends moodleform {
         }else{
             $mform->setDefault('country', '');
         }
+        
+        if (signup_captcha_enabled()) {
+            $mform->addElement('recaptcha', 'recaptcha_element', get_string('visualconfirmation'));
+        }
 
         profile_signup_fields($mform);
 
@@ -131,6 +135,18 @@ class login_signup_form extends moodleform {
         if (!check_password_policy($data['password'], $errmsg)) {
             $errors['password'] = $errmsg;
         }
+        
+        if (signup_captcha_enabled()) {
+            require_once $CFG->libdir . '/recaptchalib.php';
+            $response = recaptcha_check_answer($CFG->recaptchaprivatekey,
+                                               $_SERVER['REMOTE_ADDR'],
+                                               $this->_form->_submitValues['recaptcha_challenge_field'],
+                                               $this->_form->_submitValues['recaptcha_response_field']);
+            if (!$response->is_valid) {
+                $_SESSION['recaptcha_error'] = $response->error;
+                $errors['recaptcha'] = $response->error;
+            }
+        }
 
         return $errors;