Changeset 418 for trunk/icedtea-web/netx/net
- Timestamp:
- Feb 11, 2013, 8:53:47 PM (13 years ago)
- Location:
- trunk/icedtea-web
- Files:
-
- 2 deleted
- 54 edited
- 17 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/icedtea-web
-
Property svn:mergeinfo
set to
/branches/vendor/sourceforge/icedtea-web/1.3 merged eligible /branches/vendor/sourceforge/icedtea-web/current merged eligible
-
Property svn:mergeinfo
set to
-
trunk/icedtea-web/netx/net/sourceforge/jnlp/AppletDesc.java
r348 r418 26 26 * @version $Revision: 1.8 $ 27 27 */ 28 public class AppletDesc {28 public class AppletDesc implements LaunchDesc { 29 29 30 30 /** the applet name */ … … 74 74 75 75 /** 76 * Returns the main class name 76 * Returns the main class name in the dot-separated form (eg: foo.bar.Baz) 77 77 */ 78 @Override 78 79 public String getMainClass() { 79 80 return mainClass; -
trunk/icedtea-web/netx/net/sourceforge/jnlp/ApplicationDesc.java
r348 r418 25 25 * @version $Revision: 1.7 $ 26 26 */ 27 public class ApplicationDesc {27 public class ApplicationDesc implements LaunchDesc { 28 28 29 29 /** the main class name and package */ … … 47 47 * Returns the main class name 48 48 */ 49 @Override 49 50 public String getMainClass() { 50 51 return mainClass; -
trunk/icedtea-web/netx/net/sourceforge/jnlp/DefaultLaunchHandler.java
r348 r418 17 17 package net.sourceforge.jnlp; 18 18 19 import java.io.PrintStream; 20 19 21 import net.sourceforge.jnlp.runtime.*; 20 22 … … 27 29 * @version $Revision: 1.1 $ 28 30 */ 29 public class DefaultLaunchHandler implements LaunchHandler { 31 public class DefaultLaunchHandler extends AbstractLaunchHandler { 32 33 public DefaultLaunchHandler(PrintStream out) { 34 super(out); 35 } 30 36 31 37 /** … … 58 64 * @return true to allow the application to continue, false to stop it. 59 65 */ 60 public boolean validationError(LaunchException security) {61 printMessage( security);66 public boolean validationError(LaunchException error) { 67 printMessage(error); 62 68 return true; 63 69 } … … 72 78 public void launchCompleted(ApplicationInstance application) { 73 79 // 74 }75 76 /**77 * Print a message to stdout.78 */79 protected static void printMessage(LaunchException ex) {80 StringBuffer result = new StringBuffer();81 result.append("netx: ");82 result.append(ex.getCategory());83 if (ex.getSummary() != null) {84 result.append(": ");85 result.append(ex.getSummary());86 }87 88 if (JNLPRuntime.isDebug()) {89 if (ex.getCause() != null)90 ex.getCause().printStackTrace();91 else92 ex.printStackTrace();93 }94 95 Throwable causes[] = ex.getCauses();96 97 for (int i = 0; i < causes.length; i++) {98 result.append(" (");99 result.append(causes[i].getClass().getName());100 result.append(" ");101 result.append(causes[i].getMessage());102 result.append(")");103 }104 80 } 105 81 -
trunk/icedtea-web/netx/net/sourceforge/jnlp/GuiLaunchHandler.java
r348 r418 38 38 package net.sourceforge.jnlp; 39 39 40 import java.io.PrintStream; 41 import java.lang.reflect.InvocationTargetException; 40 42 import java.net.URL; 41 43 … … 51 53 * including splash screens and exception dialogs. 52 54 */ 53 public class GuiLaunchHandler implementsLaunchHandler {55 public class GuiLaunchHandler extends AbstractLaunchHandler { 54 56 55 57 private JNLPSplashScreen splashScreen = null; 58 private final Object mutex = new Object(); 56 59 private UpdatePolicy policy = UpdatePolicy.ALWAYS; 60 61 public GuiLaunchHandler(PrintStream outputStream) { 62 super(outputStream); 63 } 57 64 58 65 @Override … … 66 73 @Override 67 74 public void run() { 75 closeSplashScreen(); 68 76 BasicExceptionDialog.show(exception); 69 77 } 70 78 }); 79 printMessage(exception); 80 } 81 82 private void closeSplashScreen() { 83 synchronized(mutex) { 84 if (splashScreen != null) { 85 if (splashScreen.isSplashScreenValid()) { 86 splashScreen.setVisible(false); 87 } 88 splashScreen.dispose(); 89 } 90 } 71 91 } 72 92 … … 76 96 @Override 77 97 public void run() { 78 if (splashScreen != null) { 79 if (splashScreen.isSplashScreenValid()) { 80 splashScreen.setVisible(false); 81 } 82 splashScreen.dispose(); 83 } 98 closeSplashScreen(); 84 99 } 85 100 }); … … 88 103 @Override 89 104 public void launchInitialized(final JNLPFile file) { 105 106 int preferredWidth = 500; 107 int preferredHeight = 400; 108 109 final URL splashImageURL = file.getInformation().getIconLocation( 110 IconDesc.SPLASH, preferredWidth, preferredHeight); 111 112 if (splashImageURL != null) { 113 final ResourceTracker resourceTracker = new ResourceTracker(true); 114 resourceTracker.addResource(splashImageURL, file.getFileVersion(), null, policy); 115 synchronized(mutex) { 116 try { 117 SwingUtilities.invokeAndWait(new Runnable() { 118 @Override 119 public void run() { 120 splashScreen = new JNLPSplashScreen(resourceTracker, null, null); 121 } 122 }); 123 } catch (InterruptedException ie) { 124 // Wait till splash screen is created 125 while (splashScreen == null); 126 } catch (InvocationTargetException ite) { 127 ite.printStackTrace(); 128 } 129 130 splashScreen.setSplashImageURL(splashImageURL); 131 } 132 } 133 90 134 SwingUtilities.invokeLater(new Runnable() { 91 135 @Override 92 136 public void run() { 93 final int preferredWidth = 500;94 final int preferredHeight = 400;95 96 URL splashImageURL = file.getInformation().getIconLocation(97 IconDesc.SPLASH, preferredWidth, preferredHeight);98 137 if (splashImageURL != null) { 99 ResourceTracker resourceTracker = new ResourceTracker(true); 100 resourceTracker.addResource(splashImageURL, file.getFileVersion(), null, policy); 101 splashScreen = new JNLPSplashScreen(resourceTracker, null, null); 102 splashScreen.setSplashImageURL(splashImageURL); 103 if (splashScreen.isSplashScreenValid()) { 104 splashScreen.setVisible(true); 138 synchronized(mutex) { 139 if (splashScreen.isSplashScreenValid()) { 140 splashScreen.setVisible(true); 141 } 105 142 } 106 143 } … … 111 148 @Override 112 149 public boolean launchWarning(LaunchException warning) { 113 DefaultLaunchHandler.printMessage(warning);150 printMessage(warning); 114 151 return true; 115 152 } 116 153 117 154 @Override 118 public boolean validationError(LaunchException security) { 119 DefaultLaunchHandler.printMessage(security); 155 public boolean validationError(LaunchException error) { 156 closeSplashScreen(); 157 printMessage(error); 120 158 return true; 121 159 } -
trunk/icedtea-web/netx/net/sourceforge/jnlp/InstallerDesc.java
r348 r418 23 23 * @version $Revision: 1.6 $ 24 24 */ 25 public class InstallerDesc {25 public class InstallerDesc implements LaunchDesc { 26 26 27 27 /** the main class name and package. */ … … 40 40 * Returns the main class name and package. 41 41 */ 42 @Override 42 43 public String getMainClass() { 43 44 return mainClass; -
trunk/icedtea-web/netx/net/sourceforge/jnlp/JNLPFile.java
r348 r418 92 92 93 93 /** the application description */ 94 protected ObjectlaunchType;94 protected LaunchDesc launchType; 95 95 96 96 /** the component description */ … … 100 100 protected SecurityDesc security; 101 101 102 /** the default JVM locale */ 103 protected Locale defaultLocale = null; 104 102 105 /** the default OS */ 103 protected Locale defaultLocale= null;106 protected String defaultOS = null; 104 107 105 108 /** the default arch */ 106 protected String defaultOS = null;107 108 /** the default jvm */109 109 protected String defaultArch = null; 110 111 /** A signed JNLP file is missing from the main jar */ 112 private boolean missingSignedJNLP = false; 113 114 /** JNLP file contains special properties */ 115 private boolean containsSpecialProperties = false; 116 117 /** 118 * List of acceptable properties (not-special) 119 */ 120 private String[] generalProperties = SecurityDesc.getJnlpRIAPermissions(); 110 121 111 122 { // initialize defaults if security allows … … 119 130 } 120 131 132 static enum Match { LANG_COUNTRY_VARIANT, LANG_COUNTRY, LANG, GENERALIZED } 133 121 134 /** 122 135 * Empty stub, allowing child classes to override the constructor … … 175 188 */ 176 189 public JNLPFile(URL location, Version version, boolean strict, UpdatePolicy policy) throws IOException, ParseException { 190 this(location, version, strict, policy, null); 191 } 192 193 /** 194 * Create a JNLPFile from a URL and a version, checking for updates 195 * using the specified policy. 196 * 197 * @param location the location of the JNLP file 198 * @param version the version of the JNLP file 199 * @param strict whether to enforce the spec when 200 * @param policy the update policy 201 * @param forceCodebase codebase to use if not specified in JNLP file. 202 * @throws IOException if an IO exception occurred 203 * @throws ParseException if the JNLP file was invalid 204 */ 205 protected JNLPFile(URL location, Version version, boolean strict, UpdatePolicy policy, URL forceCodebase) throws IOException, ParseException { 177 206 Node root = Parser.getRootNode(openURL(location, version, policy)); 178 parse(root, strict, location );207 parse(root, strict, location, forceCodebase); 179 208 180 209 //Downloads the original jnlp file into the cache if possible … … 182 211 //originated from a website, then download the one from the website 183 212 //into the cache). 184 if (sourceLocation != null && location.getProtocol() == "file") {213 if (sourceLocation != null && "file".equals(location.getProtocol())) { 185 214 openURL(sourceLocation, version, policy); 186 215 } … … 223 252 */ 224 253 public JNLPFile(InputStream input, boolean strict) throws ParseException { 225 parse(Parser.getRootNode(input), strict, null );254 parse(Parser.getRootNode(input), strict, null, null); 226 255 } 227 256 … … 258 287 259 288 /** 260 * Returns the JNLP file's title.This method returns the same289 * Returns the JNLP file's best localized title. This method returns the same 261 290 * value as InformationDesc.getTitle(). 262 291 */ … … 266 295 267 296 /** 297 * Returns the JNLP file's best localized vendor. This method returns the same 298 * value as InformationDesc.getVendor(). 299 */ 300 public String getVendor() { 301 return getInformation().getVendor(); 302 } 303 304 /** 268 305 * Returns the JNLP file's network location as specified in the 269 306 * JNLP file. … … 323 360 public InformationDesc getInformation(final Locale locale) { 324 361 return new InformationDesc(this, new Locale[] { locale }) { 362 @Override 325 363 protected List<Object> getItems(Object key) { 326 364 List<Object> result = new ArrayList<Object>(); 327 365 328 for (int i = 0; i < info.size(); i++) { 329 InformationDesc infoDesc = info.get(i); 330 331 if (localMatches(locale, infoDesc.getLocales())) 332 result.addAll(infoDesc.getItems(key)); 366 for (Match precision : Match.values()) { 367 for (InformationDesc infoDesc : JNLPFile.this.info) { 368 if (localeMatches(locale, infoDesc.getLocales(), precision)) { 369 result.addAll(infoDesc.getItems(key)); 370 } 371 } 372 373 if (result.size() > 0) { 374 return result; 375 } 333 376 } 334 335 377 return result; 378 } 379 380 @Override 381 public String getTitle() { 382 for (Match precision : Match.values()) { 383 for (InformationDesc infoDesc : JNLPFile.this.info) { 384 String title = infoDesc.getTitle(); 385 if (localeMatches(locale, infoDesc.getLocales(), precision) 386 && title != null && !"".equals(title)) { 387 return title; 388 } 389 } 390 } 391 392 return null; 393 } 394 395 @Override 396 public String getVendor() { 397 for (Match precision : Match.values()) { 398 for (InformationDesc infoDesc : JNLPFile.this.info) { 399 String vendor = infoDesc.getVendor(); 400 if (localeMatches(locale, infoDesc.getLocales(), precision) 401 && vendor != null && !"".equals(vendor)) { 402 return vendor; 403 } 404 } 405 } 406 407 return null; 336 408 } 337 409 }; … … 367 439 public ResourcesDesc getResources(final Locale locale, final String os, final String arch) { 368 440 return new ResourcesDesc(this, new Locale[] { locale }, new String[] { os }, new String[] { arch }) { 441 442 @Override 369 443 public <T> List<T> getResources(Class<T> launchType) { 370 444 List<T> result = new ArrayList<T>(); 371 445 372 for (int i = 0; i < resources.size(); i++) { 373 ResourcesDesc rescDesc = resources.get(i); 374 375 if (localMatches(locale, rescDesc.getLocales()) 446 for (ResourcesDesc rescDesc : resources) { 447 boolean hasUsableLocale = false; 448 for (Match match : Match.values()) { 449 hasUsableLocale |= localeMatches(locale, rescDesc.getLocales(), match); 450 } 451 if (hasUsableLocale 376 452 && stringMatches(os, rescDesc.getOS()) 377 453 && stringMatches(arch, rescDesc.getArch())) … … 384 460 } 385 461 462 @Override 386 463 public void addResource(Object resource) { 387 464 // todo: honor the current locale, os, arch values … … 409 486 List<ResourcesDesc> matchingResources = new ArrayList<ResourcesDesc>(); 410 487 for (ResourcesDesc rescDesc: resources) { 411 if (localMatches(locale, rescDesc.getLocales()) 488 boolean hasUsableLocale = false; 489 for (Match match : Match.values()) { 490 hasUsableLocale |= localeMatches(locale, rescDesc.getLocales(), match); 491 } 492 if (hasUsableLocale 412 493 && stringMatches(os, rescDesc.getOS()) 413 494 && stringMatches(arch, rescDesc.getArch())) { … … 422 503 * ApplicationDesc and InstallerDesc 423 504 */ 424 public ObjectgetLaunchInfo() {505 public LaunchDesc getLaunchInfo() { 425 506 return launchType; 426 507 } … … 522 603 * @param requested the local 523 604 * @param available the available locales 605 * @param precision the depth with which to match locales. 1 checks only 606 * language, 2 checks language and country, 3 checks language, country and 607 * variant for matches. Passing 0 will always return true. 524 608 * @return true if requested matches any of available, or if 525 609 * available is empty or null. 526 610 */ 527 private boolean localMatches(Locale requested, Locale available[]) { 528 if (available == null || available.length == 0) 529 return true; 530 531 for (int i = 0; i < available.length; i++) { 532 String language = requested.getLanguage(); // "" but never null 533 String country = requested.getCountry(); 534 String variant = requested.getVariant(); 535 536 if (!"".equals(language) && !language.equalsIgnoreCase(available[i].getLanguage())) 537 continue; 538 if (!"".equals(country) && !country.equalsIgnoreCase(available[i].getCountry())) 539 continue; 540 if (!"".equals(variant) && !variant.equalsIgnoreCase(available[i].getVariant())) 541 continue; 542 543 return true; 544 } 545 611 public boolean localeMatches(Locale requested, Locale available[], Match matchLevel) { 612 613 if (matchLevel == Match.GENERALIZED) 614 return available == null || available.length == 0; 615 616 String language = requested.getLanguage(); // "" but never null 617 String country = requested.getCountry(); 618 String variant = requested.getVariant(); 619 620 for (Locale locale : available) { 621 switch (matchLevel) { 622 case LANG: 623 if (!language.isEmpty() 624 && language.equals(locale.getLanguage()) 625 && locale.getCountry().isEmpty() 626 && locale.getVariant().isEmpty()) 627 return true; 628 break; 629 case LANG_COUNTRY: 630 if (!language.isEmpty() 631 && language.equals(locale.getLanguage()) 632 && !country.isEmpty() 633 && country.equals(locale.getCountry()) 634 && locale.getVariant().isEmpty()) 635 return true; 636 break; 637 case LANG_COUNTRY_VARIANT: 638 if (language.equals(locale.getLanguage()) 639 && country.equals(locale.getCountry()) 640 && variant.equals(locale.getVariant())) 641 return true; 642 break; 643 default: 644 break; 645 } 646 } 546 647 return false; 547 648 } … … 575 676 * @param location the file location or null 576 677 */ 577 private void parse(Node root, boolean strict, URL location ) throws ParseException {678 private void parse(Node root, boolean strict, URL location, URL forceCodebase) throws ParseException { 578 679 try { 579 680 //if (location != null) 580 681 // location = new URL(location, "."); // remove filename 581 682 582 Parser parser = new Parser(this, location, root, strict, true ); // true == allow extensions683 Parser parser = new Parser(this, location, root, strict, true, forceCodebase); // true == allow extensions 583 684 584 685 // JNLP tag information … … 588 689 sourceLocation = parser.getFileLocation() != null ? parser.getFileLocation() : location; 589 690 info = parser.getInfo(root); 691 parser.checkForInformation(); 590 692 update = parser.getUpdate(root); 591 693 resources = parser.getResources(root, false); // false == not a j2se/java resources section … … 593 695 component = parser.getComponent(root); 594 696 security = parser.getSecurity(root); 697 698 checkForSpecialProperties(); 699 595 700 } catch (ParseException ex) { 596 701 throw ex; … … 600 705 601 706 throw new RuntimeException(ex.toString()); 707 } 708 } 709 710 /** 711 * Inspects the JNLP file to check if it contains any special properties 712 */ 713 private void checkForSpecialProperties() { 714 715 for (ResourcesDesc res : resources) { 716 for (PropertyDesc propertyDesc : res.getProperties()) { 717 718 for (int i = 0; i < generalProperties.length; i++) { 719 String property = propertyDesc.getKey(); 720 721 if (property.equals(generalProperties[i])) { 722 break; 723 } else if (!property.equals(generalProperties[i]) 724 && i == generalProperties.length - 1) { 725 containsSpecialProperties = true; 726 return; 727 } 728 } 729 730 } 602 731 } 603 732 } … … 675 804 } 676 805 806 /** 807 * Returns a boolean after determining if a signed JNLP warning should be 808 * displayed in the 'More Information' panel. 809 * 810 * @return true if a warning should be displayed; otherwise false 811 */ 812 public boolean requiresSignedJNLPWarning() { 813 return (missingSignedJNLP && containsSpecialProperties); 814 } 815 816 /** 817 * Informs that a signed JNLP file is missing in the main jar 818 */ 819 public void setSignedJNLPAsMissing() { 820 missingSignedJNLP = true; 821 } 677 822 } -
trunk/icedtea-web/netx/net/sourceforge/jnlp/JNLPSplashScreen.java
r348 r418 11 11 12 12 import javax.imageio.ImageIO; 13 import javax.swing.J Frame;13 import javax.swing.JDialog; 14 14 15 15 import net.sourceforge.jnlp.cache.ResourceTracker; 16 16 import net.sourceforge.jnlp.runtime.JNLPRuntime; 17 import net.sourceforge.jnlp.util.ImageResources; 17 18 18 public class JNLPSplashScreen extends J Frame{19 public class JNLPSplashScreen extends JDialog { 19 20 20 21 String applicationTitle; … … 28 29 public JNLPSplashScreen(ResourceTracker resourceTracker, 29 30 String applicationTitle, String applicationVendor) { 31 32 setIconImages(ImageResources.INSTANCE.getApplicationImages()); 30 33 31 34 // If the JNLP file does not contain any icon images, the splash image -
trunk/icedtea-web/netx/net/sourceforge/jnlp/LaunchException.java
r348 r418 17 17 package net.sourceforge.jnlp; 18 18 19 import java.io.*;20 import java.util.*;21 22 import net.sourceforge.jnlp.util.*;23 24 19 /** 25 20 * Thrown when a JNLP application, applet, or installer could not … … 31 26 public class LaunchException extends Exception { 32 27 33 /** the original exception */ 34 private Throwable cause = null; 28 private static final long serialVersionUID = 7283827853612357423L; 35 29 36 30 /** the file being launched */ … … 53 47 */ 54 48 public LaunchException(JNLPFile file, Exception cause, String severity, String category, String summary, String description) { 55 super(severity + ": " + category + ": " + summary); 49 super(severity + ": " + category + ": " + summary + " " 50 + (description == null ? "" : description), cause); 56 51 57 52 this.file = file; … … 60 55 this.description = description; 61 56 this.severity = severity; 62 63 // replace with setCause when no longer 1.3 compatible64 this.cause = cause;65 57 } 66 58 … … 69 61 */ 70 62 public LaunchException(Throwable cause) { 71 this(cause.getMessage()); 72 73 // replace with setCause when no longer 1.3 compatible 74 this.cause = cause; 63 super(cause); 75 64 } 76 65 … … 79 68 */ 80 69 public LaunchException(String message, Throwable cause) { 81 this(message + ": " + cause.getMessage()); 82 83 // replace with setCause when no longer 1.3 compatible 84 this.cause = cause; 70 super(message, cause); 85 71 } 86 72 … … 132 118 } 133 119 134 /**135 * Return the cause of the launch exception or null if there136 * is no cause exception.137 */138 public Throwable getCause() {139 return cause;140 }141 142 /**143 * Returns the causes for this exception. This method is144 * useful on JRE 1.3 since getCause is not a standard method,145 * and will be removed once netx no longer supports 1.3.146 */147 public Throwable[] getCauses() {148 ArrayList<Throwable> result = new ArrayList<Throwable>();149 150 Reflect r = new Reflect();151 Throwable cause = this.cause;152 153 while (cause != null) {154 result.add(cause);155 cause = (Throwable) r.invoke(cause, "getCause");156 }157 158 return result.toArray(new Throwable[0]);159 }160 161 /**162 * Print the stack trace and the cause exception (1.3163 * compatible)164 */165 public void printStackTrace(PrintStream stream) {166 super.printStackTrace(stream);167 168 if (cause != null) {169 stream.println("Caused by: ");170 cause.printStackTrace(stream);171 }172 }173 174 /**175 * Print the stack trace and the cause exception (1.3176 * compatible)177 */178 public void printStackTrace(PrintWriter stream) {179 super.printStackTrace(stream);180 181 if (cause != null) {182 stream.println("Caused by: ");183 cause.printStackTrace(stream);184 }185 }186 187 120 } -
trunk/icedtea-web/netx/net/sourceforge/jnlp/LaunchHandler.java
r348 r418 51 51 * @return true to allow the application to continue, false to stop it. 52 52 */ 53 public boolean validationError(LaunchException security);53 public boolean validationError(LaunchException error); 54 54 55 55 // this method will probably be replaced when real security -
trunk/icedtea-web/netx/net/sourceforge/jnlp/Launcher.java
r348 r418 26 26 import java.net.URL; 27 27 import java.net.UnknownHostException; 28 import java.util.Arrays; 28 29 import java.util.LinkedList; 29 30 import java.util.List; … … 33 34 import net.sourceforge.jnlp.cache.CacheUtil; 34 35 import net.sourceforge.jnlp.cache.UpdatePolicy; 35 import net.sourceforge.jnlp.runtime.AppThreadGroup;36 36 import net.sourceforge.jnlp.runtime.AppletInstance; 37 37 import net.sourceforge.jnlp.runtime.ApplicationInstance; … … 588 588 589 589 main.setAccessible(true); 590 591 if (JNLPRuntime.isDebug()) { 592 System.out.println("Invoking main() with args: " + Arrays.toString(args)); 593 } 590 594 main.invoke(null, new Object[] { args }); 591 595 … … 703 707 } 704 708 705 AppThreadGroup group = (AppThreadGroup) Thread.currentThread().getThreadGroup(); 706 709 ThreadGroup group = Thread.currentThread().getThreadGroup(); 710 711 // appletInstance is needed by ServiceManager when looking up 712 // services. This could potentially be done in applet constructor 713 // so initialize appletInstance before creating applet. 714 AppletInstance appletInstance; 715 if (cont == null) 716 appletInstance = new AppletInstance(file, group, loader, null); 717 else 718 appletInstance = new AppletInstance(file, group, loader, null, cont); 719 720 loader.setApplication(appletInstance); 721 722 // Initialize applet now that ServiceManager has access to its 723 // appletInstance. 707 724 String appletName = file.getApplet().getMainClass(); 708 709 //Classloader chokes if there's '/' in the path to the main class.710 //Must replace with '.' instead.711 appletName = appletName.replace('/', '.');712 725 Class appletClass = loader.loadClass(appletName); 713 726 Applet applet = (Applet) appletClass.newInstance(); 714 715 AppletInstance appletInstance; 716 if (cont == null) 717 appletInstance = new AppletInstance(file, group, loader, applet); 718 else 719 appletInstance = new AppletInstance(file, group, loader, applet, cont); 720 721 group.setApplication(appletInstance); 722 loader.setApplication(appletInstance); 723 727 // Finish setting up appletInstance. 728 appletInstance.setApplet(applet); 729 appletInstance.getAppletEnvironment().setApplet(applet); 730 724 731 setContextClassLoaderForAllThreads(appletInstance.getThreadGroup(), appletInstance.getClassLoader()); 725 732 … … 747 754 748 755 String appletName = file.getApplet().getMainClass(); 749 750 //Classloader chokes if there's '/' in the path to the main class.751 //Must replace with '.' instead.752 appletName = appletName.replace('/', '.');753 756 Class appletClass = loader.loadClass(appletName); 754 757 Applet applet = (Applet) appletClass.newInstance(); … … 766 769 try { 767 770 JNLPClassLoader loader = JNLPClassLoader.getInstance(file, updatePolicy); 768 AppThreadGroup group = (AppThreadGroup)Thread.currentThread().getThreadGroup();771 ThreadGroup group = Thread.currentThread().getThreadGroup(); 769 772 770 773 ApplicationInstance app = new ApplicationInstance(file, group, loader); 771 group.setApplication(app);772 774 loader.setApplication(app); 773 775 … … 785 787 * ThreadGroup has to be created at an earlier point in the applet code. 786 788 */ 787 protected AppThreadGroup createThreadGroup(JNLPFile file) {788 AppThreadGroup appThreadGroup= null;789 protected ThreadGroup createThreadGroup(JNLPFile file) { 790 ThreadGroup tg = null; 789 791 790 792 if (file instanceof PluginBridge) { 791 appThreadGroup = (AppThreadGroup)Thread.currentThread().getThreadGroup();793 tg = Thread.currentThread().getThreadGroup(); 792 794 } else { 793 appThreadGroup = new AppThreadGroup(mainGroup, file.getTitle());794 } 795 796 return appThreadGroup;795 tg = new ThreadGroup(mainGroup, file.getTitle()); 796 } 797 798 return tg; 797 799 } 798 800 -
trunk/icedtea-web/netx/net/sourceforge/jnlp/NetxPanel.java
r348 r418 24 24 25 25 import net.sourceforge.jnlp.AppletLog; 26 import net.sourceforge.jnlp.runtime.AppThreadGroup;27 26 import net.sourceforge.jnlp.runtime.AppletInstance; 28 27 import net.sourceforge.jnlp.runtime.JNLPRuntime; 29 28 30 29 import java.net.URL; 30 import java.util.HashMap; 31 31 import java.util.Hashtable; 32 import java.util.Map; 33 import java.util.concurrent.ConcurrentHashMap; 34 import java.util.concurrent.ConcurrentMap; 32 35 33 36 import sun.applet.AppletViewerPanel; … … 45 48 private AppletInstance appInst = null; 46 49 private boolean appletAlive; 50 private final String uKey; 51 52 // We use this so that we can create exactly one thread group 53 // for all panels with the same uKey. 54 private static final Map<String, ThreadGroup> uKeyToTG = 55 new HashMap<String, ThreadGroup>(); 56 private static final Object TGMapMutex = new Object(); 57 58 // This map is actually a set (unfortunately there is no ConcurrentSet 59 // in java.util.concurrent). If KEY is in this map, then we know that 60 // an app context has been created for the panel that has uKey.equals(KEY), 61 // so we avoid creating it a second time for panels with the same uKey. 62 // Because it's a set, only the keys matter. However, we can't insert 63 // null values in because if we did, we couldn't use null checks to see 64 // if a key was absent before a putIfAbsent. 65 private static final ConcurrentMap<String, Boolean> appContextCreated = 66 new ConcurrentHashMap<String, Boolean>(); 47 67 48 68 public NetxPanel(URL documentURL, Hashtable<String, String> atts) { 49 69 super(documentURL, atts); 70 71 /* According to http://download.oracle.com/javase/6/docs/technotes/guides/deployment/deployment-guide/applet-compatibility.html, 72 * classloaders are shared iff these properties match: 73 * codebase, cache_archive, java_archive, archive 74 * 75 * To achieve this, we create the uniquekey based on those 4 values, 76 * always in the same order. The initial "<NAME>=" parts ensure a 77 * bad tag cannot trick the loader into getting shared with another. 78 */ 79 80 // Firefox sometimes skips the codebase if it is default -- ".", 81 // so set it that way if absent 82 String codebaseAttr = atts.get("codebase") != null ? 83 atts.get("codebase") : "."; 84 85 String cache_archiveAttr = atts.get("cache_archive") != null ? 86 atts.get("cache_archive") : ""; 87 88 String java_archiveAttr = atts.get("java_archive") != null ? 89 atts.get("java_archive") : ""; 90 91 String archiveAttr = atts.get("archive") != null ? 92 atts.get("archive") : ""; 93 94 this.uKey = "codebase=" + codebaseAttr + 95 "cache_archive=" + cache_archiveAttr + 96 "java_archive=" + java_archiveAttr + 97 "archive=" + archiveAttr; 98 99 // when this was being done (incorrectly) in Launcher, the call was 100 // new AppThreadGroup(mainGroup, file.getTitle()); 101 synchronized(TGMapMutex) { 102 if (!uKeyToTG.containsKey(this.uKey)) { 103 ThreadGroup tg = new ThreadGroup(Launcher.mainGroup, this.documentURL.toString()); 104 uKeyToTG.put(this.uKey, tg); 105 } 106 } 50 107 } 51 108 … … 56 113 this.exitOnFailure = exitOnFailure; 57 114 this.appletAlive = true; 58 }59 60 @Override61 public void run() {62 /*63 * create an AppContext for this thread associated with this particular64 * plugin instance (which runs in a different thread group from the rest65 * of the plugin).66 */67 SunToolkit.createNewAppContext();68 69 super.run();70 115 } 71 116 … … 79 124 super.showAppletException(t); 80 125 } 81 126 82 127 //Overriding to use Netx classloader. You might need to relax visibility 83 128 //in sun.applet.AppletPanel for runLoader(). … … 91 136 getWidth(), 92 137 getHeight(), 93 atts );138 atts, uKey); 94 139 95 140 doInit = true; … … 155 200 } 156 201 157 // when this was being done (incorrectly) in Launcher, the call was 158 // new AppThreadGroup(mainGroup, file.getTitle()); 159 ThreadGroup tg = new AppThreadGroup(Launcher.mainGroup, 160 this.documentURL.toString()); 161 handler = new Thread(tg, this); 202 handler = new Thread(getThreadGroup(), this); 162 203 handler.start(); 163 204 } … … 175 216 return handler != null && handler.isAlive() && this.appletAlive; 176 217 } 218 219 public ThreadGroup getThreadGroup() { 220 synchronized(TGMapMutex) { 221 return uKeyToTG.get(uKey); 222 } 223 } 224 225 public void createNewAppContext() { 226 if (Thread.currentThread().getThreadGroup() != getThreadGroup()) { 227 throw new RuntimeException("createNewAppContext called from the wrong thread."); 228 } 229 // only create a new context if one hasn't already been created for the 230 // applets with this unique key. 231 if (null == appContextCreated.putIfAbsent(uKey, Boolean.TRUE)) { 232 SunToolkit.createNewAppContext(); 233 } 234 } 177 235 } -
trunk/icedtea-web/netx/net/sourceforge/jnlp/Node.java
r348 r418 20 20 private Node next; 21 21 private Node children[]; 22 private List <String> attributeNames= null; 22 23 23 24 Node(XMLElement xml) { … … 61 62 return children; 62 63 } 64 65 /** 66 * To retrieve all attribute names 67 * @return all attribute names of the Node in ArrayList<String> 68 */ 69 List<String> getAttributeNames() { 70 if (attributeNames == null) { 71 attributeNames= new ArrayList<String>(); 72 73 for (Enumeration e = xml.enumerateAttributeNames(); e.hasMoreElements();) 74 attributeNames.add(new String((String) e.nextElement())); 75 } 76 77 return attributeNames; 78 } 63 79 64 80 String getAttribute(String name) { … … 87 103 private Node next; 88 104 private Node children[]; 105 private String attributeNames[]; 89 106 90 107 Node(ParsedXML tinyNode) { … … 128 145 return children; 129 146 } 130 147 131 148 String getAttribute(String name) { 132 149 return tinyNode.getAttribute(name); -
trunk/icedtea-web/netx/net/sourceforge/jnlp/Parser.java
r348 r418 1 1 // Copyright (C) 2001-2003 Jon A. Maxwell (JAM) 2 // Copyright (C) 20 09Red Hat, Inc.2 // Copyright (C) 2012 Red Hat, Inc. 3 3 // 4 4 // This library is free software; you can redistribute it and/or … … 29 29 import net.sourceforge.jnlp.UpdateDesc.Check; 30 30 import net.sourceforge.jnlp.UpdateDesc.Policy; 31 import net.sourceforge.jnlp.runtime.JNLPRuntime; 31 32 import net.sourceforge.nanoxml.*; 32 33 … … 111 112 */ 112 113 public Parser(JNLPFile file, URL base, Node root, boolean strict, boolean allowExtensions) throws ParseException { 114 this(file, base, root, strict, allowExtensions, null); 115 } 116 117 /** 118 * Create a parser for the JNLP file. If the location 119 * parameters is not null it is used as the default codebase 120 * (does not override value of jnlp element's href 121 * attribute).<p> 122 * 123 * The root node may be normalized as a side effect of this 124 * constructor. 125 * 126 * @param file the (uninitialized) file reference 127 * @param base if codebase is not specified, a default base for relative URLs 128 * @param root the root node 129 * @param strict whether to enforce strict compliance with the JNLP spec 130 * @param allowExtensions whether to allow extensions to the JNLP spec 131 * @param codebase codebase to use if we did not parse one from JNLP file. 132 * @throws ParseException if the JNLP file is invalid 133 */ 134 public Parser(JNLPFile file, URL base, Node root, boolean strict, boolean allowExtensions, URL codebase) throws ParseException { 113 135 this.file = file; 114 136 this.root = root; … … 123 145 this.spec = getVersion(root, "spec", "1.0+"); 124 146 this.codebase = addSlash(getURL(root, "codebase", base)); 125 this.base = (codebase != null) ? codebase : base; // if codebase not specified use default codebase 147 if (this.codebase == null) // We only override it if it is not specified. 148 this.codebase = codebase; 149 this.base = (this.codebase != null) ? this.codebase : base; // if codebase not specified use default codebase 126 150 fileLocation = getURL(root, "href", this.base); 127 151 … … 403 427 404 428 /** 429 * Make sure a title and vendor are present and nonempty and localized as 430 * best matching as possible for the JVM's current locale. Fallback to a 431 * generalized title and vendor otherwise. If none is found, throw an exception. 432 * 433 * Additionally prints homepage, description, title and vendor to stdout 434 * if in Debug mode. 435 * @throws RequiredElementException 436 */ 437 void checkForInformation() throws RequiredElementException { 438 if (JNLPRuntime.isDebug()) { 439 System.out.println("Homepage: " + file.getInformation().getHomepage()); 440 System.out.println("Description: " + file.getInformation().getDescription()); 441 } 442 443 String title = file.getTitle(); 444 String vendor = file.getVendor(); 445 446 if (title == null || title.trim().isEmpty()) 447 throw new MissingTitleException(); 448 else if (JNLPRuntime.isDebug()) 449 System.out.println("Acceptable title tag found, contains: " + title); 450 451 if (vendor == null || vendor.trim().isEmpty()) 452 throw new MissingVendorException(); 453 else if (JNLPRuntime.isDebug()) 454 System.out.println("Acceptable vendor tag found, contains: " + vendor); 455 } 456 457 /** 405 458 * Returns all of the information elements under the specified 406 459 * node. … … 416 469 // ensure that there are at least one information section present 417 470 if (info.length == 0) 418 throw new ParseException(R("PNoInfoElement"));471 throw new MissingInformationException(); 419 472 420 473 // create objects from the info sections 421 for (int i = 0; i < info.length; i++) 422 result.add(getInformationDesc(info[i])); 474 for (Node infoNode : info) { 475 result.add(getInformationDesc(infoNode)); 476 } 423 477 424 478 return result; … … 582 636 * @throws ParseException if the JNLP file is invalid 583 637 */ 584 public ObjectgetLauncher(Node parent) throws ParseException {638 public LaunchDesc getLauncher(Node parent) throws ParseException { 585 639 // check for other than one application type 586 640 if (1 < getChildNodes(parent, "applet-desc").length … … 869 923 String language = localeStr.substring(0, 2); 870 924 String country = (localeStr.length() < 5) ? "" : localeStr.substring(3, 5); 871 String variant = (localeStr.length() < 7) ? "" : localeStr.substring(6, 8);925 String variant = (localeStr.length() > 7) ? localeStr.substring(6) : ""; 872 926 873 927 // null is not allowed n locale but "" is -
trunk/icedtea-web/netx/net/sourceforge/jnlp/PluginBridge.java
r348 r418 1 1 /* 2 * Copyright 20 07Red Hat, Inc.2 * Copyright 2012 Red Hat, Inc. 3 3 * This file is part of IcedTea, http://icedtea.classpath.org 4 4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. … … 23 23 package net.sourceforge.jnlp; 24 24 25 import java.io.File; 25 26 import java.net.URL; 26 27 import java.net.MalformedURLException; 27 import java.util.Hash table;28 import java.util.HashSet; 28 29 import java.util.Locale; 29 30 import java.util.List; 30 31 import java.util.ArrayList; 31 32 import java.util.Map; 33 import java.util.Set; 32 34 33 35 import net.sourceforge.jnlp.runtime.JNLPRuntime; 34 36 37 /** 38 * Allows reuse of code that expects a JNLPFile object, 39 * while overriding behaviour specific to applets. 40 */ 35 41 public class PluginBridge extends JNLPFile { 36 42 37 String name; 38 String[] jars = new String[0]; 39 String[] cacheJars = new String[0]; 40 String[] cacheExJars = new String[0]; 41 Hashtable<String, String> atts; 43 private String name; 44 private Set<String> jars = new HashSet<String>(); 45 //Folders can be added to the code-base through the archive tag 46 private List<String> codeBaseFolders = new ArrayList<String>(); 47 private String[] cacheJars = new String[0]; 48 private String[] cacheExJars = new String[0]; 49 private Map<String, String> atts; 42 50 private boolean usePack; 43 51 private boolean useVersion; 44 52 private boolean codeBaseLookup; 45 53 private boolean useJNLPHref; 54 55 /** 56 * Creates a new PluginBridge using a default JNLPCreator. 57 */ 46 58 public PluginBridge(URL codebase, URL documentBase, String jar, String main, 47 int width, int height, Hashtable<String, String> atts) 59 int width, int height, Map<String, String> atts, 60 String uKey) 61 throws Exception { 62 this(codebase, documentBase, jar, main, width, height, atts, uKey, new JNLPCreator()); 63 } 64 65 /** 66 * Handles archive tag entries, which may be folders or jar files 67 * @param archives the components of the archive tag 68 */ 69 private void addArchiveEntries(String[] archives) { 70 for (String archiveEntry : archives){ 71 // trim white spaces 72 archiveEntry = archiveEntry.trim(); 73 74 /*Only '/' on linux, '/' or '\\' on windows*/ 75 if (archiveEntry.endsWith("/") || archiveEntry.endsWith(File.pathSeparator)) { 76 this.codeBaseFolders.add(archiveEntry); 77 } else { 78 this.jars.add(archiveEntry); 79 } 80 } 81 } 82 83 public PluginBridge(URL codebase, URL documentBase, String archive, String main, 84 int width, int height, Map<String, String> atts, 85 String uKey, JNLPCreator jnlpCreator) 48 86 throws Exception { 49 87 specVersion = new Version("1.0"); … … 51 89 this.codeBase = codebase; 52 90 this.sourceLocation = documentBase; 91 this.atts = atts; 53 92 54 93 if (atts.containsKey("jnlp_href")) { 94 useJNLPHref = true; 55 95 try { 56 URL jnlp = new URL(codeBase.toExternalForm() + atts.get("jnlp_href")); 57 JNLPFile jnlpFile = new JNLPFile(jnlp); 96 // Use codeBase as the context for the URL. If jnlp_href's 97 // value is a complete URL, it will replace codeBase's context. 98 URL jnlp = new URL(codeBase, atts.get("jnlp_href")); 99 JNLPFile jnlpFile = jnlpCreator.create(jnlp, null, false, JNLPRuntime.getDefaultUpdatePolicy(), codeBase); 58 100 Map<String, String> jnlpParams = jnlpFile.getApplet().getParameters(); 101 info = jnlpFile.info; 59 102 60 103 // Change the parameter name to lowercase to follow conventions. 61 104 for (Map.Entry<String, String> entry : jnlpParams.entrySet()) { 62 atts.put(entry.getKey().toLowerCase(), entry.getValue());105 this.atts.put(entry.getKey().toLowerCase(), entry.getValue()); 63 106 } 107 JARDesc[] jarDescs = jnlpFile.getResources().getJARs(); 108 for (JARDesc jarDesc : jarDescs) { 109 String fileName = jarDesc.getLocation().toExternalForm(); 110 this.jars.add(fileName); 111 } 64 112 } catch (MalformedURLException e) { 65 113 // Don't fail because we cannot get the jnlp file. Parameters are optional not required. 66 114 // it is the site developer who should ensure that file exist. 67 System.err.println("Unable to get JNLP file at: " + codeBase.toExternalForm() 68 + atts.get("jnlp_href")); 69 } 115 System.err.println("Unable to get JNLP file at: " + atts.get("jnlp_href") 116 + " with context of URL as: " + codeBase.toExternalForm()); 117 } 118 } else { 119 // Should we populate this list with applet attribute tags? 120 info = new ArrayList<InformationDesc>(); 121 useJNLPHref = false; 70 122 } 71 123 … … 100 152 } 101 153 102 if (jar != null && jar.length() > 0) { 103 this.jars = jar.split(","); 104 105 // trim white spaces 106 for (int i = 0; i < this.jars.length; i++) { 107 this.jars[i] = this.jars[i].trim(); 108 } 154 if (archive != null && archive.length() > 0) { 155 String[] archives = archive.split(","); 156 157 addArchiveEntries(archives); 109 158 110 159 if (JNLPRuntime.isDebug()) { 111 System.err.println("Jar string: " + jar); 112 System.err.println("jars length: " + jars.length); 113 } 114 } 115 this.atts = atts; 160 System.err.println("Jar string: " + archive); 161 System.err.println("jars length: " + archives.length); 162 } 163 } 116 164 117 165 name = atts.get("name"); … … 124 172 main = main.substring(0, main.length() - 6); 125 173 126 launchType = new AppletDesc(name, main, documentBase, width, 174 // the class name should be of the form foo.bar.Baz not foo/bar/Baz 175 String mainClass = main.replace('/', '.'); 176 launchType = new AppletDesc(name, mainClass, documentBase, width, 127 177 height, atts); 128 178 … … 133 183 security = null; 134 184 135 /* According to http://download.oracle.com/javase/6/docs/technotes/guides/deployment/deployment-guide/applet-compatibility.html, 136 * classloaders are shared iff these properties match: 137 * codebase, cache_archive, java_archive, archive 138 * 139 * To achieve this, we create the uniquekey based on those 4 values, 140 * always in the same order. The initial "<NAME>=" parts ensure a 141 * bad tag cannot trick the loader into getting shared with another. 142 */ 143 144 // Firefox sometimes skips the codebase if it is default -- ".", 145 // so set it that way if absent 146 String codebaseAttr = atts.get("codebase") != null ? 147 atts.get("codebase") : "."; 148 149 String cache_archiveAttr = atts.get("cache_archive") != null ? 150 atts.get("cache_archive") : ""; 151 152 String java_archiveAttr = atts.get("java_archive") != null ? 153 atts.get("java_archive") : ""; 154 155 String archiveAttr = atts.get("archive") != null ? 156 atts.get("archive") : ""; 157 158 this.uniqueKey = "codebase=" + codebaseAttr + 159 "cache_archive=" + cache_archiveAttr + 160 "java_archive=" + java_archiveAttr + 161 "archive=" + archiveAttr; 162 185 this.uniqueKey = uKey; 163 186 usePack = false; 164 187 useVersion = false; … … 184 207 } 185 208 209 public boolean useJNLPHref() { 210 return useJNLPHref; 211 } 212 186 213 /** 187 214 * {@inheritdoc } … … 194 221 public String getTitle() { 195 222 return name; 196 }197 198 public InformationDesc getInformation(final Locale locale) {199 return new InformationDesc(this, new Locale[] { locale }) {200 protected List<Object> getItems(Object key) {201 // Should we populate this list with applet attribute tags?202 return new ArrayList<Object>();203 }204 };205 223 } 206 224 … … 218 236 jarDescs.addAll(sharedResources.getResources(JARDesc.class)); 219 237 220 for ( int i = 0; i < jars.length; i++)221 if ( jars[i].length() > 0)222 jarDescs.add(new JARDesc(new URL(codeBase, jars[i]),238 for (String name : jars) { 239 if (name.length() > 0) 240 jarDescs.add(new JARDesc(new URL(codeBase, name), 223 241 null, null, false, true, false, true)); 242 } 224 243 225 244 boolean cacheable = true; … … 229 248 cacheable = false; 230 249 231 for ( int i = 0; i < cacheJars.length; i++) {232 233 String[] jarAndVer = cacheJar s[i].split(";");250 for (String cacheJar : cacheJars) { 251 252 String[] jarAndVer = cacheJar.split(";"); 234 253 235 254 String jar = jarAndVer[0]; … … 247 266 } 248 267 249 for ( int i = 0; i < cacheExJars.length; i++) {250 251 if (cacheExJar s[i].length() == 0)268 for (String cacheExJar : cacheExJars) { 269 270 if (cacheExJar.length() == 0) 252 271 continue; 253 272 254 String[] jarInfo = cacheExJar s[i].split(";");273 String[] jarInfo = cacheExJar.split(";"); 255 274 256 275 String jar = jarInfo[0].trim(); … … 302 321 303 322 /** 323 * Returns the list of folders to be added to the codebase 324 */ 325 public List<String> getCodeBaseFolders() { 326 return new ArrayList<String>(codeBaseFolders); 327 } 328 329 /** 304 330 * Returns the resources section of the JNLP file for the 305 331 * specified locale, os, and arch. -
trunk/icedtea-web/netx/net/sourceforge/jnlp/ResourcesDesc.java
r348 r418 76 76 JARDesc jars[] = getJARs(); 77 77 78 for (int i = 0; i < jars.length; i++) 79 if (jars[i].isMain()) 80 return jars[i]; 78 for (JARDesc jar : jars) { 79 if (jar.isMain()) 80 return jar; 81 } 81 82 82 83 if (jars.length > 0) … … 161 162 Map<String, String> properties = new HashMap<String, String>(); 162 163 List<PropertyDesc> resources = getResources(PropertyDesc.class); 163 for (int i = 0; i < resources.size(); i++) { 164 PropertyDesc prop = resources.get(i); 164 for (PropertyDesc prop : resources) { 165 165 properties.put(prop.getKey(), prop.getValue()); 166 166 } … … 206 206 List<T> result = new ArrayList<T>(); 207 207 208 for (int i = 0; i < resources.size(); i++) 209 if (type.isAssignableFrom(resources.get(i).getClass())) 210 result.add(type.cast(resources.get(i))); 208 for (Object resource : resources) { 209 if (type.isAssignableFrom(resource.getClass())) 210 result.add(type.cast(resource)); 211 } 211 212 212 213 return result; -
trunk/icedtea-web/netx/net/sourceforge/jnlp/SecurityDesc.java
r348 r418 203 203 204 204 // discard sandbox, give all 205 if ( type == ALL_PERMISSIONS) {205 if (ALL_PERMISSIONS.equals(type)) { 206 206 permissions = new Permissions(); 207 207 if (customTrustedPolicy == null) { … … 214 214 215 215 // add j2ee to sandbox if needed 216 if ( type == J2EE_PERMISSIONS)216 if (J2EE_PERMISSIONS.equals(type)) 217 217 for (int i = 0; i < j2eePermissions.length; i++) 218 218 permissions.add(j2eePermissions[i]); … … 239 239 permissions.add(jnlpRIAPermissions[i]); 240 240 241 if (downloadHost != null )241 if (downloadHost != null && downloadHost.length() > 0) 242 242 permissions.add(new SocketPermission(downloadHost, 243 243 "connect, accept")); … … 245 245 return permissions; 246 246 } 247 248 /** 249 * Returns all the names of the basic JNLP system properties accessible by RIAs 250 */ 251 public static String[] getJnlpRIAPermissions() { 252 String[] jnlpPermissions = new String[jnlpRIAPermissions.length]; 253 254 for (int i = 0; i < jnlpRIAPermissions.length; i++) 255 jnlpPermissions[i] = jnlpRIAPermissions[i].getName(); 256 257 return jnlpPermissions; 258 } 247 259 248 260 } -
trunk/icedtea-web/netx/net/sourceforge/jnlp/Version.java
r348 r418 231 231 232 232 // compare as integers 233 // for normalization key, compare exact object, not using .equals 233 234 try { 234 235 if (!(part1 == emptyString)) // compare to magic normalization key … … 243 244 } 244 245 245 if (part1 == emptyString) 246 if (part1 == emptyString) // compare to magic normalization key 246 247 part1 = ""; 247 if (part2 == emptyString) 248 if (part2 == emptyString) // compare to magic normalization key 248 249 part2 = ""; 249 250 -
trunk/icedtea-web/netx/net/sourceforge/jnlp/cache/CacheLRUWrapper.java
r348 r418 37 37 package net.sourceforge.jnlp.cache; 38 38 39 import java.util.Set; 40 import static net.sourceforge.jnlp.runtime.Translator.R; 41 39 42 import java.io.File; 40 43 import java.io.IOException; … … 44 47 import java.util.Collections; 45 48 import java.util.Comparator; 49 import java.util.Iterator; 46 50 import java.util.List; 47 51 import java.util.Map.Entry; … … 68 72 69 73 /* location of cache directory */ 70 private final String cacheDir = new File(JNLPRuntime.getConfiguration()71 .getProperty(DeploymentConfiguration.KEY_USER_CACHE_DIR)).getPath();74 private final String setCachePath = JNLPRuntime.getConfiguration().getProperty(DeploymentConfiguration.KEY_USER_CACHE_DIR); 75 private final String cacheDir = new File(setCachePath != null ? setCachePath : System.getProperty("java.io.tmpdir")).getPath(); 72 76 73 77 /* … … 105 109 */ 106 110 public synchronized void load() { 107 cacheOrder.load(); 111 boolean loaded = cacheOrder.load(); 112 /* 113 * clean up possibly corrupted entries 114 */ 115 if (loaded && checkData()) { 116 if (JNLPRuntime.isDebug()) { 117 new LruCacheException().printStackTrace(); 118 } 119 System.out.println(R("CFakeCache")); 120 store(); 121 System.out.println(R("CFakedCache")); 122 } 123 } 124 125 /** 126 * check content of cacheOrder and remove invalid/corrupt entries 127 * 128 * @return true, if cache was corrupted and affected entry removed 129 */ 130 private boolean checkData () { 131 boolean modified = false; 132 Set<Entry<Object, Object>> q = cacheOrder.entrySet(); 133 for (Iterator<Entry<Object, Object>> it = q.iterator(); it.hasNext();) { 134 Entry<Object, Object> currentEntry = it.next(); 135 136 final String key = (String) currentEntry.getKey(); 137 final String path = (String) currentEntry.getValue(); 138 139 // 1. check key format: "milliseconds,number" 140 try { 141 String sa[] = key.split(","); 142 Long l1 = Long.parseLong(sa[0]); 143 Long l2 = Long.parseLong(sa[1]); 144 } catch (Exception ex) { 145 it.remove(); 146 modified = true; 147 continue; 148 } 149 150 // 2. check path format - does the path look correct? 151 if (path != null) { 152 if (path.indexOf(cacheDir) < 0) { 153 it.remove(); 154 modified = true; 155 } 156 } else { 157 it.remove(); 158 modified = true; 159 } 160 } 161 162 return modified; 108 163 } 109 164 … … 173 228 @Override 174 229 public int compare(Entry<String, String> e1, Entry<String, String> e2) { 175 try { 176 Long t1 = Long.parseLong(e1.getKey().split(",")[0]); 177 Long t2 = Long.parseLong(e2.getKey().split(",")[0]); 178 179 int c = t1.compareTo(t2); 180 return c < 0 ? 1 : (c > 0 ? -1 : 0); 181 } catch (NumberFormatException e) { 182 // Perhaps an error is too harsh. Maybe just somehow turn 183 // caching off if this is the case. 184 throw new InternalError("Corrupt LRU file entries"); 185 } 230 Long t1 = Long.parseLong(e1.getKey().split(",")[0]); 231 Long t2 = Long.parseLong(e2.getKey().split(",")[0]); 232 233 int c = t1.compareTo(t2); 234 return c < 0 ? 1 : (c > 0 ? -1 : 0); 186 235 } 187 236 }); … … 250 299 return System.currentTimeMillis() + "," + getIdForCacheFolder(path); 251 300 } 301 302 void clearLRUSortedEntries() { 303 cacheOrder.clear(); 304 } 252 305 } -
trunk/icedtea-web/netx/net/sourceforge/jnlp/cache/CacheUtil.java
r382 r418 48 48 public class CacheUtil { 49 49 50 private static final String cacheDir = new File(JNLPRuntime.getConfiguration()51 .getProperty(DeploymentConfiguration.KEY_USER_CACHE_DIR)).getPath(); // Do this with file to standardize it.50 private static final String setCacheDir = JNLPRuntime.getConfiguration().getProperty(DeploymentConfiguration.KEY_USER_CACHE_DIR); 51 private static final String cacheDir = new File(setCacheDir != null ? setCacheDir : System.getProperty("java.io.tmpdir")).getPath(); // Do this with file to standardize it. 52 52 private static final CacheLRUWrapper lruHandler = CacheLRUWrapper.getInstance(); 53 53 private static final HashMap<String, FileLock> propertiesLockPool = new HashMap<String, FileLock>(); … … 62 62 */ 63 63 public static boolean urlEquals(URL u1, URL u2) { 64 if (u1 == u2) 64 if (u1 == u2) { 65 65 return true; 66 if (u1 == null || u2 == null) 67 return false; 68 69 if (!compare(u1.getProtocol(), u2.getProtocol(), true) || 70 !compare(u1.getHost(), u2.getHost(), true) || 71 //u1.getDefaultPort() != u2.getDefaultPort() || // only in 1.4 72 !compare(u1.getPath(), u2.getPath(), false) || 73 !compare(u1.getQuery(), u2.getQuery(), false) || 74 !compare(u1.getRef(), u2.getRef(), false)) 75 return false; 76 else 66 } 67 if (u1 == null || u2 == null) { 68 return false; 69 } 70 71 if (notNullUrlEquals(u1, u2)) { 77 72 return true; 78 } 79 73 } 74 try { 75 URL nu1 = ResourceTracker.normalizeUrl(u1, false); 76 URL nu2 = ResourceTracker.normalizeUrl(u2, false); 77 if (notNullUrlEquals(nu1, nu2)) { 78 return true; 79 } 80 } catch (Exception ex) { 81 //keep silent here and return false 82 } 83 return false; 84 } 85 86 private static boolean notNullUrlEquals(URL u1, URL u2) { 87 if (!compare(u1.getProtocol(), u2.getProtocol(), true) 88 || !compare(u1.getHost(), u2.getHost(), true) 89 || //u1.getDefaultPort() != u2.getDefaultPort() || // only in 1.4 90 !compare(u1.getPath(), u2.getPath(), false) 91 || !compare(u1.getQuery(), u2.getQuery(), false) 92 || !compare(u1.getRef(), u2.getRef(), false)) { 93 return false; 94 } else { 95 return true; 96 } 97 } 80 98 /** 81 99 * Caches a resource and returns a URL for it in the cache; … … 145 163 * and we check for those by calling {@link #okToClearCache()} 146 164 */ 147 public static voidclearCache() {165 public static boolean clearCache() { 148 166 149 167 if (!okToClearCache()) { 150 168 System.err.println(R("CCannotClearCache")); 151 return ;169 return false; 152 170 } 153 171 154 172 File cacheDir = new File(CacheUtil.cacheDir); 155 173 if (!(cacheDir.isDirectory())) { 156 return ;174 return false; 157 175 } 158 176 … … 166 184 throw new RuntimeException(e); 167 185 } 186 return true; 168 187 } 169 188 … … 307 326 if (cacheFile == null) { // We did not find a copy of it. 308 327 cacheFile = makeNewCacheFile(source, version); 309 } 310 lruHandler.store();328 } else 329 lruHandler.store(); 311 330 lruHandler.unlock(); 312 331 } … … 329 348 final String path = e.getValue(); 330 349 331 if (path != null) { 332 if (pathToURLPath(path).equals(urlPath.getPath())) { // Match found. 333 cacheFile = new File(path); 334 lruHandler.updateEntry(key); 335 break; // Stop searching since we got newest one already. 336 } 350 if (pathToURLPath(path).equals(urlPath.getPath())) { // Match found. 351 cacheFile = new File(path); 352 lruHandler.updateEntry(key); 353 break; // Stop searching since we got newest one already. 337 354 } 338 355 } … … 481 498 // only resources not starting out downloaded are displayed 482 499 List<URL> urlList = new ArrayList<URL>(); 483 for ( int i = 0; i < resources.length; i++) {484 if (!tracker.checkResource( resources[i]))485 urlList.add( resources[i]);500 for (URL url : resources) { 501 if (!tracker.checkResource(url)) 502 urlList.add(url); 486 503 } 487 504 URL undownloaded[] = urlList.toArray(new URL[urlList.size()]); … … 493 510 long total = 0; 494 511 495 for ( int i = 0; i < undownloaded.length; i++) {512 for (URL url : undownloaded) { 496 513 // add in any -1's; they're insignificant 497 total += tracker.getTotalSize(u ndownloaded[i]);498 read += tracker.getAmountRead(u ndownloaded[i]);514 total += tracker.getTotalSize(url); 515 read += tracker.getAmountRead(url); 499 516 } 500 517 501 518 int percent = (int) ((100 * read) / Math.max(1, total)); 502 519 503 for ( int i = 0; i < undownloaded.length; i++)504 listener.progress(u ndownloaded[i], "version",505 tracker.getAmountRead(u ndownloaded[i]),506 tracker.getTotalSize(u ndownloaded[i]),520 for (URL url : undownloaded) { 521 listener.progress(url, "version", 522 tracker.getAmountRead(url), 523 tracker.getTotalSize(url), 507 524 percent); 525 } 508 526 } while (!tracker.waitForResources(resources, indicator.getUpdateRate())); 509 527 510 528 // make sure they read 100% until indicator closes 511 for ( int i = 0; i < undownloaded.length; i++)512 listener.progress(u ndownloaded[i], "version",513 tracker.getTotalSize(u ndownloaded[i]),514 tracker.getTotalSize(u ndownloaded[i]),529 for (URL url : undownloaded) { 530 listener.progress(url, "version", 531 tracker.getTotalSize(url), 532 tracker.getTotalSize(url), 515 533 100); 516 534 } 517 535 } catch (InterruptedException ex) { 518 536 if (JNLPRuntime.isDebug()) … … 528 546 */ 529 547 public static void cleanCache() { 548 530 549 if (okToClearCache()) { 531 550 // First we want to figure out which stuff we need to delete. … … 546 565 // Check if the item is contained in cacheOrder. 547 566 final String key = e.getKey(); 548 final String value = e.getValue(); 549 550 if (value != null) { 551 File file = new File(value); 552 PropertiesFile pf = new PropertiesFile(new File(value + ".info")); 553 boolean delete = Boolean.parseBoolean(pf.getProperty("delete")); 554 555 /* 556 * This will get me the root directory specific to this cache item. 557 * Example: 558 * cacheDir = /home/user1/.icedtea/cache 559 * file.getPath() = /home/user1/.icedtea/cache/0/http/www.example.com/subdir/a.jar 560 * rStr first becomes: /0/http/www.example.com/subdir/a.jar 561 * then rstr becomes: /home/user1/.icedtea/cache/0 562 */ 563 String rStr = file.getPath().substring(cacheDir.length()); 564 rStr = cacheDir + rStr.substring(0, rStr.indexOf(File.separatorChar, 1)); 565 long len = file.length(); 566 567 if (keep.contains(file.getPath().substring(rStr.length()))) { 568 lruHandler.removeEntry(key); 569 continue; 570 } 571 572 /* 573 * we remove entries from our lru if any of the following condition is met. 574 * Conditions: 575 * - delete: file has been marked for deletion. 576 * - !file.isFile(): if someone tampered with the directory, file doesn't exist. 577 * - maxSize >= 0 && curSize + len > maxSize: If a limit was set and the new size 578 * on disk would exceed the maximum size. 579 */ 580 if (delete || !file.isFile() || (maxSize >= 0 && curSize + len > maxSize)) { 581 lruHandler.removeEntry(key); 582 remove.add(rStr); 583 } else { 584 curSize += len; 585 keep.add(file.getPath().substring(rStr.length())); 586 587 for (File f : file.getParentFile().listFiles()) { 588 if (!(f.equals(file) || f.equals(pf.getStoreFile()))){ 589 try { 590 FileUtils.recursiveDelete(f, f); 591 } catch (IOException e1) { 592 e1.printStackTrace(); 593 } 594 } 567 final String path = e.getValue(); 568 569 File file = new File(path); 570 PropertiesFile pf = new PropertiesFile(new File(path + ".info")); 571 boolean delete = Boolean.parseBoolean(pf.getProperty("delete")); 572 573 /* 574 * This will get me the root directory specific to this cache item. 575 * Example: 576 * cacheDir = /home/user1/.icedtea/cache 577 * file.getPath() = /home/user1/.icedtea/cache/0/http/www.example.com/subdir/a.jar 578 * rStr first becomes: /0/http/www.example.com/subdir/a.jar 579 * then rstr becomes: /home/user1/.icedtea/cache/0 580 */ 581 String rStr = file.getPath().substring(cacheDir.length()); 582 rStr = cacheDir + rStr.substring(0, rStr.indexOf(File.separatorChar, 1)); 583 long len = file.length(); 584 585 if (keep.contains(file.getPath().substring(rStr.length()))) { 586 lruHandler.removeEntry(key); 587 continue; 588 } 589 590 /* 591 * we remove entries from our lru if any of the following condition is met. 592 * Conditions: 593 * - delete: file has been marked for deletion. 594 * - !file.isFile(): if someone tampered with the directory, file doesn't exist. 595 * - maxSize >= 0 && curSize + len > maxSize: If a limit was set and the new size 596 * on disk would exceed the maximum size. 597 */ 598 if (delete || !file.isFile() || (maxSize >= 0 && curSize + len > maxSize)) { 599 lruHandler.removeEntry(key); 600 remove.add(rStr); 601 continue; 602 } 603 604 curSize += len; 605 keep.add(file.getPath().substring(rStr.length())); 606 607 for (File f : file.getParentFile().listFiles()) { 608 if (!(f.equals(file) || f.equals(pf.getStoreFile()))) { 609 try { 610 FileUtils.recursiveDelete(f, f); 611 } catch (IOException e1) { 612 e1.printStackTrace(); 595 613 } 596 614 } 597 } else { 598 lruHandler.removeEntry(key); 615 599 616 } 600 617 } -
trunk/icedtea-web/netx/net/sourceforge/jnlp/cache/DefaultDownloadIndicator.java
r348 r418 29 29 30 30 import net.sourceforge.jnlp.runtime.*; 31 import net.sourceforge.jnlp.util.ImageResources; 31 32 32 33 /** … … 58 59 /** the display window */ 59 60 private static JFrame frame; 61 private static final Object frameMutex = new Object(); 60 62 61 63 /** shared constraint */ … … 98 100 DownloadPanel result = new DownloadPanel(downloadName); 99 101 100 if (frame == null) { 101 frame = new JFrame(downloading + "..."); 102 frame.getContentPane().setLayout(new GridBagLayout()); 103 } 104 105 if (resources != null) 106 for (int i = 0; i < resources.length; i++) 107 result.addProgressPanel(resources[i], null); 108 109 frame.getContentPane().add(result, vertical); 110 frame.pack(); 111 112 if (!frame.isVisible()) { 113 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); 114 Insets insets = Toolkit.getDefaultToolkit().getScreenInsets(frame.getGraphicsConfiguration()); 115 Dimension screen = new Dimension(screenSize.width - insets.left, 116 screenSize.height - insets.top); 117 frame.setLocation(screen.width - frame.getWidth(), 118 screen.height - frame.getHeight()); 119 } 120 121 frame.setVisible(true); 122 123 return result; 102 synchronized (frameMutex) { 103 if (frame == null) { 104 frame = new JFrame(downloading + "..."); 105 frame.setIconImages(ImageResources.INSTANCE.getApplicationImages()); 106 frame.getContentPane().setLayout(new GridBagLayout()); 107 } 108 109 if (resources != null) { 110 for (URL url : resources) { 111 result.addProgressPanel(url, null); 112 } 113 } 114 115 frame.getContentPane().add(result, vertical); 116 frame.pack(); 117 118 if (!frame.isVisible()) { 119 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); 120 Insets insets = Toolkit.getDefaultToolkit().getScreenInsets(frame.getGraphicsConfiguration()); 121 Dimension screen = new Dimension(screenSize.width - insets.left, 122 screenSize.height - insets.top); 123 frame.setLocation(screen.width - frame.getWidth(), 124 screen.height - frame.getHeight()); 125 } 126 127 frame.setVisible(true); 128 129 return result; 130 } 124 131 } 125 132 … … 135 142 ActionListener hider = new ActionListener() { 136 143 public void actionPerformed(ActionEvent evt) { 137 if (frame.getContentPane().getComponentCount() == 1) 138 frame.setVisible(false); 139 140 frame.getContentPane().remove((DownloadPanel) listener); 141 frame.pack(); 144 synchronized(frameMutex) { 145 frame.getContentPane().remove((DownloadPanel) listener); 146 frame.pack(); 147 148 if (frame.getContentPane().getComponentCount() == 0) { 149 frame.setVisible(false); 150 frame.dispose(); 151 frame = null; 152 } 153 } 142 154 } 143 155 }; … … 187 199 188 200 add(panel, verticalIndent); 189 frame.pack(); 201 synchronized (frameMutex) { 202 frame.pack(); 203 } 190 204 191 205 urls.add(url); -
trunk/icedtea-web/netx/net/sourceforge/jnlp/cache/Resource.java
r348 r418 273 273 } 274 274 275 for (int i = 0; i < send.size(); i++) { 276 ResourceTracker rt = send.get(i); 275 for (ResourceTracker rt : send) { 277 276 rt.fireDownloadEvent(this); 278 277 } -
trunk/icedtea-web/netx/net/sourceforge/jnlp/cache/ResourceTracker.java
r348 r418 25 25 import java.io.InputStream; 26 26 import java.io.OutputStream; 27 import java.io.UnsupportedEncodingException; 27 28 import java.net.HttpURLConnection; 28 29 import java.net.MalformedURLException; 29 30 import java.net.URL; 30 31 import java.net.URLConnection; 32 import java.net.URLDecoder; 33 import java.net.URLEncoder; 31 34 import java.security.AccessController; 32 35 import java.security.PrivilegedAction; … … 109 112 private static final int STARTED = Resource.STARTED; 110 113 114 // normalization of url 115 private static final char PATH_DELIMITER_MARK = '/'; 116 private static final String PATH_DELIMITER = "" + PATH_DELIMITER_MARK; 117 private static final char QUERY_DELIMITER_MARK = '&'; 118 private static final String QUERY_DELIMITER = "" + QUERY_DELIMITER_MARK; 119 private static final char QUERY_MARK = '?'; 120 private static final char HREF_MARK = '#'; 121 private static final String UTF8 = "utf-8"; 122 111 123 /** max threads */ 112 124 private static final int maxThreads = 5; … … 173 185 public void addResource(URL location, Version version, DownloadOptions options, UpdatePolicy updatePolicy) { 174 186 if (location == null) 175 throw new IllegalArgumentException("location==null"); 176 187 throw new IllegalResourceDescriptorException("location==null"); 188 try { 189 location = normalizeUrl(location, JNLPRuntime.isDebug()); 190 } catch (Exception ex) { 191 System.err.println("Normalization of " + location.toString() + " have failed"); 192 ex.printStackTrace(); 193 } 177 194 Resource resource = Resource.getResource(location, version, updatePolicy); 178 195 boolean downloaded = false; … … 209 226 * collected. 210 227 * 211 * @throws Illegal ArgumentException if the resource is not being tracked228 * @throws IllegalResourceDescriptorException if the resource is not being tracked 212 229 */ 213 230 public void removeResource(URL location) { … … 315 332 316 333 DownloadEvent event = new DownloadEvent(this, resource); 317 for ( int i = 0; i < l.length; i++) {334 for (DownloadListener dl : l) { 318 335 if (0 != ((ERROR | DOWNLOADED) & status)) 319 l[i].downloadCompleted(event);336 dl.downloadCompleted(event); 320 337 else if (0 != (DOWNLOADING & status)) 321 l[i].downloadStarted(event);338 dl.downloadStarted(event); 322 339 else if (0 != (CONNECTING & status)) 323 l[i].updateStarted(event);340 dl.updateStarted(event); 324 341 } 325 342 } … … 335 352 * @param location the resource location 336 353 * @return the resource, or null if it could not be downloaded 337 * @throws Illegal ArgumentException if the resource is not being tracked354 * @throws IllegalResourceDescriptorException if the resource is not being tracked 338 355 * @see CacheUtil#isCacheable 339 356 */ … … 362 379 * @param location the resource location 363 380 * @return a local file containing the resource, or null 364 * @throws Illegal ArgumentException if the resource is not being tracked381 * @throws IllegalResourceDescriptorException if the resource is not being tracked 365 382 * @see CacheUtil#isCacheable 366 383 */ … … 402 419 * 403 420 * @throws IOException if there was an error opening the stream 404 * @throws Illegal ArgumentException if the resource is not being tracked421 * @throws IllegalResourceDescriptorException if the resource is not being tracked 405 422 */ 406 423 public InputStream getInputStream(URL location) throws IOException { … … 426 443 * @param timeout the time in ms to wait before returning, 0 for no timeout 427 444 * @return whether the resources downloaded before the timeout 428 * @throws Illegal ArgumentException if the resource is not being tracked445 * @throws IllegalResourceDescriptorException if the resource is not being tracked 429 446 */ 430 447 public boolean waitForResources(URL urls[], long timeout) throws InterruptedException { … … 433 450 synchronized (resources) { 434 451 // keep the lock so getResource doesn't have to aquire it each time 435 for (int i = 0; i < urls.length; i++) 452 for (int i = 0; i < urls.length; i++) { 436 453 resources[i] = getResource(urls[i]); 454 } 437 455 } 438 456 … … 451 469 * @return whether the resource downloaded before the timeout 452 470 * @throws InterruptedException if another thread interrupted the wait 453 * @throws Illegal ArgumentException if the resource is not being tracked471 * @throws IllegalResourceDescriptorException if the resource is not being tracked 454 472 */ 455 473 public boolean waitForResource(URL location, long timeout) throws InterruptedException { … … 462 480 * @param location the resource location 463 481 * @return the number of bytes transferred 464 * @throws Illegal ArgumentException if the resource is not being tracked482 * @throws IllegalResourceDescriptorException if the resource is not being tracked 465 483 */ 466 484 public long getAmountRead(URL location) { … … 474 492 * accessed with the getCacheFile method). 475 493 * 476 * @throws Illegal ArgumentException if the resource is not being tracked494 * @throws IllegalResourceDescriptorException if the resource is not being tracked 477 495 */ 478 496 public boolean checkResource(URL location) { … … 488 506 * 489 507 * @return true if the resource is already downloaded (or an error occurred) 490 * @throws Illegal ArgumentException if the resource is not being tracked508 * @throws IllegalResourceDescriptorException if the resource is not being tracked 491 509 */ 492 510 public boolean startResource(URL location) { … … 501 519 * 502 520 * @return true if the resource is already downloaded (or an error occurred) 503 * @throws Illegal ArgumentException if the resource is not being tracked521 * @throws IllegalResourceDescriptorException if the resource is not being tracked 504 522 */ 505 523 private boolean startResource(Resource resource) { … … 533 551 * @param location the resource location 534 552 * @return the number of bytes, or -1 535 * @throws Illegal ArgumentException if the resource is not being tracked553 * @throws IllegalResourceDescriptorException if the resource is not being tracked 536 554 */ 537 555 public long getTotalSize(URL location) { … … 589 607 synchronized (lock) { 590 608 if (!resource.isSet(CONNECT | DOWNLOAD)) 591 throw new Illegal ArgumentException("Invalid resource state (resource: " + resource + ")");609 throw new IllegalResourceDescriptorException("Invalid resource state (resource: " + resource + ")"); 592 610 593 611 queue.add(resource); … … 852 870 } 853 871 URL bestUrl = null; 854 for (int i = 0; i < urls.size(); i++) { 855 URL url = urls.get(i); 872 for (URL url : urls) { 856 873 try { 857 874 URLConnection connection = url.openConnection(); … … 983 1000 int score = Integer.MAX_VALUE; 984 1001 985 for (int i = 0; i < source.size(); i++) { 986 Resource resource = source.get(i); 1002 for (Resource resource : source) { 987 1003 boolean selectable = false; 988 1004 … … 995 1011 int activeCount = 0; 996 1012 997 for ( int j = 0; j < active.size(); j++)998 if ( active.get(j)== resource.getTracker())1013 for (ResourceTracker rt : active) { 1014 if (rt == resource.getTracker()) 999 1015 activeCount++; 1016 } 1000 1017 1001 1018 // try to spread out the downloads so that a slow host … … 1014 1031 * Return the resource matching the specified URL. 1015 1032 * 1016 * @throws Illegal ArgumentException if the resource is not being tracked1033 * @throws IllegalResourceDescriptorException if the resource is not being tracked 1017 1034 */ 1018 1035 private Resource getResource(URL location) { 1019 1036 synchronized (resources) { 1020 for (int i = 0; i < resources.size(); i++) { 1021 Resource resource = resources.get(i); 1022 1037 for (Resource resource : resources) { 1023 1038 if (CacheUtil.urlEquals(resource.location, location)) 1024 1039 return resource; … … 1026 1041 } 1027 1042 1028 throw new Illegal ArgumentException("Location does not specify a resource being tracked.");1043 throw new IllegalResourceDescriptorException("Location does not specify a resource being tracked."); 1029 1044 } 1030 1045 … … 1042 1057 1043 1058 // start them downloading / connecting in background 1044 for (int i = 0; i < resources.length; i++) 1045 startResource(resources[i]); 1059 for (Resource resource : resources) { 1060 startResource(resource); 1061 } 1046 1062 1047 1063 // wait for completion … … 1051 1067 synchronized (lock) { 1052 1068 // check for completion 1053 for ( int i = 0; i < resources.length; i++) {1069 for (Resource resource : resources) { 1054 1070 //NetX Deadlocking may be solved by removing this 1055 1071 //synch block. 1056 synchronized (resource s[i]) {1057 if (!resource s[i].isSet(DOWNLOADED | ERROR)) {1072 synchronized (resource) { 1073 if (!resource.isSet(DOWNLOADED | ERROR)) { 1058 1074 finished = false; 1059 1075 break; … … 1128 1144 }; 1129 1145 1146 private static String normalizeChunk(String base, boolean debug) throws UnsupportedEncodingException { 1147 if (base == null) { 1148 return base; 1149 } 1150 if ("".equals(base)) { 1151 return base; 1152 } 1153 String result = base; 1154 String ssE = URLDecoder.decode(base, UTF8); 1155 // System.out.println("*" + base + "*"); 1156 // System.out.println("-" + ssE + "-"); 1157 if (base.equals(ssE)) { 1158 result = URLEncoder.encode(base, UTF8); 1159 if (debug) { 1160 System.out.println(base + " chunk needs to be encoded => " + result); 1161 } 1162 } else { 1163 if (debug) { 1164 System.out.println(base + " chunk already encoded"); 1165 } 1166 } 1167 return result; 1168 } 1169 1170 public static URL normalizeUrl(URL u, boolean debug) throws MalformedURLException, UnsupportedEncodingException { 1171 if (u == null) { 1172 return null; 1173 } 1174 String protocol = u.getProtocol(); 1175 if (protocol == null || "file".equals(protocol)) { 1176 return u; 1177 } 1178 String file = u.getPath(); 1179 if (file == null) { 1180 return u; 1181 } 1182 String host = u.getHost(); 1183 String ref = u.getRef(); 1184 int port = u.getPort(); 1185 String query = u.getQuery(); 1186 String[] qq = {}; 1187 if (query != null) { 1188 qq = query.split(QUERY_DELIMITER); 1189 } 1190 String[] ss = file.split(PATH_DELIMITER); 1191 int normalized = 0; 1192 if (debug) { 1193 System.out.println("normalizing path " + file + " in " + u.toString()); 1194 } 1195 for (int i = 0; i < ss.length; i++) { 1196 String base = ss[i]; 1197 String r = normalizeChunk(base, debug); 1198 if (!r.equals(ss[i])) { 1199 normalized++; 1200 } 1201 ss[i] = r; 1202 } 1203 if (debug) { 1204 System.out.println("normalizing query " + query + " in " + u.toString()); 1205 } 1206 for (int i = 0; i < qq.length; i++) { 1207 String base = qq[i]; 1208 String r = normalizeChunk(base, debug); 1209 if (!r.equals(qq[i])) { 1210 normalized++; 1211 } 1212 qq[i] = r; 1213 } 1214 if (normalized == 0) { 1215 if (debug) { 1216 System.out.println("Nothing was normalized in this url"); 1217 } 1218 return u; 1219 } else { 1220 if (debug) { 1221 System.out.println(normalized + " chunks normalized, rejoining url"); 1222 } 1223 } 1224 StringBuilder composed = new StringBuilder(""); 1225 for (int i = 0; i < ss.length; i++) { 1226 String string = ss[i]; 1227 if (ss.length <= 1 || (string != null && !"".equals(string))) { 1228 composed.append(PATH_DELIMITER_MARK).append(string); 1229 } 1230 } 1231 String composed1 = composed.toString(); 1232 if (query != null && !query.trim().equals("")) { 1233 composed.append(QUERY_MARK); 1234 for (int i = 0; i < qq.length; i++) { 1235 String string = qq[i]; 1236 if ((string != null && !"".equals(string))) { 1237 composed.append(string); 1238 if (i != qq.length - 1) { 1239 composed.append(QUERY_DELIMITER_MARK); 1240 } 1241 } 1242 } 1243 } 1244 String composed2 = composed.substring(composed1.length() - 1); 1245 if (ref != null && !ref.trim().equals("")) { 1246 composed.append(HREF_MARK).append(ref); 1247 } 1248 1249 URL result = new URL(protocol, host, port, composed.toString()); 1250 1251 if (debug) { 1252 System.out.println("normalized `" + composed1 + "` and `" + composed2 + "` in " + result.toString()); 1253 } 1254 return result; 1255 1256 } 1130 1257 } -
trunk/icedtea-web/netx/net/sourceforge/jnlp/controlpanel/AdvancedProxySettingsDialog.java
r348 r418 32 32 import net.sourceforge.jnlp.config.DeploymentConfiguration; 33 33 import net.sourceforge.jnlp.runtime.Translator; 34 import net.sourceforge.jnlp.util.ImageResources; 34 35 35 36 /** … … 55 56 public AdvancedProxySettingsDialog(DeploymentConfiguration config) { 56 57 super((Frame) null, dialogTitle, true); // Don't need a parent. 58 setIconImages(ImageResources.INSTANCE.getApplicationImages()); 59 57 60 this.config = config; 58 61 -
trunk/icedtea-web/netx/net/sourceforge/jnlp/controlpanel/CacheViewer.java
r348 r418 31 31 import net.sourceforge.jnlp.config.DeploymentConfiguration; 32 32 import net.sourceforge.jnlp.runtime.Translator; 33 import net.sourceforge.jnlp.util.ImageResources; 33 34 34 35 /** … … 52 53 public CacheViewer(DeploymentConfiguration config) { 53 54 super((Frame) null, dialogTitle, true); // Don't need a parent. 55 setIconImages(ImageResources.INSTANCE.getApplicationImages()); 54 56 this.config = config; 55 57 -
trunk/icedtea-web/netx/net/sourceforge/jnlp/controlpanel/ControlPanel.java
r348 r418 56 56 import net.sourceforge.jnlp.security.KeyStores; 57 57 import net.sourceforge.jnlp.security.viewer.CertificatePane; 58 import net.sourceforge.jnlp.util.ImageResources; 58 59 59 60 /** … … 103 104 super(); 104 105 setTitle(Translator.R("CPHead")); 106 setIconImages(ImageResources.INSTANCE.getApplicationImages()); 105 107 106 108 this.config = config; -
trunk/icedtea-web/netx/net/sourceforge/jnlp/controlpanel/TemporaryInternetFilesPanel.java
r348 r418 27 27 import java.awt.event.ItemEvent; 28 28 import java.awt.event.ItemListener; 29 import java.io.File; 29 30 30 31 import javax.swing.JButton; … … 34 35 import javax.swing.JFileChooser; 35 36 import javax.swing.JLabel; 37 import javax.swing.JOptionPane; 36 38 import javax.swing.JPanel; 37 39 import javax.swing.JSlider; … … 110 112 JFileChooser fileChooser = new JFileChooser(); 111 113 fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); 114 fileChooser.setFileHidingEnabled(false); 112 115 if (fileChooser.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) { 116 // Check if we have permission to write to that location. 113 117 String result = fileChooser.getSelectedFile().getAbsolutePath(); 114 location.setText(result); 115 config.setProperty(properties[1], result); 118 File dirLocation = new File(result); 119 boolean canWrite = dirLocation.canWrite(); 120 while (!canWrite && dirLocation != null){ // File does not exist, or no permission. 121 122 if (dirLocation.exists()) { 123 JOptionPane.showMessageDialog(null, "No permission to write to this location."); 124 return; 125 } 126 127 dirLocation = dirLocation.getParentFile(); 128 canWrite = dirLocation.canWrite(); 129 } 130 131 if (canWrite) { 132 location.setText(result); 133 config.setProperty(properties[1], result); 134 } 116 135 } 117 136 } -
trunk/icedtea-web/netx/net/sourceforge/jnlp/resources/Messages.properties
r372 r418 81 81 LSignedAppJarUsingUnsignedJar=Signed application using unsigned jars. 82 82 LSignedAppJarUsingUnsignedJarInfo=The main application jar is signed, but some of the jars it is using aren't. 83 83 LSignedJNLPFileDidNotMatch=The signed JNLP file did not match the launching JNLP file. 84 LNoSecInstance=Error: No security instance for {0}. The application may have trouble continuing 85 LCertFoundIn={0} found in cacerts ({1}) 86 84 87 JNotApplet=File is not an applet. 85 88 JNotApplication=File is not an application. … … 104 107 PTwoMains=Duplicate main JAR defined in a resources element (there can be only one) 105 108 PNativeHasMain=Cannot specify main attribute on native JARs. 106 PNoInfoElement=No information section defined 109 PNoInfoElement=No information section defined. 110 PMissingTitle=title 111 PMissingVendor=vendor 112 PMissingElement=The {0} section has not been defined for your locale nor does a default value exist in the JNLP file. 107 113 PTwoDescriptions=Duplicate description of kind {0} 108 114 PSharing=Element "sharing-allowed" is illegal in a standard JNLP file … … 120 126 PUrlNotInCodebase=Relative URL does not specify a subdirectory of the codebase. (node={0}, href={1}, base={2}) 121 127 PBadRelativeUrl=Invalid relative URL (node={0}, href={1}, base={2}) 122 PBadNonrelativeUrl=Invalid non-relative URL (node={0}, href={ 0}).128 PBadNonrelativeUrl=Invalid non-relative URL (node={0}, href={1}) 123 129 PNeedsAttribute=The {0} element must specify a {1} attribute. 124 130 PBadXML=Invalid XML document syntax. … … 190 196 CChooseCacheDir=Cache directory 191 197 CCannotClearCache=Can not clear cache at this time 198 CFakeCache=Cache is corrupt. Fixing. 199 CFakedCache=Cache is corrupt and has been fixed. It is strongly recommended that you run 'javaws -Xclearcache' and rerun your application as soon as possible. 192 200 193 201 # Security … … 199 207 SSignatureError=The application's digital signature has an error. Do you want to run the application? 200 208 SUntrustedSource=The digital signature could not be verified by a trusted source. Only run if you trust the origin of the application. 209 SWarnFullPermissionsIgnorePolicy=The code executed will be given full permissions, ignoring any java policies you may have. 201 210 STrustedSource=The digital signature has been validated by a trusted source. 202 211 SClipboardReadAccess=The application has requested read-only access to the system clipboard. Do you want to allow this action? … … 205 214 SNetworkAccess=The application has requested permission to establish connections to {0}. Do you want to allow this action? 206 215 SNoAssociatedCertificate=<no associated certificate> 216 SUnverified=(unverified) 207 217 SAlwaysTrustPublisher=Always trust content from this publisher 208 SHttpsUnverified=The website's certificate cannot be verified.218 SHttpsUnverified=The website's HTTPS certificate cannot be verified. 209 219 SNotAllSignedSummary=Only parts of this application code are signed. 210 220 SNotAllSignedDetail=This application contains both signed and unsigned code. While signed code is safe if you trust the provider, unsigned code may imply code outside of the trusted provider's control. 211 221 SNotAllSignedQuestion=Do you wish to proceed and run this application anyway? 212 222 SAuthenticationPrompt=The {0} server at {1} is requesting authentication. It says "{2}" 223 SJNLPFileIsNotSigned=This application contains a digital signature in which the launching JNLP file is not signed. 213 224 214 225 # Security - used for the More Information dialog … … 241 252 CVDetails=Details 242 253 CVExport=Export 254 CVExportPasswordMessage=Enter password to protect key file: 243 255 CVImport=Import 256 CVImportPasswordMessage=Enter password to access file: 244 257 CVIssuedBy=Issued By 245 258 CVIssuedTo=Issued To 259 CVPasswordTitle=Authentication Required 246 260 CVRemove=Remove 247 261 CVRemoveConfirmMessage=Are you sure you want to remove the selected certificate? -
trunk/icedtea-web/netx/net/sourceforge/jnlp/runtime/AppletEnvironment.java
r348 r418 117 117 118 118 List<AppletAudioClip> clips = weakClips.hardList(); 119 for ( int i = 0; i < clips.size(); i++) {120 clip s.get(i).dispose();119 for (AppletAudioClip clip : clips) { 120 clip.dispose(); 121 121 } 122 122 } … … 208 208 209 209 /** 210 * Set the applet of this environment; can only be called once. 211 */ 212 public void setApplet(Applet applet) { 213 if (this.applet != null) { 214 if (JNLPRuntime.isDebug()) { 215 Exception ex = new IllegalStateException("Applet can only be set once."); 216 ex.printStackTrace(); 217 } 218 return; 219 } 220 this.applet = applet; 221 } 222 223 /** 210 224 * Returns an enumeration that contains only the applet 211 225 * from the JNLP file. -
trunk/icedtea-web/netx/net/sourceforge/jnlp/runtime/AppletInstance.java
r348 r418 50 50 51 51 this.environment = new AppletEnvironment(file, this); 52 } 53 54 /** 55 * Set the applet of this launched application; can only be called once. 56 */ 57 public void setApplet(Applet applet) { 58 if (this.applet != null) { 59 if (JNLPRuntime.isDebug()) { 60 Exception ex = new IllegalStateException("Applet can only be set once."); 61 ex.printStackTrace(); 62 } 63 return; 64 } 65 this.applet = applet; 52 66 } 53 67 -
trunk/icedtea-web/netx/net/sourceforge/jnlp/runtime/ApplicationInstance.java
r348 r418 232 232 PrivilegedAction<Object> installProps = new PrivilegedAction<Object>() { 233 233 public Object run() { 234 for ( int i = 0; i < props.length; i++) {235 System.setProperty(prop s[i].getKey(), props[i].getValue());234 for (PropertyDesc propDesc : props) { 235 System.setProperty(propDesc.getKey(), propDesc.getValue()); 236 236 } 237 237 … … 273 273 try { 274 274 // destroy resources 275 for (int i = 0; i < weakWindows.size(); i++) { 276 Window w = weakWindows.get(i); 275 for (Window w : weakWindows) { 277 276 if (w != null) 278 277 w.dispose(); -
trunk/icedtea-web/netx/net/sourceforge/jnlp/runtime/Boot.java
r348 r418 157 157 JNLPRuntime.setForksAllowed(false); 158 158 } 159 if (null != getOption("-Xtrustall")) { 160 JNLPRuntime.setTrustAll(true); 161 } 159 162 160 163 JNLPRuntime.setInitialArgments(Arrays.asList(argsIn)); -
trunk/icedtea-web/netx/net/sourceforge/jnlp/runtime/CachedJarFileCallback.java
r348 r418 95 95 if (UrlUtils.isLocalFile(localUrl)) { 96 96 // if it is known to us, just return the cached file 97 return new JarFile(localUrl.getPath()); 97 JarFile returnFile = new JarFile(localUrl.getPath()); 98 99 try { 100 101 // Blank out the class-path because: 102 // 1) Web Start does not support it 103 // 2) For the plug-in, we want to cache files from class-path so we do it manually 104 returnFile.getManifest().getMainAttributes().putValue("Class-Path", ""); 105 106 if (JNLPRuntime.isDebug()) { 107 System.err.println("Class-Path attribute cleared for " + returnFile.getName()); 108 } 109 110 } catch (NullPointerException npe) { 111 // Discard NPE here. Maybe there was no manifest, maybe there were no attributes, etc. 112 } 113 114 return returnFile; 98 115 } else { 99 116 // throw new IllegalStateException("a non-local file in cache"); -
trunk/icedtea-web/netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java
r348 r418 18 18 import static net.sourceforge.jnlp.runtime.Translator.R; 19 19 20 import java.io.Closeable; 20 21 import java.io.File; 21 22 import java.io.FileOutputStream; 23 import java.io.FileReader; 22 24 import java.io.IOException; 23 25 import java.io.InputStream; 26 import java.io.InputStreamReader; 24 27 import java.net.MalformedURLException; 28 import java.net.SocketPermission; 25 29 import java.net.URL; 26 30 import java.net.URLClassLoader; 27 31 import java.security.AccessControlContext; 32 import java.security.AccessControlException; 28 33 import java.security.AccessController; 29 34 import java.security.AllPermission; … … 33 38 import java.security.Permissions; 34 39 import java.security.PrivilegedAction; 40 import java.security.PrivilegedActionException; 41 import java.security.PrivilegedExceptionAction; 42 import java.security.ProtectionDomain; 35 43 import java.util.ArrayList; 44 import java.util.Arrays; 45 import java.util.Collection; 36 46 import java.util.Collections; 37 47 import java.util.Enumeration; 38 48 import java.util.HashMap; 39 49 import java.util.HashSet; 50 import java.util.Iterator; 40 51 import java.util.LinkedList; 41 52 import java.util.List; … … 44 55 import java.util.TreeSet; 45 56 import java.util.Vector; 57 import java.util.concurrent.ConcurrentHashMap; 46 58 import java.util.jar.JarEntry; 47 59 import java.util.jar.JarFile; 48 60 import java.util.jar.Manifest; 49 61 62 import net.sourceforge.jnlp.AppletDesc; 63 import net.sourceforge.jnlp.ApplicationDesc; 50 64 import net.sourceforge.jnlp.DownloadOptions; 51 65 import net.sourceforge.jnlp.ExtensionDesc; 52 66 import net.sourceforge.jnlp.JARDesc; 53 67 import net.sourceforge.jnlp.JNLPFile; 68 import net.sourceforge.jnlp.JNLPMatcher; 69 import net.sourceforge.jnlp.JNLPMatcherException; 70 import net.sourceforge.jnlp.LaunchDesc; 54 71 import net.sourceforge.jnlp.LaunchException; 55 72 import net.sourceforge.jnlp.ParseException; … … 59 76 import net.sourceforge.jnlp.Version; 60 77 import net.sourceforge.jnlp.cache.CacheUtil; 78 import net.sourceforge.jnlp.cache.IllegalResourceDescriptorException; 61 79 import net.sourceforge.jnlp.cache.ResourceTracker; 62 80 import net.sourceforge.jnlp.cache.UpdatePolicy; 63 81 import net.sourceforge.jnlp.security.SecurityDialogs; 64 82 import net.sourceforge.jnlp.security.SecurityDialogs.AccessType; 65 import net.sourceforge.jnlp.tools.Jar Signer;83 import net.sourceforge.jnlp.tools.JarCertVerifier; 66 84 import net.sourceforge.jnlp.util.FileUtils; 67 85 import sun.misc.JarIndex; … … 82 100 // resources in an extension. 83 101 102 /** Signed JNLP File and Template */ 103 final public static String TEMPLATE = "JNLP-INF/APPLICATION_TEMPLATE.JNLP"; 104 final public static String APPLICATION = "JNLP-INF/APPLICATION.JNLP"; 105 106 /** True if the application has a signed JNLP File */ 107 private boolean isSignedJNLP = false; 108 84 109 /** map from JNLPFile url to shared classloader */ 85 110 private static Map<String, JNLPClassLoader> urlToLoader = … … 134 159 private ArrayList<String> unverifiedJars = null; 135 160 136 /** the jar signer tool to verify our jars */137 private Jar Signer js= null;161 /** the jar cert verifier tool to verify our jars */ 162 private JarCertVerifier jcv = null; 138 163 139 164 private boolean signing = false; … … 151 176 private HashMap<URL, SecurityDesc> jarLocationSecurityMap = 152 177 new HashMap<URL, SecurityDesc>(); 178 179 /*Set to prevent once tried-to-get resources to be tried again*/ 180 private Set<URL> alreadyTried = Collections.synchronizedSet(new HashSet<URL>()); 153 181 154 182 /** Loader for codebase (which is a path, rather than a file) */ 155 183 private CodeBaseClassLoader codeBaseLoader; 184 185 /** True if the jar with the main class has been found 186 * */ 187 private boolean foundMainJar= false; 188 189 /** Name of the application's main class */ 190 private String mainClass = null; 191 192 /** 193 * Variable to track how many times this loader is in use 194 */ 195 private int useCount = 0; 156 196 157 197 /** … … 161 201 */ 162 202 protected JNLPClassLoader(JNLPFile file, UpdatePolicy policy) throws LaunchException { 203 this(file,policy,null); 204 } 205 206 /** 207 * Create a new JNLPClassLoader from the specified file. 208 * 209 * @param file the JNLP file 210 * @param name of the application's main class 211 */ 212 protected JNLPClassLoader(JNLPFile file, UpdatePolicy policy, String mainName) throws LaunchException { 163 213 super(new URL[0], JNLPClassLoader.class.getClassLoader()); 164 214 … … 169 219 this.updatePolicy = policy; 170 220 this.resources = file.getResources(); 221 222 this.mainClass = mainName; 171 223 172 224 // initialize extensions … … 276 328 */ 277 329 public static JNLPClassLoader getInstance(JNLPFile file, UpdatePolicy policy) throws LaunchException { 330 return getInstance(file, policy, null); 331 } 332 333 /** 334 * Returns a JNLP classloader for the specified JNLP file. 335 * 336 * @param file the file to load classes for 337 * @param policy the update policy to use when downloading resources 338 * @param mainName Overrides the main class name of the application 339 */ 340 public static JNLPClassLoader getInstance(JNLPFile file, UpdatePolicy policy, String mainName) throws LaunchException { 278 341 JNLPClassLoader baseLoader = null; 279 342 JNLPClassLoader loader = null; … … 292 355 !baseLoader.getJNLPFile().getFileLocation().equals(file.getFileLocation()))) { 293 356 294 loader = new JNLPClassLoader(file, policy );357 loader = new JNLPClassLoader(file, policy, mainName); 295 358 296 359 // New loader init may have caused extentions to create a … … 304 367 305 368 loader.merge(extLoader); 369 extLoader.decrementLoaderUseCount(); // loader urls have been merged, ext loader is no longer used 306 370 } 307 371 … … 309 373 // the baseLoader 310 374 if (baseLoader != null && baseLoader != loader) { 311 375 loader.merge(baseLoader); 312 376 } 313 377 … … 316 380 if (!file.isApplication()) { 317 381 // If this is an applet, we do need to consider its loader 318 loader = new JNLPClassLoader(file, policy);382 loader = new JNLPClassLoader(file, policy, mainName); 319 383 320 384 if (baseLoader != null) … … 330 394 // loaders are mapped to a unique key. Only extensions and parent 331 395 // share a key, so it is safe to always share based on it 332 urlToLoader.put(uniqueKey, loader); 396 397 loader.incrementLoaderUseCount(); 398 synchronized(urlToLoader) { 399 urlToLoader.put(uniqueKey, loader); 400 } 333 401 334 402 return loader; … … 342 410 * @param version the file's version 343 411 * @param policy the update policy to use when downloading resources 344 */ 345 public static JNLPClassLoader getInstance(URL location, String uniqueKey, Version version, UpdatePolicy policy) 412 * @param mainName Overrides the main class name of the application 413 */ 414 public static JNLPClassLoader getInstance(URL location, String uniqueKey, Version version, UpdatePolicy policy, String mainName) 346 415 throws IOException, ParseException, LaunchException { 347 416 JNLPClassLoader loader = urlToLoader.get(uniqueKey); 348 417 349 if (loader == null || !location.equals(loader.getJNLPFile().getFileLocation())) 350 loader = getInstance(new JNLPFile(location, uniqueKey, version, false, policy), policy); 418 if (loader == null || !location.equals(loader.getJNLPFile().getFileLocation())) { 419 JNLPFile jnlpFile = new JNLPFile(location, uniqueKey, version, false, policy); 420 421 loader = getInstance(jnlpFile, policy, mainName); 422 } 351 423 352 424 return loader; … … 362 434 363 435 loaderList.add(this); 436 437 if (mainClass == null) { 438 Object obj = file.getLaunchInfo(); 439 440 if (obj instanceof ApplicationDesc) { 441 ApplicationDesc ad = (ApplicationDesc) file.getLaunchInfo(); 442 mainClass = ad.getMainClass(); 443 } else if (obj instanceof AppletDesc) { 444 AppletDesc ad = (AppletDesc) file.getLaunchInfo(); 445 mainClass = ad.getMainClass(); 446 } 447 } 364 448 365 449 //if (ext != null) { … … 367 451 try { 368 452 String uniqueKey = this.getJNLPFile().getUniqueKey(); 369 JNLPClassLoader loader = getInstance(ext[i].getLocation(), uniqueKey, ext[i].getVersion(), updatePolicy );453 JNLPClassLoader loader = getInstance(ext[i].getLocation(), uniqueKey, ext[i].getVersion(), updatePolicy, mainClass); 370 454 loaderList.add(loader); 371 455 } catch (Exception ex) { … … 401 485 402 486 /** 487 * Check if a described jar file is invalid 488 * @param jar the jar to check 489 * @return true if file exists AND is an invalid jar, false otherwise 490 */ 491 private boolean isInvalidJar(JARDesc jar){ 492 File cacheFile = tracker.getCacheFile(jar.getLocation()); 493 if (cacheFile == null) 494 return false;//File cannot be retrieved, do not claim it is an invalid jar 495 boolean isInvalid = false; 496 try { 497 JarFile jarFile = new JarFile(cacheFile.getAbsolutePath()); 498 jarFile.close(); 499 } catch (IOException ioe){ 500 //Catch a ZipException or any other read failure 501 isInvalid = true; 502 } 503 return isInvalid; 504 } 505 506 /** 507 * Determine how invalid jars should be handled 508 * @return whether to filter invalid jars, or error later on 509 */ 510 private boolean shouldFilterInvalidJars(){ 511 if (file instanceof PluginBridge){ 512 PluginBridge pluginBridge = (PluginBridge)file; 513 /*Ignore on applet, ie !useJNLPHref*/ 514 return !pluginBridge.useJNLPHref(); 515 } 516 return false;//Error is default behaviour 517 } 518 519 /** 403 520 * Load all of the JARs used in this JNLP file into the 404 521 * ResourceTracker for downloading. 405 522 */ 406 523 void initializeResources() throws LaunchException { 524 if (file instanceof PluginBridge){ 525 PluginBridge bridge = (PluginBridge)file; 526 527 for (String codeBaseFolder : bridge.getCodeBaseFolders()){ 528 try { 529 addToCodeBaseLoader(new URL(file.getCodeBase(), codeBaseFolder)); 530 } catch (MalformedURLException mfe) { 531 System.err.println("Problem trying to add folder to code base:"); 532 System.err.println(mfe.getMessage()); 533 } 534 } 535 } 536 407 537 JARDesc jars[] = resources.getJARs(); 408 if (jars == null || jars.length == 0) 538 539 if (jars == null || jars.length == 0) { 540 541 boolean allSigned = true; 542 for (int i = 1; i < loaders.length; i++) { 543 if (!loaders[i].getSigning()) { 544 allSigned = false; 545 break; 546 } 547 } 548 549 if(allSigned) 550 signing = true; 551 552 //Check if main jar is found within extensions 553 foundMainJar = foundMainJar || hasMainInExtensions(); 554 409 555 return; 556 } 410 557 /* 411 558 if (jars == null || jars.length == 0) { … … 429 576 ); 430 577 } 578 579 //If there are no eager jars, initialize the first jar 580 if(initialJars.size() == 0) 581 initialJars.add(jars[0]); 431 582 432 583 if (strict) 433 584 fillInPartJars(initialJars); // add in each initial part's lazy jars 434 585 586 waitForJars(initialJars); //download the jars first. 587 588 //A ZipException will propagate later on if the jar is invalid and not checked here 589 if (shouldFilterInvalidJars()){ 590 //We filter any invalid jars 591 Iterator<JARDesc> iterator = initialJars.iterator(); 592 while (iterator.hasNext()){ 593 JARDesc jar = iterator.next(); 594 if (isInvalidJar(jar)) { 595 //Remove this jar as an available jar 596 iterator.remove(); 597 tracker.removeResource(jar.getLocation()); 598 available.remove(jar); 599 } 600 } 601 } 602 435 603 if (JNLPRuntime.isVerifying()) { 436 604 437 JarSigner js; 438 waitForJars(initialJars); //download the jars first. 605 JarCertVerifier jcv; 439 606 440 607 try { 441 j s= verifyJars(initialJars);608 jcv = verifyJars(initialJars); 442 609 } catch (Exception e) { 443 //we caught an Exception from the Jar Signer class.610 //we caught an Exception from the JarCertVerifier class. 444 611 //Note: one of these exceptions could be from not being able 445 612 //to read the cacerts or trusted.certs files. … … 450 617 451 618 //Case when at least one jar has some signing 452 if (j s.anyJarsSigned() && js.isFullySignedByASingleCert()) {619 if (jcv.anyJarsSigned() && jcv.isFullySignedByASingleCert()) { 453 620 signing = true; 454 621 455 if (!j s.allJarsSigned() &&622 if (!jcv.allJarsSigned() && 456 623 !SecurityDialogs.showNotAllSignedWarningDialog(file)) 457 624 throw new LaunchException(file, null, R("LSFatal"), R("LCClient"), R("LSignedAppJarUsingUnsignedJar"), R("LSignedAppJarUsingUnsignedJarInfo")); 458 625 626 627 // Check for main class in the downloaded jars, and check/verify signed JNLP fill 628 checkForMain(initialJars); 629 630 // If jar with main class was not found, check available resources 631 while (!foundMainJar && available != null && available.size() != 0) 632 addNextResource(); 633 634 // If the jar with main class was not found, check extension 635 // jnlp's resources 636 foundMainJar = foundMainJar || hasMainInExtensions(); 637 638 // If jar with main class was not found and there are no more 639 // available jars, throw a LaunchException 640 if (file.getLaunchInfo() != null) { 641 if (!foundMainJar 642 && (available == null || available.size() == 0)) 643 throw new LaunchException(file, null, R("LSFatal"), 644 R("LCClient"), R("LCantDetermineMainClass"), 645 R("LCantDetermineMainClassInfo")); 646 } 647 648 // If main jar was found, but a signed JNLP file was not located 649 if (!isSignedJNLP && foundMainJar) 650 file.setSignedJNLPAsMissing(); 651 459 652 //user does not trust this publisher 460 if (!j s.getAlreadyTrustPublisher()) {461 checkTrustWithUser(j s);653 if (!jcv.getAlreadyTrustPublisher()) { 654 checkTrustWithUser(jcv); 462 655 } else { 463 656 /** … … 476 669 for (JARDesc jarDesc : file.getResources().getJARs()) { 477 670 try { 478 File cachedFile = tracker.getCacheFile(jarDesc.getLocation()); 671 672 File cachedFile; 673 674 try { 675 cachedFile = tracker.getCacheFile(jarDesc.getLocation()); 676 } catch (IllegalResourceDescriptorException irde){ 677 //Caused by ignored resource being removed due to not being valid 678 System.err.println("JAR " + jarDesc.getLocation() + " is not a valid jar file. Continuing."); 679 continue; 680 } 479 681 480 682 if (cachedFile == null) { … … 515 717 } 516 718 } 517 518 719 activateJars(initialJars); 519 720 } 520 521 private void checkTrustWithUser(JarSigner js) throws LaunchException { 522 if (!js.getRootInCacerts()) { //root cert is not in cacerts 721 722 /*** 723 * Checks for the jar that contains the main class. If the main class was 724 * found, it checks to see if the jar is signed and whether it contains a 725 * signed JNLP file 726 * 727 * @param jars Jars that are checked to see if they contain the main class 728 * @throws LaunchException Thrown if the signed JNLP file, within the main jar, fails to be verified or does not match 729 */ 730 private void checkForMain(List<JARDesc> jars) throws LaunchException { 731 732 // Check launch info 733 if (mainClass == null) { 734 LaunchDesc launchDesc = file.getLaunchInfo(); 735 if (launchDesc == null) { 736 return; 737 } 738 739 mainClass = launchDesc.getMainClass(); 740 } 741 742 // The main class may be specified in the manifest 743 744 // Check main jar 745 if (mainClass == null) { 746 JARDesc mainJarDesc = file.getResources().getMainJAR(); 747 mainClass = getMainClassName(mainJarDesc.getLocation()); 748 } 749 750 // Check first jar 751 if (mainClass == null) { 752 JARDesc firstJarDesc = jars.get(0); 753 mainClass = getMainClassName(firstJarDesc.getLocation()); 754 } 755 756 // Still not found? Iterate and set if only 1 was found 757 if (mainClass == null) { 758 759 for (JARDesc jarDesc: jars) { 760 String mainClassInThisJar = getMainClassName(jarDesc.getLocation()); 761 762 if (mainClassInThisJar != null) { 763 764 if (mainClass == null) { // first main class 765 mainClass = mainClassInThisJar; 766 } else { // There is more than one main class. Set to null and break. 767 mainClass = null; 768 break; 769 } 770 } 771 } 772 } 773 774 String desiredJarEntryName = mainClass + ".class"; 775 776 for (int i = 0; i < jars.size(); i++) { 777 778 try { 779 File localFile = tracker 780 .getCacheFile(jars.get(i).getLocation()); 781 782 if (localFile == null) { 783 System.err.println("JAR " + jars.get(i).getLocation() + " not found. Continuing."); 784 continue; // JAR not found. Keep going. 785 } 786 787 JarFile jarFile = new JarFile(localFile); 788 Enumeration<JarEntry> entries = jarFile.entries(); 789 JarEntry je; 790 791 while (entries.hasMoreElements()) { 792 je = entries.nextElement(); 793 String jeName = je.getName().replaceAll("/", "."); 794 if (jeName.equals(desiredJarEntryName)) { 795 foundMainJar = true; 796 verifySignedJNLP(jars.get(i), jarFile); 797 break; 798 } 799 } 800 } catch (IOException e) { 801 /* 802 * After this exception is caught, it is escaped. This will skip 803 * the jarFile that may have thrown this exception and move on 804 * to the next jarFile (if there are any) 805 */ 806 } 807 } 808 } 809 810 /** 811 * Gets the name of the main method if specified in the manifest 812 * 813 * @param location The JAR location 814 * @return the main class name, null if there isn't one of if there was an error 815 */ 816 private String getMainClassName(URL location) { 817 818 String mainClass = null; 819 File f = tracker.getCacheFile(location); 820 821 if( f != null) { 822 try { 823 JarFile mainJar = new JarFile(f); 824 mainClass = mainJar.getManifest(). 825 getMainAttributes().getValue("Main-Class"); 826 } catch (IOException ioe) { 827 mainClass = null; 828 } 829 } 830 831 return mainClass; 832 } 833 834 /** 835 * Returns true if this loader has the main jar 836 */ 837 public boolean hasMainJar() { 838 return this.foundMainJar; 839 } 840 841 /** 842 * Returns true if extension loaders have the main jar 843 */ 844 private boolean hasMainInExtensions() { 845 boolean foundMain = false; 846 847 for (int i = 1; i < loaders.length && !foundMain; i++) { 848 foundMain = loaders[i].hasMainJar(); 849 } 850 851 return foundMain; 852 } 853 854 /** 855 * Is called by checkForMain() to check if the jar file is signed and if it 856 * contains a signed JNLP file. 857 * 858 * @param jarDesc JARDesc of jar 859 * @param jarFile the jar file 860 * @throws LaunchException thrown if the signed JNLP file, within the main jar, fails to be verified or does not match 861 */ 862 private void verifySignedJNLP(JARDesc jarDesc, JarFile jarFile) 863 throws LaunchException { 864 865 JarCertVerifier signer = new JarCertVerifier(); 866 List<JARDesc> desc = new ArrayList<JARDesc>(); 867 desc.add(jarDesc); 868 869 // Initialize streams 870 InputStream inStream = null; 871 InputStreamReader inputReader = null; 872 FileReader fr = null; 873 InputStreamReader jnlpReader = null; 874 875 try { 876 signer.verifyJars(desc, tracker); 877 878 if (signer.allJarsSigned()) { // If the jar is signed 879 880 Enumeration<JarEntry> entries = jarFile.entries(); 881 JarEntry je; 882 883 while (entries.hasMoreElements()) { 884 je = entries.nextElement(); 885 String jeName = je.getName().toUpperCase(); 886 887 if (jeName.equals(TEMPLATE) || jeName.equals(APPLICATION)) { 888 889 if (JNLPRuntime.isDebug()) 890 System.err.println("Creating Jar InputStream from JarEntry"); 891 892 inStream = jarFile.getInputStream(je); 893 inputReader = new InputStreamReader(inStream); 894 895 if (JNLPRuntime.isDebug()) 896 System.err.println("Creating File InputStream from lauching JNLP file"); 897 898 JNLPFile jnlp = this.getJNLPFile(); 899 URL url = jnlp.getFileLocation(); 900 File jn = null; 901 902 // If the file is on the local file system, use original path, otherwise find cached file 903 if (url.getProtocol().toLowerCase().equals("file")) 904 jn = new File(url.getPath()); 905 else 906 jn = CacheUtil.getCacheFile(url, null); 907 908 fr = new FileReader(jn); 909 jnlpReader = fr; 910 911 // Initialize JNLPMatcher class 912 JNLPMatcher matcher; 913 914 if (jeName.equals(APPLICATION)) { // If signed application was found 915 if (JNLPRuntime.isDebug()) 916 System.err.println("APPLICATION.JNLP has been located within signed JAR. Starting verfication..."); 917 918 matcher = new JNLPMatcher(inputReader, jnlpReader, false); 919 } else { // Otherwise template was found 920 if (JNLPRuntime.isDebug()) 921 System.err.println("APPLICATION_TEMPLATE.JNLP has been located within signed JAR. Starting verfication..."); 922 923 matcher = new JNLPMatcher(inputReader, jnlpReader, 924 true); 925 } 926 927 // If signed JNLP file does not matches launching JNLP file, throw JNLPMatcherException 928 if (!matcher.isMatch()) 929 throw new JNLPMatcherException("Signed Application did not match launching JNLP File"); 930 931 this.isSignedJNLP = true; 932 if (JNLPRuntime.isDebug()) 933 System.err.println("Signed Application Verification Successful"); 934 935 break; 936 } 937 } 938 } 939 } catch (JNLPMatcherException e) { 940 941 /* 942 * Throws LaunchException if signed JNLP file fails to be verified 943 * or fails to match the launching JNLP file 944 */ 945 946 throw new LaunchException(file, null, R("LSFatal"), R("LCClient"), 947 R("LSignedJNLPFileDidNotMatch"), R(e.getMessage())); 948 949 /* 950 * Throwing this exception will fail to initialize the application 951 * resulting in the termination of the application 952 */ 953 954 } catch (Exception e) { 955 956 if (JNLPRuntime.isDebug()) 957 e.printStackTrace(System.err); 958 959 /* 960 * After this exception is caught, it is escaped. If an exception is 961 * thrown while handling the jar file, (mainly for 962 * JarCertVerifier.verifyJars) it assumes the jar file is unsigned and 963 * skip the check for a signed JNLP file 964 */ 965 966 } finally { 967 968 //Close all streams 969 closeStream(inStream); 970 closeStream(inputReader); 971 closeStream(fr); 972 closeStream(jnlpReader); 973 } 974 975 if (JNLPRuntime.isDebug()) 976 System.err.println("Ending check for signed JNLP file..."); 977 } 978 979 /*** 980 * Closes a stream 981 * 982 * @param stream the stream that will be closed 983 */ 984 private void closeStream (Closeable stream) { 985 if (stream != null) 986 try { 987 stream.close(); 988 } catch (Exception e) { 989 e.printStackTrace(System.err); 990 } 991 } 992 993 private void checkTrustWithUser(JarCertVerifier jcv) throws LaunchException { 994 if (JNLPRuntime.isTrustAll()){ 995 return; 996 } 997 if (!jcv.getRootInCacerts()) { //root cert is not in cacerts 523 998 boolean b = SecurityDialogs.showCertWarningDialog( 524 AccessType.UNVERIFIED, file, j s);999 AccessType.UNVERIFIED, file, jcv); 525 1000 if (!b) 526 1001 throw new LaunchException(null, null, R("LSFatal"), 527 1002 R("LCLaunching"), R("LNotVerified"), ""); 528 } else if (j s.getRootInCacerts()) { //root cert is in cacerts1003 } else if (jcv.getRootInCacerts()) { //root cert is in cacerts 529 1004 boolean b = false; 530 if (j s.noSigningIssues())1005 if (jcv.noSigningIssues()) 531 1006 b = SecurityDialogs.showCertWarningDialog( 532 AccessType.VERIFIED, file, j s);533 else if (!j s.noSigningIssues())1007 AccessType.VERIFIED, file, jcv); 1008 else if (!jcv.noSigningIssues()) 534 1009 b = SecurityDialogs.showCertWarningDialog( 535 AccessType.SIGNING_ERROR, file, j s);1010 AccessType.SIGNING_ERROR, file, jcv); 536 1011 if (!b) 537 1012 throw new LaunchException(null, null, R("LSFatal"), … … 583 1058 */ 584 1059 protected PermissionCollection getPermissions(CodeSource cs) { 585 Permissions result = new Permissions(); 586 587 // should check for extensions or boot, automatically give all 588 // access w/o security dialog once we actually check certificates. 589 590 // copy security permissions from SecurityDesc element 591 if (security != null) { 592 // Security desc. is used only to track security settings for the 593 // application. However, an application may comprise of multiple 594 // jars, and as such, security must be evaluated on a per jar basis. 595 596 // set default perms 597 PermissionCollection permissions = security.getSandBoxPermissions(); 598 599 // If more than default is needed: 600 // 1. Code must be signed 601 // 2. ALL or J2EE permissions must be requested (note: plugin requests ALL automatically) 602 if (cs.getCodeSigners() != null && 603 (getCodeSourceSecurity(cs.getLocation()).getSecurityType().equals(SecurityDesc.ALL_PERMISSIONS) || 604 getCodeSourceSecurity(cs.getLocation()).getSecurityType().equals(SecurityDesc.J2EE_PERMISSIONS))) { 605 606 permissions = getCodeSourceSecurity(cs.getLocation()).getPermissions(cs); 607 } 608 609 Enumeration<Permission> e = permissions.elements(); 610 while (e.hasMoreElements()) 611 result.add(e.nextElement()); 612 } 613 614 // add in permission to read the cached JAR files 615 for (int i = 0; i < resourcePermissions.size(); i++) 616 result.add(resourcePermissions.get(i)); 617 618 // add in the permissions that the user granted. 619 for (int i = 0; i < runtimePermissions.size(); i++) 620 result.add(runtimePermissions.get(i)); 621 622 return result; 1060 try { 1061 Permissions result = new Permissions(); 1062 1063 // should check for extensions or boot, automatically give all 1064 // access w/o security dialog once we actually check certificates. 1065 1066 // copy security permissions from SecurityDesc element 1067 if (security != null) { 1068 // Security desc. is used only to track security settings for the 1069 // application. However, an application may comprise of multiple 1070 // jars, and as such, security must be evaluated on a per jar basis. 1071 1072 // set default perms 1073 PermissionCollection permissions = security.getSandBoxPermissions(); 1074 1075 // If more than default is needed: 1076 // 1. Code must be signed 1077 // 2. ALL or J2EE permissions must be requested (note: plugin requests ALL automatically) 1078 if (cs == null) { 1079 throw new NullPointerException("Code source was null"); 1080 } 1081 if (cs.getCodeSigners() != null) { 1082 if (cs.getLocation() == null) { 1083 throw new NullPointerException("Code source location was null"); 1084 } 1085 if (getCodeSourceSecurity(cs.getLocation()) == null) { 1086 throw new NullPointerException("Code source security was null"); 1087 } 1088 if (getCodeSourceSecurity(cs.getLocation()).getSecurityType() == null) { 1089 if (JNLPRuntime.isDebug()){ 1090 new NullPointerException("Warning! Code source security type was null").printStackTrace(); 1091 } 1092 } 1093 Object securityType = getCodeSourceSecurity(cs.getLocation()).getSecurityType(); 1094 if (SecurityDesc.ALL_PERMISSIONS.equals(securityType) 1095 || SecurityDesc.J2EE_PERMISSIONS.equals(securityType)) { 1096 1097 permissions = getCodeSourceSecurity(cs.getLocation()).getPermissions(cs); 1098 } 1099 } 1100 1101 Enumeration<Permission> e = permissions.elements(); 1102 while (e.hasMoreElements()) { 1103 result.add(e.nextElement()); 1104 } 1105 } 1106 1107 // add in permission to read the cached JAR files 1108 for (int i = 0; i < resourcePermissions.size(); i++) { 1109 result.add(resourcePermissions.get(i)); 1110 } 1111 1112 // add in the permissions that the user granted. 1113 for (int i = 0; i < runtimePermissions.size(); i++) { 1114 result.add(runtimePermissions.get(i)); 1115 } 1116 1117 // Class from host X should be allowed to connect to host X 1118 if (cs.getLocation().getHost().length() > 0) 1119 result.add(new SocketPermission(cs.getLocation().getHost(), 1120 "connect, accept")); 1121 1122 return result; 1123 } catch (RuntimeException ex) { 1124 if (JNLPRuntime.isDebug()) { 1125 ex.printStackTrace(); 1126 } 1127 throw ex; 1128 } 623 1129 } 624 1130 … … 719 1225 } 720 1226 721 Jar Signer signer = new JarSigner();1227 JarCertVerifier signer = new JarCertVerifier(); 722 1228 List<JARDesc> jars = new ArrayList<JARDesc>(); 723 1229 JARDesc jarDesc = new JARDesc(new File(extractedJarLocation).toURL(), null, null, false, false, false, false); … … 780 1286 JarFile jarFile = new JarFile(localFile.getAbsolutePath()); 781 1287 Manifest mf = jarFile.getManifest(); 782 classpaths.addAll(getClassPathsFromManifest(mf, jar.getLocation().getPath())); 1288 1289 // Only check classpath if this is the plugin and there is no jnlp_href usage. 1290 // Note that this is different from proprietary plugin behaviour. 1291 // If jnlp_href is used, the app should be treated similarly to when 1292 // it is run from javaws as a webstart. 1293 if (file instanceof PluginBridge && !((PluginBridge) file).useJNLPHref()) { 1294 classpaths.addAll(getClassPathsFromManifest(mf, jar.getLocation().getPath())); 1295 } 1296 783 1297 JarIndex index = JarIndex.getJarIndex(jarFile, null); 784 1298 if (index != null) … … 964 1478 * @param jars the jars to be verified. 965 1479 */ 966 private Jar Signer verifyJars(List<JARDesc> jars) throws Exception {967 968 j s = new JarSigner();969 j s.verifyJars(jars, tracker);970 return j s;1480 private JarCertVerifier verifyJars(List<JARDesc> jars) throws Exception { 1481 1482 jcv = new JarCertVerifier(); 1483 jcv.verifyJars(jars, tracker); 1484 return jcv; 971 1485 } 972 1486 … … 978 1492 Class result = null; 979 1493 980 if (loaders[i] == this) 981 result = super.findLoadedClass(name); 982 else 1494 if (loaders[i] == this) { 1495 final String fName = name; 1496 try { 1497 result = AccessController.doPrivileged( 1498 new PrivilegedExceptionAction<Class<?>>() { 1499 public Class<?> run() { 1500 return JNLPClassLoader.super.findLoadedClass(fName); 1501 } 1502 }, getAccessControlContextForClassLoading()); 1503 } catch (PrivilegedActionException pae) { 1504 result = null; 1505 } 1506 } else { 983 1507 result = loaders[i].findLoadedClassAll(name); 1508 } 984 1509 985 1510 if (result != null) … … 1095 1620 * @param desc the JARDesc for the new jar 1096 1621 */ 1097 private void addNewJar( JARDesc desc) {1622 private void addNewJar(final JARDesc desc) { 1098 1623 1099 1624 available.add(desc); … … 1105 1630 ); 1106 1631 1107 URL remoteURL = desc.getLocation(); 1108 URL cachedUrl = tracker.getCacheURL(remoteURL); 1109 addURL(remoteURL); 1110 CachedJarFileCallback.getInstance().addMapping(remoteURL, cachedUrl); 1632 // Give read permissions to the cached jar file 1633 AccessController.doPrivileged(new PrivilegedAction<Void>() { 1634 public Void run() { 1635 Permission p = CacheUtil.getReadPermission(desc.getLocation(), 1636 desc.getVersion()); 1637 1638 resourcePermissions.add(p); 1639 1640 return null; 1641 } 1642 }); 1643 1644 final URL remoteURL = desc.getLocation(); 1645 final URL cachedUrl = tracker.getCacheURL(remoteURL); // blocks till download 1646 1647 available.remove(desc); // Resource downloaded. Remove from available list. 1648 1649 try { 1650 1651 // Verify if needed 1652 1653 final JarCertVerifier signer = new JarCertVerifier(); 1654 final List<JARDesc> jars = new ArrayList<JARDesc>(); 1655 jars.add(desc); 1656 1657 // Decide what level of security this jar should have 1658 // The verification and security setting functions rely on 1659 // having AllPermissions as those actions normally happen 1660 // during initialization. We therefore need to do those 1661 // actions as privileged. 1662 1663 AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() { 1664 public Void run() throws Exception { 1665 signer.verifyJars(jars, tracker); 1666 1667 if (signer.anyJarsSigned() && !signer.getAlreadyTrustPublisher()) { 1668 checkTrustWithUser(signer); 1669 } 1670 1671 final SecurityDesc security; 1672 if (signer.anyJarsSigned()) { 1673 security = new SecurityDesc(file, 1674 SecurityDesc.ALL_PERMISSIONS, 1675 file.getCodeBase().getHost()); 1676 } else { 1677 security = new SecurityDesc(file, 1678 SecurityDesc.SANDBOX_PERMISSIONS, 1679 file.getCodeBase().getHost()); 1680 } 1681 1682 jarLocationSecurityMap.put(remoteURL, security); 1683 1684 return null; 1685 } 1686 }); 1687 1688 addURL(remoteURL); 1689 CachedJarFileCallback.getInstance().addMapping(remoteURL, cachedUrl); 1690 1691 } catch (Exception e) { 1692 // Do nothing. This code is called by loadClass which cannot 1693 // throw additional exceptions. So instead, just ignore it. 1694 // Exception => jar will not get added to classpath, which will 1695 // result in CNFE from loadClass. 1696 e.printStackTrace(); 1697 } 1111 1698 } 1112 1699 … … 1117 1704 for (int i = 0; i < loaders.length; i++) { 1118 1705 try { 1119 if (loaders[i] == this) 1120 return super.findClass(name); 1121 else 1706 if (loaders[i] == this) { 1707 final String fName = name; 1708 return AccessController.doPrivileged( 1709 new PrivilegedExceptionAction<Class<?>>() { 1710 public Class<?> run() throws ClassNotFoundException { 1711 return JNLPClassLoader.super.findClass(fName); 1712 } 1713 }, getAccessControlContextForClassLoading()); 1714 } else { 1122 1715 return loaders[i].findClass(name); 1716 } 1123 1717 } catch (ClassNotFoundException ex) { 1124 1718 } catch (ClassFormatError cfe) { 1719 } catch (PrivilegedActionException pae) { 1125 1720 } 1126 1721 } … … 1128 1723 // Try codebase loader 1129 1724 if (codeBaseLoader != null) 1130 return codeBaseLoader.findClass(name );1131 1725 return codeBaseLoader.findClass(name, true); 1726 1132 1727 // All else failed. Throw CNFE 1133 1728 throw new ClassNotFoundException(name); … … 1151 1746 // add resources until found 1152 1747 while (true) { 1153 JNLPClassLoader addedTo = addNextResource(); 1748 JNLPClassLoader addedTo = null; 1749 1750 try { 1751 addedTo = addNextResource(); 1752 } catch (LaunchException e) { 1753 1754 /* 1755 * This method will never handle any search for the main class 1756 * [It is handled in initializeResources()]. Therefore, this 1757 * exception will never be thrown here and is escaped 1758 */ 1759 1760 throw new IllegalStateException(e); 1761 } 1154 1762 1155 1763 if (addedTo == null) … … 1166 1774 * Finds the resource in this, the parent, or the extension 1167 1775 * class loaders. 1168 */ 1169 public URL getResource(String name) { 1170 URL result = super.getResource(name); 1171 1172 for (int i = 1; i < loaders.length; i++) 1173 if (result == null) 1174 result = loaders[i].getResource(name); 1776 * 1777 * @return a <code>URL</code> for the resource, or <code>null</code> 1778 * if the resource could not be found. 1779 */ 1780 @Override 1781 public URL findResource(String name) { 1782 URL result = null; 1783 1784 try { 1785 Enumeration<URL> e = findResources(name); 1786 if (e.hasMoreElements()) { 1787 result = e.nextElement(); 1788 } 1789 } catch (IOException e) { 1790 if (JNLPRuntime.isDebug()) { 1791 e.printStackTrace(); 1792 } 1793 } 1175 1794 1176 1795 // If result is still null, look in the codebase loader 1177 1796 if (result == null && codeBaseLoader != null) 1178 result = codeBaseLoader. getResource(name);1797 result = codeBaseLoader.findResource(name); 1179 1798 1180 1799 return result; … … 1182 1801 1183 1802 /** 1184 * Find s the resourcein this, the parent, or the extension1185 * class loaders. 1803 * Find the resources in this, the parent, or the extension 1804 * class loaders. Load lazy resources if not found in current resources. 1186 1805 */ 1187 1806 @Override 1188 1807 public Enumeration<URL> findResources(String name) throws IOException { 1189 Vector<URL> resources = new Vector<URL>(); 1190 Enumeration<URL> e; 1808 Enumeration<URL> resources = findResourcesBySearching(name); 1809 1810 try { 1811 // if not found, load all lazy resources; repeat search 1812 while (!resources.hasMoreElements() && addNextResource() != null) { 1813 resources = findResourcesBySearching(name); 1814 } 1815 } catch (LaunchException le) { 1816 le.printStackTrace(); 1817 } 1818 1819 return resources; 1820 } 1821 1822 /** 1823 * Find the resources in this, the parent, or the extension 1824 * class loaders. 1825 */ 1826 private Enumeration<URL> findResourcesBySearching(String name) throws IOException { 1827 List<URL> resources = new ArrayList<URL>(); 1828 Enumeration<URL> e = null; 1191 1829 1192 1830 for (int i = 0; i < loaders.length; i++) { 1193 1194 if (loaders[i] == this) 1195 e = super.findResources(name); 1196 else 1831 // TODO check if this will blow up or not 1832 // if loaders[1].getResource() is called, wont it call getResource() on 1833 // the original caller? infinite recursion? 1834 1835 if (loaders[i] == this) { 1836 final String fName = name; 1837 try { 1838 e = AccessController.doPrivileged( 1839 new PrivilegedExceptionAction<Enumeration<URL>>() { 1840 public Enumeration<URL> run() throws IOException { 1841 return JNLPClassLoader.super.findResources(fName); 1842 } 1843 }, getAccessControlContextForClassLoading()); 1844 } catch (PrivilegedActionException pae) { 1845 } 1846 } else { 1197 1847 e = loaders[i].findResources(name); 1198 1199 while (e.hasMoreElements()) 1200 resources.add(e.nextElement()); 1848 } 1849 1850 final Enumeration<URL> fURLEnum = e; 1851 try { 1852 resources.addAll(AccessController.doPrivileged( 1853 new PrivilegedExceptionAction<Collection<URL>>() { 1854 public Collection<URL> run() { 1855 List<URL> resources = new ArrayList<URL>(); 1856 while (fURLEnum != null && fURLEnum.hasMoreElements()) { 1857 resources.add(fURLEnum.nextElement()); 1858 } 1859 return resources; 1860 } 1861 }, getAccessControlContextForClassLoading())); 1862 } catch (PrivilegedActionException pae) { 1863 } 1201 1864 } 1202 1865 … … 1209 1872 } 1210 1873 1211 return resources.elements();1874 return Collections.enumeration(resources); 1212 1875 } 1213 1876 … … 1242 1905 * 1243 1906 * @return the classloader that resources were added to, or null 1244 */ 1245 protected JNLPClassLoader addNextResource() { 1907 * @throws LaunchException Thrown if the signed JNLP file, within the main jar, fails to be verified or does not match 1908 */ 1909 protected JNLPClassLoader addNextResource() throws LaunchException { 1246 1910 if (available.size() == 0) { 1247 1911 for (int i = 1; i < loaders.length; i++) { … … 1259 1923 1260 1924 fillInPartJars(jars); 1925 checkForMain(jars); 1261 1926 activateJars(jars); 1262 1927 … … 1306 1971 1307 1972 protected SecurityDesc getCodeSourceSecurity(URL source) { 1308 return jarLocationSecurityMap.get(source); 1973 SecurityDesc sec=jarLocationSecurityMap.get(source); 1974 if (sec == null && !alreadyTried.contains(source)) { 1975 alreadyTried.add(source); 1976 //try to load the jar which is requesting the permissions, but was NOT downloaded by standard way 1977 if (JNLPRuntime.isDebug()) { 1978 System.out.println("Application is trying to get permissions for " + source.toString() + ", which was not added by standard way. Trying to download and verify!"); 1979 } 1980 try { 1981 JARDesc des = new JARDesc(source, null, null, false, false, false, false); 1982 addNewJar(des); 1983 sec = jarLocationSecurityMap.get(source); 1984 } catch (Throwable t) { 1985 if (JNLPRuntime.isDebug()) { 1986 t.printStackTrace(); 1987 } 1988 sec = null; 1989 } 1990 } 1991 if (sec == null){ 1992 System.out.println(Translator.R("LNoSecInstance",source.toString())); 1993 } 1994 return sec; 1309 1995 } 1310 1996 … … 1347 2033 */ 1348 2034 private void addToCodeBaseLoader(URL u) { 2035 if (u == null) { 2036 return; 2037 } 1349 2038 1350 2039 // Only paths may be added … … 1403 2092 return result; 1404 2093 } 2094 2095 /** 2096 * Increments loader use count by 1 2097 * 2098 * @throws SecurityException if caller is not trusted 2099 */ 2100 private synchronized void incrementLoaderUseCount() { 2101 2102 // For use by trusted code only 2103 if (System.getSecurityManager() != null) 2104 System.getSecurityManager().checkPermission(new AllPermission()); 2105 2106 useCount++; 2107 } 2108 2109 /** 2110 * Decrements loader use count by 1 2111 * 2112 * If count reaches 0, loader is removed from list of available loaders 2113 * 2114 * @throws SecurityException if caller is not trusted 2115 */ 2116 public synchronized void decrementLoaderUseCount() { 2117 2118 // For use by trusted code only 2119 if (System.getSecurityManager() != null) 2120 System.getSecurityManager().checkPermission(new AllPermission()); 2121 2122 useCount--; 2123 2124 if (useCount <= 0) { 2125 synchronized(urlToLoader) { 2126 urlToLoader.remove(file.getUniqueKey()); 2127 } 2128 } 2129 } 2130 2131 /** 2132 * Returns an appropriate AccessControlContext for loading classes in 2133 * the running instance. 2134 * 2135 * The default context during class-loading only allows connection to 2136 * codebase. However applets are allowed to load jars from arbitrary 2137 * locations and the codebase only access falls short if a class from 2138 * one location needs a class from another. 2139 * 2140 * Given protected access since CodeBaseClassloader uses this function too. 2141 * 2142 * @return The appropriate AccessControlContext for loading classes for this instance 2143 */ 2144 public AccessControlContext getAccessControlContextForClassLoading() { 2145 AccessControlContext context = AccessController.getContext(); 2146 2147 try { 2148 context.checkPermission(new AllPermission()); 2149 return context; // If context already has all permissions, don't bother 2150 } catch (AccessControlException ace) { 2151 // continue below 2152 } catch (ClassCircularityError cce) { 2153 // continue below 2154 } 2155 2156 // Since this is for class-loading, technically any class from one jar 2157 // should be able to access a class from another, therefore making the 2158 // original context code source irrelevant 2159 PermissionCollection permissions = this.security.getSandBoxPermissions(); 2160 2161 // Local cache access permissions 2162 for (Permission resourcePermission : resourcePermissions) { 2163 permissions.add(resourcePermission); 2164 } 2165 2166 // Permissions for all remote hosting urls 2167 for (URL u: jarLocationSecurityMap.keySet()) { 2168 permissions.add(new SocketPermission(u.getHost(), 2169 "connect, accept")); 2170 } 2171 2172 // Permissions for codebase urls (if there is a loader) 2173 if (codeBaseLoader != null) { 2174 for (URL u : codeBaseLoader.getURLs()) { 2175 permissions.add(new SocketPermission(u.getHost(), 2176 "connect, accept")); 2177 } 2178 } 2179 2180 ProtectionDomain pd = new ProtectionDomain(null, permissions); 2181 2182 return new AccessControlContext(new ProtectionDomain[] { pd }); 2183 } 1405 2184 1406 2185 /* … … 1412 2191 JNLPClassLoader parentJNLPClassLoader; 1413 2192 2193 /** 2194 * Classes that are not found, so that findClass can skip them next time 2195 */ 2196 ConcurrentHashMap<String, URL[]> notFoundResources = new ConcurrentHashMap<String, URL[]>(); 2197 1414 2198 public CodeBaseClassLoader(URL[] urls, JNLPClassLoader cl) { 1415 2199 super(urls); … … 1423 2207 1424 2208 @Override 1425 public Class<?> findClass(String name) throws ClassNotFoundException { 1426 return super.findClass(name); 2209 public Class<?> findClass(String name) throws ClassNotFoundException { 2210 return findClass(name, false); 2211 } 2212 2213 public Class<?> findClass(String name, boolean recursivelyInvoked) throws ClassNotFoundException { 2214 2215 if (!recursivelyInvoked) { 2216 try { 2217 return parentJNLPClassLoader.findClass(name); 2218 } catch (ClassNotFoundException cnfe) { 2219 // continue 2220 } 2221 } 2222 2223 // If we have searched this path before, don't try again 2224 if (Arrays.equals(super.getURLs(), notFoundResources.get(name))) 2225 throw new ClassNotFoundException(name); 2226 2227 try { 2228 final String fName = name; 2229 return AccessController.doPrivileged( 2230 new PrivilegedExceptionAction<Class<?>>() { 2231 public Class<?> run() throws ClassNotFoundException { 2232 return CodeBaseClassLoader.super.findClass(fName); 2233 } 2234 }, parentJNLPClassLoader.getAccessControlContextForClassLoading()); 2235 } catch (PrivilegedActionException pae) { 2236 notFoundResources.put(name, super.getURLs()); 2237 throw new ClassNotFoundException("Could not find class " + name); 2238 } 1427 2239 } 1428 2240 … … 1451 2263 @Override 1452 2264 public Enumeration<URL> findResources(String name) throws IOException { 2265 2266 // If we have searched this path before, don't try again 2267 if (Arrays.equals(super.getURLs(), notFoundResources.get(name))) 2268 return (new Vector<URL>(0)).elements(); 2269 1453 2270 if (!name.startsWith("META-INF")) { 1454 return super.findResources(name); 1455 } 2271 Enumeration<URL> urls = super.findResources(name); 2272 2273 if (!urls.hasMoreElements()) { 2274 notFoundResources.put(name, super.getURLs()); 2275 } 2276 2277 return urls; 2278 } 2279 1456 2280 return (new Vector<URL>(0)).elements(); 1457 2281 } … … 1459 2283 @Override 1460 2284 public URL findResource(String name) { 2285 2286 // If we have searched this path before, don't try again 2287 if (Arrays.equals(super.getURLs(), notFoundResources.get(name))) 2288 return null; 2289 2290 URL url = null; 1461 2291 if (!name.startsWith("META-INF")) { 1462 return super.findResource(name); 1463 } 2292 try { 2293 final String fName = name; 2294 url = AccessController.doPrivileged( 2295 new PrivilegedExceptionAction<URL>() { 2296 public URL run() { 2297 return CodeBaseClassLoader.super.findResource(fName); 2298 } 2299 }, parentJNLPClassLoader.getAccessControlContextForClassLoading()); 2300 } catch (PrivilegedActionException pae) { 2301 } 2302 2303 if (url == null) { 2304 notFoundResources.put(name, super.getURLs()); 2305 } 2306 2307 return url; 2308 } 2309 1464 2310 return null; 1465 2311 } -
trunk/icedtea-web/netx/net/sourceforge/jnlp/runtime/JNLPRuntime.java
r348 r418 30 30 import javax.naming.ConfigurationException; 31 31 import javax.net.ssl.HttpsURLConnection; 32 import javax.net.ssl.KeyManagerFactory; 32 33 import javax.net.ssl.SSLContext; 33 34 import javax.net.ssl.SSLSocketFactory; … … 94 95 private static UpdatePolicy updatePolicy = UpdatePolicy.ALWAYS; 95 96 96 /** netx window icon */97 private static Image windowIcon = null;98 99 97 /** whether initialized */ 100 98 private static boolean initialized = false; … … 124 122 private static boolean forksAllowed = true; 125 123 124 /** all security dialogs will be consumed and pretented as beeing verified by user and allowed.*/ 125 private static boolean trustAll=false; 126 126 127 /** contains the arguments passed to the jnlp runtime */ 127 128 private static List<String> initialArguments; … … 132 133 public static final String STDERR_FILE = "java.stderr"; 133 134 public static final String STDOUT_FILE = "java.stdout"; 135 134 136 135 137 /** … … 184 186 checkHeadless(); 185 187 186 if (!headless && windowIcon == null)187 loadWindowIcon();188 189 188 if (!headless && indicator == null) 190 189 indicator = new DefaultDownloadIndicator(); … … 192 191 if (handler == null) { 193 192 if (headless) { 194 handler = new DefaultLaunchHandler( );193 handler = new DefaultLaunchHandler(System.err); 195 194 } else { 196 handler = new GuiLaunchHandler( );195 handler = new GuiLaunchHandler(System.err); 197 196 } 198 197 } … … 222 221 SSLSocketFactory sslSocketFactory; 223 222 SSLContext context = SSLContext.getInstance("SSL"); 223 KeyStore ks = KeyStores.getKeyStore(KeyStores.Level.USER, KeyStores.Type.CLIENT_CERTS); 224 KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); 225 kmf.init(ks, KeyStores.getPassword()); 224 226 TrustManager[] trust = new TrustManager[] { VariableX509TrustManager.getInstance() }; 225 context.init( null, trust, null);227 context.init(kmf.getKeyManagers(), trust, null); 226 228 sslSocketFactory = context.getSocketFactory(); 227 229 … … 326 328 public static boolean isWebstartApplication() { 327 329 return isWebstartApplication; 328 }329 330 /**331 * Returns the window icon.332 */333 public static Image getWindowIcon() {334 return windowIcon;335 }336 337 /**338 * Sets the window icon that is displayed in Java applications339 * and applets instead of the default Java icon.340 *341 * @throws IllegalStateException if caller is not the exit class342 */343 public static void setWindowIcon(Image image) {344 checkExitClass();345 windowIcon = image;346 330 } 347 331 … … 611 595 } catch (Exception ex) { 612 596 throw new IllegalStateException("Missing resource bundle in netx.jar:net/sourceforge/jnlp/resource/Messages.properties"); 613 }614 }615 616 /**617 * Load the window icon.618 */619 private static void loadWindowIcon() {620 if (windowIcon != null)621 return;622 623 try {624 windowIcon = new javax.swing.ImageIcon((new sun.misc.Launcher())625 .getClassLoader().getResource("net/sourceforge/jnlp/resources/netx-icon.png")).getImage();626 } catch (Exception ex) {627 if (JNLPRuntime.isDebug())628 ex.printStackTrace();629 597 } 630 598 } … … 733 701 } 734 702 703 static void setTrustAll(boolean b) { 704 trustAll=b; 705 } 706 707 public static boolean isTrustAll() { 708 return trustAll; 709 } 710 735 711 } -
trunk/icedtea-web/netx/net/sourceforge/jnlp/runtime/JNLPSecurityManager.java
r348 r418 282 282 // } 283 283 284 try { 285 super.checkPermission(perm); 286 } catch (SecurityException se) { 287 288 //This section is a special case for dealing with SocketPermissions. 289 if (JNLPRuntime.isDebug()) 290 System.err.println("Requesting permission: " + perm.toString()); 291 292 //Change this SocketPermission's action to connect and accept 293 //(and resolve). This is to avoid asking for connect permission 294 //on every address resolve. 295 Permission tmpPerm = null; 296 if (perm instanceof SocketPermission) { 297 tmpPerm = new SocketPermission(perm.getName(), 298 SecurityConstants.SOCKET_CONNECT_ACCEPT_ACTION); 299 300 // before proceeding, check if we are trying to connect to same origin 301 ApplicationInstance app = getApplication(); 302 JNLPFile file = app.getJNLPFile(); 303 304 String srcHost = file.getSourceLocation().getAuthority(); 305 String destHost = name; 306 307 // host = abc.xyz.com or abc.xyz.com:<port> 308 if (destHost.indexOf(':') >= 0) 309 destHost = destHost.substring(0, destHost.indexOf(':')); 310 311 // host = abc.xyz.com 312 String[] hostComponents = destHost.split("\\."); 313 314 int length = hostComponents.length; 315 if (length >= 2) { 316 317 // address is in xxx.xxx.xxx format 318 destHost = hostComponents[length - 2] + "." + hostComponents[length - 1]; 319 320 // host = xyz.com i.e. origin 321 boolean isDestHostName = false; 322 323 // make sure that it is not an ip address 324 try { 325 Integer.parseInt(hostComponents[length - 1]); 326 } catch (NumberFormatException e) { 327 isDestHostName = true; 328 } 329 330 if (isDestHostName) { 331 // okay, destination is hostname. Now figure out if it is a subset of origin 332 if (srcHost.endsWith(destHost)) { 333 addPermission(tmpPerm); 334 return; 335 } 336 } 337 } 338 } else { 339 tmpPerm = perm; 340 } 341 342 if (tmpPerm != null) { 343 //askPermission will only prompt the user on SocketPermission 344 //meaning we're denying all other SecurityExceptions that may arise. 345 if (askPermission(tmpPerm)) { 346 addPermission(tmpPerm); 347 //return quietly. 348 } else { 349 throw se; 350 } 351 } 352 } 284 super.checkPermission(perm); 353 285 } catch (SecurityException ex) { 354 286 if (JNLPRuntime.isDebug()) { … … 418 350 app.addWindow(w); 419 351 } 420 421 // change coffee cup to netx for default icon422 if (window instanceof Window)423 for (Window w = (Window) window; w != null; w = w.getOwner())424 if (window instanceof Frame)425 ((Frame) window).setIconImage(JNLPRuntime.getWindowIcon());426 352 427 353 // todo: set awt.appletWarning to custom message -
trunk/icedtea-web/netx/net/sourceforge/jnlp/runtime/pac-funcs.js
r348 r418 326 326 */ 327 327 function dateRange() { 328 329 // note: watch out for wrapping around of dates. date ranges, like 330 // month=9 to month=8, wrap around and cover the entire year. this 331 // makes everything more interesting 332 333 var gmt; 334 if (arguments.length > 1) { 335 if (arguments[arguments.length-1] === "GMT") { 336 gmt = true; 337 arguments.splice(0,arguments.length-1); 338 } 339 } 328 switch (arguments.length) { 329 case 1: return isDateInRange_internallForIcedTeaWebTesting(new Date(),arguments[0]); 330 case 2: return isDateInRange_internallForIcedTeaWebTesting(new Date(),arguments[0],arguments[1]); 331 case 3: return isDateInRange_internallForIcedTeaWebTesting(new Date(),arguments[0],arguments[1],arguments[2]); 332 case 4: return isDateInRange_internallForIcedTeaWebTesting(new Date(),arguments[0],arguments[1],arguments[2],arguments[3]); 333 case 5: return isDateInRange_internallForIcedTeaWebTesting(new Date(),arguments[0],arguments[1],arguments[2],arguments[3],arguments[4]); 334 case 6: return isDateInRange_internallForIcedTeaWebTesting(new Date(),arguments[0],arguments[1],arguments[2],arguments[3],arguments[4],arguments[5]); 335 case 7: return isDateInRange_internallForIcedTeaWebTesting(new Date(),arguments[0],arguments[1],arguments[2],arguments[3],arguments[4],arguments[5],arguments[6]); //GMT 336 default: 337 return false; 338 } 339 } 340 341 function isDateInRange_internallForIcedTeaWebTesting() { 340 342 341 343 function isDate(date) { … … 414 416 415 417 function inYearRange(today, year1, year2) { 416 if (year1 <= today.get Year() && today.getYear() <= year2) {418 if (year1 <= today.getFullYear() && today.getFullYear() <= year2) { 417 419 return true; 418 420 } else { … … 481 483 function inYearMonthRange(today, month1, year1, month2, year2) { 482 484 if (year1 === year2) { 483 if (today.get Year() === year1) {485 if (today.getFullYear() === year1) { 484 486 if (month1 <= today.getMonth() && today.getMonth() <= month2) { 485 487 return true; … … 492 494 } 493 495 if (year1 < year2) { 494 if (year1 <= today.get Year() && today.getYear() <= year2) {495 if (today.get Year() === year1) {496 if (year1 <= today.getFullYear() && today.getFullYear() <= year2) { 497 if (today.getFullYear() === year1) { 496 498 if (today.getMonth() >= month1) { 497 499 return true; … … 499 501 return false; 500 502 } 501 } else if (today.get Year() === year2) {503 } else if (today.getFullYear() === year2) { 502 504 if (today.getMonth() <= month2) { 503 505 return true; … … 514 516 return false; 515 517 } 516 517 518 } 518 519 519 520 function inYearMonthDateRange(today, date1, month1, year1, date2, month2, year2) { 520 521 if (year1 === year2) { 521 if (year1 === today.get Year()) {522 if (year1 === today.getFullYear()) { 522 523 if ((month1 <= today.getMonth()) && (today.getMonth() <= month2)) { 523 524 if (month1 === month2) { … … 549 550 } 550 551 } else if (year1 < year2) { 551 if (year1 <= today.get Year() && today.getYear() <= year2) {552 if (today.get Year() === year1) {552 if (year1 <= today.getFullYear() && today.getFullYear() <= year2) { 553 if (today.getFullYear() === year1) { 553 554 if (today.getMonth() === month1) { 554 555 if (today.getDate() >= date1) { … … 562 563 return false; 563 564 } 564 } else if (today.getYear() === year2) { 565 if (today.getMonth() <= month2) { 566 567 } else { 568 return true; 569 } 570 } else { 571 return true; 572 } 573 } else { 574 return false; 575 } 576 } else { 577 return false; 578 } 579 } 580 565 } else if (today.getFullYear() === year2) { 566 if (today.getMonth() === month2) { 567 if (today.getDate() <= date1) { 568 return true; 569 } else { 570 return false; 571 } 572 } else if (today.getMonth() < month2) { 573 return true; 574 } else { 575 return false; 576 } 577 } else { 578 return true; 579 } 580 } else { 581 return false; 582 } 583 } else { 584 return false; 585 } 586 } 587 588 // note: watch out for wrapping around of dates. date ranges, like 589 // month=9 to month=8, wrap around and cover the entire year. this 590 // makes everything more interesting 591 592 var gmt; 593 if (arguments.length > 2) { 594 if (arguments[arguments.length-1] === "GMT") { 595 gmt = true; 596 arguments.splice(0,arguments.length-1); 597 } 598 } 581 599 // TODO: change date to gmt, whatever 582 var today = new Date();600 var today = arguments[0] 583 601 584 602 var arg1; … … 589 607 var arg6; 590 608 591 switch (arguments.length ) {609 switch (arguments.length-1) { 592 610 case 1: 593 var arg = arguments[ 0];611 var arg = arguments[1]; 594 612 if (isDate(arg)) { 595 613 if (today.getDate() === arg) { … … 605 623 } 606 624 } else { // year 607 if (today.get Year() === arg) {625 if (today.getFullYear() === arg) { 608 626 return true; 609 627 } else { … … 612 630 } 613 631 case 2: 614 arg1 = arguments[ 0];615 arg2 = arguments[ 1];632 arg1 = arguments[1]; 633 arg2 = arguments[2]; 616 634 if (isDate(arg1) && isDate(arg2)) { 617 635 var date1 = arg1; … … 635 653 } 636 654 case 4: 637 arg1 = arguments[ 0];638 arg2 = arguments[ 1];639 arg3 = arguments[ 2];640 arg4 = arguments[ 3];655 arg1 = arguments[1]; 656 arg2 = arguments[2]; 657 arg3 = arguments[3]; 658 arg4 = arguments[4]; 641 659 642 660 if (isDate(arg1) && isMonth(arg2) && isDate(arg3) && isMonth(arg4)) { … … 659 677 } 660 678 case 6: 661 arg1 = arguments[ 0];662 arg2 = arguments[ 1];663 arg3 = arguments[ 2];664 arg4 = arguments[ 3];665 arg5 = arguments[ 4];666 arg6 = arguments[ 5];679 arg1 = arguments[1]; 680 arg2 = arguments[2]; 681 arg3 = arguments[3]; 682 arg4 = arguments[4]; 683 arg5 = arguments[5]; 684 arg6 = arguments[6]; 667 685 if (isDate(arg1) && isMonth(arg2) && isYear(arg3) && 668 686 isDate(arg4) && isMonth(arg5) && isYear(arg6)) { -
trunk/icedtea-web/netx/net/sourceforge/jnlp/security/AccessWarningPane.java
r348 r418 105 105 106 106 try { 107 publisher = file.getInformation().getVendor() != null ? file.getInformation().getVendor() : R("SNoAssociatedCertificate"); 107 publisher = file.getInformation().getVendor() != null ? 108 file.getInformation().getVendor() + " " + R("SUnverified") : 109 R("SNoAssociatedCertificate"); 108 110 } catch (Exception e) { 109 111 } … … 151 153 } 152 154 153 ImageIcon icon = new ImageIcon((new sun.misc.Launcher()).getClassLoader().getResource("net/sourceforge/jnlp/resources/ warning.png"));155 ImageIcon icon = new ImageIcon((new sun.misc.Launcher()).getClassLoader().getResource("net/sourceforge/jnlp/resources/question.png")); 154 156 JLabel topLabel = new JLabel(htmlWrap(topLabelText), icon, SwingConstants.LEFT); 155 157 topLabel.setFont(new Font(topLabel.getFont().toString(), -
trunk/icedtea-web/netx/net/sourceforge/jnlp/security/CertWarningPane.java
r348 r418 1 1 /* CertWarningPane.java 2 Copyright (C) 20 08Red Hat, Inc.2 Copyright (C) 2012 Red Hat, Inc. 3 3 4 4 This file is part of IcedTea. … … 97 97 AccessType type = parent.getAccessType(); 98 98 JNLPFile file = parent.getFile(); 99 Certificate c = parent.get JarSigner().getPublisher();99 Certificate c = parent.getCertVerifier().getPublisher(); 100 100 101 101 String name = ""; … … 133 133 } 134 134 135 // Top label135 // Labels 136 136 String topLabelText = ""; 137 String bottomLabelText = parent.getCertVerifier().getRootInCacerts() ? 138 R("STrustedSource") : R("SUntrustedSource"); 137 139 String propertyName = ""; 140 String iconLocation = "net/sourceforge/jnlp/resources/"; 141 boolean alwaysTrustSelected = false; 138 142 if (certVerifier instanceof HttpsCertVerifier) { 139 topLabelText = R("SHttpsUnverified") + " " + 140 R("Continue"); 143 // HTTPS certs that are verified do not prompt for a dialog. 144 // @see VariableX509TrustManager#checkServerTrusted 145 topLabelText = R("SHttpsUnverified") + " " + R("Continue"); 141 146 propertyName = "OptionPane.warningIcon"; 147 iconLocation += "warning.png"; 142 148 } else 143 149 switch (type) { … … 145 151 topLabelText = R("SSigVerified"); 146 152 propertyName = "OptionPane.informationIcon"; 153 iconLocation += "question.png"; 154 alwaysTrustSelected = true; 147 155 break; 148 156 case UNVERIFIED: 149 157 topLabelText = R("SSigUnverified"); 150 158 propertyName = "OptionPane.warningIcon"; 159 iconLocation += "warning.png"; 160 bottomLabelText += " " + R("SWarnFullPermissionsIgnorePolicy"); 151 161 break; 152 162 case SIGNING_ERROR: 153 163 topLabelText = R("SSignatureError"); 154 164 propertyName = "OptionPane.warningIcon"; 165 iconLocation += "warning.png"; 166 bottomLabelText += " " + R("SWarnFullPermissionsIgnorePolicy"); 155 167 break; 156 168 } 169 157 170 ImageIcon icon = new ImageIcon((new sun.misc.Launcher()) 158 .getClassLoader().getResource( "net/sourceforge/jnlp/resources/warning.png"));171 .getClassLoader().getResource(iconLocation)); 159 172 JLabel topLabel = new JLabel(htmlWrap(topLabelText), icon, SwingConstants.LEFT); 160 173 topLabel.setFont(new Font(topLabel.getFont().toString(), … … 163 176 topPanel.setBackground(Color.WHITE); 164 177 topPanel.add(topLabel, BorderLayout.CENTER); 165 topPanel.setPreferredSize(new Dimension(400, 60));178 topPanel.setPreferredSize(new Dimension(400, 75)); 166 179 topPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); 167 180 … … 176 189 alwaysTrust = new JCheckBox(R("SAlwaysTrustPublisher")); 177 190 alwaysTrust.setEnabled(true); 191 alwaysTrust.setSelected(alwaysTrustSelected); 178 192 179 193 JPanel infoPanel = new JPanel(new GridLayout(4, 1)); … … 211 225 add(buttonPanel); 212 226 213 JLabel bottomLabel ;227 JLabel bottomLabel = new JLabel(htmlWrap(bottomLabelText));; 214 228 JButton moreInfo = new JButton(R("ButMoreInformation")); 215 229 moreInfo.addActionListener(new MoreInfoButtonListener()); 216 217 if (parent.getJarSigner().getRootInCacerts())218 bottomLabel = new JLabel(htmlWrap(R("STrustedSource")));219 else220 bottomLabel = new JLabel(htmlWrap(R("SUntrustedSource")));221 230 222 231 JPanel bottomPanel = new JPanel(); … … 224 233 bottomPanel.add(bottomLabel); 225 234 bottomPanel.add(moreInfo); 226 bottomPanel.setPreferredSize(new Dimension( 500, 100));235 bottomPanel.setPreferredSize(new Dimension(600, 100)); 227 236 bottomPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); 228 237 add(bottomPanel); … … 232 241 private class MoreInfoButtonListener implements ActionListener { 233 242 public void actionPerformed(ActionEvent e) { 234 SecurityDialog.showMoreInfoDialog(parent.get JarSigner(),243 SecurityDialog.showMoreInfoDialog(parent.getCertVerifier(), 235 244 parent); 236 245 } … … 245 254 try { 246 255 KeyStore ks = KeyStores.getKeyStore(Level.USER, Type.CERTS); 247 X509Certificate c = (X509Certificate) parent.get JarSigner().getPublisher();256 X509Certificate c = (X509Certificate) parent.getCertVerifier().getPublisher(); 248 257 CertificateUtils.addToKeyStore(c, ks); 249 258 File keyStoreFile = new File(KeyStores.getKeyStoreLocation(Level.USER, Type.CERTS)); -
trunk/icedtea-web/netx/net/sourceforge/jnlp/security/CertificateUtils.java
r348 r418 39 39 40 40 import java.io.BufferedInputStream; 41 import java.io.BufferedOutputStream; 41 42 import java.io.File; 42 43 import java.io.FileInputStream; 44 import java.io.FileOutputStream; 43 45 import java.io.IOException; 44 46 import java.io.PrintStream; 45 47 import java.math.BigInteger; 48 import java.security.InvalidKeyException; 49 import java.security.Key; 46 50 import java.security.KeyStore; 47 51 import java.security.KeyStoreException; 52 import java.security.NoSuchAlgorithmException; 53 import java.security.NoSuchProviderException; 54 import java.security.SignatureException; 48 55 import java.security.cert.Certificate; 49 56 import java.security.cert.CertificateException; 50 57 import java.security.cert.CertificateFactory; 51 58 import java.security.cert.X509Certificate; 59 import java.util.Enumeration; 52 60 import java.util.Random; 53 61 54 62 import net.sourceforge.jnlp.runtime.JNLPRuntime; 55 56 import sun.misc.BASE64Encoder;63 import net.sourceforge.jnlp.runtime.Translator; 64 import net.sourceforge.jnlp.util.replacements.BASE64Encoder; 57 65 import sun.security.provider.X509Factory; 58 66 … … 114 122 } 115 123 124 public static void addPKCS12ToKeyStore(File file, KeyStore ks, char[] password) 125 throws Exception { 126 BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file)); 127 KeyStore keyStore = KeyStore.getInstance("PKCS12"); 128 keyStore.load(bis, password); 129 130 Enumeration<String> aliasList = keyStore.aliases(); 131 132 while (aliasList.hasMoreElements()) { 133 String alias = aliasList.nextElement(); 134 Certificate[] certChain = keyStore.getCertificateChain(alias); 135 Key key = keyStore.getKey(alias, password); 136 addPKCS12ToKeyStore(certChain, key, ks); 137 } 138 } 139 140 public static void addPKCS12ToKeyStore(Certificate[] certChain, Key key, KeyStore ks) 141 throws KeyStoreException { 142 String alias = null; 143 144 // does this certificate already exist? 145 alias = ks.getCertificateAlias(certChain[0]); 146 if (alias != null) { 147 return; 148 } 149 150 // create a unique alias for this new certificate 151 Random random = new Random(); 152 do { 153 alias = new BigInteger(20, random).toString(); 154 } while (ks.getCertificate(alias) != null); 155 156 ks.setKeyEntry(alias, key, KeyStores.getPassword(), certChain); 157 } 158 116 159 /** 117 160 * Checks whether an X509Certificate is already in one of the keystores … … 123 166 for (int i = 0; i < keyStores.length; i++) { 124 167 try { 125 if (keyStores[i].getCertificateAlias(c) != null) { 126 if (JNLPRuntime.isDebug()) { 127 System.out.println(c.getSubjectX500Principal().getName() + " found in cacerts"); 128 } 129 return true; 168 // Check against all certs 169 Enumeration<String> aliases = keyStores[i].aliases(); 170 while (aliases.hasMoreElements()) { 171 172 // Verify against this entry 173 String alias = aliases.nextElement(); 174 175 if (c.equals(keyStores[i].getCertificate(alias))) { 176 if (JNLPRuntime.isDebug()) { 177 System.out.println(Translator.R("LCertFoundIn", c.getSubjectX500Principal().getName(), KeyStores.getPathToKeystore(keyStores[i].hashCode()))); 178 } 179 180 return true; 181 } // else continue 130 182 } 183 131 184 } catch (KeyStoreException e) { 132 185 e.printStackTrace(); … … 149 202 out.println(X509Factory.END_CERT); 150 203 } 204 205 public static void dumpPKCS12(String alias, File file, KeyStore ks, char[] password) 206 throws Exception { 207 Certificate[] certChain = ks.getCertificateChain(alias); 208 Key key = ks.getKey(alias, KeyStores.getPassword()); 209 BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file)); 210 KeyStore keyStore = KeyStore.getInstance("PKCS12"); 211 keyStore.load(null, null); 212 keyStore.setKeyEntry(alias, key, password, certChain); 213 keyStore.store(bos, password); 214 } 151 215 } -
trunk/icedtea-web/netx/net/sourceforge/jnlp/security/CertsInfoPane.java
r348 r418 85 85 */ 86 86 void buildTree() { 87 certPath = parent.get JarSigner().getCertPath();87 certPath = parent.getCertVerifier().getCertPath(); 88 88 X509Certificate firstCert = 89 89 ((X509Certificate) certPath.getCertificates().get(0)); -
trunk/icedtea-web/netx/net/sourceforge/jnlp/security/KeyStores.java
r348 r418 48 48 import java.security.cert.CertificateException; 49 49 import java.util.ArrayList; 50 import java.util.HashMap; 50 51 import java.util.List; 52 import java.util.Map; 51 53 import java.util.StringTokenizer; 52 54 … … 76 78 } 77 79 80 public static final Map<Integer,String> keystoresPaths=new HashMap<Integer, String>(); 81 78 82 private static DeploymentConfiguration config = null; 79 83 … … 134 138 try { 135 139 ks = createKeyStoreFromFile(new File(location), create, DEFAULT_PASSWORD); 140 //hashcode is used instead of instance so when no references are left 141 //to keystore, then this will not be blocker for garbage collection 142 keystoresPaths.put(ks.hashCode(),location); 136 143 } catch (Exception e) { 137 144 e.printStackTrace(); 138 145 } 139 146 return ks; 147 } 148 149 public static String getPathToKeystore(int k) { 150 String s = keystoresPaths.get(k); 151 if (s == null) { 152 return "unknown keystore location"; 153 } 154 return s; 140 155 } 141 156 -
trunk/icedtea-web/netx/net/sourceforge/jnlp/security/MoreInfoPane.java
r348 r418 62 62 public class MoreInfoPane extends SecurityDialogPanel { 63 63 64 private boolean showSignedJNLPWarning; 65 64 66 public MoreInfoPane(SecurityDialog x, CertVerifier certVerifier) { 65 67 super(x, certVerifier); 68 showSignedJNLPWarning= x.requiresSignedJNLPWarning(); 66 69 addComponents(); 67 70 } … … 73 76 ArrayList<String> details = certVerifier.getDetails(); 74 77 78 // Show signed JNLP warning if the signed main jar does not have a 79 // signed JNLP file and the launching JNLP file contains special properties 80 if(showSignedJNLPWarning) 81 details.add(R("SJNLPFileIsNotSigned")); 82 75 83 int numLabels = details.size(); 76 84 JPanel errorPanel = new JPanel(new GridLayout(numLabels, 1)); … … 89 97 errorPanel.add(new JLabel(htmlWrap(details.get(i)), icon, SwingConstants.LEFT)); 90 98 } 99 100 // Removes signed JNLP warning after it has been used. This will avoid 101 // any alteration to certVerifier. 102 if(showSignedJNLPWarning) 103 details.remove(details.size()-1); 91 104 92 105 JPanel buttonsPanel = new JPanel(new BorderLayout()); … … 106 119 private class CertInfoButtonListener implements ActionListener { 107 120 public void actionPerformed(ActionEvent e) { 108 SecurityDialog.showCertInfoDialog(parent.get JarSigner(),121 SecurityDialog.showCertInfoDialog(parent.getCertVerifier(), 109 122 parent); 110 123 } -
trunk/icedtea-web/netx/net/sourceforge/jnlp/security/SecurityDialog.java
r348 r418 42 42 import net.sourceforge.jnlp.security.SecurityDialogs.AccessType; 43 43 import net.sourceforge.jnlp.security.SecurityDialogs.DialogType; 44 import net.sourceforge.jnlp.util.ImageResources; 44 45 45 46 import java.awt.*; … … 93 94 private Object value; 94 95 95 SecurityDialog(DialogType dialogType, AccessType accessType, 96 JNLPFile file, CertVerifier jarSigner, X509Certificate cert, Object[] extras) { 96 /** Should show signed JNLP file warning */ 97 private boolean requiresSignedJNLPWarning; 98 99 SecurityDialog(DialogType dialogType, AccessType accessType, 100 JNLPFile file, CertVerifier JarCertVerifier, X509Certificate cert, Object[] extras) { 97 101 super(); 102 setIconImages(ImageResources.INSTANCE.getApplicationImages()); 98 103 this.dialogType = dialogType; 99 104 this.accessType = accessType; 100 105 this.file = file; 101 this.certVerifier = jarSigner;106 this.certVerifier = JarCertVerifier; 102 107 this.cert = cert; 103 108 this.extras = extras; 104 109 initialized = true; 105 110 111 if(file != null) 112 requiresSignedJNLPWarning= file.requiresSignedJNLPWarning(); 113 106 114 initDialog(); 107 115 } … … 119 127 */ 120 128 SecurityDialog(DialogType dialogType, AccessType accessType, 121 JNLPFile file, CertVerifier jarSigner) {122 this(dialogType, accessType, file, jarSigner, null, null);129 JNLPFile file, CertVerifier certVerifier) { 130 this(dialogType, accessType, file, certVerifier, null, null); 123 131 } 124 132 … … 159 167 * Shows more information regarding jar code signing 160 168 * 161 * @param jarSigner the JarSigner used to verify this application169 * @param certVerifier the JarCertVerifier used to verify this application 162 170 * @param parent the parent option pane 163 171 */ 164 172 public static void showMoreInfoDialog( 165 CertVerifier jarSigner, SecurityDialog parent) { 166 173 CertVerifier certVerifier, SecurityDialog parent) { 174 175 JNLPFile file= parent.getFile(); 167 176 SecurityDialog dialog = 168 new SecurityDialog(DialogType.MORE_INFO, null, null,169 jarSigner);177 new SecurityDialog(DialogType.MORE_INFO, null, file, 178 certVerifier); 170 179 dialog.setModalityType(ModalityType.APPLICATION_MODAL); 171 180 dialog.setVisible(true); … … 176 185 * Displays CertPath information in a readable table format. 177 186 * 178 * @param jarSigner the JarSigner used to verify this application187 * @param certVerifier the JarCertVerifier used to verify this application 179 188 * @param parent the parent option pane 180 189 */ 181 public static void showCertInfoDialog(CertVerifier jarSigner,190 public static void showCertInfoDialog(CertVerifier certVerifier, 182 191 SecurityDialog parent) { 183 192 SecurityDialog dialog = new SecurityDialog(DialogType.CERT_INFO, 184 null, null, jarSigner);193 null, null, certVerifier); 185 194 dialog.setLocationRelativeTo(parent); 186 195 dialog.setModalityType(ModalityType.APPLICATION_MODAL); … … 208 217 209 218 String dialogTitle = ""; 210 if (dialogType == DialogType.CERT_WARNING) 211 dialogTitle = "Warning - Security"; 212 else if (dialogType == DialogType.MORE_INFO) 219 if (dialogType == DialogType.CERT_WARNING) { 220 if (accessType == AccessType.VERIFIED) 221 dialogTitle = "Security Approval Required"; 222 else 223 dialogTitle = "Security Warning"; 224 } else if (dialogType == DialogType.MORE_INFO) 213 225 dialogTitle = "More Information"; 214 226 else if (dialogType == DialogType.CERT_INFO) … … 267 279 } 268 280 269 public CertVerifier get JarSigner() {281 public CertVerifier getCertVerifier() { 270 282 return certVerifier; 271 283 } … … 370 382 listeners.add(listener); 371 383 } 384 385 public boolean requiresSignedJNLPWarning() 386 { 387 return requiresSignedJNLPWarning; 388 } 372 389 373 390 } -
trunk/icedtea-web/netx/net/sourceforge/jnlp/security/SecurityDialogs.java
r348 r418 181 181 * @param accessType the type of warning dialog to show 182 182 * @param file the JNLPFile associated with this warning 183 * @param jarSigner the JarSigner used to verify this application 183 * @param certVerifier the JarCertVerifier used to verify this application 184 * 185 * @return true if the user accepted the certificate 184 186 */ 185 187 public static boolean showCertWarningDialog(AccessType accessType, 186 JNLPFile file, CertVerifier jarSigner) {188 JNLPFile file, CertVerifier certVerifier) { 187 189 188 190 if (!shouldPromptUser()) { … … 194 196 message.accessType = accessType; 195 197 message.file = file; 196 message.certVerifier = jarSigner;198 message.certVerifier = certVerifier; 197 199 198 200 Object selectedValue = getUserResponse(message); -
trunk/icedtea-web/netx/net/sourceforge/jnlp/security/VariableX509TrustManager.java
r348 r418 38 38 package net.sourceforge.jnlp.security; 39 39 40 import java.security.AccessController; 40 41 import java.security.KeyStore; 42 import java.security.PrivilegedAction; 41 43 import java.security.cert.Certificate; 42 44 import java.security.cert.CertificateException; … … 54 56 55 57 import com.sun.net.ssl.internal.ssl.X509ExtendedTrustManager; 58 import net.sourceforge.jnlp.runtime.JNLPRuntime; 56 59 57 60 import net.sourceforge.jnlp.security.SecurityDialogs.AccessType; … … 380 383 * @return user's response 381 384 */ 382 private boolean askUser(X509Certificate[] chain, String authType, 383 boolean isTrusted, boolean hostMatched, 384 String hostName) { 385 return SecurityDialogs.showCertWarningDialog( 385 private boolean askUser(final X509Certificate[] chain, final String authType, 386 final boolean isTrusted, final boolean hostMatched, 387 final String hostName) { 388 if (JNLPRuntime.isTrustAll()){ 389 return true; 390 } 391 final VariableX509TrustManager trustManager = this; 392 return AccessController.doPrivileged(new PrivilegedAction<Boolean>() { 393 @Override 394 public Boolean run() { 395 return SecurityDialogs.showCertWarningDialog( 386 396 AccessType.UNVERIFIED, null, 387 new HttpsCertVerifier(t his, chain, authType,397 new HttpsCertVerifier(trustManager, chain, authType, 388 398 isTrusted, hostMatched, 389 399 hostName)); 400 } 401 }); 390 402 } 391 403 -
trunk/icedtea-web/netx/net/sourceforge/jnlp/security/viewer/CertificatePane.java
r348 r418 67 67 import javax.swing.JOptionPane; 68 68 import javax.swing.JPanel; 69 import javax.swing.JPasswordField; 69 70 import javax.swing.JScrollPane; 70 71 import javax.swing.JTabbedPane; … … 101 102 new CertificateType(KeyStores.Type.CERTS), 102 103 new CertificateType(KeyStores.Type.JSSE_CERTS), 104 new CertificateType(KeyStores.Type.CLIENT_CERTS) 103 105 }; 104 106 … … 302 304 } 303 305 306 private char[] getPassword(final String label) { 307 JPasswordField jpf = new JPasswordField(); 308 int result = JOptionPane.showConfirmDialog(parent, 309 new Object[]{label, jpf}, R("CVPasswordTitle"), 310 JOptionPane.OK_CANCEL_OPTION, 311 JOptionPane.INFORMATION_MESSAGE); 312 if (result == JOptionPane.OK_OPTION) 313 return jpf.getPassword(); 314 else 315 return null; 316 } 317 304 318 /** Allows storing KeyStores.Types in a JComponent */ 305 319 private static class CertificateType { … … 365 379 try { 366 380 KeyStore ks = keyStore; 367 CertificateUtils.addToKeyStore(chooser.getSelectedFile(), ks); 381 if (currentKeyStoreType == KeyStores.Type.CLIENT_CERTS) { 382 char[] password = getPassword(R("CVImportPasswordMessage")); 383 if (password != null) { 384 CertificateUtils.addPKCS12ToKeyStore( 385 chooser.getSelectedFile(), ks, password); 386 } else { 387 return; 388 } 389 } else { 390 CertificateUtils.addToKeyStore(chooser.getSelectedFile(), ks); 391 } 368 392 File keyStoreFile = new File(KeyStores 369 393 .getKeyStoreLocation(currentKeyStoreLevel, currentKeyStoreType)); … … 409 433 .get(selectedRow)); 410 434 if (alias != null) { 411 Certificate c = keyStore.getCertificate(alias); 412 PrintStream ps = new PrintStream(chooser.getSelectedFile().getAbsolutePath()); 413 CertificateUtils.dump(c, ps); 435 if (currentKeyStoreType == KeyStores.Type.CLIENT_CERTS) { 436 char[] password = getPassword(R("CVExportPasswordMessage")); 437 if (password != null) 438 CertificateUtils.dumpPKCS12(alias, chooser.getSelectedFile(), keyStore, password); 439 } else { 440 Certificate c = keyStore.getCertificate(alias); 441 PrintStream ps = new PrintStream(chooser.getSelectedFile().getAbsolutePath()); 442 CertificateUtils.dump(c, ps); 443 } 414 444 repopulateTables(); 415 445 } -
trunk/icedtea-web/netx/net/sourceforge/jnlp/security/viewer/CertificateViewer.java
r348 r418 52 52 53 53 import net.sourceforge.jnlp.runtime.JNLPRuntime; 54 import net.sourceforge.jnlp.util.ImageResources; 54 55 55 56 public class CertificateViewer extends JDialog { … … 62 63 public CertificateViewer() { 63 64 super((Frame) null, dialogTitle, true); 65 setIconImages(ImageResources.INSTANCE.getApplicationImages()); 64 66 65 67 Container contentPane = getContentPane(); -
trunk/icedtea-web/netx/net/sourceforge/jnlp/services/ServiceUtil.java
r348 r418 236 236 Object... extras) { 237 237 238 if (app == null) 239 app = JNLPRuntime.getApplication(); 240 241 boolean codeTrusted = true; 242 243 StackTraceElement[] stack = Thread.currentThread().getStackTrace(); 244 245 for (int i = 0; i < stack.length; i++) { 246 247 Class c = null; 248 249 try { 250 c = Class.forName(stack[i].getClassName()); 251 } catch (Exception e1) { 252 try { 253 c = Class.forName(stack[i].getClassName(), false, app.getClassLoader()); 254 } catch (Exception e2) { 255 System.err.println(e2.getMessage()); 256 } 257 } 258 259 // Everything up to the desired class/method must be trusted 260 if (c == null || // class not found 261 (c.getProtectionDomain().getCodeSource() != null && // class is not in bootclasspath 262 c.getProtectionDomain().getCodeSource().getCodeSigners() == null) // class is trusted 263 ) { 264 codeTrusted = false; 265 } 266 } 267 268 if (!codeTrusted) { 238 boolean trusted = isSigned(app); 239 240 if (!trusted) { 269 241 270 242 if (!shouldPromptUser()) { 271 243 return false; 272 244 } 245 if (app == null) 246 app = JNLPRuntime.getApplication(); 273 247 274 248 final AccessType tmpType = type; … … 308 282 }); 309 283 } 284 285 /** 286 * Returns whether the app requesting a JNLP service is a trusted 287 * application 288 * 289 * @param app 290 * the application which is requesting the check. If null, the 291 * current application is used. 292 * @return true, if the app is a trusted application; false otherwise 293 */ 294 295 public static boolean isSigned(ApplicationInstance app) { 296 297 if (app == null) 298 app = JNLPRuntime.getApplication(); 299 300 StackTraceElement[] stack = Thread.currentThread().getStackTrace(); 301 302 for (int i = 0; i < stack.length; i++) { 303 304 Class c = null; 305 306 try { 307 c = Class.forName(stack[i].getClassName()); 308 } catch (Exception e1) { 309 try { 310 c = Class.forName(stack[i].getClassName(), false, 311 app.getClassLoader()); 312 } catch (Exception e2) { 313 System.err.println(e2.getMessage()); 314 } 315 } 316 317 // Everything up to the desired class/method must be trusted 318 if (c == null || // class not found 319 (c.getProtectionDomain().getCodeSource() != null && // class is not in bootclasspath 320 c.getProtectionDomain().getCodeSource().getCodeSigners() == null) // class is trusted 321 ) { 322 return false; 323 } 324 } 325 return true; 326 } 310 327 311 328 } -
trunk/icedtea-web/netx/net/sourceforge/jnlp/services/XPersistenceService.java
r348 r418 53 53 54 54 URL source = app.getJNLPFile().getCodeBase(); 55 56 if (!source.getHost().equalsIgnoreCase(location.getHost()) 57 && !ServiceUtil.isSigned(app)) // Allow trusted application to have access to data from a different host 58 throw new MalformedURLException( 59 "Untrusted application cannot access data from a different host."); 55 60 56 if (!source.getHost().equalsIgnoreCase(location.getHost()))57 throw new MalformedURLException("Cannot access data from a different host.");58 61 59 62 // test for above codebase, not perfect but works for now … … 70 73 } 71 74 72 if (!source.getFile().startsWith(requestPath)) 73 throw new MalformedURLException("Cannot access data below source URL path."); 75 if (!source.getFile().startsWith(requestPath) 76 && !ServiceUtil.isSigned(app)) // Allow trusted application to have access to data below source URL path 77 throw new MalformedURLException( 78 "Cannot access data below source URL path."); 74 79 } 75 80 … … 123 128 124 129 File file = toCacheFile(location); 125 if (!file.exists()) 130 if (!file.exists()) { 126 131 throw new FileNotFoundException("Persistence store for " 127 132 + location.toString() + " is not found."); 133 } 128 134 FileUtils.createParentDir(file, "Persistence store for " 129 135 + location.toString()); -
trunk/icedtea-web/netx/net/sourceforge/jnlp/tools/KeyStoreUtil.java
r348 r418 34 34 35 35 // Class and methods marked as public so that they can be 36 // accessed by Jar Signer, which although lies in a package36 // accessed by JarCertVerifier, which although lies in a package 37 37 // with the same name, but bundled in tools.jar and loaded 38 38 // by another class loader, hence in a different *runtime* -
trunk/icedtea-web/netx/net/sourceforge/jnlp/util/BasicExceptionDialog.java
r348 r418 83 83 JOptionPane optionPane = new JOptionPane(mainPanel, JOptionPane.ERROR_MESSAGE); 84 84 final JDialog errorDialog = optionPane.createDialog(R("Error")); 85 errorDialog.setIconImages(ImageResources.INSTANCE.getApplicationImages()); 85 86 86 87 final JPanel quickInfoPanel = new JPanel(); -
trunk/icedtea-web/netx/net/sourceforge/jnlp/util/PropertiesFile.java
r348 r418 36 36 /** the header string */ 37 37 String header = "netx file"; 38 39 /** lazy loaded on getProperty */40 boolean loaded = false;38 39 /** time of last modification, lazy loaded on getProperty */ 40 long lastStore; 41 41 42 42 /** … … 65 65 */ 66 66 public String getProperty(String key) { 67 if ( !loaded)67 if (lastStore == 0) 68 68 load(); 69 69 … … 76 76 */ 77 77 public String getProperty(String key, String defaultValue) { 78 if ( !loaded)78 if (lastStore == 0) 79 79 load(); 80 80 … … 88 88 */ 89 89 public Object setProperty(String key, String value) { 90 if ( !loaded)90 if (lastStore == 0) 91 91 load(); 92 92 … … 105 105 * loaded; call this method before calling any method defined by 106 106 * a superclass. 107 * 108 * @return true, if file was (re-)loaded 109 * false, if file was still current 107 110 */ 108 public void load() { 109 loaded = true; 111 public boolean load() { 110 112 111 InputStream s = null; 112 try { 113 if (!file.exists()) 114 return; 113 if (!file.exists()) { 114 return false; 115 } 115 116 117 long currentStore = file.lastModified(); 118 long currentTime = System.currentTimeMillis(); 119 120 /* (re)load file, if 121 * - it wasn't loaded/stored, yet (lastStore == 0) 122 * - current file modification timestamp has changed since last store (currentStore != lastStore) OR 123 * - current file modification timestamp has not changed since last store AND current system time equals current file modification timestamp 124 * This is necessary because some filesystems seems only to provide accuracy of the timestamp on the level of seconds! 125 */ 126 if(lastStore == 0 || currentStore != lastStore || (currentStore == lastStore && currentStore / 1000 == currentTime / 1000)) { 127 InputStream s = null; 116 128 try { 117 s = new FileInputStream(file); 118 load(s); 119 } finally { 120 if (s != null) s.close(); 129 130 try { 131 s = new FileInputStream(file); 132 load(s); 133 } finally { 134 if (s != null) { 135 s.close(); 136 lastStore=currentStore; 137 return true; 138 } 139 } 140 } catch (IOException ex) { 141 ex.printStackTrace(); 121 142 } 122 } catch (IOException ex) {123 ex.printStackTrace();124 143 } 144 145 return false; 125 146 } 126 147 … … 129 150 */ 130 151 public void store() { 131 if (!loaded)132 return; // nothing could have changed so save unnecessary load/save133 152 134 OutputStream s = null;153 FileOutputStream s = null; 135 154 try { 136 155 try { 156 file.getParentFile().mkdirs(); 137 157 s = new FileOutputStream(file); 138 158 store(s, header); 159 160 // fsync() 161 s.getChannel().force(true); 162 lastStore = file.lastModified(); 139 163 } finally { 140 164 if (s != null) s.close(); -
trunk/icedtea-web/netx/net/sourceforge/nanoxml/XMLElement.java
r348 r418 1167 1167 * xml file. 1168 1168 */ 1169 public void sanitizeInput( InputStreamReader isr, PipedOutputStream pout) {1169 public void sanitizeInput(Reader isr, OutputStream pout) { 1170 1170 try { 1171 1171 PrintStream out = new PrintStream(pout); … … 1221 1221 this.sanitizeCharReadTooMuch = next; 1222 1222 1223 // If the next char is a ? or !, then we've hit a specialtag,1223 // If the next chars are !--, then we've hit a comment tag, 1224 1224 // and should skip it. 1225 if (prev == '<' && (next == '!' || next == '?')) { 1226 this.skipSpecialTag(0); 1227 this.sanitizeCharReadTooMuch = '\0'; 1225 if (ch == '<' && sanitizeCharReadTooMuch == '!') { 1226 ch = (char) this.reader.read(); 1227 if (ch == '-') { 1228 ch = (char) this.reader.read(); 1229 if (ch == '-') { 1230 this.skipComment(); 1231 this.sanitizeCharReadTooMuch = '\0'; 1232 } else { 1233 out.print('<'); 1234 out.print('!'); 1235 out.print('-'); 1236 this.sanitizeCharReadTooMuch = ch; 1237 if (JNLPRuntime.isDebug()) { 1238 System.out.print('<'); 1239 System.out.print('!'); 1240 System.out.print('-'); 1241 } 1242 } 1243 } else { 1244 out.print('<'); 1245 out.print('!'); 1246 this.sanitizeCharReadTooMuch = ch; 1247 if (JNLPRuntime.isDebug()) { 1248 System.out.print('<'); 1249 System.out.print('!'); 1250 } 1251 } 1228 1252 } 1229 1253 // Otherwise we haven't hit a comment, and we should write ch.
Note:
See TracChangeset
for help on using the changeset viewer.