changeset 751:5284b488b3ed cacao

2008-03-06 Joshua Sumali <jsumali@redhat.com> * Makefile.am: Added new 'extra' targets. These new targets build the sources in the extra/ directory to build about.jar, which is the new sample jnlp application for javaws. * Makefile.in: Regenerated. * generated/sun/awt/X11/generator/sizer.32: Regenerated. * rt/net/sourceforge/jnlp/resources/Manifest.mf: Fix boot class typo. * rt/net/sourceforge/jnlp/resources/Messages.properties: Improved command line options. * rt/net/sourceforge/jnlp/runtime/Boot.java: Changed command line behaviour. Sample application now only runs if the -about flag is passed. * rt/net/sourceforge/jnlp/runtime/JNLPRuntime.java: Remove call to printStackTrace. * rt/net/sourceforge/jnlp/security/CertsInfoPane.java: Rearranged methods and relaxed visibility in some fields/methods for SingleCertInfoPane class. * rt/net/sourceforge/jnlp/security/SecurityWarningDialog.java: Added single certificate dialog showing. * rt/net/sourceforge/jnlp/tools/KeyTool.java: Moved KeyStore retrieving to new SecurityUtil class. * extra/net/sourceforge/jnlp/about/HTMLPanel.java: New File. * extra/net/sourceforge/jnlp/about/Main.java: Likewise. * extra/net/sourceforge/jnlp/about/resources/about.html: Likewise. * extra/net/sourceforge/jnlp/about/resources/applications.html: Likewise. * extra/net/sourceforge/jnlp/about/resources/jamIcon.jpg: Likewise. * extra/net/sourceforge/jnlp/about/resources/notes.html: Likewise. * rt/net/sourceforge/jnlp/resources/about.jnlp: Likewise. * rt/net/sourceforge/jnlp/security/SecurityUtil.java: Likewise. * rt/net/sourceforge/jnlp/security/SingleCertInfoPane.java: Likewise. * rt/net/sourceforge/jnlp/security/viewer/CertificatePane.java: Likewise. * rt/net/sourceforge/jnlp/security/viewer/CertificateViewer.java: Likewise.
author Joshua Sumali <jsumali@redhat.com>
date Thu, 06 Mar 2008 09:46:38 -0500
parents c4af65fc7574
children 1e22bff17664
files ChangeLog Makefile.am Makefile.in extra/net/sourceforge/jnlp/about/HTMLPanel.java extra/net/sourceforge/jnlp/about/Main.java extra/net/sourceforge/jnlp/about/resources/about.html extra/net/sourceforge/jnlp/about/resources/applications.html extra/net/sourceforge/jnlp/about/resources/jamIcon.jpg extra/net/sourceforge/jnlp/about/resources/notes.html generated/sun/awt/X11/generator/sizer.32 rt/net/sourceforge/jnlp/resources/Manifest.mf rt/net/sourceforge/jnlp/resources/Messages.properties rt/net/sourceforge/jnlp/resources/about.jnlp rt/net/sourceforge/jnlp/runtime/Boot.java rt/net/sourceforge/jnlp/runtime/JNLPRuntime.java rt/net/sourceforge/jnlp/security/CertsInfoPane.java rt/net/sourceforge/jnlp/security/SecurityUtil.java rt/net/sourceforge/jnlp/security/SecurityWarningDialog.java rt/net/sourceforge/jnlp/security/SingleCertInfoPane.java rt/net/sourceforge/jnlp/security/viewer/CertificatePane.java rt/net/sourceforge/jnlp/security/viewer/CertificateViewer.java rt/net/sourceforge/jnlp/tools/KeyTool.java
diffstat 22 files changed, 1523 insertions(+), 213 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Wed Mar 05 08:37:23 2008 -0500
+++ b/ChangeLog	Thu Mar 06 09:46:38 2008 -0500
@@ -1,3 +1,37 @@
+2008-03-06  Joshua Sumali  <jsumali@redhat.com>
+
+	* Makefile.am: Added new 'extra' targets. These new targets build the
+	sources in the extra/ directory to build about.jar, which is the new
+	sample jnlp application for javaws. 
+	* Makefile.in: Regenerated.
+	* generated/sun/awt/X11/generator/sizer.32: Regenerated.
+	* rt/net/sourceforge/jnlp/resources/Manifest.mf: Fix boot class typo.
+	* rt/net/sourceforge/jnlp/resources/Messages.properties: Improved command
+	line options.
+	* rt/net/sourceforge/jnlp/runtime/Boot.java: Changed command line
+	behaviour. Sample application now only runs if the -about flag is passed.
+	* rt/net/sourceforge/jnlp/runtime/JNLPRuntime.java: Remove call to
+	printStackTrace.
+	* rt/net/sourceforge/jnlp/security/CertsInfoPane.java: Rearranged methods
+	and relaxed visibility in some fields/methods for SingleCertInfoPane
+	class.
+	* rt/net/sourceforge/jnlp/security/SecurityWarningDialog.java: Added
+	single certificate dialog showing.
+	* rt/net/sourceforge/jnlp/tools/KeyTool.java: Moved KeyStore retrieving to
+	new SecurityUtil class.
+	* extra/net/sourceforge/jnlp/about/HTMLPanel.java: New File.
+	* extra/net/sourceforge/jnlp/about/Main.java: Likewise.
+	* extra/net/sourceforge/jnlp/about/resources/about.html: Likewise.
+	* extra/net/sourceforge/jnlp/about/resources/applications.html: Likewise.
+	* extra/net/sourceforge/jnlp/about/resources/jamIcon.jpg: Likewise.
+	* extra/net/sourceforge/jnlp/about/resources/notes.html: Likewise.
+	* rt/net/sourceforge/jnlp/resources/about.jnlp: Likewise.
+	* rt/net/sourceforge/jnlp/security/SecurityUtil.java: Likewise.
+	* rt/net/sourceforge/jnlp/security/SingleCertInfoPane.java: Likewise.
+	* rt/net/sourceforge/jnlp/security/viewer/CertificatePane.java: Likewise.
+	* rt/net/sourceforge/jnlp/security/viewer/CertificateViewer.java:
+	Likewise.
+
 2008-03-05  Gary Benson  <gbenson@redhat.com>
 
 	* contrib/templater/README: Updated URL.
--- a/Makefile.am	Wed Mar 05 08:37:23 2008 -0500
+++ b/Makefile.am	Thu Mar 06 09:46:38 2008 -0500
@@ -16,9 +16,11 @@
 distclean-local: clean-copy
 	rm -rf stamps
 	rm -f rt-source-files.txt \
-	  hotspot-tools-source-files.txt
+	  hotspot-tools-source-files.txt \
+	  extra-source-files.txt
 	rm -rf bootstrap
 	rm -rf lib
+	rm -rf extra-lib
 	rm -rf openjdk-ecj
 	rm -rf openjdk
 	rm -rf hotspot-tools
@@ -34,7 +36,7 @@
 	clean-icedtea icedtea-against-icedtea clean-icedtea-ecj clean-plugs \
 	clean-tools-jar clean-shared-objects \
 	clean-copy clean-hotspot-tools clean-rt clean-gcjwebplugin \
-	hotspot hotspot-helper
+	hotspot hotspot-helper clean-extra
 
 EXTRA_DIST = rt generated $(ICEDTEA_PATCHES) $(ICEDTEA_ECJ_PATCH) \
 	gcjwebplugin.cc patches/icedtea-speed.patch tools-copy contrib ports \
@@ -498,7 +500,8 @@
 # you change it in the icedtea-debug target as well.
 icedtea: stamps/bootstrap-directory-symlink.stamp \
 	stamps/hotspot-tools.stamp stamps/plugs.stamp \
-	stamps/ports.stamp stamps/patch.stamp gcjwebplugin.so
+	stamps/ports.stamp stamps/patch.stamp gcjwebplugin.so \
+	extra-lib/about.jar
 	$(MAKE) \
 	  $(ICEDTEA_ENV) \
 	  -C openjdk/control/make/
@@ -509,15 +512,18 @@
 	  cp -pPRf gcjwebplugin.so \
 	    $(BUILD_OUTPUT_DIR)/j2re-image/lib/$(INSTALL_ARCH_DIR) ; \
 	fi
-	cp rt/net/sourceforge/jnlp/resources/default.jnlp \
+	cp rt/net/sourceforge/jnlp/resources/about.jnlp \
+	  extra-lib/about.jar \
 	  $(BUILD_OUTPUT_DIR)/j2re-image/lib
-	cp rt/net/sourceforge/jnlp/resources/default.jnlp \
+	cp rt/net/sourceforge/jnlp/resources/about.jnlp \
+	  extra-lib/about.jar \
 	  $(BUILD_OUTPUT_DIR)/j2sdk-image/jre/lib
 	@echo "IcedTea is served:" $(BUILD_OUTPUT_DIR)
 
 icedtea-debug: stamps/bootstrap-directory-symlink.stamp \
 	stamps/hotspot-tools.stamp stamps/plugs.stamp \
-	stamps/ports.stamp stamps/patch.stamp gcjwebplugin.so
+	stamps/ports.stamp stamps/patch.stamp gcjwebplugin.so \
+	extra-lib/about.jar
 	$(MAKE) \
 	  $(ICEDTEA_ENV) \
 	  -C openjdk/control/make \
@@ -530,8 +536,10 @@
 	    $(BUILD_OUTPUT_DIR)-debug/j2re-image/lib/$(INSTALL_ARCH_DIR) ; \
 	fi
 	cp rt/net/sourceforge/jnlp/resources/default.jnlp \
+	  extra-lib/about.jar \
 	  $(BUILD_OUTPUT_DIR)-debug/j2re-image/lib
 	cp rt/net/sourceforge/jnlp/resources/default.jnlp \
