diff -rupN view_unpublished/README.txt view_unpublished_new/README.txt
--- view_unpublished/README.txt	2008-08-12 01:47:25.000000000 +1000
+++ README.txt	2009-11-24 15:56:40.416237736 +1100
@@ -4,13 +4,26 @@ This module allows you to grant access f
 
 Usage:
 ------
-view_unpublished looks for two user access permissions: 
-*Use view_unpublished module
-*View unpublished (node type)
+view_unpublished looks for two user access permissions:
+* Use view_unpublished module
+* View unpublished (node type)
 
 After installing the module, navigate to your user access page and assign the appropriate permissions to the roles you wish to be able to view unpublished nodes. For each role that (now) has permissions to view unpublished nodes, assign the "use view_unpublished" permission to them as well.
 
+Revisions:
+----------
+If you want to have support for using revisions on unpublished nodes you must:
+* Enable the view unpublished revisions module (comes with this module)
+* Navigate to the user access page to set permissions for unpublished node revisions
+
+NOTE ON PERMISSIONS:
+- To view revisions for an unpublished node a user must have the view unpublished revisions permission as well as the 'view unpublished *node-type* content' permission for the node type thay are viewing.
+- To revert revisions for an unpublished node a user must have the revert unpublished revisions permission.
+- The user can edit revisions if they have the 'edit unpublished *node-type* content' permission for the node type thay are viewing.
+- The user can only delete revisions if they are the admin or have the 'administer nodes' permission - Just like with published nodes normally.
+
 Code Contributions:
 -------------------
 Brad Bowman/beeradb - Aten Design Group
 Domenic Santangelo/dsantangelo - WorkHabit
+(revisions) Reuben Turk/rooby - Agileware
diff -rupN view_unpublished/view_unpublished.install view_unpublished_new/view_unpublished.install
--- view_unpublished/view_unpublished.install	2008-08-12 01:47:25.000000000 +1000
+++ view_unpublished.install	2009-11-24 15:56:40.417237584 +1100
@@ -1,5 +1,10 @@
 <?php
+// $Id$
 
-function view_unpublished_install(){
-   db_query("UPDATE {system} SET weight = -1337 WHERE name = 'view_unpublished'");
-}
\ No newline at end of file
+/**
+ * Implementation of hook_install()
+ */
+function view_unpublished_install() {
+  // This needs to run before the node module to override the menu access
+  db_query("UPDATE {system} SET weight = -1337 WHERE name = 'view_unpublished'");
+}
diff -rupN view_unpublished/view_unpublished.module view_unpublished_new/view_unpublished.module
--- view_unpublished/view_unpublished.module	2009-08-31 04:49:39.000000000 +1000
+++ view_unpublished.module	2009-11-24 15:56:40.418237153 +1100
@@ -1,72 +1,122 @@
 <?php
+// $Id$
 
-/*
-* Build a permissions list for viewing unpublished nodes of all content types.
-* Also, provide a 'use view_unpublished module' permission which determines if this module
-* will even attempt to override the default node/nid path.
-*/
+/**
+ * Implementation of hook_perm()
+ * Build a permissions list for viewing unpublished nodes of all content types.
+ * Also, provide a 'use view_unpublished module' permission which determines if this module
+ * will even attempt to override the default node/nid path.
+ */
 function view_unpublished_perm() {
   $perms = array('use view_unpublished module', 'view all unpublished content', 'edit all unpublished content');
   $types = db_query("select type from {node_type}");
   $i = 0;
   while ($type = db_result($types, $i++)) {
-    $perms[] = 'view unpublished '. $type .' content';
-    $perms[] = 'edit unpublished '. $type .' content';
+    $perms[] = 'view unpublished ' . $type . ' content';
+    $perms[] = 'edit unpublished ' . $type . ' content';
   }
- 
+
   return $perms;
 }
 
