Index: database/database.mysql
===================================================================
RCS file: /cvs/drupal/drupal/database/database.mysql,v
retrieving revision 1.203
diff -u -F^function -r1.203 database.mysql
--- database/database.mysql	5 Nov 2005 08:00:20 -0000	1.203
+++ database/database.mysql	7 Nov 2005 18:00:57 -0000
@@ -241,6 +241,22 @@
 ) TYPE=MyISAM;
 
 --
+-- Table structure for table 'deleted'
+--
+
+CREATE TABLE deleted (
+  tid int(10) unsigned NOT NULL default '0',
+  did int(10) unsigned NOT NULL default '0',
+  rid varchar(255) NOT NULL default '',
+  uid int(10) unsigned NOT NULL default '0',
+  root_row varchar(255) NOT NULL default '',
+  data longtext NOT NULL,
+  preview longtext NOT NULL,
+  timestamp int(10) unsigned NOT NULL default '0',
+  PRIMARY KEY  (tid)
+) TYPE=MyISAM;
+
+--
 -- Table structure for table 'files'
 --
 
Index: database/database.pgsql
===================================================================
RCS file: /cvs/drupal/drupal/database/database.pgsql,v
retrieving revision 1.143
diff -u -F^function -r1.143 database.pgsql
--- database/database.pgsql	5 Nov 2005 08:00:20 -0000	1.143
+++ database/database.pgsql	7 Nov 2005 18:00:58 -0000
@@ -236,6 +236,22 @@
 );
 
 --
+-- Table structure for table 'deleted'
+--
+
+CREATE TABLE deleted (
+  tid integer NOT NULL default '0',
+  did integer NOT NULL default '0',
+  rid text NOT NULL default '',
+  uid integer NOT NULL default '0',
+  root_row text NOT NULL default '',
+  data text NOT NULL default '',
+  preview text NOT NULL default '',
+  timestamp integer NOT NULL default '0',
+  PRIMARY KEY (tid)
+);
+
+--
 -- Table structure for table 'files'
 --
 
Index: database/updates.inc
===================================================================
RCS file: /cvs/drupal/drupal/database/updates.inc,v
retrieving revision 1.144
diff -u -F^function -r1.144 updates.inc
--- database/updates.inc	6 Nov 2005 11:33:28 -0000	1.144
+++ database/updates.inc	7 Nov 2005 18:00:59 -0000
@@ -103,7 +103,8 @@
   "2005-10-15" => "update_150",
   "2005-10-23" => "update_151",
   "2005-10-28" => "update_152",
