Index: drupal-6.x-dev/install.php
===================================================================
RCS file: /cvs/drupal/drupal/install.php,v
retrieving revision 1.86
diff -u -p -r1.86 install.php
--- drupal-6.x-dev/install.php	6 Nov 2007 09:00:30 -0000	1.86
+++ drupal-6.x-dev/install.php	10 Nov 2007 04:56:23 -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/common.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/common.inc,v
retrieving revision 1.710
diff -u -p -r1.710 common.inc
--- drupal-6.x-dev/includes/common.inc	4 Nov 2007 21:24:09 -0000	1.710
+++ drupal-6.x-dev/includes/common.inc	10 Nov 2007 04:56:24 -0000
@@ -2810,6 +2810,9 @@ function drupal_common_themes() {
     'username' => array(
       'arguments' => array('object' => NULL),
     ),
+    'fullname' => array(
+      'arguments' => array('object' => NULL),
+    ),
     'progress_bar' => array(
       'arguments' => array('percent' => NULL, 'message' => NULL),
     ),
Index: drupal-6.x-dev/includes/theme.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/theme.inc,v
retrieving revision 1.393
diff -u -p -r1.393 theme.inc
--- drupal-6.x-dev/includes/theme.inc	4 Nov 2007 20:32:34 -0000	1.393
+++ drupal-6.x-dev/includes/theme.inc	10 Nov 2007 04:56:24 -0000
@@ -1660,6 +1660,54 @@ function theme_username($object) {
   return $output;
 }
 
+/**
+ * Format a user full name.
+ *
+ * @param $object
+ *   The user object to format, usually returned from user_load().
+ * @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 user full name is returned.
+ */
+function theme_fullname($object) {
+
+  if ($object->uid && $object->fullname) {
+    // Shorten the name when it is too long or it will break many tables.
+    if (drupal_strlen($object->fullname) > 20) {
+      $fullname = drupal_substr($object->fullname, 0, 15) .'...';
+    }
+    else {
+      $fullname = $object->fullname;
+    }
+
+    if (user_access('access user profiles')) {
+      $output = l($fullname, 'user/'. $object->uid, array('title' => t('View user profile.')));
+    }
+    else {
+      $output = check_plain($fullname);
+    }
+  }
+  else if ($object->fullname) {
+    // Sometimes modules display content composed by people who are
+    // 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->fullname, $object->homepage, array('rel' => 'nofollow'));
+    }
+    else {
+      $output = check_plain($object->fullname);
+    }
+
+    $output .= ' ('. t('not verified') .')';
+  }
+  else {
+    $output = variable_get('anonymous', t('Anonymous'));
+  }
+
+  return $output;
+}
+
 function theme_progress_bar($percent, $message) {
   $output = '<div id="progress" class="progress">';
   $output .= '<div class="bar"><div class="filled" style="width: '. $percent .'%"></div></div>';
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	10 Nov 2007 04:56:24 -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("@fullname's blog", array('@fullname' => $node->fullname)), '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("@fullname's blog", array('@fullname' => $node->fullname)),
         'href' => "blog/$node->uid",
-        'attributes' => array('title' => t("Read @username's latest blog entries.", array('@username' => $node->name)))
+        'attributes' => array('title' => t("Read @fullname's latest blog entries.", array('@fullname' => $node->fullname)))
       );
     }
   }
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	10 Nov 2007 04:56:24 -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("@fullname's blog", array('@fullname' => $account->fullname)));
 
   $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'] = $account->fullname ."'s blog";
   $channel['link'] = url('blog/'. $account->uid, array('absolute' => TRUE));
 
   $items = array();
