From 387b47ec2bb700776162086882ed66db9a2e7626 Mon Sep 17 00:00:00 2001
From: Dries Buytaert <dries@buytaert.net>
Date: Tue, 27 Dec 2005 14:34:21 +0000
Subject: [PATCH] - Patch #41755 by Neil: normalize poll.polled database
 column.

---
 database/database.mysql  | 14 +++++++++-
 database/database.pgsql  | 14 +++++++++-
 database/updates.inc     | 56 ++++++++++++++++++++++++++++++++++++++++
 modules/poll.module      | 52 ++++++++++++++++++-------------------
 modules/poll/poll.module | 52 ++++++++++++++++++-------------------
 5 files changed, 132 insertions(+), 56 deletions(-)

diff --git a/database/database.mysql b/database/database.mysql
index c96c51ee32b9..92df2c686c3e 100644
--- a/database/database.mysql
+++ b/database/database.mysql
@@ -536,11 +536,23 @@ CREATE TABLE permission (
 CREATE TABLE poll (
   nid int(10) unsigned NOT NULL default '0',
   runtime int(10) NOT NULL default '0',
-  polled longtext NOT NULL,
   active int(2) unsigned NOT NULL default '0',
   PRIMARY KEY (nid)
 ) TYPE=MyISAM;
 
+--
+-- Table structure for table 'poll_votes'
+--
+
+CREATE TABLE poll_votes (
+  nid int(10) unsigned NOT NULL,
+  uid int(10) unsigned NOT NULL,
+  hostname varchar(128) NOT NULL,
+  INDEX (nid),
+  INDEX (uid),
+  INDEX (hostname)
+) TYPE=MyISAM;
+
 --
 -- Table structure for table 'poll_choices'
 --
diff --git a/database/database.pgsql b/database/database.pgsql
index 6278a766a63b..7883dd06c574 100644
--- a/database/database.pgsql
+++ b/database/database.pgsql
@@ -531,11 +531,23 @@ CREATE INDEX permission_rid_idx ON permission(rid);
 CREATE TABLE poll (
   nid integer NOT NULL default '0',
   runtime integer NOT NULL default '0',
-  polled text NOT NULL default '',
   active integer NOT NULL default '0',
   PRIMARY KEY (nid)
 );
 
+--
+-- Table structure for poll_votes
+--
+
+CREATE TABLE poll_votes (
+  nid int(10) NOT NULL,
+  uid int(10) NOT NULL,
+  hostname varchar(128) NOT NULL
+);
+CREATE INDEX poll_voter_nid_idx ON poll_votes (nid);
+CREATE INDEX poll_votes_uid_idx ON poll_votes (uid);
+CREATE INDEX poll_votes_hostname_idx ON poll_votes (hostname);
+
 --
 -- Table structure for poll_choices
 --
diff --git a/database/updates.inc b/database/updates.inc
index f977fdbde3b6..26f627342b75 100644
--- a/database/updates.inc
+++ b/database/updates.inc
@@ -1286,3 +1286,59 @@ function system_update_163() {
   }
   return $ret;
 }
+
+function system_update_164() {
+  $ret = array();
+
+  switch ($GLOBALS['db_type']) {
+    case 'mysql':
+    case 'mysqli':
+      $ret[] = update_sql('CREATE TABLE {poll_votes} (
+          nid int(10) unsigned NOT NULL,
+          uid int(10) unsigned NOT NULL,
+          hostname varchar(128) NOT NULL,
+          INDEX (nid),
+          INDEX (uid),
+          INDEX (hostname)
+      )');
+      break;
+
+    case 'pgsql':
+      $ret[] = update_sql('CREATE TABLE {poll_votes} (
+          nid int(10) NOT NULL,
+          uid int(10) NOT NULL,
+          hostname varchar(128) NOT NULL
+      )');
+      $ret[] = update_sql('CREATE INDEX {poll_votes}_nid_idx ON {poll_votes} (nid)');
+      $ret[] = update_sql('CREATE INDEX {poll_votes}_uid_idx ON {poll_votes} (uid)');
+      $ret[] = update_sql('CREATE INDEX {poll_votes}_hostname_idx ON {poll_votes} (hostname)');
+      break;
+  }
+
+  $result = db_query('SELECT nid, polled FROM {poll}');
+  while ($poll = db_fetch_object($result)) {
+    foreach (explode(' ', $poll->polled) as $polled) {
+      if ($polled[0] == '_') {
+        // $polled is a user id
+        db_query('INSERT INTO {poll_votes} (nid, uid) VALUES (%d, %d)', $poll->nid, substr($polled, 1, -1));
+      }
+      else {
+        // $polled is a host
+        db_query("INSERT INTO {poll_votes} (nid, hostname) VALUES (%d, '%s')", $poll->nid, $polled);
+      }
+    }
+  }
+
+  switch ($GLOBALS['db_type']) {
+    case 'mysql':
+    case 'mysqli':
+      $ret[] = update_sql('ALTER TABLE {poll} DROP polled');
+      break;
+
+    case 'pgsql':
+      $ret[] = update_sql('ALTER TABLE {poll} RENAME polled TO polled_old');
+      break;
+  }
+
+  return $ret;
+}
diff --git a/modules/poll.module b/modules/poll.module
index f90aaa3f8a2e..d3385000b9f7 100644
--- a/modules/poll.module
+++ b/modules/poll.module
@@ -175,7 +175,7 @@ function poll_insert($node) {
     $node->active = 1;
   }
 
