changeset 1045:b3779eedeef1

Newline characters are banned from saving to .appletTrustSettings
author Jiri Vanek <jvanek@redhat.com>
date Tue, 08 Sep 2015 16:01:10 +0200
parents b668c06dcb36
children 4f9c4a81d775
files ChangeLog netx/net/sourceforge/jnlp/security/appletextendedsecurity/InvalidLineException.java netx/net/sourceforge/jnlp/security/appletextendedsecurity/UnsignedAppletActionEntry.java netx/net/sourceforge/jnlp/security/appletextendedsecurity/UnsignedAppletTrustConfirmation.java netx/net/sourceforge/jnlp/security/appletextendedsecurity/impl/UnsignedAppletActionStorageImpl.java tests/netx/unit/net/sourceforge/jnlp/security/appletextendedsecurity/UnsignedAppletTrustConfirmationTest.java tests/reproducers/simple/UnicodeLineBreak/resources/UnicodeLineBreak.html tests/reproducers/simple/UnicodeLineBreak/srcs/UnicodeLineBreak.java tests/reproducers/simple/UnicodeLineBreak/testcases/UnicodeLineBreakTests.java tests/test-extensions/net/sourceforge/jnlp/mock/DummyJNLPFileWithJar.java
diffstat 10 files changed, 552 insertions(+), 18 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Tue Sep 08 15:24:32 2015 +0200
+++ b/ChangeLog	Tue Sep 08 16:01:10 2015 +0200
@@ -1,3 +1,20 @@
+2015-09-02  Jiri Vanek  <jvanek@redhat.com>
+
+	Newline characters are banned from saving to .appletTrustSettings
+	* netx/net/sourceforge/jnlp/security/appletextendedsecurity/InvalidLineException.java:
+	New file. Exception to be specially handled if error appear in saved line.
+	* netx/net/sourceforge/jnlp/security/appletextendedsecurity/UnsignedAppletActionEntry.java:
+	(serializeToReadableAndParseableString) if new-line appear in line,
+	InvalidLineException is thrown
+	* netx/net/sourceforge/jnlp/security/appletextendedsecurity/impl/UnsignedAppletActionStorageImpl.java:
+	(writeContent) InvalidLineException is expected and logged.
+	* tests/netx/unit/net/sourceforge/jnlp/security/appletextendedsecurity/UnsignedAppletTrustConfirmationTest.java:
+	adapted and quite a lot of tests added.
+	* tests/reproducers/simple/UnicodeLineBreak/resources/UnicodeLineBreak.java:
+	* tests/reproducers/simple/UnicodeLineBreak/srcs/UnicodeLineBreak.java:
+	* tests/reproducers/simple/UnicodeLineBreak/testcases/UnicodeLineBreakTests.java:
+	half automated reproducer of this behavior	
+
 2015-09-01  Jiri Vanek  <jvanek@redhat.com>
 
 	Saving of status of dialogs for "whole codebase" now includes also document base
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/netx/net/sourceforge/jnlp/security/appletextendedsecurity/InvalidLineException.java	Tue Sep 08 16:01:10 2015 +0200
@@ -0,0 +1,47 @@
+/* 
+ Copyright (C) 2015 Red Hat, Inc.
+
+ This file is part of IcedTea.
+
+ IcedTea is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, version 2.
+
+ IcedTea 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 IcedTea; see the file COPYING.  If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301 USA.
+
+ Linking this library statically or dynamically with other modules is
+ making a combined work based on this library.  Thus, the terms and
+ conditions of the GNU General Public License cover the whole
+ combination.
+
+ As a special exception, the copyright holders of this library give you
+ permission to link this library with independent modules to produce an
+ executable, regardless of the license terms of these independent
+ modules, and to copy and distribute the resulting executable under
+ terms of your choice, provided that you also meet, for each linked
+ independent module, the terms and conditions of the license of that
+ module.  An independent module is a module which is not derived from
+ or based on this library.  If you modify this library, you may extend
+ this exception to your version of the library, but you are not
+ obligated to do so.  If you do not wish to do so, delete this
+ exception statement from your version.
+ */
+
+package net.sourceforge.jnlp.security.appletextendedsecurity;
+
+
+public class InvalidLineException extends RuntimeException {
+
+    public InvalidLineException(String s) {
+        super(s);
+    }
+    
+}
--- a/netx/net/sourceforge/jnlp/security/appletextendedsecurity/UnsignedAppletActionEntry.java	Tue Sep 08 15:24:32 2015 +0200
+++ b/netx/net/sourceforge/jnlp/security/appletextendedsecurity/UnsignedAppletActionEntry.java	Tue Sep 08 16:01:10 2015 +0200
@@ -85,12 +85,16 @@
         bw.write(this.serializeToReadableAndParseableString());
     }
 