Index: drupal-6.x-dev/modules/comment/comment.admin.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/comment/comment.admin.inc,v
retrieving revision 1.1
diff -u -p -r1.1 comment.admin.inc
--- drupal-6.x-dev/modules/comment/comment.admin.inc	31 Oct 2007 17:50:47 -0000	1.1
+++ drupal-6.x-dev/modules/comment/comment.admin.inc	10 Nov 2007 04:56:25 -0000
@@ -46,20 +46,22 @@ function comment_admin_overview($type = 
   $form['header'] = array('#type' => 'value', '#value' => array(
     theme('table_select_header_cell'),
     array('data' => t('Subject'), 'field' => 'subject'),
-    array('data' => t('Author'), 'field' => 'name'),
+    array('data' => t('Author'), 'field' => 'fullname'),
     array('data' => t('Posted in'), 'field' => 'node_title'),
     array('data' => t('Time'), 'field' => 'timestamp', 'sort' => 'desc'),
     array('data' => t('Operations'))
   ));
-  $result = pager_query('SELECT c.subject, c.nid, c.cid, c.comment, c.timestamp, c.status, c.name, c.homepage, u.name AS registered_name, u.uid, n.title as node_title FROM {comments} c INNER JOIN {users} u ON u.uid = c.uid INNER JOIN {node} n ON n.nid = c.nid WHERE c.status = %d'. tablesort_sql($form['header']['#value']), 50, 0, NULL, $status);
+  $result = pager_query('SELECT c.subject, c.nid, c.cid, c.comment, c.timestamp, c.status, c.name, c.homepage, u.name AS registered_name, u.fullname AS registered_fullname, u.uid, n.title as node_title FROM {comments} c INNER JOIN {users} u ON u.uid = c.uid INNER JOIN {node} n ON n.nid = c.nid WHERE c.status = %d'. tablesort_sql($form['header']['#value']), 50, 0, NULL, $status);
 
   // build a table listing the appropriate comments
   $destination = drupal_get_destination();
   while ($comment = db_fetch_object($result)) {
     $comments[$comment->cid] = '';
     $comment->name = $comment->uid ? $comment->registered_name : $comment->name;
+    $comment->fullname = $comment->uid ? $comment->registered_fullname : $comment->name;
     $form['subject'][$comment->cid] = array('#value' => l($comment->subject, 'node/'. $comment->nid, array('title' => truncate_utf8($comment->comment, 128), 'fragment' => 'comment-'. $comment->cid)));
     $form['username'][$comment->cid] = array('#value' => theme('username', $comment));
+    $form['fullname'][$comment->cid] = array('#value' => theme('fullname', $comment));
     $form['node_title'][$comment->cid] = array('#value' => l($comment->node_title, 'node/'. $comment->nid));
     $form['timestamp'][$comment->cid] = array('#value' => format_date($comment->timestamp, 'small'));
     $form['operations'][$comment->cid] = array('#value' => l(t('edit'), 'comment/edit/'. $comment->cid, array('query' => $destination)));
@@ -119,7 +121,7 @@ function theme_comment_admin_overview($f
       $row = array();
       $row[] = drupal_render($form['comments'][$key]);
       $row[] = drupal_render($form['subject'][$key]);
-      $row[] = drupal_render($form['username'][$key]);
+      $row[] = drupal_render($form['fullname'][$key]);
       $row[] = drupal_render($form['node_title'][$key]);
       $row[] = drupal_render($form['timestamp'][$key]);
       $row[] = drupal_render($form['operations'][$key]);
Index: drupal-6.x-dev/modules/comment/comment.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/comment/comment.module,v
retrieving revision 1.601
diff -u -p -r1.601 comment.module
--- drupal-6.x-dev/modules/comment/comment.module	9 Nov 2007 07:46:10 -0000	1.601
+++ drupal-6.x-dev/modules/comment/comment.module	10 Nov 2007 04:56:25 -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) {
@@ -1129,7 +1131,7 @@ function comment_validate($edit) {
     $node = node_load($edit['nid']);
     if (variable_get('comment_anonymous_'. $node->type, COMMENT_ANONYMOUS_MAYNOT_CONTACT) > COMMENT_ANONYMOUS_MAYNOT_CONTACT) {
       if ($edit['name']) {
-        $taken = db_result(db_query("SELECT COUNT(uid) FROM {users} WHERE LOWER(name) = '%s'", $edit['name']));
+        $taken = db_result(db_query("SELECT COUNT(uid) FROM {users} WHERE name = '%s'", drupal_strtolower($edit['name'])));
 
         if ($taken != 0) {
           form_set_error('name', t('The name you used belongs to a registered user.'));
@@ -1262,7 +1264,7 @@ function comment_form(&$form_state, $edi
 
     }
     else {
-      $form['_author'] = array('#type' => 'item', '#title' => t('Your name'), '#value' => theme('username', $user)
+      $form['_author'] = array('#type' => 'item', '#title' => t('Your name'), '#value' => theme('fullname', $user)
       );
       $form['author'] = array('#type' => 'value', '#value' => $user->name);
     }
@@ -1364,6 +1366,7 @@ function comment_form_add_preview($form,
     if (!empty($account)) {
       $comment->uid = $account->uid;
       $comment->name = check_plain($account->name);
+      $comment->fullname = check_plain($account->fullname);      
     }
     elseif (empty($comment->name)) {
       $comment->name = variable_get('anonymous', t('Anonymous'));
@@ -1381,9 +1384,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 {
@@ -1546,7 +1550,7 @@ function comment_controls_submit($form, 
 function template_preprocess_comment(&$variables) {
   $comment = $variables['comment'];
   $node = $variables['node'];
-  $variables['author']    = theme('username', $comment);
+  $variables['author']    = theme('fullname', $comment);
   $variables['content']   = $comment->comment;
   $variables['date']      = format_date($comment->timestamp);
   $variables['links']     = isset($variables['links']) ? theme('links', $variables['links']) : '';
@@ -1569,7 +1573,7 @@ function template_preprocess_comment(&$v
  */
 function template_preprocess_comment_folded(&$variables) {
   $comment = $variables['comment'];
-  $variables['author'] = theme('username', $comment);
+  $variables['author'] = theme('fullname', $comment);
   $variables['date']   = format_date($comment->timestamp);
   $variables['new']    = $comment->new ? t('new') : '';
   $variables['title']  = l($comment->subject, comment_node_url() .'/'. $comment->cid, array('fragment' => "comment-$comment->cid"));
@@ -1636,9 +1640,9 @@ function template_preprocess_comment_wra
  * Make the submitted variable themable
  */
 function theme_comment_submitted($comment) {
-  return t('Submitted by !username on @datetime.',
+  return t('Submitted by !fullname on @datetime.',
     array(
-      '!username' => theme('username', $comment),
+      '!fullname' => theme('fullname', $comment),
       '@datetime' => format_date($comment->timestamp)
     ));
 }
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	10 Nov 2007 04:56:25 -0000
@@ -37,12 +37,12 @@ function contact_mail_page() {
   }
 
   if (count($categories) > 0) {
-    $form['#token'] = $user->uid ? $user->name . $user->mail : '';
+    $form['#token'] = $user->uid ? $user->fullname . $user->mail : '';
     $form['contact_information'] = array('#value' => filter_xss_admin(variable_get('contact_form_information', t('You can leave a message using the contact form below.'))));
     $form['name'] = array('#type' => 'textfield',
       '#title' => t('Your name'),
       '#maxlength' => 255,
-      '#default_value' => $user->uid ? $user->name : '',
+      '#default_value' => $user->uid ? $user->fullname : '',
       '#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(check_plain($account->fullname));
     $output = drupal_get_form('contact_mail_user', $account);
   }
 
@@ -169,15 +169,15 @@ function contact_user_page($account) {
 
 function contact_mail_user(&$form_state, $recipient) {
   global $user;
-  $form['#token'] = $user->name . $user->mail;
+  $form['#token'] = $user->fullname . $user->mail;
   $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' => check_plain($user->fullname) .' &lt;'. check_plain($user->mail) .'&gt;',
   );
   $form['to'] = array('#type' => 'item',
     '#title' => t('To'),
-    '#value' => check_plain($recipient->name),
+    '#value' => check_plain($recipient->fullname),
   );
   $form['subject'] = array('#type' => 'textfield',
     '#title' => t('Subject'),
Index: drupal-6.x-dev/modules/node/node.admin.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/node/node.admin.inc,v
retrieving revision 1.8
diff -u -p -r1.8 node.admin.inc
--- drupal-6.x-dev/modules/node/node.admin.inc	24 Oct 2007 14:38:38 -0000	1.8
+++ drupal-6.x-dev/modules/node/node.admin.inc	10 Nov 2007 04:56:25 -0000
@@ -356,7 +356,7 @@ function node_admin_nodes() {
 
   $filter = node_build_filter_query();
 
-  $result = pager_query(db_rewrite_sql('SELECT n.*, u.name FROM {node} n '. $filter['join'] .' INNER JOIN {users} u ON n.uid = u.uid '. $filter['where'] .' ORDER BY n.changed DESC'), 50, 0, NULL, $filter['args']);
+  $result = pager_query(db_rewrite_sql('SELECT n.*, u.name, u.fullname FROM {node} n '. $filter['join'] .' INNER JOIN {users} u ON n.uid = u.uid '. $filter['where'] .' ORDER BY n.changed DESC'), 50, 0, NULL, $filter['args']);
 
   // Enable language column if locale is enabled or if we have any node with language
   $count = db_result(db_query("SELECT COUNT(*) FROM {node} n WHERE language != ''"));
@@ -384,7 +384,7 @@ function node_admin_nodes() {
     $nodes[$node->nid] = '';
     $form['title'][$node->nid] = array('#value' => l($node->title, 'node/'. $node->nid) .' '. theme('mark', node_mark($node->nid, $node->changed)));
     $form['name'][$node->nid] =  array('#value' => node_get_types('name', $node));
-    $form['username'][$node->nid] = array('#value' => theme('username', $node));
+    $form['fullname'][$node->nid] = array('#value' => theme('fullname', $node));
     $form['status'][$node->nid] =  array('#value' =>  ($node->status ? t('published') : t('not published')));
     if ($multilanguage) {
       $form['language'][$node->nid] = array('#value' => empty($node->language) ? t('Language neutral') : module_invoke('locale', 'language_name', $node->language));
@@ -419,7 +419,7 @@ function theme_node_admin_nodes($form) {
       $row[] = drupal_render($form['nodes'][$key]);
       $row[] = drupal_render($form['title'][$key]);
       $row[] = drupal_render($form['name'][$key]);
-      $row[] = drupal_render($form['username'][$key]);
+      $row[] = drupal_render($form['fullname'][$key]);
       $row[] = drupal_render($form['status'][$key]);
       if (isset($form['language'])) {
         $row[] = drupal_render($form['language'][$key]);
Index: drupal-6.x-dev/modules/node/node.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/node/node.module,v
retrieving revision 1.898
diff -u -p -r1.898 node.module
--- drupal-6.x-dev/modules/node/node.module	5 Nov 2007 15:14:54 -0000	1.898
+++ drupal-6.x-dev/modules/node/node.module	10 Nov 2007 04:56:26 -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);
@@ -2242,9 +2242,9 @@ function node_forms() {
  * Format the "Submitted by username on date/time" for each node
  */
 function theme_node_submitted($node) {
-  return t('Submitted by !username on @datetime',
+  return t('Submitted by !fullname on @datetime',
     array(
-      '!username' => theme('username', $node),
+      '!fullname' => theme('fullname', $node),
       '@datetime' => format_date($node->created),
     ));
 }
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	10 Nov 2007 04:56:26 -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(check_plain($account->fullname));
   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/system/system.install
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.install,v
retrieving revision 1.173
diff -u -p -r1.173 system.install
--- drupal-6.x-dev/modules/system/system.install	7 Nov 2007 09:55:20 -0000	1.173
+++ drupal-6.x-dev/modules/system/system.install	10 Nov 2007 04:56:26 -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	10 Nov 2007 04:56:27 -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(check_plain($account->fullname));
     }
-  // 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);
@@ -52,7 +52,7 @@ function tracker_page($account = NULL, $
     $rows[] = array(
       node_get_types('name', $node->type),
       l($node->title, "node/$node->nid") .' '. theme('mark', node_mark($node->nid, $node->changed)),
-      theme('username', $node),
+      theme('fullname', $node),
       array('class' => 'replies', 'data' => $comments),
       t('!time ago', array('!time' => format_interval(time() - $node->last_updated)))
     );
Index: drupal-6.x-dev/modules/user/user.admin.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/user/user.admin.inc,v
retrieving revision 1.8
diff -u -p -r1.8 user.admin.inc
--- drupal-6.x-dev/modules/user/user.admin.inc	27 Oct 2007 15:28:43 -0000	1.8
+++ drupal-6.x-dev/modules/user/user.admin.inc	10 Nov 2007 04:56:27 -0000
@@ -132,6 +132,7 @@ function user_admin_account() {
   $header = array(
     array(),
     array('data' => t('Username'), 'field' => 'u.name'),
+    array('data' => t('Full name'), 'field' => 'u.fullname'),
     array('data' => t('Status'), 'field' => 'u.status'),
     t('Roles'),
     array('data' => t('Member for'), 'field' => 'u.created', 'sort' => 'desc'),
@@ -139,7 +140,7 @@ function user_admin_account() {
     t('Operations')
   );
 
-  $sql = 'SELECT DISTINCT u.uid, u.name, u.status, u.created, u.access FROM {users} u LEFT JOIN {users_roles} ur ON u.uid = ur.uid '. $filter['join'] .' WHERE u.uid != 0 '. $filter['where'];
+  $sql = 'SELECT DISTINCT u.uid, u.name, u.fullname, u.status, u.created, u.access FROM {users} u LEFT JOIN {users_roles} ur ON u.uid = ur.uid '. $filter['join'] .' WHERE u.uid != 0 '. $filter['where'];
   $sql .= tablesort_sql($header);
   $result = pager_query($sql, 50, 0, NULL, $filter['args']);
 
@@ -171,6 +172,7 @@ function user_admin_account() {
   while ($account = db_fetch_object($result)) {
     $accounts[$account->uid] = '';
     $form['name'][$account->uid] = array('#value' => theme('username', $account));
+    $form['fullname'][$account->uid] = array('#value' => theme('fullname', $account));
     $form['status'][$account->uid] =  array('#value' => $status[$account->status]);
     $users_roles = array();
     $roles_result = db_query('SELECT rid FROM {users_roles} WHERE uid = %d', $account->uid);
@@ -912,6 +914,7 @@ function theme_user_admin_account($form)
   $header = array(
     theme('table_select_header_cell'),
     array('data' => t('Username'), 'field' => 'u.name'),
+    array('data' => t('Full name'), 'field' => 'u.fullname'),
     array('data' => t('Status'), 'field' => 'u.status'),
     t('Roles'),
     array('data' => t('Member for'), 'field' => 'u.created', 'sort' => 'desc'),
@@ -925,6 +928,7 @@ function theme_user_admin_account($form)
       $rows[] = array(
         drupal_render($form['accounts'][$key]),
         drupal_render($form['name'][$key]),
+        drupal_render($form['fullname'][$key]),
         drupal_render($form['status'][$key]),
         drupal_render($form['roles'][$key]),
         drupal_render($form['member_for'][$key]),
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	10 Nov 2007 04:56:27 -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.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	10 Nov 2007 04:56:27 -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 = '%s'";
+        $params[] = drupal_strtolower($value);
+        break;
+      default:
+        $query[]= "LOWER($key) = LOWER('%s')";
+        $params[] = $value;
     }
   }
   $result = db_query('SELECT * FROM {users} u WHERE '. implode(' AND ', $query), $params);
@@ -217,7 +224,12 @@ function user_save($account, $array = ar
         if (in_array($key, $user_fields)) {
           // Save standard fields
           $query .= "$key = '%s', ";
-          $v[] = $value;
+          if ($key == 'name') {
+            $v[] = drupal_strtolower($value);
+          }
+          else {
+            $v[] = $value;
+          }
         }
         else if ($key != 'roles') {
           // Roles is a special case: it used below.
@@ -297,6 +309,11 @@ function user_save($account, $array = ar
           $values[] = $value;
           $s[] = "%d";
           break;
+        case 'name':
+          $fields[] = $key;
+          $values[] = drupal_strtolower($value);
+          $s[] = "'%s'";
+          break;
         default:
           if (substr($key, 0, 4) !== 'auth' && in_array($key, $user_fields)) {
             $fields[] = $key;
@@ -371,11 +388,20 @@ function user_validate_name($name) {
                    '\x{0}]/u',               // NULL byte
                    $name)) {
     return t('The username contains an illegal character.');
-  }
+                   }
+  if ($name != drupal_strtolower($name)) return t('The username contains an illegal character.');
   if (strpos($name, '@') !== FALSE && !eregi('@([0-9a-z](-?[0-9a-z])*.)+[a-z]{2}([zmuvtg]|fo|me)?$', $name)) return t('The username is not a valid authentication ID.');
   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)) {
@@ -489,7 +515,7 @@ function user_access($string, $account =
  * @return boolean TRUE for blocked users, FALSE for active
  */
 function user_is_blocked($name) {
-  $deny  = db_fetch_object(db_query("SELECT name FROM {users} WHERE status = 0 AND name = LOWER('%s')", $name));
+  $deny  = db_fetch_object(db_query("SELECT name FROM {users} WHERE status = 0 AND name = '%s'", $name));
 
   return $deny;
 }
@@ -546,13 +572,13 @@ 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 name, uid, mail FROM {users} WHERE name LIKE '%%%s%%' OR mail LIKE '%%%s%%'", 15, 0, NULL, drupal_strtolower($keys), drupal_strtolower($keys));
           while ($account = db_fetch_object($result)) {
             $find[] = array('title' => $account->name .' ('. $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 name, uid FROM {users} WHERE name LIKE '%%%s%%'", 15, 0, NULL, drupal_strtolower($keys));
           while ($account = db_fetch_object($result)) {
             $find[] = array('title' => $account->name, 'link' => url('user/'. $account->uid, array('absolute' => TRUE)));
           }
@@ -706,7 +732,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 ? check_plain($user->fullname) : t('Navigation');
            $block['content'] = $menu;
         }
         return $block;
@@ -714,7 +740,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 +759,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();
@@ -810,7 +836,7 @@ function template_preprocess_user_pictur
 function theme_user_list($users, $title = NULL) {
   if (!empty($users)) {
     foreach ($users as $user) {
-      $items[] = theme('username', $user);
+      $items[] = theme('fullname', $user);
     }
   }
   return theme('item_list', $items, $title);
@@ -1303,10 +1329,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'],
@@ -1381,7 +1414,7 @@ function _user_edit_validate($uid, &$edi
     if ($error = user_validate_name($edit['name'])) {
       form_set_error('name', $error);
     }
-    else if (db_result(db_query("SELECT COUNT(*) FROM {users} WHERE uid != %d AND LOWER(name) = LOWER('%s')", $uid, $edit['name'])) > 0) {
+    else if (db_result(db_query("SELECT COUNT(*) FROM {users} WHERE uid != %d AND name = '%s'", $uid, drupal_strtolower($edit['name']))) > 0) {
       form_set_error('name', t('The name %name is already taken.', array('%name' => $edit['name'])));
     }
     else if (drupal_is_denied('user', $edit['name'])) {
@@ -1389,11 +1422,16 @@ 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);
   }
-  else if (db_result(db_query("SELECT COUNT(*) FROM {users} WHERE uid != %d AND LOWER(mail) = LOWER('%s')", $uid, $edit['mail'])) > 0) {
+  else if (db_result(db_query("SELECT COUNT(*) FROM {users} WHERE uid != %d AND mail = '%s'", $uid, drupal_strtolower($edit['mail']))) > 0) {
     form_set_error('mail', t('The e-mail address %email is already registered. <a href="@password">Have you forgotten your password?</a>', array('%email' => $edit['mail'], '@password' => url('user/password'))));
   }
   else if (drupal_is_denied('mail', $edit['mail'])) {
@@ -2216,7 +2254,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	10 Nov 2007 04:56:28 -0000
@@ -12,7 +12,7 @@
 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 name FROM {users} WHERE name LIKE '%s%%'", drupal_strtolower($string), 0, 10);
     while ($user = db_fetch_object($result)) {
       $matches[$user->name] = check_plain($user->name);
     }
@@ -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(check_plain($account->fullname));
   // 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(check_plain($account->fullname));
   return drupal_get_form('user_profile_form', $account, $category);
 }
 
Index: drupal-6.x-dev/themes/garland/template.php
===================================================================
RCS file: /cvs/drupal/drupal/themes/garland/template.php,v
retrieving revision 1.16
diff -u -p -r1.16 template.php
--- drupal-6.x-dev/themes/garland/template.php	11 Oct 2007 09:51:29 -0000	1.16
+++ drupal-6.x-dev/themes/garland/template.php	10 Nov 2007 04:56:28 -0000
@@ -72,17 +72,17 @@ function phptemplate_menu_local_tasks() 
 }
 
 function phptemplate_comment_submitted($comment) {
-  return t('!datetime — !username',
+  return t('!datetime — !fullname',
     array(
-      '!username' => theme('username', $comment),
+      '!fullname' => theme('fullname', $comment),
       '!datetime' => format_date($comment->timestamp)
     ));
 }
 
 function phptemplate_node_submitted($node) {
-  return t('!datetime — !username',
+  return t('!datetime — !fullname',
     array(
-      '!username' => theme('username', $node),
+      '!fullname' => theme('fullname', $node),
       '!datetime' => format_date($node->created),
     ));
 }
