changeset 1214:ff7010bc3cae

- Encode newline characters instead of stripping them. - Fix bug in code that computed width factor. - Try to load images from local cache first. - Update parser to skip comments in applet tag. - Take into consideration system policy in addition to applet policy when determining permissions. - Return from jar verifier function immediately if jar could not be fetched (fixes NPE crash).
author Deepak Bhole <dbhole@redhat.com>
date Tue, 18 Nov 2008 11:04:46 -0500
parents ccf50a917765
children 8af2ec380258 85921aeaed32
files ChangeLog IcedTeaPlugin.cc plugin/icedtea/sun/applet/PluginAppletSecurityContext.java plugin/icedtea/sun/applet/PluginAppletViewer.java rt/net/sourceforge/jnlp/runtime/JNLPClassLoader.java rt/net/sourceforge/jnlp/runtime/JNLPPolicy.java rt/net/sourceforge/jnlp/tools/JarSigner.java
diffstat 7 files changed, 210 insertions(+), 48 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Mon Nov 17 09:53:50 2008 -0500
+++ b/ChangeLog	Tue Nov 18 11:04:46 2008 -0500
@@ -1,3 +1,15 @@
+2008-11-18  Deepak Bhole  <dbhole@redhat.com>
+	* IcedTeaPlugin.cc: Encode newline characters instead of stripping them.
+	* plugin/icedtea/sun/applet/PluginAppletSecurityContext.java: Minor debug
+	output change.
+	* plugin/icedtea/sun/applet/PluginAppletViewer.java: Fix bug in code that
+	computed width factor. Try to load images from local cache first. Decode
+	newline characters. Update parser to skip comments in applet tag.
+	* rt/net/sourceforge/jnlp/runtime/JNLPPolicy.java: Take into consideration
+	system policy in addition to applet policy when determining permissions.
+	* rt/net/sourceforge/jnlp/tools/JarSigner.java: Return immediately if jar
+	could not be fetched.
+
 2008-11-17  Omair Majid  <omajid@redhat.com>
 
 	* HACKING: Document icedtea-alsa-default-device.patch and
--- a/IcedTeaPlugin.cc	Mon Nov 17 09:53:50 2008 -0500
+++ b/IcedTeaPlugin.cc	Tue Nov 18 11:04:46 2008 -0500
@@ -2310,10 +2310,28 @@
   tagMessage += appletTag;
   tagMessage += "</embed>";
 
-  // remove newline characters from the message
-  tagMessage.StripChars("\r\n");
-
-  factory->SendMessageToAppletViewer (tagMessage);
+  PLUGIN_DEBUG_1ARG("TAG FROM BROWSER = %s\n", tagMessage.get());
+
+  // encode newline characters in the message
+  nsCString toSend("");
+  for (int i=0; i < tagMessage.Length(); i++)
+  {
+	  if (tagMessage.get()[i] == '\r')
+	  {
+		  toSend += "&#13;";
+		  continue;
+	  }
+
+	  if (tagMessage.get()[i] == '\n')
+	  {
+		  toSend += "&#10;";
+		  continue;
+	  }
+
+	  toSend += tagMessage.get()[i];
+  }
+
+  factory->SendMessageToAppletViewer (toSend);
 
   // Set back-pointer to peer instance.
   PLUGIN_DEBUG_1ARG ("SETTING PEER!!!: %p\n", aPeer);
--- a/plugin/icedtea/sun/applet/PluginAppletSecurityContext.java	Mon Nov 17 09:53:50 2008 -0500
+++ b/plugin/icedtea/sun/applet/PluginAppletSecurityContext.java	Tue Nov 18 11:04:46 2008 -0500
@@ -996,7 +996,7 @@
 
 		String classSrc = this.classLoaders.get(target.getClassLoader());
 
