Index: /WAeUP_SRP/trunk/Academics.py
===================================================================
--- /WAeUP_SRP/trunk/Academics.py	(revision 929)
+++ /WAeUP_SRP/trunk/Academics.py	(revision 930)
@@ -230,5 +230,5 @@
                 msg = "Department %(department_code)s for Course %(code)s not found" % course
                 logger.info(msg)
-                no_import.write(msg)
+                no_import.write('"%s",' % msg)
                 no_import.write(format % course + "\n")
                 continue
@@ -237,5 +237,5 @@
                 msg = "Dupplicate Course %(code)s" % course
                 logger.info(msg)
-                no_import.write(msg)
+                no_import.write('"%s",' % msg)
                 no_import.write(format % course + "\n")
                 continue
Index: /WAeUP_SRP/trunk/PatchZODBDirectory_searchEntries.py
===================================================================
--- /WAeUP_SRP/trunk/PatchZODBDirectory_searchEntries.py	(revision 930)
+++ /WAeUP_SRP/trunk/PatchZODBDirectory_searchEntries.py	(revision 930)
@@ -0,0 +1,82 @@
+# (C) Copyright 2004 Nuxeo SARL <http://nuxeo.com>
+# Author: Georges Racinet <gracinet@nuxeo.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 as published
+# by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+# 02111-1307, USA.
+#
+# $Id: utils.py 35055 2006-04-10 15:51:21Z gracinet $
+
+from zLOG import LOG, DEBUG, TRACE
+from copy import deepcopy
+from AccessControl import ClassSecurityInfo
+from Products.CPSSchemas.StorageAdapter import AttributeStorageAdapter
+from Products.CPSDirectory.utils import QueryMatcher
+security = ClassSecurityInfo()
+
+
+security.declarePrivate('_searchEntries')
+def _searchEntries(self, return_fields=None, **kw):
+    """Search for entries in the directory.
+    """
+    if self.ZCacheable_isCachingEnabled():
+        keyset = {'return_fields' : return_fields}
+        keyset.update(kw)
+        LOG('ZODBDirectory._searchEntries', TRACE,
+            "Searching cache for %s" % (keyset,))
+        from_cache = self.ZCacheable_get(keywords=keyset)
+        if from_cache is not None:
+            LOG('ZODBDirectory._searchEntries', TRACE, " -> results=%s" %
+                (from_cache[:20],))
+            return deepcopy(from_cache)
+    else:
+        keyset = None
+
+    matcher = QueryMatcher(kw, accepted_keys=self._getFieldIds(),
+                           substring_keys=self.search_substring_fields)
+
+    # Compute needed fields from object.
+    # All fields we need to return.
+    field_ids_d, return_fields = self._getSearchFields(return_fields)
+    # Add all fields the search is made on.
+    field_ids = matcher.getKeysSet().union(field_ids_d)
+
+    # Do the search.
+    schema = self._getUniqueSchema()
+    adapter = AttributeStorageAdapter(schema, None,
+                                      field_ids=list(field_ids))
+    res = []
+    for id, ob in self.objectItems():
+        if getattr(ob,'homeless',False):
+            continue
+        adapter.setContextObject(ob)
+        entry = adapter.getData()
+        adapter.finalizeDefaults(entry)
+        if not matcher.match(entry):
+            continue
+        # Compute result to return.
+        if return_fields is None:
+            res.append(id)
+        else:
+            d = {}
+            for key in return_fields:
+                d[key] = entry[key]
+            res.append((id, d))
+
+    if keyset is not None:
+        LOG('ZODBDirectory._searchEntries', TRACE, "Putting in cache")
+        self.ZCacheable_set(res, keywords=keyset)
+
+    return deepcopy(res)
+from Products.CPSDirectory.ZODBDirectory import  ZODBDirectory
+ZODBDirectory._searchEntries = _searchEntries
Index: /WAeUP_SRP/trunk/__init__.py
===================================================================
--- /WAeUP_SRP/trunk/__init__.py	(revision 929)
+++ /WAeUP_SRP/trunk/__init__.py	(revision 930)
@@ -16,4 +16,5 @@
 import PatchCPSMembershipTool
 import PatchCPSUserFolderUserFolder
