diff --git actions/ad_actions.module actions/ad_actions.module
index 4734b62..29c1c7d 100644
--- actions/ad_actions.module
+++ actions/ad_actions.module
@@ -414,7 +414,8 @@ function _ad_actions_email_tokens_form($context) {
     '#description' => t("The following placeholder tokens can be used in to generate the URL path. Some tokens may not be available, depending on the context in which the action is triggered."),
   );
   $form['help']['tokens'] = array(
-    '#value' => theme('token_help', 'all'),
+    '#theme' => 'token_tree',
+    '#token_types' => 'all',
   );
   return $form;
 }
diff --git ad.admin.inc ad.admin.inc
index 1f55ec9..8d12cf2 100644
--- ad.admin.inc
+++ ad.admin.inc
@@ -14,12 +14,12 @@
 function ad_admin_list() {
   _ad_check_installation();
 
-  $output = drupal_get_form('ad_filter_form');
+  $output['filter'] = drupal_get_form('ad_filter_form');
 
   if (isset($_POST['operation']) && ($_POST['operation'] == 'delete') && isset($_POST['ads'])) {
     return drupal_get_form('ad_multiple_delete_confirm');
   }
-  $output .= drupal_get_form('ad_admin_ads');
+  $output['admin'] = drupal_get_form('ad_admin_ads');
 
   return $output;
 }
