Forums
> Content Management
> phpWebSite
> Poll Integrity Hack
The ad will go away if you log in.
<< [ 1 ] >>
| New Topic
| Reply
 |
rck |
“Poll Integrity Hack” |
#1 |
|
Admin[1998] from Korneuburg |
2006-02-28 14:33 |
|
|
The Poll is programmed very strangely. First, the votes are not stored as a own relation but as a semicolon separated list in one single field. Second, this field is only loaded during the startup of the session. This field is NOT updated prior to updating the value in it.
A quick fix would be to simply load the current values prior to updating / displaying them. For writing, this approach would need the InnoDB table type of MySQL for consistency. Right now, if someone started a session very long ago and did not vote, he/she would overwrite every poll since the first log in by voting.
Changing the table type to InnoDB:
[code]ALTER TABLE mod_poll ENGINE = InnoDB;[/code]
Next, we create a new function to re-read the current values:
[code] /**
*
* loadFromDB()
*
* loads the current vote-counter and the voted IPs
* directly from the DB to by-pass caching.
*
* @author rck
* @date 2006-02-28
*
*/
function loadFromDB() {
$prefix = $GLOBALS['core']->tbl_prefix;
$id = $this->getId();
$sql = 'SELECT counts, votedIps '.
"FROM ${prefix}mod_poll ";
if(empty($id))
$sql.="WHERE active=1";
else
$sql.= "WHERE id=$id";
$result= $GLOBALS['core']->getAllAssoc($sql);
$result= $result[0];
$this->_counts=explode(';', $result['counts']);
$this->_votedIps=unserialize($result['votedIps']);
}[/code]
... this one should be called right below the headers of the functions showUserBox(), vote() and showResult(). We also slightly rewrite the constructor:
[code] function PHPWS_Poll($my_id=NULL) {
$this->setTable("mod_poll");
$this->addExclude(array('_counts', '_votedIps'));
if(isset($my_id)) {
$this->loadFromDB();
$this->setId($my_id);
$this->init();
$this->_options = explode(";", $this->_options);
}
}[/code]
Next, we create a function that will write to the db with an transaction:
[code] /**
*
* storeToDB()
*
* writes current vote-counter and voted IPs
* directly to the DB to by-pass caching.
*
* WARNING!! This only works, if you've set the
* table type of mod_poll to InnoDB previously.
*
* @author rck
* @date 2006-02-28
*
*/
function storeToDB() {
$prefix = $GLOBALS['core']->tbl_prefix;
$id = $this->getId();
$GLOBALS['core']->query('set AUTOCOMMIT=0');
$GLOBALS['core']->query('BEGIN');
$this->loadFromDB();
$counts=implode(';', $this->_counts);
$votedIps=serialize($this->votedIps);
$sql = "UPDATE ${prefix}mod_poll ";
$sql.= "SET counts='$counts', votedIps='$votedIps' ";
if(empty($id))
$sql.="WHERE active=1";
else
$sql.= "WHERE id=$id";
$GLOBALS['core']->query($sql);
$GLOBALS['core']->query('COMMIT');
$GLOBALS['core']->query('set AUTOCOMMIT=1');
}[/code]
...and add it to commit_changes() on the very bottom of Poll.php like this:
[code] function commit_changes() {
$this->storeToDB();
if(count($this->_options) != 0) {
$this->_options = implode(";", $this->_options);
}
$this->commit();
$this->_options = explode(";", $this->_options);
}[/code]
|
|
--- 200 channels and... nothing but cats.
|
Quote
|
<< [ 1 ] >>
| Reply
|
|