Logs: Fully integrated an author_uid column. Logs are now linked by user ID instead of just username, so they survive username changes better. Database is changed. Fixes issue 6.
authorDan
Fri, 18 Dec 2009 19:06:49 -0500
changeset 1175 1e2c9819ede3
parent 1174 def792dd9b1b
child 1176 5c98b9f181f0
Logs: Fully integrated an author_uid column. Logs are now linked by user ID instead of just username, so they survive username changes better. Database is changed. Fixes issue 6.
ajax.php
includes/dbal.php
includes/log.php
includes/pageprocess.php
includes/pageutils.php
includes/sessions.php
install/includes/payload.php
install/schemas/mysql_stage2.sql
install/schemas/postgresql_stage2.sql
install/schemas/upgrade/1.1.6-1.1.7-mysql.sql
install/schemas/upgrade/1.1.6-1.1.7-postgresql.sql
plugins/SpecialAdmin.php
plugins/SpecialUpdownload.php
plugins/admin/SecurityLog.php
plugins/admin/UserManager.php
--- a/ajax.php	Fri Dec 18 09:39:18 2009 -0500
+++ b/ajax.php	Fri Dec 18 19:06:49 2009 -0500
@@ -248,13 +248,14 @@
             else
             {
               // Save the draft
-              $q = $db->sql_query('INSERT INTO ' . table_prefix . 'logs ( log_type, action, page_id, namespace, author, edit_summary, page_text, is_draft, time_id, page_format )
+              $q = $db->sql_query('INSERT INTO ' . table_prefix . 'logs ( log_type, action, page_id, namespace, author, author_uid, edit_summary, page_text, is_draft, time_id, page_format )
                                      VALUES (
                                        \'page\',
                                        \'edit\',
                                        \'' . $db->escape($paths->page_id) . '\',
                                        \'' . $db->escape($paths->namespace) . '\',
                                        \'' . $db->escape($session->username) . '\',
+                                       ' . $session->user_id . ',
                                        \'' . $db->escape($request['summary']) . '\',
                                        \'' . $db->escape($src) . '\',
                                        1,
--- a/includes/dbal.php	Fri Dec 18 09:39:18 2009 -0500
+++ b/includes/dbal.php	Fri Dec 18 19:06:49 2009 -0500
@@ -411,13 +411,19 @@
   {
     global $session;
     if ( is_object($session) && defined('ENANO_MAINSTREAM') )
+    {
       $username = $session->username;
+      $user_id = $session->user_id;
+    }
     else
+    {
       $username = 'Unavailable';
+      $user_id = 1;
+    } 
     
     $query = $this->escape($query);
-    $q = $this->sql_query('INSERT INTO '.table_prefix.'logs(log_type,     action,         time_id,    date_string, page_text,      author,            edit_summary)
-                                                     VALUES(\'security\', \'sql_inject\', '.time().', \'\',        \''.$query.'\', \''.$username.'\', \''.$_SERVER['REMOTE_ADDR'].'\');');
+    $q = $this->sql_query('INSERT INTO '.table_prefix.'logs(log_type,     action,         time_id,    date_string, page_text,      author,            author_uid,       edit_summary)
+                                                     VALUES(\'security\', \'sql_inject\', '.time().', \'\',        \''.$query.'\', \''.$username.'\', ' . $user_id . ', \''.$_SERVER['REMOTE_ADDR'].'\');');
   }
   
   /**
@@ -951,13 +957,20 @@
   function report_query($query)
   {
     global $session;
-    if(is_object($session) && defined('ENANO_MAINSTREAM'))
+    if ( is_object($session) && defined('ENANO_MAINSTREAM') )
+    {
       $username = $session->username;
+      $user_id = $session->user_id;
+    }
     else
+    {
       $username = 'Unavailable';
+      $user_id = 1;
+    } 
+    
     $query = $this->escape($query);
-    $q = $this->sql_query('INSERT INTO '.table_prefix.'logs(log_type,     action,         time_id,    date_string, page_text,      author,            edit_summary)
-                                                     VALUES(\'security\', \'sql_inject\', '.time().', \'\',        \''.$query.'\', \''.$username.'\', \''.$_SERVER['REMOTE_ADDR'].'\');');
+    $q = $this->sql_query('INSERT INTO '.table_prefix.'logs(log_type,     action,         time_id,    date_string, page_text,      author,            author_uid,       edit_summary)
+                                                     VALUES(\'security\', \'sql_inject\', '.time().', \'\',        \''.$query.'\', \''.$username.'\', ' . $user_id . ', \''.$_SERVER['REMOTE_ADDR'].'\');');
   }
   
   /**
--- a/includes/log.php	Fri Dec 18 09:39:18 2009 -0500
+++ b/includes/log.php	Fri Dec 18 19:06:49 2009 -0500
@@ -160,8 +160,10 @@
       $limit = ( $page_size > 0 ) ? "\n  LIMIT $page_size OFFSET $offset" : '';
     else
       $limit = ( $page_size > 0 ) ? "\n  LIMIT $offset, $page_size" : '';
-    $columns = ( $just_page_count ) ? 'COUNT(*)' : 'log_id, action, page_id, namespace, CHAR_LENGTH(page_text) AS revision_size, author, time_id, edit_summary, minor_edit';
+    $columns = ( $just_page_count ) ? 'COUNT(*)' : 'log_id, action, page_id, namespace, CHAR_LENGTH(page_text) AS revision_size, author, author_uid, u.username, time_id, edit_summary, minor_edit';
     $sql = 'SELECT ' . $columns . ' FROM ' . table_prefix . "logs AS l\n"
+         . "  LEFT JOIN " . table_prefix . "users AS u\n"
+         . "    ON ( u.user_id = l.author_uid OR u.user_id IS NULL )\n"
          . "  WHERE log_type = 'page' AND is_draft != 1$where_extra\n"
          . "  GROUP BY log_id, action, page_id, namespace, page_text, author, time_id, edit_summary, minor_edit\n"
          . "  ORDER BY time_id DESC $limit;";
@@ -386,14 +388,15 @@
     }
     
     // link to userpage
-    $cls = ( isPage($paths->nslist['User'] . $row['author']) ) ? '' : ' class="wikilink-nonexistent"';
-    $rank_info = $session->get_user_rank($row['author']);
-    $html .= '<a style="' . $rank_info['rank_style'] . '" href="' . makeUrlNS('User', sanitize_page_id($row['author']), false, true) . '"' . $cls . '>' . htmlspecialchars($row['author']) . '</a> ';
+    $real_username = $row['author_uid'] > 1 && !empty($row['username']) ? $row['username'] : $row['author'];
+    $cls = ( isPage($paths->nslist['User'] . $real_username) ) ? '' : ' class="wikilink-nonexistent"';
+    $rank_info = $session->get_user_rank($row['author_uid']);
+    $html .= '<a style="' . $rank_info['rank_style'] . '" href="' . makeUrlNS('User', sanitize_page_id($real_username), false, true) . '"' . $cls . '>' . htmlspecialchars($real_username) . '</a> ';
     $html .= '(';
-    $html .= '<a href="' . makeUrlNS('Special', 'PrivateMessages/Compose/To/' . sanitize_page_id($row['author']), false, true) . '">';
+    $html .= '<a href="' . makeUrlNS('Special', 'PrivateMessages/Compose/To/' . sanitize_page_id($real_username), false, true) . '">';
     $html .= $lang->get('pagetools_rc_btn_pm');
     $html .= '</a>, ';
-    $html .= '<a href="' . makeUrlNS('User', sanitize_page_id($row['author']), false, true) . '#do:comments">';
+    $html .= '<a href="' . makeUrlNS('User', sanitize_page_id($real_username), false, true) . '#do:comments">';
     $html .= $lang->get('pagetools_rc_btn_usertalk');
     $html .= '</a>';
     $html .= ') . . ';
--- a/includes/pageprocess.php	Fri Dec 18 09:39:18 2009 -0500
+++ b/includes/pageprocess.php	Fri Dec 18 19:06:49 2009 -0500
@@ -459,8 +459,8 @@
     $date_string = enano_date(ED_DATE | ED_TIME);
     
     // Insert log entry
-    $sql = 'INSERT INTO ' . table_prefix . "logs ( time_id, date_string, log_type, action, page_id, namespace, author, page_text, edit_summary, minor_edit, page_format )\n"
-         . "  VALUES ( $time, '$date_string', 'page', 'edit', '{$this->page_id}', '{$this->namespace}', '$author', '$text', '$edit_summary', $minor_edit, '$page_format' );";
+    $sql = 'INSERT INTO ' . table_prefix . "logs ( time_id, date_string, log_type, action, page_id, namespace, author, author_uid, page_text, edit_summary, minor_edit, page_format )\n"
+         . "  VALUES ( $time, '$date_string', 'page', 'edit', '{$this->page_id}', '{$this->namespace}', '$author', $session->user_id, '$text', '$edit_summary', $minor_edit, '$page_format' );";
     if ( !$db->sql_query($sql) )
     {
       $this->raise_error($db->get_error());
@@ -588,9 +588,9 @@
       $db->_die('PageProcessor page creation - text stage');
     
     // Query 3: Log entry
-    $db->sql_query('INSERT INTO ' . table_prefix."logs(time_id, date_string, log_type, action, author, page_id, namespace)\n"
+    $db->sql_query('INSERT INTO ' . table_prefix."logs(time_id, date_string, log_type, action, author, author_uid, page_id, namespace)\n"
                    . "  VALUES ( " . time() . ", 'DEPRECATED', 'page', 'create', \n"
-                   . "          '" . $db->escape($session->username) . "', '" . $db->escape($this->page_id) . "', '" . $this->namespace . "');");
+                   . "          '" . $db->escape($session->username) . "', $session->user_id, '" . $db->escape($this->page_id) . "', '" . $this->namespace . "');");
     if ( !$q )
       $db->_die('PageProcessor page creation - logging stage');
     
@@ -1132,7 +1132,7 @@
     global $email;
     
     // Log it for crying out loud
-    $q = $db->sql_query('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,date_string,author,edit_summary,page_text) VALUES(\'security\', \'illegal_page\', '.time().', \'DEPRECATED\', \''.$db->escape($session->username).'\', \''.$db->escape($_SERVER['REMOTE_ADDR']).'\', \'' . $db->escape(serialize(array($this->page_id, $this->namespace))) . '\')');
+    $q = $db->sql_query('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,date_string,author,author_uid,edit_summary,page_text) VALUES(\'security\', \'illegal_page\', '.time().', \'DEPRECATED\', \''.$db->escape($session->username).'\', ' . $session->user_id . ', \''.$db->escape($_SERVER['REMOTE_ADDR']).'\', \'' . $db->escape(serialize(array($this->page_id, $this->namespace))) . '\')');
     
     $ob = '';
     //$template->tpl_strings['PAGE_NAME'] = 'Access denied';
--- a/includes/pageutils.php	Fri Dec 18 09:39:18 2009 -0500
+++ b/includes/pageutils.php	Fri Dec 18 19:06:49 2009 -0500
@@ -204,7 +204,7 @@
     
     $qa = $db->sql_query('INSERT INTO ' . table_prefix.'pages(name,urlname,namespace,visible,protected,delvote_ips) VALUES(\'' . $db->escape($name) . '\', \'' . $db->escape($page_id) . '\', \'' . $namespace . '\', '. ( $visible ? '1' : '0' ) .', ' . $prot . ', \'' . $db->escape(serialize($ips)) . '\');');
     $qb = $db->sql_query('INSERT INTO ' . table_prefix.'page_text(page_id,namespace) VALUES(\'' . $db->escape($page_id) . '\', \'' . $namespace . '\');');
-    $qc = $db->sql_query('INSERT INTO ' . table_prefix.'logs(time_id,date_string,log_type,action,author,page_id,namespace) VALUES('.time().', \'DEPRECATED\', \'page\', \'create\', \'' . $session->username . '\', \'' . $db->escape($page_id) . '\', \'' . $namespace . '\');');
+    $qc = $db->sql_query('INSERT INTO ' . table_prefix.'logs(time_id,date_string,log_type,action,author,author_uid,page_id,namespace) VALUES('.time().', \'DEPRECATED\', \'page\', \'create\', \'' . $session->username . '\', ' . $session->user_id . ', \'' . $db->escape($page_id) . '\', \'' . $namespace . '\');');
     
     if($qa && $qb && $qc)
       return 'good';
@@ -269,7 +269,11 @@
     $wiki = ( ( $cdata['wiki_mode'] == 2 && getConfig('wiki_mode') == '1') || $cdata['wiki_mode'] == 1) ? true : false;
     $prot = ( ( $cdata['protected'] == 2 && $session->user_logged_in && $session->reg_time + 60*60*24*4 < time() ) || $cdata['protected'] == 1) ? true : false;
     
-    $q = 'SELECT log_id,time_id,date_string,page_id,namespace,author,edit_summary,minor_edit FROM ' . table_prefix.'logs WHERE log_type=\'page\' AND action=\'edit\' AND page_id=\'' . $page_id . '\' AND namespace=\'' . $namespace . '\' AND is_draft != 1 ORDER BY time_id DESC;';
+    $q = 'SELECT log_id,time_id,date_string,page_id,namespace,author,author_uid,u.username,edit_summary,minor_edit FROM ' . table_prefix . "logs AS l\n"
+       . "  LEFT JOIN " . table_prefix . "users AS u\n"
+       . "    ON ( u.user_id = l.author_uid OR u.user_id IS NULL )\n"
+       . "  WHERE log_type='page' AND action='edit' AND page_id='$page_id' AND namespace='$namespace' AND is_draft != 1 ORDER BY time_id DESC;";
+    
     if ( !($q = $db->sql_query($q)) )
       $db->_die('The history data for the page "' . $paths->cpage['name'] . '" could not be selected.');
     
@@ -334,7 +338,9 @@
         echo '<td class="' . $cls . '" style="white-space: nowrap;">' . enano_date(ED_DATE | ED_TIME, intval($r['time_id'])) . '</td class="' . $cls . '">'."\n";
         
         // User
-        if ( $session->get_permissions('mod_misc') && is_valid_ip($r['author']) )
+        $real_username = $r['author_uid'] > 1 && !empty($r['username']) ? $r['username'] : $r['author'];
+        $rank_info = $session->get_user_rank($r['author_uid']);
+        if ( $session->get_permissions('mod_misc') && is_valid_ip($r['author']) && $r['author_uid'] == 1 )
         {
           $rc = ' style="cursor: pointer;" title="' . $lang->get('history_tip_rdns') . '" onclick="ajaxReverseDNS(this, \'' . $r['author'] . '\');"';
         }
@@ -342,12 +348,12 @@
         {
           $rc = '';
         }
-        echo '<td class="' . $cls . '"' . $rc . '><a href="'.makeUrlNS('User', sanitize_page_id($r['author'])).'" ';
-        if ( !isPage($paths->nslist['User'] . sanitize_page_id($r['author'])) )
+        echo '<td class="' . $cls . '"' . $rc . '><a href="'.makeUrlNS('User', sanitize_page_id($real_username)).'" ';
+        if ( !isPage($paths->nslist['User'] . sanitize_page_id($real_username)) )
         {
           echo 'class="wikilink-nonexistent"';
         }
-        echo '>' . $r['author'] . '</a></td class="' . $cls . '">'."\n";
+        echo 'style="' . $rank_info['rank_style'] . '">' . htmlspecialchars($real_username) . '</a></td class="' . $cls . '">'."\n";
         
         // Edit summary
         if ( $r['edit_summary'] == 'Automatic backup created when logs were purged' )
@@ -377,7 +383,12 @@
     }
     $db->free_result();
     echo '<h3>' . $lang->get('history_heading_other') . '</h3>';
-    $sql = 'SELECT log_id,time_id,action,date_string,page_id,namespace,author,edit_summary,minor_edit FROM ' . table_prefix.'logs WHERE log_type=\'page\' AND action!=\'edit\' AND page_id=\'' . $paths->page_id . '\' AND namespace=\'' . $paths->namespace . '\' ORDER BY time_id DESC;';
+    
+    $sql = 'SELECT log_id,action,time_id,date_string,page_id,namespace,author,author_uid,u.username,edit_summary,minor_edit FROM ' . table_prefix . "logs AS l\n"
+         . "  LEFT JOIN " . table_prefix . "users AS u\n"
+         . "    ON ( u.user_id = l.author_uid OR u.user_id IS NULL )\n"
+         . "  WHERE log_type='page' AND action!='edit' AND page_id='$page_id' AND namespace='$namespace' AND is_draft != 1 ORDER BY time_id DESC;";
+    
     if ( !( $q = $db->sql_query($sql)) )
     {
       $db->_die('The history data for the page "' . htmlspecialchars($paths->cpage['name']) . '" could not be selected.');
@@ -410,9 +421,22 @@
         echo '<td class="' . $cls . '">' . enano_date(ED_DATE | ED_TIME, intval($r['time_id'])) . '</td class="' . $cls . '">';
         
         // User
-        echo '<td class="' . $cls . '"><a href="'.makeUrlNS('User', sanitize_page_id($r['author'])).'" ';
-        if(!isPage($paths->nslist['User'] . sanitize_page_id($r['author']))) echo 'class="wikilink-nonexistent"';
-        echo '>' . $r['author'] . '</a></td class="' . $cls . '">';
+        $real_username = $r['author_uid'] > 1 && !empty($r['username']) ? $r['username'] : $r['author'];
+        $rank_info = $session->get_user_rank($r['author_uid']);
+        if ( $session->get_permissions('mod_misc') && is_valid_ip($r['author']) && $r['author_uid'] == 1 )
+        {
+          $rc = ' style="cursor: pointer;" title="' . $lang->get('history_tip_rdns') . '" onclick="ajaxReverseDNS(this, \'' . $r['author'] . '\');"';
+        }
+        else
+        {
+          $rc = '';
+        }
+        echo '<td class="' . $cls . '"' . $rc . '><a href="'.makeUrlNS('User', sanitize_page_id($real_username)).'" ';
+        if ( !isPage($paths->nslist['User'] . sanitize_page_id($real_username)) )
+        {
+          echo 'class="wikilink-nonexistent"';
+        }
+        echo 'style="' . $rank_info['rank_style'] . '">' . htmlspecialchars($real_username) . '</a></td class="' . $cls . '">'."\n";
         
         
         // Minor edit
@@ -1071,7 +1095,7 @@
       return $lang->get('etc_access_denied_need_reauth');
     }
     
-    $e = $db->sql_query('INSERT INTO ' . table_prefix.'logs(time_id,date_string,log_type,action,page_id,namespace,author,edit_summary) VALUES('.time().', \''.enano_date(ED_DATE | ED_TIME).'\', \'page\', \'delete\', \'' . $page_id . '\', \'' . $namespace . '\', \'' . $session->username . '\', \'' . $db->escape(htmlspecialchars($reason)) . '\')');
+    $e = $db->sql_query('INSERT INTO ' . table_prefix.'logs(time_id,date_string,log_type,action,page_id,namespace,author,author_uid,edit_summary) VALUES('.time().', \''.enano_date(ED_DATE | ED_TIME).'\', \'page\', \'delete\', \'' . $page_id . '\', \'' . $namespace . '\', \'' . $session->username . '\', ' . $session->user_id . ', \'' . $db->escape(htmlspecialchars($reason)) . '\')');
     if(!$e) $db->_die('The page log entry could not be inserted.');
     $e = $db->sql_query('DELETE FROM ' . table_prefix.'categories WHERE page_id=\'' . $page_id . '\' AND namespace=\'' . $namespace . '\'');
     if(!$e) $db->_die('The page categorization entries could not be deleted.');
--- a/includes/sessions.php	Fri Dec 18 09:39:18 2009 -0500
+++ b/includes/sessions.php	Fri Dec 18 19:06:49 2009 -0500
@@ -2248,7 +2248,7 @@
   function admin_activation_request($u)
   {
     global $db;
-    $this->sql('INSERT INTO '.table_prefix.'logs(log_type, action, time_id, date_string, author, edit_summary) VALUES(\'admin\', \'activ_req\', '.time().', \''.enano_date(ED_DATE | ED_TIME).'\', \''.$this->username.'\', \''.$db->escape($u).'\');');
+    $this->sql('INSERT INTO '.table_prefix.'logs(log_type, action, time_id, date_string, author, author_uid, edit_summary) VALUES(\'admin\', \'activ_req\', '.time().', \''.enano_date(ED_DATE | ED_TIME).'\', \''.$this->username.'\', ' . $session->user_id . ', \''.$db->escape($u).'\');');
   }
   
   /**
@@ -2260,15 +2260,16 @@
   function activate_account($user, $key)
   {
     global $db, $session, $paths, $template, $plugins; // Common objects
-    $this->sql('UPDATE '.table_prefix.'users SET account_active=1 WHERE username=\''.$db->escape($user).'\' AND activation_key=\''.$db->escape($key).'\';');
-    $r = mysql_affected_rows();
-    if ( $r > 0 )
+    $q = $this->sql('SELECT 1 FROM ' . table_prefix . 'users WHERE username = \''.$db->escape($user).'\' AND activation_key = \''.$db->escape($key).'\'');
+    if ( $db->numrows() > 0 )
     {
-      $e = $this->sql('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,date_string,author,edit_summary) VALUES(\'security\', \'activ_good\', '.time().', \''.enano_date(ED_DATE | ED_TIME).'\', \''.$db->escape($user).'\', \''.$_SERVER['REMOTE_ADDR'].'\')');
+      $new_key = md5(AESCrypt::randkey());
+      $this->sql('UPDATE ' . table_prefix . 'users SET account_active = 1, activation_key = \'' . $new_key . '\' WHERE username=\''.$db->escape($user).'\' AND activation_key=\''.$db->escape($key).'\';');
+      $this->sql('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,date_string,author,edit_summary) VALUES(\'security\', \'activ_good\', '.time().', \''.enano_date(ED_DATE | ED_TIME).'\', \''.$db->escape($user).'\', \''.$_SERVER['REMOTE_ADDR'].'\')');
     }
     else
     {
-      $e = $this->sql('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,date_string,author,edit_summary) VALUES(\'security\', \'activ_bad\', '.time().', \''.enano_date(ED_DATE | ED_TIME).'\', \''.$db->escape($user).'\', \''.$_SERVER['REMOTE_ADDR'].'\')');
+      $this->sql('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,date_string,author,edit_summary) VALUES(\'security\', \'activ_bad\', '.time().', \''.enano_date(ED_DATE | ED_TIME).'\', \''.$db->escape($user).'\', \''.$_SERVER['REMOTE_ADDR'].'\')');
     }
     return $r;
   }
--- a/install/includes/payload.php	Fri Dec 18 09:39:18 2009 -0500
+++ b/install/includes/payload.php	Fri Dec 18 19:06:49 2009 -0500
@@ -427,7 +427,7 @@
   global $db, $session, $paths, $template, $plugins; // Common objects
   global $installer_version;
   
-  $q = $db->sql_query('INSERT INTO ' . table_prefix . 'logs(log_type,action,time_id,date_string,author,page_text,edit_summary) VALUES(\'security\', \'install_enano\', ' . time() . ', \'' . enano_date(ED_DATE | ED_TIME) . '\', \'' . $db->escape($_POST['username']) . '\', \'' . $db->escape(enano_version()) . '\', \'' . $db->escape($_SERVER['REMOTE_ADDR']) . '\');');
+  $q = $db->sql_query('INSERT INTO ' . table_prefix . 'logs(log_type,action,time_id,date_string,author,author_uid,page_text,edit_summary) VALUES(\'security\', \'install_enano\', ' . time() . ', \'' . enano_date(ED_DATE | ED_TIME) . '\', \'' . $db->escape($_POST['username']) . '\', 2, \'' . $db->escape(enano_version()) . '\', \'' . $db->escape($_SERVER['REMOTE_ADDR']) . '\');');
   if ( !$q )
   {
     echo '<p><tt>MySQL return: ' . $db->sql_error() . '</tt></p>';
@@ -564,8 +564,8 @@
 {
   global $db, $session, $paths, $template, $plugins; // Common objects
   // log the upgrade
-  $q = $db->sql_query('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,date_string,author,page_text,edit_summary) VALUES'
-         . '(\'security\', \'upgrade_enano\', ' . time() . ', \'[DEPRECATED]\', \'' . $db->escape($session->username) . '\', \'' . $db->escape(installer_enano_version()) . '\', \'' . $db->escape($_SERVER['REMOTE_ADDR']) . '\');');
+  $q = $db->sql_query('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,date_string,author,author_uid,page_text,edit_summary) VALUES'
+         . '(\'security\', \'upgrade_enano\', ' . time() . ', \'[DEPRECATED]\', \'' . $db->escape($session->username) . '\', ' . $session->user_id . ', \'' . $db->escape(installer_enano_version()) . '\', \'' . $db->escape($_SERVER['REMOTE_ADDR']) . '\');');
   if ( !$q )
   {
     $db->_die();
--- a/install/schemas/mysql_stage2.sql	Fri Dec 18 09:39:18 2009 -0500
+++ b/install/schemas/mysql_stage2.sql	Fri Dec 18 19:06:49 2009 -0500
@@ -41,6 +41,7 @@
   page_text text,
   char_tag varchar(40),
   author varchar(63),
+  author_uid mediumint(8) NOT NULL DEFAULT 1,
   edit_summary text,
   minor_edit tinyint(1),
   page_format varchar(16) NOT NULL DEFAULT 'wikitext',
--- a/install/schemas/postgresql_stage2.sql	Fri Dec 18 09:39:18 2009 -0500
+++ b/install/schemas/postgresql_stage2.sql	Fri Dec 18 19:06:49 2009 -0500
@@ -41,6 +41,7 @@
   page_text text,
   char_tag varchar(40),
   author varchar(63),
+  author_uid int NOT NULL DEFAULT 1,
   edit_summary text,
   minor_edit smallint,
   page_format varchar(16) NOT NULL DEFAULT 'wikitext',
--- a/install/schemas/upgrade/1.1.6-1.1.7-mysql.sql	Fri Dec 18 09:39:18 2009 -0500
+++ b/install/schemas/upgrade/1.1.6-1.1.7-mysql.sql	Fri Dec 18 19:06:49 2009 -0500
@@ -1,4 +1,5 @@
 ALTER TABLE {{TABLE_PREFIX}}users_extra ADD COLUMN date_format varchar(32) NOT NULL DEFAULT 'F d, Y';
 ALTER TABLE {{TABLE_PREFIX}}users_extra ADD COLUMN time_format varchar(32) NOT NULL DEFAULT 'G:i';
 ALTER TABLE {{TABLE_PREFIX}}lockout ADD COLUMN username varchar(255) NOT NULL DEFAULT '';
-
+ALTER TABLE {{TABLE_PREFIX}}logs ADD COLUMN author_uid mediumint(8) NOT NULL DEFAULT 1;
+UPDATE {{TABLE_PREFIX}}logs SET author_uid = 1;
--- a/install/schemas/upgrade/1.1.6-1.1.7-postgresql.sql	Fri Dec 18 09:39:18 2009 -0500
+++ b/install/schemas/upgrade/1.1.6-1.1.7-postgresql.sql	Fri Dec 18 19:06:49 2009 -0500
@@ -1,4 +1,5 @@
 ALTER TABLE {{TABLE_PREFIX}}users_extra ADD COLUMN date_format varchar(32) NOT NULL DEFAULT 'F d, Y';
 ALTER TABLE {{TABLE_PREFIX}}users_extra ADD COLUMN time_format varchar(32) NOT NULL DEFAULT 'G:i';
 ALTER TABLE {{TABLE_PREFIX}}lockout ADD COLUMN username varchar(255) NOT NULL DEFAULT '';
-
+ALTER TABLE {{TABLE_PREFIX}}logs ADD COLUMN author_uid int NOT NULL DEFAULT 1;
+UPDATE {{TABLE_PREFIX}}logs SET author_uid = 1;
--- a/plugins/SpecialAdmin.php	Fri Dec 18 09:39:18 2009 -0500
+++ b/plugins/SpecialAdmin.php	Fri Dec 18 19:06:49 2009 -0500
@@ -1060,28 +1060,28 @@
   {
     if(isset($_POST['enable_uploads']) && getConfig('enable_uploads') != '1')
     {
-      $q = $db->sql_query('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,edit_summary,author) VALUES(\'security\',\'upload_enable\',' . time() . ',\'' . $db->escape($_SERVER['REMOTE_ADDR']) . '\',\'' . $db->escape($session->username) . '\');');
+      $q = $db->sql_query('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,edit_summary,author,author_uid) VALUES(\'security\',\'upload_enable\',' . time() . ',\'' . $db->escape($_SERVER['REMOTE_ADDR']) . '\',\'' . $db->escape($session->username) . '\', ' . $session->user_id . ');');
       if ( !$q )
         $db->_die();
       setConfig('enable_uploads', '1');
     }
     else if ( !isset($_POST['enable_uploads']) && getConfig('enable_uploads') == '1' )
     {
-      $q = $db->sql_query('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,edit_summary,author) VALUES(\'security\',\'upload_disable\',' . time() . ',\'' . $db->escape($_SERVER['REMOTE_ADDR']) . '\',\'' . $db->escape($session->username) . '\');');
+      $q = $db->sql_query('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,edit_summary,author,author_uid) VALUES(\'security\',\'upload_disable\',' . time() . ',\'' . $db->escape($_SERVER['REMOTE_ADDR']) . '\',\'' . $db->escape($session->username) . '\', ' . $session->user_id . ');');
       if ( !$q )
         $db->_die();
       setConfig('enable_uploads', '0');
     }
     if(isset($_POST['enable_imagemagick']) && getConfig('enable_imagemagick') != '1')
     {
-      $q = $db->sql_query('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,edit_summary,author) VALUES(\'security\',\'magick_enable\',' . time() . ',\'' . $db->escape($_SERVER['REMOTE_ADDR']) . '\',\'' . $db->escape($session->username) . '\');');
+      $q = $db->sql_query('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,edit_summary,author,author_uid) VALUES(\'security\',\'magick_enable\',' . time() . ',\'' . $db->escape($_SERVER['REMOTE_ADDR']) . '\',\'' . $db->escape($session->username) . '\', ' . $session->user_id . ');');
       if ( !$q )
         $db->_die();
       setConfig('enable_imagemagick', '1');
     }
     else if ( !isset($_POST['enable_imagemagick']) && getConfig('enable_imagemagick') == '1' )
     {
-      $q = $db->sql_query('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,edit_summary,author) VALUES(\'security\',\'magick_disable\',' . time() . ',\'' . $db->escape($_SERVER['REMOTE_ADDR']) . '\',\'' . $db->escape($session->username) . '\');');
+      $q = $db->sql_query('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,edit_summary,author,author_uid) VALUES(\'security\',\'magick_disable\',' . time() . ',\'' . $db->escape($_SERVER['REMOTE_ADDR']) . '\',\'' . $db->escape($session->username) . '\', ' . $session->user_id . ');');
       if ( !$q )
         $db->_die();
       setConfig('enable_imagemagick', '0');
@@ -1096,14 +1096,14 @@
     }
     if(isset($_POST['file_history']) && getConfig('file_history') != '1' )
     {
-      $q = $db->sql_query('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,edit_summary,author) VALUES(\'security\',\'filehist_enable\',' . time() . ',\'' . $db->escape($_SERVER['REMOTE_ADDR']) . '\',\'' . $db->escape($session->username) . '\');');
+      $q = $db->sql_query('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,edit_summary,author,author_uid) VALUES(\'security\',\'filehist_enable\',' . time() . ',\'' . $db->escape($_SERVER['REMOTE_ADDR']) . '\',\'' . $db->escape($session->username) . '\',' . $session->user_id . ');');
       if ( !$q )
         $db->_die();
       setConfig('file_history', '1');
     }
     else if ( !isset($_POST['file_history']) && getConfig('file_history') == '1' )
     {
-      $q = $db->sql_query('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,edit_summary,author) VALUES(\'security\',\'filehist_disable\',' . time() . ',\'' . $db->escape($_SERVER['REMOTE_ADDR']) . '\',\'' . $db->escape($session->username) . '\');');
+      $q = $db->sql_query('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,edit_summary,author,author_uid) VALUES(\'security\',\'filehist_disable\',' . time() . ',\'' . $db->escape($_SERVER['REMOTE_ADDR']) . '\',\'' . $db->escape($session->username) . '\',' . $session->user_id . ');');
       if ( !$q )
         $db->_die();
       setConfig('file_history', '0');
@@ -1115,7 +1115,7 @@
         $_POST['imagemagick_path'] = '/usr/bin/convert';
       $old = getConfig('imagemagick_path');
       $oldnew = "{$old}||{$_POST['imagemagick_path']}";
-      $q = $db->sql_query('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,edit_summary,author,page_text) VALUES(\'security\',\'magick_path\',' . time() . ',\'' . $db->escape($_SERVER['REMOTE_ADDR']) . '\',\'' . $db->escape($session->username) . '\',\'' . $db->escape($oldnew) . '\');');
+      $q = $db->sql_query('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,edit_summary,author,author_uid,page_text) VALUES(\'security\',\'magick_path\',' . time() . ',\'' . $db->escape($_SERVER['REMOTE_ADDR']) . '\',\'' . $db->escape($session->username) . '\',' . $session->user_id . ',\'' . $db->escape($oldnew) . '\');');
       if ( !$q )
         $db->_die();
       setConfig('imagemagick_path', $_POST['imagemagick_path']);
@@ -1266,191 +1266,6 @@
   <?php
 }
 
-/*
-function page_Admin_PluginManager()
-{
-  global $db, $session, $paths, $template, $plugins; // Common objects
-  global $lang;
-  if ( $session->auth_level < USER_LEVEL_ADMIN || $session->user_level < USER_LEVEL_ADMIN )
-  {
-    $login_link = makeUrlNS('Special', 'Login/' . $paths->nslist['Special'] . 'Administration', 'level=' . USER_LEVEL_ADMIN, true);
-    echo '<h3>' . $lang->get('adm_err_not_auth_title') . '</h3>';
-    echo '<p>' . $lang->get('adm_err_not_auth_body', array( 'login_link' => $login_link )) . '</p>';
-    return;
-  }
-  
-  if(isset($_GET['action']))
-  {
-    if ( !isset($_GET['plugin']) )
-    {
-      echo '<div class="error-box">No plugin specified.</div>';
-    }
-    else if ( !preg_match('/^[A-z0-9_\.-]+\.php$/', $_GET['plugin']) )
-    {
-      echo '<div class="error-box">Hacking attempt</div>';
-    }
-    else
-    {
-      $plugin =& $_GET['plugin'];
-      switch($_GET['action'])
-      {
-        case "enable":
-          $q = $db->sql_query('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,edit_summary,author,page_text) VALUES(\'security\',\'plugin_enable\',' . time() . ',\'' . $db->escape($_SERVER['REMOTE_ADDR']) . '\',"' . $db->escape($session->username) . '","' . $db->escape($_GET['plugin']) . '");');
-          if ( !$q )
-            $db->_die();
-          setConfig("plugin_$plugin", '1');
-          break;
-        case "disable":
-          if ( defined('ENANO_DEMO_MODE') && strstr($_GET['plugin'], 'Demo') )
-          {
-            echo('<h3>' . $lang->get('acppl_err_heading') . '</h3>
-                   <p>' . $lang->get('acppl_err_demo_plugin') . '</p>');
-            break;
-          }
-          if ( !in_array($plugin, $plugins->system_plugins) )
-          {
-            $q = $db->sql_query('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,edit_summary,author,page_text) VALUES(\'security\',\'plugin_disable\',' . time() . ',\'' . $db->escape($_SERVER['REMOTE_ADDR']) . '\',"' . $db->escape($session->username) . '","' . $db->escape($_GET['plugin']) . '");');
-            if ( !$q )
-              $db->_die();
-            setConfig("plugin_$plugin", '0');
-          }
-          else 
-          {
-            echo '<h3>' . $lang->get('acppl_err_heading') . '</h3>
-                   <p>' . $lang->get('acppl_err_system_plugin') . '</p>';
-          }
-          break;
-        case "reimport":
-          $plugin_id = substr($plugin, 0, -4);
-          if ( isset($plugins->loaded_plugins[$plugin_id]) )
-          {
-            // plugin file is safe, call import
-            $lang->import_plugin( ENANO_ROOT . "/plugins/$plugin" );
-            echo '<div class="info-box">' . $lang->get('acppl_msg_reimport_success') . '</div>';
-          }
-          break;
-      }
-    }
-  }
-  $dir = './plugins/';
-  $plugin_list = Array();
-  $system = Array();
-  $show_system = ( isset($_GET['show_system']) && $_GET['show_system'] == 'yes' );
-  
-  if (is_dir($dir))
-  {
-    if ($dh = opendir($dir))
-    {
-      while (($file = readdir($dh)) !== false)
-      {
-        if(preg_match('#^(.*?)\.php$#is', $file) && $file != 'index.php')
-        {
-          unset($thelist);
-          if ( in_array($file, $plugins->system_plugins) )
-          {
-            if ( !$show_system )
-              continue;
-            $thelist =& $system;
-          }
-          else
-          {
-            $thelist =& $plugin_list;
-          }
-          $f = file_get_contents($dir . $file);
-          $f = explode("\n", $f);
-          $f = array_slice($f, 2, 7);
-          $f[0] = substr($f[0], 13, strlen($f[0]));
-          $f[1] = substr($f[1], 12, strlen($f[1]));
-          $f[2] = substr($f[2], 13, strlen($f[2]));
-          $f[3] = substr($f[3], 8,  strlen($f[3]));
-          $f[4] = substr($f[4], 9,  strlen($f[4]));
-          $f[5] = substr($f[5], 12, strlen($f[5]));
-          $thelist[$file] = Array();
-          $thelist[$file]['name'] = $f[0];
-          $thelist[$file]['uri']  = $f[1];
-          $thelist[$file]['desc'] = $f[2];
-          $thelist[$file]['auth'] = $f[3];
-          $thelist[$file]['vers'] = $f[4];
-          $thelist[$file]['aweb'] = $f[5];
-          
-          if ( preg_match('/^[a-z0-9]+_[a-z0-9_]+$/', $thelist[$file]['name']) )
-            $thelist[$file]['name'] = $lang->get($thelist[$file]['name']);
-          
-          if ( preg_match('/^[a-z0-9]+_[a-z0-9_]+$/', $thelist[$file]['desc']) )
-            $thelist[$file]['desc'] = $lang->get($thelist[$file]['desc']);
-          
-        }
-      }
-      closedir($dh);
-    }
-    else
-    {
-      echo '<div class="error-box">' . $lang->get('acppl_err_open_dir') . '</div>';
-      return;
-    }
-  }
-  else
-  {
-    echo '<div class="error-box">' . $lang->get('acppl_err_missing_dir') . '</div>';
-    return;
-  }
-  echo('<div class="tblholder"><table border="0" width="100%" cellspacing="1" cellpadding="4">
-      <tr>
-        <th>' . $lang->get('acppl_col_filename') . '</th>
-        <th>' . $lang->get('acppl_col_name') . '</th>
-        <th>' . $lang->get('acppl_col_description') . '</th>
-        <th>' . $lang->get('acppl_col_author') . '</th>
-        <th>' . $lang->get('acppl_col_version') . '</th>
-        <th></th>
-      </tr>');
-    $plugin_files_1 = array_keys($plugin_list);
-    $plugin_files_2 = array_keys($system);
-    $plugin_files = array_values(array_merge($plugin_files_1, $plugin_files_2));
-    $cls = 'row2';
-    for ( $i = 0; $i < sizeof($plugin_files); $i++ )
-    {
-      $cls = ( $cls == 'row2' ) ? 'row3' : 'row2';
-      $this_plugin = ( isset($system[$plugin_files[$i]]) ) ? $system[$plugin_files[$i]] : $plugin_list[$plugin_files[$i]];
-      $is_system = ( @$system[$plugin_files[$i]] );
-      $bgcolor = '';
-      if ( $is_system && $cls == 'row2' )
-        $bgcolor = ' style="background-color: #FFD8D8;"';
-      else if ( $is_system && $cls == 'row3' )
-        $bgcolor = ' style="background-color: #FFD0D0;"';
-      echo '<tr>
-              <td class="'.$cls.'"'.$bgcolor.'>'.$plugin_files[$i].'</td>
-              <td class="'.$cls.'"'.$bgcolor.'><a href="'.$this_plugin['uri'].'">'.$this_plugin['name'].'</a></td>
-              <td class="'.$cls.'"'.$bgcolor.'>'.$this_plugin['desc'].'</td>
-              <td class="'.$cls.'"'.$bgcolor.'><a href="'.$this_plugin['aweb'].'">'.$this_plugin['auth'].'</a></td>
-              <td class="'.$cls.'"'.$bgcolor.'>'.$this_plugin['vers'].'</td>
-              <td class="'.$cls.'"'.( $bgcolor != '' ? str_replace_once(';', '; text-align: center;', $bgcolor) : ' style="text-align: center;"' ).' nowrap="nowrap">';
-      if ( !in_array($plugin_files[$i], $plugins->system_plugins) )
-      {
-        if ( getConfig('plugin_'.$plugin_files[$i]) == '1' )
-        {
-          echo '<a href="'.makeUrl($paths->nslist['Special'].'Administration', 'module='.$paths->cpage['module']).'&amp;show_system=' . ( $show_system ? 'yes' : 'no' ) . '&amp;action=disable&amp;plugin='.$plugin_files[$i].'">' . $lang->get('acppl_btn_disable') . '</a>';
-          echo ' | ';
-          echo '<a title="' . $lang->get('acppl_btn_reimport_tip') . '" href="'.makeUrl($paths->nslist['Special'].'Administration', 'module='.$paths->cpage['module']).'&amp;show_system=' . ( $show_system ? 'yes' : 'no' ) . '&amp;action=reimport&amp;plugin='.$plugin_files[$i].'">' . $lang->get('acppl_btn_reimport') . '</a>';
-        }
-        else
-        {
-          echo '<a href="'.makeUrl($paths->nslist['Special'].'Administration', 'module='.$paths->cpage['module']).'&amp;show_system=' . ( $show_system ? 'yes' : 'no' ) . '&amp;action=enable&amp;plugin='.$plugin_files[$i].'">' . $lang->get('acppl_btn_enable') . '</a>';
-        }
-      }
-      else
-      {
-        echo $lang->get('acppl_lbl_system_plugin');
-      }
-      echo '</td></tr>';
-    }
-    $showhide_link = ( $show_system ) ?
-    '<a style="color: white;" href="' . makeUrlNS('Special', 'Administration', 'module=' . $paths->cpage['module'] . '&show_system=no', true) . '">' . $lang->get('acppl_btn_hide_system') . '</a>' :
-    '<a style="color: white;" href="' . makeUrlNS('Special', 'Administration', 'module=' . $paths->cpage['module'] . '&show_system=yes', true) . '">' . $lang->get('acppl_btn_show_system') . '</a>' ;
-    echo '<tr><th colspan="6" class="subhead">'.$showhide_link.'</th></tr>';
-    echo '</table></div>';
-}
-*/
-
 function page_Admin_DBBackup()
 {
   global $db, $session, $paths, $template, $plugins; // Common objects
@@ -1496,7 +1311,7 @@
     $tables = array_merge($base, $add);
     
     // Log it!
-    $e = $db->sql_query('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,date_string,author,edit_summary,page_text) VALUES(\'security\', \'db_backup\', '.time().', \''.enano_date(ED_DATE | ED_TIME).'\', \''.$db->escape($session->username).'\', \''.$db->escape($_SERVER['REMOTE_ADDR']).'\', \'' . $db->escape(implode(', ', $tables)) . '\')');
+    $e = $db->sql_query('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,date_string,author,author_uid,edit_summary,page_text) VALUES(\'security\', \'db_backup\', '.time().', \''.enano_date(ED_DATE | ED_TIME).'\', \''.$db->escape($session->username).'\',' . $session->user_id . ', \''.$db->escape($_SERVER['REMOTE_ADDR']).'\', \'' . $db->escape(implode(', ', $tables)) . '\')');
     if ( !$e )
       $db->_die();
     
--- a/plugins/SpecialUpdownload.php	Fri Dec 18 09:39:18 2009 -0500
+++ b/plugins/SpecialUpdownload.php	Fri Dec 18 19:06:49 2009 -0500
@@ -128,13 +128,13 @@
     if(!$db->sql_query('INSERT INTO '.table_prefix.'files(time_id,page_id,filename,size,mimetype,file_extension,file_key) VALUES('.$utime.', \''.$urln.'\', \''.$filename.'\', '.$flen.', \''.$type.'\', \''.$ext.'\', \''.$key.'\')')) $db->_die('The file data entry could not be inserted.');
     if(!isset($_POST['update']))
     {
-      if(!$db->sql_query('INSERT INTO '.table_prefix.'logs(time_id,date_string,log_type,action,author,page_id,namespace) VALUES('.$utime.', \''.enano_date(ED_DATE | ED_TIME).'\', \'page\', \'create\', \''.$session->username.'\', \''.$filename.'\', \''.'File'.'\');')) $db->_die('The page log could not be updated.');
+      if(!$db->sql_query('INSERT INTO '.table_prefix.'logs(time_id,date_string,log_type,action,author,author_uid,page_id,namespace) VALUES('.$utime.', \''.enano_date(ED_DATE | ED_TIME).'\', \'page\', \'create\', \''.$session->username.'\',' . $session->user_id . ', \''.$filename.'\', \''.'File'.'\');')) $db->_die('The page log could not be updated.');
       if(!$db->sql_query('INSERT INTO '.table_prefix.'pages(name,urlname,namespace,protected,delvotes,delvote_ips) VALUES(\''.$filename.'\', \''.$urln.'\', \'File\', 0, 0, \'\')')) $db->_die('The page listing entry could not be inserted.');
       if(!$db->sql_query('INSERT INTO '.table_prefix.'page_text(page_id,namespace,page_text,char_tag) VALUES(\''.$urln.'\', \'File\', \''.$comments.'\', \''.$chartag.'\')')) $db->_die('The page text entry could not be inserted.');
     }
     else
     {
-      if(!$db->sql_query('INSERT INTO '.table_prefix.'logs(time_id,date_string,log_type,action,author,page_id,namespace,edit_summary) VALUES('.$utime.', \''.enano_date(ED_DATE | ED_TIME).'\', \'page\', \'reupload\', \''.$session->username.'\', \''.$filename.'\', \''.'File'.'\', \''.$comments.'\');')) $db->_die('The page log could not be updated.');
+      if(!$db->sql_query('INSERT INTO '.table_prefix.'logs(time_id,date_string,log_type,action,author,author_uid,page_id,namespace,edit_summary) VALUES('.$utime.', \''.enano_date(ED_DATE | ED_TIME).'\', \'page\', \'reupload\', \''.$session->username.'\',' . $session->user_id . ', \''.$filename.'\', \''.'File'.'\', \''.$comments.'\');')) $db->_die('The page log could not be updated.');
     }
     $cache->purge('page_meta');
     die_friendly($lang->get('upload_success_title'), '<p>' . $lang->get('upload_success_body', array('file_link' => makeUrlNS('File', $filename))) . '</p>');
--- a/plugins/admin/SecurityLog.php	Fri Dec 18 09:39:18 2009 -0500
+++ b/plugins/admin/SecurityLog.php	Fri Dec 18 19:06:49 2009 -0500
@@ -38,7 +38,14 @@
   $row = $db->fetchrow();
   $db->free_result();
   $count = intval($row['num']);
-  $q = $db->sql_query('SELECT action,date_string,author,edit_summary,time_id,page_text FROM '.table_prefix.'logs WHERE log_type=\'security\' ORDER BY time_id DESC, action ASC;');
+
+  $l = 'SELECT action,date_string,author,author_uid,u.username,edit_summary,time_id,page_text FROM '.table_prefix."logs AS l\n"
+     . "  LEFT JOIN " . table_prefix . "users AS u\n"
+     . "    ON ( u.user_id = l.author_uid OR u.user_id IS NULL )\n"
+     . "  WHERE log_type='security'\n"
+     . "  ORDER BY time_id DESC, action ASC;";
+         
+  $q = $db->sql_query($l);
   if ( !$q )
     $db->_die();
    
@@ -71,7 +78,7 @@
   
   if ( $session->auth_level < USER_LEVEL_ADMIN )
   {
-    $q = $db->sql_query('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,edit_summary,author) VALUES(\'security\',\'seclog_unauth\',' . time() . ',"' . $db->escape($_SERVER['REMOTE_ADDR']) . '","' . $db->escape($session->username) . '");');
+    $q = $db->sql_query('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,edit_summary,author,author_uid) VALUES(\'security\',\'seclog_unauth\',' . time() . ', \'' . $db->escape($_SERVER['REMOTE_ADDR']) . '\', \'' . $db->escape($session->username) . '\', ' . $session->user_id . ');');
     if ( !$q )
       $db->_die();
     die('Security log: unauthorized attempt to fetch. Call has been logged and reported to the administrators.');
@@ -94,14 +101,13 @@
   // }
   // else
   // {
-    if(is_int($num))
-    {
-      $l = 'SELECT action,date_string,author,edit_summary,time_id,page_text FROM '.table_prefix.'logs WHERE log_type=\'security\' ORDER BY time_id DESC, action ASC LIMIT '.$num.';';
-    }
-    else
-    {
-      $l = 'SELECT action,date_string,author,edit_summary,time_id,page_text FROM '.table_prefix.'logs WHERE log_type=\'security\' ORDER BY time_id DESC, action ASC;';
-    }
+    $limit_clause = is_int($num) ? " LIMIT $num" : '';
+    $l = 'SELECT action,date_string,author,author_uid,u.username,edit_summary,time_id,page_text FROM '.table_prefix."logs AS l\n"
+         . "  LEFT JOIN " . table_prefix . "users AS u\n"
+         . "    ON ( u.user_id = l.author_uid OR u.user_id IS NULL )\n"
+         . "  WHERE log_type='security'\n"
+         . "  ORDER BY time_id DESC, action ASC{$limit_clause};";
+    
     $q = $db->sql_query($l);
     while($r = $db->fetchrow($q))
     {
@@ -175,7 +181,13 @@
     case "u_to_mod"        : $return .= $lang->get('acpsl_entry_u_to_mod'         , array('username' => $r['page_text'])); break;
     case "view_comment_ip" : $return .= $lang->get('acpsl_entry_view_comment_ip'  , array('username' => htmlspecialchars($r['page_text']))); break;
   }
-  $return .= '</td><td class="'.$cls.'">'.enano_date(ED_DATE | ED_TIME, $r['time_id']).'</td><td class="'.$cls.'">'.$r['author'].'</td><td class="'.$cls.'" style="cursor: pointer;" onclick="ajaxReverseDNS(this);" title="' . $lang->get('acpsl_tip_reverse_dns') . '">'.$r['edit_summary'].'</td></tr>';
+  $author_bit = '<span style="';
+  $rank_info = $session->get_user_rank($r['author_uid']);
+  $author_bit .= $rank_info['rank_style'];
+  $author_bit .= '">';
+  $author_bit .= $r['author_uid'] > 1 && !empty($r['username']) ? htmlspecialchars($r['username']) : htmlspecialchars($r['author']);
+  $author_bit .= '</span>';
+  $return .= '</td><td class="'.$cls.'">'.enano_date(ED_DATE | ED_TIME, $r['time_id']).'</td><td class="'.$cls.'">'.$author_bit.'</td><td class="'.$cls.'" style="cursor: pointer;" onclick="ajaxReverseDNS(this);" title="' . $lang->get('acpsl_tip_reverse_dns') . '">'.$r['edit_summary'].'</td></tr>';
   return $return;
 }
 
--- a/plugins/admin/UserManager.php	Fri Dec 18 09:39:18 2009 -0500
+++ b/plugins/admin/UserManager.php	Fri Dec 18 19:06:49 2009 -0500
@@ -273,14 +273,14 @@
             // We need to update group memberships
             if ( $existing_level == USER_LEVEL_ADMIN ) 
             {
-              $q = $db->sql_query('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,edit_summary,author,page_text) VALUES(\'security\',\'u_from_admin\',' . time() . ',"' . $db->escape($_SERVER['REMOTE_ADDR']) . '","' . $db->escape($session->username) . '","' . $db->escape($username) . '");');
+              $q = $db->sql_query('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,edit_summary,author,author_uid,page_text) VALUES(\'security\',\'u_from_admin\',' . time() . ', \'' . $db->escape($_SERVER['REMOTE_ADDR']) . '\', ' . $session->user_id . ', \'' . $db->escape($session->username) . '\', \'' . $db->escape($username) . '\');');
               if ( !$q )
                 $db->_die();
               $session->remove_user_from_group($user_id, GROUP_ID_ADMIN);
             }
             else if ( $existing_level == USER_LEVEL_MOD ) 
             {
-              $q = $db->sql_query('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,edit_summary,author,page_text) VALUES(\'security\',\'u_from_mod\',' . time() . ',"' . $db->escape($_SERVER['REMOTE_ADDR']) . '","' . $db->escape($session->username) . '","' . $db->escape($username) . '");');
+              $q = $db->sql_query('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,edit_summary,author,author_uid,page_text) VALUES(\'security\',\'u_from_mod\',' . time() . ', \'' . $db->escape($_SERVER['REMOTE_ADDR']) . '\', ' . $session->user_id . ', \'' . $db->escape($session->username) . '\', \'' . $db->escape($username) . '\');');
               if ( !$q )
                 $db->_die();
               $session->remove_user_from_group($user_id, GROUP_ID_MOD);
@@ -288,14 +288,14 @@
             
             if ( $user_level == USER_LEVEL_ADMIN )
             {
-              $q = $db->sql_query('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,edit_summary,author,page_text) VALUES(\'security\',\'u_to_admin\',' . time() . ',"' . $db->escape($_SERVER['REMOTE_ADDR']) . '","' . $db->escape($session->username) . '","' . $db->escape($username) . '");');
+              $q = $db->sql_query('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,edit_summary,author,author_uid,page_text) VALUES(\'security\',\'u_to_admin\',' . time() . ', \'' . $db->escape($_SERVER['REMOTE_ADDR']) . '\', ' . $session->user_id . ', \'' . $db->escape($session->username) . '\', \'' . $db->escape($username) . '\');');
               if ( !$q )
                 $db->_die();
               $session->add_user_to_group($user_id, GROUP_ID_ADMIN, false);
             }
             else if ( $user_level == USER_LEVEL_MOD )
             {
-              $q = $db->sql_query('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,edit_summary,author,page_text) VALUES(\'security\',\'u_to_mod\',' . time() . ',"' . $db->escape($_SERVER['REMOTE_ADDR']) . '","' . $db->escape($session->username) . '","' . $db->escape($username) . '");');
+              $q = $db->sql_query('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,edit_summary,author,author_uid,page_text) VALUES(\'security\',\'u_to_mod\',' . time() . ', \'' . $db->escape($_SERVER['REMOTE_ADDR']) . '\', ' . $session->user_id . ', \'' . $db->escape($session->username) . '\', \'' . $db->escape($username) . '\');');
               if ( !$q )
                 $db->_die();
               $session->add_user_to_group($user_id, GROUP_ID_MOD, false);