+	  extra-lib/about.jar \
 	  $(BUILD_OUTPUT_DIR)-debug/j2sdk-image/jre/lib
 	@echo "IcedTea (debug build) is served:" \
 	  $(BUILD_OUTPUT_DIR)-debug
@@ -789,6 +797,42 @@
 	  cp bootstrap/jdk1.7.0/jre/lib/rt-closed.jar bootstrap/ecj/jre/lib/rt.jar; \
 	fi
 
+# extras -- used to create about.jar for javaws.
+extra-source-files.txt:
+	find extra -name '*.java' | sort > $@
+
+stamps/extra-class-files.stamp: extra-source-files.txt \
+	bootstrap/jdk1.7.0/jre/lib/rt-closed.jar
+	mkdir -p extra-lib
+	if ! test -f stamps/icedtea-ecj.stamp ; \
+	  then \
+	  $(JAVAC) $(MEMORY_LIMIT) -g -d extra-lib -bootclasspath '' -source 1.6 \
+	    -sourcepath extra -cp bootstrap/jdk1.7.0/jre/lib/rt-closed.jar \
+		@extra-source-files.txt ; \
+	else \
+	  $(ICEDTEA_BOOT_DIR)/bin/javac $(MEMORY_LIMIT) -g -d extra-lib \
+	    -bootclasspath '' -source 1.6 \
+	    -sourcepath extra -cp bootstrap/jdk1.7.0/jre/lib/rt-closed.jar \
+		@extra-source-files.txt ; \
+	fi
+	cp -r extra/net/sourceforge/jnlp/about/resources \
+	  extra-lib/net/sourceforge/jnlp/about
+	mkdir -p stamps
+	touch $@
+
+clean-extra:
+	rm -rf extra-lib
+	rm -f stamps/extra-class-files.stamp
+	rm -f extra-source-files.txt
+
+extra-lib/about.jar: stamps/extra-class-files.stamp
+	if ! test -f stamps/icedtea-ecj.stamp ; \
+	  then \
+	  $(JAR) cf $@ -C extra-lib net ; \
+	else \
+	  $(ICEDTEA_BOOT_DIR)/bin/jar cf $@ -C extra-lib net ; \
+	fi
+
 # gcjwebplugin.so.
 gcjwebplugin.so: gcjwebplugin.cc
 	if test "$(ENABLE_PLUGIN)" == "yes" ; \
--- a/Makefile.in	Wed Mar 05 08:37:23 2008 -0500
+++ b/Makefile.in	Thu Mar 06 09:46:38 2008 -0500
@@ -655,9 +655,11 @@
 distclean-local: clean-copy
 	rm -rf stamps
 	rm -f rt-source-files.txt \
-	  hotspot-tools-source-files.txt
+	  hotspot-tools-source-files.txt \
+	  extra-source-files.txt
 	rm -rf bootstrap
 	rm -rf lib
+	rm -rf extra-lib
 	rm -rf openjdk-ecj
 	rm -rf openjdk
 	rm -rf hotspot-tools
@@ -673,7 +675,7 @@
 	clean-icedtea icedtea-against-icedtea clean-icedtea-ecj clean-plugs \
 	clean-tools-jar clean-shared-objects \
 	clean-copy clean-hotspot-tools clean-rt clean-gcjwebplugin \
-	hotspot hotspot-helper
+	hotspot hotspot-helper clean-extra
 
 env:
 	@echo 'unset JAVA_HOME'
@@ -922,7 +924,8 @@
 # you change it in the icedtea-debug target as well.
 icedtea: stamps/bootstrap-directory-symlink.stamp \
 	stamps/hotspot-tools.stamp stamps/plugs.stamp \
-	stamps/ports.stamp stamps/patch.stamp gcjwebplugin.so
+	stamps/ports.stamp stamps/patch.stamp gcjwebplugin.so \
+	extra-lib/about.jar
 	$(MAKE) \
 	  $(ICEDTEA_ENV) \
 	  -C openjdk/ j2se_only
@@ -933,15 +936,18 @@
 	  cp -pPRf gcjwebplugin.so \
 	    $(BUILD_OUTPUT_DIR)/j2re-image/lib/$(INSTALL_ARCH_DIR) ; \
 	fi
-	cp rt/net/sourceforge/jnlp/resources/default.jnlp \
+	cp rt/net/sourceforge/jnlp/resources/about.jnlp \
+	  extra-lib/about.jar \
 	  $(BUILD_OUTPUT_DIR)/j2re-image/lib
-	cp rt/net/sourceforge/jnlp/resources/default.jnlp \
+	cp rt/net/sourceforge/jnlp/resources/about.jnlp \
+	  extra-lib/about.jar \
 	  $(BUILD_OUTPUT_DIR)/j2sdk-image/jre/lib
 	@echo "IcedTea is served:" $(BUILD_OUTPUT_DIR)
 
 icedtea-debug: stamps/bootstrap-directory-symlink.stamp \
 	stamps/hotspot-tools.stamp stamps/plugs.stamp \
-	stamps/ports.stamp stamps/patch.stamp gcjwebplugin.so
+	stamps/ports.stamp stamps/patch.stamp gcjwebplugin.so \
+	extra-lib/about.jar
 	$(MAKE) \
 	  $(ICEDTEA_ENV) \
 	  -C openjdk/ \
@@ -954,8 +960,10 @@
 	    $(BUILD_OUTPUT_DIR)-debug/j2re-image/lib/$(INSTALL_ARCH_DIR) ; \
 	fi
 	cp rt/net/sourceforge/jnlp/resources/default.jnlp \
+	  extra-lib/about.jar \
 	  $(BUILD_OUTPUT_DIR)-debug/j2re-image/lib
 	cp rt/net/sourceforge/jnlp/resources/default.jnlp \
+	  extra-lib/about.jar \
 	  $(BUILD_OUTPUT_DIR)-debug/j2sdk-image/jre/lib
 	@echo "IcedTea (debug build) is served:" \
 	  $(BUILD_OUTPUT_DIR)-debug
@@ -1183,6 +1191,42 @@
 	  cp bootstrap/jdk1.7.0/jre/lib/rt-closed.jar bootstrap/ecj/jre/lib/rt.jar; \
 	fi
 
+# extras -- used to create about.jar for javaws.
+extra-source-files.txt:
+	find extra -name '*.java' | sort > $@
+
+stamps/extra-class-files.stamp: extra-source-files.txt \
+	bootstrap/jdk1.7.0/jre/lib/rt-closed.jar
+	mkdir -p extra-lib
+	if ! test -f stamps/icedtea-ecj.stamp ; \
+	  then \
+	  $(JAVAC) $(MEMORY_LIMIT) -g -d extra-lib -bootclasspath '' -source 1.6 \
+	    -sourcepath extra -cp bootstrap/jdk1.7.0/jre/lib/rt-closed.jar \
+		@extra-source-files.txt ; \
+	else \
+	  $(ICEDTEA_BOOT_DIR)/bin/javac $(MEMORY_LIMIT) -g -d extra-lib \
+	    -bootclasspath '' -source 1.6 \
+	    -sourcepath extra -cp bootstrap/jdk1.7.0/jre/lib/rt-closed.jar \
+		@extra-source-files.txt ; \
+	fi
+	cp -r extra/net/sourceforge/jnlp/about/resources \
+	  extra-lib/net/sourceforge/jnlp/about
+	mkdir -p stamps
+	touch $@
+
+clean-extra:
+	rm -rf extra-lib
+	rm -f stamps/extra-class-files.stamp
+	rm -f extra-source-files.txt
+
+extra-lib/about.jar: stamps/extra-class-files.stamp
+	if ! test -f stamps/icedtea-ecj.stamp ; \
+	  then \
+	  $(JAR) cf $@ -C extra-lib net ; \
+	else \
+	  $(ICEDTEA_BOOT_DIR)/bin/jar cf $@ -C extra-lib net ; \
+	fi
+
 # gcjwebplugin.so.
 gcjwebplugin.so: gcjwebplugin.cc
 	if test "$(ENABLE_PLUGIN)" == "yes" ; \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/extra/net/sourceforge/jnlp/about/HTMLPanel.java	Thu Mar 06 09:46:38 2008 -0500
