You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@poi.apache.org by ce...@apache.org on 2016/11/25 22:07:59 UTC

svn commit: r1771396 - in /poi/trunk/src: ooxml/java/org/apache/poi/xssf/usermodel/XSSFDataValidation.java testcases/org/apache/poi/ss/usermodel/BaseTestBugzillaIssues.java

Author: centic
Date: Fri Nov 25 22:07:59 2016
New Revision: 1771396

URL: http://svn.apache.org/viewvc?rev=1771396&view=rev
Log:
Bug 60370: Encode some special characters when setting title/text for validation text-boxes, for now all characters below 32, more can be added if necessary.

Modified:
    poi/trunk/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFDataValidation.java
    poi/trunk/src/testcases/org/apache/poi/ss/usermodel/BaseTestBugzillaIssues.java

Modified: poi/trunk/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFDataValidation.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFDataValidation.java?rev=1771396&r1=1771395&r2=1771396&view=diff
==============================================================================
--- poi/trunk/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFDataValidation.java (original)
+++ poi/trunk/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFDataValidation.java Fri Nov 25 22:07:59 2016
@@ -110,8 +110,8 @@ public class XSSFDataValidation implemen
 		if(text != null && text.length() > 255) {
 			throw new IllegalStateException("Error-text cannot be longer than 255 characters, but had: " + text);
 		}
-		ctDdataValidation.setErrorTitle(title);
-		ctDdataValidation.setError(text);
+		ctDdataValidation.setErrorTitle(encodeUtf(title));
+		ctDdataValidation.setError(encodeUtf(text));
 	}
 
 	/* (non-Javadoc)
@@ -125,8 +125,35 @@ public class XSSFDataValidation implemen
 		if(text != null && text.length() > 255) {
 			throw new IllegalStateException("Error-text cannot be longer than 255 characters, but had: " + text);
 		}
-		ctDdataValidation.setPromptTitle(title);
-		ctDdataValidation.setPrompt(text);
+		ctDdataValidation.setPromptTitle(encodeUtf(title));
+		ctDdataValidation.setPrompt(encodeUtf(text));
+	}
+
+	/**
+	 * For all characters which cannot be represented in XML as defined by the XML 1.0 specification,
+	 * the characters are escaped using the Unicode numerical character representation escape character
+	 * format _xHHHH_, where H represents a hexadecimal character in the character's value.
+	 * <p>
+	 * Example: The Unicode character 0D is invalid in an XML 1.0 document,
+	 * so it shall be escaped as <code>_x000D_</code>.
+	 * </p>
+	 * See section 3.18.9 in the OOXML spec.
+	 *
+	 * @param   text the string to encode
+	 * @return  the encoded string
+	 */
+	private String encodeUtf(String text) {
+		StringBuilder builder = new StringBuilder();
+		for(char c : text.toCharArray()) {
+			// for now only encode characters below 32, we can add more here if needed
+			if(c < 32) {
+				builder.append("_x").append(c < 16 ? "000" : "00").append(Integer.toHexString(c)).append("_");
+			} else {
+				builder.append(c);
+			}
+		}
+
+		return builder.toString();
 	}
 
 	/* (non-Javadoc)

Modified: poi/trunk/src/testcases/org/apache/poi/ss/usermodel/BaseTestBugzillaIssues.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/testcases/org/apache/poi/ss/usermodel/BaseTestBugzillaIssues.java?rev=1771396&r1=1771395&r2=1771396&view=diff
==============================================================================
--- poi/trunk/src/testcases/org/apache/poi/ss/usermodel/BaseTestBugzillaIssues.java (original)
+++ poi/trunk/src/testcases/org/apache/poi/ss/usermodel/BaseTestBugzillaIssues.java Fri Nov 25 22:07:59 2016
@@ -53,6 +53,8 @@ public abstract class BaseTestBugzillaIs
     private static final String TEST_32 = "Some text with 32 characters to ";
     private static final String TEST_255 = "Some very long text that is exactly 255 characters, which are allowed here, bla bla, bla bla, bla bla, bla bla, bla bla, bla bla, bla bla, bla bla, bla bla, bla bla, bla bla, bla bla, bla bla, bla bla, bla bla, bla bla, bla bla, bla bla, bla bla, bla.....";
     private static final String TEST_256 = "Some very long text that is longer than the 255 characters allowed in HSSF here, bla bla, bla bla, bla bla, bla bla, bla bla, bla bla, bla bla, bla bla, bla bla, bla bla, bla bla, bla bla, bla bla, bla bla, bla bla, bla bla, bla bla, bla bla, bla bla, bla1";
+    private static final String TEST_SPECIAL_TITLE = "special \n\t\r\u0002characters";
+    private static final String TEST_SPECIAL = "Some text with special \n\t\r\u0002characters to s";
 
     private final ITestDataProvider _testDataProvider;
 
@@ -167,7 +169,7 @@ public abstract class BaseTestBugzillaIs
             // fetch the first merged region...EXCEPTION OCCURS HERE
             template.getMergedRegion(0);
        }
-       //make sure we dont exception
+
        wb.close();
     }
 
@@ -989,7 +991,7 @@ public abstract class BaseTestBugzillaIs
      * With HSSF, if you create a font, don't change it, and
      *  create a 2nd, you really do get two fonts that you
      *  can alter as and when you want.
-     * With XSSF, that wasn't the case, but this verfies
+     * With XSSF, that wasn't the case, but this verifies
      *  that it now is again
      */
     @Test