-  "2005-11-03" => "update_153"
+  "2005-11-03" => "update_153",
+  "2005-11-07" => "update_154",
 );
 
 function update_110() {
@@ -1139,6 +1140,43 @@ function update_153(){
 
 }
 
+function update_154() {
+  $ret = array();
+  
+  switch ($GLOBALS['db_type']) {
+    case 'mysqli':
+    case 'mysql':
+      $ret[] = update_sql("CREATE TABLE deleted (
+                           tid int(10) unsigned NOT NULL default '0',
+                           did int(10) unsigned NOT NULL default '0',
+                           rid varchar(255) NOT NULL default '',
+                           uid int(10) unsigned NOT NULL default '0',
+                           root_row varchar(255) NOT NULL default '',
+                           data longtext NOT NULL,
+                           preview longtext NOT NULL,
+                           timestamp int(10) unsigned NOT NULL default '0',
+                           PRIMARY KEY (tid)
+                           )");
+      break;
+    case 'pgsql':
+      $ret[] = update_sql("CREATE TABLE deleted (
+                           tid integer NOT NULL default '0',
+                           did integer NOT NULL default '0',
+                           rid text NOT NULL default '',
+                           uid integer NOT NULL default '0',
+                           root_row text NOT NULL default '',
+                           data text NOT NULL,
+                           preview text NOT NULL,
+                           timestamp integer NOT NULL default '0',
+                           PRIMARY KEY (tid)
+                           )");
+      break;
+    default:
+      break;
+  }
+  return $ret;
+}
+
 
 
 /**
Index: includes/locale.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/locale.inc,v
retrieving revision 1.56
diff -u -F^function -r1.56 locale.inc
--- includes/locale.inc	21 Oct 2005 11:14:28 -0000	1.56
+++ includes/locale.inc	7 Nov 2005 18:01:01 -0000
@@ -935,10 +935,14 @@ function _locale_export_remove_plural($e
 }
 
 function _locale_string_delete($lid) {
-  db_query('DELETE FROM {locales_source} WHERE lid = %d', $lid);
-  db_query('DELETE FROM {locales_target} WHERE lid = %d', $lid);
+  $did = next_delete_id();
+  $result = db_fetch_object(db_query('SELECT source, location FROM {locales_source} WHERE lid = %d', $lid));
+  $preview = array('source' => $result->source, 'location' => $result->location);
+  drupal_set_message(t('The string has been moved to trash.'));
+  system_trash($did, $lid, 'locale', $preview, 'DELETE FROM {locales_source} WHERE lid = %d', $lid);
+  system_trash($did, $lid, NULL, NULL, 'DELETE FROM {locales_target} WHERE lid = %d', $lid);
   locale_refresh_cache();
-  drupal_set_message(t('The string has been removed.'));
+  drupal_goto('admin/locale/string/search');
 }
 
 /**
@@ -1166,7 +1170,7 @@ function _locale_prepare_iso_list() {
 function _locale_get_iso639_list() {
   return array(
     "aa" => array("Afar"),
-    "ab" => array("Abkhazian", "Ð°Ò§Ñ?ÑƒÐ° Ð±Ñ‹Ð·ÑˆÓ™Ð°"),
+    "ab" => array("Abkhazian", "Ð°Ò§Ñ?ÑƒÐ° Ð±Ñ‹Ð·ÑˆÓ™Ð°"),
     "ae" => array("Avestan"),
     "af" => array("Afrikaans"),
     "ak" => array("Akan"),
@@ -1177,8 +1181,8 @@ function _locale_get_iso639_list() {
     "ay" => array("Aymara"),
     "az" => array("Azerbaijani", "azÉ™rbaycan"),
     "ba" => array("Bashkir"),
-    "be" => array("Belarusian", "Ð‘ÐµÐ»Ð°Ñ€ÑƒÑ?ÐºÐ°Ñ?"),
-    "bg" => array("Bulgarian", "Ð‘ÑŠÐ»Ð³Ð°Ñ€Ñ?ÐºÐ¸"),
+    "be" => array("Belarusian", "Ð‘ÐµÐ»Ð°Ñ€ÑƒÑ?ÐºÐ°Ñ?"),
+    "bg" => array("Bulgarian", "Ð‘ÑŠÐ»Ð³Ð°Ñ€Ñ?ÐºÐ¸"),
     "bh" => array("Bihari"),
     "bi" => array("Bislama"),
     "bm" => array("Bambara", "Bamanankan"),
@@ -1199,14 +1203,14 @@ function _locale_get_iso639_list() {
     "de" => array("German", "Deutsch"),
     "dv" => array("Maldivian"),
     "dz" => array("Bhutani"),
-    "ee" => array("Ewe", "Æ?Ê‹É›"),
+    "ee" => array("Ewe", "Æ?Ê‹É›"),
     "el" => array("Greek", "Î•Î»Î»Î·Î½Î¹ÎºÎ¬"),
     "en" => array("English"),
     "eo" => array("Esperanto"),
     "es" => array("Spanish", "EspaÃ±ol"),
     "et" => array("Estonian", "Eesti"),
     "eu" => array("Basque", "Euskera"),
-    "fa" => array("Persian", "Ù?Ø§Ø±Ø³ÛŒ"),
+    "fa" => array("Persian", "Ù?Ø§Ø±Ø³ÛŒ"),
     "ff" => array("Fulah", "Fulfulde"),
     "fi" => array("Finnish", "Suomi"),
     "fj" => array("Fiji"),
@@ -1221,7 +1225,7 @@ function _locale_get_iso639_list() {
     "gv" => array("Manx"),
     "ha" => array("Hausa"),
     "he" => array("Hebrew", "×¢×‘×¨×™×ª"),
-    "hi" => array("Hindi", "à¤¹à¤¿à¤¨à¥?à¤¦à¥€"),
+    "hi" => array("Hindi", "à¤¹à¤¿à¤¨à¥?à¤¦à¥€"),
     "ho" => array("Hiri Motu"),
     "hr" => array("Croatian", "Hrvatski"),
     "hu" => array("Hungarian", "Magyar"),
@@ -1232,7 +1236,7 @@ function _locale_get_iso639_list() {
     "ie" => array("Interlingue"),
     "ig" => array("Igbo"),
     "ik" => array("Inupiak"),
-    "is" => array("Icelandic", "Ã?slenska"),
+    "is" => array("Icelandic", "Ã?slenska"),
     "it" => array("Italian", "Italiano"),
     "iu" => array("Inuktitut"),
     "ja" => array("Japanese", "æ—¥æœ¬èªž"),
@@ -1244,7 +1248,7 @@ function _locale_get_iso639_list() {
     "kk" => array("Kazakh", "ÒšÐ°Ð·Ð°Ò›"),
     "kl" => array("Greenlandic"),
     "km" => array("Cambodian"),
-    "kn" => array("Kannada", "à²•à²¨à³?à²¨à²¡"),
+    "kn" => array("Kannada", "à²•à²¨à³?à²¨à²¡"),
     "ko" => array("Korean", "í•œêµ­ì–´"),
     "kr" => array("Kanuri"),
     "ks" => array("Kashmiri"),
@@ -1262,7 +1266,7 @@ function _locale_get_iso639_list() {
     "mg" => array("Malagasy"),
     "mh" => array("Marshallese"),
     "mi" => array("Maori"),
-    "mk" => array("Macedonian", "ÐœÐ°ÐºÐµÐ´Ð¾Ð½Ñ?ÐºÐ¸"),
+    "mk" => array("Macedonian", "ÐœÐ°ÐºÐµÐ´Ð¾Ð½Ñ?ÐºÐ¸"),
     "ml" => array("Malayalam", "à´®à´²à´¯à´¾à´³à´‚"),
     "mn" => array("Mongolian"),
     "mo" => array("Moldavian"),
@@ -1292,7 +1296,7 @@ function _locale_get_iso639_list() {
     "rm" => array("Rhaeto-Romance"),
     "rn" => array("Kirundi"),
     "ro" => array("Romanian", "RomÃ¢nÄƒ"),
-    "ru" => array("Russian", "Ð ÑƒÑ?Ñ?ÐºÐ¸Ð¹"),
+    "ru" => array("Russian", "Ð ÑƒÑ?Ñ?ÐºÐ¸Ð¹"),
     "rw" => array("Kinyarwanda"),
     "sa" => array("Sanskrit"),
     "sc" => array("Sardinian"),
@@ -1301,20 +1305,20 @@ function _locale_get_iso639_list() {
     "sg" => array("Sango"),
     "sh" => array("Serbo-Croatian"),
     "si" => array("Singhalese"),
-    "sk" => array("Slovak", "SlovenÄ?ina"),
-    "sl" => array("Slovenian", "SlovenÅ¡Ä?ina"),
+    "sk" => array("Slovak", "SlovenÄ?ina"),
+    "sl" => array("Slovenian", "SlovenÅ¡Ä?ina"),
     "sm" => array("Samoan"),
     "sn" => array("Shona"),
     "so" => array("Somali"),
     "sq" => array("Albanian", "Shqip"),
-    "sr" => array("Serbian", "Ð¡Ñ€Ð¿Ñ?ÐºÐ¸"),
+    "sr" => array("Serbian", "Ð¡Ñ€Ð¿Ñ?ÐºÐ¸"),
     "ss" => array("Siswati"),
     "st" => array("Sesotho"),
     "su" => array("Sudanese"),
     "sv" => array("Swedish", "Svenska"),
     "sw" => array("Swahili", "Kiswahili"),
-    "ta" => array("Tamil", "à®¤à®®à®¿à®´à¯?"),
-    "te" => array("Telugu", "à°¤à±†à°²à±?à°—à±?"),
+    "ta" => array("Tamil", "à®¤à®®à®¿à®´à¯?"),
+    "te" => array("Telugu", "à°¤à±†à°²à±?à°—à±?"),
     "tg" => array("Tajik"),
     "th" => array("Thai", "à¸ à¸²à¸©à¸²à¹„à¸—à¸¢"),
     "ti" => array("Tigrinya"),
@@ -1328,7 +1332,7 @@ function _locale_get_iso639_list() {
     "tw" => array("Twi"),
     "ty" => array("Tahitian"),
     "ug" => array("Uighur"),
-    "uk" => array("Ukrainian", "Ð£ÐºÑ€Ð°Ñ—Ð½Ñ?ÑŒÐºÐ°"),
+    "uk" => array("Ukrainian", "Ð£ÐºÑ€Ð°Ñ—Ð½Ñ?ÑŒÐºÐ°"),
     "ur" => array("Urdu", "Ø§Ø±Ø¯Ùˆ"),
     "uz" => array("Uzbek", "o'zbek"),
     "ve" => array("Venda"),
@@ -1340,7 +1344,7 @@ function _locale_get_iso639_list() {
     "yo" => array("Yoruba", "YorÃ¹bÃ¡"),
     "za" => array("Zhuang"),
     "zh-hans" => array("Chinese, Simplified", "ç®€ä½“ä¸­æ–‡"),
-    "zh-hant" => array("Chinese, Traditional", "ç¹?é«”ä¸­æ–‡"),
+    "zh-hant" => array("Chinese, Traditional", "ç¹?é«”ä¸­æ–‡"),
     "zu" => array("Zulu", "isiZulu"),
   );
 }
Index: modules/block.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/block.module,v
retrieving revision 1.186
diff -u -F^function -r1.186 block.module
--- modules/block.module	3 Nov 2005 15:39:37 -0000	1.186
+++ modules/block.module	7 Nov 2005 18:01:01 -0000
@@ -417,10 +417,12 @@ function block_box_add() {
  */
 function block_box_delete($bid = 0) {
   $box = block_box_get($bid);
-  $form['info'] = array('#type' => 'hidden', '#value' => $box['info'] ? $box['info'] : $box['title']);
-  $form['bid'] = array('#type' => 'hidden', '#value' => $bid);
-
-  return confirm_form('block_box_delete_confirm', $form, t('Are you sure you want to delete the block %name?', array('%name' => theme('placeholder', $info))), 'admin/block', '', t('Delete'), t('Cancel'));
+  $did = next_delete_id();
+  $preview = array('title' => $box['title'], 'info' => $box['info'], 'body' => $box['body']);
+  drupal_set_message(t('The block %name has been moved to trash.', array('%name' => theme('placeholder', $box['info']))));
+  system_trash($did, $bid, 'block', $preview, 'DELETE FROM {boxes} WHERE bid = %d', $bid);
+  cache_clear_all();
+  drupal_goto('admin/block');
 }
 
 /**
@@ -428,10 +430,7 @@ function block_box_delete($bid = 0) {
  */
 function block_box_delete_confirm_execute($form_id, $edit) {
   $form = $GLOBALS['form_values'];
-  db_query('DELETE FROM {boxes} WHERE bid = %d', $form['bid']);
-  drupal_set_message(t('The block %name has been removed.', array('%name' => theme('placeholder', $form['info']))));
-  cache_clear_all();
-  drupal_goto('admin/block');
+  
 };
 
 
Index: modules/book.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/book.module,v
retrieving revision 1.327
diff -u -F^function -r1.327 book.module
--- modules/book.module	1 Nov 2005 10:17:34 -0000	1.327
+++ modules/book.module	7 Nov 2005 18:01:02 -0000
@@ -217,7 +217,7 @@ function book_update($node) {
  * Implementation of hook_delete().
  */
 function book_delete(&$node) {
-  db_query('DELETE FROM {book} WHERE nid = %d', $node->nid);
+  system_trash($node->did, $node->nid, NULL, NULL, 'DELETE FROM {book} WHERE nid = %d', $node->nid);
 }
 
 /**
@@ -298,8 +298,10 @@ function book_outline() {
         break;
 
       case t('Remove from book outline'):
-        db_query('DELETE FROM {book} WHERE nid = %d', $node->nid);
-        drupal_set_message(t('The post has been removed from the book.'));
+        $did = next_delete_id();
+        $preview = array('title' => $node-title, 'body' => $node->body);
+        drupal_set_message(t('The post has been removed from the book and placed in trash.'));
+        system_trash($did, $node->nid, 'book', $preview, 'DELETE FROM {book} WHERE nid = %d', $node->nid);
         drupal_goto("node/$node->nid");
         break;
 
Index: modules/comment.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/comment.module,v
retrieving revision 1.385
diff -u -F^function -r1.385 comment.module
--- modules/comment.module	1 Nov 2005 10:17:34 -0000	1.385
+++ modules/comment.module	7 Nov 2005 18:01:04 -0000
@@ -220,8 +220,14 @@ function comment_nodeapi(&$node, $op, $a
       break;
 
     case 'delete':
-      db_query('DELETE FROM {comments} WHERE nid = %d', $node->nid);
-      db_query('DELETE FROM {node_comment_statistics} WHERE nid = %d', $node->nid);
+      $result = db_query('SELECT * FROM {comments} WHERE nid = %d', $node->nid);
+      while ($comment = db_fetch_object($result)) {
+        $i++;
+        $preview['subject'. $i] = $comment->subject;
+        $preview['comment'. $i] = $comment->comment;
+      }
+      system_trash($node->did, $node->nid, NULL, $preview, 'DELETE FROM {comments} WHERE nid = %d', $node->nid);
+      system_trash($node->did, $node->nid, NULL, NULL, 'DELETE FROM {node_comment_statistics} WHERE nid = %d', $node->nid);
       break;
 
     case 'update index':
@@ -897,12 +903,10 @@ function comment_delete($cid) {
   $comment = db_fetch_object(db_query('SELECT c.*, u.name AS registered_name, u.uid FROM {comments} c INNER JOIN {users} u ON u.uid = c.uid WHERE c.cid = %d', $cid));
   $comment->name = $comment->uid ? $comment->registered_name : $comment->name;
 
-  $output = '';
-
   // We'll only delete if the user has confirmed the
   // deletion using the form in our else clause below.
-  if ($comment->cid && $_POST['edit']['confirm']) {
-    drupal_set_message(t('The comment and all its replies have been deleted.'));
+  if ($comment->cid) {
+    drupal_set_message(t('The comment and all its replies have been moved to trash.'));
 
     // Delete comment and its replies.
     _comment_delete_thread($comment);
@@ -914,20 +918,10 @@ function comment_delete($cid) {
 
     drupal_goto("node/$comment->nid");
   }
-  else if ($comment->cid) {
-    $output = confirm_form('comment_confirm_delete',
-                    array(),
-                    t('Are you sure you want to delete the comment %title?', array('%title' => theme('placeholder', $comment->subject))),
-                    'node/'. $comment->nid,
-                    t('Any replies to this comment will be lost. This action cannot be undone.'),
-                    t('Delete'),
-                    t('Cancel'));
-  }
   else {
     drupal_set_message(t('The comment no longer exists.'));
   }
 
-  return $output;
 }
 
 /**
@@ -1277,9 +1271,19 @@ function theme_comment_post_forbidden() 
 }
 
 function _comment_delete_thread($comment) {
+  static $did;
+  if ($did) {
+    $root_row = NULL;
+    $preview = NULL;
+  }
+  else {
+    $did = next_delete_id();
+    $root_row = 'comment';
+    $preview = array('subject' => $comment->subject, 'comment' => $comment->comment);
+  }
   // Delete the comment:
-  db_query('DELETE FROM {comments} WHERE cid = %d', $comment->cid);
-  watchdog('content', t('Comment: deleted %subject.', array('%subject' => theme('placeholder', $comment->subject))));
+  system_trash($did, $comment->nid, $root_row, $preview, 'DELETE FROM {comments} WHERE cid = %d', $comment->cid);
+  watchdog('content', t('Comment: moved %subject to trash.', array('%subject' => theme('placeholder', $comment->subject))));
 
   comment_invoke_comment($comment, 'delete');
 
Index: modules/contact.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/contact.module,v
retrieving revision 1.28
diff -u -F^function -r1.28 contact.module
--- modules/contact.module	5 Nov 2005 08:00:20 -0000	1.28
+++ modules/contact.module	7 Nov 2005 18:01:05 -0000
@@ -209,19 +209,12 @@ function contact_admin_edit($cid = NULL)
 }
 
 function contact_admin_delete($cid) {
-  $info = db_fetch_object(db_query("SELECT cid, category FROM {contact} WHERE cid = '%d'",$cid));
-  if ($_POST['op'] != t('Delete')) {
-    return confirm_form('contact_admin_delete', array(),
-                    t('Are you sure you want to delete %category?', array('%category' => theme('placeholder', $info->category))),
-                    'admin/contact',
-                    t('This action cannot be undone.'),
-                    t('Delete'),
-                    t('Cancel'));
-  }
-  else {
-    db_query("DELETE FROM {contact} WHERE cid = '%d'", $cid);
+    $did = next_delete_id();
+    $info = db_fetch_object(db_query("SELECT cid, category FROM {contact} WHERE cid = '%d'",$cid));
+    $preview = array('category' => $info->category);
+    drupal_set_message(t('Contact category %category moved to trash', array('%category' => $info->category)));
+    system_trash($did, $category, 'contact', $preview, "DELETE FROM {contact} WHERE cid = '%d'", $cid);
     drupal_goto('admin/contact');
-  }
 }
 
 
Index: modules/filter.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/filter.module,v
retrieving revision 1.80
diff -u -F^function -r1.80 filter.module
--- modules/filter.module	1 Nov 2005 10:17:34 -0000	1.80
+++ modules/filter.module	7 Nov 2005 18:01:06 -0000
@@ -350,33 +350,23 @@ function filter_admin_add() {
  * Menu callback; confirm deletion of a format.
  */
 function filter_admin_delete() {
-  $edit = $_POST['edit'];
-  if ($edit['confirm']) {
-    if ($edit['format'] != variable_get('filter_default_format', 1)) {
-      db_query("DELETE FROM {filter_formats} WHERE format = %d", $edit['format']);
-      db_query("DELETE FROM {filters} WHERE format = %d", $edit['format']);
-
-      $default = variable_get('filter_default_format', 1);
-      db_query("UPDATE {node_revisions} SET format = %d WHERE format = %d", $default, $edit['format']);
-      db_query("UPDATE {comments} SET format = %d WHERE format = %d", $default, $edit['format']);
-      db_query("UPDATE {boxes} SET format = %d WHERE format = %d", $default, $edit['format']);
-
-      cache_clear_all('filter:'. $edit['format'], true);
-
-      drupal_set_message(t('Deleted input format %format.', array('%format' => theme('placeholder', $edit['name']))));
-    }
-    drupal_goto('admin/filters');
-  }
-
   $format = arg(3);
-  $format = db_fetch_object(db_query('SELECT * FROM {filter_formats} WHERE format = %d', $format));
-
-  $form['format'] = array('#type' => 'hidden', '#value' => $format->format);
-  $form['name'] = array('#type' => 'hidden', '#value' => $format->name);
-
-  return confirm_form('filter_admin_delete', $form, t('Are you sure you want to delete the input format %format?', array('%format' => theme('placeholder', $format->name))), 'admin/filters', t('If you have any content left in this input format, it will be switched to the default input format. This action cannot be undone.'), t('Delete'), t('Cancel'));
-
+  if ($format != variable_get('filter_default_format', 1)) {
+    $result = db_fetch_object(db_query('SELECT * FROM {filter_formats} WHERE format = %d', $format));
+    $did = next_delete_id();
+    $preview = array('name' => $result->name);
+    drupal_set_message(t('Input format %format sent to trash.', array('%format' => theme('placeholder', $result->name))));
+    system_trash($did, $format, 'filter', $preview, "DELETE FROM {filters} WHERE format = %d", $format);
+    system_trash($did, $format, NULL, NULL, "DELETE FROM {filter_formats} WHERE format = %d", $format);
+
+    $default = variable_get('filter_default_format', 1);
+    db_query("UPDATE {node_revisions} SET format = %d WHERE format = %d", $default, $format);
+    db_query("UPDATE {comments} SET format = %d WHERE format = %d", $default, $format);
+    db_query("UPDATE {boxes} SET format = %d WHERE format = %d", $default, $format);
 
+    cache_clear_all('filter:'. $format, true);
+  }
+  drupal_goto('admin/filters');
 }
 
 /**
Index: modules/forum.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/forum.module,v
retrieving revision 1.282
diff -u -F^function -r1.282 forum.module
--- modules/forum.module	4 Nov 2005 19:40:26 -0000	1.282
+++ modules/forum.module	7 Nov 2005 18:01:07 -0000
@@ -154,7 +154,9 @@ function forum_taxonomy($op, $type, $obj
   if ($op == 'delete' && $type == 'term' && $object->vid == _forum_get_vid())  {
     $results = db_query('SELECT f.nid FROM {forum} f WHERE f.tid = %d', $object->tid);
     while ($node = db_fetch_object($results)) {
-      node_delete($node->nid);
+      $node = node_load($node->nid);
+      $node->did = $object->did;
+      node_delete($node);
     }
   }
   elseif ($op == 'delete' && $type == 'vocabulary' && $object->vid == _forum_get_vid())  {
Index: modules/locale.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/locale.module,v
retrieving revision 1.129
diff -u -F^function -r1.129 locale.module
--- modules/locale.module	1 Nov 2005 10:17:34 -0000	1.129
+++ modules/locale.module	7 Nov 2005 18:01:07 -0000
@@ -301,39 +301,28 @@ function locale_admin_manage() {
 function locale_admin_manage_delete_screen() {
   include_once './includes/locale.inc';
   $langcode = arg(4);
-  $edit = $_POST['edit'];
-
-  // Check confirmation and if so, delete language
-  if ($edit['confirm']) {
-    $languages = locale_supported_languages(FALSE, TRUE);
-    if (isset($languages['name'][$edit['langcode']])) {
-      db_query("DELETE FROM {locales_meta} WHERE locale = '%s'", $edit['langcode']);
-      db_query("DELETE FROM {locales_target} WHERE locale = '%s'", $edit['langcode']);
-      $message = t('The language %locale has been removed.', array('%locale' => theme('placeholder', t($languages['name'][$edit['langcode']]))));
-      drupal_set_message($message);
-      watchdog('locale', $message);
-    }
-
-    // Changing the locale settings impacts the interface:
-    cache_clear_all();
-    drupal_goto('admin/locale/language/overview');
-  }
-
+  
   // Do not allow deletion of English locale
   if ($langcode == 'en') {
     drupal_goto('admin/locale/language/overview');
     return;
   }
 
-  // For other locales, warn user that data loss is ahead
+  // Delete language
   $languages = locale_supported_languages(FALSE, TRUE);
+  if (isset($languages['name'][$langcode])) {
+    $did = next_delete_id();
+    $preview = array('language code' => $langcode, 'name' => $languages['name'][$langcode]);
+    $message = t('The language %locale has been sent to trash.', array('%locale' => theme('placeholder', t($languages['name'][$langcode]))));
+    drupal_set_message($message);
+    watchdog('locale', $message);
+    system_trash($did, $langcode, 'locale', $preview, "DELETE FROM {locales_meta} WHERE locale = '%s'", $langcode);
+    system_trash($did, $langcode, NULL, NULL, "DELETE FROM {locales_target} WHERE locale = '%s'", $langcode);
+  }
 
-  $form['langcode'] = array('#type' => 'hidden', '#value' => $langcode);
-  return confirm_form('locale_admin_manage_delete_screen', $form,
-                  t('Are you sure you want to delete the language %name?', array('%name' => theme('placeholder', t($languages['name'][$langcode])))),
-                  'admin/locale/language/overview',
-                  t('Deleting a language will remove all data associated with it. This action cannot be undone.'),
-                  t('Delete'), t('Cancel'));
+  // Changing the locale settings impacts the interface:
+  cache_clear_all();
+  drupal_goto('admin/locale/language/overview');
 }
 
 /**
Index: modules/node.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/node.module,v
retrieving revision 1.545
diff -u -F^function -r1.545 node.module
--- modules/node.module	4 Nov 2005 19:40:28 -0000	1.545
+++ modules/node.module	7 Nov 2005 18:01:10 -0000
@@ -859,6 +859,9 @@ function node_menu($may_cache) {
       'access' => user_access('administer nodes'));
     $items[] = array('path' => 'admin/node/action', 'title' => t('content'),
       'type' => MENU_CALLBACK);
+    $items[] = array('path' => 'admin/node/batch_delete', 'title' => t('content'),
+      'type' => MENU_CALLBACK, 'access' => user_access('administer nodes'),
+      'callback' => 'node_multiple_delete_confirm');  
     $items[] = array('path' => 'admin/node/overview', 'title' => t('list'),
       'type' => MENU_DEFAULT_LOCAL_TASK, 'weight' => -10);
     $items[] = array('path' => 'admin/settings/node', 'title' => t('posts'),
@@ -1093,16 +1096,18 @@ function node_filter_form_execute() {
  * Generate the content administration overview.
  */
 function node_admin_nodes_execute($form_id, $edit) {
-  $operations = node_operations();
-  if ($operations[$edit['operation']][1]) {
-    // Flag changes
-    $operation = $operations[$edit['operation']][1];
-    foreach ($edit['nodes'] as $nid => $value) {
-      if ($value) {
-        db_query($operation, $nid);
+  if ($edit['operation'] != 'delete') {
+    $operations = node_operations();
+    if ($operations[$edit['operation']][1]) {
+      // Flag changes
+      $operation = $operations[$edit['operation']][1];
+      foreach ($edit['nodes'] as $nid => $value) {
+        if ($value) {
+          db_query($operation, $nid);
+        }
       }
+      drupal_set_message(t('The update has been performed.'));
     }
-    drupal_set_message(t('The update has been performed.'));
     drupal_goto('admin/node');
   }
 }
@@ -1153,7 +1158,7 @@ function node_admin_nodes() {
 
   // If you are attempting to delete nodes, display the multiple deletion form.
   if ($form_values['operation'] == 'delete') {
-    $output = node_multiple_delete_form();
+    $output = node_multiple_delete_confirm();
   }
 
   return $output;
@@ -1190,28 +1195,81 @@ function theme_node_admin_nodes($form) {
   return $output;
 }
 
-function node_multiple_delete_form() {
+function node_multiple_delete_confirm() {
   global $form_values;
-  $form['nodes'] = array('#prefix' => '<ul>', '#suffix' => '</ul>', '#tree' => TRUE);
-  foreach ($form_values['nodes'] as $nid => $value) {
-    if ($value) {
-      $title = db_result(db_query('SELECT title FROM {node} WHERE nid = %d', $nid));
-      $form['nodes'][$nid] = array('#type' => 'hidden', '#value' => $nid, '#prefix' => '<li>', '#suffix' => check_plain($title) .'</li>');
+  $edit = $_POST['edit'];
+  // Grab nids from url for execute
+  if ($edit['confirm']) {
+    $nids = array_keys($edit['checkboxes']);
+  }
+  else {
+    // Keep only checked nodes' nids
+    $nids = array_keys(array_intersect($form_values['nodes'], array('1')));
+  }
+  foreach ($nids as $nid) {
+    $node = node_load($nid);
+    $extras = node_invoke_nodeapi($node, 'delete pre');
+    // No extras, just delete
+    if (!count($extras)) {
+      node_delete($node);
+    }
+    else {
+      // Add node and extras to the list only if no module has cancelled deletion for this node.
+      if (!in_array(FALSE, $extras)) {
+        $form['nodes'][$node->nid] = array('#type' => 'value', '#value' => 1);
+        $form['title'][$node->nid] = array('#type' => 'markup', '#value' => check_plain($node->title));
+        $form['extras'][$node->nid] = $extras;
+        $options[$node->nid] = '';
+      }
     }
   }
-  $form['operation'] = array('#type' => 'hidden', '#value' => 'delete');
-
-  return confirm_form('node_multiple_delete_form', $form,
-                      t('Are you sure you want to delete these items?'),
-                      'admin/node', t('This action cannot be undone.'),
-                      t('Delete all'), t('Cancel'));
+  if ($edit['confirm']) {
+    confirm_form('node_multiple_delete_confirm', $form,
+                    t('The following items need to be reviewed'),
+                    'admin/node', t('Selected items will be sent to trash.'),
+                    t('Delete selected'), t('Cancel'));
+  }
+  // Back to the admin page if no nodes can be deleted.
+  if (!count($options)) {
+    drupal_goto('admin/node');
+  }
+  else {
+    $form['nodes']['#tree'] = TRUE;
+    $form['title']['#tree'] = TRUE;
+    $form['extras']['#tree'] = TRUE;
+    $form['checkboxes'] = array('#type' => 'checkboxes', '#options' => $options);
+    $form['confirm'] = array('#type' => 'value', '#value' => 1);
+    $form['operation'] = array('#type' => 'value', '#value' => 'delete');
+    $form['#method'] = 'post';
+    $form['#action'] =  url('admin/node/batch_delete');
+    return confirm_form('node_multiple_delete_confirm', $form,
+                      t('The following items need to be reviewed'),
+                      'admin/node', t('Selected items will be sent to trash.'),
+                      t('Delete selected'), t('Cancel'));
+  }
 }
 
+function theme_node_multiple_delete_confirm($form) {
+  $rows = array();
+  $header = array('');
+  $output = '';
+  foreach(element_children($form['nodes']) as $nid) {
+    $rows[] = array('<div class="container-inline">'. '<b>'. form_render($form['title'][$nid]) .'</b>'.  form_render($form['checkboxes'][$nid]) .'</div>'. form_render($form['extras'][$nid]) . form_render($form['nodes'][$nid]));
+    $rows[] = array('');
+  }
+  $output .= theme('table', $header, $rows);
+  $output .= form_render($form);
+  return $output;
+}
 
-function node_multiple_delete_form_execute($form_id, $edit) {
-  if ($edit['confirm']) {
-    foreach ($edit['nodes'] as $nid => $value) {
-      node_delete($nid);
+function node_multiple_delete_confirm_execute($form_id, $form_values) {
+  $edit = $_POST['edit'];
+  if ($form_values['confirm']) {
+    foreach ($edit['checkboxes'] as $nid => $value) {
+      // Merge extra confirm data with node
+      $node = object2array(node_load($nid));
+      $node = array2object(array_merge($node, $edit['extras'][$nid]));
+      node_delete($node);
     }
     drupal_set_message(t('The items have been deleted.'));
   }
@@ -1327,11 +1385,14 @@ function node_revision_delete($nid, $rev
     $count_revisions = db_result(db_query('SELECT COUNT(vid) FROM {node_revisions} WHERE nid = %d', $nid));
     // Don't delete the last revision of the node or the current revision
     if ($count_revisions > 1) {
-      db_query("DELETE FROM {node_revisions} WHERE nid = %d AND vid = %d", $nid, $revision);
-      drupal_set_message(t('Deleted revision with the ID %revision.', array('%revision' => theme('placeholder', $revision))));
+      $node = node_load($nid);
+      $did = next_delete_id();
+      $preview = array('title' => $node->title, 'body' => $node->body);
+      drupal_set_message(t('Revision ID %revision moved to trash.', array('%revision' => theme('placeholder', $revision))));
+      system_trash($did, $nid, 'node revision', $preview, "DELETE FROM {node_revisions} WHERE nid = %d AND vid = %d", $nid, $revision);
     }
     else {
-      drupal_set_message(t('Deletion failed. You tried to delete the current revision.'));
+      drupal_set_message(t('Deletion failed. You tried to move the current revision to trash.'));
     }
 
     drupal_goto("node/$nid/revisions");
@@ -1839,16 +1900,36 @@ function node_delete_confirm() {
   $edit = $_POST['edit'];
   $edit['nid'] = $edit['nid'] ? $edit['nid'] : arg(1);
   $node = node_load($edit['nid']);
-
   if (node_access('delete', $node)) {
     $form['nid'] = array('#type' => 'value', '#value' => $node->nid);
-    $output = confirm_form('node_delete_confirm', $form,
-                   t('Are you sure you want to delete %title?', array('%title' => theme('placeholder', $node->title))),
-                   $_GET['destination'] ? $_GET['destination'] : 'node/'. $node->nid, t('This action cannot be undone.'),
-                   t('Delete'), t('Cancel')  );
+    $form['confirm'] = array('#type' => 'value', '#value' => 1);
+    // Check for extra info from modules
+    $extras = node_invoke_nodeapi($node, 'delete pre');
+    $form['extras'] = $extras;
+    if ($edit['confirm']) {
+      confirm_form('node_delete_confirm', $form,
+                 t('Are you sure you want to delete %title?', array('%title' => theme('placeholder', $node->title))),
+                 $_GET['destination'] ? $_GET['destination'] : 'node/'. $node->nid, t('This action will send the 
+                 item to trash'), t('Delete'), t('Cancel'));
+    }
+    // No extras, just delete the node
+    if (!count($extras)) {
+      node_delete($node);
+      drupal_goto('node');
+    }
+    else {
+      // Cancel deletion if necessary, otherwise display confirm form
+      if (in_array(FALSE, $extras)) {
+        drupal_goto('node/'. $node->nid .'/edit');
+      }
+      else {
+        return confirm_form('node_delete_confirm', $form,
+               t('Are you sure you want to delete %title?', array('%title' => theme('placeholder', $node->title))),
+               $_GET['destination'] ? $_GET['destination'] : 'node/'. $node->nid, t('This action will send the 
+                 item to trash'), t('Delete'), t('Cancel'));
+      }
+    }
   }
-
-  return $output;
 }
 
 /**
@@ -1856,7 +1937,10 @@ function node_delete_confirm() {
  */
 function node_delete_confirm_execute($form_id, $form_values) {
   if ($form_values['confirm']) {
-    node_delete($form_values['nid']);
+    // Merge extra confirm data with node
+    $node = object2array(node_load($form_values['nid']));
+    $node = array2object(array_merge($node, $form_values));
+    node_delete($node);
     drupal_goto('node');
   }
 }
@@ -1864,28 +1948,40 @@ function node_delete_confirm_execute($fo
 /**
  * Delete a node.
  */
-function node_delete($nid) {
+function node_delete($node) {
+  if (is_numeric($node)) {
+    $node = node_load($node);
+  }
+  elseif (is_array($node)) {
+    $node = node_load($node['nid']);
+  }
+  if (!$node->did) {
+    $node->did = next_delete_id();
+    $root_row = 'node';
+  }
+  else {
+    $root_row = NULL;
+  }
+  $preview['title'] = $node->title;
+  if ($node->body) {
+    $preview['body'] = $node->body;
+  }
+  drupal_set_message(t('%title moved to trash.', array('%title' => theme('placeholder', $node->title))));
+  system_trash($node->did, $node->nid, $root_row, $preview, 'DELETE FROM {node} WHERE nid = %d', $node->nid);
+  system_trash($node->did, $node->nid, NULL, NULL, 'DELETE FROM {node_revisions} WHERE nid = %d', $node->nid);
 
-  $node = node_load($nid);
+  // Call the node-specific callback (if any):
+  node_invoke($node, 'delete');
+  node_invoke_nodeapi($node, 'delete');
 
-  if (node_access('delete', $node)) {
-    db_query('DELETE FROM {node} WHERE nid = %d', $node->nid);
-    db_query('DELETE FROM {node_revisions} WHERE nid = %d', $node->nid);
+  // Clear the cache so an anonymous poster can see the node being deleted.
+  cache_clear_all();
 
-    // Call the node-specific callback (if any):
-    node_invoke($node, 'delete');
-    node_invoke_nodeapi($node, 'delete');
-
-    // Clear the cache so an anonymous poster can see the node being deleted.
-    cache_clear_all();
-
-    // Remove this node from the search index if needed.
-    if (function_exists('search_wipe')) {
-      search_wipe($node->nid, 'node');
-    }
-    drupal_set_message(t('%title has been deleted.', array('%title' => theme('placeholder', $node->title))));
-    watchdog('content', t('%type: deleted %title.', array('%type' => theme('placeholder', t($node->type)), '%title' => theme('placeholder', $node->title))));
+  // Remove this node from the search index if needed.
+  if (function_exists('search_wipe')) {
+    search_wipe($node->nid, 'node');
   }
+  watchdog('content', t('%type: deleted %title.', array('%type' => theme('placeholder', t($node->type)), '%title' => theme('placeholder', $node->title))));
 }
 
 /**
Index: modules/path.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/path.module,v
retrieving revision 1.70
diff -u -F^function -r1.70 path.module
--- modules/path.module	1 Nov 2005 10:17:34 -0000	1.70
+++ modules/path.module	7 Nov 2005 18:01:10 -0000
@@ -99,17 +99,25 @@ function path_admin_edit($pid = 0) {
  * Menu callback; handles deletion of an URL alias.
  */
 function path_admin_delete($pid = 0) {
-  db_query('DELETE FROM {url_alias} WHERE pid = %d', $pid);
-  drupal_set_message(t('The alias has been deleted.'));
+  $did = next_delete_id();
+  $result = db_fetch_object(db_query('SELECT src, dst FROM {url_alias} WHERE pid = %d', $pid));
+  $preview = array('source' => $result->src, 'destination' => $result->dst);
+  drupal_set_message(t('The alias has been moved to trash.'));
+  system_trash($did, $pid, 'url alias', $preview, 'DELETE FROM {url_alias} WHERE pid = %d', $pid);
   drupal_goto('admin/path');
 }
 
 /**
  * Set an aliased path for a given Drupal path, preventing duplicates.
  */
-function path_set_alias($path = NULL, $alias = NULL, $pid = NULL) {
+function path_set_alias($path = NULL, $alias = NULL, $pid = NULL, $node = NULL) {
   if ($path && !$alias) {
-    db_query("DELETE FROM {url_alias} WHERE src = '%s'", $path);
+    if ($node->did) {
+      system_trash($node->did, $node->nid, NULL, NULL, "DELETE FROM {url_alias} WHERE src = '%s'", $path);
+    }
+    else {
+      db_query("DELETE FROM {url_alias} WHERE src = '%s'", $path);
+    }
     drupal_clear_path_cache();
   }
   else if (!$path && $alias) {
@@ -216,7 +224,7 @@ function path_nodeapi(&$node, $op, $arg)
       case 'delete':
         $path = "node/$node->nid";
         if (drupal_get_path_alias($path) != $path) {
-          path_set_alias($path);
+          path_set_alias($path, NULL, NULL, $node);
         }
         break;
     }
Index: modules/poll.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/poll.module,v
retrieving revision 1.176
diff -u -F^function -r1.176 poll.module
--- modules/poll.module	2 Nov 2005 08:58:27 -0000	1.176
+++ modules/poll.module	7 Nov 2005 18:01:11 -0000
@@ -84,9 +84,16 @@ function poll_cron() {
 /**
  * Implementation of hook_delete().
  */
-function poll_delete($node) {
-  db_query("DELETE FROM {poll} WHERE nid = %d", $node->nid);
-  db_query("DELETE FROM {poll_choices} WHERE nid = %d", $node->nid);
+function poll_delete(&$node) {
+  // Poll trash preview
+  if ($node->choice) {
+    foreach ($node->choice as $key => $array) {
+      $c++;
+      $preview["choice$c"] = $array['chtext'];
+    }
+  }
+  system_trash($node->did, $node->nid, NULL, $preview, "DELETE FROM {poll} WHERE nid = %d", $node->nid);
+  system_trash($node->did, $node->nid, NULL, NULL, "DELETE FROM {poll_choices} WHERE nid = %d", $node->nid);
 }
 
 /**
Index: modules/profile.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/profile.module,v
retrieving revision 1.116
diff -u -F^function -r1.116 profile.module
--- modules/profile.module	1 Nov 2005 10:17:34 -0000	1.116
+++ modules/profile.module	7 Nov 2005 18:01:11 -0000
@@ -554,18 +554,13 @@ function profile_admin_edit($fid) {
  * Menu callback; deletes a field from all user profiles.
  */
 function profile_admin_delete($fid) {
-  $field = db_fetch_object(db_query("SELECT title FROM {profile_fields} WHERE fid = %d", $fid));
-  if ($_POST['edit']['confirm']) {
-    db_query('DELETE FROM {profile_fields} WHERE fid = %d', $fid);
-    cache_clear_all();
-    drupal_set_message(t('The field %field has been deleted.', array('%field' => theme('placeholder', $field->title))));
-    drupal_goto('admin/settings/profile');
-  }
-  else {
-    return confirm_form('profile_confirm_delete', $form, t('Do you want to remove the field %field?',
-                    array('%field' => $field->title)),
-                  'admin/settings/profile', '', t('Delete'), t('Cancel'));
-  }
+  $did = next_delete_id();
+  $result = db_fetch_object(db_query("SELECT title, explanation, category FROM {profile_fields} WHERE fid = %d", $fid));
+  $preview = array('title' => $result->title, 'explanation' => $result->explanation, 'category' => $result->category);
+  drupal_set_message(t('The field %field has been moved to trash.', array('%field' => theme('placeholder', $result->title))));
+  system_trash($did, $fid, 'profile', $preview, 'DELETE FROM {profile_fields} WHERE fid = %d', $fid);
+  cache_clear_all();
+  drupal_goto('admin/settings/profile');
 }
 
 function _profile_field_form($type, $edit = array()) {
Index: modules/statistics.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/statistics.module,v
retrieving revision 1.211
diff -u -F^function -r1.211 statistics.module
--- modules/statistics.module	1 Nov 2005 10:17:34 -0000	1.211
+++ modules/statistics.module	7 Nov 2005 18:01:12 -0000
@@ -477,7 +477,7 @@ function statistics_nodeapi(&$node, $op,
   switch ($op) {
     case 'delete':
       // clean up statistics table when node is deleted
-      db_query('DELETE FROM {node_counter} WHERE nid = %d', $node->nid);
+      system_trash($node->did, $node->nid, NULL, NULL, 'DELETE FROM {node_counter} WHERE nid = %d', $node->nid);
   }
 }
 
Index: modules/system.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/system.module,v
retrieving revision 1.251
diff -u -F^function -r1.251 system.module
--- modules/system.module	3 Nov 2005 19:33:37 -0000	1.251
+++ modules/system.module	7 Nov 2005 18:01:14 -0000
@@ -47,7 +47,7 @@ function system_help($section) {
  * Implementation of hook_perm().
  */
 function system_perm() {
-  return array('administer site configuration', 'access administration pages', 'bypass input data check');
+  return array('administer site configuration', 'access administration pages', 'bypass input data check', 'administer trash');
 }
 
 /**
@@ -139,6 +139,18 @@ function system_menu($may_cache) {
     }
     $items[] = array('path' => 'admin/modules', 'title' => t('modules'),
       'callback' => 'system_modules', 'access' => $access);
+      
+    // Trash
+    $items[] = array('path' => 'admin/trash', 'title' => t('trash'),
+      'callback' => 'system_admin_trash', 'access' => TRUE);
+    $items[] = array('path' => 'trash/preview', 'title' => t('preview'),
+      'callback' => 'system_trash_preview', 'access' => TRUE, 'type' => MENU_CALLBACK);
+    $items[] = array('path' => 'trash/recover', 'title' => t('recover'),
+      'callback' => 'system_trash_recover', 'access' => TRUE, 'type' => MENU_CALLBACK);
+    $items[] = array('path' => 'trash/delete', 'title' => t('delete'),
+      'callback' => 'system_trash_delete', 'access' => TRUE, 'type' => MENU_CALLBACK);
+    $items[] = array('path' => 'admin/trash/action', 'title' => t('content'),
+      'type' => MENU_CALLBACK);
   }
 
   return $items;
@@ -1124,6 +1136,259 @@ function theme_search_box($form) {
   return $output;
 }
 
+function system_admin_trash() {
+
+  global $user;
+  global $form_values;
+  $op = $_POST['op'];
+  $form = array();
+  $view_all = user_access('administer trash');
+  if ($view_all) {
+    $result = pager_query("SELECT * FROM {deleted} WHERE root_row != '' ORDER BY timestamp DESC", 25  , 0);
+  }
+  else {
+    $result = pager_query("SELECT * FROM {deleted} WHERE root_row != '' AND uid = %d ORDER BY timestamp DESC", 25  , 0, NULL, $user->uid);
+  }
+  $destination = drupal_get_destination();
+  while ($recover = db_fetch_object($result)) {
+    $preview = unserialize($recover->preview);
+    $title = is_array($preview[0]) ? array_shift($preview[0]) : '[none]';
+    $items[$recover->did] = '';
+    $form['datetime'][$recover->did] = array('#type' => 'markup', '#value' => format_date($recover->timestamp, 'small'));
+    $form['type'][$recover->did] =  array('#type' => 'markup', '#value' => t($recover->root_row));
+    $form['title'][$recover->did] = array('#type' => 'markup', '#value' => t($title));
+    $form['preview'][$recover->did] = array('#type' => 'markup', '#value' => l(t('preview'), "trash/preview/$recover->tid", array(), $destination));
+  }
+  $form['did'] = array('#type' => 'checkboxes', '#options' => $items);
+  $form['pager'] = array('#value' => theme('pager', NULL, 25, 0));
+  $form['buttons'] = array('#prefix' => '<div class="container-inline">', '#suffix' => '</div>');
+  $form['buttons']['recover'] = array('#type' => 'submit', '#value' => t('Recover'));
+  if ($view_all) {
+    $form['buttons']['delete'] = array('#type' => 'button', '#button_type' => 'submit', '#value' => t('Delete selected'));
+    $form['buttons']['delete_all'] = array('#type' => 'button', '#button_type' => 'submit', '#value' => t('Delete all'));
+  }
+  $form['buttons']['all'] = array('#type' => 'hidden', '#value' => 'all');
+  $form['#method'] = 'post';
+  $form['#action'] =  url('admin/trash/action');
+  
+  if ($op != t('Delete')) {
+    $output .= drupal_get_form('system_admin_trash', $form, 'system_trash_recover_delete');
+  }
+  
+  // If you are attempting to delete nodes, display the multiple deletion form.
+    if ($op && ($op != t('Recover'))) {
+    $output = system_trash_multiple_delete_confirm();
+  }
+  return $output;
+}  
+
+function theme_system_admin_trash($form) {
+
+  // Overview table:
+  $output = form_render($form['buttons']);
+  $header = array(NULL, t('Title'), t('Type'), t('Trashed'), t('Operations'));
+  if (is_array($form['datetime'])) {
+    foreach (element_children($form['datetime']) as $key) {
+      $row = array();
+      $row[] = form_render($form['did'][$key]);
+      $row[] = form_render($form['title'][$key]);
+      $row[] = form_render($form['type'][$key]);
+      $row[] = form_render($form['datetime'][$key]);
+      $row[] = form_render($form['preview'][$key]);
+      $rows[] = $row;
+    }
+
+  }
+  else  {
+    $rows[] = array(array('data' => t('There are no items in your trash'), 'colspan' => '5'));
+  }
+
+  $output .= theme('table', $header, $rows);
+  if ($form['pager']['#value']) {
+    $output .= form_render($form['pager']);
+  }
+
+  return $output;
+}
+
+function system_trash($did, $rid, $root_row, $preview, $query) {
+  global $user;
+  static $same_did;
+  static $summed_preview;
+  // Grab the args for the query
+  $all_args = func_get_args();
+  if (count($all_args) > 5) {
+    $args = array_slice($all_args, 5);
+  }
+  else {
+    $args = array();
+  }
+  // Turn delete into select and get result
+  $delete = preg_replace('/DELETE.*?FROM/i', 'SELECT * FROM', $query);
+  $result = db_query($delete, $args);
+  $rid = $rid ? $rid : '';
+  $root_row = $root_row ? $root_row : '';
+  // Allow modules to add to data storage array
+  $recover = module_invoke_all('system_trash', $did, $rid, $root_row);
+  // Grab table name and store
+  $table = preg_match('/^DELETE FROM \{([^}]+)/', $query, $m);
+  $recover['table']  = $m[1];
+  // Loop through result inserting rows into deleted table
+  while ($recover['data'] = db_fetch_array($result)) {
+    $data = serialize($recover);
+    $tid = db_next_id('{deleted}_tid');
+    db_query("INSERT INTO {deleted} SET tid = %d, did = %d, rid = %d, uid = %d, root_row = '%s', data = '%s', timestamp = %d", $tid, $did, $rid, $user->uid, $root_row, $data, time());
+    $root_row = '';
+  }
+  // Only one message for each did
+  if ($same_did != $did) { 
+     drupal_set_message(t('Click %here to recover from %trash.', array('%here' => l(t('here'), "trash/recover/$did"), '%trash' => l(t('trash'), "admin/trash"))));
+    $same_did = $did;
+    $summed_preview = array();
+  }
+  // Insert new preview summary
+  if ($preview) {
+    $summed_preview[] = $preview;
+  }
+  $insert_preview = $summed_preview ? serialize($summed_preview) : '';
+  db_query("UPDATE {deleted} SET preview = '%s' WHERE did = %d AND root_row !=''", $insert_preview, $did);
+  // Delete from original table
+  db_query($query, $args); 
+}
+
+function system_trash_preview($tid) {
+  global $user;
+  $op = $_POST['op'];
+  $view_all = user_access('administer trash');
+  $insert = db_fetch_object(db_query('SELECT * FROM {deleted} WHERE tid = %d', $tid));
+  if ($view_all || $insert->uid == $user->uid) {
+    $did = $insert->did;
+    $output = '';
+    $form['buttons'] = array('#prefix' => '<div class="container-inline">', '#suffix' => '</div>');
+    $form['buttons']['recover'] = array('#type' => 'submit', '#value' => t('Recover'));
+    if ($view_all) {
+      $form['buttons']['delete'] = array('#type' => 'button', '#button_type' => 'submit', '#value' => t('Delete selected'));
+    }
+
+    $form['did']['#tree'] = TRUE;
+    $form['did'][$did] = array('#type' => 'hidden', '#value' => 1);
+
+    if ($op != t('Delete')) {
+      $output .= drupal_get_form('system_trash_preview', $form, 'system_trash_recover_delete');
+    }
+  
+    // If you are attempting to delete nodes, display the multiple deletion form.
+    if ($op && ($op != t('Recover'))) {
+      $output = system_trash_multiple_delete_confirm();
+    }
+    // Grab preview data
+    $values = array();
+    $data = unserialize($insert->preview);
+    $header = array();
+    $rows = array();
+    if ($data) {
+      foreach ($data as $preview_section) {
+        foreach ($preview_section as $key => $value) {
+          $rows[] = array('<strong>'. t($key) . ':</strong> ', t($value));
+        }
+        $rows[] = array(array('data' => '', 'colspan' => 2));
+      }
+    }
+    $output .= '<DL>';
+    $output .= '<DT><strong>'. t('Trashed') .': </strong>'. format_date($insert->timestamp, 'small');
+    $output .= '<DT><strong>'. t('Type') .': </strong>'. t($insert->root_row);
+    $output .= '</DL>';
+    $output .= '<h3>'. t('Data') .': </h3>';
+    $output .= theme('table', $header, $rows);;
+    return $output;
+  }
+  else {
+    drupal_access_denied();
+  }
+}
+
+function system_trash_recover_delete_execute($form_id, $form_values) {
+  $op = $_POST['op'];
+  $form_values['did'] = $form_values['did'] ? $form_values['did'] : array();
+  $dids = array_keys($form_values['did'], 1);
+  if ((count($dids) == 0) && $op != t('Delete all') && $form_values['operation'] != t('Delete all')) {
+        drupal_set_message(t('No items were selected. Select items in order to perform the operation'));
+        drupal_goto('admin/trash');
+  }
+  if ($op == t('Recover')) {
+    foreach ($dids as $did) {
+      $result = db_query('SELECT * FROM {deleted} WHERE did = %d', $did);
+      // Loop through reinserting all rows
+      while ($insert = db_fetch_object($result)) {
+        $values = array();
+        $recover = unserialize($insert->data);
+        foreach ($recover['data'] as $key => $value) {
+          $values[] = is_numeric($value) ? '%d' : '\'%s\'';
+          // Best guess at recovered node if present
+          if ($key == 'nid') {
+            $nid = $value;
+          }
+        }
+        db_query('INSERT INTO {'. $recover['table']. '} VALUES('. implode(', ', $values). ')', $recover['data']);  
+      }
+      module_invoke_all('system_trash_recover', $did);
+      db_query('DELETE FROM {deleted} WHERE did = %d', $did);
+    }
+    if ($form_id == 'system_trash_preview') { 
+      $message = $nid ? t('The %item has been recovered', array('%item' => l(t('item'), "node/$nid"))) : t('The item has been recovered');
+    }
+    else {
+      $message = t('The items have been recovered');
+    }
+  }
+  if ($form_values['confirm']) {
+    switch ($form_values['operation']) {
+      case t('Delete selected'):
+        foreach ($dids as $did) {
+          module_invoke_all('system_trash_delete', $did);
+          db_query('DELETE FROM {deleted} WHERE did = %d', $did);
+        }
+        $message = t('Permanent delete successful');
+        break;
+      case t('Delete all'):
+        module_invoke_all('system_trash_delete', 'all');
+        db_query('DELETE FROM {deleted}');
+        $message = t('Permanent delete successful');
+        break;
+    }
+  }
+  drupal_set_message($message);
+  drupal_goto('admin/trash');
+}
+
+function system_trash_multiple_delete_confirm() {
+  $op = $_POST['op'];
+  $edit = $_POST['edit'];
+  $edit['did'] = $edit['did'] ? $edit['did'] : array();
+  $dids = array_keys($edit['did'], 1);
+  if ($edit['confirm']) {
+    $form['operation'] = array('#type' => 'hidden', '#value' => $edit['operation']);
+    $_POST['edit']['form_id'] = 'system_trash_recover_delete';
+  }
+  else {
+    $form['operation'] = array('#type' => 'hidden', '#value' => $op);
+  }
+  $form['did']['#tree'] = TRUE;
+  foreach ($dids as $did) {
+  	$form['did'][$did] = array('#type' => 'hidden', '#value' => 1);
+  }
+  $item = (count($dids) == 1) ? 'this item' : 'these items';
+  $output = confirm_form('system_trash_recover_delete', $form,
+                  t('Are you sure you want to permanently delete %item?', array('%item' => $item)),
+                  'admin/trash', t('This operation cannot be undone.'),
+                  t('Delete'), t('Cancel'));
+  return $output;
+}
+
+function next_delete_id() {
+  return db_next_id('{deleted}_did');
+}
+
 /**
  * Output a confirmation form
  *
Index: modules/taxonomy.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/taxonomy.module,v
retrieving revision 1.233
diff -u -F^function -r1.233 taxonomy.module
--- modules/taxonomy.module	1 Nov 2005 10:17:34 -0000	1.233
+++ modules/taxonomy.module	7 Nov 2005 18:01:15 -0000
@@ -179,14 +179,16 @@ function taxonomy_save_vocabulary(&$edit
 
 function taxonomy_del_vocabulary($vid) {
   $vocabulary = taxonomy_get_vocabulary($vid);
-
-  db_query('DELETE FROM {vocabulary} WHERE vid = %d', $vid);
-  db_query('DELETE FROM {vocabulary_node_types} WHERE vid = %d', $vid);
+  $did = next_delete_id();
+  $preview = array('name' => $vocabulary->name, 'description' => $vocabulary->description);
+  system_trash($did, $vid, 'vocabulary', $preview, 'DELETE FROM {vocabulary} WHERE vid = %d', $vid);
+  system_trash($did, $vid, NULL, NULL, 'DELETE FROM {vocabulary_node_types} WHERE vid = %d', $vid);
   $result = db_query('SELECT tid FROM {term_data} WHERE vid = %d', $vid);
   while ($term = db_fetch_object($result)) {
-    taxonomy_del_term($term->tid);
+    taxonomy_del_term($term->tid, $did);
   }
 
+  $vocabulary->did = $did;
   module_invoke_all('taxonomy', 'delete', 'vocabulary', $vocabulary);
 
   cache_clear_all();
@@ -194,20 +196,6 @@ function taxonomy_del_vocabulary($vid) {
   return SAVED_DELETED;
 }
 
-function _taxonomy_confirm_del_vocabulary($vid) {
-  $vocabulary = taxonomy_get_vocabulary($vid);
-
-  $form['type'] = array('#type' => 'hidden', '#value' => 'vocabulary');
-  $form['vid'] = array('#type' => 'hidden', '#value' => $vid);
-  $form['name'] = array('#type' => 'hidden', '#value' => $vocabulary->name);
-  return confirm_form('vocabulary_confirm_delete', $form,
-                  t('Are you sure you want to delete the vocabulary %title?',
-                  array('%title' => theme('placeholder', $vocabulary->name))),
-                  'admin/taxonomy', t('Deleting a vocabulary will delete all the terms in it. This action cannot be undone.'),
-                  t('Delete'),
-                  t('Cancel'));
-}
-
 function taxonomy_form_term($edit = array()) {
   $vocabulary_id = isset($edit['vid']) ? $edit['vid'] : arg(4);
   $vocabulary = taxonomy_get_vocabulary($vocabulary_id);
@@ -327,7 +315,14 @@ function taxonomy_save_term(&$edit) {
   return $status;
 }
 
-function taxonomy_del_term($tid) {
+function taxonomy_del_term($tid, $vocab_did = NULL) {
+  static $count;
+  if ($vocab_did) {
+    $did = $vocab_did;
+  }
+  else {
+    $did = next_delete_id();
+  }
   $tids = array($tid);
   while ($tids) {
     $children_tids = $orphans = array();
@@ -344,37 +339,37 @@ function taxonomy_del_term($tid) {
       }
 
       $term = taxonomy_get_term($tid);
-
-      db_query('DELETE FROM {term_data} WHERE tid = %d', $tid);
-      db_query('DELETE FROM {term_hierarchy} WHERE tid = %d', $tid);
-      db_query('DELETE FROM {term_relation} WHERE tid1 = %d OR tid2 = %d', $tid, $tid);
-      db_query('DELETE FROM {term_synonym} WHERE tid = %d', $tid);
-      db_query('DELETE FROM {term_node} WHERE tid = %d', $tid);
-
+      if (!$recurse && !$vocab_did) {
+        $root_row = 'taxonomy term';
+        $preview = array('root term' => $term->name, 'description' => $term->description);
+        $recurse = 1;
+      }
+      else {
+        $count++;
+        $root_row = NULL;
+        $preview = array();
+        if ($term->name) {
+          $preview['term'. $count] = $term->name;
+        }
+        if ($term->description) {
+          $preview['description'. $count] = $term->description;
+        }
+      }
+      drupal_set_message(t('Moved term %name to trash.', array('%name' => theme('placeholder', $term->name))));
+      system_trash($did, $term->vid, $root_row, $preview, 'DELETE FROM {term_data} WHERE tid = %d', $tid);
+      system_trash($did, $term->vid, NULL, NULL, 'DELETE FROM {term_hierarchy} WHERE tid = %d', $tid);
+      system_trash($did, $term->vid, NULL, NULL, 'DELETE FROM {term_relation} WHERE tid1 = %d OR tid2 = %d', $tid, $tid);
+      system_trash($did, $term->vid, NULL, NULL, 'DELETE FROM {term_synonym} WHERE tid = %d', $tid);
+      system_trash($did, $term->vid, NULL, NULL, 'DELETE FROM {term_node} WHERE tid = %d', $tid);
+      $term->did = $did;
       module_invoke_all('taxonomy', 'delete', 'term', $term);
-      drupal_set_message(t('Deleted term %name.', array('%name' => theme('placeholder', $term->name))));
     }
 
     $tids = $orphans;
   }
-
   cache_clear_all();
 }
 
-function _taxonomy_confirm_del_term($tid) {
-  $term = taxonomy_get_term($tid);
-
-  $form['type'] = array('#type' => 'hidden', '#value' => 'term');
-  $form['tid'] = array('#type' => 'hidden', '#value' => $tid);
-  return confirm_form('term_confirm_delete', $form,
-                  t('Are you sure you want to delete the term %title?',
-                  array('%title' => theme('placeholder', $term->name))),
-                  'admin/taxonomy',
-                  t('Deleting a term will delete all its children if there are any. This action cannot be undone.'),
-                  t('Delete'),
-                  t('Cancel'));
-}
-
 /**
  * Generate a tabular listing of administrative functions for vocabularies.
  */
@@ -596,7 +591,7 @@ function taxonomy_node_validate(&$node) 
  * Save term associations for a given node.
  */
 function taxonomy_node_save($nid, $terms) {
-  taxonomy_node_delete($nid);
+  db_query('DELETE FROM {term_node} WHERE nid = %d', $nid);
 
   // Free tagging vocabularies do not send their tids in the form,
   // so we'll detect them here and process them independently.
@@ -657,13 +652,6 @@ function taxonomy_node_save($nid, $terms
 }
 
 /**
- * Remove associations of a node to its terms.
- */
-function taxonomy_node_delete($nid) {
-  db_query('DELETE FROM {term_node} WHERE nid = %d', $nid);
-}
-
-/**
  * Find all term objects related to a given term ID.
  */
 function taxonomy_get_related($tid, $key = 'tid') {
@@ -1044,7 +1032,7 @@ function taxonomy_nodeapi($node, $op, $a
       taxonomy_node_save($node->nid, $node->taxonomy);
       break;
     case 'delete':
-      taxonomy_node_delete($node->nid);
+      system_trash($node->did, $node->nid, NULL, NULL, 'DELETE FROM {term_node} WHERE nid = %d', $node->nid);
       break;
     case 'validate':
       taxonomy_node_validate($node);
@@ -1173,20 +1161,9 @@ function taxonomy_admin() {
       }
       break;
     case t('Delete'):
-      if (!$edit['confirm']) {
-        if (arg(3) == 'vocabulary') {
-          $output = _taxonomy_confirm_del_vocabulary($edit['vid']);
-        }
-        else {
-          $output = _taxonomy_confirm_del_term($edit['tid']);
-        }
-        break;
-      }
-      else {
-        $deleted_name = $edit['name'];
-        $edit['name'] = 0;
-        // fall through:
-      }
+      $deleted_name = $edit['name'];
+      $edit['name'] = 0;
+      // fall through:
     case t('Submit'):
       if (arg(3) == 'vocabulary') {
         switch (taxonomy_save_vocabulary($edit)) {
@@ -1197,7 +1174,7 @@ function taxonomy_admin() {
             drupal_set_message(t('Updated vocabulary %name.', array('%name' => theme('placeholder', $edit['name']))));
             break;
           case SAVED_DELETED:
-            drupal_set_message(t('Deleted vocabulary %name.', array('%name' => theme('placeholder', $deleted_name))));
+            drupal_set_message(t('Moved vocabulary %name to trash.', array('%name' => theme('placeholder', $deleted_name))));
             break;
         }
       }
Index: modules/upload.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/upload.module,v
retrieving revision 1.57
diff -u -F^function -r1.57 upload.module
--- modules/upload.module	1 Nov 2005 10:17:34 -0000	1.57
+++ modules/upload.module	7 Nov 2005 18:01:16 -0000
@@ -301,7 +301,12 @@ function upload_nodeapi(&$node, $op, $ar
       break;
 
     case 'delete':
-      upload_delete($node);
+      $file_info = upload_load($node);
+      foreach ($file_info as $file) {
+        $i++;
+        $preview['file'. $i] = $file->filename;
+      }
+      system_trash($node->did, $node->nid, NULL, $preview, "DELETE FROM {files} WHERE nid = %d", $node->nid);
       break;
     case 'search result':
       return $node->files ? format_plural(count($node->files), '1 attachment', '%count attachments') : null;
@@ -392,14 +397,6 @@ function upload_save($node) {
   return;
 }
 
-function upload_delete($node) {
-  $node->files = upload_load($node);
-  foreach ($node->files as $file) {
-    file_delete($file->filepath);
-  }
-  db_query("DELETE FROM {files} WHERE nid = %d", $node->nid);
-}
-
 function upload_form($node) {
   drupal_add_js('misc/progress.js');
   drupal_add_js('misc/upload.js');
@@ -524,3 +521,35 @@ function upload_js() {
   print drupal_call_js('window.parent.iframeHandler', $output);
   exit;
 }
+
+function upload_system_trash($did, $rid, $root_row) {
+  // Store file info in case of later permanent deletion
+  if ($root_row == 'node') {
+    $node = node_load($rid);
+    $file_info = upload_load($node);
+    $files = array();
+    foreach ($file_info as $file) {
+      $filepaths[] = $file->filepath;
+    }
+    $recover['files'] = $filepaths;
+    return $recover;
+  }
+}
+
+function upload_system_trash_delete($did) {
+  // Grab all node deletions and delete associated files
+  if ($did == 'all') {
+    $result = db_query("SELECT * FROM {deleted} WHERE root_row = 'node'");
+  }
+  else {
+    $result = db_query("SELECT * FROM {deleted} WHERE did = %d AND root_row = 'node'", $did);
+  }
+  while ($node = db_fetch_object($result)) {
+    $data = unserialize($node->data);
+    if ($data['files']) {
+      foreach ($data['files'] as $filepath) {
+        file_delete($filepath);
+      }
+    }
+  }
+}
Index: modules/user.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/user.module,v
retrieving revision 1.526
diff -u -F^function -r1.526 user.module
--- modules/user.module	1 Nov 2005 10:17:34 -0000	1.526
+++ modules/user.module	7 Nov 2005 18:01:18 -0000
@@ -1257,18 +1257,16 @@ function user_edit($category = 'account'
     }
   }
   else if (arg(2) == 'delete') {
-    if ($edit['confirm']) {
-      db_query('DELETE FROM {users} WHERE uid = %d', $account->uid);
-      db_query('DELETE FROM {sessions} WHERE uid = %d', $account->uid);
-      db_query('DELETE FROM {users_roles} WHERE uid = %d', $account->uid);
-      db_query('DELETE FROM {authmap} WHERE uid = %d', $account->uid);
-      drupal_set_message(t('The account has been deleted.'));
-      module_invoke_all('user', 'delete', $edit, $account);
-      drupal_goto('admin/user');
-    }
-    else {
-      return confirm_form('user_confirm_delete', $form, t('Are you sure you want to delete the account %name?', array('%name' => theme('placeholder', $account->name))), 'user/'. $account->uid, t('Deleting a user will remove all their submissions as well. This action cannot be undone.'), t('Delete'));
-    }
+    $did = next_delete_id();
+    $preview = array('name' => $account->name, 'email' => $account->mail);
+    system_trash($did, $account->uid, 'user', $preview, 'DELETE FROM {users} WHERE uid = %d', $account->uid);
+    db_query('DELETE FROM {sessions} WHERE uid = %d', $account->uid);
+    drupal_set_message(t('The account has been moved to trash.'));
+    system_trash($did, $account->uid, NULL, NULL, 'DELETE FROM {users_roles} WHERE uid = %d', $account->uid);
+    system_trash($did, $account->uid, NULL, NULL, 'DELETE FROM {authmap} WHERE uid = %d', $account->uid);
+    $account->did = $did;
+    module_invoke_all('user', 'delete', $edit, $account);
+    drupal_goto('admin/user');
   }
   else if ($_POST['op'] == t('Delete')) {
     // Note: we redirect from user/uid/edit to user/uid/delete to make the tabs disappear.
@@ -1458,21 +1456,10 @@ function user_admin_access_add($mask = N
 function user_admin_access_delete($aid = 0) {
   $access_types = array('user' => t('username'), 'mail' => t('e-mail'));
   $edit = db_fetch_object(db_query('SELECT aid, type, status, mask FROM {access} WHERE aid = %d', $aid));
-
-  $form = array();
-  $form['aid'] = array('#type' => 'hidden', '#value' => $aid);
-  $output = confirm_form('user_admin_access_delete_confirm', $form,
-                  t('Are you sure you want to delete the %type rule for %rule?', array('%type' => $access_types[$edit->type], '%rule' => theme('placeholder', $edit->mask))),
-                  'admin/access/rules',
-                  t('This action cannot be undone.'),
-                  t('Delete'),
-                  t('Cancel'));
-  return $output;
-}
-
-function user_admin_access_delete_confirm_execute($form_id, $edit) {
-  db_query('DELETE FROM {access} WHERE aid = %d', $edit['aid']);
+  $did = next_delete_id();
+  $preview = array('type' => $access_types[$edit->type], 'rule' => $edit->mask);
   drupal_set_message(t('The access rule has been deleted.'));
+  system_trash($did, $aid, 'access rule', $preview, 'DELETE FROM {access} WHERE aid = %d', $aid);
   drupal_goto('admin/access/rules');
 }
 
@@ -1665,8 +1652,11 @@ function user_admin_role() {
     }
   }
   else if ($op == t('Delete role')) {
-    db_query('DELETE FROM {role} WHERE rid = %d', $id);
-    db_query('DELETE FROM {permission} WHERE rid = %d', $id);
+    $did = next_delete_id();
+    $preview = db_fetch_array(db_query('SELECT name FROM {role} WHERE rid = %d', $id));
+    drupal_set_message(t('The role has been moved to trash.  All users with only this role have been moved to the authenticated users pool.'));
+    system_trash($did, $id, 'role', $preview, 'DELETE FROM {role} WHERE rid = %d', $id);
+    system_trash($did, $id, NULL, NULL, 'DELETE FROM {permission} WHERE rid = %d', $id);
 
     // Update the users who have this role set:
     $result = db_query('SELECT DISTINCT(ur1.uid) FROM {users_roles} ur1 LEFT JOIN {users_roles} ur2 ON ur2.uid = ur1.uid WHERE ur1.rid = %d AND ur2.rid != ur1.rid', $id);
@@ -1677,13 +1667,12 @@ function user_admin_role() {
     }
 
     if ($uid) {
-      db_query('DELETE FROM {users_roles} WHERE rid = %d AND uid IN (%s)', $id, implode(', ', $uid));
+      system_trash($did, $id, NULL, NULL, 'DELETE FROM {users_roles} WHERE rid = %d AND uid IN (%s)', $id, implode(', ', $uid));
     }
 
     // Users with only the deleted role are put back in the authenticated users pool.
     db_query('UPDATE {users_roles} SET rid = %d WHERE rid = %d', _user_authenticated_id(), $id);
 
-    drupal_set_message(t('The role has been deleted.'));
     drupal_goto('admin/access/roles');
   }
   else if ($op == t('Add role')) {
