changeset 2:e5584a19768b ad

maj module ad
author sly
date Wed, 15 Apr 2009 07:58:32 +0000
parents 948362c2a207
children 416ea999ed76
files ad.info ad.install ad.module adcache.inc adserve.inc cache/file/ad_cache_file.inc cache/file/ad_cache_file.info cache/file/ad_cache_file.module channel/ad_channel.inc channel/ad_channel.info channel/ad_channel.install channel/ad_channel.module documentation/CHANGELOG.txt documentation/DEBUG.txt documentation/INSTALL.txt embed/ad_embed.info external/ad_external.info html/ad_html.info image/ad_image.info image/ad_image.install image/ad_image.module imageserve.inc notify/ad_notify.info notify/ad_notify.module owners/ad_owners.info owners/ad_owners.module remote/ad_remote.info report/ad_report.info statistics/click_filter/click_filter.info text/ad_text.info weight/probability/ad_weight_probability.info
diffstat 31 files changed, 448 insertions(+), 147 deletions(-) [+]
line wrap: on
line diff
--- a/ad.info	Thu Apr 02 15:28:21 2009 +0000
+++ b/ad.info	Wed Apr 15 07:58:32 2009 +0000
@@ -4,9 +4,9 @@
 dependencies[] = taxonomy
 description = An advertising system for Drupal powered websites.
 core = 6.x
-; Information added by drupal.org packaging script on 2009-03-31
-version = "6.x-2.0-beta5"
+; Information added by drupal.org packaging script on 2009-04-14
+version = "6.x-2.0-beta6"
 core = "6.x"
 project = "ad"
-datestamp = "1238475303"
+datestamp = "1239719705"
 
--- a/ad.install	Thu Apr 02 15:28:21 2009 +0000
+++ b/ad.install	Wed Apr 15 07:58:32 2009 +0000
@@ -1,5 +1,5 @@
 <?php
-// $Id: ad.install,v 1.2.2.4.2.27.2.7.2.3 2009/03/27 20:11:13 jeremy Exp $
+// $Id: ad.install,v 1.2.2.4.2.27.2.7.2.4 2009/04/03 17:01:02 jeremy Exp $
 
 /**
  * @file
@@ -182,6 +182,13 @@
         'default' => 0,
         'description' => 'Count of actions triggered.',
       ),
+      'extra' => array(
+        'type' => 'varchar',
+        'length' => 255,
+        'not null' => TRUE,
+        'default' => '',
+        'description' => 'Alow add-on modules to provide additional statistics granularity.',
+      ),
     ),
     'primary key' => array('sid'),
     'indexes' => array(
@@ -190,6 +197,7 @@
       'action' => array('action'),
       'adgroup' => array('adgroup'),
       'hostid' => array('hostid'),
+      'extra' => array('extra'),
     ),
   );
 
@@ -271,6 +279,13 @@
         'default' => 0,
         'description' => 'Date when action was made.',
       ),
+      'extra' => array(
+        'type' => 'varchar',
+        'length' => 255,
+        'not null' => TRUE,
+        'default' => '',
+        'description' => 'Alow add-on modules to provide additional statistics granularity.',
+      ),
     ),
     'primary key' => array('cid'),
     'indexes' => array(
@@ -281,6 +296,7 @@
       'adgroup' => array('adgroup'),
       'hostid' => array('hostid'),
       'url' => array('url'),
+      'extra' => array('extra'),
     ),
   );
 
--- a/ad.module	Thu Apr 02 15:28:21 2009 +0000
+++ b/ad.module	Wed Apr 15 07:58:32 2009 +0000
@@ -1,5 +1,5 @@
 <?php
-// $Id: ad.module,v 1.2.2.29.2.83.2.16.2.12 2009/03/31 04:41:03 jeremy Exp $
+// $Id: ad.module,v 1.2.2.29.2.83.2.16.2.16 2009/04/14 14:02:11 jeremy Exp $
 
 /**
  * @file
@@ -157,7 +157,7 @@
       else {
         $query['u'] = $_GET['q'];
       }
-      $src = url($base_url .'/'. $adserve, array('query' => $query));
+      $src = htmlentities(url($base_url .'/'. $adserve, array('query' => $query)));
       if ($options['ad_display'] == 'iframe') {
         // TODO: We need to know the IFrame size before it is displayed.  This
         // limits the flexibility of what can be displayed in these frames.
@@ -1334,9 +1334,11 @@
         'expired' => t('Email @when after the advertisement is expired.'),
         '-active' => t('Email @when before the advertisement will be activated (if scheduled).'),
         'active' => t('Email @when after the advertisement is activated.'),
+        'offline' => t('Email @when after the advertisement is taken offline.'),
         'click' => t('Email @when after the advertisement is clicked.'),
         'approved' => t('Email @when after the advertisement is approved.'),
         'denied' => t('Email @when after the advertisement is denied.'),
+        'update' => t('Email @when after the advertisement is updated.'),
       );
       break;
     case '-expired':
@@ -1531,25 +1533,16 @@
 /**
  * Builds the necessary HTML to display an image-based impressions counter.
  */