@@ -0,0 +1,59 @@
+/* HTMLPanel.java
+   Copyright (C) 2008 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.about;
+
+import java.awt.BorderLayout;
+import java.io.IOException;
+import java.net.URL;
+
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JEditorPane;
+
+public class HTMLPanel extends JPanel {
+
+	JEditorPane pane;
+	
+	public HTMLPanel(URL url) throws IOException {
+		super(new BorderLayout());
+		pane = new JEditorPane(url);
+		pane.setEditable(false);
+		JScrollPane scroller = new JScrollPane(pane);
+		add(scroller, BorderLayout.CENTER);
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/extra/net/sourceforge/jnlp/about/Main.java	Thu Mar 06 09:46:38 2008 -0500
@@ -0,0 +1,135 @@
+/* Main.java
+   Copyright (C) 2008 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.about;
+
+import java.awt.BorderLayout;
+import java.awt.Dimension;
+import java.awt.Toolkit;
+import java.io.IOException;
+import java.net.URL;
+
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+import javax.swing.JTabbedPane;
+import javax.swing.UIManager;
+import javax.swing.event.HyperlinkEvent;
+import javax.swing.event.HyperlinkListener;
+
+import net.sourceforge.jnlp.Launcher;
+import net.sourceforge.jnlp.runtime.JNLPRuntime;
+
+public class Main extends JPanel implements HyperlinkListener {
+
+	private final String notes = "/net/sourceforge/jnlp/about/resources/notes.html";
+	private final String apps = "/net/sourceforge/jnlp/about/resources/applications.html";
+	private final String about = "/net/sourceforge/jnlp/about/resources/about.html";
+	JTabbedPane tabbedPane;
+
+	public Main() throws IOException {
+		super(new BorderLayout());
+		
+		HTMLPanel notesPanel = new HTMLPanel(getClass().getResource(notes));
+		HTMLPanel appsPanel = new HTMLPanel(getClass().getResource(apps));
+		HTMLPanel aboutPanel = new HTMLPanel(getClass().getResource(about));
+		
+		appsPanel.pane.addHyperlinkListener(this);
+		
+		tabbedPane = new JTabbedPane();
+
+		tabbedPane.add("About NetX", aboutPanel);
+		tabbedPane.add("Applications", appsPanel);
+		tabbedPane.add("Notes", notesPanel);
+		
+		tabbedPane.setPreferredSize(new Dimension(550,410));
+		add(tabbedPane, BorderLayout.CENTER);
+	}
+
+	private static void createAndShowGUI() {
+		JNLPRuntime.setExitClass(Main.class);
+		
+		try {
+			UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
+		} catch (Exception e) {	
+		}
+		
+		JFrame frame = new JFrame("About NetX");
+		frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
+		Main demo = null;
+		try {
+			demo = new Main();
+		} catch (Exception e) {
+			e.printStackTrace();
+			System.exit(1);
+		}
+		demo.setOpaque(true);
+		frame.setContentPane(demo);
+		frame.pack();
+		centerDialog(frame);
+		frame.setVisible(true);
+	}
+	
+    private static void centerDialog(JFrame frame) {
+        Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
+        Dimension dialogSize = frame.getSize();
+
+        frame.setLocation((screen.width - dialogSize.width)/2,
+            (screen.height - dialogSize.height)/2);
+    }
+
+	public static void main(String[] args) {
+		javax.swing.SwingUtilities.invokeLater(new Runnable() {
+			public void run() {
+				createAndShowGUI();
+			}
+		});
+	}
+
+	public void hyperlinkUpdate(HyperlinkEvent e) {
+		if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
+			URL url = e.getURL();
+
+			Launcher launcher = new Launcher(
+					JNLPRuntime.getDefaultLaunchHandler());
+			try {
+				launcher.launchBackground(url);
+			} catch (Exception ex) {
+				ex.printStackTrace();
+			}
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/extra/net/sourceforge/jnlp/about/resources/about.html	Thu Mar 06 09:46:38 2008 -0500
@@ -0,0 +1,28 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+    <head>
+        <title>
+        </title>
+    </head>
+    <body>
+        <b>NetX</b> is a high-quality JNLP client that executes
+        network-based applications.  
+        <br>NetX downloads code over the
+        network, caches it, and runs it in a secure sandbox
+        environment (unless signed).
+        <br><br><big><b>
+                Features of NetX:
+        </b></big>
+        <ul>
+            <li><b>Modular: </b>Easily add JNLP capabilities to an application.</li>
+            <li><b>Small Size: </b>Loads from a ~130K JAR file.</li>
+            <li><b>Saves Memory: </b>Launch programs in a shared JVM.</li>
+            <li><b>Fast startup:</b> Runs applications from a cache for fast starting. </li>
+            <li><b>Security:</b> Run any application in a sandbox or log its activities.</li>
+            <li><b>Auto-Update:</b> Applications can auto-update without special code.</li>
+            <li><b>Network Deployment:</b> Deploy to the internet, not with installers. </li>
+            <li><b>Open Source:</b> GNU Lesser General Public License.</li>
+        </ul>
+    </body>
+</html>
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/extra/net/sourceforge/jnlp/about/resources/applications.html	Thu Mar 06 09:46:38 2008 -0500
@@ -0,0 +1,36 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<title>Applications</title>
+</head>
+<body>
+
+<big><b>Sample Applications:</b></big><br>
+<b>&nbsp;&nbsp;&nbsp;<a href="http://www.jGoodies.com/download/jdiskreport/jdiskreport.jnlp">jDiskReport</a> -</b> http://www.jGoodies.com/download/jdiskreport/jdiskreport.jnlp<br>
+<b>&nbsp;&nbsp;&nbsp;<a href="http://www.jgoodies.com/download/jpathreport/jpathreport.jnlp">jPathReport</a> -</b> http://www.jgoodies.com/download/jpathreport/jpathreport.jnlp<br>
+<b>&nbsp;&nbsp;&nbsp;<a href="http://www.L2FProd.com/software/skinlf/jnlp/demo.php">Skin L2F Demo</a> -</b> http://www.L2FProd.com/software/skinlf/jnlp/demo.php<br>
+<b>&nbsp;&nbsp;&nbsp;<a href="http://www.glub.com/products/secureftp/secureftp.jnlp">Secure FTP</a> -</b> http://www.glub.com/products/secureftp/secureftp.jnlp<br>
+<b>&nbsp;&nbsp;&nbsp;<a href="http://www.jext.org/apps/jext.jnlp">Jext</a> -</b> http://www.jext.org/apps/jext.jnlp<br>
+<b>&nbsp;&nbsp;&nbsp;<a href="http://www.javazoom.net/jlgui/jws/jlgui.jnlp">Java Music Player</a> -</b> http://www.javazoom.net/jlgui/jws/jlgui.jnlp<br>
+<br>
+<big><b>Apps using netx:</b></big><br>
+<b>&nbsp;&nbsp;&nbsp;<a href="http://jnlp.sourceforge.net/netx/start/start.jnlp">Java Start Button</a> -</b> http://jnlp.sourceforge.net/netx/start/start.jnlp<br>
+<br>
+<big><b>Sun Demos:</b></big><br>
+<b>&nbsp;&nbsp;&nbsp;<a href="http://java.sun.com/products/javawebstart/apps/swingset2.jnlp">SwingSet2</a> -</b> http://java.sun.com/products/javawebstart/apps/swingset2.jnlp<br>
+<b>&nbsp;&nbsp;&nbsp;<a href="http://java.sun.com/products/javawebstart/apps/notepad.jnlp">Notepad</a> -</b> http://java.sun.com/products/javawebstart/apps/notepad.jnlp<br>
+<b>&nbsp;&nbsp;&nbsp;<a href="http://java.sun.com/products/javawebstart/apps/draw.jnlp">Draw</a> -</b> http://java.sun.com/products/javawebstart/apps/draw.jnlp<br>
+<b>&nbsp;&nbsp;&nbsp;<a href="http://java.sun.com/products/javawebstart/apps/mg.jnlp">Military Game</a> -</b> http://java.sun.com/products/javawebstart/apps/mg.jnlp<br>
+<br>
+<big><b>Tests:</b></big><br>
+&nbsp;&nbsp;&nbsp;<a href="http://www.acm.vt.edu/~jmaxwell/security/SecurityTest.jnlp">Security Test</a><br>
+&nbsp;&nbsp;&nbsp;<a href="http://www.acm.vt.edu/~jmaxwell/security/SecurityTestSigned.jnlp">Security Test (signed)</a><br>
+&nbsp;&nbsp;&nbsp;<a href="http://www.acm.vt.edu/~jmaxwell/security/StrictTest.jnlp">Security Test (signed; fail strict JNLP)</a><br>
+&nbsp;&nbsp;&nbsp;<a href="http://www.acm.vt.edu/~jmaxwell/security/PermissionList.jnlp">Permission Test</a><br>
+&nbsp;&nbsp;&nbsp;<a href="http://www.acm.vt.edu/~jmaxwell/security/PermissionListSigned.jnlp">Permission Test (signed)</a>
+<table cellpadding="0" cellspacing="0" border="0">
+		<tbody><tr><td valign="Top" nowrap="true" bgcolor="#ffffff" width="500"><br>
+		</td></tr></tbody>
+</table>
+</body>
+</html>
Binary file extra/net/sourceforge/jnlp/about/resources/jamIcon.jpg has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/extra/net/sourceforge/jnlp/about/resources/notes.html	Thu Mar 06 09:46:38 2008 -0500
@@ -0,0 +1,82 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+	<head>
+		<title>Release Notes</title>
+	</head>
+	<body>
+	<br>
+	<table cellpadding="2" cellspacing="2" border="0" width="100%">
+		<tbody>
+		<tr>
+			<td valign="Top" width="15"></td>
+			<td valign="Top" width="100%">
+				<table cellpadding="0" cellspacing="0" border="0" align="Center">
+					<tbody>
+						<tr>
+							<td valign="Middle" align="Center" nowrap="true"><div align="Center">
+								<img src="jamIcon.jpg" alt="Jam Icon" width="87" height="84" align="Center">
+								</div>
+							</td>
+						</tr>
+						<tr>
+							<td valign="Middle" nowrap="true" align="Justify">
+								<div align="Center">
+								<big><b>Jon A. Maxwell</b></big><br>
+								developer<br>
+								<big><b>Joshua Sumali</b></big><br>
+								developer
+								</div>
+							</td>
+						</tr>
+					</tbody>
+				</table>
+			</td>
+		</tr>
+		</tbody>
+	</table>
+<br>
+<big><b>Release Notes</b></big>
+<br>
+<table cellpadding="0" cellspacing="0" border="0">
+	<tbody>
+		<tr>
+			<td valign="Top" width="15"><br></td>
+			
+
+			<td valign="Top"> 
+			NetX on IcedTea: Security Support
+			<ul>
+				<li> Full signed application support </li>
+				<li> User trusted certificates support </li>
+				<li> Some JNLP API Services implemented </li>
+				<li> Improved unsigned application sandboxing with JNLP API </li>
+			</ul>
+			</td>
+		</tr>
+		<tr>
+			<td valign="Top" width="15"><br></td>
+			<td valign="Top"> 
+			Version 0.5: Refines multi-app capabilities + native code support
+			<ul>
+				<li> Released under LGPL. </li> 
+				<li> Separate event queue, look and feel, etc for each application. </li> 
+				<li> Native code support. </li> 
+				<li> Supports headless mode. </li> 
+				<li> Internationalized messages. </li> 
+				<li> Uses NanoXML parser. </li> 
+				<li> Minor changes listed on project web site... </li> 
+			</ul>
+
+			</td>
+		</tr>
+	</tbody>
+</table>
+<b>Please visit the SourceForge site
+	<a href="http://jnlp.sourceforge.net/netx/index.html">
+		http://jnlp.sourceforge.net/netx/index.html
+	</a>
+	and the IcedTea site
+	<a href="http://iced-tea.org">http://iced-tea.org</a>
+	 for more information.</b><br>
+</body>
+</html>
Binary file generated/sun/awt/X11/generator/sizer.32 has changed
--- a/rt/net/sourceforge/jnlp/resources/Manifest.mf	Wed Mar 05 08:37:23 2008 -0500
+++ b/rt/net/sourceforge/jnlp/resources/Manifest.mf	Thu Mar 06 09:46:38 2008 -0500
@@ -2,5 +2,5 @@
 Created-By: jnlp.sourceforge.net
 Specification-Title: netx JNLP client
 Sealed: true
-Main-Class: net.sourceforge.jnlp.netx.jnlp.runtime.Boot13
+Main-Class: net.sourceforge.jnlp.runtime.Boot13
 
--- a/rt/net/sourceforge/jnlp/resources/Messages.properties	Wed Mar 05 08:37:23 2008 -0500
+++ b/rt/net/sourceforge/jnlp/resources/Messages.properties	Thu Mar 06 09:46:38 2008 -0500
@@ -105,7 +105,8 @@
 RExitNoApp=Can not exit the JVM because the current application cannot be determined.
 
 # Boot options, message should be shorter than this ---------------->
-BOUsage=Usage: java -jar netx.jar [-options] -jnlp location
+BOUsage=javaws [-run-options] <jnlp file>
+BOUsage2=javaws [-control-options]
 BOBasedir   = Directory where the cache is kept.
 BOJnlp      = Location of JNLP file to launch (url or file).
 BOArg       = Adds an application argument before launching.
@@ -114,11 +115,12 @@
 BOUpdate    = Update check if seconds since last checked.
 BOLicense   = Display the GPL license and exit.
 BOVerbose   = Enable verbose output.
-BOAbout     = Streamed from the internet.
+BOAbout     = Shows a sample application.
 BONosecurity= Disables the secure runtime environment.
 BONoupdate  = Disables checking for updates.
 BOHeadless  = Disables download window, other UIs.
 BOStrict    = Enables strict checking of JNLP file format.
+BOViewer    = Shows the trusted certificate viewer.
 BOHelp      = Print this message and exit.
 
 # Cache
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rt/net/sourceforge/jnlp/resources/about.jnlp	Thu Mar 06 09:46:38 2008 -0500
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<jnlp spec="1.0" href="about.jnlp" codebase=".">
+  <information>
+    <title>About window for NetX</title>
+    <vendor>NetX</vendor>
+    <homepage href="http://jnlp.sourceforge.net/netx/"/>
+    <description>Displays information about NetX</description>
+    <offline/>
+  </information>
+  <resources>
+    <j2se version="1.4+"/>
+    <jar href="about.jar"/>
+  </resources>
+  <security>
+    <all-permissions/>
+  </security>
+  <application-desc main-class="net.sourceforge.jnlp.about.Main">
+  </application-desc>
+</jnlp>
+
--- a/rt/net/sourceforge/jnlp/runtime/Boot.java	Wed Mar 05 08:37:23 2008 -0500
+++ b/rt/net/sourceforge/jnlp/runtime/Boot.java	Thu Mar 06 09:46:38 2008 -0500
@@ -25,6 +25,7 @@
 import net.sourceforge.jnlp.*;
 import net.sourceforge.jnlp.cache.*;
 import net.sourceforge.jnlp.runtime.*;
+import net.sourceforge.jnlp.security.viewer.CertificateViewer;
 import net.sourceforge.jnlp.services.*;
 import net.sourceforge.jnlp.util.*;
 
@@ -51,8 +52,8 @@
     private static final String version = "0.5";
 
     /** the JNLP file to open to display the network-based about window */
