Index: branches/5.2.x/units/posts/post_eh.php
===================================================================
--- branches/5.2.x/units/posts/post_eh.php	(revision 15566)
+++ branches/5.2.x/units/posts/post_eh.php	(revision 15567)
@@ -1,447 +1,447 @@
 <?php
 /**
 * @version	$Id$
 * @package	In-Bulletin
 * @copyright	Copyright (C) 1997 - 2009 Intechnic. All rights reserved.
 * @license      GNU/GPL
 * In-Portal is Open Source software.
 * This means that this software may have been modified pursuant
 * the GNU General Public License, and as distributed it includes
 * or is derivative of works licensed under the GNU General Public License
 * or other free or open source software licenses.
 * See http://www.in-portal.org/license for copyright notices and details.
 */
 
 	defined('FULL_PATH') or die('restricted access!');
 
 	class PostEventHandler extends kDBEventHandler {
 
 		/**
 		 * Checks topic-post modify and delete permissions
 		 *
 		 * @param kEvent $event
 		 * @return bool
 		 * @access public
 		 */
 		public function CheckPermission(kEvent $event)
 		{
 			$events = Array ('OnUpdate', 'OnDelete');
 
 			if ( in_array($event->Name, $events) ) {
 				return true;
 			}
 
 			return parent::CheckPermission($event);
 		}
 
 		/**
 		 * Sets default values
 		 *
 		 * @param kEvent $event
 		 * @return void
 		 * @access protected
 		 */
 		protected function OnBeforeItemCreate(kEvent $event)
 		{
 			parent::OnBeforeItemCreate($event);
 
 			$object = $event->getObject();
 			/* @var $object kDBItem */
 
 			$user_id = $this->Application->RecallVar('user_id');
 
 			$now = adodb_mktime();
 
 			$object->SetDBField('CreatedById', $user_id);
 			$object->SetDBField('CreatedOn_date', $now);
 			$object->SetDBField('CreatedOn_time', $now);
 
 			$object->SetDBField('ModifiedById', $user_id);
 			$object->SetDBField('Modified_date', $now);
 			$object->SetDBField('Modified_time', $now);
 
-			$object->SetDBField('IPAddress', $_SERVER['REMOTE_ADDR']);
+			$object->SetDBField('IPAddress', $this->Application->getClientIp());
 
 			$sql = 'SELECT Username
 					FROM ' . TABLE_PREFIX . 'Users
 					WHERE PortalUserId = ' . $user_id;
 			$object->SetDBField('PosterAlias', $this->Conn->GetOne($sql));
 
 			// set post options
 			$post_helper = $this->Application->recallObject('PostHelper');
 			/* @var $post_helper PostHelper */
 
 			$options_map = $post_helper->getOptionsMap();
 			$post_options = $object->GetDBField('Options');
 			foreach ($options_map as $option_name => $field_name) {
 				$option_value = $object->GetDBField($field_name);
 				$post_helper->SetPostOption($option_name, $option_value, $post_options);
 			}
 			$object->SetDBField('Options', $post_options);
 
 			$table_info = $object->getLinkedInfo($event->Special, true);
 			$object->SetDBField($table_info['ForeignKey'], $table_info['ParentId']);
 		}
 
 		/**
 		 * Checks if user has permission on post
 		 *
 		 * @param kEvent $event
 		 * @param string $permissions
 		 */
 		function checkPostPermission($event, $permissions)
 		{
 			$object = $event->getObject();
 			/* @var $object kDBItem */
 
 			$sql = 'SELECT ci.CategoryId, p.CreatedById
 					FROM '.$object->TableName.' p
 					LEFT JOIN '.TABLE_PREFIX.'Topic t ON t.TopicId = p.TopicId
 					LEFT JOIN '.TABLE_PREFIX.'CategoryItems ci ON ci.ItemResourceId = t.ResourceId AND ci.PrimaryCat = 1
 					WHERE p.'.$object->IDField.' = '.$object->GetID();
 			$post_info = $this->Conn->GetRow($sql);
 
 			$perm_helper = $this->Application->recallObject('PermissionsHelper');
 			/* @var $perm_helper kPermissionsHelper */
 
 			$is_owner = $post_info['CreatedById'] == $this->Application->RecallVar('user_id');
 			$params['permissions'] = 'TOPIC.REPLY.MODIFY|TOPIC.REPLY.OWNER.MODIFY';
 			$params['cat_id'] = $post_info['CategoryId'];
 			return $perm_helper->TagPermissionCheck($params, $is_owner);
 		}
 
 		/**
 		 * Sets post options before post update
 		 * Ensures, that only user with permission will update topic
 		 *
 		 * @param kEvent $event
 		 * @return void
 		 * @access protected
 		 */
 		protected function OnBeforeItemUpdate(kEvent $event)
 		{
 			parent::OnBeforeItemUpdate($event);
 
 			$object = $event->getObject();
 			/* @var $object kDBItem */
 
 			$perm_status = $this->checkPostPermission($event, 'TOPIC.REPLY.MODIFY|TOPIC.REPLY.OWNER.MODIFY');
 			if ( !$perm_status ) {
 				$event->status = kEvent::erFAIL;
 				return;
 			}
 
 			$post_helper = $this->Application->recallObject('PostHelper');
 			/* @var $post_helper PostHelper */
 
 			$options_map = $post_helper->getOptionsMap();
 			$post_options = $object->GetDBField('Options');
 			foreach ($options_map as $option_name => $field_name) {
 				$option_value = $object->GetDBField($field_name);
 				$post_helper->SetPostOption($option_name, $option_value, $post_options);
 			}
 			$object->SetDBField('Options', $post_options);
 		}
 
 		/**
 		 * Notifies admin about post change
 		 *
 		 * @param kEvent $event
 		 * @return void
 		 * @access protected
 		 */
 		protected function OnAfterItemUpdate(kEvent $event)
 		{
 			parent::OnAfterItemUpdate($event);
 
 			$this->Application->EmailEventAdmin('POST.MODIFY');
 		}
 
 		/**
 		 * Checks, that user can delete post
 		 *
 		 * @param kEvent $event
 		 * @return void
 		 * @access protected
 		 */
 		protected function OnBeforeItemDelete(kEvent $event)
 		{
 			parent::OnBeforeItemDelete($event);
 
 			$object = $event->getObject();
 			/* @var $object kDBItem */
 
 			if ( !$this->checkPostPermission($event, 'TOPIC.REPLY.OWNER.DELETE|TOPIC.REPLY.DELETE') ) {
 				$event->status = kEvent::erFAIL;
 			}
 		}
 
 		/**
 		 * Sets post options to virtual fields
 		 *
 		 * @param kEvent $event
 		 * @return void
 		 * @access protected
 		 */
 		protected function OnAfterItemLoad(kEvent $event)
 		{
 			parent::OnAfterItemLoad($event);
 
 			$object = $event->getObject();
 			/* @var $object kDBItem */
 
 			$post_helper = $this->Application->recallObject('PostHelper');
 			/* @var $post_helper PostHelper */
 
 			$options_map = $post_helper->getOptionsMap();
 			$post_options = $object->GetDBField('Options');
 
 			foreach ($options_map as $option_name => $field_name) {
 				$option_value = $post_helper->GetPostOption($option_name, $post_options);
 				$object->SetDBField($field_name, (int)$option_value);
 			}
 		}
 
 		/**
 		 * Updates cached post counter in topic
 		 *
 		 * @param kEvent $event
 		 * @return void
 		 * @access protected
 		 */
 		protected function OnAfterItemCreate(kEvent $event)
 		{
 			parent::OnAfterItemCreate($event);
 
 			$object = $event->getObject();
 			/* @var $object kDBItem */
 
 			$parent_prefix = $this->Application->getUnitOption($event->Prefix, 'ParentPrefix');
 
 			$main_object = $this->Application->recallObject($parent_prefix);
 			/* @var $main_object kCatDBItem */
 
 			// update user posts counter
 			$user_posts = $this->Application->RecallPersistentVar('bb_posts');
 			$this->Application->StorePersistentVar('bb_posts', $user_posts + 1);
 
 			$post_helper = $this->Application->recallObject('PostHelper');
 			/* @var $post_helper PostHelper */
 
 			$category_id = $this->Application->GetVar('m_cat_id');
 			$post_helper->PropagateCategoryField($category_id, 'Modified', $object->GetDBField('CreatedOn'));
 
 			if ( !$this->Application->isAdmin && $main_object->GetDBField('Posts') ) {
 				// don't send any email events when in admin OR new topic just added (0 posts)
 
 				$user_notified = false; // don't send POST.ADD event twice to same user (in case if owner adds new post)
 				if ( $main_object->GetDBField('NotifyOwnerOnChanges') ) {
 					$user_notified = $main_object->GetDBField('OwnerId');
 					$this->Application->EmailEventUser('POST.ADD', $user_notified);
 				}
 
 				$post_owner_id = $object->GetDBField('CreatedById');
 				if ( ($post_owner_id > 0) && ($user_notified != $post_owner_id) ) {
 					$this->Application->EmailEventUser('POST.ADD', $post_owner_id);
 				}
 
 				$this->Application->EmailEventAdmin('POST.ADD');
 			}
 
 			$post_helper->updateTodayPostsCount($main_object, $object->GetDBField('CreatedOn'), +1);
 			$this->updateTopicInfo($event, $main_object);
 
 			$topic_id = $object->GetDBField('TopicId');
 			$posts_count = $post_helper->updatePostCount($topic_id, +1);
 			$main_object->SetDBField('Posts', $posts_count);
 
 			// auto-lock topic after N number of posts (if option enabled)
 			$auto_lock = $this->Application->ConfigValue('AutoTopicLockPosts');
 
 			if ( (int)$auto_lock > 0 ) {
 				if ( $posts_count >= $auto_lock ) {
 					// user has unlocked topic after $auto_lock and posts again -> ensure that topic will be locked again
 					$this->Application->HandleEvent(new kEvent($parent_prefix . ':OnTopicLockToggle'));
 				}
 			}
 		}
 
 		/**
 		 * Update last post info in topic
 		 *
 		 * @param kEvent $event
 		 * @param kCatDBItem $main_object
 		 */
 		function updateTopicInfo($event, &$main_object)
 		{
 			$object = $event->getObject();
 			/* @var $object kDBItem */
 
 			$main_object->SetDBField('Modified_date', $object->GetDBField('Modified'));
 			$main_object->SetDBField('Modified_time', $object->GetDBField('Modified'));
 
 			$main_object->SetDBField('LastPostId', $object->GetID());
 
 			$main_object->SetDBField('LastPostDate_date', $object->GetDBField('CreatedOn'));
 			$main_object->SetDBField('LastPostDate_time', $object->GetDBField('CreatedOn'));
 
 			$main_object->Update();
 		}
 
 		/**
 		 * Goes to next_template after post creation
 		 *
 		 * @param kEvent $event
 		 * @return void
 		 * @access protected
 		 */
 		protected function OnCreate(kEvent $event)
 		{
 			parent::OnCreate($event);
 
 			if ( $event->status == kEvent::erSUCCESS && !$this->Application->isAdmin ) {
 				$event->SetRedirectParam('opener', 's');
 				$event->redirect = $this->Application->GetVar('next_template');
 			}
 		}
 
 		/**
 		 * Goes to next_template after post editing
 		 *
 		 * @param kEvent $event
 		 * @return void
 		 * @access protected
 		 */
 		protected function OnUpdate(kEvent $event)
 		{
 			parent::OnUpdate($event);
 
 			if ($event->status == kEvent::erSUCCESS && !$this->Application->isAdmin) {
 				$event->SetRedirectParam('opener', 's');
 				$event->redirect = $this->Application->GetVar('next_template');
 				$event->SetRedirectParam('pass', 'm,bb');
 			}
 		}
 
 		/**
 		 * Moves reference to last post in topic, when it is deleted
 		 *
 		 * @param kEvent $event
 		 * @return void
 		 * @access protected
 		 */
 		protected function OnAfterItemDelete(kEvent $event)
 		{
 			parent::OnAfterItemDelete($event);
 
 			$object = $event->getObject();
 			/* @var $object kDBItem */
 
 			$topic_id = $object->GetDBField('TopicId');
 			if ( !$topic_id ) {
 				// deleting post from non-existing topic
 				return;
 			}
 
 			$post_helper = $this->Application->recallObject('PostHelper');
 			/* @var $post_helper PostHelper */
 
 			// update posts count in topic
 			$post_helper->updatePostCount($topic_id, -1);
 
 			// update post owner posts counter
 			$sql = 'UPDATE ' . TABLE_PREFIX . 'UserPersistentSessionData
 					SET VariableValue = IF (VariableValue > 0, VariableValue - 1, 0)
 					WHERE (PortalUserId = ' . $object->GetDBField('CreatedById') . ') AND (VariableName = "bb_posts")';
 			$this->Conn->Query($sql);
 
 
 			$main_object = $this->Application->recallObject('bb.-item', null, Array ('skip_autoload' => true));
 			/* @var $main_object kCatDBItem */
 
 			$main_object->Load($topic_id);
 
 			if ( !$main_object->isLoaded() ) {
 				// this is topic deletion proccess, when all it's posts are deleted too
 				return;
 			}
 
 			$post_helper->updateTodayPostsCount($main_object, $object->GetDBField('CreatedOn'), -1);
 
 			if ( $main_object->GetDBField('LastPostId') == $object->GetID() ) {
 				$sql = 'SELECT PostingId, CreatedOn
 						FROM ' . $object->TableName . '
 						WHERE TopicId = ' . $topic_id . '
 						ORDER BY PostingId DESC';
 				$last_post = $this->Conn->GetRow($sql);
 
 				$fields_hash = Array (
 					'LastPostId' => $last_post['PostingId'],
 					'LastPostDate' => $last_post['CreatedOn'],
 				);
 				$this->Conn->doUpdate($fields_hash, $main_object->TableName, $main_object->IDField . ' = ' . $topic_id);
 			}
 		}
 
 		/**
 		 * Sets default values to posting options based on persistent session
 		 *
 		 * @param kEvent $event
 		 * @return void
 		 * @access protected
 		 */
 		protected function OnAfterConfigRead(kEvent $event)
 		{
 			parent::OnAfterConfigRead($event);
 
 			$virtual_fields = $this->Application->getUnitOption($event->Prefix, 'VirtualFields');
 			$virtual_fields['DisableBBCodes']['default'] = (int)!$this->Application->RecallPersistentVar('bbcode');
 			$virtual_fields['DisableSmileys']['default'] = (int)!$this->Application->RecallPersistentVar('smileys');
 			$virtual_fields['ShowSignatures']['default'] = (int)$this->Application->RecallPersistentVar('show_sig');
 			$this->Application->setUnitOption($event->Prefix, 'VirtualFields', $virtual_fields);
 		}
 
 		/**
 		 * Deletes items & preserves clean env
 		 *
 		 * @param kEvent $event
 		 * @return void
 		 * @access protected
 		 */
 		protected function OnDelete(kEvent $event)
 		{
 			parent::OnDelete($event);
 
 			if ( $event->status == kEvent::erSUCCESS && !$this->Application->isAdmin ) {
 				$parent_prefix = $this->Application->getUnitOption($event->Prefix, 'ParentPrefix');
 				$event->SetRedirectParam('pass', 'm,' . $parent_prefix);
 			}
 		}
 
 		/**
 		 * Prepares new reply form
 		 *
 		 * @param kEvent $event
 		 * @return void
 		 * @access protected
 		 */
 		protected function OnNew(kEvent $event)
 		{
 			parent::OnNew($event);
 
 			$reply_to = $this->Application->GetVar('reply_to');
 
 			if ( $reply_to > 0 ) {
 				$object = $event->getObject();
 				/* @var $object kDBItem */
 
 				$source_post = $this->Application->recallObject($event->Prefix . '.-item', null, Array ('skip_autoload' => true));
 				/* @var $source_post kDBItem */
 
 				$source_post->Load($reply_to);
 
 				$object->SetDBField('Subject', 'Re: ' . $source_post->GetDBField('Subject'));
 				$object->SetDBField('PostingText', '[quote id=' . $reply_to . ']' . $source_post->GetDBField('PostingText') . '[/quote]');
 			}
 		}
 	}