+import PatchZODBDirectory_searchEntries
 import PatchBasicWidgetsCPSStringWidget
 # Only for CPS 3.4.1. In 3.4.2 and later this should be fixed.
Index: /WAeUP_SRP/trunk/profiles/default/layouts/members_search.xml
===================================================================
--- /WAeUP_SRP/trunk/profiles/default/layouts/members_search.xml	(revision 929)
+++ /WAeUP_SRP/trunk/profiles/default/layouts/members_search.xml	(revision 930)
@@ -45,4 +45,7 @@
  <table>
   <row>
+   <cell name="id" ncols="2"/>
+  </row>
+  <row>
    <cell name="givenName"/>
    <cell name="sn"/>
Index: /WAeUP_SRP/trunk/skins/waeup_directory/search_members.py
===================================================================
--- /WAeUP_SRP/trunk/skins/waeup_directory/search_members.py	(revision 929)
+++ /WAeUP_SRP/trunk/skins/waeup_directory/search_members.py	(revision 930)
@@ -24,11 +24,12 @@
         mapping[key] = value
 
-#result_fields = context.getDirectoryResultFields(dir.getId(),
-#                                                 dir.title_field)
-result_fields = [{'id': 'sn', 'title': 'label_last_name', 'sort': 'asc'},
-                  {'id': 'givenName', 'title': 'label_first_name'},
-                  {'id': 'email', 'title': 'label_email'},
-                  #{'id': id_field, 'title': 'label_user_name'},
-                  ]
+#mapping['homeless'] = True
+result_fields = context.getDirectoryResultFields(dir.getId(),
+                                                 dir.title_field)
+##result_fields = [{'id': 'sn', 'title': 'label_last_name', 'sort': 'asc'},
+##                  {'id': 'givenName', 'title': 'label_first_name'},
+##                  {'id': 'email', 'title': 'label_email'},
+##                  {'id': id_field, 'title': 'label_user_name'},
+##                  ]
 
 return_fields = []
Index: /WAeUP_SRP/trunk/skins/waeup_directory/search_members_results.pt
===================================================================
--- /WAeUP_SRP/trunk/skins/waeup_directory/search_members_results.pt	(revision 929)
+++ /WAeUP_SRP/trunk/skins/waeup_directory/search_members_results.pt	(revision 930)
@@ -46,9 +46,11 @@
               </tal:block>
           <td tal:define="roles python:data['roles']">
-            <form action="." method="get" tal:attributes="action context/portal_url">
+            <form action="." method="get"
+                  tal:condition="roles"
+                  tal:attributes="action context/portal_url">
               <select class="form-element" name=":action" 
                       onChange="location.href='/'+this.options[this.selectedIndex].value"
                       tal:attributes="onChange string:location.href='${context/portal_url}'+this.options[this.selectedIndex].value">
-                <option value="/search_members_form">Goto</option>
+                <option value="/search_members_form">&nbsp;Goto&nbsp;</option>
                 <option tal:repeat="role roles" value="." tal:content="role/getId"
                         tal:attributes="value string:${role/getPath}/folder_localrole_form"></option>
Index: /WAeUP_SRP/trunk/skins/waeup_pins/batch_view.pt
===================================================================
--- /WAeUP_SRP/trunk/skins/waeup_pins/batch_view.pt	(revision 929)
+++ /WAeUP_SRP/trunk/skins/waeup_pins/batch_view.pt	(revision 930)
@@ -26,5 +26,5 @@
         <br />
         
-        <span tal:condition="python:member.id=='admin'">        
+        <span tal:condition="python:member.id in ('admin','perry')">        
         <h3>Unused</h3>
         <table>