@@ -28,8 +28,17 @@ function ad_admin_list() {
  * Provide a filterable list of advertisements.
  */
 function ad_admin_ads() {
-  $filter = ad_build_filter_query();
-  $result = pager_query('SELECT a.*, n.* FROM {ads} a INNER JOIN {node} n ON a.aid = n.nid '. $filter['join'] .' '. $filter['where'] .' ORDER BY n.changed DESC', 50, 0, NULL, $filter['args']);
+  $query = db_select('ads', 'a')
+    ->fields('a')
+    ->extend('PagerDefault')
+    ->limit(50);
+  $query->innerJoin('node', 'n', 'a.aid = n.nid');
+  $query->fields('n');
+  $query->orderBy('n.changed', 'DESC');
+
+  ad_build_filter_query($query);
+
+  $result = $query->execute();
 
   $form['options'] = array('#type' => 'fieldset',
     '#title' => t('Update options'),
@@ -45,16 +54,16 @@ function ad_admin_ads() {
 
   $destination = drupal_get_destination();
   $ads = array();
-  while ($ad = db_fetch_object($result)) {
+  foreach ($result as $ad) {
     $ads[$ad->aid] = '';
-    $form['title'][$ad->aid] = array('#value' => l($ad->title, 'node/'. $ad->aid));
-    $form['group'][$ad->aid] = array('#value' => _ad_get_group($ad->aid));
-    $form['adtype'][$ad->aid] = array('#value' => t(check_plain($ad->adtype)));
-    $form['adstatus'][$ad->aid] = array('#value' => t(check_plain($ad->adstatus)));
-    $form['operations'][$ad->aid] = array('#value' => l(t('edit'), 'node/'. $ad->aid .'/edit', array('query' => $destination)));
+    $form['title'][$ad->aid] = array('#markup' => l($ad->title, 'node/' . $ad->aid));
+    $form['group'][$ad->aid] = array('#markup' => _ad_get_group($ad->aid));
+    $form['adtype'][$ad->aid] = array('#markup' => check_plain($ad->adtype));
+    $form['adstatus'][$ad->aid] = array('#markup' => check_plain($ad->adstatus));
+    $form['operations'][$ad->aid] = array('#markup' => l(t('edit'), 'node/' . $ad->aid . '/edit', array('query' => $destination)));
   }
   $form['ads'] = array('#type' => 'checkboxes', '#options' => $ads);
-  $form['pager'] = array('#value' => theme('pager', NULL, 50, 0));
+  $form['pager'] = array('#value' => theme('pager', array('tags' => NULL, 'limit' => 50, 'element' => 0)));
   return $form;
 }
 
@@ -106,10 +115,15 @@ function ad_ad_operations() {
  * TODO: Publish/unpublish nodes when appropriate.
  */
 function ad_operations_callback($ads, $action) {
-  $placeholders = implode(',', array_fill(0, count($ads), '%d'));
-  db_query("UPDATE {ads} SET adstatus = '". $action ."' WHERE aid IN(". $placeholders .')', $ads);
-  foreach ($ads as $aid) {
-    $node = node_load($aid);
+  db_update('ads')
+    ->fields(array(
+      'adstatus' => $action,
+    ))
+    ->condition('aid', $ads)
+    ->execute();
+  $nodes = node_load_multiple($ads);
+  foreach ($nodes as $node) {
+    $aid = $node->nid;
     ad_statistics_increment($aid, 'update');
     ad_statistics_increment($aid, $action);
     // Allow ad type module to act on nodeapi events.  The adapi hook provides
@@ -117,7 +131,7 @@ function ad_operations_callback($ads, $action) {
     if (isset($node->adtype)) {
       // Don't use module_invoke, as in pre-PHP5 the changes to $node won't be
       // passed back.
-      $function = "ad_$node->adtype" .'_adapi';
+      $function = "ad_{$node->adtype}_adapi";
       if (function_exists($function)) {
         $function('update', $node);
       }
@@ -125,7 +139,7 @@ function ad_operations_callback($ads, $action) {
     // Allow ad cache module to act on nodeapi events.
     $cache = variable_get('ad_cache', 'none');
     if ($cache != 'none') {
-      $function = "ad_cache_$cache" .'_adcacheapi';
+      $function = "ad_cache_{$cache}_adcacheapi";
       if (function_exists($function)) {
         $function($action, $node);
       }
@@ -139,9 +153,12 @@ function ad_operations_callback($ads, $action) {
 function ad_multiple_delete_confirm($form_state) {
   $form['ads'] = array('#prefix' => '<ul>', '#suffix' => '</ul>', '#tree' => TRUE);
   // array_filter returns only elements with TRUE values
-  foreach (array_filter($form_state['post']['ads']) as $aid => $value) {
-    $title = db_result(db_query('SELECT title FROM {node} WHERE nid = %d', $aid));
-    $form['ads'][$aid] = array('#type' => 'hidden', '#value' => $aid, '#prefix' => '<li>', '#suffix' => check_plain($title) ."</li>\n");
+  foreach (array_filter($form_state['values']['ads']) as $aid => $value) {
+    $title = db_select('node')
+      ->fields('node', array('title'))
+      ->condition('nid', $aid)
+      ->execute()->fetchField();
+    $form['ads'][$aid] = array('#type' => 'hidden', '#value' => $aid, '#prefix' => '<li>', '#suffix' => check_plain($title) . "</li>\n");
   }
   $form['operation'] = array('#type' => 'hidden', '#value' => 'delete');
 
@@ -167,7 +184,8 @@ function ad_multiple_delete_confirm_submit($form, &$form_state) {
 /**
  * Theme ad administration overview.
  */
-function theme_ad_admin_ads($form) {
+function theme_ad_admin_ads($variables) {
+  $form = $variables['form'];
   // Overview table:
   $header = array(theme('table_select_header_cell'), t('Title'), t('Group'), t('Type'), t('Status'), t('Operations'));
 
@@ -183,18 +201,18 @@ function theme_ad_admin_ads($form) {
       $row[] = drupal_render($form['operations'][$key]);
       $rows[] = $row;
     }
-
   }
   else  {
     $rows[] = array(array('data' => t('No ads available.'), 'colspan' => '6'));
   }
 
-  $output .= theme('table', $header, $rows);
+  $output .= theme('table', array('header' => $header, 'rows' => $rows));
   if ($form['pager']['#value']) {
     $output .= drupal_render($form['pager']);
   }
 
-  $output .= drupal_render($form);
+  // TODO fix recursive loop here?
+  //$output .= drupal_render($form);
 
   return $output;
 }
@@ -236,28 +254,35 @@ function ad_admin_ads_submit($form, &$form_state) {
 /**
  * Build query for ad administration filters based on session.
  */
-function ad_build_filter_query() {
+function ad_build_filter_query(SelectQueryInterface $query) {
   $filters = ad_filters();
 
   // Build query
-  $where = $args = array();
-  $join = '';
   foreach ($_SESSION['ad_overview_filter'] as $index => $filter) {
     list($key, $value) = $filter;
     switch ($key) {
       case 'status':
         list($value, $key) = explode('-', $value, 2);
         $op = $key == 1 ? '=' : '!=';
-        $where[] = "a.adstatus $op '%s'";
+        $query->condition('a.adstatus', $value, $op);
         break;
       case 'group':
-        $table = "tn$index";
-        $where[] = "$table.tid = %d";
-        $join .= "INNER JOIN {term_node} $table ON n.nid = $table.nid ";
+        // Query entity tables
+        $query = new EntityFieldQuery;
+        $entities = $query
+          ->entityCondition('entity_type', 'node')
+          ->fieldCondition('ad_group', 'tid', $value)
+          ->execute();
+        // limit by entities with this tid
+        $query->condition('aid', array_keys($entities['node']));
         break;
       case 'type':
-        $where[] = "a.adtype = '%s'";
+        $query->condition('a.adtype', $value);
+        break;
       default:
+        continue;
+        // TODO allow other modules to filter?
+        /*
         $return = module_invoke_all('adapi', 'admin_filter_query', $filter);
         foreach ($return as $module => $funcs) {
           if (isset($funcs['where'])) {
@@ -271,12 +296,9 @@ function ad_build_filter_query() {
           }
         }
         break;
+        */
     }
-    $args[] = $value;
   }
-  $where = count($where) ? 'WHERE '. implode(' AND ', $where) : '';
-
-  return array('where' => $where, 'join' => $join, 'args' => $args);
 }
 
 /**
@@ -328,21 +350,22 @@ function ad_filters() {
 /**
  * Theme ad administration filter selector.
  */
-function theme_ad_filters($form) {
+function theme_ad_filters($variables) {
+  $form = $variables['form'];
   $output = '<ul class="clear-block">';
   if (isset($form['current']) && sizeof($form['current'])) {
     foreach (element_children($form['current']) as $key) {
-      $output .= '<li>'. drupal_render($form['current'][$key]) .'</li>';
+      $output .= '<li>' . drupal_render($form['current'][$key]) . '</li>';
     }
   }
 
-  $output .= '<li><dl class="multiselect">'. (isset($form['current']) && sizeof($form['current']) ? '<dt><em>'. t('and') .'</em> '. t('where') .'</dt>' : '') .'<dd class="a">';
+  $output .= '<li><dl class="multiselect">' . (isset($form['current']) && sizeof($form['current']) ? '<dt><em>' . t('and') . '</em> ' . t('where') . '</dt>' : '') . '<dd class="a">';
   foreach (element_children($form['filter']) as $key) {
     $output .= drupal_render($form['filter'][$key]);
   }
   $output .= '</dd>';
 
-  $output .= '<dt>'. t('is') .'</dt><dd class="b">';
+  $output .= '<dt>' . t('is') . '</dt><dd class="b">';
 
   if (isset($form['status'])) {
     foreach (element_children($form['status']) as $key) {
@@ -352,7 +375,7 @@ function theme_ad_filters($form) {
   $output .= '</dd>';
 
   $output .= '</dl>';
-  $output .= '<div class="container-inline" id="ad-admin-buttons">'. drupal_render($form['buttons']) .'</div>';
+  $output .= '<div class="container-inline" id="ad-admin-buttons">' . drupal_render($form['buttons']) . '</div>';
   $output .= '</li></ul>';
 
   return $output;
@@ -378,19 +401,19 @@ function ad_filter_form($form_state) {
       $value = module_invoke('taxonomy', 'get_term', $value);
       $value = $value->name;
     }
-    else if ($type == 'status') {
+    elseif ($type == 'status') {
       $value = $filters['status']['options'][$value];
     }
     else {
       $value = $filters[$type]['options'][$value];
     }
     $string = ($i++ ? '<em>and</em> where <strong>%a</strong> is <strong>%b</strong>' : '<strong>%a</strong> is <strong>%b</strong>');
-    $form['filters']['current'][] = array('#value' => t($string, array('%a' => $filters[$type]['title'] , '%b' => $value)));
+    $form['filters']['current'][] = array('#markup' => t($string, array('%a' => $filters[$type]['title'] , '%b' => $value)));
     if ($type == 'type') {
       // Remove the type option if it is already being filtered on.
       unset($filters['type']);
     }
-    else if ($type == 'group') {
+    elseif ($type == 'group') {
       unset($filters['group']);
     }
     if ($type == 'status') {
@@ -409,7 +432,7 @@ function ad_filter_form($form_state) {
             // two opposite keys will always return 0 results.
             $inverse = $key == 1 ? 0 : 1;
             unset($filters['status']['options'][$option[1]]);
-            unset($filters['status']['options'][$value .'-'. $inverse]);
+            unset($filters['status']['options'][$value . '-' . $inverse]);
           }
         }
       }
@@ -435,11 +458,12 @@ function ad_filter_form($form_state) {
 /**
  * Theme ad administration filter form.
  */
-function theme_ad_filter_form($form) {
+function theme_ad_filter_form($variables) {
+  $form = $variables['form'];
   $output  = '<div id="ad-admin-filter">';
   $output .= drupal_render($form['filters']);
   $output .= '</div>';
-  $output .= drupal_render($form);
+  //$output .= drupal_render($form);
   return $output;
 }
 
@@ -491,7 +515,10 @@ function ad_admin_configure_settings($form_state) {
   );
   $form['configuration']['adserve'] = array(
     '#type' => 'markup',
-    '#value' => t('Using detected adserve scripts: %adserve, %adserveinc', array('%adserve' => ($adserve ? $adserve : t('not found')), '%adserveinc' => ($adserveinc ? $adserveinc : t('not found')))),
+    '#markup' => t('Using detected adserve scripts: %adserve, %adserveinc', array(
+      '%adserve' => $adserve ? $adserve : t('not found'),
+      '%adserveinc' => $adserveinc ? $adserveinc : t('not found'),
+    )),
   );
 
   $form['general'] = array(
@@ -524,13 +551,14 @@ function ad_admin_configure_settings($form_state) {
   );
 
   // Provide hook for ad_display_TYPE modules to set display TYPE.
-  $display_options = array_merge(array('javascript' => t('JavaScript'), 'jquery' => t('jQuery'), 'iframe' => t('IFrame'), 'raw' => t('Raw')), module_invoke_all('displayapi', 'display_method'), array());
+  $display_options = array('javascript' => t('JavaScript'), 'jquery' => t('jQuery'), 'iframe' => t('IFrame'), 'raw' => t('Raw'));
+  $display_options = array_merge($display_options, module_invoke_all('displayapi', 'display_method'), array());
 
   // Provide hook for ad_display_TYPE modules to define inline description.
   $description = t('This setting configures the default method for displaying advertisements on your website.  It is possible to override this setting when making direct calls to ad(), as described in the documentation.  Using the JavaScript, jQuery, and IFrame display methods allows you to display random ads and track impressions even on cached pages.  When using the Raw display method together with Drupal\'s page cache, impressions will be properly tracked but advertisements will only change when the page cache is updated.');
   $return = module_invoke_all('displayapi', 'display_description', array());
   foreach ($return as $describe) {
-    $description .= ' '. $describe;
+    $description .= ' ' . $describe;
   }
 
   $form['general']['ad_display'] = array(
@@ -620,7 +648,7 @@ function ad_admin_configure_settings($form_state) {
   $description = t('A cache can be used to efficiently track how many times advertisements are displayed and clicked.');
   $return = module_invoke_all('adcacheapi', 'description', array());
   foreach ($return as $describe) {
-    $description .= ' '. $describe;
+    $description .= ' ' . $describe;
   }
 
   $form['cache']['ad_cache'] = array(
@@ -634,12 +662,10 @@ function ad_admin_configure_settings($form_state) {
   // Provide hook for ad_cache_TYPE modules to add inline settings.
   $form['cache'] = array_merge($form['cache'], module_invoke_all('adcacheapi', 'settings'));
 
-  $form['save'] = array(
-    '#type' => 'submit',
-    '#value' => t('Save'),
-  );
+  $form['#validate'][] = 'ad_admin_configure_settings_validate';
+  $form['#submit'][] = 'ad_admin_configure_settings_submit';
 
-  return $form;
+  return system_settings_form($form);
 }
 
 /**
@@ -659,20 +685,9 @@ function ad_admin_configure_settings_validate($form, &$form_state) {
  * Save updated values from settings form.
  */
 function ad_admin_configure_settings_submit($form, &$form_state) {
-  variable_set('ad_link_target', $form_state['values']['ad_link_target']);
-  variable_set('ad_link_nofollow', $form_state['values']['ad_link_nofollow']);
-  variable_set('ad_cache', $form_state['values']['ad_cache']);
-  variable_set('ad_display', $form_state['values']['ad_display']);
-  variable_set('ad_validate_url', $form_state['values']['ad_validate_url']);
-  variable_set('ad_no_search', $form_state['values']['ad_no_search']);
-  variable_set('ad_meta_noindex', $form_state['values']['ad_meta_noindex']);
-  variable_set('ad_iframe_frameborder', $form_state['values']['ad_iframe_frameborder']);
-  variable_set('ad_iframe_scroll', $form_state['values']['ad_iframe_scroll']);
-  variable_set('ad_iframe_width', $form_state['values']['ad_iframe_width']);
-  variable_set('ad_iframe_height', $form_state['values']['ad_iframe_height']);
   if (($cache = variable_get('ad_cache', 'none')) != 'none') {
     // Allow external cache types to store their settings
-    module_invoke('ad_cache_'. $cache, 'adcacheapi', 'settings_submit', $form_state['values']);
+    module_invoke('ad_cache_' . $cache, 'adcacheapi', 'settings_submit', $form_state['values']);
   }
 /*
  // TODO: Write an external display module and implement this.
@@ -690,12 +705,7 @@ function ad_admin_configure_settings_submit($form, &$form_state) {
 function ad_no_global_settings($form_state) {
   $form = array();
 
-  $form['save'] = array(
-    '#type' => 'submit',
-    '#value' => t('Save'),
-  );
-
-  return $form;
+  return system_settings_form($form);
 }
 
 function ad_admin_groups_list() {
@@ -722,8 +732,8 @@ function ad_admin_groups_list() {
     $rows[] = array(array('data' => t('No groups have been created.'), 'colspan' => 3));
   }
 
-  $output = theme('table', $header, $rows);
-  $output .= theme('pager', NULL, 15, 0);
+  $output = theme('table', array('header' => $header, 'rows' => $rows));
+  $output .= theme('pager');
 
   return $output;
 }
@@ -731,7 +741,7 @@ function ad_admin_groups_list() {
 /**
  * Returns a form for adding an ad group.
  */
-function ad_admin_group_form($form_state, $group = NULL) {
+function ad_admin_group_form($form, $form_state, $group = NULL) {
   $form['name'] = array(
     '#type' => 'textfield',
     '#title' => t('Group name'),
@@ -791,7 +801,7 @@ function ad_admin_group_form($form_state, $group = NULL) {
  */
 function ad_admin_group_form_validate($form, &$form_state) {
   if ($form_state['values']['op'] == t('Delete')) {
-    drupal_goto('admin/content/ad/groups/'. $form_state['values']['tid'] .'/delete');
+    drupal_goto('admin/content/ad/groups/' . $form_state['values']['tid'] . '/delete');
   }
 }
 
@@ -800,7 +810,7 @@ function ad_admin_group_form_validate($form, &$form_state) {
  * Save a newly created ad group.
  */
 function ad_admin_group_form_submit($form, &$form_state) {
-  $status = taxonomy_save_term($form_state['values']);
+  $status = taxonomy_term_save((object) $form_state['values']);
   switch ($status) {
     case SAVED_NEW:
       $groups = variable_get('ad_groups', array());
@@ -817,7 +827,7 @@ function ad_admin_group_form_submit($form, &$form_state) {
 /**
  * Returns a confirmation page when deleting an ad group and all of its ads.
  */
-function ad_confirm_group_delete($form_state, $group = NULL) {
+function ad_confirm_group_delete($form, $form_state, $group = NULL) {
   $form['tid'] = array(
     '#type' => 'value',
     '#value' => $group->tid,
@@ -840,7 +850,7 @@ function ad_confirm_group_delete($form_state, $group = NULL) {
  * Delete ad group.
  */
 function ad_confirm_group_delete_submit($form, &$form_state) {
-  taxonomy_del_term($form_state['values']['tid']);
+  taxonomy_term_delete($form_state['values']['tid']);
   drupal_set_message(t('The ad group %term has been deleted.', array('%term' => $form_state['values']['name'])));
   watchdog('ad', 'mailarchive: deleted %term ad group.', array('%term' => $form_state['values']['name']));
 
diff --git ad.info ad.info
index c0c9fd6..0fb8977 100644
--- ad.info
+++ ad.info
@@ -2,4 +2,4 @@ name = Ad
 package = Ad
 dependencies[] = taxonomy
 description = An advertising system for Drupal powered websites.
-core = 6.x
\ No newline at end of file
+core = 7.x
diff --git ad.install ad.install
index 7f241d6..872e06a 100644
--- ad.install
+++ ad.install
@@ -303,33 +303,120 @@ function ad_schema() {
 }
 
 /**
- * Ad module installation.
- */
-function ad_install() {
-  // Create tables.
-  drupal_install_schema('ad');
-}
-
-/**
  * Allow complete uninstallation of the ad module.
  */
 function ad_uninstall() {
   // Delete all ad content.
-  $result = db_query("SELECT nid FROM {node} WHERE type = 'ad'");
-  while ($node = db_fetch_object($result)) {
-    node_delete($node->nid);
+  $result = db_query("SELECT nid FROM {node} WHERE type = ?", array('ad'));
+  $nodes = array();
+  foreach ($result as $node) {
+    $nodes[] = $node->nid;
     variable_del("ad_autoactivate_warning_$node->nid");
   }
+  // node_delete($nid) calls node_delete_multiple(array($nid))
+  node_delete_multiple($nodes);
 
   // Delete all remaining ad module variables.
   $variables = array('ad_cron_timestamp', 'ad_link_target', 'ad_cache', 'ad_cache_file', 'adserve', 'ad_group_vid', 'ad_groups', 'ad_validate_url', 'ad_display');
   foreach ($variables as $variable) {
     variable_del($variable);
   }
-  db_query("DELETE FROM {variable} WHERE name LIKE 'ad_block_quantity_%'");
+  db_query("DELETE FROM {variable} WHERE name LIKE ?", array('ad_block_quantity_%'));
+}
+
+/**
+ * Implements hook_enable().
+ */
+function ad_enable() {
+  // Configure the group taxonomy term field.
+  _ad_term_field_create_instance('ad_group', 'node', 'ad', t('Group'), 0);
+}
+
+/**
+ * Creates a required, locked instance of a term field on the specified bundle.
+ *
+ * @param $field_name
+ *   The name of the field; if it already exists, a new instance of the existing
+ *     field will be created.
+ * @param $entity_type
+ *   The type of entity the field instance will be attached to.
+ * @param $bundle
+ *   The bundle name of the entity the field instance will be attached to.
+ * @param $label
+ *   The label of the field instance.
+ * @param $weight
+ *   The default weight of the field instance widget and display.
+ * @param $display
+ *   An array of default display data used for the entity's current view modes.
+ */
+function _ad_term_field_create_instance($field_name, $entity_type, $bundle, $label, $weight = 0, $display = array()) {
+  // If a field type we know should exist isn't found, clear the Field cache.
+  if (!field_info_field_types('taxonomy_term_reference')) {
+    field_cache_clear();
+  }
 
-  // Remove tables.
-  drupal_uninstall_schema('ad');
+  // Look for or add the specified field to the requested entity bundle.
+  $field = field_info_field($field_name);
+  $instance = field_info_instance($entity_type, $field_name, $bundle);
+
+  if (empty($field)) {
+    // configure the taxonomy vocabulary
+    $vocabulary = taxonomy_vocabulary_load(_ad_get_vid());
+
+    $field = array(
+      'field_name' => $field_name,
+      'type' => 'taxonomy_term_reference',
+      'cardinality' => FIELD_CARDINALITY_UNLIMITED,
+      'entity_types' => array($entity_type),
+      'translatable' => FALSE,
+      'locked' => TRUE,
+      'settings' => array(
+        'allowed_values' => array(
+          array(
+            'vocabulary' => $vocabulary->machine_name,
+            'parent' => 0,
+          ),
+        ),
+      ),
+    );
+    $field = field_create_field($field);
+  }
+
+  if (empty($instance)) {
+    $instance = array(
+      'field_name' => $field_name,
+      'entity_type' => $entity_type,
+      'bundle' => $bundle,
+
+      'label' => $label,
+      'required' => FALSE,
+      'settings' => array(),
+
+      'widget' => array(
+        'type' => 'options_select',
+        'weight' => $weight,
+        'settings' => array(),
+      ),
+
+      'display' => array(),
+    );
+
+    $entity_info = entity_get_info($entity_type);
+
+    // Spoof the default view mode so its display type is set.
+    $entity_info['view modes']['default'] = array();
+
+    foreach ($entity_info['view modes'] as $view_mode => $data) {
+      $instance['display'][$view_mode] = $display + array(
+        'label' => 'hidden',
+        'type' => 'taxonomy_term_reference_link',
+        'settings' => array(),
+        'weight' => $weight,
+      );
+    }
+
+    field_create_instance($instance);
+  }
 }
 
 /**
@@ -480,6 +567,6 @@ function ad_update_6007() {
  */
 function ad_update_6008() {
   $ret = array();
-  $ret[] = update_sql("UPDATE {blocks} SET cache = ". BLOCK_CACHE_PER_PAGE ." WHERE module = 'ad'");
+  $ret[] = update_sql("UPDATE {blocks} SET cache = " . BLOCK_CACHE_PER_PAGE . " WHERE module = 'ad'");
   return $ret;
 }
diff --git ad.module ad.module
index 3243de0..892ccb2 100644
--- ad.module
+++ ad.module
@@ -17,7 +17,7 @@ function ad_theme() {
   return array(
     'ad_display' => array(
       'file' => 'ad.module',
-      'arguments' => array(
+      'variables' => array(
         'group' => NULL,
         'display' => NULL,
         'method' => 'javascript',
@@ -25,40 +25,34 @@ function ad_theme() {
     ),
     'ad_status_display' => array(
       'file' => 'ad.module',
-      'arguments' => array(
+      'variables' => array(
         'node' => NULL,
       ),
     ),
     'ad_statistics_display' => array(
       'file' => 'ad.pages.inc',
-      'arguments' => array(
+      'variables' => array(
         'statistics' => NULL,
       ),
     ),
     'node_ad' => array(
       'file' => 'ad.pages.inc',
-      'arguments' => array(
+      'variables' => array(
         'node' => NULL,
         'yield_form' => TRUE,
       ),
     ),
     'ad_admin_ads' => array(
       'file' => 'ad.admin.inc',
-      'arguments' => array(
-        'form' => NULL,
-      ),
+      'render element' => 'form',
     ),
     'ad_filters' => array(
       'file' => 'ad.admin.inc',
-      'arguments' => array(
-        'form' => NULL,
-      ),
+      'render element' => 'form',
     ),
     'ad_filter_form' => array(
       'file' => 'ad.admin.inc',
-      'arguments' => array(
-        'form' => NULL,
-      ),
+      'render element' => 'form',
     ),
   );
 };
@@ -102,8 +96,8 @@ function ad($group = FALSE, $quantity = 1, $options = array()) {
 
   switch ($options['ad_display']) {
     case 'raw':
-      require_once(drupal_get_path('module', 'ad') .'/adserve.inc');
-      require_once(drupal_get_path('module', 'ad') .'/adcache.inc');
+      require_once(drupal_get_path('module', 'ad') . '/adserve.inc');
+      require_once(drupal_get_path('module', 'ad') . '/adcache.inc');
       $output = adserve_ad($options);
       break;
     case 'iframe':
@@ -119,7 +113,7 @@ function ad($group = FALSE, $quantity = 1, $options = array()) {
       // Allow external cache files to define additional display variables.
       if ($options['cache'] != 'none') {
         $query['c'] =  $options['cache'];
-        $cache_variables = module_invoke('ad_cache_'. $options['cache'], 'adcacheapi', 'display_variables', array());
+        $cache_variables = module_invoke('ad_cache_' . $options['cache'], 'adcacheapi', 'display_variables', array());
         if (is_array($cache_variables)) {
           foreach ($cache_variables as $key => $value) {
             $query[$key] = $value;
@@ -139,7 +133,7 @@ function ad($group = FALSE, $quantity = 1, $options = array()) {
         $query['n'] = $nids;
         $group = "nids-$nids";
       }
-      else if (isset($options['tids'])) {
+      elseif (isset($options['tids'])) {
         // Choose ads from the provided list of taxonomy terms.
         $tids = $options['tids'];
         $query['t'] = $tids;
@@ -159,38 +153,45 @@ function ad($group = FALSE, $quantity = 1, $options = array()) {
           $query['l'] = $alias;
         }
       }
-      $src = url($base_url .'/'. $adserve, array('query' => $query));
+      $src = 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.
         // For now we'll have a global value, later we'll add per-group
         // over-rides.
-        $append = 'frameborder="'. variable_get('ad_iframe_frameborder', 0) .'" ';
-        $append .= 'scrolling="'. variable_get('ad_iframe_scroll', 'auto') .'" ';
-        $append .= 'name="'. $group .'" ';
+        $append = 'frameborder="' . variable_get('ad_iframe_frameborder', 0) . '" ';
+        $append .= 'scrolling="' . variable_get('ad_iframe_scroll', 'auto') . '" ';
+        $append .= 'name="' . $group . '" ';
         if ($height = variable_get('ad_iframe_height', '')) {
-          $append .= 'height="'. $height .'" ';
+          $append .= 'height="' . $height . '" ';
         }
         if ($width = variable_get('ad_iframe_width', '')) {
-          $append .= 'width="'. $width .'" ';
+          $append .= 'width="' . $width . '" ';
         }
-        $output = '<iframe src="'. htmlentities($src) ."\" $append></iframe>";
+        $output = '<iframe src="' . check_plain($src) . "\" $append></iframe>";
       }
-      else if ($options['ad_display'] == 'jquery') {
+      elseif ($options['ad_display'] == 'jquery') {
         // The theme function uses this to generate a CSS id for jQuery to use.
         $output = $src;
       }
       else {
-        $output = "<script type='text/javascript' src='". htmlentities($src) ."'></script>";
+        $output = "<script type='text/javascript' src='" . check_plain($src) . "'></script>";
       }
       break;
   }
 
   if (user_access('show advertisements')) {
-    return theme('ad_display', $group, $output, $options['ad_display']);
+    return theme('ad_display', array(
+      'group' => $group,
+      'display' => $output,
+      'method' => $options['ad_display'],
+    ));
   }
   else {
-    return theme('ad_display', 'none', "<!-- Enable 'show advertisements' permission if you wish to display ads here. -->");
+    return theme('ad_display', array(
+      'group' => 'none',
+      'display' => "<!-- Enable 'show advertisements' permission if you wish to display ads here. -->",
+    ));
   }
 }
 
@@ -198,19 +199,22 @@ function ad($group = FALSE, $quantity = 1, $options = array()) {
  * Function to display the actual advertisement to the screen.  Wrap it in a
  * theme function to make it possible to customize in your own theme.
  */
-function theme_ad_display($group, $display, $method = 'javascript') {
+function theme_ad_display($variables) {
   static $id = -1;
 
   // Increment counter for displaying multiple advertisements on the page.
   $id++;
 
+  $display = $variables['display'];
+  $method = $variables['method'];
+
   // The naming convention for the id attribute doesn't allow commas.
-  $group = preg_replace('/[,]/', '+', $group);
+  $group = preg_replace('/[,]/', '+', $variables['group']);
 
   if ($method == 'jquery') {
-    return "\n<div class=\"advertisement group-$group\" id=\"group-id-$id\">\n <script type=\"text/javascript\">\n//<![CDATA[\n  $(document).ready(function(){ jQuery(\"div#group-id-$id\").load(\"$display\"); });\n //]]>\n </script>\n</div>\n";
+    return "\n<div class=\"advertisement group-$group\" id=\"group-id-$id\">\n <script type=\"text/javascript\">\n//<![CDATA[\n  jQuery(function(){ jQuery(\"div#group-id-$id\").load(\"$display\"); });\n //]]>\n </script>\n</div>\n";
   }
-  else if ($method == 'raw') {
+  elseif ($method == 'raw') {
     return $display;
   }
   else {
@@ -234,25 +238,38 @@ function ad_redirect($aid, $group = NULL) {
   // Allow source url to be passed in.
   $url = isset($_GET['u']) ? $_GET['u'] : '';
   if (!isset($url) || !valid_url($url)) {
-    $url = referer_uri();
-  }
-  db_query("INSERT INTO {ad_clicks} (aid, uid, status, hostname, user_agent, adgroup, extra, hostid, url, timestamp) VALUES (%d, %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', %d)", $aid, $user->uid, $status, ip_address(), $_SERVER['HTTP_USER_AGENT'], $group, $extra, $hostid, $url, time());
+    $url = $_SERVER['HTTP_REFERER'];
+  }
+  db_insert('ad_clicks')
+    ->fields(array(
+      'aid' => $aid,
+      'uid' => $user->uid,
+      'status' => $status,
+      'hostname' => ip_address(),
+      'user_agent' => $_SERVER['HTTP_USER_AGENT'],
+      'adgroup' => $group,
+      'extra' => $extra,
+      'hostid' => $hostid,
+      'url' => $url,
+      'timestamp' => REQUEST_TIME,
+    ))
+    ->execute();
   watchdog('ad', 'Clicked %type ad aid %aid hostid %hostid.', array('%type' => $adtype, '%aid' => $aid, '%hostid' => $hostid));
   if (function_exists('click_filter_status') && ($status == CLICK_VALID)) {
     ad_statistics_increment($aid, 'click', $group, $hostid);
   }
-  else if (!function_exists('click_filter_status')) {
+  elseif (!function_exists('click_filter_status')) {
     // We're not filtering clicks, so all clicks are valid.
     ad_statistics_increment($aid, 'click', $group, $hostid);
   }
   // Determine where we're supposed to redirect the user.
-  $adtype = db_result(db_query('SELECT adtype FROM {ads} WHERE aid = %d', $aid));
+  $adtype = db_query('SELECT adtype FROM {ads} WHERE aid = ?', array($aid))->fetchField();
 
   $node->nid = $node->aid = $aid;
   $node->hostid = $hostid;
-  $url = module_invoke('ad_'. $adtype, 'adapi', 'redirect', $node);
+  $url = module_invoke('ad_' . $adtype, 'adapi', 'redirect', $node);
   if (isset($url)) {
-    header('Location: '. $url);
+    header('Location: ' . $url);
   }
   else {
     watchdog('ad', 'Ad redirection failed for aid %aid hostid %hostid, failed to load destination URL. ', array('%aid' => $aid, '%hostid' => $hostid));
@@ -299,7 +316,7 @@ function ad_rebuild_cache($verbose = FALSE) {
   $build = "ad_cache_{$cache}_build";
   if (function_exists($build)) {
     if ($verbose) {
-      drupal_set_message('Rebuilding ad cache.');
+      drupal_set_message(t('Rebuilding ad cache.'));
     }
     $build();
   }
@@ -323,18 +340,19 @@ function ad_link_nofollow() {
  * Increment action counter.
  */
 function ad_statistics_increment($aid, $action, $group = NULL, $hostid = NULL) {
-  // Update action statistics.
-  db_query("UPDATE {ad_statistics} SET count = count + 1 WHERE date = %d AND aid = %d AND action = '%s' AND adgroup = '%s' AND hostid = '%s'", date('YmdH'), $aid, $action, $group, $hostid);
-  // If column doesn't already exist, we need to add it.
-  if (!db_affected_rows()) {
-    db_query("INSERT INTO {ad_statistics} (aid, adgroup, hostid, date, action, count) VALUES(%d, '%s', '%s', %d, '%s', 1)", $aid, $group, $hostid, date('YmdH'), $action);
-    // If another process already added this row our INSERT will fail, if so we
-    // still need to increment it so we don't loose an action.
-    if (!db_affected_rows()) {
-      db_query("UPDATE {ad_statistics} SET count = count + 1 WHERE date = %d AND aid = %d AND action = '%s' AND adgroup = '%s' AND hostid = '%s'", date('YmdH'), $aid, $action, $group, $hostid);
-    }
-  }
-
+  db_merge('ad_statistics')
+    ->key(array(
+      'date' => date('YmdH'),
+      'aid' => $aid,
+      'action' => $action,
+      'adgroup' => (int) $group,
+      'hostid' => (int) $hostid,
+    ))
+    ->fields(array(
+      'count' => 1,
+    ))
+    ->expression('count', 'count + :inc', array(':inc' => 1))
+    ->execute();
   $event = array('aid' => $aid, 'action' => $action, 'hostid' => $hostid);
   module_invoke_all('adapi', 'statistics_increment', $event);
 }
@@ -348,49 +366,49 @@ function ad_status_array($aid = 0, $status = NULL) {
   // mark status as pending
   if (user_access('administer advertisements') ||
       $status == 'pending' || $status == NULL ||
-      ad_permission($aid, 'set status as pending')) {
+      ad_access_permission($aid, 'set status as pending')) {
     $permissions['pending'] = t('This advertisement is currently waiting for administrative approval.');
   }
   // mark status from pending to approved
   if (user_access('administer advertisements') ||
       $status == 'approved' ||
       ($status == 'pending' &&
-       ad_permission($aid, 'set status from pending to approved'))) {
+       ad_access_permission($aid, 'set status from pending to approved'))) {
     $permissions['approved'] = t('This advertisement has been approved and is currently waiting to be activated.');
   }
   // mark status as active (from pending, approved, or offline)
   if (user_access('administer advertisements') ||
       $status == 'active' ||
       ($status == 'approved' &&
-       ad_permission($aid, 'set status from approved to active')) ||
+       ad_access_permission($aid, 'set status from approved to active')) ||
       ($status == 'offline' &&
-       ad_permission($aid, 'set status from offline to active'))) {
+       ad_access_permission($aid, 'set status from offline to active'))) {
     $permissions['active'] = t('This advertisement is actively being displayed.');
   }
   // mark status as offline (from pending, approved, or active)
   if (user_access('administer advertisements') ||
       $status == 'offline' ||
       ($status == 'approved' &&
-       ad_permission($aid, 'set status from approved to offline')) ||
+       ad_access_permission($aid, 'set status from approved to offline')) ||
       ($status == 'active' &&
-       ad_permission($aid, 'set status from active to offline'))) {
+       ad_access_permission($aid, 'set status from active to offline'))) {
     $permissions['offline'] = t('This advertisement has been temporarily disabled by its owner and is not currently being displayed.');
   }
   // mark status as expired (from active or offline)
   if (user_access('administer advertisements') ||
       $status == 'expired' ||
       ($status == 'active' &&
-       ad_permission($aid, 'set status from active to expired')) ||
+       ad_access_permission($aid, 'set status from active to expired')) ||
       ($status == 'offline' &&
-       ad_permission($aid, 'set status from offline to expired'))) {
+       ad_access_permission($aid, 'set status from offline to expired'))) {
     $permissions['expired'] = t('This advertisement has expired and is no longer being displayed.');
   }
   // mark status as denied (from pending or any)
   if (user_access('administer advertisements') ||
       $status == 'denied' ||
       ($status == 'pending' &&
-       ad_permission($aid, 'set status from pending to denied')) ||
-      ad_permission($aid, 'set status as denied')) {
+       ad_access_permission($aid, 'set status from pending to denied')) ||
+      ad_access_permission($aid, 'set status as denied')) {
     $permissions['denied'] = t('This advertisement was refused by the site administrator and will not be displayed.');
   }
   return $permissions;
@@ -399,43 +417,44 @@ function ad_status_array($aid = 0, $status = NULL) {
 /**
  * Display the status of the currently viewed ad.
  */
-function theme_ad_status_display($node) {
+function theme_ad_status_display($variables) {
+  $node = $variables['node'];
   if (isset($node->adstatus)) {
     $status_array = ad_status_array($node->nid, $node->adstatus);
     $output  = '<div class="adstatus">';
-    $output .= '<p>'. t($status_array[$node->adstatus]) .'</p>';
+    $output .= '<p>' . t($status_array[$node->adstatus]) . '</p>';
     switch ($node->adstatus) {
       case 'approved':
         if ($node->autoactivate) {
-          $output .= '<p>'. t('This advertisement will be automatically activated on %timestamp, in %time.', array('%timestamp' => format_date($node->autoactivate, 'large'), '%time' => format_interval($node->autoactivate - time()))) .'</p>';
+          $output .= '<p>' . t('This advertisement will be automatically activated on %timestamp, in %time.', array('%timestamp' => format_date($node->autoactivate, 'large'), '%time' => format_interval($node->autoactivate - REQUEST_TIME))) . '</p>';
         }
         break;
       case 'active':
-        $activated = db_result(db_query("SELECT activated FROM {ads} WHERE aid = %d", $node->nid));
+        $activated = db_query("SELECT activated FROM {ads} WHERE aid = ?", array($node->nid))->fetchField();
         if ($activated) {
-          $output .= '<p>'. t('This advertisement has been active since %date.', array('%date' => format_date($activated, 'large'))) .'</p>';
+          $output .= '<p>' . t('This advertisement has been active since %date.', array('%date' => format_date($activated, 'large'))) . '</p>';
         }
         if ($node->autoexpire) {
-          $output .= '<p>'. t('This advertisement will expire on %timestamp, in %time.', array('%timestamp' => format_date($node->autoexpire, 'large'), '%time' => format_interval($node->autoexpire - time()))) .'</p>';
+          $output .= '<p>' . t('This advertisement will expire on %timestamp, in %time.', array('%timestamp' => format_date($node->autoexpire, 'large'), '%time' => format_interval($node->autoexpire - REQUEST_TIME))) . '</p>';
         }
         if ($node->maxviews) {
-          $views = (int)db_result(db_query("SELECT SUM(count) FROM {ad_statistics} WHERE aid = %d AND action = 'view' AND date >= %d", $node->nid, date('YmdH', $node->activated)));
-          $output .= '<p>'. t('This advertisement will expire after %left more impressions.', array('%left' => $node->maxviews - $views)) .'</p>';
+          $views = (int) db_query("SELECT SUM(count) FROM {ad_statistics} WHERE aid = ? AND action = 'view' AND date >= ?", array($node->nid, date('YmdH', $node->activated)))->fetchField();
+          $output .= '<p>' . t('This advertisement will expire after %left more impressions.', array('%left' => $node->maxviews - $views)) . '</p>';
         }
         if ($node->maxclicks) {
-          $clicks = (int)db_result(db_query("SELECT SUM(count) FROM {ad_statistics} WHERE aid = %d AND action = 'click' AND date >= %d", $node->nid, date('YmdH', $node->activated)));
-          $output .= '<p>'. t('This advertisement will expire after %left more clicks.', array('%left' => $node->maxclicks - $clicks)) .'</p>';
+          $clicks = (int) db_query("SELECT SUM(count) FROM {ad_statistics} WHERE aid = ? AND action = 'click' AND date >= ?", array($node->nid, date('YmdH', $node->activated)))->fetchField();
+          $output .= '<p>' . t('This advertisement will expire after %left more clicks.', array('%left' => $node->maxclicks - $clicks)) . '</p>';
         }
         break;
       case 'expired':
-        $expired = db_result(db_query("SELECT expired FROM {ads} WHERE aid = %d", $node->nid));
+        $expired = db_query("SELECT expired FROM {ads} WHERE aid = ?", array($node->nid))->fetchField();
         if ($expired) {
-          $output .= '<p>'. t('This advertisement expired %date.', array('%date' => format_date($expired, 'large'))) .'</p>';
+          $output .= '<p>' . t('This advertisement expired %date.', array('%date' => format_date($expired, 'large'))) . '</p>';
         }
         break;
     }
     $output .= '</div>';
-    return theme('box', t('Status'), $output);
+    return '<h2 class="title">' . t('Status') . '</h2><div>' . $output . '</div>';
   }
 }
 
@@ -447,7 +466,8 @@ function ad_init() {
   // caching is enabled.
   $method = variable_get('ad_display', 'javascript');
   if ($method == 'jquery') {
-    drupal_add_js('misc/jquery.js', 'core');
+    // moved to library
+    drupal_add_library('system', 'jquery', TRUE);
   }
 }
 
@@ -458,10 +478,10 @@ function ad_help($path, $arg) {
   $output = '';
   switch ($path) {
     case 'admin/help#ad':
-      $output = '<p>'. t('The ad module provides a complete advertising system for Drupal powered websites.  It does this through an API that allow other modules to handle various types of advertising content.  For example, if enabled together with the ad_image module you will be able to display image based advertisements such as banner ads.') .'</p>';
+      $output = '<p>' . t('The ad module provides a complete advertising system for Drupal powered websites.  It does this through an API that allow other modules to handle various types of advertising content.  For example, if enabled together with the ad_image module you will be able to display image based advertisements such as banner ads.') . '</p>';
       break;
     case 'node/add/ad':
-      $output = '<p>'. t('Advertisements can be randomly displayed to visitors of your website.') .'</p>';
+      $output = '<p>' . t('Advertisements can be randomly displayed to visitors of your website.') . '</p>';
       break;
   }
   return $output;
@@ -471,126 +491,183 @@ function ad_help($path, $arg) {
  * Implementation of hook_cron().
  */
 function ad_cron() {
-  if (time() - variable_get('ad_cron_timestamp', 0) >= 60) {
+  if (REQUEST_TIME - variable_get('ad_cron_timestamp', 0) >= 60) {
     // Locate ads that need to be activated or expired.
-    $result = db_query('SELECT aid, adstatus, adtype, autoactivate, autoactivated, autoexpire, autoexpired FROM {ads} WHERE autoactivate <> 0 OR autoexpire <> 0');
-    while ($ad = db_fetch_object($result)) {
+    $condition = db_or()
+      ->condition('autoactivate', 0, '<>')
+      ->condition('autoexpire', 0, '<>');
+    $result = db_select('ads')
+      ->fields('ads', array(
+        'aid',
+        'adstatus',
+        'adtype',
+        'autoactivate',
+        'autoactivated',
+        'autoexpire',
+        'autoexpired',
+      ))
+      ->condition($condition)
+      ->execute();
+    foreach ($result as $ad) {
       switch ($ad->adstatus) {
         case 'approved': {
-          // See if this ad is ready to be activated.
-          if ($ad->autoactivate && $ad->autoactivate <= time()) {
-            $node = node_load($ad->aid);
+          $node = node_load($ad->aid);
 
+          // See if this ad is ready to be activated.
+          if ($ad->autoactivate && $ad->autoactivate <= REQUEST_TIME) {
             // Activate the ad.
-            db_query("UPDATE {ads} SET adstatus = 'active', autoactivate = 0, autoactivated = %d, activated = %d WHERE aid = %d", time(), time(), $ad->aid);
+            db_update('ads')
+              ->fields(array(
+                'adstatus' => 'active',
+                'autoactivate' => 0,
+                'autoactivated' => REQUEST_TIME,
+                'activated' => REQUEST_TIME,
+              ))
+              ->condition('aid', $ad->aid)
+              ->execute();
             ad_statistics_increment($ad->aid, 'autoactivated');
             ad_statistics_increment($ad->aid, 'active');
 
-            watchdog('ad', 'Automatically activated ad %title with nid %nid.', array('%title' => $node->title, '%nid' => $node->nid));
+            watchdog('ad', 'Automatically activated ad %title with nid %nid.', array(
+              '%title' => $node->title,
+              '%nid' => $node->nid,
+            ));
 
             // Allow modules to do special processing to automatically
             // activated advertisements.
-            module_invoke('ad_'. $ad->adtype, 'adapi', 'autoactivate', $node);
+            module_invoke('ad_' . $ad->adtype, 'adapi', 'autoactivate', $node);
           }
-          else if (!$ad->autoactivate) {
+          elseif (!$ad->autoactivate) {
             // Once daily warn that there's an ad stuck in approved state.
-            if (time() - variable_get("ad_autoactivate_warning_$ad->aid", 0) >= 8600) {
-              watchdog('ad', 'Warning: ad %title with nid %nid in approved state has no autoactivate date set.', array('%title' => $node->title, '%nid' => $node->nid));
-              variable_set("ad_autoactivate_warning_$ad->aid", time());
+            if (REQUEST_TIME - variable_get("ad_autoactivate_warning_$ad->aid", 0) >= 8600) {
+              watchdog('ad', 'Warning: ad %title with nid %nid in approved state has no autoactivate date set.', array(
+                '%title' => $node->title,
+                '%nid' => $node->nid
+              ));
+              variable_set("ad_autoactivate_warning_$ad->aid", REQUEST_TIME);
             }
           }
           break;
         }
         case 'active': {
           // See if this ad is ready to be activated.
-          if ($ad->autoexpire && $ad->autoexpire <= time()) {
+          if ($ad->autoexpire && $ad->autoexpire <= REQUEST_TIME) {
             $node = node_load($ad->aid);
 
             // Expire the ad.
-            db_query("UPDATE {ads} SET adstatus = 'expired', autoexpire = 0, autoexpired = %d, expired = %d WHERE aid = %d", time(), time(), $ad->aid);
+            db_update('ads')
+              ->fields(array(
+                'adstatus' => 'expired',
+                'autoexpire' => 0,
+                'autoexpired' => REQUEST_TIME,
+                'expired' => REQUEST_TIME,
+              ))
+              ->condition('aid', $ad->aid)
+              ->execute();
             ad_statistics_increment($ad->aid, 'autoexpired');
             ad_statistics_increment($ad->aid, 'expired');
 
-            watchdog('ad', 'Automatically expired ad %title with nid %nid.', array('%title' => $node->title, '%nid' => $node->nid));
+            watchdog('ad', 'Automatically expired ad %title with nid %nid.', array(
+              '%title' => $node->title,
+              '%nid' => $node->nid,
+            ));
 
             // Allow modules to do special processing to automatically
             // activated advertisements.
-            module_invoke('ad_'. $ad->adtype, 'adapi', 'autoexpire', $node);
+            module_invoke('ad_' . $ad->adtype, 'adapi', 'autoexpire', $node);
           }
-          else if (!$ad->autoexpire) {
+          elseif (!$ad->autoexpire) {
             // Ad is already activated, but has autoactivate timestamp set.
-            db_query("UPDATE {ads} SET autoactivate = 0 WHERE aid = %d", $ad->aid);
+            db_update('ads')
+              ->fields(array(
+                'autoactivate' => 0,
+              ))
+              ->condition('aid', $ad->aid)
+              ->execute();
           }
           break;
         }
         default:
           $node = node_load($ad->aid);
-          db_query('UPDATE {ads} SET autoactivate = 0, autoexpire = 0 WHERE aid = %d', $ad->aid);
-          watchdog('ad', 'Warning: reset %type timestamp on advertisement %title with nid %nid because it is in %state state.', array('%title' => $node->title, '%nid' => $node->nid, '%type' => $ad->autoactivate ? 'autoactivate' : 'autoexpire', '%state' => $ad->adstatus));
+          db_update('ads')
+            ->fields(array(
+              'autoactivate' => 0,
+              'autoexpire' => 0,
+            ))
+            ->condition('aid', $ad->aid)
+            ->execute();
+          watchdog('ad', 'Warning: reset %type timestamp on advertisement %title with nid %nid because it is in %state state.', array(
+            '%title' => $node->title,
+            '%nid' => $node->nid,
+            '%type' => $ad->autoactivate ? 'autoactivate' : 'autoexpire',
+            '%state' => $ad->adstatus,
+          ));
       }
     }
-    variable_set('ad_cron_timestamp', time());
+    variable_set('ad_cron_timestamp', REQUEST_TIME);
   }
 }
 
 /**
- * Implementation of hook_perm().
+ * Implements of hook_permission().
  */
-function ad_perm() {
-  return array('administer advertisements',
-                'create advertisements',
-                'edit own advertisements',
-                'edit any advertisement',
-                'delete own advertisements',
-                'delete any advertisement',
-                'show advertisements');
+function ad_permission() {
+  return array(
+    'administer advertisements' => array(
+      'title' => t('Administer advertisements'),
+      'restrict access' => TRUE,
+    ),
+    'show advertisements' => array(
+      'title' => 'View advertisements',
+      'description' => 'Advertisements are only shown to the roles selected.',
+    ),
+  );
 }
 
 /**
- * Implementation of hook_node_info().
+ * Implements of hook_node_info().
  */
 function ad_node_info() {
   $items['ad'] = array(
     'name' => t('Advertisement'),
-    'module' => 'ad',
+    // required or wont call ad_form
+    'base' => 'ad',
     'description' => t('Advertisements can be randomly displayed to visitors of your website.'),
   );
   return $items;
 }
 
 /**
- * Implementation of hook_access().
+ * Implements of hook_node_access().
  */
-function ad_access($op, $node, $account) {
-  switch ($op) {
-    case 'create':
-      return (user_access('create advertisements', $account) || user_access('administer advertisements'));
-    case 'update':
-      return (user_access('edit any advertisement', $account) || (user_access('edit own advertisements', $account) && is_ad_owner($node->nid)) || user_access('administer advertisements', $account));
-    case 'delete':
-      return (user_access('delete any advertisement', $account) || (user_access('delete own advertisements', $account) && is_ad_owner($node->nid)) || user_access('administer advertisements', $account));
-    case 'view':
-      // Return false if user doesn't have basic permissions to view
-      // advertisements.  Don't return true to let default Drupal
-      // domain/node access checks happen.
-      if (!user_access('show advertisements', $account) &&
-          !user_access('administer advertisements', $account)) {
-        return false;
-      }
+function ad_node_access($node, $op, $account) {
+  $type = is_string($node) ? $node : $node->type;
+
+  if ($type == 'ad') {
+    // allow access if has admin permission
+    if (user_access('administer advertisements', $account)) {
+      return NODE_ACCESS_ALLOW;
+    }
+    // node handles create,update and delete
+    if ($op == 'view' && !user_access('show advertisements', $account)) {
+      return NODE_ACCESS_DENY;
+    }
   }
+
+  // let other modules decide
+  return NODE_ACCESS_IGNORE;
 }
 
 /**
- * Implementation of hook_form().
+ * Implements of hook_form().
  */
-function ad_form(&$node, &$form_state) {
-  $form = array();
+function ad_form($node, &$form_state) {
+  $type = node_type_get_type($node);
 
-  $type = node_get_types('type', $node);
   // When form_state is not empty, we should rather use it's values
   // to not loose data if validation fails.
   if (!empty($form_state['values'])) {
-    $node = (object)$form_state['values'];
+    $node = (object) ((array) $node + $form_state['values']);
   }
 
   $form['aid'] = array(
@@ -607,17 +684,6 @@ function ad_form(&$node, &$form_state) {
       '#weight' => -5,
     );
   }
-  if ($type->has_body) {
-    $form['body_field'] = node_body_field($node, $type->body_label, $type->min_word_count);
-  }
-  else {
-    // The body array has to exist otherwise the format field gets removed.
-    $form['body'] = array(
-      '#type' => 'hidden',
-      '#value' => '',
-    );
-    $form['body_field']['format'] = filter_form($node->format);
-  }
 
   // determine the current ad type
   if (!isset($adtype)) {
@@ -625,21 +691,21 @@ function ad_form(&$node, &$form_state) {
     if (count($adtypes) == 1) {
       $adtype = key($adtypes);
     }
-    else if (!count($adtypes)) {
-      drupal_set_message(t('At least one ad type module must be enabled before you can create advertisements.  For example, try <a href="!url">enabling</a> the ad_text or ad_image module.', array('!url' => url('admin/build/modules'))), 'error');
+    elseif (!count($adtypes)) {
+      drupal_set_message(t('At least one ad type module must be enabled before you can create advertisements.  For example, try <a href="!url">enabling</a> the ad_text or ad_image module.', array('!url' => url('admin/modules'))), 'error');
     }
   }
 
   // display ad type switch
   if ((!isset($node->adtype) || isset($node->adtype_select)) &&
        count($adtypes) >1) {
+
     $adtypes = array(0 => '---');
     $adtypes += ad_get_types('name');
     $form['select'] = array(
       '#type' => 'fieldset',
       '#title' => t('Select Ad type'),
-      '#prefix' => '<div class="container-inline">',
-      '#suffix' => '</div>',
+      '#attributes' => array('class' => array('container-inline')),
       '#weight' => 3,
     );
     $form['select']['adtype_select'] = array(
@@ -652,8 +718,8 @@ function ad_form(&$node, &$form_state) {
       '#type' => 'submit',
       '#value' => t('Select'),
       '#validate' => array('ad_select_adtype'),
-      '#ahah' => array(
-        'path' => 'node/add/ad/ahah',
+      '#ajax' => array(
+        'callback' => 'ad_form_ahah',
         'wrapper' => 'adtype-ahah-wrapper',
       ),
     );
@@ -667,13 +733,10 @@ function ad_form(&$node, &$form_state) {
       $node->adtype = $adtype;
     }
     ad_form_add_adtype_elements($form, $node->adtype, $node);
-    // add ahah wrapper
-    $form['adtype_elements']['#prefix'] = '<div id="adtype-ahah-wrapper">';
-    $form['adtype_elements']['#suffix'] = '</div>';
   }
   if (!isset($form['adtype_elements'])) {
     $form['adtype_elements'] = array(
-      '#value' => '<div id="adtype-ahah-wrapper"></div>',
+      '#markup' => '<div id="adtype-ahah-wrapper"></div>',
       '#weight' => 3.1,
     );
   }
@@ -691,10 +754,10 @@ function ad_form(&$node, &$form_state) {
   foreach (ad_status_array($nid, $adstatus) as $status => $description) {
     $form['adstatus']["ad$status"] = array(
       '#type' => 'radio',
-      '#title' => t("$status"),
+      '#title' => $status,
       '#return_value' => $status,
       '#default_value' => isset($node->adstatus) ? $node->adstatus : 'pending',
-      '#description' => "$description",
+      '#description' => $description,
       '#parents' => array("adstatus")
     );
   }
@@ -715,20 +778,21 @@ function ad_form(&$node, &$form_state) {
       isset($node->maxclicks) ||
       isset($form_state['values']['maxclicks']))
       ? FALSE : TRUE,
+    '#weight' => 5,
   );
 
   $date_api = FALSE;
   if (module_exists('date_popup')) {
     $date_api = TRUE;
   }
-  if ((isset($node->nid) && ad_permission($node->nid, 'manage status')) ||
+  if ((isset($node->nid) && ad_access_permission($node->nid, 'manage status')) ||
       user_access('administer advertisements')) {
     if (!$date_api) {
       $form['schedule']['current'] = array(
         '#type' => 'markup',
         '#prefix' => '<div>',
         '#suffix' => '</div>',
-        '#value' => t('The current date and time is "%date".', array('%date' => format_date(time(), 'custom', 'F j, Y H:i')))
+        '#value' => t('The current date and time is "%date".', array('%date' => format_date(REQUEST_TIME, 'custom', 'F j, Y H:i')))
       );
     }
     $form['schedule']['autoactivate'] = array(
@@ -739,10 +803,10 @@ function ad_form(&$node, &$form_state) {
     );
     if ($date_api) {
       $form['schedule']['autoactivate']['#date_format'] = 'F j, Y H:i';
-      $form['schedule']['autoactivate']['#default_value'] = isset($node->autoactivate) && $node->autoactivate > 0 ? format_date((int)$node->autoactivate, 'custom', 'Y-m-j H:i') : '';
+      $form['schedule']['autoactivate']['#default_value'] = isset($node->autoactivate) && $node->autoactivate > 0 ? format_date((int) $node->autoactivate, 'custom', 'Y-m-j H:i') : '';
     }
     else {
-      $form['schedule']['autoactivate']['#default_value'] = isset($node->autoactivate) && $node->autoactivate > 0 ? format_date((int)$node->autoactivate, 'custom', 'F j, Y H:i') : 0;
+      $form['schedule']['autoactivate']['#default_value'] = isset($node->autoactivate) && $node->autoactivate > 0 ? format_date((int) $node->autoactivate, 'custom', 'F j, Y H:i') : 0;
     }
   }
 
@@ -756,10 +820,10 @@ function ad_form(&$node, &$form_state) {
     );
     if ($date_api) {
       $form['schedule']['autoexpire']['#date_format'] = 'F j, Y H:i';
-      $form['schedule']['autoexpire']['#default_value'] = isset($node->autoexpire) && $node->autoexpire > 0 ? format_date((int)$node->autoexpire, 'custom', 'Y-m-j H:i') : '';
+      $form['schedule']['autoexpire']['#default_value'] = isset($node->autoexpire) && $node->autoexpire > 0 ? format_date((int) $node->autoexpire, 'custom', 'Y-m-j H:i') : '';
     }
     else {
-      $form['schedule']['autoexpire']['#default_value'] = isset($node->autoexpire) && $node->autoexpire > 0 ? format_date((int)$node->autoexpire, 'custom', 'F j, Y H:i') : 0;
+      $form['schedule']['autoexpire']['#default_value'] = isset($node->autoexpire) && $node->autoexpire > 0 ? format_date((int) $node->autoexpire, 'custom', 'F j, Y H:i') : 0;
     }
     $form['schedule']['maxviews'] = array(
       '#type' => 'textfield',
@@ -786,7 +850,7 @@ function ad_form(&$node, &$form_state) {
       '#type' => 'markup',
       '#prefix' => '<div>',
       '#suffix' => '</div>',
-      '#value' => theme('ad_status_display', $node),
+      '#value' => theme('ad_status_display', array('node' => $node)),
     );
     $form['schedule']['autoexpire'] = array(
       '#type' => 'hidden',
@@ -802,8 +866,9 @@ function ad_form(&$node, &$form_state) {
  * Ad type switch submit handler.
  */
 function ad_select_adtype(&$form, &$form_state) {
-  if (!$form_state['values']['adtype'] && !$form_state['values']['adtype_select']) {
+  if (empty($form_state['values']['adtype']) && empty($form_state['values']['adtype_select'])) {
     form_set_error('adtype_select', t('Please, select an Ad type.'));
+    return;
   }
   if (!isset($form_state['values']['adtype']) || isset($form_state['values']['adtype_select']) && $form_state['values']['adtype'] != $form_state['values']['adtype_select']) {
     $form_state['values']['adtype'] = $form_state['values']['adtype_select'];
@@ -814,23 +879,10 @@ function ad_select_adtype(&$form, &$form_state) {
 /**
  * Ad type switch AHAH menu handler.
  */
-function ad_form_ahah() {
-  $form_state = array('storage' => NULL, 'submitted' => FALSE);
-  $form_build_id = $_POST['form_build_id'];
-  $form = form_get_cache($form_build_id, $form_state);
-  ad_form_add_adtype_elements($form, $_POST['adtype_select']);
-  form_set_cache($form_build_id, $form, $form_state);
-  $form += array(
-    '#post' => $_POST,
-    '#programmed' => FALSE,
-  );
-  // Rebuild the form.
-  $form = form_builder($_POST['form_id'], $form, $form_state);
-  $output = drupal_render($form['adtype_elements']);
-  drupal_json(array(
-    'status'   => TRUE,
-    'data'     => $output,
-  ));
+function ad_form_ahah($form, $form_state) {
+  $node = $form['#node'];
+  ad_form_add_adtype_elements($form, $form_state['values']['adtype_select'], $node);
+  return $form['adtype_elements'];
 }
 
 /**
@@ -838,12 +890,15 @@ function ad_form_ahah() {
  */
 function ad_form_add_adtype_elements(&$form, $adtype, $node = NULL) {
   unset($form['adtype_elements']);
-  $form['adtype_elements'] = module_invoke('ad_'. $adtype, 'adapi', 'form', $node);
+  $form['adtype_elements'] = module_invoke('ad_' . $adtype, 'adapi', 'form', $node);
+  // add ahah wrapper
+  $form['adtype_elements']['#prefix'] = '<div id="adtype-ahah-wrapper">';
+  $form['adtype_elements']['#suffix'] = '</div>';
+  $form['adtype_elements']['#weight'] = 3.1;
   $form['adtype'] = array(
     '#type' => 'hidden',
     '#value' => $adtype,
   );
-  $form['adtype_elements']['#weight'] = 3.1;
 }
 
 /**
@@ -854,42 +909,25 @@ function ad_form_alter(&$form, &$form_state, $form_id) {
     // Remove taxonomy form options not applicable for ad groups.
     if ($form['vid']['#value'] == _ad_get_vid()) {
       $form['help_ad_vocab'] = array(
-        '#value' => t('This vocabulary was automatically created for use by the ad module.  Only applicable options are available.'),
+        '#markup' => t('This vocabulary was automatically created for use by the ad module.'),
         '#weight' => -1
       );
-      $form['nodes']['ad'] = array(
-        '#type' => 'checkbox',
-        '#title' => t('ad group'),
-        '#value' => 1,
-        '#attributes' => array('disabled' => ''),
-        '#description' => t('Type %type is required to use this vocabulary.', array('%type' => t('ad group')))
-      );
-      $form['tags']['#description'] = t('If enabled, ads are categorized by typing ad group names instead of choosing them from a list.');
-      $form['multiple']['#description'] = t('If enabled, allows ads to have more than one ad group (always true for free tagging).');
-      $form['required']['#description'] = t('If enabled, every ad <strong>must</strong> be assigned to at least one ad group.');
-      $form['hierarchy'] = array(
-        '#type' => 'value',
-        '#value' => 0
-      );
-      unset($form['relations']);
-    }
-    else {
-      unset($form['nodes']['ad']);
+      // dont allow changing machine name
+      $form['machine_name']['#access'] = FALSE;
     }
   }
-  else if ($form_id == 'taxonomy_form_term') {
+  elseif ($form_id == 'taxonomy_form_term') {
     if ($form['vid']['#value'] == _ad_get_vid()) {
       $form['name']['#title'] = t('Ad group name');
       $form['name']['#description'] = t('The name for this ad group.  Example: "Linux".');
       $form['description']['#description'] = t('A description of the ad group.');
       $form['description']['#required'] = TRUE;
-      $form['weight']['#description'] = t('In listings, the heavier ad groups will sink and the lighter ad groups will be positioned nearer the top.');
-      unset($form['synonyms']);
+      $form['relations']['weight']['#description'] = t('In listings, the heavier ad groups will sink and the lighter ad groups will be positioned nearer the top.');
     }
   }
-  else if ($form_id == 'search_form' && variable_get('ad_no_search', 1) && !user_access('administer advertisements') && !user_access('administer any advertisement')) {
+  elseif ($form_id == 'search_form' && variable_get('ad_no_search', 1) && !user_access('administer advertisements') && !user_access('edit any ad content')) {
     $vid = _ad_get_vid();
-    $vocabulary = db_result(db_query('SELECT name FROM {vocabulary} WHERE vid = %d', $vid));
+    $vocabulary = db_query('SELECT name FROM {taxonomy_vocabulary} WHERE vid = ?', array($vid))->fetchObject();
     unset($form['advanced']['category']['#options'][$vocabulary]);
     if (empty($form['advanced']['category']['#options'])) {
       unset($form['advanced']['category']);
@@ -899,149 +937,235 @@ function ad_form_alter(&$form, &$form_state, $form_id) {
 }
 
 /**
- * Implementation of hook_db_rewrite_sql().
+ * Implements of hook_query_alter().
  */
-function ad_db_rewrite_sql($query, $primary_table, $primary_field, $args) {
-  if (variable_get('ad_no_search', 1) && !user_access('administer advertisements') && !user_access('edit any advertisement') && $query == '' && $primary_table == 'n' && $primary_field = 'nid' && empty($args)) {
-    return array('where' => " n.type != 'ad'");
+function ad_query_alter($query) {
+  if (!variable_get('ad_no_search', 1) || user_access('administer advertisements') || user_access('edit any ad content')) {
+    return;
+  }
+  // remove ads from search results
+  if ($query->hasTag('node_access') && $query instanceof SelectQuery) {
+    $tables = $query->getTables();
+    // make sure we are using search_index table
+    if (isset($tables['i']) && $tables['i']['table'] == 'search_index') {
+      $query->condition('n.type', 'ad', '!=');
+    }
   }
 }
 
 /**
- * Implementation of hook_nodeapi().
+ * Implements hook_node_load().
  */
-function ad_nodeapi(&$node, $op, $teaser, $page) {
+function ad_node_load($nodes, $types) {
   global $user;
 
-  switch ($op) {
-    case 'load':
-      $ad = db_fetch_array(db_query('SELECT * FROM {ads} WHERE aid = %d', $node->nid));
-      $merge = array_merge((array)$node, (array)$ad);
-      $adtype = module_invoke('ad_'. $ad['adtype'], 'adapi', 'load', $merge);
-      if (is_array($adtype)) {
-        return array_merge($ad, $adtype);
-      }
-      else {
-        return $ad;
-      }
-      break;
+  // if no ads in loaded set ignore
+  if (!in_array('ad', $types)) {
+    return;
+  }
+
+  // fetch all ads
+  $ads = db_select('ads')
+    ->fields('ads')
+    ->condition('aid', array_keys($nodes))
+    ->execute();
+
+  foreach ($ads as $ad) {
+    $node = $nodes[$ad->aid];
+    $merge = (array) $ad;
+    // invoke adtype module
+    $array = array_merge((array) $node, $merge);
+    // TODO where does this come from?
+    $array['format'] = $merge['format'] = filter_fallback_format();
+    $return = module_invoke('ad_' . $ad->adtype, 'adapi', 'load', $array);
+    // if return is array add to merge
+    if (is_array($return)) {
+      $merge = array_merge($merge, $return);
+    }
+    // merge into node
+    foreach ($merge as $key => $value) {
+      $node->$key = $value;
+    }
+  }
 
-    case 'insert':
-      if (isset($node->adtype)) {
-        if ($node->status != 1 && $node->adstatus == 'active') {
-          $node->adstatus = 'expired';
-        }
-        $activated = $node->adstatus == 'active' ? time() : 0;
-        $node->autoactivate = isset($node->autoactivate) ? trim($node->autoactivate) : 0;
-        $node->autoactivate = (is_numeric($node->autoactivate)) ? $node->autoactivate : strtotime($node->autoactivate);
-        $node->autoexpire = isset($node->autoexpire) ? trim($node->autoexpire) : 0;
-        $node->autoexpire = (is_numeric($node->autoexpire)) ? $node->autoexpire : strtotime($node->autoexpire);
-        if (!isset($node->maxviews)) {
-          $node->maxviews = 0;
-        }
-        if (!isset($node->maxclicks)) {
-          $node->maxclicks = 0;
-        }
-        db_query("INSERT INTO {ads} (aid, uid, adstatus, adtype, redirect, autoactivate, autoexpire, activated, maxviews, maxclicks) VALUES(%d, %d, '%s', '%s', '%s', %d, %d, %d, %d, %d)", $node->nid, $node->uid, $node->adstatus, $node->adtype, url('ad/redirect/'. $node->nid, array('absolute' => TRUE)), $node->autoactivate ? strtotime($node->autoactivate) : '', $node->autoexpire ? strtotime($node->autoexpire) : '', $activated, $node->maxviews, $node->maxclicks);
-        ad_statistics_increment($node->nid, 'create');
-      }
-      break;
+  foreach ($nodes as $node) {
+    ad_node_invoke_adapi($node, 'load', FALSE);
+  }
+}
 
-    case 'update':
-      if (isset($node->adtype)) {
-        $ad = db_fetch_object(db_query('SELECT * FROM {ads} WHERE aid = %d', $node->nid));
-        $node->autoactivate = isset($node->autoactivate) ? trim($node->autoactivate) : 0;
-        $node->autoactivate = (is_numeric($node->autoactivate)) ? $node->autoactivate : strtotime($node->autoactivate);
-        $node->autoexpire = isset($node->autoexpire) ? trim($node->autoexpire) : 0;
-        $node->autoexpire = (is_numeric($node->autoexpire)) ? $node->autoexpire : strtotime($node->autoexpire);
-        // Ad must be in approved state to be able to autoactivate it.
-        if ($node->adstatus != 'approved' && $node->autoactivate) {
-          if ($node->adstatus == 'active') {
-            // This ad is already active, no need to autoactivate it.
-            drupal_set_message(t('This ad is already active, ignoring autoactivate date.'));
-            $node->autoactivate = 0;
-          }
-          else {
-            drupal_set_message(t('This ad will not be automatically activated at the scheduled time because it is not in the <em>approved</em> state.'), 'error');
-          }
-        }
-        // If this node has been upublished, the ad should no longer be active.
-        if ($node->status != 1 && $node->adstatus == 'active') {
-          $node->adstatus = 'expired';
-        }
-        // Check if ad is being manually activated.
-        if ($ad->adstatus != 'active' && $node->adstatus == 'active') {
-          $activated = time();
-        }
-        // Check if ad is being manually expired.
-        else if ($ad->adstatus != 'expired' && $node->adstatus == 'expired') {
-          // Ad has been manually expired.
-          $activated = $ad->activated;
-          $expired = time();
-        }
-        // Ad has not been manually activated or expired, preserve timestamps.
-        else {
-          $activated = $ad->activated;
-          $expired = $ad->expired;
-        }
-        // Ad status has changed, record the event.
-        if ($ad->adstatus != $node->adstatus) {
-          ad_statistics_increment($node->nid, $node->adstatus);
-        }
-        // Update ads table with new information.
-        db_query("UPDATE {ads} SET uid = %d, adstatus = '%s', adtype = '%s', redirect = '%s', autoactivate = %d, autoexpire = %d, activated = %d, maxviews = %d, maxclicks = %d, expired = %d WHERE aid = %d", $node->uid, $node->adstatus, $node->adtype, url('ad/redirect/'. $node->nid, array('absolute' => TRUE)), $node->autoactivate, $node->autoexpire, isset($activated) ? $activated : 0, isset($node->maxviews) ? (int)$node->maxviews : 0, isset($node->maxclicks) ? (int)$node->maxclicks : 0, isset($expired) ? $expired : 0, $node->nid);
-        ad_statistics_increment($node->nid, 'update');
+/**
+ * Implements hook_node_insert().
+ */
+function ad_node_insert($node) {
+  if (isset($node->adtype)) {
+    if ($node->status != 1 && $node->adstatus == 'active') {
+      $node->adstatus = 'expired';
+    }
+    $activated = $node->adstatus == 'active' ? REQUEST_TIME : 0;
+    $node->autoactivate = isset($node->autoactivate) ? trim($node->autoactivate) : 0;
+    $node->autoactivate = is_numeric($node->autoactivate) ? $node->autoactivate : strtotime($node->autoactivate);
+    $node->autoexpire = isset($node->autoexpire) ? trim($node->autoexpire) : 0;
+    $node->autoexpire = is_numeric($node->autoexpire) ? $node->autoexpire : strtotime($node->autoexpire);
+    if (!isset($node->maxviews)) {
+      $node->maxviews = 0;
+    }
+    if (!isset($node->maxclicks)) {
+      $node->maxclicks = 0;
+    }
+    db_insert('ads')
+      ->fields(array(
+        'aid' => $node->nid,
+        'uid' => $node->uid,
+        'adstatus' => $node->adstatus,
+        'adtype' => $node->adtype,
+        'redirect' => url('ad/redirect/' . $node->nid, array('absolute' => TRUE)),
+        'autoactivate' => $node->autoactivate ? strtotime($node->autoactivate) : 0,
+        'autoexpire' => $node->autoexpire ? strtotime($node->autoexpire) : 0,
+        'activated' => $activated,
+        'maxviews' => $node->maxviews,
+        'maxclicks' => $node->maxclicks,
+      ))
+      ->execute();
+    ad_statistics_increment($node->nid, 'create');
+  }
+  ad_node_invoke_adapi($node, 'insert');
+}
+
+/**
+ * Implements hook_node_update().
+ */
+function ad_node_update($node) {
+  if (isset($node->adtype)) {
+    $ad = db_select('ads')
+      ->fields('ads')
+      ->condition('aid', $node->nid)
+      ->execute()
+      ->fetchObject();
+    $node->autoactivate = isset($node->autoactivate) ? trim($node->autoactivate) : 0;
+    $node->autoactivate = is_numeric($node->autoactivate) ? $node->autoactivate : strtotime($node->autoactivate);
+    $node->autoexpire = isset($node->autoexpire) ? trim($node->autoexpire) : 0;
+    $node->autoexpire = is_numeric($node->autoexpire) ? $node->autoexpire : strtotime($node->autoexpire);
+    // Ad must be in approved state to be able to autoactivate it.
+    if ($node->adstatus != 'approved' && $node->autoactivate) {
+      if ($node->adstatus == 'active') {
+        // This ad is already active, no need to autoactivate it.
+        drupal_set_message(t('This ad is already active, ignoring autoactivate date.'));
+        $node->autoactivate = 0;
       }
-      break;
+      else {
+        drupal_set_message(t('This ad will not be automatically activated at the scheduled time because it is not in the <em>approved</em> state.'), 'error');
+      }
+    }
+    // If this node has been upublished, the ad should no longer be active.
+    if ($node->status != 1 && $node->adstatus == 'active') {
+      $node->adstatus = 'expired';
+    }
+    // Check if ad is being manually activated.
+    if ($ad->adstatus != 'active' && $node->adstatus == 'active') {
+      $activated = REQUEST_TIME;
+    }
+    // Check if ad is being manually expired.
+    elseif ($ad->adstatus != 'expired' && $node->adstatus == 'expired') {
+      // Ad has been manually expired.
+      $activated = $ad->activated;
+      $expired = REQUEST_TIME;
+    }
+    // Ad has not been manually activated or expired, preserve timestamps.
+    else {
+      $activated = $ad->activated;
+      $expired = $ad->expired;
+    }
+    // Ad status has changed, record the event.
+    if ($ad->adstatus != $node->adstatus) {
+      ad_statistics_increment($node->nid, $node->adstatus);
+    }
+    // Update ads table with new information.
+    db_update('ads')
+      ->fields(array(
+        'uid' => $node->uid,
+        'adstatus' => $node->adstatus,
+        'adtype' => $node->adtype,
+        'redirect' => url('ad/redirect/' . $node->nid, array('absolute' => TRUE)),
+        'autoactivate' => $node->autoactivate,
+        'autoexpire' => $node->autoexpire,
+        'activated' => isset($activated) ? $activated : 0,
+        'maxviews' => isset($node->maxviews) ? (int) $node->maxviews : 0,
+        'maxclicks' => isset($node->maxclicks) ? (int) $node->maxclicks : 0,
+        'expired' => isset($expired) ? $expired : 0
+      ))
+      ->condition('aid', $node->nid)
+      ->execute();
+    ad_statistics_increment($node->nid, 'update');
+  }
+  ad_node_invoke_adapi($node, 'update');
+}
 
-    case 'delete':
-      // All that's left of the ad is a single timestamp as to when it was
-      // deleted.
-      ad_statistics_increment($node->nid, 'delete');
-      db_query("DELETE FROM {ads} WHERE aid = %d", $node->nid);
-      db_query("DELETE FROM {ad_statistics} WHERE aid = %d", $node->nid);
-      break;
+/**
+ * Implements hook_node_delete().
+ */
+function ad_node_delete($node) {
+  // All that's left of the ad is a single timestamp as to when it was
+  // deleted.
+  ad_statistics_increment($node->nid, 'delete');
+  db_delete('ads')
+    ->condition('aid', $node->nid)
+    ->execute();
+  db_delete('ad_statistics')
+    ->condition('aid', $node->nid)
+    ->execute();
+  ad_node_invoke_adapi($node, 'delete');
+}
 
-    case 'view':
-      if (isset($node->adtype)) {
-        if (variable_get('ad_meta_noindex', 0)) {
-          ad_noindex_meta();
-        }
-        $node = node_prepare($node, $teaser);
-        $node->content['body'] = array(
-          '#value' => $teaser ? $node->teaser : theme('node_ad', $node, $page),
-          '#weight' => 1,
-        );
-      }
-      break;
+/**
+ * Implements hook_node_view().
+ */
+function ad_node_view($node, $view_mode, $langcode) {
+  if (isset($node->adtype)) {
+    if (variable_get('ad_meta_noindex', 0)) {
+      ad_noindex_meta();
+    }
+    $page = $view_mode == 'full';
+    $teaser = $view_mode == 'teaser' || !$page;
+    $node->content['body'] = array(
+      '#markup' => $teaser ? '' : theme('node_ad', array('node' => $node, 'yield_form' => $page)),
+      '#weight' => 1,
+    );
+  }
+  ad_node_invoke_adapi($node, 'view');
+}
 
-    case 'validate':
-      $autoactivate = isset($node->autoactivate) ? trim($node->autoactivate) : '';
-      if (!empty($autoactivate)) {
-        $timestamp = (is_numeric($autoactivate)) ? $autoactivate : strtotime($autoactivate);
-        if ($timestamp <= 0) {
-          form_set_error('autoactivate', 'Please select a valid time to automatically active this ad.');
-        }
-      }
-      $autoexpire = isset($node->autoexpire) ? trim($node->autoexpire) : '';
-      if (!empty($autoexpire)) {
-        $timestamp = (is_numeric($autoexpire)) ? $autoexpire : strtotime($autoexpire);
-        if ($timestamp <= 0) {
-          form_set_error('autoexpire', 'Please select a valid time to automatically expire this ad.');
-        }
-      }
-      break;
+/**
+ * Implements hook_node_validate().
+ */
+function ad_node_validate($node) {
+  $autoactivate = isset($node->autoactivate) ? trim($node->autoactivate) : '';
+  if (!empty($autoactivate)) {
+    $timestamp = (is_numeric($autoactivate)) ? $autoactivate : strtotime($autoactivate);
+    if ($timestamp <= 0) {
+      form_set_error('autoactivate', 'Please select a valid time to automatically active this ad.');
+    }
   }
+  $autoexpire = isset($node->autoexpire) ? trim($node->autoexpire) : '';
+  if (!empty($autoexpire)) {
+    $timestamp = (is_numeric($autoexpire)) ? $autoexpire : strtotime($autoexpire);
+    if ($timestamp <= 0) {
+      form_set_error('autoexpire', 'Please select a valid time to automatically expire this ad.');
+    }
+  }
+  ad_node_invoke_adapi($node, 'validate');
+}
+
+function ad_node_invoke_adapi($node, $op, $hook = TRUE) {
   // Allow ad type module to act on nodeapi events.  The adapi hook provides
   // access to additional variables not available in the nodeapi hook.
-  if (isset($node->adtype)) {
-    $module = "ad_{$node->adtype}";
-    module_invoke("ad_{$node->adtype}", adapi, $op, $node);
+  if ($hook && isset($node->adtype)) {
+    module_invoke("ad_{$node->adtype}", 'adapi', $op, $node);
   }
+
   // Allow ad cache module to act on nodeapi events.
   $cache = variable_get('ad_cache', 'none');
   if ($cache != 'none') {
-    $function = "ad_cache_$cache" .'_adcacheapi';
+    $function = "ad_cache_{$cache}_adcacheapi";
     if (function_exists($function)) {
       $function($op, $node);
     }
@@ -1056,6 +1180,7 @@ function ad_nodeapi(&$node, $op, $teaser, $page) {
           isset($node->adtype)) {
         ad_rebuild_cache();
       }
+      break;
   }
 }
 
@@ -1065,7 +1190,13 @@ function ad_nodeapi(&$node, $op, $teaser, $page) {
 function ad_noindex_meta() {
   static $added = FALSE;
   if (!$added) {
-    drupal_set_html_head('<meta name="robots" content="noindex" />');
+    drupal_add_html_head(array(
+      '#tag' => 'meta',
+      '#attributues' => array(
+        'name' => 'robots',
+        'content' => 'noindex',
+      ),
+    ), 'meta_robots');
     $added = TRUE;
   }
 }
@@ -1121,11 +1252,6 @@ function ad_menu() {
     'weight' => 3,
     'file' => 'ad.admin.inc',
   );
-  $items['node/add/ad/ahah'] = array(
-    'access arguments' => array('create advertisements'),
-    'page callback' => 'ad_form_ahah',
-    'type' => MENU_CALLBACK,
-  );
 
   ad_menu_add_global_settings($items);
 
@@ -1184,17 +1310,17 @@ function ad_menu() {
     'page callback' => 'ad_click_details',
     'page arguments' => array(1, 3),
     'access arguments' => array(1, 'access click history'),
-    'access callback' => 'ad_permission',
+    'access callback' => 'ad_access_permission',
     'type' => MENU_CALLBACK,
     'file' => 'ad.pages.inc',
   );
 
   $items["node/%node/activity"] = array(
-    'title' => t('Activity log'),
+    'title' => 'Activity log',
     'page callback' => 'ad_activity_details',
     'page arguments' => array(1),
     'access arguments' => array(1, 'access activity log'),
-    'access callback' => 'ad_permission',
+    'access callback' => 'ad_access_permission',
     'type' => MENU_LOCAL_TASK,
     'file' => 'ad.pages.inc',
   );
@@ -1217,13 +1343,13 @@ function ad_menu_add_global_settings(&$menu_items) {
   $adtypes = ad_get_types();
   foreach ($adtypes as $type => $name) {
     // Ad type global settings.
-    $settings = 'ad_'. $type .'_global_settings';
+    $settings = 'ad_' . $type . '_global_settings';
     $file = 'ad_image.module';
     if (!function_exists($settings)) {
       $settings = 'ad_no_global_settings';
       $file = 'ad.admin.inc';
     }
-    $menu_items['admin/content/ad/configure/'. $type] = array(
+    $menu_items['admin/content/ad/configure/' . $type] = array(
       'title' => $name,
       'page callback' => 'drupal_get_form',
       'page arguments' => array($settings),
@@ -1250,36 +1376,47 @@ function ad_group_load($tid) {
 }
 
 /**
- * Implementation of hook_block().
+ * Implements of hook_block_info().
  */
-function ad_block($op = 'list', $delta = 0, $edit = array()) {
-  switch ($op) {
-    case 'list':
-      $blocks = array();
-      $groups = ad_groups_list();
-      foreach ($groups as $tid => $name) {
-        $blocks[$tid] = array(
-          'info' => t('ad group: @name', array('@name' => $name)),
-          'cache' => BLOCK_CACHE_PER_PAGE,
-        );
-      }
-      return $blocks;
-    case 'configure':
-      $form['ad_block_quantity_'. $delta] = array(
-        '#type' => 'select',
-        '#title' => t('Number of ads'),
-        '#default_value' => variable_get('ad_block_quantity_'. $delta, 1),
-        '#options' => drupal_map_assoc(array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25)),
-        '#description' => t('Select the maximum number of unique ads that should be displayed together in this block.  If you specify a number larger than the maximum number of ads in this ad group, all ads will be displayed once.'),
-      );
-      return $form;
-    case 'save':
-      variable_set('ad_block_quantity_'. $delta, $edit['ad_block_quantity_'. $delta]);
-      break;
-    case 'view':
-      $block['content'] = ad($delta, variable_get('ad_block_quantity_'. $delta, 1));
-      return $block;
+function ad_block_info() {
+  $blocks = array();
+  $groups = ad_groups_list();
+  foreach ($groups as $tid => $name) {
+    $blocks[$tid] = array(
+      'info' => t('ad group: @name', array('@name' => $name)),
+      'cache' => DRUPAL_CACHE_PER_PAGE,
+    );
   }
+  return $blocks;
+}
+
+/**
+ * Implements of hook_block_configure().
+ */
+function ad_block_configure($delta = '') {
+  $form['ad_block_quantity_' . $delta] = array(
+    '#type' => 'select',
+    '#title' => t('Number of ads'),
+    '#default_value' => variable_get('ad_block_quantity_' . $delta, 1),
+    '#options' => drupal_map_assoc(array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25)),
+    '#description' => t('Select the maximum number of unique ads that should be displayed together in this block.  If you specify a number larger than the maximum number of ads in this ad group, all ads will be displayed once.'),
+  );
+  return $form;
+}
+
+/**
+ * Implements of hook_block_save().
+ */
+function ad_block_save($delta = '', $edit = array()) {
+  variable_set('ad_block_quantity_' . $delta, $edit['ad_block_quantity_' . $delta]);
+}
+
+/**
+ * Implements of hook_block_view().
+ */
+function ad_block_view($delta = '') {
+  $block['content'] = ad($delta, variable_get('ad_block_quantity_' . $delta, 1));
+  return $block;
 }
 
 /**
@@ -1292,7 +1429,7 @@ function ad_block($op = 'list', $delta = 0, $edit = array()) {
  * @param $account
  *   User object, which are accessing the ad or current user by default.
  */
-function ad_permission($aid, $string, $account = NULL) {
+function ad_access_permission($aid, $string, $account = NULL) {
   global $user;
   $access = FALSE;
 
@@ -1315,11 +1452,11 @@ function ad_permission($aid, $string, $account = NULL) {
   if (is_object($aid) && isset($aid->aid)) {
     $aid = $aid->aid;
   }
-  else if (is_object($aid) && isset($aid->nid)) {
+  elseif (is_object($aid) && isset($aid->nid)) {
     $aid = $aid->nid;
   }
-  else if (is_object($aid)) {
-    watchdog('ad', 'Invalid aid object passed into ad_permission, no aid->aid set.');
+  elseif (is_object($aid)) {
+    watchdog('ad', 'Invalid aid object passed into ad_access_permission, no aid->aid set.');
     $aid = 0;
   }
 
@@ -1329,7 +1466,7 @@ function ad_permission($aid, $string, $account = NULL) {
     $access = ad_owners_permission($aid, $string, $account);
   }
   // no ad_owners module, allow acces to statistics and click history
-  else if (in_array($string, array('access statistics', 'access click history'))) {
+  elseif (in_array($string, array('access statistics', 'access click history'))) {
     $access = TRUE;
   }
   // with no ad_owners module, all other permissions are denied unless user
@@ -1403,7 +1540,7 @@ function ad_groups_list($object = FALSE, $tid = NULL) {
       $groups[0]->weight = 0;
     }
     // Return a specific group object.
-    if ((int)$tid) {
+    if ((int) $tid) {
       return $groups[$tid];
     }
     // Return an array of all group objects.
@@ -1424,7 +1561,7 @@ function ad_groups_list($object = FALSE, $tid = NULL) {
       $names[0] = t('default');
     }
     // Return a specific group name.
-    if ((int)$tid) {
+    if ((int) $tid) {
       return $names[$tid];
     }
     // Return an array of all group names.
@@ -1440,7 +1577,7 @@ function _ad_check_installation() {
   $adserveinc = variable_get('adserveinc', '');
   if (!file_exists($adserve)) {
     // The serve.php file should be in the same directory as the ad.module.
-    $adserve = drupal_get_path('module', 'ad') .'/serve.php';
+    $adserve = drupal_get_path('module', 'ad') . '/serve.php';
     variable_set('adserve', $adserve);
   }
   if (!is_readable($adserve)) {
@@ -1449,7 +1586,7 @@ function _ad_check_installation() {
   }
   if (!file_exists($adserveinc)) {
     // The adserve.inc file should be in the same directory as the ad.module.
-    $adserveinc = drupal_get_path('module', 'ad') .'/adserve.inc';
+    $adserveinc = drupal_get_path('module', 'ad') . '/adserve.inc';
     variable_set('adserveinc', $adserveinc);
   }
   if (!is_readable($adserveinc)) {
@@ -1457,12 +1594,14 @@ function _ad_check_installation() {
     drupal_set_message(t('Failed to read the required file %filename.  Please make the file readable by the webserver process.  No ads can be displayed until this problem is resolved.', array('%filename' => $adserveinc)), 'error');
   }
 
+  // TODO not working yet
+  /*
   // Validate vid in vocabulary table.
-  $vid = db_result(db_query("SELECT vid FROM {vocabulary} WHERE module = 'ad'"));
+  $vid = db_query("SELECT vid FROM {taxonomy_vocabulary} WHERE module = ?", array('ad'))->fetchField();
   if ($vid != variable_get('ad_group_vid', '')) {
     drupal_set_message(t('Invalid vocabulary defined for advertisements, attempting to auto-fix.'), 'error');
     if ($vid) {
-      db_query("DELETE FROM {vocabulary_node_types} WHERE vid = %d OR type = 'ad'", variable_get('ad_group_vid', ''));
+      db_query("DELETE FROM {taxonomy_vocabulary_node_types} WHERE vid = %d OR type = 'ad'", variable_get('ad_group_vid', ''));
       variable_set('ad_group_vid_restore', variable_get('ad_group_vid', ''));
     }
     variable_del('ad_group_vid');
@@ -1478,8 +1617,8 @@ function _ad_check_installation() {
     }
     if (!$found) {
       drupal_set_message(t('Missing vocabulary node type for advertisements, attempting to auto-fix.'), 'error');
-      db_query("DELETE FROM {vocabulary_node_types} WHERE vid = %d OR type = 'ad'", variable_get('ad_group_vid', ''));
-      db_query("DELETE FROM {vocabulary} WHERE vid = %d", variable_get('ad_group_vid', ''));
+      db_query("DELETE FROM {taxonomy_vocabulary_node_types} WHERE vid = ? OR type = ?", array(variable_get('ad_group_vid', ''), 'ad'));
+      db_query("DELETE FROM {taxonomy_vocabulary} WHERE vid = ?", array(variable_get('ad_group_vid', '')));
       variable_set('ad_group_vid_restore', variable_get('ad_group_vid', ''));
       variable_del('ad_group_vid');
     }
@@ -1490,13 +1629,14 @@ function _ad_check_installation() {
   if (($old = variable_get('ad_group_vid_restore', '')) &&
        $vid = variable_get('ad_group_vid', '')) {
     drupal_set_message(t('Restoring orphaned ad group configuration.'));
-    db_query('UPDATE {term_data} SET vid = %d WHERE vid = %d', $vid, $old);
+    db_query('UPDATE {term_data} SET vid = ? WHERE vid = ?', array($vid, $old));
     variable_set('ad_group_vid_restore', '');
   }
+  */
 
-  $rid = db_result(db_query_range("SELECT rid FROM {permission} WHERE perm LIKE '%%show advertisements%%'", 1));
+  $rid = db_query("SELECT rid FROM {role_permission} WHERE permission LIKE '%%show advertisements%%'")->fetchField();
   if (!$rid) {
-    drupal_set_message(t('Be sure to enable "!show" permissions for all roles that you wish to see advertisements.', array('!show' => l(t('show advertisements'), 'admin/user/permissions'))));
+    drupal_set_message(t('Be sure to enable "!show" permissions for all roles that you wish to see advertisements.', array('!show' => l(t('show advertisements'), 'admin/people/permissions'))));
   }
 
   // Allow modules to define an action to take each time an ad is served.
@@ -1523,8 +1663,8 @@ function _ad_check_installation() {
         // weight is an optional, defaults to 0
         $weight = $action['weight'] = 0;
       }
-      $actions[$weight .'.'. $name] = $action;
-      $actions[$weight .'.'. $name]['name'] = $name;
+      $actions[$weight . '.' . $name] = $action;
+      $actions[$weight . '.' . $name]['name'] = $name;
     }
     // order actions by weight (multiple same-weight actions sorted by alpha)
     ksort($actions);
@@ -1538,24 +1678,21 @@ function _ad_check_installation() {
  * Creates a vocabulary for use by ad groups if not already created.
  */
 function _ad_get_vid() {
-  $vid = variable_get('ad_group_vid', '');
+  $vid = variable_get('ad_group_vid');
   if (empty($vid)) {
     // No vid stored in the variables table, check if one even exists.
-    $vid = db_result(db_query("SELECT vid FROM {vocabulary} WHERE module = '%s'", 'ad'));
+    $vid = db_query("SELECT vid FROM {taxonomy_vocabulary} WHERE module = ?", array('ad'))->fetchField();
     if (!$vid) {
       // No vid, so we create one.
-      $edit = array(
+      $vocabulary = (object) array(
         'name' => t('Ad groups'),
-        'multiple' => 1,
-        'required' => 0,
-        'hierarchy' => 0,
-        'relations' => 0,
+        'machine_name' => 'ad_groups',
+        'hierarchy' => FALSE,
         'module' => 'ad',
-        'nodes' => array('ad' => 1)
       );
 
-      taxonomy_save_vocabulary($edit);
-      $vid = $edit['vid'];
+      taxonomy_vocabulary_save($vocabulary);
+      $vid = $vocabulary->vid;
     }
     // Save the vid for next time.
     variable_set('ad_group_vid', $vid);
@@ -1573,11 +1710,11 @@ function ad_display_image($aid, $css = TRUE) {
   $variables = "?o=image";
   $variables .= "&a=$aid";
   if ($cache != 'none') {
-    $variables .= '&c='. $cache . module_invoke('ad_cache_'. $cache, 'adcacheapi', 'display_variables', array());
+    $variables .= '&c=' . $cache . module_invoke('ad_cache_' . $cache, 'adcacheapi', 'display_variables', array());
   }
-  $output = '<img src="'. htmlentities(url($base_url .'/'. $adserve . $variables)) .'" height="0" width="0" alt="view counter" />';
+  $output = '<img src="' . check_plain(url($base_url . '/' . $adserve . $variables)) . '" height="0" width="0" alt="view counter" />';
   if ($css) {
-    return '<div class="ad-image-counter">'. $output .'</div>';
+    return '<div class="ad-image-counter">' . $output . '</div>';
   }
   else {
     return $output;
@@ -1591,11 +1728,16 @@ function _ad_get_group($nid) {
   static $groups = array();
 
   if (!isset($groups[$nid])) {
-    $result = db_query('SELECT d.name FROM {term_data} d LEFT JOIN {term_node} n ON d.tid = n.tid WHERE n.nid = %d AND d.vid = %d', $nid, _ad_get_vid());
-    while ($term = db_fetch_object($result)) {
-      $terms[] = $term->name;
-    }
-    if (!empty($terms)) {
+    $ad = node_load($nid);
+    if (!empty($ad->ad_group[LANGUAGE_NONE][0]['tid'])) {
+      $term_ids = array();
+      foreach ($ad->ad_group[LANGUAGE_NONE] as $array) {
+        $term_ids[] = $array['tid'];
+      }
+      $terms = array();
+      foreach (taxonomy_term_load_multiple($term_ids) as $term) {
+        $terms[] = $term->name;
+      }
       $groups[$nid] = implode(', ', $terms);
     }
     else {
@@ -1605,4 +1747,3 @@ function _ad_get_group($nid) {
 
   return $groups[$nid];
 }
-
diff --git ad.pages.inc ad.pages.inc
index 281642f..2b0b1d5 100644
--- ad.pages.inc
+++ ad.pages.inc
@@ -8,13 +8,15 @@
  *   Jeremy Andrews <jeremy@tag1consulting.com>
  */
 
-function theme_node_ad($node, $yield_form = TRUE) {
+function theme_node_ad($variables) {
+  $node = $variables['node'];
+  $yield_form = $variables['yield_form'];
   $output = '';
-  if (ad_permission($node, 'access statistics')) {
-    $output = theme('ad_status_display', $node);
-    $output .= theme('ad_statistics_display', ad_statistics($node->nid));
+  if (ad_access_permission($node, 'access statistics')) {
+    $output = theme('ad_status_display', array('node' => $node));
+    $output .= theme('ad_statistics_display', array('statistics' => ad_statistics($node->nid)));
   }
-  if (ad_permission($node, 'access click history')) {
+  if (ad_access_permission($node, 'access click history')) {
     $header = array(
       array('data' => t('Time'), 'field' => 'timestamp', 'sort' => 'desc'),
       array('data' => t('User'), 'field' => 'uid'),
@@ -26,43 +28,46 @@ function theme_node_ad($node, $yield_form = TRUE) {
     $header[] = '';
 
     if (isset($node->nid) && $node->nid > 0) {
-      $sql = "SELECT cid, timestamp, uid, status, hostname, url FROM {ad_clicks} WHERE aid = %d";
-      $sql .= tablesort_sql($header);
-      $result = pager_query($sql, 25, 0, NULL, $node->nid);
+      $result = db_select('ad_clicks', 'a')
+        ->fields('a', array('cid', 'timestamp', 'uid', 'status', 'hostname', 'url'))
+        ->condition('aid', $node->nid)
+        ->extend('PagerDefault')->limit(25)
+        ->extend('TableSort')->orderByHeader($header)
+        ->execute();
 
-      while ($ad = db_fetch_object($result)) {
+      foreach ($result as $ad) {
         if (module_exists('click_filter') && $ad->status != CLICK_VALID) {
           // Only show filtered clicks to users with permission to view them.
           if (!user_access('view filtered clicks')) {
             continue;
           }
         }
-        if (strlen($ad->url) > 40) {
-          $url = substr($ad->url, 0, 37) .'...';
+        if (drupal_strlen($ad->url) > 40) {
+          $url = drupal_substr($ad->url, 0, 37) . '...';
         }
         else {
           $url = $ad->url;
         }
         $row = array();
-        $click_user = user_load(array('uid' => $ad->uid));
+        $click_user = user_load($ad->uid);
         $row[] = format_date($ad->timestamp, 'custom', 'M j H:i');
-        $row[] = theme('username', $click_user);
+        $row[] = theme('username', array('account' => $click_user));
         $row[] = l($url, $ad->url);
         if (function_exists('click_filter_status_text') && user_access('view filtered clicks')) {
           $row[] = click_filter_status_text($ad->status);
         }
-        $row[] = '['. l(t('details'), 'node/'. $node->nid .'/details/'. $ad->cid) .']';
+        $row[] = '[' . l(t('details'), 'node/' . $node->nid . '/details/' . $ad->cid) . ']';
         $rows[] = $row;
       }
 
       if (empty($rows)) {
-        $click_history = '<p>'. t('There are no clicks yet.') .'</p>';
+        $click_history = '<p>' . t('There are no clicks yet.') . '</p>';
       }
       else {
-        $click_history = theme('table', $header, $rows);
+        $click_history = theme('table', array('header' => $header, 'rows' => $rows));
       }
-      $click_history .= theme('pager', NULL, 25, 0);
-      $output .= theme('box', t('Click history'), $click_history);
+      $click_history .= theme('pager', array('tags' => NULL, 'limit' => 25, 'element' => 0));
+      $output .= '<h2 class="title">' . t('Click history') . '</h2><div>' . $click_history . '</div>';
     }
   }
   return $output;
@@ -74,8 +79,8 @@ function theme_node_ad($node, $yield_form = TRUE) {
  */
 function ad_statistics($aid) {
   // Get global statistics.
-  $statistics['global']['views'] = (int)db_result(db_query("SELECT SUM(count) FROM {ad_statistics} WHERE aid = %d AND action = 'view'", $aid));
-  $statistics['global']['clicks'] = (int)db_result(db_query("SELECT SUM(count) FROM {ad_statistics} WHERE aid = %d AND action = 'click'", $aid));
+  $statistics['global']['views'] = (int) db_query("SELECT SUM(count) FROM {ad_statistics} WHERE aid = ? AND action = 'view'", array($aid))->fetchField();
+  $statistics['global']['clicks'] = (int) db_query("SELECT SUM(count) FROM {ad_statistics} WHERE aid = ? AND action = 'click'", array($aid))->fetchField();
 
   // No sense in making further queries if the ad has no global statistics.
   if (!$statistics['global']['views'] && !$statistics['global']['clicks']) {
@@ -84,11 +89,11 @@ function ad_statistics($aid) {
 
   // Get statistics for this year and last year.
   $this_year = date('Y000000');
-  $last_year = date('Y') - 1 .'000000';
-  $statistics['last_year']['views'] = (int)db_result(db_query("SELECT SUM(count) FROM {ad_statistics} WHERE aid = %d AND action = 'view' AND date >= %d AND date <= %d", $aid, $last_year, $this_year));
-  $statistics['last_year']['clicks'] = (int)db_result(db_query("SELECT SUM(count) FROM {ad_statistics} WHERE aid = %d AND action = 'click' AND date >= %d AND date <= %d", $aid, $last_year, $this_year));
-  $statistics['this_year']['views'] = (int)db_result(db_query("SELECT SUM(count) FROM {ad_statistics} WHERE aid = %d AND action = 'view' AND date >= %d", $aid, $this_year));
-  $statistics['this_year']['clicks'] = (int)db_result(db_query("SELECT SUM(count) FROM {ad_statistics} WHERE aid = %d AND action = 'click' AND date >= %d", $aid, $this_year));
+  $last_year = date('Y') - 1 . '000000';
+  $statistics['last_year']['views'] = (int) db_query("SELECT SUM(count) FROM {ad_statistics} WHERE aid = ? AND action = 'view' AND date >= ? AND date <= ?", array($aid, $last_year, $this_year))->fetchField();
+  $statistics['last_year']['clicks'] = (int) db_query("SELECT SUM(count) FROM {ad_statistics} WHERE aid = ? AND action = 'click' AND date >= ? AND date <= ?", array($aid, $last_year, $this_year))->fetchField();
+  $statistics['this_year']['views'] = (int) db_query("SELECT SUM(count) FROM {ad_statistics} WHERE aid = ? AND action = 'view' AND date >= ?", array($aid, $this_year))->fetchField();
+  $statistics['this_year']['clicks'] = (int) db_query("SELECT SUM(count) FROM {ad_statistics} WHERE aid = ? AND action = 'click' AND date >= ?", array($aid, $this_year))->fetchField();
 
   // No sense in making further queries if the ad has no statistics this year.
   if (!$statistics['this_year']['views'] && !$statistics['this_year']['clicks']) {
@@ -99,15 +104,15 @@ function ad_statistics($aid) {
   $this_month = date('Ym0000');
   $last_month = date('m') - 1;
   if ($last_month == 0) {
-    $last_month = date('Y') - 1 .'120000';
+    $last_month = date('Y') - 1 . '120000';
   }
   else {
-    $last_month = date('Y') . ($last_month < 10 ? '0' : '') . $last_month .'0000';
+    $last_month = date('Y') . ($last_month < 10 ? '0' : '') . $last_month . '0000';
   }
-  $statistics['last_month']['views'] = (int)db_result(db_query("SELECT SUM(count) FROM {ad_statistics} WHERE aid = %d AND action = 'view' AND date >= %d AND date <= %d", $aid, $last_month, $this_month));
-  $statistics['last_month']['clicks'] = (int)db_result(db_query("SELECT SUM(count) FROM {ad_statistics} WHERE aid = %d AND action = 'click' AND date >= %d AND date <= %d", $aid, $last_month, $this_month));
-  $statistics['this_month']['views'] = (int)db_result(db_query("SELECT SUM(count) FROM {ad_statistics} WHERE aid = %d AND action = 'view' AND date >= %d", $aid, $this_month));
-  $statistics['this_month']['clicks'] = (int)db_result(db_query("SELECT SUM(count) FROM {ad_statistics} WHERE aid = %d AND action = 'click' AND date >= %d", $aid, $this_month));
+  $statistics['last_month']['views'] = (int) db_query("SELECT SUM(count) FROM {ad_statistics} WHERE aid = ? AND action = 'view' AND date >= ? AND date <= ?", array($aid, $last_month, $this_month))->fetchField();
+  $statistics['last_month']['clicks'] = (int) db_query("SELECT SUM(count) FROM {ad_statistics} WHERE aid = ? AND action = 'click' AND date >= ? AND date <= ?", array($aid, $last_month, $this_month))->fetchField();
+  $statistics['this_month']['views'] = (int) db_query("SELECT SUM(count) FROM {ad_statistics} WHERE aid = ? AND action = 'view' AND date >= ?", array($aid, $this_month))->fetchField();
+  $statistics['this_month']['clicks'] = (int) db_query("SELECT SUM(count) FROM {ad_statistics} WHERE aid = ? AND action = 'click' AND date >= ?", array($aid, $this_month))->fetchField();
 
   // No sense in making further queries if the ad has no statistics this month.
   if (!$statistics['this_month']['views'] && !$statistics['this_month']['clicks']) {
@@ -115,9 +120,9 @@ function ad_statistics($aid) {
   }
 
   // Get statistics for this week.
-  $this_week_start = date('Ymd00', time() - 60*60*24*6);
-  $statistics['this_week']['views'] = (int)db_result(db_query("SELECT SUM(count) FROM {ad_statistics} WHERE aid = %d AND action = 'view' AND date > %d", $aid, $this_week_start));
-  $statistics['this_week']['clicks'] = (int)db_result(db_query("SELECT SUM(count) FROM {ad_statistics} WHERE aid = %d AND action = 'click' AND date > %d", $aid, $this_week_start));
+  $this_week_start = date('Ymd00', REQUEST_TIME - 60*60*24*6);
+  $statistics['this_week']['views'] = (int) db_query("SELECT SUM(count) FROM {ad_statistics} WHERE aid = ? AND action = 'view' AND date > ?", array($aid, $this_week_start))->fetchField();
+  $statistics['this_week']['clicks'] = (int) db_query("SELECT SUM(count) FROM {ad_statistics} WHERE aid = ? AND action = 'click' AND date > ?", array($aid, $this_week_start))->fetchField();
 
   // No sense in making further queries if the ad has no statistics this week.
   if (!$statistics['this_week']['views'] && !$statistics['this_week']['clicks']) {
@@ -125,13 +130,13 @@ function ad_statistics($aid) {
   }
 
   // Get statistics for yesterday and today.
-  $yesterday_start = date('Ymd00', time() - 60*60*24);
-  $yesterday_end = date('Ymd24', time() - 60*60*24);
-  $today_start = date('Ymd00', time());
-  $statistics['yesterday']['views'] = (int)db_result(db_query("SELECT SUM(count) FROM {ad_statistics} WHERE aid = %d AND action = 'view' AND date >= %d AND date <= %d", $aid, $yesterday_start, $yesterday_end));
-  $statistics['yesterday']['clicks'] = (int)db_result(db_query("SELECT SUM(count) FROM {ad_statistics} WHERE aid = %d AND action = 'click' AND date >= %d AND date <= %d", $aid, $yesterday_start, $yesterday_end));
-  $statistics['today']['views'] = (int)db_result(db_query("SELECT SUM(count) FROM {ad_statistics} WHERE aid = %d AND action = 'view' AND date >= %d", $aid, $today_start));
-  $statistics['today']['clicks'] = (int)db_result(db_query("SELECT SUM(count) FROM {ad_statistics} WHERE aid = %d AND action = 'click' AND date >= %d", $aid, $today_start));
+  $yesterday_start = date('Ymd00', REQUEST_TIME - 60*60*24);
+  $yesterday_end = date('Ymd24', REQUEST_TIME - 60*60*24);
+  $today_start = date('Ymd00', REQUEST_TIME);
+  $statistics['yesterday']['views'] = (int) db_query("SELECT SUM(count) FROM {ad_statistics} WHERE aid = ? AND action = 'view' AND date >= ? AND date <= ?", array($aid, $yesterday_start, $yesterday_end))->fetchField();
+  $statistics['yesterday']['clicks'] = (int) db_query("SELECT SUM(count) FROM {ad_statistics} WHERE aid = ? AND action = 'click' AND date >= ? AND date <= ?", array($aid, $yesterday_start, $yesterday_end))->fetchField();
+  $statistics['today']['views'] = (int) db_query("SELECT SUM(count) FROM {ad_statistics} WHERE aid = ? AND action = 'view' AND date >= ?", array($aid, $today_start))->fetchField();
+  $statistics['today']['clicks'] = (int) db_query("SELECT SUM(count) FROM {ad_statistics} WHERE aid = ? AND action = 'click' AND date >= ?", array($aid, $today_start))->fetchField();
 
   // No sense in making further queries if the ad has no statistics today.
   if (!$statistics['today']['views'] && !$statistics['today']['clicks']) {
@@ -139,17 +144,18 @@ function ad_statistics($aid) {
   }
 
   // Get statistics for this hour and the last hour.
-  $last_hour = date('YmdH', time() - 60*60);
-  $this_hour = date('YmdH', time());
-  $statistics['last_hour']['views'] = (int)db_result(db_query("SELECT SUM(count) FROM {ad_statistics} WHERE aid = %d AND action = 'view' AND date = %d", $aid, $last_hour));
-  $statistics['last_hour']['clicks'] = (int)db_result(db_query("SELECT SUM(count) FROM {ad_statistics} WHERE aid = %d AND action = 'click' AND date = %d", $aid, $last_hour));
-  $statistics['this_hour']['views'] = (int)db_result(db_query("SELECT SUM(count) FROM {ad_statistics} WHERE aid = %d AND action = 'view' AND date = %d", $aid, $this_hour));
-  $statistics['this_hour']['clicks'] = (int)db_result(db_query("SELECT SUM(count) FROM {ad_statistics} WHERE aid = %d AND action = 'click' AND date = %d", $aid, $this_hour));
+  $last_hour = date('YmdH', REQUEST_TIME - 60*60);
+  $this_hour = date('YmdH', REQUEST_TIME);
+  $statistics['last_hour']['views'] = (int) db_query("SELECT SUM(count) FROM {ad_statistics} WHERE aid = ? AND action = 'view' AND date = ?", array($aid, $last_hour))->fetchField();
+  $statistics['last_hour']['clicks'] = (int) db_query("SELECT SUM(count) FROM {ad_statistics} WHERE aid = ? AND action = 'click' AND date = ?", array($aid, $last_hour))->fetchField();
+  $statistics['this_hour']['views'] = (int) db_query("SELECT SUM(count) FROM {ad_statistics} WHERE aid = ? AND action = 'view' AND date = ?", array($aid, $this_hour))->fetchField();
+  $statistics['this_hour']['clicks'] = (int) db_query("SELECT SUM(count) FROM {ad_statistics} WHERE aid = ? AND action = 'click' AND date = ?", array($aid, $this_hour))->fetchField();
 
   return $statistics;
 }
 
-function theme_ad_statistics_display($statistics) {
+function theme_ad_statistics_display($variables) {
+  $statistics = $variables['statistics'];
   $header = array('', t('Impressions'), t('Clicks'), t('Click-thru'));
   $rows = array();
 
@@ -172,28 +178,28 @@ function theme_ad_statistics_display($statistics) {
         array('data' => $value),
         array('data' => (int)$statistics[$key]['views']),
         array('data' => (int)$statistics[$key]['clicks']),
-        array('data' => $statistics[$key]['views'] ? sprintf('%1.2f', ((int)$statistics[$key]['clicks'] / (int)$statistics[$key]['views']) * 100) .'%' : '0.00%'),
+        array('data' => $statistics[$key]['views'] ? sprintf('%1.2f', ((int) $statistics[$key]['clicks'] / (int) $statistics[$key]['views']) * 100) . '%' : '0.00%'),
       );
     }
   }
   if (empty($rows) || (!$statistics['global']['views'] && !$statistics['global']['clicks'])) {
-    $statistics = '<p>'. t('There are currently no statistics for this advertisement.') .'</p>';
+    $statistics = '<p>' . t('There are currently no statistics for this advertisement.') . '</p>';
   }
   else {
-    $statistics = theme('table', $header, $rows);
+    $statistics = theme('table', array('header' => $header, 'rows' => $rows));
   }
 
-  return theme('box', t('Statistics'), $statistics);
+  return '<h2 class="title">' . t('Statictics') . '</h2><div>' . $statistics . '</div>';
 }
 
 /**
  * Display details about a specific click.
  */
 function ad_click_details($node, $cid) {
-  drupal_set_breadcrumb(array(l(t('Home'), NULL), l(check_plain($node->title), 'node/'. $node->nid)));
-  if ($click = db_fetch_object(db_query('SELECT * FROM {ad_clicks} WHERE cid = %d', $cid))) {
+  drupal_set_breadcrumb(array(l(t('Home'), NULL), l(check_plain($node->title), 'node/' . $node->nid)));
+  if ($click = db_query('SELECT * FROM {ad_clicks} WHERE cid = ?', array($cid))->fetchObject()) {
     $ad = node_load($click->aid);
-    $account = user_load(array('uid' => $click->uid));
+    $account = user_load($click->uid);
     $rows = array(
       array(
         array('data' => t('Time'), 'header' => TRUE),
@@ -201,7 +207,7 @@ function ad_click_details($node, $cid) {
       ),
       array(
         array('data' => t('User'), 'header' => TRUE),
-        theme('username', $account),
+        theme('username', array('account' => $account)),
       ),
       array(
         array('data' => t('IP Address'), 'header' => TRUE),
@@ -244,7 +250,7 @@ function ad_click_details($node, $cid) {
       }
       $rows[] = array(array('data' => t('Status'), 'header' => TRUE), $status);
     }
-    $output = theme('table', array(), $rows);
+    $output = theme('table', array('rows' => $rows));
   }
   return $output;
 }
@@ -252,30 +258,33 @@ function ad_click_details($node, $cid) {
 
 function ad_activity_details($node) {
   $output = '';
-  drupal_set_breadcrumb(array(l(t('Home'), NULL), l(check_plain($node->title), 'node/'. $node->nid)));
-  if (ad_permission($node, 'access click history')) {
+  drupal_set_breadcrumb(array(l(t('Home'), NULL), l(check_plain($node->title), 'node/' . $node->nid)));
+  if (ad_access_permission($node, 'access click history')) {
     $header = array(
       array('data' => t('Date'), 'field' => 'date', 'sort' => 'desc'),
       array('data' => t('Action'), 'field' => 'action'));
     if (isset($node->nid) && $node->nid > 0) {
-      $sql = "SELECT * FROM {ad_statistics} WHERE action NOT IN ('view', 'click') AND aid = %d";
-      $sql .= tablesort_sql($header);
-      $result = pager_query($sql, 25, 0, NULL, $node->nid);
-      while ($ad = db_fetch_object($result)) {
+      $result = db_select('ad_statistics', 'a')->fields('a')
+        ->condition('action', array('view', 'click'), 'NOT IN')
+        ->condition('aid', $node->nid)
+        ->extend('TableSort')->orderByHeader($header)
+        ->extend('PagerDefault')->limit(25)
+        ->execute();
+      foreach ($result as $ad) {
         $row = array();
         $row[] = format_date(strtotime($ad->date . '00'), 'large');
         $row[] = $ad->action;
         $rows[] = $row;
       }
       if (empty($rows)) {
-        $output = '<p>'. t('There is no activity yet.') .'</p>';
+        $output = '<p>' . t('There is no activity yet.') . '</p>';
       }
       else {
-        $output = theme('table', $header, $rows);
+        $output = theme('table', array('header' => $header, 'rows' => $rows));
       }
-      $output .= theme('pager', NULL, 25, 0);
+      $output .= theme('pager');
     }
   }
-  return theme('box', t('Activity'), $output);
+  return '<h2 class="title">' . t('Activity') . '</h2><div>' . $output . '</div>';
 }
 
diff --git ad_token.inc ad_token.inc
index 6fe845a..edf941c 100644
--- ad_token.inc
+++ ad_token.inc
@@ -25,7 +25,7 @@ function ad_token_values($type, $object = NULL, $options = array()) {
         $values['log_message'] = $node->log;
         $values['type'] = $node->adtype;
         $values['status'] = $node->adstatus;
-        $values['url'] = url('node/'. $node->nid, array('absolute' => TRUE));
+        $values['url'] = url('node/' . $node->nid, array('absolute' => TRUE));
         $values['redirect'] = url($node->redirect, array('absolute' => TRUE));
         $values['comments'] = $node->comment_count;
 
diff --git adcache.inc adcache.inc
index 3701d4f..7344f40 100644
--- adcache.inc
+++ adcache.inc
@@ -22,11 +22,11 @@ function adserve_cache() {
 
   if (function_exists($functions[$function])) {
     _debug_memory();
-    _debug_echo("Invoking cache function '". $functions[$function] ."'.");
+    _debug_echo("Invoking cache function '" . $functions[$function] . "'.");
     return call_user_func_array($functions[$function], $args);
   }
   else {
-    _debug_echo("Cache function '". $functions[$function] ."' does not exist.\n");
+    _debug_echo("Cache function '" . $functions[$function] . "' does not exist.\n");
   }
   return array();
 }
@@ -50,7 +50,7 @@ function adserve_invoke_hook() {
       foreach ($hooks[$hook]['file'] as $files) {
         if (is_array($files)) {
           foreach ($files as $file) {
-            $include_file = adserve_variable('root_dir') .'/'. $file;
+            $include_file = adserve_variable('root_dir') . '/' . $file;
             if (file_exists($include_file) && is_file($include_file)) {
               _debug_echo("Including file: '$include_file'.");
               include_once($include_file);
@@ -216,16 +216,42 @@ function adserve_cache_id($type, $id) {
   _debug_echo("adserve_cache_id: type($type) id($id)");
   switch ($type) {
     case 'nids':
-      $result = db_query("SELECT aid FROM {ads} WHERE adstatus = 'active' AND aid IN(%s)", $id);
-      _debug_echo("adserve_cache_id: SELECT aid FROM {ads} WHERE adstatus = 'active' AND aid IN($id)");
+      $result = db_select('ads')
+        ->fields('ads', array('aid'))
+        ->condition('adstatus', 'active')
+        ->condition('aid', explode(',', $id))
+        ->execute();
+      _debug_echo('adserve_cache_id: ' . $result->queryString);
       break;
     case 'tids':
-      $result = db_query("SELECT a.aid FROM {ads} a INNER JOIN {term_node} n ON a.aid = n.nid WHERE a.adstatus = 'active' AND n.tid IN(%s)", $id);
-      _debug_echo("adserve_cache_id: SELECT a.aid FROM {ads} a INNER JOIN {term_node} n ON a.aid = n.nid WHERE a.adstatus = 'active' AND n.tid IN($id)");
+      // First query entity tables
+      $query = new EntityFieldQuery;
+      $entities = $query
+        ->entityCondition('entity_type', 'node')
+        ->fieldCondition('ad_group', 'tid', explode(',', $id))
+        ->execute();
+      // now query active ads in the set
+      $result = db_select('ads')
+        ->fields('ads', array('aid'))
+        ->condition('adstatus', 'active')
+        ->condition('aid', array_keys($entities['node']))
+        ->execute();
+      _debug_echo('adserve_cache_id: ' . $result->queryString);
       break;
     case 'default':
-      $result = db_query("SELECT a.aid FROM {ads} a LEFT JOIN {term_node} n ON a.aid = n.nid WHERE a.adstatus = 'active' AND n.tid IS NULL");
-      _debug_echo("adserve_cache_id: SELECT a.aid FROM {ads} a LEFT JOIN {term_node} n ON a.aid = n.nid WHERE a.adstatus = 'active' AND n.tid IS NULL");
+      // First query entity tables
+      $query = new EntityFieldQuery;
+      $entities = $query
+        ->entityCondition('entity_type', 'node')
+        ->fieldCondition('ad_group', 'tid', NULL, 'IS NOT')
+        ->execute();
+      // now query ads not in the set
+      $result = db_select('ads')
+        ->fields('ads', array('aid'))
+        ->condition('adstatus', 'active')
+        ->condition('aid', array_keys($entities['node']), 'NOT IN')
+        ->execute();
+      _debug_echo('adserve_cache_id: ' . $result->queryString);
       break;
     default:
       _debug_echo("adserve_cache_id: unsupported type '$type'.");
@@ -233,7 +259,7 @@ function adserve_cache_id($type, $id) {
 
   $ids = array();
   if (isset($result)) {
-    while ($ad = db_fetch_object($result)) {
+    foreach ($result as $ad) {
       // perform node access check
       $node = node_load($ad->aid);
       if (node_access('view', $node) !== FALSE) {
@@ -269,9 +295,9 @@ function adserve_cache_display_ad($id) {
 
   $ad = node_load($id);
   if (!isset($modules[$ad->adtype])) {
-    $modules[$ad->adtype] = db_result(db_query("SELECT filename FROM {system} WHERE name = '%s'", "ad_$ad->adtype"));
+    $modules[$ad->adtype] = db_query("SELECT filename FROM {system} WHERE name = ?", array("ad_$ad->adtype"))->fetchField();
   }
-  _debug_echo("Ad type '$ad->adtype', loading module '". $modules[$ad->adtype] ."'");
+  _debug_echo("Ad type '$ad->adtype', loading module '" . $modules[$ad->adtype] . "'");
   return module_invoke("ad_$ad->adtype", 'display_ad', $ad);
 }
 
@@ -307,23 +333,28 @@ function adserve_cache_increment($action, $aid) {
   _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);
-  // if column doesn't already exist, add it
-  if (!db_affected_rows()) {
-    db_query("INSERT INTO {ad_statistics} (aid, date, action, adgroup, extra, hostid, count) VALUES(%d, %d, '%s', '%s', '%s', '%s', 1)", $aid, date('YmdH'), $action, adserve_variable('group'), $extra, $hostid);
-    if (!db_affected_rows()) {
-      // we lost a race to add it, increment it
-      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);
-    }
-  }
+  db_merge('ad_statistics')
+    ->key(array(
+      'date' => date('YmdH'),
+      'aid' => $aid,
+      'action' => $action,
+      'adgroup' => adserve_variable('group'),
+      'extra' => $extra,
+      'hostid' => $hostid,
+    ))
+    ->fields(array(
+      'count' => 1,
+    ))
+    ->expression('count', 'count + :inc', array(':inc' => 1))
+    ->execute();
 
   if ($action == 'view') {
-    $ad = db_fetch_object(db_query('SELECT maxviews, activated FROM {ads} WHERE aid = %d', $aid));
+    $ad = db_query('SELECT maxviews, activated FROM {ads} WHERE aid = ?', array($aid))->fetchObject();
     // See if we need to perform additional queries.
     if ($ad->maxviews) {
-      $views = (int)db_result(db_query("SELECT SUM(count) FROM {ad_statistics} WHERE aid = %d AND action = 'view' AND date >= %d", $aid, date('YmdH', $ad->activated)));
+      $views = (int) db_query("SELECT SUM(count) FROM {ad_statistics} WHERE aid = ? AND action = 'view' AND date >= ?", array($aid, date('YmdH', $ad->activated)))->fetchField();
       if ($views >= $ad->maxviews) {
-        db_query("UPDATE {ads} SET adstatus = 'expired', autoexpire = 0, autoexpired = %d, expired = %d WHERE aid = %d", time(), time(), $aid);
+        db_query("UPDATE {ads} SET adstatus = ?, autoexpire = ?, autoexpired = ?, expired = ? WHERE aid = ?", array('expired', 0, REQUEST_TIME, REQUEST_TIME, $aid));
         ad_statistics_increment($aid, 'autoexpired');
         ad_statistics_increment($aid, 'expired');
       }
@@ -399,12 +430,12 @@ function adserve_cache_get_ad_ids() {
       $type = 'host';
     }
     // use list of node ids
-    else if ($id = adserve_variable('nids')) {
+    elseif ($id = adserve_variable('nids')) {
       $type = 'nids';
       adserve_variable('group', "n$id");
     }
     // use list of group ids
-    else if ($id = adserve_variable('tids')) {
+    elseif ($id = adserve_variable('tids')) {
       $type = 'tids';
       adserve_variable('group', "t$id");
     }
@@ -426,7 +457,7 @@ function adserve_cache_get_ad_ids() {
   if (!is_array($displayed)) {
     $displayed = array();
   }
-  _debug_echo('Already displayed: '. sizeof($displayed));
+  _debug_echo('Already displayed: ' . sizeof($displayed));
 
   // validate available advertisements
   $aids = adserve_cache('validate', $aids, $displayed, $hostid);
@@ -464,7 +495,7 @@ function adserve_cache_display($ids) {
   $ads = 0;
   foreach ($ids as $id) {
     $ad = adserve_cache('display_ad', $id);
-    _debug_echo('ad: '. htmlentities($ad));
+    _debug_echo('ad: ' . htmlentities($ad));
     // if displaying multiple ads, separate each with a div
     if ($output) {
       $group = adserve_variable('group');
@@ -484,8 +515,8 @@ function adserve_cache_display($ids) {
 
   if (empty($ids)) {
     adserve_variable('error', TRUE);
-    $output = 'No active ads were found in '. adserve_variable('group');
-    adserve_cache('increment', 'count', NULL);
+    $output = 'No active ads were found in ' . adserve_variable('group');
+    adserve_cache('increment', 'count', 0);
   }
 
   // close/update cache, if necessary
@@ -505,7 +536,7 @@ function adserve_cache_display($ids) {
     $params[] = "extra=$extra";
   }
   if (!empty($params)) {
-    $replace .= '?'. implode('&', $params);
+    $replace .= '?' . implode('&', $params);
   }
   $output = preg_replace('&/@HOSTID___&', $replace, $output);
 
@@ -534,10 +565,10 @@ function adserve_cache_display($ids) {
         // Expires in the past:
         header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
         // Last load:
-        header('Last-Modified: '. gmdate('D, d M Y H:i:s') .' GMT');
+        header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
         // HTTP 1.1:
         header('Cache-Control: no-store, no-cache, must-revalidate');
-        header('Cache-Control: post-check=0, pre-check=0', false);
+        header('Cache-Control: post-check=0, pre-check=0', FALSE);
         // HTTP 1.0:
         header('Pragma: no-cache');
         // Output is a JavaScript:
@@ -554,26 +585,26 @@ function adserve_cache_display($ids) {
         // Expires in the past:
         header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
         // Last load:
-        header('Last-Modified: '. gmdate('D, d M Y H:i:s') .' GMT');
+        header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
         // HTTP 1.1:
         header('Cache-Control: no-store, no-cache, must-revalidate');
-        header('Cache-Control: post-check=0, pre-check=0', false);
+        header('Cache-Control: post-check=0, pre-check=0', FALSE);
         // HTTP 1.0:
         header('Pragma: no-cache');
       }
       else {
-        _debug_echo('Output: '. htmlentities($output));
+        _debug_echo('Output: ' . htmlentities($output));
       }
       print "$output";
       exit(0);
     case 'raw':
-      _debug_echo('Output: '. htmlentities($output));
+      _debug_echo('Output: ' . htmlentities($output));
       chdir(adserve_variable('ad_dir'));
       return $output;
 
   }
 
-  _debug_echo('Output: '. htmlentities($output));
+  _debug_echo('Output: ' . htmlentities($output));
   return $output;
 }
 
diff --git adserve.inc adserve.inc
index f3eebeb..fa7c4a7 100644
--- adserve.inc
+++ adserve.inc
@@ -141,7 +141,7 @@ function adserve_variable($variable, $value = NULL) {
   if (!isset($cache_loaded[$variables->adcache])) {
     // Retrieve variables defined by cache plugin, if enabled.
     if ($variables->adcache != 'none') {
-      $includes = array($variables->ad_dir ."/cache/$variables->adcache/ad_cache_$variables->adcache.inc", $variables->ad_dir ."/../ad_$variables->adcache/ad_cache_$variables->adcache.inc");
+      $includes = array($variables->ad_dir . "/cache/$variables->adcache/ad_cache_$variables->adcache.inc", $variables->ad_dir . "/../ad_$variables->adcache/ad_cache_$variables->adcache.inc");
       foreach ($includes as $include) {
         if (file_exists($include)) {
           if ($variables->debug) {
@@ -149,10 +149,10 @@ function adserve_variable($variable, $value = NULL) {
           }
           require_once($include);
         }
-        else if ($variables->debug) {
+        elseif ($variables->debug) {
           echo "Failed to find cache include file '$include'.<br />\n";
         }
-        $function = 'ad_cache_'. $variables->adcache .'_variables';
+        $function = 'ad_cache_' . $variables->adcache . '_variables';
         if (function_exists($function)) {
           $external_variables = $function();
           foreach ($external_variables as $key => $val) {
@@ -191,7 +191,7 @@ function adserve_invoke_file($function, $arg1 = NULL, $arg2 = NULL) {
   if (function_exists($function)) {
     $output = $function($arg1, $arg2);
   }
-  else if (adserve_variable('debug')) {
+  elseif (adserve_variable('debug')) {
     echo "Function '$function' does not exist.<br />\n";
   }
   return $output;
@@ -224,9 +224,9 @@ function _debug_echo($text) {
   static $time = 0;
 
   if (adserve_variable('debug')) {
-    if ($time < time()) {
-      $time = time();
-      echo '--> Time mark: '. date('H:i:s', $time) ."<br />\n";
+    if ($time < REQUEST_TIME) {
+      $time = REQUEST_TIME;
+      echo '--> Time mark: ' . date('H:i:s', $time) . "<br />\n";
       _debug_memory();
     }
     if (!$error_handler) {
@@ -251,12 +251,12 @@ function _debug_memory() {
 function adserve_include_drupal() {
   // For optimal performance set DRUPAL_ROOT at the top of this file.
   if (defined('DRUPAL_ROOT')) {
-    if (is_dir(DRUPAL_ROOT) && file_exists(DRUPAL_ROOT .'/includes/bootstrap.inc')) {
+    if (is_dir(DRUPAL_ROOT) && file_exists(DRUPAL_ROOT . '/includes/bootstrap.inc')) {
       chdir(DRUPAL_ROOT);
       adserve_variable('root_dir', DRUPAL_ROOT);
     }
     else {
-      echo 'Invalid DRUPAL_ROOT ('. DRUPAL_ROOT .') defined in adserve.inc';
+      echo 'Invalid DRUPAL_ROOT (' . DRUPAL_ROOT . ') defined in adserve.inc';
     }
   }
   else {
@@ -270,8 +270,10 @@ function adserve_include_drupal() {
       }
       array_pop($path);
     }
+    // define DRUPAL_ROOT required for drupal
+    define('DRUPAL_ROOT', adserve_variable('root_dir'));
   }
-  require_once adserve_variable('root_dir') .'/includes/bootstrap.inc';
+  require_once DRUPAL_ROOT . '/includes/bootstrap.inc';
 }
 
 /**
@@ -296,7 +298,7 @@ function adserve_bootstrap($bootstrap = NULL) {
  */
 function adserve_debug() {
   if (adserve_variable('debug')) {
-    echo "Root drupal directory detected as '". adserve_variable('root_dir') ."'.<br />\n<br />\n";
+    echo "Root drupal directory detected as '" . adserve_variable('root_dir') . "'.<br />\n<br />\n";
 
     $ad_dir = adserve_variable('ad_dir');
     $files = array("$ad_dir/serve.php", "$ad_dir/adserve.inc", "$ad_dir/adcache.inc", "$ad_dir/ad.module");
@@ -310,7 +312,7 @@ function adserve_debug() {
       if (!file_exists($file)) {
         echo "Error: '$file' does not exist!<br />\n";
       }
-      else if (!is_readable($file)) {
+      elseif (!is_readable($file)) {
         echo "Error: '$file' is not readable!<br />\n";
       }
       else {
diff --git cache/file/ad_cache_file.inc cache/file/ad_cache_file.inc
index 37d1ede..77b44da 100644
--- cache/file/ad_cache_file.inc
+++ cache/file/ad_cache_file.inc
@@ -25,7 +25,7 @@ function ad_cache_file_open() {
   if (adserve_variable('debug')) {
     $last_sync = $cache['last_sync'];
     $lifetime = $cache['lifetime'];
-    $time = time();
+    $time = REQUEST_TIME;
     echo "File cache: last sync: $last_sync<br />\n";
     echo "File cache: current time: $time<br />\n";
     if (adserve_variable('ad_cache_file_rebuild_realtime')) {
@@ -173,7 +173,7 @@ function ad_cache_file_increment($action, $aid) {
   if (is_array($extra) && !empty($extra)) {
     $extra = implode('|,|', $extra);
   }
-  else if (empty($extra)) {
+  elseif (empty($extra)) {
     $extra = '';
   }
   adserve_variable('extra', $extra);
@@ -193,7 +193,7 @@ function ad_cache_file_increment($action, $aid) {
   else {
     $cache['ad'][$aid]['counts'][$group][$extra][$hostid][$action][$timestamp] = 1;
   }
-  _debug_echo("File cache: aid($aid) group($group) extra($extra) hostid($hostid) action($action) timestamp($timestamp) count: ". $cache['ad'][$aid]['counts'][$group][$extra][$hostid][$action][$timestamp]);
+  _debug_echo("File cache: aid($aid) group($group) extra($extra) hostid($hostid) action($action) timestamp($timestamp) count: " . $cache['ad'][$aid]['counts'][$group][$extra][$hostid][$action][$timestamp]);
 
   // update the cache in memory
   ad_cache_file_cache($cache);
@@ -208,7 +208,7 @@ function ad_cache_file_close() {
   // prevent accidentally writing one version of the cache to a different file
   if ($written) {
     _debug_echo('File cache: unable to write cache file, already closed.');
-    return(1);
+    return (1);
   }
   $written = TRUE;
 
@@ -252,8 +252,8 @@ function ad_cache_file_close() {
 
   if (adserve_variable('ad_cache_file_rebuild_realtime')) {
     // every $lifetime seconds we flush the cache to the database
-    $time = time();
-    if ($last_sync < time() - $lifetime) {
+    $time = REQUEST_TIME;
+    if ($last_sync < REQUEST_TIME - $lifetime) {
       ad_cache_file_rebuild();
     }
   }
@@ -276,7 +276,7 @@ function ad_cache_file_get_lock() {
   // lock.
   for ($i = 1; $i <= adserve_variable('files'); $i++) {
     // Prefix the filename with a '.' to hide it on Unix systems.
-    $cache_file = adserve_variable('root_dir') .'/'. adserve_variable('path') .'/.'. $i .'.ad.cache';
+    $cache_file = adserve_variable('root_dir') . '/' . adserve_variable('path') . '/.' . $i . '.ad.cache';
 
     if (adserve_variable('debug')) {
       echo "Trying cache_file '$cache_file'.<br />\n";
@@ -306,7 +306,7 @@ function ad_cache_file_get_lock() {
       if (adserve_variable('debug')) {
         echo "Obtained lock.<br />\n";
         $stat = fstat($fd);
-        echo 'File size: '. $stat['size'] .'<br />';
+        echo 'File size: ' . $stat['size'] . '<br />';
       }
       $lock = TRUE;
       break;
@@ -350,7 +350,7 @@ function ad_cache_file_variables() {
   // files is an integer.
   $variables['files'] = isset($_GET['f']) ? (int)$_GET['f'] : 1;
   if ($variables['files'] > 15) {
-      echo "Invalid value 'f=". $variables['files'] ."', exiting.<br />\n";
+      echo "Invalid value 'f=" . $variables['files'] . "', exiting.<br />\n";
       exit();
   }
   return $variables;
diff --git channel/ad_channel.inc channel/ad_channel.inc
index df96cde..ce8d96f 100644
--- channel/ad_channel.inc
+++ channel/ad_channel.inc
@@ -33,10 +33,10 @@ function ad_channel_cache_filter($ads) {
         $display_by_url = $channel->display;
         $urls = unserialize($channel->urls);
         $frontpage = adserve_variable('site_frontpage') ? adserve_variable('site_frontpage') : 'node';
-        $regexp = '/^('. preg_replace(array('/(\r\n?|\n)/', '/\\\\\*/', '/(^|\|)\\\\<front\\\\>($|\|)/'), array('|', '.*', '\1'. preg_quote($frontpage, '/') .'\2'), preg_quote($urls, '/')) .')$/';
+        $regexp = '/^(' . preg_replace(array('/(\r\n?|\n)/', '/\\\\\*/', '/(^|\|)\\\\<front\\\\>($|\|)/'), array('|', '.*', '\1' . preg_quote($frontpage, '/') . '\2'), preg_quote($urls, '/')) . ')$/';
         foreach (array('url', 'alias') as $search) {
           $match = preg_match($regexp, adserve_variable($search));
-          _debug_echo("ad_channel_cache: checking aid($aid) against channel($chid) path(". adserve_variable($search) .") regexp($regexp) match($match) display[$display_by_url]");
+          _debug_echo("ad_channel_cache: checking aid($aid) against channel($chid) path(" . adserve_variable($search) . ") regexp($regexp) match($match) display[$display_by_url]");
           // display ad on all except matching urls
           if ($display_by_url == 0) {
             if (empty($urls) || !$match) {
@@ -98,7 +98,7 @@ function ad_channel_cache_filter($ads) {
       if ($chid) {
         if (isset($nochannel_percent[$chid])) {
           $frequencies[$chid] = $nochannel_percent[$chid];
-          _debug_echo("ad_channel_cache: channel $chid has a non-channel ad frequency of ". $nochannel_percent[$chid]."%");
+          _debug_echo("ad_channel_cache: channel $chid has a non-channel ad frequency of " . $nochannel_percent[$chid] . "%");
         }
         else {
           // by default, channels return 'non-channel ads' with a frequency
@@ -152,14 +152,14 @@ function ad_channel_cache_filter($ads) {
     }
     $random_channel = _select_channel_id($balanced_channels);
   }
-  else if (!empty($valid_ads)) {
+  elseif (!empty($valid_ads)) {
     foreach ($valid_ads as $chid => $ads) {
       $chids[$chid] = $chid;
     }
     shuffle($chids);
     $random_channel = array_pop($chids);
   }
-  else if (empty($valid_ads) && !empty($nochannel_fallback_ads)) {
+  elseif (empty($valid_ads) && !empty($nochannel_fallback_ads)) {
     _debug_echo("ad_channel_cache: using ads with no channel info");
     $valid_ads[0] = $nochannel_fallback_ads;
     $random_channel = 0;
diff --git channel/ad_channel.module channel/ad_channel.module
index 4ac274c..b6af3fe 100644
--- channel/ad_channel.module
+++ channel/ad_channel.module
@@ -324,7 +324,8 @@ function ad_channel_theme_registry_alter(&$theme_registry) {
  * Implement custom theme function for displaying ad overview, replacing groups
  * with channels.
  */
-function ad_channel_ad_admin_ads($form) {
+function ad_channel_ad_admin_ads($variables) {
+  $form = $variables['form'];
   $list = variable_get('ad_channel_admin_list', AD_CHANNEL_LIST_CHANNEL);
 
   // Conditionally build the header based on list type and
@@ -371,7 +372,7 @@ function ad_channel_ad_admin_ads($form) {
     $rows[] = array(array('data' => t('No ads available.'), 'colspan' => '6'));
   }
 
-  $output .= theme('table', $header, $rows);
+  $output .= theme('table', array('header' => $header, 'rows' => $rows));
   if ($form['pager']['#value']) {
     $output .= drupal_render($form['pager']);
   }
@@ -650,7 +651,7 @@ function _ad_channel_view_node($node) {
         $channels[] = $channel->name;
       }
       $node->content['channel'] = array(
-        '#value' => theme('box', t('Channels'), theme('item_list', $channels)),
+        '#value' => '<h2 class="title">' . t('Channels') . '</h2><div>' . theme('item_list', array('items' => $channels)) . '</div>',
         '#weight' => 1,
       );
     }
@@ -662,7 +663,7 @@ function _ad_channel_view_node($node) {
         $output = t('This is not a premiere advertisement.');
       }
       $node->content['premiere'] = array(
-        '#value' => theme('box', t('Premiere'), $output),
+        '#value' => '<h2 class="title">' . t('Premiere') . '</h2><div>' . $output . '</div>',
         '#weight' => 1,
       );
     }
@@ -670,7 +671,7 @@ function _ad_channel_view_node($node) {
       if (isset($node->remnant) && $node->remnant == 1) {
         $output = t('This is a remnant advertisement.');
         $node->content['remnant'] = array(
-          '#value' => theme('box', t('Remnant'), $output),
+          '#value' => '<h2 class="title">' . t('Remnant') . '</h2><div>' . $output . '</div>',
           '#weight' => 1,
         );
       }
@@ -840,7 +841,7 @@ function ad_channel_admin_overview() {
         );
       }
     }
-    $output .= theme('table', $header, $rows);
+    $output .= theme('table', array('header' => $header, 'rows' => $rows));
     $output .= '</div>';
   }
 
diff --git external/ad_external.module external/ad_external.module
index eb3a42d..988e42e 100644
--- external/ad_external.module
+++ external/ad_external.module
@@ -16,7 +16,7 @@
  * Function used to display the selected ad.
  */
 function ad_external_display_ad($ad) {
-  return theme('ad_external_ad', $ad);
+  return theme('ad_external_ad', array('ad' => $ad));
 }
 
 /**
@@ -27,7 +27,8 @@ function ad_external_display_ad($ad) {
  * @return
  *  A string containing the ad markup.
  */
-function theme_ad_external_ad($ad) {
+function theme_ad_external_ad($variables) {
+  $ad = $variables['ad'];
   global $base_url;
 
   if (isset($ad->aid)) {
@@ -64,7 +65,7 @@ function ad_external_theme() {
   return array(
     'ad_external_ad' => array(
       'file' => 'ad_external.module',
-      'arguments' => array(
+      'variables' => array(
         'ad' => NULL,
       ),
     ),
@@ -171,7 +172,7 @@ function ad_external_node_form(&$node) {
  */
 function ad_external_node_view(&$node) {
   $node->content['ad'] = array(
-    '#value' => theme('box', '', stripslashes(ad_external_display_ad($node))),
+    '#value' => stripslashes(ad_external_display_ad($node)),
     '#weight' => -1,
   );
   $link = t('Links to !url.', array('!url' => $node->url));
diff --git external/external.inc external/external.inc
index aea9b10..fcf2be5 100644
--- external/external.inc
+++ external/external.inc
@@ -8,7 +8,7 @@
  *   Jeremy Andrews <jeremy@tag1consulting.com>.
  */
 
-adserve_variable('ad_dir', getcwd() .'/');
+adserve_variable('ad_dir', getcwd() . '/');
 
 // Attempt to utilize the file cache, if enabled.
 if (function_exists('ad_cache_file_get_lock')) {
diff --git html/ad_html.info html/ad_html.info
index 12674ea..6c9798a 100644
--- html/ad_html.info
+++ html/ad_html.info
@@ -2,4 +2,4 @@ name = HTML Ad
 package = Ad
 dependencies[] = ad
 description = Enhances the ad module to support html-based ads, such as those defined by many advertising affiliate websites.
-core = 6.x
\ No newline at end of file
+core = 7.x
diff --git html/ad_html.install html/ad_html.install
index d9dc828..d4049c1 100644
--- html/ad_html.install
+++ html/ad_html.install
@@ -32,22 +32,11 @@ function ad_html_schema() {
 }
 
 /**
- * ad_html module installation.
- */
-function ad_html_install() {
-  drupal_install_schema('ad_html');
-}
-
-/**
  * Allow complete uninstallation of the ad_html module.
  */
 function ad_html_uninstall() {
   // Delete all ad_html content.
-  $result = db_query("SELECT aid FROM {ad_html}");
-  while ($aid = db_result($result)) {
-    node_delete($aid);
-  }
-
-  // Remove tables.
-  drupal_uninstall_schema('ad_html');
+  $aids = db_query("SELECT aid FROM {ad_html}")
+    ->fetchAllAssoc('aid');
+  node_delete_multiple(array_keys($aids));
 }
diff --git html/ad_html.module html/ad_html.module
index d493cd5..dbd5215 100644
--- html/ad_html.module
+++ html/ad_html.module
@@ -13,7 +13,7 @@
  * Function used to display the selected ad.
  */
 function ad_html_display_ad($ad) {
-  return theme('ad_html_ad', $ad);
+  return theme('ad_html_ad', array('ad' => $ad));
 }
 
 /**
@@ -24,9 +24,10 @@ function ad_html_display_ad($ad) {
  * @return
  *  A string containing the ad markup.
  */
-function theme_ad_html_ad($ad) {
+function theme_ad_html_ad($variables) {
+  $ad = $variables['ad'];
   if (isset($ad->aid)) {
-    $output  = '<div class="html-advertisement" id="ad-'. $ad->aid .'">';
+    $output  = '<div class="html-advertisement" id="ad-' . $ad->aid . '">';
     if (isset($ad->html) && isset($ad->format)) {
       $output .= check_markup($ad->html, $ad->format, FALSE);
     }
@@ -42,7 +43,7 @@ function ad_html_theme() {
   return array(
     'ad_html_ad' => array(
       'file' => 'ad_html.module',
-      'arguments' => array(
+      'variables' => array(
         'ad' => NULL,
       ),
     ),
@@ -63,39 +64,32 @@ function ad_html_help($path, $arg) {
 }
 
 /**
- * Implementation of hook_access().
- */
-function ad_html_access($op, $node, $account) {
-  return ad_access($op, $node, $account);
-}
-
-/**
  * Implementation of the ad module's _adapi hook.
  */
 function ad_html_adapi($op, $node) {
   switch ($op) {
     case 'load':
-      $return = db_fetch_array(db_query('SELECT html FROM {ad_html} WHERE aid = %d', $node['aid']));
+      $return = db_query('SELECT html FROM {ad_html} WHERE aid = ?', array($node['aid']))->fetchAssoc();
       $return['ad'] = check_markup($return['html'], $node['format'], FALSE);
       return $return;
 
     case 'insert':
-      db_query("INSERT INTO {ad_html} (aid, html) VALUES(%d, '%s')", $node->nid, $node->html);
+      db_query("INSERT INTO {ad_html} (aid, html) VALUES(?, ?)", array($node->nid, $node->html));
       break;
 
     case 'update':
-      db_query("UPDATE {ad_html} SET html = '%s' WHERE aid = %d", $node->html, $node->nid);
+      db_query("UPDATE {ad_html} SET html = ? WHERE aid = ?", array($node->html, $node->nid));
       break;
 
     case 'delete':
-      db_query('DELETE FROM {ad_html} WHERE aid = %d', $node->nid);
+      db_query('DELETE FROM {ad_html} WHERE aid = ?', array($node->nid));
       break;
 
     case 'form':
-      return ad_html_node_form($node);
+      return ad_html_adnode_form($node);
 
     case 'view':
-      return ad_html_node_view($node);
+      return ad_html_adnode_view($node);
 
     case 'type':
       return array(
@@ -116,7 +110,7 @@ function ad_html_adapi($op, $node) {
 /**
  * Adapi helper function for displaying a node form.
  */
-function ad_html_node_form(&$node) {
+function ad_html_adnode_form($node) {
   $form = array();
 
   $form['ad_html'] = array(
@@ -130,12 +124,13 @@ function ad_html_node_form(&$node) {
     '#value' => ad_html_display_ad($node),
   );
 
-  if (isset($node->nid) && ad_permission($node->nid, 'manage ad html') || arg(1) == 'add' && user_access('create advertisements')) {
+  if (isset($node->nid) && ad_permission($node->nid, 'manage ad html') || user_access('create advertisements')) {
     $form['ad_html']['html'] = array(
       '#type' => 'textarea',
       '#title' => t('Ad HTML'),
       '#required' => TRUE,
       '#default_value' => isset($node->html) ? $node->html : '',
+      '#value' => '',
       '#description' => t('Paste the complete HTML provided by your advertising affiliate.'),
     );
   }
@@ -146,9 +141,9 @@ function ad_html_node_form(&$node) {
 /**
  * Helper function, display the html ad as a node.
  */
-function ad_html_node_view(&$node) {
+function ad_html_adnode_view(&$node) {
   $node->content['ad'] = array(
-    '#value' => theme('box', '', stripslashes(ad_html_display_ad($node))),
+    '#value' => stripslashes(ad_html_display_ad($node)),
     '#weight' => -1,
   );
 }
diff --git image/ad_image.info image/ad_image.info
index a9f63ac..fe450c1 100644
--- image/ad_image.info
+++ image/ad_image.info
@@ -1,6 +1,6 @@
 name = Image Ad
 package = Ad
 dependencies[] = ad
-dependencies[] = upload
+dependencies[] = image
 description = Enhances the ad module to support banner ads.
-core = 6.x
\ No newline at end of file
+core = 7.x
diff --git image/ad_image.install image/ad_image.install
index a9ec118..5ecefde 100644
--- image/ad_image.install
+++ image/ad_image.install
@@ -107,26 +107,22 @@ function ad_image_schema() {
   return $schema;
 }
 
-
-/**
- * ad_image module installation.
- */
-function ad_image_install() {
-  drupal_install_schema('ad_image');
-}
-
 /**
  * Allow complete uninstallation of the ad_image module.
  */
 function ad_image_uninstall() {
   // Delete all ad_image content.
-  $result = db_query("SELECT aid FROM {ad_image}");
-  while ($aid = db_result($result)) {
-    node_delete($aid);
-  }
+  $aids = db_query("SELECT aid FROM {ad_image}")
+    ->fetchAllAssoc('aid');
+  node_delete_multiple(array_keys($aids));
+}
 
-  // Remove tables.
-  drupal_uninstall_schema('ad_image');
+/**
+ * Implements hook_enable().
+ */
+function ad_image_enable() {
+  // Configure the group taxonomy term field.
+  //_ad_image_field_create_instance('ad_image', 'node', 'ad', t('Image'), 0);
 }
 
 /**
diff --git image/ad_image.module image/ad_image.module
index 896beb7..dab425f 100644
--- image/ad_image.module
+++ image/ad_image.module
@@ -12,7 +12,7 @@
  * Function used to display the selected ad.
  */
 function ad_image_display_ad($ad) {
-  return theme('ad_image_ad', $ad);
+  return theme('ad_image_ad', array('ad' => $ad));
 }
 
 /**
@@ -23,15 +23,24 @@ function ad_image_display_ad($ad) {
  * @return
  *   A string containing the ad markup.
  */
-function theme_ad_image_ad($ad) {
+function theme_ad_image_ad($variables) {
+  $ad = $variables['ad'];
   if (isset($ad->aid) && (isset($ad->filepath) || isset($ad->remote_image))) {
-    $output = '<div class="image-advertisement" id="ad-'. $ad->aid .'">';
+    $output = '<div class="image-advertisement" id="ad-' . $ad->aid . '">';
     if (isset($ad->url) && !empty($ad->url)) {
-      $image = theme('ad_image_image', !empty($ad->remote_image) ? $ad->remote_image : $ad->filepath, check_plain($ad->tooltip), check_plain($ad->tooltip));
-      $output .= l($image, $ad->redirect .'/@HOSTID___', array('attributes' => ad_link_attributes(), 'absolute' => TRUE, 'html' => TRUE));
+      $image = theme('ad_image_image', array(
+        'path' => !empty($ad->remote_image) ? $ad->remote_image : $ad->filepath,
+        'alt' => check_plain($ad->tooltip),
+        'tooltip' => check_plain($ad->tooltip),
+      ));
+      $output .= l($image, $ad->redirect . '/@HOSTID___', array('attributes' => ad_link_attributes(), 'absolute' => TRUE, 'html' => TRUE));
     }
     else {
-      $output .= theme('ad_image_image', !empty($ad->remote_image) ? $ad->remote_image : $ad->filepath, check_plain($ad->tooltip), check_plain($ad->tooltip));
+      $output .= theme('ad_image_image', array(
+        'path' => !empty($ad->remote_image) ? $ad->remote_image : $ad->filepath,
+        'alt' => check_plain($ad->tooltip),
+        'tooltip' => check_plain($ad->tooltip),
+      ));
     }
     $output .= '</div>';
     return $output;
@@ -57,18 +66,23 @@ function theme_ad_image_ad($ad) {
  * @return
  *   A string containing the image tag.
 */
-function theme_ad_image_image($path, $alt = '', $tooltip = '', $attributes = NULL, $getsize = TRUE) {
-  if ($getsize) {
+function theme_ad_image_image($variables) {
+  $path = $variables['path'];
+  $alt = $variables['alt'];
+  $tooltip = $variables['tooltip'];
+  $attributes = $variables['attributes'];
+  // TODO what is this mess?
+  if ($variables['getsize']) {
     list($width, $height, $type, $image_attributes) = @getimagesize($path);
     if (isset($width) && isset($height)) {
       $attributes = drupal_attributes($attributes);
       if (is_file($path)) {
-        $url = preg_replace('&'. drupal_get_path('module', 'ad') .'/&', '', file_create_url($path));
+        $url = preg_replace('&' . drupal_get_path('module', 'ad') . '/&', '', file_create_url($path));
       }
       else {
         $url = $path;
       }
-      return '<img src="'. check_url($url) .'" alt="'. check_plain($alt) .'" title="'. check_plain($tooltip) .'" '. $image_attributes . $attributes .' />';
+      return '<img src="' . check_url($url) . '" alt="' . check_plain($alt) . '" title="' . check_plain($tooltip) . '" ' . $image_attributes . $attributes . ' />';
     }
   }
 }
@@ -80,13 +94,13 @@ function ad_image_theme() {
   return array(
     'ad_image_ad' => array(
       'file' => 'ad_image.module',
-      'arguments' => array(
+      'variables' => array(
         'ad' => NULL,
       ),
     ),
     'ad_image_image' => array(
       'file' => 'ad_image.module',
-      'arguments' => array(
+      'variables' => array(
         'path' => NULL,
         'alt' => '',
         'tooltip' => '',
@@ -111,47 +125,42 @@ function ad_image_help($path, $arg) {
 }
 
 /**
- * Implementation of hook_access().
- */
-function ad_image_access($op, $node, $account) {
-  return ad_access($op, $node, $account);
-}
-
-/**
  * Image ad settings form.
  */
-function ad_image_global_settings($edit = array()) {
-  $form = array();
+function ad_image_global_settings($form, $form_state) {
 
   $form['general'] = array(
     '#type' => 'fieldset',
     '#title' => t('General settings'),
     '#collapsible' => TRUE,
   );
-  $form['general']['remote_images'] = array(
+  $form['general']['ad_image_remote_images'] = array(
     '#type' => 'checkbox',
     '#title' => t('Allow remote hosted images'),
     '#description' => t('Check this box to add a new field when creating image advertisements allowing you to specify a path to a remotely hosted image rather than locally uploading an image.  This option is disabled by default as it is a confusing field to someone not using it.'),
     '#default_value' => variable_get('ad_image_remote_images', FALSE),
   );
 
-  $groups = module_invoke('ad', 'groups_list', TRUE);
-  foreach ($groups as $tid => $group) {
+  $form['#groups'] = module_invoke('ad', 'groups_list', TRUE);
+
+  foreach ($form['#groups'] as $tid => $group) {
     $form["group-$tid"] = array(
       '#type' => 'fieldset',
       '#title' => $group->name,
       '#collapsible' => TRUE,
+      '#tree' => TRUE,
     );
 
-    $form["group-$tid"]["description-$tid"] = array(
+    $form["group-$tid"]['description'] = array(
       '#type' => 'markup',
       '#prefix' => '<div>',
       '#suffix' => '</div>',
-      '#value' => theme_placeholder("$group->description"),
+      '#value' => drupal_placeholder($group->description),
     );
 
-    $format = db_fetch_object(db_query('SELECT * FROM {ad_image_format} WHERE gid = %d', $tid));
-    $form["group-$tid"]["max-size-$tid"] = array(
+    $format = db_query('SELECT * FROM {ad_image_format} WHERE gid = ?', array($tid))->fetchObject();
+
+    $form["group-$tid"]['max_size'] = array(
       '#type' => 'textfield',
       '#title' => t('Maximum filesize'),
       '#size' => 5,
@@ -159,7 +168,7 @@ function ad_image_global_settings($edit = array()) {
       '#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(
+    $form["group-$tid"]['min_height'] = array(
       '#type' => 'textfield',
       '#title' => t('Minimum height'),
       '#size' => 5,
@@ -167,7 +176,7 @@ function ad_image_global_settings($edit = array()) {
       '#default_value' => isset($format->min_height) ? $format->min_height : 0,
       '#description' => t('Optionally specify a minimum height in pixels for images in this group.  To specify no minimum height, enter <em>0</em>.'),
     );
-    $form["group-$tid"]["min-width-$tid"] = array(
+    $form["group-$tid"]['min_width'] = array(
       '#type' => 'textfield',
       '#title' => t('Minimum width'),
       '#size' => 5,
@@ -175,7 +184,7 @@ function ad_image_global_settings($edit = array()) {
       '#default_value' => isset($format->min_width) ? $format->min_width : 0,
       '#description' => t('Optionally specify a minimum width in pixels for images in this group.  To specify no minimum width, enter <em>0</em>.'),
     );
-    $form["group-$tid"]["max-height-$tid"] = array(
+    $form["group-$tid"]['max_height'] = array(
       '#type' => 'textfield',
       '#title' => t('Maximum height'),
       '#size' => 5,
@@ -183,7 +192,7 @@ function ad_image_global_settings($edit = array()) {
       '#default_value' => isset($format->max_height) ? $format->max_height : 0,
       '#description' => t('Optionally specify a maximum height in pixels for images in this group.  To specify no maximum height, enter <em>0</em>.'),
     );
-    $form["group-$tid"]["max-width-$tid"] = array(
+    $form["group-$tid"]['max_width'] = array(
       '#type' => 'textfield',
       '#title' => t('Maximum width'),
       '#size' => 5,
@@ -193,31 +202,30 @@ function ad_image_global_settings($edit = array()) {
     );
   }
 
-  $form['save'] = array(
-    '#type' => 'submit',
-    '#value' => t('Save'),
-  );
-
-  $form['#submit'] = array('ad_image_global_settings_submit');
+  $form['#submit'][] = 'ad_image_global_settings_submit';
 
-  return $form;
+  return system_settings_form($form);
 }
 
 /**
  * Save min and max image width and height values for ad groups.
  */
 function ad_image_global_settings_submit($form, &$form_state) {
-  variable_set('ad_image_remote_images', $form_state['values']['remote_images']);
-  $groups = module_invoke('ad', 'groups_list', TRUE);
-  foreach ($groups as $group) {
+  foreach ($form['#groups'] as $group) {
     // 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, 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, 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"]);
-    }
+    db_merge('ad_image_format')
+      ->key(array(
+        'gid' => $group->tid,
+      ))
+      ->fields(array(
+        'min_width' => $form_state['values']["group-$tid"]['min_width'],
+        'max_width' => $form_state['values']["group-$tid"]['max_width'],
+        'min_height' => $form_state['values']["group-$tid"]['min_height'],
+        'max_height' => $form_state['values']["group-$tid"]['max_height'],
+        'max_size' => $form_state['values']["group-$tid"]['max_size'],
+      ))
+      ->execute();
+    unset($form_state['values']["group-$tid"]);
   }
   drupal_set_message('Image ad global settings updated.');
 }
@@ -230,25 +238,25 @@ function ad_image_adapi($op, $node) {
   switch ($op) {
 
     case 'load':
-      $return = db_fetch_array(db_query("SELECT a.*, f.filepath FROM {ad_image} a LEFT JOIN {files} f ON a.fid = f.fid WHERE aid = %d", $node['aid']));
+      $return = db_query("SELECT a.*, f.filepath FROM {ad_image} a LEFT JOIN {files} f ON a.fid = f.fid WHERE aid = ?", array($node['aid']))->fetchAssoc();
       if (isset($return['remote_image']) && !empty($return['remote_image'])) {
         $path = $return['remote_image'];
       }
       else {
         $path = file_create_url($return['filepath']);
       }
-      $return['ad'] = '<img src="'. $path .'" width="'. $return['width'] .'" height="'. $return['height'] .'" alt="'. check_plain($return['tooltip']) .'" />';
+      $return['ad'] = '<img src="' . $path . '" width="' . $return['width'] . '" height="' . $return['height'] . '" alt="' . check_plain($return['tooltip']) . '" />';
       return $return;
 
     case 'insert':
     case 'update':
-      $fid = isset($node->files) ? (int)ad_image_active_file($node->files) : 0;
+      $fid = isset($node->files) ? (int) ad_image_active_file($node->files) : 0;
       $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
       // prevent the ad from being saved.
-      if ($op == 'update' && !ad_permission($node->nid, 'manage active image')) {
+      if ($op == 'update' && !ad_access_permission($node->nid, 'manage active image')) {
         // See if fid is changing -- it's okay if new images are uploaded, it's
         // just not okay if the active fid is changed.
         if ($fid != $image->fid) {
@@ -274,23 +282,23 @@ function ad_image_adapi($op, $node) {
         }
       }
       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, isset($node->width) ? $node->width : 0, isset($node->height) ? $node->height : 0);
+        db_query("INSERT INTO {ad_image} (aid, fid, url, tooltip, remote_image, width, height) VALUES(?, ?, ?, ?, ?, ?, ?)", array($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, isset($node->width) ? $node->width : 0, isset($node->height) ? $node->height : 0, $node->nid);
+        db_query("UPDATE {ad_image} SET fid = ?, url = ?, tooltip = ?, remote_image = ?, width = ?, height = ? WHERE aid = ?", array($fid, $node->url, $node->tooltip, $node->remote_image, isset($node->width) ? $node->width : 0, isset($node->height) ? $node->height : 0, $node->nid));
       }
       // No valid image has been uploaded, don't allow ad to be 'active'.
       if (($node->remote_image && $image === FALSE) ||
           (!$node->remote_image &&
            ($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'));
+        db_query("UPDATE {ads} SET adstatus = ? WHERE aid = ? AND adstatus = ?", array(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 (!$node->remote_image && !$fid) {
-        db_query("UPDATE {ads} SET adstatus = '%s' WHERE aid = %d AND adstatus = '%s'", t('pending'), $node->nid, t('active'));
+      elseif (!$node->remote_image && !$fid) {
+        db_query("UPDATE {ads} SET adstatus = ? WHERE aid = ? AND adstatus = ?", array(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');
         }
@@ -303,26 +311,26 @@ function ad_image_adapi($op, $node) {
           drupal_set_message('You must specify a valid path for your remote advertisement.', 'error');
         }
       }
-      else if (!isset($node->files) || !ad_image_active_file($node->files)) {
-        form_set_error('upload', t('It is required that you upload an image for your image advertisement.'));
-      }
+      //elseif (!isset($node->files) || !ad_image_active_file($node->files)) {
+      //  form_set_error('upload', t('It is required that you upload an image for your image advertisement.'));
+      //}
       if ($node->url && variable_get('ad_validate_url', 1) && (!valid_url($node->url, TRUE))) {
         form_set_error('url', t('You must specify a valid %field.', array('%field' => t('Destination URL'))));
       }
       break;
 
     case 'delete':
-      db_query('DELETE FROM {ad_image} WHERE aid = %d', $node->nid);
+      db_query('DELETE FROM {ad_image} WHERE aid = ?', array($node->nid));
       break;
 
     case 'form':
-      return ad_image_node_form($node);
+      return ad_image_adnode_form($node);
 
     case 'view':
-      return ad_image_node_view($node);
+      return ad_image_adnode_view($node);
 
     case 'redirect':
-      return db_result(db_query('SELECT url FROM {ad_image} WHERE aid = %d', $node->nid));
+      return db_query('SELECT url FROM {ad_image} WHERE aid = ?', array($node->nid))->fetchField();
 
     case 'type':
       return array(
@@ -338,21 +346,6 @@ function ad_image_adapi($op, $node) {
         return array('manage active image' => TRUE);
       }
 
-    case 'check_install':
-      if (!module_exists('upload')) {
-        drupal_set_message(t("The required <em>upload module</em> is not enabled, you will not be able to upload image ads.  Please %enable the upload module, or %disable the ad_image module.", array('%enable' => l('enable', 'admin/modules'), '%disable' => l('disable', 'admin/modules'))), 'error');
-      }
-      if (is_object($node) && !variable_get("upload_$node->type", TRUE)) {
-        drupal_set_message(t('You will not be able to upload image ads until you !enable for the advertisement content type.', array('!enable' => l(t('enable attachments'), 'admin/content/types/ad'))), 'error');
-      }
-      if (empty($node)) {
-        if (variable_get('file_downloads', FILE_DOWNLOADS_PUBLIC) ==  FILE_DOWNLOADS_PRIVATE) {
-          drupal_set_message(t('Your website is configured to use Drupal\'s private !method.  You have to enable "!view" permissions in addition to the ad module\'s standard "!show" permissions for all roles that you wish to view image advertisements.', array('!method' => l(t('download method'), 'admin/settings/file-system'), '!view' => l(t('view uploaded files'), 'admin/user/access'), '!show' => l(t('show advertisements'), 'admin/user/access'))));
-        }
-      }
-
-      break;
-
   }
 
   return $output;
@@ -385,7 +378,7 @@ function ad_image_format_load($gid) {
   if (isset($format[$gid])) {
     return $format[$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));
+  $format[$gid] = db_query('SELECT min_width, max_width, min_height, max_height, max_size FROM {ad_image_format} WHERE gid = ?', array($gid))->fetchObject();
   return $format[$gid];
 }
 
@@ -414,7 +407,7 @@ function ad_image_validate_size($file, $nid) {
           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)) {
+        elseif ($format->max_width && ($size->width > $format->max_width)) {
           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;
         }
@@ -422,7 +415,7 @@ function ad_image_validate_size($file, $nid) {
           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) {
+        elseif ($format->max_height && $size->height > $format->max_height) {
           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;
         }
@@ -457,7 +450,7 @@ function ad_image_load_image($node) {
       return $image;
     }
   }
-  else if (isset($node->files) && is_array($node->files)) {
+  elseif (isset($node->files) && is_array($node->files)) {
     foreach ($node->files as $file) {
       if (is_array($file)) {
         if ($file['list'] && file_exists($file['filepath'])) {
@@ -485,11 +478,9 @@ function ad_image_load_image($node) {
 /**
  * Adapi helper function for displaying a node form.
  */
-function ad_image_node_form(&$node) {
+function ad_image_adnode_form($node) {
   $form = array();
 
-  ad_image_adapi('check_install', $node);
-
   $form['ad_image'] = array(
     '#type' => 'fieldset',
     '#title' => t('Image'),
@@ -500,12 +491,12 @@ function ad_image_node_form(&$node) {
     $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') .'" /> ';
+    $path = '<img src="' . $node->remote_image . '" alt="' . t('image') . '" /> ';
     if ($image === FALSE) {
-      $path .= t('(invalid image)'). '<br />';
+      $path .= t('(invalid image)') . '<br />';
     }
   }
-  else if (isset($node->files)) {
+  elseif (isset($node->files)) {
     $files = $node->files;
   }
   else {
@@ -521,7 +512,7 @@ function ad_image_node_form(&$node) {
     $active = 0;
     foreach ($files as $file) {
       if (is_array($file)) {
-        $file = (object)$file;
+        $file = (object) $file;
       }
       if ($file->list && file_exists($file->filepath)) {
         $path .= '<img src="'. file_create_url($file->filepath) .'" alt="'. check_plain($file->filename) .'" /> ';
@@ -549,23 +540,27 @@ function ad_image_node_form(&$node) {
       form_set_error('upload', t('It is required that you upload an image for your image advertisement.'));
     }
   }
-  else if ($num) {
+  elseif ($num) {
     $path .= t('<br />Only the first uploaded image that has <em>List</em> checked in the <em>File attachments</em> form section below will be displayed as an advertisement.  The image that will be displayed is marked as <em>active</em> above.');
   }
 
   $form['ad_image']['image'] = array(
     '#type' => 'markup',
-    '#value' => $path,
+    '#markup' => $path,
     '#prefix' => '<div class="container-inline">',
     '#suffix' => '</div>',
   );
 
+  $form['ad_image']['upload'] = array(
+    '#type' => 'image_image',
+  );
+
   $form['ad_image']['url'] = array(
     '#type' => 'textfield',
     '#title' => t('Destination URL'),
     '#required' => FALSE,
     '#default_value' => isset($node->url) ? $node->url : '',
-    '#description' => t('Enter the complete URL where you want people to be redirected when they click on this advertisement.  The URL must be valid and begin with http:// or https://, for example %url, unless you !disable.  If you do not enter a URL, the advertisement will not be clickable.', array('%url' => t('http://www.sample.org/'), '!disable' => l(t('disable URL validation'), 'admin/content/ad/configure', array('fragment' => 'edit-ad-validate-url-wrapper')))),
+    '#description' => t('Enter the complete URL where you want people to be redirected when they click on this advertisement.  The URL must be valid and begin with http:// or https://, for example %url, unless you !disable.  If you do not enter a URL, the advertisement will not be clickable.', array('%url' => t('http://www.example.org/'), '!disable' => l(t('disable URL validation'), 'admin/content/ad/configure', array('fragment' => 'edit-ad-validate-url-wrapper')))),
   );
 
   $form['ad_image']['tooltip'] = array(
@@ -592,7 +587,7 @@ function ad_image_node_form(&$node) {
 /**
  * Adapi helper function for displaying ad itself.
  */
-function ad_image_node_view(&$node) {
+function ad_image_adnode_view(&$node) {
   $node->content['ad'] = array(
     '#value' => preg_replace('&@HOSTID___&', '0', ad_image_display_ad($node)),
     '#weight' => -1,
diff --git imageserve.inc imageserve.inc
index c1e878e..b820f8b 100644
--- imageserve.inc
+++ imageserve.inc
@@ -35,7 +35,7 @@ function adserve_counter_image() {
     // Expires in the past:
     header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
     // Last loud:
-    header('Last-Modified: '. gmdate('D, d M Y H:i:s') .' GMT');
+    header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
     // HTTP 1.1:
     header('Cache-Control: no-store, no-cache, must-revalidate');
     header('Cache-Control: post-check=0, pre-check=0', FALSE);
@@ -51,11 +51,11 @@ function adserve_counter_image() {
     header("Content-type: image/jpeg");
     imagejpeg($image);
   }
-  else if (function_exists('imagepng')) {
+  elseif (function_exists('imagepng')) {
     header("Content-type: image/png");
     imagepng($image);
   }
-  else if (function_exists('imagegif')) {
+  elseif (function_exists('imagegif')) {
     header("Content-type: image/gif");
     imagegif($image);
   }
diff --git owners/ad_owners.module owners/ad_owners.module
index 8afeed0..b0ee4d8 100644
--- owners/ad_owners.module
+++ owners/ad_owners.module
@@ -14,9 +14,7 @@
 function ad_owners_theme() {
   return array(
     'ad_owner_permissions_form' => array(
-      'arguments' => array(
-        'form' => NULL,
-      ),
+      'render element' => 'form',
     ),
   );
 };
@@ -295,8 +293,8 @@ function ad_owners_overview($node) {
     $rows[] = $row;
   }
 
-  $output = theme('table', $header, $rows);
-  $output .= theme('pager', NULL, 25, 0);
+  $output = theme('table', array('header' => $header, 'rows' => $rows));
+  $output .= theme('pager', array('tags' => NULL, 'limit' => 25, 'element' => 0));
 
   return $output;
 }
@@ -520,7 +518,8 @@ function ad_owner_permissions_form($form_state, $node, $user) {
 /**
  * Display ad owner permissions in a simple table.
  */
-function theme_ad_owner_permissions_form($form) {
+function theme_ad_owner_permissions_form($variables) {
+  $form = $variables['form'];
   $output = drupal_render($form['options']);
   foreach (element_children($form['permission']) as $key) {
     $row = array();
@@ -529,7 +528,7 @@ function theme_ad_owner_permissions_form($form) {
     $rows[] = $row;
   }
 
-  $output = theme('table', $form['header']['#value'], $rows);
+  $output = theme('table', array('header' => $form['header']['#value'], 'rows' => $rows));
   $output .= drupal_render($form);
   return $output;
 }
diff --git report/ad_report.module report/ad_report.module
index 946bec2..254e5fa 100644
--- report/ad_report.module
+++ report/ad_report.module
@@ -503,7 +503,7 @@ function ad_report_admin_ad_table($start = 0, $end = 0, $group = array(), $csv =
     }
     $rows[] = $row;
   }
-  $output  .= theme('table', $headers, $rows);
+  $output  .= theme('table', array('header' => $headers, 'rows' => $rows));
   $output .= l(t('Download CSV'), 'admin/content/ad/report/csv');
   return $output;
 }
diff --git serve.php serve.php
index 03cb99d..a109036 100644
--- serve.php
+++ serve.php
@@ -19,7 +19,7 @@ if (isset($_GET['o'])) {
     adserve_counter_image();
     exit(0);
   }
-  else if ($output) {
+  elseif ($output) {
     // TODO: Document how this hook allows external modules to use serve.php
     $files = array(
       "$output.inc", // search for file in main ad directory
@@ -27,7 +27,7 @@ if (isset($_GET['o'])) {
       "../$output/$output.inc", // search for file in higher subdirectory
     );
     foreach ($files as $file) {
-      $function = $output .'_serve';
+      $function = $output . '_serve';
       if (file_exists($file)) {
         require_once("$file");
         if (function_exists($function)) {
diff --git text/ad_text.info text/ad_text.info
index b09b17c..0aecdf3 100644
--- text/ad_text.info
+++ text/ad_text.info
@@ -2,4 +2,4 @@ name = Text Ad
 package = Ad
 dependencies[] = ad
 description = Enhances the ad module to support static text ads.
-core = 6.x
\ No newline at end of file
+core = 7.x
diff --git text/ad_text.install text/ad_text.install
index 286ae6e..f925777 100644
--- text/ad_text.install
+++ text/ad_text.install
@@ -45,22 +45,11 @@ function ad_text_schema() {
 }
 
 /**
- * ad_text module installation.
- */
-function ad_text_install() {
-  drupal_install_schema('ad_text');
-}
-
-/**
  * Allow complete uninstallation of the ad_text module.
  */
 function ad_text_uninstall() {
   // Delete all ad_text content.
-  $result = db_query("SELECT aid FROM {ad_text}");
-  while ($aid = db_result($result)) {
-    node_delete($aid);
-  }
-
-  // Remove tables.
-  drupal_uninstall_schema('ad_text');
+  $aids = db_query("SELECT aid FROM {ad_text}")
+    ->fetchAllAssoc('aid');
+  node_delete_multiple(array_keys($aids));
 }
diff --git text/ad_text.module text/ad_text.module
index 9381da1..e92fcf3 100644
--- text/ad_text.module
+++ text/ad_text.module
@@ -12,7 +12,7 @@
  * Function used to display the selected ad.
  */
 function ad_text_display_ad($ad) {
-  return theme('ad_text_ad', $ad);
+  return theme('ad_text_ad', array('ad' => $ad));
 }
 
 /**
@@ -23,17 +23,25 @@ function ad_text_display_ad($ad) {
  * @return
  *   A string containing the ad markup.
  */
-function theme_ad_text_ad($ad) {
-  if (isset($ad->aid)) {
+function theme_ad_text_ad($variables) {
+  $ad = $variables['ad'];
+  if (!empty($ad->aid)) {
     if (!isset($ad->adheader)) {
       $ad = node_load($ad->aid);
     }
-    $output = '<div class="text-advertisement" id="ad-'. $ad->aid .'">';
+    $output = '<div class="text-advertisement" id="ad-' . $ad->aid . '">';
     if (isset($ad->url) && !empty($ad->url)) {
-      $output .= theme('ad_text_text', ad_text_display_prepare($ad->adheader, $ad->format), ad_text_display_prepare($ad->adbody, $ad->format), $ad->redirect .'/@HOSTID___');
+      $output .= theme('ad_text_text', array(
+        'header' => ad_text_display_prepare($ad->adheader, $ad->format),
+        'body' => ad_text_display_prepare($ad->adbody, $ad->format),
+        'link' => $ad->redirect . '/@HOSTID___',
+      ));
     }
     else {
-      $output .= theme('ad_text_text', ad_text_display_prepare($ad->adheader, $ad->format), ad_text_display_prepare($ad->adbody, $ad->format));
+      $output .= theme('ad_text_text', array(
+        'header' => ad_text_display_prepare($ad->adheader, $ad->format),
+        'body' => ad_text_display_prepare($ad->adbody, $ad->format),
+      ));
     }
     $output .= '</div>';
     return $output;
@@ -52,7 +60,9 @@ function theme_ad_text_ad($ad) {
  * @return
  *  A string containing the text ad.
  */
-function theme_ad_text_text($header, $body, $link = NULL) {
+function theme_ad_text_text($variables) {
+  $header = $variables['header'];
+  $link = $variables['link'];
   $output  = '<div class="ad-header">';
   if (isset($link) && !empty($link)) {
     $output .= l($header, $link, array('attributes' => ad_link_attributes(), 'html' => TRUE));
@@ -61,7 +71,7 @@ function theme_ad_text_text($header, $body, $link = NULL) {
     $output .= $header;
   }
   $output .= '</div>';
-  $output .= '<div class="ad-body">'. $body .'</div>';
+  $output .= '<div class="ad-body">' . $variables['body'] . '</div>';
   return $output;
 }
 
@@ -81,13 +91,13 @@ function ad_text_theme() {
   return array(
     'ad_text_ad' => array(
       'file' => 'ad_text.module',
-      'arguments' => array(
+      'variables' => array(
         'ad' => NULL,
       ),
     ),
     'ad_text_text' => array(
       'file' => 'ad_text.module',
-      'arguments' => array(
+      'variables' => array(
         'header' => NULL,
         'body' => NULL,
         'link' => NULL,
@@ -110,17 +120,9 @@ function ad_text_help($path, $arg) {
 }
 
 /**
- * Implementation of hook_access().
- */
-function ad_text_access($op, $node, $account) {
-  return ad_access($op, $node, $account);
-}
-
-/**
  * Text ad settings form.
  */
-function ad_text_global_settings($form_state) {
-  $form = array();
+function ad_text_global_settings($form, $form_state) {
 
   $form['header_min'] = array(
     '#type' => 'textfield',
@@ -155,73 +157,79 @@ function ad_text_global_settings($form_state) {
     '#description' => t('Optionally specify the maximum number of characters allowed in the body of a text ad.  Set to <em>0</em> to specify no maximum length.'),
   );
 
+  $form['#validate'][] = 'ad_text_global_settings_validate';
 
-  $form['save'] = array(
-    '#type' => 'submit',
-    '#value' => t('Save'),
-  );
-
-  return $form;
+  return system_settings_form($form);
 }
 
 /**
  * Settings form validation handler.
  */
 function ad_text_global_settings_validate($form, &$form_state) {
-  if ((int)$form_state['values']['header_min'] > (int)$form_state['values']['header_max']) {
+  if ((int) $form_state['values']['header_min'] > (int) $form_state['values']['header_max']) {
     form_set_error('header_min', t('The header minimum length can not be greater than the header maximum length.'));
   }
-  if ((int)$form_state['values']['body_min'] > (int)$form_state['values']['body_max']) {
+  if ((int) $form_state['values']['body_min'] > (int) $form_state['values']['body_max']) {
     form_set_error('body_min', t('The body minimum length can not be greater than the body maximum length.'));
   }
 }
 
 /**
- * Settings form submit handler.
- */
-function ad_text_global_settings_submit($form, &$form_state) {
-  variable_set('header_min', $form_state['values']['header_min']);
-  variable_set('header_max', $form_state['values']['header_max']);
-  variable_set('body_min', $form_state['values']['body_min']);
-  variable_set('body_max', $form_state['values']['body_max']);
-}
-
-/**
  * Implementation of hook_adapi().
  */
 function ad_text_adapi($op, $node) {
   switch ($op) {
     case 'load':
-      $return = db_fetch_array(db_query('SELECT aid, url, adheader, adbody FROM {ad_text} WHERE aid = %d', $node['aid']));
-      $return['ad'] = ad_text_display_prepare($return['adheader'], $node['format']) .'<br />'. ad_text_display_prepare($return['adbody'], $node['format']);
+      $return = db_select('ad_text', 'a')
+        ->fields('a', array('url', 'adheader', 'adbody'))
+        ->condition('aid', $node['nid'])
+        ->execute()->fetchAssoc();
+      $return['ad'] = ad_text_display_prepare($return['adheader'], $node['format']) . '<br />' . ad_text_display_prepare($return['adbody'], $node['format']);
       return $return;
 
     case 'insert':
-      db_query("INSERT INTO {ad_text} (aid, url, adheader, adbody) VALUES(%d, '%s', '%s', '%s')", $node->nid, $node->url, $node->adheader, $node->adbody);
+      db_insert('ad_text')
+        ->fields(array(
+          'aid' => $node->nid,
+          'url' => $node->url,
+          'adheader' => $node->adheader,
+          'adbody' => $node->adbody,
+        ))
+        ->execute();
       break;
 
     case 'update':
-      if (ad_permission($node->nid, 'manage ad text')) {
-        db_query("UPDATE {ad_text} SET url = '%s', adheader = '%s', adbody = '%s' WHERE aid = %d", $node->url, $node->adheader, $node->adbody, $node->nid);
+      if (ad_access_permission($node->nid, 'manage ad text')) {
+        db_update('ad_text')
+          ->fields(array(
+            'url' => $node->url,
+            'adheader' => $node->adheader,
+            'adbody' => $node->adbody,
+          ))
+          ->condition('aid', $node->nid)
+          ->execute();
       }
       break;
 
     case 'delete':
-      db_query('DELETE FROM {ad_text} WHERE aid = %d', $node->nid);
+      db_delete('ad_text')->condition('aid', $node->nid)->execute();
       break;
 
     case 'form':
-      return ad_text_node_form($node);
+      return ad_text_adnode_form($node);
 
     case 'view':
-      return ad_text_node_view($node);
+      return ad_text_adnode_view($node);
 
     case 'redirect':
-      return db_result(db_query('SELECT url FROM {ad_text} WHERE aid = %d', $node->nid));
+      return db_select('ad_text', 'a')
+        ->fields('a', array('url'))
+        ->condition('aid', $node->nid)
+        ->execute()->fetchField();
 
     case 'validate':
       $todo = array();
-      return ad_text_node_validate($node, $todo);
+      return ad_text_adnode_validate($node, $todo);
 
     case 'type':
       return array(
@@ -243,29 +251,30 @@ function ad_text_adapi($op, $node) {
 /**
  * Adapi helper function for displaying a node form.
  */
-function ad_text_node_form(&$node) {
-  $form = array();
-
+function ad_text_adnode_form($node) {
   $form['ad_text'] = array(
     '#type' => 'fieldset',
     '#title' => t('Text'),
     '#collapsible' => TRUE,
   );
 
-  if (arg(1) == 'add' && user_access('create advertisements') || ad_permission($node->nid, 'manage ad text')) {
+  if (empty($node->nid)) {
+    $access = user_access('create advertisements');
+  }
+  elseif (ad_access_permission($node->nid, 'manage ad text')) {
     $access = TRUE;
   }
   else {
     $access = FALSE;
     $form['ad_text']['notice'] = array(
       '#type' => 'markup',
-      '#value' => '<p>'. t('You do not have permission to edit this advertisement.') .'</p>',
+      '#markup' => '<p>' . t('You do not have permission to edit this advertisement.') . '</p>',
     );
   }
 
   $form['ad_text']['text'] = array(
     '#type' => 'markup',
-    '#value' => ad_text_display_ad($node),
+    '#markup' => ad_text_display_ad($node),
   );
 
   $form['ad_text']['url'] = array(
@@ -291,7 +300,7 @@ function ad_text_node_form(&$node) {
     '#required' => $access,
     '#default_value' => isset($node->adbody) ? $node->adbody : '',
     '#description' => t('This is the rest of the ad.'),
-    '#disabled' => !$access,
+    '#disabled' => !$access, '#value' => '',
   );
 
   return $form;
@@ -300,16 +309,16 @@ function ad_text_node_form(&$node) {
 /**
  * Adapi helper function for displaying ad itself.
  */
-function ad_text_node_view(&$node) {
+function ad_text_adnode_view($node) {
   $node->content['ad'] = array(
-    '#value' => theme('box', '', preg_replace('&@HOSTID___&', '0', (ad_text_display_ad($node)))),
+    '#markup' => preg_replace('&@HOSTID___&', '0', ad_text_display_ad($node)),
     '#weight' => -1,
   );
   if (!empty($node->url)) {
     $link = t('Links to !url.', array('!url' => $node->url));
     $link = check_plain($link, $node->format, FALSE);
     $node->content['ad-link'] = array(
-      '#value' => "<div class=\"links-to\">$link</div>",
+      '#markup' => "<div class=\"links-to\">$link</div>",
       '#weight' => 1,
     );
   }
@@ -318,7 +327,7 @@ function ad_text_node_view(&$node) {
 /**
  * Text ads node validator.
  */
-function ad_text_node_validate($node, &$form_state) {
+function ad_text_adnode_validate($node, &$form_state) {
   // Enforce minimum and maximum lengths.
   $header_len = isset($node->adheader) ? strlen($node->adheader) : 0;
   $header_min = variable_get('header_min', 0);
@@ -326,7 +335,7 @@ function ad_text_node_validate($node, &$form_state) {
   if ($header_min && ($header_len < $header_min)) {
     form_set_error('adheader', t('Your text ad header is only %cur characters but must be at least %min characters.', array('%cur' => $header_len, '%min' => $header_min)));
   }
-  else if ($header_max && ($header_len > $header_max)) {
+  elseif ($header_max && ($header_len > $header_max)) {
     form_set_error('adheader', t('Your text ad header is %cur characters but can not be more than %max characters.', array('%cur' => $header_len, '%max' => $header_max)));
   }
   $body_len = strlen($node->adbody);
@@ -335,7 +344,7 @@ function ad_text_node_validate($node, &$form_state) {
   if ($body_min && ($body_len < $body_min)) {
     form_set_error('adbody', t('Your text ad body is only %cur characters but must be at least %min characters.', array('%cur' => $body_len, '%min' => $body_min)));
   }
-  else if ($body_max && ($body_len > $body_max)) {
+  elseif ($body_max && ($body_len > $body_max)) {
     form_set_error('adbody', t('Your text ad body is %cur characters but can not be more than %max characters.', array('%cur' => $body_len, '%max' => $body_max)));
   }
 
diff --git weight/percent/ad_weight_percent.inc weight/percent/ad_weight_percent.inc
index 2575bf3..f5c00fe 100644
--- weight/percent/ad_weight_percent.inc
+++ weight/percent/ad_weight_percent.inc
@@ -20,7 +20,7 @@ function ad_weight_percent_select_ad($ads, $quantity, $invalid) {
       $tid = $tids[0];
     }
   }
-  else if (!adserve_variable('nids')) {
+  elseif (!adserve_variable('nids')) {
     // The default group.
     $tid = 0;
   }
diff --git weight/percent/ad_weight_percent.install weight/percent/ad_weight_percent.install
index a36c1e8..c256872 100644
--- weight/percent/ad_weight_percent.install
+++ weight/percent/ad_weight_percent.install
@@ -30,6 +30,6 @@ function ad_weight_percent_uninstall() {
   // Remove tables.
   drupal_uninstall_schema('ad_weight_percent');
 
-  drupal_set_message('The ad_weight_percent module has been completely uninstalled.');
+  drupal_set_message(t('The ad_weight_percent module has been completely uninstalled.'));
 }
 
diff --git weight/percent/ad_weight_percent.module weight/percent/ad_weight_percent.module
index ea647aa..0dd09c3 100644
--- weight/percent/ad_weight_percent.module
+++ weight/percent/ad_weight_percent.module
@@ -66,7 +66,7 @@ function ad_weight_percent_settings() {
       '#type' => 'markup',
       '#prefix' => '<div>',
       '#suffix' => '</div>',
-      '#value' => theme_placeholder("$group->description"),
+      '#value' => drupal_placeholder("$group->description"),
     );
     $form["group-$tid"]["enable-$tid"] = array(
       '#type' => 'checkbox',
diff --git weight/probability/ad_weight_probability.install weight/probability/ad_weight_probability.install
index c9f419e..5334b16 100644
--- weight/probability/ad_weight_probability.install
+++ weight/probability/ad_weight_probability.install
@@ -27,6 +27,6 @@ function ad_weight_probability_install() {
  */
 function ad_weight_probability_uninstall() {
   db_query('DROP TABLE IF EXISTS {ad_weight_probability}');
-  drupal_set_message('The ad_weight_probability module has been completely uninstalled.');
+  drupal_set_message(t('The ad_weight_probability module has been completely uninstalled.'));
 }
 
