]> source.dussan.org Git - poi.git/commitdiff
Bug #53282 - Avoid exception when parsing OPC relationships with non-breaking spaces
authorYegor Kozlov <yegor@apache.org>
Mon, 29 Oct 2012 08:42:54 +0000 (08:42 +0000)
committerYegor Kozlov <yegor@apache.org>
Mon, 29 Oct 2012 08:42:54 +0000 (08:42 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1403195 13f79535-47bb-0310-9956-ffa450edef68

src/documentation/content/xdocs/status.xml
src/ooxml/java/org/apache/poi/openxml4j/opc/PackagingURIHelper.java
src/ooxml/testcases/org/apache/poi/openxml4j/opc/TestRelationships.java
src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFHyperlink.java
test-data/openxml4j/53282.xlsx [new file with mode: 0644]
test-data/spreadsheet/53282.xlsx [new file with mode: 0644]

index 27ec8027fb7d18c88795fed615a0a06188b0a63d..766157603e010c77a40cda0eb8967ca222956682 100644 (file)
@@ -34,6 +34,7 @@
 
     <changes>
         <release version="3.9-beta1" date="2012-??-??">
+          <action dev="poi-developers" type="fix">53282 - Avoid exception when parsing OPC relationships with non-breaking spaces</action>
           <action dev="poi-developers" type="fix">54016 - Avoid exception when parsing workbooks with DConRefRecord in row aggregate</action>
           <action dev="poi-developers" type="fix">54008 - Fixed Ant build to support build directories with blanks</action>
           <action dev="poi-developers" type="fix">53374 - Avoid exceptions when parsing hyperlinks of type "javascript://"</action>
index 37fdc5a58b1a7bb0e75a8945d95fbaed305596a2..6385124b3f0fcc378a4ec2fbb3a9f7a4bce94ace 100644 (file)
@@ -709,6 +709,25 @@ public final class PackagingURIHelper {
             value = path + "#" + encode(fragment);
         }
 
+        // trailing white spaces must be url-encoded, see Bugzilla 53282
+        if(value.length() > 0 ){
+            StringBuilder b = new StringBuilder();
+            int idx = value.length() - 1;
+            for(; idx >= 0; idx--){
+                char c = value.charAt(idx);
+                if(Character.isWhitespace(c) || c == '\u00A0') {
+                    b.append(c);
+                } else {
+                    break;
+                }
+            }
+            if(b.length() > 0){
+                value = value.substring(0, idx+1) + encode(b.reverse().toString());
+            }
+        }
+
+        // MS Office can insert URIs with missing authority, e.g. "http://" or "javascript://"
+        // append a forward slash to avoid parse exception
         if(missingAuthPattern.matcher(value).matches()){
             value += "/";
         }
@@ -756,7 +775,7 @@ public final class PackagingURIHelper {
     };
 
     private static boolean isUnsafe(int ch) {
-        return ch > 0x80 || " ".indexOf(ch) >= 0;
+        return ch > 0x80 || Character.isWhitespace(ch) || ch == '\u00A0';
     }
 
 }
index 738175f54d5d2c83fbb590c55f466a69a32a02b5..510377a9e0fad48c66760a6f4a934cc7e8ea02d0 100644 (file)
@@ -19,6 +19,7 @@ package org.apache.poi.openxml4j.opc;
 
 import java.io.*;
 import java.net.URI;
+import java.util.regex.Pattern;
 
 import junit.framework.TestCase;
 
@@ -344,4 +345,32 @@ public class TestRelationships extends TestCase {
        assertEquals(rel1.getTargetURI(), rel2.getTargetURI());
        assertEquals(rel1.getTargetMode(), rel2.getTargetMode());
     }
+
+    public void testTrailingSpacesInURI_53282() throws Exception {
+        InputStream is = OpenXML4JTestDataSamples.openSampleStream("53282.xlsx");
+        OPCPackage pkg = OPCPackage.open(is);
+        is.close();
+
+        PackageRelationshipCollection sheetRels = pkg.getPartsByName(Pattern.compile("/xl/worksheets/sheet1.xml")).get(0).getRelationships();
+        assertEquals(3, sheetRels.size());
+        PackageRelationship rId1 = sheetRels.getRelationshipByID("rId1");
+        assertEquals(TargetMode.EXTERNAL, rId1.getTargetMode());
+        URI targetUri = rId1.getTargetURI();
+        assertEquals("mailto:nobody@nowhere.uk%C2%A0", targetUri.toASCIIString());
+        assertEquals("nobody@nowhere.uk\u00A0", targetUri.getSchemeSpecificPart());
+
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
+        pkg.save(out);
+        out.close();
+
+        pkg =  OPCPackage.open(new ByteArrayInputStream(out.toByteArray()));
+        sheetRels = pkg.getPartsByName(Pattern.compile("/xl/worksheets/sheet1.xml")).get(0).getRelationships();
+        assertEquals(3, sheetRels.size());
+        rId1 = sheetRels.getRelationshipByID("rId1");
+        assertEquals(TargetMode.EXTERNAL, rId1.getTargetMode());
+        targetUri = rId1.getTargetURI();
+        assertEquals("mailto:nobody@nowhere.uk%C2%A0", targetUri.toASCIIString());
+        assertEquals("nobody@nowhere.uk\u00A0", targetUri.getSchemeSpecificPart());
+
+    }
 }
index 9a79bf3cca048d5c19e70aba964bf201b4c4a337..fbec25c670542b6c76ce775b3c7caca7e69f96c5 100644 (file)
@@ -252,4 +252,14 @@ public final class TestXSSFHyperlink extends BaseTestHyperlink {
         link = wb.getSheetAt(0).getRow(0).getCell(0).getHyperlink();
         assertEquals("javascript:///", link.getAddress());
     }
+
+    public void test53282() {
+        XSSFWorkbook wb = XSSFTestDataSamples.openSampleWorkbook("53282.xlsx");
+        XSSFHyperlink link = wb.getSheetAt(0).getRow(0).getCell(14).getHyperlink();
+        assertEquals("mailto:nobody@nowhere.uk%C2%A0", link.getAddress());
+
+        wb = XSSFTestDataSamples.writeOutAndReadBack(wb);
+        link = wb.getSheetAt(0).getRow(0).getCell(14).getHyperlink();
+        assertEquals("mailto:nobody@nowhere.uk%C2%A0", link.getAddress());
+    }
 }
diff --git a/test-data/openxml4j/53282.xlsx b/test-data/openxml4j/53282.xlsx
new file mode 100644 (file)
index 0000000..6d88303
Binary files /dev/null and b/test-data/openxml4j/53282.xlsx differ
diff --git a/test-data/spreadsheet/53282.xlsx b/test-data/spreadsheet/53282.xlsx
new file mode 100644 (file)
index 0000000..6d88303
Binary files /dev/null and b/test-data/spreadsheet/53282.xlsx differ