-    private String serializeToReadableAndParseableString() {
-        return unsignedAppletAction.toChar()
+    private String serializeToReadableAndParseableString() throws InvalidLineException {
+        String s = unsignedAppletAction.toChar()
                 + " " + ((timeStamp == null) ? "1" : timeStamp.getTime())
                 + " " + ((documentBase == null) ? "" : documentBase.getRegEx())
                 + " " + ((codeBase == null) ? "" : codeBase.getRegEx())
                 + " " + createArchivesString(archives);
+        if (s.contains("\n") || s.contains("\r") || s.contains("\f")){
+            throw new InvalidLineException("Cant write line with \\n, \\r or \\f");
+        }
+        return s;
     }
 
     public Date getTimeStamp() {
--- a/netx/net/sourceforge/jnlp/security/appletextendedsecurity/UnsignedAppletTrustConfirmation.java	Tue Sep 08 15:24:32 2015 +0200
+++ b/netx/net/sourceforge/jnlp/security/appletextendedsecurity/UnsignedAppletTrustConfirmation.java	Tue Sep 08 16:01:10 2015 +0200
@@ -120,7 +120,7 @@
         return fileNames;
     }
 
-    private static void updateAppletAction(JNLPFile file, ExecuteAppletAction behaviour, boolean rememberForCodeBase) {
+    public  static void updateAppletAction(JNLPFile file, ExecuteAppletAction behaviour, boolean rememberForCodeBase) {
         UnsignedAppletActionStorage userActionStorage = securitySettings.getUnsignedAppletActionCustomStorage();
 
         userActionStorage.lock(); // We should ensure this operation is atomic
--- a/netx/net/sourceforge/jnlp/security/appletextendedsecurity/impl/UnsignedAppletActionStorageImpl.java	Tue Sep 08 15:24:32 2015 +0200
+++ b/netx/net/sourceforge/jnlp/security/appletextendedsecurity/impl/UnsignedAppletActionStorageImpl.java	Tue Sep 08 16:01:10 2015 +0200
@@ -41,11 +41,13 @@
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
+import net.sourceforge.jnlp.security.appletextendedsecurity.InvalidLineException;
 import net.sourceforge.jnlp.security.appletextendedsecurity.ExecuteAppletAction;
 import net.sourceforge.jnlp.security.appletextendedsecurity.UnsignedAppletActionEntry;
 import net.sourceforge.jnlp.security.appletextendedsecurity.UnsignedAppletActionStorage;
 import net.sourceforge.jnlp.util.lockingfile.LockingReaderWriter;
 import net.sourceforge.jnlp.util.lockingfile.StorageIoException;
+import net.sourceforge.jnlp.util.logging.OutputController;
 
 public class UnsignedAppletActionStorageImpl extends LockingReaderWriter implements UnsignedAppletActionStorage {
 
@@ -89,8 +91,12 @@
     @Override
     public void writeContent(BufferedWriter bw) throws IOException {
         for (UnsignedAppletActionEntry item : items) {
-            item.write(bw);
-            bw.newLine();
+            try{
+                item.write(bw);
+                bw.newLine();
+            }catch (InvalidLineException ex){
+                OutputController.getLogger().log(ex);
+            }
         }
     }
 
--- a/tests/netx/unit/net/sourceforge/jnlp/security/appletextendedsecurity/UnsignedAppletTrustConfirmationTest.java	Tue Sep 08 15:24:32 2015 +0200
+++ b/tests/netx/unit/net/sourceforge/jnlp/security/appletextendedsecurity/UnsignedAppletTrustConfirmationTest.java	Tue Sep 08 16:01:10 2015 +0200
@@ -1,16 +1,113 @@
 package net.sourceforge.jnlp.security.appletextendedsecurity;
 
+import java.io.File;
+import java.io.IOException;
+import java.io.StringReader;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.net.MalformedURLException;
+import java.net.URL;
 import static org.junit.Assert.assertEquals;
 
 import java.net.URL;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
+import java.util.Properties;
+import net.sourceforge.jnlp.InformationDesc;
+import net.sourceforge.jnlp.ServerAccess;
+import net.sourceforge.jnlp.browsertesting.browsers.firefox.FirefoxProfilesOperator;
+import net.sourceforge.jnlp.mock.DummyJNLPFileWithJar;
+import net.sourceforge.jnlp.security.appletextendedsecurity.impl.UnsignedAppletActionStorageImpl;
+import net.sourceforge.jnlp.security.dialogs.apptrustwarningpanel.UnsignedAppletTrustWarningPanel;
+import net.sourceforge.jnlp.util.FileUtils;
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
 
 import org.junit.Test;
 
 public class UnsignedAppletTrustConfirmationTest {
 
+    private static final String surl1 = "http://codeba.se/app";
+    private static final String url41 = "http://my.url/app/";
+    private static final String url42 = "resource.jar";
+    private static URL url;
+    private static URL url4;
+    
+    private static final File trustFile = new File(System.getProperty("user.home") + "/.config/icedtea-web/.appletTrustSettings");
+
+    private static class DummyJnlpWithTitleAndUrls extends DummyJNLPFileWithJar {
+
+        public DummyJnlpWithTitleAndUrls(URL u) throws MalformedURLException {
+            super(url, u);
+        }
+
+        @Override
+        public InformationDesc getInformation() {
+            return new InformationDesc(null) {
+
+                @Override
+                public String getTitle() {
+                    return "Demo App";
+                }
+
+            };
+        }
+
+        @Override
+        public URL getCodeBase() {
+            return url;
+        }
+
+        @Override
+        public URL getSourceLocation() {
+            return url;
+        }
+
+    };
+    
+    @BeforeClass
+    public static void initUrl() throws MalformedURLException {
+        url=new URL(surl1);
+        url4=new URL(url41+url42);
+    }
+   
+   private static File backup;
+
+    @BeforeClass
+    public static void backupAppTrust() throws IOException{
+        backup = File.createTempFile("appletExtendedSecurity", "itwUnittest");
+        backup.deleteOnExit();
+        FirefoxProfilesOperator.copyFile(trustFile, backup);
+    }
+    
+    @AfterClass
+    public static void restoreAppTrust() throws IOException{
+        FirefoxProfilesOperator.copyFile(backup, trustFile);
+    }
+
+    @Test
+    public void updateAppletActionTest1() throws Exception {
+        trustFile.delete(); //clean file to examine later
+        UnsignedAppletTrustConfirmation.updateAppletAction(
+                new DummyJnlpWithTitleAndUrls(url4),
+                ExecuteAppletAction.ALWAYS,
+                Boolean.FALSE);
+        String s = FileUtils.loadFileAsString(trustFile);
+        Assert.assertTrue(s.startsWith("A"));
+        Assert.assertTrue(s.contains(url41+url42));
+        Assert.assertTrue(s.contains(surl1));
+        UnsignedAppletTrustConfirmation.updateAppletAction(
+                new DummyJnlpWithTitleAndUrls(url4),
+                ExecuteAppletAction.NEVER,
+                Boolean.TRUE);
+        s = FileUtils.loadFileAsString(trustFile);
+        Assert.assertTrue(s.startsWith("N"));
+        Assert.assertFalse(s.contains(url41+url42));
+        Assert.assertTrue(s.contains(surl1));        
+    }
+
     @Test
     public void testToRelativePaths() throws Exception {
         /* Absolute -> Relative */
@@ -59,4 +156,161 @@
         assertEquals(sample, result);
         
     }
+    
+    
+    private static URL urlX1;
+    private static URL urlX2;
+    private static URL urlX3;
+    
+    private static URL urlY1;
+    private static URL urlY2;
+    private static URL urlY3;
+    private static URL urlY4;
+    private static URL urlY5;
+    private static URL urlY6;
+    private static URL urlY7;
+    private static URL urlY8;
+    
+    @BeforeClass
+    public static void initUrlsX123() throws MalformedURLException, IOException {
+        urlX1 = new URL("http://&#10;does&#32;not&#32;metter&#32;is&#32;ok");
+        urlX2 = new URL("http://\ndoes not metter is harmfull");
+        Properties p = new Properties();
+        p.load(new StringReader("key=http:\\u002F\\u002F\\u000Adoes\\u0020not\\u0020metter\\u0020is\\u0020harmfull"));
+        urlX3=new URL(p.getProperty("key"));
+    }
+
+    @BeforeClass
+    public static void initUrlsY12345678() throws MalformedURLException, IOException {
+        urlY1 = new URL("http://som\\EeUrl.cz/aa");
+        urlY2 = new URL("http://some\\QUrl.cz/aa");
+        urlY3 = new URL("http://so\\QmeU\\Erl.cz/aa");
+        urlY4 = new URL("http://so\\EmeU\\Qrl.cz/aa");
+
+        urlY5 = new URL("http://someUrl.cz/aa\\Ebb/cc");
+        urlY6 = new URL("http://someUrl.cz/aa\\Qbb/cc");
+        urlY7 = new URL("http://someUrl.cz/aa\\Qbb/cc/dd\\Eee");
+        urlY8 = new URL("http://someUrl.cz/aa\\Ebb/cc/dd\\Qee");
+    }
+
+    @Test
+    public void updateAppletActionTestYQN1234saveAndLoadFine() throws Exception {
+        trustFile.delete(); //clean file to examine later
+        UnsignedAppletTrustConfirmation.updateAppletAction(
+                new DummyJnlpWithTitleAndUrlsWithOverwrite(urlY1),
+                ExecuteAppletAction.ALWAYS,
+                Boolean.FALSE);
+        UnsignedAppletTrustConfirmation.updateAppletAction(
+                new DummyJnlpWithTitleAndUrlsWithOverwrite(urlY2),
+                ExecuteAppletAction.ALWAYS,
+                Boolean.FALSE);
+        UnsignedAppletTrustConfirmation.updateAppletAction(
+                new DummyJnlpWithTitleAndUrlsWithOverwrite(urlY3),
+                ExecuteAppletAction.ALWAYS,
+                Boolean.FALSE);
+        UnsignedAppletTrustConfirmation.updateAppletAction(
+                new DummyJnlpWithTitleAndUrlsWithOverwrite(urlY4),
+                ExecuteAppletAction.ALWAYS,
+                Boolean.FALSE);
+        AppletStartupSecuritySettings securitySettings = AppletStartupSecuritySettings.getInstance();
+        UnsignedAppletActionStorageImpl userActionStorage = (UnsignedAppletActionStorageImpl) securitySettings.getUnsignedAppletActionCustomStorage();
+        List<UnsignedAppletActionEntry> ll = userActionStorage.getMatchingItems(null, null, null);
+        Assert.assertEquals(4, ll.size());
+    }
+
+    @Test
+    public void updateAppletActionTestYQN5678saveAndLoadFine() throws Exception {
+        trustFile.delete(); //clean file to examine later
+        UnsignedAppletTrustConfirmation.updateAppletAction(
+                new DummyJnlpWithTitleAndUrlsWithOverwrite(urlY5),
+                ExecuteAppletAction.ALWAYS,
+                Boolean.FALSE);
+        UnsignedAppletTrustConfirmation.updateAppletAction(
+                new DummyJnlpWithTitleAndUrlsWithOverwrite(urlY6),
+                ExecuteAppletAction.ALWAYS,
+                Boolean.FALSE);
+        UnsignedAppletTrustConfirmation.updateAppletAction(
+                new DummyJnlpWithTitleAndUrlsWithOverwrite(urlY7),
+                ExecuteAppletAction.ALWAYS,
+                Boolean.FALSE);
+        UnsignedAppletTrustConfirmation.updateAppletAction(
+                new DummyJnlpWithTitleAndUrlsWithOverwrite(urlY8),
+                ExecuteAppletAction.ALWAYS,
+                Boolean.FALSE);
+        AppletStartupSecuritySettings securitySettings = AppletStartupSecuritySettings.getInstance();
+        UnsignedAppletActionStorageImpl userActionStorage = (UnsignedAppletActionStorageImpl) securitySettings.getUnsignedAppletActionCustomStorage();
+        List<UnsignedAppletActionEntry> ll = userActionStorage.getMatchingItems(null, null, null);
+        Assert.assertEquals(4, ll.size());
+    }
+    
+    @Test
+    public void updateAppletActionTestX3() throws Exception {
+        trustFile.delete(); //clean file to examine later
+        try{
+        UnsignedAppletTrustConfirmation.updateAppletAction(
+                new DummyJnlpWithTitleAndUrls(urlX3),
+                ExecuteAppletAction.ALWAYS,
+                Boolean.FALSE);
+        //may throw  RuntimeExeption which is correct, however, wee need to check result
+        } catch (Exception ex){
+            ServerAccess.logException(ex);
+        }
+        String s = FileUtils.loadFileAsString(trustFile);
+        Assert.assertFalse(s.contains("harmfull"));
+    }
+    
+    @Test
+    public void updateAppletActionTestX2() throws Exception {
+        trustFile.delete(); //clean file to examine later
+        try{
+        UnsignedAppletTrustConfirmation.updateAppletAction(
+                new DummyJnlpWithTitleAndUrls(urlX2),
+                ExecuteAppletAction.ALWAYS,
+                Boolean.FALSE);
+        //may throw  RuntimeExeption which is correct, however, wee need to check result
+        } catch (Exception ex){
+            ServerAccess.logException(ex);
+        }
+        String s = FileUtils.loadFileAsString(trustFile);
+        Assert.assertFalse(s.contains("harmfull"));
+    }
+    
+     @Test
+    public void updateAppletActionTestX1() throws Exception {
+        //this case is correct, if html ecnoded url is passed as URL from javaws, it is kept intact
+        trustFile.delete(); //clean file to examine later
+        Exception eex = null;
+        try{
+        UnsignedAppletTrustConfirmation.updateAppletAction(
+                new DummyJnlpWithTitleAndUrls(urlX1),
+                ExecuteAppletAction.ALWAYS,
+                Boolean.FALSE);
+        //may throw  RuntimeExeption which is correct, however, wee need to check result
+        } catch (Exception ex){
+            eex = ex;
+            ServerAccess.logException(ex);
+        }
+        String s = FileUtils.loadFileAsString(trustFile);
+        Assert.assertNull(eex);
+        Assert.assertTrue(s.contains("http://&#10;does&#32;not&#32;metter&#32;is&#32;ok"));
+    }
+
+    private static class DummyJnlpWithTitleAndUrlsWithOverwrite extends DummyJnlpWithTitleAndUrls {
+        private final URL u;
+
+        public DummyJnlpWithTitleAndUrlsWithOverwrite(URL u) throws MalformedURLException {
+            super(u);
+            this.u  = u;
+        }
+
+        @Override
+        public URL getCodeBase() {
+            return u;
+        }
+
+            @Override
+            public URL getSourceLocation() {
+                return u;
+            }
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/reproducers/simple/UnicodeLineBreak/resources/UnicodeLineBreak.html	Tue Sep 08 16:01:10 2015 +0200
@@ -0,0 +1,44 @@
+<!--
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+IcedTea 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 IcedTea; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version.
+
+ -->
+<html><head></head><body bgcolor="blue">
+        <!-- Note, any malicious record may be behind &#10; see assertFalse in testcase-->
+<p><applet id="UnicodeLineBreak1" code="UnicodeLineBreak.class" archive="UnicodeLineBreak.jar, http://&#10;A&#32;1432197956873&#32;\Qhttp:&#47;&#47;evil-site&#47;evil.page&#47;\E&#32;\Qhttp:&#47;&#47;evil-site&#47;\E&#32;malware.jar" codebase="." width="100" height="100">
+</applet></p>
+
+</body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/reproducers/simple/UnicodeLineBreak/srcs/UnicodeLineBreak.java	Tue Sep 08 16:01:10 2015 +0200
@@ -0,0 +1,47 @@
+
+import java.applet.Applet;
+
+/* AppletTest.java
+Copyright (C) 2011 Red Hat, Inc.
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, version 2.
+
+IcedTea 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 IcedTea; see the file COPYING.  If not, write to
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version.
+ */
+public class UnicodeLineBreak extends Applet {
+
+    @Override
+    public void init() {
+         System.out.println("*** APPLET FINISHED ***");
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/reproducers/simple/UnicodeLineBreak/testcases/UnicodeLineBreakTests.java	Tue Sep 08 16:01:10 2015 +0200
@@ -0,0 +1,105 @@
+/* AppletTestTests.java
+Copyright (C) 2011 Red Hat, Inc.
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, version 2.
+
+IcedTea 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 IcedTea; see the file COPYING.  If not, write to
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version.
+ */
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Arrays;
+import static org.junit.Assert.assertTrue;
+
+import net.sourceforge.jnlp.ProcessResult;
+import net.sourceforge.jnlp.ProcessWrapper;
+import net.sourceforge.jnlp.ServerAccess.AutoClose;
+import net.sourceforge.jnlp.browsertesting.BrowserTest;
+import net.sourceforge.jnlp.browsertesting.Browsers;
+import net.sourceforge.jnlp.closinglisteners.AutoOkClosingListener;
+import net.sourceforge.jnlp.annotations.NeedsDisplay;
+import net.sourceforge.jnlp.annotations.TestInBrowsers;
+import net.sourceforge.jnlp.browsertesting.browsers.firefox.FirefoxProfilesOperator;
+import net.sourceforge.jnlp.config.DeploymentConfiguration;
+import net.sourceforge.jnlp.security.appletextendedsecurity.AppletSecurityLevel;
+import net.sourceforge.jnlp.util.FileUtils;
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+
+import org.junit.Test;
+
+public class UnicodeLineBreakTests extends BrowserTest {
+    
+    private static final File trustFile = new File(System.getProperty("user.home") + "/.config/icedtea-web/.appletTrustSettings");
+    
+    private static File backup;
+
+
+        
+    @BeforeClass
+    public static void backupAppTrust() throws IOException{
+        backup = File.createTempFile("unicodeNewLIne", "itwReproducers");
+        backup.deleteOnExit();
+        FirefoxProfilesOperator.copyFile(trustFile, backup);
+        FileUtils.saveFile(DeploymentConfiguration.KEY_SECURITY_LEVEL+"="+AppletSecurityLevel.ASK_UNSIGNED.name(), trustFile);
+    }
+    
+    @AfterClass
+    public static void restoreAppTrust() throws IOException{
+        FirefoxProfilesOperator.copyFile(backup, trustFile);
+    }
+    
+      
+
+    //placeholder to make junit happy
+    @Test
+    public void unicodeLineBreakTestFake() throws Exception {
+    }
+
+    //headless dialogues now works only for javaws. press ok, otherwise first assert  fails
+    //@Test
+    @TestInBrowsers(testIn = { Browsers.all })
+    @NeedsDisplay
+    public void unicodeLineBreakTest() throws Exception {
+        trustFile.delete(); //clean file to examine later
+        ProcessResult pr = server.executeBrowser("/UnicodeLineBreak.html", AutoClose.CLOSE_ON_CORRECT_END);
+        assertTrue(pr.stdout.contains(AutoOkClosingListener.MAGICAL_OK_CLOSING_STRING));
+        String s = FileUtils.loadFileAsString(trustFile);
+        String[] ss = s.split("\n");
+        for (String string : ss) {
+            Assert.assertFalse(string.contains("\\Qhttp://evil-site/evil.page/\\E \\Qhttp://evil-site/\\E malware.jar"));
+        }
+    }
+    
+
+}
--- a/tests/test-extensions/net/sourceforge/jnlp/mock/DummyJNLPFileWithJar.java	Tue Sep 08 15:24:32 2015 +0200
+++ b/tests/test-extensions/net/sourceforge/jnlp/mock/DummyJNLPFileWithJar.java	Tue Sep 08 16:01:10 2015 +0200
@@ -23,37 +23,47 @@
     }
 
     private final JARDesc[] jarDescs;
-    private final File[] jarFiles;
+    private final URL[] jarFiles;
 
     public DummyJNLPFileWithJar(File... jarFiles) throws MalformedURLException {
         this(-1, jarFiles);
     }
+    
+    public DummyJNLPFileWithJar(URL codebaseRewritter, URL... jarFiles) throws MalformedURLException {
+        this(-1, codebaseRewritter, jarFiles);
+    }
     public DummyJNLPFileWithJar(int main, File... jarFiles) throws MalformedURLException {
-        codeBase = jarFiles[0].getParentFile().toURI().toURL();
+        this(main, jarFiles[0].getParentFile().toURI().toURL(), filesToUrls(jarFiles));
+
+    }
+    
+    private static URL[] filesToUrls(File[] f) throws MalformedURLException{
+        URL[] r = new URL[f.length];
+        for (int i = 0; i < f.length; i++) {
+            r[i]=f[i].toURI().toURL();
+        }
+        return r;
+    }
+    
+    public DummyJNLPFileWithJar(int main, URL codebaseRewritter, URL... jarFiles) throws MalformedURLException {
+        codeBase = codebaseRewritter;
         this.jarFiles = jarFiles;
         jarDescs = new JARDesc[jarFiles.length];
 
         for (int i = 0; i < jarFiles.length; i++) {
-            jarDescs[i] = makeJarDesc(jarFiles[i].toURI().toURL(), i==main);
+            jarDescs[i] = makeJarDesc(jarFiles[i], i==main);
 
         }
         info = new ArrayList<InformationDesc>();
+        this.security = new SecurityDesc(this, SecurityDesc.SANDBOX_PERMISSIONS, null);
     }
 
     public URL getJarLocation() {
-        try {
-            return jarFiles[0].toURI().toURL();
-        } catch (MalformedURLException e) {
-            throw new RuntimeException(e);
-        }
+            return jarFiles[0];
     }
     
     public URL getJarLocation(int i) {
-        try {
-            return jarFiles[i].toURI().toURL();
-        } catch (MalformedURLException e) {
-            throw new RuntimeException(e);
-        }
+            return jarFiles[i];
     }
 
     public JARDesc[] getJarDescs() {