History | Log In     View a printable version of the current page.  
Issue Details (XML | Word | Printable)

Key: OX-5801
Type: Bug Bug
Status: Closed Closed
Resolution: Fixed
Priority: Critical Critical
Assignee: Miguel Correa
Reporter: Michal Czosnyka
Votes: 1
Watchers: 1

If you were logged in you would be able to see more operations.
OpenX Ad Server

Logic Flaw In Campaign Activation/expiration In 2.8.2

Created: 23/Oct/09 12:34 PM   Updated: 08/Jan/10 09:03 PM
Component/s: OXP: Maintenance Engine, OXP: Core
Affects Version/s: OpenX 2.8.2
Fix Version/s: OpenX 2.8.4
Security Level: Public (All users can see these issues)

Time Tracking:
Original Estimate: Not Specified
Remaining Estimate: 0h
Time Spent - 4.5h
Time Spent: 4.5h
Time Spent - 4.5h

Issue Links:

Source: Community

 Description  « Hide
There is a major problem with campaigns activiating before their start date that exists in 2.8.2. The problem is that the campaign activiation does not compare date/time's within the same timezone and thus there is room for campaigns starting and ending early or late depending on your timezone.

The server has the timezone set to Australia/Sydney, for example if we use "dpkg-reconfigure tzdata" on Debian to confirm the timezone.

Current default timezone: 'Australia/Sydney'
Local time is now: Fri Oct 23 16:32:54 EST 2009.
Universal Time is now: Fri Oct 23 05:32:54 UTC 2009.

Just to confirm that the server is reporting the correct date/time.

kaank@us-ox-1:/var/www/network.alluremedia.com.au/docroot$ date
Fri Oct 23 16:33:58 EST 2009

The php.ini configuration file has the timezone set to Australia/Sydney, as you can see below.

kaank@us-ox-1:/var/www/network.alluremedia.com.au/docroot$ cat /etc/php5/cgi/php.ini | grep 'date.timezone'
date.timezone = Australia/Sydney

The timezone within OpenX is currently set to Australia/Sydney as well, as you can see below.

mysql> select * from oa_account_preference_assoc where preference_id = 116;

account_id preference_id value


1 116 Australia/Sydney

1 row in set (0.00 sec)

So we can now safely assume that our OpenX installation is configured correctly and there is no chance that a misconfiguration could be causing the premature campaign activations.

I created a campaign with a start date of Saturday the 24th of October on the afternoon of Friday the 23rd of October and with the default OpenX 2.8.2 code the campaign activates immediately as if today was the 24th.

Within the database, which OpenX has activation and expiration date/time's saved in UTC, we can see that OpenX has saved the following activation date in the oa_campaigns table for this test campaign.

mysql> select activate_time from oa_campaigns where campaignid = 1429;



2009-10-23 13:00:00

1 row in set (0.00 sec)

The current UTC time is approximately 2009-10-23 05:30:00 as previously seen at the start of writing this. Therefore this campaign should not activate upon saving the activation date but it does activate immediately.

I've identified that code within lib/max/Dal/DataObjects/Campaigns.php in the _isAwaiting() and _isExpired() functions is the cause of this, which I'll now explain in more detail.

The original code, for _isAwaiting(), is as follows:

203     /**
204      * A method to check if the campaign is awaiting activation
205      *
206      * @return bool
207      */
208     function _isAwaiting()
209     {
210         static $oServiceLocator;
212         if (!empty($this->activate_time) && $this->activate_time != OX_DATAOBJECT_NULL) {
213             if (!isset($oServiceLocator)) {
214                 $oServiceLocator = &OA_ServiceLocator::instance();
215             }
216             if ((!$oNow = $oServiceLocator->get('now'))) {
217                 $oNow = new Date();
218             }
219             $oActivate = new Date($this->activate_time);
220             if ($oNow->before($oActivate)) {
221                 return true;
222             }
223         }
225         return false;
226     }

The general gist of this is that we get the current date/time in the $oNow object and then compare the date/time in the $oActivate object to see if we have reached the activation date/time. $oNow contains the current date/time in the timezone that has been set on the server, which is correct. $oActivate contains the activation date/time that comes from what is saved in the database, which is also correct, but the timezone on this object is not set to UTC even though the value of $this->activate_time is in UTC.

This is a var_dump of $oNow, notice that the date/time is correct for the timezone that the server, PHP and OpenX is configured for.

object(Date)#153 (8) {
  string(4) "2009"
  string(2) "10"
  string(2) "23"
  string(2) "16"
  string(2) "12"
  string(2) "32"
  object(Date_TimeZone)#154 (8) {
    string(16) "Australia/Sydney"
    string(39) "Eastern Standard Time (New South Wales)"
    string(3) "EST"
    string(37) "Eastern Summer Time (New South Wales)"
    string(3) "EST"

This is a var_dump of $oActivate, notice that the date/time is the same UTC date/time as what is saved in the database (see the MySQL query above) but the timezone is set to that of the server, PHP and OpenX. It is not set to UTC.

Therefore when we perform a comparison between these two objects the result will be incorrect. The $oActivate object needs to have the timezone set to UTC in order for the Date PEAR library to correctly compare the dates when using before() and after(). There is a simple solution for this which is to call setTZ('UTC') on the $oActivate and $oExpire objects after creating them. I've implemented these changes in lib/max/Dal/DataObjects/Campaigns.php, as you can see below on 220 and 246, and now the campaign activation and expiry is working 100% correct.

203     /**
204      * A method to check if the campaign is awaiting activation
205      *
206      * @return bool
207      */
208     function _isAwaiting()
209     {
210         static $oServiceLocator;
212         if (!empty($this->activate_time) && $this->activate_time != OX_DATAOBJECT_NULL) {
213             if (!isset($oServiceLocator)) {
214                 $oServiceLocator = &OA_ServiceLocator::instance();
215             }
216             if ((!$oNow = $oServiceLocator->get('now'))) {
217                 $oNow = new Date();
218             }
219             $oActivate = new Date($this->activate_time);
220             $oActivate->setTZ('UTC');
221             if ($oNow->before($oActivate)) {
222                 return true;
223             }
224         }
226         return false;
227     }
229     /**
230      * A method to check if the campaign is expired
231      *
232      * @return bool
233      */
234     function _isExpired()
235     {
236         static $oServiceLocator;
238         if (!empty($this->expire_time) && $this->expire_time != OX_DATAOBJECT_NULL) {
239             if (!isset($oServiceLocator)) {
240                 $oServiceLocator = &OA_ServiceLocator::instance();
241             }
242             if ((!$oNow = $oServiceLocator->get('now'))) {
243                 $oNow = new Date();
244             }
245             $oExpire = new Date($this->expire_time);
246             $oExpire->setTZ('UTC');
247             if ($oNow->after($oExpire)) {
248                 return true;
249             }
250         }
252         return false;
253     }

POST: http://forum.openx.org/index.php?showtopic=503443641

 All   Comments   Work Log   Change History   FishEye   Crucible   Builds      Sort Order: Ascending order - Click to sort in descending order

View Bamboo dashboard View Bamboo dashboard Bamboo Builds

The builds below were linked to this issue. Each build either fixes or is otherwise related to this issue.