-    private static final String aboutFile =
-        "http://jnlp.sourceforge.net/netx/about/netx"+version+".jnlp";
+    private static final String aboutFile = 
+    	System.getProperty("java.home") + "/lib/about.jnlp";
 
     /** the text to display before launching the about link */
     private static final String aboutMessage = ""
@@ -80,16 +81,21 @@
         + "\n";
 
     private static final String helpMessage = "\n"
-        + R("BOUsage")+"\n"
+        + "Usage:   " + R("BOUsage")+"\n"
+        + "         " + R("BOUsage2")+"\n"
+        + "\n"
+        + "control-options:"+"\n"
+        + "  -about                "+R("BOAbout")+"\n"
+        + "  -viewer               "+R("BOViewer")+"\n"
+        + "\n"
+        + "run-options:"+"\n"
         + "  -basedir dir          "+R("BOBasedir")+"\n"
-        + "  -jnlp location        "+R("BOJnlp")+"\n"
         + "  -arg arg              "+R("BOArg")+"\n"
         + "  -param name=value     "+R("BOParam")+"\n"
         + "  -property name=value  "+R("BOProperty")+"\n"
         + "  -update seconds       "+R("BOUpdate")+"\n"
         + "  -license              "+R("BOLicense")+"\n"
         + "  -verbose              "+R("BOVerbose")+"\n"
-        + "  -about                "+R("BOAbout")+"\n"
         + "  -nosecurity           "+R("BONosecurity")+"\n"
         + "  -noupdate             "+R("BONoupdate")+"\n"
         + "  -headless             "+R("BOHeadless")+"\n"