-  db_query("INSERT INTO {poll} (nid, runtime, polled, active) VALUES (%d, %d, '', %d)", $node->nid, $node->runtime, $node->active);
+  db_query("INSERT INTO {poll} (nid, runtime, active) VALUES (%d, %d, %d)", $node->nid, $node->runtime, $node->active);
 
   foreach ($node->choice as $choice) {
     if ($choice['chtext'] != '') {
@@ -222,28 +222,14 @@ function poll_menu($may_cache) {
   return $items;
 }
 
-/**
- * Determine an adjusted user id, to allow for basic tracking of anonymous
- * users (IP-based).
- */
-function poll_uid() {
-  global $user;
-  if ($user->uid) {
-     // Pad the UID with underscores to allow a simple strstr() search
-    $id = '_'. $user->uid .'_';
-  }
-  else {
-    $id = $_SERVER['REMOTE_ADDR'];
-  }
-  return $id;
-}
-
 /**
  * Implementation of hook_load().
  */
 function poll_load($node) {
+  global $user;
+
   // Load the appropriate choices into the $node object
-  $poll = db_fetch_object(db_query("SELECT runtime, polled, active FROM {poll} WHERE nid = %d", $node->nid));
+  $poll = db_fetch_object(db_query("SELECT runtime, active FROM {poll} WHERE nid = %d", $node->nid));
 
   $result = db_query("SELECT chtext, chvotes, chorder FROM {poll_choices} WHERE nid = %d ORDER BY chorder", $node->nid);
   while ($choice = db_fetch_array($result)) {
@@ -251,10 +237,13 @@ function poll_load($node) {
   }
 
   // Determine whether or not this user is allowed to vote
-  $poll->allowvotes = false;
-  if (user_access('vote on polls')) {
-    if (!strstr($poll->polled, poll_uid())) {
-      $poll->allowvotes = $poll->active;
+  $poll->allowvotes = FALSE;
+  if (user_access('vote on polls') && $poll->active) {
+    if ($user->uid && db_num_rows(db_query('SELECT uid FROM {poll_votes} WHERE nid = %d AND uid = %d', $node->nid, $user->uid)) == 0) {
+      $poll->allowvotes = TRUE;
+    }
+    else if ($user->uid == 0 && db_num_rows(db_query("SELECT hostname FROM {poll_votes} WHERE nid = %d AND hostname = '%s'", $node->nid, $_SERVER['REMOTE_ADDR'])) == 0) {
+      $poll->allowvotes = TRUE;
     }
   }
   return $poll;
@@ -411,7 +400,9 @@ function poll_results() {
  * Callback for processing a vote
  */
 function poll_vote(&$node) {
+  global $user;
   $nid = arg(1);
+
   if ($node = node_load($nid)) {
     $edit = $_POST['edit'];
     $choice = $edit['choice'];
@@ -419,11 +410,18 @@ function poll_vote(&$node) {
 
     if (isset($choice) && isset($node->choice[$choice])) {
       if ($node->allowvotes) {
-        $id = poll_uid();
-        $node->polled = $node->polled ? ($node->polled .' '. $id) : $id;
-        db_query("UPDATE {poll} SET polled = '%s' WHERE nid = %d", $node->polled, $node->nid);
+        // Mark the user or host as having voted.
+        if ($user->uid) {
+          db_query('INSERT INTO {poll_votes} (nid, uid) VALUES (%d, %d)', $node->nid, $user->uid);
+        }
+        else {
+          db_query("INSERT INTO {poll_votes} (nid, hostname) VALUES (%d, '%s')", $node->nid, $_SERVER['REMOTE_ADDR']);
+        }
+
+        // Add one to the votes.
         db_query("UPDATE {poll_choices} SET chvotes = chvotes + 1 WHERE nid = %d AND chorder = %d", $node->nid, $choice);
-        $node->allowvotes = false;
+
+        $node->allowvotes = FALSE;
         $node->choice[$choice]['chvotes']++;
         drupal_set_message(t('Your vote was recorded.'));
       }
@@ -492,4 +490,4 @@ function poll_update($node) {
       db_query("INSERT INTO {poll_choices} (nid, chtext, chvotes, chorder) VALUES (%d, '%s', %d, %d)", $node->nid, $chtext, $chvotes, $i++);
     }
   }
-}
\ No newline at end of file
+}
diff --git a/modules/poll/poll.module b/modules/poll/poll.module
index f90aaa3f8a2e..d3385000b9f7 100644
--- a/modules/poll/poll.module
+++ b/modules/poll/poll.module
@@ -175,7 +175,7 @@ function poll_insert($node) {
     $node->active = 1;
   }
 
-  db_query("INSERT INTO {poll} (nid, runtime, polled, active) VALUES (%d, %d, '', %d)", $node->nid, $node->runtime, $node->active);
+  db_query("INSERT INTO {poll} (nid, runtime, active) VALUES (%d, %d, %d)", $node->nid, $node->runtime, $node->active);
 
   foreach ($node->choice as $choice) {
     if ($choice['chtext'] != '') {
@@ -222,28 +222,14 @@ function poll_menu($may_cache) {
   return $items;
 }
 
-/**
- * Determine an adjusted user id, to allow for basic tracking of anonymous
- * users (IP-based).
- */
-function poll_uid() {
-  global $user;
-  if ($user->uid) {
-     // Pad the UID with underscores to allow a simple strstr() search
-    $id = '_'. $user->uid .'_';
-  }
-  else {
-    $id = $_SERVER['REMOTE_ADDR'];
-  }
-  return $id;
-}
-
 /**
  * Implementation of hook_load().
  */
 function poll_load($node) {
+  global $user;
+
   // Load the appropriate choices into the $node object
-  $poll = db_fetch_object(db_query("SELECT runtime, polled, active FROM {poll} WHERE nid = %d", $node->nid));
+  $poll = db_fetch_object(db_query("SELECT runtime, active FROM {poll} WHERE nid = %d", $node->nid));
 
   $result = db_query("SELECT chtext, chvotes, chorder FROM {poll_choices} WHERE nid = %d ORDER BY chorder", $node->nid);
   while ($choice = db_fetch_array($result)) {
@@ -251,10 +237,13 @@ function poll_load($node) {
   }
 
   // Determine whether or not this user is allowed to vote
-  $poll->allowvotes = false;
-  if (user_access('vote on polls')) {
-    if (!strstr($poll->polled, poll_uid())) {
-      $poll->allowvotes = $poll->active;
+  $poll->allowvotes = FALSE;
+  if (user_access('vote on polls') && $poll->active) {
+    if ($user->uid && db_num_rows(db_query('SELECT uid FROM {poll_votes} WHERE nid = %d AND uid = %d', $node->nid, $user->uid)) == 0) {
+      $poll->allowvotes = TRUE;
+    }
+    else if ($user->uid == 0 && db_num_rows(db_query("SELECT hostname FROM {poll_votes} WHERE nid = %d AND hostname = '%s'", $node->nid, $_SERVER['REMOTE_ADDR'])) == 0) {
+      $poll->allowvotes = TRUE;
     }
   }
   return $poll;
@@ -411,7 +400,9 @@ function poll_results() {
  * Callback for processing a vote
  */
 function poll_vote(&$node) {
+  global $user;
   $nid = arg(1);
+
   if ($node = node_load($nid)) {
     $edit = $_POST['edit'];
     $choice = $edit['choice'];
@@ -419,11 +410,18 @@ function poll_vote(&$node) {
 
     if (isset($choice) && isset($node->choice[$choice])) {
       if ($node->allowvotes) {
-        $id = poll_uid();
-        $node->polled = $node->polled ? ($node->polled .' '. $id) : $id;
-        db_query("UPDATE {poll} SET polled = '%s' WHERE nid = %d", $node->polled, $node->nid);
+        // Mark the user or host as having voted.
+        if ($user->uid) {
+          db_query('INSERT INTO {poll_votes} (nid, uid) VALUES (%d, %d)', $node->nid, $user->uid);
+        }
+        else {
+          db_query("INSERT INTO {poll_votes} (nid, hostname) VALUES (%d, '%s')", $node->nid, $_SERVER['REMOTE_ADDR']);
+        }
+
+        // Add one to the votes.
         db_query("UPDATE {poll_choices} SET chvotes = chvotes + 1 WHERE nid = %d AND chorder = %d", $node->nid, $choice);
-        $node->allowvotes = false;
+
+        $node->allowvotes = FALSE;
         $node->choice[$choice]['chvotes']++;
         drupal_set_message(t('Your vote was recorded.'));
       }
@@ -492,4 +490,4 @@ function poll_update($node) {
       db_query("INSERT INTO {poll_choices} (nid, chtext, chvotes, chorder) VALUES (%d, '%s', %d, %d)", $node->nid, $chtext, $chvotes, $i++);
     }
   }
-}
\ No newline at end of file
+}
-- 
GitLab