\ No newline at end of file
Index: branches/5.2.x/units/polls/poll_tp.php
===================================================================
--- branches/5.2.x/units/polls/poll_tp.php	(revision 15566)
+++ branches/5.2.x/units/polls/poll_tp.php	(revision 15567)
@@ -1,119 +1,126 @@
 <?php
 /**
 * @version	$Id$
 * @package	In-Bulletin
 * @copyright	Copyright (C) 1997 - 2009 Intechnic. All rights reserved.
 * @license      GNU/GPL
 * In-Portal is Open Source software.
 * This means that this software may have been modified pursuant
 * the GNU General Public License, and as distributed it includes
 * or is derivative of works licensed under the GNU General Public License
 * or other free or open source software licenses.
 * See http://www.in-portal.org/license for copyright notices and details.
 */
 
 	defined('FULL_PATH') or die('restricted access!');
 
 	class PollTagProcessor extends kDBTagProcessor {
 
 		/**
 		 * Allows to tell if user from current ip has voted already for current poll
 		 *
 		 * @param Array $params
 		 * @return bool
 		 */
 		function HasVoted($params)
 		{
 			$object = $this->getObject($params);
 			/* @var $object kDBItem */
 
-			if (!$object->GetDBField('AllowMultipleVotings')) {
+			if ( !$object->GetDBField('AllowMultipleVotings') ) {
+				$where_clause = Array (
+					'PollId = ' . $object->GetID(),
+					'CreatedById = ' . $this->Application->RecallVar('user_id'),
+					'UserIP = ' . $this->Conn->qstr($this->Application->getClientIp()),
+				);
+
 				$sql = 'SELECT StatisticsId
-						FROM '.TABLE_PREFIX.'PollsStatistics
-						WHERE PollId = '.$object->GetID().' AND CreatedById = '.$this->Application->RecallVar('user_id').' AND UserIP = '.$this->Conn->qstr(getenv('REMOTE_ADDR'));
+						FROM ' . TABLE_PREFIX . 'PollsStatistics
+						WHERE (' . implode(') AND (', $where_clause) . ')';
+
 				return $this->Conn->GetOne($sql) > 0;
 			}
 
 			return false;
 		}
 
 		/**
 		 * Allows to tell if user from current ip has voted already for current poll
 		 *
 		 * @param Array $params
 		 * @return bool
 		 */
 		function HasCommented($params)
 		{
 			$object = $this->getObject($params);
 			/* @var $object kDBItem */
 
 			$spam_helper = $this->Application->recallObject('SpamHelper');
 			/* @var $spam_helper SpamHelper */
 
 			$spam_helper->InitHelper($object->GetID(), 'PollComment', 0); // PollId used for SpamControl only
 
 			return $spam_helper->InSpamControl();
 		}
 
 		/**
 		 * Prints out only filled in answers of current poll
 		 *
 		 * @param Array $params
 		 * @return string
 		 */
 		function PrintPoll($params)
 		{
 			$object = $this->getObject($params);
 
 			$sql = 'SELECT COUNT(AnswerNum), AnswerNum
 					FROM '.TABLE_PREFIX.'PollsStatistics
 					WHERE PollId = '.$object->GetID().'
 					GROUP BY AnswerNum';
 			$statistics = $this->Conn->GetCol($sql, 'AnswerNum');
 
 			$total_votes = array_sum($statistics);
 
 			$block_params = $this->prepareTagParams($params);
 			$block_params['name'] = $params['render_as'];
 
 			$i = 1;
 			$ret = '';
 			while ($i < 8) {
 				$answer = $object->GetDBField('Answer'.$i);
 				if ($answer) {
 					$answer_votes = isset($statistics[$i]) ? $statistics[$i] : 0;
 					if ($total_votes > 0) {
 						$block_params['percent'] = round((100 * $answer_votes) / $total_votes, 0);
 					}
 					else {
 						$block_params['percent'] = 0;
 					}
 
 					$block_params['answer'] = $answer;
 					$block_params['answer_num'] = $i;
 
 					$ret .= $this->Application->ParseBlock($block_params);
 				}
 				$i++;
 			}
 
 			return $ret;
 		}
 
 		/**
 		 * Prints link to comments of of current poll
 		 *
 		 * @param Array $params
 		 * @return string
 		 */
 		function CommentsLink($params)
 		{
 			$object = $this->getObject($params);
 
 			$params['pass'] = 'm,poll';
 			$params['poll_id']	= $object->GetID();
 
 		 	return $this->Application->ProcessParsedTag('m', 'Link', $params);
 		}
 	}
\ No newline at end of file
Index: branches/5.2.x/units/polls/poll_eh.php
===================================================================
--- branches/5.2.x/units/polls/poll_eh.php	(revision 15566)
+++ branches/5.2.x/units/polls/poll_eh.php	(revision 15567)
@@ -1,171 +1,171 @@
 <?php
 /**
 * @version	$Id$
 * @package	In-Bulletin
 * @copyright	Copyright (C) 1997 - 2009 Intechnic. All rights reserved.
 * @license      GNU/GPL
 * In-Portal is Open Source software.
 * This means that this software may have been modified pursuant
 * the GNU General Public License, and as distributed it includes
 * or is derivative of works licensed under the GNU General Public License
 * or other free or open source software licenses.
 * See http://www.in-portal.org/license for copyright notices and details.
 */
 
 	defined('FULL_PATH') or die('restricted access!');
 
 	class PollEventHandler extends kDBEventHandler {
 
 		/**
 		 * Allows to override standard permission mapping
 		 *
 		 * @return void
 		 * @access protected
 		 * @see kEventHandler::$permMapping
 		 */
 		protected function mapPermissions()
 		{
 			parent::mapPermissions();
 
 			$permissions = Array (
 				'OnResetVotes'	=>	Array ('self' => 'edit'),
 				'OnMakeVote'	=>	Array ('self' => true),
 				'OnItemBuild'	=>	Array ('self' => true),
 			);
 
 			$this->permMapping = array_merge($this->permMapping, $permissions);
 		}
 
 		/**
 		 * Applies special filter, that allows to select all poll from given date range
 		 *
 		 * @param kEvent $event
 		 * @return void
 		 * @access protected
 		 * @see kDBEventHandler::OnListBuild()
 		 */
 		protected function SetCustomQuery(kEvent $event)
 		{
 			parent::SetCustomQuery($event);
 
 			if ( $this->Application->isAdminUser ) {
 				return;
 			}
 
 			$object = $event->getObject();
 			/* @var $object kDBList */
 
 			$object->addFilter('poll_range_filter', '(%1$s.StartDate <= ' . adodb_mktime() . ') AND (%1$s.EndDate >= ' . adodb_mktime() . ' OR EndDate IS NULL)');
 			$object->addFilter('poll_status', '(%1$s.Status = ' . STATUS_ACTIVE . ')');
 		}
 
 		/**
 		 * Reset votes statistics for current poll
 		 *
 		 * @param kEvent $event
 		 */
 		function OnResetVotes($event)
 		{
 			$object = $event->getObject();
 			/* @var $object kDBItem */
 
 			$sql = 'DELETE FROM '.TABLE_PREFIX.'PollsStatistics
 					WHERE '.$object->IDField.' = '.$object->GetID();
 			$this->Conn->Query($sql);
 
 
 			$poll_answers_table = $this->Application->getUnitOption('poll-answer', 'TableName');
 			$poll_answers_table = $this->Application->GetTempName($poll_answers_table);
 
 			$sql = 'UPDATE '.$poll_answers_table.' SET VotesQty = 0
 						WHERE '.$object->IDField.' = '.$object->GetID();
 			$this->Conn->Query($sql);
 		}
 
 		/**
 		 * Sets resource id
 		 *
 		 * @param kEvent $event
 		 * @return void
 		 * @access protected
 		 */
 		protected function OnBeforeItemCreate(kEvent $event)
 		{
 			parent::OnBeforeItemCreate($event);
 
 			$object = $event->getObject();
 			/* @var $object kDBItem */
 
 			$object->SetDBField('ResourceId', $this->Application->NextResourceId());
 		}
 
 		/**
 		 * Make vote to current poll
 		 *
 		 * @param kEvent $event
 		 */
 		function OnMakeVote($event)
 		{
 			$object = $event->getObject($this->Application->GetVar('poll_id'));
 			/* @var $object kDBItem */
 
 			$poll_answer_id = $this->Application->GetVar('option_id');
 
 			if (!$poll_answer_id) {
 				$event->redirect = false;
 				return ;
 			}
 
-			$ip_address = $_SERVER['REMOTE_ADDR'];
+			$ip_address = $this->Application->getClientIp();
 
 			if (!$object->GetDBField('AllowMultipleVotings')) {
 				$sql = 'SELECT StatisticsId
 						FROM '.TABLE_PREFIX.'PollsStatistics
 						WHERE PollId = '.$object->GetID().' AND UserIP = '.$this->Conn->qstr($ip_address);
 				$voted = $this->Conn->GetOne($sql) > 0;
 			}
 
 			if (!$voted) {
 				$user_id = $this->Application->RecallVar('user_id');
 				$fields_hash = 	Array (
 										'PollId'		=>	$object->GetID(),
 										'AnswerId'		=>	$poll_answer_id,
 										'UserIP'		=>	$ip_address,
 										'CreatedById'	=>	$user_id,
 										'AnswerDate'	=>	adodb_mktime(),
 								);
 
 				$this->Conn->doInsert($fields_hash, TABLE_PREFIX.'PollsStatistics');
 
 				$poll_table = $this->Application->getUnitOption('poll', 'TableName');
 				$this->Conn->Query('UPDATE '.$poll_table.' SET CachedVotesQty = CachedVotesQty + 1
 										WHERE PollId = '.$object->GetID());
 
 				// update table with answers
 				$poll_answers_table = $this->Application->getUnitOption('poll-answer', 'TableName');
 				$this->Conn->Query('UPDATE '.$poll_answers_table.' SET VotesQty = VotesQty + 1
 										WHERE PollId = '.$object->GetID().' AND AnswerId = '.$poll_answer_id);
 			}
 			$event->setEventParam('PollId', $this->Application->GetVar('poll_id'));
 			$event->redirect = false;
 		}
 
 		/**
 		 * Cleanup by removing items from PollStatistics before Poll is deleted
 		 *
 		 * @param kEvent $event
 		 * @return void
 		 * @access protected
 		 */
 		protected function OnAfterItemDelete(kEvent $event)
 		{
 			parent::OnAfterItemDelete($event);
 
 			$object = $event->getObject();
 			/* @var $object kDBItem */
 
 			$sql = 'DELETE FROM ' . TABLE_PREFIX . 'PollsStatistics
 					WHERE PollId = ' . $object->GetID();
 			$this->Conn->Query($sql);
 		}
 	}
\ No newline at end of file
Index: branches/5.2.x/units/poll_comments/poll_comment_eh.php
===================================================================
--- branches/5.2.x/units/poll_comments/poll_comment_eh.php	(revision 15566)
+++ branches/5.2.x/units/poll_comments/poll_comment_eh.php	(revision 15567)
@@ -1,161 +1,161 @@
 <?php
 /**
 * @version	$Id$
 * @package	In-Bulletin
 * @copyright	Copyright (C) 1997 - 2009 Intechnic. All rights reserved.
 * @license      GNU/GPL
 * In-Portal is Open Source software.
 * This means that this software may have been modified pursuant
 * the GNU General Public License, and as distributed it includes
 * or is derivative of works licensed under the GNU General Public License
 * or other free or open source software licenses.
 * See http://www.in-portal.org/license for copyright notices and details.
 */
 
 	defined('FULL_PATH') or die('restricted access!');
 
 	class PollCommentEventHandler extends kDBEventHandler {
 
 		/**
 		 * Allows to override standard permission mapping
 		 *
 		 * @return void
 		 * @access protected
 		 * @see kEventHandler::$permMapping
 		 */
 		protected function mapPermissions()
 		{
 			parent::mapPermissions();
 
 			$permissions = Array (
 				'OnCreate'		=>	Array ('self' => true, 'subitem' => true,),
 				'OnItemBuild'	=>	Array ('self' => true, 'subitem' => true,),
 			);
 
 			$this->permMapping = array_merge($this->permMapping, $permissions);
 		}
 
 		/**
 		 * Occurs, when config was parsed, allows to change config data dynamically
 		 *
 		 * @param kEvent $event
 		 * @return void
 		 * @access protected
 		 */
 		protected function OnAfterConfigRead(kEvent $event)
 		{
 			parent::OnAfterConfigRead($event);
 
 			if ( $this->Application->RecallVar('user_id') == USER_GUEST ) {
 				// make Guest Name and Email required for guests
 				$fields = $this->Application->getUnitOption($event->Prefix, 'Fields');
 				$fields['GuestName']['required'] = 1;
 				$fields['GuestEmail']['required'] = 1;
 				$this->Application->setUnitOption($event->Prefix, 'Fields', $fields);
 			}
 		}
 
 		/**
 		 * Applies special filter, that allows to select all commented from current poll
 		 *
 		 * @param kEvent $event
 		 * @return void
 		 * @access protected
 		 * @see kDBEventHandler::OnListBuild()
 		 */
 		protected function SetCustomQuery(kEvent $event)
 		{
 			parent::SetCustomQuery($event);
 
 			if ( $this->Application->isAdminUser ) {
 				return;
 			}
 
 			$object = $event->getObject();
 			/* @var $object kDBList */
 
 			$object->addFilter('comment_status', '%1$s.Status = ' . STATUS_ACTIVE);
 		}
 
 		/**
 		 * Occurs before creating item
 		 *
 		 * @param kEvent $event
 		 * @return void
 		 * @access protected
 		 */
 		protected function OnBeforeItemCreate(kEvent $event)
 		{
 			if ( !$this->Application->isAdmin ) {
 				$object = $event->getObject();
 				/* @var $object kDBItem */
 
 				$parent_info = $object->getLinkedInfo($event->Special);
 				$poll_id = $parent_info['ParentId'];
 
 				if ( $poll_id ) {
 					$spam_helper = $this->Application->recallObject('SpamHelper');
 					/* @var $spam_helper SpamHelper */
 
 					$spam_helper->InitHelper($poll_id, 'PollComment', 0); // ResourceId used for SpamControl only
 
 					if ( $spam_helper->InSpamControl() ) {
 						$event->status = kEvent::erFAIL;
 						$object->SetError('CommentText', 'too_frequent', 'lu_error_AlreadyCommented');
 						return ;
 					}
 
 					$object->SetDBField('PollId', $poll_id); // PollId
 				}
 
 				$object->SetDBField('CreatedById', $this->Application->RecallVar('user_id'));
-				$object->SetDBField('UserIP', $_SERVER['REMOTE_ADDR']);
+				$object->SetDBField('UserIP', $this->Application->getClientIp());
 				$object->SetDBField('Status', STATUS_ACTIVE);
 			}
 
 			parent::OnBeforeItemCreate($event);
 		}
 
 		/**
 		 * Updates item review counter
 		 *
 		 * @param kEvent $event
 		 * @return void
 		 * @access protected
 		 */
 		protected function OnCreate(kEvent $event)
 		{
 			parent::OnCreate($event);
 
 			if ( !$this->Application->isAdmin && $event->status == kEvent::erSUCCESS ) {
 				$event->setRedirectParam('opener', 's');
 				$event->setRedirectParam('pass', 'm,poll');
 				$event->redirect = $this->Application->GetVar('success_template');
 			}
 		}
 
 		/**
 		 * Protects against spam
 		 *
 		 * @param kEvent $event
 		 * @return void
 		 * @access protected
 		 */
 		protected function OnAfterItemCreate(kEvent $event)
 		{
 			parent::OnAfterItemCreate($event);
 
 			if ( !$this->Application->isAdminUser ) {
 				$spam_helper = $this->Application->recallObject('SpamHelper');
 				/* @var $spam_helper SpamHelper */
 
 				$object = $event->getObject();
 				/* @var $object kDBItem */
 
 				$comment_settings = 'poll_CommentDelay_Value:poll_CommentDelay_Interval';
 				$spam_helper->InitHelper($object->GetDBField('PollId'), 'PollComment', $comment_settings);
 				$spam_helper->AddToSpamControl();
 			}
 		}
 
 	}
\ No newline at end of file