Index: mollom.admin.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/mollom/mollom.admin.inc,v
retrieving revision 1.1.2.43
diff -u -p -r1.1.2.43 mollom.admin.inc
--- mollom.admin.inc	6 Oct 2010 23:55:31 -0000	1.1.2.43
+++ mollom.admin.inc	15 Oct 2010 15:21:17 -0000
@@ -669,7 +669,7 @@ function mollom_comment_admin_overview_s
       if ($value) {
         // First, report the comments as spam to Mollom.com.
         if ($data = mollom_data_load('comment', $cid)) {
-          _mollom_send_feedback($data->session);
+          _mollom_send_feedback($data->session_id);
         }
 
         // Second, perform the proper operation on the comments:
@@ -708,7 +708,7 @@ function mollom_node_admin_overview_subm
       if ($value) {
         // First, report the nodes as spam to Mollom.com.
         if ($data = mollom_data_load('node', $nid)) {
-           _mollom_send_feedback($data->session);
+           _mollom_send_feedback($data->session_id);
         }
 
         if ($node = node_load($nid)) {
Index: mollom.install
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/mollom/mollom.install,v
retrieving revision 1.2.2.33
diff -u -p -r1.2.2.33 mollom.install
--- mollom.install	12 Sep 2010 23:44:14 -0000	1.2.2.33
+++ mollom.install	15 Oct 2010 13:50:29 -0000
@@ -86,15 +86,22 @@ function mollom_schema() {
         'not null' => TRUE,
         'default' => '',
       ),
-      'did' => array(
+      'id' => array(
         'description' => 'Unique entity ID of the content.',
         'type' => 'varchar',
         'length' => 32,
         'not null' => TRUE,
         'default' => '',
       ),
-      'session' => array(
-        'description' => "Content author's session ID.",
+      'session_id' => array(
+        'description' => 'Session hash returned by Mollom.',
+        'type' => 'varchar',
+        'length' => 255,
+        'not null' => TRUE,
+        'default' => '',
+      ),
+      'form_id' => array(
+        'description' => 'The form_id of the form being protected.',
         'type' => 'varchar',
         'length' => 255,
         'not null' => TRUE,
@@ -130,8 +137,16 @@ function mollom_schema() {
         'default' => '',
       ),
     ),
-    'indexes' => array('session' => array('session')),
-    'primary key' => array('entity', 'did'),
+    'indexes' => array('session_id' => array('session_id')),
+    'primary key' => array('entity', 'id'),
+    'foreign keys' => array(
+      'mollom_form_id' => array(
+        'table' => 'mollom_form',
+        'columns' => array(
+          'form_id' => 'form_id',
+        ),
+      ),
+    ),
   );
 
   $schema['mollom_form'] = array(
@@ -209,7 +224,12 @@ function mollom_uninstall() {
  */
 function mollom_update_1() {
   $ret = array();
-  db_add_field($ret, 'mollom', 'languages', array('type' => 'varchar', 'length' => 255, 'not null' => TRUE, 'default' => ''));
+  db_add_field($ret, 'mollom', 'languages', array(
+    'type' => 'varchar',
+    'length' => 255,
+    'not null' => TRUE,
+    'default' => '',
+  ));
   return $ret;
 }
 
@@ -238,7 +258,7 @@ function mollom_update_3() {
     $mode = variable_get($name, NULL);
     // $mode was stored as 1; convert to MOLLOM_MODE_ANALYSIS.
     if (isset($mode)) {
-      variable_set($name, MOLLOM_MODE_ANALYSIS);
+      variable_set($name, 2);
     }
   }
 }
@@ -260,22 +280,26 @@ function mollom_update_6105() {
   $schema = array(
     'fields' => array(
       'form_id' => array(
+        'description' => 'The protected form ID.',
         'type' => 'varchar',
         'length' => 255,
         'not null' => TRUE,
         'default' => '',
       ),
       'mode' => array(
+        'description' => 'Protection mode for the form.',
         'type' => 'int',
         'size' => 'tiny',
         'not null' => TRUE,
         'default' => 0,
       ),
       'enabled_fields' => array(
+        'description' => 'Form elements to analyze.',
         'type' => 'text',
         'serialize' => TRUE,
       ),
       'module' => array(
+        'description' => 'Module name owning the form.',
         'type' => 'varchar',
         'length' => 255,
         'not null' => TRUE,
@@ -310,14 +334,12 @@ function mollom_update_6105() {
 
 /**
  * Add the {mollom}.form_id column.
- *
- * @todo Rename 'did' column after mollom_set_data() and mollom_get_data() have
- *   been removed.
  */
 function mollom_update_6106() {
   $ret = array();
   // Add the 'entity' column.
   db_add_field($ret, 'mollom', 'entity', array(
+    'description' => 'Entity type of the content.',
     'type' => 'varchar',
     'length' => 32,
     'not null' => TRUE,
@@ -340,6 +362,7 @@ function mollom_update_6106() {
   // @todo We do not change the type to 'int' here to still support named
   //   identifiers. Reconsider this.
   db_change_field($ret, 'mollom', 'did', 'did', array(
+    'description' => 'Unique entity ID of the content.',
     'type' => 'varchar',
     'length' => 32,
     'not null' => TRUE,
@@ -377,6 +400,7 @@ function mollom_update_6109() {
   $ret = array();
   if (db_column_exists('mollom_form', 'fields')) {
     db_change_field($ret, 'mollom_form', 'fields', 'enabled_fields', array(
+      'description' => 'Form elements to analyze.',
       'type' => 'text',
       'serialize' => TRUE,
     ));
@@ -420,6 +444,7 @@ function mollom_update_6112() {
   $ret = array();
   if (!db_column_exists('mollom', 'changed')) {
     db_add_field($ret, 'mollom', 'changed', array(
+      'description' => 'Unix timestamp when the data was changed.',
       'type' => 'int',
       'not null' => TRUE,
       'default' => 0,
@@ -437,6 +462,7 @@ function mollom_update_6113() {
   // Add {mollom_form}.checks.
   if (!db_column_exists('mollom_form', 'checks')) {
     db_add_field($ret, 'mollom_form', 'checks', array(
+      'description' => 'Text analyis checks to perform.',
       'type' => 'text',
       'not null' => FALSE,
       'serialize' => TRUE,
@@ -465,6 +491,7 @@ function mollom_update_6114() {
 
   // Change {mollom}.quality from varchar into float.
   db_change_field($ret, 'mollom', 'quality', 'quality', array(
+    'description' => 'Text analysis quality check result.',
     'type' => 'float',
     'size' => 'tiny',
     'not null' => FALSE,
@@ -473,6 +500,7 @@ function mollom_update_6114() {
   // Add {mollom}.spam.
   if (!db_column_exists('mollom', 'spam')) {
     db_add_field($ret, 'mollom', 'spam', array(
+      'description' => 'Text analysis spam check result.',
       'type' => 'int',
       'size' => 'tiny',
       'not null' => FALSE,
@@ -492,3 +520,77 @@ function mollom_update_6114() {
 
   return $ret;
 }
+
+/**
+ * Add {mollom}.form_id column to look up the originating form_id for an entity.
+ */
+function mollom_update_6115() {
+  $ret = array();
+  if (!db_column_exists('mollom', 'form_id')) {
+    db_add_field($ret, 'mollom', 'form_id', array(
+      'description' => 'The form_id of the form being protected.',
+      'type' => 'varchar',
+      'length' => 255,
+      'not null' => TRUE,
+      'default' => '',
+    ));
+    // Update simple cases first.
+    $ret[] = update_sql("UPDATE {mollom} SET form_id = 'user_register' WHERE entity = 'user'");
+    $ret[] = update_sql("UPDATE {mollom} SET form_id = 'contact_mail_page' WHERE entity = 'session'");
+    // Also perform simple update on behalf of Webform, as that is a very common
+    // use-case.
+    $ret[] = update_sql("UPDATE {mollom} SET form_id = CONCAT('webform_client_form_', did) WHERE entity = 'webform'");
+
+    // Update node entity data records.
+    $result = db_query("SELECT n.type, m.did
+      FROM {mollom} m
+      INNER JOIN {node} n ON n.nid = m.did
+      WHERE m.entity = 'node'");
+    $ids = array();
+    while ($row = db_fetch_object($result)) {
+      $ids[$row->type][] = $row->did;
+    }
+    foreach ($ids as $type => $nids) {
+      $in = implode(',', $nids);
+      $ret[] = update_sql("UPDATE {mollom} SET form_id = '{$type}_node_form' WHERE entity = 'node' AND did IN ($in)");
+    }
+
+    // Update comment entity data records.
+    // In Drupal 6, there is only one 'comment_form'. The corresponding update
+    // to Drupal 7 takes into account that {mollom}.form_id can already exist,
+    // and if it does, only comment form IDs are updated accordingly.
+    $ret[] = update_sql("UPDATE {mollom} SET form_id = 'comment_form' WHERE entity = 'comment'");
+  }
+  return $ret;
+}
+
+/**
+ * Rename {mollom}.did to .id, and {mollom}.session to .session_id.
+ */
+function mollom_update_6116() {
+  $ret = array();
+  db_drop_primary_key($ret, 'mollom');
+  if (!db_column_exists('mollom', 'id')) {
+    db_change_field($ret, 'mollom', 'did', 'id', array(
+      'description' => 'Unique entity ID of the content.',
+      'type' => 'varchar',
+      'length' => 32,
+      'not null' => TRUE,
+      'default' => '',
+    ));
+  }
+  db_add_primary_key($ret, 'mollom', array('entity', 'id'));
+
+  db_drop_index($ret, 'mollom', 'session');
+  if (!db_column_exists('mollom', 'session_id')) {
+    db_change_field($ret, 'mollom', 'session', 'session_id', array(
+      'description' => 'Session hash returned by Mollom.',
+      'type' => 'varchar',
+      'length' => 255,
+      'not null' => TRUE,
+      'default' => '',
+    ));
+  }
+  db_add_index($ret, 'mollom', 'session_id', array('session_id'));
+  return $ret;
+}
Index: mollom.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/mollom/mollom.module,v
retrieving revision 1.2.2.173
diff -u -p -r1.2.2.173 mollom.module
--- mollom.module	6 Oct 2010 23:55:31 -0000	1.2.2.173
+++ mollom.module	15 Oct 2010 15:16:39 -0000
@@ -354,6 +354,8 @@ function _mollom_access($permission = FA
  *   The entity type of the data to report.
  * @param $id
  *   The entity id of the data to report.
+ *
+ * @todo Revamp this based on new {mollom}.form_id info.
  */
 function mollom_report_access($entity, $id) {
   // The special entity 'session' means that $id is a Mollom session_id, which
@@ -423,58 +425,47 @@ function mollom_cron() {
  *   The entity id to retrieve data for.
  */
 function mollom_data_load($entity, $id) {
-  return db_fetch_object(db_query_range("SELECT * FROM {mollom} WHERE entity = '%s' AND did = '%s'", array($entity, $id), 0, 1));
+  return db_fetch_object(db_query_range("SELECT * FROM {mollom} WHERE entity = '%s' AND id = '%s'", array($entity, $id), 0, 1));
 }
 
 /**
  * Save Mollom validation data to the database.
  *
  * Based on the specified entity type and id, this function stores the
- * validation results returned by Mollom in the database. The stored data
- * is an associative array containing Mollom session information for the posted
- * content:
- * - session: The session ID returned by the Mollom server.
- * - quality: A quality rating assigned to the content to tell whether or not
- *   it's spam.
- * - languages: An array containing language codes the content might be
- *   written in.
+ * validation results returned by Mollom in the database.
  *
  * The special $entity type "session" may be used for mails and messages, which
  * originate from form submissions protected by Mollom, and can be reported by
  * anyone; $id is expected to be a Mollom session id instead of an entity id
  * then.
  *
- * @param $entity
- *   The entity type of the data to save.
- * @param $id
- *   The entity id the data belongs to.
- *
- * @todo Remove usage of global $mollom variable.
- */
-function mollom_data_save($entity, $id) {
-  // Nothing to do, if we do not have a valid Mollom response.
-  if (empty($GLOBALS['mollom']['response']['session_id'])) {
-    return FALSE;
-  }
-  $data = $GLOBALS['mollom']['response'];
-  $data['session'] = $data['session_id'];
-  $data['entity'] = $entity;
-  $data['did'] = $id;
-  $data['changed'] = time();
-
-  // Convert languages into a string.
-  if (!empty($data['languages'])) {
-    $data['languages'] = implode(' ', $data['languages']);
+ * @param $data
+ *   An object containing Mollom session data for the entity, containing at
+ *   least the following properties:
+ *   - entity: The entity type of the data to save.
+ *   - id: The entity ID the data belongs to.
+ *   - form_id: The form ID the session data belongs to.
+ *   - session_id: The session ID returned by Mollom.
+ *   And optionally:
+ *   - spam: A spam check result integer returned by Mollom, which can be
+ *     MOLLOM_ANALYSIS_SPAM, MOLLOM_ANALYSIS_UNSURE, or MOLLOM_ANALYSIS_HAM.
+ *   - quality: A rating of the content's quality, in the range of 0 and 1.0.
+ *   - profanity: A profanity check rating returned by Mollom, in the range of
+ *     0 and 1.0.
+ *   - languages: An array containing language codes the content might be
+ *     written in.
+ */
+function mollom_data_save($data) {
+  $data->changed = time();
+  // Convert languages array into a string.
+  // @todo This conversion and data handling is not correct; needs work.
+  if (isset($data->languages) && is_array($data->languages)) {
+    $data->languages = implode(' ', $data->languages);
   }
-  // Merge in default values that may not exist in the response.
-  $data += array(
-    'languages' => '',
-    'quality' => '',
-    'reputation' => '',
-  );
 
-  $update = db_result(db_query_range("SELECT 'did' FROM {mollom} WHERE entity = '%s' AND did = '%s'", $entity, $id, 0, 1));
+  $update = db_result(db_query_range("SELECT 'id' FROM {mollom} WHERE entity = '%s' AND id = '%s'", $data->entity, $data->id, 0, 1));
   drupal_write_record('mollom', $data, $update ? $update : array());
+
   return $data;
 }
 
@@ -500,7 +491,7 @@ function mollom_data_delete($entity, $id
  */
 function mollom_data_delete_multiple($entity, $ids) {
   $placeholders = db_placeholders($ids, 'varchar');
-  return db_query("DELETE FROM {mollom} WHERE entity = '%s' AND did IN ($placeholders)", array_merge(array($entity), $ids));
+  return db_query("DELETE FROM {mollom} WHERE entity = '%s' AND id IN ($placeholders)", array_merge(array($entity), $ids));
 }
 
 /**
@@ -581,8 +572,8 @@ function mollom_data_report_multiple($en
     // Load the Mollom session data.
     $data = mollom_data_load($entity, $id);
     // Send feedback, if we have session data.
-    if (isset($data->session)) {
-      $result = _mollom_send_feedback($data->session, $feedback);
+    if (isset($data->session_id)) {
+      $result = _mollom_send_feedback($data->session_id, $feedback);
       $return = $return && $result;
     }
   }
@@ -1692,10 +1683,18 @@ function mollom_form_submit($form, &$for
     // new entity id value into $form_state['values'], so we need to rebuild the
     // data mapping. We do not care for the actual fields, only for the value of
     // the mapped post_id.
-    $data = mollom_form_get_values($form_state['values'], array(), $form_state['mollom']['mapping']);
+    // Note that most entity forms in Drupal 6 do not insert the entity ID for
+    // new entities into the $form. Therefore, this code does not run for them,
+    // but instead requires dedicated hook_nodeapi() and hook_comment()
+    // implementations.
+    $values = mollom_form_get_values($form_state['values'], array(), $form_state['mollom']['mapping']);
     // We only consider non-empty and non-zero values as valid entity ids.
-    if (!empty($data['post_id'])) {
-      mollom_data_save($form_state['mollom']['entity'], $data['post_id']);
+    if (!empty($values['post_id'])) {
+      $data = (object) $form_state['mollom']['response'];
+      $data->entity = $form_state['mollom']['entity'];
+      $data->id = $values['post_id'];
+      $data->form_id = $form_state['mollom']['form_id'];
+      mollom_data_save($data);
     }
   }
   // Flush Mollom session information from database cache.
@@ -2128,7 +2127,7 @@ function mollom_get_captcha($type, $data
  * form submissions.
  */
 function mollom_mail_alter(&$message) {
-  // Attached the Mollom report link to any mails with IDs specified from the
+  // Attaches the Mollom report link to any mails with IDs specified from the
   // submitted form's hook_mollom_form_info(). This should ensure that the
   // report link is added to mails sent by actual users and not any mails sent
   // by Drupal since they should never be reported as spam.
@@ -2142,9 +2141,14 @@ function mollom_mail_alter(&$message) {
  */
 function mollom_mail_add_report_link(&$message) {
   if (!empty($GLOBALS['mollom']['response']['session_id'])) {
-    mollom_data_save('session', $GLOBALS['mollom']['response']['session_id']);
+    $mollom = $GLOBALS['mollom'];
+    $data = (object) $mollom['response'];
+    $data->entity = 'session';
+    $data->id = $mollom['response']['session_id'];
+    $data->form_id = $mollom['form_id'];
+    mollom_data_save($data);
     $report_link = t('Report as inappropriate: @link', array(
-      '@link' => url('mollom/report/session/' . $GLOBALS['mollom']['response']['session_id'], array('absolute' => TRUE)),
+      '@link' => url("mollom/report/{$data->entity}/{$data->id}", array('absolute' => TRUE)),
     ));
     // Until D7, hook_mail_alter() accepts both arrays and strings.
     if (is_array($message['body'])) {
@@ -2222,8 +2226,13 @@ function node_mollom_form_info($form_id)
  * Implements hook_nodeapi().
  */
 function mollom_nodeapi($node, $op) {
-  if ($op == 'insert') {
-    mollom_data_save('node', $node->nid);
+  if (in_array($op, array('insert', 'update')) && !empty($GLOBALS['mollom'])) {
+    $mollom = $GLOBALS['mollom'];
+    $data = (object) $mollom['response'];
+    $data->entity = 'node';
+    $data->id = $node->nid;
+    $data->form_id = $mollom['form_id'];
+    mollom_data_save($data);
   }
   elseif ($op == 'delete') {
     mollom_data_delete('node', $node->nid);
@@ -2357,8 +2366,13 @@ function mollom_comment_form_validate($f
  * Implements hook_comment().
  */
 function mollom_comment($comment, $op) {
-  if ($op == 'insert') {
-    mollom_data_save('comment', $comment['cid']);
+  if (in_array($op, array('insert', 'update')) && !empty($GLOBALS['mollom'])) {
+    $mollom = $GLOBALS['mollom'];
+    $data = (object) $mollom['response'];
+    $data->entity = 'comment';
+    $data->id = (isset($comment['cid']) ? $comment['cid'] : $comment->cid);
+    $data->form_id = $mollom['form_id'];
+    mollom_data_save($data);
   }
   elseif ($op == 'delete') {
     mollom_data_delete('comment', $comment->cid);
Index: mollom.pages.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/mollom/mollom.pages.inc,v
retrieving revision 1.1.2.16
diff -u -p -r1.1.2.16 mollom.pages.inc
--- mollom.pages.inc	7 Aug 2010 02:49:44 -0000	1.1.2.16
+++ mollom.pages.inc	15 Oct 2010 13:25:16 -0000
@@ -110,16 +110,16 @@ function mollom_report_form_submit($form
     // Load the Mollom session data.
     if ($entity == 'session') {
       $data = new stdClass;
-      $data->session = $id;
+      $data->session_id = $id;
     }
     else {
       $data = mollom_data_load($entity, $id);
     }
 
     // Send feedback to Mollom, if we have session data.
-    if (isset($data->session) && isset($form_state['values']['feedback']) && $form_state['values']['feedback'] != 'none') {
+    if (isset($data->session_id) && isset($form_state['values']['feedback']) && $form_state['values']['feedback'] != 'none') {
       // @todo Check the actual reponse.
-      _mollom_send_feedback($data->session, $form_state['values']['feedback']);
+      _mollom_send_feedback($data->session_id, $form_state['values']['feedback']);
       drupal_set_message(t('The content was successfully reported as inappropriate.'));
     }
 
Index: tests/mollom.test
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/mollom/tests/mollom.test,v
retrieving revision 1.1.2.64
diff -u -p -r1.1.2.64 mollom.test
--- tests/mollom.test	6 Oct 2010 23:55:31 -0000	1.1.2.64
+++ tests/mollom.test	15 Oct 2010 15:15:16 -0000
@@ -353,9 +353,9 @@ class MollomWebTestCase extends DrupalWe
    */
   protected function assertMollomData($entity, $id, $session_id = NULL) {
     $data = mollom_data_load($entity, $id);
-    $this->assertTrue($data->session, t('Mollom session data for %entity @id exists: <pre>@data</pre>', array('%entity' => $entity, '@id' => $id, '@data' => var_export($data, TRUE))));
+    $this->assertTrue($data->session_id, t('Mollom session data for %entity @id exists: <pre>@data</pre>', array('%entity' => $entity, '@id' => $id, '@data' => var_export($data, TRUE))));
     if (isset($session_id)) {
-      $this->assertSame(t('Stored session id'), $data->session, $session_id);
+      $this->assertSame(t('Stored session id'), $data->session_id, $session_id);
     }
     return $data;
   }
@@ -2406,6 +2406,13 @@ class MollomDataTestCase extends MollomW
     $new_mid = $this->getFieldValueByName('mid');
     $this->assertEqual($new_mid, $mid, t('Existing entity id found.'));
 
+    // Verify that session data was stored.
+    $this->assertSame('entity', $data->entity, 'mollom_test');
+    $this->assertSame('id', $data->id, $mid);
+    $this->assertSame('form_id', $data->form_id, 'mollom_test_form');
+    $count = db_result(db_query("SELECT COUNT(1) FROM {mollom}"));
+    $this->assertEqual($count, 1, t('Data was stored in {mollom}.'));
+
     // Update the stored entry.
     $edit['title'] = 'unsure';
     $this->drupalPost(NULL, $edit, 'Submit');
@@ -2415,8 +2422,9 @@ class MollomDataTestCase extends MollomW
 
     // Verify that only session data was updated.
     $this->assertSame('entity', $data->entity, $new_data->entity);
-    $this->assertSame('id', $data->did, $new_data->did);
-    $this->assertNotSame('session_id', $data->session, $new_data->session);
+    $this->assertSame('id', $data->id, $new_data->id);
+    $this->assertNotSame('session_id', $data->session_id, $new_data->session_id);
+    $this->assertSame('form_id', $data->form_id, $new_data->form_id);
     $this->assertSame('quality', $data->quality, $new_data->quality);
     $count = db_result(db_query("SELECT COUNT(1) FROM {mollom}"));
     $this->assertEqual($count, 1, t('Stored data in {mollom} was updated.'));
