Index: privatemsg.api.php
===================================================================
RCS file: /cvs/drupal/contributions/modules/privatemsg/privatemsg.api.php,v
retrieving revision 1.4
diff -u -p -r1.4 privatemsg.api.php
--- privatemsg.api.php	16 Aug 2010 08:12:25 -0000	1.4
+++ privatemsg.api.php	18 Nov 2010 00:47:00 -0000
@@ -313,7 +313,7 @@ function hook_privatemsg_message_validat
   foreach ($message['recipients'] as $recipient) {
     if ($recipient->name == 'blocked user') {
       $_privatemsg_invalid_recipients[] = $recipient->uid;
-      $errors[] = t('%name has chosen to not recieve any more messages from you.', array('%name' => $recipient->name));
+      $errors[] = t('%name has chosen to not recieve any more messages from you.', array('%name' => privatemsg_recipient_format($recipient, array('plain' => TRUE))));
     }
   }
 }
Index: privatemsg.author-pane.inc
===================================================================
RCS file: /cvs/drupal/contributions/modules/privatemsg/privatemsg.author-pane.inc,v
retrieving revision 1.6
diff -u -p -r1.6 privatemsg.author-pane.inc
--- privatemsg.author-pane.inc	10 Aug 2010 19:54:49 -0000	1.6
+++ privatemsg.author-pane.inc	18 Nov 2010 00:47:00 -0000
@@ -12,8 +12,6 @@
 function privatemsg_preprocess_author_pane(&$variables) {
   global $user;
   $account = $variables['account'];
-  $account_id = $account->uid;
-  $account_name = $account->name;
 
   if (function_exists('author_pane_api') && author_pane_api() == "2") {
     // Author Pane 2.x
@@ -25,7 +23,7 @@ function privatemsg_preprocess_author_pa
 
     $url = privatemsg_get_link($account);
     if (!empty($url)) {
-      $variables['privatemsg'] = l(t('Send private message'), $url, array('attributes' => array('class' => 'author-privatemsg-icon', 'title' => t('Send @name a private message', array('@name' => $account_name))), 'html' => TRUE));
+      $variables['privatemsg'] = l(t('Send private message'), $url, array('attributes' => array('class' => 'author-privatemsg-icon', 'title' => t('Send @name a private message', array('@name' => privatemsg_recipient_format($account, array('plain' => TRUE))))), 'html' => TRUE));
 
       // Early versions of the template used this variable so fill it for
       // backwards compatability.
Index: privatemsg.module
===================================================================
RCS file: /cvs/drupal/contributions/modules/privatemsg/privatemsg.module,v
retrieving revision 1.152
diff -u -p -r1.152 privatemsg.module
--- privatemsg.module	10 Nov 2010 15:46:44 -0000	1.152
+++ privatemsg.module	18 Nov 2010 00:47:07 -0000
@@ -665,6 +665,7 @@ function privatemsg_cron() {
 }
 
 function privatemsg_theme() {
+  debug('hook_theme called for privatemsg');
   return array(
     'privatemsg_view'    => array(
       'arguments'        => array('message' => NULL),
@@ -895,7 +896,11 @@ function _privatemsg_parse_userstring($i
         $function = $module . '_privatemsg_name_lookup';
         $return = $function($string);
         if (isset($return) && is_array($return)) {
-          $matches += $return;
+         foreach ($return as $recipient) {
+           // Save recipients under their key to merge recipients which were
+           // loaded multiple times.
+           $matches[privatemsg_recipient_key($recipient)] = $recipient;
+         }
         }
       }
 
@@ -1625,7 +1630,8 @@ function _privatemsg_validate_message(&$
       );
     }
     else {
-      $messages['error'][] = t('@user is not allowed to write messages.', array('@user' => $message['author']->name));
+      debug($message['author'], NULL, TRUE);
+      $messages['error'][] = t('@user is not allowed to write messages.', array('@user' => privatemsg_recipient_format($message['author'], array('plain' => TRUE))));
       return array(
          'success'  => FALSE,
          'messages'   => $messages,
@@ -1663,7 +1669,7 @@ function _privatemsg_validate_message(&$
       form_set_error('format', t('You are not allowed to use the specified format.'));
     }
     else {
-      $messages['error'][] = t('@user is not allowed to use the specified input format.', array('@user' => $message['author']->name));
+      $messages['error'][] = t('@user is not allowed to use the specified input format.', array('@user' => privatemsg_recipient_format($message['author'], array('plain' => TRUE))));
     }
   }
 
@@ -2517,7 +2523,11 @@ function privatemsg_recipient_format($re
   }
   $type = privatemsg_recipient_get_type($recipient->type);
   if (isset($type['format'])) {
-    return theme($type['format'], $recipient, $options);
+    debug($type['format']);
+    debug($options, NULL, TRUE);
+    $result =  theme($type['format'], $recipient, $options);
+    debug($result);
+    return $result;
   }
   return NULL;
 }
Index: privatemsg.pages.inc
===================================================================
RCS file: /cvs/drupal/contributions/modules/privatemsg/privatemsg.pages.inc,v
retrieving revision 1.19
diff -u -p -r1.19 privatemsg.pages.inc
--- privatemsg.pages.inc	27 Oct 2010 14:41:00 -0000	1.19
+++ privatemsg.pages.inc	18 Nov 2010 00:47:09 -0000
@@ -178,7 +178,9 @@ function privatemsg_new(&$form_state, $r
   $body      = '';
 
   // convert recipients to array of user objects
+  $unique = FALSE;
   if (!empty($recipients) && is_string($recipients) || is_int($recipients)) {
+    $unique = TRUE;
     $recipients = _privatemsg_generate_user_array($recipients);
   }
   elseif (is_object($recipients)) {
@@ -219,7 +221,7 @@ function privatemsg_new(&$form_state, $r
         continue;
       }
       $to[privatemsg_recipient_key($recipient)] = privatemsg_recipient_format($recipient);
-      $to_plain[privatemsg_recipient_key($recipient)] = privatemsg_recipient_format($recipient, array('plain' => TRUE));
+      $to_plain[privatemsg_recipient_key($recipient)] = privatemsg_recipient_format($recipient, array('plain' => TRUE, 'unique' => $unique));
     }
     else {
       // Recipient list contains blocked users.
Index: privatemsg.theme.inc
===================================================================
RCS file: /cvs/drupal/contributions/modules/privatemsg/privatemsg.theme.inc,v
retrieving revision 1.6
diff -u -p -r1.6 privatemsg.theme.inc
--- privatemsg.theme.inc	22 Oct 2010 08:46:15 -0000	1.6
+++ privatemsg.theme.inc	18 Nov 2010 00:47:10 -0000
@@ -315,6 +315,7 @@ function theme_privatemsg_new_block($cou
  * Wrapper for theme_username() with a few additional options.
  */
 function theme_privatemsg_username($recipient, $options) {
+  debug('theme function called');
   if (!isset($recipient->uid)) {
     $recipient->uid = $recipient->recipient;
   }
@@ -323,6 +324,7 @@ function theme_privatemsg_username($reci
     if (!empty($options['unique'])) {
       $name .= ' [user]';
     }
+    debug('name: ' . $name);
     return $name;
   }
   else {
Index: pm_block_user/pm_block_user.module
===================================================================
RCS file: /cvs/drupal/contributions/modules/privatemsg/pm_block_user/pm_block_user.module,v
retrieving revision 1.14
diff -u -p -r1.14 pm_block_user.module
--- pm_block_user/pm_block_user.module	27 Oct 2010 14:41:00 -0000	1.14
+++ pm_block_user/pm_block_user.module	18 Nov 2010 00:47:11 -0000
@@ -228,7 +228,7 @@ function pm_block_user_privatemsg_block_
     }
     $blocked[] = array(
       'recipient' => privatemsg_recipient_key($recipient),
-      'message' => t('%name has chosen to block messages from you.', array('%name' => $recipient->name))
+      'message' => t('%name has chosen to block messages from you.', array('%name' => privatemsg_recipient_format($recipient, array('plain' => TRUE))))
     );
   }
   return $blocked;
Index: pm_block_user/pm_block_user.pages.inc
===================================================================
RCS file: /cvs/drupal/contributions/modules/privatemsg/pm_block_user/pm_block_user.pages.inc,v
retrieving revision 1.5
diff -u -p -r1.5 pm_block_user.pages.inc
--- pm_block_user/pm_block_user.pages.inc	20 Oct 2010 12:52:58 -0000	1.5
+++ pm_block_user/pm_block_user.pages.inc	18 Nov 2010 00:47:11 -0000
@@ -11,15 +11,11 @@ function pm_block_user_form($form_state,
 
   $form['author'] = array(
     '#type' => 'value',
-    '#value' => $author->uid,
+    '#value' => $author,
   );
     $form['recipient'] = array(
     '#type' => 'value',
-    '#value' => $user->uid,
-  );
-  $form['author_name'] = array(
-    '#type' => 'value',
-    '#value' => $author->name,
+    '#value' => $user,
   );
   $form['destination'] = array(
     '#type' => 'value',
@@ -32,10 +28,10 @@ function pm_block_user_form($form_state,
       '#value' => 'unblock_user',
     );
     return confirm_form($form,
-      t('You have previously blocked "@author" from sending you any more messages. Are you sure you want to unblock this user?', array('@author' => $author->name)),
+      t('You have previously blocked "@author" from sending you any more messages. Are you sure you want to unblock this user?', array('@author' => privatemsg_recipient_format($author, array('plain' => TRUE)))),
       isset($_GET['destination']) ? $_GET['destination'] : privatemsg_get_dynamic_url_prefix(),
       '',
-      t('Unblock @author', array('@author' => $author->name)),
+      t('Unblock @author', array('@author' => privatemsg_recipient_format($author, array('plain' => TRUE)))),
       t('Cancel')
     );
   }
@@ -45,10 +41,10 @@ function pm_block_user_form($form_state,
       '#value' => 'block_user',
     );
     return confirm_form($form,
-      t('Are you sure you want to block "@author" from sending you any more messages?', array('@author' => $author->name)),
+      t('Are you sure you want to block "@author" from sending you any more messages?', array('@author' => privatemsg_recipient_format($author, array('plain' => TRUE)))),
       isset($_GET['destination']) ? $_GET['destination'] : privatemsg_get_dynamic_url_prefix(),
       '',
-      t('Block @author', array('@author' => $author->name)),
+      t('Block @author', array('@author' => privatemsg_recipient_format($author, array('plain' => TRUE)))),
       t('Cancel')
     );
   }
@@ -61,12 +57,12 @@ function pm_block_user_form_submit($form
   if ($form_state['values']['confirm']) {
     switch ($form_state['values']['block_action']) {
       case 'block_user':
-        db_query('INSERT INTO {pm_block_user} (author, recipient) VALUES (%d, %d)', $form_state['values']['author'], $form_state['values']['recipient']);
-        drupal_set_message(t('@author has been blocked from sending you any further messages.', array('@author' => $form_state['values']['author_name'])));
+        db_query('INSERT INTO {pm_block_user} (author, recipient) VALUES (%d, %d)', $form_state['values']['author']->uid, $form_state['values']['recipient']->uid);
+        drupal_set_message(t('@author has been blocked from sending you any further messages.', array('@author' => privatemsg_recipient_format($form_state['values']['author'], array('plain' => TRUE)))));
       break;
       case 'unblock_user':
-        db_query('DELETE FROM {pm_block_user} WHERE author = %d AND recipient = %d', $form_state['values']['author'], $form_state['values']['recipient']);
-        drupal_set_message(t('@author is now allowed to send you new messages.', array('@author' => $form_state['values']['author_name'])));
+        db_query('DELETE FROM {pm_block_user} WHERE author = %d AND recipient = %d', $form_state['values']['author']->uid, $form_state['values']['recipient']->uid);
+        drupal_set_message(t('@author has been blocked from sending you any further messages.', array('@author' => privatemsg_recipient_format($form_state['values']['author'], array('plain' => TRUE)))));
       break;
     }
   }
Index: pm_email_notify/pm_email_notify.module
===================================================================
RCS file: /cvs/drupal/contributions/modules/privatemsg/pm_email_notify/pm_email_notify.module,v
retrieving revision 1.15
diff -u -p -r1.15 pm_email_notify.module
--- pm_email_notify/pm_email_notify.module	22 Oct 2010 09:02:10 -0000	1.15
+++ pm_email_notify/pm_email_notify.module	18 Nov 2010 00:47:12 -0000
@@ -87,7 +87,7 @@ function pm_email_notify_mail($key, &$me
  */
 function _pm_email_notify_token($recipient, $message, $language) {
   $tokens = array(
-    '!author' => $message['author']->name,
+    '!author' => privatemsg_recipient_format($message['author'], array('plain' => TRUE)),
     '!pm_subject' => trim(drupal_html_to_text(check_plain($message['subject']))),
     '!pm_body' => trim(drupal_html_to_text(check_markup($message['body'], $message['format'], FALSE))),
     '!thread' => $message['thread_id'],
Index: privatemsg_filter/privatemsg_filter.module
===================================================================
RCS file: /cvs/drupal/contributions/modules/privatemsg/privatemsg_filter/privatemsg_filter.module,v
retrieving revision 1.15
diff -u -p -r1.15 privatemsg_filter.module
--- privatemsg_filter/privatemsg_filter.module	22 Oct 2010 08:48:35 -0000	1.15
+++ privatemsg_filter/privatemsg_filter.module	18 Nov 2010 00:47:15 -0000
@@ -403,7 +403,7 @@ function privatemsg_filter_dropdown_set_
   if (isset($filter['author'])) {
     $string = '';
     foreach ($filter['author'] as $author) {
-      $string .= $author->name . ', ';
+      $string .= privatemsg_recipient_format($author, array('plain' => TRUE)) . ', ';
     }
     $form['filter']['author']['#default_value'] = $string;
   }
@@ -484,10 +484,10 @@ function privatemsg_filter_create_get_qu
   if (isset($filter['author']) && !empty($filter['author'])) {
     foreach ($filter['author'] as $author) {
       if (is_object($author) && isset($author->uid) && isset($author->name)) {
-        $query['author'][] = $author->name;
+        $query['author'][] = privatemsg_recipient_format($author, array('plain' => TRUE));
       }
       elseif (is_int($author) && $author_obj = _privatemsg_user_load($author)) {
-        $query['author'][] = $author_obj->name;
+        $query['author'][] = privatemsg_recipient_format($author, array('plain' => TRUE));
       }
     }
     if (isset($query['author'])) {
Index: privatemsg_realname/privatemsg_realname.info
===================================================================
RCS file: privatemsg_realname/privatemsg_realname.info
diff -N privatemsg_realname/privatemsg_realname.info
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ privatemsg_realname/privatemsg_realname.info	18 Nov 2010 00:47:15 -0000
@@ -0,0 +1,8 @@
+; $Id$
+name = Privatemsg Realname Integration
+description = Provides reverse lookup for realnames
+package = Mail
+core = 6.x
+dependencies[] = privatemsg
+dependencies[] = realname
+
Index: privatemsg_realname/privatemsg_realname.module
===================================================================
RCS file: privatemsg_realname/privatemsg_realname.module
diff -N privatemsg_realname/privatemsg_realname.module
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ privatemsg_realname/privatemsg_realname.module	18 Nov 2010 00:47:15 -0000
@@ -0,0 +1,135 @@
+<?php
+// $Id$
+
+/**
+ * Implements hook_privatemsg_name_lookup().
+ */
+function privatemsg_realname_privatemsg_name_lookup($string) {
+
+  // First, check the unique version.
+  if (preg_match('/\[user:(.+)\]/', $string, $match)) {
+    return array(user_load(array(variable_get('privatemsg_realname_unique_identifier', 'name') => trim($match[1]))));
+  }
+
+  // Then try to look it up with the real name.
+  $result = db_query("SELECT r.uid FROM {realname} r WHERE r.realname = '%s'", $string);
+  $accounts = array();
+  while ($row = db_fetch_object($result)) {
+    if ($account = user_load($row->uid)) {
+      $account->type = 'user';
+      $account->recipient = $account->uid;
+      $accounts[] = $account;
+    }
+  }
+  return $accounts;
+}
+
+/**
+ * Implemenets hook_theme().
+ */
+function privatemsg_realname_theme() {
+  return array(
+    'privatemsg_realname_username'  => array(
+      'arguments' => array('recipient' => NULL, 'options' => array()),
+    ),
+  );
+}
+
+/**
+ * Implements hook_privatemsg_sql_autocomplete_alter().
+ */
+function privatemsg_realname_privatemsg_sql_autocomplete_alter(&$fragments, $search, $names) {
+  // Create necessary LEFT JOINs. LEFT because some users might not have a realname for any reason.
+  $fragments['inner_join'][] = 'LEFT JOIN {realname} r ON (r.uid = u.uid)';
+
+  // Either select users where the profile field name and value matches or the username.
+  // This does replace the default where.
+  if (variable_get('privatemsg_realname_search_username', TRUE)) {
+    $fragments['where'][1] = "(r.realname LIKE '%s' OR u.name LIKE '%s')";
+    array_unshift($fragments['query_args']['where'], $search . '%%');
+  }
+  else {
+    $fragments['where'][1] = "r.realname LIKE '%s'";
+  }
+
+  if (!empty($names)) {
+    // Exclude already existing realnames, but explicitly allow NULL.
+    // r.realname is left joined and cann be NULL => NULL NOT IN (...) => NOT (NULL) => NULL.
+    $fragments['where'][] = "r.realname NOT IN (". db_placeholders($names, 'text') .") OR r.realname IS NULL";
+    $fragments['query_args']['where'] = array_merge($fragments['query_args']['where'], array_values($names));
+  }
+}
+
+/**
+ * Implements hook_privatemsg_recipient_info_alter().
+ */
+function privatemsg_realname_privatemsg_recipient_type_info_alter(&$recipients) {
+  // Override format callback.
+  $recipients['user']['format'] = 'privatemsg_realname_username';
+}
+
+/**
+ * Used to theme and display user recipients.
+ *
+ * Wrapper for theme_username() with a few additional options.
+ */
+function theme_privatemsg_realname_username($recipient, $options) {
+  if (!isset($recipient->uid)) {
+    $recipient->uid = $recipient->recipient;
+  }
+  if (!empty($options['plain'])) {
+    $name = theme('username', $recipient, array('plain' => TRUE));
+    if (!empty($options['unique'])) {
+      $identifier = variable_get('privatemsg_realname_unique_identifier', 'name');
+      $name .= ' [user: ' . $recipient->$identifier . ']';
+    }
+    return $name;
+  }
+  else {
+    return theme('username', $recipient);
+  }
+}
+
+/**
+ * Implements hook_privatemsg_sql_participants_alter().
+ */
+function privatemsg_realname_privatemsg_sql_participants_alter(&$fragments, $thread_id) {
+  // Select the realname.
+  $fragments['select'][]      = 'r.realname';
+  // Also select homepage to avoid php notices.
+  $fragements['select'][]     = 'u.homepage';
+
+  // Join realname table.
+  $fragments['inner_join'][]  = 'LEFT JOIN {realname} r ON (r.uid = u.uid)';
+}
+
+/**
+ * Implements hook_form_FORM_ID_alter().
+ */
+function privatemsg_realname_form_privatemsg_admin_settings_alter(&$form, &$form_state) {
+  $form['realname'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('Realname integration'),
+    '#collapsed' => TRUE,
+    '#collapsible' => TRUE,
+    '#weight' => 25,
+  );
+
+  $form['realname']['privatemsg_realname_unique_identifier'] = array(
+    '#type' => 'radios',
+    '#title' => t('Field to use as a unique identifier'),
+    '#description' => t('Real names are often not unique. Choose which field should be used as a unique identifier when sending private messages.'),
+    '#default_value' => variable_get('privatemsg_realname_unique_identifier', 'name'),
+    '#options' => array(
+      'name' => t('Username'),
+      'uid' => t('UID'),
+      'mail' => t('E-mail'),
+    ),
+  );
+
+  $form['realname']['privatemsg_realname_search_username'] = array(
+    '#type' => 'checkbox',
+    '#title' => t('Search usernames for autocomplete suggestions'),
+    '#default_value' => variable_get('privatemsg_realname_search_username', TRUE),
+  );
+}
\ No newline at end of file
Index: tests/privatemsgapi.test
===================================================================
RCS file: /cvs/drupal/contributions/modules/privatemsg/tests/privatemsgapi.test,v
retrieving revision 1.7
diff -u -p -r1.7 privatemsgapi.test
--- tests/privatemsgapi.test	17 Aug 2010 13:05:41 -0000	1.7
+++ tests/privatemsgapi.test	18 Nov 2010 00:47:16 -0000
@@ -29,6 +29,14 @@ class PrivatemsgAPITestCase extends Drup
    */
   function setUp() {
     parent::setUp('privatemsg');
+
+    // Enforce rebuild of the theme registry.
+    global $theme;
+    $registry = theme_get_registry();
+    debug($registry['privatemsg_username'], NULL, TRUE);
+    _theme_load_registry($theme);
+    $registry = theme_get_registry();
+    debug($registry['privatemsg_username'], NULL, TRUE);
   }
 
   function testPrivatemsgApiNewThread() {
@@ -60,6 +68,8 @@ class PrivatemsgAPITestCase extends Drup
 
     $resultf3 = privatemsg_new_thread(array($recipient1, $recipient2, $recipient3), 'not allowed', 'Body text', array('author' => $recipient1));
     $errormessage = t('@user is not allowed to write messages.', array('@user' => $recipient1->name));
+    $this->fail($resultf3['messages']['error'][0]);
+    $this->fail($errormessage);
     $this->assertEqual($errormessage, $resultf3['messages']['error'][0], 'API denied to send message from user without permission');
     $message = $this->getMessageFromSubject('not allowed');
     $this->assertTrue(empty($message), 'Message was not saved in database');