@@ -106,6 +112,18 @@
      */
     public static void main(String[] argsIn) {
         args = argsIn;
+        
+        if (null != getOption("-viewer")) {
+
+        	try {
+        		CertificateViewer.main(null);
+        		System.exit(0);
+        	} catch (Exception e) {
+        		// TODO Auto-generated catch block
+        		e.printStackTrace();
+        	}
+
+        }
 
         if (null != getOption("-license")) {
             System.out.println(miniLicense);
@@ -131,8 +149,6 @@
         if (null != getOption("-headless"))
             JNLPRuntime.setHeadless(true);
 
-	if (null != getOption("-verify"))
-            JNLPRuntime.setVerify(true);
 
         if (null != getOption("-noupdate"))
             JNLPRuntime.setDefaultUpdatePolicy(UpdatePolicy.NEVER);
@@ -174,14 +190,16 @@
         System.exit(1);
     }
 
-	private static String getDefaultFile() {
+    /**
+     * Returns the about.jnlp file in {java.home}/lib or null if this file
+     * does not exist.
+     */
+	private static String getAboutFile() {
 
-		String defaultJnlpFile = System.getProperty("java.home") 
-			+ "/lib/default.jnlp";
-		if (new File(defaultJnlpFile).exists())
-			return defaultJnlpFile;
-
-		return null;
+		if (new File(aboutFile).exists())
+			return aboutFile;
+		else
+			return null;
 	}
 
     /**
@@ -189,28 +207,37 @@
      * specified.
      */
     private static JNLPFile getFile() throws ParseException, MalformedURLException, IOException {
-        String location = getOption("-jnlp");
-
+    
+        String location = getJNLPFile();
+        
         // override -jnlp with aboutFile
-        if (null != getOption("-about"))
-            location = aboutFile;
+        if (getOption("-about") != null) {
+        	location = getAboutFile();
+        	if (location == null)
+        		fatalError("Unable to find about.jnlp in {java.home}/lib/");
+        } else {
+        	location = getJNLPFile();
+        }
 
-        // still null, use default
-        if (location == null) 
-            location = getDefaultFile();
-
-        if (location == null)
-            fatalError(R("BNeedsFile")+helpMessage);
-
+        if (location == null) {
+            System.out.println(helpMessage);
+            System.exit(1);
+        }
+        
         if (JNLPRuntime.isDebug())
             System.out.println(R("BFileLoc")+": "+location);
 
         URL url = null;
-        if (new File(location).exists())
-            url = new File(location).toURL(); // Why use file.getCanonicalFile?
-        else 
-            url = new URL(ServiceUtil.getBasicService().getCodeBase(), location);
 
+        try {
+        	if (new File(location).exists())
+        		url = new File(location).toURL(); // Why use file.getCanonicalFile?
+        	else 
+        		url = new URL(ServiceUtil.getBasicService().getCodeBase(), location);
+        } catch (Exception e) {
+        	fatalError("Invalid jnlp file " + location);
+        }
+        
         boolean strict = (null != getOption("-strict"));
 
         JNLPFile file = new JNLPFile(url, strict);
@@ -292,6 +319,35 @@
     }
 
     /**
+     * Gets the JNLP file from the command line arguments, or exists upon error.
+     */
+    private static String getJNLPFile() {
+
+    	if (args.length == 0) {
+            System.out.println(helpMessage);
+            System.exit(0);
+    	} else if (args.length == 1) {
+    		
+    		String lastArg = args[args.length - 1];
+    		if (lastArg.endsWith(".jnlp")) {
+    			return args[args.length - 1];
+    		} else
+    			return null;
+    	} else {
+    		String lastArg = args[args.length - 1];
+    		String secondLastArg = args[args.length - 2];
+
+    		if (doubleArgs.indexOf(secondLastArg) == -1) {
+    			return lastArg;
+    		} else {
+                System.out.println(helpMessage);
+                System.exit(0);
+    		}
+    	}
+    	return null;
+    }
+    
+    /**
      * Return value of the first occurence of the specified
      * option, or null if the option is not present.  If the
      * option is a flag (0-parameter) and is present then the
--- a/rt/net/sourceforge/jnlp/runtime/JNLPRuntime.java	Wed Mar 05 08:37:23 2008 -0500
+++ b/rt/net/sourceforge/jnlp/runtime/JNLPRuntime.java	Thu Mar 06 09:46:38 2008 -0500
@@ -442,7 +442,6 @@
             resources = ResourceBundle.getBundle("net.sourceforge.jnlp.resources.Messages");
         }
         catch (Exception ex) {
-			ex.printStackTrace();
             throw new IllegalStateException("Missing resource bundle in netx.jar:net/sourceforge/jnlp/resource/Messages.properties");
         }
     }
--- a/rt/net/sourceforge/jnlp/security/CertsInfoPane.java	Wed Mar 05 08:37:23 2008 -0500
+++ b/rt/net/sourceforge/jnlp/security/CertsInfoPane.java	Thu Mar 06 09:46:38 2008 -0500
@@ -67,14 +67,14 @@
 	
 	private ArrayList<CertPath> certs;
     private JList list;
-	private JTree tree;
+	protected JTree tree;
     private JTable table;
     private JTextArea output;
     private ListSelectionModel listSelectionModel;
     private ListSelectionModel tableSelectionModel;
-    private String[] certNames;
+    protected String[] certNames;
     private String[] columnNames = { "Field", "Value" };
-	private ArrayList<String[][]> certsData;
+	protected ArrayList<String[][]> certsData;
 
 	public CertsInfoPane(JComponent x) {
 		super(x);
@@ -83,7 +83,7 @@
 	/**
 	 * Builds the JTree out of CertPaths.
 	 */
-	private void buildTree() {
+	void buildTree() {
 		//for now, we're only going to display the first signer, even though
 		//jars can be signed by multiple people.
 		CertPath firstPath = certs.get(0);
@@ -118,59 +118,69 @@
 	}
 
 	/**
-	 * Constructs the GUI components of this UI
+	 * Fills in certsNames, certsData with data from the certificates.
 	 */
-	protected void installComponents() {
+	protected void populateTable() {
 		certs = ((SecurityWarningDialog)optionPane).getJarSigner().getCerts();
-		buildTree();
 		certNames = new String[certs.get(0).getCertificates().size()];
 		certsData = new ArrayList<String[][]>();
 
         for (int i = 0; i < certs.get(0).getCertificates().size(); i++) {
 
             X509Certificate c = (X509Certificate) certs.get(0).getCertificates().get(i);
-
-            String version = ""+c.getVersion();
-            String serialNumber = c.getSerialNumber().toString();
-            String signatureAlg = c.getSigAlgName();
-            String issuer = c.getIssuerX500Principal().toString();
-            String validity = new CertificateValidity(c.getNotBefore(),
-                                c.getNotAfter()).toString();
-            String subject = c.getSubjectX500Principal().toString();
-
-            //convert our signature into a nice human-readable form.
-            HexDumpEncoder encoder = new HexDumpEncoder();
-            String signature = encoder.encodeBuffer(c.getSignature());
-
-			String md5Hash = "";
-			String sha1Hash = "";
-			try {
-				MessageDigest digest = MessageDigest.getInstance("MD5");
-				digest.update(c.getEncoded());
-				md5Hash = makeFingerprint(digest.digest());
-
-				digest = MessageDigest.getInstance("SHA-1");
-				digest.update(c.getEncoded());
-				sha1Hash = makeFingerprint(digest.digest());
-			} catch (Exception e) {
-				//fail quietly
-			}
-
-            String[][] cert = { {"Version", version},
-                                {"Serial", serialNumber},
-                                {"Signature Algorithm", signatureAlg},
-                                {"Issuer", issuer},
-                                {"Validity", validity},
-                                {"Subject", subject},
-                                {"Signature", signature},
-								{"MD5 Fingerprint", md5Hash},
-								{"SHA1 Fingerprint", sha1Hash}
-								};
-            certsData.add(cert);
+            certsData.add(parseCert(c));
             certNames[i] = getCN(c.getSubjectX500Principal().getName())
 				+ " (" + getCN(c.getIssuerX500Principal().getName()) + ")";
         }
+	}
+	
+	protected String[][] parseCert(X509Certificate c) {
+		
+        String version = ""+c.getVersion();
+        String serialNumber = c.getSerialNumber().toString();
+        String signatureAlg = c.getSigAlgName();
+        String issuer = c.getIssuerX500Principal().toString();
+        String validity = new CertificateValidity(c.getNotBefore(),
+                            c.getNotAfter()).toString();
+        String subject = c.getSubjectX500Principal().toString();
 
+        //convert our signature into a nice human-readable form.
+        HexDumpEncoder encoder = new HexDumpEncoder();
+        String signature = encoder.encodeBuffer(c.getSignature());
+
+		String md5Hash = "";
+		String sha1Hash = "";
+		try {
+			MessageDigest digest = MessageDigest.getInstance("MD5");
+			digest.update(c.getEncoded());
+			md5Hash = makeFingerprint(digest.digest());
+
+			digest = MessageDigest.getInstance("SHA-1");
+			digest.update(c.getEncoded());
+			sha1Hash = makeFingerprint(digest.digest());
+		} catch (Exception e) {
+			//fail quietly
+		}
+
+        String[][] cert = { {"Version", version},
+                            {"Serial", serialNumber},
+                            {"Signature Algorithm", signatureAlg},
+                            {"Issuer", issuer},
+                            {"Validity", validity},
+                            {"Subject", subject},
+                            {"Signature", signature},
+							{"MD5 Fingerprint", md5Hash},
+							{"SHA1 Fingerprint", sha1Hash}
+							};
+        return cert;
+	}
+	
+	/**
+	 * Constructs the GUI components of this UI
+	 */
+	protected void installComponents() {
+		buildTree();
+		populateTable();
 		/**
 		//List of Certs
         list = new JList(certNames);
@@ -227,7 +237,7 @@
 	/**
 	 * Extracts the CN field from a Certificate principal string.
 	 */
-	private String getCN(String principal) {
+	protected String getCN(String principal) {
         int start = principal.indexOf("CN=");
         int end = principal.indexOf(",", start);
 
@@ -276,7 +286,7 @@
 	/**
 	 * Updates the JTable when the JTree selection has changed.
 	 */
-	private class TreeSelectionHandler implements TreeSelectionListener {
+	protected class TreeSelectionHandler implements TreeSelectionListener {
 		public void valueChanged(TreeSelectionEvent e) {
 			DefaultMutableTreeNode node = (DefaultMutableTreeNode)
 				tree.getLastSelectedPathComponent();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rt/net/sourceforge/jnlp/security/SecurityUtil.java	Thu Mar 06 09:46:38 2008 -0500
@@ -0,0 +1,200 @@
+/* SecurityUtil.java
+   Copyright (C) 2008 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;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.security.KeyStore;
+
+public class SecurityUtil {
+
+	private static String homeDir = null;
+	private static final String certDir = "/.netx/security/";
+	private static final String certFile = "trusted.certs";
+	private static final char[] password = "changeit".toCharArray();
+	
+	public static String getTrustedCertsFilename() throws Exception{
+		
+		homeDir = System.getProperty("user.home");
+		
+		if (homeDir == null) {
+			throw new Exception("Could not access home directory");
+		} else {
+			return homeDir + certDir + certFile;
+		}
+	}
+	
+	public static char[] getTrustedCertsPassword() {
+		return password;
+	}
+	
+	public static String getCN(String principal) {
+        int start = principal.indexOf("CN=");
+        int end = principal.indexOf(",", start);
+
+		if (end == -1) {
+			end = principal.length();
+		}
+
+        if (start >= 0)
+            return principal.substring(start+3, end);
+        else
+            return principal;
+    }
+	
+	/**
+	 * Checks the user's home directory to see if the trusted.certs file exists.
+	 * If it does not exist, it tries to create an empty keystore.
+	 * @return true if the trusted.certs file exists or a new trusted.certs
+	 * was created successfully, otherwise false.
+	 */
+	public static boolean checkTrustedCertsFile() throws Exception {
+		
+		File certFile = new File(getTrustedCertsFilename());
+		
+		//file does not exist
+		if (!certFile.isFile()) {
+			File dir = new File(homeDir+certDir);
+			boolean madeDir = false;
+			if (!dir.isDirectory()) {
+				madeDir = dir.mkdirs();
+			}
+			
+			//made directory, or directory exists
+			if (madeDir || dir.isDirectory()) {
+				KeyStore ks = KeyStore.getInstance("JKS");
+				ks.load(null, password);
+				FileOutputStream fos = new FileOutputStream(certFile);
+				ks.store(fos, password);
+				fos.close();
+				return true;
+			} else {
+				return false;
+			}
+		} else {
+			return true;
+		}
+	}
+	
+	/**
+	 * Returns the keystore associated with the user's trusted.certs file,
+	 * or null otherwise.
+	 */
+	public static KeyStore getUserKeyStore() throws Exception {
+		
+		KeyStore ks = null;
+		FileInputStream fis = null;
+		
+		if (checkTrustedCertsFile()) {
+
+			try {
+				File file = new File(getTrustedCertsFilename());
+				if (file.exists()) {
+					fis = new FileInputStream(file);
+					ks = KeyStore.getInstance("JKS");
+					ks.load(fis, password);
+				}
+			} catch (Exception e) {
+				e.printStackTrace();
+				throw e;
+			} finally {
+				if (fis != null)
+					fis.close();
+			}
+		}
+		return ks;
+	}
+	
+    /**
+     * Returns the keystore associated with the JDK cacerts file, 
+	 * or null otherwise.
+     */
+    public static KeyStore getCacertsKeyStore() throws Exception {
+
+		KeyStore caks = null;
+		FileInputStream fis = null;
+
+		try {
+        	File file = new File(System.getProperty("java.home") 
+        			+ "/lib/security/cacerts");
+        	if (file.exists()) {
+        		fis = new FileInputStream(file);
+        		caks = KeyStore.getInstance("JKS"); 
+        		caks.load(fis, null);
+        	}
+		} catch (Exception e) {
+			caks = null;
+		} finally {
+			if (fis != null)
+				fis.close();
+		}
+
+		return caks;
+    }
+    
+	/**
+	 * Returns the keystore associated with the system certs file,
+	 * or null otherwise.
+	 */
+	public static KeyStore getSystemCertStore() throws Exception {
+
+		KeyStore caks = null;
+		FileInputStream fis = null;
+
+		try {
+			File file = new File(System.getProperty("javax.net.ssl.trustStore"));
+			String type = System.getProperty("javax.net.ssl.trustStoreType");
+			//String provider = "SUN";
+			char[] password = System.getProperty(
+				"javax.net.ssl.trustStorePassword").toCharArray();
+			if (file.exists()) {
+				fis = new FileInputStream(file);
+				caks = KeyStore.getInstance(type);
+				caks.load(fis, password);
+			}
+		} catch (Exception e) {
+			caks = null;
+		} finally {
+			if (fis != null)
+				fis.close();
+		}
+		
+		return caks;
+	}
+}
--- a/rt/net/sourceforge/jnlp/security/SecurityWarningDialog.java	Wed Mar 05 08:37:23 2008 -0500
+++ b/rt/net/sourceforge/jnlp/security/SecurityWarningDialog.java	Thu Mar 06 09:46:38 2008 -0500
@@ -44,10 +44,12 @@
 import javax.swing.*;
 import java.awt.event.*;
 import javax.swing.plaf.OptionPaneUI;
+
 import java.beans.PropertyChangeListener;
 import java.beans.PropertyChangeEvent;
 import java.util.ArrayList;
 import java.security.cert.CertPath;
+import java.security.cert.X509Certificate;
 
 /**
  * Provides methods for showing security warning dialogs
@@ -62,6 +64,7 @@
 		CERT_WARNING,
 		MORE_INFO,
 		CERT_INFO,
+		SINGLE_CERT_INFO,
 		ACCESS_WARNING,
 		APPLET_WARNING
 	}
@@ -89,6 +92,8 @@
 
 	private JarSigner jarSigner;
 	
+	private X509Certificate cert;
+	
 	/** Whether or not this object has been fully initialized */
 	private boolean initialized = false;
 
@@ -112,6 +117,17 @@
 			updateUI();
 	}
 	
+	//for displaying a single certificate
+	public SecurityWarningDialog(DialogType dialogType, X509Certificate c) {
+			this.dialogType = dialogType;
+			this.accessType = null;
+			this.file = null;
+			this.jarSigner = null;
+			this.cert = c;
+			initialized = true;
+			updateUI();
+	}
+	
 	/**
 	 * Returns if this dialog has been fully initialized yet.
 	 * @return true if this dialog has been initialized, and false otherwise.
@@ -224,6 +240,24 @@
 		dialog.dispose();
 	}
 
+	/**
+	 * Displays a single certificate's information.
+	 * 
+	 * @param c
+	 * @param optionPane
+	 */
+	public static void showSingleCertInfoDialog(X509Certificate c, 
+			JOptionPane parent) {
+
+		SecurityWarningDialog swd = new SecurityWarningDialog(DialogType.SINGLE_CERT_INFO, c);
+			JDialog dialog = swd.createDialog();
+			dialog.setLocationRelativeTo(parent);
+			swd.selectInitialValue();
+			dialog.setResizable(true);
+			dialog.setVisible(true);
+			dialog.dispose();
+	}
+	
 	public static int showAppletWarning() {
         	SecurityWarningDialog swd = new SecurityWarningDialog(DialogType.APPLET_WARNING,
             		null, null, null);
@@ -320,6 +354,10 @@
 	public JarSigner getJarSigner() {
 		return jarSigner;
 	}
+	
+	public X509Certificate getCert() {
+		return cert;
+	}
 
 	/**
 	 * Updates the UI using SecurityWarningOptionPane, instead of the
@@ -333,6 +371,8 @@
 			setUI((OptionPaneUI) new MoreInfoPane(this));
 		else if (dialogType == DialogType.CERT_INFO)
 			setUI((OptionPaneUI) new CertsInfoPane(this));
+		else if (dialogType == DialogType.SINGLE_CERT_INFO)
+			setUI((OptionPaneUI) new SingleCertInfoPane(this));
 		else if (dialogType == DialogType.ACCESS_WARNING)
 			setUI((OptionPaneUI) new AccessWarningPane(this));
 		else if (dialogType == DialogType.APPLET_WARNING)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rt/net/sourceforge/jnlp/security/SingleCertInfoPane.java	Thu Mar 06 09:46:38 2008 -0500
@@ -0,0 +1,77 @@
+/* SingleCertInfoPane.java
+   Copyright (C) 2008 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;
+
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+
+import javax.swing.JComponent;
+import javax.swing.JTree;
+import javax.swing.tree.DefaultMutableTreeNode;
+import javax.swing.tree.TreeSelectionModel;
+
+public class SingleCertInfoPane extends CertsInfoPane {
+
+	public SingleCertInfoPane(JComponent x) {
+		super(x);
+	}
+	
+	protected void buildTree() {
+		X509Certificate cert = ((SecurityWarningDialog)optionPane).getCert();
+		String subjectString = 
+			getCN(cert.getSubjectX500Principal().getName());
+		String issuerString = 
+			getCN(cert.getIssuerX500Principal().getName());
+
+		DefaultMutableTreeNode top = new DefaultMutableTreeNode(subjectString 
+				+ " (" + issuerString + ")");
+		
+		tree = new JTree(top);
+		tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
+		tree.addTreeSelectionListener(new TreeSelectionHandler());
+	}
+	
+	protected void populateTable() {
+		X509Certificate c = ((SecurityWarningDialog)optionPane).getCert();
+		certNames = new String[1];
+		certsData = new ArrayList<String[][]>();
+		certsData.add(parseCert(c));
+		certNames[0] = getCN(c.getSubjectX500Principal().getName())
+		+ " (" + getCN(c.getIssuerX500Principal().getName()) + ")";
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rt/net/sourceforge/jnlp/security/viewer/CertificatePane.java	Thu Mar 06 09:46:38 2008 -0500
@@ -0,0 +1,358 @@
+/* CertificatePane.java
+   Copyright (C) 2008 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.viewer;
+
+import java.awt.BorderLayout;
+import java.awt.Dimension;
+import java.awt.FlowLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.KeyEvent;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.PrintStream;
+import java.security.KeyStore;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Enumeration;
+
+
+import javax.swing.BorderFactory;
+import javax.swing.JButton;
+import javax.swing.JComponent;
+import javax.swing.JFileChooser;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JRootPane;
+import javax.swing.JTabbedPane;
+import javax.swing.JTable;
+import javax.swing.ListSelectionModel;
+import javax.swing.SwingUtilities;
+import javax.swing.UIManager;
+import javax.swing.plaf.OptionPaneUI;
+import javax.swing.table.DefaultTableModel;
+import javax.swing.JScrollPane;
+
+import net.sourceforge.jnlp.runtime.JNLPRuntime;
+import net.sourceforge.jnlp.security.SecurityUtil;
+import net.sourceforge.jnlp.security.SecurityWarningDialog;
+import net.sourceforge.jnlp.security.SecurityDialogUI;
+import net.sourceforge.jnlp.tools.KeyTool;
+
+//import java.security.KeyStoreException;
+//import java.security.NoSuchAlgorithmException;
+//import java.security.cert.CertificateException;
+//import java.io.FileNotFoundException;
+//import java.io.IOException;
+
+
+// note: We might want to extend OptionPaneUI instead
+public class CertificatePane extends SecurityDialogUI {
+	
+	/**
+	 * The certificates stored in the user's trusted.certs file.
+	 */
+	private ArrayList<X509Certificate> certs = null;
+	
+	/**
+	 * "Issued To" and "Issued By" string pairs for certs.
+	 */
+	private String[][] issuedToAndBy = null;
+	private final String[] columnNames = { "Issued To", "Issued By" };
+	
+	private JTable table;
+	
+	/**
+	 * The KeyStore associated with the user's trusted.certs file.
+	 */
+	private KeyStore keyStore = null;
+	
+	public CertificatePane(JComponent x) {
+		super(x);
+		initializeKeyStore();
+	}
+	
+	/**
+	 * Reads the user's trusted.cacerts keystore.
+	 */
+	private void initializeKeyStore() {
+		try {
+			keyStore = SecurityUtil.getUserKeyStore();
+		} catch (Exception e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+		}
+	}
+	
+	/**
+	 * Installs the user interface for the SecurityWarningDialog.
+	 */
+	public void installUI(JComponent c) {
+
+		//Only install the UI when type and file in SecurityWarningDialog
+		//have been set.
+		if (((CertificateViewer)c).isInitialized()) {
+			setSystemLookAndFeel();
+			optionPane = (JOptionPane)c;
+			optionPane.setLayout(new BorderLayout());
+			installComponents();
+			installListeners();
+		}
+	}
+
+	private void setSystemLookAndFeel() {
+		try {
+			UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
+		} catch (Exception e) {
+			//don't worry if we can't.
+		}
+	}
+	
+	//create the GUI here.
+	protected void installComponents() {
+		readKeyStore();
+		
+		JPanel main = new JPanel(new BorderLayout());
+		
+		JPanel tablePanel = new JPanel(new BorderLayout());
+		
+		//Table
+		DefaultTableModel tableModel 
+			= new DefaultTableModel(issuedToAndBy, columnNames);
+		table = new JTable(tableModel);
+		table.getTableHeader().setReorderingAllowed(false);
+		table.setFillsViewportHeight(true);
+		JScrollPane tablePane = new JScrollPane(table);
+		tablePane.setPreferredSize(new Dimension(500,200));
+		tablePane.setSize(new Dimension(500,200));
+		tablePane.setBorder(BorderFactory.createEmptyBorder(10,10,10,10));
+		
+		JTabbedPane tabbedPane = new JTabbedPane();
+		tabbedPane.addTab("User", tablePane);
+		JPanel buttonPanel = new JPanel(new FlowLayout());
+
+		String[] buttonNames = {"Import", "Export", "Remove", "Details"};
+		char[] buttonMnemonics = {	KeyEvent.VK_I, 
+									KeyEvent.VK_E, 
+									KeyEvent.VK_M,
+									KeyEvent.VK_D};
+		ActionListener[] listeners = {	new ImportButtonListener(),
+										new ExportButtonListener(),
+										new RemoveButtonListener(),
+										new DetailsButtonListener() };
+		JButton button;
+		
+		//get the max width
+		int maxWidth = 0;
+		for (int i = 0; i < buttonNames.length; i++) {
+			button = new JButton(buttonNames[i]);
+			maxWidth = Math.max(maxWidth, button.getMinimumSize().width);
+		}
+		
+		for (int i = 0; i < buttonNames.length; i++) {
+			button = new JButton(buttonNames[i]);
+			button.setMnemonic(buttonMnemonics[i]);
+			button.addActionListener(listeners[i]);
+			button.setSize(maxWidth, button.getSize().height);
+			buttonPanel.add(button);
+		}
+		
+		tablePanel.add(tabbedPane, BorderLayout.CENTER);
+		tablePanel.add(buttonPanel, BorderLayout.SOUTH);
+		
+		JPanel closePanel = new JPanel(new BorderLayout());
+		closePanel.setBorder(BorderFactory.createEmptyBorder(7,7,7,7));
+		JButton closeButton = new JButton("Close");
+		closeButton.addActionListener(createButtonActionListener(0));
+		closePanel.add(closeButton, BorderLayout.EAST);
+		
+		main.add(tablePanel, BorderLayout.CENTER);
+		main.add(closePanel, BorderLayout.SOUTH);
+		
+		optionPane.add(main);
+
+	}	
+	
+	/**
+	 * Read in the optionPane's keystore to issuedToAndBy.
+	 */
+	private void readKeyStore() {
+		
+		Enumeration<String> aliases = null;
+		certs = new ArrayList<X509Certificate>();
+		try {
+			
+			//Get all of the X509Certificates and put them into an ArrayList
+			aliases = keyStore.aliases();
+			while (aliases.hasMoreElements()) {
+				Certificate c = keyStore.getCertificate(aliases.nextElement());
+				if (c instanceof X509Certificate)
+					certs.add((X509Certificate)c);
+			}
+
+			//get the publisher and root information
+			issuedToAndBy = new String[certs.size()][2];
+			for (int i = 0; i < certs.size(); i++) {
+	            X509Certificate c = certs.get(i);
+				issuedToAndBy[i][0] = 
+					SecurityUtil.getCN(c.getSubjectX500Principal().getName());
+				issuedToAndBy[i][1] = 
+					SecurityUtil.getCN(c.getIssuerX500Principal().getName());
+	        }
+		} catch (Exception e) {
+			//TODO
+		}
+	}
+	
+	/**
+	 * Re-reads the certs file and repopulates the JTable. This is typically
+	 * called after a certificate was deleted from the keystore.
+	 */
+	private void repopulateTable() {
+		initializeKeyStore();
+		readKeyStore();
+		DefaultTableModel tableModel 
+			= new DefaultTableModel(issuedToAndBy, columnNames);
+		
+		table.setModel(tableModel);
+		optionPane.repaint();
+	}
+	
+	private class ImportButtonListener implements ActionListener {
+        public void actionPerformed(ActionEvent e) {
+
+        	JFileChooser chooser = new JFileChooser();
+        	int returnVal = chooser.showOpenDialog(optionPane);
+        	if(returnVal == JFileChooser.APPROVE_OPTION) {
+        		try {
+        			KeyTool kt = new KeyTool();
+        			kt.importCert(chooser.getSelectedFile());
+        			repopulateTable();
+        		} catch (Exception ex) {
+        			// TODO: handle exception
+        			ex.printStackTrace();
+        		}
+        	}
+        }
+    }
+	
+	private class ExportButtonListener implements ActionListener {
+		public void actionPerformed(ActionEvent e) {
+			//For now, let's just export in -rfc mode as keytool does.
+			//we'll write to a file the exported certificate.
+
+
+			try {
+				int selectedRow = table.getSelectedRow();
+				if (selectedRow != -1) {
+		        	JFileChooser chooser = new JFileChooser();
+		        	int returnVal = chooser.showOpenDialog(optionPane);
+		        	if(returnVal == JFileChooser.APPROVE_OPTION) {
+		        		String alias = keyStore.getCertificateAlias(certs
+		        				.get(selectedRow));
+		        		if (alias != null) {
+		        			Certificate c = keyStore.getCertificate(alias);
+		        			PrintStream ps = new PrintStream(chooser.getSelectedFile().getAbsolutePath());
+		        			KeyTool.dumpCert(c, ps);
+		        			repopulateTable();
+		        		}
+		        	}
+				}
+			} catch (Exception ex) {
+				// TODO
+				ex.printStackTrace();
+			}
+		}
+	}
+	
+	private class RemoveButtonListener implements ActionListener {
+		
+		/**
+		 * Removes a certificate from the keyStore and writes changes to disk.
+		 */
+        public void actionPerformed(ActionEvent e) {
+        	
+        	try {
+        		int selectedRow = table.getSelectedRow();
+        		
+        		if (selectedRow != -1){
+        			String alias = keyStore.getCertificateAlias(certs.get(selectedRow));
+        			if (alias != null) {
+        				
+        				int i = JOptionPane.showConfirmDialog(optionPane, 
+        						"Are you sure you want to remove the selected certificate?", 
+        						"Confirmation - Remove Certificate?", 
+        						JOptionPane.YES_NO_OPTION);
+        				if (i == 0) {
+        					keyStore.deleteEntry(alias);
+        					FileOutputStream fos = new FileOutputStream(
+        						SecurityUtil.getTrustedCertsFilename());
+        					keyStore.store(fos, SecurityUtil.getTrustedCertsPassword());
+        					fos.close();
+        				}
+        			}
+        			repopulateTable();
+        		}
+        	} catch (Exception ex) {
+        		// TODO
+				ex.printStackTrace();
+        	}
+
+        }
+    }
+	
+	private class DetailsButtonListener implements ActionListener {
+		
+		/**
+		 * Shows the details of a trusted certificate.
+		 */
+        public void actionPerformed(ActionEvent e) {
+        	
+        	int selectedRow = table.getSelectedRow();
+        	if (selectedRow != -1 && selectedRow >= 0) {
+        		X509Certificate c = certs.get(selectedRow);
+        		SecurityWarningDialog.showSingleCertInfoDialog(c, optionPane);
+        	}
+        }
+    }
+	
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rt/net/sourceforge/jnlp/security/viewer/CertificateViewer.java	Thu Mar 06 09:46:38 2008 -0500
@@ -0,0 +1,148 @@
+/* CertificateViewer.java
+   Copyright (C) 2008 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.viewer;
+
+import java.awt.BorderLayout;
+import java.awt.Container;
+import java.awt.Dimension;
+import java.awt.Frame;
+import java.awt.Toolkit;
+import java.awt.event.ComponentAdapter;
+import java.awt.event.ComponentEvent;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+
+import javax.swing.JDialog;
+import javax.swing.JOptionPane;
+import javax.swing.plaf.OptionPaneUI;
+
+public class CertificateViewer extends JOptionPane {
+
+	private boolean initialized = false;
+	
+	public CertificateViewer() throws Exception {
+
+		initialized = true;
+		updateUI();
+	}
+		
+	public boolean isInitialized(){
+		return initialized;
+	}
+	
+	public void updateUI() {
+		setUI((OptionPaneUI) new CertificatePane(this));
+	}
+	
+	private static void centerDialog(JDialog dialog) {
+		Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
+		Dimension dialogSize = dialog.getSize();
+
+		dialog.setLocation((screen.width - dialogSize.width)/2,
+			(screen.height - dialogSize.height)/2);
+	}
+	
+	//Modified from javax.swing.JOptionPane
+	private JDialog createDialog() {
+		String dialogTitle = "Certificates";
+		final JDialog dialog = new JDialog((Frame)null, dialogTitle, true);
+		
+		Container contentPane = dialog.getContentPane();
+		contentPane.setLayout(new BorderLayout());
+		contentPane.add(this, BorderLayout.CENTER);
+		dialog.pack();
+
+		WindowAdapter adapter = new WindowAdapter() {
+            private boolean gotFocus = false;
+            public void windowClosing(WindowEvent we) {
+                setValue(null);
+            }
+            public void windowGainedFocus(WindowEvent we) {
+                // Once window gets focus, set initial focus
+                if (!gotFocus) {
+                    selectInitialValue();
+                    gotFocus = true;
+                }
+            }
+        };
+		dialog.addWindowListener(adapter);
+		dialog.addWindowFocusListener(adapter);
+
+		dialog.addComponentListener(new ComponentAdapter() {
+            public void componentShown(ComponentEvent ce) {
+                // reset value to ensure closing works properly
+                setValue(JOptionPane.UNINITIALIZED_VALUE);
+            }
+        });
+
+		addPropertyChangeListener( new PropertyChangeListener() {
+            public void propertyChange(PropertyChangeEvent event) {
+                // Let the defaultCloseOperation handle the closing
+                // if the user closed the window without selecting a button
+                // (newValue = null in that case).  Otherwise, close the dialog.
+                if (dialog.isVisible() && 
+                	event.getSource() == CertificateViewer.this &&
+                	(event.getPropertyName().equals(VALUE_PROPERTY) ||
+                	event.getPropertyName().equals(INPUT_VALUE_PROPERTY)) &&
+                	event.getNewValue() != null &&
+                	event.getNewValue() != JOptionPane.UNINITIALIZED_VALUE) {
+                    dialog.setVisible(false);
+                }
+            }
+        });
+
+		return dialog;
+	}
+	
+	public static void showCertificateViewer() throws Exception {
+		CertificateViewer cv = new CertificateViewer();
+		JDialog dialog = cv.createDialog();
+		cv.selectInitialValue();
+		dialog.setResizable(true);
+		centerDialog(dialog);
+		dialog.setVisible(true);
+		dialog.dispose();	
+	}
+	
+	public static void main(String[] args) throws Exception {
+		CertificateViewer.showCertificateViewer();
+	}
+}
+
--- a/rt/net/sourceforge/jnlp/tools/KeyTool.java	Wed Mar 05 08:37:23 2008 -0500
+++ b/rt/net/sourceforge/jnlp/tools/KeyTool.java	Thu Mar 06 09:46:38 2008 -0500
@@ -25,14 +25,19 @@
 
 package net.sourceforge.jnlp.tools;
 
+import java.io.BufferedInputStream;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
 import java.io.PrintStream;
 import java.security.KeyStore;
 import java.security.MessageDigest;
 import java.security.PublicKey;
 import java.security.cert.Certificate;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
 import java.security.cert.X509Certificate;
 import java.security.Principal;
 import java.util.Enumeration;
@@ -40,6 +45,11 @@
 import java.util.Hashtable;
 import java.util.Vector;
 
+import net.sourceforge.jnlp.security.SecurityUtil;
+
+import sun.misc.BASE64Encoder;
+import sun.security.provider.X509Factory;
+
 /**
  * This tool manages the user's trusted certificates
  *
@@ -54,13 +64,9 @@
 	private KeyStore cacerts = null;
 	// System ca-bundle.crt
 	private KeyStore systemcerts = null;
-	private String homeDir = null;
-	private final String certPath = "/.netx/security/";
-	private final String certFile = "trusted.certs";
-	private String fullCertPath = null;
-	//private CertificateFactory cf = null;
+	
+	private String fullCertPath = SecurityUtil.getTrustedCertsFilename();
 
-	private FileInputStream fis = null;
 	private FileOutputStream fos = null;
 
 	/**
@@ -68,6 +74,11 @@
 	 */
 	private boolean trustcacerts = true;
 	
+	/**
+	 * Whether we print certificates in rfc, base64 encoding.
+	 */
+	private boolean rfc = true;
+	
 	private final char[] password = "changeit".toCharArray();
 
 	/**
@@ -78,13 +89,36 @@
 	public KeyTool() throws Exception {
 
 		// Initialize all the keystores.
-		usercerts = getUserKeyStore();
-		cacerts = getCacertsKeyStore(); 
-		systemcerts = getSystemCertStore();
+		usercerts = SecurityUtil.getUserKeyStore();
+		cacerts = SecurityUtil.getCacertsKeyStore(); 
+		systemcerts = SecurityUtil.getSystemCertStore();
 	}
 
 	/**
-	 * Add's a trusted certificate to the user's keystore.
+	 * Adds a trusted certificate to the user's keystore.
+	 * @return true if the add was successful, false otherwise.
+	 */
+	public boolean importCert(File file) throws Exception {
+	
+		BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
+		CertificateFactory cf = CertificateFactory.getInstance("X509");
+		X509Certificate cert = null;
+		
+		if (bis.available() >= 1) {
+			try {
+			cert = (X509Certificate)cf.generateCertificate(bis);
+			} catch (ClassCastException cce) {
+				throw new Exception("Input file is not an X509 Certificate");
+			} catch (CertificateException ce) {
+				throw new Exception("Input file is not an X509 Certificate");
+			}
+		}
+	
+		return importCert((Certificate)cert);
+	}
+	
+	/**
+	 * Adds a trusted certificate to the user's keystore.
 	 * @return true if the add was successful, false otherwise.
 	 */
 	public boolean importCert(Certificate cert) throws Exception {
@@ -112,41 +146,6 @@
 	}
 	
 	/**
-	 * Checks the user's home directory to see if the trusted.certs file exists.
-	 * If it does not exist, it tries to create an empty keystore.
-	 * @return true if the trusted.certs file exists or a new trusted.certs
-	 * was created successfully, otherwise false.
-	 */
-	private boolean checkFiles() throws Exception {
-
-		File certFile = new File(fullCertPath);
-
-		if (!certFile.isFile()) { //file does not exist
-			File certDir = new File(homeDir+certPath);
-			boolean madeDir = false;
-			if (!certDir.isDirectory()) { //directory does not exist
-				madeDir = (new File(homeDir+certPath)).mkdirs();
-			}
-		
-			// If we successfully made the directory,
-            // or the directory already exists (but the file does 
-            // not), then create the keystore.
-			if (madeDir || certDir.isDirectory()) {
-				usercerts = KeyStore.getInstance("JKS");
-				usercerts.load(null, password);
-				fos = new FileOutputStream(certFile);
-				usercerts.store(fos,	password);
-				fos.close();
-				return true;
-			} else {
-				return false;
-			}
-		} else { //cert file already exists
-			return true;
-		}
-	}
-	
-	/**
      * Prints all keystore entries.
      */
 	private void doPrintEntries(PrintStream out) throws Exception {
@@ -283,81 +282,6 @@
         return cert.getSubjectDN().equals(cert.getIssuerDN());
     }
 
-	/**
-	 * Returns the keystore associated with the users
-	 * trusted.certs file, or null otherwise.
-	 */
-	private KeyStore getUserKeyStore() throws Exception {
-
-		homeDir = System.getProperty("user.home");
-		fullCertPath = homeDir + certPath + certFile;
-		KeyStore ks = KeyStore.getInstance("JKS");
-
-		if (ks != null && checkFiles()) {
-			fis = new FileInputStream(fullCertPath);
-			ks.load(fis, password);
-			if (fis != null)
-				fis.close();
-		}
-		return ks;
-	}
-
-    /**
-     * Returns the keystore associated with the JDK cacerts file, 
-	 * or null otherwise.
-     */
-    private KeyStore getCacertsKeyStore() throws Exception {
-
-		KeyStore caks = null;
-		FileInputStream fis = null;
-
-		try {
-        	String sep = File.separator;
-        	File file = new File(System.getProperty("java.home") + sep
-							+ "lib" + sep + "security" + sep
-							+ "cacerts");
-        	caks = null;
-            fis = new FileInputStream(file);
-            caks = KeyStore.getInstance("JKS");
-            caks.load(fis, null);
-		} catch (Exception e) {
-			caks = null;
-		} finally {
-			if (fis != null)
-				fis.close();
-		}
-
-		return caks;
-    }
-
-	/**
-	 * Returns the keystore associated with the system certs file,
-	 * or null otherwise.
-	 */
-	private KeyStore getSystemCertStore() throws Exception {
-
-		KeyStore caks = null;
-		FileInputStream fis = null;
-
-		try {
-			String file = System.getProperty("javax.net.ssl.trustStore");
-			String type = System.getProperty("javax.net.ssl.trustStoreType");
-			String provider = "SUN";
-			char[] password = System.getProperty(
-				"javax.net.ssl.trustStorePassword").toCharArray();
-        	caks = KeyStore.getInstance(type);
-        	fis = new FileInputStream(file);
-        	caks.load(fis, password);
-		} catch (Exception e) {
-			caks = null;
-		} finally {
-			if (fis != null)
-				fis.close();
-		}
-		
-		return caks;
-	}
-
     /**
      * Checks if a given certificate is part of the user's cacerts
      * keystore.
@@ -428,7 +352,7 @@
             keystorecerts2Hashtable(usercerts, certs);
         }
         if (trustcacerts) { //if we're trusting the cacerts
-        	KeyStore caks = getCacertsKeyStore();
+        	KeyStore caks = SecurityUtil.getCacertsKeyStore();
             if (caks!=null && caks.size()>0) {
                 if (certs == null) {
                     certs = new Hashtable<Principal, Vector<Certificate>>(11);
@@ -534,6 +458,20 @@
         return false;
     }
 
+    public static void dumpCert(Certificate cert, PrintStream out)
+    	throws IOException, CertificateException {
+    	
+    	boolean printRfc = true;
+        if (printRfc) {
+            BASE64Encoder encoder = new BASE64Encoder();
+            out.println(X509Factory.BEGIN_CERT);
+            encoder.encodeBuffer(cert.getEncoded(), out);
+            out.println(X509Factory.END_CERT);
+        } else {
+            out.write(cert.getEncoded()); // binary
+        }
+    }
+    
 	public static void main(String[] args) throws Exception {
 		KeyTool kt = new KeyTool();
 		kt.doPrintEntries(System.out);