Index: sites/all/modules/ad/channel/ad_channel.module
===================================================================
--- sites/all/modules/ad/channel/ad_channel.module	(revision 866)
+++ sites/all/modules/ad/channel/ad_channel.module	(revision 934)
@@ -636,6 +636,32 @@
     '#description' => t('Optionally limit the number of channels that a single advertisement can be assigned to.'),
   );
 
+  // Allowed taxonomy vocabularies
+  $vocs = taxonomy_get_vocabularies();
+  unset($vocs[_ad_get_vid()]); // hide ad groups vocabulary
+  // preparing associative array for select
+  $vocabularies = array();
+  foreach ($vocs as $vid => $vocabulary) {
+   $vocabularies[$vid] = t($vocabulary->name);
+  }
+
+  $selected_vocs = variable_get('ad_channel_allowed_vids', NULL);
+  $collapsed = is_array($selected_vocs) && !empty($selected_vocs) ? FALSE : TRUE;
+  $form['vocabulary_rules'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('Allowed vocabularies for use in channels'),
+    '#collapsible' => TRUE,
+    '#collapsed' => $collapsed
+  );
+  $form['vocabulary_rules']['ad_channel_allowed_vids'] = array(
+    '#type' => 'select',
+    '#title' => t('Ctrl-click vocabularies you want to use for ad channel filtering'),
+    '#default_value' => $selected_vocs,
+    '#options' => $vocabularies,
+    '#size' => min(6, sizeof($vocabularies)),
+    '#multiple' => true
+  );
+
   return system_settings_form($form);
 }
 
@@ -1125,6 +1151,37 @@
     '#default_value' => $chid ? unserialize($channel->urls) : '',
   );
 
+  // taxonomy rules: display ads only for nodes with matching taxonomy term(s)
+  $form['taxonomy_rules'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('Taxonomy rules'),
+    '#description' => t('Display advertisements from this channel on the nodes with specific taxonomy terms'),
+    '#collapsible' => TRUE,
+    '#collasped' => FALSE
+  );
+
+  // 1. Get allowed vocabularies
+  $vocabularies = variable_get('ad_channel_allowed_vids', array());
+  // 2. iterate all allowed vocabularies, displaying select for each one
+  $form['taxonomy_rules']['allowed_terms']['#tree'] = true;
+  
+	if(count($vocabularies) > 0) {
+		foreach ($vocabularies as $vid) {
+	    $vocabulary = taxonomy_vocabulary_load($vid);
+	    $help = ($help) ? $help : filter_xss_admin($vocabulary->help);
+	    if (!$vocabulary->multiple) {
+	        $blank = ($vocabulary->required) ? t('- Please choose -') : t('- None selected -');
+	    }
+	    else {
+	        $blank = ($vocabulary->required) ? 0 : t('- None -');
+	    }
+	    // assuming $value is for selected terms
+	    $selected = variable_get('ad_channel_allowed_terms_' . $chid, NULL);
+	    $selected = $selected[$vid];
+	    $form['taxonomy_rules']['allowed_terms'][$vid] = _taxonomy_term_select(check_plain($vocabulary->name), $name, $selected, $vid, $help, intval($vocabulary->multiple), $blank);
+	  }
+	}
+
   // Group rules
   $groups = taxonomy_get_tree(_ad_get_vid());
   $collapsed = is_array($groups) && !empty($groups) ? FALSE : TRUE;
@@ -1237,6 +1294,9 @@
   switch ($form_state['values']['op']) {
     case t('Create'):
       db_query("INSERT INTO {ad_channel} (name, description, conid, weight, display, no_channel_percent, urls, groups, inventory) VALUES('%s', '%s', %d, %d, %d, '%s', '%s', '%s', %d)", $form_state['values']['name'], $form_state['values']['description'], $form_state['values']['conid'], $form_state['values']['weight'], $form_state['values']['display'], $form_state['values']['no_channel_percent'], serialize($urls), serialize($form_state['values']['groups']), $form_state['values']['inventory']);
+      if (isset($form_state['values']['allowed_terms']) && is_array($form_state['values']['allowed_terms'])) {
+        variable_set('ad_channel_allowed_terms_' . db_last_insert_id('ad_channel', 'chid'), $form_state['values']['allowed_terms']);
+      }
       drupal_set_message(t('The %name channel has been created.', array('%name' => $form_state['values']['name'])));
       break;
     case t('Update'):
@@ -1251,6 +1311,9 @@
         }
       }
       db_query("UPDATE {ad_channel} SET name = '%s', description = '%s', conid = %d, weight = %d, display = %d, urls = '%s', groups = '%s', no_channel_percent = %d, inventory = %d WHERE chid = %d", $form_state['values']['name'], $form_state['values']['description'], $form_state['values']['conid'], $form_state['values']['weight'], $form_state['values']['display'], serialize($urls), serialize($groups), $form_state['values']['no_channel_percent'], $form_state['values']['inventory'], $form_state['values']['chid']);
+      if (isset($form_state['values']['allowed_terms']) && is_array($form_state['values']['allowed_terms'])) {
+        variable_set('ad_channel_allowed_terms_' . $form_state['values']['chid'], $form_state['values']['allowed_terms']);
+      }
       drupal_set_message(t('The %name channel has been updated.', array('%name' => $form_state['values']['name'])));
       break;
     case t('Delete'):
@@ -1286,6 +1349,7 @@
   $channel = _ad_channel_get_channels($form_state['values']['chid']);
   if ($channel->chid) {
     db_query('DELETE FROM {ad_channel} WHERE chid = %d', $channel->chid);
+    variable_del('ad_channel_allowed_terms_' . $channel->chid);
     drupal_set_message(t('The %name channel has been deleted.', array('%name' => $channel->name)));
   }
   drupal_goto('admin/content/ad/channel');
