reorganized file layout (part 2: edits) RC4
authoradam <adam@megacz.com>
Mon, 12 Apr 2004 07:48:10 +0000 (07:48 +0000)
committeradam <adam@megacz.com>
Mon, 12 Apr 2004 07:48:10 +0000 (07:48 +0000)
darcs-hash:20040412074810-5007d-4ba54bb6fa3b33da53ad47735219dc3051d1d260.gz

44 files changed:
Makefile
Makefile.upstream
src/org/ibex/core/Box.java
src/org/ibex/core/Ibex.java
src/org/ibex/core/LocalStorage.java
src/org/ibex/core/Main.java
src/org/ibex/core/Template.java
src/org/ibex/graphics/Affine.java [new file with mode: 0644]
src/org/ibex/graphics/Color.java [new file with mode: 0644]
src/org/ibex/graphics/Font.java
src/org/ibex/graphics/Freetype.c
src/org/ibex/graphics/GIF.java
src/org/ibex/graphics/HTML.java [moved from src/org/ibex/util/HTML.java with 99% similarity]
src/org/ibex/graphics/PNG.java
src/org/ibex/graphics/Paint.java [new file with mode: 0644]
src/org/ibex/graphics/Path.java
src/org/ibex/graphics/Picture.java
src/org/ibex/graphics/PixelBuffer.java
src/org/ibex/graphics/SVG.java
src/org/ibex/graphics/Surface.java
src/org/ibex/js/JS.java
src/org/ibex/js/JSFunction.java
src/org/ibex/js/Stream.java
src/org/ibex/net/HTTP.java
src/org/ibex/net/SOAP.java
src/org/ibex/net/XMLRPC.java
src/org/ibex/plat/AWT.java
src/org/ibex/plat/Darwin.java
src/org/ibex/plat/GCJ.java
src/org/ibex/plat/JVM.java
src/org/ibex/plat/Java2.java
src/org/ibex/plat/Linux.java
src/org/ibex/plat/OpenGL.java
src/org/ibex/plat/POSIX.java
src/org/ibex/plat/PalmOS.java
src/org/ibex/plat/Platform.java
src/org/ibex/plat/Win32.java
src/org/ibex/plat/X11.java
src/org/ibex/util/BalancedTree.java
src/org/ibex/util/EjAlbertBrowserLauncher.java [new file with mode: 0644]
src/org/ibex/util/MSPack.java
src/org/ibex/util/SSL.java [deleted file]
src/org/ibex/util/Scheduler.java
src/org/ibex/util/Task.java [new file with mode: 0644]

index 8a452d6..a67c9e5 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -20,7 +20,7 @@ all:         Java2 Linux Win32 Darwin Solaris
 
 clean:      ; rm -rf build; rm .preprocessor
 dist-clean:
-       rm -rf .jikes .configure* .install* build .compile .build*
+       rm -rf .configure* .install* build .compile .build*
        find upstream -name config.cache -exec rm {} \;
        test -e upstream/nestedvm && make -C upstream/nestedvm clean
        rm .install_nestedvm
@@ -57,7 +57,7 @@ target_bin_extension_Java2       := jar
 target_bin_extension             := $(target_bin_extension_$(platform))
 target_bin                       := ibex.$(target_bin_extension)
 
-jikes_flags        := -nowarn
+javac   := javac -classpath upstream/bcel-5.1/src/bcel-5.1.jar:build/class -d build/class/ -sourcepath build/java/:upstream/mips:upstream/mips/build:src
 gcc_optimizations  := -Os
 #gcc_optimizations  := -O9 -ffast-math -fomit-frame-pointer -foptimize-sibling-calls
 #gcc_optimizations  += -finline-functions -funroll-loops -ffunction-sections -fdata-sections
@@ -114,38 +114,42 @@ java_sources              += build/java/org/xwt/mips/UsermodeConstants.java
 java_classes              := $(java_sources:build/java/%.java=build/class/%.class)
 java_classes              += build/class/gnu/regexp/CharUnit.class build/class/gnu/regexp/IntPair.class
 
-build/java/org/xwt/mips/%: .install_nestedvm
-       mkdir -p build/java/org/xwt/mips
-       cd build/java/org/xwt/mips; ln -sf ../../../../../upstream/nestedvm/src/org/xwt/mips/* .
-       cd build/java/org/xwt/mips; ln -sf ../../../../../upstream/nestedvm/build/org/xwt/mips/*.java .
-
-
 ### Java Source Files ##############################################################################
 
+build/java/gnu/regexp: .download_gnu.regexp-1.1.4
+       mkdir -p $(@D); cd $(@D); ln -sf ../../../upstream/gnu.regexp-1.1.4/src/src/gnu/regexp
+build/java/org/xwt/mips: .download_nestedvm
+       mkdir -p $(@D); cd $(@D); ln -sf ../../../../upstream/nestedvm/src/org/xwt/mips
+build/java/org/ibex/crypto: .download_org.ibex.crypto
+       mkdir -p $(@D); cd $(@D); ln -sf ../../../../upstream/org.ibex.crypto/src/org/ibex/crypto
+       mkdir -p build/java/org/ibex/net;
+       cd build/java/org/ibex/net; ln -sf ../../../../../upstream/org.ibex.crypto/src/org/ibex/net/SSL.java
+       cd build/java/org/ibex/net; ln -sf ../../../../../upstream/org.ibex.crypto/src/org/ibex/net/ssl
+
 ifeq ($(platform),Java2)
-.preprocessor: src/org/ibex/util/Preprocessor.java src/org/ibex/util/Vec.java src/gnu/regexp/*.java
-       @make .jikes
+.preprocessor: build/java/gnu/regexp src/org/ibex/util/Preprocessor.java src/org/ibex/util/Vec.java build/java/org/xwt/mips build/java/org/ibex/crypto
+
        @mkdir -p build/class/org/ibex/util build/class/gnu/regexp
-       ./.jikes $^ -d build/class
+       $(javac) src/org/ibex/util/Preprocessor.java src/org/ibex/util/Vec.java build/java/gnu/regexp/*.java  -d build/class
        @touch $@
 else
-.preprocessor: src/org/ibex/util/Preprocessor.java src/org/ibex/util/Vec.java src/gnu/regexp/*.java
+.preprocessor: build/java/gnu/regexp src/org/ibex/util/Preprocessor.java src/org/ibex/util/Vec.java build/java/org/xwt/mips build/java/org/ibex/crypto
        @mkdir -p build/class/org/ibex/util build/class/gnu/regexp
-       $(gcj) -Isrc -C $^ -d build/class
+       $(gcj) -Isrc -C src/org/ibex/util/Preprocessor.java src/org/ibex/util/Vec.java build/java/gnu/regexp/*.java  -d build/class
        @touch $@
 endif
 build/cc/%.cc:     src/%.c    ; @echo linking $@; mkdir -p $(@D); ln -fs `echo $(@D)/ | sed 's_[^/]*//*_../_g'`/$< $@
 build/res/%:       src/%      ; @echo linking $@; mkdir -p $(@D); ln -fs `echo $(@D)/ | sed 's_[^/]*//*_../_g'`/$< $@
 build/java/org/ibex/%.java: src/org/ibex/%.java .preprocessor
        @echo -e "\n\033[1mpreprocessing      .java -> .java:  $<\033[0m"
-       mkdir -p `dirname $@`; java -cp build/class org.ibex.util.Preprocessor < $^ > $@
+       mkdir -p `dirname $@`; java -cp build/class:build/java org.ibex.util.Preprocessor < $^ > $@
 build/java/%.java: src/%.java ; @echo linking $@; mkdir -p $(@D); ln -fs `echo $(@D)/ | sed 's_[^/]*//*_../_g'`/$< $@
 
 
 ### Java Class Files ##############################################################################
 
-build/class/org/ibex/translators/MIPSApps.class: build/mips/mipsapps.mips .install_nestedvm .jikes
-       mkdir -p build/java/org/ibex/translators
+build/class/org/ibex/util/MIPSApps.class: build/mips/mipsapps.mips .install_nestedvm 
+       mkdir -p build/java/org/ibex/util
        @echo -e "\n\033[1mtranslating        .mips -> .class:  $<\033[0m"
        java -cp upstream/nestedvm/build:upstream/nestedvm/upstream/build/bcel-5.1/bcel-5.1.jar \
                org.xwt.mips.Compiler org.ibex.translators.MIPSApps $< -outfile $@
@@ -155,10 +159,10 @@ compile: .compile
 .compile: .download_nestedvm .download_bcel-5.1 $(java_sources) $(java_classes); touch $@
 
 ifeq ($(platform),Java2)
-build/class/%.class: build/java/%.java .preprocessor .jikes
+build/class/%.class: build/java/%.java .preprocessor
        @echo -e "\n\033[1mcompiling          .java -> .class: $<\033[0m"
        mkdir -p build/class
-       @./.jikes $< -d build/class
+       @$(javac) $< -d build/class
 else
 build/class/%.class: build/java/%.java
        @echo -e "\n\033[1mcompiling          .java -> .class: $<\033[0m"
@@ -166,7 +170,7 @@ build/class/%.class: build/java/%.java
        $(gcj) -I$(bcel_jar) -C -O0 $< -d build/class
 endif
 
-build/Java2/ibex.jar: .compile build/res/builtin.jar build/class/org/ibex/translators/MIPSApps.class
+build/Java2/ibex.jar: .compile build/res/builtin.jar build/class/org/ibex/util/MIPSApps.class
        @echo -e "\n\033[1marchiving         .class -> .jar:   build/Java2/ibex.jar\033[0m"
        mkdir -p build/Java2
        echo -e "Manifest-Version: 1.0\nMain-Class: org.ibex.Main\n" > build/Java2/.manifest
@@ -286,7 +290,7 @@ endif
 
 ### Builtin Resources ##############################################################################
 
-builtin_src := $(shell find src/org/ibex/builtin -name '*.*' \! -name '*.xcf')
+builtin_src := $(shell find src/org/ibex/core/builtin -name '*.*' \! -name '*.xcf')
 build/res/fonts/vera: .download_vera-1.10
        mkdir -p build/res/fonts/vera
        cd build/res/fonts/vera; ln -fs ../../../../upstream/vera-1.10/ttf-bitstream-vera-1.10/Vera.ttf
@@ -294,7 +298,7 @@ build/res/fonts/vera: .download_vera-1.10
        cd build/res/fonts/vera; ln -fs ../../../../upstream/vera-1.10/ttf-bitstream-vera-1.10/VeraSe.ttf
 build/res/builtin.jar: $(builtin_src:src/%=build/res/%) build/res/fonts/vera
        @echo -e "\n\033[1mzipping            res/* -> .jar: builtin.jar\033[0m"
-       cd build/res; $(jar) cf builtin.jar org/ibex/builtin/scar.png fonts
+       cd build/res; $(jar) cf builtin.jar org/ibex/core/builtin/scar.png fonts
 build/$(platform)/builtin.o: build/res/builtin.jar
        @echo -e "\n\033[1mwrapping            .jar -> .o: resources.o\033[0m"
        @mkdir -p $(@D)
@@ -316,7 +320,7 @@ build/mips/%.c.o: src/%.c .download_libmspack-20030726 .install_nestedvm
                -Iupstream/libmspack-20030726/src/mspack \
                -c -o $@ $<
 
-build/mips/mipsapps.mips: build/mips/org/ibex/translators/Freetype.c.o build/mips/org/ibex/translators/MSPack.c.o build/mips/org/ibex/translators/main.c.o 
+build/mips/mipsapps.mips: build/mips/org/ibex/graphics/Freetype.c.o build/mips/org/ibex/util/MSPack.c.o
        make .install_freetype-2.1.4_mips-unknown-elf target=mips-unknown-elf
        make .install_libmspack-20030726_mips-unknown-elf target=mips-unknown-elf
        @echo -e "\n\033[1mlinking               .o -> .mips:  $@\033[0m"
index 17722ac..fb677cb 100644 (file)
@@ -13,11 +13,11 @@ url_mingw-runtime-3.0  := http://unc.dl.sourceforge.net/sourceforge/mingw/mingw-
 url_freetype-2.1.4     := http://unc.dl.sourceforge.net/sourceforge/freetype/freetype-2.1.4.tar.gz
 url_gcc-3.3            := http://mirrors.rcn.net/pub/sourceware/gcc/releases/gcc-3.3/gcc-3.3.tar.gz 
 url_jpeg-6b            := http://www.ijg.org/files/jpegsrc.v6b.tar.gz
-url_jikes-1.18         := http://dist.xwt.org/jikes-1.18.tgz
 url_libmspack-20030726 := http://www.kyz.uklinux.net/downloads/libmspack-20030726.tar.gz
 url_vera-1.10          := http://fgo-temp.acc.umu.se/pub/GNOME/sources/ttf-bitstream-vera/1.10/ttf-bitstream-vera-1.10.tar.gz
 url_WindowMaker-0.80.2 := http://windowmaker.org/pub/source/release/WindowMaker-0.80.2.tar.gz
 url_bcel-5.1           := http://www.apache.org/dist/jakarta/bcel/binaries/bcel-5.1.tar.gz
+url_gnu.regexp-1.1.4   := ftp://ftp.tralfamadore.com/pub/java/gnu.regexp-1.1.4.tar.gz
 
 .install_binutils-2.13.2.1_powerpc-apple-darwin: .vendor
        rm -rf upstream/darwin-linker/src
@@ -121,6 +121,11 @@ environment_gcc_3.3_$(target)           += PATH=$(shell pwd)/upstream/install/bi
        touch .install_gcc-3.3_mips-unknown-elf
        touch .install_binutils-2.13.2.1_mips-unknown-elf
 
+.download_org.ibex.crypto:
+       mkdir -p upstream/org.ibex.crypto
+       cd upstream/org.ibex.crypto; wget -l 99 -nH -r http://crypto.ibex.org/
+       touch $@
+
 # vendor-supplied binaries and headers; this is stuff that comes with various OSes
 vendor: .vendor; @true
 .vendor:
@@ -226,24 +231,5 @@ endif
                make $(make_install_$*_$(target)) install $(setcc) $(environment_$*_$(target))
        touch $@
 
-# jikes has a special target to autodetect a pre-installed jikes, and to autodetect the JVM's $CLASSPATH
-.jikes:
-       @echo -e "\n\033[1mdetecting your jikes installation...\033[0m"
-       echo "#!/bin/sh" > .jikes
-ifeq ($(shell javac -version 2>&1 | head -n 1),javac 1.5.0-beta)
-       echo -n 'PATH=upstream/install/bin:$$PATH javac -classpath upstream/bcel-5.1/src/bcel-5.1.jar:build/class $$@ -d build/class/ -sourcepath build/java/:upstream/mips:upstream/mips/build:src' >> .jikes
-else
-       echo -n 'PATH=upstream/install/bin:$$PATH jikes -classpath upstream/bcel-5.1/src/bcel-5.1.jar:build/class $$@ -d build/class/ -sourcepath build/java/:upstream/mips:upstream/mips/build:src ' >> .jikes
-       (type jikes && (jikes --version | grep "Version 1.18")) || make .install_jikes-1.18_ target=
-       echo -n "$(jikes_flags) -bootclasspath " >> .jikes
-       echo "public class GetBootClassPath { public static void main(String[] s) { " > GetBootClassPath.java
-       echo "System.out.println(System.getProperty(\"sun.boot.class.path\")); } }"  >> GetBootClassPath.java
-       javac GetBootClassPath.java
-       java -cp . GetBootClassPath >> .jikes
-       rm GetBootClassPath.*
-endif
-       echo 'EXIT=$$?' >> .jikes
-       echo 'exit $$EXIT' >> .jikes
-       mv .jikes .jikes+
-       cp .jikes+ .jikes
-       chmod +x .jikes
+
+
index c898d8e..f333abb 100644 (file)
@@ -1,6 +1,6 @@
 // FIXME
 // Copyright 2004 Adam Megacz, see the COPYING file for licensing [GPL]
-package org.ibex;
+package org.ibex.core;
 
 // FIXME: are traps on x/y meaningful?
 // FIXME: if we trap on cols, then set rows to 0 (forcing cols to 1), does the cols trap get triggered?
@@ -17,7 +17,7 @@ package org.ibex;
 import java.util.*;
 import org.ibex.js.*;
 import org.ibex.util.*;
-import org.ibex.translators.*;
+import org.ibex.graphics.*;
 
 /**
  *  <p>
@@ -38,7 +38,7 @@ import org.ibex.translators.*;
  *  trigger a Surface.abort; if rendering were done in the same pass,
  *  rendering work done prior to the Surface.abort would be wasted.
  */
