From f9ea12d69864c2618c21240143f8420ac06f8091 Mon Sep 17 00:00:00 2001
From: gnaegi <none@none>
Date: Fri, 5 Aug 2011 12:05:25 +0200
Subject: [PATCH] FXOLAT-193 OLAT-6439 truncate EP maps title and description
 to max DB length minus 1/3 for savety in case of legacy MySQL
 useOldUTF8Behavior which is still used by UZH

--HG--
branch : uzhFixes711
---
 .../model/structel/EPStructureElement.java    | 12 ++--
 .../persistence/PersistenceHelper.java        | 64 +++++++++++++++++++
 .../_spring/databaseCorecontext.xml           |  9 ++-
 3 files changed, 79 insertions(+), 6 deletions(-)

diff --git a/olat3/webapp/WEB-INF/src/org/olat/portfolio/model/structel/EPStructureElement.java b/olat3/webapp/WEB-INF/src/org/olat/portfolio/model/structel/EPStructureElement.java
index f0aa61199b8..47110da1326 100755
--- a/olat3/webapp/WEB-INF/src/org/olat/portfolio/model/structel/EPStructureElement.java
+++ b/olat3/webapp/WEB-INF/src/org/olat/portfolio/model/structel/EPStructureElement.java
@@ -23,8 +23,10 @@ package org.olat.portfolio.model.structel;
 import java.util.ArrayList;
 import java.util.List;
 
+import org.olat.core.commons.persistence.PersistenceHelper;
 import org.olat.core.commons.persistence.PersistentObject;
 import org.olat.core.id.OLATResourceable;
+import org.olat.core.util.Formatter;
 import org.olat.core.util.filter.FilterFactory;
 import org.olat.portfolio.model.restriction.CollectRestriction;
 import org.olat.resource.OLATResource;
@@ -84,7 +86,8 @@ public class EPStructureElement extends PersistentObject implements PortfolioStr
 	 * @uml.property  name="title"
 	 */
 	public void setTitle(String title) {
-		this.title = title;
+		// OLAT-6439 truncate to allowed database limit
+		this.title = PersistenceHelper.truncateStringDbSave(title, 512, true);
 	}
 
 	/**
@@ -107,7 +110,8 @@ public class EPStructureElement extends PersistentObject implements PortfolioStr
 	 * @uml.property  name="description"
 	 */
 	public void setDescription(String description) {
-		this.description = description;
+		// OLAT-6439 truncate to allowed database limit
+		this.description = PersistenceHelper.truncateStringDbSave(description, 2024, true);
 	}
 	
 	
@@ -120,9 +124,7 @@ public class EPStructureElement extends PersistentObject implements PortfolioStr
 		} else if(desc.length() > 50) {
 			//to remain valid html: remove html tags
 			desc = FilterFactory.getHtmlTagAndDescapingFilter().filter(desc);
-			if(desc.length() > 50) {
-				desc = desc.substring(0, 50) + "...";
-			}
+			desc = Formatter.truncate(desc, 50);
 		}
 		return desc;
 	}
diff --git a/olatcore/src/main/java/org/olat/core/commons/persistence/PersistenceHelper.java b/olatcore/src/main/java/org/olat/core/commons/persistence/PersistenceHelper.java
index 1614ef45cb8..631e3e13cfa 100644
--- a/olatcore/src/main/java/org/olat/core/commons/persistence/PersistenceHelper.java
+++ b/olatcore/src/main/java/org/olat/core/commons/persistence/PersistenceHelper.java
@@ -23,8 +23,11 @@ package org.olat.core.commons.persistence;
 
 import java.util.Iterator;
 import java.util.List;
+import java.util.Properties;
 
 import org.olat.core.id.Persistable;
+import org.olat.core.util.Formatter;
+import org.olat.core.util.filter.FilterFactory;
 
 /**
  * Description:<BR>
@@ -35,6 +38,67 @@ import org.olat.core.id.Persistable;
  * @author gnaegi 
  */
 public class PersistenceHelper {
+	private static boolean charCountNativeUTF8 = true;
+	
+	/**
+	 * Spring only constructor. Use static methods to access the helper
+	 * @param firstKeyValues init properties from spring
+	 */
+	public PersistenceHelper(Properties firstKeyValues) {
+		// OLAT-6439 Init flag to know if the database understands native UTF-8 
+		// Only necessary for old MySQL database of UZH
+		if (firstKeyValues != null) {
+			String dbvendor = firstKeyValues.getProperty("dbvendor");
+			String dboptions = firstKeyValues.getProperty("mysqloptions");
+			if ("mysql".equals(dbvendor) && dboptions != null && dboptions.contains("characterEncoding=UTF-8") && dboptions.contains("useOldUTF8Behavior=true")) {
+				charCountNativeUTF8 = false; 
+			}		
+		}
+	}
+
+	/**
+	 * Truncate the given original string to the defined max length. The method
+	 * does also check if some legacy UTF-8 conversion is done by the database
+	 * driver and shortens the allowed length to two third to be on the save
+	 * side
+	 * 
+	 * @param original
+	 *            The original String
+	 * @param maxLength
+	 *            The max length allowed by the database schema
+	 * @param showThreeDots
+	 *            Replace the last three characters with ... to indicate that
+	 *            the string has been truncated
+	 * @return The truncated string
+	 */
+	public static String truncateStringDbSave(final String original, int maxLength, final boolean showThreeDots) {
+		if (original == null) {
+			return null;
+		}  
+		if (!charCountNativeUTF8) {
+			// When using legacy UTF-8 conversion we have actually no idea how
+			// long the string can be since this is a hidden information to
+			// MySQL. In that case we subtract 1/3 and cross our fingers
+			maxLength = maxLength - (maxLength/3);
+		}
+		// Check if too long
+		int length = original.length();
+		if (length <= maxLength) {
+			return original;
+		}
+		// 1) Remove all HTML markup first as truncating could lead to invalid HTML code. 
+		String result = FilterFactory.getHtmlTagAndDescapingFilter().filter(original);
+		if (length <= maxLength) {
+			return original;
+		}
+		// 2) Truncate to maxLength
+		if (showThreeDots) {
+			result = Formatter.truncate(result, maxLength);			
+		} else {
+			result = Formatter.truncateOnly(result, maxLength);
+		}
+		return result;
+	}
 
 	/**
 	 * 
diff --git a/olatcore/src/main/java/org/olat/core/commons/persistence/_spring/databaseCorecontext.xml b/olatcore/src/main/java/org/olat/core/commons/persistence/_spring/databaseCorecontext.xml
index 05bf9a33a8b..25de2aa6992 100644
--- a/olatcore/src/main/java/org/olat/core/commons/persistence/_spring/databaseCorecontext.xml
+++ b/olatcore/src/main/java/org/olat/core/commons/persistence/_spring/databaseCorecontext.xml
@@ -95,7 +95,14 @@
 	<property name="sessionFactory" ref="sessionFactory"/>
 </bean>
 
-
+<bean id="persistenceHelper" class="org.olat.core.commons.persistence.PersistenceHelper">
+	<constructor-arg>
+		<props>
+			<prop key="dbvendor">${db.vendor}</prop>
+	        <prop key="mysqloptions">${db.url.options.mysql}</prop>
+	    </props>
+	</constructor-arg>
+</bean>
 
 <bean id="mysqlHibernateProperties" class="org.olat.core.commons.persistence.DBVendorHibernatePropertiesSimplification">
 	<constructor-arg>
-- 
GitLab