-function ad_display_image($ad, $css = TRUE) {
+function ad_display_image($aid, $css = TRUE) {
   global $base_url;
   $adserve = variable_get('adserve', '');
   $cache = variable_get('ad_cache', 'none');
   $variables = "?o=image";
-  if (is_object($ad)) {
-    $aid = $ad->aid;
+  $variables .= "&a=$aid";
+  if ($cache != 'none') {
+    $variables .= '&c='. $cache . module_invoke('ad_cache_'. $cache, 'adcacheapi', 'display_variables', array());
   }
-  else {
-    /**
-     * No ad is specified, so we're just tracking traffic.
-     */
-    $aid = 0;
-  }
-  $variables .= "&amp;a=$aid";
-  if ($cache != 'none') {
-    $variables .= '&amp;c='. $cache . module_invoke('ad_cache_'. $cache, 'adcacheapi', 'display_variables', array());
-  }
-  $output = '<img src="'. url($base_url .'/'. $adserve . $variables) .'" height="0" width="0" alt="view counter" />';
+  $output = '<img src="'. htmlentities(url($base_url .'/'. $adserve . $variables)) .'" height="0" width="0" alt="view counter" />';
   if ($css) {
     return '<div class="ad-image-counter">'. $output .'</div>';
   }
--- a/adcache.inc	Thu Apr 02 15:28:21 2009 +0000
+++ b/adcache.inc	Wed Apr 15 07:58:32 2009 +0000
@@ -282,7 +282,7 @@
  */
 function adserve_cache_increment($action, $aid) {
   $hostid = adserve_variable('hostid');
-  _debug_echo("adserve_increment action($action) aid($aid) hostid($hostid)");
+  _debug_echo("adserve_cache_increment action($action) aid($aid) hostid($hostid)");
 
   // be sure that drupal is bootstrapped
   adserve_bootstrap();
@@ -293,7 +293,7 @@
     $extra = implode('|,|', $extra);
   }
   adserve_variable('extra', $extra);
-  _debug_echo("adserve_increment extra($extra)");
+  _debug_echo("adserve_cache_increment extra($extra)");
 
   // update statistics
   db_query("UPDATE {ad_statistics} SET count = count + 1 WHERE aid = %d AND action = '%s' AND date = %d AND adgroup = '%s' AND extra = '%s' AND hostid = '%s'", $aid, $action, date('YmdH'), adserve_variable('group'), $extra, $hostid);
@@ -463,7 +463,7 @@
     $output .= $ad;
     // increment counters
     if (adserve_variable('ad_display') == 'raw') {
-      $output .= ad_display_image($ad);
+      $output .= ad_display_image($id);
     }
     else {
       adserve_cache('increment', 'view', $id);
--- a/adserve.inc	Thu Apr 02 15:28:21 2009 +0000
+++ b/adserve.inc	Wed Apr 15 07:58:32 2009 +0000
@@ -1,5 +1,5 @@
 <?php
-// $Id: adserve.inc,v 1.1.2.31.2.8.2.6 2009/03/27 17:26:02 jeremy Exp $
+// $Id: adserve.inc,v 1.1.2.31.2.8.2.7 2009/04/09 14:06:27 jeremy Exp $
 
 /**
  * @file
@@ -49,7 +49,7 @@
   $ids = adserve_cache('get_ad_ids');
 
   // display the advertisement(s)
-  adserve_cache('display', $ids);
+  return adserve_cache('display', $ids);
 }
 
 /**
--- a/cache/file/ad_cache_file.inc	Thu Apr 02 15:28:21 2009 +0000
+++ b/cache/file/ad_cache_file.inc	Wed Apr 15 07:58:32 2009 +0000
@@ -1,5 +1,5 @@
 <?php
-// $Id: ad_cache_file.inc,v 1.1.4.23.2.5.2.4 2009/03/18 21:17:31 jeremy Exp $
+// $Id: ad_cache_file.inc,v 1.1.4.23.2.5.2.5 2009/03/31 17:59:00 jeremy Exp $
 
 /**
  * @file
@@ -182,6 +182,7 @@
   // increment counter
   if (is_array($cache['ad'][$aid]) &&
       isset($cache['ad'][$aid]['counts']) &&
+      isset($cache['ad'][$aid]['counts'][$group]) &&
       is_array($cache['ad'][$aid]['counts'][$group]) &&
       is_array($cache['ad'][$aid]['counts'][$group][$extra]) &&
       is_array($cache['ad'][$aid]['counts'][$group][$extra][$hostid]) &&
--- a/cache/file/ad_cache_file.info	Thu Apr 02 15:28:21 2009 +0000
+++ b/cache/file/ad_cache_file.info	Wed Apr 15 07:58:32 2009 +0000
@@ -1,12 +1,13 @@
-; $Id: ad_cache_file.info,v 1.1.2.1.2.1 2008/08/11 21:15:26 jeremy Exp $
+; $Id: ad_cache_file.info,v 1.1.2.1.2.1.2.1 2009/04/07 17:18:30 jeremy Exp $
 name = File cache
 package = Ad
-dependencies[] = ad
+dependencies[] = ad_owners
 description = Provides a file-caching mechanism to improve ad serving performance.
 core = 6.x
-; Information added by drupal.org packaging script on 2009-03-31
-version = "6.x-2.0-beta5"
+
+; Information added by drupal.org packaging script on 2009-04-14
+version = "6.x-2.0-beta6"
 core = "6.x"
 project = "ad"
-datestamp = "1238475303"
+datestamp = "1239719705"
 
--- a/cache/file/ad_cache_file.module	Thu Apr 02 15:28:21 2009 +0000
+++ b/cache/file/ad_cache_file.module	Wed Apr 15 07:58:32 2009 +0000
@@ -1,5 +1,5 @@
 <?php
-// $Id: ad_cache_file.module,v 1.1.4.18.2.5.2.7 2009/03/27 17:26:02 jeremy Exp $
+// $Id: ad_cache_file.module,v 1.1.4.18.2.5.2.8 2009/04/07 15:41:37 jeremy Exp $
 
 /**
  * @file
@@ -44,7 +44,10 @@
 /**
  * Implementation of hook_adcacheapi().
  */
-function ad_cache_file_adcacheapi($op, &$node = array()) {
+function ad_cache_file_adcacheapi($op, &$node = NULL) {
+  if ($node == NULL) {
+    $node = array();
+  }
   switch ($op) {
     case 'display_variables':
       return array(
--- a/channel/ad_channel.inc	Thu Apr 02 15:28:21 2009 +0000
+++ b/channel/ad_channel.inc	Wed Apr 15 07:58:32 2009 +0000
@@ -17,6 +17,8 @@
   $channels = adserve_cache('get_cache', 'channel');
   $valid = array();
   $nochannel = array();
+  $nochannel_weight = array();
+  $matched_channel = array();
   foreach ($ads as $aid) {
     _debug_echo("ad_channel_cache: checking aid($aid)");
     if (is_array($channels['ads']) && isset($channels['ads'][$aid]) &&
@@ -33,6 +35,11 @@
           if (empty($urls) || !$match) {
             _debug_echo("ad_channel_cache: aid($aid) is valid");
             $valid[] = $aid;
+            if ($display == 1) {
+              $nochannel_weight[$chid] = $channel->no_channel_weight;
+            }
+            $matched_channel[$aid] = $chid;
+            _debug_echo("ad_channel_cache: channel($channel->chid) no_channel_weight(". $nochannel_weight[$chid] .')');
             break;
           }
         }
@@ -40,6 +47,10 @@
           if (!empty($urls) && $match) {
             _debug_echo("ad_channel_cache: aid($aid) is valid");
             $valid[] = $aid;
+            if ($display == 1) {
+              $nochannel_weight[$chid] = $channel->no_channel_weight;
+            }
+            $matched_channel[$aid] = $chid;
             break;
           }
         }
@@ -66,7 +77,43 @@
     }
   }
 
-  if (empty($valid) && !empty($nochannel)) {
+  // Apply weights, applicable for advertisements that are not assigned to any
+  // channel.
+  if (!empty($valid) && !empty($nochannel_weight)) {
+    $weights = array();
+    foreach ($valid as $aid) {
+      if (isset($matched_channel[$aid])) {
+        $chid = $matched_channel[$aid];
+        if (isset($nochannel_weight[$chid])) {
+          $weights[$aid] = $nochannel_weight[$chid];
+          _debug_echo("ad_channel_cache: ad $aid in channel $chid with weight ". $nochannel_weight[$chid]);
+        }
+        else {
+          // by default, ads are assigned a weight of 100%
+          $weights[$aid] = 100;
+          _debug_echo("ad_channel_cache: ad $aid in channel $chid with default weight of 100");
+        }
+      }
+      else {
+        // by default, ads are assigned a weight of 100%
+        $weights[$aid] = 100;
+        _debug_echo("ad_channel_cache: ad $aid in no channel with default weight of 100");
+      }
+    }
+    if (!empty($weights)) {
+      $gcd = ad_channel_probability_gcd($weights);
+      $display = array();
+      _debug_echo("ad_channel_cache: adjusting channel weights, gcd ($gcd)");
+      foreach ($valid as $aid) {
+        $weight = $weights[$aid] / $gcd;
+        for ($i = 1; $i <= $weight; $i++) {
+          $display[] = $aid;
+        }
+      }
+      $valid = $display;
+    }
+  }
+  else if (empty($valid) && !empty($nochannel)) {
     _debug_echo("ad_channel_cache: using ads with no channel info");
     $valid = $nochannel;
   }
@@ -91,3 +138,28 @@
   _debug_echo("ad_channel_cache: returning non-premiere advertisements");
   return $valid;
 }
+
+/**
+ * Returns the greatest common divisor of an array of integers.
+ */
+function ad_channel_probability_gcd($integers) {
+  $gcd = array_shift($integers);
+
+  while (!empty($integers)) {
+    $gcd = _ad_channel_probability_gcd($gcd, array_shift($integers));
+  }
+  return $gcd;
+}
+
+/**
+ * Helper function to calculate the greatest common divisor using the Euclidean
+ * algorithm (http://en.wikipedia.org/wiki/Euclidean_algorithm).
+ */
+function _ad_channel_probability_gcd($a, $b) {
+  if ($b == 0) {
+    return $a;
+  }
+  else {
+    return _ad_channel_probability_gcd($b, $a % $b);
+  }
+}
--- a/channel/ad_channel.info	Thu Apr 02 15:28:21 2009 +0000
+++ b/channel/ad_channel.info	Wed Apr 15 07:58:32 2009 +0000
@@ -5,9 +5,9 @@
 description = Provides the ability to create advertisement channels, about which rules can be defined.
 core = 6.x
 
-; Information added by drupal.org packaging script on 2009-03-31
-version = "6.x-2.0-beta5"
+; Information added by drupal.org packaging script on 2009-04-14
+version = "6.x-2.0-beta6"
 core = "6.x"
 project = "ad"
-datestamp = "1238475303"
+datestamp = "1239719705"
 
--- a/channel/ad_channel.install	Thu Apr 02 15:28:21 2009 +0000
+++ b/channel/ad_channel.install	Wed Apr 15 07:58:32 2009 +0000
@@ -1,5 +1,5 @@
 <?php
-// $Id: ad_channel.install,v 1.1.4.3 2009/03/05 21:20:36 jeremy Exp $
+// $Id: ad_channel.install,v 1.1.4.5 2009/04/09 22:04:49 jeremy Exp $
 
 /**
  *
@@ -88,3 +88,21 @@
   return $ret;
 }
 
+/**
+ * Rebuild the menu so that channels and containers can be deleted.
+ */
+function ad_channel_update_6002() {
+  cache_clear_all();
+  menu_rebuild();
+  return array();
+}
+
+/**
+ * Introduce no_channel_weight.
+ */
+function ad_channel_update_6003() {
+  $ret = array();
+  $ret[] = update_sql("ALTER TABLE {ad_channel} ADD no_channel_weight INT(3) NOT NULL DEFAULT '0'");
+  return $ret;
+}
+
--- a/channel/ad_channel.module	Thu Apr 02 15:28:21 2009 +0000
+++ b/channel/ad_channel.module	Wed Apr 15 07:58:32 2009 +0000
@@ -1,5 +1,5 @@
 <?php
-// $Id: ad_channel.module,v 1.1.4.15 2009/03/31 00:59:21 jeremy Exp $
+// $Id: ad_channel.module,v 1.1.4.20 2009/04/09 22:04:49 jeremy Exp $
 
 /**
  * @file
@@ -81,26 +81,43 @@
     'access arguments' => array('administer channels'),
     'type' => MENU_LOCAL_TASK,
     'weight' => 9);
-/*
-  else {
-    TODO:
-      $items[] = array(
-        'path' => "admin/content/ad/channel/container/$conid/delete",
-        'callback' => 'drupal_get_form',
-        'callback arguments' => array('ad_channel_admin_confirm_delete_container', $conid),
-        'type' => MENU_CALLBACK);
-      $items[] = array(
-        'path' => "admin/content/ad/channel/channel/$chid/delete",
-        'callback' => 'drupal_get_form',
-        'callback arguments' => array('ad_channel_admin_confirm_delete_channel', $chid),
-        'type' => MENU_CALLBACK);
-    }
-*/
+  $items['admin/content/ad/channel/container/%ad_channel_container/delete'] = array(
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('ad_channel_admin_confirm_delete_container', 5),
+    'access arguments' => array('administer channels'),
+    'type' => MENU_CALLBACK);
+  $items['admin/content/ad/channel/channel/%ad_channel_channel/delete'] = array(
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('ad_channel_admin_confirm_delete_channel', 5),
+    'access arguments' => array('administer channels'),
+    'type' => MENU_CALLBACK);
 
   return $items;
 }
 
 /**
+ * Load a specified container.
+ */
+function ad_channel_container_load($conid = 0) {
+  static $containers = array();
+  if (!isset($containers[$conid])) {
+    $containers[$conid] = db_fetch_object(db_query('SELECT * FROM {ad_channel_container} WHERE conid = %d', $conid));
+  }
+  return $containers[$conid];
+}
+
+/**
+ * Load a specified channel.
+ */
+function ad_channel_channel_load($chid = 0) {
+  static $channels = array();
+  if (!isset($channels[$chid])) {
+    $channels[$chid] = db_fetch_object(db_query('SELECT * FROM {ad_channel} WHERE chid = %d', $chid));
+  }
+  return $channels[$chid];
+}
+
+/**
  * Implementation of hook_form_alter().
  * Generate a form for selecting channels to associate with an advertisement.
  */
@@ -152,14 +169,14 @@
     }
     $form['priority'] = array(
       '#type' => 'fieldset',
-      '#access' => user_access('configure ad premiere status'),
+      '#access' => user_access('configure ad premier status'),
       '#title' => t('Priority'),
       '#collapsible' => TRUE,
       '#collapsed' => FALSE,
     );
     $form['priority']['premiere'] = array(
       '#type' => 'checkbox',
-      '#access' => user_access('configure ad premiere status'),
+      '#access' => user_access('configure ad premier status'),
       '#title' => t('Premiere'),
       '#description' => t('An active premiere advertisement will override all other non-premiere advertisements in the same channel.  As long as one or more premiere advertisements are active in a channel, non-premiere advertisements will not be displayed in that channel.'),
       '#default_value' => isset($node->premiere) ? $node->premiere : FALSE,
@@ -461,7 +478,7 @@
     }
   }
   $channels = array();
-  $result = db_query('SELECT chid, display, urls FROM {ad_channel}');
+  $result = db_query('SELECT chid, display, urls, no_channel_weight FROM {ad_channel}');
   while ($channel = db_fetch_object($result)) {
     $channels[$channel->chid] = $channel;
   }
@@ -506,6 +523,14 @@
     '#default_value' => variable_get('ad_channel_admin_list', AD_CHANNEL_LIST_CHANNEL),
     '#description' => t('By default, channels will be listed along with groups on the administrative ads list.  You can optionally disable either the groups column (by selecting "in place of groups"), or the channel column (by selecting "not at all").'),
   );
+  $options = array(0 => t('No limit')) + drupal_map_assoc(array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
+  $form['ad_channel_ad_limit'] = array(
+    '#type' => 'select',
+    '#title' => t('Maximum number of channels that can be assigned to a single ad'),
+    '#options' => $options,
+    '#default_value' => variable_get('ad_channel_ad_limit', 0),
+    '#description' => t('Optionally limit the number of channels that a single advertisement can be assigned to.'),
+  );
 
   return system_settings_form($form);
 }
@@ -565,7 +590,7 @@
   foreach ($channels as $chid) {
     db_query('INSERT INTO {ad_channel_node} (chid, nid) VALUES(%d, %d)', $chid, $node->nid);
   }
-  if (user_access('configure ad premiere status')) {
+  if (user_access('configure ad premier status')) {
     db_query('UPDATE {ad_priority} SET priority = %d WHERE aid = %d', isset($node->premiere) ? $node->premiere : 0, $node->nid);
     if (!db_affected_rows()) {
       db_query('INSERT INTO {ad_priority} (aid, priority) VALUES(%d, %d)', $node->nid, isset($node->premiere) ? $node->premiere : 0);
@@ -588,8 +613,19 @@
  */
 function _ad_channel_validate_nodes($node) {
   $channels = _ad_channel_get_enabled($node);
+  $limit = variable_get('ad_channel_ad_limit', 0);
+  if ($limit && sizeof($channels) > $limit) {
+    $quantity_error = TRUE;
+  }
+  else {
+    $quantity_error = FALSE;
+  }
   foreach ($channels as $chid) {
     $channel = _ad_channel_get_channels($chid);
+    if ($quantity_error) {
+      $quantity_error = FALSE;
+      form_set_error("channel[$channel->conid][channel-$chid]", t('You can not assign this advertisement to more than !limit.', array('!limit' => format_plural(sizeof($limit), '1 channel', '@count channels'))));
+    }
     $taxonomy = is_array($node->taxonomy) ? $node->taxonomy : array();
     $groups = unserialize($channel->groups);
     if (!empty($groups)) {
@@ -839,14 +875,12 @@
 /**
  * Confirm whether or not to delete container, and the contained channels.
  */
-function ad_channel_admin_confirm_delete_container($conid) {
+function ad_channel_admin_confirm_delete_container($form_state, $container) {
   $form = array();
 
-  $container = _ad_channel_get_containers($conid);
-
   $form['conid'] = array(
     '#type' => 'value',
-    '#value' => $conid,
+    '#value' => $container->conid,
   );
 
   return confirm_form(
@@ -975,6 +1009,29 @@
     );
   }
 
+  $collapsed = (variable_get('ad_channel_display', 0) == 1) ? 0 : 1;
+  $form['nonchannel_rules'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('Not-in-channel ad rules'),
+    '#collapsible' => TRUE,
+    '#collapsed' => $collapsed,
+  );
+  if ($collapsed) {
+    $form['nonchannel_rules']['info'] = array(
+      '#type' => 'markup',
+      '#prefix' => '<div>',
+      '#suffix' => '</div>',
+      '#value' => t('You will need to set "!variable" to %value for these %type ad rules to be applicable.  Currently these settings are doing nothing.', array('!variable' => l(t('display advertisements not assigned to any channel'), 'admin/content/ad/channel/settings'), '%value' => t('always'), '%type' => 'not-in-channel')),
+    );
+  }
+  $form['nonchannel_rules']['no_channel_weight'] = array(
+    '#type' => 'select',
+    '#title' => t('Probability'),
+    '#options' => _ad_channel_probabilities(),
+    '#default_value' => $channel->no_channel_weight ? $channel->no_channel_weight : 100,
+    '#description' => t('The greater the probability, the more frequently advertisements that aren\'t in any channel will be displayed along with ads in this channel.  For example, if set to 2, advertisements without any channel will be displayed twice as often as advertisements assigned to this channel.  If set to 1/2, advertisements without any channel will be displayed half as often as advertisements assigned to this channel.  If set to 1, advertisements without any channel will be displayed as often as advertisements assigned to this channel.'),
+  );
+
   if ($chid) {
     $form['update'] = array(
       '#type' => 'submit',
@@ -1019,9 +1076,20 @@
  * Save the channel.
  */
 function ad_channel_admin_channel_submit($form, &$form_state) {
+  // remove extraneous white space from url list which can break matching
+  $url_array = explode("\n", $form_state['values']['urls']);
+  if (is_array($url_array)) {
+    foreach ($url_array as $url) {
+      $urls[] = trim($url);
+    }
+    $urls = implode("\n", $urls);
+  }
+  else {
+    $urls = '';
+  }
   switch ($form_state['values']['op']) {
     case t('Create'):
-      db_query("INSERT INTO {ad_channel} (name, description, conid, weight, display, urls, groups) VALUES('%s', '%s', %d, %d, %d, '%s', '%s')", $form_state['values']['name'], $form_state['values']['description'], $form_state['values']['conid'], $form_state['values']['weight'], $form_state['values']['display'], serialize($form_state['values']['urls']), serialize($form_state['values']['groups']));
+      db_query("INSERT INTO {ad_channel} (name, description, conid, weight, display, urls, groups, no_channel_weight) VALUES('%s', '%s', %d, %d, %d, '%s', '%s', %d)", $form_state['values']['name'], $form_state['values']['description'], $form_state['values']['conid'], $form_state['values']['weight'], $form_state['values']['display'], serialize($urls), serialize($form_state['values']['groups']), $form_state['values']['no_channel_weight']);
       drupal_set_message(t('The %name channel has been created.', array('%name' => $form_state['values']['name'])));
       break;
     case t('Update'):
@@ -1035,7 +1103,7 @@
           }
         }
       }
-      db_query("UPDATE {ad_channel} SET name = '%s', description = '%s', conid = %d, weight = %d, display = %d, urls = '%s', groups = '%s' WHERE chid = %d", $form_state['values']['name'], $form_state['values']['description'], $form_state['values']['conid'], $form_state['values']['weight'], $form_state['values']['display'], serialize($form_state['values']['urls']), serialize($groups), $form_state['values']['chid']);
+      db_query("UPDATE {ad_channel} SET name = '%s', description = '%s', conid = %d, weight = %d, display = %d, urls = '%s', groups = '%s', no_channel_weight = %d WHERE chid = %d", $form_state['values']['name'], $form_state['values']['description'], $form_state['values']['conid'], $form_state['values']['weight'], $form_state['values']['display'], serialize($urls), serialize($groups), $form_state['values']['no_channel_weight'], $form_state['values']['chid']);
       drupal_set_message(t('The %name channel has been updated.', array('%name' => $form_state['values']['name'])));
       break;
     case t('Delete'):
@@ -1047,14 +1115,12 @@
 /**
  * Confirm whether or not to delete container, and the contained channels.
  */
-function ad_channel_admin_confirm_delete_channel($chid) {
+function ad_channel_admin_confirm_delete_channel($form_state, $channel) {
   $form = array();
 
-  $channel = _ad_channel_get_channels($chid);
-
   $form['chid'] = array(
     '#type' => 'value',
-    '#value' => $chid,
+    '#value' => $channel->chid,
   );
 
   return confirm_form(
@@ -1078,3 +1144,17 @@
   drupal_goto('admin/content/ad/channel');
 }
 
+/**
+ * Available probabilities.
+ */
+function _ad_channel_probabilities() {
+  return array(
+    25 => t('1/4'),
+    33 => t('1/3'),
+    50 => t('1/2'),
+    100 => t('1'),
+    200 => t('2'),
+    300 => t('3'),
+    400 => t('4'),
+  );
+}
--- a/documentation/CHANGELOG.txt	Thu Apr 02 15:28:21 2009 +0000
+++ b/documentation/CHANGELOG.txt	Wed Apr 15 07:58:32 2009 +0000
@@ -1,4 +1,68 @@
-$Id: CHANGELOG.txt,v 1.2.2.40.2.176.2.41.2.53 2009/03/31 04:49:25 jeremy Exp $
+$Id: CHANGELOG.txt,v 1.2.2.40.2.176.2.41.2.71 2009/04/14 14:02:11 jeremy Exp $
+
+April 14th, 2009
+ - ad.module
+    o bug #431806: use valid XHTML when displaying advertisements
+
+April 9th, 2009
+ - ad.module
+    o bug #404888: properly increment impressions when using the raw method to
+      display advertisements
+ - adserve.inc
+    o bug #404888: properly display advertisements in Raw mode
+ - imageserve.inc
+    o bug #404888: properly increment impressions when using the raw method to
+      display advertisements
+ - ad_channel.inc
+    o feature #421038: allow weighting of non-channel advertisements
+ - ad_channel.install
+    o feature #421038: allow weighting of non-channel advertisements
+ - ad_channel.module
+    o feature #421038: allow weighting of non-channel advertisements
+
+April 7th, 2009
+ - ad_cache_file
+    o bug #425482: support older versions of PHP when building cache
+ - ad_channel.module
+    o #426292: sanitize urls trimming white space from start and end of lines
+      to be sure they match as expected
+ - ad_cache_file.info
+    o bug #376924: list ad_owner as ad_cache_file dependency
+ - ad_channel.module
+    o bug #426300: allow the deletion of channels and containers
+ - ad_channel.install
+    o bug #426300: rebuild menu so channels and containers can be deleted
+
+April 3rd, 2009
+ - ad_channel.module
+    o feature #421046: optionally limit the number of channels that can be
+      assigned to a single advertisement
+ - ad.install
+    o bug #422936: add missing extra fields from table definitions
+
+April 2nd, 2009
+ - ad_channel.module
+    o bug #421008: make premier status configurable to anyone with 'configure
+      premier status' permission
+ - ad.module
+    o feature #421026: add notification event for an advertisement being taken
+      offline
+    o feature #421026: add notification event for an advertisement being updated
+ - ad_notify.module
+    o remove outdated notification references to _views, changing to the new
+      _impressions syntax
+ - ad_image.module
+    o feature #421054: enforce optional maximum filesize
+    o enforce maximum size, and minimum/maximum height and width o422936n remotely
+      hosted images in addition to locally hosted images
+ - ad_image.install
+    o feature #421054: add new max_size field for enforcing maximum filesize
+
+March 31st, 2009
+ - ad_owners.module
+    o bug #419140: always be sure $permissions is an array
+ - ad_file_cache.inc
+    o bug #400734: validate cache element exists before using it
 
 March 30th, 2009 (6.x-2.0-beta5)
  - ad_channel.module
--- a/documentation/DEBUG.txt	Thu Apr 02 15:28:21 2009 +0000
+++ b/documentation/DEBUG.txt	Wed Apr 15 07:58:32 2009 +0000
@@ -2,7 +2,7 @@
 sure to carefully follow the instructions in INSTALL.txt, and to read through
 README.txt.
 
-If after reviewing those files you are still having problems with the ad 
+If after reviewing those files you are still having problems with the ad
 module, please review the project's issue queue to see if you are experiencing
 a known bug:
    http://drupal.org/project/issues/ad
@@ -15,9 +15,9 @@
 
 In the event that ads are not displaying, it is helpful if you collect the
 following debug information and inculde it in your bug report.  Using your
-web browser, view the html source of the page on which you expect 
-advertisements to show up.  Search for the string "serve.php", then copy and 
-paste that entire URL directly into your web browser.  It will look something 
+web browser, view the html source of the page on which you expect
+advertisements to show up.  Search for the string "serve.php", then copy and
+paste that entire URL directly into your web browser.  It will look something
 like:
   http://sample.com/modules/ad/serve.php?q=1&t=23
 
@@ -30,3 +30,8 @@
 the URL will be ignored resulting in invalid output.)
 
 You can then submit the resulting debug output in your bug report.
+
+If you are seeing errors, please explain where you are seeing the errors, and
+include the _full_ error message (including any line numbers and file names).
+It is also very helpful to provide detailed instructions on how to duplicate
+these errors.
--- a/documentation/INSTALL.txt	Thu Apr 02 15:28:21 2009 +0000
+++ b/documentation/INSTALL.txt	Wed Apr 15 07:58:32 2009 +0000
@@ -1,7 +1,8 @@
 -------------
 Requirements:
 -------------
- - Drupal 5.x
+ - Drupal 6.x
+ - taxonomy.module
  - upload.module (if using the ad_image module)
 
 -------------
--- a/embed/ad_embed.info	Thu Apr 02 15:28:21 2009 +0000
+++ b/embed/ad_embed.info	Wed Apr 15 07:58:32 2009 +0000
@@ -4,9 +4,9 @@
 dependencies[] = ad
 description = Embed ads in content.
 core = 6.x
-; Information added by drupal.org packaging script on 2009-03-31
-version = "6.x-2.0-beta5"
+; Information added by drupal.org packaging script on 2009-04-14
+version = "6.x-2.0-beta6"
 core = "6.x"
 project = "ad"
-datestamp = "1238475303"
+datestamp = "1239719705"
 
--- a/external/ad_external.info	Thu Apr 02 15:28:21 2009 +0000
+++ b/external/ad_external.info	Wed Apr 15 07:58:32 2009 +0000
@@ -4,9 +4,9 @@
 dependencies[] = ad
 description = Enhances the ad module to support externally hosted ads.  Typically combined with IFrames.
 core = 6.x
-; Information added by drupal.org packaging script on 2009-03-31
-version = "6.x-2.0-beta5"
+; Information added by drupal.org packaging script on 2009-04-14
+version = "6.x-2.0-beta6"
 core = "6.x"
 project = "ad"
-datestamp = "1238475303"
+datestamp = "1239719705"
 
--- a/html/ad_html.info	Thu Apr 02 15:28:21 2009 +0000
+++ b/html/ad_html.info	Wed Apr 15 07:58:32 2009 +0000
@@ -4,9 +4,9 @@
 dependencies[] = ad
 description = Enhances the ad module to support html-based ads, such as those defined by many advertising affiliate websites.
 core = 6.x
-; Information added by drupal.org packaging script on 2009-03-31
-version = "6.x-2.0-beta5"
+; Information added by drupal.org packaging script on 2009-04-14
+version = "6.x-2.0-beta6"
 core = "6.x"
 project = "ad"
-datestamp = "1238475303"
+datestamp = "1239719705"
 
--- a/image/ad_image.info	Thu Apr 02 15:28:21 2009 +0000
+++ b/image/ad_image.info	Wed Apr 15 07:58:32 2009 +0000
@@ -5,9 +5,9 @@
 dependencies[] = upload
 description = Enhances the ad module to support banner ads.
 core = 6.x
-; Information added by drupal.org packaging script on 2009-03-31
-version = "6.x-2.0-beta5"
+; Information added by drupal.org packaging script on 2009-04-14
+version = "6.x-2.0-beta6"
 core = "6.x"
 project = "ad"
-datestamp = "1238475303"
+datestamp = "1239719705"
 
--- a/image/ad_image.install	Thu Apr 02 15:28:21 2009 +0000
+++ b/image/ad_image.install	Wed Apr 15 07:58:32 2009 +0000
@@ -1,5 +1,5 @@
 <?php
-// $Id: ad_image.install,v 1.2.2.2.2.6.2.4.2.2 2009/03/27 20:11:13 jeremy Exp $
+// $Id: ad_image.install,v 1.2.2.2.2.6.2.4.2.3 2009/04/02 15:48:29 jeremy Exp $
 
 /**
  * @file
@@ -95,6 +95,12 @@
         'not null' => TRUE,
         'default' => 0,
       ),
+      'max_size' => array(
+        'type' => 'int',
+        'unsigned' => TRUE,
+        'not null' => TRUE,
+        'default' => 0,
+      ),
     ),
     'primary key' => array('gid'),
   );
@@ -138,3 +144,18 @@
     ));
   return $ret;
 }
+
+/**
+ * Introduce remote_image field for remotely hosted images.
+ */
+function ad_image_update_6002() {
+  $ret = array();
+  db_add_field($ret, 'ad_image_format', 'max_size',
+    array(
+      'type' => 'int',
+      'unsigned' => TRUE,
+      'not null' => TRUE,
+      'default' => '0',
+    ));
+  return $ret;
+}
--- a/image/ad_image.module	Thu Apr 02 15:28:21 2009 +0000
+++ b/image/ad_image.module	Wed Apr 15 07:58:32 2009 +0000
@@ -1,5 +1,5 @@
 <?php
-// $Id: ad_image.module,v 1.2.2.13.2.40.2.11.2.5 2009/03/11 16:12:07 jeremy Exp $
+// $Id: ad_image.module,v 1.2.2.13.2.40.2.11.2.6 2009/04/02 15:48:29 jeremy Exp $
 
 /**
  * @file
@@ -152,6 +152,14 @@
     );
 
     $format = db_fetch_object(db_query('SELECT * FROM {ad_image_format} WHERE gid = %d', $tid));
+    $form["group-$tid"]["max-size-$tid"] = array(
+      '#type' => 'textfield',
+      '#title' => t('Maximum filesize'),
+      '#size' => 5,
+      '#maxlength' => 15,
+      '#default_value' => isset($format->max_size) ? $format->max_size : 0,
+      '#description' => t('Optionally specify a maximum filesize in bytes for images in this group.  To specify no maximum filesize, enter <em>0</em>.'),
+    );
     $form["group-$tid"]["min-height-$tid"] = array(
       '#type' => 'textfield',
       '#title' => t('Minimum height'),
@@ -206,10 +214,10 @@
     // TODO: Update the database schema, convert gid to tid.
     $gid = db_result(db_query('SELECT gid FROM {ad_image_format} WHERE gid = %d', $group->tid));
     if (is_numeric($gid)) {
-      db_query("UPDATE {ad_image_format} SET min_width = %d, max_width = %d, min_height = %d, max_height = %d WHERE gid = %d", $form_state['values']["min-width-$group->tid"], $form_state['values']["max-width-$group->tid"], $form_state['values']["min-height-$group->tid"], $form_state['values']["max-height-$group->tid"], $group->tid);
+      db_query("UPDATE {ad_image_format} SET min_width = %d, max_width = %d, min_height = %d, max_height = %d, max_size = %d WHERE gid = %d", $form_state['values']["min-width-$group->tid"], $form_state['values']["max-width-$group->tid"], $form_state['values']["min-height-$group->tid"], $form_state['values']["max-height-$group->tid"], $form_state['values']["max-size-$group->tid"], $group->tid);
     }
     else {
-      db_query("INSERT INTO {ad_image_format} (gid, min_width, max_width, min_height, max_height) VALUES (%d, %d, %d, %d, %d)", $group->tid, $form_state['values']["min-width-$group->tid"], $form_state['values']["max-width-$group->tid"], $form_state['values']["min-height-$group->tid"], $form_state['values']["max-height-$group->tid"]);
+      db_query("INSERT INTO {ad_image_format} (gid, min_width, max_width, min_height, max_height, max_size) VALUES (%d, %d, %d, %d, %d, %d)", $group->tid, $form_state['values']["min-width-$group->tid"], $form_state['values']["max-width-$group->tid"], $form_state['values']["min-height-$group->tid"], $form_state['values']["max-height-$group->tid"], $form_state['values']["max-size-$group->tid"]);
     }
   }
   drupal_set_message('Image ad global settings updated.');
@@ -236,12 +244,7 @@
     case 'insert':
     case 'update':
       $fid = isset($node->files) ? (int)ad_image_active_file($node->files) : 0;
-      if ($fid) {
-        $image = ad_image_load_image($node);
-      }
-      else if (isset($node->remote_image)) {
-        list($image->width, $image->height) = getimagesize($node->remote_image);
-      }
+      $image = ad_image_load_image($node);
       // This is ugly, but as "a" comes before "u" we don't seem to be able
       // to modify the upload module's form.  Instead, we check after the fact
       // if someone is editing images when they're not allowed, and if so we
@@ -272,24 +275,22 @@
         }
       }
       if ($op == 'insert') {
-        db_query("INSERT INTO {ad_image} (aid, fid, url, tooltip, remote_image, width, height) VALUES(%d, %d, '%s', '%s', '%s', %d, %d)", $node->nid, $node->fid, $node->url, $node->tooltip, $node->remote_image, $node->width, $node->height);
+        db_query("INSERT INTO {ad_image} (aid, fid, url, tooltip, remote_image, width, height) VALUES(%d, %d, '%s', '%s', '%s', %d, %d)", $node->nid, $node->fid, $node->url, $node->tooltip, $node->remote_image, isset($node->width) ? $node->width : 0, isset($node->height) ? $node->height : 0);
       }
       else {
-        db_query("UPDATE {ad_image} SET fid = %d, url = '%s', tooltip = '%s', remote_image = '%s', width = %d, height = %d WHERE aid = %d", $fid, $node->url, $node->tooltip, $node->remote_image, $node->width, $node->height, $node->nid);
+        db_query("UPDATE {ad_image} SET fid = %d, url = '%s', tooltip = '%s', remote_image = '%s', width = %d, height = %d WHERE aid = %d", $fid, $node->url, $node->tooltip, $node->remote_image, isset($node->width) ? $node->width : 0, isset($node->height) ? $node->height : 0, $node->nid);
       }
-      if (!isset($node->remote_image) || empty($node->remote_image)) {
-        // No valid image has been uploaded, don't allow ad to be 'active'.
-        if ($image === FALSE || !ad_image_active_file(($node->files))) {
-          db_query("UPDATE {ads} SET adstatus = '%s' WHERE aid = %d AND adstatus = '%s'", t('pending'), $node->nid, t('active'));
-          if (db_affected_rows()) {
-            drupal_set_message(t('Image validation failed, unable to mark ad as %active.  Setting ad as %pending.', array('%active' => t('active'), '%pending' => t('pending'))), 'error');
-          }
+      // No valid image has been uploaded, don't allow ad to be 'active'.
+      if ($image === FALSE || !ad_image_active_file(($node->files))) {
+        db_query("UPDATE {ads} SET adstatus = '%s' WHERE aid = %d AND adstatus = '%s'", t('pending'), $node->nid, t('active'));
+        if (db_affected_rows()) {
+          drupal_set_message(t('Image validation failed, unable to mark ad as %active.  Setting ad as %pending.', array('%active' => t('active'), '%pending' => t('pending'))), 'error');
         }
-        else if (!$fid) {
-          db_query("UPDATE {ads} SET adstatus = '%s' WHERE aid = %d AND adstatus = '%s'", t('pending'), $node->nid, t('active'));
-          if (db_affected_rows()) {
-            drupal_set_message(t('Unable to mark ad as <em>active</em> until uploaded image is validated.  If you do not see any more errors, you should now be able to set your ad as <em>active</em>.'), 'error');
-          }
+      }
+      else if (!$node->remote_image && !$fid) {
+        db_query("UPDATE {ads} SET adstatus = '%s' WHERE aid = %d AND adstatus = '%s'", t('pending'), $node->nid, t('active'));
+        if (db_affected_rows()) {
+          drupal_set_message(t('Unable to mark ad as <em>active</em> until uploaded image is validated.  If you do not see any more errors, you should now be able to set your ad as <em>active</em>.'), 'error');
         }
       }
       break;
@@ -382,7 +383,7 @@
   if (isset($format[$gid])) {
     return $format[$gid];
   }
-  $format[$gid] = db_fetch_object(db_query('SELECT min_width, max_width, min_height, max_height FROM {ad_image_format} WHERE gid = %d', $gid));
+  $format[$gid] = db_fetch_object(db_query('SELECT min_width, max_width, min_height, max_height, max_size FROM {ad_image_format} WHERE gid = %d', $gid));
   return $format[$gid];
 }
 
@@ -405,21 +406,26 @@
     }
     foreach ($terms as $tid => $term) {
       list($size->width, $size->height) = getimagesize($file->filepath);
+      $size->bytes = strlen(join('', file($file->filepath)));
       if ($format = ad_image_format_load($tid)) {
         if ($size->width < $format->min_width) {
-          drupal_set_message(t('The image <em>%name</em> is only %current pixels wide, which is less than the minimum of %minimum pixels allowed in the %group ad group.', array('%name' => $file->filename, '%current' => $size->width, '%minimum' => $format->min_width, '%group' => theme_placeholder($term->name))), 'error');
+          drupal_set_message(t('The image %name is only %current pixels wide, which is less than the minimum of %minimum pixels allowed in the %group ad group.', array('%name' => $file->filename, '%current' => $size->width, '%minimum' => $format->min_width, '%group' => isset($term->name) ? $term->name : t('default'))), 'error');
           $error = TRUE;
         }
         else if ($format->max_width && ($size->width > $format->max_width)) {
-          drupal_set_message(t('The image <em>%name</em> is %current pixels wide, which is more than the maximum of %maximum pixels allowed in the %group ad group.', array('%name' => $file->filename, '%current' => $size->width, '%maximum' => $format->max_width, '%group' => theme_placeholder($term->name))), 'error');
+          drupal_set_message(t('The image %name is %current pixels wide, which is more than the maximum of %maximum pixels allowed in the %group ad group.', array('%name' => $file->filename, '%current' => $size->width, '%maximum' => $format->max_width, '%group' => isset($term->name) ? $term->name : t('default'))), 'error');
           $error = TRUE;
         }
         if ($size->height < $format->min_height) {
-          drupal_set_message(t('The image <em>%name</em> is only %current pixels high, which is less than the minimum of %minimum pixels allowed in the %group ad group.', array('%name' => $file->filename, '%current' => $size->height, '%minimum' => $format->min_height, '%group' => theme_placeholder($term->name))), 'error');
+          drupal_set_message(t('The image %name is only %current pixels high, which is less than the minimum of %minimum pixels allowed in the %group ad group.', array('%name' => $file->filename, '%current' => $size->height, '%minimum' => $format->min_height, '%group' => isset($term->name) ? $term->name : t('default'))), 'error');
           $error = TRUE;
         }
         else if ($format->max_height && $size->height > $format->max_height) {
-          drupal_set_message(t('The image <em>%name</em> is %current pixels high, which is more than the maximum of %maximum pixels allowed in the %group ad group.', array('%name' => $file->filename, '%current' => $size->height, '%maximum' => $format->max_height, '%group' => theme_placeholder($term->name))), 'error');
+          drupal_set_message(t('The image %name is %current pixels high, which is more than the maximum of %maximum pixels allowed in the %group ad group.', array('%name' => $file->filename, '%current' => $size->height, '%maximum' => $format->max_height, '%group' => isset($term->name) ? $term->name : t('default'))), 'error');
+          $error = TRUE;
+        }
+        if ($format->max_size && $size->bytes > $format->max_size) {
+          drupal_set_message(t('The image %name is %current bytes in size, which is more than the maximum of %maximum bytes allowed in the %group ad group.', array('%name' => $file->filename, '%current' => $size->bytes, '%maximum' => $format->max_size, '%group' => isset($term->name) ? $term->name : t('default'))), 'error');
           $error = TRUE;
         }
       }
@@ -441,7 +447,15 @@
  * Returns image object from given ad node.
  */
 function ad_image_load_image($node) {
-  if (isset($node->files) && is_array($node->files)) {
+  if (isset($node->remote_image) && !empty($node->remote_image)) {
+    $file->filename = $node->remote_image;
+    $file->filepath = $node->remote_image;
+    $image = ad_image_validate_size($file, $node->nid);
+    if ($image !== FALSE) {
+      return $image;
+    }
+  }
+  else if (isset($node->files) && is_array($node->files)) {
     foreach ($node->files as $file) {
       if (is_array($file)) {
         if ($file['list'] && file_exists($file['filepath'])) {
@@ -481,8 +495,13 @@
   );
 
   if (!empty($node->remote_image)) {
-    list($image->width, $image->height) = getimagesize($node->remote_image);
+    $file->filename = $node->remote_image;
+    $file->filepath = $node->remote_image;
+    $image = ad_image_validate_size($file, $node->nid);
     $path = '<img src="'. $node->remote_image .'" alt="'. t('image') .'" /> ';
+    if ($image === FALSE) {
+      $path .= t('(invalid image)'). '<br />';
+    }
   }
   else if (isset($node->files)) {
     $files = $node->files;
--- a/imageserve.inc	Thu Apr 02 15:28:21 2009 +0000
+++ b/imageserve.inc	Wed Apr 15 07:58:32 2009 +0000
@@ -1,5 +1,5 @@
 <?php
-// $Id: imageserve.inc,v 1.1.2.8.2.2 2009/02/16 17:06:47 jeremy Exp $
+// $Id: imageserve.inc,v 1.1.2.8.2.2.2.1 2009/04/09 14:06:27 jeremy Exp $
 
 /**
  * @file
@@ -17,12 +17,16 @@
   adserve_variable('variable_load');
   adserve_bootstrap(0);
 
-  $ad->aid = adserve_variable('aid');
-  if ($ad->aid) {
-    adserve_increment($ad);
+  if (adserve_variable('aid')) {
+    $ad->aid = adserve_variable('aid');
+  }
+  if (isset($ad->aid) && $ad->aid) {
+    _debug_echo("adserve_counter_image: increment 'view' counter for aid: $ad->aid");
+    adserve_cache('increment', 'view', $ad->aid);
   }
   else {
-    adserve_increment($ad, 'count');
+    _debug_echo("adserve_counter_image: increment 'count' counter for no aid");
+    adserve_cache('increment', 'count', NULL);
   }
 
   if (function_exists('imagecreate')) {
--- a/notify/ad_notify.info	Thu Apr 02 15:28:21 2009 +0000
+++ b/notify/ad_notify.info	Wed Apr 15 07:58:32 2009 +0000
@@ -6,9 +6,9 @@
 description = Receive email notifications regarding ads.
 core = 6.x
 
-; Information added by drupal.org packaging script on 2009-03-31
-version = "6.x-2.0-beta5"
+; Information added by drupal.org packaging script on 2009-04-14
+version = "6.x-2.0-beta6"
 core = "6.x"
 project = "ad"
-datestamp = "1238475303"
+datestamp = "1239719705"
 
--- a/notify/ad_notify.module	Thu Apr 02 15:28:21 2009 +0000
+++ b/notify/ad_notify.module	Wed Apr 15 07:58:32 2009 +0000
@@ -1,5 +1,5 @@
 <?php
-// $Id: ad_notify.module,v 1.1.2.2.2.13.2.6.2.6 2009/03/29 20:17:21 jeremy Exp $
+// $Id: ad_notify.module,v 1.1.2.2.2.13.2.6.2.7 2009/04/02 14:11:50 jeremy Exp $
 
 /**
  * @file
@@ -551,7 +551,7 @@
       // Default message text.
       $mail = array(
         'subject' => t('[%site-name ad] %event notification'),
-        'body' => t("Hello %owner_name,\n\n  This is an automatically generated notification about your advertisement \"%title\" that is being displayed on the %site-name website.\n\n  Your advertisement has been viewed %today_views times and clicked %today_clicks times today.  It was viewed %yesterday_views times and clicked %yesterday_clicks times yesterday.  It has been viewed %global_views times and clicked %global_clicks times since it was activated on %activated_large.\n\n  You will receive this %frequency  You can view additional statistics about this advertisement or update this notification at the following url:\n    %url\n\nRegards,\n The %site-name Team\n\n-\n%site-url"),
+        'body' => t("Hello %owner_name,\n\n  This is an automatically generated notification about your advertisement \"%title\" that is being displayed on the %site-name website.\n\n  Your advertisement has been viewed %today_impressions times and clicked %today_clicks times today.  It was viewed %yesterday_impressions times and clicked %yesterday_clicks times yesterday.  It has been viewed %global_impressions times and clicked %global_clicks times since it was activated on %activated_large.\n\n  You will receive this %frequency  You can view additional statistics about this advertisement or update this notification at the following url:\n    %url\n\nRegards,\n The %site-name Team\n\n-\n%site-url"),
       );
     }
     db_query("INSERT INTO {ad_notify} (aid, oid, event, delay, expire, locked, status, address, subject, body, roles) VALUES(%d, %d, '%s', %d, %d, %d, %d, '%s', '%s', '%s', '%s')", $form_state['values']['aid'], $form_state['values']['oid'], $form_state['values']['event'], $form_state['values']['delay'], $form_state['values']['expire'], $form_state['values']['locked'], AD_NOTIFY_ENABLED, isset($form_state['values']['address']) ? $form_state['values']['address'] : '', $mail['subject'], $mail['body'], isset($form_state['values']['roles']) ? serialize($form_state['values']['roles']) : '');
--- a/owners/ad_owners.info	Thu Apr 02 15:28:21 2009 +0000
+++ b/owners/ad_owners.info	Wed Apr 15 07:58:32 2009 +0000
@@ -5,9 +5,9 @@
 description = Enhances the ad module to support ad owners.
 core = 6.x
 
-; Information added by drupal.org packaging script on 2009-03-31
-version = "6.x-2.0-beta5"
+; Information added by drupal.org packaging script on 2009-04-14
+version = "6.x-2.0-beta6"
 core = "6.x"
 project = "ad"
-datestamp = "1238475303"
+datestamp = "1239719705"
 
--- a/owners/ad_owners.module	Thu Apr 02 15:28:21 2009 +0000
+++ b/owners/ad_owners.module	Wed Apr 15 07:58:32 2009 +0000
@@ -1,5 +1,5 @@
 <?php
-// $Id: ad_owners.module,v 1.1.2.8.2.6 2009/03/31 04:41:03 jeremy Exp $
+// $Id: ad_owners.module,v 1.1.2.8.2.8 2009/03/31 21:01:31 jeremy Exp $
 
 /**
  * @file
@@ -560,7 +560,7 @@
 function ad_owners_permission($aid, $string, $account) {
   static $permissions = array();
 
-  if (!isset($permissions[$aid][$account->uid])) {
+  if (!isset($permissions[$aid]) || !isset($permissions[$aid][$account->uid])) {
     $oid = db_result(db_query("SELECT oid FROM {ad_owners} WHERE aid = %d and uid = %d", $aid, $account->uid));
     if ($oid) {
       $permissions[$aid][$account->uid] = explode('|,|', db_result(db_query("SELECT permissions FROM {ad_permissions} WHERE oid = %d", $oid)));
@@ -571,6 +571,9 @@
         $perms = ad_owners_default_permissions();
         $permissions[$aid][$account->uid] = $perms['default'];
       }
+      else {
+        $permissions[$aid][$account->uid] = array();
+      }
     }
   }
 
--- a/remote/ad_remote.info	Thu Apr 02 15:28:21 2009 +0000
+++ b/remote/ad_remote.info	Wed Apr 15 07:58:32 2009 +0000
@@ -5,9 +5,9 @@
 description = Generates cut-and-paste source snippets allowing ads to be easily displayed on remote websites.
 core = 6.x
 
-; Information added by drupal.org packaging script on 2009-03-31
-version = "6.x-2.0-beta5"
+; Information added by drupal.org packaging script on 2009-04-14
+version = "6.x-2.0-beta6"
 core = "6.x"
 project = "ad"
-datestamp = "1238475303"
+datestamp = "1239719705"
 
--- a/report/ad_report.info	Thu Apr 02 15:28:21 2009 +0000
+++ b/report/ad_report.info	Wed Apr 15 07:58:32 2009 +0000
@@ -5,9 +5,9 @@
 description = Provides comprehensive charts and reports about advertising statistics.
 core = 6.x
 
-; Information added by drupal.org packaging script on 2009-03-31
-version = "6.x-2.0-beta5"
+; Information added by drupal.org packaging script on 2009-04-14
+version = "6.x-2.0-beta6"
 core = "6.x"
 project = "ad"
-datestamp = "1238475303"
+datestamp = "1239719705"
 
--- a/statistics/click_filter/click_filter.info	Thu Apr 02 15:28:21 2009 +0000
+++ b/statistics/click_filter/click_filter.info	Wed Apr 15 07:58:32 2009 +0000
@@ -4,9 +4,9 @@
 dependencies[] = ad
 description = Filter duplicate click statistics.
 core = 6.x
-; Information added by drupal.org packaging script on 2009-03-31
-version = "6.x-2.0-beta5"
+; Information added by drupal.org packaging script on 2009-04-14
+version = "6.x-2.0-beta6"
 core = "6.x"
 project = "ad"
-datestamp = "1238475303"
+datestamp = "1239719705"
 
--- a/text/ad_text.info	Thu Apr 02 15:28:21 2009 +0000
+++ b/text/ad_text.info	Wed Apr 15 07:58:32 2009 +0000
@@ -4,9 +4,9 @@
 dependencies[] = ad
 description = Enhances the ad module to support static text ads.
 core = 6.x
-; Information added by drupal.org packaging script on 2009-03-31
-version = "6.x-2.0-beta5"
+; Information added by drupal.org packaging script on 2009-04-14
+version = "6.x-2.0-beta6"
 core = "6.x"
 project = "ad"
-datestamp = "1238475303"
+datestamp = "1239719705"
 
--- a/weight/probability/ad_weight_probability.info	Thu Apr 02 15:28:21 2009 +0000
+++ b/weight/probability/ad_weight_probability.info	Wed Apr 15 07:58:32 2009 +0000
@@ -5,9 +5,9 @@
 description = Allow admin to adjust the probability that an ad will be displayed.
 core = 6.x
 
-; Information added by drupal.org packaging script on 2009-03-31
-version = "6.x-2.0-beta5"
+; Information added by drupal.org packaging script on 2009-04-14
+version = "6.x-2.0-beta6"
 core = "6.x"
 project = "ad"
-datestamp = "1238475303"
+datestamp = "1239719705"