Index: mollom.admin.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/mollom/mollom.admin.inc,v
retrieving revision 1.8
diff -u -p -r1.8 mollom.admin.inc
--- mollom.admin.inc	29 Jan 2010 20:26:54 -0000	1.8
+++ mollom.admin.inc	29 Jan 2010 21:16:04 -0000
@@ -288,6 +288,10 @@ function mollom_admin_settings($form, &$
   $form['server'] = array(
     '#type' => 'fieldset',
     '#title' => t('Fallback strategy'),
+    '#description' => t('When the Mollom servers are down or otherwise unreachable, no text analysis is performed and no CAPTCHAs are generated. If this occurs, your site will use the configured fallback strategy. Subscribers to <a href="@pricing-url">Mollom Plus</a> receive access to <a href="@sla-url">Mollom\'s high-availability backend infrastructure</a>, not available to free users, reducing potential downtime.', array(
+      '@pricing-url' => 'http://mollom.com/pricing',
+      '@sla-url' => 'http://mollom.com/standard-service-level-agreement',
+    )),
   );
   $form['server']['mollom_fallback'] = array(
     '#type' => 'radios',
@@ -297,20 +301,15 @@ function mollom_admin_settings($form, &$
       MOLLOM_FALLBACK_BLOCK => t('Block all submissions of protected forms until the server problems are resolved'),
       MOLLOM_FALLBACK_ACCEPT => t('Leave all forms unprotected and accept all submissions'),
     ),
-    '#description' => t('When the Mollom servers are down or otherwise unreachable, no text analysis is performed and no CAPTCHAs are generated. If this occurs, your Drupal site will use the configured fallback strategy, and will either accept all submissions without spam checking, or block all submissions until the server or connection problems are resolved. Subscribers to <a href="@pricing">Mollom Plus</a> receive access to <a href="@sla">Mollom\'s high-availability backend infrastructure</a>, not available to free users, reducing potential downtime.', array(
-      '@pricing' => 'http://mollom.com/pricing',
-      '@sla' => 'http://mollom.com/standard-service-level-agreement',
-    )),
   );
 
   $form['access-keys'] = array(
     '#type' => 'fieldset',
     '#title' => t('Mollom access keys'),
-    '#description' => t('To use Mollom, you need a public and private key. To obtain your keys, <a href="@mollom-login">register and login on mollom.com</a>, and <a href="@mollom-manager-add">create a subscription</a> for your site. Once you created a subscription, copy your private and public access keys from the <a href="@mollom-manager">site manager</a> into the form fields below, and you are ready to go.', array(
-      '@mollom-register' => 'http://mollom.com/user/register',
-      '@mollom-login' => 'http://mollom.com/user',
-      '@mollom-manager-add' => 'http://mollom.com/site-manager/add',
-      '@mollom-manager' => 'http://mollom.com/site-manager',
+    '#description' => t('To use Mollom, you need a public and private key. To obtain your keys, <a href="@mollom-login-url">register and login on mollom.com</a>, and <a href="@mollom-manager-add-url">create a subscription</a> for your site. Once you created a subscription, copy your private and public access keys from the <a href="@mollom-manager-url">site manager</a> into the form fields below, and you are ready to go.', array(
+      '@mollom-login-url' => 'http://mollom.com/user',
+      '@mollom-manager-add-url' => 'http://mollom.com/site-manager/add',
+      '@mollom-manager-url' => 'http://mollom.com/site-manager',
     )),
   );
   $form['access-keys']['mollom_public_key'] = array(
@@ -326,6 +325,18 @@ function mollom_admin_settings($form, &$
     '#description' => t('The private key is used to prevent someone from hijacking your requests. Similar to a password, it should never be shared with anyone.'),
   );
 
+  $form['mollom_privacy_link'] = array(
+    '#type' => 'checkbox',
+    '#title' => t("Link to Mollom's privacy policy on forms protected by textual analysis"),
+    '#return_value' => 1,
+    '#default_value' => variable_get('mollom_privacy_link', 1),
+    '#description' => t('Displays a link to the recommended <a href="@privacy-policy-url">privacy policy on mollom.com</a> on all forms that are protected via <a href="@help-url">textual analysis</a>. When disabling this option, you are required to inform visitors about data privacy through other means, as stated in the <a href="@terms-of-service-url">terms of service</a> applying to your subscription.', array(
+      '@privacy-policy-url' => 'http://mollom.com/web-service-privacy-policy',
+      '@help-url' => url('admin/help/mollom'),
+      '@terms-of-service-url' => 'http://mollom.com/terms-of-service',
+    )),
+  );
+
   return system_settings_form($form);
 }
 
Index: mollom.js
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/mollom/mollom.js,v
retrieving revision 1.4
diff -u -p -r1.4 mollom.js
--- mollom.js	21 Dec 2009 20:24:22 -0000	1.4
+++ mollom.js	29 Jan 2010 21:13:35 -0000
@@ -3,6 +3,19 @@
 (function ($) {
 
 /**
+ * Open Mollom privacy policy link in a new window.
+ *
+ * Required for valid XHTML Strict markup.
+ */
+Drupal.behaviors.mollomPrivacy = {
+  attach: function (context) {
+    $('.mollom-privacy a', context).click(function () {
+      this.target = '_blank';
+    });
+  }
+};
+
+/**
  * Attach click event handlers for CAPTCHA links.
  */
 Drupal.behaviors.mollom = {
Index: mollom.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/mollom/mollom.module,v
retrieving revision 1.16
diff -u -p -r1.16 mollom.module
--- mollom.module	29 Jan 2010 20:26:54 -0000	1.16
+++ mollom.module	29 Jan 2010 21:09:32 -0000
@@ -411,6 +411,19 @@ function mollom_form_alter(&$form, &$for
 
       // Add a submit handler to remove form state storage.
       $form['#submit'][] = 'mollom_form_submit';
+
+      // Add link to privacy policy on forms protected via textual analysis,
+      // if enabled.
+      if ($mollom_form['mode'] == MOLLOM_MODE_ANALYSIS && variable_get('mollom_privacy_link', 1)) {
+        $form['mollom']['privacy'] = array(
+          '#prefix' => '<div class="description mollom-privacy">',
+          '#suffix' => '</div>',
+          '#markup' => t('By submitting this form, you accept the <a href="@privacy-policy-url">Mollom privacy policy</a>.', array(
+            '@privacy-policy-url' => 'http://mollom.com/web-service-privacy-policy',
+          )),
+          '#weight' => 10,
+        );
+      }
     }
   }
 }
Index: tests/mollom.test
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/mollom/tests/mollom.test,v
retrieving revision 1.10
diff -u -p -r1.10 mollom.test
--- tests/mollom.test	29 Jan 2010 20:26:54 -0000	1.10
+++ tests/mollom.test	29 Jan 2010 21:11:05 -0000
@@ -354,20 +354,36 @@ class MollomWebTestCase extends DrupalWe
   }
 
   /**
-   * Test that the CAPTCHA field is found on the current page.
+   * Assert that the CAPTCHA field is found on the current page.
    */
   protected function assertCaptchaField() {
     $this->assertFieldByXPath('//input[@type="text"][@name="mollom[captcha]"]', '', 'CAPTCHA field found.');
   }
 
   /**
-   * Test that the CAPTCHA field is not found on the current page.
+   * Assert that the CAPTCHA field is not found on the current page.
    */
   protected function assertNoCaptchaField() {
     $this->assertNoFieldByXPath('//input[@type="text"][@name="mollom[captcha]"]', '', 'CAPTCHA field not found.');
   }
 
   /**
+   * Assert that the privacy policy link is found on the current page.
+   */
+  protected function assertPrivacyLink() {
+    $elements = $this->xpath('//div[contains(@class, "mollom-privacy")]');
+    $this->assertTrue($elements, t('Privacy policy container found.'));
+  }
+
+  /**
+   * Assert that the privacy policy link is not found on the current page.
+   */
+  protected function assertNoPrivacyLink() {
+    $elements = $this->xpath('//div[contains(@class, "mollom-privacy")]');
+    $this->assertFalse($elements, t('Privacy policy container not found.'));
+  }
+
+  /**
    * Test submitting a form with a correct CAPTCHA value.
    *
    * @param $url
@@ -1425,10 +1441,12 @@ class MollomCommentFormTestCase extends 
     $this->drupalLogin($this->web_user);
     $this->drupalGet('comment/reply/'. $this->node->nid);
     $this->assertNoCaptchaField();
+    $this->assertNoPrivacyLink();
 
     // Preview a comment that is 'spam' and make sure there is still no CAPTCHA.
     $this->drupalPost(NULL, array('comment_body[und][0][value]' => 'spam'), t('Preview'));
     $this->assertNoCaptchaField();
+    $this->assertNoPrivacyLink();
 
     // Save the comment and make sure it appears.
     $this->drupalPost(NULL, array(), t('Save'));
@@ -1449,18 +1467,21 @@ class MollomCommentFormTestCase extends 
     $this->drupalGet('comment/reply/' . $this->node->nid);
     $this->assertCaptchaField();
     $this->assertSessionIDInForm();
+    $this->assertNoPrivacyLink();
 
     // Try to submit an incorrect answer for the CAPTCHA, without value for
     // required field.
     $this->postIncorrectCaptcha(NULL, array(), t('Preview'));
     $this->assertText(t('Comment field is required.'));
     $this->assertSessionIDInForm();
+    $this->assertNoPrivacyLink();
 
     // Try to submit a correct answer for the CAPTCHA, still without required
     // field value.
     $this->postCorrectCaptcha(NULL, array(), t('Preview'));
     $this->assertText(t('Comment field is required.'));
     $session_id = $this->assertSessionIDInForm();
+    $this->assertNoPrivacyLink();
 
     // Finally, we should be able to submit a comment.
     $this->drupalPost(NULL, array('comment_body[und][0][value]' => 'spam'), t('Save'));
@@ -1483,17 +1504,20 @@ class MollomCommentFormTestCase extends 
     $this->drupalLogin($this->web_user);
     $this->drupalGet('comment/reply/'. $this->node->nid);
     $this->assertNoCaptchaField();
+    $this->assertPrivacyLink();
 
     // Try to save a comment that is 'unsure' and make sure there is a CAPTCHA.
     $this->drupalPost(NULL, array('comment_body[und][0][value]' => 'unsure'), t('Save'));
     $this->assertCaptchaField();
     $session_id = $this->assertSessionIDInForm();
+    $this->assertPrivacyLink();
 
     // Try to submit the form by using an invalid CAPTCHA. At this point,
     // the submission should be rejected and a new CAPTCHA generated (even
     // if the text of the comment is changed to ham).
     $this->postIncorrectCaptcha(NULL, array('comment_body[und][0][value]' => 'ham'), t('Save'));
     $session_id = $this->assertSessionIDInForm();
+    $this->assertPrivacyLink();
 
     // Now try using a valid CAPTCHA. The CAPTCHA form should no longer
     // be present.
@@ -1506,19 +1530,23 @@ class MollomCommentFormTestCase extends 
     // appearing on the page.
     $this->resetSessionID();
     $this->drupalGet('comment/reply/' . $this->node->nid);
+    $this->assertPrivacyLink();
     $original_number_of_comments = $this->getCommentCount($this->node->nid);
     $this->assertSpamSubmit(NULL, array('comment_body[und][0][value]'), array(), t('Save'));
     $session_id = $this->assertSessionIDInForm();
     $this->assertCommentCount($this->node->nid, $original_number_of_comments);
+    $this->assertPrivacyLink();
 
     // Try to save again; it should be rejected, with no CAPTCHA.
     $this->assertSpamSubmit(NULL, array('comment_body[und][0][value]'), array(), t('Save'));
     $session_id = $this->assertSessionIDInForm();
     $this->assertCommentCount($this->node->nid, $original_number_of_comments);
+    $this->assertPrivacyLink();
 
     // Save a new 'ham' comment.
     $this->resetSessionID();
     $this->drupalGet('comment/reply/' . $this->node->nid);
+    $this->assertPrivacyLink();
     $original_number_of_comments = $this->getCommentCount($this->node->nid);
     $this->assertHamSubmit(NULL, array('comment_body[und][0][value]'), array(), t('Save'));
     $this->assertRaw('<p>ham</p>', t('A comment that is known to be ham appears on the screen after it is submitted.'));
