diff --git rules/includes/rules.core.inc rules/includes/rules.core.inc
index 3daec4e..d13aef5 100644
--- rules/includes/rules.core.inc
+++ rules/includes/rules.core.inc
@@ -1676,6 +1676,77 @@ abstract class RulesConditionContainer extends RulesContainerPlugin implements R
 }
 
 /**
+ * Base class for conditions over lists.
+ */
+abstract class RulesListCondition extends RulesConditionContainer {
+
+  protected $parameter = array(
+    'list' => array(
+      'type' => 'list',
+      'restriction' => 'selector',
+    ),
+  );
+
+  public function __construct($settings = array(), $variables = NULL) {
+    $this->setUp();
+    $this->settings = (array)$settings + array(
+      'item:var' => 'list-item',
+      'item:label' => t('Current list item'),
+    );
+    if (!empty($variables)) {
+      $this->info['variables'] = $variables;
+    }
+  }
+
+  /**
+   * Overridden because list conditions can only hold one condition.
+   *
+   * Other condition containers may be used for complex requirements.
+   */
+  public function condition($name, $settings = array()) {
+    $condition = (is_object($name) && $name instanceof RulesConditionInterface) ? $name : rules_condition($name, $settings);
+    $condition->setParent($this);
+
+    if (count($this->children) > 1) {
+      $child = array_shift($this->children);
+      $child->setParent(NULL);
+    }
+
+    return $this;
+  }
+
+  public function parameterInfo() {
+    $info = $this->parameter;
+    $info['list']['label'] = t('The list to loop over');
+    return $info;
+  }
+
+  public function integrityCheck() {
+    parent::integrityCheck();
+    $this->checkVarName($this->info['item:var']);
+  }
+
+  protected function listItemType() {
+    if (!isset($this->settings['item:type'])) {
+      $info = $this->getArgumentInfo('list');
+      $this->settings['item:type'] = isset($info['type']) ? entity_metadata_list_extract_type($info['type']) : 'unknown';
+    }
+    return $this->settings['item:type'];
+  }
+
+  protected function listItemInfo() {
+    return array(
+      'type' => $this->listItemType(),
+      'label' => $this->settings['item:label'],
+    );
+  }
+
+  protected function stateVariables($element = NULL) {
+    return array($this->settings['item:var'] => $this->listItemInfo()) + parent::stateVariables($element);
+  }
+}
+
+/**
  * The rules default logging class.
  */
 class RulesLog {
diff --git rules/includes/rules.plugins.inc rules/includes/rules.plugins.inc
index c983249..75e2a31 100644
--- rules/includes/rules.plugins.inc
+++ rules/includes/rules.plugins.inc
@@ -409,6 +409,86 @@ class RulesOr extends RulesConditionContainer {
 }
 
 /**
+ * An all in list condition.
+ */
+class RulesAll extends RulesListCondition {
+
+  protected $itemName = 'all';
+
+  public function evaluate(RulesState $state) {
+    $list_var = $this->getArgument('list', $this->parameter['list'], $state);
+    $item_info = $this->listItemInfo();
+    $name = $this->settings['item:var'];
+    if (isset($this->settings['list:select'])) {
+      rules_log('Looping over the list items of %selector', array('%selector' => $this->settings['list:select']));
+    }
+
+    $condition = reset($this->children);
+    // Loop over the list and evaluate the children for each list item.
+    foreach ($list_var as $key => $item_value) {
+      // Use a separate state so variables are available in the loop only.
+      $state2 = clone $state;
+      $state2->addVariable($name, $list_var[$key], $item_info);
+
+      if (!$condition->evaluate($state2)) {
+        rules_log('ALL OF LIST evaluated to FALSE.');
+        return $this->negate;
+      }
+    }
+    rules_log('ALL OF LIST evaluated to TRUE.');
+    return !$this->negate;
+  }
+
+  public function label() {
+    return !empty($this->label) ? $this->label : t('All');
+  }
+
+  protected function exportChildren($key = 'ALL OF LIST') {
+    return parent::exportChildren($key);
+  }
+}
+
+/**
+ * A one of list condition.
+ */
+class RulesOne extends RulesListCondition {
+
+  protected $itemName = 'one';
+
+  public function evaluate(RulesState $state) {
+    $list_var = $this->getArgument('list', $this->parameter['list'], $state);
+    $item_info = $this->listItemInfo();
+    $name = $this->settings['item:var'];
+    if (isset($this->settings['list:select'])) {
+      rules_log('Looping over the list items of %selector', array('%selector' => $this->settings['list:select']));
+    }
+
+    $condition = reset($this->children);
+    // Loop over the list and evaluate the children for each list item.
+    foreach ($list_var as $key => $item_value) {
+      // Use a separate state so variables are available in the loop only.
+      $state2 = clone $state;
+      $state2->addVariable($name, $list_var[$key], $item_info);
+
+      if ($condition->evaluate($state2)) {
+        rules_log('ONE OF LIST evaluated to TRUE.');
+        return !$this->negate;
+      }
+    }
+    rules_log('ONE OF LIST evaluated to FALSE.');
+    return $this->negate;
+  }
+
+  public function label() {
+    return !empty($this->label) ? $this->label : t('One');
+  }
+
+  protected function exportChildren($key = 'ONE OF LIST') {
+    return parent::exportChildren($key);
+  }
+}
+
+/**
  * A loop element.
  */
 class RulesLoop extends RulesActionContainer {
diff --git rules/modules/system.eval.inc rules/modules/system.eval.inc
index e5f34de..c4f7fe7 100644
--- rules/modules/system.eval.inc
+++ rules/modules/system.eval.inc
@@ -82,14 +82,15 @@ class RulesTokenEvaluator extends RulesDataInputEvaluator {
 
     $replacements = array();
     $data = array();
-    // Fix to properly support 'site' tokens.
-    $var_info['site']['type'] = 'site';
     foreach (token_scan($text) as $var_name => $tokens) {
-      if ($var_name != 'site') {
+      if (isset($var_info[$var_name])) {
         $key = $var_info[$var_name]['type'];
         $data = rules_unwrap_data(array($key => $state->get($var_name)), array($key => $var_info[$var_name]));
+        $replacements += token_generate($var_info[$var_name]['type'], $tokens, $data, $options);
+      }
+      else {
+        $replacements += token_generate($var_name, $tokens, array(), $options);
       }
-      $replacements += token_generate($var_info[$var_name]['type'], $tokens, $data, $options);
     }
 
     // Optionally clean the list of replacement values.
diff --git rules/rules.module rules/rules.module
index d88e7dd..822d33b 100644
--- rules/rules.module
+++ rules/rules.module
@@ -89,6 +89,38 @@ function rules_and($variables = NULL) {
 }
 
 /**
+ * Creates a logical condition container for all items in a list.
+ *
+ * @param $settings
+ *   The loop settings, containing
+ *     'list:select': The data selector for the list to loop over.
+ *     'item:var': Optionally a name for the list item variable.
+ *     'item:label': Optionally a lebel for the list item variable.
+ * @param $variables
+ *   An optional array as for rule().
+ * @return RulesLoop
+ */
+function rules_all($settings = array(), $variables = NULL) {
+  return rules_plugin_factory('all', $settings, $variables);
+}
+
+/**
+ * Creates a logical condition container for at least one item in a list.
+ *
+ * @param $settings
+ *   The loop settings, containing
+ *     'list:select': The data selector for the list to loop over.
+ *     'item:var': Optionally a name for the list item variable.
+ *     'item:label': Optionally a lebel for the list item variable.
+ * @param $variables
+ *   An optional array as for rule().
+ * @return RulesLoop
+ */
+function rules_one($settings = array(), $variables = NULL) {
+  return rules_plugin_factory('one', $settings, $variables);
+}
+
+/**
  * Creates a loop.
  *
  * @param $settings
@@ -363,12 +395,30 @@ function rules_rules_plugin_info() {
         ),
       ),
     ),
+    'all' => array(
+      'class' => 'RulesAll',
+      'embeddable' => 'RulesConditionContainer',
+      'extenders' => array(
+        'RulesPluginUIInterface' => array(
+          'class' => 'RulesListConditionUI',
+        ),
+      ),
+    ),
+    'one' => array(
+      'class' => 'RulesOne',
+      'embeddable' => 'RulesConditionContainer',
+      'extenders' => array(
+        'RulesPluginUIInterface' => array(
+          'class' => 'RulesListConditionUI',
+        ),
+      ),
+    ),
     'loop' => array(
       'class' => 'RulesLoop',
       'embeddable' => 'RulesActionContainer',
       'extenders' => array(
         'RulesPluginUIInterface' => array(
-          'class' => 'RulesActionContainerUI',
+          'class' => 'RulesLoopUI',
         ),
       ),
     ),
diff --git rules/ui/ui.core.inc rules/ui/ui.core.inc
index 742da98..0291dc6 100644
--- rules/ui/ui.core.inc
+++ rules/ui/ui.core.inc
@@ -816,6 +816,57 @@ class RulesConditionContainerUI extends RulesContainerPluginUI {
 }
 
 /**
+ * UI for Rules list condition.
+ */
+class RulesListConditionUI extends RulesConditionContainerUI {
+  public function form(&$form, &$form_state, $options = array(), $iterator = NULL) {
+    parent::form($form, $form_state, $options, $iterator);
+
+    // Remove add-* links when there is already a child element.
+    if (element_children($form['elements'])) {
+      unset($form['add']);
+    }
+
+    // We use $form_state['element_settings'] to store the settings of both
+    // parameter modes. That way one can switch between the parameter modes
+    // without loosing the settings of those.
+    $form_state += array('element_settings' => $this->element->settings);
+    $settings = $this->element->settings + $form_state['element_settings'];
+
+    $form['parameter'] = array(
+      '#tree' => TRUE,
+      '#weight' => -1,
+    );
+
+    foreach($this->element->parameterInfo() as $name => $parameter) {
+      if ($parameter['type'] == 'hidden') {
+        continue;
+      }
+
+      $form['parameter'][$name] = array(
+        '#type' => 'fieldset',
+        '#title' => check_plain($parameter['label']),
+        '#description' => check_plain(isset($parameter['description']) ? $parameter['description'] : ''),
+      );
+
+      // Init the parameter input mode.
+      $form_state['parameter_mode'][$name] = !isset($form_state['parameter_mode'][$name]) ? NULL : $form_state['parameter_mode'][$name];
+      $form['parameter'][$name] += $this->getParameterForm($name, $parameter, $settings, $form_state['parameter_mode'][$name]);
+    }
+  }
+
+  function form_extract_values($form, &$form_state) {
+    $this->element->settings = array();
+    foreach ($form_state['values']['parameter'] as $name => $values) {
+      $this->element->settings += $values['settings'];
+    }
+    $this->element->processSettings(TRUE, TRUE);
+
+    parent::form_extract_values($form, $form_state);
+  }
+}
+
+/**
  * UI for Rules action container.
  */
 class RulesActionContainerUI extends RulesContainerPluginUI {
@@ -830,3 +881,50 @@ class RulesActionContainerUI extends RulesContainerPluginUI {
     $form['elements']['#heading'] = t('Actions');
   }
 }
+
+/**
+ * UI for Rules loops.
+ */
+class RulesLoopUI extends RulesActionContainerUI {
+
+  public function form(&$form, &$form_state, $options = array(), $iterator = NULL) {
+    parent::form($form, $form_state, $options, $iterator);
+
+    // We use $form_state['element_settings'] to store the settings of both
+    // parameter modes. That way one can switch between the parameter modes
+    // without loosing the settings of those.
+    $form_state += array('element_settings' => $this->element->settings);
+    $settings = $this->element->settings + $form_state['element_settings'];
+
+    $form['parameter'] = array(
+      '#tree' => TRUE,
+      '#weight' => -1,
+    );
+
+    foreach($this->element->parameterInfo() as $name => $parameter) {
+      if ($parameter['type'] == 'hidden') {
+        continue;
+      }
+
+      $form['parameter'][$name] = array(
+        '#type' => 'fieldset',
+        '#title' => check_plain($parameter['label']),
+        '#description' => check_plain(isset($parameter['description']) ? $parameter['description'] : ''),
+      );
+
+      // Init the parameter input mode.
+      $form_state['parameter_mode'][$name] = !isset($form_state['parameter_mode'][$name]) ? NULL : $form_state['parameter_mode'][$name];
+      $form['parameter'][$name] += $this->getParameterForm($name, $parameter, $settings, $form_state['parameter_mode'][$name]);
+    }
+  }
+
+  function form_extract_values($form, &$form_state) {
+    $this->element->settings = array();
+    foreach ($form_state['values']['parameter'] as $name => $values) {
+      $this->element->settings += $values['settings'];
+    }
+    $this->element->processSettings(TRUE, TRUE);
+
+    parent::form_extract_values($form, $form_state);
+  }
+}
