Author: bdonlan
Date: 2005-06-11 14:17:46 -0400 (Sat, 11 Jun 2005)
New Revision: 763
Added:
trunk/clients/Javer2/src/org/haverdev/client/
trunk/clients/Javer2/src/org/haverdev/client/AuthCallback.java
trunk/clients/Javer2/src/org/haverdev/client/AuthProvider.java
trunk/clients/Javer2/src/org/haverdev/client/BasicAuthenticationProvider.java
trunk/clients/Javer2/src/org/haverdev/client/Callback.java
trunk/clients/Javer2/src/org/haverdev/client/Client.java
trunk/clients/Javer2/src/org/haverdev/client/SwingBasicAuthentication.java
trunk/clients/Javer2/src/org/haverdev/client/SwingPasswordDialog.form
trunk/clients/Javer2/src/org/haverdev/client/SwingPasswordDialog.java
trunk/clients/Javer2/src/org/haverdev/common/
trunk/clients/Javer2/src/org/haverdev/common/Base64.java
trunk/clients/Javer2/src/org/haverdev/common/BasicAuthenticationHasher.java
trunk/clients/Javer2/src/org/haverdev/common/HaverEncoding.java
trunk/clients/Javer2/src/org/haverdev/common/ObjectQueue.java
trunk/clients/Javer2/src/org/haverdev/haver/server/exceptions/AuthNotSupportedException.java
Removed:
trunk/clients/Javer2/src/org/haverdev/haver/Base64.java
trunk/clients/Javer2/src/org/haverdev/haver/Callback.java
trunk/clients/Javer2/src/org/haverdev/haver/Client.java
trunk/clients/Javer2/src/org/haverdev/haver/server/ObjectQueue.java
Modified:
trunk/clients/Javer2/nbproject/project.properties
trunk/clients/Javer2/server.conf
trunk/clients/Javer2/src/org/haverdev/haver/server/AcceptLoop.java
trunk/clients/Javer2/src/org/haverdev/haver/server/AuthProvider.java
trunk/clients/Javer2/src/org/haverdev/haver/server/AuthenticationProcess.java
trunk/clients/Javer2/src/org/haverdev/haver/server/BasicAuthentication.java
trunk/clients/Javer2/src/org/haverdev/haver/server/EntityLoader.java
trunk/clients/Javer2/src/org/haverdev/haver/server/FileUserStore.java
trunk/clients/Javer2/src/org/haverdev/haver/server/InitContext.java
trunk/clients/Javer2/src/org/haverdev/haver/server/LoginContext.java
trunk/clients/Javer2/src/org/haverdev/haver/server/Main.java
trunk/clients/Javer2/src/org/haverdev/haver/server/Misc.java
trunk/clients/Javer2/src/org/haverdev/haver/server/StatsBot.java
trunk/clients/Javer2/src/org/haverdev/haver/server/UserCommandWrapper.java
trunk/clients/Javer2/src/org/haverdev/haver/server/UserConnection.java
trunk/clients/Javer2/src/org/haverdev/haver/server/UserContextFactory.java
trunk/clients/Javer2/src/org/haverdev/haver/server/Xiao.java
trunk/clients/Javer2/src/org/haverdev/javer2/CMod.java
trunk/clients/Javer2/src/org/haverdev/javer2/ChannelPane.java
trunk/clients/Javer2/src/org/haverdev/javer2/JaverForm.form
trunk/clients/Javer2/src/org/haverdev/javer2/JaverForm.java
trunk/clients/Javer2/src/org/haverdev/javer2/Main.java
trunk/clients/Javer2/src/org/haverdev/javer2/QueryPane.java
Log:
Authentication works as per docs/auth-proposed.txt, save for some exception
stuff
Modified: trunk/clients/Javer2/nbproject/project.properties
===================================================================
--- trunk/clients/Javer2/nbproject/project.properties 2005-06-10 20:43:42 UTC
(rev 762)
+++ trunk/clients/Javer2/nbproject/project.properties 2005-06-11 18:17:46 UTC
(rev 763)
@@ -17,7 +17,7 @@
dist.javadoc.dir=${dist.dir}/javadoc
jar.compress=false
javac.classpath=\
- ${file.reference.log4j.jar}
+ ${libs.log4j.classpath}
# Space-separated list of extra javac options
javac.compilerargs=
javac.deprecation=false
Modified: trunk/clients/Javer2/server.conf
===================================================================
--- trunk/clients/Javer2/server.conf 2005-06-10 20:43:42 UTC (rev 762)
+++ trunk/clients/Javer2/server.conf 2005-06-11 18:17:46 UTC (rev 763)
@@ -1,9 +1,8 @@
-#Tue May 24 16:20:29 EDT 2005
-
# This file is absolutely vital for the server to start. Sorry.
-# Which port to listen on
-#haver.ListenPort=7070
+# You MUST configure this properly. Password authentication will NOT work
+# otherwise
+haver.hostname=uvmonkey.no-ip.org
# GNU classpath does not have SSL support
haver.listeners=org.haverdev.haver.server.AcceptLoop,
org.haverdev.haver.server.SSLAcceptLoop
@@ -11,7 +10,6 @@
org.haverdev.haver.server.AcceptLoop.listenPorts=7070
org.haverdev.haver.server.SSLAcceptLoop.listenPorts=7777
-
# Time after a S: PING before disconnect
haver.PingTimeout=30
@@ -28,10 +26,6 @@
# A list of (haver auth digest name):(java digest SPI name)
haver.digestMaps=sha512:SHA-512 sha256:SHA-256 sha1:SHA-1
-# Default chat channels (deprecated)
-#haver.ChatChannels=lobby,conspiracy,haver,creatures
-haver.ChatChannels=
-
#haver.UserStore=org.haverdev.haver.server.DefaultUserStore
haver.UserStore=org.haverdev.haver.server.FileUserStore
org.haverdev.haver.server.FileUserStore.path=store
Added: trunk/clients/Javer2/src/org/haverdev/client/AuthCallback.java
===================================================================
--- trunk/clients/Javer2/src/org/haverdev/client/AuthCallback.java
2005-06-10 20:43:42 UTC (rev 762)
+++ trunk/clients/Javer2/src/org/haverdev/client/AuthCallback.java
2005-06-11 18:17:46 UTC (rev 763)
@@ -0,0 +1,21 @@
+/*
+ * AuthCallback.java
+ *
+ * Created on June 10, 2005, 10:00 PM
+ *
+ * To change this template, choose Tools | Options and locate the template
under
+ * the Source Creation and Management node. Right-click the template and choose
+ * Open. You can then make changes to the template in the Source Editor.
+ */
+
+package org.haverdev.client;
+
+/**
+ *
+ * @author Bryan
+ */
+public interface AuthCallback {
+
+ public void failAuth(boolean retry);
+
+}
Property changes on:
trunk/clients/Javer2/src/org/haverdev/client/AuthCallback.java
___________________________________________________________________
Name: svn:eol-style
+ native
Added: trunk/clients/Javer2/src/org/haverdev/client/AuthProvider.java
===================================================================
--- trunk/clients/Javer2/src/org/haverdev/client/AuthProvider.java
2005-06-10 20:43:42 UTC (rev 762)
+++ trunk/clients/Javer2/src/org/haverdev/client/AuthProvider.java
2005-06-11 18:17:46 UTC (rev 763)
@@ -0,0 +1,28 @@
+/*
+ * AuthProvider.java
+ *
+ * Created on June 10, 2005, 9:44 PM
+ *
+ * To change this template, choose Tools | Options and locate the template
under
+ * the Source Creation and Management node. Right-click the template and choose
+ * Open. You can then make changes to the template in the Source Editor.
+ */
+
+package org.haverdev.client;
+
+/**
+ *
+ * @author Bryan
+ */
+public abstract class AuthProvider extends Callback {
+
+ /** Creates a new instance of AuthProvider */
+ public AuthProvider() {
+ }
+
+ public abstract void attach(Client c);
+ public abstract String getName();
+ public abstract void attemptAuthentication(AuthCallback c);
+ public abstract void resetState();
+
+}
Property changes on:
trunk/clients/Javer2/src/org/haverdev/client/AuthProvider.java
___________________________________________________________________
Name: svn:eol-style
+ native
Added:
trunk/clients/Javer2/src/org/haverdev/client/BasicAuthenticationProvider.java
===================================================================
---
trunk/clients/Javer2/src/org/haverdev/client/BasicAuthenticationProvider.java
2005-06-10 20:43:42 UTC (rev 762)
+++
trunk/clients/Javer2/src/org/haverdev/client/BasicAuthenticationProvider.java
2005-06-11 18:17:46 UTC (rev 763)
@@ -0,0 +1,127 @@
+/*
+ * BasicAuthenticationProvider.java
+ *
+ * Created on June 10, 2005, 9:45 PM
+ *
+ * To change this template, choose Tools | Options and locate the template
under
+ * the Source Creation and Management node. Right-click the template and choose
+ * Open. You can then make changes to the template in the Source Editor.
+ */
+
+package org.haverdev.client;
+import java.nio.charset.CharsetEncoder;
+import org.haverdev.common.*;
+import java.security.*;
+import java.util.*;
+import java.nio.*;
+import java.nio.charset.*;
+
+/**
+ *
+ * @author Bryan
+ */
+public abstract class BasicAuthenticationProvider extends AuthProvider {
+
+ static Map algos = null;
+
+ static void mapAlgo(Map algos, String havername, String spiname) {
+ try {
+ MessageDigest.getInstance(spiname);
+ algos.put(havername, spiname);
+ }
+ catch (NoSuchAlgorithmException e) {
+ e.printStackTrace();
+ }
+ }
+
+ static void algoInit() {
+ if (algos != null) return;
+
+ String algostr = System.getProperty("haver.digestMaps",
"sha512:SHA-512 sha256:SHA-256 sha1:SHA-1");
+ String[] algolist = HaverEncoding.optionSplit(algostr);
+ Map algotemp = new LinkedHashMap();
+
+ for (int i = 0; i < algolist.length; i++) {
+ String desc = algolist[i];
+ int sep = desc.indexOf(':');
+ String havername = desc.substring(0, sep);
+ String spiname = desc.substring(sep + 1);
+ mapAlgo(algotemp, havername, spiname);
+ }
+
+ algos = Collections.unmodifiableMap(algotemp);
+ }
+
+ static {
+ algoInit();
+ }
+
+ /** Creates a new instance of BasicAuthenticationProvider */
+ public BasicAuthenticationProvider() {
+ }
+
+ protected abstract String getPassword();
+
+ Client client = null;
+
+ public void attach(Client c) {
+ client = c;
+ }
+
+ public void resetState() {
+ }
+
+ public String getName() {
+ return "basic";
+ }
+
+ AuthCallback callback = null;
+
+ public void attemptAuthentication(AuthCallback callback) {
+ this.callback = callback;
+ client.sendLine(new String[] { "AUTH:TYPE", "basic" });
+ }
+
+ public void onIncomingLine(Client source, String[] args) {
+ if (args[0].equals("AUTH:BASIC")) {
+ BasicAuthenticationHasher h = new BasicAuthenticationHasher();
+
+ h.setNonce(args[1]);
+
+ h.setUsername(source.getName());
+ h.setHostname(source.getHostname());
+ h.setPassword(getPassword());
+
+ System.err.println("tok=" + h.getPasstoken());
+
+ Set algos = h.availableAlgos();
+ String algoname = null;
+ String hash = null;
+
+ for (int i = 2; i < args.length; i++) {
+ if (!this.algos.containsKey(args[i]))
+ continue;
+ try {
+ hash = h.digest(args[i]);
+ algoname = args[i];
+ break;
+ }
+ catch (NoSuchAlgorithmException e) {
+ e.printStackTrace();
+ }
+ }
+
+ if (hash == null) {
+ callback.failAuth(false);
+ return;
+ }
+
+ client.sendLine(new String[] { "AUTH:BASIC", algoname, hash });
+ return;
+ }
+ else if (args[0].equals("FAIL") && args[1].equals("AUTH:BASIC")) {
+ callback.failAuth(true);
+ }
+ }
+
+}
Property changes on:
trunk/clients/Javer2/src/org/haverdev/client/BasicAuthenticationProvider.java
___________________________________________________________________
Name: svn:eol-style
+ native
Copied: trunk/clients/Javer2/src/org/haverdev/client/Callback.java (from rev
731, trunk/clients/Javer2/src/org/haverdev/haver/Callback.java)
===================================================================
--- trunk/clients/Javer2/src/org/haverdev/haver/Callback.java 2005-05-25
02:59:42 UTC (rev 731)
+++ trunk/clients/Javer2/src/org/haverdev/client/Callback.java 2005-06-11
18:17:46 UTC (rev 763)
@@ -0,0 +1,90 @@
+/*
+ * Callback.java
+ *
+ * Created on May 21, 2005, 9:39 PM
+ */
+
+package org.haverdev.client;
+import java.io.IOException;
+import org.haverdev.haver.*;
+
+/**
+ *
+ * @author bdonlan
+ */
+public abstract class Callback implements java.util.EventListener {
+ /**
+ * Called when a connection to the server is established but before
handshaking
+ * occurs.
+ * @param source haver.Client instance associated with this event
+ * @throws java.io.IOException
+ */
+ public void onConnect(Client source) throws Throwable {}
+ /**
+ * Called when a connection attempt fails.
+ * @param source haver.Client instance associated with this event
+ * @param e IOException which caused the connection failure
+ * @throws java.io.IOException
+ */
+ public void onConnectFailed(Client source, java.io.IOException e) throws
Throwable {}
+ /**
+ * Called when an established connection is lost
+ * @param source haver.Client instance associated with this event
+ * @param e Exception associated with the connection loss, or null if
connection loss did
+ * not have an associated exception (e.g., connection broken)
+ * @throws java.io.IOException
+ */
+ public void onDisconnected(Client source, java.io.IOException e) throws
Throwable {}
+ /**
+ * Called when a message is received from the server
+ * @param source haver.Client instance associated with this event
+ * @param args Arguments of the message
+ * @throws java.io.IOException
+ */
+ public void onIncomingLine(Client source, String[] args) throws Throwable
{}
+ /**
+ * Called when a message is sent to the server
+ * @param source haver.Client instance associated with this event
+ * @param args Arguments of the message
+ * @throws java.io.IOException
+ */
+ public void onOutgoingLine(Client source, String[] args) throws Throwable
{}
+ /**
+ * Called when the server requires identification
+ * @param source haver.Client instance associated with this event
+ * @throws java.io.IOException
+ */
+ public void onNeedIdent(Client source) throws Throwable {}
+ /**
+ * Called when the name given by the client has been accepted
+ * @param source haver.Client instance associated with this event
+ * @param name Name that was accepted by the server
+ * @throws java.io.IOException
+ */
+ public void onAccept(Client source, String name) throws Throwable {}
+
+ /**
+ * Called when the server responds to a listing request
+ * @param source haver.Client instance associated with this event
+ * @param channel Channel that was listed
+ * @param namespace Namespace of objects listed
+ * @param list List of objects held by the channel
+ * @throws java.io.IOException
+ */
+ public void onReceivedList(Client source, String channel, String
namespace, String[] list) throws Throwable {}
+
+ public void onPublicMessage(Client source, String channel, String from,
String type, String[] args) throws Throwable {}
+
+ public void onPrivateMessage(Client source, String from, String type,
String[] args) throws Throwable {}
+
+ public void onJoin(Client source, String channel, String who) throws
Throwable {}
+
+ public void onPart(Client source, String channel, String who) throws
Throwable {}
+
+ public void onQuit(Client source, String who, String type, String detail)
throws Throwable {}
+
+ // XXX: this is a hack and should not be used in apps
+ void onFail(Client source, String[] args) throws Throwable {};
+
+ public void onAuthenticationFailed(Client source) {};
+}
Copied: trunk/clients/Javer2/src/org/haverdev/client/Client.java (from rev 743,
trunk/clients/Javer2/src/org/haverdev/haver/Client.java)
===================================================================
--- trunk/clients/Javer2/src/org/haverdev/haver/Client.java 2005-05-31
04:02:26 UTC (rev 743)
+++ trunk/clients/Javer2/src/org/haverdev/client/Client.java 2005-06-11
18:17:46 UTC (rev 763)
@@ -0,0 +1,985 @@
+/*
+ * Client.java
+ *
+ * Created on May 21, 2005, 8:48 PM
+ */
+
+package org.haverdev.client;
+import java.io.*;
+import java.util.*;
+import java.net.*;
+import java.lang.reflect.*;
+import org.haverdev.haver.*;
+
+/**
+ * A Haver client class
+ * @author bdonlan
+ */
+public class Client {
+
+
+ HashSet listening = new java.util.HashSet();
+ CallbackDist dist;
+ Socket theSocket = null;
+ boolean connecting = false;
+ Thread io = null;
+ Client self = this;
+ PrintWriter writer = null;
+ BufferedReader reader = null;
+ NonblockingOutputStream s;
+ String name = null;
+ String hostname = null;
+ HashMap authProviders = new HashMap();
+
+ static final String[] greeting = {"HAVER", "haver.Client/0.00", "auth"};
+
+ String host;
+ int port;
+
+ public String getName() {
+ return name;
+ }
+
+ public String getHostname() {
+ return hostname;
+ }
+
+ /**
+ * Mutable boolean flag
+ */
+ class Flag {
+ public boolean ok = true;
+ }
+
+ /** Creates a new instance of Client */
+ public Client() {
+ dist = new CallbackDist(listening);
+ }
+
+ public synchronized void addAuthProvider(AuthProvider p) {
+ p.attach(this);
+ authProviders.put(p.getName(), p);
+ }
+
+ public synchronized void removeAuthProvider(AuthProvider p) {
+ authProviders.remove(p.getName());
+ }
+
+ public synchronized void removeAuthProvider(String p) {
+ authProviders.remove(p);
+ }
+
+ /**
+ * Reverses Haver escaping.
+ * @param val String to unescape
+ * @return The unescaped string
+ */
+ protected static final String unescape(String val) {
+ //if (val != null) return val;
+ StringBuffer out = new StringBuffer();
+ int pin = 0;
+ int nextEsc = -1;
+ while (-1 != (nextEsc = val.indexOf("\033", pin))) {
+ out.append(val.substring(0, nextEsc - 1));
+ switch (val.charAt(nextEsc + 1)) {
+ case 'r':
+ out.append('\r');
+ break;
+ case 'n':
+ out.append('\n');
+ break;
+ case 'e':
+ out.append('\033');
+ break;
+ case 't':
+ out.append('\t');
+ break;
+ default:
+ out.append(val.charAt(nextEsc + 1));
+ break;
+ }
+ pin = nextEsc + 2;
+ }
+ out.append(val.substring(pin));
+ return out.toString();
+ }
+
+ /**
+ * Escapes a string according to the Haver protocol
+ * @param val String to escape
+ * @return Escaped string
+ */
+ protected static final String escape(String val) {
+ return val.replaceAll("\033", "\033e")
+ .replaceAll("\n", "\033n")
+ .replaceAll("\r", "\033r")
+ .replaceAll("\t", "\033t");
+ }
+
+ /**
+ * Decodes a raw line from the Haver protocol.
+ * @param inLine Line to decode. May end in '\r\n' but must only be one
line.
+ * @return An array containing the unescaped arguments of the line.
+ */
+ protected static final String[] decodeLine(String inLine) {
+ inLine = inLine.replaceAll("[\n\r]", ""); // We'll assume you only
passed one
+ // line in.
+ String[] args = inLine.split("\t");
+ for (int i = 0; i < args.length; i++) {
+ args[i] = unescape(args[i]);
+ }
+ return args;
+ }
+
+ /**
+ * Encodes a set of arguments for line transmission
+ * @param args Unescaped arguments to encode
+ * @return Escaped and joined line ready for transmission, complete with
ending \r\n
+ */
+ protected static final String encodeLine(String[] args) {
+ StringBuffer out = new StringBuffer();
+ for (int i = 0; i < args.length; i++) {
+ if (i != 0)
+ out.append("\t");
+ out.append(escape(args[i]));
+ }
+ out.append("\r\n");
+ return out.toString();
+ }
+
+ /**
+ * Internal class for distributing callback events to all listeners
+ */
+ protected class CallbackDist extends Callback {
+ java.util.HashSet listeners;
+
+ /**
+ *
+ * @param l Listener set
+ */
+ public CallbackDist(HashSet l) {
+ listeners = l;
+ }
+
+ /**
+ * Returns a constant iterator over the current listeners, which will
not be
+ * affected by concurrency issues.
+ */
+ protected Iterator iterator() {
+ // Prevent concurrency issues
+ synchronized (listeners) {
+ return ((HashSet)listeners.clone()).iterator();
+ }
+ }
+
+ public void onDisconnected(Client source, IOException e) throws
IOException {
+ try {reader.close();} catch (Throwable t) {}
+ try {writer.close();} catch (Throwable t) {}
+ try {theSocket.close();} catch (Throwable t) {}
+ reader = null;
+ writer = null;
+ theSocket = null;
+ io = null;
+
+ Iterator i = iterator();
+ while (i.hasNext()) {
+ Callback c = (Callback)i.next();
+ try {
+ c.onDisconnected(source, e);
+ } catch (Throwable t) {
+ t.printStackTrace();
+ }
+ }
+
+ }
+
+ public void onConnectFailed(Client source, IOException e) throws
IOException {
+ Iterator i = iterator();
+ while (i.hasNext()) {
+ Callback c = (Callback)i.next();
+ try {
+ c.onConnectFailed(source, e);
+ } catch (Throwable t) {
+ t.printStackTrace();
+ }
+ }
+ }
+
+ public void onConnect(Client source) throws IOException {
+ // Konnichiha, saaba-san!
+ sendLine(greeting);
+
+ Iterator i = iterator();
+ while (i.hasNext()) {
+ Callback c = (Callback)i.next();
+ try {
+ c.onConnect(source);
+ } catch (IOException e) {
+ throw e;
+ } catch (Throwable e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ public void onOutgoingLine(Client source, String[] args) throws
IOException {
+ Iterator i = iterator();
+ while (i.hasNext()) {
+ Callback c = (Callback)i.next();
+ try {
+ c.onOutgoingLine(source, args);
+ } catch (IOException e) {
+ throw e;
+ } catch (Throwable e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ public void onIncomingLine(Client source, String[] args) throws
IOException {
+ Iterator i = iterator();
+ while (i.hasNext()) {
+ Callback c = (Callback)i.next();
+ try {
+ c.onIncomingLine(source, args);
+ } catch (IOException e) {
+ throw e;
+ } catch (Throwable e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ public void onNeedIdent(Client source) throws IOException {
+ Iterator i = iterator();
+ while (i.hasNext()) {
+ Callback c = (Callback)i.next();
+ try {
+ c.onNeedIdent(source);
+ } catch (IOException e) {
+ throw e;
+ } catch (Throwable e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ public void onAccept(Client source, String name) throws IOException {
+ Iterator i = iterator();
+ while (i.hasNext()) {
+ Callback c = (Callback)i.next();
+ try {
+ c.onAccept(source, name);
+ } catch (IOException e) {
+ throw e;
+ } catch (Throwable e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ public void onReceivedList(Client source, String channel, String
namespace, String[] list) throws IOException {
+ Iterator i = iterator();
+ while (i.hasNext()) {
+ Callback c = (Callback)i.next();
+ try {
+ c.onReceivedList(source, channel, namespace, list);
+ } catch (IOException e) {
+ throw e;
+ } catch (Throwable e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ public void onPublicMessage(Client source, String channel, String
from, String type, String[] args) throws IOException {
+ Iterator i = iterator();
+ while (i.hasNext()) {
+ Callback c = (Callback)i.next();
+ try {
+ c.onPublicMessage(source, channel, from, type, args);
+ } catch (IOException e) {
+ throw e;
+ } catch (Throwable e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ public void onPrivateMessage(Client source, String from, String type,
String[] args) throws IOException {
+ Iterator i = iterator();
+ while (i.hasNext()) {
+ Callback c = (Callback)i.next();
+ try {
+ c.onPrivateMessage(source, from, type, args);
+ } catch (IOException e) {
+ throw e;
+ } catch (Throwable e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ public void onQuit(Client source, String who, String type, String
detail) throws IOException {
+ Iterator i = iterator();
+ while (i.hasNext()) {
+ Callback c = (Callback)i.next();
+ try {
+ c.onQuit(source, who, type, detail);
+ } catch (IOException e) {
+ throw e;
+ } catch (Throwable e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ public void onPart(Client source, String channel, String who) throws
IOException {
+ Iterator i = iterator();
+ while (i.hasNext()) {
+ Callback c = (Callback)i.next();
+ try {
+ c.onPart(source, channel, who);
+ } catch (IOException e) {
+ throw e;
+ } catch (Throwable e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ public void onJoin(Client source, String channel, String who) throws
IOException {
+ Iterator i = iterator();
+ while (i.hasNext()) {
+ Callback c = (Callback)i.next();
+ try {
+ c.onJoin(source, channel, who);
+ } catch (IOException e) {
+ throw e;
+ } catch (Throwable e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ void onFail(Client source, String[] args) throws IOException {
+ Iterator i = iterator();
+ while (i.hasNext()) {
+ Callback c = (Callback)i.next();
+ try {
+ c.onFail(source, args);
+ } catch (IOException e) {
+ throw e;
+ } catch (Throwable e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ public void onAuthenticationFailed(Client source) {
+ Iterator i = iterator();
+ while (i.hasNext()) {
+ Callback c = (Callback)i.next();
+ try {
+ c.onAuthenticationFailed(source);
+ } catch (Throwable e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ }
+
+ /**
+ * Entry point for IO thread; connects to specified host and port.
+ * @param host Hostname to connect to
+ * @param port Port number to connect to
+ */
+ protected void run(String host, int port) {
+ synchronized (this) {
+ if (Thread.currentThread() != io) {
+ throw new IllegalStateException("Client.run called outside io
thread");
+ }
+ }
+ Thread.currentThread().setName("haver.Client input thread");
+ try {
+ Socket mySock = new Socket(host, port);
+ theSocket = mySock;
+ } catch (IOException e) {
+ try {
+ io = null;
+ dist.onConnectFailed(this, e);
+ } catch (IOException e2) {}
+ return;
+ }
+ run();
+ }
+
+ protected void run() {
+ try {
+ writer = new PrintWriter
+ (new OutputStreamWriter
+ (s = new NonblockingOutputStream
+ (new BufferedOutputStream
+ (theSocket.getOutputStream()))));
+ s.setAutoFlush(true);
+ reader = new BufferedReader
+ (new InputStreamReader
+ (theSocket.getInputStream()));
+ dist.onConnect(this);
+ ioLoop(new Flag());
+ } catch (IOException e) {
+ try {
+ // XXX: may be called more than once
+ dist.onDisconnected(this, e);
+ } catch (IOException e2) {
+ }
+ return;
+ }
+ }
+
+ /**
+ * Sends a command to the server.
+ * @param args Arguments of the line to send
+ * @throws java.io.IOException
+ */
+ protected synchronized void sendLine(String[] args) {
+ if (writer != null) {
+ String l = encodeLine(args);
+ System.out.print("C: " + l);
+ writer.print(l);
+ writer.flush();
+ }
+ }
+
+ protected synchronized void killConnection() {
+ // Kill the connection. Don't ask questions, just do it.
+ try {
+ writer.flush();
+ } catch (Throwable t) {}
+ try {
+ theSocket.close();
+ } catch (Throwable t) {}
+ }
+
+ /**
+ * Main IO loop
+ * @param f Termination flag; ioLoop will return when f.ok is false
+ * @throws java.io.IOException
+ */
+ protected void ioLoop(Flag f) throws IOException {
+ while (io != null && f.ok) {
+ String l = reader.readLine();
+ if (l == null) {
+ dist.onDisconnected(this, null);
+ return;
+ }
+ System.out.println("S: " + l);
+ String[] args = decodeLine(l);
+ dist.onIncomingLine(this, args);
+ dispatch(args);
+ }
+ }
+
+ /**
+ * Connect to a given host asynchronously.
+ * @param host Hostname to connect to
+ * @param port Port number to connect to
+ * @throws java.lang.IllegalStateException Thrown if the client is already
connected or connecting.
+ */
+ public synchronized void connect(String host, int port)
+ throws IllegalStateException
+ {
+ if (io != null && io.isAlive()) {
+ throw new IllegalStateException("Already connecting");
+ }
+ name = null;
+ theSocket = null;
+ this.host = host;
+ this.port = port;
+ io = new Thread(new Runnable() {
+ public void run() {
+ self.run(self.host, self.port);
+ }
+ });
+ io.start();
+ }
+
+ public synchronized void connect(Socket s) throws IllegalStateException
+ {
+ if (io != null && io.isAlive()) {
+ throw new IllegalStateException("Already connecting");
+ }
+ name = null;
+ theSocket = s;
+ io = new Thread(new Runnable() {
+ public void run() {
+ self.run();
+ }
+ });
+ io.start();
+ }
+
+ /**
+ * Base class for event listeners for synchronous methods
+ */
+ protected class SyncMonitor extends Callback {
+ /**
+ * The exception which caused the operation to fail, or null if none
+ */
+ private IOException fail = null;
+ /**
+ * Flag for ioLoop() termination
+ */
+ private Flag flag = new Flag();
+
+ /**
+ * Return value
+ */
+ private Object ret = null;
+
+ protected synchronized void fail(IOException e) {
+ fail = e;
+ done(null);
+ }
+
+ public SyncMonitor() {
+ addNotify(this);
+ }
+
+ /**
+ * Signal completion of the synchronous event
+ */
+ protected synchronized void done(Object ret) {
+ if (!flag.ok)
+ throw new IllegalStateException("Already finished!");
+ removeNotify(this);
+ flag.ok = false;
+ this.ret = ret;
+ notifyAll();
+ }
+
+ public synchronized void onDisconnected(Client source, IOException e) {
+ if (e == null)
+ e = new IOException("Disconnected unexpectedly");
+ fail(e);
+ }
+
+ public synchronized void onConnectFailed(Client source, IOException e)
{
+ fail(e);
+ }
+
+ /**
+ * Wait until the synchronous event completes
+ * @throws java.io.IOException
+ */
+ public synchronized Object block() throws IOException,
InterruptedException {
+ if (Thread.currentThread() == io) {
+ ioLoop(flag);
+ } else {
+ try {
+ wait();
+ } catch (InterruptedException e) {
+ removeNotify(this);
+ throw e;
+ }
+ }
+ if (fail != null)
+ throw fail;
+ return ret;
+ }
+ }
+
+ /**
+ * Event listener for syncConnect()
+ */
+ protected class ConnectMonitor extends SyncMonitor {
+ /**
+ * true if connection completed successfully
+ */
+ public boolean done = false;
+ /**
+ * Name for login
+ */
+ public String name;
+
+ public ConnectMonitor(String name) {
+ this.name = name;
+ }
+
+ public void onNeedIdent(Client source) throws IOException {
+ source.ident(name);
+ }
+
+ public void onAccept(Client source, String name) {
+ done(null);
+ }
+
+ void onFail(Client source, String[] args) {
+ // XXX
+ fail(new IOException("Something broke: " + args[2]));
+ }
+ }
+
+ /**
+ * Connects to a host synchronously.
+ * @param host Hostname to connect to.
+ * @param port Port to connect to.
+ * @param name Name to use upon connect.
+ * @throws java.io.IOException Thrown if an IO exception occurs at any
point during the connect, or if the
+ * connection is lost.
+ */
+ public void syncConnect(String host, int port, String name) throws
IOException, InterruptedException {
+ ConnectMonitor m = new ConnectMonitor(name);
+ connect(host, port);
+ m.block();
+ }
+
+ public void syncConnect(Socket s, String name) throws IOException,
InterruptedException {
+ ConnectMonitor m = new ConnectMonitor(name);
+ connect(s);
+ m.block();
+ }
+
+ /**
+ * Adds a callback to notify when an event occurs
+ * @param c Callback class to add
+ */
+ public void addNotify(Callback c) {
+ synchronized (listening) {
+ listening.add(c);
+ }
+ }
+
+ /**
+ * Removes a callback class from the notify list
+ * @param c Callback to remove
+ */
+ public void removeNotify(Callback c) {
+ synchronized (listening) {
+ listening.remove(c);
+ }
+ }
+
+ /**
+ * Dispatch the passed line to the appropriate internal handler (if
present)
+ * @param args Arguments of line, including command.
+ * @throws java.io.IOException
+ */
+ protected void dispatch(String[] args) throws IOException {
+ String cmd = args[0].toUpperCase();
+ cmd = cmd.replaceAll(":", "_");
+ Class me = this.getClass();
+ try {
+ Class[] params = {args.getClass()};
+ Method m = me.getDeclaredMethod("handle_" + cmd, params);
+ Object[] args2 = {args};
+ m.invoke(this, args2);
+ } catch (InvocationTargetException e) {
+ Throwable thingy = e.getTargetException();
+ if (thingy instanceof IOException) {
+ throw (IOException) thingy;
+ }
+ thingy.printStackTrace();
+ }
+ catch (NoSuchMethodException e) {} // unhandled server event
+ catch (IllegalAccessException e) {
+ // eep!
+ e.printStackTrace();
+ }
+ }
+
+ Set availableAuth = new LinkedHashSet();
+ AuthProvider currentProvider = null;
+
+ protected synchronized void handle_AUTH_TYPE(String[] args) {
+ for (int i = 1; i < args.length; i++) {
+ if (authProviders.containsKey(args[i]))
+ availableAuth.add(args[i]);
+ }
+
+ tryAuth();
+
+ }
+
+ class AuthCallbackImpl implements AuthCallback {
+ public void failAuth(boolean retry) {
+ retryAuth(retry);
+ }
+ }
+
+ protected synchronized void tryAuth() {
+ if (availableAuth.size() == 0)
+ dist.onAuthenticationFailed(this);
+ String authType = (String) availableAuth.iterator().next();
+ removeNotify(currentProvider);
+ AuthProvider provider = (AuthProvider) authProviders.get(authType);
+ currentProvider = provider;
+ addNotify(provider);
+ provider.resetState();
+ provider.attemptAuthentication(new AuthCallbackImpl());
+ }
+
+ protected synchronized void retryAuth(boolean retrycurrent) {
+ if (!retrycurrent)
+ availableAuth.iterator().remove();
+ tryAuth();
+ }
+
+ /**
+ * Handler for server HAVER message
+ * @param args Arguments of message
+ * @throws java.io.IOException
+ */
+ protected void handle_HAVER(String[] args) throws IOException {
+ hostname = args[1];
+ dist.onNeedIdent(this);
+ }
+
+ /**
+ * Identify with the given name
+ * @param name Name to identify with
+ * @throws java.io.IOException
+ */
+ public void ident(String name) throws IOException {
+ this.name = name;
+ String[] l = {"IDENT", name};
+ sendLine(l);
+ }
+
+ /**
+ * Handler for server HELLO message
+ * @param args Arguments of message
+ * @throws java.io.IOException
+ */
+ protected synchronized void handle_HELLO(String[] args) throws IOException
{
+ removeNotify(currentProvider);
+ currentProvider = null;
+ name = args[1];
+ dist.onAccept(this, args[1]);
+ }
+
+ /**
+ * Handler for server PING message
+ * @param args Arguments of message
+ * @throws java.io.IOException
+ */
+ protected void handle_PING(String[] args) throws IOException {
+ args[0] = "PONG";
+ sendLine(args);
+ }
+
+ /**
+ * Request a listing of the contents of a channel, asynchronously.
+ * @param channel Channel to list
+ * @param namespace Namespace to filter results by
+ * @throws java.io.IOException
+ */
+ public void requestList(String channel, String namespace) {
+ String[] cmd = {"LIST", channel, namespace};
+ sendLine(cmd);
+ }
+
+ /**
+ * Handler for server LIST message
+ * @param args Arguments of message
+ * @throws java.io.IOException
+ */
+ protected void handle_LIST(String[] args) throws IOException {
+ String[] list = new String[args.length - 3];
+ System.arraycopy(args, 3, list, 0, args.length - 3);
+ String channel = args[1];
+ String namespace = args[2];
+
+ dist.onReceivedList(this, channel, namespace, list);
+ }
+
+ /**
+ * Event listener for syncList()
+ */
+ protected class ListMonitor extends SyncMonitor {
+ String channel;
+ String namespace;
+
+ public ListMonitor(String channel, String namespace) {
+ this.channel = channel;
+ this.namespace = namespace;
+ }
+
+ public synchronized void onReceivedList(Client source, String channel,
String namespace, String[] list) {
+ if (channel.equals(this.channel) &&
+ namespace.equals(this.namespace))
+ {
+ done(list);
+ }
+ }
+ void onFail(Client source, String[] args) {
+ // XXX
+ if (args.length >= 4 && args[1].equals("LIST") &&
args[3].equals(channel))
+ fail(new IOException("Something broke: " + args[2]));
+ }
+ }
+
+ /**
+ * Synchronously list a channel.
+ * @param channel Channel to list
+ * @param namespace Namespace to restrict results by
+ * @throws java.io.IOException If an IO exception occurs while this
function is being processed, it will be
+ * rethrown from here.
+ * @return An array containing the elements of the given namespace, in the
specified
+ * channel
+ */
+ public String[] syncList(String channel, String namespace) throws
IOException, InterruptedException {
+ ListMonitor m = new ListMonitor(channel, namespace);
+ requestList(channel, namespace);
+ return (String[])m.block();
+ }
+
+ protected void handle_IN(String[] args) throws IOException {
+ if (args.length < 4) {
+ // XXX: exception?
+ System.err.println("Short IN message from haver server");
+ return;
+ }
+ String channel = args[1];
+ String from = args[2];
+ String type = args[3];
+ String[] margs = new String[args.length - 4];
+ System.arraycopy(args, 4, margs, 0, args.length - 4);
+
+ dist.onPublicMessage(this, channel, from, type, margs);
+ }
+
+ public void sendPublicMessage(String channel, String type, String[] margs)
{
+ String[] cmd = new String[margs.length + 3];
+ cmd[0] = "IN";
+ cmd[1] = channel;
+ cmd[2] = type;
+ System.arraycopy(margs, 0, cmd, 3, margs.length);
+ sendLine(cmd);
+ }
+
+ public void sendPublicMessage(String channel, String type, String arg) {
+ String[] args = {arg};
+ sendPublicMessage(channel, type, args);
+ }
+
+ protected void handle_FROM(String[] args) throws IOException {
+ if (args.length < 3) {
+ // XXX: exception?
+ System.err.println("Short FROM message from haver server");
+ return;
+ }
+ String user = args[1];
+ String type = args[2];
+ String margs[] = new String[args.length - 3];
+ System.arraycopy(args, 3, margs, 0, margs.length);
+
+ dist.onPrivateMessage(this, user, type, margs);
+ }
+
+ public void sendPrivateMessage (String target, String type, String[]
margs) {
+ String[] args = new String[margs.length + 3];
+ args[0] = "TO";
+ args[1] = target;
+ args[2] = type;
+ System.arraycopy(margs, 0, args, 3, margs.length);
+ sendLine(args);
+ }
+
+ public void sendPrivateMessage (String target, String type, String arg) {
+ String[] args = {arg};
+ sendPrivateMessage(target, type, args);
+ }
+
+ public void handle_JOIN(String[] args) throws IOException {
+ String channel = args[1];
+ String user = args[2];
+ dist.onJoin(this, channel, user);
+ }
+
+ public void handle_PART(String[] args) throws IOException {
+ String channel = args[1];
+ String user = args[2];
+ dist.onPart(this, channel, user);
+ }
+
+ public void handle_QUIT(String[] args) throws IOException {
+ String who = args[1];
+ String type = args[2];
+ String detail = args.length >= 4 ? args[3] : "";
+ dist.onQuit(this, who, type, detail);
+ }
+
+ public void sendJoin(String channel) {
+ String[] cmd = {"JOIN", channel};
+ sendLine(cmd);
+ }
+
+ protected class JoinMonitor extends SyncMonitor {
+ String channel;
+
+ public JoinMonitor (String channel) {
+ this.channel = channel;
+ }
+
+ public void onJoin(Client from, String channel, String who) {
+ if (channel.equals(this.channel) && who.equals(name)) {
+ this.done(null);
+ }
+ }
+
+ void onFail(Client source, String[] args) {
+ // XXX
+ if (args.length >= 4 && args[1].equals("JOIN") &&
args[3].equals(channel))
+ fail(new IOException("Something broke: " + args[2]));
+ }
+ }
+
+ public void syncJoin(String channel) throws IOException,
InterruptedException {
+ JoinMonitor m = new JoinMonitor(channel);
+ sendJoin(channel);
+ m.block();
+ }
+
+ public void sendPart(String channel) {
+ String[] cmd = {"PART", channel};
+ sendLine(cmd);
+ }
+
+ protected class PartMonitor extends SyncMonitor {
+ String channel;
+
+ public PartMonitor (String channel) {
+ this.channel = channel;
+ }
+
+ public void onPart(Client from, String channel, String who) {
+ if (channel.equals(this.channel) && who.equals(name)) {
+ this.done(null);
+ }
+ }
+
+ void onFail(Client source, String[] args) {
+ // XXX
+ if (args.length >= 4 && args[1].equals("PART") &&
args[3].equals(channel))
+ fail(new IOException("Something broke: " + args[2]));
+ }
+ }
+
+ public void syncPart(String channel) throws IOException,
InterruptedException {
+ PartMonitor m = new PartMonitor(channel);
+ sendPart(channel);
+ m.block();
+ }
+
+ public synchronized void disconnect() {
+ killConnection();
+ }
+
+ public void handle_FAIL(String[] args) throws IOException {
+ // XXX
+ dist.onFail(this, args);
+ }
+
+}
Added:
trunk/clients/Javer2/src/org/haverdev/client/SwingBasicAuthentication.java
===================================================================
--- trunk/clients/Javer2/src/org/haverdev/client/SwingBasicAuthentication.java
2005-06-10 20:43:42 UTC (rev 762)
+++ trunk/clients/Javer2/src/org/haverdev/client/SwingBasicAuthentication.java
2005-06-11 18:17:46 UTC (rev 763)
@@ -0,0 +1,27 @@
+/*
+ * SwingBasicAuthentication.java
+ *
+ * Created on June 10, 2005, 10:10 PM
+ *
+ * To change this template, choose Tools | Options and locate the template
under
+ * the Source Creation and Management node. Right-click the template and choose
+ * Open. You can then make changes to the template in the Source Editor.
+ */
+
+package org.haverdev.client;
+
+/**
+ *
+ * @author Bryan
+ */
+public class SwingBasicAuthentication extends BasicAuthenticationProvider {
+
+ /** Creates a new instance of SwingBasicAuthentication */
+ public SwingBasicAuthentication() {
+ }
+
+ protected String getPassword() {
+ return SwingPasswordDialog.getPassword();
+ }
+
+}
Property changes on:
trunk/clients/Javer2/src/org/haverdev/client/SwingBasicAuthentication.java
___________________________________________________________________
Name: svn:eol-style
+ native
Added: trunk/clients/Javer2/src/org/haverdev/client/SwingPasswordDialog.form
===================================================================
--- trunk/clients/Javer2/src/org/haverdev/client/SwingPasswordDialog.form
2005-06-10 20:43:42 UTC (rev 762)
+++ trunk/clients/Javer2/src/org/haverdev/client/SwingPasswordDialog.form
2005-06-11 18:17:46 UTC (rev 763)
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<Form version="1.0" type="org.netbeans.modules.form.forminfo.JDialogFormInfo">
+ <Properties>
+ <Property name="defaultCloseOperation" type="int" value="2"/>
+ </Properties>
+ <SyntheticProperties>
+ <SyntheticProperty name="formSizePolicy" type="int" value="1"/>
+ </SyntheticProperties>
+ <AuxValues>
+ <AuxValue name="FormSettings_generateMnemonicsCode"
type="java.lang.Boolean" value="false"/>
+ <AuxValue name="FormSettings_listenerGenerationStyle"
type="java.lang.Integer" value="0"/>
+ <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean"
value="false"/>
+ <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer"
value="2"/>
+ </AuxValues>
+
+ <Layout
class="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout"/>
+ <SubComponents>
+ <Component class="javax.swing.JLabel" name="jLabel1">
+ <Properties>
+ <Property name="text" type="java.lang.String" value="Please enter your
password:"/>
+ </Properties>
+ <AuxValues>
+ <AuxValue name="JavaCodeGenerator_VariableLocal"
type="java.lang.Boolean" value="true"/>
+ <AuxValue name="JavaCodeGenerator_VariableModifier"
type="java.lang.Integer" value="0"/>
+ </AuxValues>
+ <Constraints>
+ <Constraint
layoutClass="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout"
value="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout$BorderConstraintsDescription">
+ <BorderConstraints direction="North"/>
+ </Constraint>
+ </Constraints>
+ </Component>
+ <Container class="javax.swing.JPanel" name="jPanel1">
+ <Constraints>
+ <Constraint
layoutClass="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout"
value="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout$BorderConstraintsDescription">
+ <BorderConstraints direction="South"/>
+ </Constraint>
+ </Constraints>
+
+ <Layout
class="org.netbeans.modules.form.compat2.layouts.DesignFlowLayout">
+ <Property name="alignment" type="int" value="2"/>
+ </Layout>
+ <SubComponents>
+ <Component class="javax.swing.JButton" name="jButton1">
+ <Properties>
+ <Property name="text" type="java.lang.String" value="OK"/>
+ </Properties>
+ <Events>
+ <EventHandler event="actionPerformed"
listener="java.awt.event.ActionListener"
parameters="java.awt.event.ActionEvent" handler="okButton"/>
+ </Events>
+ </Component>
+ <Component class="javax.swing.JButton" name="jButton3">
+ <Properties>
+ <Property name="text" type="java.lang.String" value="Cancel"/>
+ <Property name="defaultCapable" type="boolean" value="false"/>
+ </Properties>
+ <Events>
+ <EventHandler event="actionPerformed"
listener="java.awt.event.ActionListener"
parameters="java.awt.event.ActionEvent" handler="cancelButton"/>
+ </Events>
+ </Component>
+ </SubComponents>
+ </Container>
+ <Component class="javax.swing.JPasswordField" name="passwordField">
+ <Constraints>
+ <Constraint
layoutClass="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout"
value="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout$BorderConstraintsDescription">
+ <BorderConstraints direction="Center"/>
+ </Constraint>
+ </Constraints>
+ </Component>
+ </SubComponents>
+</Form>
Added: trunk/clients/Javer2/src/org/haverdev/client/SwingPasswordDialog.java
===================================================================
--- trunk/clients/Javer2/src/org/haverdev/client/SwingPasswordDialog.java
2005-06-10 20:43:42 UTC (rev 762)
+++ trunk/clients/Javer2/src/org/haverdev/client/SwingPasswordDialog.java
2005-06-11 18:17:46 UTC (rev 763)
@@ -0,0 +1,132 @@
+/*
+ * SwingPasswordDialog.java
+ *
+ * Created on June 10, 2005, 10:11 PM
+ */
+
+package org.haverdev.client;
+import javax.swing.*;
+
+/**
+ *
+ * @author Bryan
+ */
+public class SwingPasswordDialog extends javax.swing.JDialog {
+
+ StringContainer c = null;
+
+ /** Creates new form SwingPasswordDialog */
+ public SwingPasswordDialog(StringContainer c, java.awt.Frame parent,
boolean modal) {
+ super(parent, modal);
+ this.c = c;
+ initComponents();
+ }
+
+ static class StringContainer {
+ String str = null;
+ }
+
+ static class ObjectContainer {
+ Object o = null;
+ }
+
+ public static String getPassword() {
+ final StringContainer c = new StringContainer();
+ final ObjectContainer dlg_c = new ObjectContainer();
+ synchronized (c) {
+ javax.swing.SwingUtilities.invokeLater(new Runnable() {
+ public void run() {
+ SwingPasswordDialog dlg = new SwingPasswordDialog(c, null,
true);
+ dlg.setVisible(true);
+ dlg_c.o = dlg;
+ }
+ });
+ try {
+ c.wait();
+ }
+ catch (InterruptedException e) {
+ // Re-interrupt elsewhere maybe
+ javax.swing.SwingUtilities.invokeLater(new Runnable() {
+ public void run() {
+ ((JDialog)dlg_c.o).setVisible(false);
+ }
+ });
+ Thread.currentThread().interrupt();
+ return null;
+ }
+ }
+
+ return c.str;
+ }
+
+ /** This method is called from within the constructor to
+ * initialize the form.
+ * WARNING: Do NOT modify this code. The content of this method is
+ * always regenerated by the Form Editor.
+ */
+ // <editor-fold defaultstate="collapsed" desc=" Generated Code
">//GEN-BEGIN:initComponents
+ private void initComponents() {
+ javax.swing.JLabel jLabel1;
+
+ jLabel1 = new javax.swing.JLabel();
+ jPanel1 = new javax.swing.JPanel();
+ jButton1 = new javax.swing.JButton();
+ jButton3 = new javax.swing.JButton();
+ passwordField = new javax.swing.JPasswordField();
+
+ setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
+ jLabel1.setText("Please enter your password:");
+ getContentPane().add(jLabel1, java.awt.BorderLayout.NORTH);
+
+ jPanel1.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.RIGHT));
+
+ jButton1.setText("OK");
+ jButton1.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ okButton(evt);
+ }
+ });
+
+ jPanel1.add(jButton1);
+
+ jButton3.setText("Cancel");
+ jButton3.setDefaultCapable(false);
+ jButton3.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ cancelButton(evt);
+ }
+ });
+
+ jPanel1.add(jButton3);
+
+ getContentPane().add(jPanel1, java.awt.BorderLayout.SOUTH);
+
+ getContentPane().add(passwordField, java.awt.BorderLayout.CENTER);
+
+ pack();
+ }
+ // </editor-fold>//GEN-END:initComponents
+
+ private void cancelButton(java.awt.event.ActionEvent evt)
{//GEN-FIRST:event_cancelButton
+ synchronized (c) {
+ c.notifyAll();
+ }
+ setVisible(false);
+ }//GEN-LAST:event_cancelButton
+
+ private void okButton(java.awt.event.ActionEvent evt)
{//GEN-FIRST:event_okButton
+ synchronized (c) {
+ c.str = new String(passwordField.getPassword());
+ c.notifyAll();
+ }
+ setVisible(false);
+ }//GEN-LAST:event_okButton
+
+ // Variables declaration - do not modify//GEN-BEGIN:variables
+ private javax.swing.JButton jButton1;
+ private javax.swing.JButton jButton3;
+ private javax.swing.JPanel jPanel1;
+ private javax.swing.JPasswordField passwordField;
+ // End of variables declaration//GEN-END:variables
+
+}
Property changes on:
trunk/clients/Javer2/src/org/haverdev/client/SwingPasswordDialog.java
___________________________________________________________________
Name: svn:eol-style
+ native
Copied: trunk/clients/Javer2/src/org/haverdev/common/Base64.java (from rev 752,
trunk/clients/Javer2/src/org/haverdev/haver/Base64.java)
===================================================================
--- trunk/clients/Javer2/src/org/haverdev/haver/Base64.java 2005-06-10
16:35:51 UTC (rev 752)
+++ trunk/clients/Javer2/src/org/haverdev/common/Base64.java 2005-06-11
18:17:46 UTC (rev 763)
@@ -0,0 +1,1451 @@
+package org.haverdev.common;
+
+/**
+ * Encodes and decodes to and from Base64 notation.
+ *
+ * <p>
+ * Change Log:
+ * </p>
+ * <ul>
+ * <li>v2.1 - Cleaned up javadoc comments and unused variables and methods.
Added
+ * some convenience methods for reading and writing to and from files.</li>
+ * <li>v2.0.2 - Now specifies UTF-8 encoding in places where the code fails
on systems
+ * with other encodings (like EBCDIC).</li>
+ * <li>v2.0.1 - Fixed an error when decoding a single byte, that is, when the
+ * encoded data was a single byte.</li>
+ * <li>v2.0 - I got rid of methods that used booleans to set options.
+ * Now everything is more consolidated and cleaner. The code now detects
+ * when data that's being decoded is gzip-compressed and will decompress it
+ * automatically. Generally things are cleaner. You'll probably have to
+ * change some method calls that you were making to support the new
+ * options format (<tt>int</tt>s that you "OR" together).</li>
+ * <li>v1.5.1 - Fixed bug when decompressing and decoding to a
+ * byte[] using <tt>decode( String s, boolean gzipCompressed )</tt>.
+ * Added the ability to "suspend" encoding in the Output Stream so
+ * you can turn on and off the encoding if you need to embed base64
+ * data in an otherwise "normal" stream (like an XML file).</li>
+ * <li>v1.5 - Output stream pases on flush() command but doesn't do anything
itself.
+ * This helps when using GZIP streams.
+ * Added the ability to GZip-compress objects before encoding them.</li>
+ * <li>v1.4 - Added helper methods to read/write files.</li>
+ * <li>v1.3.6 - Fixed OutputStream.flush() so that 'position' is reset.</li>
+ * <li>v1.3.5 - Added flag to turn on and off line breaks. Fixed bug in input
stream
+ * where last buffer being read, if not completely full, was not
returned.</li>
+ * <li>v1.3.4 - Fixed when "improperly padded stream" error was thrown at the
wrong time.</li>
+ * <li>v1.3.3 - Fixed I/O streams which were totally messed up.</li>
+ * </ul>
+ *
+ * <p>
+ * I am placing this code in the Public Domain. Do with it as you will.
+ * This software comes with no guarantees or warranties but with
+ * plenty of well-wishing instead!
+ * Please visit <a
href="http://iharder.net/base64">http://iharder.net/base64</a>
+ * periodically to check for updates or to contribute improvements.
+ * </p>
+ *
+ * @author Robert Harder
+ * @author [EMAIL PROTECTED]
+ * @version 2.1
+ */
+public class Base64
+{
+
+/* ******** P U B L I C F I E L D S ******** */
+
+
+ /** No options specified. Value is zero. */
+ public final static int NO_OPTIONS = 0;
+
+ /** Specify encoding. */
+ public final static int ENCODE = 1;
+
+
+ /** Specify decoding. */
+ public final static int DECODE = 0;
+
+
+ /** Specify that data should be gzip-compressed. */
+ public final static int GZIP = 2;
+
+
+ /** Don't break lines when encoding (violates strict Base64 specification)
*/
+ public final static int DONT_BREAK_LINES = 8;
+
+
+/* ******** P R I V A T E F I E L D S ******** */
+
+
+ /** Maximum line length (76) of Base64 output. */
+ private final static int MAX_LINE_LENGTH = 76;
+
+
+ /** The equals sign (=) as a byte. */
+ private final static byte EQUALS_SIGN = (byte)'=';
+
+
+ /** The new line character (\n) as a byte. */
+ private final static byte NEW_LINE = (byte)'\n';
+
+
+ /** Preferred encoding. */
+ private final static String PREFERRED_ENCODING = "UTF-8";
+
+
+ /** The 64 valid Base64 values. */
+ private final static byte[] ALPHABET;
+ private final static byte[] _NATIVE_ALPHABET = /* May be something funny
like EBCDIC */
+ {
+ (byte)'A', (byte)'B', (byte)'C', (byte)'D', (byte)'E', (byte)'F',
(byte)'G',
+ (byte)'H', (byte)'I', (byte)'J', (byte)'K', (byte)'L', (byte)'M',
(byte)'N',
+ (byte)'O', (byte)'P', (byte)'Q', (byte)'R', (byte)'S', (byte)'T',
(byte)'U',
+ (byte)'V', (byte)'W', (byte)'X', (byte)'Y', (byte)'Z',
+ (byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f',
(byte)'g',
+ (byte)'h', (byte)'i', (byte)'j', (byte)'k', (byte)'l', (byte)'m',
(byte)'n',
+ (byte)'o', (byte)'p', (byte)'q', (byte)'r', (byte)'s', (byte)'t',
(byte)'u',
+ (byte)'v', (byte)'w', (byte)'x', (byte)'y', (byte)'z',
+ (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5',
+ (byte)'6', (byte)'7', (byte)'8', (byte)'9', (byte)'+', (byte)'/'
+ };
+
+ /** Determine which ALPHABET to use. */
+ static
+ {
+ byte[] __bytes;
+ try
+ {
+ __bytes =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".getBytes(
PREFERRED_ENCODING );
+ } // end try
+ catch (java.io.UnsupportedEncodingException use)
+ {
+ __bytes = _NATIVE_ALPHABET; // Fall back to native encoding
+ } // end catch
+ ALPHABET = __bytes;
+ } // end static
+
+
+ /**
+ * Translates a Base64 value to either its 6-bit reconstruction value
+ * or a negative number indicating some other meaning.
+ **/
+ private final static byte[] DECODABET =
+ {
+ -9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 0 - 8
+ -5,-5, // Whitespace: Tab and
Linefeed
+ -9,-9, // Decimal 11 - 12
+ -5, // Whitespace: Carriage
Return
+ -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 14 - 26
+ -9,-9,-9,-9,-9, // Decimal 27 - 31
+ -5, // Whitespace: Space
+ -9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 33 - 42
+ 62, // Plus sign at decimal 43
+ -9,-9,-9, // Decimal 44 - 46
+ 63, // Slash at decimal 47
+ 52,53,54,55,56,57,58,59,60,61, // Numbers zero through
nine
+ -9,-9,-9, // Decimal 58 - 60
+ -1, // Equals sign at decimal
61
+ -9,-9,-9, // Decimal 62 - 64
+ 0,1,2,3,4,5,6,7,8,9,10,11,12,13, // Letters 'A' through 'N'
+ 14,15,16,17,18,19,20,21,22,23,24,25, // Letters 'O' through 'Z'
+ -9,-9,-9,-9,-9,-9, // Decimal 91 - 96
+ 26,27,28,29,30,31,32,33,34,35,36,37,38, // Letters 'a' through 'm'
+ 39,40,41,42,43,44,45,46,47,48,49,50,51, // Letters 'n' through 'z'
+ -9,-9,-9,-9 // Decimal 123 - 126
+ /*,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 127 - 139
+ -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 140 - 152
+ -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 153 - 165
+ -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 166 - 178
+ -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 179 - 191
+ -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 192 - 204
+ -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 205 - 217
+ -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 218 - 230
+ -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 231 - 243
+ -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9 // Decimal 244 - 255 */
+ };
+
+ // I think I end up not using the BAD_ENCODING indicator.
+ //private final static byte BAD_ENCODING = -9; // Indicates error in
encoding
+ private final static byte WHITE_SPACE_ENC = -5; // Indicates white space
in encoding
+ private final static byte EQUALS_SIGN_ENC = -1; // Indicates equals sign
in encoding
+
+
+ /** Defeats instantiation. */
+ private Base64(){}
+
+
+
+/* ******** E N C O D I N G M E T H O D S ******** */
+
+
+ /**
+ * Encodes up to the first three bytes of array <var>threeBytes</var>
+ * and returns a four-byte array in Base64 notation.
+ * The actual number of significant bytes in your array is
+ * given by <var>numSigBytes</var>.
+ * The array <var>threeBytes</var> needs only be as big as
+ * <var>numSigBytes</var>.
+ * Code can reuse a byte array by passing a four-byte array as
<var>b4</var>.
+ *
+ * @param b4 A reusable byte array to reduce array instantiation
+ * @param threeBytes the array to convert
+ * @param numSigBytes the number of significant bytes in your array
+ * @return four byte array in Base64 notation.
+ * @since 1.5.1
+ */
+ private static byte[] encode3to4( byte[] b4, byte[] threeBytes, int
numSigBytes )
+ {
+ encode3to4( threeBytes, 0, numSigBytes, b4, 0 );
+ return b4;
+ } // end encode3to4
+
+
+ /**
+ * Encodes up to three bytes of the array <var>source</var>
+ * and writes the resulting four Base64 bytes to <var>destination</var>.
+ * The source and destination arrays can be manipulated
+ * anywhere along their length by specifying
+ * <var>srcOffset</var> and <var>destOffset</var>.
+ * This method does not check to make sure your arrays
+ * are large enough to accomodate <var>srcOffset</var> + 3 for
+ * the <var>source</var> array or <var>destOffset</var> + 4 for
+ * the <var>destination</var> array.
+ * The actual number of significant bytes in your array is
+ * given by <var>numSigBytes</var>.
+ *
+ * @param source the array to convert
+ * @param srcOffset the index where conversion begins
+ * @param numSigBytes the number of significant bytes in your array
+ * @param destination the array to hold the conversion
+ * @param destOffset the index where output will be put
+ * @return the <var>destination</var> array
+ * @since 1.3
+ */
+ private static byte[] encode3to4(
+ byte[] source, int srcOffset, int numSigBytes,
+ byte[] destination, int destOffset )
+ {
+ // 1 2 3
+ // 01234567890123456789012345678901 Bit position
+ // --------000000001111111122222222 Array position from threeBytes
+ // --------| || || || | Six bit groups to index ALPHABET
+ // >>18 >>12 >> 6 >> 0 Right shift necessary
+ // 0x3f 0x3f 0x3f Additional AND
+
+ // Create buffer with zero-padding if there are only one or two
+ // significant bytes passed in the array.
+ // We have to shift left 24 in order to flush out the 1's that appear
+ // when Java treats a value as negative that is cast from a byte to an
int.
+ int inBuff = ( numSigBytes > 0 ? ((source[ srcOffset ] << 24)
>>> 8) : 0 )
+ | ( numSigBytes > 1 ? ((source[ srcOffset + 1 ] << 24)
>>> 16) : 0 )
+ | ( numSigBytes > 2 ? ((source[ srcOffset + 2 ] << 24)
>>> 24) : 0 );
+
+ switch( numSigBytes )
+ {
+ case 3:
+ destination[ destOffset ] = ALPHABET[ (inBuff >>> 18)
];
+ destination[ destOffset + 1 ] = ALPHABET[ (inBuff >>> 12) &
0x3f ];
+ destination[ destOffset + 2 ] = ALPHABET[ (inBuff >>> 6) &
0x3f ];
+ destination[ destOffset + 3 ] = ALPHABET[ (inBuff ) &
0x3f ];
+ return destination;
+
+ case 2:
+ destination[ destOffset ] = ALPHABET[ (inBuff >>> 18)
];
+ destination[ destOffset + 1 ] = ALPHABET[ (inBuff >>> 12) &
0x3f ];
+ destination[ destOffset + 2 ] = ALPHABET[ (inBuff >>> 6) &
0x3f ];
+ destination[ destOffset + 3 ] = EQUALS_SIGN;
+ return destination;
+
+ case 1:
+ destination[ destOffset ] = ALPHABET[ (inBuff >>> 18)
];
+ destination[ destOffset + 1 ] = ALPHABET[ (inBuff >>> 12) &
0x3f ];
+ destination[ destOffset + 2 ] = EQUALS_SIGN;
+ destination[ destOffset + 3 ] = EQUALS_SIGN;
+ return destination;
+
+ default:
+ return destination;
+ } // end switch
+ } // end encode3to4
+
+
+
+ /**
+ * Serializes an object and returns the Base64-encoded
+ * version of that serialized object. If the object
+ * cannot be serialized or there is another error,
+ * the method will return <tt>null</tt>.
+ * The object is not GZip-compressed before being encoded.
+ *
+ * @param serializableObject The object to encode
+ * @return The Base64-encoded object
+ * @since 1.4
+ */
+ public static String encodeObject( java.io.Serializable serializableObject
)
+ {
+ return encodeObject( serializableObject, NO_OPTIONS );
+ } // end encodeObject
+
+
+
+ /**
+ * Serializes an object and returns the Base64-encoded
+ * version of that serialized object. If the object
+ * cannot be serialized or there is another error,
+ * the method will return <tt>null</tt>.
+ * <p>
+ * Valid options:<pre>
+ * GZIP: gzip-compresses object before encoding it.
+ * DONT_BREAK_LINES: don't break lines at 76 characters
+ * <i>Note: Technically, this makes your encoding non-compliant.</i>
+ * </pre>
+ * <p>
+ * Example: <code>encodeObject( myObj, Base64.GZIP )</code> or
+ * <p>
+ * Example: <code>encodeObject( myObj, Base64.GZIP |
Base64.DONT_BREAK_LINES )</code>
+ *
+ * @param serializableObject The object to encode
+ * @param options Specified options
+ * @return The Base64-encoded object
+ * @see Base64#GZIP
+ * @see Base64#DONT_BREAK_LINES
+ * @since 2.0
+ */
+ public static String encodeObject( java.io.Serializable
serializableObject, int options )
+ {
+ // Streams
+ java.io.ByteArrayOutputStream baos = null;
+ java.io.OutputStream b64os = null;
+ java.io.ObjectOutputStream oos = null;
+ java.util.zip.GZIPOutputStream gzos = null;
+
+ // Isolate options
+ int gzip = (options & GZIP);
+ int dontBreakLines = (options & DONT_BREAK_LINES);
+
+ try
+ {
+ // ObjectOutputStream -> (GZIP) -> Base64 -> ByteArrayOutputStream
+ baos = new java.io.ByteArrayOutputStream();
+ b64os = new Base64.OutputStream( baos, ENCODE | dontBreakLines );
+
+ // GZip?
+ if( gzip == GZIP )
+ {
+ gzos = new java.util.zip.GZIPOutputStream( b64os );
+ oos = new java.io.ObjectOutputStream( gzos );
+ } // end if: gzip
+ else
+ oos = new java.io.ObjectOutputStream( b64os );
+
+ oos.writeObject( serializableObject );
+ } // end try
+ catch( java.io.IOException e )
+ {
+ e.printStackTrace();
+ return null;
+ } // end catch
+ finally
+ {
+ try{ oos.close(); } catch( Exception e ){}
+ try{ gzos.close(); } catch( Exception e ){}
+ try{ b64os.close(); } catch( Exception e ){}
+ try{ baos.close(); } catch( Exception e ){}
+ } // end finally
+
+ // Return value according to relevant encoding.
+ try
+ {
+ return new String( baos.toByteArray(), PREFERRED_ENCODING );
+ } // end try
+ catch (java.io.UnsupportedEncodingException uue)
+ {
+ return new String( baos.toByteArray() );
+ } // end catch
+
+ } // end encode
+
+
+
+ /**
+ * Encodes a byte array into Base64 notation.
+ * Does not GZip-compress data.
+ *
+ * @param source The data to convert
+ * @since 1.4
+ */
+ public static String encodeBytes( byte[] source )
+ {
+ return encodeBytes( source, 0, source.length, NO_OPTIONS );
+ } // end encodeBytes
+
+
+
+ /**
+ * Encodes a byte array into Base64 notation.
+ * <p>
+ * Valid options:<pre>
+ * GZIP: gzip-compresses object before encoding it.
+ * DONT_BREAK_LINES: don't break lines at 76 characters
+ * <i>Note: Technically, this makes your encoding non-compliant.</i>
+ * </pre>
+ * <p>
+ * Example: <code>encodeBytes( myData, Base64.GZIP )</code> or
+ * <p>
+ * Example: <code>encodeBytes( myData, Base64.GZIP |
Base64.DONT_BREAK_LINES )</code>
+ *
+ *
+ * @param source The data to convert
+ * @param options Specified options
+ * @see Base64#GZIP
+ * @see Base64#DONT_BREAK_LINES
+ * @since 2.0
+ */
+ public static String encodeBytes( byte[] source, int options )
+ {
+ return encodeBytes( source, 0, source.length, options );
+ } // end encodeBytes
+
+
+ /**
+ * Encodes a byte array into Base64 notation.
+ * Does not GZip-compress data.
+ *
+ * @param source The data to convert
+ * @param off Offset in array where conversion should begin
+ * @param len Length of data to convert
+ * @since 1.4
+ */
+ public static String encodeBytes( byte[] source, int off, int len )
+ {
+ return encodeBytes( source, off, len, NO_OPTIONS );
+ } // end encodeBytes
+
+
+
+ /**
+ * Encodes a byte array into Base64 notation.
+ * <p>
+ * Valid options:<pre>
+ * GZIP: gzip-compresses object before encoding it.
+ * DONT_BREAK_LINES: don't break lines at 76 characters
+ * <i>Note: Technically, this makes your encoding non-compliant.</i>
+ * </pre>
+ * <p>
+ * Example: <code>encodeBytes( myData, Base64.GZIP )</code> or
+ * <p>
+ * Example: <code>encodeBytes( myData, Base64.GZIP |
Base64.DONT_BREAK_LINES )</code>
+ *
+ *
+ * @param source The data to convert
+ * @param off Offset in array where conversion should begin
+ * @param len Length of data to convert
+ * @param options Specified options
+ * @see Base64#GZIP
+ * @see Base64#DONT_BREAK_LINES
+ * @since 2.0
+ */
+ public static String encodeBytes( byte[] source, int off, int len, int
options )
+ {
+ // Isolate options
+ int dontBreakLines = ( options & DONT_BREAK_LINES );
+ int gzip = ( options & GZIP );
+
+ // Compress?
+ if( gzip == GZIP )
+ {
+ java.io.ByteArrayOutputStream baos = null;
+ java.util.zip.GZIPOutputStream gzos = null;
+ Base64.OutputStream b64os = null;
+
+
+ try
+ {
+ // GZip -> Base64 -> ByteArray
+ baos = new java.io.ByteArrayOutputStream();
+ b64os = new Base64.OutputStream( baos, ENCODE | dontBreakLines
);
+ gzos = new java.util.zip.GZIPOutputStream( b64os );
+
+ gzos.write( source, off, len );
+ gzos.close();
+ } // end try
+ catch( java.io.IOException e )
+ {
+ e.printStackTrace();
+ return null;
+ } // end catch
+ finally
+ {
+ try{ gzos.close(); } catch( Exception e ){}
+ try{ b64os.close(); } catch( Exception e ){}
+ try{ baos.close(); } catch( Exception e ){}
+ } // end finally
+
+ // Return value according to relevant encoding.
+ try
+ {
+ return new String( baos.toByteArray(), PREFERRED_ENCODING );
+ } // end try
+ catch (java.io.UnsupportedEncodingException uue)
+ {
+ return new String( baos.toByteArray() );
+ } // end catch
+ } // end if: compress
+
+ // Else, don't compress. Better not to use streams at all then.
+ else
+ {
+ // Convert option to boolean in way that code likes it.
+ boolean breakLines = dontBreakLines == 0;
+
+ int len43 = len * 4 / 3;
+ byte[] outBuff = new byte[ ( len43 ) //
Main 4:3
+ + ( (len % 3) > 0 ? 4 : 0 ) //
Account for padding
+ + (breakLines ? ( len43 /
MAX_LINE_LENGTH ) : 0) ]; // New lines
+ int d = 0;
+ int e = 0;
+ int len2 = len - 2;
+ int lineLength = 0;
+ for( ; d < len2; d+=3, e+=4 )
+ {
+ encode3to4( source, d+off, 3, outBuff, e );
+
+ lineLength += 4;
+ if( breakLines && lineLength == MAX_LINE_LENGTH )
+ {
+ outBuff[e+4] = NEW_LINE;
+ e++;
+ lineLength = 0;
+ } // end if: end of line
+ } // en dfor: each piece of array
+
+ if( d < len )
+ {
+ encode3to4( source, d+off, len - d, outBuff, e );
+ e += 4;
+ } // end if: some padding needed
+
+
+ // Return value according to relevant encoding.
+ try
+ {
+ return new String( outBuff, 0, e, PREFERRED_ENCODING );
+ } // end try
+ catch (java.io.UnsupportedEncodingException uue)
+ {
+ return new String( outBuff, 0, e );
+ } // end catch
+
+ } // end else: don't compress
+
+ } // end encodeBytes
+
+
+
+
+
+/* ******** D E C O D I N G M E T H O D S ******** */
+
+
+ /**
+ * Decodes four bytes from array <var>source</var>
+ * and writes the resulting bytes (up to three of them)
+ * to <var>destination</var>.
+ * The source and destination arrays can be manipulated
+ * anywhere along their length by specifying
+ * <var>srcOffset</var> and <var>destOffset</var>.
+ * This method does not check to make sure your arrays
+ * are large enough to accomodate <var>srcOffset</var> + 4 for
+ * the <var>source</var> array or <var>destOffset</var> + 3 for
+ * the <var>destination</var> array.
+ * This method returns the actual number of bytes that
+ * were converted from the Base64 encoding.
+ *
+ *
+ * @param source the array to convert
+ * @param srcOffset the index where conversion begins
+ * @param destination the array to hold the conversion
+ * @param destOffset the index where output will be put
+ * @return the number of decoded bytes converted
+ * @since 1.3
+ */
+ private static int decode4to3( byte[] source, int srcOffset, byte[]
destination, int destOffset )
+ {
+ // Example: Dk==
+ if( source[ srcOffset + 2] == EQUALS_SIGN )
+ {
+ // Two ways to do the same thing. Don't know which way I like best.
+ //int outBuff = ( ( DECODABET[ source[ srcOffset ] ] << 24 )
>>> 6 )
+ // | ( ( DECODABET[ source[ srcOffset + 1] ] << 24 )
>>> 12 );
+ int outBuff = ( ( DECODABET[ source[ srcOffset ] ] & 0xFF )
<< 18 )
+ | ( ( DECODABET[ source[ srcOffset + 1] ] & 0xFF )
<< 12 );
+
+ destination[ destOffset ] = (byte)( outBuff >>> 16 );
+ return 1;
+ }
+
+ // Example: DkL=
+ else if( source[ srcOffset + 3 ] == EQUALS_SIGN )
+ {
+ // Two ways to do the same thing. Don't know which way I like best.
+ //int outBuff = ( ( DECODABET[ source[ srcOffset ] ] << 24 )
>>> 6 )
+ // | ( ( DECODABET[ source[ srcOffset + 1 ] ] << 24 )
>>> 12 )
+ // | ( ( DECODABET[ source[ srcOffset + 2 ] ] << 24 )
>>> 18 );
+ int outBuff = ( ( DECODABET[ source[ srcOffset ] ] & 0xFF )
<< 18 )
+ | ( ( DECODABET[ source[ srcOffset + 1 ] ] & 0xFF )
<< 12 )
+ | ( ( DECODABET[ source[ srcOffset + 2 ] ] & 0xFF )
<< 6 );
+
+ destination[ destOffset ] = (byte)( outBuff >>> 16 );
+ destination[ destOffset + 1 ] = (byte)( outBuff >>> 8 );
+ return 2;
+ }
+
+ // Example: DkLE
+ else
+ {
+ try{
+ // Two ways to do the same thing. Don't know which way I like best.
+ //int outBuff = ( ( DECODABET[ source[ srcOffset ] ] << 24 )
>>> 6 )
+ // | ( ( DECODABET[ source[ srcOffset + 1 ] ] << 24 )
>>> 12 )
+ // | ( ( DECODABET[ source[ srcOffset + 2 ] ] << 24 )
>>> 18 )
+ // | ( ( DECODABET[ source[ srcOffset + 3 ] ] << 24 )
>>> 24 );
+ int outBuff = ( ( DECODABET[ source[ srcOffset ] ] & 0xFF )
<< 18 )
+ | ( ( DECODABET[ source[ srcOffset + 1 ] ] & 0xFF )
<< 12 )
+ | ( ( DECODABET[ source[ srcOffset + 2 ] ] & 0xFF )
<< 6)
+ | ( ( DECODABET[ source[ srcOffset + 3 ] ] & 0xFF )
);
+
+
+ destination[ destOffset ] = (byte)( outBuff >> 16 );
+ destination[ destOffset + 1 ] = (byte)( outBuff >> 8 );
+ destination[ destOffset + 2 ] = (byte)( outBuff );
+
+ return 3;
+ }catch( Exception e){
+ System.out.println(""+source[srcOffset]+ ": " + ( DECODABET[
source[ srcOffset ] ] ) );
+ System.out.println(""+source[srcOffset+1]+ ": " + (
DECODABET[ source[ srcOffset + 1 ] ] ) );
+ System.out.println(""+source[srcOffset+2]+ ": " + (
DECODABET[ source[ srcOffset + 2 ] ] ) );
+ System.out.println(""+source[srcOffset+3]+ ": " + (
DECODABET[ source[ srcOffset + 3 ] ] ) );
+ return -1;
+ } //e nd catch
+ }
+ } // end decodeToBytes
+
+
+
+
+ /**
+ * Very low-level access to decoding ASCII characters in
+ * the form of a byte array. Does not support automatically
+ * gunzipping or any other "fancy" features.
+ *
+ * @param source The Base64 encoded data
+ * @param off The offset of where to begin decoding
+ * @param len The length of characters to decode
+ * @return decoded data
+ * @since 1.3
+ */
+ public static byte[] decode( byte[] source, int off, int len )
+ {
+ int len34 = len * 3 / 4;
+ byte[] outBuff = new byte[ len34 ]; // Upper limit on size of output
+ int outBuffPosn = 0;
+
+ byte[] b4 = new byte[4];
+ int b4Posn = 0;
+ int i = 0;
+ byte sbiCrop = 0;
+ byte sbiDecode = 0;
+ for( i = off; i < off+len; i++ )
+ {
+ sbiCrop = (byte)(source[i] & 0x7f); // Only the low seven bits
+ sbiDecode = DECODABET[ sbiCrop ];
+
+ if( sbiDecode >= WHITE_SPACE_ENC ) // White space, Equals sign or
better
+ {
+ if( sbiDecode >= EQUALS_SIGN_ENC )
+ {
+ b4[ b4Posn++ ] = sbiCrop;
+ if( b4Posn > 3 )
+ {
+ outBuffPosn += decode4to3( b4, 0, outBuff, outBuffPosn
);
+ b4Posn = 0;
+
+ // If that was the equals sign, break out of 'for' loop
+ if( sbiCrop == EQUALS_SIGN )
+ break;
+ } // end if: quartet built
+
+ } // end if: equals sign or better
+
+ } // end if: white space, equals sign or better
+ else
+ {
+ System.err.println( "Bad Base64 input character at " + i + ":
" + source[i] + "(decimal)" );
+ return null;
+ } // end else:
+ } // each input character
+
+ byte[] out = new byte[ outBuffPosn ];
+ System.arraycopy( outBuff, 0, out, 0, outBuffPosn );
+ return out;
+ } // end decode
+
+
+
+
+ /**
+ * Decodes data from Base64 notation, automatically
+ * detecting gzip-compressed data and decompressing it.
+ *
+ * @param s the string to decode
+ * @return the decoded data
+ * @since 1.4
+ */
+ public static byte[] decode( String s )
+ {
+ byte[] bytes;
+ try
+ {
+ bytes = s.getBytes( PREFERRED_ENCODING );
+ } // end try
+ catch( java.io.UnsupportedEncodingException uee )
+ {
+ bytes = s.getBytes();
+ } // end catch
+ //</change>
+
+ // Decode
+ bytes = decode( bytes, 0, bytes.length );
+
+
+ // Check to see if it's gzip-compressed
+ // GZIP Magic Two-Byte Number: 0x8b1f (35615)
+ if( bytes != null && bytes.length >= 4 )
+ {
+
+ int head = ((int)bytes[0] & 0xff) | ((bytes[1] << 8) & 0xff00);
+ if( java.util.zip.GZIPInputStream.GZIP_MAGIC == head )
+ {
+ java.io.ByteArrayInputStream bais = null;
+ java.util.zip.GZIPInputStream gzis = null;
+ java.io.ByteArrayOutputStream baos = null;
+ byte[] buffer = new byte[2048];
+ int length = 0;
+
+ try
+ {
+ baos = new java.io.ByteArrayOutputStream();
+ bais = new java.io.ByteArrayInputStream( bytes );
+ gzis = new java.util.zip.GZIPInputStream( bais );
+
+ while( ( length = gzis.read( buffer ) ) >= 0 )
+ {
+ baos.write(buffer,0,length);
+ } // end while: reading input
+
+ // No error? Get new bytes.
+ bytes = baos.toByteArray();
+
+ } // end try
+ catch( java.io.IOException e )
+ {
+ // Just return originally-decoded bytes
+ } // end catch
+ finally
+ {
+ try{ baos.close(); } catch( Exception e ){}
+ try{ gzis.close(); } catch( Exception e ){}
+ try{ bais.close(); } catch( Exception e ){}
+ } // end finally
+
+ } // end if: gzipped
+ } // end if: bytes.length >= 2
+
+ return bytes;
+ } // end decode
+
+
+
+
+ /**
+ * Attempts to decode Base64 data and deserialize a Java
+ * Object within. Returns <tt>null</tt> if there was an error.
+ *
+ * @param encodedObject The Base64 data to decode
+ * @return The decoded and deserialized object
+ * @since 1.5
+ */
+ public static Object decodeToObject( String encodedObject )
+ {
+ // Decode and gunzip if necessary
+ byte[] objBytes = decode( encodedObject );
+
+ java.io.ByteArrayInputStream bais = null;
+ java.io.ObjectInputStream ois = null;
+ Object obj = null;
+
+ try
+ {
+ bais = new java.io.ByteArrayInputStream( objBytes );
+ ois = new java.io.ObjectInputStream( bais );
+
+ obj = ois.readObject();
+ } // end try
+ catch( java.io.IOException e )
+ {
+ e.printStackTrace();
+ obj = null;
+ } // end catch
+ catch( java.lang.ClassNotFoundException e )
+ {
+ e.printStackTrace();
+ obj = null;
+ } // end catch
+ finally
+ {
+ try{ bais.close(); } catch( Exception e ){}
+ try{ ois.close(); } catch( Exception e ){}
+ } // end finally
+
+ return obj;
+ } // end decodeObject
+
+
+
+ /**
+ * Convenience method for encoding data to a file.
+ *
+ * @param dataToEncode byte array of data to encode in base64 form
+ * @param filename Filename for saving encoded data
+ * @return <tt>true</tt> if successful, <tt>false</tt> otherwise
+ *
+ * @since 2.1
+ */
+ public static boolean encodeToFile( byte[] dataToEncode, String filename )
+ {
+ boolean success = false;
+ Base64.OutputStream bos = null;
+ try
+ {
+ bos = new Base64.OutputStream(
+ new java.io.FileOutputStream( filename ), Base64.ENCODE
);
+ bos.write( dataToEncode );
+ success = true;
+ } // end try
+ catch( java.io.IOException e )
+ {
+
+ success = false;
+ } // end catch: IOException
+ finally
+ {
+ try{ bos.close(); } catch( Exception e ){}
+ } // end finally
+
+ return success;
+ } // end encodeToFile
+
+
+ /**
+ * Convenience method for decoding data to a file.
+ *
+ * @param dataToDecode Base64-encoded data as a string
+ * @param filename Filename for saving decoded data
+ * @return <tt>true</tt> if successful, <tt>false</tt> otherwise
+ *
+ * @since 2.1
+ */
+ public static boolean decodeToFile( String dataToDecode, String filename )
+ {
+ boolean success = false;
+ Base64.OutputStream bos = null;
+ try
+ {
+ bos = new Base64.OutputStream(
+ new java.io.FileOutputStream( filename ),
Base64.DECODE );
+ bos.write( dataToDecode.getBytes( PREFERRED_ENCODING ) );
+ success = true;
+ } // end try
+ catch( java.io.IOException e )
+ {
+ success = false;
+ } // end catch: IOException
+ finally
+ {
+ try{ bos.close(); } catch( Exception e ){}
+ } // end finally
+
+ return success;
+ } // end decodeToFile
+
+
+
+
+ /**
+ * Convenience method for reading a base64-encoded
+ * file and decoding it.
+ *
+ * @param filename Filename for reading encoded data
+ * @return decoded byte array or null if unsuccessful
+ *
+ * @since 2.1
+ */
+ public static byte[] decodeFromFile( String filename )
+ {
+ byte[] decodedData = null;
+ Base64.InputStream bis = null;
+ try
+ {
+ // Set up some useful variables
+ java.io.File file = new java.io.File( filename );
+ byte[] buffer = null;
+ int length = 0;
+ int numBytes = 0;
+
+ // Check for size of file
+ if( file.length() > Integer.MAX_VALUE )
+ {
+ System.err.println( "File is too big for this convenience
method (" + file.length() + " bytes)." );
+ return null;
+ } // end if: file too big for int index
+ buffer = new byte[ (int)file.length() ];
+
+ // Open a stream
+ bis = new Base64.InputStream(
+ new java.io.BufferedInputStream(
+ new java.io.FileInputStream( file ) ), Base64.DECODE );
+
+ // Read until done
+ while( ( numBytes = bis.read( buffer, length, 4096 ) ) >= 0 )
+ length += numBytes;
+
+ // Save in a variable to return
+ decodedData = new byte[ length ];
+ System.arraycopy( buffer, 0, decodedData, 0, length );
+
+ } // end try
+ catch( java.io.IOException e )
+ {
+ System.err.println( "Error decoding from file " + filename );
+ } // end catch: IOException
+ finally
+ {
+ try{ bis.close(); } catch( Exception e) {}
+ } // end finally
+
+ return decodedData;
+ } // end decodeFromFile
+
+
+
+ /**
+ * Convenience method for reading a binary file
+ * and base64-encoding it.
+ *
+ * @param filename Filename for reading binary data
+ * @return base64-encoded string or null if unsuccessful
+ *
+ * @since 2.1
+ */
+ public static String encodeFromFile( String filename )
+ {
+ String encodedData = null;
+ Base64.InputStream bis = null;
+ try
+ {
+ // Set up some useful variables
+ java.io.File file = new java.io.File( filename );
+ byte[] buffer = new byte[ (int)(file.length() * 1.4) ];
+ int length = 0;
+ int numBytes = 0;
+
+ // Open a stream
+ bis = new Base64.InputStream(
+ new java.io.BufferedInputStream(
+ new java.io.FileInputStream( file ) ), Base64.ENCODE );
+
+ // Read until done
+ while( ( numBytes = bis.read( buffer, length, 4096 ) ) >= 0 )
+ length += numBytes;
+
+ // Save in a variable to return
+ encodedData = new String( buffer, 0, length,
Base64.PREFERRED_ENCODING );
+
+ } // end try
+ catch( java.io.IOException e )
+ {
+ System.err.println( "Error encoding from file " + filename );
+ } // end catch: IOException
+ finally
+ {
+ try{ bis.close(); } catch( Exception e) {}
+ } // end finally
+
+ return encodedData;
+ } // end encodeFromFile
+
+
+
+
+ /* ******** I N N E R C L A S S I N P U T S T R E A M ******** */
+
+
+
+ /**
+ * A [EMAIL PROTECTED] Base64.InputStream} will read data from another
+ * <tt>java.io.InputStream</tt>, given in the constructor,
+ * and encode/decode to/from Base64 notation on the fly.
+ *
+ * @see Base64
+ * @since 1.3
+ */
+ public static class InputStream extends java.io.FilterInputStream
+ {
+ private boolean encode; // Encoding or decoding
+ private int position; // Current position in the buffer
+ private byte[] buffer; // Small buffer holding converted data
+ private int bufferLength; // Length of buffer (3 or 4)
+ private int numSigBytes; // Number of meaningful bytes in the
buffer
+ private int lineLength;
+ private boolean breakLines; // Break lines at less than 80
characters
+
+
+ /**
+ * Constructs a [EMAIL PROTECTED] Base64.InputStream} in DECODE mode.
+ *
+ * @param in the <tt>java.io.InputStream</tt> from which to read data.
+ * @since 1.3
+ */
+ public InputStream( java.io.InputStream in )
+ {
+ this( in, DECODE );
+ } // end constructor
+
+
+ /**
+ * Constructs a [EMAIL PROTECTED] Base64.InputStream} in
+ * either ENCODE or DECODE mode.
+ * <p>
+ * Valid options:<pre>
+ * ENCODE or DECODE: Encode or Decode as data is read.
+ * DONT_BREAK_LINES: don't break lines at 76 characters
+ * (only meaningful when encoding)
+ * <i>Note: Technically, this makes your encoding
non-compliant.</i>
+ * </pre>
+ * <p>
+ * Example: <code>new Base64.InputStream( in, Base64.DECODE )</code>
+ *
+ *
+ * @param in the <tt>java.io.InputStream</tt> from which to read data.
+ * @param options Specified options
+ * @see Base64#ENCODE
+ * @see Base64#DECODE
+ * @see Base64#DONT_BREAK_LINES
+ * @since 2.0
+ */
+ public InputStream( java.io.InputStream in, int options )
+ {
+ super( in );
+ this.breakLines = (options & DONT_BREAK_LINES) !=
DONT_BREAK_LINES;
+ this.encode = (options & ENCODE) == ENCODE;
+ this.bufferLength = encode ? 4 : 3;
+ this.buffer = new byte[ bufferLength ];
+ this.position = -1;
+ this.lineLength = 0;
+ } // end constructor
+
+ /**
+ * Reads enough of the input stream to convert
+ * to/from Base64 and returns the next byte.
+ *
+ * @return next byte
+ * @since 1.3
+ */
+ public int read() throws java.io.IOException
+ {
+ // Do we need to get data?
+ if( position < 0 )
+ {
+ if( encode )
+ {
+ byte[] b3 = new byte[3];
+ int numBinaryBytes = 0;
+ for( int i = 0; i < 3; i++ )
+ {
+ try
+ {
+ int b = in.read();
+
+ // If end of stream, b is -1.
+ if( b >= 0 )
+ {
+ b3[i] = (byte)b;
+ numBinaryBytes++;
+ } // end if: not end of stream
+
+ } // end try: read
+ catch( java.io.IOException e )
+ {
+ // Only a problem if we got no data at all.
+ if( i == 0 )
+ throw e;
+
+ } // end catch
+ } // end for: each needed input byte
+
+ if( numBinaryBytes > 0 )
+ {
+ encode3to4( b3, 0, numBinaryBytes, buffer, 0 );
+ position = 0;
+ numSigBytes = 4;
+ } // end if: got data
+ else
+ {
+ return -1;
+ } // end else
+ } // end if: encoding
+
+ // Else decoding
+ else
+ {
+ byte[] b4 = new byte[4];
+ int i = 0;
+ for( i = 0; i < 4; i++ )
+ {
+ // Read four "meaningful" bytes:
+ int b = 0;
+ do{ b = in.read(); }
+ while( b >= 0 && DECODABET[ b & 0x7f ] <=
WHITE_SPACE_ENC );
+
+ if( b < 0 )
+ break; // Reads a -1 if end of stream
+
+ b4[i] = (byte)b;
+ } // end for: each needed input byte
+
+ if( i == 4 )
+ {
+ numSigBytes = decode4to3( b4, 0, buffer, 0 );
+ position = 0;
+ } // end if: got four characters
+ else if( i == 0 ){
+ return -1;
+ } // end else if: also padded correctly
+ else
+ {
+ // Must have broken out from above.
+ throw new java.io.IOException( "Improperly padded
Base64 input." );
+ } // end
+
+ } // end else: decode
+ } // end else: get data
+
+ // Got data?
+ if( position >= 0 )
+ {
+ // End of relevant data?
+ if( /*!encode &&*/ position >= numSigBytes )
+ return -1;
+
+ if( encode && breakLines && lineLength >= MAX_LINE_LENGTH )
+ {
+ lineLength = 0;
+ return '\n';
+ } // end if
+ else
+ {
+ lineLength++; // This isn't important when decoding
+ // but throwing an extra "if" seems
+ // just as wasteful.
+
+ int b = buffer[ position++ ];
+
+ if( position >= bufferLength )
+ position = -1;
+
+ return b & 0xFF; // This is how you "cast" a byte that's
+ // intended to be unsigned.
+ } // end else
+ } // end if: position >= 0
+
+ // Else error
+ else
+ {
+ // When JDK1.4 is more accepted, use an assertion here.
+ throw new java.io.IOException( "Error in Base64 code reading
stream." );
+ } // end else
+ } // end read
+
+
+ /**
+ * Calls [EMAIL PROTECTED] #read()} repeatedly until the end of stream
+ * is reached or <var>len</var> bytes are read.
+ * Returns number of bytes read into array or -1 if
+ * end of stream is encountered.
+ *
+ * @param dest array to hold values
+ * @param off offset for array
+ * @param len max number of bytes to read into array
+ * @return bytes read into array or -1 if end of stream is encountered.
+ * @since 1.3
+ */
+ public int read( byte[] dest, int off, int len ) throws
java.io.IOException
+ {
+ int i;
+ int b;
+ for( i = 0; i < len; i++ )
+ {
+ b = read();
+
+ //if( b < 0 && i == 0 )
+ // return -1;
+
+ if( b >= 0 )
+ dest[off + i] = (byte)b;
+ else if( i == 0 )
+ return -1;
+ else
+ break; // Out of 'for' loop
+ } // end for: each byte read
+ return i;
+ } // end read
+
+ } // end inner class InputStream
+
+
+
+
+
+
+ /* ******** I N N E R C L A S S O U T P U T S T R E A M ******** */
+
+
+
+ /**
+ * A [EMAIL PROTECTED] Base64.OutputStream} will write data to another
+ * <tt>java.io.OutputStream</tt>, given in the constructor,
+ * and encode/decode to/from Base64 notation on the fly.
+ *
+ * @see Base64
+ * @since 1.3
+ */
+ public static class OutputStream extends java.io.FilterOutputStream
+ {
+ private boolean encode;
+ private int position;
+ private byte[] buffer;
+ private int bufferLength;
+ private int lineLength;
+ private boolean breakLines;
+ private byte[] b4; // Scratch used in a few places
+ private boolean suspendEncoding;
+
+ /**
+ * Constructs a [EMAIL PROTECTED] Base64.OutputStream} in ENCODE mode.
+ *
+ * @param out the <tt>java.io.OutputStream</tt> to which data will be
written.
+ * @since 1.3
+ */
+ public OutputStream( java.io.OutputStream out )
+ {
+ this( out, ENCODE );
+ } // end constructor
+
+
+ /**
+ * Constructs a [EMAIL PROTECTED] Base64.OutputStream} in
+ * either ENCODE or DECODE mode.
+ * <p>
+ * Valid options:<pre>
+ * ENCODE or DECODE: Encode or Decode as data is read.
+ * DONT_BREAK_LINES: don't break lines at 76 characters
+ * (only meaningful when encoding)
+ * <i>Note: Technically, this makes your encoding
non-compliant.</i>
+ * </pre>
+ * <p>
+ * Example: <code>new Base64.OutputStream( out, Base64.ENCODE )</code>
+ *
+ * @param out the <tt>java.io.OutputStream</tt> to which data will be
written.
+ * @param options Specified options.
+ * @see Base64#ENCODE
+ * @see Base64#DECODE
+ * @see Base64#DONT_BREAK_LINES
+ * @since 1.3
+ */
+ public OutputStream( java.io.OutputStream out, int options )
+ {
+ super( out );
+ this.breakLines = (options & DONT_BREAK_LINES) !=
DONT_BREAK_LINES;
+ this.encode = (options & ENCODE) == ENCODE;
+ this.bufferLength = encode ? 3 : 4;
+ this.buffer = new byte[ bufferLength ];
+ this.position = 0;
+ this.lineLength = 0;
+ this.suspendEncoding = false;
+ this.b4 = new byte[4];
+ } // end constructor
+
+
+ /**
+ * Writes the byte to the output stream after
+ * converting to/from Base64 notation.
+ * When encoding, bytes are buffered three
+ * at a time before the output stream actually
+ * gets a write() call.
+ * When decoding, bytes are buffered four
+ * at a time.
+ *
+ * @param theByte the byte to write
+ * @since 1.3
+ */
+ public void write(int theByte) throws java.io.IOException
+ {
+ // Encoding suspended?
+ if( suspendEncoding )
+ {
+ super.out.write( theByte );
+ return;
+ } // end if: supsended
+
+ // Encode?
+ if( encode )
+ {
+ buffer[ position++ ] = (byte)theByte;
+ if( position >= bufferLength ) // Enough to encode.
+ {
+ out.write( encode3to4( b4, buffer, bufferLength ) );
+
+ lineLength += 4;
+ if( breakLines && lineLength >= MAX_LINE_LENGTH )
+ {
+ out.write( NEW_LINE );
+ lineLength = 0;
+ } // end if: end of line
+
+ position = 0;
+ } // end if: enough to output
+ } // end if: encoding
+
+ // Else, Decoding
+ else
+ {
+ // Meaningful Base64 character?
+ if( DECODABET[ theByte & 0x7f ] > WHITE_SPACE_ENC )
+ {
+ buffer[ position++ ] = (byte)theByte;
+ if( position >= bufferLength ) // Enough to output.
+ {
+ int len = Base64.decode4to3( buffer, 0, b4, 0 );
+ out.write( b4, 0, len );
+ //out.write( Base64.decode4to3( buffer ) );
+ position = 0;
+ } // end if: enough to output
+ } // end if: meaningful base64 character
+ else if( DECODABET[ theByte & 0x7f ] != WHITE_SPACE_ENC )
+ {
+ throw new java.io.IOException( "Invalid character in
Base64 data." );
+ } // end else: not white space either
+ } // end else: decoding
+ } // end write
+
+
+
+ /**
+ * Calls [EMAIL PROTECTED] #write(int)} repeatedly until
<var>len</var>
+ * bytes are written.
+ *
+ * @param theBytes array from which to read bytes
+ * @param off offset for array
+ * @param len max number of bytes to read into array
+ * @since 1.3
+ */
+ public void write( byte[] theBytes, int off, int len ) throws
java.io.IOException
+ {
+ // Encoding suspended?
+ if( suspendEncoding )
+ {
+ super.out.write( theBytes, off, len );
+ return;
+ } // end if: supsended
+
+ for( int i = 0; i < len; i++ )
+ {
+ write( theBytes[ off + i ] );
+ } // end for: each byte written
+
+ } // end write
+
+
+
+ /**
+ * Method added by PHIL. [Thanks, PHIL. -Rob]
+ * This pads the buffer without closing the stream.
+ */
+ public void flushBase64() throws java.io.IOException
+ {
+ if( position > 0 )
+ {
+ if( encode )
+ {
+ out.write( encode3to4( b4, buffer, position ) );
+ position = 0;
+ } // end if: encoding
+ else
+ {
+ throw new java.io.IOException( "Base64 input not properly
padded." );
+ } // end else: decoding
+ } // end if: buffer partially full
+
+ } // end flush
+
+
+ /**
+ * Flushes and closes (I think, in the superclass) the stream.
+ *
+ * @since 1.3
+ */
+ public void close() throws java.io.IOException
+ {
+ // 1. Ensure that pending characters are written
+ flushBase64();
+
+ // 2. Actually close the stream
+ // Base class both flushes and closes.
+ super.close();
+
+ buffer = null;
+ out = null;
+ } // end close
+
+
+
+ /**
+ * Suspends encoding of the stream.
+ * May be helpful if you need to embed a piece of
+ * base640-encoded data in a stream.
+ *
+ * @since 1.5.1
+ */
+ public void suspendEncoding() throws java.io.IOException
+ {
+ flushBase64();
+ this.suspendEncoding = true;
+ } // end suspendEncoding
+
+
+ /**
+ * Resumes encoding of the stream.
+ * May be helpful if you need to embed a piece of
+ * base640-encoded data in a stream.
+ *
+ * @since 1.5.1
+ */
+ public void resumeEncoding()
+ {
+ this.suspendEncoding = false;
+ } // end resumeEncoding
+
+
+
+ } // end inner class OutputStream
+
+
+} // end class Base64
Added:
trunk/clients/Javer2/src/org/haverdev/common/BasicAuthenticationHasher.java
===================================================================
--- trunk/clients/Javer2/src/org/haverdev/common/BasicAuthenticationHasher.java
2005-06-10 20:43:42 UTC (rev 762)
+++ trunk/clients/Javer2/src/org/haverdev/common/BasicAuthenticationHasher.java
2005-06-11 18:17:46 UTC (rev 763)
@@ -0,0 +1,161 @@
+/*
+ * BasicAuthenticationHasher.java
+ *
+ * Created on June 11, 2005, 1:30 PM
+ *
+ * To change this template, choose Tools | Options and locate the template
under
+ * the Source Creation and Management node. Right-click the template and choose
+ * Open. You can then make changes to the template in the Source Editor.
+ */
+
+package org.haverdev.common;
+import java.security.*;
+import java.nio.*;
+import java.nio.charset.*;
+import java.util.*;
+
+/**
+ *
+ * @author bdonlan
+ */
+public class BasicAuthenticationHasher {
+
+ static Map algos;
+
+ static void mapAlgo(Map algos, String havername, String spiname) {
+ try {
+ MessageDigest.getInstance(spiname);
+ algos.put(havername, spiname);
+ }
+ catch (NoSuchAlgorithmException e) {
+ System.err.println("Algorithm SPI " + spiname + " for " +
havername + " not found");
+ e.printStackTrace();
+ }
+ }
+
+ static void algoInit() {
+ if (algos != null) return;
+
+ String algostr = System.getProperty("haver.digestMaps",
"sha512:SHA-512 sha256:SHA-256 sha1:SHA-1");
+ String[] algolist = HaverEncoding.optionSplit(algostr);
+ Map algotemp = new LinkedHashMap();
+
+ for (int i = 0; i < algolist.length; i++) {
+ String desc = algolist[i];
+ int sep = desc.indexOf(':');
+ String havername = desc.substring(0, sep);
+ String spiname = desc.substring(sep + 1);
+ mapAlgo(algotemp, havername, spiname);
+ }
+
+ algos = Collections.unmodifiableMap(algotemp);
+ }
+
+ static MessageDigest digestForAlgo(String havername) throws
NoSuchAlgorithmException {
+ algoInit();
+ String algoname = (String)algos.get(havername);
+ if (algoname == null)
+ throw new NoSuchAlgorithmException("Haver digest name " +
havername + " not mapped");
+ return MessageDigest.getInstance(havername);
+ }
+
+ public static Set availableAlgos() {
+ algoInit();
+ return algos.keySet();
+ }
+
+ String password = null;
+ String hostname = null;
+ String username = null;
+
+ String passtok = null;
+ String nonce = null;
+
+ /** Creates a new instance of BasicAuthenticationHasher */
+ public BasicAuthenticationHasher() {
+ }
+
+ public String getPassword() {
+ return password;
+ }
+
+ public void setPassword(String password) {
+ this.password = password;
+ passtok = null;
+ }
+
+ public String getHostname() {
+ return hostname;
+ }
+
+ public void setHostname(String hostname) {
+ this.hostname = hostname;
+ passtok = null;
+ }
+
+ public String getUsername() {
+ return username;
+ }
+
+ public void setUsername(String username) {
+ this.username = username;
+ }
+
+ public String getPasstoken() {
+ if (passtok != null)
+ return passtok;
+
+ if (password == null || username == null || hostname == null)
+ throw new IllegalStateException("One or more of (password,
username, hostname) is not yet set");
+
+ MessageDigest md;
+ try {
+ md = MessageDigest.getInstance("SHA-1");
+ }
+ catch (NoSuchAlgorithmException e) {
+ throw new RuntimeException("Couldn't find SPI for SHA-1", e);
+ }
+
+ Charset utf8 = Charset.forName("UTF-8");
+ System.err.println("passtok blob=" + password+username+hostname);
+ ByteBuffer passtok_bb = utf8.encode(password + username + hostname);
+
+ md.update(passtok_bb);
+ byte[] digest = md.digest();
+
+ passtok = Base64.encodeBytes(digest);
+ return passtok;
+ }
+
+ public void setPasstoken(String passtok) {
+ this.passtok = passtok;
+ username = null;
+ hostname = null;
+ password = null;
+ }
+
+ public void setNonce(String nonce) {
+ this.nonce = nonce;
+ }
+
+ public String getNonce() {
+ return nonce;
+ }
+
+ public String digest(String haveralgo) throws NoSuchAlgorithmException {
+ String passtok = getPasstoken();
+ System.err.println("passtok="+passtok);
+ String nonce = getNonce();
+
+ if (nonce == null)
+ throw new IllegalStateException("nonce must not be null");
+
+ Charset utf8 = Charset.forName("UTF-8");
+ MessageDigest md = digestForAlgo(haveralgo);
+ md.update(utf8.encode(nonce + passtok));
+ String digest = Base64.encodeBytes(md.digest());
+ System.err.println("digest="+digest);
+ return digest;
+ }
+
+}
Property changes on:
trunk/clients/Javer2/src/org/haverdev/common/BasicAuthenticationHasher.java
___________________________________________________________________
Name: svn:eol-style
+ native
Added: trunk/clients/Javer2/src/org/haverdev/common/HaverEncoding.java
===================================================================
--- trunk/clients/Javer2/src/org/haverdev/common/HaverEncoding.java
2005-06-10 20:43:42 UTC (rev 762)
+++ trunk/clients/Javer2/src/org/haverdev/common/HaverEncoding.java
2005-06-11 18:17:46 UTC (rev 763)
@@ -0,0 +1,140 @@
+/*
+ * HaverEncoding.java
+ *
+ * Created on June 10, 2005, 9:41 PM
+ *
+ * To change this template, choose Tools | Options and locate the template
under
+ * the Source Creation and Management node. Right-click the template and choose
+ * Open. You can then make changes to the template in the Source Editor.
+ */
+
+package org.haverdev.common;
+import java.util.*;
+
+/**
+ *
+ * @author Bryan
+ */
+public final class HaverEncoding {
+
+ private HaverEncoding() {}
+
+ /**
+ * Reverses Haver escaping.
+ * @param val String to unescape
+ * @return The unescaped string
+ */
+ protected static final String unescape(String val) {
+ //if (val != null) return val;
+ StringBuffer out = new StringBuffer();
+ int pin = 0;
+ int nextEsc = -1;
+ while (-1 != (nextEsc = val.indexOf("\033", pin))) {
+ out.append(val.substring(0, nextEsc - 1));
+ switch (val.charAt(nextEsc + 1)) {
+ case 'r':
+ out.append('\r');
+ break;
+ case 'n':
+ out.append('\n');
+ break;
+ case 'e':
+ out.append('\033');
+ break;
+ case 't':
+ out.append('\t');
+ break;
+ default:
+ out.append(val.charAt(nextEsc + 1));
+ break;
+ }
+ pin = nextEsc + 2;
+ }
+ out.append(val.substring(pin));
+ return out.toString();
+ }
+
+ /**
+ * Escapes a string according to the Haver protocol
+ * @param val String to escape
+ * @return Escaped string
+ */
+ protected static final String escape(String val) {
+ /* GNU classpath
+ return val.replaceAll("\033", "\033e")
+ .replaceAll("\n", "\033n")
+ .replaceAll("\r", "\033r")
+ .replaceAll("\t", "\033t");
+ */
+ StringBuffer out = new StringBuffer();
+ char[] arr = val.toCharArray();
+ for (int i = 0; i < arr.length; i++) {
+ switch (arr[i]) {
+ case '\033':
+ out.append("\033e");
+ break;
+ case '\n':
+ out.append("\033n");
+ break;
+ case '\r':
+ out.append("\033r");
+ break;
+ case '\t':
+ out.append("\033t");
+ break;
+ default:
+ out.append(arr[i]);
+ }
+ }
+ return out.toString();
+ }
+
+ /**
+ * Decodes a raw line from the Haver protocol.
+ * @param inLine Line to decode. May end in '\r\n' but must only be one
line.
+ * @return An array containing the unescaped arguments of the line.
+ */
+ public static final String[] decodeLine(String inLine) {
+ int nl = inLine.indexOf("\r");
+ if (nl != -1)
+ inLine = inLine.substring(0, nl);
+ nl = inLine.indexOf("\n");
+ if (nl != -1)
+ inLine = inLine.substring(0, nl);
+
+ String[] args = splitString(inLine, "\t");
+ for (int i = 0; i < args.length; i++) {
+ args[i] = unescape(args[i]);
+ }
+ return args;
+ }
+
+ /**
+ * Encodes a set of arguments for line transmission
+ * @param args Unescaped arguments to encode
+ * @return Escaped and joined line ready for transmission, complete with
ending \r\n
+ */
+ public static final String encodeLine(String[] args) {
+ StringBuffer out = new StringBuffer();
+ for (int i = 0; i < args.length; i++) {
+ if (i != 0)
+ out.append("\t");
+ out.append(escape(args[i]));
+ }
+ out.append("\r\n");
+ return out.toString();
+ }
+
+ public static final String[] splitString(String str, String delims) {
+ StringTokenizer t = new StringTokenizer(str, delims);
+ ArrayList al = new ArrayList();
+ while (t.hasMoreTokens()) {
+ al.add(t.nextElement());
+ }
+ return (String[]) al.toArray(new String[al.size()]);
+ }
+
+ public static String[] optionSplit(String str) {
+ return HaverEncoding.splitString(str, " ,");
+ }
+}
Property changes on:
trunk/clients/Javer2/src/org/haverdev/common/HaverEncoding.java
___________________________________________________________________
Name: svn:eol-style
+ native
Copied: trunk/clients/Javer2/src/org/haverdev/common/ObjectQueue.java (from rev
739, trunk/clients/Javer2/src/org/haverdev/haver/server/ObjectQueue.java)
===================================================================
--- trunk/clients/Javer2/src/org/haverdev/haver/server/ObjectQueue.java
2005-05-27 19:22:09 UTC (rev 739)
+++ trunk/clients/Javer2/src/org/haverdev/common/ObjectQueue.java
2005-06-11 18:17:46 UTC (rev 763)
@@ -0,0 +1,59 @@
+/*
+ * ObjectQueue.java
+ *
+ * Created on May 27, 2005, 3:03 PM
+ */
+
+package org.haverdev.common;
+import java.util.*;
+
+/**
+ *
+ * @author bdonlan
+ */
+public class ObjectQueue {
+ LinkedList theQueue = new LinkedList();
+
+ /** Creates a new instance of ObjectQueue */
+ public ObjectQueue() {
+ }
+
+ public Object block(long millis) throws InterruptedException {
+ synchronized (theQueue) {
+ if (theQueue.isEmpty()) {
+ theQueue.wait(millis);
+ }
+ if (theQueue.isEmpty()) {
+ System.err.println("ObjectQueue: Awakened with nothing to show
for it...");
+ return null;
+ }
+ Object o = theQueue.removeFirst();
+ return o;
+ }
+ }
+
+ public Object block() throws InterruptedException {
+ return block(0);
+ }
+
+ public boolean hasData() {
+ synchronized (theQueue) {
+ return !theQueue.isEmpty();
+ }
+ }
+
+ public Object poll() {
+ synchronized (theQueue) {
+ if (theQueue.isEmpty())
+ return null;
+ return theQueue.removeFirst();
+ }
+ }
+
+ public void post(Object o) {
+ synchronized (theQueue) {
+ theQueue.addLast(o);
+ theQueue.notify();
+ }
+ }
+}
Deleted: trunk/clients/Javer2/src/org/haverdev/haver/Base64.java
===================================================================
--- trunk/clients/Javer2/src/org/haverdev/haver/Base64.java 2005-06-10
20:43:42 UTC (rev 762)
+++ trunk/clients/Javer2/src/org/haverdev/haver/Base64.java 2005-06-11
18:17:46 UTC (rev 763)
@@ -1,1451 +0,0 @@
-package org.haverdev.haver;
-
-/**
- * Encodes and decodes to and from Base64 notation.
- *
- * <p>
- * Change Log:
- * </p>
- * <ul>
- * <li>v2.1 - Cleaned up javadoc comments and unused variables and methods.
Added
- * some convenience methods for reading and writing to and from files.</li>
- * <li>v2.0.2 - Now specifies UTF-8 encoding in places where the code fails
on systems
- * with other encodings (like EBCDIC).</li>
- * <li>v2.0.1 - Fixed an error when decoding a single byte, that is, when the
- * encoded data was a single byte.</li>
- * <li>v2.0 - I got rid of methods that used booleans to set options.
- * Now everything is more consolidated and cleaner. The code now detects
- * when data that's being decoded is gzip-compressed and will decompress it
- * automatically. Generally things are cleaner. You'll probably have to
- * change some method calls that you were making to support the new
- * options format (<tt>int</tt>s that you "OR" together).</li>
- * <li>v1.5.1 - Fixed bug when decompressing and decoding to a
- * byte[] using <tt>decode( String s, boolean gzipCompressed )</tt>.
- * Added the ability to "suspend" encoding in the Output Stream so
- * you can turn on and off the encoding if you need to embed base64
- * data in an otherwise "normal" stream (like an XML file).</li>
- * <li>v1.5 - Output stream pases on flush() command but doesn't do anything
itself.
- * This helps when using GZIP streams.
- * Added the ability to GZip-compress objects before encoding them.</li>
- * <li>v1.4 - Added helper methods to read/write files.</li>
- * <li>v1.3.6 - Fixed OutputStream.flush() so that 'position' is reset.</li>
- * <li>v1.3.5 - Added flag to turn on and off line breaks. Fixed bug in input
stream
- * where last buffer being read, if not completely full, was not
returned.</li>
- * <li>v1.3.4 - Fixed when "improperly padded stream" error was thrown at the
wrong time.</li>
- * <li>v1.3.3 - Fixed I/O streams which were totally messed up.</li>
- * </ul>
- *
- * <p>
- * I am placing this code in the Public Domain. Do with it as you will.
- * This software comes with no guarantees or warranties but with
- * plenty of well-wishing instead!
- * Please visit <a
href="http://iharder.net/base64">http://iharder.net/base64</a>
- * periodically to check for updates or to contribute improvements.
- * </p>
- *
- * @author Robert Harder
- * @author [EMAIL PROTECTED]
- * @version 2.1
- */
-public class Base64
-{
-
-/* ******** P U B L I C F I E L D S ******** */
-
-
- /** No options specified. Value is zero. */
- public final static int NO_OPTIONS = 0;
-
- /** Specify encoding. */
- public final static int ENCODE = 1;
-
-
- /** Specify decoding. */
- public final static int DECODE = 0;
-
-
- /** Specify that data should be gzip-compressed. */
- public final static int GZIP = 2;
-
-
- /** Don't break lines when encoding (violates strict Base64 specification)
*/
- public final static int DONT_BREAK_LINES = 8;
-
-
-/* ******** P R I V A T E F I E L D S ******** */
-
-
- /** Maximum line length (76) of Base64 output. */
- private final static int MAX_LINE_LENGTH = 76;
-
-
- /** The equals sign (=) as a byte. */
- private final static byte EQUALS_SIGN = (byte)'=';
-
-
- /** The new line character (\n) as a byte. */
- private final static byte NEW_LINE = (byte)'\n';
-
-
- /** Preferred encoding. */
- private final static String PREFERRED_ENCODING = "UTF-8";
-
-
- /** The 64 valid Base64 values. */
- private final static byte[] ALPHABET;
- private final static byte[] _NATIVE_ALPHABET = /* May be something funny
like EBCDIC */
- {
- (byte)'A', (byte)'B', (byte)'C', (byte)'D', (byte)'E', (byte)'F',
(byte)'G',
- (byte)'H', (byte)'I', (byte)'J', (byte)'K', (byte)'L', (byte)'M',
(byte)'N',
- (byte)'O', (byte)'P', (byte)'Q', (byte)'R', (byte)'S', (byte)'T',
(byte)'U',
- (byte)'V', (byte)'W', (byte)'X', (byte)'Y', (byte)'Z',
- (byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f',
(byte)'g',
- (byte)'h', (byte)'i', (byte)'j', (byte)'k', (byte)'l', (byte)'m',
(byte)'n',
- (byte)'o', (byte)'p', (byte)'q', (byte)'r', (byte)'s', (byte)'t',
(byte)'u',
- (byte)'v', (byte)'w', (byte)'x', (byte)'y', (byte)'z',
- (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5',
- (byte)'6', (byte)'7', (byte)'8', (byte)'9', (byte)'+', (byte)'/'
- };
-
- /** Determine which ALPHABET to use. */
- static
- {
- byte[] __bytes;
- try
- {
- __bytes =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".getBytes(
PREFERRED_ENCODING );
- } // end try
- catch (java.io.UnsupportedEncodingException use)
- {
- __bytes = _NATIVE_ALPHABET; // Fall back to native encoding
- } // end catch
- ALPHABET = __bytes;
- } // end static
-
-
- /**
- * Translates a Base64 value to either its 6-bit reconstruction value
- * or a negative number indicating some other meaning.
- **/
- private final static byte[] DECODABET =
- {
- -9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 0 - 8
- -5,-5, // Whitespace: Tab and
Linefeed
- -9,-9, // Decimal 11 - 12
- -5, // Whitespace: Carriage
Return
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 14 - 26
- -9,-9,-9,-9,-9, // Decimal 27 - 31
- -5, // Whitespace: Space
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 33 - 42
- 62, // Plus sign at decimal 43
- -9,-9,-9, // Decimal 44 - 46
- 63, // Slash at decimal 47
- 52,53,54,55,56,57,58,59,60,61, // Numbers zero through
nine
- -9,-9,-9, // Decimal 58 - 60
- -1, // Equals sign at decimal
61
- -9,-9,-9, // Decimal 62 - 64
- 0,1,2,3,4,5,6,7,8,9,10,11,12,13, // Letters 'A' through 'N'
- 14,15,16,17,18,19,20,21,22,23,24,25, // Letters 'O' through 'Z'
- -9,-9,-9,-9,-9,-9, // Decimal 91 - 96
- 26,27,28,29,30,31,32,33,34,35,36,37,38, // Letters 'a' through 'm'
- 39,40,41,42,43,44,45,46,47,48,49,50,51, // Letters 'n' through 'z'
- -9,-9,-9,-9 // Decimal 123 - 126
- /*,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 127 - 139
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 140 - 152
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 153 - 165
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 166 - 178
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 179 - 191
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 192 - 204
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 205 - 217
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 218 - 230
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 231 - 243
- -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9 // Decimal 244 - 255 */
- };
-
- // I think I end up not using the BAD_ENCODING indicator.
- //private final static byte BAD_ENCODING = -9; // Indicates error in
encoding
- private final static byte WHITE_SPACE_ENC = -5; // Indicates white space
in encoding
- private final static byte EQUALS_SIGN_ENC = -1; // Indicates equals sign
in encoding
-
-
- /** Defeats instantiation. */
- private Base64(){}
-
-
-
-/* ******** E N C O D I N G M E T H O D S ******** */
-
-
- /**
- * Encodes up to the first three bytes of array <var>threeBytes</var>
- * and returns a four-byte array in Base64 notation.
- * The actual number of significant bytes in your array is
- * given by <var>numSigBytes</var>.
- * The array <var>threeBytes</var> needs only be as big as
- * <var>numSigBytes</var>.
- * Code can reuse a byte array by passing a four-byte array as
<var>b4</var>.
- *
- * @param b4 A reusable byte array to reduce array instantiation
- * @param threeBytes the array to convert
- * @param numSigBytes the number of significant bytes in your array
- * @return four byte array in Base64 notation.
- * @since 1.5.1
- */
- private static byte[] encode3to4( byte[] b4, byte[] threeBytes, int
numSigBytes )
- {
- encode3to4( threeBytes, 0, numSigBytes, b4, 0 );
- return b4;
- } // end encode3to4
-
-
- /**
- * Encodes up to three bytes of the array <var>source</var>
- * and writes the resulting four Base64 bytes to <var>destination</var>.
- * The source and destination arrays can be manipulated
- * anywhere along their length by specifying
- * <var>srcOffset</var> and <var>destOffset</var>.
- * This method does not check to make sure your arrays
- * are large enough to accomodate <var>srcOffset</var> + 3 for
- * the <var>source</var> array or <var>destOffset</var> + 4 for
- * the <var>destination</var> array.
- * The actual number of significant bytes in your array is
- * given by <var>numSigBytes</var>.
- *
- * @param source the array to convert
- * @param srcOffset the index where conversion begins
- * @param numSigBytes the number of significant bytes in your array
- * @param destination the array to hold the conversion
- * @param destOffset the index where output will be put
- * @return the <var>destination</var> array
- * @since 1.3
- */
- private static byte[] encode3to4(
- byte[] source, int srcOffset, int numSigBytes,
- byte[] destination, int destOffset )
- {
- // 1 2 3
- // 01234567890123456789012345678901 Bit position
- // --------000000001111111122222222 Array position from threeBytes
- // --------| || || || | Six bit groups to index ALPHABET
- // >>18 >>12 >> 6 >> 0 Right shift necessary
- // 0x3f 0x3f 0x3f Additional AND
-
- // Create buffer with zero-padding if there are only one or two
- // significant bytes passed in the array.
- // We have to shift left 24 in order to flush out the 1's that appear
- // when Java treats a value as negative that is cast from a byte to an
int.
- int inBuff = ( numSigBytes > 0 ? ((source[ srcOffset ] << 24)
>>> 8) : 0 )
- | ( numSigBytes > 1 ? ((source[ srcOffset + 1 ] << 24)
>>> 16) : 0 )
- | ( numSigBytes > 2 ? ((source[ srcOffset + 2 ] << 24)
>>> 24) : 0 );
-
- switch( numSigBytes )
- {
- case 3:
- destination[ destOffset ] = ALPHABET[ (inBuff >>> 18)
];
- destination[ destOffset + 1 ] = ALPHABET[ (inBuff >>> 12) &
0x3f ];
- destination[ destOffset + 2 ] = ALPHABET[ (inBuff >>> 6) &
0x3f ];
- destination[ destOffset + 3 ] = ALPHABET[ (inBuff ) &
0x3f ];
- return destination;
-
- case 2:
- destination[ destOffset ] = ALPHABET[ (inBuff >>> 18)
];
- destination[ destOffset + 1 ] = ALPHABET[ (inBuff >>> 12) &
0x3f ];
- destination[ destOffset + 2 ] = ALPHABET[ (inBuff >>> 6) &
0x3f ];
- destination[ destOffset + 3 ] = EQUALS_SIGN;
- return destination;
-
- case 1:
- destination[ destOffset ] = ALPHABET[ (inBuff >>> 18)
];
- destination[ destOffset + 1 ] = ALPHABET[ (inBuff >>> 12) &
0x3f ];
- destination[ destOffset + 2 ] = EQUALS_SIGN;
- destination[ destOffset + 3 ] = EQUALS_SIGN;
- return destination;
-
- default:
- return destination;
- } // end switch
- } // end encode3to4
-
-
-
- /**
- * Serializes an object and returns the Base64-encoded
- * version of that serialized object. If the object
- * cannot be serialized or there is another error,
- * the method will return <tt>null</tt>.
- * The object is not GZip-compressed before being encoded.
- *
- * @param serializableObject The object to encode
- * @return The Base64-encoded object
- * @since 1.4
- */
- public static String encodeObject( java.io.Serializable serializableObject
)
- {
- return encodeObject( serializableObject, NO_OPTIONS );
- } // end encodeObject
-
-
-
- /**
- * Serializes an object and returns the Base64-encoded
- * version of that serialized object. If the object
- * cannot be serialized or there is another error,
- * the method will return <tt>null</tt>.
- * <p>
- * Valid options:<pre>
- * GZIP: gzip-compresses object before encoding it.
- * DONT_BREAK_LINES: don't break lines at 76 characters
- * <i>Note: Technically, this makes your encoding non-compliant.</i>
- * </pre>
- * <p>
- * Example: <code>encodeObject( myObj, Base64.GZIP )</code> or
- * <p>
- * Example: <code>encodeObject( myObj, Base64.GZIP |
Base64.DONT_BREAK_LINES )</code>
- *
- * @param serializableObject The object to encode
- * @param options Specified options
- * @return The Base64-encoded object
- * @see Base64#GZIP
- * @see Base64#DONT_BREAK_LINES
- * @since 2.0
- */
- public static String encodeObject( java.io.Serializable
serializableObject, int options )
- {
- // Streams
- java.io.ByteArrayOutputStream baos = null;
- java.io.OutputStream b64os = null;
- java.io.ObjectOutputStream oos = null;
- java.util.zip.GZIPOutputStream gzos = null;
-
- // Isolate options
- int gzip = (options & GZIP);
- int dontBreakLines = (options & DONT_BREAK_LINES);
-
- try
- {
- // ObjectOutputStream -> (GZIP) -> Base64 -> ByteArrayOutputStream
- baos = new java.io.ByteArrayOutputStream();
- b64os = new Base64.OutputStream( baos, ENCODE | dontBreakLines );
-
- // GZip?
- if( gzip == GZIP )
- {
- gzos = new java.util.zip.GZIPOutputStream( b64os );
- oos = new java.io.ObjectOutputStream( gzos );
- } // end if: gzip
- else
- oos = new java.io.ObjectOutputStream( b64os );
-
- oos.writeObject( serializableObject );
- } // end try
- catch( java.io.IOException e )
- {
- e.printStackTrace();
- return null;
- } // end catch
- finally
- {
- try{ oos.close(); } catch( Exception e ){}
- try{ gzos.close(); } catch( Exception e ){}
- try{ b64os.close(); } catch( Exception e ){}
- try{ baos.close(); } catch( Exception e ){}
- } // end finally
-
- // Return value according to relevant encoding.
- try
- {
- return new String( baos.toByteArray(), PREFERRED_ENCODING );
- } // end try
- catch (java.io.UnsupportedEncodingException uue)
- {
- return new String( baos.toByteArray() );
- } // end catch
-
- } // end encode
-
-
-
- /**
- * Encodes a byte array into Base64 notation.
- * Does not GZip-compress data.
- *
- * @param source The data to convert
- * @since 1.4
- */
- public static String encodeBytes( byte[] source )
- {
- return encodeBytes( source, 0, source.length, NO_OPTIONS );
- } // end encodeBytes
-
-
-
- /**
- * Encodes a byte array into Base64 notation.
- * <p>
- * Valid options:<pre>
- * GZIP: gzip-compresses object before encoding it.
- * DONT_BREAK_LINES: don't break lines at 76 characters
- * <i>Note: Technically, this makes your encoding non-compliant.</i>
- * </pre>
- * <p>
- * Example: <code>encodeBytes( myData, Base64.GZIP )</code> or
- * <p>
- * Example: <code>encodeBytes( myData, Base64.GZIP |
Base64.DONT_BREAK_LINES )</code>
- *
- *
- * @param source The data to convert
- * @param options Specified options
- * @see Base64#GZIP
- * @see Base64#DONT_BREAK_LINES
- * @since 2.0
- */
- public static String encodeBytes( byte[] source, int options )
- {
- return encodeBytes( source, 0, source.length, options );
- } // end encodeBytes
-
-
- /**
- * Encodes a byte array into Base64 notation.
- * Does not GZip-compress data.
- *
- * @param source The data to convert
- * @param off Offset in array where conversion should begin
- * @param len Length of data to convert
- * @since 1.4
- */
- public static String encodeBytes( byte[] source, int off, int len )
- {
- return encodeBytes( source, off, len, NO_OPTIONS );
- } // end encodeBytes
-
-
-
- /**
- * Encodes a byte array into Base64 notation.
- * <p>
- * Valid options:<pre>
- * GZIP: gzip-compresses object before encoding it.
- * DONT_BREAK_LINES: don't break lines at 76 characters
- * <i>Note: Technically, this makes your encoding non-compliant.</i>
- * </pre>
- * <p>
- * Example: <code>encodeBytes( myData, Base64.GZIP )</code> or
- * <p>
- * Example: <code>encodeBytes( myData, Base64.GZIP |
Base64.DONT_BREAK_LINES )</code>
- *
- *
- * @param source The data to convert
- * @param off Offset in array where conversion should begin
- * @param len Length of data to convert
- * @param options Specified options
- * @see Base64#GZIP
- * @see Base64#DONT_BREAK_LINES
- * @since 2.0
- */
- public static String encodeBytes( byte[] source, int off, int len, int
options )
- {
- // Isolate options
- int dontBreakLines = ( options & DONT_BREAK_LINES );
- int gzip = ( options & GZIP );
-
- // Compress?
- if( gzip == GZIP )
- {
- java.io.ByteArrayOutputStream baos = null;
- java.util.zip.GZIPOutputStream gzos = null;
- Base64.OutputStream b64os = null;
-
-
- try
- {
- // GZip -> Base64 -> ByteArray
- baos = new java.io.ByteArrayOutputStream();
- b64os = new Base64.OutputStream( baos, ENCODE | dontBreakLines
);
- gzos = new java.util.zip.GZIPOutputStream( b64os );
-
- gzos.write( source, off, len );
- gzos.close();
- } // end try
- catch( java.io.IOException e )
- {
- e.printStackTrace();
- return null;
- } // end catch
- finally
- {
- try{ gzos.close(); } catch( Exception e ){}
- try{ b64os.close(); } catch( Exception e ){}
- try{ baos.close(); } catch( Exception e ){}
- } // end finally
-
- // Return value according to relevant encoding.
- try
- {
- return new String( baos.toByteArray(), PREFERRED_ENCODING );
- } // end try
- catch (java.io.UnsupportedEncodingException uue)
- {
- return new String( baos.toByteArray() );
- } // end catch
- } // end if: compress
-
- // Else, don't compress. Better not to use streams at all then.
- else
- {
- // Convert option to boolean in way that code likes it.
- boolean breakLines = dontBreakLines == 0;
-
- int len43 = len * 4 / 3;
- byte[] outBuff = new byte[ ( len43 ) //
Main 4:3
- + ( (len % 3) > 0 ? 4 : 0 ) //
Account for padding
- + (breakLines ? ( len43 /
MAX_LINE_LENGTH ) : 0) ]; // New lines
- int d = 0;
- int e = 0;
- int len2 = len - 2;
- int lineLength = 0;
- for( ; d < len2; d+=3, e+=4 )
- {
- encode3to4( source, d+off, 3, outBuff, e );
-
- lineLength += 4;
- if( breakLines && lineLength == MAX_LINE_LENGTH )
- {
- outBuff[e+4] = NEW_LINE;
- e++;
- lineLength = 0;
- } // end if: end of line
- } // en dfor: each piece of array
-
- if( d < len )
- {
- encode3to4( source, d+off, len - d, outBuff, e );
- e += 4;
- } // end if: some padding needed
-
-
- // Return value according to relevant encoding.
- try
- {
- return new String( outBuff, 0, e, PREFERRED_ENCODING );
- } // end try
- catch (java.io.UnsupportedEncodingException uue)
- {
- return new String( outBuff, 0, e );
- } // end catch
-
- } // end else: don't compress
-
- } // end encodeBytes
-
-
-
-
-
-/* ******** D E C O D I N G M E T H O D S ******** */
-
-
- /**
- * Decodes four bytes from array <var>source</var>
- * and writes the resulting bytes (up to three of them)
- * to <var>destination</var>.
- * The source and destination arrays can be manipulated
- * anywhere along their length by specifying
- * <var>srcOffset</var> and <var>destOffset</var>.
- * This method does not check to make sure your arrays
- * are large enough to accomodate <var>srcOffset</var> + 4 for
- * the <var>source</var> array or <var>destOffset</var> + 3 for
- * the <var>destination</var> array.
- * This method returns the actual number of bytes that
- * were converted from the Base64 encoding.
- *
- *
- * @param source the array to convert
- * @param srcOffset the index where conversion begins
- * @param destination the array to hold the conversion
- * @param destOffset the index where output will be put
- * @return the number of decoded bytes converted
- * @since 1.3
- */
- private static int decode4to3( byte[] source, int srcOffset, byte[]
destination, int destOffset )
- {
- // Example: Dk==
- if( source[ srcOffset + 2] == EQUALS_SIGN )
- {
- // Two ways to do the same thing. Don't know which way I like best.
- //int outBuff = ( ( DECODABET[ source[ srcOffset ] ] << 24 )
>>> 6 )
- // | ( ( DECODABET[ source[ srcOffset + 1] ] << 24 )
>>> 12 );
- int outBuff = ( ( DECODABET[ source[ srcOffset ] ] & 0xFF )
<< 18 )
- | ( ( DECODABET[ source[ srcOffset + 1] ] & 0xFF )
<< 12 );
-
- destination[ destOffset ] = (byte)( outBuff >>> 16 );
- return 1;
- }
-
- // Example: DkL=
- else if( source[ srcOffset + 3 ] == EQUALS_SIGN )
- {
- // Two ways to do the same thing. Don't know which way I like best.
- //int outBuff = ( ( DECODABET[ source[ srcOffset ] ] << 24 )
>>> 6 )
- // | ( ( DECODABET[ source[ srcOffset + 1 ] ] << 24 )
>>> 12 )
- // | ( ( DECODABET[ source[ srcOffset + 2 ] ] << 24 )
>>> 18 );
- int outBuff = ( ( DECODABET[ source[ srcOffset ] ] & 0xFF )
<< 18 )
- | ( ( DECODABET[ source[ srcOffset + 1 ] ] & 0xFF )
<< 12 )
- | ( ( DECODABET[ source[ srcOffset + 2 ] ] & 0xFF )
<< 6 );
-
- destination[ destOffset ] = (byte)( outBuff >>> 16 );
- destination[ destOffset + 1 ] = (byte)( outBuff >>> 8 );
- return 2;
- }
-
- // Example: DkLE
- else
- {
- try{
- // Two ways to do the same thing. Don't know which way I like best.
- //int outBuff = ( ( DECODABET[ source[ srcOffset ] ] << 24 )
>>> 6 )
- // | ( ( DECODABET[ source[ srcOffset + 1 ] ] << 24 )
>>> 12 )
- // | ( ( DECODABET[ source[ srcOffset + 2 ] ] << 24 )
>>> 18 )
- // | ( ( DECODABET[ source[ srcOffset + 3 ] ] << 24 )
>>> 24 );
- int outBuff = ( ( DECODABET[ source[ srcOffset ] ] & 0xFF )
<< 18 )
- | ( ( DECODABET[ source[ srcOffset + 1 ] ] & 0xFF )
<< 12 )
- | ( ( DECODABET[ source[ srcOffset + 2 ] ] & 0xFF )
<< 6)
- | ( ( DECODABET[ source[ srcOffset + 3 ] ] & 0xFF )
);
-
-
- destination[ destOffset ] = (byte)( outBuff >> 16 );
- destination[ destOffset + 1 ] = (byte)( outBuff >> 8 );
- destination[ destOffset + 2 ] = (byte)( outBuff );
-
- return 3;
- }catch( Exception e){
- System.out.println(""+source[srcOffset]+ ": " + ( DECODABET[
source[ srcOffset ] ] ) );
- System.out.println(""+source[srcOffset+1]+ ": " + (
DECODABET[ source[ srcOffset + 1 ] ] ) );
- System.out.println(""+source[srcOffset+2]+ ": " + (
DECODABET[ source[ srcOffset + 2 ] ] ) );
- System.out.println(""+source[srcOffset+3]+ ": " + (
DECODABET[ source[ srcOffset + 3 ] ] ) );
- return -1;
- } //e nd catch
- }
- } // end decodeToBytes
-
-
-
-
- /**
- * Very low-level access to decoding ASCII characters in
- * the form of a byte array. Does not support automatically
- * gunzipping or any other "fancy" features.
- *
- * @param source The Base64 encoded data
- * @param off The offset of where to begin decoding
- * @param len The length of characters to decode
- * @return decoded data
- * @since 1.3
- */
- public static byte[] decode( byte[] source, int off, int len )
- {
- int len34 = len * 3 / 4;
- byte[] outBuff = new byte[ len34 ]; // Upper limit on size of output
- int outBuffPosn = 0;
-
- byte[] b4 = new byte[4];
- int b4Posn = 0;
- int i = 0;
- byte sbiCrop = 0;
- byte sbiDecode = 0;
- for( i = off; i < off+len; i++ )
- {
- sbiCrop = (byte)(source[i] & 0x7f); // Only the low seven bits
- sbiDecode = DECODABET[ sbiCrop ];
-
- if( sbiDecode >= WHITE_SPACE_ENC ) // White space, Equals sign or
better
- {
- if( sbiDecode >= EQUALS_SIGN_ENC )
- {
- b4[ b4Posn++ ] = sbiCrop;
- if( b4Posn > 3 )
- {
- outBuffPosn += decode4to3( b4, 0, outBuff, outBuffPosn
);
- b4Posn = 0;
-
- // If that was the equals sign, break out of 'for' loop
- if( sbiCrop == EQUALS_SIGN )
- break;
- } // end if: quartet built
-
- } // end if: equals sign or better
-
- } // end if: white space, equals sign or better
- else
- {
- System.err.println( "Bad Base64 input character at " + i + ":
" + source[i] + "(decimal)" );
- return null;
- } // end else:
- } // each input character
-
- byte[] out = new byte[ outBuffPosn ];
- System.arraycopy( outBuff, 0, out, 0, outBuffPosn );
- return out;
- } // end decode
-
-
-
-
- /**
- * Decodes data from Base64 notation, automatically
- * detecting gzip-compressed data and decompressing it.
- *
- * @param s the string to decode
- * @return the decoded data
- * @since 1.4
- */
- public static byte[] decode( String s )
- {
- byte[] bytes;
- try
- {
- bytes = s.getBytes( PREFERRED_ENCODING );
- } // end try
- catch( java.io.UnsupportedEncodingException uee )
- {
- bytes = s.getBytes();
- } // end catch
- //</change>
-
- // Decode
- bytes = decode( bytes, 0, bytes.length );
-
-
- // Check to see if it's gzip-compressed
- // GZIP Magic Two-Byte Number: 0x8b1f (35615)
- if( bytes != null && bytes.length >= 4 )
- {
-
- int head = ((int)bytes[0] & 0xff) | ((bytes[1] << 8) & 0xff00);
- if( java.util.zip.GZIPInputStream.GZIP_MAGIC == head )
- {
- java.io.ByteArrayInputStream bais = null;
- java.util.zip.GZIPInputStream gzis = null;
- java.io.ByteArrayOutputStream baos = null;
- byte[] buffer = new byte[2048];
- int length = 0;
-
- try
- {
- baos = new java.io.ByteArrayOutputStream();
- bais = new java.io.ByteArrayInputStream( bytes );
- gzis = new java.util.zip.GZIPInputStream( bais );
-
- while( ( length = gzis.read( buffer ) ) >= 0 )
- {
- baos.write(buffer,0,length);
- } // end while: reading input
-
- // No error? Get new bytes.
- bytes = baos.toByteArray();
-
- } // end try
- catch( java.io.IOException e )
- {
- // Just return originally-decoded bytes
- } // end catch
- finally
- {
- try{ baos.close(); } catch( Exception e ){}
- try{ gzis.close(); } catch( Exception e ){}
- try{ bais.close(); } catch( Exception e ){}
- } // end finally
-
- } // end if: gzipped
- } // end if: bytes.length >= 2
-
- return bytes;
- } // end decode
-
-
-
-
- /**
- * Attempts to decode Base64 data and deserialize a Java
- * Object within. Returns <tt>null</tt> if there was an error.
- *
- * @param encodedObject The Base64 data to decode
- * @return The decoded and deserialized object
- * @since 1.5
- */
- public static Object decodeToObject( String encodedObject )
- {
- // Decode and gunzip if necessary
- byte[] objBytes = decode( encodedObject );
-
- java.io.ByteArrayInputStream bais = null;
- java.io.ObjectInputStream ois = null;
- Object obj = null;
-
- try
- {
- bais = new java.io.ByteArrayInputStream( objBytes );
- ois = new java.io.ObjectInputStream( bais );
-
- obj = ois.readObject();
- } // end try
- catch( java.io.IOException e )
- {
- e.printStackTrace();
- obj = null;
- } // end catch
- catch( java.lang.ClassNotFoundException e )
- {
- e.printStackTrace();
- obj = null;
- } // end catch
- finally
- {
- try{ bais.close(); } catch( Exception e ){}
- try{ ois.close(); } catch( Exception e ){}
- } // end finally
-
- return obj;
- } // end decodeObject
-
-
-
- /**
- * Convenience method for encoding data to a file.
- *
- * @param dataToEncode byte array of data to encode in base64 form
- * @param filename Filename for saving encoded data
- * @return <tt>true</tt> if successful, <tt>false</tt> otherwise
- *
- * @since 2.1
- */
- public static boolean encodeToFile( byte[] dataToEncode, String filename )
- {
- boolean success = false;
- Base64.OutputStream bos = null;
- try
- {
- bos = new Base64.OutputStream(
- new java.io.FileOutputStream( filename ), Base64.ENCODE
);
- bos.write( dataToEncode );
- success = true;
- } // end try
- catch( java.io.IOException e )
- {
-
- success = false;
- } // end catch: IOException
- finally
- {
- try{ bos.close(); } catch( Exception e ){}
- } // end finally
-
- return success;
- } // end encodeToFile
-
-
- /**
- * Convenience method for decoding data to a file.
- *
- * @param dataToDecode Base64-encoded data as a string
- * @param filename Filename for saving decoded data
- * @return <tt>true</tt> if successful, <tt>false</tt> otherwise
- *
- * @since 2.1
- */
- public static boolean decodeToFile( String dataToDecode, String filename )
- {
- boolean success = false;
- Base64.OutputStream bos = null;
- try
- {
- bos = new Base64.OutputStream(
- new java.io.FileOutputStream( filename ),
Base64.DECODE );
- bos.write( dataToDecode.getBytes( PREFERRED_ENCODING ) );
- success = true;
- } // end try
- catch( java.io.IOException e )
- {
- success = false;
- } // end catch: IOException
- finally
- {
- try{ bos.close(); } catch( Exception e ){}
- } // end finally
-
- return success;
- } // end decodeToFile
-
-
-
-
- /**
- * Convenience method for reading a base64-encoded
- * file and decoding it.
- *
- * @param filename Filename for reading encoded data
- * @return decoded byte array or null if unsuccessful
- *
- * @since 2.1
- */
- public static byte[] decodeFromFile( String filename )
- {
- byte[] decodedData = null;
- Base64.InputStream bis = null;
- try
- {
- // Set up some useful variables
- java.io.File file = new java.io.File( filename );
- byte[] buffer = null;
- int length = 0;
- int numBytes = 0;
-
- // Check for size of file
- if( file.length() > Integer.MAX_VALUE )
- {
- System.err.println( "File is too big for this convenience
method (" + file.length() + " bytes)." );
- return null;
- } // end if: file too big for int index
- buffer = new byte[ (int)file.length() ];
-
- // Open a stream
- bis = new Base64.InputStream(
- new java.io.BufferedInputStream(
- new java.io.FileInputStream( file ) ), Base64.DECODE );
-
- // Read until done
- while( ( numBytes = bis.read( buffer, length, 4096 ) ) >= 0 )
- length += numBytes;
-
- // Save in a variable to return
- decodedData = new byte[ length ];
- System.arraycopy( buffer, 0, decodedData, 0, length );
-
- } // end try
- catch( java.io.IOException e )
- {
- System.err.println( "Error decoding from file " + filename );
- } // end catch: IOException
- finally
- {
- try{ bis.close(); } catch( Exception e) {}
- } // end finally
-
- return decodedData;
- } // end decodeFromFile
-
-
-
- /**
- * Convenience method for reading a binary file
- * and base64-encoding it.
- *
- * @param filename Filename for reading binary data
- * @return base64-encoded string or null if unsuccessful
- *
- * @since 2.1
- */
- public static String encodeFromFile( String filename )
- {
- String encodedData = null;
- Base64.InputStream bis = null;
- try
- {
- // Set up some useful variables
- java.io.File file = new java.io.File( filename );
- byte[] buffer = new byte[ (int)(file.length() * 1.4) ];
- int length = 0;
- int numBytes = 0;
-
- // Open a stream
- bis = new Base64.InputStream(
- new java.io.BufferedInputStream(
- new java.io.FileInputStream( file ) ), Base64.ENCODE );
-
- // Read until done
- while( ( numBytes = bis.read( buffer, length, 4096 ) ) >= 0 )
- length += numBytes;
-
- // Save in a variable to return
- encodedData = new String( buffer, 0, length,
Base64.PREFERRED_ENCODING );
-
- } // end try
- catch( java.io.IOException e )
- {
- System.err.println( "Error encoding from file " + filename );
- } // end catch: IOException
- finally
- {
- try{ bis.close(); } catch( Exception e) {}
- } // end finally
-
- return encodedData;
- } // end encodeFromFile
-
-
-
-
- /* ******** I N N E R C L A S S I N P U T S T R E A M ******** */
-
-
-
- /**
- * A [EMAIL PROTECTED] Base64.InputStream} will read data from another
- * <tt>java.io.InputStream</tt>, given in the constructor,
- * and encode/decode to/from Base64 notation on the fly.
- *
- * @see Base64
- * @since 1.3
- */
- public static class InputStream extends java.io.FilterInputStream
- {
- private boolean encode; // Encoding or decoding
- private int position; // Current position in the buffer
- private byte[] buffer; // Small buffer holding converted data
- private int bufferLength; // Length of buffer (3 or 4)
- private int numSigBytes; // Number of meaningful bytes in the
buffer
- private int lineLength;
- private boolean breakLines; // Break lines at less than 80
characters
-
-
- /**
- * Constructs a [EMAIL PROTECTED] Base64.InputStream} in DECODE mode.
- *
- * @param in the <tt>java.io.InputStream</tt> from which to read data.
- * @since 1.3
- */
- public InputStream( java.io.InputStream in )
- {
- this( in, DECODE );
- } // end constructor
-
-
- /**
- * Constructs a [EMAIL PROTECTED] Base64.InputStream} in
- * either ENCODE or DECODE mode.
- * <p>
- * Valid options:<pre>
- * ENCODE or DECODE: Encode or Decode as data is read.
- * DONT_BREAK_LINES: don't break lines at 76 characters
- * (only meaningful when encoding)
- * <i>Note: Technically, this makes your encoding
non-compliant.</i>
- * </pre>
- * <p>
- * Example: <code>new Base64.InputStream( in, Base64.DECODE )</code>
- *
- *
- * @param in the <tt>java.io.InputStream</tt> from which to read data.
- * @param options Specified options
- * @see Base64#ENCODE
- * @see Base64#DECODE
- * @see Base64#DONT_BREAK_LINES
- * @since 2.0
- */
- public InputStream( java.io.InputStream in, int options )
- {
- super( in );
- this.breakLines = (options & DONT_BREAK_LINES) !=
DONT_BREAK_LINES;
- this.encode = (options & ENCODE) == ENCODE;
- this.bufferLength = encode ? 4 : 3;
- this.buffer = new byte[ bufferLength ];
- this.position = -1;
- this.lineLength = 0;
- } // end constructor
-
- /**
- * Reads enough of the input stream to convert
- * to/from Base64 and returns the next byte.
- *
- * @return next byte
- * @since 1.3
- */
- public int read() throws java.io.IOException
- {
- // Do we need to get data?
- if( position < 0 )
- {
- if( encode )
- {
- byte[] b3 = new byte[3];
- int numBinaryBytes = 0;
- for( int i = 0; i < 3; i++ )
- {
- try
- {
- int b = in.read();
-
- // If end of stream, b is -1.
- if( b >= 0 )
- {
- b3[i] = (byte)b;
- numBinaryBytes++;
- } // end if: not end of stream
-
- } // end try: read
- catch( java.io.IOException e )
- {
- // Only a problem if we got no data at all.
- if( i == 0 )
- throw e;
-
- } // end catch
- } // end for: each needed input byte
-
- if( numBinaryBytes > 0 )
- {
- encode3to4( b3, 0, numBinaryBytes, buffer, 0 );
- position = 0;
- numSigBytes = 4;
- } // end if: got data
- else
- {
- return -1;
- } // end else
- } // end if: encoding
-
- // Else decoding
- else
- {
- byte[] b4 = new byte[4];
- int i = 0;
- for( i = 0; i < 4; i++ )
- {
- // Read four "meaningful" bytes:
- int b = 0;
- do{ b = in.read(); }
- while( b >= 0 && DECODABET[ b & 0x7f ] <=
WHITE_SPACE_ENC );
-
- if( b < 0 )
- break; // Reads a -1 if end of stream
-
- b4[i] = (byte)b;
- } // end for: each needed input byte
-
- if( i == 4 )
- {
- numSigBytes = decode4to3( b4, 0, buffer, 0 );
- position = 0;
- } // end if: got four characters
- else if( i == 0 ){
- return -1;
- } // end else if: also padded correctly
- else
- {
- // Must have broken out from above.
- throw new java.io.IOException( "Improperly padded
Base64 input." );
- } // end
-
- } // end else: decode
- } // end else: get data
-
- // Got data?
- if( position >= 0 )
- {
- // End of relevant data?
- if( /*!encode &&*/ position >= numSigBytes )
- return -1;
-
- if( encode && breakLines && lineLength >= MAX_LINE_LENGTH )
- {
- lineLength = 0;
- return '\n';
- } // end if
- else
- {
- lineLength++; // This isn't important when decoding
- // but throwing an extra "if" seems
- // just as wasteful.
-
- int b = buffer[ position++ ];
-
- if( position >= bufferLength )
- position = -1;
-
- return b & 0xFF; // This is how you "cast" a byte that's
- // intended to be unsigned.
- } // end else
- } // end if: position >= 0
-
- // Else error
- else
- {
- // When JDK1.4 is more accepted, use an assertion here.
- throw new java.io.IOException( "Error in Base64 code reading
stream." );
- } // end else
- } // end read
-
-
- /**
- * Calls [EMAIL PROTECTED] #read()} repeatedly until the end of stream
- * is reached or <var>len</var> bytes are read.
- * Returns number of bytes read into array or -1 if
- * end of stream is encountered.
- *
- * @param dest array to hold values
- * @param off offset for array
- * @param len max number of bytes to read into array
- * @return bytes read into array or -1 if end of stream is encountered.
- * @since 1.3
- */
- public int read( byte[] dest, int off, int len ) throws
java.io.IOException
- {
- int i;
- int b;
- for( i = 0; i < len; i++ )
- {
- b = read();
-
- //if( b < 0 && i == 0 )
- // return -1;
-
- if( b >= 0 )
- dest[off + i] = (byte)b;
- else if( i == 0 )
- return -1;
- else
- break; // Out of 'for' loop
- } // end for: each byte read
- return i;
- } // end read
-
- } // end inner class InputStream
-
-
-
-
-
-
- /* ******** I N N E R C L A S S O U T P U T S T R E A M ******** */
-
-
-
- /**
- * A [EMAIL PROTECTED] Base64.OutputStream} will write data to another
- * <tt>java.io.OutputStream</tt>, given in the constructor,
- * and encode/decode to/from Base64 notation on the fly.
- *
- * @see Base64
- * @since 1.3
- */
- public static class OutputStream extends java.io.FilterOutputStream
- {
- private boolean encode;
- private int position;
- private byte[] buffer;
- private int bufferLength;
- private int lineLength;
- private boolean breakLines;
- private byte[] b4; // Scratch used in a few places
- private boolean suspendEncoding;
-
- /**
- * Constructs a [EMAIL PROTECTED] Base64.OutputStream} in ENCODE mode.
- *
- * @param out the <tt>java.io.OutputStream</tt> to which data will be
written.
- * @since 1.3
- */
- public OutputStream( java.io.OutputStream out )
- {
- this( out, ENCODE );
- } // end constructor
-
-
- /**
- * Constructs a [EMAIL PROTECTED] Base64.OutputStream} in
- * either ENCODE or DECODE mode.
- * <p>
- * Valid options:<pre>
- * ENCODE or DECODE: Encode or Decode as data is read.
- * DONT_BREAK_LINES: don't break lines at 76 characters
- * (only meaningful when encoding)
- * <i>Note: Technically, this makes your encoding
non-compliant.</i>
- * </pre>
- * <p>
- * Example: <code>new Base64.OutputStream( out, Base64.ENCODE )</code>
- *
- * @param out the <tt>java.io.OutputStream</tt> to which data will be
written.
- * @param options Specified options.
- * @see Base64#ENCODE
- * @see Base64#DECODE
- * @see Base64#DONT_BREAK_LINES
- * @since 1.3
- */
- public OutputStream( java.io.OutputStream out, int options )
- {
- super( out );
- this.breakLines = (options & DONT_BREAK_LINES) !=
DONT_BREAK_LINES;
- this.encode = (options & ENCODE) == ENCODE;
- this.bufferLength = encode ? 3 : 4;
- this.buffer = new byte[ bufferLength ];
- this.position = 0;
- this.lineLength = 0;
- this.suspendEncoding = false;
- this.b4 = new byte[4];
- } // end constructor
-
-
- /**
- * Writes the byte to the output stream after
- * converting to/from Base64 notation.
- * When encoding, bytes are buffered three
- * at a time before the output stream actually
- * gets a write() call.
- * When decoding, bytes are buffered four
- * at a time.
- *
- * @param theByte the byte to write
- * @since 1.3
- */
- public void write(int theByte) throws java.io.IOException
- {
- // Encoding suspended?
- if( suspendEncoding )
- {
- super.out.write( theByte );
- return;
- } // end if: supsended
-
- // Encode?
- if( encode )
- {
- buffer[ position++ ] = (byte)theByte;
- if( position >= bufferLength ) // Enough to encode.
- {
- out.write( encode3to4( b4, buffer, bufferLength ) );
-
- lineLength += 4;
- if( breakLines && lineLength >= MAX_LINE_LENGTH )
- {
- out.write( NEW_LINE );
- lineLength = 0;
- } // end if: end of line
-
- position = 0;
- } // end if: enough to output
- } // end if: encoding
-
- // Else, Decoding
- else
- {
- // Meaningful Base64 character?
- if( DECODABET[ theByte & 0x7f ] > WHITE_SPACE_ENC )
- {
- buffer[ position++ ] = (byte)theByte;
- if( position >= bufferLength ) // Enough to output.
- {
- int len = Base64.decode4to3( buffer, 0, b4, 0 );
- out.write( b4, 0, len );
- //out.write( Base64.decode4to3( buffer ) );
- position = 0;
- } // end if: enough to output
- } // end if: meaningful base64 character
- else if( DECODABET[ theByte & 0x7f ] != WHITE_SPACE_ENC )
- {
- throw new java.io.IOException( "Invalid character in
Base64 data." );
- } // end else: not white space either
- } // end else: decoding
- } // end write
-
-
-
- /**
- * Calls [EMAIL PROTECTED] #write(int)} repeatedly until
<var>len</var>
- * bytes are written.
- *
- * @param theBytes array from which to read bytes
- * @param off offset for array
- * @param len max number of bytes to read into array
- * @since 1.3
- */
- public void write( byte[] theBytes, int off, int len ) throws
java.io.IOException
- {
- // Encoding suspended?
- if( suspendEncoding )
- {
- super.out.write( theBytes, off, len );
- return;
- } // end if: supsended
-
- for( int i = 0; i < len; i++ )
- {
- write( theBytes[ off + i ] );
- } // end for: each byte written
-
- } // end write
-
-
-
- /**
- * Method added by PHIL. [Thanks, PHIL. -Rob]
- * This pads the buffer without closing the stream.
- */
- public void flushBase64() throws java.io.IOException
- {
- if( position > 0 )
- {
- if( encode )
- {
- out.write( encode3to4( b4, buffer, position ) );
- position = 0;
- } // end if: encoding
- else
- {
- throw new java.io.IOException( "Base64 input not properly
padded." );
- } // end else: decoding
- } // end if: buffer partially full
-
- } // end flush
-
-
- /**
- * Flushes and closes (I think, in the superclass) the stream.
- *
- * @since 1.3
- */
- public void close() throws java.io.IOException
- {
- // 1. Ensure that pending characters are written
- flushBase64();
-
- // 2. Actually close the stream
- // Base class both flushes and closes.
- super.close();
-
- buffer = null;
- out = null;
- } // end close
-
-
-
- /**
- * Suspends encoding of the stream.
- * May be helpful if you need to embed a piece of
- * base640-encoded data in a stream.
- *
- * @since 1.5.1
- */
- public void suspendEncoding() throws java.io.IOException
- {
- flushBase64();
- this.suspendEncoding = true;
- } // end suspendEncoding
-
-
- /**
- * Resumes encoding of the stream.
- * May be helpful if you need to embed a piece of
- * base640-encoded data in a stream.
- *
- * @since 1.5.1
- */
- public void resumeEncoding()
- {
- this.suspendEncoding = false;
- } // end resumeEncoding
-
-
-
- } // end inner class OutputStream
-
-
-} // end class Base64
Deleted: trunk/clients/Javer2/src/org/haverdev/haver/Callback.java
===================================================================
--- trunk/clients/Javer2/src/org/haverdev/haver/Callback.java 2005-06-10
20:43:42 UTC (rev 762)
+++ trunk/clients/Javer2/src/org/haverdev/haver/Callback.java 2005-06-11
18:17:46 UTC (rev 763)
@@ -1,87 +0,0 @@
-/*
- * Callback.java
- *
- * Created on May 21, 2005, 9:39 PM
- */
-
-package org.haverdev.haver;
-import java.io.IOException;
-
-/**
- *
- * @author bdonlan
- */
-public abstract class Callback implements java.util.EventListener {
- /**
- * Called when a connection to the server is established but before
handshaking
- * occurs.
- * @param source haver.Client instance associated with this event
- * @throws java.io.IOException
- */
- public void onConnect(Client source) throws Throwable {}
- /**
- * Called when a connection attempt fails.
- * @param source haver.Client instance associated with this event
- * @param e IOException which caused the connection failure
- * @throws java.io.IOException
- */
- public void onConnectFailed(Client source, java.io.IOException e) throws
Throwable {}
- /**
- * Called when an established connection is lost
- * @param source haver.Client instance associated with this event
- * @param e Exception associated with the connection loss, or null if
connection loss did
- * not have an associated exception (e.g., connection broken)
- * @throws java.io.IOException
- */
- public void onDisconnected(Client source, java.io.IOException e) throws
Throwable {}
- /**
- * Called when a message is received from the server
- * @param source haver.Client instance associated with this event
- * @param args Arguments of the message
- * @throws java.io.IOException
- */
- public void onIncomingLine(Client source, String[] args) throws Throwable
{}
- /**
- * Called when a message is sent to the server
- * @param source haver.Client instance associated with this event
- * @param args Arguments of the message
- * @throws java.io.IOException
- */
- public void onOutgoingLine(Client source, String[] args) throws Throwable
{}
- /**
- * Called when the server requires identification
- * @param source haver.Client instance associated with this event
- * @throws java.io.IOException
- */
- public void onNeedIdent(Client source) throws Throwable {}
- /**
- * Called when the name given by the client has been accepted
- * @param source haver.Client instance associated with this event
- * @param name Name that was accepted by the server
- * @throws java.io.IOException
- */
- public void onAccept(Client source, String name) throws Throwable {}
-
- /**
- * Called when the server responds to a listing request
- * @param source haver.Client instance associated with this event
- * @param channel Channel that was listed
- * @param namespace Namespace of objects listed
- * @param list List of objects held by the channel
- * @throws java.io.IOException
- */
- public void onReceivedList(Client source, String channel, String
namespace, String[] list) throws Throwable {}
-
- public void onPublicMessage(Client source, String channel, String from,
String type, String[] args) throws Throwable {}
-
- public void onPrivateMessage(Client source, String from, String type,
String[] args) throws Throwable {}
-
- public void onJoin(Client source, String channel, String who) throws
Throwable {}
-
- public void onPart(Client source, String channel, String who) throws
Throwable {}
-
- public void onQuit(Client source, String who, String type, String detail)
throws Throwable {}
-
- // XXX: this is a hack and should not be used in apps
- void onFail(Client source, String[] args) throws Throwable {};
-}
Deleted: trunk/clients/Javer2/src/org/haverdev/haver/Client.java
===================================================================
--- trunk/clients/Javer2/src/org/haverdev/haver/Client.java 2005-06-10
20:43:42 UTC (rev 762)
+++ trunk/clients/Javer2/src/org/haverdev/haver/Client.java 2005-06-11
18:17:46 UTC (rev 763)
@@ -1,911 +0,0 @@
-/*
- * Client.java
- *
- * Created on May 21, 2005, 8:48 PM
- */
-
-package org.haverdev.haver;
-import java.io.*;
-import java.util.*;
-import java.net.*;
-import java.lang.reflect.*;
-
-/**
- * A Haver client class
- * @author bdonlan
- */
-public class Client {
-
-
- HashSet listening = new java.util.HashSet();
- CallbackDist dist;
- Socket theSocket = null;
- boolean connecting = false;
- Thread io = null;
- Client self = this;
- PrintWriter writer = null;
- BufferedReader reader = null;
- NonblockingOutputStream s;
- String name = null;
-
- static final String[] greeting = {"HAVER", "haver.Client/0.00"};
-
- String host;
- int port;
-
- public String getName() {
- return name;
- }
-
- /**
- * Mutable boolean flag
- */
- class Flag {
- public boolean ok = true;
- }
-
- /** Creates a new instance of Client */
- public Client() {
- dist = new CallbackDist(listening);
- }
-
- /**
- * Reverses Haver escaping.
- * @param val String to unescape
- * @return The unescaped string
- */
- protected static final String unescape(String val) {
- //if (val != null) return val;
- StringBuffer out = new StringBuffer();
- int pin = 0;
- int nextEsc = -1;
- while (-1 != (nextEsc = val.indexOf("\033", pin))) {
- out.append(val.substring(0, nextEsc - 1));
- switch (val.charAt(nextEsc + 1)) {
- case 'r':
- out.append('\r');
- break;
- case 'n':
- out.append('\n');
- break;
- case 'e':
- out.append('\033');
- break;
- case 't':
- out.append('\t');
- break;
- default:
- out.append(val.charAt(nextEsc + 1));
- break;
- }
- pin = nextEsc + 2;
- }
- out.append(val.substring(pin));
- return out.toString();
- }
-
- /**
- * Escapes a string according to the Haver protocol
- * @param val String to escape
- * @return Escaped string
- */
- protected static final String escape(String val) {
- return val.replaceAll("\033", "\033e")
- .replaceAll("\n", "\033n")
- .replaceAll("\r", "\033r")
- .replaceAll("\t", "\033t");
- }
-
- /**
- * Decodes a raw line from the Haver protocol.
- * @param inLine Line to decode. May end in '\r\n' but must only be one
line.
- * @return An array containing the unescaped arguments of the line.
- */
- protected static final String[] decodeLine(String inLine) {
- inLine = inLine.replaceAll("[\n\r]", ""); // We'll assume you only
passed one
- // line in.
- String[] args = inLine.split("\t");
- for (int i = 0; i < args.length; i++) {
- args[i] = unescape(args[i]);
- }
- return args;
- }
-
- /**
- * Encodes a set of arguments for line transmission
- * @param args Unescaped arguments to encode
- * @return Escaped and joined line ready for transmission, complete with
ending \r\n
- */
- protected static final String encodeLine(String[] args) {
- StringBuffer out = new StringBuffer();
- for (int i = 0; i < args.length; i++) {
- if (i != 0)
- out.append("\t");
- out.append(escape(args[i]));
- }
- out.append("\r\n");
- return out.toString();
- }
-
- /**
- * Internal class for distributing callback events to all listeners
- */
- protected class CallbackDist extends Callback {
- java.util.HashSet listeners;
-
- /**
- *
- * @param l Listener set
- */
- public CallbackDist(HashSet l) {
- listeners = l;
- }
-
- /**
- * Returns a constant iterator over the current listeners, which will
not be
- * affected by concurrency issues.
- */
- protected Iterator iterator() {
- // Prevent concurrency issues
- synchronized (listeners) {
- return ((HashSet)listeners.clone()).iterator();
- }
- }
-
- public void onDisconnected(Client source, IOException e) throws
IOException {
- try {reader.close();} catch (Throwable t) {}
- try {writer.close();} catch (Throwable t) {}
- try {theSocket.close();} catch (Throwable t) {}
- reader = null;
- writer = null;
- theSocket = null;
- io = null;
-
- Iterator i = iterator();
- while (i.hasNext()) {
- Callback c = (Callback)i.next();
- try {
- c.onDisconnected(source, e);
- } catch (Throwable t) {
- t.printStackTrace();
- }
- }
-
- }
-
- public void onConnectFailed(Client source, IOException e) throws
IOException {
- Iterator i = iterator();
- while (i.hasNext()) {
- Callback c = (Callback)i.next();
- try {
- c.onConnectFailed(source, e);
- } catch (Throwable t) {
- t.printStackTrace();
- }
- }
- }
-
- public void onConnect(Client source) throws IOException {
- // Konnichiha, saaba-san!
- sendLine(greeting);
-
- Iterator i = iterator();
- while (i.hasNext()) {
- Callback c = (Callback)i.next();
- try {
- c.onConnect(source);
- } catch (IOException e) {
- throw e;
- } catch (Throwable e) {
- e.printStackTrace();
- }
- }
- }
-
- public void onOutgoingLine(Client source, String[] args) throws
IOException {
- Iterator i = iterator();
- while (i.hasNext()) {
- Callback c = (Callback)i.next();
- try {
- c.onOutgoingLine(source, args);
- } catch (IOException e) {
- throw e;
- } catch (Throwable e) {
- e.printStackTrace();
- }
- }
- }
-
- public void onIncomingLine(Client source, String[] args) throws
IOException {
- Iterator i = iterator();
- while (i.hasNext()) {
- Callback c = (Callback)i.next();
- try {
- c.onIncomingLine(source, args);
- } catch (IOException e) {
- throw e;
- } catch (Throwable e) {
- e.printStackTrace();
- }
- }
- }
-
- public void onNeedIdent(Client source) throws IOException {
- Iterator i = iterator();
- while (i.hasNext()) {
- Callback c = (Callback)i.next();
- try {
- c.onNeedIdent(source);
- } catch (IOException e) {
- throw e;
- } catch (Throwable e) {
- e.printStackTrace();
- }
- }
- }
-
- public void onAccept(Client source, String name) throws IOException {
- Iterator i = iterator();
- while (i.hasNext()) {
- Callback c = (Callback)i.next();
- try {
- c.onAccept(source, name);
- } catch (IOException e) {
- throw e;
- } catch (Throwable e) {
- e.printStackTrace();
- }
- }
- }
-
- public void onReceivedList(Client source, String channel, String
namespace, String[] list) throws IOException {
- Iterator i = iterator();
- while (i.hasNext()) {
- Callback c = (Callback)i.next();
- try {
- c.onReceivedList(source, channel, namespace, list);
- } catch (IOException e) {
- throw e;
- } catch (Throwable e) {
- e.printStackTrace();
- }
- }
- }
-
- public void onPublicMessage(Client source, String channel, String
from, String type, String[] args) throws IOException {
- Iterator i = iterator();
- while (i.hasNext()) {
- Callback c = (Callback)i.next();
- try {
- c.onPublicMessage(source, channel, from, type, args);
- } catch (IOException e) {
- throw e;
- } catch (Throwable e) {
- e.printStackTrace();
- }
- }
- }
-
- public void onPrivateMessage(Client source, String from, String type,
String[] args) throws IOException {
- Iterator i = iterator();
- while (i.hasNext()) {
- Callback c = (Callback)i.next();
- try {
- c.onPrivateMessage(source, from, type, args);
- } catch (IOException e) {
- throw e;
- } catch (Throwable e) {
- e.printStackTrace();
- }
- }
- }
-
- public void onQuit(Client source, String who, String type, String
detail) throws IOException {
- Iterator i = iterator();
- while (i.hasNext()) {
- Callback c = (Callback)i.next();
- try {
- c.onQuit(source, who, type, detail);
- } catch (IOException e) {
- throw e;
- } catch (Throwable e) {
- e.printStackTrace();
- }
- }
- }
-
- public void onPart(Client source, String channel, String who) throws
IOException {
- Iterator i = iterator();
- while (i.hasNext()) {
- Callback c = (Callback)i.next();
- try {
- c.onPart(source, channel, who);
- } catch (IOException e) {
- throw e;
- } catch (Throwable e) {
- e.printStackTrace();
- }
- }
- }
-
- public void onJoin(Client source, String channel, String who) throws
IOException {
- Iterator i = iterator();
- while (i.hasNext()) {
- Callback c = (Callback)i.next();
- try {
- c.onJoin(source, channel, who);
- } catch (IOException e) {
- throw e;
- } catch (Throwable e) {
- e.printStackTrace();
- }
- }
- }
-
- void onFail(Client source, String[] args) throws IOException {
- Iterator i = iterator();
- while (i.hasNext()) {
- Callback c = (Callback)i.next();
- try {
- c.onFail(source, args);
- } catch (IOException e) {
- throw e;
- } catch (Throwable e) {
- e.printStackTrace();
- }
- }
- }
-
- }
-
- /**
- * Entry point for IO thread; connects to specified host and port.
- * @param host Hostname to connect to
- * @param port Port number to connect to
- */
- protected void run(String host, int port) {
- synchronized (this) {
- if (Thread.currentThread() != io) {
- throw new IllegalStateException("Client.run called outside io
thread");
- }
- }
- Thread.currentThread().setName("haver.Client input thread");
- try {
- Socket mySock = new Socket(host, port);
- theSocket = mySock;
- } catch (IOException e) {
- try {
- io = null;
- dist.onConnectFailed(this, e);
- } catch (IOException e2) {}
- return;
- }
- run();
- }
-
- protected void run() {
- try {
- writer = new PrintWriter
- (new OutputStreamWriter
- (s = new NonblockingOutputStream
- (new BufferedOutputStream
- (theSocket.getOutputStream()))));
- s.setAutoFlush(true);
- reader = new BufferedReader
- (new InputStreamReader
- (theSocket.getInputStream()));
- dist.onConnect(this);
- ioLoop(new Flag());
- } catch (IOException e) {
- try {
- // XXX: may be called more than once
- dist.onDisconnected(this, e);
- } catch (IOException e2) {
- }
- return;
- }
- }
-
- /**
- * Sends a command to the server.
- * @param args Arguments of the line to send
- * @throws java.io.IOException
- */
- protected synchronized void sendLine(String[] args) {
- if (writer != null) {
- String l = encodeLine(args);
- System.out.print("C: " + l);
- writer.print(l);
- writer.flush();
- }
- }
-
- protected synchronized void killConnection() {
- // Kill the connection. Don't ask questions, just do it.
- try {
- writer.flush();
- } catch (Throwable t) {}
- try {
- theSocket.close();
- } catch (Throwable t) {}
- }
-
- /**
- * Main IO loop
- * @param f Termination flag; ioLoop will return when f.ok is false
- * @throws java.io.IOException
- */
- protected void ioLoop(Flag f) throws IOException {
- while (io != null && f.ok) {
- String l = reader.readLine();
- if (l == null) {
- dist.onDisconnected(this, null);
- return;
- }
- System.out.println("S: " + l);
- String[] args = decodeLine(l);
- dist.onIncomingLine(this, args);
- dispatch(args);
- }
- }
-
- /**
- * Connect to a given host asynchronously.
- * @param host Hostname to connect to
- * @param port Port number to connect to
- * @throws java.lang.IllegalStateException Thrown if the client is already
connected or connecting.
- */
- public synchronized void connect(String host, int port)
- throws IllegalStateException
- {
- if (io != null && io.isAlive()) {
- throw new IllegalStateException("Already connecting");
- }
- name = null;
- theSocket = null;
- this.host = host;
- this.port = port;
- io = new Thread(new Runnable() {
- public void run() {
- self.run(self.host, self.port);
- }
- });
- io.start();
- }
-
- public synchronized void connect(Socket s) throws IllegalStateException
- {
- if (io != null && io.isAlive()) {
- throw new IllegalStateException("Already connecting");
- }
- name = null;
- theSocket = s;
- io = new Thread(new Runnable() {
- public void run() {
- self.run();
- }
- });
- io.start();
- }
-
- /**
- * Base class for event listeners for synchronous methods
- */
- protected class SyncMonitor extends Callback {
- /**
- * The exception which caused the operation to fail, or null if none
- */
- private IOException fail = null;
- /**
- * Flag for ioLoop() termination
- */
- private Flag flag = new Flag();
-
- /**
- * Return value
- */
- private Object ret = null;
-
- protected synchronized void fail(IOException e) {
- fail = e;
- done(null);
- }
-
- public SyncMonitor() {
- addNotify(this);
- }
-
- /**
- * Signal completion of the synchronous event
- */
- protected synchronized void done(Object ret) {
- if (!flag.ok)
- throw new IllegalStateException("Already finished!");
- removeNotify(this);
- flag.ok = false;
- this.ret = ret;
- notifyAll();
- }
-
- public synchronized void onDisconnected(Client source, IOException e) {
- if (e == null)
- e = new IOException("Disconnected unexpectedly");
- fail(e);
- }
-
- public synchronized void onConnectFailed(Client source, IOException e)
{
- fail(e);
- }
-
- /**
- * Wait until the synchronous event completes
- * @throws java.io.IOException
- */
- public synchronized Object block() throws IOException,
InterruptedException {
- if (Thread.currentThread() == io) {
- ioLoop(flag);
- } else {
- try {
- wait();
- } catch (InterruptedException e) {
- removeNotify(this);
- throw e;
- }
- }
- if (fail != null)
- throw fail;
- return ret;
- }
- }
-
- /**
- * Event listener for syncConnect()
- */
- protected class ConnectMonitor extends SyncMonitor {
- /**
- * true if connection completed successfully
- */
- public boolean done = false;
- /**
- * Name for login
- */
- public String name;
-
- public ConnectMonitor(String name) {
- this.name = name;
- }
-
- public void onNeedIdent(Client source) throws IOException {
- source.ident(name);
- }
-
- public void onAccept(Client source, String name) {
- done(null);
- }
-
- void onFail(Client source, String[] args) {
- // XXX
- fail(new IOException("Something broke: " + args[2]));
- }
- }
-
- /**
- * Connects to a host synchronously.
- * @param host Hostname to connect to.
- * @param port Port to connect to.
- * @param name Name to use upon connect.
- * @throws java.io.IOException Thrown if an IO exception occurs at any
point during the connect, or if the
- * connection is lost.
- */
- public void syncConnect(String host, int port, String name) throws
IOException, InterruptedException {
- ConnectMonitor m = new ConnectMonitor(name);
- connect(host, port);
- m.block();
- }
-
- public void syncConnect(Socket s, String name) throws IOException,
InterruptedException {
- ConnectMonitor m = new ConnectMonitor(name);
- connect(s);
- m.block();
- }
-
- /**
- * Adds a callback to notify when an event occurs
- * @param c Callback class to add
- */
- public void addNotify(Callback c) {
- synchronized (listening) {
- listening.add(c);
- }
- }
-
- /**
- * Removes a callback class from the notify list
- * @param c Callback to remove
- */
- public void removeNotify(Callback c) {
- synchronized (listening) {
- listening.remove(c);
- }
- }
-
- /**
- * Dispatch the passed line to the appropriate internal handler (if
present)
- * @param args Arguments of line, including command.
- * @throws java.io.IOException
- */
- protected void dispatch(String[] args) throws IOException {
- String cmd = args[0].toUpperCase();
- Class me = this.getClass();
- try {
- Class[] params = {args.getClass()};
- Method m = me.getDeclaredMethod("handle_" + cmd, params);
- Object[] args2 = {args};
- m.invoke(this, args2);
- } catch (InvocationTargetException e) {
- Throwable thingy = e.getTargetException();
- if (thingy instanceof IOException) {
- throw (IOException) thingy;
- }
- thingy.printStackTrace();
- }
- catch (NoSuchMethodException e) {} // unhandled server event
- catch (IllegalAccessException e) {
- // eep!
- e.printStackTrace();
- }
- }
-
- /**
- * Handler for server HAVER message
- * @param args Arguments of message
- * @throws java.io.IOException
- */
- protected void handle_HAVER(String[] args) throws IOException {
- dist.onNeedIdent(this);
- }
-
- /**
- * Identify with the given name
- * @param name Name to identify with
- * @throws java.io.IOException
- */
- public void ident(String name) throws IOException {
- String[] l = {"IDENT", name};
- sendLine(l);
- }
-
- /**
- * Handler for server HELLO message
- * @param args Arguments of message
- * @throws java.io.IOException
- */
- protected void handle_HELLO(String[] args) throws IOException {
- name = args[1];
- dist.onAccept(this, args[1]);
- }
-
- /**
- * Handler for server PING message
- * @param args Arguments of message
- * @throws java.io.IOException
- */
- protected void handle_PING(String[] args) throws IOException {
- args[0] = "PONG";
- sendLine(args);
- }
-
- /**
- * Request a listing of the contents of a channel, asynchronously.
- * @param channel Channel to list
- * @param namespace Namespace to filter results by
- * @throws java.io.IOException
- */
- public void requestList(String channel, String namespace) {
- String[] cmd = {"LIST", channel, namespace};
- sendLine(cmd);
- }
-
- /**
- * Handler for server LIST message
- * @param args Arguments of message
- * @throws java.io.IOException
- */
- protected void handle_LIST(String[] args) throws IOException {
- String[] list = new String[args.length - 3];
- System.arraycopy(args, 3, list, 0, args.length - 3);
- String channel = args[1];
- String namespace = args[2];
-
- dist.onReceivedList(this, channel, namespace, list);
- }
-
- /**
- * Event listener for syncList()
- */
- protected class ListMonitor extends SyncMonitor {
- String channel;
- String namespace;
-
- public ListMonitor(String channel, String namespace) {
- this.channel = channel;
- this.namespace = namespace;
- }
-
- public synchronized void onReceivedList(Client source, String channel,
String namespace, String[] list) {
- if (channel.equals(this.channel) &&
- namespace.equals(this.namespace))
- {
- done(list);
- }
- }
- void onFail(Client source, String[] args) {
- // XXX
- if (args.length >= 4 && args[1].equals("LIST") &&
args[3].equals(channel))
- fail(new IOException("Something broke: " + args[2]));
- }
- }
-
- /**
- * Synchronously list a channel.
- * @param channel Channel to list
- * @param namespace Namespace to restrict results by
- * @throws java.io.IOException If an IO exception occurs while this
function is being processed, it will be
- * rethrown from here.
- * @return An array containing the elements of the given namespace, in the
specified
- * channel
- */
- public String[] syncList(String channel, String namespace) throws
IOException, InterruptedException {
- ListMonitor m = new ListMonitor(channel, namespace);
- requestList(channel, namespace);
- return (String[])m.block();
- }
-
- protected void handle_IN(String[] args) throws IOException {
- if (args.length < 4) {
- // XXX: exception?
- System.err.println("Short IN message from haver server");
- return;
- }
- String channel = args[1];
- String from = args[2];
- String type = args[3];
- String[] margs = new String[args.length - 4];
- System.arraycopy(args, 4, margs, 0, args.length - 4);
-
- dist.onPublicMessage(this, channel, from, type, margs);
- }
-
- public void sendPublicMessage(String channel, String type, String[] margs)
{
- String[] cmd = new String[margs.length + 3];
- cmd[0] = "IN";
- cmd[1] = channel;
- cmd[2] = type;
- System.arraycopy(margs, 0, cmd, 3, margs.length);
- sendLine(cmd);
- }
-
- public void sendPublicMessage(String channel, String type, String arg) {
- String[] args = {arg};
- sendPublicMessage(channel, type, args);
- }
-
- protected void handle_FROM(String[] args) throws IOException {
- if (args.length < 3) {
- // XXX: exception?
- System.err.println("Short FROM message from haver server");
- return;
- }
- String user = args[1];
- String type = args[2];
- String margs[] = new String[args.length - 3];
- System.arraycopy(args, 3, margs, 0, margs.length);
-
- dist.onPrivateMessage(this, user, type, margs);
- }
-
- public void sendPrivateMessage (String target, String type, String[]
margs) {
- String[] args = new String[margs.length + 3];
- args[0] = "TO";
- args[1] = target;
- args[2] = type;
- System.arraycopy(margs, 0, args, 3, margs.length);
- sendLine(args);
- }
-
- public void sendPrivateMessage (String target, String type, String arg) {
- String[] args = {arg};
- sendPrivateMessage(target, type, args);
- }
-
- public void handle_JOIN(String[] args) throws IOException {
- String channel = args[1];
- String user = args[2];
- dist.onJoin(this, channel, user);
- }
-
- public void handle_PART(String[] args) throws IOException {
- String channel = args[1];
- String user = args[2];
- dist.onPart(this, channel, user);
- }
-
- public void handle_QUIT(String[] args) throws IOException {
- String who = args[1];
- String type = args[2];
- String detail = args.length >= 4 ? args[3] : "";
- dist.onQuit(this, who, type, detail);
- }
-
- public void sendJoin(String channel) {
- String[] cmd = {"JOIN", channel};
- sendLine(cmd);
- }
-
- protected class JoinMonitor extends SyncMonitor {
- String channel;
-
- public JoinMonitor (String channel) {
- this.channel = channel;
- }
-
- public void onJoin(Client from, String channel, String who) {
- if (channel.equals(this.channel) && who.equals(name)) {
- this.done(null);
- }
- }
-
- void onFail(Client source, String[] args) {
- // XXX
- if (args.length >= 4 && args[1].equals("JOIN") &&
args[3].equals(channel))
- fail(new IOException("Something broke: " + args[2]));
- }
- }
-
- public void syncJoin(String channel) throws IOException,
InterruptedException {
- JoinMonitor m = new JoinMonitor(channel);
- sendJoin(channel);
- m.block();
- }
-
- public void sendPart(String channel) {
- String[] cmd = {"PART", channel};
- sendLine(cmd);
- }
-
- protected class PartMonitor extends SyncMonitor {
- String channel;
-
- public PartMonitor (String channel) {
- this.channel = channel;
- }
-
- public void onPart(Client from, String channel, String who) {
- if (channel.equals(this.channel) && who.equals(name)) {
- this.done(null);
- }
- }
-
- void onFail(Client source, String[] args) {
- // XXX
- if (args.length >= 4 && args[1].equals("PART") &&
args[3].equals(channel))
- fail(new IOException("Something broke: " + args[2]));
- }
- }
-
- public void syncPart(String channel) throws IOException,
InterruptedException {
- PartMonitor m = new PartMonitor(channel);
- sendPart(channel);
- m.block();
- }
-
- public synchronized void disconnect() {
- killConnection();
- }
-
- public void handle_FAIL(String[] args) throws IOException {
- // XXX
- dist.onFail(this, args);
- }
-
-}
Modified: trunk/clients/Javer2/src/org/haverdev/haver/server/AcceptLoop.java
===================================================================
--- trunk/clients/Javer2/src/org/haverdev/haver/server/AcceptLoop.java
2005-06-10 20:43:42 UTC (rev 762)
+++ trunk/clients/Javer2/src/org/haverdev/haver/server/AcceptLoop.java
2005-06-11 18:17:46 UTC (rev 763)
@@ -9,6 +9,7 @@
import java.net.*;
import java.util.*;
import org.apache.log4j.Logger;
+import org.haverdev.common.*;
/**
*
@@ -21,7 +22,7 @@
public static void startListening() throws Throwable {
String[] ports =
-
Misc.optionSplit(System.getProperty("org.haverdev.haver.server.AcceptLoop.listenPorts"));
+
HaverEncoding.optionSplit(System.getProperty("org.haverdev.haver.server.AcceptLoop.listenPorts"));
for (int i = 0; i < ports.length; i++) {
int port = Integer.decode(ports[i]).intValue();
try {
Modified: trunk/clients/Javer2/src/org/haverdev/haver/server/AuthProvider.java
===================================================================
--- trunk/clients/Javer2/src/org/haverdev/haver/server/AuthProvider.java
2005-06-10 20:43:42 UTC (rev 762)
+++ trunk/clients/Javer2/src/org/haverdev/haver/server/AuthProvider.java
2005-06-11 18:17:46 UTC (rev 763)
@@ -14,7 +14,9 @@
*
* @author bdonlan
*/
-public interface AuthProvider {
+public interface AuthProvider extends UserCommandHandler {
+ public boolean isAvailable();
public String getProtocolName();
- public void initiateConversation(UserInfo info, UserConnection conn,
AuthCallback cb);
+ public void initiateConversation(AuthCallback cb);
+ public void reset();
}
Modified:
trunk/clients/Javer2/src/org/haverdev/haver/server/AuthenticationProcess.java
===================================================================
---
trunk/clients/Javer2/src/org/haverdev/haver/server/AuthenticationProcess.java
2005-06-10 20:43:42 UTC (rev 762)
+++
trunk/clients/Javer2/src/org/haverdev/haver/server/AuthenticationProcess.java
2005-06-11 18:17:46 UTC (rev 763)
@@ -13,43 +13,95 @@
import java.util.*;
import org.haverdev.haver.server.exceptions.*;
import java.lang.reflect.*;
+import org.haverdev.common.*;
/**
*
* @author bdonlan
*/
public class AuthenticationProcess extends UserCommandWrapper implements
AuthCallback {
-
+
static final Logger log = Logger.getLogger(AuthenticationProcess.class);
UserConnection conn = null;
UserInfo info = null;
- HashSet methodset = new HashSet();
+ HashMap methods = new HashMap();
+ MergingContext ctx = new MergingContext();
+ UserCommandHandler authctx = null;
+
+ AuthProvider getProvider(String proto, UserConnection conn, UserInfo info)
{
+ try {
+ String delegate = System.getProperty("haver.auth." + proto +
".delegate");
+ Class delegateClass = Class.forName(delegate);
+
+ Class[] prototype = { String.class, UserConnection.class,
UserInfo.class };
+ Object[] args = { proto, conn, info };
+
+ Constructor c = delegateClass.getConstructor(prototype);
+ AuthProvider instance = (AuthProvider) c.newInstance(args);
+ if (instance.isAvailable())
+ return instance;
+ }
+ catch (ClassNotFoundException e) {
+ log.error("Unable to load provider class for " + proto, e);
+ }
+ catch (NoSuchMethodException e) {
+ log.error("Provider for " + proto + " is missing proper
constructor", e);
+ }
+ catch (InstantiationException e) {
+ log.error("Error instantiating provider for " + proto, e);
+ }
+ catch (ClassCastException e) {
+ log.error("Provider for " + proto + " does not implement requisite
interfaces", e);
+ }
+ catch (IllegalAccessException e) {
+ log.error("Illegal access exception initializing provider for " +
proto, e);
+ }
+ catch (InvocationTargetException e) {
+ log.error("Exception while initializing provider for " + proto, e);
+ }
+ return null;
+ }
+
/** Creates a new instance of AuthenticationProcess */
public AuthenticationProcess(UserConnection conn, UserInfo info) {
+ ctx.add(this);
+
this.conn = conn;
this.info = info;
+ }
+
+ public void start() throws PropagatedException {
if (!Boolean.parseBoolean(info.getProperty("authenticated", "false")))
{
accept();
return;
}
- String[] methods =
Misc.optionSplit(System.getProperty("haver.auth.methods"));
+ if (!conn.features.contains("auth"))
+ throw new AuthNotSupportedException(info.getName());
- for (int i = 0; i < methods.length; i++)
- methodset.add(methods[i]);
+ String[] methods =
HaverEncoding.optionSplit(System.getProperty("haver.auth.methods"));
+ for (int i = 0; i < methods.length; i++) {
+ AuthProvider provider = getProvider(methods[i], conn, info);
+ if (provider != null)
+ this.methods.put(methods[i], provider);
+ }
+
String[] msg = new String[methods.length + 1];
msg[0] = "AUTH:TYPE";
System.arraycopy(methods, 0, msg, 1, methods.length);
conn.sendLine(msg);
- conn.context = this;
}
+ public UserCommandHandler getContext() {
+ return ctx;
+ }
+
public void accept() {
try {
conn.entity = new UserEntity(info);
@@ -77,27 +129,22 @@
public void handleCommand(String[] cmd) throws PropagatedException {
if (!cmd[0].equals("AUTH:TYPE"))
throw new UnknownClientCommandException(cmd);
+
+ if (authctx != null) {
+ ctx.remove(authctx);
+ authctx = null;
+ }
+
String method = cmd[1];
- if (!methodset.contains(method))
+ if (!methods.containsKey(method))
throw new UnknownAuthTypeException(method);
- try {
- String delegatename = System.getProperty("haver.auth." + method +
".delegate");
- Class delegate = Class.forName(delegatename);
-
- Object[] args = { method };
- Class[] prototype = { method.getClass() };
-
- Constructor cons = delegate.getConstructor(prototype);
- Object instance = cons.newInstance(args);
-
- AuthProvider provider = (AuthProvider)instance;
-
- provider.initiateConversation(info, conn, this);
- }
- catch (Exception e) {
- log.error("Error initializing authentication provider for method "
+ method, e);
- reject();
- }
+ AuthProvider provider = (AuthProvider) methods.get(method);
+
+ provider.reset();
+ provider.initiateConversation(this);
+ authctx = provider;
+ ctx.add(authctx);
+
}
}
Modified:
trunk/clients/Javer2/src/org/haverdev/haver/server/BasicAuthentication.java
===================================================================
--- trunk/clients/Javer2/src/org/haverdev/haver/server/BasicAuthentication.java
2005-06-10 20:43:42 UTC (rev 762)
+++ trunk/clients/Javer2/src/org/haverdev/haver/server/BasicAuthentication.java
2005-06-11 18:17:46 UTC (rev 763)
@@ -9,8 +9,7 @@
*/
package org.haverdev.haver.server;
-import org.haverdev.haver.Base64;
-import org.haverdev.haver.SHA1;
+import org.haverdev.common.*;
import java.security.*;
import java.nio.charset.Charset;
import java.nio.ByteBuffer;
@@ -24,95 +23,55 @@
static org.apache.log4j.Logger log =
org.apache.log4j.Logger.getLogger(BasicAuthentication.class);
- static java.util.Map algos;
-
- static void mapAlgo(Map algos, String havername, String spiname) {
- try {
- MessageDigest.getInstance(spiname);
- algos.put(havername, spiname);
- }
- catch (NoSuchAlgorithmException e) {
- log.error("Algorithm SPI " + spiname + " for " + havername + " not
found", e);
- }
- }
-
- static void algoInit() {
- if (algos != null) return;
-
- String algostr = System.getProperty("haver.digestMaps",
"sha512:SHA-512 sha256:SHA-256 sha1:SHA-1");
- String[] algolist = Misc.optionSplit(algostr);
- Map algotemp = new LinkedHashMap();
-
- for (int i = 0; i < algolist.length; i++) {
- String desc = algolist[i];
- int sep = desc.indexOf(':');
- String havername = desc.substring(0, sep);
- String spiname = desc.substring(sep + 1);
- mapAlgo(algotemp, havername, spiname);
- }
+ UserConnection conn;
+ UserInfo info;
+ AuthCallback callback = null;
- algos = Collections.unmodifiableMap(algotemp);
- }
+ BasicAuthenticationHasher hasher = null;
- UserConnection conn = null;
- AuthCallback callback = null;
- String nonce = null;
- String passtok = null;
String cmd;
/** Creates a new instance of BasicAuthentication */
- public BasicAuthentication(String tag) {
- algoInit();
+ public BasicAuthentication(String tag, UserConnection conn, UserInfo info)
{
cmd = "AUTH:" + tag.toUpperCase();
+ this.info = info;
+ this.conn = conn;
}
- public void initiateConversation(UserInfo info, UserConnection conn,
AuthCallback cb) {
+ public boolean isAvailable() {
+ if (!Boolean.parseBoolean(info.getProperty("authenticated")))
+ return false;
+ if (info.getProperty("auth.basic.token") == null)
+ return false;
+ return true;
+ }
+
+ public void initiateConversation(AuthCallback cb) {
this.conn = conn;
callback = cb;
- SecureRandom rng = new SecureRandom();
- byte[] nonce_buf = new byte[16];
- rng.nextBytes(nonce_buf);
- nonce = Base64.encodeBytes(nonce_buf);
- passtok = info.getProperty("auth.basic.token");
+
+ String passtok = info.getProperty("auth.basic.token");
if (passtok == null) {
cb.reject();
return;
}
+ hasher.setPasstoken(passtok);
+ Set algos = hasher.availableAlgos();
String[] initcmd = new String[2 + algos.size()];
initcmd[0] = "AUTH:BASIC";
- initcmd[1] = nonce;
+ initcmd[1] = hasher.getNonce();
- java.util.Iterator it = algos.keySet().iterator();
+ java.util.Iterator it = algos.iterator();
int i = 2;
while (it.hasNext())
initcmd[i++] = (String)it.next();
conn.sendLine(initcmd);
- conn.context = this;
+ //conn.context = this;
}
- static byte[] computeHash(MessageDigest algo, String passtok, String
nonce) {
- Charset utf8 = Charset.forName("UTF-8");
-
- ByteBuffer passtok_bb = utf8.encode(passtok);
- ByteBuffer nonce_bb = utf8.encode(nonce);
-
- byte[] passtok_b = new byte[passtok_bb.limit()];
- passtok_bb.get(passtok_b);
-
- byte[] nonce_b = new byte[nonce_bb.limit()];
- nonce_bb.get(nonce_b);
-
- byte[] combined = new byte[passtok_b.length + nonce_b.length];
- System.arraycopy(nonce_b, 0, combined, 0, nonce_b.length);
- System.arraycopy(passtok_b, 0, combined, nonce_b.length,
passtok_b.length);
-
- algo.update(combined);
- byte[] result = algo.digest();
- return result;
- }
public void handleCommand(String[] cmd) throws
org.haverdev.haver.server.exceptions.PropagatedException {
if (!cmd[0].equals(this.cmd))
@@ -120,64 +79,30 @@
String algo = cmd[1];
String hash = cmd[2];
- MessageDigest h = null;;
+ String expected;
try {
- h = (MessageDigest) MessageDigest.getInstance((String)
algos.get(algo));
- } catch (NoSuchAlgorithmException e) {
- log.error("Unexpectedly lost digest " + algo + " spi " +
algos.get(algo), e);
+ expected = hasher.digest(algo);
}
- if (h == null) {
- callback.reject();
+ catch (NoSuchAlgorithmException e) {
+ callback.reject(); // XXX
return;
}
-
- byte[] result = computeHash(h, passtok, nonce);
- byte[] userval = Base64.decode(hash);
-
- // XXX: byte[].equals() doesn't work right, so we must do this
- if (result.length != userval.length) {
+
+ if (expected.equals(hash))
+ callback.accept();
+ else
callback.reject();
- return;
- }
-
- for (int i = 0; i < result.length; i++) {
- if (result[i] != userval[i]) {
- callback.reject();
- return;
- }
- }
-
- callback.accept();
}
public String getProtocolName() {
return "basic";
}
- public static void main(String[] args) throws Throwable {
- // Simple test framework
- algoInit();
-
- if (args.length != 3) {
- System.err.println("Usage: BasicAuthentication algo passtok
nonce");
- System.err.println("Algos: ");
- java.util.Iterator i = algos.keySet().iterator();
- while (i.hasNext())
- System.err.println("* " + i.next());
- System.exit(1);
- }
- String algo = args[0];
- String passtok = args[1];
- String nonce = args[2];
-
- String spi = (String) algos.get(algo);
- MessageDigest h = MessageDigest.getInstance(spi);
- if (h == null) {
- System.err.println("Algo " + algo + " unknown");
- System.exit(1);
- }
-
- byte[] result = computeHash(h, passtok, nonce);
- System.out.println(Base64.encodeBytes(result));
+ public void reset() {
+ SecureRandom rng = new SecureRandom();
+ byte[] nonce_buf = new byte[16];
+ rng.nextBytes(nonce_buf);
+ hasher = new BasicAuthenticationHasher();
+ hasher.setNonce(Base64.encodeBytes(nonce_buf));
}
}
Modified: trunk/clients/Javer2/src/org/haverdev/haver/server/EntityLoader.java
===================================================================
--- trunk/clients/Javer2/src/org/haverdev/haver/server/EntityLoader.java
2005-06-10 20:43:42 UTC (rev 762)
+++ trunk/clients/Javer2/src/org/haverdev/haver/server/EntityLoader.java
2005-06-11 18:17:46 UTC (rev 763)
@@ -7,6 +7,7 @@
package org.haverdev.haver.server;
import org.apache.log4j.Logger;
import java.lang.reflect.*;
+import org.haverdev.common.*;
/**
*
@@ -38,7 +39,7 @@
public static final void initPlugin() {
String[] entities =
-
Misc.optionSplit(System.getProperty("org.haverdev.haver.server.EntityLoader.entities"));
+
HaverEncoding.optionSplit(System.getProperty("org.haverdev.haver.server.EntityLoader.entities"));
for (int i = 0; i < entities.length; i++) {
log.info("Initializing entity " + entities[i] + "...");
try {
Modified: trunk/clients/Javer2/src/org/haverdev/haver/server/FileUserStore.java
===================================================================
--- trunk/clients/Javer2/src/org/haverdev/haver/server/FileUserStore.java
2005-06-10 20:43:42 UTC (rev 762)
+++ trunk/clients/Javer2/src/org/haverdev/haver/server/FileUserStore.java
2005-06-11 18:17:46 UTC (rev 763)
@@ -84,6 +84,8 @@
));
who.props.store(e, "Name: " + who.getName());
e.close();
+ // Java on windows doesn't do rename-overwrite
+ try { new File(path + name).delete(); } catch (Throwable t) {}
new File(path + "_" + name).renameTo(new File(path + name));
} finally {
try { new File(path + "_" + name).delete(); } catch (Throwable t)
{}
Modified: trunk/clients/Javer2/src/org/haverdev/haver/server/InitContext.java
===================================================================
--- trunk/clients/Javer2/src/org/haverdev/haver/server/InitContext.java
2005-06-10 20:43:42 UTC (rev 762)
+++ trunk/clients/Javer2/src/org/haverdev/haver/server/InitContext.java
2005-06-11 18:17:46 UTC (rev 763)
@@ -12,7 +12,6 @@
* @author bdonlan
*/
public class InitContext extends UserCommandReflect {
- static final String[] greeting = { "HAVER", Misc.version };
public InitContext(UserConnection conn, String name) {
super(conn, name);
@@ -20,6 +19,12 @@
public void handle_HAVER(String[] args) throws PropagatedException {
log.info("Client identifies itself as " + args[1]);
+
+ for (int i = 2; i < args.length; i++)
+ conn.features.add(args[i]);
+
+ String[] greeting = { "HAVER", System.getProperty("haver.hostname",
"broken.server"), Misc.version };
+
conn.sendLine(greeting);
//conn.context = new LoginContext(conn, "login");
advance();
Modified: trunk/clients/Javer2/src/org/haverdev/haver/server/LoginContext.java
===================================================================
--- trunk/clients/Javer2/src/org/haverdev/haver/server/LoginContext.java
2005-06-10 20:43:42 UTC (rev 762)
+++ trunk/clients/Javer2/src/org/haverdev/haver/server/LoginContext.java
2005-06-11 18:17:46 UTC (rev 763)
@@ -13,11 +13,19 @@
*/
public class LoginContext extends UserCommandReflect {
+ AuthenticationProcess auth = null;
+
public LoginContext(UserConnection conn, String name) {
super(conn, name);
}
public void handle_IDENT(String[] args) throws PropagatedException {
+ if (auth != null) {
+ // XXX
+ ((MergingContext)conn.context).remove(auth);
+ auth = null;
+ }
+
synchronized (conn.pingLock) {
conn.handshakeAbort.cancel();
if (conn.writer == null) // Too late
@@ -30,6 +38,10 @@
log.info("User gave name: " + args[1]);
UserInfo info = Main.theStore.getUser(args[1]);
- new AuthenticationProcess(conn, info);
+ // XXX
+ auth = new AuthenticationProcess(conn, info);
+ conn.context = auth.getContext(); // XXX
+ auth.start();
+ //((MergingContext)conn.context).add(auth.getContext());
}
}
\ No newline at end of file
Modified: trunk/clients/Javer2/src/org/haverdev/haver/server/Main.java
===================================================================
--- trunk/clients/Javer2/src/org/haverdev/haver/server/Main.java
2005-06-10 20:43:42 UTC (rev 762)
+++ trunk/clients/Javer2/src/org/haverdev/haver/server/Main.java
2005-06-11 18:17:46 UTC (rev 763)
@@ -9,6 +9,7 @@
import java.io.*;
import java.util.*;
import java.lang.reflect.*;
+import org.haverdev.common.*;
/**
*
@@ -71,24 +72,17 @@
static final void bootstrap() throws Throwable {
+ if (System.getProperty("haver.hostname") == null) {
+ Logger.getRootLogger().error("You have not configured
haver.hostname. That is bad. Fix it.");
+ }
+
// Configure the logger
PropertyConfigurator.configure(System.getProperties());
Lobby.initLobby(System.getProperty("haver.Lobby"));
initStore(System.getProperty("haver.UserStore",
"org.haverdev.haver.server.DefaultUserStore"));
- //String portStr = props.getProperty("haver.ListenPort", "7070");
- //int port = Integer.decode(portStr).intValue();
-
- String channelstr = System.getProperty("haver.ChatChannels", "");
- String[] channels = Misc.optionSplit(channelstr);
-
- for (int i = 0; i < channels.length; i++)
- Lobby.theLobby.register(new ChatChannel(channels[i]));
- if (channels.length == 0)
- Logger.getRootLogger().warn("No chat channels configured");
-
- String[] plugins =
Misc.optionSplit(System.getProperty("haver.Plugins"));
+ String[] plugins =
HaverEncoding.optionSplit(System.getProperty("haver.Plugins"));
for (int i = 0; i < plugins.length; i++) {
try {
Logger.getRootLogger().info("Initializing plugin " +
plugins[i]);
@@ -99,7 +93,7 @@
}
Logger.getRootLogger().warn("Running accept loop init functions");
- String[] listeners =
Misc.optionSplit(System.getProperty("haver.listeners",
"org.haverdev.haver.server.AcceptLoop"));
+ String[] listeners =
HaverEncoding.optionSplit(System.getProperty("haver.listeners",
"org.haverdev.haver.server.AcceptLoop"));
for (int i = 0; i < listeners.length; i++)
initListener(listeners[i]);
Modified: trunk/clients/Javer2/src/org/haverdev/haver/server/Misc.java
===================================================================
--- trunk/clients/Javer2/src/org/haverdev/haver/server/Misc.java
2005-06-10 20:43:42 UTC (rev 762)
+++ trunk/clients/Javer2/src/org/haverdev/haver/server/Misc.java
2005-06-11 18:17:46 UTC (rev 763)
@@ -10,6 +10,7 @@
//import java.util.regex.*;
import java.util.*;
+import org.haverdev.common.HaverEncoding;
import org.haverdev.haver.server.exceptions.*;
/**
@@ -74,123 +75,11 @@
public static void checkName(String name) throws PropagatedException {
checkName(name, true);
}
-
- /**
- * Reverses Haver escaping.
- * @param val String to unescape
- * @return The unescaped string
- */
- protected static final String unescape(String val) {
- //if (val != null) return val;
- StringBuffer out = new StringBuffer();
- int pin = 0;
- int nextEsc = -1;
- while (-1 != (nextEsc = val.indexOf("\033", pin))) {
- out.append(val.substring(0, nextEsc - 1));
- switch (val.charAt(nextEsc + 1)) {
- case 'r':
- out.append('\r');
- break;
- case 'n':
- out.append('\n');
- break;
- case 'e':
- out.append('\033');
- break;
- case 't':
- out.append('\t');
- break;
- default:
- out.append(val.charAt(nextEsc + 1));
- break;
- }
- pin = nextEsc + 2;
- }
- out.append(val.substring(pin));
- return out.toString();
- }
+
+
- /**
- * Escapes a string according to the Haver protocol
- * @param val String to escape
- * @return Escaped string
- */
- protected static final String escape(String val) {
- /* GNU classpath
- return val.replaceAll("\033", "\033e")
- .replaceAll("\n", "\033n")
- .replaceAll("\r", "\033r")
- .replaceAll("\t", "\033t");
- */
- StringBuffer out = new StringBuffer();
- char[] arr = val.toCharArray();
- for (int i = 0; i < arr.length; i++) {
- switch (arr[i]) {
- case '\033':
- out.append("\033e");
- break;
- case '\n':
- out.append("\033n");
- break;
- case '\r':
- out.append("\033r");
- break;
- case '\t':
- out.append("\033t");
- break;
- default:
- out.append(arr[i]);
- }
- }
- return out.toString();
+ public static String getHostname() {
+ return System.getProperty("haver.hostname", "broken.server");
}
- /**
- * Decodes a raw line from the Haver protocol.
- * @param inLine Line to decode. May end in '\r\n' but must only be one
line.
- * @return An array containing the unescaped arguments of the line.
- */
- protected static final String[] decodeLine(String inLine) {
- int nl = inLine.indexOf("\r");
- if (nl != -1)
- inLine = inLine.substring(0, nl);
- nl = inLine.indexOf("\n");
- if (nl != -1)
- inLine = inLine.substring(0, nl);
-
- String[] args = splitString(inLine, "\t");
- for (int i = 0; i < args.length; i++) {
- args[i] = unescape(args[i]);
- }
- return args;
- }
-
- /**
- * Encodes a set of arguments for line transmission
- * @param args Unescaped arguments to encode
- * @return Escaped and joined line ready for transmission, complete with
ending \r\n
- */
- protected static final String encodeLine(String[] args) {
- StringBuffer out = new StringBuffer();
- for (int i = 0; i < args.length; i++) {
- if (i != 0)
- out.append("\t");
- out.append(escape(args[i]));
- }
- out.append("\r\n");
- return out.toString();
- }
-
- public static final String[] splitString(String str, String delims) {
- StringTokenizer t = new StringTokenizer(str, delims);
- ArrayList al = new ArrayList();
- while (t.hasMoreTokens()) {
- al.add(t.nextElement());
- }
- return (String[]) al.toArray(new String[al.size()]);
- }
-
- public static String[] optionSplit(String str) {
- return splitString(str, " ,");
- }
}
Deleted: trunk/clients/Javer2/src/org/haverdev/haver/server/ObjectQueue.java
===================================================================
--- trunk/clients/Javer2/src/org/haverdev/haver/server/ObjectQueue.java
2005-06-10 20:43:42 UTC (rev 762)
+++ trunk/clients/Javer2/src/org/haverdev/haver/server/ObjectQueue.java
2005-06-11 18:17:46 UTC (rev 763)
@@ -1,59 +0,0 @@
-/*
- * ObjectQueue.java
- *
- * Created on May 27, 2005, 3:03 PM
- */
-
-package org.haverdev.haver.server;
-import java.util.*;
-
-/**
- *
- * @author bdonlan
- */
-public class ObjectQueue {
- LinkedList theQueue = new LinkedList();
-
- /** Creates a new instance of ObjectQueue */
- public ObjectQueue() {
- }
-
- public Object block(long millis) throws InterruptedException {
- synchronized (theQueue) {
- if (theQueue.isEmpty()) {
- theQueue.wait(millis);
- }
- if (theQueue.isEmpty()) {
- System.err.println("ObjectQueue: Awakened with nothing to show
for it...");
- return null;
- }
- Object o = theQueue.removeFirst();
- return o;
- }
- }
-
- public Object block() throws InterruptedException {
- return block(0);
- }
-
- public boolean hasData() {
- synchronized (theQueue) {
- return !theQueue.isEmpty();
- }
- }
-
- public Object poll() {
- synchronized (theQueue) {
- if (theQueue.isEmpty())
- return null;
- return theQueue.removeFirst();
- }
- }
-
- public void post(Object o) {
- synchronized (theQueue) {
- theQueue.addLast(o);
- theQueue.notify();
- }
- }
-}
Modified: trunk/clients/Javer2/src/org/haverdev/haver/server/StatsBot.java
===================================================================
--- trunk/clients/Javer2/src/org/haverdev/haver/server/StatsBot.java
2005-06-10 20:43:42 UTC (rev 762)
+++ trunk/clients/Javer2/src/org/haverdev/haver/server/StatsBot.java
2005-06-11 18:17:46 UTC (rev 763)
@@ -10,7 +10,7 @@
*
* @author bdonlan
*/
-public class StatsBot extends EntityBase implements User {
+public class StatsBot extends UserBase implements User {
/** Creates a new instance of StatsBot */
public StatsBot(String name) {
Modified:
trunk/clients/Javer2/src/org/haverdev/haver/server/UserCommandWrapper.java
===================================================================
--- trunk/clients/Javer2/src/org/haverdev/haver/server/UserCommandWrapper.java
2005-06-10 20:43:42 UTC (rev 762)
+++ trunk/clients/Javer2/src/org/haverdev/haver/server/UserCommandWrapper.java
2005-06-11 18:17:46 UTC (rev 763)
@@ -27,6 +27,7 @@
}
catch (PropagatedException e) {
e.setCmd(cmd[0]);
+ throw e;
}
catch (Throwable t) {
throw new InternalCommandException(cmd[0], t);
Modified: trunk/clients/Javer2/src/org/haverdev/haver/server/UserConnection.java
===================================================================
--- trunk/clients/Javer2/src/org/haverdev/haver/server/UserConnection.java
2005-06-10 20:43:42 UTC (rev 762)
+++ trunk/clients/Javer2/src/org/haverdev/haver/server/UserConnection.java
2005-06-11 18:17:46 UTC (rev 763)
@@ -13,7 +13,8 @@
import java.lang.reflect.*;
import org.haverdev.haver.server.exceptions.*;
import org.apache.log4j.Logger;
-
+import org.haverdev.common.ObjectQueue;
+import org.haverdev.common.HaverEncoding;
/**
*
* @author bdonlan
@@ -41,6 +42,8 @@
ObjectQueue outgoing = new ObjectQueue();
+ Set features = new HashSet();
+
final class Message {
public String msg;
Message(String m) {
@@ -235,14 +238,14 @@
}
public void sendLine(String[] args) {
- String line = Misc.encodeLine(args);
+ String line = HaverEncoding.encodeLine(args);
outgoing.post(line);
line = line.substring(0, line.length() - 2); // kill \r\n
log.debug("S: " + line);
}
public synchronized void processLine(String line) throws
PropagatedException {
- String[] cmd = Misc.decodeLine(line);
+ String[] cmd = HaverEncoding.decodeLine(line);
context.processCommand(cmd);
}
Modified:
trunk/clients/Javer2/src/org/haverdev/haver/server/UserContextFactory.java
===================================================================
--- trunk/clients/Javer2/src/org/haverdev/haver/server/UserContextFactory.java
2005-06-10 20:43:42 UTC (rev 762)
+++ trunk/clients/Javer2/src/org/haverdev/haver/server/UserContextFactory.java
2005-06-11 18:17:46 UTC (rev 763)
@@ -7,6 +7,7 @@
package org.haverdev.haver.server;
import java.lang.reflect.*;
import org.apache.log4j.Logger;
+import org.haverdev.common.*;
/**
*
@@ -20,7 +21,7 @@
String subcontexts = System.getProperty("haver.state." +
stateName);
if (subcontexts == null)
throw new IllegalArgumentException("Subhandler " + stateName +
" not configured");
- String[] ctx_arr = Misc.optionSplit(subcontexts);
+ String[] ctx_arr = HaverEncoding.optionSplit(subcontexts);
for (int i = 0; i < ctx_arr.length; i++) {
ctx.add(constructSubhandler(conn, ctx_arr[i]));
}
Modified: trunk/clients/Javer2/src/org/haverdev/haver/server/Xiao.java
===================================================================
--- trunk/clients/Javer2/src/org/haverdev/haver/server/Xiao.java
2005-06-10 20:43:42 UTC (rev 762)
+++ trunk/clients/Javer2/src/org/haverdev/haver/server/Xiao.java
2005-06-11 18:17:46 UTC (rev 763)
@@ -11,10 +11,9 @@
package org.haverdev.haver.server;
import java.lang.reflect.*; // Mirror, mirror...
import org.apache.log4j.Logger;
-import org.haverdev.haver.SHA1;
-import org.haverdev.haver.Base64;
+import org.haverdev.common.*;
-import java.security.SecureRandom;
+import java.security.*;
import java.nio.*;
import java.nio.charset.*;
@@ -39,7 +38,7 @@
if (args.length != 2) return;
if (!args[0].equals("say")) return;
- String[] cmd = Misc.splitString(args[1], " ");
+ String[] cmd = HaverEncoding.splitString(args[1], " ");
/* XXX
try {
Class[] proto = { ufrom.getClass(), cmd.getClass() };
@@ -73,28 +72,13 @@
UserInfo info = from.getInfo();
String password = cmd[1];
- SecureRandom rng = new SecureRandom();
- byte[] salt = new byte[4];
- rng.nextBytes(salt);
+ BasicAuthenticationHasher h = new BasicAuthenticationHasher();
+ h.setPassword(password);
+ h.setUsername(from.getName());
+ h.setHostname(Misc.getHostname());
- salt = new byte[0]; // until standardized
+ String tok = h.getPasstoken();
- Charset utf8 = Charset.forName("UTF-8");
- ByteBuffer pass_bb = utf8.encode(password);
-
- ByteBuffer fullbuffer = ByteBuffer.allocate(pass_bb.limit() +
salt.length);
- fullbuffer.rewind();
- fullbuffer.put(salt);
- fullbuffer.put(pass_bb);
-
- log.debug(fullbuffer.array());
-
- SHA1 hasher = new SHA1();
- byte[] hashin = fullbuffer.array();
- hasher.engineUpdate(hashin, 0, hashin.length);
- byte[] hashout = hasher.engineDigest();
- String tok = Base64.encodeBytes(hashout);
-
info.setProperty("persistant", "true");
info.setProperty("auth.basic.token", tok);
info.setProperty("authenticated", "true");
Added:
trunk/clients/Javer2/src/org/haverdev/haver/server/exceptions/AuthNotSupportedException.java
===================================================================
---
trunk/clients/Javer2/src/org/haverdev/haver/server/exceptions/AuthNotSupportedException.java
2005-06-10 20:43:42 UTC (rev 762)
+++
trunk/clients/Javer2/src/org/haverdev/haver/server/exceptions/AuthNotSupportedException.java
2005-06-11 18:17:46 UTC (rev 763)
@@ -0,0 +1,24 @@
+/*
+ * AuthNotSupportedException.java
+ *
+ * Created on June 10, 2005, 5:46 PM
+ *
+ * To change this template, choose Tools | Options and locate the template
under
+ * the Source Creation and Management node. Right-click the template and choose
+ * Open. You can then make changes to the template in the Source Editor.
+ */
+
+package org.haverdev.haver.server.exceptions;
+
+/**
+ *
+ * @author bdonlan
+ */
+public class AuthNotSupportedException extends SimplePropagatedException {
+
+ /** Creates a new instance of AuthNotSupportedException */
+ public AuthNotSupportedException(String name) {
+ super("auth.needed", name);
+ }
+
+}
Property changes on:
trunk/clients/Javer2/src/org/haverdev/haver/server/exceptions/AuthNotSupportedException.java
___________________________________________________________________
Name: svn:eol-style
+ native
Modified: trunk/clients/Javer2/src/org/haverdev/javer2/CMod.java
===================================================================
--- trunk/clients/Javer2/src/org/haverdev/javer2/CMod.java 2005-06-10
20:43:42 UTC (rev 762)
+++ trunk/clients/Javer2/src/org/haverdev/javer2/CMod.java 2005-06-11
18:17:46 UTC (rev 763)
@@ -9,6 +9,8 @@
import java.util.*;
import java.text.*;
import java.io.*;
+import org.haverdev.client.Client;
+import org.haverdev.client.Callback;
/**
*
Modified: trunk/clients/Javer2/src/org/haverdev/javer2/ChannelPane.java
===================================================================
--- trunk/clients/Javer2/src/org/haverdev/javer2/ChannelPane.java
2005-06-10 20:43:42 UTC (rev 762)
+++ trunk/clients/Javer2/src/org/haverdev/javer2/ChannelPane.java
2005-06-11 18:17:46 UTC (rev 763)
@@ -8,6 +8,8 @@
import org.haverdev.haver.*;
import java.util.*;
import javax.swing.*;
+import org.haverdev.client.Client;
+import org.haverdev.client.Callback;
/**
*
Modified: trunk/clients/Javer2/src/org/haverdev/javer2/JaverForm.form
===================================================================
--- trunk/clients/Javer2/src/org/haverdev/javer2/JaverForm.form 2005-06-10
20:43:42 UTC (rev 762)
+++ trunk/clients/Javer2/src/org/haverdev/javer2/JaverForm.form 2005-06-11
18:17:46 UTC (rev 763)
@@ -1,6 +1,12 @@
<?xml version="1.0" encoding="UTF-8" ?>
<Form version="1.0" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
+ <AuxValues>
+ <AuxValue name="FormSettings_generateMnemonicsCode"
type="java.lang.Boolean" value="false"/>
+ <AuxValue name="FormSettings_listenerGenerationStyle"
type="java.lang.Integer" value="0"/>
+ <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean"
value="false"/>
+ <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer"
value="2"/>
+ </AuxValues>
<Layout
class="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout"/>
<SubComponents>
Modified: trunk/clients/Javer2/src/org/haverdev/javer2/JaverForm.java
===================================================================
--- trunk/clients/Javer2/src/org/haverdev/javer2/JaverForm.java 2005-06-10
20:43:42 UTC (rev 762)
+++ trunk/clients/Javer2/src/org/haverdev/javer2/JaverForm.java 2005-06-11
18:17:46 UTC (rev 763)
@@ -12,6 +12,8 @@
import java.io.*;
import javax.net.*;
import javax.net.ssl.*;
+import org.haverdev.client.Client;
+import org.haverdev.client.Callback;
/**
@@ -57,6 +59,7 @@
cli = new Client();
watch = new Watcher();
cli.addNotify(watch);
+ cli.addAuthProvider(new
org.haverdev.client.SwingBasicAuthentication());
try {
cli.syncConnect(factory.createSocket(host, port), nick);
serverpane.putLine("Connected!");
@@ -176,7 +179,8 @@
* WARNING: Do NOT modify this code. The content of this method is
* always regenerated by the Form Editor.
*/
- private void initComponents() {//GEN-BEGIN:initComponents
+ // <editor-fold defaultstate="collapsed" desc=" Generated Code
">//GEN-BEGIN:initComponents
+ private void initComponents() {
jTabbedPane1 = new javax.swing.JTabbedPane();
jPanel1 = new javax.swing.JPanel();
inputBox = new javax.swing.JTextField();
@@ -197,7 +201,6 @@
jPanel1.add(inputBox, java.awt.BorderLayout.CENTER);
jButton1.setText("Send");
- jButton1.setActionCommand("Send");
jButton1.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
sendLine(evt);
@@ -208,7 +211,8 @@
add(jPanel1, java.awt.BorderLayout.SOUTH);
- }//GEN-END:initComponents
+ }
+ // </editor-fold>//GEN-END:initComponents
private void inputBoxKeyTyped(java.awt.event.KeyEvent evt)
{//GEN-FIRST:event_inputBoxKeyTyped
if (evt.getKeyChar() == '\n')
Modified: trunk/clients/Javer2/src/org/haverdev/javer2/Main.java
===================================================================
--- trunk/clients/Javer2/src/org/haverdev/javer2/Main.java 2005-06-10
20:43:42 UTC (rev 762)
+++ trunk/clients/Javer2/src/org/haverdev/javer2/Main.java 2005-06-11
18:17:46 UTC (rev 763)
@@ -6,12 +6,13 @@
package org.haverdev.javer2;
import org.haverdev.haver.*;
+import org.haverdev.client.Client;
/**
*
* @author bdonlan
*/
-public class Main extends org.haverdev.haver.Callback {
+public class Main extends org.haverdev.client.Callback {
Client c;
/** Creates a new instance of Main */
Modified: trunk/clients/Javer2/src/org/haverdev/javer2/QueryPane.java
===================================================================
--- trunk/clients/Javer2/src/org/haverdev/javer2/QueryPane.java 2005-06-10
20:43:42 UTC (rev 762)
+++ trunk/clients/Javer2/src/org/haverdev/javer2/QueryPane.java 2005-06-11
18:17:46 UTC (rev 763)
@@ -6,6 +6,8 @@
package org.haverdev.javer2;
import org.haverdev.haver.*;
+import org.haverdev.client.Client;
+import org.haverdev.client.Callback;
/**
*