-/*
-*  Selectively overrides the node/nid path to set access => true when a user has permission
-*  to view unpublished content
-*/
+/**
+ * Implementation of hook_menu()
+ * Selectively overrides the node/nid path to set access => true when a user has permission
+ * to view unpublished content
+ *
+ * This menu override handles overriding the access for revisions.
+ */
 function view_unpublished_menu($may_cache) {
   $items = array();
   if (!$may_cache) {
     if (is_numeric(arg(1)) && arg(0) == 'node' && user_access('use view_unpublished module') && !user_access('administer nodes')) {
-        $node = node_load(arg(1));
-        if ($node->status == 0 && (user_access('view unpublished '. $node->type .' content') || user_access('view all unpublished content'))) {
-          //print_r($node);
-          //die();
+      $node = node_load(arg(1));
+      if ($node->status == 0 && (user_access('view unpublished ' . $node->type . ' content') || user_access('view all unpublished content'))) {
+        //print_r($node);
+        //die();
+        $items[] = array(
+          'path' => 'node/' . arg(1),
+          'title' => t('View'),
+          'callback' => 'node_page_view',
+          'callback arguments' => array($node),
+          'type' => MENU_CALLBACK,
+          'access' => TRUE,
+        );
+      }
+      if ($node->status == 0 && (user_access('edit unpublished ' . $node->type . ' content') || user_access('edit all unpublished content'))) {
+        $items[] = array(
+          'path' => 'node/' . arg(1) . '/edit',
+          'title' => t('Edit'),
+          'callback' => 'node_page_edit',
+          'callback arguments' => array($node),
+          'access' => TRUE,
+          'weight' => 1,
+          'type' => MENU_LOCAL_TASK
+        );
+      }
+      // Revisions access (delete revisions is not available as that requires the administer node permission)
+      // Needs the view_unpublished_revisions module to work properly
+      if (module_exists('view_unpublished_revisions')) {
+        if ($node->status == 0 && (user_access('view unpublished ' . $node->type . ' content') || user_access('view all unpublished content')) && user_access('view unpublished revisions') && db_result(db_query('SELECT COUNT(vid) FROM {node_revisions} WHERE nid = %d', arg(1))) > 1) {
           $items[] = array(
-            'path' => 'node/'. arg(1), 
-            'title' => t('View'),
-            'callback' => 'node_page_view',
-            'callback arguments' => array($node),
-            'type' => MENU_CALLBACK,
-            'access' => true,
+            'path' => 'node/' . arg(1) . '/revisions',
+            'title' => t('Revisions'),
+            'callback' => 'view_unpublished_revisions_node_revisions',
+            'access' => TRUE,
+            'weight' => 2,
+            'type' => MENU_LOCAL_TASK,
           );
+          if (!is_null(arg(3))) {
+            $items[] = array(
+              'path' => 'node/' . arg(1) . '/revisions/' . arg(3) . '/revert',
+              'callback' => 'view_unpublished_revisions_node_revision_revert',
+              'callback arguments' => array(arg(1), arg(3)),
+              'access' => user_access('revert unpublished revisions'),
+              'type' => MENU_CALLBACK,
+            );
+          }
+
+          // If the revision moderation module is enabled we need to override its access controls too.
+          if (module_exists('revision_moderation')) {
+            // Callback to allow users to edit revisions.
+            $items[] = array(
+              'path' => 'node/' . arg(1) . '/revisions/' . arg(3) . '/edit',
+              'title' => t('Edit revision'),
+              'callback' => 'revision_moderation_edit',
+              'callback arguments' => array(arg(1), arg(3)),
+              'access' => (user_access('edit unpublished ' . $node->type . ' content') || user_access('edit all unpublished content')),
+              'type' => MENU_CALLBACK,
+            );
+            // Callback to allow users to publish revisions directly.
+            $items[] = array(
+              'path' => 'node/' . arg(1) . '/revisions/' . arg(3) . '/publish',
+              'title' => t('Make current revision'),
+              'callback' => 'drupal_get_form',
+              'callback arguments' => array('revision_moderation_publish_confirm', arg(1), arg(3)),
+              'access' => user_access('revert unpublished revisions'),
+              'type' => MENU_CALLBACK,
+            );
+          }
         }
-        if ($node->status == 0 && (user_access('edit unpublished '. $node->type .' content') || user_access('edit all unpublished content'))) {
-          $items[] = array('path' => 'node/'. arg(1) .'/edit', 
-            'title' => t('Edit'),
-            'callback' => 'node_page_edit',
-            'callback arguments' => array($node),
-            'access' => true,
-            'weight' => 1,
-            'type' => MENU_LOCAL_TASK
-          );
-        } 
+      }
     }
   }
- 
+
   return $items;
 }
 
-
-/*
-*  Implementation of hook_nodeapi
-*/
+/**
+ * Implementation of hook_nodeapi()
+ */
 function view_unpublished_nodeapi(&$node, $op, $a3 = NULL, $a4 = NULL) {
   switch ($op) {
     case 'update':
-     if (is_numeric(arg(1)) && arg(0) == 'node' && arg(2) == 'edit' && user_access('use view_unpublished module') && !user_access('administer nodes')) {
-       // If node successfully edited, then go to node view: http://drupal.org/node/301221
-       if ($node->status == 0 && (user_access('view unpublished '. $node->type .' content') || user_access('view all unpublished content'))) {
-         drupal_goto("node/$node->nid");
+      if (is_numeric(arg(1)) && arg(0) == 'node' && arg(2) == 'edit' && user_access('use view_unpublished module') && !user_access('administer nodes')) {
+        // If node successfully edited, then go to node view: http://drupal.org/node/301221
+        if ($node->status == 0 && (user_access('view unpublished ' . $node->type . ' content') || user_access('view all unpublished content'))) {
+          drupal_goto("node/$node->nid");
         }
-	 }
+      }
       break;
   }
 }
diff -rupN view_unpublished/view_unpublished_revisions/view_unpublished_revisions.info view_unpublished_new/view_unpublished_revisions/view_unpublished_revisions.info
--- view_unpublished/view_unpublished_revisions/view_unpublished_revisions.info	1970-01-01 10:00:00.000000000 +1000
+++ view_unpublished_revisions/view_unpublished_revisions.info	2009-11-24 15:56:40.418237153 +1100
@@ -0,0 +1,5 @@
+; $Id$
+name = View Unpublished Revisions
+description = Select which roles should be able to use revision management for unpublished content
+package = Permissions
+dependencies = view_unpublished
\ No newline at end of file
diff -rupN view_unpublished/view_unpublished_revisions/view_unpublished_revisions.install view_unpublished_new/view_unpublished_revisions/view_unpublished_revisions.install
--- view_unpublished/view_unpublished_revisions/view_unpublished_revisions.install	1970-01-01 10:00:00.000000000 +1000
+++ view_unpublished_revisions/view_unpublished_revisions.install	2009-11-24 16:03:11.460238721 +1100
@@ -0,0 +1,11 @@
+<?php
+// $Id$
+
+/**
+ * Implementation of hook_install()
+ */
+function view_unpublished_revisions_install() {
+  // This needs to run after other modules to override the menu callbacks
+  $max_weight = db_result(db_query("SELECT MAX(weight) FROM {system}"));
+  db_query("UPDATE {system} SET weight = %d WHERE name = 'view_unpublished_revisions'", $max_weight + 10);
+}
diff -rupN view_unpublished/view_unpublished_revisions/view_unpublished_revisions.module view_unpublished_new/view_unpublished_revisions/view_unpublished_revisions.module
--- view_unpublished/view_unpublished_revisions/view_unpublished_revisions.module	1970-01-01 10:00:00.000000000 +1000
+++ view_unpublished_revisions/view_unpublished_revisions.module	2009-11-24 15:56:40.420237129 +1100
@@ -0,0 +1,397 @@
+<?php
+// $Id$
+
+/**
+ * Implementation of hook_perm()
+ */
+function view_unpublished_revisions_perm() {
+  $perms[] = 'view unpublished revisions';
+  $perms[] = 'revert unpublished revisions';
+
+  return $perms;
+}
+
+/**
+ * Implementation of hook_menu()
+ * This has to be duplicated from the view_unpublished module because
+ * overriding a callback requires the module to run after the menu it is overriding
+ * and overriding access requires the module to run before the menu it is overriding
+ * So - Two modules with different weights to override both (annoying)
+ *
+ * This menu override handles overriding the callback.
+ */
+function view_unpublished_revisions_menu($may_cache) {
+  $items = array();
+  if (!$may_cache) {
+    if (is_numeric(arg(1)) && arg(0) == 'node' && user_access('use view_unpublished module') && !user_access('administer nodes')) {
+      $node = node_load(arg(1));
+      // Revisions access (delete revisions is not available as that requires the administer node permission)
+      if ($node->status == 0 && (user_access('view unpublished ' . $node->type . ' content') || user_access('view all unpublished content')) && user_access('view unpublished revisions') && db_result(db_query('SELECT COUNT(vid) FROM {node_revisions} WHERE nid = %d', arg(1))) > 1) {
+        // If the diff module is enabled honor it's overriding of the revisions page
+        $items[] = array(
+          'path' => 'node/' . arg(1) . '/revisions',
+          'title' => t('Revisions'),
+          'callback' => module_exists('diff') ? 'view_unpublished_revisions_diff_diffs' : 'view_unpublished_revisions_node_revisions',
+          'access' => TRUE,
+          'weight' => 2,
+          'type' => MENU_LOCAL_TASK,
+        );
+        if (!is_null(arg(3))) {
+          $revert_access = (user_access('revert unpublished revisions'));
+          $items[] = array(
+            'path' => 'node/' . arg(1) . '/revisions/' . arg(3) . '/revert',
+            'callback' => 'view_unpublished_revisions_node_revision_revert',
+            'callback arguments' => array(arg(1), arg(3)),
+            'access' => $revert_access,
+            'type' => MENU_CALLBACK,
+          );
+        }
+      }
+    }
+  }
+
+  return $items;
+}
+
+/**
+ * Overridden menu callback for revisions related activities on unpublished nodes.
+ * Original code taken from node_revisions() in node.module
+ */
+function view_unpublished_revisions_node_revisions() {
+  if (is_numeric(arg(1)) && arg(2) == 'revisions') {
+    $op = arg(4) ? arg(4) : 'overview';
+    switch ($op) {
+      case 'overview':
+        $node = node_load(arg(1));
+        if (user_access('view unpublished revisions') && (user_access('view unpublished ' . $node->type . ' content') || user_access('view all unpublished content'))) {
+          return view_unpublished_revisions_node_revision_overview($node);
+        }
+        drupal_access_denied();
+        return;
+      case 'view':
+        if (is_numeric(arg(3))) {
+          $node = node_load(arg(1), arg(3));
+          if ($node->nid) {
+            if (user_access('view unpublished revisions') && (user_access('view unpublished ' . $node->type . ' content') || user_access('view all unpublished content'))) {
+              drupal_set_title(t('Revision of %title from %date', array('%title' => $node->title, '%date' => format_date($node->revision_timestamp))));
+              return node_show($node, arg(2));
+            }
+            drupal_access_denied();
+            return;
+          }
+        }
+        break;
+    }
+  }
+  drupal_not_found();
+}
+
+/**
+ * Overridden revisions overview form for unpublished nodes.
+ * Original code taken from node_revision_overview() in node.module
+ * Generate an overview table of older revisions of a node.
+ */
+function view_unpublished_revisions_node_revision_overview($node) {
+  drupal_set_title(t('Revisions for %title', array('%title' => $node->title)));
+
+  $header = array(t('Revision'), array('data' => t('Operations'), 'colspan' => 2));
+
+  $revisions = node_revision_list($node);
+
+  $rows = array();
+  $revert_permission = FALSE;
+  if (user_access('revert unpublished revisions') || user_access('administer nodes')) {
+    $revert_permission = TRUE;
+  }
+  $delete_permission = FALSE;
+  if (user_access('administer nodes')) {
+    $delete_permission = TRUE;
+  }
+  foreach ($revisions as $revision) {
+    $row = array();
+    $operations = array();
+
+    if ($revision->current_vid > 0) {
+      $row[] = array('data' => t('!date by !username', array('!date' => l(format_date($revision->timestamp, 'small'), "node/$node->nid"), '!username' => theme('username', $revision)))
+                               . (($revision->log != '') ? '<p class="revision-log">'. filter_xss($revision->log) .'</p>' : ''),
+                     'class' => 'revision-current');
+      $operations[] = array('data' => theme('placeholder', t('current revision')), 'class' => 'revision-current', 'colspan' => 2);
+    }
+    else {
+      $row[] = t('!date by !username', array('!date' => l(format_date($revision->timestamp, 'small'), "node/$node->nid/revisions/$revision->vid/view"), '!username' => theme('username', $revision)))
+               . (($revision->log != '') ? '<p class="revision-log">'. filter_xss($revision->log) .'</p>' : '');
+      if ($revert_permission) {
+        $operations[] = l(t('revert'), "node/$node->nid/revisions/$revision->vid/revert");
+      }
+      if ($delete_permission) {
+        $operations[] = l(t('delete'), "node/$node->nid/revisions/$revision->vid/delete");
+      }
+    }
+    $rows[] = array_merge($row, $operations);
+  }
+
+  return theme('table', $header, $rows);
+}
+
+/**
+ * Overridden menu callback for diff related activities on unpublished nodes.
+ * Original code taken from diff_diffs() in diff.module
+ * If the diff module is enabled this function is the revisions callback
+ * instead of the view_unpublished_revisions_node_revisions function.
+ */
+function view_unpublished_revisions_diff_diffs() {
+  if (is_numeric(arg(1)) && arg(2) == 'revisions') {
+    $op = arg(3) ? arg(3) : 'overview';
+    switch ($op) {
+      case 'overview':
+        $node = node_load(arg(1));
+        if (user_access('view unpublished revisions') && (user_access('view unpublished ' . $node->type . ' content') || user_access('view all unpublished content'))) {
+          return view_unpublished_revisions_diff_diffs_overview($node);
+        }
+        drupal_access_denied();
+        return;
+
+      case 'view':
+        if (is_numeric(arg(4)) && is_numeric(arg(5))) {
+          $node = node_load(arg(1));
+          if ($node->nid) {
+            if (user_access('view unpublished revisions') && (user_access('view unpublished ' . $node->type . ' content') || user_access('view all unpublished content'))) {
+              drupal_set_title(t('Diff for %title', array('%title' => $node->title)));
+              return diff_diffs_show($node, arg(4), arg(5));
+            }
+            drupal_access_denied();
+            return;
+          }
+        }
+        break;
+
+      default:
+        // A view, revert or delete operation from the orignial node module,
+        // so call the override for the original node module's revisions function to handle this.
+        return view_unpublished_revisions_node_revisions();
+        break;
+    }
+  }
+  drupal_not_found();
+}
+
+/**
+ * Override of the diff_diffs_overview function for unpublished nodes.
+ * Generate an overview table of older revisions of a node and provide 
+ * an input form to select two revisions for a comparison.
+ */
+function view_unpublished_revisions_diff_diffs_overview(&$node) {
+  $output = '';
+
+  drupal_set_title(t('Revisions for %title', array('%title' => $node->title)));
+  $output .= drupal_get_form('view_unpublished_revisions_diff_node_revisions', $node);
+
+  return $output;
+}
+
+/**
+ * Override of the diff module's diff_node_revisions function for unpblished nodes.
+ * This is required for the revert/delete revisions links to work properly on unpublished nodes.
+ * - Preferrably a patch could be submitted to the diff module to take care of this in a better fashion.
+ *   That would then remove the need for this function and the view_unpublished_revisions_diff_diffs_overview function.
+ *   Or possibly the need for any special treatment for the diff module.
+ *
+ * Input form to select two revisions.
+ *
+ * @param $node
+ *   Node whose revisions are displayed for selection.
+ */
+function view_unpublished_revisions_diff_node_revisions(&$node) {
+  global $form_values;
+  $form = array();
+
+  $form['nid'] = array(
+    '#type' => 'hidden',
+    '#value' => $node->nid,
+  );
+
+  $revision_list = node_revision_list($node);
+
+  if (count($revision_list) > REVISION_LIST_SIZE) {
+    // If the list of revisions is longer than the number shown on one page split the array.
+    $page = isset($_GET['page']) ? $_GET['page'] : '0';
+    $revision_chunks = array_chunk(node_revision_list($node), REVISION_LIST_SIZE);
+    $revisions = $revision_chunks[$page];
+    // Set up global pager variables as would 'pager_query' do.
+    // These variables are then used in the theme('pager') call later.
+    global $pager_page_array, $pager_total, $pager_total_items;
+    $pager_total_items[0] = count($revision_list);
+    $pager_total[0] = ceil(count($revision_list) / REVISION_LIST_SIZE);
+    $pager_page_array[0] = max(0, min($page, ((int)$pager_total[0]) - 1));
+  } else {
+    $revisions = $revision_list;
+  }
+
+  $revert_permission = FALSE;
+  if (user_access('revert unpublished revisions') || user_access('administer nodes')) {
+    $revert_permission = TRUE;
+  }
+  $delete_permission = FALSE;
+  if (user_access('administer nodes')) {
+    $delete_permission = TRUE;
+  }
+
+  foreach ($revisions as $revision) {
+    $operations = array();
+    $revision_ids[$revision->vid] = '';
+
+    if ($revision->current_vid > 0) {
+      $form['info'][$revision->vid] = array(
+        '#value' => t('!date by !username', array(
+          '!date' => l(format_date($revision->timestamp, 'small'), "node/$node->nid"), 
+          '!username' => theme('username', $revision)))
+        . (($revision->log != '') ? '<p class="revision-log">'. filter_xss($revision->log) .'</p>' : ''),
+      );
+    }
+    else {
+      $form['info'][$revision->vid] = array(
+        '#value' => t('!date by !username', array(
+          '!date' => l(format_date($revision->timestamp, 'small'), "node/$node->nid/revisions/$revision->vid/view"), 
+          '!username' => theme('username', $revision)))
+        . (($revision->log != '') ? '<p class="revision-log">'. filter_xss($revision->log) .'</p>' : '')
+      );
+      if ($revert_permission) {
+        $operations[] = array('#value' => l(t('revert'), "node/$node->nid/revisions/$revision->vid/revert"));
+      }
+      if ($delete_permission) {
+        $operations[] = array('#value' => l(t('delete'), "node/$node->nid/revisions/$revision->vid/delete"));
+      }
+      // Set a dummy, even if the user has no permission for the other
+      // operations, so that we can check if the operations array is
+      // empty to know if the row denotes the current revision.
+      $operations[] = array();
+    }
+    $form['operations'][$revision->vid] = $operations;
+
+  }
+  $new_vid = key($revision_ids);
+  next($revision_ids);
+  $old_vid = key($revision_ids);
+  $form['diff']['old'] = array(
+    '#type' => 'radios', 
+    '#options' => $revision_ids,
+    '#default_value' => $old_vid
+  );
+  $form['diff']['new'] = array(
+    '#type' => 'radios', 
+    '#options' => $revision_ids,
+    '#default_value' => $new_vid
+  );
+  $form['submit'] = array('#type' => 'submit', '#value' => t('Show diff'));  
+
+  if (count($revision_list) > REVISION_LIST_SIZE) {
+    $form['#suffix'] = theme('pager', NULL, REVISION_LIST_SIZE, 0);
+  }
+
+  return $form;
+}
+
+/**
+ * Theme function to display the revisions formular with means to select
+ * two revisions.
+ */
+function theme_view_unpublished_revisions_diff_node_revisions($form) {
+  // Overview table:
+  $header = array(
+    t('Revision'),
+    array('data' => drupal_render($form['submit']), 'colspan' => 2),
+    array('data' => t('Operations'), 'colspan' => 2)
+  );
+  if (isset($form['info']) && is_array($form['info'])) {
+    foreach (element_children($form['info']) as $key) {
+      $row = array();
+      if (isset($form['operations'][$key][0])) {
+        // Note: even if the commands for revert and delete are not permitted,
+        // the array is not empty since we set a dummy in this case.
+        $row[] = drupal_render($form['info'][$key]);
+        $row[] = drupal_render($form['diff']['old'][$key]);
+        $row[] = drupal_render($form['diff']['new'][$key]);
+        $row[] = drupal_render($form['operations'][$key][0]);
+        $row[] = drupal_render($form['operations'][$key][1]);
+        $rows[] = $row;
+      }
+      else {
+        // its the current revision (no commands to revert or delete)
+        $row[] = array('data' => drupal_render($form['info'][$key]), 'class' => 'revision-current');
+        $row[] = array('data' => drupal_render($form['diff']['old'][$key]), 'class' => 'revision-current');
+        $row[] = array('data' => drupal_render($form['diff']['new'][$key]), 'class' => 'revision-current');
+        $row[] = array('data' => theme('placeholder', t('current revision')), 'class' => 'revision-current', 'colspan' => '2');
+        $rows[] = array(
+          'data' => $row,
+          'class' => 'error',
+        );
+      }
+    }
+  }
+  $output .= theme('table', $header, $rows);
+  $output .= drupal_render($form);
+  return $output;
+}
+
+/**
+ * Overridden node_revision_revert() for unpublished nodes.
+ * Original code taken from node_revision_revert() in node.module
+ *
+ * Revert to the revision with the specified revision number. A node and nodeapi "update" event is triggered
+ * (via the node_save() call) when a revision is reverted.
+ */
+function view_unpublished_revisions_node_revision_revert($nid, $revision) {
+  global $user;
+
+  $node = node_load($nid, $revision);
+  if (user_access('revert unpublished revisions')) {
+    if ($node->vid) {
+      return drupal_get_form('node_revision_revert_confirm', $node);
+    }
+    else {
+      drupal_set_message(t('You tried to revert to an invalid revision.'), 'error');
+    }
+    drupal_goto('node/' . $nid . '/revisions');
+  }
+  drupal_access_denied();
+}
+
+/**
+ * Implementation of hook_nodeapi().
+ * This is used to override the access controls on the revision links
+ * that are created by the revision_moderation module.
+ */
+function view_unpublished_revisions_nodeapi(&$node, $op, $teaser = NULL, $page = NULL) {
+  switch ($op) {
+    case 'view':
+      if (module_exists('revision_moderation') && !$node->status) {
+        // Remove any existing links that might have been put in by the revision moderation module
+        foreach (drupal_get_messages('status') as $key => $message) {
+          if (strpos($message, 'You are currently viewing a revision of this post created on') === 0) {
+            unset($_SESSION['messages']['status'][$key]);
+          }
+        }
+        // Display more descriptive message at the top of node revision views, including operations
+        // that the current user has available to them.
+        $current_vid = db_result(db_query('SELECT vid FROM {node} WHERE nid = %d', $node->nid));
+        if ($node->vid != $current_vid) {
+          // Set up an array of links to show along with the message.
+          $links = array();
+          if (user_access('edit unpublished ' . $node->type . ' content') || user_access('edit all unpublished content')) {
+            $links[] = l(t('Edit revision'), "node/$node->nid/revisions/$node->vid/edit");
+          }
+          if ((user_access('revert unpublished revisions') || user_access('administer nodes'))) {
+            $links[] = l(t('Make current revision'), "node/$node->nid/revisions/$node->vid/publish");
+          }
+          if (user_access('administer nodes') && node_access('delete', $node)) {
+           $links[] = l(t('Delete revision'), "node/$node->nid/revisions/$node->vid/delete");
+          }
+          // Get the revision author information for the message.
+          $revision_uid = db_result(db_query('SELECT uid FROM {node_revisions} WHERE vid = %d', $node->vid));
+          $revision_author = user_load(array('uid' => $revision_uid));
+          drupal_set_message(t('You are currently viewing a revision of this post created on @date by !author.', array('@date' => format_date($node->revision_timestamp, 'small'), '!author' => theme('username', $revision_author))) . theme('item_list', $links));
+        }
+      }
+      break;
+  }
+}
