Index: pm_block_user/pm_block_user.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/privatemsg/pm_block_user/pm_block_user.module,v
retrieving revision 1.1.2.4
diff -u -r1.1.2.4 pm_block_user.module
--- pm_block_user/pm_block_user.module	16 Apr 2009 19:03:44 -0000	1.1.2.4
+++ pm_block_user/pm_block_user.module	28 May 2009 16:48:32 -0000
@@ -103,7 +103,7 @@
   return $blocked;
 }
 
-function pm_block_user_privatemsg_sql_load_alter(&$fragments, $pmid, $uid) {
+function pm_block_user_privatemsg_sql_load_alter(&$fragments, $pmid) {
   $fragments['select'][] = 'pmbu.recipient AS is_blocked';
   $fragments['select'][] = 'pmi.thread_id';
 
Index: privatemsg.api.php
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/privatemsg/Attic/privatemsg.api.php,v
retrieving revision 1.1.2.3
diff -u -r1.1.2.3 privatemsg.api.php
--- privatemsg.api.php	21 Apr 2009 21:10:56 -0000	1.1.2.3
+++ privatemsg.api.php	28 May 2009 16:48:32 -0000
@@ -149,29 +149,16 @@
 function hook_privatemsg_sql_list_alter(&$fragment, $account) {
 
 }
-/**
- * Display a list of sent messages.
- *
- * @param $fragments
- *   Query fragments
- * @param $account
- *   User object
- */
-function hook_privatemsg_sql_list_sent_alter(&$fragment, $account) {
-
-}
 
 /**
- * Load a single message.
+ * Query definition to load a message.
  *
  * @param $fragments
  *   Query fragments
  * @param $pmid
  *   message id, pm.mid
- * @param $account
- *   User object
  */
-function hook_privatemsg_sql_load_alter(&$fragment, $pmid, $account) {
+function hook_privatemsg_sql_load_alter(&$fragment, $pmid) {
 
 }
 /**
Index: privatemsg.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/privatemsg/privatemsg.module,v
retrieving revision 1.70.2.30.2.91.2.44
diff -u -r1.70.2.30.2.91.2.44 privatemsg.module
--- privatemsg.module	26 Apr 2009 22:16:08 -0000	1.70.2.30.2.91.2.44
+++ privatemsg.module	28 May 2009 16:52:03 -0000
@@ -179,6 +179,15 @@
     'access arguments' => array('read privatemsg'),
     'type'             => MENU_CALLBACK,
   );
+  $items['user/%/messages'] = array(
+    'title' => 'Messages',
+    'page callback'    => 'drupal_get_form',
+    'page arguments'   => array('privatemsg_list', 'list', 1),
+    'access callback'  => 'privatemsg_user_tab_access',
+    'access arguments' => array(1),
+    'type' => MENU_LOCAL_TASK,
+  );
+
   return $items;
 }
 
@@ -209,6 +218,31 @@
   return TRUE;
 }
 
+/**
+ * Function to check if a user can access the messages tab on a user page.
+ *
+ * @param $uid
+ *   the user's id for whom the permission is being checked.
+ */
+function privatemsg_user_tab_access($uid) {
+  global $user;
+  $account = $user;
+  
+  // Disallow anonymous access, regardless of permissions.
+  if (!$account->uid) {
+    return FALSE;
+  }
+  // If a user is viewing own account, allow access.
+  if ($account->uid == $uid && privatemsg_user_access('read privatemsg', $account)) {
+    return TRUE;
+  }
+  // If a user has permission to view other user's messages, then allow access.
+  if (privatemsg_user_access('read all private messages', $account)) {
+    return TRUE;
+  }
+  return FALSE;
+}
+
 
 /**
  * Check access to the view messages page.
@@ -256,11 +290,24 @@
       global $user;
       $account = drupal_clone($user);
     }
+    // Load the list of participants.
+    $query = _privatemsg_assemble_query('participants', $thread_id);
+    $participants = db_query($query['query']);
+    while ($result = db_fetch_array($participants)) {
+      $thread['participants'][$result['uid']] = user_load($result['uid']);
+    }
+    $read_all = FALSE;
+    if (!array_key_exists($account->uid, $thread['participants']) && privatemsg_user_access('read all private messages', $account)) {
+      // User has permission to read all messages AND is not a participant of the current thread.
+      drupal_set_message(t('This conversation is being viewed with escalated priviledges and may not be the same as shown to normal users.'));
+      $read_all = TRUE;
+    }
+
     // load messages returned by the messages query with _privatemsg_load().
-    $query = _privatemsg_assemble_query('messages', array($thread_id), $account);
+    $query = _privatemsg_assemble_query('messages', array($thread_id), $account, FALSE, $read_all);
     $conversation = db_query($query['query']);
     while ($result = db_fetch_array($conversation)) {
-      if ($message = _privatemsg_load($result['mid'], $account)) {
+      if ($message = _privatemsg_load($result['mid'])) {
         $thread['messages'][$result['mid']] = $message;
       }
     }
@@ -274,12 +321,6 @@
     $message = current($thread['messages']);
     $thread['subject'] = $message['subject'];
 
-    // Load the list of participants.
-    $query = _privatemsg_assemble_query('participants', $thread_id);
-    $participants = db_query($query['query']);
-    while ($result = db_fetch_array($participants)) {
-      $thread['participants'][$result['uid']] = user_load($result['uid']);
-    }
     return $thread;
   }
   return FALSE;
@@ -793,11 +834,15 @@
  */
 
 /**
- * Query function for load.
+ * Query definition to load a message.
+ *
+ * @param $fragments
+ *   Query fragments array.
+ * @param $pmid
+ *   the id of the message.
  */
-function privatemsg_sql_load(&$fragments, $pmid, $account) {
-//  drupal_set_message('<pre>'. print_r(func_get_args(), 1) . '</pre>');
-  $fragments['primary_table'] = '{pm_message} pm'; // Our primary table
+function privatemsg_sql_load(&$fragments, $pmid) {
+  $fragments['primary_table'] = '{pm_message} pm';
 
   $fragments['select'][]      = "pm.mid";
   $fragments['select'][]      = "pm.author";
@@ -809,29 +854,34 @@
   $fragments['inner_join'][]  = 'INNER JOIN {pm_index} pmi ON pm.mid = pmi.mid';
   $fragments['where'][]       = 'pmi.mid = %d';
   $fragments['query_args']['where'][]  = $pmid;
-  $fragments['where'][]       = 'pmi.uid = %d';
-  $fragments['query_args']['where'][]  = $account->uid;
 }
+
 /**
  * Query definition to load messages of one or multiple threads.
  *
  * @param $fragments
- *  Query fragments array.
+ *   Query fragments array.
  * @param $threads
- *  Array with one or multiple thread id's.
+ *   Array with one or multiple thread id's.
  * @param $account
- *  User object for which the messages are being loaded.
+ *   User object for which the messages are being loaded.
  * @param $load_all
- *  Deleted messages are only loaded if this is set to TRUE.
+ *   Deleted messages are only loaded if this is set to TRUE.
+ * @param $read_all
+ *   Messages are not filtered to the user if this is set to TRUE.
  */
-function privatemsg_sql_messages(&$fragments, $threads, $account, $load_all = FALSE) {
+function privatemsg_sql_messages(&$fragments, $threads, $account, $load_all = FALSE, $read_all = FALSE) {
   $fragments['primary_table'] = '{pm_index} pmi';
 
   $fragments['select'][]      = 'DISTINCT(pmi.mid) as mid';
   $fragments['where'][]       = 'pmi.thread_id IN ('. db_placeholders($threads) .')';
   $fragments['query_args']['where']   += $threads;
-  $fragments['where'][]       = 'pmi.uid = %d';
-  $fragments['query_args']['where'][]  = $account->uid;
+
+  if (!$read_all) {
+    // Only load the user's messages.
+    $fragments['where'][]     = 'pmi.uid = %d';
+    $fragments['query_args']['where'][]  = $account->uid;
+  }
   if (!$load_all) {
     $fragments['where'][]       = 'pmi.deleted = 0';
   }
@@ -1065,14 +1115,21 @@
 }
 
 function privatemsg_delete($form_state, $pmid) {
-  global $user;
 
   $form['pmid'] = array(
     '#type' => 'value',
     '#value' => $pmid,
   );
+  if (privatemsg_user_access('read all private messages')) {
+    $form['delete_options'] = array(
+      '#type' => 'checkbox',
+      '#title' => 'Delete this message for all users?',
+      '#description' => 'Tick the box to delete the message for all users.',
+      '#default_value' => FALSE,
+    );
+  }
   return confirm_form($form,
-    t('Are you sure you want to delete'),
+    t('Are you sure you want to delete this message?'),
     isset($_GET['destination']) ? $_GET['destination'] : 'messages/view/'. $pmid,
     t('This action cannot be undone.'),
     t('Delete'),
@@ -1080,6 +1137,23 @@
   );
 }
 
+function privatemsg_delete_submit($form, &$form_state) {
+  global $user;
+  $account = drupal_clone($user);
+  
+  if ($form_state['values']['confirm']) {
+    if ($form_state['values']['delete_options']) {
+      privatemsg_message_change_delete($form_state['values']['pmid'], 1);
+      drupal_set_message(t('Message has been deleted for all users'));
+    }
+    else {
+      privatemsg_message_change_delete($form_state['values']['pmid'], 1, $account);
+      drupal_set_message(t('Message has been deleted'));
+    }
+  }
+  $form_state['redirect'] = 'messages';
+}
+
 /**
  * Delete or restore a message.
  *
@@ -1088,18 +1162,20 @@
  * @param $delete
  *   Either deletes or restores the thread (1 => delete, 0 => restore)
  * @param $account
- *   User acccount for which the message should be deleted.
+ *   User acccount for which the delete action should be carried out - Set to NULL to delete for all users.
  *
  * @ingroup api
  */
 function privatemsg_message_change_delete($pmid, $delete, $account = NULL) {
-  if (is_null($account)) {
-    global $user;
-    $account = drupal_clone($user);
-  }
-  $message = _privatemsg_load($pmid, $account);
+  $message = _privatemsg_load($pmid);
 
-  db_query('UPDATE {pm_index} SET deleted = %d WHERE mid = %d AND uid = %d', $delete, $pmid, $account->uid);
+  if ($account){
+    db_query('UPDATE {pm_index} SET deleted = %d WHERE mid = %d AND uid = %d', $delete, $pmid, $account->uid);
+  }
+  else {
+    // Mark deleted for all users.
+    db_query('UPDATE {pm_index} SET deleted = %d WHERE mid = %d', $delete, $pmid);
+  }
 
   $result = db_query("SELECT MIN(deleted) AS deleted_by_all FROM {pm_index} WHERE mid = %d", $pmid);
   $deleted = db_fetch_array($result);
@@ -1112,13 +1188,6 @@
   module_invoke_all('privatemsg_message_delete', $message, $deleted_by_all);
 }
 
-function privatemsg_delete_submit($form, &$form_state) {
-  if ($form_state['values']['confirm']) {
-    privatemsg_message_change_delete($form_state['values']['pmid'], 1);
-    drupal_set_message(t('Message has been deleted'));
-  }
-  $form_state['redirect'] = 'messages';
-}
 /**
  * Send a new message.
  *
@@ -1208,7 +1277,7 @@
 
   // We don't know the subject and the recipients, so we need to load them..
   // thread_id == mid on the first message of the thread
-  $first_message = _privatemsg_load($thread_id, $message['author']);
+  $first_message = _privatemsg_load($thread_id);
   if (!$first_message) {
     return array(t('Thread %thread_id not found, unable to answer', array('%thread_id' => $thread_id)));
   }
@@ -1374,23 +1443,14 @@
  *
  * @param $pmid
  *   Message id, pm.mid field
- * @param $account
- *   For which account the message should be loaded.
- *   Defaults to the current user.
  *
  * @ingroup api
  */
-function _privatemsg_load($pmid, $account = NULL) {
-  if (empty($account)) {
-    global $user;
-    $account = drupal_clone($user);
-  }
-
-  $query = _privatemsg_assemble_query('load', $pmid, $account);
+function _privatemsg_load($pmid) {
+  $query = _privatemsg_assemble_query('load', $pmid);
 
   $result = db_query($query['query']);
   $message = db_fetch_array($result);
-  $message['user'] = $account;
   // Load author of message.
   $message['author'] = user_load($message['author']);
   $returned = module_invoke_all('privatemsg_message_load', $message);

