=== modified file 'docs/TODO'
--- docs/TODO	2010-11-25 16:49:09 +0000
+++ docs/TODO	2011-01-19 13:02:02 +0000
@@ -31,3 +31,6 @@
 
 * HTML modernization
   convert all "checkRadio" calls to HTML labels. see revision@4227
+
+* autocomplete="off"
+Add this to forms where you save OTHER USER passwords (admin screens)

=== modified file 'htdocs/post_note.php'
--- htdocs/post_note.php	2011-01-19 10:31:30 +0000
+++ htdocs/post_note.php	2011-01-19 13:02:49 +0000
@@ -85,9 +85,13 @@
     $reply_subject = ev_gettext('Re: %1$s', $details['iss_summary']);
 }
 
+$users = Project::getUserAssocList($prj_id, 'active', User::getRoleID('Customer'));
+$user_details = User::getDetailsAssoc(array_keys($users), 'usr_grp_id');
+
 $tpl->assign(array(
     'from'               => User::getFromHeader($usr_id),
-    'users'              => Project::getUserAssocList($prj_id, 'active', User::getRoleID('Customer')),
+    'users'              => $users, // XXX: drop me, we use $user_details now
+    'user_details'       => $user_details,
     'current_user_prefs' => Prefs::get($usr_id),
     'subscribers'        => Notification::getSubscribers($issue_id, false, User::getRoleID("Standard User")),
     'statuses'           => Status::getAssocStatusList($prj_id, false),

=== modified file 'lib/eventum/class.user.php'
--- lib/eventum/class.user.php	2010-12-17 03:29:52 +0000
+++ lib/eventum/class.user.php	2011-01-19 13:03:06 +0000
@@ -668,33 +668,57 @@
      */
     function getDetails($usr_id)
     {
+        $res = self::getDetailsAssoc(array($usr_id));
+        return reset($res);
+    }
+
+    /**
+     * Method used to get the account details of a list users.
+     *
+     * @param   array $usr_ids The user ID
+     * @param   string $sort_key sort the result by that key
+     * @return  array List of accounts with account details
+     */
+    public function getDetailsAssoc($usr_ids, $sort_key = null)
+    {
         static $returns;
-
-        if (!empty($returns[$usr_id])) {
-            return $returns[$usr_id];
-        }
-
-        $stmt = "SELECT
-                    *
-                 FROM
-                    " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "user
-                 WHERE
-                    usr_id=" . Misc::escapeInteger($usr_id);
-        $res = DB_Helper::getInstance()->getRow($stmt, DB_FETCHMODE_ASSOC);
-        if (PEAR::isError($res)) {
-            Error_Handler::logError(array($res->getMessage(), $res->getDebugInfo()), __FILE__, __LINE__);
-            return null;
-        }
-
-        // do not fill empty projects, roles, groups for inexistent users
-        if (!empty($res)) {
-            $roles =  Project::getAssocList($usr_id, false, true);
-            $res['projects'] = @array_keys($roles);
-            $res['roles'] = $roles;
-            $res['group'] = Group::getName($res['usr_grp_id']);
-        }
-
-        $returns[$usr_id] = $res;
+        $key = md5(serialize($usr_ids));
+
+        if (empty($returns[$key])) {
+            $stmt = "SELECT
+                        *
+                     FROM
+                        " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "user
+                     WHERE
+                        usr_id IN (" . implode(', ', Misc::escapeInteger($usr_ids)) . ")";
+            $res = DB_Helper::getInstance()->getAll($stmt, DB_FETCHMODE_ASSOC);
+            if (PEAR::isError($res)) {
+                Error_Handler::logError(array($res->getMessage(), $res->getDebugInfo()), __FILE__, __LINE__);
+                return null;
+            }
+
+            foreach ($res as $usr_id => &$row) {
+                // FIXME: maybe PEAR has some "fill NULL" mode?
+                if (!isset($row['usr_grp_id'])) {
+                    $row['usr_grp_id'] = null;
+                }
+
+                $row['group'] = Group::getName($row['usr_grp_id']);
+                $roles = Project::getAssocList($usr_id, false, true);
+                $row['projects'] = array_keys($roles);
+                $row['roles'] = $roles;
+            }
+            $returns[$key] = $res;
+        }
+
+        $res = $returns[$key];
+
+        // sort if requested
+        if ($sort_key) {
+            $sortfn = create_function('$a, $b', 'return strcmp($a["'.$sort_key.'"], $b["'.$sort_key.'"]);');
+            uasort($res, $sortfn);
+        }
+
         return $res;
     }
 

=== modified file 'templates/post_note.tpl.html'
--- templates/post_note.tpl.html	2010-10-07 11:47:17 +0000
+++ templates/post_note.tpl.html	2011-01-19 13:01:33 +0000
@@ -127,8 +127,17 @@
                 size="{$users|@count}"
               {/if}
               multiple name="note_cc[]" onChange="showSelections('post_note_form', 'note_cc[]');">
-              {html_options options=$users}
-            </select><input class="button" type="button" value="{t}Clear Selections{/t}" onClick="clearExtraRecipients();"><br />
+
+              {foreach from=$user_details item=usr}
+              {if $usr.group}
+                {assign var=display_name value="`$usr.group`: `$usr.usr_full_name`"}
+              {else}
+                {assign var=display_name value=$usr.usr_full_name}
+              {/if}
+                {html_options values=$usr.usr_id output=$display_name}
+              {/foreach}
+            </select>
+<input class="button" type="button" value="{t}Clear Selections{/t}" onClick="clearExtraRecipients();"><br />
             {include file="lookup_field.tpl.html" lookup_field_name="search" lookup_field_target="note_cc[]" callbacks="new Array('showSelections(\'post_note_form\', \'note_cc[]\')')"}
             <div class="default" id="selection_note_cc[]"></div>
           </td>

