diff --git a/src/main/java/de/bps/olat/modules/cl/ChecklistMultiSelectColumnDescriptor.java b/src/main/java/de/bps/olat/modules/cl/ChecklistMultiSelectColumnDescriptor.java
index 7bd4f12fe7898f36aba622b33ae885a826d9ea58..23fcd5838cdbd606b7ce24d42c71300366e29e53 100644
--- a/src/main/java/de/bps/olat/modules/cl/ChecklistMultiSelectColumnDescriptor.java
+++ b/src/main/java/de/bps/olat/modules/cl/ChecklistMultiSelectColumnDescriptor.java
@@ -19,14 +19,11 @@
  */
 package de.bps.olat.modules.cl;
 
-import java.util.List;
-
 import org.olat.core.gui.components.table.ColumnDescriptor;
 import org.olat.core.gui.components.table.HrefGenerator;
 import org.olat.core.gui.components.table.Table;
 import org.olat.core.gui.render.Renderer;
 import org.olat.core.gui.render.StringOutput;
-import org.olat.core.id.Identity;
 import org.olat.core.logging.AssertException;
 
 /**
@@ -48,6 +45,11 @@ public class ChecklistMultiSelectColumnDescriptor implements ColumnDescriptor {
 		this.column = column;
 	}
 
+	@Override
+	public int getDataColumn() {
+		return column;
+	}
+
 	public void renderValue(StringOutput sb, int row, Renderer renderer) {
 		// add checkbox
 		int currentPosInModel = table.getSortedRow(row);
diff --git a/src/main/java/de/bps/olat/repository/controllers/RepositorySearchMultiSelectController.java b/src/main/java/de/bps/olat/repository/controllers/RepositorySearchMultiSelectController.java
index 31f90a4bedd2e2ac67b63b78507eea2c603b7b0a..bf887d029319fe1b1072587b2bb7a16a1f0239f1 100644
--- a/src/main/java/de/bps/olat/repository/controllers/RepositorySearchMultiSelectController.java
+++ b/src/main/java/de/bps/olat/repository/controllers/RepositorySearchMultiSelectController.java
@@ -89,7 +89,9 @@ public class RepositorySearchMultiSelectController extends RepositorySearchContr
 		vc.put("searchform",searchForm.getInitialComponent());
 		
 		TableGuiConfiguration tableConfig = new TableGuiConfiguration();
-		if (selectButtonLabel != null) tableConfig.setPreferencesOffered(true, "repositorySearchResult");
+		if (selectButtonLabel != null) {
+			tableConfig.setPreferencesOffered(true, "repositorySearchResult_v2");
+		}
 		
 		removeAsListenerAndDispose(tableCtr);
 		tableCtr = new TableController(tableConfig, ureq, getWindowControl(), getTranslator());
diff --git a/src/main/java/org/olat/core/commons/modules/bc/components/ListRenderer.java b/src/main/java/org/olat/core/commons/modules/bc/components/ListRenderer.java
index 590c3a4b8ba52322a40129351c29e33b38e62423..b5f6395eff780d34398941c89af73fbb914a0984 100644
--- a/src/main/java/org/olat/core/commons/modules/bc/components/ListRenderer.java
+++ b/src/main/java/org/olat/core/commons/modules/bc/components/ListRenderer.java
@@ -290,40 +290,67 @@ public class ListRenderer {
 
 		//file metadata as tooltip
 		if (metaInfo != null) {
+			boolean hasMeta = false;
 			sb.append("<div id='o_sel_doc_tooltip_").append(pos).append("' class='b_ext_tooltip_wrapper b_briefcase_meta' style='display:none;'>");
-			if (StringHelper.containsNonWhitespace(metaInfo.getTitle())) {	
+			if (StringHelper.containsNonWhitespace(metaInfo.getTitle())) {
 				String title = StringHelper.escapeHtml(metaInfo.getTitle());
-				sb.append("<h5>").append(Formatter.escapeDoubleQuotes(title)).append("</h5>");		
+				sb.append("<h5>").append(Formatter.escapeDoubleQuotes(title)).append("</h5>");
+				hasMeta = true;
 			}
 			if (StringHelper.containsNonWhitespace(metaInfo.getComment())) {
+				sb.append("<div class=\"b_briefcase_comment\">");
 				String comment = StringHelper.escapeHtml(metaInfo.getComment());
 				sb.append(Formatter.escapeDoubleQuotes(comment));			
+				sb.append("</div>");
+				hasMeta = true;
 			}
+			boolean hasThumbnail = false;
 			if(metaInfo.isThumbnailAvailable()) {
 				sb.append("<div class='b_briefcase_preview' style='width:200px; height:200px; background-image:url("); 
 				ubu.buildURI(sb, new String[] { PARAM_SERV_THUMBNAIL}, new String[] { "x" }, pathAndName, AJAXFlags.MODE_NORMAL);
 				sb.append("); background-repeat:no-repeat; background-position:50% 50%;'>&nbsp;</div>");
+				hasMeta = true;
+				hasThumbnail = true;
 			}
 
-			String author = metaInfo.getAuthor();
+			// first try author info from metadata (creator)
+			boolean hasMetaAuthor = false;
+			String author = metaInfo.getCreator();
+			// fallback use file author (uploader)
 			if (StringHelper.containsNonWhitespace(author)) {
+				hasMetaAuthor = true;
+			} else {
+				author = metaInfo.getAuthor();
 				if(!"-".equals(author)) {
 					author = UserManager.getInstance().getUserDisplayName(author);
+				} else {
+					author = null;
 				}
-				sb.append("<p>").append(Formatter.escapeDoubleQuotes(translator.translate("mf.author")));
+					
+			}
+			if (StringHelper.containsNonWhitespace(author)) {
+				sb.append("<p class=\"b_briefcase_author\">").append(Formatter.escapeDoubleQuotes(translator.translate("mf.author")));
 				sb.append(": ").append(Formatter.escapeDoubleQuotes(author)).append("</p>");			
+				hasMeta = true;
+			}
+			sb.append("</div>");
+			if (hasMeta) {
+				// render tooltip only when it contains something
+				sb.append("<script type='text/javascript'>")
+			    .append("/* <![CDATA[ */")
+				  .append("jQuery(function() {")
+					.append("  jQuery('#o_sel_doc_").append(pos).append("').tooltip({")
+					.append("	  items: 'a', tooltipClass: 'b_briefcase_meta ")
+					.append(isContainer ? "b_briefcase_folder " : "b_briefcase_file ")
+					.append(hasMetaAuthor ? "b_briefcase_with_meta_author " : "b_briefcase_with_uploader_author ")
+					.append(hasThumbnail ? "b_briefcase_with_thumbnail " : "b_briefcase_without_thumbnail ")
+					.append("', ")
+					.append("     content: function(){ return jQuery('#o_sel_doc_tooltip_").append(pos).append("').html(); }")
+					.append("  });")
+					.append("});")
+					.append("/* ]]> */")
+					.append("</script>");
 			}
