diff --git a/subscriptions.admin.inc b/subscriptions.admin.inc
index f13aefd..5266da6 100644
--- a/subscriptions.admin.inc
+++ b/subscriptions.admin.inc
@@ -164,7 +164,16 @@ function subscriptions_page_form_submit($form, &$form_state) {
   }
   if ($form_state['values']['op'] == $form_state['values']['submit']) {
     if (empty($rid0)) {
-      $form_state['values']['header']['role']['roles'][] = -$form_state['values']['uid'];  // will be negated again below
+      $bulk_op = (empty($_SESSION['subscriptions']['bulk_op']) ? '' : $_SESSION['subscriptions']['bulk_op']);
+      if ($bulk_op) {
+        foreach (unserialize($form_state['values']['uid']) as $uid) {
+          $form_state['values']['header']['role']['roles'][] = -$uid;
+        }
+        $form_state['redirect'] = 'admin/settings/subscriptions/userdefaults/bulk';
+      }
+      else {
+        $form_state['values']['header']['role']['roles'][] = -$form_state['values']['uid'];  // will be negated again below
+      }
     }
     $module = $form_state['values']['module'];
     $field = $form_state['values']['field'];
@@ -177,7 +186,7 @@ function subscriptions_page_form_submit($form, &$form_state) {
         $defaults = $element_values['defaults'];
         foreach ($element_values['checkboxes'] as $value => $bundle) {
           foreach ($bundle as $author_uid => $set_to_enabled) {
-            if ($set_to_enabled && (
+            if ($set_to_enabled && $bulk_op != 'unsub' && (
                 !isset($defaults['checkboxes'][$value][$author_uid]) ||
                 $element_values['send_interval'][$value][$author_uid] != $defaults['send_interval'][$value][$author_uid] ||
                 empty($element_values['send_updates'][$value][$author_uid]) != empty($defaults['send_updates'][$value][$author_uid]) ||
@@ -189,8 +198,9 @@ function subscriptions_page_form_submit($form, &$form_state) {
               }
               $changed = TRUE;
             }
-            elseif (!$set_to_enabled && isset($defaults['checkboxes'][$value][$author_uid])) {
-              // It was enabled but now it is not. Delete.
+            elseif ($bulk_op == 'unsub' && $set_to_enabled ||
+                    !$set_to_enabled && isset($defaults['checkboxes'][$value][$author_uid])) {
+              // It was bulk-unsubscribed, or it was enabled but now it is not. Delete.
               foreach ($form_state['values']['header']['role']['roles'] as $uid) {
                 db_query("DELETE FROM {subscriptions} WHERE module = '%s' AND field = '%s' AND value = '%s' AND author_uid = %d AND recipient_uid = %d", $module, $field, $value, $author_uid, -$uid);
               }
@@ -234,35 +244,56 @@ function subscriptions_page($account, $stype) {
       '#collapsed'     => FALSE,
       '#weight'        => -2,
     );
-    $form['header'][] = array(
-      '#type'          => 'item',
-      '#value'         => t('The selected subscriptions will be given to <b>newly created</b> users.'),
-      );
-
-    $tr = 't';
-    $form['header']['role'] = array(
-      '#type'        => 'fieldset',
-      '#title'       => $tr('Roles'),
-      '#collapsible' => TRUE,
-      '#collapsed'   => !is_numeric(arg(5)),
-      );
-    $form['header']['role']['header'] = array(
-      '#type'          => 'markup',
-      '#value'         => '<div>'. t('If a user has one or more roles assigned at creation time, then she will receive the additional subscriptions defined for these roles.') .'</div>',
-      '#weight'        => -5,
-      );
-    $form['header']['role']['roles'] = array(
-      '#type'          => 'select',
-      '#title'         => t('Role(s)'),
-      '#default_value' => (is_numeric(arg(5))? arg(5) : DRUPAL_AUTHENTICATED_RID),
-      '#options'       => user_roles(TRUE),
-      '#description'   => t('Select the role to load or role(s) to save.'),
-      '#multiple'      => TRUE,
+    if (empty($_SESSION['subscriptions']['bulk_op'])) {
+      $form['header'][] = array(
+        '#type'          => 'item',
+        '#value'         => t('The selected subscriptions will be given to <b>newly created</b> users.'),
+        );
+
+      $tr = 't';
+      $form['header']['role'] = array(
+        '#type'        => 'fieldset',
+        '#title'       => $tr('Roles'),
+        '#collapsible' => TRUE,
+        '#collapsed'   => !is_numeric(arg(5)),
+        );
+      $form['header']['role']['header'] = array(
+        '#type'          => 'markup',
+        '#value'         => '<div>'. t('If a user has one or more roles assigned at creation time, then she will receive the additional subscriptions defined for these roles.') .'</div>',
+        '#weight'        => -5,
+        );
+      $form['header']['role']['roles'] = array(
+        '#type'          => 'select',
+        '#title'         => t('Role(s)'),
+        '#default_value' => (is_numeric(arg(5))? arg(5) : DRUPAL_AUTHENTICATED_RID),
+        '#options'       => user_roles(TRUE),
+        '#description'   => t('Select the role to load or role(s) to save.'),
+        '#multiple'      => TRUE,
+        );
+      $form['header']['role']['load'] = array(
+        '#type'          => 'submit',
+        '#value'         => t('Load'),
+        );
+    }
+    else {
+      $bulk_op = $_SESSION['subscriptions']['bulk_op'];
+      $uids = unserialize($_SESSION['subscriptions']['uids']);
+      $form['header']['info1'] = array(
+        '#type' => 'item',
+        '#value' => t('You have selected %count users for performing bulk !action.', array(
+            '%count' => count($uids),
+            '!action' => '<strong>'. ($bulk_op == 'sub' ? t('subscribing') : t('unsubscribing')) .'</strong>',
+          )),
       );
-    $form['header']['role']['load'] = array(
-      '#type'          => 'submit',
-      '#value'         => t('Load'),
+      $form['header']['info2'] = array(
+        '#type' => 'item',
+        '#value' => t('Select the subscriptions to !change and click [@Save] to perform the action for all users.', array(
+            '!change' => '<strong>'. ($bulk_op == 'sub' ? t('add') : t('remove')) .'</strong>',
+            '@Save' => t('Save'),
+          )),
       );
+
+    }
   }
   else {
     subscriptions_suspended(arg(1), TRUE);
@@ -695,6 +726,61 @@ function subscriptions_user_settings_form_submit($form, &$form_state) {
 }
 
 /**
+ * Provide the form definition for admin/settings/subscriptions/userdefaults/bulk.
+ *
+ * Called by _subscriptions_menu() in subscriptions.module.
+ *
+ * @ingroup form
+ *
+ * @see _subscriptions_menu()
+ */
+function subscriptions_page_user_bulk(&$form_state) {
+  $bulk_op = $_SESSION['subscriptions']['bulk_op'];
+  $uids = unserialize($_SESSION['subscriptions']['uids']);
+  $form['info1'] = array(
+    '#type' => 'item',
+    '#value' => t('You have selected %count users for performing bulk !action.', array(
+        '%count' => count($uids),
+        '!action' => '<strong>'. ($bulk_op == 'sub' ? t('subscribing') : t('unsubscribing')) .'</strong>',
+      )),
+  );
+  $form['info2'] = array(
+    '#type' => 'item',
+    '#value' => '<strong>'. t('Beware: These actions cannot be undone!') .'</strong>',
+  );
+  $form['info3'] = array(
+    '#type' => 'item',
+    '#value' => t('Navigate to any of the subscription type subtabs, select the subscriptions to change, and click [@Save] to perform the action for all users and return here.', array(
+        '@Save' => t('Save'),
+      )),
+  );
+  $form['info4'] = array(
+    '#type' => 'item',
+    '#value' => t('Click [@Done] to clear the selected list of users and return to the user list.', array(
+        '@Done' => t('Done'),
+      )) .'<br /><br />',
+  );
+  $form['submit'] = array(
+    '#type' => 'submit',
+    '#value' => t('Done'),
+  );
+  return $form;
+}
+
+/**
+ * Bulk operation form submit handler.
+ *
+ * @ingroup form
+ */
+function subscriptions_page_user_bulk_submit($form, &$form_state) {
+  $back_url = $_SESSION['subscriptions']['back_url'];
+  unset($_SESSION['subscriptions']['bulk_op']);
+  unset($_SESSION['subscriptions']['uids']);
+  unset($_SESSION['subscriptions']['back_url']);
+  drupal_goto($back_url);
+}
+
+/**
  * Provide the form definition for admin/settings/subscriptions/intervals.
  *
  * Called by _subscriptions_menu() in subscriptions.module.
@@ -914,9 +1000,10 @@ function subscriptions_form_helper(&$form, &$defaults, $author_uid, $key, $title
  * @ingroup form
  */
 function subscriptions_form_column_filter(&$form_table, $uid) {
+  $bulk_unsub = (isset($_SESSION['subscriptions']['bulk_op']) && $_SESSION['subscriptions']['bulk_op'] == 'unsub');
   foreach (array('send_interval', 'send_comments', 'send_updates', 'author') as $key) {
     if (isset($form_table[$key])) {
-      $form_table[$key]['#access'] = ($uid <= 0 || $key == 'author' || _subscriptions_get_setting($key .'_visible', $uid) > 0);
+      $form_table[$key]['#access'] = !$bulk_unsub && ($uid <= 0 || $key == 'author' || _subscriptions_get_setting($key .'_visible', $uid) > 0);
     }
   }
 }
diff --git a/subscriptions.module b/subscriptions.module
index c886fda..55846ed 100644
--- a/subscriptions.module
+++ b/subscriptions.module
@@ -70,6 +70,14 @@ function subscriptions_menu() {
     'title' => 'Overview',
     'weight' => -10,
   );
+  $items['admin/settings/subscriptions/userdefaults/bulk'] = array(
+    'title' => 'Bulk operation',
+    'weight' => -8,
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('subscriptions_page_user_bulk'),
+    'type' => MENU_LOCAL_TASK,
+    'access callback' => '_subscriptions_bulk_access',
+  );
   $items['admin/settings/subscriptions/intervals'] = array(
     'title' => 'Interval',
     'page callback' => 'drupal_get_form',
@@ -194,6 +202,11 @@ function _subscriptions_access($account, $access = NULL) {
   return FALSE;
 }
 
+function _subscriptions_bulk_access()
+{
+  return user_access('bulk-administer user subscriptions') && !empty($_SESSION['subscriptions']['bulk_op']);
+}
+
 /**
  * Implementation of hook_perm().
  *
@@ -202,11 +215,13 @@ function _subscriptions_access($account, $access = NULL) {
 function subscriptions_perm() {
   return array_merge(array(
     'administer user subscriptions',
+    'bulk-administer user subscriptions',
     'subscribe to all content types',
     'suspend own subscriptions',
   ), subscriptions_types('access'));
 
   t('administer user subscriptions');
+  t('bulk-administer user subscriptions');
   t('subscribe to all content types');
   t('suspend own subscriptions');
 }
@@ -643,3 +658,32 @@ function subscriptions_form_user_profile_form_alter(&$form, &$form_state) {
   subscriptions_suspended(arg(1), TRUE);
 }
 
+/**
+ * Implementation of hook_user_operations().
+ */
+function subscriptions_user_operations($form_state = NULL) {
+  if (user_access('bulk-administer user subscriptions')) {
+    return array(
+      array(
+        "label" => t('Subscribe the selected users to...'),
+        "callback" => '_subscriptions_bulk_operation',
+        "callback arguments" => array('sub'),
+      ),
+      array(
+        "label" => t('Unsubscribe the selected users from...'),
+        "callback" => '_subscriptions_bulk_operation',
+        "callback arguments" => array('unsub'),
+      ),
+    );
+  }
+}
+
+/**
+ * Callback for bulk subscriptions.
+ */
+function _subscriptions_bulk_operation($uids, $bulk_op) {
+  $_SESSION['subscriptions']['bulk_op'] = $bulk_op;
+  $_SESSION['subscriptions']['uids'] = serialize($uids);
+  $_SESSION['subscriptions']['back_url'] = $_GET['q'];
+  drupal_goto('admin/settings/subscriptions/userdefaults/bulk');
+}
diff --git a/subscriptions_blog_ui.module b/subscriptions_blog_ui.module
index 625fee2..8ed6daf 100644
--- a/subscriptions_blog_ui.module
+++ b/subscriptions_blog_ui.module
@@ -98,16 +98,23 @@ function subscriptions_blog_ui_page_blog($account, $form) {
  * @ingroup form
  */
 function subscriptions_blog_ui_blog_form(&$form_state, $blogs, $account, $form) {
-  $uid = (isset($account) ? $account->uid : (is_numeric(arg(5)) ? -arg(5) : -DRUPAL_AUTHENTICATED_RID));
   $subscriptions = array();
-  $result = db_query("
-    SELECT s.value, s.send_interval, s.author_uid, s.send_comments, s.send_updates, u.name
-    FROM {subscriptions} s
-    INNER JOIN {users} u ON s.author_uid = u.uid
-    WHERE s.module = 'node' AND s.field = 'type' AND s.value = 'blog' AND s.recipient_uid = %d
-    ORDER BY u.name", $uid);
-  while ($s = db_fetch_array($result)) {
-    $subscriptions[$s['author_uid']] = $s;
+  $bulk_op = (empty($_SESSION['subscriptions']['bulk_op']) ? '' : $_SESSION['subscriptions']['bulk_op']);
+  if ($bulk_op) {
+    // No initialization for bulk subscription.
+    $uid = -DRUPAL_AUTHENTICATED_RID;
+  }
+  else {
+    $uid = (isset($account) ? $account->uid : (is_numeric(arg(5)) ? -arg(5) : -DRUPAL_AUTHENTICATED_RID));
+    $result = db_query("
+      SELECT s.value, s.send_interval, s.author_uid, s.send_comments, s.send_updates, u.name
+      FROM {subscriptions} s
+      INNER JOIN {users} u ON s.author_uid = u.uid
+      WHERE s.module = 'node' AND s.field = 'type' AND s.value = 'blog' AND s.recipient_uid = %d
+      ORDER BY u.name", $uid);
+    while ($s = db_fetch_array($result)) {
+      $subscriptions[$s['author_uid']] = $s;
+    }
   }
   $form[0] = array(
     '#type' => 'item',
@@ -116,7 +123,6 @@ function subscriptions_blog_ui_blog_form(&$form_state, $blogs, $account, $form)
     '#theme' => 'subscriptions_form_table',
   );
 
-  $intervals = _subscriptions_send_intervals();
   foreach ($blogs as $blog) {
     $title = ($blog['has_blog'] ? l($blog['name'], 'blog/'. $blog['uid']) : $blog['name']);
     // add the active subscriptions
@@ -138,7 +144,7 @@ function subscriptions_blog_ui_blog_form(&$form_state, $blogs, $account, $form)
   subscriptions_form_column_filter($form[0], $uid);
 
   $form['#tree'] = TRUE;
-  $form['uid'] = array('#type' => 'value', '#value' => $uid);
+  $form['uid'] = array('#type' => 'value', '#value' => ($bulk_op ? $_SESSION['subscriptions']['uids'] : $uid));
   $form['access_key'] = array('#type' => 'value', '#value' => 'blog');
   $form['module'] = array('#type' => 'value', '#value' => 'node');
   $form['field'] = array('#type' => 'value', '#value' => 'type');
diff --git a/subscriptions_content.module b/subscriptions_content.module
index 3e69c62..e1c9512 100644
--- a/subscriptions_content.module
+++ b/subscriptions_content.module
@@ -869,7 +869,6 @@ function subscriptions_content_node_form(&$form_state, $account, $form) {
       }
     }
   }
-
   $form[0] = array(
     '#type' => 'item',
     '#title' => '',
@@ -944,19 +943,27 @@ function subscriptions_content_page_type($account, $form) {
  * @ingroup form
  */
 function subscriptions_content_type_form(&$form_state, $account, $form) {
-  $uid = (isset($account) ? $account->uid : (is_numeric(arg(5)) ? -arg(5) : -DRUPAL_AUTHENTICATED_RID));
+  $subscriptions = array();
+  $bulk_op = (empty($_SESSION['subscriptions']['bulk_op']) ? '' : $_SESSION['subscriptions']['bulk_op']);
+  if ($bulk_op) {
+    // No initialization for bulk subscription.
+    $uid = -DRUPAL_AUTHENTICATED_RID;
+  }
+  else {
+    $uid = (isset($account) ? $account->uid : (is_numeric(arg(5)) ? -arg(5) : -DRUPAL_AUTHENTICATED_RID));
+    $result = db_query(db_rewrite_sql("
+      SELECT s.value, s.send_interval, s.author_uid, s.send_comments, s.send_updates, nt.type, nt.name
+      FROM {subscriptions} s
+      INNER JOIN {node_type} nt ON s.value = nt.type
+      WHERE s.module = 'node' AND s.field = 'type' AND s.recipient_uid = %d
+      ORDER BY s.author_uid", 'nt', 'type'), $uid);
+    while ($s = db_fetch_array($result)) {
+      $subscriptions[$s['value']][$s['author_uid']] = $s;
+    }
+  }
   $unlisteds = variable_get('subscriptions_unlisted_content_types', array());
   $blockeds = variable_get('subscriptions_blocked_content_types', array());
   $omits = array_merge($unlisteds, $blockeds);
-  $result = db_query(db_rewrite_sql("
-    SELECT s.value, s.send_interval, s.author_uid, s.send_comments, s.send_updates, nt.type, nt.name
-    FROM {subscriptions} s
-    INNER JOIN {node_type} nt ON s.value = nt.type
-    WHERE s.module = 'node' AND s.field = 'type' AND s.recipient_uid = %d
-    ORDER BY s.author_uid", 'nt', 'type'), $uid);
-  while ($s = db_fetch_array($result)) {
-    $subscriptions[$s['value']][$s['author_uid']] = $s;
-  }
   $form[0] = array(
     '#type' => 'item',
     '#title' => '',
@@ -1001,7 +1008,7 @@ function subscriptions_content_type_form(&$form_state, $account, $form) {
     );
     subscriptions_form_column_filter($form[0], $uid);
     $form['#tree'] = TRUE;
-    $form['uid'] = array('#type' => 'value', '#value' => $uid);
+    $form['uid'] = array('#type' => 'value', '#value' => ($bulk_op ? $_SESSION['subscriptions']['uids'] : $uid));
     $form['access_key'] = array('#type' => 'value', '#value' => 'type');
     $form['module'] = array('#type' => 'value', '#value' => 'node');
     $form['field'] = array('#type' => 'value', '#value' => 'type');
diff --git a/subscriptions_taxonomy.module b/subscriptions_taxonomy.module
index 260e06b..c84dc31 100644
--- a/subscriptions_taxonomy.module
+++ b/subscriptions_taxonomy.module
@@ -209,20 +209,29 @@ function subscriptions_taxonomy_page_taxa($account, $form) {
  * @ingroup form
  */
 function subscriptions_taxonomy_taxa_form(&$form_state, $vocabularies, $account, $form) {
-  $uid = (isset($account) ? $account->uid : (is_numeric(arg(5)) ? -arg(5) : -DRUPAL_AUTHENTICATED_RID));
-  $sql = db_rewrite_sql("
-    SELECT s.value, s.send_interval, s.author_uid, s.send_comments, s.send_updates, t.tid, t.vid, t.name
-    FROM {term_data} t
-    INNER JOIN {subscriptions} s ON ". ($GLOBALS['db_type'] == 'pgsql' ? 'CAST(' : '')
-                                  ."t.tid". ($GLOBALS['db_type'] == 'pgsql' ? ' AS VARCHAR)' : '')
-                                       ." = s.value
-    WHERE s.module = 'node' AND s.field = 'tid' AND s.recipient_uid = %d
-    ORDER BY s.author_uid", 't', 'tid');
-  $result = db_query($sql, $uid);
-  while ($s = db_fetch_array($result)) {
-    $subscriptions[$s['vid']][$s['value']][$s['author_uid']] = $s;
-    $subscriptions_terms_by_vid[$s['vid']][$s['value']] = $s;
+  $subscriptions = array();
+  $bulk_op = (empty($_SESSION['subscriptions']['bulk_op']) ? '' : $_SESSION['subscriptions']['bulk_op']);
+  if ($bulk_op) {
+    // No initialization for bulk subscription.
+    $uid = -DRUPAL_AUTHENTICATED_RID;
   }
+  else {
+    $uid = (isset($account) ? $account->uid : (is_numeric(arg(5)) ? -arg(5) : -DRUPAL_AUTHENTICATED_RID));
+    $sql = db_rewrite_sql("
+      SELECT s.value, s.send_interval, s.author_uid, s.send_comments, s.send_updates, t.tid, t.vid, t.name
+      FROM {term_data} t
+      INNER JOIN {subscriptions} s ON ". ($GLOBALS['db_type'] == 'pgsql' ? 'CAST(' : '')
+                                    ."t.tid". ($GLOBALS['db_type'] == 'pgsql' ? ' AS VARCHAR)' : '')
+                                         ." = s.value
+      WHERE s.module = 'node' AND s.field = 'tid' AND s.recipient_uid = %d
+      ORDER BY s.author_uid", 't', 'tid');
+    $result = db_query($sql, $uid);
+    while ($s = db_fetch_array($result)) {
+      $subscriptions[$s['vid']][$s['value']][$s['author_uid']] = $s;
+      $subscriptions_terms_by_vid[$s['vid']][$s['value']] = $s;
+    }
+  }
+
   foreach ($vocabularies as $vocab) {
     // display vocabulary name and group terms together
     $form[$vocab->vid] = array(
@@ -301,7 +310,7 @@ function subscriptions_taxonomy_taxa_form(&$form_state, $vocabularies, $account,
   }
   else {
     $form['#tree'] = TRUE;
-    $form['uid'] = array('#type' => 'value', '#value' => $uid);
+    $form['uid'] = array('#type' => 'value', '#value' => ($bulk_op ? $_SESSION['subscriptions']['uids'] : $uid));
     $form['access_key'] = array('#type' => 'value', '#value' => 'taxa');
     $form['module'] = array('#type' => 'value', '#value' => 'node');
     $form['field'] = array('#type' => 'value', '#value' => 'tid');
