? drupal-6.x-dev/sites/default/settings.php
Index: drupal-6.x-dev/install.php
===================================================================
RCS file: /cvs/drupal/drupal/install.php,v
retrieving revision 1.88
diff -u -p -r1.88 install.php
--- drupal-6.x-dev/install.php	11 Nov 2007 22:43:44 -0000	1.88
+++ drupal-6.x-dev/install.php	14 Nov 2007 10:53:37 -0000
@@ -884,7 +884,14 @@ function install_configure_form() {
   $form['admin_account']['account']['name'] = array('#type' => 'textfield',
     '#title' => st('Username'),
     '#maxlength' => USERNAME_MAX_LENGTH,
-    '#description' => st('Spaces are allowed; punctuation is not allowed except for periods, hyphens, and underscores.'),
+    '#description' => st('Only lower cases are allowed; spaces are allowed; punctuation is not allowed except for periods, hyphens, and underscores.'),
+    '#required' => TRUE,
+    '#weight' => -15,
+  );
+  $form['admin_account']['account']['fullname'] = array('#type' => 'textfield',
+    '#title' => st('Full name'),
+    '#maxlength' => FULLNAME_MAX_LENGTH,
+    '#description' => st('Specify your first and last name.'),
     '#required' => TRUE,
     '#weight' => -10,
   );
@@ -969,6 +976,9 @@ function install_configure_form_validate
   if ($error = user_validate_name($form_state['values']['account']['name'])) {
     form_error($form['admin_account']['account']['name'], $error);
   }
+  if ($error = user_validate_fullname($form_state['values']['account']['fullname'])) {
+    form_error($form['admin_account']['account']['fullname'], $error);
+  }
   if ($error = user_validate_mail($form_state['values']['account']['mail'])) {
     form_error($form['admin_account']['account']['mail'], $error);
   }
Index: drupal-6.x-dev/includes/theme.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/theme.inc,v
retrieving revision 1.394
diff -u -p -r1.394 theme.inc
--- drupal-6.x-dev/includes/theme.inc	11 Nov 2007 22:43:44 -0000	1.394
+++ drupal-6.x-dev/includes/theme.inc	14 Nov 2007 10:53:37 -0000
@@ -1618,22 +1618,43 @@ function theme_blocks($region) {
  *
  * @param $object
  *   The user object to format, usually returned from user_load().
+ * @param $options
+ *   An associative array of additional options, with the following keys:
+ *     'plain' (default FALSE)
+ *       Whether to force the output as plain text format. Useful for
+ *       centralize username style handling.
+ *     'format'
+ *       If fullname available, style display format with predefined pattern.
  * @return
  *   A string containing an HTML link to the user's page if the passed object
  *   suggests that this is a site user. Otherwise, only the username is returned.
  */
-function theme_username($object) {
+function theme_username($object, $options = array()) {
+  // Merge in defaults.
+  $options += array(
+    'plain' => FALSE,
+    'format' => variable_get('user_display_format', '!fullname'),
+  );
+
+  // Display user fullname with styling if available.
+  if (isset($object->fullname)) {
+    $name = t($options['format'],
+      array(
+        '!fullname' => $object->fullname,
+        '!username' => $object->name,
+      ));
+  }
+  else {
+    $name = $object->name;
+  }
 
   if ($object->uid && $object->name) {
     // Shorten the name when it is too long or it will break many tables.
-    if (drupal_strlen($object->name) > 20) {
-      $name = drupal_substr($object->name, 0, 15) .'...';
-    }
-    else {
-      $name = $object->name;
+    if (drupal_strlen($name) > 20) {
+      $name = drupal_substr($name, 0, 15) .'...';
     }
 
-    if (user_access('access user profiles')) {
+    if (user_access('access user profiles') && !$options['plain']) {
       $output = l($name, 'user/'. $object->uid, array('title' => t('View user profile.')));
     }
     else {
@@ -1645,11 +1666,11 @@ function theme_username($object) {
     // not registered members of the site (e.g. mailing list or news
     // aggregator modules). This clause enables modules to display
     // the true author of the content.
-    if (!empty($object->homepage)) {
-      $output = l($object->name, $object->homepage, array('rel' => 'nofollow'));
+    if (!empty($object->homepage) && !$options['plain']) {
+      $output = l($name, $object->homepage, array('rel' => 'nofollow'));
     }
     else {
-      $output = check_plain($object->name);
+      $output = check_plain($name);
     }
 
     $output .= ' ('. t('not verified') .')';
Index: drupal-6.x-dev/modules/blog/blog.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/blog/blog.module,v
retrieving revision 1.291
diff -u -p -r1.291 blog.module
--- drupal-6.x-dev/modules/blog/blog.module	4 Nov 2007 15:45:15 -0000	1.291
+++ drupal-6.x-dev/modules/blog/blog.module	14 Nov 2007 10:53:37 -0000
@@ -107,7 +107,7 @@ function blog_form(&$node) {
 function blog_view($node, $teaser = FALSE, $page = FALSE) {
   if ($page) {
     // Breadcrumb navigation
-    drupal_set_breadcrumb(array(l(t('Home'), NULL), l(t('Blogs'), 'blog'), l(t("@name's blog", array('@name' => $node->name)), 'blog/'. $node->uid)));
+    drupal_set_breadcrumb(array(l(t('Home'), NULL), l(t('Blogs'), 'blog'), l(t("@name's blog", array('@name' => theme('username', $node, array('plain' => TRUE)))), 'blog/'. $node->uid)));
   }
   return node_prepare($node, $teaser);
 }
@@ -121,9 +121,9 @@ function blog_link($type, $node = NULL, 
   if ($type == 'node' && $node->type == 'blog') {
     if (arg(0) != 'blog' || arg(1) != $node->uid) {
       $links['blog_usernames_blog'] = array(
-        'title' => t("@username's blog", array('@username' => $node->name)),
+        'title' => t("@username's blog", array('@username' => theme('username', $node, array('plain' => TRUE)))),
         'href' => "blog/$node->uid",
-        'attributes' => array('title' => t("Read @username's latest blog entries.", array('@username' => $node->name)))
+        'attributes' => array('title' => t("Read @username's latest blog entries.", array('@username' => theme('username', $node, array('plain' => TRUE)))))
       );
     }
   }
Index: drupal-6.x-dev/modules/blog/blog.pages.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/blog/blog.pages.inc,v
retrieving revision 1.3
diff -u -p -r1.3 blog.pages.inc
--- drupal-6.x-dev/modules/blog/blog.pages.inc	25 Oct 2007 17:44:38 -0000	1.3
+++ drupal-6.x-dev/modules/blog/blog.pages.inc	14 Nov 2007 10:53:37 -0000
@@ -12,7 +12,7 @@
 function blog_page_user($account) {
   global $user;
 
-  drupal_set_title($title = t("@name's blog", array('@name' => $account->name)));
+  drupal_set_title($title = t("@name's blog", array('@name' => theme('username', $account, array('plain' => TRUE)))));
 
   $items = array();
 
@@ -59,7 +59,7 @@ function blog_page_last() {
  */
 function blog_feed_user($account) {
   $result = db_query_range(db_rewrite_sql("SELECT n.nid, n.created FROM {node} n  WHERE n.type = 'blog' AND n.uid = %d AND n.status = 1 ORDER BY n.created DESC"), $account->uid, 0, variable_get('feed_default_items', 10));
-  $channel['title'] = $account->name ."'s blog";
+  $channel['title'] = t("@name's blog", array('@name' => theme('username', $account, array('plain' => TRUE))));
   $channel['link'] = url('blog/'. $account->uid, array('absolute' => TRUE));
 
   $items = array();
Index: drupal-6.x-dev/modules/comment/comment.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/comment/comment.module,v
retrieving revision 1.602
diff -u -p -r1.602 comment.module
--- drupal-6.x-dev/modules/comment/comment.module	12 Nov 2007 19:06:32 -0000	1.602
+++ drupal-6.x-dev/modules/comment/comment.module	14 Nov 2007 10:53:37 -0000
@@ -897,7 +897,7 @@ function comment_render($node, $cid = 0)
 
     if ($cid && is_numeric($cid)) {
       // Single comment view.
-      $query = 'SELECT c.cid, c.pid, c.nid, c.subject, c.comment, c.format, c.timestamp, c.name, c.mail, c.homepage, u.uid, u.name AS registered_name, u.signature, u.picture, u.data, c.status FROM {comments} c INNER JOIN {users} u ON c.uid = u.uid WHERE c.cid = %d';
+      $query = 'SELECT c.cid, c.pid, c.nid, c.subject, c.comment, c.format, c.timestamp, c.name, c.mail, c.homepage, u.uid, u.name AS registered_name, u.fullname AS registered_fullname, u.signature, u.picture, u.data, c.status FROM {comments} c INNER JOIN {users} u ON c.uid = u.uid WHERE c.cid = %d';
       $query_args = array($cid);
       if (!user_access('administer comments')) {
         $query .= ' AND c.status = %d';
@@ -909,6 +909,7 @@ function comment_render($node, $cid = 0)
 
       if ($comment = db_fetch_object($result)) {
         $comment->name = $comment->uid ? $comment->registered_name : $comment->name;
+        $comment->fullname = $comment->uid ? $comment->registered_fullname : $comment->name;
         $links = module_invoke_all('link', 'comment', $comment, 1);
         drupal_alter('link', $links, $node);
 
@@ -918,7 +919,7 @@ function comment_render($node, $cid = 0)
     else {
       // Multiple comment view
       $query_count = 'SELECT COUNT(*) FROM {comments} WHERE nid = %d';
-      $query = 'SELECT c.cid as cid, c.pid, c.nid, c.subject, c.comment, c.format, c.timestamp, c.name, c.mail, c.homepage, u.uid, u.name AS registered_name, u.signature, u.picture, u.data, c.thread, c.status FROM {comments} c INNER JOIN {users} u ON c.uid = u.uid WHERE c.nid = %d';
+      $query = 'SELECT c.cid as cid, c.pid, c.nid, c.subject, c.comment, c.format, c.timestamp, c.name, c.mail, c.homepage, u.uid, u.name AS registered_name, u.fullname AS registered_fullname, u.signature, u.picture, u.data, c.thread, c.status FROM {comments} c INNER JOIN {users} u ON c.uid = u.uid WHERE c.nid = %d';
 
       $query_args = array($nid);
       if (!user_access('administer comments')) {
@@ -963,6 +964,7 @@ function comment_render($node, $cid = 0)
       while ($comment = db_fetch_object($result)) {
         $comment = drupal_unpack($comment);
         $comment->name = $comment->uid ? $comment->registered_name : $comment->name;
+        $comment->fullname = $comment->uid ? $comment->registered_fullname : $comment->name;
         $comment->depth = count(explode('.', $comment->thread)) - 1;
 
         if ($mode == COMMENT_MODE_THREADED_COLLAPSED || $mode == COMMENT_MODE_THREADED_EXPANDED) {
@@ -1363,7 +1365,7 @@ function comment_form_add_preview($form,
     }
     if (!empty($account)) {
       $comment->uid = $account->uid;
-      $comment->name = check_plain($account->name);
+      $comment->name = theme('username', $account, array('plain' => TRUE));
     }
     elseif (empty($comment->name)) {
       $comment->name = variable_get('anonymous', t('Anonymous'));
@@ -1381,9 +1383,10 @@ function comment_form_add_preview($form,
   $output = '';
 
   if ($edit['pid']) {
-    $comment = db_fetch_object(db_query('SELECT c.*, u.uid, u.name AS registered_name, u.signature, u.picture, u.data FROM {comments} c INNER JOIN {users} u ON c.uid = u.uid WHERE c.cid = %d AND c.status = %d', $edit['pid'], COMMENT_PUBLISHED));
+    $comment = db_fetch_object(db_query('SELECT c.*, u.uid, u.name AS registered_name, u.fullname AS registered_fullname, u.signature, u.picture, u.data FROM {comments} c INNER JOIN {users} u ON c.uid = u.uid WHERE c.cid = %d AND c.status = %d', $edit['pid'], COMMENT_PUBLISHED));
     $comment = drupal_unpack($comment);
     $comment->name = $comment->uid ? $comment->registered_name : $comment->name;
+    $comment->fullname = $comment->uid ? $comment->registered_fullname : $comment->name;
     $output .= theme('comment_view', $comment, $node);
   }
   else {
Index: drupal-6.x-dev/modules/comment/comment.pages.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/comment/comment.pages.inc,v
retrieving revision 1.1
diff -u -p -r1.1 comment.pages.inc
--- drupal-6.x-dev/modules/comment/comment.pages.inc	31 Oct 2007 17:50:47 -0000	1.1
+++ drupal-6.x-dev/modules/comment/comment.pages.inc	14 Nov 2007 10:53:37 -0000
@@ -62,7 +62,7 @@ function comment_reply($node, $pid = NUL
       // $pid indicates that this is a reply to a comment.
       if ($pid) {
         // load the comment whose cid = $pid
-        if ($comment = db_fetch_object(db_query('SELECT c.*, u.uid, u.name AS registered_name, u.signature, u.picture, u.data FROM {comments} c INNER JOIN {users} u ON c.uid = u.uid WHERE c.cid = %d AND c.status = %d', $pid, COMMENT_PUBLISHED))) {
+        if ($comment = db_fetch_object(db_query('SELECT c.*, u.uid, u.name AS registered_name, u.fullname AS registered_fullname, u.signature, u.picture, u.data FROM {comments} c INNER JOIN {users} u ON c.uid = u.uid WHERE c.cid = %d AND c.status = %d', $pid, COMMENT_PUBLISHED))) {
           // If that comment exists, make sure that the current comment and the parent comment both
           // belong to the same parent node.
           if ($comment->nid != $node->nid) {
@@ -73,6 +73,7 @@ function comment_reply($node, $pid = NUL
           // Display the parent comment
           $comment = drupal_unpack($comment);
           $comment->name = $comment->uid ? $comment->registered_name : $comment->name;
+          $comment->fullname = $comment->uid ? $comment->registered_fullname : $comment->name;
           $output .= theme('comment_view', $comment, $node);
         }
         else {
Index: drupal-6.x-dev/modules/contact/contact.pages.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/contact/contact.pages.inc,v
retrieving revision 1.4
diff -u -p -r1.4 contact.pages.inc
--- drupal-6.x-dev/modules/contact/contact.pages.inc	2 Oct 2007 16:03:17 -0000	1.4
+++ drupal-6.x-dev/modules/contact/contact.pages.inc	14 Nov 2007 10:53:37 -0000
@@ -42,7 +42,7 @@ function contact_mail_page() {
     $form['name'] = array('#type' => 'textfield',
       '#title' => t('Your name'),
       '#maxlength' => 255,
-      '#default_value' => $user->uid ? $user->name : '',
+      '#default_value' => $user->uid ? theme('username', $user, array('plain' => TRUE)) : '',
       '#required' => TRUE,
     );
     $form['mail'] = array('#type' => 'textfield',
@@ -160,7 +160,7 @@ function contact_user_page($account) {
     $output = t('You cannot contact more than %number users per hour. Please try again later.', array('%number' => variable_get('contact_hourly_threshold', 3)));
   }
   else {
-    drupal_set_title(check_plain($account->name));
+    drupal_set_title(theme('username', $account, array('plain' => TRUE)));
     $output = drupal_get_form('contact_mail_user', $account);
   }
 
@@ -173,11 +173,11 @@ function contact_mail_user(&$form_state,
   $form['recipient'] = array('#type' => 'value', '#value' => $recipient);
   $form['from'] = array('#type' => 'item',
     '#title' => t('From'),
-    '#value' => check_plain($user->name) .' &lt;'. check_plain($user->mail) .'&gt;',
+    '#value' => theme('username', $user, array('plain' => TRUE)) .' &lt;'. check_plain($user->mail) .'&gt;',
   );
   $form['to'] = array('#type' => 'item',
     '#title' => t('To'),
-    '#value' => check_plain($recipient->name),
+    '#value' => theme('username', $recipient, array('plain' => TRUE)),
   );
   $form['subject'] = array('#type' => 'textfield',
     '#title' => t('Subject'),
Index: drupal-6.x-dev/modules/forum/forum.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/forum/forum.module,v
retrieving revision 1.425
diff -u -p -r1.425 forum.module
--- drupal-6.x-dev/modules/forum/forum.module	25 Oct 2007 15:32:55 -0000	1.425
+++ drupal-6.x-dev/modules/forum/forum.module	14 Nov 2007 10:53:37 -0000
@@ -506,14 +506,14 @@ function forum_get_forums($tid = 0) {
     // This query does not use full ANSI syntax since MySQL 3.x does not support
     // table1 INNER JOIN table2 INNER JOIN table3 ON table2_criteria ON table3_criteria
     // used to join node_comment_statistics to users.
-    $sql = "SELECT ncs.last_comment_timestamp, IF (ncs.last_comment_uid != 0, u2.name, ncs.last_comment_name) AS last_comment_name, ncs.last_comment_uid FROM {node} n INNER JOIN {users} u1 ON n.uid = u1.uid INNER JOIN {term_node} tn ON n.vid = tn.vid INNER JOIN {node_comment_statistics} ncs ON n.nid = ncs.nid INNER JOIN {users} u2 ON ncs.last_comment_uid=u2.uid WHERE n.status = 1 AND tn.tid = %d ORDER BY ncs.last_comment_timestamp DESC";
+    $sql = "SELECT ncs.last_comment_timestamp, IF (ncs.last_comment_uid != 0, u2.fullname, ncs.last_comment_name) AS last_comment_fullname, ncs.last_comment_uid FROM {node} n INNER JOIN {users} u1 ON n.uid = u1.uid INNER JOIN {term_node} tn ON n.vid = tn.vid INNER JOIN {node_comment_statistics} ncs ON n.nid = ncs.nid INNER JOIN {users} u2 ON ncs.last_comment_uid=u2.uid WHERE n.status = 1 AND tn.tid = %d ORDER BY ncs.last_comment_timestamp DESC";
     $sql = db_rewrite_sql($sql);
     $topic = db_fetch_object(db_query_range($sql, $forum->tid, 0, 1));
 
     $last_post = new stdClass();
     if (!empty($topic->last_comment_timestamp)) {
       $last_post->timestamp = $topic->last_comment_timestamp;
-      $last_post->name = $topic->last_comment_name;
+      $last_post->fullname = $topic->last_comment_fullname;
       $last_post->uid = $topic->last_comment_uid;
     }
     $forum->last_post = $last_post;
@@ -554,7 +554,7 @@ function forum_get_topics($tid, $sortby,
 
   $term = taxonomy_get_term($tid);
 
-  $sql = db_rewrite_sql("SELECT n.nid, r.tid, n.title, n.sticky, u.name, u.uid, n.created AS timestamp, n.comment AS comment_mode, l.last_comment_timestamp, IF(l.last_comment_uid != 0, cu.name, l.last_comment_name) AS last_comment_name, l.last_comment_uid, l.comment_count AS num_comments, f.tid AS forum_tid FROM {node_comment_statistics} l INNER JOIN {node} n ON n.nid = l.nid INNER JOIN {users} cu ON l.last_comment_uid = cu.uid INNER JOIN {term_node} r ON n.vid = r.vid INNER JOIN {users} u ON n.uid = u.uid INNER JOIN {forum} f ON n.vid = f.vid WHERE n.status = 1 AND r.tid = %d");
+  $sql = db_rewrite_sql("SELECT n.nid, r.tid, n.title, n.sticky, u.name, u.fullname, u.uid, n.created AS timestamp, n.comment AS comment_mode, l.last_comment_timestamp, IF(l.last_comment_uid != 0, cu.fullname, l.last_comment_name) AS last_comment_fullname, l.last_comment_uid, l.comment_count AS num_comments, f.tid AS forum_tid FROM {node_comment_statistics} l INNER JOIN {node} n ON n.nid = l.nid INNER JOIN {users} cu ON l.last_comment_uid = cu.uid INNER JOIN {term_node} r ON n.vid = r.vid INNER JOIN {users} u ON n.uid = u.uid INNER JOIN {forum} f ON n.vid = f.vid WHERE n.status = 1 AND r.tid = %d");
   $sql .= tablesort_sql($forum_topic_list_header, 'n.sticky DESC,');
   $sql .= ', n.created DESC';  // Always add a secondary sort order so that the news forum topics are on top.
 
@@ -583,7 +583,7 @@ function forum_get_topics($tid, $sortby,
     if ($topic->num_comments > 0) {
       $last_reply = new stdClass();
       $last_reply->timestamp = $topic->last_comment_timestamp;
-      $last_reply->name = $topic->last_comment_name;
+      $last_reply->fullname = $topic->last_comment_fullname;
       $last_reply->uid = $topic->last_comment_uid;
       $topic->last_reply = $last_reply;
     }
Index: drupal-6.x-dev/modules/node/node.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/node/node.module,v
retrieving revision 1.901
diff -u -p -r1.901 node.module
--- drupal-6.x-dev/modules/node/node.module	13 Nov 2007 14:56:14 -0000	1.901
+++ drupal-6.x-dev/modules/node/node.module	14 Nov 2007 10:53:38 -0000
@@ -652,7 +652,7 @@ function node_load($param = array(), $re
   // Retrieve a field list based on the site's schema.
   $fields = drupal_schema_fields_sql('node', 'n');
   $fields = array_merge($fields, drupal_schema_fields_sql('node_revisions', 'r'));
-  $fields = array_merge($fields, array('u.name', 'u.data'));
+  $fields = array_merge($fields, array('u.name', 'u.fullname', 'u.data'));
   $fields = implode(', ', $fields);
   // rename timestamp field for clarity.
   $fields = str_replace('r.timestamp', 'r.timestamp AS revision_timestamp', $fields);
Index: drupal-6.x-dev/modules/node/node.pages.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/node/node.pages.inc,v
retrieving revision 1.7
diff -u -p -r1.7 node.pages.inc
--- drupal-6.x-dev/modules/node/node.pages.inc	12 Nov 2007 19:06:33 -0000	1.7
+++ drupal-6.x-dev/modules/node/node.pages.inc	14 Nov 2007 10:53:38 -0000
@@ -321,6 +321,7 @@ function node_preview($node) {
       // user ID 0 denotes the anonymous user.
       if ($user = user_load(array('name' => $node->name))) {
         $node->uid = $user->uid;
+        $node->fullname = $user->fullname;
         $node->picture = $user->picture;
       }
       else {
@@ -330,6 +331,7 @@ function node_preview($node) {
     else if ($node->uid) {
       $user = user_load(array('uid' => $node->uid));
       $node->name = $user->name;
+      $node->fullname = $user->fullname;
       $node->picture = $user->picture;
     }
 
Index: drupal-6.x-dev/modules/openid/openid.pages.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/openid/openid.pages.inc,v
retrieving revision 1.2
diff -u -p -r1.2 openid.pages.inc
--- drupal-6.x-dev/modules/openid/openid.pages.inc	8 Nov 2007 13:58:32 -0000	1.2
+++ drupal-6.x-dev/modules/openid/openid.pages.inc	14 Nov 2007 10:53:38 -0000
@@ -28,7 +28,7 @@ function openid_authentication_page() {
  * Menu callback; Manage OpenID identities for the specified user.
  */
 function openid_user_identities($account) {
-  drupal_set_title(check_plain($account->name));
+  drupal_set_title(theme('username', $account, array('plain' => TRUE)));
   drupal_add_css(drupal_get_path('module', 'openid') .'/openid.css', 'module');
 
   // Check to see if we got a response
Index: drupal-6.x-dev/modules/statistics/statistics.pages.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/statistics/statistics.pages.inc,v
retrieving revision 1.2
diff -u -p -r1.2 statistics.pages.inc
--- drupal-6.x-dev/modules/statistics/statistics.pages.inc	20 Oct 2007 21:57:50 -0000	1.2
+++ drupal-6.x-dev/modules/statistics/statistics.pages.inc	14 Nov 2007 10:53:38 -0000
@@ -60,7 +60,7 @@ function statistics_user_tracker() {
       $rows[] = array(array('data' => t('No statistics available.'), 'colspan' => 3));
     }
 
-    drupal_set_title(check_plain($account->name));
+    drupal_set_title(theme('username', $account, array('plain' => TRUE)));
     $output = theme('table', $header, $rows);
     $output .= theme('pager', NULL, 30, 0);
     return $output;
Index: drupal-6.x-dev/modules/system/system.install
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.install,v
retrieving revision 1.176
diff -u -p -r1.176 system.install
--- drupal-6.x-dev/modules/system/system.install	13 Nov 2007 14:04:08 -0000	1.176
+++ drupal-6.x-dev/modules/system/system.install	14 Nov 2007 10:53:38 -0000
@@ -268,7 +268,7 @@ function system_install() {
   // presumed to be a serialized array. Install will change uid 1 immediately
   // anyways. So we insert the superuser here, the uid is 2 here for now, but
   // very soon it will be changed to 1.
-  db_query("INSERT INTO {users} (name, mail, created, data) VALUES('%s', '%s', %d, '%s')", 'placeholder-for-uid-1', 'placeholder-for-uid-1', time(), serialize(array()));
+  db_query("INSERT INTO {users} (name, fullname, mail, created, data) VALUES('%s', '%s', '%s', %d, '%s')", 'placeholder-for-uid-1', 'placeholder-for-uid-1', 'placeholder-for-uid-1', time(), serialize(array()));
   // This sets the above two users to 1 -1 = 0 (anonymous) and
   // 2- 1 = 1 (superuser). We skip uid 2 but that's not a big problem.
   db_query('UPDATE {users} SET uid = uid - 1');
Index: drupal-6.x-dev/modules/tracker/tracker.pages.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/tracker/tracker.pages.inc,v
retrieving revision 1.4
diff -u -p -r1.4 tracker.pages.inc
--- drupal-6.x-dev/modules/tracker/tracker.pages.inc	6 Nov 2007 08:51:23 -0000	1.4
+++ drupal-6.x-dev/modules/tracker/tracker.pages.inc	14 Nov 2007 10:53:38 -0000
@@ -19,17 +19,17 @@ function tracker_page($account = NULL, $
       // When viewed from user/%user/track, display the name of the user
       // as page title -- the tab title remains Track so this needs to be done
       // here and not in the menu definiton.
-      drupal_set_title(check_plain($account->name));
+      drupal_set_title(theme('username', $account, array('plain' => TRUE)));
     }
-  // TODO: These queries are very expensive, see http://drupal.org/node/105639
-    $sql = 'SELECT DISTINCT(n.nid), n.title, n.type, n.changed, n.uid, u.name, GREATEST(n.changed, l.last_comment_timestamp) AS last_updated, l.comment_count FROM {node} n INNER JOIN {node_comment_statistics} l ON n.nid = l.nid INNER JOIN {users} u ON n.uid = u.uid LEFT JOIN {comments} c ON n.nid = c.nid AND (c.status = %d OR c.status IS NULL) WHERE n.status = 1 AND (n.uid = %d OR c.uid = %d) ORDER BY last_updated DESC';
+    // TODO: These queries are very expensive, see http://drupal.org/node/105639
+    $sql = 'SELECT DISTINCT(n.nid), n.title, n.type, n.changed, n.uid, u.name, u.fullname, GREATEST(n.changed, l.last_comment_timestamp) AS last_updated, l.comment_count FROM {node} n INNER JOIN {node_comment_statistics} l ON n.nid = l.nid INNER JOIN {users} u ON n.uid = u.uid LEFT JOIN {comments} c ON n.nid = c.nid AND (c.status = %d OR c.status IS NULL) WHERE n.status = 1 AND (n.uid = %d OR c.uid = %d) ORDER BY last_updated DESC';
     $sql = db_rewrite_sql($sql);
     $sql_count = 'SELECT COUNT(DISTINCT(n.nid)) FROM {node} n LEFT JOIN {comments} c ON n.nid = c.nid AND (c.status = %d OR c.status IS NULL) WHERE n.status = 1 AND (n.uid = %d OR c.uid = %d)';
     $sql_count = db_rewrite_sql($sql_count);
     $result = pager_query($sql, 25, 0, $sql_count, COMMENT_PUBLISHED, $account->uid, $account->uid);
   }
   else {
-    $sql = 'SELECT DISTINCT(n.nid), n.title, n.type, n.changed, n.uid, u.name, GREATEST(n.changed, l.last_comment_timestamp) AS last_updated, l.comment_count FROM {node} n INNER JOIN {users} u ON n.uid = u.uid INNER JOIN {node_comment_statistics} l ON n.nid = l.nid WHERE n.status = 1 ORDER BY last_updated DESC';
+    $sql = 'SELECT DISTINCT(n.nid), n.title, n.type, n.changed, n.uid, u.name, u.fullname, GREATEST(n.changed, l.last_comment_timestamp) AS last_updated, l.comment_count FROM {node} n INNER JOIN {users} u ON n.uid = u.uid INNER JOIN {node_comment_statistics} l ON n.nid = l.nid WHERE n.status = 1 ORDER BY last_updated DESC';
     $sql = db_rewrite_sql($sql);
     $sql_count = 'SELECT COUNT(n.nid) FROM {node} n WHERE n.status = 1';
     $sql_count = db_rewrite_sql($sql_count);
Index: drupal-6.x-dev/modules/user/user.admin.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/user/user.admin.inc,v
retrieving revision 1.9
diff -u -p -r1.9 user.admin.inc
--- drupal-6.x-dev/modules/user/user.admin.inc	10 Nov 2007 10:15:21 -0000	1.9
+++ drupal-6.x-dev/modules/user/user.admin.inc	14 Nov 2007 10:53:38 -0000
@@ -235,6 +235,40 @@ function user_admin_settings() {
   $form['registration']['user_email_verification'] = array('#type' => 'checkbox', '#title' => t('Require e-mail verification when a visitor creates an account'), '#default_value' => variable_get('user_email_verification', TRUE), '#description' => t('If this box is checked, new users will be required to validate their e-mail address prior to logging into the site, and will be assigned a system-generated password. With it unchecked, users will be logged in immediately upon registering, and may select their own passwords during registration.'));
   $form['registration']['user_registration_help'] = array('#type' => 'textarea', '#title' => t('User registration guidelines'), '#default_value' => variable_get('user_registration_help', ''), '#description' => t('This text is displayed at the top of the user registration form and is useful for helping or instructing your users.'));
 
+  // User account settings.
+  $form['account'] = array('#type' => 'fieldset', '#title' => t('User account settings'));
+
+  $user_display_choice = array(
+    '!fullname' => t('Fullname'),
+    '!username' => t('Username'),
+    '!fullname [!username]' => t('Fullname [Username]'),
+    '[!username] !fullname' => t('[Username] Fullname'),
+    'custom' => t('Custom format'),
+  );  
+
+  $user_display_format = variable_get('user_display_format', '!fullname');
+  $form['account']['user_display_format'] = array(
+    '#prefix' => '<div class="date-container"><div class="select-container">',
+    '#suffix' => '</div>',
+    '#type' => 'select',
+    '#title' => t('Display format'),
+    '#attributes' => array('class' => 'account-format'),
+    '#default_value' => (isset($user_display_choice[$user_display_format]) ? $user_display_format : 'custom'),
+    '#options' => $user_display_choice,
+    '#description' => t('Set this to your liking. For security reasons, you might not want to show your Username in public.'),
+  );
+
+  $default_display_custom = variable_get('user_display_format_custom', (isset($user_display_choice[$user_display_format]) ? $user_display_format : ''));
+  $form['account']['user_display_format_custom'] = array(
+    '#prefix' => '<div class="custom-container">',
+    '#suffix' => '</div></div>',
+    '#type' => 'textfield',
+    '#title' => t('Custom short date format'),
+    '#attributes' => array('class' => 'custom-format'),
+    '#default_value' => $default_display_custom,
+    '#description' => t('Customize display format. Available variables are:') .' !fullname, !username.',
+  );
+
   // User e-mail settings.
   $form['email'] = array(
     '#type' => 'fieldset',
@@ -482,7 +516,17 @@ function user_admin_settings() {
     '#description' => t("This text is displayed at the picture upload form in addition to the default guidelines. It's useful for helping or instructing your users."),
   );
 
-  return system_settings_form($form);
+  $form = system_settings_form($form);
+  // We will call system_settings_form_submit() manually, so remove it for now.
+  unset($form['#submit']);
+  return $form;
+}
+
+function user_admin_settings_submit($form, &$form_state) {
+  if ($form_state['values']['user_display_format'] == 'custom') {
+    $form_state['values']['user_display_format'] = $form_state['values']['user_display_format_custom'];
+  }
+  return system_settings_form_submit($form, $form_state);
 }
 
 /**
Index: drupal-6.x-dev/modules/user/user.install
===================================================================
RCS file: /cvs/drupal/drupal/modules/user/user.install,v
retrieving revision 1.3
diff -u -p -r1.3 user.install
--- drupal-6.x-dev/modules/user/user.install	4 Nov 2007 14:33:07 -0000	1.3
+++ drupal-6.x-dev/modules/user/user.install	14 Nov 2007 10:53:38 -0000
@@ -142,6 +142,13 @@ function user_schema() {
         'default' => '',
         'description' => t('Unique user name.'),
       ),
+      'fullname' => array(
+        'type' => 'varchar',
+        'length' => 255,
+        'not null' => TRUE,
+        'default' => '',
+        'description' => t('User full name.'),
+      ),
       'pass' => array(
         'type' => 'varchar',
         'length' => 32,
@@ -282,3 +289,14 @@ function user_schema() {
   return $schema;
 }
 
+/**
+ * Add a fullname field to users table, folk from name, and convert all stored
+ * name to lower case.
+ */
+function user_update_6000() {
+  $ret = array();
+  db_add_field($ret, 'users', 'fullname', array('type' => 'varchar', 'length' => 255, 'not null' => TRUE, 'default' => '', 'description' => t('User full name.')));
+  $ret[] = update_sql('UPDATE {users} SET fullname = name');
+  $ret[] = update_sql('UPDATE {users} SET name = LOWER(name)');
+  return $ret;
+}
Index: drupal-6.x-dev/modules/user/user.js
===================================================================
RCS file: /cvs/drupal/drupal/modules/user/user.js,v
retrieving revision 1.6
diff -u -p -r1.6 user.js
--- drupal-6.x-dev/modules/user/user.js	12 Sep 2007 18:29:32 -0000	1.6
+++ drupal-6.x-dev/modules/user/user.js	14 Nov 2007 10:53:38 -0000
@@ -186,3 +186,24 @@ Drupal.behaviors.userSettings = function
   });
 };
 
+/**
+ * Show/hide custom format sections on the settings page.
+ */
+Drupal.behaviors.userAccountSettings = function(context) {
+  // Show/hide custom format depending on the select's value.
+  $('select.account-format:not(.account-processed)', context).change(function() {
+    $(this).addClass('account-processed').parents("div.date-container").children("div.custom-container")[$(this).val() == "custom" ? "show" : "hide"]();
+  });
+
+  // Attach keyup handler to custom format inputs.
+  $('input.custom-format:not(.account-processed)', context).addClass('account-processed').keyup(function() {
+    var input = $(this);
+    var url = Drupal.settings.dateTime.lookup +(Drupal.settings.dateTime.lookup.match(/\?q=/) ? "&format=" : "?format=") + Drupal.encodeURIComponent(input.val());
+    $.getJSON(url, function(data) {
+      $("div.description span", input.parent()).html(data);
+    });
+  });
+
+  // Trigger the event handler to show the form input if necessary.
+  $('select.account-format', context).trigger('change');
+};
Index: drupal-6.x-dev/modules/user/user.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/user/user.module,v
retrieving revision 1.862
diff -u -p -r1.862 user.module
--- drupal-6.x-dev/modules/user/user.module	6 Nov 2007 12:20:14 -0000	1.862
+++ drupal-6.x-dev/modules/user/user.module	14 Nov 2007 10:53:38 -0000
@@ -7,6 +7,7 @@
  */
 
 define('USERNAME_MAX_LENGTH', 60);
+define('FULLNAME_MAX_LENGTH', 255);
 define('EMAIL_MAX_LENGTH', 64);
 
 /**
@@ -144,17 +145,23 @@ function user_load($array = array()) {
   }
 
   foreach ($array as $key => $value) {
-    if ($key == 'uid' || $key == 'status') {
-      $query[] = "$key = %d";
-      $params[] = $value;
-    }
-    else if ($key == 'pass') {
-      $query[] = "pass = '%s'";
-      $params[] = md5($value);
-    }
-    else {
-      $query[]= "LOWER($key) = LOWER('%s')";
-      $params[] = $value;
+    switch ($key) {
+      case 'uid':
+      case 'status':
+        $query[] = "$key = %d";
+        $params[] = $value;
+        break;
+      case 'pass':
+        $query[] = "pass = '%s'";
+        $params[] = md5($value);
+        break;
+      case 'name':
+        $query[]= "$key = LOWER('%s')";
+        $params[] = $value;
+        break;
+      default:
+        $query[]= "LOWER($key) = LOWER('%s')";
+        $params[] = $value;
     }
   }
   $result = db_query('SELECT * FROM {users} u WHERE '. implode(' AND ', $query), $params);
@@ -216,7 +223,12 @@ function user_save($account, $array = ar
       else if ((substr($key, 0, 4) !== 'auth') && ($key != 'pass')) {
         if (in_array($key, $user_fields)) {
           // Save standard fields
-          $query .= "$key = '%s', ";
+          if ($key == 'name') {
+            $query .= "$key = LOWER('%s'), ";
+          }
+          else {
+            $query .= "$key = '%s', ";
+          }
           $v[] = $value;
         }
         else if ($key != 'roles') {
@@ -297,6 +309,11 @@ function user_save($account, $array = ar
           $values[] = $value;
           $s[] = "%d";
           break;
+        case 'name':
+          $fields[] = $key;
+          $values[] = $value;
+          $s[] = "LOWER('%s')";
+          break;
         default:
           if (substr($key, 0, 4) !== 'auth' && in_array($key, $user_fields)) {
             $fields[] = $key;
@@ -376,6 +393,14 @@ function user_validate_name($name) {
   if (strlen($name) > USERNAME_MAX_LENGTH) return t('The username %name is too long: it must be %max characters or less.', array('%name' => $name, '%max' => USERNAME_MAX_LENGTH));
 }
 
+/**
+ * Verify the syntax of the given full name.
+ */
+function user_validate_fullname($fullname) {
+  if (!strlen($fullname)) return t('You must enter a full name.');
+  if (strlen($fullname) > FULLNAME_MAX_LENGTH) return t('The full name %fullname is too long: it must be %max characters or less.', array('%fullname' => $name, '%max' => FULLNAME_MAX_LENGTH));
+}
+
 function user_validate_mail($mail) {
   if (!$mail) return t('You must enter an e-mail address.');
   if (!valid_email_address($mail)) {
@@ -546,15 +571,15 @@ function user_search($op = 'search', $ke
         $keys = preg_replace('!\*+!', '%', $keys);
         if (user_access('administer users')) {
           // Administrators can also search in the otherwise private email field.
-          $result = pager_query("SELECT name, uid, mail FROM {users} WHERE LOWER(name) LIKE LOWER('%%%s%%') OR LOWER(mail) LIKE LOWER('%%%s%%')", 15, 0, NULL, $keys, $keys);
+          $result = pager_query("SELECT uid, name, fullname, mail FROM {users} WHERE name LIKE LOWER('%%%s%%') OR LOWER(fullname) LIKE LOWER('%%%s%%') OR mail LIKE LOWER('%%%s%%')", 15, 0, NULL, $keys, $keys, $keys);
           while ($account = db_fetch_object($result)) {
-            $find[] = array('title' => $account->name .' ('. $account->mail .')', 'link' => url('user/'. $account->uid, array('absolute' => TRUE)));
+            $find[] = array('title' => theme('username', $account, array('plain' => TRUE)) .' ('. $account->mail .')', 'link' => url('user/'. $account->uid, array('absolute' => TRUE)));
           }
         }
         else {
-          $result = pager_query("SELECT name, uid FROM {users} WHERE LOWER(name) LIKE LOWER('%%%s%%')", 15, 0, NULL, $keys);
+          $result = pager_query("SELECT uid, name, fullname, FROM {users} WHERE name LIKE LOWER('%%%s%%') OR LOWER(fullname) LIKE LOWER('%%%s%%')", 15, 0, NULL, $keys, $keys);
           while ($account = db_fetch_object($result)) {
-            $find[] = array('title' => $account->name, 'link' => url('user/'. $account->uid, array('absolute' => TRUE)));
+            $find[] = array('title' => theme('username', $account, array('plain' => TRUE)), 'link' => url('user/'. $account->uid, array('absolute' => TRUE)));
           }
         }
         return $find;
@@ -706,7 +731,7 @@ function user_block($op = 'list', $delta
 
       case 1:
         if ($menu = menu_tree()) {
-           $block['subject'] = $user->uid ? check_plain($user->name) : t('Navigation');
+           $block['subject'] = $user->uid ? theme('username', $user, array('plain' => TRUE)) : t('Navigation');
            $block['content'] = $menu;
         }
         return $block;
@@ -714,7 +739,7 @@ function user_block($op = 'list', $delta
       case 2:
         if (user_access('access content')) {
           // Retrieve a list of new users who have subsequently accessed the site successfully.
-          $result = db_query_range('SELECT uid, name FROM {users} WHERE status != 0 AND access != 0 ORDER BY created DESC', 0, variable_get('user_block_whois_new_count', 5));
+          $result = db_query_range('SELECT uid, name, fullname FROM {users} WHERE status != 0 AND access != 0 ORDER BY created DESC', 0, variable_get('user_block_whois_new_count', 5));
           while ($account = db_fetch_object($result)) {
             $items[] = $account;
           }
@@ -733,7 +758,7 @@ function user_block($op = 'list', $delta
           // Perform database queries to gather online user lists.  We use s.timestamp
           // rather than u.access because it is much faster.
           $anonymous_count = sess_count($interval);
-          $authenticated_users = db_query('SELECT DISTINCT u.uid, u.name, s.timestamp FROM {users} u INNER JOIN {sessions} s ON u.uid = s.uid WHERE s.timestamp >= %d AND s.uid > 0 ORDER BY s.timestamp DESC', $interval);
+          $authenticated_users = db_query('SELECT DISTINCT u.uid, u.name, u.fullname, s.timestamp FROM {users} u INNER JOIN {sessions} s ON u.uid = s.uid WHERE s.timestamp >= %d AND s.uid > 0 ORDER BY s.timestamp DESC', $interval);
           $authenticated_count = 0;
           $max_users = variable_get('user_block_max_list_count', 10);
           $items = array();
@@ -1303,10 +1328,17 @@ function user_edit_form(&$form_state, $u
       '#title' => t('Username'),
       '#default_value' => $edit['name'],
       '#maxlength' => USERNAME_MAX_LENGTH,
-      '#description' => t('Your preferred username; punctuation is not allowed except for periods, hyphens, and underscores.'),
+      '#description' => t('Your preferred username; only lower cases are allowed; spaces are allowed; punctuation is not allowed except for periods, hyphens, and underscores.'),
       '#required' => TRUE,
     );
   }
+  $form['account']['fullname'] = array('#type' => 'textfield',
+    '#title' => t('Full name'),
+    '#default_value' => $edit['fullname'],
+    '#maxlength' => USERNAME_MAX_LENGTH,
+    '#description' => t('Specify your first and last name.'),
+    '#required' => TRUE,
+  );
   $form['account']['mail'] = array('#type' => 'textfield',
     '#title' => t('E-mail address'),
     '#default_value' => $edit['mail'],
@@ -1389,6 +1421,11 @@ function _user_edit_validate($uid, &$edi
     }
   }
 
+  // Validate the full name:
+  if ($error = user_validate_fullname($edit['fullname'])) {
+    form_set_error('fullname', $error);
+  }
+
   // Validate the e-mail address:
   if ($error = user_validate_mail($edit['mail'])) {
     form_set_error('mail', $error);
@@ -2066,7 +2103,7 @@ function user_block_user_action(&$object
   }
   db_query("UPDATE {users} SET status = 0 WHERE uid = %d", $uid);
   sess_destroy_uid($uid);
-  watchdog('action', 'Blocked user %name.', array('%name' => check_plain($user->name)));
+  watchdog('action', 'Blocked user %name.', array('%name' => theme('username', $user, array('plain' => TRUE))));
 }
 
 /**
@@ -2216,7 +2253,7 @@ function user_register() {
 
   // Remove form_group around default fields if there are no other groups.
   if (!$extra) {
-    foreach (array('name', 'mail', 'pass', 'status', 'roles', 'notify') as $key) {
+    foreach (array('name', 'fullname', 'mail', 'pass', 'status', 'roles', 'notify') as $key) {
       if (isset($form['account'][$key])) {
         $form[$key] = $form['account'][$key];
       }
Index: drupal-6.x-dev/modules/user/user.pages.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/user/user.pages.inc,v
retrieving revision 1.3
diff -u -p -r1.3 user.pages.inc
--- drupal-6.x-dev/modules/user/user.pages.inc	27 Oct 2007 14:01:12 -0000	1.3
+++ drupal-6.x-dev/modules/user/user.pages.inc	14 Nov 2007 10:53:38 -0000
@@ -12,9 +12,9 @@
 function user_autocomplete($string = '') {
   $matches = array();
   if ($string) {
-    $result = db_query_range("SELECT name FROM {users} WHERE LOWER(name) LIKE LOWER('%s%%')", $string, 0, 10);
+    $result = db_query_range("SELECT uid, name, fullname FROM {users} WHERE name LIKE LOWER('%s%%') OR LOWER(fullname) LIKE LOWER('%s%%')", $string, $string, 0, 10);
     while ($user = db_fetch_object($result)) {
-      $matches[$user->name] = check_plain($user->name);
+      $matches[$user->name] = theme('username', $user, array('plain' => TRUE));
     }
   }
 
@@ -150,7 +150,7 @@ function user_logout() {
  * Menu callback; Displays a user or user profile page.
  */
 function user_view($account) {
-  drupal_set_title(check_plain($account->name));
+  drupal_set_title(theme('username', $account, array('plain' => TRUE)));
   // Retrieve all profile fields and attach to $account->content.
   user_build_content($account);
   /**
@@ -222,7 +222,7 @@ function template_preprocess_user_profil
  * @see user_edit_submit().
  */
 function user_edit($account, $category = 'account') {
-  drupal_set_title(check_plain($account->name));
+  drupal_set_title(theme('username', $account, array('plain' => TRUE)));
   return drupal_get_form('user_profile_form', $account, $category);
 }
 
