diff --git a/book_copy.module b/book_copy.module
index 4c109392c297265cd5e1f02a40cdc0b7ba115d8d..15f35b1e5dffdb5fe893753527977e81b0d9f632 100644
--- a/book_copy.module
+++ b/book_copy.module
@@ -1,11 +1,11 @@
 <?php
-// @file
+
 
 /**
-* implementation of hook_perm
+* implementation of hook_permission
 */
-function book_copy_perm() {
-  return array('copy books', 'view book history');
+function book_copy_permission() {
+  return array('copy books' => array( 'title' => t('Copy a whole book') ), 'view book history' => array('title' => t('view book history')));
 }
 
 /**
@@ -14,19 +14,17 @@ function book_copy_perm() {
 function book_copy_menu() {
   $items['book_copy/copy/%node'] = array(
     'title' => 'Clone a book',
-    'page callback' => 'book_copy_batch_copy',
+    'page callback' => 'book_copy_copy_book',
     'page arguments' => array(2),
-    'access callback' => 'book_copy_can_copy',
-    'access arguments' => array(2),
+    'access arguments' => array('copy books'),
     'type' => MENU_CALLBACK,
   );
   
   $items['book_copy/copy/%node/%node'] = array(
     'title' => 'Clone a book',
-    'page callback' => 'book_copy_batch_copy',
+    'page callback' => 'book_copy_copy_book',
     'page arguments' => array(2, 3),
-    'access callback' => 'book_copy_can_copy',
-    'access arguments' => array(2, 3),
+    'access arguments' => array('copy books'),
     'type' => MENU_CALLBACK,
   );
   
@@ -37,245 +35,144 @@ function book_copy_menu() {
     'access arguments' => array('view book history'),
     'type' => MENU_CALLBACK,
   );
-
-  $items['book_copy/explain/%node'] = array(
-    'title' => 'Book Copy Status',
-    'page callback' => 'book_copy_explain',
-    'page arguments' => array(2,3),
-    'access arguments' => array('copy books'),
-    'type' => MENU_CALLBACK,
-  );
   
   return $items;
 }
 
 /**
- * Implementatin of hook_link()
+ * Implementatin of hook_node_view()
  */
-function book_copy_link($type, $node = NULL, $teaser = FALSE) {
+function book_copy_node_view( $node, $view_mode ){
   global $user;
   $links = array();
   
-  if ($type == 'node' && isset($node->book) && !$teaser) {
+  if (isset($node->book) && $view_mode != 'teaser') {
     if (user_access('view book history')) {
       $links['book_copy_history'] = array(
         'title' => t('Show Book History'),
         'href' => 'book_copy/history/'. $node->book['bid'],
-      );
+      );        
     }
     
     if (user_access('copy books')) {
-      if (book_copy_can_copy($node->book['bid'])) {
-        $links['book_copy_copy'] = array(
-          'title' => t('Derive a Copy'),
-          'href' => 'book_copy/copy/'. $node->book['bid'],
-        );
-      }
-      elseif(variable_get('book_copy_always_display_copy_links', TRUE)) {
-        $links['book_copy_copy'] = array(
-          'title' => t('Derive a Copy'),
-          'href' => 'book_copy/explain/'. $node->book['bid'],
-        );
-      }
-
-      if ($node->book['bid'] != $node->nid && book_copy_can_copy($node->book['bid'], $node->nid)) {
+      $links['book_copy_copy'] = array(
+        'title' => t('Derive a Copy'),
+        'href' => 'book_copy/copy/'. $node->book['bid'],
+      );
+      
+      if ($node->book['bid'] != $node->nid) {
         $links['book_copy_subtree'] = array(
           'title' => t('Copy subtree'),
           'href' => 'book_copy/copy/'. $node->book['bid'] .'/'. $node->nid,
         );
       }
-      elseif (variable_get('book_copy_always_display_copy_links', TRUE)) {
-        $links['book_copy_subtree'] = array(
-          'title' => t('Copy subtree'),
-          'href' => 'book_copy/explain/'. $node->book['bid'] .'/'. $node->nid,
-        );
-      }
     }
     
+    $node->content['links']['book'] = array(
+        '#links' => $links,
+    );
+    
   }
-  return $links;
+  return $node;
 }
 
 /**
- * This function is intended to be called via drupals batch processing system and
- * will clone an entire or partial book.
- * @param object $book The book from which we are cloning content
- * @param int $subtree The nid to start cloning from if 0 all book pages will be copied
- *        if non-zero then only those nodes under the given nid in the tree hierarchy will
- *        be copied
- * @param array $context used to maintain state via batch code
+ * This function is responsible for cloning an entire book
+ * This will also maintain book hieararchy in the new book.
+ *
+ * if 
 */
-function book_copy_copy_book($book, $subtree = 0, &$context) {
+function book_copy_copy_book($book, $subtree = 0) {
+  $newbid = 0;
   if (isset($book->book)) {
     $bid = $book->book['bid'];
-    $book = node_load(array('nid' => $bid));
-
-    module_load_include('inc', 'clone', 'clone.pages');
-
-    if (!isset($context['sandbox']['progress'])) {
-      $nodes = book_copy_find_subtree($bid, $subtree);
-
-      $context['sandbox']['newbid'] = 0;
-      $context['sandbox']['max'] = count($nodes);
-      $context['sandbox']['nodes'] = $nodes;
-      $context['sandbox']['progress'] = 0;
-      $context['sandbox']['finished'] = 0;
-      $context['sandbox']['mlinks'] = array();
-      $context['sandbox']['nidmap'] = array();
-      $context['sandbox']['mlidmap'] = array();
+    // dp6: $book = node_load(array('nid' => $bid));
+    // dp7: node_load($nid = NULL, $vid = NULL, $reset = FALSE) -> no more arrays!
+    $book = node_load($bid);
+    //dpm($book);
+    if ($subtree !== 0) {
+      // only grab those nodes matching our sub-tree
+      $mlid_res = db_query("SELECT ml.mlid FROM {menu_links} ml LEFT JOIN {book} b ON b.mlid = ml.mlid WHERE b.nid = %d", array('subtree->nid' => $subtree->nid));
+      $mlid = $mlid_res->fetchAll();
+      $where = 'AND (ml.plid = %d OR ml.p1 = %d OR ml.p2 = %d OR ml.p3 = %d OR ml.p4 = %d OR ml.p5 = %d OR ml.p6 = %d OR ml.p7 = %d OR ml.p8 = %d OR ml.p9 = %d)';
+      $args = array_fill(0, 10, $mlid['mlid']);
+      array_unshift($args, $bid);
     }
-
-    if (!empty($context['sandbox']['nodes'])) {
-      while ($context['sandbox']['progress'] < $context['sandbox']['max']) {
-        $nid = $nodes[$context['sandbox']['progress']];
-        $sql = 'SELECT ml.* FROM {menu_links} ml LEFT JOIN {book} b ON b.mlid = ml.mlid WHERE b.bid = %d AND b.nid = %d';
-        $result = db_query($sql, $bid, $nid);
-        $row = db_fetch_array($result);
-        $plid = $row['plid'];
-        $mlid = $row['mlid'];
-        $context['sandbox']['progress']++;  
+    else {
+      $where = '';
+      $args = array(':bid'=>$bid);
+      //dpm($args);      
+    }
+    module_load_include('inc', 'clone', 'clone.pages');
+    $result = db_query("SELECT ml.menu_name, ml.mlid, ml.plid, ml.link_path, ml.router_path, ml.link_title, ml.module, b.nid
+    FROM {menu_links} ml LEFT JOIN {book} b ON b.mlid = ml.mlid WHERE b.bid = :bid ". $where ." ORDER BY ml.depth", $args);
+   
+    if ($result) {
+      $mlinks = array();
+      $nidmap = array();
+      $mlidmap = array();
+      $result = $result->fetchAllAssoc('nid');
+      // dpm($result);
+       
+      //while ($row = db_fetch_array($result))
+      //echo 'result: '.dpm($result).'<br/>'; 
+      foreach ($result as $row) {
+        $plid = $row->plid;
+        $mlid = $row->mlid;
 
         // copy each node keeping reference to new nid via old nid (this copies the old book structure)
-        $context['sandbox']['nidmap'][$nid] = clone_node_save($nid); // clone_node_save() returns the nid of the new node.
+        $nidmap[$row->nid] = clone_node_save($row->nid); // clone_node_save() returns the nid of the new node.
 
-        $node = node_load(array('nid' => $context['sandbox']['nidmap'][$nid]));
+        //$node = node_load(array('nid' => $nidmap[$row['nid']]));
+        $node = node_load($nidmap[$row->nid]);
+        $mlidmap[$mlid] = $node->book['mlid'];
 
-        $context['sandbox']['mlidmap'][$mlid] = $node->book['mlid'];
-
-        if ($context['sandbox']['newbid'] == 0) {
-          $context['sandbox']['newbid'] = $context['sandbox']['nidmap'][$nid];
-          $message = $row['link_title'];
+        if ($newbid == 0) {
+          $newbid = $nidmap[$row->nid];
+          $message = $row->link_title;
           // The function signature is: hook_book_copy_alter(&$node, $oldbid, $newbid);
-          drupal_alter("book_copy", $node, $bid, $context['sandbox']['newbid']);
-
-          // fix batch redirect, we didn't have the nid when batch_set() was called
-          $batch = &batch_get();
-          $data = book_copy_copy_redirection($context['sandbox']['newbid']);
-          $batch['redirect'] = $data['url'];
+          drupal_alter("book_copy", $node, $bid, $newbid);
         }
         
-        if ($subtree != 0 || $node->nid != $context['sandbox']['newbid']) {
+        if ($subtree != 0 || $node->nid != $newbid) {
           // we need to set the bid for this node;
-          $node->book['bid'] = $context['sandbox']['newbid'];
+          $node->book['bid'] = $newbid;
           node_save($node);
         }
 
         // fix lower level nested links
-        if (isset($context['sandbox']['mlidmap'][$plid])) {
-          $node->book['plid'] = $context['sandbox']['mlidmap'][$plid];
+        if (isset($mlidmap[$plid])) {
+          $node->book['plid'] = $mlidmap[$plid];
           menu_link_save($node->book);
         }
       }
-    }
-  }
-
-  if ($context['sandbox']['progress'] < $context['sandbox']['max']) {
-    $context['finished'] = $context['sandbox']['progress'] / $context['sandbox']['max'];
-  }
-  else if ($context['sandbox']['progress'] != 0) {
-    $context['finished'] = 1;
-  }
+    
+      // add book copy reference and node copy history
+      foreach ($nidmap as $snid => $nid) {
+        db_query('INSERT INTO {book_copy_history} (nid, bid, sbid, snid, copied) VALUES (:nid, :bid, :sbid, :snid, :copied)', array(':nid'=>$nid, ':bid'=>$newbid, ':sbid'=>$bid, ':snid'=>$snid, ':copied'=>time()));
+      }
 
-  if ($context['finished'] == 1) {
-    foreach ($context['sandbox']['nidmap'] as $snid => $nid) {
-      db_query('INSERT INTO {book_copy_history} (nid, bid, sbid, snid, copied) VALUES (%d, %d, %d, %d, %d)', $nid, $context['sandbox']['newbid'], $bid, $snid, time());
-    }
-  }
-}
+      //$book = node_load(array('nid' => $newbid));
+      $book = node_load($newbid);
+      $book->bookcopydata = array();
+      $message= $book->title ;
+      $book->bookcopydata['message'] = t('Successfully cloned "%message", now viewing copy.', array('%message' => $message));
+      if (_book_outline_access($book)) {
+        $book->bookcopydata['url'] = 'node/'. $newbid .'/outline';
+      }
+      else {
+        $book->bookcopydata['url'] = 'node/'. $newbid;
+      }
 
-/**
- * This function defines our batch book copy process and starts it
- * Error checking ensures that we have a valid book, and generates a warning if 
- * the user tries to copy a non book
- *
- * @param object $book a node representing the book we want to copy
- * @param int $subtree The nid to start cloning from if 0 all book pages will be copied
- *        if non-zero then only those nodes under the given nid in the tree hierarchy will
- *        be copied
-*/
-function book_copy_batch_copy($book, $subtree = 0) {
-  if (!empty($book->book['bid'])) {
-    return drupal_get_form('book_copy_confirm_copy', $book, $subtree);
-  }
-  else {
-    drupal_set_title(t('Error copying book'));
-    if (!empty($book->title)) {
-      drupal_set_message(t('%title is not a book', array('%title' => $book->title)), 'warning');
-      drupal_goto('node/'. $book->nid);
-    }
-    else {
-      drupal_set_message(t('Could not find book corresponding to nid: %nid', array('%nid' => $bid)), 'warning');
+      // The function signature is: hook_book_copy_goto_alter(&$data);
+      drupal_alter("book_copy_goto", $book);
+      drupal_set_message($book->bookcopydata['message']);
+      drupal_goto($book->bookcopydata['url']);  // requires user has 'administer book outline' or can access personal books
     }
   }
 }
 
 /**
- * Presents the user with a confirm dialog to avoid creating a mess of copied nodes.
- */
-function book_copy_confirm_copy(&$form_state, $book, $subtree = 0) {
-  if (!empty($subtree)) {
-    $path = 'node/' . $subtree->nid;
-  }
-  else {
-    $path = 'node/' . $book->nid;
-  }
-
-  $form['book'] = array(
-    '#type' => 'value',
-    '#value' => $book->nid,
-  );
-  
-  if (!empty($subtree)) {
-    $form['subtree'] = array(
-      '#type' => 'value', 
-      '#value' => $subtree->nid
-    ); 
-  }
-
-  $form = confirm_form($form, t('Are you sure you want to copy %title', array('%title' => $book->title)), 'node/'.$book->nid, '');
-
-  return $form;
-}
-
-/*
- *
- */
-function book_copy_confirm_copy_submit($form, &$form_state) {
-  $book = node_load(array('nid' => $form_state['values']['book']));
-  $subtree = $form_state['values']['subtree'];
-  $batch = array(
-    'title' => t('Copying %title', array('%title' => $book->title)),
-    'operations' => array(
-      array('book_copy_copy_book', array($book, $subtree))
-    ),
-  );
-  batch_set($batch);
-  batch_process();
-}
-
-/**
- * Given a bid/nid this function will generate any messages and the proper url the user should be 
- * redirected to
- * @param int $bid the book id to generate redirect & message for
-*/
-function book_copy_copy_redirection($bid) {
-  $book = node_load(array('nid' => $bid));
-  $book->bookcopydata = array();
-  $book->bookcopydata['message'] = t('Successfully cloned "%message", now viewing copy.', array('%message' => $message));
-  if (_book_outline_access($book)) {
-    $book->bookcopydata['url'] = 'node/'. $bid .'/outline';
-  }
-  else {
-    $book->bookcopydata['url'] = 'node/'. $bid;
-  }
-
-  // The function signature is: hook_book_copy_goto_alter(&$data);
-  drupal_alter("book_copy_goto", $book);
-
-  return $book->bookcopydata;
-}
-
-/**
  * Implementation of hook_clone_node_alter
 */
 function book_copy_clone_node_alter(&$node, $original_node, $method) {
@@ -291,11 +188,7 @@ function book_copy_clone_node_alter(&$node, $original_node, $method) {
   }
 }
 
-/**
- * Initial function to render a books copy history
- *
- * @param object $book a node representing the book to show history for
-*/
+
 function book_copy_show_history($book) {
   drupal_set_title(t('Book History: @title', array('@title' => $book->title)));
   $ssbid = _book_copy_initial_source($book->book['bid']);
@@ -305,12 +198,8 @@ function book_copy_show_history($book) {
   return $output;
 
 }
-
-/**
- * Function responsible for generating book history
- * @param array $tree formatted book hierarchy from _book_copy_get_book_history()
- * @param int $bid The nid of the book we are viewing history for
- */
+// nid => copied
+//    \=> children
 function _book_copy_render_tree($tree, $bid) {
   foreach ($tree as $nid => $info) {
     if ($nid == $bid) {
@@ -319,7 +208,7 @@ function _book_copy_render_tree($tree, $bid) {
     else {
       $class = '';
     }
-    $output .= '<li>';
+    $output = '<li>';
     $output .= '<span '. $class .'>';
     $node = node_load($nid);
     if ($node) {
@@ -348,11 +237,7 @@ function _book_copy_render_tree($tree, $bid) {
 }
 
 
-/**
- * This function calls the recursive _book_copy_tree() to build
- * book history data
- * @param int $bid the bookid to build book history for
-*/
+
 function _book_copy_get_book_history($bid) {
   $return[$bid] = array();
   $return[$bid]['copied'] = 0;
@@ -360,166 +245,28 @@ function _book_copy_get_book_history($bid) {
   return $return;
 }
 
-/**
- * Recursive function used to build tree information for a book
- * @param int $bid The nid to build tree information for
-*/
 function _book_copy_tree($bid) {
-  $result = db_query("SELECT * FROM {book_copy_history} WHERE sbid = %d", $bid);
+  //$result = db_query("SELECT * FROM {book_copy_history} WHERE sbid = %d", $bid);
+  $result = db_query("SELECT * FROM {book_copy_history} WHERE sbid = :bid", array(':bid'=>$bid));
   $children = array();
-  while ($row = db_fetch_array($result)) {
+  $result = $result->fetchAllAssoc('sbid');
+  foreach ($result as $row) {
 
-    $children[$row['bid']] = array('copied' => $row['copied'],
-                                   'children' => _book_copy_tree($row['bid']),
+    $children[$row->bid] = array('copied' => $row->copied,
+                                   'children' => _book_copy_tree($row->bid),
                               );
   }
 
   return $children;
 }
 
-/**
- * Recursive function to traverse up a book history tree to find the originating source 
- * of the book corresponding to $bid
- * @param int $bid The current bid to find source books for
-*/
 function _book_copy_initial_source($bid) {
-  $result = db_query("SELECT * FROM {book_copy_history} WHERE bid = %d", $bid);
+  //$result = db_query("SELECT * FROM {book_copy_history} WHERE bid = %d", $bid);
+  $result = db_query("SELECT * FROM {book_copy_history} WHERE bid = :bid", array(':bid'=>$bid));
   $parents = array();
-  while ($row = db_fetch_array($result)) {
-    return _book_copy_initial_source($row['sbid']);
+  $result = $result->fetchAllAssoc('bid');
+  foreach ($result as $row) {
+    return _book_copy_initial_source($row->sbid);
   }
   return $bid;
 }
-
-/**
- * Given a book id and an optional subtree (nid) this function returns a list of node ids
- * in book order that match the given criteria.
- */
-function book_copy_find_subtree($bid, $subtree = 0) {
-  $nodes = array();
-
-  if (!empty($subtree)) {
-    // only grab those nodes matching our sub-tree
-    $mlid = db_result(db_query("SELECT ml.mlid FROM {menu_links} ml LEFT JOIN {book} b ON b.mlid = ml.mlid WHERE b.nid = %d", $subtree));
-    $where = 'AND (ml.plid = %d OR ml.p1 = %d OR ml.p2 = %d OR ml.p3 = %d OR ml.p4 = %d OR ml.p5 = %d OR ml.p6 = %d OR ml.p7 = %d OR ml.p8 = %d OR ml.p9 = %d)';
-    $args = array_fill(0, 10, $mlid);
-    array_unshift($args, $bid);
-  }
-  else {
-    $where = '';
-    $args = array($bid);
-  }
-
-  $result = db_query("SELECT b.nid FROM {menu_links} ml LEFT JOIN {book} b ON b.mlid = ml.mlid WHERE b.bid = %d ". $where ." ORDER BY ml.depth, b.nid", $args);
-  while($nid = db_result($result)) {
-    $nodes[] = $nid;
-  }
-  return $nodes;
-}
-
-/**
- * Given a book id and an optional subtree (nid) this function determines if the user
- * can copy the given book.
- *
- * @param $bid the book nid in question
- * @param $subtree optional if non-zero then the subtree pertainind to the nid supplied
- *  will be checked
- * @param $data an optional array where results will be saved. This will track why a user
- *  may not be able to copy a book or book sub-tree.
- *
- * @return TRUE if the user can copy the book FALSE otherwise
- */
-function book_copy_can_copy($bid, $subtree = 0, &$data = array()) { 
-  if (is_object($bid)) {
-    $bid = $bid->book['bid'];
-  }
-  
-  if (is_object($subtree)) {
-    $subtree = $subtree->nid;
-  }
-  $nodes = book_copy_find_subtree($bid, $subtree);
-
-  $data = array();
-  $data['headers'] = array('node' => t('Book page'), 'filter' => t('Input format'), 'create' => t('Create node type'));
-  $can_copy = TRUE;
-  if (user_access('copy books')) {
-    if (!empty($nodes)) {
-      foreach($nodes as $nid) {
-        $node = node_load(array('nid' => $nid));
-        $data[$nid]['node'] = l($node->title, 'node/'.$nid);
-        if (!filter_access($node->format)) {
-          $can_copy = FALSE;
-          $data[$nid]['filter']['status'] = FALSE;
-          $data[$nid]['filter']['message'] = $node->format;
-        }
-        else {
-          $data[$nid]['filter']['status'] = TRUE;
-        }
-      
-        if (!node_access('create', $node->type)) {
-          $can_copy = FALSE;
-          $data[$nid]['create']['status'] = FALSE;
-          $data[$nid]['create']['message'] = $node->type;
-        }
-        else {
-          $data[$nid]['create']['status'] = TRUE;
-        }
-      }
-      return $can_copy;
-    }
-  }
-  else {
-    return FALSE;
-  }
-}
-
-function book_copy_explain($book, $subtree = 0)  {
-  $table = array();
-  $output = '';
-  if (book_copy_can_copy($book->book['bid'], $subtree, $data)) {
-    if ($subtree != 0) {
-      $output = t('You can copy this sub-section of the book.');
-    }
-    else {
-      $output = t('You can copy this book.');
-    }
-  }
-  else {
-    if ($subtree != 0) {
-      $output = t('You cannot copy this sub-section of the book. ');
-    }
-    else {
-      $output = t('You cannot copy this book. ');
-    }
-    $output .= t('In order to copy this book the following issue(s) must be addressed. Please contact your site administrator for help.');
-  }
-
-  $table['headers'] = $data['headers'];
-  unset($data['headers']);
-  $table['rows'] = array();
-  foreach($data as $nid => $column) {
-    $row = array();
-    $hide = TRUE;
-    foreach($table['headers'] as $key => $header) {
-      if ($column[$key]['status'] === FALSE) {
-        $row['data'][] = t('N(%message)', array('%message' => $column[$key]['message']));
-        $hide = FALSE;
-      }
-      elseif ($column[$key]['status'] === TRUE) {
-        $row['data'][] = t('Y');
-      }
-      else {
-        $row['data'][] = $column[$key];
-      }
-    }
-    if (!$hide) {
-      $table['rows'][] = $row;
-    }
-  }
-  
-  if (!empty($table['rows'])) {
-    $output .= theme_table($table['headers'], $table['rows']);
-  }
-
-  return $output;
-}