-public final class Box extends JSScope implements Scheduler.Task {
+public final class Box extends JSScope implements Task {
 
     // Macros //////////////////////////////////////////////////////////////////////
 
@@ -52,7 +52,7 @@ public final class Box extends JSScope implements Scheduler.Task {
     //#define CHECKSET_BOOLEAN(prop) boolean nu = toBoolean(value); if (nu == prop) break; prop = nu;
     //#define CHECKSET_STRING(prop) if ((value==null&&prop==null)||(value!=null&&JS.toString(value).equals(prop))) break; prop=JS.toString(value);
 
-    protected Box() { super(null); }
+    public Box() { super(null); }
 
     // FIXME memory leak
     static Hash boxToCursor = new Hash(500, 3);
@@ -128,9 +128,9 @@ public final class Box extends JSScope implements Scheduler.Task {
 
     /*
     private VectorGraphics.VectorPath path = null;
-    private VectorGraphics.Affine transform = null;
+    private Affine transform = null;
     private VectorGraphics.RasterPath rpath = null;
-    private VectorGraphics.Affine rtransform = null;
+    private Affine rtransform = null;
     */
 
     //#define DIRTY dirty()
@@ -172,11 +172,11 @@ public final class Box extends JSScope implements Scheduler.Task {
     // Reflow ////////////////////////////////////////////////////////////////////////////////////////
 
     /** should only be invoked on the root box */
-    void reflow() { pack(); resize(x, y, maxwidth, maxheight); place(); }
+    public void reflow() { pack(); resize(x, y, maxwidth, maxheight); place(); }
 
     private static Box[] frontier = new Box[65535];
     /** pack the boxes into rows and columns, compute contentwidth */
-    void pack() {
+    public void pack() {
         if (!test(REPACK)) { constrain(); return; }
         boolean haskid = false;
         for(Box child = getChild(0); child != null; child = child.nextSibling()) { haskid = true; child.pack(); }
@@ -390,7 +390,7 @@ public final class Box extends JSScope implements Scheduler.Task {
     // Rendering Pipeline /////////////////////////////////////////////////////////////////////
 
     /** Renders self and children within the specified region. All rendering operations are clipped to xIn,yIn,wIn,hIn */
-    void render(int parentx, int parenty, int cx1, int cy1, int cx2, int cy2, PixelBuffer buf, VectorGraphics.Affine a) {
+    public void render(int parentx, int parenty, int cx1, int cy1, int cx2, int cy2, PixelBuffer buf, Affine a) {
         if (!test(VISIBLE)) return;
         int globalx = parentx + (parent == null ? 0 : x);
         int globaly = parenty + (parent == null ? 0 : y);
@@ -463,9 +463,9 @@ public final class Box extends JSScope implements Scheduler.Task {
         case "distanceto": return METHOD;
         case "text": return text;
         case "path": throw new JSExn("cannot read from the path property");
-        case "fill": return colorToString(fillcolor);
-        case "strokecolor": return colorToString(strokecolor);
-        case "textcolor": return colorToString(strokecolor);
+        case "fill": return Color.colorToString(fillcolor);
+        case "strokecolor": return Color.colorToString(strokecolor);
+        case "textcolor": return Color.colorToString(strokecolor);
         case "font": return font == null ? null : font.stream;
         case "fontsize": return font == null ? N(10) : N(font.pointsize);
         case "strokewidth": return N(strokewidth);
@@ -539,8 +539,8 @@ public final class Box extends JSScope implements Scheduler.Task {
         //#switch(name)
         case "thisbox":     if (value == null) removeSelf();
         case "text":        if (value == null) value = ""; CHECKSET_STRING(text); RECONSTRAIN(); DIRTY;
-        case "strokecolor": value = N(stringToColor((String)value)); CHECKSET_INT(strokecolor); DIRTY;
-        case "textcolor":   value = N(stringToColor((String)value)); CHECKSET_INT(strokecolor); DIRTY;
+        case "strokecolor": value = N(Color.stringToColor((String)value)); CHECKSET_INT(strokecolor); DIRTY;
+        case "textcolor":   value = N(Color.stringToColor((String)value)); CHECKSET_INT(strokecolor); DIRTY;
         case "strokewidth": CHECKSET_SHORT(strokewidth); DIRTY;
         case "shrink":      CHECKSET_FLAG(HSHRINK | VSHRINK); RECONSTRAIN();
         case "hshrink":     CHECKSET_FLAG(HSHRINK); RECONSTRAIN();
@@ -695,7 +695,7 @@ public final class Box extends JSScope implements Scheduler.Task {
             texture = null;
             fillcolor = 0;
         } else if (value instanceof String) {
-            int newfillcolor = stringToColor((String)value);
+            int newfillcolor = Color.stringToColor((String)value);
             if (newfillcolor == fillcolor) return;
             fillcolor = newfillcolor;
             texture = null;
@@ -761,34 +761,6 @@ public final class Box extends JSScope implements Scheduler.Task {
                     putAndTriggerTrapsAndCatchExceptions(name.substring(1), value);
     }
 
-    private static int stringToColor(String s) {
-        // FIXME support three-char strings by doubling digits
-        if (s == null) return 0x00000000;
-        else if (SVG.colors.get(s) != null) return 0xFF000000 | toInt(SVG.colors.get(s));
-        else if (s.length() == 7 && s.charAt(0) == '#') try {
-            // FEATURE  alpha
-            return 0xFF000000 |
-                (Integer.parseInt(s.substring(1, 3), 16) << 16) |
-                (Integer.parseInt(s.substring(3, 5), 16) << 8) |
-                Integer.parseInt(s.substring(5, 7), 16);
-        } catch (NumberFormatException e) {
-            Log.info(Box.class, "invalid color " + s);
-            return 0;
-        }
-        else return 0; // FEATURE: error?
-    }
-
-    private static String colorToString(int argb) {
-        if ((argb & 0xFF000000) == 0) return null;
-        String red = Integer.toHexString((argb & 0x00FF0000) >> 16);
-        String green = Integer.toHexString((argb & 0x0000FF00) >> 8);
-        String blue = Integer.toHexString(argb & 0x000000FF);
-        if (red.length() < 2) red = "0" + red;
-        if (blue.length() < 2) blue = "0" + blue;
-        if (green.length() < 2) green = "0" + green;
-        return "#" + red + green + blue;
-    }
-
     /** figures out what box in this subtree of the Box owns the pixel at x,y relitave to the Surface */
     public static Box whoIs(Box cur, int x, int y) {
 
@@ -862,7 +834,7 @@ public final class Box extends JSScope implements Scheduler.Task {
 
     // Tree Manipulation /////////////////////////////////////////////////////////////////////
 
-    void removeSelf() {
+    public void removeSelf() {
         if (parent != null) { parent.removeChild(parent.indexNode(this)); return; }
         Surface surface = Surface.fromBox(this); 
         if (surface != null) surface.dispose(true);
@@ -936,8 +908,8 @@ public final class Box extends JSScope implements Scheduler.Task {
             putAndTriggerTrapsAndCatchExceptions("ChildChange", b);
         }
     }
-
-    void putAndTriggerTrapsAndCatchExceptions(Object name, Object val) {
+    
+    public void putAndTriggerTrapsAndCatchExceptions(Object name, Object val) {
         try {
             putAndTriggerTraps(name, val);
         } catch (JSExn e) {
index d97a9d5..011b9bb 100644 (file)
@@ -1,10 +1,13 @@
 // Copyright 2004 Adam Megacz, see the COPYING file for licensing [GPL]
-package org.ibex;
+package org.ibex.core;
 
 import java.io.*;
 import org.ibex.js.*;
 import org.ibex.util.*;
-import org.bouncycastle.util.encoders.Base64;
+import org.ibex.graphics.*;
+import org.ibex.plat.*;
+import org.ibex.net.*;
+import org.ibex.crypto.*;
 
 /** Singleton class that provides all functionality in the ibex.* namespace */
 public final class Ibex extends JS.Cloneable {
@@ -125,7 +128,7 @@ public final class Ibex extends JS.Cloneable {
 
     public void put(Object name, final Object value) throws JSExn {
         //#switch(name)
-        case "thread": Scheduler.add((Scheduler.Task)value); return;
+        case "thread": Scheduler.add((Task)value); return;
         case "ui.clipboard": Platform.setClipBoard((String)value); return;
         case "ui.frame": Platform.createSurface((Box)value, true, true); return;
         case "ui.window": Platform.createSurface((Box)value, false, true); return;
index 7c1d747..b523d24 100644 (file)
@@ -1,9 +1,9 @@
 // Copyright 2004 Adam Megacz, see the COPYING file for licensing [GPL]
-package org.ibex;
+package org.ibex.core;
 
 import java.io.*;
 import org.ibex.util.*;
-import org.bouncycastle.util.encoders.Base64;
+import org.ibex.crypto.*;
 
 /** Manages access to ~/.ibex */
 public class LocalStorage {
index 8003ada..72fd55a 100644 (file)
@@ -1,11 +1,13 @@
 // Copyright 2004 Adam Megacz, see the COPYING file for licensing [GPL]
-package org.ibex;
+package org.ibex.core;
 
 import java.net.*;
 import java.io.*;
 import java.util.*;
 import org.ibex.js.*;
 import org.ibex.util.*;
+import org.ibex.plat.*;
+import org.ibex.graphics.*;
 
 /** Entry point for the Ibex Engine; handles splash screen, initial xwar loading, and argument processing */
 public class Main {
@@ -24,7 +26,6 @@ public class Main {
     public static String initialTemplate = null;
     
     public static final Stream builtin = new Stream.Zip(new Stream.Builtin());
-    public static Picture scarImage = null;
 
     public static void printUsage() {
         System.err.println("Usage: ibex [-lawp] [ url | file | directory ]");
@@ -91,9 +92,9 @@ public class Main {
         if (Log.on) Log.info(Main.class, "loading xwar");
         final Ibex ibex = new Ibex(rr);
 
-        scarImage =
+        org.ibex.graphics.Surface.scarImage =
             Picture.load((Stream)Main.builtin.get("org/ibex/builtin/scar.png"),
-                         new Scheduler.Task() { public void perform() throws JSExn, UnknownHostException {
+                         new Task() { public void perform() throws JSExn, UnknownHostException {
                              if (Log.on) Log.info(Main.class, "invoking initial template");
                              ibex.resolveString(startupTemplate, false).call(new Box(), null, null, null, 1);
                          } });
index 2f3e2ac..6e29c4a 100644 (file)
@@ -1,5 +1,5 @@
 // Copyright 2004 Adam Megacz, see the COPYING file for licensing [GPL]
-package org.ibex;
+package org.ibex.core;
 
 import java.io.*;
 import java.util.*;
@@ -59,7 +59,7 @@ public class Template {
      *  @param pboxes a vector of all box parents on which to put $-references
      *  @param ptemplates a vector of the fileNames to recieve private references on the pboxes
      */
-    void apply(Box b) throws JSExn {
+    public void apply(Box b) throws JSExn {
         try {
             apply(b, null);
         } catch (IOException e) {
diff --git a/src/org/ibex/graphics/Affine.java b/src/org/ibex/graphics/Affine.java
new file mode 100644 (file)
index 0000000..31e2e2b
--- /dev/null
@@ -0,0 +1,128 @@
+// FIXME
+// Copyright 2004 Adam Megacz, see the COPYING file for licensing [GPL]
+package org.ibex.graphics;
+import java.util.*;
+
+/** an affine transform; all operations are destructive */
+public final class Affine {
+
+    //  [ a b e ]
+    //  [ c d f ]
+    //  [ 0 0 1 ]
+    public float a, b, c, d, e, f;
+
+    Affine(float _a, float _b, float _c, float _d, float _e, float _f) { a = _a; b = _b; c = _c; d = _d; e = _e; f = _f; }
+    public String toString() { return "[ " + a + ", " + b + ", " + c + ", " + d + ", " + e + ", " + f + " ]"; }
+    public Affine copy() { return new Affine(a, b, c, d, e, f); }
+    public static Affine identity() { return new Affine(1, 0, 0, 1, 0, 0); }
+    public static Affine scale(float sx, float sy) { return new Affine(sx, 0, 0, sy, 0, 0); }
+    public static Affine shear(float degrees) {
+        return new Affine(1, 0, (float)Math.tan(degrees * (float)(Math.PI / 180.0)), 1, 0, 0); }
+    public static Affine translate(float tx, float ty) { return new Affine(1, 0, 0, 1, tx, ty); }
+    public static Affine flip(boolean horiz, boolean vert) { return new Affine(horiz ? -1 : 1, 0, 0, vert ? -1 : 1, 0, 0); }
+    public float multiply_px(float x, float y) { return x * a + y * c + e; }
+    public float multiply_py(float x, float y) { return x * b + y * d + f; }
+    public boolean equalsIgnoringTranslation(Affine x) { return a == x.a && b == x.b && c == x.c && d == x.d; }
+
+    public boolean equals(Object o) {
+        if (!(o instanceof Affine)) return false;
+        Affine x = (Affine)o;
+        return a == x.a && b == x.b && c == x.c && d == x.d && e == x.e && f == x.f;
+    }
+
+    public static Affine rotate(float degrees) {
+        float s = (float)Math.sin(degrees * (float)(Math.PI / 180.0));
+        float c = (float)Math.cos(degrees * (float)(Math.PI / 180.0));
+        return new Affine(c, s, -s, c, 0, 0);
+    }
+
+    /** this = this * a */
+    public Affine multiply(Affine A) {
+        float _a = this.a * A.a + this.b * A.c;
+        float _b = this.a * A.b + this.b * A.d;
+        float _c = this.c * A.a + this.d * A.c;
+        float _d = this.c * A.b + this.d * A.d;
+        float _e = this.e * A.a + this.f * A.c + A.e;
+        float _f = this.e * A.b + this.f * A.d + A.f;
+        a = _a; b = _b; c = _c; d = _d; e = _e; f = _f;
+        return this;
+    }
+
+    public void invert() {
+        float det = 1 / (a * d - b * c);
+        float _a = d * det;
+        float _b = -1 * b * det;
+        float _c = -1 * c * det;
+        float _d = a * det;
+        float _e = -1 * e * a - f * c;
+        float _f = -1 * e * b - f * d;
+        a = _a; b = _b; c = _c; d = _d; e = _e; f = _f;
+    }
+
+    public static Affine parse(String t) {
+        if (t == null) return null;
+        t = t.trim();
+        Affine ret = Affine.identity();
+        while (t.length() > 0) {
+            if (t.startsWith("skewX(")) {
+                // FIXME
+                
+            } else if (t.startsWith("shear(")) {
+                // FIXME: nonstandard; remove this
+                ret.multiply(Affine.shear(Float.parseFloat(t.substring(t.indexOf('(') + 1, t.indexOf(')')))));
+                
+            } else if (t.startsWith("skewY(")) {
+                // FIXME
+                
+            } else if (t.startsWith("rotate(")) {
+                String sub = t.substring(t.indexOf('(') + 1, t.indexOf(')'));
+                if (sub.indexOf(',') != -1) {
+                    float angle = Float.parseFloat(sub.substring(0, sub.indexOf(',')));
+                    sub = sub.substring(sub.indexOf(',') + 1);
+                    float cx = Float.parseFloat(sub.substring(0, sub.indexOf(',')));
+                    sub = sub.substring(sub.indexOf(',') + 1);
+                    float cy = Float.parseFloat(sub);
+                    ret.multiply(Affine.translate(cx, cy));
+                    ret.multiply(Affine.rotate(angle));
+                    ret.multiply(Affine.translate(-1 * cx, -1 * cy));
+                } else {
+                    ret.multiply(Affine.rotate(Float.parseFloat(t.substring(t.indexOf('(') + 1, t.indexOf(')')))));
+                }
+                
+            } else if (t.startsWith("translate(")) {
+                String sub = t.substring(t.indexOf('(') + 1, t.indexOf(')'));
+                if (sub.indexOf(',') > -1) {
+                    ret.multiply(Affine.translate(Float.parseFloat(t.substring(t.indexOf('(') + 1, t.indexOf(','))),
+                                                                 Float.parseFloat(t.substring(t.indexOf(',') + 1, t.indexOf(')')))));
+                } else {
+                    ret.multiply(Affine.translate(Float.parseFloat(t.substring(t.indexOf('(') + 1, t.indexOf(','))), 0));
+                }
+                
+            } else if (t.startsWith("flip(")) {
+                String which = t.substring(t.indexOf('(') + 1, t.indexOf(')'));
+                ret.multiply(Affine.flip(which.equals("horizontal"), which.equals("vertical")));
+                
+            } else if (t.startsWith("scale(")) {
+                String sub = t.substring(t.indexOf('(') + 1, t.indexOf(')'));
+                if (sub.indexOf(',') > -1) {
+                    ret.multiply(Affine.scale(Float.parseFloat(t.substring(t.indexOf('(') + 1, t.indexOf(','))),
+                                                             Float.parseFloat(t.substring(t.indexOf(',') + 1, t.indexOf(')')))));
+                } else {
+                    ret.multiply(Affine.scale(Float.parseFloat(t.substring(t.indexOf('(') + 1, t.indexOf(','))),
+                                                             Float.parseFloat(t.substring(t.indexOf('(') + 1, t.indexOf(',')))));
+                }
+                
+            } else if (t.startsWith("matrix(")) {
+                // FIXME: is this mapped right?
+                float d[] = new float[6];
+                StringTokenizer st = new StringTokenizer(t, ",", false);
+                for(int i=0; i<6; i++)
+                    d[i] = Float.parseFloat(st.nextToken());
+                ret.multiply(new Affine(d[0], d[1], d[2], d[3], d[4], d[5]));
+            }
+            t = t.substring(t.indexOf(')') + 1).trim();
+        }
+        return ret;
+    }
+    
+}
diff --git a/src/org/ibex/graphics/Color.java b/src/org/ibex/graphics/Color.java
new file mode 100644 (file)
index 0000000..210aade
--- /dev/null
@@ -0,0 +1,187 @@
+// Copyright 2002 Adam Megacz, see the COPYING file for licensing [GPL]
+package org.ibex.graphics;
+import java.util.*;
+import org.ibex.util.*;
+
+public class Color {
+    
+    public static int stringToColor(String s) {
+        // FIXME support three-char strings by doubling digits
+        if (s == null) return 0x00000000;
+        else if (standard.get(s) != null) return 0xFF000000 | org.ibex.js.JS.toInt(standard.get(s));
+        else if (s.length() == 7 && s.charAt(0) == '#') try {
+            // FEATURE  alpha
+            return 0xFF000000 |
+                (Integer.parseInt(s.substring(1, 3), 16) << 16) |
+                (Integer.parseInt(s.substring(3, 5), 16) << 8) |
+                Integer.parseInt(s.substring(5, 7), 16);
+        } catch (NumberFormatException e) {
+            Log.info(Color.class, "invalid color " + s);
+            return 0;
+        }
+        else return 0; // FEATURE: error?
+    }
+
+    public static String colorToString(int argb) {
+        if ((argb & 0xFF000000) == 0) return null;
+        String red = Integer.toHexString((argb & 0x00FF0000) >> 16);
+        String green = Integer.toHexString((argb & 0x0000FF00) >> 8);
+        String blue = Integer.toHexString(argb & 0x000000FF);
+        if (red.length() < 2) red = "0" + red;
+        if (blue.length() < 2) blue = "0" + blue;
+        if (green.length() < 2) green = "0" + green;
+        return "#" + red + green + blue;
+    }
+
+    /** Copied verbatim from the SVG specification */
+    private static Hashtable standard = new Hashtable(400);
+    static {
+       standard.put("aliceblue", new Integer((240 << 16) | (248 << 8) | 255));
+       standard.put("antiquewhite", new Integer((250 << 16) | (235 << 8) | 215));
+       standard.put("aqua", new Integer((0 << 16) | (255 << 8) | 255));
+       standard.put("aquamarine", new Integer((127 << 16) | (255 << 8) | 212));
+       standard.put("azure", new Integer((240 << 16) | (255 << 8) | 255));
+       standard.put("beige", new Integer((245 << 16) | (245 << 8) | 220));
+       standard.put("bisque", new Integer((255 << 16) | (228 << 8) | 196));
+       standard.put("black", new Integer((0 << 16) | (0 << 8) | 0));
+       standard.put("blanchedalmond", new Integer((255 << 16) | (235 << 8) | 205));
+       standard.put("blue", new Integer((0 << 16) | (0 << 8) | 255));
+       standard.put("blueviolet", new Integer((138 << 16) | (43 << 8) | 226));
+       standard.put("brown", new Integer((165 << 16) | (42 << 8) | 42));
+       standard.put("burlywood", new Integer((222 << 16) | (184 << 8) | 135));
+       standard.put("cadetblue", new Integer((95 << 16) | (158 << 8) | 160));
+       standard.put("chartreuse", new Integer((127 << 16) | (255 << 8) | 0));
+       standard.put("chocolate", new Integer((210 << 16) | (105 << 8) | 30));
+       standard.put("coral", new Integer((255 << 16) | (127 << 8) | 80));
+       standard.put("cornflowerblue", new Integer((100 << 16) | (149 << 8) | 237));
+       standard.put("cornsilk", new Integer((255 << 16) | (248 << 8) | 220));
+       standard.put("crimson", new Integer((220 << 16) | (20 << 8) | 60));
+       standard.put("cyan", new Integer((0 << 16) | (255 << 8) | 255));
+       standard.put("darkblue", new Integer((0 << 16) | (0 << 8) | 139));
+       standard.put("darkcyan", new Integer((0 << 16) | (139 << 8) | 139));
+       standard.put("darkgoldenrod", new Integer((184 << 16) | (134 << 8) | 11));
+       standard.put("darkgray", new Integer((169 << 16) | (169 << 8) | 169));
+       standard.put("darkgreen", new Integer((0 << 16) | (100 << 8) | 0));
+       standard.put("darkgrey", new Integer((169 << 16) | (169 << 8) | 169));
+       standard.put("darkkhaki", new Integer((189 << 16) | (183 << 8) | 107));
+       standard.put("darkmagenta", new Integer((139 << 16) | (0 << 8) | 139));
+       standard.put("darkolivegreen", new Integer((85 << 16) | (107 << 8) | 47));
+       standard.put("darkorange", new Integer((255 << 16) | (140 << 8) | 0));
+       standard.put("darkorchid", new Integer((153 << 16) | (50 << 8) | 204));
+       standard.put("darkred", new Integer((139 << 16) | (0 << 8) | 0));
+       standard.put("darksalmon", new Integer((233 << 16) | (150 << 8) | 122));
+       standard.put("darkseagreen", new Integer((143 << 16) | (188 << 8) | 143));
+       standard.put("darkslateblue", new Integer((72 << 16) | (61 << 8) | 139));
+       standard.put("darkslategray", new Integer((47 << 16) | (79 << 8) | 79));
+       standard.put("darkslategrey", new Integer((47 << 16) | (79 << 8) | 79));
+       standard.put("darkturquoise", new Integer((0 << 16) | (206 << 8) | 209));
+       standard.put("darkviolet", new Integer((148 << 16) | (0 << 8) | 211));
+       standard.put("deeppink", new Integer((255 << 16) | (20 << 8) | 147));
+       standard.put("deepskyblue", new Integer((0 << 16) | (191 << 8) | 255));
+       standard.put("dimgray", new Integer((105 << 16) | (105 << 8) | 105));
+       standard.put("dimgrey", new Integer((105 << 16) | (105 << 8) | 105));
+       standard.put("dodgerblue", new Integer((30 << 16) | (144 << 8) | 255));
+       standard.put("firebrick", new Integer((178 << 16) | (34 << 8) | 34));
+       standard.put("floralwhite", new Integer((255 << 16) | (250 << 8) | 240));
+       standard.put("forestgreen", new Integer((34 << 16) | (139 << 8) | 34));
+       standard.put("fuchsia", new Integer((255 << 16) | (0 << 8) | 255));
+       standard.put("gainsboro", new Integer((220 << 16) | (220 << 8) | 220));
+       standard.put("ghostwhite", new Integer((248 << 16) | (248 << 8) | 255));
+       standard.put("gold", new Integer((255 << 16) | (215 << 8) | 0));
+       standard.put("goldenrod", new Integer((218 << 16) | (165 << 8) | 32));
+       standard.put("gray", new Integer((128 << 16) | (128 << 8) | 128));
+       standard.put("grey", new Integer((128 << 16) | (128 << 8) | 128));
+       standard.put("green", new Integer((0 << 16) | (128 << 8) | 0));
+       standard.put("greenyellow", new Integer((173 << 16) | (255 << 8) | 47));
+       standard.put("honeydew", new Integer((240 << 16) | (255 << 8) | 240));
+       standard.put("hotpink", new Integer((255 << 16) | (105 << 8) | 180));
+       standard.put("indianred", new Integer((205 << 16) | (92 << 8) | 92));
+       standard.put("indigo", new Integer((75 << 16) | (0 << 8) | 130));
+       standard.put("ivory", new Integer((255 << 16) | (255 << 8) | 240));
+       standard.put("khaki", new Integer((240 << 16) | (230 << 8) | 140));
+       standard.put("lavender", new Integer((230 << 16) | (230 << 8) | 250));
+       standard.put("lavenderblush", new Integer((255 << 16) | (240 << 8) | 245));
+       standard.put("lawngreen", new Integer((124 << 16) | (252 << 8) | 0));
+       standard.put("lemonchiffon", new Integer((255 << 16) | (250 << 8) | 205));
+       standard.put("lightblue", new Integer((173 << 16) | (216 << 8) | 230));
+       standard.put("lightcoral", new Integer((240 << 16) | (128 << 8) | 128));
+       standard.put("lightcyan", new Integer((224 << 16) | (255 << 8) | 255));
+       standard.put("lightgoldenrodyellow", new Integer((250 << 16) | (250 << 8) | 210));
+       standard.put("lightgray", new Integer((211 << 16) | (211 << 8) | 211));
+       standard.put("lightgreen", new Integer((144 << 16) | (238 << 8) | 144));
+       standard.put("lightgrey", new Integer((211 << 16) | (211 << 8) | 211));
+       standard.put("lightpink", new Integer((255 << 16) | (182 << 8) | 193));
+       standard.put("lightsalmon", new Integer((255 << 16) | (160 << 8) | 122));
+       standard.put("lightseagreen", new Integer((32 << 16) | (178 << 8) | 170));
+       standard.put("lightskyblue", new Integer((135 << 16) | (206 << 8) | 250));
+       standard.put("lightslategray", new Integer((119 << 16) | (136 << 8) | 153));
+       standard.put("lightslategrey", new Integer((119 << 16) | (136 << 8) | 153));
+       standard.put("lightsteelblue", new Integer((176 << 16) | (196 << 8) | 222));
+       standard.put("lightyellow", new Integer((255 << 16) | (255 << 8) | 224));
+       standard.put("lime", new Integer((0 << 16) | (255 << 8) | 0));
+       standard.put("limegreen", new Integer((50 << 16) | (205 << 8) | 50));
+       standard.put("linen", new Integer((250 << 16) | (240 << 8) | 230));
+       standard.put("magenta", new Integer((255 << 16) | (0 << 8) | 255));
+       standard.put("maroon", new Integer((128 << 16) | (0 << 8) | 0));
+       standard.put("mediumaquamarine", new Integer((102 << 16) | (205 << 8) | 170));
+       standard.put("mediumblue", new Integer((0 << 16) | (0 << 8) | 205));
+       standard.put("mediumorchid", new Integer((186 << 16) | (85 << 8) | 211));
+       standard.put("mediumpurple", new Integer((147 << 16) | (112 << 8) | 219));
+       standard.put("mediumseagreen", new Integer((60 << 16) | (179 << 8) | 113));
+       standard.put("mediumslateblue", new Integer((123 << 16) | (104 << 8) | 238));
+       standard.put("mediumspringgreen", new Integer((0 << 16) | (250 << 8) | 154));
+       standard.put("mediumturquoise", new Integer((72 << 16) | (209 << 8) | 204));
+       standard.put("mediumvioletred", new Integer((199 << 16) | (21 << 8) | 133));
+       standard.put("midnightblue", new Integer((25 << 16) | (25 << 8) | 112));
+       standard.put("mintcream", new Integer((245 << 16) | (255 << 8) | 250));
+       standard.put("mistyrose", new Integer((255 << 16) | (228 << 8) | 225));
+       standard.put("moccasin", new Integer((255 << 16) | (228 << 8) | 181));
+       standard.put("navajowhite", new Integer((255 << 16) | (222 << 8) | 173));
+       standard.put("navy", new Integer((0 << 16) | (0 << 8) | 128));
+       standard.put("oldlace", new Integer((253 << 16) | (245 << 8) | 230));
+       standard.put("olive", new Integer((128 << 16) | (128 << 8) | 0));
+       standard.put("olivedrab", new Integer((107 << 16) | (142 << 8) | 35));
+       standard.put("orange", new Integer((255 << 16) | (165 << 8) | 0));
+       standard.put("orangered", new Integer((255 << 16) | (69 << 8) | 0));
+       standard.put("orchid", new Integer((218 << 16) | (112 << 8) | 214));
+       standard.put("palegoldenrod", new Integer((238 << 16) | (232 << 8) | 170));
+       standard.put("palegreen", new Integer((152 << 16) | (251 << 8) | 152));
+       standard.put("paleturquoise", new Integer((175 << 16) | (238 << 8) | 238));
+       standard.put("palevioletred", new Integer((219 << 16) | (112 << 8) | 147));
+       standard.put("papayawhip", new Integer((255 << 16) | (239 << 8) | 213));
+       standard.put("peachpuff", new Integer((255 << 16) | (218 << 8) | 185));
+       standard.put("peru", new Integer((205 << 16) | (133 << 8) | 63));
+       standard.put("pink", new Integer((255 << 16) | (192 << 8) | 203));
+       standard.put("plum", new Integer((221 << 16) | (160 << 8) | 221));
+       standard.put("powderblue", new Integer((176 << 16) | (224 << 8) | 230));
+       standard.put("purple", new Integer((128 << 16) | (0 << 8) | 128));
+       standard.put("red", new Integer((255 << 16) | (0 << 8) | 0));
+       standard.put("rosybrown", new Integer((188 << 16) | (143 << 8) | 143));
+       standard.put("royalblue", new Integer((65 << 16) | (105 << 8) | 225));
+       standard.put("saddlebrown", new Integer((139 << 16) | (69 << 8) | 19));
+       standard.put("salmon", new Integer((250 << 16) | (128 << 8) | 114));
+       standard.put("sandybrown", new Integer((244 << 16) | (164 << 8) | 96));
+       standard.put("seagreen", new Integer((46 << 16) | (139 << 8) | 87));
+       standard.put("seashell", new Integer((255 << 16) | (245 << 8) | 238));
+       standard.put("sienna", new Integer((160 << 16) | (82 << 8) | 45));
+       standard.put("silver", new Integer((192 << 16) | (192 << 8) | 192));
+       standard.put("skyblue", new Integer((135 << 16) | (206 << 8) | 235));
+       standard.put("slateblue", new Integer((106 << 16) | (90 << 8) | 205));
+       standard.put("slategray", new Integer((112 << 16) | (128 << 8) | 144));
+       standard.put("slategrey", new Integer((112 << 16) | (128 << 8) | 144));
+       standard.put("snow", new Integer((255 << 16) | (250 << 8) | 250));
+       standard.put("springgreen", new Integer((0 << 16) | (255 << 8) | 127));
+       standard.put("steelblue", new Integer((70 << 16) | (130 << 8) | 180));
+       standard.put("tan", new Integer((210 << 16) | (180 << 8) | 140));
+       standard.put("teal", new Integer((0 << 16) | (128 << 8) | 128));
+       standard.put("thistle", new Integer((216 << 16) | (191 << 8) | 216));
+       standard.put("tomato", new Integer((255 << 16) | (99 << 8) | 71));
+       standard.put("turquoise", new Integer((64 << 16) | (224 << 8) | 208));
+       standard.put("violet", new Integer((238 << 16) | (130 << 8) | 238));
+       standard.put("wheat", new Integer((245 << 16) | (222 << 8) | 179));
+       standard.put("white", new Integer((255 << 16) | (255 << 8) | 255));
+       standard.put("whitesmoke", new Integer((245 << 16) | (245 << 8) | 245));
+       standard.put("yellow", new Integer((255 << 16) | (255 << 8) | 0));
+       standard.put("yellowgreen", new Integer((154 << 16) | (205 << 8) | 50));
+    }
+}
index 451672e..47ba25b 100644 (file)
@@ -1,11 +1,11 @@
 // Copyright 2004 Adam Megacz, see the COPYING file for licensing [GPL]
-package org.ibex;
-import org.ibex.translators.*;
+package org.ibex.graphics;
 import org.ibex.util.*;
 import java.io.*;
 import java.util.Hashtable;
-
-import org.ibex.js.JSExn;
+import org.ibex.js.*;
+import org.xwt.mips.*;
+import org.ibex.plat.*;
 
 // FEATURE: this could be cleaner
 /** encapsulates a single font (a set of Glyphs) */
@@ -33,7 +33,7 @@ public class Font {
         public int height = -1;                 ///< the height of the glyph
         public byte[] data = null;              ///< the alpha channel samples for this font
         void render() {
-            if (!isLoaded) try { freetype.renderGlyph(this); } catch (IOException e) { Log.info(Freetype.class, e); }
+            if (!isLoaded) try { renderGlyph(this); } catch (IOException e) { Log.info(Font.class, e); }
             isLoaded = true;
         }
     }
@@ -41,7 +41,6 @@ public class Font {
 
     // Statics //////////////////////////////////////////////////////////////////////
 
-    static final Freetype freetype = new Freetype();
     static final Hashtable glyphsToBeCached = new Hashtable();
     static final Hashtable glyphsToBeDisplayed = new Hashtable();
     private static Cache fontCache = new Cache(100);
@@ -94,7 +93,7 @@ public class Font {
         return ret;
     }
 
-    static final Scheduler.Task glyphRenderingTask = new Scheduler.Task() { public void perform() {
+    static final Task glyphRenderingTask = new Task() { public void perform() {
         // FIXME: this should be a low-priority task
         glyphRenderingTaskIsScheduled = false;
         if (glyphsToBeCached.isEmpty()) return;
@@ -107,4 +106,59 @@ public class Font {
         glyphRenderingTaskIsScheduled = true;
         Scheduler.add(this);
     } };
+
+
+    // FreeType Interface //////////////////////////////////////////////////////////////////////////////
+
+    // FEATURE: use streams, not memoryfont's
+    // FEATURE: kerning pairs
+    private static int mem_allocated = 0;
+    private static org.xwt.mips.Runtime vm = null;
+    private static Stream loadedStream = null;
+
+    public static void loadFontByteStream(Stream res) {
+        try {
+            Log.info(Font.class, "loading font " + res);
+            loadedStream = res;
+            InputStream is = Stream.getInputStream(res);
+            byte[] fontstream = InputStreamToByteArray.convert(is);
+            vm = (org.xwt.mips.Runtime)Class.forName("org.ibex.util.MIPSApps").newInstance();
+            int baseAddr = vm.sbrk(fontstream.length);
+            vm.copyout(fontstream, baseAddr, fontstream.length);
+            vm.setUserInfo(0, baseAddr);
+            vm.setUserInfo(1, fontstream.length);
+            vm.start(new String[]{ "freetype" });
+            vm.execute();
+            if(vm.getState() == org.xwt.mips.Runtime.DONE) throw new Error("Freetype VM exited: " + vm.exitStatus());
+        } catch (Exception e) {
+            Log.info(Font.class, e);
+        }
+    }
+
+    public static synchronized void renderGlyph(Font.Glyph glyph) throws IOException {
+        try {
+            Log.debug(Font.class, "rasterizing glyph " + glyph.c + " of font " + glyph.font);
+            if (loadedStream != glyph.font.stream) loadFontByteStream(glyph.font.stream);
+            vm.setUserInfo(2, (int)glyph.c);
+            vm.setUserInfo(3, (int)glyph.c);
+            vm.setUserInfo(4, glyph.font.pointsize);
+            long start = System.currentTimeMillis();
+            vm.execute();
+            glyph.font.max_ascent = vm.getUserInfo(8);
+            glyph.font.max_descent = vm.getUserInfo(9);
+            glyph.baseline = vm.getUserInfo(10);
+            glyph.advance = vm.getUserInfo(11);
+            
+            glyph.width = vm.getUserInfo(6);
+            glyph.height = vm.getUserInfo(7);
+            
+            glyph.data = new byte[glyph.width * glyph.height];
+            int addr = vm.getUserInfo(5);
+            vm.copyin(addr, glyph.data, glyph.width * glyph.height);
+            glyph.isLoaded = true;
+            
+        } catch (Exception e) {
+            Log.info(Font.class, e);
+        }
+    }
 }
index 2a1c798..f65f5c8 100644 (file)
@@ -3,6 +3,8 @@
 #include <unistd.h>
 #include <freetype/freetype.h>
 
+char *user_info[1024];
+
 /* NOTE: _user_info is defined in crt0.c. It points to a 4096 byte
    block of memory that contains 1024 32-bit values that can be set
    with the setUserInfo() method of MIPSEmu.
@@ -34,8 +36,6 @@
 
 */
 
-extern char *user_info[1024];
-
 #define FT_Check(expr) do { \
     if((expr) != 0) { \
         errprint(#expr " failed\n"); \
@@ -105,3 +105,12 @@ if (old_glyph_index != -1) {
 }
 old_glyph_index = glyph_index;
 */
+
+
+extern int mspack_main();
+int main(int argc, char **argv) {
+  if(argc < 1) return 1;
+  if(strcmp(argv[0],"mspack")==0) return mspack_main();
+  if(strcmp(argv[0],"freetype")==0) return freetype_main();
+  return 1;
+}
index 26b1a40..254430e 100644 (file)
@@ -41,7 +41,7 @@
  * terms specified in this license.
  *
  */
-package org.ibex.translators;
+package org.ibex.graphics;
 
 import org.ibex.*;
 import org.ibex.util.*;
similarity index 99%
rename from src/org/ibex/util/HTML.java
rename to src/org/ibex/graphics/HTML.java
index 5b0811f..47de2e0 100644 (file)
@@ -1,5 +1,5 @@
 // Copyright 2004 Adam Megacz, see the COPYING file for licensing [GPL]
-package org.ibex.translators;
+package org.ibex.graphics;
 
 import java.util.*;
 import java.net.*;
index ee6537e..b5d47f2 100644 (file)
@@ -11,7 +11,7 @@
  * hereby granted.
  */
 
-package org.ibex.translators;
+package org.ibex.graphics;
 
 import org.ibex.*;
 import org.ibex.util.*;
diff --git a/src/org/ibex/graphics/Paint.java b/src/org/ibex/graphics/Paint.java
new file mode 100644 (file)
index 0000000..46c43ee
--- /dev/null
@@ -0,0 +1,102 @@
+// FIXME
+// Copyright 2004 Adam Megacz, see the COPYING file for licensing [GPL]
+package org.ibex.graphics;
+import java.util.*;
+
+public abstract class Paint {
+    public abstract void fillTrapezoid(int tx1, int tx2, int ty1, int tx3, int tx4, int ty2, PixelBuffer buf);
+
+    public static class SingleColorPaint extends Paint {
+        int color;
+        public SingleColorPaint(int color) { this.color = color; }
+        public void fillTrapezoid(int x1, int x2, int y1, int x3, int x4, int y2, PixelBuffer buf) {
+            buf.fillTrapezoid(x1, x2, y1, x3, x4, y2, color);
+        }
+    }
+
+
+    /*
+      public static abstract class GradientPaint extends Paint {
+      public GradientPaint(boolean reflect, boolean repeat, Affine gradientTransform,
+      int[] stop_colors, float[] stop_offsets) {
+      this.reflect = reflect; this.repeat = repeat;
+      this.gradientTransform = gradientTransform;
+      this.stop_colors = stop_colors;
+      this.stop_offsets = stop_offsets;
+      }
+      Affine gradientTransform = Affine.identity();
+      boolean useBoundingBox = false;            // FIXME not supported
+      boolean patternUseBoundingBox = false;     // FIXME not supported
+
+      // it's invalid for both of these to be true
+      boolean reflect = false;                   // FIXME not supported
+      boolean repeat = false;                    // FIXME not supported
+      int[] stop_colors;
+      float[] stop_offsets;
+
+      public void fillTrapezoid(float tx1, float tx2, float ty1, float tx3, float tx4, float ty2, PixelBuffer buf) {
+      Affine a = buf.a;
+      Affine inverse = a.copy().invert();
+      float slope1 = (tx3 - tx1) / (ty2 - ty1);
+      float slope2 = (tx4 - tx2) / (ty2 - ty1);
+      for(float y=ty1; y<ty2; y++) {
+      float _x1 = (y - ty1) * slope1 + tx1;
+      float _x2 = (y - ty1) * slope2 + tx2;
+      if (_x1 > _x2) { float _x0 = _x1; _x1 = _x2; _x2 = _x0; }
+
+      for(float x=_x1; x<_x2; x++) {
+                   
+      float distance = isLinear ?
+      // length of projection of <x,y> onto the gradient vector == {<x,y> \dot {grad \over |grad|}}
+      (x * (x2 - x1) + y * (y2 - y1)) / (float)Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1)) :
+                       
+      // radial form is simple! FIXME, not quite right
+      (float)Math.sqrt((x - cx) * (x - cx) + (y - cy) * (y - cy));
+                       
+      // FIXME: offsets are 0..1, not 0..length(gradient)
+      int i = 0; for(; i<stop_offsets.length; i++) if (distance < stop_offsets[i]) break;
+
+      // FIXME: handle points beyond the bounds
+      if (i < 0 || i >= stop_offsets.length) continue;
+
+      // gradate from offsets[i - 1] to offsets[i]
+      float percentage = ((distance - stop_offsets[i - 1]) / (stop_offsets[i] - stop_offsets[i - 1]));
+
+      int a = (int)((((stop_colors[i] >> 24) & 0xff) - ((stop_colors[i - 1] >> 24) & 0xff)) * percentage) +
+      ((stop_colors[i - 1] >> 24) & 0xff);
+      int r = (int)((((stop_colors[i] >> 16) & 0xff) - ((stop_colors[i - 1] >> 16) & 0xff)) * percentage) +
+      ((stop_colors[i - 1] >> 16) & 0xff);
+      int g = (int)((((stop_colors[i] >> 8) & 0xff)  - ((stop_colors[i - 1] >> 8) & 0xff)) * percentage) +
+      ((stop_colors[i - 1] >> 8) & 0xff);
+      int b = (int)((((stop_colors[i] >> 0) & 0xff)  - ((stop_colors[i - 1] >> 0) & 0xff)) * percentage) +
+      ((stop_colors[i - 1] >> 0) & 0xff);
+      int argb = (a << 24) | (r << 16) | (g << 8) | b;
+      buf.drawPoint((int)x, (int)Math.floor(y), argb);
+      }
+      }
+      }
+      }
+
+      public static class LinearGradientPaint extends GradientPaint {
+      public LinearGradientPaint(float x1, float y1, float x2, float y2, boolean reflect, boolean repeat,
+      Affine gradientTransform,  int[] stop_colors, float[] stop_offsets) {
+      super(reflect, repeat, gradientTransform, stop_colors, stop_offsets);
+      this.x1 = x1; this.x2 = x2; this.y1 = y1; this.y2 = y2;
+      }
+      float x1 = 0, y1 = 0, x2 = 300, y2 = 300;
+      }
+
+      public static class RadialGradientPaint extends GradientPaint {
+      public RadialGradientPaint(float cx, float cy, float fx, float fy, float r, boolean reflect, boolean repeat,
+      Affine gradientTransform, int[] stop_colors, float[] stop_offsets) {
+      super(reflect, repeat, gradientTransform, stop_colors, stop_offsets);
+      this.cx = cx; this.cy = cy; this.fx = fx; this.fy = fy; this.r = r;
+      }
+            
+      float cx, cy, r, fx, fy;
+
+      }
+    */
+
+
+}
index 79fecba..71063a2 100644 (file)
 // FIXME
-// Copyright 2002 Adam Megacz, see the COPYING file for licensing [GPL]
-package org.ibex;
+// Copyright 2004 Adam Megacz, see the COPYING file for licensing [GPL]
+package org.ibex.graphics;
 import java.util.*;
 
-// FIXME: offer a "subpixel" mode where we pass floats to the Platform and don't do any snapping
-// FIXME: fracture when realizing instead of when parsing?
-
-/*
-    v1.0
-    - textpath
-    - gradients
-    - patterns
-    - clipping/masking
-    - filters (filtering of a group must be performed AFTER the group is assembled; sep. canvas)
-
-    v1.1
-    - bump caps [requires Paint that can fill circles...] [remember to distinguish between closed/unclosed]
-    - line joins
-        - mitre    (hard)
-        - bevel    (easy)
-        - bump     (easy, but requires 'round' Paint)
-    - subtree sharing? otherwise the memory consumption might be outrageous... clone="" attribute?
-    - better clipping
-        - intersect clip regions (linearity)
-        - clip on trapezoids, not pixels
-    - faster gradients and patterns:
-        - transform each corner of the trapezoid and then interpolate
-*/
-
-/** Ibex's fully conformant Static SVG Viewer; see SVG spec, section G.7 */
-public final class VectorGraphics {
-
-    // Private Constants ///////////////////////////////////////////////////////////////////
+/** an abstract path; may contain splines and arcs */
+public class Path {
 
+    public static final float PX_PER_INCH = 72;
+    public static final float INCHES_PER_CM = (float)0.3937;
+    public static final float INCHES_PER_MM = INCHES_PER_CM / 10;
     private static final int DEFAULT_PATHLEN = 1000;
     private static final float PI = (float)Math.PI;
 
+    // the number of vertices on this path
+    int numvertices = 0;
 
-    // Public entry points /////////////////////////////////////////////////////////////////
-
-    public static VectorPath parseVectorPath(String s) {
-        if (s == null) return null;
-        PathTokenizer t = new PathTokenizer(s);
-        VectorPath ret = new VectorPath();
-        char last_command = 'M';
-        boolean first = true;
-        while(t.hasMoreTokens()) {
-            char command = t.parseCommand();
-            if (first && command != 'M') throw new RuntimeException("the first command of a path must be 'M'");
-            first = false;
-            boolean relative = Character.toLowerCase(command) == command;
-            command = Character.toLowerCase(command);
-            ret.parseSingleCommandAndArguments(t, command, relative);
-            last_command = command;
-        }
-        return ret;
-    }
-
-
-    // Affine //////////////////////////////////////////////////////////////////////////////
-
-    /** an affine transform; all operations are destructive */
-    public static final class Affine {
-
-       //  [ a b e ]
-       //  [ c d f ]
-       //  [ 0 0 1 ]
-        public float a, b, c, d, e, f;
-
-       Affine(float _a, float _b, float _c, float _d, float _e, float _f) { a = _a; b = _b; c = _c; d = _d; e = _e; f = _f; }
-       public String toString() { return "[ " + a + ", " + b + ", " + c + ", " + d + ", " + e + ", " + f + " ]"; }
-       public Affine copy() { return new Affine(a, b, c, d, e, f); }
-        public static Affine identity() { return new Affine(1, 0, 0, 1, 0, 0); }
-       public static Affine scale(float sx, float sy) { return new Affine(sx, 0, 0, sy, 0, 0); }
-       public static Affine shear(float degrees) {
-            return new Affine(1, 0, (float)Math.tan(degrees * (float)(Math.PI / 180.0)), 1, 0, 0); }
-       public static Affine translate(float tx, float ty) { return new Affine(1, 0, 0, 1, tx, ty); }
-       public static Affine flip(boolean horiz, boolean vert) { return new Affine(horiz ? -1 : 1, 0, 0, vert ? -1 : 1, 0, 0); }
-        public float multiply_px(float x, float y) { return x * a + y * c + e; }
-       public float multiply_py(float x, float y) { return x * b + y * d + f; }
-        public boolean equalsIgnoringTranslation(Affine x) { return a == x.a && b == x.b && c == x.c && d == x.d; }
-
-        public boolean equals(Object o) {
-            if (!(o instanceof Affine)) return false;
-            Affine x = (Affine)o;
-            return a == x.a && b == x.b && c == x.c && d == x.d && e == x.e && f == x.f;
-        }
+    // the vertices of the path
+    float[] x = new float[DEFAULT_PATHLEN];
+    float[] y = new float[DEFAULT_PATHLEN];
 
-       public static Affine rotate(float degrees) {
-           float s = (float)Math.sin(degrees * (float)(Math.PI / 180.0));
-           float c = (float)Math.cos(degrees * (float)(Math.PI / 180.0));
-           return new Affine(c, s, -s, c, 0, 0);
-       }
+    // the type of each edge; type[i] is the type of the edge from x[i],y[i] to x[i+1],y[i+1]
+    byte[] type = new byte[DEFAULT_PATHLEN];
 
-       /** this = this * a */
-        public Affine multiply(Affine A) {
-           float _a = this.a * A.a + this.b * A.c;
-           float _b = this.a * A.b + this.b * A.d;
-           float _c = this.c * A.a + this.d * A.c;
-           float _d = this.c * A.b + this.d * A.d;
-           float _e = this.e * A.a + this.f * A.c + A.e;
-           float _f = this.e * A.b + this.f * A.d + A.f;
-           a = _a; b = _b; c = _c; d = _d; e = _e; f = _f;
-            return this;
-       }
-
-        public void invert() {
-           float det = 1 / (a * d - b * c);
-           float _a = d * det;
-           float _b = -1 * b * det;
-           float _c = -1 * c * det;
-           float _d = a * det;
-           float _e = -1 * e * a - f * c;
-           float _f = -1 * e * b - f * d;
-           a = _a; b = _b; c = _c; d = _d; e = _e; f = _f;
-       }
-    }
+    // bezier control points
+    float[] c1x = new float[DEFAULT_PATHLEN];  // or rx (arcto)
+    float[] c1y = new float[DEFAULT_PATHLEN];  // or ry (arcto)
+    float[] c2x = new float[DEFAULT_PATHLEN];  // or x-axis-rotation (arcto)
+    float[] c2y = new float[DEFAULT_PATHLEN];  // or large-arc << 1 | sweep (arcto)
 
+    boolean closed = false;
 
-    // PathTokenizer //////////////////////////////////////////////////////////////////////////////
+    static final byte TYPE_MOVETO = 0;
+    static final byte TYPE_LINETO = 1;
+    static final byte TYPE_ARCTO = 2;
+    static final byte TYPE_CUBIC = 3;
+    static final byte TYPE_QUADRADIC = 4;
 
-    public static Affine parseTransform(String t) {
-        if (t == null) return null;
-        t = t.trim();
-        Affine ret = VectorGraphics.Affine.identity();
-        while (t.length() > 0) {
-            if (t.startsWith("skewX(")) {
-                // FIXME
-                
-            } else if (t.startsWith("shear(")) {
-                // FIXME: nonstandard; remove this
-                ret.multiply(VectorGraphics.Affine.shear(Float.parseFloat(t.substring(t.indexOf('(') + 1, t.indexOf(')')))));
-                
-            } else if (t.startsWith("skewY(")) {
-                // FIXME
-                
-            } else if (t.startsWith("rotate(")) {
-                String sub = t.substring(t.indexOf('(') + 1, t.indexOf(')'));
-                if (sub.indexOf(',') != -1) {
-                    float angle = Float.parseFloat(sub.substring(0, sub.indexOf(',')));
-                    sub = sub.substring(sub.indexOf(',') + 1);
-                    float cx = Float.parseFloat(sub.substring(0, sub.indexOf(',')));
-                    sub = sub.substring(sub.indexOf(',') + 1);
-                    float cy = Float.parseFloat(sub);
-                    ret.multiply(VectorGraphics.Affine.translate(cx, cy));
-                    ret.multiply(VectorGraphics.Affine.rotate(angle));
-                    ret.multiply(VectorGraphics.Affine.translate(-1 * cx, -1 * cy));
-                } else {
-                    ret.multiply(VectorGraphics.Affine.rotate(Float.parseFloat(t.substring(t.indexOf('(') + 1, t.indexOf(')')))));
-                }
-                
-            } else if (t.startsWith("translate(")) {
-                String sub = t.substring(t.indexOf('(') + 1, t.indexOf(')'));
-                if (sub.indexOf(',') > -1) {
-                    ret.multiply(VectorGraphics.Affine.translate(Float.parseFloat(t.substring(t.indexOf('(') + 1, t.indexOf(','))),
-                                                                 Float.parseFloat(t.substring(t.indexOf(',') + 1, t.indexOf(')')))));
-                } else {
-                    ret.multiply(VectorGraphics.Affine.translate(Float.parseFloat(t.substring(t.indexOf('(') + 1, t.indexOf(','))), 0));
-                }
-                
-            } else if (t.startsWith("flip(")) {
-                String which = t.substring(t.indexOf('(') + 1, t.indexOf(')'));
-                ret.multiply(VectorGraphics.Affine.flip(which.equals("horizontal"), which.equals("vertical")));
-                
-            } else if (t.startsWith("scale(")) {
-                String sub = t.substring(t.indexOf('(') + 1, t.indexOf(')'));
-                if (sub.indexOf(',') > -1) {
-                    ret.multiply(VectorGraphics.Affine.scale(Float.parseFloat(t.substring(t.indexOf('(') + 1, t.indexOf(','))),
-                                                             Float.parseFloat(t.substring(t.indexOf(',') + 1, t.indexOf(')')))));
-                } else {
-                    ret.multiply(VectorGraphics.Affine.scale(Float.parseFloat(t.substring(t.indexOf('(') + 1, t.indexOf(','))),
-                                                             Float.parseFloat(t.substring(t.indexOf('(') + 1, t.indexOf(',')))));
-                }
-                
-            } else if (t.startsWith("matrix(")) {
-                // FIXME: is this mapped right?
-                float d[] = new float[6];
-                StringTokenizer st = new StringTokenizer(t, ",", false);
-                for(int i=0; i<6; i++)
-                    d[i] = Float.parseFloat(st.nextToken());
-                ret.multiply(new VectorGraphics.Affine(d[0], d[1], d[2], d[3], d[4], d[5]));
-            }
-            t = t.substring(t.indexOf(')') + 1).trim();
-        }
-        return ret;
-    }
-    
-    public static final float PX_PER_INCH = 72;
-    public static final float INCHES_PER_CM = (float)0.3937;
-    public static final float INCHES_PER_MM = INCHES_PER_CM / 10;
-
-    public static class PathTokenizer {
+    public static class Tokenizer {
         // FIXME: check array bounds exception for improperly terminated string
         String s;
         int i = 0;
         char lastCommand = 'M';
-        public PathTokenizer(String s) { this.s = s; }
+        public Tokenizer(String s) { this.s = s; }
+            
+        public static Path parse(String s) {
+            if (s == null) return null;
+            Tokenizer t = new Tokenizer(s);
+            Path ret = new Path();
+            char last_command = 'M';
+            boolean first = true;
+            while(t.hasMoreTokens()) {
+                char command = t.parseCommand();
+                if (first && command != 'M') throw new RuntimeException("the first command of a path must be 'M'");
+                first = false;
+                boolean relative = Character.toLowerCase(command) == command;
+                command = Character.toLowerCase(command);
+                ret.parseSingleCommandAndArguments(t, command, relative);
+                last_command = command;
+            }
+            return ret;
+        }
+
         private void consumeWhitespace() {
             while(i < s.length() && (Character.isWhitespace(s.charAt(i)))) i++;
             if (i < s.length() && s.charAt(i) == ',') i++;
@@ -235,169 +100,139 @@ public final class VectorGraphics {
         }
     }
 
+    /** Creates a concrete vector path transformed through the given matrix. */
+    public Raster realize(Affine a) {
+
+        Raster ret = new Raster();
+        int NUMSTEPS = 5;  // FIXME
+        ret.numvertices = 1;
+        ret.x[0] = (int)Math.round(a.multiply_px(x[0], y[0]));
+        ret.y[0] = (int)Math.round(a.multiply_py(x[0], y[0]));
+
+        for(int i=1; i<numvertices; i++) {
+            if (type[i] == TYPE_LINETO) {
+                float rx = x[i];
+                float ry = y[i];
+                ret.x[ret.numvertices] = (int)Math.round(a.multiply_px(rx, ry));
+                ret.y[ret.numvertices] = (int)Math.round(a.multiply_py(rx, ry));
+                ret.edges[ret.numedges++] = ret.numvertices - 1; ret.numvertices++;
+
+            } else if (type[i] == TYPE_MOVETO) {
+                float rx = x[i];
+                float ry = y[i];
+                ret.x[ret.numvertices] = (int)Math.round(a.multiply_px(rx, ry));
+                ret.y[ret.numvertices] = (int)Math.round(a.multiply_py(rx, ry));
+                ret.numvertices++;
+
+            } else if (type[i] == TYPE_ARCTO) {
+                float rx = c1x[i];
+                float ry = c1y[i];
+                float phi = c2x[i];
+                float fa = ((int)c2y[i]) >> 1;
+                float fs = ((int)c2y[i]) & 1;
+                float x1 = x[i];
+                float y1 = y[i];
+                float x2 = x[i+1];
+                float y2 = y[i+1];
+
+                // F.6.5: given x1,y1,x2,y2,fa,fs, compute cx,cy,theta1,dtheta
+                float x1_ = (float)Math.cos(phi) * (x1 - x2) / 2 + (float)Math.sin(phi) * (y1 - y2) / 2;
+                float y1_ = -1 * (float)Math.sin(phi) * (x1 - x2) / 2 + (float)Math.cos(phi) * (y1 - y2) / 2;
+                float tmp = (float)Math.sqrt((rx * rx * ry * ry - rx * rx * y1_ * y1_ - ry * ry * x1_ * x1_) /
+                                             (rx * rx * y1_ * y1_ + ry * ry * x1_ * x1_));
+                float cx_ = (fa == fs ? -1 : 1) * tmp * (rx * y1_ / ry);
+                float cy_ = (fa == fs ? -1 : 1) * -1 * tmp * (ry * x1_ / rx);
+                float cx = (float)Math.cos(phi) * cx_ - (float)Math.sin(phi) * cy_ + (x1 + x2) / 2;
+                float cy = (float)Math.sin(phi) * cx_ + (float)Math.cos(phi) * cy_ + (y1 + y2) / 2;
+
+                // F.6.4 Conversion from center to endpoint parameterization
+                float ux = 1, uy = 0, vx = (x1_ - cx_) / rx, vy = (y1_ - cy_) / ry;
+                float det = ux * vy - uy * vx;
+                float theta1 = (det < 0 ? -1 : 1) *
+                    (float)Math.acos((ux * vx + uy * vy) / 
+                                     ((float)Math.sqrt(ux * ux + uy * uy) * (float)Math.sqrt(vx * vx + vy * vy)));
+                ux = (x1_ - cx_) / rx; uy = (y1_ - cy_) / ry;
+                vx = (-1 * x1_ - cx_) / rx; vy = (-1 * y1_ - cy_) / ry;
+                det = ux * vy - uy * vx;
+                float dtheta = (det < 0 ? -1 : 1) *
+                    (float)Math.acos((ux * vx + uy * vy) / 
+                                     ((float)Math.sqrt(ux * ux + uy * uy) * (float)Math.sqrt(vx * vx + vy * vy)));
+                dtheta = dtheta % (float)(2 * Math.PI);
+
+                if (fs == 0 && dtheta > 0) theta1 -= 2 * PI; 
+                if (fs == 1 && dtheta < 0) theta1 += 2 * PI;
+
+                if (fa == 1 && dtheta < 0) dtheta = 2 * PI + dtheta;
+                else if (fa == 1 && dtheta > 0) dtheta = -1 * (2 * PI - dtheta);
+
+                // FIXME: integrate F.6.6
+                // FIXME: isn't quite ending where it should...
+
+                // F.6.3: Parameterization alternatives
+                float theta = theta1;
+                for(int j=0; j<NUMSTEPS; j++) {
+                    float rasterx = rx * (float)Math.cos(theta) * (float)Math.cos(phi) -
+                        ry * (float)Math.sin(theta) * (float)Math.sin(phi) + cx;
+                    float rastery = rx * (float)Math.cos(theta) * (float)Math.sin(phi) +
+                        ry * (float)Math.cos(phi) * (float)Math.sin(theta) + cy;
+                    ret.x[ret.numvertices] = (int)Math.round(a.multiply_px(rasterx, rastery));
+                    ret.y[ret.numvertices] = (int)Math.round(a.multiply_py(rasterx, rastery));
+                    ret.edges[ret.numedges++] = ret.numvertices - 1; ret.numvertices++;
+                    theta += dtheta / NUMSTEPS;
+                }
 
-    // Abstract Path //////////////////////////////////////////////////////////////////////////////
-
-    /** an abstract path; may contain splines and arcs */
-    public static class VectorPath {
-
-        // the number of vertices on this path
-       int numvertices = 0;
-
-        // the vertices of the path
-       float[] x = new float[DEFAULT_PATHLEN];
-       float[] y = new float[DEFAULT_PATHLEN];
-
-        // the type of each edge; type[i] is the type of the edge from x[i],y[i] to x[i+1],y[i+1]
-       byte[] type = new byte[DEFAULT_PATHLEN];
-
-       // bezier control points
-       float[] c1x = new float[DEFAULT_PATHLEN];  // or rx (arcto)
-       float[] c1y = new float[DEFAULT_PATHLEN];  // or ry (arcto)
-       float[] c2x = new float[DEFAULT_PATHLEN];  // or x-axis-rotation (arcto)
-       float[] c2y = new float[DEFAULT_PATHLEN];  // or large-arc << 1 | sweep (arcto)
-
-       boolean closed = false;
-
-       static final byte TYPE_MOVETO = 0;
-       static final byte TYPE_LINETO = 1;
-       static final byte TYPE_ARCTO = 2;
-       static final byte TYPE_CUBIC = 3;
-       static final byte TYPE_QUADRADIC = 4;
-
-        /** Creates a concrete vector path transformed through the given matrix. */
-       public RasterPath realize(Affine a) {
-
-            RasterPath ret = new RasterPath();
-            int NUMSTEPS = 5;  // FIXME
-           ret.numvertices = 1;
-            ret.x[0] = (int)Math.round(a.multiply_px(x[0], y[0]));
-            ret.y[0] = (int)Math.round(a.multiply_py(x[0], y[0]));
+            } else if (type[i] == TYPE_CUBIC) {
 
-           for(int i=1; i<numvertices; i++) {
-               if (type[i] == TYPE_LINETO) {
-                   float rx = x[i];
-                   float ry = y[i];
+                float ax = x[i+1] - 3 * c2x[i] + 3 * c1x[i] - x[i];
+                float bx = 3 * c2x[i] - 6 * c1x[i] + 3 * x[i];
+                float cx = 3 * c1x[i] - 3 * x[i];
+                float dx = x[i];
+                float ay = y[i+1] - 3 * c2y[i] + 3 * c1y[i] - y[i];
+                float by = 3 * c2y[i] - 6 * c1y[i] + 3 * y[i];
+                float cy = 3 * c1y[i] - 3 * y[i];
+                float dy = y[i];
+                   
+                for(float t=0; t<1; t += 1 / (float)NUMSTEPS) {
+                    float rx = ax * t * t * t + bx * t * t + cx * t + dx;
+                    float ry = ay * t * t * t + by * t * t + cy * t + dy;
                     ret.x[ret.numvertices] = (int)Math.round(a.multiply_px(rx, ry));
                     ret.y[ret.numvertices] = (int)Math.round(a.multiply_py(rx, ry));
                     ret.edges[ret.numedges++] = ret.numvertices - 1; ret.numvertices++;
+                }
+
+
+            } else if (type[i] == TYPE_QUADRADIC) {
 
-                } else if (type[i] == TYPE_MOVETO) {
-                   float rx = x[i];
-                   float ry = y[i];
+                float bx = x[i+1] - 2 * c1x[i] + x[i];
+                float cx = 2 * c1x[i] - 2 * x[i];
+                float dx = x[i];
+                float by = y[i+1] - 2 * c1y[i] + y[i];
+                float cy = 2 * c1y[i] - 2 * y[i];
+                float dy = y[i];
+                       
+                for(float t=0; t<1; t += 1 / (float)NUMSTEPS) {
+                    float rx = bx * t * t + cx * t + dx;
+                    float ry = by * t * t + cy * t + dy;
                     ret.x[ret.numvertices] = (int)Math.round(a.multiply_px(rx, ry));
                     ret.y[ret.numvertices] = (int)Math.round(a.multiply_py(rx, ry));
-                    ret.numvertices++;
-
-               } else if (type[i] == TYPE_ARCTO) {
-                   float rx = c1x[i];
-                   float ry = c1y[i];
-                   float phi = c2x[i];
-                   float fa = ((int)c2y[i]) >> 1;
-                   float fs = ((int)c2y[i]) & 1;
-                   float x1 = x[i];
-                   float y1 = y[i];
-                   float x2 = x[i+1];
-                   float y2 = y[i+1];
-
-                   // F.6.5: given x1,y1,x2,y2,fa,fs, compute cx,cy,theta1,dtheta
-                   float x1_ = (float)Math.cos(phi) * (x1 - x2) / 2 + (float)Math.sin(phi) * (y1 - y2) / 2;
-                   float y1_ = -1 * (float)Math.sin(phi) * (x1 - x2) / 2 + (float)Math.cos(phi) * (y1 - y2) / 2;
-                   float tmp = (float)Math.sqrt((rx * rx * ry * ry - rx * rx * y1_ * y1_ - ry * ry * x1_ * x1_) /
-                                                 (rx * rx * y1_ * y1_ + ry * ry * x1_ * x1_));
-                   float cx_ = (fa == fs ? -1 : 1) * tmp * (rx * y1_ / ry);
-                   float cy_ = (fa == fs ? -1 : 1) * -1 * tmp * (ry * x1_ / rx);
-                   float cx = (float)Math.cos(phi) * cx_ - (float)Math.sin(phi) * cy_ + (x1 + x2) / 2;
-                   float cy = (float)Math.sin(phi) * cx_ + (float)Math.cos(phi) * cy_ + (y1 + y2) / 2;
-
-                    // F.6.4 Conversion from center to endpoint parameterization
-                    float ux = 1, uy = 0, vx = (x1_ - cx_) / rx, vy = (y1_ - cy_) / ry;
-                    float det = ux * vy - uy * vx;
-                    float theta1 = (det < 0 ? -1 : 1) *
-                        (float)Math.acos((ux * vx + uy * vy) / 
-                                  ((float)Math.sqrt(ux * ux + uy * uy) * (float)Math.sqrt(vx * vx + vy * vy)));
-                    ux = (x1_ - cx_) / rx; uy = (y1_ - cy_) / ry;
-                    vx = (-1 * x1_ - cx_) / rx; vy = (-1 * y1_ - cy_) / ry;
-                    det = ux * vy - uy * vx;
-                    float dtheta = (det < 0 ? -1 : 1) *
-                        (float)Math.acos((ux * vx + uy * vy) / 
-                                  ((float)Math.sqrt(ux * ux + uy * uy) * (float)Math.sqrt(vx * vx + vy * vy)));
-                    dtheta = dtheta % (float)(2 * Math.PI);
-
-                   if (fs == 0 && dtheta > 0) theta1 -= 2 * PI; 
-                   if (fs == 1 && dtheta < 0) theta1 += 2 * PI;
-
-                   if (fa == 1 && dtheta < 0) dtheta = 2 * PI + dtheta;
-                   else if (fa == 1 && dtheta > 0) dtheta = -1 * (2 * PI - dtheta);
-
-                   // FIXME: integrate F.6.6
-                   // FIXME: isn't quite ending where it should...
-
-                   // F.6.3: Parameterization alternatives
-                   float theta = theta1;
-                   for(int j=0; j<NUMSTEPS; j++) {
-                       float rasterx = rx * (float)Math.cos(theta) * (float)Math.cos(phi) -
-                            ry * (float)Math.sin(theta) * (float)Math.sin(phi) + cx;
-                       float rastery = rx * (float)Math.cos(theta) * (float)Math.sin(phi) +
-                            ry * (float)Math.cos(phi) * (float)Math.sin(theta) + cy;
-                        ret.x[ret.numvertices] = (int)Math.round(a.multiply_px(rasterx, rastery));
-                        ret.y[ret.numvertices] = (int)Math.round(a.multiply_py(rasterx, rastery));
-                        ret.edges[ret.numedges++] = ret.numvertices - 1; ret.numvertices++;
-                       theta += dtheta / NUMSTEPS;
-                   }
-
-               } else if (type[i] == TYPE_CUBIC) {
-
-                   float ax = x[i+1] - 3 * c2x[i] + 3 * c1x[i] - x[i];
-                   float bx = 3 * c2x[i] - 6 * c1x[i] + 3 * x[i];
-                   float cx = 3 * c1x[i] - 3 * x[i];
-                   float dx = x[i];
-                   float ay = y[i+1] - 3 * c2y[i] + 3 * c1y[i] - y[i];
-                   float by = 3 * c2y[i] - 6 * c1y[i] + 3 * y[i];
-                   float cy = 3 * c1y[i] - 3 * y[i];
-                   float dy = y[i];
-                   
-                   for(float t=0; t<1; t += 1 / (float)NUMSTEPS) {
-                       float rx = ax * t * t * t + bx * t * t + cx * t + dx;
-                       float ry = ay * t * t * t + by * t * t + cy * t + dy;
-                        ret.x[ret.numvertices] = (int)Math.round(a.multiply_px(rx, ry));
-                        ret.y[ret.numvertices] = (int)Math.round(a.multiply_py(rx, ry));
-                        ret.edges[ret.numedges++] = ret.numvertices - 1; ret.numvertices++;
-                   }
-
-
-               } else if (type[i] == TYPE_QUADRADIC) {
-
-                   float bx = x[i+1] - 2 * c1x[i] + x[i];
-                   float cx = 2 * c1x[i] - 2 * x[i];
-                   float dx = x[i];
-                   float by = y[i+1] - 2 * c1y[i] + y[i];
-                   float cy = 2 * c1y[i] - 2 * y[i];
-                   float dy = y[i];
-                       
-                    for(float t=0; t<1; t += 1 / (float)NUMSTEPS) {
-                       float rx = bx * t * t + cx * t + dx;
-                       float ry = by * t * t + cy * t + dy;
-                        ret.x[ret.numvertices] = (int)Math.round(a.multiply_px(rx, ry));
-                        ret.y[ret.numvertices] = (int)Math.round(a.multiply_py(rx, ry));
-                        ret.edges[ret.numedges++] = ret.numvertices - 1; ret.numvertices++;
-                   }
+                    ret.edges[ret.numedges++] = ret.numvertices - 1; ret.numvertices++;
+                }
 
-               }
+            }
 
-           }
+        }
             
-            if (ret.numedges > 0) ret.sort(0, ret.numedges - 1, false);
-            return ret;
-       }
+        if (ret.numedges > 0) ret.sort(0, ret.numedges - 1, false);
+        return ret;
+    }
 
-        protected void parseSingleCommandAndArguments(PathTokenizer t, char command, boolean relative) {
-            if (numvertices == 0 && command != 'm') throw new RuntimeException("first command MUST be an 'm'");
-            if (numvertices > x.length - 2) {
-                float[] new_x = new float[x.length * 2]; System.arraycopy(x, 0, new_x, 0, x.length); x = new_x;
-                float[] new_y = new float[y.length * 2]; System.arraycopy(y, 0, new_y, 0, y.length); y = new_y;
-            }
-            switch(command) {
+    protected void parseSingleCommandAndArguments(Tokenizer t, char command, boolean relative) {
+        if (numvertices == 0 && command != 'm') throw new RuntimeException("first command MUST be an 'm'");
+        if (numvertices > x.length - 2) {
+            float[] new_x = new float[x.length * 2]; System.arraycopy(x, 0, new_x, 0, x.length); x = new_x;
+            float[] new_y = new float[y.length * 2]; System.arraycopy(y, 0, new_y, 0, y.length); y = new_y;
+        }
+        switch(command) {
             case 'z': {
                int where;
                 type[numvertices-1] = TYPE_LINETO;
@@ -486,51 +321,48 @@ public final class VectorGraphics {
 
             default:
                 // FIXME
-           }
+        }
 
-            /*
-            // invariant: after this loop, no two lines intersect other than at a vertex
-            // FIXME: cleanup
-            int index = numvertices - 2;
-            for(int i=0; i<Math.min(numvertices - 3, index); i++) {
-                for(int j = index; j < numvertices - 1; j++) {
+        /*
+        // invariant: after this loop, no two lines intersect other than at a vertex
+        // FIXME: cleanup
+        int index = numvertices - 2;
+        for(int i=0; i<Math.min(numvertices - 3, index); i++) {
+        for(int j = index; j < numvertices - 1; j++) {
 
-                    // I'm not sure how to deal with vertical lines...
-                    if (x[i+1] == x[i] || x[j+1] == x[j]) continue;
+        // I'm not sure how to deal with vertical lines...
+        if (x[i+1] == x[i] || x[j+1] == x[j]) continue;
                        
-                    float islope = (y[i+1] - y[i]) / (x[i+1] - x[i]);
-                    float jslope = (y[j+1] - y[j]) / (x[j+1] - x[j]);
-                    if (islope == jslope) continue;   // parallel lines can't intersect
+        float islope = (y[i+1] - y[i]) / (x[i+1] - x[i]);
+        float jslope = (y[j+1] - y[j]) / (x[j+1] - x[j]);
+        if (islope == jslope) continue;   // parallel lines can't intersect
                        
-                    float _x = (islope * x[i] - jslope * x[j] + y[j] - y[i]) / (islope - jslope);
-                    float _y = islope * (_x - x[i]) + y[i];
+        float _x = (islope * x[i] - jslope * x[j] + y[j] - y[i]) / (islope - jslope);
+        float _y = islope * (_x - x[i]) + y[i];
                        
-                    if (_x > Math.min(x[i+1], x[i]) && _x < Math.max(x[i+1], x[i]) &&
-                        _x > Math.min(x[j+1], x[j]) && _x < Math.max(x[j+1], x[j])) {
-                        // FIXME: something's not right in here.  See if we can do without fracturing line 'i'.
-                        for(int k = ++numvertices; k>i; k--) { x[k] = x[k - 1]; y[k] = y[k - 1]; }
-                        x[i+1] = _x;
-                        y[i+1] = _y;
-                        x[numvertices] = x[numvertices - 1];  x[numvertices - 1] = _x;
-                        y[numvertices] = y[numvertices - 1];  y[numvertices - 1] = _y;
-                        edges[numedges++] = numvertices - 1; numvertices++;
-                        index++;
-                        break;  // actually 'continue' the outermost loop
-                    }
-                }
-            }
-            */
+        if (_x > Math.min(x[i+1], x[i]) && _x < Math.max(x[i+1], x[i]) &&
+        _x > Math.min(x[j+1], x[j]) && _x < Math.max(x[j+1], x[j])) {
+        // FIXME: something's not right in here.  See if we can do without fracturing line 'i'.
+        for(int k = ++numvertices; k>i; k--) { x[k] = x[k - 1]; y[k] = y[k - 1]; }
+        x[i+1] = _x;
+        y[i+1] = _y;
+        x[numvertices] = x[numvertices - 1];  x[numvertices - 1] = _x;
+        y[numvertices] = y[numvertices - 1];  y[numvertices - 1] = _y;
+        edges[numedges++] = numvertices - 1; numvertices++;
+        index++;
+        break;  // actually 'continue' the outermost loop
+        }
+        }
+        }
+        */
 
-       }
     }
 
 
-
-
     // Rasterized Vector Path //////////////////////////////////////////////////////////////////////////////
     
     /** a vector path */
-    public static class RasterPath {
+    public static class Raster {
 
        // the vertices of this path
        int[] x = new int[DEFAULT_PATHLEN];
@@ -658,7 +490,7 @@ public final class VectorGraphics {
                 }
                 ratio = actualLength / segLength;
             }
-            PathTokenizer pt = new PathTokenizer(dashArray);
+            Tokenizer pt = new Tokenizer(dashArray);
             Vector v = new Vector();
             while (pt.hasMoreTokens()) v.addElement(new Float(pt.parseFloat()));
             float[] dashes = new float[v.size() % 2 == 0 ? v.size() : 2 * v.size()];
@@ -702,113 +534,6 @@ public final class VectorGraphics {
             return ret;
         }
     }
-    
-    
-    // Paint //////////////////////////////////////////////////////////////////////////////
 
-    public static interface Paint {
-       public abstract void
-            fillTrapezoid(int tx1, int tx2, int ty1, int tx3, int tx4, int ty2, PixelBuffer buf);
-    }
-
-    public static class SingleColorPaint implements Paint {
-        int color;
-        public SingleColorPaint(int color) { this.color = color; }
-        public void fillTrapezoid(int x1, int x2, int y1, int x3, int x4, int y2, PixelBuffer buf) {
-            buf.fillTrapezoid(x1, x2, y1, x3, x4, y2, color);
-        }
-    }
 
 }
-
-
-
-
-
-
-
-
-
-    /*
-    public static abstract class GradientPaint extends Paint {
-        public GradientPaint(boolean reflect, boolean repeat, Affine gradientTransform,
-                             int[] stop_colors, float[] stop_offsets) {
-            this.reflect = reflect; this.repeat = repeat;
-            this.gradientTransform = gradientTransform;
-            this.stop_colors = stop_colors;
-            this.stop_offsets = stop_offsets;
-        }
-        Affine gradientTransform = Affine.identity();
-       boolean useBoundingBox = false;            // FIXME not supported
-       boolean patternUseBoundingBox = false;     // FIXME not supported
-
-       // it's invalid for both of these to be true
-       boolean reflect = false;                   // FIXME not supported
-       boolean repeat = false;                    // FIXME not supported
-       int[] stop_colors;
-       float[] stop_offsets;
-
-       public void fillTrapezoid(float tx1, float tx2, float ty1, float tx3, float tx4, float ty2, PixelBuffer buf) {
-            Affine a = buf.a;
-           Affine inverse = a.copy().invert();
-           float slope1 = (tx3 - tx1) / (ty2 - ty1);
-           float slope2 = (tx4 - tx2) / (ty2 - ty1);
-           for(float y=ty1; y<ty2; y++) {
-               float _x1 = (y - ty1) * slope1 + tx1;
-               float _x2 = (y - ty1) * slope2 + tx2;
-               if (_x1 > _x2) { float _x0 = _x1; _x1 = _x2; _x2 = _x0; }
-
-               for(float x=_x1; x<_x2; x++) {
-                   
-                   float distance = isLinear ?
-                       // length of projection of <x,y> onto the gradient vector == {<x,y> \dot {grad \over |grad|}}
-                       (x * (x2 - x1) + y * (y2 - y1)) / (float)Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1)) :
-                       
-                       // radial form is simple! FIXME, not quite right
-                       (float)Math.sqrt((x - cx) * (x - cx) + (y - cy) * (y - cy));
-                       
-                   // FIXME: offsets are 0..1, not 0..length(gradient)
-                   int i = 0; for(; i<stop_offsets.length; i++) if (distance < stop_offsets[i]) break;
-
-                   // FIXME: handle points beyond the bounds
-                   if (i < 0 || i >= stop_offsets.length) continue;
-
-                   // gradate from offsets[i - 1] to offsets[i]
-                   float percentage = ((distance - stop_offsets[i - 1]) / (stop_offsets[i] - stop_offsets[i - 1]));
-
-                   int a = (int)((((stop_colors[i] >> 24) & 0xff) - ((stop_colors[i - 1] >> 24) & 0xff)) * percentage) +
-                       ((stop_colors[i - 1] >> 24) & 0xff);
-                   int r = (int)((((stop_colors[i] >> 16) & 0xff) - ((stop_colors[i - 1] >> 16) & 0xff)) * percentage) +
-                       ((stop_colors[i - 1] >> 16) & 0xff);
-                   int g = (int)((((stop_colors[i] >> 8) & 0xff)  - ((stop_colors[i - 1] >> 8) & 0xff)) * percentage) +
-                       ((stop_colors[i - 1] >> 8) & 0xff);
-                   int b = (int)((((stop_colors[i] >> 0) & 0xff)  - ((stop_colors[i - 1] >> 0) & 0xff)) * percentage) +
-                       ((stop_colors[i - 1] >> 0) & 0xff);
-                   int argb = (a << 24) | (r << 16) | (g << 8) | b;
-                   buf.drawPoint((int)x, (int)Math.floor(y), argb);
-               }
-           }
-       }
-    }
-
-    public static class LinearGradientPaint extends GradientPaint {
-        public LinearGradientPaint(float x1, float y1, float x2, float y2, boolean reflect, boolean repeat,
-                                   Affine gradientTransform,  int[] stop_colors, float[] stop_offsets) {
-            super(reflect, repeat, gradientTransform, stop_colors, stop_offsets);
-            this.x1 = x1; this.x2 = x2; this.y1 = y1; this.y2 = y2;
-        }
-       float x1 = 0, y1 = 0, x2 = 300, y2 = 300;
-    }
-
-    public static class RadialGradientPaint extends GradientPaint {
-        public RadialGradientPaint(float cx, float cy, float fx, float fy, float r, boolean reflect, boolean repeat,
-                             Affine gradientTransform, int[] stop_colors, float[] stop_offsets) {
-            super(reflect, repeat, gradientTransform, stop_colors, stop_offsets);
-            this.cx = cx; this.cy = cy; this.fx = fx; this.fy = fy; this.r = r;
-        }
-            
-       float cx, cy, r, fx, fy;
-
-    }
-    */
-
index d1abf61..528b0d7 100644 (file)
@@ -1,9 +1,10 @@
 // Copyright 2004 Adam Megacz, see the COPYING file for licensing [GPL]
-package org.ibex;
+package org.ibex.graphics;
 import java.io.*;
 import org.ibex.js.*;
+import org.ibex.plat.*;
 import org.ibex.util.*;
-import org.ibex.translators.*;
+import org.ibex.core.*;
 
 /** 
  *    The in-memory representation of a PNG or GIF image. It is
@@ -30,7 +31,7 @@ public class Picture {
     protected void loaded() { isLoaded = true; }
 
     /** turns a stream into a Picture.Source and passes it to the callback */
-    public static Picture load(final JS stream, final Scheduler.Task callback) {
+    public static Picture load(final JS stream, final Task callback) {
         Picture ret = (Picture)cache.get(stream);
         if (ret == null) cache.put(stream, ret = Platform.createPicture(stream));
         final Picture p = ret;
index 1434301..6107f71 100644 (file)
@@ -1,5 +1,5 @@
 // Copyright 2004 Adam Megacz, see the COPYING file for licensing [GPL]
-package org.ibex;
+package org.ibex.graphics;
 
 /**
  *  <p>
@@ -22,7 +22,7 @@ package org.ibex;
 public abstract class PixelBuffer {
 
     /** draw the picture at (dx1, dy1), cropping to (cx1, cy1, cx2, cy2) */
-    protected abstract void drawPicture(Picture source, int dx1, int dy1, int cx1, int cy1, int cx2, int cy2);
+    public abstract void drawPicture(Picture source, int dx1, int dy1, int cx1, int cy1, int cx2, int cy2);
 
     /** fill a trapezoid whose top and bottom edges are horizontal */
     public abstract void fillTrapezoid(int x1, int x2, int y1, int x3, int x4, int y2, int color);
index b8f73f9..90311a6 100644 (file)
@@ -1,7 +1,33 @@
 // Copyright 2004 Adam Megacz, see the COPYING file for licensing [GPL]
-package org.ibex.translators;
+package org.ibex.graphics;
 import java.util.*;
 
+
+// FIXME: offer a "subpixel" mode where we pass floats to the Platform and don't do any snapping
+// FIXME: fracture when realizing instead of when parsing?
+
+/*
+    v1.0
+    - textpath
+    - gradients
+    - patterns
+    - clipping/masking
+    - filters (filtering of a group must be performed AFTER the group is assembled; sep. canvas)
+
+    v1.1
+    - bump caps [requires Paint that can fill circles...] [remember to distinguish between closed/unclosed]
+    - line joins
+        - mitre    (hard)
+        - bevel    (easy)
+        - bump     (easy, but requires 'round' Paint)
+    - subtree sharing? otherwise the memory consumption might be outrageous... clone="" attribute?
+    - better clipping
+        - intersect clip regions (linearity)
+        - clip on trapezoids, not pixels
+    - faster gradients and patterns:
+        - transform each corner of the trapezoid and then interpolate
+*/
+
 // FIXME: need to support style sheets and the 'style=' attribute
 // FIXME: need to convert markers into subboxes
 public class SVG {
@@ -272,157 +298,4 @@ public class SVG {
     }
     */
 
-
-    /** Copied verbatim from the SVG specification */
-    public static Hashtable colors = new Hashtable(400);
-    static {
-       colors.put("aliceblue", new Integer((240 << 16) | (248 << 8) | 255));
-       colors.put("antiquewhite", new Integer((250 << 16) | (235 << 8) | 215));
-       colors.put("aqua", new Integer((0 << 16) | (255 << 8) | 255));
-       colors.put("aquamarine", new Integer((127 << 16) | (255 << 8) | 212));
-       colors.put("azure", new Integer((240 << 16) | (255 << 8) | 255));
-       colors.put("beige", new Integer((245 << 16) | (245 << 8) | 220));
-       colors.put("bisque", new Integer((255 << 16) | (228 << 8) | 196));
-       colors.put("black", new Integer((0 << 16) | (0 << 8) | 0));
-       colors.put("blanchedalmond", new Integer((255 << 16) | (235 << 8) | 205));
-       colors.put("blue", new Integer((0 << 16) | (0 << 8) | 255));
-       colors.put("blueviolet", new Integer((138 << 16) | (43 << 8) | 226));
-       colors.put("brown", new Integer((165 << 16) | (42 << 8) | 42));
-       colors.put("burlywood", new Integer((222 << 16) | (184 << 8) | 135));
-       colors.put("cadetblue", new Integer((95 << 16) | (158 << 8) | 160));
-       colors.put("chartreuse", new Integer((127 << 16) | (255 << 8) | 0));
-       colors.put("chocolate", new Integer((210 << 16) | (105 << 8) | 30));
-       colors.put("coral", new Integer((255 << 16) | (127 << 8) | 80));
-       colors.put("cornflowerblue", new Integer((100 << 16) | (149 << 8) | 237));
-       colors.put("cornsilk", new Integer((255 << 16) | (248 << 8) | 220));
-       colors.put("crimson", new Integer((220 << 16) | (20 << 8) | 60));
-       colors.put("cyan", new Integer((0 << 16) | (255 << 8) | 255));
-       colors.put("darkblue", new Integer((0 << 16) | (0 << 8) | 139));
-       colors.put("darkcyan", new Integer((0 << 16) | (139 << 8) | 139));
-       colors.put("darkgoldenrod", new Integer((184 << 16) | (134 << 8) | 11));
-       colors.put("darkgray", new Integer((169 << 16) | (169 << 8) | 169));
-       colors.put("darkgreen", new Integer((0 << 16) | (100 << 8) | 0));
-       colors.put("darkgrey", new Integer((169 << 16) | (169 << 8) | 169));
-       colors.put("darkkhaki", new Integer((189 << 16) | (183 << 8) | 107));
-       colors.put("darkmagenta", new Integer((139 << 16) | (0 << 8) | 139));
-       colors.put("darkolivegreen", new Integer((85 << 16) | (107 << 8) | 47));
-       colors.put("darkorange", new Integer((255 << 16) | (140 << 8) | 0));
-       colors.put("darkorchid", new Integer((153 << 16) | (50 << 8) | 204));
-       colors.put("darkred", new Integer((139 << 16) | (0 << 8) | 0));
-       colors.put("darksalmon", new Integer((233 << 16) | (150 << 8) | 122));
-       colors.put("darkseagreen", new Integer((143 << 16) | (188 << 8) | 143));
-       colors.put("darkslateblue", new Integer((72 << 16) | (61 << 8) | 139));
-       colors.put("darkslategray", new Integer((47 << 16) | (79 << 8) | 79));
-       colors.put("darkslategrey", new Integer((47 << 16) | (79 << 8) | 79));
-       colors.put("darkturquoise", new Integer((0 << 16) | (206 << 8) | 209));
-       colors.put("darkviolet", new Integer((148 << 16) | (0 << 8) | 211));
-       colors.put("deeppink", new Integer((255 << 16) | (20 << 8) | 147));
-       colors.put("deepskyblue", new Integer((0 << 16) | (191 << 8) | 255));
-       colors.put("dimgray", new Integer((105 << 16) | (105 << 8) | 105));
-       colors.put("dimgrey", new Integer((105 << 16) | (105 << 8) | 105));
-       colors.put("dodgerblue", new Integer((30 << 16) | (144 << 8) | 255));
-       colors.put("firebrick", new Integer((178 << 16) | (34 << 8) | 34));
-       colors.put("floralwhite", new Integer((255 << 16) | (250 << 8) | 240));
-       colors.put("forestgreen", new Integer((34 << 16) | (139 << 8) | 34));
-       colors.put("fuchsia", new Integer((255 << 16) | (0 << 8) | 255));
-       colors.put("gainsboro", new Integer((220 << 16) | (220 << 8) | 220));
-       colors.put("ghostwhite", new Integer((248 << 16) | (248 << 8) | 255));
-       colors.put("gold", new Integer((255 << 16) | (215 << 8) | 0));
-       colors.put("goldenrod", new Integer((218 << 16) | (165 << 8) | 32));
-       colors.put("gray", new Integer((128 << 16) | (128 << 8) | 128));
-       colors.put("grey", new Integer((128 << 16) | (128 << 8) | 128));
-       colors.put("green", new Integer((0 << 16) | (128 << 8) | 0));
-       colors.put("greenyellow", new Integer((173 << 16) | (255 << 8) | 47));
-       colors.put("honeydew", new Integer((240 << 16) | (255 << 8) | 240));
-       colors.put("hotpink", new Integer((255 << 16) | (105 << 8) | 180));
-       colors.put("indianred", new Integer((205 << 16) | (92 << 8) | 92));
-       colors.put("indigo", new Integer((75 << 16) | (0 << 8) | 130));
-       colors.put("ivory", new Integer((255 << 16) | (255 << 8) | 240));
-       colors.put("khaki", new Integer((240 << 16) | (230 << 8) | 140));
-       colors.put("lavender", new Integer((230 << 16) | (230 << 8) | 250));
-       colors.put("lavenderblush", new Integer((255 << 16) | (240 << 8) | 245));
-       colors.put("lawngreen", new Integer((124 << 16) | (252 << 8) | 0));
-       colors.put("lemonchiffon", new Integer((255 << 16) | (250 << 8) | 205));
-       colors.put("lightblue", new Integer((173 << 16) | (216 << 8) | 230));
-       colors.put("lightcoral", new Integer((240 << 16) | (128 << 8) | 128));
-       colors.put("lightcyan", new Integer((224 << 16) | (255 << 8) | 255));
-       colors.put("lightgoldenrodyellow", new Integer((250 << 16) | (250 << 8) | 210));
-       colors.put("lightgray", new Integer((211 << 16) | (211 << 8) | 211));
-       colors.put("lightgreen", new Integer((144 << 16) | (238 << 8) | 144));
-       colors.put("lightgrey", new Integer((211 << 16) | (211 << 8) | 211));
-       colors.put("lightpink", new Integer((255 << 16) | (182 << 8) | 193));
-       colors.put("lightsalmon", new Integer((255 << 16) | (160 << 8) | 122));
-       colors.put("lightseagreen", new Integer((32 << 16) | (178 << 8) | 170));
-       colors.put("lightskyblue", new Integer((135 << 16) | (206 << 8) | 250));
-       colors.put("lightslategray", new Integer((119 << 16) | (136 << 8) | 153));
-       colors.put("lightslategrey", new Integer((119 << 16) | (136 << 8) | 153));
-       colors.put("lightsteelblue", new Integer((176 << 16) | (196 << 8) | 222));
-       colors.put("lightyellow", new Integer((255 << 16) | (255 << 8) | 224));
-       colors.put("lime", new Integer((0 << 16) | (255 << 8) | 0));
-       colors.put("limegreen", new Integer((50 << 16) | (205 << 8) | 50));
-       colors.put("linen", new Integer((250 << 16) | (240 << 8) | 230));
-       colors.put("magenta", new Integer((255 << 16) | (0 << 8) | 255));
-       colors.put("maroon", new Integer((128 << 16) | (0 << 8) | 0));
-       colors.put("mediumaquamarine", new Integer((102 << 16) | (205 << 8) | 170));
-       colors.put("mediumblue", new Integer((0 << 16) | (0 << 8) | 205));
-       colors.put("mediumorchid", new Integer((186 << 16) | (85 << 8) | 211));
-       colors.put("mediumpurple", new Integer((147 << 16) | (112 << 8) | 219));
-       colors.put("mediumseagreen", new Integer((60 << 16) | (179 << 8) | 113));
-       colors.put("mediumslateblue", new Integer((123 << 16) | (104 << 8) | 238));
-       colors.put("mediumspringgreen", new Integer((0 << 16) | (250 << 8) | 154));
-       colors.put("mediumturquoise", new Integer((72 << 16) | (209 << 8) | 204));
-       colors.put("mediumvioletred", new Integer((199 << 16) | (21 << 8) | 133));
-       colors.put("midnightblue", new Integer((25 << 16) | (25 << 8) | 112));
-       colors.put("mintcream", new Integer((245 << 16) | (255 << 8) | 250));
-       colors.put("mistyrose", new Integer((255 << 16) | (228 << 8) | 225));
-       colors.put("moccasin", new Integer((255 << 16) | (228 << 8) | 181));
-       colors.put("navajowhite", new Integer((255 << 16) | (222 << 8) | 173));
-       colors.put("navy", new Integer((0 << 16) | (0 << 8) | 128));
-       colors.put("oldlace", new Integer((253 << 16) | (245 << 8) | 230));
-       colors.put("olive", new Integer((128 << 16) | (128 << 8) | 0));
-       colors.put("olivedrab", new Integer((107 << 16) | (142 << 8) | 35));
-       colors.put("orange", new Integer((255 << 16) | (165 << 8) | 0));
-       colors.put("orangered", new Integer((255 << 16) | (69 << 8) | 0));
-       colors.put("orchid", new Integer((218 << 16) | (112 << 8) | 214));
-       colors.put("palegoldenrod", new Integer((238 << 16) | (232 << 8) | 170));
-       colors.put("palegreen", new Integer((152 << 16) | (251 << 8) | 152));
-       colors.put("paleturquoise", new Integer((175 << 16) | (238 << 8) | 238));
-       colors.put("palevioletred", new Integer((219 << 16) | (112 << 8) | 147));
-       colors.put("papayawhip", new Integer((255 << 16) | (239 << 8) | 213));
-       colors.put("peachpuff", new Integer((255 << 16) | (218 << 8) | 185));
-       colors.put("peru", new Integer((205 << 16) | (133 << 8) | 63));
-       colors.put("pink", new Integer((255 << 16) | (192 << 8) | 203));
-       colors.put("plum", new Integer((221 << 16) | (160 << 8) | 221));
-       colors.put("powderblue", new Integer((176 << 16) | (224 << 8) | 230));
-       colors.put("purple", new Integer((128 << 16) | (0 << 8) | 128));
-       colors.put("red", new Integer((255 << 16) | (0 << 8) | 0));
-       colors.put("rosybrown", new Integer((188 << 16) | (143 << 8) | 143));
-       colors.put("royalblue", new Integer((65 << 16) | (105 << 8) | 225));
-       colors.put("saddlebrown", new Integer((139 << 16) | (69 << 8) | 19));
-       colors.put("salmon", new Integer((250 << 16) | (128 << 8) | 114));
-       colors.put("sandybrown", new Integer((244 << 16) | (164 << 8) | 96));
-       colors.put("seagreen", new Integer((46 << 16) | (139 << 8) | 87));
-       colors.put("seashell", new Integer((255 << 16) | (245 << 8) | 238));
-       colors.put("sienna", new Integer((160 << 16) | (82 << 8) | 45));
-       colors.put("silver", new Integer((192 << 16) | (192 << 8) | 192));
-       colors.put("skyblue", new Integer((135 << 16) | (206 << 8) | 235));
-       colors.put("slateblue", new Integer((106 << 16) | (90 << 8) | 205));
-       colors.put("slategray", new Integer((112 << 16) | (128 << 8) | 144));
-       colors.put("slategrey", new Integer((112 << 16) | (128 << 8) | 144));
-       colors.put("snow", new Integer((255 << 16) | (250 << 8) | 250));
-       colors.put("springgreen", new Integer((0 << 16) | (255 << 8) | 127));
-       colors.put("steelblue", new Integer((70 << 16) | (130 << 8) | 180));
-       colors.put("tan", new Integer((210 << 16) | (180 << 8) | 140));
-       colors.put("teal", new Integer((0 << 16) | (128 << 8) | 128));
-       colors.put("thistle", new Integer((216 << 16) | (191 << 8) | 216));
-       colors.put("tomato", new Integer((255 << 16) | (99 << 8) | 71));
-       colors.put("turquoise", new Integer((64 << 16) | (224 << 8) | 208));
-       colors.put("violet", new Integer((238 << 16) | (130 << 8) | 238));
-       colors.put("wheat", new Integer((245 << 16) | (222 << 8) | 179));
-       colors.put("white", new Integer((255 << 16) | (255 << 8) | 255));
-       colors.put("whitesmoke", new Integer((245 << 16) | (245 << 8) | 245));
-       colors.put("yellow", new Integer((255 << 16) | (255 << 8) | 0));
-       colors.put("yellowgreen", new Integer((154 << 16) | (205 << 8) | 50));
-    }
-
 }
index 7e23169..b9207bb 100644 (file)
@@ -1,8 +1,11 @@
 // Copyright 2004 Adam Megacz, see the COPYING file for licensing [GPL]
-package org.ibex;
+package org.ibex.graphics;
 
 import org.ibex.js.*;
 import org.ibex.util.*;
+import org.ibex.plat.*;
+
+import org.ibex.core.*;  // FIXME
 
 /** 
  *  A Surface, as described in the Ibex Reference.
@@ -10,7 +13,7 @@ import org.ibex.util.*;
  *  Platform subclasses should include an inner class subclass of
  *  Surface to return from the Platform._createSurface() method
  */
-public abstract class Surface extends PixelBuffer implements Scheduler.Task {
+public abstract class Surface extends PixelBuffer implements Task {
 
     // Static Data ////////////////////////////////////////////////////////////////////////////////
 
@@ -21,12 +24,12 @@ public abstract class Surface extends PixelBuffer implements Scheduler.Task {
     public static Vec allSurfaces = new Vec();
     
     /** When set to true, render() should abort as soon as possible and restart the rendering process */
-    volatile boolean abort = false;
+    public volatile boolean abort = false;
 
     // these three variables are used to ensure that user resizes trump programmatic resizes
-    volatile boolean syncRootBoxToSurface = false;
-    volatile int pendingWidth = 0;
-    volatile int pendingHeight = 0;
+    public volatile boolean syncRootBoxToSurface = false;
+    public volatile int pendingWidth = 0;
+    public volatile int pendingHeight = 0;
 
     public static boolean alt = false;          ///< true iff the alt button is pressed down
     public static boolean control = false;      ///< true iff the control button is pressed down
@@ -74,6 +77,7 @@ public abstract class Surface extends PixelBuffer implements Scheduler.Task {
     public void setMinimumSize(int minx, int miny, boolean resizable) { }
     protected void setSize(int w, int h) { _setSize(w, h); }
 
+    public static Picture scarImage = null;
 
     // Helper methods for subclasses ////////////////////////////////////////////////////////////
 
@@ -88,7 +92,7 @@ public abstract class Surface extends PixelBuffer implements Scheduler.Task {
         if (button == 1) new Message("_Press1", T, root);
         else if (button == 2) new Message("_Press2", T, root);
         else if (button == 3) {
-            Scheduler.add(new Scheduler.Task() { public void perform() throws JSExn {
+            Scheduler.add(new Task() { public void perform() throws JSExn {
                 Platform.clipboardReadEnabled = true;
                 try {
                     root.putAndTriggerTraps("_Press3", T);
@@ -126,7 +130,7 @@ public abstract class Surface extends PixelBuffer implements Scheduler.Task {
     }
 
     /** we enqueue ourselves in the Scheduler when we have a Move message to deal with */
-    private Scheduler.Task mover = new Scheduler.Task() {
+    private Task mover = new Task() {
             public void perform() {
                 if (mousex == newmousex && mousey == newmousey) return;
                 int oldmousex = mousex;     mousex = newmousex;
@@ -167,7 +171,7 @@ public abstract class Surface extends PixelBuffer implements Scheduler.Task {
 
     // FEATURE: can we avoid creating objects here?
     protected final void PosChange(final int x, final int y) {
-        Scheduler.add(new Scheduler.Task() { public void perform() throws JSExn {
+        Scheduler.add(new Task() { public void perform() throws JSExn {
             root.x = x;
             root.y = y;
             root.putAndTriggerTrapsAndCatchExceptions("PosChange", T);
@@ -220,15 +224,15 @@ public abstract class Surface extends PixelBuffer implements Scheduler.Task {
 
     public Surface(Box root) {
         this.root = root;
-        root.setMaxWidth(JS.N(Math.min(Platform.getScreenWidth(), root.maxwidth)));
-        root.setMaxHeight(JS.N(Math.min(Platform.getScreenHeight(), root.maxheight)));
+        root.setWidth(root.minwidth, Math.min(Platform.getScreenWidth(), root.maxwidth));
+        root.setHeight(root.minheight, Math.min(Platform.getScreenHeight(), root.maxheight));
         Surface old = fromBox(root);
         if (old != null) old.dispose(false);
         else root.removeSelf();
         Refresh();
     }
 
-    private static VectorGraphics.Affine identity = VectorGraphics.Affine.identity();
+    private static Affine identity = Affine.identity();
 
     /** runs the prerender() and render() pipelines in the root Box to regenerate the backbuffer, then blits it to the screen */
     public synchronized void render() {
@@ -238,14 +242,14 @@ public abstract class Surface extends PixelBuffer implements Scheduler.Task {
             abort = false;
             root.pack();
             if (syncRootBoxToSurface) {
-                root.setMaxWidth(JS.N(pendingWidth));
-                root.setMaxHeight(JS.N(pendingHeight));
+                root.setWidth(root.minwidth, pendingWidth);
+                root.setHeight(root.minheight, pendingHeight);
                 syncRootBoxToSurface = false;
             }
             if (root.maxwidth != root.width || root.maxheight != root.height) {
                 // dirty the place where the scar used to be and where it is now
-                dirty(0, root.height - Main.scarImage.height, Main.scarImage.width, Main.scarImage.height);
-                dirty(0, root.maxheight - Main.scarImage.height, Main.scarImage.width, Main.scarImage.height);
+                dirty(0, root.height - scarImage.height, scarImage.width, scarImage.height);
+                dirty(0, root.maxheight - scarImage.height, scarImage.width, scarImage.height);
             }
             root.reflow();
             setSize(root.width, root.height);
@@ -266,7 +270,7 @@ public abstract class Surface extends PixelBuffer implements Scheduler.Task {
             if (w <= 0 || h <= 0) continue;
 
             root.render(0, 0, x, y, x + w, y + h, this, identity);
-            drawPicture(Main.scarImage, 0, root.height - Main.scarImage.height, x, y, x+w, y+h);
+            drawPicture(scarImage, 0, root.height - scarImage.height, x, y, x+w, y+h);
             
             if (abort) {
                 // x,y,w,h is only partially reconstructed, so we must be careful not to re-blit it
@@ -281,7 +285,7 @@ public abstract class Surface extends PixelBuffer implements Scheduler.Task {
     }
 
     // FEATURE: reinstate recycler
-    public class Message implements Scheduler.Task {
+    public class Message implements Task {
         
         private Box boxContainingMouse;
         private Object value;
index de60d0c..9a54710 100644 (file)
@@ -69,7 +69,7 @@ public class JS extends org.ibex.util.BalancedTree {
         return new JS.UnpauseCallback(i);
     }
 
-    public static class UnpauseCallback implements Scheduler.Task {
+    public static class UnpauseCallback implements Task {
         Interpreter i;
         UnpauseCallback(Interpreter i) { this.i = i; }
         public void perform() throws JSExn { unpause(null); }
index 1455d38..4bf41e4 100644 (file)
@@ -2,9 +2,10 @@
 package org.ibex.js;
 
 import java.io.*;
+import org.ibex.util.*;
 
 /** A JavaScript function, compiled into bytecode */
-class JSFunction extends JS implements ByteCodes, Tokens, org.ibex.Scheduler.Task {
+class JSFunction extends JS implements ByteCodes, Tokens, Task {
 
 
     // Fields and Accessors ///////////////////////////////////////////////
index 878afa3..05045e9 100644 (file)
@@ -1,11 +1,11 @@
 // Copyright 2004 Adam Megacz, see the COPYING file for licensing [GPL]
-package org.ibex;
+package org.ibex.js;
 
 import java.io.*;
 import java.util.zip.*;
-import org.ibex.js.*;
 import org.ibex.util.*;
-import org.ibex.translators.MSPack;
+import org.ibex.plat.*;
+import org.ibex.net.*;
 
 /**
  *   Essentiall an InputStream "factory".  You can repeatedly ask a
@@ -32,24 +32,24 @@ public abstract class Stream extends JS.Cloneable {
 
     // Private Interface //////////////////////////////////////////////////////////////////////////////
 
-    protected abstract InputStream getInputStream() throws IOException;
+    public abstract InputStream getInputStream() throws IOException;
     protected String getCacheKey() throws NotCacheableException { throw new NotCacheableException(); }
 
     /** HTTP or HTTPS resource */
     public static class HTTP extends Stream {
         private String url;
         public String toString() { return "Stream.HTTP:" + url; }
-        HTTP(String url) { while (url.endsWith("/")) url = url.substring(0, url.length() - 1); this.url = url; }
+        public HTTP(String url) { while (url.endsWith("/")) url = url.substring(0, url.length() - 1); this.url = url; }
         public Object _get(Object key) { return new HTTP(url + "/" + (String)key); }
         public String getCacheKey(Vec path) throws NotCacheableException { return url; }
-        public InputStream getInputStream() throws IOException { return new org.ibex.HTTP(url).GET(); }
+        public InputStream getInputStream() throws IOException { return new org.ibex.net.HTTP(url).GET(); }
     }
 
     /** byte arrays */
     public static class ByteArray extends Stream {
         private byte[] bytes;
         private String cacheKey;
-        ByteArray(byte[] bytes, String cacheKey) { this.bytes = bytes; this.cacheKey = cacheKey; }
+        public ByteArray(byte[] bytes, String cacheKey) { this.bytes = bytes; this.cacheKey = cacheKey; }
         public String getCacheKey() throws NotCacheableException {
             if (cacheKey == null) throw new NotCacheableException(); return cacheKey; }
         public InputStream getInputStream() throws IOException { return new ByteArrayInputStream(bytes); }
@@ -58,7 +58,7 @@ public abstract class Stream extends JS.Cloneable {
     /** a file */
     public static class File extends Stream {
         private String path;
-        File(String path) { this.path = path; }
+        public File(String path) { this.path = path; }
         public String toString() { return "file:" + path; }
         public String getCacheKey() throws NotCacheableException { throw new NotCacheableException(); /* already on disk */ }
         public InputStream getInputStream() throws IOException { return new FileInputStream(path); }
@@ -69,8 +69,8 @@ public abstract class Stream extends JS.Cloneable {
     public static class Zip extends Stream {
         private Stream parent;
         private String path;
-        Zip(Stream parent) { this(parent, null); }
-        Zip(Stream parent, String path) {
+        public Zip(Stream parent) { this(parent, null); }
+        public Zip(Stream parent, String path) {
             while(path != null && path.startsWith("/")) path = path.substring(1);
             this.parent = parent;
             this.path = path;
@@ -91,8 +91,8 @@ public abstract class Stream extends JS.Cloneable {
     public static class Cab extends Stream {
         private Stream parent;
         private String path;
-        Cab(Stream parent) { this(parent, null); }
-        Cab(Stream parent, String path) { this.parent = parent; this.path = path; }
+        public Cab(Stream parent) { this(parent, null); }
+        public Cab(Stream parent, String path) { this.parent = parent; this.path = path; }
         public String getCacheKey() throws NotCacheableException { return parent.getCacheKey() + "!cab:"; }
         public Object _get(Object key) { return new Cab(parent, path==null?(String)key:path+'/'+(String)key); }
         public InputStream getInputStream() throws IOException { return new MSPack(parent.getInputStream()).getInputStream(path); }
@@ -108,7 +108,7 @@ public abstract class Stream extends JS.Cloneable {
     public static class ProgressWatcher extends Stream {
         final Stream watchee;
         JS callback;
-        ProgressWatcher(Stream watchee, JS callback) { this.watchee = watchee; this.callback = callback; }
+        public ProgressWatcher(Stream watchee, JS callback) { this.watchee = watchee; this.callback = callback; }
         public String getCacheKey() throws NotCacheableException { return watchee.getCacheKey(); }
         public InputStream getInputStream() throws IOException {
             final InputStream is = watchee.getInputStream();
@@ -122,7 +122,7 @@ public abstract class Stream extends JS.Cloneable {
                     public int read(byte[] b, int off, int len) throws IOException {
                         int ret = super.read(b, off, len);
                         if (ret != 1) bytesDownloaded += ret;
-                        Scheduler.add(new Scheduler.Task() { public void perform() throws IOException, JSExn {
+                        Scheduler.add(new Task() { public void perform() throws IOException, JSExn {
                             callback.call(N(bytesDownloaded),
                                           N(is instanceof KnownLength ? ((KnownLength)is).getLength() : 0), null, null, 2);
                         } });
@@ -147,7 +147,7 @@ public abstract class Stream extends JS.Cloneable {
             if (!disk) {
                 cis = new CachedInputStream(parent.getInputStream());
             } else {
-                java.io.File f = LocalStorage.Cache.getCacheFileForKey(key);
+                java.io.File f = org.ibex.core.LocalStorage.Cache.getCacheFileForKey(key);
                 if (f.exists()) return new FileInputStream(f);
                 cis = new CachedInputStream(parent.getInputStream(), f);
             }
index 10da62b..0142a9e 100644 (file)
@@ -1,13 +1,14 @@
 // Copyright 2004 Adam Megacz, see the COPYING file for licensing [GPL]
-package org.ibex;
+package org.ibex.net;
 
 import java.net.*;
 import java.io.*;
 import java.util.*;
 import org.ibex.js.*;
 import org.ibex.util.*;
-import org.bouncycastle.util.encoders.Base64;
-import org.bouncycastle.crypto.digests.*;
+import org.ibex.plat.*;
+import org.ibex.core.*;
+import org.ibex.crypto.*;
 
 /**
  *  This object encapsulates a *single* HTTP connection. Multiple requests may be pipelined over a connection (thread-safe),
@@ -638,7 +639,7 @@ public class HTTP {
 
     private String H(String s) throws IOException {
         byte[] b = s.getBytes("UTF8");
-        MD5Digest md5 = new MD5Digest();
+        MD5 md5 = new MD5();
         md5.update(b, 0, b.length);
         byte[] out = new byte[md5.getDigestSize()];
         md5.doFinal(out, 0);
@@ -783,7 +784,7 @@ public class HTTP {
 
                 if (authorization != oldAuth) return;
                 if (Log.on) Log.info(Authorization.class, "displaying proxy authorization dialog");
-                Scheduler.add(new Scheduler.Task() {
+                Scheduler.add(new Task() {
                         public void perform() throws IOException, JSExn {
                             Box b = new Box();
                             Template t = null;
@@ -1021,7 +1022,7 @@ public class HTTP {
             public static byte[] getNTLM2SessionResponse(String password,
                                                          byte[] challenge, byte[] clientChallenge) throws UnsupportedEncodingException {
                 byte[] ntlmHash = ntlmHash(password);
-                MD5Digest md5 = new MD5Digest();
+                MD5 md5 = new MD5();
                 md5.update(challenge, 0, challenge.length);
                 md5.update(clientChallenge, 0, clientChallenge.length);
                 byte[] sessionHash = new byte[8];
@@ -1070,11 +1071,15 @@ public class HTTP {
              * of the NTLM Response and the NTLMv2 and LMv2 Hashes.
              */
             private static byte[] ntlmHash(String password) throws UnsupportedEncodingException {
+                // FIXME
+                /*
                 byte[] unicodePassword = password.getBytes("UnicodeLittleUnmarked");
-                MD4Digest md4 = new MD4Digest();
+                MD4 md4 = new MD4();
                 md4.update(unicodePassword, 0, unicodePassword.length);
                 byte[] ret = new byte[md4.getDigestSize()];
                 return ret;
+                */
+                return null;
             }
 
             /**
@@ -1231,14 +1236,14 @@ public class HTTP {
                 byte[] content = new byte[data.length + 64];
                 System.arraycopy(ipad, 0, content, 0, 64);
                 System.arraycopy(data, 0, content, 64, data.length);
-                MD5Digest md5 = new MD5Digest();
+                MD5 md5 = new MD5();
                 md5.update(content, 0, content.length);
                 data = new byte[md5.getDigestSize()];
                 md5.doFinal(data, 0);
                 content = new byte[data.length + 64];
                 System.arraycopy(opad, 0, content, 0, 64);
                 System.arraycopy(data, 0, content, 64, data.length);
-                md5 = new MD5Digest();
+                md5 = new MD5();
                 md5.update(content, 0, content.length);
                 byte[] ret = new byte[md5.getDigestSize()];
                 md5.doFinal(ret, 0);
index 946ccb7..85670a3 100644 (file)
@@ -1,11 +1,11 @@
 // Copyright 2004 Adam Megacz, see the COPYING file for licensing [GPL]
-package org.ibex;
+package org.ibex.net;
 
 import java.io.*;
 import java.util.*;
 import org.ibex.js.*;
 import org.ibex.util.*;
-import org.bouncycastle.util.encoders.Base64;
+import org.ibex.crypto.*;
 
 /**
  *  A partial RPC-style SOAP 1.1 client. Implemented from the SOAP 1.1
@@ -18,7 +18,7 @@ import org.bouncycastle.util.encoders.Base64;
  *      <li> WSDL support
  *  </ul>
  */
-class SOAP extends XMLRPC {
+public class SOAP extends XMLRPC {
 
     /** the desired content of the SOAPAction header */
     String action = null;
@@ -268,12 +268,12 @@ class SOAP extends XMLRPC {
         return content.toString();
     }
 
-    SOAP(String url, String methodname, String action, String nameSpace) {
+    public SOAP(String url, String methodname, String action, String nameSpace) {
         super(url, methodname);
         this.action = action;
         this.nameSpace = nameSpace;
     }
-    SOAP(String url, String methodname, SOAP httpSource, String action, String nameSpace) {
+    public SOAP(String url, String methodname, SOAP httpSource, String action, String nameSpace) {
         super(url, methodname, httpSource);
         this.action = action;
         this.nameSpace = nameSpace;
index 607d34e..14aacb5 100644 (file)
@@ -1,11 +1,11 @@
 // Copyright 2004 Adam Megacz, see the COPYING file for licensing [GPL]
-package org.ibex;
+package org.ibex.net;
 
 import java.io.*;
 import java.util.*;
 import org.ibex.js.*;
 import org.ibex.util.*;
-import org.bouncycastle.util.encoders.Base64;
+import org.ibex.crypto.*;
 
 /**
  *  An XML-RPC client implemented as a JavaScript Host Object. See the
@@ -29,7 +29,7 @@ import org.bouncycastle.util.encoders.Base64;
  *         convert.
  *  </ol>
  */
-class XMLRPC extends JS {
+public class XMLRPC extends JS {
 
     public XMLRPC(String url, String method) {
         this.http = url.startsWith("stdio:") ? HTTP.stdio : new HTTP(url);
@@ -329,20 +329,20 @@ class XMLRPC extends JS {
             try {
                 new Helper().parse(br);
                 final Object result = fault ? new JSExn(objects.elementAt(0)) : objects.size() == 0 ? null : objects.elementAt(0);
-                Scheduler.add(new Scheduler.Task() { public void perform() throws JSExn { callback.unpause(result); }});
+                Scheduler.add(new Task() { public void perform() throws JSExn { callback.unpause(result); }});
             } finally {
                 tracker.clear();
                 objects.setSize(0);
             }
         } catch (final JSExn e) {
             final Exception e2 = e;
-            Scheduler.add(new Scheduler.Task() { public void perform() throws JSExn { callback.unpause(e2); }});
+            Scheduler.add(new Task() { public void perform() throws JSExn { callback.unpause(e2); }});
         } catch (final IOException e) {
             final Exception e2 = e;
-            Scheduler.add(new Scheduler.Task() { public void perform() throws JSExn { callback.unpause(new JSExn(e2)); }});
+            Scheduler.add(new Task() { public void perform() throws JSExn { callback.unpause(new JSExn(e2)); }});
         } catch (final XML.Exn e) {
             final Exception e2 = e;
-            Scheduler.add(new Scheduler.Task() { public void perform() throws JSExn { callback.unpause(new JSExn(e2)); }});
+            Scheduler.add(new Task() { public void perform() throws JSExn { callback.unpause(new JSExn(e2)); }});
         }
     }
 }
index c7a1dce..8c8956d 100644 (file)
@@ -9,6 +9,9 @@ import java.awt.*;
 import java.awt.datatransfer.*;
 import java.awt.image.*;
 import java.awt.event.*;
+import org.ibex.graphics.*;
+import org.ibex.core.*;
+import org.ibex.net.*;
 
 /** Platform subclass for all VM's providing AWT 1.1 functionality */
 public class AWT extends JVM {
@@ -113,8 +116,8 @@ public class AWT extends JVM {
 
     // Inner Classes /////////////////////////////////////////////////////////////////////////////////////
 
-    protected org.ibex.Font.Glyph _createGlyph(org.ibex.Font f, char c) { return new AWTGlyph(f, c); }
-    protected static class AWTGlyph extends org.ibex.Font.Glyph {
+    protected org.ibex.graphics.Font.Glyph _createGlyph(org.ibex.graphics.Font f, char c) { return new AWTGlyph(f, c); }
+    protected static class AWTGlyph extends org.ibex.graphics.Font.Glyph {
         private Image i = null;
         private static ColorModel cmodel = new DirectColorModel(32, 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000);
 
@@ -128,7 +131,7 @@ public class AWT extends JVM {
         };
         */
 
-        public AWTGlyph(org.ibex.Font f, char c) { super(f, c); }
+        public AWTGlyph(org.ibex.graphics.Font f, char c) { super(f, c); }
         Image getImage() {
             if (i == null && isLoaded) {
 
@@ -213,11 +216,11 @@ public class AWT extends JVM {
         }
 
         /** implemented with java.awt 1.1's setXORMode() */
-        public void drawGlyph(org.ibex.Font.Glyph source, int dx, int dy, int cx1, int cy1, int cx2, int cy2, int rgb) {
+        public void drawGlyph(org.ibex.graphics.Font.Glyph source, int dx, int dy, int cx1, int cy1, int cx2, int cy2, int rgb) {
 
             // XOR the target region
-            g.setXORMode(new Color((rgb & 0x00ff0000) >> 16, (rgb & 0x0000ff00) >> 8, rgb & 0x000000ff));
-            g.setColor(new Color(0x0, 0x0, 0x0));
+            g.setXORMode(new java.awt.Color((rgb & 0x00ff0000) >> 16, (rgb & 0x0000ff00) >> 8, rgb & 0x000000ff));
+            g.setColor(new java.awt.Color(0x0, 0x0, 0x0));
             g.fillRect(cx1, cy1, cx2 - cx1, cy2 - cy1);
 
             // blacken the area we want the glyph to cover
@@ -227,8 +230,8 @@ public class AWT extends JVM {
             g.setClip(0, 0, i.getWidth(null), i.getHeight(null));
 
             // XOR back, turning black into the chosen rgb color
-            g.setXORMode(new Color((rgb & 0x00ff0000) >> 16, (rgb & 0x0000ff00) >> 8, rgb & 0x000000ff));
-            g.setColor(new Color(0x0, 0x0, 0x0));
+            g.setXORMode(new java.awt.Color((rgb & 0x00ff0000) >> 16, (rgb & 0x0000ff00) >> 8, rgb & 0x000000ff));
+            g.setColor(new java.awt.Color(0x0, 0x0, 0x0));
             g.fillRect(cx1, cy1, cx2 - cx1, cy2 - cy1);
 
             // restore the graphics context
@@ -237,7 +240,7 @@ public class AWT extends JVM {
 
         // FIXME: try to use os acceleration
         public void fillTrapezoid(int x1, int x2, int y1, int x3, int x4, int y2, int argb) {
-            g.setColor(new Color((argb & 0x00FF0000) >> 16, (argb & 0x0000FF00) >> 8, (argb & 0x000000FF)));
+            g.setColor(new java.awt.Color((argb & 0x00FF0000) >> 16, (argb & 0x0000FF00) >> 8, (argb & 0x000000FF)));
             if (x1 == x3 && x2 == x4) {
                 g.fillRect(x1, y1, x4 - x1, y2 - y1);
             } else for(int y=y1; y<y2; y++) {
@@ -330,8 +333,8 @@ public class AWT extends JVM {
             if (oldfill != root.fillcolor) {
                 oldfill = root.fillcolor;
                 window.setBackground((root.fillcolor & 0xFF000000) == 0 ?
-                                     Color.white :
-                                     new Color((root.fillcolor >> 16) & 0xff,
+                                     java.awt.Color.white :
+                                     new java.awt.Color((root.fillcolor >> 16) & 0xff,
                                                (root.fillcolor >> 8) & 0xff,
                                                (root.fillcolor) & 0xff));
             }
index 34cad44..09c8a65 100644 (file)
@@ -7,6 +7,9 @@ import gnu.gcj.RawData;
 import org.ibex.util.*;
 import org.ibex.js.*;
 import org.ibex.*;
+import org.ibex.graphics.*;
+import org.ibex.core.*;
+import org.ibex.net.*;
 
 public class Darwin extends POSIX {
     private static final Class openGLClass = OpenGL.class;
index 8954660..2391434 100644 (file)
@@ -6,6 +6,9 @@ import org.ibex.util.*;
 import java.io.*;
 import java.security.*;
 import java.security.cert.*;
+import org.ibex.graphics.*;
+import org.ibex.core.*;
+import org.ibex.net.*;
 
 /** common superclass for all platforms that use GCJ to compile a native binary */
 public abstract class GCJ extends Platform {
index 54f6e21..7f7bdfd 100644 (file)
@@ -2,6 +2,9 @@
 package org.ibex.plat;
 
 import org.ibex.*;
+import org.ibex.graphics.*;
+import org.ibex.core.*;
+import org.ibex.net.*;
 
 /** common superclass for all platforms that run in a "real" JVM */
 public abstract class JVM extends Platform {
index 7a1909b..32c6d0c 100644 (file)
@@ -9,7 +9,9 @@ import java.util.*;
 import org.ibex.util.*;
 import org.ibex.*;
 import java.lang.reflect.*;
-
+import org.ibex.graphics.*;
+import org.ibex.core.*;
+import org.ibex.net.*;
 
 /** Platform class for most reasonable Java1.2+ Java2s */
 public class Java2 extends AWT {
@@ -41,11 +43,11 @@ public class Java2 extends AWT {
     }
 
     /** this is done with reflection in case a new version of the plugin comes out that doesn't let us pull the sun.plugin.* trick */
-    protected synchronized org.ibex.HTTP.Proxy _detectProxy() {
-        return (org.ibex.HTTP.Proxy)java.security.AccessController.doPrivileged(new java.security.PrivilegedAction() {
+    protected synchronized org.ibex.net.HTTP.Proxy _detectProxy() {
+        return (org.ibex.net.HTTP.Proxy)java.security.AccessController.doPrivileged(new java.security.PrivilegedAction() {
                 public Object run() {
                     try {
-                        org.ibex.HTTP.Proxy pi = new org.ibex.HTTP.Proxy();
+                        org.ibex.net.HTTP.Proxy pi = new org.ibex.net.HTTP.Proxy();
                         
                         Class PluginProxyHandler = Class.forName("sun.plugin.protocol.PluginProxyHandler");
                         Method getDefaultProxyHandler = PluginProxyHandler.getMethod("getDefaultProxyHandler", new Class[] { });
@@ -176,14 +178,14 @@ public class Java2 extends AWT {
         private DataBuffer buf = null;
 
         // this doens't seem to work on Windows
-        public void drawGlyph(org.ibex.Font.Glyph source, int dx, int dy, int cx1, int cy1, int cx2, int cy2, int rgb) {
+        public void drawGlyph(org.ibex.graphics.Font.Glyph source, int dx, int dy, int cx1, int cy1, int cx2, int cy2, int rgb) {
             Image i2 = ((AWTGlyph)source).getImage();
             Graphics2D g2 = (Graphics2D)i.getGraphics();
             g2.setComposite(AlphaComposite.DstOut);
             g2.setClip(cx1, cy1, cx2 - cx1, cy2 - cy1);
             g2.drawImage(i2, dx, dy, null);
             g2.setComposite(AlphaComposite.DstOver);
-            g2.setColor(new Color((rgb & 0x00FF0000) >> 16, (rgb & 0x0000FF00) >> 8, (rgb & 0x000000FF)));
+            g2.setColor(new java.awt.Color((rgb & 0x00FF0000) >> 16, (rgb & 0x0000FF00) >> 8, (rgb & 0x000000FF)));
             g2.fillRect(dx, dy, cx2 - dx, cy2 - dy);
             g2.drawImage(i2, 0, 0, null);
             g2.setClip(0, 0, i.getWidth(null), i.getHeight(null));
index 9ece3af..959ba5d 100644 (file)
@@ -1,6 +1,10 @@
 // Copyright 2004 Adam Megacz, see the COPYING file for licensing [GPL]
 package org.ibex.plat;
 
+import org.ibex.graphics.*;
+import org.ibex.core.*;
+import org.ibex.net.*;
+
 /** Linux with an X11 display */
 public class Linux extends X11 {
 
index 0d5bf18..040556e 100644 (file)
@@ -5,6 +5,9 @@ package org.ibex.plat;
 import org.ibex.*;
 import org.ibex.js.*;
 import org.ibex.util.*;
+import org.ibex.graphics.*;
+import org.ibex.core.*;
+import org.ibex.net.*;
 
 abstract class OpenGL {
     static final boolean pretendToBeACrappyVideoCard = false;
@@ -133,7 +136,7 @@ abstract class OpenGL {
     public void deleteTexture(final int tex) {
         // CHECKME: Is this safe to do from finalize()?
         // natDeleteTexture MUST be run from the message queue thread
-        Scheduler.add(new Scheduler.Task() { public void perform() { natDeleteTexture(tex); }});
+        Scheduler.add(new Task() { public void perform() { natDeleteTexture(tex); }});
     }
     
     private static abstract class GLPicture {
index 7b721a7..314596b 100644 (file)
@@ -2,6 +2,9 @@
 package org.ibex.plat;
 
 import java.util.*;
+import org.ibex.graphics.*;
+import org.ibex.core.*;
+import org.ibex.net.*;
 
 /** Platform implementation for POSIX compliant operating systems */
 public class POSIX extends GCJ {
index 85e67da..430e9ca 100644 (file)
@@ -2,6 +2,9 @@
 package org.ibex.plat;
 import org.ibex.*;
 import java.io.*;
+import org.ibex.graphics.*;
+import org.ibex.core.*;
+import org.ibex.net.*;
 
 /** Platform class for PalmOS devices */
 public class PalmOS extends Platform {
index 4b110a6..5ad71c2 100644 (file)
@@ -1,11 +1,16 @@
 // Copyright 2004 Adam Megacz, see the COPYING file for licensing [GPL]
-package org.ibex;
+package org.ibex.plat;
 
 import java.lang.reflect.*;
 import java.net.*;
 import java.io.*;
 import org.ibex.js.*;
 import org.ibex.util.*;
+import org.ibex.graphics.*;
+import org.ibex.core.*;
+import org.ibex.graphics.*;
+import org.ibex.core.*;
+import org.ibex.net.*;
 
 /** 
  *  Abstracts away the small irregularities in JVM implementations.
@@ -23,10 +28,10 @@ public abstract class Platform {
 
     // Static Data /////////////////////////////////////////////////////////////////////////////////////
 
-    static boolean clipboardReadEnabled = false;       ///< true iff inside a C-v/A-v/Press3 trap handler
-    static Platform platform = null;                   ///< The appropriate Platform object for this JVM
-    static boolean alreadyDetectedProxy = false;       ///< true if proxy autodetection has already been run
-    static org.ibex.HTTP.Proxy cachedProxyInfo = null;  ///< the result of proxy autodetection
+    public static boolean clipboardReadEnabled = false;       ///< true iff inside a C-v/A-v/Press3 trap handler
+    public static Platform platform = null;                   ///< The appropriate Platform object for this JVM
+    public static boolean alreadyDetectedProxy = false;       ///< true if proxy autodetection has already been run
+    public static org.ibex.net.HTTP.Proxy cachedProxyInfo = null;  ///< the result of proxy autodetection
     public static String build = "unknown";            ///< the current build
 
     // VM Detection Logic /////////////////////////////////////////////////////////////////////
@@ -100,11 +105,11 @@ public abstract class Platform {
     protected Surface _createSurface(Box b, boolean framed) { return null; }
     protected Picture _createPicture(JS r) { return null; }
     protected PixelBuffer _createPixelBuffer(int w, int h, Surface owner) { return null; }
-    protected Font.Glyph _createGlyph(org.ibex.Font f, char c) { return new DefaultGlyph(f, c); }
+    protected Font.Glyph _createGlyph(org.ibex.graphics.Font f, char c) { return new DefaultGlyph(f, c); }
 
     public static PixelBuffer createPixelBuffer(int w, int h, Surface s) { return platform._createPixelBuffer(w, h, s); }
     public static Picture createPicture(JS r) { return platform._createPicture(r); }
-    public static Font.Glyph createGlyph(org.ibex.Font f, char c) { return platform._createGlyph(f, c); }
+    public static Font.Glyph createGlyph(org.ibex.graphics.Font f, char c) { return platform._createGlyph(f, c); }
     public static Surface createSurface(Box b, boolean framed, boolean refreshable) {
         Surface ret = platform._createSurface(b, framed);
         ret.setInvisible(false);
@@ -245,15 +250,15 @@ public abstract class Platform {
     }
 
     /** detects proxy settings */
-    protected synchronized org.ibex.HTTP.Proxy _detectProxy() { return null; }
-    public static synchronized org.ibex.HTTP.Proxy detectProxy() {
+    protected synchronized org.ibex.net.HTTP.Proxy _detectProxy() { return null; }
+    public static synchronized org.ibex.net.HTTP.Proxy detectProxy() {
 
         if (cachedProxyInfo != null) return cachedProxyInfo;
         if (alreadyDetectedProxy) return null;
         alreadyDetectedProxy = true;
 
         Log.info(Platform.class, "attempting environment-variable DNS proxy detection");
-        cachedProxyInfo = org.ibex.HTTP.Proxy.detectProxyViaManual();
+        cachedProxyInfo = org.ibex.net.HTTP.Proxy.detectProxyViaManual();
         if (cachedProxyInfo != null) return cachedProxyInfo;
 
         Log.info(Platform.class, "attempting " + platform.getClass().getName() + " proxy detection");
@@ -270,7 +275,7 @@ public abstract class Platform {
     // FEATURE: be more efficient for many of the subclasses
     public static class DefaultGlyph extends Font.Glyph {
         private Picture p = null;
-        public DefaultGlyph(org.ibex.Font f, char c) { super(f, c); }
+        public DefaultGlyph(org.ibex.graphics.Font f, char c) { super(f, c); }
         public Picture getPicture() {
             if (p == null && isLoaded) {
                 Picture p = createPicture(null);
index 592baf9..e034258 100644 (file)
@@ -5,6 +5,9 @@ import org.ibex.*;
 import org.ibex.util.*;
 import java.util.*;
 import org.ibex.js.*;
+import org.ibex.graphics.*;
+import org.ibex.core.*;
+import org.ibex.net.*;
 
 /** Platform specific code for GCJ-compiled Win32 binaries */
 public class Win32 extends GCJ {
index 80db668..46a549e 100644 (file)
@@ -5,6 +5,9 @@ import gnu.gcj.RawData;
 import java.util.*;
 import org.ibex.js.*;
 import org.ibex.util.*;
+import org.ibex.graphics.*;
+import org.ibex.core.*;
+import org.ibex.net.*;
 import org.ibex.*;
 
 /** Platform implementation for POSIX compliant operating systems with an X11 Server */
index 36d8542..615db24 100644 (file)
@@ -27,7 +27,7 @@ public class BalancedTree {
 
     /** the number of elements in the tree */
     public final int treeSize() { return root == 0 ? 0 : size[root]; }
-    
+
     /** clamps index to [0..treeSize()] and inserts object o *before* the specified index */
     public final synchronized void insertNode(int index, Object o) {
         if(o == null) throw new Error("can't insert nulls in the balanced tree");
@@ -169,14 +169,13 @@ public class BalancedTree {
         // collisions when a single Object is inserted into multiple
         // trees
         int dest = Math.abs(o.hashCode() ^ this.hashCode()) % objects.length;
-        if (dest == 0) dest = 1;
         Object search = alloc ? null : o;
         int odest = dest;
         boolean plus = true;
         int tries = 1;
         while (objects[dest] != search || !(alloc || root(dest) == root)) {
+            if (dest == 0) dest++;
             dest = Math.abs((odest + (plus ? 1 : -1) * tries * tries) % objects.length);
-            if (dest == 0) dest=1;
             if (plus) tries++;
             plus = !plus;
             // FEATURE: GROW - if(tries > MAX_SLOT_DISTANCE) return -1;
@@ -224,11 +223,13 @@ public class BalancedTree {
         int c = left[d];
         if (d <= 0) throw new Error("rotation error");
         left[d] = b;
-        right[b] = c <= 0 ? -d : c;
+        if(size[b] <= 3) // b is now a leaf
+            right[b] = -d;
+        else
+            right[b] = c;
         parent[b] = d;
         parent[d] = p;
         if(c > 0) parent[c] = b;
-        
         if (p == 0)              root = d;
         else if (left[p] == b)   left[p] = d;
         else if (right[p] == b)  right[p] = d;
@@ -332,6 +333,7 @@ public class BalancedTree {
 
         // we found the node to delete
         } else {
+
             // fast path: it has no children
             if (left[slot] <= 0 && right[slot] <= 0) {
                 if (p == 0) root = 0;
@@ -339,6 +341,7 @@ public class BalancedTree {
                     int[] side = left[p] == slot ? left : right;
                     side[p] = side[slot];      // fix parent's pointer
                 }
+                
             // fast path: it has no left child, so we replace it with its right child
             } else if (left[slot] <= 0) {
                 if (p == 0) root = right[slot];
diff --git a/src/org/ibex/util/EjAlbertBrowserLauncher.java b/src/org/ibex/util/EjAlbertBrowserLauncher.java
new file mode 100644 (file)
index 0000000..a2bb059
--- /dev/null
@@ -0,0 +1,589 @@
+package org.ibex.util;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+/**
+ * BrowserLauncher is a class that provides one static method, openURL, which opens the default
+ * web browser for the current user of the system to the given URL.  It may support other
+ * protocols depending on the system -- mailto, ftp, etc. -- but that has not been rigorously
+ * tested and is not guaranteed to work.
+ * <p>
+ * Yes, this is platform-specific code, and yes, it may rely on classes on certain platforms
+ * that are not part of the standard JDK.  What we're trying to do, though, is to take something
+ * that's frequently desirable but inherently platform-specific -- opening a default browser --
+ * and allow programmers (you, for example) to do so without worrying about dropping into native
+ * code or doing anything else similarly evil.
+ * <p>
+ * Anyway, this code is completely in Java and will run on all JDK 1.1-compliant systems without
+ * modification or a need for additional libraries.  All classes that are required on certain
+ * platforms to allow this to run are dynamically loaded at runtime via reflection and, if not
+ * found, will not cause this to do anything other than returning an error when opening the
+ * browser.
+ * <p>
+ * There are certain system requirements for this class, as it's running through Runtime.exec(),
+ * which is Java's way of making a native system call.  Currently, this requires that a Macintosh
+ * have a Finder which supports the GURL event, which is true for Mac OS 8.0 and 8.1 systems that
+ * have the Internet Scripting AppleScript dictionary installed in the Scripting Additions folder
+ * in the Extensions folder (which is installed by default as far as I know under Mac OS 8.0 and
+ * 8.1), and for all Mac OS 8.5 and later systems.  On Windows, it only runs under Win32 systems
+ * (Windows 95, 98, and NT 4.0, as well as later versions of all).  On other systems, this drops
+ * back from the inherently platform-sensitive concept of a default browser and simply attempts
+ * to launch Netscape via a shell command.
+ * <p>
+ * This code is Copyright 1999-2001 by Eric Albert (ejalbert@cs.stanford.edu) and may be
+ * redistributed or modified in any form without restrictions as long as the portion of this
+ * comment from this paragraph through the end of the comment is not removed.  The author
+ * requests that he be notified of any application, applet, or other binary that makes use of
+ * this code, but that's more out of curiosity than anything and is not required.  This software
+ * includes no warranty.  The author is not repsonsible for any loss of data or functionality
+ * or any adverse or unexpected effects of using this software.
+ * <p>
+ * Credits:
+ * <br>Steven Spencer, JavaWorld magazine (<a href="http://www.javaworld.com/javaworld/javatips/jw-javatip66.html">Java Tip 66</a>)
+ * <br>Thanks also to Ron B. Yeh, Eric Shapiro, Ben Engber, Paul Teitlebaum, Andrea Cantatore,
+ * Larry Barowski, Trevor Bedzek, Frank Miedrich, and Ron Rabakukk
+ *
+ * @author Eric Albert (<a href="mailto:ejalbert@cs.stanford.edu">ejalbert@cs.stanford.edu</a>)
+ * @version 1.4b1 (Released June 20, 2001)
+ */
+public class EjAlbertBrowserLauncher {
+
+       /**
+        * The Java virtual machine that we are running on.  Actually, in most cases we only care
+        * about the operating system, but some operating systems require us to switch on the VM. */
+       private static int jvm;
+
+       /** The browser for the system */
+       private static Object browser;
+
+       /**
+        * Caches whether any classes, methods, and fields that are not part of the JDK and need to
+        * be dynamically loaded at runtime loaded successfully.
+        * <p>
+        * Note that if this is <code>false</code>, <code>openURL()</code> will always return an
+        * IOException.
+        */
+       private static boolean loadedWithoutErrors;
+
+       /** The com.apple.mrj.MRJFileUtils class */
+       private static Class mrjFileUtilsClass;
+
+       /** The com.apple.mrj.MRJOSType class */
+       private static Class mrjOSTypeClass;
+
+       /** The com.apple.MacOS.AEDesc class */
+       private static Class aeDescClass;
+       
+       /** The <init>(int) method of com.apple.MacOS.AETarget */
+       private static Constructor aeTargetConstructor;
+       
+       /** The <init>(int, int, int) method of com.apple.MacOS.AppleEvent */
+       private static Constructor appleEventConstructor;
+       
+       /** The <init>(String) method of com.apple.MacOS.AEDesc */
+       private static Constructor aeDescConstructor;
+       
+       /** The findFolder method of com.apple.mrj.MRJFileUtils */
+       private static Method findFolder;
+
+       /** The getFileCreator method of com.apple.mrj.MRJFileUtils */
+       private static Method getFileCreator;
+       
+       /** The getFileType method of com.apple.mrj.MRJFileUtils */
+       private static Method getFileType;
+       
+       /** The openURL method of com.apple.mrj.MRJFileUtils */
+       private static Method openURL;
+       
+       /** The makeOSType method of com.apple.MacOS.OSUtils */
+       private static Method makeOSType;
+       
+       /** The putParameter method of com.apple.MacOS.AppleEvent */
+       private static Method putParameter;
+       
+       /** The sendNoReply method of com.apple.MacOS.AppleEvent */
+       private static Method sendNoReply;
+       
+       /** Actually an MRJOSType pointing to the System Folder on a Macintosh */
+       private static Object kSystemFolderType;
+
+       /** The keyDirectObject AppleEvent parameter type */
+       private static Integer keyDirectObject;
+
+       /** The kAutoGenerateReturnID AppleEvent code */
+       private static Integer kAutoGenerateReturnID;
+       
+       /** The kAnyTransactionID AppleEvent code */
+       private static Integer kAnyTransactionID;
+
+       /** The linkage object required for JDirect 3 on Mac OS X. */
+       private static Object linkage;
+       
+       /** The framework to reference on Mac OS X */
+       private static final String JDirect_MacOSX = "/System/Library/Frameworks/Carbon.framework/Frameworks/HIToolbox.framework/HIToolbox";
+
+       /** JVM constant for MRJ 2.0 */
+       private static final int MRJ_2_0 = 0;
+       
+       /** JVM constant for MRJ 2.1 or later */
+       private static final int MRJ_2_1 = 1;
+
+       /** JVM constant for Java on Mac OS X 10.0 (MRJ 3.0) */
+       private static final int MRJ_3_0 = 3;
+       
+       /** JVM constant for MRJ 3.1 */
+       private static final int MRJ_3_1 = 4;
+
+       /** JVM constant for any Windows NT JVM */
+       private static final int WINDOWS_NT = 5;
+       
+       /** JVM constant for any Windows 9x JVM */
+       private static final int WINDOWS_9x = 6;
+
+       /** JVM constant for any other platform */
+       private static final int OTHER = -1;
+
+       /**
+        * The file type of the Finder on a Macintosh.  Hardcoding "Finder" would keep non-U.S. English
+        * systems from working properly.
+        */
+       private static final String FINDER_TYPE = "FNDR";
+
+       /**
+        * The creator code of the Finder on a Macintosh, which is needed to send AppleEvents to the
+        * application.
+        */
+       private static final String FINDER_CREATOR = "MACS";
+
+       /** The name for the AppleEvent type corresponding to a GetURL event. */
+       private static final String GURL_EVENT = "GURL";
+
+       /**
+        * The first parameter that needs to be passed into Runtime.exec() to open the default web
+        * browser on Windows.
+        */
+    private static final String FIRST_WINDOWS_PARAMETER = "/c";
+    
+    /** The second parameter for Runtime.exec() on Windows. */
+    private static final String SECOND_WINDOWS_PARAMETER = "start";
+    
+    /**
+     * The third parameter for Runtime.exec() on Windows.  This is a "title"
+     * parameter that the command line expects.  Setting this parameter allows
+     * URLs containing spaces to work.
+     */
+    private static final String THIRD_WINDOWS_PARAMETER = "\"\"";
+       
+       /**
+        * The shell parameters for Netscape that opens a given URL in an already-open copy of Netscape
+        * on many command-line systems.
+        */
+       private static final String NETSCAPE_REMOTE_PARAMETER = "-remote";
+       private static final String NETSCAPE_OPEN_PARAMETER_START = "'openURL(";
+       private static final String NETSCAPE_OPEN_PARAMETER_END = ")'";
+       
+       /**
+        * The message from any exception thrown throughout the initialization process.
+        */
+       private static String errorMessage;
+
+       /**
+        * An initialization block that determines the operating system and loads the necessary
+        * runtime data.
+        */
+       static {
+               loadedWithoutErrors = true;
+               String osName = System.getProperty("os.name");
+               if (osName.startsWith("Mac OS")) {
+                       String mrjVersion = System.getProperty("mrj.version");
+                       String majorMRJVersion = mrjVersion.substring(0, 3);
+                       try {
+                               double version = Double.valueOf(majorMRJVersion).doubleValue();
+                               if (version == 2) {
+                                       jvm = MRJ_2_0;
+                               } else if (version >= 2.1 && version < 3) {
+                                       // Assume that all 2.x versions of MRJ work the same.  MRJ 2.1 actually
+                                       // works via Runtime.exec() and 2.2 supports that but has an openURL() method
+                                       // as well that we currently ignore.
+                                       jvm = MRJ_2_1;
+                               } else if (version == 3.0) {
+                                       jvm = MRJ_3_0;
+                               } else if (version >= 3.1) {
+                                       // Assume that all 3.1 and later versions of MRJ work the same.
+                                       jvm = MRJ_3_1;
+                               } else {
+                                       loadedWithoutErrors = false;
+                                       errorMessage = "Unsupported MRJ version: " + version;
+                               }
+                       } catch (NumberFormatException nfe) {
+                               loadedWithoutErrors = false;
+                               errorMessage = "Invalid MRJ version: " + mrjVersion;
+                       }
+               } else if (osName.startsWith("Windows")) {
+                       if (osName.indexOf("9") != -1) {
+                               jvm = WINDOWS_9x;
+                       } else {
+                               jvm = WINDOWS_NT;
+                       }
+               } else {
+                       jvm = OTHER;
+               }
+               
+               if (loadedWithoutErrors) {      // if we haven't hit any errors yet
+                       loadedWithoutErrors = loadClasses();
+               }
+       }
+
+       /**
+        * This class should be never be instantiated; this just ensures so.
+        */
+       private EjAlbertBrowserLauncher() { }
+       
+       /**
+        * Called by a static initializer to load any classes, fields, and methods required at runtime
+        * to locate the user's web browser.
+        * @return <code>true</code> if all intialization succeeded
+        *                      <code>false</code> if any portion of the initialization failed
+        */
+       private static boolean loadClasses() {
+               switch (jvm) {
+                       case MRJ_2_0:
+                               try {
+                                       Class aeTargetClass = Class.forName("com.apple.MacOS.AETarget");
+                                       Class osUtilsClass = Class.forName("com.apple.MacOS.OSUtils");
+                                       Class appleEventClass = Class.forName("com.apple.MacOS.AppleEvent");
+                                       Class aeClass = Class.forName("com.apple.MacOS.ae");
+                                       aeDescClass = Class.forName("com.apple.MacOS.AEDesc");
+
+                                       aeTargetConstructor = aeTargetClass.getDeclaredConstructor(new Class [] { int.class });
+                                       appleEventConstructor = appleEventClass.getDeclaredConstructor(new Class[] { int.class, int.class, aeTargetClass, int.class, int.class });
+                                       aeDescConstructor = aeDescClass.getDeclaredConstructor(new Class[] { String.class });
+
+                                       makeOSType = osUtilsClass.getDeclaredMethod("makeOSType", new Class [] { String.class });
+                                       putParameter = appleEventClass.getDeclaredMethod("putParameter", new Class[] { int.class, aeDescClass });
+                                       sendNoReply = appleEventClass.getDeclaredMethod("sendNoReply", new Class[] { });
+
+                                       Field keyDirectObjectField = aeClass.getDeclaredField("keyDirectObject");
+                                       keyDirectObject = (Integer) keyDirectObjectField.get(null);
+                                       Field autoGenerateReturnIDField = appleEventClass.getDeclaredField("kAutoGenerateReturnID");
+                                       kAutoGenerateReturnID = (Integer) autoGenerateReturnIDField.get(null);
+                                       Field anyTransactionIDField = appleEventClass.getDeclaredField("kAnyTransactionID");
+                                       kAnyTransactionID = (Integer) anyTransactionIDField.get(null);
+                               } catch (ClassNotFoundException cnfe) {
+                                       errorMessage = cnfe.getMessage();
+                                       return false;
+                               } catch (NoSuchMethodException nsme) {
+                                       errorMessage = nsme.getMessage();
+                                       return false;
+                               } catch (NoSuchFieldException nsfe) {
+                                       errorMessage = nsfe.getMessage();
+                                       return false;
+                               } catch (IllegalAccessException iae) {
+                                       errorMessage = iae.getMessage();
+                                       return false;
+                               }
+                               break;
+                       case MRJ_2_1:
+                               try {
+                                       mrjFileUtilsClass = Class.forName("com.apple.mrj.MRJFileUtils");
+                                       mrjOSTypeClass = Class.forName("com.apple.mrj.MRJOSType");
+                                       Field systemFolderField = mrjFileUtilsClass.getDeclaredField("kSystemFolderType");
+                                       kSystemFolderType = systemFolderField.get(null);
+                                       findFolder = mrjFileUtilsClass.getDeclaredMethod("findFolder", new Class[] { mrjOSTypeClass });
+                                       getFileCreator = mrjFileUtilsClass.getDeclaredMethod("getFileCreator", new Class[] { File.class });
+                                       getFileType = mrjFileUtilsClass.getDeclaredMethod("getFileType", new Class[] { File.class });
+                               } catch (ClassNotFoundException cnfe) {
+                                       errorMessage = cnfe.getMessage();
+                                       return false;
+                               } catch (NoSuchFieldException nsfe) {
+                                       errorMessage = nsfe.getMessage();
+                                       return false;
+                               } catch (NoSuchMethodException nsme) {
+                                       errorMessage = nsme.getMessage();
+                                       return false;
+                               } catch (SecurityException se) {
+                                       errorMessage = se.getMessage();
+                                       return false;
+                               } catch (IllegalAccessException iae) {
+                                       errorMessage = iae.getMessage();
+                                       return false;
+                               }
+                               break;
+                       case MRJ_3_0:
+                           try {
+                                       Class linker = Class.forName("com.apple.mrj.jdirect.Linker");
+                                       Constructor constructor = linker.getConstructor(new Class[]{ Class.class });
+                                       linkage = constructor.newInstance(new Object[] { EjAlbertBrowserLauncher.class });
+                               } catch (ClassNotFoundException cnfe) {
+                                       errorMessage = cnfe.getMessage();
+                                       return false;
+                               } catch (NoSuchMethodException nsme) {
+                                       errorMessage = nsme.getMessage();
+                                       return false;
+                               } catch (InvocationTargetException ite) {
+                                       errorMessage = ite.getMessage();
+                                       return false;
+                               } catch (InstantiationException ie) {
+                                       errorMessage = ie.getMessage();
+                                       return false;
+                               } catch (IllegalAccessException iae) {
+                                       errorMessage = iae.getMessage();
+                                       return false;
+                               }
+                               break;
+                       case MRJ_3_1:
+                               try {
+                                       mrjFileUtilsClass = Class.forName("com.apple.mrj.MRJFileUtils");
+                                       openURL = mrjFileUtilsClass.getDeclaredMethod("openURL", new Class[] { String.class });
+                               } catch (ClassNotFoundException cnfe) {
+                                       errorMessage = cnfe.getMessage();
+                                       return false;
+                               } catch (NoSuchMethodException nsme) {
+                                       errorMessage = nsme.getMessage();
+                                       return false;
+                               }
+                               break;
+                       default:
+                           break;
+               }
+               return true;
+       }
+
+       /**
+        * Attempts to locate the default web browser on the local system.  Caches results so it
+        * only locates the browser once for each use of this class per JVM instance.
+        * @return The browser for the system.  Note that this may not be what you would consider
+        *                      to be a standard web browser; instead, it's the application that gets called to
+        *                      open the default web browser.  In some cases, this will be a non-String object
+        *                      that provides the means of calling the default browser.
+        */
+       private static Object locateBrowser() {
+               if (browser != null) {
+                       return browser;
+               }
+               switch (jvm) {
+                       case MRJ_2_0:
+                               try {
+                                       Integer finderCreatorCode = (Integer) makeOSType.invoke(null, new Object[] { FINDER_CREATOR });
+                                       Object aeTarget = aeTargetConstructor.newInstance(new Object[] { finderCreatorCode });
+                                       Integer gurlType = (Integer) makeOSType.invoke(null, new Object[] { GURL_EVENT });
+                                       Object appleEvent = appleEventConstructor.newInstance(new Object[] { gurlType, gurlType, aeTarget, kAutoGenerateReturnID, kAnyTransactionID });
+                                       // Don't set browser = appleEvent because then the next time we call
+                                       // locateBrowser(), we'll get the same AppleEvent, to which we'll already have
+                                       // added the relevant parameter. Instead, regenerate the AppleEvent every time.
+                                       // There's probably a way to do this better; if any has any ideas, please let
+                                       // me know.
+                                       return appleEvent;
+                               } catch (IllegalAccessException iae) {
+                                       browser = null;
+                                       errorMessage = iae.getMessage();
+                                       return browser;
+                               } catch (InstantiationException ie) {
+                                       browser = null;
+                                       errorMessage = ie.getMessage();
+                                       return browser;
+                               } catch (InvocationTargetException ite) {
+                                       browser = null;
+                                       errorMessage = ite.getMessage();
+                                       return browser;
+                               }
+                       case MRJ_2_1:
+                               File systemFolder;
+                               try {
+                                       systemFolder = (File) findFolder.invoke(null, new Object[] { kSystemFolderType });
+                               } catch (IllegalArgumentException iare) {
+                                       browser = null;
+                                       errorMessage = iare.getMessage();
+                                       return browser;
+                               } catch (IllegalAccessException iae) {
+                                       browser = null;
+                                       errorMessage = iae.getMessage();
+                                       return browser;
+                               } catch (InvocationTargetException ite) {
+                                       browser = null;
+                                       errorMessage = ite.getTargetException().getClass() + ": " + ite.getTargetException().getMessage();
+                                       return browser;
+                               }
+                               String[] systemFolderFiles = systemFolder.list();
+                               // Avoid a FilenameFilter because that can't be stopped mid-list
+                               for(int i = 0; i < systemFolderFiles.length; i++) {
+                                       try {
+                                               File file = new File(systemFolder, systemFolderFiles[i]);
+                                               if (!file.isFile()) {
+                                                       continue;
+                                               }
+                                               // We're looking for a file with a creator code of 'MACS' and
+                                               // a type of 'FNDR'.  Only requiring the type results in non-Finder
+                                               // applications being picked up on certain Mac OS 9 systems,
+                                               // especially German ones, and sending a GURL event to those
+                                               // applications results in a logout under Multiple Users.
+                                               Object fileType = getFileType.invoke(null, new Object[] { file });
+                                               if (FINDER_TYPE.equals(fileType.toString())) {
+                                                       Object fileCreator = getFileCreator.invoke(null, new Object[] { file });
+                                                       if (FINDER_CREATOR.equals(fileCreator.toString())) {
+                                                               browser = file.toString();      // Actually the Finder, but that's OK
+                                                               return browser;
+                                                       }
+                                               }
+                                       } catch (IllegalArgumentException iare) {
+                                               browser = browser;
+                                               errorMessage = iare.getMessage();
+                                               return null;
+                                       } catch (IllegalAccessException iae) {
+                                               browser = null;
+                                               errorMessage = iae.getMessage();
+                                               return browser;
+                                       } catch (InvocationTargetException ite) {
+                                               browser = null;
+                                               errorMessage = ite.getTargetException().getClass() + ": " + ite.getTargetException().getMessage();
+                                               return browser;
+                                       }
+                               }
+                               browser = null;
+                               break;
+                       case MRJ_3_0:
+                       case MRJ_3_1:
+                               browser = "";   // Return something non-null
+                               break;
+                       case WINDOWS_NT:
+                               browser = "cmd.exe";
+                               break;
+                       case WINDOWS_9x:
+                               browser = "command.com";
+                               break;
+                       case OTHER:
+                       default:
+                               browser = "netscape";
+                               break;
+               }
+               return browser;
+       }
+
+       /**
+        * Attempts to open the default web browser to the given URL.
+        * @param url The URL to open
+        * @throws IOException If the web browser could not be located or does not run
+        */
+       public static void openURL(String url) throws IOException {
+               if (!loadedWithoutErrors) {
+                       throw new IOException("Exception in finding browser: " + errorMessage);
+               }
+               Object browser = locateBrowser();
+               if (browser == null) {
+                       throw new IOException("Unable to locate browser: " + errorMessage);
+               }
+               
+               switch (jvm) {
+                       case MRJ_2_0:
+                               Object aeDesc = null;
+                               try {
+                                       aeDesc = aeDescConstructor.newInstance(new Object[] { url });
+                                       putParameter.invoke(browser, new Object[] { keyDirectObject, aeDesc });
+                                       sendNoReply.invoke(browser, new Object[] { });
+                               } catch (InvocationTargetException ite) {
+                                       throw new IOException("InvocationTargetException while creating AEDesc: " + ite.getMessage());
+                               } catch (IllegalAccessException iae) {
+                                       throw new IOException("IllegalAccessException while building AppleEvent: " + iae.getMessage());
+                               } catch (InstantiationException ie) {
+                                       throw new IOException("InstantiationException while creating AEDesc: " + ie.getMessage());
+                               } finally {
+                                       aeDesc = null;  // Encourage it to get disposed if it was created
+                                       browser = null; // Ditto
+                               }
+                               break;
+                       case MRJ_2_1:
+                               Runtime.getRuntime().exec(new String[] { (String) browser, url } );
+                               break;
+                       case MRJ_3_0:
+                               int[] instance = new int[1];
+                               int result = ICStart(instance, 0);
+                               if (result == 0) {
+                                       int[] selectionStart = new int[] { 0 };
+                                       byte[] urlBytes = url.getBytes();
+                                       int[] selectionEnd = new int[] { urlBytes.length };
+                                       result = ICLaunchURL(instance[0], new byte[] { 0 }, urlBytes,
+                                                                                       urlBytes.length, selectionStart,
+                                                                                       selectionEnd);
+                                       if (result == 0) {
+                                               // Ignore the return value; the URL was launched successfully
+                                               // regardless of what happens here.
+                                               ICStop(instance);
+                                       } else {
+                                               throw new IOException("Unable to launch URL: " + result);
+                                       }
+                               } else {
+                                       throw new IOException("Unable to create an Internet Config instance: " + result);
+                               }
+                               break;
+                       case MRJ_3_1:
+                               try {
+                                       openURL.invoke(null, new Object[] { url });
+                               } catch (InvocationTargetException ite) {
+                                       throw new IOException("InvocationTargetException while calling openURL: " + ite.getMessage());
+                               } catch (IllegalAccessException iae) {
+                                       throw new IOException("IllegalAccessException while calling openURL: " + iae.getMessage());
+                               }
+                               break;
+                   case WINDOWS_NT:
+                   case WINDOWS_9x:
+                       // Add quotes around the URL to allow ampersands and other special
+                       // characters to work.
+                               Process process = Runtime.getRuntime().exec(new String[] { (String) browser,
+                                                                                                                               FIRST_WINDOWS_PARAMETER,
+                                                                                                                               SECOND_WINDOWS_PARAMETER,
+                                                                                                                               THIRD_WINDOWS_PARAMETER,
+                                                                                                                               '"' + url + '"' });
+                               // This avoids a memory leak on some versions of Java on Windows.
+                               // That's hinted at in <http://developer.java.sun.com/developer/qow/archive/68/>.
+                               try {
+                                       process.waitFor();
+                                       process.exitValue();
+                               } catch (InterruptedException ie) {
+                                       throw new IOException("InterruptedException while launching browser: " + ie.getMessage());
+                               }
+                               break;
+                       case OTHER:
+                               // Assume that we're on Unix and that Netscape is installed
+                               
+                               // First, attempt to open the URL in a currently running session of Netscape
+                               process = Runtime.getRuntime().exec(new String[] { (String) browser,
+                                                                                                       NETSCAPE_REMOTE_PARAMETER,
+                                                                                                       NETSCAPE_OPEN_PARAMETER_START +
+                                                                                                       url +
+                                                                                                       NETSCAPE_OPEN_PARAMETER_END });
+                               try {
+                                       int exitCode = process.waitFor();
+                                       if (exitCode != 0) {    // if Netscape was not open
+                                               Runtime.getRuntime().exec(new String[] { (String) browser, url });
+                                       }
+                               } catch (InterruptedException ie) {
+                                       throw new IOException("InterruptedException while launching browser: " + ie.getMessage());
+                               }
+                               break;
+                       default:
+                               // This should never occur, but if it does, we'll try the simplest thing possible
+                               Runtime.getRuntime().exec(new String[] { (String) browser, url });
+                               break;
+               }
+       }
+
+       /**
+        * Methods required for Mac OS X.  The presence of native methods does not cause
+        * any problems on other platforms.
+        */
+    /*
+       private native static int ICStart(int[] instance, int signature);
+       private native static int ICStop(int[] instance);
+       private native static int ICLaunchURL(int instance, byte[] hint, byte[] data, int len,
+                                                                                       int[] selectionStart, int[] selectionEnd);
+    */
+    private static int ICStart(int[] instance, int signature) { return 0; }
+    private static int ICStop(int[] instance) { return 0; }
+    private static int ICLaunchURL(int instance, byte[] hint, byte[] data, int len,
+        int[] selectionStart, int[] selectionEnd) { return 0; }
+}
index c6c988d..625ffec 100644 (file)
@@ -1,6 +1,6 @@
-package org.ibex.translators;
+package org.ibex.util;
 
-import org.ibex.Main;
+import org.ibex.core.Main;
 import org.ibex.util.*;
 import org.xwt.mips.*;
 import java.io.*;
@@ -18,7 +18,7 @@ public class MSPack {
         
     public MSPack(InputStream cabIS) throws IOException {
         try {
-            Runtime vm = (Runtime)Class.forName("org.ibex.translators.MIPSApps").newInstance();
+            Runtime vm = (Runtime)Class.forName("org.ibex.util.MIPSApps").newInstance();
             byte[] cab = InputStreamToByteArray.convert(cabIS);
             int cabAddr = vm.sbrk(cab.length);
             if(cabAddr < 0) throw new MSPackException("sbrk failed");
diff --git a/src/org/ibex/util/SSL.java b/src/org/ibex/util/SSL.java
deleted file mode 100644 (file)
index 25c76ac..0000000
+++ /dev/null
@@ -1,1659 +0,0 @@
-// Copyright (C) 2003 Adam Megacz <adam@ibex.org> all rights reserved.
-//
-// You may modify, copy, and redistribute this code under the terms of
-// the GNU Library Public License version 2.1, with the exception of
-// the portion of clause 6a after the semicolon (aka the "obnoxious
-// relink clause")
-
-package org.ibex.util;
-
-import org.bouncycastle.crypto.AsymmetricBlockCipher;
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.InvalidCipherTextException;
-import org.bouncycastle.crypto.params.RSAKeyParameters;
-import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.crypto.digests.SHA1Digest;
-import org.bouncycastle.crypto.digests.MD5Digest;
-import org.bouncycastle.crypto.digests.MD2Digest;
-import org.bouncycastle.crypto.engines.RSAEngine;
-import org.bouncycastle.crypto.engines.RC4Engine;
-import org.bouncycastle.util.encoders.Base64;
-import org.bouncycastle.asn1.DERInputStream;
-import org.bouncycastle.asn1.DEROutputStream;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERObject;
-import org.bouncycastle.asn1.DEROctetString;
-import org.bouncycastle.asn1.BERInputStream;
-import org.bouncycastle.asn1.x509.X509CertificateStructure;
-import org.bouncycastle.asn1.x509.RSAPublicKeyStructure;
-import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
-import org.bouncycastle.asn1.x509.TBSCertificateStructure;
-import org.bouncycastle.asn1.x509.X509Name;
-import org.bouncycastle.asn1.x509.X509Extensions;
-import org.bouncycastle.asn1.x509.X509Extension;
-import org.bouncycastle.asn1.x509.BasicConstraints;
-import org.ibex.util.Log;
-import java.net.*;
-import java.io.*;
-import java.util.*;
-import java.math.*;
-import java.text.*;
-
-/**
-
-   TinySSL: a tiny SSL implementation in Java, built on the
-            bouncycastle.org lightweight crypto library.
-
-   This class implements an SSLv3 client-side socket, with the
-   SSL_RSA_EXPORT_WITH_RC4_40_MD5 and SSL_RSA_WITH_RC4_128_MD5 cipher
-   suites, as well as certificate chain verification against a
-   collection of 93 built-in Trusted Root CA public keys (the same 93
-   included with Microsoft Internet Explorer 5.5 SP2).
-
-   As of 07-Dec-01, the zipped bytecode for this class is 43k, and the
-   subset of bouncycastle it requires is 82k.
-
-   This class should work correctly on any Java 1.1 compliant
-   platform. The java.security.* classes are not used.
-
-   The main design goal for this class was the smallest possible body
-   of code capable of connecting to 99% of all active HTTPS
-   servers. Although this class is useful in many other situations
-   (IMAPS, Secure SMTP, etc), the author will refuse all feature
-   requests and submitted patches which go beyond this scope.
-
-   Because of the limited goals of this class, certain abstractions
-   have been avoided, and certain parameters have been
-   hard-coded. "Magic numbers" are often used instead of "static final
-   int"'s, although they are usually accompanied by a descriptive
-   comment. Numeric offsets into byte arrays are also favored over
-   DataInputStream(ByteArrayInputStream(foo))'s.
-
-   Much thanks and credit go to the BouncyCastle team for producing
-   such a first-class library, and for helping me out on the
-   dev-crypto mailing list while I was writing this.
-
-   Revision History:
-
-   1.0  07-Dec-01  Initial Release
-
-   1.01 15-Mar-02  Added PKCS1 class to avoid dependancy on java.security.SecureRandom
-
-   1.02 27-Mar-02  Fixed a bug which would hang the connection when more than one
-                   Handshake message appeared in the same TLS Record
-
-   1.03 10-Aug-02  Fixed a vulnerability outlined at
-                   http://online.securityfocus.com/archive/1/286290
-
-   1.04 12-Dec-03  Renamed to org.ibex.SSL, fixed race condition
-
-*/
-
-public class SSL extends Socket {
-
-    // Simple Test //////////////////////////////////////////////
-
-    public static void main(String[] args) {
-        Log.on = true;
-        try {
-            Socket s = new SSL("www.paypal.com", 443);
-            PrintWriter pw = new PrintWriter(s.getOutputStream());
-            BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
-            pw.println("GET / HTTP/1.0");
-            pw.println("");
-            pw.flush();
-            
-            while(true) {
-                String s2 = br.readLine();
-                if (s2 == null) return;
-                Log.info(SSL.class, s2);
-            }
-            
-        } catch (Exception e) {
-            e.printStackTrace();
-        }
-    }
-
-    // Static Data //////////////////////////////////////////////
-
-    public static class SSLException extends IOException { public SSLException(String s) { super(s); } }
-    static SubjectPublicKeyInfo[] trusted_CA_public_keys;
-    static String[] trusted_CA_public_key_identifiers;
-    public static byte[] pad1 = new byte[48];
-    public static byte[] pad2 = new byte[48];
-    public static byte[] pad1_sha = new byte[40];
-    public static byte[] pad2_sha = new byte[40];
-    static byte[] randpool;
-    static long randcnt = 0;
-
-    // Cipher State //////////////////////////////////////////////
-
-    public byte[] server_random = new byte[32];
-    public byte[] client_random = new byte[32];
-    public byte[] client_write_MAC_secret = new byte[16];        
-    public byte[] server_write_MAC_secret = new byte[16];        
-    public byte[] client_write_key = null;
-    public byte[] server_write_key = null;
-    public byte[] master_secret = null;
-
-    /** the bytes of the ServerKeyExchangeMessage, null if none recieved */
-    public byte[] serverKeyExchange = null;
-
-    /** true iff the server asked for a certificate */
-    public boolean cert_requested = false;
-
-    public X509CertificateStructure server_cert = null;
-
-    public SSLOutputStream os = null;
-    public SSLInputStream is = null;
-
-    String hostname;
-
-    /** if true, we don't mind if the server's cert isn't signed by a CA. USE WITH CAUTION! */
-    boolean ignoreUntrustedCert = false;
-
-    /** the concatenation of all the bytes of all handshake messages sent or recieved */
-    public byte[] handshakes = new byte[] { };
-
-    /** true iff we're using SSL_RSA_EXPORT_WITH_RC4_40_MD5 */
-    boolean export = false;
-
-    public InputStream getInputStream() throws IOException { return is != null ? is : super.getInputStream(); }
-    public OutputStream getOutputStream() throws IOException { return os != null ? os : super.getOutputStream(); }
-
-    public SSL(String host, int port) throws IOException { this(host, port, true, false); }
-    public SSL(String host, int port, boolean negotiateImmediately) throws IOException { this(host, port, negotiateImmediately, false); }
-    public SSL(String host, int port, boolean negotiateImmediately, boolean ignoreUntrustedCert) throws IOException {
-        super(host, port);
-        if (!initializationFinished) {
-            synchronized(SSL.class) {
-                while (!initializationFinished)
-                    try { SSL.class.wait(); } catch (Exception e) { }
-            }
-        }
-        hostname = host;
-        this.ignoreUntrustedCert = ignoreUntrustedCert;
-        if (negotiateImmediately) negotiate();
-    }
-
-    /** negotiates the SSL connection */
-    public void negotiate() throws IOException {
-        os = new SSLOutputStream(super.getOutputStream());
-        is = new SSLInputStream(super.getInputStream());
-        os.writeClientHello();
-        is.readServerHandshakes();
-        os.sendClientHandshakes();
-        is.readServerFinished();
-    }
-
-    class SSLInputStream extends InputStream {
-        
-        /** the underlying inputstream */
-        DataInputStream raw;
-
-        /** the server's sequence number */
-        public int seq_num = 0;
-
-        /** the decryption engine */
-        public RC4Engine rc4 = null;
-        
-        /** pending bytes -- decrypted, but not yet fed to consumer */
-        byte[] pend = null;
-        int pendstart = 0;
-        int pendlen = 0;
-
-        public void mark() { }
-        public void reset() { }
-        public boolean markSupported() { return false; }
-        public long skip(long l) throws IOException { for(long i=0; i<l; i++) read(); return l; }
-        public SSLInputStream(InputStream raw) { this.raw = new DataInputStream(raw); }
-        public int available() throws IOException { return pendlen; }
-
-        public int read() throws IOException {
-            byte[] singlebyte = new byte[1];
-            int numread = read(singlebyte);
-            if (numread != 1) return -1;
-            return (int)singlebyte[0];
-        }
-       
-        public int read(byte[] b, int off, int len) throws IOException {
-            if (pendlen == 0) {
-                pend = readRecord();
-                if (pend == null) return -1;
-                pendstart = 0;
-                pendlen = pend.length;
-            }
-            int ret = Math.min(len, pendlen);
-            System.arraycopy(pend, pendstart, b, off, ret);
-            pendlen -= ret;
-            pendstart += ret;
-            return ret;
-        }
-
-        /** reads and decrypts exactly one record; blocks if unavailable */        
-        public byte[] readRecord() throws IOException {
-
-            // we only catch EOFException here, because anywhere else
-            // would be "unusual", and we *want* and EOFException in
-            // those cases
-            byte type;
-            try { type = raw.readByte();
-            } catch (EOFException e) {
-                if (Log.on) Log.info(this, "got EOFException reading packet type");
-                return null;
-            }
-
-            byte ver_major = raw.readByte();
-            byte ver_minor = raw.readByte();
-            short len = raw.readShort();
-            if (Log.on) Log.info(this, "got record of type " + type + ", SSLv" + ver_major + "." + ver_minor + ", length=" + len);
-
-            byte[] ret = new byte[len];
-            raw.readFully(ret);
-            
-            // simply ignore ChangeCipherSpec messages -- we change as soon as we send ours
-            if (type == 20) {
-                if (Log.on) Log.info(this, "got ChangeCipherSpec; ignoring");
-                seq_num = 0;
-                return readRecord();
-            }
-
-            byte[] decrypted_payload;
-
-            // if crypto hasn't been enabled yet; skip crypt and hash
-            if (rc4 == null) decrypted_payload = ret;
-            else {
-                // decrypt the payload
-                decrypted_payload = new byte[len - 16];
-                rc4.processBytes(ret, 0, len - 16, decrypted_payload, 0);
-                
-                // check the MAC
-                byte[] MAC = new byte[16];
-                rc4.processBytes(ret, len - 16, 16, MAC, 0);
-                byte[] ourMAC = computeMAC(type, decrypted_payload, 0, decrypted_payload.length, server_write_MAC_secret, seq_num++);
-                for(int i=0; i<MAC.length; i++)
-                    if (MAC[i] != ourMAC[i])
-                        throw new SSLException("MAC mismatch on byte " + i + ": got " + MAC[i] + ", expecting " + ourMAC[i]);
-            }
-
-            if (type == 21) {
-                if (decrypted_payload[1] > 1) {
-                    throw new SSLException("got SSL ALERT message, level=" + decrypted_payload[0] + " code=" + decrypted_payload[1]);
-                } else if (decrypted_payload[1] == 0) {
-                    if (Log.on) Log.info(this, "server requested connection closure; returning null");
-                    return null;
-                } else {
-                    if (Log.on) Log.info(this, "got SSL ALERT message, level=" + decrypted_payload[0] + " code=" + decrypted_payload[1]);
-                    return readRecord();
-                }
-
-            } else if (type == 22) {
-                if (Log.on) Log.info(this, "read a handshake");
-
-            } else if (type != 23) {
-                if (Log.on) Log.info(this, "unexpected record type: " + type + "; skipping");
-                return readRecord();
-
-            }
-                
-            if (Log.on) Log.info(this, "  returning " + decrypted_payload.length + " byte record payload");
-            return decrypted_payload;
-        }
-
-        private byte[] readHandshake() throws IOException {
-            // acquire a handshake message
-            byte type = (byte)read();
-            int len = ((read() & 0xff) << 16) | ((read() & 0xff) << 8) | (read() & 0xff);
-            byte[] rec = new byte[len + 4];
-            rec[0] = type;
-            rec[1] = (byte)(((len & 0x00ff0000) >> 16) & 0xff);
-            rec[2] = (byte)(((len & 0x0000ff00) >> 8) & 0xff);
-            rec[3] = (byte)((len & 0x000000ff) & 0xff);
-            if (len > 0) read(rec, 4, len);
-            return rec;
-        }
-
-        /** This reads the ServerHello, Certificate, and ServerHelloDone handshake messages */
-        public void readServerHandshakes() throws IOException {
-            for(;;) {
-
-                byte[] rec = readHandshake();
-                handshakes = concat(new byte[][] { handshakes, rec });
-
-                switch(rec[0]) {
-                case 2: // ServerHello
-                    if (Log.on) Log.info(this, "got ServerHello");
-                    byte ver_major = rec[4];
-                    byte ver_minor = rec[5];
-                    System.arraycopy(rec, 6, server_random, 0, server_random.length);
-                    short cipher_high = rec[6 + server_random.length + rec[6 + server_random.length] + 1];
-                    short cipher_low = rec[6 + server_random.length + rec[6 + server_random.length] + 2];
-
-                    if (cipher_low == 0x04 || cipher_high != 0x00) {
-                        export = false;
-                        if (Log.on) Log.info(this, "using SSL_RSA_WITH_RC4_128_MD5");
-
-                    } else if (cipher_low == 0x03 || cipher_high != 0x00) {
-                        export = true;
-                        if (Log.on) Log.info(this, "using SSL_RSA_EXPORT_WITH_RC4_40_MD5");
-
-                    } else throw new SSLException("server asked for cipher " + ((cipher_high << 8) | cipher_low) +
-                                                " but we only do SSL_RSA_WITH_RC4_128_MD5 (0x0004) and " +
-                                                "SSL_RSA_EXPORT_WITH_RC4_40_MD5 (0x0003)");
-
-                    byte compressionMethod = rec[6 + server_random.length + rec[6 + server_random.length] + 3];
-                    if (compressionMethod != 0x0) throw new SSLException("server asked for compression method " + compressionMethod +
-                                                                         " but we don't support compression");
-                    break;
-                    
-                case 11: // Server's certificate(s)
-                    if (Log.on) Log.info(this, "got Server Certificate(s)");
-                    int numcertbytes = ((rec[4] & 0xff) << 16) | ((rec[5] & 0xff) << 8) | (rec[6] & 0xff);
-                    int numcerts = 0;
-                    X509CertificateStructure last_cert = null;
-                    X509CertificateStructure this_cert = null;
-
-                    for(int i=0; i<numcertbytes;) {
-                        int certlen = ((rec[7 + i] & 0xff) << 16) | ((rec[7 + i + 1] & 0xff) << 8) | (rec[7 + i + 2] & 0xff);
-                        try {
-                            DERInputStream dIn = new DERInputStream(new ByteArrayInputStream(rec, 7 + i + 3, certlen));
-                            this_cert = new X509CertificateStructure((DERSequence)dIn.readObject());
-                        } catch (Exception e) {
-                            SSLException t = new SSLException("error decoding server certificate: " + e);
-                            t.fillInStackTrace();
-                            throw t;
-                        }
-
-                        if (server_cert == null) {
-                            server_cert = this_cert;
-                            TBSCertificateStructure tbs = server_cert.getTBSCertificate();
-
-                            // gross hack to extract the Common Name so we can compare it to the server hostname
-                            String CN = tbs.getSubject().toString() + " ";
-                            boolean good = false;
-                            for(int j=0; j<CN.length() - 3; j++)
-                                if (CN.substring(j, j+3).equals("CN=")) {
-                                    good = true;
-                                    CN = CN.substring(j+3, CN.indexOf(' ', j+3));
-                                    break;
-                                }
-
-                            if (!good) throw new SSLException("server certificate does not seem to have a CN: " + CN);
-                            if (!ignoreUntrustedCert && !CN.equalsIgnoreCase(hostname))
-                                throw new SSLException("connecting to host " + hostname + " but server certificate was issued for " + CN);
-
-                            SimpleDateFormat dateF = new SimpleDateFormat("MM-dd-yyyy-HH-mm-ss-z");
-
-                            // the following idiocy is a result of the brokenness of the GNU Classpath's SimpleDateFormat
-                            String s = tbs.getStartDate().getTime();
-                            s = s.substring(0, 4) + "-" + s.substring(4, 6) + "-" + s.substring(6, 8) + "-" +
-                                s.substring(8, 10) + "-" + s.substring(10, 12) + "-" +
-                                s.substring(12, 14) + "-" + s.substring(14);
-
-                            Date startDate = dateF.parse(s, new ParsePosition(0));
-
-                            s = tbs.getEndDate().getTime();
-                            s = s.substring(2, 4) + "-" + s.substring(4, 6) + "-" + s.substring(0, 2) + "-" + s.substring(6, 8) + "-" +
-                                s.substring(8, 10) + "-" + s.substring(10, 12) + "-" + s.substring(12);
-                            Date endDate = dateF.parse(s, new ParsePosition(0));
-
-                            Date now = new Date();
-                            if (!ignoreUntrustedCert && now.after(endDate))
-                                throw new SSLException("server certificate expired on " + endDate);
-                            if (!ignoreUntrustedCert && now.before(startDate))
-                                throw new SSLException("server certificate will not be valid until " + startDate);
-
-                            Log.info(this, "server cert (name, validity dates) checks out okay");
-                            
-                        } else {
-
-                            // don't check the top cert since some very old root certs lack a BasicConstraints field.
-                            if (certlen + 3 + i < numcertbytes) {
-                                // defend against Mike Benham's attack
-                                X509Extension basicConstraints = this_cert.getTBSCertificate().getExtensions().getExtension(X509Extensions.BasicConstraints);
-                                if (basicConstraints == null) throw new SSLException("certificate did not contain a basic constraints block");
-                                DERInputStream dis = new DERInputStream(new ByteArrayInputStream(basicConstraints.getValue().getOctets()));
-                                BasicConstraints bc = new BasicConstraints((DERSequence)dis.readObject());
-                                if (!bc.isCA()) throw new SSLException("non-CA certificate used for signing");
-                            }
-
-                            if (!isSignedBy(last_cert, this_cert.getSubjectPublicKeyInfo()))
-                                throw new SSLException("the server sent a broken chain of certificates");
-                        }
-
-                        last_cert = this_cert;
-                        i += certlen + 3;
-                        numcerts++;
-                    }
-                    if (Log.on) Log.info(this, "  Certificate (" + numcerts + " certificates)");
-
-                    if (ignoreUntrustedCert) break;
-
-                    boolean good = false;
-
-                    // pass 1 -- only check CA's whose subject is a partial match
-                    String subject = this_cert.getSubject().toString();
-                    for(int i=0; i<trusted_CA_public_keys.length; i++) {
-                        if (subject.indexOf(trusted_CA_public_key_identifiers[i]) != -1 && isSignedBy(this_cert, trusted_CA_public_keys[i])) {
-                            if (Log.on) Log.info(this, "pass 1: server cert was signed by trusted CA " + i);
-                            good = true;
-                            break;
-                        }
-                    }
-
-                    // pass 2 -- try all certs
-                    if (!good)
-                        for(int i=0; i<trusted_CA_public_keys.length; i++) {
-                            if (isSignedBy(this_cert, trusted_CA_public_keys[i])) {
-                                if (Log.on) Log.info(this, "pass 2: server cert was signed by trusted CA " + i);
-                                good = true;
-                                break;
-                            }
-                        }
-
-                    if (!good) throw new SSLException("server cert was not signed by a trusted CA");
-                    break;
-
-                case 12: 
-                    if (Log.on) Log.info(this, "got ServerKeyExchange");
-                    serverKeyExchange = rec;
-                    break;
-
-                case 13:
-                    if (Log.on) Log.info(this, "got Request for Client Certificates");
-                    cert_requested = true;
-                    break;
-                    
-                case 14: if (Log.on) Log.info(this, "  ServerHelloDone"); return;
-                default: throw new SSLException("unknown handshake of type " + rec[0]);
-                }
-            }
-        }
-     
-        public void readServerFinished() throws IOException {
-            
-            byte[] rec = readHandshake();
-            if (rec[0] != 20) throw new SSLException("expecting server Finished message, but got message of type " + rec[0]);
-
-            byte[] expectedFinished = concat(new byte[][] {
-                md5(new byte[][] { master_secret, pad2,
-                                   md5(new byte[][] { handshakes, new byte[] { (byte)0x53, (byte)0x52, (byte)0x56, (byte)0x52 },
-                                                      master_secret, pad1 }) }),
-                sha(new byte[][] { master_secret, pad2_sha,
-                                   sha(new byte[][] { handshakes, new byte[] { (byte)0x53, (byte)0x52, (byte)0x56, (byte)0x52 },
-                                                      master_secret, pad1_sha } ) } ) } );
-
-            for(int i=0; i<expectedFinished.length; i++)
-                if (expectedFinished[i] != rec[i + 4])
-                    throw new SSLException("server Finished message mismatch!");
-
-            if (Log.on) Log.info(this, "server finished message checked out okay!");
-        }
-   
-    }
-    
-    class SSLOutputStream extends OutputStream {
-        
-        /** the underlying outputstream */
-        DataOutputStream raw;
-        
-        /** the sequence number for sending */
-        public long seq_num = 0;
-
-        /** the encryption engine for sending */
-        RC4Engine rc4 = null;
-        
-        public SSLOutputStream(OutputStream raw) { this.raw = new DataOutputStream(raw); }
-        public void flush() throws IOException { raw.flush(); }
-        public void write(int b) throws IOException { write(new byte[] { (byte)b }, 0, 1); }
-        public void write(byte[] b, int off, int len) throws IOException { write(b, off, len, (byte)23); }
-        public void close() throws IOException {
-            write(new byte[] { 0x1, 0x0 }, 0, 2, (byte)21);
-            raw.close();
-        }
-        
-        /** writes a single SSL Record */
-        public void write(byte[] payload, int off, int len, byte type) throws IOException {
-
-            // largest permissible frame is 2^14 octets
-            if (len > 1 << 14) {
-                write(payload, off, 1 << 14, type);
-                write(payload, off + 1 << 14, len - 1 << 14, type);
-                return;
-            }
-
-            raw.writeByte(type);
-            raw.writeShort(0x0300);
-
-            if (rc4 == null) {
-                raw.writeShort(len);
-                raw.write(payload, off, len);
-
-            } else {
-                byte[] MAC = computeMAC(type, payload, off, len, client_write_MAC_secret, seq_num);
-                byte[] encryptedPayload = new byte[MAC.length + len];
-                rc4.processBytes(payload, off, len, encryptedPayload, 0);
-                rc4.processBytes(MAC, 0, MAC.length, encryptedPayload, len);
-                raw.writeShort(encryptedPayload.length);
-                raw.write(encryptedPayload);
-
-            }
-
-            seq_num++;
-        }
-
-        /** tacks a handshake header onto payload before sending it */        
-        public void writeHandshake(int type, byte[] payload) throws IOException {
-            byte[] real_payload = new byte[payload.length + 4];
-            System.arraycopy(payload, 0, real_payload, 4, payload.length);
-            real_payload[0] = (byte)(type & 0xFF);
-            intToBytes(payload.length, real_payload, 1, 3);
-            handshakes = concat(new byte[][] { handshakes, real_payload });
-            write(real_payload, 0, real_payload.length, (byte)22);
-        }
-
-        public void sendClientHandshakes() throws IOException {
-            
-            if (Log.on) Log.info(this, "shaking hands");
-            if (cert_requested) {
-                if (Log.on) Log.info(this, "telling the server we have no certificates");
-                writeHandshake(11, new byte[] { 0x0, 0x0, 0x0 });
-            }
-            
-            // generate the premaster secret
-            byte[] pre_master_secret = new byte[48];
-            pre_master_secret[0] = 0x03;                            // first two bytes of premaster secret are our version number
-            pre_master_secret[1] = 0x00;
-            getRandomBytes(pre_master_secret, 2, pre_master_secret.length - 2);
-
-            // encrypt and send the pre_master_secret            
-            try {
-                byte[] encrypted_pre_master_secret;
-
-                SubjectPublicKeyInfo pki = server_cert.getSubjectPublicKeyInfo();
-                RSAPublicKeyStructure rsa_pks = new RSAPublicKeyStructure((DERSequence)pki.getPublicKey());
-                BigInteger modulus = rsa_pks.getModulus();
-                BigInteger exponent = rsa_pks.getPublicExponent();
-
-                if (serverKeyExchange != null) {
-
-                    AsymmetricBlockCipher rsa = new PKCS1(new RSAEngine());
-                    rsa.init(false, new RSAKeyParameters(false, modulus, exponent));
-
-                    int modulus_size = ((serverKeyExchange[4] & 0xff) << 8) | (serverKeyExchange[5] & 0xff);
-                    byte[] b_modulus = new byte[modulus_size];
-                    System.arraycopy(serverKeyExchange, 6, b_modulus, 0, modulus_size);
-                    modulus = new BigInteger(1, b_modulus);
-
-                    int exponent_size = ((serverKeyExchange[6 + modulus_size] & 0xff) << 8) | (serverKeyExchange[7 + modulus_size] & 0xff);
-                    byte[] b_exponent = new byte[exponent_size];
-                    System.arraycopy(serverKeyExchange, 8 + modulus_size, b_exponent, 0, exponent_size);
-                    exponent = new BigInteger(1, b_exponent);
-
-                    byte[] server_params = new byte[modulus_size + exponent_size + 4];
-                    System.arraycopy(serverKeyExchange, 4, server_params, 0, server_params.length);
-
-                    byte[] expectedSignature = concat(new byte[][] { md5(new byte[][] { client_random, server_random, server_params } ),
-                                                                     sha(new byte[][] { client_random, server_random, server_params } ) } );
-
-                    byte[] recievedSignature = rsa.processBlock(serverKeyExchange, 6 + server_params.length,
-                                                                serverKeyExchange.length - 6 - server_params.length);
-
-                    for(int i=0; i<expectedSignature.length; i++)
-                        if (expectedSignature[i] != recievedSignature[i])
-                            throw new SSLException("ServerKeyExchange message had invalid signature " + i);
-
-                    if (Log.on) Log.info(this, "ServerKeyExchange successfully processed");
-                }
-
-                AsymmetricBlockCipher rsa = new PKCS1(new RSAEngine());
-                rsa.init(true, new RSAKeyParameters(false, modulus, exponent));
-
-                encrypted_pre_master_secret = rsa.processBlock(pre_master_secret, 0, pre_master_secret.length);
-                writeHandshake(16, encrypted_pre_master_secret);
-
-            } catch (Exception e) {
-                SSLException t = new SSLException("exception encrypting premaster secret");
-                t.fillInStackTrace();
-                throw t;
-            }
-            
-            // ChangeCipherSpec
-            if (Log.on) Log.info(this, "Handshake complete; sending ChangeCipherSpec");
-            write(new byte[] { 0x01 }, 0, 1, (byte)20);
-            seq_num = 0;
-
-            // compute master_secret
-            master_secret = concat(new byte[][] {
-                md5(new byte[][] { pre_master_secret,
-                                   sha(new byte[][] { new byte[] { 0x41 }, pre_master_secret, client_random, server_random })}),
-                md5(new byte[][] { pre_master_secret,
-                                   sha(new byte[][] { new byte[] { 0x42, 0x42 }, pre_master_secret, client_random, server_random })}),
-                md5(new byte[][] { pre_master_secret,
-                                   sha(new byte[][] { new byte[] { 0x43, 0x43, 0x43 }, pre_master_secret, client_random, server_random })})
-                } );
-            
-            // construct the key material
-            byte[] key_material = new byte[] { };
-            for(int i=0; key_material.length < 72; i++) {
-                byte[] crap = new byte[i + 1];
-                for(int j=0; j<crap.length; j++) crap[j] = (byte)(((byte)0x41) + ((byte)i));
-                key_material = concat(new byte[][] { key_material,
-                                                   md5(new byte[][] { master_secret,
-                                                                      sha(new byte[][] { crap, master_secret, server_random, client_random }) }) });
-            }
-
-            client_write_key = new byte[export ? 5 : 16];
-            server_write_key = new byte[export ? 5 : 16];
-
-            System.arraycopy(key_material, 0,  client_write_MAC_secret, 0, 16);
-            System.arraycopy(key_material, 16, server_write_MAC_secret, 0, 16);
-            System.arraycopy(key_material, 32, client_write_key, 0, export ? 5 : 16);
-            System.arraycopy(key_material, export ? 37 : 48, server_write_key, 0, export ? 5 : 16);
-            
-            if (export) {
-                // see SSLv3 spec, 6.2.2 for explanation
-                byte[] client_untrimmed = md5(new byte[][] { concat(new byte[][] { client_write_key, client_random, server_random } ) });
-                byte[] server_untrimmed = md5(new byte[][] { concat(new byte[][] { server_write_key, server_random, client_random } ) });
-                client_write_key = new byte[16];
-                server_write_key = new byte[16];
-                System.arraycopy(client_untrimmed, 0, client_write_key, 0, 16);
-                System.arraycopy(server_untrimmed, 0, server_write_key, 0, 16);
-            }
-
-            rc4 = new RC4Engine();
-            rc4.init(true, new KeyParameter(client_write_key));
-            is.rc4 = new RC4Engine();
-            is.rc4.init(false, new KeyParameter(server_write_key));
-            
-            // send Finished
-            writeHandshake(20, concat(new byte[][] { 
-                md5(new byte[][] { master_secret, pad2, 
-                                   md5(new byte[][] { handshakes, new byte[] { (byte)0x43, (byte)0x4C, (byte)0x4E, (byte)0x54 },
-                                                      master_secret, pad1 }) }),
-                sha(new byte[][] { master_secret, pad2_sha,
-                                   sha(new byte[][] { handshakes, new byte[] { (byte)0x43, (byte)0x4C, (byte)0x4E, (byte)0x54 },
-                                                      master_secret, pad1_sha } ) })
-            }));
-            raw.flush();
-            if (Log.on) Log.info(this, "wrote Finished message");
-
-        }
-        
-        public void writeClientHello() throws IOException {
-            
-            if (Log.on) Log.info(this, "sending ClientHello");
-            int unixtime = (int)(System.currentTimeMillis() / (long)1000);
-            
-            byte[] out = new byte[] {
-                0x03, 0x00,                     // client version (SSLv3.0)
-                
-                // space for random bytes
-                0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
-                0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
-                0x0, 0x0, 0x0, 0x0,
-                
-                0x0,                            // empty vector for sessionid
-                0x0, 0x4, 0x0, 0x4, 0x0, 0x3,   // we support two ciphersuites: SSL_RSA_WITH_RC4_128_MD5 and SSL_RSA_EXPORT_WITH_RC4_40_MD5
-                0x1, 0x0                        // we only support one compression method: none
-            };
-            
-            // don't need to use secure random here since it's sent in the clear
-            Random rand = new Random(System.currentTimeMillis());
-            rand.nextBytes(client_random);
-            intToBytes(unixtime, client_random, 0, 4);
-            System.arraycopy(client_random, 0, out, 2, client_random.length);
-            
-            writeHandshake(1, out);
-            flush();
-        }
-    }
-
-    // Static Helpers ////////////////////////////////////////////////////////////////////
-
-    /** copy the least significant num bytes of val into byte array b, startint at offset */
-    public static void intToBytes(long val, byte[] b, int offset, int num) {
-        for(int i=0; i<num; i++)
-            b[offset + num - i - 1] = (byte)((val & (0xFFL << (i * 8))) >> (i * 8));
-    }
-
-    /** fills b with random bytes */
-    public static synchronized void getRandomBytes(byte[] b, int offset, int len) {
-        MD5Digest md5 = new MD5Digest();
-        byte[] b2 = new byte[16];
-        while(len > 0) {
-            md5.reset();
-            md5.update(randpool, 0, randpool.length);
-            intToBytes(randcnt++, b2, 0, 8);
-            md5.update(b2, 0, 8);
-            md5.doFinal(b2, 0);
-            int n = len < 16 ? len : 16;
-            System.arraycopy(b2, 0, b, offset, n);
-            len -= n;
-            offset += n;
-        }
-    }
-
-    public static byte[] computeMAC(byte type, byte[] payload, int off, int len, byte[] MAC_secret, long seq_num) {
-        byte[] MAC = new byte[16];
-        MD5Digest md5 = new MD5Digest();
-        md5.update(MAC_secret, 0, MAC_secret.length);
-        md5.update(pad1, 0, pad1.length);
-
-        byte[] b = new byte[11];
-        intToBytes(seq_num, b, 0, 8);
-        b[8] = type;
-        intToBytes(len, b, 9, 2);
-        md5.update(b, 0, b.length);
-
-        md5.update(payload, off, len);
-        md5.doFinal(MAC, 0);
-        md5.reset();
-        md5.update(MAC_secret, 0, MAC_secret.length);
-        md5.update(pad2, 0, pad2.length);
-        md5.update(MAC, 0, MAC.length);
-        md5.doFinal(MAC, 0);
-
-        return MAC;
-    }
-
-    public static byte[] concat(byte[][] inputs) {
-        int total = 0;
-        for(int i=0; i<inputs.length; i++) total += inputs[i].length;
-        byte[] ret = new byte[total];
-        int pos = 0;
-        for(int i=0; i<inputs.length; i++) {
-            System.arraycopy(inputs[i], 0, ret, pos, inputs[i].length);
-            pos += inputs[i].length;
-        }
-        return ret;
-    }
-    
-    SHA1Digest master_sha1 = new SHA1Digest();
-    public byte[] sha(byte[][] inputs) {
-        master_sha1.reset();
-        for(int i=0; i<inputs.length; i++) master_sha1.update(inputs[i], 0, inputs[i].length);
-        byte[] ret = new byte[master_sha1.getDigestSize()];
-        master_sha1.doFinal(ret, 0);
-        return ret;
-    }
-    
-    MD5Digest master_md5 = new MD5Digest();
-    public byte[] md5(byte[][] inputs) {
-        master_md5.reset();
-        for(int i=0; i<inputs.length; i++) master_md5.update(inputs[i], 0, inputs[i].length);
-        byte[] ret = new byte[master_md5.getDigestSize()];
-        master_md5.doFinal(ret, 0);
-        return ret;
-    }
-
-    // FEATURE: improve error reporting in here
-    /** returns true iff certificate "signee" is signed by public key "signer" */
-    public static boolean isSignedBy(X509CertificateStructure signee, SubjectPublicKeyInfo signer) throws SSLException {
-
-        Digest hash = null;
-
-        String signature_algorithm_oid = signee.getSignatureAlgorithm().getObjectId().getId();
-        if (signature_algorithm_oid.equals("1.2.840.113549.1.1.4")) hash = new MD5Digest();
-        else if (signature_algorithm_oid.equals("1.2.840.113549.1.1.2")) hash = new MD2Digest();
-        else if (signature_algorithm_oid.equals("1.2.840.113549.1.1.5")) hash = new SHA1Digest();
-        else throw new SSLException("unsupported signing algorithm: " + signature_algorithm_oid);
-
-        try {
-            // decrypt the signature using the signer's public key
-            byte[] ED = signee.getSignature().getBytes();
-            SubjectPublicKeyInfo pki = signer;
-            RSAPublicKeyStructure rsa_pks = new RSAPublicKeyStructure((DERSequence)pki.getPublicKey());
-            BigInteger modulus = rsa_pks.getModulus();
-            BigInteger exponent = rsa_pks.getPublicExponent();
-            AsymmetricBlockCipher rsa = new PKCS1(new RSAEngine());
-            rsa.init(false, new RSAKeyParameters(false, modulus, exponent));
-            
-            // Decode the embedded octet string
-            byte[] D = rsa.processBlock(ED, 0, ED.length);
-            BERInputStream beris = new BERInputStream(new ByteArrayInputStream(D));
-            DERObject derob = beris.readObject();
-            DERSequence dercs = (DERSequence)derob;
-            DEROctetString deros = (DEROctetString)dercs.getObjectAt(1);
-            byte[] MD = deros.getOctets();
-            
-            // generate our own hash
-            ByteArrayOutputStream baos = new ByteArrayOutputStream();
-            DEROutputStream dos = new DEROutputStream(baos);
-            dos.writeObject(signee.getTBSCertificate());
-            dos.flush();
-            byte[] b = baos.toByteArray();
-            hash.update(b, 0, b.length);
-            byte[] md_out = new byte[MD.length];
-            hash.doFinal(md_out, 0);
-            
-            // compare our hash to the signed hash
-            for(int j=0; j<MD.length; j++) if (md_out[j] != MD[j]) return false;
-            return true;
-
-        } catch (Exception e) {
-            return false;
-
-        }
-    }
-
-    // Embedded Trusted Public Keys //////////////////////////////////////////////
-
-    /** base64-encoded sequence of DER-encoded PKCS7 certs for all the "trusted root CA's" included with IE5.5 */
-    static String[] base64_encoded_trusted_CA_public_keys = new String[] {
-
-        "CN=ABA.ECOM Root CA",
-        "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsdMR4HlVQwcITMsFQgDiDYNGPe" +
-        "STurYG0w1ZvT7BzkNnAYohqO+8zNCizLBVllOEZgUA2kRJgNhUCqUlhpTtY1b/cGyjoRnS" +
-        "eL5oKkReL8/MGF5HvDqxRj0e8LksNF+MfEwIKZ1AVes8fYPetfD3ioMOoUy0OqWzX1oil+" +
-        "wZm8EFaP3mt6mRlCzkeEgkGiUZOuuVnDkKis9CsvAc1V/7a+1oVns5LHI4sO6TqdN7dzzr" +
-        "cQOpOEoWbIkqytozE3nCVYztnLvyy1sQ+C5hNcYpTCrQKmPRZVm0+M359ACEtldChZ0yqP" +
-        "kqVPv/eEG8vXEo9LuQvP+WNATjRZ6hRihAgQIDAQAB",
-
-        "O=ViaCode",
-        "MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQCws2enlrV2g+kWA9kaoHbVdOecBdJRP9" +
-        "tPGaGoOU7LJH1hxB5qIK4Pgd7quDn9Gx9rNkDtTSEl8qPZoVHYbMAblvjUQpTUp84bj9NU" +
-        "JqKE7zKFr0o/8TI2rz3mOifrA8IlfvRhK62KGkvmmzZo1C/l0oiU3Baq2sIVTGzD4RmRyQ" +
-        "IBAw==",
-
-        "CN=Xcert EZ by DST",
-        "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArVQY3rS/963odKrti3yPwtR1Gt" +
-        "WEubZi/Inv5JdhkvsduOFaRzSengYi+9PqOMu4iwf3GqAXdwdaMBzUKTgg1ydA2FCTQ7/S" +
-        "GKIpdgVyqmu2aZireR4cZfVqi/zFFqqictpg7U5uGSV6Ch0w41CbQjxE66GwIB7bAn7+PR" +
-        "+/0ACK20B2philFadXtlLCAReYd4+KgcYatGoq5q+p1gCsz9gVSXzbG6H+gfqH+dOQwQLA" +
-        "+dBC6ZFoJV/Gv4c56ZUAYCi/gyzA51621zYW52CHdujnJ7IlDYt65aod5VnNzgsOb8bInO" +
-        "MQ2YU507eb+sa6fHTSXXVWq3SkolG/UnzucQIDAQAB",
-
-        "CN=Certiposte Classe A Personne",
-        "MIIBITANBgkqhkiG9w0BAQEFAAOCAQ4AMIIBCQKCAQAox3xaJSN48rMAR0Biy2+MQlCfnl" +
-        "7UXA5lC1hWlSvjRtBhNuAtRpuCy5Hu0pV8mpKvBAp+pp/g17HDRfmYQRs5redW19m2f867" +
-        "OS4sO8+2cwODzhNdMmpjottb+Esz6FBsy6gX7J6TuWwGSyYLdx6e+eWMiTfS0bv9qYwrLJ" +
-        "wQMdhLjM23cX44LCnjF7JP6FK245I80v3hAtphEHTSGvPI0dFmB1/EhGNpva5s3GUjHLf7" +
-        "98YTLoN+P6nlCyBtAQo34lzait4icOkN4HQ9xOtxm2Eq4g0Ui0xGN0wm0mjWVsNXqqJgN6" +
-        "9fnaCzgILmQypMgAAJUNmoanNtA/5ec5LlAgMBAAE=",
-
-        "CN=Certiposte Serveur",
-        "MIIBITANBgkqhkiG9w0BAQEFAAOCAQ4AMIIBCQKCAQA+p3gzOJHiylaV0ZFGsiPcpVZ/D8" +
-        "eXuOKekS4oFi6O80e2XIPE8Ob+ZxqTZH1ACdgdaADs1BHu2GOJAyPphF/HVQ5K4nK7KcFV" +
-        "ZHao45LN9/ZuQlYYUjOJ+YAUqBlRfsd3v3qoMcB9F25DTtVmyQU+S+Ll4lUbdKpRHarMmB" +
-        "F3pOvbKg4nx9XNSOzcfk5J50HNmQvRS14YGw06CpstmznHQAzQdgd8fI9+XHKOh9W+8qa5" +
-        "3r/dnxJ5R3zFyZdARgCS0xNak0+dfthfTMFdSEnZLZg8/MynhyHwPo5yfVk4NhYaDEi+of" +
-        "LVPqgWDCBZz84PM4M9rav1/93X/WkIiADvAgMBAAE=",
-
-        "OU=Certisign - Autoridade Certificadora - AC2",
-        "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC5MMyl65DWVpRnM4mDbUa+cJeTF04KJ3" +
-        "DOycXyxdIt0RGcdzJsdNOSb/rp1bhhmqpMEz41OvDuCTbZ0Zcxx16sQUm/SG1OIFPJe2qj" +
-        "ljFrsm6ozy9yTAatMs9aCPN9EJyqu7pz+fPwuCRvqGW2Iv4FWxBVRMIDHa3RIswIbfuMyw" +
-        "IDAQAB",
-
-        "OU=Certisign - Autoridade Certificadora - AC4",
-        "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDsg9TMg5A/X+y+wenQx1hGWR/xk0qyFx" +
-        "MLzymZqwRFM+PRXr68jiV3Yt2bkpsxCkBFedXys91suUD9mH9Aoi3pspO9S9XB3unR+nH3" +
-        "P0G89BSvzWvIOUqdYGW0hNBqQeljrptp6rlGHNsYCDtiTN5B156GfxNyEdTc6t5gpbvdGw" +
-        "IDAQAB",
-
-        "OU=Certisign Autoridade Certificadora AC1S",
-        "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCwwJXro8VB+JtvcWOOkRFX+QPHaJoanG" +
-        "Hwww8Ml2KIfiYBNX398W9PF5WqfvK7vO/idnNhlTZRgz6E6D+6VzY3lBNskmQflA3rVC9R" +
-        "WuUoXvCShufkbSF6XzcL51u9LQKogfk/yxTIvKTF49HLN9yr5Yeq8guYLnrPzB7Cf+j9AQ" +
-        "IDAQAB",
-
-        "OU=Certisign Autoridade Certificadora AC3S",
-        "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDOZE7Wz658mCeY7yjvujTDNRqd0mYecf" +
-        "Hkli0nFzmQRY8t7+bVR6nhg4F8Pihx+oC7XfhDaxkQwZhvFZ4trklkROyEGmlZFleyPZLY" +
-        "Zku/ma1DGMc4yYuOLAQus0trk/adH4SyzeYAwr42pbxZtZ+LGSD/5agopFW2irayxddE4w" +
-        "IDAQAB",
-
-        "O=Certplus, CN=Class 1 Primary CA",
-        "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAw2spyC7HrnxSBemTiVYKWnnJzN" +
-        "wl74eKLQXYgRcEGzpF+HkODUnUgUHIq0X7dcgV8uLQvNlhbISkExmn2fnySdxMD8Z9V7QT" +
-        "3B4JcSk2nYBY9BvYiRTr09KTSyrxd+dqZb0Z5ar9DEpj4cKZtA8EtlobNjw3PL/F5V7xX1" +
-        "cOH8f9LOfkb2qbYpY5EZtm8Cy2UtzhJ//bbf7rq2MUHWOIY+IWDPkgVA+b3RVqdoNPvSeL" +
-        "U6Y30ofyR1BSO2bp0XgaG7I7afBZPDhb0SpMM14Oylal7S1bgoNN1jhOila2ai8kaxIwpi" +
-        "rerwy7qkQSHBPFZQ/j/dgaMUvkPwx8RegWMwIDAQAB",
-
-        "O=Certplus, CN=Class 2 Primary CA",
-        "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3FCW0BL4NdIIeHq2UnD9b+7PuR" +
-        "HLXXfh7Ol+BI3WzG9zQ1dgrDMKROwDXxyAJJHlqJFWEoL34Cv0265hLokQjWtsurMCvdU2" +
-        "xUg3I+LwWjdSMxcS4tFgTb4vQRHj9hclDIuRwBuZe5lWDa/u0rxHV+N5SXs0iSckhN6x7O" +
-        "lYTv5O31q+Qa2sCMUYDu/SU+5s0J0SARON3IBi95WpRIhKcU5gVZ7bIxl5VgcMP2MLXLDi" +
-        "vn4V/JQzWEE4dMThj4vfJqwftYs7t0NZa7Akpm2Qi8Ry6l0zmLfL3l5775TxGz7KySHBxZ" +
-        "gCqqL2W3eb9X6WVTQcZ2nA8ULjR6z8KBxmVQIDAQAB",
-
-        "O=Certplus, CN=Class 3 Primary CA",
-        "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAt5QwbtBM2X5eYOVvuybKUm9rbI" +
-        "WZpQvvABpvG01YtRgH+t17+MssUt38nLiNUum5sgt89Y9bmUgJWN7NSJWGJYkFNCcwC1e2" +
-        "DHdjKctsqj65mVESDZhwdkdM+UmWIgj5a+qqADajFaccHp+Mylp5eyHaiR9jfnmSUAkEKK" +
-        "3O420ESUqZsT9FCXhYIO+N/oDIBO0pLKBYjYQCJZc/oBPXe4sj45+4x7hCQDgbkkq9SpRV" +
-        "x1YVDYF3zJ+iN4krW4UNi3f4xIv7EMuUx+kaVhKXZhTEu9d9bQIbv3FiJhjpSYr6o97hhK" +
-        "2AykriIoxqCGGDsiLHCYg4Vl3RMavwCZ8TWQIDAQAB",
-
-        "CN=Autoridad Certificadora de la Asociacion Nacional del Notariado Mexicano",
-        "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA7tlrVYRxJvaOrUG71tLeY+ryP2" +
-        "XyOxPBrlEm9L94j8ZMSay/Qd71KMco55/XgOXU7iMrk5U9yY9q9coA6RDHiIIabqNf8DRS" +
-        "ISVoKPiV8ICVoiyxP2r2KNbihP0WZ5wluXXb5cZZA7SrQgeI1VxIRaIJA8muZ5KoolPHyq" +
-        "t+mhKVWgVXjRBklicRsOYyMFvNPQygGxMtuxqr3TnOkmuiBNQTX213Z1Q5qHtpisZfeMoH" +
-        "GGlu+cDT0IqOrx4waO742KhmDIR9I2qJPGJNFHSs25uc/LCD/gcw8factEjI5jpCJQko91" +
-        "bCsdejmHcCh+qKwV3axIonB4VeSExVKEDtCQIDAQAB",
-
-        "O=VeriSign, Inc., OU=Class 3 Public Primary Certification Authority",
-        "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDJXFme8huKARS0EN8EQNvjV69qRUCPhA" +
-        "wL0TPZ2RHP7gJYHyX3KqhEBarsAx94f56TuZoAqiN91qyFomNFx3InzPRMxnVx0jnvT0Lw" +
-        "dd8KkMaOIG+YD/isI19wKTakyYbnsZogy1Olhec9vn2a/iRFM9x2Fe0PonFkTGUugWhFpw" +
-        "IDAQAB",
-
-        "C=US, O=VeriSign, Inc., OU=Class 3 Public Primary Certification Authority",
-        "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDJXFme8huKARS0EN8EQNvjV69qRUCPhA" +
-        "wL0TPZ2RHP7gJYHyX3KqhEBarsAx94f56TuZoAqiN91qyFomNFx3InzPRMxnVx0jnvT0Lw" +
-        "dd8KkMaOIG+YD/isI19wKTakyYbnsZogy1Olhec9vn2a/iRFM9x2Fe0PonFkTGUugWhFpw" +
-        "IDAQAB",
-
-        "C=FR, O=Certplus, CN=Class 3P Primary CA",
-        "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqzf/62CbQXhp9UlYsN4fcWmmK+" +
-        "OuUMapvJPpIL7kxBOCVu/wQzIJypt1A498T+HgT3aeC61kehQ6mp2/LxYLZRyp7py84xpl" +
-        "y0+F6pJWdWbWVUDv+8zWOD+rHO9CjRmJ9reVhsKnHen3KfEq2WV5/Cv1jsoad36e6Kz5Zr" +
-        "9F++gTnV+2c+V9e477EnRdHwZehRumXhhEALq8027RUg4GrevutbTBu7zrOA9IIpHHb9K4" +
-        "cju6f8CNbLe8R3MhKoX/rNYoohnVl2o6uaxtRezmTcPbqF3FXYKYrEpaquYrCAwQdLxi9j" +
-        "pJBGbYURwmpth1n5y/rmBRPVy8ok97iWfNUwIDAQAB",
-
-        "C=FR, O=Certplus, CN=Class 3TS Primary CA",
-        "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvWWaI0MAPPklAUOYW0Y0N2c39F" +
-        "tXjqPezYwvQbMVPeWYi/LMXKfHrzXHs6dPxxApV+kDiYNyBnZSwXACN0Dt8M6LsbGJrAKo" +
-        "W93c1UNFBtwotulRG2ru83tIxZ0Rro2mcpPAJUKRqD5G4mhMgUCwQtN6vntH0kdQDKQSps" +
-        "rkEtDAfDo8AanKApbeglrF+xm6PJzYD3QfmBiulFAyB1IQEUpL7FhVLNSeS5R7BdJy3wbw" +
-        "jcsInuTutEStgvEbYWrxs/gWMTZCJLqQv7V+YW7CWQxUebRMiCgezBvfhIsjyL6vB/KRst" +
-        "qNyoxffCg8fIlsBlm9Ps7FgtNqyaxoVe7FrwIDAQAB",
-
-        "C=US, O=RSA Data Security, Inc., OU=Commercial Certification Authority",
-        "MIGbMA0GCSqGSIb3DQEBAQUAA4GJADCBhQJ+AKT7gWJ7zhAn3ej3vmxuxnCZ27jVBQNpKI" +
-        "Kccn+WP47srCmSP4oU+EJ2vr1dA7mQ1NC8BrJRM1/Ewr+2i4+ZtmIiYN3b3yCCtMqiLy1Q" +
-        "7ZQy3uBVjdRo4uBM0s0FFi6VZlxhUjgeUaiCocTvJekK5osrjjFm2fjZ/b07adnrAgMBAA" +
-        "E=",
-
-        "C=DE, O=Deutsche Telekom AG, OU=T-TeleSec Trust Center, CN=Deutsche Telekom Root CA 1",
-        "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDQ3ZsMoBdERA+vIUBzZ1bwPmloEbrZN/" +
-        "KBrsMkrGmhzfymGFVW/4ufMsHb53gsOdtggUGl79PNgI0YPOJSDAuf92Se5aDwuGFi9L/g" +
-        "o9pYK/0VBGu9Op58nfI92OSVw+xOwvFlqwxL7EeCW+LhUHXY9mG0GFztM6BLHoP7T4S8eQ" +
-        "IDAQAB",
-
-        "C=DE, O=Deutsche Telekom AG, OU=T-TeleSec Trust Center, CN=Deutsche Telekom Root CA 2",
-        "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqwujNeCLKRSxFIWvPBDkOW81XU" +
-        "qu3ephjZVJ9G9koxpgZqSpQCKE2dSl5XiTDmgBrblNXDrO07ioQkDfz6O6gllqkhusHJra" +
-        "CCslJ/lpI0fx4Ossepv1EwLQfjR8wp48AFmr9doM9TI8K6xQ2tbD3oOUyqgMmTIOCEhWW2" +
-        "r72uFYWAFJX3JBPBUGAY5draq4k7TNnuun6GotUjTbOu9cdVHa2/Mx+e5xmDLEVBVEDPmb" +
-        "Ve2t3xgIoKOGiknuUwWPGUzV3lh5m9JqHEKrxdWnz2gPluThYZh2YciRfNY+AOKRUIfhnQ" +
-        "rmrZfSHcY6fcu82gM01Y5bAfVqB7cWtm5KfwIDAQAB",
-
-        "C=US, O=Digital Signature Trust Co., OU=DST (ANX Network) CA",
-        "MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQC0SBGAWKDVpZkP9jcsRLZu0XzzKmueEb" +
-        "aIIwRccSWeahJ3EW6/aDllqPay9qIYsokVoGe3eowiSGv2hDQftsr3G3LL8ltI04ceInYT" +
-        "BLSsbJZ/5w4IyTJRMC3VgOghZ7rzXggkLAdZnZAa7kbJtaQelrRBkdR/0o04JrBvQ24JfQ" +
-        "IBAw==",
-
-        "OU=National Retail Federation, CN=DST (NRF) RootCA",
-        "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2aybd/pQ08zcuUCsuXJqAIcj/A" +
-        "+WIdAmr+TitV/606Z9ITAuzBeCj5h0/Gekpt+Il6JCKfWn2xGT+14jMMKqvCLnQRvl7SXe" +
-        "yD/b3ldFeEBGg7LVGj3fD0Vt1WMCddgvxm6rlZF0Nw3LTQlc0dRbOtrdDshrmdjVOczfhV" +
-        "XEklMCo+H3gMlwo9rcM8R/okcIHDWWH6EDHDCD9MTM/5jDsEZEosC/rdvSgfZMmCynXiTz" +
-        "hspj1bp98JrAStAbWO7sqWfPaQJsIsBgLCzRyCDqyC373Zy7y1FM3OdXBDtUmxGlMnTsdA" +
-        "HzkBVbL3wsk2W5Zme0gYg15Z6RGH+BqEHIywIDAQAB",
-
-        "OU=United Parcel Service, CN=DST (UPS) RootCA",
-        "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA7xfsrynm2SsnwNt7JJ9m9ASjwq" +
-        "0KyrDNhCuqN/OAoWDvQo/lXXdfV0JU3SvbYbJxXpN7b1/rJCvnpPLr8XOzC431Wdcy36yQ" +
-        "jk4xuiVNtgym8eWvDOHlb1IDFcHfvn5KpqYYRnA/76dNqNz1dNlhekA8oZQo6sKUiMs3FQ" +
-        "UZPJViuhwt+yiM0ciekjxbEVQ7eNlHO5stSuY+e2vf9PYFzyj2upg2AJ48N4UKnN63pIXF" +
-        "Y/23YhRtFx7MioCFQjIRsCHinXfJgBZBnuvlFIl/t8O8T8Gfh5uW7GP2+ZBWDpWjIwqMZN" +
-        "qbuxx3sExd5sjo9X15LVckP8zjPSyYzxKfFwIDAQAB",
-
-        "CN=Autoridad Certificadora del Colegio Nacional de Correduria Publica Mexicana",
-        "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmO0dhYH7/jd0viOAJ18bQX6856" +
-        "WK2HNdlkjqq1iqfaUdz/4gCtnydQnts9X9+JMqGaleqLEU8tZChkFBXk/FVqeaokJvLihI" +
-        "6i6r2cHZmvClnotdEWeaNzdTYGbxIv93d0fp3dwYRu4u3+LBluDqWN6H65OIaZmwPm52KU" +
-        "Bhwyhmc3+sMXb0OM3WMo9zMhAVNNJ8RND8eQwAnX0P4+P3RPWedEknrRvXMshTrm8qsNe1" +
-        "LRgsbjs6TUzb9Wi1L7AMkPk93HU2msLgv7uWiMJr7hjXTlA/V4tnaKS+AzNdWRI0if52yN" +
-        "kVdgFUZP2s41DvEMjQ7l/sHd9PBZg8tBReAQIDAQAB",
-
-        "CN=DST RootCA X1",
-        "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0sYmtuelPcHEaNVQb1PFb0kTCb" +
-        "ivLEiNFGqjF19a+dMudS/YKGLRky/8TdSrh+UIx5nnkj91vesltBXBmxk90kSN13QgbTcC" +
-        "j2mTW4rEGZ30sg78Fmy5sQWSg9GFLGCUPkVVoNmrCCHmYOg7dPKZUFFo0AMtsYC+o9hSsE" +
-        "TNQ0pwjliFleFOLNYtQW/WhOfImETKR9ssJKVpJs9ruCdiw/TJepIj7RNngq5FLkXlfnI/" +
-        "hZ2UYhDmPJGhrXcA4BXs84SAcnqObmCXxyRZEDSDW+GlpGm2VzUceFnG0y86c2fulMoEEw" +
-        "ViBnAjs/R87kXZZAtbSaqkQ84mxEQSbLjdeQIDAQAB",
-
-        "OU=DSTCA X2, CN=DST RootCA X2",
-        "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3HXwjMB1lprAYh8m98ThmurgVn" +
-        "Nbmc0BRKgIttWn2hoEGDmSSnijgcL1d3pQtHD/mqvGx8pug09CmPsmC9rcbdapmVVSZ+ko" +
-        "A5Lc5bAFmg8V+WtZclby+jn8qmjuDx8Qgy/8nfoXlt2C4+ZFfcBLgEQf7SzghP2RXJJUaS" +
-        "XlYmnc5e4AUr0zC611AoWnZFAtxRkZMMAm28nT/S6ZrVm1C03UQa6FSENZ3Leo4qLew4/X" +
-        "uKFipmhQUuTPMaeUhdqfRjIXVuXy62Y9Ev9D25jvd8/LgY00scZQSibR5D5BUK9sriI0Lt" +
-        "VrboO6ebh2ZUjaCSlkYyK5+0d2hYyGRMsJ2wIDAQAB",
-
-        "C=US, O=Digital Signature Trust Co., OU=DST-Entrust GTI CA",
-        "MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQC2HfdLjQ8T4xL1Cf4GMg6vTEH1fdRHPS" +
-        "oK34MF3t595gMW9lE6y0caSq1+xP0dtL50injdC4OOtIQTxPv4bSmuoeEPD0PjtV5gafqD" +
-        "lPx55tx27dFEK479Erv+F3cXDIntp+9RfcTtOMM7o3r74k2gYLXy/RNl08bsP741nD0i7w" +
-        "IBAw==",
-
-        "C=US, O=Digital Signature Trust Co., OU=DSTCA E1",
-        "MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQCgbIGpzzQeJN3+hijM3oMv+V7UQtLodG" +
-        "BmE5gGHKlREmlvMVW5SXIACH7TpWJENySZj9mDSI+ZbZUTu0M7LklOiDfBu1h//uG9+Lth" +
-        "zfNHwJmm8fOR6Hh8AMthyUQncWlVSn5JTe2io74CTADKAqjuAQIxZA9SLRN0dja1erQtcQ" +
-        "IBAw==",
-
-        "C=US, O=Digital Signature Trust Co., OU=DSTCA E2",
-        "MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQC/k48Xku8zExjrEH9OFr//Bo8qhbxe+S" +
-        "SmJIi2A7fBw18DW9Fvrn5C6mYjuGODVvsoLeE4i7TuqAHhzhy2iCoiRoX7n6dwqUcUP87e" +
-        "ZfCocfdPJmyMvMa1795JJ/9IKn3oTQPMx7JSxhcxEzu1TdvIxPbDDyQq2gyd55FbgM2UnQ" +
-        "IBAw==",
-
-        "CN=Entrust.net Certification Authority (2048)",
-        "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArU1LqRKGsuqjIAcVFmQqK0vRvw" +
-        "tKTY7tgHalZ7d4QMBzQshowNtTK91euHaYNZOLGp18EzoOH1u3Hs/lJBQesYGpjX24zGtL" +
-        "A/ECDNyrpUAkAH90lKGdCCmziAv1h3edVc3kw37XamSrhRSGlVuXMlBvPci6Zgzj/L24Sc" +
-        "F2iUkZ/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVTXTzWnLLPKQP5L6RQstRIzgUy" +
-        "VYr9smRMDuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/HoZdenoVve8AjhUiVBcAkCaTvA5JaJ" +
-        "G/+EfTnZVCwQ5N328mz8MYIWJmQ3DW1cAH4QIDAQAB",
-
-        "CN=Entrust.net Client Certification Authority",
-        "MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQDIOpleMRffrCdvkHvkGf9FozTC28GoT/" +
-        "Bo6oT9n3V5z8GKUZSvx1cDR2SerYIbWtp/N3hHuzeYEpbOxhN979IMMFGpOZ5V+Pux5zDe" +
-        "g7K6PvHViTs7hbqqdCz+PzFur5GVbgbUB01LLFZHGARS2g4Qk79jkJvh34zmAqTmT173iw" +
-        "IBAw==",
-
-        "CN=Entrust.net Secure Server Certification Authority",
-        "MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQDNKIM0VBuJ8w+vN5Ex/68xYMmo6LIQaO" +
-        "2f55M28Qpku0f1BBc/I0dNxScZgSYMVHINiC3ZH5oSn7yzcdOAGT9HZnuMNSjSuQrfJNqc" +
-        "1lB5gXpa0zf3wkrYKZImZNHkmGw6AIr1NJtl+O3jEP/9uElY3KDegjlrgbEWGWG5VLbmQw" +
-        "IBAw==",
-
-        "C=US, O=Equifax, OU=Equifax Secure Certificate Authority",
-        "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDBXbFYZwhi7qCaLR8IbZEUaJgKHv7aBG" +
-        "8ThGIhw9F8zp8F4LgB8E407OKKlQRkrPFrU18Fs8tngL9CAo7+3QEJ7OEAFE/8+/AM3UO6" +
-        "WyvhH4BwmRVXkxbxD5dqt8JoIxzMTVkwrFEeO68r1u5jRXvF2V9Q0uNQDzqI578U/eDHuQ" +
-        "IDAQAB",
-
-        "C=US, O=Equifax Secure Inc., CN=Equifax Secure eBusiness CA-1",
-        "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDOLxm8F7d33pOpX1oNF080GgyY9CLZWd" +
-        "TEaEbwtDXFhQMgxq9FpSFRRUHrFlg2Mm/iUGJk+f1RnKok2fSdgyqHCiHTEjg0bI0Ablqg" +
-        "2ULuGiGV+VJMVVrFDzhPRvpt+C411h186+LwsHWAyKkTrL6I7zpuq18qOGICsBJ7/o+mAw" +
-        "IDAQAB",
-
-        "CN=Baltimore EZ by DST",
-        "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvMyzPUN5uEf5FbduJrFMkph57c" +
-        "Vw8zrp1d0D9Co/YIyW5UcWAvc2svGeJoj1nkJlng+uf+PMsW4h9fGIInTWH7J3BDkyuke1" +
-        "NcATXQFyowVDzE7aJpqHqGFj9GanwxVG6tHR6jDDu3Fqm8FDhsE5H8ZWYAIb/Ig6oJm7jN" +
-        "d4YdBeV4+RO4CLbv/JZYEKObuQEyA1SD+l4b8twXGDhSDtIIfLtv4ZjATd7Sld3woSzolW" +
-        "8h9aGTFYtv1jNurJI96nkZcnZXKZbMd6RMRfvpsfHsqeWBymqiNq4wYbkiTYVyIJUBWQRv" +
-        "CDXraATBKBPWZvBFU6iGvQ71aHUKC51lUbnQIDAQAB",
-
-        "C=US, O=Equifax Secure, OU=Equifax Secure eBusiness CA-2",
-        "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDkOTmTHlIGGyg2+LKjKcXtjrIRvf7r57" +
-        "R0wo//BefZnQa/Esg/DvLW0SSyEd7RcwmK1LEsmAkNHlBGsoOmRY1iaLuFGyBwMqpAzaaW" +
-        "X8RxNz8E87dBJDkHGh4uYVigEgvlpd/Fq+o3ccwcyDc6uZdSp6zFaiSUTpx7z8Bq1t8hvQ" +
-        "IDAQAB",
-
-        "C=US, O=Equifax Secure Inc., CN=Equifax Secure Global eBusiness CA-1",
-        "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC65xeQAmWxNFU8ScJR1d+n0TeP0eeBc0" +
-        "FSYJudoRcmeK3HsegmlDK13jONOi/b8pp6WnOYo1zp+4pzG1znw7+AbM2p9NYrwPf5mapj" +
-        "orFHAg/U5FE6EjxsilpUhHDbwcWQz3JFy6hZwM0znT+jluuFMyEcPh4+YG52nGeFxcjDYQ" +
-        "IDAQAB",
-
-        "O=EUnet International, CN=EUnet International Root CA",
-        "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCeQTvZQUmLKJxZFPdQaCh7TQhcZ/+FHg" +
-        "umzzoyArB8fEqftokCIQxKmYvLZFF+eFq2XqlTt+/vx9+lIVmXTuIH5S18GdUqysgz05YQ" +
-        "Lt2gAJ/9yuhhqVPKth0YPpwR4GPnKmdbyESV8BNVSLu+VbhnN83LABMN/E9pFGpRlOy8Jw" +
-        "IDAQAB",
-
-        "CN=FESTE, Public Notary Certs, EmailAddress=feste@feste.org",
-        "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDhg/ObLsnn4cf0VAXNdkD+tLMTvucVXo" +
-        "Ym6EB3GlU/0QMmjPqHX6TF+f61MonGf0GR2BVATnBS8PHa+GI1mV4clFNhzD5iwINdWNH4" +
-        "SBFxbPewd+EYl7QHKDCRMcdPVPOEnsxZiUVtfrTJ245ClWbU3x4YTfylD9YahDnEyvK98w" +
-        "IDAQAB",
-
-        "CN=FESTE, Verified Certs",
-        "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDqY58fOBqEBISzS5MZhKJ7YsOnqyzsYE" +
-        "5VEeIEMicgNfkaeB8nZ6fggrAF6Capm4pEVr9LhFOjIqYOFlO5f68QyDMYVNnGTHzRW1ZS" +
-        "U4amWz8T8sMB0jGhM1y8XeTcYjzKI5dPcPuBjrDZnq+T6raxJI0ELVFDPDjsJ0Nxh+g8xw" +
-        "IDAQAB",
-
-        "CN=First Data Digital Certificates Inc. Certification Authority",
-        "MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQDfHBQeCbm/pEByIJl5toQi9NeFksUEJO" +
-        "gHLgLkF5UFN5V2Pfyx5Q+HDmK5LDCXJuELFWcAphXe6I3LlewCWFLAR2UzTFafCh8EwDdQ" +
-        "gVe63/rya2fry9CAD9lXlRBlewZFWOuutF7jkxUrmby2KS/7Qp9HKy5M6zQoMpkO7/9voQ" +
-        "IBAw==",
-
-        "C=ES, O=FNMT, OU=FNMT Clase 2 CA",
-        "MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQCYP60ZNpM9Pv52QhT9NW/x+q0ieljjRt" +
-        "Bdxlr5Yi2PMV7+tDD+UHSs1p0d4GLGSd0UEn1xC6wGwT/XBofgkInW5eMDsvInsZ8zyKpr" +
-        "NkqjxD95QZ2JRi8rPmPUOFaRqh2xDUJ1TfOHTuMPTcy0bL9iE4fq0JuOtuL/GfSUCdWWYQ" +
-        "IBAw==",
-
-        "CN=Belgacom E-Trust Primary CA",
-        "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCq2bmz1U9qTcVB0HsEYWqLcYEH2mTjWG" +
-        "4nVcKtzhew/PqSjQjwHHL/ssMx/uBqh5dMzENXpyh5OrWDXaQdavFqxT4UIh1ZBm/wpjF3" +
-        "3LBJOObLDA/+qnI0iNooOiFa7nQrG6TbWxMWtXNfw66M0sA+PbDL8OyLhgvCwUQYWmOo1Q" +
-        "IDAQAB",
-
-        "C=BE, O=GlobalSign nv-sa, OU=Root CA, CN=GlobalSign Root CA",
-        "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2g7mmY3Oo+NPin778YuDJWvqSB" +
-        "/xKrC5lREEvfBj0eJnZs8c3c8bSCvujYmOmq8pgGWr6cctEsurHExwB6E9CjDNFY1P+N3U" +
-        "jFAVHO9Q7sQu9/zpUvKRfeBt1TUwjl5Dc/JB6dVq47KJOlY5OG8GPIhpWypNxadUuGyJzJ" +
-        "v5PMrl/Yn1EjySeJbW3HRuk0Rh0Y3HRrJ1DoboGYrVbWzVeBaVounICjjr8iQTT3NUkxOF" +
-        "Ohu8HjS1iwWMuXeLsdsfIJGrCVNukM57N3S5cEeRIlFjFnmusa5BJgjIGSvRRqpI1mQq14" +
-        "M0/ywqwWwZQ0oHhefTfPYhaO/q8lKff5OQzwIDAQAB",
-
-        "CN=GTE CyberTrust Global Root",
-        "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCVD6C28FCc6HrHiM3dFw4usJTQGz0O9p" +
-        "TAipTHBsiQl8i4ZBp6fmw8U+E3KHNgf7KXUwefU/ltWJTSr41tiGeA5u2ylc9yMcqlHHK6" +
-        "XALnZELn+aks1joNrI1CqiQBOeacPwGFVw1Yh0X404Wqk2kmhXBIgD8SFcd5tB8FLztimQ" +
-        "IDAQAB",
-
-        "CN=GTE CyberTrust Root",
-        "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC6jr11kBL65Xl0stn3JtQOQR3pNgdWct" +
-        "W4adpU1LHWeG2q4zs9o4Q3JcevrwTcsyKx6W2+gm3rjS+9tK5wHqLWbiAxUeZWXHNSsiNQ" +
-        "Trz7mmdAxIYRRsdDIrrqAE9scs1hnN7L+u4w0ub6W53Fmdwg+Dm/ZIwHVju93Gxe9r/h2Q" +
-        "IDAQAB",
-
-        "C=US, O=GTE Corporation, CN=GTE CyberTrust Root",
-        "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC45k+625h8cXyvRLfTD0bZZOWTwUKOx7" +
-        "pJjTUteueLveUFMVnGsS8KDPufpz+iCWaEVh43KRuH6X4MypqfpX/1FZSj1aJGgthoTNE3" +
-        "FQZor734sLPwKfWVWgkWYXcKIiXUT0Wqx73llt/51KiOQswkwB6RJ0q1bQaAYznEol44Aw" +
-        "IDAQAB",
-
-        "OU=ValiCert Class 3 Policy Validation Authority",
-        "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDjmFGWHOjVsQaBalfDcnWTq8+epvzzFl" +
-        "LWLU2fNUSoLgRNB0mKOCn1dzfnt6td3zZxFJmP3MKS8edgkpfs2Ejcv8ECIMYkpChMMFp2" +
-        "bbFc893enhBxoYjHW5tBbcqwuI4V7q0zK89HBFx1cQqYJJgpp0lZpd34t0NiYfPT4tBVPw" +
-        "IDAQAB",
-
-        "OU=ValiCert Class 1 Policy Validation Authority",
-        "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDYWYJ6ibiWuqYvaG9YLqdUHAZu9OqNSL" +
-        "wxlBfw8068srg1knaw0KWlAdcAAxIiGQj4/xEjm84H9b9pGib+TunRf50sQB1ZaG6m+Fiw" +
-        "nRqP0z/x3BkGgagO4DrdyFNFCQbmD3DD+kCmDuJWBQ8YTfwggtFzVXSNdnKgHZ0dwN0/cQ" +
-        "IDAQAB",
-
-        "OU=ValiCert Class 2 Policy Validation Authority",
-        "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDOOnHK5avIWZJV16vYdA757tn2VUdZZU" +
-        "cOBVXc65g2PFxTXdMwzzjsvUGJ7SVCCSRrCl6zfN1SLUzm1NZ9WlmpZdRJEy0kTRxQb7XB" +
-        "hVQ7/nHk01xC+YDgkRoKWzk2Z/M/VXwbP7RfZHM047QSv4dk+NoS/zcnwbNDu+97bi5p9w" +
-        "IDAQAB",
-
-        "C=hk, O=C&W HKT SecureNet CA Class A",
-        "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtBuiCqVMc2NGUUh0Y6i0jBbb9M" +
-        "hn3qFIAv/Lo8+n39mxMeDjLihxBKZkWsZc/tCnuOo+Ctr7EX9/JCheyIqsbniqyKIYOZ5M" +
-        "UNHwmLXvpLIbYGu/+XO0C3X5Irvp5YGgldJ2THzTp/5dlRXtB9TH3mAwAO7yLpTxhjLlWV" +
-        "Ho34CiKgDvPIhdEeMAX1TkDEcQbLD1+DN2HDRmW9S7NGM502aUOuzNIinz9hK71CEpN6VE" +
-        "Td+JDAQMfUF7h/MWwUMpZLTWRWerhkxljwG36mOMTnhUREcaU4aMaxgnIQvFVmYOJfbgea" +
-        "xoAHTpmmQ8SU6e4B3IiBtQBvddCfiNixP9XQIDAQAB",
-
-        "CN=IPS SERVIDORES",
-        "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCsT1J0nznqjtwlxLyYXZhkJAk8IbPMGb" +
-        "WOlI6H0fg3PqHILVikgDVboXVsHUUMH2Fjal5vmwpMwci4YSM1gf/+rHhwLWjhOgeYlQJU" +
-        "3c0jt4BT18g3RXIGJBK6E2Ehim51KODFDzT9NthFf+G4Nu+z4cYgjui0OLzhPvYR3oydAQ" +
-        "IDAQAB",
-
-        "CN=Microsoft Root Authority",
-        "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqQK9wXDmO/JOGyifl3heMOqiqY" +
-        "0lX/j+lUyjt/6doiA+fFGim6KPYDJr0UJkee6sdslU2vLrnIYcj5+EZrPFa3piI9YdPN4P" +
-        "AZLolsS/LWaammgmmdA6LL8MtVgmwUbnCj44liypKDmo7EmDQuOED7uabFVhrIJ8oWAtd0" +
-        "zpmbRkO5pQHDEIJBSfqeeRKxjmPZhjFGBYBWWfHTdSh/en75QCxhvTv1VFs4mAvzrsVJRO" +
-        "rv2nem10Tq8YzJYJKCEAV5BgaTe7SxIHPFb/W/ukZgoIptKBVlfvtjteFoF3BNr2vq6Alf" +
-        "6wzX/WpxpyXDzKvPAIoyIwswaFybMgdxOF3wIDAQAB",
-
-        "CN=Microsoft Root Certificate Authority",
-        "MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA8136gGfUWqepDCyQINA1CDx1hM" +
-        "23B4mcidrezsNg+pFoWp6UcSkYdnzC4MgldpQOWPoENDbm36/3gLrpWAsrk+WdBeN3IpH3" +
-        "NGQ8IpEdXuEJkLwU/vx1WBnhebcHkqOuiFkI2J8HygNY/GgpbTLX0qjLS/zhC0gyT+bruK" +
-        "1P5FxvE5SZ25XVdduoGreUkbR3W/VIDI9qeX0UcAR9ba+Q9dpw2Ee3v5svbOcFt+ERYKx5" +
-        "kRR8xdam5OF+1cN+5ZLSPAC1NoLeeeFt87Vu+J8zyctSfXOYNtuLoWuilZebo97CTSb/Bp" +
-        "ZnJQbI56zk7hIzlTGZyDUITjTKeVPVtb5jMllANsClTgRNPdtbBzPkWL/vP1Nk2EJZNVf9" +
-        "D0V8JARNntY4dBGXIpDOaER0km/VS2+whuPHNkKg0PzBwFr5o2G5MEdxlgoWsJHAQpXvEH" +
-        "8oauMqH7HkzQM/d3EExyD8SQ8dRYik18t+iK2OLexF28RRBMkq/OyGnpoRl1vezlOI5uK3" +
-        "/ayVwihA2+8EkN+BMznZskWlI4cGpVWJMbsGLWAOQRh9Hy61l8sR6xXVJKWU7xUUif1Lc/" +
-        "oyW/zRMwD5WWJwBzLqLqtALXvK3SFnGzCZjxaqI6hB0bBuEZs2xN5AdJzhWGXBYB56WzjI" +
-        "j7sEJnzUFkDltmtsqob9AL/OwTUCAwEAAQ==",
-
-        "CN=NetLock Expressz (Class C) Tanusitvanykiado",
-        "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDr7LBsYYojJa9gIOPZn/yTC9tdjbChs0" +
-        "A6gs79deB4MgOGWoaVke1T+p1A/Obo3dlbegO9XfM7DMNReZutVaDp0AMQrwq6FELZUiYR" +
-        "IsfSIMyCpJqp/riBdp1qt9I2dT6xhgn2bm1+Trd67K5xhPYEMwglMut0rBZExuRAkx1/rQ" +
-        "IDAQAB",
-
-        "CN=NetLock Kozjegyzoi (Class A) Tanusitvanykiado",
-        "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvHSMD7tM9DceqQWC2ObhbHDqeL" +
-        "Vu0ThEDaiDzl3S1tWBxdRL51uUcCbbO51qTGL3cfNk1mE7PetzozfZz+qMkjvN9wfcZnSX" +
-        "9EUi3fRc4L9t875lM+QVOr/bmJBVOMTtplVjC7B4BPTjbsE/jvxReB+SnoPC/tmwqcm8Wg" +
-        "D/qaiYdPv2LD4VOQ22BFWoDpggQrOxJa1+mm9dU7GrDPzr4PN6s6iz/0b2Y6LYOph7tqyF" +
-        "/7AlT3Rj5xMHpQqPBffAZG9+pyeAlt7ULoZgx2srXnN7F+eRP2QM2EsiNCubMvJIH5+hCo" +
-        "R64sKtlz2O1cH5VqNQ6ca0+pii7pXmKgOM3wIDAQAB",
-
-        "OU=Tanusitvanykiadok, CN=NetLock Uzleti (Class B) Tanusitvanykiado",
-        "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCx6gTsIKAjwo84YM/HRrPVG/77uZmeBN" +
-        "wcf4xKgZjupNTKihe5In+DCnVMm8Bp2GQ5o+2So/1bXHQawEfKOml2mrriRBf8TKPV/riX" +
-        "iK+IA4kfpPIEPsgHC+b5sy96YhQJRhTKZPWLgLViqNhr1nGTLbO/CVRY7QbrqHvcQ7GhaQ" +
-        "IDAQAB",
-
-        "CN=Post.Trust Root CA",
-        "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1n8T5A0k2Nj76bbDsVKjTty3O+" +
-        "L3Dl+B5gHwpuY2cNgTc6H/UgiQ8hW88jIcqNfhBhB7QaiUxz89RBXcgFHnMP5TSPWQX21t" +
-        "JeBgu6D71sYp+E1wUBo3oA7NeCq2aPOZ1AyOXhJi/8JfWporiEequ6HZdfAsXP5twrFbMc" +
-        "yDhxqnvpAO6BBUU1ILnEnzgAL+byemo1cwuNu40AAEA+Tl1EMG66toTWgm0pk0ueASln9L" +
-        "u2tuIXHmCEVKHWYNN8kD4dHK3LEvcPa3gWKWG2Sn/rvhhutBn6ic2Mqg4dYv+A/hukA492" +
-        "3RpcpMGciW3MxJHAq206iROvna7B3Nc0okPwIDAQAB",
-
-        "CN=PTT Post Root CA, 0.9.2342.19200300.100.1.3=ca@ptt-post.nl",
-        "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsH7iOgHxSK1T1HHO276A4FCtma" +
-        "KEeto6JyQ6EYE2Eg3mo5mOpMwmtQ5hxu4oq22G3y6XYfpAacmNjMQxe/pSXlZMIJ5gGl9s" +
-        "SnjJiTyflYasd2cOpg5C6CxiSTJLBD4yQ5AOCiLKyHQOhe+DgcVb8ttshQhvTialBqt245" +
-        "iiTl7EgODo+8zpMGzycmGuJ35T1BWUD9KPeYLZ9o+rxhPmHJh0SwBhDnlpVPKQsqMJAWX3" +
-        "BEdsTvopK/AOBheT3ILAEd6PsDBGWUhKZs42r8fPMdGSdBQj1aq64InbEtHs1GkjuAsWST" +
-        "POGvninF98aB13uwGqZ+Ixxv/WOmn9DBt8IwIDAQAB",
-
-        "CN=Saunalahden Serveri CA, EmailAddress=gold-certs@saunalahti.fi",
-        "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5wQp3NbgUtPWTwCvHIGIvzxUcv" +
-        "OeeWP9y2DaDHxyL8obqeIQaWd6OZ/CoCXMg4ONgxEcuP3n26mIowySIVfBquLqM35KZgO8" +
-        "c43SHCn9x39D7Y/rV3uhQb9NczFKNyi0GFdYPGhwUJO6EB14zZPDwoLvuN8PDFjVMFdDOh" +
-        "QlKjhZBrREzdvJXkbyS7gcQ0GB0j5Dsq4hnhtKgHymyrP0JqkuLPi39zwYD5sybxEJc8TN" +
-        "L+jT7Ek284GN2ML/0Bpt3dgUvzLQ6cMNPgiv7dpLnWrPE4uQgmn612cjYUtb/aWAZB1696" +
-        "XT2ncceLtR++dGgJBxcbYW+EO0Gb0Yq952ewIDAQAB",
-
-        "CN=Saunalahden Serveri CA, EmailAddress=silver-certs@saunalahti.fi",
-        "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0neMvIdsNk5TqmhgRbgjd2fj7k" +
-        "mC5mx/XpJdtRxhUteoYEsW+ut5fp1MkulXe16GMKkoPH030SHidhoZw++q2u74AZ4aOSov" +
-        "k3UDZj9uKU2NhGOMpx8VlLQ0SbTk00GruvvEXLWecvUoyjKCY0zHRPi0HcSKCldVkK8wiV" +
-        "QOp2gm00AHIrPOPKP7mNckPN58gkm0NIx9JNtkbmSy6f+GyKx+q1Pk0kH0EYTuR0wIHUTm" +
-        "Vk0AfNqJQjnveAjRhea+XJ4zuTX/HM70g7XyZMUxSKm0rMXYPIwabab/Qq3z+EvOrNrFir" +
-        "APAyPB9fPHWX8w8d9mHVoxBaJGHTnkVbOtDwIDAQAB",
-
-        "C=hk, O=C&W HKT SecureNet CA Class B",
-        "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAn+AlkQ8EV8LHXLFlAmYPqP3YMQ" +
-        "5vgmz5wx6w46C9OERSx4x2EnhMfsIrjIrk+dwK4JVF3+seftJE+AMVAOzEsTx6tk22lgp3" +
-        "vAdg7/C3N/6J/bLYB6tS/oI/vDVnM9n7LNy1WGGiDLF9lNGohGkkPZfNmwhMUImBmh/Swi" +
-        "BvzD8OZcThSEncO/nlKjEHbqZrR6gZWq7ToXS1vMLbOT36q7DwySIJ1DxGaGwuLh/4qIwR" +
-        "oXY1UpLXq4gh3L3pnNn4Pt4wMUwCIi9XZrtWcjk3UJmvV9D0S9Qp7alvxtOyhpGLHRBtaB" +
-        "Zk8Q5tv15n/bKOcGXnb3K8RHWrAXb/N2RFIQIDAQAB",
-
-        "C=US, O=RSA Data Security, Inc., OU=Secure Server Certification Authority",
-        "MIGbMA0GCSqGSIb3DQEBAQUAA4GJADCBhQJ+AJLOesGugz5aqomDV6wlAXYMra6OLDfO6z" +
-        "V4ZFQD5YRAUcm/jwjiioII0haGN1XpsSECrXZogZoFokvJSyVmIlZsiAeP94FZbYQHZXAT" +
-        "cXY+m3dM41CJVphIuR2nKRoTLkoRWZweFdVJVCxzOmmCsZc5nG1wZ0jl3S3WyB57AgMBAA" +
-        "E=",
-
-        "C=au, O=SecureNet CA Class A",
-        "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqaN8+JCzjoRM4Aq+qxIqjQw+L7" +
-        "XdmxCIuWq3h3Ugt0vvIiMG6/BWMvfLLXDFA2+3wdDDZhMCvVVJh4fpLZ6l5XY2q+JkJViI" +
-        "wxsbAvBdsY+fE03CUim0EDVPNoivCy2BCCRhw2iNWm0x6FQZUxf9pxP2QJmmqCnAn0J7Jy" +
-        "nB7tvvjQNkJYGx/pUaHtoQQWIbVn8YGEiY0k1LwRhot2lna2RMbo8CvxRpe/ZEIxDpLrxe" +
-        "Ys1bnMyjjoxRgbSiorG8qMnoKpiqu0sVoeHpkHqef+hlBegRcXpv43XeVT/L2OrIAM0llH" +
-        "JkHu99ED5NL5F5vQLq15DBSWhuWRQl4t3dCQIDAQAB",
-
-        "C=au, O=SecureNet CA Class B",
-        "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApmPZxhVadudGZcc0kfl73Va7+J" +
-        "Y1LinKp30KHvcxUuhayNPPOQFOW/AfsbhK0rNHQ2Y/AUBOMEnhD/3rEmN4zPYWYhj1b2n9" +
-        "fm4zdiGjwIgP6uYl/KmXzBhyxzG2C5vNwsV4YWNFrDSmJ3hoxL1SaM6ETdIkpShsgObK5s" +
-        "/mmp5QeM7zNtKjQ1ocBq/LIO7QLMREGJBssZFkZbm3hYNLqJGZxeCc97hQ19OwT5rtY/tN" +
-        "9NQoJDqAW3uTjMUFhK87hv6BMce2nV8a6pB7sEZesghSAFcNVVKDeJVK/WiPntlQtktT+v" +
-        "KFApVOOPWDp5bUMT8/p8o3U9zFL20adKbMvwIDAQAB",
-
-        "C=au, O=SecureNet CA Root",
-        "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApyi02Dz1v3oGkb2lQkyzfJ6IZp" +
-        "nF2xfURVTDe8DwJFZmmL9E4HkTdmiu3Zp0z6Lpl+bBwKnD9yzVNjtzna+C2twOX1Ov625Q" +
-        "16jwqo6rY9Kbdf5VCnzRs8BZk1Eqh2mKGe3k19eOFKu1GVizzmzgTYLTA4TBqwAYekmoFX" +
-        "0IyQFgJ5To+wlgntE/Ts0To3j9ZfcRX/abADCMIu0oiWUb0x9he8Mjo+PGgPmD8/e63oZ4" +
-        "X/aVw4xqSCJlhdMiefb9RBboD2EENip1xtviZRQnYtyCXJYSMw5MGNX2PJ2xzWEcsYX5A9" +
-        "G69kzW7p990ZIh8PYKFqQ0h/dWj5O+l69SpwIDAQAB",
-
-        "C=au, O=SecureNet CA SGC Root",
-        "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAp1uxDYpTIbpSiDiQQmVE/Vbrc8" +
-        "WF8wYx5Qj8jLHVescLIwq8WgkiAfinwN5XdDGLrTbMXnP39kTwMcr1LKIF8wocMHqGM+JG" +
-        "U/Zk1kersVOUY3fEYtMvC+pfsHUCXvgrzybz3tKt62V/vC5BhPyZmumBG6ecZsf49bKEGy" +
-        "B1ciHHhP8CRswPpmmFfVkh1Q6nXVYVT8wfQSx/Zhuv691Bo+yp5lZK/h6nxFwiny/gC3QB" +
-        "cMhzgwoHpGie5FEOjXQxL6LG2ggQK+8lPmyGtUbnl4PAq96wrgYa58j7736tjrCaRfGb9b" +
-        "HoMbtkAL9/kWbNqK+V6hM6Akxb68CT5EH8rQIDAQAB",
-
-        "C=JP, O=Japan Certification Services, Inc., CN=SecureSign RootCA1",
-        "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlJAMS3EpHNr2aHl6pLrn0syNr+" +
-        "hHkJkfxirql2PoH84XV8Yas6jHfIftNTWAurpubb4X/swtG2zvigBJFuHuBl5KB12rPdFQ" +
-        "uJFG1NTaFdiUXA7K19q/oPdJPMi7zuomgQoULZwNN0VrQcpXizjwJh8x/M80jo93wT/jq1" +
-        "Q8J7TOMkxVE2L8/joWJc8ba6Ijt+DqAmm79yJxbXwLGZOhl5zjkWkfaOQvfRBtj2euwRCi" +
-        "sF5jSpf35niprSa7VMnftO7FntMl3RNoU/mP6Ozl3oHWeD7uUEC0ATysFcGCOy5/8VIni3" +
-        "Lg59v5iynDw0orM4mrXCoH/HwjHitPCCL+wQIDAQAB",
-
-        "C=JP, O=Japan Certification Services, Inc., CN=SecureSign RootCA1",
-        "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlJAMS3EpHNr2aHl6pLrn0syNr+" +
-        "hHkJkfxirql2PoH84XV8Yas6jHfIftNTWAurpubb4X/swtG2zvigBJFuHuBl5KB12rPdFQ" +
-        "uJFG1NTaFdiUXA7K19q/oPdJPMi7zuomgQoULZwNN0VrQcpXizjwJh8x/M80jo93wT/jq1" +
-        "Q8J7TOMkxVE2L8/joWJc8ba6Ijt+DqAmm79yJxbXwLGZOhl5zjkWkfaOQvfRBtj2euwRCi" +
-        "sF5jSpf35niprSa7VMnftO7FntMl3RNoU/mP6Ozl3oHWeD7uUEC0ATysFcGCOy5/8VIni3" +
-        "Lg59v5iynDw0orM4mrXCoH/HwjHitPCCL+wQIDAQAB",
-
-        "C=JP, O=Japan Certification Services, Inc., CN=SecureSign RootCA2",
-        "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlnuSIz9g3wk8WIAI42MJl+jkC3" +
-        "Vh1M0Oo/LjHkO6g/+6gVwvyN6Qi0wOLyn5B9aOs6Yor4Iqe8K0Zkxx9Ax0GrjbGuhoN6n5" +
-        "oaJuHCjNbCY8jyoznp3LtHnE2WQ9lcYzqEf75QcJ3PZtuCVCTMP7Su1bLtQHqOWTECSTWG" +
-        "59wdAez+kp19C8X0zwFRbD2MLO41sXW5SLKGsUZyQ79FLsDW58TrSZAtvJ8w+CqwH0jN4W" +
-        "cMa8Fwdh/xFAhOosG3o6sANhB6qWjdDauYOO5J1RaXVxZIG0iFXcEIPOLaX1MJZhLjsK/I" +
-        "dfnFyCdRMe05jR7cntchYcDAbcWSB+8F3v9wIDAQAB",
-
-        "C=JP, O=Japan Certification Services, Inc., CN=SecureSign RootCA2",
-        "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlnuSIz9g3wk8WIAI42MJl+jkC3" +
-        "Vh1M0Oo/LjHkO6g/+6gVwvyN6Qi0wOLyn5B9aOs6Yor4Iqe8K0Zkxx9Ax0GrjbGuhoN6n5" +
-        "oaJuHCjNbCY8jyoznp3LtHnE2WQ9lcYzqEf75QcJ3PZtuCVCTMP7Su1bLtQHqOWTECSTWG" +
-        "59wdAez+kp19C8X0zwFRbD2MLO41sXW5SLKGsUZyQ79FLsDW58TrSZAtvJ8w+CqwH0jN4W" +
-        "cMa8Fwdh/xFAhOosG3o6sANhB6qWjdDauYOO5J1RaXVxZIG0iFXcEIPOLaX1MJZhLjsK/I" +
-        "dfnFyCdRMe05jR7cntchYcDAbcWSB+8F3v9wIDAQAB",
-
-        "C=JP, O=Japan Certification Services, Inc., CN=SecureSign RootCA3",
-        "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmV4egJZmI2TOnIwAPgqvCOm4BO" +
-        "CEuG1TdU02qLXg14xOYFW2A5ebWhqn87o92ZqUMXZ0I8n37BJd2CDUHekbojd2BA8+rBZp" +
-        "O+H/EC9WJeQzUBMJzE4Oq/Dkddtx1fxKze3bDzUFFdWwZntCeyblWeK1x8Cyx6FD/Q8vC4" +
-        "MlJVeBu7vRNTB0kZCyj59o1dJDt7JFqSPAVtiHEtNz/stZ6q/85x9eVEUcqm2Vk2JHQkFe" +
-        "T+s2Bw4oeFQKfMDDJBOGAwK5rHaSSlrdxdzs+LPbK7UbNud4gkyVfiBWsnUcfZfvf5Q4Ka" +
-        "IA4tHqseM0NjFAWLiqt86BGgwXgQ3967jTvQIDAQAB",
-
-        "C=hk, O=C&W HKT SecureNet CA Root",
-        "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtBiikFaM1l2/RliRJ+qddeCk66" +
-        "JQcIdFSUmSa7c5AEt7qNpA4eYNouA3AUhNznLhXJPTw/mSDSTvSM5HKsutkjqq1pWy8hme" +
-        "PpV8j2ACdJMWKGn+O+5deJMcejwj6WE5bMUwLR+EkgVx53TBQkfpMLGjFww2Y89Q0DKoh6" +
-        "VAYhQROPvOL40zsIvpjnD7sJ7HXQPu9uWNcjzIvFSSz8qQ38jbrwXx61DK0QWsBbQBFZb1" +
-        "6zihafeDQ+g8pl2lLLokFi/7DjJwphLWmTb3axuj5/zHG8jYL3XRNbPpwtaPBB3BtX4EOz" +
-        "iJ5KMj8P3KvczrnRcGFXLt0Ob71m+z8Z0+uwIDAQAB",
-
-        "C=JP, O=Japan Certification Services, Inc., CN=SecureSign RootCA3",
-        "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmV4egJZmI2TOnIwAPgqvCOm4BO" +
-        "CEuG1TdU02qLXg14xOYFW2A5ebWhqn87o92ZqUMXZ0I8n37BJd2CDUHekbojd2BA8+rBZp" +
-        "O+H/EC9WJeQzUBMJzE4Oq/Dkddtx1fxKze3bDzUFFdWwZntCeyblWeK1x8Cyx6FD/Q8vC4" +
-        "MlJVeBu7vRNTB0kZCyj59o1dJDt7JFqSPAVtiHEtNz/stZ6q/85x9eVEUcqm2Vk2JHQkFe" +
-        "T+s2Bw4oeFQKfMDDJBOGAwK5rHaSSlrdxdzs+LPbK7UbNud4gkyVfiBWsnUcfZfvf5Q4Ka" +
-        "IA4tHqseM0NjFAWLiqt86BGgwXgQ3967jTvQIDAQAB",
-        
-        "CN=SERVICIOS DE CERTIFICACION - A.N.C.",
-        "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsiov7CtZakOTiUYqiuXs+gX64s" +
-        "jeQWuvA9sAWu9IN89XifvdyZIQ3ncDlRyQPse2ZyU7VZjv2Tz+JuSKO0SpdDeDCncndLip" +
-        "ca3dlxPSyqIuuLqdyb5Z6Nly8oqFZhxHXrSHgtYP32cmpr02sfNdkFBRdjIsOy+qX2Fe41" +
-        "TVEl3/DY0Rx4J6Nt/hTBbEdN0tau/QsfAzp/6/N2dDEi55SpSvhPsHEQhOMJN16QFUzsXe" +
-        "FIbwrq6bciUPRHfi82yveZwuSceemHYyFpq8AN7gtCAFkRfdgBUU7jZBxCGP7tkAShnGcW" +
-        "GlEV0AO+SndGw6Sm6D4HoxXCFl+AiHQodn5QIDAQAB",
-
-        "CN=SIA Secure Client CA",
-        "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDS/LBAYGpmY1Jm5mkJcY2BmB4dHfPgSQ" +
-        "3IK2/Qd1FFxZ1uo1xw3hV4Fh5f4MJi9H0yQ3cI19/S9X83glLGfpOd8U1naMIvwiWIHXHm" +
-        "2ArQeORRQjlVBvOAYv6WpW3FRsdB5QASm2bB4o2VPtXHDFj3yGCknHhxlYzeegm/HNX8ow" +
-        "IDAQAB",
-
-        "C=IT, O=SIA S.p.A., L=Milano, CN=SIA Secure Server CA",
-        "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA28ELzCfTEiIuuWQWdKxZJ+IqkA" +
-        "CSntWYXCtRbhsTb1RvShCihethC+ztnH7Of2WTbsxsQZzILarGs5v7THCcEXXzcom6iQCt" +
-        "xy5J53PagLIs/vKXmfQCGzQvOaqL5u8F/Ln1ulR/ob+OHkg2Mwl0Yac9x5skx8OJzcpOKD" +
-        "EjBhxiFY7fTxtrLUri9LDczvOQ/XmBE8E+Lma8+SJNCy9iM42oK+rpb3OnN5QEL+leTQ3p" +
-        "7XwyP3lK5jp2KSBQ84+CRHJsMDRIWKpdGz8B6yHs6n6oK4Rd9sExlU8pe7U1t/60BlewFN" +
-        "fyVVmMupu5MT/lqqrvJXCVkjZB8VWfwQhEnQIDAQAB",
-
-        "OU=Public CA Services",
-        "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwOeC2xUTrnnCtF+SjyO8uvfG0Q" +
-        "Cv1lRp8V2mYvhh0Zzeyjss6VwWJzTmuNHKdO8leGRt/hzoiXMxU2dnhsStamjnClZEgzpY" +
-        "R4l3Gtpv8vkHQMk9Ae9q0dlrhJ7FaytOtyz4pGpXq2gxuhlmuuwbV/vOStZLeMPBgT1Llj" +
-        "CZqcMt4uQSJgqkYxIc1HfIgdSnVUMt/ARWndwLrrdsCtozkIgFyX5UgujSMtDXAUkqNZB5" +
-        "OXPWi7xhzYdtUBUFTKnoSkcxiwXM5flC1xJg+Do/o6k2GqWGNiymBIMJ9lLFsH0fiEGQmM" +
-        "VlaJYQshPJFkm9Kr6wSKfC/S1eVtA3TVhR+wIDAQAB",
-
-        "OU=TC TrustCenter Class 1 CA",
-        "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCwKeu0drOu17ZbtF7nveOxnEkEV1uhq9" +
-        "l/Exv9umGr2Odx3y0AlF1RSH0j73VihJA8Ch9ZEXQvjoCl/TACPSlSzXIaSSGcvMtSjkih" +
-        "Y5bIEIUwaVd0RcBahsbVPeBoV30xaiSNRZc+MX5oZjJuJG3sMjbJQcrwMUTIo2HKG6A2Hw" +
-        "IDAQAB",
-
-        "OU=TC TrustCenter Class 2 CA",
-        "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDaOOjtMgApcYMBDb+MAdzaxq05pKmKL9" +
-        "WLXGhfUMZi9Wa9ypEi7KodUdc9s1Gyg05dy0mw8ExV5Wstx4ULMBySToLUygLt92++3ODj" +
-        "FLgFU/Ka9FaLWp6Fk9G0glauTbuoS1cWvP74WJ74KY2we814yU+si2cM8Zz7/FebV1xPDQ" +
-        "IDAQAB",
-
-        "OU=TC TrustCenter Class 3 CA",
-        "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC2tME1BS4NjeygQGocDiemUJJrUBsH3i" +
-        "7ndszg2vyEqF6MY2orTdlOAnYRwQvyjXnKALbxsA7X+6QXPa+raXqWJ7+vM6GaKlmqxLU3" +
-        "CPISpTG2Q/UylnEoKKuNKIbfu+7jDH0w1sNSq49dJ5xrwKPnBWtXSUSzbupkz9KOelB3dw" +
-        "IDAQAB",
-
-        "OU=TC TrustCenter Class 4 CA",
-        "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC/L2PWNnuyDdNV9WRs5iVdxrTIFLolOI" +
-        "PrVmKlVallo/QjmcJLudDNVGemo6CjqTMrduS9rXey7VwSdMPFtg9SmnKTQ5BiZhUPRaXd" +
-        "4N24b0BuV8F5cqNgqrp2HRKJU1r8Ar7hCRPFSi/cPYsZrdeLJEX7TPTNXDUdKUxR8/JsVQ" +
-        "IDAQAB",
-
-        "CN=Thawte Premium Server CA",
-        "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDSNjZqi9fCW57agUFijzjuSQRV1tDvHB" +
-        "uVFkfvGEg1OlL0K2oGjzsv6lbjr4aNnhf3nrRldQJN78sJoiFR2JvQZ9C6DZIGFHPUk8uX" +
-        "KgCcXE4MvPoVUvzyRG7aEUpuCJ8vLeP5qjqGc7ZGU1jIiQW9gxG4cz+qB430Qk3nQJ0cNw" +
-        "IDAQAB",
-
-        "C=hk, O=C&W HKT SecureNet CA SGC Root",
-        "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqFNPj0Pdr+zBtA0bX7cIoprIQu" +
-        "Nt1yUa3+DKvC8iJPlpIr0arVHncfe1dtTzPsg+EdBNe5keGLeezT5hG0URS1sm3Ck8AE0R" +
-        "2h2Pnh903hVAvDDJD9/4LXzYjZ2g4J+wzydgzzgRCO82L3xONh0mAqf01FBDgUnr3beWFD" +
-        "BjMtEDzSG8N5EePmWuFoL2FWBLUTuW5RnowvemBYE6qH8YWD53w1kAg/T1eUlgpy4DPgH9" +
-        "heLfoZqJ2fhkCiuEzUPNJTUAXjBmdKHHCHWsSSeC17CVNW4dmYDrkqAtWtY4u7VHJ6sazL" +
-        "9TU8FGsm/o101XEd2wNUgfqybqVg24CjC22wIDAQAB",
-
-        "CN=Thawte Server CA",
-        "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDTpFBuyP9Wa+bPXbbqDGh1R6KqwtqEJf" +
-        "yo9EdR2oW1IHSUhh4PdcnpCGH1Bm0wbhUZAulSwGLbTZme4moMRDjN/r7jZAlwxf6xaym2" +
-        "L0nIO9QnBCUQly/nkG3AKEKZ10xD3sP1IW1Un13DWOHA5NlbsLjctHvfNjrCtWYiEtaHDQ" +
-        "IDAQAB",
-
-        "CN=UTN - DATACorp SGC",
-        "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3+5YEKIrblXEjr8uRgnn4AgPLi" +
-        "t6E5Qbvfa2gI5lBZMAHryv4g+OGQ0SR+ysraP6LnD43m77VkIVni5c7yPeIbkFdicZD0/W" +
-        "w5y0vpQZY/KmEQrrU0icvvIpOxboGqBMpsn0GFlowHDyUwDAXlCCpVZvNvlK4ESGoE1O1k" +
-        "duSUrLZ9emxAW5jh70/P/N5zbgnAVssjMiFdC04MwXwLLA9P4yPykqlXvY8qdOD1R8oQ2A" +
-        "swkDwf9c3V6aPryuvEeKaq5xyh+xKrhfQgUL7EYw0XILyulWbfXv33i+Ybqypa4ETLyorG" +
-        "kVl73v67SMvzX41MPRKA5cOp9wGDMgd8SirwIDAQAB",
-
-        "CN=UTN-USERFirst-Hardware",
-        "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsffDOD+0qH/POYJRZ9Btn9L/WP" +
-        "PnnyvsDYlUmbk4mRb34CF5SMK7YXQSlh08anLVPBBnOjntKxPNZuuVCTOkbJex6MbswXV5" +
-        "nEZejavQav25KlUXEFSzGfCa9vGxXbanbfvgcRdrooj7AN/+GjF3DJoBerEy4ysBBzhuw6" +
-        "VeI7xFm3tQwckwj9vlK3rTW/szQB6g1ZgXvIuHw4nTXaCOsqqq9o5piAbF+okh8widaS4J" +
-        "M5spDUYPjMxJNLBpUb35Bs1orWZMvD6sYb0KiA7I3z3ufARMnQpea5HW7sftKI2rTYeJc9" +
-        "BupNAeFosU4XZEA39jrOTNSZzFkvSrMqFIWwIDAQAB",
-
-        "CN=UTN-USERFirst-Network Applications",
-        "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAs/uRoeQ2VYWsBjRboJpYsvi1Dw" +
-        "V3g64ysXaSaOwjSsl2P+Octjd5A7mraY0HJbYZZ+SwGxhzYUrofs3TL2TjpnwM+heAow1H" +
-        "iU9RcS/u/D/5uBaAh4mTJSCaQ4JpJHYoWTWhHcB/gwZkFiAs00mkhbTAYX9RCPhoFZGAy6" +
-        "XV7js69IQEXmBZp4w0cu64eMXROxJKb35lJ7mkVcW5b0OkxR0smcBSpHhMFbNAmAhrQ8YB" +
-        "sHp79WscIj/L7/+o0DpLdhWe0tHGLuPbVxsyorhv6IamP3Cr5XCSq0QeQFD7nKNi5GxuoM" +
-        "je4oBC+ukv6M4yBI98jbccozU8Fd2ew66XpQIDAQAB",
-
-        "CN=VeriSign Class 3 Public Primary Certification Authority - G3",
-        "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAy7qcUvx4Hxoebxs3c734yWuUEj" +
-        "BP8DZH9dCRCvUXyKVhwRZATfuKYZDldiDBEQZ9qyxupvURQY76La0qYVmkZyZM0Oi8Ultw" +
-        "IARY0XrJpGm8gxdkrQWLvNBYzo2M9evwQkkLnZcnZzJu4a6TFRxwvCBNLxjekojobIVXER" +
-        "rpfuMmEVSiRZZVg8owiejc2KPtKoA/f3llVz4VIGYIL5WTv6pHL6hGl/AS4v7CCitR5nbm" +
-        "t0a34g2mzKjDTFlVieboU1wc6p3wYhYLp8lfDPDewnbOr/dq8vpBpqIzFMnlemPTnmI31Y" +
-        "Vlng7mUyR0G14dElNbxyzng0k7Fa6KaLlXlwIDAQAB",
-
-        "CN=VeriSign Class 4 Public Primary Certification Authority - G3",
-        "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArculEWnGWavxj7UZD1bOzLUfIO" +
-        "SeJiVL4HNliVne0IPk9Q+1u63xfOgh/OToDO58RSIZdpK0E7cgWwn6Ya6o8qWNhcIq1t5m" +
-        "NtKbAvSokmB8nGm0jyQe0IZS9jKcQVgeIr3NRWKVCG7QZt1ToszwENxUc4sEoUYzM1wXQL" +
-        "meTdPzvlWD6LGJjlp8mpYikDuIJfLSU4gCDAt48uY3F0swRgfkgG2m2JYu6Cz4EbM4DWam" +
-        "m+rJI1vbjuLzE44aWS2qAvDspIdm3ME/9di59OyCxtI9lR3lwE+EydmjRCgGatdFrPBrau" +
-        "9OX/gRgh44YzRmUNQ+k3P6MMNmrf+TLZfvAwIDAQAB",
-
-        "OU=VeriSign Trust Network",
-        "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC68OTP+cSuhVS5B1f5j8V/aBH4xBewRN" +
-        "zjMHPVKmIquNDMHO0oW369atyzkSTKQWI8/AIBvxwWMZQFl3Zuoq29YRdsTjCG8FE3KlDH" +
-        "qGKB3FtKqsGgtG7rL+VXxbErQHDbWk2hjh+9Ax/YA9SPTJlxvOKCzFjomDqG04Y48wApHw" +
-        "IDAQAB",
-
-        "OU=VeriSign Trust Network",
-        "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC68OTP+cSuhVS5B1f5j8V/aBH4xBewRN" +
-        "zjMHPVKmIquNDMHO0oW369atyzkSTKQWI8/AIBvxwWMZQFl3Zuoq29YRdsTjCG8FE3KlDH" +
-        "qGKB3FtKqsGgtG7rL+VXxbErQHDbWk2hjh+9Ax/YA9SPTJlxvOKCzFjomDqG04Y48wApHw" +
-        "IDAQAB",
-
-        "OU=VeriSign Trust Network",
-        "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDMXtERXVxp0KvTuWpMmR9ZmDCOFoUgRm" +
-        "1HP9SFIIThbbP4pO0M8RcPO/mn+SXXwc+EY/J8Y8+iR/LGWzOOZEAEaMGAuWQcRXfH2G71" +
-        "lSk8UOg013gfqLptQ5GVj0VXXn7F+8qkBOvqlzdUMG+7AUcyM83cV5tkaWH4mx0ciU9cZw" +
-        "IDAQAB",
-
-        "OU=VeriSign Trust Network",
-        "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDMXtERXVxp0KvTuWpMmR9ZmDCOFoUgRm" +
-        "1HP9SFIIThbbP4pO0M8RcPO/mn+SXXwc+EY/J8Y8+iR/LGWzOOZEAEaMGAuWQcRXfH2G71" +
-        "lSk8UOg013gfqLptQ5GVj0VXXn7F+8qkBOvqlzdUMG+7AUcyM83cV5tkaWH4mx0ciU9cZw" +
-        "IDAQAB"
-    };
-
-    public static boolean alwaysFalse = false;
-
-    static class entropySpinner extends Thread {
-        volatile boolean stop = false;
-        byte counter = 0;
-        entropySpinner() { start(); }
-        public void run() {
-            while (true) {
-                counter++;
-
-                // without this line, GCJ will over-optimize this loop into an infinite loop. Argh.
-                if (alwaysFalse) stop = true;
-
-                if (stop) return;
-            }
-        }
-    }
-    
-    private static volatile boolean initializationFinished = false;
-    static { 
-        entropySpinner[] spinners = new entropySpinner[10];
-        for(int i=0; i<spinners.length; i++) spinners[i] = new entropySpinner();
-
-        for(int i=0; i<pad1.length; i++) pad1[i] = (byte)0x36;
-        for(int i=0; i<pad2.length; i++) pad2[i] = (byte)0x5C;
-        for(int i=0; i<pad1_sha.length; i++) pad1_sha[i] = (byte)0x36;
-        for(int i=0; i<pad2_sha.length; i++) pad2_sha[i] = (byte)0x5C;
-
-        try { 
-            if (Log.on) Log.info(SSL.class, "reading in trusted root public keys..."); 
-            trusted_CA_public_keys = new SubjectPublicKeyInfo[base64_encoded_trusted_CA_public_keys.length / 2];
-            trusted_CA_public_key_identifiers = new String[base64_encoded_trusted_CA_public_keys.length / 2];
-            for(int i=0; i<base64_encoded_trusted_CA_public_keys.length; i+=2) {
-                trusted_CA_public_key_identifiers[i/2] = base64_encoded_trusted_CA_public_keys[i];
-                byte[] b = Base64.decode(base64_encoded_trusted_CA_public_keys[i+1]);
-                DERInputStream dIn = new DERInputStream(new ByteArrayInputStream(b)); 
-                trusted_CA_public_keys[i/2] = new SubjectPublicKeyInfo((DERSequence)dIn.readObject());
-            }
-
-        } catch (Exception e) { 
-            if (Log.on) Log.info(SSL.class, e);
-        } 
-        
-        if (Log.on) Log.info(SSL.class, "generating entropy..."); 
-        randpool = new byte[10];
-        try { Thread.sleep(100); } catch (Exception e) { }
-        for(int i=0; i<spinners.length; i++) {
-            spinners[i].stop = true;
-            randpool[i] = spinners[i].counter;
-        }
-        
-        MD5Digest md5 = new MD5Digest();
-        md5.update(randpool, 0, randpool.length);
-        intToBytes(System.currentTimeMillis(), randpool, 0, 4); md5.update(randpool, 0, 4);
-        intToBytes(Runtime.getRuntime().freeMemory(), randpool, 0, 4); md5.update(randpool, 0, 4);
-        intToBytes(Runtime.getRuntime().totalMemory(), randpool, 0, 4); md5.update(randpool, 0, 4);
-        intToBytes(System.identityHashCode(SSL.class), randpool, 0, 4); md5.update(randpool, 0, 4);
-        Properties p = System.getProperties();
-        for(Enumeration e = p.propertyNames(); e.hasMoreElements();) {
-            String s = (String)e.nextElement();
-            byte[] b = s.getBytes();
-            md5.update(b, 0, b.length);
-            b = p.getProperty(s).getBytes();
-            md5.update(b, 0, b.length);
-        }
-        randpool = new byte[md5.getDigestSize()];
-        md5.doFinal(randpool, 0);
-
-        if (Log.on) Log.info(SSL.class, "SSL is initialized."); 
-        initializationFinished = true;
-        SSL.class.notifyAll();
-    } 
-
-
-    /**
-     *  A PKCS1 encoder which uses SSL's built-in PRNG instead of java.security.SecureRandom.
-     *  This code was derived from BouncyCastle's org.bouncycastle.crypto.encoding.PKCS1Encoding.
-     */
-    private static class PKCS1 implements AsymmetricBlockCipher {
-        private static int HEADER_LENGTH = 10;
-        private AsymmetricBlockCipher engine;
-        private boolean forEncryption;
-        private boolean forPrivateKey;
-        
-        public PKCS1(AsymmetricBlockCipher cipher) { this.engine = cipher; }   
-        public AsymmetricBlockCipher getUnderlyingCipher() { return engine; }
-
-        public void init(boolean forEncryption, CipherParameters param) {
-            engine.init(forEncryption, (AsymmetricKeyParameter)param);
-            this.forPrivateKey = ((AsymmetricKeyParameter)param).isPrivate();
-            this.forEncryption = forEncryption;
-        }
-
-        public int getInputBlockSize() { return engine.getInputBlockSize() - (forEncryption ? HEADER_LENGTH : 0); }
-        public int getOutputBlockSize() { return engine.getOutputBlockSize() - (forEncryption ? 0 : HEADER_LENGTH); }
-
-        public byte[] processBlock(byte[] in, int inOff, int inLen) throws InvalidCipherTextException {
-            return forEncryption ? encodeBlock(in, inOff, inLen) : decodeBlock(in, inOff, inLen);
-        }
-
-        private byte[] encodeBlock(byte[] in, int inOff, int inLen) throws InvalidCipherTextException {
-            byte[]  block = new byte[engine.getInputBlockSize()];
-            if (forPrivateKey) {
-                block[0] = 0x01;                        // type code 1
-                for (int i = 1; i != block.length - inLen - 1; i++)
-                    block[i] = (byte)0xFF;
-            } else {
-                getRandomBytes(block, 0, block.length);
-                block[0] = 0x02;                        // type code 2
-
-                // a zero byte marks the end of the padding, so all
-                // the pad bytes must be non-zero.
-                for (int i = 1; i != block.length - inLen - 1; i++)
-                    while (block[i] == 0)
-                        getRandomBytes(block, i, 1);
-            }
-
-            block[block.length - inLen - 1] = 0x00;       // mark the end of the padding
-            System.arraycopy(in, inOff, block, block.length - inLen, inLen);
-            return engine.processBlock(block, 0, block.length);
-        }
-
-        private byte[] decodeBlock(byte[] in, int inOff, int inLen) throws InvalidCipherTextException {
-            byte[]  block = engine.processBlock(in, inOff, inLen);
-            if (block.length < getOutputBlockSize())
-                throw new InvalidCipherTextException("block truncated");
-            if (block[0] != 1 && block[0] != 2)
-                throw new InvalidCipherTextException("unknown block type");
-
-            // find and extract the message block.
-            int start;
-            for (start = 1; start != block.length; start++)
-                if (block[start] == 0)
-                    break;
-            start++;           // data should start at the next byte
-
-            if (start >= block.length || start < HEADER_LENGTH)
-                throw new InvalidCipherTextException("no data in block");
-
-            byte[]  result = new byte[block.length - start];
-            System.arraycopy(block, start, result, 0, result.length);
-            return result;
-        }
-    }
-
-}
-
index 09487bd..e4c85fa 100644 (file)
@@ -1,10 +1,12 @@
 // Copyright 2004 Adam Megacz, see the COPYING file for licensing [GPL]
-package org.ibex;
+package org.ibex.util;
 
 import java.io.IOException;
 
 import org.ibex.js.*;
 import org.ibex.util.*;
+import org.ibex.graphics.*;
+import org.ibex.plat.*;
 
 /** Implements cooperative multitasking */
 public class Scheduler {
@@ -12,7 +14,6 @@ public class Scheduler {
     // Public API Exposed to org.ibex /////////////////////////////////////////////////
 
     private static Scheduler singleton;
-    public static interface Task { public abstract void perform() throws IOException, JSExn; }
     public static void add(Task t) { Log.debug(Scheduler.class, "scheduling " + t); Scheduler.runnable.append(t); }
     public static void init() { if (singleton == null) (singleton = Platform.getScheduler()).run(); }
 
@@ -52,7 +53,7 @@ public class Scheduler {
      *  Surface.renderAll() more often than that if it so chooses.
      */
     public void run() { defaultRun(); }
-    protected Scheduler() { }
+    public Scheduler() { }
 
 
     // Default Implementation //////////////////////////////////////////////////////
diff --git a/src/org/ibex/util/Task.java b/src/org/ibex/util/Task.java
new file mode 100644 (file)
index 0000000..e710724
--- /dev/null
@@ -0,0 +1,8 @@
+// Copyright 2004 Adam Megacz, see the COPYING file for licensing [GPL]
+package org.ibex.util;
+import java.io.IOException;
+import org.ibex.js.*;
+
+public interface Task {
+    public abstract void perform() throws IOException, JSExn;
+}