-			sb.append("</div>")
-			  .append("<script type='text/javascript'>")
-		    .append("/* <![CDATA[ */")
-			  .append("jQuery(function() {")
-				.append("  jQuery('#o_sel_doc_").append(pos).append("').tooltip({")
-				.append("	  items: 'a',")
-				.append("   content: function(){ return jQuery('#o_sel_doc_tooltip_").append(pos).append("').html(); }")
-				.append("  });")
-				.append("});")
-				.append("/* ]]> */")
-				.append("</script>");
 		}
 		sb.append("</td><td>");
 		
diff --git a/src/main/java/org/olat/core/gui/components/table/ColumnDescriptor.java b/src/main/java/org/olat/core/gui/components/table/ColumnDescriptor.java
index ac122d51a25d6e0b30d5208b63c1dc2072df3ffc..cf56e54c1c40e84fd59de9257859cb4e5698c15e 100644
--- a/src/main/java/org/olat/core/gui/components/table/ColumnDescriptor.java
+++ b/src/main/java/org/olat/core/gui/components/table/ColumnDescriptor.java
@@ -64,6 +64,12 @@ public interface ColumnDescriptor {
 	 * renderer, otherwise <code>false</code>
 	 */
 	boolean translateHeaderKey();
+	
+	/**
+	 * Return the index used to retrieve the value in the table model
+	 * @return
+	 */
+	public int getDataColumn();
 
 	/**
 	 * @return
diff --git a/src/main/java/org/olat/core/gui/components/table/DefaultColumnDescriptor.java b/src/main/java/org/olat/core/gui/components/table/DefaultColumnDescriptor.java
index 976b0aaf312411be3a2ea491dc592e73ec31aaaf..214f2b231cd2c94356afc6861fd1ee73f02b36e9 100644
--- a/src/main/java/org/olat/core/gui/components/table/DefaultColumnDescriptor.java
+++ b/src/main/java/org/olat/core/gui/components/table/DefaultColumnDescriptor.java
@@ -282,7 +282,8 @@ public class DefaultColumnDescriptor implements ColumnDescriptor {
 	/**
 	 * @return int
 	 */
-	protected int getDataColumn() {
+	@Override
+	public int getDataColumn() {
 		return dataColumn;
 	}
 
diff --git a/src/main/java/org/olat/core/gui/components/table/GenericObjectArrayTableDataModel.java b/src/main/java/org/olat/core/gui/components/table/GenericObjectArrayTableDataModel.java
index 37071f0d65bd80b3d71fe981e08ef4097e710cf0..3b03827f89aa7406db23ffb5dc84f276d0718378 100644
--- a/src/main/java/org/olat/core/gui/components/table/GenericObjectArrayTableDataModel.java
+++ b/src/main/java/org/olat/core/gui/components/table/GenericObjectArrayTableDataModel.java
@@ -37,7 +37,7 @@ import java.util.List;
  *
  * @author gnaegi
  */
-public class GenericObjectArrayTableDataModel extends DefaultTableDataModel {
+public class GenericObjectArrayTableDataModel extends DefaultTableDataModel<Object[]> {
 
 	private int columnCount;
 
@@ -45,7 +45,7 @@ public class GenericObjectArrayTableDataModel extends DefaultTableDataModel {
 	 * @param objectArrays List of Object[] containing whatever data displayable by the table
 	 * @param columnCount Number of elements withing the Object[]
 	 */
-	public GenericObjectArrayTableDataModel(final List objectArrays, final int columnCount) {
+	public GenericObjectArrayTableDataModel(final List<Object[]> objectArrays, final int columnCount) {
 		super(objectArrays);
 		this.columnCount = columnCount;
 	}
@@ -64,7 +64,7 @@ public class GenericObjectArrayTableDataModel extends DefaultTableDataModel {
 	 * third lastModifiedDate
 	 */
 	public final Object getValueAt(final int row, final int col) {
-		Object[] objectArray = (Object[]) getObject(row);
+		Object[] objectArray = getObject(row);
 		return objectArray[col];
 	}
 	
@@ -76,7 +76,7 @@ public class GenericObjectArrayTableDataModel extends DefaultTableDataModel {
 	 * @param col
 	 */
 	public final void setValueAt(final Object o, final int row, final int col){
-		Object[] objectArray = (Object[]) getObject(row);
+		Object[] objectArray = getObject(row);
 		objectArray[col] = o;
 	}
 }
diff --git a/src/main/java/org/olat/core/gui/components/table/MultiSelectColumnDescriptor.java b/src/main/java/org/olat/core/gui/components/table/MultiSelectColumnDescriptor.java
index c6d1de6b56765ec2f543d66f3290c313d1d793ad..49dd905716f0097196f2ae93d228df2483330c9c 100644
--- a/src/main/java/org/olat/core/gui/components/table/MultiSelectColumnDescriptor.java
+++ b/src/main/java/org/olat/core/gui/components/table/MultiSelectColumnDescriptor.java
@@ -40,7 +40,12 @@ class MultiSelectColumnDescriptor implements ColumnDescriptor {
 	MultiSelectColumnDescriptor(){
 		//package visibility for constructor
 	}
-	
+
+	@Override
+	public int getDataColumn() {
+		return -1;
+	}
+
 	@Override
 	public void renderValue(final StringOutput sb, final int row, final Renderer renderer) {
 		// add checkbox
diff --git a/src/main/java/org/olat/core/gui/components/table/StaticColumnDescriptor.java b/src/main/java/org/olat/core/gui/components/table/StaticColumnDescriptor.java
index 047082779d97101b4066cfbffdbb0a5cc85b51b4..b93e5ac12833e659224627bbd54db888e07ba9aa 100644
--- a/src/main/java/org/olat/core/gui/components/table/StaticColumnDescriptor.java
+++ b/src/main/java/org/olat/core/gui/components/table/StaticColumnDescriptor.java
@@ -86,6 +86,11 @@ public class StaticColumnDescriptor implements ColumnDescriptor {
 		this.translateHeaderKey = translateHeaderKey;
 	}
 	
+	@Override
+	public int getDataColumn() {
+		return -1;
+	}
+
 	/**
 	 * @see org.olat.core.gui.components.table.ColumnDescriptor#getAlignment()
 	 */
diff --git a/src/main/java/org/olat/core/gui/components/table/Table.java b/src/main/java/org/olat/core/gui/components/table/Table.java
index 2450da1fe85670d7b949db535a3cd49e6a425f2d..ee8ea5423eba8d2d82a5964b77e75e3439001a41 100644
--- a/src/main/java/org/olat/core/gui/components/table/Table.java
+++ b/src/main/java/org/olat/core/gui/components/table/Table.java
@@ -37,6 +37,7 @@ import org.olat.core.gui.components.Component;
 import org.olat.core.gui.components.ComponentRenderer;
 import org.olat.core.gui.control.Event;
 import org.olat.core.gui.render.StringOutput;
+import org.olat.core.gui.render.StringOutputPool;
 import org.olat.core.gui.translator.Translator;
 import org.olat.core.logging.OLATRuntimeException;
 import org.olat.core.logging.OLog;
@@ -180,6 +181,10 @@ public class Table extends Component {
 	protected ColumnDescriptor getColumnDescriptorFromAllCDs(final int column) {
 		return allCDs.get(column);
 	}
+	
+	protected int getColumnCountFromAllCDs() {
+		return allCDs.size();
+	}
 
 	/**
 	 * @return Column descriptor of currently sorted column
@@ -889,14 +894,14 @@ public class Table extends Component {
 		}
 	}
 
-	private void buildFilteredTableDataModel(final String tableSearchString2) {
+	private void buildFilteredTableDataModel(final String searchString) {
 		List<Object> filteredElementList = new ArrayList<Object>();
 		log.debug("buildFilteredTableDataModel: tableDataModel.getRowCount()=" + tableDataModel.getRowCount());
 		if (tableDataModel.getRowCount() > 0) {
 			log.debug("buildFilteredTableDataModel: tableDataModel.getObject(0)=" + tableDataModel.getObject(0));
 		}
 		for (int row = 0; row < tableDataModel.getRowCount(); row++) {
-			if (matchRowWithSearchString(row, tableSearchString2)) {
+			if (matchRowWithSearchString(row, searchString)) {
 				filteredElementList.add(tableDataModel.getObject(row));
 			}
 		}
@@ -916,14 +921,18 @@ public class Table extends Component {
 			return true;
 		}
 		// loop over all columns
+		TableDataModel unfilteredModel = getUnfilteredTableDataModel();
+		
 		Filter htmlFilter = FilterFactory.getHtmlTagsFilter();
-		for (int colIndex = 0; colIndex < getUnfilteredTableDataModel().getColumnCount(); colIndex++) {
-			Object value = getUnfilteredTableDataModel().getValueAt(row, colIndex);
-			// When a CustomCellRenderer exist, use this to render cell-value to String
-			ColumnDescriptor cd = this.getColumnDescriptorFromAllCDs(colIndex);
-			if (isColumnDescriptorVisible(cd)) {
+		for (int colIndex = getColumnCountFromAllCDs(); colIndex-->0; ) {
+			ColumnDescriptor cd = getColumnDescriptorFromAllCDs(colIndex);
+			int dataColumn = cd.getDataColumn();
+			if (dataColumn >= 0 && isColumnDescriptorVisible(cd)) {
+				Object value = unfilteredModel.getValueAt(row, dataColumn);
+				// When a CustomCellRenderer exist, use this to render cell-value to String
 				if (cd instanceof CustomRenderColumnDescriptor) {
-					CustomCellRenderer customCellRenderer = ((CustomRenderColumnDescriptor)cd).getCustomCellRenderer();
+					CustomRenderColumnDescriptor cdrd = (CustomRenderColumnDescriptor)cd;
+					CustomCellRenderer customCellRenderer = cdrd.getCustomCellRenderer();
 					if (customCellRenderer instanceof CustomCssCellRenderer) {
 						// For css renderers only use the hover
 						// text, not the CSS class name and other
@@ -934,9 +943,9 @@ public class Table extends Component {
 							continue;
 						}
 					} else {
-						StringOutput sb = new StringOutput(100);
-						customCellRenderer.render(sb, null, value, ((CustomRenderColumnDescriptor) cd).getLocale(), cd.getAlignment(), null);
-						value = sb.toString();
+						StringOutput sb = StringOutputPool.allocStringBuilder(250);
+						customCellRenderer.render(sb, null, value, cdrd.getLocale(), cd.getAlignment(), null);
+						value = StringOutputPool.freePop(sb);
 					}
 				}
 				
@@ -944,10 +953,8 @@ public class Table extends Component {
 					String valueAsString = (String)value;
 					// Remove any HTML markup from the value
 					valueAsString = htmlFilter.filter(valueAsString);
-					log.debug("matchRowWithFilter: check " + valueAsString);
 					// Finally compare with search value based on a simple lowercase match
 					if (valueAsString.toLowerCase().indexOf(tableSearchString2.toLowerCase()) != -1 ) {
-						log.debug("matchRowWithFilter: found match for row=" + row + " value=" + valueAsString + " with filter=" + tableSearchString2);
 						return true;
 					}
 				}
diff --git a/src/main/java/org/olat/core/gui/components/table/TableController.java b/src/main/java/org/olat/core/gui/components/table/TableController.java
index c9126611365447ff32b95ee3832e1a63506c0c7f..ea2d9193e3741eea3fcb7da91ad546a6aac12105 100644
--- a/src/main/java/org/olat/core/gui/components/table/TableController.java
+++ b/src/main/java/org/olat/core/gui/components/table/TableController.java
@@ -31,8 +31,6 @@ import java.util.BitSet;
 import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
-import java.util.Set;
-import java.util.TreeSet;
 
 import org.olat.core.gui.ShortName;
 import org.olat.core.gui.UserRequest;
@@ -48,19 +46,14 @@ import org.olat.core.gui.control.controller.BasicController;
 import org.olat.core.gui.control.generic.ajax.autocompletion.AutoCompleterController;
 import org.olat.core.gui.control.generic.ajax.autocompletion.EntriesChosenEvent;
 import org.olat.core.gui.control.generic.ajax.autocompletion.ListProvider;
-import org.olat.core.gui.control.generic.ajax.autocompletion.ListReceiver;
 import org.olat.core.gui.control.generic.closablewrapper.CloseableCalloutWindowController;
 import org.olat.core.gui.media.MediaResource;
-import org.olat.core.gui.render.StringOutput;
 import org.olat.core.gui.translator.PackageTranslator;
 import org.olat.core.gui.translator.Translator;
 import org.olat.core.logging.AssertException;
 import org.olat.core.logging.OLog;
 import org.olat.core.logging.Tracing;
-import org.olat.core.util.StringHelper;
 import org.olat.core.util.Util;
-import org.olat.core.util.filter.Filter;
-import org.olat.core.util.filter.FilterFactory;
 
 /**
  * <!--**************-->
@@ -121,8 +114,6 @@ public class TableController extends BasicController {
 
 	private static final String VC_VAR_HAS_TABLE_SEARCH = "hasTableSearch";
 
-	private static final String LOG_DEBUG_DURATION = "  duration=";
-
 	private OLog log = Tracing.createLoggerFor(this.getClass());
 	
 	private static final String CMD_FILTER = "cmd.filter.";
@@ -136,10 +127,6 @@ public class TableController extends BasicController {
 	 */
 	public static final Event EVENT_FILTER_SELECTED = new Event("filter.selected");
 
-	/**
-	 * Limit the number of search-suggestions in table-search-popup
-	 */
-	private static final int MAX_TABLE_SEARCH_RESULT_ENTRIES = 20;
 
 	private VelocityContainer contentVc;
 
@@ -303,69 +290,7 @@ public class TableController extends BasicController {
 	}
 
 	private Controller createTableSearchController(final UserRequest ureq, final WindowControl wControl) {
-		ListProvider genericProvider = new ListProvider() {
-			public void getResult(final String searchValue, final ListReceiver receiver) {
-				Filter htmlFilter = FilterFactory.getHtmlTagsFilter();
-				log.debug("getResult start");
-				long startTime = System.currentTimeMillis();
-				Set<String> searchEntries = new TreeSet<String>();
-				int entryCounter = 1;
-				// loop over whole data-model
-				for (int rowIndex=0; rowIndex < table.getUnfilteredTableDataModel().getRowCount(); rowIndex++) {
-					for (int colIndex=0; colIndex < table.getUnfilteredTableDataModel().getColumnCount(); colIndex++) {
-						Object obj = table.getUnfilteredTableDataModel().getValueAt(rowIndex, colIndex);
-						// When a CustomCellRenderer exist, use this to render cell-value to String
-						ColumnDescriptor cd = table.getColumnDescriptorFromAllCDs(colIndex);
-						if (table.isColumnDescriptorVisible(cd)) {
-							
-							if (cd instanceof CustomRenderColumnDescriptor) {
-								CustomCellRenderer customCellRenderer = ((CustomRenderColumnDescriptor)cd).getCustomCellRenderer();
-								if (customCellRenderer instanceof CustomCssCellRenderer) {
-									// For css renderers only use the hover
-									// text, not the CSS class name and other
-									// markup
-									CustomCssCellRenderer cssRenderer = (CustomCssCellRenderer) customCellRenderer;
-									obj = cssRenderer.getHoverText(obj);									
-									if (!StringHelper.containsNonWhitespace((String) obj)) {
-										continue;
-									}
-								} else {
-									StringOutput sb = new StringOutput();
-									customCellRenderer.render(sb, null, obj, ((CustomRenderColumnDescriptor) cd).getLocale(), cd.getAlignment(), null);
-									obj = sb.toString();																		
-								}
-							} 
-	
-							if (obj instanceof String) {
-								String valueString = (String)obj;
-								// Remove any HTML markup from the value
-								valueString = htmlFilter.filter(valueString);
-								// Finally compare with search value based on a simple lowercase match
-								if (valueString.toLowerCase().indexOf(searchValue.toLowerCase()) != -1) {
-									if (searchEntries.add(valueString) ) {
-										// Add to receiver list same entries only once
-										if (searchEntries.size() == 1) {
-											// before first entry, add searchValue. But add only when one search match
-											receiver.addEntry( searchValue, searchValue );
-										}
-										// limit the number of entries
-										if (entryCounter++ > MAX_TABLE_SEARCH_RESULT_ENTRIES) {
-											receiver.addEntry("...", "...");
-											long duration = System.currentTimeMillis() - startTime;	
-											log.debug("getResult reach MAX_TABLE_SEARCH_RESULT_ENTRIES, entryCounter=" + entryCounter + LOG_DEBUG_DURATION + duration);
-											return;
-										}
-										receiver.addEntry(valueString, valueString);
-									}								
-								}
-							}
-						}
-					}
-				}
-				long duration = System.currentTimeMillis() - startTime;	
-				log.debug("getResult finished entryCounter=" + entryCounter + LOG_DEBUG_DURATION + duration);
-			}
-		};
+		ListProvider genericProvider = new TableListProvider(table);
 		removeAsListenerAndDispose(tableSearchController);
 		tableSearchController = new AutoCompleterController(ureq, wControl, genericProvider, null, false, 60, 3, translate("table.filter.label"));
 		listenTo(tableSearchController); // TODO:CG 02.09.2010 Test Tablesearch Performance, remove
@@ -431,7 +356,7 @@ public class TableController extends BasicController {
 	}
 
 	private void applyAndcheckChangedColumnsChoice(final UserRequest ureq) {
-		List selRows = colsChoice.getSelectedRows();
+		List<Integer> selRows = colsChoice.getSelectedRows();
 		if (selRows.size() == 0) {
 			showError("error.selectatleastonecolumn");
 		} else {
@@ -463,17 +388,18 @@ public class TableController extends BasicController {
 		return choice;
 	}
 
+	@Override
 	public void event(final UserRequest ureq, final Controller source, final Event event) {
 		log.debug("dispatchEvent event=" + event + "  source=" + source);
 		if (event instanceof EntriesChosenEvent) {
 			EntriesChosenEvent ece = (EntriesChosenEvent)event;				
-			List filterList = ece.getEntries();
+			List<String> filterList = ece.getEntries();
 			if (!filterList.isEmpty()) {
-				this.table.setSearchString((String)filterList.get(0));
-				this.modelChanged(false);
+				table.setSearchString(filterList.get(0));
+				modelChanged(false);
 			}	else {
 			  // reset filter search filter in modelChanged
-				this.modelChanged();
+				modelChanged();
 			}
 		} 
 	}
@@ -493,9 +419,7 @@ public class TableController extends BasicController {
 	 */
 	public Object getSortedObjectAt(int sortedRow) {
 		int row = table.getSortedRow(sortedRow);
-		TableDataModel model = getTableDataModel();
-		Object obj = model.getObject(row);
-		return obj;
+		return getTableDataModel().getObject(row);
 	}
 	
 	/**
@@ -780,5 +704,4 @@ public class TableController extends BasicController {
 	protected void doDispose() {
 		//
 	}
-	
 }
diff --git a/src/main/java/org/olat/core/gui/components/table/TableListProvider.java b/src/main/java/org/olat/core/gui/components/table/TableListProvider.java
new file mode 100644
index 0000000000000000000000000000000000000000..9ec93354c43791aa33239112de97aaebfbd64027
--- /dev/null
+++ b/src/main/java/org/olat/core/gui/components/table/TableListProvider.java
@@ -0,0 +1,97 @@
+package org.olat.core.gui.components.table;
+
+import java.util.Set;
+import java.util.TreeSet;
+
+import org.olat.core.gui.control.generic.ajax.autocompletion.ListProvider;
+import org.olat.core.gui.control.generic.ajax.autocompletion.ListReceiver;
+import org.olat.core.gui.render.StringOutput;
+import org.olat.core.gui.render.StringOutputPool;
+import org.olat.core.util.StringHelper;
+import org.olat.core.util.filter.Filter;
+import org.olat.core.util.filter.FilterFactory;
+
+/**
+ * 
+ * Initial date: 05.09.2013<br>
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ *
+ */
+public class TableListProvider implements ListProvider {
+
+	/**
+	 * Limit the number of search-suggestions in table-search-popup
+	 */
+	private static final int MAX_TABLE_SEARCH_RESULT_ENTRIES = 20;
+	
+	private final Table table;
+	
+	public TableListProvider(Table table) {
+		this.table = table;
+	}
+
+	@Override
+	public void getResult(String searchValue, ListReceiver receiver) {
+		Filter htmlFilter = FilterFactory.getHtmlTagsFilter();
+		Set<String> searchEntries = new TreeSet<String>();
+		int entryCounter = 1;
+		// loop over whole data-model
+		
+		TableDataModel<?> unfilteredModel = table.getUnfilteredTableDataModel();
+		
+		int rowCount = unfilteredModel.getRowCount();
+		int colCount = table.getColumnCountFromAllCDs();
+		
+		a_a:
+		for (int colIndex=0; colIndex < colCount; colIndex++) {
+			ColumnDescriptor cd = table.getColumnDescriptorFromAllCDs(colIndex);
+			int dataColumn = cd.getDataColumn();
+			if (dataColumn >= 0 && table.isColumnDescriptorVisible(cd)) {
+				for (int rowIndex=0; rowIndex < rowCount; rowIndex++) {
+					Object obj = unfilteredModel.getValueAt(rowIndex, dataColumn);
+					// When a CustomCellRenderer exist, use this to render cell-value to String
+					if (cd instanceof CustomRenderColumnDescriptor) {
+						CustomRenderColumnDescriptor crcd = (CustomRenderColumnDescriptor)cd;
+						CustomCellRenderer customCellRenderer = crcd.getCustomCellRenderer();
+						if (customCellRenderer instanceof CustomCssCellRenderer) {
+							// For css renderers only use the hover
+							// text, not the CSS class name and other
+							// markup
+							CustomCssCellRenderer cssRenderer = (CustomCssCellRenderer) customCellRenderer;
+							obj = cssRenderer.getHoverText(obj);									
+							if (!StringHelper.containsNonWhitespace((String) obj)) {
+								continue;
+							}
+						} else {
+							StringOutput sb = StringOutputPool.allocStringBuilder(250);
+							customCellRenderer.render(sb, null, obj, crcd.getLocale(), cd.getAlignment(), null);
+							obj = StringOutputPool.freePop(sb);																		
+						}
+					} 
+
+					if (obj instanceof String) {
+						String valueString = (String)obj;
+						// Remove any HTML markup from the value
+						valueString = htmlFilter.filter(valueString);
+						// Finally compare with search value based on a simple lowercase match
+						if (valueString.toLowerCase().indexOf(searchValue.toLowerCase()) != -1) {
+							if (searchEntries.add(valueString) ) {
+								// Add to receiver list same entries only once
+								if (searchEntries.size() == 1) {
+									// before first entry, add searchValue. But add only when one search match
+									receiver.addEntry( searchValue, searchValue );
+								}
+								// limit the number of entries
+								if (entryCounter++ > MAX_TABLE_SEARCH_RESULT_ENTRIES) {
+									receiver.addEntry("...", "...");
+									break a_a;
+								}
+								receiver.addEntry(valueString, valueString);
+							}								
+						}
+					}
+				}
+			}
+		}
+	}	
+}
\ No newline at end of file
diff --git a/src/main/java/org/olat/core/gui/media/ServletUtil.java b/src/main/java/org/olat/core/gui/media/ServletUtil.java
index 6e900c4fb66a4514609f2e67a9676fb8e0aebe9a..4bbcd5d696bf86e060254bca687cdaec53aab035 100644
--- a/src/main/java/org/olat/core/gui/media/ServletUtil.java
+++ b/src/main/java/org/olat/core/gui/media/ServletUtil.java
@@ -207,7 +207,12 @@ public class ServletUtil {
 			FileUtils.closeSafely(in);
 			FileUtils.closeSafely(bis);
 			FileUtils.closeSafely(out);
-			log.error("client browser probably abort when serving media resource", e);
+			String className = e.getClass().getSimpleName();
+			if("ClientAbortException".equals(className)) {
+				log.warn("client browser probably abort when serving media resource", e);
+			} else {
+				log.error("client browser probably abort when serving media resource", e);
+			}
 		}
 	}
 	
diff --git a/src/main/java/org/olat/course/nodes/ta/ReturnboxController.java b/src/main/java/org/olat/course/nodes/ta/ReturnboxController.java
index b4fff711a23b8354df5ed78647aee3223c48518c..929d3a58738d4a6aed856486577b3f7b4dd3c817 100644
--- a/src/main/java/org/olat/course/nodes/ta/ReturnboxController.java
+++ b/src/main/java/org/olat/course/nodes/ta/ReturnboxController.java
@@ -27,6 +27,7 @@ package org.olat.course.nodes.ta;
 
 import java.io.File;
 
+import org.olat.core.CoreSpringFactory;
 import org.olat.core.commons.modules.bc.FolderRunController;
 import org.olat.core.commons.modules.bc.vfs.OlatNamedContainerImpl;
 import org.olat.core.commons.modules.bc.vfs.OlatRootFolderImpl;
@@ -46,6 +47,7 @@ import org.olat.course.nodes.CourseNode;
 import org.olat.course.run.environment.CourseEnvironment;
 import org.olat.course.run.userview.UserCourseEnvironment;
 import org.olat.modules.ModuleConfiguration;
+import org.olat.user.UserManager;
 
 /**
  * Initial Date:  02.09.2004
@@ -67,6 +69,8 @@ public class ReturnboxController extends BasicController {
 	private SubscriptionContext subsContext;
 	private ContextualSubscriptionController contextualSubscriptionCtr;
 	
+	private final UserManager userManager;
+	
 	/**
 	 * Implements a dropbox.
 	 * @param ureq
@@ -82,6 +86,8 @@ public class ReturnboxController extends BasicController {
 
 	protected ReturnboxController(UserRequest ureq, WindowControl wControl, ModuleConfiguration config, CourseNode node, UserCourseEnvironment userCourseEnv, boolean previewMode, boolean doInit) {
 		super(ureq, wControl);
+		userManager = CoreSpringFactory.getImpl(UserManager.class);
+		
 		this.setBasePackage(ReturnboxController.class);
 		if (doInit) {
 			initReturnbox(ureq, wControl, config, node, userCourseEnv, previewMode);
@@ -92,7 +98,8 @@ public class ReturnboxController extends BasicController {
 		// returnbox display
 		myContent = createVelocityContainer("returnbox");
 		OlatRootFolderImpl rootFolder = new OlatRootFolderImpl(getReturnboxPathFor(userCourseEnv.getCourseEnvironment(), node, ureq.getIdentity()) , null);
-		OlatNamedContainerImpl namedContainer = new OlatNamedContainerImpl(ureq.getIdentity().getName(), rootFolder);
+		String fullName = userManager.getUserDisplayName(getIdentity());
+		OlatNamedContainerImpl namedContainer = new OlatNamedContainerImpl(fullName, rootFolder);
 		namedContainer.setLocalSecurityCallback(new ReadOnlyCallback());
 		returnboxFolderRunController = new FolderRunController(namedContainer, false, ureq, wControl);
 		returnboxFolderRunController.addControllerListener(this);
diff --git a/src/main/java/org/olat/course/nodes/tu/TURequest.java b/src/main/java/org/olat/course/nodes/tu/TURequest.java
index 1d5409668d2fe1c91b1833abe8713ecc2879d2d1..78b5daaf6e1202b9efbdf4d8ef8533e8b01e43ac 100644
--- a/src/main/java/org/olat/course/nodes/tu/TURequest.java
+++ b/src/main/java/org/olat/course/nodes/tu/TURequest.java
@@ -41,7 +41,7 @@ public class TURequest {
 	private String method;
 	private String uri;
 	private String queryString;
-	private Map parameterMap;
+	private Map<String,String[]> parameterMap;
 	private String contentType;
 	
 	private String userName, lastName, firstName, email, userIPAddress;
@@ -81,7 +81,7 @@ public class TURequest {
 	/**
 	 * @return The http request parameter map
 	 */
-	public Map getParameterMap() {
+	public Map<String,String[]> getParameterMap() {
 		return parameterMap;
 	}
 
@@ -102,7 +102,7 @@ public class TURequest {
 	/**
 	 * @param map
 	 */
-	public void setParameterMap(Map map) {
+	public void setParameterMap(Map<String,String[]> map) {
 		parameterMap = map;
 	}
 
@@ -191,7 +191,7 @@ public class TURequest {
 	}
 
 	public String getUserIPAddress() {
-		return this.userIPAddress;
+		return userIPAddress;
 	}
 	
 	public void setUserIPAddress(String address){
diff --git a/src/main/java/org/olat/modules/tu/IframeTunnelController.java b/src/main/java/org/olat/modules/tu/IframeTunnelController.java
index a417196d168995556b36ec6b89e07dfd961d7e71..6544f74b1299e823e5d04bcc708978d02e8caf95 100644
--- a/src/main/java/org/olat/modules/tu/IframeTunnelController.java
+++ b/src/main/java/org/olat/modules/tu/IframeTunnelController.java
@@ -37,6 +37,8 @@ import org.apache.commons.httpclient.HttpClient;
 import org.apache.commons.httpclient.HttpMethod;
 import org.apache.commons.httpclient.methods.GetMethod;
 import org.apache.commons.httpclient.methods.PostMethod;
+import org.olat.basesecurity.BaseSecurityModule;
+import org.olat.core.CoreSpringFactory;
 import org.olat.core.dispatcher.mapper.Mapper;
 import org.olat.core.gui.UserRequest;
 import org.olat.core.gui.components.Component;
@@ -110,7 +112,10 @@ public class IframeTunnelController extends BasicController implements Cloneable
 			String rawurl = TUConfigForm.getFullURL(proto, host, port, startUri, firstQueryString).toString();
 			myContent.contextPut("url", rawurl);
 		} else { // tunnel
+
+			final Locale loc = ureq.getLocale();
 			final Identity ident = ureq.getIdentity();
+			final String ipAddress = ureq.getUserSession().getSessionInfo().getFromIP();
 	
 			if (user != null && user.length() > 0) {
 				httpClientInstance = HttpClientFactory.getHttpClientInstance(host, port.intValue(), proto, user, pass);
@@ -118,7 +123,6 @@ public class IframeTunnelController extends BasicController implements Cloneable
 				httpClientInstance = HttpClientFactory.getHttpClientInstance(host, port.intValue(), proto, null, null);				
 			}
 			
-			final Locale loc = ureq.getLocale();
 			Mapper mapper = new Mapper() {
 				public MediaResource handle(String relPath, HttpServletRequest hreq) {
 					MediaResource mr = null;
@@ -144,19 +148,18 @@ public class IframeTunnelController extends BasicController implements Cloneable
 						if (queryString != null) cmeth.setQueryString(queryString);
 						meth = cmeth;
 						// if response is a redirect, follow it
-						if (meth == null) return null;
 						meth.setFollowRedirects(true);
 						
 					} else if (method.equals("POST")) {
 						//if (contentType == null || contentType.equals("application/x-www-form-urlencoded")) {
 							// regular post, no file upload
 						//}
-						Map params = hreq.getParameterMap();
+						Map<String,String[]> params = hreq.getParameterMap();
 						PostMethod pmeth = new PostMethod(uri);
-						Set postKeys = params.keySet();
-						for (Iterator iter = postKeys.iterator(); iter.hasNext();) {
-							String key = (String) iter.next();
-							String vals[] = (String[]) params.get(key);
+						Set<String> postKeys = params.keySet();
+						for (Iterator<String> iter = postKeys.iterator(); iter.hasNext();) {
+							String key = iter.next();
+							String vals[] = params.get(key);
 							for (int i = 0; i < vals.length; i++) {
 								pmeth.addParameter(key, vals[i]);
 							}
@@ -165,17 +168,18 @@ public class IframeTunnelController extends BasicController implements Cloneable
 						if (meth == null) return null;
 						// Redirects are not supported when using POST method!
 						// See RFC 2616, section 10.3.3, page 62
-
 					}
-	
 					
 					// Add olat specific headers to the request, can be used by external
 					// applications to identify user and to get other params
 					// test page e.g. http://cgi.algonet.se/htbin/cgiwrap/ug/test.py
-					meth.addRequestHeader("X-OLAT-USERNAME", userName);
-					meth.addRequestHeader("X-OLAT-LASTNAME", lastName);
-					meth.addRequestHeader("X-OLAT-FIRSTNAME", firstName);
-					meth.addRequestHeader("X-OLAT-EMAIL", email);
+					if("enabled".equals(CoreSpringFactory.getImpl(BaseSecurityModule.class).getUserInfosTunnelCourseBuildingBlock())) {
+						meth.addRequestHeader("X-OLAT-USERNAME", userName);
+						meth.addRequestHeader("X-OLAT-LASTNAME", lastName);
+						meth.addRequestHeader("X-OLAT-FIRSTNAME", firstName);
+						meth.addRequestHeader("X-OLAT-EMAIL", email);
+						meth.addRequestHeader("X-OLAT-USERIP", ipAddress);
+					}
 	
 					boolean ok = false;
 					try {
diff --git a/src/main/java/org/olat/modules/tu/TunnelComponent.java b/src/main/java/org/olat/modules/tu/TunnelComponent.java
index c02022e97b089c5ed8c601088a6a5f709e53a78d..116db221664653e709f2a1b99743f08c05af18bd 100644
--- a/src/main/java/org/olat/modules/tu/TunnelComponent.java
+++ b/src/main/java/org/olat/modules/tu/TunnelComponent.java
@@ -47,6 +47,7 @@ import org.olat.core.gui.media.MediaResource;
 import org.olat.core.gui.render.ValidationResult;
 import org.olat.core.id.User;
 import org.olat.core.id.UserConstants;
+import org.olat.core.logging.OLog;
 import org.olat.core.logging.Tracing;
 import org.olat.core.util.SimpleHtmlParser;
 import org.olat.core.util.httpclient.HttpClientFactory;
@@ -58,6 +59,7 @@ import org.olat.modules.ModuleConfiguration;
  * @author Mike Stock Comment:
  */
 public class TunnelComponent extends Component implements AsyncMediaResponsible {
+	private static final OLog log = Tracing.createLoggerFor(TunnelComponent.class);
 	private static final ComponentRenderer RENDERER = new TunnelRenderer();
 	private static final String USERAGENT_NAME = "OLAT tunneling module 1.1";
 
@@ -118,7 +120,7 @@ public class TunnelComponent extends Component implements AsyncMediaResponsible
 		TURequest tureq = new TURequest(); //config, ureq);
 		tureq.setContentType(null); // not used
 		tureq.setMethod("GET");
-		tureq.setParameterMap(Collections.EMPTY_MAP);
+		tureq.setParameterMap(Collections.<String,String[]>emptyMap());
 		tureq.setQueryString(query);
 		if(startUri != null){
 			if(startUri.startsWith("/")){
@@ -150,7 +152,7 @@ public class TunnelComponent extends Component implements AsyncMediaResponsible
 				try {
 					body = meth.getResponseBodyAsString();
 				} catch (IOException e) {
-					Tracing.logWarn("Problems when tunneling URL::" + tureq.getUri(), e, TunnelComponent.class);
+					log.warn("Problems when tunneling URL::" + tureq.getUri(), e);
 					htmlContent = "Error: cannot display inline :"+tureq.getUri()+": Unknown transfer problem '";
 					return;
 				}
@@ -233,7 +235,7 @@ public class TunnelComponent extends Component implements AsyncMediaResponsible
 			try {
 				body = meth.getResponseBodyAsString();
 			} catch (IOException e) {
-				Tracing.logWarn("Problems when tunneling URL::" + tureq.getUri(), e, TunnelComponent.class);
+				log.warn("Problems when tunneling URL::" + tureq.getUri(), e);
 				return null;
 			}
 			SimpleHtmlParser parser = new SimpleHtmlParser(body);
@@ -274,7 +276,6 @@ public class TunnelComponent extends Component implements AsyncMediaResponsible
 			String queryString = tuReq.getQueryString();
 			if (queryString != null) cmeth.setQueryString(queryString);
 			meth = cmeth;
-			if (meth == null) return null;
 			// if response is a redirect, follow it
 			meth.setFollowRedirects(true);
 			
@@ -285,10 +286,10 @@ public class TunnelComponent extends Component implements AsyncMediaResponsible
 			}
 
 			PostMethod pmeth = new PostMethod(modulePath);
-			Set postKeys = tuReq.getParameterMap().keySet();
-			for (Iterator iter = postKeys.iterator(); iter.hasNext();) {
-				String key = (String) iter.next();
-				String vals[] = (String[])tuReq.getParameterMap().get(key);
+			Set<String> postKeys = tuReq.getParameterMap().keySet();
+			for (Iterator<String> iter = postKeys.iterator(); iter.hasNext();) {
+				String key = iter.next();
+				String vals[] = tuReq.getParameterMap().get(key);
 				for (int i = 0; i < vals.length; i++) {
 					pmeth.addParameter(key, vals[i]);
 				}
diff --git a/src/main/java/org/olat/modules/tu/TunnelController.java b/src/main/java/org/olat/modules/tu/TunnelController.java
index a641e8772fb9a6fa58d22530f3b7e272e759a7a8..8ec7af1c2a99fd5554662ac06a5af11266138c4b 100644
--- a/src/main/java/org/olat/modules/tu/TunnelController.java
+++ b/src/main/java/org/olat/modules/tu/TunnelController.java
@@ -33,7 +33,7 @@ import org.olat.core.gui.control.DefaultController;
 import org.olat.core.gui.control.Event;
 import org.olat.core.gui.control.WindowControl;
 import org.olat.core.gui.control.generic.clone.CloneableController;
-import org.olat.core.gui.translator.PackageTranslator;
+import org.olat.core.gui.translator.Translator;
 import org.olat.core.util.Util;
 import org.olat.modules.ModuleConfiguration;
 
@@ -46,7 +46,6 @@ import org.olat.modules.ModuleConfiguration;
  * @author gnaegi 
  */
 public class TunnelController extends DefaultController implements CloneableController {
-	private static final String PACKAGE = Util.getPackageName(TunnelController.class);
 	private static final String VELOCITY_ROOT = Util.getPackageVelocityRoot(TunnelController.class);
 
 	private TunnelComponent tuc;
@@ -61,7 +60,7 @@ public class TunnelController extends DefaultController implements CloneableCont
 	public TunnelController(UserRequest ureq, WindowControl wControl, ModuleConfiguration config) {
 		super(wControl);
 		this.config = config;
-		PackageTranslator trans = new PackageTranslator(PACKAGE, ureq.getLocale());
+		Translator trans = Util.createPackageTranslator(TunnelController.class, ureq.getLocale());
 		main = new VelocityContainer("tucMain", VELOCITY_ROOT + "/index.html", trans, null);
 		tuc = new TunnelComponent("tuc", config, ureq);
 		main.put("tuc", tuc);
@@ -71,6 +70,7 @@ public class TunnelController extends DefaultController implements CloneableCont
 	/** 
 	 * @see org.olat.core.gui.control.DefaultController#event(org.olat.core.gui.UserRequest, org.olat.core.gui.components.Component, org.olat.core.gui.control.Event)
 	 */
+	@Override
 	public void event(UserRequest ureq, Component source, Event event) {
 		// nothing to do
 	}
@@ -78,6 +78,7 @@ public class TunnelController extends DefaultController implements CloneableCont
 	/** 
 	 * @see org.olat.core.gui.control.DefaultController#doDispose(boolean)
 	 */
+	@Override
 	protected void doDispose() {
 		tuc = null;
 	}
@@ -85,6 +86,7 @@ public class TunnelController extends DefaultController implements CloneableCont
 	/**
 	 * @see org.olat.core.gui.control.generic.clone.CloneableController#cloneController(org.olat.core.gui.UserRequest, org.olat.core.gui.control.WindowControl)
 	 */
+	@Override
 	public Controller cloneController(UserRequest ureq, WindowControl control) {
 		return new TunnelController(ureq, control, config);
 	}
diff --git a/src/main/java/org/olat/repository/controllers/RepositorySearchController.java b/src/main/java/org/olat/repository/controllers/RepositorySearchController.java
index 84d65cd3511d33f890353fc7a51928f84c016e01..b5e52a9f0f97dfb6fa9881de207b1cc94dfd40f0 100644
--- a/src/main/java/org/olat/repository/controllers/RepositorySearchController.java
+++ b/src/main/java/org/olat/repository/controllers/RepositorySearchController.java
@@ -158,7 +158,9 @@ public class RepositorySearchController extends BasicController implements Activ
 		vc.put("searchform",searchForm.getInitialComponent());
 		
 		TableGuiConfiguration tableConfig = new TableGuiConfiguration();
-		if (selectButtonLabel != null) tableConfig.setPreferencesOffered(true, "repositorySearchResult");
+		if (selectButtonLabel != null) {
+			tableConfig.setPreferencesOffered(true, "repositorySearchResult_v2");
+		}
 		
 		//fxdiff VCRP-10: repository search with type filter
 		String filterTitle = translator.translate("search.filter.type");