-		PluginDebug.debug("jsSrc=" + jsSrc + " classSrc=" + classSrc);
+		PluginDebug.debug("target = " + target + " jsSrc=" + jsSrc + " classSrc=" + classSrc);
 		
 		// if src is not a file and class loader does not map to the same base, UniversalBrowserRead (BrowserReadPermission) must be set
 		if (jsSrc != "file://" && !classSrc.equals(jsSrc)) {
--- a/plugin/icedtea/sun/applet/PluginAppletViewer.java	Mon Nov 17 09:53:50 2008 -0500
+++ b/plugin/icedtea/sun/applet/PluginAppletViewer.java	Tue Nov 18 11:04:46 2008 -0500
@@ -63,6 +63,7 @@
 import javax.swing.SwingUtilities;
 
 import net.sourceforge.jnlp.NetxPanel;
+import net.sourceforge.jnlp.runtime.JNLPClassLoader;
 import sun.awt.AppContext;
 import sun.awt.SunToolkit;
 import sun.awt.X11.XEmbeddedFrame;
@@ -103,7 +104,7 @@
       * Some constants...
       */
      private static String defaultSaveFile = "Applet.ser";
- 
+     
      /**
       * The panel in which the applet is being displayed.
       */
@@ -138,6 +139,8 @@
      
      private double proposedHeightFactor;
      private double proposedWidthFactor;
+     
+     private JNLPClassLoader pluginCL; 
 
      /**
       * Null constructor to allow instantiation via newInstance()
@@ -168,7 +171,7 @@
         	 proposedHeightFactor = (Integer) atts.get("heightPercentage")/100.0;
          }
          
-         if (((String) atts.get("width")).endsWith("%")) {
+         if (atts.get("widthPercentage") != null) {
         	 proposedWidthFactor = (Integer) atts.get("widthPercentage")/100.0;
          }
  
@@ -177,6 +180,7 @@
             	 	try {
             	 		panel = new NetxPanel(doc, atts, true);
             	 		AppletViewerPanel.debug("Using NetX panel");
+            	 		PluginDebug.debug(atts.toString());
             	 	} catch (Exception ex) {
             	 		AppletViewerPanel.debug("Unable to start NetX applet - defaulting to Sun applet", ex);
             	 		panel = new AppletViewerPanel(doc, atts);
@@ -284,6 +288,9 @@
     	return;
     }
 
+    if (panel instanceof NetxPanel)
+        pluginCL = (JNLPClassLoader) panel.getApplet().getClass().getClassLoader();
+
     PluginDebug.debug("Applet initialized");
 
     // Applet initialized. Find out it's classloader and add it to the list
@@ -291,7 +298,7 @@
 
     if (atts.get("codebase") != null) {
     	try {
-    		URL appletSrcURL = new URL((String) atts.get("codebase"));
+    		URL appletSrcURL = new URL(codeBase + (String) atts.get("codebase"));
     		codeBase = appletSrcURL.getProtocol() + "://" + appletSrcURL.getHost();
     	} catch (MalformedURLException mfue) {
     		// do nothing
@@ -587,7 +594,7 @@
  	return getCachedImage(url);
      }
  
-     static Image getCachedImage(URL url) {
+     private Image getCachedImage(URL url) {
  	// System.getSecurityManager().checkConnection(url.getHost(), url.getPort());
  	return (Image)getCachedImageRef(url).get();
      }
@@ -595,15 +602,45 @@
      /**
       * Get an image ref.
       */
-     static Ref getCachedImageRef(URL url) {
- 	synchronized (imageRefs) {
- 	    AppletImageRef ref = (AppletImageRef)imageRefs.get(url);
- 	    if (ref == null) {
- 		ref = new AppletImageRef(url);
- 		imageRefs.put(url, ref);
- 	    }
- 	    return ref;
- 	}
+     private synchronized Ref getCachedImageRef(URL url) {
+         PluginDebug.debug("getCachedImageRef() searching for " + url);
+         
+         try {
+
+             // wait till aplet initializes
+             while (pluginCL == null) {
+                 PluginDebug.debug("Plugin CL is null. Waiting in getCachedImageRef()..");
+             }
+
+             String originalURL = url.toString();
+             String codeBase = pluginCL.getJNLPFile().getCodeBase().toString();
+
+             if (originalURL.startsWith("http")) {
+                 PluginDebug.debug("getCachedImageRef() got URL = " + url);
+                 PluginDebug.debug("getCachedImageRef() plugin codebase = " + pluginCL.getJNLPFile().getCodeBase().toString());
+
+                 URL localURL = null;
+                 if (originalURL.startsWith(codeBase))
+                     localURL = pluginCL.getResource(originalURL.substring(codeBase.length()));
+
+                 url = localURL != null ? localURL : url;
+             }
+
+             PluginDebug.debug("getCachedImageRef() getting img from URL = " + url);
+
+             synchronized (imageRefs) {
+                 AppletImageRef ref = (AppletImageRef)imageRefs.get(url);
+                 if (ref == null) {
+                     ref = new AppletImageRef(url);
+                     imageRefs.put(url, ref);
+                 }
+                 return ref;
+             }
+         } catch (Exception e) {
+             System.err.println("Error occurred wgen trying to fetch image:");
+             e.printStackTrace();
+             return null;
+         }
      }
  
      /**
@@ -1221,6 +1258,16 @@
       */
      public static String scanIdentifier(Reader in) throws IOException {
  	StringBuffer buf = new StringBuffer();
+ 	
+ 	if (c == '!') {
+        // Technically, we should be scanning for '!--' but we are reading 
+        // from a stream, and there is no way to peek ahead. That said, 
+        // a ! at this point can only mean comment here afaik, so we 
+        // should be okay
+        skipComment(in);
+        return "";
+    }
+ 	
  	while (true) {
  	    if (((c >= 'a') && (c <= 'z')) ||
  		((c >= 'A') && (c <= 'Z')) ||
@@ -1232,6 +1279,41 @@
  	    }
  	}
      }
+
+     public static void skipComment(Reader in) throws IOException {
+         StringBuffer buf = new StringBuffer();
+         boolean commentHeaderPassed = false;
+         c = in.read();
+         buf.append((char)c);
+
+         while (true) {
+             if (c == '-' && (c = in.read()) == '-') {
+                 buf.append((char)c);
+                 if (commentHeaderPassed) {
+                     // -- encountered ... is > next?
+                     if ((c = in.read()) == '>') {
+                         buf.append((char)c);
+
+                         PluginDebug.debug("Comment skipped: " + buf.toString());
+
+                         // comment skipped.
+                         return;
+                     }
+                 } else {
+                     // first -- is part of <!-- ... , just mark that we have passed it
+                     commentHeaderPassed = true;
+                 }
+
+             } else if (commentHeaderPassed == false) {
+                 buf.append((char)c);
+                 PluginDebug.debug("Warning: Attempted to skip comment, but this tag does not appear to be a comment: " + buf.toString());
+                 return;
+             }
+
+             c = in.read();
+             buf.append((char)c);
+         }
+     }
  
      /**
       * Scan tag
@@ -1266,11 +1348,21 @@
  		val = buf.toString();
  	    }
 
+        att = att.replace("&gt;", ">");
+        att = att.replace("&lt;", "<");
+        att = att.replace("&amp;", "&");
+        att = att.replace("&#10;", "\n");
+        att = att.replace("&#13;", "\r");
+ 	    
         val = val.replace("&gt;", ">");
         val = val.replace("&lt;", "<");
         val = val.replace("&amp;", "&");
- 	    PluginDebug.debug("PUT " + att + " = '" + val + "'");
- 	    atts.put(att.toLowerCase(java.util.Locale.ENGLISH), val);
+        val = val.replace("&#10;", "\n");
+        val = val.replace("&#13;", "\r");
+
+        PluginDebug.debug("PUT " + att + " = '" + val + "'");
+        atts.put(att.toLowerCase(java.util.Locale.ENGLISH), val);
+
              while (true) {
                  if ((c == '>') || (c < 0) ||
                      ((c >= 'a') && (c <= 'z')) ||
@@ -1283,6 +1375,20 @@
  	}
  	return atts;
      }
+     
+     // private static final == inline
+     private static final boolean isInt(Object o) {
+         boolean isInt = false;
+
+         try {
+             Integer.parseInt((String) o);
+             isInt = true;
+         } catch (Exception e) {
+             // don't care
+         }
+
+         return isInt;
+     }
  
      /* values used for placement of AppletViewer's frames */
      private static int x = 0;
@@ -1426,12 +1532,19 @@
     						 if (val == null) {
     							 statusMsgStream.println(requiresNameWarning);
     						 } else if (atts != null) {
-    							 // to prevent headaches, c++ side encodes &, < and >
-    							 // decode them back
+    							 att = att.replace("&gt;", ">");
+    							 att = att.replace("&lt;", "<");
+    							 att = att.replace("&amp;", "&");
+    							 att = att.replace("&#10;", "\n");
+    							 att = att.replace("&#13;", "\r");
+
     							 val = val.replace("&gt;", ">");
     							 val = val.replace("&lt;", "<");
     							 val = val.replace("&amp;", "&");
-    							 atts.put(att.toLowerCase(), val);
+    							 val = val.replace("&#10;", "\n");
+    							 val = val.replace("&#13;", "\r");
+    							 PluginDebug.debug("PUT " + att + " = " + val);
+   							     atts.put(att.toLowerCase(), val);
     						 } else {
     							 statusMsgStream.println(paramOutsideWarning);
     						 }
@@ -1453,21 +1566,21 @@
     						 atts = null;
     					 }
 
-    					 if (atts.get("width") == null) {
-    						 atts.put("width", "100");
+    					 if (atts.get("width") == null || !isInt(atts.get("width"))) {
+    						 atts.put("width", "1000");
     						 atts.put("widthPercentage", 100);
     					 } else if (((String) atts.get("width")).endsWith("%")) {
     						 String w = (String) atts.get("width");
-    						 atts.put("width", "100");
+    						 atts.put("width", "1000");
     						 atts.put("widthPercentage", Integer.parseInt((w.substring(0,  w.length() -1))));
     					  }
 
-    					 if (atts.get("height") == null) {
-    						 atts.put("height", "100");
+    					 if (atts.get("height") == null || !isInt(atts.get("height"))) {
+    						 atts.put("height", "1000");
     						 atts.put("heightPercentage", 100);
     					 } else if (((String) atts.get("height")).endsWith("%")) {
     						 String h = (String) atts.get("height");
-    						 atts.put("height", "100");
+    						 atts.put("height", "1000");
     						 atts.put("heightPercentage", Integer.parseInt(h.substring(0,  h.length() -1)));
     					 }
     				 }
@@ -1489,21 +1602,21 @@
     						 atts.remove("codebase");
     					 }
 
-    					 if (atts.get("width") == null) {
-    						 atts.put("width", "100");
+    					 if (atts.get("width") == null || !isInt(atts.get("width"))) {
+    						 atts.put("width", "1000");
     						 atts.put("widthPercentage", 100);
     					 } else if (((String) atts.get("width")).endsWith("%")) {
     						 String w = (String) atts.get("width");
-    						 atts.put("width", "100");
+    						 atts.put("width", "1000");
     						 atts.put("widthPercentage", Integer.parseInt(w.substring(0,  w.length() -1)));
     					 }
 
-    					 if (atts.get("height") == null) {
-    						 atts.put("height", "100");
+    					 if (atts.get("height") == null || !isInt(atts.get("height"))) {
+    						 atts.put("height", "1000");
     						 atts.put("heightPercentage", 100);
     					 } else if (((String) atts.get("height")).endsWith("%")) {
     						 String h = (String) atts.get("height");
-    						 atts.put("height", "100");
+    						 atts.put("height", "1000");
     						 atts.put("heightPercentage", Integer.parseInt(h.substring(0,  h.length() -1)));
     					 }
     				 }
@@ -1523,8 +1636,8 @@
     						 atts = null;
     					 }
     					 
-    					 if (atts.get("width") == null) {
-    						 atts.put("width", "100");
+    					 if (atts.get("width") == null || !isInt(atts.get("width"))) {
+    						 atts.put("width", "1000");
     						 atts.put("widthPercentage", 100);
     					 } else if (((String) atts.get("width")).endsWith("%")) {
     						 String w = (String) atts.get("width");
@@ -1532,8 +1645,8 @@
     						 atts.put("widthPercentage", Integer.parseInt(w.substring(0,  w.length() -1)));
     					 }
 
-    					 if (atts.get("height") == null) {
-    						 atts.put("height", "100");
+    					 if (atts.get("height") == null || !isInt(atts.get("height"))) {
+    						 atts.put("height", "1000");
     						 atts.put("heightPercentage", 100);
     					 } else if (((String) atts.get("height")).endsWith("%")) {
     						 String h = (String) atts.get("height");
@@ -1554,17 +1667,17 @@
     						 atts2.remove("src");
     						 atts2.put("codebase", nm);
     					 }
-    					 if (atts2.get("width") == null) {
-    						 atts2.put("width", "100");
+    					 if (atts2.get("width") == null || !isInt(atts2.get("width"))) {
+    						 atts2.put("width", "1000");
     						 atts2.put("widthPercentage", 100);
     					 } else if (((String) atts.get("width")).endsWith("%")) {
     						 String w = (String) atts.get("width");
     						 atts2.put("width", "100");
     						 atts2.put("widthPercentage", Integer.parseInt(w.substring(0,  w.length() -1)));
     					 }
-    					 
-    					 if (atts2.get("height") == null) {
-    						 atts2.put("height", "100");
+
+    					 if (atts2.get("height") == null || !isInt(atts2.get("height"))) {
+    						 atts2.put("height", "1000");
     						 atts2.put("heightPercentage", 100);
     					 } else if (((String) atts.get("height")).endsWith("%")) {
     						 String h = (String) atts.get("height");
--- a/rt/net/sourceforge/jnlp/runtime/JNLPClassLoader.java	Mon Nov 17 09:53:50 2008 -0500
+++ b/rt/net/sourceforge/jnlp/runtime/JNLPClassLoader.java	Tue Nov 18 11:04:46 2008 -0500
@@ -29,6 +29,7 @@
 import java.security.Permission;
 import java.security.PermissionCollection;
 import java.security.Permissions;
+import java.security.Policy;
 import java.security.PrivilegedAction;
 import java.util.ArrayList;
 import java.util.Enumeration;
@@ -434,7 +435,7 @@
         // add in the permissions that the user granted.
         for (int i=0; i < runtimePermissions.size(); i++)
         	result.add(runtimePermissions.get(i));
-        
+
         return result;
     }
 
@@ -731,7 +732,7 @@
 
                         }
 
-                        // If it still fails, let it error out
+                        // If it still fails, let it error out                        
                         result = loadClassExt(name);
                     }
                 }
--- a/rt/net/sourceforge/jnlp/runtime/JNLPPolicy.java	Mon Nov 17 09:53:50 2008 -0500
+++ b/rt/net/sourceforge/jnlp/runtime/JNLPPolicy.java	Tue Nov 18 11:04:46 2008 -0500
@@ -18,6 +18,7 @@
 package net.sourceforge.jnlp.runtime;
 
 import java.security.*;
+import java.util.Enumeration;
 
 /**
  * Policy for JNLP environment.  This class delegates to the
@@ -60,7 +61,15 @@
         if (JNLPRuntime.getApplication() != null) {
         	if (JNLPRuntime.getApplication().getClassLoader() instanceof JNLPClassLoader) {
         		JNLPClassLoader cl = (JNLPClassLoader) JNLPRuntime.getApplication().getClassLoader();
-        		return cl.getPermissions(source);
+        		
+        		PermissionCollection clPermissions = cl.getPermissions(source);
+        		
+        		// systempolicy permissions need to be accounted for as well
+        		Enumeration e = systemPolicy.getPermissions(source).elements();
+                while (e.hasMoreElements())
+                    clPermissions.add((Permission) e.nextElement());
+
+        		return clPermissions;
         	}
         }
 
--- a/rt/net/sourceforge/jnlp/tools/JarSigner.java	Mon Nov 17 09:53:50 2008 -0500
+++ b/rt/net/sourceforge/jnlp/tools/JarSigner.java	Tue Nov 18 11:04:46 2008 -0500
@@ -189,7 +189,16 @@
             certs = new ArrayList<CertPath>();
 
             try {
-                String localFile = tracker.getCacheFile(jar.getLocation()).getAbsolutePath();
+                
+                File jarFile = tracker.getCacheFile(jar.getLocation());
+                
+                // some sort of resource download/cache error. Nothing to add 
+                // in that case ... but don't fail here
+                if (jarFile == null) {
+                    return;
+                }
+
+                String localFile = jarFile.getAbsolutePath();
                 boolean result = verifyJar(localFile);
                 checkTrustedCerts();