@@ -1802,9 +1804,14 @@ public abstract class BaseTestBugzillaIs
         // more than 255 fail for all
         checkFailures(dataValidation, TEST_256, TEST_32, true);
         checkFailures(dataValidation, TEST_32, TEST_256, true);
+
         // more than 32 title fail for HSSFWorkbook
         checkFailures(dataValidation, TEST_255, TEST_32, wb instanceof HSSFWorkbook);
-        // 32 length title and 255 length text wrok for both
+
+        // special characters work
+        checkFailures(dataValidation, TEST_SPECIAL_TITLE, TEST_SPECIAL, false);
+
+        // 32 length title and 255 length text work for both
         checkFailures(dataValidation, TEST_32, TEST_255, false);
 
         dataValidation.setShowErrorBox(false);
@@ -1843,4 +1850,38 @@ public abstract class BaseTestBugzillaIs
             assertTrue("Should not fail in a length-check, had " + title.length() + " and " + text.length(), shouldFail);
         }
     }
+
+    @Test
+    public void test60370() throws IOException {
+        Workbook wb = _testDataProvider.createWorkbook();
+        final Sheet sheet = wb.createSheet();
+
+        DataValidation dataValidation;
+        CellRangeAddressList headerCell = new CellRangeAddressList(0, 1, 0, 1);
+        DataValidationConstraint constraint = sheet.getDataValidationHelper().createCustomConstraint("A1<>\"\"");
+
+        dataValidation = sheet.getDataValidationHelper().createValidation(constraint, headerCell);
+        checkFailures(dataValidation, TEST_SPECIAL_TITLE, TEST_SPECIAL, false);
+
+        dataValidation.setShowErrorBox(true);
+        dataValidation.setShowPromptBox(true);
+        sheet.addValidationData(dataValidation);
+
+        // write out and read back in to trigger some more validation
+        final Workbook wbBack = _testDataProvider.writeOutAndReadBack(wb);
+
+        final Sheet sheetBack = wbBack.getSheetAt(0);
+        final List<? extends DataValidation> dataValidations = sheetBack.getDataValidations();
+        assertEquals(1, dataValidations.size());
+
+        /*String ext = (wb instanceof HSSFWorkbook) ? ".xls" : ".xlsx";
+        OutputStream str = new FileOutputStream("/tmp/60370" + ext);
+        try {
+            wb.write(str);
+        } finally {
+            str.close();
+        }*/
+
+        wb.close();
+    }
 }
\ No newline at end of file



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@poi.apache.org
For additional commands, e-mail: commits-help@poi.apache.org